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