diff options
author | James Hogan <james.hogan@imgtec.com> | 2016-06-09 09:19:20 -0400 |
---|---|---|
committer | Paolo Bonzini <pbonzini@redhat.com> | 2016-06-14 05:02:47 -0400 |
commit | 3b08aec549a0314b8c3788bdc2a21096d53225e1 (patch) | |
tree | 193997bf9f20d0f56e195816e6a657f4699debf8 /arch/mips/kvm | |
parent | e6207bbea16c60942cdc1492af4feed5aed77389 (diff) |
MIPS: KVM: Combine handle_tlb_ld/st_miss
The handle_tlb_ld/st_miss handlers are logically equivalent and
textually almost identical, so combine their implementations into a
single kvm_trap_emul_handle_tlb_miss().
Signed-off-by: James Hogan <james.hogan@imgtec.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Radim Krčmář <rkrcmar@redhat.com>
Cc: Ralf Baechle <ralf@linux-mips.org>
Cc: linux-mips@linux-mips.org
Cc: kvm@vger.kernel.org
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Diffstat (limited to 'arch/mips/kvm')
-rw-r--r-- | arch/mips/kvm/trap_emul.c | 71 |
1 files changed, 19 insertions, 52 deletions
diff --git a/arch/mips/kvm/trap_emul.c b/arch/mips/kvm/trap_emul.c index ecf0068bc95e..09b97fa9dabb 100644 --- a/arch/mips/kvm/trap_emul.c +++ b/arch/mips/kvm/trap_emul.c | |||
@@ -128,7 +128,7 @@ static int kvm_trap_emul_handle_tlb_mod(struct kvm_vcpu *vcpu) | |||
128 | return ret; | 128 | return ret; |
129 | } | 129 | } |
130 | 130 | ||
131 | static int kvm_trap_emul_handle_tlb_st_miss(struct kvm_vcpu *vcpu) | 131 | static int kvm_trap_emul_handle_tlb_miss(struct kvm_vcpu *vcpu, bool store) |
132 | { | 132 | { |
133 | struct kvm_run *run = vcpu->run; | 133 | struct kvm_run *run = vcpu->run; |
134 | u32 __user *opc = (u32 __user *) vcpu->arch.pc; | 134 | u32 __user *opc = (u32 __user *) vcpu->arch.pc; |
@@ -145,55 +145,8 @@ static int kvm_trap_emul_handle_tlb_st_miss(struct kvm_vcpu *vcpu) | |||
145 | } | 145 | } |
146 | } else if (KVM_GUEST_KSEGX(badvaddr) < KVM_GUEST_KSEG0 | 146 | } else if (KVM_GUEST_KSEGX(badvaddr) < KVM_GUEST_KSEG0 |
147 | || KVM_GUEST_KSEGX(badvaddr) == KVM_GUEST_KSEG23) { | 147 | || KVM_GUEST_KSEGX(badvaddr) == KVM_GUEST_KSEG23) { |
148 | kvm_debug("USER ADDR TLB LD fault: cause %#x, PC: %p, BadVaddr: %#lx\n", | 148 | kvm_debug("USER ADDR TLB %s fault: cause %#x, PC: %p, BadVaddr: %#lx\n", |
149 | cause, opc, badvaddr); | 149 | store ? "ST" : "LD", cause, opc, badvaddr); |
150 | er = kvm_mips_handle_tlbmiss(cause, opc, run, vcpu); | ||
151 | if (er == EMULATE_DONE) | ||
152 | ret = RESUME_GUEST; | ||
153 | else { | ||
154 | run->exit_reason = KVM_EXIT_INTERNAL_ERROR; | ||
155 | ret = RESUME_HOST; | ||
156 | } | ||
157 | } else if (KVM_GUEST_KSEGX(badvaddr) == KVM_GUEST_KSEG0) { | ||
158 | /* | ||
159 | * All KSEG0 faults are handled by KVM, as the guest kernel does | ||
160 | * not expect to ever get them | ||
161 | */ | ||
162 | if (kvm_mips_handle_kseg0_tlb_fault | ||
163 | (vcpu->arch.host_cp0_badvaddr, vcpu) < 0) { | ||
164 | run->exit_reason = KVM_EXIT_INTERNAL_ERROR; | ||
165 | ret = RESUME_HOST; | ||
166 | } | ||
167 | } else { | ||
168 | kvm_err("Illegal TLB LD fault address , cause %#x, PC: %p, BadVaddr: %#lx\n", | ||
169 | cause, opc, badvaddr); | ||
170 | kvm_mips_dump_host_tlbs(); | ||
171 | kvm_arch_vcpu_dump_regs(vcpu); | ||
172 | run->exit_reason = KVM_EXIT_INTERNAL_ERROR; | ||
173 | ret = RESUME_HOST; | ||
174 | } | ||
175 | return ret; | ||
176 | } | ||
177 | |||
178 | static int kvm_trap_emul_handle_tlb_ld_miss(struct kvm_vcpu *vcpu) | ||
179 | { | ||
180 | struct kvm_run *run = vcpu->run; | ||
181 | u32 __user *opc = (u32 __user *) vcpu->arch.pc; | ||
182 | unsigned long badvaddr = vcpu->arch.host_cp0_badvaddr; | ||
183 | u32 cause = vcpu->arch.host_cp0_cause; | ||
184 | enum emulation_result er = EMULATE_DONE; | ||
185 | int ret = RESUME_GUEST; | ||
186 | |||
187 | if (((badvaddr & PAGE_MASK) == KVM_GUEST_COMMPAGE_ADDR) | ||
188 | && KVM_GUEST_KERNEL_MODE(vcpu)) { | ||
189 | if (kvm_mips_handle_commpage_tlb_fault(badvaddr, vcpu) < 0) { | ||
190 | run->exit_reason = KVM_EXIT_INTERNAL_ERROR; | ||
191 | ret = RESUME_HOST; | ||
192 | } | ||
193 | } else if (KVM_GUEST_KSEGX(badvaddr) < KVM_GUEST_KSEG0 | ||
194 | || KVM_GUEST_KSEGX(badvaddr) == KVM_GUEST_KSEG23) { | ||
195 | kvm_debug("USER ADDR TLB ST fault: PC: %#lx, BadVaddr: %#lx\n", | ||
196 | vcpu->arch.pc, badvaddr); | ||
197 | 150 | ||
198 | /* | 151 | /* |
199 | * User Address (UA) fault, this could happen if | 152 | * User Address (UA) fault, this could happen if |
@@ -213,14 +166,18 @@ static int kvm_trap_emul_handle_tlb_ld_miss(struct kvm_vcpu *vcpu) | |||
213 | ret = RESUME_HOST; | 166 | ret = RESUME_HOST; |
214 | } | 167 | } |
215 | } else if (KVM_GUEST_KSEGX(badvaddr) == KVM_GUEST_KSEG0) { | 168 | } else if (KVM_GUEST_KSEGX(badvaddr) == KVM_GUEST_KSEG0) { |
169 | /* | ||
170 | * All KSEG0 faults are handled by KVM, as the guest kernel does | ||
171 | * not expect to ever get them | ||
172 | */ | ||
216 | if (kvm_mips_handle_kseg0_tlb_fault | 173 | if (kvm_mips_handle_kseg0_tlb_fault |
217 | (vcpu->arch.host_cp0_badvaddr, vcpu) < 0) { | 174 | (vcpu->arch.host_cp0_badvaddr, vcpu) < 0) { |
218 | run->exit_reason = KVM_EXIT_INTERNAL_ERROR; | 175 | run->exit_reason = KVM_EXIT_INTERNAL_ERROR; |
219 | ret = RESUME_HOST; | 176 | ret = RESUME_HOST; |
220 | } | 177 | } |
221 | } else { | 178 | } else { |
222 | kvm_err("Illegal TLB ST fault address , cause %#x, PC: %p, BadVaddr: %#lx\n", | 179 | kvm_err("Illegal TLB %s fault address , cause %#x, PC: %p, BadVaddr: %#lx\n", |
223 | cause, opc, badvaddr); | 180 | store ? "ST" : "LD", cause, opc, badvaddr); |
224 | kvm_mips_dump_host_tlbs(); | 181 | kvm_mips_dump_host_tlbs(); |
225 | kvm_arch_vcpu_dump_regs(vcpu); | 182 | kvm_arch_vcpu_dump_regs(vcpu); |
226 | run->exit_reason = KVM_EXIT_INTERNAL_ERROR; | 183 | run->exit_reason = KVM_EXIT_INTERNAL_ERROR; |
@@ -229,6 +186,16 @@ static int kvm_trap_emul_handle_tlb_ld_miss(struct kvm_vcpu *vcpu) | |||
229 | return ret; | 186 | return ret; |
230 | } | 187 | } |
231 | 188 | ||
189 | static int kvm_trap_emul_handle_tlb_st_miss(struct kvm_vcpu *vcpu) | ||
190 | { | ||
191 | return kvm_trap_emul_handle_tlb_miss(vcpu, true); | ||
192 | } | ||
193 | |||
194 | static int kvm_trap_emul_handle_tlb_ld_miss(struct kvm_vcpu *vcpu) | ||
195 | { | ||
196 | return kvm_trap_emul_handle_tlb_miss(vcpu, false); | ||
197 | } | ||
198 | |||
232 | static int kvm_trap_emul_handle_addr_err_st(struct kvm_vcpu *vcpu) | 199 | static int kvm_trap_emul_handle_addr_err_st(struct kvm_vcpu *vcpu) |
233 | { | 200 | { |
234 | struct kvm_run *run = vcpu->run; | 201 | struct kvm_run *run = vcpu->run; |