Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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.

+94 -93
+64 -2
arch/x86/include/asm/apic.h
··· 488 488 489 489 extern void apic_ack_irq(struct irq_data *data); 490 490 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 + 491 494 static inline bool lapic_vector_set_in_irr(unsigned int vector) 492 495 { 493 - u32 irr = apic_read(APIC_IRR + (vector / 32 * 0x10)); 496 + u32 irr = apic_read(APIC_IRR + APIC_VECTOR_TO_REG_OFFSET(vector)); 494 497 495 - return !!(irr & (1U << (vector % 32))); 498 + return !!(irr & (1U << APIC_VECTOR_TO_BIT_NUMBER(vector))); 496 499 } 497 500 498 501 static inline bool is_vector_pending(unsigned int vector) 499 502 { 500 503 return lapic_vector_set_in_irr(vector) || pi_pending_this_cpu(vector); 504 + } 505 + 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)); 501 563 } 502 564 503 565 /*
+26 -71
arch/x86/kvm/lapic.c
··· 27 27 #include <linux/export.h> 28 28 #include <linux/math64.h> 29 29 #include <linux/slab.h> 30 + #include <asm/apic.h> 30 31 #include <asm/processor.h> 31 32 #include <asm/mce.h> 32 33 #include <asm/msr.h> ··· 56 55 /* 14 is the version for Xeon and Pentium 8.4.8*/ 57 56 #define APIC_VERSION 0x14UL 58 57 #define LAPIC_MMIO_LENGTH (1 << 12) 59 - /* followed define is not in apicdef.h */ 60 - #define MAX_APIC_VECTOR 256 61 - #define APIC_VECTORS_PER_REG 32 62 58 63 59 /* 64 60 * Enable local APIC timer advancement (tscdeadline mode only) with adaptive ··· 77 79 static int kvm_lapic_msr_read(struct kvm_lapic *apic, u32 reg, u64 *data); 78 80 static int kvm_lapic_msr_write(struct kvm_lapic *apic, u32 reg, u64 data); 79 81 80 - static inline void __kvm_lapic_set_reg(char *regs, int reg_off, u32 val) 81 - { 82 - *((u32 *) (regs + reg_off)) = val; 83 - } 84 - 85 82 static inline void kvm_lapic_set_reg(struct kvm_lapic *apic, int reg_off, u32 val) 86 83 { 87 - __kvm_lapic_set_reg(apic->regs, reg_off, val); 88 - } 89 - 90 - static __always_inline u64 __kvm_lapic_get_reg64(char *regs, int reg) 91 - { 92 - BUILD_BUG_ON(reg != APIC_ICR); 93 - return *((u64 *) (regs + reg)); 84 + apic_set_reg(apic->regs, reg_off, val); 94 85 } 95 86 96 87 static __always_inline u64 kvm_lapic_get_reg64(struct kvm_lapic *apic, int reg) 97 88 { 98 - return __kvm_lapic_get_reg64(apic->regs, reg); 99 - } 100 - 101 - static __always_inline void __kvm_lapic_set_reg64(char *regs, int reg, u64 val) 102 - { 103 - BUILD_BUG_ON(reg != APIC_ICR); 104 - *((u64 *) (regs + reg)) = val; 89 + return apic_get_reg64(apic->regs, reg); 105 90 } 106 91 107 92 static __always_inline void kvm_lapic_set_reg64(struct kvm_lapic *apic, 108 93 int reg, u64 val) 109 94 { 110 - __kvm_lapic_set_reg64(apic->regs, reg, val); 111 - } 112 - 113 - static inline int apic_test_vector(int vec, void *bitmap) 114 - { 115 - return test_bit(VEC_POS(vec), (bitmap) + REG_POS(vec)); 95 + apic_set_reg64(apic->regs, reg, val); 116 96 } 117 97 118 98 bool kvm_apic_pending_eoi(struct kvm_vcpu *vcpu, int vector) ··· 99 123 100 124 return apic_test_vector(vector, apic->regs + APIC_ISR) || 101 125 apic_test_vector(vector, apic->regs + APIC_IRR); 102 - } 103 - 104 - static inline int __apic_test_and_set_vector(int vec, void *bitmap) 105 - { 106 - return __test_and_set_bit(VEC_POS(vec), (bitmap) + REG_POS(vec)); 107 - } 108 - 109 - static inline int __apic_test_and_clear_vector(int vec, void *bitmap) 110 - { 111 - return __test_and_clear_bit(VEC_POS(vec), (bitmap) + REG_POS(vec)); 112 126 } 113 127 114 128 __read_mostly DEFINE_STATIC_KEY_FALSE(kvm_has_noapic_vcpu); ··· 592 626 [LVT_CMCI] = LVT_MASK | APIC_MODE_MASK 593 627 }; 594 628 595 - static int find_highest_vector(void *bitmap) 596 - { 597 - int vec; 598 - u32 *reg; 599 - 600 - for (vec = MAX_APIC_VECTOR - APIC_VECTORS_PER_REG; 601 - vec >= 0; vec -= APIC_VECTORS_PER_REG) { 602 - reg = bitmap + REG_POS(vec); 603 - if (*reg) 604 - return __fls(*reg) + vec; 605 - } 606 - 607 - return -1; 608 - } 609 - 610 629 static u8 count_vectors(void *bitmap) 611 630 { 612 631 int vec; ··· 599 648 u8 count = 0; 600 649 601 650 for (vec = 0; vec < MAX_APIC_VECTOR; vec += APIC_VECTORS_PER_REG) { 602 - reg = bitmap + REG_POS(vec); 651 + reg = bitmap + APIC_VECTOR_TO_REG_OFFSET(vec); 603 652 count += hweight32(*reg); 604 653 } 605 654 ··· 657 706 658 707 static inline int apic_search_irr(struct kvm_lapic *apic) 659 708 { 660 - return find_highest_vector(apic->regs + APIC_IRR); 709 + return apic_find_highest_vector(apic->regs + APIC_IRR); 661 710 } 662 711 663 712 static inline int apic_find_highest_irr(struct kvm_lapic *apic) ··· 680 729 static inline void apic_clear_irr(int vec, struct kvm_lapic *apic) 681 730 { 682 731 if (unlikely(apic->apicv_active)) { 683 - kvm_lapic_clear_vector(vec, apic->regs + APIC_IRR); 732 + apic_clear_vector(vec, apic->regs + APIC_IRR); 684 733 } else { 685 734 apic->irr_pending = false; 686 - kvm_lapic_clear_vector(vec, apic->regs + APIC_IRR); 735 + apic_clear_vector(vec, apic->regs + APIC_IRR); 687 736 if (apic_search_irr(apic) != -1) 688 737 apic->irr_pending = true; 689 738 } ··· 695 744 } 696 745 EXPORT_SYMBOL_GPL(kvm_apic_clear_irr); 697 746 747 + static void *apic_vector_to_isr(int vec, struct kvm_lapic *apic) 748 + { 749 + return apic->regs + APIC_ISR + APIC_VECTOR_TO_REG_OFFSET(vec); 750 + } 751 + 698 752 static inline void apic_set_isr(int vec, struct kvm_lapic *apic) 699 753 { 700 - if (__apic_test_and_set_vector(vec, apic->regs + APIC_ISR)) 754 + if (__test_and_set_bit(APIC_VECTOR_TO_BIT_NUMBER(vec), 755 + apic_vector_to_isr(vec, apic))) 701 756 return; 702 757 703 758 /* ··· 738 781 if (likely(apic->highest_isr_cache != -1)) 739 782 return apic->highest_isr_cache; 740 783 741 - result = find_highest_vector(apic->regs + APIC_ISR); 784 + result = apic_find_highest_vector(apic->regs + APIC_ISR); 742 785 ASSERT(result == -1 || result >= 16); 743 786 744 787 return result; ··· 746 789 747 790 static inline void apic_clear_isr(int vec, struct kvm_lapic *apic) 748 791 { 749 - if (!__apic_test_and_clear_vector(vec, apic->regs + APIC_ISR)) 792 + if (!__test_and_clear_bit(APIC_VECTOR_TO_BIT_NUMBER(vec), 793 + apic_vector_to_isr(vec, apic))) 750 794 return; 751 795 752 796 /* ··· 1290 1332 1291 1333 if (apic_test_vector(vector, apic->regs + APIC_TMR) != !!trig_mode) { 1292 1334 if (trig_mode) 1293 - kvm_lapic_set_vector(vector, 1294 - apic->regs + APIC_TMR); 1335 + apic_set_vector(vector, apic->regs + APIC_TMR); 1295 1336 else 1296 - kvm_lapic_clear_vector(vector, 1297 - apic->regs + APIC_TMR); 1337 + apic_clear_vector(vector, apic->regs + APIC_TMR); 1298 1338 } 1299 1339 1300 1340 kvm_x86_call(deliver_interrupt)(apic, delivery_mode, ··· 3042 3086 3043 3087 if (!kvm_x86_ops.x2apic_icr_is_split) { 3044 3088 if (set) { 3045 - icr = __kvm_lapic_get_reg(s->regs, APIC_ICR) | 3046 - (u64)__kvm_lapic_get_reg(s->regs, APIC_ICR2) << 32; 3047 - __kvm_lapic_set_reg64(s->regs, APIC_ICR, icr); 3089 + icr = apic_get_reg(s->regs, APIC_ICR) | 3090 + (u64)apic_get_reg(s->regs, APIC_ICR2) << 32; 3091 + apic_set_reg64(s->regs, APIC_ICR, icr); 3048 3092 } else { 3049 - icr = __kvm_lapic_get_reg64(s->regs, APIC_ICR); 3050 - __kvm_lapic_set_reg(s->regs, APIC_ICR2, icr >> 32); 3093 + icr = apic_get_reg64(s->regs, APIC_ICR); 3094 + apic_set_reg(s->regs, APIC_ICR2, icr >> 32); 3051 3095 } 3052 3096 } 3053 3097 } ··· 3063 3107 * Get calculated timer current count for remaining timer period (if 3064 3108 * any) and store it in the returned register set. 3065 3109 */ 3066 - __kvm_lapic_set_reg(s->regs, APIC_TMCCT, 3067 - __apic_read(vcpu->arch.apic, APIC_TMCCT)); 3110 + apic_set_reg(s->regs, APIC_TMCCT, __apic_read(vcpu->arch.apic, APIC_TMCCT)); 3068 3111 3069 3112 return kvm_apic_state_fixup(vcpu, s, false); 3070 3113 }
+4 -20
arch/x86/kvm/lapic.h
··· 4 4 5 5 #include <kvm/iodev.h> 6 6 7 + #include <asm/apic.h> 8 + 7 9 #include <linux/kvm_host.h> 8 10 9 11 #include "hyperv.h" ··· 149 147 150 148 u64 kvm_lapic_readable_reg_mask(struct kvm_lapic *apic); 151 149 152 - #define VEC_POS(v) ((v) & (32 - 1)) 153 - #define REG_POS(v) (((v) >> 5) << 4) 154 - 155 - static inline void kvm_lapic_clear_vector(int vec, void *bitmap) 156 - { 157 - clear_bit(VEC_POS(vec), (bitmap) + REG_POS(vec)); 158 - } 159 - 160 - static inline void kvm_lapic_set_vector(int vec, void *bitmap) 161 - { 162 - set_bit(VEC_POS(vec), (bitmap) + REG_POS(vec)); 163 - } 164 - 165 150 static inline void kvm_lapic_set_irr(int vec, struct kvm_lapic *apic) 166 151 { 167 - kvm_lapic_set_vector(vec, apic->regs + APIC_IRR); 152 + apic_set_vector(vec, apic->regs + APIC_IRR); 168 153 /* 169 154 * irr_pending must be true if any interrupt is pending; set it after 170 155 * APIC_IRR to avoid race with apic_clear_irr ··· 159 170 apic->irr_pending = true; 160 171 } 161 172 162 - static inline u32 __kvm_lapic_get_reg(char *regs, int reg_off) 163 - { 164 - return *((u32 *) (regs + reg_off)); 165 - } 166 - 167 173 static inline u32 kvm_lapic_get_reg(struct kvm_lapic *apic, int reg_off) 168 174 { 169 - return __kvm_lapic_get_reg(apic->regs, reg_off); 175 + return apic_get_reg(apic->regs, reg_off); 170 176 } 171 177 172 178 DECLARE_STATIC_KEY_FALSE(kvm_has_noapic_vcpu);