Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 133664
b: refs/heads/master
c: d0bfb94
h: refs/heads/master
v: v3
  • Loading branch information
Jan Kiszka authored and Avi Kivity committed Mar 24, 2009
1 parent 5d8988e commit 51ed5f5
Show file tree
Hide file tree
Showing 15 changed files with 180 additions and 102 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 8ab2d2e231062814bd89bba2d6d92563190aa2bb
refs/heads/master: d0bfb940ecabf0b44fb1fd80d8d60594e569e5ec
7 changes: 7 additions & 0 deletions trunk/arch/ia64/include/asm/kvm.h
Original file line number Diff line number Diff line change
Expand Up @@ -214,4 +214,11 @@ struct kvm_sregs {
struct kvm_fpu {
};

struct kvm_debug_exit_arch {
};

/* for KVM_SET_GUEST_DEBUG */
struct kvm_guest_debug_arch {
};

#endif
4 changes: 2 additions & 2 deletions trunk/arch/ia64/kvm/kvm-ia64.c
Original file line number Diff line number Diff line change
Expand Up @@ -1303,8 +1303,8 @@ int kvm_arch_vcpu_ioctl_set_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu)
return -EINVAL;
}

int kvm_arch_vcpu_ioctl_debug_guest(struct kvm_vcpu *vcpu,
struct kvm_debug_guest *dbg)
int kvm_arch_vcpu_ioctl_set_guest_debug(struct kvm_vcpu *vcpu,
struct kvm_guest_debug *dbg)
{
return -EINVAL;
}
Expand Down
7 changes: 7 additions & 0 deletions trunk/arch/powerpc/include/asm/kvm.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,4 +52,11 @@ struct kvm_fpu {
__u64 fpr[32];
};

struct kvm_debug_exit_arch {
};

/* for KVM_SET_GUEST_DEBUG */
struct kvm_guest_debug_arch {
};

#endif /* __LINUX_KVM_POWERPC_H */
4 changes: 2 additions & 2 deletions trunk/arch/powerpc/kvm/powerpc.c
Original file line number Diff line number Diff line change
Expand Up @@ -240,8 +240,8 @@ void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
kvmppc_core_vcpu_put(vcpu);
}

int kvm_arch_vcpu_ioctl_debug_guest(struct kvm_vcpu *vcpu,
struct kvm_debug_guest *dbg)
int kvm_arch_vcpu_ioctl_set_guest_debug(struct kvm_vcpu *vcpu,
struct kvm_guest_debug *dbg)
{
int i;

Expand Down
7 changes: 7 additions & 0 deletions trunk/arch/s390/include/asm/kvm.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,11 @@ struct kvm_fpu {
__u64 fprs[16];
};

struct kvm_debug_exit_arch {
};

/* for KVM_SET_GUEST_DEBUG */
struct kvm_guest_debug_arch {
};

#endif
4 changes: 2 additions & 2 deletions trunk/arch/s390/kvm/kvm-s390.c
Original file line number Diff line number Diff line change
Expand Up @@ -422,8 +422,8 @@ int kvm_arch_vcpu_ioctl_translate(struct kvm_vcpu *vcpu,
return -EINVAL; /* not implemented yet */
}

int kvm_arch_vcpu_ioctl_debug_guest(struct kvm_vcpu *vcpu,
struct kvm_debug_guest *dbg)
int kvm_arch_vcpu_ioctl_set_guest_debug(struct kvm_vcpu *vcpu,
struct kvm_guest_debug *dbg)
{
return -EINVAL; /* not implemented yet */
}
Expand Down
18 changes: 18 additions & 0 deletions trunk/arch/x86/include/asm/kvm.h
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,24 @@ struct kvm_pit_channel_state {
__s64 count_load_time;
};

struct kvm_debug_exit_arch {
__u32 exception;
__u32 pad;
__u64 pc;
__u64 dr6;
__u64 dr7;
};

#define KVM_GUESTDBG_USE_SW_BP 0x00010000
#define KVM_GUESTDBG_USE_HW_BP 0x00020000
#define KVM_GUESTDBG_INJECT_DB 0x00040000
#define KVM_GUESTDBG_INJECT_BP 0x00080000

/* for KVM_SET_GUEST_DEBUG */
struct kvm_guest_debug_arch {
__u64 debugreg[8];
};

struct kvm_pit_state {
struct kvm_pit_channel_state channels[3];
};
Expand Down
9 changes: 1 addition & 8 deletions trunk/arch/x86/include/asm/kvm_host.h
Original file line number Diff line number Diff line change
Expand Up @@ -135,12 +135,6 @@ enum {

#define KVM_NR_MEM_OBJS 40

struct kvm_guest_debug {
int enabled;
unsigned long bp[4];
int singlestep;
};

/*
* We don't want allocation failures within the mmu code, so we preallocate
* enough memory for a single page fault in a cache.
Expand Down Expand Up @@ -448,8 +442,7 @@ struct kvm_x86_ops {
void (*vcpu_put)(struct kvm_vcpu *vcpu);

int (*set_guest_debug)(struct kvm_vcpu *vcpu,
struct kvm_debug_guest *dbg);
void (*guest_debug_pre)(struct kvm_vcpu *vcpu);
struct kvm_guest_debug *dbg);
int (*get_msr)(struct kvm_vcpu *vcpu, u32 msr_index, u64 *pdata);
int (*set_msr)(struct kvm_vcpu *vcpu, u32 msr_index, u64 data);
u64 (*get_segment_base)(struct kvm_vcpu *vcpu, int seg);
Expand Down
50 changes: 48 additions & 2 deletions trunk/arch/x86/kvm/svm.c
Original file line number Diff line number Diff line change
Expand Up @@ -968,9 +968,32 @@ static void svm_set_segment(struct kvm_vcpu *vcpu,

}

static int svm_guest_debug(struct kvm_vcpu *vcpu, struct kvm_debug_guest *dbg)
static int svm_guest_debug(struct kvm_vcpu *vcpu, struct kvm_guest_debug *dbg)
{
return -EOPNOTSUPP;
int old_debug = vcpu->guest_debug;
struct vcpu_svm *svm = to_svm(vcpu);

vcpu->guest_debug = dbg->control;

svm->vmcb->control.intercept_exceptions &=
~((1 << DB_VECTOR) | (1 << BP_VECTOR));
if (vcpu->guest_debug & KVM_GUESTDBG_ENABLE) {
if (vcpu->guest_debug &
(KVM_GUESTDBG_SINGLESTEP | KVM_GUESTDBG_USE_HW_BP))
svm->vmcb->control.intercept_exceptions |=
1 << DB_VECTOR;
if (vcpu->guest_debug & KVM_GUESTDBG_USE_SW_BP)
svm->vmcb->control.intercept_exceptions |=
1 << BP_VECTOR;
} else
vcpu->guest_debug = 0;

if (vcpu->guest_debug & KVM_GUESTDBG_SINGLESTEP)
svm->vmcb->save.rflags |= X86_EFLAGS_TF | X86_EFLAGS_RF;
else if (old_debug & KVM_GUESTDBG_SINGLESTEP)
svm->vmcb->save.rflags &= ~(X86_EFLAGS_TF | X86_EFLAGS_RF);

return 0;
}

static int svm_get_irq(struct kvm_vcpu *vcpu)
Expand Down Expand Up @@ -1094,6 +1117,27 @@ static int pf_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run)
return kvm_mmu_page_fault(&svm->vcpu, fault_address, error_code);
}

static int db_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run)
{
if (!(svm->vcpu.guest_debug &
(KVM_GUESTDBG_SINGLESTEP | KVM_GUESTDBG_USE_HW_BP))) {
kvm_queue_exception(&svm->vcpu, DB_VECTOR);
return 1;
}
kvm_run->exit_reason = KVM_EXIT_DEBUG;
kvm_run->debug.arch.pc = svm->vmcb->save.cs.base + svm->vmcb->save.rip;
kvm_run->debug.arch.exception = DB_VECTOR;
return 0;
}

static int bp_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run)
{
kvm_run->exit_reason = KVM_EXIT_DEBUG;
kvm_run->debug.arch.pc = svm->vmcb->save.cs.base + svm->vmcb->save.rip;
kvm_run->debug.arch.exception = BP_VECTOR;
return 0;
}

static int ud_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run)
{
int er;
Expand Down Expand Up @@ -2050,6 +2094,8 @@ static int (*svm_exit_handlers[])(struct vcpu_svm *svm,
[SVM_EXIT_WRITE_DR3] = emulate_on_interception,
[SVM_EXIT_WRITE_DR5] = emulate_on_interception,
[SVM_EXIT_WRITE_DR7] = emulate_on_interception,
[SVM_EXIT_EXCP_BASE + DB_VECTOR] = db_interception,
[SVM_EXIT_EXCP_BASE + BP_VECTOR] = bp_interception,
[SVM_EXIT_EXCP_BASE + UD_VECTOR] = ud_interception,
[SVM_EXIT_EXCP_BASE + PF_VECTOR] = pf_interception,
[SVM_EXIT_EXCP_BASE + NM_VECTOR] = nm_interception,
Expand Down
93 changes: 36 additions & 57 deletions trunk/arch/x86/kvm/vmx.c
Original file line number Diff line number Diff line change
Expand Up @@ -480,8 +480,13 @@ static void update_exception_bitmap(struct kvm_vcpu *vcpu)
eb = (1u << PF_VECTOR) | (1u << UD_VECTOR);
if (!vcpu->fpu_active)
eb |= 1u << NM_VECTOR;
if (vcpu->guest_debug.enabled)
eb |= 1u << DB_VECTOR;
if (vcpu->guest_debug & KVM_GUESTDBG_ENABLE) {
if (vcpu->guest_debug &
(KVM_GUESTDBG_SINGLESTEP | KVM_GUESTDBG_USE_HW_BP))
eb |= 1u << DB_VECTOR;
if (vcpu->guest_debug & KVM_GUESTDBG_USE_SW_BP)
eb |= 1u << BP_VECTOR;
}
if (vcpu->arch.rmode.active)
eb = ~0;
if (vm_need_ept())
Expand Down Expand Up @@ -1003,40 +1008,23 @@ static void vmx_cache_reg(struct kvm_vcpu *vcpu, enum kvm_reg reg)
}
}

static int set_guest_debug(struct kvm_vcpu *vcpu, struct kvm_debug_guest *dbg)
static int set_guest_debug(struct kvm_vcpu *vcpu, struct kvm_guest_debug *dbg)
{
unsigned long dr7 = 0x400;
int old_singlestep;

old_singlestep = vcpu->guest_debug.singlestep;

vcpu->guest_debug.enabled = dbg->enabled;
if (vcpu->guest_debug.enabled) {
int i;

dr7 |= 0x200; /* exact */
for (i = 0; i < 4; ++i) {
if (!dbg->breakpoints[i].enabled)
continue;
vcpu->guest_debug.bp[i] = dbg->breakpoints[i].address;
dr7 |= 2 << (i*2); /* global enable */
dr7 |= 0 << (i*4+16); /* execution breakpoint */
}

vcpu->guest_debug.singlestep = dbg->singlestep;
} else
vcpu->guest_debug.singlestep = 0;
int old_debug = vcpu->guest_debug;
unsigned long flags;

if (old_singlestep && !vcpu->guest_debug.singlestep) {
unsigned long flags;
vcpu->guest_debug = dbg->control;
if (!(vcpu->guest_debug & KVM_GUESTDBG_ENABLE))
vcpu->guest_debug = 0;

flags = vmcs_readl(GUEST_RFLAGS);
flags = vmcs_readl(GUEST_RFLAGS);
if (vcpu->guest_debug & KVM_GUESTDBG_SINGLESTEP)
flags |= X86_EFLAGS_TF | X86_EFLAGS_RF;
else if (old_debug & KVM_GUESTDBG_SINGLESTEP)
flags &= ~(X86_EFLAGS_TF | X86_EFLAGS_RF);
vmcs_writel(GUEST_RFLAGS, flags);
}
vmcs_writel(GUEST_RFLAGS, flags);

update_exception_bitmap(vcpu);
vmcs_writel(GUEST_DR7, dr7);

return 0;
}
Expand Down Expand Up @@ -2540,24 +2528,6 @@ static int vmx_set_tss_addr(struct kvm *kvm, unsigned int addr)
return 0;
}

static void kvm_guest_debug_pre(struct kvm_vcpu *vcpu)
{
struct kvm_guest_debug *dbg = &vcpu->guest_debug;

set_debugreg(dbg->bp[0], 0);
set_debugreg(dbg->bp[1], 1);
set_debugreg(dbg->bp[2], 2);
set_debugreg(dbg->bp[3], 3);

if (dbg->singlestep) {
unsigned long flags;

flags = vmcs_readl(GUEST_RFLAGS);
flags |= X86_EFLAGS_TF | X86_EFLAGS_RF;
vmcs_writel(GUEST_RFLAGS, flags);
}
}

static int handle_rmode_exception(struct kvm_vcpu *vcpu,
int vec, u32 err_code)
{
Expand All @@ -2574,9 +2544,17 @@ static int handle_rmode_exception(struct kvm_vcpu *vcpu,
* the required debugging infrastructure rework.
*/
switch (vec) {
case DE_VECTOR:
case DB_VECTOR:
if (vcpu->guest_debug &
(KVM_GUESTDBG_SINGLESTEP | KVM_GUESTDBG_USE_HW_BP))
return 0;
kvm_queue_exception(vcpu, vec);
return 1;
case BP_VECTOR:
if (vcpu->guest_debug & KVM_GUESTDBG_USE_SW_BP)
return 0;
/* fall through */
case DE_VECTOR:
case OF_VECTOR:
case BR_VECTOR:
case UD_VECTOR:
Expand All @@ -2593,7 +2571,7 @@ static int handle_rmode_exception(struct kvm_vcpu *vcpu,
static int handle_exception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
{
struct vcpu_vmx *vmx = to_vmx(vcpu);
u32 intr_info, error_code;
u32 intr_info, ex_no, error_code;
unsigned long cr2, rip;
u32 vect_info;
enum emulation_result er;
Expand Down Expand Up @@ -2653,14 +2631,16 @@ static int handle_exception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
return 1;
}

if ((intr_info & (INTR_INFO_INTR_TYPE_MASK | INTR_INFO_VECTOR_MASK)) ==
(INTR_TYPE_HARD_EXCEPTION | 1)) {
ex_no = intr_info & INTR_INFO_VECTOR_MASK;
if (ex_no == DB_VECTOR || ex_no == BP_VECTOR) {
kvm_run->exit_reason = KVM_EXIT_DEBUG;
return 0;
kvm_run->debug.arch.pc = vmcs_readl(GUEST_CS_BASE) + rip;
kvm_run->debug.arch.exception = ex_no;
} else {
kvm_run->exit_reason = KVM_EXIT_EXCEPTION;
kvm_run->ex.exception = ex_no;
kvm_run->ex.error_code = error_code;
}
kvm_run->exit_reason = KVM_EXIT_EXCEPTION;
kvm_run->ex.exception = intr_info & INTR_INFO_VECTOR_MASK;
kvm_run->ex.error_code = error_code;
return 0;
}

Expand Down Expand Up @@ -3600,7 +3580,6 @@ static struct kvm_x86_ops vmx_x86_ops = {
.vcpu_put = vmx_vcpu_put,

.set_guest_debug = set_guest_debug,
.guest_debug_pre = kvm_guest_debug_pre,
.get_msr = vmx_get_msr,
.set_msr = vmx_set_msr,
.get_segment_base = vmx_get_segment_base,
Expand Down
14 changes: 8 additions & 6 deletions trunk/arch/x86/kvm/x86.c
Original file line number Diff line number Diff line change
Expand Up @@ -3005,9 +3005,6 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
goto out;
}

if (vcpu->guest_debug.enabled)
kvm_x86_ops->guest_debug_pre(vcpu);

vcpu->guest_mode = 1;
/*
* Make sure that guest_mode assignment won't happen after
Expand Down Expand Up @@ -3218,7 +3215,7 @@ int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
/*
* Don't leak debug flags in case they were set for guest debugging
*/
if (vcpu->guest_debug.enabled && vcpu->guest_debug.singlestep)
if (vcpu->guest_debug & KVM_GUESTDBG_SINGLESTEP)
regs->rflags &= ~(X86_EFLAGS_TF | X86_EFLAGS_RF);

vcpu_put(vcpu);
Expand Down Expand Up @@ -3837,15 +3834,20 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,
return 0;
}

int kvm_arch_vcpu_ioctl_debug_guest(struct kvm_vcpu *vcpu,
struct kvm_debug_guest *dbg)
int kvm_arch_vcpu_ioctl_set_guest_debug(struct kvm_vcpu *vcpu,
struct kvm_guest_debug *dbg)
{
int r;

vcpu_load(vcpu);

r = kvm_x86_ops->set_guest_debug(vcpu, dbg);

if (dbg->control & KVM_GUESTDBG_INJECT_DB)
kvm_queue_exception(vcpu, DB_VECTOR);
else if (dbg->control & KVM_GUESTDBG_INJECT_BP)
kvm_queue_exception(vcpu, BP_VECTOR);

vcpu_put(vcpu);

return r;
Expand Down
Loading

0 comments on commit 51ed5f5

Please sign in to comment.