ia64/xen-unstable

changeset 5696:169cb05ce889

Add debug-register access emulation.
Signed-off-by: Keir Fraser <keir@xensource.com>
author kaf24@firebug.cl.cam.ac.uk
date Fri Jul 08 08:44:36 2005 +0000 (2005-07-08)
parents 0694fda4dbd5
children fdcf179cb6b1
files xen/arch/x86/traps.c
line diff
     1.1 --- a/xen/arch/x86/traps.c	Fri Jul 08 08:02:45 2005 +0000
     1.2 +++ b/xen/arch/x86/traps.c	Fri Jul 08 08:44:36 2005 +0000
     1.3 @@ -94,6 +94,9 @@ DECLARE_TRAP_HANDLER(alignment_check);
     1.4  DECLARE_TRAP_HANDLER(spurious_interrupt_bug);
     1.5  DECLARE_TRAP_HANDLER(machine_check);
     1.6  
     1.7 +long do_set_debugreg(int reg, unsigned long value);
     1.8 +unsigned long do_get_debugreg(int reg);
     1.9 +
    1.10  static int debug_stack_lines = 20;
    1.11  integer_param("debug_stack_lines", debug_stack_lines);
    1.12  
    1.13 @@ -568,8 +571,8 @@ static inline int admin_io_okay(
    1.14  static int emulate_privileged_op(struct cpu_user_regs *regs)
    1.15  {
    1.16      struct vcpu *v = current;
    1.17 -    unsigned long *reg, eip = regs->eip;
    1.18 -    u8 opcode, modrm_reg = 0, rep_prefix = 0;
    1.19 +    unsigned long *reg, eip = regs->eip, res;
    1.20 +    u8 opcode, modrm_reg = 0, modrm_rm = 0, rep_prefix = 0;
    1.21      unsigned int port, i, op_bytes = 4, data;
    1.22  
    1.23      /* Legacy prefixes. */
    1.24 @@ -604,7 +607,9 @@ static int emulate_privileged_op(struct 
    1.25      if ( (opcode & 0xf0) == 0x40 )
    1.26      {
    1.27          modrm_reg = (opcode & 4) << 1;  /* REX.R */
    1.28 -        /* REX.W, REX.B and REX.X do not need to be decoded. */
    1.29 +        modrm_rm  = (opcode & 1) << 3;  /* REX.B */
    1.30 +
    1.31 +        /* REX.W and REX.X do not need to be decoded. */
    1.32          opcode = insn_fetch(u8, 1, eip);
    1.33      }
    1.34  #endif
    1.35 @@ -782,11 +787,10 @@ static int emulate_privileged_op(struct 
    1.36  
    1.37      case 0x20: /* MOV CR?,<reg> */
    1.38          opcode = insn_fetch(u8, 1, eip);
    1.39 -        if ( (opcode & 0xc0) != 0xc0 )
    1.40 -            goto fail;
    1.41 -        modrm_reg |= opcode & 7;
    1.42 -        reg = decode_register(modrm_reg, regs, 0);
    1.43 -        switch ( (opcode >> 3) & 7 )
    1.44 +        modrm_reg |= (opcode >> 3) & 7;
    1.45 +        modrm_rm  |= (opcode >> 0) & 7;
    1.46 +        reg = decode_register(modrm_rm, regs, 0);
    1.47 +        switch ( modrm_reg )
    1.48          {
    1.49          case 0: /* Read CR0 */
    1.50              *reg = v->arch.guest_context.ctrlreg[0];
    1.51 @@ -805,13 +809,22 @@ static int emulate_privileged_op(struct 
    1.52          }
    1.53          break;
    1.54  
    1.55 +    case 0x21: /* MOV DR?,<reg> */
    1.56 +        opcode = insn_fetch(u8, 1, eip);
    1.57 +        modrm_reg |= (opcode >> 3) & 7;
    1.58 +        modrm_rm  |= (opcode >> 0) & 7;
    1.59 +        reg = decode_register(modrm_rm, regs, 0);
    1.60 +        if ( (res = do_get_debugreg(modrm_reg)) > (unsigned long)-256 )
    1.61 +            goto fail;
    1.62 +        *reg = res;
    1.63 +        break;
    1.64 +
    1.65      case 0x22: /* MOV <reg>,CR? */
    1.66          opcode = insn_fetch(u8, 1, eip);
    1.67 -        if ( (opcode & 0xc0) != 0xc0 )
    1.68 -            goto fail;
    1.69 -        modrm_reg |= opcode & 7;
    1.70 -        reg = decode_register(modrm_reg, regs, 0);
    1.71 -        switch ( (opcode >> 3) & 7 )
    1.72 +        modrm_reg |= (opcode >> 3) & 7;
    1.73 +        modrm_rm  |= (opcode >> 0) & 7;
    1.74 +        reg = decode_register(modrm_rm, regs, 0);
    1.75 +        switch ( modrm_reg )
    1.76          {
    1.77          case 0: /* Write CR0 */
    1.78              (void)do_fpu_taskswitch(!!(*reg & X86_CR0_TS));
    1.79 @@ -827,6 +840,15 @@ static int emulate_privileged_op(struct 
    1.80              UNLOCK_BIGLOCK(v->domain);
    1.81              break;
    1.82  
    1.83 +    case 0x23: /* MOV <reg>,DR? */
    1.84 +        opcode = insn_fetch(u8, 1, eip);
    1.85 +        modrm_reg |= (opcode >> 3) & 7;
    1.86 +        modrm_rm  |= (opcode >> 0) & 7;
    1.87 +        reg = decode_register(modrm_rm, regs, 0);
    1.88 +        if ( do_set_debugreg(modrm_reg, *reg) != 0 )
    1.89 +            goto fail;
    1.90 +        break;
    1.91 +
    1.92          default:
    1.93              goto fail;
    1.94          }