[PATCH v3 0/9] acpi: add ACPI support on QEMU ARM and RISC-V

QEMU 8.1.2 can create ACPI tables for the ARM and RISC-V architectures Allow passing them through to the operating system. Provide a new config fragment that enables this.
v3: let tables in global data depend on CONFIG_(SPL_)ACPI v2: consider ARM architecture too invoke write_acpi_tables() via EVT_LAST_STAGE_INIT
Heinrich Schuchardt (9): acpi: Kconfig symbol CONFIG_QFW_ACPI acpi: carve out qfw_acpi.c arm: add ACPI fields to global data risc-v: add ACPI fields to global data acpi: enable writing ACPI tables on QEMU risc-v: add support for QEMU firmware tables riscv: allow usage of ACPI configs: qemu: add config fragment for ACPI arm: enable support for QEMU firmware tables
MAINTAINERS | 1 + arch/Kconfig | 1 + arch/arm/include/asm/global_data.h | 7 +- arch/riscv/include/asm/global_data.h | 6 + board/emulation/configs/acpi.config | 3 + board/emulation/qemu-arm/Kconfig | 1 + board/emulation/qemu-riscv/Kconfig | 2 + doc/board/emulation/acpi.rst | 23 +++ doc/board/emulation/index.rst | 1 + drivers/misc/Kconfig | 7 + drivers/misc/Makefile | 1 + drivers/misc/qfw.c | 240 ----------------------- drivers/misc/qfw_acpi.c | 281 +++++++++++++++++++++++++++ lib/acpi/Makefile | 2 +- lib/acpi/acpi_writer.c | 4 +- 15 files changed, 336 insertions(+), 244 deletions(-) create mode 100644 board/emulation/configs/acpi.config create mode 100644 doc/board/emulation/acpi.rst create mode 100644 drivers/misc/qfw_acpi.c

We have two implementations of write_acpi_tables(). One for writing ACPI tables based on ACPI_WRITER() entries another based on copying tables from QEMU.
Create a symbol CONFIG_QFW_ACPI that signifies copying ACPI tables from QEMU and use it consistently.
Signed-off-by: Heinrich Schuchardt heinrich.schuchardt@canonical.com Reviewed-by: Simon Glass sjg@chromium.org --- v3: no change v2: no change --- drivers/misc/Kconfig | 7 +++++++ drivers/misc/qfw.c | 4 ++-- lib/acpi/Makefile | 2 +- lib/acpi/acpi_writer.c | 4 ++-- 4 files changed, 12 insertions(+), 5 deletions(-)
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index ed7ecedd3a..e8e4400516 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -540,6 +540,13 @@ config QFW Hidden option to enable QEMU fw_cfg interface and uclass. This will be selected by either CONFIG_CMD_QFW or CONFIG_GENERATE_ACPI_TABLE.
+config QFW_ACPI + bool + default y + depends on QFW && GENERATE_ACPI_TABLE && !SANDBOX + help + Hidden option to read ACPI tables from QEMU. + config QFW_PIO bool depends on QFW diff --git a/drivers/misc/qfw.c b/drivers/misc/qfw.c index e3b6b4cd74..307334faf4 100644 --- a/drivers/misc/qfw.c +++ b/drivers/misc/qfw.c @@ -21,7 +21,7 @@ #include <tables_csum.h> #include <asm/acpi_table.h>
-#if defined(CONFIG_GENERATE_ACPI_TABLE) && !defined(CONFIG_SANDBOX) +#ifdef QFW_ACPI /* * This function allocates memory for ACPI tables * @@ -259,7 +259,7 @@ ulong acpi_get_rsdp_addr(void) file = qfw_find_file(dev, "etc/acpi/rsdp"); return file->addr; } -#endif +#endif /* QFW_ACPI */
static void qfw_read_entry_io(struct qfw_dev *qdev, u16 entry, u32 size, void *address) diff --git a/lib/acpi/Makefile b/lib/acpi/Makefile index c1c9675b5d..cc2868488a 100644 --- a/lib/acpi/Makefile +++ b/lib/acpi/Makefile @@ -12,7 +12,7 @@ obj-$(CONFIG_$(SPL_)ACPIGEN) += acpi_table.o obj-y += acpi_writer.o
# With QEMU the ACPI tables come from there, not from U-Boot -ifndef CONFIG_QEMU +ifndef CONFIG_QFW_ACPI obj-y += base.o obj-y += csrt.o obj-y += mcfg.o diff --git a/lib/acpi/acpi_writer.c b/lib/acpi/acpi_writer.c index 946f90e8e7..9b9fdc190b 100644 --- a/lib/acpi/acpi_writer.c +++ b/lib/acpi/acpi_writer.c @@ -48,7 +48,7 @@ int acpi_write_one(struct acpi_ctx *ctx, const struct acpi_writer *entry) return 0; }
-#ifndef CONFIG_QEMU +#ifndef CONFIG_QFW_ACPI static int acpi_write_all(struct acpi_ctx *ctx) { const struct acpi_writer *writer = @@ -115,7 +115,7 @@ ulong acpi_get_rsdp_addr(void)
return map_to_sysmem(gd->acpi_ctx->rsdp); } -#endif /* QEMU */ +#endif /* QFW_ACPI */
void acpi_setup_ctx(struct acpi_ctx *ctx, ulong start) {

Move the code related to copying tables from QEMU to a separate code module.
Signed-off-by: Heinrich Schuchardt heinrich.schuchardt@canonical.com Reviewed-by: Tom Rini trini@konsulko.com Reviewed-by: Simon Glass sjg@chromium.org --- v3: no change v2: add missing blank line --- drivers/misc/Makefile | 1 + drivers/misc/qfw.c | 240 ------------------------------------- drivers/misc/qfw_acpi.c | 256 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 257 insertions(+), 240 deletions(-) create mode 100644 drivers/misc/qfw_acpi.c
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index b67b82358a..cda701d38e 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -63,6 +63,7 @@ obj-$(CONFIG_$(SPL_)PWRSEQ) += pwrseq-uclass.o obj-$(CONFIG_QCOM_GENI_SE) += qcom-geni-se.o ifdef CONFIG_QFW obj-y += qfw.o +obj-$(CONFIG_QFW_ACPI) += qfw_acpi.o obj-$(CONFIG_QFW_PIO) += qfw_pio.o obj-$(CONFIG_QFW_MMIO) += qfw_mmio.o obj-$(CONFIG_SANDBOX) += qfw_sandbox.o diff --git a/drivers/misc/qfw.c b/drivers/misc/qfw.c index 307334faf4..db98619fdf 100644 --- a/drivers/misc/qfw.c +++ b/drivers/misc/qfw.c @@ -21,246 +21,6 @@ #include <tables_csum.h> #include <asm/acpi_table.h>
-#ifdef QFW_ACPI -/* - * This function allocates memory for ACPI tables - * - * @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 - * 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, - struct bios_linker_entry *entry, ulong *addr) -{ - uint32_t size, align; - struct fw_file *file; - unsigned long aligned_addr; - - align = le32_to_cpu(entry->alloc.align); - /* align must be power of 2 */ - if (align & (align - 1)) { - printf("error: wrong alignment %u\n", align); - return -EINVAL; - } - - file = qfw_find_file(dev, entry->alloc.file); - if (!file) { - printf("error: can't find file %s\n", entry->alloc.file); - return -ENOENT; - } - - size = be32_to_cpu(file->cfg.size); - - /* - * ZONE_HIGH means we need to allocate from high memory, since - * malloc space is already at the end of RAM, so we directly use it. - * 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) { - aligned_addr = (unsigned long)memalign(align, size); - if (!aligned_addr) { - printf("error: allocating resource\n"); - return -ENOMEM; - } - if (aligned_addr < gd->arch.table_start_high) - gd->arch.table_start_high = aligned_addr; - if (aligned_addr + size > gd->arch.table_end_high) - gd->arch.table_end_high = aligned_addr + size; - - } else if (entry->alloc.zone == BIOS_LINKER_LOADER_ALLOC_ZONE_FSEG) { - aligned_addr = ALIGN(*addr, align); - } else { - printf("error: invalid allocation zone\n"); - return -EINVAL; - } - - debug("bios_linker_allocate: allocate file %s, size %u, zone %d, align %u, addr 0x%lx\n", - file->cfg.name, size, entry->alloc.zone, align, aligned_addr); - - qfw_read_entry(dev, be16_to_cpu(file->cfg.select), size, - (void *)aligned_addr); - file->addr = aligned_addr; - - /* adjust address for low memory allocation */ - if (entry->alloc.zone == BIOS_LINKER_LOADER_ALLOC_ZONE_FSEG) - *addr = (aligned_addr + size); - - return 0; -} - -/* - * This function patches ACPI tables previously loaded - * by bios_linker_allocate() - * - * @entry : BIOS linker command entry which tells how to patch - * ACPI tables - * @return: 0 on success, or negative value on failure - */ -static int bios_linker_add_pointer(struct udevice *dev, - struct bios_linker_entry *entry) -{ - struct fw_file *dest, *src; - uint32_t offset = le32_to_cpu(entry->pointer.offset); - uint64_t pointer = 0; - - dest = qfw_find_file(dev, entry->pointer.dest_file); - if (!dest || !dest->addr) - return -ENOENT; - src = qfw_find_file(dev, entry->pointer.src_file); - if (!src || !src->addr) - return -ENOENT; - - debug("bios_linker_add_pointer: dest->addr 0x%lx, src->addr 0x%lx, offset 0x%x size %u, 0x%llx\n", - dest->addr, src->addr, offset, entry->pointer.size, pointer); - - memcpy(&pointer, (char *)dest->addr + offset, entry->pointer.size); - pointer = le64_to_cpu(pointer); - pointer += (unsigned long)src->addr; - pointer = cpu_to_le64(pointer); - memcpy((char *)dest->addr + offset, &pointer, entry->pointer.size); - - return 0; -} - -/* - * This function updates checksum fields of ACPI tables previously loaded - * by bios_linker_allocate() - * - * @entry : BIOS linker command entry which tells where to update ACPI table - * checksums - * @return: 0 on success, or negative value on failure - */ -static int bios_linker_add_checksum(struct udevice *dev, - struct bios_linker_entry *entry) -{ - struct fw_file *file; - uint8_t *data, cksum = 0; - uint8_t *cksum_start; - - file = qfw_find_file(dev, entry->cksum.file); - if (!file || !file->addr) - return -ENOENT; - - data = (uint8_t *)(file->addr + le32_to_cpu(entry->cksum.offset)); - cksum_start = (uint8_t *)(file->addr + le32_to_cpu(entry->cksum.start)); - cksum = table_compute_checksum(cksum_start, - le32_to_cpu(entry->cksum.length)); - *data = cksum; - - return 0; -} - -/* This function loads and patches ACPI tables provided by QEMU */ -ulong write_acpi_tables(ulong addr) -{ - int i, ret; - struct fw_file *file; - struct bios_linker_entry *table_loader; - struct bios_linker_entry *entry; - uint32_t size; - struct udevice *dev; - - ret = qfw_get_dev(&dev); - if (ret) { - printf("error: no qfw\n"); - return addr; - } - - /* make sure fw_list is loaded */ - ret = qfw_read_firmware_list(dev); - if (ret) { - printf("error: can't read firmware file list\n"); - return addr; - } - - file = qfw_find_file(dev, "etc/table-loader"); - if (!file) { - printf("error: can't find etc/table-loader\n"); - return addr; - } - - size = be32_to_cpu(file->cfg.size); - if ((size % sizeof(*entry)) != 0) { - printf("error: table-loader maybe corrupted\n"); - return addr; - } - - table_loader = malloc(size); - if (!table_loader) { - printf("error: no memory for table-loader\n"); - return addr; - } - - /* QFW always puts tables at high addresses */ - gd->arch.table_start_high = (ulong)table_loader; - gd->arch.table_end_high = (ulong)table_loader; - - qfw_read_entry(dev, be16_to_cpu(file->cfg.select), size, table_loader); - - for (i = 0; i < (size / sizeof(*entry)); i++) { - entry = table_loader + i; - switch (le32_to_cpu(entry->command)) { - case BIOS_LINKER_LOADER_COMMAND_ALLOCATE: - ret = bios_linker_allocate(dev, entry, &addr); - if (ret) - goto out; - break; - case BIOS_LINKER_LOADER_COMMAND_ADD_POINTER: - ret = bios_linker_add_pointer(dev, entry); - if (ret) - goto out; - break; - case BIOS_LINKER_LOADER_COMMAND_ADD_CHECKSUM: - ret = bios_linker_add_checksum(dev, entry); - if (ret) - goto out; - break; - default: - break; - } - } - -out: - if (ret) { - struct fw_cfg_file_iter iter; - for (file = qfw_file_iter_init(dev, &iter); - !qfw_file_iter_end(&iter); - file = qfw_file_iter_next(&iter)) { - if (file->addr) { - free((void *)file->addr); - file->addr = 0; - } - } - } - - free(table_loader); - - gd_set_acpi_start(acpi_get_rsdp_addr()); - - return addr; -} - -ulong acpi_get_rsdp_addr(void) -{ - int ret; - struct fw_file *file; - struct udevice *dev; - - ret = qfw_get_dev(&dev); - if (ret) { - printf("error: no qfw\n"); - return 0; - } - - file = qfw_find_file(dev, "etc/acpi/rsdp"); - return file->addr; -} -#endif /* QFW_ACPI */ - static void qfw_read_entry_io(struct qfw_dev *qdev, u16 entry, u32 size, void *address) { diff --git a/drivers/misc/qfw_acpi.c b/drivers/misc/qfw_acpi.c new file mode 100644 index 0000000000..6e14b2a504 --- /dev/null +++ b/drivers/misc/qfw_acpi.c @@ -0,0 +1,256 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2015 Miao Yan yanmiaobest@gmail.com + * (C) Copyright 2021 Asherah Connor ashe@kivikakk.ee + */ + +#define LOG_CATEGORY UCLASS_QFW + +#include <acpi/acpi_table.h> +#include <errno.h> +#include <malloc.h> +#include <qfw.h> +#include <tables_csum.h> +#include <stdio.h> +#include <asm/byteorder.h> +#include <asm/global_data.h> + +DECLARE_GLOBAL_DATA_PTR; + +/* + * This function allocates memory for ACPI tables + * + * @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 + * 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, + struct bios_linker_entry *entry, ulong *addr) +{ + uint32_t size, align; + struct fw_file *file; + unsigned long aligned_addr; + + align = le32_to_cpu(entry->alloc.align); + /* align must be power of 2 */ + if (align & (align - 1)) { + printf("error: wrong alignment %u\n", align); + return -EINVAL; + } + + file = qfw_find_file(dev, entry->alloc.file); + if (!file) { + printf("error: can't find file %s\n", entry->alloc.file); + return -ENOENT; + } + + size = be32_to_cpu(file->cfg.size); + + /* + * ZONE_HIGH means we need to allocate from high memory, since + * malloc space is already at the end of RAM, so we directly use it. + * 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) { + aligned_addr = (unsigned long)memalign(align, size); + if (!aligned_addr) { + printf("error: allocating resource\n"); + return -ENOMEM; + } + if (aligned_addr < gd->arch.table_start_high) + gd->arch.table_start_high = aligned_addr; + if (aligned_addr + size > gd->arch.table_end_high) + gd->arch.table_end_high = aligned_addr + size; + + } else if (entry->alloc.zone == BIOS_LINKER_LOADER_ALLOC_ZONE_FSEG) { + aligned_addr = ALIGN(*addr, align); + } else { + printf("error: invalid allocation zone\n"); + return -EINVAL; + } + + debug("bios_linker_allocate: allocate file %s, size %u, zone %d, align %u, addr 0x%lx\n", + file->cfg.name, size, entry->alloc.zone, align, aligned_addr); + + qfw_read_entry(dev, be16_to_cpu(file->cfg.select), size, + (void *)aligned_addr); + file->addr = aligned_addr; + + /* adjust address for low memory allocation */ + if (entry->alloc.zone == BIOS_LINKER_LOADER_ALLOC_ZONE_FSEG) + *addr = (aligned_addr + size); + + return 0; +} + +/* + * This function patches ACPI tables previously loaded + * by bios_linker_allocate() + * + * @entry : BIOS linker command entry which tells how to patch + * ACPI tables + * @return: 0 on success, or negative value on failure + */ +static int bios_linker_add_pointer(struct udevice *dev, + struct bios_linker_entry *entry) +{ + struct fw_file *dest, *src; + uint32_t offset = le32_to_cpu(entry->pointer.offset); + uint64_t pointer = 0; + + dest = qfw_find_file(dev, entry->pointer.dest_file); + if (!dest || !dest->addr) + return -ENOENT; + src = qfw_find_file(dev, entry->pointer.src_file); + if (!src || !src->addr) + return -ENOENT; + + debug("bios_linker_add_pointer: dest->addr 0x%lx, src->addr 0x%lx, offset 0x%x size %u, 0x%llx\n", + dest->addr, src->addr, offset, entry->pointer.size, pointer); + + memcpy(&pointer, (char *)dest->addr + offset, entry->pointer.size); + pointer = le64_to_cpu(pointer); + pointer += (unsigned long)src->addr; + pointer = cpu_to_le64(pointer); + memcpy((char *)dest->addr + offset, &pointer, entry->pointer.size); + + return 0; +} + +/* + * This function updates checksum fields of ACPI tables previously loaded + * by bios_linker_allocate() + * + * @entry : BIOS linker command entry which tells where to update ACPI table + * checksums + * @return: 0 on success, or negative value on failure + */ +static int bios_linker_add_checksum(struct udevice *dev, + struct bios_linker_entry *entry) +{ + struct fw_file *file; + uint8_t *data, cksum = 0; + uint8_t *cksum_start; + + file = qfw_find_file(dev, entry->cksum.file); + if (!file || !file->addr) + return -ENOENT; + + data = (uint8_t *)(file->addr + le32_to_cpu(entry->cksum.offset)); + cksum_start = (uint8_t *)(file->addr + le32_to_cpu(entry->cksum.start)); + cksum = table_compute_checksum(cksum_start, + le32_to_cpu(entry->cksum.length)); + *data = cksum; + + return 0; +} + +/* This function loads and patches ACPI tables provided by QEMU */ +ulong write_acpi_tables(ulong addr) +{ + int i, ret; + struct fw_file *file; + struct bios_linker_entry *table_loader; + struct bios_linker_entry *entry; + uint32_t size; + struct udevice *dev; + + ret = qfw_get_dev(&dev); + if (ret) { + printf("error: no qfw\n"); + return addr; + } + + /* make sure fw_list is loaded */ + ret = qfw_read_firmware_list(dev); + if (ret) { + printf("error: can't read firmware file list\n"); + return addr; + } + + file = qfw_find_file(dev, "etc/table-loader"); + if (!file) { + printf("error: can't find etc/table-loader\n"); + return addr; + } + + size = be32_to_cpu(file->cfg.size); + if ((size % sizeof(*entry)) != 0) { + printf("error: table-loader maybe corrupted\n"); + return addr; + } + + table_loader = malloc(size); + if (!table_loader) { + printf("error: no memory for table-loader\n"); + return addr; + } + + /* QFW always puts tables at high addresses */ + gd->arch.table_start_high = (ulong)table_loader; + gd->arch.table_end_high = (ulong)table_loader; + + qfw_read_entry(dev, be16_to_cpu(file->cfg.select), size, table_loader); + + for (i = 0; i < (size / sizeof(*entry)); i++) { + entry = table_loader + i; + switch (le32_to_cpu(entry->command)) { + case BIOS_LINKER_LOADER_COMMAND_ALLOCATE: + ret = bios_linker_allocate(dev, entry, &addr); + if (ret) + goto out; + break; + case BIOS_LINKER_LOADER_COMMAND_ADD_POINTER: + ret = bios_linker_add_pointer(dev, entry); + if (ret) + goto out; + break; + case BIOS_LINKER_LOADER_COMMAND_ADD_CHECKSUM: + ret = bios_linker_add_checksum(dev, entry); + if (ret) + goto out; + break; + default: + break; + } + } + +out: + if (ret) { + struct fw_cfg_file_iter iter; + for (file = qfw_file_iter_init(dev, &iter); + !qfw_file_iter_end(&iter); + file = qfw_file_iter_next(&iter)) { + if (file->addr) { + free((void *)file->addr); + file->addr = 0; + } + } + } + + free(table_loader); + + gd_set_acpi_start(acpi_get_rsdp_addr()); + + return addr; +} + +ulong acpi_get_rsdp_addr(void) +{ + int ret; + struct fw_file *file; + struct udevice *dev; + + ret = qfw_get_dev(&dev); + if (ret) { + printf("error: no qfw\n"); + return 0; + } + + file = qfw_find_file(dev, "etc/acpi/rsdp"); + return file->addr; +}

Add fields for the location of ACPI tables to the global data.
Signed-off-by: Heinrich Schuchardt heinrich.schuchardt@canonical.com --- v3: let tables in global data depend on CONFIG_(SPL_)ACPI v2: new patch --- arch/arm/include/asm/global_data.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/arch/arm/include/asm/global_data.h b/arch/arm/include/asm/global_data.h index 75bd9d56f8..c3d87caa0b 100644 --- a/arch/arm/include/asm/global_data.h +++ b/arch/arm/include/asm/global_data.h @@ -19,7 +19,12 @@ struct arch_global_data { #if defined(CONFIG_FSL_ESDHC) || defined(CONFIG_FSL_ESDHC_IMX) u32 sdhc_clk; #endif - +#if CONFIG_IS_ENABLED(ACPI) + ulong table_start; /* Start address of ACPI tables */ + ulong table_end; /* End address of ACPI tables */ + ulong table_start_high; /* Start address of high ACPI tables */ + ulong table_end_high; /* End address of high ACPI tables */ +#endif #if defined(CONFIG_FSL_ESDHC) u32 sdhc_per_clk; #endif

On Tue, Dec 19, 2023 at 12:24 PM Heinrich Schuchardt heinrich.schuchardt@canonical.com wrote:
Add fields for the location of ACPI tables to the global data.
Signed-off-by: Heinrich Schuchardt heinrich.schuchardt@canonical.com
v3: let tables in global data depend on CONFIG_(SPL_)ACPI v2: new patch
arch/arm/include/asm/global_data.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
Reviewed-by: Simon Glass sjg@chromium.org

Add fields for the location of ACPI tables to the global data.
Signed-off-by: Heinrich Schuchardt heinrich.schuchardt@canonical.com Reviewed-by: Simon Glass sjg@chromium.org --- v3: let tables in global data depend on CONFIG_(SPL_)ACPI v2: no change --- arch/riscv/include/asm/global_data.h | 6 ++++++ 1 file changed, 6 insertions(+)
diff --git a/arch/riscv/include/asm/global_data.h b/arch/riscv/include/asm/global_data.h index 937fa4d154..0f7c08a49d 100644 --- a/arch/riscv/include/asm/global_data.h +++ b/arch/riscv/include/asm/global_data.h @@ -32,6 +32,12 @@ struct arch_global_data { ulong available_harts; #endif #endif +#if CONFIG_IS_ENABLED(ACPI) + ulong table_start; /* Start address of ACPI tables */ + ulong table_end; /* End address of ACPI tables */ + ulong table_start_high; /* Start address of high ACPI tables */ + ulong table_end_high; /* End address of high ACPI tables */ +#endif #ifdef CONFIG_SMBIOS ulong smbios_start; /* Start address of SMBIOS table */ #endif

On Tue, Dec 19, 2023 at 8:24 PM Heinrich Schuchardt heinrich.schuchardt@canonical.com wrote:
Add fields for the location of ACPI tables to the global data.
nits: I believe the tag should be 'riscv' instead of 'risc-v'.
Signed-off-by: Heinrich Schuchardt heinrich.schuchardt@canonical.com Reviewed-by: Simon Glass sjg@chromium.org
v3: let tables in global data depend on CONFIG_(SPL_)ACPI v2: no change
arch/riscv/include/asm/global_data.h | 6 ++++++ 1 file changed, 6 insertions(+)
Otherwise, Reviewed-by: Bin Meng bmeng.cn@gmail.com

Invoke write_acpi_tables() via EVT_LAST_STAGE_INIT on QEMU except on X86. X86 calls write_acpi_tables() in write_tables().
Signed-off-by: Heinrich Schuchardt heinrich.schuchardt@canonical.com Reviewed-by: Simon Glass sjg@chromium.org --- v3: no change v2: new patch --- drivers/misc/qfw_acpi.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+)
diff --git a/drivers/misc/qfw_acpi.c b/drivers/misc/qfw_acpi.c index 6e14b2a504..7ffed1e8c0 100644 --- a/drivers/misc/qfw_acpi.c +++ b/drivers/misc/qfw_acpi.c @@ -9,9 +9,11 @@ #include <acpi/acpi_table.h> #include <errno.h> #include <malloc.h> +#include <mapmem.h> #include <qfw.h> #include <tables_csum.h> #include <stdio.h> +#include <linux/sizes.h> #include <asm/byteorder.h> #include <asm/global_data.h>
@@ -254,3 +256,26 @@ ulong acpi_get_rsdp_addr(void) file = qfw_find_file(dev, "etc/acpi/rsdp"); return file->addr; } + +#ifndef CONFIG_X86 +static int evt_write_acpi_tables(void) +{ + ulong addr, end; + void *ptr; + + /* Reserve 64K for ACPI tables, aligned to a 4K boundary */ + ptr = memalign(SZ_4K, SZ_64K); + if (!ptr) + return -ENOMEM; + addr = map_to_sysmem(ptr); + + /* Generate ACPI tables */ + end = write_acpi_tables(addr); + gd->arch.table_start = addr; + gd->arch.table_end = addr; + + return 0; +} + +EVENT_SPY_SIMPLE(EVT_LAST_STAGE_INIT, evt_write_acpi_tables); +#endif

Enable the QEMU firmware interface if ACPI tables are to be supported on the QEMU platform.
Enable the QFW MMIO interface if the QEMU firmware interface is enabled.
Signed-off-by: Heinrich Schuchardt heinrich.schuchardt@canonical.com Reviewed-by: Simon Glass sjg@chromium.org Reviewed-by: Ilias Apalodimas ilias.apalodimas@linaro.org --- v3: no change v2: no change --- board/emulation/qemu-riscv/Kconfig | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/board/emulation/qemu-riscv/Kconfig b/board/emulation/qemu-riscv/Kconfig index cdd0d0d95f..d5f302ffda 100644 --- a/board/emulation/qemu-riscv/Kconfig +++ b/board/emulation/qemu-riscv/Kconfig @@ -33,6 +33,8 @@ config BOARD_SPECIFIC_OPTIONS # dummy def_bool y select GENERIC_RISCV select SUPPORT_SPL + select QFW if ACPI + select QFW_MMIO if QFW imply AHCI imply SMP imply BOARD_LATE_INIT

Select CONFIG_SUPPORT_ACPI to allow usage of ACPI tables with RISC-V.
Signed-off-by: Heinrich Schuchardt heinrich.schuchardt@canonical.com Reviewed-by: Simon Glass sjg@chromium.org --- v3: no change v2: no change --- arch/Kconfig | 1 + 1 file changed, 1 insertion(+)
diff --git a/arch/Kconfig b/arch/Kconfig index 2e0528d819..c23d57e4c4 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -108,6 +108,7 @@ config PPC config RISCV bool "RISC-V architecture" select CREATE_ARCH_SYMLINK + select SUPPORT_ACPI select SUPPORT_OF_CONTROL select OF_CONTROL select DM

Provide a configuration fragment to enable ACPI on QEMU.
Signed-off-by: Heinrich Schuchardt heinrich.schuchardt@canonical.com Acked-by: Ilias Apalodimas ilias.apalodimas@linaro.org Reviewed-by: Simon Glass sjg@chromium.org --- v3: no change v2: no change --- MAINTAINERS | 1 + board/emulation/configs/acpi.config | 3 +++ doc/board/emulation/acpi.rst | 23 +++++++++++++++++++++++ doc/board/emulation/index.rst | 1 + 4 files changed, 28 insertions(+) create mode 100644 board/emulation/configs/acpi.config create mode 100644 doc/board/emulation/acpi.rst
diff --git a/MAINTAINERS b/MAINTAINERS index 25f2bb80de..bf437b253b 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -53,6 +53,7 @@ Maintainers List (try to look for most precise areas first) ACPI: M: Simon Glass sjg@chromium.org S: Maintained +F: board/emulation/configs/acpi.config F: cmd/acpi.c F: lib/acpi/
diff --git a/board/emulation/configs/acpi.config b/board/emulation/configs/acpi.config new file mode 100644 index 0000000000..b7ed811e33 --- /dev/null +++ b/board/emulation/configs/acpi.config @@ -0,0 +1,3 @@ +CONFIG_CMD_QFW=y +CONFIG_ACPI=y +CONFIG_GENERATE_ACPI_TABLE=y diff --git a/doc/board/emulation/acpi.rst b/doc/board/emulation/acpi.rst new file mode 100644 index 0000000000..e1208ca51e --- /dev/null +++ b/doc/board/emulation/acpi.rst @@ -0,0 +1,23 @@ +.. SPDX-License-Identifier: GPL-2.0+ + +ACPI on QEMU +============ + +QEMU can provide ACPI tables on ARM, RISC-V, and x86. + +The following settings are needed:: + + CONFIG_CMD_QFW=y + CONFIG_ACPI=y + CONFIG_GENERATE_ACPI_TABLE=y + +On x86 these settings are already included in the defconfig files. ARM and +RISC-V default to use device-trees. + +Instead of updating the configuration manually you can add the configuration +fragment `acpi.config` to the make command for initializing the configuration. +E.g. + +.. code-block:: bash + + make qemu-riscv64_smode_defconfig acpi.config diff --git a/doc/board/emulation/index.rst b/doc/board/emulation/index.rst index 932c65adeb..d3d6b8f3d8 100644 --- a/doc/board/emulation/index.rst +++ b/doc/board/emulation/index.rst @@ -6,6 +6,7 @@ Emulation .. toctree:: :maxdepth: 1
+ acpi blkdev ../../usage/semihosting qemu-arm

Hi Heinrich,
On Tue, Dec 19, 2023 at 8:25 PM Heinrich Schuchardt heinrich.schuchardt@canonical.com wrote:
Provide a configuration fragment to enable ACPI on QEMU.
Signed-off-by: Heinrich Schuchardt heinrich.schuchardt@canonical.com Acked-by: Ilias Apalodimas ilias.apalodimas@linaro.org Reviewed-by: Simon Glass sjg@chromium.org
v3: no change v2: no change
MAINTAINERS | 1 + board/emulation/configs/acpi.config | 3 +++ doc/board/emulation/acpi.rst | 23 +++++++++++++++++++++++ doc/board/emulation/index.rst | 1 + 4 files changed, 28 insertions(+) create mode 100644 board/emulation/configs/acpi.config create mode 100644 doc/board/emulation/acpi.rst
diff --git a/MAINTAINERS b/MAINTAINERS index 25f2bb80de..bf437b253b 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -53,6 +53,7 @@ Maintainers List (try to look for most precise areas first) ACPI: M: Simon Glass sjg@chromium.org S: Maintained +F: board/emulation/configs/acpi.config F: cmd/acpi.c F: lib/acpi/
diff --git a/board/emulation/configs/acpi.config b/board/emulation/configs/acpi.config new file mode 100644 index 0000000000..b7ed811e33 --- /dev/null +++ b/board/emulation/configs/acpi.config @@ -0,0 +1,3 @@ +CONFIG_CMD_QFW=y +CONFIG_ACPI=y +CONFIG_GENERATE_ACPI_TABLE=y diff --git a/doc/board/emulation/acpi.rst b/doc/board/emulation/acpi.rst new file mode 100644 index 0000000000..e1208ca51e --- /dev/null +++ b/doc/board/emulation/acpi.rst @@ -0,0 +1,23 @@ +.. SPDX-License-Identifier: GPL-2.0+
+ACPI on QEMU +============
+QEMU can provide ACPI tables on ARM, RISC-V, and x86.
ACPI support on RISC-V landed on QEMU in a pretty recent version. Would you mind documenting its version?
I haven't checked QEMU yet. Is ACPI default on in QEMU for Arm and RISC-V virt? If not, we should document QEMU commands to enable ACPI.
+The following settings are needed::
- CONFIG_CMD_QFW=y
- CONFIG_ACPI=y
- CONFIG_GENERATE_ACPI_TABLE=y
+On x86 these settings are already included in the defconfig files. ARM and +RISC-V default to use device-trees.
+Instead of updating the configuration manually you can add the configuration +fragment `acpi.config` to the make command for initializing the configuration. +E.g.
+.. code-block:: bash
- make qemu-riscv64_smode_defconfig acpi.config
diff --git a/doc/board/emulation/index.rst b/doc/board/emulation/index.rst index 932c65adeb..d3d6b8f3d8 100644 --- a/doc/board/emulation/index.rst +++ b/doc/board/emulation/index.rst @@ -6,6 +6,7 @@ Emulation .. toctree:: :maxdepth: 1
- acpi blkdev ../../usage/semihosting qemu-arm
--
Regards, Bin

On 12/19/23 14:41, Bin Meng wrote:
Hi Heinrich,
On Tue, Dec 19, 2023 at 8:25 PM Heinrich Schuchardt heinrich.schuchardt@canonical.com wrote:
Provide a configuration fragment to enable ACPI on QEMU.
Signed-off-by: Heinrich Schuchardt heinrich.schuchardt@canonical.com Acked-by: Ilias Apalodimas ilias.apalodimas@linaro.org Reviewed-by: Simon Glass sjg@chromium.org
v3: no change v2: no change
MAINTAINERS | 1 + board/emulation/configs/acpi.config | 3 +++ doc/board/emulation/acpi.rst | 23 +++++++++++++++++++++++ doc/board/emulation/index.rst | 1 + 4 files changed, 28 insertions(+) create mode 100644 board/emulation/configs/acpi.config create mode 100644 doc/board/emulation/acpi.rst
diff --git a/MAINTAINERS b/MAINTAINERS index 25f2bb80de..bf437b253b 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -53,6 +53,7 @@ Maintainers List (try to look for most precise areas first) ACPI: M: Simon Glass sjg@chromium.org S: Maintained +F: board/emulation/configs/acpi.config F: cmd/acpi.c F: lib/acpi/
diff --git a/board/emulation/configs/acpi.config b/board/emulation/configs/acpi.config new file mode 100644 index 0000000000..b7ed811e33 --- /dev/null +++ b/board/emulation/configs/acpi.config @@ -0,0 +1,3 @@ +CONFIG_CMD_QFW=y +CONFIG_ACPI=y +CONFIG_GENERATE_ACPI_TABLE=y diff --git a/doc/board/emulation/acpi.rst b/doc/board/emulation/acpi.rst new file mode 100644 index 0000000000..e1208ca51e --- /dev/null +++ b/doc/board/emulation/acpi.rst @@ -0,0 +1,23 @@ +.. SPDX-License-Identifier: GPL-2.0+
+ACPI on QEMU +============
+QEMU can provide ACPI tables on ARM, RISC-V, and x86.
ACPI support on RISC-V landed on QEMU in a pretty recent version. Would you mind documenting its version?
7da2fb240f97 ("hw/riscv/virt: Enable basic ACPI infrastructure") appeared first in QEMU v8.0.0.
f5d8c8cd792b ("hw/arm/virt-acpi-build: Basic framework for building ACPI tables on ARM") made it into QEMU v2.4.0
I haven't checked QEMU yet. Is ACPI default on in QEMU for Arm and RISC-V virt? If not, we should document QEMU commands to enable ACPI.
It is enabled by default in the virt machine. You can switch it off with '-M virt,acpi=off'. See
[PATCH 1/1] docs/system/riscv: document acpi parameter of virt machine https://lore.kernel.org/qemu-devel/20231219143829.8961-1-heinrich.schuchardt...
Best regards
Heinrich
+The following settings are needed::
- CONFIG_CMD_QFW=y
- CONFIG_ACPI=y
- CONFIG_GENERATE_ACPI_TABLE=y
+On x86 these settings are already included in the defconfig files. ARM and +RISC-V default to use device-trees.
+Instead of updating the configuration manually you can add the configuration +fragment `acpi.config` to the make command for initializing the configuration. +E.g.
+.. code-block:: bash
- make qemu-riscv64_smode_defconfig acpi.config
diff --git a/doc/board/emulation/index.rst b/doc/board/emulation/index.rst index 932c65adeb..d3d6b8f3d8 100644 --- a/doc/board/emulation/index.rst +++ b/doc/board/emulation/index.rst @@ -6,6 +6,7 @@ Emulation .. toctree:: :maxdepth: 1
- acpi blkdev ../../usage/semihosting qemu-arm
--
Regards, Bin

Enable the QEMU firmware interface if ACPI tables are to be supported on the QEMU platform.
Signed-off-by: Heinrich Schuchardt heinrich.schuchardt@canonical.com Reviewed-by: Simon Glass sjg@chromium.org --- v3: no change v2: new patch --- board/emulation/qemu-arm/Kconfig | 1 + 1 file changed, 1 insertion(+)
diff --git a/board/emulation/qemu-arm/Kconfig b/board/emulation/qemu-arm/Kconfig index ac2d078f42..e21c135e86 100644 --- a/board/emulation/qemu-arm/Kconfig +++ b/board/emulation/qemu-arm/Kconfig @@ -5,6 +5,7 @@ config TEXT_BASE
config BOARD_SPECIFIC_OPTIONS # dummy def_bool y + select QFW if ACPI select QFW_MMIO if CMD_QFW imply VIRTIO_MMIO imply VIRTIO_PCI
participants (3)
-
Bin Meng
-
Heinrich Schuchardt
-
Simon Glass