From: "Jan Beulich" Subject: [RFC] x86: more debugging adjustments Date: Thu, 22 Nov 2007 12:50:50 +0000 Message-ID: <4745893A.76E4.0078.0@novell.com> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=__Part2B0D243A.0__=" Return-path: List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Sender: xen-devel-bounces@lists.xensource.com Errors-To: xen-devel-bounces@lists.xensource.com To: xen-devel@lists.xensource.com List-Id: xen-devel@lists.xenproject.org This is a MIME message. If you are reading this text, you may want to consider changing to a mail reader or gateway that understands how to properly handle MIME multipart messages. --=__Part2B0D243A.0__= Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: quoted-printable Content-Disposition: inline Apart from the cleanup patches just sent I also have two bigger ones in the queue. I'm not certain they qualify for 3.2 at this point, though: = While most of them can be considered enhancements, the io-brkp one (which depends on the inject-sstep one) also fixes the issue of guests on x86-64 not being able to utilize 8-byte breakpoints, and it reduces the likelihood= of needing to restore the debug registers by only looking at the enable bits in the respective conditions (as HVM was already doing). Therefore I'd like to understand whether these patches can go in in their current shape, or whether I should split out at least the 8-byte bug fix and submit this separately. Thanks, Jan --=__Part2B0D243A.0__= Content-Type: text/plain; name="x86-io-brkp.patch" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="x86-io-brkp.patch" Index: 2007-11-13/xen/arch/x86/domain.c =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- 2007-11-13.orig/xen/arch/x86/domain.c 2007-11-12 08:47:42.0000000= 00 +0100 +++ 2007-11-13/xen/arch/x86/domain.c 2007-11-21 09:44:48.000000000 = +0100 @@ -42,6 +42,7 @@ #include #include #include +#include #include #include #include @@ -1219,7 +1220,7 @@ static void paravirt_ctxt_switch_from(st * inside Xen, before we get a chance to reload DR7, and this cannot = always * safely be handled. */ - if ( unlikely(v->arch.guest_context.debugreg[7]) ) + if ( unlikely(v->arch.guest_context.debugreg[7] & DR7_ACTIVE_MASK) ) write_debugreg(7, 0); } =20 @@ -1234,7 +1235,7 @@ static void paravirt_ctxt_switch_to(stru if ( unlikely(cr4 !=3D read_cr4()) ) write_cr4(cr4); =20 - if ( unlikely(v->arch.guest_context.debugreg[7]) ) + if ( unlikely(v->arch.guest_context.debugreg[7] & DR7_ACTIVE_MASK) ) { write_debugreg(0, v->arch.guest_context.debugreg[0]); write_debugreg(1, v->arch.guest_context.debugreg[1]); Index: 2007-11-13/xen/arch/x86/domctl.c =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- 2007-11-13.orig/xen/arch/x86/domctl.c 2007-11-12 08:47:42.0000000= 00 +0100 +++ 2007-11-13/xen/arch/x86/domctl.c 2007-11-21 12:37:04.000000000 = +0100 @@ -825,12 +825,18 @@ void arch_get_info_guest(struct vcpu *v, c.nat->ctrlreg[1] =3D xen_pfn_to_cr3( pagetable_get_pfn(v->arch.guest_table_user)); #endif + + c.nat->debugreg[7] |=3D c.nat->debugreg[5]; + c.nat->debugreg[5] =3D 0; } #ifdef CONFIG_COMPAT else { l4_pgentry_t *l4e =3D __va(pagetable_get_paddr(v->arch.guest_t= able)); c.cmp->ctrlreg[3] =3D compat_pfn_to_cr3(l4e_get_pfn(*l4e)); + + c.cmp->debugreg[7] |=3D c.cmp->debugreg[5]; + c.cmp->debugreg[5] =3D 0; } #endif =20 Index: 2007-11-13/xen/arch/x86/hvm/svm/svm.c =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- 2007-11-13.orig/xen/arch/x86/hvm/svm/svm.c 2007-11-20 16:46:55.0000000= 00 +0100 +++ 2007-11-13/xen/arch/x86/hvm/svm/svm.c 2007-11-21 09:47:01.0000000= 00 +0100 @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include @@ -189,8 +190,6 @@ static void __restore_debug_registers(st * if one of the breakpoints is enabled. So mask out all bits that don't * enable some breakpoint functionality. */ -#define DR7_ACTIVE_MASK 0xff - static void svm_restore_dr(struct vcpu *v) { if ( unlikely(v->arch.guest_context.debugreg[7] & DR7_ACTIVE_MASK) ) Index: 2007-11-13/xen/arch/x86/hvm/vmx/vmx.c =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- 2007-11-13.orig/xen/arch/x86/hvm/vmx/vmx.c 2007-11-20 16:32:57.0000000= 00 +0100 +++ 2007-11-13/xen/arch/x86/hvm/vmx/vmx.c 2007-11-21 09:47:07.0000000= 00 +0100 @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -434,8 +435,6 @@ static void __restore_debug_registers(st * if one of the breakpoints is enabled. So mask out all bits that don't * enable some breakpoint functionality. */ -#define DR7_ACTIVE_MASK 0xff - static void vmx_restore_dr(struct vcpu *v) { /* NB. __vmread() is not usable here, so we cannot read from the = VMCS. */ Index: 2007-11-13/xen/arch/x86/traps.c =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- 2007-11-13.orig/xen/arch/x86/traps.c 2007-11-20 15:46:19.0000000= 00 +0100 +++ 2007-11-13/xen/arch/x86/traps.c 2007-11-21 11:29:05.000000000 = +0100 @@ -412,17 +412,51 @@ static void do_guest_trap( regs->error_code); } =20 -static void instruction_done(struct cpu_user_regs *regs, unsigned long = eip) +static void instruction_done(struct cpu_user_regs *regs, + unsigned long eip, unsigned int bpmatch) { regs->eip =3D eip; regs->eflags &=3D ~X86_EFLAGS_RF; - if ( regs->eflags & X86_EFLAGS_TF ) + if ( bpmatch || (regs->eflags & X86_EFLAGS_TF) ) { - current->arch.guest_context.debugreg[6] |=3D 0xffff4ff0; + current->arch.guest_context.debugreg[6] |=3D bpmatch | 0xffff0ff0;= + if ( regs->eflags & X86_EFLAGS_TF ) + current->arch.guest_context.debugreg[6] |=3D 0x4000; do_guest_trap(TRAP_debug, regs, 0); } } =20 +static unsigned int check_guest_io_breakpoint(struct vcpu *v, + unsigned int port, unsigned int len) +{ + unsigned int match =3D 0; + + if ( unlikely(v->arch.guest_context.ctrlreg[4] & X86_CR4_DE) ) + { + unsigned int i; + + for ( i =3D 0; i < 4; ++i ) + if ( v->arch.guest_context.debugreg[5] & + (3 << (i * DR_ENABLE_SIZE)) ) + { + unsigned long start =3D v->arch.guest_context.debugreg[i]; + unsigned int width =3D 0; + + switch ( (v->arch.guest_context.debugreg[7] >> + (DR_CONTROL_SHIFT + i * DR_CONTROL_SIZE)) & 0xc = ) + { + case DR_LEN_1: width =3D 1; break; + case DR_LEN_2: width =3D 2; break; + case DR_LEN_4: width =3D 4; break; + case DR_LEN_8: width =3D 8; break; + } + if ( start < port + len && start + width > port ) + match |=3D 1 << i; + } + } + return match; +} + /* * Called from asm to set up the NMI trapbounce info. * Returns 0 if no callback is set up, else 1. @@ -639,7 +673,6 @@ static int emulate_forced_invalid_op(str { /* Modify Feature Information. */ __clear_bit(X86_FEATURE_VME, &d); - __clear_bit(X86_FEATURE_DE, &d); __clear_bit(X86_FEATURE_PSE, &d); __clear_bit(X86_FEATURE_PGE, &d); if ( !cpu_has_sep ) @@ -668,7 +701,7 @@ static int emulate_forced_invalid_op(str regs->ebx =3D b; regs->ecx =3D c; regs->edx =3D d; - instruction_done(regs, eip); + instruction_done(regs, eip, 0); =20 trace_trap_one_addr(TRC_PV_FORCED_INVALID_OP, regs->eip); =20 @@ -1325,7 +1358,7 @@ static int emulate_privileged_op(struct=20 unsigned long *reg, eip =3D regs->eip, res; u8 opcode, modrm_reg =3D 0, modrm_rm =3D 0, rep_prefix =3D 0, lock = =3D 0, rex =3D 0; enum { lm_seg_none, lm_seg_fs, lm_seg_gs } lm_ovr =3D lm_seg_none; - unsigned int port, i, data_sel, ar, data, rc; + unsigned int port, i, data_sel, ar, data, rc, bpmatch =3D 0; unsigned int op_bytes, op_default, ad_bytes, ad_default; #define rd_ad(reg) (ad_bytes >=3D sizeof(regs->reg) \ ? regs->reg \ @@ -1475,6 +1508,8 @@ static int emulate_privileged_op(struct=20 } #endif =20 + port =3D (u16)regs->edx; + continue_io_string: switch ( opcode ) { @@ -1483,9 +1518,8 @@ static int emulate_privileged_op(struct=20 case 0x6d: /* INSW/INSL */ if ( data_limit < op_bytes - 1 || rd_ad(edi) > data_limit - (op_bytes - 1) || - !guest_io_okay((u16)regs->edx, op_bytes, v, regs) ) + !guest_io_okay(port, op_bytes, v, regs) ) goto fail; - port =3D (u16)regs->edx; switch ( op_bytes ) { case 1: @@ -1515,7 +1549,7 @@ static int emulate_privileged_op(struct=20 case 0x6f: /* OUTSW/OUTSL */ if ( data_limit < op_bytes - 1 || rd_ad(esi) > data_limit - (op_bytes - 1) || - !guest_io_okay((u16)regs->edx, op_bytes, v, regs) ) + !guest_io_okay(port, op_bytes, v, regs) ) goto fail; rc =3D copy_from_user(&data, (void *)data_base + rd_ad(esi), = op_bytes); if ( rc !=3D 0 ) @@ -1523,7 +1557,6 @@ static int emulate_privileged_op(struct=20 propagate_page_fault(data_base + rd_ad(esi) + op_bytes - = rc, 0); return EXCRET_fault_fixed; } - port =3D (u16)regs->edx; switch ( op_bytes ) { case 1: @@ -1549,9 +1582,11 @@ static int emulate_privileged_op(struct=20 break; } =20 + bpmatch =3D check_guest_io_breakpoint(v, port, op_bytes); + if ( rep_prefix && (wr_ad(ecx, regs->ecx - 1) !=3D 0) ) { - if ( !hypercall_preempt_check() ) + if ( !bpmatch && !hypercall_preempt_check() ) goto continue_io_string; eip =3D regs->eip; } @@ -1630,6 +1665,7 @@ static int emulate_privileged_op(struct=20 regs->eax =3D (u32)~0; break; } + bpmatch =3D check_guest_io_breakpoint(v, port, op_bytes); goto done; =20 case 0xec: /* IN %dx,%al */ @@ -1667,6 +1703,7 @@ static int emulate_privileged_op(struct=20 io_emul(regs); break; } + bpmatch =3D check_guest_io_breakpoint(v, port, op_bytes); goto done; =20 case 0xee: /* OUT %al,%dx */ @@ -1960,7 +1997,7 @@ static int emulate_privileged_op(struct=20 #undef rd_ad =20 done: - instruction_done(regs, eip); + instruction_done(regs, eip, bpmatch); skip: return EXCRET_fault_fixed; =20 @@ -2330,7 +2367,7 @@ static void emulate_gate_op(struct cpu_u sel |=3D (regs->cs & 3); =20 regs->cs =3D sel; - instruction_done(regs, off); + instruction_done(regs, off, 0); #endif } =20 @@ -2842,25 +2879,44 @@ long set_debugreg(struct vcpu *v, int re /* * DR7: Bit 10 reserved (set to 1). * Bits 11-12,14-15 reserved (set to 0). + */ + value &=3D ~DR_CONTROL_RESERVED_ZERO; /* reserved bits =3D> 0 */ + value |=3D DR_CONTROL_RESERVED_ONE; /* reserved bits =3D> 1 */ + /* * Privileged bits: * GD (bit 13): must be 0. - * R/Wn (bits 16-17,20-21,24-25,28-29): mustn't be 10. - * LENn (bits 18-19,22-23,26-27,30-31): mustn't be 10. */ - /* DR7 =3D=3D 0 =3D> debugging disabled for this domain. */ - if ( value !=3D 0 ) + if ( value & DR_GENERAL_DETECT ) + return -EPERM; + /* DR7.{G,L}E =3D 0 =3D> debugging disabled for this domain. */ + if ( value & DR7_ACTIVE_MASK ) { - value &=3D 0xffff27ff; /* reserved bits =3D> 0 */ - value |=3D 0x00000400; /* reserved bits =3D> 1 */ - if ( (value & (1<<13)) !=3D 0 ) return -EPERM; - for ( i =3D 0; i < 16; i +=3D 2 ) - if ( ((value >> (i+16)) & 3) =3D=3D 2 ) return -EPERM; + unsigned int io_enable =3D 0; + + for ( i =3D DR_CONTROL_SHIFT; i < 32; i +=3D DR_CONTROL_SIZE = ) + { + if ( ((value >> i) & 3) =3D=3D DR_IO ) + { + if ( !(v->arch.guest_context.ctrlreg[4] & X86_CR4_DE) = ) + return -EPERM; + io_enable |=3D value & (3 << ((i - 16) >> 1)); + } +#ifdef __i386__ + if ( (boot_cpu_data.x86_vendor !=3D X86_VENDOR_INTEL || + !boot_cpu_has(X86_FEATURE_LM)) && + ((value >> i) & 0xc) =3D=3D DR_LEN_8 ) + return -EPERM; +#endif + } + v->arch.guest_context.debugreg[5] =3D io_enable; + value &=3D ~io_enable; /* * If DR7 was previously clear then we need to load all other * debug registers at this point as they were not restored = during * context switch. */ - if ( (v =3D=3D curr) && (v->arch.guest_context.debugreg[7] = =3D=3D 0) ) + if ( (v =3D=3D curr) && + !(v->arch.guest_context.debugreg[7] & DR7_ACTIVE_MASK) ) { write_debugreg(0, v->arch.guest_context.debugreg[0]); write_debugreg(1, v->arch.guest_context.debugreg[1]); @@ -2868,9 +2924,9 @@ long set_debugreg(struct vcpu *v, int re write_debugreg(3, v->arch.guest_context.debugreg[3]); write_debugreg(6, v->arch.guest_context.debugreg[6]); } + if ( v =3D=3D curr ) + write_debugreg(7, value); } - if ( v =3D=3D curr )=20 - write_debugreg(7, value); break; default: return -EINVAL; @@ -2887,8 +2943,19 @@ long do_set_debugreg(int reg, unsigned l =20 unsigned long do_get_debugreg(int reg) { - if ( (reg < 0) || (reg > 7) ) return -EINVAL; - return current->arch.guest_context.debugreg[reg]; + switch ( reg ) + { + case 0 ... 3: + case 6: + return current->arch.guest_context.debugreg[reg]; + case 7: + return current->arch.guest_context.debugreg[7] | + current->arch.guest_context.debugreg[5]; + case 4 ... 5: + return current->arch.guest_context.ctrlreg[4] & X86_CR4_DE ? + current->arch.guest_context.debugreg[reg + 2] : 0; + } + return -EINVAL; } =20 /* Index: 2007-11-13/xen/include/asm-x86/debugreg.h =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- 2007-11-13.orig/xen/include/asm-x86/debugreg.h 2005-11-17 = 15:51:06.000000000 +0100 +++ 2007-11-13/xen/include/asm-x86/debugreg.h 2007-11-21 09:39:32.0000000= 00 +0100 @@ -33,11 +33,13 @@ =20 #define DR_RW_EXECUTE (0x0) /* Settings for the access types to trap on = */ #define DR_RW_WRITE (0x1) +#define DR_IO (0x2) #define DR_RW_READ (0x3) =20 #define DR_LEN_1 (0x0) /* Settings for data length to trap on */ #define DR_LEN_2 (0x4) #define DR_LEN_4 (0xC) +#define DR_LEN_8 (0x8) =20 /* The low byte to the control register determine which registers are enabled. There are 4 fields of two bits. One bit is "local", meaning @@ -53,12 +55,16 @@ #define DR_LOCAL_ENABLE_MASK (0x55) /* Set local bits for all 4 regs */ #define DR_GLOBAL_ENABLE_MASK (0xAA) /* Set global bits for all 4 regs */ =20 +#define DR7_ACTIVE_MASK (DR_LOCAL_ENABLE_MASK|DR_GLOBAL_ENABLE_MASK) + /* The second byte to the control register has a few special things. We can slow the instruction pipeline for instructions coming via the gdt or the ldt if we want to. I am not sure why this is an advantage = */ =20 -#define DR_CONTROL_RESERVED (~0xFFFF03FFUL) /* Reserved by Intel */ -#define DR_LOCAL_SLOWDOWN (0x100) /* Local slow the pipeline */ -#define DR_GLOBAL_SLOWDOWN (0x200) /* Global slow the pipeline */ +#define DR_CONTROL_RESERVED_ZERO (~0xFFFF23FFUL) /* Reserved, read as = zero */ +#define DR_CONTROL_RESERVED_ONE ( 0x00000400 ) /* Reserved, read as one = */ +#define DR_LOCAL_EXACT_ENABLE ( 0x00000100 ) /* Local exact enable */ +#define DR_GLOBAL_EXACT_ENABLE ( 0x00000200 ) /* Global exact enable = */ +#define DR_GENERAL_DETECT ( 0x00002000 ) /* General detect enable = */ =20 #endif /* _X86_DEBUGREG_H */ --=__Part2B0D243A.0__= Content-Type: text/plain; name="x86-inject-sstep.patch" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="x86-inject-sstep.patch" Index: 2007-11-13/xen/arch/x86/hvm/io.c =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- 2007-11-13.orig/xen/arch/x86/hvm/io.c 2007-11-21 08:47:45.0000000= 00 +0100 +++ 2007-11-13/xen/arch/x86/hvm/io.c 2007-11-20 16:27:57.000000000 = +0100 @@ -863,6 +863,8 @@ void hvm_io_assist(void) /* Copy register changes back into current guest state. */ regs->eflags &=3D ~X86_EFLAGS_RF; memcpy(guest_cpu_user_regs(), regs, HVM_CONTEXT_STACK_BYTES); + if ( regs->eflags & X86_EFLAGS_TF ) + hvm_inject_exception(TRAP_debug, HVM_DELIVER_NO_ERROR_CODE, 0); =20 out: vcpu_end_shutdown_deferral(v); Index: 2007-11-13/xen/arch/x86/hvm/platform.c =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- 2007-11-13.orig/xen/arch/x86/hvm/platform.c 2007-11-21 08:47:45.0000000= 00 +0100 +++ 2007-11-13/xen/arch/x86/hvm/platform.c 2007-11-20 16:37:27.0000000= 00 +0100 @@ -1061,7 +1061,6 @@ void handle_mmio(unsigned long gpa) } =20 regs->eip +=3D inst_len; /* advance %eip */ - regs->eflags &=3D ~X86_EFLAGS_RF; =20 switch ( mmio_op->instr ) { case INSTR_MOV: @@ -1121,7 +1120,6 @@ void handle_mmio(unsigned long gpa) /* The guest does not have the non-mmio address mapped.=20 * Need to send in a page fault */ regs->eip -=3D inst_len; /* do not advance %eip */ - regs->eflags |=3D X86_EFLAGS_RF; /* RF was set by original = #PF */ hvm_inject_exception(TRAP_page_fault, pfec, addr); return; } @@ -1150,7 +1148,6 @@ void handle_mmio(unsigned long gpa) /* Failed on the page-spanning copy. Inject PF = into * the guest for the address where we failed */ regs->eip -=3D inst_len; /* do not advance %eip = */ - regs->eflags |=3D X86_EFLAGS_RF; /* RF was set by = #PF */ /* Must set CR2 at the failing address */=20 addr +=3D size - rv; gdprintk(XENLOG_DEBUG, "Pagefault on non-io side = of a " Index: 2007-11-13/xen/arch/x86/hvm/svm/svm.c =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- 2007-11-13.orig/xen/arch/x86/hvm/svm/svm.c 2007-11-21 08:47:45.0000000= 00 +0100 +++ 2007-11-13/xen/arch/x86/hvm/svm/svm.c 2007-11-20 16:46:55.0000000= 00 +0100 @@ -78,14 +78,6 @@ static void *root_vmcb[NR_CPUS] __read_m =20 static void svm_update_guest_efer(struct vcpu *v); =20 -static void inline __update_guest_eip( - struct cpu_user_regs *regs, int inst_len)=20 -{ - ASSERT(inst_len > 0); - regs->eip +=3D inst_len; - regs->eflags &=3D ~X86_EFLAGS_RF; -} - static void svm_inject_exception( struct vcpu *v, int trap, int ev, int error_code) { @@ -107,6 +99,20 @@ static void svm_inject_exception( vmcb->eventinj =3D event; } =20 +static void inline __update_guest_eip(struct vcpu *v, + struct cpu_user_regs *regs, int inst_len) +{ + ASSERT(inst_len > 0); + regs->eip +=3D inst_len; + regs->eflags &=3D ~X86_EFLAGS_RF; + if ( v && (regs->eflags & X86_EFLAGS_TF) ) + { + v->arch.guest_context.debugreg[6] =3D + v->arch.hvm_svm.vmcb->dr6 |=3D 0x4000; + svm_inject_exception(v, TRAP_debug, 0, 0); + } +} + static void svm_cpu_down(void) { write_efer(read_efer() & ~EFER_SVME); @@ -868,7 +874,12 @@ static void svm_hvm_inject_exception( struct vcpu *v =3D current; if ( trapnr =3D=3D TRAP_page_fault ) v->arch.hvm_svm.vmcb->cr2 =3D v->arch.hvm_vcpu.guest_cr[2] =3D = cr2; - svm_inject_exception(v, trapnr, (errcode !=3D -1), errcode); + if ( trapnr =3D=3D TRAP_debug && + (guest_cpu_user_regs()->eflags & X86_EFLAGS_TF) ) + v->arch.guest_context.debugreg[6] =3D + v->arch.hvm_svm.vmcb->dr6 |=3D 0x4000; + svm_inject_exception(v, trapnr, + (errcode !=3D HVM_DELIVER_NO_ERROR_CODE), = errcode); } =20 static int svm_event_pending(struct vcpu *v) @@ -1083,7 +1094,7 @@ static void svm_vmexit_do_cpuid(struct v =20 inst_len =3D __get_instruction_length(v, INSTR_CPUID, NULL); ASSERT(inst_len > 0); - __update_guest_eip(regs, inst_len); + __update_guest_eip(v, regs, inst_len); } =20 static unsigned long *get_reg_p( @@ -1769,7 +1780,7 @@ static void svm_cr_access( ASSERT(inst_len); =20 if ( result ) - __update_guest_eip(regs, inst_len); + __update_guest_eip(v, regs, inst_len); } =20 static void svm_do_msr_access( @@ -1940,7 +1951,7 @@ static void svm_do_msr_access( inst_len =3D __get_instruction_length(v, INSTR_WRMSR, NULL); } =20 - __update_guest_eip(regs, inst_len); + __update_guest_eip(v, regs, inst_len); } =20 static void svm_vmexit_do_hlt(struct vmcb_struct *vmcb, @@ -1948,7 +1959,7 @@ static void svm_vmexit_do_hlt(struct vmc { struct hvm_intack intack =3D hvm_vcpu_has_pending_irq(current); =20 - __update_guest_eip(regs, 1); + __update_guest_eip(NULL, regs, 1); =20 /* Check for interrupt not handled or new interrupt. */ if ( vmcb->eventinj.fields.v || @@ -1978,7 +1989,7 @@ static void svm_vmexit_do_invalidate_cac =20 inst_len =3D __get_instruction_length_from_list( curr, list, ARRAY_SIZE(list), NULL, NULL); - __update_guest_eip(regs, inst_len); + __update_guest_eip(curr, regs, inst_len); } =20 void svm_handle_invlpg(const short invlpga, struct cpu_user_regs *regs) @@ -2003,7 +2014,7 @@ void svm_handle_invlpg(const short invlp { inst_len =3D __get_instruction_length(v, INSTR_INVLPGA, opcode); ASSERT(inst_len > 0); - __update_guest_eip(regs, inst_len); + __update_guest_eip(v, regs, inst_len); =20 /*=20 * The address is implicit on this instruction. At the moment, we = don't @@ -2030,7 +2041,7 @@ void svm_handle_invlpg(const short invlp &opcode[inst_len], &length); =20 inst_len +=3D length; - __update_guest_eip(regs, inst_len); + __update_guest_eip(v, regs, inst_len); } =20 HVMTRACE_3D(INVLPG, v, (invlpga?1:0), g_vaddr, (invlpga?regs->ecx:0));= @@ -2186,7 +2197,7 @@ asmlinkage void svm_vmexit_handler(struc goto exit_and_crash; /* AMD Vol2, 15.11: INT3, INTO, BOUND intercepts do not update = RIP. */ inst_len =3D __get_instruction_length(v, INSTR_INT3, NULL); - __update_guest_eip(regs, inst_len); + __update_guest_eip(NULL, regs, inst_len); domain_pause_for_debugger(); break; =20 @@ -2268,7 +2279,7 @@ asmlinkage void svm_vmexit_handler(struc rc =3D hvm_do_hypercall(regs); if ( rc !=3D HVM_HCALL_preempted ) { - __update_guest_eip(regs, inst_len); + __update_guest_eip(v, regs, inst_len); if ( rc =3D=3D HVM_HCALL_invalidate ) send_invalidate_req(); } Index: 2007-11-13/xen/arch/x86/hvm/vmx/vmx.c =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- 2007-11-13.orig/xen/arch/x86/hvm/vmx/vmx.c 2007-11-21 08:47:45.0000000= 00 +0100 +++ 2007-11-13/xen/arch/x86/hvm/vmx/vmx.c 2007-11-20 16:32:57.0000000= 00 +0100 @@ -1093,6 +1093,14 @@ static void vmx_inject_exception( vmx_inject_hw_exception(v, trapnr, errcode); if ( trapnr =3D=3D TRAP_page_fault ) v->arch.hvm_vcpu.guest_cr[2] =3D cr2; + if ( trapnr =3D=3D TRAP_debug && + (guest_cpu_user_regs()->eflags & X86_EFLAGS_TF) ) + { + unsigned long dr6 =3D read_debugreg(6); + + v->arch.guest_context.debugreg[6] =3D dr6 |=3D 0x4000; + write_debugreg(6, dr6); + } } =20 static void vmx_update_vtpr(struct vcpu *v, unsigned long value) @@ -1184,13 +1192,20 @@ static int __get_instruction_length(void return len; } =20 -static void __update_guest_eip(unsigned long inst_len) +static void __update_guest_eip(struct vcpu *v, unsigned long inst_len) { struct cpu_user_regs *regs =3D guest_cpu_user_regs(); unsigned long x; =20 regs->eip +=3D inst_len; regs->eflags &=3D ~X86_EFLAGS_RF; + if ( v && (regs->eflags & X86_EFLAGS_TF) ) + { + x =3D read_debugreg(6); + v->arch.guest_context.debugreg[6] =3D x |=3D 0x4000; + write_debugreg(6, x); + vmx_inject_hw_exception(v, TRAP_debug, HVM_DELIVER_NO_ERROR_CODE);= + } =20 x =3D __vmread(GUEST_INTERRUPTIBILITY_INFO); if ( x & (VMX_INTR_SHADOW_STI | VMX_INTR_SHADOW_MOV_SS) ) @@ -2824,18 +2839,18 @@ asmlinkage void vmx_vmexit_handler(struc } case EXIT_REASON_CPUID: inst_len =3D __get_instruction_length(); /* Safe: CPUID */ - __update_guest_eip(inst_len); + __update_guest_eip(v, inst_len); vmx_do_cpuid(regs); break; case EXIT_REASON_HLT: inst_len =3D __get_instruction_length(); /* Safe: HLT */ - __update_guest_eip(inst_len); + __update_guest_eip(NULL, inst_len); vmx_do_hlt(regs); break; case EXIT_REASON_INVLPG: { inst_len =3D __get_instruction_length(); /* Safe: INVLPG */ - __update_guest_eip(inst_len); + __update_guest_eip(v, inst_len); exit_qualification =3D __vmread(EXIT_QUALIFICATION); vmx_do_invlpg(exit_qualification); break; @@ -2848,7 +2863,7 @@ asmlinkage void vmx_vmexit_handler(struc rc =3D hvm_do_hypercall(regs); if ( rc !=3D HVM_HCALL_preempted ) { - __update_guest_eip(inst_len); + __update_guest_eip(v, inst_len); if ( rc =3D=3D HVM_HCALL_invalidate ) send_invalidate_req(); } @@ -2859,7 +2874,7 @@ asmlinkage void vmx_vmexit_handler(struc exit_qualification =3D __vmread(EXIT_QUALIFICATION); inst_len =3D __get_instruction_length(); /* Safe: MOV Cn, LMSW, = CLTS */ if ( vmx_cr_access(exit_qualification, regs) ) - __update_guest_eip(inst_len); + __update_guest_eip(v, inst_len); break; } case EXIT_REASON_DR_ACCESS: @@ -2874,12 +2889,12 @@ asmlinkage void vmx_vmexit_handler(struc case EXIT_REASON_MSR_READ: inst_len =3D __get_instruction_length(); /* Safe: RDMSR */ if ( vmx_do_msr_read(regs) ) - __update_guest_eip(inst_len); + __update_guest_eip(v, inst_len); break; case EXIT_REASON_MSR_WRITE: inst_len =3D __get_instruction_length(); /* Safe: WRMSR */ if ( vmx_do_msr_write(regs) ) - __update_guest_eip(inst_len); + __update_guest_eip(v, inst_len); break; =20 case EXIT_REASON_MWAIT_INSTRUCTION: @@ -2893,7 +2908,7 @@ asmlinkage void vmx_vmexit_handler(struc case EXIT_REASON_VMWRITE: case EXIT_REASON_VMXOFF: case EXIT_REASON_VMXON: - vmx_inject_hw_exception(v, TRAP_invalid_op, VMX_DELIVER_NO_ERROR_C= ODE); + vmx_inject_hw_exception(v, TRAP_invalid_op, HVM_DELIVER_NO_ERROR_C= ODE); break; =20 case EXIT_REASON_TPR_BELOW_THRESHOLD: @@ -2911,7 +2926,7 @@ asmlinkage void vmx_vmexit_handler(struc case EXIT_REASON_INVD: { inst_len =3D __get_instruction_length(); /* Safe: INVD */ - __update_guest_eip(inst_len); + __update_guest_eip(v, inst_len); if ( !list_empty(&(domain_hvm_iommu(v->domain)->pdev_list)) ) wbinvd(); break; Index: 2007-11-13/xen/arch/x86/traps.c =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- 2007-11-13.orig/xen/arch/x86/traps.c 2007-11-21 08:47:45.0000000= 00 +0100 +++ 2007-11-13/xen/arch/x86/traps.c 2007-11-20 15:46:19.000000000 = +0100 @@ -412,6 +412,17 @@ static void do_guest_trap( regs->error_code); } =20 +static void instruction_done(struct cpu_user_regs *regs, unsigned long = eip) +{ + regs->eip =3D eip; + regs->eflags &=3D ~X86_EFLAGS_RF; + if ( regs->eflags & X86_EFLAGS_TF ) + { + current->arch.guest_context.debugreg[6] |=3D 0xffff4ff0; + do_guest_trap(TRAP_debug, regs, 0); + } +} + /* * Called from asm to set up the NMI trapbounce info. * Returns 0 if no callback is set up, else 1. @@ -657,8 +668,7 @@ static int emulate_forced_invalid_op(str regs->ebx =3D b; regs->ecx =3D c; regs->edx =3D d; - regs->eip =3D eip; - regs->eflags &=3D ~X86_EFLAGS_RF; + instruction_done(regs, eip); =20 trace_trap_one_addr(TRC_PV_FORCED_INVALID_OP, regs->eip); =20 @@ -1950,8 +1960,7 @@ static int emulate_privileged_op(struct=20 #undef rd_ad =20 done: - regs->eip =3D eip; - regs->eflags &=3D ~X86_EFLAGS_RF; + instruction_done(regs, eip); skip: return EXCRET_fault_fixed; =20 @@ -2320,8 +2329,8 @@ static void emulate_gate_op(struct cpu_u else sel |=3D (regs->cs & 3); =20 - regs->eip =3D off; regs->cs =3D sel; + instruction_done(regs, off); #endif } =20 Index: 2007-11-13/xen/arch/x86/x86_emulate.c =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- 2007-11-13.orig/xen/arch/x86/x86_emulate.c 2007-11-21 08:47:45.0000000= 00 +0100 +++ 2007-11-13/xen/arch/x86/x86_emulate.c 2007-11-20 15:38:30.0000000= 00 +0100 @@ -1625,6 +1625,7 @@ x86_emulate( /* Commit shadow register state. */ _regs.eflags &=3D ~EF_RF; *ctxt->regs =3D _regs; + /* FIXME generate_exception_if(_regs.eflags & EF_TF, EXC_DB); */ =20 done: return rc; Index: 2007-11-13/xen/include/asm-x86/hvm/support.h =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- 2007-11-13.orig/xen/include/asm-x86/hvm/support.h 2007-11-21 = 08:47:45.000000000 +0100 +++ 2007-11-13/xen/include/asm-x86/hvm/support.h 2007-11-20 = 15:58:09.000000000 +0100 @@ -50,7 +50,7 @@ static inline vcpu_iodata_t *get_ioreq(s #define TYPE_CLTS (2 << 4) #define TYPE_LMSW (3 << 4) =20 -#define VMX_DELIVER_NO_ERROR_CODE -1 +#define HVM_DELIVER_NO_ERROR_CODE -1 =20 #if HVM_DEBUG #define DBG_LEVEL_0 (1 << 0) Index: 2007-11-13/xen/include/asm-x86/hvm/vmx/vmx.h =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- 2007-11-13.orig/xen/include/asm-x86/hvm/vmx/vmx.h 2007-11-21 = 08:47:45.000000000 +0100 +++ 2007-11-13/xen/include/asm-x86/hvm/vmx/vmx.h 2007-11-20 = 15:58:49.000000000 +0100 @@ -272,7 +272,7 @@ static inline void __vmx_inject_exceptio */ =20 intr_fields =3D (INTR_INFO_VALID_MASK | (type<<8) | trap); - if ( error_code !=3D VMX_DELIVER_NO_ERROR_CODE ) { + if ( error_code !=3D HVM_DELIVER_NO_ERROR_CODE ) { __vmwrite(VM_ENTRY_EXCEPTION_ERROR_CODE, error_code); intr_fields |=3D INTR_INFO_DELIVER_CODE_MASK; } @@ -294,13 +294,13 @@ static inline void vmx_inject_hw_excepti static inline void vmx_inject_extint(struct vcpu *v, int trap) { __vmx_inject_exception(v, trap, X86_EVENTTYPE_EXT_INTR, - VMX_DELIVER_NO_ERROR_CODE); + HVM_DELIVER_NO_ERROR_CODE); } =20 static inline void vmx_inject_nmi(struct vcpu *v) { __vmx_inject_exception(v, 2, X86_EVENTTYPE_NMI, - VMX_DELIVER_NO_ERROR_CODE); + HVM_DELIVER_NO_ERROR_CODE); } =20 #endif /* __ASM_X86_HVM_VMX_VMX_H__ */ --=__Part2B0D243A.0__= Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Disposition: inline _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel --=__Part2B0D243A.0__=--