Commit daf5e27109c8c16c987e955cc6abbbc0af050edd
Committed by
Marcelo Tosatti
1 parent
4b7bb92100
Exists in
master
and in
39 other branches
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
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 |