KVM: PPC: Pass EA to updating emulation ops
authorAlexander Graf <agraf@suse.de>
Mon, 12 Mar 2012 01:26:30 +0000 (02:26 +0100)
committerAvi Kivity <avi@redhat.com>
Sun, 8 Apr 2012 11:01:37 +0000 (14:01 +0300)
When emulating updating load/store instructions (lwzu, stwu, ...) we need to
write the effective address of the load/store into a register.

Currently, we write the physical address in there, which is very wrong. So
instead let's save off where the virtual fault was on MMIO and use that
information as value to put into the register.

While at it, also move the XOP variants of the above instructions to the new
scheme of using the already known vaddr instead of calculating it themselves.

Reported-by: Jörg Sommer <joerg@alea.gnuu.de>
Signed-off-by: Alexander Graf <agraf@suse.de>
Signed-off-by: Avi Kivity <avi@redhat.com>
arch/powerpc/include/asm/kvm_host.h
arch/powerpc/kvm/book3s_64_mmu_hv.c
arch/powerpc/kvm/book3s_pr.c
arch/powerpc/kvm/booke.c
arch/powerpc/kvm/emulate.c

index 014eaf27a239990b2c9af87de54fbd94669d1da6..42a527e70490d03e162e0f959ba9a8d6b06310bd 100644 (file)
@@ -464,6 +464,7 @@ struct kvm_vcpu_arch {
        u32 epr;
 #endif
        gpa_t paddr_accessed;
+       gva_t vaddr_accessed;
 
        u8 io_gpr; /* GPR used as IO source/target */
        u8 mmio_is_bigendian;
index d031ce1d83f526016a13195eec1bf7605ed71b1d..8e6401f2c16fd89421a29584410f47700d621470 100644 (file)
@@ -447,7 +447,7 @@ static int instruction_is_store(unsigned int instr)
 }
 
 static int kvmppc_hv_emulate_mmio(struct kvm_run *run, struct kvm_vcpu *vcpu,
-                                 unsigned long gpa, int is_store)
+                                 unsigned long gpa, gva_t ea, int is_store)
 {
        int ret;
        u32 last_inst;
@@ -494,6 +494,7 @@ static int kvmppc_hv_emulate_mmio(struct kvm_run *run, struct kvm_vcpu *vcpu,
         */
 
        vcpu->arch.paddr_accessed = gpa;
+       vcpu->arch.vaddr_accessed = ea;
        return kvmppc_emulate_mmio(run, vcpu);
 }
 
@@ -547,7 +548,7 @@ int kvmppc_book3s_hv_page_fault(struct kvm_run *run, struct kvm_vcpu *vcpu,
        /* No memslot means it's an emulated MMIO region */
        if (!memslot || (memslot->flags & KVM_MEMSLOT_INVALID)) {
                unsigned long gpa = (gfn << PAGE_SHIFT) | (ea & (psize - 1));
-               return kvmppc_hv_emulate_mmio(run, vcpu, gpa,
+               return kvmppc_hv_emulate_mmio(run, vcpu, gpa, ea,
                                              dsisr & DSISR_ISSTORE);
        }
 
index 7759053d391b87298a4888c1cbbb7463ee6e8431..158047fc951374611fe0e7b10cb4ea9ad2c23180 100644 (file)
@@ -351,6 +351,7 @@ int kvmppc_handle_pagefault(struct kvm_run *run, struct kvm_vcpu *vcpu,
                /* MMIO */
                vcpu->stat.mmio_exits++;
                vcpu->arch.paddr_accessed = pte.raddr;
+               vcpu->arch.vaddr_accessed = pte.eaddr;
                r = kvmppc_emulate_mmio(run, vcpu);
                if ( r == RESUME_HOST_NV )
                        r = RESUME_HOST;
index 9f27258d80356654f84de67bfe63c098345b58f4..2675dcb40a7f4cc0acedf857a586e96804b1bc9c 100644 (file)
@@ -875,6 +875,7 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
                        /* Guest has mapped and accessed a page which is not
                         * actually RAM. */
                        vcpu->arch.paddr_accessed = gpaddr;
+                       vcpu->arch.vaddr_accessed = eaddr;
                        r = kvmppc_emulate_mmio(run, vcpu);
                        kvmppc_account_exit(vcpu, MMIO_EXITS);
                }
index 968f401018834aa4758ec45afeb32eee327a37c8..e79a620608ab2ec6881481c01334c07e44f491c5 100644 (file)
@@ -141,7 +141,6 @@ u32 kvmppc_get_dec(struct kvm_vcpu *vcpu, u64 tb)
 int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu)
 {
        u32 inst = kvmppc_get_last_inst(vcpu);
-       u32 ea;
        int ra;
        int rb;
        int rs;
@@ -185,12 +184,8 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu)
                        ra = get_ra(inst);
                        rb = get_rb(inst);
 
-                       ea = kvmppc_get_gpr(vcpu, rb);
-                       if (ra)
-                               ea += kvmppc_get_gpr(vcpu, ra);
-
                        emulated = kvmppc_handle_load(run, vcpu, rt, 1, 1);
-                       kvmppc_set_gpr(vcpu, ra, ea);
+                       kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed);
                        break;
 
                case OP_31_XOP_STWX:
@@ -212,14 +207,10 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu)
                        ra = get_ra(inst);
                        rb = get_rb(inst);
 
-                       ea = kvmppc_get_gpr(vcpu, rb);
-                       if (ra)
-                               ea += kvmppc_get_gpr(vcpu, ra);
-
                        emulated = kvmppc_handle_store(run, vcpu,
                                                       kvmppc_get_gpr(vcpu, rs),
                                                       1, 1);
-                       kvmppc_set_gpr(vcpu, rs, ea);
+                       kvmppc_set_gpr(vcpu, rs, vcpu->arch.vaddr_accessed);
                        break;
 
                case OP_31_XOP_LHAX:
@@ -237,12 +228,8 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu)
                        ra = get_ra(inst);
                        rb = get_rb(inst);
 
-                       ea = kvmppc_get_gpr(vcpu, rb);
-                       if (ra)
-                               ea += kvmppc_get_gpr(vcpu, ra);
-
                        emulated = kvmppc_handle_load(run, vcpu, rt, 2, 1);
-                       kvmppc_set_gpr(vcpu, ra, ea);
+                       kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed);
                        break;
 
                case OP_31_XOP_MFSPR:
@@ -318,14 +305,10 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu)
                        ra = get_ra(inst);
                        rb = get_rb(inst);
 
-                       ea = kvmppc_get_gpr(vcpu, rb);
-                       if (ra)
-                               ea += kvmppc_get_gpr(vcpu, ra);
-
                        emulated = kvmppc_handle_store(run, vcpu,
                                                       kvmppc_get_gpr(vcpu, rs),
                                                       2, 1);
-                       kvmppc_set_gpr(vcpu, ra, ea);
+                       kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed);
                        break;
 
                case OP_31_XOP_MTSPR:
@@ -429,7 +412,7 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu)
                ra = get_ra(inst);
                rt = get_rt(inst);
                emulated = kvmppc_handle_load(run, vcpu, rt, 4, 1);
-               kvmppc_set_gpr(vcpu, ra, vcpu->arch.paddr_accessed);
+               kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed);
                break;
 
        case OP_LBZ:
@@ -441,7 +424,7 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu)
                ra = get_ra(inst);
                rt = get_rt(inst);
                emulated = kvmppc_handle_load(run, vcpu, rt, 1, 1);
-               kvmppc_set_gpr(vcpu, ra, vcpu->arch.paddr_accessed);
+               kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed);
                break;
 
        case OP_STW:
@@ -457,7 +440,7 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu)
                emulated = kvmppc_handle_store(run, vcpu,
                                               kvmppc_get_gpr(vcpu, rs),
                                               4, 1);
-               kvmppc_set_gpr(vcpu, ra, vcpu->arch.paddr_accessed);
+               kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed);
                break;
 
        case OP_STB:
@@ -473,7 +456,7 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu)
                emulated = kvmppc_handle_store(run, vcpu,
                                               kvmppc_get_gpr(vcpu, rs),
                                               1, 1);
-               kvmppc_set_gpr(vcpu, ra, vcpu->arch.paddr_accessed);
+               kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed);
                break;
 
        case OP_LHZ:
@@ -485,7 +468,7 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu)
                ra = get_ra(inst);
                rt = get_rt(inst);
                emulated = kvmppc_handle_load(run, vcpu, rt, 2, 1);
-               kvmppc_set_gpr(vcpu, ra, vcpu->arch.paddr_accessed);
+               kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed);
                break;
 
        case OP_LHA:
@@ -497,7 +480,7 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu)
                ra = get_ra(inst);
                rt = get_rt(inst);
                emulated = kvmppc_handle_loads(run, vcpu, rt, 2, 1);
-               kvmppc_set_gpr(vcpu, ra, vcpu->arch.paddr_accessed);
+               kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed);
                break;
 
        case OP_STH:
@@ -513,7 +496,7 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu)
                emulated = kvmppc_handle_store(run, vcpu,
                                               kvmppc_get_gpr(vcpu, rs),
                                               2, 1);
-               kvmppc_set_gpr(vcpu, ra, vcpu->arch.paddr_accessed);
+               kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed);
                break;
 
        default:
This page took 0.034421 seconds and 5 git commands to generate.