Skip to content

Commit f145931

Browse files
committed
x86/irq: KVM: Track PIR bitmap as an "unsigned long" array
Track the PIR bitmap in posted interrupt descriptor structures as an array of unsigned longs instead of using unionized arrays for KVM (u32s) versus IRQ management (u64s). In practice, because the non-KVM usage is (sanely) restricted to 64-bit kernels, all existing usage of the u64 variant is already working with unsigned longs. Using "unsigned long" for the array will allow reworking KVM's processing of the bitmap to read/write in 64-bit chunks on 64-bit kernels, i.e. will allow optimizing KVM by reducing the number of atomic accesses to PIR. Opportunstically replace the open coded literals in the posted MSIs code with the appropriate macro. Deliberately don't use ARRAY_SIZE() in the for-loops, even though it would be cleaner from a certain perspective, in anticipation of decoupling the processing from the array declaration. No functional change intended. Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Sean Christopherson <[email protected]>
1 parent 6433fc0 commit f145931

File tree

5 files changed

+21
-20
lines changed

5 files changed

+21
-20
lines changed

arch/x86/include/asm/posted_intr.h

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,12 @@
88

99
#define PID_TABLE_ENTRY_VALID 1
1010

11+
#define NR_PIR_VECTORS 256
12+
#define NR_PIR_WORDS (NR_PIR_VECTORS / BITS_PER_LONG)
13+
1114
/* Posted-Interrupt Descriptor */
1215
struct pi_desc {
13-
union {
14-
u32 pir[8]; /* Posted interrupt requested */
15-
u64 pir64[4];
16-
};
16+
unsigned long pir[NR_PIR_WORDS]; /* Posted interrupt requested */
1717
union {
1818
struct {
1919
u16 notifications; /* Suppress and outstanding bits */
@@ -43,12 +43,12 @@ static inline bool pi_test_and_clear_sn(struct pi_desc *pi_desc)
4343

4444
static inline bool pi_test_and_set_pir(int vector, struct pi_desc *pi_desc)
4545
{
46-
return test_and_set_bit(vector, (unsigned long *)pi_desc->pir);
46+
return test_and_set_bit(vector, pi_desc->pir);
4747
}
4848

4949
static inline bool pi_is_pir_empty(struct pi_desc *pi_desc)
5050
{
51-
return bitmap_empty((unsigned long *)pi_desc->pir, NR_VECTORS);
51+
return bitmap_empty(pi_desc->pir, NR_VECTORS);
5252
}
5353

5454
static inline void pi_set_sn(struct pi_desc *pi_desc)
@@ -110,7 +110,7 @@ static inline bool pi_pending_this_cpu(unsigned int vector)
110110
if (WARN_ON_ONCE(vector > NR_VECTORS || vector < FIRST_EXTERNAL_VECTOR))
111111
return false;
112112

113-
return test_bit(vector, (unsigned long *)pid->pir);
113+
return test_bit(vector, pid->pir);
114114
}
115115

116116
extern void intel_posted_msi_init(void);

arch/x86/kernel/irq.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -412,20 +412,20 @@ void intel_posted_msi_init(void)
412412
* instead of:
413413
* read, xchg, read, xchg, read, xchg, read, xchg
414414
*/
415-
static __always_inline bool handle_pending_pir(u64 *pir, struct pt_regs *regs)
415+
static __always_inline bool handle_pending_pir(unsigned long *pir, struct pt_regs *regs)
416416
{
417-
unsigned long pir_copy[4], pending = 0;
417+
unsigned long pir_copy[NR_PIR_WORDS], pending = 0;
418418
int i, vec = FIRST_EXTERNAL_VECTOR;
419419

420-
for (i = 0; i < 4; i++) {
420+
for (i = 0; i < NR_PIR_WORDS; i++) {
421421
pir_copy[i] = READ_ONCE(pir[i]);
422422
pending |= pir_copy[i];
423423
}
424424

425425
if (!pending)
426426
return false;
427427

428-
for (i = 0; i < 4; i++) {
428+
for (i = 0; i < NR_PIR_WORDS; i++) {
429429
if (!pir_copy[i])
430430
continue;
431431

@@ -465,7 +465,7 @@ DEFINE_IDTENTRY_SYSVEC(sysvec_posted_msi_notification)
465465
* MAX_POSTED_MSI_COALESCING_LOOP - 1 loops are executed here.
466466
*/
467467
while (++i < MAX_POSTED_MSI_COALESCING_LOOP) {
468-
if (!handle_pending_pir(pid->pir64, regs))
468+
if (!handle_pending_pir(pid->pir, regs))
469469
break;
470470
}
471471

@@ -480,7 +480,7 @@ DEFINE_IDTENTRY_SYSVEC(sysvec_posted_msi_notification)
480480
* process PIR bits one last time such that handling the new interrupts
481481
* are not delayed until the next IRQ.
482482
*/
483-
handle_pending_pir(pid->pir64, regs);
483+
handle_pending_pir(pid->pir, regs);
484484

485485
apic_eoi();
486486
irq_exit();

arch/x86/kvm/lapic.c

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -655,8 +655,9 @@ static u8 count_vectors(void *bitmap)
655655
return count;
656656
}
657657

658-
bool __kvm_apic_update_irr(u32 *pir, void *regs, int *max_irr)
658+
bool __kvm_apic_update_irr(unsigned long *pir, void *regs, int *max_irr)
659659
{
660+
u32 *__pir = (void *)pir;
660661
u32 i, vec;
661662
u32 pir_val, irr_val, prev_irr_val;
662663
int max_updated_irr;
@@ -668,10 +669,10 @@ bool __kvm_apic_update_irr(u32 *pir, void *regs, int *max_irr)
668669
u32 *p_irr = (u32 *)(regs + APIC_IRR + i * 0x10);
669670

670671
irr_val = READ_ONCE(*p_irr);
671-
pir_val = READ_ONCE(pir[i]);
672+
pir_val = READ_ONCE(__pir[i]);
672673

673674
if (pir_val) {
674-
pir_val = xchg(&pir[i], 0);
675+
pir_val = xchg(&__pir[i], 0);
675676

676677
prev_irr_val = irr_val;
677678
do {
@@ -691,7 +692,7 @@ bool __kvm_apic_update_irr(u32 *pir, void *regs, int *max_irr)
691692
}
692693
EXPORT_SYMBOL_GPL(__kvm_apic_update_irr);
693694

694-
bool kvm_apic_update_irr(struct kvm_vcpu *vcpu, u32 *pir, int *max_irr)
695+
bool kvm_apic_update_irr(struct kvm_vcpu *vcpu, unsigned long *pir, int *max_irr)
695696
{
696697
struct kvm_lapic *apic = vcpu->arch.apic;
697698
bool irr_updated = __kvm_apic_update_irr(pir, apic->regs, max_irr);

arch/x86/kvm/lapic.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,8 +103,8 @@ bool kvm_apic_match_dest(struct kvm_vcpu *vcpu, struct kvm_lapic *source,
103103
int shorthand, unsigned int dest, int dest_mode);
104104
int kvm_apic_compare_prio(struct kvm_vcpu *vcpu1, struct kvm_vcpu *vcpu2);
105105
void kvm_apic_clear_irr(struct kvm_vcpu *vcpu, int vec);
106-
bool __kvm_apic_update_irr(u32 *pir, void *regs, int *max_irr);
107-
bool kvm_apic_update_irr(struct kvm_vcpu *vcpu, u32 *pir, int *max_irr);
106+
bool __kvm_apic_update_irr(unsigned long *pir, void *regs, int *max_irr);
107+
bool kvm_apic_update_irr(struct kvm_vcpu *vcpu, unsigned long *pir, int *max_irr);
108108
void kvm_apic_update_ppr(struct kvm_vcpu *vcpu);
109109
int kvm_apic_set_irq(struct kvm_vcpu *vcpu, struct kvm_lapic_irq *irq,
110110
struct dest_map *dest_map);

arch/x86/kvm/vmx/posted_intr.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ static inline int pi_find_highest_vector(struct pi_desc *pi_desc)
2020
{
2121
int vec;
2222

23-
vec = find_last_bit((unsigned long *)pi_desc->pir, 256);
23+
vec = find_last_bit(pi_desc->pir, 256);
2424
return vec < 256 ? vec : -1;
2525
}
2626

0 commit comments

Comments
 (0)