Skip to content

Commit 89400f0

Browse files
committed
Merge tag 'kvm-x86-apic-6.17' of https://github.com/kvm-x86/linux into HEAD
KVM local APIC changes for 6.17 Extract many of KVM's helpers for accessing architectural local APIC state to common x86 so that they can be shared by guest-side code for Secure AVIC.
2 parents d7f4aac + b95a9d3 commit 89400f0

File tree

3 files changed

+94
-93
lines changed

3 files changed

+94
-93
lines changed

arch/x86/include/asm/apic.h

Lines changed: 64 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -488,18 +488,80 @@ static inline void apic_setup_apic_calls(void) { }
488488

489489
extern void apic_ack_irq(struct irq_data *data);
490490

491+
#define APIC_VECTOR_TO_BIT_NUMBER(v) ((unsigned int)(v) % 32)
492+
#define APIC_VECTOR_TO_REG_OFFSET(v) ((unsigned int)(v) / 32 * 0x10)
493+
491494
static inline bool lapic_vector_set_in_irr(unsigned int vector)
492495
{
493-
u32 irr = apic_read(APIC_IRR + (vector / 32 * 0x10));
496+
u32 irr = apic_read(APIC_IRR + APIC_VECTOR_TO_REG_OFFSET(vector));
494497

495-
return !!(irr & (1U << (vector % 32)));
498+
return !!(irr & (1U << APIC_VECTOR_TO_BIT_NUMBER(vector)));
496499
}
497500

498501
static inline bool is_vector_pending(unsigned int vector)
499502
{
500503
return lapic_vector_set_in_irr(vector) || pi_pending_this_cpu(vector);
501504
}
502505

506+
#define MAX_APIC_VECTOR 256
507+
#define APIC_VECTORS_PER_REG 32
508+
509+
/*
510+
* Vector states are maintained by APIC in 32-bit registers that are
511+
* 16 bytes aligned. The status of each vector is kept in a single
512+
* bit.
513+
*/
514+
static inline int apic_find_highest_vector(void *bitmap)
515+
{
516+
int vec;
517+
u32 *reg;
518+
519+
for (vec = MAX_APIC_VECTOR - APIC_VECTORS_PER_REG; vec >= 0; vec -= APIC_VECTORS_PER_REG) {
520+
reg = bitmap + APIC_VECTOR_TO_REG_OFFSET(vec);
521+
if (*reg)
522+
return __fls(*reg) + vec;
523+
}
524+
525+
return -1;
526+
}
527+
528+
static inline u32 apic_get_reg(void *regs, int reg)
529+
{
530+
return *((u32 *) (regs + reg));
531+
}
532+
533+
static inline void apic_set_reg(void *regs, int reg, u32 val)
534+
{
535+
*((u32 *) (regs + reg)) = val;
536+
}
537+
538+
static __always_inline u64 apic_get_reg64(void *regs, int reg)
539+
{
540+
BUILD_BUG_ON(reg != APIC_ICR);
541+
return *((u64 *) (regs + reg));
542+
}
543+
544+
static __always_inline void apic_set_reg64(void *regs, int reg, u64 val)
545+
{
546+
BUILD_BUG_ON(reg != APIC_ICR);
547+
*((u64 *) (regs + reg)) = val;
548+
}
549+
550+
static inline void apic_clear_vector(int vec, void *bitmap)
551+
{
552+
clear_bit(APIC_VECTOR_TO_BIT_NUMBER(vec), bitmap + APIC_VECTOR_TO_REG_OFFSET(vec));
553+
}
554+
555+
static inline void apic_set_vector(int vec, void *bitmap)
556+
{
557+
set_bit(APIC_VECTOR_TO_BIT_NUMBER(vec), bitmap + APIC_VECTOR_TO_REG_OFFSET(vec));
558+
}
559+
560+
static inline int apic_test_vector(int vec, void *bitmap)
561+
{
562+
return test_bit(APIC_VECTOR_TO_BIT_NUMBER(vec), bitmap + APIC_VECTOR_TO_REG_OFFSET(vec));
563+
}
564+
503565
/*
504566
* Warm reset vector position:
505567
*/

arch/x86/kvm/lapic.c

Lines changed: 26 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include <linux/export.h>
2828
#include <linux/math64.h>
2929
#include <linux/slab.h>
30+
#include <asm/apic.h>
3031
#include <asm/processor.h>
3132
#include <asm/mce.h>
3233
#include <asm/msr.h>
@@ -55,9 +56,6 @@
5556
/* 14 is the version for Xeon and Pentium 8.4.8*/
5657
#define APIC_VERSION 0x14UL
5758
#define LAPIC_MMIO_LENGTH (1 << 12)
58-
/* followed define is not in apicdef.h */
59-
#define MAX_APIC_VECTOR 256
60-
#define APIC_VECTORS_PER_REG 32
6159

6260
/*
6361
* Enable local APIC timer advancement (tscdeadline mode only) with adaptive
@@ -79,42 +77,20 @@ module_param(lapic_timer_advance, bool, 0444);
7977
static int kvm_lapic_msr_read(struct kvm_lapic *apic, u32 reg, u64 *data);
8078
static int kvm_lapic_msr_write(struct kvm_lapic *apic, u32 reg, u64 data);
8179

82-
static inline void __kvm_lapic_set_reg(char *regs, int reg_off, u32 val)
83-
{
84-
*((u32 *) (regs + reg_off)) = val;
85-
}
86-
8780
static inline void kvm_lapic_set_reg(struct kvm_lapic *apic, int reg_off, u32 val)
8881
{
89-
__kvm_lapic_set_reg(apic->regs, reg_off, val);
90-
}
91-
92-
static __always_inline u64 __kvm_lapic_get_reg64(char *regs, int reg)
93-
{
94-
BUILD_BUG_ON(reg != APIC_ICR);
95-
return *((u64 *) (regs + reg));
82+
apic_set_reg(apic->regs, reg_off, val);
9683
}
9784

9885
static __always_inline u64 kvm_lapic_get_reg64(struct kvm_lapic *apic, int reg)
9986
{
100-
return __kvm_lapic_get_reg64(apic->regs, reg);
101-
}
102-
103-
static __always_inline void __kvm_lapic_set_reg64(char *regs, int reg, u64 val)
104-
{
105-
BUILD_BUG_ON(reg != APIC_ICR);
106-
*((u64 *) (regs + reg)) = val;
87+
return apic_get_reg64(apic->regs, reg);
10788
}
10889

10990
static __always_inline void kvm_lapic_set_reg64(struct kvm_lapic *apic,
11091
int reg, u64 val)
11192
{
112-
__kvm_lapic_set_reg64(apic->regs, reg, val);
113-
}
114-
115-
static inline int apic_test_vector(int vec, void *bitmap)
116-
{
117-
return test_bit(VEC_POS(vec), (bitmap) + REG_POS(vec));
93+
apic_set_reg64(apic->regs, reg, val);
11894
}
11995

12096
bool kvm_apic_pending_eoi(struct kvm_vcpu *vcpu, int vector)
@@ -125,16 +101,6 @@ bool kvm_apic_pending_eoi(struct kvm_vcpu *vcpu, int vector)
125101
apic_test_vector(vector, apic->regs + APIC_IRR);
126102
}
127103

128-
static inline int __apic_test_and_set_vector(int vec, void *bitmap)
129-
{
130-
return __test_and_set_bit(VEC_POS(vec), (bitmap) + REG_POS(vec));
131-
}
132-
133-
static inline int __apic_test_and_clear_vector(int vec, void *bitmap)
134-
{
135-
return __test_and_clear_bit(VEC_POS(vec), (bitmap) + REG_POS(vec));
136-
}
137-
138104
__read_mostly DEFINE_STATIC_KEY_FALSE(kvm_has_noapic_vcpu);
139105
EXPORT_SYMBOL_GPL(kvm_has_noapic_vcpu);
140106

@@ -626,29 +592,14 @@ static const unsigned int apic_lvt_mask[KVM_APIC_MAX_NR_LVT_ENTRIES] = {
626592
[LVT_CMCI] = LVT_MASK | APIC_MODE_MASK
627593
};
628594

629-
static int find_highest_vector(void *bitmap)
630-
{
631-
int vec;
632-
u32 *reg;
633-
634-
for (vec = MAX_APIC_VECTOR - APIC_VECTORS_PER_REG;
635-
vec >= 0; vec -= APIC_VECTORS_PER_REG) {
636-
reg = bitmap + REG_POS(vec);
637-
if (*reg)
638-
return __fls(*reg) + vec;
639-
}
640-
641-
return -1;
642-
}
643-
644595
static u8 count_vectors(void *bitmap)
645596
{
646597
int vec;
647598
u32 *reg;
648599
u8 count = 0;
649600

650601
for (vec = 0; vec < MAX_APIC_VECTOR; vec += APIC_VECTORS_PER_REG) {
651-
reg = bitmap + REG_POS(vec);
602+
reg = bitmap + APIC_VECTOR_TO_REG_OFFSET(vec);
652603
count += hweight32(*reg);
653604
}
654605

@@ -706,7 +657,7 @@ EXPORT_SYMBOL_GPL(kvm_apic_update_irr);
706657

707658
static inline int apic_search_irr(struct kvm_lapic *apic)
708659
{
709-
return find_highest_vector(apic->regs + APIC_IRR);
660+
return apic_find_highest_vector(apic->regs + APIC_IRR);
710661
}
711662

712663
static inline int apic_find_highest_irr(struct kvm_lapic *apic)
@@ -729,10 +680,10 @@ static inline int apic_find_highest_irr(struct kvm_lapic *apic)
729680
static inline void apic_clear_irr(int vec, struct kvm_lapic *apic)
730681
{
731682
if (unlikely(apic->apicv_active)) {
732-
kvm_lapic_clear_vector(vec, apic->regs + APIC_IRR);
683+
apic_clear_vector(vec, apic->regs + APIC_IRR);
733684
} else {
734685
apic->irr_pending = false;
735-
kvm_lapic_clear_vector(vec, apic->regs + APIC_IRR);
686+
apic_clear_vector(vec, apic->regs + APIC_IRR);
736687
if (apic_search_irr(apic) != -1)
737688
apic->irr_pending = true;
738689
}
@@ -744,9 +695,15 @@ void kvm_apic_clear_irr(struct kvm_vcpu *vcpu, int vec)
744695
}
745696
EXPORT_SYMBOL_GPL(kvm_apic_clear_irr);
746697

698+
static void *apic_vector_to_isr(int vec, struct kvm_lapic *apic)
699+
{
700+
return apic->regs + APIC_ISR + APIC_VECTOR_TO_REG_OFFSET(vec);
701+
}
702+
747703
static inline void apic_set_isr(int vec, struct kvm_lapic *apic)
748704
{
749-
if (__apic_test_and_set_vector(vec, apic->regs + APIC_ISR))
705+
if (__test_and_set_bit(APIC_VECTOR_TO_BIT_NUMBER(vec),
706+
apic_vector_to_isr(vec, apic)))
750707
return;
751708

752709
/*
@@ -781,15 +738,16 @@ static inline int apic_find_highest_isr(struct kvm_lapic *apic)
781738
if (likely(apic->highest_isr_cache != -1))
782739
return apic->highest_isr_cache;
783740

784-
result = find_highest_vector(apic->regs + APIC_ISR);
741+
result = apic_find_highest_vector(apic->regs + APIC_ISR);
785742
ASSERT(result == -1 || result >= 16);
786743

787744
return result;
788745
}
789746

790747
static inline void apic_clear_isr(int vec, struct kvm_lapic *apic)
791748
{
792-
if (!__apic_test_and_clear_vector(vec, apic->regs + APIC_ISR))
749+
if (!__test_and_clear_bit(APIC_VECTOR_TO_BIT_NUMBER(vec),
750+
apic_vector_to_isr(vec, apic)))
793751
return;
794752

795753
/*
@@ -1332,11 +1290,9 @@ static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode,
13321290

13331291
if (apic_test_vector(vector, apic->regs + APIC_TMR) != !!trig_mode) {
13341292
if (trig_mode)
1335-
kvm_lapic_set_vector(vector,
1336-
apic->regs + APIC_TMR);
1293+
apic_set_vector(vector, apic->regs + APIC_TMR);
13371294
else
1338-
kvm_lapic_clear_vector(vector,
1339-
apic->regs + APIC_TMR);
1295+
apic_clear_vector(vector, apic->regs + APIC_TMR);
13401296
}
13411297

13421298
kvm_x86_call(deliver_interrupt)(apic, delivery_mode,
@@ -3086,12 +3042,12 @@ static int kvm_apic_state_fixup(struct kvm_vcpu *vcpu,
30863042

30873043
if (!kvm_x86_ops.x2apic_icr_is_split) {
30883044
if (set) {
3089-
icr = __kvm_lapic_get_reg(s->regs, APIC_ICR) |
3090-
(u64)__kvm_lapic_get_reg(s->regs, APIC_ICR2) << 32;
3091-
__kvm_lapic_set_reg64(s->regs, APIC_ICR, icr);
3045+
icr = apic_get_reg(s->regs, APIC_ICR) |
3046+
(u64)apic_get_reg(s->regs, APIC_ICR2) << 32;
3047+
apic_set_reg64(s->regs, APIC_ICR, icr);
30923048
} else {
3093-
icr = __kvm_lapic_get_reg64(s->regs, APIC_ICR);
3094-
__kvm_lapic_set_reg(s->regs, APIC_ICR2, icr >> 32);
3049+
icr = apic_get_reg64(s->regs, APIC_ICR);
3050+
apic_set_reg(s->regs, APIC_ICR2, icr >> 32);
30953051
}
30963052
}
30973053
}
@@ -3107,8 +3063,7 @@ int kvm_apic_get_state(struct kvm_vcpu *vcpu, struct kvm_lapic_state *s)
31073063
* Get calculated timer current count for remaining timer period (if
31083064
* any) and store it in the returned register set.
31093065
*/
3110-
__kvm_lapic_set_reg(s->regs, APIC_TMCCT,
3111-
__apic_read(vcpu->arch.apic, APIC_TMCCT));
3066+
apic_set_reg(s->regs, APIC_TMCCT, __apic_read(vcpu->arch.apic, APIC_TMCCT));
31123067

31133068
return kvm_apic_state_fixup(vcpu, s, false);
31143069
}

arch/x86/kvm/lapic.h

Lines changed: 4 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
#include <kvm/iodev.h>
66

7+
#include <asm/apic.h>
8+
79
#include <linux/kvm_host.h>
810

911
#include "hyperv.h"
@@ -147,37 +149,19 @@ void kvm_lapic_exit(void);
147149

148150
u64 kvm_lapic_readable_reg_mask(struct kvm_lapic *apic);
149151

150-
#define VEC_POS(v) ((v) & (32 - 1))
151-
#define REG_POS(v) (((v) >> 5) << 4)
152-
153-
static inline void kvm_lapic_clear_vector(int vec, void *bitmap)
154-
{
155-
clear_bit(VEC_POS(vec), (bitmap) + REG_POS(vec));
156-
}
157-
158-
static inline void kvm_lapic_set_vector(int vec, void *bitmap)
159-
{
160-
set_bit(VEC_POS(vec), (bitmap) + REG_POS(vec));
161-
}
162-
163152
static inline void kvm_lapic_set_irr(int vec, struct kvm_lapic *apic)
164153
{
165-
kvm_lapic_set_vector(vec, apic->regs + APIC_IRR);
154+
apic_set_vector(vec, apic->regs + APIC_IRR);
166155
/*
167156
* irr_pending must be true if any interrupt is pending; set it after
168157
* APIC_IRR to avoid race with apic_clear_irr
169158
*/
170159
apic->irr_pending = true;
171160
}
172161

173-
static inline u32 __kvm_lapic_get_reg(char *regs, int reg_off)
174-
{
175-
return *((u32 *) (regs + reg_off));
176-
}
177-
178162
static inline u32 kvm_lapic_get_reg(struct kvm_lapic *apic, int reg_off)
179163
{
180-
return __kvm_lapic_get_reg(apic->regs, reg_off);
164+
return apic_get_reg(apic->regs, reg_off);
181165
}
182166

183167
DECLARE_STATIC_KEY_FALSE(kvm_has_noapic_vcpu);

0 commit comments

Comments
 (0)