Big merge the HVM full-virtualisation abstractions.

This changeset contains all differences between
xen-unstable.hg and xen-unstable-hvm.hg.

All information and comments for changesets unique to
xen-unstable-hvm.hg are included below.

Signed-off-by: Leendert van Doorn <leendert@watson.ibm.com>
Signed-off-by: Keir Fraser <keir@xensource.com>

> user:        leendert@eserver2.watson.ibm.com
> date:        Tue Jan 31 04:29:51 2006 -0400
> files:       xen/include/asm-ia64/mm.h
> description:
> Fix ia64 compile.
> 
> Signed-off-by: Leendert van Doorn <leendert@watson.ibm.com>
> 
> 
> user:        leendert@eserver2.watson.ibm.com
> date:        Tue Jan 31 02:21:49 2006 -0400
> files:       xen/include/xen/domain_page.h
> description:
> Eliminate unused fields (pfn,va) warnings.
> 
> Signed-Off-By: Leendert van Doorn <leendert@watson.ibm.com>
> 
> 
> user:        leendert@eserver2.watson.ibm.com
> date:        Fri Jan 27 04:31:44 2006 -0400
> files:       tools/python/xen/xend/image.py
> description:
> Name cleanup. vmx refers to VT-x specific code, HVM is used for all others.
> 
> Signed-off-by: Leendert van Doorn <leendert@watson.ibm.com>
> 
> 
> user:        root@xen-trw1.amd.com
> date:        Sun Jan 22 18:39:58 2006 -0500
> files:       xen/arch/x86/hvm/platform.c
> description:
> support prefix 0x67 in hvm decode logic, gfxboot patch causes 0x67 prefix.
> 
> 
> user:        twoller@xen-trw1.amd.com
> date:        Sun Jan 22 18:35:59 2006 -0500
> files:       xen/arch/x86/hvm/svm/svm.c xen/arch/x86/hvm/svm/vmcb.c xen/include/asm-x86/hvm/svm/svm.h
> description:
> check for valid shared_page_va/vmcb before deallocating in SVM.
> 
> 
> user:        leendert@eserver2.watson.ibm.com
> date:        Sun Jan 22 02:56:20 2006 -0400
> files:       xen/include/asm-x86/hvm/svm/svm.h xen/include/asm-x86/hvm/svm/vmmcall.h
> description:
> Some SVM header file cleanups.
> 
> Signed-off-by: Leendert van Doorn <leendert@watson.ibm.com>
> 
> 
> user:        leendert@eserver2.watson.ibm.com
> date:        Fri Jan 20 11:50:23 2006 -0400
> files:       xen/arch/x86/domain.c
> description:
> Need to be more diligent about when to call into the HVM abstraction layer
> and when not.
> 
> Signed-Off-By: Leendert van Doorn <leendert@watson.ibm.com>
> 
> 
> user:        leendert@eserver2.watson.ibm.com
> date:        Wed Jan 18 15:14:56 2006 -0400
> files:       xen/arch/x86/hvm/svm/svm.c xen/arch/x86/hvm/svm/x86_32/exits.S xen/arch/x86/hvm/svm/x86_64/exits.S xen/arch/x86/hvm/vmx/x86_32/exits.S xen/arch/x86/hvm/vmx/x86_64/exits.S
> description:
> Added missing copyright statements and updated svm.c's copyright to properly
> reflect that it was derived from vmx.c.
> 
> Signed-Off-By: Leendert van Doorn <leendert@watson.ibm.com>
> 
> 
> user:        leendert@eserver2.watson.ibm.com
> date:        Tue Jan 17 09:42:11 2006 -0400
> files:       xen/arch/ia64/Makefile xen/arch/ia64/vmx/vlsapic.c xen/arch/ia64/vmx/vmx_init.c xen/include/asm-ia64/vmx_platform.h
> description:
> Make sure ia64 builds again with the new directory structure.
> 
> Signed-off-by: Leendert van Doorn <leendert@watson.ibm.com>
> 
> 
> user:        leendert@localhost.localdomain
> date:        Tue Jan 17 08:28:51 2006 -0400
> files:       xen/arch/x86/Makefile xen/arch/x86/hvm/i8259.c xen/arch/x86/hvm/vioapic.c
> description:
> The device models now belong in hvm.
> 
> Signed-ff-by: Leendert van Doorn <leendert@watson.ibm.com>
> 
> 
> user:        leendert@eserver2.watson.ibm.com
> date:        Sun Jan 15 16:40:58 2006 -0400
> files:       xen/arch/x86/Makefile xen/arch/x86/cpu/amd.c xen/arch/x86/cpu/intel.c xen/arch/x86/dm/hvm_vioapic.c xen/arch/x86/dm/i8259.c xen/arch/x86/dom0_ops.c xen/arch/x86/domain.c xen/arch/x86/hvm/hvm.c xen/arch/x86/hvm/intercept.c xen/arch/x86/hvm/io.c xen/arch/x86/hvm/platform.c xen/arch/x86/hvm/svm/emulate.c xen/arch/x86/hvm/svm/instrlen.c xen/arch/x86/hvm/svm/intr.c xen/arch/x86/hvm/svm/svm.c xen/arch/x86/hvm/svm/vmcb.c xen/arch/x86/hvm/svm/x86_32/exits.S xen/arch/x86/hvm/svm/x86_64/exits.S xen/arch/x86/hvm/vlapic.c xen/arch/x86/hvm/vmx/io.c xen/arch/x86/hvm/vmx/vmcs.c xen/arch/x86/hvm/vmx/vmx.c xen/arch/x86/hvm/vmx/x86_32/exits.S xen/arch/x86/hvm/vmx/x86_64/exits.S xen/arch/x86/i387.c xen/arch/x86/x86_32/entry.S xen/arch/x86/x86_32/traps.c xen/arch/x86/x86_64/entry.S xen/arch/x86/x86_64/traps.c xen/include/asm-x86/domain.h xen/include/asm-x86/hvm/domain.h xen/include/asm-x86/hvm/hvm.h xen/include/asm-x86/hvm/io.h xen/include/asm-x86/hvm/support.h xen/include/asm-x86/hvm/svm/emulate.h xen/include/asm-x86/hvm/svm/intr.h xen/include/asm-x86/hvm/svm/svm.h xen/include/asm-x86/hvm/svm/vmcb.h xen/include/asm-x86/hvm/svm/vmmcall.h xen/include/asm-x86/hvm/vcpu.h xen/include/asm-x86/hvm/vioapic.h xen/include/asm-x86/hvm/vlapic.h xen/include/asm-x86/hvm/vmx/cpu.h xen/include/asm-x86/hvm/vmx/vmcs.h xen/include/asm-x86/hvm/vmx/vmx.h xen/include/asm-x86/hvm/vpic.h xen/include/asm-x86/hvm/vpit.h xen/include/asm-x86/shadow.h
> description:
> As suggested by Keir, I restructured the hvm/vmx/svm tree. The new
> directory structure looks like:
> 
> 	xen/arch/hvm/
> 	xen/arch/hvm/vmx
> 	xen/arch/hvm/vmx/x86_32
> 	xen/arch/hvm/vmx/x86_64
> 	xen/arch/hvm/svm
> 	xen/arch/hvm/svm/x86_32
> 	xen/arch/hvm/svm/x86_64
> 
> 	xen/include/hvm/
> 	xen/include/hvm/vmx
> 	xen/include/hvm/svm
> 
> Many files have been renamed and had their hvm_/vmx_/svm_ suffix removed
> because this is now clear from the directory where the file resides.
> 
> Signed-off-by: Leendert van Doorn <leendert@watson.ibm.com>
> 
> 
> user:        leendert@eserver2.watson.ibm.com
> date:        Sat Jan 14 17:03:28 2006 -0400
> files:       xen/arch/ia64/vmx/vlsapic.c xen/include/asm-ia64/vmx_platform.h
> description:
> Name change fix for ia64.
> 
> Signed-off-by: Leendert van Doorn <leendert@watson.ibm.com>
> 
> 
> user:        leendert@eserver2.watson.ibm.com
> date:        Sat Jan 14 15:12:59 2006 -0400
> files:       xen/arch/x86/dm/hvm_vioapic.c xen/arch/x86/dm/i8259.c xen/arch/x86/hvm.c xen/arch/x86/hvm_intercept.c xen/arch/x86/svm.c xen/arch/x86/svm_intr.c xen/arch/x86/svm_vmcb.c xen/arch/x86/vmx.c xen/arch/x86/vmx_io.c xen/arch/x86/vmx_vmcs.c xen/include/asm-x86/hvm_domain.h xen/include/asm-x86/hvm_vcpu.h
> description:
> Move VMX/SVM print buffer to hvm_domain.
> 
> Cleanup variable names. The suffix hvm_ is redundant in hvm_domain.
> 
> Signed-off-by: Leendert van Doorn <leendert@watson.ibm.com>
> 
> 
> user:        twoller@xen-trw1.site
> date:        Fri Jan 13 17:03:18 2006 -0500
> files:       xen/arch/x86/svm.c
> description:
> remove unnecessary spin_unlock in asid_fetch code for svm.
> 
> 
> user:        twoller@xen-trw1.site
> date:        Wed Jan 11 20:00:36 2006 -0500
> files:       xen/arch/x86/svm.c
> description:
> remove unneeded update_pagetables() during svm PF handling (resolved with ASID code rework).
> 
> 
> user:        leendert@eserver2.watson.ibm.com
> date:        Tue Jan 10 02:45:32 2006 -0400
> files:       xen/arch/x86/hvm.c xen/arch/x86/vmx_io.c
> description:
> Factor out cpu_get_interrupt(). It is used by VMX and SVM.
> 
> Signed-Off-By: Leendert van Doorn <leendert@watson.ibm.com>
> 
> 
> user:        leendert@eserver2.watson.ibm.com
> date:        Mon Jan  9 00:03:30 2006 -0400
> files:       xen/arch/x86/hvm.c xen/arch/x86/svm.c xen/arch/x86/vmx.c xen/include/asm-x86/hvm_support.h xen/include/asm-x86/hvm_vcpu.h
> description:
> Introduce small print buffer per domain rather than a single global one.
> 
> Signed-off-by: Leendert van Doorn <leendert@watson.ibm.com>
> 
> 
> user:        leendert@eserver2.watson.ibm.com
> date:        Sun Jan  8 23:07:12 2006 -0400
> files:       xen/arch/x86/dom0_ops.c xen/include/asm-x86/hvm_support.h xen/include/public/arch-x86_32.h xen/include/public/arch-x86_64.h
> description:
> More cleanup. There is no point in distinguishing between SVM and VMX,
> a single HVM flag bit suffices.
> 
> Signed-Off-By: Leendert van Doorn <leendert@watson.ibm.com>
> 
> 
> user:        leendert@eserver2.watson.ibm.com
> date:        Sun Jan  8 12:05:59 2006 -0400
> files:       xen/arch/x86/svm.c xen/arch/x86/vmx.c
> description:
> Both VMX & SVM now print writes to the debug port (0xE9) on the console.
> 
> Signed-off-by: Leendert van Doorn <leendert@watson.ibm.com>
> 
> 
> user:        leendert@eserver2.watson.ibm.com
> date:        Sat Jan  7 13:55:27 2006 -0400
> files:       xen/arch/x86/svm.c xen/arch/x86/svm_intr.c xen/arch/x86/svm_vmcb.c xen/arch/x86/vmx.c xen/arch/x86/vmx_io.c xen/arch/x86/vmx_vmcs.c xen/arch/x86/x86_32/asm-offsets.c xen/arch/x86/x86_64/asm-offsets.c xen/include/asm-x86/domain.h xen/include/asm-x86/vmx.h
> description:
> Introduce shorthands to improve code legibility.
> 
> Signed-Off-By: Leendert van Doorn <leendert@watson.ibm.com>
> 
> 
> user:        leendert@eserver2.watson.ibm.com
> date:        Wed Jan  4 06:12:10 2006 -0400
> files:       tools/examples/xmexample.hvm
> description:
> Minor spelling mistakes.
> 
> Signed-off-by: Leendert van Doorn <leendert@watson.ibm.com>
> 
> 
> user:        leendert@eserver2.watson.ibm.com
> date:        Wed Jan  4 03:37:55 2006 -0400
> files:       xen/include/public/hvm/hvm_info_table.h xen/include/public/hvm/ioreq.h xen/include/public/hvm/vmx_assist.h
> description:
> Missed adding new files.
> 
> Signed-off-by: Leendert van Doorn <leendert@watson.ibm.com>
> 
> 
> user:        leendert@eserver2.watson.ibm.com
> date:        Mon Jan  2 01:23:54 2006 -0400
> files:       tools/debugger/libxendebug/xendebug.c tools/libxc/xc_hvm_build.c
> description:
> Finalize Xin Li's patch: vmx/svm_identify is no longer necessary.
> Xen debug should test for HVM instead of VMX.
> 
> Signed-off-by: Leendert van Doorn <leendert@watson.ibm.com>
> 
> 
> user:        twoller@xen-trw1.site
> date:        Sun Jan  1 03:22:39 2006 -0500
> files:       tools/ioemu/vl.c
> description:
> change hardcoded VTXEN to HVMXEN.
> 
> 
> user:        leendert@eserver2.watson.ibm.com
> date:        Sun Jan  1 02:22:47 2006 -0400
> files:       tools/libxc/xc_hvm_build.c tools/python/xen/xend/image.py xen/arch/x86/domain.c
> description:
> Avoid xen crash if there is no VMX support. If a platform
> doesn't support VMX, creating VMX domain will crash xen
> HV.
> 
> Signed-off-by: Xin Li <xin.b.li@intel.com>
> Signed-off-by: Leendert van Doorn <leendert@watson.ibm.com>
> [ vmx/svm_identify are still needed in hvm builder, but this may not
> really be necessary. I need to check this. - lvd ]
> 
> 
> user:        twoller@xen-trw1.site
> date:        Fri Dec 30 21:38:56 2005 -0500
> files:       xen/arch/x86/svm.c xen/arch/x86/svm_vmcb.c xen/arch/x86/x86_32/entry.S xen/include/asm-x86/svm.h xen/include/asm-x86/svm_vmcb.h
> description:
> add multi-core support for guest ASIDs for SVM partitions.
> 
> 
> user:        leendert@eserver2.watson.ibm.com
> date:        Sun Dec 25 20:44:43 2005 -0400
> files:       tools/firmware/vmxassist/head.S
> description:
> Make sure vmxassist still works in its debug environment.
> 
> Signed-Off-By: Leendert van Doorn <leendert@watson.ibm.com>
> 
> 
> user:        leendert@eserver2.watson.ibm.com
> date:        Fri Dec 23 18:27:57 2005 -0400
> files:       tools/libxc/xc_ia64_stubs.c
> description:
> Fixed libxc ia64, xend uses xc_hvm_build instead of xc_vmx_build.
> 
> Signed-off-by: Leendert van Doorn <leendert@watson.ibm.com>
> 
> 
> user:        twoller@xen-trw1.site
> date:        Wed Dec 21 21:39:17 2005 -0500
> files:       xen/arch/x86/svm_intr.c xen/arch/x86/svm_vmcb.c
> description:
> cleanup of svm specific code.
> 
> 
> user:        leendert@eserver2.watson.ibm.com
> date:        Wed Dec 21 17:18:25 2005 -0400
> files:       tools/python/xen/xm/tests/test_create.py tools/xm-test/README
> description:
> Minor name cleanups. xm-test isn't VMX specific. Instead use HVM.
> 
> 
> user:        twoller@xen-trw1.site
> date:        Tue Dec 20 20:01:38 2005 -0500
> files:       xen/arch/x86/svm_vmcb.c
> description:
> reword comments.
> 
> 
> user:        twoller@xen-trw1.site
> date:        Tue Dec 20 20:01:07 2005 -0500
> files:       xen/arch/x86/svm_intr.c
> description:
> add additional VLAPIC delivery modes.
> 
> 
> user:        twoller@xen-trw1.site
> date:        Tue Dec 20 20:00:22 2005 -0500
> files:       xen/arch/x86/svm.c
> description:
> reformat misaligned code.
> 
> 
> user:        twoller@xen-trw1.site
> date:        Tue Dec 20 19:59:37 2005 -0500
> files:       xen/arch/x86/svm.c
> description:
> Add additional AMD SVM specific CPUID logic.
> 
> 
> user:        leendert@eserver2.watson.ibm.com
> date:        Thu Dec 15 03:06:15 2005 -0400
> files:       tools/xm-test/tests/block-create/01_block_attach_device_pos.py tools/xm-test/tests/block-create/02_block_attach_file_device_pos.py tools/xm-test/tests/block-create/04_block_attach_device_repeatedly_pos.py tools/xm-test/tests/block-create/05_block_attach_and_dettach_device_repeatedly_pos.py tools/xm-test/tests/block-create/06_block_attach_baddomain_neg.py tools/xm-test/tests/block-create/07_block_attach_baddevice_neg.py tools/xm-test/tests/block-create/08_block_attach_bad_filedevice_neg.py tools/xm-test/tests/block-create/09_block_attach_and_dettach_device_check_data_pos.py tools/xm-test/tests/block-create/10_block_attach_dettach_multiple_devices.py tools/xm-test/tests/block-create/11_block_attach_shared_dom0.py tools/xm-test/tests/block-create/12_block_attach_shared_domU.py tools/xm-test/tests/block-destroy/01_block-destroy_btblock_pos.py tools/xm-test/tests/block-destroy/02_block-destroy_rtblock_pos.py tools/xm-test/tests/block-destroy/04_block-destroy_nonattached_neg.py tools/xm-test/tests/block-destroy/05_block-destroy_byname_pos.py tools/xm-test/tests/block-destroy/06_block-destroy_check_list_pos.py tools/xm-test/tests/block-list/01_block-list_pos.py tools/xm-test/tests/block-list/02_block-list_attachbd_pos.py tools/xm-test/tests/block-list/03_block-list_anotherbd_pos.py tools/xm-test/tests/block-list/04_block-list_nodb_pos.py tools/xm-test/tests/block-list/06_block-list_checkremove_pos.py tools/xm-test/tests/memmax/01_memmax_badparm_neg.py tools/xm-test/tests/memset/01_memset_basic_pos.py tools/xm-test/tests/memset/02_memset_badparm_neg.py tools/xm-test/tests/memset/03_memset_random_pos.py tools/xm-test/tests/memset/04_memset_smallmem_pos.py tools/xm-test/tests/migrate/01_migrate_localhost_pos.py tools/xm-test/tests/network-attach/01_network_attach_pos.py tools/xm-test/tests/network-attach/02_network_attach_detach_pos.py tools/xm-test/tests/network-attach/03_network_attach_detach_multiple_pos.py tools/xm-test/tests/restore/01_restore_basic_pos.py tools/xm-test/tests/restore/02_restore_badparm_neg.py tools/xm-test/tests/restore/03_restore_badfilename_neg.py tools/xm-test/tests/restore/04_restore_withdevices_pos.py tools/xm-test/tests/save/01_save_basic_pos.py tools/xm-test/tests/save/02_save_badparm_neg.py tools/xm-test/tests/save/03_save_bogusfile_neg.py tools/xm-test/tests/sysrq/01_sysrq_basic_neg.py tools/xm-test/tests/sysrq/02_sysrq_sync_pos.py tools/xm-test/tests/sysrq/03_sysrq_withreboot_pos.py
> description:
> Adding SKIP() to tests that aren't supported for VMX domains.
> 
> Signed-off-by: Dan Stekloff <dsteklof@us.ibm.com>
> Signed-off-by: Leendert van Doorn <leendert@watson.ibm.com>
> 
> 
> user:        leendert@eserver2.watson.ibm.com
> date:        Tue Dec 13 22:43:47 2005 -0400
> files:       xen/arch/x86/svm.c xen/arch/x86/vmx.c xen/arch/x86/vmx_io.c xen/include/asm-x86/hvm_vpit.h xen/include/asm-x86/msr.h
> description:
> Support VMX guest accesses to IA32_TIME_STAMP_COUNTER MSR.
> 
> Signed-off-by: Haifeng Xue <haifeng.xue@intel.com>
> Signed-off-by: Leendert van Doorn <leendert@us.ibm.com>
> 
> 
> user:        twoller@xen-trw1.site
> date:        Tue Dec 13 19:49:53 2005 -0500
> files:       xen/arch/x86/svm.c xen/arch/x86/svm_emulate.c xen/arch/x86/svm_instrlen.c xen/arch/x86/svm_intr.c xen/arch/x86/svm_vmcb.c xen/include/asm-x86/svm.h xen/include/asm-x86/svm_emulate.h xen/include/asm-x86/svm_intr.h xen/include/asm-x86/svm_vmcb.h xen/include/asm-x86/svm_vmmcall.h
> description:
> Add SVM base files to repository.
> 
> 
> user:        twoller@xen-trw1.site
> date:        Tue Dec 13 19:49:02 2005 -0500
> files:       xen/arch/x86/x86_32/entry.S xen/arch/x86/x86_64/entry.S
> description:
> Add SVM entry points for launch/resume.
> 
> 
> user:        twoller@xen-trw1.site
> date:        Tue Dec 13 19:47:38 2005 -0500
> files:       .hgignore
> description:
> Add hvmloader files to ignore list.
> 
> 
> user:        leendert@eserver2.watson.ibm.com
> date:        Mon Dec 12 22:58:54 2005 -0400
> files:       docs/src/user.tex tools/firmware/README xen/include/asm-x86/hvm.h
> description:
> Removed dirty words (by request).
> 
> 
> user:        leendert@eserver2.watson.ibm.com
> date:        Mon Dec 12 05:48:22 2005 -0400
> files:       tools/firmware/hvmloader/mkhex
> description:
> Fix file mode.
> 
> Signed-off-by: Leendert van Doorn <leendert@watson.ibm.com>
> 
> 
> user:        leendert@eserver2.watson.ibm.com
> date:        Mon Dec 12 04:50:42 2005 -0400
> files:       xen/Rules.mk xen/arch/x86/cpu/amd.c xen/arch/x86/cpu/intel.c xen/arch/x86/dm/hvm_vioapic.c xen/arch/x86/dm/i8259.c xen/arch/x86/dom0_ops.c xen/arch/x86/domain.c xen/arch/x86/hvm.c xen/arch/x86/hvm_intercept.c xen/arch/x86/hvm_io.c xen/arch/x86/hvm_platform.c xen/arch/x86/hvm_vlapic.c xen/arch/x86/mpparse.c xen/arch/x86/shadow.c xen/arch/x86/vmx.c xen/arch/x86/vmx_io.c xen/arch/x86/vmx_vmcs.c xen/arch/x86/x86_32/asm-offsets.c xen/arch/x86/x86_32/entry.S xen/arch/x86/x86_64/asm-offsets.c xen/arch/x86/x86_64/entry.S xen/arch/x86/x86_64/mm.c xen/include/asm-x86/config.h xen/include/asm-x86/cpufeature.h xen/include/asm-x86/domain.h xen/include/asm-x86/hvm_domain.h xen/include/asm-x86/hvm_io.h xen/include/asm-x86/hvm_support.h xen/include/asm-x86/hvm_vcpu.h xen/include/asm-x86/hvm_vioapic.h xen/include/asm-x86/hvm_vlapic.h xen/include/asm-x86/hvm_vpic.h xen/include/asm-x86/hvm_vpit.h xen/include/asm-x86/mpspec.h xen/include/asm-x86/msr.h xen/include/asm-x86/processor.h xen/include/asm-x86/vmx.h xen/include/asm-x86/vmx_cpu.h xen/include/asm-x86/vmx_vmcs.h
> description:
> Phase 3 of HVM integration: This patchset introduces the refactoring of
> virtualization architecture independent functions from specific ones.
> 
> 
> user:        leendert@eserver2.watson.ibm.com
> date:        Sun Dec 11 07:02:51 2005 -0400
> files:       xen/arch/x86/dom0_ops.c xen/arch/x86/domain.c xen/arch/x86/i387.c xen/arch/x86/shadow.c xen/arch/x86/vmx.c xen/arch/x86/x86_32/traps.c xen/arch/x86/x86_64/traps.c xen/include/asm-x86/hvm.h xen/include/asm-x86/hvm_support.h xen/include/asm-x86/regs.h xen/include/asm-x86/shadow.h xen/include/asm-x86/vmx_vmcs.h
> description:
> Phase 2 of HVM integration: This patchset introduces the hvm interface
> to the hypervisor and modifies all the non-vmx specific files to use it.
> 
> 
> user:        leendert@eserver2.watson.ibm.com
> date:        Sun Dec 11 01:10:00 2005 -0400
> files:       tools/examples/Makefile tools/examples/README tools/examples/xmexample.hvm tools/ioemu/exec-all.h tools/ioemu/hw/i8254.c tools/ioemu/hw/i8259.c tools/ioemu/monitor.c tools/ioemu/target-i386-dm/helper2.c tools/ioemu/vl.c tools/libxc/Makefile tools/libxc/xc_hvm_build.c tools/libxc/xc_ptrace.c tools/libxc/xc_ptrace_core.c tools/libxc/xenguest.h tools/python/xen/lowlevel/xc/xc.c tools/python/xen/xend/image.py tools/python/xen/xm/create.py tools/xm-test/configure.ac tools/xm-test/lib/XmTestLib/XenDomain.py tools/xm-test/lib/XmTestLib/config.py.in tools/xm-test/ramdisk/Makefile.am tools/xm-test/ramdisk/bin/create_disk_image tools/xm-test/tests/block-list/04_block-list_nodb_pos.py xen/include/public/arch-x86_32.h xen/include/public/arch-x86_64.h
> description:
> Phase 1 of HVM integration: This patchset updates the tools. Most of the
> tools are machine independent except for some detection code in the hvm
> domain builder.
This commit is contained in:
kaf24@firebug.cl.cam.ac.uk committed 2006-01-31 11:49:51 +01:00
1 parent bd0e34a173
commit d1bd157fbc
158 files changed
+8781 -2310

No files matched your search

+2
View File
@@ -108,6 +108,8 @@
^tools/firmware/.*\.sym$ ^tools/firmware/.*\.sym$
^tools/firmware/.*bios/.*bios.*\.txt$ ^tools/firmware/.*bios/.*bios.*\.txt$
^tools/firmware/acpi/acpigen$ ^tools/firmware/acpi/acpigen$
^tools/firmware/hvmloader/hvmloader$
^tools/firmware/hvmloader/roms\.h$
^tools/firmware/rombios/BIOS-bochs-latest$ ^tools/firmware/rombios/BIOS-bochs-latest$
^tools/firmware/rombios/_rombios_\.c$ ^tools/firmware/rombios/_rombios_\.c$
^tools/firmware/rombios/rombios\.s$ ^tools/firmware/rombios/rombios\.s$
+1 -1
View File
@@ -137,7 +137,7 @@ support Xen, a key feature is that user space applications and
libraries \emph{do not} require modification. libraries \emph{do not} require modification.
With hardware CPU virtualization as provided by Intel VT and AMD With hardware CPU virtualization as provided by Intel VT and AMD
Pacifica technology, the ability to run an unmodified guest OS kernel SVM technology, the ability to run an unmodified guest OS kernel
is available. No porting of the OS is required, although some is available. No porting of the OS is required, although some
additional driver support is necessary within Xen itself. Unlike additional driver support is necessary within Xen itself. Unlike
traditional full virtualization hypervisors, which suffer a tremendous traditional full virtualization hypervisors, which suffer a tremendous
+2 -2
View File
@@ -355,7 +355,7 @@ xendebug_memory_page (domain_context_p ctxt, int xc_handle, uint32_t vcpu,
if ( (pde = ctxt->cr3_virt[vcpu][vtopdi(va)]) == 0) /* logical address */ if ( (pde = ctxt->cr3_virt[vcpu][vtopdi(va)]) == 0) /* logical address */
return 0; return 0;
if (ctxt->context[vcpu].flags & VGCF_VMX_GUEST) if (ctxt->context[vcpu].flags & VGCF_HVM_GUEST)
pde = ctxt->page_array[pde >> PAGE_SHIFT] << PAGE_SHIFT; pde = ctxt->page_array[pde >> PAGE_SHIFT] << PAGE_SHIFT;
if (pde != ctxt->pde_phys[vcpu]) if (pde != ctxt->pde_phys[vcpu])
{ {
@@ -370,7 +370,7 @@ xendebug_memory_page (domain_context_p ctxt, int xc_handle, uint32_t vcpu,
if ((page = ctxt->pde_virt[vcpu][vtopti(va)]) == 0) /* logical address */ if ((page = ctxt->pde_virt[vcpu][vtopti(va)]) == 0) /* logical address */
return 0; return 0;
if (ctxt->context[vcpu].flags & VGCF_VMX_GUEST) if (ctxt->context[vcpu].flags & VGCF_HVM_GUEST)
page = ctxt->page_array[page >> PAGE_SHIFT] << PAGE_SHIFT; page = ctxt->page_array[page >> PAGE_SHIFT] << PAGE_SHIFT;
if (page != ctxt->page_phys[vcpu] || protection != ctxt->page_perm[vcpu]) if (page != ctxt->page_phys[vcpu] || protection != ctxt->page_perm[vcpu])
{ {
+1 -1
View File
@@ -16,7 +16,7 @@ XEN_CONFIG_DIR = /etc/xen
XEN_CONFIGS = xend-config.sxp XEN_CONFIGS = xend-config.sxp
XEN_CONFIGS += xmexample1 XEN_CONFIGS += xmexample1
XEN_CONFIGS += xmexample2 XEN_CONFIGS += xmexample2
XEN_CONFIGS += xmexample.vmx XEN_CONFIGS += xmexample.hvm
XEN_CONFIGS += xmexample.vti XEN_CONFIGS += xmexample.vti
# Xen script dir and scripts to go there. # Xen script dir and scripts to go there.
+1 -1
View File
@@ -32,6 +32,6 @@ xmexample2 - a more complex configuration script for 'xm create'
xmexample3 - an advanced configuration script for 'xm create' xmexample3 - an advanced configuration script for 'xm create'
that utilizes the vmid that utilizes the vmid
xmexample.nbd - configuration script that uses NBD filesystems xmexample.nbd - configuration script that uses NBD filesystems
xmexample.vmx - a configuration script for creating a vmx domain with xmexample.hvm - a configuration script for creating a hvm domain with
'xm create' 'xm create'
xmexample.vti - a configuration script for creating a domain on vti xmexample.vti - a configuration script for creating a domain on vti
@@ -15,25 +15,25 @@ else:
#---------------------------------------------------------------------------- #----------------------------------------------------------------------------
# Kernel image file. # Kernel image file.
kernel = "/usr/lib/xen/boot/vmxloader" kernel = "/usr/lib/xen/boot/hvmloader"
# The domain build function. VMX domain uses 'vmx'. # The domain build function. HVM domain uses 'hvm'.
builder='vmx' builder='hvm'
# Initial memory allocation (in megabytes) for the new domain. # Initial memory allocation (in megabytes) for the new domain.
memory = 128 memory = 128
# A name for your domain. All domains must have different names. # A name for your domain. All domains must have different names.
name = "ExampleVMXDomain" name = "ExampleHVMDomain"
#----------------------------------------------------------------------------- #-----------------------------------------------------------------------------
# the number of cpus guest platform has, default=1 # the number of cpus guest platform has, default=1
#vcpus=1 #vcpus=1
# enable/disalbe vmx guest ACPI, default=0 (disabled) # enable/disable HVM guest ACPI, default=0 (disabled)
#acpi=0 #acpi=0
# enable/disalbe vmx guest APIC, default=0 (disabled) # enable/disable HVM guest APIC, default=0 (disabled)
#apic=0 #apic=0
# List of which CPUS this domain is allowed to use, default Xen picks # List of which CPUS this domain is allowed to use, default Xen picks
@@ -46,8 +46,6 @@ name = "ExampleVMXDomain"
#vif = [ 'type=ioemu, mac=00:16:3e:00:00:11, bridge=xenbr0' ] #vif = [ 'type=ioemu, mac=00:16:3e:00:00:11, bridge=xenbr0' ]
# type=ioemu specify the NIC is an ioemu device not netfront # type=ioemu specify the NIC is an ioemu device not netfront
vif = [ 'type=ioemu, bridge=xenbr0' ] vif = [ 'type=ioemu, bridge=xenbr0' ]
# for multiple NICs in device model, 3 in this example
#vif = [ 'type=ioemu, bridge=xenbr0', 'type=ioemu', 'type=ioemu']
#---------------------------------------------------------------------------- #----------------------------------------------------------------------------
# Define the disk devices you want the domain to have access to, and # Define the disk devices you want the domain to have access to, and
+3 -2
View File
@@ -1,9 +1,9 @@
XEN_ROOT = ../.. XEN_ROOT = ../..
include $(XEN_ROOT)/tools/Rules.mk include $(XEN_ROOT)/tools/Rules.mk
# vmxloader is a 32-bit protected mode binary. # hvmloader is a 32-bit protected mode binary.
# It belongs in /usr/lib, not /usr/lib64. # It belongs in /usr/lib, not /usr/lib64.
TARGET := vmxassist/vmxloader TARGET := hvmloader/hvmloader
INSTALL_DIR := $(DESTDIR)/usr/lib/xen/boot INSTALL_DIR := $(DESTDIR)/usr/lib/xen/boot
SUBDIRS := SUBDIRS :=
@@ -11,6 +11,7 @@ SUBDIRS += rombios
SUBDIRS += vgabios SUBDIRS += vgabios
SUBDIRS += acpi SUBDIRS += acpi
SUBDIRS += vmxassist SUBDIRS += vmxassist
SUBDIRS += hvmloader
.PHONY: all install clean .PHONY: all install clean
+5 -5
View File
@@ -1,11 +1,11 @@
Domain FirmWare support Domain firmware support
----------------------- -----------------------
One of the key advantages of full virtualization hardware support (such One of the key advantages of full virtualization hardware support (such
as Intel's VT or AMD's Pacifica) is the ability to run unmodified guest as Intel's VT or AMD's SVM extensions) is the ability to run unmodified
operating systems. However, since most OSes rely on BIOS support during guest operating systems. However, since most OSes rely on BIOS support
their early bringup, we need to provide a surrogate ROMBIOS and VGABIOS during their early bringup, we need to provide a surrogate ROMBIOS and
firmware layer. VGABIOS firmware layer.
What's more, we need to support real-mode which is required by What's more, we need to support real-mode which is required by
the firmware and bootstrap loaders. Real-mode support is especially the firmware and bootstrap loaders. Real-mode support is especially
+56
View File
@@ -0,0 +1,56 @@
#
# Makefile
#
# Leendert van Doorn, leendert@watson.ibm.com
# Copyright (c) 2005, International Business Machines Corporation.
#
# This program is free software; you can redistribute it and/or modify it
# under the terms and conditions of the GNU General Public License,
# version 2, as published by the Free Software Foundation.
#
# This program is distributed in the hope it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
# more details.
#
# You should have received a copy of the GNU General Public License along with
# this program; if not, write to the Free Software Foundation, Inc., 59 Temple
# Place - Suite 330, Boston, MA 02111-1307 USA.
#
XEN_ROOT = ../../..
include $(XEN_ROOT)/tools/Rules.mk
# The HVM loader is started in 32-bit mode at the address below:
LOADADDR = 0x100000
DEFINES =-DDEBUG
XENINC =-I$(XEN_ROOT)/tools/libxc
OBJECTS = hvmloader.o acpi_madt.o
CC = gcc
OBJCOPY = objcopy
CFLAGS = $(DEFINES) -I. $(XENINC) -Wall -fno-builtin -O2 -msoft-float
CFLAGS += -m32 -march=i686
LDFLAGS = -m32 -nostdlib -Wl,-N -Wl,-Ttext -Wl,$(LOADADDR)
all: hvmloader
hvmloader: roms.h hvmloader.c acpi_madt.c
$(CC) $(CFLAGS) -c hvmloader.c acpi_madt.c
$(CC) $(LDFLAGS) -o hvmloader.tmp hvmloader.o acpi_madt.o
$(OBJCOPY) hvmloader.tmp hvmloader
rm -f hvmloader.tmp
roms.h: ../rombios/BIOS-bochs-latest ../vgabios/VGABIOS-lgpl-latest.bin ../vgabios/VGABIOS-lgpl-latest.cirrus.bin ../vmxassist/vmxassist.bin
./mkhex rombios ../rombios/BIOS-bochs-latest > roms.h
./mkhex vgabios_stdvga ../vgabios/VGABIOS-lgpl-latest.bin >> roms.h
./mkhex vgabios_cirrusvga ../vgabios/VGABIOS-lgpl-latest.cirrus.bin >> roms.h
./mkhex vmxassist ../vmxassist/vmxassist.bin >> roms.h
./mkhex acpi ../acpi/acpi.bin >> roms.h
clean:
rm -f roms.h acpi.h
rm -f hvmloader hvmloader.tmp hvmloader.o $(OBJECTS)
@@ -85,6 +85,7 @@ get_acpi_enabled(void)
return (t ? t->acpi_enabled : 0); /* default no acpi */ return (t ? t->acpi_enabled : 0); /* default no acpi */
} }
static void * static void *
acpi_madt_get_madt(unsigned char *acpi_start) acpi_madt_get_madt(unsigned char *acpi_start)
{ {
@@ -1,5 +1,5 @@
/* /*
* vmxloader.c: ROM/VMXAssist image loader. * hvmloader.c: HVM ROMBIOS/VGABIOS/ACPI/VMXAssist image loader.
* *
* A quicky so that we can boot rom images as if they were a Linux kernel. * A quicky so that we can boot rom images as if they were a Linux kernel.
* This code will copy the rom images (ROMBIOS/VGABIOS/VM86) into their * This code will copy the rom images (ROMBIOS/VGABIOS/VM86) into their
@@ -21,13 +21,16 @@
* this program; if not, write to the Free Software Foundation, Inc., 59 Temple * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
* Place - Suite 330, Boston, MA 02111-1307 USA. * Place - Suite 330, Boston, MA 02111-1307 USA.
*/ */
#include "machine.h"
#include "roms.h" #include "roms.h"
#include "../acpi/acpi2_0.h" /* for ACPI_PHYSICAL_ADDRESS */
#include "acpi.h" /* memory map */
#include "../acpi/acpi2_0.h" // for ACPI_PHYSICAL_ADDRESS #define VGABIOS_PHYSICAL_ADDRESS 0x000C0000
int acpi_madt_update(unsigned char* acpi_start); #define VMXASSIST_PHYSICAL_ADDRESS 0x000D0000
int get_acpi_enabled(void); #define ROMBIOS_PHYSICAL_ADDRESS 0x000F0000
/* invoke SVM's paged realmode support */
#define SVM_VMMCALL_RESET_TO_REALMODE 0x00000001
/* /*
* C runtime start off * C runtime start off
@@ -66,6 +69,30 @@ asm(
"stack_top: \n" "stack_top: \n"
); );
extern int get_acpi_enabled(void);
extern int acpi_madt_update(unsigned char* acpi_start);
static inline void
outw(unsigned short addr, unsigned short val)
{
__asm__ __volatile__ ("outw %%ax, %%dx" :: "d"(addr), "a"(val));
}
static inline void
outb(unsigned short addr, unsigned char val)
{
__asm__ __volatile__ ("outb %%al, %%dx" :: "d"(addr), "a"(val));
}
static inline unsigned char
inb(unsigned short addr)
{
unsigned char val;
__asm__ __volatile__ ("inb %w1,%0" : "=a" (val) : "Nd" (addr));
return val;
}
void * void *
memcpy(void *dest, const void *src, unsigned n) memcpy(void *dest, const void *src, unsigned n)
{ {
@@ -103,38 +130,82 @@ cirrus_check(void)
return inb(0x3C5) == 0x12; return inb(0x3C5) == 0x12;
} }
int
vmmcall(int edi, int esi, int edx, int ecx, int ebx)
{
int eax;
__asm__ __volatile__(
".byte 0x0F,0x01,0xD9"
: "=a" (eax)
: "a"(0x58454E00), /* XEN\0 key */
"b"(ebx), "c"(ecx), "d"(edx), "D"(edi), "S"(esi)
);
return eax;
}
int
check_amd(void)
{
char id[12];
__asm__ __volatile__(
"cpuid"
: "=b" (*(int *)(&id[0])),
"=c" (*(int *)(&id[8])),
"=d" (*(int *)(&id[4]))
: "a" (0)
);
return __builtin_memcmp(id, "AuthenticAMD", 12) == 0;
}
int int
main(void) main(void)
{ {
puts("VMXAssist Loader\n"); puts("HVM Loader\n");
puts("Loading ROMBIOS ...\n"); puts("Loading ROMBIOS ...\n");
memcpy((void *)0xF0000, rombios, sizeof(rombios)); memcpy((void *)ROMBIOS_PHYSICAL_ADDRESS, rombios, sizeof(rombios));
if (cirrus_check()) { if (cirrus_check()) {
puts("Loading Cirrus VGABIOS ...\n"); puts("Loading Cirrus VGABIOS ...\n");
memcpy((void *)0xC0000, memcpy((void *)VGABIOS_PHYSICAL_ADDRESS,
vgabios_cirrusvga, sizeof(vgabios_cirrusvga)); vgabios_cirrusvga, sizeof(vgabios_cirrusvga));
} else { } else {
puts("Loading Standard VGABIOS ...\n"); puts("Loading Standard VGABIOS ...\n");
memcpy((void *)0xC0000, memcpy((void *)VGABIOS_PHYSICAL_ADDRESS,
vgabios_stdvga, sizeof(vgabios_stdvga)); vgabios_stdvga, sizeof(vgabios_stdvga));
} }
if (get_acpi_enabled() != 0) { if (get_acpi_enabled() != 0) {
puts("Loading ACPI ...\n"); puts("Loading ACPI ...\n");
acpi_madt_update((unsigned char*)acpi); acpi_madt_update((unsigned char *) acpi);
if (ACPI_PHYSICAL_ADDRESS+sizeof(acpi) <= 0xF0000) { if (ACPI_PHYSICAL_ADDRESS+sizeof(acpi) <= 0xF0000) {
/* make sure acpi table does not overlap rombios /*
* Make sure acpi table does not overlap rombios
* currently acpi less than 8K will be OK. * currently acpi less than 8K will be OK.
*/ */
memcpy((void *)ACPI_PHYSICAL_ADDRESS, acpi, sizeof(acpi)); memcpy((void *)ACPI_PHYSICAL_ADDRESS, acpi,
sizeof(acpi));
} }
} }
puts("Loading VMXAssist ...\n"); if (check_amd()) {
memcpy((void *)TEXTADDR, vmxassist, sizeof(vmxassist)); /* AMD implies this is SVM */
puts("SVM go ...\n");
vmmcall(SVM_VMMCALL_RESET_TO_REALMODE, 0, 0, 0, 0);
} else {
puts("Loading VMXAssist ...\n");
memcpy((void *)VMXASSIST_PHYSICAL_ADDRESS,
vmxassist, sizeof(vmxassist));
puts("Go ...\n"); puts("VMX go ...\n");
asm volatile ( "jmp *%%eax" : : "a" (TEXTADDR), "d" (0) ); __asm__ __volatile__(
"jmp *%%eax"
: : "a" (VMXASSIST_PHYSICAL_ADDRESS), "d" (0)
);
}
puts("Failed to invoke ROMBIOS\n");
return 0; return 0;
} }
View File
File renamed without changes.
+12 -24
View File
@@ -26,8 +26,8 @@
// ROM BIOS for use with Bochs/Plex x86 emulation environment // ROM BIOS for use with Bochs/Plex x86 emulation environment
#define VMXASSIST #define HVMASSIST
#undef VMXTEST #undef HVMTEST
// Xen full virtualization does not handle unaligned IO with page crossing. // Xen full virtualization does not handle unaligned IO with page crossing.
// Disable 32-bit PIO as a workaround. // Disable 32-bit PIO as a workaround.
@@ -177,8 +177,8 @@
#define BASE_MEM_IN_K (640 - EBDA_SIZE) #define BASE_MEM_IN_K (640 - EBDA_SIZE)
// Define the application NAME // Define the application NAME
#ifdef VMXASSIST #ifdef HVMASSIST
# define BX_APPNAME "VMXAssist" # define BX_APPNAME "HVMAssist"
#elif PLEX86 #elif PLEX86
# define BX_APPNAME "Plex86" # define BX_APPNAME "Plex86"
#else #else
@@ -1430,7 +1430,7 @@ ASM_START
ASM_END ASM_END
} }
#ifdef VMXASSIST #ifdef HVMASSIST
void void
copy_e820_table() copy_e820_table()
{ {
@@ -1440,7 +1440,7 @@ copy_e820_table()
write_word(0xe000, 0x8, nr_entries); write_word(0xe000, 0x8, nr_entries);
memcpyb(0xe000, 0x10, 0x9000, 0x2d0, nr_entries * 0x14); memcpyb(0xe000, 0x10, 0x9000, 0x2d0, nr_entries * 0x14);
} }
#endif /* VMXASSIST */ #endif /* HVMASSIST */
#if BX_DEBUG_SERIAL #if BX_DEBUG_SERIAL
/* serial debug port*/ /* serial debug port*/
@@ -1520,7 +1520,7 @@ send(action, c)
if (c == '\n') uart_tx_byte(BX_DEBUG_PORT, '\r'); if (c == '\n') uart_tx_byte(BX_DEBUG_PORT, '\r');
uart_tx_byte(BX_DEBUG_PORT, c); uart_tx_byte(BX_DEBUG_PORT, c);
#endif #endif
#ifdef VMXASSIST #ifdef HVMASSIST
outb(0xE9, c); outb(0xE9, c);
#endif #endif
#if BX_VIRTUAL_PORTS #if BX_VIRTUAL_PORTS
@@ -4089,7 +4089,7 @@ ASM_END
case 0x20: // coded by osmaker aka K.J. case 0x20: // coded by osmaker aka K.J.
if(regs.u.r32.edx == 0x534D4150) /* SMAP */ if(regs.u.r32.edx == 0x534D4150) /* SMAP */
{ {
#ifdef VMXASSIST #ifdef HVMASSIST
if ((regs.u.r16.bx / 0x14) * 0x14 == regs.u.r16.bx) { if ((regs.u.r16.bx / 0x14) * 0x14 == regs.u.r16.bx) {
Bit16u e820_table_size = read_word(0xe000, 0x8) * 0x14; Bit16u e820_table_size = read_word(0xe000, 0x8) * 0x14;
@@ -9595,7 +9595,7 @@ post_default_ints:
;; int 1C already points at dummy_iret_handler (above) ;; int 1C already points at dummy_iret_handler (above)
mov al, #0x34 ; timer0: binary count, 16bit count, mode 2 mov al, #0x34 ; timer0: binary count, 16bit count, mode 2
out 0x43, al out 0x43, al
#ifdef VMXASSIST #ifdef HVMASSIST
mov al, #0x0b ; #0xe90b = 20 Hz (temporary, until we fix xen/vmx support) mov al, #0x0b ; #0xe90b = 20 Hz (temporary, until we fix xen/vmx support)
out 0x40, al ; lsb out 0x40, al ; lsb
mov al, #0xe9 mov al, #0xe9
@@ -9702,22 +9702,10 @@ post_default_ints:
mov al, #0x11 ; send initialisation commands mov al, #0x11 ; send initialisation commands
out 0x20, al out 0x20, al
out 0xa0, al out 0xa0, al
#ifdef VMXASSIST
;; The vm86 emulator expects interrupts to be mapped beyond the reserved
;; vectors (0 through 31). Since rombios fully controls the hardware, we
;; map it the way the emulator needs it and expect that it will do the
;; proper 8086 interrupt translation (that is, master pic base is at 0x8
;; and slave pic base is at 0x70).
mov al, #0x20
out 0x21, al
mov al, #0x28
out 0xa1, al
#else
mov al, #0x08 mov al, #0x08
out 0x21, al out 0x21, al
mov al, #0x70 mov al, #0x70
out 0xa1, al out 0xa1, al
#endif
mov al, #0x04 mov al, #0x04
out 0x21, al out 0x21, al
mov al, #0x02 mov al, #0x02
@@ -9734,7 +9722,7 @@ post_default_ints:
#endif #endif
out 0xa1, AL ;slave pic: unmask IRQ 12, 13, 14 out 0xa1, AL ;slave pic: unmask IRQ 12, 13, 14
#ifdef VMXASSIST #ifdef HVMASSIST
call _copy_e820_table call _copy_e820_table
#endif #endif
@@ -10368,13 +10356,13 @@ dummy_iret_handler:
HALT(__LINE__) HALT(__LINE__)
iret iret
#ifdef VMXTEST #ifdef HVMTEST
.org 0xffe0 .org 0xffe0
jmp 0xf000:post; jmp 0xf000:post;
#endif #endif
.org 0xfff0 ; Power-up Entry Point .org 0xfff0 ; Power-up Entry Point
#ifdef VMXTEST #ifdef HVMTEST
jmp 0xd000:0x0003; jmp 0xd000:0x0003;
#else #else
jmp 0xf000:post jmp 0xf000:post
-206
View File
@@ -1,206 +0,0 @@
--- /home/leendert/cvs/bochs/bios/rombios.c 2005-05-23 12:18:11.000000000 -0400
+++ rombios.c 2005-06-01 23:46:45.000000000 -0400
@@ -26,6 +26,7 @@
// ROM BIOS for use with Bochs/Plex x86 emulation environment
+#define VMXASSIST
// ROM BIOS compatability entry points:
// ===================================
@@ -170,7 +171,9 @@
#define BASE_MEM_IN_K (640 - EBDA_SIZE)
// Define the application NAME
-#ifdef PLEX86
+#ifdef VMXASSIST
+# define BX_APPNAME "VMXAssist"
+#elif PLEX86
# define BX_APPNAME "Plex86"
#else
# define BX_APPNAME "Bochs"
@@ -314,7 +317,6 @@
ASM_END
}
-#if 0
// memcpy of count bytes
void
memcpyb(dseg,doffset,sseg,soffset,count)
@@ -362,6 +364,7 @@
ASM_END
}
+#if 0
// memcpy of count dword
void
memcpyd(dseg,doffset,sseg,soffset,count)
@@ -858,6 +861,7 @@
static void write_byte();
static void write_word();
static void bios_printf();
+static void copy_e820_table();
static Bit8u inhibit_mouse_int_and_events();
static void enable_mouse_int_and_events();
@@ -1420,6 +1424,16 @@
ASM_END
}
+#ifdef VMXASSIST
+void
+copy_e820_table()
+{
+ Bit8u nr_entries = read_byte(0x9000, 0x1e8);
+ write_word(0xe000, 0x8, nr_entries);
+ memcpyb(0xe000, 0x10, 0x9000, 0x2d0, nr_entries * 0x14);
+}
+#endif /* VMXASSIST */
+
#if BX_DEBUG_SERIAL
/* serial debug port*/
#define BX_DEBUG_PORT 0x03f8
@@ -1498,6 +1512,9 @@
if (c == '\n') uart_tx_byte(BX_DEBUG_PORT, '\r');
uart_tx_byte(BX_DEBUG_PORT, c);
#endif
+#ifdef VMXASSIST
+ outb(0xE9, c);
+#endif
#if BX_VIRTUAL_PORTS
if (action & BIOS_PRINTF_DEBUG) outb(DEBUG_PORT, c);
if (action & BIOS_PRINTF_INFO) outb(INFO_PORT, c);
@@ -4053,6 +4070,66 @@
case 0x20: // coded by osmaker aka K.J.
if(regs.u.r32.edx == 0x534D4150)
{
+#ifdef VMXASSIST
+ if ((regs.u.r16.bx / 0x14)* 0x14 == regs.u.r16.bx) {
+ Bit16u e820_table_size = read_word(0xe000, 0x8) * 0x14;
+
+ if (regs.u.r16.bx + 0x14 <= e820_table_size) {
+ memcpyb(ES, regs.u.r16.di,
+ 0xe000, 0x10 + regs.u.r16.bx, 0x14);
+ }
+ regs.u.r32.ebx += 0x14;
+ if ((regs.u.r32.ebx + 0x14 - 1) > e820_table_size)
+ regs.u.r32.ebx = 0;
+ regs.u.r32.eax = 0x534D4150;
+ regs.u.r32.ecx = 0x14;
+ CLEAR_CF();
+ return;
+ } else if (regs.u.r16.bx == 1) {
+ extended_memory_size = inb_cmos(0x35);
+ extended_memory_size <<= 8;
+ extended_memory_size |= inb_cmos(0x34);
+ extended_memory_size *= 64;
+ if (extended_memory_size > 0x3bc000) // greater than EFF00000???
+ {
+ extended_memory_size = 0x3bc000; // everything after this is reserved memory until we get to 0x100000000
+ }
+ extended_memory_size *= 1024;
+ extended_memory_size += 15728640; // make up for the 16mb of memory that is chopped off
+
+ if (extended_memory_size <= 15728640)
+ {
+ extended_memory_size = inb_cmos(0x31);
+ extended_memory_size <<= 8;
+ extended_memory_size |= inb_cmos(0x30);
+ extended_memory_size *= 1024;
+ }
+
+ write_word(ES, regs.u.r16.di, 0x0000);
+ write_word(ES, regs.u.r16.di+2, 0x0010);
+ write_word(ES, regs.u.r16.di+4, 0x0000);
+ write_word(ES, regs.u.r16.di+6, 0x0000);
+
+ write_word(ES, regs.u.r16.di+8, extended_memory_size);
+ extended_memory_size >>= 16;
+ write_word(ES, regs.u.r16.di+10, extended_memory_size);
+ extended_memory_size >>= 16;
+ write_word(ES, regs.u.r16.di+12, extended_memory_size);
+ extended_memory_size >>= 16;
+ write_word(ES, regs.u.r16.di+14, extended_memory_size);
+
+ write_word(ES, regs.u.r16.di+16, 0x1);
+ write_word(ES, regs.u.r16.di+18, 0x0);
+
+ regs.u.r32.ebx = 0;
+ regs.u.r32.eax = 0x534D4150;
+ regs.u.r32.ecx = 0x14;
+ CLEAR_CF();
+ return;
+ } else { /* AX=E820, DX=534D4150, BX unrecognized */
+ goto int15_unimplemented;
+ }
+#else
switch(regs.u.r16.bx)
{
case 0:
@@ -4070,6 +4147,7 @@
write_word(ES, regs.u.r16.di+18, 0x0);
regs.u.r32.ebx = 1;
+
regs.u.r32.eax = 0x534D4150;
regs.u.r32.ecx = 0x14;
CLEAR_CF();
@@ -4121,6 +4199,7 @@
goto int15_unimplemented;
break;
}
+#endif
} else {
// if DX != 0x534D4150)
goto int15_unimplemented;
@@ -9497,9 +9576,16 @@
;; int 1C already points at dummy_iret_handler (above)
mov al, #0x34 ; timer0: binary count, 16bit count, mode 2
out 0x43, al
+#ifdef VMXASSIST
+ mov al, #0x0b ; #0xe90b = 20 Hz (temporary, until we fix xen/vmx support)
+ out 0x40, al ; lsb
+ mov al, #0xe9
+ out 0x40, al ; msb
+#else
mov al, #0x00 ; maximum count of 0000H = 18.2Hz
out 0x40, al
out 0x40, al
+#endif
;; Keyboard
SET_INT_VECTOR(0x09, #0xF000, #int09_handler)
@@ -9597,10 +9683,22 @@
mov al, #0x11 ; send initialisation commands
out 0x20, al
out 0xa0, al
+#ifdef VMXASSIST
+ ;; The vm86 emulator expects interrupts to be mapped beyond the reserved
+ ;; vectors (0 through 31). Since rombios fully controls the hardware, we
+ ;; map it the way the emulator needs it and expect that it will do the
+ ;; proper 8086 interrupt translation (that is, master pic base is at 0x8
+ ;; and slave pic base is at 0x70).
+ mov al, #0x20
+ out 0x21, al
+ mov al, #0x28
+ out 0xa1, al
+#else
mov al, #0x08
out 0x21, al
mov al, #0x70
out 0xa1, al
+#endif
mov al, #0x04
out 0x21, al
mov al, #0x02
@@ -9617,6 +9715,10 @@
#endif
out 0xa1, AL ;slave pic: unmask IRQ 12, 13, 14
+#ifdef VMXASSIST
+ call _copy_e820_table
+#endif
+
call pcibios_init
call rom_scan
+3 -18
View File
@@ -37,13 +37,7 @@ LDFLAGS = -m elf_i386
OBJECTS = head.o trap.o vm86.o setup.o util.o OBJECTS = head.o trap.o vm86.o setup.o util.o
all: vmxloader all: vmxassist.bin
vmxloader: roms.h vmxloader.c acpi.h acpi_madt.c
$(CC) $(CFLAGS) $(DEFINES) -c vmxloader.c -c acpi_madt.c
$(CC) -o vmxloader.tmp -m32 -nostdlib -Wl,-N -Wl,-Ttext -Wl,0x100000 vmxloader.o acpi_madt.o
objcopy vmxloader.tmp vmxloader
rm -f vmxloader.tmp
vmxassist.bin: vmxassist.ld $(OBJECTS) vmxassist.bin: vmxassist.ld $(OBJECTS)
$(CPP) $(DEFINES) vmxassist.ld > vmxassist.tmp $(CPP) $(DEFINES) vmxassist.ld > vmxassist.tmp
@@ -68,15 +62,6 @@ setup.o: machine.h setup.c
util.o: machine.h util.c util.o: machine.h util.c
$(CC) $(CFLAGS) -c util.c $(CC) $(CFLAGS) -c util.c
roms.h: ../rombios/BIOS-bochs-latest ../vgabios/VGABIOS-lgpl-latest.bin ../vgabios/VGABIOS-lgpl-latest.cirrus.bin vmxassist.bin
./mkhex rombios ../rombios/BIOS-bochs-latest > roms.h
./mkhex vgabios_stdvga ../vgabios/VGABIOS-lgpl-latest.bin >> roms.h
./mkhex vgabios_cirrusvga ../vgabios/VGABIOS-lgpl-latest.cirrus.bin >> roms.h
./mkhex vmxassist vmxassist.bin >> roms.h
acpi.h: ../acpi/acpi.bin
./mkhex acpi ../acpi/acpi.bin > acpi.h
offsets.h: gen offsets.h: gen
./gen > offsets.h ./gen > offsets.h
@@ -84,7 +69,7 @@ gen: gen.c
$(HOSTCC) $(HOSTCFLAGS) -I. $(XENINC) -o gen gen.c $(HOSTCC) $(HOSTCFLAGS) -I. $(XENINC) -o gen gen.c
clean: clean:
rm -f vmxassist vmxassist.tmp vmxassist.bin vmxassist.run vmxassist.sym head.s roms.h acpi.h rm -f vmxassist vmxassist.tmp vmxassist.bin vmxassist.run vmxassist.sym head.s
rm -f vmxloader vmxloader.tmp vmxloader.o $(OBJECTS) rm -f $(OBJECTS)
rm -f gen gen.o offsets.h rm -f gen gen.o offsets.h
+3
View File
@@ -111,6 +111,9 @@ _start:
cli cli
/* save register parameters to C land */ /* save register parameters to C land */
#ifdef TEST
xorl %edx, %edx
#endif
movl %edx, booting_cpu movl %edx, booting_cpu
movl %ebx, booting_vector movl %ebx, booting_vector
+13
View File
@@ -193,6 +193,12 @@ setup_pic(void)
outb(PIC_SLAVE + PIC_IMR, 0); outb(PIC_SLAVE + PIC_IMR, 0);
} }
void
setiomap(int port)
{
tss.iomap[port >> 3] |= 1 << (port & 7);
}
void void
enter_real_mode(struct regs *regs) enter_real_mode(struct regs *regs)
{ {
@@ -217,6 +223,13 @@ enter_real_mode(struct regs *regs)
} }
regs->uesp = 0; regs->uesp = 0;
regs->uss = 0; regs->uss = 0;
/* intercept accesses to the PIC */
setiomap(PIC_MASTER+PIC_CMD);
setiomap(PIC_MASTER+PIC_IMR);
setiomap(PIC_SLAVE+PIC_CMD);
setiomap(PIC_SLAVE+PIC_IMR);
printf("Starting emulated 16-bit real-mode: ip=%04x:%04x\n", printf("Starting emulated 16-bit real-mode: ip=%04x:%04x\n",
regs->cs, regs->eip); regs->cs, regs->eip);
+97
View File
@@ -738,6 +738,83 @@ interrupt(struct regs *regs, int n)
regs->cs = read16(address(regs, 0, n * 4 + 2)); regs->cs = read16(address(regs, 0, n * 4 + 2));
} }
/*
* Most port I/O operations are passed unmodified. We do have to be
* careful and make sure the emulated program isn't remapping the
* interrupt vectors. The following simple state machine catches
* these attempts and rewrites them.
*/
int
outbyte(struct regs *regs, unsigned prefix, unsigned opc)
{
static char icw2[2] = { 0 };
int al, port;
switch (opc) {
case 0xE6: /* outb port, al */
port = fetch8(regs);
break;
case 0xEE: /* outb (%dx), al */
port = MASK16(regs->edx);
break;
default:
return 0;
}
al = regs->eax & 0xFF;
switch (port) {
case PIC_MASTER + PIC_CMD:
if (al & (1 << 4)) /* A0=0,D4=1 -> ICW1 */
icw2[0] = 1;
break;
case PIC_MASTER + PIC_IMR:
if (icw2[0]) {
icw2[0] = 0;
printf("Remapping master: ICW2 0x%x -> 0x%x\n",
al, NR_EXCEPTION_HANDLER);
al = NR_EXCEPTION_HANDLER;
}
break;
case PIC_SLAVE + PIC_CMD:
if (al & (1 << 4)) /* A0=0,D4=1 -> ICW1 */
icw2[1] = 1;
break;
case PIC_SLAVE + PIC_IMR:
if (icw2[1]) {
icw2[1] = 0;
printf("Remapping slave: ICW2 0x%x -> 0x%x\n",
al, NR_EXCEPTION_HANDLER+8);
al = NR_EXCEPTION_HANDLER+8;
}
break;
}
outb(port, al);
return 1;
}
int
inbyte(struct regs *regs, unsigned prefix, unsigned opc)
{
int port;
switch (opc) {
case 0xE4: /* inb al, port */
port = fetch8(regs);
break;
case 0xEC: /* inb al, (%dx) */
port = MASK16(regs->edx);
break;
default:
return 0;
}
regs->eax = (regs->eax & ~0xFF) | inb(port);
return 1;
}
enum { OPC_INVALID, OPC_EMULATED }; enum { OPC_INVALID, OPC_EMULATED };
/* /*
@@ -885,6 +962,16 @@ opcode(struct regs *regs)
} }
return OPC_EMULATED; return OPC_EMULATED;
case 0xE4: /* inb al, port */
if (!inbyte(regs, prefix, opc))
goto invalid;
return OPC_EMULATED;
case 0xE6: /* outb port, al */
if (!outbyte(regs, prefix, opc))
goto invalid;
return OPC_EMULATED;
case 0xEA: /* jmpl */ case 0xEA: /* jmpl */
if ((mode == VM86_REAL_TO_PROTECTED) || if ((mode == VM86_REAL_TO_PROTECTED) ||
(mode == VM86_PROTECTED_TO_REAL)) { (mode == VM86_PROTECTED_TO_REAL)) {
@@ -903,6 +990,16 @@ opcode(struct regs *regs)
} }
goto invalid; goto invalid;
case 0xEC: /* inb al, (%dx) */
if (!inbyte(regs, prefix, opc))
goto invalid;
return OPC_EMULATED;
case 0xEE: /* outb (%dx), al */
if (!outbyte(regs, prefix, opc))
goto invalid;
return OPC_EMULATED;
case 0xF0: /* lock */ case 0xF0: /* lock */
TRACE((regs, regs->eip - eip, "lock")); TRACE((regs, regs->eip - eip, "lock"));
continue; continue;
-1
View File
@@ -2,7 +2,6 @@
* vmxassist.ld * vmxassist.ld
*/ */
OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386") OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
/*OUTPUT_ARCH(i386)*/
ENTRY(_start) ENTRY(_start)
SECTIONS SECTIONS
+1 -1
View File
@@ -584,5 +584,5 @@ static inline target_ulong get_phys_addr_code(CPUState *env, target_ulong addr)
//#define DEBUG_UNUSED_IOPORT //#define DEBUG_UNUSED_IOPORT
//#define DEBUG_IOPORT //#define DEBUG_IOPORT
#define TARGET_VMX #define TARGET_HVM
+16 -16
View File
@@ -50,7 +50,7 @@ typedef struct PITChannelState {
int64_t next_transition_time; int64_t next_transition_time;
QEMUTimer *irq_timer; QEMUTimer *irq_timer;
int irq; int irq;
int vmx_channel; /* Is this accelerated by VMX ? */ int hvm_channel; /* Is this accelerated by HVM ? */
} PITChannelState; } PITChannelState;
struct PITState { struct PITState {
@@ -61,8 +61,8 @@ static PITState pit_state;
static void pit_irq_timer_update(PITChannelState *s, int64_t current_time); static void pit_irq_timer_update(PITChannelState *s, int64_t current_time);
/* currently operate which channel for vmx use */ /* currently operate which channel for hvm use */
int vmx_channel = -1; int hvm_channel = -1;
extern FILE *logfile; extern FILE *logfile;
static int pit_get_count(PITChannelState *s) static int pit_get_count(PITChannelState *s)
{ {
@@ -215,7 +215,7 @@ int pit_get_gate(PITState *pit, int channel)
return s->gate; return s->gate;
} }
void pit_reset_vmx_vectors() void pit_reset_hvm_vectors()
{ {
extern shared_iopage_t *shared_page; extern shared_iopage_t *shared_page;
ioreq_t *req; ioreq_t *req;
@@ -225,18 +225,18 @@ void pit_reset_vmx_vectors()
irq = 0; irq = 0;
for(i = 0; i < 3; i++) { for(i = 0; i < 3; i++) {
if (pit_state.channels[i].vmx_channel) if (pit_state.channels[i].hvm_channel)
break; break;
} }
if (i == 3) if (i == 3)
return; return;
/* Assumes just one VMX accelerated channel */ /* Assumes just one HVM accelerated channel */
vmx_channel = i; hvm_channel = i;
s = &pit_state.channels[vmx_channel]; s = &pit_state.channels[hvm_channel];
fprintf(logfile, fprintf(logfile,
"VMX_PIT:guest init pit channel %d!\n", vmx_channel); "HVM_PIT:guest init pit channel %d!\n", hvm_channel);
req = &shared_page->vcpu_iodata[0].vp_ioreq; req = &shared_page->vcpu_iodata[0].vp_ioreq;
req->state = STATE_IORESP_HOOK; req->state = STATE_IORESP_HOOK;
@@ -247,9 +247,9 @@ void pit_reset_vmx_vectors()
*/ */
req->u.data = s->count; req->u.data = s->count;
req->u.data |= (irq << 16); req->u.data |= (irq << 16);
req->u.data |= (vmx_channel << 24); req->u.data |= (hvm_channel << 24);
req->u.data |= ((s->rw_mode) << 26); req->u.data |= ((s->rw_mode) << 26);
fprintf(logfile, "VMX_PIT:pass info 0x%llx to HV!\n", req->u.data); fprintf(logfile, "HVM_PIT:pass info 0x%llx to HV!\n", req->u.data);
} }
static inline void pit_load_count(PITChannelState *s, int val) static inline void pit_load_count(PITChannelState *s, int val)
@@ -261,9 +261,9 @@ static inline void pit_load_count(PITChannelState *s, int val)
/* guest init this pit channel for periodic mode. we do not update related /* guest init this pit channel for periodic mode. we do not update related
* timer so the channel never send intr from device model*/ * timer so the channel never send intr from device model*/
if (vmx_channel != -1 && s->mode == 2) { if (hvm_channel != -1 && s->mode == 2) {
pit_reset_vmx_vectors(); pit_reset_hvm_vectors();
vmx_channel = -1; hvm_channel = -1;
} }
/* pit_irq_timer_update(s, s->count_load_time);*/ /* pit_irq_timer_update(s, s->count_load_time);*/
@@ -323,8 +323,8 @@ static void pit_ioport_write(void *opaque, uint32_t addr, uint32_t val)
} }
} else { } else {
s = &pit->channels[addr]; s = &pit->channels[addr];
s->vmx_channel = 1; s->hvm_channel = 1;
vmx_channel = addr; hvm_channel = addr;
switch(s->write_state) { switch(s->write_state) {
default: default:
case RW_STATE_LSB: case RW_STATE_LSB:
+2 -2
View File
@@ -31,7 +31,7 @@
//#define DEBUG_IRQ_LATENCY //#define DEBUG_IRQ_LATENCY
//#define DEBUG_IRQ_COUNT //#define DEBUG_IRQ_COUNT
extern void pit_reset_vmx_vectors(); extern void pit_reset_hvm_vectors();
typedef struct PicState { typedef struct PicState {
uint8_t last_irr; /* edge detection */ uint8_t last_irr; /* edge detection */
@@ -368,7 +368,7 @@ static void pic_ioport_write(void *opaque, uint32_t addr, uint32_t val)
case 1: case 1:
s->irq_base = val & 0xf8; s->irq_base = val & 0xf8;
s->init_state = 2; s->init_state = 2;
pit_reset_vmx_vectors(); pit_reset_hvm_vectors();
break; break;
case 2: case 2:
if (s->init4) { if (s->init4) {
+7 -7
View File
@@ -225,10 +225,10 @@ static void do_info_history (void)
} }
} }
extern void destroy_vmx_domain(void); extern void destroy_hvm_domain(void);
static void do_quit(void) static void do_quit(void)
{ {
destroy_vmx_domain(); destroy_hvm_domain();
exit(0); exit(0);
} }
@@ -506,8 +506,8 @@ static term_cmd_t info_cmds[] = {
"", "show i8259 (PIC) state", }, "", "show i8259 (PIC) state", },
{ "pci", "", pci_info, { "pci", "", pci_info,
"", "show PCI info", }, "", "show PCI info", },
{ "vmxiopage", "", sp_info, { "hvmiopage", "", sp_info,
"", "show VMX device model shared page info", }, "", "show HVM device model shared page info", },
{ NULL, NULL, }, { NULL, NULL, },
}; };
@@ -700,7 +700,7 @@ static void monitor_handle_command(const char *cmdline)
args[nb_args++] = (void *)has_option; args[nb_args++] = (void *)has_option;
} }
break; break;
/* TODO: add more commands we need here to support vmx device model */ /* TODO: add more commands we need here to support hvm device model */
case '/': case '/':
case 'i': case 'i':
default: default:
@@ -772,14 +772,14 @@ static void monitor_handle_command1(void *opaque, const char *cmdline)
static void monitor_start_input(void) static void monitor_start_input(void)
{ {
readline_start("(VTXen) ", 0, monitor_handle_command1, NULL); readline_start("(HVMXen) ", 0, monitor_handle_command1, NULL);
} }
void monitor_init(CharDriverState *hd, int show_banner) void monitor_init(CharDriverState *hd, int show_banner)
{ {
monitor_hd = hd; monitor_hd = hd;
if (show_banner) { if (show_banner) {
term_printf("VMX device model. type 'q' to exit\n"); term_printf("HVM device model. type 'q' to exit\n");
} }
qemu_chr_add_read_handler(hd, term_can_read, term_read, NULL); qemu_chr_add_read_handler(hd, term_can_read, term_read, NULL);
monitor_start_input(); monitor_start_input();
+6 -4
View File
@@ -20,7 +20,9 @@
/* /*
* Main cpu loop for handling I/O requests coming from a virtual machine * Main cpu loop for handling I/O requests coming from a virtual machine
*
* Copyright © 2004, Intel Corporation. * Copyright © 2004, Intel Corporation.
* Copyright © 2005, International Business Machines Corporation.
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU Lesser General Public License, * under the terms and conditions of the GNU Lesser General Public License,
@@ -394,7 +396,7 @@ void cpu_handle_ioreq(CPUState *env)
int xc_handle; int xc_handle;
void void
destroy_vmx_domain(void) destroy_hvm_domain(void)
{ {
extern FILE* logfile; extern FILE* logfile;
char destroy_cmd[32]; char destroy_cmd[32];
@@ -467,11 +469,11 @@ int main_loop(void)
(void)ioctl(evtchn_fd, IOCTL_EVTCHN_NOTIFY, &notify); (void)ioctl(evtchn_fd, IOCTL_EVTCHN_NOTIFY, &notify);
} }
} }
destroy_vmx_domain(); destroy_hvm_domain();
return 0; return 0;
} }
static void qemu_vmx_reset(void *unused) static void qemu_hvm_reset(void *unused)
{ {
char cmd[64]; char cmd[64];
@@ -489,7 +491,7 @@ CPUState * cpu_init()
int rc; int rc;
cpu_exec_init(); cpu_exec_init();
qemu_register_reset(qemu_vmx_reset, NULL); qemu_register_reset(qemu_hvm_reset, NULL);
env = malloc(sizeof(CPUX86State)); env = malloc(sizeof(CPUX86State));
if (!env) if (!env)
return NULL; return NULL;
+4 -4
View File
@@ -125,7 +125,7 @@ static char network_script[1024];
int pit_min_timer_count = 0; int pit_min_timer_count = 0;
int nb_nics; int nb_nics;
char bridge[16]; char bridge[16];
char domain_name[1024] = { 'V', 'T', 'X', 'E', 'N', '-'}; char domain_name[1024] = { 'H','V', 'M', 'X', 'E', 'N', '-'};
NetDriverState nd_table[MAX_NICS]; NetDriverState nd_table[MAX_NICS];
QEMUTimer *gui_timer; QEMUTimer *gui_timer;
QEMUTimer *polling_timer; QEMUTimer *polling_timer;
@@ -826,8 +826,8 @@ static void init_timers(void)
{ {
/* get times() syscall frequency */ /* get times() syscall frequency */
timer_freq = sysconf(_SC_CLK_TCK); timer_freq = sysconf(_SC_CLK_TCK);
#ifndef TARGET_VMX #ifndef TARGET_HVM
/* timer signal */ /* timer signal */
sigfillset(&act.sa_mask); sigfillset(&act.sa_mask);
act.sa_flags = 0; act.sa_flags = 0;
@@ -869,7 +869,7 @@ static void init_timers(void)
pit_min_timer_count = ((uint64_t)itv.it_interval.tv_usec * pit_min_timer_count = ((uint64_t)itv.it_interval.tv_usec *
PIT_FREQ) / 1000000; PIT_FREQ) / 1000000;
} }
#endif /* TARGET_VMX */ #endif /* TARGET_HVM */
} }
#endif #endif
} }
+1 -1
View File
@@ -45,7 +45,7 @@ else
BUILD_SRCS += xc_load_aout9.c BUILD_SRCS += xc_load_aout9.c
BUILD_SRCS += xc_linux_restore.c BUILD_SRCS += xc_linux_restore.c
BUILD_SRCS += xc_linux_save.c BUILD_SRCS += xc_linux_save.c
BUILD_SRCS += xc_vmx_build.c BUILD_SRCS += xc_hvm_build.c
endif endif
CFLAGS += -Wall CFLAGS += -Wall
@@ -1,5 +1,5 @@
/****************************************************************************** /******************************************************************************
* xc_vmx_build.c * xc_hvm_build.c
*/ */
#include <stddef.h> #include <stddef.h>
@@ -12,7 +12,7 @@
#include <xen/hvm/hvm_info_table.h> #include <xen/hvm/hvm_info_table.h>
#include <xen/hvm/ioreq.h> #include <xen/hvm/ioreq.h>
#define VMX_LOADER_ENTR_ADDR 0x00100000 #define HVM_LOADER_ENTR_ADDR 0x00100000
#define L1_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_USER) #define L1_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_USER)
#define L2_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY|_PAGE_USER) #define L2_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY|_PAGE_USER)
@@ -133,7 +133,7 @@ set_hvm_info_checksum(struct hvm_info_table *t)
/* /*
* Use E820 reserved memory 0x9F800 to pass HVM info to vmxloader * Use E820 reserved memory 0x9F800 to pass HVM info to vmxloader
* vmxloader will use this info to set BIOS accordingly * hvmloader will use this info to set BIOS accordingly
*/ */
static int set_hvm_info(int xc_handle, uint32_t dom, static int set_hvm_info(int xc_handle, uint32_t dom,
unsigned long *pfn_list, unsigned int vcpus, unsigned long *pfn_list, unsigned int vcpus,
@@ -142,6 +142,7 @@ static int set_hvm_info(int xc_handle, uint32_t dom,
char *va_map; char *va_map;
struct hvm_info_table *va_hvm; struct hvm_info_table *va_hvm;
va_map = xc_map_foreign_range( va_map = xc_map_foreign_range(
xc_handle, xc_handle,
dom, dom,
@@ -302,7 +303,7 @@ static int setup_guest(int xc_handle,
unsigned long shared_info_frame, unsigned long shared_info_frame,
unsigned int control_evtchn, unsigned int control_evtchn,
unsigned int vcpus, unsigned int vcpus,
unsigned int acpi, unsigned int acpi,
unsigned int apic, unsigned int apic,
unsigned int store_evtchn, unsigned int store_evtchn,
unsigned long *store_mfn) unsigned long *store_mfn)
@@ -357,7 +358,7 @@ static int setup_guest(int xc_handle,
vpt_end = vpt_start + (nr_pt_pages * PAGE_SIZE); vpt_end = vpt_start + (nr_pt_pages * PAGE_SIZE);
printf("VIRTUAL MEMORY ARRANGEMENT:\n" printf("VIRTUAL MEMORY ARRANGEMENT:\n"
" Loaded VMX loader: %08lx->%08lx\n" " Loaded HVM loader: %08lx->%08lx\n"
" Page tables: %08lx->%08lx\n" " Page tables: %08lx->%08lx\n"
" TOTAL: %08lx->%08lx\n", " TOTAL: %08lx->%08lx\n",
dsi.v_kernstart, dsi.v_kernend, dsi.v_kernstart, dsi.v_kernend,
@@ -514,7 +515,7 @@ static int setup_guest(int xc_handle,
} }
if ( set_hvm_info(xc_handle, dom, page_array, vcpus, acpi, apic) ) { if ( set_hvm_info(xc_handle, dom, page_array, vcpus, acpi, apic) ) {
fprintf(stderr, "Couldn't set hvm info for VMX guest.\n"); fprintf(stderr, "Couldn't set hvm info for HVM guest.\n");
goto error_out; goto error_out;
} }
@@ -595,13 +596,13 @@ static int setup_guest(int xc_handle,
return -1; return -1;
} }
int xc_vmx_build(int xc_handle, int xc_hvm_build(int xc_handle,
uint32_t domid, uint32_t domid,
int memsize, int memsize,
const char *image_name, const char *image_name,
unsigned int control_evtchn, unsigned int control_evtchn,
unsigned int vcpus, unsigned int vcpus,
unsigned int acpi, unsigned int acpi,
unsigned int apic, unsigned int apic,
unsigned int store_evtchn, unsigned int store_evtchn,
unsigned long *store_mfn) unsigned long *store_mfn)
@@ -622,8 +623,8 @@ int xc_vmx_build(int xc_handle,
if ( !strstr(xen_caps, "hvm") ) if ( !strstr(xen_caps, "hvm") )
{ {
PERROR("CPU doesn't support VMX Extensions or " PERROR("CPU doesn't support HVM extensions or "
"CPU VMX Extensions are not turned on"); "the extensions are not enabled");
goto error_out; goto error_out;
} }
@@ -653,6 +654,7 @@ int xc_vmx_build(int xc_handle,
memset(ctxt, 0, sizeof(*ctxt)); memset(ctxt, 0, sizeof(*ctxt));
ctxt->flags = VGCF_HVM_GUEST;
if ( setup_guest(xc_handle, domid, memsize, image, image_size, nr_pages, if ( setup_guest(xc_handle, domid, memsize, image, image_size, nr_pages,
ctxt, op.u.getdomaininfo.shared_info_frame, control_evtchn, ctxt, op.u.getdomaininfo.shared_info_frame, control_evtchn,
vcpus, acpi, apic, store_evtchn, store_mfn) < 0) vcpus, acpi, apic, store_evtchn, store_mfn) < 0)
@@ -663,7 +665,6 @@ int xc_vmx_build(int xc_handle,
free(image); free(image);
ctxt->flags = VGCF_VMX_GUEST;
/* FPU is set up to default initial state. */ /* FPU is set up to default initial state. */
memset(&ctxt->fpu_ctxt, 0, sizeof(ctxt->fpu_ctxt)); memset(&ctxt->fpu_ctxt, 0, sizeof(ctxt->fpu_ctxt));
@@ -779,7 +780,7 @@ static int parseelfimage(char *elfbase,
dsi->v_kernstart = kernstart; dsi->v_kernstart = kernstart;
dsi->v_kernend = kernend; dsi->v_kernend = kernend;
dsi->v_kernentry = VMX_LOADER_ENTR_ADDR; dsi->v_kernentry = HVM_LOADER_ENTR_ADDR;
dsi->v_end = dsi->v_kernend; dsi->v_end = dsi->v_kernend;
+1 -1
View File
@@ -621,7 +621,7 @@ static int setup_guest( int xc_handle,
return -1; return -1;
} }
int xc_vmx_build(int xc_handle, int xc_hvm_build(int xc_handle,
uint32_t domid, uint32_t domid,
int memsize, int memsize,
const char *image_name, const char *image_name,
+1 -1
View File
@@ -815,7 +815,7 @@ static int setup_guest(int xc_handle,
start_info->mod_len = initrd_len; start_info->mod_len = initrd_len;
} }
if ( cmdline != NULL ) if ( cmdline != NULL )
{ {
strncpy((char *)start_info->cmd_line, cmdline, MAX_GUEST_CMDLINE); strncpy((char *)start_info->cmd_line, cmdline, MAX_GUEST_CMDLINE);
start_info->cmd_line[MAX_GUEST_CMDLINE-1] = '\0'; start_info->cmd_line[MAX_GUEST_CMDLINE-1] = '\0';
} }
+2 -2
View File
@@ -240,7 +240,7 @@ map_domain_va(
} }
if ( (pde = cr3_virt[cpu][vtopdi(va)]) == 0 ) if ( (pde = cr3_virt[cpu][vtopdi(va)]) == 0 )
goto error_out; goto error_out;
if ( (ctxt[cpu].flags & VGCF_VMX_GUEST) && paging_enabled(&ctxt[cpu]) ) if ( (ctxt[cpu].flags & VGCF_HVM_GUEST) && paging_enabled(&ctxt[cpu]) )
pde = page_array[pde >> PAGE_SHIFT] << PAGE_SHIFT; pde = page_array[pde >> PAGE_SHIFT] << PAGE_SHIFT;
if ( pde != pde_phys[cpu] ) if ( pde != pde_phys[cpu] )
{ {
@@ -255,7 +255,7 @@ map_domain_va(
} }
if ( (page = pde_virt[cpu][vtopti(va)]) == 0 ) if ( (page = pde_virt[cpu][vtopti(va)]) == 0 )
goto error_out; goto error_out;
if ( (ctxt[cpu].flags & VGCF_VMX_GUEST) && paging_enabled(&ctxt[cpu]) ) if ( (ctxt[cpu].flags & VGCF_HVM_GUEST) && paging_enabled(&ctxt[cpu]) )
page = page_array[page >> PAGE_SHIFT] << PAGE_SHIFT; page = page_array[page >> PAGE_SHIFT] << PAGE_SHIFT;
if ( (page != page_phys[cpu]) || (perm != prev_perm[cpu]) ) if ( (page != page_phys[cpu]) || (perm != prev_perm[cpu]) )
{ {
+2 -2
View File
@@ -126,7 +126,7 @@ map_domain_va(unsigned long domfd, int cpu, void * guest_va)
} }
if ((pde = cr3_virt[cpu][vtopdi(va)]) == 0) /* logical address */ if ((pde = cr3_virt[cpu][vtopdi(va)]) == 0) /* logical address */
goto error_out; goto error_out;
if (ctxt[cpu].flags & VGCF_VMX_GUEST) if (ctxt[cpu].flags & VGCF_HVM_GUEST)
pde = p2m_array[pde >> PAGE_SHIFT] << PAGE_SHIFT; pde = p2m_array[pde >> PAGE_SHIFT] << PAGE_SHIFT;
if (pde != pde_phys[cpu]) if (pde != pde_phys[cpu])
{ {
@@ -142,7 +142,7 @@ map_domain_va(unsigned long domfd, int cpu, void * guest_va)
} }
if ((page = pde_virt[cpu][vtopti(va)]) == 0) /* logical address */ if ((page = pde_virt[cpu][vtopti(va)]) == 0) /* logical address */
goto error_out; goto error_out;
if (ctxt[cpu].flags & VGCF_VMX_GUEST) if (ctxt[cpu].flags & VGCF_HVM_GUEST)
page = p2m_array[page >> PAGE_SHIFT] << PAGE_SHIFT; page = p2m_array[page >> PAGE_SHIFT] << PAGE_SHIFT;
if (page != page_phys[cpu]) if (page != page_phys[cpu])
{ {
+1 -1
View File
@@ -53,7 +53,7 @@ int xc_linux_build(int xc_handle,
unsigned int console_evtchn, unsigned int console_evtchn,
unsigned long *console_mfn); unsigned long *console_mfn);
int xc_vmx_build(int xc_handle, int xc_hvm_build(int xc_handle,
uint32_t domid, uint32_t domid,
int memsize, int memsize,
const char *image_name, const char *image_name,
+10 -11
View File
@@ -355,7 +355,7 @@ static PyObject *pyxc_linux_build(XcObject *self,
"console_mfn", console_mfn); "console_mfn", console_mfn);
} }
static PyObject *pyxc_vmx_build(XcObject *self, static PyObject *pyxc_hvm_build(XcObject *self,
PyObject *args, PyObject *args,
PyObject *kwds) PyObject *kwds)
{ {
@@ -369,16 +369,15 @@ static PyObject *pyxc_vmx_build(XcObject *self,
unsigned long store_mfn = 0; unsigned long store_mfn = 0;
static char *kwd_list[] = { "dom", "control_evtchn", "store_evtchn", static char *kwd_list[] = { "dom", "control_evtchn", "store_evtchn",
"memsize", "image", "vcpus", "acpi", "apic", "memsize", "image", "vcpus", "acpi", "apic",
NULL }; NULL };
if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iiiisiii", kwd_list, if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iiiisiii", kwd_list,
&dom, &control_evtchn, &store_evtchn, &dom, &control_evtchn, &store_evtchn,
&memsize, &image, &vcpus, &acpi, &apic) ) &memsize, &image, &vcpus, &acpi, &apic) )
return NULL; return NULL;
if ( xc_vmx_build(self->xc_handle, dom, memsize, image, control_evtchn, if ( xc_hvm_build(self->xc_handle, dom, memsize, image, control_evtchn,
vcpus, acpi, apic, store_evtchn, &store_mfn) != 0 ) vcpus, acpi, apic, store_evtchn, &store_mfn) != 0 )
return PyErr_SetFromErrno(xc_error); return PyErr_SetFromErrno(xc_error);
return Py_BuildValue("{s:i}", "store_mfn", store_mfn); return Py_BuildValue("{s:i}", "store_mfn", store_mfn);
@@ -965,12 +964,12 @@ static PyMethodDef pyxc_methods[] = {
" vcpus [int, 1]: Number of Virtual CPUS in domain.\n\n" " vcpus [int, 1]: Number of Virtual CPUS in domain.\n\n"
"Returns: [int] 0 on success; -1 on error.\n" }, "Returns: [int] 0 on success; -1 on error.\n" },
{ "vmx_build", { "hvm_build",
(PyCFunction)pyxc_vmx_build, (PyCFunction)pyxc_hvm_build,
METH_VARARGS | METH_KEYWORDS, "\n" METH_VARARGS | METH_KEYWORDS, "\n"
"Build a new VMX guest OS.\n" "Build a new HVM guest OS.\n"
" dom [int]: Identifier of domain to build into.\n" " dom [int]: Identifier of domain to build into.\n"
" image [str]: Name of VMX loader image file.\n" " image [str]: Name of HVM loader image file.\n"
" vcpus [int, 1]: Number of Virtual CPUS in domain.\n\n" " vcpus [int, 1]: Number of Virtual CPUS in domain.\n\n"
"Returns: [int] 0 on success; -1 on error.\n" }, "Returns: [int] 0 on success; -1 on error.\n" },
+16 -16
View File
@@ -143,7 +143,7 @@ class ImageHandler:
def getDomainMemory(self, mem): def getDomainMemory(self, mem):
"""@return The memory required, in KiB, by the domain to store the """@return The memory required, in KiB, by the domain to store the
given amount, also in KiB. This is normally just mem, but VMX domains given amount, also in KiB. This is normally just mem, but HVM domains
have overheads to account for.""" have overheads to account for."""
return mem return mem
@@ -183,21 +183,21 @@ class LinuxImageHandler(ImageHandler):
cmdline = self.cmdline, cmdline = self.cmdline,
ramdisk = self.ramdisk) ramdisk = self.ramdisk)
class VmxImageHandler(ImageHandler): class HVMImageHandler(ImageHandler):
ostype = "vmx" ostype = "hvm"
def configure(self, imageConfig, deviceConfig): def configure(self, imageConfig, deviceConfig):
ImageHandler.configure(self, imageConfig, deviceConfig) ImageHandler.configure(self, imageConfig, deviceConfig)
info = xc.xeninfo() info = xc.xeninfo()
if not 'hvm' in info['xen_caps']: if not 'hvm' in info['xen_caps']:
raise VmError("vmx: not an Intel VT platform, we stop creating!") raise VmError("Not an HVM capable platform, we stop creating!")
self.dmargs = self.parseDeviceModelArgs(imageConfig, deviceConfig) self.dmargs = self.parseDeviceModelArgs(imageConfig, deviceConfig)
self.device_model = sxp.child_value(imageConfig, 'device_model') self.device_model = sxp.child_value(imageConfig, 'device_model')
if not self.device_model: if not self.device_model:
raise VmError("vmx: missing device model") raise VmError("hvm: missing device model")
self.display = sxp.child_value(imageConfig, 'display') self.display = sxp.child_value(imageConfig, 'display')
self.xauthority = sxp.child_value(imageConfig, 'xauthority') self.xauthority = sxp.child_value(imageConfig, 'xauthority')
@@ -217,7 +217,7 @@ class VmxImageHandler(ImageHandler):
# Create an event channel # Create an event channel
self.device_channel = xc.evtchn_alloc_unbound(dom=self.vm.getDomid(), self.device_channel = xc.evtchn_alloc_unbound(dom=self.vm.getDomid(),
remote_dom=0) remote_dom=0)
log.info("VMX device model port: %d", self.device_channel) log.info("HVM device model port: %d", self.device_channel)
store_evtchn = self.vm.getStorePort() store_evtchn = self.vm.getStorePort()
@@ -232,7 +232,7 @@ class VmxImageHandler(ImageHandler):
self.register_shutdown_watch() self.register_shutdown_watch()
return xc.vmx_build(dom = self.vm.getDomid(), return xc.hvm_build(dom = self.vm.getDomid(),
image = self.kernel, image = self.kernel,
control_evtchn = self.device_channel, control_evtchn = self.device_channel,
store_evtchn = store_evtchn, store_evtchn = store_evtchn,
@@ -283,7 +283,7 @@ class VmxImageHandler(ImageHandler):
continue; continue;
vbddev_list = ['hda', 'hdb', 'hdc', 'hdd'] vbddev_list = ['hda', 'hdb', 'hdc', 'hdd']
if vbddev not in vbddev_list: if vbddev not in vbddev_list:
raise VmError("vmx: for qemu vbd type=file&dev=hda~hdd") raise VmError("hvm: for qemu vbd type=file&dev=hda~hdd")
ret.append("-%s" % vbddev) ret.append("-%s" % vbddev)
ret.append("%s" % vbdparam) ret.append("%s" % vbdparam)
if name == 'vif': if name == 'vif':
@@ -405,8 +405,8 @@ class VmxImageHandler(ImageHandler):
def register_shutdown_watch(self): def register_shutdown_watch(self):
""" add xen store watch on control/shutdown """ """ add xen store watch on control/shutdown """
self.shutdownWatch = xswatch(self.vm.dompath + "/control/shutdown", \ self.shutdownWatch = xswatch(self.vm.dompath + "/control/shutdown", \
self.vmx_shutdown) self.hvm_shutdown)
log.debug("vmx shutdown watch registered") log.debug("hvm shutdown watch registered")
def unregister_shutdown_watch(self): def unregister_shutdown_watch(self):
"""Remove the watch on the control/shutdown, if any. Nothrow """Remove the watch on the control/shutdown, if any. Nothrow
@@ -416,11 +416,11 @@ class VmxImageHandler(ImageHandler):
if self.shutdownWatch: if self.shutdownWatch:
self.shutdownWatch.unwatch() self.shutdownWatch.unwatch()
except: except:
log.exception("Unwatching vmx shutdown watch failed.") log.exception("Unwatching hvm shutdown watch failed.")
self.shutdownWatch = None self.shutdownWatch = None
log.debug("vmx shutdown watch unregistered") log.debug("hvm shutdown watch unregistered")
def vmx_shutdown(self, _): def hvm_shutdown(self, _):
""" watch call back on node control/shutdown, """ watch call back on node control/shutdown,
if node changed, this function will be called if node changed, this function will be called
""" """
@@ -429,7 +429,7 @@ class VmxImageHandler(ImageHandler):
vm = xd.domain_lookup( self.vm.getDomid() ) vm = xd.domain_lookup( self.vm.getDomid() )
reason = vm.readDom('control/shutdown') reason = vm.readDom('control/shutdown')
log.debug("vmx_shutdown fired, shutdown reason=%s", reason) log.debug("hvm_shutdown fired, shutdown reason=%s", reason)
for x in shutdown_reasons.keys(): for x in shutdown_reasons.keys():
if shutdown_reasons[x] == reason: if shutdown_reasons[x] == reason:
vm.info['shutdown'] = 1 vm.info['shutdown'] = 1
@@ -444,7 +444,7 @@ image type.
imageHandlerClasses = {} imageHandlerClasses = {}
for h in LinuxImageHandler, VmxImageHandler: for h in LinuxImageHandler, HVMImageHandler:
imageHandlerClasses[h.ostype] = h imageHandlerClasses[h.ostype] = h
+6 -6
View File
@@ -162,11 +162,11 @@ gopts.var('cpus', val='CPUS',
gopts.var('acpi', val='ACPI', gopts.var('acpi', val='ACPI',
fn=set_int, default=0, fn=set_int, default=0,
use="Disable or enable ACPI of VMX domain.") use="Disable or enable ACPI of HVM domain.")
gopts.var('apic', val='APIC', gopts.var('apic', val='APIC',
fn=set_int, default=0, fn=set_int, default=0,
use="Disable or enable APIC of VMX domain.") use="Disable or enable APIC of HVM domain.")
gopts.var('vcpus', val='VCPUS', gopts.var('vcpus', val='VCPUS',
fn=set_int, default=1, fn=set_int, default=1,
@@ -441,8 +441,8 @@ def configure_image(vals):
if vals.extra: if vals.extra:
config_image.append(['args', vals.extra]) config_image.append(['args', vals.extra])
if vals.builder == 'vmx': if vals.builder == 'hvm':
configure_vmx(config_image, vals) configure_hvm(config_image, vals)
return config_image return config_image
@@ -536,8 +536,8 @@ def configure_vifs(config_devs, vals):
config_devs.append(['device', config_vif]) config_devs.append(['device', config_vif])
def configure_vmx(config_image, vals): def configure_hvm(config_image, vals):
"""Create the config for VMX devices. """Create the config for HVM devices.
""" """
args = [ 'device_model', 'vcpus', 'cdrom', 'boot', 'fda', 'fdb', args = [ 'device_model', 'vcpus', 'cdrom', 'boot', 'fda', 'fdb',
'localtime', 'serial', 'stdvga', 'isa', 'nographic', 'audio', 'localtime', 'serial', 'stdvga', 'isa', 'nographic', 'audio',
+7 -7
View File
@@ -141,15 +141,15 @@ cpu_weight = 0.75
}) })
def testVMXConfigFile(self): def testHVMConfigFile(self):
(fd, fname) = tempfile.mkstemp() (fd, fname) = tempfile.mkstemp()
try: try:
os.write(fd, os.write(fd,
''' '''
kernel = "/usr/lib/xen/boot/vmxloader" kernel = "/usr/lib/xen/boot/hvmloader"
builder='vmx' builder='hvm'
memory = 128 memory = 128
name = "ExampleVMXDomain" name = "ExampleHVMDomain"
vcpus=1 vcpus=1
vif = [ 'type=ioemu, bridge=xenbr0' ] vif = [ 'type=ioemu, bridge=xenbr0' ]
disk = [ 'file:/var/images/min-el3-i386.img,ioemu:hda,w' ] disk = [ 'file:/var/images/min-el3-i386.img,ioemu:hda,w' ]
@@ -163,10 +163,10 @@ ne2000=0
os.close(fd) os.close(fd)
self.t('-f %s display=fakedisplay' % fname, self.t('-f %s display=fakedisplay' % fname,
{ 'kernel' : '/usr/lib/xen/boot/vmxloader', { 'kernel' : '/usr/lib/xen/boot/hvmloader',
'builder' : 'vmx', 'builder' : 'hvm',
'memory' : 128, 'memory' : 128,
'name' : 'ExampleVMXDomain', 'name' : 'ExampleHVMDomain',
'vcpus' : 1, 'vcpus' : 1,
'nics' : -1, 'nics' : -1,
'vif' : ['type=ioemu, bridge=xenbr0'], 'vif' : ['type=ioemu, bridge=xenbr0'],
+12 -12
View File
@@ -60,26 +60,26 @@ BUILDING with HVM Support
========================= =========================
If you'd like to build and run this with hardware virtual machine assist If you'd like to build and run this with hardware virtual machine assist
(HVM) support to test fully virtualized disk images on VMX hardware, (HVM) support to test fully virtualized disk images on VMX/SVM hardware,
please add the --enable-vmx-support option to configure: please add the --enable-hvm-support option to configure:
# ./autogen # ./autogen
# ./configure --enable-vmx-support # ./configure --enable-hvm-support
# make # make
The ramdisk/bin/create_disk_image script, which builds the full virt The ramdisk/bin/create_disk_image script, which builds the full virt
disk.img, requires Lilo 22.7+ to be installed on the system. Lilo is disk.img, requires Lilo 22.7+ to be installed on the system. Lilo is
used to install the bootloader on the disk.img. used to install the bootloader on the disk.img.
If HVM / VMX support is enabled, the ramdisk/bin/create_disk_image script If HVM support is enabled, the ramdisk/bin/create_disk_image script
will be run to create a full virt disk.img in the ramdisk directory. The will be run to create a full virt disk.img in the ramdisk directory. The
script, by default, will look in /boot for the first non-Xen kernel it script, by default, will look in /boot for the first non-Xen kernel it
runs across. If you'd like to set xm-test to use a specific kernel, runs across. If you'd like to set xm-test to use a specific kernel,
rather than the first one it finds in /boot, you can configure it in rather than the first one it finds in /boot, you can configure it in
with the "--with-vmx-kernel=KERNEL" option: with the "--with-hvm-kernel=KERNEL" option:
# ./autogen # ./autogen
# ./configure --enable-vmx-support --with-vmx-kernel=KERNEL # ./configure --enable-hvm-support --with-hvm-kernel=KERNEL
# make # make
Otherwise, you can always rerun the create script using the -k option Otherwise, you can always rerun the create script using the -k option
@@ -92,14 +92,14 @@ used. If you'd like to specify a different location for the driver or
want to tell the script that the driver is built into the kernel, please want to tell the script that the driver is built into the kernel, please
use the "--with-driver-dir=DRVDIR" configure option. If built into use the "--with-driver-dir=DRVDIR" configure option. If built into
the kernel, please use the key word "builtin" with the option: the kernel, please use the key word "builtin" with the option:
# ./autogen # ./autogen
# ./configure --enable-vmx-support --with-driver-dir=builtin # ./configure --enable-hvm-support --with-driver-dir=builtin
- or - - or -
# ./configure --enable-vmx-support --with-driver-dir=/driver/directory # ./configure --enable-hvm-support --with-driver-dir=/driver/directory
# make # make
Xm-test will look for disk.img in the ramdisk directory when run by Xm-test will look for disk.img in the ramdisk directory when run by
default. default.
+14 -14
View File
@@ -15,18 +15,18 @@ TESTLIB=../../lib
RD_PATH=../../ramdisk RD_PATH=../../ramdisk
TENV="PYTHONPATH=$PYTHONPATH:$TESTLIB:/usr/lib/python RD_PATH=$RD_PATH" TENV="PYTHONPATH=$PYTHONPATH:$TESTLIB:/usr/lib/python RD_PATH=$RD_PATH"
AC_ARG_ENABLE(vmx-support, AC_ARG_ENABLE(hvm-support,
[[ --enable-vmx-support enable hardware virtual machine assist]], [[ --enable-hvm-support enable hardware virtual machine assist]],
[ [
ENABLE_VMX=True ENABLE_HVM=True
],[ ],[
ENABLE_VMX=False ENABLE_HVM=False
]) ])
if test "x$ENABLE_VMX" = "xTrue"; then if test "x$ENABLE_HVM" = "xTrue"; then
if test "$LILO" = "no"; then if test "$LILO" = "no"; then
AC_MSG_ERROR([lilo not found AC_MSG_ERROR([lilo not found
lilo version 22.7 or greater must be installed for testing with vmx enabled.]) lilo version 22.7 or greater must be installed for testing with hvm enabled.])
else else
pass=`$LILO -V | sed -e "s/LILO version //" | awk -F "." '{if ($1 >=22 && $2 >= 7) print "true"; else print "false"}'` pass=`$LILO -V | sed -e "s/LILO version //" | awk -F "." '{if ($1 >=22 && $2 >= 7) print "true"; else print "false"}'`
if test "$pass" != "true"; then if test "$pass" != "true"; then
@@ -35,16 +35,16 @@ lilo version 22.7 or greater must be installed for testing with vmx enabled.])
fi fi
fi fi
AM_CONDITIONAL(VMX, test x$ENABLE_VMX = xTrue) AM_CONDITIONAL(HVM, test x$ENABLE_HVM = xTrue)
AC_SUBST(ENABLE_VMX) AC_SUBST(ENABLE_HVM)
AC_ARG_WITH(vmx-kernel, AC_ARG_WITH(hvm-kernel,
[[ --with-vmx-kernel=kernel Use this kernel for vmx disk.img testing]], [[ --with-hvm-kernel=kernel Use this kernel for hvm disk.img testing]],
VMXKERNEL=$withval, HVMKERNEL=$withval,
VMXKERNEL="no") HVMKERNEL="no")
dnl substitute @VMXKERNEL@ in all Makefiles dnl substitute @HVMKERNEL@ in all Makefiles
AC_SUBST(VMXKERNEL) AC_SUBST(HVMKERNEL)
AC_ARG_WITH(driver-dir, AC_ARG_WITH(driver-dir,
[[ --with-driver-dir=drvdir Look in this directory for the pcnet32 driver for the vmx disk.img. drvdir can equal key word "builtin" if driver is built into the kernel]], [[ --with-driver-dir=drvdir Look in this directory for the pcnet32 driver for the vmx disk.img. drvdir can equal key word "builtin" if driver is built into the kernel]],
+7 -7
View File
@@ -70,14 +70,14 @@ ParavirtDefaults = {"memory" : 64,
"root" : "/dev/ram0", "root" : "/dev/ram0",
"ramdisk" : getRdPath() + "/initrd.img" "ramdisk" : getRdPath() + "/initrd.img"
} }
VmxDefaults = {"memory" : 64, HVMDefaults = {"memory" : 64,
"vcpus" : 1, "vcpus" : 1,
"acpi" : 0, "acpi" : 0,
"apic" : 0, "apic" : 0,
"disk" : ["file:%s/disk.img,ioemu:%s,w" % "disk" : ["file:%s/disk.img,ioemu:%s,w" %
(getRdPath(), BLOCK_ROOT_DEV)], (getRdPath(), BLOCK_ROOT_DEV)],
"kernel" : "/usr/lib/xen/boot/vmxloader", "kernel" : "/usr/lib/xen/boot/hvmloader",
"builder" : "vmx", "builder" : "hvm",
"sdl" : 0, "sdl" : 0,
"vnc" : 0, "vnc" : 0,
"vncviewer" : 0, "vncviewer" : 0,
@@ -86,8 +86,8 @@ VmxDefaults = {"memory" : 64,
"device_model" : getDeviceModel() "device_model" : getDeviceModel()
} }
if ENABLE_VMX_SUPPORT: if ENABLE_HVM_SUPPORT:
configDefaults = VmxDefaults configDefaults = HVMDefaults
else: else:
configDefaults = ParavirtDefaults configDefaults = ParavirtDefaults
@@ -247,7 +247,7 @@ class XmTestDomain(XenDomain):
def start(self): def start(self):
XenDomain.start(self) XenDomain.start(self)
if ENABLE_VMX_SUPPORT: if ENABLE_HVM_SUPPORT:
waitForBoot() waitForBoot()
def startNow(self): def startNow(self):
@@ -271,7 +271,7 @@ if __name__ == "__main__":
print str(c) print str(c)
# c.write("/tmp/foo.conf") # c.write("/tmp/foo.conf")
+1 -1
View File
@@ -1,4 +1,4 @@
#!/usr/bin/python #!/usr/bin/python
ENABLE_VMX_SUPPORT = @ENABLE_VMX@ ENABLE_HVM_SUPPORT = @ENABLE_HVM@
+10 -10
View File
@@ -9,12 +9,12 @@ BR_IMG = $(BR_SRC)/rootfs.i386.ext2
BR_ROOT = build_i386/root BR_ROOT = build_i386/root
VMX_SCRIPT = bin/create_disk_image HVM_SCRIPT = bin/create_disk_image
XMTEST_MAJ_VER = $(shell echo @PACKAGE_VERSION@ | perl -pe 's/(\d+)\.(\d+)\.\d+/\1.\2/') XMTEST_MAJ_VER = $(shell echo @PACKAGE_VERSION@ | perl -pe 's/(\d+)\.(\d+)\.\d+/\1.\2/')
XMTEST_VER_IMG = initrd-$(XMTEST_MAJ_VER).img XMTEST_VER_IMG = initrd-$(XMTEST_MAJ_VER).img
if VMX if HVM
all: initrd.img disk.img all: initrd.img disk.img
else else
all: initrd.img all: initrd.img
@@ -44,16 +44,16 @@ initrd.img: $(XMTEST_VER_IMG)
ln -sf $(XMTEST_VER_IMG) initrd.img ln -sf $(XMTEST_VER_IMG) initrd.img
disk.img: $(XMTEST_VER_IMG) disk.img: $(XMTEST_VER_IMG)
chmod a+x $(VMX_SCRIPT) chmod a+x $(HVM_SCRIPT)
@if test ! "$(VMXKERNEL)" = "no" -a ! "$(DRVDIR)" = "no"; then \ @if test ! "$(HVMKERNEL)" = "no" -a ! "$(DRVDIR)" = "no"; then \
$(VMX_SCRIPT) -r $(XMTEST_VER_IMG) -k $(VMXKERNEL) \ $(HVM_SCRIPT) -r $(XMTEST_VER_IMG) -k $(HVMKERNEL) \
-d $(DRVDIR); \ -d $(DRVDIR); \
elif test "$(VMXKERNEL)" = "no" -a ! "$(DRVDIR)" = "no"; then \ elif test "$(HVMKERNEL)" = "no" -a ! "$(DRVDIR)" = "no"; then \
$(VMX_SCRIPT) -r $(XMTEST_VER_IMG) -d $(DRVDIR); \ $(HVM_SCRIPT) -r $(XMTEST_VER_IMG) -d $(DRVDIR); \
elif test ! "$(VMXKERNEL)" = "no" -a "$(DRVDIR)" = "no"; then \ elif test ! "$(HVMKERNEL)" = "no" -a "$(DRVDIR)" = "no"; then \
$(VMX_SCRIPT) -r $(XMTEST_VER_IMG) -k $(VMXKERNEL); \ $(HVM_SCRIPT) -r $(XMTEST_VER_IMG) -k $(HVMKERNEL); \
else \ else \
$(VMX_SCRIPT) -r $(XMTEST_VER_IMG); \ $(HVM_SCRIPT) -r $(XMTEST_VER_IMG); \
fi fi
existing: existing:
+1 -1
View File
@@ -46,7 +46,7 @@ function die()
function usage() function usage()
{ {
cat << EOU cat << EOU
Command creates a vmx guest disk image for xm-test. Command creates a hvm guest disk image for xm-test.
Usage: $0 [OPTIONS] Usage: $0 [OPTIONS]
@@ -9,8 +9,8 @@ import time
from XmTestLib import * from XmTestLib import *
if ENABLE_VMX_SUPPORT: if ENABLE_HVM_SUPPORT:
SKIP("Block-attach not supported for VMX domains") SKIP("Block-attach not supported for HVM domains")
# Create a domain (default XmTestDomain, with our ramdisk) # Create a domain (default XmTestDomain, with our ramdisk)
domain = XmTestDomain() domain = XmTestDomain()
@@ -9,8 +9,8 @@ import time
from XmTestLib import * from XmTestLib import *
if ENABLE_VMX_SUPPORT: if ENABLE_HVM_SUPPORT:
SKIP("Block-attach not supported for VMX domains") SKIP("Block-attach not supported for HVM domains")
# Create a domain (default XmTestDomain, with our ramdisk) # Create a domain (default XmTestDomain, with our ramdisk)
domain = XmTestDomain() domain = XmTestDomain()
@@ -9,8 +9,8 @@ import time
from XmTestLib import * from XmTestLib import *
if ENABLE_VMX_SUPPORT: if ENABLE_HVM_SUPPORT:
SKIP("Block-attach not supported for VMX domains") SKIP("Block-attach not supported for HVM domains")
# Create a domain (default XmTestDomain, with our ramdisk) # Create a domain (default XmTestDomain, with our ramdisk)
domain = XmTestDomain() domain = XmTestDomain()
@@ -9,8 +9,8 @@ import time
from XmTestLib import * from XmTestLib import *
if ENABLE_VMX_SUPPORT: if ENABLE_HVM_SUPPORT:
SKIP("Block-attach not supported for VMX domains") SKIP("Block-attach not supported for HVM domains")
# Create a domain (default XmTestDomain, with our ramdisk) # Create a domain (default XmTestDomain, with our ramdisk)
domain = XmTestDomain() domain = XmTestDomain()
@@ -5,8 +5,8 @@
from XmTestLib import * from XmTestLib import *
if ENABLE_VMX_SUPPORT: if ENABLE_HVM_SUPPORT:
SKIP("Block-attach not supported for VMX domains") SKIP("Block-attach not supported for HVM domains")
status, output = traceCommand("xm block-attach NOT-EXIST phy:ram1 sdb1 w") status, output = traceCommand("xm block-attach NOT-EXIST phy:ram1 sdb1 w")
@@ -9,8 +9,8 @@ import time
from XmTestLib import * from XmTestLib import *
if ENABLE_VMX_SUPPORT: if ENABLE_HVM_SUPPORT:
SKIP("Block-attach not supported for VMX domains") SKIP("Block-attach not supported for HVM domains")
# Create a domain (default XmTestDomain, with our ramdisk) # Create a domain (default XmTestDomain, with our ramdisk)
domain = XmTestDomain() domain = XmTestDomain()
@@ -9,8 +9,8 @@ import time
from XmTestLib import * from XmTestLib import *
if ENABLE_VMX_SUPPORT: if ENABLE_HVM_SUPPORT:
SKIP("Block-attach not supported for VMX domains") SKIP("Block-attach not supported for HVM domains")
# Create a domain (default XmTestDomain, with our ramdisk) # Create a domain (default XmTestDomain, with our ramdisk)
domain = XmTestDomain() domain = XmTestDomain()
@@ -9,8 +9,8 @@ import time
from XmTestLib import * from XmTestLib import *
if ENABLE_VMX_SUPPORT: if ENABLE_HVM_SUPPORT:
SKIP("Block-attach not supported for VMX domains") SKIP("Block-attach not supported for HVM domains")
# Create a domain (default XmTestDomain, with our ramdisk) # Create a domain (default XmTestDomain, with our ramdisk)
domain = XmTestDomain() domain = XmTestDomain()
@@ -46,8 +46,8 @@ def dettach(devname):
return 0, None return 0, None
if ENABLE_VMX_SUPPORT: if ENABLE_HVM_SUPPORT:
SKIP("Block-attach not supported for VMX domains") SKIP("Block-attach not supported for HVM domains")
# Create a domain (default XmTestDomain, with our ramdisk) # Create a domain (default XmTestDomain, with our ramdisk)
domain = XmTestDomain() domain = XmTestDomain()
@@ -5,8 +5,8 @@
from XmTestLib import * from XmTestLib import *
if ENABLE_VMX_SUPPORT: if ENABLE_HVM_SUPPORT:
SKIP("Block-attach not supported for VMX domains") SKIP("Block-attach not supported for HVM domains")
# Mount /dev/ram0 # Mount /dev/ram0
@@ -5,8 +5,8 @@
from XmTestLib import * from XmTestLib import *
if ENABLE_VMX_SUPPORT: if ENABLE_HVM_SUPPORT:
SKIP("Block-attach not supported for VMX domains") SKIP("Block-attach not supported for HVM domains")
config = {"disk":"phy:/dev/ram0,hda1,w"} config = {"disk":"phy:/dev/ram0,hda1,w"}
@@ -5,8 +5,8 @@
from XmTestLib import * from XmTestLib import *
if ENABLE_VMX_SUPPORT: if ENABLE_HVM_SUPPORT:
SKIP("Block-detach not supported for VMX domains") SKIP("Block-detach not supported for HVM domains")
config = {"disk":"phy:/dev/ram0,hda1,w"} config = {"disk":"phy:/dev/ram0,hda1,w"}
domain = XmTestDomain(extraConfig=config) domain = XmTestDomain(extraConfig=config)
@@ -5,8 +5,8 @@
from XmTestLib import * from XmTestLib import *
if ENABLE_VMX_SUPPORT: if ENABLE_HVM_SUPPORT:
SKIP("Block-detach not supported for VMX domains") SKIP("Block-detach not supported for HVM domains")
domain = XmTestDomain() domain = XmTestDomain()
@@ -7,8 +7,8 @@
from XmTestLib import * from XmTestLib import *
if ENABLE_VMX_SUPPORT: if ENABLE_HVM_SUPPORT:
SKIP("Block-detach not supported for VMX domains") SKIP("Block-detach not supported for HVM domains")
domain = XmTestDomain() domain = XmTestDomain()
@@ -5,8 +5,8 @@
from XmTestLib import * from XmTestLib import *
if ENABLE_VMX_SUPPORT: if ENABLE_HVM_SUPPORT:
SKIP("Block-detach not supported for VMX domains") SKIP("Block-detach not supported for HVM domains")
config = {"disk":"phy:/dev/ram0,hda1,w"} config = {"disk":"phy:/dev/ram0,hda1,w"}
domain = XmTestDomain(extraConfig=config) domain = XmTestDomain(extraConfig=config)
@@ -26,8 +26,8 @@ def checkXmLongList(domain):
else: else:
return False return False
if ENABLE_VMX_SUPPORT: if ENABLE_HVM_SUPPORT:
SKIP("Block-detach not supported for VMX domains") SKIP("Block-detach not supported for HVM domains")
domain = XmTestDomain() domain = XmTestDomain()
@@ -8,8 +8,8 @@
from XmTestLib import * from XmTestLib import *
if ENABLE_VMX_SUPPORT: if ENABLE_HVM_SUPPORT:
SKIP("Block-list not supported for VMX domains") SKIP("Block-list not supported for HVM domains")
config = {"disk":"phy:/dev/ram0,hda1,w"} config = {"disk":"phy:/dev/ram0,hda1,w"}
domain = XmTestDomain(extraConfig=config) domain = XmTestDomain(extraConfig=config)
@@ -8,8 +8,8 @@
from XmTestLib import * from XmTestLib import *
if ENABLE_VMX_SUPPORT: if ENABLE_HVM_SUPPORT:
SKIP("Block-list not supported for VMX domains") SKIP("Block-list not supported for HVM domains")
domain = XmTestDomain() domain = XmTestDomain()
@@ -8,8 +8,8 @@
from XmTestLib import * from XmTestLib import *
if ENABLE_VMX_SUPPORT: if ENABLE_HVM_SUPPORT:
SKIP("Block-list not supported for VMX domains") SKIP("Block-list not supported for HVM domains")
config = {"disk":"phy:/dev/ram0,hda1,w"} config = {"disk":"phy:/dev/ram0,hda1,w"}
domain = XmTestDomain(extraConfig=config) domain = XmTestDomain(extraConfig=config)
@@ -8,8 +8,8 @@
from XmTestLib import * from XmTestLib import *
if ENABLE_VMX_SUPPORT: if ENABLE_HVM_SUPPORT:
SKIP("Block-list not supported for VMX domains") SKIP("Block-list not supported for HVM domains")
domain = XmTestDomain() domain = XmTestDomain()
@@ -5,8 +5,8 @@
from XmTestLib import * from XmTestLib import *
if ENABLE_VMX_SUPPORT: if ENABLE_HVM_SUPPORT:
SKIP("Block-list not supported for VMX domains") SKIP("Block-list not supported for HVM domains")
domain = XmTestDomain() domain = XmTestDomain()
@@ -17,7 +17,7 @@ rdpath = getRdPath()
# if verbose: # if verbose:
# print "Using %s" % output # print "Using %s" % output
if ENABLE_VMX_SUPPORT: if ENABLE_HVM_SUPPORT:
domain = XmTestDomain(name="14_create_blockroot") domain = XmTestDomain(name="14_create_blockroot")
else: else:
config = {"memory" : "64", config = {"memory" : "64",
@@ -8,8 +8,8 @@ import re
from XmTestLib import * from XmTestLib import *
if ENABLE_VMX_SUPPORT: if ENABLE_HVM_SUPPORT:
SKIP("Mem-max not supported for VMX domains") SKIP("Mem-max not supported for HVM domains")
status, output = traceCommand("xm mem-max") status, output = traceCommand("xm mem-max")
eyecatcher = "Error:" eyecatcher = "Error:"
@@ -20,8 +20,8 @@ import re
import time import time
from XmTestLib import * from XmTestLib import *
if ENABLE_VMX_SUPPORT: if ENABLE_HVM_SUPPORT:
SKIP("Mem-set not supported for VMX domains") SKIP("Mem-set not supported for HVM domains")
# Create a domain (default XmTestDomain, with our ramdisk) # Create a domain (default XmTestDomain, with our ramdisk)
domain = XmTestDomain() domain = XmTestDomain()
@@ -18,8 +18,8 @@ import re
from XmTestLib import * from XmTestLib import *
if ENABLE_VMX_SUPPORT: if ENABLE_HVM_SUPPORT:
SKIP("Mem-set not supported for VMX domains") SKIP("Mem-set not supported for HVM domains")
# destroy no parm input - negative test # destroy no parm input - negative test
status, output = traceCommand("xm mem-set") status, output = traceCommand("xm mem-set")
@@ -8,8 +8,8 @@ import re
from XmTestLib import * from XmTestLib import *
if ENABLE_VMX_SUPPORT: if ENABLE_HVM_SUPPORT:
SKIP("Mem-set not supported for VMX domains") SKIP("Mem-set not supported for HVM domains")
domain = XmTestDomain() domain = XmTestDomain()
@@ -5,8 +5,8 @@
from XmTestLib import * from XmTestLib import *
if ENABLE_VMX_SUPPORT: if ENABLE_HVM_SUPPORT:
SKIP("Mem-set not supported for VMX domains") SKIP("Mem-set not supported for HVM domains")
domain = XmTestDomain() domain = XmTestDomain()
@@ -17,8 +17,8 @@ import commands
from XmTestLib import * from XmTestLib import *
if ENABLE_VMX_SUPPORT: if ENABLE_HVM_SUPPORT:
SKIP("Migrate currently not supported for VMX domains") SKIP("Migrate currently not supported for HVM domains")
# Create a domain (default XmTestDomain, with our ramdisk) # Create a domain (default XmTestDomain, with our ramdisk)
domain = XmTestDomain() domain = XmTestDomain()
@@ -8,8 +8,8 @@ import sys
from XmTestLib import * from XmTestLib import *
from network_utils import * from network_utils import *
if ENABLE_VMX_SUPPORT: if ENABLE_HVM_SUPPORT:
SKIP("Network-attach not supported for VMX domains") SKIP("Network-attach not supported for HVM domains")
# Create a domain (default XmTestDomain, with our ramdisk) # Create a domain (default XmTestDomain, with our ramdisk)
domain = XmTestDomain() domain = XmTestDomain()
@@ -10,8 +10,8 @@ import time
from XmTestLib import * from XmTestLib import *
from network_utils import * from network_utils import *
if ENABLE_VMX_SUPPORT: if ENABLE_HVM_SUPPORT:
SKIP("Network-attach not supported for VMX domains") SKIP("Network-attach not supported for HVM domains")
# Create a domain (default XmTestDomain, with our ramdisk) # Create a domain (default XmTestDomain, with our ramdisk)
domain = XmTestDomain() domain = XmTestDomain()
@@ -10,8 +10,8 @@ import time
from XmTestLib import * from XmTestLib import *
from network_utils import * from network_utils import *
if ENABLE_VMX_SUPPORT: if ENABLE_HVM_SUPPORT:
SKIP("Network-attach not supported for VMX domains") SKIP("Network-attach not supported for HVM domains")
# Create a domain (default XmTestDomain, with our ramdisk) # Create a domain (default XmTestDomain, with our ramdisk)
domain = XmTestDomain() domain = XmTestDomain()
@@ -12,8 +12,8 @@ import time
from XmTestLib import * from XmTestLib import *
if ENABLE_VMX_SUPPORT: if ENABLE_HVM_SUPPORT:
SKIP("Restore currently not supported for VMX domains") SKIP("Restore currently not supported for HVM domains")
domain = XmTestDomain() domain = XmTestDomain()
@@ -12,8 +12,8 @@ import re
from XmTestLib import * from XmTestLib import *
if ENABLE_VMX_SUPPORT: if ENABLE_HVM_SUPPORT:
SKIP("Restore currently not supported for VMX domains") SKIP("Restore currently not supported for HVM domains")
status, output = traceCommand("xm restore -x") status, output = traceCommand("xm restore -x")
eyecatcher1 = "Error:" eyecatcher1 = "Error:"
@@ -12,8 +12,8 @@ import re
from XmTestLib import * from XmTestLib import *
if ENABLE_VMX_SUPPORT: if ENABLE_HVM_SUPPORT:
SKIP("Restore currently not supported for VMX domains") SKIP("Restore currently not supported for HVM domains")
status, output = traceCommand("xm restore /tmp/NON_EXIST") status, output = traceCommand("xm restore /tmp/NON_EXIST")
eyecatcher1 = "Error:" eyecatcher1 = "Error:"
@@ -7,8 +7,8 @@ from XmTestLib import *
import re import re
if ENABLE_VMX_SUPPORT: if ENABLE_HVM_SUPPORT:
SKIP("Restore currently not supported for VMX domains") SKIP("Restore currently not supported for HVM domains")
config = {"disk": ["phy:/dev/ram0,hda1,w", "phy:/dev/ram1,hdb2,w"], config = {"disk": ["phy:/dev/ram0,hda1,w", "phy:/dev/ram1,hdb2,w"],
"vif": ['', '']} "vif": ['', '']}
@@ -7,8 +7,8 @@ import time
from XmTestLib import * from XmTestLib import *
if ENABLE_VMX_SUPPORT: if ENABLE_HVM_SUPPORT:
SKIP("Save currently not supported for VMX domains") SKIP("Save currently not supported for HVM domains")
domain = XmTestDomain() domain = XmTestDomain()
@@ -12,8 +12,8 @@ import re
from XmTestLib import * from XmTestLib import *
if ENABLE_VMX_SUPPORT: if ENABLE_HVM_SUPPORT:
SKIP("Save currently not supported for VMX domains") SKIP("Save currently not supported for HVM domains")
status, output = traceCommand("xm save -x") status, output = traceCommand("xm save -x")
eyecatcher1 = "Error:" eyecatcher1 = "Error:"
@@ -10,8 +10,8 @@ import time
from XmTestLib import * from XmTestLib import *
if ENABLE_VMX_SUPPORT: if ENABLE_HVM_SUPPORT:
SKIP("Save currently not supported for VMX domains") SKIP("Save currently not supported for HVM domains")
domain = XmTestDomain() domain = XmTestDomain()
@@ -9,8 +9,8 @@ import re
from XmTestLib import * from XmTestLib import *
if ENABLE_VMX_SUPPORT: if ENABLE_HVM_SUPPORT:
SKIP("Sysrq not supported for VMX domains") SKIP("Sysrq not supported for HVM domains")
status, output = traceCommand("xm sysrq does_not_exist s"); status, output = traceCommand("xm sysrq does_not_exist s");
@@ -9,8 +9,8 @@ import time
from XmTestLib import * from XmTestLib import *
if ENABLE_VMX_SUPPORT: if ENABLE_HVM_SUPPORT:
SKIP("Sysrq not supported for VMX domains") SKIP("Sysrq not supported for HVM domains")
# Create a domain (default XmTestDomain, with our ramdisk) # Create a domain (default XmTestDomain, with our ramdisk)
domain = XmTestDomain() domain = XmTestDomain()
@@ -7,8 +7,8 @@ from XmTestLib import *
import time import time
if ENABLE_VMX_SUPPORT: if ENABLE_HVM_SUPPORT:
SKIP("Sysrq not supported for VMX domains") SKIP("Sysrq not supported for HVM domains")
domain = XmTestDomain() domain = XmTestDomain()
+3
View File
@@ -53,6 +53,9 @@ else
CFLAGS += -g -DVERBOSE CFLAGS += -g -DVERBOSE
endif endif
# There is no real reason to compile without it
CFLAGS += -g
ifeq ($(crash_debug),y) ifeq ($(crash_debug),y)
CFLAGS += -g -DCRASH_DEBUG CFLAGS += -g -DCRASH_DEBUG
endif endif
+16 -8
View File
@@ -15,7 +15,7 @@ OBJS = xensetup.o setup.o time.o irq.o process.o smp.o \
OBJS += vmx_init.o vmx_virt.o vmx_vcpu.o vmx_process.o vmx_vsa.o vmx_ivt.o\ OBJS += vmx_init.o vmx_virt.o vmx_vcpu.o vmx_process.o vmx_vsa.o vmx_ivt.o\
vmx_phy_mode.o vmx_utility.o vmx_interrupt.o vmx_entry.o vmmu.o \ vmx_phy_mode.o vmx_utility.o vmx_interrupt.o vmx_entry.o vmmu.o \
vtlb.o mmio.o vlsapic.o vmx_hypercall.o mm.o vmx_support.o \ vtlb.o mmio.o vlsapic.o vmx_hypercall.o mm.o vmx_support.o \
pal_emul.o vmx_irq_ia64.o vmx_vioapic.o pal_emul.o vmx_irq_ia64.o hvm_vioapic.o
# lib files from xen/arch/ia64/linux/ (linux/arch/ia64/lib) # lib files from xen/arch/ia64/linux/ (linux/arch/ia64/lib)
OBJS += bitop.o clear_page.o flush.o copy_page_mck.o \ OBJS += bitop.o clear_page.o flush.o copy_page_mck.o \
@@ -94,13 +94,19 @@ $(BASEDIR)/include/asm-ia64/.offsets.h.stamp:
|| ln -s $(BASEDIR)/include/xen $(BASEDIR)/include/linux || ln -s $(BASEDIR)/include/xen $(BASEDIR)/include/linux
[ -e $(BASEDIR)/include/asm-ia64/xen ] \ [ -e $(BASEDIR)/include/asm-ia64/xen ] \
|| ln -s $(BASEDIR)/include/asm-ia64/linux $(BASEDIR)/include/asm-ia64/xen || ln -s $(BASEDIR)/include/asm-ia64/linux $(BASEDIR)/include/asm-ia64/xen
# Link to DM file in Xen for ia64/vti # Link to HVM files in Xen for ia64/vti
[ -e $(BASEDIR)/include/asm-ia64/vmx_vpic.h ] \ [ -e $(BASEDIR)/include/asm-ia64/hvm ] \
|| ln -s ../../include/asm-x86/vmx_vpic.h $(BASEDIR)/include/asm-ia64/vmx_vpic.h || mkdir $(BASEDIR)/include/asm-ia64/hvm
[ -e $(BASEDIR)/include/asm-ia64/vmx_vioapic.h ] \ [ -e $(BASEDIR)/include/asm-ia64/hvm/support.h ] \
|| ln -s ../../include/asm-x86/vmx_vioapic.h $(BASEDIR)/include/asm-ia64/vmx_vioapic.h || ln -s ../../../include/asm-x86/hvm/support.h $(BASEDIR)/include/asm-ia64/hvm/support.h
[ -e $(BASEDIR)/arch/ia64/vmx/vmx_vioapic.c ] \ [ -e $(BASEDIR)/include/asm-ia64/hvm/io.h ] \
|| ln -s ../../../arch/x86/dm/vmx_vioapic.c $(BASEDIR)/arch/ia64/vmx/vmx_vioapic.c || ln -s ../../../include/asm-x86/hvm/io.h $(BASEDIR)/include/asm-ia64/hvm/io.h
[ -e $(BASEDIR)/include/asm-ia64/hvm/vpic.h ] \
|| ln -s ../../../include/asm-x86/hvm/vpic.h $(BASEDIR)/include/asm-ia64/hvm/vpic.h
[ -e $(BASEDIR)/include/asm-ia64/hvm/vioapic.h ] \
|| ln -s ../../../include/asm-x86/hvm/vioapic.h $(BASEDIR)/include/asm-ia64/hvm/vioapic.h
[ -e $(BASEDIR)/arch/ia64/vmx/hvm_vioapic.c ] \
|| ln -s ../../../arch/x86/hvm/vioapic.c $(BASEDIR)/arch/ia64/vmx/hvm_vioapic.c
# Solve circular reference on asm-offsets.h # Solve circular reference on asm-offsets.h
[ -f $(BASEDIR)/include/asm-ia64/asm-offsets.h ] \ [ -f $(BASEDIR)/include/asm-ia64/asm-offsets.h ] \
|| echo "#define IA64_TASK_SIZE 0" > $(BASEDIR)/include/asm-ia64/asm-offsets.h || echo "#define IA64_TASK_SIZE 0" > $(BASEDIR)/include/asm-ia64/asm-offsets.h
@@ -136,6 +142,8 @@ __umodsi3.o: idiv32.S
clean: clean:
rm -f *.o *~ core xen.lds.s $(BASEDIR)/include/asm-ia64/.offsets.h.stamp asm-offsets.s map.out rm -f *.o *~ core xen.lds.s $(BASEDIR)/include/asm-ia64/.offsets.h.stamp asm-offsets.s map.out
rm -f asm-xsi-offsets.s $(BASEDIR)/include/asm-ia64/asm-xsi-offsets.h rm -f asm-xsi-offsets.s $(BASEDIR)/include/asm-ia64/asm-xsi-offsets.h
rm -f $(BASEDIR)/arch/ia64/vmx/hvm_*.c
rm -rf $(BASEDIR)/include/asm-ia64/hvm
rm -f linux/lib/*.o rm -f linux/lib/*.o
.PHONY: default clean .PHONY: default clean
+1 -1
View File
@@ -207,7 +207,7 @@ static void legacy_io_access(VCPU *vcpu, u64 pa, u64 *val, size_t s, int dir)
extern struct vmx_mmio_handler vioapic_mmio_handler; extern struct vmx_mmio_handler vioapic_mmio_handler;
static void mmio_access(VCPU *vcpu, u64 src_pa, u64 *dest, size_t s, int ma, int dir) static void mmio_access(VCPU *vcpu, u64 src_pa, u64 *dest, size_t s, int ma, int dir)
{ {
struct virutal_platform_def *v_plat; struct virtual_platform_def *v_plat;
//mmio_type_t iot; //mmio_type_t iot;
unsigned long iot; unsigned long iot;
struct vmx_mmio_handler *vioapic_handler = &vioapic_mmio_handler; struct vmx_mmio_handler *vioapic_handler = &vioapic_mmio_handler;
+7 -7
View File
@@ -38,7 +38,7 @@
#include <asm/vmx_pal_vsa.h> #include <asm/vmx_pal_vsa.h>
#include <asm/kregs.h> #include <asm/kregs.h>
#include <asm/vmx_platform.h> #include <asm/vmx_platform.h>
#include <asm/vmx_vioapic.h> #include <asm/hvm/vioapic.h>
//u64 fire_itc; //u64 fire_itc;
//u64 fire_itc2; //u64 fire_itc2;
@@ -278,7 +278,7 @@ void vmx_virq_line_assist(struct vcpu *v)
do { do {
irqs = *(volatile uint16_t*)virq_line; irqs = *(volatile uint16_t*)virq_line;
} while ((uint16_t)cmpxchg(virq_line, irqs, 0) != irqs); } while ((uint16_t)cmpxchg(virq_line, irqs, 0) != irqs);
vmx_vioapic_do_irqs(v->domain, irqs); hvm_vioapic_do_irqs(v->domain, irqs);
} }
virq_line = &spg->pic_clear_irr; virq_line = &spg->pic_clear_irr;
@@ -286,7 +286,7 @@ void vmx_virq_line_assist(struct vcpu *v)
do { do {
irqs = *(volatile uint16_t*)virq_line; irqs = *(volatile uint16_t*)virq_line;
} while ((uint16_t)cmpxchg(virq_line, irqs, 0) != irqs); } while ((uint16_t)cmpxchg(virq_line, irqs, 0) != irqs);
vmx_vioapic_do_irqs_clear(v->domain, irqs); hvm_vioapic_do_irqs_clear(v->domain, irqs);
} }
} }
@@ -300,7 +300,7 @@ void vmx_virq_line_init(struct domain *d)
spg->pic_clear_irr = 0; spg->pic_clear_irr = 0;
} }
int ioapic_match_logical_addr(vmx_vioapic_t *s, int number, uint16_t dest) int ioapic_match_logical_addr(hvm_vioapic_t *s, int number, uint16_t dest)
{ {
return (VLAPIC_ID(s->lapic_info[number]) == dest); return (VLAPIC_ID(s->lapic_info[number]) == dest);
} }
@@ -311,14 +311,14 @@ struct vlapic* apic_round_robin(struct domain *d,
uint32_t bitmap) uint32_t bitmap)
{ {
uint8_t bit; uint8_t bit;
vmx_vioapic_t *s; hvm_vioapic_t *s;
if (!bitmap) { if (!bitmap) {
printk("<apic_round_robin> no bit on bitmap\n"); printk("<apic_round_robin> no bit on bitmap\n");
return NULL; return NULL;
} }
s = &d->arch.vmx_platform.vmx_vioapic; s = &d->arch.vmx_platform.vioapic;
for (bit = 0; bit < s->lapic_count; bit++) { for (bit = 0; bit < s->lapic_count; bit++) {
if (bitmap & (1 << bit)) if (bitmap & (1 << bit))
return s->lapic_info[bit]; return s->lapic_info[bit];
@@ -351,7 +351,7 @@ void vlsapic_reset(VCPU *vcpu)
#ifdef V_IOSAPIC_READY #ifdef V_IOSAPIC_READY
vcpu->arch.arch_vmx.vlapic.vcpu = vcpu; vcpu->arch.arch_vmx.vlapic.vcpu = vcpu;
vmx_vioapic_add_lapic(&vcpu->arch.arch_vmx.vlapic, vcpu); hvm_vioapic_add_lapic(&vcpu->arch.arch_vmx.vlapic, vcpu);
#endif #endif
DPRINTK("VLSAPIC inservice base=%lp\n", &VLSAPIC_INSVC(vcpu,0) ); DPRINTK("VLSAPIC inservice base=%lp\n", &VLSAPIC_INSVC(vcpu,0) );
} }
+2 -2
View File
@@ -48,7 +48,7 @@
#include <asm/vmx.h> #include <asm/vmx.h>
#include <xen/mm.h> #include <xen/mm.h>
#include <public/arch-ia64.h> #include <public/arch-ia64.h>
#include <asm/vmx_vioapic.h> #include <asm/hvm/vioapic.h>
/* Global flag to identify whether Intel vmx feature is on */ /* Global flag to identify whether Intel vmx feature is on */
u32 vmx_enabled = 0; u32 vmx_enabled = 0;
@@ -394,7 +394,7 @@ void vmx_setup_platform(struct domain *d, struct vcpu_guest_context *c)
vmx_virq_line_init(d); vmx_virq_line_init(d);
/* Initialize iosapic model within hypervisor */ /* Initialize iosapic model within hypervisor */
vmx_vioapic_init(d); hvm_vioapic_init(d);
} }
+1 -1
View File
@@ -198,7 +198,7 @@ vmx_vcpu_get_vtlb(VCPU *vcpu)
} }
struct virutal_platform_def * struct virtual_platform_def *
vmx_vcpu_get_plat(VCPU *vcpu) vmx_vcpu_get_plat(VCPU *vcpu)
{ {
return &(vcpu->domain->arch.vmx_platform); return &(vcpu->domain->arch.vmx_platform);
+12 -2
View File
@@ -4,10 +4,14 @@ include $(BASEDIR)/Rules.mk
OBJS += $(patsubst %.S,%.o,$(wildcard $(TARGET_SUBARCH)/*.S)) OBJS += $(patsubst %.S,%.o,$(wildcard $(TARGET_SUBARCH)/*.S))
OBJS += $(patsubst %.c,%.o,$(wildcard $(TARGET_SUBARCH)/*.c)) OBJS += $(patsubst %.c,%.o,$(wildcard $(TARGET_SUBARCH)/*.c))
OBJS += $(patsubst %.c,%.o,$(wildcard acpi/*.c)) OBJS += $(patsubst %.c,%.o,$(wildcard acpi/*.c))
OBJS += $(patsubst %.c,%.o,$(wildcard dm/*.c))
OBJS += $(patsubst %.c,%.o,$(wildcard mtrr/*.c)) OBJS += $(patsubst %.c,%.o,$(wildcard mtrr/*.c))
OBJS += $(patsubst %.c,%.o,$(wildcard genapic/*.c)) OBJS += $(patsubst %.c,%.o,$(wildcard genapic/*.c))
OBJS += $(patsubst %.c,%.o,$(wildcard cpu/*.c)) OBJS += $(patsubst %.c,%.o,$(wildcard cpu/*.c))
OBJS += $(patsubst %.c,%.o,$(wildcard hvm/*.c))
OBJS += $(patsubst %.c,%.o,$(wildcard hvm/vmx/*.c))
OBJS += $(patsubst %.S,%.o,$(wildcard hvm/vmx/$(TARGET_SUBARCH)/*.S))
OBJS += $(patsubst %.c,%.o,$(wildcard hvm/svm/*.c))
OBJS += $(patsubst %.S,%.o,$(wildcard hvm/svm/$(TARGET_SUBARCH)/*.S))
ifeq ($(TARGET_SUBARCH),x86_64) ifeq ($(TARGET_SUBARCH),x86_64)
OBJS := $(subst cpu/centaur.o,,$(OBJS)) OBJS := $(subst cpu/centaur.o,,$(OBJS))
@@ -74,9 +78,15 @@ clean:
rm -f x86_64/*.o x86_64/*~ x86_64/core rm -f x86_64/*.o x86_64/*~ x86_64/core
rm -f mtrr/*.o mtrr/*~ mtrr/core rm -f mtrr/*.o mtrr/*~ mtrr/core
rm -f acpi/*.o acpi/*~ acpi/core rm -f acpi/*.o acpi/*~ acpi/core
rm -f dm/*.o dm/*~ dm/core
rm -f genapic/*.o genapic/*~ genapic/core rm -f genapic/*.o genapic/*~ genapic/core
rm -f cpu/*.o cpu/*~ cpu/core rm -f cpu/*.o cpu/*~ cpu/core
rm -f hvm/*.o hvm/*~ hvm/core
rm -f hvm/vmx/*.o hvm/vmx/*~ hvm/vmx/core
rm -f hvm/vmx/x86_32/*.o hvm/vmx/x86_32/*~ hvm/vmx/x86_32/core
rm -f hvm/vmx/x86_64/*.o hvm/vmx/x86_64/*~ hvm/vmx/x86_64/core
rm -f hvm/svm/*.o hvm/svm/*~ hvm/svm/core
rm -f hvm/svm/x86_32/*.o hvm/svm/x86_32/*~ hvm/svm/x86_32/core
rm -f hvm/svm/x86_64/*.o hvm/svm/x86_64/*~ hvm/svm/x86_64/core
rm -f xen.lds rm -f xen.lds
.PHONY: default clean .PHONY: default clean
+113
View File
@@ -3,12 +3,20 @@
#include <xen/bitops.h> #include <xen/bitops.h>
#include <xen/mm.h> #include <xen/mm.h>
#include <xen/smp.h> #include <xen/smp.h>
#include <xen/sched.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/msr.h> #include <asm/msr.h>
#include <asm/processor.h> #include <asm/processor.h>
#include <asm/hvm/vcpu.h>
#include <asm/hvm/support.h>
#include "cpu.h" #include "cpu.h"
#define AMD_C1_CLOCK_RAMP 0x80000084
#define AMD_ADVPM_TSC_INVARIANT 0x80000007
/* /*
* amd_flush_filter={on,off}. Forcibly Enable or disable the TLB flush * amd_flush_filter={on,off}. Forcibly Enable or disable the TLB flush
* filter on AMD 64-bit processors. * filter on AMD 64-bit processors.
@@ -41,6 +49,99 @@ custom_param("amd_flush_filter", flush_filter);
extern void vide(void); extern void vide(void);
__asm__(".text\n.align 4\nvide: ret"); __asm__(".text\n.align 4\nvide: ret");
/*
* Check if C1-Clock ramping enabled in PMM7.CpuLowPwrEnh
* On 8th-Generation cores only. Assume BIOS has setup
* all Northbridges equivalently.
*/
static int c1_ramp_8gen(void)
{
u32 l;
/* Read dev=0x18, function = 3, offset=0x87 */
l = AMD_C1_CLOCK_RAMP;
/* fill in dev (18) + function (3) */
/* direct cfc/cf8 should be safe here */
l += (((0x18) << 3) + 0x3) << 8;
outl(l, 0xcf8);
return (1 & (inl(0xcfc) >> 24));
}
/*
* returns TRUE if ok to use TSC
*/
static int use_amd_tsc(struct cpuinfo_x86 *c)
{
if (c->x86 < 0xf) {
/*
* TSC drift doesn't exist on 7th Gen or less
* However, OS still needs to consider effects
* of P-state changes on TSC
*/
return 1;
} else if ( cpuid_edx(AMD_ADVPM_TSC_INVARIANT) & 0x100 ) {
/*
* CPUID.AdvPowerMgmtInfo.TscInvariant
* EDX bit 8, 8000_0007
* Invariant TSC on 8th Gen or newer, use it
* (assume all cores have invariant TSC)
*/
return 1;
} else if ((mp_get_num_processors() == 1) && (c->x86_num_cores == 1)) {
/*
* OK to use TSC on uni-processor-uni-core
* However, OS still needs to consider effects
* of P-state changes on TSC
*/
return 1;
} else if ( (mp_get_num_processors() == 1) && (c->x86 == 0x0f)
&& !c1_ramp_8gen()) {
/*
* Use TSC on 8th Gen uni-proc with C1_ramp off
* However, OS still needs to consider effects
* of P-state changes on TSC
*/
return 1;
} else {
return 0;
}
}
/*
* Disable C1-Clock ramping if enabled in PMM7.CpuLowPwrEnh
* On 8th-Generation cores only. Assume BIOS has setup
* all Northbridges equivalently.
*/
static void amd_disable_c1_ramping(void)
{
u32 l, h;
int i;
for (i=0; i < NR_CPUS;i++) {
/* Read from the Northbridge for Node x. until we get invalid data */
/* fill in dev (18 + cpu#) + function (3) */
l = AMD_C1_CLOCK_RAMP + ((((0x18 + i) << 3) + 0x3) << 8);
/* direct cfc/cf8 should be safe here */
outl(l, 0xcf8);
h = inl(0xcfc);
if (h != 0xFFFFFFFF) {
h &= 0xFCFFFFFF; /* clears pmm7[1:0] */
outl(l, 0xcf8);
outl(h, 0xcfc);
printk ("AMD: Disabling C1 Clock Ramping Node #%x\n",i);
}
else {
i = NR_CPUS;
}
}
return;
}
static void __init init_amd(struct cpuinfo_x86 *c) static void __init init_amd(struct cpuinfo_x86 *c)
{ {
u32 l, h; u32 l, h;
@@ -245,6 +346,18 @@ static void __init init_amd(struct cpuinfo_x86 *c)
printk(KERN_INFO "CPU %d(%d) -> Core %d\n", printk(KERN_INFO "CPU %d(%d) -> Core %d\n",
cpu, c->x86_num_cores, cpu_core_id[cpu]); cpu, c->x86_num_cores, cpu_core_id[cpu]);
} }
#endif
/*
* Prevent TSC drift in non single-processor, single-core platforms
*/
if ( !use_amd_tsc(c) && (c->x86 == 0x0f) && c1_ramp_8gen() &&
(smp_processor_id() == 0)) {
/* Disable c1 Clock Ramping on all cores */
amd_disable_c1_ramping();
}
#ifdef CONFIG_SVM
start_svm();
#endif #endif
} }
+3 -1
View File
@@ -10,7 +10,9 @@
#include <asm/mpspec.h> #include <asm/mpspec.h>
#include <asm/apic.h> #include <asm/apic.h>
#include <mach_apic.h> #include <mach_apic.h>
#include <asm/vmx_vmcs.h> #include <asm/hvm/vpit.h>
#include <asm/hvm/vcpu.h>
#include <asm/hvm/support.h>
#include "cpu.h" #include "cpu.h"
+7 -8
View File
@@ -20,6 +20,8 @@
#include <xen/iocap.h> #include <xen/iocap.h>
#include <asm/shadow.h> #include <asm/shadow.h>
#include <asm/irq.h> #include <asm/irq.h>
#include <asm/hvm/hvm.h>
#include <asm/hvm/support.h>
#include <asm/processor.h> #include <asm/processor.h>
#include <public/sched_ctl.h> #include <public/sched_ctl.h>
@@ -448,15 +450,12 @@ long arch_do_dom0_op(struct dom0_op *op, struct dom0_op *u_dom0_op)
void arch_getdomaininfo_ctxt( void arch_getdomaininfo_ctxt(
struct vcpu *v, struct vcpu_guest_context *c) struct vcpu *v, struct vcpu_guest_context *c)
{ {
extern void save_vmx_cpu_user_regs(struct cpu_user_regs *);
memcpy(c, &v->arch.guest_context, sizeof(*c)); memcpy(c, &v->arch.guest_context, sizeof(*c));
if ( VMX_DOMAIN(v) ) if ( HVM_DOMAIN(v) )
{ {
save_vmx_cpu_user_regs(&c->user_regs); hvm_store_cpu_guest_regs(v, &c->user_regs);
__vmread(CR0_READ_SHADOW, &c->ctrlreg[0]); hvm_store_cpu_guest_ctrl_regs(v, c->ctrlreg);
__vmread(CR4_READ_SHADOW, &c->ctrlreg[4]);
} }
else else
{ {
@@ -470,8 +469,8 @@ void arch_getdomaininfo_ctxt(
c->flags |= VGCF_I387_VALID; c->flags |= VGCF_I387_VALID;
if ( KERNEL_MODE(v, &v->arch.guest_context.user_regs) ) if ( KERNEL_MODE(v, &v->arch.guest_context.user_regs) )
c->flags |= VGCF_IN_KERNEL; c->flags |= VGCF_IN_KERNEL;
if (VMX_DOMAIN(v)) if ( HVM_DOMAIN(v) )
c->flags |= VGCF_VMX_GUEST; c->flags |= VGCF_HVM_GUEST;
c->ctrlreg[3] = pagetable_get_paddr(v->arch.guest_table); c->ctrlreg[3] = pagetable_get_paddr(v->arch.guest_table);
+24 -21
View File
@@ -35,7 +35,8 @@
#include <asm/shadow.h> #include <asm/shadow.h>
#include <xen/console.h> #include <xen/console.h>
#include <xen/elf.h> #include <xen/elf.h>
#include <asm/vmx.h> #include <asm/hvm/hvm.h>
#include <asm/hvm/support.h>
#include <asm/msr.h> #include <asm/msr.h>
#include <xen/kernel.h> #include <xen/kernel.h>
#include <xen/multicall.h> #include <xen/multicall.h>
@@ -153,8 +154,7 @@ void machine_restart(char * __unused)
*/ */
smp_send_stop(); smp_send_stop();
disable_IO_APIC(); disable_IO_APIC();
hvm_disable();
stop_vmx();
/* Rebooting needs to touch the page at absolute address 0. */ /* Rebooting needs to touch the page at absolute address 0. */
*((unsigned short *)__va(0x472)) = reboot_mode; *((unsigned short *)__va(0x472)) = reboot_mode;
@@ -354,26 +354,26 @@ int arch_set_info_guest(
* #GP. If DS, ES, FS, GS are DPL 0 then they'll be cleared automatically. * #GP. If DS, ES, FS, GS are DPL 0 then they'll be cleared automatically.
* If SS RPL or DPL differs from CS RPL then we'll #GP. * If SS RPL or DPL differs from CS RPL then we'll #GP.
*/ */
if ( !(c->flags & VGCF_VMX_GUEST) ) if ( !(c->flags & VGCF_HVM_GUEST) )
{ {
if ( ((c->user_regs.cs & 3) == 0) || if ( ((c->user_regs.cs & 3) == 0) ||
((c->user_regs.ss & 3) == 0) ) ((c->user_regs.ss & 3) == 0) )
return -EINVAL; return -EINVAL;
} }
else if ( !hvm_enabled ) else if ( !hvm_enabled )
return -EINVAL; return -EINVAL;
clear_bit(_VCPUF_fpu_initialised, &v->vcpu_flags); clear_bit(_VCPUF_fpu_initialised, &v->vcpu_flags);
if ( c->flags & VGCF_I387_VALID ) if ( c->flags & VGCF_I387_VALID )
set_bit(_VCPUF_fpu_initialised, &v->vcpu_flags); set_bit(_VCPUF_fpu_initialised, &v->vcpu_flags);
v->arch.flags &= ~TF_kernel_mode; v->arch.flags &= ~TF_kernel_mode;
if ( (c->flags & VGCF_IN_KERNEL) || (c->flags & VGCF_VMX_GUEST) ) if ( (c->flags & VGCF_IN_KERNEL) || (c->flags & VGCF_HVM_GUEST) )
v->arch.flags |= TF_kernel_mode; v->arch.flags |= TF_kernel_mode;
memcpy(&v->arch.guest_context, c, sizeof(*c)); memcpy(&v->arch.guest_context, c, sizeof(*c));
if ( !(c->flags & VGCF_VMX_GUEST) ) if ( !(c->flags & VGCF_HVM_GUEST) )
{ {
/* IOPL privileges are virtualised. */ /* IOPL privileges are virtualised. */
v->arch.iopl = (v->arch.guest_context.user_regs.eflags >> 12) & 3; v->arch.iopl = (v->arch.guest_context.user_regs.eflags >> 12) & 3;
@@ -384,9 +384,7 @@ int arch_set_info_guest(
} }
else if ( test_bit(_VCPUF_initialised, &v->vcpu_flags) ) else if ( test_bit(_VCPUF_initialised, &v->vcpu_flags) )
{ {
return modify_vmcs( hvm_modify_guest_state(v);
&v->arch.arch_vmx,
&v->arch.guest_context.user_regs);
} }
if ( test_bit(_VCPUF_initialised, &v->vcpu_flags) ) if ( test_bit(_VCPUF_initialised, &v->vcpu_flags) )
@@ -418,7 +416,7 @@ int arch_set_info_guest(
return -EINVAL; return -EINVAL;
} }
} }
else if ( !(c->flags & VGCF_VMX_GUEST) ) else if ( !(c->flags & VGCF_HVM_GUEST) )
{ {
if ( !get_page_and_type(pfn_to_page(phys_basetab>>PAGE_SHIFT), d, if ( !get_page_and_type(pfn_to_page(phys_basetab>>PAGE_SHIFT), d,
PGT_base_page_table) ) PGT_base_page_table) )
@@ -428,14 +426,17 @@ int arch_set_info_guest(
} }
} }
if ( c->flags & VGCF_VMX_GUEST ) if ( c->flags & VGCF_HVM_GUEST )
{ {
/* VMX uses the initially provided page tables as the P2M map. */ /* HVM uses the initially provided page tables as the P2M map. */
if ( !pagetable_get_paddr(d->arch.phys_table) ) if ( !pagetable_get_paddr(d->arch.phys_table) )
d->arch.phys_table = v->arch.guest_table; d->arch.phys_table = v->arch.guest_table;
v->arch.guest_table = mk_pagetable(0); v->arch.guest_table = mk_pagetable(0);
vmx_final_setup_guest(v); if (!hvm_initialize_guest_resources(v))
return -EINVAL;
hvm_switch_on = 1;
} }
update_pagetables(v); update_pagetables(v);
@@ -611,8 +612,8 @@ static void save_segments(struct vcpu *v)
struct cpu_user_regs *regs = &ctxt->user_regs; struct cpu_user_regs *regs = &ctxt->user_regs;
unsigned int dirty_segment_mask = 0; unsigned int dirty_segment_mask = 0;
if ( VMX_DOMAIN(v) ) if ( HVM_DOMAIN(v) )
rdmsrl(MSR_SHADOW_GS_BASE, v->arch.arch_vmx.msr_content.shadow_gs); hvm_save_segments(v);
__asm__ __volatile__ ( "mov %%ds,%0" : "=m" (regs->ds) ); __asm__ __volatile__ ( "mov %%ds,%0" : "=m" (regs->ds) );
__asm__ __volatile__ ( "mov %%es,%0" : "=m" (regs->es) ); __asm__ __volatile__ ( "mov %%es,%0" : "=m" (regs->es) );
@@ -704,7 +705,7 @@ static void __context_switch(void)
loaddebug(&n->arch.guest_context, 7); loaddebug(&n->arch.guest_context, 7);
} }
if ( !VMX_DOMAIN(n) ) if ( !HVM_DOMAIN(n) )
{ {
set_int80_direct_trap(n); set_int80_direct_trap(n);
switch_kernel_stack(n, cpu); switch_kernel_stack(n, cpu);
@@ -764,15 +765,16 @@ void context_switch(struct vcpu *prev, struct vcpu *next)
/* Re-enable interrupts before restoring state which may fault. */ /* Re-enable interrupts before restoring state which may fault. */
local_irq_enable(); local_irq_enable();
if ( VMX_DOMAIN(next) ) if ( HVM_DOMAIN(next) )
{ {
vmx_restore_msrs(next); hvm_restore_msrs(next);
} }
else else
{ {
load_LDT(next); load_LDT(next);
load_segments(next); load_segments(next);
vmx_load_msrs(next); if ( HVM_DOMAIN(next) )
hvm_load_msrs(next);
} }
} }
@@ -962,7 +964,8 @@ void domain_relinquish_resources(struct domain *d)
v->arch.guest_table_user = mk_pagetable(0); v->arch.guest_table_user = mk_pagetable(0);
} }
vmx_relinquish_resources(v); if ( HVM_DOMAIN(v) )
hvm_relinquish_guest_resources(v);
} }
shadow_mode_disable(d); shadow_mode_disable(d);
+308
View File
@@ -0,0 +1,308 @@
/*
* hvm.c: Common hardware virtual machine abstractions.
*
* Copyright (c) 2004, Intel Corporation.
* Copyright (c) 2005, International Business Machines Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., 59 Temple
* Place - Suite 330, Boston, MA 02111-1307 USA.
*/
#include <xen/config.h>
#include <xen/init.h>
#include <xen/lib.h>
#include <xen/trace.h>
#include <xen/sched.h>
#include <xen/irq.h>
#include <xen/softirq.h>
#include <xen/domain_page.h>
#include <asm/current.h>
#include <asm/io.h>
#include <asm/shadow.h>
#include <asm/regs.h>
#include <asm/cpufeature.h>
#include <asm/processor.h>
#include <asm/types.h>
#include <asm/msr.h>
#include <asm/spinlock.h>
#include <asm/hvm/hvm.h>
#include <asm/hvm/support.h>
#include <asm/shadow.h>
#if CONFIG_PAGING_LEVELS >= 3
#include <asm/shadow_64.h>
#endif
#include <public/sched.h>
#include <public/hvm/ioreq.h>
#include <public/hvm/hvm_info_table.h>
int hvm_enabled = 0;
int hvm_switch_on = 0;
unsigned int opt_hvm_debug_level = 0;
integer_param("hvm_debug", opt_hvm_debug_level);
struct hvm_function_table hvm_funcs;
static void hvm_map_io_shared_page(struct domain *d)
{
int i;
unsigned char e820_map_nr;
struct e820entry *e820entry;
unsigned char *p;
unsigned long mpfn;
unsigned long gpfn = 0;
local_flush_tlb_pge();
mpfn = get_mfn_from_pfn(E820_MAP_PAGE >> PAGE_SHIFT);
if (mpfn == INVALID_MFN) {
printk("Can not find E820 memory map page for HVM domain.\n");
domain_crash_synchronous();
}
p = map_domain_page(mpfn);
if (p == NULL) {
printk("Can not map E820 memory map page for HVM domain.\n");
domain_crash_synchronous();
}
e820_map_nr = *(p + E820_MAP_NR_OFFSET);
e820entry = (struct e820entry *)(p + E820_MAP_OFFSET);
for ( i = 0; i < e820_map_nr; i++ )
{
if (e820entry[i].type == E820_SHARED_PAGE)
{
gpfn = (e820entry[i].addr >> PAGE_SHIFT);
break;
}
}
if ( gpfn == 0 ) {
printk("Can not get io request shared page"
" from E820 memory map for HVM domain.\n");
unmap_domain_page(p);
domain_crash_synchronous();
}
unmap_domain_page(p);
/* Initialise shared page */
mpfn = get_mfn_from_pfn(gpfn);
if (mpfn == INVALID_MFN) {
printk("Can not find io request shared page for HVM domain.\n");
domain_crash_synchronous();
}
p = map_domain_page_global(mpfn);
if (p == NULL) {
printk("Can not map io request shared page for HVM domain.\n");
domain_crash_synchronous();
}
d->arch.hvm_domain.shared_page_va = (unsigned long)p;
HVM_DBG_LOG(DBG_LEVEL_1, "eport: %x\n", iopacket_port(d));
clear_bit(iopacket_port(d),
&d->shared_info->evtchn_mask[0]);
}
static int validate_hvm_info(struct hvm_info_table *t)
{
char signature[] = "HVM INFO";
uint8_t *ptr = (uint8_t *)t;
uint8_t sum = 0;
int i;
/* strncmp(t->signature, "HVM INFO", 8) */
for ( i = 0; i < 8; i++ ) {
if ( signature[i] != t->signature[i] ) {
printk("Bad hvm info signature\n");
return 0;
}
}
for ( i = 0; i < t->length; i++ )
sum += ptr[i];
return (sum == 0);
}
static void hvm_get_info(struct domain *d)
{
unsigned char *p;
unsigned long mpfn;
struct hvm_info_table *t;
mpfn = get_mfn_from_pfn(HVM_INFO_PFN);
if ( mpfn == INVALID_MFN ) {
printk("Can not get info page mfn for HVM domain.\n");
domain_crash_synchronous();
}
p = map_domain_page(mpfn);
if ( p == NULL ) {
printk("Can not map info page for HVM domain.\n");
domain_crash_synchronous();
}
t = (struct hvm_info_table *)(p + HVM_INFO_OFFSET);
if ( validate_hvm_info(t) ) {
d->arch.hvm_domain.nr_vcpus = t->nr_vcpus;
d->arch.hvm_domain.apic_enabled = t->apic_enabled;
} else {
printk("Bad hvm info table\n");
d->arch.hvm_domain.nr_vcpus = 1;
d->arch.hvm_domain.apic_enabled = 0;
}
unmap_domain_page(p);
}
void hvm_setup_platform(struct domain* d)
{
struct hvm_domain *platform;
if (!(HVM_DOMAIN(current) && (current->vcpu_id == 0)))
return;
hvm_map_io_shared_page(d);
hvm_get_info(d);
platform = &d->arch.hvm_domain;
pic_init(&platform->vpic, pic_irq_request, &platform->interrupt_request);
register_pic_io_hook();
if ( hvm_apic_support(d) ) {
spin_lock_init(&d->arch.hvm_domain.round_robin_lock);
hvm_vioapic_init(d);
}
}
void pic_irq_request(int *interrupt_request, int level)
{
if (level)
*interrupt_request = 1;
else
*interrupt_request = 0;
}
void hvm_pic_assist(struct vcpu *v)
{
global_iodata_t *spg;
u16 *virq_line, irqs;
struct hvm_virpic *pic = &v->domain->arch.hvm_domain.vpic;
spg = &get_sp(v->domain)->sp_global;
virq_line = &spg->pic_clear_irr;
if ( *virq_line ) {
do {
irqs = *(volatile u16*)virq_line;
} while ( (u16)cmpxchg(virq_line,irqs, 0) != irqs );
do_pic_irqs_clear(pic, irqs);
}
virq_line = &spg->pic_irr;
if ( *virq_line ) {
do {
irqs = *(volatile u16*)virq_line;
} while ( (u16)cmpxchg(virq_line,irqs, 0) != irqs );
do_pic_irqs(pic, irqs);
}
}
int cpu_get_interrupt(struct vcpu *v, int *type)
{
int intno;
struct hvm_virpic *s = &v->domain->arch.hvm_domain.vpic;
if ( (intno = cpu_get_apic_interrupt(v, type)) != -1 ) {
/* set irq request if a PIC irq is still pending */
/* XXX: improve that */
pic_update_irq(s);
return intno;
}
/* read the irq from the PIC */
if ( (intno = cpu_get_pic_interrupt(v, type)) != -1 )
return intno;
return -1;
}
/*
* Copy from/to guest virtual.
*/
int
hvm_copy(void *buf, unsigned long vaddr, int size, int dir)
{
unsigned long gpa, mfn;
char *addr;
int count;
while (size > 0) {
count = PAGE_SIZE - (vaddr & ~PAGE_MASK);
if (count > size)
count = size;
if (hvm_paging_enabled(current)) {
gpa = gva_to_gpa(vaddr);
mfn = get_mfn_from_pfn(gpa >> PAGE_SHIFT);
} else
mfn = get_mfn_from_pfn(vaddr >> PAGE_SHIFT);
if (mfn == INVALID_MFN)
return 0;
addr = (char *)map_domain_page(mfn) + (vaddr & ~PAGE_MASK);
if (dir == HVM_COPY_IN)
memcpy(buf, addr, count);
else
memcpy(addr, buf, count);
unmap_domain_page(addr);
vaddr += count;
buf += count;
size -= count;
}
return 1;
}
/*
* HVM specific printbuf. Mostly used for hvmloader chit-chat.
*/
void hvm_print_line(struct vcpu *v, const char c)
{
int *index = &v->domain->arch.hvm_domain.pbuf_index;
char *pbuf = v->domain->arch.hvm_domain.pbuf;
if (*index == HVM_PBUF_SIZE-2 || c == '\n') {
if (*index == HVM_PBUF_SIZE-2)
pbuf[(*index)++] = c;
pbuf[*index] = '\0';
printk("(GUEST: %u) %s\n", v->domain->domain_id, pbuf);
*index = 0;
} else
pbuf[(*index)++] = c;
}
/*
* Local variables:
* mode: C
* c-set-style: "BSD"
* c-basic-offset: 4
* tab-width: 4
* indent-tabs-mode: nil
* End:
*/
@@ -29,12 +29,10 @@
#include <xen/lib.h> #include <xen/lib.h>
#include <xen/errno.h> #include <xen/errno.h>
#include <xen/sched.h> #include <xen/sched.h>
#include <public/hvm/ioreq.h> #include <asm/hvm/hvm.h>
#include <asm/vmx.h> #include <asm/hvm/io.h>
#include <asm/vmx_vpic.h> #include <asm/hvm/support.h>
#include <asm/current.h> #include <asm/current.h>
#include <asm/vmx_vioapic.h>
#include <asm/vmx_vlapic.h>
/* set irq level. If an edge is detected, then the IRR is set to 1 */ /* set irq level. If an edge is detected, then the IRR is set to 1 */
static inline void pic_set_irq1(PicState *s, int irq, int level) static inline void pic_set_irq1(PicState *s, int irq, int level)
@@ -103,7 +101,7 @@ static int pic_get_irq(PicState *s)
/* raise irq to CPU if necessary. must be called every time the active /* raise irq to CPU if necessary. must be called every time the active
irq may change */ irq may change */
/* XXX: should not export it, but it is needed for an APIC kludge */ /* XXX: should not export it, but it is needed for an APIC kludge */
void pic_update_irq(struct vmx_virpic *s) void pic_update_irq(struct hvm_virpic *s)
{ {
int irq2, irq; int irq2, irq;
@@ -123,9 +121,9 @@ void pic_update_irq(struct vmx_virpic *s)
void pic_set_irq_new(void *opaque, int irq, int level) void pic_set_irq_new(void *opaque, int irq, int level)
{ {
struct vmx_virpic *s = opaque; struct hvm_virpic *s = opaque;
vmx_vioapic_set_irq(current->domain, irq, level); hvm_vioapic_set_irq(current->domain, irq, level);
pic_set_irq1(&s->pics[irq >> 3], irq & 7, level); pic_set_irq1(&s->pics[irq >> 3], irq & 7, level);
/* used for IOAPIC irqs */ /* used for IOAPIC irqs */
if (s->alt_irq_func) if (s->alt_irq_func)
@@ -133,24 +131,24 @@ void pic_set_irq_new(void *opaque, int irq, int level)
pic_update_irq(s); pic_update_irq(s);
} }
void do_pic_irqs (struct vmx_virpic *s, uint16_t irqs) void do_pic_irqs (struct hvm_virpic *s, uint16_t irqs)
{ {
s->pics[1].irr |= (uint8_t)(irqs >> 8); s->pics[1].irr |= (uint8_t)(irqs >> 8);
s->pics[0].irr |= (uint8_t) irqs; s->pics[0].irr |= (uint8_t) irqs;
vmx_vioapic_do_irqs(current->domain, irqs); hvm_vioapic_do_irqs(current->domain, irqs);
pic_update_irq(s); pic_update_irq(s);
} }
void do_pic_irqs_clear (struct vmx_virpic *s, uint16_t irqs) void do_pic_irqs_clear (struct hvm_virpic *s, uint16_t irqs)
{ {
s->pics[1].irr &= ~(uint8_t)(irqs >> 8); s->pics[1].irr &= ~(uint8_t)(irqs >> 8);
s->pics[0].irr &= ~(uint8_t) irqs; s->pics[0].irr &= ~(uint8_t) irqs;
vmx_vioapic_do_irqs_clear(current->domain, irqs); hvm_vioapic_do_irqs_clear(current->domain, irqs);
pic_update_irq(s); pic_update_irq(s);
} }
/* obsolete function */ /* obsolete function */
void pic_set_irq(struct vmx_virpic *isa_pic, int irq, int level) void pic_set_irq(struct hvm_virpic *isa_pic, int irq, int level)
{ {
pic_set_irq_new(isa_pic, irq, level); pic_set_irq_new(isa_pic, irq, level);
} }
@@ -169,7 +167,7 @@ static inline void pic_intack(PicState *s, int irq)
s->irr &= ~(1 << irq); s->irr &= ~(1 << irq);
} }
int pic_read_irq(struct vmx_virpic *s) int pic_read_irq(struct hvm_virpic *s)
{ {
int irq, irq2, intno; int irq, irq2, intno;
@@ -200,7 +198,7 @@ int pic_read_irq(struct vmx_virpic *s)
return intno; return intno;
} }
static void update_shared_irr(struct vmx_virpic *s, PicState *c) static void update_shared_irr(struct hvm_virpic *s, PicState *c)
{ {
uint8_t *pl, *pe; uint8_t *pl, *pe;
@@ -378,7 +376,7 @@ static uint32_t pic_ioport_read(void *opaque, uint32_t addr1)
/* memory mapped interrupt status */ /* memory mapped interrupt status */
/* XXX: may be the same than pic_read_irq() */ /* XXX: may be the same than pic_read_irq() */
uint32_t pic_intack_read(struct vmx_virpic *s) uint32_t pic_intack_read(struct hvm_virpic *s)
{ {
int ret; int ret;
@@ -409,7 +407,7 @@ static void pic_init1(int io_addr, int elcr_addr, PicState *s)
pic_reset(s); pic_reset(s);
} }
void pic_init(struct vmx_virpic *s, void (*irq_request)(), void pic_init(struct hvm_virpic *s, void (*irq_request)(),
void *irq_request_opaque) void *irq_request_opaque)
{ {
memset(s, 0, sizeof(*s)); memset(s, 0, sizeof(*s));
@@ -424,7 +422,7 @@ void pic_init(struct vmx_virpic *s, void (*irq_request)(),
return; return;
} }
void pic_set_alt_irq_func(struct vmx_virpic *s, void (*alt_irq_func)(), void pic_set_alt_irq_func(struct hvm_virpic *s, void (*alt_irq_func)(),
void *alt_irq_opaque) void *alt_irq_opaque)
{ {
s->alt_irq_func = alt_irq_func; s->alt_irq_func = alt_irq_func;
@@ -433,7 +431,7 @@ void pic_set_alt_irq_func(struct vmx_virpic *s, void (*alt_irq_func)(),
static int intercept_pic_io(ioreq_t *p) static int intercept_pic_io(ioreq_t *p)
{ {
struct vmx_virpic *pic; struct hvm_virpic *pic;
struct vcpu *v = current; struct vcpu *v = current;
uint32_t data; uint32_t data;
@@ -441,10 +439,10 @@ static int intercept_pic_io(ioreq_t *p)
printk("PIC_IO wrong access size %d!\n", (int)p->size); printk("PIC_IO wrong access size %d!\n", (int)p->size);
return 1; return 1;
} }
pic = &v->domain->arch.vmx_platform.vmx_pic; pic = &v->domain->arch.hvm_domain.vpic;
if ( p->dir == 0 ) { if ( p->dir == 0 ) {
if(p->pdata_valid) if(p->pdata_valid)
vmx_copy(&data, (unsigned long)p->u.pdata, p->size, VMX_COPY_IN); hvm_copy(&data, (unsigned long)p->u.pdata, p->size, HVM_COPY_IN);
else else
data = p->u.data; data = p->u.data;
pic_ioport_write((void*)&pic->pics[p->addr>>7], pic_ioport_write((void*)&pic->pics[p->addr>>7],
@@ -454,7 +452,7 @@ static int intercept_pic_io(ioreq_t *p)
data = pic_ioport_read( data = pic_ioport_read(
(void*)&pic->pics[p->addr>>7], (uint32_t) p->addr); (void*)&pic->pics[p->addr>>7], (uint32_t) p->addr);
if(p->pdata_valid) if(p->pdata_valid)
vmx_copy(&data, (unsigned long)p->u.pdata, p->size, VMX_COPY_OUT); hvm_copy(&data, (unsigned long)p->u.pdata, p->size, HVM_COPY_OUT);
else else
p->u.data = (u64)data; p->u.data = (u64)data;
} }
@@ -463,7 +461,7 @@ static int intercept_pic_io(ioreq_t *p)
static int intercept_elcr_io(ioreq_t *p) static int intercept_elcr_io(ioreq_t *p)
{ {
struct vmx_virpic *s; struct hvm_virpic *s;
struct vcpu *v = current; struct vcpu *v = current;
uint32_t data; uint32_t data;
@@ -472,10 +470,10 @@ static int intercept_elcr_io(ioreq_t *p)
return 1; return 1;
} }
s = &v->domain->arch.vmx_platform.vmx_pic; s = &v->domain->arch.hvm_domain.vpic;
if ( p->dir == 0 ) { if ( p->dir == 0 ) {
if(p->pdata_valid) if(p->pdata_valid)
vmx_copy(&data, (unsigned long)p->u.pdata, p->size, VMX_COPY_IN); hvm_copy(&data, (unsigned long)p->u.pdata, p->size, HVM_COPY_IN);
else else
data = p->u.data; data = p->u.data;
elcr_ioport_write((void*)&s->pics[p->addr&1], elcr_ioport_write((void*)&s->pics[p->addr&1],
@@ -487,7 +485,7 @@ static int intercept_elcr_io(ioreq_t *p)
data = (u64) elcr_ioport_read( data = (u64) elcr_ioport_read(
(void*)&s->pics[p->addr&1], (uint32_t) p->addr); (void*)&s->pics[p->addr&1], (uint32_t) p->addr);
if(p->pdata_valid) if(p->pdata_valid)
vmx_copy(&data, (unsigned long)p->u.pdata, p->size, VMX_COPY_OUT); hvm_copy(&data, (unsigned long)p->u.pdata, p->size, HVM_COPY_OUT);
else else
p->u.data = (u64)data; p->u.data = (u64)data;
@@ -507,8 +505,8 @@ void register_pic_io_hook (void)
int cpu_get_pic_interrupt(struct vcpu *v, int *type) int cpu_get_pic_interrupt(struct vcpu *v, int *type)
{ {
int intno; int intno;
struct vmx_virpic *s = &v->domain->arch.vmx_platform.vmx_pic; struct hvm_virpic *s = &v->domain->arch.hvm_domain.vpic;
struct vmx_platform *plat = &v->domain->arch.vmx_platform; struct hvm_domain *plat = &v->domain->arch.hvm_domain;
if ( !vlapic_accept_pic_intr(v) ) if ( !vlapic_accept_pic_intr(v) )
return -1; return -1;
@@ -528,17 +526,17 @@ int is_pit_irq(struct vcpu *v, int irq, int type)
int pit_vec; int pit_vec;
if (type == VLAPIC_DELIV_MODE_EXT) if (type == VLAPIC_DELIV_MODE_EXT)
pit_vec = v->domain->arch.vmx_platform.vmx_pic.pics[0].irq_base; pit_vec = v->domain->arch.hvm_domain.vpic.pics[0].irq_base;
else else
pit_vec = pit_vec =
v->domain->arch.vmx_platform.vmx_vioapic.redirtbl[0].RedirForm.vector; v->domain->arch.hvm_domain.vioapic.redirtbl[0].RedirForm.vector;
return (irq == pit_vec); return (irq == pit_vec);
} }
int is_irq_enabled(struct vcpu *v, int irq) int is_irq_enabled(struct vcpu *v, int irq)
{ {
struct vmx_virpic *vpic=&v->domain->arch.vmx_platform.vmx_pic; struct hvm_virpic *vpic=&v->domain->arch.hvm_domain.vpic;
if ( irq & 8 ) { if ( irq & 8 ) {
return !( (1 << (irq&7)) & vpic->pics[1].imr); return !( (1 << (irq&7)) & vpic->pics[1].imr);
@@ -1,5 +1,6 @@
/* /*
* vmx_intercept.c: Handle performance critical I/O packets in hypervisor space * intercept.c: Handle performance critical I/O packets in hypervisor space
*
* Copyright (c) 2004, Intel Corporation. * Copyright (c) 2004, Intel Corporation.
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
@@ -14,40 +15,37 @@
* You should have received a copy of the GNU General Public License along with * You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., 59 Temple * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
* Place - Suite 330, Boston, MA 02111-1307 USA. * Place - Suite 330, Boston, MA 02111-1307 USA.
*
*/ */
#include <xen/config.h> #include <xen/config.h>
#include <xen/types.h> #include <xen/types.h>
#include <asm/vmx.h> #include <xen/sched.h>
#include <asm/vmx_platform.h> #include <asm/regs.h>
#include <asm/vmx_vpit.h> #include <asm/hvm/hvm.h>
#include <asm/vmx_intercept.h> #include <asm/hvm/support.h>
#include <asm/vmx_vlapic.h> #include <asm/hvm/domain.h>
#include <public/hvm/ioreq.h>
#include <xen/lib.h> #include <xen/lib.h>
#include <xen/sched.h> #include <xen/sched.h>
#include <asm/current.h> #include <asm/current.h>
#include <io_ports.h> #include <io_ports.h>
#include <xen/event.h> #include <xen/event.h>
#ifdef CONFIG_VMX
extern struct vmx_mmio_handler vlapic_mmio_handler; extern struct hvm_mmio_handler vlapic_mmio_handler;
extern struct vmx_mmio_handler vioapic_mmio_handler; extern struct hvm_mmio_handler vioapic_mmio_handler;
#define VMX_MMIO_HANDLER_NR 2 #define HVM_MMIO_HANDLER_NR 2
struct vmx_mmio_handler *vmx_mmio_handlers[VMX_MMIO_HANDLER_NR] = struct hvm_mmio_handler *hvm_mmio_handlers[HVM_MMIO_HANDLER_NR] =
{ {
&vlapic_mmio_handler, &vlapic_mmio_handler,
&vioapic_mmio_handler &vioapic_mmio_handler
}; };
static inline void vmx_mmio_access(struct vcpu *v, static inline void hvm_mmio_access(struct vcpu *v,
ioreq_t *p, ioreq_t *p,
vmx_mmio_read_t read_handler, hvm_mmio_read_t read_handler,
vmx_mmio_write_t write_handler) hvm_mmio_write_t write_handler)
{ {
ioreq_t *req; ioreq_t *req;
vcpu_iodata_t *vio = get_vio(v->domain, v->vcpu_id); vcpu_iodata_t *vio = get_vio(v->domain, v->vcpu_id);
@@ -78,17 +76,17 @@ static inline void vmx_mmio_access(struct vcpu *v,
data = read_handler(v, data = read_handler(v,
req->addr + (sign * i * req->size), req->addr + (sign * i * req->size),
req->size); req->size);
vmx_copy(&data, hvm_copy(&data,
(unsigned long)p->u.pdata + (sign * i * req->size), (unsigned long)p->u.pdata + (sign * i * req->size),
p->size, p->size,
VMX_COPY_OUT); HVM_COPY_OUT);
} }
} else { /* !req->dir == IOREQ_READ */ } else { /* !req->dir == IOREQ_READ */
for (i = 0; i < req->count; i++) { for (i = 0; i < req->count; i++) {
vmx_copy(&data, hvm_copy(&data,
(unsigned long)p->u.pdata + (sign * i * req->size), (unsigned long)p->u.pdata + (sign * i * req->size),
p->size, p->size,
VMX_COPY_IN); HVM_COPY_IN);
write_handler(v, write_handler(v,
req->addr + (sign * i * req->size), req->addr + (sign * i * req->size),
req->size, data); req->size, data);
@@ -132,20 +130,20 @@ static inline void vmx_mmio_access(struct vcpu *v,
} }
} }
int vmx_mmio_intercept(ioreq_t *p) int hvm_mmio_intercept(ioreq_t *p)
{ {
struct vcpu *v = current; struct vcpu *v = current;
int i; int i;
/* XXX currently only APIC use intercept */ /* XXX currently only APIC use intercept */
if ( !vmx_apic_support(v->domain) ) if ( !hvm_apic_support(v->domain) )
return 0; return 0;
for ( i = 0; i < VMX_MMIO_HANDLER_NR; i++ ) { for ( i = 0; i < HVM_MMIO_HANDLER_NR; i++ ) {
if ( vmx_mmio_handlers[i]->check_handler(v, p->addr) ) { if ( hvm_mmio_handlers[i]->check_handler(v, p->addr) ) {
vmx_mmio_access(v, p, hvm_mmio_access(v, p,
vmx_mmio_handlers[i]->read_handler, hvm_mmio_handlers[i]->read_handler,
vmx_mmio_handlers[i]->write_handler); hvm_mmio_handlers[i]->write_handler);
return 1; return 1;
} }
} }
@@ -156,11 +154,11 @@ int vmx_mmio_intercept(ioreq_t *p)
* Check if the request is handled inside xen * Check if the request is handled inside xen
* return value: 0 --not handled; 1 --handled * return value: 0 --not handled; 1 --handled
*/ */
int vmx_io_intercept(ioreq_t *p, int type) int hvm_io_intercept(ioreq_t *p, int type)
{ {
struct vcpu *v = current; struct vcpu *v = current;
struct vmx_io_handler *handler = struct hvm_io_handler *handler =
&(v->domain->arch.vmx_platform.vmx_io_handler); &(v->domain->arch.hvm_domain.io_handler);
int i; int i;
unsigned long addr, size; unsigned long addr, size;
@@ -180,8 +178,8 @@ int register_io_handler(unsigned long addr, unsigned long size,
intercept_action_t action, int type) intercept_action_t action, int type)
{ {
struct vcpu *v = current; struct vcpu *v = current;
struct vmx_io_handler *handler = struct hvm_io_handler *handler =
&(v->domain->arch.vmx_platform.vmx_io_handler); &(v->domain->arch.hvm_domain.io_handler);
int num = handler->num_slot; int num = handler->num_slot;
if (num >= MAX_IO_HANDLER) { if (num >= MAX_IO_HANDLER) {
@@ -198,21 +196,25 @@ int register_io_handler(unsigned long addr, unsigned long size,
return 1; return 1;
} }
static void pit_cal_count(struct vmx_virpit *vpit) static void pit_cal_count(struct hvm_virpit *vpit)
{ {
u64 nsec_delta = (unsigned int)((NOW() - vpit->inject_point)); u64 nsec_delta = (unsigned int)((NOW() - vpit->inject_point));
if (nsec_delta > vpit->period) if (nsec_delta > vpit->period)
VMX_DBG_LOG(DBG_LEVEL_1, "VMX_PIT:long time has passed from last injection!"); HVM_DBG_LOG(DBG_LEVEL_1,
"HVM_PIT: long time has passed from last injection!");
if(vpit->init_val == 0) if(vpit->init_val == 0)
{ {
printk("PIT init value == 0!\n"); printk("PIT init value == 0!\n");
domain_crash_synchronous(); domain_crash_synchronous();
} }
vpit->count = vpit->init_val - ((nsec_delta * PIT_FREQ / 1000000000ULL) % vpit->init_val ); vpit->count = vpit->init_val
- ((nsec_delta * PIT_FREQ / 1000000000ULL) % vpit->init_val);
} }
static void pit_latch_io(struct vmx_virpit *vpit) static void pit_latch_io(struct hvm_virpit *vpit)
{ {
pit_cal_count(vpit); pit_cal_count(vpit);
@@ -228,7 +230,8 @@ static void pit_latch_io(struct vmx_virpit *vpit)
vpit->count_MSB_latched=1; vpit->count_MSB_latched=1;
break; break;
case MSByte_multiple: case MSByte_multiple:
VMX_DBG_LOG(DBG_LEVEL_1, "VMX_PIT:latch PIT counter before MSB_multiple!"); HVM_DBG_LOG(DBG_LEVEL_1,
"HVM_PIT: latch PIT counter before MSB_multiple!");
vpit->read_state=LSByte_multiple; vpit->read_state=LSByte_multiple;
vpit->count_LSB_latched=1; vpit->count_LSB_latched=1;
vpit->count_MSB_latched=1; vpit->count_MSB_latched=1;
@@ -238,7 +241,7 @@ static void pit_latch_io(struct vmx_virpit *vpit)
} }
} }
static int pit_read_io(struct vmx_virpit *vpit) static int pit_read_io(struct hvm_virpit *vpit)
{ {
if(vpit->count_LSB_latched) { if(vpit->count_LSB_latched) {
/* Read Least Significant Byte */ /* Read Least Significant Byte */
@@ -256,7 +259,7 @@ static int pit_read_io(struct vmx_virpit *vpit)
return ((vpit->count>>8) & 0xFF); return ((vpit->count>>8) & 0xFF);
} else { } else {
/* Unlatched Count Read */ /* Unlatched Count Read */
VMX_DBG_LOG(DBG_LEVEL_1, "VMX_PIT: unlatched read"); HVM_DBG_LOG(DBG_LEVEL_1, "HVM_PIT: unlatched read");
pit_cal_count(vpit); pit_cal_count(vpit);
if(!(vpit->read_state & 0x1)) { if(!(vpit->read_state & 0x1)) {
/* Read Least Significant Byte */ /* Read Least Significant Byte */
@@ -274,7 +277,7 @@ static int pit_read_io(struct vmx_virpit *vpit)
} }
} }
/* vmx_io_assist light-weight version, specific to PIT DM */ /* hvm_io_assist light-weight version, specific to PIT DM */
static void resume_pit_io(ioreq_t *p) static void resume_pit_io(ioreq_t *p)
{ {
struct cpu_user_regs *regs = guest_cpu_user_regs(); struct cpu_user_regs *regs = guest_cpu_user_regs();
@@ -300,7 +303,7 @@ static void resume_pit_io(ioreq_t *p)
int intercept_pit_io(ioreq_t *p) int intercept_pit_io(ioreq_t *p)
{ {
struct vcpu *v = current; struct vcpu *v = current;
struct vmx_virpit *vpit = &(v->domain->arch.vmx_platform.vmx_pit); struct hvm_virpit *vpit = &(v->domain->arch.hvm_domain.vpit);
if (p->size != 1 || if (p->size != 1 ||
p->pdata_valid || p->pdata_valid ||
@@ -333,7 +336,7 @@ void hlt_timer_fn(void *data)
evtchn_set_pending(v, iopacket_port(v->domain)); evtchn_set_pending(v, iopacket_port(v->domain));
} }
static __inline__ void missed_ticks(struct vmx_virpit*vpit) static __inline__ void missed_ticks(struct hvm_virpit*vpit)
{ {
int missed_ticks; int missed_ticks;
@@ -348,7 +351,7 @@ static __inline__ void missed_ticks(struct vmx_virpit*vpit)
static void pit_timer_fn(void *data) static void pit_timer_fn(void *data)
{ {
struct vcpu *v = data; struct vcpu *v = data;
struct vmx_virpit *vpit = &(v->domain->arch.vmx_platform.vmx_pit); struct hvm_virpit *vpit = &(v->domain->arch.hvm_domain.vpit);
/* pick up missed timer tick */ /* pick up missed timer tick */
missed_ticks(vpit); missed_ticks(vpit);
@@ -360,7 +363,7 @@ static void pit_timer_fn(void *data)
} }
} }
void pickup_deactive_ticks(struct vmx_virpit *vpit) void pickup_deactive_ticks(struct hvm_virpit *vpit)
{ {
if ( !active_timer(&(vpit->pit_timer)) ) { if ( !active_timer(&(vpit->pit_timer)) ) {
@@ -375,18 +378,18 @@ void pickup_deactive_ticks(struct vmx_virpit *vpit)
/* Only some PIT operations such as load init counter need a hypervisor hook. /* Only some PIT operations such as load init counter need a hypervisor hook.
* leave all other operations in user space DM * leave all other operations in user space DM
*/ */
void vmx_hooks_assist(struct vcpu *v) void hvm_hooks_assist(struct vcpu *v)
{ {
vcpu_iodata_t *vio = get_vio(v->domain, v->vcpu_id); vcpu_iodata_t *vio = get_vio(v->domain, v->vcpu_id);
ioreq_t *p = &vio->vp_ioreq; ioreq_t *p = &vio->vp_ioreq;
struct vmx_virpit *vpit = &(v->domain->arch.vmx_platform.vmx_pit); struct hvm_virpit *vpit = &(v->domain->arch.hvm_domain.vpit);
int rw_mode, reinit = 0; int rw_mode, reinit = 0;
/* load init count*/ /* load init count*/
if (p->state == STATE_IORESP_HOOK) { if (p->state == STATE_IORESP_HOOK) {
/* set up actimer, handle re-init */ /* set up actimer, handle re-init */
if ( active_timer(&(vpit->pit_timer)) ) { if ( active_timer(&(vpit->pit_timer)) ) {
VMX_DBG_LOG(DBG_LEVEL_1, "VMX_PIT: guest reset PIT with channel %lx!\n", (unsigned long) ((p->u.data >> 24) & 0x3) ); HVM_DBG_LOG(DBG_LEVEL_1, "HVM_PIT: guest reset PIT with channel %lx!\n", (unsigned long) ((p->u.data >> 24) & 0x3) );
stop_timer(&(vpit->pit_timer)); stop_timer(&(vpit->pit_timer));
reinit = 1; reinit = 1;
@@ -399,14 +402,14 @@ void vmx_hooks_assist(struct vcpu *v)
vpit->init_val = (p->u.data & 0xFFFF) ; vpit->init_val = (p->u.data & 0xFFFF) ;
/* frequency(ns) of pit */ /* frequency(ns) of pit */
vpit->period = DIV_ROUND(((vpit->init_val) * 1000000000ULL), PIT_FREQ); vpit->period = DIV_ROUND(((vpit->init_val) * 1000000000ULL), PIT_FREQ);
VMX_DBG_LOG(DBG_LEVEL_1,"VMX_PIT: guest set init pit freq:%u ns, initval:0x%x\n", vpit->period, vpit->init_val); HVM_DBG_LOG(DBG_LEVEL_1,"HVM_PIT: guest set init pit freq:%u ns, initval:0x%x\n", vpit->period, vpit->init_val);
if (vpit->period < 900000) { /* < 0.9 ms */ if (vpit->period < 900000) { /* < 0.9 ms */
printk("VMX_PIT: guest programmed too small an init_val: %x\n", printk("HVM_PIT: guest programmed too small an init_val: %x\n",
vpit->init_val); vpit->init_val);
vpit->period = 1000000; vpit->period = 1000000;
} }
vpit->period_cycles = (u64)vpit->period * cpu_khz / 1000000L; vpit->period_cycles = (u64)vpit->period * cpu_khz / 1000000L;
printk("VMX_PIT: guest freq in cycles=%lld\n",(long long)vpit->period_cycles); printk("HVM_PIT: guest freq in cycles=%lld\n",(long long)vpit->period_cycles);
vpit->channel = ((p->u.data >> 24) & 0x3); vpit->channel = ((p->u.data >> 24) & 0x3);
vpit->first_injected = 0; vpit->first_injected = 0;
@@ -426,7 +429,7 @@ void vmx_hooks_assist(struct vcpu *v)
vpit->read_state=LSByte_multiple; vpit->read_state=LSByte_multiple;
break; break;
default: default:
printk("VMX_PIT:wrong PIT rw_mode!\n"); printk("HVM_PIT:wrong PIT rw_mode!\n");
break; break;
} }
@@ -442,7 +445,6 @@ void vmx_hooks_assist(struct vcpu *v)
} }
} }
} }
#endif /* CONFIG_VMX */
/* /*
* Local variables: * Local variables:
+50 -305
View File
@@ -1,6 +1,8 @@
/* /*
* vmx_io.c: handling I/O, interrupts related VMX entry/exit * io.c: Handling I/O and interrupts.
*
* Copyright (c) 2004, Intel Corporation. * Copyright (c) 2004, Intel Corporation.
* Copyright (c) 2005, International Business Machines Corporation.
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@@ -14,7 +16,6 @@
* You should have received a copy of the GNU General Public License along with * You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., 59 Temple * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
* Place - Suite 330, Boston, MA 02111-1307 USA. * Place - Suite 330, Boston, MA 02111-1307 USA.
*
*/ */
#include <xen/config.h> #include <xen/config.h>
@@ -24,42 +25,24 @@
#include <xen/errno.h> #include <xen/errno.h>
#include <xen/trace.h> #include <xen/trace.h>
#include <xen/event.h> #include <xen/event.h>
#include <xen/hypercall.h> #include <xen/hypercall.h>
#include <asm/current.h> #include <asm/current.h>
#include <asm/cpufeature.h> #include <asm/cpufeature.h>
#include <asm/processor.h> #include <asm/processor.h>
#include <asm/msr.h> #include <asm/msr.h>
#include <asm/vmx.h>
#include <asm/vmx_vmcs.h>
#include <asm/vmx_platform.h>
#include <asm/vmx_vpit.h>
#include <asm/apic.h> #include <asm/apic.h>
#include <asm/shadow.h> #include <asm/shadow.h>
#include <asm/vmx_vpic.h> #include <asm/hvm/hvm.h>
#include <asm/vmx_vlapic.h> #include <asm/hvm/support.h>
#include <asm/hvm/vpit.h>
#include <asm/hvm/vpic.h>
#include <asm/hvm/vlapic.h>
#include <public/sched.h> #include <public/sched.h>
#include <public/hvm/ioreq.h> #include <public/hvm/ioreq.h>
#ifdef CONFIG_VMX
#if defined (__i386__) #if defined (__i386__)
void load_cpu_user_regs(struct cpu_user_regs *regs)
{
/*
* Write the guest register value into VMCS
*/
__vmwrite(GUEST_SS_SELECTOR, regs->ss);
__vmwrite(GUEST_RSP, regs->esp);
__vmwrite(GUEST_RFLAGS, regs->eflags);
if (regs->eflags & EF_TF)
__vm_set_bit(EXCEPTION_BITMAP, EXCEPTION_BITMAP_DB);
else
__vm_clear_bit(EXCEPTION_BITMAP, EXCEPTION_BITMAP_DB);
__vmwrite(GUEST_CS_SELECTOR, regs->cs);
__vmwrite(GUEST_RIP, regs->eip);
}
static void set_reg_value (int size, int index, int seg, struct cpu_user_regs *regs, long value) static void set_reg_value (int size, int index, int seg, struct cpu_user_regs *regs, long value)
{ {
switch (size) { switch (size) {
@@ -182,21 +165,6 @@ static void set_reg_value (int size, int index, int seg, struct cpu_user_regs *r
} }
} }
#else #else
void load_cpu_user_regs(struct cpu_user_regs *regs)
{
__vmwrite(GUEST_SS_SELECTOR, regs->ss);
__vmwrite(GUEST_RSP, regs->rsp);
__vmwrite(GUEST_RFLAGS, regs->rflags);
if (regs->rflags & EF_TF)
__vm_set_bit(EXCEPTION_BITMAP, EXCEPTION_BITMAP_DB);
else
__vm_clear_bit(EXCEPTION_BITMAP, EXCEPTION_BITMAP_DB);
__vmwrite(GUEST_CS_SELECTOR, regs->cs);
__vmwrite(GUEST_RIP, regs->rip);
}
static inline void __set_reg_value(unsigned long *reg, int size, long value) static inline void __set_reg_value(unsigned long *reg, int size, long value)
{ {
switch (size) { switch (size) {
@@ -391,7 +359,7 @@ static inline void set_eflags_PF(int size, unsigned long v1,
regs->eflags |= X86_EFLAGS_PF; regs->eflags |= X86_EFLAGS_PF;
} }
static void vmx_pio_assist(struct cpu_user_regs *regs, ioreq_t *p, static void hvm_pio_assist(struct cpu_user_regs *regs, ioreq_t *p,
struct mmio_op *mmio_opp) struct mmio_op *mmio_opp)
{ {
unsigned long old_eax; unsigned long old_eax;
@@ -414,7 +382,7 @@ static void vmx_pio_assist(struct cpu_user_regs *regs, ioreq_t *p,
addr = regs->edi; addr = regs->edi;
if (sign > 0) if (sign > 0)
addr -= p->size; addr -= p->size;
vmx_copy(&p->u.data, addr, p->size, VMX_COPY_OUT); hvm_copy(&p->u.data, addr, p->size, HVM_COPY_OUT);
} else if (p->pdata_valid) { } else if (p->pdata_valid) {
regs->edi += sign * p->count * p->size; regs->edi += sign * p->count * p->size;
if (mmio_opp->flags & REPZ) if (mmio_opp->flags & REPZ)
@@ -439,8 +407,8 @@ static void vmx_pio_assist(struct cpu_user_regs *regs, ioreq_t *p,
} }
} }
static void vmx_mmio_assist(struct cpu_user_regs *regs, ioreq_t *p, static void hvm_mmio_assist(struct vcpu *v, struct cpu_user_regs *regs,
struct mmio_op *mmio_opp) ioreq_t *p, struct mmio_op *mmio_opp)
{ {
int sign = p->df ? -1 : 1; int sign = p->df ? -1 : 1;
int size = -1, index = -1; int size = -1, index = -1;
@@ -523,7 +491,7 @@ static void vmx_mmio_assist(struct cpu_user_regs *regs, ioreq_t *p,
if (sign > 0) if (sign > 0)
addr -= p->size; addr -= p->size;
vmx_copy(&p->u.data, addr, p->size, VMX_COPY_OUT); hvm_copy(&p->u.data, addr, p->size, HVM_COPY_OUT);
} }
if (mmio_opp->flags & REPZ) if (mmio_opp->flags & REPZ)
@@ -680,10 +648,10 @@ static void vmx_mmio_assist(struct cpu_user_regs *regs, ioreq_t *p,
break; break;
} }
load_cpu_user_regs(regs); hvm_load_cpu_guest_regs(v, regs);
} }
void vmx_io_assist(struct vcpu *v) void hvm_io_assist(struct vcpu *v)
{ {
vcpu_iodata_t *vio; vcpu_iodata_t *vio;
ioreq_t *p; ioreq_t *p;
@@ -691,13 +659,13 @@ void vmx_io_assist(struct vcpu *v)
struct mmio_op *mmio_opp; struct mmio_op *mmio_opp;
struct cpu_user_regs *inst_decoder_regs; struct cpu_user_regs *inst_decoder_regs;
mmio_opp = &v->arch.arch_vmx.mmio_op; mmio_opp = &v->arch.hvm_vcpu.mmio_op;
inst_decoder_regs = mmio_opp->inst_decoder_regs; inst_decoder_regs = mmio_opp->inst_decoder_regs;
vio = get_vio(v->domain, v->vcpu_id); vio = get_vio(v->domain, v->vcpu_id);
if (vio == 0) { if (vio == 0) {
VMX_DBG_LOG(DBG_LEVEL_1, HVM_DBG_LOG(DBG_LEVEL_1,
"bad shared page: %lx", (unsigned long) vio); "bad shared page: %lx", (unsigned long) vio);
printf("bad shared page: %lx\n", (unsigned long) vio); printf("bad shared page: %lx\n", (unsigned long) vio);
domain_crash_synchronous(); domain_crash_synchronous();
@@ -705,24 +673,24 @@ void vmx_io_assist(struct vcpu *v)
p = &vio->vp_ioreq; p = &vio->vp_ioreq;
if (p->state == STATE_IORESP_HOOK) if (p->state == STATE_IORESP_HOOK)
vmx_hooks_assist(v); hvm_hooks_assist(v);
/* clear IO wait VMX flag */ /* clear IO wait HVM flag */
if (test_bit(ARCH_VMX_IO_WAIT, &v->arch.arch_vmx.flags)) { if (test_bit(ARCH_HVM_IO_WAIT, &v->arch.hvm_vcpu.ioflags)) {
if (p->state == STATE_IORESP_READY) { if (p->state == STATE_IORESP_READY) {
p->state = STATE_INVALID; p->state = STATE_INVALID;
clear_bit(ARCH_VMX_IO_WAIT, &v->arch.arch_vmx.flags); clear_bit(ARCH_HVM_IO_WAIT, &v->arch.hvm_vcpu.ioflags);
if (p->type == IOREQ_TYPE_PIO) if (p->type == IOREQ_TYPE_PIO)
vmx_pio_assist(regs, p, mmio_opp); hvm_pio_assist(regs, p, mmio_opp);
else else
vmx_mmio_assist(regs, p, mmio_opp); hvm_mmio_assist(v, regs, p, mmio_opp);
} }
/* else an interrupt send event raced us */ /* else an interrupt send event raced us */
} }
} }
int vmx_clear_pending_io_event(struct vcpu *v) int hvm_clear_pending_io_event(struct vcpu *v)
{ {
struct domain *d = v->domain; struct domain *d = v->domain;
int port = iopacket_port(d); int port = iopacket_port(d);
@@ -731,7 +699,7 @@ int vmx_clear_pending_io_event(struct vcpu *v)
if (!d->shared_info->evtchn_pending[port/BITS_PER_LONG]) if (!d->shared_info->evtchn_pending[port/BITS_PER_LONG])
clear_bit(port/BITS_PER_LONG, &v->vcpu_info->evtchn_pending_sel); clear_bit(port/BITS_PER_LONG, &v->vcpu_info->evtchn_pending_sel);
/* Note: VMX domains may need upcalls as well. */ /* Note: HVM domains may need upcalls as well. */
if (!v->vcpu_info->evtchn_pending_sel) if (!v->vcpu_info->evtchn_pending_sel)
clear_bit(0, &v->vcpu_info->evtchn_upcall_pending); clear_bit(0, &v->vcpu_info->evtchn_upcall_pending);
@@ -739,270 +707,47 @@ int vmx_clear_pending_io_event(struct vcpu *v)
return test_and_clear_bit(port, &d->shared_info->evtchn_pending[0]); return test_and_clear_bit(port, &d->shared_info->evtchn_pending[0]);
} }
/* Because we've cleared the pending events first, we need to guarantee that /*
* all events to be handled by xen for VMX domains are taken care of here. * Because we've cleared the pending events first, we need to guarantee that
* all events to be handled by xen for HVM domains are taken care of here.
* *
* interrupts are guaranteed to be checked before resuming guest. * interrupts are guaranteed to be checked before resuming guest.
* VMX upcalls have been already arranged for if necessary. * HVM upcalls have been already arranged for if necessary.
*/ */
void vmx_check_events(struct vcpu *v) void hvm_check_events(struct vcpu *v)
{ {
/* clear the event *before* checking for work. This should avoid /*
the set-and-check races */ * Clear the event *before* checking for work. This should
if (vmx_clear_pending_io_event(v)) * avoid the set-and-check races
vmx_io_assist(v); */
if (hvm_clear_pending_io_event(current))
hvm_io_assist(v);
} }
/* On exit from vmx_wait_io, we're guaranteed to have a I/O response from /*
the device model */ * On exit from hvm_wait_io, we're guaranteed to have a I/O response
void vmx_wait_io() * from the device model.
*/
void hvm_wait_io(void)
{ {
int port = iopacket_port(current->domain); int port = iopacket_port(current->domain);
do { do {
if (!test_bit(port, &current->domain->shared_info->evtchn_pending[0])) if (!test_bit(port, &current->domain->shared_info->evtchn_pending[0]))
do_sched_op(SCHEDOP_block, 0); do_sched_op(SCHEDOP_block, 0);
vmx_check_events(current); hvm_check_events(current);
if (!test_bit(ARCH_VMX_IO_WAIT, &current->arch.arch_vmx.flags)) if (!test_bit(ARCH_HVM_IO_WAIT, &current->arch.hvm_vcpu.ioflags))
break; break;
/* Events other than IOPACKET_PORT might have woken us up. In that /*
case, safely go back to sleep. */ * Events other than IOPACKET_PORT might have woken us up.
* In that case, safely go back to sleep.
*/
clear_bit(port/BITS_PER_LONG, &current->vcpu_info->evtchn_pending_sel); clear_bit(port/BITS_PER_LONG, &current->vcpu_info->evtchn_pending_sel);
clear_bit(0, &current->vcpu_info->evtchn_upcall_pending); clear_bit(0, &current->vcpu_info->evtchn_upcall_pending);
} while(1); } while(1);
} }
/* Simple minded Local APIC priority implementation. Fix later */
static __inline__ int find_highest_irq(u32 *pintr)
{
if (pintr[7])
return __fls(pintr[7]) + (256-32*1);
if (pintr[6])
return __fls(pintr[6]) + (256-32*2);
if (pintr[5])
return __fls(pintr[5]) + (256-32*3);
if (pintr[4])
return __fls(pintr[4]) + (256-32*4);
if (pintr[3])
return __fls(pintr[3]) + (256-32*5);
if (pintr[2])
return __fls(pintr[2]) + (256-32*6);
if (pintr[1])
return __fls(pintr[1]) + (256-32*7);
return __fls(pintr[0]);
}
void set_tsc_shift(struct vcpu *v,struct vmx_virpit *vpit)
{
u64 drift;
if ( vpit->first_injected )
drift = vpit->period_cycles * vpit->pending_intr_nr;
else
drift = 0;
vpit->shift = v->arch.arch_vmx.tsc_offset - drift;
__vmwrite(TSC_OFFSET, vpit->shift);
#if defined (__i386__)
__vmwrite(TSC_OFFSET_HIGH, ((vpit->shift)>> 32));
#endif
}
#define BSP_CPU(v) (!(v->vcpu_id))
static inline void
interrupt_post_injection(struct vcpu * v, int vector, int type)
{
struct vmx_virpit *vpit = &(v->domain->arch.vmx_platform.vmx_pit);
if ( is_pit_irq(v, vector, type) ) {
if ( !vpit->first_injected ) {
vpit->pending_intr_nr = 0;
vpit->scheduled = NOW() + vpit->period;
set_timer(&vpit->pit_timer, vpit->scheduled);
vpit->first_injected = 1;
} else {
vpit->pending_intr_nr--;
}
vpit->inject_point = NOW();
set_tsc_shift (v, vpit);
}
switch(type)
{
case VLAPIC_DELIV_MODE_EXT:
break;
default:
vlapic_post_injection(v, vector, type);
break;
}
}
static inline void
enable_irq_window(unsigned long cpu_exec_control)
{
if (!(cpu_exec_control & CPU_BASED_VIRTUAL_INTR_PENDING)) {
cpu_exec_control |= CPU_BASED_VIRTUAL_INTR_PENDING;
__vmwrite(CPU_BASED_VM_EXEC_CONTROL, cpu_exec_control);
}
}
static inline void
disable_irq_window(unsigned long cpu_exec_control)
{
if ( cpu_exec_control & CPU_BASED_VIRTUAL_INTR_PENDING ) {
cpu_exec_control &= ~CPU_BASED_VIRTUAL_INTR_PENDING;
__vmwrite(CPU_BASED_VM_EXEC_CONTROL, cpu_exec_control);
}
}
static inline int irq_masked(unsigned long eflags)
{
return ((eflags & X86_EFLAGS_IF) == 0);
}
void pic_irq_request(int *interrupt_request, int level)
{
if (level)
*interrupt_request = 1;
else
*interrupt_request = 0;
}
void vmx_pic_assist(struct vcpu *v)
{
global_iodata_t *spg;
u16 *virq_line, irqs;
struct vmx_virpic *pic = &v->domain->arch.vmx_platform.vmx_pic;
spg = &get_sp(v->domain)->sp_global;
virq_line = &spg->pic_clear_irr;
if ( *virq_line ) {
do {
irqs = *(volatile u16*)virq_line;
} while ( (u16)cmpxchg(virq_line,irqs, 0) != irqs );
do_pic_irqs_clear(pic, irqs);
}
virq_line = &spg->pic_irr;
if ( *virq_line ) {
do {
irqs = *(volatile u16*)virq_line;
} while ( (u16)cmpxchg(virq_line,irqs, 0) != irqs );
do_pic_irqs(pic, irqs);
}
}
int cpu_get_interrupt(struct vcpu *v, int *type)
{
int intno;
struct vmx_virpic *s = &v->domain->arch.vmx_platform.vmx_pic;
if ( (intno = cpu_get_apic_interrupt(v, type)) != -1 ) {
/* set irq request if a PIC irq is still pending */
/* XXX: improve that */
pic_update_irq(s);
return intno;
}
/* read the irq from the PIC */
if ( (intno = cpu_get_pic_interrupt(v, type)) != -1 )
return intno;
return -1;
}
asmlinkage void vmx_intr_assist(void)
{
int intr_type = 0;
int highest_vector;
unsigned long intr_fields, eflags, interruptibility, cpu_exec_control;
struct vcpu *v = current;
struct vmx_platform *plat=&v->domain->arch.vmx_platform;
struct vmx_virpit *vpit = &plat->vmx_pit;
struct vmx_virpic *pic= &plat->vmx_pic;
vmx_pic_assist(v);
__vmread_vcpu(v, CPU_BASED_VM_EXEC_CONTROL, &cpu_exec_control);
if ( vpit->pending_intr_nr ) {
pic_set_irq(pic, 0, 0);
pic_set_irq(pic, 0, 1);
}
__vmread(VM_ENTRY_INTR_INFO_FIELD, &intr_fields);
if (intr_fields & INTR_INFO_VALID_MASK) {
enable_irq_window(cpu_exec_control);
VMX_DBG_LOG(DBG_LEVEL_1, "vmx_intr_assist: intr_fields: %lx",
intr_fields);
return;
}
__vmread(GUEST_INTERRUPTIBILITY_INFO, &interruptibility);
if (interruptibility) {
enable_irq_window(cpu_exec_control);
VMX_DBG_LOG(DBG_LEVEL_1, "interruptibility: %lx",interruptibility);
return;
}
__vmread(GUEST_RFLAGS, &eflags);
if (irq_masked(eflags)) {
enable_irq_window(cpu_exec_control);
return;
}
highest_vector = cpu_get_interrupt(v, &intr_type);
if (highest_vector == -1) {
disable_irq_window(cpu_exec_control);
return;
}
switch (intr_type) {
case VLAPIC_DELIV_MODE_EXT:
case VLAPIC_DELIV_MODE_FIXED:
case VLAPIC_DELIV_MODE_LPRI:
vmx_inject_extint(v, highest_vector, VMX_INVALID_ERROR_CODE);
TRACE_3D(TRC_VMX_INT, v->domain->domain_id, highest_vector, 0);
break;
case VLAPIC_DELIV_MODE_SMI:
case VLAPIC_DELIV_MODE_NMI:
case VLAPIC_DELIV_MODE_INIT:
case VLAPIC_DELIV_MODE_STARTUP:
default:
printk("Unsupported interrupt type\n");
BUG();
break;
}
interrupt_post_injection(v, highest_vector, intr_type);
return;
}
void vmx_do_resume(struct vcpu *v)
{
struct vmx_virpit *vpit = &(v->domain->arch.vmx_platform.vmx_pit);
vmx_stts();
if (event_pending(v)) {
vmx_check_events(v);
if (test_bit(ARCH_VMX_IO_WAIT, &v->arch.arch_vmx.flags))
vmx_wait_io();
}
/* pick up the elapsed PIT ticks and re-enable pit_timer */
if ( vpit->first_injected ) {
pickup_deactive_ticks(vpit);
}
set_tsc_shift(v,vpit);
/* We can't resume the guest if we're waiting on I/O */
ASSERT(!test_bit(ARCH_VMX_IO_WAIT, &v->arch.arch_vmx.flags));
}
#endif /* CONFIG_VMX */
/* /*
* Local variables: * Local variables:
* mode: C * mode: C
@@ -1,6 +1,8 @@
/* /*
* vmx_platform.c: handling x86 platform related MMIO instructions * platform.c: handling x86 platform related MMIO instructions
*
* Copyright (c) 2004, Intel Corporation. * Copyright (c) 2004, Intel Corporation.
* Copyright (c) 2005, International Business Machines Corporation.
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@@ -14,7 +16,6 @@
* You should have received a copy of the GNU General Public License along with * You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., 59 Temple * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
* Place - Suite 330, Boston, MA 02111-1307 USA. * Place - Suite 330, Boston, MA 02111-1307 USA.
*
*/ */
#include <xen/config.h> #include <xen/config.h>
@@ -25,8 +26,10 @@
#include <asm/page.h> #include <asm/page.h>
#include <xen/event.h> #include <xen/event.h>
#include <xen/trace.h> #include <xen/trace.h>
#include <asm/vmx.h> #include <xen/sched.h>
#include <asm/vmx_platform.h> #include <asm/regs.h>
#include <asm/hvm/hvm.h>
#include <asm/hvm/support.h>
#include <public/hvm/ioreq.h> #include <public/hvm/ioreq.h>
#include <xen/lib.h> #include <xen/lib.h>
@@ -35,23 +38,13 @@
#if CONFIG_PAGING_LEVELS >= 3 #if CONFIG_PAGING_LEVELS >= 3
#include <asm/shadow_64.h> #include <asm/shadow_64.h>
#endif #endif
#ifdef CONFIG_VMX
#define DECODE_success 1 #define DECODE_success 1
#define DECODE_failure 0 #define DECODE_failure 0
#if defined (__x86_64__) extern long evtchn_send(int lport);
void store_cpu_user_regs(struct cpu_user_regs *regs)
{
__vmread(GUEST_SS_SELECTOR, &regs->ss);
__vmread(GUEST_RSP, &regs->rsp);
__vmread(GUEST_RFLAGS, &regs->rflags);
__vmread(GUEST_CS_SELECTOR, &regs->cs);
__vmread(GUEST_DS_SELECTOR, &regs->ds);
__vmread(GUEST_ES_SELECTOR, &regs->es);
__vmread(GUEST_RIP, &regs->rip);
}
#if defined (__x86_64__)
static inline long __get_reg_value(unsigned long reg, int size) static inline long __get_reg_value(unsigned long reg, int size)
{ {
switch(size) { switch(size) {
@@ -119,17 +112,6 @@ long get_reg_value(int size, int index, int seg, struct cpu_user_regs *regs)
} }
} }
#elif defined (__i386__) #elif defined (__i386__)
void store_cpu_user_regs(struct cpu_user_regs *regs)
{
__vmread(GUEST_SS_SELECTOR, &regs->ss);
__vmread(GUEST_RSP, &regs->esp);
__vmread(GUEST_RFLAGS, &regs->eflags);
__vmread(GUEST_CS_SELECTOR, &regs->cs);
__vmread(GUEST_DS_SELECTOR, &regs->ds);
__vmread(GUEST_ES_SELECTOR, &regs->es);
__vmread(GUEST_RIP, &regs->eip);
}
static inline long __get_reg_value(unsigned long reg, int size) static inline long __get_reg_value(unsigned long reg, int size)
{ {
switch(size) { switch(size) {
@@ -214,8 +196,6 @@ static inline unsigned char *check_prefix(unsigned char *inst,
thread_inst->op_size = WORD; thread_inst->op_size = WORD;
break; break;
case 0x67: case 0x67:
printf("Error: Not handling 0x67 (yet)\n");
domain_crash_synchronous();
break; break;
default: default:
return inst; return inst;
@@ -366,7 +346,7 @@ static int reg_mem(unsigned char size, unsigned char *opcode,
return DECODE_success; return DECODE_success;
} }
static int vmx_decode(int vm86, unsigned char *opcode, struct instruction *instr) static int hvm_decode(int realmode, unsigned char *opcode, struct instruction *instr)
{ {
unsigned char size_reg = 0; unsigned char size_reg = 0;
unsigned char rex = 0; unsigned char rex = 0;
@@ -376,7 +356,7 @@ static int vmx_decode(int vm86, unsigned char *opcode, struct instruction *instr
opcode = check_prefix(opcode, instr, &rex); opcode = check_prefix(opcode, instr, &rex);
if (vm86) { /* meaning is reversed */ if (realmode) { /* meaning is reversed */
if (instr->op_size == WORD) if (instr->op_size == WORD)
instr->op_size = LONG; instr->op_size = LONG;
else if (instr->op_size == LONG) else if (instr->op_size == LONG)
@@ -437,7 +417,7 @@ static int vmx_decode(int vm86, unsigned char *opcode, struct instruction *instr
} }
instr->operand[0] = mk_operand(size_reg, 0, 0, IMMEDIATE); instr->operand[0] = mk_operand(size_reg, 0, 0, IMMEDIATE);
instr->immediate = get_immediate(vm86, opcode+1, instr->op_size); instr->immediate = get_immediate(realmode, opcode+1, instr->op_size);
instr->operand[1] = mk_operand(size_reg, 0, 0, MEMORY); instr->operand[1] = mk_operand(size_reg, 0, 0, MEMORY);
switch (ins_subtype) { switch (ins_subtype) {
@@ -531,7 +511,7 @@ static int vmx_decode(int vm86, unsigned char *opcode, struct instruction *instr
instr->op_size = BYTE; instr->op_size = BYTE;
instr->operand[0] = mk_operand(instr->op_size, 0, 0, IMMEDIATE); instr->operand[0] = mk_operand(instr->op_size, 0, 0, IMMEDIATE);
instr->immediate = get_immediate(vm86, opcode+1, instr->op_size); instr->immediate = get_immediate(realmode, opcode+1, instr->op_size);
instr->operand[1] = mk_operand(instr->op_size, 0, 0, MEMORY); instr->operand[1] = mk_operand(instr->op_size, 0, 0, MEMORY);
return DECODE_success; return DECODE_success;
@@ -544,7 +524,7 @@ static int vmx_decode(int vm86, unsigned char *opcode, struct instruction *instr
GET_OP_SIZE_FOR_NONEBYTE(instr->op_size); GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
instr->operand[0] = mk_operand(instr->op_size, 0, 0, IMMEDIATE); instr->operand[0] = mk_operand(instr->op_size, 0, 0, IMMEDIATE);
instr->immediate = get_immediate(vm86, opcode+1, instr->op_size); instr->immediate = get_immediate(realmode, opcode+1, instr->op_size);
instr->operand[1] = mk_operand(instr->op_size, 0, 0, MEMORY); instr->operand[1] = mk_operand(instr->op_size, 0, 0, MEMORY);
return DECODE_success; return DECODE_success;
@@ -565,7 +545,7 @@ static int vmx_decode(int vm86, unsigned char *opcode, struct instruction *instr
} }
instr->operand[0] = mk_operand(size_reg, 0, 0, IMMEDIATE); instr->operand[0] = mk_operand(size_reg, 0, 0, IMMEDIATE);
instr->immediate = get_immediate(vm86, opcode+1, instr->op_size); instr->immediate = get_immediate(realmode, opcode+1, instr->op_size);
instr->operand[1] = mk_operand(size_reg, 0, 0, MEMORY); instr->operand[1] = mk_operand(size_reg, 0, 0, MEMORY);
return DECODE_success; return DECODE_success;
@@ -634,11 +614,60 @@ int inst_copy_from_guest(unsigned char *buf, unsigned long guest_eip, int inst_l
{ {
if (inst_len > MAX_INST_LEN || inst_len <= 0) if (inst_len > MAX_INST_LEN || inst_len <= 0)
return 0; return 0;
if (!vmx_copy(buf, guest_eip, inst_len, VMX_COPY_IN)) if (!hvm_copy(buf, guest_eip, inst_len, HVM_COPY_IN))
return 0; return 0;
return inst_len; return inst_len;
} }
void send_pio_req(struct cpu_user_regs *regs, unsigned long port,
unsigned long count, int size, long value, int dir, int pvalid)
{
struct vcpu *v = current;
vcpu_iodata_t *vio;
ioreq_t *p;
vio = get_vio(v->domain, v->vcpu_id);
if (vio == NULL) {
printk("bad shared page: %lx\n", (unsigned long) vio);
domain_crash_synchronous();
}
if (test_bit(ARCH_HVM_IO_WAIT, &v->arch.hvm_vcpu.ioflags)) {
printf("HVM I/O has not yet completed\n");
domain_crash_synchronous();
}
set_bit(ARCH_HVM_IO_WAIT, &v->arch.hvm_vcpu.ioflags);
p = &vio->vp_ioreq;
p->dir = dir;
p->pdata_valid = pvalid;
p->type = IOREQ_TYPE_PIO;
p->size = size;
p->addr = port;
p->count = count;
p->df = regs->eflags & EF_DF ? 1 : 0;
if (pvalid) {
if (hvm_paging_enabled(current))
p->u.pdata = (void *) gva_to_gpa(value);
else
p->u.pdata = (void *) value; /* guest VA == guest PA */
} else
p->u.data = value;
if (hvm_portio_intercept(p)) {
p->state = STATE_IORESP_READY;
hvm_io_assist(v);
return;
}
p->state = STATE_IOREQ_READY;
evtchn_send(iopacket_port(v->domain));
hvm_wait_io();
}
void send_mmio_req(unsigned char type, unsigned long gpa, void send_mmio_req(unsigned char type, unsigned long gpa,
unsigned long count, int size, long value, int dir, int pvalid) unsigned long count, int size, long value, int dir, int pvalid)
{ {
@@ -648,7 +677,7 @@ void send_mmio_req(unsigned char type, unsigned long gpa,
struct cpu_user_regs *regs; struct cpu_user_regs *regs;
extern long evtchn_send(int lport); extern long evtchn_send(int lport);
regs = current->arch.arch_vmx.mmio_op.inst_decoder_regs; regs = current->arch.hvm_vcpu.mmio_op.inst_decoder_regs;
vio = get_vio(v->domain, v->vcpu_id); vio = get_vio(v->domain, v->vcpu_id);
if (vio == NULL) { if (vio == NULL) {
@@ -658,12 +687,12 @@ void send_mmio_req(unsigned char type, unsigned long gpa,
p = &vio->vp_ioreq; p = &vio->vp_ioreq;
if (test_bit(ARCH_VMX_IO_WAIT, &v->arch.arch_vmx.flags)) { if (test_bit(ARCH_HVM_IO_WAIT, &v->arch.hvm_vcpu.ioflags)) {
printf("VMX I/O has not yet completed\n"); printf("HVM I/O has not yet completed\n");
domain_crash_synchronous(); domain_crash_synchronous();
} }
set_bit(ARCH_VMX_IO_WAIT, &v->arch.arch_vmx.flags); set_bit(ARCH_HVM_IO_WAIT, &v->arch.hvm_vcpu.ioflags);
p->dir = dir; p->dir = dir;
p->pdata_valid = pvalid; p->pdata_valid = pvalid;
@@ -674,23 +703,23 @@ void send_mmio_req(unsigned char type, unsigned long gpa,
p->df = regs->eflags & EF_DF ? 1 : 0; p->df = regs->eflags & EF_DF ? 1 : 0;
if (pvalid) { if (pvalid) {
if (vmx_paging_enabled(current)) if (hvm_paging_enabled(v))
p->u.pdata = (void *) gva_to_gpa(value); p->u.pdata = (void *) gva_to_gpa(value);
else else
p->u.pdata = (void *) value; /* guest VA == guest PA */ p->u.pdata = (void *) value; /* guest VA == guest PA */
} else } else
p->u.data = value; p->u.data = value;
if (vmx_mmio_intercept(p)){ if (hvm_mmio_intercept(p)){
p->state = STATE_IORESP_READY; p->state = STATE_IORESP_READY;
vmx_io_assist(v); hvm_io_assist(v);
return; return;
} }
p->state = STATE_IOREQ_READY; p->state = STATE_IOREQ_READY;
evtchn_send(iopacket_port(v->domain)); evtchn_send(iopacket_port(v->domain));
vmx_wait_io(); hvm_wait_io();
} }
static void mmio_operands(int type, unsigned long gpa, struct instruction *inst, static void mmio_operands(int type, unsigned long gpa, struct instruction *inst,
@@ -727,7 +756,7 @@ static void mmio_operands(int type, unsigned long gpa, struct instruction *inst,
} }
#define GET_REPEAT_COUNT() \ #define GET_REPEAT_COUNT() \
(mmio_inst.flags & REPZ ? (vm86 ? regs->ecx & 0xFFFF : regs->ecx) : 1) (mmio_inst.flags & REPZ ? (realmode ? regs->ecx & 0xFFFF : regs->ecx) : 1)
void handle_mmio(unsigned long va, unsigned long gpa) void handle_mmio(unsigned long va, unsigned long gpa)
{ {
@@ -736,17 +765,21 @@ void handle_mmio(unsigned long va, unsigned long gpa)
struct cpu_user_regs *regs; struct cpu_user_regs *regs;
struct instruction mmio_inst; struct instruction mmio_inst;
unsigned char inst[MAX_INST_LEN]; unsigned char inst[MAX_INST_LEN];
int i, vm86, ret; int i, realmode, ret;
struct vcpu *v = current;
mmio_opp = &current->arch.arch_vmx.mmio_op; mmio_opp = &v->arch.hvm_vcpu.mmio_op;
regs = mmio_opp->inst_decoder_regs; regs = mmio_opp->inst_decoder_regs;
store_cpu_user_regs(regs); hvm_store_cpu_guest_regs(v, regs);
__vmread(VM_EXIT_INSTRUCTION_LEN, &inst_len); if ((inst_len = hvm_instruction_length(v)) <= 0) {
printf("handle_mmio: failed to get instruction length\n");
domain_crash_synchronous();
}
vm86 = regs->eflags & X86_EFLAGS_VM; realmode = hvm_realmode(v);
if (vm86) if (realmode)
inst_addr = (regs->cs << 4) + regs->eip; inst_addr = (regs->cs << 4) + regs->eip;
else else
inst_addr = regs->eip; inst_addr = regs->eip;
@@ -754,13 +787,14 @@ void handle_mmio(unsigned long va, unsigned long gpa)
memset(inst, 0, MAX_INST_LEN); memset(inst, 0, MAX_INST_LEN);
ret = inst_copy_from_guest(inst, inst_addr, inst_len); ret = inst_copy_from_guest(inst, inst_addr, inst_len);
if (ret != inst_len) { if (ret != inst_len) {
printf("handle_mmio - EXIT: get guest instruction fault\n"); printf("handle_mmio: failed to copy instruction\n");
domain_crash_synchronous(); domain_crash_synchronous();
} }
init_instruction(&mmio_inst); init_instruction(&mmio_inst);
if (vmx_decode(vm86, inst, &mmio_inst) == DECODE_failure) { if (hvm_decode(realmode, inst, &mmio_inst) == DECODE_failure) {
printf("handle_mmio: failed to decode instruction\n");
printf("mmio opcode: va 0x%lx, gpa 0x%lx, len %ld:", printf("mmio opcode: va 0x%lx, gpa 0x%lx, len %ld:",
va, gpa, inst_len); va, gpa, inst_len);
for (i = 0; i < inst_len; i++) for (i = 0; i < inst_len; i++)
@@ -785,7 +819,7 @@ void handle_mmio(unsigned long va, unsigned long gpa)
int dir; int dir;
/* determine non-MMIO address */ /* determine non-MMIO address */
if (vm86) { if (realmode) {
if (((regs->es << 4) + (regs->edi & 0xFFFF)) == va) { if (((regs->es << 4) + (regs->edi & 0xFFFF)) == va) {
dir = IOREQ_WRITE; dir = IOREQ_WRITE;
addr = (regs->ds << 4) + (regs->esi & 0xFFFF); addr = (regs->ds << 4) + (regs->esi & 0xFFFF);
@@ -824,7 +858,7 @@ void handle_mmio(unsigned long va, unsigned long gpa)
regs->eip -= inst_len; /* do not advance %eip */ regs->eip -= inst_len; /* do not advance %eip */
if (dir == IOREQ_WRITE) if (dir == IOREQ_WRITE)
vmx_copy(&value, addr, size, VMX_COPY_IN); hvm_copy(&value, addr, size, HVM_COPY_IN);
send_mmio_req(IOREQ_TYPE_COPY, gpa, 1, size, value, dir, 0); send_mmio_req(IOREQ_TYPE_COPY, gpa, 1, size, value, dir, 0);
} else { } else {
if ((addr & PAGE_MASK) != ((addr + count * size - 1) & PAGE_MASK)) { if ((addr & PAGE_MASK) != ((addr + count * size - 1) & PAGE_MASK)) {
@@ -906,8 +940,6 @@ void handle_mmio(unsigned long va, unsigned long gpa)
} }
} }
#endif /* CONFIG_VMX */
/* /*
* Local variables: * Local variables:
* mode: C * mode: C
+517
View File
@@ -0,0 +1,517 @@
/*
* emulate.c: handling SVM emulate instructions help.
* Copyright (c) 2005 AMD Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., 59 Temple
* Place - Suite 330, Boston, MA 02111-1307 USA.
*
*/
#include <xen/config.h>
#include <xen/init.h>
#include <xen/lib.h>
#include <xen/trace.h>
#include <asm/msr.h>
#include <asm/hvm/hvm.h>
#include <asm/hvm/support.h>
#include <asm/hvm/svm/vmcb.h>
#include <asm/hvm/svm/emulate.h>
#ifdef CONFIG_SVM
extern int inst_copy_from_guest(unsigned char *buf, unsigned long guest_eip,
int inst_len);
#define REX_PREFIX_BASE 0x40
#define REX_X 0x02
#define REX_W 0x08
#define REX_R 0x04
#define REX_B 0x01
#define IS_REX_PREFIX(prefix) ((prefix & 0xf0) == REX_PREFIX_BASE)
#define DECODE_MODRM_MOD(modrm) ((modrm & 0xC0) >> 6)
#define DECODE_MODRM_REG(prefix, modrm) \
((prefix & REX_R) && IS_REX_PREFIX(prefix)) \
? (0x08 | ((modrm >> 3) & 0x07)) : ((modrm >> 3) & 0x07)
#define DECODE_MODRM_RM(prefix, modrm) \
((prefix & REX_B) && IS_REX_PREFIX(prefix)) \
? (0x08 | (modrm & 0x07)) : (modrm & 0x07)
#define DECODE_SIB_SCALE(sib) DECODE_MODRM_MOD(sib)
#define DECODE_SIB_INDEX(prefix, sib) \
((prefix & REX_X) && IS_REX_PREFIX(prefix)) \
? (0x08 | ((sib >> 3) & 0x07)) : ((sib >> 3) & 0x07)
#define DECODE_SIB_BASE(prefix, sib) DECODE_MODRM_RM(prefix, sib)
static inline unsigned long DECODE_GPR_VALUE(struct vmcb_struct *vmcb,
struct cpu_user_regs *regs, u8 gpr_rm)
{
unsigned long value;
switch (gpr_rm)
{
case 0x0:
value = regs->eax;
break;
case 0x1:
value = regs->ecx;
break;
case 0x2:
value = regs->edx;
break;
case 0x3:
value = regs->ebx;
break;
case 0x4:
value = (unsigned long)vmcb->rsp;
case 0x5:
value = regs->ebp;
break;
case 0x6:
value = regs->esi;
break;
case 0x7:
value = regs->edi;
break;
#if X86_64
case 0x8:
value = regs->r8;
break;
case 0x9:
value = regs->r9;
break;
case 0xA:
value = regs->r10;
break;
case 0xB:
value = regs->r11;
break;
case 0xC:
value = regs->r12;
break;
case 0xD:
value = regs->r13;
break;
case 0xE:
value = regs->r14;
break;
case 0xF:
value = regs->r15;
break;
#endif
default:
printk("Invlaid gpr_rm = %d\n", gpr_rm);
ASSERT(0);
value = (unsigned long)-1; /* error retrun */
}
return value;
}
#define CHECK_LENGTH64(num) \
if (num > length) \
{ \
*size = 0; \
return (unsigned long) -1; \
}
#if 0
/*
* hv_is_canonical - checks if the given address is canonical
*/
static inline u64 hv_is_canonical(u64 addr)
{
u64 bits = addr & (u64)0xffff800000000000;
return (u64)((bits == (u64)0xffff800000000000) || (bits == (u64)0x0));
}
#endif
#define modrm operand [0]
#define sib operand [1]
unsigned long get_effective_addr_modrm64(struct vmcb_struct *vmcb,
struct cpu_user_regs *regs, const u8 prefix, const u8 *operand,
u8 *size)
{
unsigned long effective_addr = (unsigned long) -1;
u8 length, modrm_mod, modrm_rm;
u32 disp = 0;
HVM_DBG_LOG(DBG_LEVEL_1, "get_effective_addr_modrm64(): prefix = %x, "
"length = %d, operand[0,1] = %x %x.\n", prefix, *size, operand [0],
operand [1]);
if ((NULL == size) || (NULL == operand) || (1 > *size))
{
*size = 0;
return effective_addr;
}
modrm_mod = DECODE_MODRM_MOD(modrm);
modrm_rm = DECODE_MODRM_RM(prefix, modrm);
length = *size;
*size = 1;
switch (modrm_rm)
{
case 0x4:
#if __x86_64__
case 0xC:
#endif
if (modrm_mod < 3)
{
*size = length;
effective_addr = get_effective_addr_sib(vmcb, regs, prefix, operand, size);
}
else
{
effective_addr = DECODE_GPR_VALUE(vmcb, regs, modrm_rm);
}
break;
case 0x5:
if (0 < modrm_mod)
{
effective_addr = regs->ebp;
*size = 1;
break;
}
CHECK_LENGTH64(*size + (u8)sizeof(u32));
memcpy (&disp, operand + 1, sizeof (u32));
*size += sizeof (u32);
if (vmcb->cs.attributes.fields.l) // 64-bit mode
return vmcb->rip + disp;
else
return disp;
#if __x86_64__
case 0xD:
if (0 < modrm_mod)
{
*size = 1;
effective_addr = regs->r13;
break;
}
CHECK_LENGTH64(*size + (u8)sizeof(u32));
memcpy (&disp, operand + 1, sizeof (u32));
*size += sizeof (u32);
/* 64-bit mode */
if (vmcb->cs.attributes.fields.l)
return vmcb->rip + disp;
else
return disp;
#endif
default:
effective_addr = DECODE_GPR_VALUE(vmcb, regs, modrm_rm);
}
if (3 > modrm_mod)
{
if (1 == modrm_mod )
{
CHECK_LENGTH64(*size + (u8)sizeof(u8));
disp = sib;
*size += sizeof (u8);
}
else if (2 == modrm_mod )
{
CHECK_LENGTH64(*size + sizeof (u32));
memcpy (&disp, operand + 1, sizeof (u32));
*size += sizeof (u32);
}
effective_addr += disp;
}
return effective_addr;
}
unsigned long get_effective_addr_sib(struct vmcb_struct *vmcb,
struct cpu_user_regs *regs, const u8 prefix, const u8 *operand,
u8 *size)
{
unsigned long base, effective_addr = (unsigned long)-1;
u8 sib_scale, sib_idx, sib_base, length;
u32 disp = 0;
if (NULL == size || NULL == operand || 2 > *size)
{
*size = 0;
return effective_addr;
}
sib_scale = DECODE_SIB_SCALE(sib);
sib_idx = DECODE_SIB_INDEX(prefix, sib);
sib_base = DECODE_SIB_BASE(prefix, sib);
base = DECODE_GPR_VALUE(vmcb, regs, sib_base);
if ((unsigned long)-1 == base)
{
/*
* Surely this is wrong. base should be allowed to be -1, even if
* it's not the usual case...
*/
*size = 0;
return base;
}
length = *size;
*size = 2;
if (0x5 == (sib_base & 0x5))
{
switch (DECODE_MODRM_MOD(modrm))
{
case 0:
CHECK_LENGTH64(*size + (u8)sizeof(u32));
memcpy (&disp, operand + 2, sizeof(u32));
*size += sizeof(u32);
base = disp;
break;
case 1:
CHECK_LENGTH64(*size + (u8)sizeof (u8));
*size += sizeof(u8);
base += operand [2];
break;
case 2:
CHECK_LENGTH64(*size + (u8)sizeof (u32));
memcpy(&disp, operand + 2, sizeof(u32));
*size += sizeof(u32);
base += disp;
}
}
if (4 == sib_idx)
return base;
effective_addr = DECODE_GPR_VALUE(vmcb, regs, sib_idx);
effective_addr <<= sib_scale;
return (effective_addr + base);
}
/* Get the register/mode number of src register in ModRM register. */
unsigned int decode_dest_reg(u8 m)
{
#if __x86_64__
ASSERT(0); /* Need to adjust for REX prefix if applicable */
#endif
return (m >> 3) & 7;
}
unsigned int decode_src_reg(u8 m)
{
#if __x86_64__
ASSERT(0); /* Need to adjust for REX prefix if applicable */
#endif
return m & 7;
}
unsigned long svm_rip2pointer(struct vmcb_struct *vmcb)
{
/*
* The following is subtle. Intuitively this code would be something like:
*
* if (16bit) addr = (cs << 4) + rip; else addr = rip;
*
* However, this code doesn't work for code executing after CR0.PE=0,
* but before the %cs has been updated. We don't get signalled when
* %cs is update, but fortunately, base contain the valid base address
* no matter what kind of addressing is used.
*/
return vmcb->cs.base + vmcb->rip;
}
#define MAKE_INSTR(nm, ...) static const u8 OPCODE_##nm[] = { __VA_ARGS__ }
/*
* Here's how it works:
* First byte: Length.
* Following bytes: Opcode bytes.
* Special case: Last byte, if zero, doesn't need to match.
*/
MAKE_INSTR(INVD, 2, 0x0f, 0x08);
MAKE_INSTR(CPUID, 2, 0x0f, 0xa2);
MAKE_INSTR(RDMSR, 2, 0x0f, 0x32);
MAKE_INSTR(WRMSR, 2, 0x0f, 0x30);
MAKE_INSTR(RDTSC, 2, 0x0f, 0x31);
MAKE_INSTR(RDTSCP, 3, 0x0f, 0x01, 0xf9);
MAKE_INSTR(CLI, 1, 0xfa);
MAKE_INSTR(STI, 1, 0xfb);
MAKE_INSTR(RDPMC, 2, 0x0f, 0x33);
MAKE_INSTR(CLGI, 3, 0x0f, 0x01, 0xdd);
MAKE_INSTR(STGI, 3, 0x0f, 0x01, 0xdc);
MAKE_INSTR(VMRUN, 3, 0x0f, 0x01, 0xd8);
MAKE_INSTR(VMLOAD, 3, 0x0f, 0x01, 0xda);
MAKE_INSTR(VMSAVE, 3, 0x0f, 0x01, 0xdb);
MAKE_INSTR(VMCALL, 3, 0x0f, 0x01, 0xd9);
MAKE_INSTR(PAUSE, 2, 0xf3, 0x90);
MAKE_INSTR(SKINIT, 3, 0x0f, 0x01, 0xde);
MAKE_INSTR(MOV2CR, 3, 0x0f, 0x22, 0x00);
MAKE_INSTR(MOVCR2, 3, 0x0f, 0x20, 0x00);
MAKE_INSTR(MOV2DR, 3, 0x0f, 0x23, 0x00);
MAKE_INSTR(MOVDR2, 3, 0x0f, 0x21, 0x00);
MAKE_INSTR(PUSHF, 1, 0x9c);
MAKE_INSTR(POPF, 1, 0x9d);
MAKE_INSTR(RSM, 2, 0x0f, 0xaa);
MAKE_INSTR(INVLPG, 3, 0x0f, 0x01, 0x00);
MAKE_INSTR(INVLPGA,3, 0x0f, 0x01, 0xdf);
MAKE_INSTR(HLT, 1, 0xf4);
MAKE_INSTR(CLTS, 2, 0x0f, 0x06);
MAKE_INSTR(LMSW, 3, 0x0f, 0x01, 0x00);
MAKE_INSTR(SMSW, 3, 0x0f, 0x01, 0x00);
static const u8 *opc_bytes[INSTR_MAX_COUNT] =
{
[INSTR_INVD] = OPCODE_INVD,
[INSTR_CPUID] = OPCODE_CPUID,
[INSTR_RDMSR] = OPCODE_RDMSR,
[INSTR_WRMSR] = OPCODE_WRMSR,
[INSTR_RDTSC] = OPCODE_RDTSC,
[INSTR_RDTSCP] = OPCODE_RDTSCP,
[INSTR_CLI] = OPCODE_CLI,
[INSTR_STI] = OPCODE_STI,
[INSTR_RDPMC] = OPCODE_RDPMC,
[INSTR_CLGI] = OPCODE_CLGI,
[INSTR_STGI] = OPCODE_STGI,
[INSTR_VMRUN] = OPCODE_VMRUN,
[INSTR_VMLOAD] = OPCODE_VMLOAD,
[INSTR_VMSAVE] = OPCODE_VMSAVE,
[INSTR_VMCALL] = OPCODE_VMCALL,
[INSTR_PAUSE] = OPCODE_PAUSE,
[INSTR_SKINIT] = OPCODE_SKINIT,
[INSTR_MOV2CR] = OPCODE_MOV2CR,
[INSTR_MOVCR2] = OPCODE_MOVCR2,
[INSTR_MOV2DR] = OPCODE_MOV2DR,
[INSTR_MOVDR2] = OPCODE_MOVDR2,
[INSTR_PUSHF] = OPCODE_PUSHF,
[INSTR_POPF] = OPCODE_POPF,
[INSTR_RSM] = OPCODE_RSM,
[INSTR_INVLPG] = OPCODE_INVLPG,
[INSTR_INVLPGA]= OPCODE_INVLPGA,
[INSTR_CLTS] = OPCODE_CLTS,
[INSTR_HLT] = OPCODE_HLT,
[INSTR_LMSW] = OPCODE_LMSW,
[INSTR_SMSW] = OPCODE_SMSW
};
/*
* Intel has a vmcs entry to give the instruction length. AMD doesn't. So we
* have to do a little bit of work to find out...
*
* The caller can either pass a NULL pointer to the guest_eip_buf, or a pointer
* to enough bytes to satisfy the instruction including prefix bytes.
*/
unsigned int __get_instruction_length_from_list(struct vmcb_struct *vmcb,
enum instruction_index *list, unsigned int list_count,
u8 *guest_eip_buf, enum instruction_index *match)
{
unsigned int inst_len = 0;
unsigned int i;
unsigned int j;
int found = 0;
enum instruction_index instr = 0;
u8 buffer[MAX_INST_LEN];
u8 *buf;
const u8 *opcode = NULL;
if (guest_eip_buf)
{
buf = guest_eip_buf;
}
else
{
inst_copy_from_guest(buffer, svm_rip2pointer(vmcb), MAX_INST_LEN);
buf = buffer;
}
for (j = 0; j < list_count; j++)
{
instr = list[j];
opcode = opc_bytes[instr];
ASSERT(opcode);
while (inst_len < MAX_INST_LEN &&
is_prefix(buf[inst_len]) &&
!is_prefix(opcode[1]))
inst_len++;
ASSERT(opcode[0] <= 15); /* Make sure the table is correct. */
found = 1;
for (i = 0; i < opcode[0]; i++)
{
/* If the last byte is zero, we just accept it without checking */
if (i == opcode[0]-1 && opcode[i+1] == 0)
break;
if (buf[inst_len+i] != opcode[i+1])
{
found = 0;
break;
}
}
if (found)
break;
}
/* It's a match */
if (found)
{
inst_len += opcode[0];
ASSERT(inst_len <= MAX_INST_LEN);
if (match)
*match = instr;
return inst_len;
}
printk("%s: Mismatch between expected and actual instruction bytes: "
"eip = %lx\n", __func__, (unsigned long)vmcb->rip);
return 0;
}
#endif /* CONFIG_SVM */
/*
* Local variables:
* mode: C
* c-set-style: "BSD"
* c-basic-offset: 4
* tab-width: 4
* indent-tabs-mode: nil
* End:
*/
Loaded 100 of 158 files, more files were not shown because too many files have changed in this diff. Show more
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.