Commit acf17878 authored by Paul Mackerras's avatar Paul Mackerras Committed by Michael Ellerman

KVM: PPC: Make kvmppc_get_last_inst() produce a ppc_inst_t

This changes kvmppc_get_last_inst() so that the instruction it fetches
is returned in a ppc_inst_t variable rather than a u32.  This will
allow us to return a 64-bit prefixed instruction on those 64-bit
machines that implement Power ISA v3.1 or later, such as POWER10.
On 32-bit platforms, ppc_inst_t is 32 bits wide, and is turned back
into a u32 by ppc_inst_val, which is an identity operation on those
platforms.
Reviewed-by: default avatarNicholas Piggin <npiggin@gmail.com>
Tested-by: default avatarNicholas Piggin <npiggin@gmail.com>
Signed-off-by: default avatarPaul Mackerras <paulus@ozlabs.org>
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
Link: https://msgid.link/ZAgsiPlL9O7KnlZZ@cleo
parent 6cd5c1db
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
#include <asm/xive.h> #include <asm/xive.h>
#include <asm/cpu_has_feature.h> #include <asm/cpu_has_feature.h>
#endif #endif
#include <asm/inst.h>
/* /*
* KVMPPC_INST_SW_BREAKPOINT is debug Instruction * KVMPPC_INST_SW_BREAKPOINT is debug Instruction
...@@ -324,7 +325,7 @@ extern struct kvmppc_ops *kvmppc_hv_ops; ...@@ -324,7 +325,7 @@ extern struct kvmppc_ops *kvmppc_hv_ops;
extern struct kvmppc_ops *kvmppc_pr_ops; extern struct kvmppc_ops *kvmppc_pr_ops;
static inline int kvmppc_get_last_inst(struct kvm_vcpu *vcpu, static inline int kvmppc_get_last_inst(struct kvm_vcpu *vcpu,
enum instruction_fetch_type type, u32 *inst) enum instruction_fetch_type type, ppc_inst_t *inst)
{ {
int ret = EMULATE_DONE; int ret = EMULATE_DONE;
u32 fetched_inst; u32 fetched_inst;
...@@ -342,7 +343,7 @@ static inline int kvmppc_get_last_inst(struct kvm_vcpu *vcpu, ...@@ -342,7 +343,7 @@ static inline int kvmppc_get_last_inst(struct kvm_vcpu *vcpu,
else else
fetched_inst = vcpu->arch.last_inst; fetched_inst = vcpu->arch.last_inst;
*inst = fetched_inst; *inst = ppc_inst(fetched_inst);
return ret; return ret;
} }
......
...@@ -415,20 +415,24 @@ static int kvmppc_mmu_book3s_64_hv_xlate(struct kvm_vcpu *vcpu, gva_t eaddr, ...@@ -415,20 +415,24 @@ static int kvmppc_mmu_book3s_64_hv_xlate(struct kvm_vcpu *vcpu, gva_t eaddr,
* embodied here.) If the instruction isn't a load or store, then * embodied here.) If the instruction isn't a load or store, then
* this doesn't return anything useful. * this doesn't return anything useful.
*/ */
static int instruction_is_store(unsigned int instr) static int instruction_is_store(ppc_inst_t instr)
{ {
unsigned int mask; unsigned int mask;
unsigned int suffix;
mask = 0x10000000; mask = 0x10000000;
if ((instr & 0xfc000000) == 0x7c000000) suffix = ppc_inst_val(instr);
if (ppc_inst_prefixed(instr))
suffix = ppc_inst_suffix(instr);
else if ((suffix & 0xfc000000) == 0x7c000000)
mask = 0x100; /* major opcode 31 */ mask = 0x100; /* major opcode 31 */
return (instr & mask) != 0; return (suffix & mask) != 0;
} }
int kvmppc_hv_emulate_mmio(struct kvm_vcpu *vcpu, int kvmppc_hv_emulate_mmio(struct kvm_vcpu *vcpu,
unsigned long gpa, gva_t ea, int is_store) unsigned long gpa, gva_t ea, int is_store)
{ {
u32 last_inst; ppc_inst_t last_inst;
/* /*
* Fast path - check if the guest physical address corresponds to a * Fast path - check if the guest physical address corresponds to a
......
...@@ -1412,7 +1412,7 @@ static int kvmppc_hcall_impl_hv(unsigned long cmd) ...@@ -1412,7 +1412,7 @@ static int kvmppc_hcall_impl_hv(unsigned long cmd)
static int kvmppc_emulate_debug_inst(struct kvm_vcpu *vcpu) static int kvmppc_emulate_debug_inst(struct kvm_vcpu *vcpu)
{ {
u32 last_inst; ppc_inst_t last_inst;
if (kvmppc_get_last_inst(vcpu, INST_GENERIC, &last_inst) != if (kvmppc_get_last_inst(vcpu, INST_GENERIC, &last_inst) !=
EMULATE_DONE) { EMULATE_DONE) {
...@@ -1423,7 +1423,7 @@ static int kvmppc_emulate_debug_inst(struct kvm_vcpu *vcpu) ...@@ -1423,7 +1423,7 @@ static int kvmppc_emulate_debug_inst(struct kvm_vcpu *vcpu)
return RESUME_GUEST; return RESUME_GUEST;
} }
if (last_inst == KVMPPC_INST_SW_BREAKPOINT) { if (ppc_inst_val(last_inst) == KVMPPC_INST_SW_BREAKPOINT) {
vcpu->run->exit_reason = KVM_EXIT_DEBUG; vcpu->run->exit_reason = KVM_EXIT_DEBUG;
vcpu->run->debug.arch.address = kvmppc_get_pc(vcpu); vcpu->run->debug.arch.address = kvmppc_get_pc(vcpu);
return RESUME_HOST; return RESUME_HOST;
...@@ -1477,9 +1477,11 @@ static int kvmppc_emulate_doorbell_instr(struct kvm_vcpu *vcpu) ...@@ -1477,9 +1477,11 @@ static int kvmppc_emulate_doorbell_instr(struct kvm_vcpu *vcpu)
unsigned long arg; unsigned long arg;
struct kvm *kvm = vcpu->kvm; struct kvm *kvm = vcpu->kvm;
struct kvm_vcpu *tvcpu; struct kvm_vcpu *tvcpu;
ppc_inst_t pinst;
if (kvmppc_get_last_inst(vcpu, INST_GENERIC, &inst) != EMULATE_DONE) if (kvmppc_get_last_inst(vcpu, INST_GENERIC, &pinst) != EMULATE_DONE)
return RESUME_GUEST; return RESUME_GUEST;
inst = ppc_inst_val(pinst);
if (get_op(inst) != 31) if (get_op(inst) != 31)
return EMULATE_FAIL; return EMULATE_FAIL;
rb = get_rb(inst); rb = get_rb(inst);
...@@ -2003,14 +2005,15 @@ static int kvmppc_handle_nested_exit(struct kvm_vcpu *vcpu) ...@@ -2003,14 +2005,15 @@ static int kvmppc_handle_nested_exit(struct kvm_vcpu *vcpu)
*/ */
if (!(vcpu->arch.hfscr_permitted & (1UL << cause)) || if (!(vcpu->arch.hfscr_permitted & (1UL << cause)) ||
(vcpu->arch.nested_hfscr & (1UL << cause))) { (vcpu->arch.nested_hfscr & (1UL << cause))) {
ppc_inst_t pinst;
vcpu->arch.trap = BOOK3S_INTERRUPT_H_EMUL_ASSIST; vcpu->arch.trap = BOOK3S_INTERRUPT_H_EMUL_ASSIST;
/* /*
* If the fetch failed, return to guest and * If the fetch failed, return to guest and
* try executing it again. * try executing it again.
*/ */
r = kvmppc_get_last_inst(vcpu, INST_GENERIC, r = kvmppc_get_last_inst(vcpu, INST_GENERIC, &pinst);
&vcpu->arch.emul_inst); vcpu->arch.emul_inst = ppc_inst_val(pinst);
if (r != EMULATE_DONE) if (r != EMULATE_DONE)
r = RESUME_GUEST; r = RESUME_GUEST;
else else
......
...@@ -621,6 +621,7 @@ static int kvmppc_ps_one_in(struct kvm_vcpu *vcpu, bool rc, ...@@ -621,6 +621,7 @@ static int kvmppc_ps_one_in(struct kvm_vcpu *vcpu, bool rc,
int kvmppc_emulate_paired_single(struct kvm_vcpu *vcpu) int kvmppc_emulate_paired_single(struct kvm_vcpu *vcpu)
{ {
u32 inst; u32 inst;
ppc_inst_t pinst;
enum emulation_result emulated = EMULATE_DONE; enum emulation_result emulated = EMULATE_DONE;
int ax_rd, ax_ra, ax_rb, ax_rc; int ax_rd, ax_ra, ax_rb, ax_rc;
short full_d; short full_d;
...@@ -632,7 +633,8 @@ int kvmppc_emulate_paired_single(struct kvm_vcpu *vcpu) ...@@ -632,7 +633,8 @@ int kvmppc_emulate_paired_single(struct kvm_vcpu *vcpu)
int i; int i;
#endif #endif
emulated = kvmppc_get_last_inst(vcpu, INST_GENERIC, &inst); emulated = kvmppc_get_last_inst(vcpu, INST_GENERIC, &pinst);
inst = ppc_inst_val(pinst);
if (emulated != EMULATE_DONE) if (emulated != EMULATE_DONE)
return emulated; return emulated;
......
...@@ -1079,7 +1079,7 @@ static int kvmppc_exit_pr_progint(struct kvm_vcpu *vcpu, unsigned int exit_nr) ...@@ -1079,7 +1079,7 @@ static int kvmppc_exit_pr_progint(struct kvm_vcpu *vcpu, unsigned int exit_nr)
{ {
enum emulation_result er; enum emulation_result er;
ulong flags; ulong flags;
u32 last_inst; ppc_inst_t last_inst;
int emul, r; int emul, r;
/* /*
...@@ -1100,9 +1100,9 @@ static int kvmppc_exit_pr_progint(struct kvm_vcpu *vcpu, unsigned int exit_nr) ...@@ -1100,9 +1100,9 @@ static int kvmppc_exit_pr_progint(struct kvm_vcpu *vcpu, unsigned int exit_nr)
if (kvmppc_get_msr(vcpu) & MSR_PR) { if (kvmppc_get_msr(vcpu) & MSR_PR) {
#ifdef EXIT_DEBUG #ifdef EXIT_DEBUG
pr_info("Userspace triggered 0x700 exception at\n 0x%lx (0x%x)\n", pr_info("Userspace triggered 0x700 exception at\n 0x%lx (0x%x)\n",
kvmppc_get_pc(vcpu), last_inst); kvmppc_get_pc(vcpu), ppc_inst_val(last_inst));
#endif #endif
if ((last_inst & 0xff0007ff) != (INS_DCBZ & 0xfffffff7)) { if ((ppc_inst_val(last_inst) & 0xff0007ff) != (INS_DCBZ & 0xfffffff7)) {
kvmppc_core_queue_program(vcpu, flags); kvmppc_core_queue_program(vcpu, flags);
return RESUME_GUEST; return RESUME_GUEST;
} }
...@@ -1119,7 +1119,7 @@ static int kvmppc_exit_pr_progint(struct kvm_vcpu *vcpu, unsigned int exit_nr) ...@@ -1119,7 +1119,7 @@ static int kvmppc_exit_pr_progint(struct kvm_vcpu *vcpu, unsigned int exit_nr)
break; break;
case EMULATE_FAIL: case EMULATE_FAIL:
pr_crit("%s: emulation at %lx failed (%08x)\n", pr_crit("%s: emulation at %lx failed (%08x)\n",
__func__, kvmppc_get_pc(vcpu), last_inst); __func__, kvmppc_get_pc(vcpu), ppc_inst_val(last_inst));
kvmppc_core_queue_program(vcpu, flags); kvmppc_core_queue_program(vcpu, flags);
r = RESUME_GUEST; r = RESUME_GUEST;
break; break;
...@@ -1281,7 +1281,7 @@ int kvmppc_handle_exit_pr(struct kvm_vcpu *vcpu, unsigned int exit_nr) ...@@ -1281,7 +1281,7 @@ int kvmppc_handle_exit_pr(struct kvm_vcpu *vcpu, unsigned int exit_nr)
break; break;
case BOOK3S_INTERRUPT_SYSCALL: case BOOK3S_INTERRUPT_SYSCALL:
{ {
u32 last_sc; ppc_inst_t last_sc;
int emul; int emul;
/* Get last sc for papr */ /* Get last sc for papr */
...@@ -1296,7 +1296,7 @@ int kvmppc_handle_exit_pr(struct kvm_vcpu *vcpu, unsigned int exit_nr) ...@@ -1296,7 +1296,7 @@ int kvmppc_handle_exit_pr(struct kvm_vcpu *vcpu, unsigned int exit_nr)
} }
if (vcpu->arch.papr_enabled && if (vcpu->arch.papr_enabled &&
(last_sc == 0x44000022) && (ppc_inst_val(last_sc) == 0x44000022) &&
!(kvmppc_get_msr(vcpu) & MSR_PR)) { !(kvmppc_get_msr(vcpu) & MSR_PR)) {
/* SC 1 papr hypercalls */ /* SC 1 papr hypercalls */
ulong cmd = kvmppc_get_gpr(vcpu, 3); ulong cmd = kvmppc_get_gpr(vcpu, 3);
...@@ -1348,7 +1348,7 @@ int kvmppc_handle_exit_pr(struct kvm_vcpu *vcpu, unsigned int exit_nr) ...@@ -1348,7 +1348,7 @@ int kvmppc_handle_exit_pr(struct kvm_vcpu *vcpu, unsigned int exit_nr)
{ {
int ext_msr = 0; int ext_msr = 0;
int emul; int emul;
u32 last_inst; ppc_inst_t last_inst;
if (vcpu->arch.hflags & BOOK3S_HFLAG_PAIRED_SINGLE) { if (vcpu->arch.hflags & BOOK3S_HFLAG_PAIRED_SINGLE) {
/* Do paired single instruction emulation */ /* Do paired single instruction emulation */
...@@ -1382,15 +1382,15 @@ int kvmppc_handle_exit_pr(struct kvm_vcpu *vcpu, unsigned int exit_nr) ...@@ -1382,15 +1382,15 @@ int kvmppc_handle_exit_pr(struct kvm_vcpu *vcpu, unsigned int exit_nr)
} }
case BOOK3S_INTERRUPT_ALIGNMENT: case BOOK3S_INTERRUPT_ALIGNMENT:
{ {
u32 last_inst; ppc_inst_t last_inst;
int emul = kvmppc_get_last_inst(vcpu, INST_GENERIC, &last_inst); int emul = kvmppc_get_last_inst(vcpu, INST_GENERIC, &last_inst);
if (emul == EMULATE_DONE) { if (emul == EMULATE_DONE) {
u32 dsisr; u32 dsisr;
u64 dar; u64 dar;
dsisr = kvmppc_alignment_dsisr(vcpu, last_inst); dsisr = kvmppc_alignment_dsisr(vcpu, ppc_inst_val(last_inst));
dar = kvmppc_alignment_dar(vcpu, last_inst); dar = kvmppc_alignment_dar(vcpu, ppc_inst_val(last_inst));
kvmppc_set_dsisr(vcpu, dsisr); kvmppc_set_dsisr(vcpu, dsisr);
kvmppc_set_dar(vcpu, dar); kvmppc_set_dar(vcpu, dar);
......
...@@ -1015,6 +1015,7 @@ int kvmppc_handle_exit(struct kvm_vcpu *vcpu, unsigned int exit_nr) ...@@ -1015,6 +1015,7 @@ int kvmppc_handle_exit(struct kvm_vcpu *vcpu, unsigned int exit_nr)
int s; int s;
int idx; int idx;
u32 last_inst = KVM_INST_FETCH_FAILED; u32 last_inst = KVM_INST_FETCH_FAILED;
ppc_inst_t pinst;
enum emulation_result emulated = EMULATE_DONE; enum emulation_result emulated = EMULATE_DONE;
/* Fix irq state (pairs with kvmppc_fix_ee_before_entry()) */ /* Fix irq state (pairs with kvmppc_fix_ee_before_entry()) */
...@@ -1034,12 +1035,15 @@ int kvmppc_handle_exit(struct kvm_vcpu *vcpu, unsigned int exit_nr) ...@@ -1034,12 +1035,15 @@ int kvmppc_handle_exit(struct kvm_vcpu *vcpu, unsigned int exit_nr)
case BOOKE_INTERRUPT_DATA_STORAGE: case BOOKE_INTERRUPT_DATA_STORAGE:
case BOOKE_INTERRUPT_DTLB_MISS: case BOOKE_INTERRUPT_DTLB_MISS:
case BOOKE_INTERRUPT_HV_PRIV: case BOOKE_INTERRUPT_HV_PRIV:
emulated = kvmppc_get_last_inst(vcpu, INST_GENERIC, &last_inst); emulated = kvmppc_get_last_inst(vcpu, INST_GENERIC, &pinst);
last_inst = ppc_inst_val(pinst);
break; break;
case BOOKE_INTERRUPT_PROGRAM: case BOOKE_INTERRUPT_PROGRAM:
/* SW breakpoints arrive as illegal instructions on HV */ /* SW breakpoints arrive as illegal instructions on HV */
if (vcpu->guest_debug & KVM_GUESTDBG_USE_SW_BP) if (vcpu->guest_debug & KVM_GUESTDBG_USE_SW_BP) {
emulated = kvmppc_get_last_inst(vcpu, INST_GENERIC, &last_inst); emulated = kvmppc_get_last_inst(vcpu, INST_GENERIC, &pinst);
last_inst = ppc_inst_val(pinst);
}
break; break;
default: default:
break; break;
......
...@@ -194,6 +194,7 @@ static int kvmppc_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn, int rt) ...@@ -194,6 +194,7 @@ static int kvmppc_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn, int rt)
int kvmppc_emulate_instruction(struct kvm_vcpu *vcpu) int kvmppc_emulate_instruction(struct kvm_vcpu *vcpu)
{ {
u32 inst; u32 inst;
ppc_inst_t pinst;
int rs, rt, sprn; int rs, rt, sprn;
enum emulation_result emulated; enum emulation_result emulated;
int advance = 1; int advance = 1;
...@@ -201,7 +202,8 @@ int kvmppc_emulate_instruction(struct kvm_vcpu *vcpu) ...@@ -201,7 +202,8 @@ int kvmppc_emulate_instruction(struct kvm_vcpu *vcpu)
/* this default type might be overwritten by subcategories */ /* this default type might be overwritten by subcategories */
kvmppc_set_exit_type(vcpu, EMULATED_INST_EXITS); kvmppc_set_exit_type(vcpu, EMULATED_INST_EXITS);
emulated = kvmppc_get_last_inst(vcpu, INST_GENERIC, &inst); emulated = kvmppc_get_last_inst(vcpu, INST_GENERIC, &pinst);
inst = ppc_inst_val(pinst);
if (emulated != EMULATE_DONE) if (emulated != EMULATE_DONE)
return emulated; return emulated;
......
...@@ -71,7 +71,7 @@ static bool kvmppc_check_altivec_disabled(struct kvm_vcpu *vcpu) ...@@ -71,7 +71,7 @@ static bool kvmppc_check_altivec_disabled(struct kvm_vcpu *vcpu)
*/ */
int kvmppc_emulate_loadstore(struct kvm_vcpu *vcpu) int kvmppc_emulate_loadstore(struct kvm_vcpu *vcpu)
{ {
u32 inst; ppc_inst_t inst;
enum emulation_result emulated = EMULATE_FAIL; enum emulation_result emulated = EMULATE_FAIL;
struct instruction_op op; struct instruction_op op;
...@@ -93,7 +93,7 @@ int kvmppc_emulate_loadstore(struct kvm_vcpu *vcpu) ...@@ -93,7 +93,7 @@ int kvmppc_emulate_loadstore(struct kvm_vcpu *vcpu)
emulated = EMULATE_FAIL; emulated = EMULATE_FAIL;
vcpu->arch.regs.msr = vcpu->arch.shared->msr; vcpu->arch.regs.msr = vcpu->arch.shared->msr;
if (analyse_instr(&op, &vcpu->arch.regs, ppc_inst(inst)) == 0) { if (analyse_instr(&op, &vcpu->arch.regs, inst) == 0) {
int type = op.type & INSTR_TYPE_MASK; int type = op.type & INSTR_TYPE_MASK;
int size = GETSIZE(op.type); int size = GETSIZE(op.type);
...@@ -356,7 +356,7 @@ int kvmppc_emulate_loadstore(struct kvm_vcpu *vcpu) ...@@ -356,7 +356,7 @@ int kvmppc_emulate_loadstore(struct kvm_vcpu *vcpu)
} }
} }
trace_kvm_ppc_instr(inst, kvmppc_get_pc(vcpu), emulated); trace_kvm_ppc_instr(ppc_inst_val(inst), kvmppc_get_pc(vcpu), emulated);
/* Advance past emulated instruction. */ /* Advance past emulated instruction. */
if (emulated != EMULATE_FAIL) if (emulated != EMULATE_FAIL)
......
...@@ -304,11 +304,11 @@ int kvmppc_emulate_mmio(struct kvm_vcpu *vcpu) ...@@ -304,11 +304,11 @@ int kvmppc_emulate_mmio(struct kvm_vcpu *vcpu)
break; break;
case EMULATE_FAIL: case EMULATE_FAIL:
{ {
u32 last_inst; ppc_inst_t last_inst;
kvmppc_get_last_inst(vcpu, INST_GENERIC, &last_inst); kvmppc_get_last_inst(vcpu, INST_GENERIC, &last_inst);
kvm_debug_ratelimited("Guest access to device memory using unsupported instruction (opcode: %#08x)\n", kvm_debug_ratelimited("Guest access to device memory using unsupported instruction (opcode: %#08x)\n",
last_inst); ppc_inst_val(last_inst));
/* /*
* Injecting a Data Storage here is a bit more * Injecting a Data Storage here is a bit more
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment