diff options
28 files changed, 651 insertions, 312 deletions
diff --git a/hw/arm/bcm2835_peripherals.c b/hw/arm/bcm2835_peripherals.c index a9d7f53f6e..15c5c72e46 100644 --- a/hw/arm/bcm2835_peripherals.c +++ b/hw/arm/bcm2835_peripherals.c @@ -343,6 +343,7 @@ static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp) qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ, INTERRUPT_USB)); + create_unimp(s, &s->txp, "bcm2835-txp", TXP_OFFSET, 0x1000); create_unimp(s, &s->armtmr, "bcm2835-sp804", ARMCTRL_TIMER0_1_OFFSET, 0x40); create_unimp(s, &s->cprman, "bcm2835-cprman", CPRMAN_OFFSET, 0x1000); create_unimp(s, &s->a2w, "bcm2835-a2w", A2W_OFFSET, 0x1000); @@ -356,6 +357,7 @@ static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp) create_unimp(s, &s->otp, "bcm2835-otp", OTP_OFFSET, 0x80); create_unimp(s, &s->dbus, "bcm2835-dbus", DBUS_OFFSET, 0x8000); create_unimp(s, &s->ave0, "bcm2835-ave0", AVE0_OFFSET, 0x8000); + create_unimp(s, &s->v3d, "bcm2835-v3d", V3D_OFFSET, 0x1000); create_unimp(s, &s->sdramc, "bcm2835-sdramc", SDRAMC_OFFSET, 0x100); } diff --git a/hw/arm/raspi.c b/hw/arm/raspi.c index d2f674587d..b5b30f0f38 100644 --- a/hw/arm/raspi.c +++ b/hw/arm/raspi.c @@ -41,6 +41,7 @@ struct RaspiMachineState { MachineState parent_obj; /*< public >*/ BCM283XState soc; + struct arm_boot_info binfo; }; typedef struct RaspiMachineState RaspiMachineState; @@ -68,51 +69,43 @@ FIELD(REV_CODE, MANUFACTURER, 16, 4); FIELD(REV_CODE, MEMORY_SIZE, 20, 3); FIELD(REV_CODE, STYLE, 23, 1); +typedef enum RaspiProcessorId { + PROCESSOR_ID_BCM2836 = 1, + PROCESSOR_ID_BCM2837 = 2, +} RaspiProcessorId; + +static const struct { + const char *type; + int cores_count; +} soc_property[] = { + [PROCESSOR_ID_BCM2836] = {TYPE_BCM2836, BCM283X_NCPUS}, + [PROCESSOR_ID_BCM2837] = {TYPE_BCM2837, BCM283X_NCPUS}, +}; + static uint64_t board_ram_size(uint32_t board_rev) { assert(FIELD_EX32(board_rev, REV_CODE, STYLE)); /* Only new style */ return 256 * MiB << FIELD_EX32(board_rev, REV_CODE, MEMORY_SIZE); } -static int board_processor_id(uint32_t board_rev) +static RaspiProcessorId board_processor_id(uint32_t board_rev) { + int proc_id = FIELD_EX32(board_rev, REV_CODE, PROCESSOR); + assert(FIELD_EX32(board_rev, REV_CODE, STYLE)); /* Only new style */ - return FIELD_EX32(board_rev, REV_CODE, PROCESSOR); -} + assert(proc_id < ARRAY_SIZE(soc_property) && soc_property[proc_id].type); -static int board_version(uint32_t board_rev) -{ - return board_processor_id(board_rev) + 1; + return proc_id; } static const char *board_soc_type(uint32_t board_rev) { - static const char *soc_types[] = { - NULL, TYPE_BCM2836, TYPE_BCM2837, - }; - int proc_id = board_processor_id(board_rev); - - if (proc_id >= ARRAY_SIZE(soc_types) || !soc_types[proc_id]) { - error_report("Unsupported processor id '%d' (board revision: 0x%x)", - proc_id, board_rev); - exit(1); - } - return soc_types[proc_id]; + return soc_property[board_processor_id(board_rev)].type; } static int cores_count(uint32_t board_rev) { - static const int soc_cores_count[] = { - 0, BCM283X_NCPUS, BCM283X_NCPUS, - }; - int proc_id = board_processor_id(board_rev); - - if (proc_id >= ARRAY_SIZE(soc_cores_count) || !soc_cores_count[proc_id]) { - error_report("Unsupported processor id '%d' (board revision: 0x%x)", - proc_id, board_rev); - exit(1); - } - return soc_cores_count[proc_id]; + return soc_property[board_processor_id(board_rev)].cores_count; } static const char *board_type(uint32_t board_rev) @@ -203,44 +196,47 @@ static void reset_secondary(ARMCPU *cpu, const struct arm_boot_info *info) cpu_set_pc(cs, info->smp_loader_start); } -static void setup_boot(MachineState *machine, int version, size_t ram_size) +static void setup_boot(MachineState *machine, RaspiProcessorId processor_id, + size_t ram_size) { - static struct arm_boot_info binfo; + RaspiMachineState *s = RASPI_MACHINE(machine); int r; - binfo.board_id = MACH_TYPE_BCM2708; - binfo.ram_size = ram_size; - binfo.nb_cpus = machine->smp.cpus; + s->binfo.board_id = MACH_TYPE_BCM2708; + s->binfo.ram_size = ram_size; + s->binfo.nb_cpus = machine->smp.cpus; - if (version <= 2) { - /* The rpi1 and 2 require some custom setup code to run in Secure - * mode before booting a kernel (to set up the SMC vectors so - * that we get a no-op SMC; this is used by Linux to call the + if (processor_id <= PROCESSOR_ID_BCM2836) { + /* + * The BCM2835 and BCM2836 require some custom setup code to run + * in Secure mode before booting a kernel (to set up the SMC vectors + * so that we get a no-op SMC; this is used by Linux to call the * firmware for some cache maintenance operations. - * The rpi3 doesn't need this. + * The BCM2837 doesn't need this. */ - binfo.board_setup_addr = BOARDSETUP_ADDR; - binfo.write_board_setup = write_board_setup; - binfo.secure_board_setup = true; - binfo.secure_boot = true; + s->binfo.board_setup_addr = BOARDSETUP_ADDR; + s->binfo.write_board_setup = write_board_setup; + s->binfo.secure_board_setup = true; + s->binfo.secure_boot = true; } - /* Pi2 and Pi3 requires SMP setup */ - if (version >= 2) { - binfo.smp_loader_start = SMPBOOT_ADDR; - if (version == 2) { - binfo.write_secondary_boot = write_smpboot; + /* BCM2836 and BCM2837 requires SMP setup */ + if (processor_id >= PROCESSOR_ID_BCM2836) { + s->binfo.smp_loader_start = SMPBOOT_ADDR; + if (processor_id == PROCESSOR_ID_BCM2836) { + s->binfo.write_secondary_boot = write_smpboot; } else { - binfo.write_secondary_boot = write_smpboot64; + s->binfo.write_secondary_boot = write_smpboot64; } - binfo.secondary_cpu_reset_hook = reset_secondary; + s->binfo.secondary_cpu_reset_hook = reset_secondary; } /* If the user specified a "firmware" image (e.g. UEFI), we bypass * the normal Linux boot process */ if (machine->firmware) { - hwaddr firmware_addr = version == 3 ? FIRMWARE_ADDR_3 : FIRMWARE_ADDR_2; + hwaddr firmware_addr = processor_id <= PROCESSOR_ID_BCM2836 + ? FIRMWARE_ADDR_2 : FIRMWARE_ADDR_3; /* load the firmware image (typically kernel.img) */ r = load_image_targphys(machine->firmware, firmware_addr, ram_size - firmware_addr); @@ -249,11 +245,11 @@ static void setup_boot(MachineState *machine, int version, size_t ram_size) exit(1); } - binfo.entry = firmware_addr; - binfo.firmware_loaded = true; + s->binfo.entry = firmware_addr; + s->binfo.firmware_loaded = true; } - arm_load_kernel(ARM_CPU(first_cpu), machine, &binfo); + arm_load_kernel(&s->soc.cpu[0].core, machine, &s->binfo); } static void raspi_machine_init(MachineState *machine) @@ -261,7 +257,6 @@ static void raspi_machine_init(MachineState *machine) RaspiMachineClass *mc = RASPI_MACHINE_GET_CLASS(machine); RaspiMachineState *s = RASPI_MACHINE(machine); uint32_t board_rev = mc->board_rev; - int version = board_version(board_rev); uint64_t ram_size = board_ram_size(board_rev); uint32_t vcram_size; DriveInfo *di; @@ -302,17 +297,16 @@ static void raspi_machine_init(MachineState *machine) vcram_size = object_property_get_uint(OBJECT(&s->soc), "vcram-size", &error_abort); - setup_boot(machine, version, machine->ram_size - vcram_size); + setup_boot(machine, board_processor_id(mc->board_rev), + machine->ram_size - vcram_size); } -static void raspi_machine_class_init(ObjectClass *oc, void *data) +static void raspi_machine_class_common_init(MachineClass *mc, + uint32_t board_rev) { - MachineClass *mc = MACHINE_CLASS(oc); - RaspiMachineClass *rmc = RASPI_MACHINE_CLASS(oc); - uint32_t board_rev = (uint32_t)(uintptr_t)data; - - rmc->board_rev = board_rev; - mc->desc = g_strdup_printf("Raspberry Pi %s", board_type(board_rev)); + mc->desc = g_strdup_printf("Raspberry Pi %s (revision 1.%u)", + board_type(board_rev), + FIELD_EX32(board_rev, REV_CODE, REVISION)); mc->init = raspi_machine_init; mc->block_default_type = IF_SD; mc->no_parallel = 1; @@ -321,23 +315,40 @@ static void raspi_machine_class_init(ObjectClass *oc, void *data) mc->default_cpus = mc->min_cpus = mc->max_cpus = cores_count(board_rev); mc->default_ram_size = board_ram_size(board_rev); mc->default_ram_id = "ram"; - if (board_version(board_rev) == 2) { - mc->ignore_memory_transaction_failures = true; - } }; +static void raspi2b_machine_class_init(ObjectClass *oc, void *data) +{ + MachineClass *mc = MACHINE_CLASS(oc); + RaspiMachineClass *rmc = RASPI_MACHINE_CLASS(oc); + + mc->alias = "raspi2"; + rmc->board_rev = 0xa21041; + raspi_machine_class_common_init(mc, rmc->board_rev); +}; + +#ifdef TARGET_AARCH64 +static void raspi3b_machine_class_init(ObjectClass *oc, void *data) +{ + MachineClass *mc = MACHINE_CLASS(oc); + RaspiMachineClass *rmc = RASPI_MACHINE_CLASS(oc); + + mc->alias = "raspi3"; + rmc->board_rev = 0xa02082; + raspi_machine_class_common_init(mc, rmc->board_rev); +}; +#endif /* TARGET_AARCH64 */ + static const TypeInfo raspi_machine_types[] = { { - .name = MACHINE_TYPE_NAME("raspi2"), + .name = MACHINE_TYPE_NAME("raspi2b"), .parent = TYPE_RASPI_MACHINE, - .class_init = raspi_machine_class_init, - .class_data = (void *)0xa21041, + .class_init = raspi2b_machine_class_init, #ifdef TARGET_AARCH64 }, { - .name = MACHINE_TYPE_NAME("raspi3"), + .name = MACHINE_TYPE_NAME("raspi3b"), .parent = TYPE_RASPI_MACHINE, - .class_init = raspi_machine_class_init, - .class_data = (void *)0xa02082, + .class_init = raspi3b_machine_class_init, #endif }, { .name = TYPE_RASPI_MACHINE, diff --git a/hw/arm/sbsa-ref.c b/hw/arm/sbsa-ref.c index 257ada9425..9c3a893bed 100644 --- a/hw/arm/sbsa-ref.c +++ b/hw/arm/sbsa-ref.c @@ -80,11 +80,6 @@ enum { SBSA_EHCI, }; -typedef struct MemMapEntry { - hwaddr base; - hwaddr size; -} MemMapEntry; - struct SBSAMachineState { MachineState parent; struct arm_boot_info bootinfo; diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c index 6bff5e3738..9747a6458f 100644 --- a/hw/arm/virt-acpi-build.c +++ b/hw/arm/virt-acpi-build.c @@ -44,6 +44,7 @@ #include "hw/acpi/tpm.h" #include "hw/pci/pcie_host.h" #include "hw/pci/pci.h" +#include "hw/pci-host/gpex.h" #include "hw/arm/virt.h" #include "hw/mem/nvdimm.h" #include "hw/platform-bus.h" @@ -155,176 +156,18 @@ static void acpi_dsdt_add_pci(Aml *scope, const MemMapEntry *memmap, uint32_t irq, bool use_highmem, bool highmem_ecam) { int ecam_id = VIRT_ECAM_ID(highmem_ecam); - Aml *method, *crs, *ifctx, *UUID, *ifctx1, *elsectx, *buf; - int i, slot_no; - hwaddr base_mmio = memmap[VIRT_PCIE_MMIO].base; - hwaddr size_mmio = memmap[VIRT_PCIE_MMIO].size; - hwaddr base_pio = memmap[VIRT_PCIE_PIO].base; - hwaddr size_pio = memmap[VIRT_PCIE_PIO].size; - hwaddr base_ecam = memmap[ecam_id].base; - hwaddr size_ecam = memmap[ecam_id].size; - int nr_pcie_buses = size_ecam / PCIE_MMCFG_SIZE_MIN; - - Aml *dev = aml_device("%s", "PCI0"); - aml_append(dev, aml_name_decl("_HID", aml_string("PNP0A08"))); - aml_append(dev, aml_name_decl("_CID", aml_string("PNP0A03"))); - aml_append(dev, aml_name_decl("_SEG", aml_int(0))); - aml_append(dev, aml_name_decl("_BBN", aml_int(0))); - aml_append(dev, aml_name_decl("_UID", aml_int(0))); - aml_append(dev, aml_name_decl("_STR", aml_unicode("PCIe 0 Device"))); - aml_append(dev, aml_name_decl("_CCA", aml_int(1))); - - /* Declare the PCI Routing Table. */ - Aml *rt_pkg = aml_varpackage(PCI_SLOT_MAX * PCI_NUM_PINS); - for (slot_no = 0; slot_no < PCI_SLOT_MAX; slot_no++) { - for (i = 0; i < PCI_NUM_PINS; i++) { - int gsi = (i + slot_no) % PCI_NUM_PINS; - Aml *pkg = aml_package(4); - aml_append(pkg, aml_int((slot_no << 16) | 0xFFFF)); - aml_append(pkg, aml_int(i)); - aml_append(pkg, aml_name("GSI%d", gsi)); - aml_append(pkg, aml_int(0)); - aml_append(rt_pkg, pkg); - } - } - aml_append(dev, aml_name_decl("_PRT", rt_pkg)); - - /* Create GSI link device */ - for (i = 0; i < PCI_NUM_PINS; i++) { - uint32_t irqs = irq + i; - Aml *dev_gsi = aml_device("GSI%d", i); - aml_append(dev_gsi, aml_name_decl("_HID", aml_string("PNP0C0F"))); - aml_append(dev_gsi, aml_name_decl("_UID", aml_int(i))); - crs = aml_resource_template(); - aml_append(crs, - aml_interrupt(AML_CONSUMER, AML_LEVEL, AML_ACTIVE_HIGH, - AML_EXCLUSIVE, &irqs, 1)); - aml_append(dev_gsi, aml_name_decl("_PRS", crs)); - crs = aml_resource_template(); - aml_append(crs, - aml_interrupt(AML_CONSUMER, AML_LEVEL, AML_ACTIVE_HIGH, - AML_EXCLUSIVE, &irqs, 1)); - aml_append(dev_gsi, aml_name_decl("_CRS", crs)); - method = aml_method("_SRS", 1, AML_NOTSERIALIZED); - aml_append(dev_gsi, method); - aml_append(dev, dev_gsi); - } - - method = aml_method("_CBA", 0, AML_NOTSERIALIZED); - aml_append(method, aml_return(aml_int(base_ecam))); - aml_append(dev, method); - - method = aml_method("_CRS", 0, AML_NOTSERIALIZED); - Aml *rbuf = aml_resource_template(); - aml_append(rbuf, - aml_word_bus_number(AML_MIN_FIXED, AML_MAX_FIXED, AML_POS_DECODE, - 0x0000, 0x0000, nr_pcie_buses - 1, 0x0000, - nr_pcie_buses)); - aml_append(rbuf, - aml_dword_memory(AML_POS_DECODE, AML_MIN_FIXED, AML_MAX_FIXED, - AML_NON_CACHEABLE, AML_READ_WRITE, 0x0000, base_mmio, - base_mmio + size_mmio - 1, 0x0000, size_mmio)); - aml_append(rbuf, - aml_dword_io(AML_MIN_FIXED, AML_MAX_FIXED, AML_POS_DECODE, - AML_ENTIRE_RANGE, 0x0000, 0x0000, size_pio - 1, base_pio, - size_pio)); + struct GPEXConfig cfg = { + .mmio32 = memmap[VIRT_PCIE_MMIO], + .pio = memmap[VIRT_PCIE_PIO], + .ecam = memmap[ecam_id], + .irq = irq, + }; if (use_highmem) { - hwaddr base_mmio_high = memmap[VIRT_HIGH_PCIE_MMIO].base; - hwaddr size_mmio_high = memmap[VIRT_HIGH_PCIE_MMIO].size; - - aml_append(rbuf, - aml_qword_memory(AML_POS_DECODE, AML_MIN_FIXED, AML_MAX_FIXED, - AML_NON_CACHEABLE, AML_READ_WRITE, 0x0000, - base_mmio_high, - base_mmio_high + size_mmio_high - 1, 0x0000, - size_mmio_high)); + cfg.mmio64 = memmap[VIRT_HIGH_PCIE_MMIO]; } - aml_append(method, aml_return(rbuf)); - aml_append(dev, method); - - /* Declare an _OSC (OS Control Handoff) method */ - aml_append(dev, aml_name_decl("SUPP", aml_int(0))); - aml_append(dev, aml_name_decl("CTRL", aml_int(0))); - method = aml_method("_OSC", 4, AML_NOTSERIALIZED); - aml_append(method, - aml_create_dword_field(aml_arg(3), aml_int(0), "CDW1")); - - /* PCI Firmware Specification 3.0 - * 4.5.1. _OSC Interface for PCI Host Bridge Devices - * The _OSC interface for a PCI/PCI-X/PCI Express hierarchy is - * identified by the Universal Unique IDentifier (UUID) - * 33DB4D5B-1FF7-401C-9657-7441C03DD766 - */ - UUID = aml_touuid("33DB4D5B-1FF7-401C-9657-7441C03DD766"); - ifctx = aml_if(aml_equal(aml_arg(0), UUID)); - aml_append(ifctx, - aml_create_dword_field(aml_arg(3), aml_int(4), "CDW2")); - aml_append(ifctx, - aml_create_dword_field(aml_arg(3), aml_int(8), "CDW3")); - aml_append(ifctx, aml_store(aml_name("CDW2"), aml_name("SUPP"))); - aml_append(ifctx, aml_store(aml_name("CDW3"), aml_name("CTRL"))); - - /* - * Allow OS control for all 5 features: - * PCIeHotplug SHPCHotplug PME AER PCIeCapability. - */ - aml_append(ifctx, aml_and(aml_name("CTRL"), aml_int(0x1F), - aml_name("CTRL"))); - - ifctx1 = aml_if(aml_lnot(aml_equal(aml_arg(1), aml_int(0x1)))); - aml_append(ifctx1, aml_or(aml_name("CDW1"), aml_int(0x08), - aml_name("CDW1"))); - aml_append(ifctx, ifctx1); - - ifctx1 = aml_if(aml_lnot(aml_equal(aml_name("CDW3"), aml_name("CTRL")))); - aml_append(ifctx1, aml_or(aml_name("CDW1"), aml_int(0x10), - aml_name("CDW1"))); - aml_append(ifctx, ifctx1); - - aml_append(ifctx, aml_store(aml_name("CTRL"), aml_name("CDW3"))); - aml_append(ifctx, aml_return(aml_arg(3))); - aml_append(method, ifctx); - - elsectx = aml_else(); - aml_append(elsectx, aml_or(aml_name("CDW1"), aml_int(4), - aml_name("CDW1"))); - aml_append(elsectx, aml_return(aml_arg(3))); - aml_append(method, elsectx); - aml_append(dev, method); - - method = aml_method("_DSM", 4, AML_NOTSERIALIZED); - - /* PCI Firmware Specification 3.0 - * 4.6.1. _DSM for PCI Express Slot Information - * The UUID in _DSM in this context is - * {E5C937D0-3553-4D7A-9117-EA4D19C3434D} - */ - UUID = aml_touuid("E5C937D0-3553-4D7A-9117-EA4D19C3434D"); - ifctx = aml_if(aml_equal(aml_arg(0), UUID)); - ifctx1 = aml_if(aml_equal(aml_arg(2), aml_int(0))); - uint8_t byte_list[1] = {1}; - buf = aml_buffer(1, byte_list); - aml_append(ifctx1, aml_return(buf)); - aml_append(ifctx, ifctx1); - aml_append(method, ifctx); - - byte_list[0] = 0; - buf = aml_buffer(1, byte_list); - aml_append(method, aml_return(buf)); - aml_append(dev, method); - - Aml *dev_res0 = aml_device("%s", "RES0"); - aml_append(dev_res0, aml_name_decl("_HID", aml_string("PNP0C02"))); - crs = aml_resource_template(); - aml_append(crs, - aml_qword_memory(AML_POS_DECODE, AML_MIN_FIXED, AML_MAX_FIXED, - AML_NON_CACHEABLE, AML_READ_WRITE, 0x0000, base_ecam, - base_ecam + size_ecam - 1, 0x0000, size_ecam)); - aml_append(dev_res0, aml_name_decl("_CRS", crs)); - aml_append(dev, dev_res0); - aml_append(scope, dev); + acpi_dsdt_add_gpex(scope, &cfg); } static void acpi_dsdt_add_gpio(Aml *scope, const MemMapEntry *gpio_memmap, diff --git a/hw/i386/Kconfig b/hw/i386/Kconfig index d0bd8b537d..32aa15533b 100644 --- a/hw/i386/Kconfig +++ b/hw/i386/Kconfig @@ -104,6 +104,7 @@ config MICROVM select MC146818RTC select VIRTIO_MMIO select ACPI_HW_REDUCED + select PCI_EXPRESS_GENERIC_BRIDGE config X86_IOMMU bool diff --git a/hw/i386/acpi-microvm.c b/hw/i386/acpi-microvm.c index df39c5d3bd..f16f231195 100644 --- a/hw/i386/acpi-microvm.c +++ b/hw/i386/acpi-microvm.c @@ -33,6 +33,8 @@ #include "hw/boards.h" #include "hw/i386/fw_cfg.h" #include "hw/i386/microvm.h" +#include "hw/pci/pci.h" +#include "hw/pci/pcie_host.h" #include "hw/virtio/virtio-mmio.h" #include "acpi-common.h" @@ -87,6 +89,15 @@ static void acpi_dsdt_add_virtio(Aml *scope, } } +static void acpi_dsdt_add_pci(Aml *scope, MicrovmMachineState *mms) +{ + if (mms->pcie != ON_OFF_AUTO_ON) { + return; + } + + acpi_dsdt_add_gpex(scope, &mms->gpex); +} + static void build_dsdt_microvm(GArray *table_data, BIOSLinker *linker, MicrovmMachineState *mms) @@ -112,6 +123,7 @@ build_dsdt_microvm(GArray *table_data, BIOSLinker *linker, GED_MMIO_IRQ, AML_SYSTEM_MEMORY, GED_MMIO_BASE); acpi_dsdt_add_power_button(sb_scope); acpi_dsdt_add_virtio(sb_scope, mms); + acpi_dsdt_add_pci(sb_scope, mms); aml_append(dsdt, sb_scope); /* ACPI 5.0: Table 7-209 System State Package */ diff --git a/hw/i386/microvm.c b/hw/i386/microvm.c index aedcae3426..73a7a142b4 100644 --- a/hw/i386/microvm.c +++ b/hw/i386/microvm.c @@ -46,6 +46,7 @@ #include "hw/virtio/virtio-mmio.h" #include "hw/acpi/acpi.h" #include "hw/acpi/generic_event_device.h" +#include "hw/pci-host/gpex.h" #include "cpu.h" #include "elf.h" @@ -101,6 +102,55 @@ static void microvm_gsi_handler(void *opaque, int n, int level) qemu_set_irq(s->ioapic_irq[n], level); } +static void create_gpex(MicrovmMachineState *mms) +{ + X86MachineState *x86ms = X86_MACHINE(mms); + MemoryRegion *mmio32_alias; + MemoryRegion *mmio64_alias; + MemoryRegion *mmio_reg; + MemoryRegion *ecam_alias; + MemoryRegion *ecam_reg; + DeviceState *dev; + int i; + + dev = qdev_new(TYPE_GPEX_HOST); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); + + /* Map only the first size_ecam bytes of ECAM space */ + ecam_alias = g_new0(MemoryRegion, 1); + ecam_reg = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0); + memory_region_init_alias(ecam_alias, OBJECT(dev), "pcie-ecam", + ecam_reg, 0, mms->gpex.ecam.size); + memory_region_add_subregion(get_system_memory(), + mms->gpex.ecam.base, ecam_alias); + + /* Map the MMIO window into system address space so as to expose + * the section of PCI MMIO space which starts at the same base address + * (ie 1:1 mapping for that part of PCI MMIO space visible through + * the window). + */ + mmio_reg = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 1); + if (mms->gpex.mmio32.size) { + mmio32_alias = g_new0(MemoryRegion, 1); + memory_region_init_alias(mmio32_alias, OBJECT(dev), "pcie-mmio32", mmio_reg, + mms->gpex.mmio32.base, mms->gpex.mmio32.size); + memory_region_add_subregion(get_system_memory(), + mms->gpex.mmio32.base, mmio32_alias); + } + if (mms->gpex.mmio64.size) { + mmio64_alias = g_new0(MemoryRegion, 1); + memory_region_init_alias(mmio64_alias, OBJECT(dev), "pcie-mmio64", mmio_reg, + mms->gpex.mmio64.base, mms->gpex.mmio64.size); + memory_region_add_subregion(get_system_memory(), + mms->gpex.mmio64.base, mmio64_alias); + } + + for (i = 0; i < GPEX_NUM_IRQS; i++) { + sysbus_connect_irq(SYS_BUS_DEVICE(dev), i, + x86ms->gsi[mms->gpex.irq + i]); + } +} + static void microvm_devices_init(MicrovmMachineState *mms) { X86MachineState *x86ms = X86_MACHINE(mms); @@ -147,6 +197,21 @@ static void microvm_devices_init(MicrovmMachineState *mms) x86ms->acpi_dev = HOTPLUG_HANDLER(dev); } + if (x86_machine_is_acpi_enabled(x86ms) && mms->pcie == ON_OFF_AUTO_ON) { + /* use topmost 25% of the address space available */ + hwaddr phys_size = (hwaddr)1 << X86_CPU(first_cpu)->phys_bits; + if (phys_size > 0x1000000ll) { + mms->gpex.mmio64.size = phys_size / 4; + mms->gpex.mmio64.base = phys_size - mms->gpex.mmio64.size; + } + mms->gpex.mmio32.base = PCIE_MMIO_BASE; + mms->gpex.mmio32.size = PCIE_MMIO_SIZE; + mms->gpex.ecam.base = PCIE_ECAM_BASE; + mms->gpex.ecam.size = PCIE_ECAM_SIZE; + mms->gpex.irq = PCIE_IRQ_BASE; + create_gpex(mms); + } + if (mms->pic == ON_OFF_AUTO_ON || mms->pic == ON_OFF_AUTO_AUTO) { qemu_irq *i8259; @@ -324,6 +389,9 @@ static void microvm_fix_kernel_cmdline(MachineState *machine) static void microvm_device_pre_plug_cb(HotplugHandler *hotplug_dev, DeviceState *dev, Error **errp) { + X86CPU *cpu = X86_CPU(dev); + + cpu->host_phys_bits = true; /* need reliable phys-bits */ x86_cpu_pre_plug(hotplug_dev, dev, errp); } @@ -446,6 +514,23 @@ static void microvm_machine_set_rtc(Object *obj, Visitor *v, const char *name, visit_type_OnOffAuto(v, name, &mms->rtc, errp); } +static void microvm_machine_get_pcie(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + MicrovmMachineState *mms = MICROVM_MACHINE(obj); + OnOffAuto pcie = mms->pcie; + + visit_type_OnOffAuto(v, name, &pcie, errp); +} + +static void microvm_machine_set_pcie(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + MicrovmMachineState *mms = MICROVM_MACHINE(obj); + + visit_type_OnOffAuto(v, name, &mms->pcie, errp); +} + static bool microvm_machine_get_isa_serial(Object *obj, Error **errp) { MicrovmMachineState *mms = MICROVM_MACHINE(obj); @@ -521,6 +606,7 @@ static void microvm_machine_initfn(Object *obj) mms->pic = ON_OFF_AUTO_AUTO; mms->pit = ON_OFF_AUTO_AUTO; mms->rtc = ON_OFF_AUTO_AUTO; + mms->pcie = ON_OFF_AUTO_AUTO; mms->isa_serial = true; mms->option_roms = true; mms->auto_kernel_cmdline = true; @@ -587,6 +673,13 @@ static void microvm_class_init(ObjectClass *oc, void *data) object_class_property_set_description(oc, MICROVM_MACHINE_RTC, "Enable MC146818 RTC"); + object_class_property_add(oc, MICROVM_MACHINE_PCIE, "OnOffAuto", + microvm_machine_get_pcie, + microvm_machine_set_pcie, + NULL, NULL); + object_class_property_set_description(oc, MICROVM_MACHINE_PCIE, + "Enable PCIe"); + object_class_property_add_bool(oc, MICROVM_MACHINE_ISA_SERIAL, microvm_machine_get_isa_serial, microvm_machine_set_isa_serial); diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c index 7876c1ba07..42b1ad59e6 100644 --- a/hw/intc/armv7m_nvic.c +++ b/hw/intc/armv7m_nvic.c @@ -1238,32 +1238,74 @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs) "Aux Fault status registers unimplemented\n"); return 0; case 0xd40: /* PFR0. */ - return cpu->id_pfr0; + if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) { + goto bad_offset; + } + return cpu->isar.id_pfr0; case 0xd44: /* PFR1. */ - return cpu->id_pfr1; + if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) { + goto bad_offset; + } + return cpu->isar.id_pfr1; case 0xd48: /* DFR0. */ + if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) { + goto bad_offset; + } return cpu->isar.id_dfr0; case 0xd4c: /* AFR0. */ + if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) { + goto bad_offset; + } return cpu->id_afr0; case 0xd50: /* MMFR0. */ + if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) { + goto bad_offset; + } return cpu->isar.id_mmfr0; case 0xd54: /* MMFR1. */ + if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) { + goto bad_offset; + } return cpu->isar.id_mmfr1; case 0xd58: /* MMFR2. */ + if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) { + goto bad_offset; + } return cpu->isar.id_mmfr2; case 0xd5c: /* MMFR3. */ + if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) { + goto bad_offset; + } return cpu->isar.id_mmfr3; case 0xd60: /* ISAR0. */ + if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) { + goto bad_offset; + } return cpu->isar.id_isar0; case 0xd64: /* ISAR1. */ + if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) { + goto bad_offset; + } return cpu->isar.id_isar1; case 0xd68: /* ISAR2. */ + if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) { + goto bad_offset; + } return cpu->isar.id_isar2; case 0xd6c: /* ISAR3. */ + if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) { + goto bad_offset; + } return cpu->isar.id_isar3; case 0xd70: /* ISAR4. */ + if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) { + goto bad_offset; + } return cpu->isar.id_isar4; case 0xd74: /* ISAR5. */ + if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) { + goto bad_offset; + } return cpu->isar.id_isar5; case 0xd78: /* CLIDR */ return cpu->clidr; diff --git a/hw/pci-host/gpex-acpi.c b/hw/pci-host/gpex-acpi.c new file mode 100644 index 0000000000..dbb350a837 --- /dev/null +++ b/hw/pci-host/gpex-acpi.c @@ -0,0 +1,177 @@ +#include "qemu/osdep.h" +#include "hw/acpi/aml-build.h" +#include "hw/pci-host/gpex.h" + +void acpi_dsdt_add_gpex(Aml *scope, struct GPEXConfig *cfg) +{ + int nr_pcie_buses = cfg->ecam.size / PCIE_MMCFG_SIZE_MIN; + Aml *method, *crs, *ifctx, *UUID, *ifctx1, *elsectx, *buf; + int i, slot_no; + + Aml *dev = aml_device("%s", "PCI0"); + aml_append(dev, aml_name_decl("_HID", aml_string("PNP0A08"))); + aml_append(dev, aml_name_decl("_CID", aml_string("PNP0A03"))); + aml_append(dev, aml_name_decl("_SEG", aml_int(0))); + aml_append(dev, aml_name_decl("_BBN", aml_int(0))); + aml_append(dev, aml_name_decl("_UID", aml_int(0))); + aml_append(dev, aml_name_decl("_STR", aml_unicode("PCIe 0 Device"))); + aml_append(dev, aml_name_decl("_CCA", aml_int(1))); + + /* Declare the PCI Routing Table. */ + Aml *rt_pkg = aml_varpackage(PCI_SLOT_MAX * PCI_NUM_PINS); + for (slot_no = 0; slot_no < PCI_SLOT_MAX; slot_no++) { + for (i = 0; i < PCI_NUM_PINS; i++) { + int gsi = (i + slot_no) % PCI_NUM_PINS; + Aml *pkg = aml_package(4); + aml_append(pkg, aml_int((slot_no << 16) | 0xFFFF)); + aml_append(pkg, aml_int(i)); + aml_append(pkg, aml_name("GSI%d", gsi)); + aml_append(pkg, aml_int(0)); + aml_append(rt_pkg, pkg); + } + } + aml_append(dev, aml_name_decl("_PRT", rt_pkg)); + + /* Create GSI link device */ + for (i = 0; i < PCI_NUM_PINS; i++) { + uint32_t irqs = cfg->irq + i; + Aml *dev_gsi = aml_device("GSI%d", i); + aml_append(dev_gsi, aml_name_decl("_HID", aml_string("PNP0C0F"))); + aml_append(dev_gsi, aml_name_decl("_UID", aml_int(i))); + crs = aml_resource_template(); + aml_append(crs, + aml_interrupt(AML_CONSUMER, AML_LEVEL, AML_ACTIVE_HIGH, + AML_EXCLUSIVE, &irqs, 1)); + aml_append(dev_gsi, aml_name_decl("_PRS", crs)); + crs = aml_resource_template(); + aml_append(crs, + aml_interrupt(AML_CONSUMER, AML_LEVEL, AML_ACTIVE_HIGH, + AML_EXCLUSIVE, &irqs, 1)); + aml_append(dev_gsi, aml_name_decl("_CRS", crs)); + method = aml_method("_SRS", 1, AML_NOTSERIALIZED); + aml_append(dev_gsi, method); + aml_append(dev, dev_gsi); + } + + method = aml_method("_CBA", 0, AML_NOTSERIALIZED); + aml_append(method, aml_return(aml_int(cfg->ecam.base))); + aml_append(dev, method); + + Aml *rbuf = aml_resource_template(); + aml_append(rbuf, + aml_word_bus_number(AML_MIN_FIXED, AML_MAX_FIXED, AML_POS_DECODE, + 0x0000, 0x0000, nr_pcie_buses - 1, 0x0000, + nr_pcie_buses)); + if (cfg->mmio32.size) { + aml_append(rbuf, + aml_dword_memory(AML_POS_DECODE, AML_MIN_FIXED, AML_MAX_FIXED, + AML_NON_CACHEABLE, AML_READ_WRITE, 0x0000, + cfg->mmio32.base, + cfg->mmio32.base + cfg->mmio32.size - 1, + 0x0000, + cfg->mmio32.size)); + } + if (cfg->pio.size) { + aml_append(rbuf, + aml_dword_io(AML_MIN_FIXED, AML_MAX_FIXED, AML_POS_DECODE, + AML_ENTIRE_RANGE, 0x0000, 0x0000, + cfg->pio.size - 1, + cfg->pio.base, + cfg->pio.size)); + } + if (cfg->mmio64.size) { + aml_append(rbuf, + aml_qword_memory(AML_POS_DECODE, AML_MIN_FIXED, AML_MAX_FIXED, + AML_NON_CACHEABLE, AML_READ_WRITE, 0x0000, + cfg->mmio64.base, + cfg->mmio64.base + cfg->mmio64.size - 1, + 0x0000, + cfg->mmio64.size)); + } + aml_append(dev, aml_name_decl("_CRS", rbuf)); + + /* Declare an _OSC (OS Control Handoff) method */ + aml_append(dev, aml_name_decl("SUPP", aml_int(0))); + aml_append(dev, aml_name_decl("CTRL", aml_int(0))); + method = aml_method("_OSC", 4, AML_NOTSERIALIZED); + aml_append(method, + aml_create_dword_field(aml_arg(3), aml_int(0), "CDW1")); + + /* PCI Firmware Specification 3.0 + * 4.5.1. _OSC Interface for PCI Host Bridge Devices + * The _OSC interface for a PCI/PCI-X/PCI Express hierarchy is + * identified by the Universal Unique IDentifier (UUID) + * 33DB4D5B-1FF7-401C-9657-7441C03DD766 + */ + UUID = aml_touuid("33DB4D5B-1FF7-401C-9657-7441C03DD766"); + ifctx = aml_if(aml_equal(aml_arg(0), UUID)); + aml_append(ifctx, + aml_create_dword_field(aml_arg(3), aml_int(4), "CDW2")); + aml_append(ifctx, + aml_create_dword_field(aml_arg(3), aml_int(8), "CDW3")); + aml_append(ifctx, aml_store(aml_name("CDW2"), aml_name("SUPP"))); + aml_append(ifctx, aml_store(aml_name("CDW3"), aml_name("CTRL"))); + + /* + * Allow OS control for all 5 features: + * PCIeHotplug SHPCHotplug PME AER PCIeCapability. + */ + aml_append(ifctx, aml_and(aml_name("CTRL"), aml_int(0x1F), + aml_name("CTRL"))); + + ifctx1 = aml_if(aml_lnot(aml_equal(aml_arg(1), aml_int(0x1)))); + aml_append(ifctx1, aml_or(aml_name("CDW1"), aml_int(0x08), + aml_name("CDW1"))); + aml_append(ifctx, ifctx1); + + ifctx1 = aml_if(aml_lnot(aml_equal(aml_name("CDW3"), aml_name("CTRL")))); + aml_append(ifctx1, aml_or(aml_name("CDW1"), aml_int(0x10), + aml_name("CDW1"))); + aml_append(ifctx, ifctx1); + + aml_append(ifctx, aml_store(aml_name("CTRL"), aml_name("CDW3"))); + aml_append(ifctx, aml_return(aml_arg(3))); + aml_append(method, ifctx); + + elsectx = aml_else(); + aml_append(elsectx, aml_or(aml_name("CDW1"), aml_int(4), + aml_name("CDW1"))); + aml_append(elsectx, aml_return(aml_arg(3))); + aml_append(method, elsectx); + aml_append(dev, method); + + method = aml_method("_DSM", 4, AML_NOTSERIALIZED); + + /* PCI Firmware Specification 3.0 + * 4.6.1. _DSM for PCI Express Slot Information + * The UUID in _DSM in this context is + * {E5C937D0-3553-4D7A-9117-EA4D19C3434D} + */ + UUID = aml_touuid("E5C937D0-3553-4D7A-9117-EA4D19C3434D"); + ifctx = aml_if(aml_equal(aml_arg(0), UUID)); + ifctx1 = aml_if(aml_equal(aml_arg(2), aml_int(0))); + uint8_t byte_list[1] = {1}; + buf = aml_buffer(1, byte_list); + aml_append(ifctx1, aml_return(buf)); + aml_append(ifctx, ifctx1); + aml_append(method, ifctx); + + byte_list[0] = 0; + buf = aml_buffer(1, byte_list); + aml_append(method, aml_return(buf)); + aml_append(dev, method); + + Aml *dev_res0 = aml_device("%s", "RES0"); + aml_append(dev_res0, aml_name_decl("_HID", aml_string("PNP0C02"))); + crs = aml_resource_template(); + aml_append(crs, + aml_qword_memory(AML_POS_DECODE, AML_MIN_FIXED, AML_MAX_FIXED, + AML_NON_CACHEABLE, AML_READ_WRITE, 0x0000, + cfg->ecam.base, + cfg->ecam.base + cfg->ecam.size - 1, + 0x0000, + cfg->ecam.size)); + aml_append(dev_res0, aml_name_decl("_CRS", crs)); + aml_append(dev, dev_res0); + aml_append(scope, dev); +} diff --git a/hw/pci-host/meson.build b/hw/pci-host/meson.build index cd52f6ff1c..e6d1b89684 100644 --- a/hw/pci-host/meson.build +++ b/hw/pci-host/meson.build @@ -3,6 +3,7 @@ pci_ss.add(when: 'CONFIG_PAM', if_true: files('pam.c')) pci_ss.add(when: 'CONFIG_PCI_BONITO', if_true: files('bonito.c')) pci_ss.add(when: 'CONFIG_PCI_EXPRESS_DESIGNWARE', if_true: files('designware.c')) pci_ss.add(when: 'CONFIG_PCI_EXPRESS_GENERIC_BRIDGE', if_true: files('gpex.c')) +pci_ss.add(when: 'CONFIG_ACPI', if_true: files('gpex-acpi.c')) pci_ss.add(when: 'CONFIG_PCI_EXPRESS_Q35', if_true: files('q35.c')) pci_ss.add(when: 'CONFIG_PCI_EXPRESS_XILINX', if_true: files('xilinx-pcie.c')) pci_ss.add(when: 'CONFIG_PCI_I440FX', if_true: files('i440fx.c')) diff --git a/include/exec/hwaddr.h b/include/exec/hwaddr.h index a71c93cc81..8f16d179a8 100644 --- a/include/exec/hwaddr.h +++ b/include/exec/hwaddr.h @@ -18,4 +18,9 @@ typedef uint64_t hwaddr; #define HWADDR_PRIx PRIx64 #define HWADDR_PRIX PRIX64 +typedef struct MemMapEntry { + hwaddr base; + hwaddr size; +} MemMapEntry; + #endif diff --git a/include/hw/arm/bcm2835_peripherals.h b/include/hw/arm/bcm2835_peripherals.h index 13d7c4c553..c9ac941a82 100644 --- a/include/hw/arm/bcm2835_peripherals.h +++ b/include/hw/arm/bcm2835_peripherals.h @@ -45,6 +45,7 @@ struct BCM2835PeripheralState { BCM2835SystemTimerState systmr; BCM2835MphiState mphi; + UnimplementedDeviceState txp; UnimplementedDeviceState armtmr; UnimplementedDeviceState cprman; UnimplementedDeviceState a2w; @@ -66,6 +67,7 @@ struct BCM2835PeripheralState { UnimplementedDeviceState otp; UnimplementedDeviceState dbus; UnimplementedDeviceState ave0; + UnimplementedDeviceState v3d; UnimplementedDeviceState bscsl; UnimplementedDeviceState smi; DWC2State dwc2; diff --git a/include/hw/arm/raspi_platform.h b/include/hw/arm/raspi_platform.h index 61b04a1bd4..c7f50b260f 100644 --- a/include/hw/arm/raspi_platform.h +++ b/include/hw/arm/raspi_platform.h @@ -20,20 +20,29 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Various undocumented addresses and names come from Herman Hermitage's VC4 + * documentation: + * https://github.com/hermanhermitage/videocoreiv/wiki/MMIO-Register-map */ #ifndef HW_ARM_RASPI_PLATFORM_H #define HW_ARM_RASPI_PLATFORM_H #define MSYNC_OFFSET 0x0000 /* Multicore Sync Block */ -#define IC0_OFFSET 0x2000 +#define CCPT_OFFSET 0x1000 /* Compact Camera Port 2 TX */ +#define INTE_OFFSET 0x2000 /* VC Interrupt controller */ #define ST_OFFSET 0x3000 /* System Timer */ +#define TXP_OFFSET 0x4000 /* Transposer */ +#define JPEG_OFFSET 0x5000 #define MPHI_OFFSET 0x6000 /* Message-based Parallel Host Intf. */ #define DMA_OFFSET 0x7000 /* DMA controller, channels 0-14 */ -#define ARM_OFFSET 0xB000 /* BCM2708 ARM control block */ +#define ARBA_OFFSET 0x9000 +#define BRDG_OFFSET 0xa000 +#define ARM_OFFSET 0xB000 /* ARM control block */ #define ARMCTRL_OFFSET (ARM_OFFSET + 0x000) #define ARMCTRL_IC_OFFSET (ARM_OFFSET + 0x200) /* Interrupt controller */ -#define ARMCTRL_TIMER0_1_OFFSET (ARM_OFFSET + 0x400) /* Timer 0 and 1 */ +#define ARMCTRL_TIMER0_1_OFFSET (ARM_OFFSET + 0x400) /* Timer 0 and 1 (SP804) */ #define ARMCTRL_0_SBM_OFFSET (ARM_OFFSET + 0x800) /* User 0 (ARM) Semaphores * Doorbells & Mailboxes */ #define CPRMAN_OFFSET 0x100000 /* Power Management, Watchdog */ @@ -42,24 +51,50 @@ #define AVS_OFFSET 0x103000 /* Audio Video Standard */ #define RNG_OFFSET 0x104000 #define GPIO_OFFSET 0x200000 -#define UART0_OFFSET 0x201000 -#define MMCI0_OFFSET 0x202000 -#define I2S_OFFSET 0x203000 -#define SPI0_OFFSET 0x204000 +#define UART0_OFFSET 0x201000 /* PL011 */ +#define MMCI0_OFFSET 0x202000 /* Legacy MMC */ +#define I2S_OFFSET 0x203000 /* PCM */ +#define SPI0_OFFSET 0x204000 /* SPI master */ #define BSC0_OFFSET 0x205000 /* BSC0 I2C/TWI */ +#define PIXV0_OFFSET 0x206000 +#define PIXV1_OFFSET 0x207000 +#define DPI_OFFSET 0x208000 +#define DSI0_OFFSET 0x209000 /* Display Serial Interface */ +#define PWM_OFFSET 0x20c000 +#define PERM_OFFSET 0x20d000 +#define TEC_OFFSET 0x20e000 #define OTP_OFFSET 0x20f000 +#define SLIM_OFFSET 0x210000 /* SLIMbus */ +#define CPG_OFFSET 0x211000 #define THERMAL_OFFSET 0x212000 -#define BSC_SL_OFFSET 0x214000 /* SPI slave */ +#define AVSP_OFFSET 0x213000 +#define BSC_SL_OFFSET 0x214000 /* SPI slave (bootrom) */ #define AUX_OFFSET 0x215000 /* AUX: UART1/SPI1/SPI2 */ #define EMMC1_OFFSET 0x300000 +#define EMMC2_OFFSET 0x340000 +#define HVS_OFFSET 0x400000 #define SMI_OFFSET 0x600000 +#define DSI1_OFFSET 0x700000 +#define UCAM_OFFSET 0x800000 +#define CMI_OFFSET 0x802000 #define BSC1_OFFSET 0x804000 /* BSC1 I2C/TWI */ #define BSC2_OFFSET 0x805000 /* BSC2 I2C/TWI */ +#define VECA_OFFSET 0x806000 +#define PIXV2_OFFSET 0x807000 +#define HDMI_OFFSET 0x808000 +#define HDCP_OFFSET 0x809000 +#define ARBR0_OFFSET 0x80a000 #define DBUS_OFFSET 0x900000 #define AVE0_OFFSET 0x910000 #define USB_OTG_OFFSET 0x980000 /* DTC_OTG USB controller */ +#define V3D_OFFSET 0xc00000 #define SDRAMC_OFFSET 0xe00000 +#define L2CC_OFFSET 0xe01000 /* Level 2 Cache controller */ +#define L1CC_OFFSET 0xe02000 /* Level 1 Cache controller */ +#define ARBR1_OFFSET 0xe04000 #define DMA15_OFFSET 0xE05000 /* DMA controller, channel 15 */ +#define DCRC_OFFSET 0xe07000 +#define AXIP_OFFSET 0xe08000 /* GPU interrupts */ #define INTERRUPT_TIMER0 0 diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h index d018a4f297..655b895d5e 100644 --- a/include/hw/arm/virt.h +++ b/include/hw/arm/virt.h @@ -111,11 +111,6 @@ typedef enum VirtGICType { VIRT_GIC_VERSION_NOSEL, } VirtGICType; -typedef struct MemMapEntry { - hwaddr base; - hwaddr size; -} MemMapEntry; - struct VirtMachineClass { MachineClass parent; bool disallow_affinity_adjustment; diff --git a/include/hw/i386/microvm.h b/include/hw/i386/microvm.h index 3b9fd4ff17..91b064575d 100644 --- a/include/hw/i386/microvm.h +++ b/include/hw/i386/microvm.h @@ -25,8 +25,31 @@ #include "hw/boards.h" #include "hw/i386/x86.h" #include "hw/acpi/acpi_dev_interface.h" +#include "hw/pci-host/gpex.h" #include "qom/object.h" +/* + * IRQ | pc | microvm (acpi=on) + * --------+------------+------------------ + * 0 | pit | + * 1 | kbd | + * 2 | cascade | + * 3 | serial 1 | + * 4 | serial 0 | serial + * 5 | - | + * 6 | floppy | + * 7 | parallel | + * 8 | rtc | rtc (rtc=on) + * 9 | acpi | acpi (ged) + * 10 | pci lnk | + * 11 | pci lnk | + * 12 | ps2 | pcie + * 13 | fpu | pcie + * 14 | ide 0 | pcie + * 15 | ide 1 | pcie + * 16-23 | pci gsi | virtio + */ + /* Platform virtio definitions */ #define VIRTIO_MMIO_BASE 0xfeb00000 #define VIRTIO_NUM_TRANSPORTS 8 @@ -37,10 +60,17 @@ #define GED_MMIO_BASE_REGS (GED_MMIO_BASE + 0x200) #define GED_MMIO_IRQ 9 +#define PCIE_MMIO_BASE 0xc0000000 +#define PCIE_MMIO_SIZE 0x20000000 +#define PCIE_ECAM_BASE 0xe0000000 +#define PCIE_ECAM_SIZE 0x10000000 +#define PCIE_IRQ_BASE 12 + /* Machine type options */ #define MICROVM_MACHINE_PIT "pit" #define MICROVM_MACHINE_PIC "pic" #define MICROVM_MACHINE_RTC "rtc" +#define MICROVM_MACHINE_PCIE "pcie" #define MICROVM_MACHINE_ISA_SERIAL "isa-serial" #define MICROVM_MACHINE_OPTION_ROMS "x-option-roms" #define MICROVM_MACHINE_AUTO_KERNEL_CMDLINE "auto-kernel-cmdline" @@ -58,6 +88,7 @@ struct MicrovmMachineState { OnOffAuto pic; OnOffAuto pit; OnOffAuto rtc; + OnOffAuto pcie; bool isa_serial; bool option_roms; bool auto_kernel_cmdline; @@ -67,6 +98,7 @@ struct MicrovmMachineState { bool kernel_cmdline_fixed; Notifier machine_done; Notifier powerdown_req; + struct GPEXConfig gpex; }; #define TYPE_MICROVM_MACHINE MACHINE_TYPE_NAME("microvm") diff --git a/include/hw/pci-host/gpex.h b/include/hw/pci-host/gpex.h index 7abdb8b406..d52ea80d4e 100644 --- a/include/hw/pci-host/gpex.h +++ b/include/hw/pci-host/gpex.h @@ -20,6 +20,7 @@ #ifndef HW_GPEX_H #define HW_GPEX_H +#include "exec/hwaddr.h" #include "hw/sysbus.h" #include "hw/pci/pci.h" #include "hw/pci/pcie_host.h" @@ -52,6 +53,16 @@ struct GPEXHost { int irq_num[GPEX_NUM_IRQS]; }; +struct GPEXConfig { + MemMapEntry ecam; + MemMapEntry mmio32; + MemMapEntry mmio64; + MemMapEntry pio; + int irq; +}; + int gpex_set_irq_num(GPEXHost *s, int index, int gsi); +void acpi_dsdt_add_gpex(Aml *scope, struct GPEXConfig *cfg); + #endif /* HW_GPEX_H */ diff --git a/target/arm/cpu.c b/target/arm/cpu.c index a7643deab4..858c5a4bcb 100644 --- a/target/arm/cpu.c +++ b/target/arm/cpu.c @@ -1588,7 +1588,6 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp) } if (arm_feature(env, ARM_FEATURE_LPAE)) { set_feature(env, ARM_FEATURE_V7MP); - set_feature(env, ARM_FEATURE_PXN); } if (arm_feature(env, ARM_FEATURE_CBAR_RO)) { set_feature(env, ARM_FEATURE_CBAR); @@ -1660,7 +1659,7 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp) /* Disable the security extension feature bits in the processor feature * registers as well. These are id_pfr1[7:4] and id_aa64pfr0[15:12]. */ - cpu->id_pfr1 &= ~0xf0; + cpu->isar.id_pfr1 &= ~0xf0; cpu->isar.id_aa64pfr0 &= ~0xf000; } @@ -1697,7 +1696,7 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp) * id_aa64pfr0_el1[11:8]. */ cpu->isar.id_aa64pfr0 &= ~0xf00; - cpu->id_pfr1 &= ~0xf000; + cpu->isar.id_pfr1 &= ~0xf000; } #ifndef CONFIG_USER_ONLY @@ -1895,8 +1894,8 @@ static void cortex_a8_initfn(Object *obj) cpu->isar.mvfr1 = 0x00011111; cpu->ctr = 0x82048004; cpu->reset_sctlr = 0x00c50078; - cpu->id_pfr0 = 0x1031; - cpu->id_pfr1 = 0x11; + cpu->isar.id_pfr0 = 0x1031; + cpu->isar.id_pfr1 = 0x11; cpu->isar.id_dfr0 = 0x400; cpu->id_afr0 = 0; cpu->isar.id_mmfr0 = 0x31100003; @@ -1967,8 +1966,8 @@ static void cortex_a9_initfn(Object *obj) cpu->isar.mvfr1 = 0x01111111; cpu->ctr = 0x80038003; cpu->reset_sctlr = 0x00c50078; - cpu->id_pfr0 = 0x1031; - cpu->id_pfr1 = 0x11; + cpu->isar.id_pfr0 = 0x1031; + cpu->isar.id_pfr1 = 0x11; cpu->isar.id_dfr0 = 0x000; cpu->id_afr0 = 0; cpu->isar.id_mmfr0 = 0x00100103; @@ -2031,8 +2030,8 @@ static void cortex_a7_initfn(Object *obj) cpu->isar.mvfr1 = 0x11111111; cpu->ctr = 0x84448003; cpu->reset_sctlr = 0x00c50078; - cpu->id_pfr0 = 0x00001131; - cpu->id_pfr1 = 0x00011011; + cpu->isar.id_pfr0 = 0x00001131; + cpu->isar.id_pfr1 = 0x00011011; cpu->isar.id_dfr0 = 0x02010555; cpu->id_afr0 = 0x00000000; cpu->isar.id_mmfr0 = 0x10101105; @@ -2076,8 +2075,8 @@ static void cortex_a15_initfn(Object *obj) cpu->isar.mvfr1 = 0x11111111; cpu->ctr = 0x8444c004; cpu->reset_sctlr = 0x00c50078; - cpu->id_pfr0 = 0x00001131; - cpu->id_pfr1 = 0x00011011; + cpu->isar.id_pfr0 = 0x00001131; + cpu->isar.id_pfr1 = 0x00011011; cpu->isar.id_dfr0 = 0x02010555; cpu->id_afr0 = 0x00000000; cpu->isar.id_mmfr0 = 0x10201105; diff --git a/target/arm/cpu.h b/target/arm/cpu.h index 6036f61d60..e4549a8cc0 100644 --- a/target/arm/cpu.h +++ b/target/arm/cpu.h @@ -906,6 +906,8 @@ struct ARMCPU { uint32_t id_mmfr2; uint32_t id_mmfr3; uint32_t id_mmfr4; + uint32_t id_pfr0; + uint32_t id_pfr1; uint32_t mvfr0; uint32_t mvfr1; uint32_t mvfr2; @@ -926,8 +928,6 @@ struct ARMCPU { uint32_t reset_fpsid; uint32_t ctr; uint32_t reset_sctlr; - uint32_t id_pfr0; - uint32_t id_pfr1; uint64_t pmceid0; uint64_t pmceid1; uint32_t id_afr0; @@ -1772,6 +1772,15 @@ FIELD(ID_ISAR6, FHM, 8, 4) FIELD(ID_ISAR6, SB, 12, 4) FIELD(ID_ISAR6, SPECRES, 16, 4) +FIELD(ID_MMFR0, VMSA, 0, 4) +FIELD(ID_MMFR0, PMSA, 4, 4) +FIELD(ID_MMFR0, OUTERSHR, 8, 4) +FIELD(ID_MMFR0, SHARELVL, 12, 4) +FIELD(ID_MMFR0, TCM, 16, 4) +FIELD(ID_MMFR0, AUXREG, 20, 4) +FIELD(ID_MMFR0, FCSE, 24, 4) +FIELD(ID_MMFR0, INNERSHR, 28, 4) + FIELD(ID_MMFR3, CMAINTVA, 0, 4) FIELD(ID_MMFR3, CMAINTSW, 4, 4) FIELD(ID_MMFR3, BPMAINT, 8, 4) @@ -1790,6 +1799,15 @@ FIELD(ID_MMFR4, LSM, 20, 4) FIELD(ID_MMFR4, CCIDX, 24, 4) FIELD(ID_MMFR4, EVT, 28, 4) +FIELD(ID_PFR1, PROGMOD, 0, 4) +FIELD(ID_PFR1, SECURITY, 4, 4) +FIELD(ID_PFR1, MPROGMOD, 8, 4) +FIELD(ID_PFR1, VIRTUALIZATION, 12, 4) +FIELD(ID_PFR1, GENTIMER, 16, 4) +FIELD(ID_PFR1, SEC_FRAC, 20, 4) +FIELD(ID_PFR1, VIRT_FRAC, 24, 4) +FIELD(ID_PFR1, GIC, 28, 4) + FIELD(ID_AA64ISAR0, AES, 4, 4) FIELD(ID_AA64ISAR0, SHA1, 8, 4) FIELD(ID_AA64ISAR0, SHA2, 12, 4) @@ -1907,10 +1925,12 @@ FIELD(MVFR0, FPROUND, 28, 4) FIELD(MVFR1, FPFTZ, 0, 4) FIELD(MVFR1, FPDNAN, 4, 4) -FIELD(MVFR1, SIMDLS, 8, 4) -FIELD(MVFR1, SIMDINT, 12, 4) -FIELD(MVFR1, SIMDSP, 16, 4) -FIELD(MVFR1, SIMDHP, 20, 4) +FIELD(MVFR1, SIMDLS, 8, 4) /* A-profile only */ +FIELD(MVFR1, SIMDINT, 12, 4) /* A-profile only */ +FIELD(MVFR1, SIMDSP, 16, 4) /* A-profile only */ +FIELD(MVFR1, SIMDHP, 20, 4) /* A-profile only */ +FIELD(MVFR1, MVE, 8, 4) /* M-profile only */ +FIELD(MVFR1, FP16, 20, 4) /* M-profile only */ FIELD(MVFR1, FPHP, 24, 4) FIELD(MVFR1, SIMDFMAC, 28, 4) @@ -1949,7 +1969,6 @@ enum arm_features { ARM_FEATURE_CACHE_DIRTY_REG, /* 1136/1176 cache dirty status register */ ARM_FEATURE_CACHE_BLOCK_OPS, /* v6 optional cache block operations */ ARM_FEATURE_MPIDR, /* has cp15 MPIDR */ - ARM_FEATURE_PXN, /* has Privileged Execute Never bit */ ARM_FEATURE_LPAE, /* has Large Physical Address Extension */ ARM_FEATURE_V8, ARM_FEATURE_AARCH64, /* supports 64 bit mode */ @@ -3514,9 +3533,19 @@ static inline bool isar_feature_aa32_predinv(const ARMISARegisters *id) return FIELD_EX32(id->id_isar6, ID_ISAR6, SPECRES) != 0; } +static inline bool isar_feature_aa32_mprofile(const ARMISARegisters *id) +{ + return FIELD_EX32(id->id_pfr1, ID_PFR1, MPROGMOD) != 0; +} + static inline bool isar_feature_aa32_fp16_arith(const ARMISARegisters *id) { - return FIELD_EX32(id->mvfr1, MVFR1, FPHP) >= 3; + /* Sadly this is encoded differently for A-profile and M-profile */ + if (isar_feature_aa32_mprofile(id)) { + return FIELD_EX32(id->mvfr1, MVFR1, FP16) > 0; + } else { + return FIELD_EX32(id->mvfr1, MVFR1, FPHP) >= 3; + } } static inline bool isar_feature_aa32_vfp_simd(const ARMISARegisters *id) @@ -3615,6 +3644,11 @@ static inline bool isar_feature_aa32_vminmaxnm(const ARMISARegisters *id) return FIELD_EX32(id->mvfr2, MVFR2, FPMISC) >= 4; } +static inline bool isar_feature_aa32_pxn(const ARMISARegisters *id) +{ + return FIELD_EX32(id->id_mmfr0, ID_MMFR0, VMSA) >= 4; +} + static inline bool isar_feature_aa32_pan(const ARMISARegisters *id) { return FIELD_EX32(id->id_mmfr3, ID_MMFR3, PAN) != 0; diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c index 3c2b3d9599..e00271b932 100644 --- a/target/arm/cpu64.c +++ b/target/arm/cpu64.c @@ -108,8 +108,8 @@ static void aarch64_a57_initfn(Object *obj) cpu->isar.mvfr2 = 0x00000043; cpu->ctr = 0x8444c004; cpu->reset_sctlr = 0x00c50838; - cpu->id_pfr0 = 0x00000131; - cpu->id_pfr1 = 0x00011011; + cpu->isar.id_pfr0 = 0x00000131; + cpu->isar.id_pfr1 = 0x00011011; cpu->isar.id_dfr0 = 0x03010066; cpu->id_afr0 = 0x00000000; cpu->isar.id_mmfr0 = 0x10101105; @@ -161,8 +161,8 @@ static void aarch64_a53_initfn(Object *obj) cpu->isar.mvfr2 = 0x00000043; cpu->ctr = 0x84448004; /* L1Ip = VIPT */ cpu->reset_sctlr = 0x00c50838; - cpu->id_pfr0 = 0x00000131; - cpu->id_pfr1 = 0x00011011; + cpu->isar.id_pfr0 = 0x00000131; + cpu->isar.id_pfr1 = 0x00011011; cpu->isar.id_dfr0 = 0x03010066; cpu->id_afr0 = 0x00000000; cpu->isar.id_mmfr0 = 0x10101105; @@ -213,8 +213,8 @@ static void aarch64_a72_initfn(Object *obj) cpu->isar.mvfr2 = 0x00000043; cpu->ctr = 0x8444c004; cpu->reset_sctlr = 0x00c50838; - cpu->id_pfr0 = 0x00000131; - cpu->id_pfr1 = 0x00011011; + cpu->isar.id_pfr0 = 0x00000131; + cpu->isar.id_pfr1 = 0x00011011; cpu->isar.id_dfr0 = 0x03010066; cpu->id_afr0 = 0x00000000; cpu->isar.id_mmfr0 = 0x10201105; diff --git a/target/arm/cpu_tcg.c b/target/arm/cpu_tcg.c index 00b0e08f33..0013e25412 100644 --- a/target/arm/cpu_tcg.c +++ b/target/arm/cpu_tcg.c @@ -142,8 +142,8 @@ static void arm1136_r2_initfn(Object *obj) cpu->isar.mvfr1 = 0x00000000; cpu->ctr = 0x1dd20d2; cpu->reset_sctlr = 0x00050078; - cpu->id_pfr0 = 0x111; - cpu->id_pfr1 = 0x1; + cpu->isar.id_pfr0 = 0x111; + cpu->isar.id_pfr1 = 0x1; cpu->isar.id_dfr0 = 0x2; cpu->id_afr0 = 0x3; cpu->isar.id_mmfr0 = 0x01130003; @@ -173,8 +173,8 @@ static void arm1136_initfn(Object *obj) cpu->isar.mvfr1 = 0x00000000; cpu->ctr = 0x1dd20d2; cpu->reset_sctlr = 0x00050078; - cpu->id_pfr0 = 0x111; - cpu->id_pfr1 = 0x1; + cpu->isar.id_pfr0 = 0x111; + cpu->isar.id_pfr1 = 0x1; cpu->isar.id_dfr0 = 0x2; cpu->id_afr0 = 0x3; cpu->isar.id_mmfr0 = 0x01130003; @@ -205,8 +205,8 @@ static void arm1176_initfn(Object *obj) cpu->isar.mvfr1 = 0x00000000; cpu->ctr = 0x1dd20d2; cpu->reset_sctlr = 0x00050078; - cpu->id_pfr0 = 0x111; - cpu->id_pfr1 = 0x11; + cpu->isar.id_pfr0 = 0x111; + cpu->isar.id_pfr1 = 0x11; cpu->isar.id_dfr0 = 0x33; cpu->id_afr0 = 0; cpu->isar.id_mmfr0 = 0x01130003; @@ -234,8 +234,8 @@ static void arm11mpcore_initfn(Object *obj) cpu->isar.mvfr0 = 0x11111111; cpu->isar.mvfr1 = 0x00000000; cpu->ctr = 0x1d192992; /* 32K icache 32K dcache */ - cpu->id_pfr0 = 0x111; - cpu->id_pfr1 = 0x1; + cpu->isar.id_pfr0 = 0x111; + cpu->isar.id_pfr1 = 0x1; cpu->isar.id_dfr0 = 0; cpu->id_afr0 = 0x2; cpu->isar.id_mmfr0 = 0x01100103; @@ -256,6 +256,30 @@ static void cortex_m0_initfn(Object *obj) set_feature(&cpu->env, ARM_FEATURE_M); cpu->midr = 0x410cc200; + + /* + * These ID register values are not guest visible, because + * we do not implement the Main Extension. They must be set + * to values corresponding to the Cortex-M0's implemented + * features, because QEMU generally controls its emulation + * by looking at ID register fields. We use the same values as + * for the M3. + */ + cpu->isar.id_pfr0 = 0x00000030; + cpu->isar.id_pfr1 = 0x00000200; + cpu->isar.id_dfr0 = 0x00100000; + cpu->id_afr0 = 0x00000000; + cpu->isar.id_mmfr0 = 0x00000030; + cpu->isar.id_mmfr1 = 0x00000000; + cpu->isar.id_mmfr2 = 0x00000000; + cpu->isar.id_mmfr3 = 0x00000000; + cpu->isar.id_isar0 = 0x01141110; + cpu->isar.id_isar1 = 0x02111000; + cpu->isar.id_isar2 = 0x21112231; + cpu->isar.id_isar3 = 0x01111110; + cpu->isar.id_isar4 = 0x01310102; + cpu->isar.id_isar5 = 0x00000000; + cpu->isar.id_isar6 = 0x00000000; } static void cortex_m3_initfn(Object *obj) @@ -266,8 +290,8 @@ static void cortex_m3_initfn(Object *obj) set_feature(&cpu->env, ARM_FEATURE_M_MAIN); cpu->midr = 0x410fc231; cpu->pmsav7_dregion = 8; - cpu->id_pfr0 = 0x00000030; - cpu->id_pfr1 = 0x00000200; + cpu->isar.id_pfr0 = 0x00000030; + cpu->isar.id_pfr1 = 0x00000200; cpu->isar.id_dfr0 = 0x00100000; cpu->id_afr0 = 0x00000000; cpu->isar.id_mmfr0 = 0x00000030; @@ -296,8 +320,8 @@ static void cortex_m4_initfn(Object *obj) cpu->isar.mvfr0 = 0x10110021; cpu->isar.mvfr1 = 0x11000011; cpu->isar.mvfr2 = 0x00000000; - cpu->id_pfr0 = 0x00000030; - cpu->id_pfr1 = 0x00000200; + cpu->isar.id_pfr0 = 0x00000030; + cpu->isar.id_pfr1 = 0x00000200; cpu->isar.id_dfr0 = 0x00100000; cpu->id_afr0 = 0x00000000; cpu->isar.id_mmfr0 = 0x00000030; @@ -326,8 +350,8 @@ static void cortex_m7_initfn(Object *obj) cpu->isar.mvfr0 = 0x10110221; cpu->isar.mvfr1 = 0x12000011; cpu->isar.mvfr2 = 0x00000040; - cpu->id_pfr0 = 0x00000030; - cpu->id_pfr1 = 0x00000200; + cpu->isar.id_pfr0 = 0x00000030; + cpu->isar.id_pfr1 = 0x00000200; cpu->isar.id_dfr0 = 0x00100000; cpu->id_afr0 = 0x00000000; cpu->isar.id_mmfr0 = 0x00100030; @@ -358,8 +382,8 @@ static void cortex_m33_initfn(Object *obj) cpu->isar.mvfr0 = 0x10110021; cpu->isar.mvfr1 = 0x11000011; cpu->isar.mvfr2 = 0x00000040; - cpu->id_pfr0 = 0x00000030; - cpu->id_pfr1 = 0x00000210; + cpu->isar.id_pfr0 = 0x00000030; + cpu->isar.id_pfr1 = 0x00000210; cpu->isar.id_dfr0 = 0x00200000; cpu->id_afr0 = 0x00000000; cpu->isar.id_mmfr0 = 0x00101F40; @@ -397,8 +421,8 @@ static void cortex_r5_initfn(Object *obj) set_feature(&cpu->env, ARM_FEATURE_PMSA); set_feature(&cpu->env, ARM_FEATURE_PMU); cpu->midr = 0x411fc153; /* r1p3 */ - cpu->id_pfr0 = 0x0131; - cpu->id_pfr1 = 0x001; + cpu->isar.id_pfr0 = 0x0131; + cpu->isar.id_pfr1 = 0x001; cpu->isar.id_dfr0 = 0x010400; cpu->id_afr0 = 0x0; cpu->isar.id_mmfr0 = 0x0210030; diff --git a/target/arm/helper.c b/target/arm/helper.c index 88bd9dd35d..b394db394a 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -6625,7 +6625,7 @@ static void define_pmu_regs(ARMCPU *cpu) static uint64_t id_pfr1_read(CPUARMState *env, const ARMCPRegInfo *ri) { ARMCPU *cpu = env_archcpu(env); - uint64_t pfr1 = cpu->id_pfr1; + uint64_t pfr1 = cpu->isar.id_pfr1; if (env->gicv3state) { pfr1 |= 1 << 28; @@ -7258,7 +7258,7 @@ void register_cp_regs_for_features(ARMCPU *cpu) .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 1, .opc2 = 0, .access = PL1_R, .type = ARM_CP_CONST, .accessfn = access_aa32_tid3, - .resetvalue = cpu->id_pfr0 }, + .resetvalue = cpu->isar.id_pfr0 }, /* ID_PFR1 is not a plain ARM_CP_CONST because we don't know * the value of the GIC field until after we define these regs. */ @@ -10537,6 +10537,7 @@ static bool get_phys_addr_v6(CPUARMState *env, uint32_t address, target_ulong *page_size, ARMMMUFaultInfo *fi) { CPUState *cs = env_cpu(env); + ARMCPU *cpu = env_archcpu(env); int level = 1; uint32_t table; uint32_t desc; @@ -10563,7 +10564,7 @@ static bool get_phys_addr_v6(CPUARMState *env, uint32_t address, goto do_fault; } type = (desc & 3); - if (type == 0 || (type == 3 && !arm_feature(env, ARM_FEATURE_PXN))) { + if (type == 0 || (type == 3 && !cpu_isar_feature(aa32_pxn, cpu))) { /* Section translation fault, or attempt to use the encoding * which is Reserved on implementations without PXN. */ @@ -10605,7 +10606,7 @@ static bool get_phys_addr_v6(CPUARMState *env, uint32_t address, pxn = desc & 1; ns = extract32(desc, 19, 1); } else { - if (arm_feature(env, ARM_FEATURE_PXN)) { + if (cpu_isar_feature(aa32_pxn, cpu)) { pxn = (desc >> 2) & 1; } ns = extract32(desc, 3, 1); diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c index 987b35e33f..fae07c3f04 100644 --- a/target/arm/kvm64.c +++ b/target/arm/kvm64.c @@ -555,6 +555,10 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) * than skipping the reads and leaving 0, as we must avoid * considering the values in every case. */ + err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_pfr0, + ARM64_SYS_REG(3, 0, 0, 1, 0)); + err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_pfr1, + ARM64_SYS_REG(3, 0, 0, 1, 1)); err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_dfr0, ARM64_SYS_REG(3, 0, 0, 1, 2)); err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr0, diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c index e4cd6b6251..9095586fc9 100644 --- a/target/arm/translate-sve.c +++ b/target/arm/translate-sve.c @@ -2689,7 +2689,7 @@ static bool trans_SPLICE(DisasContext *s, arg_rprr_esz *a) { if (sve_access_check(s)) { gen_gvec_ool_zzzp(s, gen_helper_sve_splice, - a->rd, a->rn, a->rm, a->pg, 0); + a->rd, a->rn, a->rm, a->pg, a->esz); } return true; } @@ -4290,7 +4290,7 @@ static void do_ldr(DisasContext *s, uint32_t vofs, int len, int rn, int imm) for (i = 0; i < len_align; i += 8) { tcg_gen_qemu_ld_i64(t0, clean_addr, midx, MO_LEQ); tcg_gen_st_i64(t0, cpu_env, vofs + i); - tcg_gen_addi_i64(clean_addr, cpu_reg_sp(s, rn), 8); + tcg_gen_addi_i64(clean_addr, clean_addr, 8); } tcg_temp_free_i64(t0); } else { @@ -4379,7 +4379,7 @@ static void do_str(DisasContext *s, uint32_t vofs, int len, int rn, int imm) for (i = 0; i < len_align; i += 8) { tcg_gen_ld_i64(t0, cpu_env, vofs + i); tcg_gen_qemu_st_i64(t0, clean_addr, midx, MO_LEQ); - tcg_gen_addi_i64(clean_addr, cpu_reg_sp(s, rn), 8); + tcg_gen_addi_i64(clean_addr, clean_addr, 8); } tcg_temp_free_i64(t0); } else { diff --git a/tests/data/acpi/microvm/DSDT.pcie b/tests/data/acpi/microvm/DSDT.pcie new file mode 100644 index 0000000000..4b765541e3 --- /dev/null +++ b/tests/data/acpi/microvm/DSDT.pcie Binary files differdiff --git a/tests/data/acpi/virt/DSDT b/tests/data/acpi/virt/DSDT index 9b002836f3..bc519abff9 100644 --- a/tests/data/acpi/virt/DSDT +++ b/tests/data/acpi/virt/DSDT Binary files differdiff --git a/tests/data/acpi/virt/DSDT.memhp b/tests/data/acpi/virt/DSDT.memhp index 545a18c365..54728e2b4b 100644 --- a/tests/data/acpi/virt/DSDT.memhp +++ b/tests/data/acpi/virt/DSDT.memhp Binary files differdiff --git a/tests/data/acpi/virt/DSDT.numamem b/tests/data/acpi/virt/DSDT.numamem index 9b002836f3..bc519abff9 100644 --- a/tests/data/acpi/virt/DSDT.numamem +++ b/tests/data/acpi/virt/DSDT.numamem Binary files differdiff --git a/tests/qtest/bios-tables-test.c b/tests/qtest/bios-tables-test.c index 67d1bed082..e15f36c8c7 100644 --- a/tests/qtest/bios-tables-test.c +++ b/tests/qtest/bios-tables-test.c @@ -1086,20 +1086,37 @@ static void test_acpi_virt_tcg_memhp(void) } +static void test_acpi_microvm_prepare(test_data *data) +{ + memset(data, 0, sizeof(*data)); + data->machine = "microvm"; + data->required_struct_types = NULL; /* no smbios */ + data->required_struct_types_len = 0; + data->blkdev = "virtio-blk-device"; +} + static void test_acpi_microvm_tcg(void) { test_data data; - memset(&data, 0, sizeof(data)); - data.machine = "microvm"; - data.required_struct_types = NULL; /* no smbios */ - data.required_struct_types_len = 0; - data.blkdev = "virtio-blk-device"; + test_acpi_microvm_prepare(&data); test_acpi_one(" -machine microvm,acpi=on,rtc=off", &data); free_test_data(&data); } +static void test_acpi_microvm_pcie_tcg(void) +{ + test_data data; + + test_acpi_microvm_prepare(&data); + data.variant = ".pcie"; + data.tcg_only = true; /* need constant host-phys-bits */ + test_acpi_one(" -machine microvm,acpi=on,rtc=off,pcie=on", + &data); + free_test_data(&data); +} + static void test_acpi_virt_tcg_numamem(void) { test_data data = { @@ -1224,6 +1241,9 @@ int main(int argc, char *argv[]) qtest_add_func("acpi/piix4/acpihmat", test_acpi_piix4_tcg_acpi_hmat); qtest_add_func("acpi/q35/acpihmat", test_acpi_q35_tcg_acpi_hmat); qtest_add_func("acpi/microvm", test_acpi_microvm_tcg); + if (strcmp(arch, "x86_64") == 0) { + qtest_add_func("acpi/microvm/pcie", test_acpi_microvm_pcie_tcg); + } } else if (strcmp(arch, "aarch64") == 0) { qtest_add_func("acpi/virt", test_acpi_virt_tcg); qtest_add_func("acpi/virt/numamem", test_acpi_virt_tcg_numamem); |