[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] merge with xen-unstable.hg
# HG changeset patch # User awilliam@xxxxxxxxxxx # Node ID d603aed5ad6dfc3c318ef2b8bac2f7a427163cb9 # Parent 6fdbf173142d6b4da68d2019f594f9a81fa70d28 # Parent 275a8f9a07109375cd55a2bf90f111ffa09db06d merge with xen-unstable.hg --- xen/arch/x86/hvm/vmx/io.c | 202 - .hgignore | 2 Config.mk | 2 buildconfigs/linux-defconfig_xen0_x86_32 | 1 buildconfigs/linux-defconfig_xen0_x86_64 | 1 buildconfigs/linux-defconfig_xen_x86_32 | 2 buildconfigs/linux-defconfig_xen_x86_64 | 1 docs/xen-api/presentation.tex | 5 docs/xen-api/todo.tex | 2 docs/xen-api/wire-protocol.tex | 66 docs/xen-api/xenapi-datamodel-graph.dot | 3 docs/xen-api/xenapi-datamodel.tex | 320 ++ extras/mini-os/events.c | 27 extras/mini-os/include/events.h | 1 linux-2.6-xen-sparse/arch/i386/Kconfig | 2 linux-2.6-xen-sparse/arch/i386/kernel/setup-xen.c | 27 linux-2.6-xen-sparse/arch/ia64/kernel/setup.c | 10 linux-2.6-xen-sparse/arch/x86_64/Kconfig | 2 linux-2.6-xen-sparse/arch/x86_64/kernel/e820-xen.c | 6 linux-2.6-xen-sparse/arch/x86_64/kernel/setup-xen.c | 23 linux-2.6-xen-sparse/drivers/xen/Kconfig | 23 linux-2.6-xen-sparse/drivers/xen/Makefile | 2 linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c | 3 linux-2.6-xen-sparse/drivers/xen/char/mem.c | 4 linux-2.6-xen-sparse/drivers/xen/console/console.c | 28 linux-2.6-xen-sparse/drivers/xen/core/Makefile | 1 linux-2.6-xen-sparse/drivers/xen/core/machine_kexec.c | 184 + linux-2.6-xen-sparse/drivers/xen/fbfront/Makefile | 2 linux-2.6-xen-sparse/drivers/xen/fbfront/xenfb.c | 682 +++++ linux-2.6-xen-sparse/drivers/xen/fbfront/xenkbd.c | 300 ++ linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypercall.h | 8 linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/agp.h | 35 linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/hypercall.h | 7 linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/ptrace.h | 2 linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/xenoprof.h | 1 linux-2.6-xen-sparse/include/xen/xencons.h | 2 linux-2.6-xen-sparse/mm/memory.c | 1 patches/linux-2.6.16.33/git-2a8a3d5b65e86ec1dfef7d268c64a909eab94af7.patch | 50 patches/linux-2.6.16.33/git-2efe55a9cec8418f0e0cde3dc3787a42fddc4411.patch | 75 patches/linux-2.6.16.33/git-3566561bfadffcb5dbc85d576be80c0dbf2cccc9.patch | 197 + patches/linux-2.6.16.33/git-4bfaaef01a1badb9e8ffb0c0a37cd2379008d21f.patch | 156 + patches/linux-2.6.16.33/git-dbaab49f92ff6ae6255762a948375e4036cbdbd2.patch | 44 patches/linux-2.6.16.33/kexec-generic.patch | 167 + patches/linux-2.6.16.33/linux-2.6.19-rc1-kexec-move_segment_code-i386.patch | 114 patches/linux-2.6.16.33/linux-2.6.19-rc1-kexec-move_segment_code-x86_64.patch | 114 patches/linux-2.6.16.33/linux-2.6.19-rc1-kexec-xen-i386.patch | 49 patches/linux-2.6.16.33/linux-2.6.19-rc1-kexec-xen-x86_64.patch | 88 patches/linux-2.6.16.33/series | 10 tools/Makefile | 1 tools/blktap/drivers/block-aio.c | 8 tools/blktap/drivers/block-qcow.c | 9 tools/blktap/drivers/tapdisk.c | 3 tools/check/Makefile | 6 tools/check/check_libvncserver | 27 tools/check/check_sdl | 27 tools/firmware/vmxassist/setup.c | 22 tools/firmware/vmxassist/trap.S | 16 tools/firmware/vmxassist/util.c | 6 tools/firmware/vmxassist/vm86.c | 21 tools/firmware/vmxassist/vm86.h | 2 tools/ioemu/hw/pci.c | 24 tools/ioemu/hw/usb-uhci.c | 2 tools/ioemu/vl.h | 7 tools/ioemu/vnc.c | 20 tools/libxc/xc_linux.c | 9 tools/libxc/xc_solaris.c | 9 tools/libxc/xenctrl.h | 16 tools/libxen/Makefile | 4 tools/libxen/README | 5 tools/libxen/include/xen_console.h | 207 + tools/libxen/include/xen_console_decl.h | 30 tools/libxen/include/xen_console_protocol.h | 82 tools/libxen/include/xen_console_protocol_internal.h | 37 tools/libxen/include/xen_vm.h | 9 tools/libxen/src/xen_console.c | 207 + tools/libxen/src/xen_console_protocol.c | 82 tools/libxen/src/xen_vm.c | 22 tools/python/scripts/xapi.domcfg.py | 2 tools/python/scripts/xapi.py | 46 tools/python/xen/lowlevel/xc/xc.c | 4 tools/python/xen/util/bugtool.py | 5 tools/python/xen/util/mkdir.py | 44 tools/python/xen/util/xmlrpclib2.py | 13 tools/python/xen/web/unix.py | 12 tools/python/xen/xend/XendAPI.py | 620 ++-- tools/python/xen/xend/XendCheckpoint.py | 4 tools/python/xen/xend/XendConfig.py | 1356 +++++----- tools/python/xen/xend/XendConstants.py | 2 tools/python/xen/xend/XendDevices.py | 4 tools/python/xen/xend/XendDomain.py | 54 tools/python/xen/xend/XendDomainInfo.py | 415 +-- tools/python/xen/xend/XendLogging.py | 5 tools/python/xen/xend/XendStorageRepository.py | 9 tools/python/xen/xend/image.py | 218 - tools/python/xen/xend/server/DevController.py | 7 tools/python/xen/xend/server/SrvDaemon.py | 4 tools/python/xen/xend/server/SrvServer.py | 2 tools/python/xen/xend/server/blkif.py | 21 tools/python/xen/xend/server/iopif.py | 4 tools/python/xen/xend/server/irqif.py | 2 tools/python/xen/xend/server/netif.py | 24 tools/python/xen/xend/server/pciif.py | 69 tools/python/xen/xend/server/pciquirk.py | 43 tools/python/xen/xend/server/tests/test_controllers.py | 6 tools/python/xen/xend/server/tpmif.py | 12 tools/python/xen/xend/server/vfbif.py | 74 tools/python/xen/xm/create.py | 34 tools/python/xen/xm/main.py | 4 tools/tests/test_x86_emulator.c | 108 tools/xenfb/Makefile | 35 tools/xenfb/sdlfb.c | 342 ++ tools/xenfb/vncfb.c | 401 ++ tools/xenfb/xenfb.c | 711 +++++ tools/xenfb/xenfb.h | 35 tools/xm-test/grouptest/xapi | 1 tools/xm-test/lib/XmTestLib/XenManagedDomain.py | 176 + tools/xm-test/lib/XmTestLib/xapi.py | 66 tools/xm-test/tests/vtpm/09_vtpm-xapi.py | 76 tools/xm-test/tests/vtpm/Makefile.am | 3 xen/arch/ia64/xen/Makefile | 2 xen/arch/ia64/xen/crash.c | 19 xen/arch/ia64/xen/machine_kexec.c | 34 xen/arch/powerpc/Makefile | 2 xen/arch/powerpc/crash.c | 19 xen/arch/powerpc/machine_kexec.c | 34 xen/arch/x86/Makefile | 2 xen/arch/x86/crash.c | 128 xen/arch/x86/hvm/platform.c | 18 xen/arch/x86/hvm/svm/emulate.c | 15 xen/arch/x86/hvm/svm/svm.c | 232 + xen/arch/x86/hvm/svm/vmcb.c | 22 xen/arch/x86/hvm/vlapic.c | 11 xen/arch/x86/hvm/vmx/Makefile | 2 xen/arch/x86/hvm/vmx/intr.c | 196 + xen/arch/x86/hvm/vmx/vmx.c | 318 +- xen/arch/x86/machine_kexec.c | 105 xen/arch/x86/mm.c | 98 xen/arch/x86/mm/shadow/common.c | 313 +- xen/arch/x86/mm/shadow/multi.c | 83 xen/arch/x86/mm/shadow/private.h | 19 xen/arch/x86/oprofile/op_model_athlon.c | 9 xen/arch/x86/setup.c | 74 xen/arch/x86/traps.c | 2 xen/arch/x86/x86_32/entry.S | 2 xen/arch/x86/x86_64/entry.S | 2 xen/arch/x86/x86_emulate.c | 558 +--- xen/common/Makefile | 1 xen/common/domain.c | 4 xen/common/kexec.c | 350 ++ xen/common/page_alloc.c | 37 xen/drivers/char/console.c | 3 xen/include/asm-ia64/elf.h | 30 xen/include/asm-ia64/kexec.h | 25 xen/include/asm-ia64/softirq.h | 6 xen/include/asm-powerpc/elf.h | 30 xen/include/asm-powerpc/kexec.h | 25 xen/include/asm-powerpc/softirq.h | 6 xen/include/asm-x86/domain.h | 2 xen/include/asm-x86/elf.h | 24 xen/include/asm-x86/fixmap.h | 4 xen/include/asm-x86/hvm/hvm.h | 71 xen/include/asm-x86/hvm/svm/vmcb.h | 50 xen/include/asm-x86/hvm/vlapic.h | 1 xen/include/asm-x86/hvm/vmx/vmx.h | 7 xen/include/asm-x86/hypercall.h | 5 xen/include/asm-x86/kexec.h | 20 xen/include/asm-x86/shadow.h | 8 xen/include/asm-x86/softirq.h | 6 xen/include/asm-x86/x86_32/elf.h | 72 xen/include/asm-x86/x86_32/kexec.h | 40 xen/include/asm-x86/x86_32/page.h | 2 xen/include/asm-x86/x86_64/elf.h | 92 xen/include/asm-x86/x86_64/kexec.h | 39 xen/include/asm-x86/x86_64/page.h | 2 xen/include/asm-x86/x86_emulate.h | 139 - xen/include/public/elfnote.h | 19 xen/include/public/io/fbif.h | 116 xen/include/public/io/kbdif.h | 108 xen/include/public/kexec.h | 138 + xen/include/xen/elf.h | 20 xen/include/xen/elfcore.h | 140 + xen/include/xen/hypercall.h | 6 xen/include/xen/kexec.h | 45 xen/include/xen/mm.h | 1 xen/include/xen/softirq.h | 13 185 files changed, 10427 insertions(+), 2646 deletions(-) diff -r 6fdbf173142d -r d603aed5ad6d .hgignore --- a/.hgignore Sat Dec 02 15:19:50 2006 -0700 +++ b/.hgignore Mon Dec 04 08:24:41 2006 -0700 @@ -158,6 +158,8 @@ ^tools/xcutils/xc_restore$ ^tools/xcutils/xc_save$ ^tools/xcutils/readnotes$ +^tools/xenfb/sdlfb$ +^tools/xenfb/vncfb$ ^tools/xenmon/xentrace_setmask$ ^tools/xenmon/xenbaked$ ^tools/xenstat/xentop/xentop$ diff -r 6fdbf173142d -r d603aed5ad6d Config.mk --- a/Config.mk Sat Dec 02 15:19:50 2006 -0700 +++ b/Config.mk Mon Dec 04 08:24:41 2006 -0700 @@ -69,8 +69,8 @@ ACM_DEFAULT_SECURITY_POLICY ?= ACM_NULL_ # Optional components XENSTAT_XENTOP ?= y - VTPM_TOOLS ?= n LIBXENAPI_BINDINGS ?= n +XENFB_TOOLS ?= n -include $(XEN_ROOT)/.config diff -r 6fdbf173142d -r d603aed5ad6d buildconfigs/linux-defconfig_xen0_x86_32 --- a/buildconfigs/linux-defconfig_xen0_x86_32 Sat Dec 02 15:19:50 2006 -0700 +++ b/buildconfigs/linux-defconfig_xen0_x86_32 Mon Dec 04 08:24:41 2006 -0700 @@ -179,6 +179,7 @@ CONFIG_HZ_100=y # CONFIG_HZ_250 is not set # CONFIG_HZ_1000 is not set CONFIG_HZ=100 +CONFIG_KEXEC=y # CONFIG_CRASH_DUMP is not set CONFIG_PHYSICAL_START=0x100000 diff -r 6fdbf173142d -r d603aed5ad6d buildconfigs/linux-defconfig_xen0_x86_64 --- a/buildconfigs/linux-defconfig_xen0_x86_64 Sat Dec 02 15:19:50 2006 -0700 +++ b/buildconfigs/linux-defconfig_xen0_x86_64 Mon Dec 04 08:24:41 2006 -0700 @@ -126,6 +126,7 @@ CONFIG_FLAT_NODE_MEM_MAP=y # CONFIG_SPARSEMEM_STATIC is not set CONFIG_SPLIT_PTLOCK_CPUS=4096 CONFIG_SWIOTLB=y +CONFIG_KEXEC=y # CONFIG_CRASH_DUMP is not set CONFIG_PHYSICAL_START=0x100000 CONFIG_SECCOMP=y diff -r 6fdbf173142d -r d603aed5ad6d buildconfigs/linux-defconfig_xen_x86_32 --- a/buildconfigs/linux-defconfig_xen_x86_32 Sat Dec 02 15:19:50 2006 -0700 +++ b/buildconfigs/linux-defconfig_xen_x86_32 Mon Dec 04 08:24:41 2006 -0700 @@ -184,6 +184,7 @@ CONFIG_REGPARM=y CONFIG_REGPARM=y CONFIG_SECCOMP=y CONFIG_HZ_100=y +CONFIG_KEXEC=y # CONFIG_HZ_250 is not set # CONFIG_HZ_1000 is not set CONFIG_HZ=100 @@ -2776,6 +2777,7 @@ CONFIG_NTFS_FS=m # CONFIG_PROC_FS=y CONFIG_PROC_KCORE=y +# CONFIG_PROC_VMCORE is not set CONFIG_SYSFS=y CONFIG_TMPFS=y # CONFIG_HUGETLB_PAGE is not set diff -r 6fdbf173142d -r d603aed5ad6d buildconfigs/linux-defconfig_xen_x86_64 --- a/buildconfigs/linux-defconfig_xen_x86_64 Sat Dec 02 15:19:50 2006 -0700 +++ b/buildconfigs/linux-defconfig_xen_x86_64 Mon Dec 04 08:24:41 2006 -0700 @@ -139,6 +139,7 @@ CONFIG_PHYSICAL_START=0x100000 CONFIG_PHYSICAL_START=0x100000 CONFIG_SECCOMP=y CONFIG_HZ_100=y +CONFIG_KEXEC=y # CONFIG_HZ_250 is not set # CONFIG_HZ_1000 is not set CONFIG_HZ=100 diff -r 6fdbf173142d -r d603aed5ad6d docs/xen-api/presentation.tex --- a/docs/xen-api/presentation.tex Sat Dec 02 15:19:50 2006 -0700 +++ b/docs/xen-api/presentation.tex Mon Dec 04 08:24:41 2006 -0700 @@ -131,9 +131,6 @@ of that class that has the specified {\t ``{\tt get\_by\_name\_label(name)}'' RPC that returns a set of objects of that class that have the specified {\tt label}. -\item Each class has a ``{\tt to\_XML()}'' RPC that serialises the -state of all fields as an XML string. - \item Each class has a ``{\tt destroy(Ref x)}'' RPC that explicitly deletes the persistent object specified by {\tt x} from the system. This is a non-cascading delete -- if the object being removed is referenced by another @@ -144,6 +141,6 @@ object then the {\tt destroy} call will \subsection{Additional RPCs} As well as the RPCs enumerated above, some classes have additional RPCs -associated with them. For example, the {\tt VM} class have RPCs for cloning, +associated with them. For example, the {\tt VM} class has RPCs for cloning, suspending, starting etc. Such additional RPCs are described explicitly in the API reference. diff -r 6fdbf173142d -r d603aed5ad6d docs/xen-api/todo.tex --- a/docs/xen-api/todo.tex Sat Dec 02 15:19:50 2006 -0700 +++ b/docs/xen-api/todo.tex Mon Dec 04 08:24:41 2006 -0700 @@ -34,6 +34,8 @@ code, potential error description, but o \item Clarify behaviour of progress field on asyncrhonous request polling when that request fails. + +\item Clarify which calls have asynchronous counterparts by marking them as such in the reference. (Individual getters and setters are too small and quick to justify having async versions) \end{itemize} diff -r 6fdbf173142d -r d603aed5ad6d docs/xen-api/wire-protocol.tex --- a/docs/xen-api/wire-protocol.tex Sat Dec 02 15:19:50 2006 -0700 +++ b/docs/xen-api/wire-protocol.tex Mon Dec 04 08:24:41 2006 -0700 @@ -21,9 +21,9 @@ In our API Reference we specify the sign In our API Reference we specify the signatures of API functions in the following style: \begin{verbatim} - (ref_vm Set) Host.ListAllVMs() -\end{verbatim} -This specifies that the function with name {\tt Host.ListAllVMs} takes + (ref_vm Set) VM.get_all() +\end{verbatim} +This specifies that the function with name {\tt VM.get\_all} takes no parameters and returns a Set of {\tt ref\_vm}s. These types are mapped onto XML-RPC types in a straight-forward manner: \begin{itemize} @@ -105,8 +105,8 @@ the struct contains a second element nam the struct contains a second element named {\tt ErrorDescription}: \begin{itemize} \item The element of the struct named {\tt ErrorDescription} contains -an array of string values. The first element of the array represents an error code; -the remainder of the array represents error parameters relating to that code. +an array of string values. The first element of the array is an XML-RPC 32-bit {\tt i4} and represents an error code; +the remainder of the array are strings representing error parameters relating to that code. \end{itemize} For example, an XML-RPC return value from the {\tt Host.ListAllVMs} function above @@ -161,19 +161,19 @@ A session can be terminated with the {\t \subsection{Synchronous and Asynchronous invocation} -Each method call (apart from those on ``Session'' and ``Task'' objects) +Each method call (apart from methods on ``Session'' and ``Task'' objects +and ``getters'' and ``setters'' derived from fields) can be made either synchronously or asynchronously. A synchronous RPC call blocks until the return value is received; the return value of a synchronous RPC call is exactly as specified in Section~\ref{synchronous-result}. -Each of the methods specified in the API Reference is synchronous. -However, although not listed explicitly in this document, each -method call has an asynchronous analogue in the {\tt Async} -namespace. For example, synchronous call {\tt VM.Install(...)} +Only synchronous API calls are listed explicitly in this document. +All asynchronous versions are in the special {\tt Async} namespace. +For example, synchronous call {\tt VM.clone(...)} (described in Chapter~\ref{api-reference}) has an asynchronous counterpart, {\tt -Async.VM.Install(...)}, that is non-blocking. +Async.VM.clone(...)}, that is non-blocking. Instead of returning its result directly, an asynchronous RPC call returns a {\tt task-id}; this identifier is subsequently used @@ -186,39 +186,14 @@ The {\tt task-id} is provided in the {\t The {\tt task-id} is provided in the {\tt Value} field if {\tt Status} is set to {\tt Success}. -Two special RPC calls are provided to poll the status of -asynchronous calls: -\begin{verbatim} - Array<task_id> Async.Task.GetAllTasks (session_id s) - task_status Async.Task.GetStatus (session_id s, task_id t) -\end{verbatim} - -{\tt Async.Task.GetAllTasks} returns a set of the currently -executing asynchronous tasks belong to the current user\footnote{ -% -The current user is determined by the username that was provided -to {\tt Session.Login}. -% -}. - -{\tt Async.Task.GetStatus} returns a {\tt task\_status} result. -This is an XML-RPC struct with three elements: -\begin{itemize} - \item The first element is named {\tt Progress} and contains -an {\tt Integer} between 0 and 100 representing the estimated percentage of -the task currently completed. - \item The second element is named {\tt ETA} and contains a {\tt DateTime} -representing the estimated time the task will be complete. - \item The third element is named {\tt Result}. If {\tt Progress} -is not 100 then {\tt Result} contains the empty string. If {\tt Progress} -{\em is\/} set to 100, then {\tt Result} contains the function's return -result (as specified in Section~\ref{synchronous-result})\footnote{ -% -Recall that this itself is a struct potentially containing status, errorcode, -value fields etc. -% -}. -\end{itemize} +The RPC call +\begin{verbatim} + (ref_task Set) Task.get_all(session_id s) +\end{verbatim} +returns a set of all task IDs known to the system. The status (including any +returned result and error codes) of these tasks +can then be queried by accessing the fields of the Task object in the usual way. +Note that, in order to get a consistent snapshot of a task's state, it is advisable to call the ``get\_record'' function. \section{Example interactive session} @@ -267,7 +242,8 @@ Next, the user may acquire a list of all \begin{verbatim} >>> all_vms = xen.VM.do_list(session)['Value'] >>> all_vms -['b7b92d9e-d442-4710-92a5-ab039fd7d89b', '23e1e837-abbf-4675-b077-d4007989b0cc', '2045dbc0-0734-4eea-9cb2-b8218c6b5bf2', '3202ae18-a046-4c32-9fda-e32e9631866e'] +['b7b92d9e-d442-4710-92a5-ab039fd7d89b', '23e1e837-abbf-4675-b077-d4007989b0cc', + '2045dbc0-0734-4eea-9cb2-b8218c6b5bf2', '3202ae18-a046-4c32-9fda-e32e9631866e'] \end{verbatim} Note the VM references are internally UUIDs. Once a reference to a VM has been acquired a lifecycle operation may be invoked: diff -r 6fdbf173142d -r d603aed5ad6d docs/xen-api/xenapi-datamodel-graph.dot --- a/docs/xen-api/xenapi-datamodel-graph.dot Sat Dec 02 15:19:50 2006 -0700 +++ b/docs/xen-api/xenapi-datamodel-graph.dot Mon Dec 04 08:24:41 2006 -0700 @@ -1,5 +1,5 @@ digraph g{ digraph g{ -node [ shape=box ]; session [ URL="session.html" ] task [ URL="task.html" ] VM [ URL="VM.html" ] host [ URL="host.html" ] host_cpu [ URL="host_cpu.html" ] network [ URL="network.html" ] VIF [ URL="VIF.html" ] PIF [ URL="PIF.html" ] SR [ URL="SR.html" ] VDI [ URL="VDI.html" ] VBD [ URL="VBD.html" ] VTPM [ URL="VTPM.html" ] user [ URL="user.html" ] debug [ URL="debug.html" ]; +node [ shape=box ]; session [ URL="session.html" ] task [ URL="task.html" ] VM [ URL="VM.html" ] host [ URL="host.html" ] host_cpu [ URL="host_cpu.html" ] network [ URL="network.html" ] VIF [ URL="VIF.html" ] PIF [ URL="PIF.html" ] SR [ URL="SR.html" ] VDI [ URL="VDI.html" ] VBD [ URL="VBD.html" ] VTPM [ URL="VTPM.html" ] console [ URL="console.html" ] user [ URL="user.html" ] debug [ URL="debug.html" ]; session -> host [ label="this_host(1)" ] session -> user [ label="this_user(1)" ] host -> VM [ color="blue", arrowhead="crow", arrowtail="none" ] @@ -14,4 +14,5 @@ VBD -> VM [ color="blue", arrowhead="non VBD -> VM [ color="blue", arrowhead="none", arrowtail="crow" ] VTPM -> VM [ label="backend(1)" ] VTPM -> VM [ color="blue", arrowhead="none", arrowtail="crow" ] +console -> VM [ color="blue", arrowhead="none", arrowtail="crow" ] } diff -r 6fdbf173142d -r d603aed5ad6d docs/xen-api/xenapi-datamodel.tex --- a/docs/xen-api/xenapi-datamodel.tex Sat Dec 02 15:19:50 2006 -0700 +++ b/docs/xen-api/xenapi-datamodel.tex Mon Dec 04 08:24:41 2006 -0700 @@ -34,6 +34,7 @@ Name & Description \\ {\tt VDI} & A virtual disk image \\ {\tt VBD} & A virtual block device \\ {\tt VTPM} & A virtual TPM device \\ +{\tt console} & A console \\ {\tt user} & A user of the system \\ {\tt debug} & A basic class for testing \\ \hline @@ -54,6 +55,7 @@ PIF.network & network.PIFs & one-to-many PIF.network & network.PIFs & one-to-many\\ SR.VDIs & VDI.SR & many-to-one\\ VTPM.VM & VM.VTPMs & one-to-many\\ +console.VM & VM.consoles & one-to-many\\ host.resident\_VMs & VM.resident\_on & many-to-one\\ host.host\_CPUs & host\_cpu.host & many-to-one\\ \hline @@ -96,6 +98,16 @@ Map (a $\rightarrow$ b) & a table mappin \end{tabular}\end{center} \subsection{Enumeration types} The following enumeration types are used: + +\begin{longtable}{|ll|} +\hline +{\tt enum console\_protocol} & \\ +\hline +\hspace{0.5cm}{\tt vt100} & VT100 terminal \\ +\hspace{0.5cm}{\tt rfb} & Remote FrameBuffer protocol (as used in VNC) \\ +\hspace{0.5cm}{\tt rdp} & Remote Desktop Protocol \\ +\hline +\end{longtable} \begin{longtable}{|ll|} \hline @@ -947,6 +959,7 @@ Quals & Field & Type & Description \\ $\mathit{RW}$ & {\tt actions/after\_reboot} & on\_normal\_exit & action to take after the guest has rebooted itself \\ $\mathit{RW}$ & {\tt actions/after\_suspend} & on\_normal\_exit & action to take after the guest has suspended itself \\ $\mathit{RW}$ & {\tt actions/after\_crash} & on\_crash\_behaviour & action to take if the guest crashes \\ +$\mathit{RO}_\mathit{run}$ & {\tt consoles} & (console ref) Set & virtual console devices \\ $\mathit{RO}_\mathit{run}$ & {\tt VIFs} & (VIF ref) Set & virtual network interfaces \\ $\mathit{RO}_\mathit{run}$ & {\tt VBDs} & (VBD ref) Set & virtual block devices \\ $\mathit{RO}_\mathit{run}$ & {\tt VTPMs} & (VTPM ref) Set & virtual TPMs \\ @@ -2628,6 +2641,38 @@ void +\vspace{0.3cm} +\vspace{0.3cm} +\vspace{0.3cm} +\subsubsection{RPC name:~get\_consoles} + +{\bf Overview:} +Get the consoles field of the given VM. + + \noindent {\bf Signature:} +\begin{verbatim} ((console ref) Set) get_consoles (session_id s, VM ref self)\end{verbatim} + + +\noindent{\bf Arguments:} + + +\vspace{0.3cm} +\begin{tabular}{|c|c|p{7cm}|} + \hline +{\bf type} & {\bf name} & {\bf description} \\ \hline +{\tt VM ref } & self & object instance \\ \hline + +\end{tabular} + +\vspace{0.3cm} + + \noindent {\bf Return Type:} +{\tt +(console ref) Set +} + + +value of the field \vspace{0.3cm} \vspace{0.3cm} \vspace{0.3cm} @@ -9187,6 +9232,281 @@ all fields from the object \vspace{1cm} \newpage +\section{Class: console} +\subsection{Fields for class: console} +\begin{longtable}{|lllp{0.38\textwidth}|} +\hline +\multicolumn{1}{|l}{Name} & \multicolumn{3}{l|}{\bf console} \\ +\multicolumn{1}{|l}{Description} & \multicolumn{3}{l|}{\parbox{11cm}{\em A console}} \\ +\hline +Quals & Field & Type & Description \\ +\hline +$\mathit{RO}_\mathit{run}$ & {\tt uuid} & string & unique identifier/object reference \\ +$\mathit{RO}_\mathit{run}$ & {\tt protocol} & console\_protocol & the protocol used by this console \\ +$\mathit{RO}_\mathit{run}$ & {\tt uri} & string & URI for the console service \\ +$\mathit{RO}_\mathit{run}$ & {\tt VM} & VM ref & VM to which this console is attached \\ +\hline +\end{longtable} +\subsection{Additional RPCs associated with class: console} +\subsubsection{RPC name:~get\_record} + +{\bf Overview:} +Get the current state of the given console. + + \noindent {\bf Signature:} +\begin{verbatim} (console record) get_record (session_id s, console ref self)\end{verbatim} + + +\noindent{\bf Arguments:} + + +\vspace{0.3cm} +\begin{tabular}{|c|c|p{7cm}|} + \hline +{\bf type} & {\bf name} & {\bf description} \\ \hline +{\tt console ref } & self & reference to the object \\ \hline + +\end{tabular} + +\vspace{0.3cm} + + \noindent {\bf Return Type:} +{\tt +console record +} + + +all fields from the object +\vspace{0.3cm} +\vspace{0.3cm} +\vspace{0.3cm} +\subsubsection{RPC name:~get\_by\_uuid} + +{\bf Overview:} +Get a reference to the object with the specified UUID. + + \noindent {\bf Signature:} +\begin{verbatim} (console ref) get_by_uuid (session_id s, string uuid)\end{verbatim} + + +\noindent{\bf Arguments:} + + +\vspace{0.3cm} +\begin{tabular}{|c|c|p{7cm}|} + \hline +{\bf type} & {\bf name} & {\bf description} \\ \hline +{\tt string } & uuid & UUID of object to return \\ \hline + +\end{tabular} + +\vspace{0.3cm} + + \noindent {\bf Return Type:} +{\tt +console ref +} + + +reference to the object +\vspace{0.3cm} +\vspace{0.3cm} +\vspace{0.3cm} +\subsubsection{RPC name:~create} + +{\bf Overview:} +Create a new console instance, and return its handle. + + \noindent {\bf Signature:} +\begin{verbatim} (console ref) create (session_id s, console record args)\end{verbatim} + + +\noindent{\bf Arguments:} + + +\vspace{0.3cm} +\begin{tabular}{|c|c|p{7cm}|} + \hline +{\bf type} & {\bf name} & {\bf description} \\ \hline +{\tt console record } & args & All constructor arguments \\ \hline + +\end{tabular} + +\vspace{0.3cm} + + \noindent {\bf Return Type:} +{\tt +console ref +} + + +reference to the newly created object +\vspace{0.3cm} +\vspace{0.3cm} +\vspace{0.3cm} +\subsubsection{RPC name:~destroy} + +{\bf Overview:} +Destroy the specified console instance. + + \noindent {\bf Signature:} +\begin{verbatim} void destroy (session_id s, console ref self)\end{verbatim} + + +\noindent{\bf Arguments:} + + +\vspace{0.3cm} +\begin{tabular}{|c|c|p{7cm}|} + \hline +{\bf type} & {\bf name} & {\bf description} \\ \hline +{\tt console ref } & self & object instance \\ \hline + +\end{tabular} + +\vspace{0.3cm} + + \noindent {\bf Return Type:} +{\tt +void +} + + + +\vspace{0.3cm} +\vspace{0.3cm} +\vspace{0.3cm} +\subsubsection{RPC name:~get\_uuid} + +{\bf Overview:} +Get the uuid field of the given console. + + \noindent {\bf Signature:} +\begin{verbatim} string get_uuid (session_id s, console ref self)\end{verbatim} + + +\noindent{\bf Arguments:} + + +\vspace{0.3cm} +\begin{tabular}{|c|c|p{7cm}|} + \hline +{\bf type} & {\bf name} & {\bf description} \\ \hline +{\tt console ref } & self & object instance \\ \hline + +\end{tabular} + +\vspace{0.3cm} + + \noindent {\bf Return Type:} +{\tt +string +} + + +value of the field +\vspace{0.3cm} +\vspace{0.3cm} +\vspace{0.3cm} +\subsubsection{RPC name:~get\_protocol} + +{\bf Overview:} +Get the protocol field of the given console. + + \noindent {\bf Signature:} +\begin{verbatim} (console_protocol) get_protocol (session_id s, console ref self)\end{verbatim} + + +\noindent{\bf Arguments:} + + +\vspace{0.3cm} +\begin{tabular}{|c|c|p{7cm}|} + \hline +{\bf type} & {\bf name} & {\bf description} \\ \hline +{\tt console ref } & self & object instance \\ \hline + +\end{tabular} + +\vspace{0.3cm} + + \noindent {\bf Return Type:} +{\tt +console\_protocol +} + + +value of the field +\vspace{0.3cm} +\vspace{0.3cm} +\vspace{0.3cm} +\subsubsection{RPC name:~get\_uri} + +{\bf Overview:} +Get the uri field of the given console. + + \noindent {\bf Signature:} +\begin{verbatim} string get_uri (session_id s, console ref self)\end{verbatim} + + +\noindent{\bf Arguments:} + + +\vspace{0.3cm} +\begin{tabular}{|c|c|p{7cm}|} + \hline +{\bf type} & {\bf name} & {\bf description} \\ \hline +{\tt console ref } & self & object instance \\ \hline + +\end{tabular} + +\vspace{0.3cm} + + \noindent {\bf Return Type:} +{\tt +string +} + + +value of the field +\vspace{0.3cm} +\vspace{0.3cm} +\vspace{0.3cm} +\subsubsection{RPC name:~get\_VM} + +{\bf Overview:} +Get the VM field of the given console. + + \noindent {\bf Signature:} +\begin{verbatim} (VM ref) get_VM (session_id s, console ref self)\end{verbatim} + + +\noindent{\bf Arguments:} + + +\vspace{0.3cm} +\begin{tabular}{|c|c|p{7cm}|} + \hline +{\bf type} & {\bf name} & {\bf description} \\ \hline +{\tt console ref } & self & object instance \\ \hline + +\end{tabular} + +\vspace{0.3cm} + + \noindent {\bf Return Type:} +{\tt +VM ref +} + + +value of the field +\vspace{0.3cm} +\vspace{0.3cm} +\vspace{0.3cm} + +\vspace{1cm} +\newpage \section{Class: user} \subsection{Fields for class: user} \begin{longtable}{|lllp{0.38\textwidth}|} diff -r 6fdbf173142d -r d603aed5ad6d extras/mini-os/events.c --- a/extras/mini-os/events.c Sat Dec 02 15:19:50 2006 -0700 +++ b/extras/mini-os/events.c Mon Dec 04 08:24:41 2006 -0700 @@ -31,26 +31,27 @@ typedef struct _ev_action_t { u32 count; } ev_action_t; - static ev_action_t ev_actions[NR_EVS]; void default_handler(evtchn_port_t port, struct pt_regs *regs, void *data); + +static unsigned long bound_ports[NR_EVS/(8*sizeof(unsigned long))]; void unbind_all_ports(void) { int i; - for(i=0;i<NR_EVS;i++) - { - if(ev_actions[i].handler != default_handler) - { - struct evtchn_close close; - mask_evtchn(i); - close.port = i; - HYPERVISOR_event_channel_op(EVTCHNOP_close, &close); - } - } + for (i = 0; i < NR_EVS; i++) + { + if (test_and_clear_bit(i, bound_ports)) + { + struct evtchn_close close; + mask_evtchn(i); + close.port = i; + HYPERVISOR_event_channel_op(EVTCHNOP_close, &close); + } + } } - + /* * Demux events to different handlers. */ @@ -114,6 +115,7 @@ int bind_virq(uint32_t virq, evtchn_hand printk("Failed to bind virtual IRQ %d\n", virq); return 1; } + set_bit(op.port,bound_ports); bind_evtchn(op.port, handler, data); return 0; } @@ -188,6 +190,7 @@ int evtchn_bind_interdomain(domid_t pal, int err = HYPERVISOR_event_channel_op(EVTCHNOP_bind_interdomain, &op); if (err) return err; + set_bit(op.local_port,bound_ports); evtchn_port_t port = op.local_port; clear_evtchn(port); /* Without, handler gets invoked now! */ *local_port = bind_evtchn(port, handler, data); diff -r 6fdbf173142d -r d603aed5ad6d extras/mini-os/include/events.h --- a/extras/mini-os/include/events.h Sat Dec 02 15:19:50 2006 -0700 +++ b/extras/mini-os/include/events.h Mon Dec 04 08:24:41 2006 -0700 @@ -36,6 +36,7 @@ int evtchn_bind_interdomain(domid_t pal, int evtchn_bind_interdomain(domid_t pal, evtchn_port_t remote_port, evtchn_handler_t handler, void *data, evtchn_port_t *local_port); +void unbind_all_ports(void); static inline int notify_remote_via_evtchn(evtchn_port_t port) { diff -r 6fdbf173142d -r d603aed5ad6d linux-2.6-xen-sparse/arch/i386/Kconfig --- a/linux-2.6-xen-sparse/arch/i386/Kconfig Sat Dec 02 15:19:50 2006 -0700 +++ b/linux-2.6-xen-sparse/arch/i386/Kconfig Mon Dec 04 08:24:41 2006 -0700 @@ -726,7 +726,7 @@ source kernel/Kconfig.hz config KEXEC bool "kexec system call (EXPERIMENTAL)" - depends on EXPERIMENTAL && !X86_XEN + depends on EXPERIMENTAL && !XEN_UNPRIVILEGED_GUEST help kexec is a system call that implements the ability to shutdown your current kernel, and to start another kernel. It is like a reboot diff -r 6fdbf173142d -r d603aed5ad6d linux-2.6-xen-sparse/arch/i386/kernel/setup-xen.c --- a/linux-2.6-xen-sparse/arch/i386/kernel/setup-xen.c Sat Dec 02 15:19:50 2006 -0700 +++ b/linux-2.6-xen-sparse/arch/i386/kernel/setup-xen.c Mon Dec 04 08:24:41 2006 -0700 @@ -68,6 +68,10 @@ #include <xen/xencons.h> #include "setup_arch_pre.h" #include <bios_ebda.h> + +#ifdef CONFIG_XEN +#include <xen/interface/kexec.h> +#endif /* Forward Declaration. */ void __init find_max_pfn(void); @@ -943,6 +947,7 @@ static void __init parse_cmdline_early ( * after a kernel panic. */ else if (!memcmp(from, "crashkernel=", 12)) { +#ifndef CONFIG_XEN unsigned long size, base; size = memparse(from+12, &from); if (*from == '@') { @@ -953,6 +958,10 @@ static void __init parse_cmdline_early ( crashk_res.start = base; crashk_res.end = base + size - 1; } +#else + printk("Ignoring crashkernel command line, " + "parameter will be supplied by xen\n"); +#endif } #endif #ifdef CONFIG_PROC_VMCORE @@ -1322,9 +1331,13 @@ void __init setup_bootmem_allocator(void } #endif #ifdef CONFIG_KEXEC +#ifdef CONFIG_XEN + xen_machine_kexec_setup_resources(); +#else if (crashk_res.start != crashk_res.end) reserve_bootmem(crashk_res.start, crashk_res.end - crashk_res.start + 1); +#endif #endif if (!xen_feature(XENFEAT_auto_translated_physmap)) @@ -1389,7 +1402,11 @@ legacy_init_iomem_resources(struct e820e request_resource(res, data_resource); #endif #ifdef CONFIG_KEXEC - request_resource(res, &crashk_res); + if (crashk_res.start != crashk_res.end) + request_resource(res, &crashk_res); +#ifdef CONFIG_XEN + xen_machine_kexec_register_resources(res); +#endif #endif } } @@ -1850,9 +1867,11 @@ void __init setup_arch(char **cmdline_p) #endif #endif } else { - extern int console_use_vt; - console_use_vt = 0; - } +#if defined(CONFIG_VT) && defined(CONFIG_DUMMY_CONSOLE) + conswitchp = &dummy_con; +#endif + } + xencons_early_setup(); } static int diff -r 6fdbf173142d -r d603aed5ad6d linux-2.6-xen-sparse/arch/ia64/kernel/setup.c --- a/linux-2.6-xen-sparse/arch/ia64/kernel/setup.c Sat Dec 02 15:19:50 2006 -0700 +++ b/linux-2.6-xen-sparse/arch/ia64/kernel/setup.c Mon Dec 04 08:24:41 2006 -0700 @@ -550,13 +550,15 @@ setup_arch (char **cmdline_p) xen_start_info->nr_pages, xen_start_info->flags); if (!is_initial_xendomain()) { - extern int console_use_vt; +#if !defined(CONFIG_VT) || !defined(CONFIG_DUMMY_CONSOLE) conswitchp = NULL; - console_use_vt = 0; +#endif } } -#endif -#endif + xencons_early_setup(); +#endif +#endif + /* enable IA-64 Machine Check Abort Handling unless disabled */ if (!strstr(saved_command_line, "nomca")) diff -r 6fdbf173142d -r d603aed5ad6d linux-2.6-xen-sparse/arch/x86_64/Kconfig --- a/linux-2.6-xen-sparse/arch/x86_64/Kconfig Sat Dec 02 15:19:50 2006 -0700 +++ b/linux-2.6-xen-sparse/arch/x86_64/Kconfig Mon Dec 04 08:24:41 2006 -0700 @@ -435,7 +435,7 @@ config X86_MCE_AMD config KEXEC bool "kexec system call (EXPERIMENTAL)" - depends on EXPERIMENTAL && !X86_64_XEN + depends on EXPERIMENTAL && !XEN_UNPRIVILEGED_GUEST help kexec is a system call that implements the ability to shutdown your current kernel, and to start another kernel. It is like a reboot diff -r 6fdbf173142d -r d603aed5ad6d linux-2.6-xen-sparse/arch/x86_64/kernel/e820-xen.c --- a/linux-2.6-xen-sparse/arch/x86_64/kernel/e820-xen.c Sat Dec 02 15:19:50 2006 -0700 +++ b/linux-2.6-xen-sparse/arch/x86_64/kernel/e820-xen.c Mon Dec 04 08:24:41 2006 -0700 @@ -260,7 +260,11 @@ void __init e820_reserve_resources(struc request_resource(res, &data_resource); #endif #ifdef CONFIG_KEXEC - request_resource(res, &crashk_res); + if (crashk_res.start != crashk_res.end) + request_resource(res, &crashk_res); +#ifdef CONFIG_XEN + xen_machine_kexec_register_resources(res); +#endif #endif } } diff -r 6fdbf173142d -r d603aed5ad6d linux-2.6-xen-sparse/arch/x86_64/kernel/setup-xen.c --- a/linux-2.6-xen-sparse/arch/x86_64/kernel/setup-xen.c Sat Dec 02 15:19:50 2006 -0700 +++ b/linux-2.6-xen-sparse/arch/x86_64/kernel/setup-xen.c Mon Dec 04 08:24:41 2006 -0700 @@ -80,6 +80,10 @@ #include <asm/mach-xen/setup_arch_post.h> #include <xen/interface/memory.h> +#ifdef CONFIG_XEN +#include <xen/interface/kexec.h> +#endif + extern unsigned long start_pfn; extern struct edid_info edid_info; @@ -450,6 +454,7 @@ static __init void parse_cmdline_early ( * after a kernel panic. */ else if (!memcmp(from, "crashkernel=", 12)) { +#ifndef CONFIG_XEN unsigned long size, base; size = memparse(from+12, &from); if (*from == '@') { @@ -460,6 +465,10 @@ static __init void parse_cmdline_early ( crashk_res.start = base; crashk_res.end = base + size - 1; } +#else + printk("Ignoring crashkernel command line, " + "parameter will be supplied by xen\n"); +#endif } #endif @@ -812,10 +821,14 @@ void __init setup_arch(char **cmdline_p) #endif #endif /* !CONFIG_XEN */ #ifdef CONFIG_KEXEC +#ifdef CONFIG_XEN + xen_machine_kexec_setup_resources(); +#else if (crashk_res.start != crashk_res.end) { reserve_bootmem(crashk_res.start, crashk_res.end - crashk_res.start + 1); } +#endif #endif paging_init(); @@ -970,10 +983,12 @@ void __init setup_arch(char **cmdline_p) #endif #endif } else { - extern int console_use_vt; - console_use_vt = 0; - } - } +#if defined(CONFIG_VT) && defined(CONFIG_DUMMY_CONSOLE) + conswitchp = &dummy_con; +#endif + } + } + xencons_early_setup(); #else /* CONFIG_XEN */ #ifdef CONFIG_VT diff -r 6fdbf173142d -r d603aed5ad6d linux-2.6-xen-sparse/drivers/xen/Kconfig --- a/linux-2.6-xen-sparse/drivers/xen/Kconfig Sat Dec 02 15:19:50 2006 -0700 +++ b/linux-2.6-xen-sparse/drivers/xen/Kconfig Mon Dec 04 08:24:41 2006 -0700 @@ -172,6 +172,29 @@ config XEN_NETDEV_FRONTEND dedicated device-driver domain, or your master control domain (domain 0), then you almost certainly want to say Y here. +config XEN_FRAMEBUFFER + tristate "Framebuffer-device frontend driver" + depends on XEN && FB + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + default y + help + The framebuffer-device frontend drivers allows the kernel to create a + virtual framebuffer. This framebuffer can be viewed in another + domain. Unless this domain has access to a real video card, you + probably want to say Y here. + +config XEN_KEYBOARD + tristate "Keyboard-device frontend driver" + depends on XEN && XEN_FRAMEBUFFER && INPUT + default y + help + The keyboard-device frontend driver allows the kernel to create a + virtual keyboard. This keyboard can then be driven by another + domain. If you've said Y to CONFIG_XEN_FRAMEBUFFER, you probably + want to say Y here. + config XEN_SCRUB_PAGES bool "Scrub memory before freeing it to Xen" default y diff -r 6fdbf173142d -r d603aed5ad6d linux-2.6-xen-sparse/drivers/xen/Makefile --- a/linux-2.6-xen-sparse/drivers/xen/Makefile Sat Dec 02 15:19:50 2006 -0700 +++ b/linux-2.6-xen-sparse/drivers/xen/Makefile Mon Dec 04 08:24:41 2006 -0700 @@ -15,3 +15,5 @@ obj-$(CONFIG_XEN_NETDEV_FRONTEND) += net obj-$(CONFIG_XEN_NETDEV_FRONTEND) += netfront/ obj-$(CONFIG_XEN_PCIDEV_BACKEND) += pciback/ obj-$(CONFIG_XEN_PCIDEV_FRONTEND) += pcifront/ +obj-$(CONFIG_XEN_FRAMEBUFFER) += fbfront/ +obj-$(CONFIG_XEN_KEYBOARD) += fbfront/ diff -r 6fdbf173142d -r d603aed5ad6d linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c --- a/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c Sat Dec 02 15:19:50 2006 -0700 +++ b/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c Mon Dec 04 08:24:41 2006 -0700 @@ -359,7 +359,7 @@ static void blkfront_closing(struct xenb DPRINTK("blkfront_closing: %s removed\n", dev->nodename); if (info->rq == NULL) - return; + goto out; spin_lock_irqsave(&blkif_io_lock, flags); /* No more blkif_request(). */ @@ -373,6 +373,7 @@ static void blkfront_closing(struct xenb xlvbd_del(info); + out: xenbus_frontend_closed(dev); } diff -r 6fdbf173142d -r d603aed5ad6d linux-2.6-xen-sparse/drivers/xen/char/mem.c --- a/linux-2.6-xen-sparse/drivers/xen/char/mem.c Sat Dec 02 15:19:50 2006 -0700 +++ b/linux-2.6-xen-sparse/drivers/xen/char/mem.c Mon Dec 04 08:24:41 2006 -0700 @@ -147,7 +147,7 @@ static inline int uncached_access(struct return 0; } -static int mmap_mem(struct file * file, struct vm_area_struct * vma) +static int xen_mmap_mem(struct file * file, struct vm_area_struct * vma) { size_t size = vma->vm_end - vma->vm_start; @@ -200,6 +200,6 @@ struct file_operations mem_fops = { .llseek = memory_lseek, .read = read_mem, .write = write_mem, - .mmap = mmap_mem, + .mmap = xen_mmap_mem, .open = open_mem, }; diff -r 6fdbf173142d -r d603aed5ad6d linux-2.6-xen-sparse/drivers/xen/console/console.c --- a/linux-2.6-xen-sparse/drivers/xen/console/console.c Sat Dec 02 15:19:50 2006 -0700 +++ b/linux-2.6-xen-sparse/drivers/xen/console/console.c Mon Dec 04 08:24:41 2006 -0700 @@ -57,6 +57,7 @@ #include <xen/interface/event_channel.h> #include <asm/hypervisor.h> #include <xen/evtchn.h> +#include <xen/xenbus.h> #include <xen/xencons.h> /* @@ -65,14 +66,14 @@ * 'xencons=tty' [XC_TTY]: Console attached to '/dev/tty[0-9]+'. * 'xencons=ttyS' [XC_SERIAL]: Console attached to '/dev/ttyS[0-9]+'. * 'xencons=xvc' [XC_XVC]: Console attached to '/dev/xvc0'. - * [XC_DEFAULT]: DOM0 -> XC_SERIAL ; all others -> XC_TTY. + * default: DOM0 -> XC_SERIAL ; all others -> XC_TTY. * * NB. In mode XC_TTY, we create dummy consoles for tty2-63. This suppresses * warnings from standard distro startup scripts. */ static enum { - XC_OFF, XC_DEFAULT, XC_TTY, XC_SERIAL, XC_XVC -} xc_mode = XC_DEFAULT; + XC_OFF, XC_TTY, XC_SERIAL, XC_XVC +} xc_mode; static int xc_num = -1; /* /dev/xvc0 device number allocated by lanana.org. */ @@ -84,17 +85,32 @@ extern int sysrq_enabled; extern int sysrq_enabled; #endif +void xencons_early_setup(void) +{ + extern int console_use_vt; + + if (is_initial_xendomain()) { + xc_mode = XC_SERIAL; + } else { + xc_mode = XC_TTY; + console_use_vt = 0; + } +} + static int __init xencons_setup(char *str) { char *q; int n; - + extern int console_use_vt; + + console_use_vt = 1; if (!strncmp(str, "ttyS", 4)) { xc_mode = XC_SERIAL; str += 4; } else if (!strncmp(str, "tty", 3)) { xc_mode = XC_TTY; str += 3; + console_use_vt = 0; } else if (!strncmp(str, "xvc", 3)) { xc_mode = XC_XVC; str += 3; @@ -192,14 +208,10 @@ static int __init xen_console_init(void) goto out; if (is_initial_xendomain()) { - if (xc_mode == XC_DEFAULT) - xc_mode = XC_SERIAL; kcons_info.write = kcons_write_dom0; } else { if (!xen_start_info->console.domU.evtchn) goto out; - if (xc_mode == XC_DEFAULT) - xc_mode = XC_TTY; kcons_info.write = kcons_write; } diff -r 6fdbf173142d -r d603aed5ad6d linux-2.6-xen-sparse/drivers/xen/core/Makefile --- a/linux-2.6-xen-sparse/drivers/xen/core/Makefile Sat Dec 02 15:19:50 2006 -0700 +++ b/linux-2.6-xen-sparse/drivers/xen/core/Makefile Mon Dec 04 08:24:41 2006 -0700 @@ -11,3 +11,4 @@ obj-$(CONFIG_XEN_SKBUFF) += skbuff.o obj-$(CONFIG_XEN_SKBUFF) += skbuff.o obj-$(CONFIG_XEN_REBOOT) += reboot.o machine_reboot.o obj-$(CONFIG_XEN_SMPBOOT) += smpboot.o +obj-$(CONFIG_KEXEC) += machine_kexec.o diff -r 6fdbf173142d -r d603aed5ad6d linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypercall.h --- a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypercall.h Sat Dec 02 15:19:50 2006 -0700 +++ b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypercall.h Mon Dec 04 08:24:41 2006 -0700 @@ -395,5 +395,13 @@ HYPERVISOR_xenoprof_op( return _hypercall2(int, xenoprof_op, op, arg); } +static inline int +HYPERVISOR_kexec_op( + unsigned long op, void *args) +{ + return _hypercall2(int, kexec_op, op, args); +} + + #endif /* __HYPERCALL_H__ */ diff -r 6fdbf173142d -r d603aed5ad6d linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/hypercall.h --- a/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/hypercall.h Sat Dec 02 15:19:50 2006 -0700 +++ b/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/hypercall.h Mon Dec 04 08:24:41 2006 -0700 @@ -396,4 +396,11 @@ HYPERVISOR_xenoprof_op( return _hypercall2(int, xenoprof_op, op, arg); } +static inline int +HYPERVISOR_kexec_op( + unsigned long op, void *args) +{ + return _hypercall2(int, kexec_op, op, args); +} + #endif /* __HYPERCALL_H__ */ diff -r 6fdbf173142d -r d603aed5ad6d linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/ptrace.h --- a/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/ptrace.h Sat Dec 02 15:19:50 2006 -0700 +++ b/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/ptrace.h Mon Dec 04 08:24:41 2006 -0700 @@ -90,6 +90,8 @@ extern unsigned long profile_pc(struct p #define profile_pc(regs) instruction_pointer(regs) #endif +#include <linux/compiler.h> + void signal_fault(struct pt_regs *regs, void __user *frame, char *where); struct task_struct; diff -r 6fdbf173142d -r d603aed5ad6d linux-2.6-xen-sparse/include/xen/xencons.h --- a/linux-2.6-xen-sparse/include/xen/xencons.h Sat Dec 02 15:19:50 2006 -0700 +++ b/linux-2.6-xen-sparse/include/xen/xencons.h Mon Dec 04 08:24:41 2006 -0700 @@ -14,4 +14,6 @@ int xencons_ring_init(void); int xencons_ring_init(void); int xencons_ring_send(const char *data, unsigned len); +void xencons_early_setup(void); + #endif /* __ASM_XENCONS_H__ */ diff -r 6fdbf173142d -r d603aed5ad6d linux-2.6-xen-sparse/mm/memory.c --- a/linux-2.6-xen-sparse/mm/memory.c Sat Dec 02 15:19:50 2006 -0700 +++ b/linux-2.6-xen-sparse/mm/memory.c Mon Dec 04 08:24:41 2006 -0700 @@ -882,6 +882,7 @@ unsigned long zap_page_range(struct vm_a tlb_finish_mmu(tlb, address, end); return end; } +EXPORT_SYMBOL(zap_page_range); /* * Do a quick page-table lookup for a single page. diff -r 6fdbf173142d -r d603aed5ad6d patches/linux-2.6.16.33/series --- a/patches/linux-2.6.16.33/series Sat Dec 02 15:19:50 2006 -0700 +++ b/patches/linux-2.6.16.33/series Mon Dec 04 08:24:41 2006 -0700 @@ -1,3 +1,12 @@ blktap-aio-16_03_06.patch +kexec-generic.patch +git-2efe55a9cec8418f0e0cde3dc3787a42fddc4411.patch +git-2a8a3d5b65e86ec1dfef7d268c64a909eab94af7.patch +git-3566561bfadffcb5dbc85d576be80c0dbf2cccc9.patch +linux-2.6.19-rc1-kexec-move_segment_code-i386.patch +linux-2.6.19-rc1-kexec-xen-i386.patch +git-4bfaaef01a1badb9e8ffb0c0a37cd2379008d21f.patch +linux-2.6.19-rc1-kexec-move_segment_code-x86_64.patch +linux-2.6.19-rc1-kexec-xen-x86_64.patch blktap-aio-16_03_06.patch device_bind.patch fix-hz-suspend.patch @@ -22,6 +31,7 @@ xenoprof-generic.patch xenoprof-generic.patch x86-put-note-sections-into-a-pt_note-segment-in-vmlinux.patch x86_64-put-note-sections-into-a-pt_note-segment-in-vmlinux.patch +git-dbaab49f92ff6ae6255762a948375e4036cbdbd2.patch x86-elfnote-as-preprocessor-macro.patch vsnprintf.patch kasprintf.patch diff -r 6fdbf173142d -r d603aed5ad6d tools/Makefile --- a/tools/Makefile Sat Dec 02 15:19:50 2006 -0700 +++ b/tools/Makefile Mon Dec 04 08:24:41 2006 -0700 @@ -19,6 +19,7 @@ SUBDIRS-y += libaio SUBDIRS-y += libaio SUBDIRS-y += blktap SUBDIRS-y += libfsimage +SUBDIRS-$(XENFB_TOOLS) += xenfb SUBDIRS-$(LIBXENAPI_BINDINGS) += libxen # These don't cross-compile diff -r 6fdbf173142d -r d603aed5ad6d tools/blktap/drivers/block-aio.c --- a/tools/blktap/drivers/block-aio.c Sat Dec 02 15:19:50 2006 -0700 +++ b/tools/blktap/drivers/block-aio.c Mon Dec 04 08:24:41 2006 -0700 @@ -311,12 +311,8 @@ int tdaio_do_callbacks(struct td_state * struct pending_aio *pio; pio = &prv->pending_aio[(long)io->data]; - - if (ep->res != io->u.c.nbytes) { - /* TODO: handle this case better. */ - DPRINTF("AIO did less than I asked it to. \n"); - } - rsp += pio->cb(s, ep->res2, pio->id, pio->private); + rsp += pio->cb(s, ep->res == io->u.c.nbytes ? 0 : 1, + pio->id, pio->private); prv->iocb_free[prv->iocb_free_count++] = io; } diff -r 6fdbf173142d -r d603aed5ad6d tools/blktap/drivers/block-qcow.c --- a/tools/blktap/drivers/block-qcow.c Sat Dec 02 15:19:50 2006 -0700 +++ b/tools/blktap/drivers/block-qcow.c Mon Dec 04 08:24:41 2006 -0700 @@ -1145,13 +1145,6 @@ int tdqcow_do_callbacks(struct td_state pio = &prv->pending_aio[(long)io->data]; - if (ep->res != io->u.c.nbytes) { - /* TODO: handle this case better. */ - ptr = (int *)&ep->res; - DPRINTF("AIO did less than I asked it to " - "[%lu,%lu,%d]\n", - ep->res, io->u.c.nbytes, *ptr); - } aio_unlock(prv, pio->sector); if (pio->id >= 0) { if (prv->crypt_method) @@ -1162,7 +1155,7 @@ int tdqcow_do_callbacks(struct td_state &prv->aes_decrypt_key); prv->nr_reqs[pio->qcow_idx]--; if (prv->nr_reqs[pio->qcow_idx] == 0) - rsp += pio->cb(s, ep->res2, pio->id, + rsp += pio->cb(s, ep->res == io->u.c.nbytes ? 0 : 1, pio->id, pio->private); } else if (pio->id == -2) free(pio->buf); diff -r 6fdbf173142d -r d603aed5ad6d tools/blktap/drivers/tapdisk.c --- a/tools/blktap/drivers/tapdisk.c Sat Dec 02 15:19:50 2006 -0700 +++ b/tools/blktap/drivers/tapdisk.c Mon Dec 04 08:24:41 2006 -0700 @@ -424,8 +424,7 @@ int send_responses(struct td_state *s, i } if (res != 0) { - DPRINTF("*** request error %d! \n", res); - return 0; + blkif->pending_list[idx].status = BLKIF_RSP_ERROR; } blkif->pending_list[idx].count--; diff -r 6fdbf173142d -r d603aed5ad6d tools/check/Makefile --- a/tools/check/Makefile Sat Dec 02 15:19:50 2006 -0700 +++ b/tools/check/Makefile Mon Dec 04 08:24:41 2006 -0700 @@ -1,3 +1,5 @@ +XEN_ROOT = ../.. +include $(XEN_ROOT)/tools/Rules.mk .PHONY: all all: build @@ -5,7 +7,7 @@ all: build # Check this machine is OK for building on. .PHONY: build build: - ./chk build + XENFB_TOOLS=$(XENFB_TOOLS) ./chk build # Check this machine is OK for installing on. # DO NOT use this check from 'make install' in the parent @@ -13,7 +15,7 @@ build: # copy rather than actually installing. .PHONY: install install: - ./chk install + XENFB_TOOLS=$(XENFB_TOOLS) ./chk install .PHONY: clean clean: diff -r 6fdbf173142d -r d603aed5ad6d tools/firmware/vmxassist/setup.c --- a/tools/firmware/vmxassist/setup.c Sat Dec 02 15:19:50 2006 -0700 +++ b/tools/firmware/vmxassist/setup.c Mon Dec 04 08:24:41 2006 -0700 @@ -66,7 +66,7 @@ unsigned long memory_size; unsigned long memory_size; int initialize_real_mode; -extern char stack[], stack_top[]; +extern char stack_top[]; extern unsigned trap_handlers[]; void @@ -201,7 +201,7 @@ enter_real_mode(struct regs *regs) enter_real_mode(struct regs *regs) { /* mask off TSS busy bit */ - gdt[TSS_SELECTOR / sizeof(gdt[0])] &= ~0x0000020000000000ULL; + gdt[TSS_SELECTOR / sizeof(gdt[0])] &= ~0x0000020000000000ULL; /* start 8086 emulation of BIOS */ if (initialize_real_mode) { @@ -219,8 +219,10 @@ enter_real_mode(struct regs *regs) regs->cs = booting_vector << 8; /* AP entry point */ regs->eip = 0; } - regs->uesp = 0; - regs->uss = 0; + + regs->uesp = regs->uss = 0; + regs->eax = regs->ecx = regs->edx = regs->ebx = 0; + regs->esp = regs->ebp = regs->esi = regs->edi = 0; /* intercept accesses to the PIC */ setiomap(PIC_MASTER+PIC_CMD); @@ -236,14 +238,12 @@ enter_real_mode(struct regs *regs) /* this should get us into 16-bit mode */ return; - } else { - /* go from protected to real mode */ - regs->eflags |= EFLAGS_VM; - - set_mode(regs, VM86_PROTECTED_TO_REAL); - - emulate(regs); } + + /* go from protected to real mode */ + regs->eflags |= EFLAGS_VM; + set_mode(regs, VM86_PROTECTED_TO_REAL); + emulate(regs); } /* diff -r 6fdbf173142d -r d603aed5ad6d tools/firmware/vmxassist/trap.S --- a/tools/firmware/vmxassist/trap.S Sat Dec 02 15:19:50 2006 -0700 +++ b/tools/firmware/vmxassist/trap.S Mon Dec 04 08:24:41 2006 -0700 @@ -100,10 +100,6 @@ trap_handlers: .code32 .align 16 common_trap: /* common trap handler */ - pushl %gs - pushl %fs - pushl %ds - pushl %es pushal movl $(DATA_SELECTOR), %eax /* make sure these are sane */ @@ -114,17 +110,13 @@ common_trap: /* common trap handler * movl %esp, %ebp pushl %ebp - pushl 52(%ebp) - pushl 48(%ebp) + pushl 36(%ebp) + pushl 32(%ebp) call trap /* trap(trapno, errno, regs) */ addl $12, %esp trap_return: popal - popl %es - popl %ds - popl %fs - popl %gs addl $8, %esp /* skip trapno, errno */ iret /* NOT REACHED */ @@ -152,10 +144,6 @@ switch_to_real_mode: pushl oldctx+VMX_ASSIST_CTX_EIP pushl $-1 /* trapno, errno */ pushl $-1 - pushl %gs - pushl %fs - pushl %ds - pushl %es pushal movl %esp, %ebp diff -r 6fdbf173142d -r d603aed5ad6d tools/firmware/vmxassist/util.c --- a/tools/firmware/vmxassist/util.c Sat Dec 02 15:19:50 2006 -0700 +++ b/tools/firmware/vmxassist/util.c Mon Dec 04 08:24:41 2006 -0700 @@ -62,17 +62,15 @@ dump_regs(struct regs *regs) regs->eax, regs->ecx, regs->edx, regs->ebx); printf("esp %8x ebp %8x esi %8x edi %8x\n", regs->esp, regs->ebp, regs->esi, regs->edi); - printf("es %8x ds %8x fs %8x gs %8x\n", - regs->es, regs->ds, regs->fs, regs->gs); printf("trapno %8x errno %8x\n", regs->trapno, regs->errno); printf("eip %8x cs %8x eflags %8x\n", regs->eip, regs->cs, regs->eflags); - printf("uesp %8x uss %8x \n", + printf("uesp %8x uss %8x\n", regs->uesp, regs->uss); printf("ves %8x vds %8x vfs %8x vgs %8x\n", regs->ves, regs->vds, regs->vfs, regs->vgs); - printf("cr0 %8lx cr2 %8x cr3 %8lx cr4 %8lx\n", + printf("cr0 %8lx cr2 %8x cr3 %8lx cr4 %8lx\n\n", (long)oldctx.cr0, get_cr2(), (long)oldctx.cr3, (long)oldctx.cr4); } diff -r 6fdbf173142d -r d603aed5ad6d tools/firmware/vmxassist/vm86.c --- a/tools/firmware/vmxassist/vm86.c Sat Dec 02 15:19:50 2006 -0700 +++ b/tools/firmware/vmxassist/vm86.c Mon Dec 04 08:24:41 2006 -0700 @@ -376,9 +376,9 @@ segment(unsigned prefix, struct regs *re if (prefix & SEG_SS) seg = regs->uss; if (prefix & SEG_FS) - seg = regs->fs; + seg = regs->vfs; if (prefix & SEG_GS) - seg = regs->gs; + seg = regs->vgs; return seg; } @@ -934,6 +934,8 @@ static void static void protected_mode(struct regs *regs) { + extern char stack_top[]; + regs->eflags &= ~(EFLAGS_TF|EFLAGS_VM); oldctx.eip = regs->eip; @@ -958,12 +960,10 @@ protected_mode(struct regs *regs) &oldctx.gs_limit, &oldctx.gs_arbytes); /* initialize jump environment to warp back to protected mode */ + regs->uss = DATA_SELECTOR; + regs->uesp = stack_top; regs->cs = CODE_SELECTOR; - regs->ds = DATA_SELECTOR; - regs->es = DATA_SELECTOR; - regs->fs = DATA_SELECTOR; - regs->gs = DATA_SELECTOR; - regs->eip = (unsigned) &switch_to_protected_mode; + regs->eip = (unsigned) switch_to_protected_mode; /* this should get us into 32-bit mode */ } @@ -975,10 +975,6 @@ real_mode(struct regs *regs) real_mode(struct regs *regs) { regs->eflags |= EFLAGS_VM | 0x02; - regs->ds = DATA_SELECTOR; - regs->es = DATA_SELECTOR; - regs->fs = DATA_SELECTOR; - regs->gs = DATA_SELECTOR; /* * When we transition from protected to real-mode and we @@ -1070,9 +1066,6 @@ set_mode(struct regs *regs, enum vm86_mo case VM86_PROTECTED: if (mode == VM86_REAL_TO_PROTECTED) { protected_mode(regs); -// printf("<VM86_PROTECTED>\n"); - mode = newmode; - return; } else panic("unexpected protected mode transition"); break; diff -r 6fdbf173142d -r d603aed5ad6d tools/firmware/vmxassist/vm86.h --- a/tools/firmware/vmxassist/vm86.h Sat Dec 02 15:19:50 2006 -0700 +++ b/tools/firmware/vmxassist/vm86.h Mon Dec 04 08:24:41 2006 -0700 @@ -34,7 +34,6 @@ struct regs { unsigned edi, esi, ebp, esp, ebx, edx, ecx, eax; - unsigned es, ds, fs, gs; unsigned trapno, errno; unsigned eip, cs, eflags, uesp, uss; unsigned ves, vds, vfs, vgs; @@ -55,7 +54,6 @@ enum vm86_mode { extern enum vm86_mode prevmode, mode; extern struct vmx_assist_context oldctx; -extern struct vmx_assist_context newctx; extern void emulate(struct regs *); extern void dump_regs(struct regs *); diff -r 6fdbf173142d -r d603aed5ad6d tools/ioemu/hw/pci.c --- a/tools/ioemu/hw/pci.c Sat Dec 02 15:19:50 2006 -0700 +++ b/tools/ioemu/hw/pci.c Mon Dec 04 08:24:41 2006 -0700 @@ -221,23 +221,16 @@ uint32_t pci_default_read_config(PCIDevi uint32_t address, int len) { uint32_t val; - switch(len) { + case 1: + val = d->config[address]; + break; + case 2: + val = le16_to_cpu(*(uint16_t *)(d->config + address)); + break; default: case 4: - if (address <= 0xfc) { - val = le32_to_cpu(*(uint32_t *)(d->config + address)); - break; - } - /* fall through */ - case 2: - if (address <= 0xfe) { - val = le16_to_cpu(*(uint16_t *)(d->config + address)); - break; - } - /* fall through */ - case 1: - val = d->config[address]; + val = le32_to_cpu(*(uint32_t *)(d->config + address)); break; } return val; @@ -340,8 +333,7 @@ void pci_default_write_config(PCIDevice d->config[addr] = val; } - if (++addr > 0xff) - break; + addr++; val >>= 8; } diff -r 6fdbf173142d -r d603aed5ad6d tools/ioemu/hw/usb-uhci.c --- a/tools/ioemu/hw/usb-uhci.c Sat Dec 02 15:19:50 2006 -0700 +++ b/tools/ioemu/hw/usb-uhci.c Mon Dec 04 08:24:41 2006 -0700 @@ -421,7 +421,7 @@ static int uhci_handle_td(UHCIState *s, static int uhci_handle_td(UHCIState *s, UHCI_TD *td, int *int_mask) { uint8_t pid; - uint8_t buf[1280]; + uint8_t buf[2048]; int len, max_len, err, ret; if (td->ctrl & TD_CTRL_IOC) { diff -r 6fdbf173142d -r d603aed5ad6d tools/ioemu/vl.h --- a/tools/ioemu/vl.h Sat Dec 02 15:19:50 2006 -0700 +++ b/tools/ioemu/vl.h Mon Dec 04 08:24:41 2006 -0700 @@ -650,8 +650,11 @@ typedef struct PCIIORegion { #define PCI_MAX_LAT 0x3f /* 8 bits */ struct PCIDevice { - /* PCI config space */ - uint8_t config[256]; + /* + * PCI config space. The 4 extra bytes are a safety buffer for guest + * word/dword writes that can extend past byte 0xff. + */ + uint8_t config[256+4]; /* the following fields are read only */ PCIBus *bus; diff -r 6fdbf173142d -r d603aed5ad6d tools/ioemu/vnc.c --- a/tools/ioemu/vnc.c Sat Dec 02 15:19:50 2006 -0700 +++ b/tools/ioemu/vnc.c Mon Dec 04 08:24:41 2006 -0700 @@ -114,6 +114,7 @@ struct VncState int visible_h; int ctl_keys; /* Ctrl+Alt starts calibration */ + int shift_keys; /* Shift / CapsLock keys */ }; #define DIRTY_PIXEL_BITS 64 @@ -870,9 +871,12 @@ static void do_key_event(VncState *vs, i } else if (down) { int qemu_keysym = 0; - if (sym <= 128) /* normal ascii */ + if (sym <= 128) { /* normal ascii */ + int shifted = vs->shift_keys == 1 || vs->shift_keys == 2; qemu_keysym = sym; - else { + if (sym >= 'a' && sym <= 'z' && shifted) + qemu_keysym -= 'a' - 'A'; + } else { switch (sym) { case XK_Up: qemu_keysym = QEMU_KEY_UP; break; case XK_Down: qemu_keysym = QEMU_KEY_DOWN; break; @@ -903,6 +907,10 @@ static void do_key_event(VncState *vs, i vs->ctl_keys |= 2; break; + case XK_Shift_L: + vs->shift_keys |= 1; + break; + default: break; } @@ -914,6 +922,14 @@ static void do_key_event(VncState *vs, i case XK_Alt_L: vs->ctl_keys &= ~2; + break; + + case XK_Shift_L: + vs->shift_keys &= ~1; + break; + + case XK_Caps_Lock: + vs->shift_keys ^= 2; break; case XK_1 ... XK_9: diff -r 6fdbf173142d -r d603aed5ad6d tools/libxc/xc_linux.c --- a/tools/libxc/xc_linux.c Sat Dec 02 15:19:50 2006 -0700 +++ b/tools/libxc/xc_linux.c Mon Dec 04 08:24:41 2006 -0700 @@ -250,6 +250,15 @@ int xc_evtchn_notify(int xce_handle, evt return ioctl(xce_handle, IOCTL_EVTCHN_NOTIFY, ¬ify); } +evtchn_port_t xc_evtchn_bind_unbound_port(int xce_handle, int domid) +{ + struct ioctl_evtchn_bind_unbound_port bind; + + bind.remote_domain = domid; + + return ioctl(xce_handle, IOCTL_EVTCHN_BIND_UNBOUND_PORT, &bind); +} + evtchn_port_t xc_evtchn_bind_interdomain(int xce_handle, int domid, evtchn_port_t remote_port) { diff -r 6fdbf173142d -r d603aed5ad6d tools/libxc/xc_solaris.c --- a/tools/libxc/xc_solaris.c Sat Dec 02 15:19:50 2006 -0700 +++ b/tools/libxc/xc_solaris.c Mon Dec 04 08:24:41 2006 -0700 @@ -165,6 +165,15 @@ int xc_evtchn_notify(int xce_handle, evt return ioctl(xce_handle, IOCTL_EVTCHN_NOTIFY, ¬ify); } +evtchn_port_t xc_evtchn_bind_unbound_port(int xce_handle, int domid) +{ + struct ioctl_evtchn_bind_unbound_port bind; + + bind.remote_domain = domid; + + return ioctl(xce_handle, IOCTL_EVTCHN_BIND_UNBOUND_PORT, &bind); +} + evtchn_port_t xc_evtchn_bind_interdomain(int xce_handle, int domid, evtchn_port_t remote_port) { diff -r 6fdbf173142d -r d603aed5ad6d tools/libxc/xenctrl.h --- a/tools/libxc/xenctrl.h Sat Dec 02 15:19:50 2006 -0700 +++ b/tools/libxc/xenctrl.h Mon Dec 04 08:24:41 2006 -0700 @@ -382,6 +382,10 @@ int xc_sched_credit_domain_get(int xc_ha * This function allocates an unbound port. Ports are named endpoints used for * interdomain communication. This function is most useful in opening a * well-known port within a domain to receive events on. + * + * NOTE: If you are allocating a *local* unbound port, you probably want to + * use xc_evtchn_bind_unbound_port(). This function is intended for allocating + * ports *only* during domain creation. * * @parm xc_handle a handle to an open hypervisor interface * @parm dom the ID of the local domain (the 'allocatee') @@ -630,6 +634,12 @@ int xc_evtchn_notify(int xce_handle, evt int xc_evtchn_notify(int xce_handle, evtchn_port_t port); /* + * Returns a new event port awaiting interdomain connection from the given + * domain ID, or -1 on failure, in which case errno will be set appropriately. + */ +evtchn_port_t xc_evtchn_bind_unbound_port(int xce_handle, int domid); + +/* * Returns a new event port bound to the remote port for the given domain ID, * or -1 on failure, in which case errno will be set appropriately. */ @@ -661,15 +671,15 @@ int xc_evtchn_unmask(int xce_handle, evt int xc_evtchn_unmask(int xce_handle, evtchn_port_t port); int xc_hvm_set_pci_intx_level( - int xce_handle, domid_t dom, + int xc_handle, domid_t dom, uint8_t domain, uint8_t bus, uint8_t device, uint8_t intx, unsigned int level); int xc_hvm_set_isa_irq_level( - int xce_handle, domid_t dom, + int xc_handle, domid_t dom, uint8_t isa_irq, unsigned int level); int xc_hvm_set_pci_link_route( - int xce_handle, domid_t dom, uint8_t link, uint8_t isa_irq); + int xc_handle, domid_t dom, uint8_t link, uint8_t isa_irq); #endif diff -r 6fdbf173142d -r d603aed5ad6d tools/libxen/Makefile --- a/tools/libxen/Makefile Sat Dec 02 15:19:50 2006 -0700 +++ b/tools/libxen/Makefile Mon Dec 04 08:24:41 2006 -0700 @@ -48,8 +48,8 @@ libxenapi.a: $(LIBXENAPI_OBJS) libxenapi.a: $(LIBXENAPI_OBJS) $(AR) rcs libxenapi.a $^ -test/test_bindings: test/test_bindings.o src/libxen.so - $(CC) $(LDFLAGS) -o $@ $< -L src -lxen +test/test_bindings: test/test_bindings.o libxenapi.so + $(CC) $(LDFLAGS) -o $@ $< -L . -lxenapi .PHONY: install diff -r 6fdbf173142d -r d603aed5ad6d tools/libxen/README --- a/tools/libxen/README Sat Dec 02 15:19:50 2006 -0700 +++ b/tools/libxen/README Mon Dec 04 08:24:41 2006 -0700 @@ -44,11 +44,12 @@ test program depends upon libcurl3 also. test program depends upon libcurl3 also. On Debian, you need the packages libxml2-dev and libcurl3-dev. -To compile, type make. +To compile, type make. To compile the test also, type make +test/test_bindings, remembering the additional dependency. To run the test, do -LD_LIBRARY_PATH=src ./test/test_bindings <url> <username> <password> +LD_LIBRARY_PATH=. ./test/test_bindings <url> <username> <password> where <url> is the fragment of the server URL that follows the http://, for example "localhost:8005/RPC2". diff -r 6fdbf173142d -r d603aed5ad6d tools/libxen/include/xen_vm.h --- a/tools/libxen/include/xen_vm.h Sat Dec 02 15:19:50 2006 -0700 +++ b/tools/libxen/include/xen_vm.h Mon Dec 04 08:24:41 2006 -0700 @@ -21,6 +21,7 @@ #include "xen_boot_type.h" #include "xen_common.h" +#include "xen_console_decl.h" #include "xen_cpu_feature.h" #include "xen_host_decl.h" #include "xen_int_float_map.h" @@ -96,6 +97,7 @@ typedef struct xen_vm_record enum xen_on_normal_exit actions_after_reboot; enum xen_on_normal_exit actions_after_suspend; enum xen_on_crash_behaviour actions_after_crash; + struct xen_console_record_opt_set *consoles; struct xen_vif_record_opt_set *vifs; struct xen_vbd_record_opt_set *vbds; struct xen_vtpm_record_opt_set *vtpms; @@ -401,6 +403,13 @@ xen_vm_get_actions_after_crash(xen_sessi /** + * Get the consoles field of the given VM. + */ +extern bool +xen_vm_get_consoles(xen_session *session, struct xen_console_set **result, xen_vm vm); + + +/** * Get the VIFs field of the given VM. */ extern bool diff -r 6fdbf173142d -r d603aed5ad6d tools/libxen/src/xen_vm.c --- a/tools/libxen/src/xen_vm.c Sat Dec 02 15:19:50 2006 -0700 +++ b/tools/libxen/src/xen_vm.c Mon Dec 04 08:24:41 2006 -0700 @@ -22,6 +22,7 @@ #include "xen_boot_type_internal.h" #include "xen_common.h" +#include "xen_console.h" #include "xen_cpu_feature.h" #include "xen_cpu_feature_internal.h" #include "xen_host.h" @@ -120,6 +121,9 @@ static const struct_member xen_vm_record { .key = "actions_after_crash", .type = &xen_on_crash_behaviour_abstract_type_, .offset = offsetof(xen_vm_record, actions_after_crash) }, + { .key = "consoles", + .type = &abstract_type_ref_set, + .offset = offsetof(xen_vm_record, consoles) }, { .key = "VIFs", .type = &abstract_type_ref_set, .offset = offsetof(xen_vm_record, vifs) }, @@ -205,6 +209,7 @@ xen_vm_record_free(xen_vm_record *record xen_cpu_feature_set_free(record->vcpus_features_can_use); xen_cpu_feature_set_free(record->vcpus_features_force_on); xen_cpu_feature_set_free(record->vcpus_features_force_off); + xen_console_record_opt_set_free(record->consoles); xen_vif_record_opt_set_free(record->vifs); xen_vbd_record_opt_set_free(record->vbds); xen_vtpm_record_opt_set_free(record->vtpms); @@ -694,6 +699,23 @@ xen_vm_get_actions_after_crash(xen_sessi bool +xen_vm_get_consoles(xen_session *session, struct xen_console_set **result, xen_vm vm) +{ + abstract_value param_values[] = + { + { .type = &abstract_type_string, + .u.string_val = vm } + }; + + abstract_type result_type = abstract_type_string_set; + + *result = NULL; + XEN_CALL_("VM.get_consoles"); + return session->ok; +} + + +bool xen_vm_get_vifs(xen_session *session, struct xen_vif_set **result, xen_vm vm) { abstract_value param_values[] = diff -r 6fdbf173142d -r d603aed5ad6d tools/python/scripts/xapi.domcfg.py --- a/tools/python/scripts/xapi.domcfg.py Sat Dec 02 15:19:50 2006 -0700 +++ b/tools/python/scripts/xapi.domcfg.py Mon Dec 04 08:24:41 2006 -0700 @@ -26,7 +26,7 @@ platform_localtime = False platform_localtime = False platform_clock_offset = False platform_enable_audio = False -builder = '' +builder = 'linux' boot_method = '' # this will remove the kernel/initrd ?? kernel_kernel = '/boot/vmlinuz-2.6.16.29-xen' kernel_initrd = '/root/initrd-2.6.16.29-xen.img' diff -r 6fdbf173142d -r d603aed5ad6d tools/python/scripts/xapi.py --- a/tools/python/scripts/xapi.py Sat Dec 02 15:19:50 2006 -0700 +++ b/tools/python/scripts/xapi.py Mon Dec 04 08:24:41 2006 -0700 @@ -29,17 +29,20 @@ MB = 1024 * 1024 MB = 1024 * 1024 HOST_INFO_FORMAT = '%-20s: %-50s' -VM_LIST_FORMAT = '%(name_label)-18s %(memory_actual)-5s %(vcpus_number)-5s'\ +VM_LIST_FORMAT = '%(name_label)-18s %(memory_actual)-5s %(VCPUs_number)-5s'\ ' %(power_state)-10s %(uuid)-36s' SR_LIST_FORMAT = '%(name_label)-18s %(uuid)-36s %(physical_size)-10s' \ '%(type)-10s' VDI_LIST_FORMAT = '%(name_label)-18s %(uuid)-36s %(virtual_size)-8s '\ '%(sector_size)-8s' +VBD_LIST_FORMAT = '%(name_label)-18s %(uuid)-36s %(VDI)-8s '\ + '%(image)-8s' COMMANDS = { 'host-info': ('', 'Get Xen Host Info'), 'host-set-name': ('', 'Set host name'), 'sr-list': ('', 'List all SRs'), + 'vbd-list': ('', 'List all VBDs'), 'vbd-create': ('<domname> <pycfg> [opts]', 'Create VBD attached to domname'), 'vdi-create': ('<pycfg> [opts]', 'Create a VDI'), @@ -165,6 +168,13 @@ def resolve_vm(server, session, vm_name) else: return vm_uuid[0] +def resolve_vdi(server, session, vdi_name): + vdi_uuid = execute(server.VDI.get_by_name_label, session, vdi_name) + if not vdi_uuid: + return None + else: + return vdi_uuid[0] + # # Actual commands # @@ -216,16 +226,16 @@ def xapi_vm_list(*args): if not is_long: print VM_LIST_FORMAT % {'name_label':'Name', 'memory_actual':'Mem', - 'vcpus_number': 'VCPUs', + 'VCPUs_number': 'VCPUs', 'power_state': 'State', 'uuid': 'UUID'} for uuid in vm_uuids: vm_info = execute(server.VM.get_record, session, uuid) if is_long: - vbds = vm_info['vbds'] - vifs = vm_info['vifs'] - vtpms = vm_info['vtpms'] + vbds = vm_info['VBDs'] + vifs = vm_info['VIFs'] + vtpms = vm_info['VTPMs'] vif_infos = [] vbd_infos = [] vtpm_infos = [] @@ -238,9 +248,9 @@ def xapi_vm_list(*args): for vtpm in vtpms: vtpm_info = execute(server.VTPM.get_record, session, vtpm) vtpm_infos.append(vtpm_info) - vm_info['vbds'] = vbd_infos - vm_info['vifs'] = vif_infos - vm_info['vtpms'] = vtpm_infos + vm_info['VBDs'] = vbd_infos + vm_info['VIFs'] = vif_infos + vm_info['VTPMs'] = vtpm_infos pprint(vm_info) else: print VM_LIST_FORMAT % _stringify(vm_info) @@ -276,7 +286,7 @@ def xapi_vm_start(*args): server, session = _connect() vm_uuid = resolve_vm(server, session, args[0]) print 'Starting VM %s (%s)' % (args[0], vm_uuid) - success = execute(server.VM.start, session, vm_uuid) + success = execute(server.VM.start, session, vm_uuid, False) print 'Done.' def xapi_vm_shutdown(*args): @@ -333,6 +343,22 @@ def xapi_vif_create(*args): cfg['VM'] = vm_uuid vif_uuid = execute(server.VIF.create, session, cfg) print 'Done. (%s)' % vif_uuid + +def xapi_vbd_list(*args): + server, session = _connect() + domname = args[0] + + dom_uuid = resolve_vm(server, session, domname) + vbds = execute(server.VM.get_VBDs, session, dom_uuid) + + print VBD_LIST_FORMAT % {'name_label': 'VDI Label', + 'uuid' : 'UUID', + 'VDI': 'VDI', + 'image': 'Image'} + + for vbd in vbds: + vbd_struct = execute(server.VBD.get_record, session, vbd) + print VBD_LIST_FORMAT % vbd_struct def xapi_vdi_list(*args): server, session = _connect() @@ -420,8 +446,6 @@ def xapi_vtpm_create(*args): print "Has driver type '%s'" % driver vtpm_rec = execute(server.VTPM.get_record, session, vtpm_uuid) print "Has vtpm record '%s'" % vtpm_rec - vm = execute(server.VTPM.get_VM, session, vtpm_uuid) - print "Has VM '%s'" % vm # diff -r 6fdbf173142d -r d603aed5ad6d tools/python/xen/lowlevel/xc/xc.c --- a/tools/python/xen/lowlevel/xc/xc.c Sat Dec 02 15:19:50 2006 -0700 +++ b/tools/python/xen/lowlevel/xc/xc.c Mon Dec 04 08:24:41 2006 -0700 @@ -392,7 +392,7 @@ static PyObject *pyxc_hvm_build(XcObject return PyErr_SetFromErrno(xc_error); /* Set up the HVM info table. */ - va_map = xc_map_foreign_range(self->xc_handle, dom, PAGE_SIZE, + va_map = xc_map_foreign_range(self->xc_handle, dom, XC_PAGE_SIZE, PROT_READ | PROT_WRITE, HVM_INFO_PFN); if ( va_map == NULL ) @@ -407,7 +407,7 @@ static PyObject *pyxc_hvm_build(XcObject for ( i = 0, sum = 0; i < va_hvm->length; i++ ) sum += ((uint8_t *)va_hvm)[i]; va_hvm->checksum = -sum; - munmap(va_map, PAGE_SIZE); + munmap(va_map, XC_PAGE_SIZE); xc_get_hvm_param(self->xc_handle, dom, HVM_PARAM_STORE_PFN, &store_mfn); xc_set_hvm_param(self->xc_handle, dom, HVM_PARAM_PAE_ENABLED, pae); diff -r 6fdbf173142d -r d603aed5ad6d tools/python/xen/util/bugtool.py --- a/tools/python/xen/util/bugtool.py Sat Dec 02 15:19:50 2006 -0700 +++ b/tools/python/xen/util/bugtool.py Mon Dec 04 08:24:41 2006 -0700 @@ -43,8 +43,9 @@ TITLE_RE = re.compile(r'<title>(.*)</tit FILES_TO_SEND = [ '/var/log/' + x for x in [ 'syslog', 'messages', 'debug', - 'xen/xend.log', 'xen/xend-debug.log', 'xen/xenstored-trace.log', - 'xen/xen-hotplug.log' ] ] + 'xen/xend-debug.log', 'xen/xenstored-trace.log', + 'xen/xen-hotplug.log', 'xen/xend.log' ] + + [ 'xen/xend.log.%d' % z for z in range(1,6) ] ] #FILES_TO_SEND = [ ] diff -r 6fdbf173142d -r d603aed5ad6d tools/python/xen/util/xmlrpclib2.py --- a/tools/python/xen/util/xmlrpclib2.py Sat Dec 02 15:19:50 2006 -0700 +++ b/tools/python/xen/util/xmlrpclib2.py Mon Dec 04 08:24:41 2006 -0700 @@ -29,6 +29,8 @@ from SimpleXMLRPCServer import SimpleXML from SimpleXMLRPCServer import SimpleXMLRPCServer, SimpleXMLRPCRequestHandler import SocketServer import xmlrpclib, socket, os, stat + +import mkdir from xen.web import connection from xen.xend.XendLogging import log @@ -234,14 +236,9 @@ class UnixXMLRPCServer(TCPXMLRPCServer): address_family = socket.AF_UNIX def __init__(self, addr, allowed, logRequests = 1): - parent = os.path.dirname(addr) - if os.path.exists(parent): - os.chown(parent, os.geteuid(), os.getegid()) - os.chmod(parent, stat.S_IRWXU) - if self.allow_reuse_address and os.path.exists(addr): - os.unlink(addr) - else: - os.makedirs(parent, stat.S_IRWXU) + mkdir.parents(os.path.dirname(addr), stat.S_IRWXU, True) + if self.allow_reuse_address and os.path.exists(addr): + os.unlink(addr) TCPXMLRPCServer.__init__(self, addr, allowed, UnixXMLRPCRequestHandler, logRequests) diff -r 6fdbf173142d -r d603aed5ad6d tools/python/xen/web/unix.py --- a/tools/python/xen/web/unix.py Sat Dec 02 15:19:50 2006 -0700 +++ b/tools/python/xen/web/unix.py Mon Dec 04 08:24:41 2006 -0700 @@ -22,6 +22,8 @@ import socket import socket import stat +from xen.util import mkdir + import connection @@ -30,13 +32,9 @@ created such that only the current user created such that only the current user may access it.""" parent = os.path.dirname(path) - if os.path.exists(parent): - os.chown(parent, os.geteuid(), os.getegid()) - os.chmod(parent, stat.S_IRWXU) - if os.path.exists(path): - os.unlink(path) - else: - os.makedirs(parent, stat.S_IRWXU) + mkdir.parents(parent, stat.S_IRWXU, True) + if os.path.exists(path): + os.unlink(path) sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) sock.bind(path) diff -r 6fdbf173142d -r d603aed5ad6d tools/python/xen/xend/XendAPI.py --- a/tools/python/xen/xend/XendAPI.py Sat Dec 02 15:19:50 2006 -0700 +++ b/tools/python/xen/xend/XendAPI.py Mon Dec 04 08:24:41 2006 -0700 @@ -303,8 +303,8 @@ class XendAPI: # all get_by_uuid() methods. for cls in classes.keys(): - get_by_uuid = '%s_get_by_uuid' % cls.lower() - get_uuid = '%s_get_uuid' % cls.lower() + get_by_uuid = '%s_get_by_uuid' % cls + get_uuid = '%s_get_uuid' % cls setattr(XendAPI, get_by_uuid, lambda s, sess, obj_ref: xen_api_success(obj_ref)) setattr(XendAPI, get_uuid, @@ -327,7 +327,7 @@ class XendAPI: # wrap validators around readable class attributes for attr_name in ro_attrs + rw_attrs + self.Base_attr_ro: - getter_name = '%s_get_%s' % (cls.lower(), attr_name) + getter_name = '%s_get_%s' % (cls, attr_name) try: getter = getattr(XendAPI, getter_name) for validator in validators: @@ -340,7 +340,7 @@ class XendAPI: # wrap validators around writable class attrributes for attr_name in rw_attrs + self.Base_attr_rw: - setter_name = '%s_set_%s' % (cls.lower(), attr_name) + setter_name = '%s_set_%s' % (cls, attr_name) try: setter = getattr(XendAPI, setter_name) for validator in validators: @@ -353,7 +353,8 @@ class XendAPI: # wrap validators around methods for method_name in methods + self.Base_methods: - method_full_name = '%s_%s' % (cls.lower(), method_name) + method_full_name = '%s_%s' % (cls, method_name) + try: method = getattr(XendAPI, method_full_name) for validator in validators: @@ -366,7 +367,7 @@ class XendAPI: # wrap validators around class functions for func_name in funcs + self.Base_funcs: - func_full_name = '%s_%s' % (cls.lower(), func_name) + func_full_name = '%s_%s' % (cls, func_name) try: method = getattr(XendAPI, func_full_name) method = session_required(method) @@ -379,7 +380,7 @@ class XendAPI: Base_attr_ro = ['uuid'] Base_attr_rw = [] - Base_methods = ['destroy', 'to_XML', 'get_record'] + Base_methods = ['destroy', 'get_record'] Base_funcs = ['create', 'get_by_uuid', 'get_all'] # Xen API: Class Session @@ -411,8 +412,6 @@ class XendAPI: record = {'this_host': XendNode.instance().uuid, 'this_user': auth_manager().get_user(session)} return xen_api_success(record) - def session_to_XML(self, session): - return xen_api_todo() # attributes (ro) def session_get_this_host(self, session): @@ -536,8 +535,6 @@ class XendAPI: 'features': node.get_host_cpu_features(host_cpu_ref), 'utilisation': node.get_host_cpu_load(host_cpu_ref)} return xen_api_success(record) - def host_cpu_to_XML(self, session, host_cpu_ref): - return xen_api_todo() # class methods def host_cpu_get_all(self, session): @@ -656,304 +653,301 @@ class XendAPI: 'otherConfig'] # attributes (ro) - def vm_get_power_state(self, session, vm_ref): + def VM_get_power_state(self, session, vm_ref): dom = XendDomain.instance().get_vm_by_uuid(vm_ref) return xen_api_success(dom.state) - def vm_get_resident_on(self, session, vm_ref): + def VM_get_resident_on(self, session, vm_ref): return xen_api_success(XendNode.instance().uuid) - def vm_get_memory_actual(self, session, vm_ref): + def VM_get_memory_actual(self, session, vm_ref): dom = XendDomain.instance().get_vm_by_uuid(vm_ref) return xen_api_todo() # unsupported by xc - def vm_get_memory_static_max(self, session, vm_ref): + def VM_get_memory_static_max(self, session, vm_ref): dom = XendDomain.instance().get_vm_by_uuid(vm_ref) return xen_api_success(dom.get_memory_static_max()) - def vm_get_memory_static_min(self, session, vm_ref): + def VM_get_memory_static_min(self, session, vm_ref): dom = XendDomain.instance().get_vm_by_uuid(vm_ref) return xen_api_success(dom.get_memory_static_min()) - def vm_get_VCPUs_number(self, session, vm_ref): + def VM_get_VCPUs_number(self, session, vm_ref): dom = XendDomain.instance().get_vm_by_uuid(vm_ref) return xen_api_success(dom.getVCpuCount()) - def vm_get_VCPUs_utilisation(self, session, vm_ref): + def VM_get_VCPUs_utilisation(self, session, vm_ref): dom = XendDomain.instance().get_vm_by_uuid(vm_ref) return xen_api_success(dom.get_vcpus_util()) - def vm_get_VCPUs_features_required(self, session, vm_ref): + def VM_get_VCPUs_features_required(self, session, vm_ref): dom = XendDomain.instance().get_vm_by_uuid(vm_ref) return xen_api_todo() # unsupported by xc - def vm_get_VCPUs_can_use(self, session, vm_ref): + def VM_get_VCPUs_can_use(self, session, vm_ref): dom = XendDomain.instance().get_vm_by_uuid(vm_ref) return xen_api_todo() # unsupported by xc - def vm_get_VIFs(self, session, vm_ref): + def VM_get_VIFs(self, session, vm_ref): dom = XendDomain.instance().get_vm_by_uuid(vm_ref) return xen_api_success(dom.get_vifs()) - def vm_get_VBDs(self, session, vm_ref): + def VM_get_VBDs(self, session, vm_ref): dom = XendDomain.instance().get_vm_by_uuid(vm_ref) return xen_api_success(dom.get_vbds()) - def vm_get_VTPMs(self, session, vm_ref): + def VM_get_VTPMs(self, session, vm_ref): dom = XendDomain.instance().get_vm_by_uuid(vm_ref) return xen_api_success(dom.get_vtpms()) - def vm_get_PCI_bus(self, session, vm_ref): + def VM_get_PCI_bus(self, session, vm_ref): dom = XendDomain.instance().get_vm_by_uuid(vm_ref) return xen_api_todo() # unsupported by xc - def vm_get_tools_version(self, session, vm_ref): + def VM_get_tools_version(self, session, vm_ref): dom = XendDomain.instance().get_vm_by_uuid(vm_ref) return xen_api_todo() # attributes (rw) - def vm_get_name_label(self, session, vm_ref): + def VM_get_name_label(self, session, vm_ref): dom = XendDomain.instance().get_vm_by_uuid(vm_ref) return xen_api_success(dom.getName()) - def vm_get_name_description(self, session, vm_ref): - dom = XendDomain.instance().get_vm_by_uuid(vm_ref) - return xen_api_todo() - - def vm_get_user_version(self, session, vm_ref): - dom = XendDomain.instance().get_vm_by_uuid(vm_ref) - return xen_api_todo() - - def vm_get_is_a_template(self, session, vm_ref): - dom = XendDomain.instance().get_vm_by_uuid(vm_ref) - return xen_api_todo() - - def vm_get_memory_dynamic_max(self, session, vm_ref): - dom = XendDomain.instance().get_vm_by_uuid(vm_ref) - return xen_api_todo() - - def vm_get_memory_dynamic_min(self, session, vm_ref): - dom = XendDomain.instance().get_vm_by_uuid(vm_ref) - return xen_api_todo() - - def vm_get_VCPUs_policy(self, session, vm_ref): + def VM_get_name_description(self, session, vm_ref): + dom = XendDomain.instance().get_vm_by_uuid(vm_ref) + return xen_api_todo() + + def VM_get_user_version(self, session, vm_ref): + dom = XendDomain.instance().get_vm_by_uuid(vm_ref) + return xen_api_todo() + + def VM_get_is_a_template(self, session, vm_ref): + dom = XendDomain.instance().get_vm_by_uuid(vm_ref) + return xen_api_todo() + + def VM_get_memory_dynamic_max(self, session, vm_ref): + dom = XendDomain.instance().get_vm_by_uuid(vm_ref) + return xen_api_success(dom.get_memory_dynamic_max()) + + def VM_get_memory_dynamic_min(self, session, vm_ref): + dom = XendDomain.instance().get_vm_by_uuid(vm_ref) + return xen_api_success(dom.get_memory_dynamic_min()) + + def VM_get_VCPUs_policy(self, session, vm_ref): dom = XendDomain.instance().get_vm_by_uuid(vm_ref) return xen_api_todo() # need to access scheduler - def vm_get_VCPUs_params(self, session, vm_ref): + def VM_get_VCPUs_params(self, session, vm_ref): dom = XendDomain.instance().get_vm_by_uuid(vm_ref) return xen_api_todo() # need access to scheduler - def vm_get_VCPUs_features_force_on(self, session, vm_ref): - dom = XendDomain.instance().get_vm_by_uuid(vm_ref) - return xen_api_todo() - - def vm_get_VCPUs_features_force_off(self, session, vm_ref): - dom = XendDomain.instance().get_vm_by_uuid(vm_ref) - return xen_api_todo() - - def vm_get_actions_after_shutdown(self, session, vm_ref): + def VM_get_VCPUs_features_force_on(self, session, vm_ref): + dom = XendDomain.instance().get_vm_by_uuid(vm_ref) + return xen_api_todo() + + def VM_get_VCPUs_features_force_off(self, session, vm_ref): + dom = XendDomain.instance().get_vm_by_uuid(vm_ref) + return xen_api_todo() + + def VM_get_actions_after_shutdown(self, session, vm_ref): dom = XendDomain.instance().get_vm_by_uuid(vm_ref) return xen_api_success(dom.get_on_shutdown()) - def vm_get_actions_after_reboot(self, session, vm_ref): + def VM_get_actions_after_reboot(self, session, vm_ref): dom = XendDomain.instance().get_vm_by_uuid(vm_ref) return xen_api_success(dom.get_on_reboot()) - def vm_get_actions_after_suspend(self, session, vm_ref): + def VM_get_actions_after_suspend(self, session, vm_ref): dom = XendDomain.instance().get_vm_by_uuid(vm_ref) return xen_api_success(dom.get_on_suspend()) - def vm_get_actions_after_crash(self, session, vm_ref): + def VM_get_actions_after_crash(self, session, vm_ref): dom = XendDomain.instance().get_vm_by_uuid(vm_ref) return xen_api_success(dom.get_on_crash()) - def vm_get_bios_boot(self, session, vm_ref): + def VM_get_bios_boot(self, session, vm_ref): dom = XendDomain.instance().get_vm_by_uuid(vm_ref) return xen_api_success(dom.get_bios_boot()) - def vm_get_platform_std_VGA(self, session, vm_ref): - dom = XendDomain.instance().get_vm_by_uuid(vm_ref) - return xen_api_todo() - - def vm_get_platform_serial(self, session, vm_ref): - dom = XendDomain.instance().get_vm_by_uuid(vm_ref) - return xen_api_todo() - - def vm_get_platform_localtime(self, session, vm_ref): - dom = XendDomain.instance().get_vm_by_uuid(vm_ref) - return xen_api_todo() - - def vm_get_platform_clock_offset(self, session, vm_ref): - dom = XendDomain.instance().get_vm_by_uuid(vm_ref) - return xen_api_todo() - - def vm_get_platform_enable_audio(self, session, vm_ref): - dom = XendDomain.instance().get_vm_by_uuid(vm_ref) - return xen_api_todo() - - def vm_get_platform_keymap(self, session, vm_ref): - dom = XendDomain.instance().get_vm_by_uuid(vm_ref) - return xen_api_todo() - - def vm_get_builder(self, session, vm_ref): - dom = XendDomain.instance().get_vm_by_uuid(vm_ref) - return xen_api_todo() - - def vm_get_boot_method(self, session, vm_ref): + def VM_get_platform_std_VGA(self, session, vm_ref): + dom = XendDomain.instance().get_vm_by_uuid(vm_ref) + return xen_api_todo() + + def VM_get_platform_serial(self, session, vm_ref): + dom = XendDomain.instance().get_vm_by_uuid(vm_ref) + return xen_api_todo() + + def VM_get_platform_localtime(self, session, vm_ref): + dom = XendDomain.instance().get_vm_by_uuid(vm_ref) + return xen_api_todo() + + def VM_get_platform_clock_offset(self, session, vm_ref): + dom = XendDomain.instance().get_vm_by_uuid(vm_ref) + return xen_api_todo() + + def VM_get_platform_enable_audio(self, session, vm_ref): + dom = XendDomain.instance().get_vm_by_uuid(vm_ref) + return xen_api_todo() + + def VM_get_platform_keymap(self, session, vm_ref): + dom = XendDomain.instance().get_vm_by_uuid(vm_ref) + return xen_api_todo() + + def VM_get_builder(self, session, vm_ref): + dom = XendDomain.instance().get_vm_by_uuid(vm_ref) + return xen_api_success(dom.get_builder()) + + def VM_get_boot_method(self, session, vm_ref): + dom = XendDomain.instance().get_vm_by_uuid(vm_ref) + return xen_api_success(dom.get_boot_method()) + + def VM_get_kernel_kernel(self, session, vm_ref): dom = XendDomain.instance().get_vm_by_uuid(vm_ref) return xen_api_success('') - def vm_get_kernel_kernel(self, session, vm_ref): + def VM_get_kernel_initrd(self, session, vm_ref): dom = XendDomain.instance().get_vm_by_uuid(vm_ref) return xen_api_success('') - def vm_get_kernel_initrd(self, session, vm_ref): + def VM_get_kernel_args(self, session, vm_ref): dom = XendDomain.instance().get_vm_by_uuid(vm_ref) return xen_api_success('') - def vm_get_kernel_args(self, session, vm_ref): + def VM_get_grub_cmdline(self, session, vm_ref): dom = XendDomain.instance().get_vm_by_uuid(vm_ref) return xen_api_success('') - def vm_get_grub_cmdline(self, session, vm_ref): - dom = XendDomain.instance().get_vm_by_uuid(vm_ref) - return xen_api_success('') - - def vm_get_otherConfig(self, session, vm_ref): - dom = XendDomain.instance().get_vm_by_uuid(vm_ref) - return xen_api_todo() - - def vm_set_name_label(self, session, vm_ref): - dom = XendDomain.instance().get_vm_by_uuid(vm_ref) - return xen_api_success_void() - - def vm_set_name_description(self, session, vm_ref): - dom = XendDomain.instance().get_vm_by_uuid(vm_ref) - return xen_api_success_void() - - def vm_set_user_version(self, session, vm_ref): - dom = XendDomain.instance().get_vm_by_uuid(vm_ref) - return xen_api_success_void() - - def vm_set_is_a_template(self, session, vm_ref): - dom = XendDomain.instance().get_vm_by_uuid(vm_ref) - return xen_api_success_void() - - def vm_set_memory_dynamic_max(self, session, vm_ref): - dom = XendDomain.instance().get_vm_by_uuid(vm_ref) - return xen_api_success_void() - - def vm_set_memory_dynamic_min(self, session, vm_ref): - dom = XendDomain.instance().get_vm_by_uuid(vm_ref) - return xen_api_success_void() - - def vm_set_VCPUs_policy(self, session, vm_ref): - dom = XendDomain.instance().get_vm_by_uuid(vm_ref) - return xen_api_success_void() - - def vm_set_VCPUs_params(self, session, vm_ref): - dom = XendDomain.instance().get_vm_by_uuid(vm_ref) - return xen_api_success_void() - - def vm_set_VCPUs_features_force_on(self, session, vm_ref): - dom = XendDomain.instance().get_vm_by_uuid(vm_ref) - return xen_api_success_void() - - def vm_set_VCPUs_features_force_off(self, session, vm_ref): - dom = XendDomain.instance().get_vm_by_uuid(vm_ref) - return xen_api_success_void() - - def vm_set_actions_after_shutdown(self, session, vm_ref): - dom = XendDomain.instance().get_vm_by_uuid(vm_ref) - return xen_api_success_void() - - def vm_set_actions_after_reboot(self, session, vm_ref): - dom = XendDomain.instance().get_vm_by_uuid(vm_ref) - return xen_api_success_void() - - def vm_set_actions_after_suspend(self, session, vm_ref): - dom = XendDomain.instance().get_vm_by_uuid(vm_ref) - return xen_api_success_void() - - def vm_set_actions_after_crash(self, session, vm_ref): - dom = XendDomain.instance().get_vm_by_uuid(vm_ref) - return xen_api_success_void() - - def vm_set_bios_boot(self, session, vm_ref): - dom = XendDomain.instance().get_vm_by_uuid(vm_ref) - return xen_api_success_void() - - def vm_set_platform_std_VGA(self, session, vm_ref): - dom = XendDomain.instance().get_vm_by_uuid(vm_ref) - return xen_api_success_void() - - def vm_set_platform_serial(self, session, vm_ref): - dom = XendDomain.instance().get_vm_by_uuid(vm_ref) - return xen_api_success_void() - - def vm_set_platform_localtime(self, session, vm_ref): - dom = XendDomain.instance().get_vm_by_uuid(vm_ref) - return xen_api_success_void() - - def vm_set_platform_clock_offset(self, session, vm_ref): - dom = XendDomain.instance().get_vm_by_uuid(vm_ref) - return xen_api_success_void() - - def vm_set_platform_enable_audio(self, session, vm_ref): - dom = XendDomain.instance().get_vm_by_uuid(vm_ref) - return xen_api_success_void() - - def vm_set_builder(self, session, vm_ref): - dom = XendDomain.instance().get_vm_by_uuid(vm_ref) - return xen_api_success_void() - - def vm_set_boot_method(self, session, vm_ref): - dom = XendDomain.instance().get_vm_by_uuid(vm_ref) - return xen_api_success_void() - - def vm_set_kernel_kernel(self, session, vm_ref): - dom = XendDomain.instance().get_vm_by_uuid(vm_ref) - return xen_api_success_void() - - def vm_set_kernel_initrd(self, session, vm_ref): - dom = XendDomain.instance().get_vm_by_uuid(vm_ref) - return xen_api_success_void() - - def vm_set_kernel_args(self, session, vm_ref): - dom = XendDomain.instance().get_vm_by_uuid(vm_ref) - return xen_api_success_void() - - def vm_set_grub_cmdline(self, session, vm_ref): - dom = XendDomain.instance().get_vm_by_uuid(vm_ref) - return xen_api_success_void() - - def vm_set_otherConfig(self, session, vm_ref): + def VM_get_otherConfig(self, session, vm_ref): + dom = XendDomain.instance().get_vm_by_uuid(vm_ref) + return xen_api_todo() + + def VM_set_name_label(self, session, vm_ref): + dom = XendDomain.instance().get_vm_by_uuid(vm_ref) + return xen_api_success_void() + + def VM_set_name_description(self, session, vm_ref): + dom = XendDomain.instance().get_vm_by_uuid(vm_ref) + return xen_api_success_void() + + def VM_set_user_version(self, session, vm_ref): + dom = XendDomain.instance().get_vm_by_uuid(vm_ref) + return xen_api_success_void() + + def VM_set_is_a_template(self, session, vm_ref): + dom = XendDomain.instance().get_vm_by_uuid(vm_ref) + return xen_api_success_void() + + def VM_set_memory_dynamic_max(self, session, vm_ref): + dom = XendDomain.instance().get_vm_by_uuid(vm_ref) + return xen_api_success_void() + + def VM_set_memory_dynamic_min(self, session, vm_ref): + dom = XendDomain.instance().get_vm_by_uuid(vm_ref) + return xen_api_success_void() + + def VM_set_VCPUs_policy(self, session, vm_ref): + dom = XendDomain.instance().get_vm_by_uuid(vm_ref) + return xen_api_success_void() + + def VM_set_VCPUs_params(self, session, vm_ref): + dom = XendDomain.instance().get_vm_by_uuid(vm_ref) + return xen_api_success_void() + + def VM_set_VCPUs_features_force_on(self, session, vm_ref): + dom = XendDomain.instance().get_vm_by_uuid(vm_ref) + return xen_api_success_void() + + def VM_set_VCPUs_features_force_off(self, session, vm_ref): + dom = XendDomain.instance().get_vm_by_uuid(vm_ref) + return xen_api_success_void() + + def VM_set_actions_after_shutdown(self, session, vm_ref): + dom = XendDomain.instance().get_vm_by_uuid(vm_ref) + return xen_api_success_void() + + def VM_set_actions_after_reboot(self, session, vm_ref): + dom = XendDomain.instance().get_vm_by_uuid(vm_ref) + return xen_api_success_void() + + def VM_set_actions_after_suspend(self, session, vm_ref): + dom = XendDomain.instance().get_vm_by_uuid(vm_ref) + return xen_api_success_void() + + def VM_set_actions_after_crash(self, session, vm_ref): + dom = XendDomain.instance().get_vm_by_uuid(vm_ref) + return xen_api_success_void() + + def VM_set_bios_boot(self, session, vm_ref): + dom = XendDomain.instance().get_vm_by_uuid(vm_ref) + return xen_api_success_void() + + def VM_set_platform_std_VGA(self, session, vm_ref): + dom = XendDomain.instance().get_vm_by_uuid(vm_ref) + return xen_api_success_void() + + def VM_set_platform_serial(self, session, vm_ref): + dom = XendDomain.instance().get_vm_by_uuid(vm_ref) + return xen_api_success_void() + + def VM_set_platform_localtime(self, session, vm_ref): + dom = XendDomain.instance().get_vm_by_uuid(vm_ref) + return xen_api_success_void() + + def VM_set_platform_clock_offset(self, session, vm_ref): + dom = XendDomain.instance().get_vm_by_uuid(vm_ref) + return xen_api_success_void() + + def VM_set_platform_enable_audio(self, session, vm_ref): + dom = XendDomain.instance().get_vm_by_uuid(vm_ref) + return xen_api_success_void() + + def VM_set_builder(self, session, vm_ref): + dom = XendDomain.instance().get_vm_by_uuid(vm_ref) + return xen_api_success_void() + + def VM_set_boot_method(self, session, vm_ref): + dom = XendDomain.instance().get_vm_by_uuid(vm_ref) + return xen_api_success_void() + + def VM_set_kernel_kernel(self, session, vm_ref): + dom = XendDomain.instance().get_vm_by_uuid(vm_ref) + return xen_api_success_void() + + def VM_set_kernel_initrd(self, session, vm_ref): + dom = XendDomain.instance().get_vm_by_uuid(vm_ref) + return xen_api_success_void() + + def VM_set_kernel_args(self, session, vm_ref): + dom = XendDomain.instance().get_vm_by_uuid(vm_ref) + return xen_api_success_void() + + def VM_set_grub_cmdline(self, session, vm_ref): + dom = XendDomain.instance().get_vm_by_uuid(vm_ref) + return xen_api_success_void() + + def VM_set_otherConfig(self, session, vm_ref): dom = XendDomain.instance().get_vm_by_uuid(vm_ref) return xen_api_success_void() # class methods - def vm_get_all(self, session): - refs = [d.get_uuid() for d in XendDomain.instance().list()] + def VM_get_all(self, session): + refs = [d.get_uuid() for d in XendDomain.instance().list('all')] return xen_api_success(refs) - def vm_get_by_name_label(self, session, label): + def VM_get_by_name_label(self, session, label): xendom = XendDomain.instance() dom = xendom.domain_lookup_nr(label) if dom: return xen_api_success([dom.get_uuid()]) return xen_api_error(XEND_ERROR_VM_INVALID) - def vm_create(self, session, vm_struct): + def VM_create(self, session, vm_struct): xendom = XendDomain.instance() domuuid = xendom.create_domain(vm_struct) return xen_api_success(domuuid) # object methods - def vm_to_XML(self, session, vm_ref): - return xen_api_todo() - - def vm_get_record(self, session, vm_ref): + def VM_get_record(self, session, vm_ref): xendom = XendDomain.instance() xeninfo = xendom.get_vm_by_uuid(vm_ref) if not xeninfo: @@ -969,17 +963,17 @@ class XendAPI: 'resident_on': XendNode.instance().uuid, 'memory_static_min': xeninfo.get_memory_static_min(), 'memory_static_max': xeninfo.get_memory_static_max(), - 'memory_dynamic_min': xeninfo.get_memory_static_min(), - 'memory_dynamic_max': xeninfo.get_memory_static_max(), + 'memory_dynamic_min': xeninfo.get_memory_dynamic_min(), + 'memory_dynamic_max': xeninfo.get_memory_dynamic_max(), 'memory_actual': xeninfo.get_memory_static_min(), - 'vcpus_policy': xeninfo.get_vcpus_policy(), - 'vcpus_params': xeninfo.get_vcpus_params(), - 'vcpus_number': xeninfo.getVCpuCount(), - 'vcpus_utilisation': xeninfo.get_vcpus_util(), - 'vcpus_features_required': [], - 'vcpus_features_can_use': [], - 'vcpus_features_force_on': [], - 'vcpus_features_force_off': [], + 'VCPUs_policy': xeninfo.get_vcpus_policy(), + 'VCPUs_params': xeninfo.get_vcpus_params(), + 'VCPUs_number': xeninfo.getVCpuCount(), + 'VCPUs_utilisation': xeninfo.get_vcpus_util(), + 'VCPUs_features_required': [], + 'VCPUs_features_can_use': [], + 'VCPUs_features_force_on': [], + 'VCPUs_features_force_off': [], 'actions_after_shutdown': xeninfo.get_on_shutdown(), 'actions_after_reboot': xeninfo.get_on_reboot(), 'actions_after_suspend': xeninfo.get_on_suspend(), @@ -1006,41 +1000,39 @@ class XendAPI: } return xen_api_success(record) - def vm_clean_reboot(self, session, vm_ref): + def VM_clean_reboot(self, session, vm_ref): xendom = XendDomain.instance() xeninfo = xendom.get_vm_by_uuid(vm_ref) xeninfo.shutdown("reboot") return xen_api_success_void() - def vm_clean_shutdown(self, session, vm_ref): + def VM_clean_shutdown(self, session, vm_ref): xendom = XendDomain.instance() xeninfo = xendom.get_vm_by_uuid(vm_ref) xeninfo.shutdown("poweroff") return xen_api_success_void() - def vm_clone(self, session, vm_ref): + def VM_clone(self, session, vm_ref): return xen_api_error(XEND_ERROR_UNSUPPORTED) - def vm_destroy(self, session, vm_ref): + def VM_destroy(self, session, vm_ref): return do_vm_func("domain_delete", vm_ref) - def vm_hard_reboot(self, session, vm_ref): + def VM_hard_reboot(self, session, vm_ref): return xen_api_error(XEND_ERROR_UNSUPPORTED) - def vm_hard_shutdown(self, session, vm_ref): + def VM_hard_shutdown(self, session, vm_ref): return do_vm_func("domain_destroy", vm_ref) - def vm_pause(self, session, vm_ref): + def VM_pause(self, session, vm_ref): return do_vm_func("domain_pause", vm_ref) - def vm_resume(self, session, vm_ref, start_paused): + def VM_resume(self, session, vm_ref, start_paused): return do_vm_func("domain_resume", vm_ref, start_paused = start_paused) - def vm_start(self, session, vm_ref, start_paused): + def VM_start(self, session, vm_ref, start_paused): return do_vm_func("domain_start", vm_ref, start_paused = start_paused) - def vm_suspend(self, session, vm_ref): + def VM_suspend(self, session, vm_ref): return do_vm_func("domain_suspend", vm_ref) - def vm_unpause(self, session, vm_ref): + def VM_unpause(self, session, vm_ref): return do_vm_func("domain_unpause", vm_ref) - - # Xen API: Class VDI - # ---------------------------------------------------------------- - # TODO: NOT IMPLEMENTED. # Xen API: Class VBD # ---------------------------------------------------------------- + # Note: accepts a non-API standard 'image' attribute to emulate + # regular xm created VBDs VBD_attr_ro = ['image', 'IO_bandwidth_incoming_kbs', @@ -1053,8 +1045,10 @@ class XendAPI: VBD_attr_inst = VBD_attr_rw + ['image'] + VBD_methods = ['media_change'] + # object methods - def vbd_get_record(self, session, vbd_ref): + def VBD_get_record(self, session, vbd_ref): xendom = XendDomain.instance() vm = xendom.get_vm_with_dev_uuid('vbd', vbd_ref) if not vm: @@ -1063,9 +1057,12 @@ class XendAPI: if not cfg: return xen_api_error(XEND_ERROR_VBD_INVALID) return xen_api_success(cfg) - + + def VBD_media_change(self, session, vbd_ref, vdi_ref): + return xen_api_error(XEND_ERROR_UNSUPPORTED) + # class methods - def vbd_create(self, session, vbd_struct): + def VBD_create(self, session, vbd_struct): xendom = XendDomain.instance() if not xendom.is_valid_vm(vbd_struct['VM']): return xen_api_error(XEND_ERROR_DOMAIN_INVALID) @@ -1092,22 +1089,22 @@ class XendAPI: return xen_api_success(vbd_ref) # attributes (rw) - def vbd_get_VM(self, session, vbd_ref): + def VBD_get_VM(self, session, vbd_ref): xendom = XendDomain.instance() return xen_api_success(xendom.get_dev_property('vbd', vbd_ref, 'VM')) - def vbd_get_VDI(self, session, vbd_ref): - return xen_api_todo() - - def vbd_get_device(self, session, vbd_ref): + def VBD_get_VDI(self, session, vbd_ref): + return xen_api_todo() + + def VBD_get_device(self, session, vbd_ref): xendom = XendDomain.instance() return xen_api_success(xendom.get_dev_property('vbd', vbd_ref, 'device')) - def vbd_get_mode(self, session, vbd_ref): + def VBD_get_mode(self, session, vbd_ref): xendom = XendDomain.instance() return xen_api_success(xendom.get_dev_property('vbd', vbd_ref, 'mode')) - def vbd_get_driver(self, session, vbd_ref): + def VBD_get_driver(self, session, vbd_ref): xendom = XendDomain.instance() return xen_api_success(xendom.get_dev_property('vbd', vbd_ref, 'driver')) @@ -1130,7 +1127,7 @@ class XendAPI: VIF_attr_inst = VIF_attr_rw # object methods - def vif_get_record(self, session, vif_ref): + def VIF_get_record(self, session, vif_ref): xendom = XendDomain.instance() vm = xendom.get_vm_with_dev_uuid('vif', vif_ref) if not vm: @@ -1147,7 +1144,7 @@ class XendAPI: return xen_api_success(cfg) # class methods - def vif_create(self, session, vif_struct): + def VIF_create(self, session, vif_struct): xendom = XendDomain.instance() if xendom.is_valid_vm(vif_struct['VM']): dom = xendom.get_vm_by_uuid(vif_struct['VM']) @@ -1180,99 +1177,96 @@ class XendAPI: VDI_methods = ['snapshot'] VDI_funcs = ['get_by_name_label'] - def vdi_get_VBDs(self, session, vdi_ref): - return xen_api_todo() - - def vdi_get_physical_utilisation(self, session, vdi_ref): + def VDI_get_VBDs(self, session, vdi_ref): + return xen_api_todo() + + def VDI_get_physical_utilisation(self, session, vdi_ref): sr = XendNode.instance().get_sr() image = sr.xen_api_get_by_uuid(vdi_ref) return xen_api_success(image.get_physical_utilisation()) - def vdi_get_sector_size(self, session, vdi_ref): + def VDI_get_sector_size(self, session, vdi_ref): sr = XendNode.instance().get_sr() image = sr.xen_api_get_by_uuid(vdi_ref) return xen_api_success(image.sector_size) - def vdi_get_type(self, session, vdi_ref): + def VDI_get_type(self, session, vdi_ref): sr = XendNode.instance().get_sr() image = sr.xen_api_get_by_uuid(vdi_ref) return xen_api_success(image.type) - def vdi_get_parent(self, session, vdi_ref): + def VDI_get_parent(self, session, vdi_ref): sr = XendNode.instance().get_sr() image = sr.xen_api_get_by_uuid(vdi_ref) return xen_api_success(image.parent) - def vdi_get_children(self, session, vdi_ref): + def VDI_get_children(self, session, vdi_ref): sr = XendNode.instance().get_sr() image = sr.xen_api_get_by_uuid(vdi_ref) return xen_api_success(image.children) - def vdi_get_name_label(self, session, vdi_ref): + def VDI_get_name_label(self, session, vdi_ref): sr = XendNode.instance().get_sr() image = sr.xen_api_get_by_uuid(vdi_ref) return xen_api_success(image.name_label) - def vdi_get_name_description(self, session, vdi_ref): + def VDI_get_name_description(self, session, vdi_ref): sr = XendNode.instance().get_sr() image = sr.xen_api_get_by_uuid(vdi_ref) return xen_api_success(image.name_description) - def vdi_get_SR(self, session, vdi_ref): + def VDI_get_SR(self, session, vdi_ref): sr = XendNode.instance().get_sr() return xen_api_success(sr.uuid) - def vdi_get_virtual_size(self, session, vdi_ref): + def VDI_get_virtual_size(self, session, vdi_ref): sr = XendNode.instance().get_sr() image = sr.xen_api_get_by_uuid(vdi_ref) return xen_api_success(image.virtual_size) - def vdi_get_sharable(self, session, vdi_ref): + def VDI_get_sharable(self, session, vdi_ref): sr = XendNode.instance().get_sr() image = sr.xen_api_get_by_uuid(vdi_ref) return xen_api_success(image.sharable) - def vdi_get_read_only(self, session, vdi_ref): + def VDI_get_read_only(self, session, vdi_ref): sr = XendNode.instance().get_sr() image = sr.xen_api_get_by_uuid(vdi_ref) return xen_api_success(image.sharable) - def vdi_set_name_label(self, session, vdi_ref, value): + def VDI_set_name_label(self, session, vdi_ref, value): sr = XendNode.instance().get_sr() image = sr.xen_api_get_by_uuid(vdi_ref) image.name_label = value return xen_api_success_void() - def vdi_set_name_description(self, session, vdi_ref, value): + def VDI_set_name_description(self, session, vdi_ref, value): sr = XendNode.instance().get_sr() image = sr.xen_api_get_by_uuid(vdi_ref) image.name_description = value return xen_api_success_void() - def vdi_set_SR(self, session, vdi_ref, value): + def VDI_set_SR(self, session, vdi_ref, value): return xen_api_error(XEND_ERROR_UNSUPPORTED) - def vdi_set_virtual_size(self, session, vdi_ref, value): + def VDI_set_virtual_size(self, session, vdi_ref, value): return xen_api_error(XEND_ERROR_UNSUPPORTED) - def vdi_set_sharable(self, session, vdi_ref, value): - return xen_api_todo() - def vdi_set_read_only(self, session, vdi_ref, value): + def VDI_set_sharable(self, session, vdi_ref, value): + return xen_api_todo() + def VDI_set_read_only(self, session, vdi_ref, value): return xen_api_todo() # Object Methods - def vdi_snapshot(self, session, vdi_ref): - return xen_api_todo() - - def vdi_destroy(self, session, vdi_ref): + def VDI_snapshot(self, session, vdi_ref): + return xen_api_todo() + + def VDI_destroy(self, session, vdi_ref): sr = XendNode.instance().get_sr() sr.destroy_image(vdi_ref) return xen_api_success_void() - def vdi_to_XML(self, session, vdi_ref): - return xen_api_todo() - - def vdi_get_record(self, session, vdi_ref): + def VDI_get_record(self, session, vdi_ref): sr = XendNode.instance().get_sr() image = sr.xen_api_get_by_uuid(vdi_ref) if image: @@ -1295,7 +1289,7 @@ class XendAPI: return xen_api_error(XEND_ERROR_VDI_INVALID) # Class Functions - def vdi_create(self, session, vdi_struct): + def VDI_create(self, session, vdi_struct): sr = XendNode.instance().get_sr() sr_ref = vdi_struct['SR'] if sr.uuid != sr_ref: @@ -1304,11 +1298,11 @@ class XendAPI: vdi_uuid = sr.create_image(vdi_struct) return xen_api_success(vdi_uuid) - def vdi_get_all(self, session): + def VDI_get_all(self, session): sr = XendNode.instance().get_sr() return xen_api_success(sr.list_images()) - def vdi_get_by_name_label(self, session, name): + def VDI_get_by_name_label(self, session, name): sr = XendNode.instance().get_sr() image_uuid = sr.xen_api_get_by_name_label(name) if image_uuid: @@ -1329,7 +1323,7 @@ class XendAPI: VTPM_attr_inst = VTPM_attr_rw # object methods - def vtpm_get_record(self, session, vtpm_ref): + def VTPM_get_record(self, session, vtpm_ref): xendom = XendDomain.instance() vm = xendom.get_vm_with_dev_uuid('vtpm', vtpm_ref) if not vm: @@ -1346,7 +1340,7 @@ class XendAPI: return xen_api_success(cfg) # Class Functions - def vtpm_get_instance(self, session, vtpm_ref): + def VTPM_get_instance(self, session, vtpm_ref): xendom = XendDomain.instance() vm = xendom.get_vm_with_dev_uuid('vtpm', vtpm_ref) if not vm: @@ -1360,7 +1354,7 @@ class XendAPI: instance = -1 return xen_api_success(instance) - def vtpm_get_driver(self, session, vtpm_ref): + def VTPM_get_driver(self, session, vtpm_ref): xendom = XendDomain.instance() vm = xendom.get_vm_with_dev_uuid('vtpm', vtpm_ref) if not vm: @@ -1374,7 +1368,7 @@ class XendAPI: driver = "Unknown" return xen_api_success(driver) - def vtpm_get_backend(self, session, vtpm_ref): + def VTPM_get_backend(self, session, vtpm_ref): xendom = XendDomain.instance() vm = xendom.get_vm_with_dev_uuid('vtpm', vtpm_ref) if not vm: @@ -1388,12 +1382,12 @@ class XendAPI: backend = "Domain-0" return xen_api_success(backend) - def vtpm_get_VM(self, session, vtpm_ref): + def VTPM_get_VM(self, session, vtpm_ref): xendom = XendDomain.instance() return xen_api_success(xendom.get_dev_property('vtpm', vtpm_ref, 'VM')) # class methods - def vtpm_create(self, session, vtpm_struct): + def VTPM_create(self, session, vtpm_struct): xendom = XendDomain.instance() if xendom.is_valid_vm(vtpm_struct['VM']): dom = xendom.get_vm_by_uuid(vtpm_struct['VM']) @@ -1429,32 +1423,30 @@ class XendAPI: SR_funcs = ['get_by_name_label'] # Class Functions - def sr_get_all(self, session): + def SR_get_all(self, session): sr = XendNode.instance().get_sr() return xen_api_success([sr.uuid]) - def sr_get_by_name_label(self, session, label): + def SR_get_by_name_label(self, session, label): sr = XendNode.instance().get_sr() if sr.name_label != label: return xen_api_error(XEND_ERROR_SR_INVALID) return xen_api_success([sr.uuid]) - def sr_create(self, session): + def SR_create(self, session): return xen_api_error(XEND_ERROR_UNSUPPORTED) - def sr_get_by_uuid(self, session): + def SR_get_by_uuid(self, session): return xen_api_success(XendNode.instance().get_sr().uuid) # Class Methods - def sr_clone(self, session, sr_ref): + def SR_clone(self, session, sr_ref): return xen_api_error(XEND_ERROR_UNSUPPORTED) - def sr_destroy(self, session, sr_ref): + + def SR_destroy(self, session, sr_ref): return xen_api_error(XEND_ERROR_UNSUPPORTED) - def sr_to_XML(self, session, sr_ref): - return xen_api_todo() - - def sr_get_record(self, session, sr_ref): + def SR_get_record(self, session, sr_ref): sr = XendNode.instance().get_sr() return xen_api_success({ 'uuid': sr.uuid, @@ -1469,44 +1461,44 @@ class XendAPI: }) # Attribute acceess - def sr_get_VDIs(self, session, sr_ref): + def SR_get_VDIs(self, session, sr_ref): sr = XendNode.instance().get_sr() return xen_api_success(sr.list_images()) - def sr_get_virtual_allocation(self, session, sr_ref): + def SR_get_virtual_allocation(self, session, sr_ref): sr = XendNode.instance().get_sr() return sr.used_space_bytes() - def sr_get_physical_utilisation(self, session, sr_ref): + def SR_get_physical_utilisation(self, session, sr_ref): sr = XendNode.instance().get_sr() return sr.used_space_bytes() - def sr_get_physical_size(self, session, sr_ref): + def SR_get_physical_size(self, session, sr_ref): sr = XendNode.instance().get_sr() return sr.total_space_bytes() - def sr_get_type(self, session, sr_ref): + def SR_get_type(self, session, sr_ref): sr = XendNode.instance().get_sr() return xen_api_success(sr.type) - def sr_get_location(self, session, sr_ref): + def SR_get_location(self, session, sr_ref): sr = XendNode.instance().get_sr() return xen_api_success(sr.location) - def sr_get_name_label(self, session, sr_ref): + def SR_get_name_label(self, session, sr_ref): sr = XendNode.instance().get_sr() return xen_api_success(sr.name_label) - def sr_get_name_description(self, session, sr_ref): + def SR_get_name_description(self, session, sr_ref): sr = XendNode.instance().get_sr() return xen_api_success(sr.name_description) - def sr_set_name_label(self, session, sr_ref, value): + def SR_set_name_label(self, session, sr_ref, value): sr = XendNode.instance().get_sr() sr.name_label = value return xen_api_success_void() - def sr_set_name_description(self, session, sr_ref, value): + def SR_set_name_description(self, session, sr_ref, value): sr = XendNode.instance().get_sr() sr.name_description = value return xen_api_success_void() @@ -1525,24 +1517,24 @@ if __name__ == "__main__": methods = getattr(XendAPI, '%s_methods' % cls, []) funcs = getattr(XendAPI, '%s_funcs' % cls, []) - ref = '%s_ref' % cls.lower() + ref = '%s_ref' % cls for attr_name in ro_attrs + rw_attrs + XendAPI.Base_attr_ro: - getter_name = '%s_get_%s' % (cls.lower(), attr_name.lower()) + getter_name = '%s_get_%s' % (cls, attr_name) output('def %s(self, session, %s):' % (getter_name, ref)) output(' return xen_api_todo()') for attr_name in rw_attrs + XendAPI.Base_attr_rw: - setter_name = '%s_set_%s' % (cls.lower(), attr_name.lower()) + setter_name = '%s_set_%s' % (cls, attr_name) output('def %s(self, session, %s, value):' % (setter_name, ref)) output(' return xen_api_todo()') for method_name in methods + XendAPI.Base_methods: - method_full_name = '%s_%s' % (cls.lower(),method_name.lower()) + method_full_name = '%s_%s' % (cls,method_name) output('def %s(self, session, %s):' % (method_full_name, ref)) output(' return xen_api_todo()') for func_name in funcs + XendAPI.Base_funcs: - func_full_name = '%s_%s' % (cls.lower(), func_name.lower()) + func_full_name = '%s_%s' % (cls, func_name) output('def %s(self, session):' % func_full_name) output(' return xen_api_todo()') diff -r 6fdbf173142d -r d603aed5ad6d tools/python/xen/xend/XendCheckpoint.py --- a/tools/python/xen/xend/XendCheckpoint.py Sat Dec 02 15:19:50 2006 -0700 +++ b/tools/python/xen/xend/XendCheckpoint.py Mon Dec 04 08:24:41 2006 -0700 @@ -18,8 +18,8 @@ from xen.xend import balloon, sxp from xen.xend import balloon, sxp from xen.xend.XendError import XendError, VmError from xen.xend.XendLogging import log +from xen.xend.XendConfig import XendConfig from xen.xend.XendConstants import * -from xen.xend.XendConfig import XendConfig SIGNATURE = "LinuxGuestRecord" XC_SAVE = "xc_save" @@ -137,7 +137,7 @@ def restore(xd, fd, dominfo = None, paus vmconfig = p.get_val() if dominfo: - dominfo.update(XendConfig(sxp = vmconfig), refresh = False) + dominfo.update(XendConfig(sxp_obj = vmconfig), refresh = False) dominfo.resume() else: dominfo = xd.restore_(vmconfig) diff -r 6fdbf173142d -r d603aed5ad6d tools/python/xen/xend/XendConfig.py --- a/tools/python/xen/xend/XendConfig.py Sat Dec 02 15:19:50 2006 -0700 +++ b/tools/python/xen/xend/XendConfig.py Mon Dec 04 08:24:41 2006 -0700 @@ -31,143 +31,197 @@ XendConfig API XendConfig API XendConfig will try to mirror as closely the Xen API VM Struct - providing a backwards compatibility mode for SXP dumping, loading. + with extra parameters for those options that are not supported. """ - -LEGACY_CFG_TO_XENAPI_CFG = { +def reverse_dict(adict): + """Return the reverse mapping of a dictionary.""" + return dict([(v, k) for k, v in adict.items()]) + +def bool0(v): + return v != '0' and bool(v) + +# Mapping from XendConfig configuration keys to the old +# legacy configuration keys that map directly. + +XENAPI_CFG_TO_LEGACY_CFG = { 'uuid': 'uuid', - 'vcpus': 'vcpus_number', - 'maxmem': 'memory_static_max', - 'memory': 'memory_static_min', - 'name': 'name_label', - 'on_poweroff': 'actions_after_shutdown', - 'on_reboot': 'actions_after_reboot', - 'on_crash': 'actions_after_crash', - 'bootloader': 'boot_method', - 'kernel_kernel': 'kernel_kernel', - 'kernel_initrd': 'kernel_initrd', - 'kernel_args': 'kernel_args', - } - -XENAPI_CFG_CUSTOM_TRANSLATE = [ - 'vifs', - 'vbds', - ] - + 'vcpus_number': 'vcpus', + 'memory_static_min': 'memory', + 'memory_static_max': 'maxmem', + 'name_label': 'name', + 'actions_after_shutdown': 'on_poweroff', + 'actions_after_reboot': 'on_reboot', + 'actions_after_crash': 'on_crash', + 'platform_localtime': 'localtime', +} + +LEGACY_CFG_TO_XENAPI_CFG = reverse_dict(XENAPI_CFG_TO_LEGACY_CFG) + +# Mapping from XendConfig configuration keys to the old +# legacy configuration keys that are found in the 'image' +# SXP object. XENAPI_HVM_CFG = { - 'platform_std_vga': 'std-vga', + 'platform_std_vga': 'stdvga', 'platform_serial' : 'serial', 'platform_localtime': 'localtime', 'platform_enable_audio': 'soundhw', 'platform_keymap' : 'keymap', } -XENAPI_UNSUPPORTED_IN_LEGACY_CFG = [ - 'name_description', - 'user_version', - 'is_a_template', - 'memory_dynamic_min', - 'memory_dynamic_max', - 'memory_actual', - 'vcpus_policy', - 'vcpus_params', - 'vcpus_features_required', - 'vcpus_features_can_use', - 'vcpus_features_force_on', - 'vcpus_features_force_off', - 'actions_after_suspend', - 'bios_boot', - 'platform_std_vga', - 'platform_serial', - 'platform_localtime', - 'platform_clock_offset', - 'platform_enable_audio', - 'platform_keymap', - 'builder', - 'grub_cmdline', - 'pci_bus', - 'otherconfig' - ] - - -# configuration params that need to be converted to ints -# since the XMLRPC transport for Xen API does not use -# 32 bit ints but string representation of 64 bit ints. -XENAPI_INT_CFG = [ - 'user_version', - 'vcpus_number', - 'memory_static_min', - 'memory_static_max', - 'memory_dynamic_min', - 'memory_dynamic_max', - 'tpm_instance', - 'tpm_backend', -] - -## -## Xend Configuration Parameters -## - - -# All parameters of VMs that may be configured on-the-fly, or at start-up. -VM_CONFIG_ENTRIES = [ - ('name', str), - ('on_crash', str), - ('on_poweroff', str), - ('on_reboot', str), - ('on_xend_start', str), - ('on_xend_stop', str), +# List of XendConfig configuration keys that have no equivalent +# in the old world. + +XENAPI_CFG_TYPES = { + 'uuid': str, + 'power_state': str, + 'name_label': str, + 'name_description': str, + 'user_version': str, + 'is_a_template': bool0, + 'resident_on': str, + 'memory_static_min': int, + 'memory_static_max': int, + 'memory_dynamic_min': int, + 'memory_dynamic_max': int, + 'memory_actual': int, + 'vcpus_policy': str, + 'vcpus_params': str, + 'vcpus_number': int, + 'vcpus_features_required': list, + 'vcpus_features_can_use': list, + 'vcpus_features_force_on': list, + 'vcpus_features_force_off': list, + 'actions_after_shutdown': str, + 'actions_after_reboot': str, + 'actions_after_suspend': str, + 'actions_after_crash': str, + 'tpm_instance': int, + 'tpm_backend': int, + 'bios_boot': str, + 'platform_std_vga': bool0, + 'platform_serial': str, + 'platform_localtime': bool0, + 'platform_clock_offset': bool0, + 'platform_enable_audio': bool0, + 'platform_keymap': str, + 'boot_method': str, + 'builder': str, + 'kernel_kernel': str, + 'kernel_initrd': str, + 'kernel_args': str, + 'grub_cmdline': str, + 'pci_bus': str, + 'tools_version': dict, + 'otherconfig': dict, +} + +# List of legacy configuration keys that have no equivalent in the +# Xen API, but are still stored in XendConfig. + +LEGACY_UNSUPPORTED_BY_XENAPI_CFG = [ + # roundtripped (dynamic, unmodified) + 'shadow_memory', + 'security', + 'vcpu_avail', + 'cpu_weight', + 'cpu_cap', + 'bootloader', + 'bootloader_args', + 'features', + # read/write + 'on_xend_start', + 'on_xend_stop', + # read-only + 'domid', + 'start_time', + 'cpu_time', + 'online_vcpus', + # write-once + 'cpu', + 'cpus', ] -# All entries written to the store. This is VM_CONFIG_ENTRIES, plus those -# entries written to the store that cannot be reconfigured on-the-fly. -VM_STORE_ENTRIES = [ - ('uuid', str), - ('vcpus', int), - ('vcpu_avail', int), - ('memory', int), - ('maxmem', int), - ('start_time', float), +LEGACY_CFG_TYPES = { + 'uuid': str, + 'name': str, + 'vcpus': int, + 'vcpu_avail': int, + 'memory': int, + 'shadow_memory': int, + 'maxmem': int, + 'start_time': float, + 'cpu_cap': int, + 'cpu_weight': int, + 'cpu_time': float, + 'bootloader': str, + 'bootloader_args': str, + 'features': str, + 'localtime': int, + 'name': str, + 'on_poweroff': str, + 'on_reboot': str, + 'on_crash': str, + 'on_xend_stop': str, + 'on_xend_start': str, + 'online_vcpus': int, +} + +# Values that should be stored in xenstore's /vm/<uuid> that is used +# by Xend. Used in XendDomainInfo to restore running VM state from +# xenstore. +LEGACY_XENSTORE_VM_PARAMS = [ + 'uuid', + 'name', + 'vcpus', + 'vcpu_avail', + 'memory', + 'shadow_memory', + 'maxmem', + 'start_time', + 'name', + 'on_poweroff', + 'on_crash', + 'on_reboot', + 'on_xend_start', + 'on_xend_stop', ] -VM_STORED_ENTRIES = VM_CONFIG_ENTRIES + VM_STORE_ENTRIES - -# Configuration entries that we expect to round-trip -- be read from the -# config file or xc, written to save-files (i.e. through sxpr), and reused as -# config on restart or restore, all without munging. Some configuration -# entries are munged for backwards compatibility reasons, or because they -# don't come out of xc in the same form as they are specified in the config -# file, so those are handled separately. - -ROUNDTRIPPING_CONFIG_ENTRIES = [ - ('uuid', str), - ('vcpus', int), - ('vcpu_avail', int), - ('cpu_cap', int), - ('cpu_weight', int), - ('memory', int), - ('shadow_memory', int), - ('maxmem', int), - ('bootloader', str), - ('bootloader_args', str), - ('features', str), - ('localtime', int), +LEGACY_IMAGE_CFG = [ + ('root', str), + ('ip', str), + ('nographic', int), + ('vnc', int), + ('sdl', int), + ('vncdisplay', int), + ('vncunused', int), + ('vncpasswd', str), ] -ROUNDTRIPPING_CONFIG_ENTRIES += VM_CONFIG_ENTRIES - -## Static Configuration - -STATIC_CONFIG_ENTRIES = [ - ('cpu', int), - ('cpus', str), - ('image', list), - ('security', list), # TODO: what if null? + +LEGACY_IMAGE_HVM_CFG = [ + ('device_model', str), + ('display', str), + ('xauthority', str), + ('vncconsole', int), + ('pae', int), + ('apic', int), ] -DEPRECATED_ENTRIES = [ - ('restart', str), +LEGACY_IMAGE_HVM_DEVICES_CFG = [ + ('acpi', int), + ('boot', str), + ('fda', str), + ('fdb', str), + ('isa', str), + ('keymap', str), + ('localtime', str), + ('serial', str), + ('stdvga', int), + ('soundhw', str), + ('usb', str), + ('usbdevice', str), + ('vcpus', int), ] ## @@ -178,245 +232,172 @@ CONFIG_OLD_DOM_STATES = ('running', 'blo CONFIG_OLD_DOM_STATES = ('running', 'blocked', 'paused', 'shutdown', 'crashed', 'dying') -## -## Defaults -## - -def DEFAULT_VCPUS(info): - if 'max_vcpu_id' in info: return int(info['max_vcpu_id']) + 1 - else: return 1 - -DEFAULT_CONFIGURATION = ( - ('uuid', lambda info: uuid.createString()), - ('name', lambda info: 'Domain-' + info['uuid']), - - ('on_poweroff', lambda info: 'destroy'), - ('on_reboot', lambda info: 'restart'), - ('on_crash', lambda info: 'restart'), - ('features', lambda info: ''), - - - ('memory', lambda info: 0), - ('shadow_memory',lambda info: 0), - ('maxmem', lambda info: 0), - ('bootloader', lambda info: None), - ('bootloader_args', lambda info: None), - ('backend', lambda info: []), - ('device', lambda info: {}), - ('image', lambda info: None), - ('security', lambda info: []), - ('on_xend_start', lambda info: 'ignore'), - ('on_xend_stop', lambda info: 'ignore'), - - ('cpus', lambda info: []), - ('cpu_cap', lambda info: 0), - ('cpu_weight', lambda info: 256), - ('vcpus', lambda info: DEFAULT_VCPUS(info)), - ('online_vcpus', lambda info: info['vcpus']), - ('max_vcpu_id', lambda info: info['vcpus']-1), - ('vcpu_avail', lambda info: (1<<info['vcpus'])-1), - - # New for Xen API - ('kernel_kernel', lambda info: ''), - ('kernel_initrd', lambda info: ''), - ('kernel_args', lambda info: ''), - -) - class XendConfigError(VmError): def __str__(self): return 'Invalid Configuration: %s' % str(self.value) ## -## XendConfig SXP Config Compat -## - -class XendSXPConfig: - def get_domid(self): - pass - def get_handle(self): - return self['uuid'] - - -## ## XendConfig Class (an extended dictionary) ## class XendConfig(dict): - """ Generic Configuration Parser accepting SXP, Python or XML. - This is a dictionary-like object that is populated. - - @ivar legacy: dictionary holding legacy xen domain info - @ivar xenapi: dictionary holding xen api config info + """ The new Xend VM Configuration. + + Stores the configuration in xenapi compatible format but retains + import and export functions for SXP. """ - - def __init__(self, filename = None, fd = None, - sxp = None, xml = None, pycfg = None, xenapi_vm = None, - cfg = {}): - """Constructor. Provide either the filename, fd or sxp. - - @keyword filename: filename of an SXP file - @keyword fd: file descriptor of an SXP file - @keyword sxp: a list of list of a parsed SXP - @keyword xml: an XML tree object - @keyword xenapi_vm: a struct passed from an XMLRPC call (Xen API) - @keyword cfg: a dictionary of configuration (eg. from xc) - """ - format = 'unknown' - - self.xenapi = {} - - if filename and not fd: - fd = open(filename, 'r') - - if fd: - format = self._detect_format(fd) - - if fd: - if format == 'sxp': - sxp = self._read_sxp(fd) - elif format == 'python' and filename != None: - pycfg = self._read_python(filename) - elif format == 'python' and filename == None: - raise XendConfigError("Python files must be passed as a " - "filename rather than file descriptor.") - elif format == 'xml': - xml = self._read_xml(fd) - else: - raise XendConfigError("Unable to determine format of file") - - if sxp: - cfg = self._populate_from_sxp(sxp) - if xml: - cfg = self._populate_from_xml(xml) - if pycfg: - cfg = self._populate_from_python_config(pycfg) - if xenapi_vm: - cfg = self._populate_from_xenapi_vm(xenapi_vm) + def __init__(self, filename = None, sxp_obj = None, + xapi = None, dominfo = None): + + dict.__init__(self) + self.update(self._defaults()) + + if filename: + try: + sxp_obj = sxp.parse(open(filename,'r')) + sxp_obj = sxp_obj[0] + except IOError, e: + raise XendConfigError("Unable to read file: %s" % filename) + + if sxp_obj: + self._sxp_to_xapi(sxp_obj) + self._sxp_to_xapi_unsupported(sxp_obj) + elif xapi: + self.update_with_xenapi_config(xapi) + self._add_xapi_unsupported() + elif dominfo: + # output from xc.domain_getinfo + self._dominfo_to_xapi(dominfo) + + log.debug('XendConfig.init: %s' % self) + + # validators go here + self.validate() + + """ In time, we should enable this type checking addition. It is great + also for tracking bugs and unintended writes to XendDomainInfo.info + def __setitem__(self, key, value): + type_conv = XENAPI_CFG_TYPES.get(key) + if callable(type_conv): + try: + dict.__setitem__(self, key, type_conv(value)) + except (ValueError, TypeError): + raise XendConfigError("Wrong type for configuration value " + + "%s. Expected %s" % + (key, type_conv.__name__)) + else: + dict.__setitem__(self, key, value) + """ + + def _defaults(self): + defaults = { + 'uuid': uuid.createString(), + 'name_label': 'Domain-Unnamed', + 'actions_after_shutdown': 'destroy', + 'actions_after_reboot': 'restart', + 'actions_after_crash': 'restart', + 'actions_after_suspend': '', + 'features': '', + 'builder': 'linux', + 'memory_static_min': 0, + 'memory_dynamic_min': 0, + 'shadow_memory': 0, + 'memory_static_max': 0, + 'memory_dynamic_max': 0, + 'memory_actual': 0, + 'boot_method': None, + 'bootloader': None, + 'bootloader_args': None, + 'devices': {}, + 'image': {}, + 'security': None, + 'on_xend_start': 'ignore', + 'on_xend_stop': 'ignore', + 'cpus': [], + 'cpu_weight': 256, + 'cpu_cap': 0, + 'vcpus_number': 1, + 'online_vcpus': 1, + 'max_vcpu_id': 0, + 'vcpu_avail': 1, + 'vif_refs': [], + 'vbd_refs': [], + 'vtpm_refs': [], + } + + defaults['name_label'] = 'Domain-' + defaults['uuid'] + return defaults + + def _memory_sanity_check(self): + if self['memory_static_min'] == 0: + self['memory_static_min'] = self['memory_dynamic_min'] + + # If the static max is not set, let's set it to dynamic max. + # If the static max is smaller than static min, then fix it! + self['memory_static_max'] = max(self['memory_static_max'], + self['memory_dynamic_max'], + self['memory_static_min']) + + for mem_type in ('memory_static_min', 'memory_static_max'): + if self[mem_type] <= 0: + raise XendConfigError('Memory value too low for %s: %d' % + (mem_type, self[mem_type])) + + def _actions_sanity_check(self): + for event in ['shutdown', 'reboot', 'crash']: + if self['actions_after_' + event] not in CONFIG_RESTART_MODES: + raise XendConfigError('Invalid event handling mode: ' + + event) + + def _builder_sanity_check(self): + if self['builder'] not in ('hvm', 'linux'): + raise XendConfigError('Invalid builder configuration') + + def validate(self): + self._memory_sanity_check() + self._actions_sanity_check() + self._builder_sanity_check() + + def _dominfo_to_xapi(self, dominfo): + self['domid'] = dominfo['domid'] + self['online_vcpus'] = dominfo['online_vcpus'] + self['max_vcpu_id'] = dominfo['max_vcpu_id'] + self['memory_dynamic_min'] = (dominfo['mem_kb'] + 1023)/1024 + self['memory_dynamic_max'] = (dominfo['maxmem_kb'] + 1023)/1024 + self['cpu_time'] = dominfo['cpu_time']/1e9 + # TODO: i don't know what the security stuff expects here + if dominfo.get('ssidref'): + self['security'] = [['ssidref', dominfo['ssidref']]] + self['shutdown_reason'] = dominfo['shutdown_reason'] + + # parse state into Xen API states + self['running'] = dominfo['running'] + self['crashed'] = dominfo['crashed'] + self['dying'] = dominfo['dying'] + self['shutdown'] = dominfo['shutdown'] + self['paused'] = dominfo['paused'] + self['blocked'] = dominfo['blocked'] + + if 'name' in dominfo: + self['name_label'] = dominfo['name'] + + if 'handle' in dominfo: + self['uuid'] = uuid.toString(dominfo['handle']) - if cfg: - self.update(cfg) - - if xenapi_vm: - self.xenapi.update(xenapi_vm) - - log.debug('XendConfig: %s' % str(self)) - self.validate() - - # - # Xen API Attribute Access - # - - def __getattr__(self, name): - try: - return dict.__getattr__(self, name) - except AttributeError: - try: - return self.__dict__['xenapi'][name] - except KeyError: - raise AttributeError("XendConfig Xen API has no attribute " - "'%s'" % name) - - - def __setattr__(self, name, value): - try: - return dict.__setattr__(self, name, value) - except AttributeError: - self.xenapi[name] = value - #self.set_legacy_api_with_xen_api_value(name, value) - - def __delattr__(self, name): - try: - dict.__delattr__(self, name) - except AttributeError: - del self.xenapi[name] - #self.del_legacy_api_with_xen_api_key(name) - - - """ - # - # Legacy API Attribute Access - # - - def __getitem__(self, key): - try: - return self.legacy[key] - except KeyError: - raise AttributeError, "XendConfig Legacy has no attribute '%s'"\ - % key - - def __setitem__(self, key, value): - self.legacy[key] = value - self.set_xen_api_with_legacy_api_value(key, value) - - def __delitem__(self, key): - del self.legacy[key] - self.del_xen_api_with_legacy_api_key(key) - """ - - - def _detect_format(self, fd): - """Detect the format of the configuration passed. - - @param fd: file descriptor of contents to detect - @rtype: string, 'sxp', 'xml', 'python' or 'unknown' - """ - format = 'unknown' - - fd.seek(0) - for line in fd: - stripped = line.strip() - if stripped: - if re.search(r'^\(', stripped): - format = 'sxp' - elif re.search(r'^\<?xml', stripped): - format = 'xml' - else: - format = 'python' - break - - fd.seek(0) - return format - - def _read_sxp(self, fd): - """ Read and parse SXP (from SXP to list of lists) - - @rtype: list of lists. - """ - try: - parsed = sxp.parse(fd)[0] - return parsed - except: - raise - return None - - def _read_xml(self, fd): - """TODO: Read and parse XML (from XML to dict) - - @rtype: dict - """ - raise NotImplementedError - - def _read_python(self, filename): - """Read and parse python module that represents the config. - - @rtype: dict - """ - cfg_globals = {} - execfile(filename, cfg_globals, {}) - return cfg_globals - - def _populate_from_sxp(self, parsed): + def _parse_sxp(self, sxp_cfg): """ Populate this XendConfig using the parsed SXP. + @param sxp_cfg: Parsed SXP Configuration + @type sxp_cfg: list of lists @rtype: dictionary + @return: A dictionary containing the parsed options of the SXP. """ cfg = {} # First step is to convert deprecated options to # current equivalents. - restart = sxp.child_value(parsed, 'restart') + restart = sxp.child_value(sxp_cfg, 'restart') if restart: if restart == 'onreboot': cfg['on_poweroff'] = 'destroy' @@ -433,23 +414,19 @@ class XendConfig(dict): 'restart = \'%s\'', restart) # Only extract options we know about. - all_params = VM_CONFIG_ENTRIES + ROUNDTRIPPING_CONFIG_ENTRIES + \ - STATIC_CONFIG_ENTRIES - - for key, typeconv in all_params: - val = sxp.child_value(parsed, key) - if val: + extract_keys = LEGACY_UNSUPPORTED_BY_XENAPI_CFG + extract_keys += XENAPI_CFG_TO_LEGACY_CFG.values() + + for key in extract_keys: + val = sxp.child_value(sxp_cfg, key) + if val != None: try: - cfg[key] = typeconv(val) - except ValueError: - pass - - # Manually extract other complex configuration - # options. - - cfg['backend'] = [] - for c in sxp.children(parsed, 'backend'): - cfg['backend'].append(sxp.name(sxp.child0(c))) + cfg[key] = LEGACY_CFG_TYPES[key](val) + except KeyError: + cfg[key] = val + except (TypeError, ValueError), e: + log.warn("Unable to parse key %s: %s: %s" % + (key, str(val), e)) # Parsing the device SXP's. In most cases, the SXP looks # like this: @@ -472,65 +449,52 @@ class XendConfig(dict): # Hence we deal with pci device configurations outside of # the regular device parsing. - cfg['device'] = {} - for dev in sxp.children(parsed, 'device'): + cfg['devices'] = {} + for dev in sxp.children(sxp_cfg, 'device'): config = sxp.child0(dev) dev_type = sxp.name(config) dev_info = {} if dev_type == 'pci': - continue - - for opt, val in config[1:]: - dev_info[opt] = val - log.debug("XendConfig: reading device: %s" % dev_info) - # create uuid if it doesn't - dev_uuid = dev_info.get('uuid', uuid.createString()) - dev_info['uuid'] = dev_uuid - cfg['device'][dev_uuid] = (dev_type, dev_info) - - # deal with PCI device configurations if they exist - for dev in sxp.children(parsed, 'device'): - config = sxp.child0(dev) - dev_type = sxp.name(config) - - if dev_type != 'pci': - continue - - dev_attr = sxp.child_value(config, 'dev') - if isinstance(dev_attr, (types.ListType, types.TupleType)): + pci_devs_uuid = sxp.child_value(config, 'uuid', + uuid.createString()) + pci_devs = [] for pci_dev in sxp.children(config, 'dev'): - dev_info = {} + pci_dev_info = {} for opt, val in pci_dev[1:]: - dev_info[opt] = val - log.debug("XendConfig: reading device: %s" % dev_info) - dev_uuid = dev_info.get('uuid', uuid.createString()) - dev_info['uuid'] = dev_uuid - cfg['device'][dev_uuid] = (dev_type, dev_info) - - else: # Xen 2.0 PCI device configuration + pci_dev_info[opt] = val + pci_devs.append(pci_dev_info) + + cfg['devices'][pci_devs_uuid] = (dev_type, + {'devs': pci_devs, + 'uuid': pci_devs_uuid}) + + log.debug("XendConfig: reading device: %s" % pci_devs) + else: for opt, val in config[1:]: dev_info[opt] = val log.debug("XendConfig: reading device: %s" % dev_info) # create uuid if it doesn't dev_uuid = dev_info.get('uuid', uuid.createString()) dev_info['uuid'] = dev_uuid - cfg['device'][dev_uuid] = (dev_type, dev_info) + cfg['devices'][dev_uuid] = (dev_type, dev_info) + # Extract missing data from configuration entries - if 'image' in cfg: - image_vcpus = sxp.child_value(cfg['image'], 'vcpus') - if image_vcpus is not None: + image_sxp = sxp.child_value(sxp_cfg, 'image', []) + if image_sxp: + image_vcpus = sxp.child_value(image_sxp, 'vcpus') + if image_vcpus != None: try: - if 'vcpus' not in cfg: - cfg['vcpus'] = int(image_vcpus) - elif cfg['vcpus'] != int(image_vcpus): - cfg['vcpus'] = int(image_vcpus) + if 'vcpus_number' not in cfg: + cfg['vcpus_number'] = int(image_vcpus) + elif cfg['vcpus_number'] != int(image_vcpus): + cfg['vcpus_number'] = int(image_vcpus) log.warn('Overriding vcpus from %d to %d using image' - 'vcpus value.', cfg['vcpus']) + 'vcpus value.', cfg['vcpus_number']) except ValueError, e: raise XendConfigError('integer expeceted: %s: %s' % - str(cfg['image']), e) + image_sxp, e) # Deprecated cpu configuration if 'cpu' in cfg: @@ -564,101 +528,188 @@ class XendConfig(dict): except ValueError, e: raise XendConfigError('cpus = %s: %s' % (cfg['cpus'], e)) - # Parse image SXP outside of image.py - # - used to be only done in image.py - if 'image' in cfg: - cfg['kernel_kernel'] = sxp.child_value(cfg['image'], 'kernel','') - cfg['kernel_initrd'] = sxp.child_value(cfg['image'], 'ramdisk','') - kernel_args = sxp.child_value(cfg['image'], 'args', '') - - # attempt to extract extra arguments from SXP config - arg_ip = sxp.child_value(cfg['image'], 'ip') - if arg_ip: kernel_args += ' ip=%s' % arg_ip - arg_root = sxp.child_value(cfg['image'], 'root') - if arg_root: kernel_args += ' root=%s' % arg_root - - cfg['kernel_args'] = kernel_args + if 'security' in cfg and isinstance(cfg['security'], str): + cfg['security'] = sxp.from_string(cfg['security']) # TODO: get states - old_state = sxp.child_value(parsed, 'state') + old_state = sxp.child_value(sxp_cfg, 'state') if old_state: for i in range(len(CONFIG_OLD_DOM_STATES)): cfg[CONFIG_OLD_DOM_STATES[i]] = int(old_state[i] != '-') - # Xen API extra cfgs - # ------------------ - cfg['vif_refs'] = [] - cfg['vbd_refs'] = [] - cfg['vtpm_refs'] = [] - for dev_uuid, (dev_type, dev_info) in cfg['device'].items(): - if dev_type == 'vif': - cfg['vif_refs'].append(dev_uuid) - elif dev_type in ('vbd','tap'): - cfg['vbd_refs'].append(dev_uuid) - elif dev_type == 'vtpm': - cfg['vtpm_refs'].append(dev_uuid) - return cfg - - - def _populate_from_xenapi_vm(self, xenapi_vm): - cfg = {} - - for cfgkey, apikey in LEGACY_CFG_TO_XENAPI_CFG.items(): + + + def _sxp_to_xapi(self, sxp_cfg): + """Read in an SXP Configuration object and + populate at much of the Xen API with valid values. + """ + cfg = self._parse_sxp(sxp_cfg) + + # Convert parameters that can be directly mapped from + # the Legacy Config to Xen API Config + + for apikey, cfgkey in XENAPI_CFG_TO_LEGACY_CFG.items(): try: - if apikey in XENAPI_INT_CFG: - cfg[cfgkey] = int(xenapi_vm[apikey]) + type_conv = XENAPI_CFG_TYPES.get(apikey) + if callable(type_conv): + self[apikey] = type_conv(cfg[cfgkey]) else: - cfg[cfgkey] = xenapi_vm[apikey] + log.warn("Unconverted key: " + apikey) + self[apikey] = cfg[cfgkey] except KeyError: pass - # Reconstruct image SXP - # TODO: get rid of SXP altogether from here - sxp_image = ['linux'] - if xenapi_vm['kernel_kernel']: - sxp_image.append(['kernel', xenapi_vm['kernel_kernel']]) - if xenapi_vm['kernel_initrd']: - sxp_image.append(['ramdisk', xenapi_vm['kernel_initrd']]) - if xenapi_vm['kernel_args']: - sxp_image.append(['args', xenapi_vm['kernel_args']]) - - cfg['image'] = prettyprintstring(sxp_image) - - # make sure device structures are there. - if 'device' not in cfg: - cfg['device'] = {} - if 'vif_refs' not in cfg: - cfg['vif_refs'] = [] - if 'vbd_refs' not in cfg: - cfg['vbd_refs'] = [] - if 'vtpm_refs' not in cfg: - cfg['vtpm_refs'] = [] - - return cfg - - - def _sync_xen_api_from_legacy_api(self): - """ Sync all the attributes that is supported by the Xen API - from the legacy API configuration. + # Convert Legacy "image" config to Xen API kernel_* + # configuration + image_sxp = sxp.child_value(sxp_cfg, 'image', []) + if image_sxp: + self['kernel_kernel'] = sxp.child_value(image_sxp, 'kernel','') + self['kernel_initrd'] = sxp.child_value(image_sxp, 'ramdisk','') + kernel_args = sxp.child_value(image_sxp, 'args', '') + + # attempt to extract extra arguments from SXP config + arg_ip = sxp.child_value(image_sxp, 'ip') + if arg_ip and not re.search(r'ip=[^ ]+', kernel_args): + kernel_args += ' ip=%s' % arg_ip + arg_root = sxp.child_value(image_sxp, 'root') + if arg_root and not re.search(r'root=[^ ]+', kernel_args): + kernel_args += ' root=%s' % arg_root + + self['kernel_args'] = kernel_args + + # Convert Legacy HVM parameters to Xen API configuration + self['platform_std_vga'] = bool0(cfg.get('stdvga', 0)) + self['platform_serial'] = str(cfg.get('serial', '')) + self['platform_localtime'] = bool0(cfg.get('localtime', 0)) + self['platform_enable_audio'] = bool0(cfg.get('soundhw', 0)) + + # Convert path to bootloader to boot_method + if not cfg.get('bootloader'): + if self.get('kernel_kernel','').endswith('hvmloader'): + self['boot_method'] = 'bios' + else: + self['boot_method'] = 'kernel_external' + else: + self['boot_method'] = 'grub' + + # make sure a sane maximum is set + if self['memory_static_max'] <= 0: + self['memory_static_max'] = self['memory_static_min'] + + self['memory_dynamic_max'] = self['memory_static_max'] + self['memory_dynamic_min'] = self['memory_static_min'] + + # set device references in the configuration + self['devices'] = cfg.get('devices', {}) + + self['vif_refs'] = [] + self['vbd_refs'] = [] + self['vtpm_refs'] = [] + for dev_uuid, (dev_type, dev_info) in self['devices'].items(): + if dev_type == 'vif': + self['vif_refs'].append(dev_uuid) + elif dev_type in ('vbd','tap'): + self['vbd_refs'].append(dev_uuid) + elif dev_type in ('vtpm',): + self['vtpm_refs'].append(dev_uuid) + + + def _sxp_to_xapi_unsupported(self, sxp_cfg): + """Read in an SXP configuration object and populate + values are that not related directly supported in + the Xen API. """ - for cfgkey, apikey in LEGACY_CFG_TO_XENAPI_CFG.items(): - if cfgkey in self: - self.xenapi[apikey] = self[cfgkey] - - def _sync_legacy_api_from_xen_api(self): - for cfgkey, apikey in LEGACY_CFG_TO_XENAPI_CFG.items(): - if apikey in self.xenapi: - self[cfgkey] = self.xenapi[apikey] - - - def _populate_from_xml(self, parsed_xml): - raise NotImplementedError - - def _populate_from_python_config(self, parsed_py): - raise NotImplementedError + + # Parse and convert parameters used to configure + # the image (as well as HVM images) + image_sxp = sxp.child_value(sxp_cfg, 'image', []) + if image_sxp: + image = {} + image['type'] = sxp.name(image_sxp) + for arg, conv in LEGACY_IMAGE_CFG: + val = sxp.child_value(image_sxp, arg, None) + if val != None: + image[arg] = conv(val) + + image_hvm = {} + for arg, conv in LEGACY_IMAGE_HVM_CFG: + val = sxp.child_value(image_sxp, arg, None) + if val != None: + image_hvm[arg] = conv(val) + + image_hvm_devices = {} + for arg, conv in LEGACY_IMAGE_HVM_DEVICES_CFG: + val = sxp.child_value(image_sxp, arg, None) + if val != None: + image_hvm_devices[arg] = conv(val) + + if image_hvm or image_hvm_devices: + image['hvm'] = image_hvm + image['hvm']['devices'] = image_hvm_devices + + self['image'] = image + + for apikey, imgkey in XENAPI_HVM_CFG.items(): + val = sxp.child_value(image_sxp, imgkey, None) + if val != None: + self[apikey] = val + + # extract backend value + + backend = [] + for c in sxp.children(sxp_cfg, 'backend'): + backend.append(sxp.name(sxp.child0(c))) + if backend: + self['backend'] = backend + + if self['image'].has_key('hvm'): + self['builder'] = 'hvm' + + # Parse and convert other Non Xen API parameters. + def _set_cfg_if_exists(sxp_arg): + val = sxp.child_value(sxp_cfg, sxp_arg) + if val != None: + if LEGACY_CFG_TYPES.get(sxp_arg): + self[sxp_arg] = LEGACY_CFG_TYPES[sxp_arg](val) + else: + self[sxp_arg] = val + + _set_cfg_if_exists('shadow_memory') + _set_cfg_if_exists('security') + _set_cfg_if_exists('features') + _set_cfg_if_exists('on_xend_stop') + _set_cfg_if_exists('on_xend_start') + _set_cfg_if_exists('vcpu_avail') + _set_cfg_if_exists('max_vcpu_id') # TODO, deprecated? + + # Parse and store runtime configuration + _set_cfg_if_exists('start_time') + _set_cfg_if_exists('online_vcpus') + _set_cfg_if_exists('cpu_time') + _set_cfg_if_exists('shutdown_reason') + _set_cfg_if_exists('up_time') + _set_cfg_if_exists('status') # TODO, deprecated + + def _add_xapi_unsupported(self): + """Updates the configuration object with entries that are not + officially supported by the Xen API but is required for + the rest of Xend to function. + """ + + # populate image + self['image']['type'] = self['builder'] + if self['builder'] == 'hvm': + self['image']['hvm'] = {} + for xapi, cfgapi in XENAPI_HVM_CFG.items(): + self['image']['hvm'][cfgapi] = self[xapi] + def _get_old_state_string(self): + """Returns the old xm state string. + @rtype: string + @return: old state string + """ state_string = '' for state_name in CONFIG_OLD_DOM_STATES: on_off = self.get(state_name, 0) @@ -669,8 +720,40 @@ class XendConfig(dict): return state_string - def get_sxp(self, domain = None, ignore_devices = False, ignore = []): + + def update_config(self, dominfo): + """Update configuration with the output from xc.domain_getinfo(). + + @param dominfo: Domain information via xc.domain_getinfo() + @type dominfo: dict + """ + self._dominfo_to_xapi(dominfo) + self.validate() + + def update_with_xenapi_config(self, xapi): + """Update configuration with a Xen API VM struct + + @param xapi: Xen API VM Struct + @type xapi: dict + """ + for key, val in xapi.items(): + key = key.lower() + type_conv = XENAPI_CFG_TYPES.get(key) + if callable(type_conv): + self[key] = type_conv(val) + else: + self[key] = val + + self.validate() + + def to_xml(self): + """Return an XML string representing the configuration.""" + pass + + def to_sxp(self, domain = None, ignore_devices = False, ignore = []): """ Get SXP representation of this config object. + + Incompat: removed store_mfn, console_mfn @keyword domain: (optional) XendDomainInfo to get extra information from such as domid and running devices. @@ -688,44 +771,36 @@ class XendConfig(dict): if domain.getDomid() is not None: sxpr.append(['domid', domain.getDomid()]) - for cfg, typefunc in ROUNDTRIPPING_CONFIG_ENTRIES: - if cfg in self: - if self[cfg] is not None: - sxpr.append([cfg, self[cfg]]) - - if 'image' in self and self['image'] is not None: - sxpr.append(['image', self['image']]) - if 'security' in self and self['security']: - sxpr.append(['security', self['security']]) - if 'shutdown_reason' in self: - sxpr.append(['shutdown_reason', self['shutdown_reason']]) - if 'cpu_time' in self: - sxpr.append(['cpu_time', self['cpu_time']/1e9]) - - sxpr.append(['online_vcpus', self['online_vcpus']]) - - if 'start_time' in self: - uptime = time.time() - self['start_time'] - sxpr.append(['up_time', str(uptime)]) - sxpr.append(['start_time', str(self['start_time'])]) - - if domain: - sxpr.append(['status', str(domain.state)]) - else: - sxpr.append(['status', str(DOM_STATE_HALTED)]) + for xenapi, legacy in XENAPI_CFG_TO_LEGACY_CFG.items(): + if self.has_key(xenapi) and self[xenapi] not in (None, []): + if type(self[xenapi]) == bool: + # convert booleans to ints before making an sxp item + sxpr.append([legacy, int(self[xenapi])]) + else: + sxpr.append([legacy, self[xenapi]]) + + for legacy in LEGACY_UNSUPPORTED_BY_XENAPI_CFG: + if legacy in ('domid', 'uuid'): # skip these + continue + if self.has_key(legacy) and self[legacy] not in (None, []): + sxpr.append([legacy, self[legacy]]) + + if 'image' in self and self['image']: + sxpr.append(['image', self.image_sxpr()]) + + sxpr.append(['status', domain.state]) + sxpr.append(['memory_dynamic_min', self.get('memory_dynamic_min')]) + sxpr.append(['memory_dynamic_max', self.get('memory_dynamic_max')]) if domain.getDomid() is not None: sxpr.append(['state', self._get_old_state_string()]) - sxpr.append(['memory_dynamic_max', self.get('memory_dynamic_max', - self['memory'])]) - - # For save/restore migration if domain: if domain.store_mfn: sxpr.append(['store_mfn', domain.store_mfn]) if domain.console_mfn: sxpr.append(['console_mfn', domain.console_mfn]) + # Marshall devices (running or from configuration) if not ignore_devices: @@ -743,7 +818,7 @@ class XendConfig(dict): except: log.exception("dumping sxp from device controllers") pass - + # if we didn't find that device, check the existing config # for a device in the same class if not found: @@ -751,58 +826,28 @@ class XendConfig(dict): if dev_type == cls: sxpr.append(['device', dev_info]) - return sxpr - - def validate(self): - """ Validate the configuration and fill in missing configuration - with defaults. + return sxpr + + def device_add(self, dev_type, cfg_sxp = None, cfg_xenapi = None): + """Add a device configuration in SXP format or XenAPI struct format. + + For SXP, it could be either: + + [device, [vbd, [uname ...]] + + or: + + [vbd, [uname ..]] + + @type cfg_sxp: list of lists (parsed sxp object) + @param cfg_sxp: SXP configuration object + @type cfg_xenapi: dict + @param cfg_xenapi: A device configuration from Xen API (eg. vbd,vif) + @rtype: string + @return: Assigned UUID of the device. """ - - # Fill in default values - for key, default_func in DEFAULT_CONFIGURATION: - if key not in self or self[key] == None: - self[key] = default_func(self) - - # Basic sanity checks - if 'image' in self and isinstance(self['image'], str): - self['image'] = sxp.from_string(self['image']) - if 'security' in self and isinstance(self['security'], str): - self['security'] = sxp.from_string(self['security']) - if self['memory'] == 0 and 'mem_kb' in self: - self['memory'] = (self['mem_kb'] + 1023)/1024 - if self['memory'] <= 0: - raise XendConfigError('Invalid memory size: %s' % - str(self['memory'])) - - self['maxmem'] = max(self['memory'], self['maxmem']) - - # convert mem_kb from domain_getinfo to something more descriptive - if 'mem_kb' in self: - self['memory_dynamic_max'] = (self['mem_kb'] + 1023)/1024 - - # Verify devices - for d_uuid, (d_type, d_info) in self['device'].items(): - if d_type not in XendDevices.valid_devices() and \ - d_type not in XendDevices.pseudo_devices(): - raise XendConfigError('Invalid device (%s)' % d_type) - - # Verify restart modes - for event in ('on_poweroff', 'on_reboot', 'on_crash'): - if self[event] not in CONFIG_RESTART_MODES: - raise XendConfigError('Invalid restart event: %s = %s' % \ - (event, str(self[event]))) - - # Verify that {vif,vbd}_refs are here too - if 'vif_refs' not in self: - self['vif_refs'] = [] - if 'vbd_refs' not in self: - self['vbd_refs'] = [] - if 'vtpm_refs' not in self: - self['vtpm_refs'] = [] - - def device_add(self, dev_type, cfg_sxp = None, cfg_xenapi = None): if dev_type not in XendDevices.valid_devices() and \ - dev_type not in XendDevices.pseudo_devices(): + dev_type not in XendDevices.pseudo_devices(): raise XendConfigError("XendConfig: %s not a valid device type" % dev_type) @@ -816,22 +861,48 @@ class XendConfig(dict): log.debug("XendConfig.device_add: %s" % str(cfg_xenapi)) if cfg_sxp: + if sxp.child0(cfg_sxp) == 'device': + config = sxp.child0(cfg_sxp) + else: + config = cfg_sxp + + dev_type = sxp.name(config) dev_info = {} try: - for opt, val in cfg_sxp[1:]: + for opt, val in config[1:]: dev_info[opt] = val except ValueError: pass # SXP has no options for this device + + def _get_config_ipaddr(config): + val = [] + for ipaddr in sxp.children(config, elt='ip'): + val.append(sxp.child0(ipaddr)) + return val + + if dev_type == 'vif' and 'ip' in dev_info: + dev_info['ip'] = _get_config_ipaddr(config) + + if dev_type == 'vbd': + if dev_info.get('dev', '').startswith('ioemu:'): + dev_info['driver'] = 'ioemu' + else: + dev_info['driver'] = 'paravirtualised' + + # create uuid if it doesn't exist dev_uuid = dev_info.get('uuid', uuid.createString()) dev_info['uuid'] = dev_uuid - self['device'][dev_uuid] = (dev_type, dev_info) - if dev_type in ('vif', 'vbd'): + + # store dev references by uuid for certain device types + self['devices'][dev_uuid] = (dev_type, dev_info) + if dev_type in ('vif', 'vbd', 'vtpm'): self['%s_refs' % dev_type].append(dev_uuid) elif dev_type in ('tap',): self['vbd_refs'].append(dev_uuid) + return dev_uuid if cfg_xenapi: @@ -849,13 +920,21 @@ class XendConfig(dict): dev_uuid = cfg_xenapi.get('uuid', uuid.createString()) dev_info['uuid'] = dev_uuid - self['device'][dev_uuid] = (dev_type, dev_info) + self['devices'][dev_uuid] = (dev_type, dev_info) self['vif_refs'].append(dev_uuid) return dev_uuid - elif dev_type == 'vbd': - dev_info['uname'] = cfg_xenapi.get('image', None) - dev_info['dev'] = '%s:disk' % cfg_xenapi.get('device') + elif dev_type in ('vbd', 'tap'): + if dev_type == 'vbd': + dev_info['uname'] = cfg_xenapi.get('image', '') + dev_info['dev'] = '%s:disk' % cfg_xenapi.get('device') + elif dev_type == 'tap': + dev_info['uname'] = 'tap:qcow:%s' % cfg_xenapi.get('image') + dev_info['dev'] = '%s:disk' % cfg_xenapi.get('device') + + dev_info['driver'] = cfg_xenapi.get('driver') + dev_info['VDI'] = cfg_xenapi.get('VDI', '') + if cfg_xenapi.get('mode') == 'RW': dev_info['mode'] = 'w' else: @@ -863,35 +942,43 @@ class XendConfig(dict): dev_uuid = cfg_xenapi.get('uuid', uuid.createString()) dev_info['uuid'] = dev_uuid - self['device'][dev_uuid] = (dev_type, dev_info) + self['devices'][dev_uuid] = (dev_type, dev_info) self['vbd_refs'].append(dev_uuid) return dev_uuid - elif dev_type == 'vtpm': + elif dev_type in ('vtpm'): if cfg_xenapi.get('type'): dev_info['type'] = cfg_xenapi.get('type') + dev_uuid = cfg_xenapi.get('uuid', uuid.createString()) dev_info['uuid'] = dev_uuid - self['device'][dev_uuid] = (dev_type, dev_info) + self['devices'][dev_uuid] = (dev_type, dev_info) self['vtpm_refs'].append(dev_uuid) return dev_uuid - elif dev_type == 'tap': - dev_info['uname'] = 'tap:qcow:%s' % cfg_xenapi.get('image') - dev_info['dev'] = '%s:disk' % cfg_xenapi.get('device') - - if cfg_xenapi.get('mode') == 'RW': - dev_info['mode'] = 'w' - else: - dev_info['mode'] = 'r' - - dev_uuid = cfg_xenapi.get('uuid', uuid.createString()) - dev_info['uuid'] = dev_uuid - self['device'][dev_uuid] = (dev_type, dev_info) - self['vbd_refs'].append(dev_uuid) - return dev_uuid - return '' + + def device_update(self, dev_uuid, cfg_sxp): + """Update an existing device with the new configuration. + + @rtype: boolean + @return: Returns True if succesfully found and updated a device conf + """ + if dev_uuid in self['devices']: + config = sxp.child0(cfg_sxp) + dev_type = sxp.name(config) + dev_info = {} + + try: + for opt, val in config[1:]: + self['devices'][opt] = val + except ValueError: + pass # SXP has no options for this device + + return True + + return False + def device_sxpr(self, dev_uuid = None, dev_type = None, dev_info = None): """Get Device SXPR by either giving the device UUID or (type, config). @@ -900,8 +987,8 @@ class XendConfig(dict): @return: device config sxpr """ sxpr = [] - if dev_uuid != None and dev_uuid in self['device']: - dev_type, dev_info = self['device'][dev_uuid] + if dev_uuid != None and dev_uuid in self['devices']: + dev_type, dev_info = self['devices'][dev_uuid] if dev_type == None or dev_info == None: raise XendConfigError("Required either UUID or device type and " @@ -917,27 +1004,106 @@ class XendConfig(dict): """Returns the SXPR for all devices in the current configuration.""" sxprs = [] pci_devs = [] - for dev_type, dev_info in self['device'].values(): + + if 'devices' not in self: + return sxprs + + for dev_type, dev_info in self['devices'].values(): if dev_type == 'pci': # special case for pci devices - pci_devs.append(dev_info) + sxpr = [['uuid', dev_info['uuid']]] + for pci_dev_info in dev_info['devs']: + pci_dev_sxpr = ['dev'] + for opt, val in pci_dev_info.items(): + pci_dev_sxpr.append([opt, val]) + sxpr.append(pci_dev_sxpr) + sxprs.append((dev_type, sxpr)) else: sxpr = self.device_sxpr(dev_type = dev_type, dev_info = dev_info) sxprs.append((dev_type, sxpr)) - # if we have any pci_devs, we parse them differently into - # one single pci SXP entry. - if pci_devs: - sxpr = ['pci',] - for dev_info in pci_devs: - dev_sxpr = self.device_sxpr(dev_type = 'dev', - dev_info = dev_info) - sxpr.append(dev_sxpr) - sxprs.append(('pci', sxpr)) - return sxprs - + def image_sxpr(self): + """Returns a backwards compatible image SXP expression that is + used in xenstore's /vm/<uuid>/image value and xm list.""" + image = [self['image'].get('type', 'linux')] + if self.has_key('kernel_kernel'): + image.append(['kernel', self['kernel_kernel']]) + if self.has_key('kernel_initrd') and self['kernel_initrd']: + image.append(['ramdisk', self['kernel_initrd']]) + if self.has_key('kernel_args') and self['kernel_args']: + image.append(['args', self['kernel_args']]) + + for arg, conv in LEGACY_IMAGE_CFG: + if self['image'].has_key(arg): + image.append([arg, self['image'][arg]]) + + if 'hvm' in self['image']: + for arg, conv in LEGACY_IMAGE_HVM_CFG: + if self['image']['hvm'].get(arg): + image.append([arg, self['image']['hvm'][arg]]) + + if 'hvm' in self['image'] and 'devices' in self['image']['hvm']: + for arg, conv in LEGACY_IMAGE_HVM_DEVICES_CFG: + if self['image']['hvm']['devices'].get(arg): + image.append([arg, + self['image']['hvm']['devices'][arg]]) + + return image + + def update_with_image_sxp(self, image_sxp): + # Convert Legacy "image" config to Xen API kernel_* + # configuration + self['kernel_kernel'] = sxp.child_value(image_sxp, 'kernel','') + self['kernel_initrd'] = sxp.child_value(image_sxp, 'ramdisk','') + kernel_args = sxp.child_value(image_sxp, 'args', '') + + # attempt to extract extra arguments from SXP config + arg_ip = sxp.child_value(image_sxp, 'ip') + if arg_ip and not re.search(r'ip=[^ ]+', kernel_args): + kernel_args += ' ip=%s' % arg_ip + arg_root = sxp.child_value(image_sxp, 'root') + if arg_root and not re.search(r'root=', kernel_args): + kernel_args += ' root=%s' % arg_root + self['kernel_args'] = kernel_args + + # Store image SXP in python dictionary format + image = {} + image['type'] = sxp.name(image_sxp) + for arg, conv in LEGACY_IMAGE_CFG: + val = sxp.child_value(image_sxp, arg, None) + if val != None: + image[arg] = conv(val) + + image_hvm = {} + for arg, conv in LEGACY_IMAGE_HVM_CFG: + val = sxp.child_value(image_sxp, arg, None) + if val != None: + image_hvm[arg] = conv(val) + + image_hvm_devices = {} + for arg, conv in LEGACY_IMAGE_HVM_DEVICES_CFG: + val = sxp.child_value(image_sxp, arg, None) + if val != None: + image_hvm_devices[arg] = conv(val) + + if image_hvm or image_hvm_devices: + image['hvm'] = image_hvm + image['hvm']['devices'] = image_hvm_devices + + self['image'] = image + + for apikey, imgkey in XENAPI_HVM_CFG.items(): + val = sxp.child_value(image_sxp, imgkey, None) + if val != None: + type_conv = XENAPI_CFG_TYPES[apikey] + if callable(conv): + self[apikey] = type_conv(val) + else: + self[apikey] = val + + # # debugging # diff -r 6fdbf173142d -r d603aed5ad6d tools/python/xen/xend/XendConstants.py --- a/tools/python/xen/xend/XendConstants.py Sat Dec 02 15:19:50 2006 -0700 +++ b/tools/python/xen/xend/XendConstants.py Mon Dec 04 08:24:41 2006 -0700 @@ -34,6 +34,8 @@ DOMAIN_SHUTDOWN_REASONS = { DOMAIN_CRASH : "crash", DOMAIN_HALT : "halt" } +REVERSE_DOMAIN_SHUTDOWN_REASONS = \ + dict([(y, x) for x, y in DOMAIN_SHUTDOWN_REASONS.items()]) restart_modes = [ "restart", diff -r 6fdbf173142d -r d603aed5ad6d tools/python/xen/xend/XendDevices.py --- a/tools/python/xen/xend/XendDevices.py Sat Dec 02 15:19:50 2006 -0700 +++ b/tools/python/xen/xend/XendDevices.py Mon Dec 04 08:24:41 2006 -0700 @@ -19,7 +19,7 @@ # A collection of DevControllers # -from xen.xend.server import blkif, netif, tpmif, pciif, iopif, irqif, usbif +from xen.xend.server import blkif, netif, tpmif, pciif, iopif, irqif, usbif, vfbif from xen.xend.server.BlktapController import BlktapController class XendDevices: @@ -41,6 +41,8 @@ class XendDevices: 'irq': irqif.IRQController, 'usb': usbif.UsbifController, 'tap': BlktapController, + 'vfb': vfbif.VfbifController, + 'vkbd': vfbif.VkbdifController, } #@classmethod diff -r 6fdbf173142d -r d603aed5ad6d tools/python/xen/xend/XendDomain.py --- a/tools/python/xen/xend/XendDomain.py Sat Dec 02 15:19:50 2006 -0700 +++ b/tools/python/xen/xend/XendDomain.py Mon Dec 04 08:24:41 2006 -0700 @@ -23,6 +23,7 @@ """ import os +import stat import shutil import socket import threading @@ -44,7 +45,7 @@ from xen.xend.XendDevices import XendDev from xen.xend.xenstore.xstransact import xstransact from xen.xend.xenstore.xswatch import xswatch -from xen.util import security +from xen.util import mkdir, security from xen.xend import uuid xc = xen.lowlevel.xc.xc() @@ -99,11 +100,7 @@ class XendDomain: """Singleton initialisation function.""" dom_path = self._managed_path() - try: - os.stat(dom_path) - except OSError: - log.info("Making %s", dom_path) - os.makedirs(dom_path, 0755) + mkdir.parents(dom_path, stat.S_IRWXU) xstransact.Mkdir(XS_VMROOT) xstransact.SetPermissions(XS_VMROOT, {'dom': DOM0_ID}) @@ -184,7 +181,7 @@ class XendDomain: if not dom_uuid: continue - dom_name = dom.get('name', 'Domain-%s' % dom_uuid) + dom_name = dom.get('name_label', 'Domain-%s' % dom_uuid) try: running_dom = self.domain_lookup_nr(dom_name) if not running_dom: @@ -271,25 +268,17 @@ class XendDomain: domains_dir = self._managed_path() dom_uuid = dominfo.get_uuid() domain_config_dir = self._managed_path(dom_uuid) - - # make sure the domain dir exists - if not os.path.exists(domains_dir): - os.makedirs(domains_dir, 0755) - elif not os.path.isdir(domains_dir): - log.error("xend_domain_dir is not a directory.") - raise XendError("Unable to save managed configuration " - "because %s is not a directory." % - domains_dir) - - if not os.path.exists(domain_config_dir): + + def make_or_raise(path): try: - os.makedirs(domain_config_dir, 0755) - except IOError: - log.exception("Failed to create directory: %s" % - domain_config_dir) - raise XendError("Failed to create directory: %s" % - domain_config_dir) - + mkdir.parents(path, stat.S_IRWXU) + except: + log.exception("%s could not be created." % path) + raise XendError("%s could not be created." % path) + + make_or_raise(domains_dir) + make_or_raise(domain_config_dir) + try: sxp_cache_file = open(self._managed_config_path(dom_uuid),'w') prettyprint(dominfo.sxpr(), sxp_cache_file, width = 78) @@ -423,7 +412,6 @@ class XendDomain: self._remove_domain(dom, domid) - def _add_domain(self, info): """Add a domain to the list of running domains @@ -433,6 +421,11 @@ class XendDomain: """ log.debug("Adding Domain: %s" % info.getDomid()) self.domains[info.getDomid()] = info + + # update the managed domains with a new XendDomainInfo object + # if we are keeping track of it. + if info.get_uuid() in self.managed_domains: + self._managed_domain_register(info) def _remove_domain(self, info, domid = None): """Remove the domain from the list of running domains @@ -669,7 +662,7 @@ class XendDomain: self.domains_lock.acquire() try: try: - xeninfo = XendConfig(xenapi_vm = xenapi_vm) + xeninfo = XendConfig(xapi = xenapi_vm) dominfo = XendDomainInfo.createDormant(xeninfo) log.debug("Creating new managed domain: %s: %s" % (dominfo.getName(), dominfo.get_uuid())) @@ -873,8 +866,8 @@ class XendDomain: self.domains_lock.acquire() try: try: - xeninfo = XendConfig(sxp = config) - dominfo = XendDomainInfo.createDormant(xeninfo) + domconfig = XendConfig(sxp_obj = config) + dominfo = XendDomainInfo.createDormant(domconfig) log.debug("Creating new managed domain: %s" % dominfo.getName()) self._managed_domain_register(dominfo) @@ -935,6 +928,9 @@ class XendDomain: if dominfo.state != DOM_STATE_HALTED: raise XendError("Domain is still running") + + log.info("Domain %s (%s) deleted." % + (dominfo.getName(), dominfo.info.get('uuid'))) self._managed_domain_unregister(dominfo) self._remove_domain(dominfo) diff -r 6fdbf173142d -r d603aed5ad6d tools/python/xen/xend/XendDomainInfo.py --- a/tools/python/xen/xend/XendDomainInfo.py Sat Dec 02 15:19:50 2006 -0700 +++ b/tools/python/xen/xend/XendDomainInfo.py Mon Dec 04 08:24:41 2006 -0700 @@ -38,10 +38,9 @@ from xen.util import security from xen.util import security from xen.xend import balloon, sxp, uuid, image, arch -from xen.xend import XendRoot, XendNode +from xen.xend import XendRoot, XendNode, XendConfig from xen.xend.XendBootloader import bootloader -from xen.xend.XendConfig import XendConfig from xen.xend.XendError import XendError, VmError from xen.xend.XendDevices import XendDevices from xen.xend.xenstore.xstransact import xstransact, complete @@ -57,6 +56,11 @@ xroot = XendRoot.instance() log = logging.getLogger("xend.XendDomainInfo") #log.setLevel(logging.TRACE) + + +def bool0(v): + return v != "0" and bool(v) + ## # All parameters of VMs that may be configured on-the-fly, or at start-up. @@ -88,7 +92,7 @@ ROUNDTRIPPING_CONFIG_ENTRIES = [ ('bootloader', str), ('bootloader_args', str), ('features', str), - ('localtime', int), + ('localtime', bool0), ] ROUNDTRIPPING_CONFIG_ENTRIES += VM_CONFIG_PARAMS @@ -145,7 +149,7 @@ def create(config): """ log.debug("XendDomainInfo.create(%s)", config) - vm = XendDomainInfo(XendConfig(sxp = config)) + vm = XendDomainInfo(XendConfig.XendConfig(sxp_obj = config)) try: vm.start() except: @@ -175,10 +179,9 @@ def recreate(info, priv): assert not info['dying'] - xeninfo = XendConfig(cfg = info) + xeninfo = XendConfig.XendConfig(dominfo = info) domid = xeninfo['domid'] - uuid1 = xeninfo['handle'] - xeninfo['uuid'] = uuid.toString(uuid1) + uuid1 = uuid.fromString(xeninfo['uuid']) needs_reinitialising = False dompath = GetDomainPath(domid) @@ -228,6 +231,15 @@ def recreate(info, priv): vm._storeVmDetails() vm._storeDomDetails() + if vm.info['image']: # Only dom0 should be without an image entry when + # recreating, but we cope with missing ones + # elsewhere just in case. + vm.image = image.create(vm, + vm.info, + vm.info['image'], + vm.info['devices']) + vm.image.recreate() + vm._registerWatches() vm.refreshShutdown(xeninfo) return vm @@ -236,7 +248,7 @@ def restore(config): def restore(config): """Create a domain and a VM object to do a restore. - @param config: Domain configuration object + @param config: Domain SXP configuration @type config: list of lists. (see C{create}) @rtype: XendDomainInfo @@ -246,7 +258,8 @@ def restore(config): """ log.debug("XendDomainInfo.restore(%s)", config) - vm = XendDomainInfo(XendConfig(sxp = config), resume = True) + vm = XendDomainInfo(XendConfig.XendConfig(sxp_obj = config), + resume = True) try: vm.resume() return vm @@ -254,24 +267,24 @@ def restore(config): vm.destroy() raise -def createDormant(xeninfo): +def createDormant(domconfig): """Create a dormant/inactive XenDomainInfo without creating VM. This is for creating instances of persistent domains that are not yet start. - @param xeninfo: Parsed configuration - @type xeninfo: dictionary + @param domconfig: Parsed configuration + @type domconfig: XendConfig object @rtype: XendDomainInfo @return: A up and running XendDomainInfo instance @raise XendError: Errors with configuration. """ - log.debug("XendDomainInfo.createDormant(%s)", xeninfo) + log.debug("XendDomainInfo.createDormant(%s)", domconfig) # domid does not make sense for non-running domains. - xeninfo.pop('domid', None) - vm = XendDomainInfo(XendConfig(cfg = xeninfo)) + domconfig.pop('domid', None) + vm = XendDomainInfo(domconfig) return vm def domain_by_name(name): @@ -383,14 +396,6 @@ class XendDomainInfo: #if not self._infoIsSet('uuid'): # self.info['uuid'] = uuid.toString(uuid.create()) - #REMOVE: domid logic can be shortened - #if domid is not None: - # self.domid = domid - #elif info.has_key('dom'): - # self.domid = int(info['dom']) - #else: - # self.domid = None - self.vmpath = XS_VMROOT + self.info['uuid'] self.dompath = dompath @@ -403,6 +408,7 @@ class XendDomainInfo: self.vmWatch = None self.shutdownWatch = None self.shutdownStartTime = None + self._resume = resume self.state = DOM_STATE_HALTED self.state_updated = threading.Condition() @@ -416,8 +422,7 @@ class XendDomainInfo: if augment: self._augmentInfo(priv) - self._checkName(self.info['name']) - self.setResume(resume) + self._checkName(self.info['name_label']) # @@ -477,10 +482,11 @@ class XendDomainInfo: if self.domid == 0: raise XendError('Domain 0 cannot be shutdown') - if not reason in DOMAIN_SHUTDOWN_REASONS.values(): + if reason not in DOMAIN_SHUTDOWN_REASONS.values(): raise XendError('Invalid reason: %s' % reason) - self._storeDom("control/shutdown", reason) - + self._removeVm('xend/previous_restart_time') + self.storeDom("control/shutdown", reason) + def pause(self): """Pause domain @@ -506,18 +512,20 @@ class XendDomainInfo: def send_sysrq(self, key): """ Send a Sysrq equivalent key via xenstored.""" asserts.isCharConvertible(key) - self._storeDom("control/sysrq", '%c' % key) + self.storeDom("control/sysrq", '%c' % key) def device_create(self, dev_config): """Create a new device. @param dev_config: device configuration - @type dev_config: dictionary (parsed config) + @type dev_config: SXP object (parsed config) """ log.debug("XendDomainInfo.device_create: %s" % dev_config) dev_type = sxp.name(dev_config) - devid = self._createDevice(dev_type, dev_config) - self.info.device_add(dev_type, cfg_sxp = dev_config) + dev_uuid = self.info.device_add(dev_type, cfg_sxp = dev_config) + dev_config_dict = self.info['devices'][dev_uuid][1] + log.debug("XendDomainInfo.device_create: %s" % dev_config_dict) + devid = self._createDevice(dev_type, dev_config_dict) self._waitForDevice(dev_type, devid) return self.getDeviceController(dev_type).sxpr(devid) @@ -525,12 +533,26 @@ class XendDomainInfo: """Configure an existing device. @param dev_config: device configuration - @type dev_config: dictionary (parsed config) + @type dev_config: SXP object (parsed config) @param devid: device id @type devid: int + @return: Returns True if successfully updated device + @rtype: boolean """ deviceClass = sxp.name(dev_config) - self._reconfigureDevice(deviceClass, devid, dev_config) + + # look up uuid of the device + dev_control = self.getDeviceController(deviceClass) + dev_sxpr = dev_control.sxpr(devid) + dev_uuid = sxp.child_value(sxpr, 'uuid') + if not dev_uuid: + return False + + self.info.device_update(dev_uuid, dev_config) + dev_config_dict = self.info['devices'].get(dev_uuid) + if dev_config_dict: + dev_control.reconfigureDevice(devid, dev_config_dict[1]) + return True def waitForDevices(self): """Wait for this domain's configured devices to connect. @@ -558,8 +580,18 @@ class XendDomainInfo: return self.getDeviceController(deviceClass).destroyDevice(devid) + def getDeviceSxprs(self, deviceClass): - return self.getDeviceController(deviceClass).sxprs() + if self.state == DOM_STATE_RUNNING: + return self.getDeviceController(deviceClass).sxprs() + else: + sxprs = [] + dev_num = 0 + for dev_type, dev_info in self.info.all_devices_sxpr(): + if dev_type == deviceClass: + sxprs.append([dev_num, dev_info]) + dev_num += 1 + return sxprs def setMemoryTarget(self, target): @@ -567,22 +599,22 @@ class XendDomainInfo: @param target: In MiB. """ log.debug("Setting memory target of domain %s (%d) to %d MiB.", - self.info['name'], self.domid, target) + self.info['name_label'], self.domid, target) if target <= 0: raise XendError('Invalid memory size') - self.info['memory'] = target + self.info['memory_static_min'] = target self.storeVm("memory", target) - self._storeDom("memory/target", target << 10) + self.storeDom("memory/target", target << 10) def getVCPUInfo(self): try: # We include the domain name and ID, to help xm. sxpr = ['domain', ['domid', self.domid], - ['name', self.info['name']], - ['vcpu_count', self.info['online_vcpus']]] + ['name', self.info['name_label']], + ['vcpu_count', self.info['vcpus_number']]] for i in range(0, self.info['max_vcpu_id']+1): info = xc.vcpu_getinfo(self.domid, i) @@ -610,30 +642,40 @@ class XendDomainInfo: values taken from the store. This recovers those values known to xend but not to the hypervisor. """ - def useIfNeeded(name, val): - if not self._infoIsSet(name) and val is not None: - self.info[name] = val - + augment_entries = XendConfig.LEGACY_XENSTORE_VM_PARAMS[:] if priv: - entries = VM_STORE_ENTRIES[:] - entries.remove(('memory', int)) - entries.remove(('maxmem', int)) - else: - entries = VM_STORE_ENTRIES - entries.append(('image', str)) - entries.append(('security', str)) - - map(lambda x, y: useIfNeeded(x[0], y), entries, - self._readVMDetails(entries)) - + augment_entries.remove('memory') + augment_entries.remove('maxmem') + + vm_config = self._readVMDetails([(k, XendConfig.LEGACY_CFG_TYPES[k]) + for k in augment_entries]) + + # make returned lists into a dictionary + vm_config = dict(zip(augment_entries, vm_config)) + + for arg in augment_entries: + xapicfg = arg + val = vm_config[arg] + if val != None: + if arg in XendConfig.LEGACY_CFG_TO_XENAPI_CFG: + xapiarg = XendConfig.LEGACY_CFG_TO_XENAPI_CFG[arg] + self.info[xapiarg] = val + else: + self.info[arg] = val + + # read image value + image_sxp = self._readVm('image') + if image_sxp: + self.info.update_with_image_sxp(sxp.from_string(image_sxp)) + + # read devices devices = [] - for devclass in XendDevices.valid_devices(): devconfig = self.getDeviceController(devclass).configurations() if devconfig: - devices.extend(map(lambda conf: (devclass, conf), devconfig)) - - if not self.info['device'] and devices is not None: + devices.extend(devconfig) + + if not self.info['devices'] and devices is not None: for device in devices: self.info.device_add(device[0], cfg_sxp = device) @@ -660,8 +702,11 @@ class XendDomainInfo: # Function to update xenstore /dom/* # - def _readDom(self, *args): + def readDom(self, *args): return xstransact.Read(self.dompath, *args) + + def gatherDom(self, *args): + return xstransact.Gather(self.dompath, *args) def _writeDom(self, *args): return xstransact.Write(self.dompath, *args) @@ -669,7 +714,7 @@ class XendDomainInfo: def _removeDom(self, *args): return xstransact.Remove(self.dompath, *args) - def _storeDom(self, *args): + def storeDom(self, *args): return xstransact.Store(self.dompath, *args) def _recreateDom(self): @@ -678,16 +723,16 @@ class XendDomainInfo: def _recreateDomFunc(self, t): t.remove() t.mkdir() - t.set_permissions({ 'dom' : self.domid }) + t.set_permissions({'dom' : self.domid}) t.write('vm', self.vmpath) def _storeDomDetails(self): to_store = { 'domid': str(self.domid), 'vm': self.vmpath, - 'name': self.info['name'], + 'name': self.info['name_label'], 'console/limit': str(xroot.get_console_limit() * 1024), - 'memory/target': str(self.info['memory'] * 1024) + 'memory/target': str(self.info['memory_static_min'] * 1024) } def f(n, v): @@ -713,7 +758,7 @@ class XendDomainInfo: return 'offline' result = {} - for v in range(0, self.info['vcpus']): + for v in range(0, self.info['vcpus_number']): result["cpu/%d/availability" % v] = availability(v) return result @@ -735,19 +780,29 @@ class XendDomainInfo: log.trace("XendDomainInfo.storeChanged"); changed = False - - def f(x, y): - if y is not None and self.info[x[0]] != y: - self.info[x[0]] = y - changed = True - - map(f, VM_CONFIG_PARAMS, self._readVMDetails(VM_CONFIG_PARAMS)) - - im = self._readVm('image') - current_im = self.info['image'] - if (im is not None and - (current_im is None or sxp.to_string(current_im) != im)): - self.info['image'] = sxp.from_string(im) + + # Check whether values in the configuration have + # changed in Xenstore. + + cfg_vm = ['name', 'on_poweroff', 'on_reboot', 'on_crash'] + + vm_details = self._readVMDetails([(k,XendConfig.LEGACY_CFG_TYPES[k]) + for k in cfg_vm]) + + # convert two lists into a python dictionary + vm_details = dict(zip(cfg_vm, vm_details)) + + for arg, val in vm_details.items(): + if arg in XendConfig.LEGACY_CFG_TO_XENAPI_CFG: + xapiarg = XendConfig.LEGACY_CFG_TO_XENAPI_CFG[arg] + if val != None and val != self.info[xapiarg]: + self.info[xapiarg] = val + changed= True + + # Check whether image definition has been updated + image_sxp = self._readVm('image') + if image_sxp and image_sxp != self.info.image_sxpr(): + self.info.update_with_image_sxp(sxp.from_string(image_sxp)) changed = True if changed: @@ -760,17 +815,17 @@ class XendDomainInfo: def _handleShutdownWatch(self, _): log.debug('XendDomainInfo.handleShutdownWatch') - reason = self._readDom('control/shutdown') + reason = self.readDom('control/shutdown') if reason and reason != 'suspend': - sst = self._readDom('xend/shutdown_start_time') + sst = self.readDom('xend/shutdown_start_time') now = time.time() if sst: self.shutdownStartTime = float(sst) timeout = float(sst) + SHUTDOWN_TIMEOUT - now else: self.shutdownStartTime = now - self._storeDom('xend/shutdown_start_time', now) + self.storeDom('xend/shutdown_start_time', now) timeout = SHUTDOWN_TIMEOUT log.trace( @@ -791,17 +846,17 @@ class XendDomainInfo: def setName(self, name): self._checkName(name) - self.info['name'] = name + self.info['name_label'] = name self.storeVm("name", name) def getName(self): - return self.info['name'] + return self.info['name_label'] def getDomainPath(self): return self.dompath def getShutdownReason(self): - return self._readDom('control/shutdown') + return self.readDom('control/shutdown') def getStorePort(self): """For use only by image.py and XendCheckpoint.py.""" @@ -816,11 +871,13 @@ class XendDomainInfo: return self.info['features'] def getVCpuCount(self): - return self.info['vcpus'] + return self.info['vcpus_number'] def setVCpuCount(self, vcpus): self.info['vcpu_avail'] = (1 << vcpus) - 1 + self.info['vcpus_number'] = vcpus self.storeVm('vcpu_avail', self.info['vcpu_avail']) + self.storeVm('vcpus', self.info['vcpus_number']) self._writeDom(self._vcpuDomDetails()) def getLabel(self): @@ -828,19 +885,19 @@ class XendDomainInfo: def getMemoryTarget(self): """Get this domain's target memory size, in KB.""" - return self.info['memory'] * 1024 + return self.info['memory_static_min'] * 1024 def getResume(self): - return "%s" % self.info['resume'] + return str(self._resume) def getCap(self): - return self.info['cpu_cap'] + return self.info.get('cpu_cap', 0) def getWeight(self): return self.info['cpu_weight'] def setResume(self, state): - self.info['resume'] = state + self._resume = state def getRestartCount(self): return self._readVm('xend/restart_count') @@ -885,13 +942,13 @@ class XendDomainInfo: return elif xeninfo['crashed']: - if self._readDom('xend/shutdown_completed'): + if self.readDom('xend/shutdown_completed'): # We've seen this shutdown already, but we are preserving # the domain for debugging. Leave it alone. return log.warn('Domain has crashed: name=%s id=%d.', - self.info['name'], self.domid) + self.info['name_label'], self.domid) if xroot.get_enable_dump(): self.dumpCore() @@ -901,7 +958,7 @@ class XendDomainInfo: elif xeninfo['shutdown']: self._stateSet(DOM_STATE_SHUTDOWN) - if self._readDom('xend/shutdown_completed'): + if self.readDom('xend/shutdown_completed'): # We've seen this shutdown already, but we are preserving # the domain for debugging. Leave it alone. return @@ -910,7 +967,7 @@ class XendDomainInfo: reason = shutdown_reason(xeninfo['shutdown_reason']) log.info('Domain has shutdown: name=%s id=%d reason=%s.', - self.info['name'], self.domid, reason) + self.info['name_label'], self.domid, reason) self._clearRestart() @@ -945,7 +1002,7 @@ class XendDomainInfo: if timeout < 0: log.info( "Domain shutdown timeout expired: name=%s id=%s", - self.info['name'], self.domid) + self.info['name_label'], self.domid) self.destroy() finally: self.refresh_shutdown_lock.release() @@ -965,11 +1022,23 @@ class XendDomainInfo: def _maybeRestart(self, reason): # Dispatch to the correct method based upon the configured on_{reason} # behaviour. - {"destroy" : self.destroy, - "restart" : self._restart, - "preserve" : self._preserve, - "rename-restart" : self._renameRestart}[self.info['on_' + reason]]() - + actions = {"destroy" : self.destroy, + "restart" : self._restart, + "preserve" : self._preserve, + "rename-restart" : self._renameRestart} + + action_conf = { + 'poweroff': 'actions_after_shutdown', + 'reboot': 'actions_after_reboot', + 'crash': 'actions_after_crash', + } + + action_target = self.info.get(action_conf.get(reason)) + func = actions.get(action_target, None) + if func and callable(func): + func() + else: + self.destroy() # default to destroy def _renameRestart(self): self._restart(True) @@ -1008,7 +1077,7 @@ class XendDomainInfo: log.error( 'VM %s restarting too fast (%f seconds since the last ' 'restart). Refusing to restart to avoid loops.', - self.info['name'], timeout) + self.info['name_label'], timeout) self.destroy() return @@ -1055,11 +1124,11 @@ class XendDomainInfo: new_uuid = uuid.createString() new_name = 'Domain-%s' % new_uuid log.info("Renaming dead domain %s (%d, %s) to %s (%s).", - self.info['name'], self.domid, self.info['uuid'], + self.info['name_label'], self.domid, self.info['uuid'], new_name, new_uuid) self._unwatchVm() self._releaseDevices() - self.info['name'] = new_name + self.info['name_label'] = new_name self.info['uuid'] = new_uuid self.vmpath = XS_VMROOT + new_uuid self._storeVmDetails() @@ -1067,10 +1136,10 @@ class XendDomainInfo: def _preserve(self): - log.info("Preserving dead domain %s (%d).", self.info['name'], + log.info("Preserving dead domain %s (%d).", self.info['name_label'], self.domid) self._unwatchVm() - self._storeDom('xend/shutdown_completed', 'True') + self.storeDom('xend/shutdown_completed', 'True') self._stateSet(DOM_STATE_HALTED) # @@ -1084,7 +1153,7 @@ class XendDomainInfo: if not corefile: this_time = time.strftime("%Y-%m%d-%H%M.%S", time.localtime()) corefile = "/var/xen/dump/%s-%s.%s.core" % (this_time, - self.info['name'], self.domid) + self.info['name_label'], self.domid) if os.path.isdir(corefile): raise XendError("Cannot dump core in a directory: %s" % @@ -1095,7 +1164,7 @@ class XendDomainInfo: corefile_incomp = corefile+'-incomplete' os.rename(corefile, corefile_incomp) log.exception("XendDomainInfo.dumpCore failed: id = %s name = %s", - self.domid, self.info['name']) + self.domid, self.info['name_label']) raise XendError("Failed to dump core: %s" % str(ex)) # @@ -1117,8 +1186,8 @@ class XendDomainInfo: @raise: VmError for invalid devices """ - for (devclass, config) in self.info.all_devices_sxpr(): - if devclass in XendDevices.valid_devices(): + for (devclass, config) in self.info.get('devices', {}).values(): + if devclass in XendDevices.valid_devices(): log.info("createDevice: %s : %s" % (devclass, config)) self._createDevice(devclass, config) @@ -1139,7 +1208,7 @@ class XendDomainInfo: # there's nothing more we can do. log.exception( "Device release failed: %s; %s; %s", - self.info['name'], devclass, dev) + self.info['name_label'], devclass, dev) if t.commit(): break @@ -1211,11 +1280,12 @@ class XendDomainInfo: log.debug('XendDomainInfo.constructDomain') - hvm = (self._infoIsSet('image') and - sxp.name(self.info['image']) == "hvm") + image_cfg = self.info.get('image', {}) + hvm = image_cfg.has_key('hvm') + if hvm: info = xc.xeninfo() - if not 'hvm' in info['xen_caps']: + if 'hvm' not in info['xen_caps']: raise VmError("HVM guest support is unavailable: is VT/AMD-V " "supported by your CPU and enabled in your " "BIOS?") @@ -1228,14 +1298,14 @@ class XendDomainInfo: if self.domid < 0: raise VmError('Creating domain failed: name=%s' % - self.info['name']) + self.info['name_label']) self.dompath = GetDomainPath(self.domid) self._recreateDom() # Set maximum number of vcpus in domain - xc.domain_max_vcpus(self.domid, int(self.info['vcpus'])) + xc.domain_max_vcpus(self.domid, int(self.info['vcpus_number'])) def _introduceDomain(self): @@ -1256,7 +1326,7 @@ class XendDomainInfo: # if we have a boot loader but no image, then we need to set things # up by running the boot loader non-interactively - if self._infoIsSet('bootloader') and not self._infoIsSet('image'): + if self.info.get('bootloader') and self.info.get('image'): self._configureBootloader() if not self._infoIsSet('image'): @@ -1264,11 +1334,12 @@ class XendDomainInfo: try: self.image = image.create(self, + self.info, self.info['image'], - self.info.all_devices_sxpr()) - - localtime = self.info.get('localtime', 0) - if localtime is not None and localtime == 1: + self.info['devices']) + + localtime = self.info.get('localtime', False) + if localtime: xc.domain_set_time_offset(self.domid) xc.domain_setcpuweight(self.domid, self.info['cpu_weight']) @@ -1284,12 +1355,12 @@ class XendDomainInfo: # the various headrooms necessary, given the raw configured # values. maxmem, memory, and shadow are all in KiB. maxmem = self.image.getRequiredAvailableMemory( - self.info['maxmem'] * 1024) + self.info['memory_static_min'] * 1024) memory = self.image.getRequiredAvailableMemory( - self.info['memory'] * 1024) + self.info['memory_static_max'] * 1024) shadow = self.image.getRequiredShadowMemory( self.info['shadow_memory'] * 1024, - self.info['maxmem'] * 1024) + self.info['memory_static_max'] * 1024) # Round shadow up to a multiple of a MiB, as shadow_mem_control # takes MiB and we must not round down and end up under-providing. @@ -1317,7 +1388,7 @@ class XendDomainInfo: self._createDevices() - if self.info['bootloader'] not in [None, 'kernel_external']: + if self.info['bootloader']: self.image.cleanupBootloading() self.info['start_time'] = time.time() @@ -1325,7 +1396,7 @@ class XendDomainInfo: self._stateSet(DOM_STATE_RUNNING) except RuntimeError, exn: log.exception("XendDomainInfo.initDomain: exception occurred") - if self.info['bootloader'] not in [None, 'kernel_external'] \ + if self.info['bootloader'] not in (None, 'kernel_external') \ and self.image is not None: self.image.cleanupBootloading() raise VmError(str(exn)) @@ -1338,7 +1409,6 @@ class XendDomainInfo: self.refresh_shutdown_lock.acquire() try: self.unwatchShutdown() - self._releaseDevices() if self.image: @@ -1459,14 +1529,14 @@ class XendDomainInfo: def _configureBootloader(self): """Run the bootloader if we're configured to do so.""" - if not self.info['bootloader']: + if not self.info.get('bootloader'): return blcfg = None # FIXME: this assumes that we want to use the first disk device - for (n, c) in self.info.all_devices_sxpr(): - if not n or not c or not(n in ["vbd", "tap"]): + for devuuid, (devtype, devinfo) in self.info.all_devices_sxpr(): + if not devtype or not devinfo or devtype not in ('vbd', 'tap'): continue - disk = sxp.child_value(c, "uname") + disk = devinfo.get('uname') if disk is None: continue fn = blkdev_uname_to_file(disk) @@ -1478,7 +1548,8 @@ class XendDomainInfo: msg = "Had a bootloader specified, but can't find disk" log.error(msg) raise VmError(msg) - self.info['image'] = blcfg + + self.info.update_with_image_sxp(blcfg) # # VM Functions @@ -1516,7 +1587,8 @@ class XendDomainInfo: if arch.type == "x86": # 1MB per vcpu plus 4Kib/Mib of RAM. This is higher than # the minimum that Xen would allocate if no value were given. - overhead_kb = self.info['vcpus'] * 1024 + self.info['maxmem'] * 4 + overhead_kb = self.info['vcpus_number'] * 1024 + \ + self.info['memory_static_max'] * 4 overhead_kb = ((overhead_kb + 1023) / 1024) * 1024 # The domain might already have some shadow memory overhead_kb -= xc.shadow_mem_control(self.domid) * 1024 @@ -1558,12 +1630,15 @@ class XendDomainInfo: def _storeVmDetails(self): to_store = {} - for k in VM_STORE_ENTRIES: - if self._infoIsSet(k[0]): - to_store[k[0]] = str(self.info[k[0]]) - - if self._infoIsSet('image'): - to_store['image'] = sxp.to_string(self.info['image']) + for key in XendConfig.LEGACY_XENSTORE_VM_PARAMS: + info_key = XendConfig.LEGACY_CFG_TO_XENAPI_CFG.get(key, key) + if self._infoIsSet(info_key): + to_store[key] = str(self.info[info_key]) + + if self.info.get('image'): + image_sxpr = self.info.image_sxpr() + if image_sxpr: + to_store['image'] = sxp.to_string(image_sxpr) if self._infoIsSet('security'): secinfo = self.info['security'] @@ -1633,8 +1708,9 @@ class XendDomainInfo: raise VmError('Invalid VM Name') dom = XendDomain.instance().domain_lookup_nr(name) - if dom and dom != self and not dom.info['dying']: - raise VmError("VM name '%s' already exists" % name) + if dom and dom.info['uuid'] != self.info['uuid']: + raise VmError("VM name '%s' already exists as domain %s" % + (name, str(dom.domid))) def update(self, info = None, refresh = True): @@ -1656,6 +1732,7 @@ class XendDomainInfo: #create new security element self.info.update({'security': [['ssidref', str(info['ssidref'])]]}) + #ssidref field not used any longer if 'ssidref' in info: info.pop('ssidref') @@ -1663,8 +1740,7 @@ class XendDomainInfo: # make sure state is reset for info # TODO: we should eventually get rid of old_dom_states - self.info.update(info) - self.info.validate() + self.info.update_config(info) if refresh: self.refreshShutdown(info) @@ -1673,11 +1749,11 @@ class XendDomainInfo: str(self.domid), self.info) def sxpr(self, ignore_store = False): - result = self.info.get_sxp(domain = self, + result = self.info.to_sxp(domain = self, ignore_devices = ignore_store) if not ignore_store and self.dompath: - vnc_port = self._readDom('console/vnc-port') + vnc_port = self.readDom('console/vnc-port') if vnc_port is not None: result.append(['device', ['console', ['vnc-port', str(vnc_port)]]]) @@ -1695,9 +1771,15 @@ class XendDomainInfo: return dom_uuid def get_memory_static_max(self): - return self.info['maxmem'] + return self.info.get('memory_static_max') def get_memory_static_min(self): - return self.info['memory'] + return self.info.get('memory_static_min') + def get_memory_dynamic_max(self): + return self.info.get('memory_dynamic_min') + def get_memory_dynamic_min(self): + return self.info.get('memory_dynamic_max') + + def get_vcpus_policy(self): sched_id = xc.sched_id_get() if sched_id == xen.lowlevel.xc.XEN_SCHEDULER_SEDF: @@ -1713,31 +1795,29 @@ class XendDomainInfo: def get_bios_boot(self): return '' # TODO def get_platform_std_vga(self): - return False + return self.info.get('platform_std_vga', False) def get_platform_keymap(self): return '' def get_platform_serial(self): - return '' # TODO + return self.info.get('platform_serial', '') def get_platform_localtime(self): - return False # TODO + return self.info.get('platform_localtime', False) def get_platform_clock_offset(self): - return False # TODO + return self.info.get('platform_clock_offset', False) def get_platform_enable_audio(self): - return False # TODO + return self.info.get('platform_enable_audio', False) + def get_platform_keymap(self): + return self.info.get('platform_keymap', '') def get_builder(self): - return 'Linux' # TODO + return self.info.get('builder', 0) def get_boot_method(self): - bootloader = self.info['bootloader'] - if not bootloader or bootloader not in XEN_API_BOOT_TYPE: - return 'kernel_external' - return bootloader - + return self.info.get('boot_method', '') def get_kernel_image(self): - return self.info['kernel_kernel'] + return self.info.get('kernel_kernel', '') def get_kernel_initrd(self): - return self.info['kernel_initrd'] + return self.info.get('kernel_initrd', '') def get_kernel_args(self): - return self.info['kernel_args'] + return self.info.get('kernel_args', '') def get_grub_cmdline(self): return '' # TODO def get_pci_bus(self): @@ -1748,25 +1828,26 @@ class XendDomainInfo: return {} # TODO def get_on_shutdown(self): - after_shutdown = self.info.get('on_poweroff') + after_shutdown = self.info.get('action_after_shutdown') if not after_shutdown or after_shutdown not in XEN_API_ON_NORMAL_EXIT: return XEN_API_ON_NORMAL_EXIT[-1] return after_shutdown def get_on_reboot(self): - after_reboot = self.info.get('on_reboot') + after_reboot = self.info.get('action_after_reboot') if not after_reboot or after_reboot not in XEN_API_ON_NORMAL_EXIT: return XEN_API_ON_NORMAL_EXIT[-1] return after_reboot def get_on_suspend(self): - after_suspend = self.info.get('on_suspend') # TODO: not supported + # TODO: not supported + after_suspend = self.info.get('action_after_suspend') if not after_suspend or after_suspend not in XEN_API_ON_NORMAL_EXIT: return XEN_API_ON_NORMAL_EXIT[-1] return after_suspend def get_on_crash(self): - after_crash = self.info.get('on_crash') + after_crash = self.info.get('action_after_crash') if not after_crash or after_crash not in XEN_API_ON_CRASH_BEHAVIOUR: return XEN_API_ON_CRASH_BEHAVIOUR[0] return after_crash @@ -1780,7 +1861,7 @@ class XendDomainInfo: @rtype: dictionary """ - dev_type_config = self.info['device'].get(dev_uuid) + dev_type_config = self.info['devices'].get(dev_uuid) # shortcut if the domain isn't started because # the devcontrollers will have no better information @@ -1840,7 +1921,7 @@ class XendDomainInfo: config['IO_bandwidth_incoming_kbs'] = 0.0 config['IO_bandwidth_outgoing_kbs'] = 0.0 - if dev_class =='vbd': + if dev_class == 'vbd': config['VDI'] = '' # TODO config['device'] = config.get('dev', '') config['driver'] = 'paravirtualised' # TODO @@ -1984,8 +2065,8 @@ class XendDomainInfo: def __str__(self): return '<domain id=%s name=%s memory=%s state=%s>' % \ - (str(self.domid), self.info['name'], - str(self.info['memory']), DOM_STATES[self.state]) + (str(self.domid), self.info['name_label'], + str(self.info['memory_static_min']), DOM_STATES[self.state]) __repr__ = __str__ diff -r 6fdbf173142d -r d603aed5ad6d tools/python/xen/xend/XendLogging.py --- a/tools/python/xen/xend/XendLogging.py Sat Dec 02 15:19:50 2006 -0700 +++ b/tools/python/xen/xend/XendLogging.py Mon Dec 04 08:24:41 2006 -0700 @@ -16,13 +16,15 @@ # Copyright (C) 2005, 2006 XenSource Ltd. #============================================================================ - +import os +import stat import tempfile import types import logging import logging.handlers import fcntl +from xen.util import mkdir from xen.xend.server import params @@ -80,6 +82,7 @@ def init(filename, level): global logfilename def openFileHandler(fname): + mkdir.parents(os.path.dirname(fname), stat.S_IRWXU) return XendRotatingFileHandler(fname, mode = 'a', maxBytes = MAX_BYTES, backupCount = BACKUP_COUNT) diff -r 6fdbf173142d -r d603aed5ad6d tools/python/xen/xend/XendStorageRepository.py --- a/tools/python/xen/xend/XendStorageRepository.py Sat Dec 02 15:19:50 2006 -0700 +++ b/tools/python/xen/xend/XendStorageRepository.py Mon Dec 04 08:24:41 2006 -0700 @@ -19,10 +19,12 @@ # The default QCOW Xen API Storage Repository # +import commands import os -import commands +import stat import threading +from xen.util import mkdir from xen.xend import uuid from xen.xend.XendError import XendError from xen.xend.XendVDI import * @@ -98,10 +100,7 @@ class XendStorageRepository: """ self.lock.acquire() try: - # create directory if /var/lib/xend/storage does not exist - if not os.path.exists(XEND_STORAGE_DIR): - os.makedirs(XEND_STORAGE_DIR) - os.chmod(XEND_STORAGE_DIR, 0700) + mkdir.parents(XEND_STORAGE_DIR, stat.S_IRWXU) # scan the directory and populate self.images total_used = 0 diff -r 6fdbf173142d -r d603aed5ad6d tools/python/xen/xend/image.py --- a/tools/python/xen/xend/image.py Sat Dec 02 15:19:50 2006 -0700 +++ b/tools/python/xen/xend/image.py Mon Dec 04 08:24:41 2006 -0700 @@ -23,7 +23,7 @@ import signal import signal import xen.lowlevel.xc -from xen.xend import sxp +from xen.xend.XendConstants import REVERSE_DOMAIN_SHUTDOWN_REASONS from xen.xend.XendError import VmError, XendError from xen.xend.XendLogging import log from xen.xend.server.netif import randomMAC @@ -31,19 +31,18 @@ from xen.xend import arch from xen.xend import arch from xen.xend import FlatDeviceTree - xc = xen.lowlevel.xc.xc() - MAX_GUEST_CMDLINE = 1024 -def create(vm, imageConfig, deviceConfig): +def create(vm, vmConfig, imageConfig, deviceConfig): """Create an image handler for a vm. @return ImageHandler instance """ - return findImageHandlerClass(imageConfig)(vm, imageConfig, deviceConfig) + return findImageHandlerClass(imageConfig)(vm, vmConfig, imageConfig, + deviceConfig) class ImageHandler: @@ -66,34 +65,20 @@ class ImageHandler: ostype = None - def __init__(self, vm, imageConfig, deviceConfig): + def __init__(self, vm, vmConfig, imageConfig, deviceConfig): self.vm = vm self.kernel = None self.ramdisk = None self.cmdline = None - self.configure(imageConfig, deviceConfig) - - def configure(self, imageConfig, _): + self.configure(vmConfig, imageConfig, deviceConfig) + + def configure(self, vmConfig, imageConfig, _): """Config actions common to all unix-like domains.""" - - def get_cfg(name, default = None): - return sxp.child_value(imageConfig, name, default) - - self.kernel = get_cfg("kernel") - self.cmdline = "" - ip = get_cfg("ip") - if ip: - self.cmdline += " ip=" + ip - root = get_cfg("root") - if root: - self.cmdline += " root=" + root - args = get_cfg("args") - if args: - self.cmdline += " " + args - self.ramdisk = get_cfg("ramdisk", '') - + self.kernel = vmConfig['kernel_kernel'] + self.cmdline = vmConfig['kernel_args'] + self.ramdisk = vmConfig['kernel_initrd'] self.vm.storeVm(("image/ostype", self.ostype), ("image/kernel", self.kernel), ("image/cmdline", self.cmdline), @@ -181,6 +166,10 @@ class ImageHandler: pass + def recreate(self): + pass + + class LinuxImageHandler(ImageHandler): ostype = "linux" @@ -214,8 +203,8 @@ class PPC_LinuxImageHandler(LinuxImageHa ostype = "linux" - def configure(self, imageConfig, deviceConfig): - LinuxImageHandler.configure(self, imageConfig, deviceConfig) + def configure(self, vmConfig, imageConfig, deviceConfig): + LinuxImageHandler.configure(self, vmConfig, imageConfig, deviceConfig) self.imageConfig = imageConfig def buildDomain(self): @@ -248,37 +237,42 @@ class PPC_LinuxImageHandler(LinuxImageHa class HVMImageHandler(ImageHandler): - def __init__(self, vm, imageConfig, deviceConfig): - ImageHandler.__init__(self, vm, imageConfig, deviceConfig) + ostype = "hvm" + + def __init__(self, vm, vmConfig, imageConfig, deviceConfig): + ImageHandler.__init__(self, vm, vmConfig, imageConfig, deviceConfig) self.shutdownWatch = None - - def configure(self, imageConfig, deviceConfig): - ImageHandler.configure(self, imageConfig, deviceConfig) + self.rebootFeatureWatch = None + + def configure(self, vmConfig, imageConfig, deviceConfig): + ImageHandler.configure(self, vmConfig, imageConfig, deviceConfig) info = xc.xeninfo() - if not 'hvm' in info['xen_caps']: + if 'hvm' not in info['xen_caps']: raise VmError("HVM guest support is unavailable: is VT/AMD-V " "supported by your CPU and enabled in your BIOS?") self.dmargs = self.parseDeviceModelArgs(imageConfig, deviceConfig) - self.device_model = sxp.child_value(imageConfig, 'device_model') + self.device_model = imageConfig['hvm'].get('device_model') if not self.device_model: raise VmError("hvm: missing device model") - self.display = sxp.child_value(imageConfig, 'display') - self.xauthority = sxp.child_value(imageConfig, 'xauthority') - self.vncconsole = sxp.child_value(imageConfig, 'vncconsole') + + self.display = imageConfig['hvm'].get('display') + self.xauthority = imageConfig['hvm'].get('xauthority') + self.vncconsole = imageConfig['hvm'].get('vncconsole') self.vm.storeVm(("image/dmargs", " ".join(self.dmargs)), ("image/device-model", self.device_model), ("image/display", self.display)) - self.pid = 0 + self.pid = None self.dmargs += self.configVNC(imageConfig) - self.pae = int(sxp.child_value(imageConfig, 'pae', 1)) - self.acpi = int(sxp.child_value(imageConfig, 'acpi', 1)) - self.apic = int(sxp.child_value(imageConfig, 'apic', 1)) + self.pae = imageConfig['hvm'].get('pae', 0) + self.apic = imageConfig['hvm'].get('apic', 0) + self.acpi = imageConfig['hvm']['devices'].get('acpi', 0) + def buildDomain(self): store_evtchn = self.vm.getStorePort() @@ -295,6 +289,7 @@ class HVMImageHandler(ImageHandler): log.debug("apic = %d", self.apic) self.register_shutdown_watch() + self.register_reboot_feature_watch() return xc.hvm_build(domid = self.vm.getDomid(), image = self.kernel, @@ -312,8 +307,10 @@ class HVMImageHandler(ImageHandler): 'localtime', 'serial', 'stdvga', 'isa', 'vcpus', 'acpi', 'usb', 'usbdevice', 'keymap' ] ret = [] + hvmDeviceConfig = imageConfig['hvm']['devices'] + for a in dmargs: - v = sxp.child_value(imageConfig, a) + v = hvmDeviceConfig.get(a) # python doesn't allow '-' in variable names if a == 'stdvga': a = 'std-vga' @@ -328,7 +325,7 @@ class HVMImageHandler(ImageHandler): ret.append("-%s" % a) ret.append("%s" % v) - if a in ['fda', 'fdb' ]: + if a in ['fda', 'fdb']: if v: if not os.path.isabs(v): raise VmError("Floppy file %s does not exist." % v) @@ -336,26 +333,27 @@ class HVMImageHandler(ImageHandler): # Handle disk/network related options mac = None - ret = ret + ["-domain-name", "%s" % self.vm.info['name']] + ret = ret + ["-domain-name", str(self.vm.info['name_label'])] nics = 0 - for (name, info) in deviceConfig: - if name == 'vbd': - uname = sxp.child_value(info, 'uname') + + for devuuid, (devtype, devinfo) in deviceConfig.items(): + if devtype == 'vbd': + uname = devinfo['uname'] if uname is not None and 'file:' in uname: (_, vbdparam) = string.split(uname, ':', 1) if not os.path.isfile(vbdparam): raise VmError('Disk image does not exist: %s' % vbdparam) - if name == 'vif': - type = sxp.child_value(info, 'type') - if type != 'ioemu': + if devtype == 'vif': + dtype = devinfo.get('type', 'ioemu') + if dtype != 'ioemu': continue nics += 1 - mac = sxp.child_value(info, 'mac') + mac = devinfo.get('mac') if mac == None: mac = randomMAC() - bridge = sxp.child_value(info, 'bridge', 'xenbr0') - model = sxp.child_value(info, 'model', 'rtl8139') + bridge = devinfo.get('bridge', 'xenbr0') + model = devinfo.get('model', 'rtl8139') ret.append("-net") ret.append("nic,vlan=%d,macaddr=%s,model=%s" % (nics, mac, model)) @@ -363,31 +361,32 @@ class HVMImageHandler(ImageHandler): ret.append("tap,vlan=%d,bridge=%s" % (nics, bridge)) return ret - def configVNC(self, config): + def configVNC(self, imageConfig): # Handle graphics library related options - vnc = sxp.child_value(config, 'vnc') - sdl = sxp.child_value(config, 'sdl') + vnc = imageConfig.get('vnc') + sdl = imageConfig.get('sdl') ret = [] - nographic = sxp.child_value(config, 'nographic') + nographic = imageConfig.get('nographic') # get password from VM config (if password omitted, None) - vncpasswd_vmconfig = sxp.child_value(config, 'vncpasswd') + vncpasswd_vmconfig = imageConfig.get('vncpasswd') if nographic: ret.append('-nographic') return ret if vnc: - vncdisplay = int(sxp.child_value(config, 'vncdisplay', - self.vm.getDomid())) - - vncunused = sxp.child_value(config, 'vncunused') + vncdisplay = imageConfig.get('vncdisplay', + int(self.vm.getDomid())) + vncunused = imageConfig.get('vncunused') + if vncunused: ret += ['-vncunused'] else: ret += ['-vnc', '%d' % vncdisplay] - vnclisten = sxp.child_value(config, 'vnclisten') + vnclisten = imageConfig.get('vnclisten') + if not(vnclisten): vnclisten = (xen.xend.XendRoot.instance(). get_vnclisten_address()) @@ -423,21 +422,37 @@ class HVMImageHandler(ImageHandler): if self.vncconsole: args = args + ([ "-vncviewer" ]) log.info("spawning device models: %s %s", self.device_model, args) + # keep track of pid and spawned options to kill it later self.pid = os.spawnve(os.P_NOWAIT, self.device_model, args, env) + self.vm.storeDom("image/device-model-pid", self.pid) log.info("device model pid: %d", self.pid) + def recreate(self): + self.register_shutdown_watch() + self.register_reboot_feature_watch() + self.pid = self.vm.gatherDom(('image/device-model-pid', int)) + def destroy(self): - self.unregister_shutdown_watch(); - if not self.pid: - return - os.kill(self.pid, signal.SIGKILL) - os.waitpid(self.pid, 0) - self.pid = 0 + self.unregister_shutdown_watch() + self.unregister_reboot_feature_watch(); + if self.pid: + try: + os.kill(self.pid, signal.SIGKILL) + except OSError, exn: + log.exception(exn) + try: + os.waitpid(self.pid, 0) + except OSError, exn: + # This is expected if Xend has been restarted within the + # life of this domain. In this case, we can kill the process, + # but we can't wait for it because it's not our child. + pass + self.pid = None def register_shutdown_watch(self): """ add xen store watch on control/shutdown """ - self.shutdownWatch = xswatch(self.vm.dompath + "/control/shutdown", \ - self.hvm_shutdown) + self.shutdownWatch = xswatch(self.vm.dompath + "/control/shutdown", + self.hvm_shutdown) log.debug("hvm shutdown watch registered") def unregister_shutdown_watch(self): @@ -456,27 +471,54 @@ class HVMImageHandler(ImageHandler): """ watch call back on node control/shutdown, if node changed, this function will be called """ - from xen.xend.XendConstants import DOMAIN_SHUTDOWN_REASONS xd = xen.xend.XendDomain.instance() try: vm = xd.domain_lookup( self.vm.getDomid() ) except XendError: # domain isn't registered, no need to clean it up. - return + return False reason = vm.getShutdownReason() log.debug("hvm_shutdown fired, shutdown reason=%s", reason) - for x in DOMAIN_SHUTDOWN_REASONS.keys(): - if DOMAIN_SHUTDOWN_REASONS[x] == reason: - vm.info['shutdown'] = 1 - vm.info['shutdown_reason'] = x - vm.refreshShutdown(vm.info) - - return 1 # Keep watching + if reason in REVERSE_DOMAIN_SHUTDOWN_REASONS: + vm.info['shutdown'] = 1 + vm.info['shutdown_reason'] = \ + REVERSE_DOMAIN_SHUTDOWN_REASONS[reason] + vm.refreshShutdown(vm.info) + + return True # Keep watching + + def register_reboot_feature_watch(self): + """ add xen store watch on control/feature-reboot """ + self.rebootFeatureWatch = xswatch(self.vm.dompath + "/control/feature-reboot", \ + self.hvm_reboot_feature) + log.debug("hvm reboot feature watch registered") + + def unregister_reboot_feature_watch(self): + """Remove the watch on the control/feature-reboot, if any. Nothrow + guarantee.""" + + try: + if self.rebootFeatureWatch: + self.rebootFeatureWatch.unwatch() + except: + log.exception("Unwatching hvm reboot feature watch failed.") + self.rebootFeatureWatch = None + log.debug("hvm reboot feature watch unregistered") + + def hvm_reboot_feature(self, _): + """ watch call back on node control/feature-reboot, + if node changed, this function will be called + """ + status = self.vm.readDom('control/feature-reboot') + log.debug("hvm_reboot_feature fired, module status=%s", status) + if status == '1': + self.unregister_shutdown_watch() + + return True # Keep watching + class IA64_HVM_ImageHandler(HVMImageHandler): - - ostype = "hvm" def getRequiredAvailableMemory(self, mem_kb): page_kb = 16 @@ -489,8 +531,6 @@ class IA64_HVM_ImageHandler(HVMImageHand return 0 class X86_HVM_ImageHandler(HVMImageHandler): - - ostype = "hvm" def getRequiredAvailableMemory(self, mem_kb): # Add 8 MiB overhead for QEMU's video RAM. @@ -529,10 +569,10 @@ def findImageHandlerClass(image): @param image config @return ImageHandler subclass or None """ - type = sxp.name(image) - if type is None: + image_type = image['type'] + if image_type is None: raise VmError('missing image type') try: - return _handlers[arch.type][type] + return _handlers[arch.type][image_type] except KeyError: - raise VmError('unknown image type: ' + type) + raise VmError('unknown image type: ' + image_type) diff -r 6fdbf173142d -r d603aed5ad6d tools/python/xen/xend/server/DevController.py --- a/tools/python/xen/xend/server/DevController.py Sat Dec 02 15:19:50 2006 -0700 +++ b/tools/python/xen/xend/server/DevController.py Mon Dec 04 08:24:41 2006 -0700 @@ -17,6 +17,7 @@ #============================================================================ from threading import Event +import types from xen.xend import sxp from xen.xend.XendError import VmError @@ -86,7 +87,7 @@ class DevController: import xen.xend.XendDomain xd = xen.xend.XendDomain.instance() - backdom_name = sxp.child_value(config, 'backend') + backdom_name = config.get('backend') if backdom_name is None: backdom = xen.xend.XendDomain.DOM0_ID else: @@ -223,7 +224,7 @@ class DevController: configDict = self.getDeviceConfiguration(devid) sxpr = [self.deviceClass] for key, val in configDict.items(): - if type(val) == type(list()): + if isinstance(val, (types.ListType, types.TupleType)): for v in val: sxpr.append([key, v]) else: @@ -405,7 +406,7 @@ class DevController: import xen.xend.XendDomain xd = xen.xend.XendDomain.instance() - backdom_name = sxp.child_value(config, 'backend') + backdom_name = config.get('backend') if backdom_name: backdom = xd.domain_lookup_nr(backdom_name) else: diff -r 6fdbf173142d -r d603aed5ad6d tools/python/xen/xend/server/SrvDaemon.py --- a/tools/python/xen/xend/server/SrvDaemon.py Sat Dec 02 15:19:50 2006 -0700 +++ b/tools/python/xen/xend/server/SrvDaemon.py Mon Dec 04 08:24:41 2006 -0700 @@ -21,6 +21,7 @@ import xen.lowlevel.xc from xen.xend.XendLogging import log from xen.xend import osdep +from xen.util import mkdir import relocate import SrvServer @@ -108,8 +109,7 @@ class Daemon: # so _before_ we close stderr. try: parent = os.path.dirname(XEND_DEBUG_LOG) - if not os.path.exists(parent): - os.makedirs(parent, stat.S_IRWXU) + mkdir.parents(parent, stat.S_IRWXU) fd = os.open(XEND_DEBUG_LOG, os.O_WRONLY|os.O_CREAT|os.O_APPEND) except Exception, exn: print >>sys.stderr, exn diff -r 6fdbf173142d -r d603aed5ad6d tools/python/xen/xend/server/SrvServer.py --- a/tools/python/xen/xend/server/SrvServer.py Sat Dec 02 15:19:50 2006 -0700 +++ b/tools/python/xen/xend/server/SrvServer.py Mon Dec 04 08:24:41 2006 -0700 @@ -154,7 +154,7 @@ def create(): if api_cfg: try: addrs = [(str(x[0]).split(':'), - len(x) > 1 and x[1] or XendAPI.AUTH_NONE, + len(x) > 1 and x[1] or XendAPI.AUTH_PAM, len(x) > 2 and x[2] and map(re.compile, x[2].split(" ")) or None) for x in api_cfg] diff -r 6fdbf173142d -r d603aed5ad6d tools/python/xen/xend/server/blkif.py --- a/tools/python/xen/xend/server/blkif.py Sat Dec 02 15:19:50 2006 -0700 +++ b/tools/python/xen/xend/server/blkif.py Mon Dec 04 08:24:41 2006 -0700 @@ -21,7 +21,6 @@ import string from xen.util import blkif from xen.util import security -from xen.xend import sxp from xen.xend.XendError import VmError from xen.xend.server.DevController import DevController @@ -37,9 +36,9 @@ class BlkifController(DevController): def getDeviceDetails(self, config): """@see DevController.getDeviceDetails""" - uname = sxp.child_value(config, 'uname', '') - dev = sxp.child_value(config, 'dev', '') - + uname = config.get('uname', '') + dev = config.get('dev', '') + if 'ioemu:' in dev: (_, dev) = string.split(dev, ':', 1) try: @@ -59,17 +58,17 @@ class BlkifController(DevController): except ValueError: (typ, params) = ("", "") - mode = sxp.child_value(config, 'mode', 'r') + mode = config.get('mode', 'r') if mode not in ('r', 'w', 'w!'): raise VmError('Invalid mode') - back = { 'dev' : dev, - 'type' : typ, - 'params' : params, - 'mode' : mode - } + back = {'dev' : dev, + 'type' : typ, + 'params' : params, + 'mode' : mode, + } - uuid = sxp.child_value(config, 'uuid') + uuid = config.get('uuid') if uuid: back['uuid'] = uuid diff -r 6fdbf173142d -r d603aed5ad6d tools/python/xen/xend/server/iopif.py --- a/tools/python/xen/xend/server/iopif.py Sat Dec 02 15:19:50 2006 -0700 +++ b/tools/python/xen/xend/server/iopif.py Mon Dec 04 08:24:41 2006 -0700 @@ -22,7 +22,6 @@ import types import xen.lowlevel.xc -from xen.xend import sxp from xen.xend.XendError import VmError from xen.xend.server.DevController import DevController @@ -49,13 +48,12 @@ class IOPortsController(DevController): def __init__(self, vm): DevController.__init__(self, vm) - def getDeviceDetails(self, config): """@see DevController.getDeviceDetails""" def get_param(field): try: - val = sxp.child_value(config, field) + val = config.get(field) if not val: raise VmError('ioports: Missing %s config setting' % field) diff -r 6fdbf173142d -r d603aed5ad6d tools/python/xen/xend/server/irqif.py --- a/tools/python/xen/xend/server/irqif.py Sat Dec 02 15:19:50 2006 -0700 +++ b/tools/python/xen/xend/server/irqif.py Mon Dec 04 08:24:41 2006 -0700 @@ -45,7 +45,7 @@ class IRQController(DevController): def get_param(field): try: - val = sxp.child_value(config, field) + val = config.get(field) if not val: raise VmError('irq: Missing %s config setting' % field) diff -r 6fdbf173142d -r d603aed5ad6d tools/python/xen/xend/server/netif.py --- a/tools/python/xen/xend/server/netif.py Sat Dec 02 15:19:50 2006 -0700 +++ b/tools/python/xen/xend/server/netif.py Mon Dec 04 08:24:41 2006 -0700 @@ -24,7 +24,6 @@ import random import random import re -from xen.xend import sxp from xen.xend import XendRoot from xen.xend.server.DevController import DevController @@ -139,22 +138,15 @@ class NetifController(DevController): def getDeviceDetails(self, config): """@see DevController.getDeviceDetails""" - def _get_config_ipaddr(config): - val = [] - for ipaddr in sxp.children(config, elt='ip'): - val.append(sxp.child0(ipaddr)) - return val - script = os.path.join(xroot.network_script_dir, - sxp.child_value(config, 'script', - xroot.get_vif_script())) - typ = sxp.child_value(config, 'type') - bridge = sxp.child_value(config, 'bridge') - mac = sxp.child_value(config, 'mac') - vifname = sxp.child_value(config, 'vifname') - rate = sxp.child_value(config, 'rate') - uuid = sxp.child_value(config, 'uuid') - ipaddr = _get_config_ipaddr(config) + config.get('script', xroot.get_vif_script())) + typ = config.get('type') + bridge = config.get('bridge') + mac = config.get('mac') + vifname = config.get('vifname') + rate = config.get('rate') + uuid = config.get('uuid') + ipaddr = config.get('ip') devid = self.allocateDeviceID() diff -r 6fdbf173142d -r d603aed5ad6d tools/python/xen/xend/server/pciif.py --- a/tools/python/xen/xend/server/pciif.py Sat Dec 02 15:19:50 2006 -0700 +++ b/tools/python/xen/xend/server/pciif.py Mon Dec 04 08:24:41 2006 -0700 @@ -53,60 +53,29 @@ class PciController(DevController): def getDeviceDetails(self, config): """@see DevController.getDeviceDetails""" - #log.debug('pci config='+sxp.to_string(config)) - - def get_param(config, field, default=None): + def parse_hex(val): try: - val = sxp.child_value(config, field) - - if not val: - if default==None: - raise VmError('pci: Missing %s config setting' % field) - else: - return default - if isinstance(val, types.StringTypes): return int(val, 16) else: return val - except: - if default==None: - raise VmError('pci: Invalid config setting %s: %s' % - (field, val)) - else: - return default - + except ValueError: + return None + back = {} + pcidevid = 0 + for pci_config in config.get('devs', []): + domain = parse_hex(pci_config.get('domain', 0)) + bus = parse_hex(pci_config.get('bus', 0)) + slot = parse_hex(pci_config.get('slot', 0)) + func = parse_hex(pci_config.get('func', 0)) + self.setupDevice(domain, bus, slot, func) + back['dev-%i' % pcidevid] = "%04x:%02x:%02x.%02x" % \ + (domain, bus, slot, func) + pcidevid += 1 - val = sxp.child_value(config, 'dev') - if isinstance(val, (types.ListType, types.TupleType)): - pcidevid = 0 - for dev_config in sxp.children(config, 'dev'): - domain = get_param(dev_config, 'domain', 0) - bus = get_param(dev_config,'bus') - slot = get_param(dev_config,'slot') - func = get_param(dev_config,'func') - - self.setupDevice(domain, bus, slot, func) - - back['dev-%i' % pcidevid]="%04x:%02x:%02x.%02x"% \ - (domain, bus, slot, func) - pcidevid+=1 - - back['num_devs']=str(pcidevid) - - else: - # Xen 2.0 configuration compatibility - domain = get_param(config, 'domain', 0) - bus = get_param(config, 'bus') - slot = get_param(config, 'dev') - func = get_param(config, 'func') - - self.setupDevice(domain, bus, slot, func) - - back['dev-0']="%04x:%02x:%02x.%02x"%(domain, bus, slot, func) - back['num_devs']=str(1) - + back['num_devs']=str(pcidevid) + back['uuid'] = config.get('uuid','') return (0, back, {}) def getDeviceConfiguration(self, devid): @@ -129,7 +98,8 @@ class PciController(DevController): 'slot': '0x%(slot)s' % pci_dev_info, 'func': '0x%(func)s' % pci_dev_info}) - result['dev'] = pci_devs + result['devs'] = pci_devs + result['uuid'] = self.readBackend(devid, 'uuid') return result def configuration(self, devid): @@ -142,7 +112,8 @@ class PciController(DevController): sxpr = [self.deviceClass] # remove devs - devs = configDict.pop('dev', []) + devs = configDict.pop('devs', []) + for dev in devs: dev_sxpr = ['dev'] for dev_item in dev.items(): diff -r 6fdbf173142d -r d603aed5ad6d tools/python/xen/xend/server/pciquirk.py --- a/tools/python/xen/xend/server/pciquirk.py Sat Dec 02 15:19:50 2006 -0700 +++ b/tools/python/xen/xend/server/pciquirk.py Mon Dec 04 08:24:41 2006 -0700 @@ -15,25 +15,24 @@ class PCIQuirk: self.device = device self.subvendor = subvendor self.subdevice = subdevice - self.domain = domain - self.bus = bus - self.slot = slot - self.func = func + self.domain = domain + self.bus = bus + self.slot = slot + self.func = func self.devid = "%04x:%04x:%04x:%04x" % (vendor, device, subvendor, subdevice) - self.pciid = "%04x:%02x:%02x.%01x" % (domain, bus, slot, func) + self.pciid = "%04x:%02x:%02x.%01x" % (domain, bus, slot, func) + self.quirks = self.__getQuirksByID() - self.quirks = self.__getQuirksByID( ) - - self.__sendQuirks( ) - self.__sendPermDevs( ) + self.__sendQuirks() + self.__sendPermDevs() def __matchPCIdev( self, list ): ret = False if list == None: return False for id in list: - if id.startswith( self.devid[:9] ): # id's vendor and device ID match + if id.startswith(self.devid[:9]): # id's vendor and device ID match skey = id.split(':') size = len(skey) if (size == 2): # subvendor/subdevice not suplied @@ -41,13 +40,13 @@ class PCIQuirk: break elif (size == 4): # check subvendor/subdevice # check subvendor - subven = '%04x' % self.subvendor + subven = '%04x' % self.subvendor if ((skey[2] != 'FFFF') and (skey[2] != 'ffff') and (skey[2] != subven)): continue # check subdevice - subdev = '%04x' % self.subdevice + subdev = '%04x' % self.subdevice if ((skey[3] != 'FFFF') and (skey[3] != 'ffff') and (skey[3] != subdev)): @@ -101,8 +100,8 @@ class PCIQuirk: self.slot, self.func, quirk) ) f.close() except Exception, e: - raise VmError("pci: failed to open/write/close quirks sysfs " + \ - "node - " + str(e)) + raise VmError("pci: failed to open/write/close quirks " + + "sysfs node - " + str(e)) def __devIsUnconstrained( self ): if os.path.exists(PERMISSIVE_CONFIG_FILE): @@ -126,20 +125,22 @@ class PCIQuirk: devices = child_at(child(pci_perm_dev_config, 'unconstrained_dev_ids'),0) if self.__matchPCIdev( devices ): - log.debug("Permissive mode enabled for PCI device [%s]" % self.devid) + log.debug("Permissive mode enabled for PCI device [%s]" % + self.devid) return True - log.debug("Permissive mode NOT enabled for PCI device [%s]" % self.devid) + log.debug("Permissive mode NOT enabled for PCI device [%s]" % + self.devid) return False def __sendPermDevs(self): if self.__devIsUnconstrained( ): - log.debug("Unconstrained device: %04x:%02x:%02x.%1x" % (self.domain, - self.bus, self.slot, self.func)) + log.debug("Unconstrained device: %04x:%02x:%02x.%1x" % + (self.domain, self.bus, self.slot, self.func)) try: f = file(PERMISSIVE_SYSFS_NODE ,"w") f.write( "%04x:%02x:%02x.%1x" % (self.domain, self.bus, - self.slot, self.func) ) + self.slot, self.func)) f.close() except Exception, e: - raise VmError("pci: failed to open/write/close permissive " + \ - "sysfs node: " + str(e)) + raise VmError("pci: failed to open/write/close permissive " + + "sysfs node: " + str(e)) diff -r 6fdbf173142d -r d603aed5ad6d tools/python/xen/xend/server/tests/test_controllers.py --- a/tools/python/xen/xend/server/tests/test_controllers.py Sat Dec 02 15:19:50 2006 -0700 +++ b/tools/python/xen/xend/server/tests/test_controllers.py Mon Dec 04 08:24:41 2006 -0700 @@ -21,11 +21,11 @@ class test_controllers(unittest.TestCase def testNetif(self): controller = self.controllerInstance(netif.NetifController) - self.assertNetif(controller.getDeviceDetails(['vif']), None) + self.assertNetif(controller.getDeviceDetails({}), None) self.assertNetif( - controller.getDeviceDetails( - ['vif', ['mac', 'aa:bb:cc:dd:ee:ff']]), + controller.getDeviceDetails({'mac': 'aa:bb:cc:dd:ee:ff'}), 'aa:bb:cc:dd:ee:ff') + def assertNetif(self, results, expectedMac): diff -r 6fdbf173142d -r d603aed5ad6d tools/python/xen/xend/server/tpmif.py --- a/tools/python/xen/xend/server/tpmif.py Sat Dec 02 15:19:50 2006 -0700 +++ b/tools/python/xen/xend/server/tpmif.py Mon Dec 04 08:24:41 2006 -0700 @@ -18,10 +18,8 @@ # Copyright (C) 2005 XenSource Ltd #============================================================================ -"""Support for virtual TPM interfaces. -""" +"""Support for virtual TPM interfaces.""" -from xen.xend import sxp from xen.xend import XendRoot from xen.xend.XendLogging import log from xen.xend.XendError import XendError @@ -49,12 +47,12 @@ class TPMifController(DevController): """@see DevController.getDeviceDetails""" devid = self.allocateDeviceID() - inst = int(sxp.child_value(config, 'pref_instance', '-1')) + inst = int(config.get('pref_instance', -1)) if inst == -1: - inst = int(sxp.child_value(config, 'instance' , '0')) + inst = int(config.get('instance', 0)) - typ = sxp.child_value(config, 'type') - uuid = sxp.child_value(config, 'uuid') + typ = config.get('type') + uuid = config.get('uuid') log.info("The domain has a TPM with pref. instance %d and devid %d.", inst, devid) diff -r 6fdbf173142d -r d603aed5ad6d tools/python/xen/xm/create.py --- a/tools/python/xen/xm/create.py Sat Dec 02 15:19:50 2006 -0700 +++ b/tools/python/xen/xm/create.py Mon Dec 04 08:24:41 2006 -0700 @@ -284,6 +284,18 @@ gopts.var('usbport', val='PATH', use="""Add a physical USB port to a domain, as specified by the path to that port. This option may be repeated to add more than one port.""") +gopts.var('vfb', val="type={vnc,sdl},vncunused=1,vncdisplay=N,vnclisten=ADDR,display=DISPLAY,xauthority=XAUTHORITY", + fn=append_value, default=[], + use="""Make the domain a framebuffer backend. + The backend type should be either sdl or vnc. + For type=vnc, connect an external vncviewer. The server will listen + on ADDR (default 127.0.0.1) on port N+5900. N defaults to the + domain id. If vncunused=1, the server will try to find an arbitrary + unused port above 5900. + For type=sdl, a viewer will be started automatically using the + given DISPLAY and XAUTHORITY, which default to the current user's + ones.""") + gopts.var('vif', val="type=TYPE,mac=MAC,bridge=BRIDGE,ip=IPADDR,script=SCRIPT,backend=DOM,vifname=NAME", fn=append_value, default=[], use="""Add a network interface with the given MAC address and bridge. @@ -512,8 +524,8 @@ def configure_image(vals): config_image.append(['args', vals.extra]) if vals.builder == 'hvm': - configure_hvm(config_image, vals) - + configure_hvm(config_image, vals) + return config_image def configure_disks(config_devs, vals): @@ -564,6 +576,23 @@ def configure_usb(config_devs, vals): config_usb = ['usbport', ['path', path]] config_devs.append(['device', config_usb]) +def configure_vfbs(config_devs, vals): + for f in vals.vfb: + d = comma_sep_kv_to_dict(f) + config = ['vfb'] + if not d.has_key("type"): + d['type'] = 'sdl' + for (k,v) in d.iteritems(): + if not k in [ 'vnclisten', 'vncunused', 'vncdisplay', 'display', + 'xauthority', 'type' ]: + err("configuration option %s unknown to vfbs" % k) + config.append([k,v]) + if not d.has_key("display") and os.environ.has_key("DISPLAY"): + config.append(["display", os.environ['DISPLAY']]) + if not d.has_key("xauthority"): + config.append(["xauthority", get_xauthority()]) + config_devs.append(['device', ['vkbd']]) + config_devs.append(['device', config]) def configure_security(config, vals): """Create the config for ACM security labels. @@ -742,6 +771,7 @@ def make_config(vals): configure_vifs(config_devs, vals) configure_usb(config_devs, vals) configure_vtpm(config_devs, vals) + configure_vfbs(config_devs, vals) configure_security(config, vals) config += config_devs diff -r 6fdbf173142d -r d603aed5ad6d tools/python/xen/xm/main.py --- a/tools/python/xen/xm/main.py Sat Dec 02 15:19:50 2006 -0700 +++ b/tools/python/xen/xm/main.py Mon Dec 04 08:24:41 2006 -0700 @@ -581,8 +581,8 @@ def parse_doms_info(info): return { 'domid' : get_info('domid', str, ''), 'name' : get_info('name', str, '??'), - 'mem' : get_info('memory_dynamic_max', int, 0), - 'vcpus' : get_info('online_vcpus', int, 0), + 'mem' : get_info('memory_dynamic_min', int, 0), + 'vcpus' : get_info('vcpus', int, 0), 'state' : get_info('state', str, ''), 'cpu_time' : get_info('cpu_time', float, 0), 'up_time' : get_info('up_time', float, -1), diff -r 6fdbf173142d -r d603aed5ad6d tools/tests/test_x86_emulator.c --- a/tools/tests/test_x86_emulator.c Sat Dec 02 15:19:50 2006 -0700 +++ b/tools/tests/test_x86_emulator.c Mon Dec 04 08:24:41 2006 -0700 @@ -17,12 +17,14 @@ typedef int64_t s64; #define PFEC_write_access (1U<<1) -static int read_any( - unsigned long addr, +static int read( + unsigned int seg, + unsigned long offset, unsigned long *val, unsigned int bytes, struct x86_emulate_ctxt *ctxt) { + unsigned long addr = offset; switch ( bytes ) { case 1: *val = *(u8 *)addr; break; @@ -33,12 +35,14 @@ static int read_any( return X86EMUL_CONTINUE; } -static int write_any( - unsigned long addr, +static int write( + unsigned int seg, + unsigned long offset, unsigned long val, unsigned int bytes, struct x86_emulate_ctxt *ctxt) { + unsigned long addr = offset; switch ( bytes ) { case 1: *(u8 *)addr = (u8)val; break; @@ -49,13 +53,15 @@ static int write_any( return X86EMUL_CONTINUE; } -static int cmpxchg_any( - unsigned long addr, +static int cmpxchg( + unsigned int seg, + unsigned long offset, unsigned long old, unsigned long new, unsigned int bytes, struct x86_emulate_ctxt *ctxt) { + unsigned long addr = offset; switch ( bytes ) { case 1: *(u8 *)addr = (u8)new; break; @@ -66,21 +72,27 @@ static int cmpxchg_any( return X86EMUL_CONTINUE; } -static int cmpxchg8b_any( - unsigned long addr, +static int cmpxchg8b( + unsigned int seg, + unsigned long offset, unsigned long old_lo, unsigned long old_hi, unsigned long new_lo, unsigned long new_hi, struct x86_emulate_ctxt *ctxt) { + unsigned long addr = offset; ((unsigned long *)addr)[0] = new_lo; ((unsigned long *)addr)[1] = new_hi; return X86EMUL_CONTINUE; } static struct x86_emulate_ops emulops = { - read_any, write_any, read_any, write_any, cmpxchg_any, cmpxchg8b_any + .read = read, + .insn_fetch = read, + .write = write, + .cmpxchg = cmpxchg, + .cmpxchg8b = cmpxchg8b }; int main(int argc, char **argv) @@ -108,7 +120,7 @@ int main(int argc, char **argv) regs.eip = (unsigned long)&instr[0]; regs.ecx = 0x12345678; regs.error_code = PFEC_write_access; - ctxt.cr2 = (unsigned long)res; + regs.eax = (unsigned long)res; *res = 0x7FFFFFFF; rc = x86_emulate_memop(&ctxt, &emulops); if ( (rc != 0) || @@ -127,7 +139,7 @@ int main(int argc, char **argv) #else regs.ecx = 0x12345678UL; #endif - ctxt.cr2 = (unsigned long)res; + regs.eax = (unsigned long)res; regs.error_code = 0; rc = x86_emulate_memop(&ctxt, &emulops); if ( (rc != 0) || @@ -142,7 +154,7 @@ int main(int argc, char **argv) regs.eflags = 0x200; regs.eip = (unsigned long)&instr[0]; regs.ecx = ~0UL; - ctxt.cr2 = (unsigned long)res; + regs.eax = (unsigned long)res; regs.error_code = 0; rc = x86_emulate_memop(&ctxt, &emulops); if ( (rc != 0) || @@ -152,13 +164,13 @@ int main(int argc, char **argv) goto fail; printf("okay\n"); - printf("%-40s", "Testing lock cmpxchgb %%cl,(%%eax)..."); - instr[0] = 0xf0; instr[1] = 0x0f; instr[2] = 0xb0; instr[3] = 0x08; + printf("%-40s", "Testing lock cmpxchgb %%cl,(%%ebx)..."); + instr[0] = 0xf0; instr[1] = 0x0f; instr[2] = 0xb0; instr[3] = 0x0b; regs.eflags = 0x200; regs.eip = (unsigned long)&instr[0]; regs.eax = 0x92345677UL; regs.ecx = 0xAA; - ctxt.cr2 = (unsigned long)res; + regs.ebx = (unsigned long)res; regs.error_code = PFEC_write_access; rc = x86_emulate_memop(&ctxt, &emulops); if ( (rc != 0) || @@ -169,13 +181,13 @@ int main(int argc, char **argv) goto fail; printf("okay\n"); - printf("%-40s", "Testing lock cmpxchgb %%cl,(%%eax)..."); - instr[0] = 0xf0; instr[1] = 0x0f; instr[2] = 0xb0; instr[3] = 0x08; + printf("%-40s", "Testing lock cmpxchgb %%cl,(%%ebx)..."); + instr[0] = 0xf0; instr[1] = 0x0f; instr[2] = 0xb0; instr[3] = 0x0b; regs.eflags = 0x200; regs.eip = (unsigned long)&instr[0]; regs.eax = 0xAABBCC77UL; regs.ecx = 0xFF; - ctxt.cr2 = (unsigned long)res; + regs.ebx = (unsigned long)res; regs.error_code = PFEC_write_access; rc = x86_emulate_memop(&ctxt, &emulops); if ( (rc != 0) || @@ -192,7 +204,7 @@ int main(int argc, char **argv) regs.eflags = 0x200; regs.eip = (unsigned long)&instr[0]; regs.ecx = 0x12345678; - ctxt.cr2 = (unsigned long)res; + regs.eax = (unsigned long)res; regs.error_code = PFEC_write_access; rc = x86_emulate_memop(&ctxt, &emulops); if ( (rc != 0) || @@ -203,14 +215,14 @@ int main(int argc, char **argv) goto fail; printf("okay\n"); - printf("%-40s", "Testing lock cmpxchgl %%ecx,(%%eax)..."); - instr[0] = 0xf0; instr[1] = 0x0f; instr[2] = 0xb1; instr[3] = 0x08; + printf("%-40s", "Testing lock cmpxchgl %%ecx,(%%ebx)..."); + instr[0] = 0xf0; instr[1] = 0x0f; instr[2] = 0xb1; instr[3] = 0x0b; regs.eflags = 0x200; *res = 0x923456AA; regs.eip = (unsigned long)&instr[0]; regs.eax = 0x923456AAUL; regs.ecx = 0xDDEEFF00L; - ctxt.cr2 = (unsigned long)res; + regs.ebx = (unsigned long)res; regs.error_code = PFEC_write_access; rc = x86_emulate_memop(&ctxt, &emulops); if ( (rc != 0) || @@ -230,7 +242,6 @@ int main(int argc, char **argv) regs.esi = (unsigned long)res + 0; regs.edi = (unsigned long)res + 2; regs.error_code = 0; /* read fault */ - ctxt.cr2 = regs.esi; rc = x86_emulate_memop(&ctxt, &emulops); if ( (rc != 0) || (*res != 0x44554455) || @@ -248,13 +259,28 @@ int main(int argc, char **argv) regs.eflags = 0x200; regs.eip = (unsigned long)&instr[0]; regs.edi = (unsigned long)res; - ctxt.cr2 = regs.edi; regs.error_code = PFEC_write_access; rc = x86_emulate_memop(&ctxt, &emulops); if ( (rc != 0) || (*res != 0x2233445D) || ((regs.eflags&0x201) != 0x201) || (regs.eip != (unsigned long)&instr[4]) ) + goto fail; + printf("okay\n"); + + printf("%-40s", "Testing btrl %eax,(%edi)..."); + instr[0] = 0x0f; instr[1] = 0xb3; instr[2] = 0x07; + *res = 0x2233445F; + regs.eflags = 0x200; + regs.eip = (unsigned long)&instr[0]; + regs.eax = -32; + regs.edi = (unsigned long)(res+1); + regs.error_code = PFEC_write_access; + rc = x86_emulate_memop(&ctxt, &emulops); + if ( (rc != 0) || + (*res != 0x2233445E) || + ((regs.eflags&0x201) != 0x201) || + (regs.eip != (unsigned long)&instr[3]) ) goto fail; printf("okay\n"); @@ -270,7 +296,6 @@ int main(int argc, char **argv) regs.ecx = 0xCCCCFFFF; regs.eip = (unsigned long)&instr[0]; regs.edi = (unsigned long)res; - ctxt.cr2 = regs.edi; regs.error_code = PFEC_write_access; rc = x86_emulate_memop(&ctxt, &emulops); if ( (rc != 0) || @@ -283,9 +308,9 @@ int main(int argc, char **argv) printf("%-40s", "Testing cmpxchg8b (%edi) [failing]..."); instr[0] = 0x0f; instr[1] = 0xc7; instr[2] = 0x0f; + regs.eflags = 0x200; regs.eip = (unsigned long)&instr[0]; regs.edi = (unsigned long)res; - ctxt.cr2 = regs.edi; regs.error_code = PFEC_write_access; rc = x86_emulate_memop(&ctxt, &emulops); if ( (rc != 0) || @@ -300,9 +325,10 @@ int main(int argc, char **argv) printf("%-40s", "Testing movsxbd (%%eax),%%ecx..."); instr[0] = 0x0f; instr[1] = 0xbe; instr[2] = 0x08; - regs.eip = (unsigned long)&instr[0]; - regs.ecx = 0x12345678; - ctxt.cr2 = (unsigned long)res; + regs.eflags = 0x200; + regs.eip = (unsigned long)&instr[0]; + regs.ecx = 0x12345678; + regs.eax = (unsigned long)res; *res = 0x82; regs.error_code = 0; rc = x86_emulate_memop(&ctxt, &emulops); @@ -316,9 +342,10 @@ int main(int argc, char **argv) printf("%-40s", "Testing movzxwd (%%eax),%%ecx..."); instr[0] = 0x0f; instr[1] = 0xb7; instr[2] = 0x08; - regs.eip = (unsigned long)&instr[0]; - regs.ecx = 0x12345678; - ctxt.cr2 = (unsigned long)res; + regs.eflags = 0x200; + regs.eip = (unsigned long)&instr[0]; + regs.ecx = 0x12345678; + regs.eax = (unsigned long)res; *res = 0x1234aa82; regs.error_code = 0; rc = x86_emulate_memop(&ctxt, &emulops); @@ -330,6 +357,23 @@ int main(int argc, char **argv) goto fail; printf("okay\n"); + printf("%-40s", "Testing xadd %%ax,(%%ecx)..."); + instr[0] = 0x66; instr[1] = 0x0f; instr[2] = 0xc1; instr[3] = 0x01; + regs.eflags = 0x200; + regs.eip = (unsigned long)&instr[0]; + regs.ecx = (unsigned long)res; + regs.eax = 0x12345678; + *res = 0x11111111; + regs.error_code = 0; + rc = x86_emulate_memop(&ctxt, &emulops); + if ( (rc != 0) || + (*res != 0x11116789) || + (regs.eax != 0x12341111) || + ((regs.eflags&0x240) != 0x200) || + (regs.eip != (unsigned long)&instr[4]) ) + goto fail; + printf("okay\n"); + return 0; fail: diff -r 6fdbf173142d -r d603aed5ad6d tools/xm-test/tests/vtpm/Makefile.am --- a/tools/xm-test/tests/vtpm/Makefile.am Sat Dec 02 15:19:50 2006 -0700 +++ b/tools/xm-test/tests/vtpm/Makefile.am Mon Dec 04 08:24:41 2006 -0700 @@ -7,7 +7,8 @@ TESTS = 01_vtpm-list_pos.test \ 05_vtpm-loc_migr.test \ 06_vtpm-susp_res_pcrs.test \ 07_vtpm-mig_pcrs.test \ - 08_vtpm-mig_pcrs.test + 08_vtpm-mig_pcrs.test \ + 09_vtpm-xapi.test XFAIL_TESTS = diff -r 6fdbf173142d -r d603aed5ad6d xen/arch/ia64/xen/Makefile --- a/xen/arch/ia64/xen/Makefile Sat Dec 02 15:19:50 2006 -0700 +++ b/xen/arch/ia64/xen/Makefile Mon Dec 04 08:24:41 2006 -0700 @@ -1,5 +1,7 @@ subdir-y += oprofile subdir-y += oprofile +obj-y += machine_kexec.o +obj-y += crash.o obj-y += acpi.o obj-y += dom0_ops.o obj-y += domain.o diff -r 6fdbf173142d -r d603aed5ad6d xen/arch/powerpc/Makefile --- a/xen/arch/powerpc/Makefile Sat Dec 02 15:19:50 2006 -0700 +++ b/xen/arch/powerpc/Makefile Mon Dec 04 08:24:41 2006 -0700 @@ -40,6 +40,8 @@ obj-y += sysctl.o obj-y += sysctl.o obj-y += time.o obj-y += usercopy.o +obj-y += machine_kexec.o +obj-y += crash.o obj-$(debug) += 0opt.o obj-$(crash_debug) += gdbstub.o diff -r 6fdbf173142d -r d603aed5ad6d xen/arch/x86/Makefile --- a/xen/arch/x86/Makefile Sat Dec 02 15:19:50 2006 -0700 +++ b/xen/arch/x86/Makefile Mon Dec 04 08:24:41 2006 -0700 @@ -43,6 +43,8 @@ obj-y += traps.o obj-y += traps.o obj-y += usercopy.o obj-y += x86_emulate.o +obj-y += machine_kexec.o +obj-y += crash.o obj-$(crash_debug) += gdbstub.o diff -r 6fdbf173142d -r d603aed5ad6d xen/arch/x86/hvm/platform.c --- a/xen/arch/x86/hvm/platform.c Sat Dec 02 15:19:50 2006 -0700 +++ b/xen/arch/x86/hvm/platform.c Mon Dec 04 08:24:41 2006 -0700 @@ -920,7 +920,7 @@ void handle_mmio(unsigned long gpa) df = regs->eflags & X86_EFLAGS_DF ? 1 : 0; mode = hvm_guest_x86_mode(v); - inst_addr = hvm_get_segment_base(v, seg_cs) + regs->eip; + inst_addr = hvm_get_segment_base(v, x86_seg_cs) + regs->eip; inst_len = hvm_instruction_length(inst_addr, mode); if ( inst_len <= 0 ) { @@ -964,10 +964,10 @@ void handle_mmio(unsigned long gpa) addr = regs->edi; if ( ad_size == WORD ) addr &= 0xFFFF; - addr += hvm_get_segment_base(v, seg_es); + addr += hvm_get_segment_base(v, x86_seg_es); if ( addr == gpa ) { - enum segment seg; + enum x86_segment seg; dir = IOREQ_WRITE; addr = regs->esi; @@ -975,13 +975,13 @@ void handle_mmio(unsigned long gpa) addr &= 0xFFFF; switch ( seg_sel ) { - case 0x26: seg = seg_es; break; - case 0x2e: seg = seg_cs; break; - case 0x36: seg = seg_ss; break; + case 0x26: seg = x86_seg_es; break; + case 0x2e: seg = x86_seg_cs; break; + case 0x36: seg = x86_seg_ss; break; case 0: - case 0x3e: seg = seg_ds; break; - case 0x64: seg = seg_fs; break; - case 0x65: seg = seg_gs; break; + case 0x3e: seg = x86_seg_ds; break; + case 0x64: seg = x86_seg_fs; break; + case 0x65: seg = x86_seg_gs; break; default: domain_crash_synchronous(); } addr += hvm_get_segment_base(v, seg); diff -r 6fdbf173142d -r d603aed5ad6d xen/arch/x86/hvm/svm/emulate.c --- a/xen/arch/x86/hvm/svm/emulate.c Sat Dec 02 15:19:50 2006 -0700 +++ b/xen/arch/x86/hvm/svm/emulate.c Mon Dec 04 08:24:41 2006 -0700 @@ -128,17 +128,6 @@ static inline unsigned long DECODE_GPR_V 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] @@ -209,7 +198,7 @@ unsigned long get_effective_addr_modrm64 #if __x86_64__ /* 64-bit mode */ - if (vmcb->cs.attributes.fields.l && (vmcb->efer & EFER_LMA)) + if (vmcb->cs.attr.fields.l && (vmcb->efer & EFER_LMA)) return vmcb->rip + inst_len + *size + disp; #endif return disp; @@ -334,7 +323,7 @@ unsigned long svm_rip2pointer(struct vmc * no matter what kind of addressing is used. */ unsigned long p = vmcb->cs.base + vmcb->rip; - if (!(vmcb->cs.attributes.fields.l && vmcb->efer & EFER_LMA)) + if (!(vmcb->cs.attr.fields.l && vmcb->efer & EFER_LMA)) return (u32)p; /* mask to 32 bits */ /* NB. Should mask to 16 bits if in real mode or 16-bit protected mode. */ return p; diff -r 6fdbf173142d -r d603aed5ad6d xen/arch/x86/hvm/svm/svm.c --- a/xen/arch/x86/hvm/svm/svm.c Sat Dec 02 15:19:50 2006 -0700 +++ b/xen/arch/x86/hvm/svm/svm.c Mon Dec 04 08:24:41 2006 -0700 @@ -269,13 +269,11 @@ static int svm_long_mode_enabled(struct return test_bit(SVM_CPU_STATE_LMA_ENABLED, &v->arch.hvm_svm.cpu_state); } -#define IS_CANO_ADDRESS(add) 1 - static inline int long_mode_do_msr_read(struct cpu_user_regs *regs) { u64 msr_content = 0; - struct vcpu *vc = current; - struct vmcb_struct *vmcb = vc->arch.hvm_svm.vmcb; + struct vcpu *v = current; + struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb; switch ((u32)regs->ecx) { @@ -284,17 +282,25 @@ static inline int long_mode_do_msr_read( msr_content &= ~EFER_SVME; break; +#ifdef __x86_64__ case MSR_FS_BASE: msr_content = vmcb->fs.base; - break; + goto check_long_mode; case MSR_GS_BASE: msr_content = vmcb->gs.base; - break; + goto check_long_mode; case MSR_SHADOW_GS_BASE: msr_content = vmcb->kerngsbase; - break; + check_long_mode: + if ( !svm_long_mode_enabled(v) ) + { + svm_inject_exception(v, TRAP_gp_fault, 1, 0); + return 0; + } + break; +#endif case MSR_STAR: msr_content = vmcb->star; @@ -326,25 +332,25 @@ static inline int long_mode_do_msr_write static inline int long_mode_do_msr_write(struct cpu_user_regs *regs) { u64 msr_content = (u32)regs->eax | ((u64)regs->edx << 32); + u32 ecx = regs->ecx; struct vcpu *v = current; struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb; HVM_DBG_LOG(DBG_LEVEL_1, "msr %x msr_content %"PRIx64"\n", - (u32)regs->ecx, msr_content); - - switch ( (u32)regs->ecx ) + ecx, msr_content); + + switch ( ecx ) { case MSR_EFER: -#ifdef __x86_64__ /* offending reserved bit will cause #GP */ if ( msr_content & ~(EFER_LME | EFER_LMA | EFER_NX | EFER_SCE) ) { - printk("Trying to set reserved bit in EFER: %"PRIx64"\n", - msr_content); - svm_inject_exception(v, TRAP_gp_fault, 1, 0); - return 0; - } - + gdprintk(XENLOG_WARNING, "Trying to set reserved bit in " + "EFER: %"PRIx64"\n", msr_content); + goto gp_fault; + } + +#ifdef __x86_64__ /* LME: 0 -> 1 */ if ( msr_content & EFER_LME && !test_bit(SVM_CPU_STATE_LME_ENABLED, &v->arch.hvm_svm.cpu_state)) @@ -353,10 +359,9 @@ static inline int long_mode_do_msr_write !test_bit(SVM_CPU_STATE_PAE_ENABLED, &v->arch.hvm_svm.cpu_state) ) { - printk("Trying to set LME bit when " - "in paging mode or PAE bit is not set\n"); - svm_inject_exception(v, TRAP_gp_fault, 1, 0); - return 0; + gdprintk(XENLOG_WARNING, "Trying to set LME bit when " + "in paging mode or PAE bit is not set\n"); + goto gp_fault; } set_bit(SVM_CPU_STATE_LME_ENABLED, &v->arch.hvm_svm.cpu_state); } @@ -371,37 +376,38 @@ static inline int long_mode_do_msr_write vmcb->efer = msr_content | EFER_SVME; break; +#ifdef __x86_64__ case MSR_FS_BASE: case MSR_GS_BASE: + case MSR_SHADOW_GS_BASE: if ( !svm_long_mode_enabled(v) ) - goto exit_and_crash; - - if (!IS_CANO_ADDRESS(msr_content)) - { - HVM_DBG_LOG(DBG_LEVEL_1, "Not cano address of msr write\n"); - svm_inject_exception(v, TRAP_gp_fault, 1, 0); - } - - if (regs->ecx == MSR_FS_BASE) + goto gp_fault; + + if ( !is_canonical_address(msr_content) ) + goto uncanonical_address; + + if ( ecx == MSR_FS_BASE ) vmcb->fs.base = msr_content; - else + else if ( ecx == MSR_GS_BASE ) vmcb->gs.base = msr_content; - break; - - case MSR_SHADOW_GS_BASE: - vmcb->kerngsbase = msr_content; - break; + else + vmcb->kerngsbase = msr_content; + break; +#endif case MSR_STAR: vmcb->star = msr_content; break; case MSR_LSTAR: - vmcb->lstar = msr_content; - break; - case MSR_CSTAR: - vmcb->cstar = msr_content; + if ( !is_canonical_address(msr_content) ) + goto uncanonical_address; + + if ( ecx == MSR_LSTAR ) + vmcb->lstar = msr_content; + else + vmcb->cstar = msr_content; break; case MSR_SYSCALL_MASK: @@ -414,10 +420,11 @@ static inline int long_mode_do_msr_write return 1; - exit_and_crash: - gdprintk(XENLOG_ERR, "Fatal error writing MSR %lx\n", (long)regs->ecx); - domain_crash(v->domain); - return 1; /* handled */ + uncanonical_address: + HVM_DBG_LOG(DBG_LEVEL_1, "Not cano address of msr write %x\n", ecx); + gp_fault: + svm_inject_exception(v, TRAP_gp_fault, 1, 0); + return 0; } @@ -476,13 +483,13 @@ static int svm_guest_x86_mode(struct vcp struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb; if ( vmcb->efer & EFER_LMA ) - return (vmcb->cs.attributes.fields.l ? + return (vmcb->cs.attr.fields.l ? X86EMUL_MODE_PROT64 : X86EMUL_MODE_PROT32); if ( svm_realmode(v) ) return X86EMUL_MODE_REAL; - return (vmcb->cs.attributes.fields.db ? + return (vmcb->cs.attr.fields.db ? X86EMUL_MODE_PROT32 : X86EMUL_MODE_PROT16); } @@ -509,29 +516,49 @@ unsigned long svm_get_ctrl_reg(struct vc return 0; /* dummy */ } -static unsigned long svm_get_segment_base(struct vcpu *v, enum segment seg) +static unsigned long svm_get_segment_base(struct vcpu *v, enum x86_segment seg) { struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb; int long_mode = 0; #ifdef __x86_64__ - long_mode = vmcb->cs.attributes.fields.l && (vmcb->efer & EFER_LMA); + long_mode = vmcb->cs.attr.fields.l && (vmcb->efer & EFER_LMA); #endif switch ( seg ) { - case seg_cs: return long_mode ? 0 : vmcb->cs.base; - case seg_ds: return long_mode ? 0 : vmcb->ds.base; - case seg_es: return long_mode ? 0 : vmcb->es.base; - case seg_fs: return vmcb->fs.base; - case seg_gs: return vmcb->gs.base; - case seg_ss: return long_mode ? 0 : vmcb->ss.base; - case seg_tr: return vmcb->tr.base; - case seg_gdtr: return vmcb->gdtr.base; - case seg_idtr: return vmcb->idtr.base; - case seg_ldtr: return vmcb->ldtr.base; + case x86_seg_cs: return long_mode ? 0 : vmcb->cs.base; + case x86_seg_ds: return long_mode ? 0 : vmcb->ds.base; + case x86_seg_es: return long_mode ? 0 : vmcb->es.base; + case x86_seg_fs: return vmcb->fs.base; + case x86_seg_gs: return vmcb->gs.base; + case x86_seg_ss: return long_mode ? 0 : vmcb->ss.base; + case x86_seg_tr: return vmcb->tr.base; + case x86_seg_gdtr: return vmcb->gdtr.base; + case x86_seg_idtr: return vmcb->idtr.base; + case x86_seg_ldtr: return vmcb->ldtr.base; } BUG(); return 0; +} + +static void svm_get_segment_register(struct vcpu *v, enum x86_segment seg, + struct segment_register *reg) +{ + struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb; + switch ( seg ) + { + case x86_seg_cs: memcpy(reg, &vmcb->cs, sizeof(*reg)); break; + case x86_seg_ds: memcpy(reg, &vmcb->ds, sizeof(*reg)); break; + case x86_seg_es: memcpy(reg, &vmcb->es, sizeof(*reg)); break; + case x86_seg_fs: memcpy(reg, &vmcb->fs, sizeof(*reg)); break; + case x86_seg_gs: memcpy(reg, &vmcb->gs, sizeof(*reg)); break; + case x86_seg_ss: memcpy(reg, &vmcb->ss, sizeof(*reg)); break; + case x86_seg_tr: memcpy(reg, &vmcb->tr, sizeof(*reg)); break; + case x86_seg_gdtr: memcpy(reg, &vmcb->gdtr, sizeof(*reg)); break; + case x86_seg_idtr: memcpy(reg, &vmcb->idtr, sizeof(*reg)); break; + case x86_seg_ldtr: memcpy(reg, &vmcb->ldtr, sizeof(*reg)); break; + default: BUG(); + } } /* Make sure that xen intercepts any FP accesses from current */ @@ -785,6 +812,15 @@ static void svm_vcpu_destroy(struct vcpu svm_destroy_vmcb(v); } +static void svm_hvm_inject_exception( + unsigned int trapnr, int errcode, unsigned long cr2) +{ + struct vcpu *v = current; + svm_inject_exception(v, trapnr, (errcode != -1), errcode); + if ( trapnr == TRAP_page_fault ) + v->arch.hvm_svm.vmcb->cr2 = v->arch.hvm_svm.cpu_cr2 = cr2; +} + int start_svm(void) { u32 eax, ecx, edx; @@ -844,11 +880,14 @@ int start_svm(void) hvm_funcs.guest_x86_mode = svm_guest_x86_mode; hvm_funcs.get_guest_ctrl_reg = svm_get_ctrl_reg; hvm_funcs.get_segment_base = svm_get_segment_base; + hvm_funcs.get_segment_register = svm_get_segment_register; hvm_funcs.update_host_cr3 = svm_update_host_cr3; hvm_funcs.stts = svm_stts; hvm_funcs.set_tsc_offset = svm_set_tsc_offset; + + hvm_funcs.inject_exception = svm_hvm_inject_exception; hvm_funcs.init_ap_context = svm_init_ap_context; hvm_funcs.init_hypercall_page = svm_init_hypercall_page; @@ -1154,7 +1193,7 @@ static void svm_dr_access(struct vcpu *v static void svm_get_prefix_info( struct vmcb_struct *vmcb, - unsigned int dir, segment_selector_t **seg, unsigned int *asize) + unsigned int dir, svm_segment_register_t **seg, unsigned int *asize) { unsigned char inst[MAX_INST_LEN]; int i; @@ -1235,18 +1274,18 @@ static inline int svm_get_io_address( unsigned long reg; unsigned int asize, isize; int long_mode = 0; - segment_selector_t *seg = NULL; + svm_segment_register_t *seg = NULL; struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb; #ifdef __x86_64__ /* If we're in long mode, we shouldn't check the segment presence & limit */ - long_mode = vmcb->cs.attributes.fields.l && vmcb->efer & EFER_LMA; + long_mode = vmcb->cs.attr.fields.l && vmcb->efer & EFER_LMA; #endif - /* d field of cs.attributes is 1 for 32-bit, 0 for 16 or 64 bit. - * l field combined with EFER_LMA -> longmode says whether it's 16 or 64 bit. + /* d field of cs.attr is 1 for 32-bit, 0 for 16 or 64 bit. + * l field combined with EFER_LMA says whether it's 16 or 64 bit. */ - asize = (long_mode)?64:((vmcb->cs.attributes.fields.db)?32:16); + asize = (long_mode)?64:((vmcb->cs.attr.fields.db)?32:16); /* The ins/outs instructions are single byte, so if we have got more @@ -1266,7 +1305,7 @@ static inline int svm_get_io_address( reg = regs->esi; if (!seg) /* If no prefix, used DS. */ seg = &vmcb->ds; - if (!long_mode && (seg->attributes.fields.type & 0xa) == 0x8) { + if (!long_mode && (seg->attr.fields.type & 0xa) == 0x8) { svm_inject_exception(v, TRAP_gp_fault, 1, 0); return 0; } @@ -1275,14 +1314,14 @@ static inline int svm_get_io_address( { reg = regs->edi; seg = &vmcb->es; /* Note: This is ALWAYS ES. */ - if (!long_mode && (seg->attributes.fields.type & 0xa) != 0x2) { + if (!long_mode && (seg->attr.fields.type & 0xa) != 0x2) { svm_inject_exception(v, TRAP_gp_fault, 1, 0); return 0; } } /* If the segment isn't present, give GP fault! */ - if (!long_mode && !seg->attributes.fields.p) + if (!long_mode && !seg->attr.fields.p) { svm_inject_exception(v, TRAP_gp_fault, 1, 0); return 0; @@ -1305,7 +1344,7 @@ static inline int svm_get_io_address( { ASSERT(*addr == (u32)*addr); if ((u32)(*addr + size - 1) < (u32)*addr || - (seg->attributes.fields.type & 0xc) != 0x4 ? + (seg->attr.fields.type & 0xc) != 0x4 ? *addr + size - 1 > seg->limit : *addr <= seg->limit) { @@ -1318,9 +1357,9 @@ static inline int svm_get_io_address( occur. Note that the checking is not necessary for page granular segments as transfers crossing page boundaries will be broken up anyway. */ - if (!seg->attributes.fields.g && *count > 1) - { - if ((seg->attributes.fields.type & 0xc) != 0x4) + if (!seg->attr.fields.g && *count > 1) + { + if ((seg->attr.fields.type & 0xc) != 0x4) { /* expand-up */ if (!(regs->eflags & EF_DF)) @@ -1355,8 +1394,35 @@ static inline int svm_get_io_address( *addr += seg->base; } - else if (seg == &vmcb->fs || seg == &vmcb->gs) - *addr += seg->base; +#ifdef __x86_64__ + else + { + if (seg == &vmcb->fs || seg == &vmcb->gs) + *addr += seg->base; + + if (!is_canonical_address(*addr) || + !is_canonical_address(*addr + size - 1)) + { + svm_inject_exception(v, TRAP_gp_fault, 1, 0); + return 0; + } + if (*count > (1UL << 48) / size) + *count = (1UL << 48) / size; + if (!(regs->eflags & EF_DF)) + { + if (*addr + *count * size - 1 < *addr || + !is_canonical_address(*addr + *count * size - 1)) + *count = (*addr & ~((1UL << 48) - 1)) / size; + } + else + { + if ((*count - 1) * size > *addr || + !is_canonical_address(*addr + (*count - 1) * size)) + *count = (*addr & ~((1UL << 48) - 1)) / size + 1; + } + ASSERT(*count); + } +#endif return 1; } @@ -2154,52 +2220,52 @@ static int svm_do_vmmcall_reset_to_realm /* setup the segment registers and all their hidden states */ vmcb->cs.sel = 0xF000; - vmcb->cs.attributes.bytes = 0x089b; + vmcb->cs.attr.bytes = 0x089b; vmcb->cs.limit = 0xffff; vmcb->cs.base = 0x000F0000; vmcb->ss.sel = 0x00; - vmcb->ss.attributes.bytes = 0x0893; + vmcb->ss.attr.bytes = 0x0893; vmcb->ss.limit = 0xffff; vmcb->ss.base = 0x00; vmcb->ds.sel = 0x00; - vmcb->ds.attributes.bytes = 0x0893; + vmcb->ds.attr.bytes = 0x0893; vmcb->ds.limit = 0xffff; vmcb->ds.base = 0x00; vmcb->es.sel = 0x00; - vmcb->es.attributes.bytes = 0x0893; + vmcb->es.attr.bytes = 0x0893; vmcb->es.limit = 0xffff; vmcb->es.base = 0x00; vmcb->fs.sel = 0x00; - vmcb->fs.attributes.bytes = 0x0893; + vmcb->fs.attr.bytes = 0x0893; vmcb->fs.limit = 0xffff; vmcb->fs.base = 0x00; vmcb->gs.sel = 0x00; - vmcb->gs.attributes.bytes = 0x0893; + vmcb->gs.attr.bytes = 0x0893; vmcb->gs.limit = 0xffff; vmcb->gs.base = 0x00; vmcb->ldtr.sel = 0x00; - vmcb->ldtr.attributes.bytes = 0x0000; + vmcb->ldtr.attr.bytes = 0x0000; vmcb->ldtr.limit = 0x0; vmcb->ldtr.base = 0x00; vmcb->gdtr.sel = 0x00; - vmcb->gdtr.attributes.bytes = 0x0000; + vmcb->gdtr.attr.bytes = 0x0000; vmcb->gdtr.limit = 0x0; vmcb->gdtr.base = 0x00; vmcb->tr.sel = 0; - vmcb->tr.attributes.bytes = 0; + vmcb->tr.attr.bytes = 0; vmcb->tr.limit = 0x0; vmcb->tr.base = 0; vmcb->idtr.sel = 0x00; - vmcb->idtr.attributes.bytes = 0x0000; + vmcb->idtr.attr.bytes = 0x0000; vmcb->idtr.limit = 0x3ff; vmcb->idtr.base = 0x00; diff -r 6fdbf173142d -r d603aed5ad6d xen/arch/x86/hvm/svm/vmcb.c --- a/xen/arch/x86/hvm/svm/vmcb.c Sat Dec 02 15:19:50 2006 -0700 +++ b/xen/arch/x86/hvm/svm/vmcb.c Mon Dec 04 08:24:41 2006 -0700 @@ -90,7 +90,7 @@ static int construct_vmcb(struct vcpu *v { struct arch_svm_struct *arch_svm = &v->arch.hvm_svm; struct vmcb_struct *vmcb = arch_svm->vmcb; - segment_attributes_t attrib; + svm_segment_attributes_t attrib; /* Always flush the TLB on VMRUN. */ vmcb->tlb_control = 1; @@ -166,13 +166,13 @@ static int construct_vmcb(struct vcpu *v attrib.fields.p = 1; /* segment present */ attrib.fields.db = 1; /* 32-bit */ attrib.fields.g = 1; /* 4K pages in limit */ - vmcb->es.attributes = attrib; - vmcb->ss.attributes = attrib; - vmcb->ds.attributes = attrib; - vmcb->fs.attributes = attrib; - vmcb->gs.attributes = attrib; + vmcb->es.attr = attrib; + vmcb->ss.attr = attrib; + vmcb->ds.attr = attrib; + vmcb->fs.attr = attrib; + vmcb->gs.attr = attrib; attrib.fields.type = 0xb; /* type=0xb -> executable/readable, accessed */ - vmcb->cs.attributes = attrib; + vmcb->cs.attr = attrib; /* Guest IDT. */ vmcb->idtr.base = 0; @@ -186,11 +186,11 @@ static int construct_vmcb(struct vcpu *v vmcb->ldtr.sel = 0; vmcb->ldtr.base = 0; vmcb->ldtr.limit = 0; - vmcb->ldtr.attributes.bytes = 0; + vmcb->ldtr.attr.bytes = 0; /* Guest TSS. */ attrib.fields.type = 0xb; /* 32-bit TSS (busy) */ - vmcb->tr.attributes = attrib; + vmcb->tr.attr = attrib; vmcb->tr.base = 0; vmcb->tr.limit = 0xff; @@ -278,10 +278,10 @@ void svm_do_launch(struct vcpu *v) v->arch.schedule_tail = arch_svm_do_resume; } -static void svm_dump_sel(char *name, segment_selector_t *s) +static void svm_dump_sel(char *name, svm_segment_register_t *s) { printk("%s: sel=0x%04x, attr=0x%04x, limit=0x%08x, base=0x%016llx\n", - name, s->sel, s->attributes.bytes, s->limit, + name, s->sel, s->attr.bytes, s->limit, (unsigned long long)s->base); } diff -r 6fdbf173142d -r d603aed5ad6d xen/arch/x86/hvm/vlapic.c --- a/xen/arch/x86/hvm/vlapic.c Sat Dec 02 15:19:50 2006 -0700 +++ b/xen/arch/x86/hvm/vlapic.c Mon Dec 04 08:24:41 2006 -0700 @@ -119,19 +119,16 @@ static int vlapic_find_highest_vector(u3 static int vlapic_test_and_set_irr(int vector, struct vlapic *vlapic) { - vlapic->flush_tpr_threshold = 1; return vlapic_test_and_set_vector(vector, vlapic->regs + APIC_IRR); } static void vlapic_set_irr(int vector, struct vlapic *vlapic) { - vlapic->flush_tpr_threshold = 1; vlapic_set_vector(vector, vlapic->regs + APIC_IRR); } static void vlapic_clear_irr(int vector, struct vlapic *vlapic) { - vlapic->flush_tpr_threshold = 1; vlapic_clear_vector(vector, vlapic->regs + APIC_IRR); } @@ -634,7 +631,6 @@ static void vlapic_write(struct vcpu *v, { case APIC_TASKPRI: vlapic_set_reg(vlapic, APIC_TASKPRI, val & 0xff); - vlapic->flush_tpr_threshold = 1; break; case APIC_EOI: @@ -667,10 +663,7 @@ static void vlapic_write(struct vcpu *v, } } else - { vlapic->disabled &= ~VLAPIC_SW_DISABLED; - vlapic->flush_tpr_threshold = 1; - } break; case APIC_ESR: @@ -730,7 +723,7 @@ static void vlapic_write(struct vcpu *v, break; default: - gdprintk(XENLOG_WARNING, + gdprintk(XENLOG_DEBUG, "Local APIC Write to read-only register 0x%x\n", offset); break; } @@ -925,8 +918,6 @@ static int vlapic_reset(struct vlapic *v vlapic_set_reg(vlapic, APIC_SPIV, 0xff); vlapic->disabled |= VLAPIC_SW_DISABLED; - vlapic->flush_tpr_threshold = 1; - return 1; } diff -r 6fdbf173142d -r d603aed5ad6d xen/arch/x86/hvm/vmx/Makefile --- a/xen/arch/x86/hvm/vmx/Makefile Sat Dec 02 15:19:50 2006 -0700 +++ b/xen/arch/x86/hvm/vmx/Makefile Mon Dec 04 08:24:41 2006 -0700 @@ -1,6 +1,6 @@ subdir-$(x86_32) += x86_32 subdir-$(x86_32) += x86_32 subdir-$(x86_64) += x86_64 -obj-y += io.o +obj-y += intr.o obj-y += vmcs.o obj-y += vmx.o diff -r 6fdbf173142d -r d603aed5ad6d xen/arch/x86/hvm/vmx/vmx.c --- a/xen/arch/x86/hvm/vmx/vmx.c Sat Dec 02 15:19:50 2006 -0700 +++ b/xen/arch/x86/hvm/vmx/vmx.c Mon Dec 04 08:24:41 2006 -0700 @@ -95,13 +95,7 @@ static void vmx_save_host_msrs(void) rdmsrl(msr_index[i], host_msr_state->msrs[i]); } -#define CASE_READ_MSR(address) \ - case MSR_ ## address: \ - msr_content = guest_msr_state->msrs[VMX_INDEX_MSR_ ## address]; \ - break - -#define CASE_WRITE_MSR(address) \ - case MSR_ ## address: \ +#define WRITE_MSR(address) \ guest_msr_state->msrs[VMX_INDEX_MSR_ ## address] = msr_content; \ if ( !test_bit(VMX_INDEX_MSR_ ## address, &guest_msr_state->flags) )\ set_bit(VMX_INDEX_MSR_ ## address, &guest_msr_state->flags); \ @@ -109,7 +103,6 @@ static void vmx_save_host_msrs(void) set_bit(VMX_INDEX_MSR_ ## address, &host_msr_state->flags); \ break -#define IS_CANO_ADDRESS(add) 1 static inline int long_mode_do_msr_read(struct cpu_user_regs *regs) { u64 msr_content = 0; @@ -123,27 +116,38 @@ static inline int long_mode_do_msr_read( break; case MSR_FS_BASE: - if ( !(vmx_long_mode_enabled(v)) ) - goto exit_and_crash; - msr_content = __vmread(GUEST_FS_BASE); - break; + goto check_long_mode; case MSR_GS_BASE: - if ( !(vmx_long_mode_enabled(v)) ) - goto exit_and_crash; - msr_content = __vmread(GUEST_GS_BASE); - break; + goto check_long_mode; case MSR_SHADOW_GS_BASE: msr_content = guest_msr_state->shadow_gs; - break; - - CASE_READ_MSR(STAR); - CASE_READ_MSR(LSTAR); - CASE_READ_MSR(CSTAR); - CASE_READ_MSR(SYSCALL_MASK); + check_long_mode: + if ( !(vmx_long_mode_enabled(v)) ) + { + vmx_inject_hw_exception(v, TRAP_gp_fault, 0); + return 0; + } + break; + + case MSR_STAR: + msr_content = guest_msr_state->msrs[VMX_INDEX_MSR_STAR]; + break; + + case MSR_LSTAR: + msr_content = guest_msr_state->msrs[VMX_INDEX_MSR_LSTAR]; + break; + + case MSR_CSTAR: + msr_content = guest_msr_state->msrs[VMX_INDEX_MSR_CSTAR]; + break; + + case MSR_SYSCALL_MASK: + msr_content = guest_msr_state->msrs[VMX_INDEX_MSR_SYSCALL_MASK]; + break; default: return 0; @@ -155,32 +159,28 @@ static inline int long_mode_do_msr_read( regs->edx = (u32)(msr_content >> 32); return 1; - - exit_and_crash: - gdprintk(XENLOG_ERR, "Fatal error reading MSR %lx\n", (long)regs->ecx); - domain_crash(v->domain); - return 1; /* handled */ } static inline int long_mode_do_msr_write(struct cpu_user_regs *regs) { u64 msr_content = (u32)regs->eax | ((u64)regs->edx << 32); + u32 ecx = regs->ecx; struct vcpu *v = current; struct vmx_msr_state *guest_msr_state = &v->arch.hvm_vmx.msr_state; struct vmx_msr_state *host_msr_state = &this_cpu(host_msr_state); HVM_DBG_LOG(DBG_LEVEL_1, "msr 0x%x msr_content 0x%"PRIx64"\n", - (u32)regs->ecx, msr_content); - - switch ( (u32)regs->ecx ) { + ecx, msr_content); + + switch ( ecx ) + { case MSR_EFER: /* offending reserved bit will cause #GP */ if ( msr_content & ~(EFER_LME | EFER_LMA | EFER_NX | EFER_SCE) ) { - printk("Trying to set reserved bit in EFER: %"PRIx64"\n", - msr_content); - vmx_inject_hw_exception(v, TRAP_gp_fault, 0); - return 0; + gdprintk(XENLOG_WARNING, "Trying to set reserved bit in " + "EFER: %"PRIx64"\n", msr_content); + goto gp_fault; } if ( (msr_content & EFER_LME) @@ -188,9 +188,9 @@ static inline int long_mode_do_msr_write { if ( unlikely(vmx_paging_enabled(v)) ) { - printk("Trying to set EFER.LME with paging enabled\n"); - vmx_inject_hw_exception(v, TRAP_gp_fault, 0); - return 0; + gdprintk(XENLOG_WARNING, + "Trying to set EFER.LME with paging enabled\n"); + goto gp_fault; } } else if ( !(msr_content & EFER_LME) @@ -198,9 +198,9 @@ static inline int long_mode_do_msr_write { if ( unlikely(vmx_paging_enabled(v)) ) { - printk("Trying to clear EFER.LME with paging enabled\n"); - vmx_inject_hw_exception(v, TRAP_gp_fault, 0); - return 0; + gdprintk(XENLOG_WARNING, + "Trying to clear EFER.LME with paging enabled\n"); + goto gp_fault; } } @@ -209,35 +209,40 @@ static inline int long_mode_do_msr_write case MSR_FS_BASE: case MSR_GS_BASE: + case MSR_SHADOW_GS_BASE: if ( !vmx_long_mode_enabled(v) ) - goto exit_and_crash; - - if ( !IS_CANO_ADDRESS(msr_content) ) - { - HVM_DBG_LOG(DBG_LEVEL_1, "Not cano address of msr write\n"); - vmx_inject_hw_exception(v, TRAP_gp_fault, 0); - return 0; - } - - if ( regs->ecx == MSR_FS_BASE ) + goto gp_fault; + + if ( !is_canonical_address(msr_content) ) + goto uncanonical_address; + + if ( ecx == MSR_FS_BASE ) __vmwrite(GUEST_FS_BASE, msr_content); + else if ( ecx == MSR_GS_BASE ) + __vmwrite(GUEST_GS_BASE, msr_content); else - __vmwrite(GUEST_GS_BASE, msr_content); - - break; - - case MSR_SHADOW_GS_BASE: - if ( !(vmx_long_mode_enabled(v)) ) - goto exit_and_crash; - - v->arch.hvm_vmx.msr_state.shadow_gs = msr_content; - wrmsrl(MSR_SHADOW_GS_BASE, msr_content); - break; - - CASE_WRITE_MSR(STAR); - CASE_WRITE_MSR(LSTAR); - CASE_WRITE_MSR(CSTAR); - CASE_WRITE_MSR(SYSCALL_MASK); + { + v->arch.hvm_vmx.msr_state.shadow_gs = msr_content; + wrmsrl(MSR_SHADOW_GS_BASE, msr_content); + } + + break; + + case MSR_STAR: + WRITE_MSR(STAR); + + case MSR_LSTAR: + if ( !is_canonical_address(msr_content) ) + goto uncanonical_address; + WRITE_MSR(LSTAR); + + case MSR_CSTAR: + if ( !is_canonical_address(msr_content) ) + goto uncanonical_address; + WRITE_MSR(CSTAR); + + case MSR_SYSCALL_MASK: + WRITE_MSR(SYSCALL_MASK); default: return 0; @@ -245,10 +250,11 @@ static inline int long_mode_do_msr_write return 1; - exit_and_crash: - gdprintk(XENLOG_ERR, "Fatal error writing MSR %lx\n", (long)regs->ecx); - domain_crash(v->domain); - return 1; /* handled */ + uncanonical_address: + HVM_DBG_LOG(DBG_LEVEL_1, "Not cano address of msr write %x\n", ecx); + gp_fault: + vmx_inject_hw_exception(v, TRAP_gp_fault, 0); + return 0; } /* @@ -501,7 +507,7 @@ static unsigned long vmx_get_ctrl_reg(st return 0; /* dummy */ } -static unsigned long vmx_get_segment_base(struct vcpu *v, enum segment seg) +static unsigned long vmx_get_segment_base(struct vcpu *v, enum x86_segment seg) { unsigned long base = 0; int long_mode = 0; @@ -516,20 +522,92 @@ static unsigned long vmx_get_segment_bas switch ( seg ) { - case seg_cs: if ( !long_mode ) base = __vmread(GUEST_CS_BASE); break; - case seg_ds: if ( !long_mode ) base = __vmread(GUEST_DS_BASE); break; - case seg_es: if ( !long_mode ) base = __vmread(GUEST_ES_BASE); break; - case seg_fs: base = __vmread(GUEST_FS_BASE); break; - case seg_gs: base = __vmread(GUEST_GS_BASE); break; - case seg_ss: if ( !long_mode ) base = __vmread(GUEST_SS_BASE); break; - case seg_tr: base = __vmread(GUEST_TR_BASE); break; - case seg_gdtr: base = __vmread(GUEST_GDTR_BASE); break; - case seg_idtr: base = __vmread(GUEST_IDTR_BASE); break; - case seg_ldtr: base = __vmread(GUEST_LDTR_BASE); break; + case x86_seg_cs: if ( !long_mode ) base = __vmread(GUEST_CS_BASE); break; + case x86_seg_ds: if ( !long_mode ) base = __vmread(GUEST_DS_BASE); break; + case x86_seg_es: if ( !long_mode ) base = __vmread(GUEST_ES_BASE); break; + case x86_seg_fs: base = __vmread(GUEST_FS_BASE); break; + case x86_seg_gs: base = __vmread(GUEST_GS_BASE); break; + case x86_seg_ss: if ( !long_mode ) base = __vmread(GUEST_SS_BASE); break; + case x86_seg_tr: base = __vmread(GUEST_TR_BASE); break; + case x86_seg_gdtr: base = __vmread(GUEST_GDTR_BASE); break; + case x86_seg_idtr: base = __vmread(GUEST_IDTR_BASE); break; + case x86_seg_ldtr: base = __vmread(GUEST_LDTR_BASE); break; default: BUG(); break; } return base; +} + +static void vmx_get_segment_register(struct vcpu *v, enum x86_segment seg, + struct segment_register *reg) +{ + u16 attr = 0; + + ASSERT(v == current); + + switch ( seg ) + { + case x86_seg_cs: + reg->sel = __vmread(GUEST_CS_SELECTOR); + reg->limit = __vmread(GUEST_CS_LIMIT); + reg->base = __vmread(GUEST_CS_BASE); + attr = __vmread(GUEST_CS_AR_BYTES); + break; + case x86_seg_ds: + reg->sel = __vmread(GUEST_DS_SELECTOR); + reg->limit = __vmread(GUEST_DS_LIMIT); + reg->base = __vmread(GUEST_DS_BASE); + attr = __vmread(GUEST_DS_AR_BYTES); + break; + case x86_seg_es: + reg->sel = __vmread(GUEST_ES_SELECTOR); + reg->limit = __vmread(GUEST_ES_LIMIT); + reg->base = __vmread(GUEST_ES_BASE); + attr = __vmread(GUEST_ES_AR_BYTES); + break; + case x86_seg_fs: + reg->sel = __vmread(GUEST_FS_SELECTOR); + reg->limit = __vmread(GUEST_FS_LIMIT); + reg->base = __vmread(GUEST_FS_BASE); + attr = __vmread(GUEST_FS_AR_BYTES); + break; + case x86_seg_gs: + reg->sel = __vmread(GUEST_GS_SELECTOR); + reg->limit = __vmread(GUEST_GS_LIMIT); + reg->base = __vmread(GUEST_GS_BASE); + attr = __vmread(GUEST_GS_AR_BYTES); + break; + case x86_seg_ss: + reg->sel = __vmread(GUEST_SS_SELECTOR); + reg->limit = __vmread(GUEST_SS_LIMIT); + reg->base = __vmread(GUEST_SS_BASE); + attr = __vmread(GUEST_SS_AR_BYTES); + break; + case x86_seg_tr: + reg->sel = __vmread(GUEST_TR_SELECTOR); + reg->limit = __vmread(GUEST_TR_LIMIT); + reg->base = __vmread(GUEST_TR_BASE); + attr = __vmread(GUEST_TR_AR_BYTES); + break; + case x86_seg_gdtr: + reg->limit = __vmread(GUEST_GDTR_LIMIT); + reg->base = __vmread(GUEST_GDTR_BASE); + break; + case x86_seg_idtr: + reg->limit = __vmread(GUEST_IDTR_LIMIT); + reg->base = __vmread(GUEST_IDTR_BASE); + break; + case x86_seg_ldtr: + reg->sel = __vmread(GUEST_LDTR_SELECTOR); + reg->limit = __vmread(GUEST_LDTR_LIMIT); + reg->base = __vmread(GUEST_LDTR_BASE); + attr = __vmread(GUEST_LDTR_AR_BYTES); + break; + default: + BUG(); + } + + reg->attr.bytes = (attr & 0xff) | ((attr >> 4) & 0xf00); } /* Make sure that xen intercepts any FP accesses from current */ @@ -630,6 +708,22 @@ static int vmx_pae_enabled(struct vcpu * return (vmx_paging_enabled(v) && (cr4 & X86_CR4_PAE)); } +/* Works only for vcpu == current */ +static void vmx_update_host_cr3(struct vcpu *v) +{ + ASSERT(v == current); + __vmwrite(HOST_CR3, v->arch.cr3); +} + +static void vmx_inject_exception( + unsigned int trapnr, int errcode, unsigned long cr2) +{ + struct vcpu *v = current; + vmx_inject_hw_exception(v, trapnr, errcode); + if ( trapnr == TRAP_page_fault ) + v->arch.hvm_vmx.cpu_cr2 = cr2; +} + /* Setup HVM interfaces */ static void vmx_setup_hvm_funcs(void) { @@ -650,11 +744,14 @@ static void vmx_setup_hvm_funcs(void) hvm_funcs.guest_x86_mode = vmx_guest_x86_mode; hvm_funcs.get_guest_ctrl_reg = vmx_get_ctrl_reg; hvm_funcs.get_segment_base = vmx_get_segment_base; + hvm_funcs.get_segment_register = vmx_get_segment_register; hvm_funcs.update_host_cr3 = vmx_update_host_cr3; hvm_funcs.stts = vmx_stts; hvm_funcs.set_tsc_offset = vmx_set_tsc_offset; + + hvm_funcs.inject_exception = vmx_inject_exception; hvm_funcs.init_ap_context = vmx_init_ap_context; @@ -962,14 +1059,14 @@ static void vmx_do_invlpg(unsigned long static int vmx_check_descriptor(int long_mode, unsigned long eip, int inst_len, - enum segment seg, unsigned long *base, + enum x86_segment seg, unsigned long *base, u32 *limit, u32 *ar_bytes) { enum vmcs_field ar_field, base_field, limit_field; *base = 0; *limit = 0; - if ( seg != seg_es ) + if ( seg != x86_seg_es ) { unsigned char inst[MAX_INST_LEN]; int i; @@ -999,22 +1096,22 @@ static int vmx_check_descriptor(int long #endif continue; case 0x2e: /* CS */ - seg = seg_cs; + seg = x86_seg_cs; continue; case 0x36: /* SS */ - seg = seg_ss; + seg = x86_seg_ss; continue; case 0x26: /* ES */ - seg = seg_es; + seg = x86_seg_es; continue; case 0x64: /* FS */ - seg = seg_fs; + seg = x86_seg_fs; continue; case 0x65: /* GS */ - seg = seg_gs; + seg = x86_seg_gs; continue; case 0x3e: /* DS */ - seg = seg_ds; + seg = x86_seg_ds; continue; } } @@ -1022,32 +1119,32 @@ static int vmx_check_descriptor(int long switch ( seg ) { - case seg_cs: + case x86_seg_cs: ar_field = GUEST_CS_AR_BYTES; base_field = GUEST_CS_BASE; limit_field = GUEST_CS_LIMIT; break; - case seg_ds: + case x86_seg_ds: ar_field = GUEST_DS_AR_BYTES; base_field = GUEST_DS_BASE; limit_field = GUEST_DS_LIMIT; break; - case seg_es: + case x86_seg_es: ar_field = GUEST_ES_AR_BYTES; base_field = GUEST_ES_BASE; limit_field = GUEST_ES_LIMIT; break; - case seg_fs: + case x86_seg_fs: ar_field = GUEST_FS_AR_BYTES; base_field = GUEST_FS_BASE; limit_field = GUEST_FS_LIMIT; break; - case seg_gs: + case x86_seg_gs: ar_field = GUEST_FS_AR_BYTES; base_field = GUEST_FS_BASE; limit_field = GUEST_FS_LIMIT; break; - case seg_ss: + case x86_seg_ss: ar_field = GUEST_GS_AR_BYTES; base_field = GUEST_GS_BASE; limit_field = GUEST_GS_LIMIT; @@ -1057,7 +1154,7 @@ static int vmx_check_descriptor(int long return 0; } - if ( !long_mode || seg == seg_fs || seg == seg_gs ) + if ( !long_mode || seg == x86_seg_fs || seg == x86_seg_gs ) { *base = __vmread(base_field); *limit = __vmread(limit_field); @@ -1127,7 +1224,7 @@ static void vmx_io_instruction(unsigned * selector is null. */ if ( !vmx_check_descriptor(long_mode, regs->eip, inst_len, - dir == IOREQ_WRITE ? seg_ds : seg_es, + dir==IOREQ_WRITE ? x86_seg_ds : x86_seg_es, &base, &limit, &ar_bytes) ) { if ( !long_mode ) { vmx_inject_hw_exception(current, TRAP_gp_fault, 0); @@ -1196,6 +1293,32 @@ static void vmx_io_instruction(unsigned ASSERT(count); } } +#ifdef __x86_64__ + else + { + if ( !is_canonical_address(addr) || + !is_canonical_address(addr + size - 1) ) + { + vmx_inject_hw_exception(current, TRAP_gp_fault, 0); + return; + } + if ( count > (1UL << 48) / size ) + count = (1UL << 48) / size; + if ( !(regs->eflags & EF_DF) ) + { + if ( addr + count * size - 1 < addr || + !is_canonical_address(addr + count * size - 1) ) + count = (addr & ~((1UL << 48) - 1)) / size; + } + else + { + if ( (count - 1) * size > addr || + !is_canonical_address(addr + (count - 1) * size) ) + count = (addr & ~((1UL << 48) - 1)) / size + 1; + } + ASSERT(count); + } +#endif /* * Handle string pio instructions that cross pages or that @@ -2413,7 +2536,6 @@ asmlinkage void vmx_vmexit_handler(struc break; case EXIT_REASON_TPR_BELOW_THRESHOLD: - vcpu_vlapic(v)->flush_tpr_threshold = 1; break; default: diff -r 6fdbf173142d -r d603aed5ad6d xen/arch/x86/mm.c --- a/xen/arch/x86/mm.c Sat Dec 02 15:19:50 2006 -0700 +++ b/xen/arch/x86/mm.c Mon Dec 04 08:24:41 2006 -0700 @@ -3033,12 +3033,39 @@ long arch_memory_op(int op, XEN_GUEST_HA * Writable Pagetables */ +struct ptwr_emulate_ctxt { + struct x86_emulate_ctxt ctxt; + unsigned long cr2; + l1_pgentry_t pte; +}; + +static int ptwr_emulated_read( + enum x86_segment seg, + unsigned long offset, + unsigned long *val, + unsigned int bytes, + struct x86_emulate_ctxt *ctxt) +{ + unsigned int rc; + unsigned long addr = offset; + + *val = 0; + if ( (rc = copy_from_user((void *)val, (void *)addr, bytes)) != 0 ) + { + propagate_page_fault(addr + bytes - rc, 0); /* read fault */ + return X86EMUL_PROPAGATE_FAULT; + } + + return X86EMUL_CONTINUE; +} + static int ptwr_emulated_update( unsigned long addr, paddr_t old, paddr_t val, unsigned int bytes, - unsigned int do_cmpxchg) + unsigned int do_cmpxchg, + struct ptwr_emulate_ctxt *ptwr_ctxt) { unsigned long gmfn, mfn; struct page_info *page; @@ -3046,11 +3073,11 @@ static int ptwr_emulated_update( struct vcpu *v = current; struct domain *d = v->domain; - /* Aligned access only, thank you. */ - if ( !access_ok(addr, bytes) || ((addr & (bytes-1)) != 0) ) - { - MEM_LOG("ptwr_emulate: Unaligned or bad size ptwr access (%d, %lx)", - bytes, addr); + /* Only allow naturally-aligned stores within the original %cr2 page. */ + if ( unlikely(((addr^ptwr_ctxt->cr2) & PAGE_MASK) || (addr & (bytes-1))) ) + { + MEM_LOG("Bad ptwr access (cr2=%lx, addr=%lx, bytes=%u)", + ptwr_ctxt->cr2, addr, bytes); return X86EMUL_UNHANDLEABLE; } @@ -3079,17 +3106,9 @@ static int ptwr_emulated_update( old |= full; } - /* Read the PTE that maps the page being updated. */ - guest_get_eff_l1e(v, addr, &pte); - if ( unlikely(!(l1e_get_flags(pte) & _PAGE_PRESENT)) ) - { - MEM_LOG("%s: Cannot get L1 PTE for guest address %lx", - __func__, addr); - return X86EMUL_UNHANDLEABLE; - } - - gmfn = l1e_get_pfn(pte); - mfn = gmfn_to_mfn(d, gmfn); + pte = ptwr_ctxt->pte; + gmfn = l1e_get_pfn(pte); + mfn = gmfn_to_mfn(d, gmfn); page = mfn_to_page(mfn); /* We are looking only for read-only mappings of p.t. pages. */ @@ -3164,26 +3183,33 @@ static int ptwr_emulated_update( } static int ptwr_emulated_write( - unsigned long addr, + enum x86_segment seg, + unsigned long offset, unsigned long val, unsigned int bytes, struct x86_emulate_ctxt *ctxt) { - return ptwr_emulated_update(addr, 0, val, bytes, 0); + return ptwr_emulated_update( + offset, 0, val, bytes, 0, + container_of(ctxt, struct ptwr_emulate_ctxt, ctxt)); } static int ptwr_emulated_cmpxchg( - unsigned long addr, + enum x86_segment seg, + unsigned long offset, unsigned long old, unsigned long new, unsigned int bytes, struct x86_emulate_ctxt *ctxt) { - return ptwr_emulated_update(addr, old, new, bytes, 1); + return ptwr_emulated_update( + offset, old, new, bytes, 1, + container_of(ctxt, struct ptwr_emulate_ctxt, ctxt)); } static int ptwr_emulated_cmpxchg8b( - unsigned long addr, + enum x86_segment seg, + unsigned long offset, unsigned long old, unsigned long old_hi, unsigned long new, @@ -3192,18 +3218,17 @@ static int ptwr_emulated_cmpxchg8b( { if ( CONFIG_PAGING_LEVELS == 2 ) return X86EMUL_UNHANDLEABLE; - else - return ptwr_emulated_update( - addr, ((u64)old_hi << 32) | old, ((u64)new_hi << 32) | new, 8, 1); + return ptwr_emulated_update( + offset, ((u64)old_hi << 32) | old, ((u64)new_hi << 32) | new, 8, 1, + container_of(ctxt, struct ptwr_emulate_ctxt, ctxt)); } static struct x86_emulate_ops ptwr_emulate_ops = { - .read_std = x86_emulate_read_std, - .write_std = x86_emulate_write_std, - .read_emulated = x86_emulate_read_std, - .write_emulated = ptwr_emulated_write, - .cmpxchg_emulated = ptwr_emulated_cmpxchg, - .cmpxchg8b_emulated = ptwr_emulated_cmpxchg8b + .read = ptwr_emulated_read, + .insn_fetch = ptwr_emulated_read, + .write = ptwr_emulated_write, + .cmpxchg = ptwr_emulated_cmpxchg, + .cmpxchg8b = ptwr_emulated_cmpxchg8b }; /* Write page fault handler: check if guest is trying to modify a PTE. */ @@ -3214,7 +3239,7 @@ int ptwr_do_page_fault(struct vcpu *v, u unsigned long pfn; struct page_info *page; l1_pgentry_t pte; - struct x86_emulate_ctxt emul_ctxt; + struct ptwr_emulate_ctxt ptwr_ctxt; LOCK_BIGLOCK(d); @@ -3235,10 +3260,11 @@ int ptwr_do_page_fault(struct vcpu *v, u (page_get_owner(page) != d) ) goto bail; - emul_ctxt.regs = guest_cpu_user_regs(); - emul_ctxt.cr2 = addr; - emul_ctxt.mode = X86EMUL_MODE_HOST; - if ( x86_emulate_memop(&emul_ctxt, &ptwr_emulate_ops) ) + ptwr_ctxt.ctxt.regs = guest_cpu_user_regs(); + ptwr_ctxt.ctxt.mode = X86EMUL_MODE_HOST; + ptwr_ctxt.cr2 = addr; + ptwr_ctxt.pte = pte; + if ( x86_emulate_memop(&ptwr_ctxt.ctxt, &ptwr_emulate_ops) ) goto bail; UNLOCK_BIGLOCK(d); diff -r 6fdbf173142d -r d603aed5ad6d xen/arch/x86/mm/shadow/common.c --- a/xen/arch/x86/mm/shadow/common.c Sat Dec 02 15:19:50 2006 -0700 +++ b/xen/arch/x86/mm/shadow/common.c Mon Dec 04 08:24:41 2006 -0700 @@ -69,18 +69,122 @@ int _shadow_mode_refcounts(struct domain /* x86 emulator support for the shadow code */ +struct segment_register *hvm_get_seg_reg( + enum x86_segment seg, struct sh_emulate_ctxt *sh_ctxt) +{ + struct segment_register *seg_reg = &sh_ctxt->seg_reg[seg]; + if ( !__test_and_set_bit(seg, &sh_ctxt->valid_seg_regs) ) + hvm_get_segment_register(current, seg, seg_reg); + return seg_reg; +} + +enum hvm_access_type { + hvm_access_insn_fetch, hvm_access_read, hvm_access_write +}; + +static int hvm_translate_linear_addr( + enum x86_segment seg, + unsigned long offset, + unsigned int bytes, + enum hvm_access_type access_type, + struct sh_emulate_ctxt *sh_ctxt, + unsigned long *paddr) +{ + struct segment_register *reg = hvm_get_seg_reg(seg, sh_ctxt); + unsigned long limit, addr = offset; + uint32_t last_byte; + + if ( sh_ctxt->ctxt.mode != X86EMUL_MODE_PROT64 ) + { + /* + * COMPATIBILITY MODE: Apply segment checks and add base. + */ + + switch ( access_type ) + { + case hvm_access_read: + if ( (reg->attr.fields.type & 0xa) == 0x8 ) + goto gpf; /* execute-only code segment */ + break; + case hvm_access_write: + if ( (reg->attr.fields.type & 0xa) != 0x2 ) + goto gpf; /* not a writable data segment */ + break; + default: + break; + } + + /* Calculate the segment limit, including granularity flag. */ + limit = reg->limit; + if ( reg->attr.fields.g ) + limit = (limit << 12) | 0xfff; + + last_byte = offset + bytes - 1; + + /* Is this a grows-down data segment? Special limit check if so. */ + if ( (reg->attr.fields.type & 0xc) == 0x4 ) + { + /* Is upper limit 0xFFFF or 0xFFFFFFFF? */ + if ( !reg->attr.fields.db ) + last_byte = (uint16_t)last_byte; + + /* Check first byte and last byte against respective bounds. */ + if ( (offset <= limit) || (last_byte < offset) ) + goto gpf; + } + else if ( (last_byte > limit) || (last_byte < offset) ) + goto gpf; /* last byte is beyond limit or wraps 0xFFFFFFFF */ + + /* + * Hardware truncates to 32 bits in compatibility mode. + * It does not truncate to 16 bits in 16-bit address-size mode. + */ + addr = (uint32_t)(addr + reg->base); + } + else + { + /* + * LONG MODE: FS and GS add segment base. Addresses must be canonical. + */ + + if ( (seg == x86_seg_fs) || (seg == x86_seg_gs) ) + addr += reg->base; + + if ( !is_canonical_address(addr) ) + goto gpf; + } + + *paddr = addr; + return 0; + + gpf: + /* Inject #GP(0). */ + hvm_inject_exception(TRAP_gp_fault, 0, 0); + return X86EMUL_PROPAGATE_FAULT; +} + static int -sh_x86_emulate_read_std(unsigned long addr, - unsigned long *val, - unsigned int bytes, - struct x86_emulate_ctxt *ctxt) -{ +hvm_read(enum x86_segment seg, + unsigned long offset, + unsigned long *val, + unsigned int bytes, + enum hvm_access_type access_type, + struct sh_emulate_ctxt *sh_ctxt) +{ + unsigned long addr; + int rc, errcode; + + rc = hvm_translate_linear_addr( + seg, offset, bytes, access_type, sh_ctxt, &addr); + if ( rc ) + return rc; + *val = 0; // XXX -- this is WRONG. // It entirely ignores the permissions in the page tables. // In this case, that is only a user vs supervisor access check. // - if ( hvm_copy_from_guest_virt(val, addr, bytes) == 0 ) + if ( (rc = hvm_copy_from_guest_virt(val, addr, bytes)) == 0 ) { #if 0 struct vcpu *v = current; @@ -95,93 +199,168 @@ sh_x86_emulate_read_std(unsigned long ad * was mapped here. This should never happen: we're here because * of a write fault at the end of the instruction we're emulating. */ SHADOW_PRINTK("read failed to va %#lx\n", addr); + errcode = ring_3(sh_ctxt->ctxt.regs) ? PFEC_user_mode : 0; + if ( access_type == hvm_access_insn_fetch ) + errcode |= PFEC_insn_fetch; + hvm_inject_exception(TRAP_page_fault, errcode, addr + bytes - rc); return X86EMUL_PROPAGATE_FAULT; } +void shadow_init_emulation(struct sh_emulate_ctxt *sh_ctxt, + struct cpu_user_regs *regs) +{ + struct segment_register *creg; + struct vcpu *v = current; + unsigned long addr; + + sh_ctxt->ctxt.regs = regs; + + /* Segment cache initialisation. Primed with CS. */ + sh_ctxt->valid_seg_regs = 0; + creg = hvm_get_seg_reg(x86_seg_cs, sh_ctxt); + + /* Work out the emulation mode. */ + if ( hvm_long_mode_enabled(v) ) + sh_ctxt->ctxt.mode = creg->attr.fields.l ? + X86EMUL_MODE_PROT64 : X86EMUL_MODE_PROT32; + else if ( regs->eflags & X86_EFLAGS_VM ) + sh_ctxt->ctxt.mode = X86EMUL_MODE_REAL; + else + sh_ctxt->ctxt.mode = creg->attr.fields.db ? + X86EMUL_MODE_PROT32 : X86EMUL_MODE_PROT16; + + /* Attempt to prefetch whole instruction. */ + sh_ctxt->insn_buf_bytes = + (!hvm_translate_linear_addr( + x86_seg_cs, regs->eip, sizeof(sh_ctxt->insn_buf), + hvm_access_insn_fetch, sh_ctxt, &addr) && + !hvm_copy_from_guest_virt( + sh_ctxt->insn_buf, addr, sizeof(sh_ctxt->insn_buf))) + ? sizeof(sh_ctxt->insn_buf) : 0; +} + static int -sh_x86_emulate_write_std(unsigned long addr, - unsigned long val, +sh_x86_emulate_read(enum x86_segment seg, + unsigned long offset, + unsigned long *val, + unsigned int bytes, + struct x86_emulate_ctxt *ctxt) +{ + return hvm_read(seg, offset, val, bytes, hvm_access_read, + container_of(ctxt, struct sh_emulate_ctxt, ctxt)); +} + +static int +sh_x86_emulate_insn_fetch(enum x86_segment seg, + unsigned long offset, + unsigned long *val, unsigned int bytes, struct x86_emulate_ctxt *ctxt) { -#if 0 + struct sh_emulate_ctxt *sh_ctxt = + container_of(ctxt, struct sh_emulate_ctxt, ctxt); + unsigned int insn_off = offset - ctxt->regs->eip; + + /* Fall back if requested bytes are not in the prefetch cache. */ + if ( unlikely((insn_off + bytes) > sh_ctxt->insn_buf_bytes) ) + return hvm_read(seg, offset, val, bytes, + hvm_access_insn_fetch, sh_ctxt); + + /* Hit the cache. Simple memcpy. */ + *val = 0; + memcpy(val, &sh_ctxt->insn_buf[insn_off], bytes); + return X86EMUL_CONTINUE; +} + +static int +sh_x86_emulate_write(enum x86_segment seg, + unsigned long offset, + unsigned long val, + unsigned int bytes, + struct x86_emulate_ctxt *ctxt) +{ + struct sh_emulate_ctxt *sh_ctxt = + container_of(ctxt, struct sh_emulate_ctxt, ctxt); struct vcpu *v = current; - SHADOW_PRINTK("d=%u v=%u a=%#lx v=%#lx bytes=%u\n", - v->domain->domain_id, v->vcpu_id, addr, val, bytes); -#endif - - // XXX -- this is WRONG. - // It entirely ignores the permissions in the page tables. - // In this case, that includes user vs supervisor, and - // write access. - // - if ( hvm_copy_to_guest_virt(addr, &val, bytes) == 0 ) - return X86EMUL_CONTINUE; - - /* If we got here, there was nothing mapped here, or a bad GFN - * was mapped here. This should never happen: we're here because - * of a write fault at the end of the instruction we're emulating, - * which should be handled by sh_x86_emulate_write_emulated. */ - SHADOW_PRINTK("write failed to va %#lx\n", addr); - return X86EMUL_PROPAGATE_FAULT; -} - -static int -sh_x86_emulate_write_emulated(unsigned long addr, - unsigned long val, - unsigned int bytes, - struct x86_emulate_ctxt *ctxt) -{ - struct vcpu *v = current; + unsigned long addr; + int rc; + + rc = hvm_translate_linear_addr( + seg, offset, bytes, hvm_access_write, sh_ctxt, &addr); + if ( rc ) + return rc; + #if 0 SHADOW_PRINTK("d=%u v=%u a=%#lx v=%#lx bytes=%u\n", v->domain->domain_id, v->vcpu_id, addr, val, bytes); #endif - return v->arch.shadow.mode->x86_emulate_write(v, addr, &val, bytes, ctxt); + return v->arch.shadow.mode->x86_emulate_write( + v, addr, &val, bytes, sh_ctxt); } static int -sh_x86_emulate_cmpxchg_emulated(unsigned long addr, - unsigned long old, - unsigned long new, - unsigned int bytes, - struct x86_emulate_ctxt *ctxt) -{ +sh_x86_emulate_cmpxchg(enum x86_segment seg, + unsigned long offset, + unsigned long old, + unsigned long new, + unsigned int bytes, + struct x86_emulate_ctxt *ctxt) +{ + struct sh_emulate_ctxt *sh_ctxt = + container_of(ctxt, struct sh_emulate_ctxt, ctxt); struct vcpu *v = current; + unsigned long addr; + int rc; + + rc = hvm_translate_linear_addr( + seg, offset, bytes, hvm_access_write, sh_ctxt, &addr); + if ( rc ) + return rc; + #if 0 SHADOW_PRINTK("d=%u v=%u a=%#lx o?=%#lx n:=%#lx bytes=%u\n", v->domain->domain_id, v->vcpu_id, addr, old, new, bytes); #endif - return v->arch.shadow.mode->x86_emulate_cmpxchg(v, addr, old, new, - bytes, ctxt); + return v->arch.shadow.mode->x86_emulate_cmpxchg( + v, addr, old, new, bytes, sh_ctxt); } static int -sh_x86_emulate_cmpxchg8b_emulated(unsigned long addr, - unsigned long old_lo, - unsigned long old_hi, - unsigned long new_lo, - unsigned long new_hi, - struct x86_emulate_ctxt *ctxt) -{ +sh_x86_emulate_cmpxchg8b(enum x86_segment seg, + unsigned long offset, + unsigned long old_lo, + unsigned long old_hi, + unsigned long new_lo, + unsigned long new_hi, + struct x86_emulate_ctxt *ctxt) +{ + struct sh_emulate_ctxt *sh_ctxt = + container_of(ctxt, struct sh_emulate_ctxt, ctxt); struct vcpu *v = current; + unsigned long addr; + int rc; + + rc = hvm_translate_linear_addr( + seg, offset, 8, hvm_access_write, sh_ctxt, &addr); + if ( rc ) + return rc; + #if 0 SHADOW_PRINTK("d=%u v=%u a=%#lx o?=%#lx:%lx n:=%#lx:%lx\n", v->domain->domain_id, v->vcpu_id, addr, old_hi, old_lo, new_hi, new_lo, ctxt); #endif - return v->arch.shadow.mode->x86_emulate_cmpxchg8b(v, addr, old_lo, old_hi, - new_lo, new_hi, ctxt); + return v->arch.shadow.mode->x86_emulate_cmpxchg8b( + v, addr, old_lo, old_hi, new_lo, new_hi, sh_ctxt); } struct x86_emulate_ops shadow_emulator_ops = { - .read_std = sh_x86_emulate_read_std, - .write_std = sh_x86_emulate_write_std, - .read_emulated = sh_x86_emulate_read_std, - .write_emulated = sh_x86_emulate_write_emulated, - .cmpxchg_emulated = sh_x86_emulate_cmpxchg_emulated, - .cmpxchg8b_emulated = sh_x86_emulate_cmpxchg8b_emulated, + .read = sh_x86_emulate_read, + .insn_fetch = sh_x86_emulate_insn_fetch, + .write = sh_x86_emulate_write, + .cmpxchg = sh_x86_emulate_cmpxchg, + .cmpxchg8b = sh_x86_emulate_cmpxchg8b, }; /**************************************************************************/ @@ -938,12 +1117,13 @@ shadow_set_p2m_entry(struct domain *d, u void *table = sh_map_domain_page(table_mfn); unsigned long gfn_remainder = gfn; l1_pgentry_t *p2m_entry; + int rv=0; #if CONFIG_PAGING_LEVELS >= 4 if ( !p2m_next_level(d, &table_mfn, &table, &gfn_remainder, gfn, L4_PAGETABLE_SHIFT - PAGE_SHIFT, L4_PAGETABLE_ENTRIES, PGT_l3_page_table) ) - return 0; + goto out; #endif #if CONFIG_PAGING_LEVELS >= 3 // When using PAE Xen, we only allow 33 bits of pseudo-physical @@ -957,12 +1137,12 @@ shadow_set_p2m_entry(struct domain *d, u ? 8 : L3_PAGETABLE_ENTRIES), PGT_l2_page_table) ) - return 0; + goto out; #endif if ( !p2m_next_level(d, &table_mfn, &table, &gfn_remainder, gfn, L2_PAGETABLE_SHIFT - PAGE_SHIFT, L2_PAGETABLE_ENTRIES, PGT_l1_page_table) ) - return 0; + goto out; p2m_entry = p2m_find_entry(table, &gfn_remainder, gfn, 0, L1_PAGETABLE_ENTRIES); @@ -981,9 +1161,12 @@ shadow_set_p2m_entry(struct domain *d, u (void)__shadow_validate_guest_entry( d->vcpu[0], table_mfn, p2m_entry, sizeof(*p2m_entry)); + /* Success */ + rv = 1; + + out: sh_unmap_domain_page(table); - - return 1; + return rv; } // Allocate a new p2m table for a domain. diff -r 6fdbf173142d -r d603aed5ad6d xen/arch/x86/mm/shadow/multi.c --- a/xen/arch/x86/mm/shadow/multi.c Sat Dec 02 15:19:50 2006 -0700 +++ b/xen/arch/x86/mm/shadow/multi.c Mon Dec 04 08:24:41 2006 -0700 @@ -581,7 +581,7 @@ guest_index(void *ptr) return (u32)((unsigned long)ptr & ~PAGE_MASK) / sizeof(guest_l1e_t); } -static inline u32 +static u32 shadow_l1_index(mfn_t *smfn, u32 guest_index) { #if (GUEST_PAGING_LEVELS == 2) && (SHADOW_PAGING_LEVELS != 2) @@ -593,7 +593,7 @@ shadow_l1_index(mfn_t *smfn, u32 guest_i #endif } -static inline u32 +static u32 shadow_l2_index(mfn_t *smfn, u32 guest_index) { #if (GUEST_PAGING_LEVELS == 2) && (SHADOW_PAGING_LEVELS != 2) @@ -613,13 +613,13 @@ shadow_l2_index(mfn_t *smfn, u32 guest_i #if GUEST_PAGING_LEVELS >= 4 -static inline u32 +static u32 shadow_l3_index(mfn_t *smfn, u32 guest_index) { return guest_index; } -static inline u32 +static u32 shadow_l4_index(mfn_t *smfn, u32 guest_index) { return guest_index; @@ -2582,7 +2582,7 @@ static int sh_page_fault(struct vcpu *v, mfn_t gmfn, sl1mfn=_mfn(0); shadow_l1e_t sl1e, *ptr_sl1e; paddr_t gpa; - struct x86_emulate_ctxt emul_ctxt; + struct sh_emulate_ctxt emul_ctxt; int r, mmio; fetch_type_t ft = 0; @@ -2808,26 +2808,21 @@ static int sh_page_fault(struct vcpu *v, return EXCRET_fault_fixed; emulate: - /* Take the register set we were called with */ - if ( is_hvm_domain(d) ) - hvm_store_cpu_guest_regs(v, regs, NULL); - emul_ctxt.regs = regs; - emul_ctxt.cr2 = va; - emul_ctxt.mode = (is_hvm_domain(d) ? - hvm_guest_x86_mode(v) : X86EMUL_MODE_HOST); - + if ( !is_hvm_domain(d) || !guest_mode(regs) ) + goto not_a_shadow_fault; + + hvm_store_cpu_guest_regs(v, regs, NULL); SHADOW_PRINTK("emulate: eip=%#lx\n", regs->eip); - v->arch.shadow.propagate_fault = 0; + shadow_init_emulation(&emul_ctxt, regs); /* * We do not emulate user writes. Instead we use them as a hint that the * page is no longer a page table. This behaviour differs from native, but * it seems very unlikely that any OS grants user access to page tables. - * We also disallow guest PTE updates from within Xen. */ - if ( (regs->error_code & PFEC_user_mode) || !guest_mode(regs) || - x86_emulate_memop(&emul_ctxt, &shadow_emulator_ops) ) + if ( (regs->error_code & PFEC_user_mode) || + x86_emulate_memop(&emul_ctxt.ctxt, &shadow_emulator_ops) ) { SHADOW_PRINTK("emulator failure, unshadowing mfn %#lx\n", mfn_x(gmfn)); @@ -2836,19 +2831,10 @@ static int sh_page_fault(struct vcpu *v, * to support more operations in the emulator. More likely, * though, this is a hint that this page should not be shadowed. */ shadow_remove_all_shadows(v, gmfn); - /* This means that actual missing operations will cause the - * guest to loop on the same page fault. */ - goto done; - } - - /* Emulation triggered another page fault? */ - if ( v->arch.shadow.propagate_fault ) - goto not_a_shadow_fault; + } /* Emulator has changed the user registers: write back */ - if ( is_hvm_domain(d) ) - hvm_load_cpu_guest_regs(v, regs); - + hvm_load_cpu_guest_regs(v, regs); goto done; mmio: @@ -3787,11 +3773,11 @@ int sh_remove_l3_shadow(struct vcpu *v, * or NULL for error. */ static inline void * emulate_map_dest(struct vcpu *v, unsigned long vaddr, - struct x86_emulate_ctxt *ctxt, + struct sh_emulate_ctxt *sh_ctxt, mfn_t *mfnp) { walk_t gw; - u32 flags; + u32 flags, errcode; gfn_t gfn; mfn_t mfn; @@ -3802,13 +3788,17 @@ static inline void * emulate_map_dest(st sh_audit_gw(v, &gw); unmap_walk(v, &gw); - if ( !(flags & _PAGE_PRESENT) - || !(flags & _PAGE_RW) - || (!(flags & _PAGE_USER) && ring_3(ctxt->regs)) ) - { - /* This write would have faulted even on bare metal */ - v->arch.shadow.propagate_fault = 1; - return NULL; + if ( !(flags & _PAGE_PRESENT) ) + { + errcode = 0; + goto page_fault; + } + + if ( !(flags & _PAGE_RW) || + (!(flags & _PAGE_USER) && ring_3(sh_ctxt->ctxt.regs)) ) + { + errcode = PFEC_page_present; + goto page_fault; } /* Attempted a write to a bad gfn? This should never happen: @@ -3818,11 +3808,18 @@ static inline void * emulate_map_dest(st ASSERT(sh_mfn_is_a_page_table(mfn)); *mfnp = mfn; return sh_map_domain_page(mfn) + (vaddr & ~PAGE_MASK); + + page_fault: + errcode |= PFEC_write_access; + if ( ring_3(sh_ctxt->ctxt.regs) ) + errcode |= PFEC_user_mode; + hvm_inject_exception(TRAP_page_fault, errcode, vaddr); + return NULL; } int sh_x86_emulate_write(struct vcpu *v, unsigned long vaddr, void *src, - u32 bytes, struct x86_emulate_ctxt *ctxt) + u32 bytes, struct sh_emulate_ctxt *sh_ctxt) { mfn_t mfn; void *addr; @@ -3833,7 +3830,7 @@ sh_x86_emulate_write(struct vcpu *v, uns ASSERT(shadow_lock_is_acquired(v->domain)); ASSERT(((vaddr & ~PAGE_MASK) + bytes) <= PAGE_SIZE); - if ( (addr = emulate_map_dest(v, vaddr, ctxt, &mfn)) == NULL ) + if ( (addr = emulate_map_dest(v, vaddr, sh_ctxt, &mfn)) == NULL ) return X86EMUL_PROPAGATE_FAULT; memcpy(addr, src, bytes); @@ -3851,7 +3848,7 @@ int int sh_x86_emulate_cmpxchg(struct vcpu *v, unsigned long vaddr, unsigned long old, unsigned long new, - unsigned int bytes, struct x86_emulate_ctxt *ctxt) + unsigned int bytes, struct sh_emulate_ctxt *sh_ctxt) { mfn_t mfn; void *addr; @@ -3864,7 +3861,7 @@ sh_x86_emulate_cmpxchg(struct vcpu *v, u if ( vaddr & (bytes-1) ) return X86EMUL_UNHANDLEABLE; - if ( (addr = emulate_map_dest(v, vaddr, ctxt, &mfn)) == NULL ) + if ( (addr = emulate_map_dest(v, vaddr, sh_ctxt, &mfn)) == NULL ) return X86EMUL_PROPAGATE_FAULT; switch ( bytes ) @@ -3900,7 +3897,7 @@ sh_x86_emulate_cmpxchg8b(struct vcpu *v, sh_x86_emulate_cmpxchg8b(struct vcpu *v, unsigned long vaddr, unsigned long old_lo, unsigned long old_hi, unsigned long new_lo, unsigned long new_hi, - struct x86_emulate_ctxt *ctxt) + struct sh_emulate_ctxt *sh_ctxt) { mfn_t mfn; void *addr; @@ -3912,7 +3909,7 @@ sh_x86_emulate_cmpxchg8b(struct vcpu *v, if ( vaddr & 7 ) return X86EMUL_UNHANDLEABLE; - if ( (addr = emulate_map_dest(v, vaddr, ctxt, &mfn)) == NULL ) + if ( (addr = emulate_map_dest(v, vaddr, sh_ctxt, &mfn)) == NULL ) return X86EMUL_PROPAGATE_FAULT; old = (((u64) old_hi) << 32) | (u64) old_lo; diff -r 6fdbf173142d -r d603aed5ad6d xen/arch/x86/mm/shadow/private.h --- a/xen/arch/x86/mm/shadow/private.h Sat Dec 02 15:19:50 2006 -0700 +++ b/xen/arch/x86/mm/shadow/private.h Mon Dec 04 08:24:41 2006 -0700 @@ -506,6 +506,25 @@ static inline void sh_unpin(struct vcpu } } + +/**************************************************************************/ +/* PTE-write emulation. */ + +struct sh_emulate_ctxt { + struct x86_emulate_ctxt ctxt; + + /* Cache of up to 15 bytes of instruction. */ + uint8_t insn_buf[15]; + uint8_t insn_buf_bytes; + + /* Cache of segment registers already gathered for this emulation. */ + unsigned int valid_seg_regs; + struct segment_register seg_reg[6]; +}; + +void shadow_init_emulation(struct sh_emulate_ctxt *sh_ctxt, + struct cpu_user_regs *regs); + #endif /* _XEN_SHADOW_PRIVATE_H */ /* diff -r 6fdbf173142d -r d603aed5ad6d xen/arch/x86/oprofile/op_model_athlon.c --- a/xen/arch/x86/oprofile/op_model_athlon.c Sat Dec 02 15:19:50 2006 -0700 +++ b/xen/arch/x86/oprofile/op_model_athlon.c Mon Dec 04 08:24:41 2006 -0700 @@ -113,14 +113,15 @@ static int athlon_check_ctrs(unsigned in unsigned long eip = regs->eip; int mode = 0; struct vcpu *v = current; - struct cpu_user_regs tmp_regs; + struct cpu_user_regs *guest_regs = guest_cpu_user_regs(); if (!guest_mode(regs) && (regs->eip == (unsigned long)svm_stgi_label)) { /* SVM guest was running when NMI occurred */ - hvm_store_cpu_guest_regs(v, &tmp_regs, NULL); - eip = tmp_regs.eip; - mode = xenoprofile_get_mode(v, &tmp_regs); + ASSERT(is_hvm_vcpu(v)); + hvm_store_cpu_guest_regs(v, guest_regs, NULL); + eip = guest_regs->eip; + mode = xenoprofile_get_mode(v, guest_regs); } else { eip = regs->eip; mode = xenoprofile_get_mode(v, regs); diff -r 6fdbf173142d -r d603aed5ad6d xen/arch/x86/setup.c --- a/xen/arch/x86/setup.c Sat Dec 02 15:19:50 2006 -0700 +++ b/xen/arch/x86/setup.c Mon Dec 04 08:24:41 2006 -0700 @@ -27,6 +27,7 @@ #include <asm/shadow.h> #include <asm/e820.h> #include <acm/acm_hooks.h> +#include <xen/kexec.h> extern void dmi_scan_machine(void); extern void generic_apic_probe(void); @@ -273,6 +274,20 @@ static void srat_detect_node(int cpu) printk(KERN_INFO "CPU %d APIC %d -> Node %d\n", cpu, apicid, node); } +void __init move_memory(unsigned long dst, + unsigned long src_start, unsigned long src_end) +{ +#if defined(CONFIG_X86_32) + memmove((void *)dst, /* use low mapping */ + (void *)src_start, /* use low mapping */ + src_end - src_start); +#elif defined(CONFIG_X86_64) + memmove(__va(dst), + __va(src_start), + src_end - src_start); +#endif +} + void __init __start_xen(multiboot_info_t *mbi) { char __cmdline[] = "", *cmdline = __cmdline; @@ -415,15 +430,8 @@ void __init __start_xen(multiboot_info_t initial_images_start = xenheap_phys_end; initial_images_end = initial_images_start + modules_length; -#if defined(CONFIG_X86_32) - memmove((void *)initial_images_start, /* use low mapping */ - (void *)mod[0].mod_start, /* use low mapping */ - mod[mbi->mods_count-1].mod_end - mod[0].mod_start); -#elif defined(CONFIG_X86_64) - memmove(__va(initial_images_start), - __va(mod[0].mod_start), - mod[mbi->mods_count-1].mod_end - mod[0].mod_start); -#endif + move_memory(initial_images_start, + mod[0].mod_start, mod[mbi->mods_count-1].mod_end); /* Initialise boot-time allocator with all RAM situated after modules. */ xenheap_phys_start = init_boot_allocator(__pa(&_end)); @@ -471,10 +479,56 @@ void __init __start_xen(multiboot_info_t #endif } + if ( kexec_crash_area.size > 0 ) + { + unsigned long kdump_start, kdump_size, k; + + /* Mark images pages as free for now. */ + + init_boot_pages(initial_images_start, initial_images_end); + + kdump_start = kexec_crash_area.start; + kdump_size = kexec_crash_area.size; + + printk("Kdump: %luMB (%lukB) at 0x%lx\n", + kdump_size >> 20, + kdump_size >> 10, + kdump_start); + + if ( (kdump_start & ~PAGE_MASK) || (kdump_size & ~PAGE_MASK) ) + panic("Kdump parameters not page aligned\n"); + + kdump_start >>= PAGE_SHIFT; + kdump_size >>= PAGE_SHIFT; + + /* allocate pages for Kdump memory area */ + + k = alloc_boot_pages_at(kdump_size, kdump_start); + + if ( k != kdump_start ) + panic("Unable to reserve Kdump memory\n"); + + /* allocate pages for relocated initial images */ + + k = ((initial_images_end - initial_images_start) & ~PAGE_MASK) ? 1 : 0; + k += (initial_images_end - initial_images_start) >> PAGE_SHIFT; + + k = alloc_boot_pages(k, 1); + + if ( !k ) + panic("Unable to allocate initial images memory\n"); + + move_memory(k << PAGE_SHIFT, initial_images_start, initial_images_end); + + initial_images_end -= initial_images_start; + initial_images_start = k << PAGE_SHIFT; + initial_images_end += initial_images_start; + } + memguard_init(); percpu_guard_areas(); - printk("System RAM: %luMB (%lukB)\n", + printk("System RAM: %luMB (%lukB)\n", nr_pages >> (20 - PAGE_SHIFT), nr_pages << (PAGE_SHIFT - 10)); total_pages = nr_pages; diff -r 6fdbf173142d -r d603aed5ad6d xen/arch/x86/traps.c --- a/xen/arch/x86/traps.c Sat Dec 02 15:19:50 2006 -0700 +++ b/xen/arch/x86/traps.c Mon Dec 04 08:24:41 2006 -0700 @@ -45,6 +45,7 @@ #include <xen/iocap.h> #include <xen/nmi.h> #include <xen/version.h> +#include <xen/kexec.h> #include <asm/shadow.h> #include <asm/system.h> #include <asm/io.h> @@ -1633,6 +1634,7 @@ static void unknown_nmi_error(unsigned c printk("Uhhuh. NMI received for unknown reason %02x.\n", reason); printk("Dazed and confused, but trying to continue\n"); printk("Do you have a strange power saving mode enabled?\n"); + machine_crash_kexec(); } } diff -r 6fdbf173142d -r d603aed5ad6d xen/arch/x86/x86_32/entry.S --- a/xen/arch/x86/x86_32/entry.S Sat Dec 02 15:19:50 2006 -0700 +++ b/xen/arch/x86/x86_32/entry.S Mon Dec 04 08:24:41 2006 -0700 @@ -659,6 +659,7 @@ ENTRY(hypercall_table) .long do_hvm_op .long do_sysctl /* 35 */ .long do_domctl + .long do_kexec_op .rept NR_hypercalls-((.-hypercall_table)/4) .long do_ni_hypercall .endr @@ -701,6 +702,7 @@ ENTRY(hypercall_args_table) .byte 2 /* do_hvm_op */ .byte 1 /* do_sysctl */ /* 35 */ .byte 1 /* do_domctl */ + .byte 2 /* do_kexec_op */ .rept NR_hypercalls-(.-hypercall_args_table) .byte 0 /* do_ni_hypercall */ .endr diff -r 6fdbf173142d -r d603aed5ad6d xen/arch/x86/x86_64/entry.S --- a/xen/arch/x86/x86_64/entry.S Sat Dec 02 15:19:50 2006 -0700 +++ b/xen/arch/x86/x86_64/entry.S Mon Dec 04 08:24:41 2006 -0700 @@ -559,6 +559,7 @@ ENTRY(hypercall_table) .quad do_hvm_op .quad do_sysctl /* 35 */ .quad do_domctl + .quad do_kexec_op .rept NR_hypercalls-((.-hypercall_table)/8) .quad do_ni_hypercall .endr @@ -601,6 +602,7 @@ ENTRY(hypercall_args_table) .byte 2 /* do_hvm_op */ .byte 1 /* do_sysctl */ /* 35 */ .byte 1 /* do_domctl */ + .byte 2 /* do_kexec */ .rept NR_hypercalls-(.-hypercall_args_table) .byte 0 /* do_ni_hypercall */ .endr diff -r 6fdbf173142d -r d603aed5ad6d xen/arch/x86/x86_emulate.c --- a/xen/arch/x86/x86_emulate.c Sat Dec 02 15:19:50 2006 -0700 +++ b/xen/arch/x86/x86_emulate.c Mon Dec 04 08:24:41 2006 -0700 @@ -7,24 +7,17 @@ */ #ifndef __XEN__ -#include <stdio.h> +#include <stddef.h> #include <stdint.h> #include <public/xen.h> -#define dprintf(_f, _a...) printf( _f , ## _a ) #else #include <xen/config.h> #include <xen/types.h> #include <xen/lib.h> -#include <xen/mm.h> #include <asm/regs.h> -#define dprintf(_f, _a...) gdprintk(XENLOG_WARNING, _f , ## _a ) +#undef cmpxchg #endif #include <asm-x86/x86_emulate.h> - -#ifndef PFEC_write_access -#define PFEC_write_access (1U<<1) -#define PFEC_insn_fetch (1U<<4) -#endif /* * Opcode effective-address decode tables. @@ -38,6 +31,7 @@ /* Operand sizes: 8-bit operands or specified/overridden size. */ #define ByteOp (1<<0) /* 8-bit operands. */ /* Destination operand type. */ +#define DstBitBase (0<<1) /* Memory operand, bit string. */ #define ImplicitOps (1<<1) /* Implicit in opcode. No generic decode. */ #define DstReg (2<<1) /* Register operand. */ #define DstMem (3<<1) /* Memory operand. */ @@ -111,8 +105,8 @@ static uint8_t opcode_table[256] = { /* 0x90 - 0x9F */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xA0 - 0xA7 */ - ByteOp|DstReg|SrcMem|Mov, DstReg|SrcMem|Mov, - ByteOp|DstMem|SrcReg|Mov, DstMem|SrcReg|Mov, + ByteOp|ImplicitOps|Mov, ImplicitOps|Mov, + ByteOp|ImplicitOps|Mov, ImplicitOps|Mov, ByteOp|ImplicitOps|Mov, ImplicitOps|Mov, 0, 0, /* 0xA8 - 0xAF */ 0, 0, ByteOp|ImplicitOps|Mov, ImplicitOps|Mov, @@ -170,17 +164,21 @@ static uint8_t twobyte_table[256] = { /* 0x90 - 0x9F */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xA0 - 0xA7 */ - 0, 0, 0, DstMem|SrcReg|ModRM, 0, 0, 0, 0, + 0, 0, 0, DstBitBase|SrcReg|ModRM, 0, 0, 0, 0, /* 0xA8 - 0xAF */ - 0, 0, 0, DstMem|SrcReg|ModRM, 0, 0, 0, 0, + 0, 0, 0, DstBitBase|SrcReg|ModRM, 0, 0, 0, 0, /* 0xB0 - 0xB7 */ - ByteOp|DstMem|SrcReg|ModRM, DstMem|SrcReg|ModRM, 0, DstMem|SrcReg|ModRM, + ByteOp|DstMem|SrcReg|ModRM, DstMem|SrcReg|ModRM, + 0, DstBitBase|SrcReg|ModRM, 0, 0, ByteOp|DstReg|SrcMem|ModRM|Mov, DstReg|SrcMem16|ModRM|Mov, /* 0xB8 - 0xBF */ - 0, 0, DstMem|SrcImmByte|ModRM, DstMem|SrcReg|ModRM, + 0, 0, DstBitBase|SrcImmByte|ModRM, DstBitBase|SrcReg|ModRM, 0, 0, ByteOp|DstReg|SrcMem|ModRM|Mov, DstReg|SrcMem16|ModRM|Mov, - /* 0xC0 - 0xCF */ - 0, 0, 0, 0, 0, 0, 0, ImplicitOps|ModRM, 0, 0, 0, 0, 0, 0, 0, 0, + /* 0xC0 - 0xC7 */ + ByteOp|DstMem|SrcReg|ModRM, DstMem|SrcReg|ModRM, 0, 0, + 0, 0, 0, ImplicitOps|ModRM, + /* 0xC8 - 0xCF */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 0xD0 - 0xDF */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xE0 - 0xEF */ @@ -193,7 +191,12 @@ struct operand { struct operand { enum { OP_REG, OP_MEM, OP_IMM } type; unsigned int bytes; - unsigned long val, orig_val, *ptr; + unsigned long val, orig_val; + /* OP_REG: Pointer to register field. */ + unsigned long *reg; + /* OP_MEM: Segment and offset. */ + enum x86_segment mem_seg; + unsigned long mem_off; }; /* EFLAGS bit definitions. */ @@ -366,24 +369,23 @@ do{ __asm__ __volatile__ ( #endif /* __i386__ */ /* Fetch next part of the instruction being emulated. */ -#define _insn_fetch(_size) \ -({ unsigned long _x, _ptr = _regs.eip; \ - if ( mode == X86EMUL_MODE_REAL ) _ptr += _regs.cs << 4; \ - rc = ops->read_std(_ptr, &_x, (_size), ctxt); \ +#define insn_fetch_bytes(_size) \ +({ unsigned long _x; \ + rc = ops->insn_fetch(x86_seg_cs, _regs.eip, &_x, (_size), ctxt); \ if ( rc != 0 ) \ goto done; \ _regs.eip += (_size); \ _x; \ }) -#define insn_fetch(_type) ((_type)_insn_fetch(sizeof(_type))) - -/* Access/update address held in a register, based on addressing mode. */ -#define register_address(sel, reg) \ -({ unsigned long __reg = (reg); \ - (((mode == X86EMUL_MODE_REAL) ? ((unsigned long)(sel) << 4) : 0) + \ - ((ad_bytes == sizeof(unsigned long)) ? __reg : \ - (__reg & ((1UL << (ad_bytes << 3)) - 1)))); \ +#define insn_fetch_type(_type) ((_type)insn_fetch_bytes(sizeof(_type))) + +#define truncate_ea(ea) \ +({ unsigned long __ea = (ea); \ + ((ad_bytes == sizeof(unsigned long)) ? __ea : \ + (__ea & ((1UL << (ad_bytes << 3)) - 1))); \ }) + +/* Update address held in a register, based on addressing mode. */ #define register_address_increment(reg, inc) \ do { \ int _inc = (inc); /* signed type ensures sign extension to long */ \ @@ -393,17 +395,6 @@ do { (reg) = ((reg) & ~((1UL << (ad_bytes << 3)) - 1)) | \ (((reg) + _inc) & ((1UL << (ad_bytes << 3)) - 1)); \ } while (0) - -/* - * We cannot handle a page fault on a data access that straddles two pages - * and faults on the second page. This is because CR2 is not equal to the - * memory operand's effective address in this case. Rather than fix up the - * effective address it is okay for us to fail the emulation. - */ -#define page_boundary_test() do { \ - if ( ((cr2 & (PAGE_SIZE-1)) == 0) && ((ea & 7) != 0) ) \ - goto bad_ea; \ -} while ( 0 ) void * decode_register( @@ -445,31 +436,6 @@ decode_register( return p; } -static void -dump_instr( - struct x86_emulate_ctxt *ctxt, - struct x86_emulate_ops *ops) -{ -#ifdef __XEN__ - int i; - unsigned long x, pc; - - pc = ctxt->regs->eip; - if ( ctxt->mode == X86EMUL_MODE_REAL ) - pc += ctxt->regs->cs << 4; - - dprintf("Instr:"); - for ( i = 0; i < 16; i++, pc++ ) - { - if ( ops->read_std(pc, &x, 1, ctxt) != 0 ) - printk(" ??"); - else - printk(" %02x", (uint8_t)x); - } - printk("\n"); -#endif -} - int x86_emulate_memop( struct x86_emulate_ctxt *ctxt, @@ -480,19 +446,13 @@ x86_emulate_memop( uint8_t b, d, sib, sib_index, sib_base, twobyte = 0, rex_prefix = 0; uint8_t modrm, modrm_mod = 0, modrm_reg = 0, modrm_rm = 0; - uint16_t *seg = &_regs.ds; /* override segment */ unsigned int op_bytes, ad_bytes, lock_prefix = 0, rep_prefix = 0, i; int rc = 0; struct operand src, dst; - unsigned long ea = 0, cr2 = ctxt->cr2; int mode = ctxt->mode; - /* - * We do not emulate faults on instruction fetch. We assume that the - * guest never executes out of a special memory area. - */ - if ( _regs.error_code & PFEC_insn_fetch ) - return -1; + enum x86_segment ea_seg = x86_seg_ds; + unsigned long ea_off = 0; switch ( mode ) { @@ -516,7 +476,7 @@ x86_emulate_memop( /* Legacy prefixes. */ for ( i = 0; i < 8; i++ ) { - switch ( b = insn_fetch(uint8_t) ) + switch ( b = insn_fetch_type(uint8_t) ) { case 0x66: /* operand-size override */ op_bytes ^= 6; /* switch between 2/4 bytes */ @@ -528,22 +488,22 @@ x86_emulate_memop( ad_bytes ^= 6; /* switch between 2/4 bytes */ break; case 0x2e: /* CS override */ - seg = &_regs.cs; + ea_seg = x86_seg_cs; break; case 0x3e: /* DS override */ - seg = &_regs.ds; + ea_seg = x86_seg_ds; break; case 0x26: /* ES override */ - seg = &_regs.es; + ea_seg = x86_seg_es; break; case 0x64: /* FS override */ - seg = &_regs.fs; + ea_seg = x86_seg_fs; break; case 0x65: /* GS override */ - seg = &_regs.gs; + ea_seg = x86_seg_gs; break; case 0x36: /* SS override */ - seg = &_regs.ss; + ea_seg = x86_seg_ss; break; case 0xf0: /* LOCK */ lock_prefix = 1; @@ -565,7 +525,7 @@ x86_emulate_memop( rex_prefix = b; if ( b & 8 ) /* REX.W */ op_bytes = 8; - b = insn_fetch(uint8_t); + b = insn_fetch_type(uint8_t); } /* Opcode byte(s). */ @@ -576,7 +536,7 @@ x86_emulate_memop( if ( b == 0x0f ) { twobyte = 1; - b = insn_fetch(uint8_t); + b = insn_fetch_type(uint8_t); d = twobyte_table[b]; } @@ -588,36 +548,40 @@ x86_emulate_memop( /* ModRM and SIB bytes. */ if ( d & ModRM ) { - modrm = insn_fetch(uint8_t); + modrm = insn_fetch_type(uint8_t); modrm_mod = (modrm & 0xc0) >> 6; modrm_reg = ((rex_prefix & 4) << 1) | ((modrm & 0x38) >> 3); modrm_rm = modrm & 0x07; if ( modrm_mod == 3 ) - { - dprintf("Cannot parse ModRM.mod == 3.\n"); goto cannot_emulate; - } if ( ad_bytes == 2 ) { /* 16-bit ModR/M decode. */ switch ( modrm_rm ) { - case 0: ea = _regs.ebx + _regs.esi; break; - case 1: ea = _regs.ebx + _regs.edi; break; - case 2: ea = _regs.ebp + _regs.esi; break; - case 3: ea = _regs.ebp + _regs.edi; break; - case 4: ea = _regs.esi; break; - case 5: ea = _regs.edi; break; - case 6: ea = _regs.ebp; break; - case 7: ea = _regs.ebx; break; + case 0: ea_off = _regs.ebx + _regs.esi; break; + case 1: ea_off = _regs.ebx + _regs.edi; break; + case 2: ea_off = _regs.ebp + _regs.esi; break; + case 3: ea_off = _regs.ebp + _regs.edi; break; + case 4: ea_off = _regs.esi; break; + case 5: ea_off = _regs.edi; break; + case 6: ea_off = _regs.ebp; break; + case 7: ea_off = _regs.ebx; break; } switch ( modrm_mod ) { - case 0: if ( modrm_rm == 6 ) ea = insn_fetch(int16_t); break; - case 1: ea += insn_fetch(int8_t); break; - case 2: ea += insn_fetch(int16_t); break; + case 0: + if ( modrm_rm == 6 ) + ea_off = insn_fetch_type(int16_t); + break; + case 1: + ea_off += insn_fetch_type(int8_t); + break; + case 2: + ea_off += insn_fetch_type(int16_t); + break; } } else @@ -625,87 +589,58 @@ x86_emulate_memop( /* 32/64-bit ModR/M decode. */ if ( modrm_rm == 4 ) { - sib = insn_fetch(uint8_t); - sib_index = ((sib >> 3) & 7) | ((modrm << 2) & 8); - sib_base = (sib & 7) | ((modrm << 3) & 8); + sib = insn_fetch_type(uint8_t); + sib_index = ((sib >> 3) & 7) | ((rex_prefix << 2) & 8); + sib_base = (sib & 7) | ((rex_prefix << 3) & 8); if ( sib_index != 4 ) - ea = *(long *)decode_register(sib_index, &_regs, 0); - ea <<= (sib >> 6) & 3; + ea_off = *(long *)decode_register(sib_index, &_regs, 0); + ea_off <<= (sib >> 6) & 3; if ( (modrm_mod == 0) && ((sib_base & 7) == 5) ) - ea += insn_fetch(int32_t); + ea_off += insn_fetch_type(int32_t); else - ea += *(long *)decode_register(sib_base, &_regs, 0); + ea_off += *(long *)decode_register(sib_base, &_regs, 0); } else { modrm_rm |= (rex_prefix & 1) << 3; - ea = *(long *)decode_register(modrm_rm, &_regs, 0); + ea_off = *(long *)decode_register(modrm_rm, &_regs, 0); } switch ( modrm_mod ) { case 0: if ( (modrm_rm & 7) != 5 ) break; - ea = insn_fetch(int32_t); + ea_off = insn_fetch_type(int32_t); if ( mode != X86EMUL_MODE_PROT64 ) break; /* Relative to RIP of next instruction. Argh! */ - ea += _regs.eip; + ea_off += _regs.eip; if ( (d & SrcMask) == SrcImm ) - ea += (d & ByteOp) ? 1 : ((op_bytes == 8) ? 4 : op_bytes); + ea_off += (d & ByteOp) ? 1 : + ((op_bytes == 8) ? 4 : op_bytes); else if ( (d & SrcMask) == SrcImmByte ) - ea += 1; + ea_off += 1; else if ( ((b == 0xf6) || (b == 0xf7)) && ((modrm_reg & 7) <= 1) ) /* Special case in Grp3: test has immediate operand. */ - ea += (d & ByteOp) ? 1 + ea_off += (d & ByteOp) ? 1 : ((op_bytes == 8) ? 4 : op_bytes); break; - case 1: ea += insn_fetch(int8_t); break; - case 2: ea += insn_fetch(int32_t); break; + case 1: + ea_off += insn_fetch_type(int8_t); + break; + case 2: + ea_off += insn_fetch_type(int32_t); + break; } } - ea = register_address(*seg, ea); - page_boundary_test(); - } - - /* Decode and fetch the destination operand: register or memory. */ - switch ( d & DstMask ) - { - case ImplicitOps: - /* Special instructions do their own operand decoding. */ + ea_off = truncate_ea(ea_off); + } + + /* Special instructions do their own operand decoding. */ + if ( (d & DstMask) == ImplicitOps ) goto special_insn; - case DstReg: - dst.type = OP_REG; - if ( d & ByteOp ) - { - dst.ptr = decode_register(modrm_reg, &_regs, (rex_prefix == 0)); - dst.val = *(uint8_t *)dst.ptr; - dst.bytes = 1; - } - else - { - dst.ptr = decode_register(modrm_reg, &_regs, 0); - switch ( (dst.bytes = op_bytes) ) - { - case 2: dst.val = *(uint16_t *)dst.ptr; break; - case 4: dst.val = *(uint32_t *)dst.ptr; break; - case 8: dst.val = *(uint64_t *)dst.ptr; break; - } - } - break; - case DstMem: - dst.type = OP_MEM; - dst.ptr = (unsigned long *)cr2; - dst.bytes = (d & ByteOp) ? 1 : op_bytes; - if ( !(d & Mov) && /* optimisation - avoid slow emulated read */ - ((rc = ops->read_emulated((unsigned long)dst.ptr, - &dst.val, dst.bytes, ctxt)) != 0) ) - goto done; - break; - } - dst.orig_val = dst.val; /* Decode and fetch the source operand: register, memory or immediate. */ switch ( d & SrcMask ) @@ -716,18 +651,18 @@ x86_emulate_memop( src.type = OP_REG; if ( d & ByteOp ) { - src.ptr = decode_register(modrm_reg, &_regs, (rex_prefix == 0)); - src.val = src.orig_val = *(uint8_t *)src.ptr; + src.reg = decode_register(modrm_reg, &_regs, (rex_prefix == 0)); + src.val = src.orig_val = *(uint8_t *)src.reg; src.bytes = 1; } else { - src.ptr = decode_register(modrm_reg, &_regs, 0); + src.reg = decode_register(modrm_reg, &_regs, 0); switch ( (src.bytes = op_bytes) ) { - case 2: src.val = src.orig_val = *(uint16_t *)src.ptr; break; - case 4: src.val = src.orig_val = *(uint32_t *)src.ptr; break; - case 8: src.val = src.orig_val = *(uint64_t *)src.ptr; break; + case 2: src.val = src.orig_val = *(uint16_t *)src.reg; break; + case 4: src.val = src.orig_val = *(uint32_t *)src.reg; break; + case 8: src.val = src.orig_val = *(uint64_t *)src.reg; break; } } break; @@ -741,32 +676,101 @@ x86_emulate_memop( src.bytes = (d & ByteOp) ? 1 : op_bytes; srcmem_common: src.type = OP_MEM; - src.ptr = (unsigned long *)cr2; - if ( (rc = ops->read_emulated((unsigned long)src.ptr, - &src.val, src.bytes, ctxt)) != 0 ) + src.mem_seg = ea_seg; + src.mem_off = ea_off; + if ( (rc = ops->read(src.mem_seg, src.mem_off, + &src.val, src.bytes, ctxt)) != 0 ) goto done; src.orig_val = src.val; break; case SrcImm: src.type = OP_IMM; - src.ptr = (unsigned long *)_regs.eip; src.bytes = (d & ByteOp) ? 1 : op_bytes; if ( src.bytes == 8 ) src.bytes = 4; /* NB. Immediates are sign-extended as necessary. */ switch ( src.bytes ) { - case 1: src.val = insn_fetch(int8_t); break; - case 2: src.val = insn_fetch(int16_t); break; - case 4: src.val = insn_fetch(int32_t); break; + case 1: src.val = insn_fetch_type(int8_t); break; + case 2: src.val = insn_fetch_type(int16_t); break; + case 4: src.val = insn_fetch_type(int32_t); break; } break; case SrcImmByte: src.type = OP_IMM; - src.ptr = (unsigned long *)_regs.eip; src.bytes = 1; - src.val = insn_fetch(int8_t); - break; - } + src.val = insn_fetch_type(int8_t); + break; + } + + /* Decode and fetch the destination operand: register or memory. */ + switch ( d & DstMask ) + { + case DstReg: + dst.type = OP_REG; + if ( d & ByteOp ) + { + dst.reg = decode_register(modrm_reg, &_regs, (rex_prefix == 0)); + dst.val = *(uint8_t *)dst.reg; + dst.bytes = 1; + } + else + { _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |