From 75d68a9da6cb2b319a01e81034d94f037891c5bc Mon Sep 17 00:00:00 2001 From: yxk Date: Thu, 8 Jan 2026 02:12:02 +0800 Subject: [PATCH] CCA support DA --- hw/pci/pci.c | 17 +++ hw/vfio/common.c | 8 + hw/vfio/container.c | 13 +- hw/vfio/pci.c | 20 +++ hw/vfio/pci.h | 2 + include/hw/pci/pci.h | 1 + include/sysemu/kvm.h | 2 + linux-headers/asm-arm64/kvm.h | 12 +- linux-headers/linux/kvm.h | 8 + linux-headers/linux/vfio.h | 1 + monitor/qmp-cmds.c | 5 + qapi/qom.json | 3 +- system/physmem.c | 7 + target/arm/kvm-rme.c | 266 ++++++++++------------------------ target/arm/kvm-stub.c | 4 + target/arm/kvm.c | 14 +- target/arm/kvm_arm.h | 41 ++++-- 17 files changed, 213 insertions(+), 211 deletions(-) diff --git a/hw/pci/pci.c b/hw/pci/pci.c index 447ef2b163..ba180e14a2 100644 --- a/hw/pci/pci.c +++ b/hw/pci/pci.c @@ -2054,6 +2054,23 @@ PCIDevice *pci_find_device(PCIBus *bus, int bus_num, uint8_t devfn) return bus->devices[devfn]; } +PCIDevice *pci_find_device_by_bdf(uint16_t bdf) +{ + PCIHostState *host_bridge; + PCIDevice *dev = NULL; + int bus = PCI_BUS_NUM(bdf); + uint8_t devfn = PCI_BDF_TO_DEVFN(bdf); + + QLIST_FOREACH(host_bridge, &pci_host_bridges, next) { + dev = pci_find_device(host_bridge->bus, bus, devfn); + if (dev) { + return dev; + } + } + + return NULL; +} + #define ONBOARD_INDEX_MAX (16 * 1024 - 1) static void pci_qdev_realize(DeviceState *qdev, Error **errp) diff --git a/hw/vfio/common.c b/hw/vfio/common.c index c0bc61fdee..eb75983b1a 100644 --- a/hw/vfio/common.c +++ b/hw/vfio/common.c @@ -44,6 +44,9 @@ #include "migration/blocker.h" #include "migration/qemu-file.h" #include "sysemu/tpm.h" +#include "hw/boards.h" +#include "hw/qdev-core.h" + VFIODeviceList vfio_device_list = QLIST_HEAD_INITIALIZER(vfio_device_list); @@ -798,6 +801,11 @@ static void vfio_listener_region_add(MemoryListener *listener, goto fail; } + MachineState *ms = MACHINE(qdev_get_machine()); + if (ms->cgs && kvm_enabled()) { + ms->iommu = true; + } + return; fail: diff --git a/hw/vfio/container.c b/hw/vfio/container.c index 56c55d00f1..a83adbc3d5 100644 --- a/hw/vfio/container.c +++ b/hw/vfio/container.c @@ -36,6 +36,7 @@ #include "migration/migration.h" #include "sysemu/kvm.h" #include "pci.h" +#include "target/arm/kvm_arm.h" VFIOGroupList vfio_group_list = QLIST_HEAD_INITIALIZER(vfio_group_list); @@ -420,6 +421,15 @@ static int vfio_get_iommu_type(VFIOContainer *container, } } + if (kvm_arm_rme_enabled()) { + if (ioctl(container->fd, VFIO_CHECK_EXTENSION, VFIO_TYPE1_IOMMU_RME)) { + return VFIO_TYPE1_IOMMU_RME; + } else { + error_setg(errp, "cannot find rme IOMMU model"); + return -EINVAL; + } + } + for (i = 0; i < ARRAY_SIZE(iommu_types); i++) { if (ioctl(container->fd, VFIO_CHECK_EXTENSION, iommu_types[i])) { return iommu_types[i]; @@ -440,6 +450,7 @@ static const VFIOIOMMUClass *vfio_get_iommu_class(int iommu_type, Error **errp) case VFIO_TYPE1v2_IOMMU: case VFIO_TYPE1_IOMMU: case VFIO_TYPE1v2_S_IOMMU: + case VFIO_TYPE1_IOMMU_RME: klass = object_class_by_name(TYPE_VFIO_IOMMU_LEGACY); break; case VFIO_SPAPR_TCE_v2_IOMMU: @@ -933,7 +944,7 @@ static int vfio_get_device(VFIOGroup *group, const char *name, return -1; } - if (!virtcca_cvm_enabled() && (info->flags & VFIO_DEVICE_FLAGS_SECURE)) { + if (!virtcca_cvm_enabled() && !kvm_arm_rme_enabled() && (info->flags & VFIO_DEVICE_FLAGS_SECURE)) { error_setg(errp, "Normal vm cannot use confidential device."); return -1; } diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c index 7322c8be63..912cc2dbd1 100644 --- a/hw/vfio/pci.c +++ b/hw/vfio/pci.c @@ -1211,6 +1211,26 @@ static void vfio_sub_page_bar_update_mapping(PCIDevice *pdev, int bar) memory_region_transaction_commit(); } +bool get_vfio_dev_bdf(uint16_t guest_dev_bdf, uint16_t *host_dev_bdf) +{ + PCIDevice *pdev = NULL; + VFIOPCIDevice *vdev; + + pdev = pci_find_device_by_bdf(guest_dev_bdf); + if (!pdev) { + return false; + } + + if (!object_dynamic_cast(OBJECT(pdev), TYPE_VFIO_PCI)) { + /* If the pci dev is not passthrough via vfio, it couldn't be realm */ + return false; + } + vdev = VFIO_PCI(pdev); + *host_dev_bdf = vdev->host.bus << 8 | + PCI_DEVFN(vdev->host.slot, vdev->host.function); + return true; +} + /* * PCI config space */ diff --git a/hw/vfio/pci.h b/hw/vfio/pci.h index 6e64a2654e..64a9bd0426 100644 --- a/hw/vfio/pci.h +++ b/hw/vfio/pci.h @@ -236,4 +236,6 @@ void vfio_display_finalize(VFIOPCIDevice *vdev); extern const VMStateDescription vfio_display_vmstate; +bool get_vfio_dev_bdf(uint16_t guest_dev_bdf, uint16_t *host_dev_bdf); + #endif /* HW_VFIO_VFIO_PCI_H */ diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h index 0dfe274c33..8ba492fe14 100644 --- a/include/hw/pci/pci.h +++ b/include/hw/pci/pci.h @@ -684,4 +684,5 @@ static inline void pci_irq_deassert(PCIDevice *pci_dev) MSIMessage pci_get_msi_message(PCIDevice *dev, int vector); void pci_set_power(PCIDevice *pci_dev, bool state); +PCIDevice *pci_find_device_by_bdf(uint16_t bdf); #endif diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h index 7602cd4429..fcb5a0d141 100644 --- a/include/sysemu/kvm.h +++ b/include/sysemu/kvm.h @@ -596,6 +596,8 @@ bool kvm_arch_cpu_check_are_resettable(void); bool kvm_dirty_ring_enabled(void); +bool kvm_arch_readonly_mem_allowed(KVMState *s); + uint32_t kvm_dirty_ring_size(void); int kvm_load_user_data(hwaddr loader_start, hwaddr image_end, hwaddr initrd_start, hwaddr dtb_end, hwaddr ram_size, diff --git a/linux-headers/asm-arm64/kvm.h b/linux-headers/asm-arm64/kvm.h index da480c5aa5..2fc2d4a65f 100644 --- a/linux-headers/asm-arm64/kvm.h +++ b/linux-headers/asm-arm64/kvm.h @@ -430,6 +430,7 @@ enum { #define ARM_RME_CONFIG_RPV 0 #define ARM_RME_CONFIG_HASH_ALGO 1 #define ARM_RME_CONFIG_CCAL 2 +#define ARM_RME_CONFIG_ENHANCED_RMI 3 #define ARM_RME_CONFIG_MEASUREMENT_ALGO_SHA256 0 @@ -450,6 +451,11 @@ struct arm_rme_config { __u32 hash_algo; }; + /* cfg == ARM_RME_CONFIG_ENHANCED_RMI */ + struct { + __u8 use_enhanced_rmi; + }; + /* Fix the size of the union */ __u8 reserved[256]; }; @@ -597,12 +603,12 @@ struct reg_mask_range { #define KVM_CAP_ARM_TMM_CREATE_RD 1 #define KVM_CAP_ARM_TMM_POPULATE_CVM 2 #define KVM_CAP_ARM_TMM_ACTIVATE_CVM 3 - + #define KVM_CAP_ARM_TMM_MEASUREMENT_ALGO_SHA256 0 #define KVM_CAP_ARM_TMM_MEASUREMENT_ALGO_SHA512 1 - + #define KVM_CAP_ARM_TMM_RPV_SIZE 64 - + /* List of configuration items accepted for KVM_CAP_ARM_RME_CONFIG_REALM */ #define KVM_CAP_ARM_TMM_CFG_RPV 0 #define KVM_CAP_ARM_TMM_CFG_HASH_ALGO 1 diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h index 96bc60475e..f69bea0789 100644 --- a/linux-headers/linux/kvm.h +++ b/linux-headers/linux/kvm.h @@ -267,6 +267,7 @@ struct kvm_xen_exit { #define KVM_EXIT_RISCV_CSR 36 #define KVM_EXIT_NOTIFY 37 #define KVM_EXIT_LOONGARCH_IOCSR 38 +#define KVM_EXIT_ARM_RME_DEV 39 /* For KVM_EXIT_INTERNAL_ERROR */ /* Emulate instruction failed. */ @@ -517,6 +518,13 @@ struct kvm_run { #define KVM_NOTIFY_CONTEXT_INVALID (1 << 0) __u32 flags; } notify; + /* KVM_EXIT_ARM_RME_DEV */ + struct { + __u16 guest_dev_bdf; + __u16 dev_bdf; + bool dev_valid; + bool vfio_dev; + } rme_dev; /* Fix the size of the union. */ char padding[256]; }; diff --git a/linux-headers/linux/vfio.h b/linux-headers/linux/vfio.h index 5b1e2871af..538c8c940e 100644 --- a/linux-headers/linux/vfio.h +++ b/linux-headers/linux/vfio.h @@ -26,6 +26,7 @@ #define VFIO_SPAPR_TCE_IOMMU 2 #define VFIO_TYPE1v2_IOMMU 3 #define VFIO_TYPE1v2_S_IOMMU 12 +#define VFIO_TYPE1_IOMMU_RME 13 /* * IOMMU enforces DMA cache coherence (ex. PCIe NoSnoop stripping). This * capability is subject to change as groups are added or removed. diff --git a/monitor/qmp-cmds.c b/monitor/qmp-cmds.c index c0b66f11bf..e905e41f30 100644 --- a/monitor/qmp-cmds.c +++ b/monitor/qmp-cmds.c @@ -56,6 +56,11 @@ void qmp_stop(Error **errp) return; } + if (kvm_arm_rme_enabled()) { + qemu_log("qmp stop is received and realm does not support it\n"); + return; + } + /* if there is a dump in background, we should wait until the dump * finished */ if (qemu_system_dump_in_progress()) { diff --git a/qapi/qom.json b/qapi/qom.json index f409bd0306..74678dcd11 100644 --- a/qapi/qom.json +++ b/qapi/qom.json @@ -992,7 +992,8 @@ 'data': { '*personalization-value': 'str', '*measurement-algorithm': 'RmeGuestMeasurementAlgorithm', '*measurement-log': 'bool', - '*ccal-enable': 'bool' } } + '*ccal-enable': 'bool' , + '*enhanced-rmi': 'bool' } } ## # @ObjectType: diff --git a/system/physmem.c b/system/physmem.c index e862f99ff6..0adf73bb9f 100644 --- a/system/physmem.c +++ b/system/physmem.c @@ -80,6 +80,8 @@ #include #endif +#include "target/arm/kvm_arm.h" + //#define DEBUG_SUBPAGE /* ram_list is read under rcu_read_lock()/rcu_read_unlock(). Writes @@ -369,6 +371,11 @@ address_space_translate_internal(AddressSpaceDispatch *d, hwaddr addr, hwaddr *x MemoryRegion *mr; Int128 diff; + if (kvm_arm_rme_enabled()) { + error_report("address_space_translate_internal addr: %lx, mssked: %lx", addr, rme_mask_share_bit(addr)); + addr = rme_mask_share_bit(addr); + } + section = address_space_lookup_region(d, addr, resolve_subpage); /* Compute offset within MemoryRegionSection */ addr -= section->offset_within_address_space; diff --git a/target/arm/kvm-rme.c b/target/arm/kvm-rme.c index 0a16b837d2..0343f9545e 100644 --- a/target/arm/kvm-rme.c +++ b/target/arm/kvm-rme.c @@ -54,11 +54,6 @@ struct RealmDmaRegion { IOMMUMemoryRegion parent_obj; }; -#define TYPE_REALM_DMA_REGION "realm-dma-region" -OBJECT_DECLARE_SIMPLE_TYPE(RealmDmaRegion, REALM_DMA_REGION) -OBJECT_DEFINE_SIMPLE_TYPE(RealmDmaRegion, realm_dma_region, - REALM_DMA_REGION, IOMMU_MEMORY_REGION); - typedef struct RealmPrivateSharedListener { MemoryRegion *mr; hwaddr offset_within_region; @@ -83,12 +78,12 @@ struct RmeGuest { uint8_t personalization_value[ARM_RME_CONFIG_RPV_SIZE]; RmeGuestMeasurementAlgorithm measurement_algo; bool use_measurement_log; + bool use_enhanced_rmi; RmeRamRegion init_ram; uint8_t ipa_bits; size_t num_cpus; - RealmDmaRegion *dma_region; QLIST_HEAD(, RealmPrivateSharedListener) ram_discard_list; MemoryListener memory_listener; AddressSpace dma_as; @@ -131,6 +126,17 @@ typedef struct { static RmeGuest *rme_guest; +bool kvm_arm_rme_enabled(void) +{ + return !!rme_guest; +} + +hwaddr rme_mask_share_bit(hwaddr addr) +{ + const hwaddr address_mask = MAKE_64BIT_MASK(0, rme_guest->ipa_bits - 1); + return addr & address_mask; +} + static int rme_init_measurement_log(MachineState *ms) { Object *log; @@ -447,6 +453,14 @@ static int rme_configure_one(RmeGuest *guest, uint32_t cfg, Error **errp) } cfg_str = "ccal enabled"; break; + case ARM_RME_CONFIG_ENHANCED_RMI: + /* By default ENHANCED_RMI is off, there is no need to call + * use_enhanced_rmi=0 */ + if (!guest->use_enhanced_rmi) + return 0; + args.use_enhanced_rmi = (__u8)guest->use_enhanced_rmi; + cfg_str = "use enhanced rmi"; + break; default: g_assert_not_reached(); } @@ -467,6 +481,7 @@ static int rme_configure(Error **errp) ARM_RME_CONFIG_RPV, ARM_RME_CONFIG_HASH_ALGO, ARM_RME_CONFIG_CCAL, + ARM_RME_CONFIG_ENHANCED_RMI, }; for (option = 0; option < ARRAY_SIZE(config_options); option++) { @@ -592,7 +607,7 @@ static void rme_map_ram_realm(hwaddr base, uint64_t size) } } -void rme_map_ram(hwaddr base, size_t size, GSList *ram_regions) +static void rme_map_ram(hwaddr base, size_t size, GSList *ram_regions) { uint64_t last_end = base; GSList *current = ram_regions; @@ -645,6 +660,13 @@ static int rme_create_realm(Error **errp) g_slist_foreach(rme_guest->ram_regions, rme_populate_ram_region, errp); + // rust-rmm:enable DA + MachineState *ms = MACHINE(qdev_get_machine()); + if (ms->iommu) { + rme_map_ram(rme_guest->init_ram.base, rme_guest->init_ram.size, rme_guest->ram_regions); + } + + // c-rmm:enable ccal if (rme_guest->ccal_enable) { rme_map_ram(rme_guest->ram_base, rme_guest->ram_size, rme_guest->ram_regions); } @@ -759,6 +781,34 @@ static void rme_set_ccal_enable(Object *obj, bool value, Error **errp) guest->ccal_enable = value; } +static bool rme_get_enhanced_rmi(Object *obj, Error **errp) +{ + RmeGuest *guest = RME_GUEST(obj); + + return guest->use_enhanced_rmi; +} + +int kvm_arm_handle_rme_dev(CPUState *cs, struct kvm_run *run) +{ + ARMCPU *cpu = ARM_CPU(cs); + + if (!cpu->kvm_rme) { + return -EINVAL; + } + + /* Host dev bdf is valid if the dev is passthrough via VFIO */ + run->rme_dev.vfio_dev = get_vfio_dev_bdf(run->rme_dev.guest_dev_bdf, &run->rme_dev.dev_bdf); + run->rme_dev.dev_valid = true; + return 0; +} + +static void rme_set_enhanced_rmi(Object *obj, bool value, Error **errp) +{ + RmeGuest *guest = RME_GUEST(obj); + + guest->use_enhanced_rmi = value; +} + static void rme_guest_class_init(ObjectClass *oc, void *data) { object_class_property_add_str(oc, "personalization-value", rme_get_rpv, @@ -785,6 +835,12 @@ static void rme_guest_class_init(ObjectClass *oc, void *data) object_class_property_set_description(oc, "ccal-enable", "Set on/off to enable/disable ccal " "for realm vm"); + + object_class_property_add_bool(oc, "enhanced-rmi", + rme_get_enhanced_rmi, + rme_set_enhanced_rmi); + object_class_property_set_description(oc, "enhanced-rmi", + "Enable/disable enhanced RMI interfaces"); } static void rme_guest_init(Object *obj) @@ -903,6 +959,16 @@ void kvm_arm_rme_init_guest_ram(hwaddr base, size_t size) } } +void kvm_arm_rme_init_gpa_space(hwaddr highest_gpa, PCIBus *pci_bus) +{ + const unsigned int ipa_bits = 64 - clz64(highest_gpa) + 1; + if (!rme_guest) { + return; + } + + rme_guest->ipa_bits = ipa_bits; + } + int kvm_arm_rme_vcpu_init(CPUState *cs) { ARMCPU *cpu = ARM_CPU(cs); @@ -922,191 +988,6 @@ int kvm_arm_rme_vm_type(MachineState *ms) return 0; } -static int rme_ram_discard_notify(StateChangeListener *scl, - MemoryRegionSection *section, - bool populate) -{ - hwaddr gpa, next; - IOMMUTLBEvent event; - const hwaddr end = section->offset_within_address_space + - int128_get64(section->size); - const hwaddr address_mask = MAKE_64BIT_MASK(0, rme_guest->ipa_bits - 1); - PrivateSharedListener *psl = container_of(scl, PrivateSharedListener, scl); - RealmPrivateSharedListener *rpsl = container_of(psl, RealmPrivateSharedListener, - listener); - - assert(rme_guest->dma_region != NULL); - - event.type = populate ? IOMMU_NOTIFIER_MAP : IOMMU_NOTIFIER_UNMAP; - event.entry.target_as = &address_space_memory; - event.entry.perm = populate ? IOMMU_RW : IOMMU_NONE; - event.entry.addr_mask = rpsl->granularity - 1; - - assert(end <= address_mask); - - /* - * Create IOMMU mappings from the top half of the address space to the RAM - * region. - */ - for (gpa = section->offset_within_address_space; gpa < end; gpa = next) { - event.entry.iova = gpa + address_mask + 1; - event.entry.translated_addr = gpa; - memory_region_notify_iommu(IOMMU_MEMORY_REGION(rme_guest->dma_region), - 0, event); - - next = ROUND_UP(gpa + 1, rpsl->granularity); - next = MIN(next, end); - } - - return 0; -} - -static int rme_ram_discard_notify_populate(StateChangeListener *scl, - MemoryRegionSection *section) -{ - return rme_ram_discard_notify(scl, section, /* populate */ true); -} - -static int rme_ram_discard_notify_discard(StateChangeListener *scl, - MemoryRegionSection *section) -{ - return rme_ram_discard_notify(scl, section, /* populate */ false); -} - -/* Install a RAM discard listener */ -static void rme_listener_region_add(MemoryListener *listener, - MemoryRegionSection *section) -{ - RealmPrivateSharedListener *rpsl; - GenericStateManager *gsm = memory_region_get_generic_state_manager(section->mr); - - - if (!gsm) { - return; - } - - rpsl = g_new0(RealmPrivateSharedListener, 1); - rpsl->mr = section->mr; - rpsl->offset_within_region = section->offset_within_region; - rpsl->granularity = generic_state_manager_get_min_granularity(gsm, - section->mr); - QLIST_INSERT_HEAD(&rme_guest->ram_discard_list, rpsl, rpsl_next); - - private_shared_listener_init(&rpsl->listener, - rme_ram_discard_notify_populate, - rme_ram_discard_notify_discard, true); - generic_state_manager_register_listener(gsm, &rpsl->listener.scl, section); -} - -static void rme_listener_region_del(MemoryListener *listener, - MemoryRegionSection *section) -{ - RealmPrivateSharedListener *rpsl; - GenericStateManager *gsm = memory_region_get_generic_state_manager(section->mr); - - if (!gsm) { - return; - } - - QLIST_FOREACH(rpsl, &rme_guest->ram_discard_list, rpsl_next) { - if (MEMORY_REGION(rpsl->mr) == section->mr && - rpsl->offset_within_region == section->offset_within_region) { - generic_state_manager_unregister_listener(gsm, &rpsl->listener.scl); - g_free(rpsl); - break; - } - } -} - -static AddressSpace *rme_dma_get_address_space(PCIBus *bus, void *opaque, - int devfn) -{ - return &rme_guest->dma_as; -} - -static const PCIIOMMUOps rme_dma_ops = { - .get_address_space = rme_dma_get_address_space, -}; - -void kvm_arm_rme_init_gpa_space(hwaddr highest_gpa, PCIBus *pci_bus) -{ - RealmDmaRegion *dma_region; - const unsigned int ipa_bits = 64 - clz64(highest_gpa) + 1; - - if (!rme_guest) { - return; - } - - assert(ipa_bits < 64); - - /* - * Setup a DMA translation from the shared top half of the guest-physical - * address space to our merged view of RAM. - */ - dma_region = g_new0(RealmDmaRegion, 1); - - memory_region_init_iommu(dma_region, sizeof(*dma_region), - TYPE_REALM_DMA_REGION, OBJECT(rme_guest), - "realm-dma-region", 1ULL << ipa_bits); - address_space_init(&rme_guest->dma_as, MEMORY_REGION(dma_region), - TYPE_REALM_DMA_REGION); - rme_guest->dma_region = dma_region; - - pci_setup_iommu(pci_bus, &rme_dma_ops, NULL); - - /* - * Install notifiers to forward RAM discard changes to the IOMMU notifiers - * (ie. tell VFIO to map shared pages and unmap private ones). - */ - rme_guest->memory_listener = (MemoryListener) { - .name = "rme", - .region_add = rme_listener_region_add, - .region_del = rme_listener_region_del, - }; - memory_listener_register(&rme_guest->memory_listener, - &address_space_memory); - - rme_guest->ipa_bits = ipa_bits; -} - -static void realm_dma_region_init(Object *obj) -{ -} - -static IOMMUTLBEntry realm_dma_region_translate(IOMMUMemoryRegion *mr, - hwaddr addr, - IOMMUAccessFlags flag, - int iommu_idx) -{ - const hwaddr address_mask = MAKE_64BIT_MASK(0, rme_guest->ipa_bits - 1); - IOMMUTLBEntry entry = { - .target_as = &address_space_memory, - .iova = addr, - .translated_addr = addr & address_mask, - .addr_mask = address_mask, - .perm = IOMMU_RW, - }; - - return entry; -} - -static void realm_dma_region_replay(IOMMUMemoryRegion *mr, IOMMUNotifier *n) -{ - /* Nothing is shared at boot */ -} - -static void realm_dma_region_finalize(Object *obj) -{ -} - -static void realm_dma_region_class_init(ObjectClass *oc, void *data) -{ - IOMMUMemoryRegionClass *imrc = IOMMU_MEMORY_REGION_CLASS(oc); - - imrc->translate = realm_dma_region_translate; - imrc->replay = realm_dma_region_replay; -} - Object *kvm_arm_rme_get_measurement_log(void) { if (rme_guest && rme_guest->log) { @@ -1114,3 +995,4 @@ Object *kvm_arm_rme_get_measurement_log(void) } return NULL; } + diff --git a/target/arm/kvm-stub.c b/target/arm/kvm-stub.c index 965a486b32..7a2c4166e3 100644 --- a/target/arm/kvm-stub.c +++ b/target/arm/kvm-stub.c @@ -22,3 +22,7 @@ bool write_list_to_kvmstate(ARMCPU *cpu, int level) { g_assert_not_reached(); } + +void kvm_arm_rme_init_gpa_space(hwaddr highest_gpa, PCIBus *pci_bus) +{ +} diff --git a/target/arm/kvm.c b/target/arm/kvm.c index f45783a9da..1a7227aaff 100644 --- a/target/arm/kvm.c +++ b/target/arm/kvm.c @@ -1151,6 +1151,9 @@ int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run) case KVM_EXIT_HYPERCALL: ret = kvm_arm_handle_hypercall(cs, run); break; + case KVM_EXIT_ARM_RME_DEV: + ret = kvm_arm_handle_rme_dev(cs, run); + break; default: qemu_log_mask(LOG_UNIMP, "%s: un-handled exit reason %d\n", __func__, run->exit_reason); @@ -1327,7 +1330,16 @@ int kvm_arch_msi_data_to_gsi(uint32_t data) bool kvm_arch_cpu_check_are_resettable(void) { - return !virtcca_cvm_enabled(); + /* A Realm cannot be reset */ + if (kvm_arm_rme_enabled()) { + return false; + } + + if (virtcca_cvm_enabled()) { + return false; + } + + return true; } static void kvm_arch_get_eager_split_size(Object *obj, Visitor *v, diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h index 8e9b2039c4..d95b14c64b 100644 --- a/target/arm/kvm_arm.h +++ b/target/arm/kvm_arm.h @@ -441,15 +441,6 @@ int kvm_arm_rme_vcpu_init(CPUState *cs); */ void kvm_arm_rme_init_guest_ram(hwaddr base, size_t size); -/** - * kvm_arm_rme_setup_gpa - * @highest_gpa: highest address of the lower half of the guest address space - * @pci_bus: The main PCI bus, for which PCI queries DMA address spaces - * - * Setup the guest-physical address space for a Realm. Install a memory region - * and notifier to manage the shared upper half of the address space. - */ -void kvm_arm_rme_init_gpa_space(hwaddr highest_gpa, PCIBus *pci_bus); /** * kvm_arm_rme_get_measurement_log @@ -461,6 +452,12 @@ void kvm_arm_rme_init_gpa_space(hwaddr highest_gpa, PCIBus *pci_bus); */ Object *kvm_arm_rme_get_measurement_log(void); + + +hwaddr rme_mask_share_bit(hwaddr addr); + +bool kvm_arm_rme_enabled(void); + #else /* @@ -491,10 +488,17 @@ static inline void kvm_arm_rme_init_guest_ram(hwaddr base, size_t size) { } -static inline void kvm_arm_rme_init_gpa_space(hwaddr highest_gpa, - PCIBus *pci_bus) -{ -} +/** + * kvm_arm_rme_setup_gpa + * @highest_gpa: highest address of the lower half of the guest address space + * @pci_bus: The main PCI bus, for which PCI queries DMA address spaces + * + * Setup the guest-physical address space for a Realm. Install a memory region + * and notifier to manage the shared upper half of the address space. + */ +void kvm_arm_rme_init_gpa_space(hwaddr highest_gpa, PCIBus *pci_bus); + +hwaddr rme_mask_share_bit(hwaddr addr); static inline Object *kvm_arm_rme_get_measurement_log(void) { @@ -639,4 +643,15 @@ void kvm_arm_copy_hw_debug_data(struct kvm_guest_debug_arch *ptr); */ bool kvm_arm_verify_ext_dabt_pending(CPUState *cs); +/** + * kvm_arm_handle_rme_dev: + * @cs: CPUState + * @run: kvm run handler + * + * Find the corresponding host pci dev of the pci dev in realm, request host to + * validate whether the dev is realm. + * + * Returns: 0 if the host pci dev if found, and the request is sent. + */ +int kvm_arm_handle_rme_dev(CPUState *cs, struct kvm_run *run); #endif -- Gitee