ia64/xen-unstable

changeset 9379:f9e912842006

The following patch adds support to vmxassist for SYSLINUX/ISOLINUX. This
enables you to install SLES-10 as an unmodified guest.

Notice that at this time, vmxassist does not support the graphic bootstrap
loader (gfxboot), so be sure the set "stdvga=1" in your configuration file
to prevent gfxboot from kicking in (or hit SHIFT really fast).

Signed-Off-By: Leendert van Doorn <leendert@watson.ibm.com>
author kaf24@firebug.cl.cam.ac.uk
date Tue Mar 21 22:50:48 2006 +0100 (2006-03-21)
parents 4dec7a81f8f5
children a6a5a1b963e8
files tools/examples/xmexample.hvm tools/firmware/vmxassist/machine.h tools/firmware/vmxassist/util.c tools/firmware/vmxassist/vm86.c
line diff
     1.1 --- a/tools/examples/xmexample.hvm	Tue Mar 21 22:48:04 2006 +0100
     1.2 +++ b/tools/examples/xmexample.hvm	Tue Mar 21 22:50:48 2006 +0100
     1.3 @@ -129,6 +129,9 @@ vncviewer=1
     1.4  # no graphics, use serial port
     1.5  #nographic=0
     1.6  
     1.7 +#----------------------------------------------------------------------------
     1.8 +# enable stdvga, default = 0 (use cirrus logic device model)
     1.9 +stdvga=0
    1.10  
    1.11  #-----------------------------------------------------------------------------
    1.12  #   serial port re-direct to pty deivce, /dev/pts/n 
     2.1 --- a/tools/firmware/vmxassist/machine.h	Tue Mar 21 22:48:04 2006 +0100
     2.2 +++ b/tools/firmware/vmxassist/machine.h	Tue Mar 21 22:50:48 2006 +0100
     2.3 @@ -37,10 +37,11 @@
     2.4  #define CR4_PVI		(1 << 1)
     2.5  #define CR4_PSE		(1 << 4)
     2.6  
     2.7 +#define EFLAGS_ZF	(1 << 6)
     2.8  #define EFLAGS_TF	(1 << 8)
     2.9  #define EFLAGS_IF	(1 << 9)
    2.10  #define EFLAGS_DF	(1 << 10)
    2.11 -#define EFLAGS_IOPL (3 << 12)
    2.12 +#define EFLAGS_IOPL	(3 << 12)
    2.13  #define EFLAGS_VM	((1 << 17) | EFLAGS_IOPL)
    2.14  #define EFLAGS_VIF	(1 << 19)
    2.15  #define EFLAGS_VIP	(1 << 20)
     3.1 --- a/tools/firmware/vmxassist/util.c	Tue Mar 21 22:48:04 2006 +0100
     3.2 +++ b/tools/firmware/vmxassist/util.c	Tue Mar 21 22:50:48 2006 +0100
     3.3 @@ -48,7 +48,8 @@ dump_regs(struct regs *regs)
     3.4  		printf("trapno %8x errno  %8x\n", regs->trapno, regs->errno);
     3.5  
     3.6  	printf("cr0    %8lx cr2    %8x cr3    %8lx cr4    %8lx\n",
     3.7 -		oldctx.cr0, get_cr2(), oldctx.cr3, oldctx.cr4);
     3.8 +		(long)oldctx.cr0, get_cr2(),
     3.9 +		(long)oldctx.cr3, (long)oldctx.cr4);
    3.10  }
    3.11  
    3.12  #ifdef DEBUG
    3.13 @@ -104,15 +105,25 @@ print_e820_map(struct e820entry *map, in
    3.14  }
    3.15  
    3.16  void
    3.17 -dump_dtr(unsigned long base, unsigned long limit)
    3.18 +dump_dtr(unsigned long addr, unsigned long size)
    3.19  {
    3.20  	unsigned long long entry;
    3.21 +	unsigned long base, limit;
    3.22  	int i;
    3.23  
    3.24 -	for (i = 0; i < limit; i += 8) {
    3.25 -		entry = ((unsigned long long *) base)[i >> 3];
    3.26 -		printf("[0x%x] = 0x%08x%08x\n", i,
    3.27 -			(unsigned)(entry >> 32), (unsigned)(entry));
    3.28 +	for (i = 0; i < size; i += 8) {
    3.29 +		entry = ((unsigned long long *) addr)[i >> 3];
    3.30 +		base = (((entry >> (56-24)) & 0xFF000000) |
    3.31 +			((entry >> (32-16)) & 0x00FF0000) |
    3.32 +			((entry >> (   16)) & 0x0000FFFF));
    3.33 +		limit = (((entry >> (48-16)) & 0x000F0000) |
    3.34 +		         ((entry           ) & 0x0000FFFF));
    3.35 +		if (entry & (1ULL << (23+32))) /* G */
    3.36 +			limit = (limit << 12) | 0xFFF;
    3.37 +
    3.38 +		printf("[0x%x] = 0x%08x%08x, base 0x%lx, limit 0x%lx\n", i,
    3.39 +			(unsigned)(entry >> 32), (unsigned)(entry),
    3.40 +			base, limit);
    3.41  	}
    3.42  }
    3.43  
    3.44 @@ -120,18 +131,19 @@ void
    3.45  dump_vmx_context(struct vmx_assist_context *c)
    3.46  {
    3.47  	printf("eip 0x%lx, esp 0x%lx, eflags 0x%lx\n",
    3.48 -		c->eip, c->esp, c->eflags);
    3.49 +		(long) c->eip, (long) c->esp, (long) c->eflags);
    3.50  
    3.51 -	printf("cr0 0x%lx, cr3 0x%lx, cr4 0x%lx\n", c->cr0, c->cr3, c->cr4);
    3.52 +	printf("cr0 0x%lx, cr3 0x%lx, cr4 0x%lx\n",
    3.53 +		(long)c->cr0, (long)c->cr3, (long)c->cr4);
    3.54  
    3.55  	printf("idtr: limit 0x%lx, base 0x%lx\n",
    3.56 -		c->idtr_limit, c->idtr_base);
    3.57 +		(long)c->idtr_limit, (long)c->idtr_base);
    3.58  
    3.59  	printf("gdtr: limit 0x%lx, base 0x%lx\n",
    3.60 -		c->gdtr_limit, c->gdtr_base);
    3.61 +		(long)c->gdtr_limit, (long)c->gdtr_base);
    3.62  
    3.63  	printf("cs: sel 0x%lx, limit 0x%lx, base 0x%lx\n",
    3.64 -		c->cs_sel, c->cs_limit, c->cs_base);
    3.65 +		(long)c->cs_sel, (long)c->cs_limit, (long)c->cs_base);
    3.66  	printf("\ttype %d, s %d, dpl %d, p %d, avl %d, ops %d, g %d, nul %d\n",
    3.67  		c->cs_arbytes.fields.seg_type,
    3.68  		c->cs_arbytes.fields.s,
    3.69 @@ -143,7 +155,7 @@ dump_vmx_context(struct vmx_assist_conte
    3.70  		c->cs_arbytes.fields.null_bit);
    3.71  
    3.72  	printf("ds: sel 0x%lx, limit 0x%lx, base 0x%lx\n",
    3.73 -		c->ds_sel, c->ds_limit, c->ds_base);
    3.74 +		(long)c->ds_sel, (long)c->ds_limit, (long)c->ds_base);
    3.75  	printf("\ttype %d, s %d, dpl %d, p %d, avl %d, ops %d, g %d, nul %d\n",
    3.76  		c->ds_arbytes.fields.seg_type,
    3.77  		c->ds_arbytes.fields.s,
    3.78 @@ -155,7 +167,7 @@ dump_vmx_context(struct vmx_assist_conte
    3.79  		c->ds_arbytes.fields.null_bit);
    3.80  
    3.81  	printf("es: sel 0x%lx, limit 0x%lx, base 0x%lx\n",
    3.82 -		c->es_sel, c->es_limit, c->es_base);
    3.83 +		(long)c->es_sel, (long)c->es_limit, (long)c->es_base);
    3.84  	printf("\ttype %d, s %d, dpl %d, p %d, avl %d, ops %d, g %d, nul %d\n",
    3.85  		c->es_arbytes.fields.seg_type,
    3.86  		c->es_arbytes.fields.s,
    3.87 @@ -167,7 +179,7 @@ dump_vmx_context(struct vmx_assist_conte
    3.88  		c->es_arbytes.fields.null_bit);
    3.89  
    3.90  	printf("ss: sel 0x%lx, limit 0x%lx, base 0x%lx\n",
    3.91 -		c->ss_sel, c->ss_limit, c->ss_base);
    3.92 +		(long)c->ss_sel, (long)c->ss_limit, (long)c->ss_base);
    3.93  	printf("\ttype %d, s %d, dpl %d, p %d, avl %d, ops %d, g %d, nul %d\n",
    3.94  		c->ss_arbytes.fields.seg_type,
    3.95  		c->ss_arbytes.fields.s,
    3.96 @@ -179,7 +191,7 @@ dump_vmx_context(struct vmx_assist_conte
    3.97  		c->ss_arbytes.fields.null_bit);
    3.98  
    3.99  	printf("fs: sel 0x%lx, limit 0x%lx, base 0x%lx\n",
   3.100 -		c->fs_sel, c->fs_limit, c->fs_base);
   3.101 +		(long)c->fs_sel, (long)c->fs_limit, (long)c->fs_base);
   3.102  	printf("\ttype %d, s %d, dpl %d, p %d, avl %d, ops %d, g %d, nul %d\n",
   3.103  		c->fs_arbytes.fields.seg_type,
   3.104  		c->fs_arbytes.fields.s,
   3.105 @@ -191,7 +203,7 @@ dump_vmx_context(struct vmx_assist_conte
   3.106  		c->fs_arbytes.fields.null_bit);
   3.107  
   3.108  	printf("gs: sel 0x%lx, limit 0x%lx, base 0x%lx\n",
   3.109 -		c->gs_sel, c->gs_limit, c->gs_base);
   3.110 +		(long)c->gs_sel, (long)c->gs_limit, (long)c->gs_base);
   3.111  	printf("\ttype %d, s %d, dpl %d, p %d, avl %d, ops %d, g %d, nul %d\n",
   3.112  		c->gs_arbytes.fields.seg_type,
   3.113  		c->gs_arbytes.fields.s,
   3.114 @@ -203,7 +215,7 @@ dump_vmx_context(struct vmx_assist_conte
   3.115  		c->gs_arbytes.fields.null_bit);
   3.116  
   3.117  	printf("tr: sel 0x%lx, limit 0x%lx, base 0x%lx\n",
   3.118 -		c->tr_sel, c->tr_limit, c->tr_base);
   3.119 +		(long)c->tr_sel, (long)c->tr_limit, (long)c->tr_base);
   3.120  	printf("\ttype %d, s %d, dpl %d, p %d, avl %d, ops %d, g %d, nul %d\n",
   3.121  		c->tr_arbytes.fields.seg_type,
   3.122  		c->tr_arbytes.fields.s,
   3.123 @@ -215,7 +227,7 @@ dump_vmx_context(struct vmx_assist_conte
   3.124  		c->tr_arbytes.fields.null_bit);
   3.125  
   3.126  	printf("ldtr: sel 0x%lx, limit 0x%lx, base 0x%lx\n",
   3.127 -		c->ldtr_sel, c->ldtr_limit, c->ldtr_base);
   3.128 +		(long)c->ldtr_sel, (long)c->ldtr_limit, (long)c->ldtr_base);
   3.129  	printf("\ttype %d, s %d, dpl %d, p %d, avl %d, ops %d, g %d, nul %d\n",
   3.130  		c->ldtr_arbytes.fields.seg_type,
   3.131  		c->ldtr_arbytes.fields.s,
   3.132 @@ -226,7 +238,8 @@ dump_vmx_context(struct vmx_assist_conte
   3.133  		c->ldtr_arbytes.fields.g,
   3.134  		c->ldtr_arbytes.fields.null_bit);
   3.135  
   3.136 -	printf("GDTR <0x%lx,0x%lx>:\n", c->gdtr_base,  c->gdtr_limit);
   3.137 +	printf("GDTR <0x%lx,0x%lx>:\n",
   3.138 +		(long)c->gdtr_base, (long)c->gdtr_limit);
   3.139  	dump_dtr(c->gdtr_base, c->gdtr_limit);
   3.140  }
   3.141  #endif /* DEBUG */
     4.1 --- a/tools/firmware/vmxassist/vm86.c	Tue Mar 21 22:48:04 2006 +0100
     4.2 +++ b/tools/firmware/vmxassist/vm86.c	Tue Mar 21 22:50:48 2006 +0100
     4.3 @@ -3,7 +3,7 @@
     4.4   * little work as possible. 
     4.5   *
     4.6   * Leendert van Doorn, leendert@watson.ibm.com
     4.7 - * Copyright (c) 2005, International Business Machines Corporation.
     4.8 + * Copyright (c) 2005-2006, International Business Machines Corporation.
     4.9   *
    4.10   * This program is free software; you can redistribute it and/or modify it
    4.11   * under the terms and conditions of the GNU General Public License,
    4.12 @@ -35,7 +35,7 @@
    4.13  #define	SEG_GS		0x0080
    4.14  
    4.15  unsigned prev_eip = 0;
    4.16 -enum vm86_mode mode;
    4.17 +enum vm86_mode mode = 0;
    4.18  
    4.19  #ifdef DEBUG
    4.20  int traceset = 0;
    4.21 @@ -46,24 +46,21 @@ char *states[] = {
    4.22  	"<VM86_PROTECTED_TO_REAL>",
    4.23  	"<VM86_PROTECTED>"
    4.24  };
    4.25 +
    4.26 +static char *rnames[] = { "ax", "cx", "dx", "bx", "sp", "bp", "si", "di" };
    4.27  #endif /* DEBUG */
    4.28  
    4.29 -
    4.30  unsigned
    4.31  address(struct regs *regs, unsigned seg, unsigned off)
    4.32  {
    4.33  	unsigned long long entry;
    4.34  	unsigned addr;
    4.35  
    4.36 -	/* real mode: segment is part of the address */
    4.37 -	if (mode == VM86_REAL || mode == VM86_REAL_TO_PROTECTED)
    4.38 -		return ((seg & 0xFFFF) << 4) + off;
    4.39 +	if (seg == 0)
    4.40 +		return off;
    4.41  
    4.42 -	/* protected mode: use seg as index into gdt */
    4.43 -	if (seg > oldctx.gdtr_limit) {
    4.44 -		printf("address: Invalid segment descriptor (0x%x)\n", seg);
    4.45 -		return 0;
    4.46 -	}
    4.47 +	if (seg > oldctx.gdtr_limit)
    4.48 +		return ((seg & 0xFFFF) << 4) + off;
    4.49  
    4.50  	entry = ((unsigned long long *) oldctx.gdtr_base)[seg >> 3];
    4.51  	addr = (((entry >> (56-24)) & 0xFF000000) |
    4.52 @@ -198,7 +195,7 @@ fetch8(struct regs *regs)
    4.53  }
    4.54  
    4.55  unsigned
    4.56 -getreg(struct regs *regs, int r)
    4.57 +getreg32(struct regs *regs, int r)
    4.58  {
    4.59  	switch (r & 7) {
    4.60  	case 0: return regs->eax;
    4.61 @@ -213,8 +210,30 @@ getreg(struct regs *regs, int r)
    4.62  	return ~0;
    4.63  }
    4.64  
    4.65 +unsigned
    4.66 +getreg16(struct regs *regs, int r)
    4.67 +{
    4.68 +	return MASK16(getreg32(regs, r));
    4.69 +}
    4.70 +
    4.71 +unsigned
    4.72 +getreg8(struct regs *regs, int r)
    4.73 +{
    4.74 +	switch (r & 7) {
    4.75 +	case 0: return regs->eax & 0xFF; /* al */
    4.76 +	case 1: return regs->ecx & 0xFF; /* cl */
    4.77 +	case 2: return regs->edx & 0xFF; /* dl */
    4.78 +	case 3: return regs->ebx & 0xFF; /* bl */
    4.79 +	case 4: return (regs->esp >> 8) & 0xFF; /* ah */
    4.80 +	case 5: return (regs->ebp >> 8) & 0xFF; /* ch */
    4.81 +	case 6: return (regs->esi >> 8) & 0xFF; /* dh */
    4.82 +	case 7: return (regs->edi >> 8) & 0xFF; /* bh */
    4.83 +	}
    4.84 +	return ~0;
    4.85 +}
    4.86 +
    4.87  void
    4.88 -setreg(struct regs *regs, int r, unsigned v)
    4.89 +setreg32(struct regs *regs, int r, unsigned v)
    4.90  {
    4.91  	switch (r & 7) {
    4.92  	case 0: regs->eax = v; break;
    4.93 @@ -228,15 +247,31 @@ setreg(struct regs *regs, int r, unsigne
    4.94  	}
    4.95  }
    4.96  
    4.97 -/*
    4.98 - * Operand (modrm) decode
    4.99 - */
   4.100 +void
   4.101 +setreg16(struct regs *regs, int r, unsigned v)
   4.102 +{
   4.103 +	setreg32(regs, r, (getreg32(regs, r) & ~0xFFFF) | MASK16(v));
   4.104 +}
   4.105 +
   4.106 +void
   4.107 +setreg8(struct regs *regs, int r, unsigned v)
   4.108 +{
   4.109 +	v &= 0xFF;
   4.110 +	switch (r & 7) {
   4.111 +	case 0: regs->eax = (regs->eax & ~0xFF) | v; break;
   4.112 +	case 1: regs->ecx = (regs->ecx & ~0xFF) | v; break;
   4.113 +	case 2: regs->edx = (regs->edx & ~0xFF) | v; break;
   4.114 +	case 3: regs->ebx = (regs->ebx & ~0xFF) | v; break;
   4.115 +	case 4: regs->esp = (regs->esp & ~0xFF00) | (v << 8); break;
   4.116 +	case 5: regs->ebp = (regs->ebp & ~0xFF00) | (v << 8); break;
   4.117 +	case 6: regs->esi = (regs->esi & ~0xFF00) | (v << 8); break;
   4.118 +	case 7: regs->edi = (regs->edi & ~0xFF00) | (v << 8); break;
   4.119 +	}
   4.120 +}
   4.121 +
   4.122  unsigned
   4.123 -operand(unsigned prefix, struct regs *regs, unsigned modrm)
   4.124 +segment(unsigned prefix, struct regs *regs, unsigned seg)
   4.125  {
   4.126 -	int mod, disp = 0, seg;
   4.127 -
   4.128 -	seg = regs->vds;
   4.129  	if (prefix & SEG_ES)
   4.130  		seg = regs->ves;
   4.131  	if (prefix & SEG_DS)
   4.132 @@ -249,6 +284,47 @@ operand(unsigned prefix, struct regs *re
   4.133  		seg = regs->fs;
   4.134  	if (prefix & SEG_GS)
   4.135  		seg = regs->gs;
   4.136 +	return seg;
   4.137 +}
   4.138 +
   4.139 +unsigned
   4.140 +sib(struct regs *regs, int mod, unsigned byte)
   4.141 +{
   4.142 +	unsigned scale = (byte >> 6) & 3;
   4.143 +	int index = (byte >> 3) & 7;
   4.144 +	int base = byte & 7;
   4.145 +	unsigned addr = 0;
   4.146 +
   4.147 +	switch (mod) {
   4.148 +	case 0:
   4.149 +		if (base == 5)
   4.150 +			addr = fetch32(regs);
   4.151 +		else
   4.152 +			addr = getreg32(regs, base);
   4.153 +		break;
   4.154 +	case 1:
   4.155 +		addr = getreg32(regs, base) + (char) fetch8(regs);
   4.156 +		break;
   4.157 +	case 2:
   4.158 +		addr = getreg32(regs, base) + fetch32(regs);
   4.159 +		break;
   4.160 +	}
   4.161 +
   4.162 +	if (index != 4)
   4.163 +		addr += getreg32(regs, index) << scale;
   4.164 +
   4.165 +	return addr;
   4.166 +}
   4.167 +
   4.168 +/*
   4.169 + * Operand (modrm) decode
   4.170 + */
   4.171 +unsigned
   4.172 +operand(unsigned prefix, struct regs *regs, unsigned modrm)
   4.173 +{
   4.174 +	int mod, disp = 0, seg;
   4.175 +
   4.176 +	seg = segment(prefix, regs, regs->vds);
   4.177  
   4.178  	if (prefix & ADDR32) { /* 32-bit addressing */
   4.179  		switch ((mod = (modrm >> 6) & 3)) {
   4.180 @@ -258,7 +334,8 @@ operand(unsigned prefix, struct regs *re
   4.181  			case 1: return address(regs, seg, regs->ecx);
   4.182  			case 2: return address(regs, seg, regs->edx);
   4.183  			case 3: return address(regs, seg, regs->ebx);
   4.184 -			case 4: panic("No SIB decode (yet)");
   4.185 +			case 4: return address(regs, seg,
   4.186 +					       sib(regs, mod, fetch8(regs)));
   4.187  			case 5: return address(regs, seg, fetch32(regs));
   4.188  			case 6: return address(regs, seg, regs->esi);
   4.189  			case 7: return address(regs, seg, regs->edi);
   4.190 @@ -277,14 +354,15 @@ operand(unsigned prefix, struct regs *re
   4.191  			case 1: return address(regs, seg, regs->ecx + disp);
   4.192  			case 2: return address(regs, seg, regs->edx + disp);
   4.193  			case 3: return address(regs, seg, regs->ebx + disp);
   4.194 -			case 4: panic("No SIB decode (yet)");
   4.195 +			case 4: return address(regs, seg,
   4.196 +					       sib(regs, mod, fetch8(regs)));
   4.197  			case 5: return address(regs, seg, regs->ebp + disp);
   4.198  			case 6: return address(regs, seg, regs->esi + disp);
   4.199  			case 7: return address(regs, seg, regs->edi + disp);
   4.200  			}
   4.201  			break;
   4.202  		case 3:
   4.203 -			return getreg(regs, modrm);
   4.204 +			return getreg32(regs, modrm);
   4.205  		}
   4.206  	} else { /* 16-bit addressing */
   4.207  		switch ((mod = (modrm >> 6) & 3)) {
   4.208 @@ -330,7 +408,7 @@ operand(unsigned prefix, struct regs *re
   4.209  			}
   4.210  			break;
   4.211  		case 3:
   4.212 -			return MASK16(getreg(regs, modrm));
   4.213 +			return getreg16(regs, modrm);
   4.214  		}
   4.215  	}
   4.216  
   4.217 @@ -400,6 +478,72 @@ lmsw(struct regs *regs, unsigned prefix,
   4.218  }
   4.219  
   4.220  /*
   4.221 + * We need to handle moves that address memory beyond the 64KB segment
   4.222 + * limit that VM8086 mode enforces.
   4.223 + */
   4.224 +int
   4.225 +movr(struct regs *regs, unsigned prefix, unsigned opc)
   4.226 +{
   4.227 +	unsigned eip = regs->eip - 1;
   4.228 +	unsigned modrm = fetch8(regs);
   4.229 +	unsigned addr = operand(prefix, regs, modrm);
   4.230 +	unsigned val, r = (modrm >> 3) & 7;
   4.231 +
   4.232 +	if ((modrm & 0xC0) == 0xC0) /* no registers */
   4.233 +		return 0;
   4.234 +
   4.235 +	switch (opc) {
   4.236 +	case 0x88: /* addr32 mov r8, r/m8 */
   4.237 +		val = getreg8(regs, r);
   4.238 +		TRACE((regs, regs->eip - eip,
   4.239 +			"movb %%e%s, *0x%x", rnames[r], addr));
   4.240 +		write8(addr, val);
   4.241 +		break;
   4.242 +
   4.243 +	case 0x8A: /* addr32 mov r/m8, r8 */
   4.244 +		TRACE((regs, regs->eip - eip,
   4.245 +			"movb *0x%x, %%%s", addr, rnames[r]));
   4.246 +		setreg8(regs, r, read8(addr));
   4.247 +		break;
   4.248 +
   4.249 +	case 0x89: /* addr32 mov r16, r/m16 */
   4.250 +		val = getreg32(regs, r);
   4.251 +		if (prefix & DATA32) {
   4.252 +			TRACE((regs, regs->eip - eip,
   4.253 +				"movl %%e%s, *0x%x", rnames[r], addr));
   4.254 +			write32(addr, val);
   4.255 +		} else {
   4.256 +			TRACE((regs, regs->eip - eip,
   4.257 +				"movw %%%s, *0x%x", rnames[r], addr));
   4.258 +			write16(addr, MASK16(val));
   4.259 +		}
   4.260 +		break;
   4.261 +
   4.262 +	case 0x8B: /* addr32 mov r/m16, r16 */
   4.263 +		if (prefix & DATA32) {
   4.264 +			TRACE((regs, regs->eip - eip,
   4.265 +				"movl *0x%x, %%e%s", addr, rnames[r]));
   4.266 +			setreg32(regs, r, read32(addr));
   4.267 +		} else {
   4.268 +			TRACE((regs, regs->eip - eip,
   4.269 +				"movw *0x%x, %%%s", addr, rnames[r]));
   4.270 +			setreg16(regs, r, read16(addr));
   4.271 +		}
   4.272 +		break;
   4.273 +
   4.274 +	case 0xC6: /* addr32 movb $imm, r/m8 */
   4.275 +		if ((modrm >> 3) & 7)
   4.276 +			return 0;
   4.277 +		val = fetch8(regs);
   4.278 +		write8(addr, val);
   4.279 +		TRACE((regs, regs->eip - eip, "movb $0x%x, *0x%x",
   4.280 +							val, addr));
   4.281 +		break;
   4.282 +	}
   4.283 +	return 1;
   4.284 +}
   4.285 +
   4.286 +/*
   4.287   * Move to and from a control register.
   4.288   */
   4.289  int
   4.290 @@ -418,21 +562,21 @@ movcr(struct regs *regs, unsigned prefix
   4.291  		switch (cr) {
   4.292  		case 0:
   4.293  #ifndef TEST
   4.294 -			setreg(regs, modrm,
   4.295 +			setreg32(regs, modrm,
   4.296  				oldctx.cr0 & ~(CR0_PE | CR0_NE));
   4.297  #else
   4.298 -			setreg(regs, modrm,
   4.299 +			setreg32(regs, modrm,
   4.300  				oldctx.cr0 & ~(CR0_PE | CR0_NE | CR0_PG));
   4.301  #endif
   4.302  			break;
   4.303  		case 2:
   4.304 -			setreg(regs, modrm, get_cr2());
   4.305 +			setreg32(regs, modrm, get_cr2());
   4.306  			break;
   4.307  		case 3:
   4.308 -			setreg(regs, modrm, oldctx.cr3);
   4.309 +			setreg32(regs, modrm, oldctx.cr3);
   4.310  			break;
   4.311  		case 4:
   4.312 -			setreg(regs, modrm, oldctx.cr4);
   4.313 +			setreg32(regs, modrm, oldctx.cr4);
   4.314  			break;
   4.315  		}
   4.316  		break;
   4.317 @@ -440,19 +584,20 @@ movcr(struct regs *regs, unsigned prefix
   4.318  		TRACE((regs, regs->eip - eip, "movl %%eax, %%cr%d", cr));
   4.319  		switch (cr) {
   4.320  		case 0:
   4.321 -			oldctx.cr0 = getreg(regs, modrm) | (CR0_PE | CR0_NE);
   4.322 +			oldctx.cr0 = getreg32(regs, modrm) | (CR0_PE | CR0_NE);
   4.323  #ifdef TEST
   4.324  			oldctx.cr0 |= CR0_PG;
   4.325  #endif
   4.326 -			if (getreg(regs, modrm) & CR0_PE)
   4.327 +			if (getreg32(regs, modrm) & CR0_PE)
   4.328  				set_mode(regs, VM86_REAL_TO_PROTECTED);
   4.329 -
   4.330 +			else
   4.331 +				set_mode(regs, VM86_REAL);
   4.332  			break;
   4.333  		case 3:
   4.334 -			oldctx.cr3 = getreg(regs, modrm);
   4.335 +			oldctx.cr3 = getreg32(regs, modrm);
   4.336  			break;
   4.337  		case 4:
   4.338 -			oldctx.cr4 = getreg(regs, modrm);
   4.339 +			oldctx.cr4 = getreg32(regs, modrm);
   4.340  			break;
   4.341  		}
   4.342  		break;
   4.343 @@ -461,6 +606,118 @@ movcr(struct regs *regs, unsigned prefix
   4.344  	return 1;
   4.345  }
   4.346  
   4.347 +static inline void set_eflags_ZF(unsigned mask, unsigned v1, struct regs *regs)
   4.348 +{
   4.349 +	if ((v1 & mask) == 0)
   4.350 +		regs->eflags |= EFLAGS_ZF;
   4.351 +	else
   4.352 +		regs->eflags &= ~EFLAGS_ZF;
   4.353 +}
   4.354 +
   4.355 +/*
   4.356 + * We need to handle cmp opcodes that address memory beyond the 64KB
   4.357 + * segment limit that VM8086 mode enforces.
   4.358 + */
   4.359 +int
   4.360 +cmp(struct regs *regs, unsigned prefix, unsigned opc)
   4.361 +{
   4.362 +	unsigned eip = regs->eip - 1;
   4.363 +	unsigned modrm = fetch8(regs);
   4.364 +	unsigned addr = operand(prefix, regs, modrm);
   4.365 +	unsigned diff, val, r = (modrm >> 3) & 7;
   4.366 +
   4.367 +	if ((modrm & 0xC0) == 0xC0) /* no registers */
   4.368 +		return 0;
   4.369 +
   4.370 +	switch (opc) {
   4.371 +	case 0x39: /* addr32 cmp r16, r/m16 */
   4.372 +		val = getreg32(regs, r);
   4.373 +		if (prefix & DATA32) {
   4.374 +			diff = read32(addr) - val;
   4.375 +			set_eflags_ZF(~0, diff, regs);
   4.376 +
   4.377 +			TRACE((regs, regs->eip - eip,
   4.378 +				"cmp %%e%s, *0x%x (0x%x)",
   4.379 +				rnames[r], addr, diff));
   4.380 +		} else {
   4.381 +			diff = read16(addr) - val;
   4.382 +			set_eflags_ZF(0xFFFF, diff, regs);
   4.383 +
   4.384 +			TRACE((regs, regs->eip - eip,
   4.385 +				"cmp %%%s, *0x%x (0x%x)",
   4.386 +				rnames[r], addr, diff));
   4.387 +		}
   4.388 +		break;
   4.389 +
   4.390 +	/* other cmp opcodes ... */
   4.391 +	}
   4.392 +	return 1;
   4.393 +}
   4.394 +
   4.395 +/*
   4.396 + * We need to handle test opcodes that address memory beyond the 64KB
   4.397 + * segment limit that VM8086 mode enforces.
   4.398 + */
   4.399 +int
   4.400 +test(struct regs *regs, unsigned prefix, unsigned opc)
   4.401 +{
   4.402 +	unsigned eip = regs->eip - 1;
   4.403 +	unsigned modrm = fetch8(regs);
   4.404 +	unsigned addr = operand(prefix, regs, modrm);
   4.405 +	unsigned val, diff;
   4.406 +
   4.407 +	if ((modrm & 0xC0) == 0xC0) /* no registers */
   4.408 +		return 0;
   4.409 +
   4.410 +	switch (opc) {
   4.411 +	case 0xF6: /* testb $imm, r/m8 */
   4.412 +		if ((modrm >> 3) & 7)
   4.413 +			return 0;
   4.414 +		val = fetch8(regs);
   4.415 +		diff = read8(addr) & val;
   4.416 +		set_eflags_ZF(0xFF, diff, regs);
   4.417 +
   4.418 +		TRACE((regs, regs->eip - eip, "testb $0x%x, *0x%x (0x%x)",
   4.419 +							val, addr, diff));
   4.420 +		break;
   4.421 +
   4.422 +	/* other test opcodes ... */
   4.423 +	}
   4.424 +
   4.425 +	return 1;
   4.426 +}
   4.427 +
   4.428 +/*
   4.429 + * We need to handle pop opcodes that address memory beyond the 64KB
   4.430 + * segment limit that VM8086 mode enforces.
   4.431 + */
   4.432 +int
   4.433 +pop(struct regs *regs, unsigned prefix, unsigned opc)
   4.434 +{
   4.435 +	unsigned eip = regs->eip - 1;
   4.436 +	unsigned modrm = fetch8(regs);
   4.437 +	unsigned addr = operand(prefix, regs, modrm);
   4.438 +
   4.439 +	if ((modrm & 0xC0) == 0xC0) /* no registers */
   4.440 +		return 0;
   4.441 +
   4.442 +	switch (opc) {
   4.443 +	case 0x8F: /* pop r/m16 */
   4.444 +		if ((modrm >> 3) & 7)
   4.445 +			return 0;
   4.446 +		if (prefix & DATA32)
   4.447 +			write32(addr, pop32(regs));
   4.448 +		else
   4.449 +			write16(addr, pop16(regs));
   4.450 +		TRACE((regs, regs->eip - eip, "pop *0x%x", addr));
   4.451 +		break;
   4.452 +
   4.453 +	/* other pop opcodes ... */
   4.454 +	}
   4.455 +
   4.456 +	return 1;
   4.457 +}
   4.458 +
   4.459  /*
   4.460   * Emulate a segment load in protected mode
   4.461   */
   4.462 @@ -473,17 +730,16 @@ load_seg(unsigned long sel, uint32_t *ba
   4.463  	if (sel > oldctx.gdtr_limit)
   4.464  		return 0;
   4.465  
   4.466 -    if (sel == 0) {
   4.467 -        arbytes->fields.null_bit = 1;
   4.468 -        return 1;
   4.469 -    }
   4.470 +	if (sel == 0) {
   4.471 +		arbytes->fields.null_bit = 1;
   4.472 +		return 1;
   4.473 +	}
   4.474  
   4.475  	entry =  ((unsigned long long *) oldctx.gdtr_base)[sel >> 3];
   4.476  
   4.477 -    /* Check the P bit fisrt*/
   4.478 -    if (!((entry >> (15+32)) & 0x1) && sel != 0) {
   4.479 -        return 0;
   4.480 -    }
   4.481 +	/* Check the P bit first */
   4.482 +	if (!((entry >> (15+32)) & 0x1) && sel != 0)
   4.483 +		return 0;
   4.484  
   4.485  	*base =  (((entry >> (56-24)) & 0xFF000000) |
   4.486  		  ((entry >> (32-16)) & 0x00FF0000) |
   4.487 @@ -530,42 +786,47 @@ protected_mode(struct regs *regs)
   4.488  	if (load_seg(regs->ves, &oldctx.es_base,
   4.489  				&oldctx.es_limit, &oldctx.es_arbytes))
   4.490  		oldctx.es_sel = regs->ves;
   4.491 -    else {
   4.492 -        load_seg(0, &oldctx.es_base,&oldctx.es_limit, &oldctx.es_arbytes);
   4.493 -        oldctx.es_sel = 0;
   4.494 -    }
   4.495 +	else {
   4.496 +		load_seg(0, &oldctx.es_base,
   4.497 +			    &oldctx.es_limit, &oldctx.es_arbytes);
   4.498 +		oldctx.es_sel = 0;
   4.499 +	}
   4.500  
   4.501  	if (load_seg(regs->uss, &oldctx.ss_base,
   4.502  				&oldctx.ss_limit, &oldctx.ss_arbytes))
   4.503  		oldctx.ss_sel = regs->uss;
   4.504 -    else {
   4.505 -        load_seg(0, &oldctx.ss_base, &oldctx.ss_limit, &oldctx.ss_arbytes);
   4.506 -        oldctx.ss_sel = 0;
   4.507 -    }
   4.508 +	else {
   4.509 +		load_seg(0, &oldctx.ss_base,
   4.510 +			    &oldctx.ss_limit, &oldctx.ss_arbytes);
   4.511 +		oldctx.ss_sel = 0;
   4.512 +	}
   4.513  
   4.514  	if (load_seg(regs->vds, &oldctx.ds_base,
   4.515  				&oldctx.ds_limit, &oldctx.ds_arbytes))
   4.516  		oldctx.ds_sel = regs->vds;
   4.517 -    else {
   4.518 -        load_seg(0, &oldctx.ds_base, &oldctx.ds_limit, &oldctx.ds_arbytes);
   4.519 -        oldctx.ds_sel = 0;
   4.520 -    }
   4.521 +	else {
   4.522 +		load_seg(0, &oldctx.ds_base,
   4.523 +			    &oldctx.ds_limit, &oldctx.ds_arbytes);
   4.524 +		oldctx.ds_sel = 0;
   4.525 +	}
   4.526  
   4.527  	if (load_seg(regs->vfs, &oldctx.fs_base,
   4.528  				&oldctx.fs_limit, &oldctx.fs_arbytes))
   4.529  		oldctx.fs_sel = regs->vfs;
   4.530 -    else {
   4.531 -        load_seg(0, &oldctx.fs_base, &oldctx.fs_limit, &oldctx.fs_arbytes);
   4.532 -        oldctx.fs_sel = 0;
   4.533 -    }
   4.534 +	else {
   4.535 +		load_seg(0, &oldctx.fs_base,
   4.536 +			    &oldctx.fs_limit, &oldctx.fs_arbytes);
   4.537 +		oldctx.fs_sel = 0;
   4.538 +	}
   4.539  
   4.540  	if (load_seg(regs->vgs, &oldctx.gs_base,
   4.541  				&oldctx.gs_limit, &oldctx.gs_arbytes))
   4.542  		oldctx.gs_sel = regs->vgs;
   4.543 -    else {
   4.544 -        load_seg(0, &oldctx.gs_base, &oldctx.gs_limit, &oldctx.gs_arbytes);
   4.545 -        oldctx.gs_sel = 0;
   4.546 -    }
   4.547 +	else {
   4.548 +		load_seg(0, &oldctx.gs_base,
   4.549 +			    &oldctx.gs_limit, &oldctx.gs_arbytes);
   4.550 +		oldctx.gs_sel = 0;
   4.551 +	}
   4.552  
   4.553  	/* initialize jump environment to warp back to protected mode */
   4.554  	regs->cs = CODE_SELECTOR;
   4.555 @@ -618,22 +879,24 @@ real_mode(struct regs *regs)
   4.556  
   4.557  /*
   4.558   * This is the smarts of the emulator and handles the mode transitions. The
   4.559 - * emulator handles 4 different modes. 1) VM86_REAL: emulated real-mode, Just
   4.560 - * handle those instructions that are not supported under VM8086.
   4.561 - * 2) VM86_REAL_TO_PROTECTED: going from real-mode to protected mode. In this
   4.562 - * we single step through the instructions until we reload the new %cs (some
   4.563 - * OSes do a lot of computations before reloading %cs). 2) VM86_PROTECTED_TO_REAL
   4.564 - * when we are going from protected to real mode. In this case we emulate the
   4.565 - * instructions by hand. Finally, 4) VM86_PROTECTED when we transitioned to
   4.566 - * protected mode and we should abandon the emulator. No instructions are
   4.567 - * emulated when in VM86_PROTECTED mode.
   4.568 + * emulator handles 4 different modes. 1) VM86_REAL: emulated real-mode,
   4.569 + * Just handle those instructions that are not supported under VM8086.
   4.570 + * 2) VM86_REAL_TO_PROTECTED: going from real-mode to protected mode. In
   4.571 + * this we single step through the instructions until we reload the
   4.572 + * new %cs (some OSes do a lot of computations before reloading %cs). 2)
   4.573 + * VM86_PROTECTED_TO_REAL when we are going from protected to real mode. In
   4.574 + * this case we emulate the instructions by hand. Finally, 4) VM86_PROTECTED
   4.575 + * when we transitioned to protected mode and we should abandon the
   4.576 + * emulator. No instructions are emulated when in VM86_PROTECTED mode.
   4.577   */
   4.578  void
   4.579  set_mode(struct regs *regs, enum vm86_mode newmode)
   4.580  {
   4.581  	switch (newmode) {
   4.582  	case VM86_REAL:
   4.583 -		if (mode == VM86_PROTECTED_TO_REAL) {
   4.584 +		if ((mode == VM86_PROTECTED_TO_REAL) ||
   4.585 +		    (mode == VM86_REAL_TO_PROTECTED)) {
   4.586 +			regs->eflags &= ~EFLAGS_TF;
   4.587  			real_mode(regs);
   4.588  			break;
   4.589  		} else if (mode == VM86_REAL) {
   4.590 @@ -653,10 +916,11 @@ set_mode(struct regs *regs, enum vm86_mo
   4.591  		break;
   4.592  
   4.593  	case VM86_PROTECTED_TO_REAL:
   4.594 -		if (mode == VM86_PROTECTED)
   4.595 +		if (mode == VM86_PROTECTED) {
   4.596  			break;
   4.597 -		else
   4.598 +		} else
   4.599  			panic("unexpected protected-to-real mode transition");
   4.600 +		break;
   4.601  
   4.602  	case VM86_PROTECTED:
   4.603  		if (mode == VM86_REAL_TO_PROTECTED) {
   4.604 @@ -887,6 +1151,16 @@ opcode(struct regs *regs)
   4.605  			prefix |= SEG_SS;
   4.606  			continue;
   4.607  
   4.608 +		case 0x39: /* addr32 cmp r16, r/m16 */
   4.609 +		case 0x3B: /* addr32 cmp r/m16, r16 */
   4.610 +			if (mode != VM86_REAL && mode != VM86_REAL_TO_PROTECTED)
   4.611 +				goto invalid;
   4.612 +                        if ((prefix & ADDR32) == 0)
   4.613 +                                goto invalid;
   4.614 +                        if (!cmp(regs, prefix, opc))
   4.615 +                                goto invalid;
   4.616 +                        return OPC_EMULATED;
   4.617 +
   4.618  		case 0x3E:
   4.619  			TRACE((regs, regs->eip - eip, "%%ds:"));
   4.620  			prefix |= SEG_DS;
   4.621 @@ -912,6 +1186,33 @@ opcode(struct regs *regs)
   4.622  			prefix |= ADDR32;
   4.623  			continue;
   4.624  
   4.625 +		case 0x88: /* addr32 mov r8, r/m8 */
   4.626 +		case 0x8A: /* addr32 mov r/m8, r8 */
   4.627 +			if (mode != VM86_REAL && mode != VM86_REAL_TO_PROTECTED)
   4.628 +				goto invalid;
   4.629 +                        if ((prefix & ADDR32) == 0)
   4.630 +                                goto invalid;
   4.631 +                        if (!movr(regs, prefix, opc))
   4.632 +                                goto invalid;
   4.633 +                        return OPC_EMULATED;
   4.634 +
   4.635 +		case 0x89: /* addr32 mov r16, r/m16 */
   4.636 +		case 0x8B: /* addr32 mov r/m16, r16 */
   4.637 +			if (mode != VM86_REAL && mode != VM86_REAL_TO_PROTECTED)
   4.638 +				goto invalid;
   4.639 +                        if ((prefix & ADDR32) == 0)
   4.640 +                                goto invalid;
   4.641 +                        if (!movr(regs, prefix, opc))
   4.642 +                                goto invalid;
   4.643 +                        return OPC_EMULATED;
   4.644 +
   4.645 +		case 0x8F: /* addr32 pop r/m16 */
   4.646 +                        if ((prefix & ADDR32) == 0)
   4.647 +                                goto invalid;
   4.648 +                        if (!pop(regs, prefix, opc))
   4.649 +                                goto invalid;
   4.650 +                        return OPC_EMULATED;
   4.651 +
   4.652  		case 0x90: /* nop */
   4.653  			TRACE((regs, regs->eip - eip, "nop"));
   4.654  			return OPC_EMULATED;
   4.655 @@ -924,7 +1225,7 @@ opcode(struct regs *regs)
   4.656  				push16(regs, regs->eflags & ~EFLAGS_VM);
   4.657  			return OPC_EMULATED;
   4.658  
   4.659 -		case 0x9D:	/* popf */
   4.660 +		case 0x9D: /* popf */
   4.661  			TRACE((regs, regs->eip - eip, "popf"));
   4.662  			if (prefix & DATA32)
   4.663  				regs->eflags = pop32(regs);
   4.664 @@ -934,7 +1235,14 @@ opcode(struct regs *regs)
   4.665  			regs->eflags |= EFLAGS_VM;
   4.666  			return OPC_EMULATED;
   4.667  
   4.668 -		case 0xCB:	/* retl */
   4.669 +		case 0xC6: /* addr32 movb $imm, r/m8 */
   4.670 +                        if ((prefix & ADDR32) == 0)
   4.671 +                                goto invalid;
   4.672 +                        if (!movr(regs, prefix, opc))
   4.673 +                                goto invalid;
   4.674 +			return OPC_EMULATED;
   4.675 +
   4.676 +		case 0xCB: /* retl */
   4.677  			if ((mode == VM86_REAL_TO_PROTECTED) ||
   4.678  			    (mode == VM86_PROTECTED_TO_REAL)) {
   4.679  				retl(regs, prefix);
   4.680 @@ -942,12 +1250,12 @@ opcode(struct regs *regs)
   4.681  			}
   4.682  			goto invalid;
   4.683  
   4.684 -		case 0xCD:	/* int $n */
   4.685 +		case 0xCD: /* int $n */
   4.686  			TRACE((regs, regs->eip - eip, "int"));
   4.687  			interrupt(regs, fetch8(regs));
   4.688  			return OPC_EMULATED;
   4.689  
   4.690 -		case 0xCF:	/* iret */
   4.691 +		case 0xCF: /* iret */
   4.692  			if (prefix & DATA32) {
   4.693  				TRACE((regs, regs->eip - eip, "data32 iretd"));
   4.694  				regs->eip = pop32(regs);
   4.695 @@ -962,17 +1270,17 @@ opcode(struct regs *regs)
   4.696  			}
   4.697  			return OPC_EMULATED;
   4.698  
   4.699 -		case 0xE4:	/* inb al, port */
   4.700 +		case 0xE4: /* inb al, port */
   4.701  			if (!inbyte(regs, prefix, opc))
   4.702  				goto invalid;
   4.703  			return OPC_EMULATED;
   4.704  
   4.705 -		case 0xE6:	/* outb port, al */
   4.706 +		case 0xE6: /* outb port, al */
   4.707  			if (!outbyte(regs, prefix, opc))
   4.708  				goto invalid;
   4.709  			return OPC_EMULATED;
   4.710  
   4.711 -		case 0xEA: 	/* jmpl */
   4.712 +		case 0xEA: /* jmpl */
   4.713  			if ((mode == VM86_REAL_TO_PROTECTED) ||
   4.714  			    (mode == VM86_PROTECTED_TO_REAL)) {
   4.715  				jmpl(regs, prefix);
   4.716 @@ -980,7 +1288,7 @@ opcode(struct regs *regs)
   4.717  			}
   4.718  			goto invalid;
   4.719  
   4.720 -		case 0xEB:	/* short jump */
   4.721 +		case 0xEB: /* short jump */
   4.722  			if ((mode == VM86_REAL_TO_PROTECTED) ||
   4.723  			    (mode == VM86_PROTECTED_TO_REAL)) {
   4.724  				disp = (char) fetch8(regs);
   4.725 @@ -990,26 +1298,33 @@ opcode(struct regs *regs)
   4.726  			}
   4.727  			goto invalid;
   4.728  
   4.729 -		case 0xEC:	/* inb al, (%dx) */
   4.730 +		case 0xEC: /* inb al, (%dx) */
   4.731  			if (!inbyte(regs, prefix, opc))
   4.732  				goto invalid;
   4.733  			return OPC_EMULATED;
   4.734  
   4.735 -		case 0xEE:	/* outb (%dx), al */
   4.736 +		case 0xEE: /* outb (%dx), al */
   4.737  			if (!outbyte(regs, prefix, opc))
   4.738  				goto invalid;
   4.739  			return OPC_EMULATED;
   4.740  
   4.741 -		case 0xF0:	/* lock */
   4.742 +		case 0xF0: /* lock */
   4.743  			TRACE((regs, regs->eip - eip, "lock"));
   4.744  			continue;
   4.745  
   4.746 -		case 0xFA:	/* cli */
   4.747 +		case 0xF6: /* addr32 testb $imm, r/m8 */
   4.748 +                        if ((prefix & ADDR32) == 0)
   4.749 +                                goto invalid;
   4.750 +                        if (!test(regs, prefix, opc))
   4.751 +                                goto invalid;
   4.752 +			return OPC_EMULATED;
   4.753 +
   4.754 +		case 0xFA: /* cli */
   4.755  			TRACE((regs, regs->eip - eip, "cli"));
   4.756  			regs->eflags &= ~EFLAGS_IF;
   4.757  			return OPC_EMULATED;
   4.758  
   4.759 -		case 0xFB:	/* sti */
   4.760 +		case 0xFB: /* sti */
   4.761  			TRACE((regs, regs->eip - eip, "sti"));
   4.762  			regs->eflags |= EFLAGS_IF;
   4.763  			return OPC_EMULATED;
   4.764 @@ -1021,6 +1336,7 @@ opcode(struct regs *regs)
   4.765  
   4.766  invalid:
   4.767  	regs->eip = eip;
   4.768 +	TRACE((regs, regs->eip - eip, "opc 0x%x", opc));
   4.769  	return OPC_INVALID;
   4.770  }
   4.771  
   4.772 @@ -1087,4 +1403,3 @@ trap(int trapno, int errno, struct regs 
   4.773  		halt();
   4.774  	}
   4.775  }
   4.776 -