ia64/xen-unstable
changeset 17005:9203ee23e724
merge with xen-unstable.hg
author | Alex Williamson <alex.williamson@hp.com> |
---|---|
date | Thu Feb 07 11:08:49 2008 -0700 (2008-02-07) |
parents | e3e8bdb5d52d e6cf98edf0c5 |
children | 390707dd4c2f |
files | tools/firmware/README tools/firmware/vmxassist/Makefile tools/firmware/vmxassist/gen.c tools/firmware/vmxassist/head.S tools/firmware/vmxassist/machine.h tools/firmware/vmxassist/setup.c tools/firmware/vmxassist/trap.S tools/firmware/vmxassist/util.c tools/firmware/vmxassist/util.h tools/firmware/vmxassist/vm86.c tools/firmware/vmxassist/vm86.h tools/firmware/vmxassist/vmxassist.ld xen/include/asm-x86/hvm/vmx/cpu.h xen/include/public/hvm/vmx_assist.h |
line diff
1.1 --- a/docs/man/xmdomain.cfg.pod.5 Thu Feb 07 09:23:26 2008 -0700 1.2 +++ b/docs/man/xmdomain.cfg.pod.5 Thu Feb 07 11:08:49 2008 -0700 1.3 @@ -298,6 +298,22 @@ it holds, so that the new one may take t 1.4 1.5 =back 1.6 1.7 +=over 4 1.8 + 1.9 +Additionally, the "on_crash" event can also take: 1.10 + 1.11 +=item B<coredump-destroy> 1.12 + 1.13 +Dump the crashed domain's core and then destroy it. 1.14 + 1.15 +=back 1.16 + 1.17 +=item B<coredump-restart> 1.18 + 1.19 +Dump the crashed domain's core and then restart it. 1.20 + 1.21 +=back 1.22 + 1.23 =head1 EXAMPLES 1.24 1.25 The following are quick examples of ways that domains might be
2.1 --- a/extras/mini-os/blkfront.c Thu Feb 07 09:23:26 2008 -0700 2.2 +++ b/extras/mini-os/blkfront.c Thu Feb 07 11:08:49 2008 -0700 2.3 @@ -35,6 +35,8 @@ struct blk_buffer { 2.4 }; 2.5 2.6 struct blkfront_dev { 2.7 + domid_t dom; 2.8 + 2.9 struct blkif_front_ring ring; 2.10 grant_ref_t ring_ref; 2.11 evtchn_port_t evtchn, local_port; 2.12 @@ -81,6 +83,15 @@ struct blkfront_dev *init_blkfront(char 2.13 dev = malloc(sizeof(*dev)); 2.14 dev->nodename = strdup(nodename); 2.15 2.16 + evtchn_alloc_unbound_t op; 2.17 + op.dom = DOMID_SELF; 2.18 + snprintf(path, sizeof(path), "%s/backend-id", nodename); 2.19 + dev->dom = op.remote_dom = xenbus_read_integer(path); 2.20 + HYPERVISOR_event_channel_op(EVTCHNOP_alloc_unbound, &op); 2.21 + clear_evtchn(op.port); /* Without, handler gets invoked now! */ 2.22 + dev->local_port = bind_evtchn(op.port, blkfront_handler, dev); 2.23 + dev->evtchn=op.port; 2.24 + 2.25 s = (struct blkif_sring*) alloc_page(); 2.26 memset(s,0,PAGE_SIZE); 2.27 2.28 @@ -88,16 +99,7 @@ struct blkfront_dev *init_blkfront(char 2.29 SHARED_RING_INIT(s); 2.30 FRONT_RING_INIT(&dev->ring, s, PAGE_SIZE); 2.31 2.32 - dev->ring_ref = gnttab_grant_access(0,virt_to_mfn(s),0); 2.33 - 2.34 - evtchn_alloc_unbound_t op; 2.35 - op.dom = DOMID_SELF; 2.36 - snprintf(path, sizeof(path), "%s/backend-id", nodename); 2.37 - op.remote_dom = xenbus_read_integer(path); 2.38 - HYPERVISOR_event_channel_op(EVTCHNOP_alloc_unbound, &op); 2.39 - clear_evtchn(op.port); /* Without, handler gets invoked now! */ 2.40 - dev->local_port = bind_evtchn(op.port, blkfront_handler, dev); 2.41 - dev->evtchn=op.port; 2.42 + dev->ring_ref = gnttab_grant_access(dev->dom,virt_to_mfn(s),0); 2.43 2.44 // FIXME: proper frees on failures 2.45 again: 2.46 @@ -256,7 +258,7 @@ void blkfront_aio(struct blkfront_aiocb 2.47 2.48 start = (uintptr_t)aiocbp->aio_buf & PAGE_MASK; 2.49 end = ((uintptr_t)aiocbp->aio_buf + aiocbp->aio_nbytes + PAGE_SIZE - 1) & PAGE_MASK; 2.50 - n = (end - start) / PAGE_SIZE; 2.51 + aiocbp->n = n = (end - start) / PAGE_SIZE; 2.52 2.53 /* qemu's IDE max multsect is 16 (8KB) and SCSI max DMA was set to 32KB, 2.54 * so max 44KB can't happen */ 2.55 @@ -280,7 +282,7 @@ void blkfront_aio(struct blkfront_aiocb 2.56 barrier(); 2.57 } 2.58 aiocbp->gref[j] = req->seg[j].gref = 2.59 - gnttab_grant_access(0, virtual_to_mfn(data), write); 2.60 + gnttab_grant_access(dev->dom, virtual_to_mfn(data), write); 2.61 req->seg[j].first_sect = 0; 2.62 req->seg[j].last_sect = PAGE_SIZE / dev->sector_size - 1; 2.63 } 2.64 @@ -325,8 +327,8 @@ moretodo: 2.65 case BLKIF_OP_WRITE: 2.66 { 2.67 struct blkfront_aiocb *aiocbp = (void*) (uintptr_t) rsp->id; 2.68 - int n = (aiocbp->aio_nbytes + PAGE_SIZE - 1) / PAGE_SIZE, j; 2.69 - for (j = 0; j < n; j++) 2.70 + int j; 2.71 + for (j = 0; j < aiocbp->n; j++) 2.72 gnttab_end_access(aiocbp->gref[j]); 2.73 2.74 /* Nota: callback frees aiocbp itself */
3.1 --- a/extras/mini-os/include/blkfront.h Thu Feb 07 09:23:26 2008 -0700 3.2 +++ b/extras/mini-os/include/blkfront.h Thu Feb 07 11:08:49 2008 -0700 3.3 @@ -11,6 +11,7 @@ struct blkfront_aiocb 3.4 void *data; 3.5 3.6 grant_ref_t gref[BLKIF_MAX_SEGMENTS_PER_REQUEST]; 3.7 + int n; 3.8 3.9 void (*aio_cb)(struct blkfront_aiocb *aiocb, int ret); 3.10 };
4.1 --- a/extras/mini-os/netfront.c Thu Feb 07 09:23:26 2008 -0700 4.2 +++ b/extras/mini-os/netfront.c Thu Feb 07 11:08:49 2008 -0700 4.3 @@ -33,6 +33,8 @@ struct net_buffer { 4.4 }; 4.5 4.6 struct netfront_dev { 4.7 + domid_t dom; 4.8 + 4.9 unsigned short tx_freelist[NET_TX_RING_SIZE]; 4.10 struct semaphore tx_sem; 4.11 4.12 @@ -141,7 +143,7 @@ moretodo: 4.13 4.14 /* We are sure to have free gnttab entries since they got released above */ 4.15 buf->gref = req->gref = 4.16 - gnttab_grant_access(0,virt_to_mfn(page),0); 4.17 + gnttab_grant_access(dev->dom,virt_to_mfn(page),0); 4.18 4.19 req->id = id; 4.20 } 4.21 @@ -258,6 +260,15 @@ struct netfront_dev *init_netfront(char 4.22 dev->rx_buffers[i].page = (char*)alloc_page(); 4.23 } 4.24 4.25 + evtchn_alloc_unbound_t op; 4.26 + op.dom = DOMID_SELF; 4.27 + snprintf(path, sizeof(path), "%s/backend-id", nodename); 4.28 + dev->dom = op.remote_dom = xenbus_read_integer(path); 4.29 + HYPERVISOR_event_channel_op(EVTCHNOP_alloc_unbound, &op); 4.30 + clear_evtchn(op.port); /* Without, handler gets invoked now! */ 4.31 + dev->local_port = bind_evtchn(op.port, netfront_handler, dev); 4.32 + dev->evtchn=op.port; 4.33 + 4.34 txs = (struct netif_tx_sring*) alloc_page(); 4.35 rxs = (struct netif_rx_sring *) alloc_page(); 4.36 memset(txs,0,PAGE_SIZE); 4.37 @@ -269,17 +280,8 @@ struct netfront_dev *init_netfront(char 4.38 FRONT_RING_INIT(&dev->tx, txs, PAGE_SIZE); 4.39 FRONT_RING_INIT(&dev->rx, rxs, PAGE_SIZE); 4.40 4.41 - dev->tx_ring_ref = gnttab_grant_access(0,virt_to_mfn(txs),0); 4.42 - dev->rx_ring_ref = gnttab_grant_access(0,virt_to_mfn(rxs),0); 4.43 - 4.44 - evtchn_alloc_unbound_t op; 4.45 - op.dom = DOMID_SELF; 4.46 - snprintf(path, sizeof(path), "%s/backend-id", nodename); 4.47 - op.remote_dom = xenbus_read_integer(path); 4.48 - HYPERVISOR_event_channel_op(EVTCHNOP_alloc_unbound, &op); 4.49 - clear_evtchn(op.port); /* Without, handler gets invoked now! */ 4.50 - dev->local_port = bind_evtchn(op.port, netfront_handler, dev); 4.51 - dev->evtchn=op.port; 4.52 + dev->tx_ring_ref = gnttab_grant_access(dev->dom,virt_to_mfn(txs),0); 4.53 + dev->rx_ring_ref = gnttab_grant_access(dev->dom,virt_to_mfn(rxs),0); 4.54 4.55 dev->netif_rx = thenetif_rx; 4.56 4.57 @@ -416,7 +418,7 @@ void init_rx_buffers(struct netfront_dev 4.58 req = RING_GET_REQUEST(&dev->rx, requeue_idx); 4.59 4.60 buf->gref = req->gref = 4.61 - gnttab_grant_access(0,virt_to_mfn(buf->page),0); 4.62 + gnttab_grant_access(dev->dom,virt_to_mfn(buf->page),0); 4.63 4.64 req->id = requeue_idx; 4.65 4.66 @@ -461,7 +463,7 @@ void netfront_xmit(struct netfront_dev * 4.67 memcpy(page,data,len); 4.68 4.69 buf->gref = 4.70 - tx->gref = gnttab_grant_access(0,virt_to_mfn(page),0); 4.71 + tx->gref = gnttab_grant_access(dev->dom,virt_to_mfn(page),1); 4.72 4.73 tx->offset=0; 4.74 tx->size = len;
5.1 --- a/tools/examples/xmexample.hvm Thu Feb 07 09:23:26 2008 -0700 5.2 +++ b/tools/examples/xmexample.hvm Thu Feb 07 11:08:49 2008 -0700 5.3 @@ -87,6 +87,11 @@ disk = [ 'file:/var/images/min-el3-i386. 5.4 # "rename-restart", meaning that the old domain is not cleaned up, but is 5.5 # renamed and a new domain started in its place. 5.6 # 5.7 +# In the event a domain stops due to a crash, you have the additional options: 5.8 +# 5.9 +# "coredump-destroy", meaning dump the crashed domain's core and then destroy; 5.10 +# "coredump-restart', meaning dump the crashed domain's core and the restart. 5.11 +# 5.12 # The default is 5.13 # 5.14 # on_poweroff = 'destroy'
6.1 --- a/tools/examples/xmexample1 Thu Feb 07 09:23:26 2008 -0700 6.2 +++ b/tools/examples/xmexample1 Thu Feb 07 11:08:49 2008 -0700 6.3 @@ -155,6 +155,11 @@ extra = "4" 6.4 # "rename-restart", meaning that the old domain is not cleaned up, but is 6.5 # renamed and a new domain started in its place. 6.6 # 6.7 +# In the event a domain stops due to a crash, you have the additional options: 6.8 +# 6.9 +# "coredump-destroy", meaning dump the crashed domain's core and then destroy; 6.10 +# "coredump-restart', meaning dump the crashed domain's core and the restart. 6.11 +# 6.12 # The default is 6.13 # 6.14 # on_poweroff = 'destroy'
7.1 --- a/tools/examples/xmexample2 Thu Feb 07 09:23:26 2008 -0700 7.2 +++ b/tools/examples/xmexample2 Thu Feb 07 11:08:49 2008 -0700 7.3 @@ -191,6 +191,11 @@ extra = "4 VMID=%d usr=/dev/sda6" % vmid 7.4 # "rename-restart", meaning that the old domain is not cleaned up, but is 7.5 # renamed and a new domain started in its place. 7.6 # 7.7 +# In the event a domain stops due to a crash, you have the additional options: 7.8 +# 7.9 +# "coredump-destroy", meaning dump the crashed domain's core and then destroy; 7.10 +# "coredump-restart', meaning dump the crashed domain's core and the restart. 7.11 +# 7.12 # The default is 7.13 # 7.14 # on_poweroff = 'destroy'
8.1 --- a/tools/examples/xmexample3 Thu Feb 07 09:23:26 2008 -0700 8.2 +++ b/tools/examples/xmexample3 Thu Feb 07 11:08:49 2008 -0700 8.3 @@ -177,6 +177,11 @@ extra = "4 VMID=%d" % vmid 8.4 # "rename-restart", meaning that the old domain is not cleaned up, but is 8.5 # renamed and a new domain started in its place. 8.6 # 8.7 +# In the event a domain stops due to a crash, you have the additional options: 8.8 +# 8.9 +# "coredump-destroy", meaning dump the crashed domain's core and then destroy; 8.10 +# "coredump-restart', meaning dump the crashed domain's core and the restart. 8.11 +# 8.12 # The default is 8.13 # 8.14 # on_poweroff = 'destroy'
9.1 --- a/tools/firmware/Makefile Thu Feb 07 09:23:26 2008 -0700 9.2 +++ b/tools/firmware/Makefile Thu Feb 07 11:08:49 2008 -0700 9.3 @@ -9,7 +9,6 @@ INST_DIR := $(DESTDIR)/usr/lib/xen/boot 9.4 SUBDIRS := 9.5 SUBDIRS += rombios rombios/32bit 9.6 SUBDIRS += vgabios 9.7 -SUBDIRS += vmxassist 9.8 SUBDIRS += extboot 9.9 #SUBDIRS += etherboot 9.10 SUBDIRS += hvmloader
10.1 --- a/tools/firmware/README Thu Feb 07 09:23:26 2008 -0700 10.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 10.3 @@ -1,88 +0,0 @@ 10.4 -Domain firmware support 10.5 ------------------------ 10.6 - 10.7 -One of the key advantages of full virtualization hardware support (such 10.8 -as Intel's VT or AMD's SVM extensions) is the ability to run unmodified 10.9 -guest operating systems. However, since most OSes rely on BIOS support 10.10 -during their early bringup, we need to provide a surrogate ROMBIOS and 10.11 -VGABIOS firmware layer. 10.12 - 10.13 -What's more, we need to support real-mode which is required by 10.14 -the firmware and bootstrap loaders. Real-mode support is especially 10.15 -challenging for Intel's VMX (VT) enabled CPUs where there is no real-mode 10.16 -support for VMX guest partitions. In this case you either have to do full 10.17 -emulation (full real-mode emulator; more complete but potentially slower) 10.18 -or partial emulation (use the VM8086 extensions, emulate only those 10.19 -instructions that are missing; faster, but potentially incomplete). The 10.20 -vmxassist code in this subdirectory uses the later approach because it 10.21 -is smaller and faster. 10.22 - 10.23 -The approach is relatively straight forward. Vmxloader contains three 10.24 -payloads (rombios, vgabios and vmxassist) and it is bootstrapped as any 10.25 -other 32-bit OS. Vmxloader copies its payloads to the addresses below 10.26 -and transfers control to vmxassist. 10.27 - 10.28 - vgabios VGABIOS (standard and Cirrus). 10.29 - Resides at C000:0000. 10.30 - 10.31 - vmxassist VMXAssist VM86 realmode emulator for VMX. 10.32 - Resides at D000:0000. 10.33 - 10.34 - rombios ROMBIOS code. Derived from Bochs. 10.35 - Resides at F000:0000 10.36 - 10.37 -Vmxassist first sets up it own world (GDT, IDT, TR, etc), enables 10.38 -VM8086 and then transfers control to F000:FFF0 and executes 16-bit 10.39 -code. Unsupported instructions cause a general protection failure at 10.40 -which point vmxassist kicks in and emulates the offending instruction. 10.41 -Whever the emulated code transitions to 32-bit protected mode, vmxassist 10.42 -will go away. Whenever 32-bit protected code transitions to real-mode, 10.43 -Xen/VMX will detect this and transfer control to vmxassist. 10.44 - 10.45 -Most of the vmxassist complexity comes from properly handling the 10.46 -real to protected mode and protected to real mode transitions and 10.47 -the proper emulation of the segment registers. Even though the Intel 10.48 -manual clearly states that you should immediately perform a jmp far 10.49 -after a mode transition, many operating systems execute additional 10.50 -instructions and some even refer to segment selectors and pop data 10.51 -from the stack. Vmxassist contains a number of work arounds for these 10.52 -OSes. 10.53 - 10.54 - 10.55 -Acknowledgements 10.56 ----------------- 10.57 - 10.58 -The rombios was taken (largely unmodified) from Bochs, which was written 10.59 -by Kevin Lawton. The VGABIOS was written by Christophe Bothamy. Arun Sharma, 10.60 -Asit Mallick and Nitin Kamble (Intel) provided the E820 patches and lots 10.61 -of useful feedback. 10.62 - 10.63 - 10.64 -Contact 10.65 -------- 10.66 - 10.67 -Leendert van Doorn 10.68 -IBM T.J. Watson Research Center 10.69 -19 Skyline Drive 10.70 -Hawthorne, NY 10532 10.71 -leendert@watson.ibm.com 10.72 - 10.73 - 10.74 -Tested Operating Systems 10.75 ------------------------- 10.76 - 10.77 -Since vmxassist uses partial emulation, it may always miss opcodes 10.78 -that are required by a particular OS. The table below lists the OSes 10.79 -I have tried. The Install column indicates a full CD/DVD install into 10.80 -a VMX partition. The Disk column indicates booting from prefabricated 10.81 -disk image. 10.82 - 10.83 -Operating System Install Disk 10.84 ------------------------------------------------------------- 10.85 -RedHat Enterprise Linux (RHEL3_U5) Yes Yes 10.86 -Fedora Code (FC3) (-) Yes 10.87 -FreeBSD 5.3 (-) Yes 10.88 -MS-DOS 5.0 (-) Yes 10.89 - 10.90 -(-) not tried yet 10.91 -
11.1 --- a/tools/firmware/hvmloader/Makefile Thu Feb 07 09:23:26 2008 -0700 11.2 +++ b/tools/firmware/hvmloader/Makefile Thu Feb 07 11:08:49 2008 -0700 11.3 @@ -50,11 +50,10 @@ hvmloader: roms.h acpi/acpi.a $(SRCS) 11.4 acpi/acpi.a: 11.5 $(MAKE) -C acpi 11.6 11.7 -roms.h: ../rombios/BIOS-bochs-latest ../vgabios/VGABIOS-lgpl-latest.bin ../vgabios/VGABIOS-lgpl-latest.cirrus.bin ../vmxassist/vmxassist.bin ../etherboot/eb-roms.h ../extboot/extboot.bin 11.8 +roms.h: ../rombios/BIOS-bochs-latest ../vgabios/VGABIOS-lgpl-latest.bin ../vgabios/VGABIOS-lgpl-latest.cirrus.bin ../etherboot/eb-roms.h ../extboot/extboot.bin 11.9 sh ./mkhex rombios ../rombios/BIOS-bochs-latest > roms.h 11.10 sh ./mkhex vgabios_stdvga ../vgabios/VGABIOS-lgpl-latest.bin >> roms.h 11.11 sh ./mkhex vgabios_cirrusvga ../vgabios/VGABIOS-lgpl-latest.cirrus.bin >> roms.h 11.12 - sh ./mkhex vmxassist ../vmxassist/vmxassist.bin >> roms.h 11.13 cat ../etherboot/eb-roms.h >> roms.h 11.14 sh ./mkhex extboot ../extboot/extboot.bin >> roms.h 11.15
12.1 --- a/tools/firmware/hvmloader/config.h Thu Feb 07 09:23:26 2008 -0700 12.2 +++ b/tools/firmware/hvmloader/config.h Thu Feb 07 11:08:49 2008 -0700 12.3 @@ -21,7 +21,6 @@ 12.4 #define HYPERCALL_PHYSICAL_ADDRESS 0x00080000 12.5 #define VGABIOS_PHYSICAL_ADDRESS 0x000C0000 12.6 #define ETHERBOOT_PHYSICAL_ADDRESS 0x000C8000 12.7 -#define VMXASSIST_PHYSICAL_ADDRESS 0x000D0000 12.8 #define EXTBOOT_PHYSICAL_ADDRESS 0x000DF800 12.9 #define SMBIOS_PHYSICAL_ADDRESS 0x000E9000 12.10 #define SMBIOS_MAXIMUM_SIZE 0x00001000
13.1 --- a/tools/firmware/hvmloader/hvmloader.c Thu Feb 07 09:23:26 2008 -0700 13.2 +++ b/tools/firmware/hvmloader/hvmloader.c Thu Feb 07 11:08:49 2008 -0700 13.3 @@ -1,5 +1,5 @@ 13.4 /* 13.5 - * hvmloader.c: HVM ROMBIOS/VGABIOS/ACPI/VMXAssist image loader. 13.6 + * hvmloader.c: HVM bootloader. 13.7 * 13.8 * Leendert van Doorn, leendert@watson.ibm.com 13.9 * Copyright (c) 2005, International Business Machines Corporation. 13.10 @@ -40,7 +40,6 @@ asm( 13.11 " cli \n" 13.12 " movl $stack_top,%esp \n" 13.13 " movl %esp,%ebp \n" 13.14 - " movl %eax,initial_eax \n" 13.15 " call main \n" 13.16 /* Relocate real-mode trampoline to 0x0. */ 13.17 " mov $trampoline_start,%esi \n" 13.18 @@ -98,8 +97,6 @@ asm( 13.19 "stack_top: \n" 13.20 ); 13.21 13.22 -static unsigned int initial_eax; 13.23 - 13.24 void create_mp_tables(void); 13.25 int hvm_write_smbios_tables(void); 13.26 13.27 @@ -110,26 +107,6 @@ cirrus_check(void) 13.28 return inb(0x3C5) == 0x12; 13.29 } 13.30 13.31 -static int 13.32 -check_amd(void) 13.33 -{ 13.34 - char id[12]; 13.35 - 13.36 - __asm__ __volatile__ ( 13.37 - "cpuid" 13.38 - : "=b" (*(int *)(&id[0])), 13.39 - "=c" (*(int *)(&id[8])), 13.40 - "=d" (*(int *)(&id[4])) 13.41 - : "a" (0) ); 13.42 - return __builtin_memcmp(id, "AuthenticAMD", 12) == 0; 13.43 -} 13.44 - 13.45 -static int 13.46 -use_vmxassist(void) 13.47 -{ 13.48 - return !check_amd() && !initial_eax; 13.49 -} 13.50 - 13.51 static void 13.52 wrmsr(uint32_t idx, uint64_t v) 13.53 { 13.54 @@ -506,10 +483,6 @@ int main(void) 13.55 printf(" %05x-%05x: Extboot ROM\n", 13.56 EXTBOOT_PHYSICAL_ADDRESS, 13.57 EXTBOOT_PHYSICAL_ADDRESS + extboot_sz - 1); 13.58 - if ( use_vmxassist() ) 13.59 - printf(" %05x-%05x: VMXAssist\n", 13.60 - VMXASSIST_PHYSICAL_ADDRESS, 13.61 - VMXASSIST_PHYSICAL_ADDRESS + sizeof(vmxassist) - 1); 13.62 if ( smbios_sz ) 13.63 printf(" %05x-%05x: SMBIOS tables\n", 13.64 SMBIOS_PHYSICAL_ADDRESS, 13.65 @@ -523,19 +496,6 @@ int main(void) 13.66 ROMBIOS_PHYSICAL_ADDRESS, 13.67 ROMBIOS_PHYSICAL_ADDRESS + rombios_sz - 1); 13.68 13.69 - if ( use_vmxassist() ) 13.70 - { 13.71 - printf("Loading VMXAssist ...\n"); 13.72 - memcpy((void *)VMXASSIST_PHYSICAL_ADDRESS, 13.73 - vmxassist, sizeof(vmxassist)); 13.74 - 13.75 - printf("VMX go ...\n"); 13.76 - __asm__ __volatile__( 13.77 - "jmp *%%eax" 13.78 - : : "a" (VMXASSIST_PHYSICAL_ADDRESS), "d" (0) 13.79 - ); 13.80 - } 13.81 - 13.82 printf("Invoking ROMBIOS ...\n"); 13.83 return 0; 13.84 }
14.1 --- a/tools/firmware/vmxassist/Makefile Thu Feb 07 09:23:26 2008 -0700 14.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 14.3 @@ -1,81 +0,0 @@ 14.4 -# 14.5 -# Makefile 14.6 -# 14.7 -# Leendert van Doorn, leendert@watson.ibm.com 14.8 -# Copyright (c) 2005, International Business Machines Corporation. 14.9 -# 14.10 -# This program is free software; you can redistribute it and/or modify it 14.11 -# under the terms and conditions of the GNU General Public License, 14.12 -# version 2, as published by the Free Software Foundation. 14.13 -# 14.14 -# This program is distributed in the hope it will be useful, but WITHOUT 14.15 -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14.16 -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 14.17 -# more details. 14.18 -# 14.19 -# You should have received a copy of the GNU General Public License along with 14.20 -# this program; if not, write to the Free Software Foundation, Inc., 59 Temple 14.21 -# Place - Suite 330, Boston, MA 02111-1307 USA. 14.22 -# 14.23 - 14.24 -# External CFLAGS can do more harm than good. 14.25 -CFLAGS := 14.26 - 14.27 -override XEN_TARGET_ARCH = x86_32 14.28 -XEN_ROOT = ../../.. 14.29 -include $(XEN_ROOT)/tools/Rules.mk 14.30 - 14.31 -# The emulator code lives in ROM space 14.32 -TEXTADDR=0x000D0000 14.33 - 14.34 -DEFINES=-DDEBUG -DTEXTADDR=$(TEXTADDR) 14.35 -XENINC=$(CFLAGS_include) 14.36 - 14.37 -# Disable PIE/SSP if GCC supports them. They can break us. 14.38 -CFLAGS += $(call cc-option,$(CC),-nopie,) 14.39 -CFLAGS += $(call cc-option,$(CC),-fno-stack-protector,) 14.40 -CFLAGS += $(call cc-option,$(CC),-fno-stack-protector-all,) 14.41 - 14.42 -CPP = cpp -P 14.43 -CFLAGS += $(DEFINES) -I. $(XENINC) -fno-builtin -O2 -msoft-float 14.44 - 14.45 -OBJECTS = head.o trap.o vm86.o setup.o util.o 14.46 - 14.47 -.PHONY: all 14.48 -all: vmxassist.bin 14.49 - 14.50 -vmxassist.bin: vmxassist.ld $(OBJECTS) 14.51 - $(CPP) $(DEFINES) vmxassist.ld > vmxassist.tmp 14.52 - $(LD) -o vmxassist $(LDFLAGS_DIRECT) --fatal-warnings -N -T vmxassist.tmp $(OBJECTS) 14.53 - nm -n vmxassist > vmxassist.sym 14.54 - $(OBJCOPY) -p -O binary -R .note -R .comment -R .bss -S --gap-fill=0 vmxassist vmxassist.tmp 14.55 - dd if=vmxassist.tmp of=vmxassist.bin ibs=512 conv=sync 14.56 - rm -f vmxassist.tmp 14.57 - 14.58 -head.o: machine.h vm86.h head.S 14.59 - $(CC) $(CFLAGS) -D__ASSEMBLY__ $(DEFINES) -c head.S 14.60 - 14.61 -trap.o: machine.h vm86.h offsets.h trap.S 14.62 - $(CC) $(CFLAGS) -D__ASSEMBLY__ $(DEFINES) -c trap.S 14.63 - 14.64 -vm86.o: machine.h vm86.h vm86.c 14.65 - $(CC) $(CFLAGS) -c vm86.c 14.66 - 14.67 -setup.o: machine.h vm86.h setup.c 14.68 - $(CC) $(CFLAGS) -c setup.c 14.69 - 14.70 -util.o: machine.h vm86.h util.c 14.71 - $(CC) $(CFLAGS) -c util.c 14.72 - 14.73 -offsets.h: gen 14.74 - ./gen > offsets.h 14.75 - 14.76 -gen: vm86.h gen.c 14.77 - $(HOSTCC) $(HOSTCFLAGS) -I. $(XENINC) -o gen gen.c 14.78 - 14.79 -.PHONY: clean 14.80 -clean: 14.81 - rm -f vmxassist vmxassist.tmp vmxassist.bin vmxassist.run vmxassist.sym head.s 14.82 - rm -f $(OBJECTS) 14.83 - rm -f gen gen.o offsets.h 14.84 -
15.1 --- a/tools/firmware/vmxassist/gen.c Thu Feb 07 09:23:26 2008 -0700 15.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 15.3 @@ -1,52 +0,0 @@ 15.4 -/* 15.5 - * gen.c: Generate assembler symbols. 15.6 - * 15.7 - * Leendert van Doorn, leendert@watson.ibm.com 15.8 - * Copyright (c) 2005, International Business Machines Corporation. 15.9 - * 15.10 - * This program is free software; you can redistribute it and/or modify it 15.11 - * under the terms and conditions of the GNU General Public License, 15.12 - * version 2, as published by the Free Software Foundation. 15.13 - * 15.14 - * This program is distributed in the hope it will be useful, but WITHOUT 15.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 15.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 15.17 - * more details. 15.18 - * 15.19 - * You should have received a copy of the GNU General Public License along with 15.20 - * this program; if not, write to the Free Software Foundation, Inc., 59 Temple 15.21 - * Place - Suite 330, Boston, MA 02111-1307 USA. 15.22 - */ 15.23 -#include <stdio.h> 15.24 -#include <stddef.h> 15.25 -#include <stdlib.h> 15.26 -#include <vm86.h> 15.27 - 15.28 -int 15.29 -main(void) 15.30 -{ 15.31 - printf("/* MACHINE GENERATED; DO NOT EDIT */\n"); 15.32 - printf("#define VMX_ASSIST_CTX_GS_SEL 0x%x\n", 15.33 - (unsigned int)offsetof(struct vmx_assist_context, gs_sel)); 15.34 - printf("#define VMX_ASSIST_CTX_FS_SEL 0x%x\n", 15.35 - (unsigned int)offsetof(struct vmx_assist_context, fs_sel)); 15.36 - printf("#define VMX_ASSIST_CTX_DS_SEL 0x%x\n", 15.37 - (unsigned int)offsetof(struct vmx_assist_context, ds_sel)); 15.38 - printf("#define VMX_ASSIST_CTX_ES_SEL 0x%x\n", 15.39 - (unsigned int)offsetof(struct vmx_assist_context, es_sel)); 15.40 - printf("#define VMX_ASSIST_CTX_SS_SEL 0x%x\n", 15.41 - (unsigned int)offsetof(struct vmx_assist_context, ss_sel)); 15.42 - printf("#define VMX_ASSIST_CTX_ESP 0x%x\n", 15.43 - (unsigned int)offsetof(struct vmx_assist_context, esp)); 15.44 - printf("#define VMX_ASSIST_CTX_EFLAGS 0x%x\n", 15.45 - (unsigned int)offsetof(struct vmx_assist_context, eflags)); 15.46 - printf("#define VMX_ASSIST_CTX_CS_SEL 0x%x\n", 15.47 - (unsigned int)offsetof(struct vmx_assist_context, cs_sel)); 15.48 - printf("#define VMX_ASSIST_CTX_EIP 0x%x\n", 15.49 - (unsigned int)offsetof(struct vmx_assist_context, eip)); 15.50 - 15.51 - printf("#define VMX_ASSIST_CTX_CR0 0x%x\n", 15.52 - (unsigned int)offsetof(struct vmx_assist_context, cr0)); 15.53 - 15.54 - return 0; 15.55 -}
16.1 --- a/tools/firmware/vmxassist/head.S Thu Feb 07 09:23:26 2008 -0700 16.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 16.3 @@ -1,94 +0,0 @@ 16.4 -/* 16.5 - * head.S: VMXAssist runtime start off. 16.6 - * 16.7 - * Leendert van Doorn, leendert@watson.ibm.com 16.8 - * Copyright (c) 2005, International Business Machines Corporation. 16.9 - * 16.10 - * This program is free software; you can redistribute it and/or modify it 16.11 - * under the terms and conditions of the GNU General Public License, 16.12 - * version 2, as published by the Free Software Foundation. 16.13 - * 16.14 - * This program is distributed in the hope it will be useful, but WITHOUT 16.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 16.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 16.17 - * more details. 16.18 - * 16.19 - * You should have received a copy of the GNU General Public License along with 16.20 - * this program; if not, write to the Free Software Foundation, Inc., 59 Temple 16.21 - * Place - Suite 330, Boston, MA 02111-1307 USA. 16.22 - */ 16.23 -#include "vm86.h" 16.24 -#include "machine.h" 16.25 - 16.26 -/* 16.27 - * When a partition tries to mask off the CR0_PE bit a world 16.28 - * switch happens to the environment below. The magic indicates 16.29 - * that this is a valid context. 16.30 - */ 16.31 - jmp _start 16.32 - 16.33 - .align 8 16.34 - .long VMXASSIST_MAGIC 16.35 - .long newctx /* new context */ 16.36 - .long oldctx /* old context */ 16.37 - 16.38 -/* 16.39 - * This is the real start. Control was transfered to this point 16.40 - * with CR0_PE set and executing in some 32-bit segment. We call 16.41 - * main and setup our own environment. 16.42 - */ 16.43 - .globl _start 16.44 - .code32 16.45 -_start: 16.46 - cli 16.47 - 16.48 - /* save register parameters to C land */ 16.49 - 16.50 - /* clear bss */ 16.51 - cld 16.52 - xorb %al, %al 16.53 - movl $_bbss, %edi 16.54 - movl $_ebss, %ecx 16.55 - subl %edi, %ecx 16.56 - rep stosb 16.57 - 16.58 - movl %edx, booting_cpu 16.59 - movl %ebx, booting_vector 16.60 - 16.61 - /* make sure we are in a sane world */ 16.62 - clts 16.63 - 16.64 - /* setup my own stack */ 16.65 - movl $stack_top, %esp 16.66 - movl %esp, %ebp 16.67 - 16.68 - /* go ... */ 16.69 - call main 16.70 - jmp halt 16.71 - 16.72 -/* 16.73 - * Something bad happened, print invoking %eip and loop forever 16.74 - */ 16.75 - .align 4 16.76 - .globl halt 16.77 -halt: 16.78 - push $halt_msg 16.79 - call printf 16.80 - cli 16.81 - jmp . 16.82 - 16.83 - .data 16.84 -halt_msg: 16.85 - .asciz "Halt called from %%eip 0x%x\n" 16.86 - 16.87 - 16.88 -/* 16.89 - * Our stack 16.90 - */ 16.91 - .bss 16.92 - .align 8 16.93 - .globl stack, stack_top 16.94 -stack: 16.95 - .skip STACK_SIZE 16.96 -stack_top: 16.97 -
17.1 --- a/tools/firmware/vmxassist/machine.h Thu Feb 07 09:23:26 2008 -0700 17.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 17.3 @@ -1,199 +0,0 @@ 17.4 -/* 17.5 - * machine.h: Intel CPU specific definitions 17.6 - * 17.7 - * Leendert van Doorn, leendert@watson.ibm.com 17.8 - * Copyright (c) 2005, International Business Machines Corporation. 17.9 - * 17.10 - * This program is free software; you can redistribute it and/or modify it 17.11 - * under the terms and conditions of the GNU General Public License, 17.12 - * version 2, as published by the Free Software Foundation. 17.13 - * 17.14 - * This program is distributed in the hope it will be useful, but WITHOUT 17.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 17.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 17.17 - * more details. 17.18 - * 17.19 - * You should have received a copy of the GNU General Public License along with 17.20 - * this program; if not, write to the Free Software Foundation, Inc., 59 Temple 17.21 - * Place - Suite 330, Boston, MA 02111-1307 USA. 17.22 - */ 17.23 -#ifndef __MACHINE_H__ 17.24 -#define __MACHINE_H__ 17.25 - 17.26 -/* the size of our stack (4KB) */ 17.27 -#define STACK_SIZE 8192 17.28 - 17.29 -#define TSS_SELECTOR 0x08 17.30 -#define CODE_SELECTOR 0x10 17.31 -#define DATA_SELECTOR 0x18 17.32 - 17.33 -#define CR0_PE (1 << 0) 17.34 -#define CR0_EM (1 << 2) 17.35 -#define CR0_TS (1 << 3) 17.36 -#define CR0_NE (1 << 5) 17.37 -#define CR0_PG (1 << 31) 17.38 - 17.39 -#define CR4_VME (1 << 0) 17.40 -#define CR4_PVI (1 << 1) 17.41 -#define CR4_PSE (1 << 4) 17.42 -#define CR4_PAE (1 << 5) 17.43 - 17.44 -#define EFLAGS_CF (1 << 0) 17.45 -#define EFLAGS_PF (1 << 2) 17.46 -#define EFLAGS_AF (1 << 4) 17.47 -#define EFLAGS_ZF (1 << 6) 17.48 -#define EFLAGS_SF (1 << 7) 17.49 -#define EFLAGS_TF (1 << 8) 17.50 -#define EFLAGS_IF (1 << 9) 17.51 -#define EFLAGS_DF (1 << 10) 17.52 -#define EFLAGS_OF (1 << 11) 17.53 -#define EFLAGS_IOPL (3 << 12) 17.54 -#define EFLAGS_VM ((1 << 17) | EFLAGS_IOPL) 17.55 -#define EFLAGS_VIF (1 << 19) 17.56 -#define EFLAGS_VIP (1 << 20) 17.57 - 17.58 -#define LOG_PGSIZE 12 /* log2(page size) */ 17.59 -#define LOG_PDSIZE 22 /* log2(page directory size) */ 17.60 - 17.61 -/* Derived constants */ 17.62 -#define PGSIZE (1 << LOG_PGSIZE) /* page size */ 17.63 -#define PGMASK (~(PGSIZE - 1)) /* page mask */ 17.64 -#define LPGSIZE (1 << LOG_PDSIZE) /* large page size */ 17.65 -#define LPGMASK (~(LPGSIZE - 1)) /* large page mask */ 17.66 - 17.67 -/* Programmable Interrupt Contoller (PIC) defines */ 17.68 -#define PIC_MASTER 0x20 17.69 -#define PIC_SLAVE 0xA0 17.70 - 17.71 -#define PIC_CMD 0 /* command */ 17.72 -#define PIC_ISR 0 /* interrupt status */ 17.73 -#define PIC_IMR 1 /* interrupt mask */ 17.74 - 17.75 - 17.76 -#ifndef __ASSEMBLY__ 17.77 - 17.78 -struct dtr { 17.79 - unsigned short size; 17.80 - unsigned long base __attribute__ ((packed)); 17.81 -}; 17.82 - 17.83 -struct tss { 17.84 - unsigned short prev_link; 17.85 - unsigned short _1; 17.86 - unsigned long esp0; 17.87 - unsigned short ss0; 17.88 - unsigned short _2; 17.89 - unsigned long esp1; 17.90 - unsigned short ss1; 17.91 - unsigned short _3; 17.92 - unsigned long esp2; 17.93 - unsigned short ss2; 17.94 - unsigned short _4; 17.95 - unsigned long cr3; 17.96 - unsigned long eip; 17.97 - unsigned long eflags; 17.98 - unsigned long eax; 17.99 - unsigned long ecx; 17.100 - unsigned long edx; 17.101 - unsigned long ebx; 17.102 - unsigned long esi; 17.103 - unsigned long edi; 17.104 - unsigned long esp; 17.105 - unsigned long ebp; 17.106 - unsigned long es; 17.107 - unsigned long cs; 17.108 - unsigned long ss; 17.109 - unsigned long ds; 17.110 - unsigned long fs; 17.111 - unsigned long gs; 17.112 - unsigned short ldt_segment; 17.113 - unsigned short _5; 17.114 - unsigned short _6; 17.115 - unsigned short iomap_base; 17.116 -#ifdef ENABLE_VME 17.117 - unsigned long int_redir[8]; 17.118 -#endif 17.119 - unsigned char iomap[8193]; 17.120 -}; 17.121 - 17.122 -static inline void 17.123 -outw(unsigned short addr, unsigned short val) 17.124 -{ 17.125 - __asm__ __volatile__ ("outw %%ax, %%dx" :: "d"(addr), "a"(val)); 17.126 -} 17.127 - 17.128 -static inline void 17.129 -outb(unsigned short addr, unsigned char val) 17.130 -{ 17.131 - __asm__ __volatile__ ("outb %%al, %%dx" :: "d"(addr), "a"(val)); 17.132 -} 17.133 - 17.134 -static inline unsigned char 17.135 -inb(unsigned short addr) 17.136 -{ 17.137 - unsigned char val; 17.138 - 17.139 - __asm__ __volatile__ ("inb %w1,%0" : "=a" (val) : "Nd" (addr)); 17.140 - return val; 17.141 -} 17.142 - 17.143 -static inline unsigned 17.144 -get_cmos(int reg) 17.145 -{ 17.146 - outb(0x70, reg); 17.147 - return inb(0x71); 17.148 -} 17.149 - 17.150 -static inline unsigned 17.151 -get_cr0(void) 17.152 -{ 17.153 - unsigned rv; 17.154 - __asm__ __volatile__("movl %%cr0, %0" : "=r"(rv)); 17.155 - return rv; 17.156 -} 17.157 - 17.158 -static inline void 17.159 -set_cr0(unsigned value) 17.160 -{ 17.161 - __asm__ __volatile__( 17.162 - "movl %0, %%cr0\n" 17.163 - "jmp 1f\n" 17.164 - "1: nop\n" 17.165 - : /* no outputs */ 17.166 - : "r"(value) 17.167 - ); 17.168 -} 17.169 - 17.170 -static inline unsigned 17.171 -get_cr2(void) 17.172 -{ 17.173 - unsigned rv; 17.174 - 17.175 - __asm__ __volatile__("movl %%cr2, %0" : "=r"(rv)); 17.176 - return rv; 17.177 -} 17.178 - 17.179 -static inline unsigned 17.180 -get_cr4(void) 17.181 -{ 17.182 - unsigned rv; 17.183 - __asm__ __volatile__("movl %%cr4, %0" : "=r"(rv)); 17.184 - return rv; 17.185 -} 17.186 - 17.187 -static inline void 17.188 -set_cr3(unsigned addr) 17.189 -{ 17.190 - __asm__ __volatile__("movl %0, %%cr3" : /* no outputs */ : "r"(addr)); 17.191 -} 17.192 - 17.193 -static inline void 17.194 -set_cr4(unsigned value) 17.195 -{ 17.196 - __asm__ __volatile__("movl %0, %%cr4" : /* no outputs */ : "r"(value)); 17.197 -} 17.198 - 17.199 -#endif /* __ASSEMBLY__ */ 17.200 - 17.201 -#endif /* __MACHINE_H__ */ 17.202 -
18.1 --- a/tools/firmware/vmxassist/setup.c Thu Feb 07 09:23:26 2008 -0700 18.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 18.3 @@ -1,337 +0,0 @@ 18.4 -/* 18.5 - * setup.c: Setup the world for vmxassist. 18.6 - * 18.7 - * Leendert van Doorn, leendert@watson.ibm.com 18.8 - * Copyright (c) 2005, International Business Machines Corporation. 18.9 - * 18.10 - * This program is free software; you can redistribute it and/or modify it 18.11 - * under the terms and conditions of the GNU General Public License, 18.12 - * version 2, as published by the Free Software Foundation. 18.13 - * 18.14 - * This program is distributed in the hope it will be useful, but WITHOUT 18.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 18.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 18.17 - * more details. 18.18 - * 18.19 - * You should have received a copy of the GNU General Public License along with 18.20 - * this program; if not, write to the Free Software Foundation, Inc., 59 Temple 18.21 - * Place - Suite 330, Boston, MA 02111-1307 USA. 18.22 - */ 18.23 -#include "vm86.h" 18.24 -#include "util.h" 18.25 -#include "machine.h" 18.26 - 18.27 -#if (VMXASSIST_BASE != TEXTADDR) 18.28 -#error VMXAssist base mismatch 18.29 -#endif 18.30 - 18.31 -#define NR_PGD (PGSIZE / sizeof(unsigned)) 18.32 - 18.33 -#define min(a, b) ((a) > (b) ? (b) : (a)) 18.34 - 18.35 -/* Which CPU are we booting, and what is the initial CS segment? */ 18.36 -int booting_cpu, booting_vector; 18.37 - 18.38 -unsigned long long gdt[] __attribute__ ((aligned(32))) = { 18.39 - 0x0000000000000000ULL, /* 0x00: reserved */ 18.40 - 0x0000890000000000ULL, /* 0x08: 32-bit TSS */ 18.41 - 0x00CF9A000000FFFFULL, /* 0x10: CS 32-bit */ 18.42 - 0x00CF92000000FFFFULL, /* 0x18: DS 32-bit */ 18.43 -}; 18.44 - 18.45 -struct dtr gdtr = { sizeof(gdt)-1, (unsigned long) &gdt }; 18.46 - 18.47 -struct tss tss __attribute__ ((aligned(4))); 18.48 - 18.49 -unsigned long long idt[NR_TRAPS] __attribute__ ((aligned(32))); 18.50 - 18.51 -struct dtr idtr = { sizeof(idt)-1, (unsigned long) &idt }; 18.52 - 18.53 -struct vmx_assist_context oldctx; 18.54 -struct vmx_assist_context newctx; 18.55 - 18.56 -unsigned long memory_size; 18.57 -int initialize_real_mode; 18.58 - 18.59 -extern char stack_top[]; 18.60 -extern unsigned trap_handlers[]; 18.61 - 18.62 -void 18.63 -banner(void) 18.64 -{ 18.65 - printf("VMXAssist (%s)\n", __DATE__); 18.66 - 18.67 - /* Bochs its way to convey memory size */ 18.68 - memory_size = ((get_cmos(0x35) << 8) | get_cmos(0x34)) << 6; 18.69 - if (memory_size > 0x3bc000) 18.70 - memory_size = 0x3bc000; 18.71 - memory_size = (memory_size << 10) + 0xF00000; 18.72 - if (memory_size <= 0xF00000) 18.73 - memory_size = 18.74 - (((get_cmos(0x31) << 8) | get_cmos(0x30)) + 0x400) << 10; 18.75 - memory_size += 0x400 << 10; /* + 1MB */ 18.76 - 18.77 - printf("Memory size %ld MB\n", memory_size >> 20); 18.78 - printf("E820 map:\n"); 18.79 - print_e820_map(HVM_E820, *HVM_E820_NR); 18.80 - printf("\n"); 18.81 -} 18.82 - 18.83 -void 18.84 -setup_gdt(void) 18.85 -{ 18.86 - unsigned long long addr = (unsigned long long) &tss; 18.87 - 18.88 - /* setup task state segment */ 18.89 - memset(&tss, 0, sizeof(tss)); 18.90 - tss.ss0 = DATA_SELECTOR; 18.91 - tss.esp0 = (unsigned) stack_top; 18.92 - tss.iomap_base = offsetof(struct tss, iomap); 18.93 - tss.iomap[sizeof(tss.iomap)-1] = 0xff; 18.94 - 18.95 - /* initialize gdt's tss selector */ 18.96 - gdt[TSS_SELECTOR / sizeof(gdt[0])] |= 18.97 - ((addr & 0xFF000000) << (56-24)) | 18.98 - ((addr & 0x00FF0000) << (32-16)) | 18.99 - ((addr & 0x0000FFFF) << (16)) | 18.100 - (sizeof(tss) - 1); 18.101 - 18.102 - /* switch to our own gdt and set current tss */ 18.103 - __asm__ __volatile__ ("lgdt %0" : : "m" (gdtr)); 18.104 - __asm__ __volatile__ ("movl %%eax,%%ds;" 18.105 - "movl %%eax,%%es;" 18.106 - "movl %%eax,%%fs;" 18.107 - "movl %%eax,%%gs;" 18.108 - "movl %%eax,%%ss" : : "a" (DATA_SELECTOR)); 18.109 - 18.110 - __asm__ __volatile__ ("ljmp %0,$1f; 1:" : : "i" (CODE_SELECTOR)); 18.111 - 18.112 - __asm__ __volatile__ ("ltr %%ax" : : "a" (TSS_SELECTOR)); 18.113 -} 18.114 - 18.115 -void 18.116 -set_intr_gate(int i, unsigned handler) 18.117 -{ 18.118 - unsigned long long addr = handler; 18.119 - 18.120 - idt[i] = ((addr & 0xFFFF0000ULL) << 32) | (0x8E00ULL << 32) | 18.121 - (addr & 0xFFFFULL) | (CODE_SELECTOR << 16); 18.122 -} 18.123 - 18.124 -void 18.125 -setup_idt(void) 18.126 -{ 18.127 - int i; 18.128 - 18.129 - for (i = 0; i < NR_TRAPS; i++) 18.130 - set_intr_gate(i, trap_handlers[i]); 18.131 - __asm__ __volatile__ ("lidt %0" : : "m" (idtr)); 18.132 -} 18.133 - 18.134 -void 18.135 -setup_pic(void) 18.136 -{ 18.137 - /* mask all interrupts */ 18.138 - outb(PIC_MASTER + PIC_IMR, 0xFF); 18.139 - outb(PIC_SLAVE + PIC_IMR, 0xFF); 18.140 - 18.141 - /* setup master PIC */ 18.142 - outb(PIC_MASTER + PIC_CMD, 0x11); /* edge triggered, cascade, ICW4 */ 18.143 - outb(PIC_MASTER + PIC_IMR, NR_EXCEPTION_HANDLER); 18.144 - outb(PIC_MASTER + PIC_IMR, 1 << 2); /* slave on channel 2 */ 18.145 - outb(PIC_MASTER + PIC_IMR, 0x01); 18.146 - 18.147 - /* setup slave PIC */ 18.148 - outb(PIC_SLAVE + PIC_CMD, 0x11); /* edge triggered, cascade, ICW4 */ 18.149 - outb(PIC_SLAVE + PIC_IMR, NR_EXCEPTION_HANDLER + 8); 18.150 - outb(PIC_SLAVE + PIC_IMR, 0x02); /* slave identity is 2 */ 18.151 - outb(PIC_SLAVE + PIC_IMR, 0x01); 18.152 - 18.153 - /* enable all interrupts */ 18.154 - outb(PIC_MASTER + PIC_IMR, 0); 18.155 - outb(PIC_SLAVE + PIC_IMR, 0); 18.156 -} 18.157 - 18.158 -void 18.159 -setiomap(int port) 18.160 -{ 18.161 - tss.iomap[port >> 3] |= 1 << (port & 7); 18.162 -} 18.163 - 18.164 -void 18.165 -enter_real_mode(struct regs *regs) 18.166 -{ 18.167 - /* mask off TSS busy bit */ 18.168 - gdt[TSS_SELECTOR / sizeof(gdt[0])] &= ~0x0000020000000000ULL; 18.169 - 18.170 - /* start 8086 emulation of BIOS */ 18.171 - if (initialize_real_mode) { 18.172 - initialize_real_mode = 0; 18.173 - regs->eflags |= EFLAGS_VM | 0x02; 18.174 - regs->ves = regs->vds = regs->vfs = regs->vgs = 0xF000; 18.175 - if (booting_cpu == 0) { 18.176 - regs->cs = 0xF000; /* ROM BIOS POST entry point */ 18.177 - regs->eip = 0xFFF0; 18.178 - } else { 18.179 - regs->cs = booting_vector << 8; /* AP entry point */ 18.180 - regs->eip = 0; 18.181 - } 18.182 - 18.183 - regs->uesp = regs->uss = 0; 18.184 - regs->eax = regs->ecx = regs->edx = regs->ebx = 0; 18.185 - regs->esp = regs->ebp = regs->esi = regs->edi = 0; 18.186 - 18.187 - /* intercept accesses to the PIC */ 18.188 - setiomap(PIC_MASTER+PIC_CMD); 18.189 - setiomap(PIC_MASTER+PIC_IMR); 18.190 - setiomap(PIC_SLAVE+PIC_CMD); 18.191 - setiomap(PIC_SLAVE+PIC_IMR); 18.192 - 18.193 - printf("Starting emulated 16-bit real-mode: ip=%04x:%04x\n", 18.194 - regs->cs, regs->eip); 18.195 - 18.196 - mode = VM86_REAL; /* becomes previous mode */ 18.197 - set_mode(regs, VM86_REAL); 18.198 - 18.199 - /* this should get us into 16-bit mode */ 18.200 - return; 18.201 - } 18.202 - 18.203 - /* go from protected to real mode */ 18.204 - set_mode(regs, VM86_PROTECTED_TO_REAL); 18.205 - emulate(regs); 18.206 - if (mode != VM86_REAL) 18.207 - panic("failed to emulate between clear PE and long jump.\n"); 18.208 -} 18.209 - 18.210 -/* 18.211 - * Setup the environment for VMX assist. 18.212 - * This environment consists of flat segments (code and data), 18.213 - * its own gdt, idt, and tr. 18.214 - */ 18.215 -void 18.216 -setup_ctx(void) 18.217 -{ 18.218 - struct vmx_assist_context *c = &newctx; 18.219 - 18.220 - memset(c, 0, sizeof(*c)); 18.221 - c->eip = (unsigned long) switch_to_real_mode; 18.222 - c->esp = (unsigned) stack_top; 18.223 - c->eflags = 0x2; /* no interrupts, please */ 18.224 - 18.225 - /* 18.226 - * Obviously, vmx assist is not running with CR0_PE disabled. 18.227 - * The reason why the vmx assist cr0 has CR0.PE disabled is 18.228 - * that a transtion to CR0.PE causes a world switch. It seems 18.229 - * more natural to enable CR0.PE to cause a world switch to 18.230 - * protected mode rather than disabling it. 18.231 - */ 18.232 - c->cr0 = (get_cr0() | CR0_NE) & ~CR0_PE; 18.233 - c->cr3 = 0; 18.234 - c->cr4 = get_cr4(); 18.235 - 18.236 - c->idtr_limit = sizeof(idt)-1; 18.237 - c->idtr_base = (unsigned long) &idt; 18.238 - 18.239 - c->gdtr_limit = sizeof(gdt)-1; 18.240 - c->gdtr_base = (unsigned long) &gdt; 18.241 - 18.242 - c->cs_sel = CODE_SELECTOR; 18.243 - c->cs_limit = 0xFFFFFFFF; 18.244 - c->cs_base = 0; 18.245 - c->cs_arbytes.fields.seg_type = 0xb; 18.246 - c->cs_arbytes.fields.s = 1; 18.247 - c->cs_arbytes.fields.dpl = 0; 18.248 - c->cs_arbytes.fields.p = 1; 18.249 - c->cs_arbytes.fields.avl = 0; 18.250 - c->cs_arbytes.fields.default_ops_size = 1; 18.251 - c->cs_arbytes.fields.g = 1; 18.252 - 18.253 - c->ds_sel = DATA_SELECTOR; 18.254 - c->ds_limit = 0xFFFFFFFF; 18.255 - c->ds_base = 0; 18.256 - c->ds_arbytes = c->cs_arbytes; 18.257 - c->ds_arbytes.fields.seg_type = 0x3; 18.258 - 18.259 - c->es_sel = DATA_SELECTOR; 18.260 - c->es_limit = 0xFFFFFFFF; 18.261 - c->es_base = 0; 18.262 - c->es_arbytes = c->ds_arbytes; 18.263 - 18.264 - c->ss_sel = DATA_SELECTOR; 18.265 - c->ss_limit = 0xFFFFFFFF; 18.266 - c->ss_base = 0; 18.267 - c->ss_arbytes = c->ds_arbytes; 18.268 - 18.269 - c->fs_sel = DATA_SELECTOR; 18.270 - c->fs_limit = 0xFFFFFFFF; 18.271 - c->fs_base = 0; 18.272 - c->fs_arbytes = c->ds_arbytes; 18.273 - 18.274 - c->gs_sel = DATA_SELECTOR; 18.275 - c->gs_limit = 0xFFFFFFFF; 18.276 - c->gs_base = 0; 18.277 - c->gs_arbytes = c->ds_arbytes; 18.278 - 18.279 - c->tr_sel = TSS_SELECTOR; 18.280 - c->tr_limit = sizeof(tss) - 1; 18.281 - c->tr_base = (unsigned long) &tss; 18.282 - c->tr_arbytes.fields.seg_type = 0xb; /* 0x9 | 0x2 (busy) */ 18.283 - c->tr_arbytes.fields.s = 0; 18.284 - c->tr_arbytes.fields.dpl = 0; 18.285 - c->tr_arbytes.fields.p = 1; 18.286 - c->tr_arbytes.fields.avl = 0; 18.287 - c->tr_arbytes.fields.default_ops_size = 0; 18.288 - c->tr_arbytes.fields.g = 0; 18.289 - 18.290 - c->ldtr_sel = 0; 18.291 - c->ldtr_limit = 0; 18.292 - c->ldtr_base = 0; 18.293 - c->ldtr_arbytes = c->ds_arbytes; 18.294 - c->ldtr_arbytes.fields.seg_type = 0x2; 18.295 - c->ldtr_arbytes.fields.s = 0; 18.296 - c->ldtr_arbytes.fields.dpl = 0; 18.297 - c->ldtr_arbytes.fields.p = 1; 18.298 - c->ldtr_arbytes.fields.avl = 0; 18.299 - c->ldtr_arbytes.fields.default_ops_size = 0; 18.300 - c->ldtr_arbytes.fields.g = 0; 18.301 -} 18.302 - 18.303 -/* 18.304 - * Start BIOS by causing a world switch to vmxassist, which causes 18.305 - * VM8086 to be enabled and control is transfered to F000:FFF0. 18.306 - */ 18.307 -void 18.308 -start_bios(void) 18.309 -{ 18.310 - if (booting_cpu == 0) 18.311 - printf("Start BIOS ...\n"); 18.312 - else 18.313 - printf("Start AP %d from %08x ...\n", 18.314 - booting_cpu, booting_vector << 12); 18.315 - 18.316 - initialize_real_mode = 1; 18.317 - set_cr0(get_cr0() & ~CR0_PE); 18.318 - panic("vmxassist returned"); /* "cannot happen" */ 18.319 -} 18.320 - 18.321 -int 18.322 -main(void) 18.323 -{ 18.324 - if (booting_cpu == 0) 18.325 - banner(); 18.326 - 18.327 - setup_gdt(); 18.328 - setup_idt(); 18.329 - 18.330 - set_cr4(get_cr4() | CR4_VME); 18.331 - 18.332 - setup_ctx(); 18.333 - 18.334 - if (booting_cpu == 0) 18.335 - setup_pic(); 18.336 - 18.337 - start_bios(); 18.338 - 18.339 - return 0; 18.340 -}
19.1 --- a/tools/firmware/vmxassist/trap.S Thu Feb 07 09:23:26 2008 -0700 19.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 19.3 @@ -1,179 +0,0 @@ 19.4 -/* 19.5 - * trap.S: Trap and world switch handlers 19.6 - * 19.7 - * Leendert van Doorn, leendert@watson.ibm.com 19.8 - * Copyright (c) 2005, International Business Machines Corporation. 19.9 - * 19.10 - * This program is free software; you can redistribute it and/or modify it 19.11 - * under the terms and conditions of the GNU General Public License, 19.12 - * version 2, as published by the Free Software Foundation. 19.13 - * 19.14 - * This program is distributed in the hope it will be useful, but WITHOUT 19.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 19.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 19.17 - * more details. 19.18 - * 19.19 - * You should have received a copy of the GNU General Public License along with 19.20 - * this program; if not, write to the Free Software Foundation, Inc., 59 Temple 19.21 - * Place - Suite 330, Boston, MA 02111-1307 USA. 19.22 - */ 19.23 -#include "machine.h" 19.24 -#include "vm86.h" 19.25 -#include "offsets.h" 19.26 - 19.27 -/* 19.28 - * All processor exception/faults/interrupts end up here. 19.29 - * 19.30 - * On an exception/fault, the processor pushes CS:EIP, SS, ESP and an 19.31 - * optional error code onto the stack. The common_trap routine 19.32 - * below saves the processor context and transfers control to trap() 19.33 - * whose job it is to virtualize and pass on the trap. 19.34 - */ 19.35 - .macro TRAP_HANDLER trapno error 19.36 - .text 19.37 - .align 16 19.38 -1: .if \error == 0 19.39 - pushl $0 /* dummy error code */ 19.40 - .endif 19.41 - pushl $\trapno 19.42 - jmp common_trap 19.43 - .section .rodata 19.44 - .long 1b 19.45 - .text 19.46 - .endm 19.47 - 19.48 - .section .rodata 19.49 - .code32 19.50 - .align 4 19.51 - .global trap_handlers 19.52 -trap_handlers: 19.53 - TRAP_HANDLER 0, 0 /* divide error */ 19.54 - TRAP_HANDLER 1, 0 /* debug */ 19.55 - TRAP_HANDLER 2, 0 /* NMI interrupt */ 19.56 - TRAP_HANDLER 3, 0 /* breakpoint */ 19.57 - TRAP_HANDLER 4, 0 /* overflow */ 19.58 - TRAP_HANDLER 5, 0 /* BOUND range exceeded */ 19.59 - TRAP_HANDLER 6, 0 /* invalid opcode */ 19.60 - TRAP_HANDLER 7, 0 /* device not available */ 19.61 - TRAP_HANDLER 8, 1 /* double fault */ 19.62 - TRAP_HANDLER 9, 0 /* coprocessor segment overrun */ 19.63 - TRAP_HANDLER 10, 1 /* invalid TSS */ 19.64 - TRAP_HANDLER 11, 1 /* segment not present */ 19.65 - TRAP_HANDLER 12, 1 /* stack-segment fault */ 19.66 - TRAP_HANDLER 13, 1 /* general protection */ 19.67 - TRAP_HANDLER 14, 1 /* page fault */ 19.68 - TRAP_HANDLER 15, 0 /* reserved */ 19.69 - TRAP_HANDLER 16, 0 /* FPU floating-point error */ 19.70 - TRAP_HANDLER 17, 1 /* alignment check */ 19.71 - TRAP_HANDLER 18, 0 /* machine check */ 19.72 - TRAP_HANDLER 19, 0 /* SIMD floating-point error */ 19.73 - TRAP_HANDLER 20, 0 /* reserved */ 19.74 - TRAP_HANDLER 21, 0 /* reserved */ 19.75 - TRAP_HANDLER 22, 0 /* reserved */ 19.76 - TRAP_HANDLER 23, 0 /* reserved */ 19.77 - TRAP_HANDLER 24, 0 /* reserved */ 19.78 - TRAP_HANDLER 25, 0 /* reserved */ 19.79 - TRAP_HANDLER 26, 0 /* reserved */ 19.80 - TRAP_HANDLER 27, 0 /* reserved */ 19.81 - TRAP_HANDLER 28, 0 /* reserved */ 19.82 - TRAP_HANDLER 29, 0 /* reserved */ 19.83 - TRAP_HANDLER 30, 0 /* reserved */ 19.84 - TRAP_HANDLER 31, 0 /* reserved */ 19.85 - TRAP_HANDLER 32, 0 /* irq 0 */ 19.86 - TRAP_HANDLER 33, 0 /* irq 1 */ 19.87 - TRAP_HANDLER 34, 0 /* irq 2 */ 19.88 - TRAP_HANDLER 35, 0 /* irq 3 */ 19.89 - TRAP_HANDLER 36, 0 /* irq 4 */ 19.90 - TRAP_HANDLER 37, 0 /* irq 5 */ 19.91 - TRAP_HANDLER 38, 0 /* irq 6 */ 19.92 - TRAP_HANDLER 39, 0 /* irq 7 */ 19.93 - TRAP_HANDLER 40, 0 /* irq 8 */ 19.94 - TRAP_HANDLER 41, 0 /* irq 9 */ 19.95 - TRAP_HANDLER 42, 0 /* irq 10 */ 19.96 - TRAP_HANDLER 43, 0 /* irq 11 */ 19.97 - TRAP_HANDLER 44, 0 /* irq 12 */ 19.98 - TRAP_HANDLER 45, 0 /* irq 13 */ 19.99 - TRAP_HANDLER 46, 0 /* irq 14 */ 19.100 - TRAP_HANDLER 47, 0 /* irq 15 */ 19.101 - 19.102 - .text 19.103 - .code32 19.104 - .align 16 19.105 -common_trap: /* common trap handler */ 19.106 - pushal 19.107 - 19.108 - movl $(DATA_SELECTOR), %eax /* make sure these are sane */ 19.109 - movl %eax, %ds 19.110 - movl %eax, %es 19.111 - movl %eax, %fs 19.112 - movl %eax, %gs 19.113 - movl %esp, %ebp 19.114 - 19.115 - pushl %ebp 19.116 - pushl 36(%ebp) 19.117 - pushl 32(%ebp) 19.118 - call trap /* trap(trapno, errno, regs) */ 19.119 - addl $12, %esp 19.120 - 19.121 -trap_return: 19.122 - popal 19.123 - addl $8, %esp /* skip trapno, errno */ 19.124 - iret 19.125 - /* NOT REACHED */ 19.126 - 19.127 - 19.128 -/* 19.129 - * A world switch to real mode occured. The hypervisor saved the 19.130 - * executing context into "oldctx" and instantiated "newctx", which 19.131 - * gets us here. Here we push a stack frame that is compatible with 19.132 - * a trap frame (see above) so that we can handle this event as a 19.133 - * regular trap. 19.134 - */ 19.135 - .text 19.136 - .align 16 19.137 - .globl switch_to_real_mode 19.138 -switch_to_real_mode: 19.139 - pushl oldctx+VMX_ASSIST_CTX_GS_SEL /* 16 to 32-bit transition */ 19.140 - pushl oldctx+VMX_ASSIST_CTX_FS_SEL 19.141 - pushl oldctx+VMX_ASSIST_CTX_DS_SEL 19.142 - pushl oldctx+VMX_ASSIST_CTX_ES_SEL 19.143 - pushl oldctx+VMX_ASSIST_CTX_SS_SEL 19.144 - pushl oldctx+VMX_ASSIST_CTX_ESP 19.145 - pushl oldctx+VMX_ASSIST_CTX_EFLAGS 19.146 - pushl oldctx+VMX_ASSIST_CTX_CS_SEL 19.147 - pushl oldctx+VMX_ASSIST_CTX_EIP 19.148 - pushl $-1 /* trapno, errno */ 19.149 - pushl $-1 19.150 - pushal 19.151 - 19.152 - movl %esp, %ebp 19.153 - pushl %ebp 19.154 - call enter_real_mode 19.155 - addl $4, %esp 19.156 - 19.157 - jmp trap_return 19.158 - /* NOT REACHED */ 19.159 - 19.160 - 19.161 -/* 19.162 - * Switch to protected mode. At this point all the registers have 19.163 - * been reloaded by trap_return and all we have to do is cause a 19.164 - * world switch by turning on CR0.PE. 19.165 - */ 19.166 - .text 19.167 - .align 16 19.168 - .globl switch_to_protected_mode 19.169 -switch_to_protected_mode: 19.170 - movl oldctx+VMX_ASSIST_CTX_CR0, %esp 19.171 - movl %esp, %cr0 /* actual world switch ! */ 19.172 - 19.173 - /* NOT REACHED */ 19.174 - pushl $switch_failed 19.175 - call panic 19.176 - jmp . 19.177 - 19.178 - .data 19.179 - .align 4 19.180 -switch_failed: 19.181 - .asciz "World switch to protected mode failed\n" 19.182 -
20.1 --- a/tools/firmware/vmxassist/util.c Thu Feb 07 09:23:26 2008 -0700 20.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 20.3 @@ -1,430 +0,0 @@ 20.4 -/* 20.5 - * util.c: Commonly used utility functions. 20.6 - * 20.7 - * Leendert van Doorn, leendert@watson.ibm.com 20.8 - * Copyright (c) 2005, International Business Machines Corporation. 20.9 - * 20.10 - * This program is free software; you can redistribute it and/or modify it 20.11 - * under the terms and conditions of the GNU General Public License, 20.12 - * version 2, as published by the Free Software Foundation. 20.13 - * 20.14 - * This program is distributed in the hope it will be useful, but WITHOUT 20.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 20.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 20.17 - * more details. 20.18 - * 20.19 - * You should have received a copy of the GNU General Public License along with 20.20 - * this program; if not, write to the Free Software Foundation, Inc., 59 Temple 20.21 - * Place - Suite 330, Boston, MA 02111-1307 USA. 20.22 - */ 20.23 -#include <stdarg.h> 20.24 - 20.25 -#include "util.h" 20.26 -#include "machine.h" 20.27 - 20.28 -#define isdigit(c) ((c) >= '0' && (c) <= '9') 20.29 -#define min(a, b) ((a) < (b) ? (a) : (b)) 20.30 - 20.31 -static void putchar(int); 20.32 -static char *printnum(char *, unsigned long, int); 20.33 -static void _doprint(void (*)(int), const char *, va_list); 20.34 - 20.35 -void 20.36 -cpuid_addr_value(uint64_t addr, uint64_t *value) 20.37 -{ 20.38 - uint32_t addr_low = (uint32_t)addr; 20.39 - uint32_t addr_high = (uint32_t)(addr >> 32); 20.40 - uint32_t value_low, value_high; 20.41 - static unsigned int addr_leaf; 20.42 - 20.43 - if (!addr_leaf) { 20.44 - unsigned int eax, ebx, ecx, edx; 20.45 - __asm__ __volatile__( 20.46 - "cpuid" 20.47 - : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) 20.48 - : "0" (0x40000000)); 20.49 - addr_leaf = eax + 1; 20.50 - } 20.51 - 20.52 - __asm__ __volatile__( 20.53 - "cpuid" 20.54 - : "=c" (value_low), "=d" (value_high) 20.55 - : "a" (addr_leaf), "0" (addr_low), "1" (addr_high) 20.56 - : "ebx"); 20.57 - 20.58 - *value = (uint64_t)value_high << 32 | value_low; 20.59 -} 20.60 - 20.61 -void 20.62 -dump_regs(struct regs *regs) 20.63 -{ 20.64 - printf("eax %8x ecx %8x edx %8x ebx %8x\n", 20.65 - regs->eax, regs->ecx, regs->edx, regs->ebx); 20.66 - printf("esp %8x ebp %8x esi %8x edi %8x\n", 20.67 - regs->esp, regs->ebp, regs->esi, regs->edi); 20.68 - printf("trapno %8x errno %8x\n", regs->trapno, regs->errno); 20.69 - printf("eip %8x cs %8x eflags %8x\n", 20.70 - regs->eip, regs->cs, regs->eflags); 20.71 - printf("uesp %8x uss %8x\n", 20.72 - regs->uesp, regs->uss); 20.73 - printf("ves %8x vds %8x vfs %8x vgs %8x\n", 20.74 - regs->ves, regs->vds, regs->vfs, regs->vgs); 20.75 - 20.76 - printf("cr0 %8lx cr2 %8x cr3 %8lx cr4 %8lx\n\n", 20.77 - (long)oldctx.cr0, get_cr2(), 20.78 - (long)oldctx.cr3, (long)oldctx.cr4); 20.79 -} 20.80 - 20.81 -#ifdef DEBUG 20.82 -void 20.83 -hexdump(unsigned char *data, int sz) 20.84 -{ 20.85 - unsigned char *d; 20.86 - int i; 20.87 - 20.88 - for (d = data; sz > 0; d += 16, sz -= 16) { 20.89 - int n = sz > 16 ? 16 : sz; 20.90 - 20.91 - printf("%08x: ", (unsigned)d); 20.92 - for (i = 0; i < n; i++) 20.93 - printf("%02x%c", d[i], i == 7 ? '-' : ' '); 20.94 - for (; i < 16; i++) 20.95 - printf(" %c", i == 7 ? '-' : ' '); 20.96 - printf(" "); 20.97 - for (i = 0; i < n; i++) 20.98 - printf("%c", d[i] >= ' ' && d[i] <= '~' ? d[i] : '.'); 20.99 - printf("\n"); 20.100 - } 20.101 -} 20.102 - 20.103 -void 20.104 -print_e820_map(struct e820entry *map, int entries) 20.105 -{ 20.106 - struct e820entry *m; 20.107 - 20.108 - if (entries > 32) 20.109 - entries = 32; 20.110 - 20.111 - for (m = map; m < &map[entries]; m++) { 20.112 - printf("%08lx%08lx - %08lx%08lx ", 20.113 - (unsigned long) (m->addr >> 32), 20.114 - (unsigned long) (m->addr), 20.115 - (unsigned long) ((m->addr+m->size) >> 32), 20.116 - (unsigned long) ((m->addr+m->size))); 20.117 - 20.118 - switch (m->type) { 20.119 - case E820_RAM: 20.120 - printf("(RAM)\n"); break; 20.121 - case E820_RESERVED: 20.122 - printf("(Reserved)\n"); break; 20.123 - case E820_ACPI: 20.124 - printf("(ACPI Data)\n"); break; 20.125 - case E820_NVS: 20.126 - printf("(ACPI NVS)\n"); break; 20.127 - default: 20.128 - printf("(Type %ld)\n", m->type); break; 20.129 - } 20.130 - } 20.131 -} 20.132 - 20.133 -void 20.134 -dump_dtr(unsigned long addr, unsigned long size) 20.135 -{ 20.136 - unsigned long long entry; 20.137 - unsigned long base, limit; 20.138 - int i; 20.139 - 20.140 - for (i = 0; i < size; i += 8) { 20.141 - entry = ((unsigned long long *) addr)[i >> 3]; 20.142 - base = (((entry >> (56-24)) & 0xFF000000) | 20.143 - ((entry >> (32-16)) & 0x00FF0000) | 20.144 - ((entry >> ( 16)) & 0x0000FFFF)); 20.145 - limit = (((entry >> (48-16)) & 0x000F0000) | 20.146 - ((entry ) & 0x0000FFFF)); 20.147 - if (entry & (1ULL << (23+32))) /* G */ 20.148 - limit = (limit << 12) | 0xFFF; 20.149 - 20.150 - printf("[0x%x] = 0x%08x%08x, base 0x%lx, limit 0x%lx\n", i, 20.151 - (unsigned)(entry >> 32), (unsigned)(entry), 20.152 - base, limit); 20.153 - } 20.154 -} 20.155 - 20.156 -void 20.157 -dump_vmx_context(struct vmx_assist_context *c) 20.158 -{ 20.159 - printf("eip 0x%lx, esp 0x%lx, eflags 0x%lx\n", 20.160 - (long) c->eip, (long) c->esp, (long) c->eflags); 20.161 - 20.162 - printf("cr0 0x%lx, cr3 0x%lx, cr4 0x%lx\n", 20.163 - (long)c->cr0, (long)c->cr3, (long)c->cr4); 20.164 - 20.165 - printf("idtr: limit 0x%lx, base 0x%lx\n", 20.166 - (long)c->idtr_limit, (long)c->idtr_base); 20.167 - 20.168 - printf("gdtr: limit 0x%lx, base 0x%lx\n", 20.169 - (long)c->gdtr_limit, (long)c->gdtr_base); 20.170 - 20.171 - printf("cs: sel 0x%lx, limit 0x%lx, base 0x%lx\n", 20.172 - (long)c->cs_sel, (long)c->cs_limit, (long)c->cs_base); 20.173 - printf("\ttype %d, s %d, dpl %d, p %d, avl %d, ops %d, g %d, nul %d\n", 20.174 - c->cs_arbytes.fields.seg_type, 20.175 - c->cs_arbytes.fields.s, 20.176 - c->cs_arbytes.fields.dpl, 20.177 - c->cs_arbytes.fields.p, 20.178 - c->cs_arbytes.fields.avl, 20.179 - c->cs_arbytes.fields.default_ops_size, 20.180 - c->cs_arbytes.fields.g, 20.181 - c->cs_arbytes.fields.null_bit); 20.182 - 20.183 - printf("ds: sel 0x%lx, limit 0x%lx, base 0x%lx\n", 20.184 - (long)c->ds_sel, (long)c->ds_limit, (long)c->ds_base); 20.185 - printf("\ttype %d, s %d, dpl %d, p %d, avl %d, ops %d, g %d, nul %d\n", 20.186 - c->ds_arbytes.fields.seg_type, 20.187 - c->ds_arbytes.fields.s, 20.188 - c->ds_arbytes.fields.dpl, 20.189 - c->ds_arbytes.fields.p, 20.190 - c->ds_arbytes.fields.avl, 20.191 - c->ds_arbytes.fields.default_ops_size, 20.192 - c->ds_arbytes.fields.g, 20.193 - c->ds_arbytes.fields.null_bit); 20.194 - 20.195 - printf("es: sel 0x%lx, limit 0x%lx, base 0x%lx\n", 20.196 - (long)c->es_sel, (long)c->es_limit, (long)c->es_base); 20.197 - printf("\ttype %d, s %d, dpl %d, p %d, avl %d, ops %d, g %d, nul %d\n", 20.198 - c->es_arbytes.fields.seg_type, 20.199 - c->es_arbytes.fields.s, 20.200 - c->es_arbytes.fields.dpl, 20.201 - c->es_arbytes.fields.p, 20.202 - c->es_arbytes.fields.avl, 20.203 - c->es_arbytes.fields.default_ops_size, 20.204 - c->es_arbytes.fields.g, 20.205 - c->es_arbytes.fields.null_bit); 20.206 - 20.207 - printf("ss: sel 0x%lx, limit 0x%lx, base 0x%lx\n", 20.208 - (long)c->ss_sel, (long)c->ss_limit, (long)c->ss_base); 20.209 - printf("\ttype %d, s %d, dpl %d, p %d, avl %d, ops %d, g %d, nul %d\n", 20.210 - c->ss_arbytes.fields.seg_type, 20.211 - c->ss_arbytes.fields.s, 20.212 - c->ss_arbytes.fields.dpl, 20.213 - c->ss_arbytes.fields.p, 20.214 - c->ss_arbytes.fields.avl, 20.215 - c->ss_arbytes.fields.default_ops_size, 20.216 - c->ss_arbytes.fields.g, 20.217 - c->ss_arbytes.fields.null_bit); 20.218 - 20.219 - printf("fs: sel 0x%lx, limit 0x%lx, base 0x%lx\n", 20.220 - (long)c->fs_sel, (long)c->fs_limit, (long)c->fs_base); 20.221 - printf("\ttype %d, s %d, dpl %d, p %d, avl %d, ops %d, g %d, nul %d\n", 20.222 - c->fs_arbytes.fields.seg_type, 20.223 - c->fs_arbytes.fields.s, 20.224 - c->fs_arbytes.fields.dpl, 20.225 - c->fs_arbytes.fields.p, 20.226 - c->fs_arbytes.fields.avl, 20.227 - c->fs_arbytes.fields.default_ops_size, 20.228 - c->fs_arbytes.fields.g, 20.229 - c->fs_arbytes.fields.null_bit); 20.230 - 20.231 - printf("gs: sel 0x%lx, limit 0x%lx, base 0x%lx\n", 20.232 - (long)c->gs_sel, (long)c->gs_limit, (long)c->gs_base); 20.233 - printf("\ttype %d, s %d, dpl %d, p %d, avl %d, ops %d, g %d, nul %d\n", 20.234 - c->gs_arbytes.fields.seg_type, 20.235 - c->gs_arbytes.fields.s, 20.236 - c->gs_arbytes.fields.dpl, 20.237 - c->gs_arbytes.fields.p, 20.238 - c->gs_arbytes.fields.avl, 20.239 - c->gs_arbytes.fields.default_ops_size, 20.240 - c->gs_arbytes.fields.g, 20.241 - c->gs_arbytes.fields.null_bit); 20.242 - 20.243 - printf("tr: sel 0x%lx, limit 0x%lx, base 0x%lx\n", 20.244 - (long)c->tr_sel, (long)c->tr_limit, (long)c->tr_base); 20.245 - printf("\ttype %d, s %d, dpl %d, p %d, avl %d, ops %d, g %d, nul %d\n", 20.246 - c->tr_arbytes.fields.seg_type, 20.247 - c->tr_arbytes.fields.s, 20.248 - c->tr_arbytes.fields.dpl, 20.249 - c->tr_arbytes.fields.p, 20.250 - c->tr_arbytes.fields.avl, 20.251 - c->tr_arbytes.fields.default_ops_size, 20.252 - c->tr_arbytes.fields.g, 20.253 - c->tr_arbytes.fields.null_bit); 20.254 - 20.255 - printf("ldtr: sel 0x%lx, limit 0x%lx, base 0x%lx\n", 20.256 - (long)c->ldtr_sel, (long)c->ldtr_limit, (long)c->ldtr_base); 20.257 - printf("\ttype %d, s %d, dpl %d, p %d, avl %d, ops %d, g %d, nul %d\n", 20.258 - c->ldtr_arbytes.fields.seg_type, 20.259 - c->ldtr_arbytes.fields.s, 20.260 - c->ldtr_arbytes.fields.dpl, 20.261 - c->ldtr_arbytes.fields.p, 20.262 - c->ldtr_arbytes.fields.avl, 20.263 - c->ldtr_arbytes.fields.default_ops_size, 20.264 - c->ldtr_arbytes.fields.g, 20.265 - c->ldtr_arbytes.fields.null_bit); 20.266 - 20.267 - printf("GDTR <0x%lx,0x%lx>:\n", 20.268 - (long)c->gdtr_base, (long)c->gdtr_limit); 20.269 - dump_dtr(c->gdtr_base, c->gdtr_limit); 20.270 -} 20.271 -#endif /* DEBUG */ 20.272 - 20.273 -/* 20.274 - * Lightweight printf that doesn't drag in everything under the sun. 20.275 - */ 20.276 -int 20.277 -printf(const char *fmt, ...) 20.278 -{ 20.279 - va_list ap; 20.280 - 20.281 - va_start(ap, fmt); 20.282 - _doprint(putchar, fmt, ap); 20.283 - va_end(ap); 20.284 - return 0; /* for gcc compat */ 20.285 -} 20.286 - 20.287 -int 20.288 -vprintf(const char *fmt, va_list ap) 20.289 -{ 20.290 - _doprint(putchar, fmt, ap); 20.291 - return 0; /* for gcc compat */ 20.292 -} 20.293 - 20.294 -void 20.295 -panic(const char *fmt, ...) 20.296 -{ 20.297 - va_list ap; 20.298 - 20.299 - va_start(ap, fmt); 20.300 - _doprint(putchar, fmt, ap); 20.301 - putchar('\n'); 20.302 - va_end(ap); 20.303 - halt(); 20.304 -} 20.305 - 20.306 -unsigned 20.307 -strlen(const char *s) 20.308 -{ 20.309 - const char *q = s; 20.310 - 20.311 - while (*s++) 20.312 - /* void */; 20.313 - return s - q - 1; 20.314 -} 20.315 - 20.316 -static void 20.317 -putchar(int ch) 20.318 -{ 20.319 - outb(0xE9, ch); 20.320 -} 20.321 - 20.322 -/* 20.323 - * A stripped down version of doprint, 20.324 - * but still powerful enough for most tasks. 20.325 - */ 20.326 -static void 20.327 -_doprint(void (*put)(int), const char *fmt, va_list ap) 20.328 -{ 20.329 - register char *str, c; 20.330 - int lflag, zflag, nflag; 20.331 - char buffer[17]; 20.332 - unsigned value; 20.333 - int i, slen, pad; 20.334 - 20.335 - for ( ; *fmt != '\0'; fmt++) { 20.336 - pad = zflag = nflag = lflag = 0; 20.337 - if (*fmt == '%') { 20.338 - c = *++fmt; 20.339 - if (c == '-' || isdigit(c)) { 20.340 - if (c == '-') { 20.341 - nflag = 1; 20.342 - c = *++fmt; 20.343 - } 20.344 - zflag = c == '0'; 20.345 - for (pad = 0; isdigit(c); c = *++fmt) 20.346 - pad = (pad * 10) + c - '0'; 20.347 - } 20.348 - if (c == 'l') { /* long extension */ 20.349 - lflag = 1; 20.350 - c = *++fmt; 20.351 - } 20.352 - if (c == 'd' || c == 'u' || c == 'o' || c == 'x') { 20.353 - if (lflag) 20.354 - value = va_arg(ap, unsigned); 20.355 - else 20.356 - value = (unsigned) va_arg(ap, unsigned int); 20.357 - str = buffer; 20.358 - printnum(str, value, 20.359 - c == 'o' ? 8 : (c == 'x' ? 16 : 10)); 20.360 - goto printn; 20.361 - } else if (c == 'O' || c == 'D' || c == 'X') { 20.362 - value = va_arg(ap, unsigned); 20.363 - str = buffer; 20.364 - printnum(str, value, 20.365 - c == 'O' ? 8 : (c == 'X' ? 16 : 10)); 20.366 - printn: 20.367 - slen = strlen(str); 20.368 - for (i = pad - slen; i > 0; i--) 20.369 - put(zflag ? '0' : ' '); 20.370 - while (*str) put(*str++); 20.371 - } else if (c == 's') { 20.372 - str = va_arg(ap, char *); 20.373 - slen = strlen(str); 20.374 - if (nflag == 0) 20.375 - for (i = pad - slen; i > 0; i--) put(' '); 20.376 - while (*str) put(*str++); 20.377 - if (nflag) 20.378 - for (i = pad - slen; i > 0; i--) put(' '); 20.379 - } else if (c == 'c') 20.380 - put(va_arg(ap, int)); 20.381 - else 20.382 - put(*fmt); 20.383 - } else 20.384 - put(*fmt); 20.385 - } 20.386 -} 20.387 - 20.388 -static char * 20.389 -printnum(char *p, unsigned long num, int base) 20.390 -{ 20.391 - unsigned long n; 20.392 - 20.393 - if ((n = num/base) > 0) 20.394 - p = printnum(p, n, base); 20.395 - *p++ = "0123456789ABCDEF"[(int)(num % base)]; 20.396 - *p = '\0'; 20.397 - return p; 20.398 -} 20.399 - 20.400 -void * 20.401 -memset(void *s, int c, unsigned n) 20.402 -{ 20.403 - int t0, t1; 20.404 - 20.405 - __asm__ __volatile__ ("cld; rep; stosb" 20.406 - : "=&c" (t0), "=&D" (t1) 20.407 - : "a" (c), "1" (s), "0" (n) 20.408 - : "memory"); 20.409 - return s; 20.410 -} 20.411 - 20.412 -void * 20.413 -memcpy(void *dest, const void *src, unsigned n) 20.414 -{ 20.415 - int t0, t1, t2; 20.416 - 20.417 - __asm__ __volatile__( 20.418 - "cld\n" 20.419 - "rep; movsl\n" 20.420 - "testb $2,%b4\n" 20.421 - "je 1f\n" 20.422 - "movsw\n" 20.423 - "1: testb $1,%b4\n" 20.424 - "je 2f\n" 20.425 - "movsb\n" 20.426 - "2:" 20.427 - : "=&c" (t0), "=&D" (t1), "=&S" (t2) 20.428 - : "0" (n/4), "q" (n), "1" ((long) dest), "2" ((long) src) 20.429 - : "memory" 20.430 - ); 20.431 - return dest; 20.432 -} 20.433 -
21.1 --- a/tools/firmware/vmxassist/util.h Thu Feb 07 09:23:26 2008 -0700 21.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 21.3 @@ -1,45 +0,0 @@ 21.4 -/* 21.5 - * util.h: Useful utility functions. 21.6 - * 21.7 - * Leendert van Doorn, leendert@watson.ibm.com 21.8 - * Copyright (c) 2005, International Business Machines Corporation. 21.9 - * 21.10 - * This program is free software; you can redistribute it and/or modify it 21.11 - * under the terms and conditions of the GNU General Public License, 21.12 - * version 2, as published by the Free Software Foundation. 21.13 - * 21.14 - * This program is distributed in the hope it will be useful, but WITHOUT 21.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 21.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 21.17 - * more details. 21.18 - * 21.19 - * You should have received a copy of the GNU General Public License along with 21.20 - * this program; if not, write to the Free Software Foundation, Inc., 59 Temple 21.21 - * Place - Suite 330, Boston, MA 02111-1307 USA. 21.22 - */ 21.23 -#ifndef __UTIL_H__ 21.24 -#define __UTIL_H__ 21.25 - 21.26 -#include <stdarg.h> 21.27 -#include <vm86.h> 21.28 - 21.29 -#define offsetof(type, member) ((unsigned) &((type *)0)->member) 21.30 - 21.31 -struct vmx_assist_context; 21.32 - 21.33 -#include "../hvmloader/e820.h" 21.34 - 21.35 -extern void cpuid_addr_value(uint64_t addr, uint64_t *value); 21.36 -extern void hexdump(unsigned char *, int); 21.37 -extern void dump_regs(struct regs *); 21.38 -extern void dump_vmx_context(struct vmx_assist_context *); 21.39 -extern void print_e820_map(struct e820entry *, int); 21.40 -extern void dump_dtr(unsigned long, unsigned long); 21.41 -extern void *memcpy(void *, const void *, unsigned); 21.42 -extern void *memset(void *, int, unsigned); 21.43 -extern int printf(const char *fmt, ...); 21.44 -extern int vprintf(const char *fmt, va_list ap); 21.45 -extern void panic(const char *format, ...); 21.46 -extern void halt(void); 21.47 - 21.48 -#endif /* __UTIL_H__ */
22.1 --- a/tools/firmware/vmxassist/vm86.c Thu Feb 07 09:23:26 2008 -0700 22.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 22.3 @@ -1,1992 +0,0 @@ 22.4 -/* 22.5 - * vm86.c: A vm86 emulator. The main purpose of this emulator is to do as 22.6 - * little work as possible. 22.7 - * 22.8 - * Leendert van Doorn, leendert@watson.ibm.com 22.9 - * Copyright (c) 2005-2006, International Business Machines Corporation. 22.10 - * 22.11 - * This program is free software; you can redistribute it and/or modify it 22.12 - * under the terms and conditions of the GNU General Public License, 22.13 - * version 2, as published by the Free Software Foundation. 22.14 - * 22.15 - * This program is distributed in the hope it will be useful, but WITHOUT 22.16 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 22.17 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 22.18 - * more details. 22.19 - * 22.20 - * You should have received a copy of the GNU General Public License along with 22.21 - * this program; if not, write to the Free Software Foundation, Inc., 59 Temple 22.22 - * Place - Suite 330, Boston, MA 02111-1307 USA. 22.23 - */ 22.24 -#include "vm86.h" 22.25 -#include "util.h" 22.26 -#include "machine.h" 22.27 - 22.28 -#define HIGHMEM (1 << 20) /* 1MB */ 22.29 -#define MASK16(v) ((v) & 0xFFFF) 22.30 - 22.31 -#define DATA32 0x0001 22.32 -#define ADDR32 0x0002 22.33 -#define SEG_CS 0x0004 22.34 -#define SEG_DS 0x0008 22.35 -#define SEG_ES 0x0010 22.36 -#define SEG_SS 0x0020 22.37 -#define SEG_FS 0x0040 22.38 -#define SEG_GS 0x0080 22.39 -#define REP 0x0100 22.40 - 22.41 -static unsigned prev_eip = 0; 22.42 -enum vm86_mode mode = 0; 22.43 - 22.44 -static struct regs saved_rm_regs; 22.45 - 22.46 -#ifdef DEBUG 22.47 -int traceset = 0; 22.48 - 22.49 -char *states[] = { 22.50 - "<VM86_REAL>", 22.51 - "<VM86_REAL_TO_PROTECTED>", 22.52 - "<VM86_PROTECTED_TO_REAL>", 22.53 - "<VM86_PROTECTED>" 22.54 -}; 22.55 - 22.56 -static char *rnames[] = { "ax", "cx", "dx", "bx", "sp", "bp", "si", "di" }; 22.57 -#endif /* DEBUG */ 22.58 - 22.59 -#define PDE_PS (1 << 7) 22.60 -#define PT_ENTRY_PRESENT 0x1 22.61 - 22.62 -/* We only support access to <=4G physical memory due to 1:1 mapping */ 22.63 -static uint64_t 22.64 -guest_linear_to_phys(uint32_t base) 22.65 -{ 22.66 - uint32_t gcr3 = oldctx.cr3; 22.67 - uint64_t l2_mfn; 22.68 - uint64_t l1_mfn; 22.69 - uint64_t l0_mfn; 22.70 - 22.71 - if (!(oldctx.cr0 & CR0_PG)) 22.72 - return base; 22.73 - 22.74 - if (!(oldctx.cr4 & CR4_PAE)) { 22.75 - l1_mfn = ((uint32_t *)(long)gcr3)[(base >> 22) & 0x3ff]; 22.76 - if (!(l1_mfn & PT_ENTRY_PRESENT)) 22.77 - panic("l2 entry not present\n"); 22.78 - 22.79 - if ((oldctx.cr4 & CR4_PSE) && (l1_mfn & PDE_PS)) { 22.80 - l0_mfn = l1_mfn & 0xffc00000; 22.81 - return l0_mfn + (base & 0x3fffff); 22.82 - } 22.83 - 22.84 - l1_mfn &= 0xfffff000; 22.85 - 22.86 - l0_mfn = ((uint32_t *)(long)l1_mfn)[(base >> 12) & 0x3ff]; 22.87 - if (!(l0_mfn & PT_ENTRY_PRESENT)) 22.88 - panic("l1 entry not present\n"); 22.89 - l0_mfn &= 0xfffff000; 22.90 - 22.91 - return l0_mfn + (base & 0xfff); 22.92 - } else { 22.93 - l2_mfn = ((uint64_t *)(long)gcr3)[(base >> 30) & 0x3]; 22.94 - if (!(l2_mfn & PT_ENTRY_PRESENT)) 22.95 - panic("l3 entry not present\n"); 22.96 - l2_mfn &= 0xffffff000ULL; 22.97 - 22.98 - if (l2_mfn & 0xf00000000ULL) { 22.99 - printf("l2 page above 4G\n"); 22.100 - cpuid_addr_value(l2_mfn + 8 * ((base >> 21) & 0x1ff), &l1_mfn); 22.101 - } else 22.102 - l1_mfn = ((uint64_t *)(long)l2_mfn)[(base >> 21) & 0x1ff]; 22.103 - if (!(l1_mfn & PT_ENTRY_PRESENT)) 22.104 - panic("l2 entry not present\n"); 22.105 - 22.106 - if (l1_mfn & PDE_PS) { /* CR4.PSE is ignored in PAE mode */ 22.107 - l0_mfn = l1_mfn & 0xfffe00000ULL; 22.108 - return l0_mfn + (base & 0x1fffff); 22.109 - } 22.110 - 22.111 - l1_mfn &= 0xffffff000ULL; 22.112 - 22.113 - if (l1_mfn & 0xf00000000ULL) { 22.114 - printf("l1 page above 4G\n"); 22.115 - cpuid_addr_value(l1_mfn + 8 * ((base >> 12) & 0x1ff), &l0_mfn); 22.116 - } else 22.117 - l0_mfn = ((uint64_t *)(long)l1_mfn)[(base >> 12) & 0x1ff]; 22.118 - if (!(l0_mfn & PT_ENTRY_PRESENT)) 22.119 - panic("l1 entry not present\n"); 22.120 - 22.121 - l0_mfn &= 0xffffff000ULL; 22.122 - 22.123 - return l0_mfn + (base & 0xfff); 22.124 - } 22.125 -} 22.126 - 22.127 -static unsigned 22.128 -address(struct regs *regs, unsigned seg, unsigned off) 22.129 -{ 22.130 - uint64_t gdt_phys_base; 22.131 - unsigned long long entry; 22.132 - unsigned seg_base, seg_limit; 22.133 - unsigned entry_low, entry_high; 22.134 - 22.135 - if (seg == 0) { 22.136 - if (mode == VM86_REAL || mode == VM86_REAL_TO_PROTECTED) 22.137 - return off; 22.138 - else 22.139 - panic("segment is zero, but not in real mode!\n"); 22.140 - } 22.141 - 22.142 - if (mode == VM86_REAL || seg > oldctx.gdtr_limit || 22.143 - (mode == VM86_REAL_TO_PROTECTED && regs->cs == seg)) 22.144 - return ((seg & 0xFFFF) << 4) + off; 22.145 - 22.146 - gdt_phys_base = guest_linear_to_phys(oldctx.gdtr_base); 22.147 - if (gdt_phys_base != (uint32_t)gdt_phys_base) { 22.148 - printf("gdt base address above 4G\n"); 22.149 - cpuid_addr_value(gdt_phys_base + 8 * (seg >> 3), &entry); 22.150 - } else 22.151 - entry = ((unsigned long long *)(long)gdt_phys_base)[seg >> 3]; 22.152 - 22.153 - entry_high = entry >> 32; 22.154 - entry_low = entry & 0xFFFFFFFF; 22.155 - 22.156 - seg_base = (entry_high & 0xFF000000) | ((entry >> 16) & 0xFFFFFF); 22.157 - seg_limit = (entry_high & 0xF0000) | (entry_low & 0xFFFF); 22.158 - 22.159 - if (entry_high & 0x8000 && 22.160 - ((entry_high & 0x800000 && off >> 12 <= seg_limit) || 22.161 - (!(entry_high & 0x800000) && off <= seg_limit))) 22.162 - return seg_base + off; 22.163 - 22.164 - panic("should never reach here in function address():\n\t" 22.165 - "entry=0x%08x%08x, mode=%d, seg=0x%08x, offset=0x%08x\n", 22.166 - entry_high, entry_low, mode, seg, off); 22.167 - 22.168 - return 0; 22.169 -} 22.170 - 22.171 -#ifdef DEBUG 22.172 -void 22.173 -trace(struct regs *regs, int adjust, char *fmt, ...) 22.174 -{ 22.175 - unsigned off = regs->eip - adjust; 22.176 - va_list ap; 22.177 - 22.178 - if ((traceset & (1 << mode)) && 22.179 - (mode == VM86_REAL_TO_PROTECTED || mode == VM86_REAL)) { 22.180 - /* 16-bit, seg:off addressing */ 22.181 - unsigned addr = address(regs, regs->cs, off); 22.182 - printf("0x%08x: 0x%x:0x%04x ", addr, regs->cs, off); 22.183 - printf("(%d) ", mode); 22.184 - va_start(ap, fmt); 22.185 - vprintf(fmt, ap); 22.186 - va_end(ap); 22.187 - printf("\n"); 22.188 - } 22.189 - if ((traceset & (1 << mode)) && 22.190 - (mode == VM86_PROTECTED_TO_REAL || mode == VM86_PROTECTED)) { 22.191 - /* 16-bit, gdt addressing */ 22.192 - unsigned addr = address(regs, regs->cs, off); 22.193 - printf("0x%08x: 0x%x:0x%08x ", addr, regs->cs, off); 22.194 - printf("(%d) ", mode); 22.195 - va_start(ap, fmt); 22.196 - vprintf(fmt, ap); 22.197 - va_end(ap); 22.198 - printf("\n"); 22.199 - } 22.200 -} 22.201 -#endif /* DEBUG */ 22.202 - 22.203 -static inline unsigned 22.204 -read32(unsigned addr) 22.205 -{ 22.206 - return *(unsigned long *) addr; 22.207 -} 22.208 - 22.209 -static inline unsigned 22.210 -read16(unsigned addr) 22.211 -{ 22.212 - return *(unsigned short *) addr; 22.213 -} 22.214 - 22.215 -static inline unsigned 22.216 -read8(unsigned addr) 22.217 -{ 22.218 - return *(unsigned char *) addr; 22.219 -} 22.220 - 22.221 -static inline void 22.222 -write32(unsigned addr, unsigned value) 22.223 -{ 22.224 - *(unsigned long *) addr = value; 22.225 -} 22.226 - 22.227 -static inline void 22.228 -write16(unsigned addr, unsigned value) 22.229 -{ 22.230 - *(unsigned short *) addr = value; 22.231 -} 22.232 - 22.233 -static inline void 22.234 -write8(unsigned addr, unsigned value) 22.235 -{ 22.236 - *(unsigned char *) addr = value; 22.237 -} 22.238 - 22.239 -static inline void 22.240 -push32(struct regs *regs, unsigned value) 22.241 -{ 22.242 - regs->uesp -= 4; 22.243 - write32(address(regs, regs->uss, MASK16(regs->uesp)), value); 22.244 -} 22.245 - 22.246 -static inline void 22.247 -push16(struct regs *regs, unsigned value) 22.248 -{ 22.249 - regs->uesp -= 2; 22.250 - write16(address(regs, regs->uss, MASK16(regs->uesp)), value); 22.251 -} 22.252 - 22.253 -static inline unsigned 22.254 -pop32(struct regs *regs) 22.255 -{ 22.256 - unsigned value = read32(address(regs, regs->uss, MASK16(regs->uesp))); 22.257 - regs->uesp += 4; 22.258 - return value; 22.259 -} 22.260 - 22.261 -static inline unsigned 22.262 -pop16(struct regs *regs) 22.263 -{ 22.264 - unsigned value = read16(address(regs, regs->uss, MASK16(regs->uesp))); 22.265 - regs->uesp += 2; 22.266 - return value; 22.267 -} 22.268 - 22.269 -static inline unsigned 22.270 -fetch32(struct regs *regs) 22.271 -{ 22.272 - unsigned addr = address(regs, regs->cs, MASK16(regs->eip)); 22.273 - 22.274 - regs->eip += 4; 22.275 - return read32(addr); 22.276 -} 22.277 - 22.278 -static inline unsigned 22.279 -fetch16(struct regs *regs) 22.280 -{ 22.281 - unsigned addr = address(regs, regs->cs, MASK16(regs->eip)); 22.282 - 22.283 - regs->eip += 2; 22.284 - return read16(addr); 22.285 -} 22.286 - 22.287 -static inline unsigned 22.288 -fetch8(struct regs *regs) 22.289 -{ 22.290 - unsigned addr = address(regs, regs->cs, MASK16(regs->eip)); 22.291 - 22.292 - regs->eip++; 22.293 - return read8(addr); 22.294 -} 22.295 - 22.296 -static unsigned 22.297 -getreg32(struct regs *regs, int r) 22.298 -{ 22.299 - switch (r & 7) { 22.300 - case 0: return regs->eax; 22.301 - case 1: return regs->ecx; 22.302 - case 2: return regs->edx; 22.303 - case 3: return regs->ebx; 22.304 - case 4: return regs->uesp; 22.305 - case 5: return regs->ebp; 22.306 - case 6: return regs->esi; 22.307 - case 7: return regs->edi; 22.308 - } 22.309 - return ~0; 22.310 -} 22.311 - 22.312 -static unsigned 22.313 -getreg16(struct regs *regs, int r) 22.314 -{ 22.315 - return MASK16(getreg32(regs, r)); 22.316 -} 22.317 - 22.318 -static unsigned 22.319 -getreg8(struct regs *regs, int r) 22.320 -{ 22.321 - switch (r & 7) { 22.322 - case 0: return regs->eax & 0xFF; /* al */ 22.323 - case 1: return regs->ecx & 0xFF; /* cl */ 22.324 - case 2: return regs->edx & 0xFF; /* dl */ 22.325 - case 3: return regs->ebx & 0xFF; /* bl */ 22.326 - case 4: return (regs->eax >> 8) & 0xFF; /* ah */ 22.327 - case 5: return (regs->ecx >> 8) & 0xFF; /* ch */ 22.328 - case 6: return (regs->edx >> 8) & 0xFF; /* dh */ 22.329 - case 7: return (regs->ebx >> 8) & 0xFF; /* bh */ 22.330 - } 22.331 - return ~0; 22.332 -} 22.333 - 22.334 -static void 22.335 -setreg32(struct regs *regs, int r, unsigned v) 22.336 -{ 22.337 - switch (r & 7) { 22.338 - case 0: regs->eax = v; break; 22.339 - case 1: regs->ecx = v; break; 22.340 - case 2: regs->edx = v; break; 22.341 - case 3: regs->ebx = v; break; 22.342 - case 4: regs->uesp = v; break; 22.343 - case 5: regs->ebp = v; break; 22.344 - case 6: regs->esi = v; break; 22.345 - case 7: regs->edi = v; break; 22.346 - } 22.347 -} 22.348 - 22.349 -static void 22.350 -setreg16(struct regs *regs, int r, unsigned v) 22.351 -{ 22.352 - setreg32(regs, r, (getreg32(regs, r) & ~0xFFFF) | MASK16(v)); 22.353 -} 22.354 - 22.355 -static void 22.356 -setreg8(struct regs *regs, int r, unsigned v) 22.357 -{ 22.358 - v &= 0xFF; 22.359 - switch (r & 7) { 22.360 - case 0: regs->eax = (regs->eax & ~0xFF) | v; break; 22.361 - case 1: regs->ecx = (regs->ecx & ~0xFF) | v; break; 22.362 - case 2: regs->edx = (regs->edx & ~0xFF) | v; break; 22.363 - case 3: regs->ebx = (regs->ebx & ~0xFF) | v; break; 22.364 - case 4: regs->eax = (regs->eax & ~0xFF00) | (v << 8); break; 22.365 - case 5: regs->ecx = (regs->ecx & ~0xFF00) | (v << 8); break; 22.366 - case 6: regs->edx = (regs->edx & ~0xFF00) | (v << 8); break; 22.367 - case 7: regs->ebx = (regs->ebx & ~0xFF00) | (v << 8); break; 22.368 - } 22.369 -} 22.370 - 22.371 -static unsigned 22.372 -segment(unsigned prefix, struct regs *regs, unsigned seg) 22.373 -{ 22.374 - if (prefix & SEG_ES) 22.375 - seg = regs->ves; 22.376 - if (prefix & SEG_DS) 22.377 - seg = regs->vds; 22.378 - if (prefix & SEG_CS) 22.379 - seg = regs->cs; 22.380 - if (prefix & SEG_SS) 22.381 - seg = regs->uss; 22.382 - if (prefix & SEG_FS) 22.383 - seg = regs->vfs; 22.384 - if (prefix & SEG_GS) 22.385 - seg = regs->vgs; 22.386 - return seg; 22.387 -} 22.388 - 22.389 -static unsigned 22.390 -sib(struct regs *regs, int mod, unsigned byte) 22.391 -{ 22.392 - unsigned scale = (byte >> 6) & 3; 22.393 - int index = (byte >> 3) & 7; 22.394 - int base = byte & 7; 22.395 - unsigned addr = 0; 22.396 - 22.397 - switch (mod) { 22.398 - case 0: 22.399 - if (base == 5) 22.400 - addr = fetch32(regs); 22.401 - else 22.402 - addr = getreg32(regs, base); 22.403 - break; 22.404 - case 1: 22.405 - addr = getreg32(regs, base) + (char) fetch8(regs); 22.406 - break; 22.407 - case 2: 22.408 - addr = getreg32(regs, base) + fetch32(regs); 22.409 - break; 22.410 - } 22.411 - 22.412 - if (index != 4) 22.413 - addr += getreg32(regs, index) << scale; 22.414 - 22.415 - return addr; 22.416 -} 22.417 - 22.418 -/* 22.419 - * Operand (modrm) decode 22.420 - */ 22.421 -static unsigned 22.422 -operand(unsigned prefix, struct regs *regs, unsigned modrm) 22.423 -{ 22.424 - int mod, disp = 0, seg; 22.425 - 22.426 - seg = segment(prefix, regs, regs->vds); 22.427 - 22.428 - if (prefix & ADDR32) { /* 32-bit addressing */ 22.429 - switch ((mod = (modrm >> 6) & 3)) { 22.430 - case 0: 22.431 - switch (modrm & 7) { 22.432 - case 0: return address(regs, seg, regs->eax); 22.433 - case 1: return address(regs, seg, regs->ecx); 22.434 - case 2: return address(regs, seg, regs->edx); 22.435 - case 3: return address(regs, seg, regs->ebx); 22.436 - case 4: return address(regs, seg, 22.437 - sib(regs, mod, fetch8(regs))); 22.438 - case 5: return address(regs, seg, fetch32(regs)); 22.439 - case 6: return address(regs, seg, regs->esi); 22.440 - case 7: return address(regs, seg, regs->edi); 22.441 - } 22.442 - break; 22.443 - case 1: 22.444 - case 2: 22.445 - if ((modrm & 7) != 4) { 22.446 - if (mod == 1) 22.447 - disp = (char) fetch8(regs); 22.448 - else 22.449 - disp = (int) fetch32(regs); 22.450 - } 22.451 - switch (modrm & 7) { 22.452 - case 0: return address(regs, seg, regs->eax + disp); 22.453 - case 1: return address(regs, seg, regs->ecx + disp); 22.454 - case 2: return address(regs, seg, regs->edx + disp); 22.455 - case 3: return address(regs, seg, regs->ebx + disp); 22.456 - case 4: return address(regs, seg, 22.457 - sib(regs, mod, fetch8(regs))); 22.458 - case 5: return address(regs, seg, regs->ebp + disp); 22.459 - case 6: return address(regs, seg, regs->esi + disp); 22.460 - case 7: return address(regs, seg, regs->edi + disp); 22.461 - } 22.462 - break; 22.463 - case 3: 22.464 - return getreg32(regs, modrm); 22.465 - } 22.466 - } else { /* 16-bit addressing */ 22.467 - switch ((mod = (modrm >> 6) & 3)) { 22.468 - case 0: 22.469 - switch (modrm & 7) { 22.470 - case 0: return address(regs, seg, MASK16(regs->ebx) + 22.471 - MASK16(regs->esi)); 22.472 - case 1: return address(regs, seg, MASK16(regs->ebx) + 22.473 - MASK16(regs->edi)); 22.474 - case 2: return address(regs, seg, MASK16(regs->ebp) + 22.475 - MASK16(regs->esi)); 22.476 - case 3: return address(regs, seg, MASK16(regs->ebp) + 22.477 - MASK16(regs->edi)); 22.478 - case 4: return address(regs, seg, MASK16(regs->esi)); 22.479 - case 5: return address(regs, seg, MASK16(regs->edi)); 22.480 - case 6: return address(regs, seg, fetch16(regs)); 22.481 - case 7: return address(regs, seg, MASK16(regs->ebx)); 22.482 - } 22.483 - break; 22.484 - case 1: 22.485 - case 2: 22.486 - if (mod == 1) 22.487 - disp = (char) fetch8(regs); 22.488 - else 22.489 - disp = (int) fetch16(regs); 22.490 - switch (modrm & 7) { 22.491 - case 0: return address(regs, seg, MASK16(regs->ebx) + 22.492 - MASK16(regs->esi) + disp); 22.493 - case 1: return address(regs, seg, MASK16(regs->ebx) + 22.494 - MASK16(regs->edi) + disp); 22.495 - case 2: return address(regs, seg, MASK16(regs->ebp) + 22.496 - MASK16(regs->esi) + disp); 22.497 - case 3: return address(regs, seg, MASK16(regs->ebp) + 22.498 - MASK16(regs->edi) + disp); 22.499 - case 4: return address(regs, seg, 22.500 - MASK16(regs->esi) + disp); 22.501 - case 5: return address(regs, seg, 22.502 - MASK16(regs->edi) + disp); 22.503 - case 6: return address(regs, seg, 22.504 - MASK16(regs->ebp) + disp); 22.505 - case 7: return address(regs, seg, 22.506 - MASK16(regs->ebx) + disp); 22.507 - } 22.508 - break; 22.509 - case 3: 22.510 - return getreg16(regs, modrm); 22.511 - } 22.512 - } 22.513 - 22.514 - return 0; 22.515 -} 22.516 - 22.517 -/* 22.518 - * Load new IDT 22.519 - */ 22.520 -static int 22.521 -lidt(struct regs *regs, unsigned prefix, unsigned modrm) 22.522 -{ 22.523 - unsigned eip = regs->eip - 3; 22.524 - unsigned addr = operand(prefix, regs, modrm); 22.525 - 22.526 - oldctx.idtr_limit = ((struct dtr *) addr)->size; 22.527 - if ((prefix & DATA32) == 0) 22.528 - oldctx.idtr_base = ((struct dtr *) addr)->base & 0xFFFFFF; 22.529 - else 22.530 - oldctx.idtr_base = ((struct dtr *) addr)->base; 22.531 - TRACE((regs, regs->eip - eip, "lidt 0x%x <%d, 0x%x>", 22.532 - addr, oldctx.idtr_limit, oldctx.idtr_base)); 22.533 - 22.534 - return 1; 22.535 -} 22.536 - 22.537 -/* 22.538 - * Load new GDT 22.539 - */ 22.540 -static int 22.541 -lgdt(struct regs *regs, unsigned prefix, unsigned modrm) 22.542 -{ 22.543 - unsigned eip = regs->eip - 3; 22.544 - unsigned addr = operand(prefix, regs, modrm); 22.545 - 22.546 - oldctx.gdtr_limit = ((struct dtr *) addr)->size; 22.547 - if ((prefix & DATA32) == 0) 22.548 - oldctx.gdtr_base = ((struct dtr *) addr)->base & 0xFFFFFF; 22.549 - else 22.550 - oldctx.gdtr_base = ((struct dtr *) addr)->base; 22.551 - TRACE((regs, regs->eip - eip, "lgdt 0x%x <%d, 0x%x>", 22.552 - addr, oldctx.gdtr_limit, oldctx.gdtr_base)); 22.553 - 22.554 - return 1; 22.555 -} 22.556 - 22.557 -/* 22.558 - * Modify CR0 either through an lmsw instruction. 22.559 - */ 22.560 -static int 22.561 -lmsw(struct regs *regs, unsigned prefix, unsigned modrm) 22.562 -{ 22.563 - unsigned eip = regs->eip - 3; 22.564 - unsigned ax = operand(prefix, regs, modrm) & 0xF; 22.565 - unsigned cr0 = (oldctx.cr0 & 0xFFFFFFF0) | ax; 22.566 - 22.567 - TRACE((regs, regs->eip - eip, "lmsw 0x%x", ax)); 22.568 - oldctx.cr0 = cr0 | CR0_PE | CR0_NE; 22.569 - if (cr0 & CR0_PE) 22.570 - set_mode(regs, VM86_REAL_TO_PROTECTED); 22.571 - 22.572 - return 1; 22.573 -} 22.574 - 22.575 -/* 22.576 - * We need to handle moves that address memory beyond the 64KB segment 22.577 - * limit that VM8086 mode enforces. 22.578 - */ 22.579 -static int 22.580 -movr(struct regs *regs, unsigned prefix, unsigned opc) 22.581 -{ 22.582 - unsigned eip = regs->eip - 1; 22.583 - unsigned modrm = fetch8(regs); 22.584 - unsigned addr = operand(prefix, regs, modrm); 22.585 - unsigned val, r = (modrm >> 3) & 7; 22.586 - 22.587 - if ((modrm & 0xC0) == 0xC0) { 22.588 - /* 22.589 - * Emulate all guest instructions in protected to real mode. 22.590 - */ 22.591 - if (mode != VM86_PROTECTED_TO_REAL) 22.592 - return 0; 22.593 - } 22.594 - 22.595 - switch (opc) { 22.596 - case 0x88: /* addr32 mov r8, r/m8 */ 22.597 - val = getreg8(regs, r); 22.598 - TRACE((regs, regs->eip - eip, 22.599 - "movb %%e%s, *0x%x", rnames[r], addr)); 22.600 - write8(addr, val); 22.601 - return 1; 22.602 - 22.603 - case 0x8A: /* addr32 mov r/m8, r8 */ 22.604 - TRACE((regs, regs->eip - eip, 22.605 - "movb *0x%x, %%%s", addr, rnames[r])); 22.606 - setreg8(regs, r, read8(addr)); 22.607 - return 1; 22.608 - 22.609 - case 0x89: /* addr32 mov r16, r/m16 */ 22.610 - val = getreg32(regs, r); 22.611 - if ((modrm & 0xC0) == 0xC0) { 22.612 - if (prefix & DATA32) 22.613 - setreg32(regs, modrm & 7, val); 22.614 - else 22.615 - setreg16(regs, modrm & 7, MASK16(val)); 22.616 - return 1; 22.617 - } 22.618 - 22.619 - if (prefix & DATA32) { 22.620 - TRACE((regs, regs->eip - eip, 22.621 - "movl %%e%s, *0x%x", rnames[r], addr)); 22.622 - write32(addr, val); 22.623 - } else { 22.624 - TRACE((regs, regs->eip - eip, 22.625 - "movw %%%s, *0x%x", rnames[r], addr)); 22.626 - write16(addr, MASK16(val)); 22.627 - } 22.628 - return 1; 22.629 - 22.630 - case 0x8B: /* mov r/m16, r16 */ 22.631 - if ((modrm & 0xC0) == 0xC0) { 22.632 - if (prefix & DATA32) 22.633 - setreg32(regs, r, addr); 22.634 - else 22.635 - setreg16(regs, r, MASK16(addr)); 22.636 - return 1; 22.637 - } 22.638 - 22.639 - if (prefix & DATA32) { 22.640 - TRACE((regs, regs->eip - eip, 22.641 - "movl *0x%x, %%e%s", addr, rnames[r])); 22.642 - setreg32(regs, r, read32(addr)); 22.643 - } else { 22.644 - TRACE((regs, regs->eip - eip, 22.645 - "movw *0x%x, %%%s", addr, rnames[r])); 22.646 - setreg16(regs, r, read16(addr)); 22.647 - } 22.648 - return 1; 22.649 - 22.650 - case 0xC6: /* addr32 movb $imm, r/m8 */ 22.651 - if ((modrm >> 3) & 7) 22.652 - return 0; 22.653 - val = fetch8(regs); 22.654 - write8(addr, val); 22.655 - TRACE((regs, regs->eip - eip, "movb $0x%x, *0x%x", 22.656 - val, addr)); 22.657 - return 1; 22.658 - } 22.659 - return 0; 22.660 -} 22.661 - 22.662 -/* 22.663 - * We need to handle string moves that address memory beyond the 64KB segment 22.664 - * limit that VM8086 mode enforces. 22.665 - */ 22.666 -static inline int 22.667 -movs(struct regs *regs, unsigned prefix, unsigned opc) 22.668 -{ 22.669 - unsigned eip = regs->eip - 1; 22.670 - unsigned sseg = segment(prefix, regs, regs->vds); 22.671 - unsigned dseg = regs->ves; 22.672 - unsigned saddr, daddr; 22.673 - unsigned count = 1; 22.674 - int incr = ((regs->eflags & EFLAGS_DF) == 0) ? 1 : -1; 22.675 - 22.676 - saddr = address(regs, sseg, regs->esi); 22.677 - daddr = address(regs, dseg, regs->edi); 22.678 - 22.679 - if ((prefix & REP) != 0) { 22.680 - count = regs->ecx; 22.681 - regs->ecx = 0; 22.682 - } 22.683 - 22.684 - switch (opc) { 22.685 - case 0xA4: /* movsb */ 22.686 - regs->esi += (incr * count); 22.687 - regs->edi += (incr * count); 22.688 - 22.689 - while (count-- != 0) { 22.690 - write8(daddr, read8(saddr)); 22.691 - daddr += incr; 22.692 - saddr += incr; 22.693 - } 22.694 - TRACE((regs, regs->eip - eip, "movsb (%%esi),%%es:(%%edi)")); 22.695 - break; 22.696 - 22.697 - case 0xA5: /* movsw */ 22.698 - if ((prefix & DATA32) == 0) { 22.699 - incr = 2 * incr; 22.700 - regs->esi += (incr * count); 22.701 - regs->edi += (incr * count); 22.702 - 22.703 - while (count-- != 0) { 22.704 - write16(daddr, read16(saddr)); 22.705 - daddr += incr; 22.706 - saddr += incr; 22.707 - } 22.708 - } else { 22.709 - incr = 4 * incr; 22.710 - regs->esi += (incr * count); 22.711 - regs->edi += (incr * count); 22.712 - 22.713 - while (count-- != 0) { 22.714 - write32(daddr, read32(saddr)); 22.715 - daddr += incr; 22.716 - saddr += incr; 22.717 - } 22.718 - } 22.719 - TRACE((regs, regs->eip - eip, "movsw %s(%%esi),%%es:(%%edi)")); 22.720 - break; 22.721 - } 22.722 - 22.723 - return 1; 22.724 -} 22.725 - 22.726 -static inline int 22.727 -lods(struct regs *regs, unsigned prefix, unsigned opc) 22.728 -{ 22.729 - unsigned eip = regs->eip - 1; 22.730 - unsigned seg = segment(prefix, regs, regs->vds); 22.731 - unsigned addr = address(regs, seg, regs->esi); 22.732 - unsigned count = 1; 22.733 - int incr = ((regs->eflags & EFLAGS_DF) == 0) ? 1 : -1; 22.734 - 22.735 - if ((prefix & REP) != 0) { 22.736 - count = regs->ecx; 22.737 - regs->ecx = 0; 22.738 - } 22.739 - 22.740 - switch (opc) { 22.741 - case 0xAD: /* lodsw */ 22.742 - if ((prefix & DATA32) == 0) { 22.743 - incr = 2 * incr; 22.744 - regs->esi += (incr * count); 22.745 - while (count-- != 0) { 22.746 - setreg16(regs, 0, read16(addr)); 22.747 - addr += incr; 22.748 - } 22.749 - 22.750 - TRACE((regs, regs->eip - eip, "lodsw (%%esi),%%ax")); 22.751 - } else { 22.752 - incr = 4 * incr; 22.753 - regs->esi += (incr * count); 22.754 - while (count-- != 0) { 22.755 - setreg32(regs, 0, read32(addr)); 22.756 - addr += incr; 22.757 - } 22.758 - TRACE((regs, regs->eip - eip, "lodsw (%%esi),%%eax")); 22.759 - } 22.760 - break; 22.761 - } 22.762 - return 1; 22.763 -} 22.764 -/* 22.765 - * Move to and from a control register. 22.766 - */ 22.767 -static int 22.768 -movcr(struct regs *regs, unsigned prefix, unsigned opc) 22.769 -{ 22.770 - unsigned eip = regs->eip - 2; 22.771 - unsigned modrm = fetch8(regs); 22.772 - unsigned cr = (modrm >> 3) & 7; 22.773 - 22.774 - if ((modrm & 0xC0) != 0xC0) /* only registers */ 22.775 - return 0; 22.776 - 22.777 - switch (opc) { 22.778 - case 0x20: /* mov Rd, Cd */ 22.779 - TRACE((regs, regs->eip - eip, "movl %%cr%d, %%eax", cr)); 22.780 - switch (cr) { 22.781 - case 0: 22.782 - setreg32(regs, modrm, 22.783 - oldctx.cr0 & ~(CR0_PE | CR0_NE)); 22.784 - break; 22.785 - case 2: 22.786 - setreg32(regs, modrm, get_cr2()); 22.787 - break; 22.788 - case 3: 22.789 - setreg32(regs, modrm, oldctx.cr3); 22.790 - break; 22.791 - case 4: 22.792 - setreg32(regs, modrm, oldctx.cr4); 22.793 - break; 22.794 - } 22.795 - break; 22.796 - case 0x22: /* mov Cd, Rd */ 22.797 - TRACE((regs, regs->eip - eip, "movl %%eax, %%cr%d", cr)); 22.798 - switch (cr) { 22.799 - case 0: 22.800 - oldctx.cr0 = getreg32(regs, modrm) | (CR0_PE | CR0_NE); 22.801 - if (getreg32(regs, modrm) & CR0_PE) 22.802 - set_mode(regs, VM86_REAL_TO_PROTECTED); 22.803 - else 22.804 - set_mode(regs, VM86_REAL); 22.805 - break; 22.806 - case 3: 22.807 - oldctx.cr3 = getreg32(regs, modrm); 22.808 - break; 22.809 - case 4: 22.810 - oldctx.cr4 = getreg32(regs, modrm); 22.811 - break; 22.812 - } 22.813 - break; 22.814 - } 22.815 - 22.816 - return 1; 22.817 -} 22.818 - 22.819 -static inline void set_eflags_ZF(unsigned mask, unsigned v1, struct regs *regs) 22.820 -{ 22.821 - if ((v1 & mask) == 0) 22.822 - regs->eflags |= EFLAGS_ZF; 22.823 - else 22.824 - regs->eflags &= ~EFLAGS_ZF; 22.825 -} 22.826 - 22.827 -static void set_eflags_add(unsigned hi_bit_mask, unsigned v1, unsigned v2, 22.828 - unsigned result, struct regs *regs) 22.829 -{ 22.830 - int bit_count; 22.831 - unsigned tmp; 22.832 - unsigned full_mask; 22.833 - unsigned nonsign_mask; 22.834 - 22.835 - /* Carry out of high order bit? */ 22.836 - if ( v1 & v2 & hi_bit_mask ) 22.837 - regs->eflags |= EFLAGS_CF; 22.838 - else 22.839 - regs->eflags &= ~EFLAGS_CF; 22.840 - 22.841 - /* Even parity in least significant byte? */ 22.842 - tmp = result & 0xff; 22.843 - for (bit_count = 0; tmp != 0; bit_count++) 22.844 - tmp &= (tmp - 1); 22.845 - 22.846 - if (bit_count & 1) 22.847 - regs->eflags &= ~EFLAGS_PF; 22.848 - else 22.849 - regs->eflags |= EFLAGS_PF; 22.850 - 22.851 - /* Carry out of least significant BCD digit? */ 22.852 - if ( v1 & v2 & (1<<3) ) 22.853 - regs->eflags |= EFLAGS_AF; 22.854 - else 22.855 - regs->eflags &= ~EFLAGS_AF; 22.856 - 22.857 - /* Result is zero? */ 22.858 - full_mask = (hi_bit_mask - 1) | hi_bit_mask; 22.859 - set_eflags_ZF(full_mask, result, regs); 22.860 - 22.861 - /* Sign of result? */ 22.862 - if ( result & hi_bit_mask ) 22.863 - regs->eflags |= EFLAGS_SF; 22.864 - else 22.865 - regs->eflags &= ~EFLAGS_SF; 22.866 - 22.867 - /* Carry out of highest non-sign bit? */ 22.868 - nonsign_mask = (hi_bit_mask >> 1) & ~hi_bit_mask; 22.869 - if ( v1 & v2 & hi_bit_mask ) 22.870 - regs->eflags |= EFLAGS_OF; 22.871 - else 22.872 - regs->eflags &= ~EFLAGS_OF; 22.873 - 22.874 -} 22.875 - 22.876 -/* 22.877 - * We need to handle cmp opcodes that address memory beyond the 64KB 22.878 - * segment limit that VM8086 mode enforces. 22.879 - */ 22.880 -static int 22.881 -cmp(struct regs *regs, unsigned prefix, unsigned opc) 22.882 -{ 22.883 - unsigned eip = regs->eip - 1; 22.884 - unsigned modrm = fetch8(regs); 22.885 - unsigned addr = operand(prefix, regs, modrm); 22.886 - unsigned diff, val, r = (modrm >> 3) & 7; 22.887 - 22.888 - if ((modrm & 0xC0) == 0xC0) /* no registers */ 22.889 - return 0; 22.890 - 22.891 - switch (opc) { 22.892 - case 0x39: /* addr32 cmp r16, r/m16 */ 22.893 - val = getreg32(regs, r); 22.894 - if (prefix & DATA32) { 22.895 - diff = read32(addr) - val; 22.896 - set_eflags_ZF(~0, diff, regs); 22.897 - 22.898 - TRACE((regs, regs->eip - eip, 22.899 - "cmp %%e%s, *0x%x (0x%x)", 22.900 - rnames[r], addr, diff)); 22.901 - } else { 22.902 - diff = read16(addr) - val; 22.903 - set_eflags_ZF(0xFFFF, diff, regs); 22.904 - 22.905 - TRACE((regs, regs->eip - eip, 22.906 - "cmp %%%s, *0x%x (0x%x)", 22.907 - rnames[r], addr, diff)); 22.908 - } 22.909 - break; 22.910 - 22.911 - /* other cmp opcodes ... */ 22.912 - } 22.913 - return 1; 22.914 -} 22.915 - 22.916 -/* 22.917 - * We need to handle test opcodes that address memory beyond the 64KB 22.918 - * segment limit that VM8086 mode enforces. 22.919 - */ 22.920 -static int 22.921 -test(struct regs *regs, unsigned prefix, unsigned opc) 22.922 -{ 22.923 - unsigned eip = regs->eip - 1; 22.924 - unsigned modrm = fetch8(regs); 22.925 - unsigned addr = operand(prefix, regs, modrm); 22.926 - unsigned val, diff; 22.927 - 22.928 - if ((modrm & 0xC0) == 0xC0) /* no registers */ 22.929 - return 0; 22.930 - 22.931 - switch (opc) { 22.932 - case 0xF6: /* testb $imm, r/m8 */ 22.933 - if ((modrm >> 3) & 7) 22.934 - return 0; 22.935 - val = fetch8(regs); 22.936 - diff = read8(addr) & val; 22.937 - set_eflags_ZF(0xFF, diff, regs); 22.938 - 22.939 - TRACE((regs, regs->eip - eip, "testb $0x%x, *0x%x (0x%x)", 22.940 - val, addr, diff)); 22.941 - break; 22.942 - 22.943 - /* other test opcodes ... */ 22.944 - } 22.945 - 22.946 - return 1; 22.947 -} 22.948 - 22.949 -/* 22.950 - * We need to handle add opcodes that address memory beyond the 64KB 22.951 - * segment limit that VM8086 mode enforces. 22.952 - */ 22.953 -static int 22.954 -add(struct regs *regs, unsigned prefix, unsigned opc) 22.955 -{ 22.956 - unsigned eip = regs->eip - 1; 22.957 - unsigned modrm = fetch8(regs); 22.958 - unsigned addr = operand(prefix, regs, modrm); 22.959 - unsigned r = (modrm >> 3) & 7; 22.960 - 22.961 - unsigned val1 = 0; 22.962 - unsigned val2 = 0; 22.963 - unsigned result = 0; 22.964 - unsigned hi_bit; 22.965 - 22.966 - if ((modrm & 0xC0) == 0xC0) /* no registers */ 22.967 - return 0; 22.968 - 22.969 - switch (opc) { 22.970 - case 0x00: /* addr32 add r8, r/m8 */ 22.971 - val1 = getreg8(regs, r); 22.972 - val2 = read8(addr); 22.973 - result = val1 + val2; 22.974 - write8(addr, result); 22.975 - TRACE((regs, regs->eip - eip, 22.976 - "addb %%e%s, *0x%x", rnames[r], addr)); 22.977 - break; 22.978 - 22.979 - case 0x01: /* addr32 add r16, r/m16 */ 22.980 - if (prefix & DATA32) { 22.981 - val1 = getreg32(regs, r); 22.982 - val2 = read32(addr); 22.983 - result = val1 + val2; 22.984 - write32(addr, result); 22.985 - TRACE((regs, regs->eip - eip, 22.986 - "addl %%e%s, *0x%x", rnames[r], addr)); 22.987 - } else { 22.988 - val1 = getreg16(regs, r); 22.989 - val2 = read16(addr); 22.990 - result = val1 + val2; 22.991 - write16(addr, result); 22.992 - TRACE((regs, regs->eip - eip, 22.993 - "addw %%e%s, *0x%x", rnames[r], addr)); 22.994 - } 22.995 - break; 22.996 - 22.997 - case 0x03: /* addr32 add r/m16, r16 */ 22.998 - if (prefix & DATA32) { 22.999 - val1 = getreg32(regs, r); 22.1000 - val2 = read32(addr); 22.1001 - result = val1 + val2; 22.1002 - setreg32(regs, r, result); 22.1003 - TRACE((regs, regs->eip - eip, 22.1004 - "addl *0x%x, %%e%s", addr, rnames[r])); 22.1005 - } else { 22.1006 - val1 = getreg16(regs, r); 22.1007 - val2 = read16(addr); 22.1008 - result = val1 + val2; 22.1009 - setreg16(regs, r, result); 22.1010 - TRACE((regs, regs->eip - eip, 22.1011 - "addw *0x%x, %%%s", addr, rnames[r])); 22.1012 - } 22.1013 - break; 22.1014 - } 22.1015 - 22.1016 - if (opc == 0x00) 22.1017 - hi_bit = (1<<7); 22.1018 - else 22.1019 - hi_bit = (prefix & DATA32) ? (1<<31) : (1<<15); 22.1020 - set_eflags_add(hi_bit, val1, val2, result, regs); 22.1021 - 22.1022 - return 1; 22.1023 -} 22.1024 - 22.1025 -/* 22.1026 - * We need to handle pop opcodes that address memory beyond the 64KB 22.1027 - * segment limit that VM8086 mode enforces. 22.1028 - */ 22.1029 -static int 22.1030 -pop(struct regs *regs, unsigned prefix, unsigned opc) 22.1031 -{ 22.1032 - unsigned eip = regs->eip - 1; 22.1033 - unsigned modrm = fetch8(regs); 22.1034 - unsigned addr = operand(prefix, regs, modrm); 22.1035 - 22.1036 - if ((modrm & 0xC0) == 0xC0) /* no registers */ 22.1037 - return 0; 22.1038 - 22.1039 - switch (opc) { 22.1040 - case 0x8F: /* pop r/m16 */ 22.1041 - if ((modrm >> 3) & 7) 22.1042 - return 0; 22.1043 - if (prefix & DATA32) 22.1044 - write32(addr, pop32(regs)); 22.1045 - else 22.1046 - write16(addr, pop16(regs)); 22.1047 - TRACE((regs, regs->eip - eip, "pop *0x%x", addr)); 22.1048 - break; 22.1049 - 22.1050 - /* other pop opcodes ... */ 22.1051 - } 22.1052 - 22.1053 - return 1; 22.1054 -} 22.1055 - 22.1056 -static int 22.1057 -mov_to_seg(struct regs *regs, unsigned prefix, unsigned opc) 22.1058 -{ 22.1059 - unsigned modrm = fetch8(regs); 22.1060 - 22.1061 - /* 22.1062 - * Emulate segment loads in: 22.1063 - * 1) real->protected mode. 22.1064 - * 2) protected->real mode. 22.1065 - */ 22.1066 - if (mode != VM86_REAL_TO_PROTECTED && 22.1067 - mode != VM86_PROTECTED_TO_REAL) 22.1068 - return 0; 22.1069 - 22.1070 - /* Register source only. */ 22.1071 - if ((modrm & 0xC0) != 0xC0) 22.1072 - goto fail; 22.1073 - 22.1074 - switch ((modrm & 0x38) >> 3) { 22.1075 - case 0: /* es */ 22.1076 - regs->ves = getreg16(regs, modrm); 22.1077 - if (mode == VM86_PROTECTED_TO_REAL) 22.1078 - return 1; 22.1079 - saved_rm_regs.ves = 0; 22.1080 - oldctx.es_sel = regs->ves; 22.1081 - return 1; 22.1082 - 22.1083 - /* case 1: cs */ 22.1084 - 22.1085 - case 2: /* ss */ 22.1086 - regs->uss = getreg16(regs, modrm); 22.1087 - if (mode == VM86_PROTECTED_TO_REAL) 22.1088 - return 1; 22.1089 - saved_rm_regs.uss = 0; 22.1090 - oldctx.ss_sel = regs->uss; 22.1091 - return 1; 22.1092 - case 3: /* ds */ 22.1093 - regs->vds = getreg16(regs, modrm); 22.1094 - if (mode == VM86_PROTECTED_TO_REAL) 22.1095 - return 1; 22.1096 - saved_rm_regs.vds = 0; 22.1097 - oldctx.ds_sel = regs->vds; 22.1098 - return 1; 22.1099 - case 4: /* fs */ 22.1100 - regs->vfs = getreg16(regs, modrm); 22.1101 - if (mode == VM86_PROTECTED_TO_REAL) 22.1102 - return 1; 22.1103 - saved_rm_regs.vfs = 0; 22.1104 - oldctx.fs_sel = regs->vfs; 22.1105 - return 1; 22.1106 - case 5: /* gs */ 22.1107 - regs->vgs = getreg16(regs, modrm); 22.1108 - if (mode == VM86_PROTECTED_TO_REAL) 22.1109 - return 1; 22.1110 - saved_rm_regs.vgs = 0; 22.1111 - oldctx.gs_sel = regs->vgs; 22.1112 - return 1; 22.1113 - } 22.1114 - 22.1115 - fail: 22.1116 - printf("%s:%d: missed opcode %02x %02x\n", 22.1117 - __FUNCTION__, __LINE__, opc, modrm); 22.1118 - return 0; 22.1119 -} 22.1120 - 22.1121 -/* 22.1122 - * Emulate a segment load in protected mode 22.1123 - */ 22.1124 -static int 22.1125 -load_seg(unsigned long sel, uint32_t *base, uint32_t *limit, union vmcs_arbytes *arbytes) 22.1126 -{ 22.1127 - uint64_t gdt_phys_base; 22.1128 - unsigned long long entry; 22.1129 - 22.1130 - /* protected mode: use seg as index into gdt */ 22.1131 - if (sel > oldctx.gdtr_limit) 22.1132 - return 0; 22.1133 - 22.1134 - if (sel == 0) { 22.1135 - arbytes->fields.null_bit = 1; 22.1136 - return 1; 22.1137 - } 22.1138 - 22.1139 - gdt_phys_base = guest_linear_to_phys(oldctx.gdtr_base); 22.1140 - if (gdt_phys_base != (uint32_t)gdt_phys_base) { 22.1141 - printf("gdt base address above 4G\n"); 22.1142 - cpuid_addr_value(gdt_phys_base + 8 * (sel >> 3), &entry); 22.1143 - } else 22.1144 - entry = ((unsigned long long *)(long)gdt_phys_base)[sel >> 3]; 22.1145 - 22.1146 - /* Check the P bit first */ 22.1147 - if (!((entry >> (15+32)) & 0x1) && sel != 0) 22.1148 - return 0; 22.1149 - 22.1150 - *base = (((entry >> (56-24)) & 0xFF000000) | 22.1151 - ((entry >> (32-16)) & 0x00FF0000) | 22.1152 - ((entry >> ( 16)) & 0x0000FFFF)); 22.1153 - *limit = (((entry >> (48-16)) & 0x000F0000) | 22.1154 - (entry & 0x0000FFFF)); 22.1155 - 22.1156 - arbytes->bytes = 0; 22.1157 - arbytes->fields.seg_type = (entry >> (8+32)) & 0xF; /* TYPE */ 22.1158 - arbytes->fields.s = (entry >> (12+32)) & 0x1; /* S */ 22.1159 - if (arbytes->fields.s) 22.1160 - arbytes->fields.seg_type |= 1; /* accessed */ 22.1161 - arbytes->fields.dpl = (entry >> (13+32)) & 0x3; /* DPL */ 22.1162 - arbytes->fields.p = (entry >> (15+32)) & 0x1; /* P */ 22.1163 - arbytes->fields.avl = (entry >> (20+32)) & 0x1; /* AVL */ 22.1164 - arbytes->fields.default_ops_size = (entry >> (22+32)) & 0x1; /* D */ 22.1165 - 22.1166 - if (entry & (1ULL << (23+32))) { /* G */ 22.1167 - arbytes->fields.g = 1; 22.1168 - *limit = (*limit << 12) | 0xFFF; 22.1169 - } 22.1170 - 22.1171 - return 1; 22.1172 -} 22.1173 - 22.1174 -/* 22.1175 - * Emulate a protected mode segment load, falling back to clearing it if 22.1176 - * the descriptor was invalid. 22.1177 - */ 22.1178 -static void 22.1179 -load_or_clear_seg(unsigned long sel, uint32_t *base, uint32_t *limit, union vmcs_arbytes *arbytes) 22.1180 -{ 22.1181 - if (!load_seg(sel, base, limit, arbytes)) 22.1182 - load_seg(0, base, limit, arbytes); 22.1183 -} 22.1184 - 22.1185 -static unsigned char rm_irqbase[2]; 22.1186 - 22.1187 -/* 22.1188 - * Transition to protected mode 22.1189 - */ 22.1190 -static void 22.1191 -protected_mode(struct regs *regs) 22.1192 -{ 22.1193 - extern char stack_top[]; 22.1194 - 22.1195 - oldctx.rm_irqbase[0] = rm_irqbase[0]; 22.1196 - oldctx.rm_irqbase[1] = rm_irqbase[1]; 22.1197 - 22.1198 - regs->eflags &= ~(EFLAGS_TF|EFLAGS_VM); 22.1199 - 22.1200 - oldctx.eip = regs->eip; 22.1201 - oldctx.esp = regs->uesp; 22.1202 - oldctx.eflags = regs->eflags; 22.1203 - 22.1204 - /* reload all segment registers */ 22.1205 - if (!load_seg(regs->cs, &oldctx.cs_base, 22.1206 - &oldctx.cs_limit, &oldctx.cs_arbytes)) 22.1207 - panic("Invalid %%cs=0x%x for protected mode\n", regs->cs); 22.1208 - oldctx.cs_sel = regs->cs; 22.1209 - 22.1210 - load_or_clear_seg(oldctx.es_sel, &oldctx.es_base, 22.1211 - &oldctx.es_limit, &oldctx.es_arbytes); 22.1212 - load_or_clear_seg(oldctx.ss_sel, &oldctx.ss_base, 22.1213 - &oldctx.ss_limit, &oldctx.ss_arbytes); 22.1214 - load_or_clear_seg(oldctx.ds_sel, &oldctx.ds_base, 22.1215 - &oldctx.ds_limit, &oldctx.ds_arbytes); 22.1216 - load_or_clear_seg(oldctx.fs_sel, &oldctx.fs_base, 22.1217 - &oldctx.fs_limit, &oldctx.fs_arbytes); 22.1218 - load_or_clear_seg(oldctx.gs_sel, &oldctx.gs_base, 22.1219 - &oldctx.gs_limit, &oldctx.gs_arbytes); 22.1220 - 22.1221 - /* initialize jump environment to warp back to protected mode */ 22.1222 - regs->uss = DATA_SELECTOR; 22.1223 - regs->uesp = (unsigned long)stack_top; 22.1224 - regs->cs = CODE_SELECTOR; 22.1225 - regs->eip = (unsigned long)switch_to_protected_mode; 22.1226 - 22.1227 - /* this should get us into 32-bit mode */ 22.1228 -} 22.1229 - 22.1230 -/* 22.1231 - * Start real-mode emulation 22.1232 - */ 22.1233 -static void 22.1234 -real_mode(struct regs *regs) 22.1235 -{ 22.1236 - regs->eflags |= EFLAGS_VM | 0x02; 22.1237 - 22.1238 - /* 22.1239 - * When we transition from protected to real-mode and we 22.1240 - * have not reloaded the segment descriptors yet, they are 22.1241 - * interpreted as if they were in protect mode. 22.1242 - * We emulate this behavior by assuming that these memory 22.1243 - * reference are below 1MB and set %ss, %ds, %es accordingly. 22.1244 - */ 22.1245 - if (regs->uss != 0) { 22.1246 - if (regs->uss >= HIGHMEM) 22.1247 - panic("%%ss 0x%lx higher than 1MB", regs->uss); 22.1248 - regs->uss = address(regs, regs->uss, 0) >> 4; 22.1249 - } else { 22.1250 - regs->uss = saved_rm_regs.uss; 22.1251 - } 22.1252 - if (regs->vds != 0) { 22.1253 - if (regs->vds >= HIGHMEM) 22.1254 - panic("%%ds 0x%lx higher than 1MB", regs->vds); 22.1255 - regs->vds = address(regs, regs->vds, 0) >> 4; 22.1256 - } else { 22.1257 - regs->vds = saved_rm_regs.vds; 22.1258 - } 22.1259 - if (regs->ves != 0) { 22.1260 - if (regs->ves >= HIGHMEM) 22.1261 - panic("%%es 0x%lx higher than 1MB", regs->ves); 22.1262 - regs->ves = address(regs, regs->ves, 0) >> 4; 22.1263 - } else { 22.1264 - regs->ves = saved_rm_regs.ves; 22.1265 - } 22.1266 - 22.1267 - /* this should get us into 16-bit mode */ 22.1268 -} 22.1269 - 22.1270 -/* 22.1271 - * This is the smarts of the emulator and handles the mode transitions. The 22.1272 - * emulator handles 4 different modes. 1) VM86_REAL: emulated real-mode, 22.1273 - * Just handle those instructions that are not supported under VM8086. 22.1274 - * 2) VM86_REAL_TO_PROTECTED: going from real-mode to protected mode. In 22.1275 - * this we single step through the instructions until we reload the 22.1276 - * new %cs (some OSes do a lot of computations before reloading %cs). 2) 22.1277 - * VM86_PROTECTED_TO_REAL when we are going from protected to real mode. In 22.1278 - * this case we emulate the instructions by hand. Finally, 4) VM86_PROTECTED 22.1279 - * when we transitioned to protected mode and we should abandon the 22.1280 - * emulator. No instructions are emulated when in VM86_PROTECTED mode. 22.1281 - */ 22.1282 -void 22.1283 -set_mode(struct regs *regs, enum vm86_mode newmode) 22.1284 -{ 22.1285 - switch (newmode) { 22.1286 - case VM86_REAL: 22.1287 - if (mode == VM86_PROTECTED_TO_REAL || 22.1288 - mode == VM86_REAL_TO_PROTECTED) { 22.1289 - regs->eflags &= ~EFLAGS_TF; 22.1290 - real_mode(regs); 22.1291 - } else if (mode != VM86_REAL) 22.1292 - panic("unexpected real mode transition"); 22.1293 - break; 22.1294 - 22.1295 - case VM86_REAL_TO_PROTECTED: 22.1296 - if (mode == VM86_REAL) { 22.1297 - regs->eflags |= EFLAGS_TF; 22.1298 - saved_rm_regs.vds = regs->vds; 22.1299 - saved_rm_regs.ves = regs->ves; 22.1300 - saved_rm_regs.vfs = regs->vfs; 22.1301 - saved_rm_regs.vgs = regs->vgs; 22.1302 - saved_rm_regs.uss = regs->uss; 22.1303 - oldctx.ds_sel = 0; 22.1304 - oldctx.es_sel = 0; 22.1305 - oldctx.fs_sel = 0; 22.1306 - oldctx.gs_sel = 0; 22.1307 - oldctx.ss_sel = 0; 22.1308 - } else if (mode != VM86_REAL_TO_PROTECTED) 22.1309 - panic("unexpected real-to-protected mode transition"); 22.1310 - break; 22.1311 - 22.1312 - case VM86_PROTECTED_TO_REAL: 22.1313 - if (mode != VM86_PROTECTED) 22.1314 - panic("unexpected protected-to-real mode transition"); 22.1315 - break; 22.1316 - 22.1317 - case VM86_PROTECTED: 22.1318 - if (mode != VM86_REAL_TO_PROTECTED) 22.1319 - panic("unexpected protected mode transition"); 22.1320 - protected_mode(regs); 22.1321 - break; 22.1322 - } 22.1323 - 22.1324 - mode = newmode; 22.1325 - if (mode != VM86_PROTECTED) 22.1326 - TRACE((regs, 0, states[mode])); 22.1327 -} 22.1328 - 22.1329 -static void 22.1330 -jmpl(struct regs *regs, int prefix) 22.1331 -{ 22.1332 - unsigned n = regs->eip; 22.1333 - unsigned cs, eip; 22.1334 - 22.1335 - eip = (prefix & DATA32) ? fetch32(regs) : fetch16(regs); 22.1336 - cs = fetch16(regs); 22.1337 - 22.1338 - TRACE((regs, (regs->eip - n) + 1, "jmpl 0x%x:0x%x", cs, eip)); 22.1339 - 22.1340 - regs->cs = cs; 22.1341 - regs->eip = eip; 22.1342 - 22.1343 - if (mode == VM86_REAL_TO_PROTECTED) /* jump to protected mode */ 22.1344 - set_mode(regs, VM86_PROTECTED); 22.1345 - else if (mode == VM86_PROTECTED_TO_REAL) /* jump to real mode */ 22.1346 - set_mode(regs, VM86_REAL); 22.1347 - else 22.1348 - panic("jmpl"); 22.1349 -} 22.1350 - 22.1351 -static void 22.1352 -jmpl_indirect(struct regs *regs, int prefix, unsigned modrm) 22.1353 -{ 22.1354 - unsigned n = regs->eip; 22.1355 - unsigned cs, eip; 22.1356 - unsigned addr; 22.1357 - 22.1358 - addr = operand(prefix, regs, modrm); 22.1359 - 22.1360 - eip = (prefix & DATA32) ? read32(addr) : read16(addr); 22.1361 - addr += (prefix & DATA32) ? 4 : 2; 22.1362 - cs = read16(addr); 22.1363 - 22.1364 - TRACE((regs, (regs->eip - n) + 1, "jmpl 0x%x:0x%x", cs, eip)); 22.1365 - 22.1366 - regs->cs = cs; 22.1367 - regs->eip = eip; 22.1368 - 22.1369 - if (mode == VM86_REAL_TO_PROTECTED) /* jump to protected mode */ 22.1370 - set_mode(regs, VM86_PROTECTED); 22.1371 - else if (mode == VM86_PROTECTED_TO_REAL) /* jump to real mode */ 22.1372 - set_mode(regs, VM86_REAL); 22.1373 - else 22.1374 - panic("jmpl"); 22.1375 -} 22.1376 - 22.1377 -static void 22.1378 -retl(struct regs *regs, int prefix) 22.1379 -{ 22.1380 - unsigned cs, eip; 22.1381 - 22.1382 - if (prefix & DATA32) { 22.1383 - eip = pop32(regs); 22.1384 - cs = MASK16(pop32(regs)); 22.1385 - } else { 22.1386 - eip = pop16(regs); 22.1387 - cs = pop16(regs); 22.1388 - } 22.1389 - 22.1390 - TRACE((regs, 1, "retl (to 0x%x:0x%x)", cs, eip)); 22.1391 - 22.1392 - regs->cs = cs; 22.1393 - regs->eip = eip; 22.1394 - 22.1395 - if (mode == VM86_REAL_TO_PROTECTED) /* jump to protected mode */ 22.1396 - set_mode(regs, VM86_PROTECTED); 22.1397 - else if (mode == VM86_PROTECTED_TO_REAL) /* jump to real mode */ 22.1398 - set_mode(regs, VM86_REAL); 22.1399 - else 22.1400 - panic("retl"); 22.1401 -} 22.1402 - 22.1403 -static void 22.1404 -interrupt(struct regs *regs, int n) 22.1405 -{ 22.1406 - TRACE((regs, 0, "external interrupt %d", n)); 22.1407 - push16(regs, regs->eflags); 22.1408 - push16(regs, regs->cs); 22.1409 - push16(regs, regs->eip); 22.1410 - regs->eflags &= ~EFLAGS_IF; 22.1411 - regs->eip = read16(address(regs, 0, n * 4)); 22.1412 - regs->cs = read16(address(regs, 0, n * 4 + 2)); 22.1413 -} 22.1414 - 22.1415 -/* 22.1416 - * Most port I/O operations are passed unmodified. We do have to be 22.1417 - * careful and make sure the emulated program isn't remapping the 22.1418 - * interrupt vectors. The following simple state machine catches 22.1419 - * these attempts and rewrites them. 22.1420 - */ 22.1421 -static int 22.1422 -outbyte(struct regs *regs, unsigned prefix, unsigned opc) 22.1423 -{ 22.1424 - static char icw2[2] = { 0 }; 22.1425 - int al, port; 22.1426 - 22.1427 - switch (opc) { 22.1428 - case 0xE6: /* outb port, al */ 22.1429 - port = fetch8(regs); 22.1430 - break; 22.1431 - case 0xEE: /* outb (%dx), al */ 22.1432 - port = MASK16(regs->edx); 22.1433 - break; 22.1434 - default: 22.1435 - return 0; 22.1436 - } 22.1437 - 22.1438 - al = regs->eax & 0xFF; 22.1439 - 22.1440 - switch (port) { 22.1441 - case PIC_MASTER + PIC_CMD: 22.1442 - if (al & (1 << 4)) /* A0=0,D4=1 -> ICW1 */ 22.1443 - icw2[0] = 1; 22.1444 - break; 22.1445 - case PIC_MASTER + PIC_IMR: 22.1446 - if (icw2[0]) { 22.1447 - icw2[0] = 0; 22.1448 - printf("Remapping master: ICW2 0x%x -> 0x%x\n", 22.1449 - al, NR_EXCEPTION_HANDLER); 22.1450 - rm_irqbase[0] = al; 22.1451 - al = NR_EXCEPTION_HANDLER; 22.1452 - } 22.1453 - break; 22.1454 - 22.1455 - case PIC_SLAVE + PIC_CMD: 22.1456 - if (al & (1 << 4)) /* A0=0,D4=1 -> ICW1 */ 22.1457 - icw2[1] = 1; 22.1458 - break; 22.1459 - case PIC_SLAVE + PIC_IMR: 22.1460 - if (icw2[1]) { 22.1461 - icw2[1] = 0; 22.1462 - printf("Remapping slave: ICW2 0x%x -> 0x%x\n", 22.1463 - al, NR_EXCEPTION_HANDLER+8); 22.1464 - rm_irqbase[1] = al; 22.1465 - al = NR_EXCEPTION_HANDLER+8; 22.1466 - } 22.1467 - break; 22.1468 - } 22.1469 - 22.1470 - outb(port, al); 22.1471 - return 1; 22.1472 -} 22.1473 - 22.1474 -static int 22.1475 -inbyte(struct regs *regs, unsigned prefix, unsigned opc) 22.1476 -{ 22.1477 - int port; 22.1478 - 22.1479 - switch (opc) { 22.1480 - case 0xE4: /* inb al, port */ 22.1481 - port = fetch8(regs); 22.1482 - break; 22.1483 - case 0xEC: /* inb al, (%dx) */ 22.1484 - port = MASK16(regs->edx); 22.1485 - break; 22.1486 - default: 22.1487 - return 0; 22.1488 - } 22.1489 - 22.1490 - regs->eax = (regs->eax & ~0xFF) | inb(port); 22.1491 - return 1; 22.1492 -} 22.1493 - 22.1494 -static void 22.1495 -pushrm(struct regs *regs, int prefix, unsigned modrm) 22.1496 -{ 22.1497 - unsigned n = regs->eip; 22.1498 - unsigned addr; 22.1499 - unsigned data; 22.1500 - 22.1501 - addr = operand(prefix, regs, modrm); 22.1502 - 22.1503 - if (prefix & DATA32) { 22.1504 - data = read32(addr); 22.1505 - push32(regs, data); 22.1506 - } else { 22.1507 - data = read16(addr); 22.1508 - push16(regs, data); 22.1509 - } 22.1510 - 22.1511 - TRACE((regs, (regs->eip - n) + 1, "push *0x%x", addr)); 22.1512 -} 22.1513 - 22.1514 -enum { OPC_INVALID, OPC_EMULATED }; 22.1515 - 22.1516 -#define rdmsr(msr,val1,val2) \ 22.1517 - __asm__ __volatile__( \ 22.1518 - "rdmsr" \ 22.1519 - : "=a" (val1), "=d" (val2) \ 22.1520 - : "c" (msr)) 22.1521 - 22.1522 -#define wrmsr(msr,val1,val2) \ 22.1523 - __asm__ __volatile__( \ 22.1524 - "wrmsr" \ 22.1525 - : /* no outputs */ \ 22.1526 - : "c" (msr), "a" (val1), "d" (val2)) 22.1527 - 22.1528 -/* 22.1529 - * Emulate a single instruction, including all its prefixes. We only implement 22.1530 - * a small subset of the opcodes, and not all opcodes are implemented for each 22.1531 - * of the four modes we can operate in. 22.1532 - */ 22.1533 -static int 22.1534 -opcode(struct regs *regs) 22.1535 -{ 22.1536 - unsigned eip = regs->eip; 22.1537 - unsigned opc, modrm, disp; 22.1538 - unsigned prefix = 0; 22.1539 - 22.1540 - if (mode == VM86_PROTECTED_TO_REAL && 22.1541 - oldctx.cs_arbytes.fields.default_ops_size) { 22.1542 - prefix |= DATA32; 22.1543 - prefix |= ADDR32; 22.1544 - } 22.1545 - 22.1546 - for (;;) { 22.1547 - switch ((opc = fetch8(regs))) { 22.1548 - 22.1549 - case 0x00: /* addr32 add r8, r/m8 */ 22.1550 - case 0x01: /* addr32 add r16, r/m16 */ 22.1551 - case 0x03: /* addr32 add r/m16, r16 */ 22.1552 - if (mode != VM86_REAL && mode != VM86_REAL_TO_PROTECTED) 22.1553 - goto invalid; 22.1554 - if ((prefix & ADDR32) == 0) 22.1555 - goto invalid; 22.1556 - if (!add(regs, prefix, opc)) 22.1557 - goto invalid; 22.1558 - return OPC_EMULATED; 22.1559 - 22.1560 - case 0x07: /* pop %es */ 22.1561 - regs->ves = (prefix & DATA32) ? 22.1562 - pop32(regs) : pop16(regs); 22.1563 - TRACE((regs, regs->eip - eip, "pop %%es")); 22.1564 - if (mode == VM86_REAL_TO_PROTECTED) { 22.1565 - saved_rm_regs.ves = 0; 22.1566 - oldctx.es_sel = regs->ves; 22.1567 - } 22.1568 - return OPC_EMULATED; 22.1569 - 22.1570 - case 0x0F: /* two byte opcode */ 22.1571 - if (mode == VM86_PROTECTED) 22.1572 - goto invalid; 22.1573 - switch ((opc = fetch8(regs))) { 22.1574 - case 0x01: 22.1575 - switch (((modrm = fetch8(regs)) >> 3) & 7) { 22.1576 - case 0: /* sgdt */ 22.1577 - case 1: /* sidt */ 22.1578 - goto invalid; 22.1579 - case 2: /* lgdt */ 22.1580 - if (!lgdt(regs, prefix, modrm)) 22.1581 - goto invalid; 22.1582 - return OPC_EMULATED; 22.1583 - case 3: /* lidt */ 22.1584 - if (!lidt(regs, prefix, modrm)) 22.1585 - goto invalid; 22.1586 - return OPC_EMULATED; 22.1587 - case 4: /* smsw */ 22.1588 - goto invalid; 22.1589 - case 5: 22.1590 - goto invalid; 22.1591 - case 6: /* lmsw */ 22.1592 - if (!lmsw(regs, prefix, modrm)) 22.1593 - goto invalid; 22.1594 - return OPC_EMULATED; 22.1595 - case 7: /* invlpg */ 22.1596 - goto invalid; 22.1597 - } 22.1598 - break; 22.1599 - case 0x06: /* clts */ 22.1600 - oldctx.cr0 &= ~CR0_TS; 22.1601 - return OPC_EMULATED; 22.1602 - case 0x09: /* wbinvd */ 22.1603 - return OPC_EMULATED; 22.1604 - case 0x20: /* mov Rd, Cd (1h) */ 22.1605 - case 0x22: 22.1606 - if (!movcr(regs, prefix, opc)) 22.1607 - goto invalid; 22.1608 - return OPC_EMULATED; 22.1609 - case 0x30: /* WRMSR */ 22.1610 - wrmsr(regs->ecx, regs->eax, regs->edx); 22.1611 - return OPC_EMULATED; 22.1612 - case 0x32: /* RDMSR */ 22.1613 - rdmsr(regs->ecx, regs->eax, regs->edx); 22.1614 - return OPC_EMULATED; 22.1615 - default: 22.1616 - goto invalid; 22.1617 - } 22.1618 - goto invalid; 22.1619 - 22.1620 - case 0x1F: /* pop %ds */ 22.1621 - regs->vds = (prefix & DATA32) ? 22.1622 - pop32(regs) : pop16(regs); 22.1623 - TRACE((regs, regs->eip - eip, "pop %%ds")); 22.1624 - if (mode == VM86_REAL_TO_PROTECTED) { 22.1625 - saved_rm_regs.vds = 0; 22.1626 - oldctx.ds_sel = regs->vds; 22.1627 - } 22.1628 - return OPC_EMULATED; 22.1629 - 22.1630 - case 0x26: 22.1631 - TRACE((regs, regs->eip - eip, "%%es:")); 22.1632 - prefix |= SEG_ES; 22.1633 - continue; 22.1634 - 22.1635 - case 0x2E: 22.1636 - TRACE((regs, regs->eip - eip, "%%cs:")); 22.1637 - prefix |= SEG_CS; 22.1638 - continue; 22.1639 - 22.1640 - case 0x36: 22.1641 - TRACE((regs, regs->eip - eip, "%%ss:")); 22.1642 - prefix |= SEG_SS; 22.1643 - continue; 22.1644 - 22.1645 - case 0x39: /* addr32 cmp r16, r/m16 */ 22.1646 - case 0x3B: /* addr32 cmp r/m16, r16 */ 22.1647 - if (mode == VM86_PROTECTED_TO_REAL || !(prefix & ADDR32)) 22.1648 - goto invalid; 22.1649 - if (!cmp(regs, prefix, opc)) 22.1650 - goto invalid; 22.1651 - return OPC_EMULATED; 22.1652 - 22.1653 - case 0x3E: 22.1654 - TRACE((regs, regs->eip - eip, "%%ds:")); 22.1655 - prefix |= SEG_DS; 22.1656 - continue; 22.1657 - 22.1658 - case 0x64: 22.1659 - TRACE((regs, regs->eip - eip, "%%fs:")); 22.1660 - prefix |= SEG_FS; 22.1661 - continue; 22.1662 - 22.1663 - case 0x65: 22.1664 - TRACE((regs, regs->eip - eip, "%%gs:")); 22.1665 - prefix |= SEG_GS; 22.1666 - continue; 22.1667 - 22.1668 - case 0x66: 22.1669 - if (mode == VM86_PROTECTED_TO_REAL && 22.1670 - oldctx.cs_arbytes.fields.default_ops_size) { 22.1671 - TRACE((regs, regs->eip - eip, "data16")); 22.1672 - prefix &= ~DATA32; 22.1673 - } else { 22.1674 - TRACE((regs, regs->eip - eip, "data32")); 22.1675 - prefix |= DATA32; 22.1676 - } 22.1677 - continue; 22.1678 - 22.1679 - case 0x67: 22.1680 - if (mode == VM86_PROTECTED_TO_REAL && 22.1681 - oldctx.cs_arbytes.fields.default_ops_size) { 22.1682 - TRACE((regs, regs->eip - eip, "addr16")); 22.1683 - prefix &= ~ADDR32; 22.1684 - } else { 22.1685 - TRACE((regs, regs->eip - eip, "addr32")); 22.1686 - prefix |= ADDR32; 22.1687 - } 22.1688 - continue; 22.1689 - 22.1690 - case 0x88: /* addr32 mov r8, r/m8 */ 22.1691 - case 0x8A: /* addr32 mov r/m8, r8 */ 22.1692 - if (mode == VM86_PROTECTED_TO_REAL || !(prefix & ADDR32)) 22.1693 - goto invalid; 22.1694 - if (!movr(regs, prefix, opc)) 22.1695 - goto invalid; 22.1696 - return OPC_EMULATED; 22.1697 - 22.1698 - case 0x89: /* mov r16, r/m16 */ 22.1699 - case 0x8B: /* mov r/m16, r16 */ 22.1700 - if (mode != VM86_PROTECTED_TO_REAL && !(prefix & ADDR32)) 22.1701 - goto invalid; 22.1702 - if (!movr(regs, prefix, opc)) 22.1703 - goto invalid; 22.1704 - return OPC_EMULATED; 22.1705 - 22.1706 - case 0x8E: /* mov r16, sreg */ 22.1707 - if (!mov_to_seg(regs, prefix, opc)) 22.1708 - goto invalid; 22.1709 - return OPC_EMULATED; 22.1710 - 22.1711 - case 0x8F: /* addr32 pop r/m16 */ 22.1712 - if (!(prefix & ADDR32)) 22.1713 - goto invalid; 22.1714 - if (!pop(regs, prefix, opc)) 22.1715 - goto invalid; 22.1716 - return OPC_EMULATED; 22.1717 - 22.1718 - case 0x90: /* nop */ 22.1719 - TRACE((regs, regs->eip - eip, "nop")); 22.1720 - return OPC_EMULATED; 22.1721 - 22.1722 - case 0x9C: /* pushf */ 22.1723 - TRACE((regs, regs->eip - eip, "pushf")); 22.1724 - if (prefix & DATA32) 22.1725 - push32(regs, regs->eflags & ~EFLAGS_VM); 22.1726 - else 22.1727 - push16(regs, regs->eflags & ~EFLAGS_VM); 22.1728 - return OPC_EMULATED; 22.1729 - 22.1730 - case 0x9D: /* popf */ 22.1731 - TRACE((regs, regs->eip - eip, "popf")); 22.1732 - if (prefix & DATA32) 22.1733 - regs->eflags = pop32(regs); 22.1734 - else 22.1735 - regs->eflags = (regs->eflags & 0xFFFF0000L) | 22.1736 - pop16(regs); 22.1737 - regs->eflags |= EFLAGS_VM; 22.1738 - return OPC_EMULATED; 22.1739 - 22.1740 - case 0xA1: /* mov ax, r/m16 */ 22.1741 - { 22.1742 - int addr, data; 22.1743 - int seg = segment(prefix, regs, regs->vds); 22.1744 - int offset = prefix & ADDR32 ? fetch32(regs) : fetch16(regs); 22.1745 - 22.1746 - if (prefix & DATA32) { 22.1747 - addr = address(regs, seg, offset); 22.1748 - data = read32(addr); 22.1749 - setreg32(regs, 0, data); 22.1750 - } else { 22.1751 - addr = address(regs, seg, offset); 22.1752 - data = read16(addr); 22.1753 - setreg16(regs, 0, data); 22.1754 - } 22.1755 - TRACE((regs, regs->eip - eip, "mov *0x%x, %%ax", addr)); 22.1756 - return OPC_EMULATED; 22.1757 - } 22.1758 - 22.1759 - case 0xA4: /* movsb */ 22.1760 - case 0xA5: /* movsw */ 22.1761 - if ((prefix & ADDR32) == 0) 22.1762 - goto invalid; 22.1763 - if (!movs(regs, prefix, opc)) 22.1764 - goto invalid; 22.1765 - return OPC_EMULATED; 22.1766 - 22.1767 - case 0xAD: /* lodsw */ 22.1768 - if ((prefix & ADDR32) == 0) 22.1769 - goto invalid; 22.1770 - if (!lods(regs, prefix, opc)) 22.1771 - goto invalid; 22.1772 - return OPC_EMULATED; 22.1773 - 22.1774 - case 0xBB: /* mov bx, imm16 */ 22.1775 - { 22.1776 - int data; 22.1777 - if (prefix & DATA32) { 22.1778 - data = fetch32(regs); 22.1779 - setreg32(regs, 3, data); 22.1780 - } else { 22.1781 - data = fetch16(regs); 22.1782 - setreg16(regs, 3, data); 22.1783 - } 22.1784 - TRACE((regs, regs->eip - eip, "mov $0x%x, %%bx", data)); 22.1785 - return OPC_EMULATED; 22.1786 - } 22.1787 - 22.1788 - case 0xC6: /* addr32 movb $imm, r/m8 */ 22.1789 - if (!(prefix & ADDR32)) 22.1790 - goto invalid; 22.1791 - if (!movr(regs, prefix, opc)) 22.1792 - goto invalid; 22.1793 - return OPC_EMULATED; 22.1794 - 22.1795 - case 0xCB: /* retl */ 22.1796 - if (mode == VM86_REAL_TO_PROTECTED || 22.1797 - mode == VM86_PROTECTED_TO_REAL) { 22.1798 - retl(regs, prefix); 22.1799 - return OPC_INVALID; 22.1800 - } 22.1801 - goto invalid; 22.1802 - 22.1803 - case 0xCD: /* int $n */ 22.1804 - TRACE((regs, regs->eip - eip, "int")); 22.1805 - interrupt(regs, fetch8(regs)); 22.1806 - return OPC_EMULATED; 22.1807 - 22.1808 - case 0xCF: /* iret */ 22.1809 - if (prefix & DATA32) { 22.1810 - TRACE((regs, regs->eip - eip, "data32 iretd")); 22.1811 - regs->eip = pop32(regs); 22.1812 - regs->cs = pop32(regs); 22.1813 - regs->eflags = pop32(regs); 22.1814 - } else { 22.1815 - TRACE((regs, regs->eip - eip, "iret")); 22.1816 - regs->eip = pop16(regs); 22.1817 - regs->cs = pop16(regs); 22.1818 - regs->eflags = (regs->eflags & 0xFFFF0000L) | 22.1819 - pop16(regs); 22.1820 - } 22.1821 - return OPC_EMULATED; 22.1822 - 22.1823 - case 0xE4: /* inb al, port */ 22.1824 - if (!inbyte(regs, prefix, opc)) 22.1825 - goto invalid; 22.1826 - return OPC_EMULATED; 22.1827 - 22.1828 - case 0xE6: /* outb port, al */ 22.1829 - if (!outbyte(regs, prefix, opc)) 22.1830 - goto invalid; 22.1831 - return OPC_EMULATED; 22.1832 - 22.1833 - case 0xEA: /* jmpl */ 22.1834 - if (mode == VM86_REAL_TO_PROTECTED || 22.1835 - mode == VM86_PROTECTED_TO_REAL) { 22.1836 - jmpl(regs, prefix); 22.1837 - return OPC_INVALID; 22.1838 - } 22.1839 - goto invalid; 22.1840 - 22.1841 - case 0xFF: 22.1842 - { 22.1843 - unsigned modrm = fetch8(regs); 22.1844 - switch((modrm >> 3) & 7) { 22.1845 - case 5: /* jmpl (indirect) */ 22.1846 - if (mode == VM86_REAL_TO_PROTECTED || 22.1847 - mode == VM86_PROTECTED_TO_REAL) { 22.1848 - jmpl_indirect(regs, prefix, modrm); 22.1849 - return OPC_INVALID; 22.1850 - } 22.1851 - goto invalid; 22.1852 - 22.1853 - case 6: /* push r/m16 */ 22.1854 - pushrm(regs, prefix, modrm); 22.1855 - return OPC_EMULATED; 22.1856 - 22.1857 - default: 22.1858 - goto invalid; 22.1859 - } 22.1860 - } 22.1861 - 22.1862 - case 0xEB: /* short jump */ 22.1863 - if (mode == VM86_REAL_TO_PROTECTED || 22.1864 - mode == VM86_PROTECTED_TO_REAL) { 22.1865 - disp = (char) fetch8(regs); 22.1866 - TRACE((regs, 2, "jmp 0x%x", regs->eip + disp)); 22.1867 - regs->eip += disp; 22.1868 - return OPC_EMULATED; 22.1869 - } 22.1870 - goto invalid; 22.1871 - 22.1872 - case 0xEC: /* inb al, (%dx) */ 22.1873 - if (!inbyte(regs, prefix, opc)) 22.1874 - goto invalid; 22.1875 - return OPC_EMULATED; 22.1876 - 22.1877 - case 0xEE: /* outb (%dx), al */ 22.1878 - if (!outbyte(regs, prefix, opc)) 22.1879 - goto invalid; 22.1880 - return OPC_EMULATED; 22.1881 - 22.1882 - case 0xF0: /* lock */ 22.1883 - TRACE((regs, regs->eip - eip, "lock")); 22.1884 - continue; 22.1885 - 22.1886 - case 0xF4: /* hlt */ 22.1887 - TRACE((regs, regs->eip - eip, "hlt")); 22.1888 - /* Do something power-saving here! */ 22.1889 - return OPC_EMULATED; 22.1890 - 22.1891 - case 0xF3: /* rep/repe/repz */ 22.1892 - TRACE((regs, regs->eip - eip, "rep")); 22.1893 - prefix |= REP; 22.1894 - continue; 22.1895 - 22.1896 - case 0xF6: /* addr32 testb $imm, r/m8 */ 22.1897 - if (!(prefix & ADDR32)) 22.1898 - goto invalid; 22.1899 - if (!test(regs, prefix, opc)) 22.1900 - goto invalid; 22.1901 - return OPC_EMULATED; 22.1902 - 22.1903 - case 0xFA: /* cli */ 22.1904 - TRACE((regs, regs->eip - eip, "cli")); 22.1905 - regs->eflags &= ~EFLAGS_IF; 22.1906 - return OPC_EMULATED; 22.1907 - 22.1908 - case 0xFB: /* sti */ 22.1909 - TRACE((regs, regs->eip - eip, "sti")); 22.1910 - regs->eflags |= EFLAGS_IF; 22.1911 - return OPC_EMULATED; 22.1912 - 22.1913 - default: 22.1914 - goto invalid; 22.1915 - } 22.1916 - } 22.1917 - 22.1918 -invalid: 22.1919 - regs->eip = eip; 22.1920 - TRACE((regs, regs->eip - eip, "opc 0x%x", opc)); 22.1921 - return OPC_INVALID; 22.1922 -} 22.1923 - 22.1924 -void 22.1925 -emulate(struct regs *regs) 22.1926 -{ 22.1927 - unsigned flteip; 22.1928 - int nemul = 0; 22.1929 - unsigned ip; 22.1930 - 22.1931 - /* emulate as many instructions as possible */ 22.1932 - while (opcode(regs) != OPC_INVALID) 22.1933 - nemul++; 22.1934 - 22.1935 - /* detect the case where we are not making progress */ 22.1936 - if (nemul == 0 && prev_eip == regs->eip) { 22.1937 - flteip = address(regs, MASK16(regs->cs), regs->eip); 22.1938 - 22.1939 - printf("Undecoded sequence: \n"); 22.1940 - for (ip=flteip; ip < flteip+16; ip++) 22.1941 - printf("0x%02x ", read8(ip)); 22.1942 - printf("\n"); 22.1943 - 22.1944 - panic("Unknown opcode at %04x:%04x=0x%x", 22.1945 - MASK16(regs->cs), regs->eip, flteip); 22.1946 - } else 22.1947 - prev_eip = regs->eip; 22.1948 -} 22.1949 - 22.1950 -void 22.1951 -trap(int trapno, int errno, struct regs *regs) 22.1952 -{ 22.1953 - /* emulate device interrupts */ 22.1954 - if (trapno >= NR_EXCEPTION_HANDLER) { 22.1955 - int irq = trapno - NR_EXCEPTION_HANDLER; 22.1956 - if (irq < 8) 22.1957 - interrupt(regs, irq + 8); 22.1958 - else 22.1959 - interrupt(regs, 0x70 + (irq - 8)); 22.1960 - return; 22.1961 - } 22.1962 - 22.1963 - switch (trapno) { 22.1964 - case 1: /* Debug */ 22.1965 - if (regs->eflags & EFLAGS_VM) { 22.1966 - /* emulate any 8086 instructions */ 22.1967 - if (mode == VM86_REAL) 22.1968 - return; 22.1969 - if (mode != VM86_REAL_TO_PROTECTED) 22.1970 - panic("not in real-to-protected mode"); 22.1971 - emulate(regs); 22.1972 - return; 22.1973 - } 22.1974 - goto invalid; 22.1975 - 22.1976 - case 13: /* GPF */ 22.1977 - if (regs->eflags & EFLAGS_VM) { 22.1978 - /* emulate any 8086 instructions */ 22.1979 - if (mode == VM86_PROTECTED) 22.1980 - panic("unexpected protected mode"); 22.1981 - emulate(regs); 22.1982 - return; 22.1983 - } 22.1984 - goto invalid; 22.1985 - 22.1986 - default: 22.1987 - invalid: 22.1988 - printf("Trap (0x%x) while in %s mode\n", 22.1989 - trapno, regs->eflags & EFLAGS_VM ? "real" : "protected"); 22.1990 - if (trapno == 14) 22.1991 - printf("Page fault address 0x%x\n", get_cr2()); 22.1992 - dump_regs(regs); 22.1993 - halt(); 22.1994 - } 22.1995 -}
23.1 --- a/tools/firmware/vmxassist/vm86.h Thu Feb 07 09:23:26 2008 -0700 23.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 23.3 @@ -1,64 +0,0 @@ 23.4 -/* 23.5 - * vm86.h: vm86 emulator definitions. 23.6 - * 23.7 - * Leendert van Doorn, leendert@watson.ibm.com 23.8 - * Copyright (c) 2005, International Business Machines Corporation. 23.9 - * 23.10 - * This program is free software; you can redistribute it and/or modify it 23.11 - * under the terms and conditions of the GNU General Public License, 23.12 - * version 2, as published by the Free Software Foundation. 23.13 - * 23.14 - * This program is distributed in the hope it will be useful, but WITHOUT 23.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 23.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 23.17 - * more details. 23.18 - * 23.19 - * You should have received a copy of the GNU General Public License along with 23.20 - * this program; if not, write to the Free Software Foundation, Inc., 59 Temple 23.21 - * Place - Suite 330, Boston, MA 02111-1307 USA. 23.22 - */ 23.23 -#ifndef __VM86_H__ 23.24 -#define __VM86_H__ 23.25 - 23.26 -#ifndef __ASSEMBLY__ 23.27 -#include <stdint.h> 23.28 -#endif 23.29 - 23.30 -#include <xen/hvm/vmx_assist.h> 23.31 - 23.32 -#ifndef __ASSEMBLY__ 23.33 - 23.34 -struct regs { 23.35 - unsigned edi, esi, ebp, esp, ebx, edx, ecx, eax; 23.36 - unsigned trapno, errno; 23.37 - unsigned eip, cs, eflags, uesp, uss; 23.38 - unsigned ves, vds, vfs, vgs; 23.39 -}; 23.40 - 23.41 -enum vm86_mode { 23.42 - VM86_REAL = 0, 23.43 - VM86_REAL_TO_PROTECTED, 23.44 - VM86_PROTECTED_TO_REAL, 23.45 - VM86_PROTECTED 23.46 -}; 23.47 - 23.48 -#ifdef DEBUG 23.49 -#define TRACE(a) trace a 23.50 -#else 23.51 -#define TRACE(a) 23.52 -#endif 23.53 - 23.54 -extern enum vm86_mode prevmode, mode; 23.55 -extern struct vmx_assist_context oldctx; 23.56 - 23.57 -extern void emulate(struct regs *); 23.58 -extern void dump_regs(struct regs *); 23.59 -extern void trace(struct regs *, int, char *, ...); 23.60 - 23.61 -extern void set_mode(struct regs *, enum vm86_mode); 23.62 -extern void switch_to_real_mode(void); 23.63 -extern void switch_to_protected_mode(void); 23.64 - 23.65 -#endif /* __ASSEMBLY__ */ 23.66 - 23.67 -#endif /* __VM86_H__ */
24.1 --- a/tools/firmware/vmxassist/vmxassist.ld Thu Feb 07 09:23:26 2008 -0700 24.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 24.3 @@ -1,32 +0,0 @@ 24.4 -/* 24.5 - * vmxassist.ld 24.6 - */ 24.7 -OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386") 24.8 -ENTRY(_start) 24.9 - 24.10 -SECTIONS 24.11 -{ 24.12 - _btext = .; 24.13 - .text TEXTADDR : 24.14 - { 24.15 - *(.text) 24.16 - *(.rodata) 24.17 - *(.rodata.*) 24.18 - } 24.19 - _etext = .; 24.20 - 24.21 - _bdata = .; 24.22 - .data : 24.23 - { 24.24 - *(.data) 24.25 - } 24.26 - _edata = .; 24.27 - 24.28 - _bbss = .; 24.29 - .bss : 24.30 - { 24.31 - *(.bss) 24.32 - } 24.33 - _ebss = .; 24.34 -} 24.35 -
25.1 --- a/tools/ioemu/audio/audio.c Thu Feb 07 09:23:26 2008 -0700 25.2 +++ b/tools/ioemu/audio/audio.c Thu Feb 07 11:08:49 2008 -0700 25.3 @@ -707,8 +707,8 @@ static void audio_detach_capture (HWVoic 25.4 sw->rate = NULL; 25.5 } 25.6 25.7 - LIST_REMOVE (sw, entries); 25.8 - LIST_REMOVE (sc, entries); 25.9 + QEMU_LIST_REMOVE (sw, entries); 25.10 + QEMU_LIST_REMOVE (sc, entries); 25.11 qemu_free (sc); 25.12 if (was_active) { 25.13 /* We have removed soft voice from the capture: 25.14 @@ -751,8 +751,8 @@ static int audio_attach_capture (AudioSt 25.15 qemu_free (sw); 25.16 return -1; 25.17 } 25.18 - LIST_INSERT_HEAD (&hw_cap->sw_head, sw, entries); 25.19 - LIST_INSERT_HEAD (&hw->cap_head, sc, entries); 25.20 + QEMU_LIST_INSERT_HEAD (&hw_cap->sw_head, sw, entries); 25.21 + QEMU_LIST_INSERT_HEAD (&hw->cap_head, sc, entries); 25.22 #ifdef DEBUG_CAPTURE 25.23 asprintf (&sw->name, "for %p %d,%d,%d", 25.24 hw, sw->info.freq, sw->info.bits, sw->info.nchannels); 25.25 @@ -1620,12 +1620,12 @@ void AUD_register_card (AudioState *s, c 25.26 card->audio = s; 25.27 card->name = qemu_strdup (name); 25.28 memset (&card->entries, 0, sizeof (card->entries)); 25.29 - LIST_INSERT_HEAD (&s->card_head, card, entries); 25.30 + QEMU_LIST_INSERT_HEAD (&s->card_head, card, entries); 25.31 } 25.32 25.33 void AUD_remove_card (QEMUSoundCard *card) 25.34 { 25.35 - LIST_REMOVE (card, entries); 25.36 + QEMU_LIST_REMOVE (card, entries); 25.37 card->audio = NULL; 25.38 qemu_free (card->name); 25.39 } 25.40 @@ -1637,9 +1637,9 @@ AudioState *AUD_init (void) 25.41 const char *drvname; 25.42 AudioState *s = &glob_audio_state; 25.43 25.44 - LIST_INIT (&s->hw_head_out); 25.45 - LIST_INIT (&s->hw_head_in); 25.46 - LIST_INIT (&s->cap_head); 25.47 + QEMU_LIST_INIT (&s->hw_head_out); 25.48 + QEMU_LIST_INIT (&s->hw_head_in); 25.49 + QEMU_LIST_INIT (&s->cap_head); 25.50 atexit (audio_atexit); 25.51 25.52 s->ts = qemu_new_timer (vm_clock, audio_timer, s); 25.53 @@ -1731,7 +1731,7 @@ AudioState *AUD_init (void) 25.54 return NULL; 25.55 } 25.56 25.57 - LIST_INIT (&s->card_head); 25.58 + QEMU_LIST_INIT (&s->card_head); 25.59 register_savevm ("audio", 0, 1, audio_save, audio_load, s); 25.60 qemu_mod_timer (s->ts, qemu_get_clock (vm_clock) + conf.period.ticks); 25.61 return s; 25.62 @@ -1769,7 +1769,7 @@ CaptureVoiceOut *AUD_add_capture ( 25.63 25.64 cap = audio_pcm_capture_find_specific (s, as); 25.65 if (cap) { 25.66 - LIST_INSERT_HEAD (&cap->cb_head, cb, entries); 25.67 + QEMU_LIST_INSERT_HEAD (&cap->cb_head, cb, entries); 25.68 return cap; 25.69 } 25.70 else { 25.71 @@ -1784,8 +1784,8 @@ CaptureVoiceOut *AUD_add_capture ( 25.72 } 25.73 25.74 hw = &cap->hw; 25.75 - LIST_INIT (&hw->sw_head); 25.76 - LIST_INIT (&cap->cb_head); 25.77 + QEMU_LIST_INIT (&hw->sw_head); 25.78 + QEMU_LIST_INIT (&cap->cb_head); 25.79 25.80 /* XXX find a more elegant way */ 25.81 hw->samples = 4096 * 4; 25.82 @@ -1813,8 +1813,8 @@ CaptureVoiceOut *AUD_add_capture ( 25.83 [hw->info.swap_endianness] 25.84 [hw->info.bits == 16]; 25.85 25.86 - LIST_INSERT_HEAD (&s->cap_head, cap, entries); 25.87 - LIST_INSERT_HEAD (&cap->cb_head, cb, entries); 25.88 + QEMU_LIST_INSERT_HEAD (&s->cap_head, cap, entries); 25.89 + QEMU_LIST_INSERT_HEAD (&cap->cb_head, cb, entries); 25.90 25.91 hw = NULL; 25.92 while ((hw = audio_pcm_hw_find_any_out (s, hw))) { 25.93 @@ -1840,7 +1840,7 @@ void AUD_del_capture (CaptureVoiceOut *c 25.94 for (cb = cap->cb_head.lh_first; cb; cb = cb->entries.le_next) { 25.95 if (cb->opaque == cb_opaque) { 25.96 cb->ops.destroy (cb_opaque); 25.97 - LIST_REMOVE (cb, entries); 25.98 + QEMU_LIST_REMOVE (cb, entries); 25.99 qemu_free (cb); 25.100 25.101 if (!cap->cb_head.lh_first) { 25.102 @@ -1857,12 +1857,12 @@ void AUD_del_capture (CaptureVoiceOut *c 25.103 st_rate_stop (sw->rate); 25.104 sw->rate = NULL; 25.105 } 25.106 - LIST_REMOVE (sw, entries); 25.107 - LIST_REMOVE (sc, entries); 25.108 + QEMU_LIST_REMOVE (sw, entries); 25.109 + QEMU_LIST_REMOVE (sc, entries); 25.110 qemu_free (sc); 25.111 sw = sw1; 25.112 } 25.113 - LIST_REMOVE (cap, entries); 25.114 + QEMU_LIST_REMOVE (cap, entries); 25.115 qemu_free (cap); 25.116 } 25.117 return;
26.1 --- a/tools/ioemu/audio/audio.h Thu Feb 07 09:23:26 2008 -0700 26.2 +++ b/tools/ioemu/audio/audio.h Thu Feb 07 11:08:49 2008 -0700 26.3 @@ -68,7 +68,7 @@ struct capture_ops { 26.4 typedef struct CaptureState { 26.5 void *opaque; 26.6 struct capture_ops ops; 26.7 - LIST_ENTRY (CaptureState) entries; 26.8 + QEMU_LIST_ENTRY (CaptureState) entries; 26.9 } CaptureState; 26.10 26.11 typedef struct AudioState AudioState; 26.12 @@ -79,7 +79,7 @@ typedef struct SWVoiceIn SWVoiceIn; 26.13 typedef struct QEMUSoundCard { 26.14 AudioState *audio; 26.15 char *name; 26.16 - LIST_ENTRY (QEMUSoundCard) entries; 26.17 + QEMU_LIST_ENTRY (QEMUSoundCard) entries; 26.18 } QEMUSoundCard; 26.19 26.20 typedef struct QEMUAudioTimeStamp {
27.1 --- a/tools/ioemu/audio/audio_int.h Thu Feb 07 09:23:26 2008 -0700 27.2 +++ b/tools/ioemu/audio/audio_int.h Thu Feb 07 11:08:49 2008 -0700 27.3 @@ -79,10 +79,10 @@ typedef struct HWVoiceOut { 27.4 st_sample_t *mix_buf; 27.5 27.6 int samples; 27.7 - LIST_HEAD (sw_out_listhead, SWVoiceOut) sw_head; 27.8 - LIST_HEAD (sw_cap_listhead, SWVoiceCap) cap_head; 27.9 + QEMU_LIST_HEAD (sw_out_listhead, SWVoiceOut) sw_head; 27.10 + QEMU_LIST_HEAD (sw_cap_listhead, SWVoiceCap) cap_head; 27.11 struct audio_pcm_ops *pcm_ops; 27.12 - LIST_ENTRY (HWVoiceOut) entries; 27.13 + QEMU_LIST_ENTRY (HWVoiceOut) entries; 27.14 } HWVoiceOut; 27.15 27.16 typedef struct HWVoiceIn { 27.17 @@ -98,9 +98,9 @@ typedef struct HWVoiceIn { 27.18 st_sample_t *conv_buf; 27.19 27.20 int samples; 27.21 - LIST_HEAD (sw_in_listhead, SWVoiceIn) sw_head; 27.22 + QEMU_LIST_HEAD (sw_in_listhead, SWVoiceIn) sw_head; 27.23 struct audio_pcm_ops *pcm_ops; 27.24 - LIST_ENTRY (HWVoiceIn) entries; 27.25 + QEMU_LIST_ENTRY (HWVoiceIn) entries; 27.26 } HWVoiceIn; 27.27 27.28 struct SWVoiceOut { 27.29 @@ -116,7 +116,7 @@ struct SWVoiceOut { 27.30 char *name; 27.31 volume_t vol; 27.32 struct audio_callback callback; 27.33 - LIST_ENTRY (SWVoiceOut) entries; 27.34 + QEMU_LIST_ENTRY (SWVoiceOut) entries; 27.35 }; 27.36 27.37 struct SWVoiceIn { 27.38 @@ -131,7 +131,7 @@ struct SWVoiceIn { 27.39 char *name; 27.40 volume_t vol; 27.41 struct audio_callback callback; 27.42 - LIST_ENTRY (SWVoiceIn) entries; 27.43 + QEMU_LIST_ENTRY (SWVoiceIn) entries; 27.44 }; 27.45 27.46 struct audio_driver { 27.47 @@ -165,20 +165,20 @@ struct audio_pcm_ops { 27.48 struct capture_callback { 27.49 struct audio_capture_ops ops; 27.50 void *opaque; 27.51 - LIST_ENTRY (capture_callback) entries; 27.52 + QEMU_LIST_ENTRY (capture_callback) entries; 27.53 }; 27.54 27.55 struct CaptureVoiceOut { 27.56 HWVoiceOut hw; 27.57 void *buf; 27.58 - LIST_HEAD (cb_listhead, capture_callback) cb_head; 27.59 - LIST_ENTRY (CaptureVoiceOut) entries; 27.60 + QEMU_LIST_HEAD (cb_listhead, capture_callback) cb_head; 27.61 + QEMU_LIST_ENTRY (CaptureVoiceOut) entries; 27.62 }; 27.63 27.64 struct SWVoiceCap { 27.65 SWVoiceOut sw; 27.66 CaptureVoiceOut *cap; 27.67 - LIST_ENTRY (SWVoiceCap) entries; 27.68 + QEMU_LIST_ENTRY (SWVoiceCap) entries; 27.69 }; 27.70 27.71 struct AudioState { 27.72 @@ -186,10 +186,10 @@ struct AudioState { 27.73 void *drv_opaque; 27.74 27.75 QEMUTimer *ts; 27.76 - LIST_HEAD (card_listhead, QEMUSoundCard) card_head; 27.77 - LIST_HEAD (hw_in_listhead, HWVoiceIn) hw_head_in; 27.78 - LIST_HEAD (hw_out_listhead, HWVoiceOut) hw_head_out; 27.79 - LIST_HEAD (cap_listhead, CaptureVoiceOut) cap_head; 27.80 + QEMU_LIST_HEAD (card_listhead, QEMUSoundCard) card_head; 27.81 + QEMU_LIST_HEAD (hw_in_listhead, HWVoiceIn) hw_head_in; 27.82 + QEMU_LIST_HEAD (hw_out_listhead, HWVoiceOut) hw_head_out; 27.83 + QEMU_LIST_HEAD (cap_listhead, CaptureVoiceOut) cap_head; 27.84 int nb_hw_voices_out; 27.85 int nb_hw_voices_in; 27.86 };
28.1 --- a/tools/ioemu/audio/audio_template.h Thu Feb 07 09:23:26 2008 -0700 28.2 +++ b/tools/ioemu/audio/audio_template.h Thu Feb 07 11:08:49 2008 -0700 28.3 @@ -186,12 +186,12 @@ static void glue (audio_pcm_sw_fini_, TY 28.4 28.5 static void glue (audio_pcm_hw_add_sw_, TYPE) (HW *hw, SW *sw) 28.6 { 28.7 - LIST_INSERT_HEAD (&hw->sw_head, sw, entries); 28.8 + QEMU_LIST_INSERT_HEAD (&hw->sw_head, sw, entries); 28.9 } 28.10 28.11 static void glue (audio_pcm_hw_del_sw_, TYPE) (SW *sw) 28.12 { 28.13 - LIST_REMOVE (sw, entries); 28.14 + QEMU_LIST_REMOVE (sw, entries); 28.15 } 28.16 28.17 static void glue (audio_pcm_hw_gc_, TYPE) (AudioState *s, HW **hwp) 28.18 @@ -202,7 +202,7 @@ static void glue (audio_pcm_hw_gc_, TYPE 28.19 #ifdef DAC 28.20 audio_detach_capture (hw); 28.21 #endif 28.22 - LIST_REMOVE (hw, entries); 28.23 + QEMU_LIST_REMOVE (hw, entries); 28.24 glue (s->nb_hw_voices_, TYPE) += 1; 28.25 glue (audio_pcm_hw_free_resources_ ,TYPE) (hw); 28.26 glue (hw->pcm_ops->fini_, TYPE) (hw); 28.27 @@ -267,9 +267,9 @@ static HW *glue (audio_pcm_hw_add_new_, 28.28 } 28.29 28.30 hw->pcm_ops = drv->pcm_ops; 28.31 - LIST_INIT (&hw->sw_head); 28.32 + QEMU_LIST_INIT (&hw->sw_head); 28.33 #ifdef DAC 28.34 - LIST_INIT (&hw->cap_head); 28.35 + QEMU_LIST_INIT (&hw->cap_head); 28.36 #endif 28.37 if (glue (hw->pcm_ops->init_, TYPE) (hw, as)) { 28.38 goto err0; 28.39 @@ -294,7 +294,7 @@ static HW *glue (audio_pcm_hw_add_new_, 28.40 goto err1; 28.41 } 28.42 28.43 - LIST_INSERT_HEAD (&s->glue (hw_head_, TYPE), hw, entries); 28.44 + QEMU_LIST_INSERT_HEAD (&s->glue (hw_head_, TYPE), hw, entries); 28.45 glue (s->nb_hw_voices_, TYPE) -= 1; 28.46 #ifdef DAC 28.47 audio_attach_capture (s, hw);
29.1 --- a/tools/ioemu/audio/sys-queue.h Thu Feb 07 09:23:26 2008 -0700 29.2 +++ b/tools/ioemu/audio/sys-queue.h Thu Feb 07 11:08:49 2008 -0700 29.3 @@ -64,12 +64,12 @@ 29.4 /* 29.5 * List definitions. 29.6 */ 29.7 -#define LIST_HEAD(name, type) \ 29.8 +#define QEMU_LIST_HEAD(name, type) \ 29.9 struct name { \ 29.10 struct type *lh_first; /* first element */ \ 29.11 } 29.12 29.13 -#define LIST_ENTRY(type) \ 29.14 +#define QEMU_LIST_ENTRY(type) \ 29.15 struct { \ 29.16 struct type *le_next; /* next element */ \ 29.17 struct type **le_prev; /* address of previous next element */ \ 29.18 @@ -78,11 +78,11 @@ struct { \ 29.19 /* 29.20 * List functions. 29.21 */ 29.22 -#define LIST_INIT(head) { \ 29.23 +#define QEMU_LIST_INIT(head) { \ 29.24 (head)->lh_first = NULL; \ 29.25 } 29.26 29.27 -#define LIST_INSERT_AFTER(listelm, elm, field) { \ 29.28 +#define QEMU_LIST_INSERT_AFTER(listelm, elm, field) { \ 29.29 if (((elm)->field.le_next = (listelm)->field.le_next) != NULL) \ 29.30 (listelm)->field.le_next->field.le_prev = \ 29.31 &(elm)->field.le_next; \ 29.32 @@ -90,14 +90,14 @@ struct { \ 29.33 (elm)->field.le_prev = &(listelm)->field.le_next; \ 29.34 } 29.35 29.36 -#define LIST_INSERT_HEAD(head, elm, field) { \ 29.37 +#define QEMU_LIST_INSERT_HEAD(head, elm, field) { \ 29.38 if (((elm)->field.le_next = (head)->lh_first) != NULL) \ 29.39 (head)->lh_first->field.le_prev = &(elm)->field.le_next;\ 29.40 (head)->lh_first = (elm); \ 29.41 (elm)->field.le_prev = &(head)->lh_first; \ 29.42 } 29.43 29.44 -#define LIST_REMOVE(elm, field) { \ 29.45 +#define QEMU_LIST_REMOVE(elm, field) { \ 29.46 if ((elm)->field.le_next != NULL) \ 29.47 (elm)->field.le_next->field.le_prev = \ 29.48 (elm)->field.le_prev; \
30.1 --- a/tools/ioemu/hw/rtl8139.c Thu Feb 07 09:23:26 2008 -0700 30.2 +++ b/tools/ioemu/hw/rtl8139.c Thu Feb 07 11:08:49 2008 -0700 30.3 @@ -1468,7 +1468,7 @@ static void rtl8139_BasicModeCtrl_write( 30.4 DEBUG_PRINT(("RTL8139: BasicModeCtrl register write(w) val=0x%04x\n", val)); 30.5 30.6 /* mask unwriteable bits */ 30.7 - uint32 mask = 0x4cff; 30.8 + uint32_t mask = 0x4cff; 30.9 30.10 if (1 || !rtl8139_config_writeable(s)) 30.11 {
31.1 --- a/tools/ioemu/monitor.c Thu Feb 07 09:23:26 2008 -0700 31.2 +++ b/tools/ioemu/monitor.c Thu Feb 07 11:08:49 2008 -0700 31.3 @@ -1167,7 +1167,7 @@ static void do_info_profile(void) 31.4 #endif 31.5 31.6 /* Capture support */ 31.7 -static LIST_HEAD (capture_list_head, CaptureState) capture_head; 31.8 +static QEMU_LIST_HEAD (capture_list_head, CaptureState) capture_head; 31.9 31.10 static void do_info_capture (void) 31.11 { 31.12 @@ -1188,7 +1188,7 @@ static void do_stop_capture (int n) 31.13 for (s = capture_head.lh_first, i = 0; s; s = s->entries.le_next, ++i) { 31.14 if (i == n) { 31.15 s->ops.destroy (s->opaque); 31.16 - LIST_REMOVE (s, entries); 31.17 + QEMU_LIST_REMOVE (s, entries); 31.18 qemu_free (s); 31.19 return; 31.20 } 31.21 @@ -1220,7 +1220,7 @@ static void do_wav_capture (const char * 31.22 term_printf ("Faied to add wave capture\n"); 31.23 qemu_free (s); 31.24 } 31.25 - LIST_INSERT_HEAD (&capture_head, s, entries); 31.26 + QEMU_LIST_INSERT_HEAD (&capture_head, s, entries); 31.27 } 31.28 #endif 31.29
32.1 --- a/tools/ioemu/qemu_socket.h Thu Feb 07 09:23:26 2008 -0700 32.2 +++ b/tools/ioemu/qemu_socket.h Thu Feb 07 11:08:49 2008 -0700 32.3 @@ -14,12 +14,19 @@ 32.4 #define EINTR WSAEINTR 32.5 #define EINPROGRESS WSAEINPROGRESS 32.6 32.7 +#ifndef NO_UNIX_SOCKETS 32.8 +#define NO_UNIX_SOCKETS 1 32.9 +#endif 32.10 + 32.11 #else 32.12 32.13 #include <sys/socket.h> 32.14 #include <netinet/in.h> 32.15 #include <netinet/tcp.h> 32.16 + 32.17 +#ifndef NO_UNIX_SOCKETS 32.18 #include <sys/un.h> 32.19 +#endif 32.20 32.21 #define socket_error() errno 32.22 #define closesocket(s) close(s)
33.1 --- a/tools/ioemu/vl.c Thu Feb 07 09:23:26 2008 -0700 33.2 +++ b/tools/ioemu/vl.c Thu Feb 07 11:08:49 2008 -0700 33.3 @@ -3127,7 +3127,7 @@ int parse_host_port(struct sockaddr_in * 33.4 return 0; 33.5 } 33.6 33.7 -#ifndef _WIN32 33.8 +#ifndef NO_UNIX_SOCKETS 33.9 static int parse_unix_path(struct sockaddr_un *uaddr, const char *str) 33.10 { 33.11 const char *p; 33.12 @@ -6065,10 +6065,10 @@ void gui_update(void *opaque) 33.13 struct vm_change_state_entry { 33.14 VMChangeStateHandler *cb; 33.15 void *opaque; 33.16 - LIST_ENTRY (vm_change_state_entry) entries; 33.17 + QEMU_LIST_ENTRY (vm_change_state_entry) entries; 33.18 }; 33.19 33.20 -static LIST_HEAD(vm_change_state_head, vm_change_state_entry) vm_change_state_head; 33.21 +static QEMU_LIST_HEAD(vm_change_state_head, vm_change_state_entry) vm_change_state_head; 33.22 33.23 VMChangeStateEntry *qemu_add_vm_change_state_handler(VMChangeStateHandler *cb, 33.24 void *opaque) 33.25 @@ -6081,13 +6081,13 @@ VMChangeStateEntry *qemu_add_vm_change_s 33.26 33.27 e->cb = cb; 33.28 e->opaque = opaque; 33.29 - LIST_INSERT_HEAD(&vm_change_state_head, e, entries); 33.30 + QEMU_LIST_INSERT_HEAD(&vm_change_state_head, e, entries); 33.31 return e; 33.32 } 33.33 33.34 void qemu_del_vm_change_state_handler(VMChangeStateEntry *e) 33.35 { 33.36 - LIST_REMOVE (e, entries); 33.37 + QEMU_LIST_REMOVE (e, entries); 33.38 qemu_free (e); 33.39 } 33.40 33.41 @@ -7052,7 +7052,7 @@ int main(int argc, char **argv) 33.42 sigprocmask(SIG_BLOCK, &set, NULL); 33.43 } 33.44 33.45 - LIST_INIT (&vm_change_state_head); 33.46 + QEMU_LIST_INIT (&vm_change_state_head); 33.47 #ifndef _WIN32 33.48 { 33.49 struct sigaction act;
34.1 --- a/tools/ioemu/vnc.c Thu Feb 07 09:23:26 2008 -0700 34.2 +++ b/tools/ioemu/vnc.c Thu Feb 07 11:08:49 2008 -0700 34.3 @@ -2401,7 +2401,7 @@ int vnc_display_open(DisplayState *ds, c 34.4 } 34.5 #endif 34.6 } 34.7 -#ifndef _WIN32 34.8 +#ifndef NO_UNIX_SOCKETS 34.9 if (strstart(display, "unix:", &p)) { 34.10 addr = (struct sockaddr *)&uaddr; 34.11 addrlen = sizeof(uaddr);
35.1 --- a/tools/python/xen/xend/XendAPIConstants.py Thu Feb 07 09:23:26 2008 -0700 35.2 +++ b/tools/python/xen/xend/XendAPIConstants.py Thu Feb 07 11:08:49 2008 -0700 35.3 @@ -51,6 +51,18 @@ XEN_API_ON_CRASH_BEHAVIOUR = [ 35.4 'rename_restart' 35.5 ] 35.6 35.7 +XEN_API_ON_CRASH_BEHAVIOUR_FILTER = { 35.8 + 'destroy' : 'destroy', 35.9 + 'coredump-destroy' : 'coredump_and_destroy', 35.10 + 'coredump_and_destroy' : 'coredump_and_destroy', 35.11 + 'restart' : 'restart', 35.12 + 'coredump-restart' : 'coredump_and_restart', 35.13 + 'coredump_and_restart' : 'coredump_and_restart', 35.14 + 'preserve' : 'preserve', 35.15 + 'rename-restart' : 'rename_restart', 35.16 + 'rename_restart' : 'rename_restart', 35.17 +} 35.18 + 35.19 XEN_API_VBD_MODE = ['RO', 'RW'] 35.20 XEN_API_VDI_TYPE = ['system', 'user', 'ephemeral'] 35.21 XEN_API_VBD_TYPE = ['CD', 'Disk']
36.1 --- a/tools/python/xen/xend/XendConfig.py Thu Feb 07 09:23:26 2008 -0700 36.2 +++ b/tools/python/xen/xend/XendConfig.py Thu Feb 07 11:08:49 2008 -0700 36.3 @@ -242,7 +242,8 @@ LEGACY_XENSTORE_VM_PARAMS = [ 36.4 ## Config Choices 36.5 ## 36.6 36.7 -CONFIG_RESTART_MODES = ('restart', 'destroy', 'preserve', 'rename-restart') 36.8 +CONFIG_RESTART_MODES = ('restart', 'destroy', 'preserve', 'rename-restart', 36.9 + 'coredump-destroy', 'coredump-restart') 36.10 CONFIG_OLD_DOM_STATES = ('running', 'blocked', 'paused', 'shutdown', 36.11 'crashed', 'dying') 36.12
37.1 --- a/tools/python/xen/xend/XendConstants.py Thu Feb 07 09:23:26 2008 -0700 37.2 +++ b/tools/python/xen/xend/XendConstants.py Thu Feb 07 11:08:49 2008 -0700 37.3 @@ -52,7 +52,9 @@ restart_modes = [ 37.4 "restart", 37.5 "destroy", 37.6 "preserve", 37.7 - "rename-restart" 37.8 + "rename-restart", 37.9 + "coredump-destroy", 37.10 + "coredump-restart" 37.11 ] 37.12 37.13 DOM_STATES = [
38.1 --- a/tools/python/xen/xend/XendDomainInfo.py Thu Feb 07 09:23:26 2008 -0700 38.2 +++ b/tools/python/xen/xend/XendDomainInfo.py Thu Feb 07 11:08:49 2008 -0700 38.3 @@ -879,6 +879,9 @@ class XendDomainInfo: 38.4 def _gatherVm(self, *args): 38.5 return xstransact.Gather(self.vmpath, *args) 38.6 38.7 + def _listRecursiveVm(self, *args): 38.8 + return xstransact.ListRecursive(self.vmpath, *args) 38.9 + 38.10 def storeVm(self, *args): 38.11 return xstransact.Store(self.vmpath, *args) 38.12 38.13 @@ -1260,14 +1263,6 @@ class XendDomainInfo: 38.14 self.info['name_label'], self.domid) 38.15 self._writeVm(LAST_SHUTDOWN_REASON, 'crash') 38.16 38.17 - if xoptions.get_enable_dump(): 38.18 - try: 38.19 - self.dumpCore() 38.20 - except XendError: 38.21 - # This error has been logged -- there's nothing more 38.22 - # we can do in this context. 38.23 - pass 38.24 - 38.25 restart_reason = 'crash' 38.26 self._stateSet(DOM_STATE_HALTED) 38.27 38.28 @@ -1335,14 +1330,30 @@ class XendDomainInfo: 38.29 def _clearRestart(self): 38.30 self._removeDom("xend/shutdown_start_time") 38.31 38.32 + def _maybeDumpCore(self, reason): 38.33 + if reason == 'crash': 38.34 + if xoptions.get_enable_dump() or self.get_on_crash() \ 38.35 + in ['coredump_and_destroy', 'coredump_and_restart']: 38.36 + try: 38.37 + self.dumpCore() 38.38 + except XendError: 38.39 + # This error has been logged -- there's nothing more 38.40 + # we can do in this context. 38.41 + pass 38.42 38.43 def _maybeRestart(self, reason): 38.44 + # Before taking configured action, dump core if configured to do so. 38.45 + # 38.46 + self._maybeDumpCore(reason) 38.47 + 38.48 # Dispatch to the correct method based upon the configured on_{reason} 38.49 # behaviour. 38.50 actions = {"destroy" : self.destroy, 38.51 "restart" : self._restart, 38.52 "preserve" : self._preserve, 38.53 - "rename-restart" : self._renameRestart} 38.54 + "rename-restart" : self._renameRestart, 38.55 + "coredump-destroy" : self.destroy, 38.56 + "coredump-restart" : self._restart} 38.57 38.58 action_conf = { 38.59 'poweroff': 'actions_after_shutdown', 38.60 @@ -1393,6 +1404,7 @@ class XendDomainInfo: 38.61 38.62 self._writeVm('xend/previous_restart_time', str(now)) 38.63 38.64 + prev_vm_xend = self._listRecursiveVm('xend') 38.65 new_dom_info = self.info 38.66 try: 38.67 if rename: 38.68 @@ -1411,8 +1423,13 @@ class XendDomainInfo: 38.69 try: 38.70 new_dom = XendDomain.instance().domain_create_from_dict( 38.71 new_dom_info) 38.72 + for x in prev_vm_xend[0][1]: 38.73 + new_dom._writeVm('xend/%s' % x[0], x[1]) 38.74 new_dom.waitForDevices() 38.75 new_dom.unpause() 38.76 + rst_cnt = new_dom._readVm('xend/restart_count') 38.77 + rst_cnt = int(rst_cnt) + 1 38.78 + new_dom._writeVm('xend/restart_count', str(rst_cnt)) 38.79 new_dom._removeVm(RESTART_IN_PROGRESS) 38.80 except: 38.81 if new_dom: 38.82 @@ -1448,9 +1465,6 @@ class XendDomainInfo: 38.83 self.vmpath = XS_VMROOT + new_uuid 38.84 # Write out new vm node to xenstore 38.85 self._storeVmDetails() 38.86 - rst_cnt = self._readVm('xend/restart_count') 38.87 - rst_cnt = int(rst_cnt) + 1 38.88 - self._writeVm('xend/restart_count', str(rst_cnt)) 38.89 self._preserve() 38.90 return new_dom_info 38.91 38.92 @@ -2566,9 +2580,10 @@ class XendDomainInfo: 38.93 38.94 def get_on_crash(self): 38.95 after_crash = self.info.get('actions_after_crash') 38.96 - if not after_crash or after_crash not in XEN_API_ON_CRASH_BEHAVIOUR: 38.97 + if not after_crash or after_crash not in \ 38.98 + XEN_API_ON_CRASH_BEHAVIOUR + restart_modes: 38.99 return XEN_API_ON_CRASH_BEHAVIOUR[0] 38.100 - return after_crash 38.101 + return XEN_API_ON_CRASH_BEHAVIOUR_FILTER[after_crash] 38.102 38.103 def get_dev_config_by_uuid(self, dev_class, dev_uuid): 38.104 """ Get's a device configuration either from XendConfig or
39.1 --- a/tools/python/xen/xend/image.py Thu Feb 07 09:23:26 2008 -0700 39.2 +++ b/tools/python/xen/xend/image.py Thu Feb 07 11:08:49 2008 -0700 39.3 @@ -329,7 +329,7 @@ class ImageHandler: 39.4 return 39.5 if self.pid: 39.6 try: 39.7 - os.kill(self.pid, signal.SIGHUP) 39.8 + os.kill(self.pid, signal.SIGKILL) 39.9 except OSError, exn: 39.10 log.exception(exn) 39.11 try:
40.1 --- a/tools/python/xen/xend/server/DevController.py Thu Feb 07 09:23:26 2008 -0700 40.2 +++ b/tools/python/xen/xend/server/DevController.py Thu Feb 07 11:08:49 2008 -0700 40.3 @@ -22,6 +22,7 @@ import types 40.4 from xen.xend import sxp, XendOptions 40.5 from xen.xend.XendError import VmError 40.6 from xen.xend.XendLogging import log 40.7 +import xen.xend.XendConfig 40.8 40.9 from xen.xend.xenstore.xstransact import xstransact, complete 40.10 from xen.xend.xenstore.xswatch import xswatch 40.11 @@ -113,10 +114,10 @@ class DevController: 40.12 raise VmError("Device %s is already connected." % dev_str) 40.13 40.14 if count == 0: 40.15 - log.debug('DevController: writing %s to %s.', str(front), 40.16 - frontpath) 40.17 - log.debug('DevController: writing %s to %s.', str(back), 40.18 - backpath) 40.19 + log.debug('DevController: writing %s to %s.', 40.20 + str(front), frontpath) 40.21 + log.debug('DevController: writing %s to %s.', 40.22 + str(xen.xend.XendConfig.scrub_password(back)), backpath) 40.23 elif count % 50 == 0: 40.24 log.debug( 40.25 'DevController: still waiting to write device entries.')
41.1 --- a/tools/python/xen/xm/create.py Thu Feb 07 09:23:26 2008 -0700 41.2 +++ b/tools/python/xen/xm/create.py Thu Feb 07 11:08:49 2008 -0700 41.3 @@ -264,15 +264,17 @@ gopts.var('on_reboot', val='destroy|rest 41.4 renamed and a new domain started in its place. 41.5 """) 41.6 41.7 -gopts.var('on_crash', val='destroy|restart|preserve|rename-restart', 41.8 +gopts.var('on_crash', val='destroy|restart|preserve|rename-restart|coredump-destroy|ciredump-restart', 41.9 fn=set_value, default=None, 41.10 - use="""Behaviour when a domain exits with reason 'crash'. 41.11 - - destroy: the domain is cleaned up as normal; 41.12 - - restart: a new domain is started in place of the old one; 41.13 - - preserve: no clean-up is done until the domain is manually 41.14 - destroyed (using xm destroy, for example); 41.15 - - rename-restart: the old domain is not cleaned up, but is 41.16 - renamed and a new domain started in its place. 41.17 + use="""Behaviour when a domain exits with reason 'crash'. 41.18 + - destroy: the domain is cleaned up as normal; 41.19 + - restart: a new domain is started in place of the old one; 41.20 + - preserve: no clean-up is done until the domain is manually 41.21 + destroyed (using xm destroy, for example); 41.22 + - rename-restart: the old domain is not cleaned up, but is 41.23 + renamed and a new domain started in its place. 41.24 + - coredump-destroy: dump the domain's core, followed by destroy 41.25 + - coredump-restart: dump the domain's core, followed by restart 41.26 """) 41.27 41.28 gopts.var('blkif', val='no|yes',
42.1 --- a/tools/python/xen/xm/shutdown.py Thu Feb 07 09:23:26 2008 -0700 42.2 +++ b/tools/python/xen/xm/shutdown.py Thu Feb 07 11:08:49 2008 -0700 42.3 @@ -24,6 +24,8 @@ from opts import * 42.4 from main import server, serverType, SERVER_XEN_API, get_single_vm 42.5 from xen.xend.XendAPIConstants import * 42.6 42.7 +RECREATING_TIMEOUT = 30 42.8 + 42.9 gopts = Opts(use="""[options] [DOM] 42.10 42.11 Shutdown one or more domains gracefully. 42.12 @@ -53,6 +55,7 @@ def wait_reboot(opts, doms, rcs): 42.13 if serverType == SERVER_XEN_API: 42.14 opts.err("Cannot wait for reboot w/ XenAPI (yet)") 42.15 42.16 + recreating = {} 42.17 while doms: 42.18 alive = server.xend.domains(0) 42.19 reboot = [] 42.20 @@ -61,9 +64,17 @@ def wait_reboot(opts, doms, rcs): 42.21 rc = server.xend.domain.getRestartCount(d) 42.22 if rc == rcs[d]: continue 42.23 reboot.append(d) 42.24 + 42.25 + # Probably the domain is being recreated now. 42.26 + # We have to wait just a bit for recreating the domain. 42.27 + elif not recreating.has_key(d): 42.28 + recreating[d] = 0 42.29 else: 42.30 - opts.info("Domain %s destroyed for failed in rebooting" % d) 42.31 - doms.remove(d) 42.32 + recreating[d] += 1 42.33 + if recreating[d] > RECREATING_TIMEOUT: 42.34 + opts.info("Domain %s destroyed for failing to reboot" % d) 42.35 + doms.remove(d) 42.36 + 42.37 for d in reboot: 42.38 opts.info("Domain %s rebooted" % d) 42.39 doms.remove(d)
43.1 --- a/xen/arch/x86/Rules.mk Thu Feb 07 09:23:26 2008 -0700 43.2 +++ b/xen/arch/x86/Rules.mk Thu Feb 07 11:08:49 2008 -0700 43.3 @@ -11,11 +11,6 @@ xenoprof := y 43.4 # 43.5 pae ?= n 43.6 supervisor_mode_kernel ?= n 43.7 -vmxassist ?= n 43.8 - 43.9 -ifeq ($(vmxassist),y) 43.10 -CFLAGS += -DVMXASSIST 43.11 -endif 43.12 43.13 # Solaris grabs stdarg.h and friends from the system include directory. 43.14 ifneq ($(XEN_OS),SunOS)
44.1 --- a/xen/arch/x86/domain_build.c Thu Feb 07 09:23:26 2008 -0700 44.2 +++ b/xen/arch/x86/domain_build.c Thu Feb 07 11:08:49 2008 -0700 44.3 @@ -292,9 +292,6 @@ int __init construct_dom0( 44.4 compatible = 1; 44.5 break; 44.6 case 4: /* x86_64 */ 44.7 -#ifndef CONFIG_COMPAT 44.8 - printk(" Xen kernel: 64-bit, lsb\n"); 44.9 -#else 44.10 printk(" Xen kernel: 64-bit, lsb, compat32\n"); 44.11 if (elf_32bit(&elf) && parms.pae == PAEKERN_bimodal) 44.12 parms.pae = PAEKERN_extended_cr3; 44.13 @@ -303,7 +300,6 @@ int __init construct_dom0( 44.14 compat32 = 1; 44.15 compatible = 1; 44.16 } 44.17 -#endif 44.18 if (elf_64bit(&elf) && machine == EM_X86_64) 44.19 compatible = 1; 44.20 break; 44.21 @@ -323,7 +319,7 @@ int __init construct_dom0( 44.22 return -EINVAL; 44.23 } 44.24 44.25 -#ifdef CONFIG_COMPAT 44.26 +#if defined(__x86_64__) 44.27 if ( compat32 ) 44.28 { 44.29 l1_pgentry_t gdt_l1e; 44.30 @@ -346,34 +342,32 @@ int __init construct_dom0( 44.31 flush_tlb_one_local(GDT_LDT_VIRT_START + FIRST_RESERVED_GDT_BYTE); 44.32 } 44.33 #endif 44.34 + 44.35 if ( parms.pae == PAEKERN_extended_cr3 ) 44.36 set_bit(VMASST_TYPE_pae_extended_cr3, &d->vm_assist); 44.37 44.38 - if ( UNSET_ADDR != parms.virt_hv_start_low && elf_32bit(&elf) ) 44.39 + if ( (parms.virt_hv_start_low != UNSET_ADDR) && elf_32bit(&elf) ) 44.40 { 44.41 -#if CONFIG_PAGING_LEVELS < 4 44.42 unsigned long mask = (1UL << L2_PAGETABLE_SHIFT) - 1; 44.43 + value = (parms.virt_hv_start_low + mask) & ~mask; 44.44 + BUG_ON(!is_pv_32bit_domain(d)); 44.45 +#if defined(__i386__) 44.46 + if ( value > HYPERVISOR_VIRT_START ) 44.47 + panic("Domain 0 expects too high a hypervisor start address.\n"); 44.48 #else 44.49 - unsigned long mask = is_pv_32bit_domain(d) 44.50 - ? (1UL << L2_PAGETABLE_SHIFT) - 1 44.51 - : (1UL << L4_PAGETABLE_SHIFT) - 1; 44.52 -#endif 44.53 - 44.54 - value = (parms.virt_hv_start_low + mask) & ~mask; 44.55 -#ifdef CONFIG_COMPAT 44.56 + if ( value > __HYPERVISOR_COMPAT_VIRT_START ) 44.57 + panic("Domain 0 expects too high a hypervisor start address.\n"); 44.58 HYPERVISOR_COMPAT_VIRT_START(d) = 44.59 max_t(unsigned int, m2p_compat_vstart, value); 44.60 +#endif 44.61 + } 44.62 + 44.63 +#if defined(__x86_64__) 44.64 + if ( is_pv_32on64_domain(d) ) 44.65 d->arch.physaddr_bitsize = 44.66 fls((1UL << 32) - HYPERVISOR_COMPAT_VIRT_START(d)) - 1 44.67 + (PAGE_SIZE - 2); 44.68 - if ( value > (!is_pv_32on64_domain(d) ? 44.69 - HYPERVISOR_VIRT_START : 44.70 - __HYPERVISOR_COMPAT_VIRT_START) ) 44.71 -#else 44.72 - if ( value > HYPERVISOR_VIRT_START ) 44.73 #endif 44.74 - panic("Domain 0 expects too high a hypervisor start address.\n"); 44.75 - } 44.76 44.77 /* 44.78 * Why do we need this? The number of page-table frames depends on the 44.79 @@ -702,7 +696,6 @@ int __init construct_dom0( 44.80 mfn++; 44.81 } 44.82 44.83 -#ifdef CONFIG_COMPAT 44.84 if ( is_pv_32on64_domain(d) ) 44.85 { 44.86 /* Ensure the first four L3 entries are all populated. */ 44.87 @@ -724,7 +717,6 @@ int __init construct_dom0( 44.88 &compat_idle_pg_table_l2[l2_table_offset(HIRO_COMPAT_MPT_VIRT_START)], 44.89 COMPAT_L2_PAGETABLE_XEN_SLOTS(d) * sizeof(*l2tab)); 44.90 } 44.91 -#endif 44.92 44.93 /* Pages that are part of page tables must be read only. */ 44.94 l4tab = l4start + l4_table_offset(vpt_start); 44.95 @@ -885,7 +877,7 @@ int __init construct_dom0( 44.96 si->console.dom0.info_size = sizeof(struct dom0_vga_console_info); 44.97 } 44.98 44.99 -#ifdef CONFIG_COMPAT 44.100 +#if defined(__x86_64__) 44.101 if ( is_pv_32on64_domain(d) ) 44.102 xlat_start_info(si, XLAT_start_info_console_dom0); 44.103 #endif
45.1 --- a/xen/arch/x86/hvm/hvm.c Thu Feb 07 09:23:26 2008 -0700 45.2 +++ b/xen/arch/x86/hvm/hvm.c Thu Feb 07 11:08:49 2008 -0700 45.3 @@ -1400,6 +1400,7 @@ void hvm_print_line(struct vcpu *v, cons 45.4 spin_unlock(&hd->pbuf_lock); 45.5 } 45.6 45.7 +#define bitmaskof(idx) (1U << ((idx) & 31)) 45.8 void hvm_cpuid(unsigned int input, unsigned int *eax, unsigned int *ebx, 45.9 unsigned int *ecx, unsigned int *edx) 45.10 { 45.11 @@ -1413,16 +1414,44 @@ void hvm_cpuid(unsigned int input, unsig 45.12 switch ( input ) 45.13 { 45.14 case 0x00000001: 45.15 - __clear_bit(X86_FEATURE_MWAIT & 31, ecx); 45.16 + /* Clear #threads count and poke initial VLAPIC ID. */ 45.17 + *ebx &= 0x0000FFFFu; 45.18 + *ebx |= (current->vcpu_id * 2) << 24; 45.19 + 45.20 + *ecx &= (bitmaskof(X86_FEATURE_XMM3) | 45.21 + bitmaskof(X86_FEATURE_SSSE3) | 45.22 + bitmaskof(X86_FEATURE_CX16) | 45.23 + bitmaskof(X86_FEATURE_SSE4_1) | 45.24 + bitmaskof(X86_FEATURE_SSE4_2) | 45.25 + bitmaskof(X86_FEATURE_POPCNT)); 45.26 45.27 + *edx &= (bitmaskof(X86_FEATURE_FPU) | 45.28 + bitmaskof(X86_FEATURE_VME) | 45.29 + bitmaskof(X86_FEATURE_DE) | 45.30 + bitmaskof(X86_FEATURE_PSE) | 45.31 + bitmaskof(X86_FEATURE_TSC) | 45.32 + bitmaskof(X86_FEATURE_MSR) | 45.33 + bitmaskof(X86_FEATURE_PAE) | 45.34 + bitmaskof(X86_FEATURE_MCE) | 45.35 + bitmaskof(X86_FEATURE_CX8) | 45.36 + bitmaskof(X86_FEATURE_APIC) | 45.37 + bitmaskof(X86_FEATURE_SEP) | 45.38 + bitmaskof(X86_FEATURE_MTRR) | 45.39 + bitmaskof(X86_FEATURE_PGE) | 45.40 + bitmaskof(X86_FEATURE_MCA) | 45.41 + bitmaskof(X86_FEATURE_CMOV) | 45.42 + bitmaskof(X86_FEATURE_PAT) | 45.43 + bitmaskof(X86_FEATURE_CLFLSH) | 45.44 + bitmaskof(X86_FEATURE_MMX) | 45.45 + bitmaskof(X86_FEATURE_FXSR) | 45.46 + bitmaskof(X86_FEATURE_XMM) | 45.47 + bitmaskof(X86_FEATURE_XMM2)); 45.48 if ( vlapic_hw_disabled(vcpu_vlapic(v)) ) 45.49 __clear_bit(X86_FEATURE_APIC & 31, edx); 45.50 - 45.51 #if CONFIG_PAGING_LEVELS >= 3 45.52 if ( !v->domain->arch.hvm_domain.params[HVM_PARAM_PAE_ENABLED] ) 45.53 #endif 45.54 __clear_bit(X86_FEATURE_PAE & 31, edx); 45.55 - __clear_bit(X86_FEATURE_PSE36 & 31, edx); 45.56 break; 45.57 45.58 case 0x80000001: 45.59 @@ -1671,16 +1700,6 @@ int hvm_bringup_ap(int vcpuid, int tramp 45.60 ctxt->flags = VGCF_online; 45.61 ctxt->user_regs.eflags = 2; 45.62 45.63 -#ifdef VMXASSIST 45.64 - if ( boot_cpu_data.x86_vendor == X86_VENDOR_INTEL ) 45.65 - { 45.66 - ctxt->user_regs.eip = VMXASSIST_BASE; 45.67 - ctxt->user_regs.edx = vcpuid; 45.68 - ctxt->user_regs.ebx = trampoline_vector; 45.69 - goto done; 45.70 - } 45.71 -#endif 45.72 - 45.73 v->arch.hvm_vcpu.guest_cr[0] = X86_CR0_ET; 45.74 hvm_update_guest_cr(v, 0); 45.75 45.76 @@ -1721,9 +1740,6 @@ int hvm_bringup_ap(int vcpuid, int tramp 45.77 hvm_set_segment_register(v, x86_seg_gdtr, ®); 45.78 hvm_set_segment_register(v, x86_seg_idtr, ®); 45.79 45.80 -#ifdef VMXASSIST 45.81 - done: 45.82 -#endif 45.83 /* Sync AP's TSC with BSP's. */ 45.84 v->arch.hvm_vcpu.cache_tsc_offset = 45.85 v->domain->vcpu[0]->arch.hvm_vcpu.cache_tsc_offset;
46.1 --- a/xen/arch/x86/hvm/svm/svm.c Thu Feb 07 09:23:26 2008 -0700 46.2 +++ b/xen/arch/x86/hvm/svm/svm.c Thu Feb 07 11:08:49 2008 -0700 46.3 @@ -578,8 +578,8 @@ static unsigned long svm_get_segment_bas 46.4 case x86_seg_gdtr: return vmcb->gdtr.base; 46.5 case x86_seg_idtr: return vmcb->idtr.base; 46.6 case x86_seg_ldtr: svm_sync_vmcb(v); return vmcb->ldtr.base; 46.7 + default: BUG(); 46.8 } 46.9 - BUG(); 46.10 return 0; 46.11 } 46.12 46.13 @@ -986,11 +986,6 @@ static void svm_do_no_device_fault(struc 46.14 vmcb->cr0 &= ~X86_CR0_TS; 46.15 } 46.16 46.17 -/* Reserved bits ECX: [31:14], [12:4], [2:1]*/ 46.18 -#define SVM_VCPU_CPUID_L1_ECX_RESERVED 0xffffdff6 46.19 -/* Reserved bits EDX: [31:29], [27], [22:20], [18], [10] */ 46.20 -#define SVM_VCPU_CPUID_L1_EDX_RESERVED 0xe8740400 46.21 - 46.22 #define bitmaskof(idx) (1U << ((idx) & 31)) 46.23 static void svm_vmexit_do_cpuid(struct vmcb_struct *vmcb, 46.24 struct cpu_user_regs *regs) 46.25 @@ -1005,16 +1000,10 @@ static void svm_vmexit_do_cpuid(struct v 46.26 switch ( input ) 46.27 { 46.28 case 0x00000001: 46.29 - /* Clear out reserved bits. */ 46.30 - ecx &= ~SVM_VCPU_CPUID_L1_ECX_RESERVED; 46.31 - edx &= ~SVM_VCPU_CPUID_L1_EDX_RESERVED; 46.32 - 46.33 - /* Guest should only see one logical processor. 46.34 - * See details on page 23 of AMD CPUID Specification. 46.35 - */ 46.36 - __clear_bit(X86_FEATURE_HT & 31, &edx); 46.37 - ebx &= 0xFF00FFFF; /* clear the logical processor count when HTT=0 */ 46.38 - ebx |= 0x00010000; /* set to 1 just for precaution */ 46.39 + /* Mask Intel-only features. */ 46.40 + ecx &= ~(bitmaskof(X86_FEATURE_SSSE3) | 46.41 + bitmaskof(X86_FEATURE_SSE4_1) | 46.42 + bitmaskof(X86_FEATURE_SSE4_2)); 46.43 break; 46.44 46.45 case 0x80000001:
47.1 --- a/xen/arch/x86/hvm/vmx/Makefile Thu Feb 07 09:23:26 2008 -0700 47.2 +++ b/xen/arch/x86/hvm/vmx/Makefile Thu Feb 07 11:08:49 2008 -0700 47.3 @@ -4,9 +4,7 @@ subdir-$(x86_32) += x86_32 47.4 subdir-$(x86_64) += x86_64 47.5 47.6 obj-y += intr.o 47.7 -ifneq ($(vmxassist),y) 47.8 obj-y += realmode.o 47.9 -endif 47.10 obj-y += vmcs.o 47.11 obj-y += vmx.o 47.12 obj-y += vpmu.o
48.1 --- a/xen/arch/x86/hvm/vmx/realmode.c Thu Feb 07 09:23:26 2008 -0700 48.2 +++ b/xen/arch/x86/hvm/vmx/realmode.c Thu Feb 07 11:08:49 2008 -0700 48.3 @@ -18,7 +18,6 @@ 48.4 #include <asm/hvm/support.h> 48.5 #include <asm/hvm/vmx/vmx.h> 48.6 #include <asm/hvm/vmx/vmcs.h> 48.7 -#include <asm/hvm/vmx/cpu.h> 48.8 #include <asm/x86_emulate.h> 48.9 48.10 struct realmode_emulate_ctxt { 48.11 @@ -118,6 +117,18 @@ static void realmode_deliver_exception( 48.12 } 48.13 } 48.14 48.15 +static uint32_t virtual_to_linear( 48.16 + enum x86_segment seg, 48.17 + uint32_t offset, 48.18 + struct realmode_emulate_ctxt *rm_ctxt) 48.19 +{ 48.20 + uint32_t addr = offset; 48.21 + if ( seg == x86_seg_none ) 48.22 + return addr; 48.23 + ASSERT(is_x86_user_segment(seg)); 48.24 + return addr + rm_ctxt->seg_reg[seg].base; 48.25 +} 48.26 + 48.27 static int 48.28 realmode_read( 48.29 enum x86_segment seg, 48.30 @@ -127,14 +138,17 @@ realmode_read( 48.31 enum hvm_access_type access_type, 48.32 struct realmode_emulate_ctxt *rm_ctxt) 48.33 { 48.34 - uint32_t addr = rm_ctxt->seg_reg[seg].base + offset; 48.35 + uint32_t addr = virtual_to_linear(seg, offset, rm_ctxt); 48.36 48.37 *val = 0; 48.38 48.39 - if ( hvm_copy_from_guest_phys(val, addr, bytes) ) 48.40 + if ( hvm_copy_from_guest_virt_nofault(val, addr, bytes) ) 48.41 { 48.42 struct vcpu *curr = current; 48.43 48.44 + if ( curr->arch.hvm_vcpu.guest_cr[0] & X86_CR0_PE ) 48.45 + return X86EMUL_UNHANDLEABLE; 48.46 + 48.47 if ( curr->arch.hvm_vmx.real_mode_io_in_progress ) 48.48 return X86EMUL_UNHANDLEABLE; 48.49 48.50 @@ -202,12 +216,15 @@ realmode_emulate_write( 48.51 { 48.52 struct realmode_emulate_ctxt *rm_ctxt = 48.53 container_of(ctxt, struct realmode_emulate_ctxt, ctxt); 48.54 - uint32_t addr = rm_ctxt->seg_reg[seg].base + offset; 48.55 + uint32_t addr = virtual_to_linear(seg, offset, rm_ctxt); 48.56 48.57 - if ( hvm_copy_to_guest_phys(addr, &val, bytes) ) 48.58 + if ( hvm_copy_to_guest_virt_nofault(addr, &val, bytes) ) 48.59 { 48.60 struct vcpu *curr = current; 48.61 48.62 + if ( curr->arch.hvm_vcpu.guest_cr[0] & X86_CR0_PE ) 48.63 + return X86EMUL_UNHANDLEABLE; 48.64 + 48.65 if ( curr->arch.hvm_vmx.real_mode_io_in_progress ) 48.66 return X86EMUL_UNHANDLEABLE; 48.67 48.68 @@ -244,7 +261,10 @@ realmode_rep_ins( 48.69 struct realmode_emulate_ctxt *rm_ctxt = 48.70 container_of(ctxt, struct realmode_emulate_ctxt, ctxt); 48.71 struct vcpu *curr = current; 48.72 - uint32_t paddr = rm_ctxt->seg_reg[dst_seg].base + dst_offset; 48.73 + uint32_t paddr = virtual_to_linear(dst_seg, dst_offset, rm_ctxt); 48.74 + 48.75 + if ( curr->arch.hvm_vcpu.guest_cr[0] & X86_CR0_PE ) 48.76 + return X86EMUL_UNHANDLEABLE; 48.77 48.78 if ( curr->arch.hvm_vmx.real_mode_io_in_progress ) 48.79 return X86EMUL_UNHANDLEABLE; 48.80 @@ -277,7 +297,10 @@ realmode_rep_outs( 48.81 struct realmode_emulate_ctxt *rm_ctxt = 48.82 container_of(ctxt, struct realmode_emulate_ctxt, ctxt); 48.83 struct vcpu *curr = current; 48.84 - uint32_t paddr = rm_ctxt->seg_reg[src_seg].base + src_offset; 48.85 + uint32_t paddr = virtual_to_linear(src_seg, src_offset, rm_ctxt); 48.86 + 48.87 + if ( curr->arch.hvm_vcpu.guest_cr[0] & X86_CR0_PE ) 48.88 + return X86EMUL_UNHANDLEABLE; 48.89 48.90 if ( curr->arch.hvm_vmx.real_mode_io_in_progress ) 48.91 return X86EMUL_UNHANDLEABLE; 48.92 @@ -310,9 +333,29 @@ realmode_write_segment( 48.93 { 48.94 struct realmode_emulate_ctxt *rm_ctxt = 48.95 container_of(ctxt, struct realmode_emulate_ctxt, ctxt); 48.96 - memcpy(&rm_ctxt->seg_reg[seg], reg, sizeof(struct segment_register)); 48.97 + struct vcpu *curr = current; 48.98 + 48.99 + if ( seg == x86_seg_cs ) 48.100 + { 48.101 + if ( reg->attr.fields.dpl != 0 ) 48.102 + return X86EMUL_UNHANDLEABLE; 48.103 + curr->arch.hvm_vmx.vmxemul &= ~VMXEMUL_BAD_CS; 48.104 + if ( reg->sel & 3 ) 48.105 + curr->arch.hvm_vmx.vmxemul |= VMXEMUL_BAD_CS; 48.106 + } 48.107 + 48.108 if ( seg == x86_seg_ss ) 48.109 + { 48.110 + if ( reg->attr.fields.dpl != 0 ) 48.111 + return X86EMUL_UNHANDLEABLE; 48.112 + curr->arch.hvm_vmx.vmxemul &= ~VMXEMUL_BAD_SS; 48.113 + if ( reg->sel & 3 ) 48.114 + curr->arch.hvm_vmx.vmxemul |= VMXEMUL_BAD_SS; 48.115 rm_ctxt->flags.mov_ss = 1; 48.116 + } 48.117 + 48.118 + memcpy(&rm_ctxt->seg_reg[seg], reg, sizeof(struct segment_register)); 48.119 + 48.120 return X86EMUL_OKAY; 48.121 } 48.122 48.123 @@ -336,7 +379,7 @@ realmode_read_io( 48.124 48.125 if ( !curr->arch.hvm_vmx.real_mode_io_completed ) 48.126 return X86EMUL_RETRY; 48.127 - 48.128 + 48.129 *val = curr->arch.hvm_vmx.real_mode_io_data; 48.130 curr->arch.hvm_vmx.real_mode_io_completed = 0; 48.131 48.132 @@ -506,11 +549,19 @@ static int realmode_hlt( 48.133 48.134 static int realmode_inject_hw_exception( 48.135 uint8_t vector, 48.136 + uint16_t error_code, 48.137 struct x86_emulate_ctxt *ctxt) 48.138 { 48.139 struct realmode_emulate_ctxt *rm_ctxt = 48.140 container_of(ctxt, struct realmode_emulate_ctxt, ctxt); 48.141 48.142 + /* We don't emulate protected-mode exception delivery. */ 48.143 + if ( current->arch.hvm_vcpu.guest_cr[0] & X86_CR0_PE ) 48.144 + return X86EMUL_UNHANDLEABLE; 48.145 + 48.146 + if ( error_code != 0 ) 48.147 + return X86EMUL_UNHANDLEABLE; 48.148 + 48.149 rm_ctxt->exn_vector = vector; 48.150 rm_ctxt->exn_insn_len = 0; 48.151 48.152 @@ -525,6 +576,10 @@ static int realmode_inject_sw_interrupt( 48.153 struct realmode_emulate_ctxt *rm_ctxt = 48.154 container_of(ctxt, struct realmode_emulate_ctxt, ctxt); 48.155 48.156 + /* We don't emulate protected-mode exception delivery. */ 48.157 + if ( current->arch.hvm_vcpu.guest_cr[0] & X86_CR0_PE ) 48.158 + return X86EMUL_UNHANDLEABLE; 48.159 + 48.160 rm_ctxt->exn_vector = vector; 48.161 rm_ctxt->exn_insn_len = insn_len; 48.162 48.163 @@ -568,12 +623,22 @@ static void realmode_emulate_one(struct 48.164 struct vcpu *curr = current; 48.165 u32 new_intr_shadow; 48.166 int rc, io_completed; 48.167 + unsigned long addr; 48.168 48.169 - rm_ctxt->insn_buf_eip = regs->eip; 48.170 - (void)hvm_copy_from_guest_phys( 48.171 - rm_ctxt->insn_buf, 48.172 - (uint32_t)(rm_ctxt->seg_reg[x86_seg_cs].base + regs->eip), 48.173 - sizeof(rm_ctxt->insn_buf)); 48.174 + rm_ctxt->ctxt.addr_size = 48.175 + rm_ctxt->seg_reg[x86_seg_cs].attr.fields.db ? 32 : 16; 48.176 + rm_ctxt->ctxt.sp_size = 48.177 + rm_ctxt->seg_reg[x86_seg_ss].attr.fields.db ? 32 : 16; 48.178 + 48.179 + rm_ctxt->insn_buf_eip = (uint32_t)regs->eip; 48.180 + addr = virtual_to_linear(x86_seg_cs, regs->eip, rm_ctxt); 48.181 + if ( hvm_fetch_from_guest_virt_nofault(rm_ctxt->insn_buf, addr, 48.182 + sizeof(rm_ctxt->insn_buf)) 48.183 + != HVMCOPY_okay ) 48.184 + { 48.185 + gdprintk(XENLOG_ERR, "Failed to pre-fetch instruction bytes.\n"); 48.186 + goto fail; 48.187 + } 48.188 48.189 rm_ctxt->flag_word = 0; 48.190 48.191 @@ -670,39 +735,35 @@ void vmx_realmode(struct cpu_user_regs * 48.192 for ( i = 0; i < 10; i++ ) 48.193 hvm_get_segment_register(curr, i, &rm_ctxt.seg_reg[i]); 48.194 48.195 - rm_ctxt.ctxt.addr_size = 48.196 - rm_ctxt.seg_reg[x86_seg_cs].attr.fields.db ? 32 : 16; 48.197 - rm_ctxt.ctxt.sp_size = 48.198 - rm_ctxt.seg_reg[x86_seg_ss].attr.fields.db ? 32 : 16; 48.199 - 48.200 rm_ctxt.intr_shadow = __vmread(GUEST_INTERRUPTIBILITY_INFO); 48.201 48.202 if ( curr->arch.hvm_vmx.real_mode_io_in_progress || 48.203 curr->arch.hvm_vmx.real_mode_io_completed ) 48.204 realmode_emulate_one(&rm_ctxt); 48.205 48.206 - if ( intr_info & INTR_INFO_VALID_MASK ) 48.207 + /* Only deliver interrupts into emulated real mode. */ 48.208 + if ( !(curr->arch.hvm_vcpu.guest_cr[0] & X86_CR0_PE) && 48.209 + (intr_info & INTR_INFO_VALID_MASK) ) 48.210 { 48.211 realmode_deliver_exception((uint8_t)intr_info, 0, &rm_ctxt); 48.212 __vmwrite(VM_ENTRY_INTR_INFO, 0); 48.213 } 48.214 48.215 - while ( !(curr->arch.hvm_vcpu.guest_cr[0] & X86_CR0_PE) && 48.216 + while ( curr->arch.hvm_vmx.vmxemul && 48.217 !softirq_pending(smp_processor_id()) && 48.218 - !hvm_local_events_need_delivery(curr) && 48.219 - !curr->arch.hvm_vmx.real_mode_io_in_progress ) 48.220 + !curr->arch.hvm_vmx.real_mode_io_in_progress && 48.221 + /* Check for pending interrupts only in proper real mode. */ 48.222 + ((curr->arch.hvm_vcpu.guest_cr[0] & X86_CR0_PE) || 48.223 + !hvm_local_events_need_delivery(curr)) ) 48.224 realmode_emulate_one(&rm_ctxt); 48.225 48.226 - /* 48.227 - * Cannot enter protected mode with bogus selector RPLs and DPLs. Hence we 48.228 - * fix up as best we can, even though this deviates from native execution 48.229 - */ 48.230 - if ( curr->arch.hvm_vcpu.guest_cr[0] & X86_CR0_PE ) 48.231 + if ( !curr->arch.hvm_vmx.vmxemul ) 48.232 { 48.233 - /* CS.RPL == SS.RPL == SS.DPL == 0. */ 48.234 - rm_ctxt.seg_reg[x86_seg_cs].sel &= ~3; 48.235 - rm_ctxt.seg_reg[x86_seg_ss].sel &= ~3; 48.236 - /* DS,ES,FS,GS: The most uninvasive trick is to set DPL == RPL. */ 48.237 + /* 48.238 + * Cannot enter protected mode with bogus selector RPLs and DPLs. 48.239 + * At this point CS.RPL == SS.RPL == CS.DPL == SS.DPL == 0. For 48.240 + * DS, ES, FS and GS the most uninvasive trick is to set DPL == RPL. 48.241 + */ 48.242 rm_ctxt.seg_reg[x86_seg_ds].attr.fields.dpl = 48.243 rm_ctxt.seg_reg[x86_seg_ds].sel & 3; 48.244 rm_ctxt.seg_reg[x86_seg_es].attr.fields.dpl =
49.1 --- a/xen/arch/x86/hvm/vmx/vmx.c Thu Feb 07 09:23:26 2008 -0700 49.2 +++ b/xen/arch/x86/hvm/vmx/vmx.c Thu Feb 07 11:08:49 2008 -0700 49.3 @@ -41,7 +41,6 @@ 49.4 #include <asm/hvm/support.h> 49.5 #include <asm/hvm/vmx/vmx.h> 49.6 #include <asm/hvm/vmx/vmcs.h> 49.7 -#include <asm/hvm/vmx/cpu.h> 49.8 #include <public/sched.h> 49.9 #include <public/hvm/ioreq.h> 49.10 #include <asm/hvm/vpic.h> 49.11 @@ -94,11 +93,10 @@ static int vmx_vcpu_initialise(struct vc 49.12 49.13 vmx_install_vlapic_mapping(v); 49.14 49.15 -#ifndef VMXASSIST 49.16 + /* %eax == 1 signals full real-mode support to the guest loader. */ 49.17 if ( v->vcpu_id == 0 ) 49.18 v->arch.guest_context.user_regs.eax = 1; 49.19 v->arch.hvm_vcpu.io_complete = vmx_realmode_io_complete; 49.20 -#endif 49.21 49.22 return 0; 49.23 } 49.24 @@ -710,10 +708,6 @@ static void vmx_load_cpu_state(struct vc 49.25 v->arch.hvm_vmx.shadow_gs = data->shadow_gs; 49.26 #endif 49.27 49.28 -#ifdef VMXASSIST 49.29 - v->arch.hvm_vmx.vmxassist_enabled = !(data->cr0 & X86_CR0_PE); 49.30 -#endif 49.31 - 49.32 hvm_set_guest_time(v, data->tsc); 49.33 49.34 dump_msr_state(guest_state); 49.35 @@ -1061,6 +1055,10 @@ static void vmx_update_guest_cr(struct v 49.36 vmx_fpu_enter(v); 49.37 } 49.38 49.39 + v->arch.hvm_vmx.vmxemul &= ~VMXEMUL_REALMODE; 49.40 + if ( !(v->arch.hvm_vcpu.guest_cr[0] & X86_CR0_PE) ) 49.41 + v->arch.hvm_vmx.vmxemul |= VMXEMUL_REALMODE; 49.42 + 49.43 v->arch.hvm_vcpu.hw_cr[0] = 49.44 v->arch.hvm_vcpu.guest_cr[0] | hw_cr0_mask; 49.45 __vmwrite(GUEST_CR0, v->arch.hvm_vcpu.hw_cr[0]); 49.46 @@ -1263,65 +1261,18 @@ void vmx_cpuid_intercept( 49.47 unsigned int input = *eax; 49.48 unsigned int count = *ecx; 49.49 49.50 -#ifdef VMXASSIST 49.51 - if ( input == 0x40000003 ) 49.52 - { 49.53 - /* 49.54 - * NB. Unsupported interface for private use of VMXASSIST only. 49.55 - * Note that this leaf lives at <max-hypervisor-leaf> + 1. 49.56 - */ 49.57 - u64 value = ((u64)*edx << 32) | (u32)*ecx; 49.58 - p2m_type_t p2mt; 49.59 - unsigned long mfn; 49.60 - struct vcpu *v = current; 49.61 - char *p; 49.62 - 49.63 - mfn = mfn_x(gfn_to_mfn_current(value >> PAGE_SHIFT, &p2mt)); 49.64 - 49.65 - gdprintk(XENLOG_INFO, "Input address is 0x%"PRIx64".\n", value); 49.66 - 49.67 - /* 8-byte aligned valid pseudophys address from vmxassist, please. */ 49.68 - if ( (value & 7) || !p2m_is_ram(p2mt) || 49.69 - !v->arch.hvm_vmx.vmxassist_enabled ) 49.70 - { 49.71 - domain_crash(v->domain); 49.72 - return; 49.73 - } 49.74 - ASSERT(mfn_valid(mfn)); 49.75 - 49.76 - p = map_domain_page(mfn); 49.77 - value = *((uint64_t *)(p + (value & (PAGE_SIZE - 1)))); 49.78 - unmap_domain_page(p); 49.79 - 49.80 - gdprintk(XENLOG_INFO, "Output value is 0x%"PRIx64".\n", value); 49.81 - *ecx = (u32)value; 49.82 - *edx = (u32)(value >> 32); 49.83 - return; 49.84 - } 49.85 -#endif 49.86 - 49.87 hvm_cpuid(input, eax, ebx, ecx, edx); 49.88 49.89 switch ( input ) 49.90 { 49.91 case 0x00000001: 49.92 - *ecx &= ~VMX_VCPU_CPUID_L1_ECX_RESERVED; 49.93 - *ebx &= NUM_THREADS_RESET_MASK; 49.94 - *ecx &= ~(bitmaskof(X86_FEATURE_VMXE) | 49.95 - bitmaskof(X86_FEATURE_EST) | 49.96 - bitmaskof(X86_FEATURE_TM2) | 49.97 - bitmaskof(X86_FEATURE_CID) | 49.98 - bitmaskof(X86_FEATURE_PDCM) | 49.99 - bitmaskof(X86_FEATURE_DSCPL)); 49.100 - *edx &= ~(bitmaskof(X86_FEATURE_HT) | 49.101 - bitmaskof(X86_FEATURE_ACPI) | 49.102 - bitmaskof(X86_FEATURE_ACC) | 49.103 - bitmaskof(X86_FEATURE_DS)); 49.104 + /* Mask AMD-only features. */ 49.105 + *ecx &= ~(bitmaskof(X86_FEATURE_POPCNT)); 49.106 break; 49.107 49.108 case 0x00000004: 49.109 cpuid_count(input, count, eax, ebx, ecx, edx); 49.110 - *eax &= NUM_CORES_RESET_MASK; 49.111 + *eax &= 0x3FFF; /* one core */ 49.112 break; 49.113 49.114 case 0x00000006: 49.115 @@ -1839,256 +1790,6 @@ static void vmx_io_instruction(unsigned 49.116 } 49.117 } 49.118 49.119 -#ifdef VMXASSIST 49.120 - 49.121 -static void vmx_world_save(struct vcpu *v, struct vmx_assist_context *c) 49.122 -{ 49.123 - struct cpu_user_regs *regs = guest_cpu_user_regs(); 49.124 - 49.125 - c->eip = regs->eip; 49.126 - c->eip += __get_instruction_length(); /* Safe: MOV Cn, LMSW, CLTS */ 49.127 - c->esp = regs->esp; 49.128 - c->eflags = regs->eflags & ~X86_EFLAGS_RF; 49.129 - 49.130 - c->cr0 = v->arch.hvm_vcpu.guest_cr[0]; 49.131 - c->cr3 = v->arch.hvm_vcpu.guest_cr[3]; 49.132 - c->cr4 = v->arch.hvm_vcpu.guest_cr[4]; 49.133 - 49.134 - c->idtr_limit = __vmread(GUEST_IDTR_LIMIT); 49.135 - c->idtr_base = __vmread(GUEST_IDTR_BASE); 49.136 - 49.137 - c->gdtr_limit = __vmread(GUEST_GDTR_LIMIT); 49.138 - c->gdtr_base = __vmread(GUEST_GDTR_BASE); 49.139 - 49.140 - c->cs_sel = __vmread(GUEST_CS_SELECTOR); 49.141 - c->cs_limit = __vmread(GUEST_CS_LIMIT); 49.142 - c->cs_base = __vmread(GUEST_CS_BASE); 49.143 - c->cs_arbytes.bytes = __vmread(GUEST_CS_AR_BYTES); 49.144 - 49.145 - c->ds_sel = __vmread(GUEST_DS_SELECTOR); 49.146 - c->ds_limit = __vmread(GUEST_DS_LIMIT); 49.147 - c->ds_base = __vmread(GUEST_DS_BASE); 49.148 - c->ds_arbytes.bytes = __vmread(GUEST_DS_AR_BYTES); 49.149 - 49.150 - c->es_sel = __vmread(GUEST_ES_SELECTOR); 49.151 - c->es_limit = __vmread(GUEST_ES_LIMIT); 49.152 - c->es_base = __vmread(GUEST_ES_BASE); 49.153 - c->es_arbytes.bytes = __vmread(GUEST_ES_AR_BYTES); 49.154 - 49.155 - c->ss_sel = __vmread(GUEST_SS_SELECTOR); 49.156 - c->ss_limit = __vmread(GUEST_SS_LIMIT); 49.157 - c->ss_base = __vmread(GUEST_SS_BASE); 49.158 - c->ss_arbytes.bytes = __vmread(GUEST_SS_AR_BYTES); 49.159 - 49.160 - c->fs_sel = __vmread(GUEST_FS_SELECTOR); 49.161 - c->fs_limit = __vmread(GUEST_FS_LIMIT); 49.162 - c->fs_base = __vmread(GUEST_FS_BASE); 49.163 - c->fs_arbytes.bytes = __vmread(GUEST_FS_AR_BYTES); 49.164 - 49.165 - c->gs_sel = __vmread(GUEST_GS_SELECTOR); 49.166 - c->gs_limit = __vmread(GUEST_GS_LIMIT); 49.167 - c->gs_base = __vmread(GUEST_GS_BASE); 49.168 - c->gs_arbytes.bytes = __vmread(GUEST_GS_AR_BYTES); 49.169 - 49.170 - c->tr_sel = __vmread(GUEST_TR_SELECTOR); 49.171 - c->tr_limit = __vmread(GUEST_TR_LIMIT); 49.172 - c->tr_base = __vmread(GUEST_TR_BASE); 49.173 - c->tr_arbytes.bytes = __vmread(GUEST_TR_AR_BYTES); 49.174 - 49.175 - c->ldtr_sel = __vmread(GUEST_LDTR_SELECTOR); 49.176 - c->ldtr_limit = __vmread(GUEST_LDTR_LIMIT); 49.177 - c->ldtr_base = __vmread(GUEST_LDTR_BASE); 49.178 - c->ldtr_arbytes.bytes = __vmread(GUEST_LDTR_AR_BYTES); 49.179 -} 49.180 - 49.181 -static int vmx_world_restore(struct vcpu *v, struct vmx_assist_context *c) 49.182 -{ 49.183 - struct cpu_user_regs *regs = guest_cpu_user_regs(); 49.184 - int rc; 49.185 - 49.186 - rc = vmx_restore_cr0_cr3(v, c->cr0, c->cr3); 49.187 - if ( rc ) 49.188 - return rc; 49.189 - 49.190 - regs->eip = c->eip; 49.191 - regs->esp = c->esp; 49.192 - regs->eflags = c->eflags | 2; 49.193 - 49.194 - v->arch.hvm_vcpu.guest_cr[4] = c->cr4; 49.195 - vmx_update_guest_cr(v, 0); 49.196 - vmx_update_guest_cr(v, 4); 49.197 - 49.198 - __vmwrite(GUEST_IDTR_LIMIT, c->idtr_limit); 49.199 - __vmwrite(GUEST_IDTR_BASE, c->idtr_base); 49.200 - 49.201 - __vmwrite(GUEST_GDTR_LIMIT, c->gdtr_limit); 49.202 - __vmwrite(GUEST_GDTR_BASE, c->gdtr_base); 49.203 - 49.204 - __vmwrite(GUEST_CS_SELECTOR, c->cs_sel); 49.205 - __vmwrite(GUEST_CS_LIMIT, c->cs_limit); 49.206 - __vmwrite(GUEST_CS_BASE, c->cs_base); 49.207 - __vmwrite(GUEST_CS_AR_BYTES, c->cs_arbytes.bytes); 49.208 - 49.209 - __vmwrite(GUEST_DS_SELECTOR, c->ds_sel); 49.210 - __vmwrite(GUEST_DS_LIMIT, c->ds_limit); 49.211 - __vmwrite(GUEST_DS_BASE, c->ds_base); 49.212 - __vmwrite(GUEST_DS_AR_BYTES, c->ds_arbytes.bytes); 49.213 - 49.214 - __vmwrite(GUEST_ES_SELECTOR, c->es_sel); 49.215 - __vmwrite(GUEST_ES_LIMIT, c->es_limit); 49.216 - __vmwrite(GUEST_ES_BASE, c->es_base); 49.217 - __vmwrite(GUEST_ES_AR_BYTES, c->es_arbytes.bytes); 49.218 - 49.219 - __vmwrite(GUEST_SS_SELECTOR, c->ss_sel); 49.220 - __vmwrite(GUEST_SS_LIMIT, c->ss_limit); 49.221 - __vmwrite(GUEST_SS_BASE, c->ss_base); 49.222 - __vmwrite(GUEST_SS_AR_BYTES, c->ss_arbytes.bytes); 49.223 - 49.224 - __vmwrite(GUEST_FS_SELECTOR, c->fs_sel); 49.225 - __vmwrite(GUEST_FS_LIMIT, c->fs_limit); 49.226 - __vmwrite(GUEST_FS_BASE, c->fs_base); 49.227 - __vmwrite(GUEST_FS_AR_BYTES, c->fs_arbytes.bytes); 49.228 - 49.229 - __vmwrite(GUEST_GS_SELECTOR, c->gs_sel); 49.230 - __vmwrite(GUEST_GS_LIMIT, c->gs_limit); 49.231 - __vmwrite(GUEST_GS_BASE, c->gs_base); 49.232 - __vmwrite(GUEST_GS_AR_BYTES, c->gs_arbytes.bytes); 49.233 - 49.234 - __vmwrite(GUEST_TR_SELECTOR, c->tr_sel); 49.235 - __vmwrite(GUEST_TR_LIMIT, c->tr_limit); 49.236 - __vmwrite(GUEST_TR_BASE, c->tr_base); 49.237 - __vmwrite(GUEST_TR_AR_BYTES, c->tr_arbytes.bytes); 49.238 - 49.239 - __vmwrite(GUEST_LDTR_SELECTOR, c->ldtr_sel); 49.240 - __vmwrite(GUEST_LDTR_LIMIT, c->ldtr_limit); 49.241 - __vmwrite(GUEST_LDTR_BASE, c->ldtr_base); 49.242 - __vmwrite(GUEST_LDTR_AR_BYTES, c->ldtr_arbytes.bytes); 49.243 - 49.244 - paging_update_paging_modes(v); 49.245 - return 0; 49.246 -} 49.247 - 49.248 -enum { VMX_ASSIST_INVOKE = 0, VMX_ASSIST_RESTORE }; 49.249 - 49.250 -static int vmx_assist(struct vcpu *v, int mode) 49.251 -{ 49.252 - struct vmx_assist_context c; 49.253 - struct hvm_hw_vpic *vpic = v->domain->arch.hvm_domain.vpic; 49.254 - u32 magic, cp; 49.255 - 49.256 - if ( hvm_copy_from_guest_phys(&magic, VMXASSIST_MAGIC_OFFSET, 49.257 - sizeof(magic)) ) 49.258 - { 49.259 - gdprintk(XENLOG_ERR, "No vmxassist: can't execute real mode code\n"); 49.260 - domain_crash(v->domain); 49.261 - return 0; 49.262 - } 49.263 - 49.264 - if ( magic != VMXASSIST_MAGIC ) 49.265 - { 49.266 - gdprintk(XENLOG_ERR, "vmxassist magic number not match\n"); 49.267 - domain_crash(v->domain); 49.268 - return 0; 49.269 - } 49.270 - 49.271 - switch ( mode ) { 49.272 - /* 49.273 - * Transfer control to vmxassist. 49.274 - * Store the current context in VMXASSIST_OLD_CONTEXT and load 49.275 - * the new VMXASSIST_NEW_CONTEXT context. This context was created 49.276 - * by vmxassist and will transfer control to it. 49.277 - */ 49.278 - case VMX_ASSIST_INVOKE: 49.279 - /* save the old context */ 49.280 - if ( hvm_copy_from_guest_phys(&cp, VMXASSIST_OLD_CONTEXT, sizeof(cp)) ) 49.281 - goto error; 49.282 - if ( cp != 0 ) { 49.283 - vmx_world_save(v, &c); 49.284 - if ( hvm_copy_to_guest_phys(cp, &c, sizeof(c)) ) 49.285 - goto error; 49.286 - } 49.287 - 49.288 - /* restore the new context, this should activate vmxassist */ 49.289 - if ( hvm_copy_from_guest_phys(&cp, VMXASSIST_NEW_CONTEXT, sizeof(cp)) ) 49.290 - goto error; 49.291 - if ( cp != 0 ) { 49.292 - if ( hvm_copy_from_guest_phys(&c, cp, sizeof(c)) ) 49.293 - goto error; 49.294 - if ( vmx_world_restore(v, &c) != 0 ) 49.295 - goto error; 49.296 - v->arch.hvm_vmx.pm_irqbase[0] = vpic[0].irq_base; 49.297 - v->arch.hvm_vmx.pm_irqbase[1] = vpic[1].irq_base; 49.298 - vpic[0].irq_base = NR_EXCEPTION_HANDLER; 49.299 - vpic[1].irq_base = NR_EXCEPTION_HANDLER + 8; 49.300 - v->arch.hvm_vmx.vmxassist_enabled = 1; 49.301 - return 1; 49.302 - } 49.303 - break; 49.304 - 49.305 - /* 49.306 - * Restore the VMXASSIST_OLD_CONTEXT that was saved by 49.307 - * VMX_ASSIST_INVOKE above. 49.308 - */ 49.309 - case VMX_ASSIST_RESTORE: 49.310 - /* save the old context */ 49.311 - if ( hvm_copy_from_guest_phys(&cp, VMXASSIST_OLD_CONTEXT, sizeof(cp)) ) 49.312 - goto error; 49.313 - if ( cp != 0 ) { 49.314 - if ( hvm_copy_from_guest_phys(&c, cp, sizeof(c)) ) 49.315 - goto error; 49.316 - if ( vmx_world_restore(v, &c) != 0 ) 49.317 - goto error; 49.318 - if ( v->arch.hvm_vmx.irqbase_mode ) { 49.319 - vpic[0].irq_base = c.rm_irqbase[0] & 0xf8; 49.320 - vpic[1].irq_base = c.rm_irqbase[1] & 0xf8; 49.321 - } else { 49.322 - vpic[0].irq_base = v->arch.hvm_vmx.pm_irqbase[0]; 49.323 - vpic[1].irq_base = v->arch.hvm_vmx.pm_irqbase[1]; 49.324 - } 49.325 - v->arch.hvm_vmx.vmxassist_enabled = 0; 49.326 - return 1; 49.327 - } 49.328 - break; 49.329 - } 49.330 - 49.331 - error: 49.332 - gdprintk(XENLOG_ERR, "Failed to transfer to vmxassist\n"); 49.333 - domain_crash(v->domain); 49.334 - return 0; 49.335 -} 49.336 - 49.337 -static int vmx_set_cr0(unsigned long value) 49.338 -{ 49.339 - struct vcpu *v = current; 49.340 - 49.341 - if ( hvm_set_cr0(value) == 0 ) 49.342 - return 0; 49.343 - 49.344 - /* 49.345 - * VMX does not implement real-mode virtualization. We emulate 49.346 - * real-mode by performing a world switch to VMXAssist whenever 49.347 - * a partition disables the CR0.PE bit. 49.348 - */ 49.349 - if ( !(value & X86_CR0_PE) ) 49.350 - { 49.351 - if ( vmx_assist(v, VMX_ASSIST_INVOKE) ) 49.352 - return 0; /* do not update eip! */ 49.353 - } 49.354 - else if ( v->arch.hvm_vmx.vmxassist_enabled ) 49.355 - { 49.356 - if ( vmx_assist(v, VMX_ASSIST_RESTORE) ) 49.357 - return 0; /* do not update eip! */ 49.358 - } 49.359 - 49.360 - return 1; 49.361 -} 49.362 - 49.363 -#else /* !defined(VMXASSIST) */ 49.364 - 49.365 -#define vmx_set_cr0(v) hvm_set_cr0(v) 49.366 - 49.367 -#endif 49.368 - 49.369 #define CASE_SET_REG(REG, reg) \ 49.370 case REG_ ## REG: regs->reg = value; break 49.371 #define CASE_GET_REG(REG, reg) \ 49.372 @@ -2142,7 +1843,7 @@ static int mov_to_cr(int gp, int cr, str 49.373 switch ( cr ) 49.374 { 49.375 case 0: 49.376 - return vmx_set_cr0(value); 49.377 + return hvm_set_cr0(value); 49.378 49.379 case 3: 49.380 return hvm_set_cr3(value); 49.381 @@ -2239,7 +1940,7 @@ static int vmx_cr_access(unsigned long e 49.382 value = (value & ~0xF) | 49.383 (((exit_qualification & LMSW_SOURCE_DATA) >> 16) & 0xF); 49.384 HVMTRACE_1D(LMSW, current, value); 49.385 - return vmx_set_cr0(value); 49.386 + return hvm_set_cr0(value); 49.387 default: 49.388 BUG(); 49.389 }
50.1 --- a/xen/arch/x86/hvm/vmx/vpmu.c Thu Feb 07 09:23:26 2008 -0700 50.2 +++ b/xen/arch/x86/hvm/vmx/vpmu.c Thu Feb 07 11:08:49 2008 -0700 50.3 @@ -89,8 +89,6 @@ void vpmu_initialise(struct vcpu *v) 50.4 case 15: 50.5 case 23: 50.6 vpmu->arch_vpmu_ops = &core2_vpmu_ops; 50.7 - dprintk(XENLOG_INFO, 50.8 - "Core 2 duo CPU detected for guest PMU usage.\n"); 50.9 break; 50.10 } 50.11 }
51.1 --- a/xen/arch/x86/hvm/vmx/vpmu_core2.c Thu Feb 07 09:23:26 2008 -0700 51.2 +++ b/xen/arch/x86/hvm/vmx/vpmu_core2.c Thu Feb 07 11:08:49 2008 -0700 51.3 @@ -35,60 +35,69 @@ 51.4 #include <asm/hvm/vmx/vpmu.h> 51.5 #include <asm/hvm/vmx/vpmu_core2.h> 51.6 51.7 -static int arch_pmc_cnt = 0; 51.8 +static int arch_pmc_cnt; 51.9 51.10 static int core2_get_pmc_count(void) 51.11 { 51.12 u32 eax, ebx, ecx, edx; 51.13 51.14 - if ( arch_pmc_cnt ) 51.15 - return arch_pmc_cnt; 51.16 + if ( arch_pmc_cnt == 0 ) 51.17 + { 51.18 + cpuid(0xa, &eax, &ebx, &ecx, &edx); 51.19 + arch_pmc_cnt = (eax & 0xff00) >> 8; 51.20 + } 51.21 51.22 - cpuid(0xa, &eax, &ebx, &ecx, &edx); 51.23 - return arch_pmc_cnt = (eax & 0xff00) >> 8; 51.24 + return arch_pmc_cnt; 51.25 } 51.26 51.27 static int is_core2_vpmu_msr(u32 msr_index, int *type, int *index) 51.28 { 51.29 int i; 51.30 51.31 - for ( i=0; i < core2_counters.num; i++ ) 51.32 + for ( i = 0; i < core2_counters.num; i++ ) 51.33 + { 51.34 if ( core2_counters.msr[i] == msr_index ) 51.35 { 51.36 *type = MSR_TYPE_COUNTER; 51.37 *index = i; 51.38 return 1; 51.39 } 51.40 - for ( i=0; i < core2_ctrls.num; i++ ) 51.41 + } 51.42 + 51.43 + for ( i = 0; i < core2_ctrls.num; i++ ) 51.44 + { 51.45 if ( core2_ctrls.msr[i] == msr_index ) 51.46 { 51.47 *type = MSR_TYPE_CTRL; 51.48 *index = i; 51.49 return 1; 51.50 } 51.51 + } 51.52 51.53 - if ( msr_index == MSR_CORE_PERF_GLOBAL_CTRL || 51.54 - msr_index == MSR_CORE_PERF_GLOBAL_STATUS || 51.55 - msr_index == MSR_CORE_PERF_GLOBAL_OVF_CTRL ) 51.56 + if ( (msr_index == MSR_CORE_PERF_GLOBAL_CTRL) || 51.57 + (msr_index == MSR_CORE_PERF_GLOBAL_STATUS) || 51.58 + (msr_index == MSR_CORE_PERF_GLOBAL_OVF_CTRL) ) 51.59 { 51.60 *type = MSR_TYPE_GLOBAL; 51.61 return 1; 51.62 } 51.63 51.64 - if ( msr_index >= MSR_IA32_PERFCTR0 && 51.65 - msr_index < MSR_IA32_PERFCTR0 + core2_get_pmc_count() ) 51.66 + if ( (msr_index >= MSR_IA32_PERFCTR0) && 51.67 + (msr_index < (MSR_IA32_PERFCTR0 + core2_get_pmc_count())) ) 51.68 { 51.69 *type = MSR_TYPE_ARCH_COUNTER; 51.70 *index = msr_index - MSR_IA32_PERFCTR0; 51.71 return 1; 51.72 } 51.73 - if ( msr_index >= MSR_P6_EVNTSEL0 && 51.74 - msr_index < MSR_P6_EVNTSEL0 + core2_get_pmc_count() ) 51.75 + 51.76 + if ( (msr_index >= MSR_P6_EVNTSEL0) && 51.77 + (msr_index < (MSR_P6_EVNTSEL0 + core2_get_pmc_count())) ) 51.78 { 51.79 *type = MSR_TYPE_ARCH_CTRL; 51.80 *index = msr_index - MSR_P6_EVNTSEL0; 51.81 return 1; 51.82 } 51.83 + 51.84 return 0; 51.85 } 51.86 51.87 @@ -97,20 +106,21 @@ static void core2_vpmu_set_msr_bitmap(ch 51.88 int i; 51.89 51.90 /* Allow Read/Write PMU Counters MSR Directly. */ 51.91 - for ( i=0; i < core2_counters.num; i++ ) 51.92 + for ( i = 0; i < core2_counters.num; i++ ) 51.93 { 51.94 clear_bit(msraddr_to_bitpos(core2_counters.msr[i]), msr_bitmap); 51.95 - clear_bit(msraddr_to_bitpos(core2_counters.msr[i]), msr_bitmap + 0x800); 51.96 + clear_bit(msraddr_to_bitpos(core2_counters.msr[i]), msr_bitmap+0x800); 51.97 } 51.98 - for ( i=0; i < core2_get_pmc_count(); i++ ) 51.99 + for ( i = 0; i < core2_get_pmc_count(); i++ ) 51.100 { 51.101 clear_bit(msraddr_to_bitpos(MSR_IA32_PERFCTR0+i), msr_bitmap); 51.102 - clear_bit(msraddr_to_bitpos(MSR_IA32_PERFCTR0+i), msr_bitmap + 0x800); 51.103 + clear_bit(msraddr_to_bitpos(MSR_IA32_PERFCTR0+i), msr_bitmap+0x800); 51.104 } 51.105 + 51.106 /* Allow Read PMU Non-global Controls Directly. */ 51.107 - for ( i=0; i < core2_ctrls.num; i++ ) 51.108 + for ( i = 0; i < core2_ctrls.num; i++ ) 51.109 clear_bit(msraddr_to_bitpos(core2_ctrls.msr[i]), msr_bitmap); 51.110 - for ( i=0; i < core2_get_pmc_count(); i++ ) 51.111 + for ( i = 0; i < core2_get_pmc_count(); i++ ) 51.112 clear_bit(msraddr_to_bitpos(MSR_P6_EVNTSEL0+i), msr_bitmap); 51.113 } 51.114 51.115 @@ -118,20 +128,19 @@ static void core2_vpmu_unset_msr_bitmap( 51.116 { 51.117 int i; 51.118 51.119 - /* Undo all the changes to msr bitmap. */ 51.120 - for ( i=0; i < core2_counters.num; i++ ) 51.121 + for ( i = 0; i < core2_counters.num; i++ ) 51.122 { 51.123 set_bit(msraddr_to_bitpos(core2_counters.msr[i]), msr_bitmap); 51.124 - set_bit(msraddr_to_bitpos(core2_counters.msr[i]), msr_bitmap + 0x800); 51.125 + set_bit(msraddr_to_bitpos(core2_counters.msr[i]), msr_bitmap+0x800); 51.126 } 51.127 - for ( i=0; i < core2_get_pmc_count(); i++ ) 51.128 + for ( i = 0; i < core2_get_pmc_count(); i++ ) 51.129 { 51.130 set_bit(msraddr_to_bitpos(MSR_IA32_PERFCTR0+i), msr_bitmap); 51.131 - set_bit(msraddr_to_bitpos(MSR_IA32_PERFCTR0+i), msr_bitmap + 0x800); 51.132 + set_bit(msraddr_to_bitpos(MSR_IA32_PERFCTR0+i), msr_bitmap+0x800); 51.133 } 51.134 - for ( i=0; i < core2_ctrls.num; i++ ) 51.135 + for ( i = 0; i < core2_ctrls.num; i++ ) 51.136 set_bit(msraddr_to_bitpos(core2_ctrls.msr[i]), msr_bitmap); 51.137 - for ( i=0; i < core2_get_pmc_count(); i++ ) 51.138 + for ( i = 0; i < core2_get_pmc_count(); i++ ) 51.139 set_bit(msraddr_to_bitpos(MSR_P6_EVNTSEL0+i), msr_bitmap); 51.140 } 51.141 51.142 @@ -140,9 +149,9 @@ static inline void __core2_vpmu_save(str 51.143 int i; 51.144 struct core2_vpmu_context *core2_vpmu_cxt = vcpu_vpmu(v)->context; 51.145 51.146 - for ( i=0; i < core2_counters.num; i++ ) 51.147 + for ( i = 0; i < core2_counters.num; i++ ) 51.148 rdmsrl(core2_counters.msr[i], core2_vpmu_cxt->counters[i]); 51.149 - for ( i=0; i < core2_get_pmc_count(); i++ ) 51.150 + for ( i = 0; i < core2_get_pmc_count(); i++ ) 51.151 rdmsrl(MSR_IA32_PERFCTR0+i, core2_vpmu_cxt->arch_msr_pair[i].counter); 51.152 core2_vpmu_cxt->hw_lapic_lvtpc = apic_read(APIC_LVTPC); 51.153 apic_write(APIC_LVTPC, LVTPC_HVM_PMU | APIC_LVT_MASKED); 51.154 @@ -171,14 +180,14 @@ static inline void __core2_vpmu_load(str 51.155 int i; 51.156 struct core2_vpmu_context *core2_vpmu_cxt = vcpu_vpmu(v)->context; 51.157 51.158 - for ( i=0; i < core2_counters.num; i++ ) 51.159 + for ( i = 0; i < core2_counters.num; i++ ) 51.160 wrmsrl(core2_counters.msr[i], core2_vpmu_cxt->counters[i]); 51.161 - for ( i=0; i < core2_get_pmc_count(); i++ ) 51.162 + for ( i = 0; i < core2_get_pmc_count(); i++ ) 51.163 wrmsrl(MSR_IA32_PERFCTR0+i, core2_vpmu_cxt->arch_msr_pair[i].counter); 51.164 51.165 - for ( i=0; i < core2_ctrls.num; i++ ) 51.166 + for ( i = 0; i < core2_ctrls.num; i++ ) 51.167 wrmsrl(core2_ctrls.msr[i], core2_vpmu_cxt->ctrls[i]); 51.168 - for ( i=0; i < core2_get_pmc_count(); i++ ) 51.169 + for ( i = 0; i < core2_get_pmc_count(); i++ ) 51.170 wrmsrl(MSR_P6_EVNTSEL0+i, core2_vpmu_cxt->arch_msr_pair[i].control); 51.171 51.172 apic_write_around(APIC_LVTPC, core2_vpmu_cxt->hw_lapic_lvtpc); 51.173 @@ -233,9 +242,9 @@ static int core2_vpmu_alloc_resource(str 51.174 out2: 51.175 xfree(pmu_enable); 51.176 out1: 51.177 - dprintk(XENLOG_WARNING, "Insufficient memory for PMU, PMU feature is \ 51.178 - unavailable on domain %d vcpu %d.\n", 51.179 - v->vcpu_id, v->domain->domain_id); 51.180 + gdprintk(XENLOG_WARNING, "Insufficient memory for PMU, PMU feature is " 51.181 + "unavailable on domain %d vcpu %d.\n", 51.182 + v->vcpu_id, v->domain->domain_id); 51.183 return 0; 51.184 } 51.185 51.186 @@ -300,17 +309,17 @@ static int core2_vpmu_do_wrmsr(struct cp 51.187 core2_vpmu_cxt->global_ovf_status &= ~msr_content; 51.188 return 1; 51.189 case MSR_CORE_PERF_GLOBAL_STATUS: 51.190 - dprintk(XENLOG_INFO, "Can not write readonly MSR: \ 51.191 - MSR_PERF_GLOBAL_STATUS(0x38E)!\n"); 51.192 + gdprintk(XENLOG_INFO, "Can not write readonly MSR: " 51.193 + "MSR_PERF_GLOBAL_STATUS(0x38E)!\n"); 51.194 vmx_inject_hw_exception(current, TRAP_gp_fault, 0); 51.195 return 1; 51.196 case MSR_IA32_PEBS_ENABLE: 51.197 if ( msr_content & 1 ) 51.198 - dprintk(XENLOG_WARNING, "Guest is trying to enable PEBS, \ 51.199 - which is not supported.\n"); 51.200 + gdprintk(XENLOG_WARNING, "Guest is trying to enable PEBS, " 51.201 + "which is not supported.\n"); 51.202 return 1; 51.203 case MSR_IA32_DS_AREA: 51.204 - dprintk(XENLOG_WARNING, "Guest setting of DTS is ignored.\n"); 51.205 + gdprintk(XENLOG_WARNING, "Guest setting of DTS is ignored.\n"); 51.206 return 1; 51.207 case MSR_CORE_PERF_GLOBAL_CTRL: 51.208 global_ctrl = msr_content; 51.209 @@ -466,4 +475,3 @@ struct arch_vpmu_ops core2_vpmu_ops = { 51.210 .arch_vpmu_save = core2_vpmu_save, 51.211 .arch_vpmu_load = core2_vpmu_load 51.212 }; 51.213 -
52.1 --- a/xen/arch/x86/hvm/vmx/x86_32/exits.S Thu Feb 07 09:23:26 2008 -0700 52.2 +++ b/xen/arch/x86/hvm/vmx/x86_32/exits.S Thu Feb 07 11:08:49 2008 -0700 52.3 @@ -115,10 +115,8 @@ ENTRY(vmx_asm_do_vmentry) 52.4 movl $GUEST_RFLAGS,%eax 52.5 VMWRITE(UREGS_eflags) 52.6 52.7 -#ifndef VMXASSIST 52.8 - testb $X86_CR0_PE,VCPU_hvm_guest_cr0(%ebx) 52.9 - jz vmx_goto_realmode 52.10 -#endif 52.11 + testb $0xff,VCPU_vmx_emul(%ebx) 52.12 + jnz vmx_goto_realmode 52.13 52.14 cmpb $0,VCPU_vmx_launched(%ebx) 52.15 je vmx_launch 52.16 @@ -138,7 +136,6 @@ vmx_launch: 52.17 call vm_launch_fail 52.18 ud2 52.19 52.20 -#ifndef VMXASSIST 52.21 vmx_goto_realmode: 52.22 sti 52.23 movl %esp,%eax 52.24 @@ -146,4 +143,3 @@ vmx_goto_realmode: 52.25 call vmx_realmode 52.26 addl $4,%esp 52.27 jmp vmx_asm_do_vmentry 52.28 -#endif
53.1 --- a/xen/arch/x86/hvm/vmx/x86_64/exits.S Thu Feb 07 09:23:26 2008 -0700 53.2 +++ b/xen/arch/x86/hvm/vmx/x86_64/exits.S Thu Feb 07 11:08:49 2008 -0700 53.3 @@ -134,10 +134,8 @@ ENTRY(vmx_asm_do_vmentry) 53.4 movl $GUEST_RFLAGS,%eax 53.5 VMWRITE(UREGS_eflags) 53.6 53.7 -#ifndef VMXASSIST 53.8 - testb $X86_CR0_PE,VCPU_hvm_guest_cr0(%rbx) 53.9 - jz vmx_goto_realmode 53.10 -#endif 53.11 + testb $0xff,VCPU_vmx_emul(%rbx) 53.12 + jnz vmx_goto_realmode 53.13 53.14 cmpb $0,VCPU_vmx_launched(%rbx) 53.15 je vmx_launch 53.16 @@ -157,10 +155,8 @@ vmx_launch: 53.17 call vm_launch_fail 53.18 ud2 53.19 53.20 -#ifndef VMXASSIST 53.21 vmx_goto_realmode: 53.22 sti 53.23 movq %rsp,%rdi 53.24 call vmx_realmode 53.25 jmp vmx_asm_do_vmentry 53.26 -#endif
54.1 --- a/xen/arch/x86/hvm/vpic.c Thu Feb 07 09:23:26 2008 -0700 54.2 +++ b/xen/arch/x86/hvm/vpic.c Thu Feb 07 11:08:49 2008 -0700 54.3 @@ -271,11 +271,6 @@ static void vpic_ioport_write( 54.4 vpic->imr = val; 54.5 break; 54.6 case 1: 54.7 -#ifdef VMXASSIST 54.8 - /* Which mode is irqbase programmed in? */ 54.9 - current->arch.hvm_vmx.irqbase_mode = 54.10 - current->arch.hvm_vmx.vmxassist_enabled; 54.11 -#endif 54.12 /* ICW2 */ 54.13 vpic->irq_base = val & 0xf8; 54.14 vpic->init_state++;
55.1 --- a/xen/arch/x86/mm/shadow/common.c Thu Feb 07 09:23:26 2008 -0700 55.2 +++ b/xen/arch/x86/mm/shadow/common.c Thu Feb 07 11:08:49 2008 -0700 55.3 @@ -176,6 +176,8 @@ hvm_emulate_read(enum x86_segment seg, 55.4 unsigned int bytes, 55.5 struct x86_emulate_ctxt *ctxt) 55.6 { 55.7 + if ( !is_x86_user_segment(seg) ) 55.8 + return X86EMUL_UNHANDLEABLE; 55.9 return hvm_read(seg, offset, val, bytes, hvm_access_read, 55.10 container_of(ctxt, struct sh_emulate_ctxt, ctxt)); 55.11 } 55.12 @@ -191,6 +193,8 @@ hvm_emulate_insn_fetch(enum x86_segment 55.13 container_of(ctxt, struct sh_emulate_ctxt, ctxt); 55.14 unsigned int insn_off = offset - sh_ctxt->insn_buf_eip; 55.15 55.16 + ASSERT(seg == x86_seg_cs); 55.17 + 55.18 /* Fall back if requested bytes are not in the prefetch cache. */ 55.19 if ( unlikely((insn_off + bytes) > sh_ctxt->insn_buf_bytes) ) 55.20 return hvm_read(seg, offset, val, bytes, 55.21 @@ -215,6 +219,9 @@ hvm_emulate_write(enum x86_segment seg, 55.22 unsigned long addr; 55.23 int rc; 55.24 55.25 + if ( !is_x86_user_segment(seg) ) 55.26 + return X86EMUL_UNHANDLEABLE; 55.27 + 55.28 /* How many emulations could we save if we unshadowed on stack writes? */ 55.29 if ( seg == x86_seg_ss ) 55.30 perfc_incr(shadow_fault_emulate_stack); 55.31 @@ -242,6 +249,9 @@ hvm_emulate_cmpxchg(enum x86_segment seg 55.32 unsigned long addr; 55.33 int rc; 55.34 55.35 + if ( !is_x86_user_segment(seg) ) 55.36 + return X86EMUL_UNHANDLEABLE; 55.37 + 55.38 rc = hvm_translate_linear_addr( 55.39 seg, offset, bytes, hvm_access_write, sh_ctxt, &addr); 55.40 if ( rc ) 55.41 @@ -266,6 +276,9 @@ hvm_emulate_cmpxchg8b(enum x86_segment s 55.42 unsigned long addr; 55.43 int rc; 55.44 55.45 + if ( !is_x86_user_segment(seg) ) 55.46 + return X86EMUL_UNHANDLEABLE; 55.47 + 55.48 rc = hvm_translate_linear_addr( 55.49 seg, offset, 8, hvm_access_write, sh_ctxt, &addr); 55.50 if ( rc ) 55.51 @@ -292,6 +305,9 @@ pv_emulate_read(enum x86_segment seg, 55.52 { 55.53 unsigned int rc; 55.54 55.55 + if ( !is_x86_user_segment(seg) ) 55.56 + return X86EMUL_UNHANDLEABLE; 55.57 + 55.58 *val = 0; 55.59 if ( (rc = copy_from_user((void *)val, (void *)offset, bytes)) != 0 ) 55.60 { 55.61 @@ -312,6 +328,8 @@ pv_emulate_write(enum x86_segment seg, 55.62 struct sh_emulate_ctxt *sh_ctxt = 55.63 container_of(ctxt, struct sh_emulate_ctxt, ctxt); 55.64 struct vcpu *v = current; 55.65 + if ( !is_x86_user_segment(seg) ) 55.66 + return X86EMUL_UNHANDLEABLE; 55.67 return v->arch.paging.mode->shadow.x86_emulate_write( 55.68 v, offset, &val, bytes, sh_ctxt); 55.69 } 55.70 @@ -327,6 +345,8 @@ pv_emulate_cmpxchg(enum x86_segment seg, 55.71 struct sh_emulate_ctxt *sh_ctxt = 55.72 container_of(ctxt, struct sh_emulate_ctxt, ctxt); 55.73 struct vcpu *v = current; 55.74 + if ( !is_x86_user_segment(seg) ) 55.75 + return X86EMUL_UNHANDLEABLE; 55.76 return v->arch.paging.mode->shadow.x86_emulate_cmpxchg( 55.77 v, offset, old, new, bytes, sh_ctxt); 55.78 } 55.79 @@ -343,6 +363,8 @@ pv_emulate_cmpxchg8b(enum x86_segment se 55.80 struct sh_emulate_ctxt *sh_ctxt = 55.81 container_of(ctxt, struct sh_emulate_ctxt, ctxt); 55.82 struct vcpu *v = current; 55.83 + if ( !is_x86_user_segment(seg) ) 55.84 + return X86EMUL_UNHANDLEABLE; 55.85 return v->arch.paging.mode->shadow.x86_emulate_cmpxchg8b( 55.86 v, offset, old_lo, old_hi, new_lo, new_hi, sh_ctxt); 55.87 }
56.1 --- a/xen/arch/x86/x86_32/asm-offsets.c Thu Feb 07 09:23:26 2008 -0700 56.2 +++ b/xen/arch/x86/x86_32/asm-offsets.c Thu Feb 07 11:08:49 2008 -0700 56.3 @@ -84,7 +84,7 @@ void __dummy__(void) 56.4 BLANK(); 56.5 56.6 OFFSET(VCPU_vmx_launched, struct vcpu, arch.hvm_vmx.launched); 56.7 - OFFSET(VCPU_hvm_guest_cr0, struct vcpu, arch.hvm_vcpu.guest_cr[0]); 56.8 + OFFSET(VCPU_vmx_emul, struct vcpu, arch.hvm_vmx.vmxemul); 56.9 OFFSET(VCPU_hvm_guest_cr2, struct vcpu, arch.hvm_vcpu.guest_cr[2]); 56.10 BLANK(); 56.11
57.1 --- a/xen/arch/x86/x86_64/asm-offsets.c Thu Feb 07 09:23:26 2008 -0700 57.2 +++ b/xen/arch/x86/x86_64/asm-offsets.c Thu Feb 07 11:08:49 2008 -0700 57.3 @@ -103,7 +103,7 @@ void __dummy__(void) 57.4 BLANK(); 57.5 57.6 OFFSET(VCPU_vmx_launched, struct vcpu, arch.hvm_vmx.launched); 57.7 - OFFSET(VCPU_hvm_guest_cr0, struct vcpu, arch.hvm_vcpu.guest_cr[0]); 57.8 + OFFSET(VCPU_vmx_emul, struct vcpu, arch.hvm_vmx.vmxemul); 57.9 OFFSET(VCPU_hvm_guest_cr2, struct vcpu, arch.hvm_vcpu.guest_cr[2]); 57.10 BLANK(); 57.11
58.1 --- a/xen/arch/x86/x86_emulate.c Thu Feb 07 09:23:26 2008 -0700 58.2 +++ b/xen/arch/x86/x86_emulate.c Thu Feb 07 11:08:49 2008 -0700 58.3 @@ -303,7 +303,11 @@ struct operand { 58.4 #define EXC_OF 4 58.5 #define EXC_BR 5 58.6 #define EXC_UD 6 58.7 +#define EXC_TS 10 58.8 +#define EXC_NP 11 58.9 +#define EXC_SS 12 58.10 #define EXC_GP 13 58.11 +#define EXC_PF 14 58.12 58.13 /* 58.14 * Instruction emulation: 58.15 @@ -500,12 +504,12 @@ do { 58.16 if ( rc ) goto done; \ 58.17 } while (0) 58.18 58.19 -#define generate_exception_if(p, e) \ 58.20 -({ if ( (p) ) { \ 58.21 - fail_if(ops->inject_hw_exception == NULL); \ 58.22 - rc = ops->inject_hw_exception(e, ctxt) ? : X86EMUL_EXCEPTION; \ 58.23 - goto done; \ 58.24 - } \ 58.25 +#define generate_exception_if(p, e) \ 58.26 +({ if ( (p) ) { \ 58.27 + fail_if(ops->inject_hw_exception == NULL); \ 58.28 + rc = ops->inject_hw_exception(e, 0, ctxt) ? : X86EMUL_EXCEPTION; \ 58.29 + goto done; \ 58.30 + } \ 58.31 }) 58.32 58.33 /* 58.34 @@ -546,7 +550,8 @@ do { 58.35 58.36 #define jmp_rel(rel) \ 58.37 do { \ 58.38 - _regs.eip += (int)(rel); \ 58.39 + int _rel = (int)(rel); \ 58.40 + _regs.eip += _rel; \ 58.41 if ( !mode_64bit() ) \ 58.42 _regs.eip = ((op_bytes == 2) \ 58.43 ? (uint16_t)_regs.eip : (uint32_t)_regs.eip); \ 58.44 @@ -774,7 +779,7 @@ in_realmode( 58.45 } 58.46 58.47 static int 58.48 -load_seg( 58.49 +realmode_load_seg( 58.50 enum x86_segment seg, 58.51 uint16_t sel, 58.52 struct x86_emulate_ctxt *ctxt, 58.53 @@ -783,11 +788,6 @@ load_seg( 58.54 struct segment_register reg; 58.55 int rc; 58.56 58.57 - if ( !in_realmode(ctxt, ops) || 58.58 - (ops->read_segment == NULL) || 58.59 - (ops->write_segment == NULL) ) 58.60 - return X86EMUL_UNHANDLEABLE; 58.61 - 58.62 if ( (rc = ops->read_segment(seg, ®, ctxt)) != 0 ) 58.63 return rc; 58.64 58.65 @@ -797,6 +797,148 @@ load_seg( 58.66 return ops->write_segment(seg, ®, ctxt); 58.67 } 58.68 58.69 +static int 58.70 +protmode_load_seg( 58.71 + enum x86_segment seg, 58.72 + uint16_t sel, 58.73 + struct x86_emulate_ctxt *ctxt, 58.74 + struct x86_emulate_ops *ops) 58.75 +{ 58.76 + struct segment_register desctab, cs, segr; 58.77 + struct { uint32_t a, b; } desc; 58.78 + unsigned long val; 58.79 + uint8_t dpl, rpl, cpl; 58.80 + int rc, fault_type = EXC_TS; 58.81 + 58.82 + /* NULL selector? */ 58.83 + if ( (sel & 0xfffc) == 0 ) 58.84 + { 58.85 + if ( (seg == x86_seg_cs) || (seg == x86_seg_ss) ) 58.86 + goto raise_exn; 58.87 + memset(&segr, 0, sizeof(segr)); 58.88 + return ops->write_segment(seg, &segr, ctxt); 58.89 + } 58.90 + 58.91 + /* LDT descriptor must be in the GDT. */ 58.92 + if ( (seg == x86_seg_ldtr) && (sel & 4) ) 58.93 + goto raise_exn; 58.94 + 58.95 + if ( (rc = ops->read_segment(x86_seg_cs, &cs, ctxt)) || 58.96 + (rc = ops->read_segment((sel & 4) ? x86_seg_ldtr : x86_seg_gdtr, 58.97 + &desctab, ctxt)) ) 58.98 + return rc; 58.99 + 58.100 + /* Check against descriptor table limit. */ 58.101 + if ( ((sel & 0xfff8) + 7) > desctab.limit ) 58.102 + goto raise_exn; 58.103 + 58.104 + do { 58.105 + if ( (rc = ops->read(x86_seg_none, desctab.base + (sel & 0xfff8), 58.106 + &val, 4, ctxt)) ) 58.107 + return rc; 58.108 + desc.a = val; 58.109 + if ( (rc = ops->read(x86_seg_none, desctab.base + (sel & 0xfff8) + 4, 58.110 + &val, 4, ctxt)) ) 58.111 + return rc; 58.112 + desc.b = val; 58.113 + 58.114 + /* Segment present in memory? */ 58.115 + if ( !(desc.b & (1u<<15)) ) 58.116 + { 58.117 + fault_type = EXC_NP; 58.118 + goto raise_exn; 58.119 + } 58.120 + 58.121 + /* LDT descriptor is a system segment. All others are code/data. */ 58.122 + if ( (desc.b & (1u<<12)) == ((seg == x86_seg_ldtr) << 12) ) 58.123 + goto raise_exn; 58.124 + 58.125 + dpl = (desc.b >> 13) & 3; 58.126 + rpl = sel & 3; 58.127 + cpl = cs.sel & 3; 58.128 + 58.129 + switch ( seg ) 58.130 + { 58.131 + case x86_seg_cs: 58.132 + /* Code segment? */ 58.133 + if ( !(desc.b & (1u<<11)) ) 58.134 + goto raise_exn; 58.135 + /* Non-conforming segment: check DPL against RPL. */ 58.136 + if ( ((desc.b & (6u<<9)) != 6) && (dpl != rpl) ) 58.137 + goto raise_exn; 58.138 + break; 58.139 + case x86_seg_ss: 58.140 + /* Writable data segment? */ 58.141 + if ( (desc.b & (5u<<9)) != (1u<<9) ) 58.142 + goto raise_exn; 58.143 + if ( (dpl != cpl) || (dpl != rpl) ) 58.144 + goto raise_exn; 58.145 + break; 58.146 + case x86_seg_ldtr: 58.147 + /* LDT system segment? */ 58.148 + if ( (desc.b & (15u<<8)) != (2u<<8) ) 58.149 + goto raise_exn; 58.150 + goto skip_accessed_flag; 58.151 + default: 58.152 + /* Readable code or data segment? */ 58.153 + if ( (desc.b & (5u<<9)) == (4u<<9) ) 58.154 + goto raise_exn; 58.155 + /* Non-conforming segment: check DPL against RPL and CPL. */ 58.156 + if ( ((desc.b & (6u<<9)) != 6) && ((dpl < cpl) || (dpl < rpl)) ) 58.157 + goto raise_exn; 58.158 + break; 58.159 + } 58.160 + 58.161 + /* Ensure Accessed flag is set. */ 58.162 + rc = ((desc.b & 0x100) ? X86EMUL_OKAY : 58.163 + ops->cmpxchg( 58.164 + x86_seg_none, desctab.base + (sel & 0xfff8) + 4, desc.b, 58.165 + desc.b | 0x100, 4, ctxt)); 58.166 + } while ( rc == X86EMUL_CMPXCHG_FAILED ); 58.167 + 58.168 + if ( rc ) 58.169 + return rc; 58.170 + 58.171 + /* Force the Accessed flag in our local copy. */ 58.172 + desc.b |= 0x100; 58.173 + 58.174 + skip_accessed_flag: 58.175 + segr.base = (((desc.b << 0) & 0xff000000u) | 58.176 + ((desc.b << 16) & 0x00ff0000u) | 58.177 + ((desc.a >> 16) & 0x0000ffffu)); 58.178 + segr.attr.bytes = (((desc.b >> 8) & 0x00ffu) | 58.179 + ((desc.b >> 12) & 0x0f00u)); 58.180 + segr.limit = (desc.b & 0x000f0000u) | (desc.a & 0x0000ffffu); 58.181 + if ( segr.attr.fields.g ) 58.182 + segr.limit = (segr.limit << 12) | 0xfffu; 58.183 + segr.sel = sel; 58.184 + return ops->write_segment(seg, &segr, ctxt); 58.185 + 58.186 + raise_exn: 58.187 + if ( ops->inject_hw_exception == NULL ) 58.188 + return X86EMUL_UNHANDLEABLE; 58.189 + if ( (rc = ops->inject_hw_exception(fault_type, sel & 0xfffc, ctxt)) ) 58.190 + return rc; 58.191 + return X86EMUL_EXCEPTION; 58.192 +} 58.193 + 58.194 +static int 58.195 +load_seg( 58.196 + enum x86_segment seg, 58.197 + uint16_t sel, 58.198 + struct x86_emulate_ctxt *ctxt, 58.199 + struct x86_emulate_ops *ops) 58.200 +{ 58.201 + if ( (ops->read_segment == NULL) || 58.202 + (ops->write_segment == NULL) ) 58.203 + return X86EMUL_UNHANDLEABLE; 58.204 + 58.205 + if ( in_realmode(ctxt, ops) ) 58.206 + return realmode_load_seg(seg, sel, ctxt, ops); 58.207 + 58.208 + return protmode_load_seg(seg, sel, ctxt, ops); 58.209 +} 58.210 + 58.211 void * 58.212 decode_register( 58.213 uint8_t modrm_reg, struct cpu_user_regs *regs, int highbyte_regs) 58.214 @@ -1858,7 +2000,7 @@ x86_emulate( 58.215 if ( (_regs.eflags & EFLG_TF) && 58.216 (rc == X86EMUL_OKAY) && 58.217 (ops->inject_hw_exception != NULL) ) 58.218 - rc = ops->inject_hw_exception(EXC_DB, ctxt) ? : X86EMUL_EXCEPTION; 58.219 + rc = ops->inject_hw_exception(EXC_DB, 0, ctxt) ? : X86EMUL_EXCEPTION; 58.220 58.221 done: 58.222 return rc; 58.223 @@ -2226,7 +2368,7 @@ x86_emulate( 58.224 } 58.225 58.226 case 0x9e: /* sahf */ 58.227 - *(uint8_t *)_regs.eflags = (((uint8_t *)&_regs.eax)[1] & 0xd7) | 0x02; 58.228 + *(uint8_t *)&_regs.eflags = (((uint8_t *)&_regs.eax)[1] & 0xd7) | 0x02; 58.229 break; 58.230 58.231 case 0x9f: /* lahf */ 58.232 @@ -2644,9 +2786,11 @@ x86_emulate( 58.233 break; 58.234 } 58.235 58.236 - case 0xeb: /* jmp (short) */ 58.237 - jmp_rel(insn_fetch_type(int8_t)); 58.238 + case 0xeb: /* jmp (short) */ { 58.239 + int rel = insn_fetch_type(int8_t); 58.240 + jmp_rel(rel); 58.241 break; 58.242 + } 58.243 58.244 case 0xf1: /* int1 (icebp) */ 58.245 src.val = EXC_DB;
59.1 --- a/xen/include/asm-x86/hvm/vmx/cpu.h Thu Feb 07 09:23:26 2008 -0700 59.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 59.3 @@ -1,32 +0,0 @@ 59.4 -/* 59.5 - * cpu.h: Virtual CPU state 59.6 - * Copyright (c) 2004, Intel Corporation. 59.7 - * 59.8 - * This program is free software; you can redistribute it and/or modify it 59.9 - * under the terms and conditions of the GNU General Public License, 59.10 - * version 2, as published by the Free Software Foundation. 59.11 - * 59.12 - * This program is distributed in the hope it will be useful, but WITHOUT 59.13 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 59.14 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 59.15 - * more details. 59.16 - * 59.17 - * You should have received a copy of the GNU General Public License along with 59.18 - * this program; if not, write to the Free Software Foundation, Inc., 59 Temple 59.19 - * Place - Suite 330, Boston, MA 02111-1307 USA. 59.20 - * 59.21 - */ 59.22 -#ifndef __ASM_X86_HVM_VMX_CPU_H__ 59.23 -#define __ASM_X86_HVM_VMX_CPU_H__ 59.24 - 59.25 -#define NUM_CORES_RESET_MASK 0x00003FFF 59.26 -#define NUM_THREADS_RESET_MASK 0xFF00FFFF 59.27 - 59.28 -#define VMX_VCPU_CPUID_L1_ECX_RESERVED_18 0x00040000 59.29 -#define VMX_VCPU_CPUID_L1_ECX_RESERVED_6 0x00000040 59.30 - 59.31 -#define VMX_VCPU_CPUID_L1_ECX_RESERVED \ 59.32 - ( VMX_VCPU_CPUID_L1_ECX_RESERVED_18 | \ 59.33 - VMX_VCPU_CPUID_L1_ECX_RESERVED_6 ) 59.34 - 59.35 -#endif /* __ASM_X86_HVM_VMX_CPU_H__ */
60.1 --- a/xen/include/asm-x86/hvm/vmx/vmcs.h Thu Feb 07 09:23:26 2008 -0700 60.2 +++ b/xen/include/asm-x86/hvm/vmx/vmcs.h Thu Feb 07 11:08:49 2008 -0700 60.3 @@ -21,13 +21,8 @@ 60.4 60.5 #include <asm/config.h> 60.6 #include <asm/hvm/io.h> 60.7 -#include <asm/hvm/vmx/cpu.h> 60.8 #include <asm/hvm/vmx/vpmu.h> 60.9 60.10 -#ifdef VMXASSIST 60.11 -#include <public/hvm/vmx_assist.h> 60.12 -#endif 60.13 - 60.14 extern void start_vmx(void); 60.15 extern void vmcs_dump_vcpu(struct vcpu *v); 60.16 extern void setup_vmcs_dump(void); 60.17 @@ -94,15 +89,16 @@ struct arch_vmx_struct { 60.18 60.19 unsigned long host_cr0; 60.20 60.21 -#ifdef VMXASSIST 60.22 - unsigned long vmxassist_enabled:1; 60.23 - unsigned long irqbase_mode:1; 60.24 - unsigned char pm_irqbase[2]; 60.25 -#else 60.26 + /* Are we emulating rather than VMENTERing? */ 60.27 +#define VMXEMUL_REALMODE 1 /* Yes, because CR0.PE == 0 */ 60.28 +#define VMXEMUL_BAD_CS 2 /* Yes, because CS.RPL != CPL */ 60.29 +#define VMXEMUL_BAD_SS 4 /* Yes, because SS.RPL != CPL */ 60.30 + uint8_t vmxemul; 60.31 + 60.32 + /* I/O request in flight to device model. */ 60.33 bool_t real_mode_io_in_progress; 60.34 bool_t real_mode_io_completed; 60.35 unsigned long real_mode_io_data; 60.36 -#endif 60.37 }; 60.38 60.39 int vmx_create_vmcs(struct vcpu *v);
61.1 --- a/xen/include/asm-x86/x86_emulate.h Thu Feb 07 09:23:26 2008 -0700 61.2 +++ b/xen/include/asm-x86/x86_emulate.h Thu Feb 07 11:08:49 2008 -0700 61.3 @@ -39,9 +39,18 @@ enum x86_segment { 61.4 x86_seg_tr, 61.5 x86_seg_ldtr, 61.6 x86_seg_gdtr, 61.7 - x86_seg_idtr 61.8 + x86_seg_idtr, 61.9 + /* 61.10 + * Dummy: used to emulate direct processor accesses to management 61.11 + * structures (TSS, GDT, LDT, IDT, etc.) which use linear addressing 61.12 + * (no segment component) and bypass usual segment- and page-level 61.13 + * protection checks. 61.14 + */ 61.15 + x86_seg_none 61.16 }; 61.17 61.18 +#define is_x86_user_segment(seg) ((unsigned)(seg) <= x86_seg_gs) 61.19 + 61.20 /* 61.21 * Attribute for segment selector. This is a copy of bit 40:47 & 52:55 of the 61.22 * segment descriptor. It happens to match the format of an AMD SVM VMCB. 61.23 @@ -333,6 +342,7 @@ struct x86_emulate_ops 61.24 /* inject_hw_exception */ 61.25 int (*inject_hw_exception)( 61.26 uint8_t vector, 61.27 + uint16_t error_code, 61.28 struct x86_emulate_ctxt *ctxt); 61.29 61.30 /* inject_sw_interrupt */
62.1 --- a/xen/include/public/hvm/vmx_assist.h Thu Feb 07 09:23:26 2008 -0700 62.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 62.3 @@ -1,122 +0,0 @@ 62.4 -/* 62.5 - * vmx_assist.h: Context definitions for the VMXASSIST world switch. 62.6 - * 62.7 - * Permission is hereby granted, free of charge, to any person obtaining a copy 62.8 - * of this software and associated documentation files (the "Software"), to 62.9 - * deal in the Software without restriction, including without limitation the 62.10 - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 62.11 - * sell copies of the Software, and to permit persons to whom the Software is 62.12 - * furnished to do so, subject to the following conditions: 62.13 - * 62.14 - * The above copyright notice and this permission notice shall be included in 62.15 - * all copies or substantial portions of the Software. 62.16 - * 62.17 - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 62.18 - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 62.19 - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 62.20 - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 62.21 - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 62.22 - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 62.23 - * DEALINGS IN THE SOFTWARE. 62.24 - * 62.25 - * Leendert van Doorn, leendert@watson.ibm.com 62.26 - * Copyright (c) 2005, International Business Machines Corporation. 62.27 - */ 62.28 - 62.29 -#ifndef _VMX_ASSIST_H_ 62.30 -#define _VMX_ASSIST_H_ 62.31 - 62.32 -#define VMXASSIST_BASE 0xD0000 62.33 -#define VMXASSIST_MAGIC 0x17101966 62.34 -#define VMXASSIST_MAGIC_OFFSET (VMXASSIST_BASE+8) 62.35 - 62.36 -#define VMXASSIST_NEW_CONTEXT (VMXASSIST_BASE + 12) 62.37 -#define VMXASSIST_OLD_CONTEXT (VMXASSIST_NEW_CONTEXT + 4) 62.38 - 62.39 -#ifndef __ASSEMBLY__ 62.40 - 62.41 -#define NR_EXCEPTION_HANDLER 32 62.42 -#define NR_INTERRUPT_HANDLERS 16 62.43 -#define NR_TRAPS (NR_EXCEPTION_HANDLER+NR_INTERRUPT_HANDLERS) 62.44 - 62.45 -union vmcs_arbytes { 62.46 - struct arbyte_fields { 62.47 - unsigned int seg_type : 4, 62.48 - s : 1, 62.49 - dpl : 2, 62.50 - p : 1, 62.51 - reserved0 : 4, 62.52 - avl : 1, 62.53 - reserved1 : 1, 62.54 - default_ops_size: 1, 62.55 - g : 1, 62.56 - null_bit : 1, 62.57 - reserved2 : 15; 62.58 - } fields; 62.59 - unsigned int bytes; 62.60 -}; 62.61 - 62.62 -/* 62.63 - * World switch state 62.64 - */ 62.65 -struct vmx_assist_context { 62.66 - uint32_t eip; /* execution pointer */ 62.67 - uint32_t esp; /* stack pointer */ 62.68 - uint32_t eflags; /* flags register */ 62.69 - uint32_t cr0; 62.70 - uint32_t cr3; /* page table directory */ 62.71 - uint32_t cr4; 62.72 - uint32_t idtr_limit; /* idt */ 62.73 - uint32_t idtr_base; 62.74 - uint32_t gdtr_limit; /* gdt */ 62.75 - uint32_t gdtr_base; 62.76 - uint32_t cs_sel; /* cs selector */ 62.77 - uint32_t cs_limit; 62.78 - uint32_t cs_base; 62.79 - union vmcs_arbytes cs_arbytes; 62.80 - uint32_t ds_sel; /* ds selector */ 62.81 - uint32_t ds_limit; 62.82 - uint32_t ds_base; 62.83 - union vmcs_arbytes ds_arbytes; 62.84 - uint32_t es_sel; /* es selector */ 62.85 - uint32_t es_limit; 62.86 - uint32_t es_base; 62.87 - union vmcs_arbytes es_arbytes; 62.88 - uint32_t ss_sel; /* ss selector */ 62.89 - uint32_t ss_limit; 62.90 - uint32_t ss_base; 62.91 - union vmcs_arbytes ss_arbytes; 62.92 - uint32_t fs_sel; /* fs selector */ 62.93 - uint32_t fs_limit; 62.94 - uint32_t fs_base; 62.95 - union vmcs_arbytes fs_arbytes; 62.96 - uint32_t gs_sel; /* gs selector */ 62.97 - uint32_t gs_limit; 62.98 - uint32_t gs_base; 62.99 - union vmcs_arbytes gs_arbytes; 62.100 - uint32_t tr_sel; /* task selector */ 62.101 - uint32_t tr_limit; 62.102 - uint32_t tr_base; 62.103 - union vmcs_arbytes tr_arbytes; 62.104 - uint32_t ldtr_sel; /* ldtr selector */ 62.105 - uint32_t ldtr_limit; 62.106 - uint32_t ldtr_base; 62.107 - union vmcs_arbytes ldtr_arbytes; 62.108 - 62.109 - unsigned char rm_irqbase[2]; 62.110 -}; 62.111 -typedef struct vmx_assist_context vmx_assist_context_t; 62.112 - 62.113 -#endif /* __ASSEMBLY__ */ 62.114 - 62.115 -#endif /* _VMX_ASSIST_H_ */ 62.116 - 62.117 -/* 62.118 - * Local variables: 62.119 - * mode: C 62.120 - * c-set-style: "BSD" 62.121 - * c-basic-offset: 4 62.122 - * tab-width: 4 62.123 - * indent-tabs-mode: nil 62.124 - * End: 62.125 - */