Skip to content

Commit

Permalink
KVM: PPC: E500: exit to user space on "ehpriv 1" instruction
Browse files Browse the repository at this point in the history
"ehpriv 1" instruction is used for setting software breakpoints
by user space. This patch adds support to exit to user space
with "run->debug" have relevant information.

As this is the first point we are using run->debug, also defined
the run->debug structure.

Signed-off-by: Bharat Bhushan <bharat.bhushan@freescale.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
  • Loading branch information
Bharat Bhushan authored and Alexander Graf committed Oct 17, 2013
1 parent fc82cf1 commit b12c784
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 6 deletions.
4 changes: 4 additions & 0 deletions arch/powerpc/include/asm/disassemble.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,4 +77,8 @@ static inline unsigned int get_d(u32 inst)
return inst & 0xffff;
}

static inline unsigned int get_oc(u32 inst)
{
return (inst >> 11) & 0x7fff;
}
#endif /* __ASM_PPC_DISASSEMBLE_H__ */
7 changes: 6 additions & 1 deletion arch/powerpc/include/asm/kvm_booke.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,12 @@
/* LPIDs we support with this build -- runtime limit may be lower */
#define KVMPPC_NR_LPIDS 64

#define KVMPPC_INST_EHPRIV 0x7c00021c
#define KVMPPC_INST_EHPRIV 0x7c00021c
#define EHPRIV_OC_SHIFT 11
/* "ehpriv 1" : ehpriv with OC = 1 is used for debug emulation */
#define EHPRIV_OC_DEBUG 1
#define KVMPPC_INST_EHPRIV_DEBUG (KVMPPC_INST_EHPRIV | \
(EHPRIV_OC_DEBUG << EHPRIV_OC_SHIFT))

static inline void kvmppc_set_gpr(struct kvm_vcpu *vcpu, int num, ulong val)
{
Expand Down
21 changes: 17 additions & 4 deletions arch/powerpc/include/uapi/asm/kvm.h
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,24 @@ struct kvm_fpu {
__u64 fpr[32];
};

/*
* Defines for h/w breakpoint, watchpoint (read, write or both) and
* software breakpoint.
* These are used as "type" in KVM_SET_GUEST_DEBUG ioctl and "status"
* for KVM_DEBUG_EXIT.
*/
#define KVMPPC_DEBUG_NONE 0x0
#define KVMPPC_DEBUG_BREAKPOINT (1UL << 1)
#define KVMPPC_DEBUG_WATCH_WRITE (1UL << 2)
#define KVMPPC_DEBUG_WATCH_READ (1UL << 3)
struct kvm_debug_exit_arch {
__u64 address;
/*
* exiting to userspace because of h/w breakpoint, watchpoint
* (read, write or both) and software breakpoint.
*/
__u32 status;
__u32 reserved;
};

/* for KVM_SET_GUEST_DEBUG */
Expand All @@ -281,10 +298,6 @@ struct kvm_guest_debug_arch {
* Type denotes h/w breakpoint, read watchpoint, write
* watchpoint or watchpoint (both read and write).
*/
#define KVMPPC_DEBUG_NONE 0x0
#define KVMPPC_DEBUG_BREAKPOINT (1UL << 1)
#define KVMPPC_DEBUG_WATCH_WRITE (1UL << 2)
#define KVMPPC_DEBUG_WATCH_READ (1UL << 3)
__u32 type;
__u32 reserved;
} bp[16];
Expand Down
2 changes: 1 addition & 1 deletion arch/powerpc/kvm/booke.c
Original file line number Diff line number Diff line change
Expand Up @@ -1477,7 +1477,7 @@ int kvm_vcpu_ioctl_get_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg)
val = get_reg_val(reg->id, vcpu->arch.tsr);
break;
case KVM_REG_PPC_DEBUG_INST:
val = get_reg_val(reg->id, KVMPPC_INST_EHPRIV);
val = get_reg_val(reg->id, KVMPPC_INST_EHPRIV_DEBUG);
break;
case KVM_REG_PPC_VRSAVE:
val = get_reg_val(reg->id, vcpu->arch.vrsave);
Expand Down
26 changes: 26 additions & 0 deletions arch/powerpc/kvm/e500_emulate.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#define XOP_TLBRE 946
#define XOP_TLBWE 978
#define XOP_TLBILX 18
#define XOP_EHPRIV 270

#ifdef CONFIG_KVM_E500MC
static int dbell2prio(ulong param)
Expand Down Expand Up @@ -82,6 +83,26 @@ static int kvmppc_e500_emul_msgsnd(struct kvm_vcpu *vcpu, int rb)
}
#endif

static int kvmppc_e500_emul_ehpriv(struct kvm_run *run, struct kvm_vcpu *vcpu,
unsigned int inst, int *advance)
{
int emulated = EMULATE_DONE;

switch (get_oc(inst)) {
case EHPRIV_OC_DEBUG:
run->exit_reason = KVM_EXIT_DEBUG;
run->debug.arch.address = vcpu->arch.pc;
run->debug.arch.status = 0;
kvmppc_account_exit(vcpu, DEBUG_EXITS);
emulated = EMULATE_EXIT_USER;
*advance = 0;
break;
default:
emulated = EMULATE_FAIL;
}
return emulated;
}

int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu,
unsigned int inst, int *advance)
{
Expand Down Expand Up @@ -130,6 +151,11 @@ int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu,
emulated = kvmppc_e500_emul_tlbivax(vcpu, ea);
break;

case XOP_EHPRIV:
emulated = kvmppc_e500_emul_ehpriv(run, vcpu, inst,
advance);
break;

default:
emulated = EMULATE_FAIL;
}
Expand Down

0 comments on commit b12c784

Please sign in to comment.