* [PATCH v1 0/9] KVM: x86: Add support for AMD Extended APIC registers
@ 2026-02-04 7:44 Manali Shukla
2026-02-04 7:44 ` [PATCH v1 1/9] KVM: x86: Refactor APIC register mask handling to support extended " Manali Shukla
` (9 more replies)
0 siblings, 10 replies; 15+ messages in thread
From: Manali Shukla @ 2026-02-04 7:44 UTC (permalink / raw)
To: seanjc, pbonzini
Cc: mingo, bp, dave.hansen, kvm, x86, santosh.shukla, nikunj.dadhania,
Naveen.Rao, dapeng1.mi, manali.shukla
Add support for AMD's Extended APIC registers, which reside in a 4KB
APIC page instead of the legacy 1KB APIC register space. Extended LVT
registers (offsets 0x500-0x530) provide additional interrupt vectors
for features like Instruction Based Sampling (IBS).
Introduce KVM_CAP_LAPIC2 to allow userspace to opt into the full 4KB
APIC register space. The capability uses a bitmask to support different
APIC extensions:
KVM_LAPIC2_DEFAULT: 4KB APIC register space (common foundation)
KVM_LAPIC2_AMD_DEFAULT: Extended LVT registers (AMD-specific)
Add KVM_GET/SET_LAPIC2 ioctls that operate on a 4KB APIC register space
accommodate extended registers. Legacy KVM_GET/SET_LAPIC continue to
work for backward compatibility.
Emulate extended APIC registers (APIC_EFEAT, APIC_ECTRL, APIC_EILVTn)
when the guest has X86_FEATURE_EXTAPIC and userspace enables
KVM_CAP_LAPIC2. Current AMD processors support four extended LVT
entries, future processors may support up to 255.
Integrate with AVIC to accelerate extended LVT MSR access when
AVIC_EXTLVT is supported. Reads are accelerated without VM-exits;
writes trigger trap-style VM-exits.
Tested on AMD hardware with Extapic support:
- Extended APIC register read/write emulation and AVIC acceleration
with IBS driver running on the guest
- VM migration with extended APIC state and without extended APIC state
- Backward compatibility check:
Fallback to legacy IOCTLs when KVM_CAP_LAPIC2 capability is not enabled
Equivalent Qemu changes can be found at:
https://github.com/AMDESE/qemu/tree/extlvt_v1
Patches are prepared on kvm-x86/next (003f68c79227).
Manali Shukla (7):
KVM: x86: Refactor APIC register mask handling to support extended
APIC registers
x86/apic: Add helper to get maximum number of Extended LVT registers
KVM: SVM: Set kvm_caps.has_extapic when CPU supports Extended APIC
KVM: x86: Introduce KVM_CAP_LAPIC2 for 4KB APIC register space support
KVM: x86: Refactor APIC state get/set to accept variable-sized buffers
KVM: Add KVM_GET_LAPIC2 and KVM_SET_LAPIC2 for extended APIC
KVM: SVM: Add AVIC support for extended LVT MSRs
Santosh Shukla (2):
KVM: x86: Emulate Extended LVT registers for AMD guests
x86/cpufeatures: Add CPUID feature bit for Extended LVT AVIC
acceleration
Documentation/virt/kvm/api.rst | 75 +++++++++++++
arch/x86/include/asm/apic.h | 1 +
arch/x86/include/asm/apicdef.h | 18 +++
arch/x86/include/asm/cpufeatures.h | 1 +
arch/x86/include/asm/kvm_host.h | 12 ++
arch/x86/include/uapi/asm/kvm.h | 5 +
arch/x86/kernel/apic/apic.c | 17 +++
arch/x86/kvm/cpuid.c | 10 +-
arch/x86/kvm/lapic.c | 169 ++++++++++++++++++++---------
arch/x86/kvm/lapic.h | 14 ++-
arch/x86/kvm/svm/avic.c | 14 +++
arch/x86/kvm/svm/svm.c | 3 +
arch/x86/kvm/vmx/vmx.c | 10 +-
arch/x86/kvm/x86.c | 93 +++++++++++++++-
arch/x86/kvm/x86.h | 2 +
include/uapi/linux/kvm.h | 7 ++
16 files changed, 390 insertions(+), 61 deletions(-)
--
2.43.0
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH v1 1/9] KVM: x86: Refactor APIC register mask handling to support extended APIC registers
2026-02-04 7:44 [PATCH v1 0/9] KVM: x86: Add support for AMD Extended APIC registers Manali Shukla
@ 2026-02-04 7:44 ` Manali Shukla
2026-02-04 7:44 ` [PATCH v1 2/9] x86/apic: Add helper to get maximum number of Extended LVT registers Manali Shukla
` (8 subsequent siblings)
9 siblings, 0 replies; 15+ messages in thread
From: Manali Shukla @ 2026-02-04 7:44 UTC (permalink / raw)
To: seanjc, pbonzini
Cc: mingo, bp, dave.hansen, kvm, x86, santosh.shukla, nikunj.dadhania,
Naveen.Rao, dapeng1.mi, manali.shukla
Expand the APIC register mask infrastructure from a single u64 to
a u64[2] array to accommodate both standard APIC registers (0x0-0x3f0)
and extended APIC registers (0x400-0x530). Current AMD processors
support four extended LVT registers; future processors may support up to
255.
The existing single 64-bit mask can track at most 64 registers (with 16-
byte granularity), which is insufficient for the extended APIC register
space. A 128-bit mask (u64[2]) provides coverage for both standard and
extended register ranges.
Convert the bitmask infrastructure to use kernel bitmap APIs.
APIC_REG_MASK now sets bits in the u64[2] array via bitmap_set(),
APIC_REG_TEST checks register validity via test_bit(), and
kvm_lapic_readable_reg_mask() populates the expanded mask as an output
parameter instead of a return value.
Update all callers, including vmx_update_msr_bitmap_x2apic() in VMX, to
pass and utilize the new two-element mask array. Currently, extended
APIC registers are only supported for AMD processors.
No functional change intended; extended APIC register emulation will be
added in a subsequent patch.
Suggested-by: Naveen N Rao (AMD) <naveen@kernel.org>
Suggested-by: Dapeng Mi <dapeng1.mi@linux.intel.com>
Signed-off-by: Manali Shukla <manali.shukla@amd.com>
---
arch/x86/kvm/lapic.c | 96 ++++++++++++++++++++++++++----------------
arch/x86/kvm/lapic.h | 2 +-
arch/x86/kvm/vmx/vmx.c | 10 +++--
3 files changed, 67 insertions(+), 41 deletions(-)
diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
index 2e513f1c8988..66819397e073 100644
--- a/arch/x86/kvm/lapic.c
+++ b/arch/x86/kvm/lapic.c
@@ -1664,53 +1664,74 @@ static inline struct kvm_lapic *to_lapic(struct kvm_io_device *dev)
return container_of(dev, struct kvm_lapic, dev);
}
-#define APIC_REG_MASK(reg) (1ull << ((reg) >> 4))
-#define APIC_REGS_MASK(first, count) \
- (APIC_REG_MASK(first) * ((1ull << (count)) - 1))
-
-u64 kvm_lapic_readable_reg_mask(struct kvm_lapic *apic)
-{
- /* Leave bits '0' for reserved and write-only registers. */
- u64 valid_reg_mask =
- APIC_REG_MASK(APIC_ID) |
- APIC_REG_MASK(APIC_LVR) |
- APIC_REG_MASK(APIC_TASKPRI) |
- APIC_REG_MASK(APIC_PROCPRI) |
- APIC_REG_MASK(APIC_LDR) |
- APIC_REG_MASK(APIC_SPIV) |
- APIC_REGS_MASK(APIC_ISR, APIC_ISR_NR) |
- APIC_REGS_MASK(APIC_TMR, APIC_ISR_NR) |
- APIC_REGS_MASK(APIC_IRR, APIC_ISR_NR) |
- APIC_REG_MASK(APIC_ESR) |
- APIC_REG_MASK(APIC_ICR) |
- APIC_REG_MASK(APIC_LVTT) |
- APIC_REG_MASK(APIC_LVTTHMR) |
- APIC_REG_MASK(APIC_LVTPC) |
- APIC_REG_MASK(APIC_LVT0) |
- APIC_REG_MASK(APIC_LVT1) |
- APIC_REG_MASK(APIC_LVTERR) |
- APIC_REG_MASK(APIC_TMICT) |
- APIC_REG_MASK(APIC_TMCCT) |
- APIC_REG_MASK(APIC_TDCR);
+/*
+ * Helper macros for APIC register bitmask handling
+ * 2 element array is being used to represent 128-bit mask, where:
+ * - mask[0] tracks standard APIC registers
+ * - mask[1] tracks extended APIC registers
+ */
+
+#define APIC_REG_BITMAP_WORDS 2 /* 2 x 64-bit words = 128 bits */
+#define APIC_REG_BITMAP_BITS (APIC_REG_BITMAP_WORDS * BITS_PER_LONG)
+
+#define APIC_REG_TO_BIT(reg) (((reg) < 0x400) ? ((reg) >> 4) : \
+ (64 + (((reg) - 0x400) >> 4)))
+
+#define APIC_REG_MASK(reg, mask) \
+ bitmap_set((unsigned long *)(mask), APIC_REG_TO_BIT(reg), 1)
+
+#define APIC_REGS_MASK(first, count, mask) \
+ bitmap_set((unsigned long *)(mask), APIC_REG_TO_BIT(first), (count))
+
+#define APIC_REG_TEST(reg, mask) \
+ test_bit(APIC_REG_TO_BIT(reg), (unsigned long *)(mask))
+
+#define APIC_LAST_REG_OFFSET 0x3f0
+
+void kvm_lapic_readable_reg_mask(struct kvm_lapic *apic, u64 mask[2])
+{
+ bitmap_zero((unsigned long *)(mask), APIC_REG_BITMAP_BITS);
+
+ APIC_REG_MASK(APIC_ID, mask);
+ APIC_REG_MASK(APIC_LVR, mask);
+ APIC_REG_MASK(APIC_TASKPRI, mask);
+ APIC_REG_MASK(APIC_PROCPRI, mask);
+ APIC_REG_MASK(APIC_LDR, mask);
+ APIC_REG_MASK(APIC_SPIV, mask);
+ APIC_REGS_MASK(APIC_ISR, APIC_ISR_NR, mask);
+ APIC_REGS_MASK(APIC_TMR, APIC_ISR_NR, mask);
+ APIC_REGS_MASK(APIC_IRR, APIC_ISR_NR, mask);
+ APIC_REG_MASK(APIC_ESR, mask);
+ APIC_REG_MASK(APIC_ICR, mask);
+ APIC_REG_MASK(APIC_LVTT, mask);
+ APIC_REG_MASK(APIC_LVTTHMR, mask);
+ APIC_REG_MASK(APIC_LVTPC, mask);
+ APIC_REG_MASK(APIC_LVT0, mask);
+ APIC_REG_MASK(APIC_LVT1, mask);
+ APIC_REG_MASK(APIC_LVTERR, mask);
+ APIC_REG_MASK(APIC_TMICT, mask);
+ APIC_REG_MASK(APIC_TMCCT, mask);
+ APIC_REG_MASK(APIC_TDCR, mask);
if (kvm_lapic_lvt_supported(apic, LVT_CMCI))
- valid_reg_mask |= APIC_REG_MASK(APIC_LVTCMCI);
+ APIC_REG_MASK(APIC_LVTCMCI, mask);
/* ARBPRI, DFR, and ICR2 are not valid in x2APIC mode. */
- if (!apic_x2apic_mode(apic))
- valid_reg_mask |= APIC_REG_MASK(APIC_ARBPRI) |
- APIC_REG_MASK(APIC_DFR) |
- APIC_REG_MASK(APIC_ICR2);
-
- return valid_reg_mask;
+ if (!apic_x2apic_mode(apic)) {
+ APIC_REG_MASK(APIC_ARBPRI, mask);
+ APIC_REG_MASK(APIC_DFR, mask);
+ APIC_REG_MASK(APIC_ICR2, mask);
+ }
}
EXPORT_SYMBOL_FOR_KVM_INTERNAL(kvm_lapic_readable_reg_mask);
static int kvm_lapic_reg_read(struct kvm_lapic *apic, u32 offset, int len,
void *data)
{
+ unsigned int last_reg = APIC_LAST_REG_OFFSET;
unsigned char alignment = offset & 0xf;
u32 result;
+ u64 mask[2];
/*
* WARN if KVM reads ICR in x2APIC mode, as it's an 8-byte register in
@@ -1721,8 +1742,9 @@ static int kvm_lapic_reg_read(struct kvm_lapic *apic, u32 offset, int len,
if (alignment + len > 4)
return 1;
- if (offset > 0x3f0 ||
- !(kvm_lapic_readable_reg_mask(apic) & APIC_REG_MASK(offset)))
+ kvm_lapic_readable_reg_mask(apic, mask);
+
+ if (offset > last_reg || !APIC_REG_TEST(offset, mask))
return 1;
result = __apic_read(apic, offset & ~0xf);
diff --git a/arch/x86/kvm/lapic.h b/arch/x86/kvm/lapic.h
index adf04a9bd57d..152f17903ff0 100644
--- a/arch/x86/kvm/lapic.h
+++ b/arch/x86/kvm/lapic.h
@@ -156,7 +156,7 @@ int kvm_hv_vapic_msr_read(struct kvm_vcpu *vcpu, u32 msr, u64 *data);
int kvm_lapic_set_pv_eoi(struct kvm_vcpu *vcpu, u64 data, unsigned long len);
void kvm_lapic_exit(void);
-u64 kvm_lapic_readable_reg_mask(struct kvm_lapic *apic);
+void kvm_lapic_readable_reg_mask(struct kvm_lapic *apic, u64 mask[2]);
static inline void kvm_lapic_set_irr(int vec, struct kvm_lapic *apic)
{
diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
index 9e6c78a22b10..35440753e5c6 100644
--- a/arch/x86/kvm/vmx/vmx.c
+++ b/arch/x86/kvm/vmx/vmx.c
@@ -4231,10 +4231,14 @@ static void vmx_update_msr_bitmap_x2apic(struct kvm_vcpu *vcpu)
* through reads for all valid registers by default in x2APIC+APICv
* mode, only the current timer count needs on-demand emulation by KVM.
*/
- if (mode & MSR_BITMAP_MODE_X2APIC_APICV)
- msr_bitmap[read_idx] = ~kvm_lapic_readable_reg_mask(vcpu->arch.apic);
- else
+ if (mode & MSR_BITMAP_MODE_X2APIC_APICV) {
+ u64 mask[2];
+
+ kvm_lapic_readable_reg_mask(vcpu->arch.apic, mask);
+ msr_bitmap[read_idx] = ~mask[0];
+ } else {
msr_bitmap[read_idx] = ~0ull;
+ }
msr_bitmap[write_idx] = ~0ull;
/*
--
2.43.0
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH v1 2/9] x86/apic: Add helper to get maximum number of Extended LVT registers
2026-02-04 7:44 [PATCH v1 0/9] KVM: x86: Add support for AMD Extended APIC registers Manali Shukla
2026-02-04 7:44 ` [PATCH v1 1/9] KVM: x86: Refactor APIC register mask handling to support extended " Manali Shukla
@ 2026-02-04 7:44 ` Manali Shukla
2026-05-06 11:22 ` Borislav Petkov
2026-02-04 7:44 ` [PATCH v1 3/9] KVM: SVM: Set kvm_caps.has_extapic when CPU supports Extended APIC Manali Shukla
` (7 subsequent siblings)
9 siblings, 1 reply; 15+ messages in thread
From: Manali Shukla @ 2026-02-04 7:44 UTC (permalink / raw)
To: seanjc, pbonzini
Cc: mingo, bp, dave.hansen, kvm, x86, santosh.shukla, nikunj.dadhania,
Naveen.Rao, dapeng1.mi, manali.shukla
Add lapic_get_max_extlvt() to retrieve the maximum number of Extended
LVT registers supported by the local APIC on AMD processors. The count
is read from APIC_EFEAT[23:16] (offset 0x400), per AMD APM Volume 2.
Extended LVT registers provide additional interrupt vectors beyond
standard LVT entries, enabling features like Instruction Based Sampling
(IBS). Current AMD processors support four extended LVT entries, but
future processors may support up to 255.
Wrap lapic_get_max_extlvt() with kvm_cpu_get_max_extlvt() for use by
KVM code. Subsequent patches will use this helper to configure the guest's
extended APIC register space.
Signed-off-by: Manali Shukla <manali.shukla@amd.com>
---
arch/x86/include/asm/apic.h | 1 +
arch/x86/include/asm/kvm_host.h | 10 ++++++++++
arch/x86/kernel/apic/apic.c | 17 +++++++++++++++++
3 files changed, 28 insertions(+)
diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h
index a26e66d66444..d45696563a4e 100644
--- a/arch/x86/include/asm/apic.h
+++ b/arch/x86/include/asm/apic.h
@@ -128,6 +128,7 @@ static inline bool apic_is_x2apic_enabled(void)
extern void enable_IR_x2apic(void);
extern int lapic_get_maxlvt(void);
+extern int lapic_get_max_extlvt(void);
extern void clear_local_APIC(void);
extern void disconnect_bsp_APIC(int virt_wire_setup);
extern void disable_local_APIC(void);
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index ecd4019b84b7..df642723cea6 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -2461,6 +2461,16 @@ static inline int kvm_cpu_get_apicid(int mps_cpu)
#endif
}
+static inline int kvm_cpu_get_max_extlvt(void)
+{
+#ifdef CONFIG_X86_LOCAL_APIC
+ return lapic_get_max_extlvt();
+#else
+ WARN_ON_ONCE(1);
+ return 0;
+#endif
+}
+
int memslot_rmap_alloc(struct kvm_memory_slot *slot, unsigned long npages);
#define KVM_CLOCK_VALID_FLAGS \
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c
index d93f87f29d03..90992ae4852a 100644
--- a/arch/x86/kernel/apic/apic.c
+++ b/arch/x86/kernel/apic/apic.c
@@ -253,6 +253,23 @@ int lapic_get_maxlvt(void)
return lapic_is_integrated() ? GET_APIC_MAXLVT(apic_read(APIC_LVR)) : 2;
}
+/**
+ * lapic_get_max_extlvt - Get number of extended LVT entries
+ */
+int lapic_get_max_extlvt(void)
+{
+ u32 reg;
+
+ if (!boot_cpu_has(X86_FEATURE_EXTAPIC))
+ return 0;
+
+ reg = apic_read(APIC_EFEAT);
+
+ /* Extract extended LVT count from bits 16-23 */
+ return (reg >> 16) & 0xff;
+}
+EXPORT_SYMBOL_GPL(lapic_get_max_extlvt);
+
/*
* Local APIC timer
*/
--
2.43.0
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH v1 3/9] KVM: SVM: Set kvm_caps.has_extapic when CPU supports Extended APIC
2026-02-04 7:44 [PATCH v1 0/9] KVM: x86: Add support for AMD Extended APIC registers Manali Shukla
2026-02-04 7:44 ` [PATCH v1 1/9] KVM: x86: Refactor APIC register mask handling to support extended " Manali Shukla
2026-02-04 7:44 ` [PATCH v1 2/9] x86/apic: Add helper to get maximum number of Extended LVT registers Manali Shukla
@ 2026-02-04 7:44 ` Manali Shukla
2026-02-04 7:44 ` [PATCH v1 4/9] KVM: x86: Introduce KVM_CAP_LAPIC2 for 4KB APIC register space support Manali Shukla
` (6 subsequent siblings)
9 siblings, 0 replies; 15+ messages in thread
From: Manali Shukla @ 2026-02-04 7:44 UTC (permalink / raw)
To: seanjc, pbonzini
Cc: mingo, bp, dave.hansen, kvm, x86, santosh.shukla, nikunj.dadhania,
Naveen.Rao, dapeng1.mi, manali.shukla
Set kvm_caps.has_extapic when the CPU has X86_FEATURE_EXTAPIC, allowing
KVM to expose Extended APIC functionality to AMD guests. This is a
prerequisite for advertising AMD's extended APIC space to userspace and
enabling extended LVT emulation.
The has_extapic flag gates access to extended APIC registers (APIC_EFEAT
at 0x400, APIC_ECTRL at 0x410, and APIC_EILVTn at 0x500-0x530) beyond
the standard APIC register space.
Signed-off-by: Manali Shukla <manali.shukla@amd.com>
---
arch/x86/kvm/svm/svm.c | 3 +++
arch/x86/kvm/x86.h | 2 ++
2 files changed, 5 insertions(+)
diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c
index 7803d2781144..6b582fede23d 100644
--- a/arch/x86/kvm/svm/svm.c
+++ b/arch/x86/kvm/svm/svm.c
@@ -5356,6 +5356,9 @@ static __init void svm_set_cpu_caps(void)
if (cpu_feature_enabled(X86_FEATURE_BUS_LOCK_THRESHOLD))
kvm_caps.has_bus_lock_exit = true;
+ if (cpu_feature_enabled(X86_FEATURE_EXTAPIC))
+ kvm_caps.has_extapic = true;
+
/* CPUID 0x80000008 */
if (boot_cpu_has(X86_FEATURE_LS_CFG_SSBD) ||
boot_cpu_has(X86_FEATURE_AMD_SSBD))
diff --git a/arch/x86/kvm/x86.h b/arch/x86/kvm/x86.h
index 70e81f008030..ec70f6579b58 100644
--- a/arch/x86/kvm/x86.h
+++ b/arch/x86/kvm/x86.h
@@ -27,6 +27,8 @@ struct kvm_caps {
bool has_bus_lock_exit;
/* notify VM exit supported? */
bool has_notify_vmexit;
+ /* extapic supported */
+ bool has_extapic;
/* bit mask of VM types */
u32 supported_vm_types;
--
2.43.0
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH v1 4/9] KVM: x86: Introduce KVM_CAP_LAPIC2 for 4KB APIC register space support
2026-02-04 7:44 [PATCH v1 0/9] KVM: x86: Add support for AMD Extended APIC registers Manali Shukla
` (2 preceding siblings ...)
2026-02-04 7:44 ` [PATCH v1 3/9] KVM: SVM: Set kvm_caps.has_extapic when CPU supports Extended APIC Manali Shukla
@ 2026-02-04 7:44 ` Manali Shukla
2026-02-04 7:44 ` [PATCH v1 5/9] KVM: x86: Refactor APIC state get/set to accept variable-sized buffers Manali Shukla
` (5 subsequent siblings)
9 siblings, 0 replies; 15+ messages in thread
From: Manali Shukla @ 2026-02-04 7:44 UTC (permalink / raw)
To: seanjc, pbonzini
Cc: mingo, bp, dave.hansen, kvm, x86, santosh.shukla, nikunj.dadhania,
Naveen.Rao, dapeng1.mi, manali.shukla
Add KVM_CAP_LAPIC2 to allow userspace to opt into extended APIC register
space, i.e. to expose the full 4KB APIC page to the guest. Extended LVT
registers are part of the 4KB APIC page and are AMD-specific. Extended
APIC registers provide additional interrupt vectors for hardware features
like Instruction Based Sampling (IBS).
Use a capability negotiation model to allow for future extensibility.
KVM_CHECK_EXTENSION returns a bitmask of supported capabilities, and
userspace enables the intersection of KVM and VMM support via
KVM_ENABLE_CAP. This allows KVM and userspace to independently add
support for new APIC configurations without breaking compatibility.
Define two capability flags:
- KVM_LAPIC2_DEFAULT: full 4KB APIC page support
- KVM_LAPIC2_AMD_DEFAULT: extended LVT registers are supported
Require that the capability be enabled before vCPUs are created to avoid
the need to handle runtime changes to the APIC page size.
When KVM_LAPIC2_AMD_DEFAULT is enabled, set kvm->arch.nr_extlvt to
KVM_X86_NR_EXTLVT_DEFAULT (4) to track the number of extended LVT
registers available to the guest. Future patches will use nr_extlvt to
emulate guest accesses to extended LVT registers at APIC offset 0x500.
Suggested-by: Naveen N Rao (AMD) <naveen@kernel.org>
Signed-off-by: Manali Shukla <manali.shukla@amd.com>
---
Documentation/virt/kvm/api.rst | 31 +++++++++++++++++++++++++++++++
arch/x86/include/asm/kvm_host.h | 1 +
arch/x86/kvm/x86.c | 30 ++++++++++++++++++++++++++++++
include/uapi/linux/kvm.h | 5 +++++
4 files changed, 67 insertions(+)
diff --git a/Documentation/virt/kvm/api.rst b/Documentation/virt/kvm/api.rst
index 01a3abef8abb..71b4d24f009a 100644
--- a/Documentation/virt/kvm/api.rst
+++ b/Documentation/virt/kvm/api.rst
@@ -9291,6 +9291,37 @@ KVM exits with the register state of either the L1 or L2 guest
depending on which executed at the time of an exit. Userspace must
take care to differentiate between these cases.
+8.46 KVM_CAP_LAPIC2
+---------------------------
+
+:Architectures: x86
+:Target: VM
+:Parameters: args[0] is a bitmask of LAPIC2 capabilities
+:Returns: 0 on success, -EINVAL when arg[0] contains invalid bits
+
+This capability indicates that KVM supports extended APIC register space of the
+whole 4KB page.
+
+Calling KVM_CHECK_EXTENSION for this capability returns a bitmask of LAPIC2
+capabilities that can be enabled on a VM.
+
+The argument to KVM_ENABLE_CAP is also a bitmask that selects which LAPIC2
+capabilities to enable for the VM. Userspace should enable the intersection
+of capabilities supported by KVM (from KVM_CHECK_EXTENSION) and capabilities
+supported by the VMM. This must be called before creating any VCPUs.
+
+At this time, KVM_LAPIC2_DEFAULT and KVM_LAPIC2_AMD_DEFAULT are the supported
+capabilities:
+
+ - KVM_LAPIC2_DEFAULT: Full 4KB APIC page support
+ - KVM_LAPIC2_AMD_DEFAULT: Extended LVT registers are supported (they are part
+ of 4KB APIC page)
+
+KVM_LAPIC2_AMD_DEFAULT is available on AMD processors with ExtApicSpace feature
+(CPUID 8000_0001h.ECX[3]). Extended APIC registers start at APIC offset 400h.
+Currently 4 extended LVT registers are supported, used for features like
+Instruction Based Sampling (IBS), but future processors may support more.
+
9. Known KVM API problems
=========================
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index df642723cea6..5a659982aebd 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -1460,6 +1460,7 @@ struct kvm_arch {
u32 default_tsc_khz;
bool user_set_tsc;
u64 apic_bus_cycle_ns;
+ u8 nr_extlvt;
seqcount_raw_spinlock_t pvclock_sc;
bool use_master_clock;
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 8acfdfc583a1..368ee9276366 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -4990,6 +4990,18 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
case KVM_CAP_READONLY_MEM:
r = kvm ? kvm_arch_has_readonly_mem(kvm) : 1;
break;
+ case KVM_CAP_LAPIC2: {
+ u8 max_extlvt;
+
+ r = KVM_LAPIC2_DEFAULT;
+ if (!kvm_caps.has_extapic)
+ break;
+
+ max_extlvt = kvm_cpu_get_max_extlvt();
+ if (max_extlvt == KVM_X86_NR_EXTLVT_DEFAULT)
+ r |= KVM_LAPIC2_AMD_DEFAULT;
+ break;
+ }
default:
break;
}
@@ -6966,6 +6978,24 @@ int kvm_vm_ioctl_enable_cap(struct kvm *kvm,
mutex_unlock(&kvm->lock);
break;
}
+ case KVM_CAP_LAPIC2: {
+ r = -EINVAL;
+
+ mutex_lock(&kvm->lock);
+
+ kvm->arch.nr_extlvt = 0;
+
+ if (!kvm->created_vcpus) {
+ if (cap->args[0] & KVM_LAPIC2_DEFAULT) {
+ r = 0;
+ if (cap->args[0] & KVM_LAPIC2_AMD_DEFAULT)
+ kvm->arch.nr_extlvt = KVM_X86_NR_EXTLVT_DEFAULT;
+ }
+ }
+
+ mutex_unlock(&kvm->lock);
+ break;
+ }
default:
r = -EINVAL;
break;
diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
index 76bd54848b11..cb27eeb09bdb 100644
--- a/include/uapi/linux/kvm.h
+++ b/include/uapi/linux/kvm.h
@@ -659,6 +659,10 @@ struct kvm_ioeventfd {
#define KVM_X86_DISABLE_EXITS_CSTATE (1 << 3)
#define KVM_X86_DISABLE_EXITS_APERFMPERF (1 << 4)
+#define KVM_X86_NR_EXTLVT_DEFAULT 4
+#define KVM_LAPIC2_DEFAULT (1 << 0)
+#define KVM_LAPIC2_AMD_DEFAULT (1 << 1)
+
/* for KVM_ENABLE_CAP */
struct kvm_enable_cap {
/* in */
@@ -978,6 +982,7 @@ struct kvm_enable_cap {
#define KVM_CAP_GUEST_MEMFD_FLAGS 244
#define KVM_CAP_ARM_SEA_TO_USER 245
#define KVM_CAP_S390_USER_OPEREXEC 246
+#define KVM_CAP_LAPIC2 247
struct kvm_irq_routing_irqchip {
__u32 irqchip;
--
2.43.0
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH v1 5/9] KVM: x86: Refactor APIC state get/set to accept variable-sized buffers
2026-02-04 7:44 [PATCH v1 0/9] KVM: x86: Add support for AMD Extended APIC registers Manali Shukla
` (3 preceding siblings ...)
2026-02-04 7:44 ` [PATCH v1 4/9] KVM: x86: Introduce KVM_CAP_LAPIC2 for 4KB APIC register space support Manali Shukla
@ 2026-02-04 7:44 ` Manali Shukla
2026-02-04 7:44 ` [PATCH v1 6/9] KVM: Add KVM_GET_LAPIC2 and KVM_SET_LAPIC2 for extended APIC Manali Shukla
` (4 subsequent siblings)
9 siblings, 0 replies; 15+ messages in thread
From: Manali Shukla @ 2026-02-04 7:44 UTC (permalink / raw)
To: seanjc, pbonzini
Cc: mingo, bp, dave.hansen, kvm, x86, santosh.shukla, nikunj.dadhania,
Naveen.Rao, dapeng1.mi, manali.shukla
Refactor kvm_apic_get_state() and kvm_apic_set_state() to accept a void
pointer and explicit size parameter instead of struct kvm_lapic_state.
This removes the hard-coded assumption about 1KB APIC register space and
allows functions to work with both 1KB and 4KB APIC register space.
Existing callers of kvm_apic_get_state() and kvm_apic_set_state() pass
`s->regs` and `sizeof(*s)` to maintain the current behavior with the 1KB
kvm_lapic_state structure. Subsequent patches will add KVM_GET_LAPIC2
and KVM_SET_LAPIC2 IOCTLs that will also use these functions in order to
save/restore 4KB APIC register space.
No functional change intended; existing KVM_GET_LAPIC and KVM_SET_LAPIC
IOCTLs work exactly as before.
Signed-off-by: Manali Shukla <manali.shukla@amd.com>
---
arch/x86/kvm/lapic.c | 32 ++++++++++++++++----------------
arch/x86/kvm/lapic.h | 4 ++--
arch/x86/kvm/x86.c | 4 ++--
3 files changed, 20 insertions(+), 20 deletions(-)
diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
index 66819397e073..4ed6abb414e4 100644
--- a/arch/x86/kvm/lapic.c
+++ b/arch/x86/kvm/lapic.c
@@ -3151,12 +3151,12 @@ void kvm_apic_ack_interrupt(struct kvm_vcpu *vcpu, int vector)
EXPORT_SYMBOL_FOR_KVM_INTERNAL(kvm_apic_ack_interrupt);
static int kvm_apic_state_fixup(struct kvm_vcpu *vcpu,
- struct kvm_lapic_state *s, bool set)
+ void *regs, bool set)
{
if (apic_x2apic_mode(vcpu->arch.apic)) {
u32 x2apic_id = kvm_x2apic_id(vcpu->arch.apic);
- u32 *id = (u32 *)(s->regs + APIC_ID);
- u32 *ldr = (u32 *)(s->regs + APIC_LDR);
+ u32 *id = (u32 *)(regs + APIC_ID);
+ u32 *ldr = (u32 *)(regs + APIC_LDR);
u64 icr;
if (vcpu->kvm->arch.x2apic_format) {
@@ -3189,12 +3189,12 @@ static int kvm_apic_state_fixup(struct kvm_vcpu *vcpu,
if (!kvm_x86_ops.x2apic_icr_is_split) {
if (set) {
- icr = apic_get_reg(s->regs, APIC_ICR) |
- (u64)apic_get_reg(s->regs, APIC_ICR2) << 32;
- apic_set_reg64(s->regs, APIC_ICR, icr);
+ icr = apic_get_reg(regs, APIC_ICR) |
+ (u64)apic_get_reg(regs, APIC_ICR2) << 32;
+ apic_set_reg64(regs, APIC_ICR, icr);
} else {
- icr = apic_get_reg64(s->regs, APIC_ICR);
- apic_set_reg(s->regs, APIC_ICR2, icr >> 32);
+ icr = apic_get_reg64(regs, APIC_ICR);
+ apic_set_reg(regs, APIC_ICR2, icr >> 32);
}
}
}
@@ -3202,20 +3202,20 @@ 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, void *regs, unsigned int size)
{
- memcpy(s->regs, vcpu->arch.apic->regs, sizeof(*s));
+ memcpy(regs, vcpu->arch.apic->regs, size);
/*
* Get calculated timer current count for remaining timer period (if
* any) and store it in the returned register set.
*/
- apic_set_reg(s->regs, APIC_TMCCT, __apic_read(vcpu->arch.apic, APIC_TMCCT));
+ apic_set_reg(regs, APIC_TMCCT, __apic_read(vcpu->arch.apic, APIC_TMCCT));
- return kvm_apic_state_fixup(vcpu, s, false);
+ return kvm_apic_state_fixup(vcpu, regs, false);
}
-int kvm_apic_set_state(struct kvm_vcpu *vcpu, struct kvm_lapic_state *s)
+int kvm_apic_set_state(struct kvm_vcpu *vcpu, void *regs, unsigned int size)
{
struct kvm_lapic *apic = vcpu->arch.apic;
int r;
@@ -3223,14 +3223,14 @@ int kvm_apic_set_state(struct kvm_vcpu *vcpu, struct kvm_lapic_state *s)
kvm_x86_call(apicv_pre_state_restore)(vcpu);
/* set SPIV separately to get count of SW disabled APICs right */
- apic_set_spiv(apic, *((u32 *)(s->regs + APIC_SPIV)));
+ apic_set_spiv(apic, *((u32 *)(regs + APIC_SPIV)));
- r = kvm_apic_state_fixup(vcpu, s, true);
+ r = kvm_apic_state_fixup(vcpu, regs, true);
if (r) {
kvm_recalculate_apic_map(vcpu->kvm);
return r;
}
- memcpy(vcpu->arch.apic->regs, s->regs, sizeof(*s));
+ memcpy(vcpu->arch.apic->regs, 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 152f17903ff0..c6ac40c76f62 100644
--- a/arch/x86/kvm/lapic.h
+++ b/arch/x86/kvm/lapic.h
@@ -132,8 +132,8 @@ static inline int kvm_irq_delivery_to_apic(struct kvm *kvm,
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);
+int kvm_apic_get_state(struct kvm_vcpu *vcpu, void *regs, unsigned int size);
+int kvm_apic_set_state(struct kvm_vcpu *vcpu, void *regs, 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 368ee9276366..669c894f1061 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -5328,7 +5328,7 @@ static int kvm_vcpu_ioctl_get_lapic(struct kvm_vcpu *vcpu,
kvm_x86_call(sync_pir_to_irr)(vcpu);
- return kvm_apic_get_state(vcpu, s);
+ return kvm_apic_get_state(vcpu, s->regs, sizeof(*s));
}
static int kvm_vcpu_ioctl_set_lapic(struct kvm_vcpu *vcpu,
@@ -5339,7 +5339,7 @@ static int kvm_vcpu_ioctl_set_lapic(struct kvm_vcpu *vcpu,
if (vcpu->arch.apic->guest_apic_protected)
return -EINVAL;
- r = kvm_apic_set_state(vcpu, s);
+ r = kvm_apic_set_state(vcpu, s->regs, sizeof(*s));
if (r)
return r;
update_cr8_intercept(vcpu);
--
2.43.0
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH v1 6/9] KVM: Add KVM_GET_LAPIC2 and KVM_SET_LAPIC2 for extended APIC
2026-02-04 7:44 [PATCH v1 0/9] KVM: x86: Add support for AMD Extended APIC registers Manali Shukla
` (4 preceding siblings ...)
2026-02-04 7:44 ` [PATCH v1 5/9] KVM: x86: Refactor APIC state get/set to accept variable-sized buffers Manali Shukla
@ 2026-02-04 7:44 ` Manali Shukla
2026-03-16 13:00 ` Nikunj A. Dadhania
2026-02-04 7:44 ` [PATCH v1 7/9] KVM: x86: Emulate Extended LVT registers for AMD guests Manali Shukla
` (3 subsequent siblings)
9 siblings, 1 reply; 15+ messages in thread
From: Manali Shukla @ 2026-02-04 7:44 UTC (permalink / raw)
To: seanjc, pbonzini
Cc: mingo, bp, dave.hansen, kvm, x86, santosh.shukla, nikunj.dadhania,
Naveen.Rao, dapeng1.mi, manali.shukla
Add KVM_GET_LAPIC2 and KVM_SET_LAPIC2 ioctls to save and restore APIC
state using a 4KB buffer (kvm_lapic_state2). The larger buffer allows
saving additional APIC registers beyond the standard APIC registers
supported by the existing 1KB KVM_GET/SET_LAPIC ioctls.
The 4KB buffer size matches the LAPIC2 capability, which enables the
full APIC register page including extended APIC registers for AMD
processors.
KVM_GET/SET_LAPIC continue to work as before for backward compatibility.
Document the new ioctls in Documentation/virt/kvm/api.rst.
Suggested-by: Sean Christopherson <seanjc@google.com>
Signed-off-by: Manali Shukla <manali.shukla@amd.com>
---
Documentation/virt/kvm/api.rst | 45 +++++++++++++++++++++++++
arch/x86/include/uapi/asm/kvm.h | 5 +++
arch/x86/kvm/x86.c | 59 +++++++++++++++++++++++++++++++++
include/uapi/linux/kvm.h | 2 ++
4 files changed, 111 insertions(+)
diff --git a/Documentation/virt/kvm/api.rst b/Documentation/virt/kvm/api.rst
index 71b4d24f009a..c49cf3104b2c 100644
--- a/Documentation/virt/kvm/api.rst
+++ b/Documentation/virt/kvm/api.rst
@@ -6517,6 +6517,51 @@ the capability to be present.
`flags` must currently be zero.
+4.144 KVM_GET_LAPIC2
+----------------------
+
+:Capability: KVM_CAP_LAPIC2
+:Architectures: x86
+:Type: vcpu ioctl
+:Parameters: struct kvm_lapic_state2 (out)
+:Returns: 0 on success, negative on failure
+
+Reads the extended Local APIC registers, including both the standard APIC
+register space (offsets 0h-3FFh) and the extended APIC register space (offsets
+400h-500h and beyond).
+
+This ioctl is similar to KVM_GET_LAPIC but operates on a 4KB APIC
+register space that includes extended LVT registers available on AMD processors
+with the ExtApicSpace feature.
+
+::
+
+ #define KVM_APIC_EXT_REG_SIZE 0x1000
+ struct kvm_lapic_state2 {
+ char regs[KVM_APIC_EXT_REG_SIZE];
+ };
+
+4.145 KVM_SET_LAPIC2
+----------------------
+
+:Capability: KVM_CAP_LAPIC2
+:Architectures: x86
+:Type: vcpu ioctl
+:Parameters: struct kvm_lapic_state2 (in)
+:Returns: 0 on success, negative on failure
+
+Sets the extended Local APIC registers, including both the standard APIC
+register space and the extended APIC register space.
+
+This ioctl is similar to KVM_SET_LAPIC but operates on a 4KB APIC register space
+that includes extended LVT registers for AMD processors.
+
+::
+
+ #define KVM_APIC_EXT_REG_SIZE 0x1000
+ struct kvm_lapic_stat2 {
+ char regs[KVM_APIC_EXT_REG_SIZE];
+ };
.. _kvm_run:
diff --git a/arch/x86/include/uapi/asm/kvm.h b/arch/x86/include/uapi/asm/kvm.h
index 7ceff6583652..516d4a0be25a 100644
--- a/arch/x86/include/uapi/asm/kvm.h
+++ b/arch/x86/include/uapi/asm/kvm.h
@@ -129,6 +129,11 @@ struct kvm_lapic_state {
char regs[KVM_APIC_REG_SIZE];
};
+#define KVM_APIC_EXT_REG_SIZE 0x1000
+struct kvm_lapic_state2 {
+ char regs[KVM_APIC_EXT_REG_SIZE];
+};
+
struct kvm_segment {
__u64 base;
__u32 limit;
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 669c894f1061..ccd16bdff56a 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -5331,6 +5331,17 @@ static int kvm_vcpu_ioctl_get_lapic(struct kvm_vcpu *vcpu,
return kvm_apic_get_state(vcpu, s->regs, sizeof(*s));
}
+static int kvm_vcpu_ioctl_get_lapic2(struct kvm_vcpu *vcpu,
+ struct kvm_lapic_state2 *s)
+{
+ if (vcpu->arch.apic->guest_apic_protected)
+ return -EINVAL;
+
+ kvm_x86_call(sync_pir_to_irr)(vcpu);
+
+ return kvm_apic_get_state(vcpu, s->regs, sizeof(*s));
+}
+
static int kvm_vcpu_ioctl_set_lapic(struct kvm_vcpu *vcpu,
struct kvm_lapic_state *s)
{
@@ -5347,6 +5358,22 @@ static int kvm_vcpu_ioctl_set_lapic(struct kvm_vcpu *vcpu,
return 0;
}
+static int kvm_vcpu_ioctl_set_lapic2(struct kvm_vcpu *vcpu,
+ struct kvm_lapic_state2 *s)
+{
+ int r;
+
+ if (vcpu->arch.apic->guest_apic_protected)
+ return -EINVAL;
+
+ r = kvm_apic_set_state(vcpu, s->regs, sizeof(*s));
+ if (r)
+ return r;
+ update_cr8_intercept(vcpu);
+
+ return 0;
+}
+
static int kvm_cpu_accept_dm_intr(struct kvm_vcpu *vcpu)
{
/*
@@ -6203,6 +6230,7 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
union {
struct kvm_sregs2 *sregs2;
struct kvm_lapic_state *lapic;
+ struct kvm_lapic_state2 *lapic2;
struct kvm_xsave *xsave;
struct kvm_xcrs *xcrs;
void *buffer;
@@ -6243,6 +6271,37 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
r = kvm_vcpu_ioctl_set_lapic(vcpu, u.lapic);
break;
}
+ case KVM_GET_LAPIC2: {
+ r = -EINVAL;
+ if (!lapic_in_kernel(vcpu))
+ goto out;
+ u.lapic2 = kzalloc(sizeof(struct kvm_lapic_state2), GFP_KERNEL);
+
+ r = -ENOMEM;
+ if (!u.lapic2)
+ goto out;
+ r = kvm_vcpu_ioctl_get_lapic2(vcpu, u.lapic2);
+ if (r)
+ goto out;
+ r = -EFAULT;
+ if (copy_to_user(argp, u.lapic2, sizeof(struct kvm_lapic_state2)))
+ goto out;
+ r = 0;
+ break;
+ }
+ case KVM_SET_LAPIC2: {
+ r = -EINVAL;
+ if (!lapic_in_kernel(vcpu))
+ goto out;
+ u.lapic2 = memdup_user(argp, sizeof(*u.lapic2));
+ if (IS_ERR(u.lapic2)) {
+ r = PTR_ERR(u.lapic2);
+ goto out_nofree;
+ }
+
+ r = kvm_vcpu_ioctl_set_lapic2(vcpu, u.lapic2);
+ break;
+ }
case KVM_INTERRUPT: {
struct kvm_interrupt irq;
diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
index cb27eeb09bdb..f45d313e30ae 100644
--- a/include/uapi/linux/kvm.h
+++ b/include/uapi/linux/kvm.h
@@ -1339,6 +1339,8 @@ 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)
+#define KVM_GET_LAPIC2 _IOR(KVMIO, 0x8e, struct kvm_lapic_state2)
+#define KVM_SET_LAPIC2 _IOW(KVMIO, 0x8f, struct kvm_lapic_state2)
#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 */
--
2.43.0
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH v1 7/9] KVM: x86: Emulate Extended LVT registers for AMD guests
2026-02-04 7:44 [PATCH v1 0/9] KVM: x86: Add support for AMD Extended APIC registers Manali Shukla
` (5 preceding siblings ...)
2026-02-04 7:44 ` [PATCH v1 6/9] KVM: Add KVM_GET_LAPIC2 and KVM_SET_LAPIC2 for extended APIC Manali Shukla
@ 2026-02-04 7:44 ` Manali Shukla
2026-02-04 7:44 ` [PATCH v1 8/9] x86/cpufeatures: Add CPUID feature bit for Extended LVT AVIC acceleration Manali Shukla
` (2 subsequent siblings)
9 siblings, 0 replies; 15+ messages in thread
From: Manali Shukla @ 2026-02-04 7:44 UTC (permalink / raw)
To: seanjc, pbonzini
Cc: mingo, bp, dave.hansen, kvm, x86, santosh.shukla, nikunj.dadhania,
Naveen.Rao, dapeng1.mi, manali.shukla
From: Santosh Shukla <santosh.shukla@amd.com>
Emulate reads and writes to AMD Extended APIC registers: APIC_EFEAT
(0x400), APIC_ECTRL (0x410), and APIC_EILVTn (0x500-0x530). Without
emulation, Instruction Based Sampling (IBS) driver fails to initialize
when it tries to access APIC_EILVT(0).
Extend the LAPIC register read and write paths to allow accesses beyond
the standard 0x3f0 offset when the guest has X86_FEATURE_EXTAPIC. The
valid range is determined by kvm->arch.nr_extlvt, which userspace
configures via KVM_CAP_LAPIC2.
Initialize extended APIC registers in both kvm_vcpu_after_set_cpuid()
and kvm_lapic_reset(). The initial kvm_lapic_reset() occurs before
userspace configures CPUID via KVM_SET_CPUID2, so extended LVT registers
can't be initialized until X86_FEATURE_EXTAPIC is set. Handle the
initial setup in kvm_vcpu_after_set_cpuid() and subsequent resets in
kvm_lapic_reset().
Initialize APIC_EFEAT to report the number of extended LVTs (read-only).
Initialize APIC_ECTRL to zero (read-write). Initialize APIC_EILVTn
entries to masked (bit 16 set), matching hardware reset behavior.
Please refer to Section 16.4.5 in AMD Programmer's Manual Volume 2 at
https://bugzilla.kernel.org/attachment.cgi?id=306250 for more details
on Extended LVT.
Signed-off-by: Santosh Shukla <santosh.shukla@amd.com>
Co-developed-by: Manali Shukla <manali.shukla@amd.com>
Signed-off-by: Manali Shukla <manali.shukla@amd.com>
---
arch/x86/include/asm/apicdef.h | 18 ++++++++++++++
arch/x86/kvm/cpuid.c | 10 +++++++-
arch/x86/kvm/lapic.c | 43 ++++++++++++++++++++++++++++++++++
arch/x86/kvm/lapic.h | 8 +++++++
4 files changed, 78 insertions(+), 1 deletion(-)
diff --git a/arch/x86/include/asm/apicdef.h b/arch/x86/include/asm/apicdef.h
index be39a543fbe5..5c5e9db1e27d 100644
--- a/arch/x86/include/asm/apicdef.h
+++ b/arch/x86/include/asm/apicdef.h
@@ -148,6 +148,24 @@
#define APIC_EILVT_MSG_EXT 0x7
#define APIC_EILVT_MASKED (1 << 16)
+/*
+ * Initialize extended APIC registers to the default value when guest
+ * is started and EXTAPIC feature is enabled on the guest.
+ *
+ * APIC_EFEAT is a read only Extended APIC feature register, whose bits
+ * 0, 1, and 2 represent features that are not currently emulated by KVM.
+ * Therefore, these bits must be cleared during initialization. As a result, the
+ * default value used for APIC_EFEAT in KVM is set based on number of extended
+ * LVT registers supported by the guest.
+ *
+ * APIC_ECTRL is a read-write Extended APIC control register, whose
+ * default value is 0x0.
+ */
+
+#define APIC_EFEAT_MASK 0x00FF0000
+#define APIC_EFEAT_DEFAULT(n) ((n << 16) & APIC_EFEAT_MASK)
+#define APIC_ECTRL_DEFAULT 0x0
+
#define APIC_BASE (fix_to_virt(FIX_APIC_BASE))
#define APIC_BASE_MSR 0x800
#define APIC_X2APIC_ID_MSR 0x802
diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c
index baa1cf473d45..4574149d137b 100644
--- a/arch/x86/kvm/cpuid.c
+++ b/arch/x86/kvm/cpuid.c
@@ -435,6 +435,14 @@ void kvm_vcpu_after_set_cpuid(struct kvm_vcpu *vcpu)
kvm_apic_set_version(vcpu);
}
+ /*
+ * Initialize extended APIC registers after CPUID is set. The initial
+ * reset occurs before userspace configures CPUID, so extended LVT
+ * registers (which require X86_FEATURE_EXTAPIC) can't be initialized
+ * until after KVM_SET_CPUID2.
+ */
+ kvm_apic_init_extlvt_regs(vcpu);
+
vcpu->arch.guest_supported_xcr0 = cpuid_get_supported_xcr0(vcpu);
vcpu->arch.guest_supported_xss = cpuid_get_supported_xss(vcpu);
@@ -1076,7 +1084,7 @@ void kvm_set_cpu_caps(void)
F(LAHF_LM),
F(CMP_LEGACY),
VENDOR_F(SVM),
- /* ExtApicSpace */
+ F(EXTAPIC),
F(CR8_LEGACY),
F(ABM),
F(SSE4A),
diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
index 4ed6abb414e4..a04c808289c3 100644
--- a/arch/x86/kvm/lapic.c
+++ b/arch/x86/kvm/lapic.c
@@ -1687,6 +1687,7 @@ static inline struct kvm_lapic *to_lapic(struct kvm_io_device *dev)
test_bit(APIC_REG_TO_BIT(reg), (unsigned long *)(mask))
#define APIC_LAST_REG_OFFSET 0x3f0
+#define APIC_EXT_LAST_REG_OFFSET(n) APIC_EILVTn((n))
void kvm_lapic_readable_reg_mask(struct kvm_lapic *apic, u64 mask[2])
{
@@ -1722,6 +1723,12 @@ void kvm_lapic_readable_reg_mask(struct kvm_lapic *apic, u64 mask[2])
APIC_REG_MASK(APIC_DFR, mask);
APIC_REG_MASK(APIC_ICR2, mask);
}
+
+ if (guest_cpu_cap_has(apic->vcpu, X86_FEATURE_EXTAPIC)) {
+ APIC_REG_MASK(APIC_EFEAT, mask);
+ APIC_REG_MASK(APIC_ECTRL, mask);
+ APIC_REGS_MASK(APIC_EILVTn(0), apic->vcpu->kvm->arch.nr_extlvt, mask);
+ }
}
EXPORT_SYMBOL_FOR_KVM_INTERNAL(kvm_lapic_readable_reg_mask);
@@ -1739,6 +1746,13 @@ static int kvm_lapic_reg_read(struct kvm_lapic *apic, u32 offset, int len,
*/
WARN_ON_ONCE(apic_x2apic_mode(apic) && offset == APIC_ICR);
+ if (guest_cpu_cap_has(apic->vcpu, X86_FEATURE_EXTAPIC)) {
+ u8 nr_extlvt = apic->vcpu->kvm->arch.nr_extlvt;
+
+ if (nr_extlvt > 0)
+ last_reg = APIC_EXT_LAST_REG_OFFSET(nr_extlvt - 1);
+ }
+
if (alignment + len > 4)
return 1;
@@ -2500,7 +2514,15 @@ static int kvm_lapic_reg_write(struct kvm_lapic *apic, u32 reg, u32 val)
else
kvm_apic_send_ipi(apic, APIC_DEST_SELF | val, 0);
break;
+
default:
+ if (guest_cpu_cap_has(apic->vcpu, X86_FEATURE_EXTAPIC)) {
+ if (reg == APIC_ECTRL ||
+ kvm_is_extlvt_offset(reg, apic->vcpu->kvm->arch.nr_extlvt)) {
+ kvm_lapic_set_reg(apic, reg, val);
+ break;
+ }
+ }
ret = 1;
break;
}
@@ -2866,6 +2888,26 @@ void kvm_inhibit_apic_access_page(struct kvm_vcpu *vcpu)
kvm_vcpu_srcu_read_lock(vcpu);
}
+/*
+ * Initialize extended APIC registers to the default value when guest is
+ * started. The extended APIC registers should only be initialized when the
+ * EXTAPIC feature is enabled on the guest.
+ */
+void kvm_apic_init_extlvt_regs(struct kvm_vcpu *vcpu)
+{
+ struct kvm_lapic *apic = vcpu->arch.apic;
+ int i, max_extlvt;
+
+ max_extlvt = vcpu->kvm->arch.nr_extlvt;
+
+ if (guest_cpu_cap_has(vcpu, X86_FEATURE_EXTAPIC)) {
+ kvm_lapic_set_reg(apic, APIC_EFEAT, APIC_EFEAT_DEFAULT(max_extlvt));
+ kvm_lapic_set_reg(apic, APIC_ECTRL, APIC_ECTRL_DEFAULT);
+ for (i = 0; i < max_extlvt; i++)
+ kvm_lapic_set_reg(apic, APIC_EILVTn(i), APIC_EILVT_MASKED);
+ }
+}
+
void kvm_lapic_reset(struct kvm_vcpu *vcpu, bool init_event)
{
struct kvm_lapic *apic = vcpu->arch.apic;
@@ -2927,6 +2969,7 @@ void kvm_lapic_reset(struct kvm_vcpu *vcpu, bool init_event)
kvm_lapic_set_reg(apic, APIC_ISR + 0x10 * i, 0);
kvm_lapic_set_reg(apic, APIC_TMR + 0x10 * i, 0);
}
+ kvm_apic_init_extlvt_regs(vcpu);
kvm_apic_update_apicv(vcpu);
update_divide_count(apic);
atomic_set(&apic->lapic_timer.pending, 0);
diff --git a/arch/x86/kvm/lapic.h b/arch/x86/kvm/lapic.h
index c6ac40c76f62..6716828b65e5 100644
--- a/arch/x86/kvm/lapic.h
+++ b/arch/x86/kvm/lapic.h
@@ -98,6 +98,7 @@ void kvm_apic_ack_interrupt(struct kvm_vcpu *vcpu, int vector);
int kvm_apic_accept_pic_intr(struct kvm_vcpu *vcpu);
int kvm_apic_accept_events(struct kvm_vcpu *vcpu);
void kvm_lapic_reset(struct kvm_vcpu *vcpu, bool init_event);
+void kvm_apic_init_extlvt_regs(struct kvm_vcpu *vcpu);
u64 kvm_lapic_get_cr8(struct kvm_vcpu *vcpu);
void kvm_lapic_set_tpr(struct kvm_vcpu *vcpu, unsigned long cr8);
void kvm_lapic_set_eoi(struct kvm_vcpu *vcpu);
@@ -266,4 +267,11 @@ static inline u8 kvm_xapic_id(struct kvm_lapic *apic)
return kvm_lapic_get_reg(apic, APIC_ID) >> 24;
}
+static inline bool kvm_is_extlvt_offset(u32 offset, u8 nr_extlvt)
+{
+ if ((offset < APIC_EILVTn(0)) || (offset & 0xf))
+ return false;
+ return ((offset - APIC_EILVTn(0)) >> 4) < nr_extlvt;
+}
+
#endif
--
2.43.0
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH v1 8/9] x86/cpufeatures: Add CPUID feature bit for Extended LVT AVIC acceleration
2026-02-04 7:44 [PATCH v1 0/9] KVM: x86: Add support for AMD Extended APIC registers Manali Shukla
` (6 preceding siblings ...)
2026-02-04 7:44 ` [PATCH v1 7/9] KVM: x86: Emulate Extended LVT registers for AMD guests Manali Shukla
@ 2026-02-04 7:44 ` Manali Shukla
2026-02-04 7:44 ` [PATCH v1 9/9] KVM: SVM: Add AVIC support for extended LVT MSRs Manali Shukla
2026-03-10 6:17 ` [PATCH v1 0/9] KVM: x86: Add support for AMD Extended APIC registers Manali Shukla
9 siblings, 0 replies; 15+ messages in thread
From: Manali Shukla @ 2026-02-04 7:44 UTC (permalink / raw)
To: seanjc, pbonzini
Cc: mingo, bp, dave.hansen, kvm, x86, santosh.shukla, nikunj.dadhania,
Naveen.Rao, dapeng1.mi, manali.shukla
From: Santosh Shukla <santosh.shukla@amd.com>
Local interrupts can be extended to include more LVT registers in order
to allow additional interrupt sources, like Instruction Based Sampling
(IBS).
The Extended APIC feature register indicates the number of extended
Local Vector Table (LVT) registers in the local APIC. Currently, there
are 4 extended LVT registers available which are located at APIC offsets
(500h-530h). Future AMD processors may expose up to 255 extended LVT
registers.
The AVIC_EXTLVT (Extended LVT AVIC acceleration support) feature bit
changes the behavior associated with reading and writing an extended LVT
register when AVIC is enabled. When the AVIC_EXTLVT and AVIC are
enabled, a write to an extended LVT register changes from a fault
style #VMEXIT to a trap style #VMEXIT and a read of an extended LVT
register no longer triggers a #VMEXIT [1].
Presence of the AVIC_EXTLVT feature is indicated via CPUID function
0x8000000A_EDX[27].
[1]: AMD Programmer's Manual Volume 2,
Table 15-22. Guest vAPIC Register Access Behavior.
https://bugzilla.kernel.org/attachment.cgi?id=306250
Acked-by: Borislav Petkov (AMD) <bp@alien8.de>
Signed-off-by: Santosh Shukla <santosh.shukla@amd.com>
Signed-off-by: Manali Shukla <manali.shukla@amd.com>
---
arch/x86/include/asm/cpufeatures.h | 1 +
1 file changed, 1 insertion(+)
diff --git a/arch/x86/include/asm/cpufeatures.h b/arch/x86/include/asm/cpufeatures.h
index 81f7b3b91986..52882d794b3c 100644
--- a/arch/x86/include/asm/cpufeatures.h
+++ b/arch/x86/include/asm/cpufeatures.h
@@ -381,6 +381,7 @@
#define X86_FEATURE_X2AVIC (15*32+18) /* "x2avic" Virtual x2apic */
#define X86_FEATURE_V_SPEC_CTRL (15*32+20) /* "v_spec_ctrl" Virtual SPEC_CTRL */
#define X86_FEATURE_VNMI (15*32+25) /* "vnmi" Virtual NMI */
+#define X86_FEATURE_AVIC_EXTLVT (15*32+27) /* Extended LVT AVIC acceleration support */
#define X86_FEATURE_SVME_ADDR_CHK (15*32+28) /* SVME addr check */
#define X86_FEATURE_BUS_LOCK_THRESHOLD (15*32+29) /* Bus lock threshold */
#define X86_FEATURE_IDLE_HLT (15*32+30) /* IDLE HLT intercept */
--
2.43.0
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH v1 9/9] KVM: SVM: Add AVIC support for extended LVT MSRs
2026-02-04 7:44 [PATCH v1 0/9] KVM: x86: Add support for AMD Extended APIC registers Manali Shukla
` (7 preceding siblings ...)
2026-02-04 7:44 ` [PATCH v1 8/9] x86/cpufeatures: Add CPUID feature bit for Extended LVT AVIC acceleration Manali Shukla
@ 2026-02-04 7:44 ` Manali Shukla
2026-03-10 6:17 ` [PATCH v1 0/9] KVM: x86: Add support for AMD Extended APIC registers Manali Shukla
9 siblings, 0 replies; 15+ messages in thread
From: Manali Shukla @ 2026-02-04 7:44 UTC (permalink / raw)
To: seanjc, pbonzini
Cc: mingo, bp, dave.hansen, kvm, x86, santosh.shukla, nikunj.dadhania,
Naveen.Rao, dapeng1.mi, manali.shukla
Configure MSR intercepts for extended LVT registers when both AVIC and
AVIC_EXTLVT are supported by hardware. Extended LVT registers are
x2APIC MSRs at offsets 0x500-0x530 in the APIC register space.
When AVIC is enabled and MSR intercepts are disabled, allow passthrough
access to extended LVT MSRs. Hardware accelerates reads without VM-exits,
while writes trigger trap-style VM-exits that are handled by the existing
avic_unaccelerated_access_interception() path.
Enable AVIC_EXTLVT support only when both X86_FEATURE_AVIC and
X86_FEATURE_AVIC_EXTLVT are present.
Signed-off-by: Manali Shukla <manali.shukla@amd.com>
---
arch/x86/kvm/svm/avic.c | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/arch/x86/kvm/svm/avic.c b/arch/x86/kvm/svm/avic.c
index f92214b1a938..039cb02dc00f 100644
--- a/arch/x86/kvm/svm/avic.c
+++ b/arch/x86/kvm/svm/avic.c
@@ -107,6 +107,7 @@ static bool next_vm_id_wrapped = 0;
static DEFINE_SPINLOCK(svm_vm_data_hash_lock);
static bool x2avic_enabled;
static u32 x2avic_max_physical_id;
+static bool avic_extlvt_enabled;
static void avic_set_x2apic_msr_interception(struct vcpu_svm *svm,
bool intercept)
@@ -155,6 +156,12 @@ static void avic_set_x2apic_msr_interception(struct vcpu_svm *svm,
svm_set_intercept_for_msr(&svm->vcpu, x2avic_passthrough_msrs[i],
MSR_TYPE_RW, intercept);
+ if (avic_extlvt_enabled) {
+ for (i = 0; i < svm->vcpu.kvm->arch.nr_extlvt; i++)
+ svm_set_intercept_for_msr(&svm->vcpu, X2APIC_MSR(APIC_EILVTn(i)),
+ MSR_TYPE_RW, intercept);
+ }
+
svm->x2avic_msrs_intercepted = intercept;
}
@@ -815,6 +822,10 @@ int avic_unaccelerated_access_interception(struct kvm_vcpu *vcpu)
AVIC_UNACCEL_ACCESS_WRITE_MASK;
bool trap = is_avic_unaccelerated_access_trap(offset);
+ if (avic_extlvt_enabled &&
+ kvm_is_extlvt_offset(offset, vcpu->kvm->arch.nr_extlvt))
+ trap = true;
+
trace_kvm_avic_unaccelerated_access(vcpu->vcpu_id, offset,
trap, write, vector);
if (trap) {
@@ -1293,6 +1304,9 @@ bool __init avic_hardware_setup(void)
*/
enable_ipiv = enable_ipiv && boot_cpu_data.x86 != 0x17;
+ avic_extlvt_enabled = (boot_cpu_has(X86_FEATURE_AVIC) &&
+ boot_cpu_has(X86_FEATURE_AVIC_EXTLVT));
+
amd_iommu_register_ga_log_notifier(&avic_ga_log_notifier);
return true;
--
2.43.0
^ permalink raw reply related [flat|nested] 15+ messages in thread
* Re: [PATCH v1 0/9] KVM: x86: Add support for AMD Extended APIC registers
2026-02-04 7:44 [PATCH v1 0/9] KVM: x86: Add support for AMD Extended APIC registers Manali Shukla
` (8 preceding siblings ...)
2026-02-04 7:44 ` [PATCH v1 9/9] KVM: SVM: Add AVIC support for extended LVT MSRs Manali Shukla
@ 2026-03-10 6:17 ` Manali Shukla
2026-04-27 4:34 ` Shukla, Manali
9 siblings, 1 reply; 15+ messages in thread
From: Manali Shukla @ 2026-03-10 6:17 UTC (permalink / raw)
To: seanjc, pbonzini
Cc: mingo, bp, dave.hansen, kvm, x86, santosh.shukla, nikunj.dadhania,
Naveen.Rao, dapeng1.mi
On 2/4/2026 1:14 PM, Manali Shukla wrote:
> Add support for AMD's Extended APIC registers, which reside in a 4KB
> APIC page instead of the legacy 1KB APIC register space. Extended LVT
> registers (offsets 0x500-0x530) provide additional interrupt vectors
> for features like Instruction Based Sampling (IBS).
>
> Introduce KVM_CAP_LAPIC2 to allow userspace to opt into the full 4KB
> APIC register space. The capability uses a bitmask to support different
> APIC extensions:
>
> KVM_LAPIC2_DEFAULT: 4KB APIC register space (common foundation)
> KVM_LAPIC2_AMD_DEFAULT: Extended LVT registers (AMD-specific)
>
> Add KVM_GET/SET_LAPIC2 ioctls that operate on a 4KB APIC register space
> accommodate extended registers. Legacy KVM_GET/SET_LAPIC continue to
> work for backward compatibility.
>
> Emulate extended APIC registers (APIC_EFEAT, APIC_ECTRL, APIC_EILVTn)
> when the guest has X86_FEATURE_EXTAPIC and userspace enables
> KVM_CAP_LAPIC2. Current AMD processors support four extended LVT
> entries, future processors may support up to 255.
>
> Integrate with AVIC to accelerate extended LVT MSR access when
> AVIC_EXTLVT is supported. Reads are accelerated without VM-exits;
> writes trigger trap-style VM-exits.
>
> Tested on AMD hardware with Extapic support:
> - Extended APIC register read/write emulation and AVIC acceleration
> with IBS driver running on the guest
> - VM migration with extended APIC state and without extended APIC state
> - Backward compatibility check:
> Fallback to legacy IOCTLs when KVM_CAP_LAPIC2 capability is not enabled
>
> Equivalent Qemu changes can be found at:
> https://github.com/AMDESE/qemu/tree/extlvt_v1
>
> Patches are prepared on kvm-x86/next (003f68c79227).
>
> Manali Shukla (7):
> KVM: x86: Refactor APIC register mask handling to support extended
> APIC registers
> x86/apic: Add helper to get maximum number of Extended LVT registers
> KVM: SVM: Set kvm_caps.has_extapic when CPU supports Extended APIC
> KVM: x86: Introduce KVM_CAP_LAPIC2 for 4KB APIC register space support
> KVM: x86: Refactor APIC state get/set to accept variable-sized buffers
> KVM: Add KVM_GET_LAPIC2 and KVM_SET_LAPIC2 for extended APIC
> KVM: SVM: Add AVIC support for extended LVT MSRs
>
> Santosh Shukla (2):
> KVM: x86: Emulate Extended LVT registers for AMD guests
> x86/cpufeatures: Add CPUID feature bit for Extended LVT AVIC
> acceleration
>
> Documentation/virt/kvm/api.rst | 75 +++++++++++++
> arch/x86/include/asm/apic.h | 1 +
> arch/x86/include/asm/apicdef.h | 18 +++
> arch/x86/include/asm/cpufeatures.h | 1 +
> arch/x86/include/asm/kvm_host.h | 12 ++
> arch/x86/include/uapi/asm/kvm.h | 5 +
> arch/x86/kernel/apic/apic.c | 17 +++
> arch/x86/kvm/cpuid.c | 10 +-
> arch/x86/kvm/lapic.c | 169 ++++++++++++++++++++---------
> arch/x86/kvm/lapic.h | 14 ++-
> arch/x86/kvm/svm/avic.c | 14 +++
> arch/x86/kvm/svm/svm.c | 3 +
> arch/x86/kvm/vmx/vmx.c | 10 +-
> arch/x86/kvm/x86.c | 93 +++++++++++++++-
> arch/x86/kvm/x86.h | 2 +
> include/uapi/linux/kvm.h | 7 ++
> 16 files changed, 390 insertions(+), 61 deletions(-)
>
A Gentle reminder to review.
-Manali
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v1 6/9] KVM: Add KVM_GET_LAPIC2 and KVM_SET_LAPIC2 for extended APIC
2026-02-04 7:44 ` [PATCH v1 6/9] KVM: Add KVM_GET_LAPIC2 and KVM_SET_LAPIC2 for extended APIC Manali Shukla
@ 2026-03-16 13:00 ` Nikunj A. Dadhania
2026-03-23 11:15 ` Manali Shukla
0 siblings, 1 reply; 15+ messages in thread
From: Nikunj A. Dadhania @ 2026-03-16 13:00 UTC (permalink / raw)
To: Manali Shukla, seanjc, pbonzini
Cc: mingo, bp, dave.hansen, kvm, x86, santosh.shukla, nikunj.dadhania,
Naveen.Rao, dapeng1.mi
On 2/4/2026 1:14 PM, Manali Shukla wrote:
> Add KVM_GET_LAPIC2 and KVM_SET_LAPIC2 ioctls to save and restore APIC
> state using a 4KB buffer (kvm_lapic_state2). The larger buffer allows
> saving additional APIC registers beyond the standard APIC registers
> supported by the existing 1KB KVM_GET/SET_LAPIC ioctls.
>
> The 4KB buffer size matches the LAPIC2 capability, which enables the
> full APIC register page including extended APIC registers for AMD
> processors.
>
> KVM_GET/SET_LAPIC continue to work as before for backward compatibility.
> Document the new ioctls in Documentation/virt/kvm/api.rst.
>
> Suggested-by: Sean Christopherson <seanjc@google.com>
> Signed-off-by: Manali Shukla <manali.shukla@amd.com>
> ---
> Documentation/virt/kvm/api.rst | 45 +++++++++++++++++++++++++
> arch/x86/include/uapi/asm/kvm.h | 5 +++
> arch/x86/kvm/x86.c | 59 +++++++++++++++++++++++++++++++++
> include/uapi/linux/kvm.h | 2 ++
> 4 files changed, 111 insertions(+)
>
> diff --git a/Documentation/virt/kvm/api.rst b/Documentation/virt/kvm/api.rst
> index 71b4d24f009a..c49cf3104b2c 100644
> --- a/Documentation/virt/kvm/api.rst
> +++ b/Documentation/virt/kvm/api.rst
> @@ -6517,6 +6517,51 @@ the capability to be present.
>
> `flags` must currently be zero.
>
> +4.144 KVM_GET_LAPIC2
> +----------------------
> +
> +:Capability: KVM_CAP_LAPIC2
> +:Architectures: x86
> +:Type: vcpu ioctl
> +:Parameters: struct kvm_lapic_state2 (out)
> +:Returns: 0 on success, negative on failure
> +
> +Reads the extended Local APIC registers, including both the standard APIC
> +register space (offsets 0h-3FFh) and the extended APIC register space (offsets
> +400h-500h and beyond).
> +
> +This ioctl is similar to KVM_GET_LAPIC but operates on a 4KB APIC
> +register space that includes extended LVT registers available on AMD processors
> +with the ExtApicSpace feature.
> +
> +::
> +
> + #define KVM_APIC_EXT_REG_SIZE 0x1000
> + struct kvm_lapic_state2 {
> + char regs[KVM_APIC_EXT_REG_SIZE];
> + };
> +
> +4.145 KVM_SET_LAPIC2
> +----------------------
> +
> +:Capability: KVM_CAP_LAPIC2
> +:Architectures: x86
> +:Type: vcpu ioctl
> +:Parameters: struct kvm_lapic_state2 (in)
> +:Returns: 0 on success, negative on failure
> +
> +Sets the extended Local APIC registers, including both the standard APIC
> +register space and the extended APIC register space.
> +
> +This ioctl is similar to KVM_SET_LAPIC but operates on a 4KB APIC register space
> +that includes extended LVT registers for AMD processors.
> +
> +::
> +
> + #define KVM_APIC_EXT_REG_SIZE 0x1000
> + struct kvm_lapic_stat2 {
> + char regs[KVM_APIC_EXT_REG_SIZE];
> + };
>
> .. _kvm_run:
>
> diff --git a/arch/x86/include/uapi/asm/kvm.h b/arch/x86/include/uapi/asm/kvm.h
> index 7ceff6583652..516d4a0be25a 100644
> --- a/arch/x86/include/uapi/asm/kvm.h
> +++ b/arch/x86/include/uapi/asm/kvm.h
> @@ -129,6 +129,11 @@ struct kvm_lapic_state {
> char regs[KVM_APIC_REG_SIZE];
> };
>
> +#define KVM_APIC_EXT_REG_SIZE 0x1000
> +struct kvm_lapic_state2 {
> + char regs[KVM_APIC_EXT_REG_SIZE];
> +};
> +
> struct kvm_segment {
> __u64 base;
> __u32 limit;
> diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
> index 669c894f1061..ccd16bdff56a 100644
> --- a/arch/x86/kvm/x86.c
> +++ b/arch/x86/kvm/x86.c
> @@ -5331,6 +5331,17 @@ static int kvm_vcpu_ioctl_get_lapic(struct kvm_vcpu *vcpu,
> return kvm_apic_get_state(vcpu, s->regs, sizeof(*s));
> }
>
> +static int kvm_vcpu_ioctl_get_lapic2(struct kvm_vcpu *vcpu,
> + struct kvm_lapic_state2 *s)
> +{
> + if (vcpu->arch.apic->guest_apic_protected)
> + return -EINVAL;
> +
> + kvm_x86_call(sync_pir_to_irr)(vcpu);
> +
> + return kvm_apic_get_state(vcpu, s->regs, sizeof(*s));
> +}
Should this function verify that KVM_CAP_LAPIC2 was enabled for the VM?
The KVM_CAP_LAPIC2 documentation states "This must be called before
creating any VCPUs" which implies userspace must explicitly enable the
capability. However, this ioctl doesn't check kvm->arch.nr_extlvt or any
flag indicating the capability was enabled.
Looking at how this interacts with kvm_apic_get_state() in
arch/x86/kvm/lapic.c:
int kvm_apic_get_state(struct kvm_vcpu *vcpu, void *regs, unsigned int size)
{
memcpy(regs, vcpu->arch.apic->regs, size);
...
}
The function copies 'size' bytes from vcpu->arch.apic->regs. Since
sizeof(struct kvm_lapic_state2) is 4096 bytes and apic->regs is allocated
as a single page (also 4096 bytes), this works. But if the extended APIC
capability wasn't enabled via KVM_ENABLE_CAP, should userspace be allowed
to read the extended register space?
> +
> static int kvm_vcpu_ioctl_set_lapic(struct kvm_vcpu *vcpu,
> struct kvm_lapic_state *s)
> {
> @@ -5347,6 +5358,22 @@ static int kvm_vcpu_ioctl_set_lapic(struct kvm_vcpu *vcpu,
> return 0;
> }
>
> +static int kvm_vcpu_ioctl_set_lapic2(struct kvm_vcpu *vcpu,
> + struct kvm_lapic_state2 *s)
> +{
> + int r;
> +
> + if (vcpu->arch.apic->guest_apic_protected)
> + return -EINVAL;
> +
> + r = kvm_apic_set_state(vcpu, s->regs, sizeof(*s));
> + if (r)
> + return r;
> + update_cr8_intercept(vcpu);
> +
> + return 0;
> +}
> +
Ditto, shouldn't it verify the capability was enabled before allowing writes
to the extended APIC space?
> static int kvm_cpu_accept_dm_intr(struct kvm_vcpu *vcpu)
> {
> /*
> @@ -6203,6 +6230,7 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
> union {
> struct kvm_sregs2 *sregs2;
> struct kvm_lapic_state *lapic;
> + struct kvm_lapic_state2 *lapic2;
> struct kvm_xsave *xsave;
> struct kvm_xcrs *xcrs;
> void *buffer;
> @@ -6243,6 +6271,37 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
> r = kvm_vcpu_ioctl_set_lapic(vcpu, u.lapic);
> break;
> }
> + case KVM_GET_LAPIC2: {
> + r = -EINVAL;
> + if (!lapic_in_kernel(vcpu))
> + goto out;
> + u.lapic2 = kzalloc(sizeof(struct kvm_lapic_state2), GFP_KERNEL);
> +
> + r = -ENOMEM;
> + if (!u.lapic2)
> + goto out;
> + r = kvm_vcpu_ioctl_get_lapic2(vcpu, u.lapic2);
> + if (r)
> + goto out;
> + r = -EFAULT;
> + if (copy_to_user(argp, u.lapic2, sizeof(struct kvm_lapic_state2)))
> + goto out;
> + r = 0;
> + break;
> + }
> + case KVM_SET_LAPIC2: {
> + r = -EINVAL;
> + if (!lapic_in_kernel(vcpu))
> + goto out;
> + u.lapic2 = memdup_user(argp, sizeof(*u.lapic2));
> + if (IS_ERR(u.lapic2)) {
> + r = PTR_ERR(u.lapic2);
> + goto out_nofree;
> + }
> +
> + r = kvm_vcpu_ioctl_set_lapic2(vcpu, u.lapic2);
> + break;
> + }
> case KVM_INTERRUPT: {
> struct kvm_interrupt irq;
>
> diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
> index cb27eeb09bdb..f45d313e30ae 100644
> --- a/include/uapi/linux/kvm.h
> +++ b/include/uapi/linux/kvm.h
> @@ -1339,6 +1339,8 @@ 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)
> +#define KVM_GET_LAPIC2 _IOR(KVMIO, 0x8e, struct kvm_lapic_state2)
> +#define KVM_SET_LAPIC2 _IOW(KVMIO, 0x8f, struct kvm_lapic_state2)
KVM_GET_LAPIC2 and KVM_SET_LAPIC2 reuse command numbers 0x8e and 0x8f.
While the _IOR/_IOW macros encode the structure size into the ioctl
number, this still seems unconventional compared to other KVM ioctls
that use unique command numbers: for e.g. SET_CPUID / SET_CPUID2
#define KVM_SET_CPUID _IOW(KVMIO, 0x8a, struct kvm_cpuid)
#define KVM_SET_CPUID2 _IOW(KVMIO, 0x90, struct kvm_cpuid2)
It would be clearer to use unique command numbers like 0x92 and 0x93.
> #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 */
Regards,
Nikunj
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v1 6/9] KVM: Add KVM_GET_LAPIC2 and KVM_SET_LAPIC2 for extended APIC
2026-03-16 13:00 ` Nikunj A. Dadhania
@ 2026-03-23 11:15 ` Manali Shukla
0 siblings, 0 replies; 15+ messages in thread
From: Manali Shukla @ 2026-03-23 11:15 UTC (permalink / raw)
To: Nikunj A. Dadhania, seanjc, pbonzini
Cc: mingo, bp, dave.hansen, kvm, x86, santosh.shukla, nikunj.dadhania,
Naveen.Rao, dapeng1.mi
On 3/16/2026 6:30 PM, Nikunj A. Dadhania wrote:
>
>
> On 2/4/2026 1:14 PM, Manali Shukla wrote:
>> Add KVM_GET_LAPIC2 and KVM_SET_LAPIC2 ioctls to save and restore APIC
>> state using a 4KB buffer (kvm_lapic_state2). The larger buffer allows
>> saving additional APIC registers beyond the standard APIC registers
>> supported by the existing 1KB KVM_GET/SET_LAPIC ioctls.
>>
>> The 4KB buffer size matches the LAPIC2 capability, which enables the
>> full APIC register page including extended APIC registers for AMD
>> processors.
>>
>> KVM_GET/SET_LAPIC continue to work as before for backward compatibility.
>> Document the new ioctls in Documentation/virt/kvm/api.rst.
>>
>> Suggested-by: Sean Christopherson <seanjc@google.com>
>> Signed-off-by: Manali Shukla <manali.shukla@amd.com>
>> ---
>> Documentation/virt/kvm/api.rst | 45 +++++++++++++++++++++++++
>> arch/x86/include/uapi/asm/kvm.h | 5 +++
>> arch/x86/kvm/x86.c | 59 +++++++++++++++++++++++++++++++++
>> include/uapi/linux/kvm.h | 2 ++
>> 4 files changed, 111 insertions(+)
>>
>> diff --git a/Documentation/virt/kvm/api.rst b/Documentation/virt/kvm/api.rst
>> index 71b4d24f009a..c49cf3104b2c 100644
>> --- a/Documentation/virt/kvm/api.rst
>> +++ b/Documentation/virt/kvm/api.rst
>> @@ -6517,6 +6517,51 @@ the capability to be present.
>>
>> `flags` must currently be zero.
>>
>> +4.144 KVM_GET_LAPIC2
>> +----------------------
>> +
>> +:Capability: KVM_CAP_LAPIC2
>> +:Architectures: x86
>> +:Type: vcpu ioctl
>> +:Parameters: struct kvm_lapic_state2 (out)
>> +:Returns: 0 on success, negative on failure
>> +
>> +Reads the extended Local APIC registers, including both the standard APIC
>> +register space (offsets 0h-3FFh) and the extended APIC register space (offsets
>> +400h-500h and beyond).
>> +
>> +This ioctl is similar to KVM_GET_LAPIC but operates on a 4KB APIC
>> +register space that includes extended LVT registers available on AMD processors
>> +with the ExtApicSpace feature.
>> +
>> +::
>> +
>> + #define KVM_APIC_EXT_REG_SIZE 0x1000
>> + struct kvm_lapic_state2 {
>> + char regs[KVM_APIC_EXT_REG_SIZE];
>> + };
>> +
>> +4.145 KVM_SET_LAPIC2
>> +----------------------
>> +
>> +:Capability: KVM_CAP_LAPIC2
>> +:Architectures: x86
>> +:Type: vcpu ioctl
>> +:Parameters: struct kvm_lapic_state2 (in)
>> +:Returns: 0 on success, negative on failure
>> +
>> +Sets the extended Local APIC registers, including both the standard APIC
>> +register space and the extended APIC register space.
>> +
>> +This ioctl is similar to KVM_SET_LAPIC but operates on a 4KB APIC register space
>> +that includes extended LVT registers for AMD processors.
>> +
>> +::
>> +
>> + #define KVM_APIC_EXT_REG_SIZE 0x1000
>> + struct kvm_lapic_stat2 {
>> + char regs[KVM_APIC_EXT_REG_SIZE];
>> + };
>>
>> .. _kvm_run:
>>
>> diff --git a/arch/x86/include/uapi/asm/kvm.h b/arch/x86/include/uapi/asm/kvm.h
>> index 7ceff6583652..516d4a0be25a 100644
>> --- a/arch/x86/include/uapi/asm/kvm.h
>> +++ b/arch/x86/include/uapi/asm/kvm.h
>> @@ -129,6 +129,11 @@ struct kvm_lapic_state {
>> char regs[KVM_APIC_REG_SIZE];
>> };
>>
>> +#define KVM_APIC_EXT_REG_SIZE 0x1000
>> +struct kvm_lapic_state2 {
>> + char regs[KVM_APIC_EXT_REG_SIZE];
>> +};
>> +
>> struct kvm_segment {
>> __u64 base;
>> __u32 limit;
>> diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
>> index 669c894f1061..ccd16bdff56a 100644
>> --- a/arch/x86/kvm/x86.c
>> +++ b/arch/x86/kvm/x86.c
>> @@ -5331,6 +5331,17 @@ static int kvm_vcpu_ioctl_get_lapic(struct kvm_vcpu *vcpu,
>> return kvm_apic_get_state(vcpu, s->regs, sizeof(*s));
>> }
>>
>> +static int kvm_vcpu_ioctl_get_lapic2(struct kvm_vcpu *vcpu,
>> + struct kvm_lapic_state2 *s)
>> +{
>> + if (vcpu->arch.apic->guest_apic_protected)
>> + return -EINVAL;
>> +
>> + kvm_x86_call(sync_pir_to_irr)(vcpu);
>> +
>> + return kvm_apic_get_state(vcpu, s->regs, sizeof(*s));
>> +}
>
> Should this function verify that KVM_CAP_LAPIC2 was enabled for the VM?
> The KVM_CAP_LAPIC2 documentation states "This must be called before
> creating any VCPUs" which implies userspace must explicitly enable the
> capability. However, this ioctl doesn't check kvm->arch.nr_extlvt or any
> flag indicating the capability was enabled.
>
> Looking at how this interacts with kvm_apic_get_state() in
> arch/x86/kvm/lapic.c:
>
> int kvm_apic_get_state(struct kvm_vcpu *vcpu, void *regs, unsigned int size)
> {
> memcpy(regs, vcpu->arch.apic->regs, size);
> ...
> }
>
> The function copies 'size' bytes from vcpu->arch.apic->regs. Since
> sizeof(struct kvm_lapic_state2) is 4096 bytes and apic->regs is allocated
> as a single page (also 4096 bytes), this works. But if the extended APIC
> capability wasn't enabled via KVM_ENABLE_CAP, should userspace be allowed
> to read the extended register space?
>
Yeah. Correct. If the capability is not enabled, userspace should not be
allowed to read/write the extended register space. It makes sense to put
a check here. I will fix this in V2.
>> +
>> static int kvm_vcpu_ioctl_set_lapic(struct kvm_vcpu *vcpu,
>> struct kvm_lapic_state *s)
>> {
>> @@ -5347,6 +5358,22 @@ static int kvm_vcpu_ioctl_set_lapic(struct kvm_vcpu *vcpu,
>> return 0;
>> }
>>
>> +static int kvm_vcpu_ioctl_set_lapic2(struct kvm_vcpu *vcpu,
>> + struct kvm_lapic_state2 *s)
>> +{
>> + int r;
>> +
>> + if (vcpu->arch.apic->guest_apic_protected)
>> + return -EINVAL;
>> +
>> + r = kvm_apic_set_state(vcpu, s->regs, sizeof(*s));
>> + if (r)
>> + return r;
>> + update_cr8_intercept(vcpu);
>> +
>> + return 0;
>> +}
>> +
>
> Ditto, shouldn't it verify the capability was enabled before allowing writes
> to the extended APIC space?
>
Agreed. Will add a check here too.
>>
>> diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
>> index cb27eeb09bdb..f45d313e30ae 100644
>> --- a/include/uapi/linux/kvm.h
>> +++ b/include/uapi/linux/kvm.h
>> @@ -1339,6 +1339,8 @@ 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)
>> +#define KVM_GET_LAPIC2 _IOR(KVMIO, 0x8e, struct kvm_lapic_state2)
>> +#define KVM_SET_LAPIC2 _IOW(KVMIO, 0x8f, struct kvm_lapic_state2)
>
> KVM_GET_LAPIC2 and KVM_SET_LAPIC2 reuse command numbers 0x8e and 0x8f.
> While the _IOR/_IOW macros encode the structure size into the ioctl
> number, this still seems unconventional compared to other KVM ioctls
> that use unique command numbers: for e.g. SET_CPUID / SET_CPUID2
>
> #define KVM_SET_CPUID _IOW(KVMIO, 0x8a, struct kvm_cpuid)
> #define KVM_SET_CPUID2 _IOW(KVMIO, 0x90, struct kvm_cpuid2)
>
> It would be clearer to use unique command numbers like 0x92 and 0x93.
>
This was discussed during the PUCK call and in [1]. The _IOR/_IOW macros
encode the struct size into the ioctl number, and since kvm_lapic_state
and kvm_lapic_state2 have different sizes, the final ioctl numbers will
differ.
In case of the KVM_SET_CPUID / KVM_SET_CPUID2, both the structures
(kvm_cpuid2 and kvm_cpuid) use a flex array, so are of same size, I
think that is why it required the different IOCTL number.
[1] https://lore.kernel.org/kvm/aWgRvCdPsAFHRwcU@google.com/
>> #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 */
>
> Regards,
> Nikunj
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v1 0/9] KVM: x86: Add support for AMD Extended APIC registers
2026-03-10 6:17 ` [PATCH v1 0/9] KVM: x86: Add support for AMD Extended APIC registers Manali Shukla
@ 2026-04-27 4:34 ` Shukla, Manali
0 siblings, 0 replies; 15+ messages in thread
From: Shukla, Manali @ 2026-04-27 4:34 UTC (permalink / raw)
To: seanjc, pbonzini
Cc: mingo, bp, dave.hansen, kvm, x86, santosh.shukla, nikunj.dadhania,
Naveen.Rao, dapeng1.mi
On 3/10/2026 11:47 AM, Manali Shukla wrote:
> On 2/4/2026 1:14 PM, Manali Shukla wrote:
>> Add support for AMD's Extended APIC registers, which reside in a 4KB
>> APIC page instead of the legacy 1KB APIC register space. Extended LVT
>> registers (offsets 0x500-0x530) provide additional interrupt vectors
>> for features like Instruction Based Sampling (IBS).
>>
>> Introduce KVM_CAP_LAPIC2 to allow userspace to opt into the full 4KB
>> APIC register space. The capability uses a bitmask to support different
>> APIC extensions:
>>
>> KVM_LAPIC2_DEFAULT: 4KB APIC register space (common foundation)
>> KVM_LAPIC2_AMD_DEFAULT: Extended LVT registers (AMD-specific)
>>
>> Add KVM_GET/SET_LAPIC2 ioctls that operate on a 4KB APIC register space
>> accommodate extended registers. Legacy KVM_GET/SET_LAPIC continue to
>> work for backward compatibility.
>>
>> Emulate extended APIC registers (APIC_EFEAT, APIC_ECTRL, APIC_EILVTn)
>> when the guest has X86_FEATURE_EXTAPIC and userspace enables
>> KVM_CAP_LAPIC2. Current AMD processors support four extended LVT
>> entries, future processors may support up to 255.
>>
>> Integrate with AVIC to accelerate extended LVT MSR access when
>> AVIC_EXTLVT is supported. Reads are accelerated without VM-exits;
>> writes trigger trap-style VM-exits.
>>
>> Tested on AMD hardware with Extapic support:
>> - Extended APIC register read/write emulation and AVIC acceleration
>> with IBS driver running on the guest
>> - VM migration with extended APIC state and without extended APIC state
>> - Backward compatibility check:
>> Fallback to legacy IOCTLs when KVM_CAP_LAPIC2 capability is not enabled
>>
>> Equivalent Qemu changes can be found at:
>> https://github.com/AMDESE/qemu/tree/extlvt_v1
>>
>> Patches are prepared on kvm-x86/next (003f68c79227).
>>
>> Manali Shukla (7):
>> KVM: x86: Refactor APIC register mask handling to support extended
>> APIC registers
>> x86/apic: Add helper to get maximum number of Extended LVT registers
>> KVM: SVM: Set kvm_caps.has_extapic when CPU supports Extended APIC
>> KVM: x86: Introduce KVM_CAP_LAPIC2 for 4KB APIC register space support
>> KVM: x86: Refactor APIC state get/set to accept variable-sized buffers
>> KVM: Add KVM_GET_LAPIC2 and KVM_SET_LAPIC2 for extended APIC
>> KVM: SVM: Add AVIC support for extended LVT MSRs
>>
>> Santosh Shukla (2):
>> KVM: x86: Emulate Extended LVT registers for AMD guests
>> x86/cpufeatures: Add CPUID feature bit for Extended LVT AVIC
>> acceleration
>>
>> Documentation/virt/kvm/api.rst | 75 +++++++++++++
>> arch/x86/include/asm/apic.h | 1 +
>> arch/x86/include/asm/apicdef.h | 18 +++
>> arch/x86/include/asm/cpufeatures.h | 1 +
>> arch/x86/include/asm/kvm_host.h | 12 ++
>> arch/x86/include/uapi/asm/kvm.h | 5 +
>> arch/x86/kernel/apic/apic.c | 17 +++
>> arch/x86/kvm/cpuid.c | 10 +-
>> arch/x86/kvm/lapic.c | 169 ++++++++++++++++++++---------
>> arch/x86/kvm/lapic.h | 14 ++-
>> arch/x86/kvm/svm/avic.c | 14 +++
>> arch/x86/kvm/svm/svm.c | 3 +
>> arch/x86/kvm/vmx/vmx.c | 10 +-
>> arch/x86/kvm/x86.c | 93 +++++++++++++++-
>> arch/x86/kvm/x86.h | 2 +
>> include/uapi/linux/kvm.h | 7 ++
>> 16 files changed, 390 insertions(+), 61 deletions(-)
>>
>
> A Gentle reminder to review.
>
> -Manali
>
A Gentle reminder to review.
-Manali
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v1 2/9] x86/apic: Add helper to get maximum number of Extended LVT registers
2026-02-04 7:44 ` [PATCH v1 2/9] x86/apic: Add helper to get maximum number of Extended LVT registers Manali Shukla
@ 2026-05-06 11:22 ` Borislav Petkov
0 siblings, 0 replies; 15+ messages in thread
From: Borislav Petkov @ 2026-05-06 11:22 UTC (permalink / raw)
To: Manali Shukla
Cc: seanjc, pbonzini, mingo, dave.hansen, kvm, x86, santosh.shukla,
nikunj.dadhania, Naveen.Rao, dapeng1.mi
On Wed, Feb 04, 2026 at 07:44:45AM +0000, Manali Shukla wrote:
> +/**
> + * lapic_get_max_extlvt - Get number of extended LVT entries
> + */
> +int lapic_get_max_extlvt(void)
> +{
> + u32 reg;
> +
> + if (!boot_cpu_has(X86_FEATURE_EXTAPIC))
check_for_deprecated_apis: WARNING: arch/x86/kernel/apic/apic.c:263: Do not use boot_cpu_has() - use cpu_feature_enabled() instead.
> + return 0;
> +
> + reg = apic_read(APIC_EFEAT);
> +
> + /* Extract extended LVT count from bits 16-23 */
> + return (reg >> 16) & 0xff;
Use GENMASK() and get rid of the comment because it is obvious then.
> +}
> +EXPORT_SYMBOL_GPL(lapic_get_max_extlvt);
EXPORT_SYMBOL_FOR_KVM_INTERNAL
--
Regards/Gruss,
Boris.
https://people.kernel.org/tglx/notes-about-netiquette
^ permalink raw reply [flat|nested] 15+ messages in thread
end of thread, other threads:[~2026-05-06 11:23 UTC | newest]
Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-02-04 7:44 [PATCH v1 0/9] KVM: x86: Add support for AMD Extended APIC registers Manali Shukla
2026-02-04 7:44 ` [PATCH v1 1/9] KVM: x86: Refactor APIC register mask handling to support extended " Manali Shukla
2026-02-04 7:44 ` [PATCH v1 2/9] x86/apic: Add helper to get maximum number of Extended LVT registers Manali Shukla
2026-05-06 11:22 ` Borislav Petkov
2026-02-04 7:44 ` [PATCH v1 3/9] KVM: SVM: Set kvm_caps.has_extapic when CPU supports Extended APIC Manali Shukla
2026-02-04 7:44 ` [PATCH v1 4/9] KVM: x86: Introduce KVM_CAP_LAPIC2 for 4KB APIC register space support Manali Shukla
2026-02-04 7:44 ` [PATCH v1 5/9] KVM: x86: Refactor APIC state get/set to accept variable-sized buffers Manali Shukla
2026-02-04 7:44 ` [PATCH v1 6/9] KVM: Add KVM_GET_LAPIC2 and KVM_SET_LAPIC2 for extended APIC Manali Shukla
2026-03-16 13:00 ` Nikunj A. Dadhania
2026-03-23 11:15 ` Manali Shukla
2026-02-04 7:44 ` [PATCH v1 7/9] KVM: x86: Emulate Extended LVT registers for AMD guests Manali Shukla
2026-02-04 7:44 ` [PATCH v1 8/9] x86/cpufeatures: Add CPUID feature bit for Extended LVT AVIC acceleration Manali Shukla
2026-02-04 7:44 ` [PATCH v1 9/9] KVM: SVM: Add AVIC support for extended LVT MSRs Manali Shukla
2026-03-10 6:17 ` [PATCH v1 0/9] KVM: x86: Add support for AMD Extended APIC registers Manali Shukla
2026-04-27 4:34 ` Shukla, Manali
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox