cpu/x86: Support CPUs without rdmsr/wrmsr instructions

Quark does not support the rdmsr and wrmsr instructions.  In this case
use a SOC specific routine to support the setting of the MTRRs.  Migrate
the code from FSP 1.1 to be x86 CPU common.

Since all rdmsr/wrmsr accesses are being converted, fix the build
failure for quark in lib/reg_script.c.  Move the soc_msr_x routines and
their depencies from romstage/mtrr.c to reg_access.c.

TEST=Build and run on Galileo Gen2

Change-Id: Ibc68e696d8066fbe2322f446d8c983d3f86052ea
Signed-off-by: Lee Leahy <leroy.p.leahy@intel.com>
Reviewed-on: https://review.coreboot.org/15839
Tested-by: build bot (Jenkins)
Reviewed-by: Aaron Durbin <adurbin@chromium.org>
This commit is contained in:
Lee Leahy 2016-07-24 08:03:37 -07:00
parent 7c2e5396a3
commit ae738acdc5
13 changed files with 148 additions and 128 deletions

View File

@ -153,3 +153,10 @@ config BOOT_MEDIA_SPI_BUS
depends on SPI_FLASH
help
Most x86 systems which boot from SPI flash boot using bus 0.
config SOC_SETS_MSRS
bool
default n
help
The SoC requires different access methods for reading and writing
the MSRs. Use SoC specific routines to handle the MSR access.

View File

@ -87,7 +87,7 @@
* +0: Number of variable MTRRs to clear
*/
#if IS_ENABLED(CONFIG_SOC_SETS_MTRRS)
#if IS_ENABLED(CONFIG_SOC_SETS_MSRS)
push %esp
call soc_set_mtrrs
@ -136,7 +136,7 @@
dec %ebx
jmp 2b
2:
#endif /* CONFIG_SOC_SETS_MTRRS */
#endif /* CONFIG_SOC_SETS_MSRS */
post_code(0x39)
@ -147,7 +147,7 @@
post_code(0x3a)
#if IS_ENABLED(CONFIG_SOC_SETS_MTRRS)
#if IS_ENABLED(CONFIG_SOC_SETS_MSRS)
call soc_enable_mtrrs
#else
/* Enable MTRR. */
@ -155,7 +155,7 @@
rdmsr
orl $MTRR_DEF_TYPE_EN, %eax
wrmsr
#endif /* CONFIG_SOC_SETS_MTRRS */
#endif /* CONFIG_SOC_SETS_MSRS */
post_code(0x3b)

View File

@ -88,11 +88,4 @@ void soc_memory_init_params(struct romstage_params *params,
MEMORY_INIT_UPD *upd);
void soc_pre_ram_init(struct romstage_params *params);
/*
* Set the MTRRs using the data on the stack from setup_stack_and_mtrrs.
* Return a new top_of_stack value which removes the setup_stack_and_mtrrs data.
*/
asmlinkage void *soc_set_mtrrs(void *top_of_stack);
asmlinkage void soc_enable_mtrrs(void);
#endif /* _COMMON_ROMSTAGE_H_ */

View File

@ -29,6 +29,23 @@ typedef struct msrinit_struct
msr_t msr;
} msrinit_t;
#if IS_ENABLED(CONFIG_SOC_SETS_MSRS)
msr_t soc_msr_read(unsigned index);
void soc_msr_write(unsigned index, msr_t msr);
/* Handle MSR references in the other source code */
static inline __attribute__((always_inline)) msr_t rdmsr(unsigned index)
{
return soc_msr_read(index);
}
static inline __attribute__((always_inline)) void wrmsr(unsigned index,
msr_t msr)
{
soc_msr_write(index, msr);
}
#else /* CONFIG_SOC_SETS_MSRS */
/* The following functions require the always_inline due to AMD
* function STOP_CAR_AND_CPU that disables cache as
* ram, the cache as ram stack can no longer be used. Called
@ -50,7 +67,8 @@ static inline __attribute__((always_inline)) msr_t rdmsr(unsigned index)
return result;
}
static inline __attribute__((always_inline)) void wrmsr(unsigned index, msr_t msr)
static inline __attribute__((always_inline)) void wrmsr(unsigned index,
msr_t msr)
{
__asm__ __volatile__ (
"wrmsr"
@ -59,6 +77,7 @@ static inline __attribute__((always_inline)) void wrmsr(unsigned index, msr_t ms
);
}
#endif /* CONFIG_SOC_SETS_MSRS */
#endif /* __ROMCC__ */
#endif /* CPU_X86_MSR_H */

View File

@ -124,4 +124,17 @@ int get_free_var_mtrr(void);
#define CACHE_ROM_BASE (((1<<20) - (CACHE_ROM_SIZE>>12))<<12)
#if (IS_ENABLED(CONFIG_SOC_SETS_MSRS) && !defined(__ASSEMBLER__) \
&& !defined(__ROMCC__))
#include <cpu/x86/msr.h>
#include <arch/cpu.h>
/*
* Set the MTRRs using the data on the stack from setup_stack_and_mtrrs.
* Return a new top_of_stack value which removes the setup_stack_and_mtrrs data.
*/
asmlinkage void *soc_set_mtrrs(void *top_of_stack);
asmlinkage void soc_enable_mtrrs(void);
#endif /* CONFIG_SOC_SETS_MSRS ... */
#endif /* CPU_X86_MTRR_H */

View File

@ -56,13 +56,6 @@ config SOC_INTEL_COMMON_LPSS_I2C_CLOCK_MHZ
No default is set here as this is an SOC-specific value and must
be provided by the SOC when it selects this driver.
config SOC_SETS_MTRRS
bool
default n
help
The SoC needs uses different access methods for reading and writing
the MTRRs. Use SoC specific routines to handle the MTRR access.
config MMA
bool "enable MMA (Memory Margin Analysis) support"
default n

View File

@ -26,7 +26,7 @@ uint32_t soc_get_variable_mtrr_count(uint64_t *msr)
msr_t s;
} mtrrcap;
mtrrcap.s = soc_mtrr_read(MTRR_CAP_MSR);
mtrrcap.s = rdmsr(MTRR_CAP_MSR);
if (msr != NULL)
*msr = mtrrcap.u64;
return mtrrcap.u64 & MTRR_CAP_VCNT;
@ -83,7 +83,7 @@ static void soc_display_4k_mtrr(uint32_t msr_reg, uint32_t starting_address,
msr_t s;
} msr;
msr.s = soc_mtrr_read(msr_reg);
msr.s = rdmsr(msr_reg);
printk(BIOS_DEBUG, "0x%016llx: %s\n", msr.u64, name);
soc_display_mtrr_fixed_types(msr.u64, starting_address, 0x1000);
}
@ -96,7 +96,7 @@ static void soc_display_16k_mtrr(uint32_t msr_reg, uint32_t starting_address,
msr_t s;
} msr;
msr.s = soc_mtrr_read(msr_reg);
msr.s = rdmsr(msr_reg);
printk(BIOS_DEBUG, "0x%016llx: %s\n", msr.u64, name);
soc_display_mtrr_fixed_types(msr.u64, starting_address, 0x4000);
}
@ -108,7 +108,7 @@ static void soc_display_64k_mtrr(void)
msr_t s;
} msr;
msr.s = soc_mtrr_read(MTRR_FIX_64K_00000);
msr.s = rdmsr(MTRR_FIX_64K_00000);
printk(BIOS_DEBUG, "0x%016llx: IA32_MTRR_FIX64K_00000\n", msr.u64);
soc_display_mtrr_fixed_types(msr.u64, 0, 0x10000);
}
@ -136,7 +136,7 @@ static void soc_display_mtrr_def_type(void)
msr_t s;
} msr;
msr.s = soc_mtrr_read(MTRR_DEF_TYPE_MSR);
msr.s = rdmsr(MTRR_DEF_TYPE_MSR);
printk(BIOS_DEBUG, "0x%016llx: IA32_MTRR_DEF_TYPE:%s%s %s\n",
msr.u64,
(msr.u64 & MTRR_DEF_TYPE_EN) ? " E," : "",
@ -160,8 +160,8 @@ static void soc_display_variable_mtrr(uint32_t msr_reg, int index,
msr_t s;
} msr_m;
msr_a.s = soc_mtrr_read(msr_reg);
msr_m.s = soc_mtrr_read(msr_reg + 1);
msr_a.s = rdmsr(msr_reg);
msr_m.s = rdmsr(msr_reg + 1);
if (msr_m.u64 & MTRR_PHYS_MASK_VALID) {
base_address = (msr_a.u64 & 0xfffffffffffff000ULL)
& address_mask;

View File

@ -22,12 +22,5 @@
asmlinkage void soc_display_mtrrs(void);
uint32_t soc_get_variable_mtrr_count(uint64_t *msr);
#if IS_ENABLED(CONFIG_SOC_SETS_MTRRS)
msr_t soc_mtrr_read(unsigned long index);
void soc_mtrr_write(unsigned long index, msr_t msr);
#else
#define soc_mtrr_read rdmsr
#define soc_mtrr_write wrmsr
#endif /* CONFIG_SOC_SETS_MTRRS */
#endif /* _INTEL_COMMON_UTIL_H_ */

View File

@ -30,7 +30,7 @@ config CPU_SPECIFIC_OPTIONS
select C_ENVIRONMENT_BOOTBLOCK
select REG_SCRIPT
select SOC_INTEL_COMMON
select SOC_SETS_MTRRS
select SOC_SETS_MSRS
select TSC_CONSTANT_RATE
select UART_OVERRIDE_REFCLK
select UDELAY_TSC

View File

@ -19,6 +19,7 @@
#define __SIMPLE_DEVICE__
#include <arch/io.h>
#include <cpu/x86/msr.h>
#include <delay.h>
#include <fsp/util.h>
#include <reg_script.h>
@ -230,6 +231,8 @@ void mcr_write(uint8_t opcode, uint8_t port, uint32_t reg_address);
uint32_t mdr_read(void);
void mdr_write(uint32_t value);
void mea_write(uint32_t reg_address);
uint32_t port_reg_read(uint8_t port, uint32_t offset);
void port_reg_write(uint8_t port, uint32_t offset, uint32_t value);
uint32_t reg_host_bridge_unit_read(uint32_t reg_address);
uint32_t reg_legacy_gpio_read(uint32_t reg_address);
void reg_legacy_gpio_write(uint32_t reg_address, uint32_t value);

View File

@ -26,8 +26,6 @@
#include <soc/reg_access.h>
asmlinkage void *car_state_c_entry(void);
uint32_t port_reg_read(uint8_t port, uint32_t offset);
void port_reg_write(uint8_t port, uint32_t offset, uint32_t value);
void report_platform_info(void);
int set_base_address_and_enable_uart(u8 bus, u8 dev, u8 func, u32 mmio_base);
void pcie_init(void);

View File

@ -15,6 +15,7 @@
#define __SIMPLE_DEVICE__
#include <cpu/x86/mtrr.h>
#include <console/console.h>
#include <soc/pci_devs.h>
#include <soc/ramstage.h>
@ -71,6 +72,33 @@ static uint16_t get_legacy_gpio_address(uint32_t reg_address)
return (uint16_t)(gpio_base_address + reg_address);
}
static uint32_t mtrr_index_to_host_bridge_register_offset(unsigned long index)
{
uint32_t offset;
/* Convert from MTRR index to host brigde offset (Datasheet 12.7.2) */
if (index == MTRR_CAP_MSR)
offset = QUARK_NC_HOST_BRIDGE_IA32_MTRR_CAP;
else if (index == MTRR_DEF_TYPE_MSR)
offset = QUARK_NC_HOST_BRIDGE_IA32_MTRR_DEF_TYPE;
else if (index == MTRR_FIX_64K_00000)
offset = QUARK_NC_HOST_BRIDGE_MTRR_FIX64K_00000;
else if ((index >= MTRR_FIX_16K_80000) && (index <= MTRR_FIX_16K_A0000))
offset = ((index - MTRR_FIX_16K_80000) << 1)
+ QUARK_NC_HOST_BRIDGE_MTRR_FIX16K_80000;
else if ((index >= MTRR_FIX_4K_C0000) && (index <= MTRR_FIX_4K_F8000))
offset = ((index - MTRR_FIX_4K_C0000) << 1)
+ QUARK_NC_HOST_BRIDGE_IA32_MTRR_PHYSBASE0;
else if ((index >= MTRR_PHYS_BASE(0)) && (index <= MTRR_PHYS_MASK(7)))
offset = (index - MTRR_PHYS_BASE(0))
+ QUARK_NC_HOST_BRIDGE_IA32_MTRR_PHYSBASE0;
else {
printk(BIOS_DEBUG, "index: 0x%08lx\n", index);
die("Invalid MTRR index specified!\n");
}
return offset;
}
void mcr_write(uint8_t opcode, uint8_t port, uint32_t reg_address)
{
pci_write_config32(MC_BDF, QNC_ACCESS_PORT_MCR,
@ -96,6 +124,22 @@ void mea_write(uint32_t reg_address)
& QNC_MEA_MASK);
}
uint32_t port_reg_read(uint8_t port, uint32_t offset)
{
/* Read the port register */
mea_write(offset);
mcr_write(QUARK_OPCODE_READ, port, offset);
return mdr_read();
}
void port_reg_write(uint8_t port, uint32_t offset, uint32_t value)
{
/* Write the port register */
mea_write(offset);
mdr_write(value);
mcr_write(QUARK_OPCODE_WRITE, port, offset);
}
static uint32_t reg_gpe0_read(uint32_t reg_address)
{
/* Read the GPE0 register */
@ -348,6 +392,50 @@ static void reg_write(struct reg_script_context *ctx)
}
}
msr_t soc_msr_read(unsigned index)
{
uint32_t offset;
union {
uint64_t u64;
msr_t msr;
} value;
/* Read the low 32-bits of the register */
offset = mtrr_index_to_host_bridge_register_offset(index);
value.u64 = port_reg_read(QUARK_NC_HOST_BRIDGE_SB_PORT_ID, offset);
/* For 64-bit registers, read the upper 32-bits */
if ((offset >= QUARK_NC_HOST_BRIDGE_MTRR_FIX64K_00000)
&& (offset <= QUARK_NC_HOST_BRIDGE_MTRR_FIX4K_F8000)) {
offset += 1;
value.u64 |= port_reg_read(QUARK_NC_HOST_BRIDGE_SB_PORT_ID,
offset);
}
return value.msr;
}
void soc_msr_write(unsigned index, msr_t msr)
{
uint32_t offset;
union {
uint32_t u32[2];
msr_t msr;
} value;
/* Write the low 32-bits of the register */
value.msr = msr;
offset = mtrr_index_to_host_bridge_register_offset(index);
port_reg_write(QUARK_NC_HOST_BRIDGE_SB_PORT_ID, offset, value.u32[0]);
/* For 64-bit registers, write the upper 32-bits */
if ((offset >= QUARK_NC_HOST_BRIDGE_MTRR_FIX64K_00000)
&& (offset <= QUARK_NC_HOST_BRIDGE_MTRR_FIX4K_F8000)) {
offset += 1;
port_reg_write(QUARK_NC_HOST_BRIDGE_SB_PORT_ID, offset,
value.u32[1]);
}
}
const struct reg_script_bus_entry soc_reg_script_bus_table = {
SOC_TYPE, reg_read, reg_write
};

View File

@ -21,93 +21,6 @@
#include <soc/pci_devs.h>
#include <soc/romstage.h>
static uint32_t mtrr_index_to_host_bridge_register_offset(unsigned long index)
{
uint32_t offset;
/* Convert from MTRR index to host brigde offset (Datasheet 12.7.2) */
if (index == MTRR_CAP_MSR)
offset = QUARK_NC_HOST_BRIDGE_IA32_MTRR_CAP;
else if (index == MTRR_DEF_TYPE_MSR)
offset = QUARK_NC_HOST_BRIDGE_IA32_MTRR_DEF_TYPE;
else if (index == MTRR_FIX_64K_00000)
offset = QUARK_NC_HOST_BRIDGE_MTRR_FIX64K_00000;
else if ((index >= MTRR_FIX_16K_80000) && (index <= MTRR_FIX_16K_A0000))
offset = ((index - MTRR_FIX_16K_80000) << 1)
+ QUARK_NC_HOST_BRIDGE_MTRR_FIX16K_80000;
else if ((index >= MTRR_FIX_4K_C0000) && (index <= MTRR_FIX_4K_F8000))
offset = ((index - MTRR_FIX_4K_C0000) << 1)
+ QUARK_NC_HOST_BRIDGE_IA32_MTRR_PHYSBASE0;
else if ((index >= MTRR_PHYS_BASE(0)) && (index <= MTRR_PHYS_MASK(7)))
offset = (index - MTRR_PHYS_BASE(0))
+ QUARK_NC_HOST_BRIDGE_IA32_MTRR_PHYSBASE0;
else {
printk(BIOS_DEBUG, "index: 0x%08lx\n", index);
die("Invalid MTRR index specified!\n");
}
return offset;
}
uint32_t port_reg_read(uint8_t port, uint32_t offset)
{
/* Read the port register */
mea_write(offset);
mcr_write(QUARK_OPCODE_READ, port, offset);
return mdr_read();
}
void port_reg_write(uint8_t port, uint32_t offset, uint32_t value)
{
/* Write the port register */
mea_write(offset);
mdr_write(value);
mcr_write(QUARK_OPCODE_WRITE, port, offset);
}
msr_t soc_mtrr_read(unsigned long index)
{
uint32_t offset;
union {
uint64_t u64;
msr_t msr;
} value;
/* Read the low 32-bits of the register */
offset = mtrr_index_to_host_bridge_register_offset(index);
value.u64 = port_reg_read(QUARK_NC_HOST_BRIDGE_SB_PORT_ID, offset);
/* For 64-bit registers, read the upper 32-bits */
if ((offset >= QUARK_NC_HOST_BRIDGE_MTRR_FIX64K_00000)
&& (offset <= QUARK_NC_HOST_BRIDGE_MTRR_FIX4K_F8000)) {
offset += 1;
value.u64 |= port_reg_read(QUARK_NC_HOST_BRIDGE_SB_PORT_ID,
offset);
}
return value.msr;
}
void soc_mtrr_write(unsigned long index, msr_t msr)
{
uint32_t offset;
union {
uint32_t u32[2];
msr_t msr;
} value;
/* Write the low 32-bits of the register */
value.msr = msr;
offset = mtrr_index_to_host_bridge_register_offset(index);
port_reg_write(QUARK_NC_HOST_BRIDGE_SB_PORT_ID, offset, value.u32[0]);
/* For 64-bit registers, write the upper 32-bits */
if ((offset >= QUARK_NC_HOST_BRIDGE_MTRR_FIX64K_00000)
&& (offset <= QUARK_NC_HOST_BRIDGE_MTRR_FIX4K_F8000)) {
offset += 1;
port_reg_write(QUARK_NC_HOST_BRIDGE_SB_PORT_ID, offset,
value.u32[1]);
}
}
asmlinkage void *soc_set_mtrrs(void *top_of_stack)
{
union {
@ -150,7 +63,7 @@ asmlinkage void *soc_set_mtrrs(void *top_of_stack)
mtrr_count = (*mtrr_data++) * 2;
data.u64 = 0;
while (mtrr_count-- > 0)
soc_mtrr_write(mtrr_reg++, data.msr);
soc_msr_write(mtrr_reg++, data.msr);
/* Setup the specified variable MTRRs */
mtrr_reg = MTRR_PHYS_BASE(0);
@ -158,10 +71,10 @@ asmlinkage void *soc_set_mtrrs(void *top_of_stack)
while (mtrr_count-- > 0) {
data.u32[0] = *mtrr_data++;
data.u32[1] = *mtrr_data++;
soc_mtrr_write(mtrr_reg++, data.msr); /* Base */
soc_msr_write(mtrr_reg++, data.msr); /* Base */
data.u32[0] = *mtrr_data++;
data.u32[1] = *mtrr_data++;
soc_mtrr_write(mtrr_reg++, data.msr); /* Mask */
soc_msr_write(mtrr_reg++, data.msr); /* Mask */
}
/* Remove setup_stack_and_mtrrs data and return the new top_of_stack */
@ -178,7 +91,7 @@ asmlinkage void soc_enable_mtrrs(void)
} data;
/* Enable MTRR. */
data.msr = soc_mtrr_read(MTRR_DEF_TYPE_MSR);
data.msr = soc_msr_read(MTRR_DEF_TYPE_MSR);
data.u32[0] |= MTRR_DEF_TYPE_EN;
soc_mtrr_write(MTRR_DEF_TYPE_MSR, data.msr);
soc_msr_write(MTRR_DEF_TYPE_MSR, data.msr);
}