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

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
Loading
Loading
Loading
Loading
+3 −2
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@
#include <asm/xive.h>
#include <asm/cpu_has_feature.h>
#endif
#include <asm/inst.h>

/*
 * KVMPPC_INST_SW_BREAKPOINT is debug Instruction
@@ -324,7 +325,7 @@ extern struct kvmppc_ops *kvmppc_hv_ops;
extern struct kvmppc_ops *kvmppc_pr_ops;

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;
	u32 fetched_inst;
@@ -342,7 +343,7 @@ static inline int kvmppc_get_last_inst(struct kvm_vcpu *vcpu,
	else
		fetched_inst = vcpu->arch.last_inst;

	*inst = fetched_inst;
	*inst = ppc_inst(fetched_inst);
	return ret;
}

+8 −4
Original line number Diff line number Diff line
@@ -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
 * 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 suffix;

	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 */
	return (instr & mask) != 0;
	return (suffix & mask) != 0;
}

int kvmppc_hv_emulate_mmio(struct kvm_vcpu *vcpu,
			   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
+8 −5
Original line number Diff line number Diff line
@@ -1412,7 +1412,7 @@ static int kvmppc_hcall_impl_hv(unsigned long cmd)

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) !=
					EMULATE_DONE) {
@@ -1423,7 +1423,7 @@ static int kvmppc_emulate_debug_inst(struct kvm_vcpu *vcpu)
		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->debug.arch.address = kvmppc_get_pc(vcpu);
		return RESUME_HOST;
@@ -1477,9 +1477,11 @@ static int kvmppc_emulate_doorbell_instr(struct kvm_vcpu *vcpu)
	unsigned long arg;
	struct kvm *kvm = vcpu->kvm;
	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;
	inst = ppc_inst_val(pinst);
	if (get_op(inst) != 31)
		return EMULATE_FAIL;
	rb = get_rb(inst);
@@ -2003,14 +2005,15 @@ static int kvmppc_handle_nested_exit(struct kvm_vcpu *vcpu)
		 */
		if (!(vcpu->arch.hfscr_permitted & (1UL << cause)) ||
				(vcpu->arch.nested_hfscr & (1UL << cause))) {
			ppc_inst_t pinst;
			vcpu->arch.trap = BOOK3S_INTERRUPT_H_EMUL_ASSIST;

			/*
			 * If the fetch failed, return to guest and
			 * try executing it again.
			 */
			r = kvmppc_get_last_inst(vcpu, INST_GENERIC,
						 &vcpu->arch.emul_inst);
			r = kvmppc_get_last_inst(vcpu, INST_GENERIC, &pinst);
			vcpu->arch.emul_inst = ppc_inst_val(pinst);
			if (r != EMULATE_DONE)
				r = RESUME_GUEST;
			else
+3 −1
Original line number Diff line number Diff line
@@ -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)
{
	u32 inst;
	ppc_inst_t pinst;
	enum emulation_result emulated = EMULATE_DONE;
	int ax_rd, ax_ra, ax_rb, ax_rc;
	short full_d;
@@ -632,7 +633,8 @@ int kvmppc_emulate_paired_single(struct kvm_vcpu *vcpu)
	int i;
#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)
		return emulated;

+10 −10
Original line number Diff line number Diff line
@@ -1079,7 +1079,7 @@ static int kvmppc_exit_pr_progint(struct kvm_vcpu *vcpu, unsigned int exit_nr)
{
	enum emulation_result er;
	ulong flags;
	u32 last_inst;
	ppc_inst_t last_inst;
	int emul, r;

	/*
@@ -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) {
#ifdef EXIT_DEBUG
		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
		if ((last_inst & 0xff0007ff) != (INS_DCBZ & 0xfffffff7)) {
		if ((ppc_inst_val(last_inst) & 0xff0007ff) != (INS_DCBZ & 0xfffffff7)) {
			kvmppc_core_queue_program(vcpu, flags);
			return RESUME_GUEST;
		}
@@ -1119,7 +1119,7 @@ static int kvmppc_exit_pr_progint(struct kvm_vcpu *vcpu, unsigned int exit_nr)
		break;
	case EMULATE_FAIL:
		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);
		r = RESUME_GUEST;
		break;
@@ -1281,7 +1281,7 @@ int kvmppc_handle_exit_pr(struct kvm_vcpu *vcpu, unsigned int exit_nr)
		break;
	case BOOK3S_INTERRUPT_SYSCALL:
	{
		u32 last_sc;
		ppc_inst_t last_sc;
		int emul;

		/* Get last sc for papr */
@@ -1296,7 +1296,7 @@ int kvmppc_handle_exit_pr(struct kvm_vcpu *vcpu, unsigned int exit_nr)
		}

		if (vcpu->arch.papr_enabled &&
		    (last_sc == 0x44000022) &&
		    (ppc_inst_val(last_sc) == 0x44000022) &&
		    !(kvmppc_get_msr(vcpu) & MSR_PR)) {
			/* SC 1 papr hypercalls */
			ulong cmd = kvmppc_get_gpr(vcpu, 3);
@@ -1348,7 +1348,7 @@ int kvmppc_handle_exit_pr(struct kvm_vcpu *vcpu, unsigned int exit_nr)
	{
		int ext_msr = 0;
		int emul;
		u32 last_inst;
		ppc_inst_t last_inst;

		if (vcpu->arch.hflags & BOOK3S_HFLAG_PAIRED_SINGLE) {
			/* Do paired single instruction emulation */
@@ -1382,15 +1382,15 @@ int kvmppc_handle_exit_pr(struct kvm_vcpu *vcpu, unsigned int exit_nr)
	}
	case BOOK3S_INTERRUPT_ALIGNMENT:
	{
		u32 last_inst;
		ppc_inst_t last_inst;
		int emul = kvmppc_get_last_inst(vcpu, INST_GENERIC, &last_inst);

		if (emul == EMULATE_DONE) {
			u32 dsisr;
			u64 dar;

			dsisr = kvmppc_alignment_dsisr(vcpu, last_inst);
			dar = kvmppc_alignment_dar(vcpu, last_inst);
			dsisr = kvmppc_alignment_dsisr(vcpu, ppc_inst_val(last_inst));
			dar = kvmppc_alignment_dar(vcpu, ppc_inst_val(last_inst));

			kvmppc_set_dsisr(vcpu, dsisr);
			kvmppc_set_dar(vcpu, dar);
Loading