mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 02:01:24 +01:00
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:
1 parent
bd0e34a173
commit
d1bd157fbc
158 files changed
+8781
-2310
No files matched your search
@@ -108,6 +108,8 @@
|
||||
^tools/firmware/.*\.sym$
|
||||
^tools/firmware/.*bios/.*bios.*\.txt$
|
||||
^tools/firmware/acpi/acpigen$
|
||||
^tools/firmware/hvmloader/hvmloader$
|
||||
^tools/firmware/hvmloader/roms\.h$
|
||||
^tools/firmware/rombios/BIOS-bochs-latest$
|
||||
^tools/firmware/rombios/_rombios_\.c$
|
||||
^tools/firmware/rombios/rombios\.s$
|
||||
|
||||
+1
-1
@@ -137,7 +137,7 @@ support Xen, a key feature is that user space applications and
|
||||
libraries \emph{do not} require modification.
|
||||
|
||||
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
|
||||
additional driver support is necessary within Xen itself. Unlike
|
||||
traditional full virtualization hypervisors, which suffer a tremendous
|
||||
|
||||
@@ -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 */
|
||||
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;
|
||||
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 */
|
||||
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;
|
||||
if (page != ctxt->page_phys[vcpu] || protection != ctxt->page_perm[vcpu])
|
||||
{
|
||||
|
||||
@@ -16,7 +16,7 @@ XEN_CONFIG_DIR = /etc/xen
|
||||
XEN_CONFIGS = xend-config.sxp
|
||||
XEN_CONFIGS += xmexample1
|
||||
XEN_CONFIGS += xmexample2
|
||||
XEN_CONFIGS += xmexample.vmx
|
||||
XEN_CONFIGS += xmexample.hvm
|
||||
XEN_CONFIGS += xmexample.vti
|
||||
|
||||
# Xen script dir and scripts to go there.
|
||||
|
||||
@@ -32,6 +32,6 @@ xmexample2 - a more complex configuration script for 'xm create'
|
||||
xmexample3 - an advanced configuration script for 'xm create'
|
||||
that utilizes the vmid
|
||||
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'
|
||||
xmexample.vti - a configuration script for creating a domain on vti
|
||||
@@ -15,25 +15,25 @@ else:
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# Kernel image file.
|
||||
kernel = "/usr/lib/xen/boot/vmxloader"
|
||||
kernel = "/usr/lib/xen/boot/hvmloader"
|
||||
|
||||
# The domain build function. VMX domain uses 'vmx'.
|
||||
builder='vmx'
|
||||
# The domain build function. HVM domain uses 'hvm'.
|
||||
builder='hvm'
|
||||
|
||||
# Initial memory allocation (in megabytes) for the new domain.
|
||||
memory = 128
|
||||
|
||||
# A name for your domain. All domains must have different names.
|
||||
name = "ExampleVMXDomain"
|
||||
name = "ExampleHVMDomain"
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# the number of cpus guest platform has, default=1
|
||||
#vcpus=1
|
||||
|
||||
# enable/disalbe vmx guest ACPI, default=0 (disabled)
|
||||
# enable/disable HVM guest ACPI, default=0 (disabled)
|
||||
#acpi=0
|
||||
|
||||
# enable/disalbe vmx guest APIC, default=0 (disabled)
|
||||
# enable/disable HVM guest APIC, default=0 (disabled)
|
||||
#apic=0
|
||||
|
||||
# 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' ]
|
||||
# type=ioemu specify the NIC is an ioemu device not netfront
|
||||
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
|
||||
@@ -1,9 +1,9 @@
|
||||
XEN_ROOT = ../..
|
||||
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.
|
||||
TARGET := vmxassist/vmxloader
|
||||
TARGET := hvmloader/hvmloader
|
||||
INSTALL_DIR := $(DESTDIR)/usr/lib/xen/boot
|
||||
|
||||
SUBDIRS :=
|
||||
@@ -11,6 +11,7 @@ SUBDIRS += rombios
|
||||
SUBDIRS += vgabios
|
||||
SUBDIRS += acpi
|
||||
SUBDIRS += vmxassist
|
||||
SUBDIRS += hvmloader
|
||||
|
||||
.PHONY: all install clean
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
Domain FirmWare support
|
||||
Domain firmware support
|
||||
-----------------------
|
||||
|
||||
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
|
||||
operating systems. However, since most OSes rely on BIOS support during
|
||||
their early bringup, we need to provide a surrogate ROMBIOS and VGABIOS
|
||||
firmware layer.
|
||||
as Intel's VT or AMD's SVM extensions) is the ability to run unmodified
|
||||
guest operating systems. However, since most OSes rely on BIOS support
|
||||
during their early bringup, we need to provide a surrogate ROMBIOS and
|
||||
VGABIOS firmware layer.
|
||||
|
||||
What's more, we need to support real-mode which is required by
|
||||
the firmware and bootstrap loaders. Real-mode support is especially
|
||||
|
||||
@@ -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 */
|
||||
}
|
||||
|
||||
|
||||
static void *
|
||||
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.
|
||||
* 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
|
||||
* Place - Suite 330, Boston, MA 02111-1307 USA.
|
||||
*/
|
||||
#include "machine.h"
|
||||
#include "roms.h"
|
||||
#include "../acpi/acpi2_0.h" /* for ACPI_PHYSICAL_ADDRESS */
|
||||
|
||||
#include "acpi.h"
|
||||
#include "../acpi/acpi2_0.h" // for ACPI_PHYSICAL_ADDRESS
|
||||
int acpi_madt_update(unsigned char* acpi_start);
|
||||
int get_acpi_enabled(void);
|
||||
/* memory map */
|
||||
#define VGABIOS_PHYSICAL_ADDRESS 0x000C0000
|
||||
#define VMXASSIST_PHYSICAL_ADDRESS 0x000D0000
|
||||
#define ROMBIOS_PHYSICAL_ADDRESS 0x000F0000
|
||||
|
||||
/* invoke SVM's paged realmode support */
|
||||
#define SVM_VMMCALL_RESET_TO_REALMODE 0x00000001
|
||||
|
||||
/*
|
||||
* C runtime start off
|
||||
@@ -66,6 +69,30 @@ asm(
|
||||
"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 *
|
||||
memcpy(void *dest, const void *src, unsigned n)
|
||||
{
|
||||
@@ -103,38 +130,82 @@ cirrus_check(void)
|
||||
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
|
||||
main(void)
|
||||
{
|
||||
puts("VMXAssist Loader\n");
|
||||
puts("HVM Loader\n");
|
||||
|
||||
puts("Loading ROMBIOS ...\n");
|
||||
memcpy((void *)0xF0000, rombios, sizeof(rombios));
|
||||
memcpy((void *)ROMBIOS_PHYSICAL_ADDRESS, rombios, sizeof(rombios));
|
||||
if (cirrus_check()) {
|
||||
puts("Loading Cirrus VGABIOS ...\n");
|
||||
memcpy((void *)0xC0000,
|
||||
memcpy((void *)VGABIOS_PHYSICAL_ADDRESS,
|
||||
vgabios_cirrusvga, sizeof(vgabios_cirrusvga));
|
||||
} else {
|
||||
puts("Loading Standard VGABIOS ...\n");
|
||||
memcpy((void *)0xC0000,
|
||||
memcpy((void *)VGABIOS_PHYSICAL_ADDRESS,
|
||||
vgabios_stdvga, sizeof(vgabios_stdvga));
|
||||
}
|
||||
|
||||
if (get_acpi_enabled() != 0) {
|
||||
puts("Loading ACPI ...\n");
|
||||
acpi_madt_update((unsigned char*)acpi);
|
||||
acpi_madt_update((unsigned char *) acpi);
|
||||
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.
|
||||
*/
|
||||
memcpy((void *)ACPI_PHYSICAL_ADDRESS, acpi, sizeof(acpi));
|
||||
memcpy((void *)ACPI_PHYSICAL_ADDRESS, acpi,
|
||||
sizeof(acpi));
|
||||
}
|
||||
}
|
||||
|
||||
puts("Loading VMXAssist ...\n");
|
||||
memcpy((void *)TEXTADDR, vmxassist, sizeof(vmxassist));
|
||||
if (check_amd()) {
|
||||
/* 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");
|
||||
asm volatile ( "jmp *%%eax" : : "a" (TEXTADDR), "d" (0) );
|
||||
puts("VMX go ...\n");
|
||||
__asm__ __volatile__(
|
||||
"jmp *%%eax"
|
||||
: : "a" (VMXASSIST_PHYSICAL_ADDRESS), "d" (0)
|
||||
);
|
||||
}
|
||||
|
||||
puts("Failed to invoke ROMBIOS\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
Executable → Regular
File renamed without changes.
@@ -26,8 +26,8 @@
|
||||
|
||||
// ROM BIOS for use with Bochs/Plex x86 emulation environment
|
||||
|
||||
#define VMXASSIST
|
||||
#undef VMXTEST
|
||||
#define HVMASSIST
|
||||
#undef HVMTEST
|
||||
|
||||
// Xen full virtualization does not handle unaligned IO with page crossing.
|
||||
// Disable 32-bit PIO as a workaround.
|
||||
@@ -177,8 +177,8 @@
|
||||
#define BASE_MEM_IN_K (640 - EBDA_SIZE)
|
||||
|
||||
// Define the application NAME
|
||||
#ifdef VMXASSIST
|
||||
# define BX_APPNAME "VMXAssist"
|
||||
#ifdef HVMASSIST
|
||||
# define BX_APPNAME "HVMAssist"
|
||||
#elif PLEX86
|
||||
# define BX_APPNAME "Plex86"
|
||||
#else
|
||||
@@ -1430,7 +1430,7 @@ ASM_START
|
||||
ASM_END
|
||||
}
|
||||
|
||||
#ifdef VMXASSIST
|
||||
#ifdef HVMASSIST
|
||||
void
|
||||
copy_e820_table()
|
||||
{
|
||||
@@ -1440,7 +1440,7 @@ copy_e820_table()
|
||||
write_word(0xe000, 0x8, nr_entries);
|
||||
memcpyb(0xe000, 0x10, 0x9000, 0x2d0, nr_entries * 0x14);
|
||||
}
|
||||
#endif /* VMXASSIST */
|
||||
#endif /* HVMASSIST */
|
||||
|
||||
#if BX_DEBUG_SERIAL
|
||||
/* serial debug port*/
|
||||
@@ -1520,7 +1520,7 @@ send(action, c)
|
||||
if (c == '\n') uart_tx_byte(BX_DEBUG_PORT, '\r');
|
||||
uart_tx_byte(BX_DEBUG_PORT, c);
|
||||
#endif
|
||||
#ifdef VMXASSIST
|
||||
#ifdef HVMASSIST
|
||||
outb(0xE9, c);
|
||||
#endif
|
||||
#if BX_VIRTUAL_PORTS
|
||||
@@ -4089,7 +4089,7 @@ ASM_END
|
||||
case 0x20: // coded by osmaker aka K.J.
|
||||
if(regs.u.r32.edx == 0x534D4150) /* SMAP */
|
||||
{
|
||||
#ifdef VMXASSIST
|
||||
#ifdef HVMASSIST
|
||||
if ((regs.u.r16.bx / 0x14) * 0x14 == regs.u.r16.bx) {
|
||||
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)
|
||||
mov al, #0x34 ; timer0: binary count, 16bit count, mode 2
|
||||
out 0x43, al
|
||||
#ifdef VMXASSIST
|
||||
#ifdef HVMASSIST
|
||||
mov al, #0x0b ; #0xe90b = 20 Hz (temporary, until we fix xen/vmx support)
|
||||
out 0x40, al ; lsb
|
||||
mov al, #0xe9
|
||||
@@ -9702,22 +9702,10 @@ post_default_ints:
|
||||
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
|
||||
@@ -9734,7 +9722,7 @@ post_default_ints:
|
||||
#endif
|
||||
out 0xa1, AL ;slave pic: unmask IRQ 12, 13, 14
|
||||
|
||||
#ifdef VMXASSIST
|
||||
#ifdef HVMASSIST
|
||||
call _copy_e820_table
|
||||
#endif
|
||||
|
||||
@@ -10368,13 +10356,13 @@ dummy_iret_handler:
|
||||
HALT(__LINE__)
|
||||
iret
|
||||
|
||||
#ifdef VMXTEST
|
||||
#ifdef HVMTEST
|
||||
.org 0xffe0
|
||||
jmp 0xf000:post;
|
||||
#endif
|
||||
|
||||
.org 0xfff0 ; Power-up Entry Point
|
||||
#ifdef VMXTEST
|
||||
#ifdef HVMTEST
|
||||
jmp 0xd000:0x0003;
|
||||
#else
|
||||
jmp 0xf000:post
|
||||
|
||||
@@ -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
|
||||
@@ -37,13 +37,7 @@ LDFLAGS = -m elf_i386
|
||||
|
||||
OBJECTS = head.o trap.o vm86.o setup.o util.o
|
||||
|
||||
all: vmxloader
|
||||
|
||||
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
|
||||
all: vmxassist.bin
|
||||
|
||||
vmxassist.bin: vmxassist.ld $(OBJECTS)
|
||||
$(CPP) $(DEFINES) vmxassist.ld > vmxassist.tmp
|
||||
@@ -68,15 +62,6 @@ setup.o: machine.h setup.c
|
||||
util.o: machine.h 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
|
||||
./gen > offsets.h
|
||||
|
||||
@@ -84,7 +69,7 @@ gen: gen.c
|
||||
$(HOSTCC) $(HOSTCFLAGS) -I. $(XENINC) -o gen gen.c
|
||||
|
||||
clean:
|
||||
rm -f vmxassist vmxassist.tmp vmxassist.bin vmxassist.run vmxassist.sym head.s roms.h acpi.h
|
||||
rm -f vmxloader vmxloader.tmp vmxloader.o $(OBJECTS)
|
||||
rm -f vmxassist vmxassist.tmp vmxassist.bin vmxassist.run vmxassist.sym head.s
|
||||
rm -f $(OBJECTS)
|
||||
rm -f gen gen.o offsets.h
|
||||
|
||||
@@ -111,6 +111,9 @@ _start:
|
||||
cli
|
||||
|
||||
/* save register parameters to C land */
|
||||
#ifdef TEST
|
||||
xorl %edx, %edx
|
||||
#endif
|
||||
movl %edx, booting_cpu
|
||||
movl %ebx, booting_vector
|
||||
|
||||
|
||||
@@ -193,6 +193,12 @@ setup_pic(void)
|
||||
outb(PIC_SLAVE + PIC_IMR, 0);
|
||||
}
|
||||
|
||||
void
|
||||
setiomap(int port)
|
||||
{
|
||||
tss.iomap[port >> 3] |= 1 << (port & 7);
|
||||
}
|
||||
|
||||
void
|
||||
enter_real_mode(struct regs *regs)
|
||||
{
|
||||
@@ -217,6 +223,13 @@ enter_real_mode(struct regs *regs)
|
||||
}
|
||||
regs->uesp = 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",
|
||||
regs->cs, regs->eip);
|
||||
|
||||
|
||||
@@ -738,6 +738,83 @@ interrupt(struct regs *regs, int n)
|
||||
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 };
|
||||
|
||||
/*
|
||||
@@ -885,6 +962,16 @@ opcode(struct regs *regs)
|
||||
}
|
||||
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 */
|
||||
if ((mode == VM86_REAL_TO_PROTECTED) ||
|
||||
(mode == VM86_PROTECTED_TO_REAL)) {
|
||||
@@ -903,6 +990,16 @@ opcode(struct regs *regs)
|
||||
}
|
||||
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 */
|
||||
TRACE((regs, regs->eip - eip, "lock"));
|
||||
continue;
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
* vmxassist.ld
|
||||
*/
|
||||
OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
|
||||
/*OUTPUT_ARCH(i386)*/
|
||||
ENTRY(_start)
|
||||
|
||||
SECTIONS
|
||||
|
||||
@@ -584,5 +584,5 @@ static inline target_ulong get_phys_addr_code(CPUState *env, target_ulong addr)
|
||||
|
||||
//#define DEBUG_UNUSED_IOPORT
|
||||
//#define DEBUG_IOPORT
|
||||
#define TARGET_VMX
|
||||
#define TARGET_HVM
|
||||
|
||||
+16
-16
@@ -50,7 +50,7 @@ typedef struct PITChannelState {
|
||||
int64_t next_transition_time;
|
||||
QEMUTimer *irq_timer;
|
||||
int irq;
|
||||
int vmx_channel; /* Is this accelerated by VMX ? */
|
||||
int hvm_channel; /* Is this accelerated by HVM ? */
|
||||
} PITChannelState;
|
||||
|
||||
struct PITState {
|
||||
@@ -61,8 +61,8 @@ static PITState pit_state;
|
||||
|
||||
static void pit_irq_timer_update(PITChannelState *s, int64_t current_time);
|
||||
|
||||
/* currently operate which channel for vmx use */
|
||||
int vmx_channel = -1;
|
||||
/* currently operate which channel for hvm use */
|
||||
int hvm_channel = -1;
|
||||
extern FILE *logfile;
|
||||
static int pit_get_count(PITChannelState *s)
|
||||
{
|
||||
@@ -215,7 +215,7 @@ int pit_get_gate(PITState *pit, int channel)
|
||||
return s->gate;
|
||||
}
|
||||
|
||||
void pit_reset_vmx_vectors()
|
||||
void pit_reset_hvm_vectors()
|
||||
{
|
||||
extern shared_iopage_t *shared_page;
|
||||
ioreq_t *req;
|
||||
@@ -225,18 +225,18 @@ void pit_reset_vmx_vectors()
|
||||
irq = 0;
|
||||
|
||||
for(i = 0; i < 3; i++) {
|
||||
if (pit_state.channels[i].vmx_channel)
|
||||
if (pit_state.channels[i].hvm_channel)
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == 3)
|
||||
return;
|
||||
|
||||
/* Assumes just one VMX accelerated channel */
|
||||
vmx_channel = i;
|
||||
s = &pit_state.channels[vmx_channel];
|
||||
/* Assumes just one HVM accelerated channel */
|
||||
hvm_channel = i;
|
||||
s = &pit_state.channels[hvm_channel];
|
||||
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->state = STATE_IORESP_HOOK;
|
||||
@@ -247,9 +247,9 @@ void pit_reset_vmx_vectors()
|
||||
*/
|
||||
req->u.data = s->count;
|
||||
req->u.data |= (irq << 16);
|
||||
req->u.data |= (vmx_channel << 24);
|
||||
req->u.data |= (hvm_channel << 24);
|
||||
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)
|
||||
@@ -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
|
||||
* timer so the channel never send intr from device model*/
|
||||
if (vmx_channel != -1 && s->mode == 2) {
|
||||
pit_reset_vmx_vectors();
|
||||
vmx_channel = -1;
|
||||
if (hvm_channel != -1 && s->mode == 2) {
|
||||
pit_reset_hvm_vectors();
|
||||
hvm_channel = -1;
|
||||
}
|
||||
|
||||
/* 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 {
|
||||
s = &pit->channels[addr];
|
||||
s->vmx_channel = 1;
|
||||
vmx_channel = addr;
|
||||
s->hvm_channel = 1;
|
||||
hvm_channel = addr;
|
||||
switch(s->write_state) {
|
||||
default:
|
||||
case RW_STATE_LSB:
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
//#define DEBUG_IRQ_LATENCY
|
||||
//#define DEBUG_IRQ_COUNT
|
||||
|
||||
extern void pit_reset_vmx_vectors();
|
||||
extern void pit_reset_hvm_vectors();
|
||||
|
||||
typedef struct PicState {
|
||||
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:
|
||||
s->irq_base = val & 0xf8;
|
||||
s->init_state = 2;
|
||||
pit_reset_vmx_vectors();
|
||||
pit_reset_hvm_vectors();
|
||||
break;
|
||||
case 2:
|
||||
if (s->init4) {
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
destroy_vmx_domain();
|
||||
destroy_hvm_domain();
|
||||
exit(0);
|
||||
}
|
||||
|
||||
@@ -506,8 +506,8 @@ static term_cmd_t info_cmds[] = {
|
||||
"", "show i8259 (PIC) state", },
|
||||
{ "pci", "", pci_info,
|
||||
"", "show PCI info", },
|
||||
{ "vmxiopage", "", sp_info,
|
||||
"", "show VMX device model shared page info", },
|
||||
{ "hvmiopage", "", sp_info,
|
||||
"", "show HVM device model shared page info", },
|
||||
{ NULL, NULL, },
|
||||
};
|
||||
|
||||
@@ -700,7 +700,7 @@ static void monitor_handle_command(const char *cmdline)
|
||||
args[nb_args++] = (void *)has_option;
|
||||
}
|
||||
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 'i':
|
||||
default:
|
||||
@@ -772,14 +772,14 @@ static void monitor_handle_command1(void *opaque, const char *cmdline)
|
||||
|
||||
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)
|
||||
{
|
||||
monitor_hd = hd;
|
||||
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);
|
||||
monitor_start_input();
|
||||
|
||||
@@ -20,7 +20,9 @@
|
||||
|
||||
/*
|
||||
* Main cpu loop for handling I/O requests coming from a virtual machine
|
||||
*
|
||||
* Copyright © 2004, Intel Corporation.
|
||||
* Copyright © 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 Lesser General Public License,
|
||||
@@ -394,7 +396,7 @@ void cpu_handle_ioreq(CPUState *env)
|
||||
int xc_handle;
|
||||
|
||||
void
|
||||
destroy_vmx_domain(void)
|
||||
destroy_hvm_domain(void)
|
||||
{
|
||||
extern FILE* logfile;
|
||||
char destroy_cmd[32];
|
||||
@@ -467,11 +469,11 @@ int main_loop(void)
|
||||
(void)ioctl(evtchn_fd, IOCTL_EVTCHN_NOTIFY, ¬ify);
|
||||
}
|
||||
}
|
||||
destroy_vmx_domain();
|
||||
destroy_hvm_domain();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void qemu_vmx_reset(void *unused)
|
||||
static void qemu_hvm_reset(void *unused)
|
||||
{
|
||||
char cmd[64];
|
||||
|
||||
@@ -489,7 +491,7 @@ CPUState * cpu_init()
|
||||
int rc;
|
||||
|
||||
cpu_exec_init();
|
||||
qemu_register_reset(qemu_vmx_reset, NULL);
|
||||
qemu_register_reset(qemu_hvm_reset, NULL);
|
||||
env = malloc(sizeof(CPUX86State));
|
||||
if (!env)
|
||||
return NULL;
|
||||
|
||||
+4
-4
@@ -125,7 +125,7 @@ static char network_script[1024];
|
||||
int pit_min_timer_count = 0;
|
||||
int nb_nics;
|
||||
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];
|
||||
QEMUTimer *gui_timer;
|
||||
QEMUTimer *polling_timer;
|
||||
@@ -826,8 +826,8 @@ static void init_timers(void)
|
||||
{
|
||||
/* get times() syscall frequency */
|
||||
timer_freq = sysconf(_SC_CLK_TCK);
|
||||
|
||||
#ifndef TARGET_VMX
|
||||
|
||||
#ifndef TARGET_HVM
|
||||
/* timer signal */
|
||||
sigfillset(&act.sa_mask);
|
||||
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_FREQ) / 1000000;
|
||||
}
|
||||
#endif /* TARGET_VMX */
|
||||
#endif /* TARGET_HVM */
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ else
|
||||
BUILD_SRCS += xc_load_aout9.c
|
||||
BUILD_SRCS += xc_linux_restore.c
|
||||
BUILD_SRCS += xc_linux_save.c
|
||||
BUILD_SRCS += xc_vmx_build.c
|
||||
BUILD_SRCS += xc_hvm_build.c
|
||||
endif
|
||||
|
||||
CFLAGS += -Wall
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/******************************************************************************
|
||||
* xc_vmx_build.c
|
||||
* xc_hvm_build.c
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
@@ -12,7 +12,7 @@
|
||||
#include <xen/hvm/hvm_info_table.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 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
|
||||
* 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,
|
||||
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;
|
||||
struct hvm_info_table *va_hvm;
|
||||
|
||||
|
||||
va_map = xc_map_foreign_range(
|
||||
xc_handle,
|
||||
dom,
|
||||
@@ -302,7 +303,7 @@ static int setup_guest(int xc_handle,
|
||||
unsigned long shared_info_frame,
|
||||
unsigned int control_evtchn,
|
||||
unsigned int vcpus,
|
||||
unsigned int acpi,
|
||||
unsigned int acpi,
|
||||
unsigned int apic,
|
||||
unsigned int store_evtchn,
|
||||
unsigned long *store_mfn)
|
||||
@@ -357,7 +358,7 @@ static int setup_guest(int xc_handle,
|
||||
vpt_end = vpt_start + (nr_pt_pages * PAGE_SIZE);
|
||||
|
||||
printf("VIRTUAL MEMORY ARRANGEMENT:\n"
|
||||
" Loaded VMX loader: %08lx->%08lx\n"
|
||||
" Loaded HVM loader: %08lx->%08lx\n"
|
||||
" Page tables: %08lx->%08lx\n"
|
||||
" TOTAL: %08lx->%08lx\n",
|
||||
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) ) {
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -595,13 +596,13 @@ static int setup_guest(int xc_handle,
|
||||
return -1;
|
||||
}
|
||||
|
||||
int xc_vmx_build(int xc_handle,
|
||||
int xc_hvm_build(int xc_handle,
|
||||
uint32_t domid,
|
||||
int memsize,
|
||||
const char *image_name,
|
||||
unsigned int control_evtchn,
|
||||
unsigned int vcpus,
|
||||
unsigned int acpi,
|
||||
unsigned int acpi,
|
||||
unsigned int apic,
|
||||
unsigned int store_evtchn,
|
||||
unsigned long *store_mfn)
|
||||
@@ -622,8 +623,8 @@ int xc_vmx_build(int xc_handle,
|
||||
|
||||
if ( !strstr(xen_caps, "hvm") )
|
||||
{
|
||||
PERROR("CPU doesn't support VMX Extensions or "
|
||||
"CPU VMX Extensions are not turned on");
|
||||
PERROR("CPU doesn't support HVM extensions or "
|
||||
"the extensions are not enabled");
|
||||
goto error_out;
|
||||
}
|
||||
|
||||
@@ -653,6 +654,7 @@ int xc_vmx_build(int xc_handle,
|
||||
|
||||
memset(ctxt, 0, sizeof(*ctxt));
|
||||
|
||||
ctxt->flags = VGCF_HVM_GUEST;
|
||||
if ( setup_guest(xc_handle, domid, memsize, image, image_size, nr_pages,
|
||||
ctxt, op.u.getdomaininfo.shared_info_frame, control_evtchn,
|
||||
vcpus, acpi, apic, store_evtchn, store_mfn) < 0)
|
||||
@@ -663,7 +665,6 @@ int xc_vmx_build(int xc_handle,
|
||||
|
||||
free(image);
|
||||
|
||||
ctxt->flags = VGCF_VMX_GUEST;
|
||||
/* FPU is set up to default initial state. */
|
||||
memset(&ctxt->fpu_ctxt, 0, sizeof(ctxt->fpu_ctxt));
|
||||
|
||||
@@ -779,7 +780,7 @@ static int parseelfimage(char *elfbase,
|
||||
|
||||
dsi->v_kernstart = kernstart;
|
||||
dsi->v_kernend = kernend;
|
||||
dsi->v_kernentry = VMX_LOADER_ENTR_ADDR;
|
||||
dsi->v_kernentry = HVM_LOADER_ENTR_ADDR;
|
||||
|
||||
dsi->v_end = dsi->v_kernend;
|
||||
|
||||
@@ -621,7 +621,7 @@ static int setup_guest( int xc_handle,
|
||||
return -1;
|
||||
}
|
||||
|
||||
int xc_vmx_build(int xc_handle,
|
||||
int xc_hvm_build(int xc_handle,
|
||||
uint32_t domid,
|
||||
int memsize,
|
||||
const char *image_name,
|
||||
|
||||
@@ -815,7 +815,7 @@ static int setup_guest(int xc_handle,
|
||||
start_info->mod_len = initrd_len;
|
||||
}
|
||||
if ( cmdline != NULL )
|
||||
{
|
||||
{
|
||||
strncpy((char *)start_info->cmd_line, cmdline, MAX_GUEST_CMDLINE);
|
||||
start_info->cmd_line[MAX_GUEST_CMDLINE-1] = '\0';
|
||||
}
|
||||
|
||||
@@ -240,7 +240,7 @@ map_domain_va(
|
||||
}
|
||||
if ( (pde = cr3_virt[cpu][vtopdi(va)]) == 0 )
|
||||
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;
|
||||
if ( pde != pde_phys[cpu] )
|
||||
{
|
||||
@@ -255,7 +255,7 @@ map_domain_va(
|
||||
}
|
||||
if ( (page = pde_virt[cpu][vtopti(va)]) == 0 )
|
||||
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;
|
||||
if ( (page != page_phys[cpu]) || (perm != prev_perm[cpu]) )
|
||||
{
|
||||
|
||||
@@ -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 */
|
||||
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;
|
||||
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 */
|
||||
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;
|
||||
if (page != page_phys[cpu])
|
||||
{
|
||||
|
||||
@@ -53,7 +53,7 @@ int xc_linux_build(int xc_handle,
|
||||
unsigned int console_evtchn,
|
||||
unsigned long *console_mfn);
|
||||
|
||||
int xc_vmx_build(int xc_handle,
|
||||
int xc_hvm_build(int xc_handle,
|
||||
uint32_t domid,
|
||||
int memsize,
|
||||
const char *image_name,
|
||||
|
||||
@@ -355,7 +355,7 @@ static PyObject *pyxc_linux_build(XcObject *self,
|
||||
"console_mfn", console_mfn);
|
||||
}
|
||||
|
||||
static PyObject *pyxc_vmx_build(XcObject *self,
|
||||
static PyObject *pyxc_hvm_build(XcObject *self,
|
||||
PyObject *args,
|
||||
PyObject *kwds)
|
||||
{
|
||||
@@ -369,16 +369,15 @@ static PyObject *pyxc_vmx_build(XcObject *self,
|
||||
unsigned long store_mfn = 0;
|
||||
|
||||
static char *kwd_list[] = { "dom", "control_evtchn", "store_evtchn",
|
||||
"memsize", "image", "vcpus", "acpi", "apic",
|
||||
NULL };
|
||||
|
||||
"memsize", "image", "vcpus", "acpi", "apic",
|
||||
NULL };
|
||||
if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iiiisiii", kwd_list,
|
||||
&dom, &control_evtchn, &store_evtchn,
|
||||
&memsize, &image, &vcpus, &acpi, &apic) )
|
||||
&memsize, &image, &vcpus, &acpi, &apic) )
|
||||
return NULL;
|
||||
|
||||
if ( xc_vmx_build(self->xc_handle, dom, memsize, image, control_evtchn,
|
||||
vcpus, acpi, apic, store_evtchn, &store_mfn) != 0 )
|
||||
if ( xc_hvm_build(self->xc_handle, dom, memsize, image, control_evtchn,
|
||||
vcpus, acpi, apic, store_evtchn, &store_mfn) != 0 )
|
||||
return PyErr_SetFromErrno(xc_error);
|
||||
|
||||
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"
|
||||
"Returns: [int] 0 on success; -1 on error.\n" },
|
||||
|
||||
{ "vmx_build",
|
||||
(PyCFunction)pyxc_vmx_build,
|
||||
{ "hvm_build",
|
||||
(PyCFunction)pyxc_hvm_build,
|
||||
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"
|
||||
" 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"
|
||||
"Returns: [int] 0 on success; -1 on error.\n" },
|
||||
|
||||
|
||||
@@ -143,7 +143,7 @@ class ImageHandler:
|
||||
|
||||
def getDomainMemory(self, mem):
|
||||
"""@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."""
|
||||
return mem
|
||||
|
||||
@@ -183,21 +183,21 @@ class LinuxImageHandler(ImageHandler):
|
||||
cmdline = self.cmdline,
|
||||
ramdisk = self.ramdisk)
|
||||
|
||||
class VmxImageHandler(ImageHandler):
|
||||
class HVMImageHandler(ImageHandler):
|
||||
|
||||
ostype = "vmx"
|
||||
ostype = "hvm"
|
||||
|
||||
def configure(self, imageConfig, deviceConfig):
|
||||
ImageHandler.configure(self, imageConfig, deviceConfig)
|
||||
|
||||
info = xc.xeninfo()
|
||||
if not 'hvm' in info['xen_caps']:
|
||||
raise VmError("vmx: not an Intel VT platform, we stop creating!")
|
||||
if not 'hvm' in info['xen_caps']:
|
||||
raise VmError("Not an HVM capable platform, we stop creating!")
|
||||
|
||||
self.dmargs = self.parseDeviceModelArgs(imageConfig, deviceConfig)
|
||||
self.device_model = sxp.child_value(imageConfig, '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.xauthority = sxp.child_value(imageConfig, 'xauthority')
|
||||
|
||||
@@ -217,7 +217,7 @@ class VmxImageHandler(ImageHandler):
|
||||
# Create an event channel
|
||||
self.device_channel = xc.evtchn_alloc_unbound(dom=self.vm.getDomid(),
|
||||
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()
|
||||
|
||||
@@ -232,7 +232,7 @@ class VmxImageHandler(ImageHandler):
|
||||
|
||||
self.register_shutdown_watch()
|
||||
|
||||
return xc.vmx_build(dom = self.vm.getDomid(),
|
||||
return xc.hvm_build(dom = self.vm.getDomid(),
|
||||
image = self.kernel,
|
||||
control_evtchn = self.device_channel,
|
||||
store_evtchn = store_evtchn,
|
||||
@@ -283,7 +283,7 @@ class VmxImageHandler(ImageHandler):
|
||||
continue;
|
||||
vbddev_list = ['hda', 'hdb', 'hdc', 'hdd']
|
||||
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" % vbdparam)
|
||||
if name == 'vif':
|
||||
@@ -405,8 +405,8 @@ class VmxImageHandler(ImageHandler):
|
||||
def register_shutdown_watch(self):
|
||||
""" add xen store watch on control/shutdown """
|
||||
self.shutdownWatch = xswatch(self.vm.dompath + "/control/shutdown", \
|
||||
self.vmx_shutdown)
|
||||
log.debug("vmx shutdown watch registered")
|
||||
self.hvm_shutdown)
|
||||
log.debug("hvm shutdown watch registered")
|
||||
|
||||
def unregister_shutdown_watch(self):
|
||||
"""Remove the watch on the control/shutdown, if any. Nothrow
|
||||
@@ -416,11 +416,11 @@ class VmxImageHandler(ImageHandler):
|
||||
if self.shutdownWatch:
|
||||
self.shutdownWatch.unwatch()
|
||||
except:
|
||||
log.exception("Unwatching vmx shutdown watch failed.")
|
||||
log.exception("Unwatching hvm shutdown watch failed.")
|
||||
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,
|
||||
if node changed, this function will be called
|
||||
"""
|
||||
@@ -429,7 +429,7 @@ class VmxImageHandler(ImageHandler):
|
||||
vm = xd.domain_lookup( self.vm.getDomid() )
|
||||
|
||||
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():
|
||||
if shutdown_reasons[x] == reason:
|
||||
vm.info['shutdown'] = 1
|
||||
@@ -444,7 +444,7 @@ image type.
|
||||
imageHandlerClasses = {}
|
||||
|
||||
|
||||
for h in LinuxImageHandler, VmxImageHandler:
|
||||
for h in LinuxImageHandler, HVMImageHandler:
|
||||
imageHandlerClasses[h.ostype] = h
|
||||
|
||||
|
||||
|
||||
@@ -162,11 +162,11 @@ gopts.var('cpus', val='CPUS',
|
||||
|
||||
gopts.var('acpi', val='ACPI',
|
||||
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',
|
||||
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',
|
||||
fn=set_int, default=1,
|
||||
@@ -441,8 +441,8 @@ def configure_image(vals):
|
||||
if vals.extra:
|
||||
config_image.append(['args', vals.extra])
|
||||
|
||||
if vals.builder == 'vmx':
|
||||
configure_vmx(config_image, vals)
|
||||
if vals.builder == 'hvm':
|
||||
configure_hvm(config_image, vals)
|
||||
|
||||
return config_image
|
||||
|
||||
@@ -536,8 +536,8 @@ def configure_vifs(config_devs, vals):
|
||||
config_devs.append(['device', config_vif])
|
||||
|
||||
|
||||
def configure_vmx(config_image, vals):
|
||||
"""Create the config for VMX devices.
|
||||
def configure_hvm(config_image, vals):
|
||||
"""Create the config for HVM devices.
|
||||
"""
|
||||
args = [ 'device_model', 'vcpus', 'cdrom', 'boot', 'fda', 'fdb',
|
||||
'localtime', 'serial', 'stdvga', 'isa', 'nographic', 'audio',
|
||||
|
||||
@@ -141,15 +141,15 @@ cpu_weight = 0.75
|
||||
})
|
||||
|
||||
|
||||
def testVMXConfigFile(self):
|
||||
def testHVMConfigFile(self):
|
||||
(fd, fname) = tempfile.mkstemp()
|
||||
try:
|
||||
os.write(fd,
|
||||
'''
|
||||
kernel = "/usr/lib/xen/boot/vmxloader"
|
||||
builder='vmx'
|
||||
kernel = "/usr/lib/xen/boot/hvmloader"
|
||||
builder='hvm'
|
||||
memory = 128
|
||||
name = "ExampleVMXDomain"
|
||||
name = "ExampleHVMDomain"
|
||||
vcpus=1
|
||||
vif = [ 'type=ioemu, bridge=xenbr0' ]
|
||||
disk = [ 'file:/var/images/min-el3-i386.img,ioemu:hda,w' ]
|
||||
@@ -163,10 +163,10 @@ ne2000=0
|
||||
os.close(fd)
|
||||
|
||||
self.t('-f %s display=fakedisplay' % fname,
|
||||
{ 'kernel' : '/usr/lib/xen/boot/vmxloader',
|
||||
'builder' : 'vmx',
|
||||
{ 'kernel' : '/usr/lib/xen/boot/hvmloader',
|
||||
'builder' : 'hvm',
|
||||
'memory' : 128,
|
||||
'name' : 'ExampleVMXDomain',
|
||||
'name' : 'ExampleHVMDomain',
|
||||
'vcpus' : 1,
|
||||
'nics' : -1,
|
||||
'vif' : ['type=ioemu, bridge=xenbr0'],
|
||||
|
||||
+12
-12
@@ -60,26 +60,26 @@ BUILDING with HVM Support
|
||||
=========================
|
||||
|
||||
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,
|
||||
please add the --enable-vmx-support option to configure:
|
||||
(HVM) support to test fully virtualized disk images on VMX/SVM hardware,
|
||||
please add the --enable-hvm-support option to configure:
|
||||
|
||||
# ./autogen
|
||||
# ./configure --enable-vmx-support
|
||||
# ./configure --enable-hvm-support
|
||||
# make
|
||||
|
||||
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
|
||||
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
|
||||
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,
|
||||
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
|
||||
# ./configure --enable-vmx-support --with-vmx-kernel=KERNEL
|
||||
# ./configure --enable-hvm-support --with-hvm-kernel=KERNEL
|
||||
# make
|
||||
|
||||
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
|
||||
use the "--with-driver-dir=DRVDIR" configure option. If built into
|
||||
the kernel, please use the key word "builtin" with the option:
|
||||
|
||||
|
||||
# ./autogen
|
||||
# ./configure --enable-vmx-support --with-driver-dir=builtin
|
||||
# ./configure --enable-hvm-support --with-driver-dir=builtin
|
||||
- or -
|
||||
# ./configure --enable-vmx-support --with-driver-dir=/driver/directory
|
||||
# ./configure --enable-hvm-support --with-driver-dir=/driver/directory
|
||||
# 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.
|
||||
|
||||
|
||||
|
||||
+14
-14
@@ -15,18 +15,18 @@ TESTLIB=../../lib
|
||||
RD_PATH=../../ramdisk
|
||||
TENV="PYTHONPATH=$PYTHONPATH:$TESTLIB:/usr/lib/python RD_PATH=$RD_PATH"
|
||||
|
||||
AC_ARG_ENABLE(vmx-support,
|
||||
[[ --enable-vmx-support enable hardware virtual machine assist]],
|
||||
AC_ARG_ENABLE(hvm-support,
|
||||
[[ --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
|
||||
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
|
||||
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
|
||||
@@ -35,16 +35,16 @@ lilo version 22.7 or greater must be installed for testing with vmx enabled.])
|
||||
fi
|
||||
fi
|
||||
|
||||
AM_CONDITIONAL(VMX, test x$ENABLE_VMX = xTrue)
|
||||
AC_SUBST(ENABLE_VMX)
|
||||
AM_CONDITIONAL(HVM, test x$ENABLE_HVM = xTrue)
|
||||
AC_SUBST(ENABLE_HVM)
|
||||
|
||||
AC_ARG_WITH(vmx-kernel,
|
||||
[[ --with-vmx-kernel=kernel Use this kernel for vmx disk.img testing]],
|
||||
VMXKERNEL=$withval,
|
||||
VMXKERNEL="no")
|
||||
AC_ARG_WITH(hvm-kernel,
|
||||
[[ --with-hvm-kernel=kernel Use this kernel for hvm disk.img testing]],
|
||||
HVMKERNEL=$withval,
|
||||
HVMKERNEL="no")
|
||||
|
||||
dnl substitute @VMXKERNEL@ in all Makefiles
|
||||
AC_SUBST(VMXKERNEL)
|
||||
dnl substitute @HVMKERNEL@ in all Makefiles
|
||||
AC_SUBST(HVMKERNEL)
|
||||
|
||||
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]],
|
||||
|
||||
@@ -70,14 +70,14 @@ ParavirtDefaults = {"memory" : 64,
|
||||
"root" : "/dev/ram0",
|
||||
"ramdisk" : getRdPath() + "/initrd.img"
|
||||
}
|
||||
VmxDefaults = {"memory" : 64,
|
||||
HVMDefaults = {"memory" : 64,
|
||||
"vcpus" : 1,
|
||||
"acpi" : 0,
|
||||
"apic" : 0,
|
||||
"disk" : ["file:%s/disk.img,ioemu:%s,w" %
|
||||
(getRdPath(), BLOCK_ROOT_DEV)],
|
||||
"kernel" : "/usr/lib/xen/boot/vmxloader",
|
||||
"builder" : "vmx",
|
||||
"kernel" : "/usr/lib/xen/boot/hvmloader",
|
||||
"builder" : "hvm",
|
||||
"sdl" : 0,
|
||||
"vnc" : 0,
|
||||
"vncviewer" : 0,
|
||||
@@ -86,8 +86,8 @@ VmxDefaults = {"memory" : 64,
|
||||
"device_model" : getDeviceModel()
|
||||
}
|
||||
|
||||
if ENABLE_VMX_SUPPORT:
|
||||
configDefaults = VmxDefaults
|
||||
if ENABLE_HVM_SUPPORT:
|
||||
configDefaults = HVMDefaults
|
||||
else:
|
||||
configDefaults = ParavirtDefaults
|
||||
|
||||
@@ -247,7 +247,7 @@ class XmTestDomain(XenDomain):
|
||||
|
||||
def start(self):
|
||||
XenDomain.start(self)
|
||||
if ENABLE_VMX_SUPPORT:
|
||||
if ENABLE_HVM_SUPPORT:
|
||||
waitForBoot()
|
||||
|
||||
def startNow(self):
|
||||
@@ -271,7 +271,7 @@ if __name__ == "__main__":
|
||||
|
||||
print str(c)
|
||||
|
||||
|
||||
|
||||
|
||||
# c.write("/tmp/foo.conf")
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
ENABLE_VMX_SUPPORT = @ENABLE_VMX@
|
||||
ENABLE_HVM_SUPPORT = @ENABLE_HVM@
|
||||
|
||||
@@ -9,12 +9,12 @@ BR_IMG = $(BR_SRC)/rootfs.i386.ext2
|
||||
|
||||
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_VER_IMG = initrd-$(XMTEST_MAJ_VER).img
|
||||
|
||||
if VMX
|
||||
if HVM
|
||||
all: initrd.img disk.img
|
||||
else
|
||||
all: initrd.img
|
||||
@@ -44,16 +44,16 @@ initrd.img: $(XMTEST_VER_IMG)
|
||||
ln -sf $(XMTEST_VER_IMG) initrd.img
|
||||
|
||||
disk.img: $(XMTEST_VER_IMG)
|
||||
chmod a+x $(VMX_SCRIPT)
|
||||
@if test ! "$(VMXKERNEL)" = "no" -a ! "$(DRVDIR)" = "no"; then \
|
||||
$(VMX_SCRIPT) -r $(XMTEST_VER_IMG) -k $(VMXKERNEL) \
|
||||
chmod a+x $(HVM_SCRIPT)
|
||||
@if test ! "$(HVMKERNEL)" = "no" -a ! "$(DRVDIR)" = "no"; then \
|
||||
$(HVM_SCRIPT) -r $(XMTEST_VER_IMG) -k $(HVMKERNEL) \
|
||||
-d $(DRVDIR); \
|
||||
elif test "$(VMXKERNEL)" = "no" -a ! "$(DRVDIR)" = "no"; then \
|
||||
$(VMX_SCRIPT) -r $(XMTEST_VER_IMG) -d $(DRVDIR); \
|
||||
elif test ! "$(VMXKERNEL)" = "no" -a "$(DRVDIR)" = "no"; then \
|
||||
$(VMX_SCRIPT) -r $(XMTEST_VER_IMG) -k $(VMXKERNEL); \
|
||||
elif test "$(HVMKERNEL)" = "no" -a ! "$(DRVDIR)" = "no"; then \
|
||||
$(HVM_SCRIPT) -r $(XMTEST_VER_IMG) -d $(DRVDIR); \
|
||||
elif test ! "$(HVMKERNEL)" = "no" -a "$(DRVDIR)" = "no"; then \
|
||||
$(HVM_SCRIPT) -r $(XMTEST_VER_IMG) -k $(HVMKERNEL); \
|
||||
else \
|
||||
$(VMX_SCRIPT) -r $(XMTEST_VER_IMG); \
|
||||
$(HVM_SCRIPT) -r $(XMTEST_VER_IMG); \
|
||||
fi
|
||||
|
||||
existing:
|
||||
|
||||
@@ -46,7 +46,7 @@ function die()
|
||||
function usage()
|
||||
{
|
||||
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]
|
||||
|
||||
|
||||
@@ -9,8 +9,8 @@ import time
|
||||
|
||||
from XmTestLib import *
|
||||
|
||||
if ENABLE_VMX_SUPPORT:
|
||||
SKIP("Block-attach not supported for VMX domains")
|
||||
if ENABLE_HVM_SUPPORT:
|
||||
SKIP("Block-attach not supported for HVM domains")
|
||||
|
||||
# Create a domain (default XmTestDomain, with our ramdisk)
|
||||
domain = XmTestDomain()
|
||||
|
||||
@@ -9,8 +9,8 @@ import time
|
||||
|
||||
from XmTestLib import *
|
||||
|
||||
if ENABLE_VMX_SUPPORT:
|
||||
SKIP("Block-attach not supported for VMX domains")
|
||||
if ENABLE_HVM_SUPPORT:
|
||||
SKIP("Block-attach not supported for HVM domains")
|
||||
|
||||
# Create a domain (default XmTestDomain, with our ramdisk)
|
||||
domain = XmTestDomain()
|
||||
|
||||
@@ -9,8 +9,8 @@ import time
|
||||
|
||||
from XmTestLib import *
|
||||
|
||||
if ENABLE_VMX_SUPPORT:
|
||||
SKIP("Block-attach not supported for VMX domains")
|
||||
if ENABLE_HVM_SUPPORT:
|
||||
SKIP("Block-attach not supported for HVM domains")
|
||||
|
||||
# Create a domain (default XmTestDomain, with our ramdisk)
|
||||
domain = XmTestDomain()
|
||||
|
||||
+2
-2
@@ -9,8 +9,8 @@ import time
|
||||
|
||||
from XmTestLib import *
|
||||
|
||||
if ENABLE_VMX_SUPPORT:
|
||||
SKIP("Block-attach not supported for VMX domains")
|
||||
if ENABLE_HVM_SUPPORT:
|
||||
SKIP("Block-attach not supported for HVM domains")
|
||||
|
||||
# Create a domain (default XmTestDomain, with our ramdisk)
|
||||
domain = XmTestDomain()
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
|
||||
from XmTestLib import *
|
||||
|
||||
if ENABLE_VMX_SUPPORT:
|
||||
SKIP("Block-attach not supported for VMX domains")
|
||||
if ENABLE_HVM_SUPPORT:
|
||||
SKIP("Block-attach not supported for HVM domains")
|
||||
|
||||
status, output = traceCommand("xm block-attach NOT-EXIST phy:ram1 sdb1 w")
|
||||
|
||||
|
||||
@@ -9,8 +9,8 @@ import time
|
||||
|
||||
from XmTestLib import *
|
||||
|
||||
if ENABLE_VMX_SUPPORT:
|
||||
SKIP("Block-attach not supported for VMX domains")
|
||||
if ENABLE_HVM_SUPPORT:
|
||||
SKIP("Block-attach not supported for HVM domains")
|
||||
|
||||
# Create a domain (default XmTestDomain, with our ramdisk)
|
||||
domain = XmTestDomain()
|
||||
|
||||
@@ -9,8 +9,8 @@ import time
|
||||
|
||||
from XmTestLib import *
|
||||
|
||||
if ENABLE_VMX_SUPPORT:
|
||||
SKIP("Block-attach not supported for VMX domains")
|
||||
if ENABLE_HVM_SUPPORT:
|
||||
SKIP("Block-attach not supported for HVM domains")
|
||||
|
||||
# Create a domain (default XmTestDomain, with our ramdisk)
|
||||
domain = XmTestDomain()
|
||||
|
||||
+2
-2
@@ -9,8 +9,8 @@ import time
|
||||
|
||||
from XmTestLib import *
|
||||
|
||||
if ENABLE_VMX_SUPPORT:
|
||||
SKIP("Block-attach not supported for VMX domains")
|
||||
if ENABLE_HVM_SUPPORT:
|
||||
SKIP("Block-attach not supported for HVM domains")
|
||||
|
||||
# Create a domain (default XmTestDomain, with our ramdisk)
|
||||
domain = XmTestDomain()
|
||||
|
||||
@@ -46,8 +46,8 @@ def dettach(devname):
|
||||
|
||||
return 0, None
|
||||
|
||||
if ENABLE_VMX_SUPPORT:
|
||||
SKIP("Block-attach not supported for VMX domains")
|
||||
if ENABLE_HVM_SUPPORT:
|
||||
SKIP("Block-attach not supported for HVM domains")
|
||||
|
||||
# Create a domain (default XmTestDomain, with our ramdisk)
|
||||
domain = XmTestDomain()
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
|
||||
from XmTestLib import *
|
||||
|
||||
if ENABLE_VMX_SUPPORT:
|
||||
SKIP("Block-attach not supported for VMX domains")
|
||||
if ENABLE_HVM_SUPPORT:
|
||||
SKIP("Block-attach not supported for HVM domains")
|
||||
|
||||
# Mount /dev/ram0
|
||||
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
|
||||
from XmTestLib import *
|
||||
|
||||
if ENABLE_VMX_SUPPORT:
|
||||
SKIP("Block-attach not supported for VMX domains")
|
||||
if ENABLE_HVM_SUPPORT:
|
||||
SKIP("Block-attach not supported for HVM domains")
|
||||
|
||||
config = {"disk":"phy:/dev/ram0,hda1,w"}
|
||||
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
|
||||
from XmTestLib import *
|
||||
|
||||
if ENABLE_VMX_SUPPORT:
|
||||
SKIP("Block-detach not supported for VMX domains")
|
||||
if ENABLE_HVM_SUPPORT:
|
||||
SKIP("Block-detach not supported for HVM domains")
|
||||
|
||||
config = {"disk":"phy:/dev/ram0,hda1,w"}
|
||||
domain = XmTestDomain(extraConfig=config)
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
|
||||
from XmTestLib import *
|
||||
|
||||
if ENABLE_VMX_SUPPORT:
|
||||
SKIP("Block-detach not supported for VMX domains")
|
||||
if ENABLE_HVM_SUPPORT:
|
||||
SKIP("Block-detach not supported for HVM domains")
|
||||
|
||||
domain = XmTestDomain()
|
||||
|
||||
|
||||
@@ -7,8 +7,8 @@
|
||||
|
||||
from XmTestLib import *
|
||||
|
||||
if ENABLE_VMX_SUPPORT:
|
||||
SKIP("Block-detach not supported for VMX domains")
|
||||
if ENABLE_HVM_SUPPORT:
|
||||
SKIP("Block-detach not supported for HVM domains")
|
||||
|
||||
domain = XmTestDomain()
|
||||
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
|
||||
from XmTestLib import *
|
||||
|
||||
if ENABLE_VMX_SUPPORT:
|
||||
SKIP("Block-detach not supported for VMX domains")
|
||||
if ENABLE_HVM_SUPPORT:
|
||||
SKIP("Block-detach not supported for HVM domains")
|
||||
|
||||
config = {"disk":"phy:/dev/ram0,hda1,w"}
|
||||
domain = XmTestDomain(extraConfig=config)
|
||||
|
||||
@@ -26,8 +26,8 @@ def checkXmLongList(domain):
|
||||
else:
|
||||
return False
|
||||
|
||||
if ENABLE_VMX_SUPPORT:
|
||||
SKIP("Block-detach not supported for VMX domains")
|
||||
if ENABLE_HVM_SUPPORT:
|
||||
SKIP("Block-detach not supported for HVM domains")
|
||||
|
||||
domain = XmTestDomain()
|
||||
|
||||
|
||||
@@ -8,8 +8,8 @@
|
||||
|
||||
from XmTestLib import *
|
||||
|
||||
if ENABLE_VMX_SUPPORT:
|
||||
SKIP("Block-list not supported for VMX domains")
|
||||
if ENABLE_HVM_SUPPORT:
|
||||
SKIP("Block-list not supported for HVM domains")
|
||||
|
||||
config = {"disk":"phy:/dev/ram0,hda1,w"}
|
||||
domain = XmTestDomain(extraConfig=config)
|
||||
|
||||
@@ -8,8 +8,8 @@
|
||||
|
||||
from XmTestLib import *
|
||||
|
||||
if ENABLE_VMX_SUPPORT:
|
||||
SKIP("Block-list not supported for VMX domains")
|
||||
if ENABLE_HVM_SUPPORT:
|
||||
SKIP("Block-list not supported for HVM domains")
|
||||
|
||||
domain = XmTestDomain()
|
||||
|
||||
|
||||
@@ -8,8 +8,8 @@
|
||||
|
||||
from XmTestLib import *
|
||||
|
||||
if ENABLE_VMX_SUPPORT:
|
||||
SKIP("Block-list not supported for VMX domains")
|
||||
if ENABLE_HVM_SUPPORT:
|
||||
SKIP("Block-list not supported for HVM domains")
|
||||
|
||||
config = {"disk":"phy:/dev/ram0,hda1,w"}
|
||||
domain = XmTestDomain(extraConfig=config)
|
||||
|
||||
@@ -8,8 +8,8 @@
|
||||
|
||||
from XmTestLib import *
|
||||
|
||||
if ENABLE_VMX_SUPPORT:
|
||||
SKIP("Block-list not supported for VMX domains")
|
||||
if ENABLE_HVM_SUPPORT:
|
||||
SKIP("Block-list not supported for HVM domains")
|
||||
|
||||
domain = XmTestDomain()
|
||||
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
|
||||
from XmTestLib import *
|
||||
|
||||
if ENABLE_VMX_SUPPORT:
|
||||
SKIP("Block-list not supported for VMX domains")
|
||||
if ENABLE_HVM_SUPPORT:
|
||||
SKIP("Block-list not supported for HVM domains")
|
||||
|
||||
domain = XmTestDomain()
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ rdpath = getRdPath()
|
||||
# if verbose:
|
||||
# print "Using %s" % output
|
||||
|
||||
if ENABLE_VMX_SUPPORT:
|
||||
if ENABLE_HVM_SUPPORT:
|
||||
domain = XmTestDomain(name="14_create_blockroot")
|
||||
else:
|
||||
config = {"memory" : "64",
|
||||
|
||||
@@ -8,8 +8,8 @@ import re
|
||||
|
||||
from XmTestLib import *
|
||||
|
||||
if ENABLE_VMX_SUPPORT:
|
||||
SKIP("Mem-max not supported for VMX domains")
|
||||
if ENABLE_HVM_SUPPORT:
|
||||
SKIP("Mem-max not supported for HVM domains")
|
||||
|
||||
status, output = traceCommand("xm mem-max")
|
||||
eyecatcher = "Error:"
|
||||
|
||||
@@ -20,8 +20,8 @@ import re
|
||||
import time
|
||||
from XmTestLib import *
|
||||
|
||||
if ENABLE_VMX_SUPPORT:
|
||||
SKIP("Mem-set not supported for VMX domains")
|
||||
if ENABLE_HVM_SUPPORT:
|
||||
SKIP("Mem-set not supported for HVM domains")
|
||||
|
||||
# Create a domain (default XmTestDomain, with our ramdisk)
|
||||
domain = XmTestDomain()
|
||||
|
||||
@@ -18,8 +18,8 @@ import re
|
||||
|
||||
from XmTestLib import *
|
||||
|
||||
if ENABLE_VMX_SUPPORT:
|
||||
SKIP("Mem-set not supported for VMX domains")
|
||||
if ENABLE_HVM_SUPPORT:
|
||||
SKIP("Mem-set not supported for HVM domains")
|
||||
|
||||
# destroy no parm input - negative test
|
||||
status, output = traceCommand("xm mem-set")
|
||||
|
||||
@@ -8,8 +8,8 @@ import re
|
||||
|
||||
from XmTestLib import *
|
||||
|
||||
if ENABLE_VMX_SUPPORT:
|
||||
SKIP("Mem-set not supported for VMX domains")
|
||||
if ENABLE_HVM_SUPPORT:
|
||||
SKIP("Mem-set not supported for HVM domains")
|
||||
|
||||
domain = XmTestDomain()
|
||||
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
|
||||
from XmTestLib import *
|
||||
|
||||
if ENABLE_VMX_SUPPORT:
|
||||
SKIP("Mem-set not supported for VMX domains")
|
||||
if ENABLE_HVM_SUPPORT:
|
||||
SKIP("Mem-set not supported for HVM domains")
|
||||
|
||||
domain = XmTestDomain()
|
||||
|
||||
|
||||
@@ -17,8 +17,8 @@ import commands
|
||||
|
||||
from XmTestLib import *
|
||||
|
||||
if ENABLE_VMX_SUPPORT:
|
||||
SKIP("Migrate currently not supported for VMX domains")
|
||||
if ENABLE_HVM_SUPPORT:
|
||||
SKIP("Migrate currently not supported for HVM domains")
|
||||
|
||||
# Create a domain (default XmTestDomain, with our ramdisk)
|
||||
domain = XmTestDomain()
|
||||
|
||||
@@ -8,8 +8,8 @@ import sys
|
||||
from XmTestLib import *
|
||||
from network_utils import *
|
||||
|
||||
if ENABLE_VMX_SUPPORT:
|
||||
SKIP("Network-attach not supported for VMX domains")
|
||||
if ENABLE_HVM_SUPPORT:
|
||||
SKIP("Network-attach not supported for HVM domains")
|
||||
|
||||
# Create a domain (default XmTestDomain, with our ramdisk)
|
||||
domain = XmTestDomain()
|
||||
|
||||
@@ -10,8 +10,8 @@ import time
|
||||
from XmTestLib import *
|
||||
from network_utils import *
|
||||
|
||||
if ENABLE_VMX_SUPPORT:
|
||||
SKIP("Network-attach not supported for VMX domains")
|
||||
if ENABLE_HVM_SUPPORT:
|
||||
SKIP("Network-attach not supported for HVM domains")
|
||||
|
||||
# Create a domain (default XmTestDomain, with our ramdisk)
|
||||
domain = XmTestDomain()
|
||||
|
||||
@@ -10,8 +10,8 @@ import time
|
||||
from XmTestLib import *
|
||||
from network_utils import *
|
||||
|
||||
if ENABLE_VMX_SUPPORT:
|
||||
SKIP("Network-attach not supported for VMX domains")
|
||||
if ENABLE_HVM_SUPPORT:
|
||||
SKIP("Network-attach not supported for HVM domains")
|
||||
|
||||
# Create a domain (default XmTestDomain, with our ramdisk)
|
||||
domain = XmTestDomain()
|
||||
|
||||
@@ -12,8 +12,8 @@ import time
|
||||
|
||||
from XmTestLib import *
|
||||
|
||||
if ENABLE_VMX_SUPPORT:
|
||||
SKIP("Restore currently not supported for VMX domains")
|
||||
if ENABLE_HVM_SUPPORT:
|
||||
SKIP("Restore currently not supported for HVM domains")
|
||||
|
||||
domain = XmTestDomain()
|
||||
|
||||
|
||||
@@ -12,8 +12,8 @@ import re
|
||||
|
||||
from XmTestLib import *
|
||||
|
||||
if ENABLE_VMX_SUPPORT:
|
||||
SKIP("Restore currently not supported for VMX domains")
|
||||
if ENABLE_HVM_SUPPORT:
|
||||
SKIP("Restore currently not supported for HVM domains")
|
||||
|
||||
status, output = traceCommand("xm restore -x")
|
||||
eyecatcher1 = "Error:"
|
||||
|
||||
@@ -12,8 +12,8 @@ import re
|
||||
|
||||
from XmTestLib import *
|
||||
|
||||
if ENABLE_VMX_SUPPORT:
|
||||
SKIP("Restore currently not supported for VMX domains")
|
||||
if ENABLE_HVM_SUPPORT:
|
||||
SKIP("Restore currently not supported for HVM domains")
|
||||
|
||||
status, output = traceCommand("xm restore /tmp/NON_EXIST")
|
||||
eyecatcher1 = "Error:"
|
||||
|
||||
@@ -7,8 +7,8 @@ from XmTestLib import *
|
||||
|
||||
import re
|
||||
|
||||
if ENABLE_VMX_SUPPORT:
|
||||
SKIP("Restore currently not supported for VMX domains")
|
||||
if ENABLE_HVM_SUPPORT:
|
||||
SKIP("Restore currently not supported for HVM domains")
|
||||
|
||||
config = {"disk": ["phy:/dev/ram0,hda1,w", "phy:/dev/ram1,hdb2,w"],
|
||||
"vif": ['', '']}
|
||||
|
||||
@@ -7,8 +7,8 @@ import time
|
||||
|
||||
from XmTestLib import *
|
||||
|
||||
if ENABLE_VMX_SUPPORT:
|
||||
SKIP("Save currently not supported for VMX domains")
|
||||
if ENABLE_HVM_SUPPORT:
|
||||
SKIP("Save currently not supported for HVM domains")
|
||||
|
||||
domain = XmTestDomain()
|
||||
|
||||
|
||||
@@ -12,8 +12,8 @@ import re
|
||||
|
||||
from XmTestLib import *
|
||||
|
||||
if ENABLE_VMX_SUPPORT:
|
||||
SKIP("Save currently not supported for VMX domains")
|
||||
if ENABLE_HVM_SUPPORT:
|
||||
SKIP("Save currently not supported for HVM domains")
|
||||
|
||||
status, output = traceCommand("xm save -x")
|
||||
eyecatcher1 = "Error:"
|
||||
|
||||
@@ -10,8 +10,8 @@ import time
|
||||
|
||||
from XmTestLib import *
|
||||
|
||||
if ENABLE_VMX_SUPPORT:
|
||||
SKIP("Save currently not supported for VMX domains")
|
||||
if ENABLE_HVM_SUPPORT:
|
||||
SKIP("Save currently not supported for HVM domains")
|
||||
|
||||
domain = XmTestDomain()
|
||||
|
||||
|
||||
@@ -9,8 +9,8 @@ import re
|
||||
|
||||
from XmTestLib import *
|
||||
|
||||
if ENABLE_VMX_SUPPORT:
|
||||
SKIP("Sysrq not supported for VMX domains")
|
||||
if ENABLE_HVM_SUPPORT:
|
||||
SKIP("Sysrq not supported for HVM domains")
|
||||
|
||||
status, output = traceCommand("xm sysrq does_not_exist s");
|
||||
|
||||
|
||||
@@ -9,8 +9,8 @@ import time
|
||||
|
||||
from XmTestLib import *
|
||||
|
||||
if ENABLE_VMX_SUPPORT:
|
||||
SKIP("Sysrq not supported for VMX domains")
|
||||
if ENABLE_HVM_SUPPORT:
|
||||
SKIP("Sysrq not supported for HVM domains")
|
||||
|
||||
# Create a domain (default XmTestDomain, with our ramdisk)
|
||||
domain = XmTestDomain()
|
||||
|
||||
@@ -7,8 +7,8 @@ from XmTestLib import *
|
||||
|
||||
import time
|
||||
|
||||
if ENABLE_VMX_SUPPORT:
|
||||
SKIP("Sysrq not supported for VMX domains")
|
||||
if ENABLE_HVM_SUPPORT:
|
||||
SKIP("Sysrq not supported for HVM domains")
|
||||
|
||||
domain = XmTestDomain()
|
||||
|
||||
|
||||
@@ -53,6 +53,9 @@ else
|
||||
CFLAGS += -g -DVERBOSE
|
||||
endif
|
||||
|
||||
# There is no real reason to compile without it
|
||||
CFLAGS += -g
|
||||
|
||||
ifeq ($(crash_debug),y)
|
||||
CFLAGS += -g -DCRASH_DEBUG
|
||||
endif
|
||||
|
||||
+16
-8
@@ -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\
|
||||
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 \
|
||||
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)
|
||||
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
|
||||
[ -e $(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
|
||||
[ -e $(BASEDIR)/include/asm-ia64/vmx_vpic.h ] \
|
||||
|| ln -s ../../include/asm-x86/vmx_vpic.h $(BASEDIR)/include/asm-ia64/vmx_vpic.h
|
||||
[ -e $(BASEDIR)/include/asm-ia64/vmx_vioapic.h ] \
|
||||
|| ln -s ../../include/asm-x86/vmx_vioapic.h $(BASEDIR)/include/asm-ia64/vmx_vioapic.h
|
||||
[ -e $(BASEDIR)/arch/ia64/vmx/vmx_vioapic.c ] \
|
||||
|| ln -s ../../../arch/x86/dm/vmx_vioapic.c $(BASEDIR)/arch/ia64/vmx/vmx_vioapic.c
|
||||
# Link to HVM files in Xen for ia64/vti
|
||||
[ -e $(BASEDIR)/include/asm-ia64/hvm ] \
|
||||
|| mkdir $(BASEDIR)/include/asm-ia64/hvm
|
||||
[ -e $(BASEDIR)/include/asm-ia64/hvm/support.h ] \
|
||||
|| ln -s ../../../include/asm-x86/hvm/support.h $(BASEDIR)/include/asm-ia64/hvm/support.h
|
||||
[ -e $(BASEDIR)/include/asm-ia64/hvm/io.h ] \
|
||||
|| 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
|
||||
[ -f $(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:
|
||||
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 $(BASEDIR)/arch/ia64/vmx/hvm_*.c
|
||||
rm -rf $(BASEDIR)/include/asm-ia64/hvm
|
||||
rm -f linux/lib/*.o
|
||||
|
||||
.PHONY: default clean
|
||||
@@ -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;
|
||||
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;
|
||||
unsigned long iot;
|
||||
struct vmx_mmio_handler *vioapic_handler = &vioapic_mmio_handler;
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
#include <asm/vmx_pal_vsa.h>
|
||||
#include <asm/kregs.h>
|
||||
#include <asm/vmx_platform.h>
|
||||
#include <asm/vmx_vioapic.h>
|
||||
#include <asm/hvm/vioapic.h>
|
||||
|
||||
//u64 fire_itc;
|
||||
//u64 fire_itc2;
|
||||
@@ -278,7 +278,7 @@ void vmx_virq_line_assist(struct vcpu *v)
|
||||
do {
|
||||
irqs = *(volatile uint16_t*)virq_line;
|
||||
} 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;
|
||||
@@ -286,7 +286,7 @@ void vmx_virq_line_assist(struct vcpu *v)
|
||||
do {
|
||||
irqs = *(volatile uint16_t*)virq_line;
|
||||
} 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;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
@@ -311,14 +311,14 @@ struct vlapic* apic_round_robin(struct domain *d,
|
||||
uint32_t bitmap)
|
||||
{
|
||||
uint8_t bit;
|
||||
vmx_vioapic_t *s;
|
||||
hvm_vioapic_t *s;
|
||||
|
||||
if (!bitmap) {
|
||||
printk("<apic_round_robin> no bit on bitmap\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
s = &d->arch.vmx_platform.vmx_vioapic;
|
||||
s = &d->arch.vmx_platform.vioapic;
|
||||
for (bit = 0; bit < s->lapic_count; bit++) {
|
||||
if (bitmap & (1 << bit))
|
||||
return s->lapic_info[bit];
|
||||
@@ -351,7 +351,7 @@ void vlsapic_reset(VCPU *vcpu)
|
||||
|
||||
#ifdef V_IOSAPIC_READY
|
||||
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
|
||||
DPRINTK("VLSAPIC inservice base=%lp\n", &VLSAPIC_INSVC(vcpu,0) );
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@
|
||||
#include <asm/vmx.h>
|
||||
#include <xen/mm.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 */
|
||||
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);
|
||||
|
||||
/* Initialize iosapic model within hypervisor */
|
||||
vmx_vioapic_init(d);
|
||||
hvm_vioapic_init(d);
|
||||
}
|
||||
|
||||
|
||||
@@ -198,7 +198,7 @@ vmx_vcpu_get_vtlb(VCPU *vcpu)
|
||||
}
|
||||
|
||||
|
||||
struct virutal_platform_def *
|
||||
struct virtual_platform_def *
|
||||
vmx_vcpu_get_plat(VCPU *vcpu)
|
||||
{
|
||||
return &(vcpu->domain->arch.vmx_platform);
|
||||
|
||||
+12
-2
@@ -4,10 +4,14 @@ include $(BASEDIR)/Rules.mk
|
||||
OBJS += $(patsubst %.S,%.o,$(wildcard $(TARGET_SUBARCH)/*.S))
|
||||
OBJS += $(patsubst %.c,%.o,$(wildcard $(TARGET_SUBARCH)/*.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 genapic/*.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)
|
||||
OBJS := $(subst cpu/centaur.o,,$(OBJS))
|
||||
@@ -74,9 +78,15 @@ clean:
|
||||
rm -f x86_64/*.o x86_64/*~ x86_64/core
|
||||
rm -f mtrr/*.o mtrr/*~ mtrr/core
|
||||
rm -f acpi/*.o acpi/*~ acpi/core
|
||||
rm -f dm/*.o dm/*~ dm/core
|
||||
rm -f genapic/*.o genapic/*~ genapic/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
|
||||
|
||||
.PHONY: default clean
|
||||
@@ -3,12 +3,20 @@
|
||||
#include <xen/bitops.h>
|
||||
#include <xen/mm.h>
|
||||
#include <xen/smp.h>
|
||||
#include <xen/sched.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/msr.h>
|
||||
#include <asm/processor.h>
|
||||
#include <asm/hvm/vcpu.h>
|
||||
#include <asm/hvm/support.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
|
||||
* filter on AMD 64-bit processors.
|
||||
@@ -41,6 +49,99 @@ custom_param("amd_flush_filter", flush_filter);
|
||||
extern void vide(void);
|
||||
__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)
|
||||
{
|
||||
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",
|
||||
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
|
||||
}
|
||||
|
||||
|
||||
@@ -10,7 +10,9 @@
|
||||
#include <asm/mpspec.h>
|
||||
#include <asm/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"
|
||||
|
||||
|
||||
@@ -20,6 +20,8 @@
|
||||
#include <xen/iocap.h>
|
||||
#include <asm/shadow.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/hvm/hvm.h>
|
||||
#include <asm/hvm/support.h>
|
||||
#include <asm/processor.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(
|
||||
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));
|
||||
|
||||
if ( VMX_DOMAIN(v) )
|
||||
if ( HVM_DOMAIN(v) )
|
||||
{
|
||||
save_vmx_cpu_user_regs(&c->user_regs);
|
||||
__vmread(CR0_READ_SHADOW, &c->ctrlreg[0]);
|
||||
__vmread(CR4_READ_SHADOW, &c->ctrlreg[4]);
|
||||
hvm_store_cpu_guest_regs(v, &c->user_regs);
|
||||
hvm_store_cpu_guest_ctrl_regs(v, c->ctrlreg);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -470,8 +469,8 @@ void arch_getdomaininfo_ctxt(
|
||||
c->flags |= VGCF_I387_VALID;
|
||||
if ( KERNEL_MODE(v, &v->arch.guest_context.user_regs) )
|
||||
c->flags |= VGCF_IN_KERNEL;
|
||||
if (VMX_DOMAIN(v))
|
||||
c->flags |= VGCF_VMX_GUEST;
|
||||
if ( HVM_DOMAIN(v) )
|
||||
c->flags |= VGCF_HVM_GUEST;
|
||||
|
||||
c->ctrlreg[3] = pagetable_get_paddr(v->arch.guest_table);
|
||||
|
||||
|
||||
+24
-21
@@ -35,7 +35,8 @@
|
||||
#include <asm/shadow.h>
|
||||
#include <xen/console.h>
|
||||
#include <xen/elf.h>
|
||||
#include <asm/vmx.h>
|
||||
#include <asm/hvm/hvm.h>
|
||||
#include <asm/hvm/support.h>
|
||||
#include <asm/msr.h>
|
||||
#include <xen/kernel.h>
|
||||
#include <xen/multicall.h>
|
||||
@@ -153,8 +154,7 @@ void machine_restart(char * __unused)
|
||||
*/
|
||||
smp_send_stop();
|
||||
disable_IO_APIC();
|
||||
|
||||
stop_vmx();
|
||||
hvm_disable();
|
||||
|
||||
/* Rebooting needs to touch the page at absolute address 0. */
|
||||
*((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.
|
||||
* 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) ||
|
||||
((c->user_regs.ss & 3) == 0) )
|
||||
return -EINVAL;
|
||||
}
|
||||
else if ( !hvm_enabled )
|
||||
return -EINVAL;
|
||||
return -EINVAL;
|
||||
|
||||
clear_bit(_VCPUF_fpu_initialised, &v->vcpu_flags);
|
||||
if ( c->flags & VGCF_I387_VALID )
|
||||
set_bit(_VCPUF_fpu_initialised, &v->vcpu_flags);
|
||||
|
||||
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;
|
||||
|
||||
memcpy(&v->arch.guest_context, c, sizeof(*c));
|
||||
|
||||
if ( !(c->flags & VGCF_VMX_GUEST) )
|
||||
if ( !(c->flags & VGCF_HVM_GUEST) )
|
||||
{
|
||||
/* IOPL privileges are virtualised. */
|
||||
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) )
|
||||
{
|
||||
return modify_vmcs(
|
||||
&v->arch.arch_vmx,
|
||||
&v->arch.guest_context.user_regs);
|
||||
hvm_modify_guest_state(v);
|
||||
}
|
||||
|
||||
if ( test_bit(_VCPUF_initialised, &v->vcpu_flags) )
|
||||
@@ -418,7 +416,7 @@ int arch_set_info_guest(
|
||||
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,
|
||||
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) )
|
||||
d->arch.phys_table = v->arch.guest_table;
|
||||
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);
|
||||
@@ -611,8 +612,8 @@ static void save_segments(struct vcpu *v)
|
||||
struct cpu_user_regs *regs = &ctxt->user_regs;
|
||||
unsigned int dirty_segment_mask = 0;
|
||||
|
||||
if ( VMX_DOMAIN(v) )
|
||||
rdmsrl(MSR_SHADOW_GS_BASE, v->arch.arch_vmx.msr_content.shadow_gs);
|
||||
if ( HVM_DOMAIN(v) )
|
||||
hvm_save_segments(v);
|
||||
|
||||
__asm__ __volatile__ ( "mov %%ds,%0" : "=m" (regs->ds) );
|
||||
__asm__ __volatile__ ( "mov %%es,%0" : "=m" (regs->es) );
|
||||
@@ -704,7 +705,7 @@ static void __context_switch(void)
|
||||
loaddebug(&n->arch.guest_context, 7);
|
||||
}
|
||||
|
||||
if ( !VMX_DOMAIN(n) )
|
||||
if ( !HVM_DOMAIN(n) )
|
||||
{
|
||||
set_int80_direct_trap(n);
|
||||
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. */
|
||||
local_irq_enable();
|
||||
|
||||
if ( VMX_DOMAIN(next) )
|
||||
if ( HVM_DOMAIN(next) )
|
||||
{
|
||||
vmx_restore_msrs(next);
|
||||
hvm_restore_msrs(next);
|
||||
}
|
||||
else
|
||||
{
|
||||
load_LDT(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);
|
||||
}
|
||||
|
||||
vmx_relinquish_resources(v);
|
||||
if ( HVM_DOMAIN(v) )
|
||||
hvm_relinquish_guest_resources(v);
|
||||
}
|
||||
|
||||
shadow_mode_disable(d);
|
||||
|
||||
@@ -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/errno.h>
|
||||
#include <xen/sched.h>
|
||||
#include <public/hvm/ioreq.h>
|
||||
#include <asm/vmx.h>
|
||||
#include <asm/vmx_vpic.h>
|
||||
#include <asm/hvm/hvm.h>
|
||||
#include <asm/hvm/io.h>
|
||||
#include <asm/hvm/support.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 */
|
||||
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
|
||||
irq may change */
|
||||
/* 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;
|
||||
|
||||
@@ -123,9 +121,9 @@ void pic_update_irq(struct vmx_virpic *s)
|
||||
|
||||
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);
|
||||
/* used for IOAPIC irqs */
|
||||
if (s->alt_irq_func)
|
||||
@@ -133,24 +131,24 @@ void pic_set_irq_new(void *opaque, int irq, int level)
|
||||
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[0].irr |= (uint8_t) irqs;
|
||||
vmx_vioapic_do_irqs(current->domain, irqs);
|
||||
hvm_vioapic_do_irqs(current->domain, irqs);
|
||||
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[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);
|
||||
}
|
||||
|
||||
/* 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);
|
||||
}
|
||||
@@ -169,7 +167,7 @@ static inline void pic_intack(PicState *s, int 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;
|
||||
|
||||
@@ -200,7 +198,7 @@ int pic_read_irq(struct vmx_virpic *s)
|
||||
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;
|
||||
|
||||
@@ -378,7 +376,7 @@ static uint32_t pic_ioport_read(void *opaque, uint32_t addr1)
|
||||
|
||||
/* memory mapped interrupt status */
|
||||
/* 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;
|
||||
|
||||
@@ -409,7 +407,7 @@ static void pic_init1(int io_addr, int elcr_addr, PicState *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)
|
||||
{
|
||||
memset(s, 0, sizeof(*s));
|
||||
@@ -424,7 +422,7 @@ void pic_init(struct vmx_virpic *s, void (*irq_request)(),
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
struct vmx_virpic *pic;
|
||||
struct hvm_virpic *pic;
|
||||
struct vcpu *v = current;
|
||||
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);
|
||||
return 1;
|
||||
}
|
||||
pic = &v->domain->arch.vmx_platform.vmx_pic;
|
||||
pic = &v->domain->arch.hvm_domain.vpic;
|
||||
if ( p->dir == 0 ) {
|
||||
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
|
||||
data = p->u.data;
|
||||
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(
|
||||
(void*)&pic->pics[p->addr>>7], (uint32_t) p->addr);
|
||||
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
|
||||
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)
|
||||
{
|
||||
struct vmx_virpic *s;
|
||||
struct hvm_virpic *s;
|
||||
struct vcpu *v = current;
|
||||
uint32_t data;
|
||||
|
||||
@@ -472,10 +470,10 @@ static int intercept_elcr_io(ioreq_t *p)
|
||||
return 1;
|
||||
}
|
||||
|
||||
s = &v->domain->arch.vmx_platform.vmx_pic;
|
||||
s = &v->domain->arch.hvm_domain.vpic;
|
||||
if ( p->dir == 0 ) {
|
||||
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
|
||||
data = p->u.data;
|
||||
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(
|
||||
(void*)&s->pics[p->addr&1], (uint32_t) p->addr);
|
||||
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
|
||||
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 intno;
|
||||
struct vmx_virpic *s = &v->domain->arch.vmx_platform.vmx_pic;
|
||||
struct vmx_platform *plat = &v->domain->arch.vmx_platform;
|
||||
struct hvm_virpic *s = &v->domain->arch.hvm_domain.vpic;
|
||||
struct hvm_domain *plat = &v->domain->arch.hvm_domain;
|
||||
|
||||
if ( !vlapic_accept_pic_intr(v) )
|
||||
return -1;
|
||||
@@ -528,17 +526,17 @@ int is_pit_irq(struct vcpu *v, int irq, int type)
|
||||
int pit_vec;
|
||||
|
||||
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
|
||||
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);
|
||||
}
|
||||
|
||||
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 ) {
|
||||
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.
|
||||
*
|
||||
* 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
|
||||
* 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/types.h>
|
||||
#include <asm/vmx.h>
|
||||
#include <asm/vmx_platform.h>
|
||||
#include <asm/vmx_vpit.h>
|
||||
#include <asm/vmx_intercept.h>
|
||||
#include <asm/vmx_vlapic.h>
|
||||
#include <public/hvm/ioreq.h>
|
||||
#include <xen/sched.h>
|
||||
#include <asm/regs.h>
|
||||
#include <asm/hvm/hvm.h>
|
||||
#include <asm/hvm/support.h>
|
||||
#include <asm/hvm/domain.h>
|
||||
#include <xen/lib.h>
|
||||
#include <xen/sched.h>
|
||||
#include <asm/current.h>
|
||||
#include <io_ports.h>
|
||||
#include <xen/event.h>
|
||||
|
||||
#ifdef CONFIG_VMX
|
||||
|
||||
extern struct vmx_mmio_handler vlapic_mmio_handler;
|
||||
extern struct vmx_mmio_handler vioapic_mmio_handler;
|
||||
extern struct hvm_mmio_handler vlapic_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,
|
||||
&vioapic_mmio_handler
|
||||
};
|
||||
|
||||
static inline void vmx_mmio_access(struct vcpu *v,
|
||||
static inline void hvm_mmio_access(struct vcpu *v,
|
||||
ioreq_t *p,
|
||||
vmx_mmio_read_t read_handler,
|
||||
vmx_mmio_write_t write_handler)
|
||||
hvm_mmio_read_t read_handler,
|
||||
hvm_mmio_write_t write_handler)
|
||||
{
|
||||
ioreq_t *req;
|
||||
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,
|
||||
req->addr + (sign * i * req->size),
|
||||
req->size);
|
||||
vmx_copy(&data,
|
||||
hvm_copy(&data,
|
||||
(unsigned long)p->u.pdata + (sign * i * req->size),
|
||||
p->size,
|
||||
VMX_COPY_OUT);
|
||||
HVM_COPY_OUT);
|
||||
}
|
||||
} else { /* !req->dir == IOREQ_READ */
|
||||
for (i = 0; i < req->count; i++) {
|
||||
vmx_copy(&data,
|
||||
hvm_copy(&data,
|
||||
(unsigned long)p->u.pdata + (sign * i * req->size),
|
||||
p->size,
|
||||
VMX_COPY_IN);
|
||||
HVM_COPY_IN);
|
||||
write_handler(v,
|
||||
req->addr + (sign * i * req->size),
|
||||
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;
|
||||
int i;
|
||||
|
||||
/* XXX currently only APIC use intercept */
|
||||
if ( !vmx_apic_support(v->domain) )
|
||||
if ( !hvm_apic_support(v->domain) )
|
||||
return 0;
|
||||
|
||||
for ( i = 0; i < VMX_MMIO_HANDLER_NR; i++ ) {
|
||||
if ( vmx_mmio_handlers[i]->check_handler(v, p->addr) ) {
|
||||
vmx_mmio_access(v, p,
|
||||
vmx_mmio_handlers[i]->read_handler,
|
||||
vmx_mmio_handlers[i]->write_handler);
|
||||
for ( i = 0; i < HVM_MMIO_HANDLER_NR; i++ ) {
|
||||
if ( hvm_mmio_handlers[i]->check_handler(v, p->addr) ) {
|
||||
hvm_mmio_access(v, p,
|
||||
hvm_mmio_handlers[i]->read_handler,
|
||||
hvm_mmio_handlers[i]->write_handler);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@@ -156,11 +154,11 @@ int vmx_mmio_intercept(ioreq_t *p)
|
||||
* Check if the request is handled inside xen
|
||||
* 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 vmx_io_handler *handler =
|
||||
&(v->domain->arch.vmx_platform.vmx_io_handler);
|
||||
struct hvm_io_handler *handler =
|
||||
&(v->domain->arch.hvm_domain.io_handler);
|
||||
int i;
|
||||
unsigned long addr, size;
|
||||
|
||||
@@ -180,8 +178,8 @@ int register_io_handler(unsigned long addr, unsigned long size,
|
||||
intercept_action_t action, int type)
|
||||
{
|
||||
struct vcpu *v = current;
|
||||
struct vmx_io_handler *handler =
|
||||
&(v->domain->arch.vmx_platform.vmx_io_handler);
|
||||
struct hvm_io_handler *handler =
|
||||
&(v->domain->arch.hvm_domain.io_handler);
|
||||
int num = handler->num_slot;
|
||||
|
||||
if (num >= MAX_IO_HANDLER) {
|
||||
@@ -198,21 +196,25 @@ int register_io_handler(unsigned long addr, unsigned long size,
|
||||
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));
|
||||
|
||||
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)
|
||||
{
|
||||
printk("PIT init value == 0!\n");
|
||||
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);
|
||||
|
||||
@@ -228,7 +230,8 @@ static void pit_latch_io(struct vmx_virpit *vpit)
|
||||
vpit->count_MSB_latched=1;
|
||||
break;
|
||||
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->count_LSB_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) {
|
||||
/* Read Least Significant Byte */
|
||||
@@ -256,7 +259,7 @@ static int pit_read_io(struct vmx_virpit *vpit)
|
||||
return ((vpit->count>>8) & 0xFF);
|
||||
} else {
|
||||
/* 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);
|
||||
if(!(vpit->read_state & 0x1)) {
|
||||
/* 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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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 ||
|
||||
p->pdata_valid ||
|
||||
@@ -333,7 +336,7 @@ void hlt_timer_fn(void *data)
|
||||
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;
|
||||
|
||||
@@ -348,7 +351,7 @@ static __inline__ void missed_ticks(struct vmx_virpit*vpit)
|
||||
static void pit_timer_fn(void *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 */
|
||||
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)) ) {
|
||||
@@ -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.
|
||||
* 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);
|
||||
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;
|
||||
|
||||
/* load init count*/
|
||||
if (p->state == STATE_IORESP_HOOK) {
|
||||
/* set up actimer, handle re-init */
|
||||
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));
|
||||
reinit = 1;
|
||||
|
||||
@@ -399,14 +402,14 @@ void vmx_hooks_assist(struct vcpu *v)
|
||||
vpit->init_val = (p->u.data & 0xFFFF) ;
|
||||
/* frequency(ns) of pit */
|
||||
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 */
|
||||
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->period = 1000000;
|
||||
}
|
||||
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->first_injected = 0;
|
||||
@@ -426,7 +429,7 @@ void vmx_hooks_assist(struct vcpu *v)
|
||||
vpit->read_state=LSByte_multiple;
|
||||
break;
|
||||
default:
|
||||
printk("VMX_PIT:wrong PIT rw_mode!\n");
|
||||
printk("HVM_PIT:wrong PIT rw_mode!\n");
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -442,7 +445,6 @@ void vmx_hooks_assist(struct vcpu *v)
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_VMX */
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
@@ -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) 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,
|
||||
@@ -14,7 +16,6 @@
|
||||
* 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>
|
||||
@@ -24,42 +25,24 @@
|
||||
#include <xen/errno.h>
|
||||
#include <xen/trace.h>
|
||||
#include <xen/event.h>
|
||||
|
||||
#include <xen/hypercall.h>
|
||||
#include <asm/current.h>
|
||||
#include <asm/cpufeature.h>
|
||||
#include <asm/processor.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/shadow.h>
|
||||
#include <asm/vmx_vpic.h>
|
||||
#include <asm/vmx_vlapic.h>
|
||||
#include <asm/hvm/hvm.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/hvm/ioreq.h>
|
||||
|
||||
#ifdef CONFIG_VMX
|
||||
#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)
|
||||
{
|
||||
switch (size) {
|
||||
@@ -182,21 +165,6 @@ static void set_reg_value (int size, int index, int seg, struct cpu_user_regs *r
|
||||
}
|
||||
}
|
||||
#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)
|
||||
{
|
||||
switch (size) {
|
||||
@@ -391,7 +359,7 @@ static inline void set_eflags_PF(int size, unsigned long v1,
|
||||
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)
|
||||
{
|
||||
unsigned long old_eax;
|
||||
@@ -414,7 +382,7 @@ static void vmx_pio_assist(struct cpu_user_regs *regs, ioreq_t *p,
|
||||
addr = regs->edi;
|
||||
if (sign > 0)
|
||||
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) {
|
||||
regs->edi += sign * p->count * p->size;
|
||||
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,
|
||||
struct mmio_op *mmio_opp)
|
||||
static void hvm_mmio_assist(struct vcpu *v, struct cpu_user_regs *regs,
|
||||
ioreq_t *p, struct mmio_op *mmio_opp)
|
||||
{
|
||||
int sign = p->df ? -1 : 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)
|
||||
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)
|
||||
@@ -680,10 +648,10 @@ static void vmx_mmio_assist(struct cpu_user_regs *regs, ioreq_t *p,
|
||||
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;
|
||||
ioreq_t *p;
|
||||
@@ -691,13 +659,13 @@ void vmx_io_assist(struct vcpu *v)
|
||||
struct mmio_op *mmio_opp;
|
||||
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;
|
||||
|
||||
vio = get_vio(v->domain, v->vcpu_id);
|
||||
|
||||
if (vio == 0) {
|
||||
VMX_DBG_LOG(DBG_LEVEL_1,
|
||||
HVM_DBG_LOG(DBG_LEVEL_1,
|
||||
"bad shared page: %lx", (unsigned long) vio);
|
||||
printf("bad shared page: %lx\n", (unsigned long) vio);
|
||||
domain_crash_synchronous();
|
||||
@@ -705,24 +673,24 @@ void vmx_io_assist(struct vcpu *v)
|
||||
|
||||
p = &vio->vp_ioreq;
|
||||
if (p->state == STATE_IORESP_HOOK)
|
||||
vmx_hooks_assist(v);
|
||||
hvm_hooks_assist(v);
|
||||
|
||||
/* clear IO wait VMX flag */
|
||||
if (test_bit(ARCH_VMX_IO_WAIT, &v->arch.arch_vmx.flags)) {
|
||||
/* clear IO wait HVM flag */
|
||||
if (test_bit(ARCH_HVM_IO_WAIT, &v->arch.hvm_vcpu.ioflags)) {
|
||||
if (p->state == STATE_IORESP_READY) {
|
||||
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)
|
||||
vmx_pio_assist(regs, p, mmio_opp);
|
||||
hvm_pio_assist(regs, p, mmio_opp);
|
||||
else
|
||||
vmx_mmio_assist(regs, p, mmio_opp);
|
||||
hvm_mmio_assist(v, regs, p, mmio_opp);
|
||||
}
|
||||
/* 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;
|
||||
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])
|
||||
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)
|
||||
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]);
|
||||
}
|
||||
|
||||
/* 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.
|
||||
* 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 */
|
||||
if (vmx_clear_pending_io_event(v))
|
||||
vmx_io_assist(v);
|
||||
/*
|
||||
* Clear the event *before* checking for work. This should
|
||||
* avoid the set-and-check races
|
||||
*/
|
||||
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 */
|
||||
void vmx_wait_io()
|
||||
/*
|
||||
* On exit from hvm_wait_io, we're guaranteed to have a I/O response
|
||||
* from the device model.
|
||||
*/
|
||||
void hvm_wait_io(void)
|
||||
{
|
||||
int port = iopacket_port(current->domain);
|
||||
|
||||
do {
|
||||
if (!test_bit(port, ¤t->domain->shared_info->evtchn_pending[0]))
|
||||
do_sched_op(SCHEDOP_block, 0);
|
||||
do_sched_op(SCHEDOP_block, 0);
|
||||
|
||||
vmx_check_events(current);
|
||||
if (!test_bit(ARCH_VMX_IO_WAIT, ¤t->arch.arch_vmx.flags))
|
||||
hvm_check_events(current);
|
||||
if (!test_bit(ARCH_HVM_IO_WAIT, ¤t->arch.hvm_vcpu.ioflags))
|
||||
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, ¤t->vcpu_info->evtchn_pending_sel);
|
||||
clear_bit(0, ¤t->vcpu_info->evtchn_upcall_pending);
|
||||
} 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:
|
||||
* 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) 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,
|
||||
@@ -14,7 +16,6 @@
|
||||
* 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>
|
||||
@@ -25,8 +26,10 @@
|
||||
#include <asm/page.h>
|
||||
#include <xen/event.h>
|
||||
#include <xen/trace.h>
|
||||
#include <asm/vmx.h>
|
||||
#include <asm/vmx_platform.h>
|
||||
#include <xen/sched.h>
|
||||
#include <asm/regs.h>
|
||||
#include <asm/hvm/hvm.h>
|
||||
#include <asm/hvm/support.h>
|
||||
#include <public/hvm/ioreq.h>
|
||||
|
||||
#include <xen/lib.h>
|
||||
@@ -35,23 +38,13 @@
|
||||
#if CONFIG_PAGING_LEVELS >= 3
|
||||
#include <asm/shadow_64.h>
|
||||
#endif
|
||||
#ifdef CONFIG_VMX
|
||||
|
||||
#define DECODE_success 1
|
||||
#define DECODE_failure 0
|
||||
|
||||
#if defined (__x86_64__)
|
||||
void store_cpu_user_regs(struct cpu_user_regs *regs)
|
||||
{
|
||||
__vmread(GUEST_SS_SELECTOR, ®s->ss);
|
||||
__vmread(GUEST_RSP, ®s->rsp);
|
||||
__vmread(GUEST_RFLAGS, ®s->rflags);
|
||||
__vmread(GUEST_CS_SELECTOR, ®s->cs);
|
||||
__vmread(GUEST_DS_SELECTOR, ®s->ds);
|
||||
__vmread(GUEST_ES_SELECTOR, ®s->es);
|
||||
__vmread(GUEST_RIP, ®s->rip);
|
||||
}
|
||||
extern long evtchn_send(int lport);
|
||||
|
||||
#if defined (__x86_64__)
|
||||
static inline long __get_reg_value(unsigned long reg, int 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__)
|
||||
void store_cpu_user_regs(struct cpu_user_regs *regs)
|
||||
{
|
||||
__vmread(GUEST_SS_SELECTOR, ®s->ss);
|
||||
__vmread(GUEST_RSP, ®s->esp);
|
||||
__vmread(GUEST_RFLAGS, ®s->eflags);
|
||||
__vmread(GUEST_CS_SELECTOR, ®s->cs);
|
||||
__vmread(GUEST_DS_SELECTOR, ®s->ds);
|
||||
__vmread(GUEST_ES_SELECTOR, ®s->es);
|
||||
__vmread(GUEST_RIP, ®s->eip);
|
||||
}
|
||||
|
||||
static inline long __get_reg_value(unsigned long reg, int size)
|
||||
{
|
||||
switch(size) {
|
||||
@@ -214,8 +196,6 @@ static inline unsigned char *check_prefix(unsigned char *inst,
|
||||
thread_inst->op_size = WORD;
|
||||
break;
|
||||
case 0x67:
|
||||
printf("Error: Not handling 0x67 (yet)\n");
|
||||
domain_crash_synchronous();
|
||||
break;
|
||||
default:
|
||||
return inst;
|
||||
@@ -366,7 +346,7 @@ static int reg_mem(unsigned char size, unsigned char *opcode,
|
||||
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 rex = 0;
|
||||
@@ -376,7 +356,7 @@ static int vmx_decode(int vm86, unsigned char *opcode, struct instruction *instr
|
||||
|
||||
opcode = check_prefix(opcode, instr, &rex);
|
||||
|
||||
if (vm86) { /* meaning is reversed */
|
||||
if (realmode) { /* meaning is reversed */
|
||||
if (instr->op_size == WORD)
|
||||
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->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);
|
||||
|
||||
switch (ins_subtype) {
|
||||
@@ -531,7 +511,7 @@ static int vmx_decode(int vm86, unsigned char *opcode, struct instruction *instr
|
||||
instr->op_size = BYTE;
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
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->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);
|
||||
|
||||
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)
|
||||
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 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,
|
||||
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;
|
||||
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);
|
||||
if (vio == NULL) {
|
||||
@@ -658,12 +687,12 @@ void send_mmio_req(unsigned char type, unsigned long gpa,
|
||||
|
||||
p = &vio->vp_ioreq;
|
||||
|
||||
if (test_bit(ARCH_VMX_IO_WAIT, &v->arch.arch_vmx.flags)) {
|
||||
printf("VMX I/O has not yet completed\n");
|
||||
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_VMX_IO_WAIT, &v->arch.arch_vmx.flags);
|
||||
set_bit(ARCH_HVM_IO_WAIT, &v->arch.hvm_vcpu.ioflags);
|
||||
p->dir = dir;
|
||||
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;
|
||||
|
||||
if (pvalid) {
|
||||
if (vmx_paging_enabled(current))
|
||||
if (hvm_paging_enabled(v))
|
||||
p->u.pdata = (void *) gva_to_gpa(value);
|
||||
else
|
||||
p->u.pdata = (void *) value; /* guest VA == guest PA */
|
||||
} else
|
||||
p->u.data = value;
|
||||
|
||||
if (vmx_mmio_intercept(p)){
|
||||
if (hvm_mmio_intercept(p)){
|
||||
p->state = STATE_IORESP_READY;
|
||||
vmx_io_assist(v);
|
||||
hvm_io_assist(v);
|
||||
return;
|
||||
}
|
||||
|
||||
p->state = STATE_IOREQ_READY;
|
||||
|
||||
evtchn_send(iopacket_port(v->domain));
|
||||
vmx_wait_io();
|
||||
hvm_wait_io();
|
||||
}
|
||||
|
||||
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() \
|
||||
(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)
|
||||
{
|
||||
@@ -736,17 +765,21 @@ void handle_mmio(unsigned long va, unsigned long gpa)
|
||||
struct cpu_user_regs *regs;
|
||||
struct instruction mmio_inst;
|
||||
unsigned char inst[MAX_INST_LEN];
|
||||
int i, vm86, ret;
|
||||
int i, realmode, ret;
|
||||
struct vcpu *v = current;
|
||||
|
||||
mmio_opp = ¤t->arch.arch_vmx.mmio_op;
|
||||
mmio_opp = &v->arch.hvm_vcpu.mmio_op;
|
||||
|
||||
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;
|
||||
if (vm86)
|
||||
realmode = hvm_realmode(v);
|
||||
if (realmode)
|
||||
inst_addr = (regs->cs << 4) + regs->eip;
|
||||
else
|
||||
inst_addr = regs->eip;
|
||||
@@ -754,13 +787,14 @@ void handle_mmio(unsigned long va, unsigned long gpa)
|
||||
memset(inst, 0, MAX_INST_LEN);
|
||||
ret = inst_copy_from_guest(inst, inst_addr, 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();
|
||||
}
|
||||
|
||||
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:",
|
||||
va, gpa, inst_len);
|
||||
for (i = 0; i < inst_len; i++)
|
||||
@@ -785,7 +819,7 @@ void handle_mmio(unsigned long va, unsigned long gpa)
|
||||
int dir;
|
||||
|
||||
/* determine non-MMIO address */
|
||||
if (vm86) {
|
||||
if (realmode) {
|
||||
if (((regs->es << 4) + (regs->edi & 0xFFFF)) == va) {
|
||||
dir = IOREQ_WRITE;
|
||||
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 */
|
||||
|
||||
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);
|
||||
} else {
|
||||
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:
|
||||
* mode: C
|
||||
@@ -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