Commit bb3a8a178dec1e46df3138a30f76acf67fe12397
Committed by
Avi Kivity
1 parent
bdc89f13ec
Exists in
master
and in
7 other branches
KVM: ppc: Add extra E500 exceptions
e500 has additional interrupt vectors (and corresponding IVORs) for SPE and performance monitoring interrupts. Signed-off-by: Liu Yu <yu.liu@freescale.com> Signed-off-by: Hollis Blanchard <hollisb@us.ibm.com> Signed-off-by: Avi Kivity <avi@redhat.com>
Showing 7 changed files with 92 additions and 15 deletions Side-by-side Diff
arch/powerpc/include/asm/kvm_asm.h
... | ... | @@ -42,7 +42,12 @@ |
42 | 42 | #define BOOKE_INTERRUPT_DTLB_MISS 13 |
43 | 43 | #define BOOKE_INTERRUPT_ITLB_MISS 14 |
44 | 44 | #define BOOKE_INTERRUPT_DEBUG 15 |
45 | -#define BOOKE_MAX_INTERRUPT 15 | |
45 | + | |
46 | +/* E500 */ | |
47 | +#define BOOKE_INTERRUPT_SPE_UNAVAIL 32 | |
48 | +#define BOOKE_INTERRUPT_SPE_FP_DATA 33 | |
49 | +#define BOOKE_INTERRUPT_SPE_FP_ROUND 34 | |
50 | +#define BOOKE_INTERRUPT_PERFORMANCE_MONITOR 35 | |
46 | 51 | |
47 | 52 | #define RESUME_FLAG_NV (1<<0) /* Reload guest nonvolatile state? */ |
48 | 53 | #define RESUME_FLAG_HOST (1<<1) /* Resume host? */ |
arch/powerpc/include/asm/kvm_host.h
arch/powerpc/kvm/booke.c
... | ... | @@ -118,6 +118,9 @@ |
118 | 118 | case BOOKE_IRQPRIO_DATA_STORAGE: |
119 | 119 | case BOOKE_IRQPRIO_INST_STORAGE: |
120 | 120 | case BOOKE_IRQPRIO_FP_UNAVAIL: |
121 | + case BOOKE_IRQPRIO_SPE_UNAVAIL: | |
122 | + case BOOKE_IRQPRIO_SPE_FP_DATA: | |
123 | + case BOOKE_IRQPRIO_SPE_FP_ROUND: | |
121 | 124 | case BOOKE_IRQPRIO_AP_UNAVAIL: |
122 | 125 | case BOOKE_IRQPRIO_ALIGNMENT: |
123 | 126 | allowed = 1; |
... | ... | @@ -258,6 +261,21 @@ |
258 | 261 | case BOOKE_INTERRUPT_FP_UNAVAIL: |
259 | 262 | kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_FP_UNAVAIL); |
260 | 263 | kvmppc_account_exit(vcpu, FP_UNAVAIL); |
264 | + r = RESUME_GUEST; | |
265 | + break; | |
266 | + | |
267 | + case BOOKE_INTERRUPT_SPE_UNAVAIL: | |
268 | + kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_SPE_UNAVAIL); | |
269 | + r = RESUME_GUEST; | |
270 | + break; | |
271 | + | |
272 | + case BOOKE_INTERRUPT_SPE_FP_DATA: | |
273 | + kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_SPE_FP_DATA); | |
274 | + r = RESUME_GUEST; | |
275 | + break; | |
276 | + | |
277 | + case BOOKE_INTERRUPT_SPE_FP_ROUND: | |
278 | + kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_SPE_FP_ROUND); | |
261 | 279 | r = RESUME_GUEST; |
262 | 280 | break; |
263 | 281 |
arch/powerpc/kvm/booke.h
... | ... | @@ -31,18 +31,24 @@ |
31 | 31 | #define BOOKE_IRQPRIO_ALIGNMENT 2 |
32 | 32 | #define BOOKE_IRQPRIO_PROGRAM 3 |
33 | 33 | #define BOOKE_IRQPRIO_FP_UNAVAIL 4 |
34 | -#define BOOKE_IRQPRIO_SYSCALL 5 | |
35 | -#define BOOKE_IRQPRIO_AP_UNAVAIL 6 | |
36 | -#define BOOKE_IRQPRIO_DTLB_MISS 7 | |
37 | -#define BOOKE_IRQPRIO_ITLB_MISS 8 | |
38 | -#define BOOKE_IRQPRIO_MACHINE_CHECK 9 | |
39 | -#define BOOKE_IRQPRIO_DEBUG 10 | |
40 | -#define BOOKE_IRQPRIO_CRITICAL 11 | |
41 | -#define BOOKE_IRQPRIO_WATCHDOG 12 | |
42 | -#define BOOKE_IRQPRIO_EXTERNAL 13 | |
43 | -#define BOOKE_IRQPRIO_FIT 14 | |
44 | -#define BOOKE_IRQPRIO_DECREMENTER 15 | |
45 | -#define BOOKE_IRQPRIO_MAX 15 | |
34 | +#define BOOKE_IRQPRIO_SPE_UNAVAIL 5 | |
35 | +#define BOOKE_IRQPRIO_SPE_FP_DATA 6 | |
36 | +#define BOOKE_IRQPRIO_SPE_FP_ROUND 7 | |
37 | +#define BOOKE_IRQPRIO_SYSCALL 8 | |
38 | +#define BOOKE_IRQPRIO_AP_UNAVAIL 9 | |
39 | +#define BOOKE_IRQPRIO_DTLB_MISS 10 | |
40 | +#define BOOKE_IRQPRIO_ITLB_MISS 11 | |
41 | +#define BOOKE_IRQPRIO_MACHINE_CHECK 12 | |
42 | +#define BOOKE_IRQPRIO_DEBUG 13 | |
43 | +#define BOOKE_IRQPRIO_CRITICAL 14 | |
44 | +#define BOOKE_IRQPRIO_WATCHDOG 15 | |
45 | +#define BOOKE_IRQPRIO_EXTERNAL 16 | |
46 | +#define BOOKE_IRQPRIO_FIT 17 | |
47 | +#define BOOKE_IRQPRIO_DECREMENTER 18 | |
48 | +#define BOOKE_IRQPRIO_PERFORMANCE_MONITOR 19 | |
49 | +#define BOOKE_IRQPRIO_MAX 19 | |
50 | + | |
51 | +extern unsigned long kvmppc_booke_handlers; | |
46 | 52 | |
47 | 53 | /* Helper function for "full" MSR writes. No need to call this if only EE is |
48 | 54 | * changing. */ |
arch/powerpc/kvm/booke_interrupts.S
... | ... | @@ -86,6 +86,9 @@ |
86 | 86 | KVM_HANDLER BOOKE_INTERRUPT_DTLB_MISS |
87 | 87 | KVM_HANDLER BOOKE_INTERRUPT_ITLB_MISS |
88 | 88 | KVM_HANDLER BOOKE_INTERRUPT_DEBUG |
89 | +KVM_HANDLER BOOKE_INTERRUPT_SPE_UNAVAIL | |
90 | +KVM_HANDLER BOOKE_INTERRUPT_SPE_FP_DATA | |
91 | +KVM_HANDLER BOOKE_INTERRUPT_SPE_FP_ROUND | |
89 | 92 | |
90 | 93 | _GLOBAL(kvmppc_handler_len) |
91 | 94 | .long kvmppc_handler_1 - kvmppc_handler_0 |
arch/powerpc/kvm/e500.c
... | ... | @@ -21,6 +21,7 @@ |
21 | 21 | #include <asm/kvm_e500.h> |
22 | 22 | #include <asm/kvm_ppc.h> |
23 | 23 | |
24 | +#include "booke.h" | |
24 | 25 | #include "e500_tlb.h" |
25 | 26 | |
26 | 27 | void kvmppc_core_load_host_debugstate(struct kvm_vcpu *vcpu) |
27 | 28 | |
... | ... | @@ -133,11 +134,28 @@ |
133 | 134 | |
134 | 135 | static int kvmppc_e500_init(void) |
135 | 136 | { |
136 | - int r; | |
137 | + int r, i; | |
138 | + unsigned long ivor[3]; | |
139 | + unsigned long max_ivor = 0; | |
137 | 140 | |
138 | 141 | r = kvmppc_booke_init(); |
139 | 142 | if (r) |
140 | 143 | return r; |
144 | + | |
145 | + /* copy extra E500 exception handlers */ | |
146 | + ivor[0] = mfspr(SPRN_IVOR32); | |
147 | + ivor[1] = mfspr(SPRN_IVOR33); | |
148 | + ivor[2] = mfspr(SPRN_IVOR34); | |
149 | + for (i = 0; i < 3; i++) { | |
150 | + if (ivor[i] > max_ivor) | |
151 | + max_ivor = ivor[i]; | |
152 | + | |
153 | + memcpy((void *)kvmppc_booke_handlers + ivor[i], | |
154 | + kvmppc_handlers_start + (i + 16) * kvmppc_handler_len, | |
155 | + kvmppc_handler_len); | |
156 | + } | |
157 | + flush_icache_range(kvmppc_booke_handlers, | |
158 | + kvmppc_booke_handlers + max_ivor + kvmppc_handler_len); | |
141 | 159 | |
142 | 160 | return kvm_init(NULL, sizeof(struct kvmppc_vcpu_e500), THIS_MODULE); |
143 | 161 | } |
arch/powerpc/kvm/e500_emulate.c
... | ... | @@ -107,6 +107,20 @@ |
107 | 107 | case SPRN_HID1: |
108 | 108 | vcpu_e500->hid1 = vcpu->arch.gpr[rs]; break; |
109 | 109 | |
110 | + /* extra exceptions */ | |
111 | + case SPRN_IVOR32: | |
112 | + vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_UNAVAIL] = vcpu->arch.gpr[rs]; | |
113 | + break; | |
114 | + case SPRN_IVOR33: | |
115 | + vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_FP_DATA] = vcpu->arch.gpr[rs]; | |
116 | + break; | |
117 | + case SPRN_IVOR34: | |
118 | + vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_FP_ROUND] = vcpu->arch.gpr[rs]; | |
119 | + break; | |
120 | + case SPRN_IVOR35: | |
121 | + vcpu->arch.ivor[BOOKE_IRQPRIO_PERFORMANCE_MONITOR] = vcpu->arch.gpr[rs]; | |
122 | + break; | |
123 | + | |
110 | 124 | default: |
111 | 125 | emulated = kvmppc_booke_emulate_mtspr(vcpu, sprn, rs); |
112 | 126 | } |
... | ... | @@ -160,6 +174,19 @@ |
160 | 174 | case SPRN_HID1: |
161 | 175 | vcpu->arch.gpr[rt] = vcpu_e500->hid1; break; |
162 | 176 | |
177 | + /* extra exceptions */ | |
178 | + case SPRN_IVOR32: | |
179 | + vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_UNAVAIL]; | |
180 | + break; | |
181 | + case SPRN_IVOR33: | |
182 | + vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_FP_DATA]; | |
183 | + break; | |
184 | + case SPRN_IVOR34: | |
185 | + vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_FP_ROUND]; | |
186 | + break; | |
187 | + case SPRN_IVOR35: | |
188 | + vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_PERFORMANCE_MONITOR]; | |
189 | + break; | |
163 | 190 | default: |
164 | 191 | emulated = kvmppc_booke_emulate_mfspr(vcpu, sprn, rt); |
165 | 192 | } |