[PATCH 3/3] KVM: x86: add DSM APIC forwarding ioctls
From: muliang.shou
Date: Fri Jun 05 2026 - 05:47:11 EST
Add userspace ioctls that apply forwarded APIC, x2APIC ICR, and APIC
base updates on a target vCPU.
Signed-off-by: muliang.shou <muliang.shou@xxxxxxxxxxx>
---
arch/x86/kvm/lapic.c | 8 ++++++++
arch/x86/kvm/lapic.h | 4 ++++
arch/x86/kvm/x86.c | 40 ++++++++++++++++++++++++++++++++++++++++
include/uapi/linux/kvm.h | 27 +++++++++++++++++++++++++++
4 files changed, 79 insertions(+)
diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
index 2485d50b45647..a7b691aa9f020 100644
--- a/arch/x86/kvm/lapic.c
+++ b/arch/x86/kvm/lapic.c
@@ -2555,6 +2555,14 @@ static int kvm_lapic_reg_write(struct kvm_lapic *apic, u32 reg, u32 val)
return ret;
}
+#ifdef CONFIG_KVM_DSM_IRQ_FORWARD
+int kvm_lapic_reg_write_remote(struct kvm_lapic *apic, u32 reg, u32 val, u32 dest_id)
+{
+ return kvm_lapic_reg_write(apic, reg, val);
+}
+EXPORT_SYMBOL_FOR_KVM_INTERNAL(kvm_lapic_reg_write_remote);
+#endif
+
static int apic_mmio_write(struct kvm_vcpu *vcpu, struct kvm_io_device *this,
gpa_t address, int len, const void *data)
{
diff --git a/arch/x86/kvm/lapic.h b/arch/x86/kvm/lapic.h
index 274885af4ebc4..67828d7fc3be1 100644
--- a/arch/x86/kvm/lapic.h
+++ b/arch/x86/kvm/lapic.h
@@ -146,6 +146,10 @@ int kvm_lapic_set_vapic_addr(struct kvm_vcpu *vcpu, gpa_t vapic_addr);
void kvm_lapic_sync_from_vapic(struct kvm_vcpu *vcpu);
void kvm_lapic_sync_to_vapic(struct kvm_vcpu *vcpu);
+#ifdef CONFIG_KVM_DSM_IRQ_FORWARD
+int kvm_lapic_reg_write_remote(struct kvm_lapic *apic, u32 reg, u32 val, u32 dest_id);
+#endif
+
int kvm_x2apic_icr_write_fast(struct kvm_lapic *apic, u64 data);
int kvm_x2apic_msr_write(struct kvm_vcpu *vcpu, u32 msr, u64 data);
int kvm_x2apic_msr_read(struct kvm_vcpu *vcpu, u32 msr, u64 *data);
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 42d6f8c977985..06a1c5045606c 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -7633,6 +7633,46 @@ int kvm_arch_vm_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg)
r = kvm_vm_ioctl_set_msr_filter(kvm, &filter);
break;
}
+#ifdef CONFIG_KVM_DSM_IRQ_FORWARD
+ case KVM_DSM_IPI: {
+ struct kvm_dipi_params params;
+ struct kvm_vcpu *vcpu = NULL;
+ u32 reg;
+ u32 val;
+
+ r = 0;
+ if (copy_from_user(¶ms, argp, sizeof(params)))
+ goto out;
+ vcpu = kvm_get_vcpu(kvm, params.vcpu_id);
+ reg = params.val;
+ val = params.val2;
+ kvm_lapic_reg_write_remote(vcpu->arch.apic, reg, val, params.dest_id);
+ break;
+ }
+ case KVM_DSM_X2APIC: {
+ struct kvm_x2apic_params params;
+ struct kvm_vcpu *vcpu = NULL;
+
+ r = 0;
+ if (copy_from_user(¶ms, argp, sizeof(params)))
+ goto out;
+
+ vcpu = kvm_get_vcpu(kvm, params.vcpu_id);
+ kvm_x2apic_icr_write_fast(vcpu->arch.apic, params.data);
+ break;
+ }
+ case KVM_DSM_APIC_BASE: {
+ struct kvm_apic_base_params params;
+ struct kvm_vcpu *vcpu = NULL;
+
+ r = 0;
+ if (copy_from_user(¶ms, argp, sizeof(params)))
+ goto out;
+ vcpu = kvm_get_vcpu(kvm, params.vcpu_id);
+ kvm_apic_set_base(vcpu, params.data, params.host);
+ break;
+ }
+#endif
default:
r = -ENOTTY;
}
diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
index 75a11e72e232e..65d7094aa06e9 100644
--- a/include/uapi/linux/kvm.h
+++ b/include/uapi/linux/kvm.h
@@ -231,6 +231,33 @@ struct kvm_exit_snp_req_certs {
#define HINT_UNSAFE_IN_KVM(_symbol) _symbol
#endif
+#ifdef CONFIG_KVM_DSM_IRQ_FORWARD
+struct kvm_dipi_params {
+ int vcpu_id;
+ __u32 val;
+ __u32 val2;
+ __u32 dest_id;
+};
+
+#define KVM_DSM_IPI _IOW(KVMIO, 0xf3, struct kvm_dipi_params)
+
+struct kvm_x2apic_params {
+ int vcpu_id;
+ __u64 data;
+};
+
+#define KVM_DSM_X2APIC _IOW(KVMIO, 0xf4, struct kvm_x2apic_params)
+
+struct kvm_apic_base_params {
+ int vcpu_id;
+ bool host;
+ __u32 index;
+ __u64 data;
+};
+
+#define KVM_DSM_APIC_BASE _IOW(KVMIO, 0xf5, struct kvm_apic_base_params)
+
+#endif
/* for KVM_RUN, returned by mmap(vcpu_fd, offset=0) */
struct kvm_run {
/* in */
--
2.43.0