Files
xen/xen/arch/x86/hvm/platform.c
T
kaf24@firebug.cl.cam.ac.uk d1bd157fbc 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.
2006-01-31 11:49:51 +01:00

952 lines
29 KiB
C

/*
* platform.c: handling x86 platform related MMIO instructions
*
* Copyright (c) 2004, Intel Corporation.
* Copyright (c) 2005, International Business Machines Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* 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/types.h>
#include <xen/mm.h>
#include <asm/shadow.h>
#include <xen/domain_page.h>
#include <asm/page.h>
#include <xen/event.h>
#include <xen/trace.h>
#include <xen/sched.h>
#include <asm/regs.h>
#include <asm/hvm/hvm.h>
#include <asm/hvm/support.h>
#include <public/hvm/ioreq.h>
#include <xen/lib.h>
#include <xen/sched.h>
#include <asm/current.h>
#if CONFIG_PAGING_LEVELS >= 3
#include <asm/shadow_64.h>
#endif
#define DECODE_success 1
#define DECODE_failure 0
extern long evtchn_send(int lport);
#if defined (__x86_64__)
static inline long __get_reg_value(unsigned long reg, int size)
{
switch(size) {
case BYTE_64:
return (char)(reg & 0xFF);
case WORD:
return (short)(reg & 0xFFFF);
case LONG:
return (int)(reg & 0xFFFFFFFF);
case QUAD:
return (long)(reg);
default:
printf("Error: (__get_reg_value) Invalid reg size\n");
domain_crash_synchronous();
}
}
long get_reg_value(int size, int index, int seg, struct cpu_user_regs *regs)
{
if (size == BYTE) {
switch (index) {
case 0: /* %al */
return (char)(regs->rax & 0xFF);
case 1: /* %cl */
return (char)(regs->rcx & 0xFF);
case 2: /* %dl */
return (char)(regs->rdx & 0xFF);
case 3: /* %bl */
return (char)(regs->rbx & 0xFF);
case 4: /* %ah */
return (char)((regs->rax & 0xFF00) >> 8);
case 5: /* %ch */
return (char)((regs->rcx & 0xFF00) >> 8);
case 6: /* %dh */
return (char)((regs->rdx & 0xFF00) >> 8);
case 7: /* %bh */
return (char)((regs->rbx & 0xFF00) >> 8);
default:
printf("Error: (get_reg_value) Invalid index value\n");
domain_crash_synchronous();
}
/* NOTREACHED */
}
switch (index) {
case 0: return __get_reg_value(regs->rax, size);
case 1: return __get_reg_value(regs->rcx, size);
case 2: return __get_reg_value(regs->rdx, size);
case 3: return __get_reg_value(regs->rbx, size);
case 4: return __get_reg_value(regs->rsp, size);
case 5: return __get_reg_value(regs->rbp, size);
case 6: return __get_reg_value(regs->rsi, size);
case 7: return __get_reg_value(regs->rdi, size);
case 8: return __get_reg_value(regs->r8, size);
case 9: return __get_reg_value(regs->r9, size);
case 10: return __get_reg_value(regs->r10, size);
case 11: return __get_reg_value(regs->r11, size);
case 12: return __get_reg_value(regs->r12, size);
case 13: return __get_reg_value(regs->r13, size);
case 14: return __get_reg_value(regs->r14, size);
case 15: return __get_reg_value(regs->r15, size);
default:
printf("Error: (get_reg_value) Invalid index value\n");
domain_crash_synchronous();
}
}
#elif defined (__i386__)
static inline long __get_reg_value(unsigned long reg, int size)
{
switch(size) {
case WORD:
return (short)(reg & 0xFFFF);
case LONG:
return (int)(reg & 0xFFFFFFFF);
default:
printf("Error: (__get_reg_value) Invalid reg size\n");
domain_crash_synchronous();
}
}
long get_reg_value(int size, int index, int seg, struct cpu_user_regs *regs)
{
if (size == BYTE) {
switch (index) {
case 0: /* %al */
return (char)(regs->eax & 0xFF);
case 1: /* %cl */
return (char)(regs->ecx & 0xFF);
case 2: /* %dl */
return (char)(regs->edx & 0xFF);
case 3: /* %bl */
return (char)(regs->ebx & 0xFF);
case 4: /* %ah */
return (char)((regs->eax & 0xFF00) >> 8);
case 5: /* %ch */
return (char)((regs->ecx & 0xFF00) >> 8);
case 6: /* %dh */
return (char)((regs->edx & 0xFF00) >> 8);
case 7: /* %bh */
return (char)((regs->ebx & 0xFF00) >> 8);
default:
printf("Error: (get_reg_value) Invalid index value\n");
domain_crash_synchronous();
}
}
switch (index) {
case 0: return __get_reg_value(regs->eax, size);
case 1: return __get_reg_value(regs->ecx, size);
case 2: return __get_reg_value(regs->edx, size);
case 3: return __get_reg_value(regs->ebx, size);
case 4: return __get_reg_value(regs->esp, size);
case 5: return __get_reg_value(regs->ebp, size);
case 6: return __get_reg_value(regs->esi, size);
case 7: return __get_reg_value(regs->edi, size);
default:
printf("Error: (get_reg_value) Invalid index value\n");
domain_crash_synchronous();
}
}
#endif
static inline unsigned char *check_prefix(unsigned char *inst,
struct instruction *thread_inst, unsigned char *rex_p)
{
while (1) {
switch (*inst) {
/* rex prefix for em64t instructions */
case 0x40 ... 0x4e:
*rex_p = *inst;
break;
case 0xf3: /* REPZ */
thread_inst->flags = REPZ;
break;
case 0xf2: /* REPNZ */
thread_inst->flags = REPNZ;
break;
case 0xf0: /* LOCK */
break;
case 0x2e: /* CS */
case 0x36: /* SS */
case 0x3e: /* DS */
case 0x26: /* ES */
case 0x64: /* FS */
case 0x65: /* GS */
thread_inst->seg_sel = *inst;
break;
case 0x66: /* 32bit->16bit */
thread_inst->op_size = WORD;
break;
case 0x67:
break;
default:
return inst;
}
inst++;
}
}
static inline unsigned long get_immediate(int op16,const unsigned char *inst, int op_size)
{
int mod, reg, rm;
unsigned long val = 0;
int i;
mod = (*inst >> 6) & 3;
reg = (*inst >> 3) & 7;
rm = *inst & 7;
inst++; //skip ModR/M byte
if (mod != 3 && rm == 4) {
inst++; //skip SIB byte
}
switch(mod) {
case 0:
if (rm == 5 || rm == 4) {
if (op16)
inst = inst + 2; //disp16, skip 2 bytes
else
inst = inst + 4; //disp32, skip 4 bytes
}
break;
case 1:
inst++; //disp8, skip 1 byte
break;
case 2:
if (op16)
inst = inst + 2; //disp16, skip 2 bytes
else
inst = inst + 4; //disp32, skip 4 bytes
break;
}
if (op_size == QUAD)
op_size = LONG;
for (i = 0; i < op_size; i++) {
val |= (*inst++ & 0xff) << (8 * i);
}
return val;
}
static inline int get_index(const unsigned char *inst, unsigned char rex)
{
int mod, reg, rm;
int rex_r, rex_b;
mod = (*inst >> 6) & 3;
reg = (*inst >> 3) & 7;
rm = *inst & 7;
rex_r = (rex >> 2) & 1;
rex_b = rex & 1;
//Only one operand in the instruction is register
if (mod == 3) {
return (rm + (rex_b << 3));
} else {
return (reg + (rex_r << 3));
}
return 0;
}
static void init_instruction(struct instruction *mmio_inst)
{
mmio_inst->instr = 0;
mmio_inst->op_size = 0;
mmio_inst->immediate = 0;
mmio_inst->seg_sel = 0;
mmio_inst->operand[0] = 0;
mmio_inst->operand[1] = 0;
mmio_inst->flags = 0;
}
#define GET_OP_SIZE_FOR_BYTE(op_size) \
do { \
if (rex) \
op_size = BYTE_64; \
else \
op_size = BYTE; \
} while(0)
#define GET_OP_SIZE_FOR_NONEBYTE(op_size) \
do { \
if (rex & 0x8) \
op_size = QUAD; \
else if (op_size != WORD) \
op_size = LONG; \
} while(0)
/*
* Decode mem,accumulator operands (as in <opcode> m8/m16/m32, al,ax,eax)
*/
static int mem_acc(unsigned char size, struct instruction *instr)
{
instr->operand[0] = mk_operand(size, 0, 0, MEMORY);
instr->operand[1] = mk_operand(size, 0, 0, REGISTER);
return DECODE_success;
}
/*
* Decode accumulator,mem operands (as in <opcode> al,ax,eax, m8/m16/m32)
*/
static int acc_mem(unsigned char size, struct instruction *instr)
{
instr->operand[0] = mk_operand(size, 0, 0, REGISTER);
instr->operand[1] = mk_operand(size, 0, 0, MEMORY);
return DECODE_success;
}
/*
* Decode mem,reg operands (as in <opcode> r32/16, m32/16)
*/
static int mem_reg(unsigned char size, unsigned char *opcode,
struct instruction *instr, unsigned char rex)
{
int index = get_index(opcode + 1, rex);
instr->operand[0] = mk_operand(size, 0, 0, MEMORY);
instr->operand[1] = mk_operand(size, index, 0, REGISTER);
return DECODE_success;
}
/*
* Decode reg,mem operands (as in <opcode> m32/16, r32/16)
*/
static int reg_mem(unsigned char size, unsigned char *opcode,
struct instruction *instr, unsigned char rex)
{
int index = get_index(opcode + 1, rex);
instr->operand[0] = mk_operand(size, index, 0, REGISTER);
instr->operand[1] = mk_operand(size, 0, 0, MEMORY);
return DECODE_success;
}
static int hvm_decode(int realmode, unsigned char *opcode, struct instruction *instr)
{
unsigned char size_reg = 0;
unsigned char rex = 0;
int index;
init_instruction(instr);
opcode = check_prefix(opcode, instr, &rex);
if (realmode) { /* meaning is reversed */
if (instr->op_size == WORD)
instr->op_size = LONG;
else if (instr->op_size == LONG)
instr->op_size = WORD;
else if (instr->op_size == 0)
instr->op_size = WORD;
}
switch (*opcode) {
case 0x0B: /* or m32/16, r32/16 */
instr->instr = INSTR_OR;
GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
return mem_reg(instr->op_size, opcode, instr, rex);
case 0x20: /* and r8, m8 */
instr->instr = INSTR_AND;
instr->op_size = BYTE;
GET_OP_SIZE_FOR_BYTE(size_reg);
return reg_mem(size_reg, opcode, instr, rex);
case 0x21: /* and r32/16, m32/16 */
instr->instr = INSTR_AND;
GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
return reg_mem(instr->op_size, opcode, instr, rex);
case 0x23: /* and m32/16, r32/16 */
instr->instr = INSTR_AND;
GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
return mem_reg(instr->op_size, opcode, instr, rex);
case 0x30: /* xor r8, m8 */
instr->instr = INSTR_XOR;
instr->op_size = BYTE;
GET_OP_SIZE_FOR_BYTE(size_reg);
return reg_mem(size_reg, opcode, instr, rex);
case 0x31: /* xor r32/16, m32/16 */
instr->instr = INSTR_XOR;
GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
return reg_mem(instr->op_size, opcode, instr, rex);
case 0x39: /* cmp r32/16, m32/16 */
instr->instr = INSTR_CMP;
GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
return reg_mem(instr->op_size, opcode, instr, rex);
case 0x80:
case 0x81:
{
unsigned char ins_subtype = (opcode[1] >> 3) & 7;
if (opcode[0] == 0x80) {
GET_OP_SIZE_FOR_BYTE(size_reg);
instr->op_size = BYTE;
} else {
GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
size_reg = instr->op_size;
}
instr->operand[0] = mk_operand(size_reg, 0, 0, IMMEDIATE);
instr->immediate = get_immediate(realmode, opcode+1, instr->op_size);
instr->operand[1] = mk_operand(size_reg, 0, 0, MEMORY);
switch (ins_subtype) {
case 7: /* cmp $imm, m32/16 */
instr->instr = INSTR_CMP;
return DECODE_success;
case 1: /* or $imm, m32/16 */
instr->instr = INSTR_OR;
return DECODE_success;
default:
printf("%x, This opcode isn't handled yet!\n", *opcode);
return DECODE_failure;
}
}
case 0x84: /* test m8, r8 */
instr->instr = INSTR_TEST;
instr->op_size = BYTE;
GET_OP_SIZE_FOR_BYTE(size_reg);
return mem_reg(size_reg, opcode, instr, rex);
case 0x88: /* mov r8, m8 */
instr->instr = INSTR_MOV;
instr->op_size = BYTE;
GET_OP_SIZE_FOR_BYTE(size_reg);
return reg_mem(size_reg, opcode, instr, rex);
case 0x89: /* mov r32/16, m32/16 */
instr->instr = INSTR_MOV;
GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
return reg_mem(instr->op_size, opcode, instr, rex);
case 0x8A: /* mov m8, r8 */
instr->instr = INSTR_MOV;
instr->op_size = BYTE;
GET_OP_SIZE_FOR_BYTE(size_reg);
return mem_reg(size_reg, opcode, instr, rex);
case 0x8B: /* mov m32/16, r32/16 */
instr->instr = INSTR_MOV;
GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
return mem_reg(instr->op_size, opcode, instr, rex);
case 0xA0: /* mov <addr>, al */
instr->instr = INSTR_MOV;
instr->op_size = BYTE;
GET_OP_SIZE_FOR_BYTE(size_reg);
return mem_acc(size_reg, instr);
case 0xA1: /* mov <addr>, ax/eax */
instr->instr = INSTR_MOV;
GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
return mem_acc(instr->op_size, instr);
case 0xA2: /* mov al, <addr> */
instr->instr = INSTR_MOV;
instr->op_size = BYTE;
GET_OP_SIZE_FOR_BYTE(size_reg);
return acc_mem(size_reg, instr);
case 0xA3: /* mov ax/eax, <addr> */
instr->instr = INSTR_MOV;
GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
return acc_mem(instr->op_size, instr);
case 0xA4: /* movsb */
instr->instr = INSTR_MOVS;
instr->op_size = BYTE;
return DECODE_success;
case 0xA5: /* movsw/movsl */
instr->instr = INSTR_MOVS;
GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
return DECODE_success;
case 0xAA: /* stosb */
instr->instr = INSTR_STOS;
instr->op_size = BYTE;
return DECODE_success;
case 0xAB: /* stosw/stosl */
instr->instr = INSTR_STOS;
GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
return DECODE_success;
case 0xC6:
if (((opcode[1] >> 3) & 7) == 0) { /* mov $imm8, m8 */
instr->instr = INSTR_MOV;
instr->op_size = BYTE;
instr->operand[0] = mk_operand(instr->op_size, 0, 0, IMMEDIATE);
instr->immediate = get_immediate(realmode, opcode+1, instr->op_size);
instr->operand[1] = mk_operand(instr->op_size, 0, 0, MEMORY);
return DECODE_success;
} else
return DECODE_failure;
case 0xC7:
if (((opcode[1] >> 3) & 7) == 0) { /* mov $imm16/32, m16/32 */
instr->instr = INSTR_MOV;
GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
instr->operand[0] = mk_operand(instr->op_size, 0, 0, IMMEDIATE);
instr->immediate = get_immediate(realmode, opcode+1, instr->op_size);
instr->operand[1] = mk_operand(instr->op_size, 0, 0, MEMORY);
return DECODE_success;
} else
return DECODE_failure;
case 0xF6:
case 0xF7:
if (((opcode[1] >> 3) & 7) == 0) { /* test $imm8/16/32, m8/16/32 */
instr->instr = INSTR_TEST;
if (opcode[0] == 0xF6) {
GET_OP_SIZE_FOR_BYTE(size_reg);
instr->op_size = BYTE;
} else {
GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
size_reg = instr->op_size;
}
instr->operand[0] = mk_operand(size_reg, 0, 0, IMMEDIATE);
instr->immediate = get_immediate(realmode, opcode+1, instr->op_size);
instr->operand[1] = mk_operand(size_reg, 0, 0, MEMORY);
return DECODE_success;
} else
return DECODE_failure;
case 0x0F:
break;
default:
printf("%x, This opcode isn't handled yet!\n", *opcode);
return DECODE_failure;
}
switch (*++opcode) {
case 0xB6: /* movzx m8, r16/r32/r64 */
instr->instr = INSTR_MOVZX;
GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
index = get_index(opcode + 1, rex);
instr->operand[0] = mk_operand(BYTE, 0, 0, MEMORY);
instr->operand[1] = mk_operand(instr->op_size, index, 0, REGISTER);
return DECODE_success;
case 0xB7: /* movzx m16/m32, r32/r64 */
instr->instr = INSTR_MOVZX;
GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
index = get_index(opcode + 1, rex);
if (rex & 0x8)
instr->operand[0] = mk_operand(LONG, 0, 0, MEMORY);
else
instr->operand[0] = mk_operand(WORD, 0, 0, MEMORY);
instr->operand[1] = mk_operand(instr->op_size, index, 0, REGISTER);
return DECODE_success;
case 0xBE: /* movsx m8, r16/r32/r64 */
instr->instr = INSTR_MOVSX;
GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
index = get_index(opcode + 1, rex);
instr->operand[0] = mk_operand(BYTE, 0, 0, MEMORY);
instr->operand[1] = mk_operand(instr->op_size, index, 0, REGISTER);
return DECODE_success;
case 0xBF: /* movsx m16, r32/r64 */
instr->instr = INSTR_MOVSX;
GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
index = get_index(opcode + 1, rex);
instr->operand[0] = mk_operand(WORD, 0, 0, MEMORY);
instr->operand[1] = mk_operand(instr->op_size, index, 0, REGISTER);
return DECODE_success;
case 0xA3: /* bt r32, m32 */
instr->instr = INSTR_BT;
index = get_index(opcode + 1, rex);
instr->op_size = LONG;
instr->operand[0] = mk_operand(instr->op_size, index, 0, REGISTER);
instr->operand[1] = mk_operand(instr->op_size, 0, 0, MEMORY);
return DECODE_success;
default:
printf("0f %x, This opcode isn't handled yet\n", *opcode);
return DECODE_failure;
}
}
int inst_copy_from_guest(unsigned char *buf, unsigned long guest_eip, int inst_len)
{
if (inst_len > MAX_INST_LEN || inst_len <= 0)
return 0;
if (!hvm_copy(buf, guest_eip, inst_len, HVM_COPY_IN))
return 0;
return inst_len;
}
void send_pio_req(struct cpu_user_regs *regs, unsigned long port,
unsigned long count, int size, long value, int dir, int pvalid)
{
struct vcpu *v = current;
vcpu_iodata_t *vio;
ioreq_t *p;
vio = get_vio(v->domain, v->vcpu_id);
if (vio == NULL) {
printk("bad shared page: %lx\n", (unsigned long) vio);
domain_crash_synchronous();
}
if (test_bit(ARCH_HVM_IO_WAIT, &v->arch.hvm_vcpu.ioflags)) {
printf("HVM I/O has not yet completed\n");
domain_crash_synchronous();
}
set_bit(ARCH_HVM_IO_WAIT, &v->arch.hvm_vcpu.ioflags);
p = &vio->vp_ioreq;
p->dir = dir;
p->pdata_valid = pvalid;
p->type = IOREQ_TYPE_PIO;
p->size = size;
p->addr = port;
p->count = count;
p->df = regs->eflags & EF_DF ? 1 : 0;
if (pvalid) {
if (hvm_paging_enabled(current))
p->u.pdata = (void *) gva_to_gpa(value);
else
p->u.pdata = (void *) value; /* guest VA == guest PA */
} else
p->u.data = value;
if (hvm_portio_intercept(p)) {
p->state = STATE_IORESP_READY;
hvm_io_assist(v);
return;
}
p->state = STATE_IOREQ_READY;
evtchn_send(iopacket_port(v->domain));
hvm_wait_io();
}
void send_mmio_req(unsigned char type, unsigned long gpa,
unsigned long count, int size, long value, int dir, int pvalid)
{
struct vcpu *v = current;
vcpu_iodata_t *vio;
ioreq_t *p;
struct cpu_user_regs *regs;
extern long evtchn_send(int lport);
regs = current->arch.hvm_vcpu.mmio_op.inst_decoder_regs;
vio = get_vio(v->domain, v->vcpu_id);
if (vio == NULL) {
printf("bad shared page\n");
domain_crash_synchronous();
}
p = &vio->vp_ioreq;
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->dir = dir;
p->pdata_valid = pvalid;
p->type = type;
p->size = size;
p->addr = gpa;
p->count = count;
p->df = regs->eflags & EF_DF ? 1 : 0;
if (pvalid) {
if (hvm_paging_enabled(v))
p->u.pdata = (void *) gva_to_gpa(value);
else
p->u.pdata = (void *) value; /* guest VA == guest PA */
} else
p->u.data = value;
if (hvm_mmio_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();
}
static void mmio_operands(int type, unsigned long gpa, struct instruction *inst,
struct mmio_op *mmio_opp, struct cpu_user_regs *regs)
{
unsigned long value = 0;
int index, size_reg;
size_reg = operand_size(inst->operand[0]);
mmio_opp->flags = inst->flags;
mmio_opp->instr = inst->instr;
mmio_opp->operand[0] = inst->operand[0]; /* source */
mmio_opp->operand[1] = inst->operand[1]; /* destination */
mmio_opp->immediate = inst->immediate;
if (inst->operand[0] & REGISTER) { /* dest is memory */
index = operand_index(inst->operand[0]);
value = get_reg_value(size_reg, index, 0, regs);
send_mmio_req(type, gpa, 1, inst->op_size, value, IOREQ_WRITE, 0);
} else if (inst->operand[0] & IMMEDIATE) { /* dest is memory */
value = inst->immediate;
send_mmio_req(type, gpa, 1, inst->op_size, value, IOREQ_WRITE, 0);
} else if (inst->operand[0] & MEMORY) { /* dest is register */
/* send the request and wait for the value */
if ( (inst->instr == INSTR_MOVZX) || (inst->instr == INSTR_MOVSX) )
send_mmio_req(type, gpa, 1, size_reg, 0, IOREQ_READ, 0);
else
send_mmio_req(type, gpa, 1, inst->op_size, 0, IOREQ_READ, 0);
} else {
printf("mmio_operands: invalid operand\n");
domain_crash_synchronous();
}
}
#define GET_REPEAT_COUNT() \
(mmio_inst.flags & REPZ ? (realmode ? regs->ecx & 0xFFFF : regs->ecx) : 1)
void handle_mmio(unsigned long va, unsigned long gpa)
{
unsigned long inst_len, inst_addr;
struct mmio_op *mmio_opp;
struct cpu_user_regs *regs;
struct instruction mmio_inst;
unsigned char inst[MAX_INST_LEN];
int i, realmode, ret;
struct vcpu *v = current;
mmio_opp = &v->arch.hvm_vcpu.mmio_op;
regs = mmio_opp->inst_decoder_regs;
hvm_store_cpu_guest_regs(v, regs);
if ((inst_len = hvm_instruction_length(v)) <= 0) {
printf("handle_mmio: failed to get instruction length\n");
domain_crash_synchronous();
}
realmode = hvm_realmode(v);
if (realmode)
inst_addr = (regs->cs << 4) + regs->eip;
else
inst_addr = regs->eip;
memset(inst, 0, MAX_INST_LEN);
ret = inst_copy_from_guest(inst, inst_addr, inst_len);
if (ret != inst_len) {
printf("handle_mmio: failed to copy instruction\n");
domain_crash_synchronous();
}
init_instruction(&mmio_inst);
if (hvm_decode(realmode, inst, &mmio_inst) == DECODE_failure) {
printf("handle_mmio: failed to decode instruction\n");
printf("mmio opcode: va 0x%lx, gpa 0x%lx, len %ld:",
va, gpa, inst_len);
for (i = 0; i < inst_len; i++)
printf(" %02x", inst[i] & 0xFF);
printf("\n");
domain_crash_synchronous();
}
regs->eip += inst_len; /* advance %eip */
switch (mmio_inst.instr) {
case INSTR_MOV:
mmio_operands(IOREQ_TYPE_COPY, gpa, &mmio_inst, mmio_opp, regs);
break;
case INSTR_MOVS:
{
unsigned long count = GET_REPEAT_COUNT();
unsigned long size = mmio_inst.op_size;
int sign = regs->eflags & EF_DF ? -1 : 1;
unsigned long addr = 0;
int dir;
/* determine non-MMIO address */
if (realmode) {
if (((regs->es << 4) + (regs->edi & 0xFFFF)) == va) {
dir = IOREQ_WRITE;
addr = (regs->ds << 4) + (regs->esi & 0xFFFF);
} else {
dir = IOREQ_READ;
addr = (regs->es << 4) + (regs->edi & 0xFFFF);
}
} else {
if (va == regs->edi) {
dir = IOREQ_WRITE;
addr = regs->esi;
} else {
dir = IOREQ_READ;
addr = regs->edi;
}
}
mmio_opp->flags = mmio_inst.flags;
mmio_opp->instr = mmio_inst.instr;
/*
* In case of a movs spanning multiple pages, we break the accesses
* up into multiple pages (the device model works with non-continguous
* physical guest pages). To copy just one page, we adjust %ecx and
* do not advance %eip so that the next "rep movs" copies the next page.
* Unaligned accesses, for example movsl starting at PGSZ-2, are
* turned into a single copy where we handle the overlapping memory
* copy ourself. After this copy succeeds, "rep movs" is executed
* again.
*/
if ((addr & PAGE_MASK) != ((addr + size - 1) & PAGE_MASK)) {
unsigned long value = 0;
mmio_opp->flags |= OVERLAP;
regs->eip -= inst_len; /* do not advance %eip */
if (dir == IOREQ_WRITE)
hvm_copy(&value, addr, size, HVM_COPY_IN);
send_mmio_req(IOREQ_TYPE_COPY, gpa, 1, size, value, dir, 0);
} else {
if ((addr & PAGE_MASK) != ((addr + count * size - 1) & PAGE_MASK)) {
regs->eip -= inst_len; /* do not advance %eip */
if (sign > 0)
count = (PAGE_SIZE - (addr & ~PAGE_MASK)) / size;
else
count = (addr & ~PAGE_MASK) / size;
}
send_mmio_req(IOREQ_TYPE_COPY, gpa, count, size, addr, dir, 1);
}
break;
}
case INSTR_MOVZX:
case INSTR_MOVSX:
mmio_operands(IOREQ_TYPE_COPY, gpa, &mmio_inst, mmio_opp, regs);
break;
case INSTR_STOS:
/*
* Since the destination is always in (contiguous) mmio space we don't
* need to break it up into pages.
*/
mmio_opp->flags = mmio_inst.flags;
mmio_opp->instr = mmio_inst.instr;
send_mmio_req(IOREQ_TYPE_COPY, gpa,
GET_REPEAT_COUNT(), mmio_inst.op_size, regs->eax, IOREQ_WRITE, 0);
break;
case INSTR_OR:
mmio_operands(IOREQ_TYPE_OR, gpa, &mmio_inst, mmio_opp, regs);
break;
case INSTR_AND:
mmio_operands(IOREQ_TYPE_AND, gpa, &mmio_inst, mmio_opp, regs);
break;
case INSTR_XOR:
mmio_operands(IOREQ_TYPE_XOR, gpa, &mmio_inst, mmio_opp, regs);
break;
case INSTR_CMP: /* Pass through */
case INSTR_TEST:
mmio_opp->flags = mmio_inst.flags;
mmio_opp->instr = mmio_inst.instr;
mmio_opp->operand[0] = mmio_inst.operand[0]; /* source */
mmio_opp->operand[1] = mmio_inst.operand[1]; /* destination */
mmio_opp->immediate = mmio_inst.immediate;
/* send the request and wait for the value */
send_mmio_req(IOREQ_TYPE_COPY, gpa, 1,
mmio_inst.op_size, 0, IOREQ_READ, 0);
break;
case INSTR_BT:
{
unsigned long value = 0;
int index, size;
mmio_opp->instr = mmio_inst.instr;
mmio_opp->operand[0] = mmio_inst.operand[0]; /* bit offset */
mmio_opp->operand[1] = mmio_inst.operand[1]; /* bit base */
index = operand_index(mmio_inst.operand[0]);
size = operand_size(mmio_inst.operand[0]);
value = get_reg_value(size, index, 0, regs);
send_mmio_req(IOREQ_TYPE_COPY, gpa + (value >> 5), 1,
mmio_inst.op_size, 0, IOREQ_READ, 0);
break;
}
default:
printf("Unhandled MMIO instruction\n");
domain_crash_synchronous();
}
}
/*
* Local variables:
* mode: C
* c-set-style: "BSD"
* c-basic-offset: 4
* tab-width: 4
* indent-tabs-mode: nil
* End:
*/