From 7de8319bedc7cc17eddddaf5bc23c7156f8c8586 Mon Sep 17 00:00:00 2001 From: yxk Date: Thu, 18 Dec 2025 03:30:42 +0800 Subject: [PATCH] CCA support DA --- hw/pci/pci.c | 17 +++++++++++++++++ hw/vfio/pci.c | 22 ++++++++++++++++++++++ hw/vfio/pci.h | 2 ++ include/hw/pci/pci.h | 1 + linux-headers/linux/kvm.h | 15 +++++++++++++++ target/arm/kvm-rme.c | 28 ++++++++++++++++++++++++++++ target/arm/kvm.c | 3 +++ target/arm/kvm_arm.h | 11 +++++++++++ 8 files changed, 99 insertions(+) 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/pci.c b/hw/vfio/pci.c index 7322c8be63..9814e06445 100644 --- a/hw/vfio/pci.c +++ b/hw/vfio/pci.c @@ -1211,6 +1211,28 @@ 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/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h index 96bc60475e..aa9b966598 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,10 @@ struct kvm_run { #define KVM_NOTIFY_CONTEXT_INVALID (1 << 0) __u32 flags; } notify; + /* KVM_EXIT_ARM_RME_DEV */ + struct { + __u16 guest_dev_bdf; + } rme_dev; /* Fix the size of the union. */ char padding[256]; }; @@ -2469,4 +2474,14 @@ struct kvm_arm_rmm_psci_complete { __u32 padding[3]; }; +/* Available with KVM_CAP_ARM_RME, only for VMs with KVM_VM_TYPE_ARM_REALM */ +struct kvm_arm_rme_dev_validate { + __u16 dev_bdf; /* pci dev bdf in the host */ + __u16 guest_dev_bdf; /* pci dev bdf in the realm */ + bool vfio_dev; /* True if the host dev bdf refers to a VFIO dev */ + __u32 reserved[6]; +}; + +#define KVM_ARM_VCPU_RME_DEV_VALIDATE _IOW(KVMIO, 0xd3, struct kvm_arm_rme_dev_validate) + #endif /* __LINUX_KVM_H */ diff --git a/target/arm/kvm-rme.c b/target/arm/kvm-rme.c index 0a16b837d2..85114c40be 100644 --- a/target/arm/kvm-rme.c +++ b/target/arm/kvm-rme.c @@ -759,6 +759,34 @@ static void rme_set_ccal_enable(Object *obj, bool value, Error **errp) guest->ccal_enable = value; } +int kvm_arm_handle_rme_dev(CPUState *cs, uint16_t guest_dev_bdf) +{ + ARMCPU *cpu = ARM_CPU(cs); + uint16_t host_dev_bdf = 0; + bool vfio_dev; + int ret; + + if (!cpu->kvm_rme) { + return -EINVAL; + } + + /* Host dev bdf is valid if the dev is passthrough via VFIO */ + vfio_dev = get_vfio_dev_bdf(guest_dev_bdf, &host_dev_bdf); + struct kvm_arm_rme_dev_validate dev_args = { + .dev_bdf = host_dev_bdf, + .guest_dev_bdf = guest_dev_bdf, + .vfio_dev = vfio_dev, + }; + + ret = kvm_vcpu_ioctl(cs, KVM_ARM_VCPU_RME_DEV_VALIDATE, &dev_args); + if (ret) { + error_report("RME: Failed to validate rdev %#x, %#x, err %s", + guest_dev_bdf, host_dev_bdf, strerror(-ret)); + return -EIO; + } + return 0; +} + static void rme_guest_class_init(ObjectClass *oc, void *data) { object_class_property_add_str(oc, "personalization-value", rme_get_rpv, diff --git a/target/arm/kvm.c b/target/arm/kvm.c index f45783a9da..2c3439211e 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->rme_dev.guest_dev_bdf); + break; default: qemu_log_mask(LOG_UNIMP, "%s: un-handled exit reason %d\n", __func__, run->exit_reason); diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h index 8e9b2039c4..78e8e40ee6 100644 --- a/target/arm/kvm_arm.h +++ b/target/arm/kvm_arm.h @@ -639,4 +639,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 + * @guest_dev_bdf: bdf of a pci dev in realm + * + * 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, uint16_t guest_dev_bdf); #endif -- Gitee