diff options
author | Sanjay Lal <sanjayl@kymasys.com> | 2013-05-18 09:54:24 -0400 |
---|---|---|
committer | Gleb Natapov <gleb@redhat.com> | 2013-05-22 04:44:09 -0400 |
commit | 6d17c0d1e8a66f5508082cb0fecb8afb7e9a21e4 (patch) | |
tree | eca5c93989a96bd5afff0e48178286861f8ce475 /arch/mips/kvm | |
parent | ba86e4dda700b3e696119c7f4fad945b90cf5c84 (diff) |
KVM/MIPS32: Wrap calls to gfn_to_pfn() with srcu_read_lock/unlock()
- As suggested by Gleb, wrap calls to gfn_to_pfn() with srcu_read_lock/unlock().
Memory slots should be acccessed from a SRCU read section.
- kvm_mips_map_page() now returns an error code to it's callers, instead of
calling panic() if it cannot find a mapping for a particular gfn.
Signed-off-by: Sanjay Lal <sanjayl@kymasys.com>
Signed-off-by: Gleb Natapov <gleb@redhat.com>
Diffstat (limited to 'arch/mips/kvm')
-rw-r--r-- | arch/mips/kvm/kvm_tlb.c | 35 |
1 files changed, 26 insertions, 9 deletions
diff --git a/arch/mips/kvm/kvm_tlb.c b/arch/mips/kvm/kvm_tlb.c index 89511a9258d3..87d845e9e5ab 100644 --- a/arch/mips/kvm/kvm_tlb.c +++ b/arch/mips/kvm/kvm_tlb.c | |||
@@ -17,6 +17,8 @@ | |||
17 | #include <linux/delay.h> | 17 | #include <linux/delay.h> |
18 | #include <linux/module.h> | 18 | #include <linux/module.h> |
19 | #include <linux/kvm_host.h> | 19 | #include <linux/kvm_host.h> |
20 | #include <linux/srcu.h> | ||
21 | |||
20 | 22 | ||
21 | #include <asm/cpu.h> | 23 | #include <asm/cpu.h> |
22 | #include <asm/bootinfo.h> | 24 | #include <asm/bootinfo.h> |
@@ -169,21 +171,27 @@ void kvm_mips_dump_shadow_tlbs(struct kvm_vcpu *vcpu) | |||
169 | } | 171 | } |
170 | } | 172 | } |
171 | 173 | ||
172 | static void kvm_mips_map_page(struct kvm *kvm, gfn_t gfn) | 174 | static int kvm_mips_map_page(struct kvm *kvm, gfn_t gfn) |
173 | { | 175 | { |
176 | int srcu_idx, err = 0; | ||
174 | pfn_t pfn; | 177 | pfn_t pfn; |
175 | 178 | ||
176 | if (kvm->arch.guest_pmap[gfn] != KVM_INVALID_PAGE) | 179 | if (kvm->arch.guest_pmap[gfn] != KVM_INVALID_PAGE) |
177 | return; | 180 | return 0; |
178 | 181 | ||
182 | srcu_idx = srcu_read_lock(&kvm->srcu); | ||
179 | pfn = kvm_mips_gfn_to_pfn(kvm, gfn); | 183 | pfn = kvm_mips_gfn_to_pfn(kvm, gfn); |
180 | 184 | ||
181 | if (kvm_mips_is_error_pfn(pfn)) { | 185 | if (kvm_mips_is_error_pfn(pfn)) { |
182 | panic("Couldn't get pfn for gfn %#" PRIx64 "!\n", gfn); | 186 | kvm_err("Couldn't get pfn for gfn %#" PRIx64 "!\n", gfn); |
187 | err = -EFAULT; | ||
188 | goto out; | ||
183 | } | 189 | } |
184 | 190 | ||
185 | kvm->arch.guest_pmap[gfn] = pfn; | 191 | kvm->arch.guest_pmap[gfn] = pfn; |
186 | return; | 192 | out: |
193 | srcu_read_unlock(&kvm->srcu, srcu_idx); | ||
194 | return err; | ||
187 | } | 195 | } |
188 | 196 | ||
189 | /* Translate guest KSEG0 addresses to Host PA */ | 197 | /* Translate guest KSEG0 addresses to Host PA */ |
@@ -207,7 +215,10 @@ unsigned long kvm_mips_translate_guest_kseg0_to_hpa(struct kvm_vcpu *vcpu, | |||
207 | gva); | 215 | gva); |
208 | return KVM_INVALID_PAGE; | 216 | return KVM_INVALID_PAGE; |
209 | } | 217 | } |
210 | kvm_mips_map_page(vcpu->kvm, gfn); | 218 | |
219 | if (kvm_mips_map_page(vcpu->kvm, gfn) < 0) | ||
220 | return KVM_INVALID_ADDR; | ||
221 | |||
211 | return (kvm->arch.guest_pmap[gfn] << PAGE_SHIFT) + offset; | 222 | return (kvm->arch.guest_pmap[gfn] << PAGE_SHIFT) + offset; |
212 | } | 223 | } |
213 | 224 | ||
@@ -310,8 +321,11 @@ int kvm_mips_handle_kseg0_tlb_fault(unsigned long badvaddr, | |||
310 | even = !(gfn & 0x1); | 321 | even = !(gfn & 0x1); |
311 | vaddr = badvaddr & (PAGE_MASK << 1); | 322 | vaddr = badvaddr & (PAGE_MASK << 1); |
312 | 323 | ||
313 | kvm_mips_map_page(vcpu->kvm, gfn); | 324 | if (kvm_mips_map_page(vcpu->kvm, gfn) < 0) |
314 | kvm_mips_map_page(vcpu->kvm, gfn ^ 0x1); | 325 | return -1; |
326 | |||
327 | if (kvm_mips_map_page(vcpu->kvm, gfn ^ 0x1) < 0) | ||
328 | return -1; | ||
315 | 329 | ||
316 | if (even) { | 330 | if (even) { |
317 | pfn0 = kvm->arch.guest_pmap[gfn]; | 331 | pfn0 = kvm->arch.guest_pmap[gfn]; |
@@ -389,8 +403,11 @@ kvm_mips_handle_mapped_seg_tlb_fault(struct kvm_vcpu *vcpu, | |||
389 | pfn0 = 0; | 403 | pfn0 = 0; |
390 | pfn1 = 0; | 404 | pfn1 = 0; |
391 | } else { | 405 | } else { |
392 | kvm_mips_map_page(kvm, mips3_tlbpfn_to_paddr(tlb->tlb_lo0) >> PAGE_SHIFT); | 406 | if (kvm_mips_map_page(kvm, mips3_tlbpfn_to_paddr(tlb->tlb_lo0) >> PAGE_SHIFT) < 0) |
393 | kvm_mips_map_page(kvm, mips3_tlbpfn_to_paddr(tlb->tlb_lo1) >> PAGE_SHIFT); | 407 | return -1; |
408 | |||
409 | if (kvm_mips_map_page(kvm, mips3_tlbpfn_to_paddr(tlb->tlb_lo1) >> PAGE_SHIFT) < 0) | ||
410 | return -1; | ||
394 | 411 | ||
395 | pfn0 = kvm->arch.guest_pmap[mips3_tlbpfn_to_paddr(tlb->tlb_lo0) >> PAGE_SHIFT]; | 412 | pfn0 = kvm->arch.guest_pmap[mips3_tlbpfn_to_paddr(tlb->tlb_lo0) >> PAGE_SHIFT]; |
396 | pfn1 = kvm->arch.guest_pmap[mips3_tlbpfn_to_paddr(tlb->tlb_lo1) >> PAGE_SHIFT]; | 413 | pfn1 = kvm->arch.guest_pmap[mips3_tlbpfn_to_paddr(tlb->tlb_lo1) >> PAGE_SHIFT]; |