-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
MIPS: KVM: Use kmap instead of CKSEG0ADDR()
There are several unportable uses of CKSEG0ADDR() in MIPS KVM, which implicitly assume that a host physical address will be in the low 512MB of the physical address space (accessible in KSeg0). These assumptions don't hold for highmem or on 64-bit kernels. When interpreting the guest physical address when reading or overwriting a trapping instruction, use kmap_atomic() to get a usable virtual address to access guest memory, which is portable to 64-bit and highmem kernels. Signed-off-by: James Hogan <[email protected]> Cc: Paolo Bonzini <[email protected]> Cc: "Radim Krčmář" <[email protected]> Cc: Ralf Baechle <[email protected]> Cc: [email protected] Cc: [email protected] Signed-off-by: Paolo Bonzini <[email protected]>
- Loading branch information
Showing
2 changed files
with
17 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -9,6 +9,7 @@ | |
* Authors: Sanjay Lal <[email protected]> | ||
*/ | ||
|
||
#include <linux/highmem.h> | ||
#include <linux/kvm_host.h> | ||
#include <asm/mmu_context.h> | ||
|
||
|
@@ -330,6 +331,7 @@ u32 kvm_get_inst(u32 *opc, struct kvm_vcpu *vcpu) | |
struct mips_coproc *cop0 = vcpu->arch.cop0; | ||
unsigned long paddr, flags, vpn2, asid; | ||
unsigned long va = (unsigned long)opc; | ||
void *vaddr; | ||
u32 inst; | ||
int index; | ||
|
||
|
@@ -360,7 +362,10 @@ u32 kvm_get_inst(u32 *opc, struct kvm_vcpu *vcpu) | |
local_irq_restore(flags); | ||
} else if (KVM_GUEST_KSEGX(va) == KVM_GUEST_KSEG0) { | ||
paddr = kvm_mips_translate_guest_kseg0_to_hpa(vcpu, va); | ||
inst = *(u32 *) CKSEG0ADDR(paddr); | ||
vaddr = kmap_atomic(pfn_to_page(PHYS_PFN(paddr))); | ||
vaddr += paddr & ~PAGE_MASK; | ||
inst = *(u32 *)vaddr; | ||
kunmap_atomic(vaddr); | ||
} else { | ||
kvm_err("%s: illegal address: %p\n", __func__, opc); | ||
return KVM_INVALID_INST; | ||
|