Commit bb3a8a178dec1e46df3138a30f76acf67fe12397

Authored by Hollis Blanchard
Committed by Avi Kivity
1 parent bdc89f13ec

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
... ... @@ -150,7 +150,7 @@
150 150 u32 tbu;
151 151 u32 tcr;
152 152 u32 tsr;
153   - u32 ivor[16];
  153 + u32 ivor[64];
154 154 ulong ivpr;
155 155 u32 pir;
156 156  
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 }