1 | Optimizing KVM's PIR harvesting using the same techniques as posted MSIs, | 1 | Optimizing KVM's PIR harvesting using the same techniques as posted MSIs, |
---|---|---|---|
2 | most notably to use 8-byte accesses on 64-bit kernels (/facepalm). | 2 | most notably to use 8-byte accesses on 64-bit kernels (/facepalm). |
3 | 3 | ||
4 | Fix a few warts along the way, and finish up by adding a helper to dedup | 4 | Fix a few warts along the way, and finish up by adding a helper to dedup |
5 | the PIR harvesting code between KVM and posted MSIs. | 5 | the PIR harvesting code between KVM and posted MSIs. |
6 | |||
7 | v2: | ||
8 | - Collect a review. [tglx] | ||
9 | - Use an "unsigned long" with a bitwise-OR to gather PIR. [tglx] | ||
10 | |||
11 | v1: https://lore.kernel.org/all/20250315030630.2371712-1-seanjc@google.com | ||
6 | 12 | ||
7 | Sean Christopherson (8): | 13 | Sean Christopherson (8): |
8 | x86/irq: Ensure initial PIR loads are performed exactly once | 14 | x86/irq: Ensure initial PIR loads are performed exactly once |
9 | x86/irq: Track if IRQ was found in PIR during initial loop (to load | 15 | x86/irq: Track if IRQ was found in PIR during initial loop (to load |
10 | PIR vals) | 16 | PIR vals) |
... | ... | ||
14 | KVM: VMX: Isolate pure loads from atomic XCHG when processing PIR | 20 | KVM: VMX: Isolate pure loads from atomic XCHG when processing PIR |
15 | KVM: VMX: Use arch_xchg() when processing PIR to avoid instrumentation | 21 | KVM: VMX: Use arch_xchg() when processing PIR to avoid instrumentation |
16 | x86/irq: KVM: Add helper for harvesting PIR to deduplicate KVM and | 22 | x86/irq: KVM: Add helper for harvesting PIR to deduplicate KVM and |
17 | posted MSIs | 23 | posted MSIs |
18 | 24 | ||
19 | arch/x86/include/asm/posted_intr.h | 79 +++++++++++++++++++++++++++--- | 25 | arch/x86/include/asm/posted_intr.h | 78 +++++++++++++++++++++++++++--- |
20 | arch/x86/kernel/irq.c | 63 ++++-------------------- | 26 | arch/x86/kernel/irq.c | 63 ++++-------------------- |
21 | arch/x86/kvm/lapic.c | 20 ++++---- | 27 | arch/x86/kvm/lapic.c | 20 ++++---- |
22 | arch/x86/kvm/lapic.h | 4 +- | 28 | arch/x86/kvm/lapic.h | 4 +- |
23 | arch/x86/kvm/vmx/posted_intr.h | 2 +- | 29 | arch/x86/kvm/vmx/posted_intr.h | 2 +- |
24 | 5 files changed, 96 insertions(+), 72 deletions(-) | 30 | 5 files changed, 95 insertions(+), 72 deletions(-) |
25 | 31 | ||
26 | 32 | ||
27 | base-commit: c9ea48bb6ee6b28bbc956c1e8af98044618fed5e | 33 | base-commit: 782f9feaa9517caf33186dcdd6b50a8f770ed29b |
28 | -- | 34 | -- |
29 | 2.49.0.rc1.451.g8f38331e32-goog | 35 | 2.49.0.472.ge94155a9ec-goog | diff view generated by jsdifflib |
1 | Ensure the PIR is read exactly once at the start of handle_pending_pir(), | 1 | Ensure the PIR is read exactly once at the start of handle_pending_pir(), |
---|---|---|---|
2 | to guarantee that checking for an outstanding posted interrupt in a given | 2 | to guarantee that checking for an outstanding posted interrupt in a given |
3 | chuck doesn't reload the chunk from the "real" PIR. Functionally, a reload | 3 | chuck doesn't reload the chunk from the "real" PIR. Functionally, a reload |
4 | is benign, but it would defeat the purpose of pre-loading into a copy. | 4 | is benign, but it would defeat the purpose of pre-loading into a copy. |
5 | 5 | ||
6 | Fixes: 1b03d82ba15e ("x86/irq: Install posted MSI notification handler") | 6 | Fixes: 1b03d82ba15e ("x86/irq: Install posted MSI notification handler") |
7 | Cc: Jacob Pan <jacob.jun.pan@linux.intel.com> | 7 | Reviewed-by: Thomas Gleixner <tglx@linutronix.de> |
8 | Signed-off-by: Sean Christopherson <seanjc@google.com> | 8 | Signed-off-by: Sean Christopherson <seanjc@google.com> |
9 | --- | 9 | --- |
10 | arch/x86/kernel/irq.c | 2 +- | 10 | arch/x86/kernel/irq.c | 2 +- |
11 | 1 file changed, 1 insertion(+), 1 deletion(-) | 11 | 1 file changed, 1 insertion(+), 1 deletion(-) |
12 | 12 | ||
... | ... | ||
22 | + pir_copy[i] = READ_ONCE(pir[i]); | 22 | + pir_copy[i] = READ_ONCE(pir[i]); |
23 | 23 | ||
24 | for (i = 0; i < 4; i++) { | 24 | for (i = 0; i < 4; i++) { |
25 | if (!pir_copy[i]) | 25 | if (!pir_copy[i]) |
26 | -- | 26 | -- |
27 | 2.49.0.rc1.451.g8f38331e32-goog | 27 | 2.49.0.472.ge94155a9ec-goog | diff view generated by jsdifflib |
1 | Track whether or not at least one IRQ was found in PIR during the initial | 1 | Track whether or not at least one IRQ was found in PIR during the initial |
---|---|---|---|
2 | loop to load PIR chunks from memory. Doing so generates slightly better | 2 | loop to load PIR chunks from memory. Doing so generates slightly better |
3 | code (arguably), especially for the case where there are no pending IRQs. | 3 | code (arguably) for processing the for-loop of XCHGs, especially for the |
4 | case where there are no pending IRQs. | ||
4 | 5 | ||
5 | Note, while PIR can be modified between the initial load and the XCHG, it | 6 | Note, while PIR can be modified between the initial load and the XCHG, it |
6 | can only _gain_ new IRQs, i.e. there is no danger of a false positive due | 7 | can only _gain_ new IRQs, i.e. there is no danger of a false positive due |
7 | to the final version of pir_copy[] being empty. | 8 | to the final version of pir_copy[] being empty. |
8 | 9 | ||
9 | Opportunistically rename the boolean in anticipation of moving the PIR | 10 | Opportunistically convert the boolean to an "unsigned long" and compute |
11 | the effective boolean result via bitwise-OR. Some compilers, e.g. | ||
12 | clang-14, need the extra "hint" to elide conditional branches. | ||
13 | |||
14 | Opportunistically rename the variable in anticipation of moving the PIR | ||
10 | accesses to a common helper that can be shared by posted MSIs and KVM. | 15 | accesses to a common helper that can be shared by posted MSIs and KVM. |
11 | 16 | ||
12 | Old: | 17 | Old: |
13 | <+74>: test %rdx,%rdx | 18 | <+74>: test %rdx,%rdx |
14 | <+77>: je 0xffffffff812bbeb0 <handle_pending_pir+144> | 19 | <+77>: je 0xffffffff812bbeb0 <handle_pending_pir+144> |
... | ... | ||
53 | <+144>: je 0xffffffff812bbebd <handle_pending_pir+157> | 58 | <+144>: je 0xffffffff812bbebd <handle_pending_pir+157> |
54 | <pir[3]> | 59 | <pir[3]> |
55 | 60 | ||
56 | Signed-off-by: Sean Christopherson <seanjc@google.com> | 61 | Signed-off-by: Sean Christopherson <seanjc@google.com> |
57 | --- | 62 | --- |
58 | arch/x86/kernel/irq.c | 19 +++++++++++-------- | 63 | arch/x86/kernel/irq.c | 19 ++++++++++--------- |
59 | 1 file changed, 11 insertions(+), 8 deletions(-) | 64 | 1 file changed, 10 insertions(+), 9 deletions(-) |
60 | 65 | ||
61 | diff --git a/arch/x86/kernel/irq.c b/arch/x86/kernel/irq.c | 66 | diff --git a/arch/x86/kernel/irq.c b/arch/x86/kernel/irq.c |
62 | index XXXXXXX..XXXXXXX 100644 | 67 | index XXXXXXX..XXXXXXX 100644 |
63 | --- a/arch/x86/kernel/irq.c | 68 | --- a/arch/x86/kernel/irq.c |
64 | +++ b/arch/x86/kernel/irq.c | 69 | +++ b/arch/x86/kernel/irq.c |
65 | @@ -XXX,XX +XXX,XX @@ static __always_inline bool handle_pending_pir(u64 *pir, struct pt_regs *regs) | 70 | @@ -XXX,XX +XXX,XX @@ void intel_posted_msi_init(void) |
71 | */ | ||
72 | static __always_inline bool handle_pending_pir(u64 *pir, struct pt_regs *regs) | ||
66 | { | 73 | { |
74 | + unsigned long pir_copy[4], pending = 0; | ||
67 | int i, vec = FIRST_EXTERNAL_VECTOR; | 75 | int i, vec = FIRST_EXTERNAL_VECTOR; |
68 | unsigned long pir_copy[4]; | 76 | - unsigned long pir_copy[4]; |
69 | - bool handled = false; | 77 | - bool handled = false; |
70 | + bool found_irq = false; | ||
71 | 78 | ||
72 | - for (i = 0; i < 4; i++) | 79 | - for (i = 0; i < 4; i++) |
73 | + for (i = 0; i < 4; i++) { | 80 | + for (i = 0; i < 4; i++) { |
74 | pir_copy[i] = READ_ONCE(pir[i]); | 81 | pir_copy[i] = READ_ONCE(pir[i]); |
75 | + if (pir_copy[i]) | 82 | + pending |= pir_copy[i]; |
76 | + found_irq = true; | ||
77 | + } | 83 | + } |
78 | + | 84 | + |
79 | + if (!found_irq) | 85 | + if (!pending) |
80 | + return false; | 86 | + return false; |
81 | 87 | ||
82 | for (i = 0; i < 4; i++) { | 88 | for (i = 0; i < 4; i++) { |
83 | if (!pir_copy[i]) | 89 | if (!pir_copy[i]) |
84 | continue; | 90 | continue; |
... | ... | ||
98 | + return true; | 104 | + return true; |
99 | } | 105 | } |
100 | 106 | ||
101 | /* | 107 | /* |
102 | -- | 108 | -- |
103 | 2.49.0.rc1.451.g8f38331e32-goog | 109 | 2.49.0.472.ge94155a9ec-goog | diff view generated by jsdifflib |
... | ... | ||
---|---|---|---|
21 | + irr_val = READ_ONCE(*p_irr); | 21 | + irr_val = READ_ONCE(*p_irr); |
22 | pir_val = READ_ONCE(pir[i]); | 22 | pir_val = READ_ONCE(pir[i]); |
23 | 23 | ||
24 | if (pir_val) { | 24 | if (pir_val) { |
25 | -- | 25 | -- |
26 | 2.49.0.rc1.451.g8f38331e32-goog | 26 | 2.49.0.472.ge94155a9ec-goog | diff view generated by jsdifflib |
... | ... | ||
---|---|---|---|
78 | * read, xchg, read, xchg, read, xchg, read, xchg | 78 | * read, xchg, read, xchg, read, xchg, read, xchg |
79 | */ | 79 | */ |
80 | -static __always_inline bool handle_pending_pir(u64 *pir, struct pt_regs *regs) | 80 | -static __always_inline bool handle_pending_pir(u64 *pir, struct pt_regs *regs) |
81 | +static __always_inline bool handle_pending_pir(unsigned long *pir, struct pt_regs *regs) | 81 | +static __always_inline bool handle_pending_pir(unsigned long *pir, struct pt_regs *regs) |
82 | { | 82 | { |
83 | - unsigned long pir_copy[4], pending = 0; | ||
84 | + unsigned long pir_copy[NR_PIR_WORDS], pending = 0; | ||
83 | int i, vec = FIRST_EXTERNAL_VECTOR; | 85 | int i, vec = FIRST_EXTERNAL_VECTOR; |
84 | - unsigned long pir_copy[4]; | ||
85 | + unsigned long pir_copy[NR_PIR_WORDS]; | ||
86 | bool found_irq = false; | ||
87 | 86 | ||
88 | - for (i = 0; i < 4; i++) { | 87 | - for (i = 0; i < 4; i++) { |
89 | + for (i = 0; i < NR_PIR_WORDS; i++) { | 88 | + for (i = 0; i < NR_PIR_WORDS; i++) { |
90 | pir_copy[i] = READ_ONCE(pir[i]); | 89 | pir_copy[i] = READ_ONCE(pir[i]); |
91 | if (pir_copy[i]) | 90 | pending |= pir_copy[i]; |
92 | found_irq = true; | 91 | } |
93 | @@ -XXX,XX +XXX,XX @@ static __always_inline bool handle_pending_pir(u64 *pir, struct pt_regs *regs) | 92 | @@ -XXX,XX +XXX,XX @@ static __always_inline bool handle_pending_pir(u64 *pir, struct pt_regs *regs) |
94 | if (!found_irq) | 93 | if (!pending) |
95 | return false; | 94 | return false; |
96 | 95 | ||
97 | - for (i = 0; i < 4; i++) { | 96 | - for (i = 0; i < 4; i++) { |
98 | + for (i = 0; i < NR_PIR_WORDS; i++) { | 97 | + for (i = 0; i < NR_PIR_WORDS; i++) { |
99 | if (!pir_copy[i]) | 98 | if (!pir_copy[i]) |
... | ... | ||
181 | + vec = find_last_bit(pi_desc->pir, 256); | 180 | + vec = find_last_bit(pi_desc->pir, 256); |
182 | return vec < 256 ? vec : -1; | 181 | return vec < 256 ? vec : -1; |
183 | } | 182 | } |
184 | 183 | ||
185 | -- | 184 | -- |
186 | 2.49.0.rc1.451.g8f38331e32-goog | 185 | 2.49.0.472.ge94155a9ec-goog | diff view generated by jsdifflib |
... | ... | ||
---|---|---|---|
55 | + irr_val = prev_irr_val | __pir[i]; | 55 | + irr_val = prev_irr_val | __pir[i]; |
56 | } while (prev_irr_val != irr_val && | 56 | } while (prev_irr_val != irr_val && |
57 | !try_cmpxchg(p_irr, &prev_irr_val, irr_val)); | 57 | !try_cmpxchg(p_irr, &prev_irr_val, irr_val)); |
58 | 58 | ||
59 | -- | 59 | -- |
60 | 2.49.0.rc1.451.g8f38331e32-goog | 60 | 2.49.0.472.ge94155a9ec-goog | diff view generated by jsdifflib |
... | ... | ||
---|---|---|---|
13 | why isolating loads from XCHG is desirable. | 13 | why isolating loads from XCHG is desirable. |
14 | 14 | ||
15 | Suggested-by: Jim Mattson <jmattson@google.com> | 15 | Suggested-by: Jim Mattson <jmattson@google.com> |
16 | Signed-off-by: Sean Christopherson <seanjc@google.com> | 16 | Signed-off-by: Sean Christopherson <seanjc@google.com> |
17 | --- | 17 | --- |
18 | arch/x86/kvm/lapic.c | 9 +++++++++ | 18 | arch/x86/kvm/lapic.c | 9 ++++++++- |
19 | 1 file changed, 9 insertions(+) | 19 | 1 file changed, 8 insertions(+), 1 deletion(-) |
20 | 20 | ||
21 | diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c | 21 | diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c |
22 | index XXXXXXX..XXXXXXX 100644 | 22 | index XXXXXXX..XXXXXXX 100644 |
23 | --- a/arch/x86/kvm/lapic.c | 23 | --- a/arch/x86/kvm/lapic.c |
24 | +++ b/arch/x86/kvm/lapic.c | 24 | +++ b/arch/x86/kvm/lapic.c |
25 | @@ -XXX,XX +XXX,XX @@ bool __kvm_apic_update_irr(unsigned long *pir, void *regs, int *max_irr) | 25 | @@ -XXX,XX +XXX,XX @@ static u8 count_vectors(void *bitmap) |
26 | |||
27 | bool __kvm_apic_update_irr(unsigned long *pir, void *regs, int *max_irr) | ||
26 | { | 28 | { |
27 | unsigned long pir_vals[NR_PIR_WORDS]; | 29 | - unsigned long pir_vals[NR_PIR_WORDS]; |
30 | + unsigned long pir_vals[NR_PIR_WORDS], pending = 0; | ||
28 | u32 *__pir = (void *)pir_vals; | 31 | u32 *__pir = (void *)pir_vals; |
29 | + bool found_irq = false; | ||
30 | u32 i, vec; | 32 | u32 i, vec; |
31 | u32 irr_val, prev_irr_val; | 33 | u32 irr_val, prev_irr_val; |
32 | int max_updated_irr; | ||
33 | @@ -XXX,XX +XXX,XX @@ bool __kvm_apic_update_irr(unsigned long *pir, void *regs, int *max_irr) | 34 | @@ -XXX,XX +XXX,XX @@ bool __kvm_apic_update_irr(unsigned long *pir, void *regs, int *max_irr) |
34 | 35 | ||
35 | for (i = 0; i < NR_PIR_WORDS; i++) { | 36 | for (i = 0; i < NR_PIR_WORDS; i++) { |
36 | pir_vals[i] = READ_ONCE(pir[i]); | 37 | pir_vals[i] = READ_ONCE(pir[i]); |
37 | + if (pir_vals[i]) | 38 | + pending |= pir_vals[i]; |
38 | + found_irq = true; | ||
39 | + } | 39 | + } |
40 | + | 40 | + |
41 | + if (!found_irq) | 41 | + if (!pending) |
42 | + return false; | 42 | + return false; |
43 | + | 43 | + |
44 | + for (i = 0; i < NR_PIR_WORDS; i++) { | 44 | + for (i = 0; i < NR_PIR_WORDS; i++) { |
45 | if (!pir_vals[i]) | 45 | if (!pir_vals[i]) |
46 | continue; | 46 | continue; |
47 | 47 | ||
48 | -- | 48 | -- |
49 | 2.49.0.rc1.451.g8f38331e32-goog | 49 | 2.49.0.472.ge94155a9ec-goog | diff view generated by jsdifflib |
... | ... | ||
---|---|---|---|
20 | + pir_vals[i] = arch_xchg(&pir[i], 0); | 20 | + pir_vals[i] = arch_xchg(&pir[i], 0); |
21 | } | 21 | } |
22 | 22 | ||
23 | for (i = vec = 0; i <= 7; i++, vec += 32) { | 23 | for (i = vec = 0; i <= 7; i++, vec += 32) { |
24 | -- | 24 | -- |
25 | 2.49.0.rc1.451.g8f38331e32-goog | 25 | 2.49.0.472.ge94155a9ec-goog | diff view generated by jsdifflib |
... | ... | ||
---|---|---|---|
3 | 3 | ||
4 | No functional change intended. | 4 | No functional change intended. |
5 | 5 | ||
6 | Signed-off-by: Sean Christopherson <seanjc@google.com> | 6 | Signed-off-by: Sean Christopherson <seanjc@google.com> |
7 | --- | 7 | --- |
8 | arch/x86/include/asm/posted_intr.h | 65 ++++++++++++++++++++++++++++++ | 8 | arch/x86/include/asm/posted_intr.h | 64 ++++++++++++++++++++++++++++++ |
9 | arch/x86/kernel/irq.c | 50 +---------------------- | 9 | arch/x86/kernel/irq.c | 50 ++--------------------- |
10 | arch/x86/kvm/lapic.c | 16 +------- | 10 | arch/x86/kvm/lapic.c | 16 +------- |
11 | 3 files changed, 68 insertions(+), 63 deletions(-) | 11 | 3 files changed, 69 insertions(+), 61 deletions(-) |
12 | 12 | ||
13 | diff --git a/arch/x86/include/asm/posted_intr.h b/arch/x86/include/asm/posted_intr.h | 13 | diff --git a/arch/x86/include/asm/posted_intr.h b/arch/x86/include/asm/posted_intr.h |
14 | index XXXXXXX..XXXXXXX 100644 | 14 | index XXXXXXX..XXXXXXX 100644 |
15 | --- a/arch/x86/include/asm/posted_intr.h | 15 | --- a/arch/x86/include/asm/posted_intr.h |
16 | +++ b/arch/x86/include/asm/posted_intr.h | 16 | +++ b/arch/x86/include/asm/posted_intr.h |
... | ... | ||
68 | + * read, xchg, read, xchg, read, xchg, read, xchg | 68 | + * read, xchg, read, xchg, read, xchg, read, xchg |
69 | + */ | 69 | + */ |
70 | +static __always_inline bool pi_harvest_pir(unsigned long *pir, | 70 | +static __always_inline bool pi_harvest_pir(unsigned long *pir, |
71 | + unsigned long *pir_vals) | 71 | + unsigned long *pir_vals) |
72 | +{ | 72 | +{ |
73 | + bool found_irq = false; | 73 | + unsigned long pending = 0; |
74 | + int i; | 74 | + int i; |
75 | + | 75 | + |
76 | + for (i = 0; i < NR_PIR_WORDS; i++) { | 76 | + for (i = 0; i < NR_PIR_WORDS; i++) { |
77 | + pir_vals[i] = READ_ONCE(pir[i]); | 77 | + pir_vals[i] = READ_ONCE(pir[i]); |
78 | + if (pir_vals[i]) | 78 | + pending |= pir_vals[i]; |
79 | + found_irq = true; | ||
80 | + } | 79 | + } |
81 | + | 80 | + |
82 | + if (!found_irq) | 81 | + if (!pending) |
83 | + return false; | 82 | + return false; |
84 | + | 83 | + |
85 | + for (i = 0; i < NR_PIR_WORDS; i++) { | 84 | + for (i = 0; i < NR_PIR_WORDS; i++) { |
86 | + if (!pir_vals[i]) | 85 | + if (!pir_vals[i]) |
87 | + continue; | 86 | + continue; |
... | ... | ||
135 | - * instead of: | 134 | - * instead of: |
136 | - * read, xchg, read, xchg, read, xchg, read, xchg | 135 | - * read, xchg, read, xchg, read, xchg, read, xchg |
137 | - */ | 136 | - */ |
138 | static __always_inline bool handle_pending_pir(unsigned long *pir, struct pt_regs *regs) | 137 | static __always_inline bool handle_pending_pir(unsigned long *pir, struct pt_regs *regs) |
139 | { | 138 | { |
139 | - unsigned long pir_copy[NR_PIR_WORDS], pending = 0; | ||
140 | - int i, vec = FIRST_EXTERNAL_VECTOR; | 140 | - int i, vec = FIRST_EXTERNAL_VECTOR; |
141 | + unsigned long pir_copy[NR_PIR_WORDS]; | ||
141 | + int vec = FIRST_EXTERNAL_VECTOR; | 142 | + int vec = FIRST_EXTERNAL_VECTOR; |
142 | unsigned long pir_copy[NR_PIR_WORDS]; | ||
143 | - bool found_irq = false; | ||
144 | 143 | ||
145 | - for (i = 0; i < NR_PIR_WORDS; i++) { | 144 | - for (i = 0; i < NR_PIR_WORDS; i++) { |
146 | - pir_copy[i] = READ_ONCE(pir[i]); | 145 | - pir_copy[i] = READ_ONCE(pir[i]); |
147 | - if (pir_copy[i]) | 146 | - pending |= pir_copy[i]; |
148 | - found_irq = true; | 147 | - } |
149 | - } | 148 | - |
150 | - | 149 | - if (!pending) |
151 | - if (!found_irq) | ||
152 | + if (!pi_harvest_pir(pir, pir_copy)) | 150 | + if (!pi_harvest_pir(pir, pir_copy)) |
153 | return false; | 151 | return false; |
154 | 152 | ||
155 | - for (i = 0; i < NR_PIR_WORDS; i++) { | 153 | - for (i = 0; i < NR_PIR_WORDS; i++) { |
156 | - if (!pir_copy[i]) | 154 | - if (!pir_copy[i]) |
... | ... | ||
164 | 162 | ||
165 | diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c | 163 | diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c |
166 | index XXXXXXX..XXXXXXX 100644 | 164 | index XXXXXXX..XXXXXXX 100644 |
167 | --- a/arch/x86/kvm/lapic.c | 165 | --- a/arch/x86/kvm/lapic.c |
168 | +++ b/arch/x86/kvm/lapic.c | 166 | +++ b/arch/x86/kvm/lapic.c |
169 | @@ -XXX,XX +XXX,XX @@ bool __kvm_apic_update_irr(unsigned long *pir, void *regs, int *max_irr) | 167 | @@ -XXX,XX +XXX,XX @@ static u8 count_vectors(void *bitmap) |
168 | |||
169 | bool __kvm_apic_update_irr(unsigned long *pir, void *regs, int *max_irr) | ||
170 | { | 170 | { |
171 | unsigned long pir_vals[NR_PIR_WORDS]; | 171 | - unsigned long pir_vals[NR_PIR_WORDS], pending = 0; |
172 | + unsigned long pir_vals[NR_PIR_WORDS]; | ||
172 | u32 *__pir = (void *)pir_vals; | 173 | u32 *__pir = (void *)pir_vals; |
173 | - bool found_irq = false; | ||
174 | u32 i, vec; | 174 | u32 i, vec; |
175 | u32 irr_val, prev_irr_val; | 175 | u32 irr_val, prev_irr_val; |
176 | int max_updated_irr; | ||
177 | @@ -XXX,XX +XXX,XX @@ bool __kvm_apic_update_irr(unsigned long *pir, void *regs, int *max_irr) | 176 | @@ -XXX,XX +XXX,XX @@ bool __kvm_apic_update_irr(unsigned long *pir, void *regs, int *max_irr) |
178 | max_updated_irr = -1; | 177 | max_updated_irr = -1; |
179 | *max_irr = -1; | 178 | *max_irr = -1; |
180 | 179 | ||
181 | - for (i = 0; i < NR_PIR_WORDS; i++) { | 180 | - for (i = 0; i < NR_PIR_WORDS; i++) { |
182 | - pir_vals[i] = READ_ONCE(pir[i]); | 181 | - pir_vals[i] = READ_ONCE(pir[i]); |
183 | - if (pir_vals[i]) | 182 | - pending |= pir_vals[i]; |
184 | - found_irq = true; | 183 | - } |
185 | - } | 184 | - |
186 | - | 185 | - if (!pending) |
187 | - if (!found_irq) | ||
188 | + if (!pi_harvest_pir(pir, pir_vals)) | 186 | + if (!pi_harvest_pir(pir, pir_vals)) |
189 | return false; | 187 | return false; |
190 | 188 | ||
191 | - for (i = 0; i < NR_PIR_WORDS; i++) { | 189 | - for (i = 0; i < NR_PIR_WORDS; i++) { |
192 | - if (!pir_vals[i]) | 190 | - if (!pir_vals[i]) |
... | ... | ||
197 | - | 195 | - |
198 | for (i = vec = 0; i <= 7; i++, vec += 32) { | 196 | for (i = vec = 0; i <= 7; i++, vec += 32) { |
199 | u32 *p_irr = (u32 *)(regs + APIC_IRR + i * 0x10); | 197 | u32 *p_irr = (u32 *)(regs + APIC_IRR + i * 0x10); |
200 | 198 | ||
201 | -- | 199 | -- |
202 | 2.49.0.rc1.451.g8f38331e32-goog | 200 | 2.49.0.472.ge94155a9ec-goog | diff view generated by jsdifflib |