ia64/xen-unstable

changeset 6621:f27205ea60ef

merge?
author cl349@firebug.cl.cam.ac.uk
date Sat Sep 03 16:58:50 2005 +0000 (2005-09-03)
parents 5aae0c8158b9 ce018d2730c0
children 29808fef9148 2e2611af05c6
files .hgignore linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c linux-2.6-xen-sparse/drivers/xen/evtchn/evtchn.c linux-2.6-xen-sparse/drivers/xen/xenbus/Makefile linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.c linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_xs.c linux-2.6-xen-sparse/mm/memory.c tools/firmware/rombios/rombios.c tools/firmware/vmxassist/Makefile tools/firmware/vmxassist/setup.c tools/firmware/vmxassist/vm86.c tools/firmware/vmxassist/vmxloader.c tools/ioemu/exec.c tools/ioemu/hw/pcnet.c tools/ioemu/target-i386-dm/helper2.c tools/ioemu/vl.c tools/libxc/xc_linux_save.c tools/libxc/xenguest.h tools/python/xen/xend/XendCheckpoint.py tools/python/xen/xend/XendDomain.py tools/xcutils/xc_save.c tools/xenstore/Makefile tools/xenstore/xs.c tools/xenstore/xs.h tools/xenstore/xs_lib.c tools/xenstore/xs_lib.h xen/arch/x86/shadow.c xen/arch/x86/vmx.c xen/arch/x86/vmx_intercept.c xen/arch/x86/vmx_io.c xen/arch/x86/vmx_platform.c xen/common/memory.c xen/include/asm-x86/vmx.h xen/include/asm-x86/vmx_platform.h xen/include/public/io/ioreq.h
line diff
     1.1 --- a/linux-2.6-xen-sparse/mm/memory.c	Sat Sep 03 16:57:54 2005 +0000
     1.2 +++ b/linux-2.6-xen-sparse/mm/memory.c	Sat Sep 03 16:58:50 2005 +0000
     1.3 @@ -1367,20 +1367,15 @@ static int do_wp_page(struct mm_struct *
     1.4  	struct page *old_page, *new_page;
     1.5  	unsigned long pfn = pte_pfn(pte);
     1.6  	pte_t entry;
     1.7 +	struct page invalid_page;
     1.8  
     1.9  	if (unlikely(!pfn_valid(pfn))) {
    1.10 -		/*
    1.11 -		 * This should really halt the system so it can be debugged or
    1.12 -		 * at least the kernel stops what it's doing before it corrupts
    1.13 -		 * data, but for the moment just pretend this is OOM.
    1.14 -		 */
    1.15 -		pte_unmap(page_table);
    1.16 -		printk(KERN_ERR "do_wp_page: bogus page at address %08lx\n",
    1.17 -				address);
    1.18 -		spin_unlock(&mm->page_table_lock);
    1.19 -		return VM_FAULT_OOM;
    1.20 +		/* This can happen with /dev/mem (PROT_WRITE, MAP_PRIVATE). */
    1.21 +		invalid_page.flags = (1<<PG_reserved) | (1<<PG_locked);
    1.22 +		old_page = &invalid_page;
    1.23 +	} else {
    1.24 +		old_page = pfn_to_page(pfn);
    1.25  	}
    1.26 -	old_page = pfn_to_page(pfn);
    1.27  
    1.28  	if (!TestSetPageLocked(old_page)) {
    1.29  		int reuse = can_share_swap_page(old_page);
    1.30 @@ -1416,7 +1411,13 @@ static int do_wp_page(struct mm_struct *
    1.31  		new_page = alloc_page_vma(GFP_HIGHUSER, vma, address);
    1.32  		if (!new_page)
    1.33  			goto no_new_page;
    1.34 -		copy_user_highpage(new_page, old_page, address);
    1.35 +		if (old_page == &invalid_page) {
    1.36 +			char *vto = kmap_atomic(new_page, KM_USER1);
    1.37 +			copy_page(vto, (void *)(address & PAGE_MASK));
    1.38 +			kunmap_atomic(vto, KM_USER1);
    1.39 +		} else {
    1.40 +			copy_user_highpage(new_page, old_page, address);
    1.41 +		}
    1.42  	}
    1.43  	/*
    1.44  	 * Re-check the pte - we dropped the lock
     2.1 --- a/tools/firmware/rombios/rombios.c	Sat Sep 03 16:57:54 2005 +0000
     2.2 +++ b/tools/firmware/rombios/rombios.c	Sat Sep 03 16:58:50 2005 +0000
     2.3 @@ -31,7 +31,7 @@
     2.4  
     2.5  // Xen full virtualization does not handle unaligned IO with page crossing.
     2.6  // Disable 32-bit PIO as a workaround.
     2.7 -#define NO_PIO32
     2.8 +#undef NO_PIO32
     2.9  
    2.10  
    2.11  // ROM BIOS compatability entry points:
     3.1 --- a/tools/firmware/vmxassist/Makefile	Sat Sep 03 16:57:54 2005 +0000
     3.2 +++ b/tools/firmware/vmxassist/Makefile	Sat Sep 03 16:58:50 2005 +0000
     3.3 @@ -24,7 +24,7 @@ include $(XEN_ROOT)/tools/Rules.mk
     3.4  # The emulator code lives in ROM space
     3.5  TEXTADDR=0x000D0000
     3.6  
     3.7 -DEFINES=-DDEBUG -DENABLE_VME -DTEXTADDR=${TEXTADDR}
     3.8 +DEFINES=-DDEBUG -DTEXTADDR=${TEXTADDR}
     3.9  XENINC=-I$(XEN_ROOT)/xen/include -I$(XEN_ROOT)/tools/libxc
    3.10  #DEFINES=-DDEBUG -DTEST -DTEXTADDR=${TEXTADDR}
    3.11  #XENINC=-I/home/leendert/xen/xeno-unstable.bk/xen/include
     4.1 --- a/tools/firmware/vmxassist/TODO	Sat Sep 03 16:57:54 2005 +0000
     4.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.3 @@ -1,8 +0,0 @@
     4.4 -
     4.5 -- Use the VME extensions (interrupt handling)
     4.6 -
     4.7 -- Use E820 map in vmxassist instead of cmos hack
     4.8 -
     4.9 -- Add ACPI support (Nitin's patch)
    4.10 -
    4.11 -
     5.1 --- a/tools/firmware/vmxassist/setup.c	Sat Sep 03 16:57:54 2005 +0000
     5.2 +++ b/tools/firmware/vmxassist/setup.c	Sat Sep 03 16:58:50 2005 +0000
     5.3 @@ -353,7 +353,7 @@ main()
     5.4  #endif
     5.5  	setup_gdt();
     5.6  	setup_idt();
     5.7 -#ifdef	ENABLE_VME
     5.8 +#ifndef	TEST
     5.9  	set_cr4(get_cr4() | CR4_VME); 
    5.10  #endif
    5.11  	setup_ctx();
     6.1 --- a/tools/firmware/vmxassist/vm86.c	Sat Sep 03 16:57:54 2005 +0000
     6.2 +++ b/tools/firmware/vmxassist/vm86.c	Sat Sep 03 16:58:50 2005 +0000
     6.3 @@ -465,8 +465,7 @@ movcr(struct regs *regs, unsigned prefix
     6.4   * Emulate a segment load in protected mode
     6.5   */
     6.6  int
     6.7 -load_seg(unsigned long sel, unsigned long *base, unsigned long *limit,
     6.8 -						union vmcs_arbytes *arbytes)
     6.9 +load_seg(unsigned long sel, u32 *base, u32 *limit, union vmcs_arbytes *arbytes)
    6.10  {
    6.11  	unsigned long long entry;
    6.12  
     7.1 --- a/tools/firmware/vmxassist/vmxloader.c	Sat Sep 03 16:57:54 2005 +0000
     7.2 +++ b/tools/firmware/vmxassist/vmxloader.c	Sat Sep 03 16:58:50 2005 +0000
     7.3 @@ -110,8 +110,8 @@ main()
     7.4  	}
     7.5  #ifdef _ACPI_
     7.6  	puts("Loading ACPI ...\n");
     7.7 -    if (ACPI_PHYSICAL_ADDRESS+sizeof(acpi) <= 0xF0000 ){
     7.8 -        /* make sure acpi table does not overlap rombios
     7.9 +	if (ACPI_PHYSICAL_ADDRESS+sizeof(acpi) <= 0xF0000 ){
    7.10 +		/* make sure acpi table does not overlap rombios
    7.11   		 * currently acpi less than 8K will be OK.
    7.12  		 */
    7.13  		 memcpy((void *)ACPI_PHYSICAL_ADDRESS, acpi, sizeof(acpi));
    7.14 @@ -122,5 +122,6 @@ main()
    7.15  	memcpy((void *)TEXTADDR, vmxassist, sizeof(vmxassist));
    7.16  	puts("Go ...\n");
    7.17  	((void (*)())TEXTADDR)();
    7.18 +	return 0;
    7.19  }
    7.20  
     8.1 --- a/tools/ioemu/exec.c	Sat Sep 03 16:57:54 2005 +0000
     8.2 +++ b/tools/ioemu/exec.c	Sat Sep 03 16:58:50 2005 +0000
     8.3 @@ -142,6 +142,10 @@ void cpu_set_log(int log_flags)
     8.4  #else
     8.5          setvbuf(logfile, NULL, _IOLBF, 0);
     8.6  #endif
     8.7 +/*
     8.8 +    	stdout = logfile;
     8.9 +    	stderr = logfile;
    8.10 +*/
    8.11      }
    8.12  }
    8.13  
    8.14 @@ -386,9 +390,6 @@ void cpu_physical_memory_rw(target_phys_
    8.15                      io_mem_write[io_index][1](io_mem_opaque[io_index], addr, val);
    8.16                      l = 2;
    8.17                  } else {
    8.18 -                    if (l!=1){
    8.19 -                        fprintf(logfile, "ERROR 8 bit mmio\n");
    8.20 -                    }
    8.21                      /* 8 bit access */
    8.22                      val = ldub_raw(buf);
    8.23                      io_mem_write[io_index][0](io_mem_opaque[io_index], addr, val);
     9.1 --- a/tools/ioemu/hw/pcnet.c	Sat Sep 03 16:57:54 2005 +0000
     9.2 +++ b/tools/ioemu/hw/pcnet.c	Sat Sep 03 16:58:50 2005 +0000
     9.3 @@ -569,6 +569,10 @@ static void pcnet_transmit(PCNetState *s
     9.4              cpu_physical_memory_read(PHYSADDR(s, tmd.tmd0.tbadr),
     9.5                      s->buffer + s->xmit_pos, 4096 - tmd.tmd1.bcnt);
     9.6              s->xmit_pos += 4096 - tmd.tmd1.bcnt;
     9.7 +
     9.8 +	    tmd.tmd1.own = 0;
     9.9 +	    TMDSTORE(&tmd, PHYSADDR(s,CSR_CXDA(s)));
    9.10 +
    9.11  #ifdef PCNET_DEBUG
    9.12              printf("pcnet_transmit size=%d\n", s->xmit_pos);
    9.13  #endif            
    9.14 @@ -580,10 +584,10 @@ static void pcnet_transmit(PCNetState *s
    9.15              s->csr[0] &= ~0x0008;   /* clear TDMD */
    9.16              s->csr[4] |= 0x0004;    /* set TXSTRT */
    9.17              s->xmit_pos = -1;
    9.18 -        }
    9.19 -
    9.20 -        tmd.tmd1.own = 0;
    9.21 -        TMDSTORE(&tmd, PHYSADDR(s,CSR_CXDA(s)));
    9.22 +        } else {
    9.23 +	    tmd.tmd1.own = 0;
    9.24 +	    TMDSTORE(&tmd, PHYSADDR(s,CSR_CXDA(s)));
    9.25 +	}
    9.26          if (!CSR_TOKINTD(s) || (CSR_LTINTEN(s) && tmd.tmd1.ltint))
    9.27              s->csr[0] |= 0x0200;    /* set TINT */
    9.28  
    10.1 --- a/tools/ioemu/target-i386-dm/helper2.c	Sat Sep 03 16:57:54 2005 +0000
    10.2 +++ b/tools/ioemu/target-i386-dm/helper2.c	Sat Sep 03 16:58:50 2005 +0000
    10.3 @@ -169,133 +169,217 @@ ioreq_t* cpu_get_ioreq(void)
    10.4  unsigned long
    10.5  do_inp(CPUState *env, unsigned long addr, unsigned long size)
    10.6  {
    10.7 -  switch(size) {
    10.8 -      case 1:
    10.9 -        return cpu_inb(env, addr);
   10.10 -      case 2:
   10.11 -        return cpu_inw(env, addr);
   10.12 -      case 4:
   10.13 -        return cpu_inl(env, addr);
   10.14 -      default:
   10.15 -	fprintf(logfile, "inp: bad size: %lx %lx\n", addr, size);
   10.16 -        exit(-1);
   10.17 -  }
   10.18 +	switch(size) {
   10.19 +	case 1:
   10.20 +		return cpu_inb(env, addr);
   10.21 +	case 2:
   10.22 +		return cpu_inw(env, addr);
   10.23 +	case 4:
   10.24 +		return cpu_inl(env, addr);
   10.25 +	default:
   10.26 +		fprintf(logfile, "inp: bad size: %lx %lx\n", addr, size);
   10.27 +		exit(-1);
   10.28 +	}
   10.29  }
   10.30  
   10.31  void
   10.32  do_outp(CPUState *env, unsigned long addr, unsigned long size, 
   10.33          unsigned long val)
   10.34  {
   10.35 -  switch(size) {
   10.36 -      case 1:
   10.37 -        return cpu_outb(env, addr, val);
   10.38 -      case 2:
   10.39 -        return cpu_outw(env, addr, val);
   10.40 -      case 4:
   10.41 -        return cpu_outl(env, addr, val);
   10.42 -      default:
   10.43 -	fprintf(logfile, "outp: bad size: %lx %lx\n", addr, size);
   10.44 -        exit(-1);
   10.45 -  }
   10.46 +	switch(size) {
   10.47 +	case 1:
   10.48 +		return cpu_outb(env, addr, val);
   10.49 +	case 2:
   10.50 +		return cpu_outw(env, addr, val);
   10.51 +	case 4:
   10.52 +		return cpu_outl(env, addr, val);
   10.53 +	default:
   10.54 +		fprintf(logfile, "outp: bad size: %lx %lx\n", addr, size);
   10.55 +		exit(-1);
   10.56 +	}
   10.57  }
   10.58  
   10.59  extern void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf, 
   10.60                                     int len, int is_write);
   10.61  
   10.62  static inline void
   10.63 -read_physical(target_phys_addr_t addr, unsigned long size, void *val)
   10.64 +read_physical(u64 addr, unsigned long size, void *val)
   10.65  {
   10.66 -        return cpu_physical_memory_rw(addr, val, size, 0);
   10.67 +        return cpu_physical_memory_rw((target_phys_addr_t)addr, val, size, 0);
   10.68  }
   10.69  
   10.70  static inline void
   10.71 -write_physical(target_phys_addr_t addr, unsigned long size, void *val)
   10.72 +write_physical(u64 addr, unsigned long size, void *val)
   10.73  {
   10.74 -        return cpu_physical_memory_rw(addr, val, size, 1);
   10.75 +        return cpu_physical_memory_rw((target_phys_addr_t)addr, val, size, 1);
   10.76  }
   10.77  
   10.78 -//send the ioreq to device model
   10.79 -void cpu_dispatch_ioreq(CPUState *env, ioreq_t *req)
   10.80 +void
   10.81 +cpu_ioreq_pio(CPUState *env, ioreq_t *req)
   10.82  {
   10.83 -	int i;
   10.84 -	int sign;
   10.85 -
   10.86 -	sign = (req->df) ? -1 : 1;
   10.87 +	int i, sign;
   10.88  
   10.89 -	if ((!req->pdata_valid) && (req->dir == IOREQ_WRITE)) {
   10.90 -		if (req->size != 4) {
   10.91 -			// Bochs expects higher bits to be 0
   10.92 -			req->u.data &= (1UL << (8 * req->size))-1;
   10.93 -		}
   10.94 -	}
   10.95 +	sign = req->df ? -1 : 1;
   10.96  
   10.97 -	if (req->port_mm == 0){//port io
   10.98 -		if(req->dir == IOREQ_READ){//read
   10.99 -			if (!req->pdata_valid) {
  10.100 -				req->u.data = do_inp(env, req->addr, req->size);
  10.101 -			} else {
  10.102 -				unsigned long tmp; 
  10.103 +	if (req->dir == IOREQ_READ) {
  10.104 +		if (!req->pdata_valid) {
  10.105 +			req->u.data = do_inp(env, req->addr, req->size);
  10.106 +		} else {
  10.107 +			unsigned long tmp; 
  10.108  
  10.109 -				for (i = 0; i < req->count; i++) {
  10.110 -					tmp = do_inp(env, req->addr, req->size);
  10.111 -					write_physical((target_phys_addr_t)req->u.pdata + (sign * i * req->size), 
  10.112 -						       req->size, &tmp);
  10.113 -				}
  10.114 +			for (i = 0; i < req->count; i++) {
  10.115 +				tmp = do_inp(env, req->addr, req->size);
  10.116 +				write_physical((target_phys_addr_t) req->u.pdata
  10.117 +						+ (sign * i * req->size), 
  10.118 +					req->size, &tmp);
  10.119  			}
  10.120 -		} else if(req->dir == IOREQ_WRITE) {
  10.121 -			if (!req->pdata_valid) {
  10.122 -				do_outp(env, req->addr, req->size, req->u.data);
  10.123 -			} else {
  10.124 -				for (i = 0; i < req->count; i++) {
  10.125 -					unsigned long tmp;
  10.126 -
  10.127 -					read_physical((target_phys_addr_t)req->u.pdata + (sign * i * req->size), req->size, 
  10.128 -						      &tmp);
  10.129 -					do_outp(env, req->addr, req->size, tmp);
  10.130 -				}
  10.131 -			}
  10.132 -			
  10.133  		}
  10.134 -	} else if (req->port_mm == 1){//memory map io
  10.135 +	} else if (req->dir == IOREQ_WRITE) {
  10.136  		if (!req->pdata_valid) {
  10.137 -			//handle stos
  10.138 -			if(req->dir == IOREQ_READ) { //read
  10.139 -				for (i = 0; i < req->count; i++) {
  10.140 -					read_physical((target_phys_addr_t)req->addr + (sign * i * req->size), req->size, &req->u.data);
  10.141 -				}
  10.142 -			} else if(req->dir == IOREQ_WRITE) { //write
  10.143 -				for (i = 0; i < req->count; i++) {
  10.144 -					write_physical((target_phys_addr_t)req->addr + (sign * i * req->size), req->size, &req->u.data);
  10.145 -				}
  10.146 -			}
  10.147 +			do_outp(env, req->addr, req->size, req->u.data);
  10.148  		} else {
  10.149 -			//handle movs
  10.150 -			unsigned long tmp;
  10.151 -			if (req->dir == IOREQ_READ) {
  10.152 -				for (i = 0; i < req->count; i++) {
  10.153 -					read_physical((target_phys_addr_t)req->addr + (sign * i * req->size), req->size, &tmp);
  10.154 -					write_physical((target_phys_addr_t)req->u.pdata + (sign * i * req->size), req->size, &tmp);
  10.155 -				}
  10.156 -			} else if (req->dir == IOREQ_WRITE) {
  10.157 -				for (i = 0; i < req->count; i++) {
  10.158 -					read_physical((target_phys_addr_t)req->u.pdata + (sign * i * req->size), req->size, &tmp);
  10.159 -					write_physical((target_phys_addr_t)req->addr + (sign * i * req->size), req->size, &tmp);
  10.160 -				}
  10.161 +			for (i = 0; i < req->count; i++) {
  10.162 +				unsigned long tmp;
  10.163 +
  10.164 +				read_physical((target_phys_addr_t) req->u.pdata
  10.165 +						+ (sign * i * req->size),
  10.166 +					req->size, &tmp);
  10.167 +				do_outp(env, req->addr, req->size, tmp);
  10.168  			}
  10.169  		}
  10.170  	}
  10.171 -        /* No state change if state = STATE_IORESP_HOOK */
  10.172 -        if (req->state == STATE_IOREQ_INPROCESS)
  10.173 -                req->state = STATE_IORESP_READY;
  10.174 -	env->send_event = 1;
  10.175 +}
  10.176 +
  10.177 +void
  10.178 +cpu_ioreq_move(CPUState *env, ioreq_t *req)
  10.179 +{
  10.180 +	int i, sign;
  10.181 +
  10.182 +	sign = req->df ? -1 : 1;
  10.183 +
  10.184 +	if (!req->pdata_valid) {
  10.185 +		if (req->dir == IOREQ_READ) {
  10.186 +			for (i = 0; i < req->count; i++) {
  10.187 +				read_physical(req->addr
  10.188 +						+ (sign * i * req->size),
  10.189 +					req->size, &req->u.data);
  10.190 +			}
  10.191 +		} else if (req->dir == IOREQ_WRITE) {
  10.192 +			for (i = 0; i < req->count; i++) {
  10.193 +				write_physical(req->addr
  10.194 +						+ (sign * i * req->size),
  10.195 +					req->size, &req->u.data);
  10.196 +			}
  10.197 +		}
  10.198 +	} else {
  10.199 +		unsigned long tmp;
  10.200 +
  10.201 +		if (req->dir == IOREQ_READ) {
  10.202 +			for (i = 0; i < req->count; i++) {
  10.203 +				read_physical(req->addr
  10.204 +						+ (sign * i * req->size),
  10.205 +					req->size, &tmp);
  10.206 +				write_physical((target_phys_addr_t )req->u.pdata
  10.207 +						+ (sign * i * req->size),
  10.208 +					req->size, &tmp);
  10.209 +			}
  10.210 +		} else if (req->dir == IOREQ_WRITE) {
  10.211 +			for (i = 0; i < req->count; i++) {
  10.212 +				read_physical((target_phys_addr_t) req->u.pdata
  10.213 +						+ (sign * i * req->size),
  10.214 +					req->size, &tmp);
  10.215 +				write_physical(req->addr
  10.216 +						+ (sign * i * req->size),
  10.217 +					req->size, &tmp);
  10.218 +			}
  10.219 +		}
  10.220 +	}
  10.221 +}
  10.222 +
  10.223 +void
  10.224 +cpu_ioreq_and(CPUState *env, ioreq_t *req)
  10.225 +{
  10.226 +	unsigned long tmp1, tmp2;
  10.227 +
  10.228 +	if (req->pdata_valid != 0)
  10.229 +		hw_error("expected scalar value");
  10.230 +
  10.231 +	read_physical(req->addr, req->size, &tmp1);
  10.232 +	if (req->dir == IOREQ_WRITE) {
  10.233 +		tmp2 = tmp1 & (unsigned long) req->u.data;
  10.234 +		write_physical(req->addr, req->size, &tmp2);
  10.235 +	}
  10.236 +	req->u.data = tmp1;
  10.237 +}
  10.238 +
  10.239 +void
  10.240 +cpu_ioreq_or(CPUState *env, ioreq_t *req)
  10.241 +{
  10.242 +	unsigned long tmp1, tmp2;
  10.243 +
  10.244 +	if (req->pdata_valid != 0)
  10.245 +		hw_error("expected scalar value");
  10.246 +
  10.247 +	read_physical(req->addr, req->size, &tmp1);
  10.248 +	if (req->dir == IOREQ_WRITE) {
  10.249 +		tmp2 = tmp1 | (unsigned long) req->u.data;
  10.250 +		write_physical(req->addr, req->size, &tmp2);
  10.251 +	}
  10.252 +	req->u.data = tmp1;
  10.253 +}
  10.254 +
  10.255 +void
  10.256 +cpu_ioreq_xor(CPUState *env, ioreq_t *req)
  10.257 +{
  10.258 +	unsigned long tmp1, tmp2;
  10.259 +
  10.260 +	if (req->pdata_valid != 0)
  10.261 +		hw_error("expected scalar value");
  10.262 +
  10.263 +	read_physical(req->addr, req->size, &tmp1);
  10.264 +	if (req->dir == IOREQ_WRITE) {
  10.265 +		tmp2 = tmp1 ^ (unsigned long) req->u.data;
  10.266 +		write_physical(req->addr, req->size, &tmp2);
  10.267 +	}
  10.268 +	req->u.data = tmp1;
  10.269  }
  10.270  
  10.271  void
  10.272  cpu_handle_ioreq(CPUState *env)
  10.273  {
  10.274  	ioreq_t *req = cpu_get_ioreq();
  10.275 -	if (req)
  10.276 -		cpu_dispatch_ioreq(env, req);
  10.277 +
  10.278 +	if (req) {
  10.279 +		if ((!req->pdata_valid) && (req->dir == IOREQ_WRITE)) {
  10.280 +			if (req->size != 4)
  10.281 +				req->u.data &= (1UL << (8 * req->size))-1;
  10.282 +		}
  10.283 +
  10.284 +		switch (req->type) {
  10.285 +		case IOREQ_TYPE_PIO:
  10.286 +			cpu_ioreq_pio(env, req);
  10.287 +			break;
  10.288 +		case IOREQ_TYPE_COPY:
  10.289 +			cpu_ioreq_move(env, req);
  10.290 +			break;
  10.291 +		case IOREQ_TYPE_AND:
  10.292 +			cpu_ioreq_and(env, req);
  10.293 +			break;
  10.294 +		case IOREQ_TYPE_OR:
  10.295 +			cpu_ioreq_or(env, req);
  10.296 +			break;
  10.297 +		case IOREQ_TYPE_XOR:
  10.298 +			cpu_ioreq_xor(env, req);
  10.299 +			break;
  10.300 +		default:
  10.301 +			hw_error("Invalid ioreq type 0x%x", req->type);
  10.302 +		}
  10.303 +
  10.304 +		/* No state change if state = STATE_IORESP_HOOK */
  10.305 +		if (req->state == STATE_IOREQ_INPROCESS)
  10.306 +			req->state = STATE_IORESP_READY;
  10.307 +		env->send_event = 1;
  10.308 +	}
  10.309  }
  10.310  
  10.311  void
  10.312 @@ -321,7 +405,7 @@ do_interrupt(CPUState *env, int vector)
  10.313  
  10.314  	// Send a message on the event channel. Add the vector to the shared mem
  10.315  	// page.
  10.316 -	intr = &(shared_page->sp_global.pic_intr[0]);
  10.317 +	intr = (unsigned long *) &(shared_page->sp_global.pic_intr[0]);
  10.318  	atomic_set_bit(vector, intr);
  10.319          if (loglevel & CPU_LOG_INT)
  10.320                  fprintf(logfile, "injecting vector: %x\n", vector);
    11.1 --- a/tools/ioemu/vl.c	Sat Sep 03 16:57:54 2005 +0000
    11.2 +++ b/tools/ioemu/vl.c	Sat Sep 03 16:58:50 2005 +0000
    11.3 @@ -413,6 +413,11 @@ void hw_error(const char *fmt, ...)
    11.4      fprintf(stderr, "qemu: hardware error: ");
    11.5      vfprintf(stderr, fmt, ap);
    11.6      fprintf(stderr, "\n");
    11.7 +    if (logfile) {
    11.8 +	fprintf(logfile, "qemu: hardware error: ");
    11.9 +	vfprintf(logfile, fmt, ap);
   11.10 +	fprintf(logfile, "\n");
   11.11 +    }
   11.12      va_end(ap);
   11.13      abort();
   11.14  }
    12.1 --- a/tools/libxc/xc_linux_save.c	Sat Sep 03 16:57:54 2005 +0000
    12.2 +++ b/tools/libxc/xc_linux_save.c	Sat Sep 03 16:58:50 2005 +0000
    12.3 @@ -21,6 +21,24 @@
    12.4  
    12.5  #define MAX_MBIT_RATE 500
    12.6  
    12.7 +
    12.8 +/*
    12.9 +** Default values for important tuning parameters. Can override by passing
   12.10 +** non-zero replacement values to xc_linux_save().  
   12.11 +**
   12.12 +** XXX SMH: should consider if want to be able to override MAX_MBIT_RATE too. 
   12.13 +** 
   12.14 +*/
   12.15 +#define DEF_MAX_ITERS   29   /* limit us to 30 times round loop */ 
   12.16 +#define DEF_MAX_FACTOR   3   /* never send more than 3x nr_pfns */
   12.17 +
   12.18 +
   12.19 +
   12.20 +/* Flags to control behaviour of xc_linux_save */
   12.21 +#define XCFLAGS_LIVE      1
   12.22 +#define XCFLAGS_DEBUG     2
   12.23 +
   12.24 +
   12.25  #define DEBUG 0
   12.26  
   12.27  #if 1
   12.28 @@ -320,18 +338,18 @@ static int suspend_and_state(int xc_hand
   12.29                               xc_dominfo_t *info,
   12.30                               vcpu_guest_context_t *ctxt)
   12.31  {
   12.32 -    int i=0;
   12.33 +    int i = 0;
   12.34      char ans[30];
   12.35  
   12.36      printf("suspend\n");
   12.37      fflush(stdout);
   12.38      if (fgets(ans, sizeof(ans), stdin) == NULL) {
   12.39 -	ERR("failed reading suspend reply");
   12.40 -	return -1;
   12.41 +        ERR("failed reading suspend reply");
   12.42 +        return -1;
   12.43      }
   12.44      if (strncmp(ans, "done\n", 5)) {
   12.45 -	ERR("suspend reply incorrect: %s", ans);
   12.46 -	return -1;
   12.47 +        ERR("suspend reply incorrect: %s", ans);
   12.48 +        return -1;
   12.49      }
   12.50  
   12.51  retry:
   12.52 @@ -377,20 +395,17 @@ retry:
   12.53      return -1;
   12.54  }
   12.55  
   12.56 -int xc_linux_save(int xc_handle, int io_fd, u32 dom)
   12.57 +int xc_linux_save(int xc_handle, int io_fd, u32 dom, u32 max_iters, 
   12.58 +                  u32 max_factor, u32 flags)
   12.59  {
   12.60      xc_dominfo_t info;
   12.61  
   12.62      int rc = 1, i, j, k, last_iter, iter = 0;
   12.63      unsigned long mfn;
   12.64 -    int live =  0; // (ioctxt->flags & XCFLAGS_LIVE);
   12.65 -    int debug = 0; // (ioctxt->flags & XCFLAGS_DEBUG);
   12.66 +    int live  = (flags & XCFLAGS_LIVE); 
   12.67 +    int debug = (flags & XCFLAGS_DEBUG); 
   12.68      int sent_last_iter, skip_this_iter;
   12.69  
   12.70 -    /* Important tuning parameters */
   12.71 -    int max_iters  = 29; /* limit us to 30 times round loop */
   12.72 -    int max_factor = 3;  /* never send more than 3x nr_pfns */
   12.73 -
   12.74      /* The new domain's shared-info frame number. */
   12.75      unsigned long shared_info_frame;
   12.76      
   12.77 @@ -442,8 +457,16 @@ int xc_linux_save(int xc_handle, int io_
   12.78  
   12.79      MBIT_RATE = START_MBIT_RATE;
   12.80  
   12.81 -    DPRINTF("xc_linux_save start %d\n", dom);
   12.82 -    
   12.83 +
   12.84 +    /* If no explicit control parameters given, use defaults */
   12.85 +    if(!max_iters) 
   12.86 +        max_iters = DEF_MAX_ITERS; 
   12.87 +    if(!max_factor) 
   12.88 +        max_factor = DEF_MAX_FACTOR; 
   12.89 +
   12.90 +
   12.91 +    DPRINTF("xc_linux_save start DOM%u live=%s\n", dom, live?"true":"false"); 
   12.92 +
   12.93      if (mlock(&ctxt, sizeof(ctxt))) {
   12.94          ERR("Unable to mlock ctxt");
   12.95          return 1;
    13.1 --- a/tools/libxc/xenguest.h	Sat Sep 03 16:57:54 2005 +0000
    13.2 +++ b/tools/libxc/xenguest.h	Sat Sep 03 16:58:50 2005 +0000
    13.3 @@ -6,13 +6,12 @@
    13.4   * Copyright (c) 2003-2004, K A Fraser.
    13.5   */
    13.6  
    13.7 -#ifndef XENBUILD_H
    13.8 -#define XENBUILD_H
    13.9 +#ifndef XENGUEST_H
   13.10 +#define XENGUEST_H
   13.11  
   13.12 -#define XCFLAGS_VERBOSE   1
   13.13 -#define XCFLAGS_LIVE      2
   13.14 -#define XCFLAGS_DEBUG     4
   13.15 -#define XCFLAGS_CONFIGURE 8
   13.16 +#define XCFLAGS_LIVE      1
   13.17 +#define XCFLAGS_DEBUG     2
   13.18 +
   13.19  
   13.20  /**
   13.21   * This function will save a domain running Linux.
   13.22 @@ -22,7 +21,8 @@
   13.23   * @parm dom the id of the domain
   13.24   * @return 0 on success, -1 on failure
   13.25   */
   13.26 -int xc_linux_save(int xc_handle, int fd, uint32_t dom);
   13.27 +int xc_linux_save(int xc_handle, int fd, uint32_t dom, uint32_t max_iters, 
   13.28 +                  uint32_t max_factor, uint32_t flags /* XCFLAGS_xxx */);
   13.29  
   13.30  /**
   13.31   * This function will restore a saved domain running Linux.
   13.32 @@ -35,8 +35,9 @@ int xc_linux_save(int xc_handle, int fd,
   13.33   * @parm store_mfn returned with the mfn of the store page
   13.34   * @return 0 on success, -1 on failure
   13.35   */
   13.36 -int xc_linux_restore(int xc_handle, int io_fd, uint32_t dom, unsigned long nr_pfns,
   13.37 -		     unsigned int store_evtchn, unsigned long *store_mfn);
   13.38 +int xc_linux_restore(int xc_handle, int io_fd, uint32_t dom, 
   13.39 +                     unsigned long nr_pfns, unsigned int store_evtchn, 
   13.40 +                     unsigned long *store_mfn);
   13.41  
   13.42  int xc_linux_build(int xc_handle,
   13.43                     uint32_t domid,
   13.44 @@ -65,4 +66,4 @@ int xc_vmx_build(int xc_handle,
   13.45                   unsigned int store_evtchn,
   13.46                   unsigned long *store_mfn);
   13.47  
   13.48 -#endif
   13.49 +#endif // XENGUEST_H
    14.1 --- a/tools/python/xen/xend/XendCheckpoint.py	Sat Sep 03 16:57:54 2005 +0000
    14.2 +++ b/tools/python/xen/xend/XendCheckpoint.py	Sat Sep 03 16:58:50 2005 +0000
    14.3 @@ -34,7 +34,7 @@ def read_exact(fd, size, errmsg):
    14.4          raise XendError(errmsg)
    14.5      return buf
    14.6  
    14.7 -def save(xd, fd, dominfo):
    14.8 +def save(xd, fd, dominfo, live):
    14.9      write_exact(fd, SIGNATURE, "could not write guest state file: signature")
   14.10  
   14.11      config = sxp.to_string(dominfo.sxpr())
   14.12 @@ -42,8 +42,13 @@ def save(xd, fd, dominfo):
   14.13                  "could not write guest state file: config len")
   14.14      write_exact(fd, config, "could not write guest state file: config")
   14.15  
   14.16 +    # xc_save takes three customization parameters: maxit, max_f, and flags
   14.17 +    # the last controls whether or not save is 'live', while the first two
   14.18 +    # further customize behaviour when 'live' save is enabled. Passing "0"
   14.19 +    # simply uses the defaults compiled into libxenguest; see the comments 
   14.20 +    # and/or code in xc_linux_save() for more information. 
   14.21      cmd = [PATH_XC_SAVE, str(xc.handle()), str(fd),
   14.22 -           str(dominfo.id)]
   14.23 +           str(dominfo.id), "0", "0", str(live) ]
   14.24      log.info("[xc_save] " + join(cmd))
   14.25      child = xPopen3(cmd, True, -1, [fd, xc.handle()])
   14.26      
    15.1 --- a/tools/python/xen/xend/XendDomain.py	Sat Sep 03 16:57:54 2005 +0000
    15.2 +++ b/tools/python/xen/xend/XendDomain.py	Sat Sep 03 16:58:50 2005 +0000
    15.3 @@ -542,7 +542,7 @@ class XendDomain:
    15.4              dominfo.name = "tmp-" + dominfo.name
    15.5  
    15.6          try:
    15.7 -            XendCheckpoint.save(self, sock.fileno(), dominfo)
    15.8 +            XendCheckpoint.save(self, sock.fileno(), dominfo, live)
    15.9          except:
   15.10              if dst == "localhost":
   15.11                  dominfo.name = string.replace(dominfo.name, "tmp-", "", 1)
   15.12 @@ -563,7 +563,8 @@ class XendDomain:
   15.13  
   15.14              fd = os.open(dst, os.O_WRONLY | os.O_CREAT | os.O_TRUNC)
   15.15  
   15.16 -            return XendCheckpoint.save(self, fd, dominfo)
   15.17 +            # For now we don't support 'live checkpoint' 
   15.18 +            return XendCheckpoint.save(self, fd, dominfo, False)
   15.19  
   15.20          except OSError, ex:
   15.21              raise XendError("can't write guest state file %s: %s" %
    16.1 --- a/tools/xcutils/xc_save.c	Sat Sep 03 16:57:54 2005 +0000
    16.2 +++ b/tools/xcutils/xc_save.c	Sat Sep 03 16:58:50 2005 +0000
    16.3 @@ -17,14 +17,17 @@
    16.4  int
    16.5  main(int argc, char **argv)
    16.6  {
    16.7 -    unsigned int xc_fd, io_fd, domid;
    16.8 +    unsigned int xc_fd, io_fd, domid, maxit, max_f, flags; 
    16.9  
   16.10 -    if (argc != 4)
   16.11 -	errx(1, "usage: %s xcfd iofd domid", argv[0]);
   16.12 +    if (argc != 7)
   16.13 +	errx(1, "usage: %s xcfd iofd domid maxit maxf flags", argv[0]);
   16.14  
   16.15      xc_fd = atoi(argv[1]);
   16.16      io_fd = atoi(argv[2]);
   16.17      domid = atoi(argv[3]);
   16.18 +    maxit = atoi(argv[4]);
   16.19 +    max_f = atoi(argv[5]);
   16.20 +    flags = atoi(argv[6]);
   16.21  
   16.22 -    return xc_linux_save(xc_fd, io_fd, domid);
   16.23 +    return xc_linux_save(xc_fd, io_fd, domid, maxit, max_f, flags);
   16.24  }
    17.1 --- a/xen/arch/x86/shadow.c	Sat Sep 03 16:57:54 2005 +0000
    17.2 +++ b/xen/arch/x86/shadow.c	Sat Sep 03 16:58:50 2005 +0000
    17.3 @@ -531,7 +531,7 @@ static void shadow_map_l1_into_current_l
    17.4      int i, init_table = 0;
    17.5  
    17.6      __guest_get_l2e(v, va, &gl2e);
    17.7 -    ASSERT(l2e_get_flags(gl2e) & _PAGE_PRESENT);
    17.8 +    ASSERT(guest_l2e_get_flags(gl2e) & _PAGE_PRESENT);
    17.9      gl1pfn = l2e_get_pfn(gl2e);
   17.10  
   17.11      if ( !(sl1mfn = __shadow_status(d, gl1pfn, PGT_l1_shadow)) )
   17.12 @@ -1664,7 +1664,7 @@ static inline int l1pte_write_fault(
   17.13          return 0;
   17.14      }
   17.15  
   17.16 -    ASSERT(l1e_get_flags(gpte) & _PAGE_RW);
   17.17 +    ASSERT(guest_l1e_get_flags(gpte) & _PAGE_RW);
   17.18      guest_l1e_add_flags(gpte, _PAGE_DIRTY | _PAGE_ACCESSED);
   17.19      spte = l1e_from_pfn(gmfn, guest_l1e_get_flags(gpte) & ~_PAGE_GLOBAL);
   17.20  
    18.1 --- a/xen/arch/x86/vmx.c	Sat Sep 03 16:57:54 2005 +0000
    18.2 +++ b/xen/arch/x86/vmx.c	Sat Sep 03 16:58:50 2005 +0000
    18.3 @@ -602,16 +602,67 @@ static int check_for_null_selector(unsig
    18.4      return 0;
    18.5  }
    18.6  
    18.7 +void send_pio_req(struct cpu_user_regs *regs, unsigned long port,
    18.8 +       unsigned long count, int size, long value, int dir, int pvalid)
    18.9 +{
   18.10 +    struct vcpu *v = current;
   18.11 +    vcpu_iodata_t *vio;
   18.12 +    ioreq_t *p;
   18.13 +
   18.14 +    vio = get_vio(v->domain, v->vcpu_id);
   18.15 +    if (vio == NULL) {
   18.16 +        printk("bad shared page: %lx\n", (unsigned long) vio);
   18.17 +        domain_crash_synchronous();
   18.18 +    }
   18.19 +
   18.20 +    if (test_bit(ARCH_VMX_IO_WAIT, &v->arch.arch_vmx.flags)) {
   18.21 +       printf("VMX I/O has not yet completed\n");
   18.22 +       domain_crash_synchronous();
   18.23 +    }
   18.24 +    set_bit(ARCH_VMX_IO_WAIT, &v->arch.arch_vmx.flags);
   18.25 +
   18.26 +    p = &vio->vp_ioreq;
   18.27 +    p->dir = dir;
   18.28 +    p->pdata_valid = pvalid;
   18.29 +
   18.30 +    p->type = IOREQ_TYPE_PIO;
   18.31 +    p->size = size;
   18.32 +    p->addr = port;
   18.33 +    p->count = count;
   18.34 +    p->df = regs->eflags & EF_DF ? 1 : 0;
   18.35 +
   18.36 +    if (pvalid) {
   18.37 +        if (vmx_paging_enabled(current))
   18.38 +            p->u.pdata = (void *) gva_to_gpa(value);
   18.39 +        else
   18.40 +            p->u.pdata = (void *) value; /* guest VA == guest PA */
   18.41 +    } else
   18.42 +        p->u.data = value;
   18.43 +
   18.44 +    p->state = STATE_IOREQ_READY;
   18.45 +
   18.46 +    if (vmx_portio_intercept(p)) {
   18.47 +        /* no blocking & no evtchn notification */
   18.48 +        clear_bit(ARCH_VMX_IO_WAIT, &v->arch.arch_vmx.flags);
   18.49 +        return;
   18.50 +    }
   18.51 +
   18.52 +    evtchn_send(iopacket_port(v->domain));
   18.53 +    vmx_wait_io();
   18.54 +}
   18.55 +
   18.56  static void vmx_io_instruction(struct cpu_user_regs *regs, 
   18.57                     unsigned long exit_qualification, unsigned long inst_len) 
   18.58  {
   18.59 -    struct vcpu *d = current;
   18.60 -    vcpu_iodata_t *vio;
   18.61 -    ioreq_t *p;
   18.62 -    unsigned long addr;
   18.63 +    struct mi_per_cpu_info *mpcip;
   18.64      unsigned long eip, cs, eflags;
   18.65 +    unsigned long port, size, dir;
   18.66      int vm86;
   18.67  
   18.68 +    mpcip = &current->domain->arch.vmx_platform.mpci;
   18.69 +    mpcip->instr = INSTR_PIO;
   18.70 +    mpcip->flags = 0;
   18.71 +
   18.72      __vmread(GUEST_RIP, &eip);
   18.73      __vmread(GUEST_CS_SELECTOR, &cs);
   18.74      __vmread(GUEST_RFLAGS, &eflags);
   18.75 @@ -623,105 +674,87 @@ static void vmx_io_instruction(struct cp
   18.76                  vm86, cs, eip, exit_qualification);
   18.77  
   18.78      if (test_bit(6, &exit_qualification))
   18.79 -        addr = (exit_qualification >> 16) & (0xffff);
   18.80 +        port = (exit_qualification >> 16) & 0xFFFF;
   18.81      else
   18.82 -        addr = regs->edx & 0xffff;
   18.83 -    TRACE_VMEXIT (2,addr);
   18.84 -
   18.85 -    vio = get_vio(d->domain, d->vcpu_id);
   18.86 -    if (vio == 0) {
   18.87 -        printk("bad shared page: %lx", (unsigned long) vio);
   18.88 -        domain_crash_synchronous(); 
   18.89 -    }
   18.90 -    p = &vio->vp_ioreq;
   18.91 -    p->dir = test_bit(3, &exit_qualification); /* direction */
   18.92 -
   18.93 -    p->pdata_valid = 0;
   18.94 -    p->count = 1;
   18.95 -    p->size = (exit_qualification & 7) + 1;
   18.96 +        port = regs->edx & 0xffff;
   18.97 +    TRACE_VMEXIT(2, port);
   18.98 +    size = (exit_qualification & 7) + 1;
   18.99 +    dir = test_bit(3, &exit_qualification); /* direction */
  18.100  
  18.101      if (test_bit(4, &exit_qualification)) { /* string instruction */
  18.102 -	unsigned long laddr;
  18.103 +	unsigned long addr, count = 1;
  18.104 +	int sign = regs->eflags & EF_DF ? -1 : 1;
  18.105  
  18.106 -	__vmread(GUEST_LINEAR_ADDRESS, &laddr);
  18.107 +	__vmread(GUEST_LINEAR_ADDRESS, &addr);
  18.108 +
  18.109          /*
  18.110           * In protected mode, guest linear address is invalid if the
  18.111           * selector is null.
  18.112           */
  18.113 -        if (!vm86 && check_for_null_selector(eip)) {
  18.114 -            laddr = (p->dir == IOREQ_WRITE) ? regs->esi : regs->edi;
  18.115 -        }
  18.116 -        p->pdata_valid = 1;
  18.117 -
  18.118 -        p->u.data = laddr;
  18.119 -        if (vmx_paging_enabled(d))
  18.120 -                p->u.pdata = (void *) gva_to_gpa(p->u.data);
  18.121 -        p->df = (eflags & X86_EFLAGS_DF) ? 1 : 0;
  18.122 -
  18.123 -        if (test_bit(5, &exit_qualification)) /* "rep" prefix */
  18.124 -            p->count = vm86 ? regs->ecx & 0xFFFF : regs->ecx;
  18.125 +        if (!vm86 && check_for_null_selector(eip))
  18.126 +            addr = dir == IOREQ_WRITE ? regs->esi : regs->edi;
  18.127  
  18.128 -        /*
  18.129 -         * Split up string I/O operations that cross page boundaries. Don't
  18.130 -         * advance %eip so that "rep insb" will restart at the next page.
  18.131 -         */
  18.132 -        if ((p->u.data & PAGE_MASK) != 
  18.133 -		((p->u.data + p->count * p->size - 1) & PAGE_MASK)) {
  18.134 -	    VMX_DBG_LOG(DBG_LEVEL_2,
  18.135 -		"String I/O crosses page boundary (cs:eip=0x%lx:0x%lx)\n",
  18.136 -		cs, eip);
  18.137 -            if (p->u.data & (p->size - 1)) {
  18.138 -		printf("Unaligned string I/O operation (cs:eip=0x%lx:0x%lx)\n",
  18.139 -			cs, eip);
  18.140 -                domain_crash_synchronous();     
  18.141 -            }
  18.142 -            p->count = (PAGE_SIZE - (p->u.data & ~PAGE_MASK)) / p->size;
  18.143 -        } else {
  18.144 -            __update_guest_eip(inst_len);
  18.145 -        }
  18.146 -    } else if (p->dir == IOREQ_WRITE) {
  18.147 -        p->u.data = regs->eax;
  18.148 +        if (test_bit(5, &exit_qualification)) { /* "rep" prefix */
  18.149 +	    mpcip->flags |= REPZ;
  18.150 +	    count = vm86 ? regs->ecx & 0xFFFF : regs->ecx;
  18.151 +	}
  18.152 +
  18.153 +	/*
  18.154 +	 * Handle string pio instructions that cross pages or that
  18.155 +	 * are unaligned. See the comments in vmx_platform.c/handle_mmio()
  18.156 +	 */
  18.157 +	if ((addr & PAGE_MASK) != ((addr + size - 1) & PAGE_MASK)) {
  18.158 +	    unsigned long value = 0;
  18.159 +
  18.160 +	    mpcip->flags |= OVERLAP;
  18.161 +	    if (dir == IOREQ_WRITE)
  18.162 +		vmx_copy(&value, addr, size, VMX_COPY_IN);
  18.163 +	    send_pio_req(regs, port, 1, size, value, dir, 0);
  18.164 +	} else {
  18.165 +	    if ((addr & PAGE_MASK) != ((addr + count * size - 1) & PAGE_MASK)) {
  18.166 +                if (sign > 0)
  18.167 +                    count = (PAGE_SIZE - (addr & ~PAGE_MASK)) / size;
  18.168 +                else
  18.169 +                    count = (addr & ~PAGE_MASK) / size;
  18.170 +	    } else
  18.171 +		__update_guest_eip(inst_len);
  18.172 +
  18.173 +	    send_pio_req(regs, port, count, size, addr, dir, 1);
  18.174 +	}
  18.175 +    } else {
  18.176          __update_guest_eip(inst_len);
  18.177 -    } else
  18.178 -        __update_guest_eip(inst_len);
  18.179 -
  18.180 -    p->addr = addr;
  18.181 -    p->port_mm = 0;
  18.182 -
  18.183 -    /* Check if the packet needs to be intercepted */
  18.184 -    if (vmx_portio_intercept(p))
  18.185 -	/* no blocking & no evtchn notification */
  18.186 -        return;
  18.187 -
  18.188 -    set_bit(ARCH_VMX_IO_WAIT, &d->arch.arch_vmx.flags);
  18.189 -    p->state = STATE_IOREQ_READY;
  18.190 -    evtchn_send(iopacket_port(d->domain));
  18.191 -    vmx_wait_io();
  18.192 +	send_pio_req(regs, port, 1, size, regs->eax, dir, 0);
  18.193 +    }
  18.194  }
  18.195  
  18.196 -enum { COPY_IN = 0, COPY_OUT };
  18.197 -
  18.198 -static inline int
  18.199 +int
  18.200  vmx_copy(void *buf, unsigned long laddr, int size, int dir)
  18.201  {
  18.202 +    unsigned long mfn;
  18.203      char *addr;
  18.204 -    unsigned long mfn;
  18.205 +    int count;
  18.206  
  18.207 -    if ( (size + (laddr & (PAGE_SIZE - 1))) >= PAGE_SIZE )
  18.208 -    {
  18.209 -    	printf("vmx_copy exceeds page boundary\n");
  18.210 -        return 0;
  18.211 +    while (size > 0) {
  18.212 +	count = PAGE_SIZE - (laddr & ~PAGE_MASK);
  18.213 +	if (count > size)
  18.214 +	    count = size;
  18.215 +
  18.216 +	mfn = get_mfn_from_pfn(laddr >> PAGE_SHIFT);
  18.217 +	/* XXX check whether laddr is valid */
  18.218 +	addr = (char *)map_domain_page(mfn) + (laddr & ~PAGE_MASK);
  18.219 +
  18.220 +	if (dir == VMX_COPY_IN)
  18.221 +	    memcpy(buf, addr, count);
  18.222 +	else
  18.223 +	    memcpy(addr, buf, count);
  18.224 +
  18.225 +	unmap_domain_page(addr);
  18.226 +
  18.227 +	laddr += count;
  18.228 +	buf += count;
  18.229 +	size -= count;
  18.230      }
  18.231  
  18.232 -    mfn = get_mfn_from_pfn(laddr >> PAGE_SHIFT);
  18.233 -    addr = (char *)map_domain_page(mfn) + (laddr & ~PAGE_MASK);
  18.234 -
  18.235 -    if (dir == COPY_IN)
  18.236 -	    memcpy(buf, addr, size);
  18.237 -    else
  18.238 -	    memcpy(addr, buf, size);
  18.239 -
  18.240 -    unmap_domain_page(addr);
  18.241      return 1;
  18.242  }
  18.243  
  18.244 @@ -908,7 +941,7 @@ vmx_assist(struct vcpu *d, int mode)
  18.245      u32 cp;
  18.246  
  18.247      /* make sure vmxassist exists (this is not an error) */
  18.248 -    if (!vmx_copy(&magic, VMXASSIST_MAGIC_OFFSET, sizeof(magic), COPY_IN))
  18.249 +    if (!vmx_copy(&magic, VMXASSIST_MAGIC_OFFSET, sizeof(magic), VMX_COPY_IN))
  18.250      	return 0;
  18.251      if (magic != VMXASSIST_MAGIC)
  18.252      	return 0;
  18.253 @@ -922,20 +955,20 @@ vmx_assist(struct vcpu *d, int mode)
  18.254       */
  18.255      case VMX_ASSIST_INVOKE:
  18.256  	/* save the old context */
  18.257 -	if (!vmx_copy(&cp, VMXASSIST_OLD_CONTEXT, sizeof(cp), COPY_IN))
  18.258 +	if (!vmx_copy(&cp, VMXASSIST_OLD_CONTEXT, sizeof(cp), VMX_COPY_IN))
  18.259      	    goto error;
  18.260  	if (cp != 0) {
  18.261      	    if (!vmx_world_save(d, &c))
  18.262  		goto error;
  18.263 -	    if (!vmx_copy(&c, cp, sizeof(c), COPY_OUT))
  18.264 +	    if (!vmx_copy(&c, cp, sizeof(c), VMX_COPY_OUT))
  18.265  		goto error;
  18.266  	}
  18.267  
  18.268  	/* restore the new context, this should activate vmxassist */
  18.269 -	if (!vmx_copy(&cp, VMXASSIST_NEW_CONTEXT, sizeof(cp), COPY_IN))
  18.270 +	if (!vmx_copy(&cp, VMXASSIST_NEW_CONTEXT, sizeof(cp), VMX_COPY_IN))
  18.271  	    goto error;
  18.272  	if (cp != 0) {
  18.273 -            if (!vmx_copy(&c, cp, sizeof(c), COPY_IN))
  18.274 +            if (!vmx_copy(&c, cp, sizeof(c), VMX_COPY_IN))
  18.275  		goto error;
  18.276      	    if (!vmx_world_restore(d, &c))
  18.277  		goto error;
  18.278 @@ -949,10 +982,10 @@ vmx_assist(struct vcpu *d, int mode)
  18.279       */
  18.280      case VMX_ASSIST_RESTORE:
  18.281  	/* save the old context */
  18.282 -	if (!vmx_copy(&cp, VMXASSIST_OLD_CONTEXT, sizeof(cp), COPY_IN))
  18.283 +	if (!vmx_copy(&cp, VMXASSIST_OLD_CONTEXT, sizeof(cp), VMX_COPY_IN))
  18.284      	    goto error;
  18.285  	if (cp != 0) {
  18.286 -            if (!vmx_copy(&c, cp, sizeof(c), COPY_IN))
  18.287 +            if (!vmx_copy(&c, cp, sizeof(c), VMX_COPY_IN))
  18.288  		goto error;
  18.289      	    if (!vmx_world_restore(d, &c))
  18.290  		goto error;
  18.291 @@ -1554,15 +1587,18 @@ asmlinkage void vmx_vmexit_handler(struc
  18.292  
  18.293      __vmread(IDT_VECTORING_INFO_FIELD, &idtv_info_field);
  18.294      if (idtv_info_field & INTR_INFO_VALID_MASK) {
  18.295 -	if ((idtv_info_field & 0x0700) != 0x400) { /* exclude soft ints */
  18.296 -            __vmwrite(VM_ENTRY_INTR_INFO_FIELD, idtv_info_field);
  18.297 +	__vmwrite(VM_ENTRY_INTR_INFO_FIELD, idtv_info_field);
  18.298  
  18.299 -	    if (idtv_info_field & 0x800) { /* valid error code */
  18.300 -		unsigned long error_code;
  18.301 -		__vmread(VM_EXIT_INTR_ERROR_CODE, &error_code);
  18.302 -		__vmwrite(VM_ENTRY_EXCEPTION_ERROR_CODE, error_code);
  18.303 -	    } 
  18.304 -	}
  18.305 +	__vmread(VM_EXIT_INSTRUCTION_LEN, &inst_len);
  18.306 +	if (inst_len >= 1 && inst_len <= 15) 
  18.307 +	    __vmwrite(VM_ENTRY_INSTRUCTION_LEN, inst_len);
  18.308 +
  18.309 +	if (idtv_info_field & 0x800) { /* valid error code */
  18.310 +	    unsigned long error_code;
  18.311 +	    __vmread(IDT_VECTORING_ERROR_CODE, &error_code);
  18.312 +	    __vmwrite(VM_ENTRY_EXCEPTION_ERROR_CODE, error_code);
  18.313 +	} 
  18.314 +
  18.315          VMX_DBG_LOG(DBG_LEVEL_1, "idtv_info_field=%x", idtv_info_field);
  18.316      }
  18.317  
    19.1 --- a/xen/arch/x86/vmx_intercept.c	Sat Sep 03 16:57:54 2005 +0000
    19.2 +++ b/xen/arch/x86/vmx_intercept.c	Sat Sep 03 16:58:50 2005 +0000
    19.3 @@ -172,7 +172,7 @@ int intercept_pit_io(ioreq_t *p)
    19.4  
    19.5      if (p->size != 1 ||
    19.6          p->pdata_valid ||
    19.7 -        p->port_mm)
    19.8 +	p->type != IOREQ_TYPE_PIO)
    19.9          return 0;
   19.10      
   19.11      if (p->addr == PIT_MODE &&
   19.12 @@ -284,7 +284,5 @@ void vmx_hooks_assist(struct vcpu *d)
   19.13          if (!reinit)
   19.14  	    register_portio_handler(0x40, 4, intercept_pit_io); 
   19.15      }
   19.16 -
   19.17  }
   19.18 -
   19.19  #endif /* CONFIG_VMX */
    20.1 --- a/xen/arch/x86/vmx_io.c	Sat Sep 03 16:57:54 2005 +0000
    20.2 +++ b/xen/arch/x86/vmx_io.c	Sat Sep 03 16:58:50 2005 +0000
    20.3 @@ -33,6 +33,7 @@
    20.4  #include <asm/vmx_platform.h>
    20.5  #include <asm/vmx_virpit.h>
    20.6  #include <asm/apic.h>
    20.7 +#include <asm/shadow.h>
    20.8  
    20.9  #include <public/io/ioreq.h>
   20.10  #include <public/io/vmx_vlapic.h>
   20.11 @@ -123,7 +124,6 @@ static void set_reg_value (int size, int
   20.12              regs->esp &= 0xFFFF0000;
   20.13              regs->esp |= (value & 0xFFFF);
   20.14              break;
   20.15 -
   20.16          case 5:
   20.17              regs->ebp &= 0xFFFF0000;
   20.18              regs->ebp |= (value & 0xFFFF);
   20.19 @@ -207,7 +207,6 @@ static inline void __set_reg_value(unsig
   20.20              *reg &= ~0xFFFF;
   20.21              *reg |= (value & 0xFFFF);
   20.22              break;
   20.23 -
   20.24          case LONG:
   20.25              *reg &= ~0xFFFFFFFF;
   20.26              *reg |= (value & 0xFFFFFFFF);
   20.27 @@ -322,13 +321,319 @@ static void set_reg_value (int size, int
   20.28  }
   20.29  #endif
   20.30  
   20.31 +extern long get_reg_value(int size, int index, int seg, struct cpu_user_regs *regs);
   20.32 +
   20.33 +static inline void set_eflags_CF(int size, unsigned long v1,
   20.34 +	unsigned long v2, struct cpu_user_regs *regs)
   20.35 +{
   20.36 +    unsigned long mask = (1 << (8 * size)) - 1;
   20.37 +
   20.38 +    if ((v1 & mask) > (v2 & mask))
   20.39 +	regs->eflags |= X86_EFLAGS_CF;
   20.40 +    else
   20.41 +	regs->eflags &= ~X86_EFLAGS_CF;
   20.42 +}
   20.43 +
   20.44 +static inline void set_eflags_OF(int size, unsigned long v1,
   20.45 +	unsigned long v2, unsigned long v3, struct cpu_user_regs *regs)
   20.46 +{
   20.47 +    if ((v3 ^ v2) & (v3 ^ v1) & (1 << ((8 * size) - 1)))
   20.48 +	regs->eflags |= X86_EFLAGS_OF;
   20.49 +}
   20.50 +
   20.51 +static inline void set_eflags_AF(int size, unsigned long v1,
   20.52 +	unsigned long v2, unsigned long v3, struct cpu_user_regs *regs)
   20.53 +{
   20.54 +    if ((v1 ^ v2 ^ v3) & 0x10)
   20.55 +	regs->eflags |= X86_EFLAGS_AF;
   20.56 +}
   20.57 +
   20.58 +static inline void set_eflags_ZF(int size, unsigned long v1,
   20.59 +	struct cpu_user_regs *regs)
   20.60 +{
   20.61 +    unsigned long mask = (1 << (8 * size)) - 1;
   20.62 +
   20.63 +    if ((v1 & mask) == 0)
   20.64 +	regs->eflags |= X86_EFLAGS_ZF;
   20.65 +}
   20.66 +
   20.67 +static inline void set_eflags_SF(int size, unsigned long v1,
   20.68 +	struct cpu_user_regs *regs)
   20.69 +{
   20.70 +    if (v1 & (1 << ((8 * size) - 1)))
   20.71 +	regs->eflags |= X86_EFLAGS_SF;
   20.72 +}
   20.73 +
   20.74 +static char parity_table[256] = {
   20.75 +    1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
   20.76 +    0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
   20.77 +    0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
   20.78 +    1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
   20.79 +    0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
   20.80 +    1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
   20.81 +    1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
   20.82 +    0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
   20.83 +    0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
   20.84 +    1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
   20.85 +    1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
   20.86 +    0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
   20.87 +    1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
   20.88 +    0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
   20.89 +    0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
   20.90 +    1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1
   20.91 +};
   20.92 +
   20.93 +static inline void set_eflags_PF(int size, unsigned long v1,
   20.94 +	struct cpu_user_regs *regs)
   20.95 +{
   20.96 +    if (parity_table[v1 & 0xFF])
   20.97 +	regs->eflags |= X86_EFLAGS_PF;
   20.98 +}
   20.99 +
  20.100 +static void vmx_pio_assist(struct cpu_user_regs *regs, ioreq_t *p,
  20.101 +					struct mi_per_cpu_info *mpcip)
  20.102 +{
  20.103 +    unsigned long old_eax;
  20.104 +    int sign = p->df ? -1 : 1;
  20.105 +
  20.106 +    if (p->dir == IOREQ_WRITE) {
  20.107 +        if (p->pdata_valid) {
  20.108 +            regs->esi += sign * p->count * p->size;
  20.109 +	    if (mpcip->flags & REPZ)
  20.110 +		regs->ecx -= p->count;
  20.111 +        }
  20.112 +    } else {
  20.113 +	if (mpcip->flags & OVERLAP) {
  20.114 +	    unsigned long addr;
  20.115 +
  20.116 +            regs->edi += sign * p->count * p->size;
  20.117 +	    if (mpcip->flags & REPZ)
  20.118 +		regs->ecx -= p->count;
  20.119 +
  20.120 +	    addr = regs->edi;
  20.121 +	    if (sign > 0)
  20.122 +		addr -= p->size;
  20.123 +	    vmx_copy(&p->u.data, addr, p->size, VMX_COPY_OUT);
  20.124 +	} else if (p->pdata_valid) {
  20.125 +            regs->edi += sign * p->count * p->size;
  20.126 +	    if (mpcip->flags & REPZ)
  20.127 +		regs->ecx -= p->count;
  20.128 +        } else {
  20.129 +	    old_eax = regs->eax;
  20.130 +	    switch (p->size) {
  20.131 +            case 1:
  20.132 +                regs->eax = (old_eax & 0xffffff00) | (p->u.data & 0xff);
  20.133 +                break;
  20.134 +            case 2:
  20.135 +                regs->eax = (old_eax & 0xffff0000) | (p->u.data & 0xffff);
  20.136 +                break;
  20.137 +            case 4:
  20.138 +                regs->eax = (p->u.data & 0xffffffff);
  20.139 +                break;
  20.140 +            default:
  20.141 +		printk("Error: %s unknown port size\n", __FUNCTION__);
  20.142 +		domain_crash_synchronous();
  20.143 +	    }
  20.144 +    	}
  20.145 +    }
  20.146 +}
  20.147 +
  20.148 +static void vmx_mmio_assist(struct cpu_user_regs *regs, ioreq_t *p,
  20.149 +					struct mi_per_cpu_info *mpcip)
  20.150 +{
  20.151 +    int sign = p->df ? -1 : 1;
  20.152 +    int size = -1, index = -1;
  20.153 +    unsigned long value = 0, diff = 0;
  20.154 +    unsigned long src, dst;
  20.155 +
  20.156 +    src = mpcip->operand[0];
  20.157 +    dst = mpcip->operand[1];
  20.158 +    size = operand_size(src);
  20.159 +
  20.160 +    switch (mpcip->instr) {
  20.161 +    case INSTR_MOV:
  20.162 +	if (dst & REGISTER) {
  20.163 +	    index = operand_index(dst);
  20.164 +	    set_reg_value(size, index, 0, regs, p->u.data);
  20.165 +	}
  20.166 +	break;
  20.167 +
  20.168 +    case INSTR_MOVZ:
  20.169 +	if (dst & REGISTER) {
  20.170 +	    index = operand_index(dst);
  20.171 +	    switch (size) {
  20.172 +	    case BYTE: p->u.data = p->u.data & 0xFFULL; break;
  20.173 +	    case WORD: p->u.data = p->u.data & 0xFFFFULL; break;
  20.174 +	    case LONG: p->u.data = p->u.data & 0xFFFFFFFFULL; break;
  20.175 +	    }
  20.176 +	    set_reg_value(operand_size(dst), index, 0, regs, p->u.data);
  20.177 +	}
  20.178 +	break;
  20.179 +
  20.180 +    case INSTR_MOVS:
  20.181 +	sign = p->df ? -1 : 1;
  20.182 +	regs->esi += sign * p->count * p->size;
  20.183 +	regs->edi += sign * p->count * p->size;
  20.184 +
  20.185 +	if ((mpcip->flags & OVERLAP) && p->dir == IOREQ_READ) {
  20.186 +	    unsigned long addr = regs->edi;
  20.187 +
  20.188 +	    if (sign > 0)
  20.189 +		addr -= p->size;
  20.190 +	    vmx_copy(&p->u.data, addr, p->size, VMX_COPY_OUT);
  20.191 +	}
  20.192 +
  20.193 +	if (mpcip->flags & REPZ)
  20.194 +	    regs->ecx -= p->count;
  20.195 +	break;
  20.196 +
  20.197 +    case INSTR_STOS:
  20.198 +	sign = p->df ? -1 : 1;
  20.199 +	regs->edi += sign * p->count * p->size;
  20.200 +	if (mpcip->flags & REPZ)
  20.201 +	    regs->ecx -= p->count;
  20.202 +	break;
  20.203 +
  20.204 +    case INSTR_AND:
  20.205 +	if (src & REGISTER) {
  20.206 +	    index = operand_index(src);
  20.207 +	    value = get_reg_value(size, index, 0, regs);
  20.208 +	    diff = (unsigned long) p->u.data & value;
  20.209 +	} else if (src & IMMEDIATE) {
  20.210 +	    value = mpcip->immediate;
  20.211 +	    diff = (unsigned long) p->u.data & value;
  20.212 +	} else if (src & MEMORY) {
  20.213 +	    index = operand_index(dst);
  20.214 +	    value = get_reg_value(size, index, 0, regs);
  20.215 +	    diff = (unsigned long) p->u.data & value;
  20.216 +	    set_reg_value(size, index, 0, regs, diff);
  20.217 +	}
  20.218 +
  20.219 +	/*
  20.220 +	 * The OF and CF flags are cleared; the SF, ZF, and PF
  20.221 +	 * flags are set according to the result. The state of
  20.222 +	 * the AF flag is undefined.
  20.223 +	 */
  20.224 +	regs->eflags &= ~(X86_EFLAGS_CF|X86_EFLAGS_PF|
  20.225 +			  X86_EFLAGS_ZF|X86_EFLAGS_SF|X86_EFLAGS_OF);
  20.226 +	set_eflags_ZF(size, diff, regs);
  20.227 +	set_eflags_SF(size, diff, regs);
  20.228 +	set_eflags_PF(size, diff, regs);
  20.229 +	break;
  20.230 +
  20.231 +    case INSTR_OR:
  20.232 +	if (src & REGISTER) {
  20.233 +	    index = operand_index(src);
  20.234 +	    value = get_reg_value(size, index, 0, regs);
  20.235 +	    diff = (unsigned long) p->u.data | value;
  20.236 +	} else if (src & IMMEDIATE) {
  20.237 +	    value = mpcip->immediate;
  20.238 +	    diff = (unsigned long) p->u.data | value;
  20.239 +	} else if (src & MEMORY) {
  20.240 +	    index = operand_index(dst);
  20.241 +	    value = get_reg_value(size, index, 0, regs);
  20.242 +	    diff = (unsigned long) p->u.data | value;
  20.243 +	    set_reg_value(size, index, 0, regs, diff);
  20.244 +	}
  20.245 +
  20.246 +	/*
  20.247 +	 * The OF and CF flags are cleared; the SF, ZF, and PF
  20.248 +	 * flags are set according to the result. The state of
  20.249 +	 * the AF flag is undefined.
  20.250 +	 */
  20.251 +	regs->eflags &= ~(X86_EFLAGS_CF|X86_EFLAGS_PF|
  20.252 +			  X86_EFLAGS_ZF|X86_EFLAGS_SF|X86_EFLAGS_OF);
  20.253 +	set_eflags_ZF(size, diff, regs);
  20.254 +	set_eflags_SF(size, diff, regs);
  20.255 +	set_eflags_PF(size, diff, regs);
  20.256 +	break;
  20.257 +
  20.258 +    case INSTR_XOR:
  20.259 +	if (src & REGISTER) {
  20.260 +	    index = operand_index(src);
  20.261 +	    value = get_reg_value(size, index, 0, regs);
  20.262 +	    diff = (unsigned long) p->u.data ^ value;
  20.263 +	} else if (src & IMMEDIATE) {
  20.264 +	    value = mpcip->immediate;
  20.265 +	    diff = (unsigned long) p->u.data ^ value;
  20.266 +	} else if (src & MEMORY) {
  20.267 +	    index = operand_index(dst);
  20.268 +	    value = get_reg_value(size, index, 0, regs);
  20.269 +	    diff = (unsigned long) p->u.data ^ value;
  20.270 +	    set_reg_value(size, index, 0, regs, diff);
  20.271 +	}
  20.272 +
  20.273 +	/*
  20.274 +	 * The OF and CF flags are cleared; the SF, ZF, and PF
  20.275 +	 * flags are set according to the result. The state of
  20.276 +	 * the AF flag is undefined.
  20.277 +	 */
  20.278 +	regs->eflags &= ~(X86_EFLAGS_CF|X86_EFLAGS_PF|
  20.279 +			  X86_EFLAGS_ZF|X86_EFLAGS_SF|X86_EFLAGS_OF);
  20.280 +	set_eflags_ZF(size, diff, regs);
  20.281 +	set_eflags_SF(size, diff, regs);
  20.282 +	set_eflags_PF(size, diff, regs);
  20.283 +	break;
  20.284 +
  20.285 +    case INSTR_CMP:
  20.286 +	if (src & REGISTER) {
  20.287 +	    index = operand_index(src);
  20.288 +	    value = get_reg_value(size, index, 0, regs);
  20.289 +	    diff = (unsigned long) p->u.data - value;
  20.290 +	} else if (src & IMMEDIATE) {
  20.291 +	    value = mpcip->immediate;
  20.292 +	    diff = (unsigned long) p->u.data - value;
  20.293 +	} else if (src & MEMORY) {
  20.294 +	    index = operand_index(dst);
  20.295 +	    value = get_reg_value(size, index, 0, regs);
  20.296 +	    diff = value - (unsigned long) p->u.data;
  20.297 +	}
  20.298 +
  20.299 +	/*
  20.300 +	 * The CF, OF, SF, ZF, AF, and PF flags are set according
  20.301 +	 * to the result
  20.302 +	 */
  20.303 +	regs->eflags &= ~(X86_EFLAGS_CF|X86_EFLAGS_PF|X86_EFLAGS_AF|
  20.304 +			  X86_EFLAGS_ZF|X86_EFLAGS_SF|X86_EFLAGS_OF);
  20.305 +	set_eflags_CF(size, value, (unsigned long) p->u.data, regs);
  20.306 +	set_eflags_OF(size, diff, value, (unsigned long) p->u.data, regs);
  20.307 +	set_eflags_AF(size, diff, value, (unsigned long) p->u.data, regs);
  20.308 +	set_eflags_ZF(size, diff, regs);
  20.309 +	set_eflags_SF(size, diff, regs);
  20.310 +	set_eflags_PF(size, diff, regs);
  20.311 +	break;
  20.312 +
  20.313 +    case INSTR_TEST:
  20.314 +	if (src & REGISTER) {
  20.315 +	    index = operand_index(src);
  20.316 +	    value = get_reg_value(size, index, 0, regs);
  20.317 +	} else if (src & IMMEDIATE) {
  20.318 +	    value = mpcip->immediate;
  20.319 +	} else if (src & MEMORY) {
  20.320 +	    index = operand_index(dst);
  20.321 +	    value = get_reg_value(size, index, 0, regs);
  20.322 +	}
  20.323 +	diff = (unsigned long) p->u.data & value;
  20.324 +
  20.325 +	/*
  20.326 +	 * Sets the SF, ZF, and PF status flags. CF and OF are set to 0
  20.327 +	 */
  20.328 +	regs->eflags &= ~(X86_EFLAGS_CF|X86_EFLAGS_PF|
  20.329 +			  X86_EFLAGS_ZF|X86_EFLAGS_SF|X86_EFLAGS_OF);
  20.330 +	set_eflags_ZF(size, diff, regs);
  20.331 +	set_eflags_SF(size, diff, regs);
  20.332 +	set_eflags_PF(size, diff, regs);
  20.333 +	break;
  20.334 +    }
  20.335 +
  20.336 +    load_cpu_user_regs(regs);
  20.337 +}
  20.338 +
  20.339  void vmx_io_assist(struct vcpu *v) 
  20.340  {
  20.341      vcpu_iodata_t *vio;
  20.342      ioreq_t *p;
  20.343      struct cpu_user_regs *regs = guest_cpu_user_regs();
  20.344 -    unsigned long old_eax;
  20.345 -    int sign;
  20.346      struct mi_per_cpu_info *mpci_p;
  20.347      struct cpu_user_regs *inst_decoder_regs;
  20.348  
  20.349 @@ -340,80 +645,26 @@ void vmx_io_assist(struct vcpu *v)
  20.350      if (vio == 0) {
  20.351          VMX_DBG_LOG(DBG_LEVEL_1, 
  20.352                      "bad shared page: %lx", (unsigned long) vio);
  20.353 +	printf("bad shared page: %lx\n", (unsigned long) vio);
  20.354          domain_crash_synchronous();
  20.355      }
  20.356 -    p = &vio->vp_ioreq;
  20.357  
  20.358 -    if (p->state == STATE_IORESP_HOOK){
  20.359 +    p = &vio->vp_ioreq;
  20.360 +    if (p->state == STATE_IORESP_HOOK)
  20.361          vmx_hooks_assist(v);
  20.362 -    }
  20.363  
  20.364      /* clear IO wait VMX flag */
  20.365      if (test_bit(ARCH_VMX_IO_WAIT, &v->arch.arch_vmx.flags)) {
  20.366 -        if (p->state != STATE_IORESP_READY) {
  20.367 -                /* An interrupt send event raced us */
  20.368 -                return;
  20.369 -        } else {
  20.370 -            p->state = STATE_INVALID;
  20.371 -        }
  20.372 -        clear_bit(ARCH_VMX_IO_WAIT, &v->arch.arch_vmx.flags);
  20.373 -    } else {
  20.374 -        return;
  20.375 -    }
  20.376 -
  20.377 -    sign = (p->df) ? -1 : 1;
  20.378 -    if (p->port_mm) {
  20.379 -        if (p->pdata_valid) {
  20.380 -            regs->esi += sign * p->count * p->size;
  20.381 -            regs->edi += sign * p->count * p->size;
  20.382 -        } else {
  20.383 -            if (p->dir == IOREQ_WRITE) {
  20.384 -                return;
  20.385 -            }
  20.386 -            int size = -1, index = -1;
  20.387 -
  20.388 -            size = operand_size(v->domain->arch.vmx_platform.mpci.mmio_target);
  20.389 -            index = operand_index(v->domain->arch.vmx_platform.mpci.mmio_target);
  20.390 -
  20.391 -            if (v->domain->arch.vmx_platform.mpci.mmio_target & WZEROEXTEND) {
  20.392 -                p->u.data = p->u.data & 0xffff;
  20.393 -            }        
  20.394 -            set_reg_value(size, index, 0, regs, p->u.data);
  20.395 +        if (p->state == STATE_IORESP_READY) {
  20.396 +	    p->state = STATE_INVALID;
  20.397 +            clear_bit(ARCH_VMX_IO_WAIT, &v->arch.arch_vmx.flags);
  20.398  
  20.399 -        }
  20.400 -        load_cpu_user_regs(regs);
  20.401 -        return;
  20.402 -    }
  20.403 -
  20.404 -    if (p->dir == IOREQ_WRITE) {
  20.405 -        if (p->pdata_valid) {
  20.406 -            regs->esi += sign * p->count * p->size;
  20.407 -            regs->ecx -= p->count;
  20.408 -        }
  20.409 -        return;
  20.410 -    } else {
  20.411 -        if (p->pdata_valid) {
  20.412 -            regs->edi += sign * p->count * p->size;
  20.413 -            regs->ecx -= p->count;
  20.414 -            return;
  20.415 -        }
  20.416 -    }
  20.417 -
  20.418 -    old_eax = regs->eax;
  20.419 -
  20.420 -    switch(p->size) {
  20.421 -    case 1:
  20.422 -        regs->eax = (old_eax & 0xffffff00) | (p->u.data & 0xff);
  20.423 -        break;
  20.424 -    case 2:
  20.425 -        regs->eax = (old_eax & 0xffff0000) | (p->u.data & 0xffff);
  20.426 -        break;
  20.427 -    case 4:
  20.428 -        regs->eax = (p->u.data & 0xffffffff);
  20.429 -        break;
  20.430 -    default:
  20.431 -        printk("Error: %s unknwon port size\n", __FUNCTION__);
  20.432 -        domain_crash_synchronous();
  20.433 +	    if (p->type == IOREQ_TYPE_PIO)
  20.434 +		vmx_pio_assist(regs, p, mpci_p);
  20.435 +	    else
  20.436 +		vmx_mmio_assist(regs, p, mpci_p);
  20.437 +	}
  20.438 +	/* else an interrupt send event raced us */
  20.439      }
  20.440  }
  20.441  
  20.442 @@ -456,8 +707,9 @@ void vmx_wait_io()
  20.443      int port = iopacket_port(current->domain);
  20.444  
  20.445      do {
  20.446 -        if(!test_bit(port, &current->domain->shared_info->evtchn_pending[0]))
  20.447 +        if (!test_bit(port, &current->domain->shared_info->evtchn_pending[0]))
  20.448              do_block();
  20.449 +
  20.450          vmx_check_events(current);
  20.451          if (!test_bit(ARCH_VMX_IO_WAIT, &current->arch.arch_vmx.flags))
  20.452              break;
    21.1 --- a/xen/arch/x86/vmx_platform.c	Sat Sep 03 16:57:54 2005 +0000
    21.2 +++ b/xen/arch/x86/vmx_platform.c	Sat Sep 03 16:58:50 2005 +0000
    21.3 @@ -64,37 +64,37 @@ static inline long __get_reg_value(unsig
    21.4          case QUAD:
    21.5              return (long)(reg);
    21.6          default:
    21.7 -            printk("Error: <__get_reg_value>Invalid reg size\n");
    21.8 +	printf("Error: (__get_reg_value) Invalid reg size\n");
    21.9              domain_crash_synchronous();
   21.10      }
   21.11  }
   21.12  
   21.13 -static long get_reg_value(int size, int index, int seg, struct cpu_user_regs *regs) 
   21.14 +long get_reg_value(int size, int index, int seg, struct cpu_user_regs *regs) 
   21.15  {
   21.16      if (size == BYTE) {
   21.17          switch (index) { 
   21.18 -            case 0: //%al
   21.19 +	case 0: /* %al */
   21.20                  return (char)(regs->rax & 0xFF);
   21.21 -            case 1: //%cl  
   21.22 +	case 1: /* %cl */
   21.23                  return (char)(regs->rcx & 0xFF);
   21.24 -            case 2: //%dl
   21.25 +	case 2: /* %dl */
   21.26                  return (char)(regs->rdx & 0xFF); 
   21.27 -            case 3: //%bl
   21.28 +	case 3: /* %bl */
   21.29                  return (char)(regs->rbx & 0xFF);
   21.30 -            case 4: //%ah
   21.31 +	case 4: /* %ah */
   21.32                  return (char)((regs->rax & 0xFF00) >> 8);
   21.33 -            case 5: //%ch 
   21.34 +	case 5: /* %ch */
   21.35                  return (char)((regs->rcx & 0xFF00) >> 8);
   21.36 -            case 6: //%dh
   21.37 +	case 6: /* %dh */
   21.38                  return (char)((regs->rdx & 0xFF00) >> 8);
   21.39 -            case 7: //%bh
   21.40 +	case 7: /* %bh */
   21.41                  return (char)((regs->rbx & 0xFF00) >> 8);
   21.42              default:
   21.43 -                printk("Error: (get_reg_value)Invalid index value\n"); 
   21.44 +	    printf("Error: (get_reg_value) Invalid index value\n"); 
   21.45                  domain_crash_synchronous();
   21.46          }
   21.47 +    }
   21.48  
   21.49 -    }
   21.50      switch (index) {
   21.51          case 0: return __get_reg_value(regs->rax, size);
   21.52          case 1: return __get_reg_value(regs->rcx, size);
   21.53 @@ -113,7 +113,7 @@ static long get_reg_value(int size, int 
   21.54          case 14: return __get_reg_value(regs->r14, size);
   21.55          case 15: return __get_reg_value(regs->r15, size);
   21.56          default:
   21.57 -            printk("Error: (get_reg_value)Invalid index value\n"); 
   21.58 +	printf("Error: (get_reg_value) Invalid index value\n"); 
   21.59              domain_crash_synchronous();
   21.60      }
   21.61  }
   21.62 @@ -129,117 +129,91 @@ void store_cpu_user_regs(struct cpu_user
   21.63      __vmread(GUEST_RIP, &regs->eip);
   21.64  }
   21.65  
   21.66 -static long get_reg_value(int size, int index, int seg, struct cpu_user_regs *regs)
   21.67 +static inline long __get_reg_value(unsigned long reg, int size)
   21.68  {                    
   21.69 -    /*               
   21.70 -     * Reference the db_reg[] table
   21.71 -     */              
   21.72 -    switch (size) {  
   21.73 -    case BYTE: 
   21.74 +    switch(size) {
   21.75 +    case WORD:
   21.76 +	return (short)(reg & 0xFFFF);
   21.77 +    case LONG:
   21.78 +	return (int)(reg & 0xFFFFFFFF);
   21.79 +    default:
   21.80 +	printf("Error: (__get_reg_value) Invalid reg size\n");
   21.81 +	domain_crash_synchronous();
   21.82 +    }
   21.83 +}
   21.84 +
   21.85 +long get_reg_value(int size, int index, int seg, struct cpu_user_regs *regs)
   21.86 +{                    
   21.87 +    if (size == BYTE) {
   21.88          switch (index) { 
   21.89 -        case 0: //%al
   21.90 +	case 0: /* %al */
   21.91              return (char)(regs->eax & 0xFF);
   21.92 -        case 1: //%cl  
   21.93 +	case 1: /* %cl */
   21.94              return (char)(regs->ecx & 0xFF);
   21.95 -        case 2: //%dl
   21.96 +	case 2: /* %dl */
   21.97              return (char)(regs->edx & 0xFF); 
   21.98 -        case 3: //%bl
   21.99 +	case 3: /* %bl */
  21.100              return (char)(regs->ebx & 0xFF);
  21.101 -        case 4: //%ah
  21.102 +	case 4: /* %ah */
  21.103              return (char)((regs->eax & 0xFF00) >> 8);
  21.104 -        case 5: //%ch 
  21.105 +	case 5: /* %ch */
  21.106              return (char)((regs->ecx & 0xFF00) >> 8);
  21.107 -        case 6: //%dh
  21.108 +	case 6: /* %dh */
  21.109              return (char)((regs->edx & 0xFF00) >> 8);
  21.110 -        case 7: //%bh
  21.111 +	case 7: /* %bh */
  21.112              return (char)((regs->ebx & 0xFF00) >> 8);
  21.113          default:
  21.114 -            printk("Error: (get_reg_value)size case 0 error\n"); 
  21.115 +	    printf("Error: (get_reg_value) Invalid index value\n"); 
  21.116              domain_crash_synchronous();
  21.117          }
  21.118 -    case WORD:
  21.119 -        switch (index) {
  21.120 -        case 0: //%ax
  21.121 -            return (short)(regs->eax & 0xFFFF);
  21.122 -        case 1: //%cx
  21.123 -            return (short)(regs->ecx & 0xFFFF);
  21.124 -        case 2: //%dx
  21.125 -            return (short)(regs->edx & 0xFFFF);
  21.126 -        case 3: //%bx
  21.127 -            return (short)(regs->ebx & 0xFFFF);
  21.128 -        case 4: //%sp
  21.129 -            return (short)(regs->esp & 0xFFFF);
  21.130 -            break;
  21.131 -        case 5: //%bp
  21.132 -            return (short)(regs->ebp & 0xFFFF);
  21.133 -        case 6: //%si
  21.134 -            return (short)(regs->esi & 0xFFFF);
  21.135 -        case 7: //%di
  21.136 -            return (short)(regs->edi & 0xFFFF);
  21.137 -        default:
  21.138 -            printk("Error: (get_reg_value)size case 1 error\n");
  21.139 -            domain_crash_synchronous();
  21.140          }
  21.141 -    case LONG:
  21.142 -        switch (index) {
  21.143 -        case 0: //%eax
  21.144 -            return regs->eax;
  21.145 -        case 1: //%ecx
  21.146 -            return regs->ecx;
  21.147 -        case 2: //%edx
  21.148 -            return regs->edx;
  21.149  
  21.150 -        case 3: //%ebx
  21.151 -            return regs->ebx;
  21.152 -        case 4: //%esp
  21.153 -            return regs->esp;
  21.154 -        case 5: //%ebp
  21.155 -            return regs->ebp;
  21.156 -        case 6: //%esi
  21.157 -            return regs->esi;
  21.158 -        case 7: //%edi
  21.159 -            return regs->edi;
  21.160 -        default:
  21.161 -            printk("Error: (get_reg_value)size case 2 error\n");
  21.162 -            domain_crash_synchronous();
  21.163 -        }
  21.164 +        switch (index) {
  21.165 +    case 0: return __get_reg_value(regs->eax, size);
  21.166 +    case 1: return __get_reg_value(regs->ecx, size);
  21.167 +    case 2: return __get_reg_value(regs->edx, size);
  21.168 +    case 3: return __get_reg_value(regs->ebx, size);
  21.169 +    case 4: return __get_reg_value(regs->esp, size);
  21.170 +    case 5: return __get_reg_value(regs->ebp, size);
  21.171 +    case 6: return __get_reg_value(regs->esi, size);
  21.172 +    case 7: return __get_reg_value(regs->edi, size);
  21.173      default:
  21.174 -        printk("Error: (get_reg_value)size case error\n");
  21.175 +	printf("Error: (get_reg_value) Invalid index value\n"); 
  21.176          domain_crash_synchronous();
  21.177      }
  21.178  }
  21.179  #endif
  21.180  
  21.181 -static inline const unsigned char *check_prefix(const unsigned char *inst, struct instruction *thread_inst, unsigned char *rex_p)
  21.182 +static inline unsigned char *check_prefix(unsigned char *inst,
  21.183 +		struct instruction *thread_inst, unsigned char *rex_p)
  21.184  {
  21.185      while (1) {
  21.186          switch (*inst) {
  21.187 -            /* rex prefix for em64t instructions*/
  21.188 +        /* rex prefix for em64t instructions */
  21.189              case 0x40 ... 0x4e:
  21.190                  *rex_p = *inst;
  21.191                  break;
  21.192 -
  21.193 -            case 0xf3: //REPZ
  21.194 +        case 0xf3: /* REPZ */
  21.195      	    	thread_inst->flags = REPZ;
  21.196 -	        	break;
  21.197 -            case 0xf2: //REPNZ
  21.198 +        	break;
  21.199 +        case 0xf2: /* REPNZ */
  21.200      	    	thread_inst->flags = REPNZ;
  21.201 -	        	break;
  21.202 -            case 0xf0: //LOCK
  21.203 +        	break;
  21.204 +        case 0xf0: /* LOCK */
  21.205      	    	break;
  21.206 -            case 0x2e: //CS
  21.207 -            case 0x36: //SS
  21.208 -            case 0x3e: //DS
  21.209 -            case 0x26: //ES
  21.210 -            case 0x64: //FS
  21.211 -            case 0x65: //GS
  21.212 -		        thread_inst->seg_sel = *inst;
  21.213 +        case 0x2e: /* CS */
  21.214 +        case 0x36: /* SS */
  21.215 +        case 0x3e: /* DS */
  21.216 +        case 0x26: /* ES */
  21.217 +        case 0x64: /* FS */
  21.218 +        case 0x65: /* GS */
  21.219 +	        thread_inst->seg_sel = *inst;
  21.220                  break;
  21.221 -            case 0x66: //32bit->16bit
  21.222 +        case 0x66: /* 32bit->16bit */
  21.223                  thread_inst->op_size = WORD;
  21.224                  break;
  21.225              case 0x67:
  21.226 -	        	printf("Error: Not handling 0x67 (yet)\n");
  21.227 +        	printf("Error: Not handling 0x67 (yet)\n");
  21.228                  domain_crash_synchronous();
  21.229                  break;
  21.230              default:
  21.231 @@ -249,7 +223,7 @@ static inline const unsigned char *check
  21.232      }
  21.233  }
  21.234  
  21.235 -static inline unsigned long get_immediate(int op16, const unsigned char *inst, int op_size)
  21.236 +static inline unsigned long get_immediate(int op16,const unsigned char *inst, int op_size)
  21.237  {
  21.238      int mod, reg, rm;
  21.239      unsigned long val = 0;
  21.240 @@ -317,197 +291,299 @@ static inline int get_index(const unsign
  21.241  
  21.242  static void init_instruction(struct instruction *mmio_inst)
  21.243  {
  21.244 -    memset(mmio_inst->i_name, '0', I_NAME_LEN);
  21.245 -    mmio_inst->op_size =  0;
  21.246 -    mmio_inst->offset = 0;
  21.247 +    mmio_inst->instr = 0;
  21.248 +    mmio_inst->op_size = 0;
  21.249      mmio_inst->immediate = 0;
  21.250      mmio_inst->seg_sel = 0;
  21.251 -    mmio_inst->op_num = 0;
  21.252  
  21.253      mmio_inst->operand[0] = 0;
  21.254      mmio_inst->operand[1] = 0;
  21.255 -    mmio_inst->operand[2] = 0;
  21.256          
  21.257      mmio_inst->flags = 0;
  21.258  }
  21.259  
  21.260  #define GET_OP_SIZE_FOR_BYTE(op_size)   \
  21.261 -    do {if (rex) op_size = BYTE_64;else op_size = BYTE;} while(0)
  21.262 +    do {				\
  21.263 +    	if (rex)			\
  21.264 +	    op_size = BYTE_64;		\
  21.265 +	else				\
  21.266 +	    op_size = BYTE;		\
  21.267 +    } while(0)
  21.268  
  21.269  #define GET_OP_SIZE_FOR_NONEBYTE(op_size)   \
  21.270 -    do {if (rex & 0x8) op_size = QUAD; else if (op_size != WORD) op_size = LONG;} while(0)
  21.271 +    do {				\
  21.272 +    	if (rex & 0x8)			\
  21.273 +	    op_size = QUAD;		\
  21.274 +	else if (op_size != WORD)	\
  21.275 +	    op_size = LONG;		\
  21.276 +    } while(0)
  21.277  
  21.278 -static int vmx_decode(const unsigned char *inst, struct instruction *thread_inst)
  21.279 +
  21.280 +/*
  21.281 + * Decode mem,accumulator operands (as in <opcode> m8/m16/m32, al,ax,eax)
  21.282 + */
  21.283 +static int mem_acc(unsigned char size, struct instruction *instr)
  21.284 +{
  21.285 +    instr->operand[0] = mk_operand(size, 0, 0, MEMORY);
  21.286 +    instr->operand[1] = mk_operand(size, 0, 0, REGISTER);
  21.287 +    return DECODE_success;
  21.288 +}
  21.289 +
  21.290 +/*
  21.291 + * Decode accumulator,mem operands (as in <opcode> al,ax,eax, m8/m16/m32)
  21.292 + */
  21.293 +static int acc_mem(unsigned char size, struct instruction *instr)
  21.294 +{
  21.295 +    instr->operand[0] = mk_operand(size, 0, 0, REGISTER);
  21.296 +    instr->operand[1] = mk_operand(size, 0, 0, MEMORY);
  21.297 +    return DECODE_success;
  21.298 +}
  21.299 +
  21.300 +/*
  21.301 + * Decode mem,reg operands (as in <opcode> r32/16, m32/16)
  21.302 + */
  21.303 +static int mem_reg(unsigned char size, unsigned char *opcode,
  21.304 +			struct instruction *instr, unsigned char rex)
  21.305 +{
  21.306 +    int index = get_index(opcode + 1, rex);
  21.307 +
  21.308 +    instr->operand[0] = mk_operand(size, 0, 0, MEMORY);
  21.309 +    instr->operand[1] = mk_operand(size, index, 0, REGISTER);
  21.310 +    return DECODE_success;
  21.311 +}
  21.312 +
  21.313 +/*
  21.314 + * Decode reg,mem operands (as in <opcode> m32/16, r32/16)
  21.315 + */
  21.316 +static int reg_mem(unsigned char size, unsigned char *opcode,
  21.317 +			struct instruction *instr, unsigned char rex)
  21.318 +{
  21.319 +    int index = get_index(opcode + 1, rex);
  21.320 +
  21.321 +    instr->operand[0] = mk_operand(size, index, 0, REGISTER);
  21.322 +    instr->operand[1] = mk_operand(size, 0, 0, MEMORY);
  21.323 +    return DECODE_success;
  21.324 +}
  21.325 +
  21.326 +static int vmx_decode(unsigned char *opcode, struct instruction *instr)
  21.327  {
  21.328      unsigned long eflags;
  21.329      int index, vm86 = 0;
  21.330      unsigned char rex = 0;
  21.331      unsigned char tmp_size = 0;
  21.332  
  21.333 +    init_instruction(instr);
  21.334  
  21.335 -    init_instruction(thread_inst);
  21.336 -
  21.337 -    inst = check_prefix(inst, thread_inst, &rex);
  21.338 +    opcode = check_prefix(opcode, instr, &rex);
  21.339  
  21.340      __vmread(GUEST_RFLAGS, &eflags);
  21.341      if (eflags & X86_EFLAGS_VM)
  21.342          vm86 = 1;
  21.343  
  21.344      if (vm86) { /* meaning is reversed */
  21.345 -       if (thread_inst->op_size == WORD)
  21.346 -           thread_inst->op_size = LONG;
  21.347 -       else if (thread_inst->op_size == LONG)
  21.348 -           thread_inst->op_size = WORD;
  21.349 -       else if (thread_inst->op_size == 0)
  21.350 -           thread_inst->op_size = WORD;
  21.351 +       if (instr->op_size == WORD)
  21.352 +           instr->op_size = LONG;
  21.353 +       else if (instr->op_size == LONG)
  21.354 +           instr->op_size = WORD;
  21.355 +       else if (instr->op_size == 0)
  21.356 +           instr->op_size = WORD;
  21.357      }
  21.358  
  21.359 -    switch(*inst) {
  21.360 -        case 0x81:
  21.361 -            /* This is only a workaround for cmpl instruction*/
  21.362 -            strcpy((char *)thread_inst->i_name, "cmp");
  21.363 -            return DECODE_success;
  21.364 -
  21.365 -        case 0x88:
  21.366 -            /* mov r8 to m8 */
  21.367 -            thread_inst->op_size = BYTE;
  21.368 -            index = get_index((inst + 1), rex);
  21.369 -            GET_OP_SIZE_FOR_BYTE(tmp_size);
  21.370 -            thread_inst->operand[0] = mk_operand(tmp_size, index, 0, REGISTER);
  21.371 -
  21.372 -            break;
  21.373 -        case 0x89:
  21.374 -            /* mov r32/16 to m32/16 */
  21.375 -            index = get_index((inst + 1), rex);
  21.376 -            GET_OP_SIZE_FOR_NONEBYTE(thread_inst->op_size);
  21.377 -            thread_inst->operand[0] = mk_operand(thread_inst->op_size, index, 0, REGISTER);
  21.378 -
  21.379 -            break;
  21.380 -        case 0x8a:
  21.381 -            /* mov m8 to r8 */
  21.382 -            thread_inst->op_size = BYTE;
  21.383 -            index = get_index((inst + 1), rex);
  21.384 -            GET_OP_SIZE_FOR_BYTE(tmp_size);
  21.385 -            thread_inst->operand[1] = mk_operand(tmp_size, index, 0, REGISTER);
  21.386 -            break;
  21.387 -        case 0x8b:
  21.388 -            /* mov r32/16 to m32/16 */
  21.389 -            index = get_index((inst + 1), rex);
  21.390 -            GET_OP_SIZE_FOR_NONEBYTE(thread_inst->op_size);
  21.391 -            thread_inst->operand[1] = mk_operand(thread_inst->op_size, index, 0, REGISTER);
  21.392 -            break;
  21.393 -        case 0x8c:
  21.394 -        case 0x8e:
  21.395 -            printk("%x, This opcode hasn't been handled yet!", *inst);
  21.396 -            return DECODE_failure;
  21.397 -            /* Not handle it yet. */
  21.398 -        case 0xa0:
  21.399 -            /* mov byte to al */
  21.400 -            thread_inst->op_size = BYTE;
  21.401 -            GET_OP_SIZE_FOR_BYTE(tmp_size);
  21.402 -            thread_inst->operand[1] = mk_operand(tmp_size, 0, 0, REGISTER);
  21.403 -            break;
  21.404 -        case 0xa1:
  21.405 -            /* mov word/doubleword to ax/eax */
  21.406 -	    GET_OP_SIZE_FOR_NONEBYTE(thread_inst->op_size);
  21.407 -	    thread_inst->operand[1] = mk_operand(thread_inst->op_size, 0, 0, REGISTER);
  21.408 +    switch (*opcode) {
  21.409 +    case 0x0B: /* or m32/16, r32/16 */
  21.410 +	instr->instr = INSTR_OR;
  21.411 +	GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
  21.412 +	return mem_reg(instr->op_size, opcode, instr, rex);
  21.413  
  21.414 -            break;
  21.415 -        case 0xa2:
  21.416 -            /* mov al to (seg:offset) */
  21.417 -            thread_inst->op_size = BYTE;
  21.418 -            GET_OP_SIZE_FOR_BYTE(tmp_size);
  21.419 -            thread_inst->operand[0] = mk_operand(tmp_size, 0, 0, REGISTER);
  21.420 -            break;
  21.421 -        case 0xa3:
  21.422 -            /* mov ax/eax to (seg:offset) */
  21.423 -            GET_OP_SIZE_FOR_NONEBYTE(thread_inst->op_size);
  21.424 -            thread_inst->operand[0] = mk_operand(thread_inst->op_size, 0, 0, REGISTER);
  21.425 -            break;
  21.426 -        case 0xa4:
  21.427 -            /* movsb */
  21.428 -            thread_inst->op_size = BYTE;
  21.429 -            strcpy((char *)thread_inst->i_name, "movs");
  21.430 -            return DECODE_success;
  21.431 -        case 0xa5:
  21.432 -            /* movsw/movsl */
  21.433 -            GET_OP_SIZE_FOR_NONEBYTE(thread_inst->op_size);
  21.434 -	    strcpy((char *)thread_inst->i_name, "movs");
  21.435 -            return DECODE_success;
  21.436 -        case 0xaa:
  21.437 -            /* stosb */
  21.438 -            thread_inst->op_size = BYTE;
  21.439 -            strcpy((char *)thread_inst->i_name, "stosb");
  21.440 +    case 0x20: /* and r8, m8 */
  21.441 +	instr->instr = INSTR_AND;
  21.442 +	GET_OP_SIZE_FOR_BYTE(instr->op_size);
  21.443 +	return reg_mem(instr->op_size, opcode, instr, rex);
  21.444 +
  21.445 +    case 0x21: /* and r32/16, m32/16 */
  21.446 +	instr->instr = INSTR_AND;
  21.447 +	GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
  21.448 +	return reg_mem(instr->op_size, opcode, instr, rex);
  21.449 +
  21.450 +    case 0x23: /* and m32/16, r32/16 */
  21.451 +	instr->instr = INSTR_AND;
  21.452 +	GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
  21.453 +	return mem_reg(instr->op_size, opcode, instr, rex);
  21.454 +
  21.455 +    case 0x30: /* xor r8, m8 */
  21.456 +	instr->instr = INSTR_XOR;
  21.457 +	GET_OP_SIZE_FOR_BYTE(instr->op_size);
  21.458 +	return reg_mem(instr->op_size, opcode, instr, rex);
  21.459 +
  21.460 +    case 0x31: /* xor r32/16, m32/16 */
  21.461 +	instr->instr = INSTR_XOR;
  21.462 +	GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
  21.463 +	return reg_mem(instr->op_size, opcode, instr, rex);
  21.464 +
  21.465 +    case 0x39: /* cmp r32/16, m32/16 */
  21.466 +	instr->instr = INSTR_CMP;
  21.467 +	GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
  21.468 +	return reg_mem(instr->op_size, opcode, instr, rex);
  21.469 +
  21.470 +    case 0x81:
  21.471 +	if (((opcode[1] >> 3) & 7) == 7) { /* cmp $imm, m32/16 */
  21.472 +	    instr->instr = INSTR_CMP;
  21.473 +	    GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
  21.474 +
  21.475 +	    instr->operand[0] = mk_operand(instr->op_size, 0, 0, IMMEDIATE);
  21.476 +	    instr->immediate = get_immediate(vm86, opcode+1, BYTE);
  21.477 +	    instr->operand[1] = mk_operand(instr->op_size, 0, 0, MEMORY);
  21.478 +
  21.479              return DECODE_success;
  21.480 -       case 0xab:
  21.481 -            /* stosw/stosl */
  21.482 -            if (thread_inst->op_size == WORD) {
  21.483 -                strcpy((char *)thread_inst->i_name, "stosw");
  21.484 -            } else {
  21.485 -                thread_inst->op_size = LONG;
  21.486 -                strcpy((char *)thread_inst->i_name, "stosl");
  21.487 -            }
  21.488 +	} else
  21.489 +	    return DECODE_failure;
  21.490 +
  21.491 +    case 0x84:  /* test m8, r8 */
  21.492 +	instr->instr = INSTR_TEST;
  21.493 +	instr->op_size = BYTE;
  21.494 +	GET_OP_SIZE_FOR_BYTE(tmp_size);
  21.495 +	return mem_reg(tmp_size, opcode, instr, rex);
  21.496 +
  21.497 +    case 0x88: /* mov r8, m8 */
  21.498 +	instr->instr = INSTR_MOV;
  21.499 +	instr->op_size = BYTE;
  21.500 +        GET_OP_SIZE_FOR_BYTE(tmp_size);
  21.501 +	return reg_mem(tmp_size, opcode, instr, rex);
  21.502 +
  21.503 +    case 0x89: /* mov r32/16, m32/16 */
  21.504 +	instr->instr = INSTR_MOV;
  21.505 +	GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
  21.506 +	return reg_mem(instr->op_size, opcode, instr, rex);
  21.507 +
  21.508 +    case 0x8A: /* mov m8, r8 */
  21.509 +	instr->instr = INSTR_MOV;
  21.510 +	instr->op_size = BYTE;
  21.511 +        GET_OP_SIZE_FOR_BYTE(tmp_size);
  21.512 +	return mem_reg(tmp_size, opcode, instr, rex);
  21.513 +
  21.514 +    case 0x8B: /* mov m32/16, r32/16 */
  21.515 +	instr->instr = INSTR_MOV;
  21.516 +	GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
  21.517 +	return mem_reg(instr->op_size, opcode, instr, rex);
  21.518 +
  21.519 +    case 0xA0: /* mov <addr>, al */
  21.520 +	instr->instr = INSTR_MOV;
  21.521 +	instr->op_size = BYTE;
  21.522 +        GET_OP_SIZE_FOR_BYTE(tmp_size);
  21.523 +	return mem_acc(tmp_size, instr);
  21.524 +
  21.525 +    case 0xA1: /* mov <addr>, ax/eax */
  21.526 +	instr->instr = INSTR_MOV;
  21.527 +	GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
  21.528 +	return mem_acc(instr->op_size, instr);
  21.529 +
  21.530 +    case 0xA2: /* mov al, <addr> */
  21.531 +	instr->instr = INSTR_MOV;
  21.532 +	instr->op_size = BYTE;
  21.533 +        GET_OP_SIZE_FOR_BYTE(tmp_size);
  21.534 +	return acc_mem(tmp_size, instr);
  21.535 +
  21.536 +    case 0xA3: /* mov ax/eax, <addr> */
  21.537 +	instr->instr = INSTR_MOV;
  21.538 +	GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
  21.539 +	return acc_mem(instr->op_size, instr);
  21.540 +
  21.541 +    case 0xA4: /* movsb */
  21.542 +	instr->instr = INSTR_MOVS;
  21.543 +	instr->op_size = BYTE;
  21.544 +        return DECODE_success;
  21.545 +            
  21.546 +    case 0xA5: /* movsw/movsl */
  21.547 +	instr->instr = INSTR_MOVS;
  21.548 +	GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
  21.549 +	return DECODE_success;
  21.550 +    
  21.551 +    case 0xAA: /* stosb */
  21.552 +	instr->instr = INSTR_STOS;
  21.553 +	instr->op_size = BYTE;
  21.554 +        return DECODE_success;
  21.555 +
  21.556 +    case 0xAB: /* stosw/stosl */
  21.557 +	instr->instr = INSTR_STOS;
  21.558 +	GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
  21.559 +	return DECODE_success;
  21.560 +                    
  21.561 +    case 0xC6:
  21.562 +	if (((opcode[1] >> 3) & 7) == 0) { /* mov $imm8, m8 */
  21.563 +	    instr->instr = INSTR_MOV;
  21.564 +	    instr->op_size = BYTE;
  21.565 +
  21.566 +	    instr->operand[0] = mk_operand(instr->op_size, 0, 0, IMMEDIATE);
  21.567 +	    instr->immediate = get_immediate(vm86, opcode+1, instr->op_size);
  21.568 +	    instr->operand[1] = mk_operand(instr->op_size, 0, 0, MEMORY);
  21.569 +            
  21.570              return DECODE_success;
  21.571 -        case 0xc6:
  21.572 -            /* mov imm8 to m8 */
  21.573 -            thread_inst->op_size = BYTE;
  21.574 -            thread_inst->operand[0] = mk_operand(BYTE, 0, 0, IMMEDIATE);
  21.575 -            thread_inst->immediate = get_immediate(vm86,
  21.576 -					(inst+1), thread_inst->op_size);
  21.577 -            break;
  21.578 -        case 0xc7:
  21.579 -            /* mov imm16/32 to m16/32 */
  21.580 -            GET_OP_SIZE_FOR_NONEBYTE(thread_inst->op_size);
  21.581 -            thread_inst->operand[0] = mk_operand(thread_inst->op_size, 0, 0, IMMEDIATE);
  21.582 -            thread_inst->immediate = get_immediate(vm86, (inst+1), thread_inst->op_size);
  21.583 +	} else
  21.584 +	    return DECODE_failure;
  21.585              
  21.586 -            break;
  21.587 -        case 0x0f:
  21.588 -            break;
  21.589 -        default:
  21.590 -            printk("%x, This opcode hasn't been handled yet!", *inst);
  21.591 -            return DECODE_failure;
  21.592 -    }
  21.593 -    
  21.594 -    strcpy((char *)thread_inst->i_name, "mov");
  21.595 -    if (*inst != 0x0f) {
  21.596 -        return DECODE_success;
  21.597 +    case 0xC7:
  21.598 +	if (((opcode[1] >> 3) & 7) == 0) { /* mov $imm16/32, m16/32 */
  21.599 +	    instr->instr = INSTR_MOV;
  21.600 +	    GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
  21.601 +
  21.602 +	    instr->operand[0] = mk_operand(instr->op_size, 0, 0, IMMEDIATE);
  21.603 +	    instr->immediate = get_immediate(vm86, opcode+1, instr->op_size);
  21.604 +	    instr->operand[1] = mk_operand(instr->op_size, 0, 0, MEMORY);
  21.605 +            
  21.606 +            return DECODE_success;
  21.607 +	} else
  21.608 +	    return DECODE_failure;
  21.609 +
  21.610 +    case 0xF6:
  21.611 +	if (((opcode[1] >> 3) & 7) == 0) { /* testb $imm8, m8 */
  21.612 +	    instr->instr = INSTR_TEST;
  21.613 +	    instr->op_size = BYTE;
  21.614 +
  21.615 +	    instr->operand[0] = mk_operand(instr->op_size, 0, 0, IMMEDIATE);
  21.616 +	    instr->immediate = get_immediate(vm86, opcode+1, instr->op_size);
  21.617 +	    instr->operand[1] = mk_operand(instr->op_size, 0, 0, MEMORY);
  21.618 +
  21.619 +	    return DECODE_success;
  21.620 +	} else
  21.621 +	    return DECODE_failure;
  21.622 +
  21.623 +    case 0x0F:
  21.624 +	break;
  21.625 +
  21.626 +    default:
  21.627 +	printf("%x, This opcode isn't handled yet!\n", *opcode);
  21.628 +        return DECODE_failure;
  21.629      }
  21.630  
  21.631 -    inst++;
  21.632 -    switch (*inst) {
  21.633 -                    
  21.634 -        /* movz */
  21.635 -        case 0xb6:
  21.636 -            index = get_index((inst + 1), rex);
  21.637 -            GET_OP_SIZE_FOR_NONEBYTE(thread_inst->op_size);
  21.638 -            thread_inst->operand[1] = mk_operand(thread_inst->op_size, index, 0, REGISTER);
  21.639 -            thread_inst->op_size = BYTE;
  21.640 -            strcpy((char *)thread_inst->i_name, "movzb");
  21.641 -            
  21.642 -            return DECODE_success;
  21.643 -        case 0xb7:
  21.644 -	    index = get_index((inst + 1), rex);
  21.645 -	    if (rex & 0x8) {
  21.646 -		    thread_inst->op_size = LONG;
  21.647 -		    thread_inst->operand[1] = mk_operand(QUAD, index, 0, REGISTER);
  21.648 -	    } else {
  21.649 -		    thread_inst->op_size = WORD;
  21.650 -		    thread_inst->operand[1] = mk_operand(LONG, index, 0, REGISTER);
  21.651 -	    }
  21.652 -            
  21.653 -            strcpy((char *)thread_inst->i_name, "movzw");
  21.654 -            
  21.655 -            return DECODE_success;
  21.656 -        default:
  21.657 -            printk("0f %x, This opcode hasn't been handled yet!", *inst);
  21.658 -            return DECODE_failure;
  21.659 +    switch (*++opcode) {
  21.660 +    case 0xB6: /* movz m8, r16/r32 */
  21.661 +	instr->instr = INSTR_MOVZ;
  21.662 +	GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
  21.663 +	index = get_index(opcode + 1, rex);
  21.664 +	instr->operand[0] = mk_operand(BYTE, 0, 0, MEMORY);
  21.665 +	instr->operand[1] = mk_operand(instr->op_size, index, 0, REGISTER);
  21.666 +	return DECODE_success;
  21.667 +
  21.668 +    case 0xB7: /* movz m16, r32 */
  21.669 +	instr->instr = INSTR_MOVZ;
  21.670 +	index = get_index(opcode + 1, rex);
  21.671 +	if (rex & 0x8) {
  21.672 +	   instr->op_size = LONG;
  21.673 +	   instr->operand[1] = mk_operand(QUAD, index, 0, REGISTER);
  21.674 +	} else {
  21.675 +	   instr->op_size = WORD;
  21.676 +	   instr->operand[1] = mk_operand(LONG, index, 0, REGISTER);
  21.677 +	}
  21.678 +	instr->operand[0] = mk_operand(instr->op_size, 0, 0, MEMORY);
  21.679 +	return DECODE_success;
  21.680 +
  21.681 +    default:
  21.682 +	printf("0f %x, This opcode isn't handled yet\n", *opcode);
  21.683 +	return DECODE_failure;
  21.684      }
  21.685 -
  21.686 -    /* will never reach here */
  21.687 -    return DECODE_failure;
  21.688  }
  21.689  
  21.690 +/* XXX use vmx_copy instead */
  21.691  int inst_copy_from_guest(unsigned char *buf, unsigned long guest_eip, int inst_len)
  21.692  {
  21.693      unsigned long gpa;
  21.694 @@ -552,40 +628,27 @@ int inst_copy_from_guest(unsigned char *
  21.695      return inst_len+remaining;
  21.696  }
  21.697  
  21.698 -static int read_from_mmio(struct instruction *inst_p)
  21.699 -{
  21.700 -    // Only for mov instruction now!!!
  21.701 -    if (inst_p->operand[1] & REGISTER)
  21.702 -        return 1;
  21.703 -
  21.704 -    return 0;
  21.705 -}
  21.706 -
  21.707 -// dir:  1 read from mmio
  21.708 -//       0 write to mmio
  21.709 -static void send_mmio_req(unsigned long gpa, 
  21.710 -                   struct instruction *inst_p, long value, int dir, int pvalid)
  21.711 +void send_mmio_req(unsigned char type, unsigned long gpa, 
  21.712 +	   unsigned long count, int size, long value, int dir, int pvalid)
  21.713  {
  21.714      struct vcpu *d = current;
  21.715      vcpu_iodata_t *vio;
  21.716      ioreq_t *p;
  21.717      int vm86;
  21.718 -    struct mi_per_cpu_info *mpci_p;
  21.719 -    struct cpu_user_regs *inst_decoder_regs;
  21.720 +    struct cpu_user_regs *regs;
  21.721      extern long evtchn_send(int lport);
  21.722  
  21.723 -    mpci_p = &current->domain->arch.vmx_platform.mpci;
  21.724 -    inst_decoder_regs = mpci_p->inst_decoder_regs;
  21.725 +    regs = current->domain->arch.vmx_platform.mpci.inst_decoder_regs;
  21.726  
  21.727      vio = get_vio(d->domain, d->vcpu_id);
  21.728 -
  21.729      if (vio == NULL) {
  21.730 -        printk("bad shared page\n");
  21.731 +        printf("bad shared page\n");
  21.732          domain_crash_synchronous(); 
  21.733      }
  21.734 +
  21.735      p = &vio->vp_ioreq;
  21.736  
  21.737 -    vm86 = inst_decoder_regs->eflags & X86_EFLAGS_VM;
  21.738 +    vm86 = regs->eflags & X86_EFLAGS_VM;
  21.739  
  21.740      if (test_bit(ARCH_VMX_IO_WAIT, &d->arch.arch_vmx.flags)) {
  21.741          printf("VMX I/O has not yet completed\n");
  21.742 @@ -596,25 +659,22 @@ static void send_mmio_req(unsigned long 
  21.743      p->dir = dir;
  21.744      p->pdata_valid = pvalid;
  21.745  
  21.746 -    p->port_mm = 1;
  21.747 -    p->size = inst_p->op_size;
  21.748 +    p->type = type;
  21.749 +    p->size = size;
  21.750      p->addr = gpa;
  21.751 -    p->u.data = value;
  21.752 +    p->count = count;
  21.753 +    p->df = regs->eflags & EF_DF ? 1 : 0;
  21.754 +
  21.755 +    if (pvalid) {
  21.756 +	if (vmx_paging_enabled(current))
  21.757 +	    p->u.pdata = (void *) gva_to_gpa(value);
  21.758 +        else
  21.759 +	    p->u.pdata = (void *) value; /* guest VA == guest PA */
  21.760 +    } else
  21.761 +	p->u.data = value;
  21.762  
  21.763      p->state = STATE_IOREQ_READY;
  21.764  
  21.765 -    if (inst_p->flags & REPZ) {
  21.766 -        if (vm86)
  21.767 -            p->count = inst_decoder_regs->ecx & 0xFFFF;
  21.768 -        else
  21.769 -            p->count = inst_decoder_regs->ecx;
  21.770 -        p->df = (inst_decoder_regs->eflags & EF_DF) ? 1 : 0;
  21.771 -    } else
  21.772 -        p->count = 1;
  21.773 -
  21.774 -    if ((pvalid) && vmx_paging_enabled(current))
  21.775 -        p->u.pdata = (void *) gva_to_gpa(p->u.data);
  21.776 -
  21.777      if (vmx_mmio_intercept(p)){
  21.778          p->state = STATE_IORESP_READY;
  21.779          vmx_io_assist(d);
  21.780 @@ -625,18 +685,50 @@ static void send_mmio_req(unsigned long 
  21.781      vmx_wait_io();
  21.782  }
  21.783  
  21.784 +static void mmio_operands(int type, unsigned long gpa, struct instruction *inst,
  21.785 +		struct mi_per_cpu_info *mpcip, struct cpu_user_regs *regs)
  21.786 +{
  21.787 +    unsigned long value = 0;
  21.788 +    int index, size;
  21.789 +    
  21.790 +    size = operand_size(inst->operand[0]);
  21.791 +
  21.792 +    mpcip->flags = inst->flags;
  21.793 +    mpcip->instr = inst->instr;
  21.794 +    mpcip->operand[0] = inst->operand[0]; /* source */
  21.795 +    mpcip->operand[1] = inst->operand[1]; /* destination */
  21.796 +
  21.797 +    if (inst->operand[0] & REGISTER) { /* dest is memory */
  21.798 +	index = operand_index(inst->operand[0]);
  21.799 +	value = get_reg_value(size, index, 0, regs);
  21.800 +	send_mmio_req(type, gpa, 1, size, value, IOREQ_WRITE, 0);
  21.801 +    } else if (inst->operand[0] & IMMEDIATE) { /* dest is memory */
  21.802 +	value = inst->immediate;
  21.803 +	send_mmio_req(type, gpa, 1, size, value, IOREQ_WRITE, 0);
  21.804 +    } else if (inst->operand[0] & MEMORY) { /* dest is register */
  21.805 +	/* send the request and wait for the value */
  21.806 +	send_mmio_req(type, gpa, 1, size, 0, IOREQ_READ, 0);
  21.807 +    } else {
  21.808 +	printf("mmio_operands: invalid operand\n");
  21.809 +	domain_crash_synchronous();
  21.810 +    }
  21.811 +}
  21.812 +
  21.813 +#define GET_REPEAT_COUNT() \
  21.814 +     (mmio_inst.flags & REPZ ? (vm86 ? regs->ecx & 0xFFFF : regs->ecx) : 1)
  21.815 +	
  21.816  void handle_mmio(unsigned long va, unsigned long gpa)
  21.817  {
  21.818      unsigned long eip, eflags, cs;
  21.819      unsigned long inst_len, inst_addr;
  21.820 -    struct mi_per_cpu_info *mpci_p;
  21.821 -    struct cpu_user_regs *inst_decoder_regs;
  21.822 +    struct mi_per_cpu_info *mpcip;
  21.823 +    struct cpu_user_regs *regs;
  21.824      struct instruction mmio_inst;
  21.825      unsigned char inst[MAX_INST_LEN];
  21.826 -    int vm86, ret;
  21.827 +    int i, vm86, ret;
  21.828       
  21.829 -    mpci_p = &current->domain->arch.vmx_platform.mpci;
  21.830 -    inst_decoder_regs = mpci_p->inst_decoder_regs;
  21.831 +    mpcip = &current->domain->arch.vmx_platform.mpci;
  21.832 +    regs = mpcip->inst_decoder_regs;
  21.833  
  21.834      __vmread(GUEST_RIP, &eip);
  21.835      __vmread(VM_EXIT_INSTRUCTION_LEN, &inst_len);
  21.836 @@ -647,108 +739,142 @@ void handle_mmio(unsigned long va, unsig
  21.837          __vmread(GUEST_CS_SELECTOR, &cs);
  21.838          inst_addr = (cs << 4) + eip;
  21.839      } else
  21.840 -        inst_addr = eip; /* XXX should really look at GDT[cs].base too */
  21.841 +        inst_addr = eip;
  21.842  
  21.843 -    memset(inst, '0', MAX_INST_LEN);
  21.844 +    memset(inst, 0, MAX_INST_LEN);
  21.845      ret = inst_copy_from_guest(inst, inst_addr, inst_len);
  21.846      if (ret != inst_len) {
  21.847 -        printk("handle_mmio - EXIT: get guest instruction fault\n");
  21.848 +        printf("handle_mmio - EXIT: get guest instruction fault\n");
  21.849          domain_crash_synchronous();
  21.850      }
  21.851  
  21.852 -
  21.853      init_instruction(&mmio_inst);
  21.854      
  21.855      if (vmx_decode(inst, &mmio_inst) == DECODE_failure) {
  21.856 -        printk("vmx decode failure: eip=%lx, va=%lx\n %x %x %x %x\n", eip, va, 
  21.857 -               inst[0], inst[1], inst[2], inst[3]);
  21.858 +	printf("mmio opcode: va 0x%lx, gpa 0x%lx, len %ld:",
  21.859 +		va, gpa, inst_len);
  21.860 +	for (i = 0; i < inst_len; i++)
  21.861 +	    printf(" %02x", inst[i] & 0xFF);
  21.862 +	printf("\n");
  21.863          domain_crash_synchronous();
  21.864      }
  21.865  
  21.866 -    __vmwrite(GUEST_RIP, eip + inst_len);
  21.867 -    store_cpu_user_regs(inst_decoder_regs);
  21.868 +    store_cpu_user_regs(regs);
  21.869 +    regs->eip += inst_len; /* advance %eip */
  21.870  
  21.871 -    // Only handle "mov" and "movs" instructions!
  21.872 -    if (!strncmp((char *)mmio_inst.i_name, "movz", 4)) {
  21.873 -        if (read_from_mmio(&mmio_inst)) {
  21.874 -            // Send the request and waiting for return value.
  21.875 -            mpci_p->mmio_target = mmio_inst.operand[1] | WZEROEXTEND;
  21.876 -            send_mmio_req(gpa, &mmio_inst, 0, IOREQ_READ, 0);
  21.877 -            return ;
  21.878 -        } else {
  21.879 -            printk("handle_mmio - EXIT: movz error!\n");
  21.880 -            domain_crash_synchronous();
  21.881 -        }
  21.882 -    }
  21.883 +    switch (mmio_inst.instr) {
  21.884 +    case INSTR_MOV:
  21.885 +	mmio_operands(IOREQ_TYPE_COPY, gpa, &mmio_inst, mpcip, regs);
  21.886 +	break;
  21.887  
  21.888 -    if (!strncmp((char *)mmio_inst.i_name, "movs", 4)) {
  21.889 +    case INSTR_MOVS:
  21.890 +    {
  21.891 +	unsigned long count = GET_REPEAT_COUNT();
  21.892 +	unsigned long size = mmio_inst.op_size;
  21.893 +	int sign = regs->eflags & EF_DF ? -1 : 1;
  21.894  	unsigned long addr = 0;
  21.895  	int dir;
  21.896  
  21.897 +	/* determine non-MMIO address */
  21.898  	if (vm86) {
  21.899  	    unsigned long seg;
  21.900  
  21.901  	    __vmread(GUEST_ES_SELECTOR, &seg);
  21.902 -	    if (((seg << 4) + (inst_decoder_regs->edi & 0xFFFF)) == va) {
  21.903 +	    if (((seg << 4) + (regs->edi & 0xFFFF)) == va) {
  21.904  		dir = IOREQ_WRITE;
  21.905  		__vmread(GUEST_DS_SELECTOR, &seg);
  21.906 -		addr = (seg << 4) + (inst_decoder_regs->esi & 0xFFFF);
  21.907 +		addr = (seg << 4) + (regs->esi & 0xFFFF);
  21.908  	    } else {
  21.909  		dir = IOREQ_READ;
  21.910 -		addr = (seg << 4) + (inst_decoder_regs->edi & 0xFFFF);
  21.911 +		addr = (seg << 4) + (regs->edi & 0xFFFF);
  21.912  	    }
  21.913 -	} else { /* XXX should really look at GDT[ds/es].base too */
  21.914 -	    if (va == inst_decoder_regs->edi) {
  21.915 +	} else {
  21.916 +	    if (va == regs->edi) {
  21.917  		dir = IOREQ_WRITE;
  21.918 -		addr = inst_decoder_regs->esi;
  21.919 +		addr = regs->esi;
  21.920  	    } else {
  21.921  		dir = IOREQ_READ;
  21.922 -		addr = inst_decoder_regs->edi;
  21.923 +		addr = regs->edi;
  21.924  	    }
  21.925  	}
  21.926  
  21.927 -	send_mmio_req(gpa, &mmio_inst, addr, dir, 1);
  21.928 -        return;
  21.929 +	mpcip->flags = mmio_inst.flags;
  21.930 +	mpcip->instr = mmio_inst.instr;
  21.931 +
  21.932 +	/*
  21.933 +	 * In case of a movs spanning multiple pages, we break the accesses
  21.934 +	 * up into multiple pages (the device model works with non-continguous
  21.935 +	 * physical guest pages). To copy just one page, we adjust %ecx and
  21.936 +	 * do not advance %eip so that the next "rep movs" copies the next page.
  21.937 +	 * Unaligned accesses, for example movsl starting at PGSZ-2, are
  21.938 +	 * turned into a single copy where we handle the overlapping memory
  21.939 +	 * copy ourself. After this copy succeeds, "rep movs" is executed
  21.940 +	 * again.
  21.941 +	 */
  21.942 +	if ((addr & PAGE_MASK) != ((addr + size - 1) & PAGE_MASK)) {
  21.943 +	    unsigned long value = 0;
  21.944 +
  21.945 +	    mpcip->flags |= OVERLAP;
  21.946 +
  21.947 +	    regs->eip -= inst_len; /* do not advance %eip */
  21.948 +
  21.949 +	    if (dir == IOREQ_WRITE)
  21.950 +		vmx_copy(&value, addr, size, VMX_COPY_IN);
  21.951 +	    send_mmio_req(IOREQ_TYPE_COPY, gpa, 1, size, value, dir, 0);
  21.952 +	} else {
  21.953 +	    if ((addr & PAGE_MASK) != ((addr + count * size - 1) & PAGE_MASK)) {
  21.954 +	        regs->eip -= inst_len; /* do not advance %eip */
  21.955 +
  21.956 +		if (sign > 0)
  21.957 +		    count = (PAGE_SIZE - (addr & ~PAGE_MASK)) / size;
  21.958 +		else
  21.959 +		    count = (addr & ~PAGE_MASK) / size;
  21.960 +	    }
  21.961 +
  21.962 +	    send_mmio_req(IOREQ_TYPE_COPY, gpa, count, size, addr, dir, 1);
  21.963 +	}
  21.964 +        break;
  21.965      }
  21.966  
  21.967 -    if (!strncmp((char *)mmio_inst.i_name, "mov", 3)) {
  21.968 -        long value = 0;
  21.969 -        int size, index;
  21.970 +    case INSTR_MOVZ:
  21.971 +	mmio_operands(IOREQ_TYPE_COPY, gpa, &mmio_inst, mpcip, regs);
  21.972 +	break;
  21.973  
  21.974 -        if (read_from_mmio(&mmio_inst)) {
  21.975 -            // Send the request and waiting for return value.
  21.976 -            mpci_p->mmio_target = mmio_inst.operand[1];
  21.977 -            send_mmio_req(gpa, &mmio_inst, value, IOREQ_READ, 0);
  21.978 -            return;
  21.979 -        } else {
  21.980 -            // Write to MMIO
  21.981 -            if (mmio_inst.operand[0] & IMMEDIATE) {
  21.982 -                value = mmio_inst.immediate;
  21.983 -            } else if (mmio_inst.operand[0] & REGISTER) {
  21.984 -                size = operand_size(mmio_inst.operand[0]);
  21.985 -                index = operand_index(mmio_inst.operand[0]);
  21.986 -                value = get_reg_value(size, index, 0, inst_decoder_regs);
  21.987 -            } else {
  21.988 -                domain_crash_synchronous();
  21.989 -            }
  21.990 -            send_mmio_req(gpa, &mmio_inst, value, IOREQ_WRITE, 0);
  21.991 -            return;
  21.992 -        }
  21.993 +    case INSTR_STOS:
  21.994 +	/*
  21.995 +	 * Since the destination is always in (contiguous) mmio space we don't
  21.996 +	 * need to break it up into pages.
  21.997 +	 */
  21.998 +	mpcip->flags = mmio_inst.flags;
  21.999 +	mpcip->instr = mmio_inst.instr;
 21.1000 +        send_mmio_req(IOREQ_TYPE_COPY, gpa,
 21.1001 +	    GET_REPEAT_COUNT(), mmio_inst.op_size, regs->eax, IOREQ_WRITE, 0);
 21.1002 +	break;
 21.1003 +
 21.1004 +    case INSTR_OR:
 21.1005 +	mmio_operands(IOREQ_TYPE_OR, gpa, &mmio_inst, mpcip, regs);
 21.1006 +	break;
 21.1007 +
 21.1008 +    case INSTR_AND:
 21.1009 +	mmio_operands(IOREQ_TYPE_AND, gpa, &mmio_inst, mpcip, regs);
 21.1010 +	break;
 21.1011 +
 21.1012 +    case INSTR_XOR:
 21.1013 +	mmio_operands(IOREQ_TYPE_XOR, gpa, &mmio_inst, mpcip, regs);
 21.1014 +	break;
 21.1015 +
 21.1016 +    case INSTR_CMP:
 21.1017 +	mmio_operands(IOREQ_TYPE_COPY, gpa, &mmio_inst, mpcip, regs);
 21.1018 +	break;
 21.1019 +
 21.1020 +    case INSTR_TEST:
 21.1021 +	mmio_operands(IOREQ_TYPE_COPY, gpa, &mmio_inst, mpcip, regs);
 21.1022 +    	break;
 21.1023 +
 21.1024 +    default:
 21.1025 +	printf("Unhandled MMIO instruction\n");
 21.1026 +	domain_crash_synchronous();
 21.1027      }
 21.1028 -
 21.1029 -    if (!strncmp((char *)mmio_inst.i_name, "stos", 4)) {
 21.1030 -        send_mmio_req(gpa, &mmio_inst,
 21.1031 -            inst_decoder_regs->eax, IOREQ_WRITE, 0);
 21.1032 -        return;
 21.1033 -    }
 21.1034 -    /* Workaround for cmp instruction */
 21.1035 -    if (!strncmp((char *)mmio_inst.i_name, "cmp", 3)) {
 21.1036 -        inst_decoder_regs->eflags &= ~X86_EFLAGS_ZF;
 21.1037 -        __vmwrite(GUEST_RFLAGS, inst_decoder_regs->eflags);
 21.1038 -        return;
 21.1039 -    }
 21.1040 -
 21.1041 -    domain_crash_synchronous();
 21.1042  }
 21.1043  
 21.1044  #endif /* CONFIG_VMX */
    22.1 --- a/xen/common/memory.c	Sat Sep 03 16:57:54 2005 +0000
    22.2 +++ b/xen/common/memory.c	Sat Sep 03 16:58:50 2005 +0000
    22.3 @@ -25,7 +25,8 @@ increase_reservation(
    22.4      unsigned long *extent_list, 
    22.5      unsigned int   nr_extents,
    22.6      unsigned int   extent_order,
    22.7 -    unsigned int   flags)
    22.8 +    unsigned int   flags,
    22.9 +    int           *preempted)
   22.10  {
   22.11      struct pfn_info *page;
   22.12      unsigned long    i;
   22.13 @@ -43,7 +44,10 @@ increase_reservation(
   22.14      for ( i = 0; i < nr_extents; i++ )
   22.15      {
   22.16          if ( hypercall_preempt_check() )
   22.17 +        {
   22.18 +            *preempted = 1;
   22.19              return i;
   22.20 +        }
   22.21  
   22.22          if ( unlikely((page = alloc_domheap_pages(
   22.23              d, extent_order, flags)) == NULL) )
   22.24 @@ -67,7 +71,8 @@ decrease_reservation(
   22.25      unsigned long *extent_list, 
   22.26      unsigned int   nr_extents,
   22.27      unsigned int   extent_order,
   22.28 -    unsigned int   flags)
   22.29 +    unsigned int   flags,
   22.30 +    int           *preempted)
   22.31  {
   22.32      struct pfn_info *page;
   22.33      unsigned long    i, j, mpfn;
   22.34 @@ -78,7 +83,10 @@ decrease_reservation(
   22.35      for ( i = 0; i < nr_extents; i++ )
   22.36      {
   22.37          if ( hypercall_preempt_check() )
   22.38 +        {
   22.39 +            *preempted = 1;
   22.40              return i;
   22.41 +        }
   22.42  
   22.43          if ( unlikely(__get_user(mpfn, &extent_list[i]) != 0) )
   22.44              return i;
   22.45 @@ -124,7 +132,7 @@ decrease_reservation(
   22.46  long do_memory_op(int cmd, void *arg)
   22.47  {
   22.48      struct domain *d;
   22.49 -    int rc, start_extent, op, flags = 0;
   22.50 +    int rc, start_extent, op, flags = 0, preempted = 0;
   22.51      struct xen_memory_reservation reservation;
   22.52  
   22.53      op = cmd & ((1 << START_EXTENT_SHIFT) - 1);
   22.54 @@ -165,19 +173,18 @@ long do_memory_op(int cmd, void *arg)
   22.55                    reservation.extent_start,
   22.56                    reservation.nr_extents,
   22.57                    reservation.extent_order,
   22.58 -                  flags);
   22.59 +                  flags,
   22.60 +                  &preempted);
   22.61  
   22.62          if ( unlikely(reservation.domid != DOMID_SELF) )
   22.63              put_domain(d);
   22.64  
   22.65          rc += start_extent;
   22.66  
   22.67 -        if ( (rc != reservation.nr_extents) && hypercall_preempt_check() )
   22.68 +        if ( preempted )
   22.69              return hypercall2_create_continuation(
   22.70 -                __HYPERVISOR_memory_op,
   22.71 -                op | (rc << START_EXTENT_SHIFT),
   22.72 -                arg);
   22.73 -        
   22.74 +                __HYPERVISOR_memory_op, op | (rc << START_EXTENT_SHIFT), arg);
   22.75 +
   22.76          break;
   22.77  
   22.78      case XENMEM_maximum_ram_page:
    23.1 --- a/xen/include/asm-x86/vmx.h	Sat Sep 03 16:57:54 2005 +0000
    23.2 +++ b/xen/include/asm-x86/vmx.h	Sat Sep 03 16:58:50 2005 +0000
    23.3 @@ -471,4 +471,7 @@ static inline int iopacket_port(struct d
    23.4  void load_cpu_user_regs(struct cpu_user_regs *regs);
    23.5  void store_cpu_user_regs(struct cpu_user_regs *regs);
    23.6  
    23.7 +enum { VMX_COPY_IN = 0, VMX_COPY_OUT };
    23.8 +int vmx_copy(void *buf, unsigned long laddr, int size, int dir);
    23.9 +
   23.10  #endif /* __ASM_X86_VMX_H__ */
    24.1 --- a/xen/include/asm-x86/vmx_platform.h	Sat Sep 03 16:57:54 2005 +0000
    24.2 +++ b/xen/include/asm-x86/vmx_platform.h	Sat Sep 03 16:58:50 2005 +0000
    24.3 @@ -24,8 +24,7 @@
    24.4  #include <asm/vmx_virpit.h>
    24.5  #include <asm/vmx_intercept.h>
    24.6  
    24.7 -#define MAX_OPERAND_NUM 3
    24.8 -#define I_NAME_LEN  16
    24.9 +#define MAX_OPERAND_NUM 2
   24.10  
   24.11  #define mk_operand(size, index, seg, flag) \
   24.12      (((size) << 24) | ((index) << 16) | ((seg) << 8) | (flag))
   24.13 @@ -35,54 +34,60 @@
   24.14  
   24.15  #define operand_index(operand)  \
   24.16        ((operand >> 16) & 0xFF)
   24.17 -      //For instruction.operand[].size
   24.18 +
   24.19 +/* for instruction.operand[].size */
   24.20  #define BYTE    1
   24.21  #define WORD    2
   24.22  #define LONG    4
   24.23  #define QUAD    8
   24.24  #define BYTE_64 16
   24.25  
   24.26 -      //For instruction.operand[].flag
   24.27 +/* for instruction.operand[].flag */
   24.28  #define REGISTER    0x1
   24.29  #define MEMORY      0x2
   24.30  #define IMMEDIATE   0x4
   24.31 -#define WZEROEXTEND 0x8
   24.32  
   24.33 -      //For instruction.flags
   24.34 +/* for instruction.flags */
   24.35  #define REPZ    0x1
   24.36  #define REPNZ   0x2
   24.37 +#define OVERLAP 0x4
   24.38 +
   24.39 +#define	INSTR_PIO	1
   24.40 +#define INSTR_OR	2
   24.41 +#define INSTR_AND	3
   24.42 +#define INSTR_XOR	4
   24.43 +#define INSTR_CMP	5
   24.44 +#define INSTR_MOV	6
   24.45 +#define INSTR_MOVS	7
   24.46 +#define INSTR_MOVZ	8
   24.47 +#define INSTR_STOS	9
   24.48 +#define INSTR_TEST	10
   24.49  
   24.50  struct instruction {
   24.51 -    __s8    i_name[I_NAME_LEN];  //Instruction's name
   24.52 -    __s16   op_size;    //The operand's bit size, e.g. 16-bit or 32-bit.
   24.53 -
   24.54 -    __u64   offset;     //The effective address
   24.55 -          //offset = Base + (Index * Scale) + Displacement
   24.56 -
   24.57 +    __s8    instr;	/* instruction type */
   24.58 +    __s16   op_size;    /* the operand's bit size, e.g. 16-bit or 32-bit */
   24.59      __u64   immediate;
   24.60 -
   24.61 -    __u16   seg_sel;    //Segmentation selector
   24.62 -
   24.63 -    __u32   operand[MAX_OPERAND_NUM];   //The order of operand is from AT&T Assembly
   24.64 -    __s16   op_num; //The operand numbers
   24.65 -
   24.66 -    __u32   flags; //
   24.67 +    __u16   seg_sel;    /* segmentation selector */
   24.68 +    __u32   operand[MAX_OPERAND_NUM];   /* order is AT&T assembly */
   24.69 +    __u32   flags;
   24.70  };
   24.71  
   24.72  #define MAX_INST_LEN      32
   24.73  
   24.74 -struct mi_per_cpu_info
   24.75 -{
   24.76 -    unsigned long          mmio_target;
   24.77 -    struct cpu_user_regs        *inst_decoder_regs;
   24.78 +struct mi_per_cpu_info {
   24.79 +    int                    flags;
   24.80 +    int			   instr;		/* instruction */
   24.81 +    unsigned long          operand[2];		/* operands */
   24.82 +    unsigned long          immediate;		/* immediate portion */
   24.83 +    struct cpu_user_regs   *inst_decoder_regs;	/* current context */
   24.84  };
   24.85  
   24.86  struct virtual_platform_def {
   24.87 -    unsigned long          *real_mode_data; /* E820, etc. */
   24.88 +    unsigned long          *real_mode_data;	/* E820, etc. */
   24.89      unsigned long          shared_page_va;
   24.90      struct vmx_virpit_t    vmx_pit;
   24.91      struct vmx_handler_t   vmx_handler;
   24.92 -    struct mi_per_cpu_info mpci;            /* MMIO */
   24.93 +    struct mi_per_cpu_info mpci;		/* MMIO */
   24.94  };
   24.95  
   24.96  extern void handle_mmio(unsigned long, unsigned long);
    25.1 --- a/xen/include/public/io/ioreq.h	Sat Sep 03 16:57:54 2005 +0000
    25.2 +++ b/xen/include/public/io/ioreq.h	Sat Sep 03 16:58:50 2005 +0000
    25.3 @@ -29,9 +29,17 @@
    25.4  #define STATE_IORESP_READY      3
    25.5  #define STATE_IORESP_HOOK       4
    25.6  
    25.7 -/* VMExit dispatcher should cooperate with instruction decoder to
    25.8 -   prepare this structure and notify service OS and DM by sending
    25.9 -   virq */
   25.10 +#define IOREQ_TYPE_PIO		0	/* pio */
   25.11 +#define IOREQ_TYPE_COPY		1	/* mmio ops */
   25.12 +#define IOREQ_TYPE_AND		2
   25.13 +#define IOREQ_TYPE_OR		3
   25.14 +#define IOREQ_TYPE_XOR		4
   25.15 +
   25.16 +/*
   25.17 + * VMExit dispatcher should cooperate with instruction decoder to
   25.18 + * prepare this structure and notify service OS and DM by sending
   25.19 + * virq 
   25.20 + */
   25.21  typedef struct {
   25.22      u64     addr;               /*  physical address            */
   25.23      u64     size;               /*  size in bytes               */
   25.24 @@ -43,8 +51,8 @@ typedef struct {
   25.25      u8      state:4;
   25.26      u8      pdata_valid:1;	/* if 1, use pdata above        */
   25.27      u8      dir:1;		/*  1=read, 0=write             */
   25.28 -    u8      port_mm:1;		/*  0=portio, 1=mmio            */
   25.29      u8      df:1;
   25.30 +    u8      type;		/* I/O type			*/
   25.31  } ioreq_t;
   25.32  
   25.33  #define MAX_VECTOR    256