Commit daf5e27109c8c16c987e955cc6abbbc0af050edd

Authored by Liu Yu
Committed by Marcelo Tosatti
1 parent 4b7bb92100

KVM: ppc/booke: Set ESR and DEAR when inject interrupt to guest

Old method prematurely sets ESR and DEAR.
Move this part after we decide to inject interrupt,
which is more like hardware behave.

Signed-off-by: Liu Yu <yu.liu@freescale.com>
Acked-by: Hollis Blanchard <hollis@penguinppc.org>
Acked-by: Alexander Graf <agraf@suse.de>
Signed-off-by: Avi Kivity <avi@redhat.com>

Showing 3 changed files with 48 additions and 17 deletions Side-by-side Diff

arch/powerpc/include/asm/kvm_host.h
... ... @@ -259,6 +259,8 @@
259 259 #endif
260 260 ulong fault_dear;
261 261 ulong fault_esr;
  262 + ulong queued_dear;
  263 + ulong queued_esr;
262 264 gpa_t paddr_accessed;
263 265  
264 266 u8 io_gpr; /* GPR used as IO source/target */
arch/powerpc/kvm/booke.c
... ... @@ -82,9 +82,32 @@
82 82 set_bit(priority, &vcpu->arch.pending_exceptions);
83 83 }
84 84  
85   -void kvmppc_core_queue_program(struct kvm_vcpu *vcpu, ulong flags)
  85 +static void kvmppc_core_queue_dtlb_miss(struct kvm_vcpu *vcpu,
  86 + ulong dear_flags, ulong esr_flags)
86 87 {
87   - /* BookE does flags in ESR, so ignore those we get here */
  88 + vcpu->arch.queued_dear = dear_flags;
  89 + vcpu->arch.queued_esr = esr_flags;
  90 + kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_DTLB_MISS);
  91 +}
  92 +
  93 +static void kvmppc_core_queue_data_storage(struct kvm_vcpu *vcpu,
  94 + ulong dear_flags, ulong esr_flags)
  95 +{
  96 + vcpu->arch.queued_dear = dear_flags;
  97 + vcpu->arch.queued_esr = esr_flags;
  98 + kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_DATA_STORAGE);
  99 +}
  100 +
  101 +static void kvmppc_core_queue_inst_storage(struct kvm_vcpu *vcpu,
  102 + ulong esr_flags)
  103 +{
  104 + vcpu->arch.queued_esr = esr_flags;
  105 + kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_INST_STORAGE);
  106 +}
  107 +
  108 +void kvmppc_core_queue_program(struct kvm_vcpu *vcpu, ulong esr_flags)
  109 +{
  110 + vcpu->arch.queued_esr = esr_flags;
88 111 kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_PROGRAM);
89 112 }
90 113  
91 114  
92 115  
93 116  
94 117  
... ... @@ -115,14 +138,19 @@
115 138 {
116 139 int allowed = 0;
117 140 ulong msr_mask;
  141 + bool update_esr = false, update_dear = false;
118 142  
119 143 switch (priority) {
120   - case BOOKE_IRQPRIO_PROGRAM:
121 144 case BOOKE_IRQPRIO_DTLB_MISS:
122   - case BOOKE_IRQPRIO_ITLB_MISS:
123   - case BOOKE_IRQPRIO_SYSCALL:
124 145 case BOOKE_IRQPRIO_DATA_STORAGE:
  146 + update_dear = true;
  147 + /* fall through */
125 148 case BOOKE_IRQPRIO_INST_STORAGE:
  149 + case BOOKE_IRQPRIO_PROGRAM:
  150 + update_esr = true;
  151 + /* fall through */
  152 + case BOOKE_IRQPRIO_ITLB_MISS:
  153 + case BOOKE_IRQPRIO_SYSCALL:
126 154 case BOOKE_IRQPRIO_FP_UNAVAIL:
127 155 case BOOKE_IRQPRIO_SPE_UNAVAIL:
128 156 case BOOKE_IRQPRIO_SPE_FP_DATA:
... ... @@ -157,6 +185,10 @@
157 185 vcpu->arch.srr0 = vcpu->arch.pc;
158 186 vcpu->arch.srr1 = vcpu->arch.msr;
159 187 vcpu->arch.pc = vcpu->arch.ivpr | vcpu->arch.ivor[priority];
  188 + if (update_esr == true)
  189 + vcpu->arch.esr = vcpu->arch.queued_esr;
  190 + if (update_dear == true)
  191 + vcpu->arch.dear = vcpu->arch.queued_dear;
160 192 kvmppc_set_msr(vcpu, vcpu->arch.msr & msr_mask);
161 193  
162 194 clear_bit(priority, &vcpu->arch.pending_exceptions);
... ... @@ -229,8 +261,7 @@
229 261 if (vcpu->arch.msr & MSR_PR) {
230 262 /* Program traps generated by user-level software must be handled
231 263 * by the guest kernel. */
232   - vcpu->arch.esr = vcpu->arch.fault_esr;
233   - kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_PROGRAM);
  264 + kvmppc_core_queue_program(vcpu, vcpu->arch.fault_esr);
234 265 r = RESUME_GUEST;
235 266 kvmppc_account_exit(vcpu, USR_PR_INST);
236 267 break;
237 268  
... ... @@ -286,16 +317,14 @@
286 317 break;
287 318  
288 319 case BOOKE_INTERRUPT_DATA_STORAGE:
289   - vcpu->arch.dear = vcpu->arch.fault_dear;
290   - vcpu->arch.esr = vcpu->arch.fault_esr;
291   - kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_DATA_STORAGE);
  320 + kvmppc_core_queue_data_storage(vcpu, vcpu->arch.fault_dear,
  321 + vcpu->arch.fault_esr);
292 322 kvmppc_account_exit(vcpu, DSI_EXITS);
293 323 r = RESUME_GUEST;
294 324 break;
295 325  
296 326 case BOOKE_INTERRUPT_INST_STORAGE:
297   - vcpu->arch.esr = vcpu->arch.fault_esr;
298   - kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_INST_STORAGE);
  327 + kvmppc_core_queue_inst_storage(vcpu, vcpu->arch.fault_esr);
299 328 kvmppc_account_exit(vcpu, ISI_EXITS);
300 329 r = RESUME_GUEST;
301 330 break;
... ... @@ -316,9 +345,9 @@
316 345 gtlb_index = kvmppc_mmu_dtlb_index(vcpu, eaddr);
317 346 if (gtlb_index < 0) {
318 347 /* The guest didn't have a mapping for it. */
319   - kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_DTLB_MISS);
320   - vcpu->arch.dear = vcpu->arch.fault_dear;
321   - vcpu->arch.esr = vcpu->arch.fault_esr;
  348 + kvmppc_core_queue_dtlb_miss(vcpu,
  349 + vcpu->arch.fault_dear,
  350 + vcpu->arch.fault_esr);
322 351 kvmppc_mmu_dtlb_miss(vcpu);
323 352 kvmppc_account_exit(vcpu, DTLB_REAL_MISS_EXITS);
324 353 r = RESUME_GUEST;
arch/powerpc/kvm/emulate.c
... ... @@ -151,10 +151,10 @@
151 151 case OP_TRAP:
152 152 #ifdef CONFIG_PPC64
153 153 case OP_TRAP_64:
  154 + kvmppc_core_queue_program(vcpu, SRR1_PROGTRAP);
154 155 #else
155   - vcpu->arch.esr |= ESR_PTR;
  156 + kvmppc_core_queue_program(vcpu, vcpu->arch.esr | ESR_PTR);
156 157 #endif
157   - kvmppc_core_queue_program(vcpu, SRR1_PROGTRAP);
158 158 advance = 0;
159 159 break;
160 160