aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/kvm
diff options
context:
space:
mode:
authorJames Hogan <james.hogan@imgtec.com>2016-06-09 09:19:20 -0400
committerPaolo Bonzini <pbonzini@redhat.com>2016-06-14 05:02:47 -0400
commit3b08aec549a0314b8c3788bdc2a21096d53225e1 (patch)
tree193997bf9f20d0f56e195816e6a657f4699debf8 /arch/mips/kvm
parente6207bbea16c60942cdc1492af4feed5aed77389 (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.c71
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
131static int kvm_trap_emul_handle_tlb_st_miss(struct kvm_vcpu *vcpu) 131static 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
178static 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
189static 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
194static 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
232static int kvm_trap_emul_handle_addr_err_st(struct kvm_vcpu *vcpu) 199static 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;