summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorTom Rini <[email protected]>2025-04-03 11:43:38 -0600
committerTom Rini <[email protected]>2025-04-03 11:43:38 -0600
commit1f2a3d066c99f57675162ce09586e9de30407f1b (patch)
tree40bfceab01cc1c6a035eb66792638149400db1ef /drivers
parent39ff722b3ee0bd569388a3b89c59899511ac1a24 (diff)
parenta3d255d996b346c527962926ff80343e02ae8f00 (diff)
Merge patch series "x86: Improve operation under QEMU"
Simon Glass <[email protected]> says: U-Boot can start and boot an OS in both qemu-x86 and qemu-x86_64 but it is not perfect. With both builds, executing the VESA ROM causes an intermittent hang, at least on some AMD CPUs. With qemu-x86_64 kvm cannot be used since the move to long mode (64-bit) is done in a way that works on real hardware but not with QEMU. This means that performance is 4-5x slower than it could be, at least on my CPU. We can work around the first problem by using Bochs, which is anyway a better choice than VESA for QEMU. The second can be addressed by using the same descriptor across the jump to long mode. With an MTRR fix this allows booting into Ubuntu on qemu-x86_64 In v3 some e820 patches are included to make booting reliable and avoid ACPI tables being dropped. Also, several MTTR problems are addressed, to support memory sizes above 4GB reliably. Link: https://lore.kernel.org/all/[email protected]/
Diffstat (limited to 'drivers')
-rw-r--r--drivers/misc/qfw_acpi.c32
1 files changed, 27 insertions, 5 deletions
diff --git a/drivers/misc/qfw_acpi.c b/drivers/misc/qfw_acpi.c
index 0d0cf764689..ec00ba65ade 100644
--- a/drivers/misc/qfw_acpi.c
+++ b/drivers/misc/qfw_acpi.c
@@ -25,17 +25,18 @@ DECLARE_GLOBAL_DATA_PTR;
*
* @entry : BIOS linker command entry which tells where to allocate 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
* be ignored.
* @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)
{
uint32_t size, align;
struct fw_file *file;
unsigned long aligned_addr;
+ struct acpi_rsdp *rsdp;
align = le32_to_cpu(entry->alloc.align);
/* 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
* 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);
if (!aligned_addr) {
printf("error: allocating resource\n");
@@ -83,8 +86,13 @@ static int bios_linker_allocate(struct udevice *dev,
(void *)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 */
- 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);
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);
for (i = 0; i < (size / sizeof(*entry)); i++) {
+ log_content("entry %d: addr %lx\n", i, addr);
entry = table_loader + i;
switch (le32_to_cpu(entry->command)) {
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)
goto out;
break;
case BIOS_LINKER_LOADER_COMMAND_ADD_POINTER:
+ log_content(" - %s\n", entry->pointer.src_file);
ret = bios_linker_add_pointer(dev, entry);
if (ret)
goto out;
break;
case BIOS_LINKER_LOADER_COMMAND_ADD_CHECKSUM:
+ log_content(" - %s\n", entry->cksum.file);
ret = bios_linker_add_checksum(dev, entry);
if (ret)
goto out;
@@ -246,6 +258,16 @@ out:
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());
return addr;