From: "Mi, Dapeng" <dapeng1.mi@linux.intel.com>
To: Manali Shukla <manali.shukla@amd.com>,
kvm@vger.kernel.org, linux-perf-users@vger.kernel.org,
linux-doc@vger.kernel.org
Cc: seanjc@google.com, pbonzini@redhat.com, nikunj@amd.com,
bp@alien8.de, peterz@infradead.org, mingo@redhat.com,
mizhang@google.com, thomas.lendacky@amd.com,
ravi.bangoria@amd.com, Sandipan.Das@amd.com
Subject: Re: [PATCH v1 02/11] KVM: Add KVM_GET_LAPIC_W_EXTAPIC and KVM_SET_LAPIC_W_EXTAPIC for extapic
Date: Tue, 15 Jul 2025 10:21:58 +0800 [thread overview]
Message-ID: <03934334-a4b6-4c9f-ad99-5f8041836065@linux.intel.com> (raw)
In-Reply-To: <20250627162550.14197-3-manali.shukla@amd.com>
On 6/28/2025 12:25 AM, Manali Shukla wrote:
> Modern AMD processors expose four additional extended LVT registers in
> the extended APIC register space, which can be used for additional
> interrupt sources such as instruction-based sampling and others.
>
> To support this, introduce two new vCPU-based IOCTLs:
> KVM_GET_LAPIC_W_EXTAPIC and KVM_SET_LAPIC_W_EXTAPIC. These IOCTLs works
> similarly to KVM_GET_LAPIC and KVM_SET_LAPIC, but operate on APIC page
> with extended APIC register space located at APIC offsets 400h-530h.
>
> These IOCTLs are intended for use when extended APIC support is
> enabled in the guest. They allow saving and restoring the full APIC
> page, including the extended registers.
>
> To support this, the `struct kvm_lapic_state_w_extapic` has been made
> extensible rather than hardcoding its size, improving forward
> compatibility.
>
> Documentation for the new IOCTLs has also been added.
>
> For more details on the extended APIC space, refer to AMD Programmer’s
> Manual Volume 2, Section 16.4.5: Extended Interrupts.
> https://bugzilla.kernel.org/attachment.cgi?id=306250
>
> Signed-off-by: Manali Shukla <manali.shukla@amd.com>
> ---
> Documentation/virt/kvm/api.rst | 23 ++++++++++++++++++++
> arch/x86/include/uapi/asm/kvm.h | 5 +++++
> arch/x86/kvm/lapic.c | 12 ++++++-----
> arch/x86/kvm/lapic.h | 6 ++++--
> arch/x86/kvm/x86.c | 37 ++++++++++++++++++++++++---------
> include/uapi/linux/kvm.h | 10 +++++++++
> 6 files changed, 76 insertions(+), 17 deletions(-)
>
> diff --git a/Documentation/virt/kvm/api.rst b/Documentation/virt/kvm/api.rst
> index 1bd2d42e6424..0ca11d43f833 100644
> --- a/Documentation/virt/kvm/api.rst
> +++ b/Documentation/virt/kvm/api.rst
> @@ -2041,6 +2041,18 @@ error.
> Reads the Local APIC registers and copies them into the input argument. The
> data format and layout are the same as documented in the architecture manual.
>
> +::
> +
> + #define KVM_APIC_EXT_REG_SIZE 0x540
> + struct kvm_lapic_state_w_extapic {
> + __DECLARE_FLEX_ARRAY(__u8, regs);
> + };
> +
> +Applications should use KVM_GET_LAPIC_W_EXTAPIC ioctl if extended APIC is
> +enabled. KVM_GET_LAPIC_W_EXTAPIC reads Local APIC registers with extended
> +APIC register space located at offsets 400h-530h and copies them into input
> +argument.
> +
> If KVM_X2APIC_API_USE_32BIT_IDS feature of KVM_CAP_X2APIC_API is
> enabled, then the format of APIC_ID register depends on the APIC mode
> (reported by MSR_IA32_APICBASE) of its VCPU. x2APIC stores APIC ID in
> @@ -2072,6 +2084,17 @@ always uses xAPIC format.
> Copies the input argument into the Local APIC registers. The data format
> and layout are the same as documented in the architecture manual.
>
> +::
> +
> + #define KVM_APIC_EXT_REG_SIZE 0x540
> + struct kvm_lapic_state_w_extapic {
> + __DECLARE_FLEX_ARRAY(__u8, regs);
> + };
> +
> +Applications should use KVM_SET_LAPIC_W_EXTAPIC ioctl if extended APIC is enabled.
> +KVM_SET_LAPIC_W_EXTAPIC copies input arguments with extended APIC register into
> +Local APIC and extended APIC registers.
> +
> The format of the APIC ID register (bytes 32-35 of struct kvm_lapic_state's
> regs field) depends on the state of the KVM_CAP_X2APIC_API capability.
> See the note in KVM_GET_LAPIC.
> diff --git a/arch/x86/include/uapi/asm/kvm.h b/arch/x86/include/uapi/asm/kvm.h
> index 6f3499507c5e..91c3c5b8cae3 100644
> --- a/arch/x86/include/uapi/asm/kvm.h
> +++ b/arch/x86/include/uapi/asm/kvm.h
> @@ -124,6 +124,11 @@ struct kvm_lapic_state {
> char regs[KVM_APIC_REG_SIZE];
> };
>
> +#define KVM_APIC_EXT_REG_SIZE 0x540
> +struct kvm_lapic_state_w_extapic {
> + __DECLARE_FLEX_ARRAY(__u8, regs);
> +};
The name "kvm_lapic_state_w_extapic" seems a little bit too long, maybe
"kvm_ext_lapic_state" is enough?
> +
> struct kvm_segment {
> __u64 base;
> __u32 limit;
> diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
> index 73418dc0ebb2..00ca2b0faa45 100644
> --- a/arch/x86/kvm/lapic.c
> +++ b/arch/x86/kvm/lapic.c
> @@ -3046,7 +3046,7 @@ void kvm_apic_ack_interrupt(struct kvm_vcpu *vcpu, int vector)
> EXPORT_SYMBOL_GPL(kvm_apic_ack_interrupt);
>
> static int kvm_apic_state_fixup(struct kvm_vcpu *vcpu,
> - struct kvm_lapic_state *s, bool set)
> + struct kvm_lapic_state_w_extapic *s, bool set)
> {
> if (apic_x2apic_mode(vcpu->arch.apic)) {
> u32 x2apic_id = kvm_x2apic_id(vcpu->arch.apic);
> @@ -3097,9 +3097,10 @@ static int kvm_apic_state_fixup(struct kvm_vcpu *vcpu,
> return 0;
> }
>
> -int kvm_apic_get_state(struct kvm_vcpu *vcpu, struct kvm_lapic_state *s)
> +int kvm_apic_get_state(struct kvm_vcpu *vcpu, struct kvm_lapic_state_w_extapic *s,
> + unsigned int size)
> {
> - memcpy(s->regs, vcpu->arch.apic->regs, sizeof(*s));
> + memcpy(s->regs, vcpu->arch.apic->regs, size);
>
> /*
> * Get calculated timer current count for remaining timer period (if
> @@ -3111,7 +3112,8 @@ int kvm_apic_get_state(struct kvm_vcpu *vcpu, struct kvm_lapic_state *s)
> return kvm_apic_state_fixup(vcpu, s, false);
> }
>
> -int kvm_apic_set_state(struct kvm_vcpu *vcpu, struct kvm_lapic_state *s)
> +int kvm_apic_set_state(struct kvm_vcpu *vcpu, struct kvm_lapic_state_w_extapic *s,
> + unsigned int size)
> {
> struct kvm_lapic *apic = vcpu->arch.apic;
> int r;
> @@ -3126,7 +3128,7 @@ int kvm_apic_set_state(struct kvm_vcpu *vcpu, struct kvm_lapic_state *s)
> kvm_recalculate_apic_map(vcpu->kvm);
> return r;
> }
> - memcpy(vcpu->arch.apic->regs, s->regs, sizeof(*s));
> + memcpy(vcpu->arch.apic->regs, s->regs, size);
>
> atomic_set_release(&apic->vcpu->kvm->arch.apic_map_dirty, DIRTY);
> kvm_recalculate_apic_map(vcpu->kvm);
> diff --git a/arch/x86/kvm/lapic.h b/arch/x86/kvm/lapic.h
> index 4518b4e0552f..7ad946b3738d 100644
> --- a/arch/x86/kvm/lapic.h
> +++ b/arch/x86/kvm/lapic.h
> @@ -120,9 +120,11 @@ bool kvm_irq_delivery_to_apic_fast(struct kvm *kvm, struct kvm_lapic *src,
> void kvm_apic_send_ipi(struct kvm_lapic *apic, u32 icr_low, u32 icr_high);
>
> int kvm_apic_set_base(struct kvm_vcpu *vcpu, u64 value, bool host_initiated);
> -int kvm_apic_get_state(struct kvm_vcpu *vcpu, struct kvm_lapic_state *s);
> -int kvm_apic_set_state(struct kvm_vcpu *vcpu, struct kvm_lapic_state *s);
> void kvm_apic_update_hwapic_isr(struct kvm_vcpu *vcpu);
> +int kvm_apic_get_state(struct kvm_vcpu *vcpu, struct kvm_lapic_state_w_extapic *s,
> + unsigned int size);
> +int kvm_apic_set_state(struct kvm_vcpu *vcpu, struct kvm_lapic_state_w_extapic *s,
> + unsigned int size);
> int kvm_lapic_find_highest_irr(struct kvm_vcpu *vcpu);
>
> u64 kvm_get_lapic_tscdeadline_msr(struct kvm_vcpu *vcpu);
> diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
> index c880a512005e..c273bbbbbcc6 100644
> --- a/arch/x86/kvm/x86.c
> +++ b/arch/x86/kvm/x86.c
> @@ -5156,25 +5156,25 @@ void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
> }
>
> static int kvm_vcpu_ioctl_get_lapic(struct kvm_vcpu *vcpu,
> - struct kvm_lapic_state *s)
> + struct kvm_lapic_state_w_extapic *s, unsigned int size)
> {
> if (vcpu->arch.apic->guest_apic_protected)
> return -EINVAL;
>
> kvm_x86_call(sync_pir_to_irr)(vcpu);
>
> - return kvm_apic_get_state(vcpu, s);
> + return kvm_apic_get_state(vcpu, s, size);
> }
>
> static int kvm_vcpu_ioctl_set_lapic(struct kvm_vcpu *vcpu,
> - struct kvm_lapic_state *s)
> + struct kvm_lapic_state_w_extapic *s, unsigned int size)
> {
> int r;
>
> if (vcpu->arch.apic->guest_apic_protected)
> return -EINVAL;
>
> - r = kvm_apic_set_state(vcpu, s);
> + r = kvm_apic_set_state(vcpu, s, size);
> if (r)
> return r;
> update_cr8_intercept(vcpu);
> @@ -5903,10 +5903,11 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
> {
> struct kvm_vcpu *vcpu = filp->private_data;
> void __user *argp = (void __user *)arg;
> + unsigned long size;
> int r;
> union {
> struct kvm_sregs2 *sregs2;
> - struct kvm_lapic_state *lapic;
> + struct kvm_lapic_state_w_extapic *lapic;
> struct kvm_xsave *xsave;
> struct kvm_xcrs *xcrs;
> void *buffer;
> @@ -5916,35 +5917,51 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
>
> u.buffer = NULL;
> switch (ioctl) {
> + case KVM_GET_LAPIC_W_EXTAPIC:
> case KVM_GET_LAPIC: {
> r = -EINVAL;
> if (!lapic_in_kernel(vcpu))
> goto out;
> - u.lapic = kzalloc(sizeof(struct kvm_lapic_state), GFP_KERNEL);
> +
> + if (ioctl == KVM_GET_LAPIC_W_EXTAPIC)
> + size = struct_size(u.lapic, regs, KVM_APIC_EXT_REG_SIZE);
> + else
> + size = sizeof(struct kvm_lapic_state);
> +
> + u.lapic = kzalloc(size, GFP_KERNEL);
>
> r = -ENOMEM;
> if (!u.lapic)
> goto out;
> - r = kvm_vcpu_ioctl_get_lapic(vcpu, u.lapic);
> + r = kvm_vcpu_ioctl_get_lapic(vcpu, u.lapic, size);
> if (r)
> goto out;
> +
> r = -EFAULT;
> - if (copy_to_user(argp, u.lapic, sizeof(struct kvm_lapic_state)))
> + if (copy_to_user(argp, u.lapic, size))
> goto out;
> +
> r = 0;
> break;
> }
> + case KVM_SET_LAPIC_W_EXTAPIC:
> case KVM_SET_LAPIC: {
> r = -EINVAL;
> if (!lapic_in_kernel(vcpu))
> goto out;
> - u.lapic = memdup_user(argp, sizeof(*u.lapic));
> +
> + if (ioctl == KVM_SET_LAPIC_W_EXTAPIC)
> + size = struct_size(u.lapic, regs, KVM_APIC_EXT_REG_SIZE);
> + else
> + size = sizeof(struct kvm_lapic_state);
> + u.lapic = memdup_user(argp, size);
> +
> if (IS_ERR(u.lapic)) {
> r = PTR_ERR(u.lapic);
> goto out_nofree;
> }
>
> - r = kvm_vcpu_ioctl_set_lapic(vcpu, u.lapic);
> + r = kvm_vcpu_ioctl_set_lapic(vcpu, u.lapic, size);
> break;
> }
> case KVM_INTERRUPT: {
> diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
> index d00b85cb168c..cf23c1b52c49 100644
> --- a/include/uapi/linux/kvm.h
> +++ b/include/uapi/linux/kvm.h
> @@ -1290,6 +1290,16 @@ struct kvm_vfio_spapr_tce {
> #define KVM_SET_FPU _IOW(KVMIO, 0x8d, struct kvm_fpu)
> #define KVM_GET_LAPIC _IOR(KVMIO, 0x8e, struct kvm_lapic_state)
> #define KVM_SET_LAPIC _IOW(KVMIO, 0x8f, struct kvm_lapic_state)
> +/*
> + * Added to save/restore local APIC registers with extended APIC (extapic)
> + * register space.
> + *
> + * Qemu emulates extapic logic only when KVM enables extapic functionality via
> + * KVM capability. In the condition where Qemu sets extapic registers, but KVM doesn't
> + * set extapic capability, Qemu ends up using KVM_GET_LAPIC and KVM_SET_LAPIC.
> + */
> +#define KVM_GET_LAPIC_W_EXTAPIC _IOR(KVMIO, 0x8e, struct kvm_lapic_state_w_extapic)
> +#define KVM_SET_LAPIC_W_EXTAPIC _IOW(KVMIO, 0x8f, struct kvm_lapic_state_w_extapic)
> #define KVM_SET_CPUID2 _IOW(KVMIO, 0x90, struct kvm_cpuid2)
> #define KVM_GET_CPUID2 _IOWR(KVMIO, 0x91, struct kvm_cpuid2)
> /* Available with KVM_CAP_VAPIC */
next prev parent reply other threads:[~2025-07-15 2:22 UTC|newest]
Thread overview: 22+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-06-27 16:25 [PATCH v1 00/11] Implement support for IBS virtualization Manali Shukla
2025-06-27 16:25 ` [PATCH v1 01/11] perf/amd/ibs: Fix race condition in IBS Manali Shukla
2025-06-27 16:25 ` [PATCH v1 02/11] KVM: Add KVM_GET_LAPIC_W_EXTAPIC and KVM_SET_LAPIC_W_EXTAPIC for extapic Manali Shukla
2025-07-15 2:21 ` Mi, Dapeng [this message]
2025-07-16 7:45 ` Manali Shukla
2025-06-27 16:25 ` [PATCH v1 03/11] x86/cpufeatures: Add CPUID feature bit for Extended LVT Manali Shukla
2025-06-27 16:25 ` [PATCH v1 04/11] KVM: x86: Add emulation support for Extented LVT registers Manali Shukla
2025-07-15 2:58 ` Mi, Dapeng
2025-07-16 10:10 ` Manali Shukla
2025-07-17 2:02 ` Mi, Dapeng
2025-08-01 9:33 ` Manali Shukla
2025-08-05 1:10 ` Mi, Dapeng
2025-06-27 16:25 ` [PATCH v1 05/11] x86/cpufeatures: Add CPUID feature bit for VIBS in SVM/SEV guests Manali Shukla
2025-06-27 16:25 ` [PATCH v1 06/11] KVM: x86/cpuid: Add a KVM-only leaf for IBS capabilities Manali Shukla
2025-06-27 16:25 ` [PATCH v1 07/11] KVM: x86: Extend CPUID range to include new leaf Manali Shukla
2025-06-27 16:25 ` [PATCH v1 08/11] KVM: SVM: Extend VMCB area for virtualized IBS registers Manali Shukla
2025-07-15 3:13 ` Mi, Dapeng
2025-07-16 7:40 ` Manali Shukla
2025-06-27 16:25 ` [PATCH v1 09/11] KVM: SVM: Add support for IBS Virtualization Manali Shukla
2025-06-27 16:25 ` [PATCH v1 10/11] perf/x86/amd: Enable VPMU passthrough capability for IBS PMU Manali Shukla
2025-06-27 16:25 ` [PATCH v1 11/11] perf/x86/amd: Remove exclude_guest check from perf_ibs_init() Manali Shukla
2025-07-14 11:51 ` [PATCH v1 00/11] Implement support for IBS virtualization Manali Shukla
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=03934334-a4b6-4c9f-ad99-5f8041836065@linux.intel.com \
--to=dapeng1.mi@linux.intel.com \
--cc=Sandipan.Das@amd.com \
--cc=bp@alien8.de \
--cc=kvm@vger.kernel.org \
--cc=linux-doc@vger.kernel.org \
--cc=linux-perf-users@vger.kernel.org \
--cc=manali.shukla@amd.com \
--cc=mingo@redhat.com \
--cc=mizhang@google.com \
--cc=nikunj@amd.com \
--cc=pbonzini@redhat.com \
--cc=peterz@infradead.org \
--cc=ravi.bangoria@amd.com \
--cc=seanjc@google.com \
--cc=thomas.lendacky@amd.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).