diff options
author | Keir Fraser <keir.fraser@citrix.com> | 2008-12-09 16:28:02 +0000 |
---|---|---|
committer | Keir Fraser <keir.fraser@citrix.com> | 2008-12-09 16:28:02 +0000 |
commit | 8d4638d15e10d2d52547195dd6b57402b5382cce (patch) | |
tree | 768819983f8a3eebd83b897bf28835ea0540f84b /tools | |
parent | dbc75f4a5b8300ed2ef4bd2005b986953ddaf9b3 (diff) | |
download | xen-8d4638d15e10d2d52547195dd6b57402b5382cce.tar.gz xen-8d4638d15e10d2d52547195dd6b57402b5382cce.tar.bz2 xen-8d4638d15e10d2d52547195dd6b57402b5382cce.zip |
Use virtual 8086 mode for VMX guests with CR0.PE == 0
When a VMX guest tries to enter real mode, put it in virtual 8086 mode
instead, if that's possible. Handle all errors and corner cases by
falling back to the real-mode emulator.
This is similar to the old VMXASSIST system except it uses Xen's
x86_emulate emulator instead of having a partial emulator in the guest
firmware. It more than doubles the speed of real-mode operation on
VMX.
Signed-off-by: Tim Deegan <Tim.Deegan@citrix.com>
Diffstat (limited to 'tools')
-rw-r--r-- | tools/firmware/hvmloader/hvmloader.c | 19 | ||||
-rw-r--r-- | tools/libxc/xc_domain_restore.c | 16 | ||||
-rw-r--r-- | tools/libxc/xc_domain_save.c | 22 |
3 files changed, 52 insertions, 5 deletions
diff --git a/tools/firmware/hvmloader/hvmloader.c b/tools/firmware/hvmloader/hvmloader.c index ec066cbf68..bff548f9f2 100644 --- a/tools/firmware/hvmloader/hvmloader.c +++ b/tools/firmware/hvmloader/hvmloader.c @@ -536,6 +536,23 @@ static uint16_t init_xen_platform_io_base(void) return bios_info->xen_pfiob; } +/* Set up an empty TSS area for virtual 8086 mode to use. + * The only important thing is that it musn't have any bits set + * in the interrupt redirection bitmap, so all zeros will do. */ +static void init_vm86_tss(void) +{ + uint32_t tss; + struct xen_hvm_param p; + + tss = e820_malloc(128, 128); + memset((char *)tss, 0, 128); + p.domid = DOMID_SELF; + p.index = HVM_PARAM_VM86_TSS; + p.value = tss; + hypercall_hvm_op(HVMOP_set_param, &p); + printf("vm86 TSS at %08x\n", tss); +} + int main(void) { int option_rom_sz = 0, vgabios_sz = 0, etherboot_sz = 0; @@ -606,6 +623,8 @@ int main(void) acpi_build_tables(); } + init_vm86_tss(); + cmos_write_memory_size(); printf("BIOS map:\n"); diff --git a/tools/libxc/xc_domain_restore.c b/tools/libxc/xc_domain_restore.c index 1916728495..4f92ebb549 100644 --- a/tools/libxc/xc_domain_restore.c +++ b/tools/libxc/xc_domain_restore.c @@ -490,6 +490,22 @@ int xc_domain_restore(int xc_handle, int io_fd, uint32_t dom, continue; } + if ( j == -4 ) + { + uint64_t vm86_tss; + + /* Skip padding 4 bytes then read the vm86 TSS location. */ + if ( read_exact(io_fd, &vm86_tss, sizeof(uint32_t)) || + read_exact(io_fd, &vm86_tss, sizeof(uint64_t)) ) + { + ERROR("error read the address of the vm86 TSS"); + goto out; + } + + xc_set_hvm_param(xc_handle, dom, HVM_PARAM_VM86_TSS, vm86_tss); + continue; + } + if ( j == 0 ) break; /* our work here is done */ diff --git a/tools/libxc/xc_domain_save.c b/tools/libxc/xc_domain_save.c index a910414988..efd581966c 100644 --- a/tools/libxc/xc_domain_save.c +++ b/tools/libxc/xc_domain_save.c @@ -1388,20 +1388,32 @@ int xc_domain_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, if ( hvm ) { struct { - int minusthree; + int id; uint32_t pad; - uint64_t ident_pt; - } chunk = { -3, 0 }; + uint64_t data; + } chunk = { 0, }; + chunk.id = -3; xc_get_hvm_param(xc_handle, dom, HVM_PARAM_IDENT_PT, - (unsigned long *)&chunk.ident_pt); + (unsigned long *)&chunk.data); - if ( (chunk.ident_pt != 0) && + if ( (chunk.data != 0) && write_exact(io_fd, &chunk, sizeof(chunk)) ) { PERROR("Error when writing the ident_pt for EPT guest"); goto out; } + + chunk.id = -4; + xc_get_hvm_param(xc_handle, dom, HVM_PARAM_VM86_TSS, + (unsigned long *)&chunk.data); + + if ( (chunk.data != 0) && + write_exact(io_fd, &chunk, sizeof(chunk)) ) + { + PERROR("Error when writing the vm86 TSS for guest"); + goto out; + } } /* Zero terminate */ |