|
@@ -11,6 +11,7 @@
|
|
|
|
|
|
#include <linux/errno.h>
|
|
|
#include <linux/err.h>
|
|
|
+#include <linux/highmem.h>
|
|
|
#include <linux/kvm_host.h>
|
|
|
#include <linux/module.h>
|
|
|
#include <linux/vmalloc.h>
|
|
@@ -29,14 +30,18 @@
|
|
|
static int kvm_mips_trans_replace(struct kvm_vcpu *vcpu, u32 *opc,
|
|
|
union mips_instruction replace)
|
|
|
{
|
|
|
- unsigned long kseg0_opc, flags;
|
|
|
+ unsigned long paddr, flags;
|
|
|
+ void *vaddr;
|
|
|
|
|
|
if (KVM_GUEST_KSEGX(opc) == KVM_GUEST_KSEG0) {
|
|
|
- kseg0_opc =
|
|
|
- CKSEG0ADDR(kvm_mips_translate_guest_kseg0_to_hpa
|
|
|
- (vcpu, (unsigned long) opc));
|
|
|
- memcpy((void *)kseg0_opc, (void *)&replace, sizeof(u32));
|
|
|
- local_flush_icache_range(kseg0_opc, kseg0_opc + 32);
|
|
|
+ paddr = kvm_mips_translate_guest_kseg0_to_hpa(vcpu,
|
|
|
+ (unsigned long)opc);
|
|
|
+ vaddr = kmap_atomic(pfn_to_page(PHYS_PFN(paddr)));
|
|
|
+ vaddr += paddr & ~PAGE_MASK;
|
|
|
+ memcpy(vaddr, (void *)&replace, sizeof(u32));
|
|
|
+ local_flush_icache_range((unsigned long)vaddr,
|
|
|
+ (unsigned long)vaddr + 32);
|
|
|
+ kunmap_atomic(vaddr);
|
|
|
} else if (KVM_GUEST_KSEGX((unsigned long) opc) == KVM_GUEST_KSEG23) {
|
|
|
local_irq_save(flags);
|
|
|
memcpy((void *)opc, (void *)&replace, sizeof(u32));
|