[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 Alex Williamson <alex.williamson@xxxxxx> # Date 1175296722 21600 # Node ID fc9e2f7920c95229caaf5ad8fc44965dd891f600 # Parent e7da2fcb7a226a4a96a97f1c17711649309aa15c # Parent b0b20a09d2534a97dd871c1fe787af9a32864c0c merge with xen-unstable.hg --- .hgignore | 1 Config.mk | 14 docs/xen-api/xenapi-datamodel.tex | 273 ++ linux-2.6-xen-sparse/arch/x86_64/kernel/entry-xen.S | 16 linux-2.6-xen-sparse/arch/x86_64/kernel/head64-xen.c | 2 linux-2.6-xen-sparse/arch/x86_64/kernel/setup-xen.c | 2 linux-2.6-xen-sparse/drivers/xen/balloon/balloon.c | 1 linux-2.6-xen-sparse/drivers/xen/core/machine_reboot.c | 2 linux-2.6-xen-sparse/drivers/xen/core/reboot.c | 19 linux-2.6-xen-sparse/drivers/xen/evtchn/evtchn.c | 35 linux-2.6-xen-sparse/drivers/xen/pciback/conf_space_capability_pm.c | 35 linux-2.6-xen-sparse/drivers/xen/pciback/conf_space_header.c | 14 linux-2.6-xen-sparse/drivers/xen/pciback/pci_stub.c | 53 linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_dev.c | 104 linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c | 60 linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.h | 1 linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe_backend.c | 25 tools/Rules.mk | 6 tools/examples/Makefile | 2 tools/examples/xend-config-xenapi.sxp | 195 + tools/examples/xend-config.sxp | 14 tools/examples/xm-config-xenapi.xml | 43 tools/ioemu/hw/ne2000.c | 13 tools/ioemu/hw/pcnet.c | 58 tools/ioemu/hw/piix4acpi.c | 20 tools/ioemu/hw/rtl8139.c | 9 tools/ioemu/hw/usb-uhci.c | 1 tools/ioemu/vl.c | 7 tools/libxc/xc_hvm_restore.c | 29 tools/libxen/Makefile | 3 tools/libxen/include/xen_event.h | 102 tools/libxen/include/xen_event_decl.h | 25 tools/libxen/include/xen_event_operation.h | 82 tools/libxen/include/xen_event_operation_internal.h | 37 tools/libxen/include/xen_network.h | 33 tools/libxen/src/xen_common.c | 132 - tools/libxen/src/xen_event.c | 123 tools/libxen/src/xen_event_operation.c | 75 tools/libxen/src/xen_network.c | 74 tools/libxen/test/test_event_handling.c | 211 + tools/pygrub/src/pygrub | 17 tools/python/xen/lowlevel/xc/xc.c | 28 tools/python/xen/util/xmlrpcclient.py | 123 tools/python/xen/util/xmlrpclib2.py | 71 tools/python/xen/xend/XendAPI.py | 400 ++- tools/python/xen/xend/XendCheckpoint.py | 8 tools/python/xen/xend/XendClient.py | 2 tools/python/xen/xend/XendConfig.py | 15 tools/python/xen/xend/XendConstants.py | 7 tools/python/xen/xend/XendDomain.py | 20 tools/python/xen/xend/XendDomainInfo.py | 20 tools/python/xen/xend/XendLogging.py | 1 tools/python/xen/xend/XendMonitor.py | 16 tools/python/xen/xend/XendNetwork.py | 43 tools/python/xen/xend/XendNode.py | 32 tools/python/xen/xend/XendOptions.py | 8 tools/python/xen/xend/XendPIFMetrics.py | 8 tools/python/xen/xend/XendStateStore.py | 13 tools/python/xen/xend/XendVMMetrics.py | 11 tools/python/xen/xend/server/SSLXMLRPCServer.py | 103 tools/python/xen/xend/server/SrvDaemon.py | 94 tools/python/xen/xend/server/SrvServer.py | 96 tools/python/xen/xend/server/XMLRPCServer.py | 50 tools/python/xen/xm/XenAPI.py | 16 tools/python/xen/xm/create.dtd | 17 tools/python/xen/xm/create.py | 68 tools/python/xen/xm/main.py | 68 tools/python/xen/xm/messages/en/xen-xm.po | 5 tools/python/xen/xm/opts.py | 19 tools/python/xen/xm/xenapi_create.py | 193 + tools/security/policies/security_policy.xsd | 15 tools/security/secpol_tool.c | 62 tools/security/secpol_xml2bin.c | 78 tools/security/secpol_xml2bin.h | 60 tools/xcutils/xc_restore.c | 2 tools/xm-test/lib/XmTestLib/XenAPIDomain.py | 1 tools/xm-test/tests/destroy/06_destroy_dom0_neg.py | 2 unmodified_drivers/linux-2.6/platform-pci/platform-pci.c | 35 xen/acm/acm_chinesewall_hooks.c | 13 xen/acm/acm_core.c | 67 xen/acm/acm_null_hooks.c | 2 xen/acm/acm_policy.c | 42 xen/acm/acm_simple_type_enforcement_hooks.c | 26 xen/arch/ia64/asm-offsets.c | 9 xen/arch/ia64/linux-xen/irq_ia64.c | 2 xen/arch/ia64/linux-xen/mca.c | 10 xen/arch/ia64/linux-xen/smp.c | 2 xen/arch/ia64/vmx/pal_emul.c | 2 xen/arch/ia64/vmx/vlsapic.c | 8 xen/arch/ia64/vmx/vmmu.c | 2 xen/arch/ia64/vmx/vmx_process.c | 2 xen/arch/ia64/vmx/vmx_support.c | 4 xen/arch/ia64/vmx/vmx_virt.c | 78 xen/arch/ia64/xen/dom0_ops.c | 4 xen/arch/ia64/xen/domain.c | 26 xen/arch/ia64/xen/faults.c | 2 xen/arch/ia64/xen/fw_emul.c | 4 xen/arch/ia64/xen/hypercall.c | 20 xen/arch/ia64/xen/hyperprivop.S | 13 xen/arch/ia64/xen/mm.c | 31 xen/arch/ia64/xen/privop.c | 30 xen/arch/ia64/xen/privop_stat.c | 86 xen/arch/ia64/xen/tlb_track.c | 42 xen/arch/ia64/xen/vcpu.c | 10 xen/arch/ia64/xen/vhpt.c | 40 xen/arch/powerpc/backtrace.c | 15 xen/arch/powerpc/domain.c | 11 xen/arch/powerpc/domain_build.c | 4 xen/arch/powerpc/mm.c | 12 xen/arch/x86/Rules.mk | 4 xen/arch/x86/apic.c | 2 xen/arch/x86/domain.c | 16 xen/arch/x86/domain_build.c | 8 xen/arch/x86/domctl.c | 4 xen/arch/x86/extable.c | 2 xen/arch/x86/hvm/hvm.c | 35 xen/arch/x86/hvm/io.c | 64 xen/arch/x86/hvm/save.c | 2 xen/arch/x86/hvm/svm/emulate.c | 4 xen/arch/x86/hvm/svm/intr.c | 122 xen/arch/x86/hvm/svm/svm.c | 1248 ++-------- xen/arch/x86/hvm/svm/vmcb.c | 8 xen/arch/x86/hvm/vlapic.c | 4 xen/arch/x86/hvm/vmx/intr.c | 35 xen/arch/x86/hvm/vmx/vmcs.c | 131 - xen/arch/x86/hvm/vmx/vmx.c | 213 - xen/arch/x86/hvm/vpt.c | 2 xen/arch/x86/i387.c | 4 xen/arch/x86/irq.c | 2 xen/arch/x86/mm.c | 48 xen/arch/x86/mm/hap/hap.c | 23 xen/arch/x86/mm/paging.c | 15 xen/arch/x86/mm/shadow/common.c | 44 xen/arch/x86/mm/shadow/multi.c | 62 xen/arch/x86/nmi.c | 16 xen/arch/x86/smp.c | 6 xen/arch/x86/time.c | 22 xen/arch/x86/traps.c | 30 xen/arch/x86/x86_32/asm-offsets.c | 19 xen/arch/x86/x86_32/domain_page.c | 6 xen/arch/x86/x86_32/entry.S | 18 xen/arch/x86/x86_32/seg_fixup.c | 2 xen/arch/x86/x86_32/traps.c | 2 xen/arch/x86/x86_64/asm-offsets.c | 34 xen/arch/x86/x86_64/compat/entry.S | 17 xen/arch/x86/x86_64/compat/traps.c | 2 xen/arch/x86/x86_64/entry.S | 44 xen/arch/x86/x86_64/traps.c | 2 xen/arch/x86/x86_emulate.c | 12 xen/common/compat/domain.c | 2 xen/common/domain.c | 124 xen/common/domctl.c | 77 xen/common/event_channel.c | 19 xen/common/grant_table.c | 16 xen/common/kernel.c | 2 xen/common/keyhandler.c | 8 xen/common/memory.c | 6 xen/common/multicall.c | 5 xen/common/page_alloc.c | 6 xen/common/perfc.c | 223 - xen/common/sched_credit.c | 5 xen/common/sched_sedf.c | 2 xen/common/schedule.c | 81 xen/drivers/char/console.c | 10 xen/include/acm/acm_core.h | 10 xen/include/acm/acm_hooks.h | 12 xen/include/asm-ia64/bug.h | 1 xen/include/asm-ia64/event.h | 6 xen/include/asm-ia64/linux-xen/asm/asmmacro.h | 4 xen/include/asm-ia64/linux-xen/asm/iosapic.h | 19 xen/include/asm-ia64/mm.h | 5 xen/include/asm-ia64/perfc_defn.h | 214 - xen/include/asm-ia64/privop_stat.h | 25 xen/include/asm-ia64/tlb_track.h | 4 xen/include/asm-ia64/vmx_vpd.h | 3 xen/include/asm-powerpc/bug.h | 1 xen/include/asm-powerpc/debugger.h | 4 xen/include/asm-powerpc/event.h | 8 xen/include/asm-powerpc/mm.h | 5 xen/include/asm-x86/bug.h | 6 xen/include/asm-x86/debugger.h | 3 xen/include/asm-x86/event.h | 6 xen/include/asm-x86/hvm/hvm.h | 2 xen/include/asm-x86/hvm/support.h | 41 xen/include/asm-x86/hvm/svm/emulate.h | 1 xen/include/asm-x86/hvm/svm/vmcb.h | 1 xen/include/asm-x86/hvm/vcpu.h | 4 xen/include/asm-x86/hvm/vmx/vmcs.h | 20 xen/include/asm-x86/hvm/vmx/vmx.h | 28 xen/include/asm-x86/i387.h | 11 xen/include/asm-x86/mm.h | 5 xen/include/asm-x86/msr.h | 4 xen/include/asm-x86/multicall.h | 104 xen/include/asm-x86/perfc_defn.h | 126 - xen/include/asm-x86/x86_32/asm_defns.h | 12 xen/include/asm-x86/x86_32/bug.h | 6 xen/include/asm-x86/x86_64/asm_defns.h | 19 xen/include/asm-x86/x86_64/bug.h | 6 xen/include/public/acm.h | 26 xen/include/public/foreign/Makefile | 4 xen/include/xen/event.h | 6 xen/include/xen/lib.h | 4 xen/include/xen/list.h | 704 +++++ xen/include/xen/perfc.h | 120 xen/include/xen/perfc_defn.h | 15 xen/include/xen/sched.h | 139 - xen/include/xen/spinlock.h | 7 xen/include/xen/types.h | 2 208 files changed, 5559 insertions(+), 3511 deletions(-) diff -r e7da2fcb7a22 -r fc9e2f7920c9 .hgignore --- a/.hgignore Fri Mar 30 10:27:15 2007 -0600 +++ b/.hgignore Fri Mar 30 17:18:42 2007 -0600 @@ -126,6 +126,7 @@ ^tools/ioemu/qemu\.pod$ ^tools/libxc/xen/.*$ ^tools/libxen/test/test_bindings$ +^tools/libxen/test/test_event_handling$ ^tools/libaio/src/.*\.ol$ ^tools/libaio/src/.*\.os$ ^tools/misc/cpuperf/cpuperf-perfcntr$ diff -r e7da2fcb7a22 -r fc9e2f7920c9 Config.mk --- a/Config.mk Fri Mar 30 10:27:15 2007 -0600 +++ b/Config.mk Fri Mar 30 17:18:42 2007 -0600 @@ -31,16 +31,26 @@ EXTRA_LIB += $(EXTRA_PREFIX)/$(LIBDIR) EXTRA_LIB += $(EXTRA_PREFIX)/$(LIBDIR) endif -# cc-option +# cc-option: Check if compiler supports first option, else fall back to second. # Usage: cflags-y += $(call cc-option,$(CC),-march=winchip-c6,-march=i586) cc-option = $(shell if test -z "`$(1) $(2) -S -o /dev/null -xc \ /dev/null 2>&1`"; then echo "$(2)"; else echo "$(3)"; fi ;) -# cc-ver +# cc-ver: Check compiler is at least specified version. Return boolean 'y'/'n'. # Usage: ifeq ($(call cc-ver,$(CC),0x030400),y) cc-ver = $(shell if [ $$((`$(1) -dumpversion | awk -F. \ '{ printf "0x%02x%02x%02x", $$1, $$2, $$3}'`)) -ge $$(($(2))) ]; \ then echo y; else echo n; fi ;) + +# cc-ver-check: Check compiler is at least specified version, else fail. +# Usage: $(call cc-ver-check,CC,0x030400,"Require at least gcc-3.4") +cc-ver-check = $(eval $(call cc-ver-check-closure,$(1),$(2),$(3))) +define cc-ver-check-closure + ifeq ($$(call cc-ver,$$($(1)),$(2)),n) + override $(1) = echo "*** FATAL BUILD ERROR: "$(3) >&2; exit 1; + cc-option := n + endif +endef ifneq ($(debug),y) CFLAGS += -DNDEBUG diff -r e7da2fcb7a22 -r fc9e2f7920c9 docs/xen-api/xenapi-datamodel.tex --- a/docs/xen-api/xenapi-datamodel.tex Fri Mar 30 10:27:15 2007 -0600 +++ b/docs/xen-api/xenapi-datamodel.tex Fri Mar 30 17:18:42 2007 -0600 @@ -24,6 +24,7 @@ Name & Description \\ \hline {\tt session} & A session \\ {\tt task} & A long-running asynchronous task \\ +{\tt event} & Asynchronous event registration and handling \\ {\tt VM} & A virtual machine (or 'guest') \\ {\tt VM\_metrics} & The metrics associated with a VM \\ {\tt VM\_guest\_metrics} & The metrics reported by the guest (as opposed to inferred from outside) \\ @@ -112,6 +113,17 @@ The following enumeration types are used \begin{longtable}{|ll|} \hline +{\tt enum event\_operation} & \\ +\hline +\hspace{0.5cm}{\tt add} & An object has been created \\ +\hspace{0.5cm}{\tt del} & An object has been deleted \\ +\hspace{0.5cm}{\tt mod} & An object has been modified \\ +\hline +\end{longtable} + +\vspace{1cm} +\begin{longtable}{|ll|} +\hline {\tt enum console\_protocol} & \\ \hline \hspace{0.5cm}{\tt vt100} & VT100 terminal \\ @@ -1013,6 +1025,116 @@ references to objects with match names \vspace{0.3cm} \vspace{0.3cm} \vspace{0.3cm} + +\vspace{1cm} +\newpage +\section{Class: event} +\subsection{Fields for class: event} +\begin{longtable}{|lllp{0.38\textwidth}|} +\hline +\multicolumn{1}{|l}{Name} & \multicolumn{3}{l|}{\bf event} \\ +\multicolumn{1}{|l}{Description} & \multicolumn{3}{l|}{\parbox{11cm}{\em +Asynchronous event registration and handling.}} \\ +\hline +Quals & Field & Type & Description \\ +\hline +$\mathit{RO}_\mathit{ins}$ & {\tt id} & int & An ID, monotonically increasing, and local to the current session \\ +$\mathit{RO}_\mathit{ins}$ & {\tt timestamp} & datetime & The time at which the event occurred \\ +$\mathit{RO}_\mathit{ins}$ & {\tt class} & string & The name of the class of the object that changed \\ +$\mathit{RO}_\mathit{ins}$ & {\tt operation} & event\_operation & The operation that was performed \\ +$\mathit{RO}_\mathit{ins}$ & {\tt ref} & string & A reference to the object that changed \\ +$\mathit{RO}_\mathit{ins}$ & {\tt obj\_uuid} & string & The uuid of the object that changed \\ +\hline +\end{longtable} +\subsection{RPCs associated with class: event} +\subsubsection{RPC name:~register} + +{\bf Overview:} +Registers this session with the event system. Specifying the empty list +will register for all classes. + + \noindent {\bf Signature:} +\begin{verbatim} void register (session_id s, string Set classes)\end{verbatim} + + +\noindent{\bf Arguments:} + + +\vspace{0.3cm} +\begin{tabular}{|c|c|p{7cm}|} + \hline +{\bf type} & {\bf name} & {\bf description} \\ \hline +{\tt string Set } & classes & register for events for the indicated classes \\ \hline + +\end{tabular} + +\vspace{0.3cm} + + \noindent {\bf Return Type:} +{\tt +void +} + + + +\vspace{0.3cm} +\vspace{0.3cm} +\vspace{0.3cm} +\subsubsection{RPC name:~unregister} + +{\bf Overview:} +Unregisters this session with the event system. + + \noindent {\bf Signature:} +\begin{verbatim} void unregister (session_id s, string Set classes)\end{verbatim} + + +\noindent{\bf Arguments:} + + +\vspace{0.3cm} +\begin{tabular}{|c|c|p{7cm}|} + \hline +{\bf type} & {\bf name} & {\bf description} \\ \hline +{\tt string Set } & classes & remove this session's registration for the indicated classes \\ \hline + +\end{tabular} + +\vspace{0.3cm} + + \noindent {\bf Return Type:} +{\tt +void +} + + + +\vspace{0.3cm} +\vspace{0.3cm} +\vspace{0.3cm} +\subsubsection{RPC name:~next} + +{\bf Overview:} +Blocking call which returns a (possibly empty) batch of events. + + \noindent {\bf Signature:} +\begin{verbatim} ((event record) Set) next (session_id s)\end{verbatim} + + +\vspace{0.3cm} + + \noindent {\bf Return Type:} +{\tt +(event record) Set +} + + +the batch of events +\vspace{0.3cm} + +\noindent{\bf Possible Error Codes:} {\tt SESSION\_NOT\_REGISTERED} + +\vspace{0.6cm} \vspace{1cm} \newpage @@ -6549,6 +6671,7 @@ Quals & Field & Type & Description \\ $\mathit{RW}$ & {\tt name/description} & string & a notes field containg human-readable description \\ $\mathit{RO}_\mathit{run}$ & {\tt VIFs} & (VIF ref) Set & list of connected vifs \\ $\mathit{RO}_\mathit{run}$ & {\tt PIFs} & (PIF ref) Set & list of connected pifs \\ +$\mathit{RW}$ & {\tt other\_config} & (string $\rightarrow$ string) Map & additional configuration \\ \hline \end{longtable} \subsection{RPCs associated with class: network} @@ -6798,6 +6921,145 @@ Get the PIFs field of the given network. value of the field +\vspace{0.3cm} +\vspace{0.3cm} +\vspace{0.3cm} +\subsubsection{RPC name:~get\_other\_config} + +{\bf Overview:} +Get the other\_config field of the given network. + + \noindent {\bf Signature:} +\begin{verbatim} ((string -> string) Map) get_other_config (session_id s, network 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 network ref } & self & reference to the object \\ \hline + +\end{tabular} + +\vspace{0.3cm} + + \noindent {\bf Return Type:} +{\tt +(string $\rightarrow$ string) Map +} + + +value of the field +\vspace{0.3cm} +\vspace{0.3cm} +\vspace{0.3cm} +\subsubsection{RPC name:~set\_other\_config} + +{\bf Overview:} +Set the other\_config field of the given network. + + \noindent {\bf Signature:} +\begin{verbatim} void set_other_config (session_id s, network ref self, (string -> string) Map value)\end{verbatim} + + +\noindent{\bf Arguments:} + + +\vspace{0.3cm} +\begin{tabular}{|c|c|p{7cm}|} + \hline +{\bf type} & {\bf name} & {\bf description} \\ \hline +{\tt network ref } & self & reference to the object \\ \hline + +{\tt (string $\rightarrow$ string) Map } & value & New value to set \\ \hline + +\end{tabular} + +\vspace{0.3cm} + + \noindent {\bf Return Type:} +{\tt +void +} + + + +\vspace{0.3cm} +\vspace{0.3cm} +\vspace{0.3cm} +\subsubsection{RPC name:~add\_to\_other\_config} + +{\bf Overview:} +Add the given key-value pair to the other\_config field of the given +network. + + \noindent {\bf Signature:} +\begin{verbatim} void add_to_other_config (session_id s, network ref self, string key, string value)\end{verbatim} + + +\noindent{\bf Arguments:} + + +\vspace{0.3cm} +\begin{tabular}{|c|c|p{7cm}|} + \hline +{\bf type} & {\bf name} & {\bf description} \\ \hline +{\tt network ref } & self & reference to the object \\ \hline + +{\tt string } & key & Key to add \\ \hline + +{\tt string } & value & Value to add \\ \hline + +\end{tabular} + +\vspace{0.3cm} + + \noindent {\bf Return Type:} +{\tt +void +} + + + +\vspace{0.3cm} +\vspace{0.3cm} +\vspace{0.3cm} +\subsubsection{RPC name:~remove\_from\_other\_config} + +{\bf Overview:} +Remove the given key and its corresponding value from the other\_config +field of the given network. If the key is not in that Map, then do +nothing. + + \noindent {\bf Signature:} +\begin{verbatim} void remove_from_other_config (session_id s, network ref self, string key)\end{verbatim} + + +\noindent{\bf Arguments:} + + +\vspace{0.3cm} +\begin{tabular}{|c|c|p{7cm}|} + \hline +{\bf type} & {\bf name} & {\bf description} \\ \hline +{\tt network ref } & self & reference to the object \\ \hline + +{\tt string } & key & Key to remove \\ \hline + +\end{tabular} + +\vspace{0.3cm} + + \noindent {\bf Return Type:} +{\tt +void +} + + + \vspace{0.3cm} \vspace{0.3cm} \vspace{0.3cm} @@ -13576,6 +13838,17 @@ current connection. The handle paramete \begin{verbatim}SESSION_INVALID(handle)\end{verbatim} \begin{center}\rule{10em}{0.1pt}\end{center} +\subsubsection{SESSION\_NOT\_REGISTERED} + +This session is not registered to receive events. You must call +event.register before event.next. The session handle you are using is +echoed. + +\vspace{0.3cm} +{\bf Signature:} +\begin{verbatim}SESSION_NOT_REGISTERED(handle)\end{verbatim} +\begin{center}\rule{10em}{0.1pt}\end{center} + \subsubsection{VALUE\_NOT\_SUPPORTED} You attempted to set a value that is not supported by this implementation. diff -r e7da2fcb7a22 -r fc9e2f7920c9 linux-2.6-xen-sparse/arch/x86_64/kernel/entry-xen.S --- a/linux-2.6-xen-sparse/arch/x86_64/kernel/entry-xen.S Fri Mar 30 10:27:15 2007 -0600 +++ b/linux-2.6-xen-sparse/arch/x86_64/kernel/entry-xen.S Fri Mar 30 17:18:42 2007 -0600 @@ -148,11 +148,11 @@ NMI_MASK = 0x80000000 .endm /* - * Must be consistent with the definition in arch-x86_64.h: + * Must be consistent with the definition in arch-x86/xen-x86_64.h: * struct iret_context { * u64 rax, r11, rcx, flags, rip, cs, rflags, rsp, ss; * }; - * #define VGCF_IN_SYSCALL (1<<8) + * with rax, r11, and rcx being taken care of in the hypercall stub. */ .macro HYPERVISOR_IRET flag testb $3,1*8(%rsp) @@ -164,21 +164,15 @@ NMI_MASK = 0x80000000 jnz 1f /* Direct iret to kernel space. Correct CS and SS. */ - orb $3,1*8(%rsp) - orb $3,4*8(%rsp) + orl $3,1*8(%rsp) + orl $3,4*8(%rsp) 1: iretq 2: /* Slow iret via hypervisor. */ - andl $~NMI_MASK, 16(%rsp) + andl $~NMI_MASK, 2*8(%rsp) pushq $\flag jmp hypercall_page + (__HYPERVISOR_iret * 32) .endm - - .macro SWITCH_TO_KERNEL ssoff,adjust=0 - jc 1f - orb $1,\ssoff-\adjust+4(%rsp) -1: - .endm /* * A newly forked process directly context switches into this. diff -r e7da2fcb7a22 -r fc9e2f7920c9 linux-2.6-xen-sparse/arch/x86_64/kernel/head64-xen.c --- a/linux-2.6-xen-sparse/arch/x86_64/kernel/head64-xen.c Fri Mar 30 10:27:15 2007 -0600 +++ b/linux-2.6-xen-sparse/arch/x86_64/kernel/head64-xen.c Fri Mar 30 17:18:42 2007 -0600 @@ -104,6 +104,8 @@ void __init x86_64_start_kernel(char * r char *s; int i; + setup_xen_features(); + xen_start_info = (struct start_info *)real_mode_data; if (!xen_feature(XENFEAT_auto_translated_physmap)) phys_to_machine_mapping = diff -r e7da2fcb7a22 -r fc9e2f7920c9 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 Fri Mar 30 10:27:15 2007 -0600 +++ b/linux-2.6-xen-sparse/arch/x86_64/kernel/setup-xen.c Fri Mar 30 17:18:42 2007 -0600 @@ -625,8 +625,6 @@ void __init setup_arch(char **cmdline_p) #endif - setup_xen_features(); - HYPERVISOR_vm_assist(VMASST_CMD_enable, VMASST_TYPE_writable_pagetables); diff -r e7da2fcb7a22 -r fc9e2f7920c9 linux-2.6-xen-sparse/drivers/xen/balloon/balloon.c --- a/linux-2.6-xen-sparse/drivers/xen/balloon/balloon.c Fri Mar 30 10:27:15 2007 -0600 +++ b/linux-2.6-xen-sparse/drivers/xen/balloon/balloon.c Fri Mar 30 17:18:42 2007 -0600 @@ -43,6 +43,7 @@ #include <linux/bootmem.h> #include <linux/highmem.h> #include <linux/vmalloc.h> +#include <linux/mutex.h> #include <xen/xen_proc.h> #include <asm/hypervisor.h> #include <xen/balloon.h> diff -r e7da2fcb7a22 -r fc9e2f7920c9 linux-2.6-xen-sparse/drivers/xen/core/machine_reboot.c --- a/linux-2.6-xen-sparse/drivers/xen/core/machine_reboot.c Fri Mar 30 10:27:15 2007 -0600 +++ b/linux-2.6-xen-sparse/drivers/xen/core/machine_reboot.c Fri Mar 30 17:18:42 2007 -0600 @@ -123,7 +123,7 @@ static int take_machine_down(void *p_fas static int take_machine_down(void *p_fast_suspend) { int fast_suspend = *(int *)p_fast_suspend; - int suspend_cancelled, err, cpu; + int suspend_cancelled, err; extern void time_resume(void); if (fast_suspend) { diff -r e7da2fcb7a22 -r fc9e2f7920c9 linux-2.6-xen-sparse/drivers/xen/core/reboot.c --- a/linux-2.6-xen-sparse/drivers/xen/core/reboot.c Fri Mar 30 10:27:15 2007 -0600 +++ b/linux-2.6-xen-sparse/drivers/xen/core/reboot.c Fri Mar 30 17:18:42 2007 -0600 @@ -33,7 +33,24 @@ static DECLARE_WORK(shutdown_work, __shu #ifdef CONFIG_XEN int __xen_suspend(int fast_suspend); #else -#define __xen_suspend(fast_suspend) 0 +extern void xenbus_suspend(void); +extern void xenbus_resume(void); +extern void platform_pci_suspend(void); +extern void platform_pci_resume(void); +int __xen_suspend(int fast_suspend) +{ + xenbus_suspend(); + platform_pci_suspend(); + + /* pvdrv sleep in this hyper-call when save */ + HYPERVISOR_shutdown(SHUTDOWN_suspend); + + platform_pci_resume(); + xenbus_resume(); + printk("PV stuff on HVM resume successfully!\n"); + + return 0; +} #endif static int shutdown_process(void *__unused) diff -r e7da2fcb7a22 -r fc9e2f7920c9 linux-2.6-xen-sparse/drivers/xen/evtchn/evtchn.c --- a/linux-2.6-xen-sparse/drivers/xen/evtchn/evtchn.c Fri Mar 30 10:27:15 2007 -0600 +++ b/linux-2.6-xen-sparse/drivers/xen/evtchn/evtchn.c Fri Mar 30 17:18:42 2007 -0600 @@ -47,6 +47,7 @@ #include <linux/irq.h> #include <linux/init.h> #include <linux/gfp.h> +#include <linux/mutex.h> #include <xen/evtchn.h> #include <xen/public/evtchn.h> @@ -56,6 +57,7 @@ struct per_user_data { #define EVTCHN_RING_MASK(_i) ((_i)&(EVTCHN_RING_SIZE-1)) evtchn_port_t *ring; unsigned int ring_cons, ring_prod, ring_overflow; + struct mutex ring_cons_mutex; /* protect against concurrent readers */ /* Processes wait on this queue when ring is empty. */ wait_queue_head_t evtchn_wait; @@ -108,11 +110,16 @@ static ssize_t evtchn_read(struct file * count = PAGE_SIZE; for (;;) { + mutex_lock(&u->ring_cons_mutex); + + rc = -EFBIG; if (u->ring_overflow) - return -EFBIG; + goto unlock_out; if ((c = u->ring_cons) != (p = u->ring_prod)) break; + + mutex_unlock(&u->ring_cons_mutex); if (file->f_flags & O_NONBLOCK) return -EAGAIN; @@ -141,20 +148,24 @@ static ssize_t evtchn_read(struct file * bytes2 = count - bytes1; } + rc = -EFAULT; if (copy_to_user(buf, &u->ring[EVTCHN_RING_MASK(c)], bytes1) || ((bytes2 != 0) && copy_to_user(&buf[bytes1], &u->ring[0], bytes2))) - return -EFAULT; + goto unlock_out; u->ring_cons += (bytes1 + bytes2) / sizeof(evtchn_port_t); - - return bytes1 + bytes2; + rc = bytes1 + bytes2; + + unlock_out: + mutex_unlock(&u->ring_cons_mutex); + return rc; } static ssize_t evtchn_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { - int rc, i; + int rc, i; evtchn_port_t *kbuf = (evtchn_port_t *)__get_free_page(GFP_KERNEL); struct per_user_data *u = file->private_data; @@ -164,18 +175,16 @@ static ssize_t evtchn_write(struct file /* Whole number of ports. */ count &= ~(sizeof(evtchn_port_t)-1); - if (count == 0) { - rc = 0; + rc = 0; + if (count == 0) goto out; - } if (count > PAGE_SIZE) count = PAGE_SIZE; - if (copy_from_user(kbuf, buf, count) != 0) { - rc = -EFAULT; + rc = -EFAULT; + if (copy_from_user(kbuf, buf, count) != 0) goto out; - } spin_lock_irq(&port_user_lock); for (i = 0; i < (count/sizeof(evtchn_port_t)); i++) @@ -321,9 +330,11 @@ static int evtchn_ioctl(struct inode *in case IOCTL_EVTCHN_RESET: { /* Initialise the ring to empty. Clear errors. */ + mutex_lock(&u->ring_cons_mutex); spin_lock_irq(&port_user_lock); u->ring_cons = u->ring_prod = u->ring_overflow = 0; spin_unlock_irq(&port_user_lock); + mutex_unlock(&u->ring_cons_mutex); rc = 0; break; } @@ -370,6 +381,8 @@ static int evtchn_open(struct inode *ino kfree(u); return -ENOMEM; } + + mutex_init(&u->ring_cons_mutex); filp->private_data = u; diff -r e7da2fcb7a22 -r fc9e2f7920c9 linux-2.6-xen-sparse/drivers/xen/pciback/conf_space_capability_pm.c --- a/linux-2.6-xen-sparse/drivers/xen/pciback/conf_space_capability_pm.c Fri Mar 30 10:27:15 2007 -0600 +++ b/linux-2.6-xen-sparse/drivers/xen/pciback/conf_space_capability_pm.c Fri Mar 30 17:18:42 2007 -0600 @@ -32,19 +32,19 @@ static int pm_ctrl_write(struct pci_dev void *data) { int err; - u16 cur_value; - pci_power_t new_state; + u16 old_value; + pci_power_t new_state, old_state; - /* Handle setting power state separately */ - new_state = (pci_power_t)(new_value & PCI_PM_CTRL_STATE_MASK); - - err = pci_read_config_word(dev, offset, &cur_value); + err = pci_read_config_word(dev, offset, &old_value); if (err) goto out; + old_state = (pci_power_t)(old_value & PCI_PM_CTRL_STATE_MASK); + new_state = (pci_power_t)(new_value & PCI_PM_CTRL_STATE_MASK); + new_value &= PM_OK_BITS; - if ((cur_value & PM_OK_BITS) != new_value) { - new_value = (cur_value & ~PM_OK_BITS) | new_value; + if ((old_value & PM_OK_BITS) != new_value) { + new_value = (old_value & ~PM_OK_BITS) | new_value; err = pci_write_config_word(dev, offset, new_value); if (err) goto out; @@ -53,10 +53,25 @@ static int pm_ctrl_write(struct pci_dev /* Let pci core handle the power management change */ dev_dbg(&dev->dev, "set power state to %x\n", new_state); err = pci_set_power_state(dev, new_state); - if (err) + if (err) { err = PCIBIOS_SET_FAILED; + goto out; + } - out: + /* + * Device may lose PCI config info on D3->D0 transition. This + * is a problem for some guests which will not reset BARs. Even + * those that have a go will be foiled by our BAR-write handler + * which will discard the write! Since Linux won't re-init + * the config space automatically in all cases, we do it here. + * Future: Should we re-initialise all first 64 bytes of config space? + */ + if (new_state == PCI_D0 && + (old_state == PCI_D3hot || old_state == PCI_D3cold) && + !(old_value & PCI_PM_CTRL_NO_SOFT_RESET)) + pci_restore_bars(dev); + + out: return err; } diff -r e7da2fcb7a22 -r fc9e2f7920c9 linux-2.6-xen-sparse/drivers/xen/pciback/conf_space_header.c --- a/linux-2.6-xen-sparse/drivers/xen/pciback/conf_space_header.c Fri Mar 30 10:27:15 2007 -0600 +++ b/linux-2.6-xen-sparse/drivers/xen/pciback/conf_space_header.c Fri Mar 30 17:18:42 2007 -0600 @@ -20,11 +20,15 @@ struct pci_bar_info { static int command_write(struct pci_dev *dev, int offset, u16 value, void *data) { + int err; + if (!dev->is_enabled && is_enable_cmd(value)) { if (unlikely(verbose_request)) printk(KERN_DEBUG "pciback: %s: enable\n", pci_name(dev)); - pci_enable_device(dev); + err = pci_enable_device(dev); + if (err) + return err; } else if (dev->is_enabled && !is_enable_cmd(value)) { if (unlikely(verbose_request)) printk(KERN_DEBUG "pciback: %s: disable\n", @@ -44,7 +48,13 @@ static int command_write(struct pci_dev printk(KERN_DEBUG "pciback: %s: enable memory-write-invalidate\n", pci_name(dev)); - pci_set_mwi(dev); + err = pci_set_mwi(dev); + if (err) { + printk(KERN_WARNING + "pciback: %s: cannot enable memory-write-invalidate (%d)\n", + pci_name(dev), err); + value &= ~PCI_COMMAND_INVALIDATE; + } } return pci_write_config_word(dev, offset, value); diff -r e7da2fcb7a22 -r fc9e2f7920c9 linux-2.6-xen-sparse/drivers/xen/pciback/pci_stub.c --- a/linux-2.6-xen-sparse/drivers/xen/pciback/pci_stub.c Fri Mar 30 10:27:15 2007 -0600 +++ b/linux-2.6-xen-sparse/drivers/xen/pciback/pci_stub.c Fri Mar 30 17:18:42 2007 -0600 @@ -805,6 +805,18 @@ static ssize_t permissive_show(struct de DRIVER_ATTR(permissive, S_IRUSR | S_IWUSR, permissive_show, permissive_add); +static void pcistub_exit(void) +{ + driver_remove_file(&pciback_pci_driver.driver, &driver_attr_new_slot); + driver_remove_file(&pciback_pci_driver.driver, + &driver_attr_remove_slot); + driver_remove_file(&pciback_pci_driver.driver, &driver_attr_slots); + driver_remove_file(&pciback_pci_driver.driver, &driver_attr_quirks); + driver_remove_file(&pciback_pci_driver.driver, &driver_attr_permissive); + + pci_unregister_driver(&pciback_pci_driver); +} + static int __init pcistub_init(void) { int pos = 0; @@ -845,12 +857,23 @@ static int __init pcistub_init(void) if (err < 0) goto out; - driver_create_file(&pciback_pci_driver.driver, &driver_attr_new_slot); - driver_create_file(&pciback_pci_driver.driver, - &driver_attr_remove_slot); - driver_create_file(&pciback_pci_driver.driver, &driver_attr_slots); - driver_create_file(&pciback_pci_driver.driver, &driver_attr_quirks); - driver_create_file(&pciback_pci_driver.driver, &driver_attr_permissive); + err = driver_create_file(&pciback_pci_driver.driver, + &driver_attr_new_slot); + if (!err) + err = driver_create_file(&pciback_pci_driver.driver, + &driver_attr_remove_slot); + if (!err) + err = driver_create_file(&pciback_pci_driver.driver, + &driver_attr_slots); + if (!err) + err = driver_create_file(&pciback_pci_driver.driver, + &driver_attr_quirks); + if (!err) + err = driver_create_file(&pciback_pci_driver.driver, + &driver_attr_permissive); + + if (err) + pcistub_exit(); out: return err; @@ -887,23 +910,17 @@ static int __init pciback_init(void) #endif pcistub_init_devices_late(); - pciback_xenbus_register(); - - return 0; + err = pciback_xenbus_register(); + if (err) + pcistub_exit(); + + return err; } static void __exit pciback_cleanup(void) { pciback_xenbus_unregister(); - - driver_remove_file(&pciback_pci_driver.driver, &driver_attr_new_slot); - driver_remove_file(&pciback_pci_driver.driver, - &driver_attr_remove_slot); - driver_remove_file(&pciback_pci_driver.driver, &driver_attr_slots); - driver_remove_file(&pciback_pci_driver.driver, &driver_attr_quirks); - driver_remove_file(&pciback_pci_driver.driver, &driver_attr_permissive); - - pci_unregister_driver(&pciback_pci_driver); + pcistub_exit(); } module_init(pciback_init); diff -r e7da2fcb7a22 -r fc9e2f7920c9 linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_dev.c --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_dev.c Fri Mar 30 10:27:15 2007 -0600 +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_dev.c Fri Mar 30 17:18:42 2007 -0600 @@ -58,6 +58,13 @@ struct xenbus_dev_transaction { struct xenbus_transaction handle; }; +struct read_buffer { + struct list_head list; + unsigned int cons; + unsigned int len; + char msg[]; +}; + struct xenbus_dev_data { /* In-progress transaction. */ struct list_head transactions; @@ -73,9 +80,7 @@ struct xenbus_dev_data { } u; /* Response queue. */ -#define MASK_READ_IDX(idx) ((idx)&(PAGE_SIZE-1)) - char read_buffer[PAGE_SIZE]; - unsigned int read_cons, read_prod; + struct list_head read_buffers; wait_queue_head_t read_waitq; struct mutex reply_mutex; @@ -88,18 +93,34 @@ static ssize_t xenbus_dev_read(struct fi size_t len, loff_t *ppos) { struct xenbus_dev_data *u = filp->private_data; - int i; - - if (wait_event_interruptible(u->read_waitq, - u->read_prod != u->read_cons)) - return -EINTR; - - for (i = 0; i < len; i++) { - if (u->read_cons == u->read_prod) - break; - put_user(u->read_buffer[MASK_READ_IDX(u->read_cons)], ubuf+i); - u->read_cons++; - } + struct read_buffer *rb; + int i, ret; + + mutex_lock(&u->reply_mutex); + while (list_empty(&u->read_buffers)) { + mutex_unlock(&u->reply_mutex); + ret = wait_event_interruptible(u->read_waitq, + !list_empty(&u->read_buffers)); + if (ret) + return ret; + mutex_lock(&u->reply_mutex); + } + + rb = list_entry(u->read_buffers.next, struct read_buffer, list); + for (i = 0; i < len;) { + put_user(rb->msg[rb->cons], ubuf + i); + i++; + rb->cons++; + if (rb->cons == rb->len) { + list_del(&rb->list); + kfree(rb); + if (list_empty(&u->read_buffers)) + break; + rb = list_entry(u->read_buffers.next, + struct read_buffer, list); + } + } + mutex_unlock(&u->reply_mutex); return i; } @@ -107,16 +128,20 @@ static void queue_reply(struct xenbus_de static void queue_reply(struct xenbus_dev_data *u, char *data, unsigned int len) { - int i; - - mutex_lock(&u->reply_mutex); - - for (i = 0; i < len; i++, u->read_prod++) - u->read_buffer[MASK_READ_IDX(u->read_prod)] = data[i]; - - BUG_ON((u->read_prod - u->read_cons) > sizeof(u->read_buffer)); - - mutex_unlock(&u->reply_mutex); + struct read_buffer *rb; + + if (len == 0) + return; + + rb = kmalloc(sizeof(*rb) + len, GFP_KERNEL); + BUG_ON(rb == NULL); + + rb->cons = 0; + rb->len = len; + + memcpy(rb->msg, data, len); + + list_add_tail(&rb->list, &u->read_buffers); wake_up(&u->read_waitq); } @@ -155,10 +180,12 @@ static void watch_fired(struct xenbus_wa hdr.type = XS_WATCH_EVENT; hdr.len = body_len; - + + mutex_lock(&adap->dev_data->reply_mutex); queue_reply(adap->dev_data, (char *)&hdr, sizeof(hdr)); queue_reply(adap->dev_data, (char *)path, path_len); queue_reply(adap->dev_data, (char *)token, tok_len); + mutex_unlock(&adap->dev_data->reply_mutex); } static LIST_HEAD(watch_list); @@ -230,13 +257,18 @@ static ssize_t xenbus_dev_write(struct f list_del(&trans->list); kfree(trans); } + mutex_lock(&u->reply_mutex); queue_reply(u, (char *)&u->u.msg, sizeof(u->u.msg)); queue_reply(u, (char *)reply, u->u.msg.len); + mutex_unlock(&u->reply_mutex); kfree(reply); break; case XS_WATCH: - case XS_UNWATCH: + case XS_UNWATCH: { + static const char *XS_RESP = "OK"; + struct xsd_sockmsg hdr; + path = u->u.buffer + sizeof(u->u.msg); token = memchr(path, 0, u->u.msg.len); if (token == NULL) { @@ -246,9 +278,6 @@ static ssize_t xenbus_dev_write(struct f token++; if (msg_type == XS_WATCH) { - static const char * XS_WATCH_RESP = "OK"; - struct xsd_sockmsg hdr; - watch = kmalloc(sizeof(*watch), GFP_KERNEL); watch->watch.node = kmalloc(strlen(path)+1, GFP_KERNEL); @@ -266,11 +295,6 @@ static ssize_t xenbus_dev_write(struct f } list_add(&watch->list, &u->watches); - - hdr.type = XS_WATCH; - hdr.len = strlen(XS_WATCH_RESP) + 1; - queue_reply(u, (char *)&hdr, sizeof(hdr)); - queue_reply(u, (char *)XS_WATCH_RESP, hdr.len); } else { list_for_each_entry_safe(watch, tmp_watch, &u->watches, list) { @@ -285,7 +309,14 @@ static ssize_t xenbus_dev_write(struct f } } + hdr.type = msg_type; + hdr.len = strlen(XS_RESP) + 1; + mutex_lock(&u->reply_mutex); + queue_reply(u, (char *)&hdr, sizeof(hdr)); + queue_reply(u, (char *)XS_RESP, hdr.len); + mutex_unlock(&u->reply_mutex); break; + } default: rc = -EINVAL; @@ -312,6 +343,7 @@ static int xenbus_dev_open(struct inode INIT_LIST_HEAD(&u->transactions); INIT_LIST_HEAD(&u->watches); + INIT_LIST_HEAD(&u->read_buffers); init_waitqueue_head(&u->read_waitq); mutex_init(&u->reply_mutex); @@ -349,7 +381,7 @@ static unsigned int xenbus_dev_poll(stru struct xenbus_dev_data *u = file->private_data; poll_wait(file, &u->read_waitq, wait); - if (u->read_cons != u->read_prod) + if (!list_empty(&u->read_buffers)) return POLLIN | POLLRDNORM; return 0; } diff -r e7da2fcb7a22 -r fc9e2f7920c9 linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c Fri Mar 30 10:27:15 2007 -0600 +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c Fri Mar 30 17:18:42 2007 -0600 @@ -335,6 +335,9 @@ int xenbus_register_driver_common(struct { int ret; + if (bus->error) + return bus->error; + drv->driver.name = drv->name; drv->driver.bus = &bus->bus; #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10) @@ -476,6 +479,9 @@ int xenbus_probe_node(struct xen_bus_typ enum xenbus_state state = xenbus_read_driver_state(nodename); + if (bus->error) + return bus->error; + if (state != XenbusStateInitialising) { /* Device is not new, so ignore it. This can happen if a device is going away after switching to Closed. */ @@ -513,10 +519,18 @@ int xenbus_probe_node(struct xen_bus_typ if (err) goto fail; - device_create_file(&xendev->dev, &dev_attr_nodename); - device_create_file(&xendev->dev, &dev_attr_devtype); - - return 0; + err = device_create_file(&xendev->dev, &dev_attr_nodename); + if (err) + goto unregister; + err = device_create_file(&xendev->dev, &dev_attr_devtype); + if (err) + goto unregister; + + return 0; +unregister: + device_remove_file(&xendev->dev, &dev_attr_nodename); + device_remove_file(&xendev->dev, &dev_attr_devtype); + device_unregister(&xendev->dev); fail: kfree(xendev); return err; @@ -564,6 +578,9 @@ int xenbus_probe_devices(struct xen_bus_ int err = 0; char **dir; unsigned int i, dir_n; + + if (bus->error) + return bus->error; dir = xenbus_directory(XBT_NIL, bus->root, "", &dir_n); if (IS_ERR(dir)) @@ -608,7 +625,7 @@ void dev_changed(const char *node, struc char type[BUS_ID_SIZE]; const char *p, *root; - if (char_count(node, '/') < 2) + if (bus->error || char_count(node, '/') < 2) return; exists = xenbus_exists(XBT_NIL, node, ""); @@ -742,7 +759,8 @@ void xenbus_suspend(void) { DPRINTK(""); - bus_for_each_dev(&xenbus_frontend.bus, NULL, NULL, suspend_dev); + if (!xenbus_frontend.error) + bus_for_each_dev(&xenbus_frontend.bus, NULL, NULL, suspend_dev); xenbus_backend_suspend(suspend_dev); xs_suspend(); } @@ -752,7 +770,8 @@ void xenbus_resume(void) { xb_init_comms(); xs_resume(); - bus_for_each_dev(&xenbus_frontend.bus, NULL, NULL, resume_dev); + if (!xenbus_frontend.error) + bus_for_each_dev(&xenbus_frontend.bus, NULL, NULL, resume_dev); xenbus_backend_resume(resume_dev); } EXPORT_SYMBOL_GPL(xenbus_resume); @@ -760,7 +779,8 @@ void xenbus_suspend_cancel(void) void xenbus_suspend_cancel(void) { xs_suspend_cancel(); - bus_for_each_dev(&xenbus_frontend.bus, NULL, NULL, suspend_cancel_dev); + if (!xenbus_frontend.error) + bus_for_each_dev(&xenbus_frontend.bus, NULL, NULL, suspend_cancel_dev); xenbus_backend_resume(suspend_cancel_dev); } EXPORT_SYMBOL_GPL(xenbus_suspend_cancel); @@ -854,7 +874,11 @@ static int __init xenbus_probe_init(void return -ENODEV; /* Register ourselves with the kernel bus subsystem */ - bus_register(&xenbus_frontend.bus); + xenbus_frontend.error = bus_register(&xenbus_frontend.bus); + if (xenbus_frontend.error) + printk(KERN_WARNING + "XENBUS: Error registering frontend bus: %i\n", + xenbus_frontend.error); xenbus_backend_bus_register(); /* @@ -925,7 +949,15 @@ static int __init xenbus_probe_init(void } /* Register ourselves with the kernel device subsystem */ - device_register(&xenbus_frontend.dev); + if (!xenbus_frontend.error) { + xenbus_frontend.error = device_register(&xenbus_frontend.dev); + if (xenbus_frontend.error) { + bus_unregister(&xenbus_frontend.bus); + printk(KERN_WARNING + "XENBUS: Error registering frontend device: %i\n", + xenbus_frontend.error); + } + } xenbus_backend_device_register(); if (!is_initial_xendomain()) @@ -972,6 +1004,8 @@ static int is_disconnected_device(struct static int exists_disconnected_device(struct device_driver *drv) { + if (xenbus_frontend.error) + return xenbus_frontend.error; return bus_for_each_dev(&xenbus_frontend.bus, NULL, drv, is_disconnected_device); } @@ -1036,8 +1070,10 @@ static void wait_for_devices(struct xenb #ifndef MODULE static int __init boot_wait_for_devices(void) { - ready_to_wait_for_devices = 1; - wait_for_devices(NULL); + if (!xenbus_frontend.error) { + ready_to_wait_for_devices = 1; + wait_for_devices(NULL); + } return 0; } diff -r e7da2fcb7a22 -r fc9e2f7920c9 linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.h --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.h Fri Mar 30 10:27:15 2007 -0600 +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.h Fri Mar 30 17:18:42 2007 -0600 @@ -51,6 +51,7 @@ struct xen_bus_type struct xen_bus_type { char *root; + int error; unsigned int levels; int (*get_bus_id)(char bus_id[BUS_ID_SIZE], const char *nodename); int (*probe)(const char *type, const char *dir); diff -r e7da2fcb7a22 -r fc9e2f7920c9 linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe_backend.c --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe_backend.c Fri Mar 30 10:27:15 2007 -0600 +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe_backend.c Fri Mar 30 17:18:42 2007 -0600 @@ -245,13 +245,15 @@ void xenbus_backend_suspend(int (*fn)(st void xenbus_backend_suspend(int (*fn)(struct device *, void *)) { DPRINTK(""); - bus_for_each_dev(&xenbus_backend.bus, NULL, NULL, fn); + if (!xenbus_backend.error) + bus_for_each_dev(&xenbus_backend.bus, NULL, NULL, fn); } void xenbus_backend_resume(int (*fn)(struct device *, void *)) { DPRINTK(""); - bus_for_each_dev(&xenbus_backend.bus, NULL, NULL, fn); + if (!xenbus_backend.error) + bus_for_each_dev(&xenbus_backend.bus, NULL, NULL, fn); } void xenbus_backend_probe_and_watch(void) @@ -262,10 +264,23 @@ void xenbus_backend_probe_and_watch(void void xenbus_backend_bus_register(void) { - bus_register(&xenbus_backend.bus); + xenbus_backend.error = bus_register(&xenbus_backend.bus); + if (xenbus_backend.error) + printk(KERN_WARNING + "XENBUS: Error registering backend bus: %i\n", + xenbus_backend.error); } void xenbus_backend_device_register(void) { - device_register(&xenbus_backend.dev); -} + if (xenbus_backend.error) + return; + + xenbus_backend.error = device_register(&xenbus_backend.dev); + if (xenbus_backend.error) { + bus_unregister(&xenbus_backend.bus); + printk(KERN_WARNING + "XENBUS: Error registering backend device: %i\n", + xenbus_backend.error); + } +} diff -r e7da2fcb7a22 -r fc9e2f7920c9 tools/Rules.mk --- a/tools/Rules.mk Fri Mar 30 10:27:15 2007 -0600 +++ b/tools/Rules.mk Fri Mar 30 17:18:42 2007 -0600 @@ -24,9 +24,9 @@ CFLAGS += $(CFLAGS-y) CFLAGS += $(CFLAGS-y) # Require GCC v3.4+ (to avoid issues with alignment constraints in Xen headers) -ifeq ($(CONFIG_X86)$(call cc-ver,$(CC),0x030400),yn) -$(error Xen tools require at least gcc-3.4) -endif +check-$(CONFIG_X86) = $(call cc-ver-check,CC,0x030400,\ + "Xen requires at least gcc-3.4") +$(eval $(check-y)) %.opic: %.c $(CC) $(CPPFLAGS) -DPIC $(CFLAGS) -fPIC -c -o $@ $< diff -r e7da2fcb7a22 -r fc9e2f7920c9 tools/examples/Makefile --- a/tools/examples/Makefile Fri Mar 30 10:27:15 2007 -0600 +++ b/tools/examples/Makefile Fri Mar 30 17:18:42 2007 -0600 @@ -9,7 +9,9 @@ XENDOMAINS_SYSCONFIG = init.d/sysconfig. # Xen configuration dir and configs to go there. XEN_CONFIG_DIR = /etc/xen XEN_CONFIGS = xend-config.sxp +XEN_CONFIGS += xend-config-xenapi.sxp XEN_CONFIGS += xm-config.xml +XEN_CONFIGS += xm-config-xenapi.xml XEN_CONFIGS += xmexample1 XEN_CONFIGS += xmexample2 XEN_CONFIGS += xmexample.hvm diff -r e7da2fcb7a22 -r fc9e2f7920c9 tools/examples/xend-config-xenapi.sxp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/examples/xend-config-xenapi.sxp Fri Mar 30 17:18:42 2007 -0600 @@ -0,0 +1,195 @@ +# -*- sh -*- + +# +# Xend configuration file. +# + +# This example configuration is appropriate for an installation that +# utilizes a bridged network configuration. Access to xend via http +# is disabled. + +# Commented out entries show the default for that entry, unless otherwise +# specified. + +#(logfile /var/log/xen/xend.log) +#(loglevel DEBUG) + + +# The Xen-API server configuration. (Please note that this server is +# available as an UNSUPPORTED PREVIEW in Xen 3.0.4, and should not be relied +# upon). +# +# This value configures the ports, interfaces, and access controls for the +# Xen-API server. Each entry in the list starts with either unix, a port +# number, or an address:port pair. If this is "unix", then a UDP socket is +# opened, and this entry applies to that. If it is a port, then Xend will +# listen on all interfaces on that TCP port, and if it is an address:port +# pair, then Xend will listen on the specified port, using the interface with +# the specified address. +# +# The subsequent string configures the user-based access control for the +# listener in question. This can be one of "none" or "pam", indicating either +# that users should be allowed access unconditionally, or that the local +# Pluggable Authentication Modules configuration should be used. If this +# string is missing or empty, then "pam" is used. +# +# The final string gives the host-based access control for that listener. If +# this is missing or empty, then all connections are accepted. Otherwise, +# this should be a space-separated sequence of regular expressions; any host +# with a fully-qualified domain name or an IP address that matches one of +# these regular expressions will be accepted. +# +# Example: listen on TCP port 9363 on all interfaces, accepting connections +# only from machines in example.com or localhost, and allow access through +# the unix domain socket unconditionally: +# + (xen-api-server ((9363 none))) +# (unix none))) +# +# Optionally, the TCP Xen-API server can use SSL by specifying the private +# key and certificate location: +# +# (9367 pam '' /etc/xen/xen-api.key /etc/xen/xen-api.crt) +# +# Default: +# (xen-api-server ((unix))) + + +#(xend-http-server no) +#(xend-unix-server no) +#(xend-tcp-xmlrpc-server no) +#(xend-unix-xmlrpc-server yes) +#(xend-relocation-server no) +(xend-relocation-server yes) + +#(xend-unix-path /var/lib/xend/xend-socket) + + +# Address and port xend should use for the legacy TCP XMLRPC interface, +# if xen-tcp-xmlrpc-server is set. +#(xen-tcp-xmlrpc-server-address 'localhost') +#(xen-tcp-xmlrpc-server-port 8006) + +# SSL key and certificate to use for the legacy TCP XMLRPC interface. +# Setting these will mean that this port serves only SSL connections as +# opposed to plaintext ones. +#(xend-tcp-xmlrpc-server-ssl-key-file /etc/xen/xmlrpc.key) +#(xend-tcp-xmlrpc-server-ssl-cert-file /etc/xen/xmlrpc.crt) + + +# Port xend should use for the HTTP interface, if xend-http-server is set. +#(xend-port 8000) + +# Port xend should use for the relocation interface, if xend-relocation-server +# is set. +#(xend-relocation-port 8002) + +# Address xend should listen on for HTTP connections, if xend-http-server is +# set. +# Specifying 'localhost' prevents remote connections. +# Specifying the empty string '' (the default) allows all connections. +#(xend-address '') +#(xend-address localhost) + +# Address xend should listen on for relocation-socket connections, if +# xend-relocation-server is set. +# Meaning and default as for xend-address above. +#(xend-relocation-address '') + +# The hosts allowed to talk to the relocation port. If this is empty (the +# default), then all connections are allowed (assuming that the connection +# arrives on a port and interface on which we are listening; see +# xend-relocation-port and xend-relocation-address above). Otherwise, this +# should be a space-separated sequence of regular expressions. Any host with +# a fully-qualified domain name or an IP address that matches one of these +# regular expressions will be accepted. +# +# For example: +# (xend-relocation-hosts-allow '^localhost$ ^.*\\.example\\.org$') +# +#(xend-relocation-hosts-allow '') +(xend-relocation-hosts-allow '^localhost$ ^localhost\\.localdomain$') + +# The limit (in kilobytes) on the size of the console buffer +#(console-limit 1024) + +## +# To bridge network traffic, like this: +# +# dom0: fake eth0 -> vif0.0 -+ +# | +# bridge -> real eth0 -> the network +# | +# domU: fake eth0 -> vifN.0 -+ +# +# use +# +# (network-script network-bridge) +# +# Your default ethernet device is used as the outgoing interface, by default. +# To use a different one (e.g. eth1) use +# +# (network-script 'network-bridge netdev=eth1') +# +# The bridge is named xenbr0, by default. To rename the bridge, use +# +# (network-script 'network-bridge bridge=<name>') +# +# It is possible to use the network-bridge script in more complicated +# scenarios, such as having two outgoing interfaces, with two bridges, and +# two fake interfaces per guest domain. To do things like this, write +# yourself a wrapper script, and call network-bridge from it, as appropriate. +# +(network-script network-bridge) + +# The script used to control virtual interfaces. This can be overridden on a +# per-vif basis when creating a domain or a configuring a new vif. The +# vif-bridge script is designed for use with the network-bridge script, or +# similar configurations. +# +# If you have overridden the bridge name using +# (network-script 'network-bridge bridge=<name>') then you may wish to do the +# same here. The bridge name can also be set when creating a domain or +# configuring a new vif, but a value specified here would act as a default. +# +# If you are using only one bridge, the vif-bridge script will discover that, +# so there is no need to specify it explicitly. +# +(vif-script vif-bridge) + + +## Use the following if network traffic is routed, as an alternative to the +# settings for bridged networking given above. +#(network-script network-route) +#(vif-script vif-route) + + +## Use the following if network traffic is routed with NAT, as an alternative +# to the settings for bridged networking given above. +#(network-script network-nat) +#(vif-script vif-nat) + + +# Dom0 will balloon out when needed to free memory for domU. +# dom0-min-mem is the lowest memory level (in MB) dom0 will get down to. +# If dom0-min-mem=0, dom0 will never balloon out. +(dom0-min-mem 196) + +# In SMP system, dom0 will use dom0-cpus # of CPUS +# If dom0-cpus = 0, dom0 will take all cpus available +(dom0-cpus 0) + +# Whether to enable core-dumps when domains crash. +#(enable-dump no) + +# The tool used for initiating virtual TPM migration +#(external-migration-tool '') + +# The interface for VNC servers to listen on. Defaults +# to 127.0.0.1 To restore old 'listen everywhere' behaviour +# set this to 0.0.0.0 +#(vnc-listen '127.0.0.1') + +# The default password for VNC console on HVM domain. +# Empty string is no authentication. +(vncpasswd '') diff -r e7da2fcb7a22 -r fc9e2f7920c9 tools/examples/xend-config.sxp --- a/tools/examples/xend-config.sxp Fri Mar 30 10:27:15 2007 -0600 +++ b/tools/examples/xend-config.sxp Fri Mar 30 17:18:42 2007 -0600 @@ -46,6 +46,11 @@ # (xen-api-server ((9363 pam '^localhost$ example\\.com$') # (unix none))) # +# Optionally, the TCP Xen-API server can use SSL by specifying the private +# key and certificate location: +# +# (9367 pam '' /etc/xen/xen-api.key /etc/xen/xen-api.crt) +# # Default: # (xen-api-server ((unix))) @@ -59,10 +64,17 @@ #(xend-unix-path /var/lib/xend/xend-socket) -# Address and port xend should use for the TCP XMLRPC interface, + +# Address and port xend should use for the legacy TCP XMLRPC interface, # if xen-tcp-xmlrpc-server is set. #(xen-tcp-xmlrpc-server-address 'localhost') #(xen-tcp-xmlrpc-server-port 8006) + +# SSL key and certificate to use for the legacy TCP XMLRPC interface. +# Setting these will mean that this port serves only SSL connections as +# opposed to plaintext ones. +#(xend-tcp-xmlrpc-server-ssl-key-file /etc/xen/xmlrpc.key) +#(xend-tcp-xmlrpc-server-ssl-cert-file /etc/xen/xmlrpc.crt) # Port xend should use for the HTTP interface, if xend-http-server is set. diff -r e7da2fcb7a22 -r fc9e2f7920c9 tools/examples/xm-config-xenapi.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/examples/xm-config-xenapi.xml Fri Mar 30 17:18:42 2007 -0600 @@ -0,0 +1,43 @@ +<!-- + +Copyright (C) 2006 XenSource Inc. + +This library is free software; you can redistribute it and/or +modify it under the terms of version 2.1 of the GNU Lesser General Public +License as published by the Free Software Foundation. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +--> + +<!-- + +This is a configuration file for xm; it should be placed in +/etc/xen/xm-config.xml. If this file is missing, then xm will fall back to +the normal behaviour that's in Xen 3.0.4 and below. The settings here are +most useful for experimenting with the Xen-API preview in Xen 3.0.4. + +--> + +<xm> + <!-- The server element describes how to talk to Xend. The type may be + Xen-API or LegacyXMLRPC (the default). The URI is that of the + server; you might try http://server:9363/ or + httpu:///var/run/xend/xen-api.sock for the Xen-API, or + httpu:///var/run/xend/xmlrpc.sock for the legacy server. + + The username and password attributes will be used to log in if Xen-API + is being used. + --> + <server type='Xen-API' + uri='http://localhost:9363/' + username='me' + password='mypassword' /> +</xm> diff -r e7da2fcb7a22 -r fc9e2f7920c9 tools/ioemu/hw/ne2000.c --- a/tools/ioemu/hw/ne2000.c Fri Mar 30 10:27:15 2007 -0600 +++ b/tools/ioemu/hw/ne2000.c Fri Mar 30 17:18:42 2007 -0600 @@ -770,7 +770,7 @@ void isa_ne2000_init(int base, int irq, s->macaddr[4], s->macaddr[5]); - register_savevm("ne2000", 0, 2, ne2000_save, ne2000_load, s); + register_savevm("ne2000", base, 2, ne2000_save, ne2000_load, s); } /***********************************************************/ @@ -806,6 +806,7 @@ void pci_ne2000_init(PCIBus *bus, NICInf PCINE2000State *d; NE2000State *s; uint8_t *pci_conf; + int instance; d = (PCINE2000State *)pci_register_device(bus, "NE2000", sizeof(PCINE2000State), @@ -840,8 +841,8 @@ void pci_ne2000_init(PCIBus *bus, NICInf s->macaddr[4], s->macaddr[5]); - /* XXX: instance number ? */ - register_savevm("ne2000", 0, 2, ne2000_save, ne2000_load, s); - register_savevm("ne2000_pci", 0, 1, generic_pci_save, generic_pci_load, - &d->dev); -} + instance = pci_bus_num(bus) << 8 | s->pci_dev->devfn; + register_savevm("ne2000", instance, 2, ne2000_save, ne2000_load, s); + register_savevm("ne2000_pci", instance, 1, generic_pci_save, + generic_pci_load, &d->dev); +} diff -r e7da2fcb7a22 -r fc9e2f7920c9 tools/ioemu/hw/pcnet.c --- a/tools/ioemu/hw/pcnet.c Fri Mar 30 10:27:15 2007 -0600 +++ b/tools/ioemu/hw/pcnet.c Fri Mar 30 17:18:42 2007 -0600 @@ -1727,10 +1727,63 @@ static void pcnet_mmio_map(PCIDevice *pc cpu_register_physical_memory(addr, PCNET_PNPMMIO_SIZE, d->mmio_io_addr); } + +static void pcnet_save(QEMUFile *f, void *opaque) +{ + PCNetState *s = opaque; + unsigned int i; + + qemu_put_be32s(f, &s->rap); + qemu_put_be32s(f, &s->isr); + qemu_put_be32s(f, &s->lnkst); + qemu_put_be32s(f, &s->rdra); + qemu_put_be32s(f, &s->tdra); + qemu_put_buffer(f, s->prom, 16); + for (i = 0; i < 128; i++) + qemu_put_be16s(f, &s->csr[i]); + for (i = 0; i < 32; i++) + qemu_put_be16s(f, &s->bcr[i]); + qemu_put_be64s(f, &s->timer); + qemu_put_be32s(f, &s->xmit_pos); + qemu_put_be32s(f, &s->recv_pos); + qemu_put_buffer(f, s->buffer, 4096); + qemu_put_be32s(f, &s->tx_busy); + qemu_put_timer(f, s->poll_timer); +} + +static int pcnet_load(QEMUFile *f, void *opaque, int version_id) +{ + PCNetState *s = opaque; + int i, ret; + + if (version_id != 1) + return -EINVAL; + + qemu_get_be32s(f, &s->rap); + qemu_get_be32s(f, &s->isr); + qemu_get_be32s(f, &s->lnkst); + qemu_get_be32s(f, &s->rdra); + qemu_get_be32s(f, &s->tdra); + qemu_get_buffer(f, s->prom, 16); + for (i = 0; i < 128; i++) + qemu_get_be16s(f, &s->csr[i]); + for (i = 0; i < 32; i++) + qemu_get_be16s(f, &s->bcr[i]); + qemu_get_be64s(f, &s->timer); + qemu_get_be32s(f, &s->xmit_pos); + qemu_get_be32s(f, &s->recv_pos); + qemu_get_buffer(f, s->buffer, 4096); + qemu_get_be32s(f, &s->tx_busy); + qemu_get_timer(f, s->poll_timer); + + return 0; +} + void pci_pcnet_init(PCIBus *bus, NICInfo *nd) { PCNetState *d; uint8_t *pci_conf; + int instance; #if 0 printf("sizeof(RMD)=%d, sizeof(TMD)=%d\n", @@ -1775,6 +1828,11 @@ void pci_pcnet_init(PCIBus *bus, NICInfo d->vc = qemu_new_vlan_client(nd->vlan, pcnet_receive, pcnet_can_receive, d); + + instance = pci_bus_num(bus) << 8 | d->dev.devfn; + register_savevm("pcnet", instance, 1, pcnet_save, pcnet_load, d); + register_savevm("pcnet_pci", instance, 1, generic_pci_save, + generic_pci_load, &d->dev); snprintf(d->vc->info_str, sizeof(d->vc->info_str), "pcnet macaddr=%02x:%02x:%02x:%02x:%02x:%02x", diff -r e7da2fcb7a22 -r fc9e2f7920c9 tools/ioemu/hw/piix4acpi.c --- a/tools/ioemu/hw/piix4acpi.c Fri Mar 30 10:27:15 2007 -0600 +++ b/tools/ioemu/hw/piix4acpi.c Fri Mar 30 17:18:42 2007 -0600 @@ -57,6 +57,20 @@ typedef struct PCIAcpiState { uint16_t pm1_control; /* pm1a_ECNT_BLK */ } PCIAcpiState; +static void piix4acpi_save(QEMUFile *f, void *opaque) +{ + PCIAcpiState *s = opaque; + qemu_put_be16s(f, &s->pm1_control); +} + +static int piix4acpi_load(QEMUFile *f, void *opaque, int version_id) +{ + PCIAcpiState *s = opaque; + if (version_id > 1) + return -EINVAL; + qemu_get_be16s(f, &s->pm1_control); +} + static void acpiPm1Control_writeb(void *opaque, uint32_t addr, uint32_t val) { PCIAcpiState *s = opaque; @@ -193,4 +207,8 @@ void pci_piix4_acpi_init(PCIBus *bus, in d->pm1_control = SCI_EN; acpi_map(d, 0, 0x1f40, 0x10, PCI_ADDRESS_SPACE_IO); -} + + register_savevm("piix4acpi", 0, 1, piix4acpi_save, piix4acpi_load, d); + register_savevm("piix4acpi_pci", 0, 1, generic_pci_save, generic_pci_load, + &d->dev); +} diff -r e7da2fcb7a22 -r fc9e2f7920c9 tools/ioemu/hw/rtl8139.c --- a/tools/ioemu/hw/rtl8139.c Fri Mar 30 10:27:15 2007 -0600 +++ b/tools/ioemu/hw/rtl8139.c Fri Mar 30 17:18:42 2007 -0600 @@ -3406,6 +3406,7 @@ void pci_rtl8139_init(PCIBus *bus, NICIn PCIRTL8139State *d; RTL8139State *s; uint8_t *pci_conf; + int instance; d = (PCIRTL8139State *)pci_register_device(bus, "RTL8139", sizeof(PCIRTL8139State), @@ -3460,10 +3461,10 @@ void pci_rtl8139_init(PCIBus *bus, NICIn s->cplus_txbuffer_len = 0; s->cplus_txbuffer_offset = 0; - /* XXX: instance number ? */ - register_savevm("rtl8139", 0, 2, rtl8139_save, rtl8139_load, s); - register_savevm("rtl8139_pci", 0, 1, generic_pci_save, generic_pci_load, - &d->dev); + instance = pci_bus_num(bus) << 8 | s->pci_dev->devfn; + register_savevm("rtl8139", instance, 2, rtl8139_save, rtl8139_load, s); + register_savevm("rtl8139_pci", instance, 1, generic_pci_save, + generic_pci_load, &d->dev); #if RTL8139_ONBOARD_TIMER s->timer = qemu_new_timer(vm_clock, rtl8139_timer, s); diff -r e7da2fcb7a22 -r fc9e2f7920c9 tools/ioemu/hw/usb-uhci.c --- a/tools/ioemu/hw/usb-uhci.c Fri Mar 30 10:27:15 2007 -0600 +++ b/tools/ioemu/hw/usb-uhci.c Fri Mar 30 17:18:42 2007 -0600 @@ -700,6 +700,7 @@ int uhci_usb_load(QEMUFile *f, void *opa qemu_get_timer(f, s->frame_timer); + return 0; } void usb_uhci_init(PCIBus *bus, int devfn) diff -r e7da2fcb7a22 -r fc9e2f7920c9 tools/ioemu/vl.c --- a/tools/ioemu/vl.c Fri Mar 30 10:27:15 2007 -0600 +++ b/tools/ioemu/vl.c Fri Mar 30 17:18:42 2007 -0600 @@ -6109,10 +6109,9 @@ int main(int argc, char **argv) #endif /* !CONFIG_DM */ cyls = heads = secs = 0; translation = BIOS_ATA_TRANSLATION_AUTO; - pstrcpy(monitor_device, sizeof(monitor_device), "vc"); - - pstrcpy(serial_devices[0], sizeof(serial_devices[0]), "vc"); - for(i = 1; i < MAX_SERIAL_PORTS; i++) + pstrcpy(monitor_device, sizeof(monitor_device), "null"); + + for(i = 0; i < MAX_SERIAL_PORTS; i++) serial_devices[i][0] = '\0'; serial_device_index = 0; diff -r e7da2fcb7a22 -r fc9e2f7920c9 tools/libxc/xc_hvm_restore.c --- a/tools/libxc/xc_hvm_restore.c Fri Mar 30 10:27:15 2007 -0600 +++ b/tools/libxc/xc_hvm_restore.c Fri Mar 30 17:18:42 2007 -0600 @@ -81,7 +81,7 @@ int xc_hvm_restore(int xc_handle, int io unsigned int rc = 1, n, i; uint32_t rec_len, nr_vcpus; uint8_t *hvm_buf = NULL; - unsigned long long v_end, memsize; + unsigned long long v_end; unsigned long shared_page_nr; unsigned long pfn; @@ -91,16 +91,19 @@ int xc_hvm_restore(int xc_handle, int io /* Types of the pfns in the current region */ unsigned long region_pfn_type[MAX_BATCH_SIZE]; - /* Number of pages of memory the guest has. *Not* the same as max_pfn. */ - unsigned long nr_pages; - /* The size of an array big enough to contain all guest pfns */ unsigned long pfn_array_size = max_pfn + 1; - /* hvm guest mem size (Mb) */ - memsize = (unsigned long long)*store_mfn; - v_end = memsize << 20; - nr_pages = (unsigned long) memsize << (20 - PAGE_SHIFT); + /* Number of pages of memory the guest has. *Not* the same as max_pfn. */ + unsigned long nr_pages = max_pfn + 1; + /* MMIO hole doesn't contain RAM */ + if ( nr_pages >= HVM_BELOW_4G_MMIO_START >> PAGE_SHIFT ) + nr_pages -= HVM_BELOW_4G_MMIO_LENGTH >> PAGE_SHIFT; + /* VGA hole doesn't contain RAM */ + nr_pages -= 0x20; + + /* XXX: Unlikely to be true, but matches previous behaviour. :( */ + v_end = (nr_pages + 0x20) << PAGE_SHIFT; DPRINTF("xc_hvm_restore:dom=%d, nr_pages=0x%lx, store_evtchn=%d, " "*store_mfn=%ld, pae=%u, apic=%u.\n", @@ -146,7 +149,7 @@ int xc_hvm_restore(int xc_handle, int io 0, 0, &pfns[0x00]); if ( (rc == 0) && (nr_pages > 0xc0) ) rc = xc_domain_memory_populate_physmap( - xc_handle, dom, nr_pages - 0xc0, 0, 0, &pfns[0xc0]); + xc_handle, dom, nr_pages - 0xa0, 0, 0, &pfns[0xc0]); if ( rc != 0 ) { PERROR("Could not allocate memory for HVM guest.\n"); @@ -276,14 +279,6 @@ int xc_hvm_restore(int xc_handle, int io else shared_page_nr = (v_end >> PAGE_SHIFT) - 1; - /* Paranoia: clean pages. */ - if ( xc_clear_domain_page(xc_handle, dom, shared_page_nr) || - xc_clear_domain_page(xc_handle, dom, shared_page_nr-1) || - xc_clear_domain_page(xc_handle, dom, shared_page_nr-2) ) { - ERROR("error clearing comms frames!\n"); - goto out; - } - xc_set_hvm_param(xc_handle, dom, HVM_PARAM_STORE_PFN, shared_page_nr-1); xc_set_hvm_param(xc_handle, dom, HVM_PARAM_BUFIOREQ_PFN, shared_page_nr-2); xc_set_hvm_param(xc_handle, dom, HVM_PARAM_IOREQ_PFN, shared_page_nr); diff -r e7da2fcb7a22 -r fc9e2f7920c9 tools/libxen/Makefile --- a/tools/libxen/Makefile Fri Mar 30 10:27:15 2007 -0600 +++ b/tools/libxen/Makefile Fri Mar 30 17:18:42 2007 -0600 @@ -51,6 +51,9 @@ test/test_bindings: test/test_bindings.o test/test_bindings: test/test_bindings.o libxenapi.so $(CC) $(LDFLAGS) -o $@ $< -L . -lxenapi +test/test_event_handling: test/test_event_handling.o libxenapi.so + $(CC) $(LDFLAGS) -o $@ $< -L . -lxenapi + test/test_hvm_bindings: test/test_hvm_bindings.o libxenapi.so $(CC) $(LDFLAGS) -o $@ $< -L . -lxenapi diff -r e7da2fcb7a22 -r fc9e2f7920c9 tools/libxen/include/xen_event.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/libxen/include/xen_event.h Fri Mar 30 17:18:42 2007 -0600 @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2006-2007, XenSource Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef XEN_EVENT_H +#define XEN_EVENT_H + +#include "xen_common.h" +#include "xen_event_decl.h" +#include "xen_event_operation.h" +#include "xen_string_set.h" + + +/* + * The event class. + * + * Asynchronous event registration and handling. + */ + + + +typedef struct xen_event_record +{ + int64_t id; + time_t timestamp; + char *class; + enum xen_event_operation operation; + char *ref; + char *obj_uuid; +} xen_event_record; + +/** + * Allocate a xen_event_record. + */ +extern xen_event_record * +xen_event_record_alloc(void); + +/** + * Free the given xen_event_record, and all referenced values. The + * given record must have been allocated by this library. + */ +extern void +xen_event_record_free(xen_event_record *record); + + +typedef struct xen_event_record_set +{ + size_t size; + xen_event_record *contents[]; +} xen_event_record_set; + +/** + * Allocate a xen_event_record_set of the given size. + */ +extern xen_event_record_set * +xen_event_record_set_alloc(size_t size); + +/** + * Free the given xen_event_record_set, and all referenced values. The + * given set must have been allocated by this library. + */ +extern void +xen_event_record_set_free(xen_event_record_set *set); + + +/** + * Registers this session with the event system. Specifying the empty + * list will register for all classes. + */ +extern bool +xen_event_register(xen_session *session, struct xen_string_set *classes); + + +/** + * Unregisters this session with the event system. + */ +extern bool +xen_event_unregister(xen_session *session, struct xen_string_set *classes); + + +/** + * Blocking call which returns a (possibly empty) batch of events. + */ +extern bool +xen_event_next(xen_session *session, struct xen_event_record_set **result); + + +#endif diff -r e7da2fcb7a22 -r fc9e2f7920c9 tools/libxen/include/xen_event_decl.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/libxen/include/xen_event_decl.h Fri Mar 30 17:18:42 2007 -0600 @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2006-2007, XenSource Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef XEN_EVENT_DECL_H +#define XEN_EVENT_DECL_H + +struct xen_event_record; +struct xen_event_record_set; + +#endif diff -r e7da2fcb7a22 -r fc9e2f7920c9 tools/libxen/include/xen_event_operation.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/libxen/include/xen_event_operation.h Fri Mar 30 17:18:42 2007 -0600 @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2006-2007, XenSource Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef XEN_EVENT_OPERATION_H +#define XEN_EVENT_OPERATION_H + + +#include "xen_common.h" + + +enum xen_event_operation +{ + /** + * An object has been created + */ + XEN_EVENT_OPERATION_ADD, + + /** + * An object has been deleted + */ + XEN_EVENT_OPERATION_DEL, + + /** + * An object has been modified + */ + XEN_EVENT_OPERATION_MOD +}; + + +typedef struct xen_event_operation_set +{ + size_t size; + enum xen_event_operation contents[]; +} xen_event_operation_set; + +/** + * Allocate a xen_event_operation_set of the given size. + */ +extern xen_event_operation_set * +xen_event_operation_set_alloc(size_t size); + +/** + * Free the given xen_event_operation_set. The given set must have + * been allocated by this library. + */ +extern void +xen_event_operation_set_free(xen_event_operation_set *set); + + +/** + * Return the name corresponding to the given code. This string must + * not be modified or freed. + */ +extern const char * +xen_event_operation_to_string(enum xen_event_operation val); + + +/** + * Return the correct code for the given string, or set the session + * object to failure and return an undefined value if the given string does + * not match a known code. + */ +extern enum xen_event_operation +xen_event_operation_from_string(xen_session *session, const char *str); + + +#endif diff -r e7da2fcb7a22 -r fc9e2f7920c9 tools/libxen/include/xen_event_operation_internal.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/libxen/include/xen_event_operation_internal.h Fri Mar 30 17:18:42 2007 -0600 @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2006-2007, XenSource Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +/* + * Declarations of the abstract types used during demarshalling of enum + * xen_event_operation. Internal to this library -- do not use from outside. + */ + + +#ifndef XEN_EVENT_OPERATION_INTERNAL_H +#define XEN_EVENT_OPERATION_INTERNAL_H + + +#include "xen_internal.h" + + +extern const abstract_type xen_event_operation_abstract_type_; +extern const abstract_type xen_event_operation_set_abstract_type_; + + +#endif diff -r e7da2fcb7a22 -r fc9e2f7920c9 tools/libxen/include/xen_network.h --- a/tools/libxen/include/xen_network.h Fri Mar 30 10:27:15 2007 -0600 +++ b/tools/libxen/include/xen_network.h Fri Mar 30 17:18:42 2007 -0600 @@ -22,6 +22,7 @@ #include "xen_common.h" #include "xen_network_decl.h" #include "xen_pif_decl.h" +#include "xen_string_string_map.h" #include "xen_vif_decl.h" @@ -68,6 +69,7 @@ typedef struct xen_network_record char *name_description; struct xen_vif_record_opt_set *vifs; struct xen_pif_record_opt_set *pifs; + xen_string_string_map *other_config; } xen_network_record; /** @@ -220,6 +222,13 @@ xen_network_get_pifs(xen_session *sessio /** + * Get the other_config field of the given network. + */ +extern bool +xen_network_get_other_config(xen_session *session, xen_string_string_map **result, xen_network network); + + +/** * Set the name/label field of the given network. */ extern bool @@ -234,6 +243,30 @@ xen_network_set_name_description(xen_ses /** + * Set the other_config field of the given network. + */ +extern bool +xen_network_set_other_config(xen_session *session, xen_network network, xen_string_string_map *other_config); + + +/** + * Add the given key-value pair to the other_config field of the given + * network. + */ +extern bool +xen_network_add_to_other_config(xen_session *session, xen_network network, char *key, char *value); + + +/** + * Remove the given key and its corresponding value from the + * other_config field of the given network. If the key is not in that Map, + * then do nothing. + */ +extern bool +xen_network_remove_from_other_config(xen_session *session, xen_network network, char *key); + + +/** * Return a list of all the networks known to the system. */ extern bool diff -r e7da2fcb7a22 -r fc9e2f7920c9 tools/libxen/src/xen_common.c --- a/tools/libxen/src/xen_common.c Fri Mar 30 10:27:15 2007 -0600 +++ b/tools/libxen/src/xen_common.c Fri Mar 30 17:18:42 2007 -0600 @@ -1217,11 +1217,88 @@ static void parse_result(xen_session *se } +static void +make_body_add_type(enum abstract_typename typename, abstract_value *v, + xmlNode *params_node) +{ + char buf[20]; + switch (typename) + { + case STRING: + add_param(params_node, "string", v->u.string_val); + break; + + case INT: + snprintf(buf, sizeof(buf), "%"PRId64, v->u.int_val); + add_param(params_node, "string", buf); + break; + + case FLOAT: + snprintf(buf, sizeof(buf), "%lf", v->u.float_val); + add_param(params_node, "double", buf); + break; + + case BOOL: + add_param(params_node, "boolean", v->u.bool_val ? "1" : "0"); + break; + + case VOID: + add_param(params_node, "string", ""); + break; + + case ENUM: + add_param(params_node, "string", + v->type->enum_marshaller(v->u.enum_val)); + break; + + case SET: + { + const struct abstract_type *member_type = v->type->child; + arbitrary_set *set_val = v->u.struct_val; + abstract_value v; + xmlNode *data_node = add_param_struct(params_node); + + for (size_t i = 0; i < set_val->size; i++) + { + switch (member_type->typename) { + case STRING: + v.u.string_val = (char *)set_val->contents[i]; + make_body_add_type(member_type->typename, &v, data_node); + break; + default: + assert(false); + } + } + } + break; + + case STRUCT: + { + size_t member_count = v->type->member_count; + + xmlNode *struct_node = add_param_struct(params_node); + + for (size_t i = 0; i < member_count; i++) + { + const struct struct_member *mem = v->type->members + i; + const char *key = mem->key; + void *struct_value = v->u.struct_val; + + add_struct_value(mem->type, struct_value + mem->offset, + add_struct_member, key, struct_node); + } + } + break; + + default: + assert(false); + } +} + + static char * make_body(const char *method_name, abstract_value params[], int param_count) { - char buf[20]; - xmlDocPtr doc = xmlNewDoc(BAD_CAST "1.0"); xmlNode *methodCall = xmlNewNode(NULL, BAD_CAST "methodCall"); xmlDocSetRootElement(doc, methodCall); @@ -1235,56 +1312,7 @@ make_body(const char *method_name, abstr for (int p = 0; p < param_count; p++) { abstract_value *v = params + p; - switch (v->type->typename) - { - case STRING: - add_param(params_node, "string", v->u.string_val); - break; - - case INT: - snprintf(buf, sizeof(buf), "%"PRId64, v->u.int_val); - add_param(params_node, "string", buf); - break; - - case FLOAT: - snprintf(buf, sizeof(buf), "%lf", v->u.float_val); - add_param(params_node, "double", buf); - break; - - case BOOL: - add_param(params_node, "boolean", v->u.bool_val ? "1" : "0"); - break; - - case VOID: - add_param(params_node, "string", ""); - break; - - case ENUM: - add_param(params_node, "string", - v->type->enum_marshaller(v->u.enum_val)); - break; - - case STRUCT: - { - size_t member_count = v->type->member_count; - - xmlNode *struct_node = add_param_struct(params_node); - - for (size_t i = 0; i < member_count; i++) - { - const struct struct_member *mem = v->type->members + i; - const char *key = mem->key; - void *struct_value = v->u.struct_val; - - add_struct_value(mem->type, struct_value + mem->offset, - add_struct_member, key, struct_node); - } - } - break; - - default: - assert(false); - } + make_body_add_type(v->type->typename, v, params_node); } xmlBufferPtr buffer = xmlBufferCreate(); diff -r e7da2fcb7a22 -r fc9e2f7920c9 tools/libxen/src/xen_event.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/libxen/src/xen_event.c Fri Mar 30 17:18:42 2007 -0600 @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2006-2007, XenSource Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include <stddef.h> +#include <stdlib.h> + +#include "xen_common.h" +#include "xen_event.h" +#include "xen_event_operation_internal.h" +#include "xen_internal.h" + + +XEN_ALLOC(xen_event_record) +XEN_SET_ALLOC_FREE(xen_event_record) + + +static const struct_member xen_event_record_struct_members[] = + { + { .key = "id", + .type = &abstract_type_int, + .offset = offsetof(xen_event_record, id) }, + { .key = "timestamp", + .type = &abstract_type_datetime, + .offset = offsetof(xen_event_record, timestamp) }, + { .key = "class", + .type = &abstract_type_string, + .offset = offsetof(xen_event_record, class) }, + { .key = "operation", + .type = &xen_event_operation_abstract_type_, + .offset = offsetof(xen_event_record, operation) }, + { .key = "ref", + .type = &abstract_type_string, + .offset = offsetof(xen_event_record, ref) }, + { .key = "obj_uuid", + .type = &abstract_type_string, + .offset = offsetof(xen_event_record, obj_uuid) } + }; + +const abstract_type xen_event_record_abstract_type_ = + { + .typename = STRUCT, + .struct_size = sizeof(xen_event_record), + .member_count = + sizeof(xen_event_record_struct_members) / sizeof(struct_member), + .members = xen_event_record_struct_members + }; + + +const abstract_type xen_event_record_set_abstract_type_ = + { + .typename = SET, + .child = &xen_event_record_abstract_type_ + }; + + +void +xen_event_record_free(xen_event_record *record) +{ + if (record == NULL) + { + return; + } + free(record->class); + free(record->ref); + free(record->obj_uuid); + free(record); +} + + +bool +xen_event_register(xen_session *session, struct xen_string_set *classes) +{ + abstract_value param_values[] = + { + { .type = &abstract_type_string_set, + .u.set_val = (arbitrary_set *)classes } + }; + + xen_call_(session, "event.register", param_values, 1, NULL, NULL); + return session->ok; +} + + +bool +xen_event_unregister(xen_session *session, struct xen_string_set *classes) +{ + abstract_value param_values[] = + { + { .type = &abstract_type_string_set, + .u.set_val = (arbitrary_set *)classes } + }; + + xen_call_(session, "event.unregister", param_values, 1, NULL, NULL); + return session->ok; +} + + +bool +xen_event_next(xen_session *session, struct xen_event_record_set **result) +{ + + abstract_type result_type = xen_event_record_set_abstract_type_; + + *result = NULL; + xen_call_(session, "event.next", NULL, 0, &result_type, result); + return session->ok; +} diff -r e7da2fcb7a22 -r fc9e2f7920c9 tools/libxen/src/xen_event_operation.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/libxen/src/xen_event_operation.c Fri Mar 30 17:18:42 2007 -0600 @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2006-2007, XenSource Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <string.h> + +#include "xen_internal.h" +#include "xen_event_operation.h" +#include "xen_event_operation_internal.h" + + +/* + * Maintain this in the same order as the enum declaration! + */ +static const char *lookup_table[] = +{ + "add", + "del", + "mod" +}; + + +extern xen_event_operation_set * +xen_event_operation_set_alloc(size_t size) +{ + return calloc(1, sizeof(xen_event_operation_set) + + size * sizeof(enum xen_event_operation)); +} + + +extern void +xen_event_operation_set_free(xen_event_operation_set *set) +{ + free(set); +} + + +const char * +xen_event_operation_to_string(enum xen_event_operation val) +{ + return lookup_table[val]; +} + + +extern enum xen_event_operation +xen_event_operation_from_string(xen_session *session, const char *str) +{ + return ENUM_LOOKUP(session, str, lookup_table); +} + + +const abstract_type xen_event_operation_abstract_type_ = + { + .typename = ENUM, + .enum_marshaller = + (const char *(*)(int))&xen_event_operation_to_string, + .enum_demarshaller = + (int (*)(xen_session *, const char *))&xen_event_operation_from_string + }; + + diff -r e7da2fcb7a22 -r fc9e2f7920c9 tools/libxen/src/xen_network.c --- a/tools/libxen/src/xen_network.c Fri Mar 30 10:27:15 2007 -0600 +++ b/tools/libxen/src/xen_network.c Fri Mar 30 17:18:42 2007 -0600 @@ -24,6 +24,7 @@ #include "xen_internal.h" #include "xen_network.h" #include "xen_pif.h" +#include "xen_string_string_map.h" #include "xen_vif.h" @@ -52,7 +53,10 @@ static const struct_member xen_network_r .offset = offsetof(xen_network_record, vifs) }, { .key = "PIFs", .type = &abstract_type_ref_set, - .offset = offsetof(xen_network_record, pifs) } + .offset = offsetof(xen_network_record, pifs) }, + { .key = "other_config", + .type = &abstract_type_string_string_map, + .offset = offsetof(xen_network_record, other_config) } }; const abstract_type xen_network_record_abstract_type_ = @@ -78,6 +82,7 @@ xen_network_record_free(xen_network_reco free(record->name_description); xen_vif_record_opt_set_free(record->vifs); xen_pif_record_opt_set_free(record->pifs); + xen_string_string_map_free(record->other_config); free(record); } @@ -239,6 +244,23 @@ xen_network_get_pifs(xen_session *sessio bool +xen_network_get_other_config(xen_session *session, xen_string_string_map **result, xen_network network) +{ + abstract_value param_values[] = + { + { .type = &abstract_type_string, + .u.string_val = network } + }; + + abstract_type result_type = abstract_type_string_string_map; + + *result = NULL; + XEN_CALL_("network.get_other_config"); + return session->ok; +} + + +bool xen_network_set_name_label(xen_session *session, xen_network network, char *label) { abstract_value param_values[] = @@ -271,6 +293,56 @@ xen_network_set_name_description(xen_ses bool +xen_network_set_other_config(xen_session *session, xen_network network, xen_string_string_map *other_config) +{ + abstract_value param_values[] = + { + { .type = &abstract_type_string, + .u.string_val = network }, + { .type = &abstract_type_string_string_map, + .u.set_val = (arbitrary_set *)other_config } + }; + + xen_call_(session, "network.set_other_config", param_values, 2, NULL, NULL); + return session->ok; +} + + +bool +xen_network_add_to_other_config(xen_session *session, xen_network network, char *key, char *value) +{ + abstract_value param_values[] = + { + { .type = &abstract_type_string, + .u.string_val = network }, + { .type = &abstract_type_string, + .u.string_val = key }, + { .type = &abstract_type_string, + .u.string_val = value } + }; + + xen_call_(session, "network.add_to_other_config", param_values, 3, NULL, NULL); + return session->ok; +} + + +bool +xen_network_remove_from_other_config(xen_session *session, xen_network network, char *key) +{ + abstract_value param_values[] = + { + { .type = &abstract_type_string, + .u.string_val = network }, + { .type = &abstract_type_string, + .u.string_val = key } + }; + + xen_call_(session, "network.remove_from_other_config", param_values, 2, NULL, NULL); + return session->ok; +} + + +bool xen_network_get_all(xen_session *session, struct xen_network_set **result) { diff -r e7da2fcb7a22 -r fc9e2f7920c9 tools/libxen/test/test_event_handling.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/libxen/test/test_event_handling.c Fri Mar 30 17:18:42 2007 -0600 @@ -0,0 +1,211 @@ +/* + * Copyright (c) 2006-2007 XenSource, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#define _GNU_SOURCE +#include <assert.h> +#include <inttypes.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#include <libxml/parser.h> +#include <curl/curl.h> + +#include "xen_event.h" + +//#define PRINT_XML + +static void usage() +{ + fprintf(stderr, +"Usage:\n" +"\n" +" test_event_handling <server> <username> <password>\n" +"\n" +"where\n" +" <server> is the server's host and port, e.g. localhost:9363;\n" +" <username> is the username to use at the server; and\n" +" <password> is the password.\n"); + + exit(EXIT_FAILURE); +} + + +static char *url; + + +typedef struct +{ + xen_result_func func; + void *handle; +} xen_comms; + + +static size_t +write_func(void *ptr, size_t size, size_t nmemb, xen_comms *comms) +{ + size_t n = size * nmemb; +#ifdef PRINT_XML + printf("\n\n---Result from server -----------------------\n"); + printf("%s\n",((char*) ptr)); + fflush(stdout); +#endif + return comms->func(ptr, n, comms->handle) ? n : 0; +} + + +static int +call_func(const void *data, size_t len, void *user_handle, + void *result_handle, xen_result_func result_func) +{ + (void)user_handle; + +#ifdef PRINT_XML + printf("\n\n---Data to server: -----------------------\n"); + printf("%s\n",((char*) data)); + fflush(stdout); +#endif + + CURL *curl = curl_easy_init(); + if (!curl) { + return -1; + } + + xen_comms comms = { + .func = result_func, + .handle = result_handle + }; + + curl_easy_setopt(curl, CURLOPT_URL, url); + curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 1); + curl_easy_setopt(curl, CURLOPT_MUTE, 1); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &write_func); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, &comms); + curl_easy_setopt(curl, CURLOPT_POST, 1); + curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data); + curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, len); + + CURLcode result = curl_easy_perform(curl); + + curl_easy_cleanup(curl); + + return result; +} + + +static void print_error(xen_session *session) +{ + fprintf(stderr, "Error: %d", session->error_description_count); + for (int i = 0; i < session->error_description_count; i++) + { + fprintf(stderr, "%s ", session->error_description[i]); + } + fprintf(stderr, "\n"); +} + + +/** + * Workaround for whinging GCCs, as suggested by strftime(3). + */ +static size_t my_strftime(char *s, size_t max, const char *fmt, + const struct tm *tm) +{ + return strftime(s, max, fmt, tm); +} + + +int main(int argc, char **argv) +{ + if (argc != 4) + { + usage(); + } + + url = argv[1]; + char *username = argv[2]; + char *password = argv[3]; + + xmlInitParser(); + xen_init(); + curl_global_init(CURL_GLOBAL_ALL); + +#define CLEANUP \ + do { \ + xen_session_logout(session); \ + curl_global_cleanup(); \ + xen_fini(); \ + xmlCleanupParser(); \ + } while(0) \ + + + xen_session *session = + xen_session_login_with_password(call_func, NULL, username, password); + + struct xen_string_set *classes = xen_string_set_alloc(0); + xen_event_register(session, classes); + xen_string_set_free(classes); + + if (!session->ok) + { + print_error(session); + CLEANUP; + return 1; + } + + while (true) + { + struct xen_event_record_set *events; + if (!xen_event_next(session, &events)) + { + print_error(session); + CLEANUP; + return 1; + } + + for (size_t i = 0; i < events->size; i++) + { + xen_event_record *ev = events->contents[i]; + char time[256]; + struct tm *tm = localtime(&ev->timestamp); + my_strftime(time, 256, "%c, local time", tm); + printf("Event received: ID = %"PRId64", %s.\n", ev->id, time); + switch (ev->operation) + { + case XEN_EVENT_OPERATION_ADD: + printf("%s created with UUID %s.\n", ev->class, ev->obj_uuid); + break; + + case XEN_EVENT_OPERATION_DEL: + printf("%s with UUID %s deleted.\n", ev->class, ev->obj_uuid); + break; + + case XEN_EVENT_OPERATION_MOD: + printf("%s with UUID %s modified.\n", ev->class, ev->obj_uuid); + break; + default: + assert(false); + } + } + + xen_event_record_set_free(events); + } + + CLEANUP; + + return 0; +} diff -r e7da2fcb7a22 -r fc9e2f7920c9 tools/pygrub/src/pygrub --- a/tools/pygrub/src/pygrub Fri Mar 30 10:27:15 2007 -0600 +++ b/tools/pygrub/src/pygrub Fri Mar 30 17:18:42 2007 -0600 @@ -125,16 +125,13 @@ class GrubLineEditor(curses.textpad.Text is that we can handle lines longer than the window.""" self.win.clear() - if self.pos > 70: - if self.pos > 130: - off = 120 - else: - off = 55 - l = [ "<" ] + self.line[off:] - p = self.pos - off - else: - l = self.line[:70] - p = self.pos + p = self.pos + off = 0 + while p > 70: + p -= 55 + off += 55 + + l = self.line[off:off+70] self.win.addstr(0, 0, string.join(l, (""))) if self.pos > 70: self.win.addch(0, 0, curses.ACS_LARROW) diff -r e7da2fcb7a22 -r fc9e2f7920c9 tools/python/xen/lowlevel/xc/xc.c --- a/tools/python/xen/lowlevel/xc/xc.c Fri Mar 30 10:27:15 2007 -0600 +++ b/tools/python/xen/lowlevel/xc/xc.c Fri Mar 30 17:18:42 2007 -0600 @@ -467,6 +467,26 @@ static PyObject *pyxc_linux_build(XcObje return pyxc_error_to_exception(); } +static PyObject *pyxc_get_hvm_param(XcObject *self, + PyObject *args, + PyObject *kwds) +{ + uint32_t dom; + int param; + unsigned long value; + + static char *kwd_list[] = { "domid", "param", NULL }; + if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i|i", kwd_list, + &dom, ¶m) ) + return NULL; + + if ( xc_get_hvm_param(self->xc_handle, dom, param, &value) != 0 ) + return pyxc_error_to_exception(); + + return Py_BuildValue("i", value); + +} + static PyObject *pyxc_hvm_build(XcObject *self, PyObject *args, PyObject *kwds) @@ -1224,6 +1244,14 @@ static PyMethodDef pyxc_methods[] = { " image [str]: Name of HVM loader image file.\n" " vcpus [int, 1]: Number of Virtual CPUS in domain.\n\n" "Returns: [int] 0 on success; -1 on error.\n" }, + + { "hvm_get_param", + (PyCFunction)pyxc_get_hvm_param, + METH_VARARGS | METH_KEYWORDS, "\n" + "get a parameter of HVM guest OS.\n" + " dom [int]: Identifier of domain to build into.\n" + " param [int]: No. of HVM param.\n" + "Returns: [int] value of the param.\n" }, { "sched_id_get", (PyCFunction)pyxc_sched_id_get, diff -r e7da2fcb7a22 -r fc9e2f7920c9 tools/python/xen/util/xmlrpcclient.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/python/xen/util/xmlrpcclient.py Fri Mar 30 17:18:42 2007 -0600 @@ -0,0 +1,123 @@ +#============================================================================ +# This library is free software; you can redistribute it and/or +# modify it under the terms of version 2.1 of the GNU Lesser General Public +# License as published by the Free Software Foundation. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +#============================================================================ +# Copyright (C) 2006 Anthony Liguori <aliguori@xxxxxxxxxx> +# Copyright (C) 2007 XenSource Inc. +#============================================================================ + + +from httplib import FakeSocket, HTTPConnection, HTTP +import socket +import string +import xmlrpclib +from types import StringTypes + + +try: + import SSHTransport + ssh_enabled = True +except ImportError: + # SSHTransport is disabled on Python <2.4, because it uses the subprocess + # package. + ssh_enabled = False + + +# A new ServerProxy that also supports httpu urls. An http URL comes in the +# form: +# +# httpu:///absolute/path/to/socket.sock +# +# It assumes that the RPC handler is /RPC2. This probably needs to be improved + +class HTTPUnixConnection(HTTPConnection): + def connect(self): + self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) + self.sock.connect(self.host) + +class HTTPUnix(HTTP): + _connection_class = HTTPUnixConnection + +class UnixTransport(xmlrpclib.Transport): + def request(self, host, handler, request_body, verbose=0): + self.__handler = handler + return xmlrpclib.Transport.request(self, host, '/RPC2', + request_body, verbose) + def make_connection(self, host): + return HTTPUnix(self.__handler) + + +# We need our own transport for HTTPS, because xmlrpclib.SafeTransport is +# broken -- it does not handle ERROR_ZERO_RETURN properly. +class HTTPSTransport(xmlrpclib.SafeTransport): + def _parse_response(self, file, sock): + p, u = self.getparser() + while 1: + try: + if sock: + response = sock.recv(1024) + else: + response = file.read(1024) + except socket.sslerror, exn: + if exn[0] == socket.SSL_ERROR_ZERO_RETURN: + break + raise + + if not response: + break + if self.verbose: + print 'body:', repr(response) + p.feed(response) + + file.close() + p.close() + return u.close() + + +# See xmlrpclib2.TCPXMLRPCServer._marshalled_dispatch. +def conv_string(x): + if isinstance(x, StringTypes): + s = string.replace(x, "'", r"\047") + exec "s = '" + s + "'" + return s + else: + return x + + +class ServerProxy(xmlrpclib.ServerProxy): + def __init__(self, uri, transport=None, encoding=None, verbose=0, + allow_none=1): + if transport == None: + (protocol, rest) = uri.split(':', 1) + if protocol == 'httpu': + uri = 'http:' + rest + transport = UnixTransport() + elif protocol == 'https': + transport = HTTPSTransport() + elif protocol == 'ssh': + global ssh_enabled + if ssh_enabled: + (transport, uri) = SSHTransport.getHTTPURI(uri) + else: + raise ValueError( + "SSH transport not supported on Python <2.4.") + xmlrpclib.ServerProxy.__init__(self, uri, transport, encoding, + verbose, allow_none) + + def __request(self, methodname, params): + response = xmlrpclib.ServerProxy.__request(self, methodname, params) + + if isinstance(response, tuple): + return tuple([conv_string(x) for x in response]) + else: + return conv_string(response) diff -r e7da2fcb7a22 -r fc9e2f7920c9 tools/python/xen/util/xmlrpclib2.py --- a/tools/python/xen/util/xmlrpclib2.py Fri Mar 30 10:27:15 2007 -0600 +++ b/tools/python/xen/util/xmlrpclib2.py Fri Mar 30 17:18:42 2007 -0600 @@ -21,12 +21,10 @@ An enhanced XML-RPC client/server interf """ import re -import string import fcntl from types import * -from httplib import HTTPConnection, HTTP from SimpleXMLRPCServer import SimpleXMLRPCServer, SimpleXMLRPCRequestHandler import SocketServer import xmlrpclib, socket, os, stat @@ -35,14 +33,6 @@ import mkdir from xen.web import connection from xen.xend.XendLogging import log - -try: - import SSHTransport - ssh_enabled = True -except ImportError: - # SSHTransport is disabled on Python <2.4, because it uses the subprocess - # package. - ssh_enabled = False # # Convert all integers to strings as described in the Xen API @@ -64,13 +54,6 @@ def stringify(value): return value -# A new ServerProxy that also supports httpu urls. An http URL comes in the -# form: -# -# httpu:///absolute/path/to/socket.sock -# -# It assumes that the RPC handler is /RPC2. This probably needs to be improved - # We're forced to subclass the RequestHandler class so that we can work around # some bugs in Keep-Alive handling and also enabled it by default class XMLRPCRequestHandler(SimpleXMLRPCRequestHandler): @@ -105,60 +88,6 @@ class XMLRPCRequestHandler(SimpleXMLRPCR self.wfile.flush() if self.close_connection == 1: self.connection.shutdown(1) - -class HTTPUnixConnection(HTTPConnection): - def connect(self): - self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) - self.sock.connect(self.host) - -class HTTPUnix(HTTP): - _connection_class = HTTPUnixConnection - -class UnixTransport(xmlrpclib.Transport): - def request(self, host, handler, request_body, verbose=0): - self.__handler = handler - return xmlrpclib.Transport.request(self, host, '/RPC2', - request_body, verbose) - def make_connection(self, host): - return HTTPUnix(self.__handler) - - -# See _marshalled_dispatch below. -def conv_string(x): - if isinstance(x, StringTypes): - s = string.replace(x, "'", r"\047") - exec "s = '" + s + "'" - return s - else: - return x - - -class ServerProxy(xmlrpclib.ServerProxy): - def __init__(self, uri, transport=None, encoding=None, verbose=0, - allow_none=1): - if transport == None: - (protocol, rest) = uri.split(':', 1) - if protocol == 'httpu': - uri = 'http:' + rest - transport = UnixTransport() - elif protocol == 'ssh': - global ssh_enabled - if ssh_enabled: - (transport, uri) = SSHTransport.getHTTPURI(uri) - else: - raise ValueError( - "SSH transport not supported on Python <2.4.") - xmlrpclib.ServerProxy.__init__(self, uri, transport, encoding, - verbose, allow_none) - - def __request(self, methodname, params): - response = xmlrpclib.ServerProxy.__request(self, methodname, params) - - if isinstance(response, tuple): - return tuple([conv_string(x) for x in response]) - else: - return conv_string(response) - # This is a base XML-RPC server for TCP. It sets allow_reuse_address to # true, and has an improved marshaller that logs and serializes exceptions. diff -r e7da2fcb7a22 -r fc9e2f7920c9 tools/python/xen/xend/XendAPI.py --- a/tools/python/xen/xend/XendAPI.py Fri Mar 30 10:27:15 2007 -0600 +++ b/tools/python/xen/xend/XendAPI.py Fri Mar 30 17:18:42 2007 -0600 @@ -17,6 +17,8 @@ import inspect import os +import Queue +import sets import string import sys import traceback @@ -32,7 +34,9 @@ from xen.xend.XendError import * from xen.xend.XendError import * from xen.xend.XendClient import ERROR_INVALID_DOMAIN from xen.xend.XendLogging import log +from xen.xend.XendNetwork import XendNetwork from xen.xend.XendTask import XendTask +from xen.xend.XendPIFMetrics import XendPIFMetrics from xen.xend.XendVMMetrics import XendVMMetrics from xen.xend.XendAPIConstants import * @@ -82,6 +86,91 @@ def xen_api_todo(): def now(): return xmlrpclib.DateTime(time.strftime("%Y%m%dT%H:%M:%S", time.gmtime())) + + +# --------------------------------------------------- +# Event dispatch +# --------------------------------------------------- + +EVENT_QUEUE_LENGTH = 50 +event_registrations = {} + +def event_register(session, reg_classes): + if session not in event_registrations: + event_registrations[session] = { + 'classes' : sets.Set(), + 'queue' : Queue.Queue(EVENT_QUEUE_LENGTH), + 'next-id' : 1 + } + if not reg_classes: + reg_classes = classes + event_registrations[session]['classes'].union_update(reg_classes) + + +def event_unregister(session, unreg_classes): + if session not in event_registrations: + return + + if unreg_classes: + event_registrations[session]['classes'].intersection_update( + unreg_classes) + if len(event_registrations[session]['classes']) == 0: + del event_registrations[session] + else: + del event_registrations[session] + + +def event_next(session): + if session not in event_registrations: + return xen_api_error(['SESSION_NOT_REGISTERED', session]) + queue = event_registrations[session]['queue'] + events = [queue.get()] + try: + while True: + events.append(queue.get(False)) + except Queue.Empty: + pass + + return xen_api_success(events) + + +def _ctor_event_dispatch(xenapi, ctor, api_cls, session, args): + result = ctor(xenapi, session, *args) + if result['Status'] == 'Success': + ref = result['Value'] + _event_dispatch('add', api_cls, ref, '') + return result + + +def _dtor_event_dispatch(xenapi, dtor, api_cls, session, ref, args): + result = dtor(xenapi, session, ref, *args) + if result['Status'] == 'Success': + _event_dispatch('del', api_cls, ref, '') + return result + + +def _setter_event_dispatch(xenapi, setter, api_cls, attr_name, session, ref, + args): + result = setter(xenapi, session, ref, *args) + if result['Status'] == 'Success': + _event_dispatch('mod', api_cls, ref, attr_name) + return result + + +def _event_dispatch(operation, api_cls, ref, attr_name): + event = { + 'timestamp' : now(), + 'class' : api_cls, + 'operation' : operation, + 'ref' : ref, + 'obj_uuid' : ref, + 'field' : attr_name, + } + for reg in event_registrations.values(): + if api_cls in reg['classes']: + event['id'] = reg['next-id'] + reg['next-id'] += 1 + reg['queue'].put(event) # --------------------------------------------------- @@ -373,6 +462,36 @@ def do_vm_func(fn_name, vm_ref, *args, * exn.actual]) +classes = { + 'session' : None, + 'event' : None, + 'host' : valid_host, + 'host_cpu' : valid_host_cpu, + 'host_metrics' : valid_host_metrics, + 'network' : valid_network, + 'VM' : valid_vm, + 'VM_metrics' : valid_vm_metrics, + 'VBD' : valid_vbd, + 'VBD_metrics' : valid_vbd_metrics, + 'VIF' : valid_vif, + 'VIF_metrics' : valid_vif_metrics, + 'VDI' : valid_vdi, + 'VTPM' : valid_vtpm, + 'console' : valid_console, + 'SR' : valid_sr, + 'PIF' : valid_pif, + 'PIF_metrics' : valid_pif_metrics, + 'task' : valid_task, + 'debug' : valid_debug, +} + +autoplug_classes = { + 'network' : XendNetwork, + 'VM_metrics' : XendVMMetrics, + 'PIF_metrics' : XendPIFMetrics, +} + + class XendAPI(object): """Implementation of the Xen-API in Xend. Expects to be used via XMLRPCServer. @@ -414,27 +533,7 @@ class XendAPI(object): server. """ global_validators = [session_required, catch_typeerror] - classes = { - 'session' : None, - 'host' : valid_host, - 'host_cpu' : valid_host_cpu, - 'host_metrics' : valid_host_metrics, - 'network' : valid_network, - 'VM' : valid_vm, - 'VM_metrics' : valid_vm_metrics, - 'VBD' : valid_vbd, - 'VBD_metrics' : valid_vbd_metrics, - 'VIF' : valid_vif, - 'VIF_metrics' : valid_vif_metrics, - 'VDI' : valid_vdi, - 'VTPM' : valid_vtpm, - 'console' : valid_console, - 'SR' : valid_sr, - 'PIF' : valid_pif, - 'PIF_metrics' : valid_pif_metrics, - 'task' : valid_task, - 'debug' : valid_debug, - } + # Cheat methods # ------------- @@ -457,6 +556,77 @@ class XendAPI(object): setattr(cls, get_by_uuid, _get_by_uuid) setattr(cls, get_uuid, _get_uuid) + + # Autoplugging classes + # -------------------- + # These have all of their methods grabbed out from the implementation + # class, and wrapped up to be compatible with the Xen-API. + + for api_cls, impl_cls in autoplug_classes.items(): + def doit(n): + getter = getattr(cls, '_%s_get' % api_cls) + dot_n = '%s.%s' % (api_cls, n) + full_n = '%s_%s' % (api_cls, n) + if not hasattr(cls, full_n): + f = getattr(impl_cls, n) + argcounts[dot_n] = f.func_code.co_argcount + 1 + setattr(cls, full_n, + lambda s, session, ref, *args: \ + xen_api_success( \ + f(getter(s, session, ref), *args))) + + ro_attrs = getattr(cls, '%s_attr_ro' % api_cls, []) + rw_attrs = getattr(cls, '%s_attr_rw' % api_cls, []) + methods = getattr(cls, '%s_methods' % api_cls, []) + funcs = getattr(cls, '%s_funcs' % api_cls, []) + + for attr_name in ro_attrs + rw_attrs: + doit('get_%s' % attr_name) + for attr_name in rw_attrs + cls.Base_attr_rw: + doit('set_%s' % attr_name) + for method_name, return_type in methods + cls.Base_methods: + doit('%s' % method_name) + for func_name, return_type in funcs + cls.Base_funcs: + doit('%s' % func_name) + + + def wrap_method(name, new_f): + try: + f = getattr(cls, name) + wrapped_f = (lambda *args: new_f(f, *args)) + wrapped_f.api = f.api + wrapped_f.async = f.async + setattr(cls, name, wrapped_f) + except AttributeError: + # Logged below (API call: %s not found) + pass + + + def setter_event_wrapper(api_cls, attr_name): + setter_name = '%s_set_%s' % (api_cls, attr_name) + wrap_method( + setter_name, + lambda setter, s, session, ref, *args: + _setter_event_dispatch(s, setter, api_cls, attr_name, + session, ref, args)) + + + def ctor_event_wrapper(api_cls): + ctor_name = '%s_create' % api_cls + wrap_method( + ctor_name, + lambda ctor, s, session, *args: + _ctor_event_dispatch(s, ctor, api_cls, session, args)) + + + def dtor_event_wrapper(api_cls): + dtor_name = '%s_destroy' % api_cls + wrap_method( + dtor_name, + lambda dtor, s, session, ref, *args: + _dtor_event_dispatch(s, dtor, api_cls, session, ref, args)) + + # Wrapping validators around XMLRPC calls # --------------------------------------- @@ -466,7 +636,8 @@ class XendAPI(object): n_ = n.replace('.', '_') try: f = getattr(cls, n_) - argcounts[n] = f.func_code.co_argcount - 1 + if n not in argcounts: + argcounts[n] = f.func_code.co_argcount - 1 validators = takes_instance and validator and \ [validator] or [] @@ -498,6 +669,7 @@ class XendAPI(object): for attr_name in rw_attrs + cls.Base_attr_rw: doit('%s.set_%s' % (api_cls, attr_name), True, async_support = False) + setter_event_wrapper(api_cls, attr_name) # wrap validators around methods for method_name, return_type in methods + cls.Base_methods: @@ -509,6 +681,10 @@ class XendAPI(object): doit('%s.%s' % (api_cls, func_name), False, async_support = True, return_type = return_type) + ctor_event_wrapper(api_cls) + dtor_event_wrapper(api_cls) + + _decorate = classmethod(_decorate) def __init__(self, auth): @@ -516,7 +692,7 @@ class XendAPI(object): Base_attr_ro = ['uuid'] Base_attr_rw = [] - Base_methods = [('destroy', None), ('get_record', 'Struct')] + Base_methods = [('get_record', 'Struct')] Base_funcs = [('get_all', 'Set'), ('get_by_uuid', None)] # Xen API: Class Session @@ -916,59 +1092,40 @@ class XendAPI(object): network_attr_ro = ['VIFs', 'PIFs'] network_attr_rw = ['name_label', - 'name_description'] - - network_funcs = [('create', 'network')] - - def network_create(self, _, name_label, name_description): - return xen_api_success( - XendNode.instance().network_create(name_label, name_description)) + 'name_description', + 'other_config'] + network_methods = [('add_to_other_config', None), + ('remove_from_other_config', None), + ('destroy', None)] + network_funcs = [('create', None)] + + def _network_get(self, _, ref): + return XendNode.instance().get_network(ref) + + def network_get_all(self, _): + return xen_api_success(XendNode.instance().get_network_refs()) + + def network_create(self, _, record): + return xen_api_success(XendNode.instance().network_create(record)) def network_destroy(self, _, ref): return xen_api_success(XendNode.instance().network_destroy(ref)) - def _get_network(self, ref): - return XendNode.instance().get_network(ref) - - def network_get_all(self, _): - return xen_api_success(XendNode.instance().get_network_refs()) - - def network_get_record(self, _, ref): - return xen_api_success( - XendNode.instance().get_network(ref).get_record()) - - def network_get_name_label(self, _, ref): - return xen_api_success(self._get_network(ref).name_label) - - def network_get_name_description(self, _, ref): - return xen_api_success(self._get_network(ref).name_description) - - def network_get_VIFs(self, _, ref): - return xen_api_success(self._get_network(ref).get_VIF_UUIDs()) - - def network_get_PIFs(self, session, ref): - return xen_api_success(self._get_network(ref).get_PIF_UUIDs()) - - def network_set_name_label(self, _, ref, val): - return xen_api_success(self._get_network(ref).set_name_label(val)) - - def network_set_name_description(self, _, ref, val): - return xen_api_success(self._get_network(ref).set_name_description(val)) # Xen API: Class PIF # ---------------------------------------------------------------- - PIF_attr_ro = ['metrics'] + PIF_attr_ro = ['network', + 'host', + 'metrics'] PIF_attr_rw = ['device', - 'network', - 'host', 'MAC', 'MTU', 'VLAN'] PIF_attr_inst = PIF_attr_rw - PIF_methods = [('create_VLAN', 'int')] + PIF_methods = [('create_VLAN', 'int'), ('destroy', None)] def _get_PIF(self, ref): return XendNode.instance().pifs[ref] @@ -1044,25 +1201,13 @@ class XendAPI(object): 'io_write_kbs', 'last_updated'] PIF_metrics_attr_rw = [] - PIF_methods = [] + PIF_metrics_methods = [] def PIF_metrics_get_all(self, _): return xen_api_success(XendNode.instance().pif_metrics.keys()) - def _PIF_metrics_get(self, ref): + def _PIF_metrics_get(self, _, ref): return XendNode.instance().pif_metrics[ref] - - def PIF_metrics_get_record(self, _, ref): - return xen_api_success(self._PIF_metrics_get(ref).get_record()) - - def PIF_metrics_get_io_read_kbs(self, _, ref): - return xen_api_success(self._PIF_metrics_get(ref).get_io_read_kbs()) - - def PIF_metrics_get_io_write_kbs(self, _, ref): - return xen_api_success(self._PIF_metrics_get(ref).get_io_write_kbs()) - - def PIF_metrics_get_last_updated(self, _1, _2): - return xen_api_success(now()) # Xen API: Class VM @@ -1131,7 +1276,8 @@ class XendAPI(object): ('save', None), ('set_memory_dynamic_max_live', None), ('set_memory_dynamic_min_live', None), - ('send_trigger', None)] + ('send_trigger', None), + ('destroy', None)] VM_funcs = [('create', 'VM'), ('restore', None), @@ -1390,7 +1536,8 @@ class XendAPI(object): if key.startswith("cpumap"): vcpu = int(key[6:]) try: - xendom.domain_pincpu(xeninfo.getDomid(), vcpu, value) + cpus = map(int, value.split(",")) + xendom.domain_pincpu(xeninfo.getDomid(), vcpu, cpus) except Exception, ex: log.exception(ex) @@ -1633,14 +1780,15 @@ class XendAPI(object): def VM_send_sysrq(self, _, vm_ref, req): xeninfo = XendDomain.instance().get_vm_by_uuid(vm_ref) - if xeninfo.state != XEN_API_VM_POWER_STATE_RUNNING: + if xeninfo.state == XEN_API_VM_POWER_STATE_RUNNING \ + or xeninfo.state == XEN_API_VM_POWER_STATE_PAUSED: + xeninfo.send_sysrq(req) + return xen_api_success_void() + else: return xen_api_error( ['VM_BAD_POWER_STATE', vm_ref, XendDomain.POWER_STATE_NAMES[XEN_API_VM_POWER_STATE_RUNNING], XendDomain.POWER_STATE_NAMES[xeninfo.state]]) - xeninfo.send_sysrq(req) - return xen_api_success_void() - def VM_send_trigger(self, _, vm_ref, trigger, vcpu): xendom = XendDomain.instance() @@ -1675,58 +1823,28 @@ class XendAPI(object): VM_metrics_attr_rw = [] VM_metrics_methods = [] - def _VM_metrics_get(self, ref): + def _VM_metrics_get(self, _, ref): return XendVMMetrics.get_by_uuid(ref) def VM_metrics_get_all(self, _): return xen_api_success(XendVMMetrics.get_all()) - def VM_metrics_get_record(self, _, ref): - return xen_api_success(self._VM_metrics_get(ref).get_record()) - - def VM_metrics_get_memory_actual(self, _, ref): - return xen_api_success(self._VM_metrics_get(ref).get_memory_actual()) - - def VM_metrics_get_VCPUs_number(self, _, ref): - return xen_api_success(self._VM_metrics_get(ref).get_VCPUs_number()) - - def VM_metrics_get_VCPUs_utilisation(self, _, ref): - return xen_api_success(self._VM_metrics_get(ref).get_VCPUs_utilisation()) - - def VM_metrics_get_VCPUs_CPU(self, _, ref): - return xen_api_success(self._VM_metrics_get(ref).get_VCPUs_CPU()) - - def VM_metrics_get_VCPUs_flags(self, _, ref): - return xen_api_success(self._VM_metrics_get(ref).get_VCPUs_flags()) - - def VM_metrics_get_VCPUs_params(self, _, ref): - return xen_api_success(self._VM_metrics_get(ref).get_VCPUs_params()) - - def VM_metrics_get_start_time(self, _, ref): - return xen_api_success(self._VM_metrics_get(ref).get_start_time()) - - def VM_metrics_get_state(self, _, ref): - return xen_api_success(self._VM_metrics_get(ref).get_state()) - - def VM_metrics_get_last_updated(self, _1, _2): - return xen_api_success(now()) - # Xen API: Class VBD # ---------------------------------------------------------------- - VBD_attr_ro = ['metrics', + VBD_attr_ro = ['VM', + 'VDI', + 'metrics', 'runtime_properties'] - VBD_attr_rw = ['VM', - 'VDI', - 'device', + VBD_attr_rw = ['device', 'bootable', 'mode', 'type'] VBD_attr_inst = VBD_attr_rw - VBD_methods = [('media_change', None)] + VBD_methods = [('media_change', None), ('destroy', None)] VBD_funcs = [('create', 'VBD')] # object methods @@ -1868,7 +1986,10 @@ class XendAPI(object): 'io_write_kbs', 'last_updated'] VBD_metrics_attr_rw = [] - VBD_methods = [] + VBD_metrics_methods = [] + + def VBD_metrics_get_all(self, session): + return self.VBD_get_all(session) def VBD_metrics_get_record(self, _, ref): vm = XendDomain.instance().get_vm_with_dev_uuid('vbd', ref) @@ -1893,16 +2014,17 @@ class XendAPI(object): # Xen API: Class VIF # ---------------------------------------------------------------- - VIF_attr_ro = ['metrics', + VIF_attr_ro = ['network', + 'VM', + 'metrics', 'runtime_properties'] VIF_attr_rw = ['device', - 'network', - 'VM', 'MAC', 'MTU'] VIF_attr_inst = VIF_attr_rw + VIF_methods = [('destroy', None)] VIF_funcs = [('create', 'VIF')] @@ -1960,10 +2082,10 @@ class XendAPI(object): return xen_api_success(vif_ref) def VIF_get_VM(self, session, vif_ref): - xendom = XendDomain.instance() - vm = xendom.get_vm_with_dev_uuid('vif', vif_ref) + xendom = XendDomain.instance() + vm = xendom.get_vm_with_dev_uuid('vif', vif_ref) return xen_api_success(vm.get_uuid()) - + def VIF_get_MTU(self, session, vif_ref): return self._VIF_get(vif_ref, 'MTU') @@ -2008,7 +2130,10 @@ class XendAPI(object): 'io_write_kbs', 'last_updated'] VIF_metrics_attr_rw = [] - VIF_methods = [] + VIF_metrics_methods = [] + + def VIF_metrics_get_all(self, session): + return self.VIF_get_all(session) def VIF_metrics_get_record(self, _, ref): vm = XendDomain.instance().get_vm_with_dev_uuid('vif', ref) @@ -2044,7 +2169,7 @@ class XendAPI(object): 'other_config'] VDI_attr_inst = VDI_attr_ro + VDI_attr_rw - VDI_methods = [('snapshot', 'VDI')] + VDI_methods = [('snapshot', 'VDI'), ('destroy', None)] VDI_funcs = [('create', 'VDI'), ('get_by_name_label', 'Set(VDI)')] @@ -2161,6 +2286,7 @@ class XendAPI(object): VTPM_attr_inst = VTPM_attr_rw + VTPM_methods = [('destroy', None)] VTPM_funcs = [('create', 'VTPM')] # object methods @@ -2319,7 +2445,7 @@ class XendAPI(object): 'name_label', 'name_description'] - SR_methods = [('clone', 'SR')] + SR_methods = [('clone', 'SR'), ('destroy', None)] SR_funcs = [('get_by_name_label', 'Set(SR)'), ('get_by_uuid', 'SR')] @@ -2394,6 +2520,26 @@ class XendAPI(object): XendNode.instance().save() return xen_api_success_void() + + # Xen API: Class event + # ---------------------------------------------------------------- + + event_attr_ro = [] + event_attr_rw = [] + event_funcs = [('register', None), + ('unregister', None), + ('next', None)] + + def event_register(self, session, reg_classes): + event_register(session, reg_classes) + return xen_api_success_void() + + def event_unregister(self, session, unreg_classes): + event_unregister(session, reg_classes) + return xen_api_success_void() + + def event_next(self, session): + return event_next(session) # Xen API: Class debug # ---------------------------------------------------------------- diff -r e7da2fcb7a22 -r fc9e2f7920c9 tools/python/xen/xend/XendCheckpoint.py --- a/tools/python/xen/xend/XendCheckpoint.py Fri Mar 30 10:27:15 2007 -0600 +++ b/tools/python/xen/xend/XendCheckpoint.py Fri Mar 30 17:18:42 2007 -0600 @@ -192,13 +192,11 @@ def restore(xd, fd, dominfo = None, paus image_cfg = dominfo.info.get('image', {}) is_hvm = dominfo.info.is_hvm() if is_hvm: - hvm = dominfo.info['memory_static_min'] apic = int(dominfo.info['platform'].get('apic', 0)) pae = int(dominfo.info['platform'].get('pae', 0)) - log.info("restore hvm domain %d, mem=%d, apic=%d, pae=%d", - dominfo.domid, hvm, apic, pae) + log.info("restore hvm domain %d, apic=%d, pae=%d", + dominfo.domid, apic, pae) else: - hvm = 0 apic = 0 pae = 0 @@ -224,7 +222,7 @@ def restore(xd, fd, dominfo = None, paus cmd = map(str, [xen.util.auxbin.pathTo(XC_RESTORE), fd, dominfo.getDomid(), max_pfn, - store_port, console_port, hvm, pae, apic]) + store_port, console_port, int(is_hvm), pae, apic]) log.debug("[xc_restore]: %s", string.join(cmd)) handler = RestoreInputHandler() diff -r e7da2fcb7a22 -r fc9e2f7920c9 tools/python/xen/xend/XendClient.py --- a/tools/python/xen/xend/XendClient.py Fri Mar 30 10:27:15 2007 -0600 +++ b/tools/python/xen/xend/XendClient.py Fri Mar 30 17:18:42 2007 -0600 @@ -17,7 +17,7 @@ # Copyright (C) 2006 Anthony Liguori <aliguori@xxxxxxxxxx> #============================================================================ -from xen.util.xmlrpclib2 import ServerProxy +from xen.util.xmlrpcclient import ServerProxy import os import sys diff -r e7da2fcb7a22 -r fc9e2f7920c9 tools/python/xen/xend/XendConfig.py --- a/tools/python/xen/xend/XendConfig.py Fri Mar 30 10:27:15 2007 -0600 +++ b/tools/python/xen/xend/XendConfig.py Fri Mar 30 17:18:42 2007 -0600 @@ -298,7 +298,7 @@ class XendConfig(dict): 'actions_after_reboot': 'restart', 'actions_after_crash': 'restart', 'actions_after_suspend': '', - 'is_template': False, + 'is_a_template': False, 'is_control_domain': False, 'features': '', 'PV_bootloader': '', @@ -452,7 +452,10 @@ class XendConfig(dict): for key, typ in XENAPI_CFG_TYPES.items(): val = sxp.child_value(sxp_cfg, key) if val is not None: - cfg[key] = typ(val) + try: + cfg[key] = typ(val) + except (ValueError, TypeError), e: + log.warn('Unable to convert type value for key: %s' % key) # Convert deprecated options to current equivalents. @@ -727,7 +730,7 @@ class XendConfig(dict): for key in XENAPI_PLATFORM_CFG: val = sxp.child_value(image_sxp, key, None) - if val is not None: + if val is not None and val != '': self['platform'][key] = val notes = sxp.children(image_sxp, 'notes') @@ -845,6 +848,8 @@ class XendConfig(dict): sxpr.append([name, s]) for xenapi, legacy in XENAPI_CFG_TO_LEGACY_CFG.items(): + if legacy in ('cpus'): # skip this + continue 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 @@ -858,7 +863,7 @@ class XendConfig(dict): sxpr.append(["memory", int(self["memory_dynamic_max"])/MiB]) for legacy in LEGACY_UNSUPPORTED_BY_XENAPI_CFG: - if legacy in ('domid', 'uuid'): # skip these + if legacy in ('domid', 'uuid', 'cpus'): # skip these continue if self.has_key(legacy) and self[legacy] not in (None, []): sxpr.append([legacy, self[legacy]]) @@ -1354,7 +1359,7 @@ class XendConfig(dict): for key in XENAPI_PLATFORM_CFG: val = sxp.child_value(image_sxp, key, None) - if val is not None: + if val is not None and val != '': self['platform'][key] = val notes = sxp.children(image_sxp, 'notes') diff -r e7da2fcb7a22 -r fc9e2f7920c9 tools/python/xen/xend/XendConstants.py --- a/tools/python/xen/xend/XendConstants.py Fri Mar 30 10:27:15 2007 -0600 +++ b/tools/python/xen/xend/XendConstants.py Fri Mar 30 17:18:42 2007 -0600 @@ -36,6 +36,13 @@ DOMAIN_SHUTDOWN_REASONS = { } REVERSE_DOMAIN_SHUTDOWN_REASONS = \ dict([(y, x) for x, y in DOMAIN_SHUTDOWN_REASONS.items()]) + +HVM_PARAM_CALLBACK_IRQ = 0 +HVM_PARAM_STORE_PFN = 1 +HVM_PARAM_STORE_EVTCHN = 2 +HVM_PARAM_PAE_ENABLED = 4 +HVM_PARAM_IOREQ_PFN = 5 +HVM_PARAM_BUFIOREQ_PFN = 6 restart_modes = [ "restart", diff -r e7da2fcb7a22 -r fc9e2f7920c9 tools/python/xen/xend/XendDomain.py --- a/tools/python/xen/xend/XendDomain.py Fri Mar 30 10:27:15 2007 -0600 +++ b/tools/python/xen/xend/XendDomain.py Fri Mar 30 17:18:42 2007 -0600 @@ -569,6 +569,26 @@ class XendDomain: finally: self.domains_lock.release() + def autostart_domains(self): + """ Autostart managed domains that are marked as such. """ + + need_starting = [] + + self.domains_lock.acquire() + try: + for dom_uuid, dom in self.managed_domains.items(): + if dom and dom.state == DOM_STATE_HALTED: + on_xend_start = dom.info.get('on_xend_start', 'ignore') + auto_power_on = dom.info.get('auto_power_on', False) + should_start = (on_xend_start == 'start') or auto_power_on + if should_start: + need_starting.append(dom_uuid) + finally: + self.domains_lock.release() + + for dom_uuid in need_starting: + self.domain_start(dom_uuid, False) + def cleanup_domains(self): """Clean up domains that are marked as autostop. Should be called when Xend goes down. This is currently diff -r e7da2fcb7a22 -r fc9e2f7920c9 tools/python/xen/xend/XendDomainInfo.py --- a/tools/python/xen/xend/XendDomainInfo.py Fri Mar 30 10:27:15 2007 -0600 +++ b/tools/python/xen/xend/XendDomainInfo.py Fri Mar 30 17:18:42 2007 -0600 @@ -152,8 +152,9 @@ def recreate(info, priv): try: vmpath = xstransact.Read(dompath, "vm") if not vmpath: - log.warn('/local/domain/%d/vm is missing. recreate is ' - 'confused, trying our best to recover' % domid) + if not priv: + log.warn('/local/domain/%d/vm is missing. recreate is ' + 'confused, trying our best to recover' % domid) needs_reinitialising = True raise XendError('reinit') @@ -447,13 +448,13 @@ class XendDomainInfo: self._removeVm('xend/previous_restart_time') self.storeDom("control/shutdown", reason) - ## shutdown hypercall for hvm domain desides xenstore write + # HVM domain shuts itself down only if it has PV drivers if self.info.is_hvm(): - for code in DOMAIN_SHUTDOWN_REASONS.keys(): - if DOMAIN_SHUTDOWN_REASONS[code] == reason: - break - xc.domain_shutdown(self.domid, code) - + hvm_pvdrv = xc.hvm_get_param(self.domid, HVM_PARAM_CALLBACK_IRQ) + if not hvm_pvdrv: + code = REVERSE_DOMAIN_SHUTDOWN_REASONS[reason] + log.info("HVM save:remote shutdown dom %d!", self.domid) + xc.domain_shutdown(self.domid, code) def pause(self): """Pause domain @@ -2354,7 +2355,8 @@ class XendDomainInfo: if not dev_uuid: raise XendError('Failed to create device') - if self.state == XEN_API_VM_POWER_STATE_RUNNING: + if self.state == XEN_API_VM_POWER_STATE_RUNNING \ + or self.state == XEN_API_VM_POWER_STATE_PAUSED: _, config = self.info['devices'][dev_uuid] dev_control = self.getDeviceController('vif') diff -r e7da2fcb7a22 -r fc9e2f7920c9 tools/python/xen/xend/XendLogging.py --- a/tools/python/xen/xend/XendLogging.py Fri Mar 30 10:27:15 2007 -0600 +++ b/tools/python/xen/xend/XendLogging.py Fri Mar 30 17:18:42 2007 -0600 @@ -62,6 +62,7 @@ if 'TRACE' not in logging.__dict__: # Work around a bug in Python's inspect module: findsource is supposed to # raise IOError if it fails, with other functions in that module coping # with that, but some people are seeing IndexError raised from there. + # This is Python bug 1628987. http://python.org/sf/1628987. if hasattr(inspect, 'findsource'): real_findsource = getattr(inspect, 'findsource') def findsource(*args, **kwargs): diff -r e7da2fcb7a22 -r fc9e2f7920c9 tools/python/xen/xend/XendMonitor.py --- a/tools/python/xen/xend/XendMonitor.py Fri Mar 30 10:27:15 2007 -0600 +++ b/tools/python/xen/xend/XendMonitor.py Fri Mar 30 17:18:42 2007 -0600 @@ -24,8 +24,8 @@ import re """Monitoring thread to keep track of Xend statistics. """ VBD_SYSFS_PATH = '/sys/devices/xen-backend/' -VBD_WR_PATH = VBD_SYSFS_PATH + '%s/statistics/wr_req' -VBD_RD_PATH = VBD_SYSFS_PATH + '%s/statistics/rd_req' +VBD_WR_PATH = VBD_SYSFS_PATH + '%s/statistics/wr_sect' +VBD_RD_PATH = VBD_SYSFS_PATH + '%s/statistics/rd_sect' VBD_DOMAIN_RE = r'vbd-(?P<domid>\d+)-(?P<devid>\d+)$' NET_PROCFS_PATH = '/proc/net/dev' @@ -51,14 +51,9 @@ VIF_DOMAIN_RE = re.compile(r'vif(?P<domi PROC_NET_DEV_RE) PIF_RE = re.compile(r'^\s*(?P<iface>peth\d+):\s*' + PROC_NET_DEV_RE) -# The VBD transfer figures are in "requests" where we don't -# really know how many bytes per requests. For now we make -# up a number roughly could be. -VBD_ROUGH_BYTES_PER_REQUEST = 1024 * 8 * 4 - # Interval to poll xc, sysfs and proc POLL_INTERVAL = 2.0 - +SECTOR_SIZE = 512 class XendMonitor(threading.Thread): """Monitors VCPU, VBD, VIF and PIF statistics for Xen API. @@ -186,9 +181,8 @@ class XendMonitor(threading.Thread): usage_at = time.time() rd_stat = int(open(rd_stat_path).readline().strip()) wr_stat = int(open(wr_stat_path).readline().strip()) - rd_stat *= VBD_ROUGH_BYTES_PER_REQUEST - wr_stat *= VBD_ROUGH_BYTES_PER_REQUEST - + rd_stat *= SECTOR_SIZE + wr_stat *= SECTOR_SIZE if domid not in stats: stats[domid] = {} diff -r e7da2fcb7a22 -r fc9e2f7920c9 tools/python/xen/xend/XendNetwork.py --- a/tools/python/xen/xend/XendNetwork.py Fri Mar 30 10:27:15 2007 -0600 +++ b/tools/python/xen/xend/XendNetwork.py Fri Mar 30 17:18:42 2007 -0600 @@ -28,10 +28,17 @@ IP_ROUTE_RE = r'^default via ([\d\.]+) d IP_ROUTE_RE = r'^default via ([\d\.]+) dev (\w+)' class XendNetwork: - def __init__(self, uuid, name, description): + def __init__(self, uuid, record): self.uuid = uuid - self.name_label = name - self.name_description = description + self.name_label = record.get('name_label', '') + self.name_description = record.get('name_description', '') + self.other_config = record.get('other_config', {}) + + def get_name_label(self): + return self.name_label + + def get_name_description(self): + return self.name_description def set_name_label(self, new_name): self.name_label = new_name @@ -41,7 +48,7 @@ class XendNetwork: self.name_description = new_desc XendNode.instance().save_networks() - def get_VIF_UUIDs(self): + def get_VIFs(self): result = [] vms = XendDomain.instance().get_all_vms() for vm in vms: @@ -52,17 +59,37 @@ class XendNetwork: result.append(vif) return result - def get_PIF_UUIDs(self): + def get_PIFs(self): return [x.uuid for x in XendNode.instance().pifs.values() if x.network == self] - def get_record(self, transient = True): + def get_other_config(self): + return self.other_config + + def set_other_config(self, value): + self.other_config = value + XendNode.instance().save_networks() + + def add_to_other_config(self, key, value): + self.other_config[key] = value + XendNode.instance().save_networks() + + def remove_from_other_config(self, key): + if key in self.other_config: + del self.other_config[key] + XendNode.instance().save_networks() + + def get_record(self): + return self.get_record_internal(True) + + def get_record_internal(self, transient): result = { 'uuid': self.uuid, 'name_label': self.name_label, 'name_description': self.name_description, + 'other_config' : self.other_config, } if transient: - result['VIFs'] = self.get_VIF_UUIDs() - result['PIFs'] = self.get_PIF_UUIDs() + result['VIFs'] = self.get_VIFs() + result['PIFs'] = self.get_PIFs() return result diff -r e7da2fcb7a22 -r fc9e2f7920c9 tools/python/xen/xend/XendNode.py --- a/tools/python/xen/xend/XendNode.py Fri Mar 30 10:27:15 2007 -0600 +++ b/tools/python/xen/xend/XendNode.py Fri Mar 30 17:18:42 2007 -0600 @@ -141,12 +141,16 @@ class XendNode: saved_networks = self.state_store.load_state('network') if saved_networks: for net_uuid, network in saved_networks.items(): - self.network_create(network.get('name_label'), - network.get('name_description', ''), - False, net_uuid) + self.network_create(network, False, net_uuid) else: - self.network_create('net0', '', False) - + bridges = Brctl.get_state().keys() + for bridge in bridges: + self.network_create({'name_label' : bridge }, False) + + # Get a mapping from interface to bridge + + if_to_br = dict(reduce(lambda ls,(b,ifs):[(i,b) for i in ifs] + ls, + Brctl.get_state().items(), [])) # initialise PIFs saved_pifs = self.state_store.load_state('pif') if saved_pifs: @@ -176,8 +180,14 @@ class XendNode: pif_uuid, pif['network'], exn.pif_uuid) else: for name, mtu, mac in linux_get_phy_ifaces(): - network = self.networks.values()[0] - self._PIF_create(name, mtu, -1, mac, network, False) + bridge_name = if_to_br.get(name, None) + if bridge_name is not None: + networks = [network for + network in self.networks.values() + if network.get_name_label() == bridge_name] + if len(networks) > 0: + network = networks[0] + self._PIF_create(name, mtu, -1, mac, network, False) # initialise storage saved_srs = self.state_store.load_state('sr') @@ -199,12 +209,10 @@ class XendNode: - def network_create(self, name_label, name_description, persist = True, - net_uuid = None): + def network_create(self, record, persist = True, net_uuid = None): if net_uuid is None: net_uuid = uuid.createString() - self.networks[net_uuid] = XendNetwork(net_uuid, name_label, - name_description) + self.networks[net_uuid] = XendNetwork(net_uuid, record) if persist: self.save_networks() return net_uuid @@ -280,7 +288,7 @@ class XendNode: self.state_store.save_state('pif', pif_records) def save_networks(self): - net_records = dict([(k, v.get_record(transient = False)) + net_records = dict([(k, v.get_record_internal(False)) for k, v in self.networks.items()]) self.state_store.save_state('network', net_records) diff -r e7da2fcb7a22 -r fc9e2f7920c9 tools/python/xen/xend/XendOptions.py --- a/tools/python/xen/xend/XendOptions.py Fri Mar 30 10:27:15 2007 -0600 +++ b/tools/python/xen/xend/XendOptions.py Fri Mar 30 17:18:42 2007 -0600 @@ -165,7 +165,13 @@ class XendOptions: def get_xend_tcp_xmlrpc_server_address(self): return self.get_config_string("xend-tcp-xmlrpc-server-address", - self.xend_tcp_xmlrpc_server_address_default) + self.xend_tcp_xmlrpc_server_address_default) + + def get_xend_tcp_xmlrpc_server_ssl_key_file(self): + return self.get_config_string("xend-tcp-xmlrpc-server-ssl-key-file") + + def get_xend_tcp_xmlrpc_server_ssl_cert_file(self): + return self.get_config_string("xend-tcp-xmlrpc-server-ssl-cert-file") def get_xend_unix_xmlrpc_server(self): return self.get_config_bool("xend-unix-xmlrpc-server", diff -r e7da2fcb7a22 -r fc9e2f7920c9 tools/python/xen/xend/XendPIFMetrics.py --- a/tools/python/xen/xend/XendPIFMetrics.py Fri Mar 30 10:27:15 2007 -0600 +++ b/tools/python/xen/xend/XendPIFMetrics.py Fri Mar 30 17:18:42 2007 -0600 @@ -39,11 +39,13 @@ class XendPIFMetrics: return pifs_util[pifname][n] return 0.0 + def get_last_updated(self): + import xen.xend.XendAPI as XendAPI + return XendAPI.now() + def get_record(self): - import xen.xend.XendAPI as XendAPI return {'uuid' : self.uuid, - 'PIF' : self.pif.uuid, 'io_read_kbs' : self.get_io_read_kbs(), 'io_write_kbs' : self.get_io_write_kbs(), - 'last_updated' : XendAPI.now(), + 'last_updated' : self.get_last_updated(), } diff -r e7da2fcb7a22 -r fc9e2f7920c9 tools/python/xen/xend/XendStateStore.py --- a/tools/python/xen/xend/XendStateStore.py Fri Mar 30 10:27:15 2007 -0600 +++ b/tools/python/xen/xend/XendStateStore.py Fri Mar 30 17:18:42 2007 -0600 @@ -126,6 +126,13 @@ class XendStateStore: if val_name not in cls_dict: cls_dict[val_name] = {} cls_dict[val_name][val_uuid] = None + elif val_type == '': + # dictionary + k = val_elem.getAttribute('key').encode('utf8') + v = val_elem.getAttribute('value').encode('utf8') + if val_name not in cls_dict: + cls_dict[val_name] = {} + cls_dict[val_name][k] = v elif val_type == 'string': cls_dict[val_name] = val_text.encode('utf8') elif val_type == 'float': @@ -197,7 +204,11 @@ class XendStateStore: if type(val) == dict: for val_uuid in val.keys(): val_node = doc.createElement(key) - val_node.setAttribute('uuid', val_uuid) + if key == 'other_config': + val_node.setAttribute('key', str(val_uuid)) + val_node.setAttribute('value', str(val[val_uuid])) + else: + val_node.setAttribute('uuid', val_uuid) node.appendChild(val_node) elif type(val) in (list, tuple): for val_uuid in val: diff -r e7da2fcb7a22 -r fc9e2f7920c9 tools/python/xen/xend/XendVMMetrics.py --- a/tools/python/xen/xend/XendVMMetrics.py Fri Mar 30 10:27:15 2007 -0600 +++ b/tools/python/xen/xend/XendVMMetrics.py Fri Mar 30 17:18:42 2007 -0600 @@ -92,7 +92,7 @@ class XendVMMetrics: set_flag('blocked') set_flag('online') set_flag('running') - vcpus_flags[i] = ",".join(flags) + vcpus_flags[i] = flags return vcpus_flags else: return {} @@ -115,7 +115,7 @@ class XendVMMetrics: addState("dying") addState("crashed") addState("shutdown") - return ",".join(states) + return states except Exception, err: # ignore missing domain log.trace("domain_getinfo(%d) failed, ignoring: %s", domid, str(err)) @@ -140,8 +140,11 @@ class XendVMMetrics: def get_start_time(self): return self.xend_domain_instance.info.get("start_time", -1) + def get_last_updated(self): + import xen.xend.XendAPI as XendAPI + return XendAPI.now() + def get_record(self): - import xen.xend.XendAPI as XendAPI return { 'uuid' : self.uuid, 'memory_actual' : self.get_memory_actual(), 'VCPUs_number' : self.get_VCPUs_number(), @@ -151,5 +154,5 @@ class XendVMMetrics: 'VCPUs_params' : self.get_VCPUs_params(), 'start_time' : self.get_start_time(), 'state' : self.get_state(), - 'last_updated' : XendAPI.now(), + 'last_updated' : self.get_last_updated(), } diff -r e7da2fcb7a22 -r fc9e2f7920c9 tools/python/xen/xend/server/SSLXMLRPCServer.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/python/xen/xend/server/SSLXMLRPCServer.py Fri Mar 30 17:18:42 2007 -0600 @@ -0,0 +1,103 @@ +#============================================================================ +# This library is free software; you can redistribute it and/or +# modify it under the terms of version 2.1 of the GNU Lesser General Public +# License as published by the Free Software Foundation. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +#============================================================================ +# Copyright (C) 2007 XenSource Inc. +#============================================================================ + + +""" +HTTPS wrapper for an XML-RPC server interface. Requires PyOpenSSL (Debian +package python-pyopenssl). +""" + +import socket + +from OpenSSL import SSL + +from xen.util.xmlrpclib2 import XMLRPCRequestHandler, TCPXMLRPCServer + + +class SSLXMLRPCRequestHandler(XMLRPCRequestHandler): + def setup(self): + self.connection = self.request + self.rfile = socket._fileobject(self.request, "rb", self.rbufsize) + self.wfile = socket._fileobject(self.request, "wb", self.wbufsize) + +# +# Taken from pyOpenSSL-0.6 examples (public-domain) +# + +class SSLWrapper: + """ + """ + def __init__(self, conn): + """ + Connection is not yet a new-style class, + so I'm making a proxy instead of subclassing. + """ + self.__dict__["conn"] = conn + def __getattr__(self, name): + return getattr(self.__dict__["conn"], name) + def __setattr__(self, name, value): + setattr(self.__dict__["conn"], name, value) + + def close(self): + self.shutdown() + return self.__dict__["conn"].close() + + def shutdown(self, how=1): + """ + SimpleXMLRpcServer.doPOST calls shutdown(1), + and Connection.shutdown() doesn't take + an argument. So we just discard the argument. + """ + # Block until the shutdown is complete + self.__dict__["conn"].shutdown() + self.__dict__["conn"].shutdown() + + def accept(self): + """ + This is the other part of the shutdown() workaround. + Since servers create new sockets, we have to infect + them with our magic. :) + """ + c, a = self.__dict__["conn"].accept() + return (SSLWrapper(c), a) + +# +# End of pyOpenSSL-0.6 example code. +# + +class SSLXMLRPCServer(TCPXMLRPCServer): + def __init__(self, addr, allowed, xenapi, logRequests = 1, + ssl_key_file = None, ssl_cert_file = None): + + TCPXMLRPCServer.__init__(self, addr, allowed, xenapi, + SSLXMLRPCRequestHandler, logRequests) + + if not ssl_key_file or not ssl_cert_file: + raise ValueError("SSLXMLRPCServer requires ssl_key_file " + "and ssl_cert_file to be set.") + + # make a SSL socket + ctx = SSL.Context(SSL.SSLv23_METHOD) + ctx.set_options(SSL.OP_NO_SSLv2) + ctx.use_privatekey_file (ssl_key_file) + ctx.use_certificate_file(ssl_cert_file) + self.socket = SSLWrapper(SSL.Connection(ctx, + socket.socket(self.address_family, + self.socket_type))) + self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + self.server_bind() + self.server_activate() diff -r e7da2fcb7a22 -r fc9e2f7920c9 tools/python/xen/xend/server/SrvDaemon.py --- a/tools/python/xen/xend/server/SrvDaemon.py Fri Mar 30 10:27:15 2007 -0600 +++ b/tools/python/xen/xend/server/SrvDaemon.py Fri Mar 30 17:18:42 2007 -0600 @@ -38,7 +38,8 @@ class Daemon: self.traceon = False self.tracefile = None self.traceindent = 0 - self.child = 0 + self.child = 0 + self.traceLock = threading.Lock() def cleanup_xend(self, kill): @@ -253,6 +254,7 @@ class Daemon: pass def print_trace(self, string): + self.tracefile.write("%s: "% threading.currentThread().getName()) for i in range(self.traceindent): ch = " " if (i % 5): @@ -263,50 +265,54 @@ class Daemon: self.tracefile.write(string) def trace(self, frame, event, arg): - if not self.traceon: - print >>self.tracefile - print >>self.tracefile, '-' * 20, 'TRACE OFF', '-' * 20 - self.tracefile.close() - self.tracefile = None - return None - if event == 'call': - code = frame.f_code - filename = code.co_filename - m = re.search('.*xend/(.*)', filename) - if not m: + self.traceLock.acquire() + try: + if not self.traceon: + print >>self.tracefile + print >>self.tracefile, '-' * 20, 'TRACE OFF', '-' * 20 + self.tracefile.close() + self.tracefile = None return None - modulename = m.group(1) - if modulename.endswith('.pyc'): - modulename = modulename[:-1] - if modulename == 'sxp.py' or \ - modulename == 'XendLogging.py' or \ - modulename == 'XendMonitor.py' or \ - modulename == 'server/SrvServer.py': - return None - self.traceindent += 1 - self.print_trace("> %s:%s\n" - % (modulename, code.co_name)) - elif event == 'line': - filename = frame.f_code.co_filename - lineno = frame.f_lineno - self.print_trace("%4d %s" % - (lineno, linecache.getline(filename, lineno))) - elif event == 'return': - code = frame.f_code - filename = code.co_filename - m = re.search('.*xend/(.*)', filename) - if not m: - return None - modulename = m.group(1) - self.print_trace("< %s:%s\n" - % (modulename, code.co_name)) - self.traceindent -= 1 - elif event == 'exception': - self.print_trace("! Exception:\n") - (ex, val, tb) = arg - traceback.print_exception(ex, val, tb, 10, self.tracefile) - #del tb - return self.trace + if event == 'call': + code = frame.f_code + filename = code.co_filename + m = re.search('.*xend/(.*)', filename) + if not m: + return None + modulename = m.group(1) + if modulename.endswith('.pyc'): + modulename = modulename[:-1] + if modulename == 'sxp.py' or \ + modulename == 'XendLogging.py' or \ + modulename == 'XendMonitor.py' or \ + modulename == 'server/SrvServer.py': + return None + self.traceindent += 1 + self.print_trace("> %s:%s\n" + % (modulename, code.co_name)) + elif event == 'line': + filename = frame.f_code.co_filename + lineno = frame.f_lineno + self.print_trace("%4d %s" % + (lineno, linecache.getline(filename, lineno))) + elif event == 'return': + code = frame.f_code + filename = code.co_filename + m = re.search('.*xend/(.*)', filename) + if not m: + return None + modulename = m.group(1) + self.print_trace("< %s:%s\n" + % (modulename, code.co_name)) + self.traceindent -= 1 + elif event == 'exception': + self.print_trace("! Exception:\n") + (ex, val, tb) = arg + traceback.print_exception(ex, val, tb, 10, self.tracefile) + #del tb + return self.trace + finally: + self.traceLock.release() def set_user(self): # Set the UID. diff -r e7da2fcb7a22 -r fc9e2f7920c9 tools/python/xen/xend/server/SrvServer.py --- a/tools/python/xen/xend/server/SrvServer.py Fri Mar 30 10:27:15 2007 -0600 +++ b/tools/python/xen/xend/server/SrvServer.py Fri Mar 30 17:18:42 2007 -0600 @@ -52,6 +52,7 @@ from xen.xend import Vifctl from xen.xend import Vifctl from xen.xend.XendLogging import log from xen.xend.XendClient import XEN_API_SOCKET +from xen.xend.XendDomain import instance as xenddomain from xen.web.SrvDir import SrvDir from SrvRoot import SrvRoot @@ -72,7 +73,7 @@ class XendServers: def add(self, server): self.servers.append(server) - def cleanup(self, signum = 0, frame = None): + def cleanup(self, signum = 0, frame = None, reloading = False): log.debug("SrvServer.cleanup()") self.cleaningUp = True for server in self.servers: @@ -80,12 +81,18 @@ class XendServers: server.shutdown() except: pass + + # clean up domains for those that have on_xend_stop + if not reloading: + xenddomain().cleanup_domains() + self.running = False + def reloadConfig(self, signum = 0, frame = None): log.debug("SrvServer.reloadConfig()") self.reloadingConfig = True - self.cleanup(signum, frame) + self.cleanup(signum, frame, reloading = True) def start(self, status): # Running the network script will spawn another process, which takes @@ -144,6 +151,12 @@ class XendServers: status.close() status = None + # Reaching this point means we can auto start domains + try: + xenddomain().autostart_domains() + except Exception, e: + log.exception("Failed while autostarting domains") + # loop to keep main thread alive until it receives a SIGTERM self.running = True while self.running: @@ -172,33 +185,49 @@ def _loadConfig(servers, root, reload): api_cfg = xoptions.get_xen_api_server() if api_cfg: try: - addrs = [(str(x[0]).split(':'), - 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] - for addrport, auth, allowed in addrs: - if auth not in [XendAPI.AUTH_PAM, XendAPI.AUTH_NONE]: - log.error('Xen-API server configuration %s is invalid, ' + - 'as %s is not a valid authentication type.', - api_cfg, auth) - break - - if len(addrport) == 1: - if addrport[0] == 'unix': - servers.add(XMLRPCServer(auth, True, - path = XEN_API_SOCKET, - hosts_allowed = allowed)) + for server_cfg in api_cfg: + # Parse the xen-api-server config + + ssl_key_file = None + ssl_cert_file = None + auth_method = XendAPI.AUTH_NONE + hosts_allowed = None + + host_addr = server_cfg[0].split(':', 1) + if len(host_addr) == 1: + if host_addr[0].lower() == 'unix': + use_tcp = False + host = 'localhost' + port = 0 else: - servers.add( - XMLRPCServer(auth, True, True, '', - int(addrport[0]), - hosts_allowed = allowed)) + use_tcp = True + host = '' + port = int(host_addr[0]) else: - addr, port = addrport - servers.add(XMLRPCServer(auth, True, True, addr, - int(port), - hosts_allowed = allowed)) + use_tcp = True + host = str(host_addr[0]) + port = int(host_addr[1]) + + if len(server_cfg) > 1: + if server_cfg[1] in [XendAPI.AUTH_PAM, XendAPI.AUTH_NONE]: + auth_method = server_cfg[1] + + if len(server_cfg) > 2: + hosts_allowed = server_cfg[2] or None + + if len(server_cfg) > 4: + # SSL key and cert file + ssl_key_file = server_cfg[3] + ssl_cert_file = server_cfg[4] + + + servers.add(XMLRPCServer(auth_method, True, use_tcp = use_tcp, + ssl_key_file = ssl_key_file, + ssl_cert_file = ssl_cert_file, + host = host, port = port, + path = XEN_API_SOCKET, + hosts_allowed = hosts_allowed)) + except (ValueError, TypeError), exn: log.exception('Xen API Server init failed') log.error('Xen-API server configuration %s is invalid.', api_cfg) @@ -206,8 +235,17 @@ def _loadConfig(servers, root, reload): if xoptions.get_xend_tcp_xmlrpc_server(): addr = xoptions.get_xend_tcp_xmlrpc_server_address() port = xoptions.get_xend_tcp_xmlrpc_server_port() - servers.add(XMLRPCServer(XendAPI.AUTH_PAM, False, use_tcp = True, - host = addr, port = port)) + ssl_key_file = xoptions.get_xend_tcp_xmlrpc_server_ssl_key_file() + ssl_cert_file = xoptions.get_xend_tcp_xmlrpc_server_ssl_cert_file() + + if ssl_key_file and ssl_cert_file: + servers.add(XMLRPCServer(XendAPI.AUTH_PAM, False, use_tcp = True, + ssl_key_file = ssl_key_file, + ssl_cert_file = ssl_cert_file, + host = addr, port = port)) + else: + servers.add(XMLRPCServer(XendAPI.AUTH_PAM, False, use_tcp = True, + host = addr, port = port)) if xoptions.get_xend_unix_xmlrpc_server(): servers.add(XMLRPCServer(XendAPI.AUTH_PAM, False)) diff -r e7da2fcb7a22 -r fc9e2f7920c9 tools/python/xen/xend/server/XMLRPCServer.py --- a/tools/python/xen/xend/server/XMLRPCServer.py Fri Mar 30 10:27:15 2007 -0600 +++ b/tools/python/xen/xend/server/XMLRPCServer.py Fri Mar 30 17:18:42 2007 -0600 @@ -21,6 +21,11 @@ import types import types import xmlrpclib from xen.util.xmlrpclib2 import UnixXMLRPCServer, TCPXMLRPCServer +try: + from SSLXMLRPCServer import SSLXMLRPCServer + ssl_enabled = True +except ImportError: + ssl_enabled = False from xen.xend import XendAPI, XendDomain, XendDomainInfo, XendNode from xen.xend import XendLogging, XendDmesg @@ -87,14 +92,20 @@ exclude = ['domain_create', 'domain_rest exclude = ['domain_create', 'domain_restore'] class XMLRPCServer: - def __init__(self, auth, use_xenapi, use_tcp=False, host = "localhost", - port = 8006, path = XML_RPC_SOCKET, hosts_allowed = None): + def __init__(self, auth, use_xenapi, use_tcp = False, + ssl_key_file = None, ssl_cert_file = None, + host = "localhost", port = 8006, path = XML_RPC_SOCKET, + hosts_allowed = None): + self.use_tcp = use_tcp self.port = port self.host = host self.path = path self.hosts_allowed = hosts_allowed + self.ssl_key_file = ssl_key_file + self.ssl_cert_file = ssl_cert_file + self.ready = False self.running = True self.auth = auth @@ -107,14 +118,32 @@ class XMLRPCServer: try: if self.use_tcp: - log.info("Opening TCP XML-RPC server on %s%d%s", + using_ssl = self.ssl_key_file and self.ssl_cert_file + + log.info("Opening %s XML-RPC server on %s%d%s", + using_ssl and 'HTTPS' or 'TCP', self.host and '%s:' % self.host or 'all interfaces, port ', self.port, authmsg) - self.server = TCPXMLRPCServer((self.host, self.port), - self.hosts_allowed, - self.xenapi is not None, - logRequests = False) + + if using_ssl: + if not ssl_enabled: + raise ValueError("pyOpenSSL not installed. " + "Unable to start HTTPS XML-RPC server") + self.server = SSLXMLRPCServer( + (self.host, self.port), + self.hosts_allowed, + self.xenapi is not None, + logRequests = False, + ssl_key_file = self.ssl_key_file, + ssl_cert_file = self.ssl_cert_file) + else: + self.server = TCPXMLRPCServer( + (self.host, self.port), + self.hosts_allowed, + self.xenapi is not None, + logRequests = False) + else: log.info("Opening Unix domain socket XML-RPC server on %s%s", self.path, authmsg) @@ -126,7 +155,12 @@ class XMLRPCServer: ready = True running = False return - + except Exception, e: + log.exception('Cannot start server: %s!', e) + ready = True + running = False + return + # Register Xen API Functions # ------------------------------------------------------------------- # exportable functions are ones that do not begin with '_' diff -r e7da2fcb7a22 -r fc9e2f7920c9 tools/python/xen/xm/XenAPI.py --- a/tools/python/xen/xm/XenAPI.py Fri Mar 30 10:27:15 2007 -0600 +++ b/tools/python/xen/xm/XenAPI.py Fri Mar 30 17:18:42 2007 -0600 @@ -12,7 +12,7 @@ # License along with this library; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #============================================================================ -# Copyright (C) 2006 XenSource Inc. +# Copyright (C) 2006-2007 XenSource Inc. #============================================================================ # # Parts of this file are based upon xmlrpclib.py, the XML-RPC client @@ -47,7 +47,7 @@ import gettext import gettext import xmlrpclib -import xen.util.xmlrpclib2 +import xen.util.xmlrpcclient as xmlrpcclient translation = gettext.translation('xen-xm', fallback = True) @@ -85,7 +85,7 @@ _RECONNECT_AND_RETRY = (lambda _ : ()) _RECONNECT_AND_RETRY = (lambda _ : ()) -class Session(xen.util.xmlrpclib2.ServerProxy): +class Session(xmlrpcclient.ServerProxy): """A server proxy and session manager for communicating with Xend using the Xen-API. @@ -104,13 +104,15 @@ class Session(xen.util.xmlrpclib2.Server def __init__(self, uri, transport=None, encoding=None, verbose=0, allow_none=1): - xen.util.xmlrpclib2.ServerProxy.__init__(self, uri, transport, - encoding, verbose, - allow_none) + xmlrpcclient.ServerProxy.__init__(self, uri, transport, encoding, + verbose, allow_none) self._session = None self.last_login_method = None self.last_login_params = None + + def getSession(self): + return self._session def xenapi_request(self, methodname, params): if methodname.startswith('login'): @@ -150,7 +152,7 @@ class Session(xen.util.xmlrpclib2.Server elif name.startswith('login'): return lambda *params: self._login(name, params) else: - return xen.util.xmlrpclib2.ServerProxy.__getattr__(self, name) + return xmlrpcclient.ServerProxy.__getattr__(self, name) def _parse_result(result): diff -r e7da2fcb7a22 -r fc9e2f7920c9 tools/python/xen/xm/create.dtd --- a/tools/python/xen/xm/create.dtd Fri Mar 30 10:27:15 2007 -0600 +++ b/tools/python/xen/xm/create.dtd Fri Mar 30 17:18:42 2007 -0600 @@ -37,6 +37,8 @@ memory, vbd*, vif*, + console*, + platform*, vcpu_param*, other_config*)> <!ATTLIST vm is_a_template CDATA #REQUIRED @@ -46,11 +48,6 @@ actions_after_shutdown %NORMAL_EXIT; #REQUIRED actions_after_reboot %NORMAL_EXIT; #REQUIRED actions_after_crash %CRASH_BEHAVIOUR; #REQUIRED - platform_std_VGA CDATA #REQUIRED - platform_serial CDATA #REQUIRED - platform_localtime CDATA #REQUIRED - platform_clock_offet CDATA #REQUIRED - platform_enable_audio CDATA #REQUIRED PCI_bus CDATA #REQUIRED> <!ELEMENT memory EMPTY> @@ -74,8 +71,10 @@ mtu CDATA #REQUIRED device CDATA #REQUIRED qos_algorithm_type CDATA #REQUIRED - bridge CDATA #IMPLIED network CDATA #IMPLIED> + +<!ELEMENT console (other_config*)> +<!ATTLIST console protocol (vt100|rfb|rdp) #REQUIRED> <!ELEMENT pv EMPTY> <!ATTLIST pv kernel CDATA #REQUIRED @@ -105,13 +104,17 @@ <!ELEMENT label (#PCDATA)> <!ELEMENT description (#PCDATA)> +<!ELEMENT platform EMPTY> +<!ATTLIST platform key CDATA #REQUIRED + value CDATA #REQUIRED> + <!ELEMENT vcpu_param EMPTY> <!ATTLIST vcpu_param key CDATA #REQUIRED value CDATA #REQUIRED> <!ELEMENT other_config EMPTY> <!ATTLIST other_config key CDATA #REQUIRED - value CDATA #REQUIRED> + value CDATA #REQUIRED> <!ELEMENT qos_algorithm_param EMPTY> <!ATTLIST qos_algorithm_param key CDATA #REQUIRED diff -r e7da2fcb7a22 -r fc9e2f7920c9 tools/python/xen/xm/create.py --- a/tools/python/xen/xm/create.py Fri Mar 30 10:27:15 2007 -0600 +++ b/tools/python/xen/xm/create.py Fri Mar 30 17:18:42 2007 -0600 @@ -103,6 +103,11 @@ gopts.opt('xmldryrun', short='x', fn=set_true, default=0, use="XML dry run - prints the resulting configuration in XML but " "does not create the domain.") + +gopts.opt('skipdtd', short='s', + fn=set_true, default=0, + use="Skip DTD checking - skips checks on XML before creating. " + " Experimental. Can decrease create time." ) gopts.opt('paused', short='p', fn=set_true, default=0, @@ -1098,6 +1103,8 @@ def parseCommandLine(argv): if not gopts.vals.xauthority: gopts.vals.xauthority = get_xauthority() + gopts.is_xml = False + # Process remaining args as config variables. for arg in args: if '=' in arg: @@ -1106,11 +1113,16 @@ def parseCommandLine(argv): if gopts.vals.config: config = gopts.vals.config else: - gopts.load_defconfig() - preprocess(gopts.vals) - if not gopts.getopt('name') and gopts.getopt('defconfig'): - gopts.setopt('name', os.path.basename(gopts.getopt('defconfig'))) - config = make_config(gopts.vals) + try: + gopts.load_defconfig() + preprocess(gopts.vals) + if not gopts.getopt('name') and gopts.getopt('defconfig'): + gopts.setopt('name', os.path.basename(gopts.getopt('defconfig'))) + config = make_config(gopts.vals) + except XMLFileError, ex: + XMLFile = ex.getFile() + gopts.is_xml = True + config = ex.getFile() return (gopts, config) @@ -1233,6 +1245,8 @@ def help(): return str(gopts) def main(argv): + is_xml = False + try: (opts, config) = parseCommandLine(argv) except StandardError, ex: @@ -1241,23 +1255,24 @@ def main(argv): if not opts: return - if type(config) == str: - try: - config = sxp.parse(file(config))[0] - except IOError, exn: - raise OptionError("Cannot read file %s: %s" % (config, exn[1])) - - if serverType == SERVER_XEN_API: - from xen.xm.xenapi_create import sxp2xml - sxp2xml_inst = sxp2xml() - doc = sxp2xml_inst.convert_sxp_to_xml(config, transient=True) - - if opts.vals.dryrun: - SXPPrettyPrint.prettyprint(config) - - if opts.vals.xmldryrun and serverType == SERVER_XEN_API: - from xml.dom.ext import PrettyPrint as XMLPrettyPrint - XMLPrettyPrint(doc) + if not opts.is_xml: + if type(config) == str: + try: + config = sxp.parse(file(config))[0] + except IOError, exn: + raise OptionError("Cannot read file %s: %s" % (config, exn[1])) + + if serverType == SERVER_XEN_API: + from xen.xm.xenapi_create import sxp2xml + sxp2xml_inst = sxp2xml() + doc = sxp2xml_inst.convert_sxp_to_xml(config, transient=True) + + if opts.vals.dryrun and not opts.is_xml: + SXPPrettyPrint.prettyprint(config) + + if opts.vals.xmldryrun and serverType == SERVER_XEN_API: + from xml.dom.ext import PrettyPrint as XMLPrettyPrint + XMLPrettyPrint(doc) if opts.vals.dryrun or opts.vals.xmldryrun: return @@ -1268,10 +1283,15 @@ def main(argv): if serverType == SERVER_XEN_API: from xen.xm.xenapi_create import xenapi_create xenapi_create_inst = xenapi_create() - vm_refs = xenapi_create_inst.create(document = doc) + if opts.is_xml: + vm_refs = xenapi_create_inst.create(filename = config, + skipdtd = opts.vals.skipdtd) + else: + vm_refs = xenapi_create_inst.create(document = doc, + skipdtd = opts.vals.skipdtd) map(lambda vm_ref: server.xenapi.VM.start(vm_ref, 0), vm_refs) - else: + elif not opts.is_xml: if not create_security_check(config): raise security.ACMError( 'Security Configuration prevents domain from starting') diff -r e7da2fcb7a22 -r fc9e2f7920c9 tools/python/xen/xm/main.py --- a/tools/python/xen/xm/main.py Fri Mar 30 10:27:15 2007 -0600 +++ b/tools/python/xen/xm/main.py Fri Mar 30 17:18:42 2007 -0600 @@ -49,7 +49,7 @@ from xen.xend.XendConstants import * from xen.xm.opts import OptionError, Opts, wrap, set_true from xen.xm import console -from xen.util.xmlrpclib2 import ServerProxy +from xen.util.xmlrpcclient import ServerProxy import XenAPI @@ -345,7 +345,8 @@ acm_commands = [ ] all_commands = (domain_commands + host_commands + scheduler_commands + - device_commands + vnet_commands + acm_commands + ['shell']) + device_commands + vnet_commands + acm_commands + + ['shell', 'event-monitor']) ## @@ -559,11 +560,21 @@ def get_single_vm(dom): def get_single_vm(dom): if serverType == SERVER_XEN_API: uuids = server.xenapi.VM.get_by_name_label(dom) - n = len(uuids) - if n > 0: + if len(uuids) > 0: return uuids[0] - else: - raise OptionError("Domain '%s' not found." % dom) + + try: + domid = int(dom) + uuids = [server.xenapi.VM.get_domid(vm_ref) + for vm_ref in server.xenapi.VM.get_all() + if int(server.xenapi.VM.get_domid(vm_ref)) == domid] + except: + pass + + if len(uuids) > 0: + return uuids[0] + + raise OptionError("Domain '%s' not found." % dom) else: dominfo = server.xend.domain(dom, False) return dominfo['uuid'] @@ -633,6 +644,17 @@ def xm_shell(args): Shell().cmdloop('The Xen Master. Type "help" for a list of functions.') +def xm_event_monitor(args): + if serverType == SERVER_XEN_API: + while True: + server.xenapi.event.register(args) + events = server.xenapi.event.next() + for e in events: + print e + else: + err("Event monitoring not supported unless using Xen-API.") + + ######################################################################### # # Main xm functions @@ -722,7 +744,7 @@ def getDomains(domain_names, state, full states = ('running', 'blocked', 'paused', 'shutdown', 'crashed', 'dying') def state_on_off(state): - if dom_metrics['state'].find(state) > -1: + if state in dom_metrics['state']: return state[0] else: return "-" @@ -850,7 +872,8 @@ def parse_doms_info(info): def check_sched_type(sched): if serverType == SERVER_XEN_API: - current = server.xenapi.host.get_sched_policy(server.xenapi.session.get_this_host()) + current = server.xenapi.host.get_sched_policy( + server.xenapi.session.get_this_host(server.getSession())) else: current = 'unknown' for x in server.xend.node.info()[1:]: @@ -952,12 +975,10 @@ def xm_vcpu_list(args): ['name', vm_records[vm_ref]['name_label']], ['vcpu_count', vm_records[vm_ref]['VCPUs_max']]] - - for i in range(int(vm_records[vm_ref]['VCPUs_max'])): def chk_flag(flag): - return vm_metrics[vm_ref]['VCPUs_flags'][str(i)] \ - .find(flag) > -1 and 1 or 0 + return flag in vm_metrics[vm_ref]['VCPUs_flags'][str(i)] \ + and 1 or 0 vcpu_info = ['vcpu', ['number', @@ -1044,7 +1065,7 @@ def xm_vcpu_list(args): if serverType == SERVER_XEN_API: nr_cpus = len(server.xenapi.host.get_host_CPUs( - server.xenapi.session.get_this_host())) + server.xenapi.session.get_this_host(server.getSession()))) else: for x in server.xend.node.info()[1:]: if len(x) > 1 and x[0] == 'nr_cpus': @@ -1260,8 +1281,9 @@ def xm_vcpu_pin(args): cpumap = cpu_make_map(args[2]) if serverType == SERVER_XEN_API: + cpumap = map(str, cpumap) server.xenapi.VM.add_to_VCPUs_params_live( - get_single_vm(dom), "cpumap%i" % vcpu, ",".join(cpumap)) + get_single_vm(dom), "cpumap%i" % int(vcpu), ",".join(cpumap)) else: server.xend.domain.pincpu(dom, vcpu, cpumap) @@ -1509,7 +1531,7 @@ def xm_info(args): # Need to fake out old style xm info as people rely on parsing it host_record = server.xenapi.host.get_record( - server.xenapi.session.get_this_host()) + server.xenapi.session.get_this_host(server.getSession())) host_cpu_records = map(server.xenapi.host_cpu.get_record, host_record["host_CPUs"]) @@ -1686,7 +1708,7 @@ def xm_debug_keys(args): if serverType == SERVER_XEN_API: server.xenapi.host.send_debug_keys( - server.xenapi.session.get_this_host(), + server.xenapi.session.get_this_host(server.getSession()), keys) else: server.xend.node.send_debug_keys(keys) @@ -1715,7 +1737,7 @@ def xm_dmesg(args): usage('dmesg') if serverType == SERVER_XEN_API: - host = server.xenapi.session.get_this_host() + host = server.xenapi.session.get_this_host(server.getSession()) if use_clear: print server.xenapi.host.dmesg_clear(host), else: @@ -1731,7 +1753,7 @@ def xm_log(args): if serverType == SERVER_XEN_API: print server.xenapi.host.get_log( - server.xenapi.session.get_this_host()) + server.xenapi.session.get_this_host(server.getSession())) else: print server.xend.node.log() @@ -2169,6 +2191,7 @@ def xm_vnet_delete(args): commands = { "shell": xm_shell, + "event-monitor": xm_event_monitor, # console commands "console": xm_console, # xenstat commands @@ -2371,11 +2394,10 @@ def _run_cmd(cmd, cmd_name, args): if isinstance(e, security.ACMError): err(str(e)) return False, 1 - else: - print "Unexpected error:", sys.exc_info()[0] - print - print "Please report to xen-devel@xxxxxxxxxxxxxxxxxxx" - raise + print "Unexpected error:", sys.exc_info()[0] + print + print "Please report to xen-devel@xxxxxxxxxxxxxxxxxxx" + raise return False, 1 diff -r e7da2fcb7a22 -r fc9e2f7920c9 tools/python/xen/xm/messages/en/xen-xm.po --- a/tools/python/xen/xm/messages/en/xen-xm.po Fri Mar 30 10:27:15 2007 -0600 +++ b/tools/python/xen/xm/messages/en/xen-xm.po Fri Mar 30 17:18:42 2007 -0600 @@ -19,7 +19,7 @@ msgid "" msgid "" msgstr "" "Project-Id-Version: Xen-xm 3.0\n" -"PO-Revision-Date: 2007-03-10 23:17+0000\n" +"PO-Revision-Date: 2007-03-29 16:13+0100\n" "Last-Translator: Ewan Mellor <ewan@xxxxxxxxxxxxx>\n" "Language-Team: xen-devel <xen-devel@xxxxxxxxxxxxxxxxxxx>\n" "MIME-Version: 1.0\n" @@ -64,3 +64,6 @@ msgstr "The VM must be %(2)s to perform msgid "VM_HVM_REQUIRED" msgstr "HVM guest support is unavailable: is VT/AMD-V supported by your CPU and enabled in your BIOS?" + +msgid "SESSION_NOT_REGISTERED" +msgstr "This session is not registered to receive events. You must call event.register before event.next. (Session handle is %(1)s.)" diff -r e7da2fcb7a22 -r fc9e2f7920c9 tools/python/xen/xm/opts.py --- a/tools/python/xen/xm/opts.py Fri Mar 30 10:27:15 2007 -0600 +++ b/tools/python/xen/xm/opts.py Fri Mar 30 17:18:42 2007 -0600 @@ -24,6 +24,8 @@ import sys import sys import types + + def _line_wrap(text, width = 70): lines = [] current_line = '' @@ -59,6 +61,15 @@ class OptionError(Exception): self.usage = usage def __str__(self): return self.message + +class XMLFileError(Exception): + """Thrown is input is an XML File""" + def __init__(self, XMLFile): + self.XMLFile = XMLFile + def __str__(self): + return "XMLFileError: %s" % self.XMLFile + def getFile(self): + return self.XMLFile class Opt: """An individual option. @@ -492,6 +503,14 @@ class Opts: p = os.path.join(os.path.curdir, p) if os.path.exists(p): self.info('Using config file "%s".' % p) + + f = open(p) + is_xml = (f.read(1) == '<') + f.close() + + if is_xml: + raise XMLFileError(p) + self.load(p, help) break else: diff -r e7da2fcb7a22 -r fc9e2f7920c9 tools/python/xen/xm/xenapi_create.py --- a/tools/python/xen/xm/xenapi_create.py Fri Mar 30 10:27:15 2007 -0600 +++ b/tools/python/xen/xm/xenapi_create.py Fri Mar 30 17:18:42 2007 -0600 @@ -25,7 +25,7 @@ from xen.xend import sxp from xen.xend import sxp from xen.xend.XendAPIConstants import XEN_API_ON_NORMAL_EXIT, \ XEN_API_ON_CRASH_BEHAVIOUR - +from xen.xm.opts import OptionError import sys import os @@ -75,15 +75,20 @@ class xenapi_create: self.dtd = "/usr/lib/python/xen/xm/create.dtd" - def create(self, filename=None, document=None): + def create(self, filename=None, document=None, skipdtd=False): """ Create a domain from an XML file or DOM tree """ + if skipdtd: + print "Skipping DTD checks. Dangerous!" + if filename is not None: - self.check_dtd(file) - document = parse(file) + if not skipdtd: + self.check_dtd(filename) + document = parse(filename) elif document is not None: - self.check_dom_against_dtd(document) + if not skipdtd: + self.check_dom_against_dtd(document) self.check_doc(document) @@ -179,15 +184,7 @@ class xenapi_create: map(self.check_vif, vifs) def check_vif(self, vif): - """ - Check that the vif has - either a bridge or network - name but not both - """ - if "bridge" in vif.attributes.keys() \ - and "network" in vif.attributes.keys(): - raise "You cannot specify both a bridge and\ - a network name." + pass # Cleanup methods here def cleanup_vdis(self, vdi_refs_dict): @@ -265,18 +262,8 @@ class xenapi_create: vm.attributes["actions_after_reboot"].value, "actions_after_crash": vm.attributes["actions_after_crash"].value, - "platform_std_VGA": - vm.attributes["platform_std_VGA"].value, - "platform_serial": - vm.attributes["platform_serial"].value, - "platform_localtime": - vm.attributes["platform_localtime"].value, - "platform_clock_offet": - vm.attributes["platform_clock_offet"].value, - "platform_enable_audio": - vm.attributes["platform_enable_audio"].value, - "PCI_bus": - vm.attributes["platform_enable_audio"].value, + "platform": + get_child_nodes_as_dict(vm, "platform", "key", "value"), "other_config": get_child_nodes_as_dict(vm, "other_config", "key", "value") } @@ -300,7 +287,7 @@ class xenapi_create: "HVM_boot_policy": get_child_node_attribute(vm, "hvm", "boot_policy"), "HVM_boot_params": - get_child_nodes_as_dict(hvm, "boot_params", "key", "value") + get_child_nodes_as_dict(hvm, "boot_param", "key", "value") }) try: vm_ref = server.xenapi.VM.create(vm_record) @@ -308,19 +295,29 @@ class xenapi_create: traceback.print_exc() sys.exit(-1) - # Now create vbds - - vbds = vm.getElementsByTagName("vbd") - - self.create_vbds(vm_ref, vbds, vdis) - - # Now create vifs - - vifs = vm.getElementsByTagName("vif") - - self.create_vifs(vm_ref, vifs) - - return vm_ref + try: + # Now create vbds + + vbds = vm.getElementsByTagName("vbd") + + self.create_vbds(vm_ref, vbds, vdis) + + # Now create vifs + + vifs = vm.getElementsByTagName("vif") + + self.create_vifs(vm_ref, vifs) + + # Now create consoles + + consoles = vm.getElementsByTagName("console") + + self.create_consoles(vm_ref, consoles) + + return vm_ref + except: + server.xenapi.VM.destroy(vm_ref) + raise def create_vbds(self, vm_ref, vbds, vdis): log(DEBUG, "create_vbds") @@ -358,13 +355,16 @@ class xenapi_create: def create_vif(self, vm_ref, vif): log(DEBUG, "create_vif") - if "bridge" in vif.attributes.keys(): - raise "Not allowed to add by bridge just yet" - elif "network" in vif.attributes.keys(): - network = [network_ref + if "network" in vif.attributes.keys(): + networks = [network_ref for network_ref in server.xenapi.network.get_all() if server.xenapi.network.get_name_label(network_ref) - == vif.attributes["network"].value][0] + == vif.attributes["network"].value] + if len(networks) > 0: + network = networks[0] + else: + raise OptionError("Network %s doesn't exist" + % vif.attributes["network"].value) else: network = self._get_network_ref() @@ -397,6 +397,26 @@ class xenapi_create: self._network_refs = server.xenapi.network.get_all() return self._network_refs.pop(0) + def create_consoles(self, vm_ref, consoles): + log(DEBUG, "create_consoles") + return map(lambda console: self.create_console(vm_ref, console), + consoles) + + def create_console(self, vm_ref, console): + log(DEBUG, "create_consoles") + + console_record = { + "VM": + vm_ref, + "protocol": + console.attributes["protocol"].value, + "other_params": + get_child_nodes_as_dict(console, + "other_param", "key", "value") + } + + return server.xenapi.console.create(console_record) + def get_child_by_name(exp, childname, default = None): try: return [child for child in sxp.children(exp) @@ -460,11 +480,6 @@ class sxp2xml: = actions_after_reboot vm.attributes["actions_after_crash"] \ = actions_after_crash - vm.attributes["platform_std_VGA"] = "false" - vm.attributes["platform_serial"] = "" - vm.attributes["platform_localtime"] = "" - vm.attributes["platform_clock_offet"] = "" - vm.attributes["platform_enable_audio"] = "" vm.attributes["PCI_bus"] = "" vm.attributes["vcpus_max"] \ @@ -502,7 +517,13 @@ class sxp2xml: vm.appendChild(pv) elif image[0] == "hvm": hvm = document.createElement("hvm") - hvm.attributes["boot_policy"] = "" + hvm.attributes["boot_policy"] = "BIOS order" + + boot_order = document.createElement("boot_param") + boot_order.attributes["key"] = "order" + boot_order.attributes["value"] \ + = get_child_by_name(image, "boot", "abcd") + hvm.appendChild vm.appendChild(hvm) @@ -535,6 +556,18 @@ class sxp2xml: vifs = map(lambda vif: self.extract_vif(vif, document), vifs_sxp) map(vm.appendChild, vifs) + + # Last but not least the consoles... + + consoles = self.extract_consoles(image, document) + + map(vm.appendChild, consoles) + + # Platform variables... + + platform = self.extract_platform(image, document) + + map(vm.appendChild, platform) # transient? @@ -626,13 +659,69 @@ class sxp2xml: vif.attributes["qos_algorithm_type"] = "" if get_child_by_name(vif_sxp, "bridge") is not None: - vif.attributes["bridge"] \ + vif.attributes["network"] \ = get_child_by_name(vif_sxp, "bridge") return vif _eths = -1 + def mk_other_config(self, key, value, document): + other_config = document.createElement("other_config") + other_config.attributes["key"] = key + other_config.attributes["value"] = value + return other_config + + def extract_consoles(self, image, document): + consoles = [] + + if int(get_child_by_name(image, "nographic", "1")) == 1: + return consoles + + if int(get_child_by_name(image, "vnc", "0")) == 1: + console = document.createElement("console") + console.attributes["protocol"] = "rfb" + console.appendChild(self.mk_other_config( + "vncunused", str(get_child_by_name(image, "vncunused", "0")), + document)) + console.appendChild(self.mk_other_config( + "vnclisten", + get_child_by_name(image, "vnclisten", "127.0.0.1"), + document)) + console.appendChild(self.mk_other_config( + "vncpasswd", get_child_by_name(image, "vncpasswd", ""), + document)) + consoles.append(console) + if int(get_child_by_name(image, "sdl", "0")) == 1: + console = document.createElement("console") + console.attributes["protocol"] = "sdl" + console.appendChild(self.mk_other_config( + "display", get_child_by_name(image, "display", ""), + document)) + console.appendChild(self.mk_other_config( + "xauthority", + get_child_by_name(image, "vxauthority", "127.0.0.1"), + document)) + console.appendChild(self.mk_other_config( + "vncpasswd", get_child_by_name(image, "vncpasswd", ""), + document)) + consoles.append(console) + + return consoles + + + def extract_platform(self, image, document): + platform_keys = ['acpi', 'apic', 'pae'] + + def extract_platform_key(key): + platform = document.createElement("platform") + platform.attributes["key"] = key + platform.attributes["value"] \ + = str(get_child_by_name(image, key, "1")) + return platform + + return map(extract_platform_key, platform_keys) + def getFreshEthDevice(self): self._eths += 1 return "eth%i" % self._eths diff -r e7da2fcb7a22 -r fc9e2f7920c9 tools/security/policies/security_policy.xsd --- a/tools/security/policies/security_policy.xsd Fri Mar 30 10:27:15 2007 -0600 +++ b/tools/security/policies/security_policy.xsd Fri Mar 30 17:18:42 2007 -0600 @@ -22,6 +22,8 @@ <xsd:element name="Reference" type="xsd:string" minOccurs="0" maxOccurs="1" /> <xsd:element name="Date" minOccurs="0" maxOccurs="1" type="xsd:string"></xsd:element> <xsd:element name="NameSpaceUrl" minOccurs="0" maxOccurs="1" type="xsd:string"></xsd:element> + <xsd:element name="Version" minOccurs="0" maxOccurs="1" type="VersionFormat"/> + <xsd:element ref="FromPolicy" minOccurs="0" maxOccurs="1"/> </xsd:sequence> </xsd:complexType> </xsd:element> @@ -116,4 +118,17 @@ <xsd:enumeration value="PrimaryPolicyComponent"></xsd:enumeration> </xsd:restriction> </xsd:simpleType> + <xsd:element name="FromPolicy"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="PolicyName" minOccurs="1" maxOccurs="1" type="xsd:string"/> + <xsd:element name="Version" minOccurs="1" maxOccurs="1" type="VersionFormat"/> + </xsd:sequence> + </xsd:complexType> + </xsd:element> + <xsd:simpleType name="VersionFormat"> + <xsd:restriction base="xsd:string"> + <xsd:pattern value="[0-9]{1,8}.[0-9]{1,8}"></xsd:pattern> + </xsd:restriction> + </xsd:simpleType> </xsd:schema> diff -r e7da2fcb7a22 -r fc9e2f7920c9 tools/security/secpol_tool.c --- a/tools/security/secpol_tool.c Fri Mar 30 10:27:15 2007 -0600 +++ b/tools/security/secpol_tool.c Fri Mar 30 17:18:42 2007 -0600 @@ -57,7 +57,7 @@ void usage(char *progname) /*************************** DUMPS *******************************/ -void acm_dump_chinesewall_buffer(void *buf, int buflen) +void acm_dump_chinesewall_buffer(void *buf, int buflen, uint16_t chwall_ref) { struct acm_chwall_policy_buffer *cwbuf = @@ -91,6 +91,8 @@ void acm_dump_chinesewall_buffer(void *b for (j = 0; j < ntohl(cwbuf->chwall_max_types); j++) printf("%02x ", ntohs(ssids[i * ntohl(cwbuf->chwall_max_types) + j])); + if (i == chwall_ref) + printf(" <-- Domain-0"); } printf("\n\nConfict Sets:\n"); conflicts = @@ -131,7 +133,7 @@ void acm_dump_chinesewall_buffer(void *b } } -void acm_dump_ste_buffer(void *buf, int buflen) +void acm_dump_ste_buffer(void *buf, int buflen, uint16_t ste_ref) { struct acm_ste_policy_buffer *stebuf = @@ -158,11 +160,14 @@ void acm_dump_ste_buffer(void *buf, int for (j = 0; j < ntohl(stebuf->ste_max_types); j++) printf("%02x ", ntohs(ssids[i * ntohl(stebuf->ste_max_types) + j])); + if (i == ste_ref) + printf(" <-- Domain-0"); } printf("\n\n"); } -void acm_dump_policy_buffer(void *buf, int buflen) +void acm_dump_policy_buffer(void *buf, int buflen, + uint16_t chwall_ref, uint16_t ste_ref) { struct acm_policy_buffer *pol = (struct acm_policy_buffer *) buf; char *policy_reference_name = @@ -172,6 +177,9 @@ void acm_dump_policy_buffer(void *buf, i printf("============\n"); printf("POLICY REFERENCE = %s.\n", policy_reference_name); printf("PolicyVer = %x.\n", ntohl(pol->policy_version)); + printf("XML Vers. = %d.%d\n", + ntohl(pol->xml_pol_version.major), + ntohl(pol->xml_pol_version.minor)); printf("Magic = %x.\n", ntohl(pol->magic)); printf("Len = %x.\n", ntohl(pol->len)); printf("Primary = %s (c=%x, off=%x).\n", @@ -187,13 +195,15 @@ void acm_dump_policy_buffer(void *buf, i acm_dump_chinesewall_buffer(ALIGN8(buf + ntohl(pol->primary_buffer_offset)), ntohl(pol->len) - - ntohl(pol->primary_buffer_offset)); + ntohl(pol->primary_buffer_offset), + chwall_ref); break; case ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY: acm_dump_ste_buffer(ALIGN8(buf + ntohl(pol->primary_buffer_offset)), ntohl(pol->len) - - ntohl(pol->primary_buffer_offset)); + ntohl(pol->primary_buffer_offset), + ste_ref); break; case ACM_NULL_POLICY: @@ -209,13 +219,15 @@ void acm_dump_policy_buffer(void *buf, i acm_dump_chinesewall_buffer(ALIGN8(buf + ntohl(pol->secondary_buffer_offset)), ntohl(pol->len) - - ntohl(pol->secondary_buffer_offset)); + ntohl(pol->secondary_buffer_offset), + chwall_ref); break; case ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY: acm_dump_ste_buffer(ALIGN8(buf + ntohl(pol->secondary_buffer_offset)), ntohl(pol->len) - - ntohl(pol->secondary_buffer_offset)); + ntohl(pol->secondary_buffer_offset), + ste_ref); break; case ACM_NULL_POLICY: @@ -227,6 +239,27 @@ void acm_dump_policy_buffer(void *buf, i } } +/************************** get dom0 ssidref *****************************/ +int acm_get_ssidref(int xc_handle, int domid, uint16_t *chwall_ref, + uint16_t *ste_ref) +{ + int ret; + struct acm_getssid getssid; + char buf[4096]; + struct acm_ssid_buffer *ssid = (struct acm_ssid_buffer *)buf; + getssid.interface_version = ACM_INTERFACE_VERSION; + set_xen_guest_handle(getssid.ssidbuf, buf); + getssid.ssidbuf_size = sizeof(buf); + getssid.get_ssid_by = ACM_GETBY_domainid; + getssid.id.domainid = domid; + ret = xc_acm_op(xc_handle, ACMOP_getssid, &getssid, sizeof(getssid)); + if (ret == 0) { + *chwall_ref = ssid->ssidref & 0xffff; + *ste_ref = ssid->ssidref >> 16; + } + return ret; +} + /******************************* get policy ******************************/ #define PULL_CACHE_SIZE 8192 @@ -236,12 +269,16 @@ int acm_domain_getpolicy(int xc_handle) { struct acm_getpolicy getpolicy; int ret; + uint16_t chwall_ref, ste_ref; memset(pull_buffer, 0x00, sizeof(pull_buffer)); getpolicy.interface_version = ACM_INTERFACE_VERSION; set_xen_guest_handle(getpolicy.pullcache, pull_buffer); getpolicy.pullcache_size = sizeof(pull_buffer); ret = xc_acm_op(xc_handle, ACMOP_getpolicy, &getpolicy, sizeof(getpolicy)); + if (ret >= 0) { + ret = acm_get_ssidref(xc_handle, 0, &chwall_ref, &ste_ref); + } if (ret < 0) { printf("ACM operation failed: errno=%d\n", errno); @@ -251,7 +288,9 @@ int acm_domain_getpolicy(int xc_handle) } /* dump policy */ - acm_dump_policy_buffer(pull_buffer, sizeof(pull_buffer)); + acm_dump_policy_buffer(pull_buffer, sizeof(pull_buffer), + chwall_ref, ste_ref); + return ret; } @@ -263,6 +302,7 @@ int acm_domain_loadpolicy(int xc_handle, int ret, fd; off_t len; uint8_t *buffer; + uint16_t chwall_ssidref, ste_ssidref; if ((ret = stat(filename, &mystat))) { printf("File %s not found.\n", filename); @@ -279,10 +319,14 @@ int acm_domain_loadpolicy(int xc_handle, printf("File %s not found.\n", filename); goto free_out; } + ret =acm_get_ssidref(xc_handle, 0, &chwall_ssidref, &ste_ssidref); + if (ret < 0) { + goto free_out; + } if (len == read(fd, buffer, len)) { struct acm_setpolicy setpolicy; /* dump it and then push it down into xen/acm */ - acm_dump_policy_buffer(buffer, len); + acm_dump_policy_buffer(buffer, len, chwall_ssidref, ste_ssidref); setpolicy.interface_version = ACM_INTERFACE_VERSION; set_xen_guest_handle(setpolicy.pushcache, buffer); setpolicy.pushcache_size = len; diff -r e7da2fcb7a22 -r fc9e2f7920c9 tools/security/secpol_xml2bin.c --- a/tools/security/secpol_xml2bin.c Fri Mar 30 10:27:15 2007 -0600 +++ b/tools/security/secpol_xml2bin.c Fri Mar 30 17:18:42 2007 -0600 @@ -108,26 +108,25 @@ char *policy_filename = NULL, char *policy_reference_name = NULL; +char *policy_version_string = NULL; + void walk_labels(xmlNode * start, xmlDocPtr doc, unsigned long state); void usage(char *prg) { - printf("Usage: %s [OPTIONS] POLICYNAME\n", prg); - printf - ("POLICYNAME is the directory name within the policy directory\n"); - printf - ("that contains the policy files. The default policy directory\n"); - printf("is '%s' (see the '-d' option below to change it)\n", - POLICY_DIR); - printf - ("The policy files contained in the POLICYNAME directory must be named:\n"); - printf("\tPOLICYNAME-security_policy.xml\n"); - printf("\tPOLICYNAME-security_label_template.xml\n\n"); - printf("OPTIONS:\n"); - printf("\t-d POLICYDIR\n"); - printf - ("\t\tUse POLICYDIR as the policy directory. This directory must contain\n"); - printf("\t\tthe policy schema file 'security_policy.xsd'\n"); + printf( + "Usage: %s [OPTIONS] POLICYNAME\n" + "POLICYNAME is the directory name within the policy directory\n" + "that contains the policy files. The default policy directory\n" + "is '%s' (see the '-d' option below to change it)\n" + "The policy files contained in the POLICYNAME directory must be named:\n" + "\tPOLICYNAME-security_policy.xml\n" + "\tPOLICYNAME-security_label_template.xml\n\n" + "OPTIONS:\n" + "\t-d POLICYDIR\n" + "\t\tUse POLICYDIR as the policy directory. This directory must \n" + "\t\tcontain the policy schema file 'security_policy.xsd'\n", + prg, POLICY_DIR); exit(EXIT_FAILURE); } @@ -300,25 +299,50 @@ void walk_policy(xmlNode * start, xmlDoc case XML2BIN_CHWALLTYPES: case XML2BIN_CONFLICTSETS: case XML2BIN_POLICYHEADER: + case XML2BIN_FROMPOLICY: walk_policy(cur_node->children, doc, state | (1 << code)); break; case XML2BIN_POLICYNAME: /* get policy reference name .... */ - if (state != XML2BIN_PN_S) { + if (state != XML2BIN_PN_S && + state != XML2BIN_PN_frompolicy_S) { printf("ERROR: >Url< >%s< out of context.\n", (char *) xmlNodeListGetString(doc, cur_node-> xmlChildrenNode, 1)); exit(EXIT_FAILURE); } - policy_reference_name = (char *) - xmlNodeListGetString(doc, cur_node->xmlChildrenNode, 1); - if (!policy_reference_name) { - printf("ERROR: empty >policy reference name (Url)<!\n"); + if (state == XML2BIN_PN_S) { + policy_reference_name = (char *) + xmlNodeListGetString(doc, cur_node->xmlChildrenNode, 1); + if (!policy_reference_name) { + printf("ERROR: empty >policy reference name (Url)<!\n"); + exit(EXIT_FAILURE); + } else + printf("Policy Reference name (Url): %s\n", + policy_reference_name); + } + break; + + case XML2BIN_VERSION: /* get policy version number .... */ + if (state != XML2BIN_PN_S && + state != XML2BIN_PN_frompolicy_S) { + printf("ERROR: >Url< >%s< out of context.\n", + (char *) xmlNodeListGetString(doc, + cur_node-> + xmlChildrenNode, 1)); exit(EXIT_FAILURE); - } else - printf("Policy Reference name (Url): %s\n", - policy_reference_name); + } + if (state == XML2BIN_PN_S) { + policy_version_string = (char *) + xmlNodeListGetString(doc, cur_node->xmlChildrenNode, 1); + if (!policy_version_string) { + printf("ERROR: empty >policy version string <!\n"); + exit(EXIT_FAILURE); + } else + printf("Policy version string: %s\n", + policy_version_string); + } break; case XML2BIN_STE: @@ -1135,8 +1159,12 @@ int write_binary(char *filename) NULL, *policy_reference_buffer = NULL; u_int32_t len; int fd, ret = 0; + uint32_t major = 0, minor = 0; u_int32_t len_ste = 0, len_chwall = 0, len_pr = 0; /* length of policy components */ + + if (policy_version_string) + sscanf(policy_version_string,"%d.%d", &major, &minor); /* open binary file */ if ((fd = @@ -1152,6 +1180,8 @@ int write_binary(char *filename) /* determine primary component (default chwall) */ header.policy_version = htonl(ACM_POLICY_VERSION); header.magic = htonl(ACM_MAGIC); + header.xml_pol_version.major = htonl(major); + header.xml_pol_version.minor = htonl(minor); len = sizeof(struct acm_policy_buffer); if (have_chwall) diff -r e7da2fcb7a22 -r fc9e2f7920c9 tools/security/secpol_xml2bin.h --- a/tools/security/secpol_xml2bin.h Fri Mar 30 10:27:15 2007 -0600 +++ b/tools/security/secpol_xml2bin.h Fri Mar 30 17:18:42 2007 -0600 @@ -22,31 +22,35 @@ #define SCHEMA_FILENAME "security_policy.xsd" /* basic states (used as 1 << X) */ -#define ENDOFLIST_POS 22 /* ADAPT!! this position will be NULL; stay below 32 (bit) */ -#define XML2BIN_SECPOL 0 /* policy tokens */ -#define XML2BIN_STE 1 -#define XML2BIN_CHWALL 2 -#define XML2BIN_CONFLICTSETS 3 -#define XML2BIN_CSTYPE 4 -#define XML2BIN_POLICYHEADER 5 -#define XML2BIN_NSURL 6 -#define XML2BIN_POLICYNAME 7 -#define XML2BIN_URL 8 -#define XML2BIN_REFERENCE 9 -#define XML2BIN_DATE 10 +enum { + XML2BIN_SECPOL = 0, /* policy tokens */ + XML2BIN_STE, + XML2BIN_CHWALL, + XML2BIN_CONFLICTSETS, + XML2BIN_CSTYPE, + XML2BIN_POLICYHEADER, + XML2BIN_NSURL, + XML2BIN_POLICYNAME, + XML2BIN_URL, + XML2BIN_REFERENCE, + XML2BIN_DATE, + XML2BIN_VERSION, + XML2BIN_FROMPOLICY, -#define XML2BIN_LABELTEMPLATE 11 /* label tokens */ -#define XML2BIN_SUBJECTS 12 -#define XML2BIN_OBJECTS 13 -#define XML2BIN_VM 14 -#define XML2BIN_RES 15 -#define XML2BIN_NAME 16 + XML2BIN_LABELTEMPLATE, /* label tokens */ + XML2BIN_SUBJECTS, + XML2BIN_OBJECTS, + XML2BIN_VM, + XML2BIN_RES, + XML2BIN_NAME, -#define XML2BIN_STETYPES 17 /* shared tokens */ -#define XML2BIN_CHWALLTYPES 18 -#define XML2BIN_TYPE 19 -#define XML2BIN_TEXT 20 -#define XML2BIN_COMMENT 21 + XML2BIN_STETYPES, + XML2BIN_CHWALLTYPES, + XML2BIN_TYPE, + XML2BIN_TEXT, + XML2BIN_COMMENT, + ENDOFLIST_POS /* keep last ! */ +}; /* type "data type" (currently 16bit) */ typedef u_int16_t type_t; @@ -68,6 +72,8 @@ char *token[32] = [XML2BIN_URL] = "PolicyUrl", [XML2BIN_REFERENCE] = "Reference", [XML2BIN_DATE] = "Date", + [XML2BIN_VERSION] = "Version", + [XML2BIN_FROMPOLICY] = "FromPolicy", [XML2BIN_LABELTEMPLATE] = "SecurityLabelTemplate", /* label-template xml */ [XML2BIN_SUBJECTS] = "SubjectLabels", @@ -79,7 +85,7 @@ char *token[32] = [XML2BIN_STETYPES] = "SimpleTypeEnforcementTypes", /* common tags */ [XML2BIN_CHWALLTYPES] = "ChineseWallTypes", [XML2BIN_TYPE] = "Type", - [XML2BIN_TEXT] = "text", + [XML2BIN_TEXT] = "text", [XML2BIN_COMMENT] = "comment", [ENDOFLIST_POS] = NULL /* End of LIST, adapt ENDOFLIST_POS when adding entries */ @@ -112,6 +118,10 @@ char *token[32] = #define XML2BIN_PN_S ((1 << XML2BIN_SECPOL) | \ (1 << XML2BIN_POLICYHEADER)) +#define XML2BIN_PN_frompolicy_S ((1 << XML2BIN_SECPOL) | \ + (1 << XML2BIN_POLICYHEADER) | \ + (1 << XML2BIN_FROMPOLICY)) + /* label xml states */ #define XML2BIN_VM_S ((1 << XML2BIN_SECPOL) | \ (1 << XML2BIN_LABELTEMPLATE) | \ @@ -147,7 +157,7 @@ char *token[32] = */ /* protects from unnoticed changes in struct acm_policy_buffer */ -#define WRITTEN_AGAINST_ACM_POLICY_VERSION 2 +#define WRITTEN_AGAINST_ACM_POLICY_VERSION 3 /* protects from unnoticed changes in struct acm_chwall_policy_buffer */ #define WRITTEN_AGAINST_ACM_CHWALL_VERSION 1 diff -r e7da2fcb7a22 -r fc9e2f7920c9 tools/xcutils/xc_restore.c --- a/tools/xcutils/xc_restore.c Fri Mar 30 10:27:15 2007 -0600 +++ b/tools/xcutils/xc_restore.c Fri Mar 30 17:18:42 2007 -0600 @@ -42,8 +42,6 @@ main(int argc, char **argv) apic = atoi(argv[8]); if (hvm) { - /* pass the memsize to xc_hvm_restore to find the store_mfn */ - store_mfn = hvm; ret = xc_hvm_restore(xc_fd, io_fd, domid, max_pfn, store_evtchn, &store_mfn, pae, apic); } else diff -r e7da2fcb7a22 -r fc9e2f7920c9 tools/xm-test/lib/XmTestLib/XenAPIDomain.py --- a/tools/xm-test/lib/XmTestLib/XenAPIDomain.py Fri Mar 30 10:27:15 2007 -0600 +++ b/tools/xm-test/lib/XmTestLib/XenAPIDomain.py Fri Mar 30 17:18:42 2007 -0600 @@ -22,7 +22,6 @@ import os import os import sys from XmTestLib import * -from xen.util.xmlrpclib2 import ServerProxy from types import DictType diff -r e7da2fcb7a22 -r fc9e2f7920c9 tools/xm-test/tests/destroy/06_destroy_dom0_neg.py --- a/tools/xm-test/tests/destroy/06_destroy_dom0_neg.py Fri Mar 30 10:27:15 2007 -0600 +++ b/tools/xm-test/tests/destroy/06_destroy_dom0_neg.py Fri Mar 30 17:18:42 2007 -0600 @@ -10,5 +10,5 @@ status, output = traceCommand("xm destro status, output = traceCommand("xm destroy 0") if status == 0: FAIL("xm destroy returned bad status, expected non 0, status is: %i" % status) -elif not re.search("Error", output): +elif not re.search("Error", output, re.I): FAIL("xm destroy returned bad output, expected Error:, output is: %s" % output) diff -r e7da2fcb7a22 -r fc9e2f7920c9 unmodified_drivers/linux-2.6/platform-pci/platform-pci.c --- a/unmodified_drivers/linux-2.6/platform-pci/platform-pci.c Fri Mar 30 10:27:15 2007 -0600 +++ b/unmodified_drivers/linux-2.6/platform-pci/platform-pci.c Fri Mar 30 17:18:42 2007 -0600 @@ -36,6 +36,7 @@ #include <asm/pgtable.h> #include <xen/interface/memory.h> #include <xen/features.h> +#include <xen/gnttab.h> #ifdef __ia64__ #include <asm/xen/xencomm.h> #endif @@ -61,9 +62,11 @@ unsigned long *phys_to_machine_mapping; unsigned long *phys_to_machine_mapping; EXPORT_SYMBOL(phys_to_machine_mapping); +static unsigned long shared_info_frame; +static uint64_t callback_via; + static int __devinit init_xen_info(void) { - unsigned long shared_info_frame; struct xen_add_to_physmap xatp; extern void *shared_info_area; @@ -219,7 +222,6 @@ static int __devinit platform_pci_init(s int i, ret; long ioaddr, iolen; long mmio_addr, mmio_len; - uint64_t callback_via; i = pci_enable_device(pdev); if (i) @@ -303,6 +305,35 @@ static struct pci_driver platform_driver static int pci_device_registered; +void platform_pci_suspend(void) +{ + gnttab_suspend(); +} +EXPORT_SYMBOL_GPL(platform_pci_suspend); + +void platform_pci_resume(void) +{ + struct xen_add_to_physmap xatp; + phys_to_machine_mapping = NULL; + + /* do 2 things for PV driver restore on HVM + * 1: rebuild share info + * 2: set callback irq again + */ + xatp.domid = DOMID_SELF; + xatp.idx = 0; + xatp.space = XENMAPSPACE_shared_info; + xatp.gpfn = shared_info_frame; + if (HYPERVISOR_memory_op(XENMEM_add_to_physmap, &xatp)) + BUG(); + + if (( set_callback_via(callback_via))) + printk("platform_pci_resume failure!\n"); + + gnttab_resume(); +} +EXPORT_SYMBOL_GPL(platform_pci_resume); + static int __init platform_pci_module_init(void) { int rc; diff -r e7da2fcb7a22 -r fc9e2f7920c9 xen/acm/acm_chinesewall_hooks.c --- a/xen/acm/acm_chinesewall_hooks.c Fri Mar 30 10:27:15 2007 -0600 +++ b/xen/acm/acm_chinesewall_hooks.c Fri Mar 30 17:18:42 2007 -0600 @@ -41,6 +41,9 @@ #include <acm/acm_core.h> #include <acm/acm_hooks.h> #include <acm/acm_endian.h> +#include <acm/acm_core.h> + +ssidref_t dom0_chwall_ssidref = 0x0001; /* local cache structures for chinese wall policy */ struct chwall_binary_policy chwall_bin_pol; @@ -53,7 +56,7 @@ int acm_init_chwall_policy(void) { /* minimal startup policy; policy write-locked already */ chwall_bin_pol.max_types = 1; - chwall_bin_pol.max_ssidrefs = 2; + chwall_bin_pol.max_ssidrefs = 1 + dom0_chwall_ssidref; chwall_bin_pol.max_conflictsets = 1; chwall_bin_pol.ssidrefs = (domaintype_t *) xmalloc_array(domaintype_t, @@ -254,7 +257,7 @@ chwall_init_state(struct acm_chwall_poli * more than one type is currently running */ } -static int chwall_set_policy(u8 * buf, u32 buf_size) +static int chwall_set_policy(u8 * buf, u32 buf_size, int is_bootpolicy) { /* policy write-locked already */ struct acm_chwall_policy_buffer *chwall_buf = @@ -285,6 +288,12 @@ static int chwall_set_policy(u8 * buf, u if ((chwall_buf->policy_code != ACM_CHINESE_WALL_POLICY) || (chwall_buf->policy_version != ACM_CHWALL_VERSION)) return -EINVAL; + + /* during boot dom0_chwall_ssidref is set */ + if (is_bootpolicy && + (dom0_chwall_ssidref >= chwall_buf->chwall_max_ssidrefs)) { + goto error_free; + } /* 1. allocate new buffers */ ssids = diff -r e7da2fcb7a22 -r fc9e2f7920c9 xen/acm/acm_core.c --- a/xen/acm/acm_core.c Fri Mar 30 10:27:15 2007 -0600 +++ b/xen/acm/acm_core.c Fri Mar 30 17:18:42 2007 -0600 @@ -62,18 +62,63 @@ struct acm_binary_policy acm_bin_pol; /* acm binary policy lock */ DEFINE_RWLOCK(acm_bin_pol_rwlock); +/* ACM's only accepted policy name */ +char polname[80]; +char *acm_accepted_boot_policy_name = NULL; + +static void __init set_dom0_ssidref(const char *val) +{ + /* expected format: + ssidref=<hex number>:<policy name> + Policy name must not have a 'space'. + */ + const char *c; + int lo, hi; + int i; + int dom0_ssidref = simple_strtoull(val, &c, 0); + + if (!strncmp(&c[0],":sHype:", 7)) { + lo = dom0_ssidref & 0xffff; + if (lo < ACM_MAX_NUM_TYPES && lo >= 1) + dom0_chwall_ssidref = lo; + hi = dom0_ssidref >> 16; + if (hi < ACM_MAX_NUM_TYPES && hi >= 1) + dom0_ste_ssidref = hi; + for (i = 0; i < sizeof(polname); i++) { + polname[i] = c[7+i]; + if (polname[i] == '\0' || polname[i] == '\t' || + polname[i] == '\n' || polname[i] == ' ' || + polname[i] == ':') { + break; + } + } + polname[i] = 0; + acm_accepted_boot_policy_name = polname; + } +} + +custom_param("ssidref", set_dom0_ssidref); + int acm_set_policy_reference(u8 *buf, u32 buf_size) { + char *name = (char *)(buf + sizeof(struct acm_policy_reference_buffer)); struct acm_policy_reference_buffer *pr = (struct acm_policy_reference_buffer *)buf; + + if (acm_accepted_boot_policy_name != NULL) { + if (strcmp(acm_accepted_boot_policy_name, name)) { + printk("Policy's name '%s' is not the expected one '%s'.\n", + name, acm_accepted_boot_policy_name); + return ACM_ERROR; + } + } + acm_bin_pol.policy_reference_name = (char *)xmalloc_array(u8, be32_to_cpu(pr->len)); if (!acm_bin_pol.policy_reference_name) return -ENOMEM; - - strlcpy(acm_bin_pol.policy_reference_name, - (char *)(buf + sizeof(struct acm_policy_reference_buffer)), - be32_to_cpu(pr->len)); + strlcpy(acm_bin_pol.policy_reference_name, name, be32_to_cpu(pr->len)); + printk("%s: Activating policy %s\n", __func__, acm_bin_pol.policy_reference_name); return 0; @@ -190,7 +235,8 @@ acm_is_policy(char *buf, unsigned long l static int acm_setup(char *policy_start, - unsigned long policy_len) + unsigned long policy_len, + int is_bootpolicy) { int rc = ACM_OK; struct acm_policy_buffer *pol; @@ -202,7 +248,8 @@ acm_setup(char *policy_start, if (be32_to_cpu(pol->magic) != ACM_MAGIC) return rc; - rc = do_acm_set_policy((void *)policy_start, (u32)policy_len); + rc = do_acm_set_policy((void *)policy_start, (u32)policy_len, + is_bootpolicy); if (rc == ACM_OK) { printkd("Policy len 0x%lx, start at %p.\n",policy_len,policy_start); @@ -224,7 +271,10 @@ acm_init(char *policy_start, int ret = ACM_OK; /* first try to load the boot policy (uses its own locks) */ - acm_setup(policy_start, policy_len); + acm_setup(policy_start, policy_len, 1); + + /* a user-provided policy may have any name; only matched during boot */ + acm_accepted_boot_policy_name = NULL; if (acm_active_security_policy != ACM_POLICY_UNDEFINED) { @@ -235,6 +285,9 @@ acm_init(char *policy_start, /* else continue with the minimal hardcoded default startup policy */ printk("%s: Loading default policy (%s).\n", __func__, ACM_POLICY_NAME(ACM_DEFAULT_SECURITY_POLICY)); + + /* (re-)set dom-0 ssidref to default */ + dom0_ste_ssidref = dom0_chwall_ssidref = 0x0001; if (acm_init_binary_policy(ACM_DEFAULT_SECURITY_POLICY)) { ret = -EINVAL; diff -r e7da2fcb7a22 -r fc9e2f7920c9 xen/acm/acm_null_hooks.c --- a/xen/acm/acm_null_hooks.c Fri Mar 30 10:27:15 2007 -0600 +++ b/xen/acm/acm_null_hooks.c Fri Mar 30 17:18:42 2007 -0600 @@ -33,7 +33,7 @@ null_dump_binary_policy(u8 *buf, u32 buf } static int -null_set_binary_policy(u8 *buf, u32 buf_size) +null_set_binary_policy(u8 *buf, u32 buf_size, int is_bootpolicy) { return ACM_OK; } diff -r e7da2fcb7a22 -r fc9e2f7920c9 xen/acm/acm_policy.c --- a/xen/acm/acm_policy.c Fri Mar 30 10:27:15 2007 -0600 +++ b/xen/acm/acm_policy.c Fri Mar 30 17:18:42 2007 -0600 @@ -50,7 +50,7 @@ acm_set_policy(XEN_GUEST_HANDLE(void) bu printk("%s: Error copying!\n",__func__); goto error_free; } - ret = do_acm_set_policy(policy_buffer, buf_size); + ret = do_acm_set_policy(policy_buffer, buf_size, 0); error_free: xfree(policy_buffer); @@ -59,9 +59,10 @@ acm_set_policy(XEN_GUEST_HANDLE(void) bu int -do_acm_set_policy(void *buf, u32 buf_size) +do_acm_set_policy(void *buf, u32 buf_size, int is_bootpolicy) { struct acm_policy_buffer *pol = (struct acm_policy_buffer *)buf; + uint32_t offset, length; /* some sanity checking */ if ((be32_to_cpu(pol->magic) != ACM_MAGIC) || (buf_size != be32_to_cpu(pol->len)) || @@ -92,23 +93,34 @@ do_acm_set_policy(void *buf, u32 buf_siz /* get bin_policy lock and rewrite policy (release old one) */ write_lock(&acm_bin_pol_rwlock); + offset = be32_to_cpu(pol->policy_reference_offset); + length = be32_to_cpu(pol->primary_buffer_offset) - offset; + /* set label reference name */ - if (acm_set_policy_reference(buf + be32_to_cpu(pol->policy_reference_offset), - be32_to_cpu(pol->primary_buffer_offset) - - be32_to_cpu(pol->policy_reference_offset))) + if ( (offset + length) > buf_size || + acm_set_policy_reference(buf + offset, length)) goto error_lock_free; /* set primary policy data */ - if (acm_primary_ops->set_binary_policy(buf + be32_to_cpu(pol->primary_buffer_offset), - be32_to_cpu(pol->secondary_buffer_offset) - - be32_to_cpu(pol->primary_buffer_offset))) + offset = be32_to_cpu(pol->primary_buffer_offset); + length = be32_to_cpu(pol->secondary_buffer_offset) - offset; + + if ( (offset + length) > buf_size || + acm_primary_ops->set_binary_policy(buf + offset, length, + is_bootpolicy)) goto error_lock_free; /* set secondary policy data */ - if (acm_secondary_ops->set_binary_policy(buf + be32_to_cpu(pol->secondary_buffer_offset), - be32_to_cpu(pol->len) - - be32_to_cpu(pol->secondary_buffer_offset))) - goto error_lock_free; + offset = be32_to_cpu(pol->secondary_buffer_offset); + length = be32_to_cpu(pol->len) - offset; + if ( (offset + length) > buf_size || + acm_secondary_ops->set_binary_policy(buf + offset, length, + is_bootpolicy)) + goto error_lock_free; + + memcpy(&acm_bin_pol.xml_pol_version, + &pol->xml_pol_version, + sizeof(acm_bin_pol.xml_pol_version)); write_unlock(&acm_bin_pol_rwlock); return ACM_OK; @@ -126,7 +138,7 @@ acm_get_policy(XEN_GUEST_HANDLE(void) bu u8 *policy_buffer; int ret; struct acm_policy_buffer *bin_pol; - + if (buf_size < sizeof(struct acm_policy_buffer)) return -EFAULT; @@ -145,6 +157,10 @@ acm_get_policy(XEN_GUEST_HANDLE(void) bu bin_pol->primary_buffer_offset = cpu_to_be32(be32_to_cpu(bin_pol->len)); bin_pol->secondary_buffer_offset = cpu_to_be32(be32_to_cpu(bin_pol->len)); + memcpy(&bin_pol->xml_pol_version, + &acm_bin_pol.xml_pol_version, + sizeof(struct acm_policy_version)); + ret = acm_dump_policy_reference(policy_buffer + be32_to_cpu(bin_pol->policy_reference_offset), buf_size - be32_to_cpu(bin_pol->policy_reference_offset)); if (ret < 0) diff -r e7da2fcb7a22 -r fc9e2f7920c9 xen/acm/acm_simple_type_enforcement_hooks.c --- a/xen/acm/acm_simple_type_enforcement_hooks.c Fri Mar 30 10:27:15 2007 -0600 +++ b/xen/acm/acm_simple_type_enforcement_hooks.c Fri Mar 30 17:18:42 2007 -0600 @@ -31,6 +31,9 @@ #include <acm/acm_hooks.h> #include <asm/atomic.h> #include <acm/acm_endian.h> +#include <acm/acm_core.h> + +ssidref_t dom0_ste_ssidref = 0x0001; /* local cache structures for STE policy */ struct ste_binary_policy ste_bin_pol; @@ -74,15 +77,21 @@ int acm_init_ste_policy(void) { /* minimal startup policy; policy write-locked already */ ste_bin_pol.max_types = 1; - ste_bin_pol.max_ssidrefs = 2; - ste_bin_pol.ssidrefs = (domaintype_t *)xmalloc_array(domaintype_t, 2); - memset(ste_bin_pol.ssidrefs, 0, 2); + ste_bin_pol.max_ssidrefs = 1 + dom0_ste_ssidref; + ste_bin_pol.ssidrefs = + (domaintype_t *)xmalloc_array(domaintype_t, + ste_bin_pol.max_types * + ste_bin_pol.max_ssidrefs); if (ste_bin_pol.ssidrefs == NULL) return ACM_INIT_SSID_ERROR; - /* initialize state so that dom0 can start up and communicate with itself */ - ste_bin_pol.ssidrefs[1] = 1; + memset(ste_bin_pol.ssidrefs, 0, sizeof(domaintype_t) * + ste_bin_pol.max_types * + ste_bin_pol.max_ssidrefs); + + /* initialize state so that dom0 can start up and communicate with itself */ + ste_bin_pol.ssidrefs[ste_bin_pol.max_types * dom0_ste_ssidref] = 1; /* init stats */ atomic_set(&(ste_bin_pol.ec_eval_count), 0); @@ -274,7 +283,7 @@ ste_init_state(struct acm_ste_policy_buf /* set new policy; policy write-locked already */ static int -ste_set_policy(u8 *buf, u32 buf_size) +ste_set_policy(u8 *buf, u32 buf_size, int is_bootpolicy) { struct acm_ste_policy_buffer *ste_buf = (struct acm_ste_policy_buffer *)buf; void *ssidrefsbuf; @@ -304,6 +313,11 @@ ste_set_policy(u8 *buf, u32 buf_size) } if (ste_buf->ste_ssid_offset + sizeof(domaintype_t) * ste_buf->ste_max_ssidrefs*ste_buf->ste_max_types > buf_size) goto error_free; + + /* during boot dom0_chwall_ssidref is set */ + if (is_bootpolicy && (dom0_ste_ssidref >= ste_buf->ste_max_ssidrefs)) { + goto error_free; + } arrcpy(ssidrefsbuf, buf + ste_buf->ste_ssid_offset, diff -r e7da2fcb7a22 -r fc9e2f7920c9 xen/arch/ia64/asm-offsets.c --- a/xen/arch/ia64/asm-offsets.c Fri Mar 30 10:27:15 2007 -0600 +++ b/xen/arch/ia64/asm-offsets.c Fri Mar 30 17:18:42 2007 -0600 @@ -223,10 +223,11 @@ void foo(void) #ifdef PERF_COUNTERS BLANK(); - DEFINE(RECOVER_TO_PAGE_FAULT_PERFC_OFS, offsetof (struct perfcounter, recover_to_page_fault)); - DEFINE(RECOVER_TO_BREAK_FAULT_PERFC_OFS, offsetof (struct perfcounter, recover_to_break_fault)); - DEFINE(FAST_HYPERPRIVOP_PERFC_OFS, offsetof (struct perfcounter, fast_hyperprivop)); - DEFINE(FAST_REFLECT_PERFC_OFS, offsetof (struct perfcounter, fast_reflect)); + DEFINE(IA64_PERFC_recover_to_page_fault, PERFC_recover_to_page_fault); + DEFINE(IA64_PERFC_recover_to_break_fault, PERFC_recover_to_break_fault); + DEFINE(IA64_PERFC_fast_vhpt_translate, PERFC_fast_vhpt_translate); + DEFINE(IA64_PERFC_fast_hyperprivop, PERFC_fast_hyperprivop); + DEFINE(IA64_PERFC_fast_reflect, PERFC_fast_reflect); #endif BLANK(); diff -r e7da2fcb7a22 -r fc9e2f7920c9 xen/arch/ia64/linux-xen/irq_ia64.c --- a/xen/arch/ia64/linux-xen/irq_ia64.c Fri Mar 30 10:27:15 2007 -0600 +++ b/xen/arch/ia64/linux-xen/irq_ia64.c Fri Mar 30 17:18:42 2007 -0600 @@ -113,7 +113,7 @@ ia64_handle_irq (ia64_vector vector, str unsigned long saved_tpr; #ifdef XEN - perfc_incrc(irqs); + perfc_incr(irqs); #endif #if IRQ_DEBUG #ifdef XEN diff -r e7da2fcb7a22 -r fc9e2f7920c9 xen/arch/ia64/linux-xen/mca.c --- a/xen/arch/ia64/linux-xen/mca.c Fri Mar 30 10:27:15 2007 -0600 +++ b/xen/arch/ia64/linux-xen/mca.c Fri Mar 30 17:18:42 2007 -0600 @@ -396,16 +396,6 @@ ia64_log_queue(int sal_info_type, int vi #ifdef CONFIG_ACPI #ifdef XEN -/** - * Copy from linux/include/asm-generic/bug.h - */ -#define WARN_ON(condition) do { \ - if (unlikely((condition)!=0)) { \ - printk("Badness in %s at %s:%d\n", __FUNCTION__, __FILE__, __LINE__); \ - dump_stack(); \ - } \ -} while (0) - /** * Copy from linux/kernel/irq/manage.c * diff -r e7da2fcb7a22 -r fc9e2f7920c9 xen/arch/ia64/linux-xen/smp.c --- a/xen/arch/ia64/linux-xen/smp.c Fri Mar 30 10:27:15 2007 -0600 +++ b/xen/arch/ia64/linux-xen/smp.c Fri Mar 30 17:18:42 2007 -0600 @@ -148,7 +148,7 @@ handle_IPI (int irq, void *dev_id, struc unsigned long ops; #ifdef XEN - perfc_incrc(ipis); + perfc_incr(ipis); #endif mb(); /* Order interrupt and bit testing. */ while ((ops = xchg(pending_ipis, 0)) != 0) { diff -r e7da2fcb7a22 -r fc9e2f7920c9 xen/arch/ia64/vmx/pal_emul.c --- a/xen/arch/ia64/vmx/pal_emul.c Fri Mar 30 10:27:15 2007 -0600 +++ b/xen/arch/ia64/vmx/pal_emul.c Fri Mar 30 17:18:42 2007 -0600 @@ -37,7 +37,7 @@ pal_emul(struct vcpu *vcpu) vcpu_get_gr_nat(vcpu, 30, &gr30); vcpu_get_gr_nat(vcpu, 31, &gr31); - perfc_incrc(vmx_pal_emul); + perfc_incr(vmx_pal_emul); result = xen_pal_emulator(gr28, gr29, gr30, gr31); vcpu_set_gr(vcpu, 8, result.status, 0); diff -r e7da2fcb7a22 -r fc9e2f7920c9 xen/arch/ia64/vmx/vlsapic.c --- a/xen/arch/ia64/vmx/vlsapic.c Fri Mar 30 10:27:15 2007 -0600 +++ b/xen/arch/ia64/vmx/vlsapic.c Fri Mar 30 17:18:42 2007 -0600 @@ -692,8 +692,8 @@ static void vlsapic_write_ipi(VCPU *vcpu if (targ == NULL) panic_domain(NULL, "Unknown IPI cpu\n"); - if (!test_bit(_VCPUF_initialised, &targ->vcpu_flags) || - test_bit(_VCPUF_down, &targ->vcpu_flags)) { + if (!targ->is_initialised || + test_bit(_VPF_down, &targ->pause_flags)) { struct pt_regs *targ_regs = vcpu_regs(targ); struct vcpu_guest_context c; @@ -709,7 +709,7 @@ static void vlsapic_write_ipi(VCPU *vcpu targ_regs->cr_iip = d->arch.sal_data->boot_rdv_ip; targ_regs->r1 = d->arch.sal_data->boot_rdv_r1; - if (test_and_clear_bit(_VCPUF_down,&targ->vcpu_flags)) { + if (test_and_clear_bit(_VPF_down,&targ->pause_flags)) { vcpu_wake(targ); printk(XENLOG_DEBUG "arch_boot_vcpu: vcpu %d awaken %016lx!\n", targ->vcpu_id, targ_regs->cr_iip); @@ -717,7 +717,7 @@ static void vlsapic_write_ipi(VCPU *vcpu printk("arch_boot_vcpu: huh, already awake!"); } } else { - int running = test_bit(_VCPUF_running, &targ->vcpu_flags); + int running = targ->is_running; vlsapic_deliver_ipi(targ, ((ipi_d_t)value).dm, ((ipi_d_t)value).vector); vcpu_unblock(targ); diff -r e7da2fcb7a22 -r fc9e2f7920c9 xen/arch/ia64/vmx/vmmu.c --- a/xen/arch/ia64/vmx/vmmu.c Fri Mar 30 10:27:15 2007 -0600 +++ b/xen/arch/ia64/vmx/vmmu.c Fri Mar 30 17:18:42 2007 -0600 @@ -598,7 +598,7 @@ IA64FAULT vmx_vcpu_ptc_ga(VCPU *vcpu, u6 vcpu_get_rr(vcpu, va, &args.rid); args.ps = ps; for_each_vcpu (d, v) { - if (!test_bit(_VCPUF_initialised, &v->vcpu_flags)) + if (!v->is_initialised) continue; args.vcpu = v; diff -r e7da2fcb7a22 -r fc9e2f7920c9 xen/arch/ia64/vmx/vmx_process.c --- a/xen/arch/ia64/vmx/vmx_process.c Fri Mar 30 10:27:15 2007 -0600 +++ b/xen/arch/ia64/vmx/vmx_process.c Fri Mar 30 17:18:42 2007 -0600 @@ -151,7 +151,7 @@ vmx_ia64_handle_break (unsigned long ifa struct domain *d = current->domain; struct vcpu *v = current; - perfc_incrc(vmx_ia64_handle_break); + perfc_incr(vmx_ia64_handle_break); #ifdef CRASH_DEBUG if ((iim == 0 || iim == CDB_BREAK_NUM) && !user_mode(regs) && IS_VMM_ADDRESS(regs->cr_iip)) { diff -r e7da2fcb7a22 -r fc9e2f7920c9 xen/arch/ia64/vmx/vmx_support.c --- a/xen/arch/ia64/vmx/vmx_support.c Fri Mar 30 10:27:15 2007 -0600 +++ b/xen/arch/ia64/vmx/vmx_support.c Fri Mar 30 17:18:42 2007 -0600 @@ -82,12 +82,12 @@ void vmx_send_assist_req(struct vcpu *v) p->state != STATE_IOREQ_INPROCESS) break; - set_bit(_VCPUF_blocked_in_xen, ¤t->vcpu_flags); + set_bit(_VPF_blocked_in_xen, ¤t->pause_flags); mb(); /* set blocked status /then/ re-evaluate condition */ if (p->state != STATE_IOREQ_READY && p->state != STATE_IOREQ_INPROCESS) { - clear_bit(_VCPUF_blocked_in_xen, ¤t->vcpu_flags); + clear_bit(_VPF_blocked_in_xen, ¤t->pause_flags); break; } diff -r e7da2fcb7a22 -r fc9e2f7920c9 xen/arch/ia64/vmx/vmx_virt.c --- a/xen/arch/ia64/vmx/vmx_virt.c Fri Mar 30 10:27:15 2007 -0600 +++ b/xen/arch/ia64/vmx/vmx_virt.c Fri Mar 30 17:18:42 2007 -0600 @@ -1401,159 +1401,159 @@ if ( (cause == 0xff && opcode == 0x1e000 switch(cause) { case EVENT_RSM: - perfc_incrc(vmx_rsm); + perfc_incr(vmx_rsm); status=vmx_emul_rsm(vcpu, inst); break; case EVENT_SSM: - perfc_incrc(vmx_ssm); + perfc_incr(vmx_ssm); status=vmx_emul_ssm(vcpu, inst); break; case EVENT_MOV_TO_PSR: - perfc_incrc(vmx_mov_to_psr); + perfc_incr(vmx_mov_to_psr); status=vmx_emul_mov_to_psr(vcpu, inst); break; case EVENT_MOV_FROM_PSR: - perfc_incrc(vmx_mov_from_psr); + perfc_incr(vmx_mov_from_psr); status=vmx_emul_mov_from_psr(vcpu, inst); break; case EVENT_MOV_FROM_CR: - perfc_incrc(vmx_mov_from_cr); + perfc_incr(vmx_mov_from_cr); status=vmx_emul_mov_from_cr(vcpu, inst); break; case EVENT_MOV_TO_CR: - perfc_incrc(vmx_mov_to_cr); + perfc_incr(vmx_mov_to_cr); status=vmx_emul_mov_to_cr(vcpu, inst); break; case EVENT_BSW_0: - perfc_incrc(vmx_bsw0); + perfc_incr(vmx_bsw0); status=vmx_emul_bsw0(vcpu, inst); break; case EVENT_BSW_1: - perfc_incrc(vmx_bsw1); + perfc_incr(vmx_bsw1); status=vmx_emul_bsw1(vcpu, inst); break; case EVENT_COVER: - perfc_incrc(vmx_cover); + perfc_incr(vmx_cover); status=vmx_emul_cover(vcpu, inst); break; case EVENT_RFI: - perfc_incrc(vmx_rfi); + perfc_incr(vmx_rfi); status=vmx_emul_rfi(vcpu, inst); break; case EVENT_ITR_D: - perfc_incrc(vmx_itr_d); + perfc_incr(vmx_itr_d); status=vmx_emul_itr_d(vcpu, inst); break; case EVENT_ITR_I: - perfc_incrc(vmx_itr_i); + perfc_incr(vmx_itr_i); status=vmx_emul_itr_i(vcpu, inst); break; case EVENT_PTR_D: - perfc_incrc(vmx_ptr_d); + perfc_incr(vmx_ptr_d); status=vmx_emul_ptr_d(vcpu, inst); break; case EVENT_PTR_I: - perfc_incrc(vmx_ptr_i); + perfc_incr(vmx_ptr_i); status=vmx_emul_ptr_i(vcpu, inst); break; case EVENT_ITC_D: - perfc_incrc(vmx_itc_d); + perfc_incr(vmx_itc_d); status=vmx_emul_itc_d(vcpu, inst); break; case EVENT_ITC_I: - perfc_incrc(vmx_itc_i); + perfc_incr(vmx_itc_i); status=vmx_emul_itc_i(vcpu, inst); break; case EVENT_PTC_L: - perfc_incrc(vmx_ptc_l); + perfc_incr(vmx_ptc_l); status=vmx_emul_ptc_l(vcpu, inst); break; case EVENT_PTC_G: - perfc_incrc(vmx_ptc_g); + perfc_incr(vmx_ptc_g); status=vmx_emul_ptc_g(vcpu, inst); break; case EVENT_PTC_GA: - perfc_incrc(vmx_ptc_ga); + perfc_incr(vmx_ptc_ga); status=vmx_emul_ptc_ga(vcpu, inst); break; case EVENT_PTC_E: - perfc_incrc(vmx_ptc_e); + perfc_incr(vmx_ptc_e); status=vmx_emul_ptc_e(vcpu, inst); break; case EVENT_MOV_TO_RR: - perfc_incrc(vmx_mov_to_rr); + perfc_incr(vmx_mov_to_rr); status=vmx_emul_mov_to_rr(vcpu, inst); break; case EVENT_MOV_FROM_RR: - perfc_incrc(vmx_mov_from_rr); + perfc_incr(vmx_mov_from_rr); status=vmx_emul_mov_from_rr(vcpu, inst); break; case EVENT_THASH: - perfc_incrc(vmx_thash); + perfc_incr(vmx_thash); status=vmx_emul_thash(vcpu, inst); break; case EVENT_TTAG: - perfc_incrc(vmx_ttag); + perfc_incr(vmx_ttag); status=vmx_emul_ttag(vcpu, inst); break; case EVENT_TPA: - perfc_incrc(vmx_tpa); + perfc_incr(vmx_tpa); status=vmx_emul_tpa(vcpu, inst); break; case EVENT_TAK: - perfc_incrc(vmx_tak); + perfc_incr(vmx_tak); status=vmx_emul_tak(vcpu, inst); break; case EVENT_MOV_TO_AR_IMM: - perfc_incrc(vmx_mov_to_ar_imm); + perfc_incr(vmx_mov_to_ar_imm); status=vmx_emul_mov_to_ar_imm(vcpu, inst); break; case EVENT_MOV_TO_AR: - perfc_incrc(vmx_mov_to_ar_reg); + perfc_incr(vmx_mov_to_ar_reg); status=vmx_emul_mov_to_ar_reg(vcpu, inst); break; case EVENT_MOV_FROM_AR: - perfc_incrc(vmx_mov_from_ar_reg); + perfc_incr(vmx_mov_from_ar_reg); status=vmx_emul_mov_from_ar_reg(vcpu, inst); break; case EVENT_MOV_TO_DBR: - perfc_incrc(vmx_mov_to_dbr); + perfc_incr(vmx_mov_to_dbr); status=vmx_emul_mov_to_dbr(vcpu, inst); break; case EVENT_MOV_TO_IBR: - perfc_incrc(vmx_mov_to_ibr); + perfc_incr(vmx_mov_to_ibr); status=vmx_emul_mov_to_ibr(vcpu, inst); break; case EVENT_MOV_TO_PMC: - perfc_incrc(vmx_mov_to_pmc); + perfc_incr(vmx_mov_to_pmc); status=vmx_emul_mov_to_pmc(vcpu, inst); break; case EVENT_MOV_TO_PMD: - perfc_incrc(vmx_mov_to_pmd); + perfc_incr(vmx_mov_to_pmd); status=vmx_emul_mov_to_pmd(vcpu, inst); break; case EVENT_MOV_TO_PKR: - perfc_incrc(vmx_mov_to_pkr); + perfc_incr(vmx_mov_to_pkr); status=vmx_emul_mov_to_pkr(vcpu, inst); break; case EVENT_MOV_FROM_DBR: - perfc_incrc(vmx_mov_from_dbr); + perfc_incr(vmx_mov_from_dbr); status=vmx_emul_mov_from_dbr(vcpu, inst); break; case EVENT_MOV_FROM_IBR: - perfc_incrc(vmx_mov_from_ibr); + perfc_incr(vmx_mov_from_ibr); status=vmx_emul_mov_from_ibr(vcpu, inst); break; case EVENT_MOV_FROM_PMC: - perfc_incrc(vmx_mov_from_pmc); + perfc_incr(vmx_mov_from_pmc); status=vmx_emul_mov_from_pmc(vcpu, inst); break; case EVENT_MOV_FROM_PKR: - perfc_incrc(vmx_mov_from_pkr); + perfc_incr(vmx_mov_from_pkr); status=vmx_emul_mov_from_pkr(vcpu, inst); break; case EVENT_MOV_FROM_CPUID: - perfc_incrc(vmx_mov_from_cpuid); + perfc_incr(vmx_mov_from_cpuid); status=vmx_emul_mov_from_cpuid(vcpu, inst); break; case EVENT_VMSW: diff -r e7da2fcb7a22 -r fc9e2f7920c9 xen/arch/ia64/xen/dom0_ops.c --- a/xen/arch/ia64/xen/dom0_ops.c Fri Mar 30 10:27:15 2007 -0600 +++ b/xen/arch/ia64/xen/dom0_ops.c Fri Mar 30 17:18:42 2007 -0600 @@ -372,7 +372,7 @@ do_dom0vp_op(unsigned long cmd, } else { ret = (ret & _PFN_MASK) >> PAGE_SHIFT;//XXX pte_pfn() } - perfc_incrc(dom0vp_phystomach); + perfc_incr(dom0vp_phystomach); break; case IA64_DOM0VP_machtophys: if (!mfn_valid(arg0)) { @@ -380,7 +380,7 @@ do_dom0vp_op(unsigned long cmd, break; } ret = get_gpfn_from_mfn(arg0); - perfc_incrc(dom0vp_machtophys); + perfc_incr(dom0vp_machtophys); break; case IA64_DOM0VP_zap_physmap: ret = dom0vp_zap_physmap(d, arg0, (unsigned int)arg1); diff -r e7da2fcb7a22 -r fc9e2f7920c9 xen/arch/ia64/xen/domain.c --- a/xen/arch/ia64/xen/domain.c Fri Mar 30 10:27:15 2007 -0600 +++ b/xen/arch/ia64/xen/domain.c Fri Mar 30 17:18:42 2007 -0600 @@ -131,11 +131,11 @@ static void flush_vtlb_for_context_switc if (vhpt_is_flushed || NEED_FLUSH(__get_cpu_var(tlbflush_time), last_tlbflush_timestamp)) { local_flush_tlb_all(); - perfc_incrc(tlbflush_clock_cswitch_purge); + perfc_incr(tlbflush_clock_cswitch_purge); } else { - perfc_incrc(tlbflush_clock_cswitch_skip); - } - perfc_incrc(flush_vtlb_for_context_switch); + perfc_incr(tlbflush_clock_cswitch_skip); + } + perfc_incr(flush_vtlb_for_context_switch); } } @@ -658,7 +658,7 @@ int arch_set_info_guest(struct vcpu *v, v->arch.iva = er->iva; } - if (test_bit(_VCPUF_initialised, &v->vcpu_flags)) + if (v->is_initialised) return 0; if (d->arch.is_vti) { @@ -677,10 +677,12 @@ int arch_set_info_guest(struct vcpu *v, /* This overrides some registers. */ vcpu_init_regs(v); - /* Don't redo final setup. Auto-online VCPU0. */ - if (!test_and_set_bit(_VCPUF_initialised, &v->vcpu_flags) && - (v->vcpu_id == 0)) - clear_bit(_VCPUF_down, &v->vcpu_flags); + if (!v->is_initialised) { + v->is_initialised = 1; + /* Auto-online VCPU0 when it is initialised. */ + if (v->vcpu_id == 0) + clear_bit(_VPF_down, &v->pause_flags); + } return 0; } @@ -1068,7 +1070,7 @@ int construct_dom0(struct domain *d, /* Sanity! */ BUG_ON(d != dom0); BUG_ON(d->vcpu[0] == NULL); - BUG_ON(test_bit(_VCPUF_initialised, &v->vcpu_flags)); + BUG_ON(v->is_initialised); printk("*** LOADING DOMAIN 0 ***\n"); @@ -1189,8 +1191,8 @@ int construct_dom0(struct domain *d, printk("Dom0: 0x%lx\n", (u64)dom0); - set_bit(_VCPUF_initialised, &v->vcpu_flags); - clear_bit(_VCPUF_down, &v->vcpu_flags); + v->is_initialised = 1; + clear_bit(_VPF_down, &v->pause_flags); /* Build firmware. Note: Linux kernel reserve memory used by start_info, so there is diff -r e7da2fcb7a22 -r fc9e2f7920c9 xen/arch/ia64/xen/faults.c --- a/xen/arch/ia64/xen/faults.c Fri Mar 30 10:27:15 2007 -0600 +++ b/xen/arch/ia64/xen/faults.c Fri Mar 30 17:18:42 2007 -0600 @@ -187,7 +187,7 @@ static int handle_lazy_cover(struct vcpu if (!PSCB(v, interrupt_collection_enabled)) { PSCB(v, ifs) = regs->cr_ifs; regs->cr_ifs = 0; - perfc_incrc(lazy_cover); + perfc_incr(lazy_cover); return 1; // retry same instruction with cr.ifs off } return 0; diff -r e7da2fcb7a22 -r fc9e2f7920c9 xen/arch/ia64/xen/fw_emul.c --- a/xen/arch/ia64/xen/fw_emul.c Fri Mar 30 10:27:15 2007 -0600 +++ b/xen/arch/ia64/xen/fw_emul.c Fri Mar 30 17:18:42 2007 -0600 @@ -374,7 +374,7 @@ sal_emulator (long index, unsigned long printk("*** CALLED SAL_UPDATE_PAL. IGNORED...\n"); break; case SAL_XEN_SAL_RETURN: - if (!test_and_set_bit(_VCPUF_down, ¤t->vcpu_flags)) + if (!test_and_set_bit(_VPF_down, ¤t->pause_flags)) vcpu_sleep_nosync(current); break; case SN_SAL_GET_MASTER_NASID: @@ -725,7 +725,7 @@ xen_pal_emulator(unsigned long index, u6 console_start_sync(); (*efi.reset_system)(EFI_RESET_SHUTDOWN,0,0,NULL); } else { - set_bit(_VCPUF_down, ¤t->vcpu_flags); + set_bit(_VPF_down, ¤t->pause_flags); vcpu_sleep_nosync(current); status = PAL_STATUS_SUCCESS; } diff -r e7da2fcb7a22 -r fc9e2f7920c9 xen/arch/ia64/xen/hypercall.c --- a/xen/arch/ia64/xen/hypercall.c Fri Mar 30 10:27:15 2007 -0600 +++ b/xen/arch/ia64/xen/hypercall.c Fri Mar 30 17:18:42 2007 -0600 @@ -81,11 +81,11 @@ fw_hypercall_ipi (struct pt_regs *regs) return; if (vector == XEN_SAL_BOOT_RENDEZ_VEC - && (!test_bit(_VCPUF_initialised, &targ->vcpu_flags) - || test_bit(_VCPUF_down, &targ->vcpu_flags))) { + && (!targ->is_initialised + || test_bit(_VPF_down, &targ->pause_flags))) { /* First start: initialize vpcu. */ - if (!test_bit(_VCPUF_initialised, &targ->vcpu_flags)) { + if (!targ->is_initialised) { struct vcpu_guest_context c; memset (&c, 0, sizeof (c)); @@ -102,8 +102,8 @@ fw_hypercall_ipi (struct pt_regs *regs) vcpu_regs (targ)->r1 = d->arch.sal_data->boot_rdv_r1; vcpu_regs (targ)->b0 = FW_HYPERCALL_SAL_RETURN_PADDR; - if (test_and_clear_bit(_VCPUF_down, - &targ->vcpu_flags)) { + if (test_and_clear_bit(_VPF_down, + &targ->pause_flags)) { vcpu_wake(targ); printk(XENLOG_INFO "arch_boot_vcpu: vcpu %d awaken\n", targ->vcpu_id); @@ -112,9 +112,7 @@ fw_hypercall_ipi (struct pt_regs *regs) printk ("arch_boot_vcpu: huu, already awaken!\n"); } else { - int running = test_bit(_VCPUF_running, - &targ->vcpu_flags); - + int running = targ->is_running; vcpu_pend_interrupt(targ, vector); vcpu_unblock(targ); if (running) @@ -161,7 +159,7 @@ ia64_hypercall(struct pt_regs *regs) if (regs->r28 == PAL_HALT_LIGHT) { if (vcpu_deliverable_interrupts(v) || event_pending(v)) { - perfc_incrc(idle_when_pending); + perfc_incr(idle_when_pending); vcpu_pend_unspecified_interrupt(v); //printk("idle w/int#%d pending!\n",pi); //this shouldn't happen, but it apparently does quite a bit! so don't @@ -170,7 +168,7 @@ ia64_hypercall(struct pt_regs *regs) //as deliver_pending_interrupt is called on the way out and will deliver it } else { - perfc_incrc(pal_halt_light); + perfc_incr(pal_halt_light); migrate_timer(&v->arch.hlt_timer, v->processor); set_timer(&v->arch.hlt_timer, @@ -209,7 +207,7 @@ ia64_hypercall(struct pt_regs *regs) regs->r10 = x.r10; regs->r11 = x.r11; break; case FW_HYPERCALL_SAL_RETURN: - if ( !test_and_set_bit(_VCPUF_down, &v->vcpu_flags) ) + if ( !test_and_set_bit(_VPF_down, &v->pause_flags) ) vcpu_sleep_nosync(v); break; case FW_HYPERCALL_EFI_CALL: diff -r e7da2fcb7a22 -r fc9e2f7920c9 xen/arch/ia64/xen/hyperprivop.S --- a/xen/arch/ia64/xen/hyperprivop.S Fri Mar 30 10:27:15 2007 -0600 +++ b/xen/arch/ia64/xen/hyperprivop.S Fri Mar 30 17:18:42 2007 -0600 @@ -26,8 +26,7 @@ # define FAST_HYPERPRIVOPS # ifdef PERF_COUNTERS # define FAST_HYPERPRIVOP_CNT -# define FAST_HYPERPRIVOP_PERFC(N) \ - (perfcounters + FAST_HYPERPRIVOP_PERFC_OFS + (4 * N)) +# define FAST_HYPERPRIVOP_PERFC(N) PERFC(fast_hyperprivop + N) # define FAST_REFLECT_CNT # endif @@ -364,7 +363,7 @@ GLOBAL_ENTRY(fast_tick_reflect) mov rp=r29;; mov cr.itm=r26;; // ensure next tick #ifdef FAST_REFLECT_CNT - movl r20=perfcounters+FAST_REFLECT_PERFC_OFS+((0x3000>>8)*4);; + movl r20=PERFC(fast_reflect + (0x3000>>8));; ld4 r21=[r20];; adds r21=1,r21;; st4 [r20]=r21;; @@ -597,7 +596,7 @@ END(fast_break_reflect) // r31 == pr ENTRY(fast_reflect) #ifdef FAST_REFLECT_CNT - movl r22=perfcounters+FAST_REFLECT_PERFC_OFS; + movl r22=PERFC(fast_reflect); shr r23=r20,8-2;; add r22=r22,r23;; ld4 r21=[r22];; @@ -938,7 +937,7 @@ 1: // check the guest VHPT (p7) br.cond.spnt.few page_not_present;; #ifdef FAST_REFLECT_CNT - movl r21=perfcounter+FAST_VHPT_TRANSLATE_PERFC_OFS;; + movl r21=PERFC(fast_vhpt_translate);; ld4 r22=[r21];; adds r22=1,r22;; st4 [r21]=r22;; @@ -968,7 +967,7 @@ END(fast_tlb_miss_reflect) // we get here if fast_insert fails (e.g. due to metaphysical lookup) ENTRY(recover_and_page_fault) #ifdef PERF_COUNTERS - movl r21=perfcounters + RECOVER_TO_PAGE_FAULT_PERFC_OFS;; + movl r21=PERFC(recover_to_page_fault);; ld4 r22=[r21];; adds r22=1,r22;; st4 [r21]=r22;; @@ -1832,7 +1831,7 @@ END(hyper_ptc_ga) // recovery block for hyper_itc metaphysical memory lookup ENTRY(recover_and_dispatch_break_fault) #ifdef PERF_COUNTERS - movl r21=perfcounters + RECOVER_TO_BREAK_FAULT_PERFC_OFS;; + movl r21=PERFC(recover_to_break_fault);; ld4 r22=[r21];; adds r22=1,r22;; st4 [r21]=r22;; diff -r e7da2fcb7a22 -r fc9e2f7920c9 xen/arch/ia64/xen/mm.c --- a/xen/arch/ia64/xen/mm.c Fri Mar 30 10:27:15 2007 -0600 +++ b/xen/arch/ia64/xen/mm.c Fri Mar 30 17:18:42 2007 -0600 @@ -400,7 +400,7 @@ share_xen_page_with_guest(struct page_in ASSERT(page->count_info == 0); /* Only add to the allocation list if the domain isn't dying. */ - if ( !test_bit(_DOMF_dying, &d->domain_flags) ) + if ( !d->is_dying ) { page->count_info |= PGC_allocated | 1; if ( unlikely(d->xenheap_pages++ == 0) ) @@ -1131,7 +1131,7 @@ assign_domain_page_replace(struct domain domain_put_page(d, mpaddr, pte, old_pte, 1); } } - perfc_incrc(assign_domain_page_replace); + perfc_incr(assign_domain_page_replace); } // caller must get_page(new_page) before @@ -1207,7 +1207,7 @@ assign_domain_page_cmpxchg_rel(struct do } domain_page_flush_and_put(d, mpaddr, pte, old_pte, old_page); - perfc_incrc(assign_domain_pge_cmpxchg_rel); + perfc_incr(assign_domain_pge_cmpxchg_rel); return 0; } @@ -1266,7 +1266,7 @@ zap_domain_page_one(struct domain *d, un BUG_ON(clear_PGC_allocate && (page_get_owner(page) == NULL)); domain_put_page(d, mpaddr, pte, old_pte, clear_PGC_allocate); - perfc_incrc(zap_dcomain_page_one); + perfc_incr(zap_dcomain_page_one); } unsigned long @@ -1279,7 +1279,7 @@ dom0vp_zap_physmap(struct domain *d, uns } zap_domain_page_one(d, gpfn << PAGE_SHIFT, 1, INVALID_MFN); - perfc_incrc(dom0vp_zap_physmap); + perfc_incr(dom0vp_zap_physmap); return 0; } @@ -1333,7 +1333,7 @@ __dom0vp_add_physmap(struct domain* d, u get_gpfn_from_mfn(mfn) != INVALID_M2P_ENTRY); assign_domain_page_replace(d, gpfn << PAGE_SHIFT, mfn, flags); //don't update p2m table because this page belongs to rd, not d. - perfc_incrc(dom0vp_add_physmap); + perfc_incr(dom0vp_add_physmap); out1: put_domain(rd); return error; @@ -1503,7 +1503,7 @@ create_grant_host_mapping(unsigned long #endif ((flags & GNTMAP_readonly) ? ASSIGN_readonly : ASSIGN_writable)); - perfc_incrc(create_grant_host_mapping); + perfc_incr(create_grant_host_mapping); return GNTST_okay; } @@ -1568,7 +1568,7 @@ destroy_grant_host_mapping(unsigned long BUG_ON(pte_pgc_allocated(old_pte)); domain_page_flush_and_put(d, gpaddr, pte, old_pte, page); - perfc_incrc(destroy_grant_host_mapping); + perfc_incr(destroy_grant_host_mapping); return GNTST_okay; } @@ -1629,7 +1629,7 @@ steal_page(struct domain *d, struct page free_domheap_page(new); return -1; } - perfc_incrc(steal_page_refcount); + perfc_incr(steal_page_refcount); } spin_lock(&d->page_alloc_lock); @@ -1693,7 +1693,7 @@ steal_page(struct domain *d, struct page list_del(&page->list); spin_unlock(&d->page_alloc_lock); - perfc_incrc(steal_page); + perfc_incr(steal_page); return 0; } @@ -1710,7 +1710,7 @@ guest_physmap_add_page(struct domain *d, //BUG_ON(mfn != ((lookup_domain_mpa(d, gpfn << PAGE_SHIFT) & _PFN_MASK) >> PAGE_SHIFT)); - perfc_incrc(guest_physmap_add_page); + perfc_incr(guest_physmap_add_page); } void @@ -1719,7 +1719,7 @@ guest_physmap_remove_page(struct domain { BUG_ON(mfn == 0);//XXX zap_domain_page_one(d, gpfn << PAGE_SHIFT, 0, mfn); - perfc_incrc(guest_physmap_remove_page); + perfc_incr(guest_physmap_remove_page); } static void @@ -1799,7 +1799,7 @@ domain_page_flush_and_put(struct domain* break; } #endif - perfc_incrc(domain_page_flush_and_put); + perfc_incr(domain_page_flush_and_put); } int @@ -1935,8 +1935,7 @@ void put_page_type(struct page_info *pag * page-table pages if we detect a referential loop. * See domain.c:relinquish_list(). */ - ASSERT((x & PGT_validated) || - test_bit(_DOMF_dying, &page_get_owner(page)->domain_flags)); + ASSERT((x & PGT_validated) || page_get_owner(page)->is_dying); if ( unlikely((nx & PGT_count_mask) == 0) ) { @@ -1996,7 +1995,7 @@ int get_page_type(struct page_info *page if ( unlikely(!cpus_empty(mask)) ) { - perfc_incrc(need_flush_tlb_flush); + perfc_incr(need_flush_tlb_flush); flush_tlb_mask(mask); } diff -r e7da2fcb7a22 -r fc9e2f7920c9 xen/arch/ia64/xen/privop.c --- a/xen/arch/ia64/xen/privop.c Fri Mar 30 10:27:15 2007 -0600 +++ b/xen/arch/ia64/xen/privop.c Fri Mar 30 17:18:42 2007 -0600 @@ -641,15 +641,15 @@ static IA64FAULT priv_handle_op(VCPU * v if (inst.M29.x3 != 0) break; if (inst.M30.x4 == 8 && inst.M30.x2 == 2) { - perfc_incrc(mov_to_ar_imm); + perfc_incr(mov_to_ar_imm); return priv_mov_to_ar_imm(vcpu, inst); } if (inst.M44.x4 == 6) { - perfc_incrc(ssm); + perfc_incr(ssm); return priv_ssm(vcpu, inst); } if (inst.M44.x4 == 7) { - perfc_incrc(rsm); + perfc_incr(rsm); return priv_rsm(vcpu, inst); } break; @@ -658,9 +658,9 @@ static IA64FAULT priv_handle_op(VCPU * v x6 = inst.M29.x6; if (x6 == 0x2a) { if (privify_en && inst.M29.r2 > 63 && inst.M29.ar3 < 8) - perfc_incrc(mov_from_ar); // privified mov from kr + perfc_incr(mov_from_ar); // privified mov from kr else - perfc_incrc(mov_to_ar_reg); + perfc_incr(mov_to_ar_reg); return priv_mov_to_ar_reg(vcpu, inst); } if (inst.M29.x3 != 0) @@ -676,9 +676,9 @@ static IA64FAULT priv_handle_op(VCPU * v } } if (privify_en && x6 == 52 && inst.M28.r3 > 63) - perfc_incrc(fc); + perfc_incr(fc); else if (privify_en && x6 == 16 && inst.M43.r3 > 63) - perfc_incrc(cpuid); + perfc_incr(cpuid); else perfc_incra(misc_privop, x6); return (*pfunc) (vcpu, inst); @@ -688,23 +688,23 @@ static IA64FAULT priv_handle_op(VCPU * v break; if (inst.B8.x6 == 0x08) { IA64FAULT fault; - perfc_incrc(rfi); + perfc_incr(rfi); fault = priv_rfi(vcpu, inst); if (fault == IA64_NO_FAULT) fault = IA64_RFI_IN_PROGRESS; return fault; } if (inst.B8.x6 == 0x0c) { - perfc_incrc(bsw0); + perfc_incr(bsw0); return priv_bsw0(vcpu, inst); } if (inst.B8.x6 == 0x0d) { - perfc_incrc(bsw1); + perfc_incr(bsw1); return priv_bsw1(vcpu, inst); } if (inst.B8.x6 == 0x0) { // break instr for privified cover - perfc_incrc(cover); + perfc_incr(cover); return priv_cover(vcpu, inst); } break; @@ -713,7 +713,7 @@ static IA64FAULT priv_handle_op(VCPU * v break; #if 0 if (inst.I26.x6 == 0 && inst.I26.x3 == 0) { - perfc_incrc(cover); + perfc_incr(cover); return priv_cover(vcpu, inst); } #endif @@ -721,13 +721,13 @@ static IA64FAULT priv_handle_op(VCPU * v break; // I26.x3 == I27.x3 if (inst.I26.x6 == 0x2a) { if (privify_en && inst.I26.r2 > 63 && inst.I26.ar3 < 8) - perfc_incrc(mov_from_ar); // privified mov from kr + perfc_incr(mov_from_ar); // privified mov from kr else - perfc_incrc(mov_to_ar_reg); + perfc_incr(mov_to_ar_reg); return priv_mov_to_ar_reg(vcpu, inst); } if (inst.I27.x6 == 0x0a) { - perfc_incrc(mov_to_ar_imm); + perfc_incr(mov_to_ar_imm); return priv_mov_to_ar_imm(vcpu, inst); } break; diff -r e7da2fcb7a22 -r fc9e2f7920c9 xen/arch/ia64/xen/privop_stat.c --- a/xen/arch/ia64/xen/privop_stat.c Fri Mar 30 10:27:15 2007 -0600 +++ b/xen/arch/ia64/xen/privop_stat.c Fri Mar 30 17:18:42 2007 -0600 @@ -10,48 +10,39 @@ struct privop_addr_count { unsigned long addr[PRIVOP_COUNT_NADDRS]; unsigned int count[PRIVOP_COUNT_NADDRS]; unsigned int overflow; - atomic_t *perfc_addr; - atomic_t *perfc_count; - atomic_t *perfc_overflow; }; -#undef PERFCOUNTER +struct privop_addr_info { + enum perfcounter perfc_addr; + enum perfcounter perfc_count; + enum perfcounter perfc_overflow; +}; + #define PERFCOUNTER(var, name) - -#undef PERFCOUNTER_CPU -#define PERFCOUNTER_CPU(var, name) - -#undef PERFCOUNTER_ARRAY #define PERFCOUNTER_ARRAY(var, name, size) -#undef PERFSTATUS #define PERFSTATUS(var, name) - -#undef PERFSTATUS_CPU -#define PERFSTATUS_CPU(var, name) - -#undef PERFSTATUS_ARRAY #define PERFSTATUS_ARRAY(var, name, size) -#undef PERFPRIVOPADDR #define PERFPRIVOPADDR(name) \ { \ - { 0 }, { 0 }, 0, \ - perfcounters.privop_addr_##name##_addr, \ - perfcounters.privop_addr_##name##_count, \ - perfcounters.privop_addr_##name##_overflow \ + PERFC_privop_addr_##name##_addr, \ + PERFC_privop_addr_##name##_count, \ + PERFC_privop_addr_##name##_overflow \ }, -static struct privop_addr_count privop_addr_counter[] = { +static const struct privop_addr_info privop_addr_info[] = { #include <asm/perfc_defn.h> }; #define PRIVOP_COUNT_NINSTS \ - (sizeof(privop_addr_counter) / sizeof(privop_addr_counter[0])) + (sizeof(privop_addr_info) / sizeof(privop_addr_info[0])) + +static DEFINE_PER_CPU(struct privop_addr_count[PRIVOP_COUNT_NINSTS], privop_addr_counter); void privop_count_addr(unsigned long iip, enum privop_inst inst) { - struct privop_addr_count *v = &privop_addr_counter[inst]; + struct privop_addr_count *v = this_cpu(privop_addr_counter) + inst; int i; if (inst >= PRIVOP_COUNT_NINSTS) @@ -72,31 +63,44 @@ void privop_count_addr(unsigned long iip void gather_privop_addrs(void) { - int i, j; - atomic_t *v; - for (i = 0; i < PRIVOP_COUNT_NINSTS; i++) { - /* Note: addresses are truncated! */ - v = privop_addr_counter[i].perfc_addr; - for (j = 0; j < PRIVOP_COUNT_NADDRS; j++) - atomic_set(&v[j], privop_addr_counter[i].addr[j]); + unsigned int cpu; - v = privop_addr_counter[i].perfc_count; - for (j = 0; j < PRIVOP_COUNT_NADDRS; j++) - atomic_set(&v[j], privop_addr_counter[i].count[j]); + for_each_cpu ( cpu ) { + perfc_t *perfcounters = per_cpu(perfcounters, cpu); + struct privop_addr_count *s = per_cpu(privop_addr_counter, cpu); + int i, j; + + for (i = 0; i < PRIVOP_COUNT_NINSTS; i++, s++) { + perfc_t *d; + + /* Note: addresses are truncated! */ + d = perfcounters + privop_addr_info[i].perfc_addr; + for (j = 0; j < PRIVOP_COUNT_NADDRS; j++) + d[j] = s->addr[j]; + + d = perfcounters + privop_addr_info[i].perfc_count; + for (j = 0; j < PRIVOP_COUNT_NADDRS; j++) + d[j] = s->count[j]; - atomic_set(privop_addr_counter[i].perfc_overflow, - privop_addr_counter[i].overflow); + perfcounters[privop_addr_info[i].perfc_overflow] = + s->overflow; + } } } void reset_privop_addrs(void) { - int i, j; - for (i = 0; i < PRIVOP_COUNT_NINSTS; i++) { - struct privop_addr_count *v = &privop_addr_counter[i]; - for (j = 0; j < PRIVOP_COUNT_NADDRS; j++) - v->addr[j] = v->count[j] = 0; - v->overflow = 0; + unsigned int cpu; + + for_each_cpu ( cpu ) { + struct privop_addr_count *v = per_cpu(privop_addr_counter, cpu); + int i, j; + + for (i = 0; i < PRIVOP_COUNT_NINSTS; i++, v++) { + for (j = 0; j < PRIVOP_COUNT_NADDRS; j++) + v->addr[j] = v->count[j] = 0; + v->overflow = 0; + } } } #endif diff -r e7da2fcb7a22 -r fc9e2f7920c9 xen/arch/ia64/xen/tlb_track.c --- a/xen/arch/ia64/xen/tlb_track.c Fri Mar 30 10:27:15 2007 -0600 +++ b/xen/arch/ia64/xen/tlb_track.c Fri Mar 30 17:18:42 2007 -0600 @@ -216,14 +216,14 @@ tlb_track_insert_or_dirty(struct tlb_tra TLB_TRACK_RET_T ret = TLB_TRACK_NOT_FOUND; #if 0 /* this is done at vcpu_tlb_track_insert_or_dirty() */ - perfc_incrc(tlb_track_iod); + perfc_incr(tlb_track_iod); if (!pte_tlb_tracking(old_pte)) { - perfc_incrc(tlb_track_iod_not_tracked); + perfc_incr(tlb_track_iod_not_tracked); return TLB_TRACK_NOT_TRACKED; } #endif if (pte_tlb_inserted_many(old_pte)) { - perfc_incrc(tlb_track_iod_tracked_many); + perfc_incr(tlb_track_iod_tracked_many); return TLB_TRACK_MANY; } @@ -260,7 +260,7 @@ tlb_track_insert_or_dirty(struct tlb_tra if (entry->vaddr == vaddr && entry->rid == rid) { // tlb_track_printd("TLB_TRACK_FOUND\n"); ret = TLB_TRACK_FOUND; - perfc_incrc(tlb_track_iod_found); + perfc_incr(tlb_track_iod_found); #ifdef CONFIG_TLB_TRACK_CNT entry->cnt++; if (entry->cnt > TLB_TRACK_CNT_FORCE_MANY) { @@ -276,7 +276,7 @@ tlb_track_insert_or_dirty(struct tlb_tra */ // tlb_track_entry_printf(entry); // tlb_track_printd("cnt = %ld\n", entry->cnt); - perfc_incrc(tlb_track_iod_force_many); + perfc_incr(tlb_track_iod_force_many); goto force_many; } #endif @@ -294,14 +294,14 @@ tlb_track_insert_or_dirty(struct tlb_tra if (pte_val(ret_pte) != pte_val(old_pte)) { // tlb_track_printd("TLB_TRACK_AGAIN\n"); ret = TLB_TRACK_AGAIN; - perfc_incrc(tlb_track_iod_again); + perfc_incr(tlb_track_iod_again); } else { // tlb_track_printd("TLB_TRACK_MANY del entry 0x%p\n", // entry); ret = TLB_TRACK_MANY; list_del(&entry->list); // tlb_track_entry_printf(entry); - perfc_incrc(tlb_track_iod_tracked_many_del); + perfc_incr(tlb_track_iod_tracked_many_del); } goto out; } @@ -314,7 +314,7 @@ tlb_track_insert_or_dirty(struct tlb_tra */ // tlb_track_printd("TLB_TRACK_AGAIN\n"); ret = TLB_TRACK_AGAIN; - perfc_incrc(tlb_track_iod_again); + perfc_incr(tlb_track_iod_again); goto out; } @@ -323,7 +323,7 @@ tlb_track_insert_or_dirty(struct tlb_tra /* Other thread else removed the tlb_track_entry after we got old_pte before we got spin lock. */ ret = TLB_TRACK_AGAIN; - perfc_incrc(tlb_track_iod_again); + perfc_incr(tlb_track_iod_again); goto out; } if (new_entry == NULL && bit_to_be_set == _PAGE_TLB_INSERTED) { @@ -334,10 +334,10 @@ tlb_track_insert_or_dirty(struct tlb_tra /* entry can't be allocated. fall down into full flush mode. */ bit_to_be_set |= _PAGE_TLB_INSERTED_MANY; - perfc_incrc(tlb_track_iod_new_failed); + perfc_incr(tlb_track_iod_new_failed); } // tlb_track_printd("new_entry 0x%p\n", new_entry); - perfc_incrc(tlb_track_iod_new_entry); + perfc_incr(tlb_track_iod_new_entry); goto again; } @@ -348,7 +348,7 @@ tlb_track_insert_or_dirty(struct tlb_tra if (tlb_track_pte_zapped(old_pte, ret_pte)) { // tlb_track_printd("zapped TLB_TRACK_AGAIN\n"); ret = TLB_TRACK_AGAIN; - perfc_incrc(tlb_track_iod_again); + perfc_incr(tlb_track_iod_again); goto out; } @@ -359,7 +359,7 @@ tlb_track_insert_or_dirty(struct tlb_tra // tlb_track_printd("iserted TLB_TRACK_MANY\n"); BUG_ON(!pte_tlb_inserted(ret_pte)); ret = TLB_TRACK_MANY; - perfc_incrc(tlb_track_iod_new_many); + perfc_incr(tlb_track_iod_new_many); goto out; } BUG_ON(pte_tlb_inserted(ret_pte)); @@ -381,7 +381,7 @@ tlb_track_insert_or_dirty(struct tlb_tra #ifdef CONFIG_TLB_TRACK_CNT entry->cnt = 0; #endif - perfc_incrc(tlb_track_iod_insert); + perfc_incr(tlb_track_iod_insert); // tlb_track_entry_printf(entry); } else { goto out; @@ -392,7 +392,7 @@ tlb_track_insert_or_dirty(struct tlb_tra cpu_set(v->processor, entry->pcpu_dirty_mask); BUG_ON(v->vcpu_id >= NR_CPUS); vcpu_set(v->vcpu_id, entry->vcpu_dirty_mask); - perfc_incrc(tlb_track_iod_dirtied); + perfc_incr(tlb_track_iod_dirtied); out: spin_unlock(&tlb_track->hash_lock); @@ -432,19 +432,19 @@ tlb_track_search_and_remove(struct tlb_t struct list_head* head = tlb_track_hash_head(tlb_track, ptep); struct tlb_track_entry* entry; - perfc_incrc(tlb_track_sar); + perfc_incr(tlb_track_sar); if (!pte_tlb_tracking(old_pte)) { - perfc_incrc(tlb_track_sar_not_tracked); + perfc_incr(tlb_track_sar_not_tracked); return TLB_TRACK_NOT_TRACKED; } if (!pte_tlb_inserted(old_pte)) { BUG_ON(pte_tlb_inserted_many(old_pte)); - perfc_incrc(tlb_track_sar_not_found); + perfc_incr(tlb_track_sar_not_found); return TLB_TRACK_NOT_FOUND; } if (pte_tlb_inserted_many(old_pte)) { BUG_ON(!pte_tlb_inserted(old_pte)); - perfc_incrc(tlb_track_sar_many); + perfc_incr(tlb_track_sar_many); return TLB_TRACK_MANY; } @@ -475,14 +475,14 @@ tlb_track_search_and_remove(struct tlb_t pte_tlb_inserted(current_pte))) { BUG_ON(pte_tlb_inserted_many(current_pte)); spin_unlock(&tlb_track->hash_lock); - perfc_incrc(tlb_track_sar_many); + perfc_incr(tlb_track_sar_many); return TLB_TRACK_MANY; } list_del(&entry->list); spin_unlock(&tlb_track->hash_lock); *entryp = entry; - perfc_incrc(tlb_track_sar_found); + perfc_incr(tlb_track_sar_found); // tlb_track_entry_printf(entry); #ifdef CONFIG_TLB_TRACK_CNT // tlb_track_printd("cnt = %ld\n", entry->cnt); diff -r e7da2fcb7a22 -r fc9e2f7920c9 xen/arch/ia64/xen/vcpu.c --- a/xen/arch/ia64/xen/vcpu.c Fri Mar 30 10:27:15 2007 -0600 +++ b/xen/arch/ia64/xen/vcpu.c Fri Mar 30 17:18:42 2007 -0600 @@ -1616,7 +1616,7 @@ IA64FAULT vcpu_translate(VCPU * vcpu, u6 *pteval = (address & _PAGE_PPN_MASK) | __DIRTY_BITS | _PAGE_PL_2 | _PAGE_AR_RWX; *itir = PAGE_SHIFT << 2; - perfc_incrc(phys_translate); + perfc_incr(phys_translate); return IA64_NO_FAULT; } } else if (!region && warn_region0_address) { @@ -1637,7 +1637,7 @@ IA64FAULT vcpu_translate(VCPU * vcpu, u6 if (trp != NULL) { *pteval = trp->pte.val; *itir = trp->itir; - perfc_incrc(tr_translate); + perfc_incr(tr_translate); return IA64_NO_FAULT; } } @@ -1647,7 +1647,7 @@ IA64FAULT vcpu_translate(VCPU * vcpu, u6 if (trp != NULL) { *pteval = trp->pte.val; *itir = trp->itir; - perfc_incrc(tr_translate); + perfc_incr(tr_translate); return IA64_NO_FAULT; } } @@ -1660,7 +1660,7 @@ IA64FAULT vcpu_translate(VCPU * vcpu, u6 && vcpu_match_tr_entry_no_p(trp, address, rid)) { *pteval = pte.val; *itir = trp->itir; - perfc_incrc(dtlb_translate); + perfc_incr(dtlb_translate); return IA64_USE_TLB; } @@ -1709,7 +1709,7 @@ out: out: *itir = rr & RR_PS_MASK; *pteval = pte.val; - perfc_incrc(vhpt_translate); + perfc_incr(vhpt_translate); return IA64_NO_FAULT; } diff -r e7da2fcb7a22 -r fc9e2f7920c9 xen/arch/ia64/xen/vhpt.c --- a/xen/arch/ia64/xen/vhpt.c Fri Mar 30 10:27:15 2007 -0600 +++ b/xen/arch/ia64/xen/vhpt.c Fri Mar 30 17:18:42 2007 -0600 @@ -48,14 +48,14 @@ local_vhpt_flush(void) /* this must be after flush */ tlbflush_update_time(&__get_cpu_var(vhpt_tlbflush_timestamp), flush_time); - perfc_incrc(local_vhpt_flush); + perfc_incr(local_vhpt_flush); } void vcpu_vhpt_flush(struct vcpu* v) { __vhpt_flush(vcpu_vhpt_maddr(v)); - perfc_incrc(vcpu_vhpt_flush); + perfc_incr(vcpu_vhpt_flush); } static void @@ -184,7 +184,7 @@ domain_purge_swtc_entries(struct domain { struct vcpu* v; for_each_vcpu(d, v) { - if (!test_bit(_VCPUF_initialised, &v->vcpu_flags)) + if (!v->is_initialised) continue; /* Purge TC entries. @@ -202,7 +202,7 @@ domain_purge_swtc_entries_vcpu_dirty_mas for_each_vcpu_mask(vcpu, vcpu_dirty_mask) { struct vcpu* v = d->vcpu[vcpu]; - if (!test_bit(_VCPUF_initialised, &v->vcpu_flags)) + if (!v->is_initialised) continue; /* Purge TC entries. @@ -248,7 +248,7 @@ void vcpu_flush_vtlb_all(struct vcpu *v) not running on this processor. There is currently no easy way to check this. */ - perfc_incrc(vcpu_flush_vtlb_all); + perfc_incr(vcpu_flush_vtlb_all); } static void __vcpu_flush_vtlb_all(void *vcpu) @@ -263,7 +263,7 @@ void domain_flush_vtlb_all(struct domain struct vcpu *v; for_each_vcpu(d, v) { - if (!test_bit(_VCPUF_initialised, &v->vcpu_flags)) + if (!v->is_initialised) continue; if (v->processor == cpu) @@ -280,7 +280,7 @@ void domain_flush_vtlb_all(struct domain __vcpu_flush_vtlb_all, v, 1, 1); } - perfc_incrc(domain_flush_vtlb_all); + perfc_incr(domain_flush_vtlb_all); } // Callers may need to call smp_mb() before/after calling this. @@ -322,7 +322,7 @@ void vcpu_flush_tlb_vhpt_range (u64 vadr vadr, 1UL << log_range); ia64_ptcl(vadr, log_range << 2); ia64_srlz_i(); - perfc_incrc(vcpu_flush_tlb_vhpt_range); + perfc_incr(vcpu_flush_tlb_vhpt_range); } void domain_flush_vtlb_range (struct domain *d, u64 vadr, u64 addr_range) @@ -341,7 +341,7 @@ void domain_flush_vtlb_range (struct dom smp_mb(); for_each_vcpu (d, v) { - if (!test_bit(_VCPUF_initialised, &v->vcpu_flags)) + if (!v->is_initialised) continue; if (HAS_PERVCPU_VHPT(d)) { @@ -361,7 +361,7 @@ void domain_flush_vtlb_range (struct dom /* ptc.ga */ platform_global_tlb_purge(vadr, vadr + addr_range, PAGE_SHIFT); - perfc_incrc(domain_flush_vtlb_range); + perfc_incr(domain_flush_vtlb_range); } #ifdef CONFIG_XEN_IA64_TLB_TRACK @@ -391,11 +391,11 @@ __domain_flush_vtlb_track_entry(struct d */ vcpu_get_rr(current, VRN7 << VRN_SHIFT, &rr7_rid); if (likely(rr7_rid == entry->rid)) { - perfc_incrc(tlb_track_use_rr7); + perfc_incr(tlb_track_use_rr7); } else { swap_rr0 = 1; vaddr = (vaddr << 3) >> 3;// force vrn0 - perfc_incrc(tlb_track_swap_rr0); + perfc_incr(tlb_track_swap_rr0); } // tlb_track_entry_printf(entry); @@ -407,7 +407,7 @@ __domain_flush_vtlb_track_entry(struct d if (HAS_PERVCPU_VHPT(d)) { for_each_vcpu_mask(vcpu, entry->vcpu_dirty_mask) { v = d->vcpu[vcpu]; - if (!test_bit(_VCPUF_initialised, &v->vcpu_flags)) + if (!v->is_initialised) continue; /* Invalidate VHPT entries. */ @@ -435,18 +435,18 @@ __domain_flush_vtlb_track_entry(struct d /* ptc.ga */ if (local_purge) { ia64_ptcl(vaddr, PAGE_SHIFT << 2); - perfc_incrc(domain_flush_vtlb_local); + perfc_incr(domain_flush_vtlb_local); } else { /* ptc.ga has release semantics. */ platform_global_tlb_purge(vaddr, vaddr + PAGE_SIZE, PAGE_SHIFT); - perfc_incrc(domain_flush_vtlb_global); + perfc_incr(domain_flush_vtlb_global); } if (swap_rr0) { vcpu_set_rr(current, 0, old_rid); } - perfc_incrc(domain_flush_vtlb_track_entry); + perfc_incr(domain_flush_vtlb_track_entry); } void @@ -512,7 +512,7 @@ void gather_vhpt_stats(void) for (i = 0; i < VHPT_NUM_ENTRIES; i++, v++) if (!(v->ti_tag & INVALID_TI_TAG)) vhpt_valid++; - perfc_seta(vhpt_valid_entries, cpu, vhpt_valid); - } -} -#endif + per_cpu(perfcounters, cpu)[PERFC_vhpt_valid_entries] = vhpt_valid; + } +} +#endif diff -r e7da2fcb7a22 -r fc9e2f7920c9 xen/arch/powerpc/backtrace.c --- a/xen/arch/powerpc/backtrace.c Fri Mar 30 10:27:15 2007 -0600 +++ b/xen/arch/powerpc/backtrace.c Fri Mar 30 17:18:42 2007 -0600 @@ -205,21 +205,6 @@ void show_backtrace_regs(struct cpu_user console_end_sync(); } -void __warn(char *file, int line) -{ - ulong sp; - ulong lr; - - console_start_sync(); - printk("WARN at %s:%d\n", file, line); - - sp = (ulong)__builtin_frame_address(0); - lr = (ulong)__builtin_return_address(0); - backtrace(sp, lr, lr); - - console_end_sync(); -} - void dump_execution_state(void) { struct cpu_user_regs *regs = guest_cpu_user_regs(); diff -r e7da2fcb7a22 -r fc9e2f7920c9 xen/arch/powerpc/domain.c --- a/xen/arch/powerpc/domain.c Fri Mar 30 10:27:15 2007 -0600 +++ b/xen/arch/powerpc/domain.c Fri Mar 30 17:18:42 2007 -0600 @@ -168,10 +168,13 @@ int arch_set_info_guest(struct vcpu *v, d->shared_info->wc_nsec = dom0->shared_info->wc_nsec; d->shared_info->arch.boot_timebase = dom0->shared_info->arch.boot_timebase; - /* Auto-online VCPU0 when it is initialised. */ - if ( !test_and_set_bit(_VCPUF_initialised, &v->vcpu_flags) && - (v->vcpu_id == 0) ) - clear_bit(_VCPUF_down, &v->vcpu_flags); + if ( !v->is_initialised ) + { + v->is_initialised = 1; + /* Auto-online VCPU0 when it is initialised. */ + if ( v->vcpu_id == 0 ) + clear_bit(_VPF_down, &v->pause_flags); + } cpu_init_vcpu(v); diff -r e7da2fcb7a22 -r fc9e2f7920c9 xen/arch/powerpc/domain_build.c --- a/xen/arch/powerpc/domain_build.c Fri Mar 30 10:27:15 2007 -0600 +++ b/xen/arch/powerpc/domain_build.c Fri Mar 30 17:18:42 2007 -0600 @@ -273,8 +273,8 @@ int construct_dom0(struct domain *d, ofd_dom0_fixup(d, *ofh_tree + rma, cmdline, shared_info_addr); - set_bit(_VCPUF_initialised, &v->vcpu_flags); - clear_bit(_VCPUF_down, &v->vcpu_flags); + v->is_initialised = 1; + clear_bit(_VPF_down, &v->pause_flags); rc = 0; diff -r e7da2fcb7a22 -r fc9e2f7920c9 xen/arch/powerpc/mm.c --- a/xen/arch/powerpc/mm.c Fri Mar 30 10:27:15 2007 -0600 +++ b/xen/arch/powerpc/mm.c Fri Mar 30 17:18:42 2007 -0600 @@ -106,7 +106,7 @@ void share_xen_page_with_guest( ASSERT(page->count_info == 0); /* Only add to the allocation list if the domain isn't dying. */ - if ( !test_bit(_DOMF_dying, &d->domain_flags) ) + if ( !d->is_dying ) { page->count_info |= PGC_allocated | 1; if ( unlikely(d->xenheap_pages++ == 0) ) @@ -218,8 +218,7 @@ void put_page_type(struct page_info *pag * page-table pages if we detect a referential loop. * See domain.c:relinquish_list(). */ - ASSERT((x & PGT_validated) || - test_bit(_DOMF_dying, &page_get_owner(page)->domain_flags)); + ASSERT((x & PGT_validated) || page_get_owner(page)->is_dying); if ( unlikely((nx & PGT_count_mask) == 0) ) { @@ -261,7 +260,7 @@ int get_page_type(struct page_info *page if ( unlikely(!cpus_empty(mask)) ) { - perfc_incrc(need_flush_tlb_flush); + perfc_incr(need_flush_tlb_flush); flush_tlb_mask(mask); } @@ -402,7 +401,7 @@ void free_rma_check(struct page_info *pa void free_rma_check(struct page_info *page) { if (test_bit(_PGC_page_RMA, &page->count_info)) { - if (!test_bit(_DOMF_dying, &page_get_owner(page)->domain_flags)) { + if (!page_get_owner(page)->is_dying) { panic("Attempt to free an RMA page: 0x%lx\n", page_to_mfn(page)); } else { clear_bit(_PGC_page_RMA, &page->count_info); @@ -439,8 +438,7 @@ ulong pfn2mfn(struct domain *d, ulong pf mfn = d->arch.p2m[pfn]; } #ifdef DEBUG - if (t != PFN_TYPE_NONE && - (d->domain_flags & DOMF_dying) && + if (t != PFN_TYPE_NONE && d->is_dying && page_get_owner(mfn_to_page(mfn)) != d) { printk("%s: page type: %d owner Dom[%d]:%p expected Dom[%d]:%p\n", __func__, t, diff -r e7da2fcb7a22 -r fc9e2f7920c9 xen/arch/x86/Rules.mk --- a/xen/arch/x86/Rules.mk Fri Mar 30 10:27:15 2007 -0600 +++ b/xen/arch/x86/Rules.mk Fri Mar 30 17:18:42 2007 -0600 @@ -59,6 +59,4 @@ HDRS += $(wildcard $(BASEDIR)/include/as HDRS += $(wildcard $(BASEDIR)/include/asm-x86/hvm/vmx/*.h) # Require GCC v3.4+ (to avoid issues with alignment constraints in Xen headers) -ifneq ($(call cc-ver,$(CC),0x030400),y) -$(error Xen requires at least gcc-3.4) -endif +$(call cc-ver-check,CC,0x030400,"Xen requires at least gcc-3.4") diff -r e7da2fcb7a22 -r fc9e2f7920c9 xen/arch/x86/apic.c --- a/xen/arch/x86/apic.c Fri Mar 30 10:27:15 2007 -0600 +++ b/xen/arch/x86/apic.c Fri Mar 30 17:18:42 2007 -0600 @@ -1076,7 +1076,7 @@ fastcall void smp_apic_timer_interrupt(s fastcall void smp_apic_timer_interrupt(struct cpu_user_regs * regs) { ack_APIC_irq(); - perfc_incrc(apic_timer); + perfc_incr(apic_timer); raise_softirq(TIMER_SOFTIRQ); } diff -r e7da2fcb7a22 -r fc9e2f7920c9 xen/arch/x86/domain.c --- a/xen/arch/x86/domain.c Fri Mar 30 10:27:15 2007 -0600 +++ b/xen/arch/x86/domain.c Fri Mar 30 17:18:42 2007 -0600 @@ -274,7 +274,7 @@ int switch_native(struct domain *d) if ( !IS_COMPAT(d) ) return 0; - clear_bit(_DOMF_compat, &d->domain_flags); + d->is_compat = 0; release_arg_xlat_area(d); /* switch gdt */ @@ -306,7 +306,7 @@ int switch_compat(struct domain *d) if ( IS_COMPAT(d) ) return 0; - set_bit(_DOMF_compat, &d->domain_flags); + d->is_compat = 1; /* switch gdt */ gdt_l1e = l1e_from_page(virt_to_page(compat_gdt_table), PAGE_HYPERVISOR); @@ -563,9 +563,7 @@ int arch_set_info_guest( #endif } - clear_bit(_VCPUF_fpu_initialised, &v->vcpu_flags); - if ( flags & VGCF_I387_VALID ) - set_bit(_VCPUF_fpu_initialised, &v->vcpu_flags); + v->fpu_initialised = !!(flags & VGCF_I387_VALID); v->arch.flags &= ~TF_kernel_mode; if ( (flags & VGCF_in_kernel) || is_hvm_vcpu(v)/*???*/ ) @@ -600,7 +598,7 @@ int arch_set_info_guest( hvm_load_cpu_guest_regs(v, &v->arch.guest_context.user_regs); } - if ( test_bit(_VCPUF_initialised, &v->vcpu_flags) ) + if ( v->is_initialised ) goto out; memset(v->arch.guest_context.debugreg, 0, @@ -699,7 +697,7 @@ int arch_set_info_guest( update_domain_wallclock_time(d); /* Don't redo final setup */ - set_bit(_VCPUF_initialised, &v->vcpu_flags); + v->is_initialised = 1; if ( paging_mode_enabled(d) ) paging_update_paging_modes(v); @@ -708,9 +706,9 @@ int arch_set_info_guest( out: if ( flags & VGCF_online ) - clear_bit(_VCPUF_down, &v->vcpu_flags); + clear_bit(_VPF_down, &v->pause_flags); else - set_bit(_VCPUF_down, &v->vcpu_flags); + set_bit(_VPF_down, &v->pause_flags); return 0; #undef c } diff -r e7da2fcb7a22 -r fc9e2f7920c9 xen/arch/x86/domain_build.c --- a/xen/arch/x86/domain_build.c Fri Mar 30 10:27:15 2007 -0600 +++ b/xen/arch/x86/domain_build.c Fri Mar 30 17:18:42 2007 -0600 @@ -254,7 +254,7 @@ int construct_dom0(struct domain *d, /* Sanity! */ BUG_ON(d->domain_id != 0); BUG_ON(d->vcpu[0] == NULL); - BUG_ON(test_bit(_VCPUF_initialised, &v->vcpu_flags)); + BUG_ON(v->is_initialised); printk("*** LOADING DOMAIN 0 ***\n"); @@ -324,7 +324,7 @@ int construct_dom0(struct domain *d, { l1_pgentry_t gdt_l1e; - set_bit(_DOMF_compat, &d->domain_flags); + d->is_compat = 1; v->vcpu_info = (void *)&d->shared_info->compat.vcpu_info[0]; if ( nr_pages != (unsigned int)nr_pages ) @@ -901,8 +901,8 @@ int construct_dom0(struct domain *d, update_domain_wallclock_time(d); - set_bit(_VCPUF_initialised, &v->vcpu_flags); - clear_bit(_VCPUF_down, &v->vcpu_flags); + v->is_initialised = 1; + clear_bit(_VPF_down, &v->pause_flags); /* * Initial register values: diff -r e7da2fcb7a22 -r fc9e2f7920c9 xen/arch/x86/domctl.c --- a/xen/arch/x86/domctl.c Fri Mar 30 10:27:15 2007 -0600 +++ b/xen/arch/x86/domctl.c Fri Mar 30 17:18:42 2007 -0600 @@ -448,9 +448,9 @@ void arch_get_info_guest(struct vcpu *v, #endif c(flags &= ~(VGCF_i387_valid|VGCF_in_kernel)); - if ( test_bit(_VCPUF_fpu_initialised, &v->vcpu_flags) ) + if ( v->fpu_initialised ) c(flags |= VGCF_i387_valid); - if ( !test_bit(_VCPUF_down, &v->vcpu_flags) ) + if ( !test_bit(_VPF_down, &v->pause_flags) ) c(flags |= VGCF_online); if ( is_hvm_vcpu(v) ) diff -r e7da2fcb7a22 -r fc9e2f7920c9 xen/arch/x86/extable.c --- a/xen/arch/x86/extable.c Fri Mar 30 10:27:15 2007 -0600 +++ b/xen/arch/x86/extable.c Fri Mar 30 17:18:42 2007 -0600 @@ -72,7 +72,7 @@ search_pre_exception_table(struct cpu_us if ( fixup ) { dprintk(XENLOG_INFO, "Pre-exception: %p -> %p\n", _p(addr), _p(fixup)); - perfc_incrc(exception_fixed); + perfc_incr(exception_fixed); } return fixup; } diff -r e7da2fcb7a22 -r fc9e2f7920c9 xen/arch/x86/hvm/hvm.c --- a/xen/arch/x86/hvm/hvm.c Fri Mar 30 10:27:15 2007 -0600 +++ b/xen/arch/x86/hvm/hvm.c Fri Mar 30 17:18:42 2007 -0600 @@ -59,11 +59,14 @@ struct hvm_function_table hvm_funcs __re /* I/O permission bitmap is globally shared by all HVM guests. */ char __attribute__ ((__section__ (".bss.page_aligned"))) hvm_io_bitmap[3*PAGE_SIZE]; +/* MSR permission bitmap is globally shared by all HVM guests. */ +char __attribute__ ((__section__ (".bss.page_aligned"))) + hvm_msr_bitmap[PAGE_SIZE]; void hvm_enable(struct hvm_function_table *fns) { - if ( hvm_enabled ) - return; + BUG_ON(hvm_enabled); + printk("HVM: %s enabled\n", fns->name); /* * Allow direct access to the PC debug port (it is often used for I/O @@ -72,6 +75,9 @@ void hvm_enable(struct hvm_function_tabl memset(hvm_io_bitmap, ~0, sizeof(hvm_io_bitmap)); clear_bit(0x80, hvm_io_bitmap); + /* All MSR accesses are intercepted by default. */ + memset(hvm_msr_bitmap, ~0, sizeof(hvm_msr_bitmap)); + hvm_funcs = *fns; hvm_enabled = 1; } @@ -85,7 +91,7 @@ void hvm_stts(struct vcpu *v) void hvm_stts(struct vcpu *v) { /* FPU state already dirty? Then no need to setup_fpu() lazily. */ - if ( !test_bit(_VCPUF_fpu_dirtied, &v->vcpu_flags) ) + if ( !v->fpu_dirtied ) hvm_funcs.stts(v); } @@ -238,7 +244,7 @@ static int hvm_save_cpu_ctxt(struct doma { /* We don't need to save state for a vcpu that is down; the restore * code will leave it down if there is nothing saved. */ - if ( test_bit(_VCPUF_down, &v->vcpu_flags) ) + if ( test_bit(_VPF_down, &v->pause_flags) ) continue; hvm_funcs.save_cpu_ctxt(v, &ctxt); @@ -269,7 +275,7 @@ static int hvm_load_cpu_ctxt(struct doma return -EINVAL; /* Auxiliary processors should be woken immediately. */ - if ( test_and_clear_bit(_VCPUF_down, &v->vcpu_flags) ) + if ( test_and_clear_bit(_VPF_down, &v->pause_flags) ) vcpu_wake(v); return 0; @@ -331,11 +337,11 @@ void hvm_vcpu_reset(struct vcpu *v) hvm_funcs.vcpu_initialise(v); - set_bit(_VCPUF_down, &v->vcpu_flags); - clear_bit(_VCPUF_initialised, &v->vcpu_flags); - clear_bit(_VCPUF_fpu_initialised, &v->vcpu_flags); - clear_bit(_VCPUF_fpu_dirtied, &v->vcpu_flags); - clear_bit(_VCPUF_blocked, &v->vcpu_flags); + set_bit(_VPF_down, &v->pause_flags); + clear_bit(_VPF_blocked, &v->pause_flags); + v->fpu_initialised = 0; + v->fpu_dirtied = 0; + v->is_initialised = 0; vcpu_unpause(v); } @@ -350,13 +356,13 @@ static void hvm_vcpu_down(void) d->domain_id, v->vcpu_id); /* Doesn't halt us immediately, but we'll never return to guest context. */ - set_bit(_VCPUF_down, &v->vcpu_flags); + set_bit(_VPF_down, &v->pause_flags); vcpu_sleep_nosync(v); /* Any other VCPUs online? ... */ LOCK_BIGLOCK(d); for_each_vcpu ( d, v ) - if ( !test_bit(_VCPUF_down, &v->vcpu_flags) ) + if ( !test_bit(_VPF_down, &v->pause_flags) ) online_count++; UNLOCK_BIGLOCK(d); @@ -556,6 +562,7 @@ static hvm_hypercall_t *hvm_hypercall_ta HYPERCALL(multicall), HYPERCALL(xen_version), HYPERCALL(event_channel_op), + HYPERCALL(sched_op), HYPERCALL(hvm_op) }; @@ -722,7 +729,7 @@ int hvm_bringup_ap(int vcpuid, int tramp LOCK_BIGLOCK(d); rc = -EEXIST; - if ( !test_bit(_VCPUF_initialised, &v->vcpu_flags) ) + if ( !v->is_initialised ) rc = boot_vcpu(d, vcpuid, ctxt); UNLOCK_BIGLOCK(d); @@ -733,7 +740,7 @@ int hvm_bringup_ap(int vcpuid, int tramp goto out; } - if ( test_and_clear_bit(_VCPUF_down, &v->vcpu_flags) ) + if ( test_and_clear_bit(_VPF_down, &v->pause_flags) ) vcpu_wake(v); gdprintk(XENLOG_INFO, "AP %d bringup suceeded.\n", vcpuid); diff -r e7da2fcb7a22 -r fc9e2f7920c9 xen/arch/x86/hvm/io.c --- a/xen/arch/x86/hvm/io.c Fri Mar 30 10:27:15 2007 -0600 +++ b/xen/arch/x86/hvm/io.c Fri Mar 30 17:18:42 2007 -0600 @@ -287,12 +287,18 @@ static void set_reg_value (int size, int } #endif -extern long get_reg_value(int size, int index, int seg, struct cpu_user_regs *regs); +long get_reg_value(int size, int index, int seg, struct cpu_user_regs *regs); static inline void set_eflags_CF(int size, unsigned long v1, unsigned long v2, struct cpu_user_regs *regs) { - unsigned long mask = (1 << (8 * size)) - 1; + unsigned long mask; + + if ( size == BYTE_64 ) + size = BYTE; + ASSERT((size <= sizeof(mask)) && (size > 0)); + + mask = ~0UL >> (8 * (sizeof(mask) - size)); if ((v1 & mask) > (v2 & mask)) regs->eflags |= X86_EFLAGS_CF; @@ -301,14 +307,24 @@ static inline void set_eflags_CF(int siz } static inline void set_eflags_OF(int size, unsigned long v1, - unsigned long v2, unsigned long v3, struct cpu_user_regs *regs) -{ - if ((v3 ^ v2) & (v3 ^ v1) & (1 << ((8 * size) - 1))) + unsigned long v2, unsigned long v3, + struct cpu_user_regs *regs) +{ + unsigned long mask; + + if ( size == BYTE_64 ) + size = BYTE; + ASSERT((size <= sizeof(mask)) && (size > 0)); + + mask = ~0UL >> (8 * (sizeof(mask) - size)); + + if ((v3 ^ v2) & (v3 ^ v1) & mask) regs->eflags |= X86_EFLAGS_OF; } static inline void set_eflags_AF(int size, unsigned long v1, - unsigned long v2, unsigned long v3, struct cpu_user_regs *regs) + unsigned long v2, unsigned long v3, + struct cpu_user_regs *regs) { if ((v1 ^ v2 ^ v3) & 0x10) regs->eflags |= X86_EFLAGS_AF; @@ -317,7 +333,13 @@ static inline void set_eflags_ZF(int siz static inline void set_eflags_ZF(int size, unsigned long v1, struct cpu_user_regs *regs) { - unsigned long mask = (1 << (8 * size)) - 1; + unsigned long mask; + + if ( size == BYTE_64 ) + size = BYTE; + ASSERT((size <= sizeof(mask)) && (size > 0)); + + mask = ~0UL >> (8 * (sizeof(mask) - size)); if ((v1 & mask) == 0) regs->eflags |= X86_EFLAGS_ZF; @@ -326,7 +348,15 @@ static inline void set_eflags_SF(int siz static inline void set_eflags_SF(int size, unsigned long v1, struct cpu_user_regs *regs) { - if (v1 & (1 << ((8 * size) - 1))) + unsigned long mask; + + if ( size == BYTE_64 ) + size = BYTE; + ASSERT((size <= sizeof(mask)) && (size > 0)); + + mask = ~0UL >> (8 * (sizeof(mask) - size)); + + if (v1 & mask) regs->eflags |= X86_EFLAGS_SF; } @@ -375,14 +405,14 @@ static void hvm_pio_assist(struct cpu_us if ( hvm_paging_enabled(current) ) { int rv = hvm_copy_to_guest_virt(addr, &p->data, p->size); - if ( rv != 0 ) + if ( rv != 0 ) { /* Failed on the page-spanning copy. Inject PF into * the guest for the address where we failed. */ addr += p->size - rv; gdprintk(XENLOG_DEBUG, "Pagefault writing non-io side " "of a page-spanning PIO: va=%#lx\n", addr); - hvm_inject_exception(TRAP_page_fault, + hvm_inject_exception(TRAP_page_fault, PFEC_write_access, addr); return; } @@ -505,14 +535,14 @@ static void hvm_mmio_assist(struct cpu_u if (hvm_paging_enabled(current)) { int rv = hvm_copy_to_guest_virt(addr, &p->data, p->size); - if ( rv != 0 ) + if ( rv != 0 ) { /* Failed on the page-spanning copy. Inject PF into * the guest for the address where we failed. */ addr += p->size - rv; gdprintk(XENLOG_DEBUG, "Pagefault writing non-io side of " "a page-spanning MMIO: va=%#lx\n", addr); - hvm_inject_exception(TRAP_page_fault, + hvm_inject_exception(TRAP_page_fault, PFEC_write_access, addr); return; } @@ -718,14 +748,14 @@ static void hvm_mmio_assist(struct cpu_u case INSTR_PUSH: mmio_opp->addr += hvm_get_segment_base(current, x86_seg_ss); - { + { unsigned long addr = mmio_opp->addr; int rv = hvm_copy_to_guest_virt(addr, &p->data, size); - if ( rv != 0 ) + if ( rv != 0 ) { addr += p->size - rv; - gdprintk(XENLOG_DEBUG, "Pagefault emulating PUSH from MMIO: " - "va=%#lx\n", addr); + gdprintk(XENLOG_DEBUG, "Pagefault emulating PUSH from MMIO:" + " va=%#lx\n", addr); hvm_inject_exception(TRAP_page_fault, PFEC_write_access, addr); return; } @@ -767,7 +797,7 @@ void hvm_io_assist(struct vcpu *v) memcpy(guest_cpu_user_regs(), regs, HVM_CONTEXT_STACK_BYTES); /* Has memory been dirtied? */ - if ( p->dir == IOREQ_READ && p->data_is_ptr ) + if ( p->dir == IOREQ_READ && p->data_is_ptr ) { gmfn = get_mfn_from_gpfn(paging_gva_to_gfn(v, p->data)); mark_dirty(v->domain, gmfn); diff -r e7da2fcb7a22 -r fc9e2f7920c9 xen/arch/x86/hvm/save.c --- a/xen/arch/x86/hvm/save.c Fri Mar 30 10:27:15 2007 -0600 +++ b/xen/arch/x86/hvm/save.c Fri Mar 30 17:18:42 2007 -0600 @@ -185,7 +185,7 @@ int hvm_load(struct domain *d, hvm_domai /* Down all the vcpus: we only re-enable the ones that had state saved. */ for_each_vcpu(d, v) - if ( test_and_set_bit(_VCPUF_down, &v->vcpu_flags) ) + if ( test_and_set_bit(_VPF_down, &v->pause_flags) ) vcpu_sleep_nosync(v); while(1) { diff -r e7da2fcb7a22 -r fc9e2f7920c9 xen/arch/x86/hvm/svm/emulate.c --- a/xen/arch/x86/hvm/svm/emulate.c Fri Mar 30 10:27:15 2007 -0600 +++ b/xen/arch/x86/hvm/svm/emulate.c Fri Mar 30 17:18:42 2007 -0600 @@ -373,6 +373,7 @@ MAKE_INSTR(CLTS, 2, 0x0f, 0x06); MAKE_INSTR(CLTS, 2, 0x0f, 0x06); MAKE_INSTR(LMSW, 3, 0x0f, 0x01, 0x00); MAKE_INSTR(SMSW, 3, 0x0f, 0x01, 0x00); +MAKE_INSTR(INT3, 1, 0xcc); static const u8 *opc_bytes[INSTR_MAX_COUNT] = { @@ -405,7 +406,8 @@ static const u8 *opc_bytes[INSTR_MAX_COU [INSTR_CLTS] = OPCODE_CLTS, [INSTR_HLT] = OPCODE_HLT, [INSTR_LMSW] = OPCODE_LMSW, - [INSTR_SMSW] = OPCODE_SMSW + [INSTR_SMSW] = OPCODE_SMSW, + [INSTR_INT3] = OPCODE_INT3 }; /* diff -r e7da2fcb7a22 -r fc9e2f7920c9 xen/arch/x86/hvm/svm/intr.c --- a/xen/arch/x86/hvm/svm/intr.c Fri Mar 30 10:27:15 2007 -0600 +++ b/xen/arch/x86/hvm/svm/intr.c Fri Mar 30 17:18:42 2007 -0600 @@ -64,87 +64,73 @@ asmlinkage void svm_intr_assist(void) { struct vcpu *v = current; struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb; - struct periodic_time *pt; int intr_type = APIC_DM_EXTINT; int intr_vector = -1; - int re_injecting = 0; - /* Check if an Injection is active */ - /* Previous Interrupt delivery caused this Intercept? */ + /* + * Previous Interrupt delivery caused this intercept? + * This will happen if the injection is latched by the processor (hence + * clearing vintr.fields.irq) but then subsequently a fault occurs (e.g., + * due to lack of shadow mapping of guest IDT or guest-kernel stack). + * + * NB. Exceptions that fault during delivery are lost. This needs to be + * fixed but we'll usually get away with it since faults are usually + * idempotent. But this isn't the case for e.g. software interrupts! + */ if ( vmcb->exitintinfo.fields.v && (vmcb->exitintinfo.fields.type == 0) ) { - v->arch.hvm_svm.saved_irq_vector = vmcb->exitintinfo.fields.vector; + intr_vector = vmcb->exitintinfo.fields.vector; vmcb->exitintinfo.bytes = 0; - re_injecting = 1; + HVMTRACE_1D(REINJ_VIRQ, v, intr_vector); + svm_inject_extint(v, intr_vector); + return; } - /* Previous interrupt still pending? */ + /* + * Previous interrupt still pending? This occurs if we return from VMRUN + * very early in the entry-to-guest process. Usually this is because an + * external physical interrupt was pending when we executed VMRUN. + */ if ( vmcb->vintr.fields.irq ) + return; + + /* Crank the handle on interrupt state and check for new interrrupts. */ + pt_update_irq(v); + hvm_set_callback_irq_level(); + if ( !cpu_has_pending_irq(v) ) + return; + + /* + * If the guest can't take an interrupt right now, create a 'fake' + * virtual interrupt on to intercept as soon as the guest _can_ take + * interrupts. Do not obtain the next interrupt from the vlapic/pic + * if unable to inject. + * + * Also do this if there is an exception pending. This is because + * the delivery of the exception can arbitrarily delay the injection + * of the vintr (for example, if the exception is handled via an + * interrupt gate, hence zeroing RFLAGS.IF). In the meantime: + * - the vTPR could be modified upwards, so we need to wait until the + * exception is delivered before we can safely decide that an + * interrupt is deliverable; and + * - the guest might look at the APIC/PIC state, so we ought not to have + * cleared the interrupt out of the IRR. + */ + if ( irq_masked(vmcb->rflags) || vmcb->interrupt_shadow + || vmcb->eventinj.fields.v ) { - intr_vector = vmcb->vintr.fields.vector; - vmcb->vintr.bytes = 0; - re_injecting = 1; - } - /* Pending IRQ saved at last VMExit? */ - else if ( v->arch.hvm_svm.saved_irq_vector >= 0 ) - { - intr_vector = v->arch.hvm_svm.saved_irq_vector; - v->arch.hvm_svm.saved_irq_vector = -1; - re_injecting = 1; - } - /* Now let's check for newer interrrupts */ - else - { - pt_update_irq(v); - - hvm_set_callback_irq_level(); - - if ( cpu_has_pending_irq(v) ) - { - /* - * Create a 'fake' virtual interrupt on to intercept as soon - * as the guest _can_ take interrupts. Do not obtain the next - * interrupt from the vlapic/pic if unable to inject. - */ - if ( irq_masked(vmcb->rflags) || vmcb->interrupt_shadow ) - { - vmcb->general1_intercepts |= GENERAL1_INTERCEPT_VINTR; - HVMTRACE_2D(INJ_VIRQ, v, 0x0, /*fake=*/ 1); - svm_inject_extint(v, 0x0); /* actual vector doesn't really matter */ - return; - } - intr_vector = cpu_get_interrupt(v, &intr_type); - } + vmcb->general1_intercepts |= GENERAL1_INTERCEPT_VINTR; + HVMTRACE_2D(INJ_VIRQ, v, 0x0, /*fake=*/ 1); + svm_inject_extint(v, 0x0); /* actual vector doesn't matter */ + return; } - /* have we got an interrupt to inject? */ - if ( intr_vector < 0 ) - return; + /* Okay, we can deliver the interrupt: grab it and update PIC state. */ + intr_vector = cpu_get_interrupt(v, &intr_type); + BUG_ON(intr_vector < 0); - switch ( intr_type ) - { - case APIC_DM_EXTINT: - case APIC_DM_FIXED: - case APIC_DM_LOWEST: - /* Re-injecting a PIT interruptt? */ - if ( re_injecting && (pt = is_pt_irq(v, intr_vector, intr_type)) ) - ++pt->pending_intr_nr; - /* let's inject this interrupt */ - if (re_injecting) - HVMTRACE_1D(REINJ_VIRQ, v, intr_vector); - else - HVMTRACE_2D(INJ_VIRQ, v, intr_vector, /*fake=*/ 0); - svm_inject_extint(v, intr_vector); - break; - case APIC_DM_SMI: - case APIC_DM_NMI: - case APIC_DM_INIT: - case APIC_DM_STARTUP: - default: - printk("Unsupported interrupt type: %d\n", intr_type); - BUG(); - break; - } + HVMTRACE_2D(INJ_VIRQ, v, intr_vector, /*fake=*/ 0); + svm_inject_extint(v, intr_vector); pt_intr_post(v, intr_vector, intr_type); } diff -r e7da2fcb7a22 -r fc9e2f7920c9 xen/arch/x86/hvm/svm/svm.c --- a/xen/arch/x86/hvm/svm/svm.c Fri Mar 30 10:27:15 2007 -0600 +++ b/xen/arch/x86/hvm/svm/svm.c Fri Mar 30 17:18:42 2007 -0600 @@ -15,7 +15,6 @@ * You should have received a copy of the GNU General Public License along with * this program; if not, write to the Free Software Foundation, Inc., 59 Temple * Place - Suite 330, Boston, MA 02111-1307 USA. - * */ #include <xen/config.h> @@ -50,22 +49,15 @@ #include <asm/hvm/trace.h> #include <asm/hap.h> -#define SVM_EXTRA_DEBUG - #define set_segment_register(name, value) \ - __asm__ __volatile__ ( "movw %%ax ,%%" STR(name) "" : : "a" (value) ) - -/* External functions. We should move these to some suitable header file(s) */ - -extern int inst_copy_from_guest(unsigned char *buf, unsigned long guest_eip, - int inst_len); -extern asmlinkage void do_IRQ(struct cpu_user_regs *); -extern void svm_dump_inst(unsigned long eip); -extern int svm_dbg_on; -void svm_dump_regs(const char *from, struct cpu_user_regs *regs); - -static int svm_do_vmmcall_reset_to_realmode(struct vcpu *v, - struct cpu_user_regs *regs); + asm volatile ( "movw %%ax ,%%" STR(name) "" : : "a" (value) ) + +int inst_copy_from_guest(unsigned char *buf, unsigned long guest_eip, + int inst_len); +asmlinkage void do_IRQ(struct cpu_user_regs *); + +static int svm_reset_to_realmode(struct vcpu *v, + struct cpu_user_regs *regs); /* va of hardware host save area */ static void *hsa[NR_CPUS] __read_mostly; @@ -78,7 +70,6 @@ u64 root_vmcb_pa[NR_CPUS] __read_mostly; /* hardware assisted paging bits */ extern int opt_hap_enabled; -extern int hap_capable_system; static inline void svm_inject_exception(struct vcpu *v, int trap, int ev, int error_code) @@ -213,7 +204,7 @@ static inline int long_mode_do_msr_write switch ( ecx ) { case MSR_EFER: - /* offending reserved bit will cause #GP */ + /* Offending reserved bit will cause #GP. */ if ( msr_content & ~(EFER_LME | EFER_LMA | EFER_NX | EFER_SCE) ) { gdprintk(XENLOG_WARNING, "Trying to set reserved bit in " @@ -221,53 +212,33 @@ static inline int long_mode_do_msr_write goto gp_fault; } - /* - * update the VMCB's EFER with the intended value along with - * that crucial EFER.SVME bit =) - */ - vmcb->efer = msr_content | EFER_SVME; - #ifdef __x86_64__ - - /* - * Check for EFER.LME transitions from 0->1 or 1->0. Do the - * sanity checks and then make sure that both EFER.LME and - * EFER.LMA are cleared. (EFER.LME can't be set in the vmcb - * until the guest also sets CR0.PG, since even if the guest has - * paging "disabled", the vmcb's CR0 always has PG set.) - */ if ( (msr_content & EFER_LME) && !svm_lme_is_set(v) ) { - /* EFER.LME transition from 0 to 1 */ - - if ( svm_paging_enabled(v) || - !svm_cr4_pae_is_set(v) ) + /* EFER.LME transition from 0 to 1. */ + if ( svm_paging_enabled(v) || !svm_cr4_pae_is_set(v) ) { gdprintk(XENLOG_WARNING, "Trying to set LME bit when " "in paging mode or PAE bit is not set\n"); goto gp_fault; } - - vmcb->efer &= ~(EFER_LME | EFER_LMA); } else if ( !(msr_content & EFER_LME) && svm_lme_is_set(v) ) { - /* EFER.LME transistion from 1 to 0 */ - + /* EFER.LME transistion from 1 to 0. */ if ( svm_paging_enabled(v) ) { gdprintk(XENLOG_WARNING, "Trying to clear EFER.LME while paging enabled\n"); goto gp_fault; } - + } +#endif /* __x86_64__ */ + + v->arch.hvm_svm.cpu_shadow_efer = msr_content; + vmcb->efer = msr_content | EFER_SVME; + if ( !svm_paging_enabled(v) ) vmcb->efer &= ~(EFER_LME | EFER_LMA); - } - -#endif /* __x86_64__ */ - - /* update the guest EFER's shadow with the intended value */ - v->arch.hvm_svm.cpu_shadow_efer = msr_content; break; @@ -324,9 +295,9 @@ static inline int long_mode_do_msr_write #define loaddebug(_v,_reg) \ - __asm__ __volatile__ ("mov %0,%%db" #_reg : : "r" ((_v)->debugreg[_reg])) + asm volatile ("mov %0,%%db" #_reg : : "r" ((_v)->debugreg[_reg])) #define savedebug(_v,_reg) \ - __asm__ __volatile__ ("mov %%db" #_reg ",%0" : : "r" ((_v)->debugreg[_reg])) + asm volatile ("mov %%db" #_reg ",%0" : : "r" ((_v)->debugreg[_reg])) static inline void svm_save_dr(struct vcpu *v) { @@ -733,7 +704,7 @@ static void svm_stts(struct vcpu *v) */ if ( !(v->arch.hvm_svm.cpu_shadow_cr0 & X86_CR0_TS) ) { - v->arch.hvm_svm.vmcb->exception_intercepts |= EXCEPTION_BITMAP_NM; + v->arch.hvm_svm.vmcb->exception_intercepts |= 1U << TRAP_no_device; vmcb->cr0 |= X86_CR0_TS; } } @@ -749,19 +720,21 @@ static void svm_init_ap_context( struct vcpu_guest_context *ctxt, int vcpuid, int trampoline_vector) { struct vcpu *v; + struct vmcb_struct *vmcb; cpu_user_regs_t *regs; u16 cs_sel; /* We know this is safe because hvm_bringup_ap() does it */ v = current->domain->vcpu[vcpuid]; + vmcb = v->arch.hvm_svm.vmcb; regs = &v->arch.guest_context.user_regs; memset(ctxt, 0, sizeof(*ctxt)); /* * We execute the trampoline code in real mode. The trampoline vector - * passed to us is page alligned and is the physicall frame number for - * the code. We will execute this code in real mode. + * passed to us is page alligned and is the physical frame number for + * the code. We will execute this code in real mode. */ cs_sel = trampoline_vector << 8; ctxt->user_regs.eip = 0x0; @@ -771,11 +744,11 @@ static void svm_init_ap_context( * This is the launch of an AP; set state so that we begin executing * the trampoline code in real-mode. */ - svm_do_vmmcall_reset_to_realmode(v, regs); + svm_reset_to_realmode(v, regs); /* Adjust the vmcb's hidden register state. */ - v->arch.hvm_svm.vmcb->rip = 0; - v->arch.hvm_svm.vmcb->cs.sel = cs_sel; - v->arch.hvm_svm.vmcb->cs.base = (cs_sel << 4); + vmcb->rip = 0; + vmcb->cs.sel = cs_sel; + vmcb->cs.base = (cs_sel << 4); } static void svm_init_hypercall_page(struct domain *d, void *hypercall_page) @@ -800,74 +773,9 @@ static void svm_init_hypercall_page(stru *(u16 *)(hypercall_page + (__HYPERVISOR_iret * 32)) = 0x0b0f; /* ud2 */ } - -int svm_dbg_on = 0; - -static inline int svm_do_debugout(unsigned long exit_code) -{ - int i; - - static unsigned long counter = 0; - static unsigned long works[] = - { - VMEXIT_IOIO, - VMEXIT_HLT, - VMEXIT_CPUID, - VMEXIT_DR0_READ, - VMEXIT_DR1_READ, - VMEXIT_DR2_READ, - VMEXIT_DR3_READ, - VMEXIT_DR6_READ, - VMEXIT_DR7_READ, - VMEXIT_DR0_WRITE, - VMEXIT_DR1_WRITE, - VMEXIT_DR2_WRITE, - VMEXIT_DR3_WRITE, - VMEXIT_CR0_READ, - VMEXIT_CR0_WRITE, - VMEXIT_CR3_READ, - VMEXIT_CR4_READ, - VMEXIT_MSR, - VMEXIT_CR0_WRITE, - VMEXIT_CR3_WRITE, - VMEXIT_CR4_WRITE, - VMEXIT_EXCEPTION_PF, - VMEXIT_INTR, - VMEXIT_INVLPG, - VMEXIT_EXCEPTION_NM - }; - - -#if 0 - if (svm_dbg_on && exit_code != 0x7B) - return 1; -#endif - - counter++; - -#if 0 - if ((exit_code == 0x4E - || exit_code == VMEXIT_CR0_READ - || exit_code == VMEXIT_CR0_WRITE) - && counter < 200000) - return 0; - - if ((exit_code == 0x4E) && counter < 500000) - return 0; -#endif - - for (i = 0; i < sizeof(works) / sizeof(works[0]); i++) - if (exit_code == works[i]) - return 0; - - return 1; -} - static void save_svm_cpu_user_regs(struct vcpu *v, struct cpu_user_regs *ctxt) { struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb; - - ASSERT(vmcb); ctxt->eax = vmcb->rax; ctxt->ss = vmcb->ss.sel; @@ -882,42 +790,16 @@ static void save_svm_cpu_user_regs(struc ctxt->ds = vmcb->ds.sel; } -static void svm_store_cpu_user_regs(struct cpu_user_regs *regs, struct vcpu *v) -{ - struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb; - - regs->eip = vmcb->rip; - regs->esp = vmcb->rsp; - regs->eflags = vmcb->rflags; - regs->cs = vmcb->cs.sel; - regs->ds = vmcb->ds.sel; - regs->es = vmcb->es.sel; - regs->ss = vmcb->ss.sel; -} - -/* XXX Use svm_load_cpu_guest_regs instead */ -static void svm_load_cpu_user_regs(struct vcpu *v, struct cpu_user_regs *regs) -{ - struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb; - u32 *intercepts = &v->arch.hvm_svm.vmcb->exception_intercepts; +static void svm_load_cpu_guest_regs(struct vcpu *v, struct cpu_user_regs *regs) +{ + struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb; - /* Write the guest register value into VMCB */ vmcb->rax = regs->eax; vmcb->ss.sel = regs->ss; vmcb->rsp = regs->esp; vmcb->rflags = regs->eflags | 2UL; vmcb->cs.sel = regs->cs; vmcb->rip = regs->eip; - if (regs->eflags & EF_TF) - *intercepts |= EXCEPTION_BITMAP_DB; - else - *intercepts &= ~EXCEPTION_BITMAP_DB; -} - -static void svm_load_cpu_guest_regs( - struct vcpu *v, struct cpu_user_regs *regs) -{ - svm_load_cpu_user_regs(v, regs); } static void svm_ctxt_switch_from(struct vcpu *v) @@ -941,8 +823,20 @@ static void svm_ctxt_switch_to(struct vc svm_restore_dr(v); } -static void arch_svm_do_resume(struct vcpu *v) -{ +static void svm_do_resume(struct vcpu *v) +{ + bool_t debug_state = v->domain->debugger_attached; + + if ( unlikely(v->arch.hvm_vcpu.debug_state_latch != debug_state) ) + { + uint32_t mask = (1U << TRAP_debug) | (1U << TRAP_int3); + v->arch.hvm_vcpu.debug_state_latch = debug_state; + if ( debug_state ) + v->arch.hvm_svm.vmcb->exception_intercepts |= mask; + else + v->arch.hvm_svm.vmcb->exception_intercepts &= ~mask; + } + if ( v->arch.hvm_svm.launch_core != smp_processor_id() ) { v->arch.hvm_svm.launch_core = smp_processor_id(); @@ -957,11 +851,9 @@ static int svm_vcpu_initialise(struct vc { int rc; - v->arch.schedule_tail = arch_svm_do_resume; + v->arch.schedule_tail = svm_do_resume; v->arch.ctxt_switch_from = svm_ctxt_switch_from; v->arch.ctxt_switch_to = svm_ctxt_switch_to; - - v->arch.hvm_svm.saved_irq_vector = -1; v->arch.hvm_svm.launch_core = -1; @@ -997,6 +889,7 @@ static int svm_event_injection_faulted(s } static struct hvm_function_table svm_function_table = { + .name = "SVM", .disable = stop_svm, .vcpu_initialise = svm_vcpu_initialise, .vcpu_destroy = svm_vcpu_destroy, @@ -1026,16 +919,13 @@ void svm_npt_detect(void) { u32 eax, ebx, ecx, edx; - /* check CPUID for nested paging support */ + /* Check CPUID for nested paging support. */ cpuid(0x8000000A, &eax, &ebx, &ecx, &edx); - if ( edx & 0x01 ) /* nested paging */ - { - hap_capable_system = 1; - } - else if ( opt_hap_enabled ) - { - printk(" nested paging is not supported by this CPU.\n"); - hap_capable_system = 0; /* no nested paging, we disable flag. */ + + if ( !(edx & 1) && opt_hap_enabled ) + { + printk("SVM: Nested paging is not supported by this CPU.\n"); + opt_hap_enabled = 0; } } @@ -1050,7 +940,7 @@ int start_svm(void) ecx = cpuid_ecx(0x80000001); boot_cpu_data.x86_capability[5] = ecx; - if (!(test_bit(X86_FEATURE_SVME, &boot_cpu_data.x86_capability))) + if ( !(test_bit(X86_FEATURE_SVME, &boot_cpu_data.x86_capability)) ) return 0; /* check whether SVM feature is disabled in BIOS */ @@ -1061,14 +951,13 @@ int start_svm(void) return 0; } - if (!hsa[cpu]) - if (!(hsa[cpu] = alloc_host_save_area())) - return 0; - + if ( ((hsa[cpu] = alloc_host_save_area()) == NULL) || + ((root_vmcb[cpu] = alloc_vmcb()) == NULL) ) + return 0; + rdmsr(MSR_EFER, eax, edx); eax |= EFER_SVME; wrmsr(MSR_EFER, eax, edx); - printk("AMD SVM Extension is enabled for cpu %d.\n", cpu ); svm_npt_detect(); @@ -1077,14 +966,13 @@ int start_svm(void) phys_hsa_lo = (u32) phys_hsa; phys_hsa_hi = (u32) (phys_hsa >> 32); wrmsr(MSR_K8_VM_HSAVE_PA, phys_hsa_lo, phys_hsa_hi); + + root_vmcb_pa[cpu] = virt_to_maddr(root_vmcb[cpu]); - if (!root_vmcb[cpu]) - if (!(root_vmcb[cpu] = alloc_vmcb())) - return 0; - root_vmcb_pa[cpu] = virt_to_maddr(root_vmcb[cpu]); - - if (cpu == 0) - setup_vmcb_dump(); + if ( cpu != 0 ) + return 1; + + setup_vmcb_dump(); hvm_enable(&svm_function_table); @@ -1102,61 +990,15 @@ static int svm_do_nested_pgfault(paddr_t return 0; } - -static int svm_do_page_fault(unsigned long va, struct cpu_user_regs *regs) -{ - HVM_DBG_LOG(DBG_LEVEL_VMMU, - "svm_do_page_fault = 0x%lx, eip = %lx, error_code = %lx", - va, (unsigned long)current->arch.hvm_svm.vmcb->rip, - (unsigned long)regs->error_code); - return paging_fault(va, regs); -} - - static void svm_do_no_device_fault(struct vmcb_struct *vmcb) { struct vcpu *v = current; setup_fpu(v); - vmcb->exception_intercepts &= ~EXCEPTION_BITMAP_NM; + vmcb->exception_intercepts &= ~(1U << TRAP_no_device); if ( !(v->arch.hvm_svm.cpu_shadow_cr0 & X86_CR0_TS) ) vmcb->cr0 &= ~X86_CR0_TS; -} - - -static void svm_do_general_protection_fault(struct vcpu *v, - struct cpu_user_regs *regs) -{ - struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb; - unsigned long eip, error_code; - - ASSERT(vmcb); - - eip = vmcb->rip; - error_code = vmcb->exitinfo1; - - if (vmcb->idtr.limit == 0) { - printk("Huh? We got a GP Fault with an invalid IDTR!\n"); - svm_dump_vmcb(__func__, vmcb); - svm_dump_regs(__func__, regs); - svm_dump_inst(svm_rip2pointer(v)); - domain_crash(v->domain); - return; - } - - HVM_DBG_LOG(DBG_LEVEL_1, - "svm_general_protection_fault: eip = %lx, erro_code = %lx", - eip, error_code); - - HVM_DBG_LOG(DBG_LEVEL_1, - "eax=%lx, ebx=%lx, ecx=%lx, edx=%lx, esi=%lx, edi=%lx", - (unsigned long)regs->eax, (unsigned long)regs->ebx, - (unsigned long)regs->ecx, (unsigned long)regs->edx, - (unsigned long)regs->esi, (unsigned long)regs->edi); - - /* Reflect it back into the guest */ - svm_inject_exception(v, TRAP_gp_fault, 1, error_code); } /* Reserved bits ECX: [31:14], [12:4], [2:1]*/ @@ -1171,8 +1013,6 @@ static void svm_vmexit_do_cpuid(struct v unsigned int eax, ebx, ecx, edx; struct vcpu *v = current; int inst_len; - - ASSERT(vmcb); hvm_cpuid(input, &eax, &ebx, &ecx, &edx); @@ -1305,8 +1145,8 @@ static inline unsigned long *get_reg_p( } -static inline unsigned long get_reg(unsigned int gpreg, - struct cpu_user_regs *regs, struct vmcb_struct *vmcb) +static inline unsigned long get_reg( + unsigned int gpreg, struct cpu_user_regs *regs, struct vmcb_struct *vmcb) { unsigned long *gp; gp = get_reg_p(gpreg, regs, vmcb); @@ -1314,8 +1154,9 @@ static inline unsigned long get_reg(unsi } -static inline void set_reg(unsigned int gpreg, unsigned long value, - struct cpu_user_regs *regs, struct vmcb_struct *vmcb) +static inline void set_reg( + unsigned int gpreg, unsigned long value, + struct cpu_user_regs *regs, struct vmcb_struct *vmcb) { unsigned long *gp; gp = get_reg_p(gpreg, regs, vmcb); @@ -1585,7 +1426,6 @@ static void svm_io_instruction(struct vc ioio_info_t info; struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb; - ASSERT(vmcb); pio_opp = ¤t->arch.hvm_vcpu.io_op; pio_opp->instr = INSTR_PIO; pio_opp->flags = 0; @@ -1729,226 +1569,95 @@ static void svm_io_instruction(struct vc } } -static int npt_set_cr0(unsigned long value) +static int svm_set_cr0(unsigned long value) { struct vcpu *v = current; - struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb; - - ASSERT(vmcb); - - /* ET is reserved and should be always be 1*/ - value |= X86_CR0_ET; - - /* Check whether the guest is about to turn on long mode. - * If it is, set EFER.LME and EFER.LMA. Update the shadow EFER.LMA - * bit too, so svm_long_mode_enabled() will work. - */ - if ( (value & X86_CR0_PG) && svm_lme_is_set(v) && - (vmcb->cr4 & X86_CR4_PAE) && (vmcb->cr0 & X86_CR0_PE) ) - { - v->arch.hvm_svm.cpu_shadow_efer |= EFER_LMA; - vmcb->efer |= EFER_LMA | EFER_LME; - } - - /* Whenever CR0.PG is cleared under long mode, LMA will be cleared - * immediatly. We emulate this process for svm_long_mode_enabled(). - */ - if ( (value & (X86_CR0_PE | X86_CR0_PG)) == X86_CR0_PE ) - { - if ( svm_long_mode_enabled(v) ) - { - v->arch.hvm_svm.cpu_shadow_efer &= ~EFER_LMA; - } - } - - vmcb->cr0 = value | X86_CR0_WP; - v->arch.hvm_svm.cpu_shadow_cr0 = value; - - /* TS cleared? Then initialise FPU now. */ - if ( !(value & X86_CR0_TS) ) { - setup_fpu(v); - vmcb->exception_intercepts &= ~EXCEPTION_BITMAP_NM; - } - - paging_update_paging_modes(v); - - return 1; -} - -static int svm_set_cr0(unsigned long value) -{ - struct vcpu *v = current; - unsigned long mfn; - int paging_enabled; + unsigned long mfn, old_value = v->arch.hvm_svm.cpu_shadow_cr0; struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb; unsigned long old_base_mfn; - ASSERT(vmcb); - - /* We don't want to lose PG. ET is reserved and should be always be 1*/ - paging_enabled = svm_paging_enabled(v); + HVM_DBG_LOG(DBG_LEVEL_VMMU, "Update CR0 value = %lx\n", value); + + /* ET is reserved and should be always be 1. */ value |= X86_CR0_ET; - vmcb->cr0 = value | X86_CR0_PG | X86_CR0_WP; - v->arch.hvm_svm.cpu_shadow_cr0 = value; + + if ( (value & (X86_CR0_PE|X86_CR0_PG)) == X86_CR0_PG ) + { + svm_inject_exception(v, TRAP_gp_fault, 1, 0); + return 0; + } /* TS cleared? Then initialise FPU now. */ if ( !(value & X86_CR0_TS) ) { setup_fpu(v); - vmcb->exception_intercepts &= ~EXCEPTION_BITMAP_NM; - } - - HVM_DBG_LOG(DBG_LEVEL_VMMU, "Update CR0 value = %lx\n", value); - - if ( ((value & (X86_CR0_PE | X86_CR0_PG)) == (X86_CR0_PE | X86_CR0_PG)) - && !paging_enabled ) - { - /* The guest CR3 must be pointing to the guest physical. */ - mfn = get_mfn_from_gpfn(v->arch.hvm_svm.cpu_cr3 >> PAGE_SHIFT); - if ( !mfn_valid(mfn) || !get_page(mfn_to_page(mfn), v->domain)) - { - gdprintk(XENLOG_ERR, "Invalid CR3 value = %lx (mfn=%lx)\n", - v->arch.hvm_svm.cpu_cr3, mfn); - domain_crash(v->domain); - return 0; - } - + vmcb->exception_intercepts &= ~(1U << TRAP_no_device); + } + + if ( (value & X86_CR0_PG) && !(old_value & X86_CR0_PG) ) + { #if defined(__x86_64__) - if ( svm_lme_is_set(v) && !svm_cr4_pae_is_set(v) ) - { - HVM_DBG_LOG(DBG_LEVEL_1, "Enable paging before PAE enable\n"); - svm_inject_exception(v, TRAP_gp_fault, 1, 0); - } - if ( svm_lme_is_set(v) ) { + if ( !svm_cr4_pae_is_set(v) ) + { + HVM_DBG_LOG(DBG_LEVEL_1, "Enable paging before PAE enable\n"); + svm_inject_exception(v, TRAP_gp_fault, 1, 0); + return 0; + } HVM_DBG_LOG(DBG_LEVEL_1, "Enable the Long mode\n"); v->arch.hvm_svm.cpu_shadow_efer |= EFER_LMA; vmcb->efer |= EFER_LMA | EFER_LME; } #endif /* __x86_64__ */ - /* Now arch.guest_table points to machine physical. */ - old_base_mfn = pagetable_get_pfn(v->arch.guest_table); - v->arch.guest_table = pagetable_from_pfn(mfn); - if ( old_base_mfn ) - put_page(mfn_to_page(old_base_mfn)); - paging_update_paging_modes(v); - - HVM_DBG_LOG(DBG_LEVEL_VMMU, "New arch.guest_table = %lx", - (unsigned long) (mfn << PAGE_SHIFT)); - } - - if ( !((value & X86_CR0_PE) && (value & X86_CR0_PG)) && paging_enabled ) - if ( v->arch.hvm_svm.cpu_cr3 ) { + if ( !paging_mode_hap(v->domain) ) + { + /* The guest CR3 must be pointing to the guest physical. */ + mfn = get_mfn_from_gpfn(v->arch.hvm_svm.cpu_cr3 >> PAGE_SHIFT); + if ( !mfn_valid(mfn) || !get_page(mfn_to_page(mfn), v->domain)) + { + gdprintk(XENLOG_ERR, "Invalid CR3 value = %lx (mfn=%lx)\n", + v->arch.hvm_svm.cpu_cr3, mfn); + domain_crash(v->domain); + return 0; + } + + /* Now arch.guest_table points to machine physical. */ + old_base_mfn = pagetable_get_pfn(v->arch.guest_table); + v->arch.guest_table = pagetable_from_pfn(mfn); + if ( old_base_mfn ) + put_page(mfn_to_page(old_base_mfn)); + + HVM_DBG_LOG(DBG_LEVEL_VMMU, "New arch.guest_table = %lx", + (unsigned long) (mfn << PAGE_SHIFT)); + } + } + else if ( !(value & X86_CR0_PG) && (old_value & X86_CR0_PG) ) + { + /* When CR0.PG is cleared, LMA is cleared immediately. */ + if ( svm_long_mode_enabled(v) ) + { + vmcb->efer &= ~(EFER_LME | EFER_LMA); + v->arch.hvm_svm.cpu_shadow_efer &= ~EFER_LMA; + } + + if ( !paging_mode_hap(v->domain) && v->arch.hvm_svm.cpu_cr3 ) + { put_page(mfn_to_page(get_mfn_from_gpfn( v->arch.hvm_svm.cpu_cr3 >> PAGE_SHIFT))); v->arch.guest_table = pagetable_null(); } - - /* - * SVM implements paged real-mode and when we return to real-mode - * we revert back to the physical mappings that the domain builder - * created. - */ - if ((value & X86_CR0_PE) == 0) { - if (value & X86_CR0_PG) { - svm_inject_exception(v, TRAP_gp_fault, 1, 0); - return 0; - } + } + + vmcb->cr0 = v->arch.hvm_svm.cpu_shadow_cr0 = value; + if ( !paging_mode_hap(v->domain) ) + vmcb->cr0 |= X86_CR0_PG | X86_CR0_WP; + + if ( (value ^ old_value) & X86_CR0_PG ) paging_update_paging_modes(v); - } - else if ( (value & (X86_CR0_PE | X86_CR0_PG)) == X86_CR0_PE ) - { - if ( svm_long_mode_enabled(v) ) - { - vmcb->efer &= ~(EFER_LME | EFER_LMA); - v->arch.hvm_svm.cpu_shadow_efer &= ~EFER_LMA; - } - /* we should take care of this kind of situation */ - paging_update_paging_modes(v); - } return 1; -} - -// -// nested paging functions -// - -static int npt_mov_to_cr(int gpreg, int cr, struct cpu_user_regs *regs) -{ - unsigned long value; - struct vcpu *v = current; - struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb; - struct vlapic *vlapic = vcpu_vlapic(v); - - ASSERT(vmcb); - - value = get_reg(gpreg, regs, vmcb); - - switch (cr) { - case 0: - return npt_set_cr0(value); - - case 3: - vmcb->cr3 = value; - v->arch.hvm_svm.cpu_cr3 = value; - break; - - case 4: /* CR4 */ - vmcb->cr4 = value; - v->arch.hvm_svm.cpu_shadow_cr4 = value; - paging_update_paging_modes(v); - break; - - case 8: - vlapic_set_reg(vlapic, APIC_TASKPRI, ((value & 0x0F) << 4)); - vmcb->vintr.fields.tpr = value & 0x0F; - break; - - default: - gdprintk(XENLOG_ERR, "invalid cr: %d\n", cr); - domain_crash(v->domain); - return 0; - } - - return 1; -} - -static void npt_mov_from_cr(int cr, int gp, struct cpu_user_regs *regs) -{ - unsigned long value = 0; - struct vcpu *v = current; - struct vmcb_struct *vmcb; - struct vlapic *vlapic = vcpu_vlapic(v); - - vmcb = v->arch.hvm_svm.vmcb; - ASSERT(vmcb); - - switch(cr) { - case 0: - value = (unsigned long) v->arch.hvm_svm.cpu_shadow_cr0; - break; - case 2: - value = vmcb->cr2; - break; - case 3: - value = (unsigned long) v->arch.hvm_svm.cpu_cr3; - break; - case 4: - value = (unsigned long) v->arch.hvm_svm.cpu_shadow_cr4; - break; - case 8: - value = (unsigned long)vlapic_get_reg(vlapic, APIC_TASKPRI); - value = (value & 0xF0) >> 4; - break; - default: - domain_crash(v->domain); - return; - } - - set_reg(gp, value, regs, vmcb); } /* @@ -1959,30 +1668,21 @@ static void mov_from_cr(int cr, int gp, unsigned long value = 0; struct vcpu *v = current; struct vlapic *vlapic = vcpu_vlapic(v); - struct vmcb_struct *vmcb; - - vmcb = v->arch.hvm_svm.vmcb; - ASSERT(vmcb); + struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb; switch ( cr ) { case 0: value = v->arch.hvm_svm.cpu_shadow_cr0; - if (svm_dbg_on) - printk("CR0 read =%lx \n", value ); break; case 2: value = vmcb->cr2; break; case 3: - value = (unsigned long) v->arch.hvm_svm.cpu_cr3; - if (svm_dbg_on) - printk("CR3 read =%lx \n", value ); + value = (unsigned long)v->arch.hvm_svm.cpu_cr3; break; case 4: - value = (unsigned long) v->arch.hvm_svm.cpu_shadow_cr4; - if (svm_dbg_on) - printk("CR4 read=%lx\n", value); + value = (unsigned long)v->arch.hvm_svm.cpu_shadow_cr4; break; case 8: value = (unsigned long)vlapic_get_reg(vlapic, APIC_TASKPRI); @@ -2019,24 +1719,27 @@ static int mov_to_cr(int gpreg, int cr, HVM_DBG_LOG(DBG_LEVEL_1, "mov_to_cr: CR%d, value = %lx,", cr, value); HVM_DBG_LOG(DBG_LEVEL_1, "current = %lx,", (unsigned long) current); - switch (cr) + switch ( cr ) { case 0: - if (svm_dbg_on) - printk("CR0 write =%lx \n", value ); return svm_set_cr0(value); - case 3: - if (svm_dbg_on) - printk("CR3 write =%lx \n", value ); + case 3: + if ( paging_mode_hap(v->domain) ) + { + vmcb->cr3 = v->arch.hvm_svm.cpu_cr3 = value; + break; + } + /* If paging is not enabled yet, simply copy the value to CR3. */ - if (!svm_paging_enabled(v)) { + if ( !svm_paging_enabled(v) ) + { v->arch.hvm_svm.cpu_cr3 = value; break; } /* We make a new one if the shadow does not exist. */ - if (value == v->arch.hvm_svm.cpu_cr3) + if ( value == v->arch.hvm_svm.cpu_cr3 ) { /* * This is simple TLB flush, implying the guest has @@ -2044,7 +1747,7 @@ static int mov_to_cr(int gpreg, int cr, * We simply invalidate the shadow. */ mfn = get_mfn_from_gpfn(value >> PAGE_SHIFT); - if (mfn != pagetable_get_pfn(v->arch.guest_table)) + if ( mfn != pagetable_get_pfn(v->arch.guest_table) ) goto bad_cr3; paging_update_cr3(v); } @@ -2056,13 +1759,13 @@ static int mov_to_cr(int gpreg, int cr, */ HVM_DBG_LOG(DBG_LEVEL_VMMU, "CR3 value = %lx", value); mfn = get_mfn_from_gpfn(value >> PAGE_SHIFT); - if ( !mfn_valid(mfn) || !get_page(mfn_to_page(mfn), v->domain)) + if ( !mfn_valid(mfn) || !get_page(mfn_to_page(mfn), v->domain) ) goto bad_cr3; old_base_mfn = pagetable_get_pfn(v->arch.guest_table); v->arch.guest_table = pagetable_from_pfn(mfn); - if (old_base_mfn) + if ( old_base_mfn ) put_page(mfn_to_page(old_base_mfn)); v->arch.hvm_svm.cpu_cr3 = value; @@ -2072,9 +1775,13 @@ static int mov_to_cr(int gpreg, int cr, break; case 4: /* CR4 */ - if (svm_dbg_on) - printk( "write cr4=%lx, cr0=%lx\n", - value, v->arch.hvm_svm.cpu_shadow_cr0 ); + if ( paging_mode_hap(v->domain) ) + { + vmcb->cr4 = v->arch.hvm_svm.cpu_shadow_cr4 = value; + paging_update_paging_modes(v); + break; + } + old_cr = v->arch.hvm_svm.cpu_shadow_cr4; if ( value & X86_CR4_PAE && !(old_cr & X86_CR4_PAE) ) { @@ -2154,17 +1861,17 @@ static int svm_cr_access(struct vcpu *v, { struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb; int inst_len = 0; - int index; - unsigned int gpreg; - unsigned long value; + int index,addr_size,i; + unsigned int gpreg,offset; + unsigned long value,addr; u8 buffer[MAX_INST_LEN]; u8 prefix = 0; + u8 modrm; + enum x86_segment seg; int result = 1; enum instruction_index list_a[] = {INSTR_MOV2CR, INSTR_CLTS, INSTR_LMSW}; enum instruction_index list_b[] = {INSTR_MOVCR2, INSTR_SMSW}; enum instruction_index match; - - ASSERT(vmcb); inst_copy_from_guest(buffer, svm_rip2pointer(v), sizeof(buffer)); @@ -2197,60 +1904,83 @@ static int svm_cr_access(struct vcpu *v, { case INSTR_MOV2CR: gpreg = decode_src_reg(prefix, buffer[index+2]); - if ( paging_mode_hap(v->domain) ) - result = npt_mov_to_cr(gpreg, cr, regs); - else - result = mov_to_cr(gpreg, cr, regs); + result = mov_to_cr(gpreg, cr, regs); break; case INSTR_MOVCR2: gpreg = decode_src_reg(prefix, buffer[index+2]); - if ( paging_mode_hap(v->domain) ) - npt_mov_from_cr(cr, gpreg, regs); - else - mov_from_cr(cr, gpreg, regs); + mov_from_cr(cr, gpreg, regs); break; case INSTR_CLTS: /* TS being cleared means that it's time to restore fpu state. */ setup_fpu(current); - vmcb->exception_intercepts &= ~EXCEPTION_BITMAP_NM; + vmcb->exception_intercepts &= ~(1U << TRAP_no_device); vmcb->cr0 &= ~X86_CR0_TS; /* clear TS */ v->arch.hvm_svm.cpu_shadow_cr0 &= ~X86_CR0_TS; /* clear TS */ break; case INSTR_LMSW: - if (svm_dbg_on) - svm_dump_inst(svm_rip2pointer(v)); - gpreg = decode_src_reg(prefix, buffer[index+2]); value = get_reg(gpreg, regs, vmcb) & 0xF; - - if (svm_dbg_on) - printk("CR0-LMSW value=%lx, reg=%d, inst_len=%d\n", value, gpreg, - inst_len); - value = (v->arch.hvm_svm.cpu_shadow_cr0 & ~0xF) | value; - - if (svm_dbg_on) - printk("CR0-LMSW CR0 - New value=%lx\n", value); - - if ( paging_mode_hap(v->domain) ) - result = npt_set_cr0(value); + result = svm_set_cr0(value); + break; + + case INSTR_SMSW: + value = v->arch.hvm_svm.cpu_shadow_cr0 & 0xFFFF; + modrm = buffer[index+2]; + addr_size = svm_guest_x86_mode( v ); + if ( likely((modrm & 0xC0) >> 6 == 3) ) + { + gpreg = decode_src_reg(prefix, modrm); + set_reg(gpreg, value, regs, vmcb); + } + /* + * For now, only implement decode of the offset mode, since that's the + * only mode observed in a real-world OS. This code is also making the + * assumption that we'll never hit this code in long mode. + */ + else if ( (modrm == 0x26) || (modrm == 0x25) ) + { + seg = x86_seg_ds; + i = index; + /* Segment or address size overrides? */ + while ( i-- ) + { + switch ( buffer[i] ) + { + case 0x26: seg = x86_seg_es; break; + case 0x2e: seg = x86_seg_cs; break; + case 0x36: seg = x86_seg_ss; break; + case 0x64: seg = x86_seg_fs; break; + case 0x65: seg = x86_seg_gs; break; + case 0x67: addr_size ^= 6; break; + } + } + /* Bail unless this really is a seg_base + offset case */ + if ( ((modrm == 0x26) && (addr_size == 4)) || + ((modrm == 0x25) && (addr_size == 2)) ) + { + gdprintk(XENLOG_ERR, "SMSW emulation at guest address: " + "%lx failed due to unhandled addressing mode." + "ModRM byte was: %x \n", svm_rip2pointer(v), modrm); + domain_crash(v->domain); + } + inst_len += addr_size; + offset = *(( unsigned int *) ( void *) &buffer[index + 3]); + offset = ( addr_size == 4 ) ? offset : ( offset & 0xFFFF ); + addr = hvm_get_segment_base(v, seg); + addr += offset; + hvm_copy_to_guest_virt(addr,&value,2); + } else - result = svm_set_cr0(value); - break; - - case INSTR_SMSW: - if (svm_dbg_on) - svm_dump_inst(svm_rip2pointer(v)); - value = v->arch.hvm_svm.cpu_shadow_cr0; - gpreg = decode_src_reg(prefix, buffer[index+2]); - set_reg(gpreg, value, regs, vmcb); - - if (svm_dbg_on) - printk("CR0-SMSW value=%lx, reg=%d, inst_len=%d\n", value, gpreg, - inst_len); + { + gdprintk(XENLOG_ERR, "SMSW emulation at guest address: %lx " + "failed due to unhandled addressing mode!" + "ModRM byte was: %x \n", svm_rip2pointer(v), modrm); + domain_crash(v->domain); + } break; default: @@ -2271,8 +2001,6 @@ static inline void svm_do_msr_access( int inst_len; u64 msr_content=0; u32 ecx = regs->ecx, eax, edx; - - ASSERT(vmcb); HVM_DBG_LOG(DBG_LEVEL_1, "ecx=%x, eax=%x, edx=%x, exitinfo = %lx", ecx, (u32)regs->eax, (u32)regs->edx, @@ -2357,7 +2085,6 @@ static inline void svm_do_msr_access( __update_guest_eip(vmcb, inst_len); } - static inline void svm_vmexit_do_hlt(struct vmcb_struct *vmcb) { __update_guest_eip(vmcb, 1); @@ -2372,7 +2099,6 @@ static inline void svm_vmexit_do_hlt(str HVMTRACE_1D(HLT, current, /*int pending=*/ 0); hvm_hlt(vmcb->rflags); } - static void svm_vmexit_do_invd(struct vcpu *v) { @@ -2387,48 +2113,12 @@ static void svm_vmexit_do_invd(struct vc /* Tell the user that we did this - just in case someone runs some really * weird operating system and wants to know why it's not working... */ - printk("INVD instruction intercepted - ignored\n"); + gdprintk(XENLOG_WARNING, "INVD instruction intercepted - ignored\n"); inst_len = __get_instruction_length(v, INSTR_INVD, NULL); __update_guest_eip(vmcb, inst_len); } - - - -#ifdef XEN_DEBUGGER -static void svm_debug_save_cpu_user_regs(struct vmcb_struct *vmcb, - struct cpu_user_regs *regs) -{ - regs->eip = vmcb->rip; - regs->esp = vmcb->rsp; - regs->eflags = vmcb->rflags; - - regs->xcs = vmcb->cs.sel; - regs->xds = vmcb->ds.sel; - regs->xes = vmcb->es.sel; - regs->xfs = vmcb->fs.sel; - regs->xgs = vmcb->gs.sel; - regs->xss = vmcb->ss.sel; -} - - -static void svm_debug_restore_cpu_user_regs(struct cpu_user_regs *regs) -{ - vmcb->ss.sel = regs->xss; - vmcb->rsp = regs->esp; - vmcb->rflags = regs->eflags; - vmcb->cs.sel = regs->xcs; - vmcb->rip = regs->eip; - - vmcb->gs.sel = regs->xgs; - vmcb->fs.sel = regs->xfs; - vmcb->es.sel = regs->xes; - vmcb->ds.sel = regs->xds; -} -#endif - - void svm_handle_invlpg(const short invlpga, struct cpu_user_regs *regs) { struct vcpu *v = current; @@ -2494,18 +2184,11 @@ void svm_handle_invlpg(const short invlp * * returns 0 on success, non-zero otherwise */ -static int svm_do_vmmcall_reset_to_realmode(struct vcpu *v, - struct cpu_user_regs *regs) -{ - struct vmcb_struct *vmcb; - - ASSERT(v); - ASSERT(regs); - - vmcb = v->arch.hvm_svm.vmcb; - - ASSERT(vmcb); - +static int svm_reset_to_realmode(struct vcpu *v, + struct cpu_user_regs *regs) +{ + struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb; + /* clear the vmcb and user regs */ memset(regs, 0, sizeof(struct cpu_user_regs)); @@ -2587,449 +2270,65 @@ static int svm_do_vmmcall_reset_to_realm return 0; } - -void svm_dump_inst(unsigned long eip) -{ - u8 opcode[256]; - unsigned long ptr; - int len; - int i; - - ptr = eip & ~0xff; - len = 0; - - if (hvm_copy_from_guest_virt(opcode, ptr, sizeof(opcode)) == 0) - len = sizeof(opcode); - - printk("Code bytes around(len=%d) %lx:", len, eip); - for (i = 0; i < len; i++) - { - if ((i & 0x0f) == 0) - printk("\n%08lx:", ptr+i); - - printk("%02x ", opcode[i]); - } - - printk("\n"); -} - - -void svm_dump_regs(const char *from, struct cpu_user_regs *regs) -{ - struct vcpu *v = current; - struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb; - unsigned long pt = v->arch.hvm_vcpu.hw_cr3; - - printk("%s: guest registers from %s:\n", __func__, from); -#if defined (__x86_64__) - printk("rax: %016lx rbx: %016lx rcx: %016lx\n", - regs->rax, regs->rbx, regs->rcx); - printk("rdx: %016lx rsi: %016lx rdi: %016lx\n", - regs->rdx, regs->rsi, regs->rdi); - printk("rbp: %016lx rsp: %016lx r8: %016lx\n", - regs->rbp, regs->rsp, regs->r8); - printk("r9: %016lx r10: %016lx r11: %016lx\n", - regs->r9, regs->r10, regs->r11); - printk("r12: %016lx r13: %016lx r14: %016lx\n", - regs->r12, regs->r13, regs->r14); - printk("r15: %016lx cr0: %016lx cr3: %016lx\n", - regs->r15, v->arch.hvm_svm.cpu_shadow_cr0, vmcb->cr3); -#else - printk("eax: %08x, ebx: %08x, ecx: %08x, edx: %08x\n", - regs->eax, regs->ebx, regs->ecx, regs->edx); - printk("edi: %08x, esi: %08x, ebp: %08x, esp: %08x\n", - regs->edi, regs->esi, regs->ebp, regs->esp); - printk("%s: guest cr0: %lx\n", __func__, - v->arch.hvm_svm.cpu_shadow_cr0); - printk("guest CR3 = %llx\n", vmcb->cr3); -#endif - printk("%s: pt = %lx\n", __func__, pt); -} - - -void svm_dump_host_regs(const char *from) -{ - struct vcpu *v = current; - unsigned long pt = pt = pagetable_get_paddr(v->arch.monitor_table); - unsigned long cr3, cr0; - printk("Host registers at %s\n", from); - - __asm__ __volatile__ ("\tmov %%cr0,%0\n" - "\tmov %%cr3,%1\n" - : "=r" (cr0), "=r"(cr3)); - printk("%s: pt = %lx, cr3 = %lx, cr0 = %lx\n", __func__, pt, cr3, cr0); -} - -#ifdef SVM_EXTRA_DEBUG -static char *exit_reasons[] = { - [VMEXIT_CR0_READ] = "CR0_READ", - [VMEXIT_CR1_READ] = "CR1_READ", - [VMEXIT_CR2_READ] = "CR2_READ", - [VMEXIT_CR3_READ] = "CR3_READ", - [VMEXIT_CR4_READ] = "CR4_READ", - [VMEXIT_CR5_READ] = "CR5_READ", - [VMEXIT_CR6_READ] = "CR6_READ", - [VMEXIT_CR7_READ] = "CR7_READ", - [VMEXIT_CR8_READ] = "CR8_READ", - [VMEXIT_CR9_READ] = "CR9_READ", - [VMEXIT_CR10_READ] = "CR10_READ", - [VMEXIT_CR11_READ] = "CR11_READ", - [VMEXIT_CR12_READ] = "CR12_READ", - [VMEXIT_CR13_READ] = "CR13_READ", - [VMEXIT_CR14_READ] = "CR14_READ", - [VMEXIT_CR15_READ] = "CR15_READ", - [VMEXIT_CR0_WRITE] = "CR0_WRITE", - [VMEXIT_CR1_WRITE] = "CR1_WRITE", - [VMEXIT_CR2_WRITE] = "CR2_WRITE", - [VMEXIT_CR3_WRITE] = "CR3_WRITE", - [VMEXIT_CR4_WRITE] = "CR4_WRITE", - [VMEXIT_CR5_WRITE] = "CR5_WRITE", - [VMEXIT_CR6_WRITE] = "CR6_WRITE", - [VMEXIT_CR7_WRITE] = "CR7_WRITE", - [VMEXIT_CR8_WRITE] = "CR8_WRITE", - [VMEXIT_CR9_WRITE] = "CR9_WRITE", - [VMEXIT_CR10_WRITE] = "CR10_WRITE", - [VMEXIT_CR11_WRITE] = "CR11_WRITE", - [VMEXIT_CR12_WRITE] = "CR12_WRITE", - [VMEXIT_CR13_WRITE] = "CR13_WRITE", - [VMEXIT_CR14_WRITE] = "CR14_WRITE", - [VMEXIT_CR15_WRITE] = "CR15_WRITE", - [VMEXIT_DR0_READ] = "DR0_READ", - [VMEXIT_DR1_READ] = "DR1_READ", - [VMEXIT_DR2_READ] = "DR2_READ", - [VMEXIT_DR3_READ] = "DR3_READ", - [VMEXIT_DR4_READ] = "DR4_READ", - [VMEXIT_DR5_READ] = "DR5_READ", - [VMEXIT_DR6_READ] = "DR6_READ", - [VMEXIT_DR7_READ] = "DR7_READ", - [VMEXIT_DR8_READ] = "DR8_READ", - [VMEXIT_DR9_READ] = "DR9_READ", - [VMEXIT_DR10_READ] = "DR10_READ", - [VMEXIT_DR11_READ] = "DR11_READ", - [VMEXIT_DR12_READ] = "DR12_READ", - [VMEXIT_DR13_READ] = "DR13_READ", - [VMEXIT_DR14_READ] = "DR14_READ", - [VMEXIT_DR15_READ] = "DR15_READ", - [VMEXIT_DR0_WRITE] = "DR0_WRITE", - [VMEXIT_DR1_WRITE] = "DR1_WRITE", - [VMEXIT_DR2_WRITE] = "DR2_WRITE", - [VMEXIT_DR3_WRITE] = "DR3_WRITE", - [VMEXIT_DR4_WRITE] = "DR4_WRITE", - [VMEXIT_DR5_WRITE] = "DR5_WRITE", - [VMEXIT_DR6_WRITE] = "DR6_WRITE", - [VMEXIT_DR7_WRITE] = "DR7_WRITE", - [VMEXIT_DR8_WRITE] = "DR8_WRITE", - [VMEXIT_DR9_WRITE] = "DR9_WRITE", - [VMEXIT_DR10_WRITE] = "DR10_WRITE", - [VMEXIT_DR11_WRITE] = "DR11_WRITE", - [VMEXIT_DR12_WRITE] = "DR12_WRITE", - [VMEXIT_DR13_WRITE] = "DR13_WRITE", - [VMEXIT_DR14_WRITE] = "DR14_WRITE", - [VMEXIT_DR15_WRITE] = "DR15_WRITE", - [VMEXIT_EXCEPTION_DE] = "EXCEPTION_DE", - [VMEXIT_EXCEPTION_DB] = "EXCEPTION_DB", - [VMEXIT_EXCEPTION_NMI] = "EXCEPTION_NMI", - [VMEXIT_EXCEPTION_BP] = "EXCEPTION_BP", - [VMEXIT_EXCEPTION_OF] = "EXCEPTION_OF", - [VMEXIT_EXCEPTION_BR] = "EXCEPTION_BR", - [VMEXIT_EXCEPTION_UD] = "EXCEPTION_UD", - [VMEXIT_EXCEPTION_NM] = "EXCEPTION_NM", - [VMEXIT_EXCEPTION_DF] = "EXCEPTION_DF", - [VMEXIT_EXCEPTION_09] = "EXCEPTION_09", - [VMEXIT_EXCEPTION_TS] = "EXCEPTION_TS", - [VMEXIT_EXCEPTION_NP] = "EXCEPTION_NP", - [VMEXIT_EXCEPTION_SS] = "EXCEPTION_SS", - [VMEXIT_EXCEPTION_GP] = "EXCEPTION_GP", - [VMEXIT_EXCEPTION_PF] = "EXCEPTION_PF", - [VMEXIT_EXCEPTION_15] = "EXCEPTION_15", - [VMEXIT_EXCEPTION_MF] = "EXCEPTION_MF", - [VMEXIT_EXCEPTION_AC] = "EXCEPTION_AC", - [VMEXIT_EXCEPTION_MC] = "EXCEPTION_MC", - [VMEXIT_EXCEPTION_XF] = "EXCEPTION_XF", - [VMEXIT_INTR] = "INTR", - [VMEXIT_NMI] = "NMI", - [VMEXIT_SMI] = "SMI", - [VMEXIT_INIT] = "INIT", - [VMEXIT_VINTR] = "VINTR", - [VMEXIT_CR0_SEL_WRITE] = "CR0_SEL_WRITE", - [VMEXIT_IDTR_READ] = "IDTR_READ", - [VMEXIT_GDTR_READ] = "GDTR_READ", - [VMEXIT_LDTR_READ] = "LDTR_READ", - [VMEXIT_TR_READ] = "TR_READ", - [VMEXIT_IDTR_WRITE] = "IDTR_WRITE", - [VMEXIT_GDTR_WRITE] = "GDTR_WRITE", - [VMEXIT_LDTR_WRITE] = "LDTR_WRITE", - [VMEXIT_TR_WRITE] = "TR_WRITE", - [VMEXIT_RDTSC] = "RDTSC", - [VMEXIT_RDPMC] = "RDPMC", - [VMEXIT_PUSHF] = "PUSHF", - [VMEXIT_POPF] = "POPF", - [VMEXIT_CPUID] = "CPUID", - [VMEXIT_RSM] = "RSM", - [VMEXIT_IRET] = "IRET", - [VMEXIT_SWINT] = "SWINT", - [VMEXIT_INVD] = "INVD", - [VMEXIT_PAUSE] = "PAUSE", - [VMEXIT_HLT] = "HLT", - [VMEXIT_INVLPG] = "INVLPG", - [VMEXIT_INVLPGA] = "INVLPGA", - [VMEXIT_IOIO] = "IOIO", - [VMEXIT_MSR] = "MSR", - [VMEXIT_TASK_SWITCH] = "TASK_SWITCH", - [VMEXIT_FERR_FREEZE] = "FERR_FREEZE", - [VMEXIT_SHUTDOWN] = "SHUTDOWN", - [VMEXIT_VMRUN] = "VMRUN", - [VMEXIT_VMMCALL] = "VMMCALL", - [VMEXIT_VMLOAD] = "VMLOAD", - [VMEXIT_VMSAVE] = "VMSAVE", - [VMEXIT_STGI] = "STGI", - [VMEXIT_CLGI] = "CLGI", - [VMEXIT_SKINIT] = "SKINIT", - [VMEXIT_RDTSCP] = "RDTSCP", - [VMEXIT_ICEBP] = "ICEBP", - [VMEXIT_NPF] = "NPF" -}; -#endif /* SVM_EXTRA_DEBUG */ - -#ifdef SVM_WALK_GUEST_PAGES -void walk_shadow_and_guest_pt(unsigned long gva) -{ - l2_pgentry_t gpde; - l2_pgentry_t spde; - l1_pgentry_t gpte; - l1_pgentry_t spte; - struct vcpu *v = current; - struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb; - paddr_t gpa; - - gpa = paging_gva_to_gpa(current, gva); - printk("gva = %lx, gpa=%"PRIpaddr", gCR3=%x\n", gva, gpa, (u32)vmcb->cr3); - if( !svm_paging_enabled(v) || mmio_space(gpa) ) - return; - - /* let's dump the guest and shadow page info */ - - __guest_get_l2e(v, gva, &gpde); - printk( "G-PDE = %x, flags=%x\n", gpde.l2, l2e_get_flags(gpde) ); - __shadow_get_l2e( v, gva, &spde ); - printk( "S-PDE = %x, flags=%x\n", spde.l2, l2e_get_flags(spde) ); - - if ( unlikely(!(l2e_get_flags(gpde) & _PAGE_PRESENT)) ) - return; - - spte = l1e_empty(); - - /* This is actually overkill - we only need to ensure the hl2 is in-sync.*/ - shadow_sync_va(v, gva); - - gpte.l1 = 0; - __copy_from_user(&gpte, &__linear_l1_table[ l1_linear_offset(gva) ], - sizeof(gpte) ); - printk( "G-PTE = %x, flags=%x\n", gpte.l1, l1e_get_flags(gpte) ); - - BUG(); // need to think about this, and convert usage of - // phys_to_machine_mapping to use pagetable format... - __copy_from_user( &spte, &phys_to_machine_mapping[ l1e_get_pfn( gpte ) ], - sizeof(spte) ); - - printk( "S-PTE = %x, flags=%x\n", spte.l1, l1e_get_flags(spte)); -} -#endif /* SVM_WALK_GUEST_PAGES */ - - asmlinkage void svm_vmexit_handler(struct cpu_user_regs *regs) { unsigned int exit_reason; unsigned long eip; struct vcpu *v = current; - int do_debug = 0; - struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb; - - ASSERT(vmcb); + struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb; + int inst_len; exit_reason = vmcb->exitcode; save_svm_cpu_user_regs(v, regs); HVMTRACE_2D(VMEXIT, v, vmcb->rip, exit_reason); - if (exit_reason == VMEXIT_INVALID) + if ( unlikely(exit_reason == VMEXIT_INVALID) ) { svm_dump_vmcb(__func__, vmcb); goto exit_and_crash; } -#ifdef SVM_EXTRA_DEBUG - { -#if defined(__i386__) -#define rip eip -#endif - - static unsigned long intercepts_counter = 0; - - if (svm_dbg_on && exit_reason == VMEXIT_EXCEPTION_PF) - { - if (svm_paging_enabled(v) && - !mmio_space( - paging_gva_to_gfn(current, vmcb->exitinfo2) << PAGE_SHIFT)) - { - printk("I%08ld,ExC=%s(%d),IP=%x:%"PRIx64"," - "I1=%"PRIx64",I2=%"PRIx64",INT=%"PRIx64", " - "gpa=%"PRIx64"\n", intercepts_counter, - exit_reasons[exit_reason], exit_reason, regs->cs, - (u64)regs->rip, - (u64)vmcb->exitinfo1, - (u64)vmcb->exitinfo2, - (u64)vmcb->exitintinfo.bytes, - (((u64)paging_gva_to_gfn(current, vmcb->exitinfo2) - << PAGE_SHIFT) | (vmcb->exitinfo2 & ~PAGE_MASK))); - } - else - { - printk("I%08ld,ExC=%s(%d),IP=%x:%"PRIx64"," - "I1=%"PRIx64",I2=%"PRIx64",INT=%"PRIx64"\n", - intercepts_counter, - exit_reasons[exit_reason], exit_reason, regs->cs, - (u64)regs->rip, - (u64)vmcb->exitinfo1, - (u64)vmcb->exitinfo2, - (u64)vmcb->exitintinfo.bytes ); - } - } - else if ( svm_dbg_on - && exit_reason != VMEXIT_IOIO - && exit_reason != VMEXIT_INTR) - { - - if (exit_reasons[exit_reason]) - { - printk("I%08ld,ExC=%s(%d),IP=%x:%"PRIx64"," - "I1=%"PRIx64",I2=%"PRIx64",INT=%"PRIx64"\n", - intercepts_counter, - exit_reasons[exit_reason], exit_reason, regs->cs, - (u64)regs->rip, - (u64)vmcb->exitinfo1, - (u64)vmcb->exitinfo2, - (u64)vmcb->exitintinfo.bytes); - } - else - { - printk("I%08ld,ExC=%d(0x%x),IP=%x:%"PRIx64"," _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |