:p
atchew
Login
Hi; here's an arm pullreq for the freeze. Mostly this is Philippe's hvf cleanup work, but there are some other smaller things in here too. thanks -- PMM The following changes since commit 3728de31925ae9658e2ce3d1ff9b63c83609f310: Merge tag 'single-binary-20251030' of https://github.com/philmd/qemu into staging (2025-10-31 10:26:34 +0100) are available in the Git repository at: https://gitlab.com/pm215/qemu.git tags/pull-target-arm-20251031 for you to fetch changes up to 8b733be9f408f9b550fc998c790e32aded5119f1: accel/hvf: Trace prefetch abort (2025-10-31 16:26:46 +0000) ---------------------------------------------------------------- target-arm queue: * hw/gpio/pl061: Declare pullups/pulldowns as 8-bit types * docs/system/arm/virt: Document user-creatable SMMUv3 * docs/system/security: Restrict "virtualization use case" to specific machines * target/arm: Add assert to arm_to_core_mmu_idx() * hw/arm/virt: remove deprecated virt-4.1 and virt-4.2 machine types * hvf: Refactorings and cleanups ---------------------------------------------------------------- Mohamed Mediouni (2): target/arm/hvf: Hardcode Apple MIDR target/arm/hvf: switch hvf_arm_get_host_cpu_features to not create a vCPU Peter Maydell (3): docs/system/arm/virt: Document user-creatable SMMUv3 docs/system/security: Restrict "virtualization use case" to specific machines target/arm: Add assert to arm_to_core_mmu_idx() Philippe Mathieu-Daudé (33): hw/gpio/pl061: Declare pullups/pulldowns as 8-bit types hw/arm/virt: Remove deprecated virt-4.1 machine hw/arm/virt: Remove VirtMachineClass::no_ged field hw/arm/virt: Remove deprecated virt-4.2 machine hw/arm/virt: Remove VirtMachineClass::kvm_no_adjvtime field target/arm/hvf: Release memory allocated by hv_vcpu_config_create() target/arm/hvf: Trace vCPU KICK events target/arm/hvf: Check hv_vcpus_exit() returned value target/arm/hvf: Check hv_vcpu_set_vtimer_mask() returned value accel/hvf: Rename hvf_vcpu_exec() -> hvf_arch_vcpu_exec() accel/hvf: Rename hvf_put|get_registers -> hvf_arch_put|get_registers target/arm/hvf: Mention flush_cpu_state() must run on vCPU thread accel/hvf: Mention hvf_arch_init_vcpu() must run on vCPU thread target/arm/hvf: Mention hvf_sync_vtimer() must run on vCPU thread target/arm/hvf: Mention hvf_arch_set_traps() must run on vCPU thread accel/hvf: Mention hvf_arch_update_guest_debug() must run on vCPU target/arm/hvf: Mention hvf_inject_interrupts() must run on vCPU thread accel/hvf: Implement hvf_arch_vcpu_destroy() target/arm/hvf: Simplify hvf_arm_get_host_cpu_features() target/arm/hvf: Factor hvf_handle_exception() out target/i386/hvf: Factor hvf_handle_vmexit() out target/arm/hvf: Factor hvf_handle_vmexit() out target/arm/hvf: Keep calling hv_vcpu_run() in loop cpus: Trace cpu_exec_start() and cpu_exec_end() calls accel/hvf: Guard hv_vcpu_run() between cpu_exec_start/end() calls target/arm: Call aarch64_add_pauth_properties() once in host_initfn() accel/hvf: Restrict ARM specific fields of AccelCPUState target/arm: Rename init_cpreg_list() -> arm_init_cpreg_list() target/arm/hvf: Rename 'vgic' -> 'emu_reginfo' in trace events target/arm: Re-use arm_is_psci_call() in HVF target/arm: Share ARM_PSCI_CALL trace event between TCG and HVF target/arm/hvf/hvf: Document $pc adjustment in HVF & SMC accel/hvf: Trace prefetch abort docs/system/arm/virt.rst | 35 +++- docs/system/security.rst | 26 +++ include/hw/arm/virt.h | 2 - include/system/hvf_int.h | 23 ++- target/arm/internals.h | 6 +- accel/hvf/hvf-accel-ops.c | 4 +- cpu-common.c | 3 + hw/arm/virt.c | 33 +-- hw/gpio/pl061.c | 16 +- hw/vmapple/vmapple.c | 4 +- target/arm/cpu.c | 2 +- target/arm/cpu64.c | 8 +- target/arm/helper.c | 2 +- target/arm/hvf/hvf.c | 244 +++++++++++++--------- target/arm/tcg/psci.c | 3 + target/i386/hvf/hvf.c | 484 +++++++++++++++++++++++--------------------- target/i386/hvf/x86hvf.c | 4 +- target/arm/hvf/trace-events | 6 +- target/arm/trace-events | 3 + trace-events | 2 + 20 files changed, 511 insertions(+), 399 deletions(-)
From: Philippe Mathieu-Daudé <philmd@linaro.org> uint8_t is good enough to hold a property "between 0 and 0xff". Define pullups/pulldowns properties using DEFINE_PROP_UINT8() macro, remove unnecessary range checks in pl061_realize(). Update the two caller sites. Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org> Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- hw/arm/virt.c | 4 ++-- hw/gpio/pl061.c | 16 ++++------------ hw/vmapple/vmapple.c | 4 ++-- 3 files changed, 8 insertions(+), 16 deletions(-) diff --git a/hw/arm/virt.c b/hw/arm/virt.c index XXXXXXX..XXXXXXX 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -XXX,XX +XXX,XX @@ static void create_gpio_devices(const VirtMachineState *vms, int gpio, pl061_dev = qdev_new("pl061"); /* Pull lines down to 0 if not driven by the PL061 */ - qdev_prop_set_uint32(pl061_dev, "pullups", 0); - qdev_prop_set_uint32(pl061_dev, "pulldowns", 0xff); + qdev_prop_set_uint8(pl061_dev, "pullups", 0); + qdev_prop_set_uint8(pl061_dev, "pulldowns", 0xff); s = SYS_BUS_DEVICE(pl061_dev); sysbus_realize_and_unref(s, &error_fatal); memory_region_add_subregion(mem, base, sysbus_mmio_get_region(s, 0)); diff --git a/hw/gpio/pl061.c b/hw/gpio/pl061.c index XXXXXXX..XXXXXXX 100644 --- a/hw/gpio/pl061.c +++ b/hw/gpio/pl061.c @@ -XXX,XX +XXX,XX @@ struct PL061State { qemu_irq out[N_GPIOS]; const unsigned char *id; /* Properties, for non-Luminary PL061 */ - uint32_t pullups; - uint32_t pulldowns; + uint8_t pullups; + uint8_t pulldowns; }; static const VMStateDescription vmstate_pl061 = { @@ -XXX,XX +XXX,XX @@ static void pl061_realize(DeviceState *dev, Error **errp) { PL061State *s = PL061(dev); - if (s->pullups > 0xff) { - error_setg(errp, "pullups property must be between 0 and 0xff"); - return; - } - if (s->pulldowns > 0xff) { - error_setg(errp, "pulldowns property must be between 0 and 0xff"); - return; - } if (s->pullups & s->pulldowns) { error_setg(errp, "no bit may be set both in pullups and pulldowns"); return; @@ -XXX,XX +XXX,XX @@ static void pl061_realize(DeviceState *dev, Error **errp) } static const Property pl061_props[] = { - DEFINE_PROP_UINT32("pullups", PL061State, pullups, 0xff), - DEFINE_PROP_UINT32("pulldowns", PL061State, pulldowns, 0x0), + DEFINE_PROP_UINT8("pullups", PL061State, pullups, 0xff), + DEFINE_PROP_UINT8("pulldowns", PL061State, pulldowns, 0x0), }; static void pl061_class_init(ObjectClass *klass, const void *data) diff --git a/hw/vmapple/vmapple.c b/hw/vmapple/vmapple.c index XXXXXXX..XXXXXXX 100644 --- a/hw/vmapple/vmapple.c +++ b/hw/vmapple/vmapple.c @@ -XXX,XX +XXX,XX @@ static void create_gpio_devices(const VMAppleMachineState *vms, int gpio, pl061_dev = qdev_new("pl061"); /* Pull lines down to 0 if not driven by the PL061 */ - qdev_prop_set_uint32(pl061_dev, "pullups", 0); - qdev_prop_set_uint32(pl061_dev, "pulldowns", 0xff); + qdev_prop_set_uint8(pl061_dev, "pullups", 0); + qdev_prop_set_uint8(pl061_dev, "pulldowns", 0xff); s = SYS_BUS_DEVICE(pl061_dev); sysbus_realize_and_unref(s, &error_fatal); memory_region_add_subregion(mem, base, sysbus_mmio_get_region(s, 0)); -- 2.43.0
The virt machine now supports creating multiple SMMUv3 instances, each associated with a separate PCIe root complex. Update the documentation with an example. Signed-off-by: Shameer Kolothum <skolothumtho@nvidia.com> [PMM: some minor wording tweaks] Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Eric Auger <eric.auger@redhat.com> Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- docs/system/arm/virt.rst | 35 +++++++++++++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/docs/system/arm/virt.rst b/docs/system/arm/virt.rst index XXXXXXX..XXXXXXX 100644 --- a/docs/system/arm/virt.rst +++ b/docs/system/arm/virt.rst @@ -XXX,XX +XXX,XX @@ The virt board supports: - An RTC - The fw_cfg device that allows a guest to obtain data from QEMU - A PL061 GPIO controller -- An optional SMMUv3 IOMMU +- An optional machine-wide SMMUv3 IOMMU +- User-creatable SMMUv3 devices (see below for example) - hotpluggable DIMMs - hotpluggable NVDIMMs - An MSI controller (GICv2M or ITS). GICv2M is selected by default along @@ -XXX,XX +XXX,XX @@ iommu ``none`` Don't create an IOMMU (the default) ``smmuv3`` - Create an SMMUv3 + Create a machine-wide SMMUv3. default-bus-bypass-iommu Set ``on``/``off`` to enable/disable `bypass_iommu @@ -XXX,XX +XXX,XX @@ x-oem-table-id Set string (up to 8 bytes) to override the default value of field OEM Table ID in ACPI table header. +SMMU configuration +"""""""""""""""""" + +Machine-wide SMMUv3 IOMMU + Setting the machine-specific option ``iommu=smmuv3`` causes QEMU to + create a single, machine-wide SMMUv3 instance that applies to all + devices in the PCIe topology. + + For information about selectively bypassing devices, refer to + ``docs/bypass-iommu.txt``. + +User-creatable SMMUv3 devices + You can use the ``-device arm-smmuv3`` option to create multiple + user-defined SMMUv3 devices, each associated with a separate PCIe + root complex. This is only permitted if the machine-wide SMMUv3 + (``iommu=smmuv3``) option is not used. Each ``arm-smmuv3`` device + uses the ``primary-bus`` sub-option to specify which PCIe root + complex it is associated with. + + This model is useful when you want to mirror a host configuration where + each NUMA node typically has its own SMMU, allowing the VM topology to + align more closely with the host’s hardware layout. + + Example:: + + -device arm-smmuv3,primary-bus=pcie.0,id=smmuv3.0 + ... + -device pxb-pcie,id=pcie.1,numa_node=1 + -device arm-smmuv3,primary-bus=pcie.1,id=smmuv3.1 + Linux guest kernel configuration """""""""""""""""""""""""""""""" -- 2.43.0
Currently our security policy defines a "virtualization use case" where we consider bugs to be security issues, and a "non-virtualization use case" where we do not make any security guarantees and don't consider bugs to be security issues. The rationale for this split is that much code in QEMU is older and was not written with malicious guests in mind, and we don't have the resources to audit, fix and defend it. So instead we inform users about what the can in practice rely on as a security barrier, and what they can't. We don't currently restrict the "virtualization use case" to any particular set of machine types. This means that we have effectively barred ourselves from adding KVM support to any machine type that we don't want to put into the "bugs are security issues" category, even if it would be useful for users to be able to get better performance with a trusted guest by enabling KVM. This seems an unnecessary restriction, and in practice the set of machine types it makes sense to use for untrusted-guest virtualization is quite small. Specifically, we would like to be able to enable the use of KVM with the imx8 development board machine types, but we don't want to commit ourselves to having to support those SoC models and device models as part of QEMU's security boundary: https://lore.kernel.org/qemu-devel/20250629204851.1778-3-shentey@gmail.com/ This patch updates the security policy to explicitly list the machine types we consider to be useful for the "virtualization use case". Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Acked-by: Christian Borntraeger <borntraeger@linux.ibm.com> Reviewed-by: Bibo Mao <maobibo@loongson.cn> Reviewed-by: Thomas Huth <thuth@redhat.com> Reviewed-by: Harsh Prateek Bora <harshpb@linux.ibm.com> Reviewed-by: Bernhard Beschow <shentey@gmail.com> Message-id: 20251016131159.750480-1-peter.maydell@linaro.org Acked-by: Markus Armbruster <armbru@redhat.com> --- docs/system/security.rst | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/docs/system/security.rst b/docs/system/security.rst index XXXXXXX..XXXXXXX 100644 --- a/docs/system/security.rst +++ b/docs/system/security.rst @@ -XXX,XX +XXX,XX @@ malicious: Bugs affecting these entities are evaluated on whether they can cause damage in real-world use cases and treated as security bugs if this is the case. +To be covered by this security support policy you must: + +- use a virtualization accelerator like KVM or HVF +- use one of the machine types listed below + +It may be possible to use other machine types with a virtualization +accelerator to provide improved performance with a trusted guest +workload, but any machine type not listed here should not be +considered to be providing guest isolation or security guarantees, +and falls under the "non-virtualization use case". + +Supported machine types for the virtualization use case, by target architecture: + +aarch64 + ``virt`` +i386, x86_64 + ``microvm``, ``xenfv``, ``xenpv``, ``xenpvh``, ``pc``, ``q35`` +s390x + ``s390-ccw-virtio`` +loongarch64: + ``virt`` +ppc64: + ``pseries`` +riscv32, riscv64: + ``virt`` + Non-virtualization Use Case ''''''''''''''''''''''''''' -- 2.43.0
Before commit f76cee647c ("target/arm: Introduce mmu indexes for GCS") it was impossible for arm_to_core_mmu_idx() to return an invalid core MMU index, because NB_MMU_MODES was 16 and ARM_MMU_IDX_COREIDX_MASK was 0xf. That commit raises ARM_MMU_IDX_COREIDX_MASK to 0x1f and NB_MMU_MODES to 22, so it's now possible for a bogus Arm mmu index to result in an out of range core mmu index (which can then get used as an array index in the CPUTLB struct arrays). Coverity complains that this might result in an out-of-bounds access. The out-of-bounds access can't happen because we construct all the ARMMMUIdx values we will use for TLBs to have valid core MMU indexes in the COREIDX field. But we can add an assert() so that if we ever do end up operating on a corrupted or wrong ARMMMUIdx value we get an assert rather than silently indexing off the end of an array. This should also make Coverity happier. Coverity: CID 1641404 Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20251023101339.1983809-1-peter.maydell@linaro.org --- target/arm/internals.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/target/arm/internals.h b/target/arm/internals.h index XXXXXXX..XXXXXXX 100644 --- a/target/arm/internals.h +++ b/target/arm/internals.h @@ -XXX,XX +XXX,XX @@ bool arm_cpu_tlb_fill_align(CPUState *cs, CPUTLBEntryFull *out, vaddr addr, static inline int arm_to_core_mmu_idx(ARMMMUIdx mmu_idx) { - return mmu_idx & ARM_MMU_IDX_COREIDX_MASK; + int coreidx = mmu_idx & ARM_MMU_IDX_COREIDX_MASK; + assert(coreidx < NB_MMU_MODES); + return coreidx; } static inline ARMMMUIdx core_to_arm_mmu_idx(CPUARMState *env, int mmu_idx) -- 2.43.0
From: Philippe Mathieu-Daudé <philmd@linaro.org> This machine has been supported for a period of more than 6 years. According to our versioned machine support policy (see commit ce80c4fa6ff "docs: document special exception for machine type deprecation & removal") it can now be removed. Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org> Message-id: 20251020094022.68768-2-philmd@linaro.org Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- hw/arm/virt.c | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/hw/arm/virt.c b/hw/arm/virt.c index XXXXXXX..XXXXXXX 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -XXX,XX +XXX,XX @@ static void virt_machine_4_2_options(MachineClass *mc) vmc->kvm_no_adjvtime = true; } DEFINE_VIRT_MACHINE(4, 2) - -static void virt_machine_4_1_options(MachineClass *mc) -{ - VirtMachineClass *vmc = VIRT_MACHINE_CLASS(OBJECT_CLASS(mc)); - - virt_machine_4_2_options(mc); - compat_props_add(mc->compat_props, hw_compat_4_1, hw_compat_4_1_len); - vmc->no_ged = true; - mc->auto_enable_numa_with_memhp = false; -} -DEFINE_VIRT_MACHINE(4, 1) -- 2.43.0
From: Philippe Mathieu-Daudé <philmd@linaro.org> The VirtMachineClass::no_ged field was only used by virt-4.1 machine, which got removed. Remove it as now unused. Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org> Message-id: 20251020094022.68768-3-philmd@linaro.org Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- include/hw/arm/virt.h | 1 - hw/arm/virt.c | 3 +-- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h index XXXXXXX..XXXXXXX 100644 --- a/include/hw/arm/virt.h +++ b/include/hw/arm/virt.h @@ -XXX,XX +XXX,XX @@ struct VirtMachineClass { MachineClass parent; bool no_tcg_its; bool no_highmem_compact; - bool no_ged; /* Machines < 4.2 have no support for ACPI GED device */ bool kvm_no_adjvtime; bool no_kvm_steal_time; bool acpi_expose_flash; diff --git a/hw/arm/virt.c b/hw/arm/virt.c index XXXXXXX..XXXXXXX 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -XXX,XX +XXX,XX @@ static void machvirt_init(MachineState *machine) int n, virt_max_cpus; bool firmware_loaded; bool aarch64 = true; - bool has_ged = !vmc->no_ged; unsigned int smp_cpus = machine->smp.cpus; unsigned int max_cpus = machine->smp.max_cpus; @@ -XXX,XX +XXX,XX @@ static void machvirt_init(MachineState *machine) create_pcie(vms); create_cxl_host_reg_region(vms); - if (has_ged && aarch64 && firmware_loaded && virt_is_acpi_enabled(vms)) { + if (aarch64 && firmware_loaded && virt_is_acpi_enabled(vms)) { vms->acpi_dev = create_acpi_ged(vms); vms->generic_error_notifier.notify = virt_generic_error_req; notifier_list_add(&acpi_generic_error_notifiers, -- 2.43.0
From: Philippe Mathieu-Daudé <philmd@linaro.org> This machine has been supported for a period of more than 6 years. According to our versioned machine support policy (see commit ce80c4fa6ff "docs: document special exception for machine type deprecation & removal") it can now be removed. Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org> Message-id: 20251020094022.68768-4-philmd@linaro.org Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- hw/arm/virt.c | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/hw/arm/virt.c b/hw/arm/virt.c index XXXXXXX..XXXXXXX 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -XXX,XX +XXX,XX @@ static void virt_machine_5_0_options(MachineClass *mc) mc->auto_enable_numa_with_memdev = false; } DEFINE_VIRT_MACHINE(5, 0) - -static void virt_machine_4_2_options(MachineClass *mc) -{ - VirtMachineClass *vmc = VIRT_MACHINE_CLASS(OBJECT_CLASS(mc)); - - virt_machine_5_0_options(mc); - compat_props_add(mc->compat_props, hw_compat_4_2, hw_compat_4_2_len); - vmc->kvm_no_adjvtime = true; -} -DEFINE_VIRT_MACHINE(4, 2) -- 2.43.0
From: Philippe Mathieu-Daudé <philmd@linaro.org> The VirtMachineClass::kvm_no_adjvtime field was only used by the virt-4.2 machine, which got removed. Remove it as now unused, but keep the ARMCPU homonym property. Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org> Message-id: 20251020094022.68768-5-philmd@linaro.org Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- include/hw/arm/virt.h | 1 - hw/arm/virt.c | 5 ----- 2 files changed, 6 deletions(-) diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h index XXXXXXX..XXXXXXX 100644 --- a/include/hw/arm/virt.h +++ b/include/hw/arm/virt.h @@ -XXX,XX +XXX,XX @@ struct VirtMachineClass { MachineClass parent; bool no_tcg_its; bool no_highmem_compact; - bool kvm_no_adjvtime; bool no_kvm_steal_time; bool acpi_expose_flash; bool no_secure_gpio; diff --git a/hw/arm/virt.c b/hw/arm/virt.c index XXXXXXX..XXXXXXX 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -XXX,XX +XXX,XX @@ static void machvirt_init(MachineState *machine) object_property_set_bool(cpuobj, "has_el2", false, NULL); } - if (vmc->kvm_no_adjvtime && - object_property_find(cpuobj, "kvm-no-adjvtime")) { - object_property_set_bool(cpuobj, "kvm-no-adjvtime", true, NULL); - } - if (vmc->no_kvm_steal_time && object_property_find(cpuobj, "kvm-steal-time")) { object_property_set_bool(cpuobj, "kvm-steal-time", false, NULL); -- 2.43.0
From: Philippe Mathieu-Daudé <philmd@linaro.org> hv_vcpu_config_create() is documented in <Hypervisor/hv_vcpu_config.h> as: /*! @abstract Creates a vcpu configuration object. @result A new vcpu configuration object. This should be released with os_release when no longer used. */ OS_OBJECT_RETURNS_RETAINED OS_WARN_RESULT hv_vcpu_config_t hv_vcpu_config_create(void); Release the memory allocated by hv_vcpu_config_create() with os_release(). Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Reviewed-by: Mads Ynddal <mads@ynddal.dk> Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- target/arm/hvf/hvf.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/target/arm/hvf/hvf.c b/target/arm/hvf/hvf.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/hvf/hvf.c +++ b/target/arm/hvf/hvf.c @@ -XXX,XX +XXX,XX @@ void hvf_arm_init_debug(void) max_hw_wps = hvf_arm_num_wrps(config); hw_watchpoints = g_array_sized_new(true, true, sizeof(HWWatchpoint), max_hw_wps); + + os_release(config); } #define SYSREG_OP0_SHIFT 20 -- 2.43.0
From: Philippe Mathieu-Daudé <philmd@linaro.org> Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- target/arm/hvf/hvf.c | 1 + target/arm/hvf/trace-events | 1 + 2 files changed, 2 insertions(+) diff --git a/target/arm/hvf/hvf.c b/target/arm/hvf/hvf.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/hvf/hvf.c +++ b/target/arm/hvf/hvf.c @@ -XXX,XX +XXX,XX @@ int hvf_arch_init_vcpu(CPUState *cpu) void hvf_kick_vcpu_thread(CPUState *cpu) { + trace_hvf_kick_vcpu_thread(cpu->cpu_index, cpu->stop); cpus_kick_thread(cpu); hv_vcpus_exit(&cpu->accel->fd, 1); } diff --git a/target/arm/hvf/trace-events b/target/arm/hvf/trace-events index XXXXXXX..XXXXXXX 100644 --- a/target/arm/hvf/trace-events +++ b/target/arm/hvf/trace-events @@ -XXX,XX +XXX,XX @@ hvf_psci_call(uint64_t x0, uint64_t x1, uint64_t x2, uint64_t x3, uint32_t cpuid hvf_vgic_write(const char *name, uint64_t val) "vgic write to %s [val=0x%016"PRIx64"]" hvf_vgic_read(const char *name, uint64_t val) "vgic read from %s [val=0x%016"PRIx64"]" hvf_illegal_guest_state(void) "HV_ILLEGAL_GUEST_STATE" +hvf_kick_vcpu_thread(unsigned cpuidx, bool stop) "cpu:%u stop:%u" -- 2.43.0
From: Philippe Mathieu-Daudé <philmd@linaro.org> hv_vcpus_exit() returns a hv_return_t enum type (defined in <Hypervisor/hv_error.h>). Assert we succeeded, as we are not ready to handle any error path. Suggested-by: Alex Bennée <alex.bennee@linaro.org> Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org> Reviewed-by: Mads Ynddal <mads@ynddal.dk> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- target/arm/hvf/hvf.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/target/arm/hvf/hvf.c b/target/arm/hvf/hvf.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/hvf/hvf.c +++ b/target/arm/hvf/hvf.c @@ -XXX,XX +XXX,XX @@ int hvf_arch_init_vcpu(CPUState *cpu) void hvf_kick_vcpu_thread(CPUState *cpu) { + hv_return_t ret; trace_hvf_kick_vcpu_thread(cpu->cpu_index, cpu->stop); cpus_kick_thread(cpu); - hv_vcpus_exit(&cpu->accel->fd, 1); + ret = hv_vcpus_exit(&cpu->accel->fd, 1); + assert_hvf_ok(ret); } static void hvf_raise_exception(CPUState *cpu, uint32_t excp, -- 2.43.0
From: Philippe Mathieu-Daudé <philmd@linaro.org> hv_vcpu_set_vtimer_mask() returns a hv_return_t enum type (defined in <Hypervisor/hv_error.h>). Assert we succeeded, as we are not ready to handle any error path. Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Reviewed-by: Mads Ynddal <mads@ynddal.dk> Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- target/arm/hvf/hvf.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/target/arm/hvf/hvf.c b/target/arm/hvf/hvf.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/hvf/hvf.c +++ b/target/arm/hvf/hvf.c @@ -XXX,XX +XXX,XX @@ static void hvf_sync_vtimer(CPUState *cpu) if (!irq_state) { /* Timer no longer asserting, we can unmask it */ - hv_vcpu_set_vtimer_mask(cpu->accel->fd, false); + r = hv_vcpu_set_vtimer_mask(cpu->accel->fd, false); + assert_hvf_ok(r); cpu->accel->vtimer_masked = false; } } -- 2.43.0
From: Philippe Mathieu-Daudé <philmd@linaro.org> hvf_vcpu_exec() is implemented per target, rename it as hvf_arch_vcpu_exec(), following the per target pattern. Since it calls hv_vcpu_run(), mention it must be called on the vCPU. Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Reviewed-by: Mads Ynddal <mads@ynddal.dk> Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- include/system/hvf_int.h | 4 +++- accel/hvf/hvf-accel-ops.c | 2 +- target/arm/hvf/hvf.c | 2 +- target/i386/hvf/hvf.c | 2 +- 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/include/system/hvf_int.h b/include/system/hvf_int.h index XXXXXXX..XXXXXXX 100644 --- a/include/system/hvf_int.h +++ b/include/system/hvf_int.h @@ -XXX,XX +XXX,XX @@ int hvf_arch_init(void); hv_return_t hvf_arch_vm_create(MachineState *ms, uint32_t pa_range); int hvf_arch_init_vcpu(CPUState *cpu); void hvf_arch_vcpu_destroy(CPUState *cpu); -int hvf_vcpu_exec(CPUState *); hvf_slot *hvf_find_overlap_slot(uint64_t, uint64_t); int hvf_put_registers(CPUState *); int hvf_get_registers(CPUState *); void hvf_kick_vcpu_thread(CPUState *cpu); +/* Must be called by the owning thread */ +int hvf_arch_vcpu_exec(CPUState *); + struct hvf_sw_breakpoint { vaddr pc; vaddr saved_insn; diff --git a/accel/hvf/hvf-accel-ops.c b/accel/hvf/hvf-accel-ops.c index XXXXXXX..XXXXXXX 100644 --- a/accel/hvf/hvf-accel-ops.c +++ b/accel/hvf/hvf-accel-ops.c @@ -XXX,XX +XXX,XX @@ static void *hvf_cpu_thread_fn(void *arg) do { qemu_process_cpu_events(cpu); if (cpu_can_run(cpu)) { - r = hvf_vcpu_exec(cpu); + r = hvf_arch_vcpu_exec(cpu); if (r == EXCP_DEBUG) { cpu_handle_guest_debug(cpu); } diff --git a/target/arm/hvf/hvf.c b/target/arm/hvf/hvf.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/hvf/hvf.c +++ b/target/arm/hvf/hvf.c @@ -XXX,XX +XXX,XX @@ static void hvf_sync_vtimer(CPUState *cpu) } } -int hvf_vcpu_exec(CPUState *cpu) +int hvf_arch_vcpu_exec(CPUState *cpu) { ARMCPU *arm_cpu = ARM_CPU(cpu); CPUARMState *env = &arm_cpu->env; diff --git a/target/i386/hvf/hvf.c b/target/i386/hvf/hvf.c index XXXXXXX..XXXXXXX 100644 --- a/target/i386/hvf/hvf.c +++ b/target/i386/hvf/hvf.c @@ -XXX,XX +XXX,XX @@ void hvf_simulate_wrmsr(CPUState *cs) printf("write msr %llx\n", RCX(cs));*/ } -int hvf_vcpu_exec(CPUState *cpu) +int hvf_arch_vcpu_exec(CPUState *cpu) { X86CPU *x86_cpu = X86_CPU(cpu); CPUX86State *env = &x86_cpu->env; -- 2.43.0
From: Philippe Mathieu-Daudé <philmd@linaro.org> hvf_put_registers() and hvf_get_registers() are implemented per target, rename them using the 'hvf_arch_' prefix following the per target pattern. Since they call hv_vcpu_set_reg() / hv_vcpu_get_reg(), mention they must be called on the vCPU. Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Reviewed-by: Mads Ynddal <mads@ynddal.dk> Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- include/system/hvf_int.h | 6 ++++-- accel/hvf/hvf-accel-ops.c | 2 +- target/arm/hvf/hvf.c | 8 +++++--- target/i386/hvf/hvf.c | 2 +- target/i386/hvf/x86hvf.c | 4 ++-- 5 files changed, 13 insertions(+), 9 deletions(-) diff --git a/include/system/hvf_int.h b/include/system/hvf_int.h index XXXXXXX..XXXXXXX 100644 --- a/include/system/hvf_int.h +++ b/include/system/hvf_int.h @@ -XXX,XX +XXX,XX @@ hv_return_t hvf_arch_vm_create(MachineState *ms, uint32_t pa_range); int hvf_arch_init_vcpu(CPUState *cpu); void hvf_arch_vcpu_destroy(CPUState *cpu); hvf_slot *hvf_find_overlap_slot(uint64_t, uint64_t); -int hvf_put_registers(CPUState *); -int hvf_get_registers(CPUState *); void hvf_kick_vcpu_thread(CPUState *cpu); /* Must be called by the owning thread */ int hvf_arch_vcpu_exec(CPUState *); +/* Must be called by the owning thread */ +int hvf_arch_put_registers(CPUState *); +/* Must be called by the owning thread */ +int hvf_arch_get_registers(CPUState *); struct hvf_sw_breakpoint { vaddr pc; diff --git a/accel/hvf/hvf-accel-ops.c b/accel/hvf/hvf-accel-ops.c index XXXXXXX..XXXXXXX 100644 --- a/accel/hvf/hvf-accel-ops.c +++ b/accel/hvf/hvf-accel-ops.c @@ -XXX,XX +XXX,XX @@ hvf_slot *hvf_find_overlap_slot(uint64_t start, uint64_t size) static void do_hvf_cpu_synchronize_state(CPUState *cpu, run_on_cpu_data arg) { if (!cpu->vcpu_dirty) { - hvf_get_registers(cpu); + hvf_arch_get_registers(cpu); cpu->vcpu_dirty = true; } } diff --git a/target/arm/hvf/hvf.c b/target/arm/hvf/hvf.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/hvf/hvf.c +++ b/target/arm/hvf/hvf.c @@ -XXX,XX +XXX,XX @@ static const hv_sys_reg_t hvf_sreg_list[] = { #undef DEF_SYSREG -int hvf_get_registers(CPUState *cpu) +int hvf_arch_get_registers(CPUState *cpu) { ARMCPU *arm_cpu = ARM_CPU(cpu); CPUARMState *env = &arm_cpu->env; @@ -XXX,XX +XXX,XX @@ int hvf_get_registers(CPUState *cpu) return 0; } -int hvf_put_registers(CPUState *cpu) +int hvf_arch_put_registers(CPUState *cpu) { ARMCPU *arm_cpu = ARM_CPU(cpu); CPUARMState *env = &arm_cpu->env; @@ -XXX,XX +XXX,XX @@ int hvf_put_registers(CPUState *cpu) static void flush_cpu_state(CPUState *cpu) { if (cpu->vcpu_dirty) { - hvf_put_registers(cpu); + hvf_arch_put_registers(cpu); cpu->vcpu_dirty = false; } } +/* Must be called by the owning thread */ static void hvf_set_reg(CPUState *cpu, int rt, uint64_t val) { hv_return_t r; @@ -XXX,XX +XXX,XX @@ static void hvf_set_reg(CPUState *cpu, int rt, uint64_t val) } } +/* Must be called by the owning thread */ static uint64_t hvf_get_reg(CPUState *cpu, int rt) { uint64_t val = 0; diff --git a/target/i386/hvf/hvf.c b/target/i386/hvf/hvf.c index XXXXXXX..XXXXXXX 100644 --- a/target/i386/hvf/hvf.c +++ b/target/i386/hvf/hvf.c @@ -XXX,XX +XXX,XX @@ int hvf_arch_vcpu_exec(CPUState *cpu) do { if (cpu->vcpu_dirty) { - hvf_put_registers(cpu); + hvf_arch_put_registers(cpu); cpu->vcpu_dirty = false; } diff --git a/target/i386/hvf/x86hvf.c b/target/i386/hvf/x86hvf.c index XXXXXXX..XXXXXXX 100644 --- a/target/i386/hvf/x86hvf.c +++ b/target/i386/hvf/x86hvf.c @@ -XXX,XX +XXX,XX @@ void hvf_get_msrs(CPUState *cs) env->tsc = rdtscp() + rvmcs(cs->accel->fd, VMCS_TSC_OFFSET); } -int hvf_put_registers(CPUState *cs) +int hvf_arch_put_registers(CPUState *cs) { X86CPU *x86cpu = X86_CPU(cs); CPUX86State *env = &x86cpu->env; @@ -XXX,XX +XXX,XX @@ int hvf_put_registers(CPUState *cs) return 0; } -int hvf_get_registers(CPUState *cs) +int hvf_arch_get_registers(CPUState *cs) { X86CPU *x86cpu = X86_CPU(cs); CPUX86State *env = &x86cpu->env; -- 2.43.0
From: Philippe Mathieu-Daudé <philmd@linaro.org> Since flush_cpu_state() calls hvf_arch_put_registers(), which must run on a vCPU, it also must. Mention it. Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Reviewed-by: Mads Ynddal <mads@ynddal.dk> Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- target/arm/hvf/hvf.c | 1 + 1 file changed, 1 insertion(+) diff --git a/target/arm/hvf/hvf.c b/target/arm/hvf/hvf.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/hvf/hvf.c +++ b/target/arm/hvf/hvf.c @@ -XXX,XX +XXX,XX @@ int hvf_arch_put_registers(CPUState *cpu) return 0; } +/* Must be called by the owning thread */ static void flush_cpu_state(CPUState *cpu) { if (cpu->vcpu_dirty) { -- 2.43.0
From: Philippe Mathieu-Daudé <philmd@linaro.org> hvf_arch_init_vcpu(), along with hvf_put_guest_debug_registers() and hvf_put_gdbstub_debug_registers(), calls hv_vcpu_set_sys_reg(), which must run on a vCPU. Mention they also must. Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Reviewed-by: Mads Ynddal <mads@ynddal.dk> Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- include/system/hvf_int.h | 3 ++- target/arm/hvf/hvf.c | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/include/system/hvf_int.h b/include/system/hvf_int.h index XXXXXXX..XXXXXXX 100644 --- a/include/system/hvf_int.h +++ b/include/system/hvf_int.h @@ -XXX,XX +XXX,XX @@ void assert_hvf_ok_impl(hv_return_t ret, const char *file, unsigned int line, const char *hvf_return_string(hv_return_t ret); int hvf_arch_init(void); hv_return_t hvf_arch_vm_create(MachineState *ms, uint32_t pa_range); -int hvf_arch_init_vcpu(CPUState *cpu); void hvf_arch_vcpu_destroy(CPUState *cpu); hvf_slot *hvf_find_overlap_slot(uint64_t, uint64_t); void hvf_kick_vcpu_thread(CPUState *cpu); +/* Must be called by the owning thread */ +int hvf_arch_init_vcpu(CPUState *cpu); /* Must be called by the owning thread */ int hvf_arch_vcpu_exec(CPUState *); /* Must be called by the owning thread */ diff --git a/target/arm/hvf/hvf.c b/target/arm/hvf/hvf.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/hvf/hvf.c +++ b/target/arm/hvf/hvf.c @@ -XXX,XX +XXX,XX @@ void hvf_arch_remove_all_hw_breakpoints(void) * Update the vCPU with the gdbstub's view of debug registers. This view * consists of all hardware breakpoints and watchpoints inserted so far while * debugging the guest. + * Must be called by the owning thread. */ static void hvf_put_gdbstub_debug_registers(CPUState *cpu) { @@ -XXX,XX +XXX,XX @@ static void hvf_put_gdbstub_debug_registers(CPUState *cpu) /* * Update the vCPU with the guest's view of debug registers. This view is kept * in the environment at all times. + * Must be called by the owning thread. */ static void hvf_put_guest_debug_registers(CPUState *cpu) { -- 2.43.0
From: Philippe Mathieu-Daudé <philmd@linaro.org> Since hvf_sync_vtimer() calls hv_vcpu_get_sys_reg(), which must run on a vCPU, it also must. Mention it. Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org> Reviewed-by: Mads Ynddal <mads@ynddal.dk> Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- target/arm/hvf/hvf.c | 1 + 1 file changed, 1 insertion(+) diff --git a/target/arm/hvf/hvf.c b/target/arm/hvf/hvf.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/hvf/hvf.c +++ b/target/arm/hvf/hvf.c @@ -XXX,XX +XXX,XX @@ static void hvf_wfi(CPUState *cpu) hvf_wait_for_ipi(cpu, &ts); } +/* Must be called by the owning thread */ static void hvf_sync_vtimer(CPUState *cpu) { ARMCPU *arm_cpu = ARM_CPU(cpu); -- 2.43.0
From: Philippe Mathieu-Daudé <philmd@linaro.org> Since hvf_arch_set_traps() calls hv_vcpu_set_trap_debug_exceptions() and hv_vcpu_set_trap_debug_reg_accesses(), which must run on a vCPU, it also must. Mention it. Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org> Reviewed-by: Mads Ynddal <mads@ynddal.dk> Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- target/arm/hvf/hvf.c | 1 + 1 file changed, 1 insertion(+) diff --git a/target/arm/hvf/hvf.c b/target/arm/hvf/hvf.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/hvf/hvf.c +++ b/target/arm/hvf/hvf.c @@ -XXX,XX +XXX,XX @@ static inline bool hvf_arm_hw_debug_active(CPUState *cpu) return ((cur_hw_wps > 0) || (cur_hw_bps > 0)); } +/* Must be called by the owning thread */ static void hvf_arch_set_traps(CPUState *cpu) { bool should_enable_traps = false; -- 2.43.0
From: Philippe Mathieu-Daudé <philmd@linaro.org> Since hvf_arch_update_guest_debug() calls hvf_arch_set_traps() and hvf_arch_update_guest_debug(), which must run on a vCPU, it also must. Mention it. Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org> Reviewed-by: Mads Ynddal <mads@ynddal.dk> Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- include/system/hvf_int.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/system/hvf_int.h b/include/system/hvf_int.h index XXXXXXX..XXXXXXX 100644 --- a/include/system/hvf_int.h +++ b/include/system/hvf_int.h @@ -XXX,XX +XXX,XX @@ int hvf_arch_vcpu_exec(CPUState *); int hvf_arch_put_registers(CPUState *); /* Must be called by the owning thread */ int hvf_arch_get_registers(CPUState *); +/* Must be called by the owning thread */ +void hvf_arch_update_guest_debug(CPUState *cpu); struct hvf_sw_breakpoint { vaddr pc; @@ -XXX,XX +XXX,XX @@ void hvf_arch_remove_all_hw_breakpoints(void); * handled by calling down to hvf_arch_update_guest_debug. */ int hvf_update_guest_debug(CPUState *cpu); -void hvf_arch_update_guest_debug(CPUState *cpu); /* * Return whether the guest supports debugging. -- 2.43.0
From: Philippe Mathieu-Daudé <philmd@linaro.org> Since hvf_inject_interrupts() calls hv_vcpu_set_pending_interrupt(), which must run on a vCPU, it also must. Mention it. Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org> Reviewed-by: Mads Ynddal <mads@ynddal.dk> Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- target/arm/hvf/hvf.c | 1 + 1 file changed, 1 insertion(+) diff --git a/target/arm/hvf/hvf.c b/target/arm/hvf/hvf.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/hvf/hvf.c +++ b/target/arm/hvf/hvf.c @@ -XXX,XX +XXX,XX @@ static int hvf_sysreg_write(CPUState *cpu, uint32_t reg, uint64_t val) return 1; } +/* Must be called by the owning thread */ static int hvf_inject_interrupts(CPUState *cpu) { if (cpu_test_interrupt(cpu, CPU_INTERRUPT_FIQ)) { -- 2.43.0
From: Philippe Mathieu-Daudé <philmd@linaro.org> Call hv_vcpu_destroy() to destroy our vCPU context. As hv_vcpu_destroy() must be called by the owning thread, document hvf_arch_vcpu_destroy() also does. Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Reviewed-by: Mads Ynddal <mads@ynddal.dk> Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- include/system/hvf_int.h | 3 ++- target/arm/hvf/hvf.c | 4 ++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/include/system/hvf_int.h b/include/system/hvf_int.h index XXXXXXX..XXXXXXX 100644 --- a/include/system/hvf_int.h +++ b/include/system/hvf_int.h @@ -XXX,XX +XXX,XX @@ void assert_hvf_ok_impl(hv_return_t ret, const char *file, unsigned int line, const char *hvf_return_string(hv_return_t ret); int hvf_arch_init(void); hv_return_t hvf_arch_vm_create(MachineState *ms, uint32_t pa_range); -void hvf_arch_vcpu_destroy(CPUState *cpu); hvf_slot *hvf_find_overlap_slot(uint64_t, uint64_t); void hvf_kick_vcpu_thread(CPUState *cpu); /* Must be called by the owning thread */ int hvf_arch_init_vcpu(CPUState *cpu); /* Must be called by the owning thread */ +void hvf_arch_vcpu_destroy(CPUState *cpu); +/* Must be called by the owning thread */ int hvf_arch_vcpu_exec(CPUState *); /* Must be called by the owning thread */ int hvf_arch_put_registers(CPUState *); diff --git a/target/arm/hvf/hvf.c b/target/arm/hvf/hvf.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/hvf/hvf.c +++ b/target/arm/hvf/hvf.c @@ -XXX,XX +XXX,XX @@ void hvf_arm_set_cpu_features_from_host(ARMCPU *cpu) void hvf_arch_vcpu_destroy(CPUState *cpu) { + hv_return_t ret; + + ret = hv_vcpu_destroy(cpu->accel->fd); + assert_hvf_ok(ret); } hv_return_t hvf_arch_vm_create(MachineState *ms, uint32_t pa_range) -- 2.43.0
From: Mohamed Mediouni <mohamed@unpredictable.fr> Hardcode MIDR because Apple deliberately doesn't expose a divergent MIDR across systems. Signed-off-by: Mohamed Mediouni <mohamed@unpredictable.fr> Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- target/arm/hvf/hvf.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/target/arm/hvf/hvf.c b/target/arm/hvf/hvf.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/hvf/hvf.c +++ b/target/arm/hvf/hvf.c @@ -XXX,XX +XXX,XX @@ static bool hvf_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) hv_vcpu_t fd; hv_return_t r = HV_SUCCESS; hv_vcpu_exit_t *exit; + uint64_t t; int i; ahcf->dtb_compatible = "arm,armv8"; @@ -XXX,XX +XXX,XX @@ static bool hvf_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) for (i = 0; i < ARRAY_SIZE(regs); i++) { r |= hv_vcpu_get_sys_reg(fd, regs[i].reg, regs[i].val); } - r |= hv_vcpu_get_sys_reg(fd, HV_SYS_REG_MIDR_EL1, &ahcf->midr); r |= hv_vcpu_destroy(fd); + /* + * Hardcode MIDR because Apple deliberately doesn't expose a divergent + * MIDR across systems. + */ + t = FIELD_DP64(0, MIDR_EL1, IMPLEMENTER, 0x61); /* Apple */ + t = FIELD_DP64(t, MIDR_EL1, ARCHITECTURE, 0xf); /* v7 or later */ + t = FIELD_DP64(t, MIDR_EL1, PARTNUM, 0); + t = FIELD_DP64(t, MIDR_EL1, VARIANT, 0); + t = FIELD_DP64(t, MIDR_EL1, REVISION, 0); + ahcf->midr = t; + clamp_id_aa64mmfr0_parange_to_ipa_size(&host_isar); /* -- 2.43.0
From: Philippe Mathieu-Daudé <philmd@linaro.org> Use index in the structure, dereference &host_isar.idregs[] once. Suggested-by: Richard Henderson <richard.henderson@linaro.org> Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org> Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- target/arm/hvf/hvf.c | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/target/arm/hvf/hvf.c b/target/arm/hvf/hvf.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/hvf/hvf.c +++ b/target/arm/hvf/hvf.c @@ -XXX,XX +XXX,XX @@ static void clamp_id_aa64mmfr0_parange_to_ipa_size(ARMISARegisters *isar) static bool hvf_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) { ARMISARegisters host_isar = {}; - const struct isar_regs { + static const struct isar_regs { int reg; - uint64_t *val; + ARMIDRegisterIdx index; } regs[] = { - { HV_SYS_REG_ID_AA64PFR0_EL1, &host_isar.idregs[ID_AA64PFR0_EL1_IDX] }, - { HV_SYS_REG_ID_AA64PFR1_EL1, &host_isar.idregs[ID_AA64PFR1_EL1_IDX] }, + { HV_SYS_REG_ID_AA64PFR0_EL1, ID_AA64PFR0_EL1_IDX }, + { HV_SYS_REG_ID_AA64PFR1_EL1, ID_AA64PFR1_EL1_IDX }, /* Add ID_AA64PFR2_EL1 here when HVF supports it */ - { HV_SYS_REG_ID_AA64DFR0_EL1, &host_isar.idregs[ID_AA64DFR0_EL1_IDX] }, - { HV_SYS_REG_ID_AA64DFR1_EL1, &host_isar.idregs[ID_AA64DFR1_EL1_IDX] }, - { HV_SYS_REG_ID_AA64ISAR0_EL1, &host_isar.idregs[ID_AA64ISAR0_EL1_IDX] }, - { HV_SYS_REG_ID_AA64ISAR1_EL1, &host_isar.idregs[ID_AA64ISAR1_EL1_IDX] }, + { HV_SYS_REG_ID_AA64DFR0_EL1, ID_AA64DFR0_EL1_IDX }, + { HV_SYS_REG_ID_AA64DFR1_EL1, ID_AA64DFR1_EL1_IDX }, + { HV_SYS_REG_ID_AA64ISAR0_EL1, ID_AA64ISAR0_EL1_IDX }, + { HV_SYS_REG_ID_AA64ISAR1_EL1, ID_AA64ISAR1_EL1_IDX }, /* Add ID_AA64ISAR2_EL1 here when HVF supports it */ - { HV_SYS_REG_ID_AA64MMFR0_EL1, &host_isar.idregs[ID_AA64MMFR0_EL1_IDX] }, - { HV_SYS_REG_ID_AA64MMFR1_EL1, &host_isar.idregs[ID_AA64MMFR1_EL1_IDX] }, - { HV_SYS_REG_ID_AA64MMFR2_EL1, &host_isar.idregs[ID_AA64MMFR2_EL1_IDX] }, + { HV_SYS_REG_ID_AA64MMFR0_EL1, ID_AA64MMFR0_EL1_IDX }, + { HV_SYS_REG_ID_AA64MMFR1_EL1, ID_AA64MMFR1_EL1_IDX }, + { HV_SYS_REG_ID_AA64MMFR2_EL1, ID_AA64MMFR2_EL1_IDX }, /* Add ID_AA64MMFR3_EL1 here when HVF supports it */ }; hv_vcpu_t fd; @@ -XXX,XX +XXX,XX @@ static bool hvf_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) } for (i = 0; i < ARRAY_SIZE(regs); i++) { - r |= hv_vcpu_get_sys_reg(fd, regs[i].reg, regs[i].val); + r |= hv_vcpu_get_sys_reg(fd, regs[i].reg, + &host_isar.idregs[regs[i].index]); } r |= hv_vcpu_destroy(fd); -- 2.43.0
From: Mohamed Mediouni <mohamed@unpredictable.fr> Creating a vCPU locks out APIs such as hv_gic_create(). As a result, switch to using the hv_vcpu_config_get_feature_reg interface. Besides, all the following methods must be run on a vCPU thread: - hv_vcpu_create() - hv_vcpu_get_sys_reg() - hv_vcpu_destroy() Signed-off-by: Mohamed Mediouni <mohamed@unpredictable.fr> Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> Tested-by: Philippe Mathieu-Daudé <philmd@linaro.org> Reviewed-by: Mads Ynddal <mads@ynddal.dk> Message-ID: <20250808070137.48716-3-mohamed@unpredictable.fr> [PMD: Release config calling os_release()] Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org> Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- target/arm/hvf/hvf.c | 35 ++++++++++++++--------------------- 1 file changed, 14 insertions(+), 21 deletions(-) diff --git a/target/arm/hvf/hvf.c b/target/arm/hvf/hvf.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/hvf/hvf.c +++ b/target/arm/hvf/hvf.c @@ -XXX,XX +XXX,XX @@ static bool hvf_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) { ARMISARegisters host_isar = {}; static const struct isar_regs { - int reg; + hv_feature_reg_t reg; ARMIDRegisterIdx index; } regs[] = { - { HV_SYS_REG_ID_AA64PFR0_EL1, ID_AA64PFR0_EL1_IDX }, - { HV_SYS_REG_ID_AA64PFR1_EL1, ID_AA64PFR1_EL1_IDX }, + { HV_FEATURE_REG_ID_AA64PFR0_EL1, ID_AA64PFR0_EL1_IDX }, + { HV_FEATURE_REG_ID_AA64PFR1_EL1, ID_AA64PFR1_EL1_IDX }, /* Add ID_AA64PFR2_EL1 here when HVF supports it */ - { HV_SYS_REG_ID_AA64DFR0_EL1, ID_AA64DFR0_EL1_IDX }, - { HV_SYS_REG_ID_AA64DFR1_EL1, ID_AA64DFR1_EL1_IDX }, - { HV_SYS_REG_ID_AA64ISAR0_EL1, ID_AA64ISAR0_EL1_IDX }, - { HV_SYS_REG_ID_AA64ISAR1_EL1, ID_AA64ISAR1_EL1_IDX }, + { HV_FEATURE_REG_ID_AA64DFR0_EL1, ID_AA64DFR0_EL1_IDX }, + { HV_FEATURE_REG_ID_AA64DFR1_EL1, ID_AA64DFR1_EL1_IDX }, + { HV_FEATURE_REG_ID_AA64ISAR0_EL1, ID_AA64ISAR0_EL1_IDX }, + { HV_FEATURE_REG_ID_AA64ISAR1_EL1, ID_AA64ISAR1_EL1_IDX }, /* Add ID_AA64ISAR2_EL1 here when HVF supports it */ - { HV_SYS_REG_ID_AA64MMFR0_EL1, ID_AA64MMFR0_EL1_IDX }, - { HV_SYS_REG_ID_AA64MMFR1_EL1, ID_AA64MMFR1_EL1_IDX }, - { HV_SYS_REG_ID_AA64MMFR2_EL1, ID_AA64MMFR2_EL1_IDX }, + { HV_FEATURE_REG_ID_AA64MMFR0_EL1, ID_AA64MMFR0_EL1_IDX }, + { HV_FEATURE_REG_ID_AA64MMFR1_EL1, ID_AA64MMFR1_EL1_IDX }, + { HV_FEATURE_REG_ID_AA64MMFR2_EL1, ID_AA64MMFR2_EL1_IDX }, /* Add ID_AA64MMFR3_EL1 here when HVF supports it */ }; - hv_vcpu_t fd; hv_return_t r = HV_SUCCESS; - hv_vcpu_exit_t *exit; + hv_vcpu_config_t config = hv_vcpu_config_create(); uint64_t t; int i; @@ -XXX,XX +XXX,XX @@ static bool hvf_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) (1ULL << ARM_FEATURE_PMU) | (1ULL << ARM_FEATURE_GENERIC_TIMER); - /* We set up a small vcpu to extract host registers */ - - if (hv_vcpu_create(&fd, &exit, NULL) != HV_SUCCESS) { - return false; - } - for (i = 0; i < ARRAY_SIZE(regs); i++) { - r |= hv_vcpu_get_sys_reg(fd, regs[i].reg, - &host_isar.idregs[regs[i].index]); + r |= hv_vcpu_config_get_feature_reg(config, regs[i].reg, + &host_isar.idregs[regs[i].index]); } - r |= hv_vcpu_destroy(fd); + os_release(config); /* * Hardcode MIDR because Apple deliberately doesn't expose a divergent -- 2.43.0
From: Philippe Mathieu-Daudé <philmd@linaro.org> Factor hvf_handle_exception() out of hvf_vcpu_exec(). Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org> Reviewed-by: Mads Ynddal <mads@ynddal.dk> Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- target/arm/hvf/hvf.c | 123 +++++++++++++++++++++++-------------------- 1 file changed, 65 insertions(+), 58 deletions(-) diff --git a/target/arm/hvf/hvf.c b/target/arm/hvf/hvf.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/hvf/hvf.c +++ b/target/arm/hvf/hvf.c @@ -XXX,XX +XXX,XX @@ static void hvf_sync_vtimer(CPUState *cpu) } } -int hvf_arch_vcpu_exec(CPUState *cpu) +static int hvf_handle_exception(CPUState *cpu, hv_vcpu_exit_exception_t *excp) { - ARMCPU *arm_cpu = ARM_CPU(cpu); - CPUARMState *env = &arm_cpu->env; - int ret; - hv_vcpu_exit_t *hvf_exit = cpu->accel->exit; - hv_return_t r; - bool advance_pc = false; - - if (!(cpu->singlestep_enabled & SSTEP_NOIRQ) && - hvf_inject_interrupts(cpu)) { - return EXCP_INTERRUPT; - } - - if (cpu->halted) { - return EXCP_HLT; - } - - flush_cpu_state(cpu); - - bql_unlock(); - r = hv_vcpu_run(cpu->accel->fd); - bql_lock(); - switch (r) { - case HV_SUCCESS: - break; - case HV_ILLEGAL_GUEST_STATE: - trace_hvf_illegal_guest_state(); - /* fall through */ - default: - g_assert_not_reached(); - } - - /* handle VMEXIT */ - uint64_t exit_reason = hvf_exit->reason; - uint64_t syndrome = hvf_exit->exception.syndrome; + CPUARMState *env = cpu_env(cpu); + ARMCPU *arm_cpu = env_archcpu(env); + uint64_t syndrome = excp->syndrome; uint32_t ec = syn_get_ec(syndrome); - - ret = 0; - switch (exit_reason) { - case HV_EXIT_REASON_EXCEPTION: - /* This is the main one, handle below. */ - break; - case HV_EXIT_REASON_VTIMER_ACTIVATED: - qemu_set_irq(arm_cpu->gt_timer_outputs[GTIMER_VIRT], 1); - cpu->accel->vtimer_masked = true; - return 0; - case HV_EXIT_REASON_CANCELED: - /* we got kicked, no exit to process */ - return 0; - default: - g_assert_not_reached(); - } - - hvf_sync_vtimer(cpu); + bool advance_pc = false; + hv_return_t r; + int ret = 0; switch (ec) { case EC_SOFTWARESTEP: { @@ -XXX,XX +XXX,XX @@ int hvf_arch_vcpu_exec(CPUState *cpu) cpu_synchronize_state(cpu); CPUWatchpoint *wp = - find_hw_watchpoint(cpu, hvf_exit->exception.virtual_address); + find_hw_watchpoint(cpu, excp->virtual_address); if (!wp) { error_report("EXCP_DEBUG but unknown hw watchpoint"); } @@ -XXX,XX +XXX,XX @@ int hvf_arch_vcpu_exec(CPUState *cpu) uint32_t cm = (syndrome >> 8) & 0x1; uint64_t val = 0; - trace_hvf_data_abort(hvf_exit->exception.virtual_address, - hvf_exit->exception.physical_address, isv, + trace_hvf_data_abort(excp->virtual_address, + excp->physical_address, isv, iswrite, s1ptw, len, srt); if (cm) { @@ -XXX,XX +XXX,XX @@ int hvf_arch_vcpu_exec(CPUState *cpu) if (iswrite) { val = hvf_get_reg(cpu, srt); address_space_write(&address_space_memory, - hvf_exit->exception.physical_address, + excp->physical_address, MEMTXATTRS_UNSPECIFIED, &val, len); } else { address_space_read(&address_space_memory, - hvf_exit->exception.physical_address, + excp->physical_address, MEMTXATTRS_UNSPECIFIED, &val, len); if (sse) { val = sextract64(val, 0, len * 8); @@ -XXX,XX +XXX,XX @@ int hvf_arch_vcpu_exec(CPUState *cpu) return ret; } +int hvf_arch_vcpu_exec(CPUState *cpu) +{ + ARMCPU *arm_cpu = ARM_CPU(cpu); + hv_vcpu_exit_t *hvf_exit = cpu->accel->exit; + hv_return_t r; + + if (!(cpu->singlestep_enabled & SSTEP_NOIRQ) && + hvf_inject_interrupts(cpu)) { + return EXCP_INTERRUPT; + } + + if (cpu->halted) { + return EXCP_HLT; + } + + flush_cpu_state(cpu); + + bql_unlock(); + r = hv_vcpu_run(cpu->accel->fd); + bql_lock(); + switch (r) { + case HV_SUCCESS: + break; + case HV_ILLEGAL_GUEST_STATE: + trace_hvf_illegal_guest_state(); + /* fall through */ + default: + g_assert_not_reached(); + } + + /* handle VMEXIT */ + uint64_t exit_reason = hvf_exit->reason; + + switch (exit_reason) { + case HV_EXIT_REASON_EXCEPTION: + /* This is the main one, handle below. */ + break; + case HV_EXIT_REASON_VTIMER_ACTIVATED: + qemu_set_irq(arm_cpu->gt_timer_outputs[GTIMER_VIRT], 1); + cpu->accel->vtimer_masked = true; + return 0; + case HV_EXIT_REASON_CANCELED: + /* we got kicked, no exit to process */ + return 0; + default: + g_assert_not_reached(); + } + + hvf_sync_vtimer(cpu); + + return hvf_handle_exception(cpu, &hvf_exit->exception); +} + static const VMStateDescription vmstate_hvf_vtimer = { .name = "hvf-vtimer", .version_id = 1, -- 2.43.0
From: Philippe Mathieu-Daudé <philmd@linaro.org> Factor hvf_handle_vmexit() out of hvf_arch_vcpu_exec(). Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org> Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- target/i386/hvf/hvf.c | 478 +++++++++++++++++++++--------------------- 1 file changed, 244 insertions(+), 234 deletions(-) diff --git a/target/i386/hvf/hvf.c b/target/i386/hvf/hvf.c index XXXXXXX..XXXXXXX 100644 --- a/target/i386/hvf/hvf.c +++ b/target/i386/hvf/hvf.c @@ -XXX,XX +XXX,XX @@ void hvf_simulate_wrmsr(CPUState *cs) printf("write msr %llx\n", RCX(cs));*/ } +static int hvf_handle_vmexit(CPUState *cpu) +{ + X86CPU *x86_cpu = env_archcpu(cpu_env(cpu)); + uint64_t exit_reason = rvmcs(cpu->accel->fd, VMCS_EXIT_REASON); + uint64_t exit_qual = rvmcs(cpu->accel->fd, VMCS_EXIT_QUALIFICATION); + uint32_t ins_len = (uint32_t)rvmcs(cpu->accel->fd, + VMCS_EXIT_INSTRUCTION_LENGTH); + + uint64_t idtvec_info = rvmcs(cpu->accel->fd, VMCS_IDT_VECTORING_INFO); + int ret = 0; + + hvf_store_events(cpu, ins_len, idtvec_info); + rip = rreg(cpu->accel->fd, HV_X86_RIP); + env->eflags = rreg(cpu->accel->fd, HV_X86_RFLAGS); + + bql_lock(); + + update_apic_tpr(cpu); + current_cpu = cpu; + + switch (exit_reason) { + case EXIT_REASON_HLT: { + macvm_set_rip(cpu, rip + ins_len); + if (!(cpu_test_interrupt(cpu, CPU_INTERRUPT_HARD) + && (env->eflags & IF_MASK)) + && !cpu_test_interrupt(cpu, CPU_INTERRUPT_NMI) + && !(idtvec_info & VMCS_IDT_VEC_VALID)) { + cpu->halted = 1; + ret = EXCP_HLT; + break; + } + ret = EXCP_INTERRUPT; + break; + } + case EXIT_REASON_MWAIT: { + ret = EXCP_INTERRUPT; + break; + } + /* Need to check if MMIO or unmapped fault */ + case EXIT_REASON_EPT_FAULT: + { + hvf_slot *slot; + uint64_t gpa = rvmcs(cpu->accel->fd, VMCS_GUEST_PHYSICAL_ADDRESS); + + if (((idtvec_info & VMCS_IDT_VEC_VALID) == 0) && + ((exit_qual & EXIT_QUAL_NMIUDTI) != 0)) { + vmx_set_nmi_blocking(cpu); + } + + slot = hvf_find_overlap_slot(gpa, 1); + /* mmio */ + if (ept_emulation_fault(slot, gpa, exit_qual)) { + struct x86_decode decode; + + hvf_load_regs(cpu); + decode_instruction(env, &decode); + exec_instruction(env, &decode); + hvf_store_regs(cpu); + break; + } + break; + } + case EXIT_REASON_INOUT: + { + uint32_t in = (exit_qual & 8) != 0; + uint32_t size = (exit_qual & 7) + 1; + uint32_t string = (exit_qual & 16) != 0; + uint32_t port = exit_qual >> 16; + /*uint32_t rep = (exit_qual & 0x20) != 0;*/ + struct x86_decode decode; + + if (!string && in) { + uint64_t val = 0; + + hvf_load_regs(cpu); + hvf_handle_io(env_cpu(env), port, &val, 0, size, 1); + if (size == 1) { + AL(env) = val; + } else if (size == 2) { + AX(env) = val; + } else if (size == 4) { + RAX(env) = (uint32_t)val; + } else { + RAX(env) = (uint64_t)val; + } + env->eip += ins_len; + hvf_store_regs(cpu); + break; + } else if (!string && !in) { + RAX(env) = rreg(cpu->accel->fd, HV_X86_RAX); + hvf_handle_io(env_cpu(env), port, &RAX(env), 1, size, 1); + macvm_set_rip(cpu, rip + ins_len); + break; + } + + hvf_load_regs(cpu); + decode_instruction(env, &decode); + assert(ins_len == decode.len); + exec_instruction(env, &decode); + hvf_store_regs(cpu); + + break; + } + case EXIT_REASON_CPUID: { + uint32_t rax = (uint32_t)rreg(cpu->accel->fd, HV_X86_RAX); + uint32_t rbx = (uint32_t)rreg(cpu->accel->fd, HV_X86_RBX); + uint32_t rcx = (uint32_t)rreg(cpu->accel->fd, HV_X86_RCX); + uint32_t rdx = (uint32_t)rreg(cpu->accel->fd, HV_X86_RDX); + + if (rax == 1) { + /* CPUID1.ecx.OSXSAVE needs to know CR4 */ + env->cr[4] = rvmcs(cpu->accel->fd, VMCS_GUEST_CR4); + } + hvf_cpu_x86_cpuid(env, rax, rcx, &rax, &rbx, &rcx, &rdx); + + wreg(cpu->accel->fd, HV_X86_RAX, rax); + wreg(cpu->accel->fd, HV_X86_RBX, rbx); + wreg(cpu->accel->fd, HV_X86_RCX, rcx); + wreg(cpu->accel->fd, HV_X86_RDX, rdx); + + macvm_set_rip(cpu, rip + ins_len); + break; + } + case EXIT_REASON_XSETBV: { + uint32_t eax = (uint32_t)rreg(cpu->accel->fd, HV_X86_RAX); + uint32_t ecx = (uint32_t)rreg(cpu->accel->fd, HV_X86_RCX); + uint32_t edx = (uint32_t)rreg(cpu->accel->fd, HV_X86_RDX); + + if (ecx) { + macvm_set_rip(cpu, rip + ins_len); + break; + } + env->xcr0 = ((uint64_t)edx << 32) | eax; + wreg(cpu->accel->fd, HV_X86_XCR0, env->xcr0 | 1); + macvm_set_rip(cpu, rip + ins_len); + break; + } + case EXIT_REASON_INTR_WINDOW: + vmx_clear_int_window_exiting(cpu); + ret = EXCP_INTERRUPT; + break; + case EXIT_REASON_NMI_WINDOW: + vmx_clear_nmi_window_exiting(cpu); + ret = EXCP_INTERRUPT; + break; + case EXIT_REASON_EXT_INTR: + /* force exit and allow io handling */ + ret = EXCP_INTERRUPT; + break; + case EXIT_REASON_RDMSR: + case EXIT_REASON_WRMSR: + { + hvf_load_regs(cpu); + if (exit_reason == EXIT_REASON_RDMSR) { + hvf_simulate_rdmsr(cpu); + } else { + hvf_simulate_wrmsr(cpu); + } + env->eip += ins_len; + hvf_store_regs(cpu); + break; + } + case EXIT_REASON_CR_ACCESS: { + int cr; + int reg; + + hvf_load_regs(cpu); + cr = exit_qual & 15; + reg = (exit_qual >> 8) & 15; + + switch (cr) { + case 0x0: { + macvm_set_cr0(cpu->accel->fd, RRX(env, reg)); + break; + } + case 4: { + macvm_set_cr4(cpu->accel->fd, RRX(env, reg)); + break; + } + case 8: { + if (exit_qual & 0x10) { + RRX(env, reg) = cpu_get_apic_tpr(x86_cpu->apic_state); + } else { + int tpr = RRX(env, reg); + cpu_set_apic_tpr(x86_cpu->apic_state, tpr); + ret = EXCP_INTERRUPT; + } + break; + } + default: + error_report("Unrecognized CR %d", cr); + abort(); + } + env->eip += ins_len; + hvf_store_regs(cpu); + break; + } + case EXIT_REASON_APIC_ACCESS: { /* TODO */ + struct x86_decode decode; + + hvf_load_regs(cpu); + decode_instruction(env, &decode); + exec_instruction(env, &decode); + hvf_store_regs(cpu); + break; + } + case EXIT_REASON_TPR: { + ret = 1; + break; + } + case EXIT_REASON_TASK_SWITCH: { + uint64_t vinfo = rvmcs(cpu->accel->fd, VMCS_IDT_VECTORING_INFO); + x86_segment_selector sel = {.sel = exit_qual & 0xffff}; + + vmx_handle_task_switch(cpu, sel, (exit_qual >> 30) & 0x3, + vinfo & VMCS_INTR_VALID, + vinfo & VECTORING_INFO_VECTOR_MASK, + vinfo & VMCS_INTR_T_MASK); + break; + } + case EXIT_REASON_TRIPLE_FAULT: { + qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET); + ret = EXCP_INTERRUPT; + break; + } + case EXIT_REASON_RDPMC: + wreg(cpu->accel->fd, HV_X86_RAX, 0); + wreg(cpu->accel->fd, HV_X86_RDX, 0); + macvm_set_rip(cpu, rip + ins_len); + break; + case VMX_REASON_VMCALL: + env->exception_nr = EXCP0D_GPF; + env->exception_injected = 1; + env->has_error_code = true; + env->error_code = 0; + break; + default: + error_report("%llx: unhandled exit %llx", rip, exit_reason); + } + + return ret; +} + int hvf_arch_vcpu_exec(CPUState *cpu) { X86CPU *x86_cpu = X86_CPU(cpu); @@ -XXX,XX +XXX,XX @@ int hvf_arch_vcpu_exec(CPUState *cpu) hv_return_t r = hv_vcpu_run_until(cpu->accel->fd, HV_DEADLINE_FOREVER); assert_hvf_ok(r); - /* handle VMEXIT */ - uint64_t exit_reason = rvmcs(cpu->accel->fd, VMCS_EXIT_REASON); - uint64_t exit_qual = rvmcs(cpu->accel->fd, VMCS_EXIT_QUALIFICATION); - uint32_t ins_len = (uint32_t)rvmcs(cpu->accel->fd, - VMCS_EXIT_INSTRUCTION_LENGTH); - - uint64_t idtvec_info = rvmcs(cpu->accel->fd, VMCS_IDT_VECTORING_INFO); - - hvf_store_events(cpu, ins_len, idtvec_info); - rip = rreg(cpu->accel->fd, HV_X86_RIP); - env->eflags = rreg(cpu->accel->fd, HV_X86_RFLAGS); - - bql_lock(); - - update_apic_tpr(cpu); - current_cpu = cpu; - - ret = 0; - switch (exit_reason) { - case EXIT_REASON_HLT: { - macvm_set_rip(cpu, rip + ins_len); - if (!(cpu_test_interrupt(cpu, CPU_INTERRUPT_HARD) && - (env->eflags & IF_MASK)) - && !cpu_test_interrupt(cpu, CPU_INTERRUPT_NMI) && - !(idtvec_info & VMCS_IDT_VEC_VALID)) { - cpu->halted = 1; - ret = EXCP_HLT; - break; - } - ret = EXCP_INTERRUPT; - break; - } - case EXIT_REASON_MWAIT: { - ret = EXCP_INTERRUPT; - break; - } - /* Need to check if MMIO or unmapped fault */ - case EXIT_REASON_EPT_FAULT: - { - hvf_slot *slot; - uint64_t gpa = rvmcs(cpu->accel->fd, VMCS_GUEST_PHYSICAL_ADDRESS); - - if (((idtvec_info & VMCS_IDT_VEC_VALID) == 0) && - ((exit_qual & EXIT_QUAL_NMIUDTI) != 0)) { - vmx_set_nmi_blocking(cpu); - } - - slot = hvf_find_overlap_slot(gpa, 1); - /* mmio */ - if (ept_emulation_fault(slot, gpa, exit_qual)) { - struct x86_decode decode; - - hvf_load_regs(cpu); - decode_instruction(env, &decode); - exec_instruction(env, &decode); - hvf_store_regs(cpu); - break; - } - break; - } - case EXIT_REASON_INOUT: - { - uint32_t in = (exit_qual & 8) != 0; - uint32_t size = (exit_qual & 7) + 1; - uint32_t string = (exit_qual & 16) != 0; - uint32_t port = exit_qual >> 16; - /*uint32_t rep = (exit_qual & 0x20) != 0;*/ - - if (!string && in) { - uint64_t val = 0; - hvf_load_regs(cpu); - hvf_handle_io(env_cpu(env), port, &val, 0, size, 1); - if (size == 1) { - AL(env) = val; - } else if (size == 2) { - AX(env) = val; - } else if (size == 4) { - RAX(env) = (uint32_t)val; - } else { - RAX(env) = (uint64_t)val; - } - env->eip += ins_len; - hvf_store_regs(cpu); - break; - } else if (!string && !in) { - RAX(env) = rreg(cpu->accel->fd, HV_X86_RAX); - hvf_handle_io(env_cpu(env), port, &RAX(env), 1, size, 1); - macvm_set_rip(cpu, rip + ins_len); - break; - } - struct x86_decode decode; - - hvf_load_regs(cpu); - decode_instruction(env, &decode); - assert(ins_len == decode.len); - exec_instruction(env, &decode); - hvf_store_regs(cpu); - - break; - } - case EXIT_REASON_CPUID: { - uint32_t rax = (uint32_t)rreg(cpu->accel->fd, HV_X86_RAX); - uint32_t rbx = (uint32_t)rreg(cpu->accel->fd, HV_X86_RBX); - uint32_t rcx = (uint32_t)rreg(cpu->accel->fd, HV_X86_RCX); - uint32_t rdx = (uint32_t)rreg(cpu->accel->fd, HV_X86_RDX); - - if (rax == 1) { - /* CPUID1.ecx.OSXSAVE needs to know CR4 */ - env->cr[4] = rvmcs(cpu->accel->fd, VMCS_GUEST_CR4); - } - hvf_cpu_x86_cpuid(env, rax, rcx, &rax, &rbx, &rcx, &rdx); - - wreg(cpu->accel->fd, HV_X86_RAX, rax); - wreg(cpu->accel->fd, HV_X86_RBX, rbx); - wreg(cpu->accel->fd, HV_X86_RCX, rcx); - wreg(cpu->accel->fd, HV_X86_RDX, rdx); - - macvm_set_rip(cpu, rip + ins_len); - break; - } - case EXIT_REASON_XSETBV: { - uint32_t eax = (uint32_t)rreg(cpu->accel->fd, HV_X86_RAX); - uint32_t ecx = (uint32_t)rreg(cpu->accel->fd, HV_X86_RCX); - uint32_t edx = (uint32_t)rreg(cpu->accel->fd, HV_X86_RDX); - - if (ecx) { - macvm_set_rip(cpu, rip + ins_len); - break; - } - env->xcr0 = ((uint64_t)edx << 32) | eax; - wreg(cpu->accel->fd, HV_X86_XCR0, env->xcr0 | 1); - macvm_set_rip(cpu, rip + ins_len); - break; - } - case EXIT_REASON_INTR_WINDOW: - vmx_clear_int_window_exiting(cpu); - ret = EXCP_INTERRUPT; - break; - case EXIT_REASON_NMI_WINDOW: - vmx_clear_nmi_window_exiting(cpu); - ret = EXCP_INTERRUPT; - break; - case EXIT_REASON_EXT_INTR: - /* force exit and allow io handling */ - ret = EXCP_INTERRUPT; - break; - case EXIT_REASON_RDMSR: - case EXIT_REASON_WRMSR: - { - hvf_load_regs(cpu); - if (exit_reason == EXIT_REASON_RDMSR) { - hvf_simulate_rdmsr(cpu); - } else { - hvf_simulate_wrmsr(cpu); - } - env->eip += ins_len; - hvf_store_regs(cpu); - break; - } - case EXIT_REASON_CR_ACCESS: { - int cr; - int reg; - - hvf_load_regs(cpu); - cr = exit_qual & 15; - reg = (exit_qual >> 8) & 15; - - switch (cr) { - case 0x0: { - macvm_set_cr0(cpu->accel->fd, RRX(env, reg)); - break; - } - case 4: { - macvm_set_cr4(cpu->accel->fd, RRX(env, reg)); - break; - } - case 8: { - if (exit_qual & 0x10) { - RRX(env, reg) = cpu_get_apic_tpr(x86_cpu->apic_state); - } else { - int tpr = RRX(env, reg); - cpu_set_apic_tpr(x86_cpu->apic_state, tpr); - ret = EXCP_INTERRUPT; - } - break; - } - default: - error_report("Unrecognized CR %d", cr); - abort(); - } - env->eip += ins_len; - hvf_store_regs(cpu); - break; - } - case EXIT_REASON_APIC_ACCESS: { /* TODO */ - struct x86_decode decode; - - hvf_load_regs(cpu); - decode_instruction(env, &decode); - exec_instruction(env, &decode); - hvf_store_regs(cpu); - break; - } - case EXIT_REASON_TPR: { - ret = 1; - break; - } - case EXIT_REASON_TASK_SWITCH: { - uint64_t vinfo = rvmcs(cpu->accel->fd, VMCS_IDT_VECTORING_INFO); - x86_segment_selector sel = {.sel = exit_qual & 0xffff}; - vmx_handle_task_switch(cpu, sel, (exit_qual >> 30) & 0x3, - vinfo & VMCS_INTR_VALID, vinfo & VECTORING_INFO_VECTOR_MASK, vinfo - & VMCS_INTR_T_MASK); - break; - } - case EXIT_REASON_TRIPLE_FAULT: { - qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET); - ret = EXCP_INTERRUPT; - break; - } - case EXIT_REASON_RDPMC: - wreg(cpu->accel->fd, HV_X86_RAX, 0); - wreg(cpu->accel->fd, HV_X86_RDX, 0); - macvm_set_rip(cpu, rip + ins_len); - break; - case VMX_REASON_VMCALL: - env->exception_nr = EXCP0D_GPF; - env->exception_injected = 1; - env->has_error_code = true; - env->error_code = 0; - break; - default: - error_report("%llx: unhandled exit %llx", rip, exit_reason); - } + ret = hvf_handle_vmexit(cpu); } while (ret == 0); return ret; -- 2.43.0
From: Philippe Mathieu-Daudé <philmd@linaro.org> Factor hvf_handle_vmexit() out of hvf_vcpu_exec(). Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Reviewed-by: Mads Ynddal <mads@ynddal.dk> Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- target/arm/hvf/hvf.c | 50 ++++++++++++++++++++++++-------------------- 1 file changed, 27 insertions(+), 23 deletions(-) diff --git a/target/arm/hvf/hvf.c b/target/arm/hvf/hvf.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/hvf/hvf.c +++ b/target/arm/hvf/hvf.c @@ -XXX,XX +XXX,XX @@ static int hvf_handle_exception(CPUState *cpu, hv_vcpu_exit_exception_t *excp) return ret; } +static int hvf_handle_vmexit(CPUState *cpu, hv_vcpu_exit_t *exit) +{ + ARMCPU *arm_cpu = env_archcpu(cpu_env(cpu)); + int ret = 0; + + switch (exit->reason) { + case HV_EXIT_REASON_EXCEPTION: + hvf_sync_vtimer(cpu); + ret = hvf_handle_exception(cpu, &exit->exception); + break; + case HV_EXIT_REASON_VTIMER_ACTIVATED: + qemu_set_irq(arm_cpu->gt_timer_outputs[GTIMER_VIRT], 1); + cpu->accel->vtimer_masked = true; + break; + case HV_EXIT_REASON_CANCELED: + /* we got kicked, no exit to process */ + break; + default: + g_assert_not_reached(); + } + + return ret; +} + int hvf_arch_vcpu_exec(CPUState *cpu) { - ARMCPU *arm_cpu = ARM_CPU(cpu); - hv_vcpu_exit_t *hvf_exit = cpu->accel->exit; + int ret; hv_return_t r; if (!(cpu->singlestep_enabled & SSTEP_NOIRQ) && @@ -XXX,XX +XXX,XX @@ int hvf_arch_vcpu_exec(CPUState *cpu) bql_lock(); switch (r) { case HV_SUCCESS: + ret = hvf_handle_vmexit(cpu, cpu->accel->exit); break; case HV_ILLEGAL_GUEST_STATE: trace_hvf_illegal_guest_state(); @@ -XXX,XX +XXX,XX @@ int hvf_arch_vcpu_exec(CPUState *cpu) g_assert_not_reached(); } - /* handle VMEXIT */ - uint64_t exit_reason = hvf_exit->reason; - - switch (exit_reason) { - case HV_EXIT_REASON_EXCEPTION: - /* This is the main one, handle below. */ - break; - case HV_EXIT_REASON_VTIMER_ACTIVATED: - qemu_set_irq(arm_cpu->gt_timer_outputs[GTIMER_VIRT], 1); - cpu->accel->vtimer_masked = true; - return 0; - case HV_EXIT_REASON_CANCELED: - /* we got kicked, no exit to process */ - return 0; - default: - g_assert_not_reached(); - } - - hvf_sync_vtimer(cpu); - - return hvf_handle_exception(cpu, &hvf_exit->exception); + return ret; } static const VMStateDescription vmstate_hvf_vtimer = { -- 2.43.0
From: Philippe Mathieu-Daudé <philmd@linaro.org> Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Reviewed-by: Mads Ynddal <mads@ynddal.dk> Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- target/arm/hvf/hvf.c | 38 ++++++++++++++++++++------------------ 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/target/arm/hvf/hvf.c b/target/arm/hvf/hvf.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/hvf/hvf.c +++ b/target/arm/hvf/hvf.c @@ -XXX,XX +XXX,XX @@ int hvf_arch_vcpu_exec(CPUState *cpu) int ret; hv_return_t r; - if (!(cpu->singlestep_enabled & SSTEP_NOIRQ) && - hvf_inject_interrupts(cpu)) { - return EXCP_INTERRUPT; - } - if (cpu->halted) { return EXCP_HLT; } flush_cpu_state(cpu); - bql_unlock(); - r = hv_vcpu_run(cpu->accel->fd); - bql_lock(); - switch (r) { - case HV_SUCCESS: - ret = hvf_handle_vmexit(cpu, cpu->accel->exit); - break; - case HV_ILLEGAL_GUEST_STATE: - trace_hvf_illegal_guest_state(); - /* fall through */ - default: - g_assert_not_reached(); - } + do { + if (!(cpu->singlestep_enabled & SSTEP_NOIRQ) && + hvf_inject_interrupts(cpu)) { + return EXCP_INTERRUPT; + } + + bql_unlock(); + r = hv_vcpu_run(cpu->accel->fd); + bql_lock(); + switch (r) { + case HV_SUCCESS: + ret = hvf_handle_vmexit(cpu, cpu->accel->exit); + break; + case HV_ILLEGAL_GUEST_STATE: + trace_hvf_illegal_guest_state(); + /* fall through */ + default: + g_assert_not_reached(); + } + } while (ret == 0); return ret; } -- 2.43.0
From: Philippe Mathieu-Daudé <philmd@linaro.org> Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- cpu-common.c | 3 +++ trace-events | 2 ++ 2 files changed, 5 insertions(+) diff --git a/cpu-common.c b/cpu-common.c index XXXXXXX..XXXXXXX 100644 --- a/cpu-common.c +++ b/cpu-common.c @@ -XXX,XX +XXX,XX @@ void end_exclusive(void) /* Wait for exclusive ops to finish, and begin cpu execution. */ void cpu_exec_start(CPUState *cpu) { + trace_cpu_exec_start(cpu->cpu_index); + qatomic_set(&cpu->running, true); /* Write cpu->running before reading pending_cpus. */ @@ -XXX,XX +XXX,XX @@ void cpu_exec_end(CPUState *cpu) } } } + trace_cpu_exec_end(cpu->cpu_index); } void async_safe_run_on_cpu(CPUState *cpu, run_on_cpu_func func, diff --git a/trace-events b/trace-events index XXXXXXX..XXXXXXX 100644 --- a/trace-events +++ b/trace-events @@ -XXX,XX +XXX,XX @@ breakpoint_insert(int cpu_index, uint64_t pc, int flags) "cpu=%d pc=0x%" PRIx64 " flags=0x%x" breakpoint_remove(int cpu_index, uint64_t pc, int flags) "cpu=%d pc=0x%" PRIx64 " flags=0x%x" breakpoint_singlestep(int cpu_index, int enabled) "cpu=%d enable=%d" +cpu_exec_start(int cpu_index) "cpu=%d" +cpu_exec_end(int cpu_index) "cpu=%d" # job.c job_state_transition(void *job, int ret, const char *legal, const char *s0, const char *s1) "job %p (ret: %d) attempting %s transition (%s-->%s)" -- 2.43.0
From: Philippe Mathieu-Daudé <philmd@linaro.org> Similarly to 1d78a3c3ab8 for KVM, wrap hv_vcpu_run() with cpu_exec_start/end(), so that the accelerator can perform pending operations while all vCPUs are quiescent. See also explanation in commit c265e976f46 ("cpus-common: lock-free fast path for cpu_exec_start/end"). Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- target/arm/hvf/hvf.c | 2 ++ target/i386/hvf/hvf.c | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/target/arm/hvf/hvf.c b/target/arm/hvf/hvf.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/hvf/hvf.c +++ b/target/arm/hvf/hvf.c @@ -XXX,XX +XXX,XX @@ int hvf_arch_vcpu_exec(CPUState *cpu) } bql_unlock(); + cpu_exec_start(cpu); r = hv_vcpu_run(cpu->accel->fd); + cpu_exec_end(cpu); bql_lock(); switch (r) { case HV_SUCCESS: diff --git a/target/i386/hvf/hvf.c b/target/i386/hvf/hvf.c index XXXXXXX..XXXXXXX 100644 --- a/target/i386/hvf/hvf.c +++ b/target/i386/hvf/hvf.c @@ -XXX,XX +XXX,XX @@ int hvf_arch_vcpu_exec(CPUState *cpu) return EXCP_HLT; } + cpu_exec_start(cpu); + hv_return_t r = hv_vcpu_run_until(cpu->accel->fd, HV_DEADLINE_FOREVER); assert_hvf_ok(r); + cpu_exec_end(cpu); + ret = hvf_handle_vmexit(cpu); } while (ret == 0); -- 2.43.0
From: Philippe Mathieu-Daudé <philmd@linaro.org> Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- target/arm/cpu64.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/cpu64.c +++ b/target/arm/cpu64.c @@ -XXX,XX +XXX,XX @@ static void aarch64_a53_initfn(Object *obj) static void aarch64_host_initfn(Object *obj) { -#if defined(CONFIG_KVM) ARMCPU *cpu = ARM_CPU(obj); +#if defined(CONFIG_KVM) kvm_arm_set_cpu_features_from_host(cpu); if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) { aarch64_add_sve_properties(obj); - aarch64_add_pauth_properties(obj); } #elif defined(CONFIG_HVF) - ARMCPU *cpu = ARM_CPU(obj); hvf_arm_set_cpu_features_from_host(cpu); - aarch64_add_pauth_properties(obj); #else g_assert_not_reached(); #endif + if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) { + aarch64_add_pauth_properties(obj); + } } static void aarch64_max_initfn(Object *obj) -- 2.43.0
From: Philippe Mathieu-Daudé <philmd@linaro.org> Do not expose ARM specific fields to X86 implementation, allowing to use the proper 'hv_vcpu_exit_t' type. Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- include/system/hvf_int.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/include/system/hvf_int.h b/include/system/hvf_int.h index XXXXXXX..XXXXXXX 100644 --- a/include/system/hvf_int.h +++ b/include/system/hvf_int.h @@ -XXX,XX +XXX,XX @@ extern HVFState *hvf_state; struct AccelCPUState { hvf_vcpuid fd; - void *exit; +#ifdef __aarch64__ + hv_vcpu_exit_t *exit; bool vtimer_masked; sigset_t unblock_ipi_mask; bool guest_debug_enabled; +#endif }; void assert_hvf_ok_impl(hv_return_t ret, const char *file, unsigned int line, -- 2.43.0
From: Philippe Mathieu-Daudé <philmd@linaro.org> Prefix init_cpreg_list() with 'arm_'. Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org> Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- target/arm/internals.h | 2 +- target/arm/cpu.c | 2 +- target/arm/helper.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/target/arm/internals.h b/target/arm/internals.h index XXXXXXX..XXXXXXX 100644 --- a/target/arm/internals.h +++ b/target/arm/internals.h @@ -XXX,XX +XXX,XX @@ void arm_cpu_register(const ARMCPUInfo *info); void arm_do_plugin_vcpu_discon_cb(CPUState *cs, uint64_t from); void register_cp_regs_for_features(ARMCPU *cpu); -void init_cpreg_list(ARMCPU *cpu); +void arm_init_cpreg_list(ARMCPU *cpu); void arm_cpu_register_gdb_regs_for_features(ARMCPU *cpu); void arm_translate_init(void); diff --git a/target/arm/cpu.c b/target/arm/cpu.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/cpu.c +++ b/target/arm/cpu.c @@ -XXX,XX +XXX,XX @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp) arm_cpu_register_gdb_regs_for_features(cpu); arm_cpu_register_gdb_commands(cpu); - init_cpreg_list(cpu); + arm_init_cpreg_list(cpu); #ifndef CONFIG_USER_ONLY MachineState *ms = MACHINE(qdev_get_machine()); diff --git a/target/arm/helper.c b/target/arm/helper.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -XXX,XX +XXX,XX @@ static void count_cpreg(gpointer key, gpointer value, gpointer opaque) } } -void init_cpreg_list(ARMCPU *cpu) +void arm_init_cpreg_list(ARMCPU *cpu) { /* * Initialise the cpreg_tuples[] array based on the cp_regs hash. -- 2.43.0
From: Philippe Mathieu-Daudé <philmd@linaro.org> In order to extend the trace events to other registers, rename and pass the register group as argument. Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org> Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- target/arm/hvf/hvf.c | 14 ++++++++------ target/arm/hvf/trace-events | 4 ++-- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/target/arm/hvf/hvf.c b/target/arm/hvf/hvf.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/hvf/hvf.c +++ b/target/arm/hvf/hvf.c @@ -XXX,XX +XXX,XX @@ static uint32_t hvf_reg2cp_reg(uint32_t reg) (reg >> SYSREG_OP2_SHIFT) & SYSREG_OP2_MASK); } -static bool hvf_sysreg_read_cp(CPUState *cpu, uint32_t reg, uint64_t *val) +static bool hvf_sysreg_read_cp(CPUState *cpu, const char *cpname, + uint32_t reg, uint64_t *val) { ARMCPU *arm_cpu = ARM_CPU(cpu); CPUARMState *env = &arm_cpu->env; @@ -XXX,XX +XXX,XX @@ static bool hvf_sysreg_read_cp(CPUState *cpu, uint32_t reg, uint64_t *val) } else { *val = raw_read(env, ri); } - trace_hvf_vgic_read(ri->name, *val); + trace_hvf_emu_reginfo_read(cpname, ri->name, *val); return true; } @@ -XXX,XX +XXX,XX @@ static int hvf_sysreg_read(CPUState *cpu, uint32_t reg, uint64_t *val) case SYSREG_ICC_SRE_EL1: case SYSREG_ICC_CTLR_EL1: /* Call the TCG sysreg handler. This is only safe for GICv3 regs. */ - if (hvf_sysreg_read_cp(cpu, reg, val)) { + if (hvf_sysreg_read_cp(cpu, "GICv3", reg, val)) { return 0; } break; @@ -XXX,XX +XXX,XX @@ static void pmswinc_write(CPUARMState *env, uint64_t value) } } -static bool hvf_sysreg_write_cp(CPUState *cpu, uint32_t reg, uint64_t val) +static bool hvf_sysreg_write_cp(CPUState *cpu, const char *cpname, + uint32_t reg, uint64_t val) { ARMCPU *arm_cpu = ARM_CPU(cpu); CPUARMState *env = &arm_cpu->env; @@ -XXX,XX +XXX,XX @@ static bool hvf_sysreg_write_cp(CPUState *cpu, uint32_t reg, uint64_t val) raw_write(env, ri, val); } - trace_hvf_vgic_write(ri->name, val); + trace_hvf_emu_reginfo_write(cpname, ri->name, val); return true; } @@ -XXX,XX +XXX,XX @@ static int hvf_sysreg_write(CPUState *cpu, uint32_t reg, uint64_t val) case SYSREG_ICC_SGI1R_EL1: case SYSREG_ICC_SRE_EL1: /* Call the TCG sysreg handler. This is only safe for GICv3 regs. */ - if (hvf_sysreg_write_cp(cpu, reg, val)) { + if (hvf_sysreg_write_cp(cpu, "GICv3", reg, val)) { return 0; } break; diff --git a/target/arm/hvf/trace-events b/target/arm/hvf/trace-events index XXXXXXX..XXXXXXX 100644 --- a/target/arm/hvf/trace-events +++ b/target/arm/hvf/trace-events @@ -XXX,XX +XXX,XX @@ hvf_unknown_hvc(uint64_t pc, uint64_t x0) "pc=0x%"PRIx64" unknown HVC! 0x%016"PR hvf_unknown_smc(uint64_t x0) "unknown SMC! 0x%016"PRIx64 hvf_exit(uint64_t syndrome, uint32_t ec, uint64_t pc) "exit: 0x%"PRIx64" [ec=0x%x pc=0x%"PRIx64"]" hvf_psci_call(uint64_t x0, uint64_t x1, uint64_t x2, uint64_t x3, uint32_t cpuid) "PSCI Call x0=0x%016"PRIx64" x1=0x%016"PRIx64" x2=0x%016"PRIx64" x3=0x%016"PRIx64" cpuid=0x%x" -hvf_vgic_write(const char *name, uint64_t val) "vgic write to %s [val=0x%016"PRIx64"]" -hvf_vgic_read(const char *name, uint64_t val) "vgic read from %s [val=0x%016"PRIx64"]" +hvf_emu_reginfo_write(const char *cpname, const char *regname, uint64_t val) "[%s] write to %s [val=0x%016"PRIx64"]" +hvf_emu_reginfo_read(const char *cpname, const char *regname, uint64_t val) "[%s] read from %s [val=0x%016"PRIx64"]" hvf_illegal_guest_state(void) "HV_ILLEGAL_GUEST_STATE" hvf_kick_vcpu_thread(unsigned cpuidx, bool stop) "cpu:%u stop:%u" -- 2.43.0
From: Philippe Mathieu-Daudé <philmd@linaro.org> Re-use arm_is_psci_call() instead of open-coding it. Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- target/arm/hvf/hvf.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/target/arm/hvf/hvf.c b/target/arm/hvf/hvf.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/hvf/hvf.c +++ b/target/arm/hvf/hvf.c @@ -XXX,XX +XXX,XX @@ static int hvf_handle_exception(CPUState *cpu, hv_vcpu_exit_exception_t *excp) break; case EC_AA64_HVC: cpu_synchronize_state(cpu); - if (arm_cpu->psci_conduit == QEMU_PSCI_CONDUIT_HVC) { + if (arm_is_psci_call(arm_cpu, EXCP_HVC)) { if (!hvf_handle_psci_call(cpu)) { trace_hvf_unknown_hvc(env->pc, env->xregs[0]); /* SMCCC 1.3 section 5.2 says every unknown SMCCC call returns -1 */ @@ -XXX,XX +XXX,XX @@ static int hvf_handle_exception(CPUState *cpu, hv_vcpu_exit_exception_t *excp) break; case EC_AA64_SMC: cpu_synchronize_state(cpu); - if (arm_cpu->psci_conduit == QEMU_PSCI_CONDUIT_SMC) { + if (arm_is_psci_call(arm_cpu, EXCP_SMC)) { advance_pc = true; if (!hvf_handle_psci_call(cpu)) { -- 2.43.0
From: Philippe Mathieu-Daudé <philmd@linaro.org> It is useful to compare PSCI calls of the same guest running under TCG or HVF. Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- target/arm/hvf/hvf.c | 3 ++- target/arm/tcg/psci.c | 3 +++ target/arm/trace-events | 3 +++ 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/target/arm/hvf/hvf.c b/target/arm/hvf/hvf.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/hvf/hvf.c +++ b/target/arm/hvf/hvf.c @@ -XXX,XX +XXX,XX @@ #include "target/arm/internals.h" #include "target/arm/multiprocessing.h" #include "target/arm/gtimer.h" +#include "target/arm/trace.h" #include "trace.h" #include "migration/vmstate.h" @@ -XXX,XX +XXX,XX @@ static bool hvf_handle_psci_call(CPUState *cpu) int target_el = 1; int32_t ret = 0; - trace_hvf_psci_call(param[0], param[1], param[2], param[3], + trace_arm_psci_call(param[0], param[1], param[2], param[3], arm_cpu_mp_affinity(arm_cpu)); switch (param[0]) { diff --git a/target/arm/tcg/psci.c b/target/arm/tcg/psci.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/tcg/psci.c +++ b/target/arm/tcg/psci.c @@ -XXX,XX +XXX,XX @@ #include "internals.h" #include "arm-powerctl.h" #include "target/arm/multiprocessing.h" +#include "target/arm/trace.h" bool arm_is_psci_call(ARMCPU *cpu, int excp_type) { @@ -XXX,XX +XXX,XX @@ void arm_handle_psci_call(ARMCPU *cpu) */ param[i] = is_a64(env) ? env->xregs[i] : env->regs[i]; } + trace_arm_psci_call(param[0], param[1], param[2], param[3], + arm_cpu_mp_affinity(cpu)); if ((param[0] & QEMU_PSCI_0_2_64BIT) && !is_a64(env)) { ret = QEMU_PSCI_RET_NOT_SUPPORTED; diff --git a/target/arm/trace-events b/target/arm/trace-events index XXXXXXX..XXXXXXX 100644 --- a/target/arm/trace-events +++ b/target/arm/trace-events @@ -XXX,XX +XXX,XX @@ arm_powerctl_set_cpu_on(uint64_t mp_aff, unsigned target_el, const char *mode, u arm_powerctl_set_cpu_on_and_reset(uint64_t mp_aff) "cpu %" PRIu64 arm_powerctl_set_cpu_off(uint64_t mp_aff) "cpu %" PRIu64 arm_powerctl_reset_cpu(uint64_t mp_aff) "cpu %" PRIu64 + +# tcg/psci.c and hvf/hvf.c +arm_psci_call(uint64_t x0, uint64_t x1, uint64_t x2, uint64_t x3, uint32_t cpuid) "PSCI Call x0=0x%016"PRIx64" x1=0x%016"PRIx64" x2=0x%016"PRIx64" x3=0x%016"PRIx64" cpuid=0x%x" -- 2.43.0
From: Philippe Mathieu-Daudé <philmd@linaro.org> Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- target/arm/hvf/hvf.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/target/arm/hvf/hvf.c b/target/arm/hvf/hvf.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/hvf/hvf.c +++ b/target/arm/hvf/hvf.c @@ -XXX,XX +XXX,XX @@ static int hvf_handle_exception(CPUState *cpu, hv_vcpu_exit_exception_t *excp) case EC_AA64_HVC: cpu_synchronize_state(cpu); if (arm_is_psci_call(arm_cpu, EXCP_HVC)) { + /* Do NOT advance $pc for HVC */ if (!hvf_handle_psci_call(cpu)) { trace_hvf_unknown_hvc(env->pc, env->xregs[0]); /* SMCCC 1.3 section 5.2 says every unknown SMCCC call returns -1 */ @@ -XXX,XX +XXX,XX @@ static int hvf_handle_exception(CPUState *cpu, hv_vcpu_exit_exception_t *excp) case EC_AA64_SMC: cpu_synchronize_state(cpu); if (arm_is_psci_call(arm_cpu, EXCP_SMC)) { + /* Secure Monitor Call exception, we need to advance $pc */ advance_pc = true; if (!hvf_handle_psci_call(cpu)) { -- 2.43.0
From: Philippe Mathieu-Daudé <philmd@linaro.org> Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- target/arm/hvf/hvf.c | 11 +++++++++++ target/arm/hvf/trace-events | 1 + 2 files changed, 12 insertions(+) diff --git a/target/arm/hvf/hvf.c b/target/arm/hvf/hvf.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/hvf/hvf.c +++ b/target/arm/hvf/hvf.c @@ -XXX,XX +XXX,XX @@ static int hvf_handle_exception(CPUState *cpu, hv_vcpu_exit_exception_t *excp) hvf_raise_exception(cpu, EXCP_UDEF, syn_uncategorized(), 1); } break; + case EC_INSNABORT: { + uint32_t set = (syndrome >> 12) & 3; + bool fnv = (syndrome >> 10) & 1; + bool ea = (syndrome >> 9) & 1; + bool s1ptw = (syndrome >> 7) & 1; + uint32_t ifsc = (syndrome >> 0) & 0x3f; + + trace_hvf_insn_abort(env->pc, set, fnv, ea, s1ptw, ifsc); + + /* fall through */ + } default: cpu_synchronize_state(cpu); trace_hvf_exit(syndrome, ec, env->pc); diff --git a/target/arm/hvf/trace-events b/target/arm/hvf/trace-events index XXXXXXX..XXXXXXX 100644 --- a/target/arm/hvf/trace-events +++ b/target/arm/hvf/trace-events @@ -XXX,XX +XXX,XX @@ hvf_unhandled_sysreg_write(uint64_t pc, uint32_t reg, uint32_t op0, uint32_t op1 hvf_inject_fiq(void) "injecting FIQ" hvf_inject_irq(void) "injecting IRQ" hvf_data_abort(uint64_t va, uint64_t pa, bool isv, bool iswrite, bool s1ptw, uint32_t len, uint32_t srt) "data abort: [va=0x%016"PRIx64" pa=0x%016"PRIx64" isv=%d iswrite=%d s1ptw=%d len=%d srt=%d]" +hvf_insn_abort(uint64_t pc, uint32_t set, bool fnv, bool ea, bool s1ptw, uint32_t ifsc) "insn abort: [pc=0x%"PRIx64" set=%d fnv=%d ea=%d s1ptw=%d ifsc=%d]" hvf_sysreg_read(uint32_t reg, uint32_t op0, uint32_t op1, uint32_t crn, uint32_t crm, uint32_t op2, uint64_t val) "sysreg read 0x%08x (op0=%d op1=%d crn=%d crm=%d op2=%d) = 0x%016"PRIx64 hvf_sysreg_write(uint32_t reg, uint32_t op0, uint32_t op1, uint32_t crn, uint32_t crm, uint32_t op2, uint64_t val) "sysreg write 0x%08x (op0=%d op1=%d crn=%d crm=%d op2=%d, val=0x%016"PRIx64")" hvf_unknown_hvc(uint64_t pc, uint64_t x0) "pc=0x%"PRIx64" unknown HVC! 0x%016"PRIx64 -- 2.43.0
v3->v4: Windows headers define an INT type which clashed with an enum value name in arm_gicv3_its.c... The following changes since commit eae587e8e3694b1aceab23239493fb4c7e1a80f5: Merge remote-tracking branch 'remotes/armbru/tags/pull-qapi-2021-09-13' into staging (2021-09-13 11:00:30 +0100) are available in the Git repository at: https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20210913-3 for you to fetch changes up to 28e987a7e7edaa3ca7feeac65edca26145df8814: hw/arm/mps2.c: Mark internal-only I2C buses as 'full' (2021-09-13 21:01:08 +0100) ---------------------------------------------------------------- target-arm queue: * mark MPS2/MPS3 board-internal i2c buses as 'full' so that command line user-created devices are not plugged into them * Take an exception if PSTATE.IL is set * Support an emulated ITS in the virt board * Add support for kudo-bmc board * Probe for KVM_CAP_ARM_VM_IPA_SIZE when creating scratch VM * cadence_uart: Fix clock handling issues that prevented u-boot from running ---------------------------------------------------------------- Bin Meng (6): hw/misc: zynq_slcr: Correctly compute output clocks in the reset exit phase hw/char: cadence_uart: Disable transmit when input clock is disabled hw/char: cadence_uart: Move clock/reset check to uart_can_receive() hw/char: cadence_uart: Convert to memop_with_attrs() ops hw/char: cadence_uart: Ignore access when unclocked or in reset for uart_{read, write}() hw/char: cadence_uart: Log a guest error when device is unclocked or in reset Chris Rauer (1): hw/arm: Add support for kudo-bmc board. Marc Zyngier (1): hw/arm/virt: KVM: Probe for KVM_CAP_ARM_VM_IPA_SIZE when creating scratch VM Peter Maydell (5): target/arm: Take an exception if PSTATE.IL is set qdev: Support marking individual buses as 'full' hw/arm/mps2-tz.c: Add extra data parameter to MakeDevFn hw/arm/mps2-tz.c: Mark internal-only I2C buses as 'full' hw/arm/mps2.c: Mark internal-only I2C buses as 'full' Richard Henderson (1): target/arm: Merge disas_a64_insn into aarch64_tr_translate_insn Shashi Mallela (9): hw/intc: GICv3 ITS initial framework hw/intc: GICv3 ITS register definitions added hw/intc: GICv3 ITS command queue framework hw/intc: GICv3 ITS Command processing hw/intc: GICv3 ITS Feature enablement hw/intc: GICv3 redistributor ITS processing tests/data/acpi/virt: Add IORT files for ITS hw/arm/virt: add ITS support in virt GIC tests/data/acpi/virt: Update IORT files for ITS docs/system/arm/nuvoton.rst | 1 + hw/intc/gicv3_internal.h | 188 ++++- include/hw/arm/virt.h | 2 + include/hw/intc/arm_gicv3_common.h | 13 + include/hw/intc/arm_gicv3_its_common.h | 32 +- include/hw/qdev-core.h | 24 + target/arm/cpu.h | 1 + target/arm/kvm_arm.h | 4 +- target/arm/syndrome.h | 5 + target/arm/translate.h | 2 + hw/arm/mps2-tz.c | 92 ++- hw/arm/mps2.c | 12 +- hw/arm/npcm7xx_boards.c | 34 + hw/arm/virt.c | 29 +- hw/char/cadence_uart.c | 61 +- hw/intc/arm_gicv3.c | 14 + hw/intc/arm_gicv3_common.c | 13 + hw/intc/arm_gicv3_cpuif.c | 7 +- hw/intc/arm_gicv3_dist.c | 5 +- hw/intc/arm_gicv3_its.c | 1322 ++++++++++++++++++++++++++++++++ hw/intc/arm_gicv3_its_common.c | 7 +- hw/intc/arm_gicv3_its_kvm.c | 2 +- hw/intc/arm_gicv3_redist.c | 153 +++- hw/misc/zynq_slcr.c | 31 +- softmmu/qdev-monitor.c | 7 +- target/arm/helper-a64.c | 1 + target/arm/helper.c | 8 + target/arm/kvm.c | 7 +- target/arm/translate-a64.c | 255 +++--- target/arm/translate.c | 21 + hw/intc/meson.build | 1 + tests/data/acpi/virt/IORT | Bin 0 -> 124 bytes tests/data/acpi/virt/IORT.memhp | Bin 0 -> 124 bytes tests/data/acpi/virt/IORT.numamem | Bin 0 -> 124 bytes tests/data/acpi/virt/IORT.pxb | Bin 0 -> 124 bytes 35 files changed, 2144 insertions(+), 210 deletions(-) create mode 100644 hw/intc/arm_gicv3_its.c create mode 100644 tests/data/acpi/virt/IORT create mode 100644 tests/data/acpi/virt/IORT.memhp create mode 100644 tests/data/acpi/virt/IORT.numamem create mode 100644 tests/data/acpi/virt/IORT.pxb