Skip to content

Commit

Permalink
KVM: PPC: Pass EA to updating emulation ops
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Alexander Graf authored and Avi Kivity committed Apr 8, 2012
1 parent 8943633 commit 6020c0f
Show file tree
Hide file tree
Showing 5 changed files with 17 additions and 30 deletions.
1 change: 1 addition & 0 deletions arch/powerpc/include/asm/kvm_host.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
5 changes: 3 additions & 2 deletions arch/powerpc/kvm/book3s_64_mmu_hv.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
}

Expand Down Expand Up @@ -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);
}

Expand Down
1 change: 1 addition & 0 deletions arch/powerpc/kvm/book3s_pr.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
1 change: 1 addition & 0 deletions arch/powerpc/kvm/booke.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down
39 changes: 11 additions & 28 deletions arch/powerpc/kvm/emulate.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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:
Expand All @@ -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:
Expand All @@ -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:
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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:
Expand All @@ -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:
Expand All @@ -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:
Expand All @@ -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:
Expand All @@ -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:
Expand All @@ -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:
Expand All @@ -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:
Expand Down

0 comments on commit 6020c0f

Please sign in to comment.