Add userspace ioctls that apply forwarded APIC, x2APIC ICR, and APIC base updates on a target vCPU. Signed-off-by: muliang.shou --- 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