ia64/xen-unstable

changeset 4103:d5c2dbd99373

bitkeeper revision 1.1236.25.5 (4231c8e9V-iDqxIZGUl47adwrecjjw)

Virtualize I/O privilege level (IOPL) to disallow direct execution
of IN/OUT/CLI/STI instructions by guests.
Signed-off-by: Keir Fraser <keir@xensource.com>
author kaf24@firebug.cl.cam.ac.uk
date Fri Mar 11 16:35:53 2005 +0000 (2005-03-11)
parents 72960d67a3c4
children 2b9699a37f17
files linux-2.4.29-xen-sparse/arch/xen/kernel/process.c linux-2.6.10-xen-sparse/arch/xen/i386/kernel/process.c xen/arch/x86/dom0_ops.c xen/arch/x86/domain.c xen/arch/x86/traps.c xen/arch/x86/x86_32/entry.S xen/arch/x86/x86_64/entry.S xen/arch/x86/x86_emulate.c xen/include/asm-x86/domain.h
line diff
     1.1 --- a/linux-2.4.29-xen-sparse/arch/xen/kernel/process.c	Fri Mar 11 16:04:54 2005 +0000
     1.2 +++ b/linux-2.4.29-xen-sparse/arch/xen/kernel/process.c	Fri Mar 11 16:35:53 2005 +0000
     1.3 @@ -214,7 +214,6 @@ int copy_thread(int nr, unsigned long cl
     1.4                  struct task_struct * p, struct pt_regs * regs)
     1.5  {
     1.6      struct pt_regs * childregs;
     1.7 -    unsigned long eflags;
     1.8  
     1.9      childregs = ((struct pt_regs *) (THREAD_SIZE + (unsigned long) p)) - 1;
    1.10      struct_cpy(childregs, regs);
    1.11 @@ -232,9 +231,7 @@ int copy_thread(int nr, unsigned long cl
    1.12      unlazy_fpu(current);
    1.13      struct_cpy(&p->thread.i387, &current->thread.i387);
    1.14  
    1.15 -
    1.16 -    __asm__ __volatile__ ( "pushfl; popl %0" : "=r" (eflags) : );
    1.17 -    p->thread.io_pl = (eflags >> 12) & 3;
    1.18 +    p->thread.io_pl = current->thread.io_pl;
    1.19  
    1.20      return 0;
    1.21  }
     2.1 --- a/linux-2.6.10-xen-sparse/arch/xen/i386/kernel/process.c	Fri Mar 11 16:04:54 2005 +0000
     2.2 +++ b/linux-2.6.10-xen-sparse/arch/xen/i386/kernel/process.c	Fri Mar 11 16:35:53 2005 +0000
     2.3 @@ -273,7 +273,6 @@ int copy_thread(int nr, unsigned long cl
     2.4  	struct pt_regs * childregs;
     2.5  	struct task_struct *tsk;
     2.6  	int err;
     2.7 -	unsigned long eflags;
     2.8  
     2.9  	childregs = ((struct pt_regs *) (THREAD_SIZE + (unsigned long) p->thread_info)) - 1;
    2.10  	*childregs = *regs;
    2.11 @@ -323,9 +322,7 @@ int copy_thread(int nr, unsigned long cl
    2.12  		desc->b = LDT_entry_b(&info);
    2.13  	}
    2.14  
    2.15 -
    2.16 -	__asm__ __volatile__ ( "pushfl; popl %0" : "=r" (eflags) : );
    2.17 -	p->thread.io_pl = (eflags >> 12) & 3;
    2.18 +        p->thread.io_pl = current->thread.io_pl;
    2.19  
    2.20  	err = 0;
    2.21   out:
     3.1 --- a/xen/arch/x86/dom0_ops.c	Fri Mar 11 16:04:54 2005 +0000
     3.2 +++ b/xen/arch/x86/dom0_ops.c	Fri Mar 11 16:35:53 2005 +0000
     3.3 @@ -138,8 +138,12 @@ long arch_do_dom0_op(dom0_op_t *op, dom0
     3.4  
     3.5      case DOM0_IOPL:
     3.6      {
     3.7 -        extern long do_iopl(domid_t, unsigned int);
     3.8 -        ret = do_iopl(op->u.iopl.domain, op->u.iopl.iopl);
     3.9 +        ret = -EINVAL;
    3.10 +        if ( op->u.iopl.domain == DOMID_SELF )
    3.11 +        {
    3.12 +            current->arch.iopl = op->u.iopl.iopl & 3;
    3.13 +            ret = 0;
    3.14 +        }
    3.15      }
    3.16      break;
    3.17  
    3.18 @@ -358,6 +362,9 @@ void arch_getdomaininfo_ctxt(
    3.19      memcpy(&c->cpu_ctxt, 
    3.20             &ed->arch.user_ctxt,
    3.21             sizeof(ed->arch.user_ctxt));
    3.22 +    /* IOPL privileges are virtualised -- merge back into returned eflags. */
    3.23 +    BUG_ON((c->cpu_ctxt.eflags & EF_IOPL) != 0);
    3.24 +    c->cpu_ctxt.eflags |= ed->arch.iopl << 12;
    3.25  
    3.26  #ifdef __i386__
    3.27  #ifdef CONFIG_VMX
     4.1 --- a/xen/arch/x86/domain.c	Fri Mar 11 16:04:54 2005 +0000
     4.2 +++ b/xen/arch/x86/domain.c	Fri Mar 11 16:35:53 2005 +0000
     4.3 @@ -441,6 +441,9 @@ int arch_final_setup_guest(
     4.4      memcpy(&ed->arch.user_ctxt,
     4.5             &c->cpu_ctxt,
     4.6             sizeof(ed->arch.user_ctxt));
     4.7 +    /* IOPL privileges are virtualised. */
     4.8 +    ed->arch.iopl = (ed->arch.user_ctxt.eflags >> 12) & 3;
     4.9 +    ed->arch.user_ctxt.eflags &= ~EF_IOPL;
    4.10  
    4.11      /* Clear IOPL for unprivileged domains. */
    4.12      if (!IS_PRIV(d))
    4.13 @@ -820,15 +823,6 @@ void context_switch(struct exec_domain *
    4.14      BUG();
    4.15  }
    4.16  
    4.17 -
    4.18 -/* XXX Currently the 'domain' field is ignored! XXX */
    4.19 -long do_iopl(domid_t domain, unsigned int new_io_pl)
    4.20 -{
    4.21 -    execution_context_t *ec = get_execution_context();
    4.22 -    ec->eflags = (ec->eflags & 0xffffcfff) | ((new_io_pl&3) << 12);
    4.23 -    return 0;
    4.24 -}
    4.25 -
    4.26  unsigned long __hypercall_create_continuation(
    4.27      unsigned int op, unsigned int nr_args, ...)
    4.28  {
     5.1 --- a/xen/arch/x86/traps.c	Fri Mar 11 16:04:54 2005 +0000
     5.2 +++ b/xen/arch/x86/traps.c	Fri Mar 11 16:35:53 2005 +0000
     5.3 @@ -368,22 +368,222 @@ long do_fpu_taskswitch(int set)
     5.4      return 0;
     5.5  }
     5.6  
     5.7 +static inline int user_io_okay(
     5.8 +    unsigned int port, unsigned int bytes,
     5.9 +    struct exec_domain *ed, struct xen_regs *regs)
    5.10 +{
    5.11 +    if ( ed->arch.iopl < (KERNEL_MODE(ed, regs) ? 1 : 3) )
    5.12 +        return 0;
    5.13 +    return 1;
    5.14 +}
    5.15 +
    5.16 +#define insn_fetch(_type, _size, _ptr)          \
    5.17 +({  unsigned long _x;                           \
    5.18 +    if ( get_user(_x, (_type *)eip) )           \
    5.19 +        goto read_fault;                        \
    5.20 +    eip += _size; (_type)_x; })
    5.21 +
    5.22  static int emulate_privileged_op(struct xen_regs *regs)
    5.23  {
    5.24      struct exec_domain *ed = current;
    5.25      unsigned long *reg, eip = regs->eip;
    5.26 -    u8 opcode;
    5.27 +    u8 opcode, modrm_reg = 0, rep_prefix = 0;
    5.28 +    unsigned int port, i, op_bytes = 4, data;
    5.29  
    5.30 -    if ( get_user(opcode, (u8 *)eip) )
    5.31 -        goto page_fault;
    5.32 -    eip += 1;
    5.33 -    if ( (opcode & 0xff) != 0x0f )
    5.34 +    /* Legacy prefixes. */
    5.35 +    for ( i = 0; i < 8; i++ )
    5.36 +    {
    5.37 +        switch ( opcode = insn_fetch(u8, 1, eip) )
    5.38 +        {
    5.39 +        case 0x66: /* operand-size override */
    5.40 +            op_bytes ^= 6; /* switch between 2/4 bytes */
    5.41 +            break;
    5.42 +        case 0x67: /* address-size override */
    5.43 +        case 0x2e: /* CS override */
    5.44 +        case 0x3e: /* DS override */
    5.45 +        case 0x26: /* ES override */
    5.46 +        case 0x64: /* FS override */
    5.47 +        case 0x65: /* GS override */
    5.48 +        case 0x36: /* SS override */
    5.49 +        case 0xf0: /* LOCK */
    5.50 +        case 0xf2: /* REPNE/REPNZ */
    5.51 +            break;
    5.52 +        case 0xf3: /* REP/REPE/REPZ */
    5.53 +            rep_prefix = 1;
    5.54 +            break;
    5.55 +        default:
    5.56 +            goto done_prefixes;
    5.57 +        }
    5.58 +    }
    5.59 + done_prefixes:
    5.60 +
    5.61 +#ifdef __x86_64__
    5.62 +    /* REX prefix. */
    5.63 +    if ( (opcode & 0xf0) == 0x40 )
    5.64 +    {
    5.65 +        modrm_reg = (opcode & 4) << 1;  /* REX.R */
    5.66 +        /* REX.W, REX.B and REX.X do not need to be decoded. */
    5.67 +        opcode = insn_fetch(u8, 1, eip);
    5.68 +    }
    5.69 +#endif
    5.70 +    
    5.71 +    /* Input/Output String instructions. */
    5.72 +    if ( (opcode >= 0x6c) && (opcode <= 0x6f) )
    5.73 +    {
    5.74 +        if ( rep_prefix && (regs->ecx == 0) )
    5.75 +            goto done;
    5.76 +
    5.77 +    continue_io_string:
    5.78 +        switch ( opcode )
    5.79 +        {
    5.80 +        case 0x6c: /* INSB */
    5.81 +            op_bytes = 1;
    5.82 +        case 0x6d: /* INSW/INSL */
    5.83 +            if ( !user_io_okay((u16)regs->edx, op_bytes, ed, regs) )
    5.84 +                goto fail;
    5.85 +            switch ( op_bytes )
    5.86 +            {
    5.87 +            case 1:
    5.88 +                data = (u8)inb((u16)regs->edx);
    5.89 +                if ( put_user((u8)data, (u8 *)regs->edi) )
    5.90 +                    goto write_fault;
    5.91 +                break;
    5.92 +            case 2:
    5.93 +                data = (u16)inw((u16)regs->edx);
    5.94 +                if ( put_user((u16)data, (u16 *)regs->edi) )
    5.95 +                    goto write_fault;
    5.96 +                break;
    5.97 +            case 4:
    5.98 +                data = (u32)inl((u16)regs->edx);
    5.99 +                if ( put_user((u32)data, (u32 *)regs->edi) )
   5.100 +                    goto write_fault;
   5.101 +                break;
   5.102 +            }
   5.103 +            regs->edi += (regs->eflags & EF_DF) ? -op_bytes : op_bytes;
   5.104 +            break;
   5.105 +
   5.106 +        case 0x6e: /* OUTSB */
   5.107 +            op_bytes = 1;
   5.108 +        case 0x6f: /* OUTSW/OUTSL */
   5.109 +            if ( !user_io_okay((u16)regs->edx, op_bytes, ed, regs) )
   5.110 +                goto fail;
   5.111 +            switch ( op_bytes )
   5.112 +            {
   5.113 +            case 1:
   5.114 +                if ( get_user(data, (u8 *)regs->esi) )
   5.115 +                    goto read_fault;
   5.116 +                outb((u8)data, (u16)regs->edx);
   5.117 +                break;
   5.118 +            case 2:
   5.119 +                if ( get_user(data, (u16 *)regs->esi) )
   5.120 +                    goto read_fault;
   5.121 +                outw((u16)data, (u16)regs->edx);
   5.122 +                break;
   5.123 +            case 4:
   5.124 +                if ( get_user(data, (u32 *)regs->esi) )
   5.125 +                    goto read_fault;
   5.126 +                outl((u32)data, (u16)regs->edx);
   5.127 +                break;
   5.128 +            }
   5.129 +            regs->esi += (regs->eflags & EF_DF) ? -op_bytes : op_bytes;
   5.130 +            break;
   5.131 +        }
   5.132 +
   5.133 +        if ( rep_prefix && (--regs->ecx != 0) )
   5.134 +        {
   5.135 +            if ( !hypercall_preempt_check() )
   5.136 +                goto continue_io_string;
   5.137 +            eip = regs->eip;
   5.138 +        }
   5.139 +
   5.140 +        goto done;
   5.141 +    }
   5.142 +
   5.143 +    /* I/O Port and Interrupt Flag instructions. */
   5.144 +    switch ( opcode )
   5.145 +    {
   5.146 +    case 0xe4: /* IN imm8,%al */
   5.147 +        op_bytes = 1;
   5.148 +    case 0xe5: /* IN imm8,%eax */
   5.149 +        port = insn_fetch(u8, 1, eip);
   5.150 +    exec_in:
   5.151 +        if ( !user_io_okay(port, op_bytes, ed, regs) )
   5.152 +            goto fail;
   5.153 +        switch ( op_bytes )
   5.154 +        {
   5.155 +        case 1:
   5.156 +            regs->eax &= ~0xffUL;
   5.157 +            regs->eax |= (u8)inb(port);
   5.158 +            break;
   5.159 +        case 2:
   5.160 +            regs->eax &= ~0xffffUL;
   5.161 +            regs->eax |= (u16)inw(port);
   5.162 +            break;
   5.163 +        case 4:
   5.164 +            regs->eax = (u32)inl(port);
   5.165 +            break;
   5.166 +        }
   5.167 +        goto done;
   5.168 +
   5.169 +    case 0xec: /* IN %dx,%al */
   5.170 +        op_bytes = 1;
   5.171 +    case 0xed: /* IN %dx,%eax */
   5.172 +        port = (u16)regs->edx;
   5.173 +        goto exec_in;
   5.174 +
   5.175 +    case 0xe6: /* OUT %al,imm8 */
   5.176 +        op_bytes = 1;
   5.177 +    case 0xe7: /* OUT %eax,imm8 */
   5.178 +        port = insn_fetch(u8, 1, eip);
   5.179 +    exec_out:
   5.180 +        if ( !user_io_okay(port, op_bytes, ed, regs) )
   5.181 +            goto fail;
   5.182 +        switch ( op_bytes )
   5.183 +        {
   5.184 +        case 1:
   5.185 +            outb((u8)regs->eax, port);
   5.186 +            break;
   5.187 +        case 2:
   5.188 +            outw((u16)regs->eax, port);
   5.189 +            break;
   5.190 +        case 4:
   5.191 +            outl((u32)regs->eax, port);
   5.192 +            break;
   5.193 +        }
   5.194 +        goto done;
   5.195 +
   5.196 +    case 0xee: /* OUT %al,%dx */
   5.197 +        op_bytes = 1;
   5.198 +    case 0xef: /* OUT %eax,%dx */
   5.199 +        port = (u16)regs->edx;
   5.200 +        goto exec_out;
   5.201 +
   5.202 +    case 0xfa: /* CLI */
   5.203 +    case 0xfb: /* STI */
   5.204 +        if ( ed->arch.iopl < (KERNEL_MODE(ed, regs) ? 1 : 3) )
   5.205 +            goto fail;
   5.206 +        /*
   5.207 +         * This is just too dangerous to allow, in my opinion. Consider if the
   5.208 +         * caller then tries to reenable interrupts using POPF: we can't trap
   5.209 +         * that and we'll end up with hard-to-debug lockups. Fast & loose will
   5.210 +         * do for us. :-)
   5.211 +         */
   5.212 +        /*ed->vcpu_info->evtchn_upcall_mask = (opcode == 0xfa);*/
   5.213 +        goto done;
   5.214 +
   5.215 +    case 0x0f: /* Two-byte opcode */
   5.216 +        break;
   5.217 +
   5.218 +    default:
   5.219 +        goto fail;
   5.220 +    }
   5.221 +
   5.222 +    /* Remaining instructions only emulated from guest kernel. */
   5.223 +    if ( !KERNEL_MODE(ed, regs) )
   5.224          goto fail;
   5.225  
   5.226 -    if ( get_user(opcode, (u8 *)eip) )
   5.227 -        goto page_fault;
   5.228 -    eip += 1;
   5.229 -
   5.230 +    /* Privileged (ring 0) instructions. */
   5.231 +    opcode = insn_fetch(u8, 1, eip);
   5.232      switch ( opcode )
   5.233      {
   5.234      case 0x06: /* CLTS */
   5.235 @@ -399,12 +599,11 @@ static int emulate_privileged_op(struct 
   5.236          break;
   5.237  
   5.238      case 0x20: /* MOV CR?,<reg> */
   5.239 -        if ( get_user(opcode, (u8 *)eip) )
   5.240 -            goto page_fault;
   5.241 -        eip += 1;
   5.242 +        opcode = insn_fetch(u8, 1, eip);
   5.243          if ( (opcode & 0xc0) != 0xc0 )
   5.244              goto fail;
   5.245 -        reg = decode_register(opcode & 7, regs, 0);
   5.246 +        modrm_reg |= opcode & 7;
   5.247 +        reg = decode_register(modrm_reg, regs, 0);
   5.248          switch ( (opcode >> 3) & 7 )
   5.249          {
   5.250          case 0: /* Read CR0 */
   5.251 @@ -427,12 +626,11 @@ static int emulate_privileged_op(struct 
   5.252          break;
   5.253  
   5.254      case 0x22: /* MOV <reg>,CR? */
   5.255 -        if ( get_user(opcode, (u8 *)eip) )
   5.256 -            goto page_fault;
   5.257 -        eip += 1;
   5.258 +        opcode = insn_fetch(u8, 1, eip);
   5.259          if ( (opcode & 0xc0) != 0xc0 )
   5.260              goto fail;
   5.261 -        reg = decode_register(opcode & 7, regs, 0);
   5.262 +        modrm_reg |= opcode & 7;
   5.263 +        reg = decode_register(modrm_reg, regs, 0);
   5.264          switch ( (opcode >> 3) & 7 )
   5.265          {
   5.266          case 0: /* Write CR0 */
   5.267 @@ -476,14 +674,19 @@ static int emulate_privileged_op(struct 
   5.268          goto fail;
   5.269      }
   5.270  
   5.271 + done:
   5.272      regs->eip = eip;
   5.273      return EXCRET_fault_fixed;
   5.274  
   5.275   fail:
   5.276      return 0;
   5.277  
   5.278 - page_fault:
   5.279 -    propagate_page_fault(eip, 0);
   5.280 + read_fault:
   5.281 +    propagate_page_fault(eip, 4); /* user mode, read fault */
   5.282 +    return EXCRET_fault_fixed;
   5.283 +
   5.284 + write_fault:
   5.285 +    propagate_page_fault(eip, 6); /* user mode, write fault */
   5.286      return EXCRET_fault_fixed;
   5.287  }
   5.288  
   5.289 @@ -534,9 +737,8 @@ asmlinkage int do_general_protection(str
   5.290          }
   5.291      }
   5.292  
   5.293 -    /* Emulate some simple privileged instructions when exec'ed in ring 1. */
   5.294 +    /* Emulate some simple privileged and I/O instructions. */
   5.295      if ( (regs->error_code == 0) &&
   5.296 -         KERNEL_MODE(ed, regs) &&
   5.297           emulate_privileged_op(regs) )
   5.298          return 0;
   5.299  
     6.1 --- a/xen/arch/x86/x86_32/entry.S	Fri Mar 11 16:04:54 2005 +0000
     6.2 +++ b/xen/arch/x86/x86_32/entry.S	Fri Mar 11 16:35:53 2005 +0000
     6.3 @@ -463,7 +463,7 @@ error_code:
     6.4          SET_XEN_SEGMENTS(a)
     6.5          testb $X86_EFLAGS_IF>>8,XREGS_eflags+1(%esp)
     6.6          jz    exception_with_ints_disabled
     6.7 -1:      sti                             # re-enable interrupts
     6.8 +        sti                             # re-enable interrupts
     6.9          xorl  %eax,%eax
    6.10          movw  XREGS_entry_vector(%esp),%ax
    6.11          movl  %esp,%edx
    6.12 @@ -482,8 +482,7 @@ exception_with_ints_disabled:
    6.13          movl  XREGS_eflags(%esp),%eax
    6.14          movb  XREGS_cs(%esp),%al
    6.15          testl $(3|X86_EFLAGS_VM),%eax   # interrupts disabled outside Xen?
    6.16 -        jnz   1b                        # it really does happen!
    6.17 -                                        #  (e.g., DOM0 X server)
    6.18 +        jnz   FATAL_exception_with_ints_disabled
    6.19          pushl %esp
    6.20          call  search_pre_exception_table
    6.21          addl  $4,%esp
    6.22 @@ -701,8 +700,6 @@ do_switch_vm86:
    6.23          # Discard the return address
    6.24          addl $4,%esp
    6.25  
    6.26 -        movl XREGS_eflags(%esp),%edx
    6.27 -
    6.28          # GS:ESI == Ring-1 stack activation
    6.29          movl XREGS_esp(%esp),%esi
    6.30  VFLT1:  movl XREGS_ss(%esp),%gs
    6.31 @@ -722,13 +719,9 @@ VFLT3:  movl %gs:(%esi),%eax
    6.32          addl $4,%esi
    6.33          loop VFLT3
    6.34  
    6.35 -        # Fix up EFLAGS
    6.36 +        # Fix up EFLAGS: IOPL=0, IF=1, VM=1
    6.37          andl $~X86_EFLAGS_IOPL,XREGS_eflags(%esp)
    6.38 -        andl $X86_EFLAGS_IOPL,%edx # Ignore attempts to change EFLAGS.IOPL
    6.39 -        jnz  1f
    6.40 -        orl  $X86_EFLAGS_IF,%edx   # EFLAGS.IOPL=0 => no messing with EFLAGS.IF
    6.41 -1:      orl  $X86_EFLAGS_VM,%edx   # Force EFLAGS.VM
    6.42 -        orl  %edx,XREGS_eflags(%esp)
    6.43 +        orl  $X86_EFLAGS_IF|X86_EFLAGS_VM,XREGS_eflags(%esp)
    6.44          
    6.45          jmp test_all_events
    6.46  
     7.1 --- a/xen/arch/x86/x86_64/entry.S	Fri Mar 11 16:04:54 2005 +0000
     7.2 +++ b/xen/arch/x86/x86_64/entry.S	Fri Mar 11 16:35:53 2005 +0000
     7.3 @@ -294,7 +294,7 @@ error_code:
     7.4          SAVE_ALL
     7.5          testb $X86_EFLAGS_IF>>8,XREGS_eflags+1(%rsp)
     7.6          jz    exception_with_ints_disabled
     7.7 -1:      sti
     7.8 +        sti
     7.9          movq  %rsp,%rdi
    7.10          movl  XREGS_entry_vector(%rsp),%eax
    7.11          leaq  SYMBOL_NAME(exception_table)(%rip),%rdx
    7.12 @@ -308,8 +308,7 @@ 1:      sti
    7.13  /* No special register assumptions. */
    7.14  exception_with_ints_disabled:
    7.15          testb $3,XREGS_cs(%rsp)         # interrupts disabled outside Xen?
    7.16 -        jnz   1b                        # it really does happen!
    7.17 -                                        #  (e.g., DOM0 X server)
    7.18 +        jnz   FATAL_exception_with_ints_disabled
    7.19          movq  %rsp,%rdi
    7.20          call  search_pre_exception_table
    7.21          testq %rax,%rax                 # no fixup code for faulting EIP?
     8.1 --- a/xen/arch/x86/x86_emulate.c	Fri Mar 11 16:04:54 2005 +0000
     8.2 +++ b/xen/arch/x86/x86_emulate.c	Fri Mar 11 16:35:53 2005 +0000
     8.3 @@ -421,39 +421,44 @@ x86_emulate_memop(
     8.4      u8 b, d, sib, twobyte = 0, rex_prefix = 0;
     8.5      u8 modrm, modrm_mod = 0, modrm_reg = 0, modrm_rm = 0;
     8.6      unsigned int op_bytes = (mode == 8) ? 4 : mode, ad_bytes = mode;
     8.7 -    unsigned int lock_prefix = 0, rep_prefix = 0;
     8.8 +    unsigned int lock_prefix = 0, rep_prefix = 0, i;
     8.9      struct operand src, dst;
    8.10  
    8.11      /* Shadow copy of register state. Committed on successful emulation. */
    8.12      struct xen_regs _regs = *regs;
    8.13  
    8.14      /* Legacy prefixes. */
    8.15 - next_prefix:
    8.16 -    switch ( b = insn_fetch(u8, 1, _regs.eip) )
    8.17 +    for ( i = 0; i < 8; i++ )
    8.18      {
    8.19 -    case 0x66: /* operand-size override */
    8.20 -        op_bytes ^= 6;                    /* switch between 2/4 bytes */
    8.21 -        goto next_prefix;
    8.22 -    case 0x67: /* address-size override */
    8.23 -        ad_bytes ^= (mode == 8) ? 12 : 6; /* switch between 2/4 or 4/8 bytes */
    8.24 -        goto next_prefix;
    8.25 -    case 0x2e: /* CS override */
    8.26 -    case 0x3e: /* DS override */
    8.27 -    case 0x26: /* ES override */
    8.28 -    case 0x64: /* FS override */
    8.29 -    case 0x65: /* GS override */
    8.30 -    case 0x36: /* SS override */
    8.31 -        DPRINTF("Warning: ignoring a segment override. Probably okay. :-)\n");
    8.32 -        goto next_prefix;
    8.33 -    case 0xf0: /* LOCK */
    8.34 -        lock_prefix = 1;
    8.35 -        goto next_prefix;
    8.36 -    case 0xf3: /* REP/REPE/REPZ */
    8.37 -        rep_prefix = 1;
    8.38 -        goto next_prefix;
    8.39 -    case 0xf2: /* REPNE/REPNZ */
    8.40 -        goto next_prefix;
    8.41 +        switch ( b = insn_fetch(u8, 1, _regs.eip) )
    8.42 +        {
    8.43 +        case 0x66: /* operand-size override */
    8.44 +            op_bytes ^= 6;                    /* switch between 2/4 bytes */
    8.45 +            break;
    8.46 +        case 0x67: /* address-size override */
    8.47 +            ad_bytes ^= (mode == 8) ? 12 : 6; /* switch between 2/4/8 bytes */
    8.48 +            break;
    8.49 +        case 0x2e: /* CS override */
    8.50 +        case 0x3e: /* DS override */
    8.51 +        case 0x26: /* ES override */
    8.52 +        case 0x64: /* FS override */
    8.53 +        case 0x65: /* GS override */
    8.54 +        case 0x36: /* SS override */
    8.55 +            DPRINTF("Warning: ignoring a segment override.\n");
    8.56 +            break;
    8.57 +        case 0xf0: /* LOCK */
    8.58 +            lock_prefix = 1;
    8.59 +            break;
    8.60 +        case 0xf3: /* REP/REPE/REPZ */
    8.61 +            rep_prefix = 1;
    8.62 +            break;
    8.63 +        case 0xf2: /* REPNE/REPNZ */
    8.64 +            break;
    8.65 +        default:
    8.66 +            goto done_prefixes;
    8.67 +        }
    8.68      }
    8.69 + done_prefixes:
    8.70  
    8.71      if ( ad_bytes == 2 )
    8.72      {
     9.1 --- a/xen/include/asm-x86/domain.h	Fri Mar 11 16:04:54 2005 +0000
     9.2 +++ b/xen/include/asm-x86/domain.h	Fri Mar 11 16:35:53 2005 +0000
     9.3 @@ -57,6 +57,7 @@ struct arch_exec_domain
     9.4  
     9.5      /* general user-visible register state */
     9.6      execution_context_t user_ctxt;
     9.7 +    unsigned int iopl;
     9.8  
     9.9      void (*schedule_tail) (struct exec_domain *);
    9.10