18 changes: 9 additions & 9 deletions Documentation/tutorial/part3.md
Expand Up @@ -274,8 +274,8 @@ without changing the source code.

coreboot unit test infrastructure supports overriding of functions at link time.
This is as simple as adding a `name_of_function` to be mocked into
<test_name>-mocks variable in Makefile.inc. The result is that every time the
function is called, `wrap_name_of_function` will be called instead.
<test_name>-mocks variable in Makefile.inc. The result is that the test's
implementation of that function is called instead of coreboot's.

```eval_rst
.. admonition:: i2c-test example
Expand All @@ -284,13 +284,13 @@ function is called, `wrap_name_of_function` will be called instead.
i2c-test-mocks += platform_i2c_transfer
Now, dev can write own implementation of `platform_i2c_transfer` and define it
as `wrap_platform_i2c_transfer`. This implementation instead of accessing real
i2c bus, will write/read from fake structs.
Now, dev can write own implementation of `platform_i2c_transfer`. This
implementation instead of accessing real i2c bus, will write/read from
fake structs.
.. code-block:: c
int __wrap_platform_i2c_transfer(unsigned int bus, struct i2c_msg *segments,
int platform_i2c_transfer(unsigned int bus, struct i2c_msg *segments,
int count)
{
}
Expand Down Expand Up @@ -324,13 +324,13 @@ in which mock should have particular value, or be inside a described range.
I2C_M_RECV_LEN, I2C_M_NOSTART};
/* Flags should always be only within supported range */
expect_in_set_count(__wrap_platform_i2c_transfer, segments->flags,
expect_in_set_count(platform_i2c_transfer, segments->flags,
expected_flags, -1);
expect_not_value_count(__wrap_platform_i2c_transfer, segments->buf,
expect_not_value_count(platform_i2c_transfer, segments->buf,
NULL, -1);
expect_in_range_count(__wrap_platform_i2c_transfer, count, 1, INT_MAX,
expect_in_range_count(platform_i2c_transfer, count, 1, INT_MAX,
-1);
}
Expand Down
11 changes: 10 additions & 1 deletion configs/builder/config.ocp.deltalake
Expand Up @@ -3,15 +3,24 @@

CONFIG_VENDOR_OCP=y
CONFIG_BOARD_OCP_DELTALAKE=y
CONFIG_UART_FOR_CONSOLE=1
CONFIG_HAVE_IFD_BIN=y
CONFIG_ADD_FSP_BINARIES=y
CONFIG_LINUX_COMMAND_LINE="earlyprintk=uart8250,io,0x2f8,57600n1 console=uart8250,io,0x2f8,57600n1 intel_pstate=disable"
CONFIG_CPU_MICROCODE_CBFS_EXTERNAL_BINS=y
CONFIG_HAVE_ME_BIN=y
CONFIG_DO_NOT_TOUCH_DESCRIPTOR_REGION=y
# CONFIG_ON_DEVICE_ROM_LOAD is not set
CONFIG_USE_CPU_MICROCODE_CBFS_BINS=y
CONFIG_CPU_MICROCODE_CBFS_EXTERNAL_BINS=y
CONFIG_CPU_UCODE_BINARIES="site-local/deltalake/mbf5065a.mcb"
CONFIG_CPU_UCODE_BINARIES="site-local/deltalake/mbf5065b.mcb"
CONFIG_ADD_FSP_BINARIES=y
CONFIG_FSP_T_FILE="site-local/deltalake/Server_T.fd"
CONFIG_FSP_M_FILE="site-local/deltalake/Server_M.fd"
CONFIG_FSP_S_FILE="site-local/deltalake/Server_S.fd"
CONFIG_ME_BIN_PATH="site-local/deltalake/flashregion_2_intel_me.bin"
CONFIG_IFD_BIN_PATH="site-local/deltalake/flashregion_0_flashdescriptor.bin"
CONFIG_CONSOLE_SERIAL_57600=y
CONFIG_DEFAULT_CONSOLE_LOGLEVEL_4=y
CONFIG_PAYLOAD_LINUX=y
CONFIG_PAYLOAD_FILE="site-local/deltalake/linuxboot_uroot_ttys0"
2 changes: 1 addition & 1 deletion configs/config.asrock_b85m_pro4.tpm2_txt_placeholder_acms
Expand Up @@ -3,7 +3,7 @@
# Used ACMs were extracted from a Supermicro X10SLH firmware update.
CONFIG_VENDOR_ASROCK=y
CONFIG_BOARD_ASROCK_B85M_PRO4=y
CONFIG_USER_TPM2=y
CONFIG_TPM2=y
CONFIG_INTEL_TXT=y
CONFIG_INTEL_TXT_BIOSACM_FILE="3rdparty/blobs/cpu/intel/stm/stm.bin"
CONFIG_INTEL_TXT_SINITACM_FILE="3rdparty/blobs/cpu/intel/stm/stm.bin"
Expand Down
1 change: 1 addition & 0 deletions configs/config.dell_optiplex_9010_sff
@@ -1,6 +1,7 @@
CONFIG_USE_OPTION_TABLE=y
CONFIG_USE_BLOBS=y
CONFIG_VENDOR_DELL=y
CONFIG_BOARD_DELL_OPTIPLEX_9010=y
CONFIG_ONBOARD_VGA_IS_PRIMARY=y
# CONFIG_DRIVERS_UART_8250IO is not set
CONFIG_PCIEXP_CLK_PM=y
Expand Down
5 changes: 5 additions & 0 deletions configs/config.google_guado.pch_serialio_uart
@@ -0,0 +1,5 @@
# Configuration used to build-test Wildcat Point SerialIO UART console code.
CONFIG_VENDOR_GOOGLE=y
CONFIG_BOARD_GOOGLE_GUADO=y
CONFIG_SERIALIO_UART_CONSOLE=y
# CONFIG_DRIVERS_UART_8250IO is not set
5 changes: 5 additions & 0 deletions configs/config.google_panther.pch_serialio_uart
@@ -0,0 +1,5 @@
# Configuration used to build-test Lynx Point SerialIO UART console code.
CONFIG_VENDOR_GOOGLE=y
CONFIG_BOARD_GOOGLE_PANTHER=y
CONFIG_SERIALIO_UART_CONSOLE=y
# CONFIG_DRIVERS_UART_8250IO is not set
2 changes: 1 addition & 1 deletion configs/config.libretrend_lt1000
@@ -1,5 +1,5 @@
CONFIG_VENDOR_LIBRETREND=y
CONFIG_POWER_STATE_OFF_AFTER_FAILURE=y
CONFIG_GENERIC_LINEAR_FRAMEBUFFER=y
CONFIG_USER_TPM2=y
CONFIG_TPM2=y
CONFIG_SEABIOS_ADD_SERCON_PORT_FILE=y
8 changes: 8 additions & 0 deletions configs/config.ocp_deltalake_cbnt
@@ -0,0 +1,8 @@
CONFIG_VENDOR_OCP=y
CONFIG_INTEL_TXT_BIOSACM_FILE="3rdparty/intel-sec-tools/testdata/fake_acm/biosacm_cbnt_fake.bin"
CONFIG_INTEL_TXT_LOGGING=y
CONFIG_INTEL_CBNT_SUPPORT=y
# CONFIG_INTEL_CBNT_CBNT_PROV_KM_USE_CFG_FILE is not set
# CONFIG_INTEL_CBNT_CBNT_PROV_BPM_USE_CFG_FILE is not set
CONFIG_INTEL_CBNT_KM_PRIV_KEY_FILE="3rdparty/intel-sec-tools/testdata/testkeys/km_priv_key.pem"
CONFIG_INTEL_CBNT_BPM_PRIV_KEY_FILE="3rdparty/intel-sec-tools/testdata/testkeys/bpm_priv_key.pem"
4 changes: 2 additions & 2 deletions configs/config.pcengines_apu1
@@ -1,8 +1,8 @@
CONFIG_LOCALVERSION="v4.14.0.1"
CONFIG_LOCALVERSION="v4.14.0.2"
CONFIG_VENDOR_PCENGINES=y
CONFIG_PAYLOAD_CONFIGFILE="$(top)/src/mainboard/$(MAINBOARDDIR)/seabios_config"
CONFIG_NO_GFX_INIT=y
CONFIG_USER_TPM2=y
CONFIG_TPM2=y
CONFIG_DEFAULT_CONSOLE_LOGLEVEL_1=y
CONFIG_SEABIOS_REVISION=y
CONFIG_SEABIOS_REVISION_ID="rel-1.14.0.1"
Expand Down
4 changes: 2 additions & 2 deletions configs/config.pcengines_apu2
@@ -1,10 +1,10 @@
CONFIG_LOCALVERSION="v4.14.0.1"
CONFIG_LOCALVERSION="v4.14.0.2"
CONFIG_VENDOR_PCENGINES=y
CONFIG_PAYLOAD_CONFIGFILE="$(top)/src/mainboard/$(MAINBOARDDIR)/seabios_config"
CONFIG_PXE_ROM_ID="8086,157b"
CONFIG_BOARD_PCENGINES_APU2=y
CONFIG_NO_GFX_INIT=y
CONFIG_USER_TPM2=y
CONFIG_TPM2=y
CONFIG_DEFAULT_CONSOLE_LOGLEVEL_1=y
CONFIG_SEABIOS_REVISION=y
CONFIG_SEABIOS_REVISION_ID="rel-1.14.0.1"
Expand Down
4 changes: 2 additions & 2 deletions configs/config.pcengines_apu3
@@ -1,10 +1,10 @@
CONFIG_LOCALVERSION="v4.14.0.1"
CONFIG_LOCALVERSION="v4.14.0.2"
CONFIG_VENDOR_PCENGINES=y
CONFIG_PAYLOAD_CONFIGFILE="$(top)/src/mainboard/$(MAINBOARDDIR)/seabios_config"
CONFIG_BOARD_PCENGINES_APU3=y
CONFIG_PXE_ROM_ID="8086,1539"
CONFIG_NO_GFX_INIT=y
CONFIG_USER_TPM2=y
CONFIG_TPM2=y
CONFIG_DEFAULT_CONSOLE_LOGLEVEL_1=y
CONFIG_SEABIOS_REVISION=y
CONFIG_SEABIOS_REVISION_ID="rel-1.14.0.1"
Expand Down
4 changes: 2 additions & 2 deletions configs/config.pcengines_apu4
@@ -1,10 +1,10 @@
CONFIG_LOCALVERSION="v4.14.0.1"
CONFIG_LOCALVERSION="v4.14.0.2"
CONFIG_VENDOR_PCENGINES=y
CONFIG_PAYLOAD_CONFIGFILE="$(top)/src/mainboard/$(MAINBOARDDIR)/seabios_config"
CONFIG_BOARD_PCENGINES_APU4=y
CONFIG_PXE_ROM_ID="8086,1539"
CONFIG_NO_GFX_INIT=y
CONFIG_USER_TPM2=y
CONFIG_TPM2=y
CONFIG_DEFAULT_CONSOLE_LOGLEVEL_1=y
CONFIG_SEABIOS_REVISION=y
CONFIG_SEABIOS_REVISION_ID="rel-1.14.0.1"
Expand Down
4 changes: 2 additions & 2 deletions configs/config.pcengines_apu5
@@ -1,10 +1,10 @@
CONFIG_LOCALVERSION="v4.14.0.1"
CONFIG_LOCALVERSION="v4.14.0.2"
CONFIG_VENDOR_PCENGINES=y
CONFIG_PAYLOAD_CONFIGFILE="$(top)/src/mainboard/$(MAINBOARDDIR)/seabios_config"
CONFIG_BOARD_PCENGINES_APU5=y
CONFIG_PXE_ROM_ID="8086,1539"
CONFIG_NO_GFX_INIT=y
CONFIG_USER_TPM2=y
CONFIG_TPM2=y
CONFIG_DEFAULT_CONSOLE_LOGLEVEL_1=y
CONFIG_SEABIOS_REVISION=y
CONFIG_SEABIOS_REVISION_ID="rel-1.14.0.1"
Expand Down
4 changes: 2 additions & 2 deletions configs/config.pcengines_apu6
@@ -1,10 +1,10 @@
CONFIG_LOCALVERSION="v4.14.0.1"
CONFIG_LOCALVERSION="v4.14.0.2"
CONFIG_VENDOR_PCENGINES=y
CONFIG_PAYLOAD_CONFIGFILE="$(top)/src/mainboard/$(MAINBOARDDIR)/seabios_config"
CONFIG_BOARD_PCENGINES_APU6=y
CONFIG_PXE_ROM_ID="8086,1539"
CONFIG_NO_GFX_INIT=y
CONFIG_USER_TPM2=y
CONFIG_TPM2=y
CONFIG_DEFAULT_CONSOLE_LOGLEVEL_1=y
CONFIG_SEABIOS_REVISION=y
CONFIG_SEABIOS_REVISION_ID="rel-1.14.0.1"
Expand Down
1 change: 0 additions & 1 deletion payloads/Kconfig
Expand Up @@ -133,7 +133,6 @@ config NVRAMCUI_SECONDARY_PAYLOAD
bool "Load nvramcui as a secondary payload"
default n
depends on ARCH_X86 && HAVE_OPTION_TABLE
select USE_OPTION_TABLE
help
nvramcui can be loaded as a secondary payload under SeaBIOS, GRUB,
or any other payload that can load additional payloads.
Expand Down
1 change: 1 addition & 0 deletions payloads/external/Makefile.inc
Expand Up @@ -203,6 +203,7 @@ payloads/external/tianocore/tianocore/Build/UEFIPAYLOAD.fd tianocore: $(DOTCONFI
CONFIG_TIANOCORE_UPSTREAM=$(CONFIG_TIANOCORE_UPSTREAM) \
CONFIG_MMCONF_BASE_ADDRESS=$(CONFIG_MMCONF_BASE_ADDRESS) \
CONFIG_TIANOCORE_BOOT_TIMEOUT=$(CONFIG_TIANOCORE_BOOT_TIMEOUT) \
CONFIG_TIANOCORE_CBMEM_LOGGING=$(CONFIG_TIANOCORE_CBMEM_LOGGING) \
GCC_CC_x86_32=$(GCC_CC_x86_32) \
GCC_CC_x86_64=$(GCC_CC_x86_64) \
GCC_CC_arm=$(GCC_CC_arm) \
Expand Down
12 changes: 12 additions & 0 deletions payloads/external/tianocore/Kconfig
Expand Up @@ -53,6 +53,16 @@ config TIANOCORE_RELEASE

endchoice

if TIANOCORE_UEFIPAYLOAD

config TIANOCORE_CBMEM_LOGGING
bool "Enable Tianocore logging to CBMEM"
help
Select this option if you want to enable Tianocore logging to CBMEM.
You may want to increase the default cbmem buffer size when selecting
this option, especially if using a debug (vs release) build.
Selecting this option will increase the payload size in CBFS by ~220KB.

config TIANOCORE_BOOTSPLASH_IMAGE
bool "Use a custom bootsplash image"
help
Expand All @@ -72,6 +82,8 @@ config TIANOCORE_BOOTSPLASH_FILE
If an absolute path is not given, the path will assumed to be
relative to the coreboot root directory.

endif

config TIANOCORE_BOOT_TIMEOUT
int
default 2
Expand Down
8 changes: 6 additions & 2 deletions payloads/external/tianocore/Makefile
Expand Up @@ -30,9 +30,13 @@ else
BUILD_TYPE=RELEASE
endif

ifeq ($(CONFIG_TIANOCORE_CBMEM_LOGGING),y)
CBMEM=-D USE_CBMEM_FOR_CONSOLE=TRUE
endif

TIMEOUT=-D PLATFORM_BOOT_TIMEOUT=$(CONFIG_TIANOCORE_BOOT_TIMEOUT)

BUILD_STR=-q -a IA32 -a X64 -p UefiPayloadPkg/UefiPayloadPkg.dsc -t COREBOOT -b $(BUILD_TYPE) $(TIMEOUT) $(build_flavor)
BUILD_STR=-q -a IA32 -a X64 -p UefiPayloadPkg/UefiPayloadPkg.dsc -t COREBOOT -b $(BUILD_TYPE) $(TIMEOUT) $(build_flavor) $(CBMEM)

all: clean build

Expand Down Expand Up @@ -90,7 +94,7 @@ build: update checktools
cat ../tools_def.txt >> $(project_dir)/Conf/tools_def.txt; \
fi; \
build $(BUILD_STR); \
mv $(project_dir)/Build/$(bootloader)*/*/FV/UEFIPAYLOAD.fd $(project_dir)/Build/UEFIPAYLOAD.fd; \
mv $(project_dir)/Build/UefiPayloadPkg*/*/FV/UEFIPAYLOAD.fd $(project_dir)/Build/UEFIPAYLOAD.fd; \
git checkout MdeModulePkg/Logo/Logo.bmp > /dev/null 2>&1 || true

clean:
Expand Down
10 changes: 4 additions & 6 deletions payloads/libpayload/curses/curses.h
Expand Up @@ -154,9 +154,9 @@ typedef unsigned long mmask_t;
//// #define va_list int // FIXME

#define _XOPEN_SOURCE_EXTENDED 1 // XXX
//// #ifdef _XOPEN_SOURCE_EXTENDED
//// #include <stddef.h> /* we want wchar_t */
//// #endif /* _XOPEN_SOURCE_EXTENDED */
#ifdef _XOPEN_SOURCE_EXTENDED
#include <stddef.h> /* we want wchar_t */
#endif /* _XOPEN_SOURCE_EXTENDED */

/* XSI and SVr4 specify that curses implements 'bool'. However, C++ may also
* implement it. If so, we must use the C++ compiler's type to avoid conflict
Expand Down Expand Up @@ -350,9 +350,7 @@ typedef chtype attr_t; /* ...must be at least as wide as chtype */
#endif

#if 1
//// #include <wchar.h> /* ...to get mbstate_t, etc. */
typedef unsigned long wchar_t; // XXX
typedef unsigned long wint_t; // XXX
#include <wchar.h> /* ...to get mbstate_t, etc. */
#endif

#if 0
Expand Down
1 change: 1 addition & 0 deletions payloads/libpayload/include/coreboot_tables.h
Expand Up @@ -81,6 +81,7 @@ enum {
CB_TAG_FMAP = 0x0037,
CB_TAG_SMMSTOREV2 = 0x0039,
CB_TAG_BOARD_CONFIG = 0x0040,
CB_TAG_ACPI_CNVS = 0x0041,
CB_TAG_CMOS_OPTION_TABLE = 0x00c8,
CB_TAG_OPTION = 0x00c9,
CB_TAG_OPTION_ENUM = 0x00ca,
Expand Down
3 changes: 0 additions & 3 deletions payloads/libpayload/include/libpayload.h
Expand Up @@ -441,9 +441,6 @@ int exec(long addr, int argc, char **argv);
*/
int bcd2dec(int b);
int dec2bcd(int d);
int abs(int j);
long int labs(long int j);
long long int llabs(long long int j);
u8 bin2hex(u8 b);
u8 hex2bin(u8 h);
void hexdump(const void *memory, size_t length);
Expand Down
2 changes: 2 additions & 0 deletions payloads/libpayload/include/limits.h
Expand Up @@ -39,6 +39,8 @@
# endif
#endif

#define CHAR_BIT 8

#define USHRT_MAX ((unsigned short int)~0U)
#define SHRT_MIN ((short int)(USHRT_MAX & ~(USHRT_MAX >> 1)))
#define SHRT_MAX ((short int)(USHRT_MAX >> 1))
Expand Down
11 changes: 11 additions & 0 deletions payloads/libpayload/include/stddef.h
@@ -1,6 +1,15 @@
#ifndef _STDDEF_H
#define _STDDEF_H

#include <arch/types.h>

#ifndef __WCHAR_TYPE__
#define __WCHAR_TYPE__ int
#endif
#ifndef __cplusplus
typedef __WCHAR_TYPE__ wchar_t;
#endif

#ifndef __SIZE_TYPE__
#define __SIZE_TYPE__ unsigned long
#endif
Expand Down Expand Up @@ -35,3 +44,5 @@ typedef __SIZE_TYPE__ ssize_t;
#define NSECS_PER_MSEC (NSECS_PER_SEC / MSECS_PER_SEC)
#define NSECS_PER_USEC (NSECS_PER_SEC / USECS_PER_SEC)
#define USECS_PER_MSEC (USECS_PER_SEC / MSECS_PER_SEC)

#endif
11 changes: 9 additions & 2 deletions payloads/libpayload/include/stdlib.h
Expand Up @@ -201,6 +201,15 @@ int rand(void);
void srand(unsigned int seed);
/** @} */

/**
* @defgroup misc Misc functions
* @{
*/
int abs(int j);
long int labs(long int j);
long long int llabs(long long int j);
/** @} */

/* Enter remote GDB mode. Will initialize connection if not already up. */
void gdb_enter(void);
/* Disconnect existing GDB connection if one exists. */
Expand All @@ -217,8 +226,6 @@ void exit(int status) __attribute__((noreturn));
#define halt() do { gdb_enter(); halt(); } while (0)
#endif

/** @} */

void qsort(void *aa, size_t n, size_t es, int (*cmp)(const void *, const void *));
char *getenv(const char*);
uint64_t __umoddi3(uint64_t num, uint64_t den);
Expand Down
1 change: 1 addition & 0 deletions payloads/libpayload/include/sysinfo.h
Expand Up @@ -109,6 +109,7 @@ struct sysinfo_t {
uintptr_t cbmem_cons;
uintptr_t mrc_cache;
uintptr_t acpi_gnvs;
uintptr_t acpi_cnvs;

#define UNDEFINED_STRAPPING_ID (~0)
#define UNDEFINED_FW_CONFIG ~((uint64_t)0)
Expand Down
11 changes: 11 additions & 0 deletions payloads/libpayload/include/wchar.h
@@ -0,0 +1,11 @@
#ifndef _WCHAR_H
#define _WCHAR_H

#include <stddef.h>

#ifndef __WINT_TYPE__
# define __WINT_TYPE__ unsigned int
#endif
typedef __WINT_TYPE__ wint_t;

#endif
8 changes: 8 additions & 0 deletions payloads/libpayload/libc/coreboot.c
Expand Up @@ -143,6 +143,11 @@ static void cb_parse_acpi_gnvs(unsigned char *ptr, struct sysinfo_t *info)
info->acpi_gnvs = get_cbmem_addr(ptr);
}

static void cb_parse_acpi_cnvs(unsigned char *ptr, struct sysinfo_t *info)
{
info->acpi_cnvs = get_cbmem_addr(ptr);
}

static void cb_parse_board_config(unsigned char *ptr, struct sysinfo_t *info)
{
struct cb_board_config *const config = (struct cb_board_config *)ptr;
Expand Down Expand Up @@ -380,6 +385,9 @@ int cb_parse_header(void *addr, int len, struct sysinfo_t *info)
case CB_TAG_ACPI_GNVS:
cb_parse_acpi_gnvs(ptr, info);
break;
case CB_TAG_ACPI_CNVS:
cb_parse_acpi_cnvs(ptr, info);
break;
case CB_TAG_BOARD_CONFIG:
cb_parse_board_config(ptr, info);
break;
Expand Down
24 changes: 24 additions & 0 deletions src/Kconfig
Expand Up @@ -120,13 +120,30 @@ config UTIL_GENPARSER

Otherwise, say N to use the provided pregenerated scanner/parser.

choice
prompt "Option backend to use"
default USE_MAINBOARD_SPECIFIC_OPTION_BACKEND if HAVE_MAINBOARD_SPECIFIC_OPTION_BACKEND
default USE_OPTION_TABLE if NVRAMCUI_SECONDARY_PAYLOAD

config OPTION_BACKEND_NONE
bool "None"

config USE_OPTION_TABLE
bool "Use CMOS for configuration values"
depends on HAVE_OPTION_TABLE
help
Enable this option if coreboot shall read options from the "CMOS"
NVRAM instead of using hard-coded values.

config USE_MAINBOARD_SPECIFIC_OPTION_BACKEND
bool "Use mainboard-specific option backend"
depends on HAVE_MAINBOARD_SPECIFIC_OPTION_BACKEND
help
Use a mainboard-specific mechanism to access runtime-configurable
options.

endchoice

config STATIC_OPTION_TABLE
bool "Load default configuration values into CMOS on each boot"
depends on USE_OPTION_TABLE
Expand Down Expand Up @@ -674,6 +691,13 @@ config NUM_THREADS
help
How many execution threads to cooperatively multitask with.

config HAVE_MAINBOARD_SPECIFIC_OPTION_BACKEND
bool
help
Selected by mainboards which implement a mainboard-specific mechanism
to access the values for runtime-configurable options. For example, a
custom BMC interface or an EEPROM with an externally-imposed layout.

config HAVE_OPTION_TABLE
bool
default n
Expand Down
3 changes: 0 additions & 3 deletions src/acpi/Kconfig
Expand Up @@ -30,9 +30,6 @@ config ACPI_SOC_NVS
Set to indicate <soc/nvs.h> exists for the platform with a definition
for global_nvs.

config ACPI_HAS_DEVICE_NVS
bool

config ACPI_NO_PCAT_8259
bool
help
Expand Down
27 changes: 11 additions & 16 deletions src/acpi/acpi.c
Expand Up @@ -1559,14 +1559,6 @@ unsigned long acpi_create_lpi_desc_ncst(acpi_lpi_desc_ncst_t *lpi_desc, uint16_t
return lpi_desc->header.length;
}

/* BERT helpers */
bool __weak acpi_is_boot_error_src_present(void)
{
return false;
}

__weak void acpi_soc_fill_bert(acpi_bert_t *bert, void **region, size_t *length) {}

unsigned long __weak fw_cfg_acpi_tables(unsigned long start)
{
return 0;
Expand Down Expand Up @@ -1712,6 +1704,8 @@ unsigned long write_acpi_tables(unsigned long start)

if (CONFIG(ACPI_SOC_NVS))
acpi_fill_gnvs();
if (CONFIG(CHROMEOS_NVS))
acpi_fill_cnvs();

for (dev = all_devices; dev; dev = dev->next)
if (dev->ops && dev->ops->acpi_inject_dsdt)
Expand Down Expand Up @@ -1810,18 +1804,19 @@ unsigned long write_acpi_tables(unsigned long start)

current = acpi_align_current(current);

if (acpi_is_boot_error_src_present()) {
if (CONFIG(ACPI_BERT)) {
void *region;
size_t size;
printk(BIOS_DEBUG, "ACPI: * BERT\n");
bert = (acpi_bert_t *) current;
acpi_soc_fill_bert(bert, &region, &size);
acpi_write_bert(bert, (uintptr_t)region, size);
if (bert->header.length >= sizeof(acpi_bert_t)) {
current += bert->header.length;
acpi_add_table(rsdp, bert);
if (acpi_soc_get_bert_region(&region, &size) == CB_SUCCESS) {
printk(BIOS_DEBUG, "ACPI: * BERT\n");
acpi_write_bert(bert, (uintptr_t)region, size);
if (bert->header.length >= sizeof(acpi_bert_t)) {
current += bert->header.length;
acpi_add_table(rsdp, bert);
}
current = acpi_align_current(current);
}
current = acpi_align_current(current);
}

printk(BIOS_DEBUG, "current = %lx\n", current);
Expand Down
3 changes: 0 additions & 3 deletions src/acpi/acpigen_extern.asl
Expand Up @@ -9,9 +9,6 @@

#if CONFIG(ACPI_SOC_NVS)
External (GNVS, OpRegionObj)
#endif

#if CONFIG(ACPI_HAS_DEVICE_NVS)
External (DNVS, OpRegionObj)
#endif

Expand Down
52 changes: 50 additions & 2 deletions src/acpi/device.c
Expand Up @@ -598,6 +598,50 @@ void acpi_device_write_uart(const struct acpi_uart *uart)
acpi_device_fill_len(desc_length);
}

#define ACPI_POWER_RESOURCE_STATUS_ON_OP ONE_OP
#define ACPI_POWER_RESOURCE_STATUS_OFF_OP ZERO_OP

/**
* Writes an ACPI fragment that will check the GPIO and return 0 if the GPIO
* state does not match the active parameter.
*/
static void acpigen_write_gpio_STA(const struct acpi_gpio *gpio, bool active)
{
if (!gpio || !gpio->pin_count)
return;

/* Read current GPIO status into Local0. */
acpigen_get_tx_gpio(gpio);

/*
* If (!Local0)
* {
* Return (Zero)
* }
*/
acpigen_write_if();
if (active)
acpigen_emit_byte(LNOT_OP);
acpigen_emit_byte(LOCAL0_OP);
acpigen_write_return_op(ACPI_POWER_RESOURCE_STATUS_OFF_OP);
acpigen_write_if_end();
}

static void acpigen_write_power_res_STA(const struct acpi_power_res_params *params)
{
acpigen_write_method_serialized("_STA", 0);

/* Verify all the GPIOs are in the ON state, otherwise return 0 */
acpigen_write_gpio_STA(params->enable_gpio, true);
acpigen_write_gpio_STA(params->reset_gpio, false);
acpigen_write_gpio_STA(params->stop_gpio, false);

/* All GPIOs are in the ON state */
acpigen_write_return_op(ACPI_POWER_RESOURCE_STATUS_ON_OP);

acpigen_pop_len(); /* Method */
}

/* PowerResource() with Enable and/or Reset control */
void acpi_device_add_power_res(const struct acpi_power_res_params *params)
{
Expand All @@ -613,8 +657,12 @@ void acpi_device_add_power_res(const struct acpi_power_res_params *params)
acpigen_write_power_res("PRIC", 0, 0, power_res_dev_states,
ARRAY_SIZE(power_res_dev_states));

/* Method (_STA, 0, NotSerialized) { Return (0x1) } */
acpigen_write_STA(0x1);
if (params->use_gpio_for_status) {
acpigen_write_power_res_STA(params);
} else {
/* Method (_STA, 0, NotSerialized) { Return (0x1) } */
acpigen_write_STA(ACPI_POWER_RESOURCE_STATUS_ON_OP);
}

/* Method (_ON, 0, Serialized) */
acpigen_write_method_serialized("_ON", 0);
Expand Down
46 changes: 16 additions & 30 deletions src/acpi/gnvs.c
Expand Up @@ -8,40 +8,31 @@
#include <stdint.h>
#include <string.h>
#include <types.h>
#include <vendorcode/google/chromeos/gnvs.h>

static struct global_nvs *gnvs;
static void *dnvs;

void acpi_create_gnvs(void)
{
size_t gnvs_size;
const size_t gnvs_size = ALIGN_UP(sizeof(struct global_nvs), sizeof(uint64_t));
const size_t dnvs_size = ALIGN_UP(size_of_dnvs(), sizeof(uint64_t));

gnvs = cbmem_find(CBMEM_ID_ACPI_GNVS);
if (gnvs)
return;

/* Match with OpRegion declared in global_nvs.asl. */
gnvs_size = sizeof(struct global_nvs);
if (gnvs_size < 0x100)
gnvs_size = 0x100;
if (CONFIG(ACPI_HAS_DEVICE_NVS))
gnvs_size = 0x2000;
else if (CONFIG(CHROMEOS_NVS))
gnvs_size = 0x1000;

gnvs = cbmem_add(CBMEM_ID_ACPI_GNVS, gnvs_size);
/* Allocate for both GNVS and DNVS OpRegions. */
gnvs = cbmem_add(CBMEM_ID_ACPI_GNVS, gnvs_size + dnvs_size);
if (!gnvs)
return;

memset(gnvs, 0, gnvs_size);
memset(gnvs, 0, gnvs_size + dnvs_size);

if (dnvs_size)
dnvs = (char *)gnvs + gnvs_size;

if (CONFIG(CONSOLE_CBMEM))
gnvs->cbmc = (uintptr_t)cbmem_find(CBMEM_ID_CONSOLE);

if (CONFIG(CHROMEOS_NVS)) {
chromeos_acpi_t *init = (void *)((u8 *)gnvs + GNVS_CHROMEOS_ACPI_OFFSET);
chromeos_init_chromeos_acpi(init);
}
}

void *acpi_get_gnvs(void)
Expand All @@ -59,21 +50,21 @@ void *acpi_get_gnvs(void)

void *acpi_get_device_nvs(void)
{
return (u8 *)gnvs + GNVS_DEVICE_NVS_OFFSET;
return dnvs;
}

/* Implemented under platform. */
__weak void soc_fill_gnvs(struct global_nvs *gnvs_) { }
__weak void mainboard_fill_gnvs(struct global_nvs *gnvs_) { }
__weak size_t size_of_dnvs(void) { return 0; }

/* Called from write_acpi_tables() only on normal boot path. */
void acpi_fill_gnvs(void)
{
const struct opregion gnvs_op = OPREGION("GNVS", SYSTEMMEMORY, (uintptr_t)gnvs, 0x100);
const struct opregion cnvs_op = OPREGION("CNVS", SYSTEMMEMORY,
(uintptr_t)gnvs + GNVS_CHROMEOS_ACPI_OFFSET, 0xf00);
const struct opregion dnvs_op = OPREGION("DNVS", SYSTEMMEMORY,
(uintptr_t)gnvs + GNVS_DEVICE_NVS_OFFSET, 0x1000);
const struct opregion gnvs_op = OPREGION("GNVS", SYSTEMMEMORY, (uintptr_t)gnvs,
sizeof(struct global_nvs));
const struct opregion dnvs_op = OPREGION("DNVS", SYSTEMMEMORY, (uintptr_t)dnvs,
size_of_dnvs());

if (!gnvs)
return;
Expand All @@ -83,13 +74,8 @@ void acpi_fill_gnvs(void)

acpigen_write_scope("\\");
acpigen_write_opregion(&gnvs_op);

if (CONFIG(CHROMEOS_NVS))
acpigen_write_opregion(&cnvs_op);

if (CONFIG(ACPI_HAS_DEVICE_NVS))
if (dnvs)
acpigen_write_opregion(&dnvs_op);

acpigen_pop_len();
}

Expand Down
8 changes: 0 additions & 8 deletions src/arch/x86/Kconfig
Expand Up @@ -172,14 +172,6 @@ config CMOS_DEFAULT_FILE
default "src/mainboard/\$(MAINBOARDDIR)/cmos.default"
depends on HAVE_CMOS_DEFAULT

config IOAPIC_INTERRUPTS_ON_FSB
bool
default y if !IOAPIC_INTERRUPTS_ON_APIC_SERIAL_BUS

config IOAPIC_INTERRUPTS_ON_APIC_SERIAL_BUS
bool
default n

config HPET_ADDRESS_OVERRIDE
def_bool n

Expand Down
15 changes: 6 additions & 9 deletions src/arch/x86/acpi_bert_storage.c
Expand Up @@ -8,6 +8,7 @@
#include <acpi/acpi.h>
#include <arch/bert_storage.h>
#include <string.h>
#include <types.h>

/* BERT region management: Allow the chipset to determine the specific
* location of the BERT region. We find that base and size, then manage
Expand All @@ -19,7 +20,7 @@
* resume cycles. If the requirements change, consider using IMD to help
* manage the space.
*/
static int bert_region_broken;
static bool bert_region_broken;
static void *bert_region_base;
static size_t bert_region_size;
static size_t bert_region_used;
Expand All @@ -32,9 +33,9 @@ size_t bert_storage_remaining(void)
return bert_region_broken ? 0 : bert_region_size - bert_region_used;
}

int bert_errors_present(void)
bool bert_errors_present(void)
{
return bert_region_broken ? 0 : !!bert_region_used;
return !bert_region_broken && bert_region_used;
}

void bert_errors_region(void **start, size_t *size)
Expand Down Expand Up @@ -106,7 +107,6 @@ static void revise_error_sizes(acpi_generic_error_status_t *status, size_t size)
entries = bert_entry_count(status);
entry = acpi_hest_generic_data_nth(status, entries);
status->data_length += size;
status->raw_data_length += size;
if (entry)
entry->data_length += size;
}
Expand Down Expand Up @@ -175,7 +175,6 @@ static acpi_hest_generic_data_v300_t *new_generic_error_entry(
entry->validation_bits |= ACPI_GENERROR_VALID_TIMESTAMP;

status->data_length += sizeof(*entry);
status->raw_data_length += sizeof(*entry);
bert_bump_entry_count(status);

return entry;
Expand Down Expand Up @@ -528,8 +527,6 @@ acpi_generic_error_status_t *bert_new_event(guid_t *guid)
if (!status)
return NULL;

status->raw_data_length = sizeof(*status);

if (!guidcmp(guid, &CPER_SEC_PROC_GENERIC_GUID))
r = bert_append_genproc(status);
else if (!guidcmp(guid, &CPER_SEC_PROC_GENERIC_GUID))
Expand Down Expand Up @@ -585,14 +582,14 @@ static void bert_storage_setup(int unused)
/* Always start with a blank bert region. Make sure nothing is
* maintained across reboots or resumes.
*/
bert_region_broken = 0;
bert_region_broken = false;
bert_region_used = 0;

bert_reserved_region(&bert_region_base, &bert_region_size);

if (!bert_region_base || !bert_region_size) {
printk(BIOS_ERR, "Bug: Can't find/add BERT storage area\n");
bert_region_broken = 1;
bert_region_broken = true;
return;
}

Expand Down
2 changes: 1 addition & 1 deletion src/arch/x86/bootblock.ld
Expand Up @@ -17,7 +17,7 @@ SECTIONS {
. = _ebootblock - CONFIG_C_ENV_BOOTBLOCK_SIZE;
#else
. = BOOTBLOCK_TOP - PROGRAM_SZ;
. = ALIGN(16);
. = ALIGN(64);
#endif

_bootblock = .;
Expand Down
13 changes: 9 additions & 4 deletions src/arch/x86/c_start.S
Expand Up @@ -32,8 +32,11 @@ thread_stacks:
.globl _start
_start:
cli
#ifdef __x86_64__
movabs $gdtaddr, %rax
lgdt (%rax)
#else
lgdt %cs:gdtaddr
#ifndef __x86_64__
ljmp $RAM_CODE_SEG, $1f
#endif
1: movl $RAM_DATA_SEG, %eax
Expand All @@ -52,19 +55,21 @@ _start:
cld

#ifdef __x86_64__
mov %rdi, _cbmem_top_ptr
mov %rdi, %rax
movabs %rax, _cbmem_top_ptr
movabs $_stack, %rdi
#else
/* The return argument is at 0(%esp), the calling argument at 4(%esp) */
movl 4(%esp), %eax
movl %eax, _cbmem_top_ptr
leal _stack, %edi
#endif

/** poison the stack. Code should not count on the
* stack being full of zeros. This stack poisoning
* recently uncovered a bug in the broadcast SIPI
* code.
*/
leal _stack, %edi
movl $_estack, %ecx
subl %edi, %ecx
shrl $2, %ecx /* it is 32 bit aligned, right? */
Expand Down Expand Up @@ -226,7 +231,7 @@ SetCodeSelector:
push %rsp
pushfq
push %rcx # cx is code segment selector from caller
mov $setCodeSelectorLongJump, %rax
movabs $setCodeSelectorLongJump, %rax
push %rax

# the iret will continue at next instruction, with the new cs value
Expand Down
5 changes: 0 additions & 5 deletions src/arch/x86/cpu.c
Expand Up @@ -340,8 +340,3 @@ int cpu_index(void)
}
return -1;
}

uintptr_t cpu_get_lapic_addr(void)
{
return LOCAL_APIC_ADDR;
}
5 changes: 3 additions & 2 deletions src/arch/x86/exception.c
Expand Up @@ -486,6 +486,7 @@ void x86_exception(struct eregs *info)
#else /* !CONFIG_GDB_STUB */

int logical_processor = 0;
u32 apic_id = CONFIG(SMP) ? lapicid() : 0;

#if ENV_RAMSTAGE
logical_processor = cpu_index();
Expand All @@ -505,7 +506,7 @@ void x86_exception(struct eregs *info)
"r10: %016llx r11: %016llx\n"
"r12: %016llx r13: %016llx\n"
"r14: %016llx r15: %016llx\n",
logical_processor, (unsigned int)lapicid(),
logical_processor, apic_id,
info->vector, info->cs, info->rip,
info->error_code, info->rflags, read_cr2(),
info->rax, info->rbx, info->rcx, info->rdx,
Expand All @@ -522,7 +523,7 @@ void x86_exception(struct eregs *info)
"Code: %d eflags: %08x cr2: %08x\n"
"eax: %08x ebx: %08x ecx: %08x edx: %08x\n"
"edi: %08x esi: %08x ebp: %08x esp: %08x\n",
logical_processor, (unsigned int)lapicid(),
logical_processor, apic_id,
info->vector, info->cs, info->eip,
info->error_code, info->eflags, read_cr2(),
info->eax, info->ebx, info->ecx, info->edx,
Expand Down
19 changes: 16 additions & 3 deletions src/arch/x86/exit_car.S
Expand Up @@ -49,7 +49,8 @@ _start:
#endif

#ifdef __x86_64__
mov %rdi, _cbmem_top_ptr
mov %rdi, %rax
movabs %rax, _cbmem_top_ptr
#else
/* The return argument is at 0(%esp), the calling argument at 4(%esp) */
movl 4(%esp), %eax
Expand All @@ -60,7 +61,12 @@ _start:
cpuid
btl $CPUID_FEATURE_CLFLUSH_BIT, %edx
jnc skip_clflush
#ifdef __x86_64__
movabs _cbmem_top_ptr, %rax
clflush (%rax)
#else
clflush _cbmem_top_ptr
#endif

skip_clflush:
/* chipset_teardown_car() is expected to disable cache-as-ram. */
Expand All @@ -71,17 +77,24 @@ skip_clflush:
mov %cr0, %rax
and $(~(CR0_CD | CR0_NW)), %eax
mov %rax, %cr0

/* Ensure cache is clean. */
invd

/* Set up new stack. */
movabs post_car_stack_top, %rax
mov %rax, %rsp
#else
mov %cr0, %eax
and $(~(CR0_CD | CR0_NW)), %eax
mov %eax, %cr0
#endif

/* Ensure cache is clean. */
invd

/* Set up new stack. */
mov post_car_stack_top, %esp

#endif
/*
* Honor variable MTRR information pushed on the stack with the
* following layout:
Expand Down
12 changes: 0 additions & 12 deletions src/arch/x86/gdt_init.S
Expand Up @@ -23,18 +23,6 @@ gdtptr:
.section .init._gdt64_, "ax", @progbits
.globl gdt_init64
gdt_init64:
/* Workaround a bug in the assembler.
* The following code doesn't work:
* lgdt gdtptr64
*
* The assembler tries to save memory by using 32bit displacement addressing mode.
* Displacements are using signed integers.
* This is fine in protected mode, as the negative address points to the correct
* address > 2GiB, but in long mode this doesn't work at all.
* Tests showed that QEMU can gracefully handle it, but real CPUs can't.
*
* Use the movabs pseudo instruction to force using a 64bit absolute address.
*/
movabs $gdtptr64, %rax
lgdt (%rax)
ret
Expand Down
9 changes: 7 additions & 2 deletions src/arch/x86/include/arch/bert_storage.h
Expand Up @@ -3,8 +3,8 @@
#ifndef _BERT_STORAGE_H_
#define _BERT_STORAGE_H_

#include <stdint.h>
#include <acpi/acpi.h>
#include <types.h>

/* Items in the BERT region
*
Expand Down Expand Up @@ -55,7 +55,12 @@ void bert_errors_region(void **start, size_t *size);
/* Get amount of available storage left for error info */
size_t bert_storage_remaining(void);
/* Find if errors were added, a BERT region is present, and ACPI table needed */
int bert_errors_present(void);
bool bert_errors_present(void);
/* The BERT table should only be generated when BERT support is enabled and there's an error */
static inline bool bert_should_generate_acpi_table(void)
{
return CONFIG(ACPI_BERT) && bert_errors_present();
}

/* Get the number of entries associated with status */
static inline size_t bert_entry_count(acpi_generic_error_status_t *status)
Expand Down
7 changes: 6 additions & 1 deletion src/arch/x86/include/arch/ioapic.h
Expand Up @@ -9,7 +9,7 @@

#ifndef __ACPI__

#include <stdint.h>
#include <types.h>

#define ALL (0xff << 24)
#define NONE (0)
Expand All @@ -29,8 +29,13 @@
u32 io_apic_read(void *ioapic_base, u32 reg);
void io_apic_write(void *ioapic_base, u32 reg, u32 value);
void set_ioapic_id(void *ioapic_base, u8 ioapic_id);
u8 get_ioapic_id(void *ioapic_base);
u8 get_ioapic_version(void *ioapic_base);
void setup_ioapic(void *ioapic_base, u8 ioapic_id);
void clear_ioapic(void *ioapic_base);

void ioapic_set_boot_config(void *ioapic_base, bool irq_on_fsb);
void setup_ioapic_helper(void *ioapic_base, u8 ioapic_id, bool enable_virtual_wire);
#endif

#endif
8 changes: 6 additions & 2 deletions src/arch/x86/include/arch/smp/mpspec.h
Expand Up @@ -155,7 +155,7 @@ struct mpc_config_lintsrc {
#define MAX_IRQ_SOURCES 128
#define MAX_MP_BUSSES 32
enum mp_bustype {
MP_BUS_ISA,
MP_BUS_ISA = 0,
MP_BUS_EISA,
MP_BUS_PCI,
MP_BUS_MCA
Expand Down Expand Up @@ -224,7 +224,7 @@ struct mp_exten_compatibility_address_space {
*/
} __packed;

void mptable_init(struct mp_config_table *mc, u32 lapic_addr);
void mptable_init(struct mp_config_table *mc);
void *smp_next_mpc_entry(struct mp_config_table *mc);
void *smp_next_mpe_entry(struct mp_config_table *mc);

Expand All @@ -235,6 +235,10 @@ void smp_write_processor(struct mp_config_table *mc,
void smp_write_processors(struct mp_config_table *mc);
void smp_write_ioapic(struct mp_config_table *mc,
u8 id, u8 ver, void *apicaddr);

/* Call smp_write_ioapic() and return IOAPIC ID field. */
u8 smp_write_ioapic_from_hw(struct mp_config_table *mc, void *apicaddr);

void smp_write_intsrc(struct mp_config_table *mc,
u8 irqtype, u16 irqflag, u8 srcbus, u8 srcbusirq,
u8 dstapic, u8 dstirq);
Expand Down
104 changes: 60 additions & 44 deletions src/arch/x86/ioapic.c
@@ -1,5 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */

#include <assert.h>
#include <device/mmio.h>
#include <arch/ioapic.h>
#include <console/console.h>
Expand All @@ -17,11 +18,20 @@ void io_apic_write(void *ioapic_base, u32 reg, u32 value)
write32(ioapic_base + 0x10, value);
}

static void write_vector(void *ioapic_base, u8 vector, u32 high, u32 low)
{
io_apic_write(ioapic_base, vector * 2 + 0x10, low);
io_apic_write(ioapic_base, vector * 2 + 0x11, high);

printk(BIOS_SPEW, "IOAPIC: vector 0x%02x value 0x%08x 0x%08x\n",
vector, high, low);
}

static int ioapic_interrupt_count(void *ioapic_base)
{
/* Read the available number of interrupts. */
int ioapic_interrupts = (io_apic_read(ioapic_base, 0x01) >> 16) & 0xff;
if (ioapic_interrupts == 0xff)
if (!ioapic_interrupts || ioapic_interrupts == 0xff)
ioapic_interrupts = 23;
ioapic_interrupts += 1; /* Bits 23-16 specify the maximum redirection
entry, which is the number of interrupts
Expand All @@ -31,25 +41,45 @@ static int ioapic_interrupt_count(void *ioapic_base)
return ioapic_interrupts;
}

void clear_ioapic(void *ioapic_base)
static void clear_vectors(void *ioapic_base, u8 first, u8 last)
{
u32 low, high;
u32 i, ioapic_interrupts;
u8 i;

printk(BIOS_DEBUG, "IOAPIC: Clearing IOAPIC at %p\n", ioapic_base);

ioapic_interrupts = ioapic_interrupt_count(ioapic_base);

low = INT_DISABLED;
high = NONE;

for (i = 0; i < ioapic_interrupts; i++) {
io_apic_write(ioapic_base, i * 2 + 0x10, low);
io_apic_write(ioapic_base, i * 2 + 0x11, high);
for (i = first; i <= last; i++)
write_vector(ioapic_base, i, high, low);

printk(BIOS_SPEW, "IOAPIC: reg 0x%08x value 0x%08x 0x%08x\n",
i, high, low);
if (io_apic_read(ioapic_base, 0x10) == 0xffffffff) {
printk(BIOS_WARNING, "IOAPIC not responding.\n");
return;
}
}

void clear_ioapic(void *ioapic_base)
{
clear_vectors(ioapic_base, 0, ioapic_interrupt_count(ioapic_base) - 1);
}

static void route_i8259_irq0(void *ioapic_base)
{
u32 bsp_lapicid = lapicid();
u32 low, high;

ASSERT(bsp_lapicid < 255);

printk(BIOS_DEBUG, "IOAPIC: Bootstrap Processor Local APIC = 0x%02x\n",
bsp_lapicid);

/* Enable Virtual Wire Mode. Should this be LOGICAL_DEST instead? */
low = INT_ENABLED | TRIGGER_EDGE | POLARITY_HIGH | PHYSICAL_DEST | ExtINT;
high = bsp_lapicid << (56 - 32);

write_vector(ioapic_base, 0, high, low);

if (io_apic_read(ioapic_base, 0x10) == 0xffffffff) {
printk(BIOS_WARNING, "IOAPIC not responding.\n");
Expand All @@ -59,13 +89,10 @@ void clear_ioapic(void *ioapic_base)

void set_ioapic_id(void *ioapic_base, u8 ioapic_id)
{
u32 bsp_lapicid = lapicid();
int i;

printk(BIOS_DEBUG, "IOAPIC: Initializing IOAPIC at %p\n",
ioapic_base);
printk(BIOS_DEBUG, "IOAPIC: Bootstrap Processor Local APIC = 0x%02x\n",
bsp_lapicid);

if (ioapic_id) {
printk(BIOS_DEBUG, "IOAPIC: ID = 0x%02x\n", ioapic_id);
Expand All @@ -82,55 +109,44 @@ void set_ioapic_id(void *ioapic_base, u8 ioapic_id)

}

static void load_vectors(void *ioapic_base)
u8 get_ioapic_id(void *ioapic_base)
{
u32 bsp_lapicid = lapicid();
u32 low, high;
u32 i, ioapic_interrupts;
return (io_apic_read(ioapic_base, 0x00) >> 24) & 0x0f;
}

ioapic_interrupts = ioapic_interrupt_count(ioapic_base);
u8 get_ioapic_version(void *ioapic_base)
{
return io_apic_read(ioapic_base, 0x01) & 0xff;
}

if (CONFIG(IOAPIC_INTERRUPTS_ON_FSB)) {
void ioapic_set_boot_config(void *ioapic_base, bool irq_on_fsb)
{
if (irq_on_fsb) {
/*
* For the Pentium 4 and above APICs deliver their interrupts
* on the front side bus, enable that.
*/
printk(BIOS_DEBUG, "IOAPIC: Enabling interrupts on FSB\n");
io_apic_write(ioapic_base, 0x03,
io_apic_read(ioapic_base, 0x03) | (1 << 0));
} else if (CONFIG(IOAPIC_INTERRUPTS_ON_APIC_SERIAL_BUS)) {
} else {
printk(BIOS_DEBUG,
"IOAPIC: Enabling interrupts on APIC serial bus\n");
io_apic_write(ioapic_base, 0x03, 0);
}
}

/* Enable Virtual Wire Mode. */
low = INT_ENABLED | TRIGGER_EDGE | POLARITY_HIGH | PHYSICAL_DEST | ExtINT;
high = bsp_lapicid << (56 - 32);

io_apic_write(ioapic_base, 0x10, low);
io_apic_write(ioapic_base, 0x11, high);

if (io_apic_read(ioapic_base, 0x10) == 0xffffffff) {
printk(BIOS_WARNING, "IOAPIC not responding.\n");
return;
}

printk(BIOS_SPEW, "IOAPIC: reg 0x%08x value 0x%08x 0x%08x\n",
0, high, low);
low = INT_DISABLED;
high = NONE;
for (i = 1; i < ioapic_interrupts; i++) {
io_apic_write(ioapic_base, i * 2 + 0x10, low);
io_apic_write(ioapic_base, i * 2 + 0x11, high);
void setup_ioapic_helper(void *ioapic_base, u8 ioapic_id, bool enable_virtual_wire)
{
set_ioapic_id(ioapic_base, ioapic_id);
clear_ioapic(ioapic_base);

printk(BIOS_SPEW, "IOAPIC: reg 0x%08x value 0x%08x 0x%08x\n",
i, high, low);
}
if (enable_virtual_wire)
route_i8259_irq0(ioapic_base);
}


void setup_ioapic(void *ioapic_base, u8 ioapic_id)
{
set_ioapic_id(ioapic_base, ioapic_id);
load_vectors(ioapic_base);
setup_ioapic_helper(ioapic_base, ioapic_id, true);
}
15 changes: 13 additions & 2 deletions src/arch/x86/mpspec.c
Expand Up @@ -3,16 +3,19 @@
#include <console/console.h>
#include <device/path.h>
#include <device/pci_ids.h>
#include <arch/ioapic.h>
#include <arch/smp/mpspec.h>
#include <string.h>
#include <arch/cpu.h>
#include <cpu/cpu.h>
#include <cpu/x86/lapic.h>
#include <drivers/generic/ioapic/chip.h>

/* Initialize the specified "mc" struct with initial values. */
void mptable_init(struct mp_config_table *mc, u32 lapic_addr)
void mptable_init(struct mp_config_table *mc)
{
int i;
u32 lapic_addr = cpu_get_lapic_addr();

memset(mc, 0, sizeof(*mc));

Expand Down Expand Up @@ -219,6 +222,14 @@ void smp_write_ioapic(struct mp_config_table *mc,
smp_add_mpc_entry(mc, sizeof(*mpc));
}

u8 smp_write_ioapic_from_hw(struct mp_config_table *mc, void *apicaddr)
{
u8 id = get_ioapic_id(apicaddr);
u8 ver = get_ioapic_version(apicaddr);
smp_write_ioapic(mc, id, ver, apicaddr);
return id;
}

/*
* Type 3: I/O Interrupt Table Entries:
* Entry Type, Int Type, Int Polarity, Int Level,
Expand Down Expand Up @@ -533,7 +544,7 @@ unsigned long __weak write_smp_table(unsigned long addr)
v = smp_write_floating_table(addr, 0);
mc = (void *)(((char *)v) + SMP_FLOATING_TABLE_LEN);

mptable_init(mc, LOCAL_APIC_ADDR);
mptable_init(mc);

smp_write_processors(mc);

Expand Down
23 changes: 0 additions & 23 deletions src/arch/x86/timestamp.inc

This file was deleted.

8 changes: 7 additions & 1 deletion src/arch/x86/walkcbfs.S
Expand Up @@ -13,6 +13,12 @@

#define CBFS_FILE_STRUCTSIZE (CBFS_FILE_OFFSET + 4)

#if FMAP_SECTION_COREBOOT_START < (0xffffffff - CONFIG_ROM_SIZE + 1)
#define COREBOOT_CBFS_START (0xffffffff - CONFIG_ROM_SIZE + 1 + FMAP_SECTION_COREBOOT_START)
#else
#define COREBOOT_CBFS_START FMAP_SECTION_COREBOOT_START
#endif

.code32
.section .init
.global walkcbfs_asm
Expand All @@ -26,7 +32,7 @@
walkcbfs_asm:
cld

movl $FMAP_SECTION_COREBOOT_START, %ebx
movl $COREBOOT_CBFS_START, %ebx

/* determine filename length */
mov $0, %eax
Expand Down
35 changes: 35 additions & 0 deletions src/commonlib/bsd/include/commonlib/bsd/helpers.h
Expand Up @@ -88,4 +88,39 @@
/* Calculate size of structure member. */
#define member_size(type, member) (sizeof(((type *)0)->member))

#define _retry_impl(attempts, condition, expr, ...) \
({ \
__typeof__(condition) _retry_ret = \
(__typeof__(condition))0; \
int _retry_attempts = (attempts); \
do { \
_retry_ret = (condition); \
if (_retry_ret) \
break; \
if (--_retry_attempts > 0) { \
expr; \
} else { \
break; \
} \
} while (1); \
_retry_ret; \
})

/*
* Helper macro to retry until a condition becomes true or the maximum number
* of attempts is reached. Two forms are supported:
*
* 1. retry(attempts, condition)
* 2. retry(attempts, condition, expr)
*
* @param attempts Maximum attempts.
* @param condition Condition to retry for.
* @param expr Procedure to run between each evaluation to "condition".
*
* @return Condition value if it evaluates to true within the maximum attempts;
* 0 otherwise.
*/
#define retry(attempts, condition, ...) \
_retry_impl(attempts, condition, __VA_ARGS__)

#endif /* COMMONLIB_BSD_HELPERS_H */
72 changes: 33 additions & 39 deletions src/commonlib/bsd/lz4_wrapper.c
Expand Up @@ -63,39 +63,32 @@ typedef uint64_t U64;

#define LZ4F_MAGICNUMBER 0x184D2204

/* Bit field endianness is implementation-defined. Use masks instead.
* https://stackoverflow.com/a/6044223 */
#define RESERVED0 0x03
#define HAS_CONTENT_CHECKSUM 0x04
#define HAS_CONTENT_SIZE 0x08
#define HAS_BLOCK_CHECKSUM 0x10
#define INDEPENDENT_BLOCKS 0x20
#define VERSION 0xC0
#define VERSION_SHIFT 6

#define RESERVED1_2 0x8F
#define MAX_BLOCK_SIZE 0x70

struct lz4_frame_header {
uint32_t magic;
union {
uint8_t flags;
struct {
uint8_t reserved0 : 2;
uint8_t has_content_checksum : 1;
uint8_t has_content_size : 1;
uint8_t has_block_checksum : 1;
uint8_t independent_blocks : 1;
uint8_t version : 2;
};
};
union {
uint8_t block_descriptor;
struct {
uint8_t reserved1 : 4;
uint8_t max_block_size : 3;
uint8_t reserved2 : 1;
};
};
uint8_t flags;
uint8_t block_descriptor;
/* + uint64_t content_size iff has_content_size is set */
/* + uint8_t header_checksum */
} __packed;

#define BH_SIZE 0x7FFFFFFF
#define NOT_COMPRESSED 0x80000000

struct lz4_block_header {
union {
uint32_t raw;
struct {
uint32_t size : 31;
uint32_t not_compressed : 1;
};
};
uint32_t raw;
/* + size bytes of data */
/* + uint32_t block_checksum iff has_block_checksum is set */
} __packed;
Expand All @@ -114,16 +107,17 @@ size_t ulz4fn(const void *src, size_t srcn, void *dst, size_t dstn)
return 0; /* input overrun */

/* We assume there's always only a single, standard frame. */
if (le32toh(h->magic) != LZ4F_MAGICNUMBER || h->version != 1)
if (le32toh(h->magic) != LZ4F_MAGICNUMBER
|| (h->flags & VERSION) != (1 << VERSION_SHIFT))
return 0; /* unknown format */
if (h->reserved0 || h->reserved1 || h->reserved2)
if ((h->flags & RESERVED0) || (h->block_descriptor & RESERVED1_2))
return 0; /* reserved must be zero */
if (!h->independent_blocks)
if (!(h->flags & INDEPENDENT_BLOCKS))
return 0; /* we don't support block dependency */
has_block_checksum = h->has_block_checksum;
has_block_checksum = h->flags & HAS_BLOCK_CHECKSUM;

in += sizeof(*h);
if (h->has_content_size)
if (h->flags & HAS_CONTENT_SIZE)
in += sizeof(uint64_t);
in += sizeof(uint8_t);
}
Expand All @@ -133,36 +127,36 @@ size_t ulz4fn(const void *src, size_t srcn, void *dst, size_t dstn)
break; /* input overrun */

struct lz4_block_header b = {
{ .raw = le32toh(*(const uint32_t *)in) }
.raw = le32toh(*(const uint32_t *)in)
};
in += sizeof(struct lz4_block_header);

if ((size_t)(in - src) + b.size > srcn)
if ((size_t)(in - src) + (b.raw & BH_SIZE) > srcn)
break; /* input overrun */

if (!b.size) {
if (!(b.raw & BH_SIZE)) {
out_size = out - dst;
break; /* decompression successful */
}

if (b.not_compressed) {
size_t size = MIN((uintptr_t)b.size, (uintptr_t)dst
if (b.raw & NOT_COMPRESSED) {
size_t size = MIN((uintptr_t)(b.raw & BH_SIZE), (uintptr_t)dst
+ dstn - (uintptr_t)out);
memcpy(out, in, size);
if (size < b.size)
if (size < (b.raw & BH_SIZE))
break; /* output overrun */
out += size;
} else {
/* constant folding essential, do not touch params! */
int ret = LZ4_decompress_generic(in, out, b.size,
int ret = LZ4_decompress_generic(in, out, (b.raw & BH_SIZE),
dst + dstn - out, endOnInputSize,
full, 0, noDict, out, NULL, 0);
if (ret < 0)
break; /* decompression error */
out += ret;
}

in += b.size;
in += (b.raw & BH_SIZE);
if (has_block_checksum)
in += sizeof(uint32_t);
}
Expand Down
4 changes: 4 additions & 0 deletions src/commonlib/include/commonlib/cbmem_id.h
Expand Up @@ -5,7 +5,9 @@

#define CBMEM_ID_ACPI 0x41435049
#define CBMEM_ID_ACPI_BERT 0x42455254
#define CBMEM_ID_ACPI_CNVS 0x434e5653
#define CBMEM_ID_ACPI_GNVS 0x474e5653
#define CMBMEM_ID_ACPI_HEST 0x48455354
#define CBMEM_ID_ACPI_UCSI 0x55435349
#define CBMEM_ID_AFTER_CAR 0xc4787a93
#define CBMEM_ID_AGESA_RUNTIME 0x41474553
Expand Down Expand Up @@ -81,7 +83,9 @@
#define CBMEM_ID_TO_NAME_TABLE \
{ CBMEM_ID_ACPI, "ACPI " }, \
{ CBMEM_ID_ACPI_BERT, "ACPI BERT " }, \
{ CBMEM_ID_ACPI_CNVS, "CHROMEOS NVS" }, \
{ CBMEM_ID_ACPI_GNVS, "ACPI GNVS " }, \
{ CMBMEM_ID_ACPI_HEST, "ACPI HEST " }, \
{ CBMEM_ID_ACPI_UCSI, "ACPI UCSI " }, \
{ CBMEM_ID_AGESA_RUNTIME, "AGESA RSVD " }, \
{ CBMEM_ID_AFTER_CAR, "AFTER CAR " }, \
Expand Down
1 change: 1 addition & 0 deletions src/commonlib/include/commonlib/coreboot_tables.h
Expand Up @@ -83,6 +83,7 @@ enum {
LB_TAG_SMMSTOREV2 = 0x0039,
LB_TAG_TPM_PPI_HANDOFF = 0x003a,
LB_TAG_BOARD_CONFIG = 0x0040,
LB_TAG_ACPI_CNVS = 0x0041,
/* The following options are CMOS-related */
LB_TAG_CMOS_OPTION_TABLE = 0x00c8,
LB_TAG_OPTION = 0x00c9,
Expand Down
20 changes: 17 additions & 3 deletions src/commonlib/include/commonlib/timestamp_serialized.h
Expand Up @@ -78,7 +78,7 @@ enum timestamp_id {
TS_END_COPYVPD_RO = 551,
TS_END_COPYVPD_RW = 552,

/* 900-920 reserved for vendorcode extensions (900-940: AMD AGESA) */
/* 900-940 reserved for vendorcode extensions (900-940: AMD) */
TS_AGESA_INIT_RESET_START = 900,
TS_AGESA_INIT_RESET_DONE = 901,
TS_AGESA_INIT_EARLY_START = 902,
Expand All @@ -99,6 +99,10 @@ enum timestamp_id {
TS_AGESA_S3_LATE_DONE = 917,
TS_AGESA_S3_FINAL_START = 918,
TS_AGESA_S3_FINAL_DONE = 919,
TS_AMD_APOB_READ_START = 920,
TS_AMD_APOB_ERASE_START = 921,
TS_AMD_APOB_WRITE_START = 922,
TS_AMD_APOB_DONE = 923,

/* 940-950 reserved for vendorcode extensions (940-950: Intel ME) */
TS_ME_INFORM_DRAM_WAIT = 940,
Expand All @@ -119,6 +123,8 @@ enum timestamp_id {
TS_FSP_AFTER_END_OF_FIRMWARE = 961,
TS_FSP_MULTI_PHASE_SI_INIT_START = 962,
TS_FSP_MULTI_PHASE_SI_INIT_END = 963,
TS_FSP_MEMORY_INIT_LOAD = 970,
TS_FSP_SILICON_INIT_LOAD = 971,

/* 1000+ reserved for payloads (1000-1200: ChromeOS depthcharge) */

Expand Down Expand Up @@ -176,7 +182,7 @@ static const struct timestamp_id_to_name {
{ TS_CBMEM_POST, "cbmem post" },
{ TS_WRITE_TABLES, "write tables" },
{ TS_FINALIZE_CHIPS, "finalize chips" },
{ TS_LOAD_PAYLOAD, "load payload" },
{ TS_LOAD_PAYLOAD, "starting to load payload" },
{ TS_ACPI_WAKE_JUMP, "ACPI wake jump" },
{ TS_SELFBOOT_JUMP, "selfboot jump" },
{ TS_DELAY_START, "Forced delay start" },
Expand Down Expand Up @@ -220,7 +226,7 @@ static const struct timestamp_id_to_name {
{ TS_KERNEL_DECOMPRESSION, "starting kernel decompression/relocation" },
{ TS_START_KERNEL, "jumping to kernel" },

/* AMD AGESA related timestamps */
/* AMD related timestamps */
{ TS_AGESA_INIT_RESET_START, "calling AmdInitReset" },
{ TS_AGESA_INIT_RESET_DONE, "back from AmdInitReset" },
{ TS_AGESA_INIT_EARLY_START, "calling AmdInitEarly" },
Expand All @@ -241,6 +247,10 @@ static const struct timestamp_id_to_name {
{ TS_AGESA_S3_LATE_DONE, "back from AmdS3LateRestore" },
{ TS_AGESA_S3_FINAL_START, "calling AmdS3FinalRestore" },
{ TS_AGESA_S3_FINAL_DONE, "back from AmdS3FinalRestore" },
{ TS_AMD_APOB_READ_START, "starting APOB read" },
{ TS_AMD_APOB_ERASE_START, "starting APOB erase" },
{ TS_AMD_APOB_WRITE_START, "starting APOB write" },
{ TS_AMD_APOB_DONE, "finished APOB" },

/* Intel ME related timestamps */
{ TS_ME_INFORM_DRAM_WAIT, "waiting for ME acknowledgement of raminit"},
Expand All @@ -261,6 +271,10 @@ static const struct timestamp_id_to_name {
{ TS_FSP_BEFORE_END_OF_FIRMWARE, "calling FspNotify(EndOfFirmware)" },
{ TS_FSP_AFTER_END_OF_FIRMWARE,
"returning from FspNotify(EndOfFirmware)" },

{ TS_FSP_MEMORY_INIT_LOAD, "loading FSP-M" },
{ TS_FSP_SILICON_INIT_LOAD, "loading FSP-S" },

{ TS_START_POSTCAR, "start of postcar" },
{ TS_END_POSTCAR, "end of postcar" },
};
Expand Down
10 changes: 6 additions & 4 deletions src/console/Kconfig
Expand Up @@ -464,10 +464,12 @@ config NO_EARLY_BOOTBLOCK_POSTCODES
def_bool n
help
Some chipsets require that the routing for the port 80h POST
code be configured before any POST codes are sent out.
This can be done in the boot block, but there are a couple of
POST codes that go out before the chipset's bootblock initialization
can happen. This option suppresses those POST codes.
code be configured before any POST codes are sent out. If this is
not done, the system can hang on the first POST code. This
initialization can be done in the boot block, but there are a couple
of POST codes that go out before the chipset's C bootblock
initialization can happen. This option suppresses all postcodes in
the early assembly code.

config HWBASE_DEBUG_CB
bool
Expand Down
9 changes: 2 additions & 7 deletions src/cpu/intel/car/romstage.c
Expand Up @@ -16,7 +16,7 @@

static struct postcar_frame early_mtrrs;

static void romstage_main(unsigned long bist)
static void romstage_main(void)
{
int i;
const int num_guards = 64;
Expand Down Expand Up @@ -58,17 +58,12 @@ static void romstage_main(unsigned long bist)
/* We do not return here. */
}

/* We don't carry BIST from bootblock in a good location to read from.
* Any error should have been reported in bootblock already.
*/
#define NO_BIST 0

asmlinkage void car_stage_entry(void)
{
timestamp_add_now(TS_START_ROMSTAGE);

/* Assumes the hardware was set up during the bootblock */
console_init();

romstage_main(NO_BIST);
romstage_main();
}
2 changes: 1 addition & 1 deletion src/cpu/intel/haswell/Kconfig
Expand Up @@ -16,10 +16,10 @@ config CPU_SPECIFIC_OPTIONS
#select AP_IN_SIPI_WAIT
select TSC_SYNC_MFENCE
select CPU_INTEL_FIRMWARE_INTERFACE_TABLE
select PARALLEL_MP
select CPU_INTEL_COMMON
select CPU_INTEL_COMMON_TIMEBASE
select HAVE_ASAN_IN_ROMSTAGE
select HAVE_DISPLAY_MTRRS
select CPU_INTEL_COMMON_VOLTAGE

config SMM_TSEG_SIZE
Expand Down
10 changes: 2 additions & 8 deletions src/cpu/intel/haswell/acpi.c
Expand Up @@ -333,7 +333,7 @@ static void generate_P_state_entries(int core, int cores_per_package)

void generate_cpu_entries(const struct device *device)
{
int coreID, cpuID, pcontrol_blk = get_pmbase(), plen = 6;
int coreID, cpuID;
int totalcores = dev_count_cpu();
int cores_per_package = get_logical_cores_per_package();
int numcpus = totalcores/cores_per_package;
Expand All @@ -343,15 +343,9 @@ void generate_cpu_entries(const struct device *device)

for (cpuID = 1; cpuID <= numcpus; cpuID++) {
for (coreID = 1; coreID <= cores_per_package; coreID++) {
if (coreID > 1) {
pcontrol_blk = 0;
plen = 0;
}

/* Generate processor \_SB.CPUx */
acpigen_write_processor(
(cpuID - 1) * cores_per_package+coreID - 1,
pcontrol_blk, plen);
(cpuID - 1) * cores_per_package+coreID - 1, 0, 0);

/* Generate P-state tables */
generate_P_state_entries(
Expand Down
6 changes: 6 additions & 0 deletions src/cpu/intel/haswell/haswell_init.c
Expand Up @@ -524,6 +524,12 @@ static void configure_mca(void)

msr = rdmsr(IA32_MCG_CAP);
num_banks = msr.lo & 0xff;

/* Enable all error reporting */
msr.lo = msr.hi = ~0;
for (i = 0; i < num_banks; i++)
wrmsr(IA32_MC0_CTL + (i * 4), msr);

msr.lo = msr.hi = 0;
/* TODO(adurbin): This should only be done on a cold boot. Also, some
* of these banks are core vs package scope. For now every CPU clears
Expand Down
4 changes: 1 addition & 3 deletions src/cpu/intel/hyperthreading/intel_sibling.c
Expand Up @@ -6,9 +6,7 @@
#include <option.h>
#include <smp/spinlock.h>

#if CONFIG(PARALLEL_CPU_INIT)
#error Intel hyper-threading requires serialized CPU init
#endif
/* Intel hyper-threading requires serialized CPU init. */

static int first_time = 1;
static int disable_siblings = !CONFIG(LOGICAL_CPUS);
Expand Down
2 changes: 0 additions & 2 deletions src/cpu/intel/model_2065x/Kconfig
Expand Up @@ -11,12 +11,10 @@ config CPU_SPECIFIC_OPTIONS
select UDELAY_TSC
select TSC_MONOTONIC_TIMER
select SUPPORT_CPU_UCODE_IN_CBFS
select PARALLEL_CPU_INIT
#select AP_IN_SIPI_WAIT
select TSC_SYNC_MFENCE
select CPU_INTEL_COMMON
select CPU_INTEL_COMMON_TIMEBASE
select PARALLEL_MP

config SMM_TSEG_SIZE
hex
Expand Down
10 changes: 2 additions & 8 deletions src/cpu/intel/model_2065x/acpi.c
Expand Up @@ -205,7 +205,7 @@ static void generate_P_state_entries(int core, int cores_per_package)

void generate_cpu_entries(const struct device *device)
{
int coreID, cpuID, pcontrol_blk = PMB0_BASE, plen = 6;
int coreID, cpuID;
int totalcores = dev_count_cpu();
int cores_per_package = get_cores_per_package();
int numcpus = totalcores/cores_per_package;
Expand All @@ -215,15 +215,9 @@ void generate_cpu_entries(const struct device *device)

for (cpuID = 1; cpuID <= numcpus; cpuID++) {
for (coreID = 1; coreID <= cores_per_package; coreID++) {
if (coreID > 1) {
pcontrol_blk = 0;
plen = 0;
}

/* Generate processor \_SB.CPUx */
acpigen_write_processor(
(cpuID-1)*cores_per_package+coreID-1,
pcontrol_blk, plen);
(cpuID-1)*cores_per_package+coreID-1, 0, 0);

/* Generate P-state tables */
generate_P_state_entries(
Expand Down
9 changes: 7 additions & 2 deletions src/cpu/intel/model_206ax/Kconfig
Expand Up @@ -3,9 +3,15 @@ config CPU_INTEL_MODEL_206AX

if CPU_INTEL_MODEL_206AX

config ARCH_EXP_X86_64
bool "Experimental 64bit support"
depends on USE_NATIVE_RAMINIT
default n

config CPU_SPECIFIC_OPTIONS
def_bool y
select ARCH_ALL_STAGES_X86_32
select ARCH_ALL_STAGES_X86_32 if !ARCH_EXP_X86_64
select ARCH_ALL_STAGES_X86_64 if ARCH_EXP_X86_64
select BOOT_DEVICE_SPI_FLASH_NO_EARLY_WRITES
select MMX
select SSE2
Expand All @@ -16,7 +22,6 @@ config CPU_SPECIFIC_OPTIONS
select TSC_SYNC_MFENCE
select CPU_INTEL_COMMON
select CPU_INTEL_COMMON_TIMEBASE
select PARALLEL_MP

config SMM_TSEG_SIZE
hex
Expand Down
10 changes: 2 additions & 8 deletions src/cpu/intel/model_206ax/acpi.c
Expand Up @@ -306,7 +306,7 @@ static void generate_P_state_entries(int core, int cores_per_package)

void generate_cpu_entries(const struct device *device)
{
int coreID, cpuID, pcontrol_blk = PMB0_BASE, plen = 6;
int coreID, cpuID;
int totalcores = dev_count_cpu();
int cores_per_package = get_logical_cores_per_package();
int numcpus = totalcores/cores_per_package;
Expand All @@ -316,15 +316,9 @@ void generate_cpu_entries(const struct device *device)

for (cpuID = 1; cpuID <= numcpus; cpuID++) {
for (coreID = 1; coreID <= cores_per_package; coreID++) {
if (coreID > 1) {
pcontrol_blk = 0;
plen = 0;
}

/* Generate processor \_SB.CPUx */
acpigen_write_processor(
(cpuID-1)*cores_per_package+coreID-1,
pcontrol_blk, plen);
(cpuID-1)*cores_per_package+coreID-1, 0, 0);

/* Generate P-state tables */
generate_P_state_entries(
Expand Down
6 changes: 0 additions & 6 deletions src/cpu/intel/model_206ax/model_206ax_init.c
Expand Up @@ -172,12 +172,6 @@ static void configure_c_states(void)
msr.lo |= (1 << 15); // Lock C-State MSR
wrmsr(MSR_PKG_CST_CONFIG_CONTROL, msr);

msr = rdmsr(MSR_PMG_IO_CAPTURE_ADDR);
msr.lo &= ~0x7ffff;
msr.lo |= (PMB0_BASE + 4); // LVL_2 base address
msr.lo |= (2 << 16); // CST Range: C7 is max C-state
wrmsr(MSR_PMG_IO_CAPTURE_ADDR, msr);

msr = rdmsr(MSR_MISC_PWR_MGMT);
msr.lo &= ~(1 << 0); // Enable P-state HW_ALL coordination
wrmsr(MSR_MISC_PWR_MGMT, msr);
Expand Down
1 change: 1 addition & 0 deletions src/cpu/intel/model_f2x/Makefile.inc
@@ -1,4 +1,5 @@
subdirs-y += ../common
subdirs-y += ../hyperthreading

ramstage-y += model_f2x_init.c

Expand Down
3 changes: 3 additions & 0 deletions src/cpu/intel/model_f3x/Makefile.inc
@@ -1,5 +1,8 @@
ramstage-y += model_f3x_init.c

subdirs-y += ../hyperthreading
subdirs-y += ../smm/gen1

ramstage-$(CONFIG_PARALLEL_MP) += ../model_1067x/mp_init.c

cpu_microcode_bins += $(wildcard 3rdparty/intel-microcode/intel-ucode/0f-03-*)
1 change: 0 additions & 1 deletion src/cpu/intel/socket_441/Makefile.inc
Expand Up @@ -4,7 +4,6 @@ subdirs-y += ../../x86/mtrr
subdirs-y += ../../x86/lapic
subdirs-y += ../../x86/cache
subdirs-y += ../microcode
subdirs-y += ../hyperthreading
subdirs-y += ../speedstep

bootblock-y += ../car/p4-netburst/cache_as_ram.S
Expand Down
1 change: 0 additions & 1 deletion src/cpu/intel/socket_BGA956/Makefile.inc
Expand Up @@ -4,7 +4,6 @@ subdirs-y += ../../x86/mtrr
subdirs-y += ../../x86/lapic
subdirs-y += ../../x86/cache
subdirs-y += ../microcode
subdirs-y += ../hyperthreading
subdirs-y += ../speedstep

bootblock-y += ../car/core2/cache_as_ram.S
Expand Down
1 change: 0 additions & 1 deletion src/cpu/intel/socket_FCBGA559/Makefile.inc
Expand Up @@ -4,7 +4,6 @@ subdirs-y += ../../x86/mtrr
subdirs-y += ../../x86/lapic
subdirs-y += ../../x86/cache
subdirs-y += ../microcode
subdirs-y += ../hyperthreading
subdirs-y += ../speedstep

bootblock-y += ../car/bootblock.c
Expand Down
1 change: 0 additions & 1 deletion src/cpu/intel/socket_LGA775/Makefile.inc
Expand Up @@ -9,7 +9,6 @@ subdirs-y += ../../x86/mtrr
subdirs-y += ../../x86/lapic
subdirs-y += ../../x86/cache
subdirs-y += ../microcode
subdirs-y += ../hyperthreading
subdirs-y += ../speedstep

bootblock-y += ../car/p4-netburst/cache_as_ram.S
Expand Down
1 change: 0 additions & 1 deletion src/cpu/intel/socket_m/Makefile.inc
Expand Up @@ -5,7 +5,6 @@ subdirs-y += ../../x86/mtrr
subdirs-y += ../../x86/lapic
subdirs-y += ../../x86/cache
subdirs-y += ../microcode
subdirs-y += ../hyperthreading
subdirs-y += ../speedstep

bootblock-y += ../car/core2/cache_as_ram.S
Expand Down
1 change: 0 additions & 1 deletion src/cpu/intel/socket_mPGA604/Makefile.inc
Expand Up @@ -4,7 +4,6 @@ subdirs-y += ../../x86/mtrr
subdirs-y += ../../x86/lapic
subdirs-y += ../../x86/cache
subdirs-y += ../microcode
subdirs-y += ../hyperthreading

bootblock-y += ../car/p4-netburst/cache_as_ram.S
bootblock-y += ../car/bootblock.c
Expand Down
1 change: 0 additions & 1 deletion src/cpu/intel/socket_p/Makefile.inc
Expand Up @@ -5,7 +5,6 @@ subdirs-y += ../../x86/mtrr
subdirs-y += ../../x86/lapic
subdirs-y += ../../x86/cache
subdirs-y += ../microcode
subdirs-y += ../hyperthreading
subdirs-y += ../speedstep

bootblock-y += ../car/core2/cache_as_ram.S
Expand Down
8 changes: 3 additions & 5 deletions src/cpu/qemu-x86/Kconfig
Expand Up @@ -15,10 +15,10 @@ choice

config CPU_QEMU_X86_LAPIC_INIT
bool "Legacy serial LAPIC init"
select LEGACY_SMP_INIT

config CPU_QEMU_X86_PARALLEL_MP
bool "Parallel MP init"
select PARALLEL_MP

endchoice

Expand All @@ -33,13 +33,13 @@ config CPU_QEMU_X86_NO_SMM

config CPU_QEMU_X86_ASEG_SMM
bool "SMM in ASEG"
depends on !PARALLEL_MP
depends on CPU_QEMU_X86_LAPIC_INIT
select SMM_ASEG

config CPU_QEMU_X86_TSEG_SMM
bool "SMM in TSEG"
select SMM_TSEG
depends on PARALLEL_MP
depends on CPU_QEMU_X86_PARALLEL_MP

endchoice

Expand All @@ -51,12 +51,10 @@ config MAX_CPUS
config CPU_QEMU_X86_64
bool "Experimental 64bit support"
select ARCH_ALL_STAGES_X86_64
select ARCH_POSTCAR_X86_64

config CPU_QEMU_X86_32
bool
default n if CPU_QEMU_X86_64
default y
select ARCH_ALL_STAGES_X86_32
select ARCH_POSTCAR_X86_32
endif
33 changes: 27 additions & 6 deletions src/cpu/x86/Kconfig
@@ -1,10 +1,7 @@
# TODO These two options look too similar
config PARALLEL_CPU_INIT
bool
default n

config PARALLEL_MP
def_bool n
def_bool y
depends on !LEGACY_SMP_INIT
depends on SMP
help
This option uses common MP infrastructure for bringing up APs
in parallel. It additionally provides a more flexible mechanism
Expand All @@ -17,6 +14,29 @@ config PARALLEL_MP_AP_WORK
Allow APs to do other work after initialization instead of going
to sleep.

config LEGACY_SMP_INIT
bool

choice LAPIC_ACCESS_MODE
prompt "APIC operation mode"
default XAPIC_ONLY

config XAPIC_ONLY
prompt "Set XAPIC mode"
bool

config X2APIC_ONLY
prompt "Set X2APIC mode"
bool
depends on PARALLEL_MP

config X2APIC_RUNTIME
prompt "Support both XAPIC and X2APIC"
bool
depends on PARALLEL_MP

endchoice

config UDELAY_LAPIC
bool
default n
Expand Down Expand Up @@ -107,6 +127,7 @@ config SMM_MODULE_HEAP_SIZE

config SMM_MODULE_STACK_SIZE
hex
default 0x800 if ARCH_RAMSTAGE_X86_64
default 0x400
help
This option determines the size of the stack within the SMM handler
Expand Down
16 changes: 14 additions & 2 deletions src/cpu/x86/entry16.S
Expand Up @@ -43,9 +43,7 @@ _start16bit:
cli
/* Save the BIST result */
movl %eax, %ebp
#if !CONFIG(NO_EARLY_BOOTBLOCK_POSTCODES)
post_code(POST_RESET_VECTOR_CORRECT)
#endif

/* IMMEDIATELY invalidate the translation lookaside buffer (TLB) before
* executing any further code. Even though paging is disabled we
Expand Down Expand Up @@ -115,10 +113,24 @@ _start16bit:
subw %ax, %bx
lgdtl %cs:(%bx)

#if CONFIG(INTEL_CBNT_SUPPORT)
#include <cpu/intel/msr.h>
movl $MSR_BOOT_GUARD_SACM_INFO, %ecx
rdmsr
andl $B_BOOT_GUARD_SACM_INFO_NEM_ENABLED, %eax
jz 1f
movl %cr0, %eax
andl $0x7FFAFFD1, %eax /* PG,AM,WP,NE,TS,EM,MP = 0 */
orl $0x01, %eax /* PE = 1 */
movl %eax, %cr0
jmp 2f
#endif
1:
movl %cr0, %eax
andl $0x7FFAFFD1, %eax /* PG,AM,WP,NE,TS,EM,MP = 0 */
orl $0x60000001, %eax /* CD, NW, PE = 1 */
movl %eax, %cr0
2:

/* Restore BIST to %eax */
movl %ebp, %eax
Expand Down
2 changes: 0 additions & 2 deletions src/cpu/x86/entry32.S
Expand Up @@ -31,9 +31,7 @@ bootblock_protected_mode_entry:
/* Save the BIST value */
movl %eax, %ebp

#if !CONFIG(NO_EARLY_BOOTBLOCK_POSTCODES)
post_code(POST_ENTER_PROTECTED_MODE)
#endif

movw $ROM_DATA_SEG, %ax
movw %ax, %ds
Expand Down
13 changes: 10 additions & 3 deletions src/cpu/x86/lapic/Makefile.inc
@@ -1,6 +1,7 @@
ramstage-y += lapic.c
ramstage-y += lapic_cpu_init.c
ramstage-$(CONFIG_SMP) += secondary.S
ramstage-$(CONFIG_AP_IN_SIPI_WAIT) += lapic_cpu_stop.c
ramstage-$(CONFIG_LEGACY_SMP_INIT) += lapic_cpu_init.c
ramstage-$(CONFIG_LEGACY_SMP_INIT) += secondary.S

bootblock-$(CONFIG_UDELAY_LAPIC) += apic_timer.c
romstage-$(CONFIG_UDELAY_LAPIC) += apic_timer.c
ramstage-$(CONFIG_UDELAY_LAPIC) += apic_timer.c
Expand All @@ -10,3 +11,9 @@ verstage_x86-y += boot_cpu.c
romstage-y += boot_cpu.c
ramstage-y += boot_cpu.c
postcar-y += boot_cpu.c

bootblock-y += lapic.c
verstage_x86-y += lapic.c
romstage-y += lapic.c
ramstage-y += lapic.c
postcar-y += lapic.c
88 changes: 61 additions & 27 deletions src/cpu/x86/lapic/lapic.c
@@ -1,16 +1,51 @@
/* SPDX-License-Identifier: GPL-2.0-only */

#include <cpu/cpu.h>
#include <cpu/x86/lapic.h>
#include <cpu/x86/lapic_def.h>
#include <cpu/x86/msr.h>
#include <console/console.h>
#include <smp/node.h>
#include <stdint.h>

void lapic_virtual_wire_mode_init(void)
void enable_lapic(void)
{
const uint32_t lvt0_mask = LAPIC_LVT_MASKED | LAPIC_LVT_LEVEL_TRIGGER |
LAPIC_LVT_REMOTE_IRR | LAPIC_INPUT_POLARITY |
LAPIC_SEND_PENDING | LAPIC_LVT_RESERVED_1 |
LAPIC_DELIVERY_MODE_MASK;
uint32_t lvt0_val = LAPIC_LVT_REMOTE_IRR | LAPIC_SEND_PENDING;
msr_t msr;
msr = rdmsr(LAPIC_BASE_MSR);
msr.hi &= 0xffffff00;
msr.lo &= ~LAPIC_BASE_MSR_ADDR_MASK;
msr.lo |= LAPIC_DEFAULT_BASE;
msr.lo |= LAPIC_BASE_MSR_ENABLE;
wrmsr(LAPIC_BASE_MSR, msr);
}

void disable_lapic(void)
{
msr_t msr;
msr = rdmsr(LAPIC_BASE_MSR);
msr.lo &= ~LAPIC_BASE_MSR_ENABLE;
wrmsr(LAPIC_BASE_MSR, msr);
}

uintptr_t cpu_get_lapic_addr(void)
{
return LAPIC_DEFAULT_BASE;
}

/* See if I need to initialize the local APIC */
static int need_lapic_init(void)
{
return CONFIG(SMP) || CONFIG(IOAPIC);
}

static void lapic_virtual_wire_mode_init(void)
{
/* this is so interrupts work. This is very limited scope --
* linux will do better later, we hope ...
*/
/* this is the first way we learned to do it. It fails on real SMP
* stuff. So we have to do things differently ...
* see the Intel mp1.4 spec, page A-3
*/

printk(BIOS_INFO, "Setting up local APIC...\n");

Expand All @@ -20,30 +55,29 @@ void lapic_virtual_wire_mode_init(void)
/*
* Set Task Priority to 'accept all'.
*/
lapic_write_around(LAPIC_TASKPRI,
lapic_read_around(LAPIC_TASKPRI) & ~LAPIC_TPRI_MASK);
lapic_update32(LAPIC_TASKPRI, ~LAPIC_TPRI_MASK, 0);

/* Put the local APIC in virtual wire mode */
lapic_write_around(LAPIC_SPIV,
(lapic_read_around(LAPIC_SPIV) & ~(LAPIC_VECTOR_MASK))
| LAPIC_SPIV_ENABLE);
lapic_update32(LAPIC_SPIV, ~LAPIC_VECTOR_MASK, LAPIC_SPIV_ENABLE);

if (boot_cpu())
lvt0_val |= LAPIC_DELIVERY_MODE_EXTINT;
else
lvt0_val |= LAPIC_DELIVERY_MODE_FIXED | LAPIC_LVT_MASKED;
lapic_write_around(LAPIC_LVT0, (lapic_read_around(LAPIC_LVT0) & ~lvt0_mask) | lvt0_val);

lapic_write_around(LAPIC_LVT1,
(lapic_read_around(LAPIC_LVT1) &
~(LAPIC_LVT_MASKED | LAPIC_LVT_LEVEL_TRIGGER |
LAPIC_LVT_REMOTE_IRR | LAPIC_INPUT_POLARITY |
LAPIC_SEND_PENDING | LAPIC_LVT_RESERVED_1 |
LAPIC_DELIVERY_MODE_MASK))
| (LAPIC_LVT_REMOTE_IRR | LAPIC_SEND_PENDING |
LAPIC_DELIVERY_MODE_NMI)
);
uint32_t mask = LAPIC_LVT_MASKED | LAPIC_LVT_LEVEL_TRIGGER | LAPIC_LVT_REMOTE_IRR |
LAPIC_INPUT_POLARITY | LAPIC_SEND_PENDING | LAPIC_LVT_RESERVED_1 |
LAPIC_DELIVERY_MODE_MASK;

lapic_update32(LAPIC_LVT0, ~mask, LAPIC_LVT_REMOTE_IRR | LAPIC_SEND_PENDING |
LAPIC_DELIVERY_MODE_EXTINT);

lapic_update32(LAPIC_LVT1, ~mask, LAPIC_LVT_REMOTE_IRR | LAPIC_SEND_PENDING |
LAPIC_DELIVERY_MODE_NMI);

printk(BIOS_DEBUG, " apic_id: 0x%x ", lapicid());
printk(BIOS_INFO, "done.\n");
}

void setup_lapic(void)
{
if (need_lapic_init())
lapic_virtual_wire_mode_init();
else
disable_lapic();
}
194 changes: 38 additions & 156 deletions src/cpu/x86/lapic/lapic_cpu_init.c
Expand Up @@ -6,7 +6,6 @@
#include <cpu/x86/smi_deprecated.h>
#include <acpi/acpi.h>
#include <delay.h>
#include <halt.h>
#include <lib.h>
#include <string.h>
#include <symbols.h>
Expand Down Expand Up @@ -88,9 +87,25 @@ static void recover_lowest_1M(void)
memcpy(lowmem_backup_ptr, lowmem_backup, lowmem_backup_size);
}

static uint32_t wait_for_ipi_completion(const int timeout_ms)
{
int loops = timeout_ms * 10;
uint32_t send_status;

/* wait for the ipi send to finish */
printk(BIOS_SPEW, "Waiting for send to finish...\n");
do {
printk(BIOS_SPEW, "+");
udelay(100);
send_status = lapic_busy();
} while (send_status && (--loops > 0));

return send_status;
}

static int lapic_start_cpu(unsigned long apicid)
{
int timeout;
const int timeout_100ms = 100;
uint32_t send_status, accept_status;
int j, maxlvt;

Expand All @@ -103,30 +118,17 @@ static int lapic_start_cpu(unsigned long apicid)
/*
* Turn INIT on target chip
*/
lapic_write_around(LAPIC_ICR2, SET_LAPIC_DEST_FIELD(apicid));

/*
* Send IPI
*/

lapic_write_around(LAPIC_ICR, LAPIC_INT_LEVELTRIG | LAPIC_INT_ASSERT
| LAPIC_DM_INIT);
lapic_send_ipi(LAPIC_INT_LEVELTRIG | LAPIC_INT_ASSERT | LAPIC_DM_INIT, apicid);

printk(BIOS_SPEW, "Waiting for send to finish...\n");
timeout = 0;
do {
printk(BIOS_SPEW, "+");
udelay(100);
send_status = lapic_read(LAPIC_ICR) & LAPIC_ICR_BUSY;
} while (send_status && (timeout++ < 1000));
if (timeout >= 1000) {
send_status = wait_for_ipi_completion(timeout_100ms);
if (send_status) {
printk(BIOS_ERR, "CPU %ld: First APIC write timed out. "
"Disabling\n", apicid);
// too bad.
printk(BIOS_ERR, "ESR is 0x%x\n", lapic_read(LAPIC_ESR));
if (lapic_read(LAPIC_ESR)) {
printk(BIOS_ERR, "Try to reset ESR\n");
lapic_write_around(LAPIC_ESR, 0);
xapic_write_atomic(LAPIC_ESR, 0);
printk(BIOS_ERR, "ESR is 0x%x\n",
lapic_read(LAPIC_ESR));
}
Expand All @@ -136,20 +138,10 @@ static int lapic_start_cpu(unsigned long apicid)

printk(BIOS_SPEW, "Deasserting INIT.\n");

/* Target chip */
lapic_write_around(LAPIC_ICR2, SET_LAPIC_DEST_FIELD(apicid));
lapic_send_ipi(LAPIC_INT_LEVELTRIG | LAPIC_DM_INIT, apicid);

/* Send IPI */
lapic_write_around(LAPIC_ICR, LAPIC_INT_LEVELTRIG | LAPIC_DM_INIT);

printk(BIOS_SPEW, "Waiting for send to finish...\n");
timeout = 0;
do {
printk(BIOS_SPEW, "+");
udelay(100);
send_status = lapic_read(LAPIC_ICR) & LAPIC_ICR_BUSY;
} while (send_status && (timeout++ < 1000));
if (timeout >= 1000) {
send_status = wait_for_ipi_completion(timeout_100ms);
if (send_status) {
printk(BIOS_ERR, "CPU %ld: Second APIC write timed out. "
"Disabling\n", apicid);
// too bad.
Expand All @@ -165,7 +157,7 @@ static int lapic_start_cpu(unsigned long apicid)

for (j = 1; j <= CONFIG_NUM_IPI_STARTS; j++) {
printk(BIOS_SPEW, "Sending STARTUP #%d to %lu.\n", j, apicid);
lapic_read_around(LAPIC_SPIV);
lapic_read(LAPIC_SPIV);
lapic_write(LAPIC_ESR, 0);
lapic_read(LAPIC_ESR);
printk(BIOS_SPEW, "After apic_write.\n");
Expand All @@ -174,13 +166,7 @@ static int lapic_start_cpu(unsigned long apicid)
* STARTUP IPI
*/

/* Target chip */
lapic_write_around(LAPIC_ICR2, SET_LAPIC_DEST_FIELD(apicid));

/* Boot on the stack */
/* Kick the second */
lapic_write_around(LAPIC_ICR, LAPIC_DM_STARTUP
| (AP_SIPI_VECTOR >> 12));
lapic_send_ipi(LAPIC_DM_STARTUP | (AP_SIPI_VECTOR >> 12), apicid);

/*
* Give the other CPU some time to accept the IPI.
Expand All @@ -189,13 +175,7 @@ static int lapic_start_cpu(unsigned long apicid)

printk(BIOS_SPEW, "Startup point 1.\n");

printk(BIOS_SPEW, "Waiting for send to finish...\n");
timeout = 0;
do {
printk(BIOS_SPEW, "+");
udelay(100);
send_status = lapic_read(LAPIC_ICR) & LAPIC_ICR_BUSY;
} while (send_status && (timeout++ < 1000));
send_status = wait_for_ipi_completion(timeout_100ms);

/*
* Give the other CPU some time to accept the IPI.
Expand All @@ -205,7 +185,7 @@ static int lapic_start_cpu(unsigned long apicid)
* Due to the Pentium erratum 3AP.
*/
if (maxlvt > 3) {
lapic_read_around(LAPIC_SPIV);
lapic_read(LAPIC_SPIV);
lapic_write(LAPIC_ESR, 0);
}
accept_status = (lapic_read(LAPIC_ESR) & 0xEF);
Expand Down Expand Up @@ -241,7 +221,7 @@ static void *stacks[CONFIG_MAX_CPUS];
volatile unsigned long secondary_stack;
volatile unsigned int secondary_cpu_index;

int start_cpu(struct device *cpu)
static int start_cpu(struct device *cpu)
{
struct cpu_info *info;
uintptr_t stack_top;
Expand Down Expand Up @@ -302,96 +282,12 @@ int start_cpu(struct device *cpu)
return result;
}

#if CONFIG(AP_IN_SIPI_WAIT)

/**
* Sending INIT IPI to self is equivalent of asserting #INIT with a bit of
* delay.
* An undefined number of instruction cycles will complete. All global locks
* must be released before INIT IPI and no printk is allowed after this.
* De-asserting INIT IPI is a no-op on later Intel CPUs.
*
* If you set DEBUG_HALT_SELF to 1, printk's after INIT IPI are enabled
* but running thread may halt without releasing the lock and effectively
* deadlock other CPUs.
*/
#define DEBUG_HALT_SELF 0

/**
* Normally this function is defined in lapic.h as an always inline function
* that just keeps the CPU in a hlt() loop. This does not work on all CPUs.
* I think all hyperthreading CPUs might need this version, but I could only
* verify this on the Intel Core Duo
*/
void stop_this_cpu(void)
{
int timeout;
unsigned long send_status;
unsigned long id;

id = lapicid();

printk(BIOS_DEBUG, "CPU %ld going down...\n", id);

/* send an LAPIC INIT to myself */
lapic_write_around(LAPIC_ICR2, SET_LAPIC_DEST_FIELD(id));
lapic_write_around(LAPIC_ICR, LAPIC_INT_LEVELTRIG |
LAPIC_INT_ASSERT | LAPIC_DM_INIT);

/* wait for the ipi send to finish */
#if DEBUG_HALT_SELF
printk(BIOS_SPEW, "Waiting for send to finish...\n");
#endif
timeout = 0;
do {
#if DEBUG_HALT_SELF
printk(BIOS_SPEW, "+");
#endif
udelay(100);
send_status = lapic_read(LAPIC_ICR) & LAPIC_ICR_BUSY;
} while (send_status && (timeout++ < 1000));
if (timeout >= 1000) {
#if DEBUG_HALT_SELF
printk(BIOS_ERR, "timed out\n");
#endif
}
mdelay(10);

#if DEBUG_HALT_SELF
printk(BIOS_SPEW, "Deasserting INIT.\n");
#endif
/* Deassert the LAPIC INIT */
lapic_write_around(LAPIC_ICR2, SET_LAPIC_DEST_FIELD(id));
lapic_write_around(LAPIC_ICR, LAPIC_INT_LEVELTRIG | LAPIC_DM_INIT);

#if DEBUG_HALT_SELF
printk(BIOS_SPEW, "Waiting for send to finish...\n");
#endif
timeout = 0;
do {
#if DEBUG_HALT_SELF
printk(BIOS_SPEW, "+");
#endif
udelay(100);
send_status = lapic_read(LAPIC_ICR) & LAPIC_ICR_BUSY;
} while (send_status && (timeout++ < 1000));
if (timeout >= 1000) {
#if DEBUG_HALT_SELF
printk(BIOS_ERR, "timed out\n");
#endif
}

halt();
}
#endif

/* C entry point of secondary cpus */
asmlinkage void secondary_cpu_init(unsigned int index)
{
atomic_inc(&active_cpus);

if (!CONFIG(PARALLEL_CPU_INIT))
spin_lock(&start_cpu_lock);
spin_lock(&start_cpu_lock);

#ifdef __SSE3__
/*
Expand All @@ -405,8 +301,7 @@ asmlinkage void secondary_cpu_init(unsigned int index)
#endif
cpu_initialize(index);

if (!CONFIG(PARALLEL_CPU_INIT))
spin_unlock(&start_cpu_lock);
spin_unlock(&start_cpu_lock);

atomic_dec(&active_cpus);

Expand All @@ -422,9 +317,6 @@ static void start_other_cpus(struct bus *cpu_bus, struct device *bsp_cpu)
if (cpu->path.type != DEVICE_PATH_APIC)
continue;

if (CONFIG(PARALLEL_CPU_INIT) && (cpu == bsp_cpu))
continue;

if (!cpu->enabled)
continue;

Expand All @@ -436,8 +328,7 @@ static void start_other_cpus(struct bus *cpu_bus, struct device *bsp_cpu)
printk(BIOS_ERR, "CPU 0x%02x would not start!\n",
cpu->path.apic.apic_id);

if (!CONFIG(PARALLEL_CPU_INIT))
udelay(10);
udelay(10);
}

}
Expand Down Expand Up @@ -516,18 +407,13 @@ void initialize_cpus(struct bus *cpu_bus)
/* Find the info struct for this CPU */
info = cpu_info();

if (need_lapic_init()) {
/* Ensure the local APIC is enabled */
/* Ensure the local APIC is enabled */
if (is_smp_boot())
enable_lapic();

/* Get the device path of the boot CPU */
cpu_path.type = DEVICE_PATH_APIC;
cpu_path.apic.apic_id = lapicid();
} else {
/* Get the device path of the boot CPU */
cpu_path.type = DEVICE_PATH_CPU;
cpu_path.cpu.id = 0;
}
/* Get the device path of the boot CPU */
cpu_path.type = DEVICE_PATH_APIC;
cpu_path.apic.apic_id = lapicid();

/* Find the device structure for the boot CPU */
info->cpu = alloc_find_dev(cpu_bus, &cpu_path);
Expand All @@ -540,14 +426,10 @@ void initialize_cpus(struct bus *cpu_bus)
if (!CONFIG(SERIALIZED_SMM_INITIALIZATION))
smm_init();

/* start all aps at first, so we can init ECC all together */
if (is_smp_boot() && CONFIG(PARALLEL_CPU_INIT))
start_other_cpus(cpu_bus, info->cpu);

/* Initialize the bootstrap processor */
cpu_initialize(0);

if (is_smp_boot() && !CONFIG(PARALLEL_CPU_INIT))
if (is_smp_boot())
start_other_cpus(cpu_bus, info->cpu);

/* Now wait the rest of the cpus stop*/
Expand Down
70 changes: 70 additions & 0 deletions src/cpu/x86/lapic/lapic_cpu_stop.c
@@ -0,0 +1,70 @@
/* SPDX-License-Identifier: GPL-2.0-only */

#include <console/console.h>
#include <cpu/x86/lapic.h>
#include <delay.h>
#include <halt.h>

/**
* Sending INIT IPI to self is equivalent of asserting #INIT with a bit of
* delay.
* An undefined number of instruction cycles will complete. All global locks
* must be released before INIT IPI and no printk is allowed after this.
* De-asserting INIT IPI is a no-op on later Intel CPUs.
*
* If you set DEBUG_HALT_SELF to 1, printk's after INIT IPI are enabled
* but running thread may halt without releasing the lock and effectively
* deadlock other CPUs.
*/
#define DEBUG_HALT_SELF 0

#if DEBUG_HALT_SELF
#define dprintk(LEVEL, args...) do { printk(LEVEL, ##args); } while (0)
#else
#define dprintk(LEVEL, args...) do { } while (0)
#endif

static void wait_for_ipi_completion_without_printk(const int timeout_ms)
{
int loops = timeout_ms * 10;
uint32_t send_status;

/* wait for the ipi send to finish */
dprintk(BIOS_SPEW, "Waiting for send to finish...\n");
do {
dprintk(BIOS_SPEW, "+");
udelay(100);
send_status = lapic_busy();
} while (send_status && (--loops > 0));

if (send_status)
dprintk(BIOS_ERR, "timed out\n");
}

/**
* Normally this function is defined in lapic.h as an always inline function
* that just keeps the CPU in a hlt() loop. This does not work on all CPUs.
* I think all hyperthreading CPUs might need this version, but I could only
* verify this on the Intel Core Duo
*/
void stop_this_cpu(void)
{
const int timeout_100ms = 100;
unsigned long id = lapicid();

printk(BIOS_DEBUG, "CPU %ld going down...\n", id);

/* send an LAPIC INIT to myself */
lapic_send_ipi(LAPIC_INT_LEVELTRIG | LAPIC_INT_ASSERT | LAPIC_DM_INIT, id);
wait_for_ipi_completion_without_printk(timeout_100ms);

mdelay(10);

dprintk(BIOS_SPEW, "Deasserting INIT.\n");

/* Deassert the LAPIC INIT */
lapic_send_ipi(LAPIC_INT_LEVELTRIG | LAPIC_DM_INIT, id);
wait_for_ipi_completion_without_printk(timeout_100ms);

halt();
}
6 changes: 4 additions & 2 deletions src/cpu/x86/lapic/secondary.S
Expand Up @@ -61,9 +61,11 @@ __ap_protected_start:
#if ENV_X86_64
/* entry64.inc preserves ebx. */
#include <cpu/x86/64bit/entry64.inc>
mov secondary_stack, %rsp
movabs secondary_stack, %rax
mov %rax, %rsp
andl $0xfffffff0, %esp
mov secondary_cpu_index, %rdi
movabs secondary_cpu_index, %rax
mov %rax, %rdi
#else
/* Set the stack pointer, and flag that we are done */
xorl %eax, %eax
Expand Down
67 changes: 21 additions & 46 deletions src/cpu/x86/mp_init.c
Expand Up @@ -403,7 +403,7 @@ static int apic_wait_timeout(int total_delay, int delay_step)
int total = 0;
int timeout = 0;

while (lapic_read(LAPIC_ICR) & LAPIC_ICR_BUSY) {
while (lapic_busy()) {
udelay(delay_step);
total += delay_step;
if (total >= total_delay) {
Expand Down Expand Up @@ -435,29 +435,10 @@ static int start_aps(struct bus *cpu_bus, int ap_count, atomic_t *num_aps)

printk(BIOS_DEBUG, "Attempting to start %d APs\n", ap_count);

if (is_x2apic_mode()) {
x2apic_send_ipi(LAPIC_DM_INIT | LAPIC_INT_LEVELTRIG |
LAPIC_INT_ASSERT | LAPIC_DEST_ALLBUT, 0);
mdelay(10);
x2apic_send_ipi(LAPIC_DM_STARTUP | LAPIC_INT_LEVELTRIG |
LAPIC_DEST_ALLBUT | sipi_vector, 0);
int x2apic_mode = is_x2apic_mode();
printk(BIOS_DEBUG, "Starting CPUs in %s mode\n", x2apic_mode ? "x2apic" : "xapic");

/* Wait for CPUs to check in up to 200 us. */
wait_for_aps(num_aps, ap_count, 200 /* us */, 15 /* us */);

x2apic_send_ipi(LAPIC_DM_STARTUP | LAPIC_INT_LEVELTRIG |
LAPIC_DEST_ALLBUT | sipi_vector, 0);

/* Wait for CPUs to check in. */
if (wait_for_aps(num_aps, ap_count, 100000 /* 100 ms */, 50 /* us */)) {
printk(BIOS_ERR, "Not all APs checked in: %d/%d.\n",
atomic_read(num_aps), ap_count);
return -1;
}
return 0;
}

if ((lapic_read(LAPIC_ICR) & LAPIC_ICR_BUSY)) {
if (lapic_busy()) {
printk(BIOS_DEBUG, "Waiting for ICR not to be busy...");
if (apic_wait_timeout(1000 /* 1 ms */, 50)) {
printk(BIOS_ERR, "timed out. Aborting.\n");
Expand All @@ -467,14 +448,12 @@ static int start_aps(struct bus *cpu_bus, int ap_count, atomic_t *num_aps)
}

/* Send INIT IPI to all but self. */
lapic_write_around(LAPIC_ICR2, SET_LAPIC_DEST_FIELD(0));
lapic_write_around(LAPIC_ICR, LAPIC_DEST_ALLBUT | LAPIC_INT_ASSERT |
LAPIC_DM_INIT);
lapic_send_ipi(LAPIC_DEST_ALLBUT | LAPIC_INT_ASSERT | LAPIC_DM_INIT, 0);
printk(BIOS_DEBUG, "Waiting for 10ms after sending INIT.\n");
mdelay(10);

/* Send 1st SIPI */
if ((lapic_read(LAPIC_ICR) & LAPIC_ICR_BUSY)) {
if (lapic_busy()) {
printk(BIOS_DEBUG, "Waiting for ICR not to be busy...");
if (apic_wait_timeout(1000 /* 1 ms */, 50)) {
printk(BIOS_ERR, "timed out. Aborting.\n");
Expand All @@ -483,9 +462,8 @@ static int start_aps(struct bus *cpu_bus, int ap_count, atomic_t *num_aps)
printk(BIOS_DEBUG, "done.\n");
}

lapic_write_around(LAPIC_ICR2, SET_LAPIC_DEST_FIELD(0));
lapic_write_around(LAPIC_ICR, LAPIC_DEST_ALLBUT | LAPIC_INT_ASSERT |
LAPIC_DM_STARTUP | sipi_vector);
lapic_send_ipi(LAPIC_DEST_ALLBUT | LAPIC_INT_ASSERT | LAPIC_DM_STARTUP | sipi_vector,
0);
printk(BIOS_DEBUG, "Waiting for 1st SIPI to complete...");
if (apic_wait_timeout(10000 /* 10 ms */, 50 /* us */)) {
printk(BIOS_ERR, "timed out.\n");
Expand All @@ -500,7 +478,7 @@ static int start_aps(struct bus *cpu_bus, int ap_count, atomic_t *num_aps)
return 0;

/* Send 2nd SIPI */
if ((lapic_read(LAPIC_ICR) & LAPIC_ICR_BUSY)) {
if (lapic_busy()) {
printk(BIOS_DEBUG, "Waiting for ICR not to be busy...");
if (apic_wait_timeout(1000 /* 1 ms */, 50)) {
printk(BIOS_ERR, "timed out. Aborting.\n");
Expand All @@ -509,9 +487,8 @@ static int start_aps(struct bus *cpu_bus, int ap_count, atomic_t *num_aps)
printk(BIOS_DEBUG, "done.\n");
}

lapic_write_around(LAPIC_ICR2, SET_LAPIC_DEST_FIELD(0));
lapic_write_around(LAPIC_ICR, LAPIC_DEST_ALLBUT | LAPIC_INT_ASSERT |
LAPIC_DM_STARTUP | sipi_vector);
lapic_send_ipi(LAPIC_DEST_ALLBUT | LAPIC_INT_ASSERT | LAPIC_DM_STARTUP | sipi_vector,
0);
printk(BIOS_DEBUG, "Waiting for 2nd SIPI to complete...");
if (apic_wait_timeout(10000 /* 10 ms */, 50 /* us */)) {
printk(BIOS_ERR, "timed out.\n");
Expand Down Expand Up @@ -675,12 +652,7 @@ static void mp_initialize_cpu(void)

void smm_initiate_relocation_parallel(void)
{
if (is_x2apic_mode()) {
x2apic_send_ipi(LAPIC_DM_SMI | LAPIC_INT_LEVELTRIG, lapicid());
return;
}

if ((lapic_read(LAPIC_ICR) & LAPIC_ICR_BUSY)) {
if (lapic_busy()) {
printk(BIOS_DEBUG, "Waiting for ICR not to be busy...");
if (apic_wait_timeout(1000 /* 1 ms */, 50)) {
printk(BIOS_DEBUG, "timed out. Aborting.\n");
Expand All @@ -689,12 +661,15 @@ void smm_initiate_relocation_parallel(void)
printk(BIOS_DEBUG, "done.\n");
}

lapic_write_around(LAPIC_ICR2, SET_LAPIC_DEST_FIELD(lapicid()));
lapic_write_around(LAPIC_ICR, LAPIC_INT_ASSERT | LAPIC_DM_SMI);
if (apic_wait_timeout(1000 /* 1 ms */, 100 /* us */))
printk(BIOS_DEBUG, "SMI Relocation timed out.\n");
else
printk(BIOS_DEBUG, "Relocation complete.\n");
lapic_send_ipi(LAPIC_INT_ASSERT | LAPIC_DM_SMI, lapicid());

if (lapic_busy()) {
if (apic_wait_timeout(1000 /* 1 ms */, 100 /* us */)) {
printk(BIOS_DEBUG, "SMI Relocation timed out.\n");
return;
}
}
printk(BIOS_DEBUG, "Relocation complete.\n");
}

DECLARE_SPIN_LOCK(smm_relocation_lock);
Expand Down
2 changes: 1 addition & 1 deletion src/cpu/x86/sipi_vector.S
Expand Up @@ -220,7 +220,7 @@ load_msr:

mov %rsi, %rdi /* cpu_num */

movl c_handler, %eax
movabs c_handler, %eax
call *%rax
#else
/* c_handler(cpu_num), preserve proper stack alignment */
Expand Down
1 change: 1 addition & 0 deletions src/cpu/x86/smm/smihandler.c
Expand Up @@ -208,3 +208,4 @@ void __weak southbridge_smi_handler(void) {}
void __weak mainboard_smi_gpi(u32 gpi_sts) {}
int __weak mainboard_smi_apmc(u8 data) { return 0; }
void __weak mainboard_smi_sleep(u8 slp_typ) {}
void __weak mainboard_smi_finalize(void) {}
1 change: 1 addition & 0 deletions src/cpu/x86/smm/smm_module_handler.c
Expand Up @@ -198,3 +198,4 @@ void __weak southbridge_smi_handler() {}
void __weak mainboard_smi_gpi(u32 gpi_sts) {}
int __weak mainboard_smi_apmc(u8 data) { return 0; }
void __weak mainboard_smi_sleep(u8 slp_typ) {}
void __weak mainboard_smi_finalize(void) {}
16 changes: 8 additions & 8 deletions src/cpu/x86/smm/smm_module_loader.c
Expand Up @@ -143,10 +143,10 @@ static int smm_create_map(uintptr_t smbase, unsigned int num_cpus,
for (i = 0; i < num_cpus; i++) {
printk(BIOS_DEBUG, "CPU 0x%x\n", i);
printk(BIOS_DEBUG,
" smbase %zx entry %zx\n",
" smbase %lx entry %lx\n",
cpus[i].smbase, cpus[i].entry);
printk(BIOS_DEBUG,
" ss_start %zx code_end %zx\n",
" ss_start %lx code_end %lx\n",
cpus[i].ss_start, cpus[i].code_end);
seg_count++;
if (seg_count >= cpus_in_segment) {
Expand Down Expand Up @@ -217,23 +217,23 @@ static int smm_place_entry_code(uintptr_t smbase, unsigned int num_cpus,
if (cpus[num_cpus].active) {
if (cpus[num_cpus - 1].smbase + SMM_ENTRY_OFFSET < stack_top) {
printk(BIOS_ERR, "%s: stack encroachment\n", __func__);
printk(BIOS_ERR, "%s: smbase %zx, stack_top %lx\n",
printk(BIOS_ERR, "%s: smbase %lx, stack_top %lx\n",
__func__, cpus[num_cpus].smbase, stack_top);
return 0;
}
}

printk(BIOS_INFO, "%s: smbase %zx, stack_top %lx\n",
printk(BIOS_INFO, "%s: smbase %lx, stack_top %lx\n",
__func__, cpus[num_cpus-1].smbase, stack_top);

/* start at 1, the first CPU stub code is already there */
size = cpus[0].code_end - cpus[0].code_start;
for (i = 1; i < num_cpus; i++) {
memcpy((int *)cpus[i].code_start, (int *)cpus[0].code_start, size);
printk(BIOS_DEBUG,
"SMM Module: placing smm entry code at %zx, cpu # 0x%x\n",
"SMM Module: placing smm entry code at %lx, cpu # 0x%x\n",
cpus[i].code_start, i);
printk(BIOS_DEBUG, "%s: copying from %zx to %zx 0x%x bytes\n",
printk(BIOS_DEBUG, "%s: copying from %lx to %lx 0x%x bytes\n",
__func__, cpus[0].code_start, cpus[i].code_start, size);
}
return 1;
Expand Down Expand Up @@ -356,7 +356,7 @@ static int smm_module_setup_stub(void *const smbase, const size_t smm_size,
/* The save state size encroached over the first SMM entry point. */
if (size <= SMM_ENTRY_OFFSET) {
printk(BIOS_ERR, "%s: encroachment over SMM entry point\n", __func__);
printk(BIOS_ERR, "%s: state save size: %zx : smm_entry_offset -> %lx\n",
printk(BIOS_ERR, "%s: state save size: %zx : smm_entry_offset -> %zx\n",
__func__, size, (size_t)SMM_ENTRY_OFFSET);
return -1;
}
Expand Down Expand Up @@ -411,7 +411,7 @@ static int smm_module_setup_stub(void *const smbase, const size_t smm_size,

const size_t total_stack_size =
params->num_concurrent_stacks * params->per_cpu_stack_size;
printk(BIOS_DEBUG, "%s: stack_end = 0x%lx\n",
printk(BIOS_DEBUG, "%s: stack_end = 0x%zx\n",
__func__, stub_params->stack_top - total_stack_size);
printk(BIOS_DEBUG,
"%s: stack_top = 0x%x\n", __func__, stub_params->stack_top);
Expand Down
2 changes: 1 addition & 1 deletion src/cpu/x86/smm/smm_stub.S
Expand Up @@ -210,7 +210,7 @@ apicid_end:

mov %rsp, %rdi /* *arg */

movl c_handler, %eax
movabs c_handler, %eax
call *%rax

/*
Expand Down
3 changes: 2 additions & 1 deletion src/cpu/x86/smm/smmhandler.S
Expand Up @@ -126,8 +126,9 @@ untampered_lapic:
movw %ax, %fs
movw %ax, %gs

/* FIXME: Incompatible with X2APIC_SUPPORT. */
/* Get this CPU's LAPIC ID */
movl $(LOCAL_APIC_ADDR | LAPIC_ID), %esi
movl $(LAPIC_DEFAULT_BASE | LAPIC_ID), %esi
movl (%esi), %ecx
shr $24, %ecx

Expand Down
7 changes: 7 additions & 0 deletions src/device/device.c
Expand Up @@ -21,6 +21,13 @@
extern struct device *last_dev;
/** Linked list of free resources */
struct resource *free_resources = NULL;
/* Disable a PCI device based on bus, device and function. */
void devfn_disable(const struct bus *bus, unsigned int devfn)
{
struct device *dev = pcidev_path_behind(bus, devfn);
if (dev)
dev->enabled = 0;
}

/**
* Initialize all chips of statically known devices.
Expand Down
6 changes: 6 additions & 0 deletions src/device/device_const.c
Expand Up @@ -397,3 +397,9 @@ bool is_dev_enabled(const struct device *dev)
return false;
return dev->enabled;
}

bool is_devfn_enabled(unsigned int devfn)
{
const struct device *dev = pcidev_path_on_root(devfn);
return is_dev_enabled(dev);
}
4 changes: 2 additions & 2 deletions src/device/dram/Makefile.inc
@@ -1,3 +1,3 @@
romstage-y += ddr4.c ddr3.c ddr2.c ddr_common.c
romstage-y += lpddr4.c ddr4.c ddr3.c ddr2.c ddr_common.c

ramstage-y += ddr4.c ddr3.c ddr2.c ddr_common.c spd.c
ramstage-y += lpddr4.c ddr4.c ddr3.c ddr2.c ddr_common.c spd.c
2 changes: 1 addition & 1 deletion src/device/dram/ddr4.c
Expand Up @@ -143,7 +143,7 @@ uint16_t ddr4_speed_mhz_to_reported_mts(uint16_t speed_mhz)
return speed_attr->reported_mts;
}
}
printk(BIOS_ERR, "ERROR: DDR4 speed of %d MHz is out of range", speed_mhz);
printk(BIOS_ERR, "ERROR: DDR4 speed of %d MHz is out of range\n", speed_mhz);
return 0;
}

Expand Down
70 changes: 70 additions & 0 deletions src/device/dram/lpddr4.c
@@ -0,0 +1,70 @@
/* SPDX-License-Identifier: GPL-2.0-only */

#include <console/console.h>
#include <cbmem.h>
#include <device/device.h>
#include <device/dram/lpddr4.h>
#include <string.h>
#include <memory_info.h>
#include <smbios.h>
#include <types.h>

enum lpddr4_speed_grade {
LPDDR4_1600,
LPDDR4_2400,
LPDDR4_3200,
LPDDR4_4266
};

struct lpddr4_speed_attr {
uint32_t min_clock_mhz; // inclusive
uint32_t max_clock_mhz; // inclusive
uint32_t reported_mts;
};

/**
* LPDDR4 speed attributes derived from JEDEC 209-4C table 210
*
* min_clock_mhz = Previous max_clock_mhz + 1
* max_clock_mhz = 1000/min_tCk_avg(ns)
* reported_mts = Standard reported DDR4 speed in MT/s
* May be slightly less than the actual max MT/s
*/
static const struct lpddr4_speed_attr lpddr4_speeds[] = {
[LPDDR4_1600] = {
.min_clock_mhz = 10,
.max_clock_mhz = 800,
.reported_mts = 1600
},
[LPDDR4_2400] = {
.min_clock_mhz = 801,
.max_clock_mhz = 1200,
.reported_mts = 2400
},
[LPDDR4_3200] = {
.min_clock_mhz = 1201,
.max_clock_mhz = 1600,
.reported_mts = 3200
},
[LPDDR4_4266] = {
.min_clock_mhz = 1601,
.max_clock_mhz = 2137,
.reported_mts = 4266
},
};

/**
* Converts LPDDR4 clock speed in MHz to the standard reported speed in MT/s
*/
uint16_t lpddr4_speed_mhz_to_reported_mts(uint16_t speed_mhz)
{
for (enum lpddr4_speed_grade speed = 0; speed < ARRAY_SIZE(lpddr4_speeds); speed++) {
const struct lpddr4_speed_attr *speed_attr = &lpddr4_speeds[speed];
if (speed_mhz >= speed_attr->min_clock_mhz &&
speed_mhz <= speed_attr->max_clock_mhz) {
return speed_attr->reported_mts;
}
}
printk(BIOS_ERR, "ERROR: LPDDR4 speed of %d MHz is out of range\n", speed_mhz);
return 0;
}
9 changes: 9 additions & 0 deletions src/device/pnp_device.c
Expand Up @@ -47,6 +47,15 @@ u8 pnp_read_config(struct device *dev, u8 reg)
return inb(dev->path.pnp.port + 1);
}

void pnp_unset_and_set_config(struct device *dev, u8 reg, u8 unset, u8 set)
{
outb(reg, dev->path.pnp.port);
u8 value = inb(dev->path.pnp.port + 1);
value &= ~unset;
value |= set;
outb(value, dev->path.pnp.port + 1);
}

void pnp_set_logical_device(struct device *dev)
{
pnp_write_config(dev, 0x07, dev->path.pnp.device & 0xff);
Expand Down
1 change: 0 additions & 1 deletion src/drivers/generic/ioapic/chip.h
Expand Up @@ -6,7 +6,6 @@
typedef struct drivers_generic_ioapic_config {
u32 version;
u8 apicid;
u8 irq_on_fsb;
u8 enable_virtual_wire;
u8 have_isa_interrupts;
void *base;
Expand Down
67 changes: 1 addition & 66 deletions src/drivers/generic/ioapic/ioapic.c
Expand Up @@ -9,76 +9,11 @@
static void ioapic_init(struct device *dev)
{
struct drivers_generic_ioapic_config *config = dev->chip_info;
u32 bsp_lapicid = lapicid();
u32 low, high;
u32 i, ioapic_interrupts;
void *ioapic_base;
u8 ioapic_id;

if (!dev->enabled || !config)
return;

ioapic_base = config->base;
ioapic_id = config->apicid;

printk(BIOS_DEBUG, "IOAPIC: Initializing IOAPIC at %p\n",
ioapic_base);
printk(BIOS_DEBUG, "IOAPIC: Bootstrap Processor Local APIC = 0x%02x\n",
bsp_lapicid);

if (ioapic_id) {
printk(BIOS_DEBUG, "IOAPIC: ID = 0x%02x\n", ioapic_id);
/* Set IOAPIC ID if it has been specified. */
io_apic_write(ioapic_base, 0x00,
(io_apic_read(ioapic_base, 0x00) & 0xf0ffffff) |
(ioapic_id << 24));
}

/* Read the available number of interrupts. */
ioapic_interrupts = (io_apic_read(ioapic_base, 0x01) >> 16) & 0xff;
if (!ioapic_interrupts || ioapic_interrupts == 0xff)
ioapic_interrupts = 24;
printk(BIOS_DEBUG, "IOAPIC: %d interrupts\n", ioapic_interrupts);

if (config->irq_on_fsb) {
/*
* For the Pentium 4 and above APICs deliver their interrupts
* on the front side bus, enable that.
*/
printk(BIOS_DEBUG, "IOAPIC: Enabling interrupts on FSB\n");
io_apic_write(ioapic_base, 0x03,
io_apic_read(ioapic_base, 0x03) | (1 << 0));
} else {
printk(BIOS_DEBUG, "IOAPIC: Enabling interrupts on APIC serial bus\n");
io_apic_write(ioapic_base, 0x03, 0);
}

if (config->enable_virtual_wire) {
/* Enable Virtual Wire Mode. */
low = INT_ENABLED | TRIGGER_EDGE | POLARITY_HIGH | PHYSICAL_DEST | ExtINT;
high = bsp_lapicid << (56 - 32);

io_apic_write(ioapic_base, 0x10, low);
io_apic_write(ioapic_base, 0x11, high);

if (io_apic_read(ioapic_base, 0x10) == 0xffffffff) {
printk(BIOS_WARNING, "IOAPIC not responding.\n");
return;
}

printk(BIOS_SPEW, "IOAPIC: reg 0x%08x value 0x%08x 0x%08x\n", 0,
high, low);
}
low = INT_DISABLED;
high = NONE;

for (i = 1; i < ioapic_interrupts; i++) {
io_apic_write(ioapic_base, i * 2 + 0x10, low);
io_apic_write(ioapic_base, i * 2 + 0x11, high);

printk(BIOS_SPEW, "IOAPIC: reg 0x%08x value 0x%08x 0x%08x\n",
i, high, low);
}
setup_ioapic_helper(config->base, config->apicid, config->enable_virtual_wire);
}

static void ioapic_read_resources(struct device *dev)
Expand Down
13 changes: 9 additions & 4 deletions src/drivers/i2c/designware/dw_i2c.c
Expand Up @@ -803,7 +803,7 @@ void dw_i2c_acpi_fill_ssdt(const struct device *dev)
struct dw_i2c_speed_config sgen;
int bus;
const char *path;
unsigned int speed;
unsigned int speed, i;

bus = dw_i2c_soc_dev_to_bus(dev);

Expand All @@ -826,12 +826,17 @@ void dw_i2c_acpi_fill_ssdt(const struct device *dev)
/* Ensure a default speed is available */
speed = (bcfg->speed == 0) ? I2C_SPEED_FAST : bcfg->speed;

/* Report timing values for the OS driver */
/* Report currently used timing values for the OS driver */
acpigen_write_scope(path);
if (dw_i2c_gen_speed_config(dw_i2c_addr, speed, bcfg, &sgen) >= 0) {
acpigen_write_scope(path);
dw_i2c_acpi_write_speed_config(&sgen);
acpigen_pop_len();
}
/* Now check if there are more speed settings available and report them as well. */
for (i = 0; i < DW_I2C_SPEED_CONFIG_COUNT; i++) {
if (bcfg->speed_config[i].speed && speed != bcfg->speed_config[i].speed)
dw_i2c_acpi_write_speed_config(&bcfg->speed_config[i]);
}
acpigen_write_scope_end();
}

static int dw_i2c_dev_transfer(struct device *dev,
Expand Down
7 changes: 7 additions & 0 deletions src/drivers/i2c/rx6110sa/Kconfig
Expand Up @@ -3,3 +3,10 @@ config DRIVERS_I2C_RX6110SA
default n
help
Enable support for external RTC chip RX6110 SA.

config RX6110SA_DISABLE_ACPI
bool
default n
help
Disable the generation of an ACPI entry for this RTC. This is helpful
when the native driver for this RTC in OS does not have ACPI support enabled.
4 changes: 2 additions & 2 deletions src/drivers/i2c/rx6110sa/rx6110sa.c
Expand Up @@ -166,7 +166,7 @@ static void rx6110sa_init(struct device *dev)
rx6110sa_write(dev, CTRL_REG, reg);
}

#if CONFIG(HAVE_ACPI_TABLES)
#if CONFIG(HAVE_ACPI_TABLES) && !CONFIG(RX6110SA_DISABLE_ACPI)
static void rx6110sa_fill_ssdt(const struct device *dev)
{
struct drivers_i2c_rx6110sa_config *config = dev->chip_info;
Expand Down Expand Up @@ -227,7 +227,7 @@ static struct device_operations rx6110sa_ops = {
.set_resources = noop_set_resources,
.init = rx6110sa_init,
.final = rx6110sa_final,
#if CONFIG(HAVE_ACPI_TABLES)
#if CONFIG(HAVE_ACPI_TABLES) && !CONFIG(RX6110SA_DISABLE_ACPI)
.acpi_name = rx6110sa_acpi_name,
.acpi_fill_ssdt = rx6110sa_fill_ssdt,
#endif
Expand Down
1 change: 0 additions & 1 deletion src/drivers/intel/fsp2_0/include/fsp/api.h
Expand Up @@ -34,7 +34,6 @@ enum fsp_notify_phase {
/* Main FSP stages */
void fsp_memory_init(bool s3wake);
void fsp_silicon_init(void);
void fsp_temp_ram_exit(void);

/*
* Load FSP-S from stage cache or CBFS. This allows SoCs to load FSPS-S
Expand Down
7 changes: 7 additions & 0 deletions src/drivers/intel/fsp2_0/include/fsp/util.h
Expand Up @@ -15,6 +15,13 @@

#define FSP_VER_LEN 30

/* Macro for checking and loading array type configs into array type UPDs */
#define FSP_ARRAY_LOAD(dst, src) \
do { \
_Static_assert(ARRAY_SIZE(dst) >= ARRAY_SIZE(src), "copy buffer overflow!"); \
memcpy(dst, src, sizeof(src)); \
} while (0)

struct hob_header {
uint16_t type;
uint16_t length;
Expand Down