summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKyösti Mälkki <kyosti.malkki@gmail.com>2016-07-22 22:48:35 +0300
committerKyösti Mälkki <kyosti.malkki@gmail.com>2016-11-18 21:00:30 +0100
commitbfca67078cfddc18994fa6bbe9094a2ecca275a3 (patch)
treed251389ecf692dab90b16af9dfe643fd1b71386e
parentde01136484c58d13457ccf1e42fdb2310f3cbe65 (diff)
downloadcoreboot-bfca67078cfddc18994fa6bbe9094a2ecca275a3.tar.xz
intel/sandybridge post-car: Redo MTRR settings and stack selection
Adapt implementation from haswell to prepare for removal of HIGH_MEMORY_SAVE and moving on to RELOCATABLE_RAMSTAGE. With the change, CBMEM and SMM regions are set to WRBACK with MTRRs and romstage ram stack is moved to CBMEM. Also fixes regression of slower S3 resume path after commit 9b99152 intel/sandybridge: Use common ACPI S3 recovery Skipping low memory backup and using stage cache for ramstage decreases time spent on S3 resume path by 50 ms on samsung/lumpy. Change-Id: I2afee3662e73e8e629188258b2f4119e02d60305 Signed-off-by: Kyösti Mälkki <kyosti.malkki@gmail.com> Reviewed-on: https://review.coreboot.org/15790 Reviewed-by: Aaron Durbin <adurbin@chromium.org> Tested-by: build bot (Jenkins)
-rw-r--r--src/cpu/intel/model_206ax/cache_as_ram.inc56
-rw-r--r--src/northbridge/intel/sandybridge/Kconfig2
-rw-r--r--src/northbridge/intel/sandybridge/early_init.c1
-rw-r--r--src/northbridge/intel/sandybridge/ram_calc.c89
4 files changed, 113 insertions, 35 deletions
diff --git a/src/cpu/intel/model_206ax/cache_as_ram.inc b/src/cpu/intel/model_206ax/cache_as_ram.inc
index d51fd01c05..f0d49390ba 100644
--- a/src/cpu/intel/model_206ax/cache_as_ram.inc
+++ b/src/cpu/intel/model_206ax/cache_as_ram.inc
@@ -174,10 +174,9 @@ before_romstage:
post_code(0x29)
/* Call romstage.c main function. */
call romstage_main
-
/* Save return value from romstage_main. It contains the stack to use
- * after cache-as-ram is torn down.
- */
+ * after cache-as-ram is torn down. It also contains the information
+ * for setting up MTRRs. */
movl %eax, %esp
post_code(0x30)
@@ -210,14 +209,6 @@ before_romstage:
andl $~1, %eax
wrmsr
- /* Clear MTRR that was used to cache MRC */
- xorl %eax, %eax
- xorl %edx, %edx
- movl $MTRR_PHYS_BASE(2), %ecx
- wrmsr
- movl $MTRR_PHYS_MASK(2), %ecx
- wrmsr
-
post_code(0x33)
/* Enable cache. */
@@ -234,32 +225,31 @@ before_romstage:
post_code(0x38)
- /* Enable Write Back and Speculative Reads for the first MB
- * and ramstage.
- */
+ /* Get number of MTRRs. */
+ popl %ebx
movl $MTRR_PHYS_BASE(0), %ecx
- movl $(0x00000000 | MTRR_TYPE_WRBACK), %eax
- xorl %edx, %edx
- wrmsr
- movl $MTRR_PHYS_MASK(0), %ecx
- movl $(~(CACHE_TMP_RAMTOP - 1) | MTRR_PHYS_MASK_VALID), %eax
- movl $CPU_PHYSMASK_HI, %edx // 36bit address space
+1:
+ testl %ebx, %ebx
+ jz 1f
+
+ /* Low 32 bits of MTRR base. */
+ popl %eax
+ /* Upper 32 bits of MTRR base. */
+ popl %edx
+ /* Write MTRR base. */
wrmsr
-
-#if CACHE_ROM_SIZE
- /* Enable Caching and speculative Reads for the
- * complete ROM now that we actually have RAM.
- */
- movl $MTRR_PHYS_BASE(1), %ecx
- movl $(CACHE_ROM_BASE | MTRR_TYPE_WRPROT), %eax
- xorl %edx, %edx
- wrmsr
- movl $MTRR_PHYS_MASK(1), %ecx
- movl $(~(CACHE_ROM_SIZE - 1) | MTRR_PHYS_MASK_VALID), %eax
- movl $CPU_PHYSMASK_HI, %edx
+ inc %ecx
+ /* Low 32 bits of MTRR mask. */
+ popl %eax
+ /* Upper 32 bits of MTRR mask. */
+ popl %edx
+ /* Write MTRR mask. */
wrmsr
-#endif
+ inc %ecx
+ dec %ebx
+ jmp 1b
+1:
post_code(0x39)
/* And enable cache again after setting MTRRs. */
diff --git a/src/northbridge/intel/sandybridge/Kconfig b/src/northbridge/intel/sandybridge/Kconfig
index 2fb455159e..d7af9f2329 100644
--- a/src/northbridge/intel/sandybridge/Kconfig
+++ b/src/northbridge/intel/sandybridge/Kconfig
@@ -22,6 +22,7 @@ config NORTHBRIDGE_INTEL_SANDYBRIDGE
select CPU_INTEL_MODEL_206AX
select HAVE_DEBUG_RAM_SETUP
select INTEL_GMA_ACPI
+ select RELOCATABLE_RAMSTAGE
config NORTHBRIDGE_INTEL_IVYBRIDGE
bool
@@ -31,6 +32,7 @@ config NORTHBRIDGE_INTEL_IVYBRIDGE
select CPU_INTEL_MODEL_306AX
select HAVE_DEBUG_RAM_SETUP
select INTEL_GMA_ACPI
+ select RELOCATABLE_RAMSTAGE
if NORTHBRIDGE_INTEL_IVYBRIDGE || NORTHBRIDGE_INTEL_SANDYBRIDGE
diff --git a/src/northbridge/intel/sandybridge/early_init.c b/src/northbridge/intel/sandybridge/early_init.c
index a013ec3707..86d1c002a5 100644
--- a/src/northbridge/intel/sandybridge/early_init.c
+++ b/src/northbridge/intel/sandybridge/early_init.c
@@ -234,7 +234,6 @@ void northbridge_romstage_finalize(int s3resume)
*/
if (s3resume) {
- acpi_prepare_for_resume();
/* Magic for S3 resume */
pci_write_config32(PCI_DEV(0, 0x00, 0), SKPAD, 0xcafed00d);
diff --git a/src/northbridge/intel/sandybridge/ram_calc.c b/src/northbridge/intel/sandybridge/ram_calc.c
index 125f808fd1..026531a250 100644
--- a/src/northbridge/intel/sandybridge/ram_calc.c
+++ b/src/northbridge/intel/sandybridge/ram_calc.c
@@ -2,6 +2,7 @@
* This file is part of the coreboot project.
*
* Copyright (C) 2011 Google Inc.
+ * Copyright (C) 2012 ChromeOS Authors
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -15,11 +16,21 @@
#define __SIMPLE_DEVICE__
+#include <arch/cpu.h>
#include <arch/io.h>
#include <cbmem.h>
#include <cpu/intel/romstage.h>
+#include <cpu/x86/mtrr.h>
+#include <program_loading.h>
#include "sandybridge.h"
+#if (CONFIG_SMM_TSEG_SIZE < 0x800000)
+# error "CONFIG_SMM_TSEG_SIZE must at least be 8MiB"
+#endif
+#if ((CONFIG_SMM_TSEG_SIZE & (CONFIG_SMM_TSEG_SIZE - 1)) != 0)
+# error "CONFIG_SMM_TSEG_SIZE is not a power of 2"
+#endif
+
static uintptr_t smm_region_start(void)
{
/* Base of TSEG is top of usable DRAM */
@@ -32,7 +43,83 @@ void *cbmem_top(void)
return (void *) smm_region_start();
}
+static inline u32 *stack_push(u32 *stack, u32 value)
+{
+ stack = &stack[-1];
+ *stack = value;
+ return stack;
+}
+
+/* setup_stack_and_mtrrs() determines the stack to use after
+ * cache-as-ram is torn down as well as the MTRR settings to use. */
void *setup_stack_and_mtrrs(void)
{
- return (void*)CONFIG_RAMTOP;
+ int num_mtrrs;
+ u32 *slot;
+ u32 mtrr_mask_upper;
+ u32 top_of_ram;
+
+ /* Top of stack needs to be aligned to a 4-byte boundary. */
+ slot = (void *)romstage_ram_stack_top();
+ num_mtrrs = 0;
+
+ /* The upper bits of the MTRR mask need to set according to the number
+ * of physical address bits. */
+ mtrr_mask_upper = (1 << (cpu_phys_address_size() - 32)) - 1;
+
+ /* The order for each MTRR is value then base with upper 32-bits of
+ * each value coming before the lower 32-bits. The reasoning for
+ * this ordering is to create a stack layout like the following:
+ * +0: Number of MTRRs
+ * +4: MTRR base 0 31:0
+ * +8: MTRR base 0 63:32
+ * +12: MTRR mask 0 31:0
+ * +16: MTRR mask 0 63:32
+ * +20: MTRR base 1 31:0
+ * +24: MTRR base 1 63:32
+ * +28: MTRR mask 1 31:0
+ * +32: MTRR mask 1 63:32
+ */
+
+ /* Cache the ROM as WP just below 4GiB. */
+ slot = stack_push(slot, mtrr_mask_upper); /* upper mask */
+ slot = stack_push(slot, ~(CACHE_ROM_SIZE - 1) | MTRR_PHYS_MASK_VALID);
+ slot = stack_push(slot, 0); /* upper base */
+ slot = stack_push(slot, ~(CACHE_ROM_SIZE - 1) | MTRR_TYPE_WRPROT);
+ num_mtrrs++;
+
+ /* Cache RAM as WB from 0 -> CACHE_TMP_RAMTOP. */
+ slot = stack_push(slot, mtrr_mask_upper); /* upper mask */
+ slot = stack_push(slot, ~(CACHE_TMP_RAMTOP - 1) | MTRR_PHYS_MASK_VALID);
+ slot = stack_push(slot, 0); /* upper base */
+ slot = stack_push(slot, 0 | MTRR_TYPE_WRBACK);
+ num_mtrrs++;
+
+ top_of_ram = (uint32_t)cbmem_top();
+ /* Cache 8MiB below the top of ram. On sandybridge systems the top of
+ * ram under 4GiB is the start of the TSEG region. It is required to
+ * be 8MiB aligned. Set this area as cacheable so it can be used later
+ * for ramstage before setting up the entire RAM as cacheable. */
+ slot = stack_push(slot, mtrr_mask_upper); /* upper mask */
+ slot = stack_push(slot, ~((8 << 20) - 1) | MTRR_PHYS_MASK_VALID);
+ slot = stack_push(slot, 0); /* upper base */
+ slot = stack_push(slot, (top_of_ram - (8 << 20)) | MTRR_TYPE_WRBACK);
+ num_mtrrs++;
+
+ /* Cache 8MiB at the top of ram. Top of ram on sandybridge systems
+ * is where the TSEG region resides. However, it is not restricted
+ * to SMM mode until SMM has been relocated. By setting the region
+ * to cacheable it provides faster access when relocating the SMM
+ * handler as well as using the TSEG region for other purposes. */
+ slot = stack_push(slot, mtrr_mask_upper); /* upper mask */
+ slot = stack_push(slot, ~((8 << 20) - 1) | MTRR_PHYS_MASK_VALID);
+ slot = stack_push(slot, 0); /* upper base */
+ slot = stack_push(slot, top_of_ram | MTRR_TYPE_WRBACK);
+ num_mtrrs++;
+
+ /* Save the number of MTRRs to setup. Return the stack location
+ * pointing to the number of MTRRs. */
+ slot = stack_push(slot, num_mtrrs);
+
+ return slot;
}