x86: emulation: Support BLOBLIST_TABLES properly
The existing QEMU implementation mostly ignored BLOBLIST_TABLES and allocates the bulk of the tables with malloc(). Update it to place all tables in the bloblist. Since QEMU declares a size of 128KB regardless of the size of its tables, this requires a larger bloblist. Fix up the e820 table to handle this, keeping the old code as an option for now, to assist with any future bug-fixing. Signed-off-by: Simon Glass <sjg@chromium.org>
This commit is contained in:
@@ -6,6 +6,7 @@
|
|||||||
* (C) Copyright 2019 Bin Meng <bmeng.cn@gmail.com>
|
* (C) Copyright 2019 Bin Meng <bmeng.cn@gmail.com>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <bloblist.h>
|
||||||
#include <env_internal.h>
|
#include <env_internal.h>
|
||||||
#include <malloc.h>
|
#include <malloc.h>
|
||||||
#include <asm/e820.h>
|
#include <asm/e820.h>
|
||||||
@@ -27,12 +28,19 @@ unsigned int install_e820_map(unsigned int max_entries,
|
|||||||
e820_next(&ctx, E820_RESERVED, ISA_END_ADDRESS);
|
e820_next(&ctx, E820_RESERVED, ISA_END_ADDRESS);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* since we use memalign(malloc) to allocate high memory for
|
* if we use bloblist to allocate high memory for storing ACPI tables,
|
||||||
* storing ACPI tables, we need to reserve them in e820 tables,
|
* we need to reserve that region in e820 tables, otherwise the kernel
|
||||||
* otherwise kernel will reclaim them and data will be corrupted
|
* will reclaim them and data will be corrupted. The ACPI tables may not
|
||||||
|
* have been written yet, so use the whole bloblist size
|
||||||
*/
|
*/
|
||||||
e820_to_addr(&ctx, E820_RAM, gd->relocaddr - TOTAL_MALLOC_LEN);
|
if (IS_ENABLED(CONFIG_BLOBLIST_TABLES)) {
|
||||||
e820_next(&ctx, E820_RESERVED, TOTAL_MALLOC_LEN);
|
e820_to_addr(&ctx, E820_RAM, (ulong)gd->bloblist);
|
||||||
|
e820_next(&ctx, E820_ACPI, bloblist_get_total_size());
|
||||||
|
} else {
|
||||||
|
/* If using memalign() reserve that whole region instead */
|
||||||
|
e820_to_addr(&ctx, E820_RAM, gd->relocaddr - TOTAL_MALLOC_LEN);
|
||||||
|
e820_next(&ctx, E820_ACPI, TOTAL_MALLOC_LEN);
|
||||||
|
}
|
||||||
e820_to_addr(&ctx, E820_RAM, qemu_get_low_memory_size());
|
e820_to_addr(&ctx, E820_RAM, qemu_get_low_memory_size());
|
||||||
e820_add(&ctx, E820_RESERVED, CONFIG_PCIE_ECAM_BASE,
|
e820_add(&ctx, E820_RESERVED, CONFIG_PCIE_ECAM_BASE,
|
||||||
CONFIG_PCIE_ECAM_SIZE);
|
CONFIG_PCIE_ECAM_SIZE);
|
||||||
|
@@ -45,6 +45,13 @@ struct table_info {
|
|||||||
int align;
|
int align;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* QEMU's tables include quite a bit of empty space */
|
||||||
|
#ifdef CONFIG_QEMU
|
||||||
|
#define ACPI_SIZE (192 << 10)
|
||||||
|
#else
|
||||||
|
#define ACPI_SIZE SZ_64K
|
||||||
|
#endif
|
||||||
|
|
||||||
static struct table_info table_list[] = {
|
static struct table_info table_list[] = {
|
||||||
#ifdef CONFIG_GENERATE_PIRQ_TABLE
|
#ifdef CONFIG_GENERATE_PIRQ_TABLE
|
||||||
{ "pirq", write_pirq_routing_table },
|
{ "pirq", write_pirq_routing_table },
|
||||||
@@ -60,7 +67,7 @@ static struct table_info table_list[] = {
|
|||||||
* that the calculation of gd->table_end works properly
|
* that the calculation of gd->table_end works properly
|
||||||
*/
|
*/
|
||||||
#ifdef CONFIG_GENERATE_ACPI_TABLE
|
#ifdef CONFIG_GENERATE_ACPI_TABLE
|
||||||
{ "acpi", write_acpi_tables, BLOBLISTT_ACPI_TABLES, SZ_64K, SZ_4K},
|
{ "acpi", write_acpi_tables, BLOBLISTT_ACPI_TABLES, ACPI_SIZE, SZ_4K},
|
||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_GENERATE_SMBIOS_TABLE
|
#ifdef CONFIG_GENERATE_SMBIOS_TABLE
|
||||||
/*
|
/*
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
CONFIG_X86=y
|
CONFIG_X86=y
|
||||||
CONFIG_TEXT_BASE=0x1110000
|
CONFIG_TEXT_BASE=0x1110000
|
||||||
CONFIG_SYS_MALLOC_F_LEN=0x1800
|
CONFIG_SYS_MALLOC_F_LEN=0x1800
|
||||||
CONFIG_BLOBLIST_SIZE_RELOC=0x20000
|
CONFIG_BLOBLIST_SIZE_RELOC=0x40000
|
||||||
CONFIG_NR_DRAM_BANKS=8
|
CONFIG_NR_DRAM_BANKS=8
|
||||||
CONFIG_ENV_SIZE=0x40000
|
CONFIG_ENV_SIZE=0x40000
|
||||||
CONFIG_MAX_CPUS=2
|
CONFIG_MAX_CPUS=2
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
CONFIG_X86=y
|
CONFIG_X86=y
|
||||||
CONFIG_TEXT_BASE=0xFFF00000
|
CONFIG_TEXT_BASE=0xFFF00000
|
||||||
CONFIG_SYS_MALLOC_F_LEN=0x1000
|
CONFIG_SYS_MALLOC_F_LEN=0x1000
|
||||||
CONFIG_BLOBLIST_SIZE_RELOC=0x20000
|
CONFIG_BLOBLIST_SIZE_RELOC=0x40000
|
||||||
CONFIG_NR_DRAM_BANKS=8
|
CONFIG_NR_DRAM_BANKS=8
|
||||||
CONFIG_ENV_SIZE=0x40000
|
CONFIG_ENV_SIZE=0x40000
|
||||||
CONFIG_MAX_CPUS=2
|
CONFIG_MAX_CPUS=2
|
||||||
|
@@ -25,17 +25,18 @@ DECLARE_GLOBAL_DATA_PTR;
|
|||||||
*
|
*
|
||||||
* @entry : BIOS linker command entry which tells where to allocate memory
|
* @entry : BIOS linker command entry which tells where to allocate memory
|
||||||
* (either high memory or low memory)
|
* (either high memory or low memory)
|
||||||
* @addr : The address that should be used for low memory allcation. If the
|
* @addr : The address that should be used for low memory allocation. If the
|
||||||
* memory allocation request is 'ZONE_HIGH' then this parameter will
|
* memory allocation request is 'ZONE_HIGH' then this parameter will
|
||||||
* be ignored.
|
* be ignored.
|
||||||
* @return: 0 on success, or negative value on failure
|
* @return: 0 on success, or negative value on failure
|
||||||
*/
|
*/
|
||||||
static int bios_linker_allocate(struct udevice *dev,
|
static int bios_linker_allocate(struct acpi_ctx *ctx, struct udevice *dev,
|
||||||
struct bios_linker_entry *entry, ulong *addr)
|
struct bios_linker_entry *entry, ulong *addr)
|
||||||
{
|
{
|
||||||
uint32_t size, align;
|
uint32_t size, align;
|
||||||
struct fw_file *file;
|
struct fw_file *file;
|
||||||
unsigned long aligned_addr;
|
unsigned long aligned_addr;
|
||||||
|
struct acpi_rsdp *rsdp;
|
||||||
|
|
||||||
align = le32_to_cpu(entry->alloc.align);
|
align = le32_to_cpu(entry->alloc.align);
|
||||||
/* align must be power of 2 */
|
/* align must be power of 2 */
|
||||||
@@ -58,7 +59,9 @@ static int bios_linker_allocate(struct udevice *dev,
|
|||||||
* If allocation zone is ZONE_FSEG, then we use the 'addr' passed
|
* If allocation zone is ZONE_FSEG, then we use the 'addr' passed
|
||||||
* in which is low memory
|
* in which is low memory
|
||||||
*/
|
*/
|
||||||
if (entry->alloc.zone == BIOS_LINKER_LOADER_ALLOC_ZONE_HIGH) {
|
if (IS_ENABLED(CONFIG_BLOBLIST_TABLES)) {
|
||||||
|
aligned_addr = ALIGN(*addr, align);
|
||||||
|
} else if (entry->alloc.zone == BIOS_LINKER_LOADER_ALLOC_ZONE_HIGH) {
|
||||||
aligned_addr = (unsigned long)memalign(align, size);
|
aligned_addr = (unsigned long)memalign(align, size);
|
||||||
if (!aligned_addr) {
|
if (!aligned_addr) {
|
||||||
printf("error: allocating resource\n");
|
printf("error: allocating resource\n");
|
||||||
@@ -83,8 +86,13 @@ static int bios_linker_allocate(struct udevice *dev,
|
|||||||
(void *)aligned_addr);
|
(void *)aligned_addr);
|
||||||
file->addr = aligned_addr;
|
file->addr = aligned_addr;
|
||||||
|
|
||||||
|
rsdp = (void *)aligned_addr;
|
||||||
|
if (!strncmp(rsdp->signature, RSDP_SIG, sizeof(rsdp->signature)))
|
||||||
|
ctx->rsdp = rsdp;
|
||||||
|
|
||||||
/* adjust address for low memory allocation */
|
/* adjust address for low memory allocation */
|
||||||
if (entry->alloc.zone == BIOS_LINKER_LOADER_ALLOC_ZONE_FSEG)
|
if (IS_ENABLED(CONFIG_BLOBLIST_TABLES) ||
|
||||||
|
entry->alloc.zone == BIOS_LINKER_LOADER_ALLOC_ZONE_FSEG)
|
||||||
*addr = (aligned_addr + size);
|
*addr = (aligned_addr + size);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -209,19 +217,23 @@ ulong write_acpi_tables(ulong addr)
|
|||||||
qfw_read_entry(dev, be16_to_cpu(file->cfg.select), size, table_loader);
|
qfw_read_entry(dev, be16_to_cpu(file->cfg.select), size, table_loader);
|
||||||
|
|
||||||
for (i = 0; i < (size / sizeof(*entry)); i++) {
|
for (i = 0; i < (size / sizeof(*entry)); i++) {
|
||||||
|
log_content("entry %d: addr %lx\n", i, addr);
|
||||||
entry = table_loader + i;
|
entry = table_loader + i;
|
||||||
switch (le32_to_cpu(entry->command)) {
|
switch (le32_to_cpu(entry->command)) {
|
||||||
case BIOS_LINKER_LOADER_COMMAND_ALLOCATE:
|
case BIOS_LINKER_LOADER_COMMAND_ALLOCATE:
|
||||||
ret = bios_linker_allocate(dev, entry, &addr);
|
log_content(" - %s\n", entry->alloc.file);
|
||||||
|
ret = bios_linker_allocate(ctx, dev, entry, &addr);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto out;
|
goto out;
|
||||||
break;
|
break;
|
||||||
case BIOS_LINKER_LOADER_COMMAND_ADD_POINTER:
|
case BIOS_LINKER_LOADER_COMMAND_ADD_POINTER:
|
||||||
|
log_content(" - %s\n", entry->pointer.src_file);
|
||||||
ret = bios_linker_add_pointer(dev, entry);
|
ret = bios_linker_add_pointer(dev, entry);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto out;
|
goto out;
|
||||||
break;
|
break;
|
||||||
case BIOS_LINKER_LOADER_COMMAND_ADD_CHECKSUM:
|
case BIOS_LINKER_LOADER_COMMAND_ADD_CHECKSUM:
|
||||||
|
log_content(" - %s\n", entry->cksum.file);
|
||||||
ret = bios_linker_add_checksum(dev, entry);
|
ret = bios_linker_add_checksum(dev, entry);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto out;
|
goto out;
|
||||||
@@ -246,6 +258,16 @@ out:
|
|||||||
|
|
||||||
free(table_loader);
|
free(table_loader);
|
||||||
|
|
||||||
|
if (!ctx->rsdp) {
|
||||||
|
printf("error: no RSDP found\n");
|
||||||
|
return addr;
|
||||||
|
}
|
||||||
|
struct acpi_rsdp *rsdp = ctx->rsdp;
|
||||||
|
|
||||||
|
rsdp->length = sizeof(*rsdp);
|
||||||
|
rsdp->xsdt_address = 0;
|
||||||
|
rsdp->ext_checksum = table_compute_checksum((u8 *)rsdp, sizeof(*rsdp));
|
||||||
|
|
||||||
gd_set_acpi_start(acpi_get_rsdp_addr());
|
gd_set_acpi_start(acpi_get_rsdp_addr());
|
||||||
|
|
||||||
return addr;
|
return addr;
|
||||||
|
Reference in New Issue
Block a user