cpu/intel/smm: Use CONFIG_SMM_TSEG_SIZE

An epic battle to fix Nehalem finally ended when we found an odd mask
set in SMRR. This was caused by a wrong calculation of TSEG size. It
was assumed that TSEG spans the whole space between TSEG base
and GTT. This is wrong as TSEG base might have been aligned down.

TEST: On X201, copied 1GiB from usb key to sd-card and verified.

Change-Id: Id8c8a656446f092629fe2517f043e3c6d0f1b6b7
Found-by: Alexander Couzens, Nico Huber
Signed-off-by: Nico Huber <nico.huber@secunet.com>
Reviewed-on: https://review.coreboot.org/16939
Tested-by: build bot (Jenkins)
Reviewed-by: Paul Menzel <paulepanter@users.sourceforge.net>
Reviewed-by: Alexander Couzens <lynxis@fe80.eu>
Reviewed-by: Kyösti Mälkki <kyosti.malkki@gmail.com>
This commit is contained in:
Nico Huber 2016-10-08 18:42:46 +02:00 committed by Nico Huber
parent c9848a82e2
commit 6f8b7df8ab
5 changed files with 17 additions and 37 deletions

View File

@ -15,6 +15,6 @@
void southbridge_smm_init(void); void southbridge_smm_init(void);
void southbridge_trigger_smi(void); void southbridge_trigger_smi(void);
void southbridge_clear_smi_status(void); void southbridge_clear_smi_status(void);
void northbridge_get_tseg_base_and_size(u32 *tsegmb, u32 *tseg_size); u32 northbridge_get_tseg_base(void);
int cpu_get_apic_id_map(int *apic_id_map); int cpu_get_apic_id_map(int *apic_id_map);
void northbridge_write_smram(u8 smram); void northbridge_write_smram(u8 smram);

View File

@ -114,22 +114,17 @@ static void asmlinkage cpu_smm_do_relocation(void *arg)
static void fill_in_relocation_params(struct smm_relocation_params *params) static void fill_in_relocation_params(struct smm_relocation_params *params)
{ {
u32 tseg_size;
u32 tsegmb;
int phys_bits;
/* All range registers are aligned to 4KiB */ /* All range registers are aligned to 4KiB */
const u32 rmask = ~((1 << 12) - 1); const u32 rmask = ~((1 << 12) - 1);
/* Some of the range registers are dependent on the number of physical const u32 tsegmb = northbridge_get_tseg_base();
* address bits supported. */ /* TSEG base is usually aligned down (to 8MiB). So we can't
phys_bits = cpuid_eax(0x80000008) & 0xff; derive the TSEG size from the distance to GTT but use the
configuration value instead. */
/* The range bounded by the TSEGMB and BGSM registers encompasses the const u32 tseg_size = CONFIG_SMM_TSEG_SIZE;
* SMRAM range as well as the IED range. However, the SMRAM available
* to the handler is 4MiB since the IEDRAM lives TSEGMB + 4MiB.
*/
northbridge_get_tseg_base_and_size(&tsegmb, &tseg_size);
/* The SMRAM available to the handler is 4MiB
since the IEDRAM lives at TSEGMB + 4MiB. */
params->smram_base = tsegmb; params->smram_base = tsegmb;
params->smram_size = 4 << 20; params->smram_size = 4 << 20;
params->ied_base = tsegmb + params->smram_size; params->ied_base = tsegmb + params->smram_size;

View File

@ -325,16 +325,11 @@ static u32 northbridge_get_base_reg(device_t dev, int reg)
return value; return value;
} }
void u32 northbridge_get_tseg_base(void)
northbridge_get_tseg_base_and_size(u32 *tsegmb, u32 *tseg_size)
{ {
device_t dev; const device_t dev = dev_find_slot(0, PCI_DEVFN(0, 0));
u32 bgsm;
dev = dev_find_slot(0, PCI_DEVFN(0, 0));
*tsegmb = northbridge_get_base_reg(dev, TSEG); return northbridge_get_base_reg(dev, TSEG);
bgsm = northbridge_get_base_reg(dev, BGSM);
*tseg_size = bgsm - *tsegmb;
} }
void northbridge_write_smram(u8 smram) void northbridge_write_smram(u8 smram)

View File

@ -162,16 +162,11 @@ static void mc_read_resources(device_t dev)
add_fixed_resources(dev, 10); add_fixed_resources(dev, 10);
} }
void u32 northbridge_get_tseg_base(void)
northbridge_get_tseg_base_and_size(u32 *tsegmb, u32 *tseg_size)
{ {
device_t dev; const device_t dev = dev_find_slot(0, PCI_DEVFN(0, 0));
u32 bgsm;
dev = dev_find_slot(0, PCI_DEVFN(0, 0));
*tsegmb = pci_read_config32(dev, TSEG) & ~1; return pci_read_config32(dev, TSEG) & ~1;
bgsm = pci_read_config32(dev, D0F0_GTT_BASE);
*tseg_size = bgsm - *tsegmb;
} }
static void mc_set_resources(device_t dev) static void mc_set_resources(device_t dev)

View File

@ -500,16 +500,11 @@ static u32 northbridge_get_base_reg(device_t dev, int reg)
return value; return value;
} }
void u32 northbridge_get_tseg_base(void)
northbridge_get_tseg_base_and_size(u32 *tsegmb, u32 *tseg_size)
{ {
device_t dev; const device_t dev = dev_find_slot(0, PCI_DEVFN(0, 0));
u32 bgsm;
dev = dev_find_slot(0, PCI_DEVFN(0, 0));
*tsegmb = northbridge_get_base_reg(dev, TSEG); return northbridge_get_base_reg(dev, TSEG);
bgsm = northbridge_get_base_reg(dev, BGSM);
*tseg_size = bgsm - *tsegmb;
} }
void northbridge_write_smram(u8 smram) void northbridge_write_smram(u8 smram)