diff --git a/Config.mk b/Config.mk index 7474ce19c5..6f9f970fe6 100644 --- a/Config.mk +++ b/Config.mk @@ -73,9 +73,10 @@ ACM_SECURITY ?= n ACM_DEFAULT_SECURITY_POLICY ?= ACM_NULL_POLICY # Optional components -XENSTAT_XENTOP ?= y -VTPM_TOOLS ?= n +XENSTAT_XENTOP ?= y +VTPM_TOOLS ?= n LIBXENAPI_BINDINGS ?= n -XENFB_TOOLS ?= n +XENFB_TOOLS ?= n +PYTHON_TOOLS ?= y -include $(XEN_ROOT)/.config diff --git a/README b/README index 418d72fc30..b1200f7b29 100644 --- a/README +++ b/README @@ -92,6 +92,8 @@ provided by your Linux distributor: * Development install of zlib (e.g., zlib-dev) * Development install of Python v2.3 or later (e.g., python-dev) * Development install of curses (e.g., libncurses-dev) + * Development install of openssl (e.g., openssl-dev) + * Development install of x11 (e.g. xorg-x11-dev) * bridge-utils package (/sbin/brctl) * iproute package (/sbin/ip) * hotplug or udev diff --git a/config/StdGNU.mk b/config/StdGNU.mk index 32a37b44fa..8c947f4832 100644 --- a/config/StdGNU.mk +++ b/config/StdGNU.mk @@ -12,9 +12,9 @@ OBJDUMP = $(CROSS_COMPILE)objdump MSGFMT = msgfmt INSTALL = install -INSTALL_DIR = $(INSTALL) -d -m0755 -INSTALL_DATA = $(INSTALL) -m0644 -INSTALL_PROG = $(INSTALL) -m0755 +INSTALL_DIR = $(INSTALL) -d -m0755 -p +INSTALL_DATA = $(INSTALL) -m0644 -p +INSTALL_PROG = $(INSTALL) -m0755 -p LIB64DIR = lib64 diff --git a/config/SunOS.mk b/config/SunOS.mk index 77e4b24825..5c12fd4c23 100644 --- a/config/SunOS.mk +++ b/config/SunOS.mk @@ -14,9 +14,9 @@ MSGFMT = gmsgfmt SHELL = bash INSTALL = ginstall -INSTALL_DIR = $(INSTALL) -d -m0755 -INSTALL_DATA = $(INSTALL) -m0644 -INSTALL_PROG = $(INSTALL) -m0755 +INSTALL_DIR = $(INSTALL) -d -m0755 -p +INSTALL_DATA = $(INSTALL) -m0644 -p +INSTALL_PROG = $(INSTALL) -m0755 -p LIB64DIR = lib/amd64 diff --git a/docs/misc/dump-core-format.txt b/docs/misc/dump-core-format.txt new file mode 100644 index 0000000000..99384ca94a --- /dev/null +++ b/docs/misc/dump-core-format.txt @@ -0,0 +1,231 @@ +xen dump-core format + Written by Isaku Yamahata Feb. 2007 + + +Introduction +------------ +With xm dump-core command, the guest domain's core can be created as a file. +Its format was changed to be based on ELF format because elf format is easily +extensible and handy. This document describes the new format. +In this document the new format is called new xen dump-core format, +xen dump-core format or simply dump-core format. The file of xen dump-core +format is called xen dump-core file or dump-core file. + +The usual process core file includes program headers and no section header. +On the other hand the xen dump-core file includes no program headers and +some sections because of its peculiar requirements. + + +Reference +--------- +For ELF format itself, see Tool Interface Standard(TIS) Executable and +Linking Format(ELF) Specification version 1.2. +For xen related structure, please see the xen header files. + + +Elf header +---------- +The elf header members are set as follows + e_ident[EI_CLASS] = ELFCLASS64 = 2 + e_ident[EI_OSABI] = ELFOSABI_SYSV = 0 + e_type = ET_CORE = 4 +ELFCLASS64 is always used independent of architecture. +e_ident[EI_DATA] and e_flags are set according to the dumping system's +architecture. Other members are set as usual. + +Sections +-------- +Currently the following sections are defined. Some sections are optional. + +".note.Xen" section + name ".note.Xen" + type SHT_NOTE + description + This section is used as note section to store xen dump-core + file specific informations. The each detailed informations are + described in note section. This section must exist. + +".xen_prstatus" section + name ".xen_prstatus" + type SHT_PROGBITS + structure array of vcpu_guest_context_t + description + This section stores the array of vcpu_guest_context_t + which is obtained by XEN_DOMCTL_getvcpucontext hypercall + when the xen dump-core file is created. + The size of array is stored in xch_nr_vcpus member of header + note descriptor in .note.Xen note section. + This section must exist. + +".xen_shared_info" section + name ".xen_shared_info" + type SHT_PROGBITS + structure shared_info_t + description + This section stores the contents of shared info page + of a domain. This section is optional. + +".xen_p2m" section + name ".xen_p2m" + type SHT_PROGBITS + structure array of struct xen_dumpcore_p2m + struct xen_dumpcore_p2m { + uint64_t pfn; + uint64_t gmfn; + }; + description + This elements represents the frame number of the page + in .xen_pages section. + pfn: guest-specific pseudo-physical frame number + gmfn: machine physical frame number + The size of arrays is stored in xch_nr_pages member of header + note descriptor in .note.Xen note section. + There is no rule about the order. Analysis tools must no rely + on its order. + This section must exist when the domain is non auto + translated physmap mode. Currently x86 paravirtualized domain. + +".xen_pfn" section + name ".xen_pfn" + type SHT_PROGBITS + structure array of uint64_t + description + This elements represents the frame number of the page + in .xen_pages section. + The size of arrays is stored in xch_nr_pages member of header + note descriptor in .note.Xen note section. + There is no rule about the order. Analysis tools must no rely + on its order. + This section must exist when the domain is auto translated + physmap mode. Currently x86 full virtualized domain and + ia64 domain. + +".xen_pages" section + name ".xen_pages" + type SHT_PROGBITS + structure array of page where page is page size byte array + description + This section includes the contents of pages. + The corresponding address is described in .xen_p2m section + or .xen_pfn section. + The page size is stored in xch_page_size member of header note + descriptor in .note.Xen section. + The array size is stored in xch_nr_pages member of header note + descriptor in .note.Xen section. + This section must exist. + + +".xen_ia64_mapped_regs" section + name ".xen_ia64_mapped_regs" + type SHT_PROGBITS + structure array of mapped_regs_t + description + This section stores the array of mapped_regs_t. + The size of array is stored in xch_nr_vcpus member of header + note descriptor in .note.Xen note section. + This section is ia64 specific and must exist for ia64 domain. + This section must not exist for non-ia64 domain. + + +note section +------------ +The note types are defined in xen/include/public/elfnote.h. +The note descriptors are defined in tools/libxc/xc_core.h +Currently the following note informations are defined. + + +elf note section + +"Xen" is used as elf note name in elf note info + namesz 4 + name "Xen" (null-terminated) + + +Descriptors + +none note descriptor + type XEN_ELFNOTE_DUMPCORE_NONE = 0x2000000 + structure struct xen_dumpcore_elfnote_none_desc { + /* nothing is defined */ + }; + description + This note descriptor is defined to just indicate that this + file is xen dump-core format without any specific information. + This note information must exist. + +header note descriptor + type XEN_ELFNOTE_DUMPCORE_HEADER = 0x2000001 + structure struct xen_dumpcore_elfnote_header_desc { + uint64_t xch_magic; + uint64_t xch_nr_vcpus; + uint64_t xch_nr_pages; + uint64_t xch_page_size; + }; + description + This note descriptor stores basic information of the domain. + xch_magic magic number + XC_CORE_MAGIC = 0xF00FEBED for paravirtualized domain + XC_CORE_MAGIC_HVM = 0xF00FEBEE for full virtualized domain + xch_nr_vcpus the number of vcpus + xch_nr_pages the number of pages + xch_page_size guest OS's page size + This note information must exist. + +xen_version descriptor + type XEN_ELFNOTE_DUMPCORE_XEN_VERSION = 0x2000002 + structure struct xen_dumpcore_elfnote_xen_version_desc { + uint64_t major_version; + uint64_t minor_version; + xen_extraversion_t extra_version; + xen_compile_info_t compile_info; + xen_capabilities_info_t capabilities; + xen_changeset_info_t changeset; + xen_platform_parameters_t platform_parameters; + uint64_t pagesize; + }; + description + This note descriptor stores basic information about xen + hypervisor. The each members store the result of + __HYPERVISOR_xen_version hypercall. + major_version 16msb bit of the result of XENVER_version + minor_version 16lsb bit of the result of XENVER_version + uint64_t is used to make struct + xen_dumpcore_elfnote_xen_version_desc independent + on 32bit/64bit instead of uint32_t. + extra_version the result of XENVER_extraversion + compile_info the result of XENVER_compile_info + capabilities the result of XENVER_capabilities + changeset the result of XENVER_changeset + platform_parameters + the result of XENVER_platform_parameters + pagesize the result of XENVER_pagesize + This note information must exist. + +format_version descriptor + type XEN_ELFNOTE_DUMPCORE_FORMAT_VERSION = 0x2000003 + structure struct xen_dumpcore_elfnote_format_version_desc { + uint64_t version; + }; + description + This note descriptor stores xen dump-core format version. + The 32msb bit is major version and the 32lsb bit is minor + version. + The minor version will be incremented when the format + is changed in compatible way. e.g. new sections, new note + descriptors are added. + the major version will be incremented when the format is + changed in incompatible way. + This note information must exit. Analysis tools should check + this format version. + This note information must exist. + + +Format version history +---------------------- +Currently only (major, minor) = (0, 1) is used. +[When the format is changed, it would be described here.] + +(0, 1) update +- EI_CLASS member of elf header was changed to ELFCLASS64 independent of + architecture. This is mainly for x86_32pae. + The format version isn't bumped because analysis tools can distinguish it. diff --git a/docs/xen-api/xenapi-datamodel.tex b/docs/xen-api/xenapi-datamodel.tex index 82c3bea252..cce4ae5cc7 100644 --- a/docs/xen-api/xenapi-datamodel.tex +++ b/docs/xen-api/xenapi-datamodel.tex @@ -26,6 +26,7 @@ Name & Description \\ {\tt task} & A long-running asynchronous task \\ {\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) \\ {\tt host} & A physical host \\ {\tt host\_metrics} & The metrics associated with a host \\ {\tt host\_cpu} & A physical CPU \\ @@ -61,8 +62,6 @@ VBD.VM & VM.VBDs & one-to-many\\ crashdump.VM & VM.crash\_dumps & one-to-many\\ VIF.VM & VM.VIFs & one-to-many\\ VIF.network & network.VIFs & one-to-many\\ -host.metrics & host\_metrics.host & one-to-one\\ -PIF.metrics & PIF\_metrics.PIF & one-to-one\\ PIF.host & host.PIFs & one-to-many\\ PIF.network & network.PIFs & one-to-many\\ SR.VDIs & VDI.SR & many-to-one\\ @@ -1098,10 +1097,11 @@ $\mathit{RW}$ & {\tt platform/localtime} & bool & set RTC to local time \\ $\mathit{RW}$ & {\tt platform/clock\_offset} & bool & timeshift applied to guest's clock \\ $\mathit{RW}$ & {\tt platform/enable\_audio} & bool & emulate audio \\ $\mathit{RO}_\mathit{ins}$ & {\tt PCI\_bus} & string & PCI bus path for pass-through devices \\ -$\mathit{RO}_\mathit{run}$ & {\tt tools\_version} & (string $\rightarrow$ string) Map & versions of installed paravirtualised drivers \\ $\mathit{RW}$ & {\tt other\_config} & (string $\rightarrow$ string) Map & additional configuration \\ +$\mathit{RO}_\mathit{run}$ & {\tt domid} & int & domain ID (if available, -1 otherwise) \\ $\mathit{RO}_\mathit{run}$ & {\tt is\_control\_domain} & bool & true if this is a control domain (domain 0 or a driver domain) \\ $\mathit{RO}_\mathit{run}$ & {\tt metrics} & VM\_metrics ref & metrics associated with this VM. \\ +$\mathit{RO}_\mathit{run}$ & {\tt guest\_metrics} & VM\_guest\_metrics ref & metrics associated with the running guest \\ \hline \end{longtable} \subsection{Additional RPCs associated with class: VM} @@ -3796,38 +3796,6 @@ string } -value of the field -\vspace{0.3cm} -\vspace{0.3cm} -\vspace{0.3cm} -\subsubsection{RPC name:~get\_tools\_version} - -{\bf Overview:} -Get the tools\_version field of the given VM. - - \noindent {\bf Signature:} -\begin{verbatim} ((string -> string) Map) get_tools_version (session_id s, VM ref self)\end{verbatim} - - -\noindent{\bf Arguments:} - - -\vspace{0.3cm} -\begin{tabular}{|c|c|p{7cm}|} - \hline -{\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VM ref } & self & 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} @@ -3966,6 +3934,38 @@ void +\vspace{0.3cm} +\vspace{0.3cm} +\vspace{0.3cm} +\subsubsection{RPC name:~get\_domid} + +{\bf Overview:} +Get the domid field of the given VM. + + \noindent {\bf Signature:} +\begin{verbatim} int get_domid (session_id s, VM ref self)\end{verbatim} + + +\noindent{\bf Arguments:} + + +\vspace{0.3cm} +\begin{tabular}{|c|c|p{7cm}|} + \hline +{\bf type} & {\bf name} & {\bf description} \\ \hline +{\tt VM ref } & self & reference to the object \\ \hline + +\end{tabular} + +\vspace{0.3cm} + + \noindent {\bf Return Type:} +{\tt +int +} + + +value of the field \vspace{0.3cm} \vspace{0.3cm} \vspace{0.3cm} @@ -4029,6 +4029,38 @@ VM\_metrics ref } +value of the field +\vspace{0.3cm} +\vspace{0.3cm} +\vspace{0.3cm} +\subsubsection{RPC name:~get\_guest\_metrics} + +{\bf Overview:} +Get the guest\_metrics field of the given VM. + + \noindent {\bf Signature:} +\begin{verbatim} (VM_guest_metrics ref) get_guest_metrics (session_id s, VM ref self)\end{verbatim} + + +\noindent{\bf Arguments:} + + +\vspace{0.3cm} +\begin{tabular}{|c|c|p{7cm}|} + \hline +{\bf type} & {\bf name} & {\bf description} \\ \hline +{\tt VM ref } & self & reference to the object \\ \hline + +\end{tabular} + +\vspace{0.3cm} + + \noindent {\bf Return Type:} +{\tt +VM\_guest\_metrics ref +} + + value of the field \vspace{0.3cm} \vspace{0.3cm} @@ -4214,6 +4246,27 @@ $\mathit{RO}_\mathit{run}$ & {\tt VCPUs/utilisation} & (int $\rightarrow$ float \hline \end{longtable} \subsection{Additional RPCs associated with class: VM\_metrics} +\subsubsection{RPC name:~get\_all} + +{\bf Overview:} +Return a list of all the VM\_metrics instances known to the system. + + \noindent {\bf Signature:} +\begin{verbatim} ((VM_metrics ref) Set) get_all (session_id s)\end{verbatim} + + +\vspace{0.3cm} + + \noindent {\bf Return Type:} +{\tt +(VM\_metrics ref) Set +} + + +references to all objects +\vspace{0.3cm} +\vspace{0.3cm} +\vspace{0.3cm} \subsubsection{RPC name:~get\_uuid} {\bf Overview:} @@ -4402,6 +4455,338 @@ VM\_metrics record } +all fields from the object +\vspace{0.3cm} +\vspace{0.3cm} +\vspace{0.3cm} + +\vspace{1cm} +\newpage +\section{Class: VM\_guest\_metrics} +\subsection{Fields for class: VM\_guest\_metrics} +\begin{longtable}{|lllp{0.38\textwidth}|} +\hline +\multicolumn{1}{|l}{Name} & \multicolumn{3}{l|}{\bf VM\_guest\_metrics} \\ +\multicolumn{1}{|l}{Description} & \multicolumn{3}{l|}{\parbox{11cm}{\em +The metrics reported by the guest (as opposed to inferred from outside).}} \\ +\hline +Quals & Field & Type & Description \\ +\hline +$\mathit{RO}_\mathit{run}$ & {\tt uuid} & string & unique identifier/object reference \\ +$\mathit{RO}_\mathit{run}$ & {\tt os\_version} & (string $\rightarrow$ string) Map & version of the OS \\ +$\mathit{RO}_\mathit{run}$ & {\tt PV\_drivers\_version} & (string $\rightarrow$ string) Map & version of the PV drivers \\ +$\mathit{RO}_\mathit{run}$ & {\tt memory} & (string $\rightarrow$ string) Map & free/used/total memory \\ +$\mathit{RO}_\mathit{run}$ & {\tt disks} & (string $\rightarrow$ string) Map & disk configuration/free space \\ +$\mathit{RO}_\mathit{run}$ & {\tt networks} & (string $\rightarrow$ string) Map & network configuration \\ +$\mathit{RO}_\mathit{run}$ & {\tt other} & (string $\rightarrow$ string) Map & anything else \\ +\hline +\end{longtable} +\subsection{Additional RPCs associated with class: VM\_guest\_metrics} +\subsubsection{RPC name:~get\_all} + +{\bf Overview:} +Return a list of all the VM\_guest\_metrics instances known to the system. + + \noindent {\bf Signature:} +\begin{verbatim} ((VM_guest_metrics ref) Set) get_all (session_id s)\end{verbatim} + + +\vspace{0.3cm} + + \noindent {\bf Return Type:} +{\tt +(VM\_guest\_metrics ref) Set +} + + +references to all objects +\vspace{0.3cm} +\vspace{0.3cm} +\vspace{0.3cm} +\subsubsection{RPC name:~get\_uuid} + +{\bf Overview:} +Get the uuid field of the given VM\_guest\_metrics. + + \noindent {\bf Signature:} +\begin{verbatim} string get_uuid (session_id s, VM_guest_metrics ref self)\end{verbatim} + + +\noindent{\bf Arguments:} + + +\vspace{0.3cm} +\begin{tabular}{|c|c|p{7cm}|} + \hline +{\bf type} & {\bf name} & {\bf description} \\ \hline +{\tt VM\_guest\_metrics ref } & self & reference to the object \\ \hline + +\end{tabular} + +\vspace{0.3cm} + + \noindent {\bf Return Type:} +{\tt +string +} + + +value of the field +\vspace{0.3cm} +\vspace{0.3cm} +\vspace{0.3cm} +\subsubsection{RPC name:~get\_os\_version} + +{\bf Overview:} +Get the os\_version field of the given VM\_guest\_metrics. + + \noindent {\bf Signature:} +\begin{verbatim} ((string -> string) Map) get_os_version (session_id s, VM_guest_metrics ref self)\end{verbatim} + + +\noindent{\bf Arguments:} + + +\vspace{0.3cm} +\begin{tabular}{|c|c|p{7cm}|} + \hline +{\bf type} & {\bf name} & {\bf description} \\ \hline +{\tt VM\_guest\_metrics 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:~get\_PV\_drivers\_version} + +{\bf Overview:} +Get the PV\_drivers\_version field of the given VM\_guest\_metrics. + + \noindent {\bf Signature:} +\begin{verbatim} ((string -> string) Map) get_PV_drivers_version (session_id s, VM_guest_metrics ref self)\end{verbatim} + + +\noindent{\bf Arguments:} + + +\vspace{0.3cm} +\begin{tabular}{|c|c|p{7cm}|} + \hline +{\bf type} & {\bf name} & {\bf description} \\ \hline +{\tt VM\_guest\_metrics 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:~get\_memory} + +{\bf Overview:} +Get the memory field of the given VM\_guest\_metrics. + + \noindent {\bf Signature:} +\begin{verbatim} ((string -> string) Map) get_memory (session_id s, VM_guest_metrics ref self)\end{verbatim} + + +\noindent{\bf Arguments:} + + +\vspace{0.3cm} +\begin{tabular}{|c|c|p{7cm}|} + \hline +{\bf type} & {\bf name} & {\bf description} \\ \hline +{\tt VM\_guest\_metrics 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:~get\_disks} + +{\bf Overview:} +Get the disks field of the given VM\_guest\_metrics. + + \noindent {\bf Signature:} +\begin{verbatim} ((string -> string) Map) get_disks (session_id s, VM_guest_metrics ref self)\end{verbatim} + + +\noindent{\bf Arguments:} + + +\vspace{0.3cm} +\begin{tabular}{|c|c|p{7cm}|} + \hline +{\bf type} & {\bf name} & {\bf description} \\ \hline +{\tt VM\_guest\_metrics 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:~get\_networks} + +{\bf Overview:} +Get the networks field of the given VM\_guest\_metrics. + + \noindent {\bf Signature:} +\begin{verbatim} ((string -> string) Map) get_networks (session_id s, VM_guest_metrics ref self)\end{verbatim} + + +\noindent{\bf Arguments:} + + +\vspace{0.3cm} +\begin{tabular}{|c|c|p{7cm}|} + \hline +{\bf type} & {\bf name} & {\bf description} \\ \hline +{\tt VM\_guest\_metrics 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:~get\_other} + +{\bf Overview:} +Get the other field of the given VM\_guest\_metrics. + + \noindent {\bf Signature:} +\begin{verbatim} ((string -> string) Map) get_other (session_id s, VM_guest_metrics ref self)\end{verbatim} + + +\noindent{\bf Arguments:} + + +\vspace{0.3cm} +\begin{tabular}{|c|c|p{7cm}|} + \hline +{\bf type} & {\bf name} & {\bf description} \\ \hline +{\tt VM\_guest\_metrics 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:~get\_by\_uuid} + +{\bf Overview:} +Get a reference to the VM\_guest\_metrics instance with the specified UUID. + + \noindent {\bf Signature:} +\begin{verbatim} (VM_guest_metrics ref) get_by_uuid (session_id s, string uuid)\end{verbatim} + + +\noindent{\bf Arguments:} + + +\vspace{0.3cm} +\begin{tabular}{|c|c|p{7cm}|} + \hline +{\bf type} & {\bf name} & {\bf description} \\ \hline +{\tt string } & uuid & UUID of object to return \\ \hline + +\end{tabular} + +\vspace{0.3cm} + + \noindent {\bf Return Type:} +{\tt +VM\_guest\_metrics ref +} + + +reference to the object +\vspace{0.3cm} +\vspace{0.3cm} +\vspace{0.3cm} +\subsubsection{RPC name:~get\_record} + +{\bf Overview:} +Get a record containing the current state of the given VM\_guest\_metrics. + + \noindent {\bf Signature:} +\begin{verbatim} (VM_guest_metrics record) get_record (session_id s, VM_guest_metrics ref self)\end{verbatim} + + +\noindent{\bf Arguments:} + + +\vspace{0.3cm} +\begin{tabular}{|c|c|p{7cm}|} + \hline +{\bf type} & {\bf name} & {\bf description} \\ \hline +{\tt VM\_guest\_metrics ref } & self & reference to the object \\ \hline + +\end{tabular} + +\vspace{0.3cm} + + \noindent {\bf Return Type:} +{\tt +VM\_guest\_metrics record +} + + all fields from the object \vspace{0.3cm} \vspace{0.3cm} @@ -4422,8 +4807,13 @@ Quals & Field & Type & Description \\ $\mathit{RO}_\mathit{run}$ & {\tt uuid} & string & unique identifier/object reference \\ $\mathit{RW}$ & {\tt name/label} & string & a human-readable name \\ $\mathit{RW}$ & {\tt name/description} & string & a notes field containg human-readable description \\ +$\mathit{RO}_\mathit{run}$ & {\tt API\_version/major} & int & major version number \\ +$\mathit{RO}_\mathit{run}$ & {\tt API\_version/minor} & int & minor version number \\ +$\mathit{RO}_\mathit{run}$ & {\tt API\_version/vendor} & string & identification of vendor \\ +$\mathit{RO}_\mathit{run}$ & {\tt API\_version/vendor\_implementation} & (string $\rightarrow$ string) Map & details of vendor implementation \\ $\mathit{RO}_\mathit{run}$ & {\tt software\_version} & (string $\rightarrow$ string) Map & version strings \\ $\mathit{RW}$ & {\tt other\_config} & (string $\rightarrow$ string) Map & additional configuration \\ +$\mathit{RO}_\mathit{run}$ & {\tt capabilities} & string Set & Xen capabilities \\ $\mathit{RO}_\mathit{run}$ & {\tt supported\_bootloaders} & string Set & a list of the bootloaders installed on the machine \\ $\mathit{RO}_\mathit{run}$ & {\tt resident\_VMs} & (VM ref) Set & list of VMs currently resident on host \\ $\mathit{RW}$ & {\tt logging} & (string $\rightarrow$ string) Map & logging configuration \\ @@ -4781,6 +5171,134 @@ void +\vspace{0.3cm} +\vspace{0.3cm} +\vspace{0.3cm} +\subsubsection{RPC name:~get\_API\_version\_major} + +{\bf Overview:} +Get the API\_version/major field of the given host. + + \noindent {\bf Signature:} +\begin{verbatim} int get_API_version_major (session_id s, host 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 host ref } & self & reference to the object \\ \hline + +\end{tabular} + +\vspace{0.3cm} + + \noindent {\bf Return Type:} +{\tt +int +} + + +value of the field +\vspace{0.3cm} +\vspace{0.3cm} +\vspace{0.3cm} +\subsubsection{RPC name:~get\_API\_version\_minor} + +{\bf Overview:} +Get the API\_version/minor field of the given host. + + \noindent {\bf Signature:} +\begin{verbatim} int get_API_version_minor (session_id s, host 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 host ref } & self & reference to the object \\ \hline + +\end{tabular} + +\vspace{0.3cm} + + \noindent {\bf Return Type:} +{\tt +int +} + + +value of the field +\vspace{0.3cm} +\vspace{0.3cm} +\vspace{0.3cm} +\subsubsection{RPC name:~get\_API\_version\_vendor} + +{\bf Overview:} +Get the API\_version/vendor field of the given host. + + \noindent {\bf Signature:} +\begin{verbatim} string get_API_version_vendor (session_id s, host 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 host ref } & self & reference to the object \\ \hline + +\end{tabular} + +\vspace{0.3cm} + + \noindent {\bf Return Type:} +{\tt +string +} + + +value of the field +\vspace{0.3cm} +\vspace{0.3cm} +\vspace{0.3cm} +\subsubsection{RPC name:~get\_API\_version\_vendor\_implementation} + +{\bf Overview:} +Get the API\_version/vendor\_implementation field of the given host. + + \noindent {\bf Signature:} +\begin{verbatim} ((string -> string) Map) get_API_version_vendor_implementation (session_id s, host 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 host 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} @@ -4950,6 +5468,38 @@ void +\vspace{0.3cm} +\vspace{0.3cm} +\vspace{0.3cm} +\subsubsection{RPC name:~get\_capabilities} + +{\bf Overview:} +Get the capabilities field of the given host. + + \noindent {\bf Signature:} +\begin{verbatim} (string Set) get_capabilities (session_id s, host 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 host ref } & self & reference to the object \\ \hline + +\end{tabular} + +\vspace{0.3cm} + + \noindent {\bf Return Type:} +{\tt +string Set +} + + +value of the field \vspace{0.3cm} \vspace{0.3cm} \vspace{0.3cm} @@ -5524,12 +6074,32 @@ The metrics associated with a host.}} \\ Quals & Field & Type & Description \\ \hline $\mathit{RO}_\mathit{run}$ & {\tt uuid} & string & unique identifier/object reference \\ -$\mathit{RO}_\mathit{ins}$ & {\tt host} & host ref & Host to which these metrics apply \\ $\mathit{RO}_\mathit{run}$ & {\tt memory/total} & int & Host's total memory (bytes) \\ $\mathit{RO}_\mathit{run}$ & {\tt memory/free} & int & Host's free memory (bytes) \\ \hline \end{longtable} \subsection{Additional RPCs associated with class: host\_metrics} +\subsubsection{RPC name:~get\_all} + +{\bf Overview:} +Return a list of all the host\_metrics instances known to the system. + + \noindent {\bf Signature:} +\begin{verbatim} ((host_metrics ref) Set) get_all (session_id s)\end{verbatim} + + +\vspace{0.3cm} + + \noindent {\bf Return Type:} +{\tt +(host\_metrics ref) Set +} + + +references to all objects +\vspace{0.3cm} +\vspace{0.3cm} +\vspace{0.3cm} \subsubsection{RPC name:~get\_uuid} {\bf Overview:} @@ -5558,38 +6128,6 @@ string } -value of the field -\vspace{0.3cm} -\vspace{0.3cm} -\vspace{0.3cm} -\subsubsection{RPC name:~get\_host} - -{\bf Overview:} -Get the host field of the given host\_metrics. - - \noindent {\bf Signature:} -\begin{verbatim} (host ref) get_host (session_id s, host_metrics 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 host\_metrics ref } & self & reference to the object \\ \hline - -\end{tabular} - -\vspace{0.3cm} - - \noindent {\bf Return Type:} -{\tt -host ref -} - - value of the field \vspace{0.3cm} \vspace{0.3cm} @@ -5735,15 +6273,38 @@ all fields from the object Quals & Field & Type & Description \\ \hline $\mathit{RO}_\mathit{run}$ & {\tt uuid} & string & unique identifier/object reference \\ -$\mathit{RO}_\mathit{ins}$ & {\tt host} & host ref & the host the CPU is in \\ -$\mathit{RO}_\mathit{ins}$ & {\tt number} & int & the number of the physical CPU within the host \\ -$\mathit{RO}_\mathit{ins}$ & {\tt vendor} & string & the vendor of the physical CPU \\ -$\mathit{RO}_\mathit{ins}$ & {\tt speed} & int & the speed of the physical CPU \\ -$\mathit{RO}_\mathit{ins}$ & {\tt modelname} & string & the model name of the physical CPU \\ +$\mathit{RO}_\mathit{run}$ & {\tt host} & host ref & the host the CPU is in \\ +$\mathit{RO}_\mathit{run}$ & {\tt number} & int & the number of the physical CPU within the host \\ +$\mathit{RO}_\mathit{run}$ & {\tt vendor} & string & the vendor of the physical CPU \\ +$\mathit{RO}_\mathit{run}$ & {\tt speed} & int & the speed of the physical CPU \\ +$\mathit{RO}_\mathit{run}$ & {\tt modelname} & string & the model name of the physical CPU \\ +$\mathit{RO}_\mathit{run}$ & {\tt stepping} & string & the stepping of the physical CPU \\ +$\mathit{RO}_\mathit{run}$ & {\tt flags} & string & the flags of the physical CPU \\ $\mathit{RO}_\mathit{run}$ & {\tt utilisation} & float & the current CPU utilisation \\ \hline \end{longtable} \subsection{Additional RPCs associated with class: host\_cpu} +\subsubsection{RPC name:~get\_all} + +{\bf Overview:} +Return a list of all the host\_cpus known to the system. + + \noindent {\bf Signature:} +\begin{verbatim} ((host_cpu ref) Set) get_all (session_id s)\end{verbatim} + + +\vspace{0.3cm} + + \noindent {\bf Return Type:} +{\tt +(host\_cpu ref) Set +} + + +references to all objects +\vspace{0.3cm} +\vspace{0.3cm} +\vspace{0.3cm} \subsubsection{RPC name:~get\_uuid} {\bf Overview:} @@ -5932,6 +6493,70 @@ string } +value of the field +\vspace{0.3cm} +\vspace{0.3cm} +\vspace{0.3cm} +\subsubsection{RPC name:~get\_stepping} + +{\bf Overview:} +Get the stepping field of the given host\_cpu. + + \noindent {\bf Signature:} +\begin{verbatim} string get_stepping (session_id s, host_cpu 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 host\_cpu ref } & self & reference to the object \\ \hline + +\end{tabular} + +\vspace{0.3cm} + + \noindent {\bf Return Type:} +{\tt +string +} + + +value of the field +\vspace{0.3cm} +\vspace{0.3cm} +\vspace{0.3cm} +\subsubsection{RPC name:~get\_flags} + +{\bf Overview:} +Get the flags field of the given host\_cpu. + + \noindent {\bf Signature:} +\begin{verbatim} string get_flags (session_id s, host_cpu 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 host\_cpu ref } & self & reference to the object \\ \hline + +\end{tabular} + +\vspace{0.3cm} + + \noindent {\bf Return Type:} +{\tt +string +} + + value of the field \vspace{0.3cm} \vspace{0.3cm} @@ -5965,70 +6590,6 @@ float value of the field -\vspace{0.3cm} -\vspace{0.3cm} -\vspace{0.3cm} -\subsubsection{RPC name:~create} - -{\bf Overview:} -Create a new host\_cpu instance, and return its handle. - - \noindent {\bf Signature:} -\begin{verbatim} (host_cpu ref) create (session_id s, host_cpu record args)\end{verbatim} - - -\noindent{\bf Arguments:} - - -\vspace{0.3cm} -\begin{tabular}{|c|c|p{7cm}|} - \hline -{\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt host\_cpu record } & args & All constructor arguments \\ \hline - -\end{tabular} - -\vspace{0.3cm} - - \noindent {\bf Return Type:} -{\tt -host\_cpu ref -} - - -reference to the newly created object -\vspace{0.3cm} -\vspace{0.3cm} -\vspace{0.3cm} -\subsubsection{RPC name:~destroy} - -{\bf Overview:} -Destroy the specified host\_cpu instance. - - \noindent {\bf Signature:} -\begin{verbatim} void destroy (session_id s, host_cpu 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 host\_cpu ref } & self & reference to the object \\ \hline - -\end{tabular} - -\vspace{0.3cm} - - \noindent {\bf Return Type:} -{\tt -void -} - - - \vspace{0.3cm} \vspace{0.3cm} \vspace{0.3cm} @@ -6114,8 +6675,6 @@ $\mathit{RW}$ & {\tt name/label} & string & a human-readable name \\ $\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 default\_gateway} & string & default gateway IP address. Used for auto-configuring guests with fixed IP setting \\ -$\mathit{RW}$ & {\tt default\_netmask} & string & default netmask. Used for auto-configuring guests with fixed IP setting \\ \hline \end{longtable} \subsection{Additional RPCs associated with class: network} @@ -6365,138 +6924,6 @@ 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\_default\_gateway} - -{\bf Overview:} -Get the default\_gateway field of the given network. - - \noindent {\bf Signature:} -\begin{verbatim} string get_default_gateway (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 -} - - -value of the field -\vspace{0.3cm} -\vspace{0.3cm} -\vspace{0.3cm} -\subsubsection{RPC name:~set\_default\_gateway} - -{\bf Overview:} -Set the default\_gateway field of the given network. - - \noindent {\bf Signature:} -\begin{verbatim} void set_default_gateway (session_id s, network ref self, 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 } & 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:~get\_default\_netmask} - -{\bf Overview:} -Get the default\_netmask field of the given network. - - \noindent {\bf Signature:} -\begin{verbatim} string get_default_netmask (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 -} - - -value of the field -\vspace{0.3cm} -\vspace{0.3cm} -\vspace{0.3cm} -\subsubsection{RPC name:~set\_default\_netmask} - -{\bf Overview:} -Set the default\_netmask field of the given network. - - \noindent {\bf Signature:} -\begin{verbatim} void set_default_netmask (session_id s, network ref self, 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 } & 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} @@ -6679,12 +7106,37 @@ $\mathit{RO}_\mathit{ins}$ & {\tt network} & network ref & virtual network to w $\mathit{RO}_\mathit{ins}$ & {\tt VM} & VM ref & virtual machine to which this vif is connected \\ $\mathit{RW}$ & {\tt MAC} & string & ethernet MAC address of virtual interface, as exposed to guest \\ $\mathit{RW}$ & {\tt MTU} & int & MTU in octets \\ +$\mathit{RO}_\mathit{run}$ & {\tt currently\_attached} & bool & is the device currently attached (erased on reboot) \\ +$\mathit{RO}_\mathit{run}$ & {\tt status\_code} & int & error/success code associated with last attach-operation (erased on reboot) \\ +$\mathit{RO}_\mathit{run}$ & {\tt status\_detail} & string & error/success information associated with last attach-operation status (erased on reboot) \\ $\mathit{RW}$ & {\tt qos/algorithm\_type} & string & QoS algorithm to use \\ -$\mathit{RW}$ & {\tt qos/algorithm\_params} & (string $\rightarrow$ string) Map & Paramters for chosen QoS algorithm \\ +$\mathit{RW}$ & {\tt qos/algorithm\_params} & (string $\rightarrow$ string) Map & parameters for chosen QoS algorithm \\ +$\mathit{RO}_\mathit{run}$ & {\tt qos/supported\_algorithms} & string Set & supported QoS algorithms for this VIF \\ $\mathit{RO}_\mathit{run}$ & {\tt metrics} & VIF\_metrics ref & metrics associated with this VIF. \\ \hline \end{longtable} \subsection{Additional RPCs associated with class: VIF} +\subsubsection{RPC name:~get\_all} + +{\bf Overview:} +Return a list of all the VIFs known to the system. + + \noindent {\bf Signature:} +\begin{verbatim} ((VIF ref) Set) get_all (session_id s)\end{verbatim} + + +\vspace{0.3cm} + + \noindent {\bf Return Type:} +{\tt +(VIF ref) Set +} + + +references to all objects +\vspace{0.3cm} +\vspace{0.3cm} +\vspace{0.3cm} \subsubsection{RPC name:~get\_uuid} {\bf Overview:} @@ -6976,6 +7428,102 @@ void +\vspace{0.3cm} +\vspace{0.3cm} +\vspace{0.3cm} +\subsubsection{RPC name:~get\_currently\_attached} + +{\bf Overview:} +Get the currently\_attached field of the given VIF. + + \noindent {\bf Signature:} +\begin{verbatim} bool get_currently_attached (session_id s, VIF 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 VIF ref } & self & reference to the object \\ \hline + +\end{tabular} + +\vspace{0.3cm} + + \noindent {\bf Return Type:} +{\tt +bool +} + + +value of the field +\vspace{0.3cm} +\vspace{0.3cm} +\vspace{0.3cm} +\subsubsection{RPC name:~get\_status\_code} + +{\bf Overview:} +Get the status\_code field of the given VIF. + + \noindent {\bf Signature:} +\begin{verbatim} int get_status_code (session_id s, VIF 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 VIF ref } & self & reference to the object \\ \hline + +\end{tabular} + +\vspace{0.3cm} + + \noindent {\bf Return Type:} +{\tt +int +} + + +value of the field +\vspace{0.3cm} +\vspace{0.3cm} +\vspace{0.3cm} +\subsubsection{RPC name:~get\_status\_detail} + +{\bf Overview:} +Get the status\_detail field of the given VIF. + + \noindent {\bf Signature:} +\begin{verbatim} string get_status_detail (session_id s, VIF 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 VIF ref } & self & reference to the object \\ \hline + +\end{tabular} + +\vspace{0.3cm} + + \noindent {\bf Return Type:} +{\tt +string +} + + +value of the field \vspace{0.3cm} \vspace{0.3cm} \vspace{0.3cm} @@ -7181,6 +7729,38 @@ void +\vspace{0.3cm} +\vspace{0.3cm} +\vspace{0.3cm} +\subsubsection{RPC name:~get\_qos\_supported\_algorithms} + +{\bf Overview:} +Get the qos/supported\_algorithms field of the given VIF. + + \noindent {\bf Signature:} +\begin{verbatim} (string Set) get_qos_supported_algorithms (session_id s, VIF 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 VIF ref } & self & reference to the object \\ \hline + +\end{tabular} + +\vspace{0.3cm} + + \noindent {\bf Return Type:} +{\tt +string Set +} + + +value of the field \vspace{0.3cm} \vspace{0.3cm} \vspace{0.3cm} @@ -7363,6 +7943,27 @@ $\mathit{RO}_\mathit{run}$ & {\tt io/write\_kbs} & float & Write bandwidth (KiB \hline \end{longtable} \subsection{Additional RPCs associated with class: VIF\_metrics} +\subsubsection{RPC name:~get\_all} + +{\bf Overview:} +Return a list of all the VIF\_metrics instances known to the system. + + \noindent {\bf Signature:} +\begin{verbatim} ((VIF_metrics ref) Set) get_all (session_id s)\end{verbatim} + + +\vspace{0.3cm} + + \noindent {\bf Return Type:} +{\tt +(VIF\_metrics ref) Set +} + + +references to all objects +\vspace{0.3cm} +\vspace{0.3cm} +\vspace{0.3cm} \subsubsection{RPC name:~get\_uuid} {\bf Overview:} @@ -7623,6 +8224,27 @@ void \noindent{\bf Possible Error Codes:} {\tt PIF\_IS\_PHYSICAL} \vspace{0.6cm} +\subsubsection{RPC name:~get\_all} + +{\bf Overview:} +Return a list of all the PIFs known to the system. + + \noindent {\bf Signature:} +\begin{verbatim} ((PIF ref) Set) get_all (session_id s)\end{verbatim} + + +\vspace{0.3cm} + + \noindent {\bf Return Type:} +{\tt +(PIF ref) Set +} + + +references to all objects +\vspace{0.3cm} +\vspace{0.3cm} +\vspace{0.3cm} \subsubsection{RPC name:~get\_uuid} {\bf Overview:} @@ -8093,12 +8715,32 @@ The metrics associated with a physical network interface.}} \\ Quals & Field & Type & Description \\ \hline $\mathit{RO}_\mathit{run}$ & {\tt uuid} & string & unique identifier/object reference \\ -$\mathit{RO}_\mathit{ins}$ & {\tt PIF} & PIF ref & PIF to which these metrics apply \\ $\mathit{RO}_\mathit{run}$ & {\tt io/read\_kbs} & float & Read bandwidth (KiB/s) \\ $\mathit{RO}_\mathit{run}$ & {\tt io/write\_kbs} & float & Write bandwidth (KiB/s) \\ \hline \end{longtable} \subsection{Additional RPCs associated with class: PIF\_metrics} +\subsubsection{RPC name:~get\_all} + +{\bf Overview:} +Return a list of all the PIF\_metrics instances known to the system. + + \noindent {\bf Signature:} +\begin{verbatim} ((PIF_metrics ref) Set) get_all (session_id s)\end{verbatim} + + +\vspace{0.3cm} + + \noindent {\bf Return Type:} +{\tt +(PIF\_metrics ref) Set +} + + +references to all objects +\vspace{0.3cm} +\vspace{0.3cm} +\vspace{0.3cm} \subsubsection{RPC name:~get\_uuid} {\bf Overview:} @@ -8127,38 +8769,6 @@ string } -value of the field -\vspace{0.3cm} -\vspace{0.3cm} -\vspace{0.3cm} -\subsubsection{RPC name:~get\_PIF} - -{\bf Overview:} -Get the PIF field of the given PIF\_metrics. - - \noindent {\bf Signature:} -\begin{verbatim} (PIF ref) get_PIF (session_id s, PIF_metrics 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 PIF\_metrics ref } & self & reference to the object \\ \hline - -\end{tabular} - -\vspace{0.3cm} - - \noindent {\bf Return Type:} -{\tt -PIF ref -} - - value of the field \vspace{0.3cm} \vspace{0.3cm} @@ -8942,7 +9552,7 @@ $\mathit{RW}$ & {\tt name/description} & string & a notes field containg human- $\mathit{RW}$ & {\tt SR} & SR ref & storage repository in which the VDI resides \\ $\mathit{RO}_\mathit{run}$ & {\tt VBDs} & (VBD ref) Set & list of vbds that refer to this disk \\ $\mathit{RO}_\mathit{run}$ & {\tt crash\_dumps} & (crashdump ref) Set & list of crash dumps that refer to this disk \\ -$\mathit{RW}$ & {\tt virtual\_size} & int & size of disk as presented to the guest (in multiples of sector\_size field) \\ +$\mathit{RW}$ & {\tt virtual\_size} & int & size of disk as presented to the guest (in bytes). Note that, depending on storage backend type, requested size may not be respected exactly \\ $\mathit{RO}_\mathit{run}$ & {\tt physical\_utilisation} & int & amount of physical space that the disk image is currently taking up on the storage repository (in bytes) \\ $\mathit{RO}_\mathit{ins}$ & {\tt sector\_size} & int & sector size of VDI (in bytes) \\ $\mathit{RO}_\mathit{ins}$ & {\tt type} & vdi\_type & type of the VDI \\ @@ -9015,6 +9625,27 @@ void +\vspace{0.3cm} +\vspace{0.3cm} +\vspace{0.3cm} +\subsubsection{RPC name:~get\_all} + +{\bf Overview:} +Return a list of all the VDIs known to the system. + + \noindent {\bf Signature:} +\begin{verbatim} ((VDI ref) Set) get_all (session_id s)\end{verbatim} + + +\vspace{0.3cm} + + \noindent {\bf Return Type:} +{\tt +(VDI ref) Set +} + + +references to all objects \vspace{0.3cm} \vspace{0.3cm} \vspace{0.3cm} @@ -9786,9 +10417,13 @@ $\mathit{RW}$ & {\tt device} & string & device seen by the guest e.g. hda1 \\ $\mathit{RW}$ & {\tt bootable} & bool & true if this VBD is bootable \\ $\mathit{RW}$ & {\tt mode} & vbd\_mode & the mode the VBD should be mounted with \\ $\mathit{RW}$ & {\tt type} & vbd\_type & how the VBD will appear to the guest (e.g. disk or CD) \\ +$\mathit{RO}_\mathit{run}$ & {\tt currently\_attached} & bool & is the device currently attached (erased on reboot) \\ +$\mathit{RO}_\mathit{run}$ & {\tt status\_code} & int & error/success code associated with last attach-operation (erased on reboot) \\ +$\mathit{RO}_\mathit{run}$ & {\tt status\_detail} & string & error/success information associated with last attach-operation status (erased on reboot) \\ $\mathit{RW}$ & {\tt qos/algorithm\_type} & string & QoS algorithm to use \\ -$\mathit{RW}$ & {\tt qos/algorithm\_params} & (string $\rightarrow$ string) Map & Paramters for chosen QoS algorithm \\ -$\mathit{RO}_\mathit{run}$ & {\tt metrics} & VBD\_metrics ref & metrics associated with this VBD. \\ +$\mathit{RW}$ & {\tt qos/algorithm\_params} & (string $\rightarrow$ string) Map & parameters for chosen QoS algorithm \\ +$\mathit{RO}_\mathit{run}$ & {\tt qos/supported\_algorithms} & string Set & supported QoS algorithms for this VBD \\ +$\mathit{RO}_\mathit{run}$ & {\tt metrics} & VBD\_metrics ref & metrics associated with this VBD \\ \hline \end{longtable} \subsection{Additional RPCs associated with class: VBD} @@ -9824,6 +10459,27 @@ void +\vspace{0.3cm} +\vspace{0.3cm} +\vspace{0.3cm} +\subsubsection{RPC name:~get\_all} + +{\bf Overview:} +Return a list of all the VBDs known to the system. + + \noindent {\bf Signature:} +\begin{verbatim} ((VBD ref) Set) get_all (session_id s)\end{verbatim} + + +\vspace{0.3cm} + + \noindent {\bf Return Type:} +{\tt +(VBD ref) Set +} + + +references to all objects \vspace{0.3cm} \vspace{0.3cm} \vspace{0.3cm} @@ -10184,6 +10840,102 @@ void +\vspace{0.3cm} +\vspace{0.3cm} +\vspace{0.3cm} +\subsubsection{RPC name:~get\_currently\_attached} + +{\bf Overview:} +Get the currently\_attached field of the given VBD. + + \noindent {\bf Signature:} +\begin{verbatim} bool get_currently_attached (session_id s, VBD 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 VBD ref } & self & reference to the object \\ \hline + +\end{tabular} + +\vspace{0.3cm} + + \noindent {\bf Return Type:} +{\tt +bool +} + + +value of the field +\vspace{0.3cm} +\vspace{0.3cm} +\vspace{0.3cm} +\subsubsection{RPC name:~get\_status\_code} + +{\bf Overview:} +Get the status\_code field of the given VBD. + + \noindent {\bf Signature:} +\begin{verbatim} int get_status_code (session_id s, VBD 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 VBD ref } & self & reference to the object \\ \hline + +\end{tabular} + +\vspace{0.3cm} + + \noindent {\bf Return Type:} +{\tt +int +} + + +value of the field +\vspace{0.3cm} +\vspace{0.3cm} +\vspace{0.3cm} +\subsubsection{RPC name:~get\_status\_detail} + +{\bf Overview:} +Get the status\_detail field of the given VBD. + + \noindent {\bf Signature:} +\begin{verbatim} string get_status_detail (session_id s, VBD 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 VBD ref } & self & reference to the object \\ \hline + +\end{tabular} + +\vspace{0.3cm} + + \noindent {\bf Return Type:} +{\tt +string +} + + +value of the field \vspace{0.3cm} \vspace{0.3cm} \vspace{0.3cm} @@ -10389,6 +11141,38 @@ void +\vspace{0.3cm} +\vspace{0.3cm} +\vspace{0.3cm} +\subsubsection{RPC name:~get\_qos\_supported\_algorithms} + +{\bf Overview:} +Get the qos/supported\_algorithms field of the given VBD. + + \noindent {\bf Signature:} +\begin{verbatim} (string Set) get_qos_supported_algorithms (session_id s, VBD 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 VBD ref } & self & reference to the object \\ \hline + +\end{tabular} + +\vspace{0.3cm} + + \noindent {\bf Return Type:} +{\tt +string Set +} + + +value of the field \vspace{0.3cm} \vspace{0.3cm} \vspace{0.3cm} @@ -10571,6 +11355,27 @@ $\mathit{RO}_\mathit{run}$ & {\tt io/write\_kbs} & float & Write bandwidth (KiB \hline \end{longtable} \subsection{Additional RPCs associated with class: VBD\_metrics} +\subsubsection{RPC name:~get\_all} + +{\bf Overview:} +Return a list of all the VBD\_metrics instances known to the system. + + \noindent {\bf Signature:} +\begin{verbatim} ((VBD_metrics ref) Set) get_all (session_id s)\end{verbatim} + + +\vspace{0.3cm} + + \noindent {\bf Return Type:} +{\tt +(VBD\_metrics ref) Set +} + + +references to all objects +\vspace{0.3cm} +\vspace{0.3cm} +\vspace{0.3cm} \subsubsection{RPC name:~get\_uuid} {\bf Overview:} @@ -10752,6 +11557,27 @@ $\mathit{RO}_\mathit{run}$ & {\tt currently\_attached} & bool & is the SR curre \hline \end{longtable} \subsection{Additional RPCs associated with class: PBD} +\subsubsection{RPC name:~get\_all} + +{\bf Overview:} +Return a list of all the PBDs known to the system. + + \noindent {\bf Signature:} +\begin{verbatim} ((PBD ref) Set) get_all (session_id s)\end{verbatim} + + +\vspace{0.3cm} + + \noindent {\bf Return Type:} +{\tt +(PBD ref) Set +} + + +references to all objects +\vspace{0.3cm} +\vspace{0.3cm} +\vspace{0.3cm} \subsubsection{RPC name:~get\_uuid} {\bf Overview:} @@ -11568,6 +12394,27 @@ $\mathit{RW}$ & {\tt other\_config} & (string $\rightarrow$ string) Map & addit \hline \end{longtable} \subsection{Additional RPCs associated with class: console} +\subsubsection{RPC name:~get\_all} + +{\bf Overview:} +Return a list of all the consoles known to the system. + + \noindent {\bf Signature:} +\begin{verbatim} ((console ref) Set) get_all (session_id s)\end{verbatim} + + +\vspace{0.3cm} + + \noindent {\bf Return Type:} +{\tt +(console ref) Set +} + + +references to all objects +\vspace{0.3cm} +\vspace{0.3cm} +\vspace{0.3cm} \subsubsection{RPC name:~get\_uuid} {\bf Overview:} diff --git a/extras/mini-os/Makefile b/extras/mini-os/Makefile index e337f1656d..75427676e5 100644 --- a/extras/mini-os/Makefile +++ b/extras/mini-os/Makefile @@ -4,8 +4,6 @@ # Makefile and a arch.mk. # -pae ?= n - XEN_ROOT = ../.. include $(XEN_ROOT)/Config.mk @@ -35,6 +33,7 @@ TARGET_ARCH_DIR := arch/$(TARGET_ARCH_FAM) export TARGET_ARCH export TARGET_ARCH_DIR export TARGET_ARCH_FAM +export XEN_TARGET_X86_PAE # This is used for architecture specific links. # This can be overwritten from arch specific rules. diff --git a/extras/mini-os/arch/ia64/mm.c b/extras/mini-os/arch/ia64/mm.c index ad5acccc7e..dd1fb9dc78 100644 --- a/extras/mini-os/arch/ia64/mm.c +++ b/extras/mini-os/arch/ia64/mm.c @@ -130,3 +130,7 @@ map_frames(unsigned long* frames, unsigned long n) return (void*) __va(frames[0] << PAGE_SHIFT); } +void arch_init_p2m(unsigned long max_pfn) +{ + printk("Warn: p2m map not implemented.\n"); +} diff --git a/extras/mini-os/arch/x86/Makefile b/extras/mini-os/arch/x86/Makefile index 8e655f1d64..10cb1ff9a1 100644 --- a/extras/mini-os/arch/x86/Makefile +++ b/extras/mini-os/arch/x86/Makefile @@ -4,6 +4,7 @@ # # include arch.mk has to be before mini-os.mk! + include arch.mk include ../../minios.mk diff --git a/extras/mini-os/arch/x86/arch.mk b/extras/mini-os/arch/x86/arch.mk index 9a7704b490..bf3350c150 100644 --- a/extras/mini-os/arch/x86/arch.mk +++ b/extras/mini-os/arch/x86/arch.mk @@ -9,13 +9,11 @@ ARCH_LDFLAGS := -m elf_i386 ARCH_ASFLAGS := -m32 EXTRA_INC += $(TARGET_ARCH_FAM)/$(TARGET_ARCH) EXTRA_SRC += arch/$(EXTRA_INC) -endif -ifeq ($(TARGET_ARCH)$(pae),x86_32y) -ARCH_CFLAGS := -DCONFIG_X86_PAE=1 -ARCH_ASFLAGS := -DCONFIG_X86_PAE=1 -EXTRA_INC += $(TARGET_ARCH_FAM)/$(TARGET_ARCH) -EXTRA_SRC += arch/$(EXTRA_INC) +ifeq ($(XEN_TARGET_X86_PAE),y) +ARCH_CFLAGS += -DCONFIG_X86_PAE=1 +ARCH_ASFLAGS += -DCONFIG_X86_PAE=1 +endif endif ifeq ($(TARGET_ARCH),x86_64) diff --git a/extras/mini-os/arch/x86/mm.c b/extras/mini-os/arch/x86/mm.c index d0fe762792..d1508f8263 100644 --- a/extras/mini-os/arch/x86/mm.c +++ b/extras/mini-os/arch/x86/mm.c @@ -402,6 +402,49 @@ void *map_frames(unsigned long *f, unsigned long n) } } + +void arch_init_p2m(unsigned long max_pfn) +{ +#define L1_P2M_SHIFT 10 +#define L2_P2M_SHIFT 20 +#define L3_P2M_SHIFT 30 +#define L1_P2M_ENTRIES (1 << L1_P2M_SHIFT) +#define L2_P2M_ENTRIES (1 << (L2_P2M_SHIFT - L1_P2M_SHIFT)) +#define L3_P2M_ENTRIES (1 << (L3_P2M_SHIFT - L2_P2M_SHIFT)) +#define L1_P2M_MASK (L1_P2M_ENTRIES - 1) +#define L2_P2M_MASK (L2_P2M_ENTRIES - 1) +#define L3_P2M_MASK (L3_P2M_ENTRIES - 1) + + unsigned long *l1_list, *l2_list, *l3_list; + unsigned long pfn; + + l3_list = (unsigned long *)alloc_page(); + for(pfn=0; pfn> L3_P2M_SHIFT) > 0) + { + printk("Error: Too many pfns.\n"); + do_exit(); + } + l3_list[(pfn >> L2_P2M_SHIFT)] = virt_to_mfn(l2_list); + } + if(!(pfn % (L1_P2M_ENTRIES))) + { + l1_list = (unsigned long*)alloc_page(); + l2_list[(pfn >> L1_P2M_SHIFT) & L2_P2M_MASK] = + virt_to_mfn(l1_list); + } + + l1_list[pfn & L1_P2M_MASK] = pfn_to_mfn(pfn); + } + HYPERVISOR_shared_info->arch.pfn_to_mfn_frame_list_list = + virt_to_mfn(l3_list); + HYPERVISOR_shared_info->arch.max_pfn = max_pfn; +} + void arch_init_mm(unsigned long* start_pfn_p, unsigned long* max_pfn_p) { diff --git a/extras/mini-os/include/mm.h b/extras/mini-os/include/mm.h index cd53a4bf25..a9c0f2c181 100644 --- a/extras/mini-os/include/mm.h +++ b/extras/mini-os/include/mm.h @@ -55,6 +55,7 @@ static __inline__ int get_order(unsigned long size) void arch_init_demand_mapping_area(unsigned long max_pfn); void arch_init_mm(unsigned long* start_pfn_p, unsigned long* max_pfn_p); +void arch_init_p2m(unsigned long max_pfn_p); void *map_frames(unsigned long *f, unsigned long n); diff --git a/extras/mini-os/mm.c b/extras/mini-os/mm.c index a24a521cf6..11e249d421 100644 --- a/extras/mini-os/mm.c +++ b/extras/mini-os/mm.c @@ -379,6 +379,8 @@ void init_mm(void) init_page_allocator(PFN_PHYS(start_pfn), PFN_PHYS(max_pfn)); printk("MM: done\n"); + arch_init_p2m(max_pfn); + arch_init_demand_mapping_area(max_pfn); } diff --git a/linux-2.6-xen-sparse/arch/i386/Kconfig b/linux-2.6-xen-sparse/arch/i386/Kconfig index 60dff4004e..f799b5fdec 100644 --- a/linux-2.6-xen-sparse/arch/i386/Kconfig +++ b/linux-2.6-xen-sparse/arch/i386/Kconfig @@ -255,7 +255,6 @@ config NR_CPUS config SCHED_SMT bool "SMT (Hyperthreading) scheduler support" depends on X86_HT - depends on !X86_XEN help SMT scheduler support improves the CPU scheduler's decision making when dealing with Intel Pentium 4 chips with HyperThreading at a @@ -313,11 +312,6 @@ config X86_VISWS_APIC depends on X86_VISWS default y -config X86_TSC - bool - depends on (MWINCHIP3D || MWINCHIP2 || MCRUSOE || MEFFICEON || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || MK8 || MVIAC3_2 || MGEODEGX1) && !X86_NUMAQ && !X86_XEN - default y - config X86_MCE bool "Machine Check Exception" depends on !(X86_VOYAGER || X86_XEN) diff --git a/linux-2.6-xen-sparse/arch/i386/Kconfig.cpu b/linux-2.6-xen-sparse/arch/i386/Kconfig.cpu index 2180bfbd49..eb6c84bd67 100644 --- a/linux-2.6-xen-sparse/arch/i386/Kconfig.cpu +++ b/linux-2.6-xen-sparse/arch/i386/Kconfig.cpu @@ -311,5 +311,5 @@ config X86_OOSTORE config X86_TSC bool - depends on (MWINCHIP3D || MWINCHIP2 || MCRUSOE || MEFFICEON || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || MK8 || MVIAC3_2 || MGEODEGX1 || MGEODE_LX) && !X86_NUMAQ + depends on (MWINCHIP3D || MWINCHIP2 || MCRUSOE || MEFFICEON || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || MK8 || MVIAC3_2 || MGEODEGX1 || MGEODE_LX) && !X86_NUMAQ && !X86_XEN default y diff --git a/linux-2.6-xen-sparse/arch/i386/kernel/alternative-xen.c b/linux-2.6-xen-sparse/arch/i386/kernel/alternative-xen.c deleted file mode 100644 index 479a2ddc1f..0000000000 --- a/linux-2.6-xen-sparse/arch/i386/kernel/alternative-xen.c +++ /dev/null @@ -1,389 +0,0 @@ -#include -#include -#include -#include -#include - -static int no_replacement = 0; -static int smp_alt_once = 0; -static int debug_alternative = 0; - -static int __init noreplacement_setup(char *s) -{ - no_replacement = 1; - return 1; -} -static int __init bootonly(char *str) -{ - smp_alt_once = 1; - return 1; -} -static int __init debug_alt(char *str) -{ - debug_alternative = 1; - return 1; -} - -__setup("noreplacement", noreplacement_setup); -__setup("smp-alt-boot", bootonly); -__setup("debug-alternative", debug_alt); - -#define DPRINTK(fmt, args...) if (debug_alternative) \ - printk(KERN_DEBUG fmt, args) - -#ifdef GENERIC_NOP1 -/* Use inline assembly to define this because the nops are defined - as inline assembly strings in the include files and we cannot - get them easily into strings. */ -asm("\t.data\nintelnops: " - GENERIC_NOP1 GENERIC_NOP2 GENERIC_NOP3 GENERIC_NOP4 GENERIC_NOP5 GENERIC_NOP6 - GENERIC_NOP7 GENERIC_NOP8); -extern unsigned char intelnops[]; -static unsigned char *intel_nops[ASM_NOP_MAX+1] = { - NULL, - intelnops, - intelnops + 1, - intelnops + 1 + 2, - intelnops + 1 + 2 + 3, - intelnops + 1 + 2 + 3 + 4, - intelnops + 1 + 2 + 3 + 4 + 5, - intelnops + 1 + 2 + 3 + 4 + 5 + 6, - intelnops + 1 + 2 + 3 + 4 + 5 + 6 + 7, -}; -#endif - -#ifdef K8_NOP1 -asm("\t.data\nk8nops: " - K8_NOP1 K8_NOP2 K8_NOP3 K8_NOP4 K8_NOP5 K8_NOP6 - K8_NOP7 K8_NOP8); -extern unsigned char k8nops[]; -static unsigned char *k8_nops[ASM_NOP_MAX+1] = { - NULL, - k8nops, - k8nops + 1, - k8nops + 1 + 2, - k8nops + 1 + 2 + 3, - k8nops + 1 + 2 + 3 + 4, - k8nops + 1 + 2 + 3 + 4 + 5, - k8nops + 1 + 2 + 3 + 4 + 5 + 6, - k8nops + 1 + 2 + 3 + 4 + 5 + 6 + 7, -}; -#endif - -#ifdef K7_NOP1 -asm("\t.data\nk7nops: " - K7_NOP1 K7_NOP2 K7_NOP3 K7_NOP4 K7_NOP5 K7_NOP6 - K7_NOP7 K7_NOP8); -extern unsigned char k7nops[]; -static unsigned char *k7_nops[ASM_NOP_MAX+1] = { - NULL, - k7nops, - k7nops + 1, - k7nops + 1 + 2, - k7nops + 1 + 2 + 3, - k7nops + 1 + 2 + 3 + 4, - k7nops + 1 + 2 + 3 + 4 + 5, - k7nops + 1 + 2 + 3 + 4 + 5 + 6, - k7nops + 1 + 2 + 3 + 4 + 5 + 6 + 7, -}; -#endif - -#ifdef CONFIG_X86_64 - -extern char __vsyscall_0; -static inline unsigned char** find_nop_table(void) -{ - return k8_nops; -} - -#else /* CONFIG_X86_64 */ - -static struct nop { - int cpuid; - unsigned char **noptable; -} noptypes[] = { - { X86_FEATURE_K8, k8_nops }, - { X86_FEATURE_K7, k7_nops }, - { -1, NULL } -}; - -static unsigned char** find_nop_table(void) -{ - unsigned char **noptable = intel_nops; - int i; - - for (i = 0; noptypes[i].cpuid >= 0; i++) { - if (boot_cpu_has(noptypes[i].cpuid)) { - noptable = noptypes[i].noptable; - break; - } - } - return noptable; -} - -#endif /* CONFIG_X86_64 */ - -extern struct alt_instr __alt_instructions[], __alt_instructions_end[]; -extern struct alt_instr __smp_alt_instructions[], __smp_alt_instructions_end[]; -extern u8 *__smp_locks[], *__smp_locks_end[]; - -extern u8 __smp_alt_begin[], __smp_alt_end[]; - -/* Replace instructions with better alternatives for this CPU type. - This runs before SMP is initialized to avoid SMP problems with - self modifying code. This implies that assymetric systems where - APs have less capabilities than the boot processor are not handled. - Tough. Make sure you disable such features by hand. */ - -void apply_alternatives(struct alt_instr *start, struct alt_instr *end) -{ - unsigned char **noptable = find_nop_table(); - struct alt_instr *a; - u8 *instr; - int diff, i, k; - - DPRINTK("%s: alt table %p -> %p\n", __FUNCTION__, start, end); - for (a = start; a < end; a++) { - BUG_ON(a->replacementlen > a->instrlen); - if (!boot_cpu_has(a->cpuid)) - continue; - instr = a->instr; -#ifdef CONFIG_X86_64 - /* vsyscall code is not mapped yet. resolve it manually. */ - if (instr >= (u8 *)VSYSCALL_START && instr < (u8*)VSYSCALL_END) { - instr -= VSYSCALL_START - (unsigned long)&__vsyscall_0; - DPRINTK("%s: vsyscall fixup: %p => %p\n", - __FUNCTION__, a->instr, instr); - } -#endif - memcpy(instr, a->replacement, a->replacementlen); - diff = a->instrlen - a->replacementlen; - /* Pad the rest with nops */ - for (i = a->replacementlen; diff > 0; diff -= k, i += k) { - k = diff; - if (k > ASM_NOP_MAX) - k = ASM_NOP_MAX; - memcpy(a->instr + i, noptable[k], k); - } - } -} - -#ifdef CONFIG_SMP - -static void alternatives_smp_save(struct alt_instr *start, struct alt_instr *end) -{ - struct alt_instr *a; - - DPRINTK("%s: alt table %p-%p\n", __FUNCTION__, start, end); - for (a = start; a < end; a++) { - memcpy(a->replacement + a->replacementlen, - a->instr, - a->instrlen); - } -} - -static void alternatives_smp_apply(struct alt_instr *start, struct alt_instr *end) -{ - struct alt_instr *a; - - for (a = start; a < end; a++) { - memcpy(a->instr, - a->replacement + a->replacementlen, - a->instrlen); - } -} - -static void alternatives_smp_lock(u8 **start, u8 **end, u8 *text, u8 *text_end) -{ - u8 **ptr; - - for (ptr = start; ptr < end; ptr++) { - if (*ptr < text) - continue; - if (*ptr > text_end) - continue; - **ptr = 0xf0; /* lock prefix */ - }; -} - -static void alternatives_smp_unlock(u8 **start, u8 **end, u8 *text, u8 *text_end) -{ - unsigned char **noptable = find_nop_table(); - u8 **ptr; - - for (ptr = start; ptr < end; ptr++) { - if (*ptr < text) - continue; - if (*ptr > text_end) - continue; - **ptr = noptable[1][0]; - }; -} - -struct smp_alt_module { - /* what is this ??? */ - struct module *mod; - char *name; - - /* ptrs to lock prefixes */ - u8 **locks; - u8 **locks_end; - - /* .text segment, needed to avoid patching init code ;) */ - u8 *text; - u8 *text_end; - - struct list_head next; -}; -static LIST_HEAD(smp_alt_modules); -static DEFINE_SPINLOCK(smp_alt); - -void alternatives_smp_module_add(struct module *mod, char *name, - void *locks, void *locks_end, - void *text, void *text_end) -{ - struct smp_alt_module *smp; - unsigned long flags; - - if (no_replacement) - return; - - if (smp_alt_once) { - if (boot_cpu_has(X86_FEATURE_UP)) - alternatives_smp_unlock(locks, locks_end, - text, text_end); - return; - } - - smp = kzalloc(sizeof(*smp), GFP_KERNEL); - if (NULL == smp) - return; /* we'll run the (safe but slow) SMP code then ... */ - - smp->mod = mod; - smp->name = name; - smp->locks = locks; - smp->locks_end = locks_end; - smp->text = text; - smp->text_end = text_end; - DPRINTK("%s: locks %p -> %p, text %p -> %p, name %s\n", - __FUNCTION__, smp->locks, smp->locks_end, - smp->text, smp->text_end, smp->name); - - spin_lock_irqsave(&smp_alt, flags); - list_add_tail(&smp->next, &smp_alt_modules); - if (boot_cpu_has(X86_FEATURE_UP)) - alternatives_smp_unlock(smp->locks, smp->locks_end, - smp->text, smp->text_end); - spin_unlock_irqrestore(&smp_alt, flags); -} - -void alternatives_smp_module_del(struct module *mod) -{ - struct smp_alt_module *item; - unsigned long flags; - - if (no_replacement || smp_alt_once) - return; - - spin_lock_irqsave(&smp_alt, flags); - list_for_each_entry(item, &smp_alt_modules, next) { - if (mod != item->mod) - continue; - list_del(&item->next); - spin_unlock_irqrestore(&smp_alt, flags); - DPRINTK("%s: %s\n", __FUNCTION__, item->name); - kfree(item); - return; - } - spin_unlock_irqrestore(&smp_alt, flags); -} - -void alternatives_smp_switch(int smp) -{ - struct smp_alt_module *mod; - unsigned long flags; - -#ifdef CONFIG_LOCKDEP - /* - * A not yet fixed binutils section handling bug prevents - * alternatives-replacement from working reliably, so turn - * it off: - */ - printk("lockdep: not fixing up alternatives.\n"); - return; -#endif - - if (no_replacement || smp_alt_once) - return; - BUG_ON(!smp && (num_online_cpus() > 1)); - - spin_lock_irqsave(&smp_alt, flags); - if (smp) { - printk(KERN_INFO "SMP alternatives: switching to SMP code\n"); - clear_bit(X86_FEATURE_UP, boot_cpu_data.x86_capability); - clear_bit(X86_FEATURE_UP, cpu_data[0].x86_capability); - alternatives_smp_apply(__smp_alt_instructions, - __smp_alt_instructions_end); - list_for_each_entry(mod, &smp_alt_modules, next) - alternatives_smp_lock(mod->locks, mod->locks_end, - mod->text, mod->text_end); - } else { - printk(KERN_INFO "SMP alternatives: switching to UP code\n"); - set_bit(X86_FEATURE_UP, boot_cpu_data.x86_capability); - set_bit(X86_FEATURE_UP, cpu_data[0].x86_capability); - apply_alternatives(__smp_alt_instructions, - __smp_alt_instructions_end); - list_for_each_entry(mod, &smp_alt_modules, next) - alternatives_smp_unlock(mod->locks, mod->locks_end, - mod->text, mod->text_end); - } - spin_unlock_irqrestore(&smp_alt, flags); -} - -#endif - -void __init alternative_instructions(void) -{ - if (no_replacement) { - printk(KERN_INFO "(SMP-)alternatives turned off\n"); - free_init_pages("SMP alternatives", - (unsigned long)__smp_alt_begin, - (unsigned long)__smp_alt_end); - return; - } - apply_alternatives(__alt_instructions, __alt_instructions_end); - - /* switch to patch-once-at-boottime-only mode and free the - * tables in case we know the number of CPUs will never ever - * change */ -#ifdef CONFIG_HOTPLUG_CPU - if (num_possible_cpus() < 2) - smp_alt_once = 1; -#else - smp_alt_once = 1; -#endif - -#ifdef CONFIG_SMP - if (smp_alt_once) { - if (1 == num_possible_cpus()) { - printk(KERN_INFO "SMP alternatives: switching to UP code\n"); - set_bit(X86_FEATURE_UP, boot_cpu_data.x86_capability); - set_bit(X86_FEATURE_UP, cpu_data[0].x86_capability); - apply_alternatives(__smp_alt_instructions, - __smp_alt_instructions_end); - alternatives_smp_unlock(__smp_locks, __smp_locks_end, - _text, _etext); - } - free_init_pages("SMP alternatives", - (unsigned long)__smp_alt_begin, - (unsigned long)__smp_alt_end); - } else { - alternatives_smp_save(__smp_alt_instructions, - __smp_alt_instructions_end); - alternatives_smp_module_add(NULL, "core kernel", - __smp_locks, __smp_locks_end, - _text, _etext); - alternatives_smp_switch(0); - } -#endif -} diff --git a/linux-2.6-xen-sparse/arch/i386/kernel/cpu/intel_cacheinfo-xen.c b/linux-2.6-xen-sparse/arch/i386/kernel/cpu/intel_cacheinfo-xen.c deleted file mode 100644 index 5c43be4758..0000000000 --- a/linux-2.6-xen-sparse/arch/i386/kernel/cpu/intel_cacheinfo-xen.c +++ /dev/null @@ -1,774 +0,0 @@ -/* - * Routines to indentify caches on Intel CPU. - * - * Changes: - * Venkatesh Pallipadi : Adding cache identification through cpuid(4) - * Ashok Raj : Work with CPU hotplug infrastructure. - * Andi Kleen : CPUID4 emulation on AMD. - */ - -#include -#include -#include -#include -#include -#include - -#include -#include - -#define LVL_1_INST 1 -#define LVL_1_DATA 2 -#define LVL_2 3 -#define LVL_3 4 -#define LVL_TRACE 5 - -struct _cache_table -{ - unsigned char descriptor; - char cache_type; - short size; -}; - -/* all the cache descriptor types we care about (no TLB or trace cache entries) */ -static struct _cache_table cache_table[] __cpuinitdata = -{ - { 0x06, LVL_1_INST, 8 }, /* 4-way set assoc, 32 byte line size */ - { 0x08, LVL_1_INST, 16 }, /* 4-way set assoc, 32 byte line size */ - { 0x0a, LVL_1_DATA, 8 }, /* 2 way set assoc, 32 byte line size */ - { 0x0c, LVL_1_DATA, 16 }, /* 4-way set assoc, 32 byte line size */ - { 0x22, LVL_3, 512 }, /* 4-way set assoc, sectored cache, 64 byte line size */ - { 0x23, LVL_3, 1024 }, /* 8-way set assoc, sectored cache, 64 byte line size */ - { 0x25, LVL_3, 2048 }, /* 8-way set assoc, sectored cache, 64 byte line size */ - { 0x29, LVL_3, 4096 }, /* 8-way set assoc, sectored cache, 64 byte line size */ - { 0x2c, LVL_1_DATA, 32 }, /* 8-way set assoc, 64 byte line size */ - { 0x30, LVL_1_INST, 32 }, /* 8-way set assoc, 64 byte line size */ - { 0x39, LVL_2, 128 }, /* 4-way set assoc, sectored cache, 64 byte line size */ - { 0x3a, LVL_2, 192 }, /* 6-way set assoc, sectored cache, 64 byte line size */ - { 0x3b, LVL_2, 128 }, /* 2-way set assoc, sectored cache, 64 byte line size */ - { 0x3c, LVL_2, 256 }, /* 4-way set assoc, sectored cache, 64 byte line size */ - { 0x3d, LVL_2, 384 }, /* 6-way set assoc, sectored cache, 64 byte line size */ - { 0x3e, LVL_2, 512 }, /* 4-way set assoc, sectored cache, 64 byte line size */ - { 0x41, LVL_2, 128 }, /* 4-way set assoc, 32 byte line size */ - { 0x42, LVL_2, 256 }, /* 4-way set assoc, 32 byte line size */ - { 0x43, LVL_2, 512 }, /* 4-way set assoc, 32 byte line size */ - { 0x44, LVL_2, 1024 }, /* 4-way set assoc, 32 byte line size */ - { 0x45, LVL_2, 2048 }, /* 4-way set assoc, 32 byte line size */ - { 0x46, LVL_3, 4096 }, /* 4-way set assoc, 64 byte line size */ - { 0x47, LVL_3, 8192 }, /* 8-way set assoc, 64 byte line size */ - { 0x49, LVL_3, 4096 }, /* 16-way set assoc, 64 byte line size */ - { 0x4a, LVL_3, 6144 }, /* 12-way set assoc, 64 byte line size */ - { 0x4b, LVL_3, 8192 }, /* 16-way set assoc, 64 byte line size */ - { 0x4c, LVL_3, 12288 }, /* 12-way set assoc, 64 byte line size */ - { 0x4d, LVL_3, 16384 }, /* 16-way set assoc, 64 byte line size */ - { 0x60, LVL_1_DATA, 16 }, /* 8-way set assoc, sectored cache, 64 byte line size */ - { 0x66, LVL_1_DATA, 8 }, /* 4-way set assoc, sectored cache, 64 byte line size */ - { 0x67, LVL_1_DATA, 16 }, /* 4-way set assoc, sectored cache, 64 byte line size */ - { 0x68, LVL_1_DATA, 32 }, /* 4-way set assoc, sectored cache, 64 byte line size */ - { 0x70, LVL_TRACE, 12 }, /* 8-way set assoc */ - { 0x71, LVL_TRACE, 16 }, /* 8-way set assoc */ - { 0x72, LVL_TRACE, 32 }, /* 8-way set assoc */ - { 0x73, LVL_TRACE, 64 }, /* 8-way set assoc */ - { 0x78, LVL_2, 1024 }, /* 4-way set assoc, 64 byte line size */ - { 0x79, LVL_2, 128 }, /* 8-way set assoc, sectored cache, 64 byte line size */ - { 0x7a, LVL_2, 256 }, /* 8-way set assoc, sectored cache, 64 byte line size */ - { 0x7b, LVL_2, 512 }, /* 8-way set assoc, sectored cache, 64 byte line size */ - { 0x7c, LVL_2, 1024 }, /* 8-way set assoc, sectored cache, 64 byte line size */ - { 0x7d, LVL_2, 2048 }, /* 8-way set assoc, 64 byte line size */ - { 0x7f, LVL_2, 512 }, /* 2-way set assoc, 64 byte line size */ - { 0x82, LVL_2, 256 }, /* 8-way set assoc, 32 byte line size */ - { 0x83, LVL_2, 512 }, /* 8-way set assoc, 32 byte line size */ - { 0x84, LVL_2, 1024 }, /* 8-way set assoc, 32 byte line size */ - { 0x85, LVL_2, 2048 }, /* 8-way set assoc, 32 byte line size */ - { 0x86, LVL_2, 512 }, /* 4-way set assoc, 64 byte line size */ - { 0x87, LVL_2, 1024 }, /* 8-way set assoc, 64 byte line size */ - { 0x00, 0, 0} -}; - - -enum _cache_type -{ - CACHE_TYPE_NULL = 0, - CACHE_TYPE_DATA = 1, - CACHE_TYPE_INST = 2, - CACHE_TYPE_UNIFIED = 3 -}; - -union _cpuid4_leaf_eax { - struct { - enum _cache_type type:5; - unsigned int level:3; - unsigned int is_self_initializing:1; - unsigned int is_fully_associative:1; - unsigned int reserved:4; - unsigned int num_threads_sharing:12; - unsigned int num_cores_on_die:6; - } split; - u32 full; -}; - -union _cpuid4_leaf_ebx { - struct { - unsigned int coherency_line_size:12; - unsigned int physical_line_partition:10; - unsigned int ways_of_associativity:10; - } split; - u32 full; -}; - -union _cpuid4_leaf_ecx { - struct { - unsigned int number_of_sets:32; - } split; - u32 full; -}; - -struct _cpuid4_info { - union _cpuid4_leaf_eax eax; - union _cpuid4_leaf_ebx ebx; - union _cpuid4_leaf_ecx ecx; - unsigned long size; - cpumask_t shared_cpu_map; -}; - -unsigned short num_cache_leaves; - -/* AMD doesn't have CPUID4. Emulate it here to report the same - information to the user. This makes some assumptions about the machine: - No L3, L2 not shared, no SMT etc. that is currently true on AMD CPUs. - - In theory the TLBs could be reported as fake type (they are in "dummy"). - Maybe later */ -union l1_cache { - struct { - unsigned line_size : 8; - unsigned lines_per_tag : 8; - unsigned assoc : 8; - unsigned size_in_kb : 8; - }; - unsigned val; -}; - -union l2_cache { - struct { - unsigned line_size : 8; - unsigned lines_per_tag : 4; - unsigned assoc : 4; - unsigned size_in_kb : 16; - }; - unsigned val; -}; - -static const unsigned short assocs[] = { - [1] = 1, [2] = 2, [4] = 4, [6] = 8, - [8] = 16, - [0xf] = 0xffff // ?? - }; -static const unsigned char levels[] = { 1, 1, 2 }; -static const unsigned char types[] = { 1, 2, 3 }; - -static void __cpuinit amd_cpuid4(int leaf, union _cpuid4_leaf_eax *eax, - union _cpuid4_leaf_ebx *ebx, - union _cpuid4_leaf_ecx *ecx) -{ - unsigned dummy; - unsigned line_size, lines_per_tag, assoc, size_in_kb; - union l1_cache l1i, l1d; - union l2_cache l2; - - eax->full = 0; - ebx->full = 0; - ecx->full = 0; - - cpuid(0x80000005, &dummy, &dummy, &l1d.val, &l1i.val); - cpuid(0x80000006, &dummy, &dummy, &l2.val, &dummy); - - if (leaf > 2 || !l1d.val || !l1i.val || !l2.val) - return; - - eax->split.is_self_initializing = 1; - eax->split.type = types[leaf]; - eax->split.level = levels[leaf]; - eax->split.num_threads_sharing = 0; - eax->split.num_cores_on_die = current_cpu_data.x86_max_cores - 1; - - if (leaf <= 1) { - union l1_cache *l1 = leaf == 0 ? &l1d : &l1i; - assoc = l1->assoc; - line_size = l1->line_size; - lines_per_tag = l1->lines_per_tag; - size_in_kb = l1->size_in_kb; - } else { - assoc = l2.assoc; - line_size = l2.line_size; - lines_per_tag = l2.lines_per_tag; - /* cpu_data has errata corrections for K7 applied */ - size_in_kb = current_cpu_data.x86_cache_size; - } - - if (assoc == 0xf) - eax->split.is_fully_associative = 1; - ebx->split.coherency_line_size = line_size - 1; - ebx->split.ways_of_associativity = assocs[assoc] - 1; - ebx->split.physical_line_partition = lines_per_tag - 1; - ecx->split.number_of_sets = (size_in_kb * 1024) / line_size / - (ebx->split.ways_of_associativity + 1) - 1; -} - -static int __cpuinit cpuid4_cache_lookup(int index, struct _cpuid4_info *this_leaf) -{ - union _cpuid4_leaf_eax eax; - union _cpuid4_leaf_ebx ebx; - union _cpuid4_leaf_ecx ecx; - unsigned edx; - - if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD) - amd_cpuid4(index, &eax, &ebx, &ecx); - else - cpuid_count(4, index, &eax.full, &ebx.full, &ecx.full, &edx); - if (eax.split.type == CACHE_TYPE_NULL) - return -EIO; /* better error ? */ - - this_leaf->eax = eax; - this_leaf->ebx = ebx; - this_leaf->ecx = ecx; - this_leaf->size = (ecx.split.number_of_sets + 1) * - (ebx.split.coherency_line_size + 1) * - (ebx.split.physical_line_partition + 1) * - (ebx.split.ways_of_associativity + 1); - return 0; -} - -/* will only be called once; __init is safe here */ -static int __init find_num_cache_leaves(void) -{ - unsigned int eax, ebx, ecx, edx; - union _cpuid4_leaf_eax cache_eax; - int i = -1; - - do { - ++i; - /* Do cpuid(4) loop to find out num_cache_leaves */ - cpuid_count(4, i, &eax, &ebx, &ecx, &edx); - cache_eax.full = eax; - } while (cache_eax.split.type != CACHE_TYPE_NULL); - return i; -} - -unsigned int __cpuinit init_intel_cacheinfo(struct cpuinfo_x86 *c) -{ - unsigned int trace = 0, l1i = 0, l1d = 0, l2 = 0, l3 = 0; /* Cache sizes */ - unsigned int new_l1d = 0, new_l1i = 0; /* Cache sizes from cpuid(4) */ - unsigned int new_l2 = 0, new_l3 = 0, i; /* Cache sizes from cpuid(4) */ - unsigned int l2_id = 0, l3_id = 0, num_threads_sharing, index_msb; -#ifdef CONFIG_X86_HT - unsigned int cpu = (c == &boot_cpu_data) ? 0 : (c - cpu_data); -#endif - - if (c->cpuid_level > 3) { - static int is_initialized; - - if (is_initialized == 0) { - /* Init num_cache_leaves from boot CPU */ - num_cache_leaves = find_num_cache_leaves(); - is_initialized++; - } - - /* - * Whenever possible use cpuid(4), deterministic cache - * parameters cpuid leaf to find the cache details - */ - for (i = 0; i < num_cache_leaves; i++) { - struct _cpuid4_info this_leaf; - - int retval; - - retval = cpuid4_cache_lookup(i, &this_leaf); - if (retval >= 0) { - switch(this_leaf.eax.split.level) { - case 1: - if (this_leaf.eax.split.type == - CACHE_TYPE_DATA) - new_l1d = this_leaf.size/1024; - else if (this_leaf.eax.split.type == - CACHE_TYPE_INST) - new_l1i = this_leaf.size/1024; - break; - case 2: - new_l2 = this_leaf.size/1024; - num_threads_sharing = 1 + this_leaf.eax.split.num_threads_sharing; - index_msb = get_count_order(num_threads_sharing); - l2_id = c->apicid >> index_msb; - break; - case 3: - new_l3 = this_leaf.size/1024; - num_threads_sharing = 1 + this_leaf.eax.split.num_threads_sharing; - index_msb = get_count_order(num_threads_sharing); - l3_id = c->apicid >> index_msb; - break; - default: - break; - } - } - } - } - /* - * Don't use cpuid2 if cpuid4 is supported. For P4, we use cpuid2 for - * trace cache - */ - if ((num_cache_leaves == 0 || c->x86 == 15) && c->cpuid_level > 1) { - /* supports eax=2 call */ - int i, j, n; - int regs[4]; - unsigned char *dp = (unsigned char *)regs; - int only_trace = 0; - - if (num_cache_leaves != 0 && c->x86 == 15) - only_trace = 1; - - /* Number of times to iterate */ - n = cpuid_eax(2) & 0xFF; - - for ( i = 0 ; i < n ; i++ ) { - cpuid(2, ®s[0], ®s[1], ®s[2], ®s[3]); - - /* If bit 31 is set, this is an unknown format */ - for ( j = 0 ; j < 3 ; j++ ) { - if ( regs[j] < 0 ) regs[j] = 0; - } - - /* Byte 0 is level count, not a descriptor */ - for ( j = 1 ; j < 16 ; j++ ) { - unsigned char des = dp[j]; - unsigned char k = 0; - - /* look up this descriptor in the table */ - while (cache_table[k].descriptor != 0) - { - if (cache_table[k].descriptor == des) { - if (only_trace && cache_table[k].cache_type != LVL_TRACE) - break; - switch (cache_table[k].cache_type) { - case LVL_1_INST: - l1i += cache_table[k].size; - break; - case LVL_1_DATA: - l1d += cache_table[k].size; - break; - case LVL_2: - l2 += cache_table[k].size; - break; - case LVL_3: - l3 += cache_table[k].size; - break; - case LVL_TRACE: - trace += cache_table[k].size; - break; - } - - break; - } - - k++; - } - } - } - } - - if (new_l1d) - l1d = new_l1d; - - if (new_l1i) - l1i = new_l1i; - - if (new_l2) { - l2 = new_l2; -#ifdef CONFIG_X86_HT - cpu_llc_id[cpu] = l2_id; -#endif - } - - if (new_l3) { - l3 = new_l3; -#ifdef CONFIG_X86_HT - cpu_llc_id[cpu] = l3_id; -#endif - } - - if (trace) - printk (KERN_INFO "CPU: Trace cache: %dK uops", trace); - else if ( l1i ) - printk (KERN_INFO "CPU: L1 I cache: %dK", l1i); - - if (l1d) - printk(", L1 D cache: %dK\n", l1d); - else - printk("\n"); - - if (l2) - printk(KERN_INFO "CPU: L2 cache: %dK\n", l2); - - if (l3) - printk(KERN_INFO "CPU: L3 cache: %dK\n", l3); - - c->x86_cache_size = l3 ? l3 : (l2 ? l2 : (l1i+l1d)); - - return l2; -} - -/* pointer to _cpuid4_info array (for each cache leaf) */ -static struct _cpuid4_info *cpuid4_info[NR_CPUS]; -#define CPUID4_INFO_IDX(x,y) (&((cpuid4_info[x])[y])) - -#ifdef CONFIG_SMP -static void __cpuinit cache_shared_cpu_map_setup(unsigned int cpu, int index) -{ - struct _cpuid4_info *this_leaf, *sibling_leaf; - unsigned long num_threads_sharing; - int index_msb, i; - struct cpuinfo_x86 *c = cpu_data; - - this_leaf = CPUID4_INFO_IDX(cpu, index); - num_threads_sharing = 1 + this_leaf->eax.split.num_threads_sharing; - - if (num_threads_sharing == 1) - cpu_set(cpu, this_leaf->shared_cpu_map); - else { - index_msb = get_count_order(num_threads_sharing); - - for_each_online_cpu(i) { - if (c[i].apicid >> index_msb == - c[cpu].apicid >> index_msb) { - cpu_set(i, this_leaf->shared_cpu_map); - if (i != cpu && cpuid4_info[i]) { - sibling_leaf = CPUID4_INFO_IDX(i, index); - cpu_set(cpu, sibling_leaf->shared_cpu_map); - } - } - } - } -} -static void __cpuinit cache_remove_shared_cpu_map(unsigned int cpu, int index) -{ - struct _cpuid4_info *this_leaf, *sibling_leaf; - int sibling; - - this_leaf = CPUID4_INFO_IDX(cpu, index); - for_each_cpu_mask(sibling, this_leaf->shared_cpu_map) { - sibling_leaf = CPUID4_INFO_IDX(sibling, index); - cpu_clear(cpu, sibling_leaf->shared_cpu_map); - } -} -#else -static void __init cache_shared_cpu_map_setup(unsigned int cpu, int index) {} -static void __init cache_remove_shared_cpu_map(unsigned int cpu, int index) {} -#endif - -static void free_cache_attributes(unsigned int cpu) -{ - kfree(cpuid4_info[cpu]); - cpuid4_info[cpu] = NULL; -} - -static int __cpuinit detect_cache_attributes(unsigned int cpu) -{ - struct _cpuid4_info *this_leaf; - unsigned long j; - int retval; - cpumask_t oldmask; - - if (num_cache_leaves == 0) - return -ENOENT; - - cpuid4_info[cpu] = kmalloc( - sizeof(struct _cpuid4_info) * num_cache_leaves, GFP_KERNEL); - if (unlikely(cpuid4_info[cpu] == NULL)) - return -ENOMEM; - memset(cpuid4_info[cpu], 0, - sizeof(struct _cpuid4_info) * num_cache_leaves); - - oldmask = current->cpus_allowed; - retval = set_cpus_allowed(current, cpumask_of_cpu(cpu)); - if (retval) - goto out; - - /* Do cpuid and store the results */ - retval = 0; - for (j = 0; j < num_cache_leaves; j++) { - this_leaf = CPUID4_INFO_IDX(cpu, j); - retval = cpuid4_cache_lookup(j, this_leaf); - if (unlikely(retval < 0)) - break; - cache_shared_cpu_map_setup(cpu, j); - } - set_cpus_allowed(current, oldmask); - -out: - if (retval) - free_cache_attributes(cpu); - return retval; -} - -#ifdef CONFIG_SYSFS - -#include -#include - -extern struct sysdev_class cpu_sysdev_class; /* from drivers/base/cpu.c */ - -/* pointer to kobject for cpuX/cache */ -static struct kobject * cache_kobject[NR_CPUS]; - -struct _index_kobject { - struct kobject kobj; - unsigned int cpu; - unsigned short index; -}; - -/* pointer to array of kobjects for cpuX/cache/indexY */ -static struct _index_kobject *index_kobject[NR_CPUS]; -#define INDEX_KOBJECT_PTR(x,y) (&((index_kobject[x])[y])) - -#define show_one_plus(file_name, object, val) \ -static ssize_t show_##file_name \ - (struct _cpuid4_info *this_leaf, char *buf) \ -{ \ - return sprintf (buf, "%lu\n", (unsigned long)this_leaf->object + val); \ -} - -show_one_plus(level, eax.split.level, 0); -show_one_plus(coherency_line_size, ebx.split.coherency_line_size, 1); -show_one_plus(physical_line_partition, ebx.split.physical_line_partition, 1); -show_one_plus(ways_of_associativity, ebx.split.ways_of_associativity, 1); -show_one_plus(number_of_sets, ecx.split.number_of_sets, 1); - -static ssize_t show_size(struct _cpuid4_info *this_leaf, char *buf) -{ - return sprintf (buf, "%luK\n", this_leaf->size / 1024); -} - -static ssize_t show_shared_cpu_map(struct _cpuid4_info *this_leaf, char *buf) -{ - char mask_str[NR_CPUS]; - cpumask_scnprintf(mask_str, NR_CPUS, this_leaf->shared_cpu_map); - return sprintf(buf, "%s\n", mask_str); -} - -static ssize_t show_type(struct _cpuid4_info *this_leaf, char *buf) { - switch(this_leaf->eax.split.type) { - case CACHE_TYPE_DATA: - return sprintf(buf, "Data\n"); - break; - case CACHE_TYPE_INST: - return sprintf(buf, "Instruction\n"); - break; - case CACHE_TYPE_UNIFIED: - return sprintf(buf, "Unified\n"); - break; - default: - return sprintf(buf, "Unknown\n"); - break; - } -} - -struct _cache_attr { - struct attribute attr; - ssize_t (*show)(struct _cpuid4_info *, char *); - ssize_t (*store)(struct _cpuid4_info *, const char *, size_t count); -}; - -#define define_one_ro(_name) \ -static struct _cache_attr _name = \ - __ATTR(_name, 0444, show_##_name, NULL) - -define_one_ro(level); -define_one_ro(type); -define_one_ro(coherency_line_size); -define_one_ro(physical_line_partition); -define_one_ro(ways_of_associativity); -define_one_ro(number_of_sets); -define_one_ro(size); -define_one_ro(shared_cpu_map); - -static struct attribute * default_attrs[] = { - &type.attr, - &level.attr, - &coherency_line_size.attr, - &physical_line_partition.attr, - &ways_of_associativity.attr, - &number_of_sets.attr, - &size.attr, - &shared_cpu_map.attr, - NULL -}; - -#define to_object(k) container_of(k, struct _index_kobject, kobj) -#define to_attr(a) container_of(a, struct _cache_attr, attr) - -static ssize_t show(struct kobject * kobj, struct attribute * attr, char * buf) -{ - struct _cache_attr *fattr = to_attr(attr); - struct _index_kobject *this_leaf = to_object(kobj); - ssize_t ret; - - ret = fattr->show ? - fattr->show(CPUID4_INFO_IDX(this_leaf->cpu, this_leaf->index), - buf) : - 0; - return ret; -} - -static ssize_t store(struct kobject * kobj, struct attribute * attr, - const char * buf, size_t count) -{ - return 0; -} - -static struct sysfs_ops sysfs_ops = { - .show = show, - .store = store, -}; - -static struct kobj_type ktype_cache = { - .sysfs_ops = &sysfs_ops, - .default_attrs = default_attrs, -}; - -static struct kobj_type ktype_percpu_entry = { - .sysfs_ops = &sysfs_ops, -}; - -static void cpuid4_cache_sysfs_exit(unsigned int cpu) -{ - kfree(cache_kobject[cpu]); - kfree(index_kobject[cpu]); - cache_kobject[cpu] = NULL; - index_kobject[cpu] = NULL; - free_cache_attributes(cpu); -} - -static int __cpuinit cpuid4_cache_sysfs_init(unsigned int cpu) -{ - - if (num_cache_leaves == 0) - return -ENOENT; - - detect_cache_attributes(cpu); - if (cpuid4_info[cpu] == NULL) - return -ENOENT; - - /* Allocate all required memory */ - cache_kobject[cpu] = kmalloc(sizeof(struct kobject), GFP_KERNEL); - if (unlikely(cache_kobject[cpu] == NULL)) - goto err_out; - memset(cache_kobject[cpu], 0, sizeof(struct kobject)); - - index_kobject[cpu] = kmalloc( - sizeof(struct _index_kobject ) * num_cache_leaves, GFP_KERNEL); - if (unlikely(index_kobject[cpu] == NULL)) - goto err_out; - memset(index_kobject[cpu], 0, - sizeof(struct _index_kobject) * num_cache_leaves); - - return 0; - -err_out: - cpuid4_cache_sysfs_exit(cpu); - return -ENOMEM; -} - -/* Add/Remove cache interface for CPU device */ -static int __cpuinit cache_add_dev(struct sys_device * sys_dev) -{ - unsigned int cpu = sys_dev->id; - unsigned long i, j; - struct _index_kobject *this_object; - int retval = 0; - - retval = cpuid4_cache_sysfs_init(cpu); - if (unlikely(retval < 0)) - return retval; - - cache_kobject[cpu]->parent = &sys_dev->kobj; - kobject_set_name(cache_kobject[cpu], "%s", "cache"); - cache_kobject[cpu]->ktype = &ktype_percpu_entry; - retval = kobject_register(cache_kobject[cpu]); - - for (i = 0; i < num_cache_leaves; i++) { - this_object = INDEX_KOBJECT_PTR(cpu,i); - this_object->cpu = cpu; - this_object->index = i; - this_object->kobj.parent = cache_kobject[cpu]; - kobject_set_name(&(this_object->kobj), "index%1lu", i); - this_object->kobj.ktype = &ktype_cache; - retval = kobject_register(&(this_object->kobj)); - if (unlikely(retval)) { - for (j = 0; j < i; j++) { - kobject_unregister( - &(INDEX_KOBJECT_PTR(cpu,j)->kobj)); - } - kobject_unregister(cache_kobject[cpu]); - cpuid4_cache_sysfs_exit(cpu); - break; - } - } - return retval; -} - -static void __cpuexit cache_remove_dev(struct sys_device * sys_dev) -{ - unsigned int cpu = sys_dev->id; - unsigned long i; - - for (i = 0; i < num_cache_leaves; i++) { - cache_remove_shared_cpu_map(cpu, i); - kobject_unregister(&(INDEX_KOBJECT_PTR(cpu,i)->kobj)); - } - kobject_unregister(cache_kobject[cpu]); - cpuid4_cache_sysfs_exit(cpu); - return; -} - -static int __cpuinit cacheinfo_cpu_callback(struct notifier_block *nfb, - unsigned long action, void *hcpu) -{ - unsigned int cpu = (unsigned long)hcpu; - struct sys_device *sys_dev; - - sys_dev = get_cpu_sysdev(cpu); - switch (action) { - case CPU_ONLINE: - cache_add_dev(sys_dev); - break; - case CPU_DEAD: - cache_remove_dev(sys_dev); - break; - } - return NOTIFY_OK; -} - -static struct notifier_block __cpuinitdata cacheinfo_cpu_notifier = -{ - .notifier_call = cacheinfo_cpu_callback, -}; - -static int __cpuinit cache_sysfs_init(void) -{ - int i; - - if (num_cache_leaves == 0) - return 0; - - register_hotcpu_notifier(&cacheinfo_cpu_notifier); - - for_each_online_cpu(i) { - cacheinfo_cpu_callback(&cacheinfo_cpu_notifier, CPU_ONLINE, - (void *)(long)i); - } - - return 0; -} - -device_initcall(cache_sysfs_init); - -#endif diff --git a/linux-2.6-xen-sparse/arch/i386/kernel/entry-xen.S b/linux-2.6-xen-sparse/arch/i386/kernel/entry-xen.S index ab569d974b..c7f38485cf 100644 --- a/linux-2.6-xen-sparse/arch/i386/kernel/entry-xen.S +++ b/linux-2.6-xen-sparse/arch/i386/kernel/entry-xen.S @@ -368,6 +368,7 @@ sysexit_scrit: /**** START OF SYSEXIT CRITICAL REGION ****/ movl ESI(%esp), %esi sysexit 14: __DISABLE_INTERRUPTS + TRACE_IRQS_OFF sysexit_ecrit: /**** END OF SYSEXIT CRITICAL REGION ****/ push %esp call evtchn_do_upcall @@ -427,11 +428,13 @@ restore_nocheck: restore_nocheck: movl EFLAGS(%esp), %eax testl $(VM_MASK|NMI_MASK), %eax + CFI_REMEMBER_STATE jnz hypervisor_iret shr $9, %eax # EAX[0] == IRET_EFLAGS.IF GET_VCPU_INFO andb evtchn_upcall_mask(%esi),%al andb $1,%al # EAX[0] == IRET_EFLAGS.IF & event_mask + CFI_REMEMBER_STATE jnz restore_all_enable_events # != 0 => enable event delivery #endif TRACE_IRQS_IRET @@ -455,8 +458,8 @@ iret_exc: .long 1b,iret_exc .previous -#ifndef CONFIG_XEN CFI_RESTORE_STATE +#ifndef CONFIG_XEN ldt_ss: larl OLDSS(%esp), %eax jnz restore_nocheck @@ -485,14 +488,36 @@ ldt_ss: .align 4 .long 1b,iret_exc .previous - CFI_ENDPROC #else + ALIGN +restore_all_enable_events: + TRACE_IRQS_ON + __ENABLE_INTERRUPTS +scrit: /**** START OF CRITICAL REGION ****/ + __TEST_PENDING + jnz 14f # process more events if necessary... + RESTORE_REGS + addl $4, %esp + CFI_ADJUST_CFA_OFFSET -4 +1: iret +.section __ex_table,"a" + .align 4 + .long 1b,iret_exc +.previous +14: __DISABLE_INTERRUPTS + TRACE_IRQS_OFF + jmp 11f +ecrit: /**** END OF CRITICAL REGION ****/ + + CFI_RESTORE_STATE hypervisor_iret: andl $~NMI_MASK, EFLAGS(%esp) RESTORE_REGS addl $4, %esp + CFI_ADJUST_CFA_OFFSET -4 jmp hypercall_page + (__HYPERVISOR_iret * 32) #endif + CFI_ENDPROC # perform work that needs to be done immediately before resumption ALIGN @@ -736,7 +761,9 @@ error_code: # critical region we know that the entire frame is present and correct # so we can simply throw away the new one. ENTRY(hypervisor_callback) + RING0_INT_FRAME pushl %eax + CFI_ADJUST_CFA_OFFSET 4 SAVE_ALL movl EIP(%esp),%eax cmpl $scrit,%eax @@ -749,26 +776,13 @@ ENTRY(hypervisor_callback) ja 11f addl $OLDESP,%esp # Remove eflags...ebx from stack frame. 11: push %esp + CFI_ADJUST_CFA_OFFSET 4 call evtchn_do_upcall add $4,%esp + CFI_ADJUST_CFA_OFFSET -4 jmp ret_from_intr + CFI_ENDPROC - ALIGN -restore_all_enable_events: - __ENABLE_INTERRUPTS -scrit: /**** START OF CRITICAL REGION ****/ - __TEST_PENDING - jnz 14f # process more events if necessary... - RESTORE_REGS - addl $4, %esp -1: iret -.section __ex_table,"a" - .align 4 - .long 1b,iret_exc -.previous -14: __DISABLE_INTERRUPTS - jmp 11b -ecrit: /**** END OF CRITICAL REGION ****/ # [How we do the fixup]. We want to merge the current stack frame with the # just-interrupted frame. How we do this depends on where in the critical # region the interrupted handler was executing, and so how many saved @@ -835,6 +849,7 @@ ENTRY(failsafe_callback) addl $16,%esp # EAX != 0 => Category 2 (Bad IRET) jmp iret_exc 5: addl $16,%esp # EAX == 0 => Category 1 (Bad segment) + RING0_INT_FRAME pushl $0 SAVE_ALL jmp ret_from_exception @@ -860,6 +875,7 @@ ENTRY(failsafe_callback) .long 4b,9b; \ .previous #endif + CFI_ENDPROC ENTRY(coprocessor_error) RING0_INT_FRAME @@ -1187,8 +1203,11 @@ ENDPROC(arch_unwind_init_running) #endif ENTRY(fixup_4gb_segment) + RING0_EC_FRAME pushl $do_fixup_4gb_segment + CFI_ADJUST_CFA_OFFSET 4 jmp error_code + CFI_ENDPROC .section .rodata,"a" .align 4 diff --git a/linux-2.6-xen-sparse/arch/i386/kernel/fixup.c b/linux-2.6-xen-sparse/arch/i386/kernel/fixup.c index f7e6feedee..aa6b12c2fd 100644 --- a/linux-2.6-xen-sparse/arch/i386/kernel/fixup.c +++ b/linux-2.6-xen-sparse/arch/i386/kernel/fixup.c @@ -27,7 +27,6 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include #include #include #include diff --git a/linux-2.6-xen-sparse/arch/i386/kernel/head-xen.S b/linux-2.6-xen-sparse/arch/i386/kernel/head-xen.S index d788f323ae..2bd3dbfeb0 100644 --- a/linux-2.6-xen-sparse/arch/i386/kernel/head-xen.S +++ b/linux-2.6-xen-sparse/arch/i386/kernel/head-xen.S @@ -9,11 +9,10 @@ #include #include #include +#include #include #include -#define _PAGE_PRESENT 0x1 - /* * References to members of the new_cpu_data structure. */ @@ -65,14 +64,13 @@ ENTRY(startup_32) pushl %eax # fake return address jmp start_kernel -L6: - jmp L6 # main should never return here, but - # just in case, we know what happens. #define HYPERCALL_PAGE_OFFSET 0x1000 .org HYPERCALL_PAGE_OFFSET ENTRY(hypercall_page) + CFI_STARTPROC .skip 0x1000 + CFI_ENDPROC /* * Real beginning of normal "text" segment @@ -206,3 +204,4 @@ ENTRY(cpu_gdt_table) ELFNOTE(Xen, XEN_ELFNOTE_L1_MFN_VALID, .long, _PAGE_PRESENT,_PAGE_PRESENT) #endif ELFNOTE(Xen, XEN_ELFNOTE_LOADER, .asciz, "generic") + ELFNOTE(Xen, XEN_ELFNOTE_SUSPEND_CANCEL, .long, 1) diff --git a/linux-2.6-xen-sparse/arch/i386/kernel/process-xen.c b/linux-2.6-xen-sparse/arch/i386/kernel/process-xen.c index 76d9b15481..2225fcc962 100644 --- a/linux-2.6-xen-sparse/arch/i386/kernel/process-xen.c +++ b/linux-2.6-xen-sparse/arch/i386/kernel/process-xen.c @@ -60,9 +60,6 @@ #include #include -#include -#include - asmlinkage void ret_from_fork(void) __asm__("ret_from_fork"); static int hlt_counter; @@ -104,7 +101,7 @@ EXPORT_SYMBOL(enable_hlt); * to poll the ->work.need_resched flag instead of waiting for the * cross-CPU IPI to arrive. Use this option with caution. */ -static void poll_idle(void) +static void poll_idle (void) { local_irq_enable(); @@ -172,10 +169,7 @@ void cpu_idle(void) __get_cpu_var(cpu_idle_state) = 0; rmb(); - idle = pm_idle; - - if (!idle) - idle = xen_idle; + idle = xen_idle; /* no alternatives */ if (cpu_is_offline(cpu)) play_dead(); diff --git a/linux-2.6-xen-sparse/arch/i386/kernel/setup-xen.c b/linux-2.6-xen-sparse/arch/i386/kernel/setup-xen.c index 8afbd64e64..15cd36142f 100644 --- a/linux-2.6-xen-sparse/arch/i386/kernel/setup-xen.c +++ b/linux-2.6-xen-sparse/arch/i386/kernel/setup-xen.c @@ -1847,6 +1847,9 @@ static __init int add_pcspkr(void) struct platform_device *pd; int ret; + if (!is_initial_xendomain()) + return 0; + pd = platform_device_alloc("pcspkr", -1); if (!pd) return -ENOMEM; diff --git a/linux-2.6-xen-sparse/arch/i386/kernel/time-xen.c b/linux-2.6-xen-sparse/arch/i386/kernel/time-xen.c index 9dc489b404..b57ab9bdfe 100644 --- a/linux-2.6-xen-sparse/arch/i386/kernel/time-xen.c +++ b/linux-2.6-xen-sparse/arch/i386/kernel/time-xen.c @@ -1022,16 +1022,21 @@ void halt(void) } EXPORT_SYMBOL(halt); -/* No locking required. We are only CPU running, and interrupts are off. */ +/* No locking required. Interrupts are disabled on all CPUs. */ void time_resume(void) { + unsigned int cpu; + init_cpu_khz(); - get_time_values_from_xen(0); + for_each_online_cpu(cpu) { + get_time_values_from_xen(cpu); + per_cpu(processed_system_time, cpu) = + per_cpu(shadow_time, 0).system_timestamp; + init_missing_ticks_accounting(cpu); + } processed_system_time = per_cpu(shadow_time, 0).system_timestamp; - per_cpu(processed_system_time, 0) = processed_system_time; - init_missing_ticks_accounting(0); update_wallclock(); } diff --git a/linux-2.6-xen-sparse/arch/i386/mm/hypervisor.c b/linux-2.6-xen-sparse/arch/i386/mm/hypervisor.c index 3c20351e92..7c9a60aace 100644 --- a/linux-2.6-xen-sparse/arch/i386/mm/hypervisor.c +++ b/linux-2.6-xen-sparse/arch/i386/mm/hypervisor.c @@ -30,7 +30,6 @@ * IN THE SOFTWARE. */ -#include #include #include #include diff --git a/linux-2.6-xen-sparse/arch/i386/mm/ioremap-xen.c b/linux-2.6-xen-sparse/arch/i386/mm/ioremap-xen.c index b2e8832b85..bd13dbdade 100644 --- a/linux-2.6-xen-sparse/arch/i386/mm/ioremap-xen.c +++ b/linux-2.6-xen-sparse/arch/i386/mm/ioremap-xen.c @@ -374,8 +374,6 @@ void iounmap(volatile void __iomem *addr) } EXPORT_SYMBOL(iounmap); -#ifdef __i386__ - void __init *bt_ioremap(unsigned long phys_addr, unsigned long size) { unsigned long offset, last_addr; @@ -443,5 +441,3 @@ void __init bt_iounmap(void *addr, unsigned long size) --nrpages; } } - -#endif /* __i386__ */ diff --git a/linux-2.6-xen-sparse/arch/i386/mm/pgtable-xen.c b/linux-2.6-xen-sparse/arch/i386/mm/pgtable-xen.c index 18f27c7cde..4f72489800 100644 --- a/linux-2.6-xen-sparse/arch/i386/mm/pgtable-xen.c +++ b/linux-2.6-xen-sparse/arch/i386/mm/pgtable-xen.c @@ -573,64 +573,67 @@ void make_pages_writable(void *va, unsigned int nr, unsigned int feature) } } -static inline int pgd_walk_set_prot(struct page *page, pgprot_t flags) +static inline void pgd_walk_set_prot(struct page *page, pgprot_t flags) { unsigned long pfn = page_to_pfn(page); + int rc; - if (PageHighMem(page)) - return pgprot_val(flags) & _PAGE_RW - ? test_and_clear_bit(PG_pinned, &page->flags) - : !test_and_set_bit(PG_pinned, &page->flags); - - BUG_ON(HYPERVISOR_update_va_mapping( - (unsigned long)__va(pfn << PAGE_SHIFT), - pfn_pte(pfn, flags), 0)); - - return 0; + if (PageHighMem(page)) { + if (pgprot_val(flags) & _PAGE_RW) + clear_bit(PG_pinned, &page->flags); + else + set_bit(PG_pinned, &page->flags); + } else { + rc = HYPERVISOR_update_va_mapping( + (unsigned long)__va(pfn << PAGE_SHIFT), + pfn_pte(pfn, flags), 0); + if (rc) + BUG(); + } } -static int pgd_walk(pgd_t *pgd_base, pgprot_t flags) +static void pgd_walk(pgd_t *pgd_base, pgprot_t flags) { pgd_t *pgd = pgd_base; pud_t *pud; pmd_t *pmd; - int g, u, m, flush; + int g, u, m, rc; if (xen_feature(XENFEAT_auto_translated_physmap)) return 0; - for (g = 0, flush = 0; g < USER_PTRS_PER_PGD; g++, pgd++) { + for (g = 0; g < USER_PTRS_PER_PGD; g++, pgd++) { if (pgd_none(*pgd)) continue; pud = pud_offset(pgd, 0); if (PTRS_PER_PUD > 1) /* not folded */ - flush |= pgd_walk_set_prot(virt_to_page(pud),flags); + pgd_walk_set_prot(virt_to_page(pud),flags); for (u = 0; u < PTRS_PER_PUD; u++, pud++) { if (pud_none(*pud)) continue; pmd = pmd_offset(pud, 0); if (PTRS_PER_PMD > 1) /* not folded */ - flush |= pgd_walk_set_prot(virt_to_page(pmd),flags); + pgd_walk_set_prot(virt_to_page(pmd),flags); for (m = 0; m < PTRS_PER_PMD; m++, pmd++) { if (pmd_none(*pmd)) continue; - flush |= pgd_walk_set_prot(pmd_page(*pmd),flags); + pgd_walk_set_prot(pmd_page(*pmd),flags); } } } - BUG_ON(HYPERVISOR_update_va_mapping( + rc = HYPERVISOR_update_va_mapping( (unsigned long)pgd_base, pfn_pte(virt_to_phys(pgd_base)>>PAGE_SHIFT, flags), - UVMF_TLB_FLUSH)); - - return flush; + UVMF_TLB_FLUSH); + if (rc) + BUG(); } static void __pgd_pin(pgd_t *pgd) { - if (pgd_walk(pgd, PAGE_KERNEL_RO)) - kmap_flush_unused(); + pgd_walk(pgd, PAGE_KERNEL_RO); + kmap_flush_unused(); xen_pgd_pin(__pa(pgd)); set_bit(PG_pinned, &virt_to_page(pgd)->flags); } @@ -638,8 +641,7 @@ static void __pgd_pin(pgd_t *pgd) static void __pgd_unpin(pgd_t *pgd) { xen_pgd_unpin(__pa(pgd)); - if (pgd_walk(pgd, PAGE_KERNEL)) - kmap_flush_unused(); + pgd_walk(pgd, PAGE_KERNEL); clear_bit(PG_pinned, &virt_to_page(pgd)->flags); } @@ -671,9 +673,6 @@ void mm_pin_all(void) { struct page *page; - /* Only pgds on the pgd_list please: none hidden in the slab cache. */ - kmem_cache_shrink(pgd_cache); - if (xen_feature(XENFEAT_writable_page_tables)) return; diff --git a/linux-2.6-xen-sparse/arch/ia64/oprofile/oprofile_perfmon.h b/linux-2.6-xen-sparse/arch/ia64/oprofile/oprofile_perfmon.h index 14f1677aea..6ba1170bd6 100644 --- a/linux-2.6-xen-sparse/arch/ia64/oprofile/oprofile_perfmon.h +++ b/linux-2.6-xen-sparse/arch/ia64/oprofile/oprofile_perfmon.h @@ -1,8 +1,6 @@ #ifndef OPROFILE_PERFMON_H #define OPROFILE_PERFMON_H -#include - #ifdef CONFIG_PERFMON int __perfmon_init(void); void __perfmon_exit(void); diff --git a/linux-2.6-xen-sparse/arch/ia64/xen/hypercall.S b/linux-2.6-xen-sparse/arch/ia64/xen/hypercall.S index 0e2b1cf9d0..dc5977886e 100644 --- a/linux-2.6-xen-sparse/arch/ia64/xen/hypercall.S +++ b/linux-2.6-xen-sparse/arch/ia64/xen/hypercall.S @@ -4,7 +4,6 @@ * Copyright (C) 2005 Dan Magenheimer */ -#include #include #include diff --git a/linux-2.6-xen-sparse/arch/ia64/xen/mem.c b/linux-2.6-xen-sparse/arch/ia64/xen/mem.c index 1c995b6f11..dc93097c70 100644 --- a/linux-2.6-xen-sparse/arch/ia64/xen/mem.c +++ b/linux-2.6-xen-sparse/arch/ia64/xen/mem.c @@ -15,7 +15,6 @@ * VA Linux Systems Japan K.K. */ -#include #include #include diff --git a/linux-2.6-xen-sparse/arch/ia64/xen/util.c b/linux-2.6-xen-sparse/arch/ia64/xen/util.c index 9976201b37..387a1c3368 100644 --- a/linux-2.6-xen-sparse/arch/ia64/xen/util.c +++ b/linux-2.6-xen-sparse/arch/ia64/xen/util.c @@ -21,7 +21,6 @@ * */ -#include #include #include #include diff --git a/linux-2.6-xen-sparse/arch/ia64/xen/xcom_privcmd.c b/linux-2.6-xen-sparse/arch/ia64/xen/xcom_privcmd.c index 0f5fccdac7..e1e312d204 100644 --- a/linux-2.6-xen-sparse/arch/ia64/xen/xcom_privcmd.c +++ b/linux-2.6-xen-sparse/arch/ia64/xen/xcom_privcmd.c @@ -303,6 +303,7 @@ xencomm_privcmd_domctl(privcmd_hypercall_t *hypercall) case XEN_DOMCTL_hypercall_init: case XEN_DOMCTL_arch_setup: case XEN_DOMCTL_settimeoffset: + case XEN_DOMCTL_sendtrigger: break; default: printk("%s: unknown domctl cmd %d\n", __func__, kern_op.cmd); diff --git a/linux-2.6-xen-sparse/arch/ia64/xen/xenentry.S b/linux-2.6-xen-sparse/arch/ia64/xen/xenentry.S index 08bd970460..e122449c16 100644 --- a/linux-2.6-xen-sparse/arch/ia64/xen/xenentry.S +++ b/linux-2.6-xen-sparse/arch/ia64/xen/xenentry.S @@ -8,8 +8,6 @@ * Dan Magenheimer */ -#include - #include #include #include diff --git a/linux-2.6-xen-sparse/arch/ia64/xen/xenivt.S b/linux-2.6-xen-sparse/arch/ia64/xen/xenivt.S index c7648e0bcd..eaa9801bf0 100644 --- a/linux-2.6-xen-sparse/arch/ia64/xen/xenivt.S +++ b/linux-2.6-xen-sparse/arch/ia64/xen/xenivt.S @@ -29,8 +29,6 @@ * Table is based upon EAS2.6 (Oct 1999) */ -#include - #include #include #include diff --git a/linux-2.6-xen-sparse/arch/ia64/xen/xenminstate.h b/linux-2.6-xen-sparse/arch/ia64/xen/xenminstate.h index 75ec49f886..5741b4e75d 100644 --- a/linux-2.6-xen-sparse/arch/ia64/xen/xenminstate.h +++ b/linux-2.6-xen-sparse/arch/ia64/xen/xenminstate.h @@ -1,5 +1,3 @@ -#include - #include #ifdef CONFIG_XEN diff --git a/linux-2.6-xen-sparse/arch/ia64/xen/xensetup.S b/linux-2.6-xen-sparse/arch/ia64/xen/xensetup.S index c295cc3431..469f39e226 100644 --- a/linux-2.6-xen-sparse/arch/ia64/xen/xensetup.S +++ b/linux-2.6-xen-sparse/arch/ia64/xen/xensetup.S @@ -4,7 +4,6 @@ * Copyright (C) 2005 Dan Magenheimer */ -#include #include #include diff --git a/linux-2.6-xen-sparse/arch/x86_64/Kconfig b/linux-2.6-xen-sparse/arch/x86_64/Kconfig index ae0f21a97f..09d6e4f926 100644 --- a/linux-2.6-xen-sparse/arch/x86_64/Kconfig +++ b/linux-2.6-xen-sparse/arch/x86_64/Kconfig @@ -450,7 +450,7 @@ config CALGARY_IOMMU bool "IBM Calgary IOMMU support" default y select SWIOTLB - depends on PCI && EXPERIMENTAL + depends on PCI && !X86_64_XEN && EXPERIMENTAL help Support for hardware IOMMUs in IBM's xSeries x366 and x460 systems. Needed to run systems with more than 3GB of memory diff --git a/linux-2.6-xen-sparse/arch/x86_64/kernel/Makefile b/linux-2.6-xen-sparse/arch/x86_64/kernel/Makefile index ae36f842a4..fca2eae4d6 100644 --- a/linux-2.6-xen-sparse/arch/x86_64/kernel/Makefile +++ b/linux-2.6-xen-sparse/arch/x86_64/kernel/Makefile @@ -61,9 +61,7 @@ ifdef CONFIG_XEN time-y += ../../i386/kernel/time-xen.o pci-dma-y += ../../i386/kernel/pci-dma-xen.o microcode-$(subst m,y,$(CONFIG_MICROCODE)) := ../../i386/kernel/microcode-xen.o -intel_cacheinfo-y := ../../i386/kernel/cpu/intel_cacheinfo-xen.o quirks-y := ../../i386/kernel/quirks-xen.o -alternative-y := ../../i386/kernel/alternative-xen.o n-obj-xen := i8259.o reboot.o i8237.o smpboot.o trampoline.o diff --git a/linux-2.6-xen-sparse/arch/x86_64/kernel/early_printk-xen.c b/linux-2.6-xen-sparse/arch/x86_64/kernel/early_printk-xen.c index 19cc717324..090f670a7e 100644 --- a/linux-2.6-xen-sparse/arch/x86_64/kernel/early_printk-xen.c +++ b/linux-2.6-xen-sparse/arch/x86_64/kernel/early_printk-xen.c @@ -1,4 +1,3 @@ -#include #include #include #include diff --git a/linux-2.6-xen-sparse/arch/x86_64/kernel/entry-xen.S b/linux-2.6-xen-sparse/arch/x86_64/kernel/entry-xen.S index cfe59a6783..a22433f435 100644 --- a/linux-2.6-xen-sparse/arch/x86_64/kernel/entry-xen.S +++ b/linux-2.6-xen-sparse/arch/x86_64/kernel/entry-xen.S @@ -116,19 +116,21 @@ NMI_MASK = 0x80000000 CFI_ADJUST_CFA_OFFSET -(6*8) .endm - .macro CFI_DEFAULT_STACK start=1 + .macro CFI_DEFAULT_STACK start=1,adj=0 .if \start CFI_STARTPROC simple - CFI_DEF_CFA rsp,SS+8 + CFI_DEF_CFA rsp,SS+8-(\adj*ARGOFFSET) .else - CFI_DEF_CFA_OFFSET SS+8 + CFI_DEF_CFA_OFFSET SS+8-(\adj*ARGOFFSET) .endif + .if \adj == 0 CFI_REL_OFFSET r15,R15 CFI_REL_OFFSET r14,R14 CFI_REL_OFFSET r13,R13 CFI_REL_OFFSET r12,R12 CFI_REL_OFFSET rbp,RBP CFI_REL_OFFSET rbx,RBX + .endif CFI_REL_OFFSET r11,R11 CFI_REL_OFFSET r10,R10 CFI_REL_OFFSET r9,R9 @@ -363,8 +365,8 @@ ENTRY(int_ret_from_sys_call) CFI_REL_OFFSET r9,R9-ARGOFFSET CFI_REL_OFFSET r10,R10-ARGOFFSET CFI_REL_OFFSET r11,R11-ARGOFFSET - TRACE_IRQS_OFF XEN_BLOCK_EVENTS(%rsi) + TRACE_IRQS_OFF testb $3,CS-ARGOFFSET(%rsp) jnz 1f /* Need to set the proper %ss (not NULL) for ring 3 iretq */ @@ -534,7 +536,7 @@ END(stub_rt_sigreturn) */ retint_check: - CFI_DEFAULT_STACK + CFI_DEFAULT_STACK adj=1 movl threadinfo_flags(%rcx),%edx andl %edi,%edx CFI_REMEMBER_STATE @@ -838,6 +840,7 @@ ENTRY(error_entry) CFI_REL_OFFSET r15,R15 #if 0 cmpl $__KERNEL_CS,CS(%rsp) + CFI_REMEMBER_STATE je error_kernelspace #endif error_call_handler: @@ -864,7 +867,7 @@ error_exit: TRACE_IRQS_IRETQ jmp retint_restore_args -error_kernelspace: +#if 0 /* * We need to re-write the logic here because we don't do iretq to * to return to user mode. It's still possible that we get trap/fault @@ -872,7 +875,8 @@ error_kernelspace: * for example). * */ -#if 0 + CFI_RESTORE_STATE +error_kernelspace: incl %ebx /* There are two places in the kernel that can potentially fault with usergs. Handle them here. The exception handlers after @@ -888,11 +892,13 @@ error_kernelspace: cmpq $gs_change,RIP(%rsp) je error_swapgs jmp error_sti -#endif +#endif + CFI_ENDPROC END(error_entry) ENTRY(hypervisor_callback) zeroentry do_hypervisor_callback +END(hypervisor_callback) /* * Copied from arch/xen/i386/kernel/entry.S @@ -909,48 +915,66 @@ ENTRY(hypervisor_callback) # existing activation in its critical region -- if so, we pop the current # activation and restart the handler using the previous one. ENTRY(do_hypervisor_callback) # do_hypervisor_callback(struct *pt_regs) + CFI_STARTPROC # Since we don't modify %rdi, evtchn_do_upall(struct *pt_regs) will # see the correct pointer to the pt_regs movq %rdi, %rsp # we don't return, adjust the stack frame -11: movq %gs:pda_irqstackptr,%rax - incl %gs:pda_irqcount - cmovzq %rax,%rsp - pushq %rdi + CFI_ENDPROC + CFI_DEFAULT_STACK +11: incl %gs:pda_irqcount + movq %rsp,%rbp + CFI_DEF_CFA_REGISTER rbp + cmovzq %gs:pda_irqstackptr,%rsp + pushq %rbp # backlink for old unwinder call evtchn_do_upcall popq %rsp + CFI_DEF_CFA_REGISTER rsp decl %gs:pda_irqcount jmp error_exit + CFI_ENDPROC +END(do_hypervisor_callback) #ifdef CONFIG_X86_LOCAL_APIC KPROBE_ENTRY(nmi) zeroentry do_nmi_callback ENTRY(do_nmi_callback) + CFI_STARTPROC addq $8, %rsp + CFI_ENDPROC + CFI_DEFAULT_STACK call do_nmi orl $NMI_MASK,EFLAGS(%rsp) RESTORE_REST XEN_BLOCK_EVENTS(%rsi) + TRACE_IRQS_OFF GET_THREAD_INFO(%rcx) jmp retint_restore_args + CFI_ENDPROC .previous .text +END(nmi) #endif ALIGN restore_all_enable_events: + CFI_DEFAULT_STACK adj=1 + TRACE_IRQS_ON XEN_UNBLOCK_EVENTS(%rsi) # %rsi is already set up... scrit: /**** START OF CRITICAL REGION ****/ XEN_TEST_PENDING(%rsi) + CFI_REMEMBER_STATE jnz 14f # process more events if necessary... XEN_PUT_VCPU_INFO(%rsi) RESTORE_ARGS 0,8,0 HYPERVISOR_IRET 0 + CFI_RESTORE_STATE 14: XEN_LOCKED_BLOCK_EVENTS(%rsi) XEN_PUT_VCPU_INFO(%rsi) SAVE_REST movq %rsp,%rdi # set the argument again jmp 11b + CFI_ENDPROC ecrit: /**** END OF CRITICAL REGION ****/ # At this point, unlike on x86-32, we don't do the fixup to simplify the # code and the stack frame is more complex on x86-64. @@ -970,8 +994,12 @@ ecrit: /**** END OF CRITICAL REGION ****/ # We distinguish between categories by comparing each saved segment register # with its current contents: any discrepancy means we in category 1. ENTRY(failsafe_callback) + _frame (RIP-0x30) + CFI_REL_OFFSET rcx, 0 + CFI_REL_OFFSET r11, 8 movw %ds,%cx cmpw %cx,0x10(%rsp) + CFI_REMEMBER_STATE jne 1f movw %es,%cx cmpw %cx,0x18(%rsp) @@ -984,17 +1012,26 @@ ENTRY(failsafe_callback) jne 1f /* All segments match their saved values => Category 2 (Bad IRET). */ movq (%rsp),%rcx + CFI_RESTORE rcx movq 8(%rsp),%r11 + CFI_RESTORE r11 addq $0x30,%rsp + CFI_ADJUST_CFA_OFFSET -0x30 movq $11,%rdi /* SIGSEGV */ jmp do_exit + CFI_RESTORE_STATE 1: /* Segment mismatch => Category 1 (Bad segment). Retry the IRET. */ movq (%rsp),%rcx + CFI_RESTORE rcx movq 8(%rsp),%r11 + CFI_RESTORE r11 addq $0x30,%rsp + CFI_ADJUST_CFA_OFFSET -0x30 pushq $0 + CFI_ADJUST_CFA_OFFSET 8 SAVE_ALL jmp error_exit + CFI_ENDPROC #if 0 .section __ex_table,"a" .align 8 @@ -1117,12 +1154,12 @@ END(device_not_available) /* runs on exception stack */ KPROBE_ENTRY(debug) - INTR_FRAME -/* pushq $0 +/* INTR_FRAME + pushq $0 CFI_ADJUST_CFA_OFFSET 8 */ zeroentry do_debug -/* paranoid_exit */ - CFI_ENDPROC +/* paranoidexit + CFI_ENDPROC */ END(debug) .previous .text @@ -1144,12 +1181,12 @@ END(nmi) #endif KPROBE_ENTRY(int3) - INTR_FRAME -/* pushq $0 +/* INTR_FRAME + pushq $0 CFI_ADJUST_CFA_OFFSET 8 */ zeroentry do_int3 -/* jmp paranoid_exit1 */ - CFI_ENDPROC +/* jmp paranoid_exit1 + CFI_ENDPROC */ END(int3) .previous .text @@ -1193,9 +1230,11 @@ END(segment_not_present) /* runs on exception stack */ ENTRY(stack_segment) - XCPT_FRAME +/* XCPT_FRAME + paranoidentry do_stack_segment */ errorentry do_stack_segment - CFI_ENDPROC +/* jmp paranoid_exit1 + CFI_ENDPROC */ END(stack_segment) KPROBE_ENTRY(general_protection) diff --git a/linux-2.6-xen-sparse/arch/x86_64/kernel/genapic_xen.c b/linux-2.6-xen-sparse/arch/x86_64/kernel/genapic_xen.c index 711c8237b8..1171aad778 100644 --- a/linux-2.6-xen-sparse/arch/x86_64/kernel/genapic_xen.c +++ b/linux-2.6-xen-sparse/arch/x86_64/kernel/genapic_xen.c @@ -10,7 +10,6 @@ * * Hacked to pieces for Xen by Chris Wright. */ -#include #include #include #include diff --git a/linux-2.6-xen-sparse/arch/x86_64/kernel/head-xen.S b/linux-2.6-xen-sparse/arch/x86_64/kernel/head-xen.S index b7ef0cbcb0..ca7fbf5a2b 100644 --- a/linux-2.6-xen-sparse/arch/x86_64/kernel/head-xen.S +++ b/linux-2.6-xen-sparse/arch/x86_64/kernel/head-xen.S @@ -22,11 +22,9 @@ #include #include #include - +#include #include -#define _PAGE_PRESENT 0x1 - .section .bootstrap.text, "ax", @progbits .code64 #define VIRT_ENTRY_OFFSET 0x0 @@ -42,6 +40,7 @@ ENTRY(_start) /* rsi is pointer to startup info structure. pass it to C */ movq %rsi,%rdi + pushq $0 # fake return address jmp x86_64_start_kernel ENTRY(stext) @@ -82,7 +81,25 @@ NEXT_PAGE(level2_kernel_pgt) .fill 512,8,0 NEXT_PAGE(hypercall_page) - .fill 512,8,0 + CFI_STARTPROC + .rept 0x1000 / 0x20 + .skip 1 /* push %rcx */ + CFI_ADJUST_CFA_OFFSET 8 + CFI_REL_OFFSET rcx,0 + .skip 2 /* push %r11 */ + CFI_ADJUST_CFA_OFFSET 8 + CFI_REL_OFFSET rcx,0 + .skip 5 /* mov $#,%eax */ + .skip 2 /* syscall */ + .skip 2 /* pop %r11 */ + CFI_ADJUST_CFA_OFFSET -8 + CFI_RESTORE r11 + .skip 1 /* pop %rcx */ + CFI_ADJUST_CFA_OFFSET -8 + CFI_RESTORE rcx + .align 0x20,0 /* ret */ + .endr + CFI_ENDPROC #undef NEXT_PAGE @@ -186,3 +203,4 @@ ENTRY(empty_zero_page) ELFNOTE(Xen, XEN_ELFNOTE_L1_MFN_VALID, .quad, _PAGE_PRESENT,_PAGE_PRESENT) ELFNOTE(Xen, XEN_ELFNOTE_FEATURES, .asciz, "writable_page_tables|writable_descriptor_tables|auto_translated_physmap|pae_pgdir_above_4gb|supervisor_mode_kernel") ELFNOTE(Xen, XEN_ELFNOTE_LOADER, .asciz, "generic") + ELFNOTE(Xen, XEN_ELFNOTE_SUSPEND_CANCEL, .long, 1) diff --git a/linux-2.6-xen-sparse/arch/x86_64/kernel/init_task.c b/linux-2.6-xen-sparse/arch/x86_64/kernel/init_task.c index 86bc43b046..e0bd1e50e7 100644 --- a/linux-2.6-xen-sparse/arch/x86_64/kernel/init_task.c +++ b/linux-2.6-xen-sparse/arch/x86_64/kernel/init_task.c @@ -47,11 +47,11 @@ EXPORT_SYMBOL(init_task); * on exact cacheline boundaries, to eliminate cacheline ping-pong. */ DEFINE_PER_CPU(struct tss_struct, init_tss) ____cacheline_internodealigned_in_smp = INIT_TSS; -#endif /* Copies of the original ist values from the tss are only accessed during * debugging, no special alignment required. */ DEFINE_PER_CPU(struct orig_ist, orig_ist); +#endif #define ALIGN_TO_4K __attribute__((section(".data.init_task"))) diff --git a/linux-2.6-xen-sparse/arch/x86_64/kernel/process-xen.c b/linux-2.6-xen-sparse/arch/x86_64/kernel/process-xen.c index ada9751fb3..6a7bf2ed37 100644 --- a/linux-2.6-xen-sparse/arch/x86_64/kernel/process-xen.c +++ b/linux-2.6-xen-sparse/arch/x86_64/kernel/process-xen.c @@ -117,7 +117,7 @@ void exit_idle(void) * to poll the ->need_resched flag instead of waiting for the * cross-CPU IPI to arrive. Use this option with caution. */ -static void poll_idle(void) +static void poll_idle (void) { local_irq_enable(); @@ -179,9 +179,7 @@ void cpu_idle (void) if (__get_cpu_var(cpu_idle_state)) __get_cpu_var(cpu_idle_state) = 0; rmb(); - idle = pm_idle; - if (!idle) - idle = xen_idle; + idle = xen_idle; /* no alternatives */ if (cpu_is_offline(smp_processor_id())) play_dead(); enter_idle(); diff --git a/linux-2.6-xen-sparse/arch/x86_64/kernel/setup-xen.c b/linux-2.6-xen-sparse/arch/x86_64/kernel/setup-xen.c index 7410cf6574..22164fb524 100644 --- a/linux-2.6-xen-sparse/arch/x86_64/kernel/setup-xen.c +++ b/linux-2.6-xen-sparse/arch/x86_64/kernel/setup-xen.c @@ -676,7 +676,8 @@ void __init setup_arch(char **cmdline_p) init_memory_mapping(0, (end_pfn_map << PAGE_SHIFT)); - /* dmi_scan_machine(); */ + if (is_initial_xendomain()) + dmi_scan_machine(); #ifdef CONFIG_ACPI_NUMA /* @@ -691,6 +692,14 @@ void __init setup_arch(char **cmdline_p) contig_initmem_init(0, end_pfn); #endif +#ifdef CONFIG_XEN + /* + * Reserve kernel, physmap, start info, initial page tables, and + * direct mapping. + */ + reserve_bootmem_generic(__pa_symbol(&_text), + (table_end << PAGE_SHIFT) - __pa_symbol(&_text)); +#else /* Reserve direct mapping */ reserve_bootmem_generic(table_start << PAGE_SHIFT, (table_end - table_start) << PAGE_SHIFT); @@ -699,12 +708,6 @@ void __init setup_arch(char **cmdline_p) reserve_bootmem_generic(__pa_symbol(&_text), __pa_symbol(&_end) - __pa_symbol(&_text)); -#ifdef CONFIG_XEN - /* reserve physmap, start info and initial page tables */ - reserve_bootmem_generic(__pa_symbol(&_end), - (table_start << PAGE_SHIFT) - - __pa_symbol(&_end)); -#else /* * reserve physical page 0 - it's a special BIOS page on many boxes, * enabling clean reboots, SMP operation, laptop functions. @@ -1625,13 +1628,6 @@ struct seq_operations cpuinfo_op = { .show = show_cpuinfo, }; -static int __init run_dmi_scan(void) -{ - dmi_scan_machine(); - return 0; -} -core_initcall(run_dmi_scan); - #if defined(CONFIG_INPUT_PCSPKR) || defined(CONFIG_INPUT_PCSPKR_MODULE) #include static __init int add_pcspkr(void) @@ -1639,6 +1635,9 @@ static __init int add_pcspkr(void) struct platform_device *pd; int ret; + if (!is_initial_xendomain()) + return 0; + pd = platform_device_alloc("pcspkr", -1); if (!pd) return -ENOMEM; diff --git a/linux-2.6-xen-sparse/arch/x86_64/kernel/x8664_ksyms-xen.c b/linux-2.6-xen-sparse/arch/x86_64/kernel/x8664_ksyms-xen.c deleted file mode 100644 index 8ace4cb71a..0000000000 --- a/linux-2.6-xen-sparse/arch/x86_64/kernel/x8664_ksyms-xen.c +++ /dev/null @@ -1,60 +0,0 @@ -/* Exports for assembly files. - All C exports should go in the respective C files. */ - -#include -#include -#include - -#include -#include -#include -#include - -EXPORT_SYMBOL(kernel_thread); - -EXPORT_SYMBOL(__down_failed); -EXPORT_SYMBOL(__down_failed_interruptible); -EXPORT_SYMBOL(__down_failed_trylock); -EXPORT_SYMBOL(__up_wakeup); - -EXPORT_SYMBOL(__get_user_1); -EXPORT_SYMBOL(__get_user_2); -EXPORT_SYMBOL(__get_user_4); -EXPORT_SYMBOL(__get_user_8); -EXPORT_SYMBOL(__put_user_1); -EXPORT_SYMBOL(__put_user_2); -EXPORT_SYMBOL(__put_user_4); -EXPORT_SYMBOL(__put_user_8); - -EXPORT_SYMBOL(copy_user_generic); -EXPORT_SYMBOL(copy_from_user); -EXPORT_SYMBOL(copy_to_user); - -EXPORT_SYMBOL(copy_page); -EXPORT_SYMBOL(clear_page); - -#ifdef CONFIG_SMP -extern void FASTCALL( __write_lock_failed(rwlock_t *rw)); -extern void FASTCALL( __read_lock_failed(rwlock_t *rw)); -EXPORT_SYMBOL(__write_lock_failed); -EXPORT_SYMBOL(__read_lock_failed); -#endif - -/* Export string functions. We normally rely on gcc builtin for most of these, - but gcc sometimes decides not to inline them. */ -#undef memcpy -#undef memset -#undef memmove - -extern void * memset(void *,int,__kernel_size_t); -extern void * memcpy(void *,const void *,__kernel_size_t); -extern void * __memcpy(void *,const void *,__kernel_size_t); - -EXPORT_SYMBOL(memset); -EXPORT_SYMBOL(memcpy); -EXPORT_SYMBOL(__memcpy); - -EXPORT_SYMBOL(empty_zero_page); - -EXPORT_SYMBOL(load_gs_index); - diff --git a/linux-2.6-xen-sparse/arch/x86_64/mm/init-xen.c b/linux-2.6-xen-sparse/arch/x86_64/mm/init-xen.c index 83898daeaa..de7c80dfb8 100644 --- a/linux-2.6-xen-sparse/arch/x86_64/mm/init-xen.c +++ b/linux-2.6-xen-sparse/arch/x86_64/mm/init-xen.c @@ -102,14 +102,11 @@ static void __meminit early_make_page_readonly(void *va, unsigned int feature) BUG(); } -void make_page_readonly(void *va, unsigned int feature) +static void __make_page_readonly(void *va) { pgd_t *pgd; pud_t *pud; pmd_t *pmd; pte_t pte, *ptep; unsigned long addr = (unsigned long) va; - if (xen_feature(feature)) - return; - pgd = pgd_offset_k(addr); pud = pud_offset(pgd, addr); pmd = pmd_offset(pud, addr); @@ -120,17 +117,14 @@ void make_page_readonly(void *va, unsigned int feature) xen_l1_entry_update(ptep, pte); /* fallback */ if ((addr >= VMALLOC_START) && (addr < VMALLOC_END)) - make_page_readonly(__va(pte_pfn(pte) << PAGE_SHIFT), feature); + __make_page_readonly(__va(pte_pfn(pte) << PAGE_SHIFT)); } -void make_page_writable(void *va, unsigned int feature) +static void __make_page_writable(void *va) { pgd_t *pgd; pud_t *pud; pmd_t *pmd; pte_t pte, *ptep; unsigned long addr = (unsigned long) va; - if (xen_feature(feature)) - return; - pgd = pgd_offset_k(addr); pud = pud_offset(pgd, addr); pmd = pmd_offset(pud, addr); @@ -141,7 +135,19 @@ void make_page_writable(void *va, unsigned int feature) xen_l1_entry_update(ptep, pte); /* fallback */ if ((addr >= VMALLOC_START) && (addr < VMALLOC_END)) - make_page_writable(__va(pte_pfn(pte) << PAGE_SHIFT), feature); + __make_page_writable(__va(pte_pfn(pte) << PAGE_SHIFT)); +} + +void make_page_readonly(void *va, unsigned int feature) +{ + if (!xen_feature(feature)) + __make_page_readonly(va); +} + +void make_page_writable(void *va, unsigned int feature) +{ + if (!xen_feature(feature)) + __make_page_writable(va); } void make_pages_readonly(void *va, unsigned nr, unsigned int feature) @@ -150,7 +156,7 @@ void make_pages_readonly(void *va, unsigned nr, unsigned int feature) return; while (nr-- != 0) { - make_page_readonly(va, feature); + __make_page_readonly(va); va = (void*)((unsigned long)va + PAGE_SIZE); } } @@ -161,7 +167,7 @@ void make_pages_writable(void *va, unsigned nr, unsigned int feature) return; while (nr-- != 0) { - make_page_writable(va, feature); + __make_page_writable(va); va = (void*)((unsigned long)va + PAGE_SIZE); } } @@ -208,7 +214,11 @@ static __init void *spp_getpage(void) void *ptr; if (after_bootmem) ptr = (void *) get_zeroed_page(GFP_ATOMIC); - else + else if (start_pfn < table_end) { + ptr = __va(start_pfn << PAGE_SHIFT); + start_pfn++; + memset(ptr, 0, PAGE_SIZE); + } else ptr = alloc_bootmem_pages(PAGE_SIZE); if (!ptr || ((unsigned long)ptr & ~PAGE_MASK)) panic("set_pte_phys: cannot allocate page data %s\n", after_bootmem?"after bootmem":""); @@ -299,36 +309,26 @@ static __init void set_pte_phys_ma(unsigned long vaddr, pmd = (pmd_t *) spp_getpage(); make_page_readonly(pmd, XENFEAT_writable_page_tables); - set_pud(pud, __pud(__pa(pmd) | _KERNPG_TABLE | _PAGE_USER)); - if (pmd != pmd_offset(pud, 0)) { printk("PAGETABLE BUG #01! %p <-> %p\n", pmd, pmd_offset(pud,0)); return; } } pmd = pmd_offset(pud, vaddr); - if (pmd_none(*pmd)) { pte = (pte_t *) spp_getpage(); make_page_readonly(pte, XENFEAT_writable_page_tables); - set_pmd(pmd, __pmd(__pa(pte) | _KERNPG_TABLE | _PAGE_USER)); if (pte != pte_offset_kernel(pmd, 0)) { printk("PAGETABLE BUG #02!\n"); return; } } - new_pte = pfn_pte_ma(phys >> PAGE_SHIFT, prot); - pte = pte_offset_kernel(pmd, vaddr); - /* - * Note that the pte page is already RO, thus we want to use - * xen_l1_entry_update(), not set_pte(). - */ - xen_l1_entry_update(pte, - pfn_pte_ma(phys >> PAGE_SHIFT, prot)); + pte = pte_offset_kernel(pmd, vaddr); + set_pte(pte, new_pte); /* * It's enough to flush this one mapping. @@ -404,6 +404,7 @@ static inline void __set_pte(pte_t *dst, pte_t val) static inline int make_readonly(unsigned long paddr) { + extern char __vsyscall_0; int readonly = 0; /* Make new page tables read-only. */ @@ -420,25 +421,45 @@ static inline int make_readonly(unsigned long paddr) /* * No need for writable mapping of kernel image. This also ensures that * page and descriptor tables embedded inside don't have writable - * mappings. + * mappings. Exclude the vsyscall area here, allowing alternative + * instruction patching to work. */ - if ((paddr >= __pa_symbol(&_text)) && (paddr < __pa_symbol(&_end))) + if ((paddr >= __pa_symbol(&_text)) && (paddr < __pa_symbol(&_end)) + && !(paddr >= __pa_symbol(&__vsyscall_0) + && paddr < __pa_symbol(&__vsyscall_0) + PAGE_SIZE)) readonly = 1; return readonly; } +#ifndef CONFIG_XEN /* Must run before zap_low_mappings */ __init void *early_ioremap(unsigned long addr, unsigned long size) { - return ioremap(addr, size); + unsigned long map = round_down(addr, LARGE_PAGE_SIZE); + + /* actually usually some more */ + if (size >= LARGE_PAGE_SIZE) { + printk("SMBIOS area too long %lu\n", size); + return NULL; + } + set_pmd(temp_mappings[0].pmd, __pmd(map | _KERNPG_TABLE | _PAGE_PSE)); + map += LARGE_PAGE_SIZE; + set_pmd(temp_mappings[1].pmd, __pmd(map | _KERNPG_TABLE | _PAGE_PSE)); + __flush_tlb(); + return temp_mappings[0].address + (addr & (LARGE_PAGE_SIZE-1)); } /* To avoid virtual aliases later */ __init void early_iounmap(void *addr, unsigned long size) { - iounmap(addr); + if ((void *)round_down((unsigned long)addr, LARGE_PAGE_SIZE) != temp_mappings[0].address) + printk("early_iounmap: bad address %p\n", addr); + set_pmd(temp_mappings[0].pmd, __pmd(0)); + set_pmd(temp_mappings[1].pmd, __pmd(0)); + __flush_tlb(); } +#endif static void __meminit phys_pmd_init(pmd_t *pmd, unsigned long address, unsigned long end) @@ -638,7 +659,7 @@ static void __init extend_init_mapping(unsigned long tables_space) static void __init find_early_table_space(unsigned long end) { - unsigned long puds, pmds, ptes, tables; + unsigned long puds, pmds, ptes, tables; puds = (end + PUD_SIZE - 1) >> PUD_SHIFT; pmds = (end + PMD_SIZE - 1) >> PMD_SHIFT; @@ -658,12 +679,70 @@ static void __init find_early_table_space(unsigned long end) (table_start << PAGE_SHIFT) + tables); } +static void xen_finish_init_mapping(void) +{ + unsigned long i, start, end; + + /* Re-vector virtual addresses pointing into the initial + mapping to the just-established permanent ones. */ + xen_start_info = __va(__pa(xen_start_info)); + xen_start_info->pt_base = (unsigned long) + __va(__pa(xen_start_info->pt_base)); + if (!xen_feature(XENFEAT_auto_translated_physmap)) { + phys_to_machine_mapping = + __va(__pa(xen_start_info->mfn_list)); + xen_start_info->mfn_list = (unsigned long) + phys_to_machine_mapping; + } + if (xen_start_info->mod_start) + xen_start_info->mod_start = (unsigned long) + __va(__pa(xen_start_info->mod_start)); + + /* Destroy the Xen-created mappings beyond the kernel image as + * well as the temporary mappings created above. Prevents + * overlap with modules area (if init mapping is very big). + */ + start = PAGE_ALIGN((unsigned long)_end); + end = __START_KERNEL_map + (table_end << PAGE_SHIFT); + for (; start < end; start += PAGE_SIZE) + WARN_ON(HYPERVISOR_update_va_mapping( + start, __pte_ma(0), 0)); + + /* Allocate pte's for initial fixmaps from 'start_pfn' allocator. */ + table_end = ~0UL; + + /* + * Prefetch pte's for the bt_ioremap() area. It gets used before the + * boot-time allocator is online, so allocate-on-demand would fail. + */ + for (i = FIX_BTMAP_END; i <= FIX_BTMAP_BEGIN; i++) + __set_fixmap(i, 0, __pgprot(0)); + + /* Switch to the real shared_info page, and clear the dummy page. */ + set_fixmap(FIX_SHARED_INFO, xen_start_info->shared_info); + HYPERVISOR_shared_info = (shared_info_t *)fix_to_virt(FIX_SHARED_INFO); + memset(empty_zero_page, 0, sizeof(empty_zero_page)); + + /* Set up mapping of lowest 1MB of physical memory. */ + for (i = 0; i < NR_FIX_ISAMAPS; i++) + if (is_initial_xendomain()) + set_fixmap(FIX_ISAMAP_BEGIN - i, i * PAGE_SIZE); + else + __set_fixmap(FIX_ISAMAP_BEGIN - i, + virt_to_mfn(empty_zero_page) + << PAGE_SHIFT, + PAGE_KERNEL_RO); + + /* Disable the 'start_pfn' allocator. */ + table_end = start_pfn; +} + /* Setup the direct mapping of the physical memory at PAGE_OFFSET. This runs before bootmem is initialized and gets pages directly from the physical memory. To access them they are temporarily mapped. */ void __meminit init_memory_mapping(unsigned long start, unsigned long end) { - unsigned long next; + unsigned long next; Dprintk("init_memory_mapping\n"); @@ -702,31 +781,7 @@ void __meminit init_memory_mapping(unsigned long start, unsigned long end) if (!after_bootmem) { BUG_ON(start_pfn != table_end); - - /* Re-vector virtual addresses pointing into the initial - mapping to the just-established permanent ones. */ - xen_start_info = __va(__pa(xen_start_info)); - xen_start_info->pt_base = (unsigned long) - __va(__pa(xen_start_info->pt_base)); - if (!xen_feature(XENFEAT_auto_translated_physmap)) { - phys_to_machine_mapping = - __va(__pa(xen_start_info->mfn_list)); - xen_start_info->mfn_list = (unsigned long) - phys_to_machine_mapping; - } - if (xen_start_info->mod_start) - xen_start_info->mod_start = (unsigned long) - __va(__pa(xen_start_info->mod_start)); - - /* Destroy the Xen-created mappings beyond the kernel image as - * well as the temporary mappings created above. Prevents - * overlap with modules area (if init mapping is very big). - */ - start = PAGE_ALIGN((unsigned long)_end); - end = __START_KERNEL_map + (table_end << PAGE_SHIFT); - for (; start < end; start += PAGE_SIZE) - WARN_ON(HYPERVISOR_update_va_mapping( - start, __pte_ma(0), 0)); + xen_finish_init_mapping(); } __flush_tlb_all(); @@ -805,7 +860,6 @@ size_zones(unsigned long *z, unsigned long *h, void __init paging_init(void) { unsigned long zones[MAX_NR_ZONES], holes[MAX_NR_ZONES]; - int i; memory_present(0, 0, end_pfn); sparse_init(); @@ -813,22 +867,7 @@ void __init paging_init(void) free_area_init_node(0, NODE_DATA(0), zones, __pa(PAGE_OFFSET) >> PAGE_SHIFT, holes); - /* Switch to the real shared_info page, and clear the - * dummy page. */ - set_fixmap(FIX_SHARED_INFO, xen_start_info->shared_info); - HYPERVISOR_shared_info = (shared_info_t *)fix_to_virt(FIX_SHARED_INFO); - memset(empty_zero_page, 0, sizeof(empty_zero_page)); - init_mm.context.pinned = 1; - - /* Setup mapping of lower 1st MB */ - for (i = 0; i < NR_FIX_ISAMAPS; i++) - if (is_initial_xendomain()) - set_fixmap(FIX_ISAMAP_BEGIN - i, i * PAGE_SIZE); - else - __set_fixmap(FIX_ISAMAP_BEGIN - i, - virt_to_mfn(empty_zero_page) << PAGE_SHIFT, - PAGE_KERNEL_RO); } #endif @@ -1028,11 +1067,6 @@ void __init mem_init(void) void free_init_pages(char *what, unsigned long begin, unsigned long end) { -#ifdef __DO_LATER__ - /* - * Some pages can be pinned, but some are not. Unpinning such pages - * triggers BUG(). - */ unsigned long addr; if (begin >= end) @@ -1044,25 +1078,27 @@ void free_init_pages(char *what, unsigned long begin, unsigned long end) init_page_count(virt_to_page(addr)); memset((void *)(addr & ~(PAGE_SIZE-1)), POISON_FREE_INITMEM, PAGE_SIZE); - make_page_writable( - __va(__pa(addr)), XENFEAT_writable_page_tables); - /* - * Make pages from __PAGE_OFFSET address as well - */ - make_page_writable( - (void *)addr, XENFEAT_writable_page_tables); + if (addr >= __START_KERNEL_map) { + /* make_readonly() reports all kernel addresses. */ + __make_page_writable(__va(__pa(addr))); + if (HYPERVISOR_update_va_mapping(addr, __pte(0), 0)) { + pgd_t *pgd = pgd_offset_k(addr); + pud_t *pud = pud_offset(pgd, addr); + pmd_t *pmd = pmd_offset(pud, addr); + pte_t *pte = pte_offset_kernel(pmd, addr); + + xen_l1_entry_update(pte, __pte(0)); /* fallback */ + } + } free_page(addr); totalram_pages++; } -#endif } void free_initmem(void) { -#ifdef __DO_LATER__ memset(__initdata_begin, POISON_FREE_INITDATA, __initdata_end - __initdata_begin); -#endif free_init_pages("unused kernel memory", (unsigned long)(&__init_begin), (unsigned long)(&__init_end)); @@ -1125,7 +1161,7 @@ int kern_addr_valid(unsigned long addr) if (pgd_none(*pgd)) return 0; - pud = pud_offset_k(pgd, addr); + pud = pud_offset(pgd, addr); if (pud_none(*pud)) return 0; diff --git a/linux-2.6-xen-sparse/arch/x86_64/mm/pageattr-xen.c b/linux-2.6-xen-sparse/arch/x86_64/mm/pageattr-xen.c index a0f1d0535d..ae434e6be4 100644 --- a/linux-2.6-xen-sparse/arch/x86_64/mm/pageattr-xen.c +++ b/linux-2.6-xen-sparse/arch/x86_64/mm/pageattr-xen.c @@ -24,10 +24,13 @@ static inline void mm_walk_set_prot(void *pt, pgprot_t flags) { struct page *page = virt_to_page(pt); unsigned long pfn = page_to_pfn(page); + int rc; - BUG_ON(HYPERVISOR_update_va_mapping( - (unsigned long)__va(pfn << PAGE_SHIFT), - pfn_pte(pfn, flags), 0)); + rc = HYPERVISOR_update_va_mapping( + (unsigned long)__va(pfn << PAGE_SHIFT), + pfn_pte(pfn, flags), 0); + if (rc) + BUG(); } static void mm_walk(struct mm_struct *mm, pgprot_t flags) diff --git a/linux-2.6-xen-sparse/drivers/char/mem.c b/linux-2.6-xen-sparse/drivers/char/mem.c index 9b7c774ff0..4bfcfb84ac 100644 --- a/linux-2.6-xen-sparse/drivers/char/mem.c +++ b/linux-2.6-xen-sparse/drivers/char/mem.c @@ -787,7 +787,7 @@ static const struct file_operations mem_fops = { .open = open_mem, }; #else -extern struct file_operations mem_fops; +extern const struct file_operations mem_fops; #endif static const struct file_operations kmem_fops = { diff --git a/linux-2.6-xen-sparse/drivers/char/tpm/tpm_xen.c b/linux-2.6-xen-sparse/drivers/char/tpm/tpm_xen.c index cdbc7decd7..8b62b07724 100644 --- a/linux-2.6-xen-sparse/drivers/char/tpm/tpm_xen.c +++ b/linux-2.6-xen-sparse/drivers/char/tpm/tpm_xen.c @@ -113,14 +113,13 @@ void __exit tpmif_exit(void); static inline int -tx_buffer_copy(struct tx_buffer *txb, const u8 * src, int len, +tx_buffer_copy(struct tx_buffer *txb, const u8 *src, int len, int isuserbuffer) { int copied = len; - if (len > txb->size) { + if (len > txb->size) copied = txb->size; - } if (isuserbuffer) { if (copy_from_user(txb->data, src, copied)) return -EFAULT; @@ -133,18 +132,20 @@ tx_buffer_copy(struct tx_buffer *txb, const u8 * src, int len, static inline struct tx_buffer *tx_buffer_alloc(void) { - struct tx_buffer *txb = kzalloc(sizeof (struct tx_buffer), - GFP_KERNEL); + struct tx_buffer *txb; - if (txb) { - txb->len = 0; - txb->size = PAGE_SIZE; - txb->data = (unsigned char *)__get_free_page(GFP_KERNEL); - if (txb->data == NULL) { - kfree(txb); - txb = NULL; - } + txb = kzalloc(sizeof(struct tx_buffer), GFP_KERNEL); + if (!txb) + return NULL; + + txb->len = 0; + txb->size = PAGE_SIZE; + txb->data = (unsigned char *)__get_free_page(GFP_KERNEL); + if (txb->data == NULL) { + kfree(txb); + txb = NULL; } + return txb; } @@ -160,37 +161,41 @@ static inline void tx_buffer_free(struct tx_buffer *txb) /************************************************************** Utility function for the tpm_private structure **************************************************************/ -static inline void tpm_private_init(struct tpm_private *tp) +static void tpm_private_init(struct tpm_private *tp) { spin_lock_init(&tp->tx_lock); init_waitqueue_head(&tp->wait_q); atomic_set(&tp->refcnt, 1); } -static inline void tpm_private_put(void) +static void tpm_private_put(void) { - if ( atomic_dec_and_test(&my_priv->refcnt)) { - tpmif_free_tx_buffers(my_priv); - kfree(my_priv); - my_priv = NULL; - } + if (!atomic_dec_and_test(&my_priv->refcnt)) + return; + + tpmif_free_tx_buffers(my_priv); + kfree(my_priv); + my_priv = NULL; } static struct tpm_private *tpm_private_get(void) { int err; - if (!my_priv) { - my_priv = kzalloc(sizeof(struct tpm_private), GFP_KERNEL); - if (my_priv) { - tpm_private_init(my_priv); - err = tpmif_allocate_tx_buffers(my_priv); - if (err < 0) { - tpm_private_put(); - } - } - } else { + + if (my_priv) { atomic_inc(&my_priv->refcnt); + return my_priv; } + + my_priv = kzalloc(sizeof(struct tpm_private), GFP_KERNEL); + if (!my_priv) + return NULL; + + tpm_private_init(my_priv); + err = tpmif_allocate_tx_buffers(my_priv); + if (err < 0) + tpm_private_put(); + return my_priv; } @@ -379,10 +384,8 @@ static int tpmfront_probe(struct xenbus_device *dev, return -ENOMEM; tp->chip = init_vtpm(&dev->dev, &tvd, tp); - - if (IS_ERR(tp->chip)) { + if (IS_ERR(tp->chip)) return PTR_ERR(tp->chip); - } err = xenbus_scanf(XBT_NIL, dev->nodename, "handle", "%i", &handle); @@ -401,6 +404,7 @@ static int tpmfront_probe(struct xenbus_device *dev, tpm_private_put(); return err; } + return 0; } @@ -417,32 +421,36 @@ static int tpmfront_suspend(struct xenbus_device *dev) { struct tpm_private *tp = tpm_private_from_dev(&dev->dev); u32 ctr; - /* lock, so no app can send */ + + /* Take the lock, preventing any application from sending. */ mutex_lock(&suspend_lock); tp->is_suspended = 1; - for (ctr = 0; atomic_read(&tp->tx_busy) && ctr <= 300; ctr++) { + for (ctr = 0; atomic_read(&tp->tx_busy); ctr++) { if ((ctr % 10) == 0) printk("TPM-FE [INFO]: Waiting for outstanding " "request.\n"); - /* - * Wait for a request to be responded to. - */ + /* Wait for a request to be responded to. */ interruptible_sleep_on_timeout(&tp->wait_q, 100); } - xenbus_switch_state(dev, XenbusStateClosing); - - if (atomic_read(&tp->tx_busy)) { - /* - * A temporary work-around. - */ - printk("TPM-FE [WARNING]: Resetting busy flag."); - atomic_set(&tp->tx_busy, 0); - } return 0; } +static int tpmfront_suspend_finish(struct tpm_private *tp) +{ + tp->is_suspended = 0; + /* Allow applications to send again. */ + mutex_unlock(&suspend_lock); + return 0; +} + +static int tpmfront_suspend_cancel(struct xenbus_device *dev) +{ + struct tpm_private *tp = tpm_private_from_dev(&dev->dev); + return tpmfront_suspend_finish(tp); +} + static int tpmfront_resume(struct xenbus_device *dev) { struct tpm_private *tp = tpm_private_from_dev(&dev->dev); @@ -484,6 +492,7 @@ static struct xenbus_driver tpmfront = { .resume = tpmfront_resume, .otherend_changed = backend_changed, .suspend = tpmfront_suspend, + .suspend_cancel = tpmfront_suspend_cancel, }; static void __init init_tpm_xenbus(void) @@ -514,9 +523,8 @@ static void tpmif_free_tx_buffers(struct tpm_private *tp) { unsigned int i; - for (i = 0; i < TPMIF_TX_RING_SIZE; i++) { + for (i = 0; i < TPMIF_TX_RING_SIZE; i++) tx_buffer_free(tp->tx_buffers[i]); - } } static void tpmif_rx_action(unsigned long priv) @@ -536,9 +544,8 @@ static void tpmif_rx_action(unsigned long priv) received = tx->size; buffer = kmalloc(received, GFP_ATOMIC); - if (NULL == buffer) { + if (!buffer) goto exit; - } for (i = 0; i < TPMIF_TX_RING_SIZE && offset < received; i++) { struct tx_buffer *txb = tp->tx_buffers[i]; @@ -547,9 +554,8 @@ static void tpmif_rx_action(unsigned long priv) tx = &tp->tx->ring[i].req; tocopy = tx->size; - if (tocopy > PAGE_SIZE) { + if (tocopy > PAGE_SIZE) tocopy = PAGE_SIZE; - } memcpy(&buffer[offset], txb->data, tocopy); @@ -607,12 +613,13 @@ static int tpm_xmit(struct tpm_private *tp, struct tx_buffer *txb = tp->tx_buffers[i]; int copied; - if (NULL == txb) { + if (!txb) { DPRINTK("txb (i=%d) is NULL. buffers initilized?\n" "Not transmitting anything!\n", i); spin_unlock_irq(&tp->tx_lock); return -EFAULT; } + copied = tx_buffer_copy(txb, &buf[offset], count, isuserbuffer); if (copied < 0) { @@ -624,25 +631,26 @@ static int tpm_xmit(struct tpm_private *tp, offset += copied; tx = &tp->tx->ring[i].req; - tx->addr = virt_to_machine(txb->data); tx->size = txb->len; - DPRINTK("First 4 characters sent by TPM-FE are 0x%02x 0x%02x 0x%02x 0x%02x\n", + DPRINTK("First 4 characters sent by TPM-FE are " + "0x%02x 0x%02x 0x%02x 0x%02x\n", txb->data[0],txb->data[1],txb->data[2],txb->data[3]); - /* get the granttable reference for this page */ + /* Get the granttable reference for this page. */ tx->ref = gnttab_claim_grant_reference(&gref_head); - - if (-ENOSPC == tx->ref) { + if (tx->ref == -ENOSPC) { spin_unlock_irq(&tp->tx_lock); - DPRINTK(" Grant table claim reference failed in func:%s line:%d file:%s\n", __FUNCTION__, __LINE__, __FILE__); + DPRINTK("Grant table claim reference failed in " + "func:%s line:%d file:%s\n", + __FUNCTION__, __LINE__, __FILE__); return -ENOSPC; } - gnttab_grant_foreign_access_ref( tx->ref, - tp->backend_id, - (tx->addr >> PAGE_SHIFT), - 0 /*RW*/); + gnttab_grant_foreign_access_ref(tx->ref, + tp->backend_id, + virt_to_mfn(txb->data), + 0 /*RW*/); wmb(); } @@ -660,15 +668,10 @@ static int tpm_xmit(struct tpm_private *tp, static void tpmif_notify_upperlayer(struct tpm_private *tp) { - /* - * Notify upper layer about the state of the connection - * to the BE. - */ - if (tp->is_connected) { - vtpm_vd_status(tp->chip, TPM_VD_STATUS_CONNECTED); - } else { - vtpm_vd_status(tp->chip, TPM_VD_STATUS_DISCONNECTED); - } + /* Notify upper layer about the state of the connection to the BE. */ + vtpm_vd_status(tp->chip, (tp->is_connected + ? TPM_VD_STATUS_CONNECTED + : TPM_VD_STATUS_DISCONNECTED)); } @@ -679,20 +682,16 @@ static void tpmif_set_connected_state(struct tpm_private *tp, u8 is_connected) * should disconnect - assumption is that we will resume * The mutex keeps apps from sending. */ - if (is_connected == 0 && tp->is_suspended == 1) { + if (is_connected == 0 && tp->is_suspended == 1) return; - } /* * Unlock the mutex if we are connected again * after being suspended - now resuming. * This also removes the suspend state. */ - if (is_connected == 1 && tp->is_suspended == 1) { - tp->is_suspended = 0; - /* unlock, so apps can resume sending */ - mutex_unlock(&suspend_lock); - } + if (is_connected == 1 && tp->is_suspended == 1) + tpmfront_suspend_finish(tp); if (is_connected != tp->is_connected) { tp->is_connected = is_connected; @@ -710,33 +709,24 @@ static void tpmif_set_connected_state(struct tpm_private *tp, u8 is_connected) static int __init tpmif_init(void) { - long rc = 0; struct tpm_private *tp; if (is_initial_xendomain()) return -EPERM; tp = tpm_private_get(); - if (!tp) { - rc = -ENOMEM; - goto failexit; - } + if (!tp) + return -ENOMEM; IPRINTK("Initialising the vTPM driver.\n"); - if ( gnttab_alloc_grant_references ( TPMIF_TX_RING_SIZE, - &gref_head ) < 0) { - rc = -EFAULT; - goto gnttab_alloc_failed; + if (gnttab_alloc_grant_references(TPMIF_TX_RING_SIZE, + &gref_head) < 0) { + tpm_private_put(); + return -EFAULT; } init_tpm_xenbus(); return 0; - -gnttab_alloc_failed: - tpm_private_put(); -failexit: - - return (int)rc; } diff --git a/linux-2.6-xen-sparse/drivers/xen/balloon/balloon.c b/linux-2.6-xen-sparse/drivers/xen/balloon/balloon.c index 91b2ee8d35..22dd026fee 100644 --- a/linux-2.6-xen-sparse/drivers/xen/balloon/balloon.c +++ b/linux-2.6-xen-sparse/drivers/xen/balloon/balloon.c @@ -32,7 +32,6 @@ * IN THE SOFTWARE. */ -#include #include #include #include diff --git a/linux-2.6-xen-sparse/drivers/xen/balloon/sysfs.c b/linux-2.6-xen-sparse/drivers/xen/balloon/sysfs.c index a4ed8a6f1e..68bf60ddd8 100644 --- a/linux-2.6-xen-sparse/drivers/xen/balloon/sysfs.c +++ b/linux-2.6-xen-sparse/drivers/xen/balloon/sysfs.c @@ -28,7 +28,6 @@ * IN THE SOFTWARE. */ -#include #include #include #include diff --git a/linux-2.6-xen-sparse/drivers/xen/blkback/common.h b/linux-2.6-xen-sparse/drivers/xen/blkback/common.h index 9341f6ea36..948edf39b9 100644 --- a/linux-2.6-xen-sparse/drivers/xen/blkback/common.h +++ b/linux-2.6-xen-sparse/drivers/xen/blkback/common.h @@ -27,7 +27,6 @@ #ifndef __BLKIF__BACKEND__COMMON_H__ #define __BLKIF__BACKEND__COMMON_H__ -#include #include #include #include diff --git a/linux-2.6-xen-sparse/drivers/xen/blkfront/block.h b/linux-2.6-xen-sparse/drivers/xen/blkfront/block.h index b8422bb8ff..6c5bd8ed90 100644 --- a/linux-2.6-xen-sparse/drivers/xen/blkfront/block.h +++ b/linux-2.6-xen-sparse/drivers/xen/blkfront/block.h @@ -35,7 +35,6 @@ #ifndef __XEN_DRIVERS_BLOCK_H__ #define __XEN_DRIVERS_BLOCK_H__ -#include #include #include #include diff --git a/linux-2.6-xen-sparse/drivers/xen/blktap/blktap.c b/linux-2.6-xen-sparse/drivers/xen/blktap/blktap.c index 20b533a3ac..586de79f77 100644 --- a/linux-2.6-xen-sparse/drivers/xen/blktap/blktap.c +++ b/linux-2.6-xen-sparse/drivers/xen/blktap/blktap.c @@ -335,7 +335,7 @@ static int blktap_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); static unsigned int blktap_poll(struct file *file, poll_table *wait); -static struct file_operations blktap_fops = { +static const struct file_operations blktap_fops = { .owner = THIS_MODULE, .poll = blktap_poll, .ioctl = blktap_ioctl, diff --git a/linux-2.6-xen-sparse/drivers/xen/blktap/common.h b/linux-2.6-xen-sparse/drivers/xen/blktap/common.h index de551f136d..792d128054 100644 --- a/linux-2.6-xen-sparse/drivers/xen/blktap/common.h +++ b/linux-2.6-xen-sparse/drivers/xen/blktap/common.h @@ -27,7 +27,6 @@ #ifndef __BLKIF__BACKEND__COMMON_H__ #define __BLKIF__BACKEND__COMMON_H__ -#include #include #include #include diff --git a/linux-2.6-xen-sparse/drivers/xen/char/mem.c b/linux-2.6-xen-sparse/drivers/xen/char/mem.c index 81852f0055..4fba735afa 100644 --- a/linux-2.6-xen-sparse/drivers/xen/char/mem.c +++ b/linux-2.6-xen-sparse/drivers/xen/char/mem.c @@ -8,7 +8,6 @@ * Shared /dev/zero mmaping support, Feb 2000, Kanoj Sarcar */ -#include #include #include #include @@ -195,7 +194,7 @@ static int open_mem(struct inode * inode, struct file * filp) return capable(CAP_SYS_RAWIO) ? 0 : -EPERM; } -struct file_operations mem_fops = { +const struct file_operations mem_fops = { .llseek = memory_lseek, .read = read_mem, .write = write_mem, diff --git a/linux-2.6-xen-sparse/drivers/xen/console/console.c b/linux-2.6-xen-sparse/drivers/xen/console/console.c index 32c7f9c1ca..78fbc79940 100644 --- a/linux-2.6-xen-sparse/drivers/xen/console/console.c +++ b/linux-2.6-xen-sparse/drivers/xen/console/console.c @@ -30,7 +30,6 @@ * IN THE SOFTWARE. */ -#include #include #include #include diff --git a/linux-2.6-xen-sparse/drivers/xen/core/cpu_hotplug.c b/linux-2.6-xen-sparse/drivers/xen/core/cpu_hotplug.c index 490d86bc2a..5602088e3e 100644 --- a/linux-2.6-xen-sparse/drivers/xen/core/cpu_hotplug.c +++ b/linux-2.6-xen-sparse/drivers/xen/core/cpu_hotplug.c @@ -1,4 +1,3 @@ -#include #include #include #include @@ -122,29 +121,19 @@ arch_initcall(setup_vcpu_hotplug_event); int smp_suspend(void) { - int i, err; + int cpu, err; - lock_cpu_hotplug(); - - /* - * Take all other CPUs offline. We hold the hotplug mutex to - * avoid other processes bringing up CPUs under our feet. - */ - while (num_online_cpus() > 1) { - unlock_cpu_hotplug(); - for_each_online_cpu(i) { - if (i == 0) - continue; - err = cpu_down(i); - if (err) { - printk(KERN_CRIT "Failed to take all CPUs " - "down: %d.\n", err); - for_each_possible_cpu(i) - vcpu_hotplug(i); - return err; - } + for_each_online_cpu(cpu) { + if (cpu == 0) + continue; + err = cpu_down(cpu); + if (err) { + printk(KERN_CRIT "Failed to take all CPUs " + "down: %d.\n", err); + for_each_possible_cpu(cpu) + vcpu_hotplug(cpu); + return err; } - lock_cpu_hotplug(); } return 0; @@ -154,11 +143,6 @@ void smp_resume(void) { int cpu; - for_each_possible_cpu(cpu) - cpu_initialize_context(cpu); - - unlock_cpu_hotplug(); - for_each_possible_cpu(cpu) vcpu_hotplug(cpu); } diff --git a/linux-2.6-xen-sparse/drivers/xen/core/evtchn.c b/linux-2.6-xen-sparse/drivers/xen/core/evtchn.c index 3e66f3be45..fda12a3f32 100644 --- a/linux-2.6-xen-sparse/drivers/xen/core/evtchn.c +++ b/linux-2.6-xen-sparse/drivers/xen/core/evtchn.c @@ -30,7 +30,6 @@ * IN THE SOFTWARE. */ -#include #include #include #include @@ -889,11 +888,67 @@ void unmask_evtchn(int port) } EXPORT_SYMBOL_GPL(unmask_evtchn); -void irq_resume(void) +static void restore_cpu_virqs(int cpu) { struct evtchn_bind_virq bind_virq; - struct evtchn_bind_ipi bind_ipi; - int cpu, pirq, virq, ipi, irq, evtchn; + int virq, irq, evtchn; + + for (virq = 0; virq < NR_VIRQS; virq++) { + if ((irq = per_cpu(virq_to_irq, cpu)[virq]) == -1) + continue; + + BUG_ON(irq_info[irq] != mk_irq_info(IRQT_VIRQ, virq, 0)); + + /* Get a new binding from Xen. */ + bind_virq.virq = virq; + bind_virq.vcpu = cpu; + if (HYPERVISOR_event_channel_op(EVTCHNOP_bind_virq, + &bind_virq) != 0) + BUG(); + evtchn = bind_virq.port; + + /* Record the new mapping. */ + evtchn_to_irq[evtchn] = irq; + irq_info[irq] = mk_irq_info(IRQT_VIRQ, virq, evtchn); + bind_evtchn_to_cpu(evtchn, cpu); + + /* Ready for use. */ + unmask_evtchn(evtchn); + } +} + +static void restore_cpu_ipis(int cpu) +{ + struct evtchn_bind_ipi bind_ipi; + int ipi, irq, evtchn; + + for (ipi = 0; ipi < NR_IPIS; ipi++) { + if ((irq = per_cpu(ipi_to_irq, cpu)[ipi]) == -1) + continue; + + BUG_ON(irq_info[irq] != mk_irq_info(IRQT_IPI, ipi, 0)); + + /* Get a new binding from Xen. */ + bind_ipi.vcpu = cpu; + if (HYPERVISOR_event_channel_op(EVTCHNOP_bind_ipi, + &bind_ipi) != 0) + BUG(); + evtchn = bind_ipi.port; + + /* Record the new mapping. */ + evtchn_to_irq[evtchn] = irq; + irq_info[irq] = mk_irq_info(IRQT_IPI, ipi, evtchn); + bind_evtchn_to_cpu(evtchn, cpu); + + /* Ready for use. */ + unmask_evtchn(evtchn); + + } +} + +void irq_resume(void) +{ + int cpu, pirq, irq, evtchn; init_evtchn_cpu_bindings(); @@ -905,66 +960,17 @@ void irq_resume(void) for (pirq = 0; pirq < NR_PIRQS; pirq++) BUG_ON(irq_info[pirq_to_irq(pirq)] != IRQ_UNBOUND); - /* Secondary CPUs must have no VIRQ or IPI bindings. */ - for_each_possible_cpu(cpu) { - if (cpu == 0) - continue; - for (virq = 0; virq < NR_VIRQS; virq++) - BUG_ON(per_cpu(virq_to_irq, cpu)[virq] != -1); - for (ipi = 0; ipi < NR_IPIS; ipi++) - BUG_ON(per_cpu(ipi_to_irq, cpu)[ipi] != -1); - } - /* No IRQ <-> event-channel mappings. */ for (irq = 0; irq < NR_IRQS; irq++) irq_info[irq] &= ~0xFFFF; /* zap event-channel binding */ for (evtchn = 0; evtchn < NR_EVENT_CHANNELS; evtchn++) evtchn_to_irq[evtchn] = -1; - /* Primary CPU: rebind VIRQs automatically. */ - for (virq = 0; virq < NR_VIRQS; virq++) { - if ((irq = per_cpu(virq_to_irq, 0)[virq]) == -1) - continue; - - BUG_ON(irq_info[irq] != mk_irq_info(IRQT_VIRQ, virq, 0)); - - /* Get a new binding from Xen. */ - bind_virq.virq = virq; - bind_virq.vcpu = 0; - if (HYPERVISOR_event_channel_op(EVTCHNOP_bind_virq, - &bind_virq) != 0) - BUG(); - evtchn = bind_virq.port; - - /* Record the new mapping. */ - evtchn_to_irq[evtchn] = irq; - irq_info[irq] = mk_irq_info(IRQT_VIRQ, virq, evtchn); - - /* Ready for use. */ - unmask_evtchn(evtchn); + for_each_possible_cpu(cpu) { + restore_cpu_virqs(cpu); + restore_cpu_ipis(cpu); } - /* Primary CPU: rebind IPIs automatically. */ - for (ipi = 0; ipi < NR_IPIS; ipi++) { - if ((irq = per_cpu(ipi_to_irq, 0)[ipi]) == -1) - continue; - - BUG_ON(irq_info[irq] != mk_irq_info(IRQT_IPI, ipi, 0)); - - /* Get a new binding from Xen. */ - bind_ipi.vcpu = 0; - if (HYPERVISOR_event_channel_op(EVTCHNOP_bind_ipi, - &bind_ipi) != 0) - BUG(); - evtchn = bind_ipi.port; - - /* Record the new mapping. */ - evtchn_to_irq[evtchn] = irq; - irq_info[irq] = mk_irq_info(IRQT_IPI, ipi, evtchn); - - /* Ready for use. */ - unmask_evtchn(evtchn); - } } void __init xen_init_IRQ(void) diff --git a/linux-2.6-xen-sparse/drivers/xen/core/gnttab.c b/linux-2.6-xen-sparse/drivers/xen/core/gnttab.c index 80226fb6e8..07588d36a3 100644 --- a/linux-2.6-xen-sparse/drivers/xen/core/gnttab.c +++ b/linux-2.6-xen-sparse/drivers/xen/core/gnttab.c @@ -31,7 +31,6 @@ * IN THE SOFTWARE. */ -#include #include #include #include @@ -518,25 +517,26 @@ int gnttab_suspend(void) static int gnttab_map(unsigned int start_idx, unsigned int end_idx) { struct xen_add_to_physmap xatp; - unsigned int i; + unsigned int i = end_idx; /* Loop backwards, so that the first hypercall has the largest index, * ensuring that the table will grow only once. */ - for (i = end_idx; i >= start_idx; i--) { + do { xatp.domid = DOMID_SELF; xatp.idx = i; xatp.space = XENMAPSPACE_grant_table; xatp.gpfn = (resume_frames >> PAGE_SHIFT) + i; if (HYPERVISOR_memory_op(XENMEM_add_to_physmap, &xatp)) BUG(); - } + } while (i-- > start_idx); + + return 0; } int gnttab_resume(void) { - struct xen_add_to_physmap xatp; - unsigned int i, max_nr_gframes, nr_gframes; + unsigned int max_nr_gframes, nr_gframes; nr_gframes = nr_grant_frames; max_nr_gframes = max_nr_grant_frames(); diff --git a/linux-2.6-xen-sparse/drivers/xen/core/hypervisor_sysfs.c b/linux-2.6-xen-sparse/drivers/xen/core/hypervisor_sysfs.c index 42ee6a8148..ab3ce04d8e 100644 --- a/linux-2.6-xen-sparse/drivers/xen/core/hypervisor_sysfs.c +++ b/linux-2.6-xen-sparse/drivers/xen/core/hypervisor_sysfs.c @@ -7,7 +7,6 @@ * published by the Free Software Foundation. */ -#include #include #include #include diff --git a/linux-2.6-xen-sparse/drivers/xen/core/machine_reboot.c b/linux-2.6-xen-sparse/drivers/xen/core/machine_reboot.c index 07de13c835..72efdce56f 100644 --- a/linux-2.6-xen-sparse/drivers/xen/core/machine_reboot.c +++ b/linux-2.6-xen-sparse/drivers/xen/core/machine_reboot.c @@ -1,4 +1,3 @@ -#define __KERNEL_SYSCALLS__ #include #include #include @@ -7,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -18,6 +18,7 @@ #include #include #include +#include #if defined(__i386__) || defined(__x86_64__) @@ -58,27 +59,11 @@ EXPORT_SYMBOL(machine_restart); EXPORT_SYMBOL(machine_halt); EXPORT_SYMBOL(machine_power_off); -/* Ensure we run on the idle task page tables so that we will - switch page tables before running user space. This is needed - on architectures with separate kernel and user page tables - because the user page table pointer is not saved/restored. */ -static void switch_idle_mm(void) -{ - struct mm_struct *mm = current->active_mm; - - if (mm == &init_mm) - return; - - atomic_inc(&init_mm.mm_count); - switch_mm(mm, &init_mm, current); - current->active_mm = &init_mm; - mmdrop(mm); -} - static void pre_suspend(void) { HYPERVISOR_shared_info = (shared_info_t *)empty_zero_page; - clear_fixmap(FIX_SHARED_INFO); + HYPERVISOR_update_va_mapping(fix_to_virt(FIX_SHARED_INFO), + __pte_ma(0), 0); xen_start_info->store_mfn = mfn_to_pfn(xen_start_info->store_mfn); xen_start_info->console.domU.mfn = @@ -88,6 +73,7 @@ static void pre_suspend(void) static void post_suspend(int suspend_cancelled) { int i, j, k, fpp; + unsigned long shinfo_mfn; extern unsigned long max_pfn; extern unsigned long *pfn_to_mfn_frame_list_list; extern unsigned long *pfn_to_mfn_frame_list[]; @@ -97,10 +83,15 @@ static void post_suspend(int suspend_cancelled) pfn_to_mfn(xen_start_info->store_mfn); xen_start_info->console.domU.mfn = pfn_to_mfn(xen_start_info->console.domU.mfn); + } else { +#ifdef CONFIG_SMP + cpu_initialized_map = cpumask_of_cpu(0); +#endif } - - set_fixmap(FIX_SHARED_INFO, xen_start_info->shared_info); + shinfo_mfn = xen_start_info->shared_info >> PAGE_SHIFT; + HYPERVISOR_update_va_mapping(fix_to_virt(FIX_SHARED_INFO), + pfn_pte_ma(shinfo_mfn, PAGE_KERNEL), 0); HYPERVISOR_shared_info = (shared_info_t *)fix_to_virt(FIX_SHARED_INFO); memset(empty_zero_page, 0, PAGE_SIZE); @@ -130,12 +121,87 @@ static void post_suspend(int suspend_cancelled) #endif -int __xen_suspend(void) +static int take_machine_down(void *p_fast_suspend) +{ + int fast_suspend = *(int *)p_fast_suspend; + int suspend_cancelled, err, cpu; + extern void time_resume(void); + + if (fast_suspend) { + preempt_disable(); + } else { + for (;;) { + err = smp_suspend(); + if (err) + return err; + + xenbus_suspend(); + preempt_disable(); + + if (num_online_cpus() == 1) + break; + + preempt_enable(); + xenbus_suspend_cancel(); + } + } + + mm_pin_all(); + local_irq_disable(); + preempt_enable(); + gnttab_suspend(); + pre_suspend(); + + /* + * This hypercall returns 1 if suspend was cancelled or the domain was + * merely checkpointed, and 0 if it is resuming in a new domain. + */ + suspend_cancelled = HYPERVISOR_suspend(virt_to_mfn(xen_start_info)); + + post_suspend(suspend_cancelled); + gnttab_resume(); + if (!suspend_cancelled) { + irq_resume(); +#ifdef __x86_64__ + /* + * Older versions of Xen do not save/restore the user %cr3. + * We do it here just in case, but there's no need if we are + * in fast-suspend mode as that implies a new enough Xen. + */ + if (!fast_suspend) { + struct mmuext_op op; + op.cmd = MMUEXT_NEW_USER_BASEPTR; + op.arg1.mfn = pfn_to_mfn(__pa(__user_pgd( + current->active_mm->pgd)) >> PAGE_SHIFT); + if (HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF)) + BUG(); + } +#endif + } + time_resume(); + local_irq_enable(); + + if (fast_suspend && !suspend_cancelled) { + /* + * In fast-suspend mode the APs may not be brought back online + * when we resume. In that case we do it here. + */ + for_each_online_cpu(cpu) { + if (cpu == 0) + continue; + cpu_set_initialized(cpu); + err = HYPERVISOR_vcpu_op(VCPUOP_up, cpu, NULL); + BUG_ON(err); + } + } + + return suspend_cancelled; +} + +int __xen_suspend(int fast_suspend) { int err, suspend_cancelled; - extern void time_resume(void); - BUG_ON(smp_processor_id() != 0); BUG_ON(in_interrupt()); @@ -147,41 +213,21 @@ int __xen_suspend(void) } #endif - err = smp_suspend(); - if (err) + /* If we are definitely UP then 'slow mode' is actually faster. */ + if (num_possible_cpus() == 1) + fast_suspend = 0; + + if (fast_suspend) { + xenbus_suspend(); + err = stop_machine_run(take_machine_down, &fast_suspend, 0); + } else { + err = take_machine_down(&fast_suspend); + } + + if (err < 0) return err; - xenbus_suspend(); - - preempt_disable(); - - mm_pin_all(); - local_irq_disable(); - preempt_enable(); - - gnttab_suspend(); - - pre_suspend(); - - /* - * This hypercall returns 1 if suspend was cancelled or the domain was - * merely checkpointed, and 0 if it is resuming in a new domain. - */ - suspend_cancelled = HYPERVISOR_suspend(virt_to_mfn(xen_start_info)); - - post_suspend(suspend_cancelled); - - gnttab_resume(); - - if (!suspend_cancelled) - irq_resume(); - - time_resume(); - - switch_idle_mm(); - - local_irq_enable(); - + suspend_cancelled = err; if (!suspend_cancelled) { xencons_resume(); xenbus_resume(); @@ -189,7 +235,8 @@ int __xen_suspend(void) xenbus_suspend_cancel(); } - smp_resume(); + if (!fast_suspend) + smp_resume(); - return err; + return 0; } diff --git a/linux-2.6-xen-sparse/drivers/xen/core/reboot.c b/linux-2.6-xen-sparse/drivers/xen/core/reboot.c index aab244a738..0dcd2fa252 100644 --- a/linux-2.6-xen-sparse/drivers/xen/core/reboot.c +++ b/linux-2.6-xen-sparse/drivers/xen/core/reboot.c @@ -24,13 +24,16 @@ MODULE_LICENSE("Dual BSD/GPL"); /* Ignore multiple shutdown requests. */ static int shutting_down = SHUTDOWN_INVALID; +/* Can we leave APs online when we suspend? */ +static int fast_suspend; + static void __shutdown_handler(void *unused); static DECLARE_WORK(shutdown_work, __shutdown_handler, NULL); #ifdef CONFIG_XEN -int __xen_suspend(void); +int __xen_suspend(int fast_suspend); #else -#define __xen_suspend() (void)0 +#define __xen_suspend(fast_suspend) 0 #endif static int shutdown_process(void *__unused) @@ -44,7 +47,8 @@ static int shutdown_process(void *__unused) if ((shutting_down == SHUTDOWN_POWEROFF) || (shutting_down == SHUTDOWN_HALT)) { - if (call_usermodehelper("/sbin/poweroff", poweroff_argv, envp, 0) < 0) { + if (call_usermodehelper("/sbin/poweroff", poweroff_argv, + envp, 0) < 0) { #ifdef CONFIG_XEN sys_reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, @@ -61,7 +65,9 @@ static int shutdown_process(void *__unused) static int xen_suspend(void *__unused) { - __xen_suspend(); + int err = __xen_suspend(fast_suspend); + if (err) + printk(KERN_ERR "Xen suspend failed (%d)\n", err); shutting_down = SHUTDOWN_INVALID; return 0; } @@ -193,6 +199,10 @@ static int setup_shutdown_watcher(struct notifier_block *notifier, { int err; + xenbus_scanf(XBT_NIL, "control", + "platform-feature-multiprocessor-suspend", + "%d", &fast_suspend); + err = register_xenbus_watch(&shutdown_watch); if (err) printk(KERN_ERR "Failed to set shutdown watcher\n"); diff --git a/linux-2.6-xen-sparse/drivers/xen/core/smpboot.c b/linux-2.6-xen-sparse/drivers/xen/core/smpboot.c index 853df13908..fd8b170186 100644 --- a/linux-2.6-xen-sparse/drivers/xen/core/smpboot.c +++ b/linux-2.6-xen-sparse/drivers/xen/core/smpboot.c @@ -6,7 +6,6 @@ */ #include -#include #include #include #include @@ -48,7 +47,7 @@ cpumask_t cpu_online_map; EXPORT_SYMBOL(cpu_online_map); cpumask_t cpu_possible_map; EXPORT_SYMBOL(cpu_possible_map); -static cpumask_t cpu_initialized_map; +cpumask_t cpu_initialized_map; struct cpuinfo_x86 cpu_data[NR_CPUS] __cacheline_aligned; EXPORT_SYMBOL(cpu_data); @@ -186,7 +185,7 @@ static void cpu_bringup_and_idle(void) cpu_idle(); } -void cpu_initialize_context(unsigned int cpu) +static void cpu_initialize_context(unsigned int cpu) { vcpu_guest_context_t ctxt; struct task_struct *idle = idle_task(cpu); @@ -196,7 +195,7 @@ void cpu_initialize_context(unsigned int cpu) struct Xgt_desc_struct *gdt_descr = &per_cpu(cpu_gdt_descr, cpu); #endif - if (cpu == 0) + if (cpu_test_and_set(cpu, cpu_initialized_map)) return; memset(&ctxt, 0, sizeof(ctxt)); @@ -418,10 +417,7 @@ int __devinit __cpu_up(unsigned int cpu) if (rc) return rc; - if (!cpu_isset(cpu, cpu_initialized_map)) { - cpu_set(cpu, cpu_initialized_map); - cpu_initialize_context(cpu); - } + cpu_initialize_context(cpu); if (num_online_cpus() == 1) alternatives_smp_switch(1); diff --git a/linux-2.6-xen-sparse/drivers/xen/core/xen_proc.c b/linux-2.6-xen-sparse/drivers/xen/core/xen_proc.c index f00cd8168d..fe9311be66 100644 --- a/linux-2.6-xen-sparse/drivers/xen/core/xen_proc.c +++ b/linux-2.6-xen-sparse/drivers/xen/core/xen_proc.c @@ -1,5 +1,4 @@ -#include #include #include diff --git a/linux-2.6-xen-sparse/drivers/xen/core/xen_sysfs.c b/linux-2.6-xen-sparse/drivers/xen/core/xen_sysfs.c index b58cbe96c2..fd8bfdb53d 100644 --- a/linux-2.6-xen-sparse/drivers/xen/core/xen_sysfs.c +++ b/linux-2.6-xen-sparse/drivers/xen/core/xen_sysfs.c @@ -7,7 +7,6 @@ * published by the Free Software Foundation. */ -#include #include #include #include diff --git a/linux-2.6-xen-sparse/drivers/xen/evtchn/evtchn.c b/linux-2.6-xen-sparse/drivers/xen/evtchn/evtchn.c index 32f8de5bff..12fea95050 100644 --- a/linux-2.6-xen-sparse/drivers/xen/evtchn/evtchn.c +++ b/linux-2.6-xen-sparse/drivers/xen/evtchn/evtchn.c @@ -31,7 +31,6 @@ * IN THE SOFTWARE. */ -#include #include #include #include @@ -407,7 +406,7 @@ static int evtchn_release(struct inode *inode, struct file *filp) return 0; } -static struct file_operations evtchn_fops = { +static const struct file_operations evtchn_fops = { .owner = THIS_MODULE, .read = evtchn_read, .write = evtchn_write, diff --git a/linux-2.6-xen-sparse/drivers/xen/netback/common.h b/linux-2.6-xen-sparse/drivers/xen/netback/common.h index e0537e52ff..861c5faeac 100644 --- a/linux-2.6-xen-sparse/drivers/xen/netback/common.h +++ b/linux-2.6-xen-sparse/drivers/xen/netback/common.h @@ -29,7 +29,6 @@ #ifndef __NETIF__BACKEND__COMMON_H__ #define __NETIF__BACKEND__COMMON_H__ -#include #include #include #include @@ -100,9 +99,21 @@ typedef struct netif_st { struct net_device *dev; struct net_device_stats stats; + unsigned int carrier; + wait_queue_head_t waiting_to_free; } netif_t; +/* + * Implement our own carrier flag: the network stack's version causes delays + * when the carrier is re-enabled (in particular, dev_activate() may not + * immediately be called, which can cause packet loss; also the etherbridge + * can be rather lazy in activating its port). + */ +#define netback_carrier_on(netif) ((netif)->carrier = 1) +#define netback_carrier_off(netif) ((netif)->carrier = 0) +#define netback_carrier_ok(netif) ((netif)->carrier) + #define NET_TX_RING_SIZE __RING_SIZE((netif_tx_sring_t *)0, PAGE_SIZE) #define NET_RX_RING_SIZE __RING_SIZE((netif_rx_sring_t *)0, PAGE_SIZE) @@ -121,7 +132,8 @@ int netif_map(netif_t *netif, unsigned long tx_ring_ref, void netif_xenbus_init(void); -#define netif_schedulable(dev) (netif_running(dev) && netif_carrier_ok(dev)) +#define netif_schedulable(netif) \ + (netif_running((netif)->dev) && netback_carrier_ok(netif)) void netif_schedule_work(netif_t *netif); void netif_deschedule_work(netif_t *netif); diff --git a/linux-2.6-xen-sparse/drivers/xen/netback/interface.c b/linux-2.6-xen-sparse/drivers/xen/netback/interface.c index 8bf951117f..610891fc29 100644 --- a/linux-2.6-xen-sparse/drivers/xen/netback/interface.c +++ b/linux-2.6-xen-sparse/drivers/xen/netback/interface.c @@ -66,16 +66,19 @@ static void __netif_down(netif_t *netif) static int net_open(struct net_device *dev) { netif_t *netif = netdev_priv(dev); - if (netif_carrier_ok(dev)) + if (netback_carrier_ok(netif)) { __netif_up(netif); + netif_start_queue(dev); + } return 0; } static int net_close(struct net_device *dev) { netif_t *netif = netdev_priv(dev); - if (netif_carrier_ok(dev)) + if (netback_carrier_ok(netif)) __netif_down(netif); + netif_stop_queue(dev); return 0; } @@ -138,8 +141,6 @@ netif_t *netif_alloc(domid_t domid, unsigned int handle) return ERR_PTR(-ENOMEM); } - netif_carrier_off(dev); - netif = netdev_priv(dev); memset(netif, 0, sizeof(*netif)); netif->domid = domid; @@ -148,6 +149,8 @@ netif_t *netif_alloc(domid_t domid, unsigned int handle) init_waitqueue_head(&netif->waiting_to_free); netif->dev = dev; + netback_carrier_off(netif); + netif->credit_bytes = netif->remaining_credit = ~0UL; netif->credit_usec = 0UL; init_timer(&netif->credit_timeout); @@ -285,7 +288,7 @@ int netif_map(netif_t *netif, unsigned long tx_ring_ref, netif_get(netif); rtnl_lock(); - netif_carrier_on(netif->dev); + netback_carrier_on(netif); if (netif_running(netif->dev)) __netif_up(netif); rtnl_unlock(); @@ -302,9 +305,10 @@ err_rx: void netif_disconnect(netif_t *netif) { - if (netif_carrier_ok(netif->dev)) { + if (netback_carrier_ok(netif)) { rtnl_lock(); - netif_carrier_off(netif->dev); + netback_carrier_off(netif); + netif_carrier_off(netif->dev); /* discard queued packets */ if (netif_running(netif->dev)) __netif_down(netif); rtnl_unlock(); diff --git a/linux-2.6-xen-sparse/drivers/xen/netback/loopback.c b/linux-2.6-xen-sparse/drivers/xen/netback/loopback.c index d021c9689a..8f7c890b9d 100644 --- a/linux-2.6-xen-sparse/drivers/xen/netback/loopback.c +++ b/linux-2.6-xen-sparse/drivers/xen/netback/loopback.c @@ -45,7 +45,6 @@ * IN THE SOFTWARE. */ -#include #include #include #include diff --git a/linux-2.6-xen-sparse/drivers/xen/netback/netback.c b/linux-2.6-xen-sparse/drivers/xen/netback/netback.c index 2f88a9b51d..b05e3000e3 100644 --- a/linux-2.6-xen-sparse/drivers/xen/netback/netback.c +++ b/linux-2.6-xen-sparse/drivers/xen/netback/netback.c @@ -38,7 +38,10 @@ #include #include -/*#define NETBE_DEBUG_INTERRUPT*/ +/*define NETBE_DEBUG_INTERRUPT*/ + +/* extra field used in struct page */ +#define netif_page_index(pg) (*(long *)&(pg)->mapping) struct netbk_rx_meta { skb_frag_t frag; @@ -231,7 +234,7 @@ static inline int netbk_queue_full(netif_t *netif) static void tx_queue_callback(unsigned long data) { netif_t *netif = (netif_t *)data; - if (netif_schedulable(netif->dev)) + if (netif_schedulable(netif)) netif_wake_queue(netif->dev); } @@ -242,7 +245,7 @@ int netif_be_start_xmit(struct sk_buff *skb, struct net_device *dev) BUG_ON(skb->dev != dev); /* Drop the packet if the target domain has no receive buffers. */ - if (unlikely(!netif_schedulable(dev) || netbk_queue_full(netif))) + if (unlikely(!netif_schedulable(netif) || netbk_queue_full(netif))) goto drop; /* @@ -352,7 +355,7 @@ static u16 netbk_gop_frag(netif_t *netif, struct netbk_rx_meta *meta, copy_gop->flags = GNTCOPY_dest_gref; if (PageForeign(page)) { struct pending_tx_info *src_pend = - &pending_tx_info[page->index]; + &pending_tx_info[netif_page_index(page)]; copy_gop->source.domid = src_pend->netif->domid; copy_gop->source.u.ref = src_pend->req.gref; copy_gop->flags |= GNTCOPY_source_gref; @@ -681,7 +684,7 @@ static void net_rx_action(unsigned long unused) } if (netif_queue_stopped(netif->dev) && - netif_schedulable(netif->dev) && + netif_schedulable(netif) && !netbk_queue_full(netif)) netif_wake_queue(netif->dev); @@ -739,7 +742,7 @@ static void add_to_net_schedule_list_tail(netif_t *netif) spin_lock_irq(&net_schedule_list_lock); if (!__on_net_schedule_list(netif) && - likely(netif_schedulable(netif->dev))) { + likely(netif_schedulable(netif))) { list_add_tail(&netif->list, &net_schedule_list); netif_get(netif); } @@ -1327,7 +1330,7 @@ static void netif_page_release(struct page *page) /* Ready for next use. */ init_page_count(page); - netif_idx_release(page->index); + netif_idx_release(netif_page_index(page)); } irqreturn_t netif_be_int(int irq, void *dev_id, struct pt_regs *regs) @@ -1337,7 +1340,7 @@ irqreturn_t netif_be_int(int irq, void *dev_id, struct pt_regs *regs) add_to_net_schedule_list_tail(netif); maybe_schedule_tx_action(); - if (netif_schedulable(netif->dev) && !netbk_queue_full(netif)) + if (netif_schedulable(netif) && !netbk_queue_full(netif)) netif_wake_queue(netif->dev); return IRQ_HANDLED; @@ -1457,7 +1460,7 @@ static int __init netback_init(void) for (i = 0; i < MAX_PENDING_REQS; i++) { page = mmap_pages[i]; SetPageForeign(page, netif_page_release); - page->index = i; + netif_page_index(page) = i; } pending_cons = 0; diff --git a/linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c b/linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c index 12a3dc26f8..50bc909309 100644 --- a/linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c +++ b/linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c @@ -338,9 +338,7 @@ static void connect(struct backend_info *be) xenbus_switch_state(dev, XenbusStateConnected); - /* May not get a kick from the frontend, so start the tx_queue now. */ - if (!netbk_can_queue(be->netif->dev)) - netif_wake_queue(be->netif->dev); + netif_wake_queue(be->netif->dev); } diff --git a/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c b/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c index 80d1a3e995..17d1daf658 100644 --- a/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c +++ b/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c @@ -29,7 +29,6 @@ * IN THE SOFTWARE. */ -#include #include #include #include @@ -155,6 +154,7 @@ struct netfront_info { unsigned int irq; unsigned int copying_receiver; + unsigned int carrier; /* Receive-ring batched refills. */ #define RX_MIN_TARGET 8 @@ -193,6 +193,15 @@ struct netfront_rx_info { struct netif_extra_info extras[XEN_NETIF_EXTRA_TYPE_MAX - 1]; }; +/* + * Implement our own carrier flag: the network stack's version causes delays + * when the carrier is re-enabled (in particular, dev_activate() may not + * immediately be called, which can cause packet loss). + */ +#define netfront_carrier_on(netif) ((netif)->carrier = 1) +#define netfront_carrier_off(netif) ((netif)->carrier = 0) +#define netfront_carrier_ok(netif) ((netif)->carrier) + /* * Access macros for acquiring freeing slots in tx_skbs[]. */ @@ -591,26 +600,6 @@ static int send_fake_arp(struct net_device *dev) return dev_queue_xmit(skb); } -static int network_open(struct net_device *dev) -{ - struct netfront_info *np = netdev_priv(dev); - - memset(&np->stats, 0, sizeof(np->stats)); - - spin_lock(&np->rx_lock); - if (netif_carrier_ok(dev)) { - network_alloc_rx_buffers(dev); - np->rx.sring->rsp_event = np->rx.rsp_cons + 1; - if (RING_HAS_UNCONSUMED_RESPONSES(&np->rx)) - netif_rx_schedule(dev); - } - spin_unlock(&np->rx_lock); - - netif_start_queue(dev); - - return 0; -} - static inline int netfront_tx_slot_available(struct netfront_info *np) { return ((np->tx.req_prod_pvt - np->tx.rsp_cons) < @@ -627,6 +616,26 @@ static inline void network_maybe_wake_tx(struct net_device *dev) netif_wake_queue(dev); } +static int network_open(struct net_device *dev) +{ + struct netfront_info *np = netdev_priv(dev); + + memset(&np->stats, 0, sizeof(np->stats)); + + spin_lock(&np->rx_lock); + if (netfront_carrier_ok(np)) { + network_alloc_rx_buffers(dev); + np->rx.sring->rsp_event = np->rx.rsp_cons + 1; + if (RING_HAS_UNCONSUMED_RESPONSES(&np->rx)) + netif_rx_schedule(dev); + } + spin_unlock(&np->rx_lock); + + network_maybe_wake_tx(dev); + + return 0; +} + static void network_tx_buf_gc(struct net_device *dev) { RING_IDX cons, prod; @@ -634,7 +643,7 @@ static void network_tx_buf_gc(struct net_device *dev) struct netfront_info *np = netdev_priv(dev); struct sk_buff *skb; - BUG_ON(!netif_carrier_ok(dev)); + BUG_ON(!netfront_carrier_ok(np)); do { prod = np->tx.sring->rsp_prod; @@ -704,7 +713,7 @@ static void network_alloc_rx_buffers(struct net_device *dev) int nr_flips; netif_rx_request_t *req; - if (unlikely(!netif_carrier_ok(dev))) + if (unlikely(!netfront_carrier_ok(np))) return; /* @@ -935,7 +944,7 @@ static int network_start_xmit(struct sk_buff *skb, struct net_device *dev) spin_lock_irq(&np->tx_lock); - if (unlikely(!netif_carrier_ok(dev) || + if (unlikely(!netfront_carrier_ok(np) || (frags > 1 && !xennet_can_sg(dev)) || netif_needs_gso(dev, skb))) { spin_unlock_irq(&np->tx_lock); @@ -1025,7 +1034,7 @@ static irqreturn_t netif_int(int irq, void *dev_id, struct pt_regs *ptregs) spin_lock_irqsave(&np->tx_lock, flags); - if (likely(netif_carrier_ok(dev))) { + if (likely(netfront_carrier_ok(np))) { network_tx_buf_gc(dev); /* Under tx_lock: protects access to rx shared-ring indexes. */ if (RING_HAS_UNCONSUMED_RESPONSES(&np->rx)) @@ -1300,7 +1309,7 @@ static int netif_poll(struct net_device *dev, int *pbudget) spin_lock(&np->rx_lock); - if (unlikely(!netif_carrier_ok(dev))) { + if (unlikely(!netfront_carrier_ok(np))) { spin_unlock(&np->rx_lock); return 0; } @@ -1318,7 +1327,7 @@ static int netif_poll(struct net_device *dev, int *pbudget) work_done = 0; while ((i != rp) && (work_done < budget)) { memcpy(rx, RING_GET_RESPONSE(&np->rx, i), sizeof(*rx)); - memset(extras, 0, sizeof(extras)); + memset(extras, 0, sizeof(rinfo.extras)); err = xennet_get_responses(np, &rinfo, rp, &tmpq, &pages_flipped); @@ -1745,7 +1754,7 @@ static int network_connect(struct net_device *dev) * domain a kick because we've probably just requeued some * packets. */ - netif_carrier_on(dev); + netfront_carrier_on(np); notify_remote_via_irq(np->irq); network_tx_buf_gc(dev); network_alloc_rx_buffers(dev); @@ -1990,7 +1999,7 @@ static struct net_device * __devinit create_netdev(struct xenbus_device *dev) np->netdev = netdev; - netif_carrier_off(netdev); + netfront_carrier_off(np); return netdev; @@ -2024,7 +2033,7 @@ static void netif_disconnect_backend(struct netfront_info *info) /* Stop old i/f to prevent errors whilst we rebuild the state. */ spin_lock_irq(&info->tx_lock); spin_lock(&info->rx_lock); - netif_carrier_off(info->netdev); + netfront_carrier_off(info); spin_unlock(&info->rx_lock); spin_unlock_irq(&info->tx_lock); diff --git a/linux-2.6-xen-sparse/drivers/xen/pcifront/pci_op.c b/linux-2.6-xen-sparse/drivers/xen/pcifront/pci_op.c index 47b4d1e372..608c277b2f 100644 --- a/linux-2.6-xen-sparse/drivers/xen/pcifront/pci_op.c +++ b/linux-2.6-xen-sparse/drivers/xen/pcifront/pci_op.c @@ -239,17 +239,12 @@ static void free_root_bus_devs(struct pci_bus *bus) { struct pci_dev *dev; - down_write(&pci_bus_sem); while (!list_empty(&bus->devices)) { - dev = container_of(bus->devices.next, struct pci_dev, bus_list); - up_write(&pci_bus_sem); - + dev = container_of(bus->devices.next, struct pci_dev, + bus_list); dev_dbg(&dev->dev, "removing device\n"); pci_remove_bus_device(dev); - - down_write(&pci_bus_sem); } - up_write(&pci_bus_sem); } void pcifront_free_roots(struct pcifront_device *pdev) diff --git a/linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c b/linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c index d159e4ac74..46414068c1 100644 --- a/linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c +++ b/linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c @@ -6,7 +6,6 @@ * Copyright (c) 2002-2004, K A Fraser, B Dragovic */ -#include #include #include #include @@ -249,7 +248,7 @@ static int privcmd_enforce_singleshot_mapping(struct vm_area_struct *vma) } #endif -static struct file_operations privcmd_file_ops = { +static const struct file_operations privcmd_file_ops = { .ioctl = privcmd_ioctl, .mmap = privcmd_mmap, }; diff --git a/linux-2.6-xen-sparse/drivers/xen/tpmback/common.h b/linux-2.6-xen-sparse/drivers/xen/tpmback/common.h index d28eb31fdd..80655ebffb 100644 --- a/linux-2.6-xen-sparse/drivers/xen/tpmback/common.h +++ b/linux-2.6-xen-sparse/drivers/xen/tpmback/common.h @@ -2,10 +2,9 @@ * drivers/xen/tpmback/common.h */ -#ifndef __NETIF__BACKEND__COMMON_H__ -#define __NETIF__BACKEND__COMMON_H__ +#ifndef __TPM__BACKEND__COMMON_H__ +#define __TPM__BACKEND__COMMON_H__ -#include #include #include #include diff --git a/linux-2.6-xen-sparse/drivers/xen/tpmback/tpmback.c b/linux-2.6-xen-sparse/drivers/xen/tpmback/tpmback.c index 701a5ad03e..662144ddde 100644 --- a/linux-2.6-xen-sparse/drivers/xen/tpmback/tpmback.c +++ b/linux-2.6-xen-sparse/drivers/xen/tpmback/tpmback.c @@ -629,7 +629,7 @@ static unsigned int vtpm_op_poll(struct file *file, return flags; } -static struct file_operations vtpm_ops = { +static const struct file_operations vtpm_ops = { .owner = THIS_MODULE, .llseek = no_llseek, .open = vtpm_op_open, diff --git a/linux-2.6-xen-sparse/drivers/xen/util.c b/linux-2.6-xen-sparse/drivers/xen/util.c index 8f5ae386ff..9d32712ff7 100644 --- a/linux-2.6-xen-sparse/drivers/xen/util.c +++ b/linux-2.6-xen-sparse/drivers/xen/util.c @@ -1,4 +1,3 @@ -#include #include #include #include diff --git a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.c b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.c index b758c9f676..c00aaf7f6f 100644 --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.c +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.c @@ -137,6 +137,17 @@ int xb_write(const void *data, unsigned len) return 0; } +int xb_data_to_read(void) +{ + struct xenstore_domain_interface *intf = xen_store_interface; + return (intf->rsp_cons != intf->rsp_prod); +} + +int xb_wait_for_data_to_read(void) +{ + return wait_event_interruptible(xb_waitq, xb_data_to_read()); +} + int xb_read(void *data, unsigned len) { struct xenstore_domain_interface *intf = xen_store_interface; @@ -147,9 +158,7 @@ int xb_read(void *data, unsigned len) unsigned int avail; const char *src; - rc = wait_event_interruptible( - xb_waitq, - intf->rsp_cons != intf->rsp_prod); + rc = xb_wait_for_data_to_read(); if (rc < 0) return rc; @@ -191,8 +200,20 @@ int xb_read(void *data, unsigned len) /* Set up interrupt handler off store event channel. */ int xb_init_comms(void) { + struct xenstore_domain_interface *intf = xen_store_interface; int err; + if (intf->req_prod != intf->req_cons) + printk(KERN_ERR "XENBUS request ring is not quiescent " + "(%08x:%08x)!\n", intf->req_cons, intf->req_prod); + + if (intf->rsp_prod != intf->rsp_cons) { + printk(KERN_WARNING "XENBUS response ring is not quiescent " + "(%08x:%08x): fixing up\n", + intf->rsp_cons, intf->rsp_prod); + intf->rsp_cons = intf->rsp_prod; + } + if (xenbus_irq) unbind_from_irqhandler(xenbus_irq, &xb_waitq); diff --git a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.h b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.h index b54d168cbb..505100dace 100644 --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.h +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.h @@ -37,6 +37,8 @@ int xb_init_comms(void); /* Low level routines. */ int xb_write(const void *data, unsigned len); int xb_read(void *data, unsigned len); +int xb_data_to_read(void); +int xb_wait_for_data_to_read(void); int xs_input_avail(void); extern struct xenstore_domain_interface *xen_store_interface; extern int xen_store_evtchn; diff --git a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_dev.c b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_dev.c index ba37e61856..6a81140af1 100644 --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_dev.c +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_dev.c @@ -32,7 +32,6 @@ * IN THE SOFTWARE. */ -#include #include #include #include @@ -174,17 +173,22 @@ static ssize_t xenbus_dev_write(struct file *filp, void *reply; char *path, *token; struct watch_adapter *watch, *tmp_watch; - int err; + int err, rc = len; - if ((len + u->len) > sizeof(u->u.buffer)) - return -EINVAL; + if ((len + u->len) > sizeof(u->u.buffer)) { + rc = -EINVAL; + goto out; + } - if (copy_from_user(u->u.buffer + u->len, ubuf, len) != 0) - return -EFAULT; + if (copy_from_user(u->u.buffer + u->len, ubuf, len) != 0) { + rc = -EFAULT; + goto out; + } u->len += len; - if (u->len < (sizeof(u->u.msg) + u->u.msg.len)) - return len; + if ((u->len < sizeof(u->u.msg)) || + (u->len < (sizeof(u->u.msg) + u->u.msg.len))) + return rc; msg_type = u->u.msg.type; @@ -202,14 +206,17 @@ static ssize_t xenbus_dev_write(struct file *filp, case XS_SET_PERMS: if (msg_type == XS_TRANSACTION_START) { trans = kmalloc(sizeof(*trans), GFP_KERNEL); - if (!trans) - return -ENOMEM; + if (!trans) { + rc = -ENOMEM; + goto out; + } } reply = xenbus_dev_request_and_reply(&u->u.msg); if (IS_ERR(reply)) { kfree(trans); - return PTR_ERR(reply); + rc = PTR_ERR(reply); + goto out; } if (msg_type == XS_TRANSACTION_START) { @@ -232,8 +239,10 @@ static ssize_t xenbus_dev_write(struct file *filp, case XS_UNWATCH: path = u->u.buffer + sizeof(u->u.msg); token = memchr(path, 0, u->u.msg.len); - if (token == NULL) - return -EILSEQ; + if (token == NULL) { + rc = -EILSEQ; + goto out; + } token++; if (msg_type == XS_WATCH) { @@ -252,7 +261,8 @@ static ssize_t xenbus_dev_write(struct file *filp, err = register_xenbus_watch(&watch->watch); if (err) { free_watch_adapter(watch); - return err; + rc = err; + goto out; } list_add(&watch->list, &u->watches); @@ -266,7 +276,6 @@ static ssize_t xenbus_dev_write(struct file *filp, &u->watches, list) { if (!strcmp(watch->token, token) && !strcmp(watch->watch.node, path)) - break; { unregister_xenbus_watch(&watch->watch); list_del(&watch->list); @@ -279,11 +288,13 @@ static ssize_t xenbus_dev_write(struct file *filp, break; default: - return -EINVAL; + rc = -EINVAL; + break; } + out: u->len = 0; - return len; + return rc; } static int xenbus_dev_open(struct inode *inode, struct file *filp) @@ -343,7 +354,7 @@ static unsigned int xenbus_dev_poll(struct file *file, poll_table *wait) return 0; } -static struct file_operations xenbus_dev_file_ops = { +static const struct file_operations xenbus_dev_file_ops = { .read = xenbus_dev_read, .write = xenbus_dev_write, .open = xenbus_dev_open, diff --git a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_xs.c b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_xs.c index 23b99b86f5..b1387e3574 100644 --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_xs.c +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_xs.c @@ -77,11 +77,22 @@ struct xs_handle { spinlock_t reply_lock; wait_queue_head_t reply_waitq; + /* + * Mutex ordering: transaction_mutex -> watch_mutex -> request_mutex. + * response_mutex is never taken simultaneously with the other three. + */ + /* One request at a time. */ struct mutex request_mutex; + /* Protect xenbus reader thread against save/restore. */ + struct mutex response_mutex; + /* Protect transactions against save/restore. */ - struct rw_semaphore suspend_mutex; + struct rw_semaphore transaction_mutex; + + /* Protect watch (de)register against save/restore. */ + struct rw_semaphore watch_mutex; }; static struct xs_handle xs_state; @@ -150,22 +161,6 @@ static void *read_reply(enum xsd_sockmsg_type *type, unsigned int *len) return body; } -/* Emergency write. */ -void xenbus_debug_write(const char *str, unsigned int count) -{ - struct xsd_sockmsg msg = { 0 }; - - msg.type = XS_DEBUG; - msg.len = sizeof("print") + count + 1; - - mutex_lock(&xs_state.request_mutex); - xb_write(&msg, sizeof(msg)); - xb_write("print", sizeof("print")); - xb_write(str, count); - xb_write("", 1); - mutex_unlock(&xs_state.request_mutex); -} - void *xenbus_dev_request_and_reply(struct xsd_sockmsg *msg) { void *ret; @@ -173,7 +168,7 @@ void *xenbus_dev_request_and_reply(struct xsd_sockmsg *msg) int err; if (req_msg.type == XS_TRANSACTION_START) - down_read(&xs_state.suspend_mutex); + down_read(&xs_state.transaction_mutex); mutex_lock(&xs_state.request_mutex); @@ -189,7 +184,7 @@ void *xenbus_dev_request_and_reply(struct xsd_sockmsg *msg) if ((req_msg.type == XS_TRANSACTION_END) || ((req_msg.type == XS_TRANSACTION_START) && (msg->type == XS_ERROR))) - up_read(&xs_state.suspend_mutex); + up_read(&xs_state.transaction_mutex); return ret; } @@ -440,11 +435,11 @@ int xenbus_transaction_start(struct xenbus_transaction *t) { char *id_str; - down_read(&xs_state.suspend_mutex); + down_read(&xs_state.transaction_mutex); id_str = xs_single(XBT_NIL, XS_TRANSACTION_START, "", NULL); if (IS_ERR(id_str)) { - up_read(&xs_state.suspend_mutex); + up_read(&xs_state.transaction_mutex); return PTR_ERR(id_str); } @@ -469,7 +464,7 @@ int xenbus_transaction_end(struct xenbus_transaction t, int abort) err = xs_error(xs_single(t, XS_TRANSACTION_END, abortstr, NULL)); - up_read(&xs_state.suspend_mutex); + up_read(&xs_state.transaction_mutex); return err; } @@ -602,7 +597,7 @@ int register_xenbus_watch(struct xenbus_watch *watch) sprintf(token, "%lX", (long)watch); - down_read(&xs_state.suspend_mutex); + down_read(&xs_state.watch_mutex); spin_lock(&watches_lock); BUG_ON(find_watch(token)); @@ -618,7 +613,7 @@ int register_xenbus_watch(struct xenbus_watch *watch) spin_unlock(&watches_lock); } - up_read(&xs_state.suspend_mutex); + up_read(&xs_state.watch_mutex); return err; } @@ -632,7 +627,7 @@ void unregister_xenbus_watch(struct xenbus_watch *watch) sprintf(token, "%lX", (long)watch); - down_read(&xs_state.suspend_mutex); + down_read(&xs_state.watch_mutex); spin_lock(&watches_lock); BUG_ON(!find_watch(token)); @@ -645,7 +640,7 @@ void unregister_xenbus_watch(struct xenbus_watch *watch) "XENBUS Failed to release watch %s: %i\n", watch->node, err); - up_read(&xs_state.suspend_mutex); + up_read(&xs_state.watch_mutex); /* Cancel pending watch events. */ spin_lock(&watch_events_lock); @@ -668,8 +663,10 @@ EXPORT_SYMBOL_GPL(unregister_xenbus_watch); void xs_suspend(void) { - down_write(&xs_state.suspend_mutex); + down_write(&xs_state.transaction_mutex); + down_write(&xs_state.watch_mutex); mutex_lock(&xs_state.request_mutex); + mutex_lock(&xs_state.response_mutex); } void xs_resume(void) @@ -677,21 +674,25 @@ void xs_resume(void) struct xenbus_watch *watch; char token[sizeof(watch) * 2 + 1]; + mutex_unlock(&xs_state.response_mutex); mutex_unlock(&xs_state.request_mutex); + up_write(&xs_state.transaction_mutex); - /* No need for watches_lock: the suspend_mutex is sufficient. */ + /* No need for watches_lock: the watch_mutex is sufficient. */ list_for_each_entry(watch, &watches, list) { sprintf(token, "%lX", (long)watch); xs_watch(watch->node, token); } - up_write(&xs_state.suspend_mutex); + up_write(&xs_state.watch_mutex); } void xs_suspend_cancel(void) { + mutex_unlock(&xs_state.response_mutex); mutex_unlock(&xs_state.request_mutex); - up_write(&xs_state.suspend_mutex); + up_write(&xs_state.watch_mutex); + up_write(&xs_state.transaction_mutex); } static int xenwatch_handle_callback(void *data) @@ -753,27 +754,46 @@ static int process_msg(void) char *body; int err; + /* + * We must disallow save/restore while reading a xenstore message. + * A partial read across s/r leaves us out of sync with xenstored. + */ + for (;;) { + err = xb_wait_for_data_to_read(); + if (err) + return err; + mutex_lock(&xs_state.response_mutex); + if (xb_data_to_read()) + break; + /* We raced with save/restore: pending data 'disappeared'. */ + mutex_unlock(&xs_state.response_mutex); + } + + msg = kmalloc(sizeof(*msg), GFP_KERNEL); - if (msg == NULL) - return -ENOMEM; + if (msg == NULL) { + err = -ENOMEM; + goto out; + } err = xb_read(&msg->hdr, sizeof(msg->hdr)); if (err) { kfree(msg); - return err; + goto out; } body = kmalloc(msg->hdr.len + 1, GFP_KERNEL); if (body == NULL) { kfree(msg); - return -ENOMEM; + err = -ENOMEM; + goto out; } err = xb_read(body, msg->hdr.len); if (err) { kfree(body); kfree(msg); - return err; + goto out; } body[msg->hdr.len] = '\0'; @@ -782,7 +802,8 @@ static int process_msg(void) &msg->u.watch.vec_size); if (IS_ERR(msg->u.watch.vec)) { kfree(msg); - return PTR_ERR(msg->u.watch.vec); + err = PTR_ERR(msg->u.watch.vec); + goto out; } spin_lock(&watches_lock); @@ -806,7 +827,9 @@ static int process_msg(void) wake_up(&xs_state.reply_waitq); } - return 0; + out: + mutex_unlock(&xs_state.response_mutex); + return err; } static int xenbus_thread(void *unused) @@ -835,7 +858,9 @@ int xs_init(void) init_waitqueue_head(&xs_state.reply_waitq); mutex_init(&xs_state.request_mutex); - init_rwsem(&xs_state.suspend_mutex); + mutex_init(&xs_state.response_mutex); + init_rwsem(&xs_state.transaction_mutex); + init_rwsem(&xs_state.watch_mutex); /* Initialize the shared memory rings to talk to xenstored */ err = xb_init_comms(); diff --git a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/dma-mapping.h b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/dma-mapping.h index 38befd4ed0..39a9ce0ad0 100644 --- a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/dma-mapping.h +++ b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/dma-mapping.h @@ -6,7 +6,6 @@ * documentation. */ -#include #include #include #include diff --git a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypervisor.h b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypervisor.h index ffe031b601..5797dcc696 100644 --- a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypervisor.h +++ b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypervisor.h @@ -33,7 +33,6 @@ #ifndef __HYPERVISOR_H__ #define __HYPERVISOR_H__ -#include #include #include #include @@ -57,7 +56,11 @@ extern shared_info_t *HYPERVISOR_shared_info; #define vcpu_info(cpu) (HYPERVISOR_shared_info->vcpu_info + (cpu)) +#ifdef CONFIG_SMP #define current_vcpu_info() vcpu_info(smp_processor_id()) +#else +#define current_vcpu_info() vcpu_info(0) +#endif #ifdef CONFIG_X86_32 extern unsigned long hypervisor_virt_start; diff --git a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/page.h b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/page.h index 7edb3e7ccf..5f7e40d725 100644 --- a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/page.h +++ b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/page.h @@ -20,6 +20,14 @@ #define LARGE_PAGE_SIZE (1UL << PMD_SHIFT) #ifdef __KERNEL__ + +/* + * Need to repeat this here in order to not include pgtable.h (which in turn + * depends on definitions made here), but to be able to use the symbolic + * below. The preprocessor will warn if the two definitions aren't identical. + */ +#define _PAGE_PRESENT 0x001 + #ifndef __ASSEMBLY__ #include @@ -29,13 +37,6 @@ #include #include -/* - * Need to repeat this here in order to not include pgtable.h (which in turn - * depends on definitions made here), but to be able to use the symbolic - * below. The preprocessor will warn if the two definitions aren't identical. - */ -#define _PAGE_PRESENT 0x001 - #define arch_free_page(_page,_order) \ ({ int foreign = PageForeign(_page); \ if (foreign) \ @@ -139,7 +140,11 @@ typedef struct { unsigned long pgprot; } pgprot_t; static inline unsigned long pgd_val(pgd_t x) { unsigned long ret = x.pgd; +#ifdef CONFIG_XEN_COMPAT_030002 + if (ret) ret = machine_to_phys(ret) | _PAGE_PRESENT; +#else if (ret & _PAGE_PRESENT) ret = machine_to_phys(ret); +#endif return ret; } #define HPAGE_SHIFT 22 @@ -221,8 +226,6 @@ extern int page_is_ram(unsigned long pagenr); ((current->personality & READ_IMPLIES_EXEC) ? VM_EXEC : 0 ) | \ VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC) -#define __HAVE_ARCH_GATE_AREA 1 - #include #include diff --git a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/swiotlb.h b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/swiotlb.h index cf3efdeed6..0a287eff2c 100644 --- a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/swiotlb.h +++ b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/swiotlb.h @@ -1,8 +1,6 @@ #ifndef _ASM_SWIOTLB_H #define _ASM_SWIOTLB_H 1 -#include - /* SWIOTLB interface */ extern dma_addr_t swiotlb_map_single(struct device *hwdev, void *ptr, size_t size, diff --git a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/synch_bitops.h b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/synch_bitops.h index 807ca388c5..f2e5f853e2 100644 --- a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/synch_bitops.h +++ b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/synch_bitops.h @@ -7,8 +7,6 @@ * when communicating with Xen or other guest OSes running on other CPUs. */ -#include - #ifdef HAVE_XEN_PLATFORM_COMPAT_H #include #endif diff --git a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/system.h b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/system.h index 55b227aa59..37e8a5cc65 100644 --- a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/system.h +++ b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/system.h @@ -137,7 +137,7 @@ __asm__ __volatile__ ("movw %%dx,%1\n\t" \ }) #define write_cr4(x) \ - __asm__ __volatile__("movl %0,%%cr4": :"r" (x)); + __asm__ __volatile__("movl %0,%%cr4": :"r" (x)) /* * Clear and set 'TS' bit respectively diff --git a/linux-2.6-xen-sparse/include/asm-ia64/hypervisor.h b/linux-2.6-xen-sparse/include/asm-ia64/hypervisor.h index 6485dd87f0..4cfea9a769 100644 --- a/linux-2.6-xen-sparse/include/asm-ia64/hypervisor.h +++ b/linux-2.6-xen-sparse/include/asm-ia64/hypervisor.h @@ -46,7 +46,6 @@ extern int running_on_xen; #endif /* CONFIG_XEN */ #if defined(CONFIG_XEN) || defined(CONFIG_VMX_GUEST) -#include #include #include #include diff --git a/linux-2.6-xen-sparse/include/asm-ia64/swiotlb.h b/linux-2.6-xen-sparse/include/asm-ia64/swiotlb.h index 74a0c21bbe..c9afcbbf0e 100644 --- a/linux-2.6-xen-sparse/include/asm-ia64/swiotlb.h +++ b/linux-2.6-xen-sparse/include/asm-ia64/swiotlb.h @@ -1,8 +1,6 @@ #ifndef _ASM_SWIOTLB_H #define _ASM_SWIOTLB_H 1 -#include - /* SWIOTLB interface */ extern dma_addr_t swiotlb_map_single(struct device *hwdev, void *ptr, size_t size, diff --git a/linux-2.6-xen-sparse/include/asm-ia64/synch_bitops.h b/linux-2.6-xen-sparse/include/asm-ia64/synch_bitops.h index 6c01cf8b7e..21b7f8cd14 100644 --- a/linux-2.6-xen-sparse/include/asm-ia64/synch_bitops.h +++ b/linux-2.6-xen-sparse/include/asm-ia64/synch_bitops.h @@ -7,8 +7,6 @@ * when communicating with Xen or other guest OSes running on other CPUs. */ -#include - #define ADDR (*(volatile long *) addr) static __inline__ void synch_set_bit(int nr, volatile void * addr) diff --git a/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/fixmap.h b/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/fixmap.h index 693adff6de..3e4d0daef9 100644 --- a/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/fixmap.h +++ b/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/fixmap.h @@ -53,6 +53,11 @@ enum fixed_addresses { #define NR_FIX_ISAMAPS 256 FIX_ISAMAP_END, FIX_ISAMAP_BEGIN = FIX_ISAMAP_END + NR_FIX_ISAMAPS - 1, + __end_of_permanent_fixed_addresses, + /* temporary boot-time mappings, used before ioremap() is functional */ +#define NR_FIX_BTMAPS 16 + FIX_BTMAP_END = __end_of_permanent_fixed_addresses, + FIX_BTMAP_BEGIN = FIX_BTMAP_END + NR_FIX_BTMAPS - 1, __end_of_fixed_addresses }; diff --git a/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/io.h b/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/io.h index 4788b4bcc2..d92cbd5572 100644 --- a/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/io.h +++ b/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/io.h @@ -150,8 +150,10 @@ static inline void __iomem * ioremap (unsigned long offset, unsigned long size) return __ioremap(offset, size, 0); } -extern void *early_ioremap(unsigned long addr, unsigned long size); -extern void early_iounmap(void *addr, unsigned long size); +extern void *bt_ioremap(unsigned long addr, unsigned long size); +extern void bt_iounmap(void *addr, unsigned long size); +#define early_ioremap bt_ioremap +#define early_iounmap bt_iounmap /* * This one maps high address device memory and turns off caching for that area. diff --git a/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/irq.h b/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/irq.h index e52fab7966..f489bf586e 100644 --- a/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/irq.h +++ b/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/irq.h @@ -10,7 +10,6 @@ * */ -#include #include /* include comes from machine specific directory */ #include "irq_vectors.h" diff --git a/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/pgtable.h b/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/pgtable.h index 6a99d49abd..0e34d80a9f 100644 --- a/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/pgtable.h +++ b/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/pgtable.h @@ -403,19 +403,6 @@ static inline int pmd_large(pmd_t pte) { /* to find an entry in a page-table-directory. */ #define pud_index(address) (((address) >> PUD_SHIFT) & (PTRS_PER_PUD-1)) #define pud_offset(pgd, address) ((pud_t *) pgd_page(*(pgd)) + pud_index(address)) -static inline pud_t *__pud_offset_k(pud_t *pud, unsigned long address) -{ - return pud + pud_index(address); -} - -/* Find correct pud via the hidden fourth level page level: */ - -/* This accesses the reference page table of the boot cpu. - Other CPUs get synced lazily via the page fault handler. */ -static inline pud_t *pud_offset_k(pgd_t *pgd, unsigned long address) -{ - return pud_offset(pgd_offset_k(address), address); -} /* PMD - Level 2 access */ #define pmd_page_kernel(pmd) ((unsigned long) __va(pmd_val(pmd) & PTE_MASK)) diff --git a/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/processor.h b/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/processor.h index 2ca8c14faf..794efcbcd9 100644 --- a/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/processor.h +++ b/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/processor.h @@ -246,11 +246,13 @@ DECLARE_PER_CPU(struct tss_struct,init_tss); extern struct cpuinfo_x86 boot_cpu_data; +#ifndef CONFIG_X86_NO_TSS /* Save the original ist values for checking stack pointers during debugging */ struct orig_ist { unsigned long ist[7]; }; DECLARE_PER_CPU(struct orig_ist, orig_ist); +#endif #ifdef CONFIG_X86_VSMP #define ARCH_MIN_TASKALIGN (1 << INTERNODE_CACHE_SHIFT) diff --git a/linux-2.6-xen-sparse/include/linux/page-flags.h b/linux-2.6-xen-sparse/include/linux/page-flags.h index 9c67754857..f50f6559c5 100644 --- a/linux-2.6-xen-sparse/include/linux/page-flags.h +++ b/linux-2.6-xen-sparse/include/linux/page-flags.h @@ -252,14 +252,14 @@ #define PageForeign(page) test_bit(PG_foreign, &(page)->flags) #define SetPageForeign(page, dtor) do { \ set_bit(PG_foreign, &(page)->flags); \ - (page)->mapping = (void *)dtor; \ + (page)->index = (long)(dtor); \ } while (0) #define ClearPageForeign(page) do { \ clear_bit(PG_foreign, &(page)->flags); \ - (page)->mapping = NULL; \ + (page)->index = 0; \ } while (0) #define PageForeignDestructor(page) \ - ( (void (*) (struct page *)) (page)->mapping )(page) + ( (void (*) (struct page *)) (page)->index )(page) struct page; /* forward declaration */ diff --git a/linux-2.6-xen-sparse/include/xen/cpu_hotplug.h b/linux-2.6-xen-sparse/include/xen/cpu_hotplug.h index fad14d8393..abf8d528c9 100644 --- a/linux-2.6-xen-sparse/include/xen/cpu_hotplug.h +++ b/linux-2.6-xen-sparse/include/xen/cpu_hotplug.h @@ -1,18 +1,18 @@ #ifndef __XEN_CPU_HOTPLUG_H__ #define __XEN_CPU_HOTPLUG_H__ -#include #include #include -#if defined(CONFIG_HOTPLUG_CPU) - -#if defined(CONFIG_X86) -void cpu_initialize_context(unsigned int cpu); +#if defined(CONFIG_X86) && defined(CONFIG_SMP) +extern cpumask_t cpu_initialized_map; +#define cpu_set_initialized(cpu) cpu_set(cpu, cpu_initialized_map) #else -#define cpu_initialize_context(cpu) ((void)0) +#define cpu_set_initialized(cpu) ((void)0) #endif +#if defined(CONFIG_HOTPLUG_CPU) + int cpu_up_check(unsigned int cpu); void init_xenbus_allowed_cpumask(void); int smp_suspend(void); diff --git a/linux-2.6-xen-sparse/include/xen/driver_util.h b/linux-2.6-xen-sparse/include/xen/driver_util.h index 736adfdd75..766f651d54 100644 --- a/linux-2.6-xen-sparse/include/xen/driver_util.h +++ b/linux-2.6-xen-sparse/include/xen/driver_util.h @@ -2,7 +2,6 @@ #ifndef __ASM_XEN_DRIVER_UTIL_H__ #define __ASM_XEN_DRIVER_UTIL_H__ -#include #include /* Allocate/destroy a 'vmalloc' VM area. */ diff --git a/linux-2.6-xen-sparse/include/xen/evtchn.h b/linux-2.6-xen-sparse/include/xen/evtchn.h index facfb735cb..7c4dd5c8d5 100644 --- a/linux-2.6-xen-sparse/include/xen/evtchn.h +++ b/linux-2.6-xen-sparse/include/xen/evtchn.h @@ -34,7 +34,6 @@ #ifndef __ASM_EVTCHN_H__ #define __ASM_EVTCHN_H__ -#include #include #include #include diff --git a/linux-2.6-xen-sparse/include/xen/gnttab.h b/linux-2.6-xen-sparse/include/xen/gnttab.h index 2f02fe3cd3..93a6e2541e 100644 --- a/linux-2.6-xen-sparse/include/xen/gnttab.h +++ b/linux-2.6-xen-sparse/include/xen/gnttab.h @@ -37,7 +37,6 @@ #ifndef __ASM_GNTTAB_H__ #define __ASM_GNTTAB_H__ -#include #include #include /* maddr_t */ #include diff --git a/linux-2.6-xen-sparse/include/xen/pcifront.h b/linux-2.6-xen-sparse/include/xen/pcifront.h index 1a26e279f5..50d76fe821 100644 --- a/linux-2.6-xen-sparse/include/xen/pcifront.h +++ b/linux-2.6-xen-sparse/include/xen/pcifront.h @@ -6,7 +6,6 @@ #ifndef __XEN_ASM_PCIFRONT_H__ #define __XEN_ASM_PCIFRONT_H__ -#include #include #ifdef __KERNEL__ diff --git a/linux-2.6-xen-sparse/include/xen/xen_proc.h b/linux-2.6-xen-sparse/include/xen/xen_proc.h index f17d61a391..44af17c2ae 100644 --- a/linux-2.6-xen-sparse/include/xen/xen_proc.h +++ b/linux-2.6-xen-sparse/include/xen/xen_proc.h @@ -2,7 +2,6 @@ #ifndef __ASM_XEN_PROC_H__ #define __ASM_XEN_PROC_H__ -#include #include extern struct proc_dir_entry *create_xen_proc_entry( diff --git a/linux-2.6-xen-sparse/mm/Kconfig b/linux-2.6-xen-sparse/mm/Kconfig deleted file mode 100644 index 14492aaa5b..0000000000 --- a/linux-2.6-xen-sparse/mm/Kconfig +++ /dev/null @@ -1,157 +0,0 @@ -config SELECT_MEMORY_MODEL - def_bool y - depends on EXPERIMENTAL || ARCH_SELECT_MEMORY_MODEL - -choice - prompt "Memory model" - depends on SELECT_MEMORY_MODEL - default DISCONTIGMEM_MANUAL if ARCH_DISCONTIGMEM_DEFAULT - default SPARSEMEM_MANUAL if ARCH_SPARSEMEM_DEFAULT - default FLATMEM_MANUAL - -config FLATMEM_MANUAL - bool "Flat Memory" - depends on !(ARCH_DISCONTIGMEM_ENABLE || ARCH_SPARSEMEM_ENABLE) || ARCH_FLATMEM_ENABLE - help - This option allows you to change some of the ways that - Linux manages its memory internally. Most users will - only have one option here: FLATMEM. This is normal - and a correct option. - - Some users of more advanced features like NUMA and - memory hotplug may have different options here. - DISCONTIGMEM is an more mature, better tested system, - but is incompatible with memory hotplug and may suffer - decreased performance over SPARSEMEM. If unsure between - "Sparse Memory" and "Discontiguous Memory", choose - "Discontiguous Memory". - - If unsure, choose this option (Flat Memory) over any other. - -config DISCONTIGMEM_MANUAL - bool "Discontiguous Memory" - depends on ARCH_DISCONTIGMEM_ENABLE - help - This option provides enhanced support for discontiguous - memory systems, over FLATMEM. These systems have holes - in their physical address spaces, and this option provides - more efficient handling of these holes. However, the vast - majority of hardware has quite flat address spaces, and - can have degraded performance from extra overhead that - this option imposes. - - Many NUMA configurations will have this as the only option. - - If unsure, choose "Flat Memory" over this option. - -config SPARSEMEM_MANUAL - bool "Sparse Memory" - depends on ARCH_SPARSEMEM_ENABLE - help - This will be the only option for some systems, including - memory hotplug systems. This is normal. - - For many other systems, this will be an alternative to - "Discontiguous Memory". This option provides some potential - performance benefits, along with decreased code complexity, - but it is newer, and more experimental. - - If unsure, choose "Discontiguous Memory" or "Flat Memory" - over this option. - -endchoice - -config DISCONTIGMEM - def_bool y - depends on (!SELECT_MEMORY_MODEL && ARCH_DISCONTIGMEM_ENABLE) || DISCONTIGMEM_MANUAL - -config SPARSEMEM - def_bool y - depends on SPARSEMEM_MANUAL - -config FLATMEM - def_bool y - depends on (!DISCONTIGMEM && !SPARSEMEM) || FLATMEM_MANUAL - -config FLAT_NODE_MEM_MAP - def_bool y - depends on !SPARSEMEM - -# -# Both the NUMA code and DISCONTIGMEM use arrays of pg_data_t's -# to represent different areas of memory. This variable allows -# those dependencies to exist individually. -# -config NEED_MULTIPLE_NODES - def_bool y - depends on DISCONTIGMEM || NUMA - -config HAVE_MEMORY_PRESENT - def_bool y - depends on ARCH_HAVE_MEMORY_PRESENT || SPARSEMEM - -# -# SPARSEMEM_EXTREME (which is the default) does some bootmem -# allocations when memory_present() is called. If this can not -# be done on your architecture, select this option. However, -# statically allocating the mem_section[] array can potentially -# consume vast quantities of .bss, so be careful. -# -# This option will also potentially produce smaller runtime code -# with gcc 3.4 and later. -# -config SPARSEMEM_STATIC - def_bool n - -# -# Architectecture platforms which require a two level mem_section in SPARSEMEM -# must select this option. This is usually for architecture platforms with -# an extremely sparse physical address space. -# -config SPARSEMEM_EXTREME - def_bool y - depends on SPARSEMEM && !SPARSEMEM_STATIC - -# eventually, we can have this option just 'select SPARSEMEM' -config MEMORY_HOTPLUG - bool "Allow for memory hot-add" - depends on SPARSEMEM && HOTPLUG && !SOFTWARE_SUSPEND && ARCH_ENABLE_MEMORY_HOTPLUG - depends on (IA64 || X86 || PPC64) - -comment "Memory hotplug is currently incompatible with Software Suspend" - depends on SPARSEMEM && HOTPLUG && SOFTWARE_SUSPEND - -# Heavily threaded applications may benefit from splitting the mm-wide -# page_table_lock, so that faults on different parts of the user address -# space can be handled with less contention: split it at this NR_CPUS. -# Default to 4 for wider testing, though 8 might be more appropriate. -# ARM's adjust_pte (unused if VIPT) depends on mm-wide page_table_lock. -# PA-RISC 7xxx's spinlock_t would enlarge struct page from 32 to 44 bytes. -# XEN on x86 architecture uses the mapping field on pagetable pages to store a -# pointer to the destructor. This conflicts with pte_lock_deinit(). -# -config SPLIT_PTLOCK_CPUS - int - default "4096" if ARM && !CPU_CACHE_VIPT - default "4096" if PARISC && !PA20 - default "4096" if X86_XEN || X86_64_XEN - default "4" - -# -# support for page migration -# -config MIGRATION - bool "Page migration" - def_bool y - depends on NUMA - help - Allows the migration of the physical location of pages of processes - while the virtual addresses are not changed. This is useful for - example on NUMA systems to put pages nearer to the processors accessing - the page. - -config RESOURCES_64BIT - bool "64 bit Memory and IO resources (EXPERIMENTAL)" if (!64BIT && EXPERIMENTAL) - default 64BIT - help - This option allows memory and IO resources to be 64 bit. diff --git a/patches/linux-2.6.18/blktap-aio-16_03_06.patch b/patches/linux-2.6.18/blktap-aio-16_03_06.patch index b0f2a81075..bb2aba6928 100644 --- a/patches/linux-2.6.18/blktap-aio-16_03_06.patch +++ b/patches/linux-2.6.18/blktap-aio-16_03_06.patch @@ -106,7 +106,7 @@ diff -pruN ../orig-linux-2.6.18/fs/aio.c ./fs/aio.c + return pollflags; +} + -+static struct file_operations aioq_fops = { ++static const struct file_operations aioq_fops = { + .release = aio_queue_fd_close, + .poll = aio_queue_fd_poll +}; @@ -201,7 +201,7 @@ diff -pruN ../orig-linux-2.6.18/fs/eventpoll.c ./fs/eventpoll.c int maxevents, long timeout); static int eventpollfs_delete_dentry(struct dentry *dentry); -static struct inode *ep_eventpoll_inode(void); -+static struct inode *ep_eventpoll_inode(struct file_operations *fops); ++static struct inode *ep_eventpoll_inode(const struct file_operations *fops); static int eventpollfs_get_sb(struct file_system_type *fs_type, int flags, const char *dev_name, void *data, struct vfsmount *mnt); @@ -221,7 +221,7 @@ diff -pruN ../orig-linux-2.6.18/fs/eventpoll.c ./fs/eventpoll.c -static int ep_getfd(int *efd, struct inode **einode, struct file **efile, - struct eventpoll *ep) +int ep_getfd(int *efd, struct inode **einode, struct file **efile, -+ struct eventpoll *ep, struct file_operations *fops) ++ struct eventpoll *ep, const struct file_operations *fops) { struct qstr this; char name[32]; @@ -248,7 +248,7 @@ diff -pruN ../orig-linux-2.6.18/fs/eventpoll.c ./fs/eventpoll.c -static struct inode *ep_eventpoll_inode(void) -+static struct inode *ep_eventpoll_inode(struct file_operations *fops) ++static struct inode *ep_eventpoll_inode(const struct file_operations *fops) { int error = -ENOMEM; struct inode *inode = new_inode(eventpoll_mnt->mnt_sb); @@ -288,7 +288,7 @@ diff -pruN ../orig-linux-2.6.18/include/linux/eventpoll.h ./include/linux/eventp + */ +struct eventpoll; +int ep_getfd(int *efd, struct inode **einode, struct file **efile, -+ struct eventpoll *ep, struct file_operations *fops); ++ struct eventpoll *ep, const struct file_operations *fops); #else static inline void eventpoll_init_file(struct file *file) {} diff --git a/tools/Makefile b/tools/Makefile index 77ec437689..7cf1bed341 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -24,9 +24,8 @@ SUBDIRS-$(LIBXENAPI_BINDINGS) += libxen # These don't cross-compile ifeq ($(XEN_COMPILE_ARCH),$(XEN_TARGET_ARCH)) -SUBDIRS-y += python -SUBDIRS-y += pygrub -SUBDIRS-y += ptsname +SUBDIRS-$(PYTHON_TOOLS) += python +SUBDIRS-$(PYTHON_TOOLS) += pygrub endif .PHONY: all @@ -42,8 +41,8 @@ install: check $(MAKE) -C $$subdir $@; \ done $(MAKE) ioemuinstall - $(INSTALL_DIR) -p $(DESTDIR)/var/xen/dump - $(INSTALL_DIR) -p $(DESTDIR)/var/log/xen + $(INSTALL_DIR) $(DESTDIR)/var/xen/dump + $(INSTALL_DIR) $(DESTDIR)/var/log/xen .PHONY: clean clean: check_clean diff --git a/tools/blktap/drivers/blktapctrl.c b/tools/blktap/drivers/blktapctrl.c index f2022fcc97..5f78cede2a 100644 --- a/tools/blktap/drivers/blktapctrl.c +++ b/tools/blktap/drivers/blktapctrl.c @@ -303,6 +303,7 @@ static int write_msg(int fd, int msgtype, void *ptr, void *ptr2) msg->type = CTLMSG_PARAMS; msg->len = msglen; msg->drivertype = blkif->drivertype; + msg->readonly = blkif->readonly; gettimeofday(&timeout, NULL); msg->cookie = blkif->cookie; @@ -410,7 +411,6 @@ static int read_msg(int fd, int msgtype, void *ptr) if (select(fd+1, &readfds, (fd_set *) 0, (fd_set *) 0, &timeout) > 0) { ret = read(fd, buf, msglen); - } if (ret > 0) { msg = (msg_hdr_t *)buf; diff --git a/tools/blktap/drivers/block-aio.c b/tools/blktap/drivers/block-aio.c index bbcc4c785a..733407b8c6 100644 --- a/tools/blktap/drivers/block-aio.c +++ b/tools/blktap/drivers/block-aio.c @@ -152,9 +152,9 @@ static inline void init_fds(struct disk_driver *dd) } /* Open the disk file and initialize aio state. */ -int tdaio_open (struct disk_driver *dd, const char *name) +int tdaio_open (struct disk_driver *dd, const char *name, td_flag_t flags) { - int i, fd, ret = 0; + int i, fd, ret = 0, o_flags; struct td_state *s = dd->td_state; struct tdaio_state *prv = (struct tdaio_state *)dd->private; @@ -187,12 +187,15 @@ int tdaio_open (struct disk_driver *dd, const char *name) prv->iocb_free[i] = &prv->iocb_list[i]; /* Open the file */ - fd = open(name, O_RDWR | O_DIRECT | O_LARGEFILE); + o_flags = O_DIRECT | O_LARGEFILE | + ((flags == TD_RDONLY) ? O_RDONLY : O_RDWR); + fd = open(name, o_flags); if ( (fd == -1) && (errno == EINVAL) ) { /* Maybe O_DIRECT isn't supported. */ - fd = open(name, O_RDWR | O_LARGEFILE); + o_flags &= ~O_DIRECT; + fd = open(name, o_flags); if (fd != -1) DPRINTF("WARNING: Accessing image without" "O_DIRECT! (%s)\n", name); @@ -280,6 +283,9 @@ int tdaio_submit(struct disk_driver *dd) int ret; struct tdaio_state *prv = (struct tdaio_state *)dd->private; + if (!prv->iocb_queued) + return 0; + ret = io_submit(prv->aio_ctx, prv->iocb_queued, prv->iocb_queue); /* XXX: TODO: Handle error conditions here. */ @@ -324,12 +330,13 @@ int tdaio_do_callbacks(struct disk_driver *dd, int sid) return rsp; } -int tdaio_has_parent(struct disk_driver *dd) +int tdaio_get_parent_id(struct disk_driver *dd, struct disk_id *id) { - return 0; + return TD_NO_PARENT; } -int tdaio_get_parent(struct disk_driver *dd, struct disk_driver *parent) +int tdaio_validate_parent(struct disk_driver *dd, + struct disk_driver *parent, td_flag_t flags) { return -EINVAL; } @@ -341,8 +348,8 @@ struct tap_disk tapdisk_aio = { .td_queue_read = tdaio_queue_read, .td_queue_write = tdaio_queue_write, .td_submit = tdaio_submit, - .td_has_parent = tdaio_has_parent, - .td_get_parent = tdaio_get_parent, .td_close = tdaio_close, .td_do_callbacks = tdaio_do_callbacks, + .td_get_parent_id = tdaio_get_parent_id, + .td_validate_parent = tdaio_validate_parent }; diff --git a/tools/blktap/drivers/block-qcow.c b/tools/blktap/drivers/block-qcow.c index 2859b08829..36f77e6f05 100644 --- a/tools/blktap/drivers/block-qcow.c +++ b/tools/blktap/drivers/block-qcow.c @@ -209,23 +209,6 @@ static int init_aio_state(struct disk_driver *dd) return -1; } -/* - *Test if block is zero. - * Return: - * 1 for TRUE - * 0 for FALSE - */ -static inline int IS_ZERO(char *buf, int len) -{ - int i; - - for (i = 0; i < len; i++) { - /*if not zero, return false*/ - if (ZERO_TEST(*(buf + i))) return 0; - } - return 1; -} - static uint32_t gen_cksum(char *ptr, int len) { unsigned char *md; @@ -439,7 +422,7 @@ static int qtruncate(int fd, off_t length, int sparse) return -1; if (S_ISBLK(st.st_mode)) return 0; - + sectors = (length + DEFAULT_SECTOR_SIZE - 1)/DEFAULT_SECTOR_SIZE; current = (st.st_size + DEFAULT_SECTOR_SIZE - 1)/DEFAULT_SECTOR_SIZE; rem = st.st_size % DEFAULT_SECTOR_SIZE; @@ -825,9 +808,9 @@ static inline void init_fds(struct disk_driver *dd) } /* Open the disk file and initialize qcow state. */ -int tdqcow_open (struct disk_driver *dd, const char *name) +int tdqcow_open (struct disk_driver *dd, const char *name, td_flag_t flags) { - int fd, len, i, shift, ret, size, l1_table_size; + int fd, len, i, shift, ret, size, l1_table_size, o_flags; struct td_state *bs = dd->td_state; struct tdqcow_state *s = (struct tdqcow_state *)dd->private; char *buf; @@ -838,7 +821,9 @@ int tdqcow_open (struct disk_driver *dd, const char *name) DPRINTF("QCOW: Opening %s\n",name); - fd = open(name, O_RDWR | O_DIRECT | O_LARGEFILE); + o_flags = O_DIRECT | O_LARGEFILE | + ((flags == TD_RDONLY) ? O_RDONLY : O_RDWR); + fd = open(name, o_flags); if (fd < 0) { DPRINTF("Unable to open %s (%d)\n",name,0 - errno); return -1; @@ -1016,7 +1001,8 @@ int tdqcow_queue_read(struct disk_driver *dd, uint64_t sector, * as busy and try again later */ return cb(dd, -EBUSY, sector + n, nb_sectors - n, id, private); - } else rsp += ret; + } else + rsp += ret; } else if (cluster_offset & QCOW_OFLAG_COMPRESSED) { aio_unlock(s, sector); if (decompress_cluster(s, cluster_offset) < 0) { @@ -1403,21 +1389,15 @@ int qcow_compress_cluster(struct tdqcow_state *s, int64_t sector_num, return 0; } -int tdqcow_has_parent(struct disk_driver *dd) -{ - struct tdqcow_state *s = (struct tdqcow_state *)dd->private; - return (s->backing_file_offset ? 1 : 0); -} - -int tdqcow_get_parent(struct disk_driver *cdd, struct disk_driver *pdd) +int tdqcow_get_parent_id(struct disk_driver *dd, struct disk_id *id) { off_t off; char *buf, *filename; - int len, secs, ret = -1; - struct tdqcow_state *child = (struct tdqcow_state *)cdd->private; + int len, secs, err = -EINVAL; + struct tdqcow_state *child = (struct tdqcow_state *)dd->private; if (!child->backing_file_offset) - return -1; + return TD_NO_PARENT; /* read the backing file name */ len = child->backing_file_size; @@ -1432,14 +1412,39 @@ int tdqcow_get_parent(struct disk_driver *cdd, struct disk_driver *pdd) if (read(child->fd, buf, secs << 9) != secs << 9) goto out; - filename = buf + (child->backing_file_offset - off); - filename[len] = '\0'; + filename = buf + (child->backing_file_offset - off); + filename[len] = '\0'; - /*Open backing file*/ - ret = tdqcow_open(pdd, filename); + id->name = strdup(filename); + id->drivertype = DISK_TYPE_QCOW; + err = 0; out: free(buf); - return ret; + return err; +} + +int tdqcow_validate_parent(struct disk_driver *child, + struct disk_driver *parent, td_flag_t flags) +{ + struct stat stats; + uint64_t psize, csize; + struct tdqcow_state *c = (struct tdqcow_state *)child->private; + struct tdqcow_state *p = (struct tdqcow_state *)parent->private; + + if (stat(p->name, &stats)) + return -EINVAL; + if (get_filesize(p->name, &psize, &stats)) + return -EINVAL; + + if (stat(c->name, &stats)) + return -EINVAL; + if (get_filesize(c->name, &csize, &stats)) + return -EINVAL; + + if (csize != psize) + return -EINVAL; + + return 0; } struct tap_disk tapdisk_qcow = { @@ -1449,8 +1454,8 @@ struct tap_disk tapdisk_qcow = { .td_queue_read = tdqcow_queue_read, .td_queue_write = tdqcow_queue_write, .td_submit = tdqcow_submit, - .td_has_parent = tdqcow_has_parent, - .td_get_parent = tdqcow_get_parent, .td_close = tdqcow_close, .td_do_callbacks = tdqcow_do_callbacks, + .td_get_parent_id = tdqcow_get_parent_id, + .td_validate_parent = tdqcow_validate_parent }; diff --git a/tools/blktap/drivers/block-ram.c b/tools/blktap/drivers/block-ram.c index c23dd6b27e..3b4ef7ceb5 100644 --- a/tools/blktap/drivers/block-ram.c +++ b/tools/blktap/drivers/block-ram.c @@ -135,11 +135,11 @@ static inline void init_fds(struct disk_driver *dd) } /* Open the disk file and initialize ram state. */ -int tdram_open (struct disk_driver *dd, const char *name) +int tdram_open (struct disk_driver *dd, const char *name, td_flag_t flags) { char *p; uint64_t size; - int i, fd, ret = 0, count = 0; + int i, fd, ret = 0, count = 0, o_flags; struct td_state *s = dd->td_state; struct tdram_state *prv = (struct tdram_state *)dd->private; @@ -167,12 +167,15 @@ int tdram_open (struct disk_driver *dd, const char *name) } /* Open the file */ - fd = open(name, O_RDWR | O_DIRECT | O_LARGEFILE); + o_flags = O_DIRECT | O_LARGEFILE | + ((flags == TD_RDONLY) ? O_RDONLY : O_RDWR); + fd = open(name, o_flags); if ((fd == -1) && (errno == EINVAL)) { /* Maybe O_DIRECT isn't supported. */ - fd = open(name, O_RDWR | O_LARGEFILE); + o_flags &= ~O_DIRECT; + fd = open(name, o_flags); if (fd != -1) DPRINTF("WARNING: Accessing image without" "O_DIRECT! (%s)\n", name); @@ -275,12 +278,13 @@ int tdram_do_callbacks(struct disk_driver *dd, int sid) return 1; } -int tdram_has_parent(struct disk_driver *dd) +int tdram_get_parent_id(struct disk_driver *dd, struct disk_id *id) { - return 0; + return TD_NO_PARENT; } -int tdram_get_parent(struct disk_driver *dd, struct disk_driver *parent) +int tdram_validate_parent(struct disk_driver *dd, + struct disk_driver *parent, td_flag_t flags) { return -EINVAL; } @@ -292,8 +296,8 @@ struct tap_disk tapdisk_ram = { .td_queue_read = tdram_queue_read, .td_queue_write = tdram_queue_write, .td_submit = tdram_submit, - .td_has_parent = tdram_has_parent, - .td_get_parent = tdram_get_parent, .td_close = tdram_close, .td_do_callbacks = tdram_do_callbacks, + .td_get_parent_id = tdram_get_parent_id, + .td_validate_parent = tdram_validate_parent }; diff --git a/tools/blktap/drivers/block-sync.c b/tools/blktap/drivers/block-sync.c index 367eb70ab9..74f77d6f61 100644 --- a/tools/blktap/drivers/block-sync.c +++ b/tools/blktap/drivers/block-sync.c @@ -118,9 +118,9 @@ static inline void init_fds(struct disk_driver *dd) } /* Open the disk file and initialize aio state. */ -int tdsync_open (struct disk_driver *dd, const char *name) +int tdsync_open (struct disk_driver *dd, const char *name, td_flag_t flags) { - int i, fd, ret = 0; + int i, fd, ret = 0, o_flags; struct td_state *s = dd->td_state; struct tdsync_state *prv = (struct tdsync_state *)dd->private; @@ -130,11 +130,14 @@ int tdsync_open (struct disk_driver *dd, const char *name) return (0 - errno); /* Open the file */ - fd = open(name, O_RDWR | O_DIRECT | O_LARGEFILE); + o_flags = O_DIRECT | O_LARGEFILE | + ((flags == TD_RDONLY) ? O_RDONLY : O_RDWR); + fd = open(name, o_flags); if ( (fd == -1) && (errno == EINVAL) ) { /* Maybe O_DIRECT isn't supported. */ + o_flags &= ~O_DIRECT; fd = open(name, O_RDWR | O_LARGEFILE); if (fd != -1) DPRINTF("WARNING: Accessing image without" "O_DIRECT! (%s)\n", name); @@ -223,12 +226,13 @@ int tdsync_do_callbacks(struct disk_driver *dd, int sid) return 1; } -int tdsync_has_parent(struct disk_driver *dd) +int tdsync_get_parent_id(struct disk_driver *dd, struct disk_id *id) { - return 0; + return TD_NO_PARENT; } -int tdsync_get_parent(struct disk_driver *dd, struct disk_driver *parent) +int tdsync_validate_parent(struct disk_driver *dd, + struct disk_driver *parent, td_flag_t flags) { return -EINVAL; } @@ -240,8 +244,8 @@ struct tap_disk tapdisk_sync = { .td_queue_read = tdsync_queue_read, .td_queue_write = tdsync_queue_write, .td_submit = tdsync_submit, - .td_has_parent = tdsync_has_parent, - .td_get_parent = tdsync_get_parent, .td_close = tdsync_close, .td_do_callbacks = tdsync_do_callbacks, + .td_get_parent_id = tdsync_get_parent_id, + .td_validate_parent = tdsync_validate_parent }; diff --git a/tools/blktap/drivers/block-vmdk.c b/tools/blktap/drivers/block-vmdk.c index 5a6a5ca775..4ab88373ea 100644 --- a/tools/blktap/drivers/block-vmdk.c +++ b/tools/blktap/drivers/block-vmdk.c @@ -119,10 +119,11 @@ static inline void init_fds(struct disk_driver *dd) } /* Open the disk file and initialize aio state. */ -static int tdvmdk_open (struct disk_driver *dd, const char *name) +static int tdvmdk_open (struct disk_driver *dd, + const char *name, td_flag_t flags) { int ret, fd; - int l1_size, i; + int l1_size, i, o_flags; uint32_t magic; struct td_state *s = dd->td_state; struct tdvmdk_state *prv = (struct tdvmdk_state *)dd->private; @@ -133,12 +134,15 @@ static int tdvmdk_open (struct disk_driver *dd, const char *name) return -1; /* Open the file */ - fd = open(name, O_RDWR | O_LARGEFILE); + o_flags = O_DIRECT | O_LARGEFILE | + ((flags == TD_RDONLY) ? O_RDONLY : O_RDWR); + fd = open(name, o_flags); if ( (fd == -1) && (errno == EINVAL) ) { /* Maybe O_DIRECT isn't supported. */ - fd = open(name, O_RDWR | O_LARGEFILE); + o_flags &= ~O_DIRECT; + fd = open(name, o_flags); if (fd != -1) DPRINTF("WARNING: Accessing image without" "O_DIRECT! (%s)\n", name); @@ -394,12 +398,13 @@ static int tdvmdk_do_callbacks(struct disk_driver *dd, int sid) return 1; } -static int tdvmdk_has_parent(struct disk_driver *dd) +static int tdvmdk_get_parent_id(struct disk_driver *dd, struct disk_id *id) { - return 0; + return TD_NO_PARENT; } -static int tdvmdk_get_parent(struct disk_driver *dd, struct disk_driver *parent) +static int tdvmdk_validate_parent(struct disk_driver *dd, + struct disk_driver *parent, td_flag_t flags) { return -EINVAL; } @@ -411,8 +416,8 @@ struct tap_disk tapdisk_vmdk = { .td_queue_read = tdvmdk_queue_read, .td_queue_write = tdvmdk_queue_write, .td_submit = tdvmdk_submit, - .td_has_parent = tdvmdk_has_parent, - .td_get_parent = tdvmdk_get_parent, .td_close = tdvmdk_close, .td_do_callbacks = tdvmdk_do_callbacks, + .td_get_parent_id = tdvmdk_get_parent_id, + .td_validate_parent = tdvmdk_validate_parent }; diff --git a/tools/blktap/drivers/img2qcow.c b/tools/blktap/drivers/img2qcow.c index 7baf28fb02..926cf2742e 100644 --- a/tools/blktap/drivers/img2qcow.c +++ b/tools/blktap/drivers/img2qcow.c @@ -201,7 +201,7 @@ int main(int argc, char *argv[]) dd.private = malloc(dd.drv->private_data_size); /*Open qcow file*/ - if (dd.drv->td_open(&dd, argv[1])!=0) { + if (dd.drv->td_open(&dd, argv[1], 0)!=0) { DFPRINTF("Unable to open Qcow file [%s]\n",argv[1]); exit(-1); } diff --git a/tools/blktap/drivers/qcow2raw.c b/tools/blktap/drivers/qcow2raw.c index 8adf573309..55ae4ad108 100644 --- a/tools/blktap/drivers/qcow2raw.c +++ b/tools/blktap/drivers/qcow2raw.c @@ -169,7 +169,7 @@ int main(int argc, char *argv[]) ddqcow.drv = &tapdisk_qcow; ddqcow.private = malloc(ddqcow.drv->private_data_size); - if (ddqcow.drv->td_open(&ddqcow, argv[2])!=0) { + if (ddqcow.drv->td_open(&ddqcow, argv[2], TD_RDONLY)!=0) { DFPRINTF("Unable to open Qcow file [%s]\n",argv[2]); exit(-1); } else DFPRINTF("QCOW file opened, size %llu\n", @@ -270,7 +270,7 @@ int main(int argc, char *argv[]) ddaio.drv = &tapdisk_aio; ddaio.private = malloc(ddaio.drv->private_data_size); - if (ddaio.drv->td_open(&ddaio, argv[1])!=0) { + if (ddaio.drv->td_open(&ddaio, argv[1], 0)!=0) { DFPRINTF("Unable to open Qcow file [%s]\n", argv[1]); exit(-1); } diff --git a/tools/blktap/drivers/tapdisk.c b/tools/blktap/drivers/tapdisk.c index 6215770d97..954901b2a8 100644 --- a/tools/blktap/drivers/tapdisk.c +++ b/tools/blktap/drivers/tapdisk.c @@ -81,6 +81,15 @@ void daemonize(void) return; } +static void free_driver(struct disk_driver *d) +{ + if (d->name) + free(d->name); + if (d->private) + free(d->private); + free(d); +} + static void unmap_disk(struct td_state *s) { tapdev_info_t *info = s->ring_info; @@ -91,8 +100,7 @@ static void unmap_disk(struct td_state *s) while (dd) { tmp = dd->next; dd->drv->td_close(dd); - free(dd->private); - free(dd); + free_driver(dd); dd = tmp; } @@ -112,7 +120,6 @@ static void unmap_disk(struct td_state *s) free(s); return; - } void sig_handler(int sig) @@ -205,26 +212,6 @@ static struct td_state *state_init(void) return s; } -static struct disk_driver *disk_init(struct td_state *s, struct tap_disk *drv) -{ - struct disk_driver *dd; - - dd = calloc(1, sizeof(struct disk_driver)); - if (!dd) - return NULL; - - dd->private = malloc(drv->private_data_size); - if (!dd->private) { - free(dd); - return NULL; - } - - dd->drv = drv; - dd->td_state = s; - - return dd; -} - static int map_new_dev(struct td_state *s, int minor) { int tap_fd; @@ -280,49 +267,104 @@ static int map_new_dev(struct td_state *s, int minor) return -1; } -static int open_disk(struct td_state *s, struct disk_driver *dd, char *path) +static struct disk_driver *disk_init(struct td_state *s, + struct tap_disk *drv, + char *name, td_flag_t flags) +{ + struct disk_driver *dd; + + dd = calloc(1, sizeof(struct disk_driver)); + if (!dd) + return NULL; + + dd->private = malloc(drv->private_data_size); + if (!dd->private) { + free(dd); + return NULL; + } + + dd->drv = drv; + dd->td_state = s; + dd->name = name; + dd->flags = flags; + + return dd; +} + +static int open_disk(struct td_state *s, + struct tap_disk *drv, char *path, td_flag_t flags) { int err; - struct disk_driver *d = dd; + char *dup; + td_flag_t pflags; + struct disk_id id; + struct disk_driver *d; - err = dd->drv->td_open(dd, path); - if (err) - return err; + dup = strdup(path); + if (!dup) + return -ENOMEM; + + memset(&id, 0, sizeof(struct disk_id)); + s->disks = d = disk_init(s, drv, dup, flags); + if (!d) + return -ENOMEM; + + err = drv->td_open(d, path, flags); + if (err) { + free_driver(d); + s->disks = NULL; + return -ENOMEM; + } + pflags = flags | TD_RDONLY; /* load backing files as necessary */ - while (d->drv->td_has_parent(d)) { + while ((err = d->drv->td_get_parent_id(d, &id)) == 0) { struct disk_driver *new; - new = calloc(1, sizeof(struct disk_driver)); + if (id.drivertype > MAX_DISK_TYPES || + !get_driver(id.drivertype) || !id.name) + goto fail; + + dup = strdup(id.name); + if (!dup) + goto fail; + + new = disk_init(s, get_driver(id.drivertype), dup, pflags); if (!new) goto fail; - new->drv = d->drv; - new->td_state = s; - new->private = malloc(new->drv->private_data_size); - if (!new->private) { - free(new); - goto fail; - } - - err = d->drv->td_get_parent(d, new); + + err = new->drv->td_open(new, new->name, pflags); if (err) goto fail; + err = d->drv->td_validate_parent(d, new, 0); + if (err) { + d->next = new; + goto fail; + } + d = d->next = new; + free(id.name); } - return 0; + s->info |= ((flags & TD_RDONLY) ? VDISK_READONLY : 0); + + if (err >= 0) + return 0; fail: DPRINTF("failed opening disk\n"); - while (dd) { - d = dd->next; - dd->drv->td_close(dd); - free(dd->private); - free(dd); - dd = d; + if (id.name) + free(id.name); + d = s->disks; + while (d) { + struct disk_driver *tmp = d->next; + d->drv->td_close(d); + free_driver(d); + d = tmp; } - return err; + s->disks = NULL; + return -1; } static int read_msg(char *buf) @@ -334,7 +376,6 @@ static int read_msg(char *buf) msg_newdev_t *msg_dev; msg_pid_t *msg_pid; struct tap_disk *drv; - struct disk_driver *dd; int ret = -1; struct td_state *s = NULL; fd_list_entry_t *entry; @@ -369,14 +410,9 @@ static int read_msg(char *buf) if (s == NULL) goto params_done; - s->disks = dd = disk_init(s, drv); - if (!dd) { - free(s); - goto params_done; - } - /*Open file*/ - ret = open_disk(s, dd, path); + ret = open_disk(s, drv, path, + ((msg->readonly) ? TD_RDONLY : 0)); if (ret) goto params_done; @@ -482,7 +518,8 @@ void io_done(struct disk_driver *dd, int sid) if (!run) return; /*We have received signal to close*/ - if (drv->td_do_callbacks(dd, sid) > 0) kick_responses(dd->td_state); + if (sid > MAX_IOFD || drv->td_do_callbacks(dd, sid) > 0) + kick_responses(dd->td_state); return; } @@ -633,6 +670,12 @@ static void get_io_request(struct td_state *s) sector_nr = req->sector_number; } + if ((dd->flags & TD_RDONLY) && + (req->operation == BLKIF_OP_WRITE)) { + blkif->pending_list[idx].status = BLKIF_RSP_ERROR; + goto send_response; + } + for (i = start_seg; i < req->nr_segments; i++) { nsects = req->seg[i].last_sect - req->seg[i].first_sect + 1; @@ -698,10 +741,12 @@ static void get_io_request(struct td_state *s) } sector_nr += nsects; } + send_response: blkif->pending_list[idx].submitting = 0; /* force write_rsp_to_ring for synchronous case */ if (blkif->pending_list[idx].secs_pending == 0) - dd->early += send_responses(dd, 0, 0, 0, idx, (void *)0); + dd->early += send_responses(dd, 0, 0, 0, idx, + (void *)(long)0); } out: @@ -709,7 +754,7 @@ static void get_io_request(struct td_state *s) td_for_each_disk(s, dd) { dd->early += dd->drv->td_submit(dd); if (dd->early > 0) { - io_done(dd, 10); + io_done(dd, MAX_IOFD + 1); dd->early = 0; } } @@ -785,6 +830,20 @@ int main(int argc, char *argv[]) } } + /* completed io from above may have + * queued new requests on chained disks */ + if (progress_made) { + td_for_each_disk(ptr->s, dd) { + dd->early += + dd->drv->td_submit(dd); + if (dd->early > 0) { + io_done(dd, + MAX_IOFD + 1); + dd->early = 0; + } + } + } + if (FD_ISSET(ptr->tap_fd, &readfds) || (info->busy.req && progress_made)) get_io_request(ptr->s); diff --git a/tools/blktap/drivers/tapdisk.h b/tools/blktap/drivers/tapdisk.h index 7b03fa0762..5c68a5e9c8 100644 --- a/tools/blktap/drivers/tapdisk.h +++ b/tools/blktap/drivers/tapdisk.h @@ -42,10 +42,15 @@ * * - The fd used for poll is an otherwise unused pipe, which allows poll to * be safely called without ever returning anything. - * + * * NOTE: tapdisk uses the number of sectors submitted per request as a * ref count. Plugins must use the callback function to communicate the * completion--or error--of every sector submitted to them. + * + * td_get_parent_id returns: + * 0 if parent id successfully retrieved + * TD_NO_PARENT if no parent exists + * -errno on error */ #ifndef TAPDISK_H_ @@ -71,13 +76,25 @@ #define MAX_IOFD 2 #define BLK_NOT_ALLOCATED 99 +#define TD_NO_PARENT 1 + +typedef uint32_t td_flag_t; + +#define TD_RDONLY 1 struct td_state; struct tap_disk; +struct disk_id { + char *name; + int drivertype; +}; + struct disk_driver { int early; + char *name; void *private; + td_flag_t flags; int io_fd[MAX_IOFD]; struct tap_disk *drv; struct td_state *td_state; @@ -105,18 +122,20 @@ typedef int (*td_callback_t)(struct disk_driver *dd, int res, uint64_t sector, struct tap_disk { const char *disk_type; int private_data_size; - int (*td_open) (struct disk_driver *dd, const char *name); - int (*td_queue_read) (struct disk_driver *dd, uint64_t sector, - int nb_sectors, char *buf, td_callback_t cb, - int id, void *prv); - int (*td_queue_write) (struct disk_driver *dd, uint64_t sector, - int nb_sectors, char *buf, td_callback_t cb, - int id, void *prv); - int (*td_submit) (struct disk_driver *dd); - int (*td_has_parent) (struct disk_driver *dd); - int (*td_get_parent) (struct disk_driver *dd, struct disk_driver *p); - int (*td_close) (struct disk_driver *dd); - int (*td_do_callbacks)(struct disk_driver *dd, int sid); + int (*td_open) (struct disk_driver *dd, + const char *name, td_flag_t flags); + int (*td_queue_read) (struct disk_driver *dd, uint64_t sector, + int nb_sectors, char *buf, td_callback_t cb, + int id, void *prv); + int (*td_queue_write) (struct disk_driver *dd, uint64_t sector, + int nb_sectors, char *buf, td_callback_t cb, + int id, void *prv); + int (*td_submit) (struct disk_driver *dd); + int (*td_close) (struct disk_driver *dd); + int (*td_do_callbacks) (struct disk_driver *dd, int sid); + int (*td_get_parent_id) (struct disk_driver *dd, struct disk_id *id); + int (*td_validate_parent)(struct disk_driver *dd, + struct disk_driver *p, td_flag_t flags); }; typedef struct disk_info { diff --git a/tools/blktap/lib/Makefile b/tools/blktap/lib/Makefile index a4880d44cc..d07aef7cce 100644 --- a/tools/blktap/lib/Makefile +++ b/tools/blktap/lib/Makefile @@ -40,8 +40,8 @@ build: libblktap.a libblktap: libblktap.a install: all - $(INSTALL_DIR) -p $(DESTDIR)/usr/$(LIBDIR) - $(INSTALL_DIR) -p $(DESTDIR)/usr/include + $(INSTALL_DIR) $(DESTDIR)/usr/$(LIBDIR) + $(INSTALL_DIR) $(DESTDIR)/usr/include $(INSTALL_PROG) $(LIB) $(DESTDIR)/usr/$(LIBDIR) ln -sf libblktap.so.$(MAJOR).$(MINOR) $(DESTDIR)/usr/$(LIBDIR)/libblktap.so.$(MAJOR) ln -sf libblktap.so.$(MAJOR) $(DESTDIR)/usr/$(LIBDIR)/libblktap.so diff --git a/tools/blktap/lib/blktaplib.h b/tools/blktap/lib/blktaplib.h index 0ba3c04ec8..078a293185 100644 --- a/tools/blktap/lib/blktaplib.h +++ b/tools/blktap/lib/blktaplib.h @@ -173,6 +173,7 @@ typedef struct msg_hdr { uint16_t len; uint16_t drivertype; uint16_t cookie; + uint8_t readonly; } msg_hdr_t; typedef struct msg_newdev { diff --git a/tools/blktap/lib/xenbus.c b/tools/blktap/lib/xenbus.c index d50e492784..fb36e748fe 100644 --- a/tools/blktap/lib/xenbus.c +++ b/tools/blktap/lib/xenbus.c @@ -177,8 +177,11 @@ static void ueblktap_setup(struct xs_handle *h, char *bepath) } /* Check to see if device is to be opened read-only. */ - asprintf(&path, "%s/%s", bepath, "read-only"); - if (xs_exists(h, path)) + deverr = xs_gather(h, bepath, "mode", NULL, &path, NULL); + if (deverr) { + DPRINTF("ERROR: could not find read/write mode\n"); + goto fail; + } else if (path[0] == 'r') be->readonly = 1; if (be->blkif == NULL) { diff --git a/tools/console/Makefile b/tools/console/Makefile index f33204cfaf..7a8e15c0a8 100644 --- a/tools/console/Makefile +++ b/tools/console/Makefile @@ -30,7 +30,7 @@ xenconsole: $(patsubst %.c,%.o,$(wildcard client/*.c)) .PHONY: install install: $(BIN) - $(INSTALL_DIR) -p $(DESTDIR)/$(DAEMON_INSTALL_DIR) + $(INSTALL_DIR) $(DESTDIR)/$(DAEMON_INSTALL_DIR) $(INSTALL_PROG) xenconsoled $(DESTDIR)/$(DAEMON_INSTALL_DIR) - $(INSTALL_DIR) -p $(DESTDIR)/$(CLIENT_INSTALL_DIR) + $(INSTALL_DIR) $(DESTDIR)/$(CLIENT_INSTALL_DIR) $(INSTALL_PROG) xenconsole $(DESTDIR)/$(CLIENT_INSTALL_DIR) diff --git a/tools/examples/init.d/xendomains b/tools/examples/init.d/xendomains index 7aca157bc9..461037e3ac 100644 --- a/tools/examples/init.d/xendomains +++ b/tools/examples/init.d/xendomains @@ -58,18 +58,7 @@ else _SMSG=(done failed failed missed failed skipped unused failed failed) _RC_UNUSED=6 fi - if test -e /lib/lsb/init-functions; then - # LSB - . /lib/lsb/init-functions - echo_rc() - { - if test ${_RC_RV} = 0; then - log_success_msg " [${_SMSG[${_RC_RV}]}] " - else - log_failure_msg " [${_SMSG[${_RC_RV}]}] " - fi - } - elif test -e /etc/init.d/functions; then + if test -e /etc/init.d/functions; then # REDHAT . /etc/init.d/functions echo_rc() @@ -81,6 +70,24 @@ else failure " [${_SMSG[${_RC_RV}]}] " fi } + elif test -e /lib/lsb/init-functions; then + # LSB + . /lib/lsb/init-functions + if alias log_success_msg >/dev/null 2>/dev/null; then + echo_rc() + { + echo " [${_SMSG[${_RC_RV}]}] " + } + else + echo_rc() + { + if test ${_RC_RV} = 0; then + log_success_msg " [${_SMSG[${_RC_RV}]}] " + else + log_failure_msg " [${_SMSG[${_RC_RV}]}] " + fi + } + fi else # emulate it echo_rc() diff --git a/tools/firmware/hvmloader/acpi/dsdt.asl b/tools/firmware/hvmloader/acpi/dsdt.asl index 96f8163c2f..0c843c1833 100644 --- a/tools/firmware/hvmloader/acpi/dsdt.asl +++ b/tools/firmware/hvmloader/acpi/dsdt.asl @@ -123,7 +123,7 @@ DefinitionBlock ("DSDT.aml", "DSDT", 2, "Xen", "HVM", 0) } Name(BUFA, ResourceTemplate() { - IRQ(Level, ActiveLow, Shared) { 5, 6, 10, 11 } + IRQ(Level, ActiveLow, Shared) { 5, 7, 10, 11 } }) Name(BUFB, Buffer() { @@ -643,22 +643,6 @@ DefinitionBlock ("DSDT.aml", "DSDT", 2, "Xen", "HVM", 0) IRQNoFlags () {4} }) } - - Device (LTP1) - { - Name (_HID, EisaId ("PNP0400")) - Name (_UID, 0x02) - Method (_STA, 0, NotSerialized) - { - Return (0x0F) - } - - Name (_CRS, ResourceTemplate() - { - IO (Decode16, 0x0378, 0x0378, 0x08, 0x08) - IRQNoFlags () {7} - }) - } } } } diff --git a/tools/firmware/hvmloader/acpi/dsdt.c b/tools/firmware/hvmloader/acpi/dsdt.c index 36498f6d01..d757ed107c 100644 --- a/tools/firmware/hvmloader/acpi/dsdt.c +++ b/tools/firmware/hvmloader/acpi/dsdt.c @@ -5,15 +5,15 @@ * Copyright (C) 2000 - 2006 Intel Corporation * Supports ACPI Specification Revision 3.0a * - * Compilation of "dsdt.asl" - Fri Feb 16 15:14:37 2007 + * Compilation of "dsdt.asl" - Mon Feb 26 11:09:49 2007 * * C source code output * */ unsigned char AmlCode[] = { - 0x44,0x53,0x44,0x54,0x9F,0x0D,0x00,0x00, /* 00000000 "DSDT...." */ - 0x02,0xEE,0x58,0x65,0x6E,0x00,0x00,0x00, /* 00000008 "..Xen..." */ + 0x44,0x53,0x44,0x54,0x67,0x0D,0x00,0x00, /* 00000000 "DSDTg..." */ + 0x02,0xE0,0x58,0x65,0x6E,0x00,0x00,0x00, /* 00000008 "..Xen..." */ 0x48,0x56,0x4D,0x00,0x00,0x00,0x00,0x00, /* 00000010 "HVM....." */ 0x00,0x00,0x00,0x00,0x49,0x4E,0x54,0x4C, /* 00000018 "....INTL" */ 0x07,0x07,0x06,0x20,0x08,0x50,0x4D,0x42, /* 00000020 "... .PMB" */ @@ -27,7 +27,7 @@ unsigned char AmlCode[] = 0x04,0x0A,0x07,0x0A,0x07,0x00,0x00,0x08, /* 00000060 "........" */ 0x50,0x49,0x43,0x44,0x00,0x14,0x0C,0x5F, /* 00000068 "PICD..._" */ 0x50,0x49,0x43,0x01,0x70,0x68,0x50,0x49, /* 00000070 "PIC.phPI" */ - 0x43,0x44,0x10,0x44,0xD2,0x5F,0x53,0x42, /* 00000078 "CD.D._SB" */ + 0x43,0x44,0x10,0x4C,0xCE,0x5F,0x53,0x42, /* 00000078 "CD.L._SB" */ 0x5F,0x5B,0x82,0x49,0x04,0x4D,0x45,0x4D, /* 00000080 "_[.I.MEM" */ 0x30,0x08,0x5F,0x48,0x49,0x44,0x0C,0x41, /* 00000088 "0._HID.A" */ 0xD0,0x0C,0x02,0x08,0x5F,0x43,0x52,0x53, /* 00000090 "...._CRS" */ @@ -37,7 +37,7 @@ unsigned char AmlCode[] = 0x00,0x00,0xFF,0xFF,0x09,0x00,0x00,0x00, /* 000000B0 "........" */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 000000B8 "........" */ 0x00,0x00,0x00,0x00,0x0A,0x00,0x00,0x00, /* 000000C0 "........" */ - 0x00,0x00,0x79,0x00,0x5B,0x82,0x41,0xCD, /* 000000C8 "..y.[.A." */ + 0x00,0x00,0x79,0x00,0x5B,0x82,0x49,0xC9, /* 000000C8 "..y.[.I." */ 0x50,0x43,0x49,0x30,0x08,0x5F,0x48,0x49, /* 000000D0 "PCI0._HI" */ 0x44,0x0C,0x41,0xD0,0x0A,0x03,0x08,0x5F, /* 000000D8 "D.A...._" */ 0x55,0x49,0x44,0x00,0x08,0x5F,0x41,0x44, /* 000000E0 "UID.._AD" */ @@ -59,7 +59,7 @@ unsigned char AmlCode[] = 0x00,0xF0,0xFF,0xFF,0xFF,0xF4,0x00,0x00, /* 00000160 "........" */ 0x00,0x00,0x00,0x00,0x00,0x05,0x79,0x00, /* 00000168 "......y." */ 0xA4,0x50,0x52,0x54,0x30,0x08,0x42,0x55, /* 00000170 ".PRT0.BU" */ - 0x46,0x41,0x11,0x09,0x0A,0x06,0x23,0x60, /* 00000178 "FA....#`" */ + 0x46,0x41,0x11,0x09,0x0A,0x06,0x23,0xA0, /* 00000178 "FA....#." */ 0x0C,0x18,0x79,0x00,0x08,0x42,0x55,0x46, /* 00000180 "..y..BUF" */ 0x42,0x11,0x09,0x0A,0x06,0x23,0x00,0x00, /* 00000188 "B....#.." */ 0x18,0x79,0x00,0x8B,0x42,0x55,0x46,0x42, /* 00000190 ".y..BUFB" */ @@ -348,7 +348,7 @@ unsigned char AmlCode[] = 0x0C,0x04,0x0C,0xFF,0xFF,0x0F,0x00,0x0A, /* 00000A68 "........" */ 0x02,0x00,0x0A,0x2F,0x12,0x0C,0x04,0x0C, /* 00000A70 ".../...." */ 0xFF,0xFF,0x0F,0x00,0x0A,0x03,0x00,0x0A, /* 00000A78 "........" */ - 0x10,0x5B,0x82,0x4C,0x31,0x49,0x53,0x41, /* 00000A80 ".[.L1ISA" */ + 0x10,0x5B,0x82,0x44,0x2E,0x49,0x53,0x41, /* 00000A80 ".[.D.ISA" */ 0x5F,0x08,0x5F,0x41,0x44,0x52,0x0C,0x00, /* 00000A88 "_._ADR.." */ 0x00,0x01,0x00,0x5B,0x80,0x50,0x49,0x52, /* 00000A90 "...[.PIR" */ 0x51,0x02,0x0A,0x60,0x0A,0x04,0x10,0x2E, /* 00000A98 "Q..`...." */ @@ -440,13 +440,6 @@ unsigned char AmlCode[] = 0x09,0x5F,0x53,0x54,0x41,0x00,0xA4,0x0A, /* 00000D48 "._STA..." */ 0x0F,0x08,0x5F,0x43,0x52,0x53,0x11,0x10, /* 00000D50 ".._CRS.." */ 0x0A,0x0D,0x47,0x01,0xF8,0x03,0xF8,0x03, /* 00000D58 "..G....." */ - 0x01,0x08,0x22,0x10,0x00,0x79,0x00,0x5B, /* 00000D60 ".."..y.[" */ - 0x82,0x36,0x4C,0x54,0x50,0x31,0x08,0x5F, /* 00000D68 ".6LTP1._" */ - 0x48,0x49,0x44,0x0C,0x41,0xD0,0x04,0x00, /* 00000D70 "HID.A..." */ - 0x08,0x5F,0x55,0x49,0x44,0x0A,0x02,0x14, /* 00000D78 "._UID..." */ - 0x09,0x5F,0x53,0x54,0x41,0x00,0xA4,0x0A, /* 00000D80 "._STA..." */ - 0x0F,0x08,0x5F,0x43,0x52,0x53,0x11,0x10, /* 00000D88 ".._CRS.." */ - 0x0A,0x0D,0x47,0x01,0x78,0x03,0x78,0x03, /* 00000D90 "..G.x.x." */ - 0x08,0x08,0x22,0x80,0x00,0x79,0x00, + 0x01,0x08,0x22,0x10,0x00,0x79,0x00, }; int DsdtLen=sizeof(AmlCode); diff --git a/tools/firmware/hvmloader/config.h b/tools/firmware/hvmloader/config.h index 0eb63f581d..fcd2302c3b 100644 --- a/tools/firmware/hvmloader/config.h +++ b/tools/firmware/hvmloader/config.h @@ -9,7 +9,7 @@ #define LAPIC_ID(vcpu_id) ((vcpu_id) * 2) #define PCI_ISA_DEVFN 0x08 /* dev 1, fn 0 */ -#define PCI_ISA_IRQ_MASK 0x0c60U /* ISA IRQs 5,6,10,11 are PCI connected */ +#define PCI_ISA_IRQ_MASK 0x0ca0U /* ISA IRQs 5,7,10,11 are PCI connected */ #define ROMBIOS_SEG 0xF000 #define ROMBIOS_BEGIN 0x000F0000 diff --git a/tools/firmware/rombios/rombios.c b/tools/firmware/rombios/rombios.c index 414a2ec252..7b6ef8062d 100644 --- a/tools/firmware/rombios/rombios.c +++ b/tools/firmware/rombios/rombios.c @@ -890,7 +890,7 @@ static void int14_function(); static void int15_function(); static void int16_function(); static void int17_function(); -static void int19_function(); +static void int18_function(); static void int1a_function(); static void int70_function(); static void int74_function(); @@ -1836,6 +1836,38 @@ keyboard_panic(status) BX_PANIC("Keyboard error:%u\n",status); } +//-------------------------------------------------------------------------- +// machine_reset +//-------------------------------------------------------------------------- + void +machine_reset() +{ + /* Frob the keyboard reset line to reset the processor */ + outb(0x64, 0x60); /* Map the flags register at data port (0x60) */ + outb(0x60, 0x14); /* Set the flags to system|disable */ + outb(0x64, 0xfe); /* Pulse output 0 (system reset) low */ + BX_PANIC("Couldn't reset the machine\n"); +} + +//-------------------------------------------------------------------------- +// clobber_entry_point +// Because PV drivers in HVM guests detach some of the emulated devices, +// it is not safe to do a soft reboot by just dropping to real mode and +// jumping at ffff:0000. -- the boot drives might have disappeared! +// This rather foul function overwrites(!) the BIOS entry point +// to point at machine-reset, which will cause the Xen tools to +// rebuild the whole machine from scratch. +//-------------------------------------------------------------------------- + void +clobber_entry_point() +{ + /* The instruction at the entry point is one byte (0xea) for the + * jump opcode, then two bytes of address, then two of segment. + * Overwrite the address bytes.*/ + write_word(0xffff, 0x0001, machine_reset); +} + + //-------------------------------------------------------------------------- // shutdown_status_panic // called when the shutdown statsu is not implemented, displays the status @@ -7626,7 +7658,7 @@ int17_function(regs, ds, iret_addr) } void -int19_function(seq_nr) +int18_function(seq_nr) Bit16u seq_nr; { Bit16u ebda_seg=read_word(0x0040,0x000E); @@ -7702,8 +7734,8 @@ ASM_START push cx push dx - mov dl, _int19_function.bootdrv + 2[bp] - mov ax, _int19_function.bootseg + 2[bp] + mov dl, _int18_function.bootdrv + 2[bp] + mov ax, _int18_function.bootseg + 2[bp] mov es, ax ;; segment mov bx, #0x0000 ;; offset mov ah, #0x02 ;; function 2, read diskette sector @@ -7714,7 +7746,7 @@ ASM_START int #0x13 ;; read sector jnc int19_load_done mov ax, #0x0001 - mov _int19_function.status + 2[bp], ax + mov _int18_function.status + 2[bp], ax int19_load_done: pop dx @@ -7789,13 +7821,13 @@ ASM_START ;; Build an iret stack frame that will take us to the boot vector. ;; iret pops ip, then cs, then flags, so push them in the opposite order. pushf - mov ax, _int19_function.bootseg + 0[bp] + mov ax, _int18_function.bootseg + 0[bp] push ax - mov ax, _int19_function.bootip + 0[bp] + mov ax, _int18_function.bootip + 0[bp] push ax ;; Set the magic number in ax and the boot drive in dl. mov ax, #0xaa55 - mov dl, _int19_function.bootdrv + 0[bp] + mov dl, _int18_function.bootdrv + 0[bp] ;; Zero some of the other registers. xor bx, bx mov ds, bx @@ -8272,6 +8304,8 @@ int18_handler: ;; Boot Failure recovery: try the next device. mov ss, ax ;; Get the boot sequence number out of the IPL memory + ;; The first time we do this it will have been set to -1 so + ;; we will start from device 0. mov bx, #IPL_SEG mov ds, bx ;; Set segment mov bx, IPL_SEQUENCE_OFFSET ;; BX is now the sequence number @@ -8279,43 +8313,33 @@ int18_handler: ;; Boot Failure recovery: try the next device. mov IPL_SEQUENCE_OFFSET, bx ;; Write it back mov ds, ax ;; and reset the segment to zero. - ;; Carry on in the INT 19h handler, using the new sequence number + ;; Call the C code for the next boot device push bx + call _int18_function - jmp int19_next_boot + ;; Boot failed: invoke the boot recovery function... + int #0x18 ;---------- ;- INT19h - ;---------- int19_relocated: ;; Boot function, relocated - - ;; int19 was beginning to be really complex, so now it - ;; just calls a C function that does the work - - push bp - mov bp, sp - - ;; Reset SS and SP + ;; + ;; *** Warning: INT 19h resets the whole machine *** + ;; + ;; Because PV drivers in HVM guests detach some of the emulated devices, + ;; it is not safe to do a soft reboot by just dropping to real mode and + ;; invoking INT 19h -- the boot drives might have disappeared! + ;; If the user asks for a soft reboot, the only thing we can do is + ;; reset the whole machine. When it comes back up, the normal BIOS + ;; boot sequence will start, which is more or less the required behaviour. + ;; + ;; Reset SP and SS mov ax, #0xfffe mov sp, ax xor ax, ax mov ss, ax - - ;; Start from the first boot device (0, in AX) - mov bx, #IPL_SEG - mov ds, bx ;; Set segment to write to the IPL memory - mov IPL_SEQUENCE_OFFSET, ax ;; Save the sequence number - mov ds, ax ;; and reset the segment. - - push ax - -int19_next_boot: - - ;; Call the C code for the next boot device - call _int19_function - - ;; Boot failed: invoke the boot recovery function - int #0x18 + call _machine_reset ;---------- ;- INT1Ch - @@ -9214,218 +9238,80 @@ pci_routing_table_structure: db 0 ;; pci bus number db 0x08 ;; pci device number (bit 7-3) db 0x61 ;; link value INTA#: pointer into PCI2ISA config space - dw 0x0c60 ;; IRQ bitmap INTA# + dw 0x0ca0 ;; IRQ bitmap INTA# db 0x62 ;; link value INTB# - dw 0x0c60 ;; IRQ bitmap INTB# + dw 0x0ca0 ;; IRQ bitmap INTB# db 0x63 ;; link value INTC# - dw 0x0c60 ;; IRQ bitmap INTC# + dw 0x0ca0 ;; IRQ bitmap INTC# db 0x60 ;; link value INTD# - dw 0x0c60 ;; IRQ bitmap INTD# + dw 0x0ca0 ;; IRQ bitmap INTD# db 0 ;; physical slot (0 = embedded) db 0 ;; reserved ;; second slot entry: 1st PCI slot db 0 ;; pci bus number db 0x10 ;; pci device number (bit 7-3) db 0x62 ;; link value INTA# - dw 0x0c60 ;; IRQ bitmap INTA# + dw 0x0ca0 ;; IRQ bitmap INTA# db 0x63 ;; link value INTB# - dw 0x0c60 ;; IRQ bitmap INTB# + dw 0x0ca0 ;; IRQ bitmap INTB# db 0x60 ;; link value INTC# - dw 0x0c60 ;; IRQ bitmap INTC# + dw 0x0ca0 ;; IRQ bitmap INTC# db 0x61 ;; link value INTD# - dw 0x0c60 ;; IRQ bitmap INTD# + dw 0x0ca0 ;; IRQ bitmap INTD# db 1 ;; physical slot (0 = embedded) db 0 ;; reserved ;; third slot entry: 2nd PCI slot db 0 ;; pci bus number db 0x18 ;; pci device number (bit 7-3) db 0x63 ;; link value INTA# - dw 0x0c60 ;; IRQ bitmap INTA# + dw 0x0ca0 ;; IRQ bitmap INTA# db 0x60 ;; link value INTB# - dw 0x0c60 ;; IRQ bitmap INTB# + dw 0x0ca0 ;; IRQ bitmap INTB# db 0x61 ;; link value INTC# - dw 0x0c60 ;; IRQ bitmap INTC# + dw 0x0ca0 ;; IRQ bitmap INTC# db 0x62 ;; link value INTD# - dw 0x0c60 ;; IRQ bitmap INTD# + dw 0x0ca0 ;; IRQ bitmap INTD# db 2 ;; physical slot (0 = embedded) db 0 ;; reserved ;; 4th slot entry: 3rd PCI slot db 0 ;; pci bus number db 0x20 ;; pci device number (bit 7-3) db 0x60 ;; link value INTA# - dw 0x0c60 ;; IRQ bitmap INTA# + dw 0x0ca0 ;; IRQ bitmap INTA# db 0x61 ;; link value INTB# - dw 0x0c60 ;; IRQ bitmap INTB# + dw 0x0ca0 ;; IRQ bitmap INTB# db 0x62 ;; link value INTC# - dw 0x0c60 ;; IRQ bitmap INTC# + dw 0x0ca0 ;; IRQ bitmap INTC# db 0x63 ;; link value INTD# - dw 0x0c60 ;; IRQ bitmap INTD# + dw 0x0ca0 ;; IRQ bitmap INTD# db 3 ;; physical slot (0 = embedded) db 0 ;; reserved ;; 5th slot entry: 4rd PCI slot db 0 ;; pci bus number db 0x28 ;; pci device number (bit 7-3) db 0x61 ;; link value INTA# - dw 0x0c60 ;; IRQ bitmap INTA# + dw 0x0ca0 ;; IRQ bitmap INTA# db 0x62 ;; link value INTB# - dw 0x0c60 ;; IRQ bitmap INTB# + dw 0x0ca0 ;; IRQ bitmap INTB# db 0x63 ;; link value INTC# - dw 0x0c60 ;; IRQ bitmap INTC# + dw 0x0ca0 ;; IRQ bitmap INTC# db 0x60 ;; link value INTD# - dw 0x0c60 ;; IRQ bitmap INTD# + dw 0x0ca0 ;; IRQ bitmap INTD# db 4 ;; physical slot (0 = embedded) db 0 ;; reserved ;; 6th slot entry: 5rd PCI slot db 0 ;; pci bus number db 0x30 ;; pci device number (bit 7-3) db 0x62 ;; link value INTA# - dw 0x0c60 ;; IRQ bitmap INTA# + dw 0x0ca0 ;; IRQ bitmap INTA# db 0x63 ;; link value INTB# - dw 0x0c60 ;; IRQ bitmap INTB# + dw 0x0ca0 ;; IRQ bitmap INTB# db 0x60 ;; link value INTC# - dw 0x0c60 ;; IRQ bitmap INTC# + dw 0x0ca0 ;; IRQ bitmap INTC# db 0x61 ;; link value INTD# - dw 0x0c60 ;; IRQ bitmap INTD# + dw 0x0ca0 ;; IRQ bitmap INTD# db 5 ;; physical slot (0 = embedded) db 0 ;; reserved - -pci_irq_list: - db 11, 10, 9, 5; - -pcibios_init_sel_reg: - push eax - mov eax, #0x800000 - mov ax, bx - shl eax, #8 - and dl, #0xfc - or al, dl - mov dx, #0x0cf8 - out dx, eax - pop eax - ret - -pcibios_init_set_elcr: - push ax - push cx - mov dx, #0x04d0 - test al, #0x08 - jz is_master_pic - inc dx - and al, #0x07 -is_master_pic: - mov cl, al - mov bl, #0x01 - shl bl, cl - in al, dx - or al, bl - out dx, al - pop cx - pop ax - ret - -pcibios_init: - push ds - push bp - mov ax, #0xf000 - mov ds, ax - mov dx, #0x04d0 ;; reset ELCR1 + ELCR2 - mov al, #0x00 - out dx, al - inc dx - out dx, al - mov si, #pci_routing_table_structure - mov bh, [si+8] - mov bl, [si+9] - mov dl, #0x00 - call pcibios_init_sel_reg - mov dx, #0x0cfc - in eax, dx - cmp eax, [si+12] ;; check irq router - jne pci_init_end - mov dl, [si+34] - call pcibios_init_sel_reg - push bx ;; save irq router bus + devfunc - mov dx, #0x0cfc - mov ax, #0x8080 - out dx, ax ;; reset PIRQ route control - inc dx - inc dx - out dx, ax - mov ax, [si+6] - sub ax, #0x20 - shr ax, #4 - mov cx, ax - add si, #0x20 ;; set pointer to 1st entry - mov bp, sp - mov ax, #pci_irq_list - push ax - xor ax, ax - push ax -pci_init_loop1: - mov bh, [si] - mov bl, [si+1] -pci_init_loop2: - mov dl, #0x00 - call pcibios_init_sel_reg - mov dx, #0x0cfc - in ax, dx - cmp ax, #0xffff - jnz pci_test_int_pin - test bl, #0x07 - jz next_pir_entry - jmp next_pci_func -pci_test_int_pin: - mov dl, #0x3c - call pcibios_init_sel_reg - mov dx, #0x0cfd - in al, dx - and al, #0x07 - jz next_pci_func - dec al ;; determine pirq reg - mov dl, #0x03 - mul al, dl - add al, #0x02 - xor ah, ah - mov bx, ax - mov al, [si+bx] - mov dl, al - mov bx, [bp] - call pcibios_init_sel_reg - mov dx, #0x0cfc - and al, #0x03 - add dl, al - in al, dx - cmp al, #0x80 - jb pirq_found - mov bx, [bp-2] ;; pci irq list pointer - mov al, [bx] - out dx, al - inc bx - mov [bp-2], bx - call pcibios_init_set_elcr -pirq_found: - mov bh, [si] - mov bl, [si+1] - add bl, [bp-3] ;; pci function number - mov dl, #0x3c - call pcibios_init_sel_reg - mov dx, #0x0cfc - out dx, al -next_pci_func: - inc byte ptr[bp-3] - inc bl - test bl, #0x07 - jnz pci_init_loop2 -next_pir_entry: - add si, #0x10 - mov byte ptr[bp-3], #0x00 - loop pci_init_loop1 - mov sp, bp - pop bx -pci_init_end: - pop bp - pop ds - ret #endif // BX_PCIBIOS ; parallel port detection: base address in DX, index in BX, timeout in CL @@ -9747,6 +9633,8 @@ normal_post: call _log_bios_start + call _clobber_entry_point + ;; set all interrupts to default handler mov bx, #0x0000 ;; offset index mov cx, #0x0100 ;; counter (256 interrupts) @@ -9995,8 +9883,10 @@ post_default_ints: call _tcpa_calling_int19h /* specs: 8.2.3 step 1 */ call _tcpa_add_event_separators /* specs: 8.2.3 step 2 */ #endif - int #0x19 - //JMP_EP(0x0064) ; INT 19h location + + ;; Start the boot sequence. See the comments in int19_relocated + ;; for why we use INT 18h instead of INT 19h here. + int #0x18 #if BX_TCGBIOS call _tcpa_returned_int19h /* specs: 8.2.3 step 3/7 */ diff --git a/tools/guest-headers/Makefile b/tools/guest-headers/Makefile index 1c50599a4c..4802e76fad 100644 --- a/tools/guest-headers/Makefile +++ b/tools/guest-headers/Makefile @@ -13,7 +13,7 @@ check: install-Linux: mkdir -p $(DESTDIR)/usr/include/xen/linux - install -m0644 $(linuxsparsetree)/include/xen/public/*.h $(DESTDIR)/usr/include/xen/linux + $(INSTALL_DATA) $(linuxsparsetree)/include/xen/public/*.h $(DESTDIR)/usr/include/xen/linux install-SunOS: diff --git a/tools/ioemu/Makefile b/tools/ioemu/Makefile index beab19c772..6333268289 100644 --- a/tools/ioemu/Makefile +++ b/tools/ioemu/Makefile @@ -65,10 +65,10 @@ common de-ch es fo fr-ca hu ja mk nl-be pt sl tr install-doc: $(DOCS) mkdir -p "$(DESTDIR)$(docdir)" - $(INSTALL) -m 644 qemu-doc.html qemu-tech.html "$(DESTDIR)$(docdir)" + $(INSTALL_DATA) qemu-doc.html qemu-tech.html "$(DESTDIR)$(docdir)" ifndef CONFIG_WIN32 mkdir -p "$(DESTDIR)$(mandir)/man1" - $(INSTALL) qemu.1 qemu-img.1 "$(DESTDIR)$(mandir)/man1" + $(INSTALL_DATA) qemu.1 qemu-img.1 "$(DESTDIR)$(mandir)/man1" endif install: all $(if $(BUILD_DOCS),install-doc) @@ -77,12 +77,12 @@ install: all $(if $(BUILD_DOCS),install-doc) # mkdir -p "$(DESTDIR)$(datadir)" # for x in bios.bin vgabios.bin vgabios-cirrus.bin ppc_rom.bin \ # video.x openbios-sparc32 linux_boot.bin; do \ -# $(INSTALL) -m 644 $(SRC_PATH)/pc-bios/$$x "$(DESTDIR)$(datadir)"; \ +# $(INSTALL_DATA) $(SRC_PATH)/pc-bios/$$x "$(DESTDIR)$(datadir)"; \ # done ifndef CONFIG_WIN32 mkdir -p "$(DESTDIR)$(datadir)/keymaps" for x in $(KEYMAPS); do \ - $(INSTALL) -m 644 $(SRC_PATH)/keymaps/$$x "$(DESTDIR)$(datadir)/keymaps"; \ + $(INSTALL_DATA) $(SRC_PATH)/keymaps/$$x "$(DESTDIR)$(datadir)/keymaps"; \ done endif for d in $(TARGET_DIRS); do \ diff --git a/tools/ioemu/hw/ide.c b/tools/ioemu/hw/ide.c index 3bf2c7d594..108a04c7b2 100644 --- a/tools/ioemu/hw/ide.c +++ b/tools/ioemu/hw/ide.c @@ -434,6 +434,121 @@ static void dma_create_thread(void) } #endif /* DMA_MULTI_THREAD */ +#if defined(__ia64__) +#include + +struct buffered_piopage *buffered_pio_page; + +static inline struct pio_buffer * +piobuf_by_addr(uint32_t addr) +{ + if (addr == 0x1F0) + return &buffered_pio_page->pio[PIO_BUFFER_IDE_PRIMARY]; + if (addr == 0x170) + return &buffered_pio_page->pio[PIO_BUFFER_IDE_SECONDARY]; + return NULL; +} + +static void +buffered_pio_init(void) +{ + struct pio_buffer *p1, *p2; + uint32_t off1, off2; + + if (!buffered_pio_page) + return; + + p1 = &buffered_pio_page->pio[PIO_BUFFER_IDE_PRIMARY]; + p2 = &buffered_pio_page->pio[PIO_BUFFER_IDE_SECONDARY]; + off1 = offsetof(struct buffered_piopage, buffer); + off2 = (off1 + TARGET_PAGE_SIZE)/2; + + p1->buf_size = off2 - off1; + p1->page_offset = off1; + + p2->buf_size = TARGET_PAGE_SIZE - off2; + p2->page_offset = off2; +} + +static inline void +buffered_pio_flush(struct pio_buffer *piobuf) +{ + IDEState *s = piobuf->opaque; + uint32_t pointer = piobuf->pointer; + + if (s != NULL && pointer > 0) { + uint8_t *buf = (uint8_t *)buffered_pio_page + piobuf->page_offset; + memcpy(s->data_ptr, buf, pointer); + s->data_ptr += pointer; + } +} + +static inline void +buffered_pio_reset(IDEState *s) +{ + struct pio_buffer *piobuf; + + if ((unsigned)s->drive_serial - 1 < 2) /* 1,2 */ + piobuf = &buffered_pio_page->pio[PIO_BUFFER_IDE_PRIMARY]; + else if ((unsigned)s->drive_serial - 3 < 2) /* 3,4 */ + piobuf = &buffered_pio_page->pio[PIO_BUFFER_IDE_SECONDARY]; + else + return; + buffered_pio_flush(piobuf); + piobuf->pointer = 0; + piobuf->data_end = 0; + piobuf->opaque = NULL; +} + +static inline void +buffered_pio_write(IDEState *s, uint32_t addr, int size) +{ + struct pio_buffer *piobuf = piobuf_by_addr(addr); + int data_end; + + if (!piobuf) + return; + buffered_pio_flush(piobuf); + data_end = s->data_end - s->data_ptr - size; + if (data_end <= 0) + data_end = 0; + else if (data_end > piobuf->buf_size) + data_end = piobuf->buf_size; + piobuf->pointer = 0; + piobuf->data_end = data_end; + piobuf->opaque = s; +} + +static inline void +buffered_pio_read(IDEState *s, uint32_t addr, int size) +{ + struct pio_buffer *piobuf = piobuf_by_addr(addr); + int data_end; + + if (!piobuf) + return; + s->data_ptr += piobuf->pointer; + data_end = s->data_end - s->data_ptr - size; + if (data_end <= 0) { + data_end = 0; + } else { + uint8_t *buf = (uint8_t *)buffered_pio_page + piobuf->page_offset; + if (data_end > piobuf->buf_size) + data_end = piobuf->buf_size; + memcpy(buf, s->data_ptr + size, data_end); + } + piobuf->pointer = 0; + piobuf->data_end = data_end; + piobuf->opaque = NULL; +} + +#else /* !__ia64__ */ +#define buffered_pio_init() do {} while (0) +#define buffered_pio_reset(I) do {} while (0) +#define buffered_pio_write(I,A,S) do {} while (0) +#define buffered_pio_read(I,A,S) do {} while (0) +#endif + static void ide_dma_start(IDEState *s, IDEDMAFunc *dma_cb); static void padstr(char *str, const char *src, int len) @@ -618,6 +733,7 @@ static void ide_transfer_start(IDEState *s, uint8_t *buf, int size, s->data_ptr = buf; s->data_end = buf + size; s->status |= DRQ_STAT; + buffered_pio_reset(s); } static void ide_transfer_stop(IDEState *s) @@ -626,6 +742,7 @@ static void ide_transfer_stop(IDEState *s) s->data_ptr = s->io_buffer; s->data_end = s->io_buffer; s->status &= ~DRQ_STAT; + buffered_pio_reset(s); } static int64_t ide_get_sector(IDEState *s) @@ -1562,6 +1679,7 @@ static void ide_ioport_write(void *opaque, uint32_t addr, uint32_t val) ide_if[0].select = (val & ~0x10) | 0xa0; ide_if[1].select = (val | 0x10) | 0xa0; /* select drive */ + buffered_pio_reset(ide_if->cur_drive); unit = (val >> 4) & 1; s = ide_if + unit; ide_if->cur_drive = s; @@ -1928,6 +2046,7 @@ static void ide_data_writew(void *opaque, uint32_t addr, uint32_t val) IDEState *s = ((IDEState *)opaque)->cur_drive; uint8_t *p; + buffered_pio_write(s, addr, 2); p = s->data_ptr; *(uint16_t *)p = le16_to_cpu(val); p += 2; @@ -1941,6 +2060,8 @@ static uint32_t ide_data_readw(void *opaque, uint32_t addr) IDEState *s = ((IDEState *)opaque)->cur_drive; uint8_t *p; int ret; + + buffered_pio_read(s, addr, 2); p = s->data_ptr; ret = cpu_to_le16(*(uint16_t *)p); p += 2; @@ -1955,6 +2076,7 @@ static void ide_data_writel(void *opaque, uint32_t addr, uint32_t val) IDEState *s = ((IDEState *)opaque)->cur_drive; uint8_t *p; + buffered_pio_write(s, addr, 4); p = s->data_ptr; *(uint32_t *)p = le32_to_cpu(val); p += 4; @@ -1969,6 +2091,7 @@ static uint32_t ide_data_readl(void *opaque, uint32_t addr) uint8_t *p; int ret; + buffered_pio_read(s, addr, 4); p = s->data_ptr; ret = cpu_to_le32(*(uint32_t *)p); p += 4; @@ -2517,6 +2640,8 @@ void pci_piix3_ide_init(PCIBus *bus, BlockDriverState **hd_table, int devfn) ide_init_ioport(&d->ide_if[0], 0x1f0, 0x3f6); ide_init_ioport(&d->ide_if[2], 0x170, 0x376); + buffered_pio_init(); + register_savevm("ide_pci", 0, 1, generic_pci_save, generic_pci_load, d); #ifdef DMA_MULTI_THREAD diff --git a/tools/ioemu/target-i386-dm/qemu-ifup b/tools/ioemu/target-i386-dm/qemu-ifup index f852b86bf8..1212ae8926 100644 --- a/tools/ioemu/target-i386-dm/qemu-ifup +++ b/tools/ioemu/target-i386-dm/qemu-ifup @@ -3,8 +3,7 @@ #. /etc/rc.d/init.d/functions #ulimit -c unlimited -echo -c 'config qemu network with xen bridge for ' -echo $* +echo 'config qemu network with xen bridge for ' $* ifconfig $1 0.0.0.0 up brctl addif $2 $1 diff --git a/tools/ioemu/vl.c b/tools/ioemu/vl.c index ed29028d41..0b78fa8650 100644 --- a/tools/ioemu/vl.c +++ b/tools/ioemu/vl.c @@ -1565,12 +1565,51 @@ CharDriverState *qemu_chr_open_stdio(void) return chr; } -int store_console_dev(int domid, char *pts) +/* + * Create a store entry for a device (e.g., monitor, serial/parallel lines). + * The entry is /tty and the value is the name + * of the pty associated with the device. + */ +static int store_dev_info(char *devName, int domid, + CharDriverState *cState, char *storeString) { int xc_handle; struct xs_handle *xs; char *path; + char *newpath; + FDCharDriver *s; + char *pts; + /* Check for valid arguments (at least, prevent segfaults). */ + if ((devName == NULL) || (cState == NULL) || (storeString == NULL)) { + fprintf(logfile, "%s - invalid arguments\n", __FUNCTION__); + return EINVAL; + } + + /* + * Only continue if we're talking to a pty + * Actually, the following code works for any CharDriverState using + * FDCharDriver, but we really only care about pty's here + */ + if (strcmp(devName, "pty")) + return 0; + + s = cState->opaque; + if (s == NULL) { + fprintf(logfile, "%s - unable to retrieve fd for '%s'/'%s'\n", + __FUNCTION__, storeString, devName); + return EBADF; + } + + pts = ptsname(s->fd_in); + if (pts == NULL) { + fprintf(logfile, "%s - unable to determine ptsname '%s'/'%s', " + "error %d (%s)\n", + __FUNCTION__, storeString, devName, errno, strerror(errno)); + return errno; + } + + /* We now have everything we need to set the xenstore entry. */ xs = xs_daemon_open(); if (xs == NULL) { fprintf(logfile, "Could not contact XenStore\n"); @@ -1588,14 +1627,19 @@ int store_console_dev(int domid, char *pts) fprintf(logfile, "xs_get_domain_path() error\n"); return -1; } - path = realloc(path, strlen(path) + strlen("/console/tty") + 1); - if (path == NULL) { + newpath = realloc(path, (strlen(path) + strlen(storeString) + + strlen("/tty") + 1)); + if (newpath == NULL) { + free(path); /* realloc errors leave old block */ fprintf(logfile, "realloc error\n"); return -1; } - strcat(path, "/console/tty"); + path = newpath; + + strcat(path, storeString); + strcat(path, "/tty"); if (!xs_write(xs, XBT_NULL, path, pts, strlen(pts))) { - fprintf(logfile, "xs_write for console fail"); + fprintf(logfile, "xs_write for '%s' fail", storeString); return -1; } @@ -1622,7 +1666,6 @@ CharDriverState *qemu_chr_open_pty(void) tcsetattr(slave_fd, TCSAFLUSH, &tty); fprintf(stderr, "char device redirected to %s\n", ptsname(master_fd)); - store_console_dev(domid, ptsname(master_fd)); return qemu_chr_open_fd(master_fd, master_fd); } @@ -3207,6 +3250,14 @@ static int net_tap_init(VLANState *vlan, const char *ifname1, pid = fork(); if (pid >= 0) { if (pid == 0) { + int open_max = sysconf(_SC_OPEN_MAX), i; + for (i = 0; i < open_max; i++) + if (i != STDIN_FILENO && + i != STDOUT_FILENO && + i != STDERR_FILENO && + i != fd) + close(i); + parg = args; *parg++ = (char *)setup_script; *parg++ = ifname; @@ -5768,17 +5819,17 @@ int unset_mm_mapping(int xc_handle, uint32_t domid, int err = 0; xc_dominfo_t info; + xc_domain_getinfo(xc_handle, domid, 1, &info); + if ((info.nr_pages - nr_pages) <= 0) { + fprintf(stderr, "unset_mm_mapping: error nr_pages\n"); + err = -1; + } + err = xc_domain_memory_decrease_reservation(xc_handle, domid, nr_pages, 0, extent_start); if (err) fprintf(stderr, "Failed to decrease physmap\n"); - xc_domain_getinfo(xc_handle, domid, 1, &info); - - if ((info.nr_pages - nr_pages) <= 0) { - fprintf(stderr, "unset_mm_mapping: error nr_pages\n"); - err = -1; - } if (xc_domain_setmaxmem(xc_handle, domid, (info.nr_pages - nr_pages) * PAGE_SIZE/1024) != 0) { @@ -5972,6 +6023,7 @@ int main(int argc, char **argv) xen_pfn_t *page_array; extern void *shared_page; extern void *buffered_io_page; + extern void *buffered_pio_page; char qemu_dm_logfilename[64]; @@ -6044,9 +6096,14 @@ int main(int argc, char **argv) for(i = 1; i < MAX_SERIAL_PORTS; i++) serial_devices[i][0] = '\0'; serial_device_index = 0; - + +#ifndef CONFIG_DM pstrcpy(parallel_devices[0], sizeof(parallel_devices[0]), "vc"); for(i = 1; i < MAX_PARALLEL_PORTS; i++) +#else + /* Xen steals IRQ7 for PCI. Disable LPT1 by default. */ + for(i = 0; i < MAX_PARALLEL_PORTS; i++) +#endif parallel_devices[i][0] = '\0'; parallel_device_index = 0; @@ -6571,6 +6628,10 @@ int main(int argc, char **argv) PROT_READ|PROT_WRITE, BUFFER_IO_PAGE_START >> PAGE_SHIFT); + buffered_pio_page = xc_map_foreign_range(xc_handle, domid, PAGE_SIZE, + PROT_READ|PROT_WRITE, + BUFFER_PIO_PAGE_START >> PAGE_SHIFT); + for (i = 0; i < tmp_nr_pages; i++) page_array[i] = i; @@ -6684,16 +6745,23 @@ int main(int argc, char **argv) fprintf(stderr, "qemu: could not open monitor device '%s'\n", monitor_device); exit(1); } + store_dev_info(monitor_device, domid, monitor_hd, "/monitor"); monitor_init(monitor_hd, !nographic); for(i = 0; i < MAX_SERIAL_PORTS; i++) { if (serial_devices[i][0] != '\0') { + char buf[16]; serial_hds[i] = qemu_chr_open(serial_devices[i]); if (!serial_hds[i]) { fprintf(stderr, "qemu: could not open serial device '%s'\n", serial_devices[i]); exit(1); } + snprintf(buf, sizeof(buf), "/serial/%d", i); + store_dev_info(serial_devices[i], domid, serial_hds[i], buf); + if (i == 0) /* serial 0 is also called the console */ + store_dev_info(serial_devices[i], domid, + serial_hds[i], "/console"); if (!strcmp(serial_devices[i], "vc")) qemu_chr_printf(serial_hds[i], "serial%d console\r\n", i); } @@ -6701,12 +6769,15 @@ int main(int argc, char **argv) for(i = 0; i < MAX_PARALLEL_PORTS; i++) { if (parallel_devices[i][0] != '\0') { + char buf[16]; parallel_hds[i] = qemu_chr_open(parallel_devices[i]); if (!parallel_hds[i]) { fprintf(stderr, "qemu: could not open parallel device '%s'\n", parallel_devices[i]); exit(1); } + snprintf(buf, sizeof(buf), "/parallel/%d", i); + store_dev_info(parallel_devices[i], domid, parallel_hds[i], buf); if (!strcmp(parallel_devices[i], "vc")) qemu_chr_printf(parallel_hds[i], "parallel%d console\r\n", i); } diff --git a/tools/ioemu/vnc.c b/tools/ioemu/vnc.c index 46f3614c21..d06b47a220 100644 --- a/tools/ioemu/vnc.c +++ b/tools/ioemu/vnc.c @@ -1445,7 +1445,7 @@ int vnc_display_init(DisplayState *ds, int display, int find_unused, struct sock int vnc_start_viewer(int port) { - int pid; + int pid, i, open_max; char s[16]; sprintf(s, ":%d", port); @@ -1456,6 +1456,12 @@ int vnc_start_viewer(int port) exit(1); case 0: /* child */ + open_max = sysconf(_SC_OPEN_MAX); + for (i = 0; i < open_max; i++) + if (i != STDIN_FILENO && + i != STDOUT_FILENO && + i != STDERR_FILENO) + close(i); execlp("vncviewer", "vncviewer", s, NULL); fprintf(stderr, "vncviewer execlp failed\n"); exit(1); diff --git a/tools/ioemu/xenstore.c b/tools/ioemu/xenstore.c index 6b1036bcbf..edaf741c3d 100644 --- a/tools/ioemu/xenstore.c +++ b/tools/ioemu/xenstore.c @@ -16,6 +16,9 @@ static struct xs_handle *xsh = NULL; static char *hd_filename[MAX_DISKS]; static QEMUTimer *insert_timer = NULL; +#define UWAIT_MAX (30*1000000) /* thirty seconds */ +#define UWAIT (100000) /* 1/10th second */ + static int pasprintf(char **buf, const char *fmt, ...) { va_list ap; @@ -53,32 +56,20 @@ void xenstore_check_new_media_present(int timeout) qemu_mod_timer(insert_timer, qemu_get_clock(rt_clock) + timeout); } -static int waitForDevice(char *path, char *field, char *desired) +static void waitForDevice(char *fn) { - char *buf = NULL, *stat = NULL; - unsigned int len; - int val = 1; + struct stat sbuf; + int status; + int uwait = UWAIT_MAX; - /* loop until we find a value in xenstore, return - * if it was what we wanted, or not - */ - while (1) { - if (pasprintf(&buf, "%s/%s", path, field) == -1) - goto done; - free(stat); - stat = xs_read(xsh, XBT_NULL, buf, &len); - if (stat == NULL) { - usleep(100000); /* 1/10th second, no path found */ - } else { - val = strcmp(stat, desired); - goto done; - } - } + do { + status = stat(fn, &sbuf); + if (!status) break; + usleep(UWAIT); + uwait -= UWAIT; + } while (uwait > 0); -done: - free(stat); - free(buf); - return val; + return; } void xenstore_parse_domain_config(int domid) @@ -161,11 +152,6 @@ void xenstore_parse_domain_config(int domid) free(fpath); fpath = xs_read(xsh, XBT_NULL, buf, &len); if (fpath != NULL) { - - if (waitForDevice(fpath, "hotplug-status", "connected")) { - continue; - } - if (pasprintf(&buf, "%s/dev", fpath) == -1) continue; params = xs_read(xsh, XBT_NULL, buf , &len); @@ -173,6 +159,11 @@ void xenstore_parse_domain_config(int domid) free(hd_filename[hd_index]); hd_filename[hd_index] = params; params = NULL; /* don't free params on re-use */ + /* + * wait for device, on timeout silently fail because we will + * fail to open below + */ + waitForDevice(hd_filename[hd_index]); } } bs_table[hd_index] = bdrv_new(dev); diff --git a/tools/libxc/Makefile b/tools/libxc/Makefile index 3f8baba795..6dc76ae782 100644 --- a/tools/libxc/Makefile +++ b/tools/libxc/Makefile @@ -6,6 +6,8 @@ MINOR = 0 CTRL_SRCS-y := CTRL_SRCS-y += xc_core.c +CTRL_SRCS-$(CONFIG_X86) += xc_core_x86.c +CTRL_SRCS-$(CONFIG_IA64) += xc_core_ia64.c CTRL_SRCS-y += xc_domain.c CTRL_SRCS-y += xc_evtchn.c CTRL_SRCS-y += xc_misc.c @@ -57,6 +59,9 @@ CFLAGS += -Werror -Wmissing-prototypes CFLAGS += -fno-strict-aliasing CFLAGS += $(INCLUDES) -I. +# Needed for posix_fadvise64() in xc_linux.c +CFLAGS-$(CONFIG_Linux) += -D_GNU_SOURCE + # Define this to make it possible to run valgrind on code linked with these # libraries. #CFLAGS += -DVALGRIND -O0 -ggdb3 diff --git a/tools/libxc/ia64/xc_ia64_hvm_build.c b/tools/libxc/ia64/xc_ia64_hvm_build.c index 270a6f67a2..7beddddf32 100644 --- a/tools/libxc/ia64/xc_ia64_hvm_build.c +++ b/tools/libxc/ia64/xc_ia64_hvm_build.c @@ -569,6 +569,7 @@ setup_guest(int xc_handle, uint32_t dom, unsigned long memsize, xen_pfn_t *pfn_list; shared_iopage_t *sp; void *ioreq_buffer_page; + void *pio_buffer_page; unsigned long dom_memsize = memsize << 20; unsigned long nr_pages = memsize << (20 - PAGE_SHIFT); unsigned long vcpus; @@ -628,9 +629,10 @@ setup_guest(int xc_handle, uint32_t dom, unsigned long memsize, pfn_list[0] = IO_PAGE_START >> PAGE_SHIFT; pfn_list[1] = STORE_PAGE_START >> PAGE_SHIFT; - pfn_list[2] = BUFFER_IO_PAGE_START >> PAGE_SHIFT; + pfn_list[2] = BUFFER_IO_PAGE_START >> PAGE_SHIFT; + pfn_list[3] = BUFFER_PIO_PAGE_START >> PAGE_SHIFT; - rc = xc_domain_memory_populate_physmap(xc_handle, dom, 3, + rc = xc_domain_memory_populate_physmap(xc_handle, dom, 4, 0, 0, &pfn_list[0]); if (rc != 0) { PERROR("Could not allocate IO page or store page or buffer io page.\n"); @@ -684,6 +686,12 @@ setup_guest(int xc_handle, uint32_t dom, unsigned long memsize, pfn_list[2]); memset(ioreq_buffer_page,0,PAGE_SIZE); munmap(ioreq_buffer_page, PAGE_SIZE); + + pio_buffer_page = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE, + PROT_READ | PROT_WRITE, + pfn_list[3]); + memset(pio_buffer_page,0,PAGE_SIZE); + munmap(pio_buffer_page, PAGE_SIZE); free(pfn_list); return 0; diff --git a/tools/libxc/powerpc64/mk_flatdevtree.c b/tools/libxc/powerpc64/mk_flatdevtree.c index 17085aeca1..a6f1de9150 100644 --- a/tools/libxc/powerpc64/mk_flatdevtree.c +++ b/tools/libxc/powerpc64/mk_flatdevtree.c @@ -618,7 +618,7 @@ int make_devtree(struct ft_cxt *root, } /* write a copy of the tree to a file */ - if ((dtb_fd = open(DTB_FILE , O_RDWR)) == -1) { + if ((dtb_fd = creat(DTB_FILE, S_IRUSR | S_IWUSR)) == -1) { PERROR("%s: failed to open file %s", __func__, DTB_FILE); goto error; } diff --git a/tools/libxc/powerpc64/xc_linux_build.c b/tools/libxc/powerpc64/xc_linux_build.c index e6b45ec466..f6416dfefb 100644 --- a/tools/libxc/powerpc64/xc_linux_build.c +++ b/tools/libxc/powerpc64/xc_linux_build.c @@ -33,13 +33,16 @@ #include #include #include -#include #include "flatdevtree_env.h" #include "flatdevtree.h" #include "utils.h" #include "mk_flatdevtree.h" +/* Use 16MB extents to match PowerPC's large page size. */ +#define EXTENT_SHIFT 24 +#define EXTENT_ORDER (EXTENT_SHIFT - PAGE_SHIFT) + #define INITRD_ADDR (24UL << 20) #define DEVTREE_ADDR (16UL << 20) @@ -151,6 +154,50 @@ static int check_memory_config(int rma_log, unsigned int mem_mb) return 1; } +static int alloc_memory(int xc_handle, domid_t domid, ulong nr_pages, + ulong rma_pages) +{ + xen_pfn_t *extent_pfn_arry; + ulong nr_extents; + ulong start_pfn = rma_pages; + int i; + int j; + int rc = 0; + + nr_extents = (nr_pages - rma_pages) >> EXTENT_ORDER; + DPRINTF("allocating memory in %lu chunks of %luMB\n", nr_extents, + 1UL >> (20 - EXTENT_ORDER)); + + /* populate_physmap requires an array of PFNs that determine where the + * guest mapping of the new MFNs. */ + extent_pfn_arry = malloc((1<> extent_order; - DPRINTF("allocating memory in %llu chunks of %luMB\n", nr_extents, - (((1 << extent_order) >> 10) * PAGE_SIZE) >> 10); - - /* now allocate the remaining memory as large-order allocations */ - DPRINTF("increase_reservation(%u, %llu, %u)\n", domid, nr_extents, extent_order); - if (xc_domain_memory_increase_reservation(xc_handle, domid, nr_extents, - extent_order, 0, NULL)) { - rc = -1; - goto out; - } - + /* Get the MFN mapping (for RMA only -- we only load data into the RMA). */ if (get_rma_page_array(xc_handle, domid, &page_array, rma_pages)) { rc = -1; goto out; } + /* Allocate the non-RMA memory. */ + rc = alloc_memory(xc_handle, domid, nr_pages, rma_pages); + if (rc) { + goto out; + } + + /* Load kernel. */ DPRINTF("loading image '%s'\n", image_name); if (load_elf_kernel(xc_handle, domid, image_name, &dsi, page_array)) { rc = -1; @@ -238,6 +272,7 @@ int xc_linux_build(int xc_handle, } kern_addr = 0; + /* Load initrd. */ if (initrd_name && initrd_name[0] != '\0') { DPRINTF("loading initrd '%s'\n", initrd_name); if (load_initrd(xc_handle, domid, page_array, initrd_name, @@ -250,16 +285,15 @@ int xc_linux_build(int xc_handle, /* fetch the current shadow_memory value for this domain */ op = XEN_DOMCTL_SHADOW_OP_GET_ALLOCATION; if (xc_shadow_control(xc_handle, domid, op, NULL, 0, - &shadow_mb, 0, NULL) < 0 ) { + &shadow_mb, 0, NULL) < 0) { rc = -1; goto out; } /* determine shared_info, console, and store paddr */ - shared_info_paddr = (rma_pages << PAGE_SHIFT) - - (RMA_SHARED_INFO * PAGE_SIZE); - console_paddr = (rma_pages << PAGE_SHIFT) - (RMA_CONSOLE * PAGE_SIZE); - store_paddr = (rma_pages << PAGE_SHIFT) - (RMA_STORE * PAGE_SIZE); + shared_info_paddr = (rma_pages << PAGE_SHIFT) - PAGE_SIZE; + console_paddr = shared_info_paddr - PAGE_SIZE; + store_paddr = console_paddr - PAGE_SIZE; /* map paddrs to mfns */ *store_mfn = page_array[(xen_pfn_t)(store_paddr >> PAGE_SHIFT)]; @@ -286,16 +320,17 @@ int xc_linux_build(int xc_handle, devtree_addr, devtree.bph->totalsize)) { DPRINTF("couldn't load flattened device tree.\n"); rc = -1; - goto out; + goto out2; } if (init_boot_vcpu(xc_handle, domid, &dsi, devtree_addr, kern_addr)) { rc = -1; - goto out; + goto out2; } -out: +out2: free_devtree(&devtree); +out: free_page_array(page_array); return rc; } diff --git a/tools/libxc/xc_core.c b/tools/libxc/xc_core.c index 37be5d9cd0..3dcf51e131 100644 --- a/tools/libxc/xc_core.c +++ b/tools/libxc/xc_core.c @@ -1,10 +1,62 @@ +/* + * Elf format, (pfn, gmfn) table, IA64 support. + * Copyright (c) 2007 Isaku Yamahata + * VA Linux Systems Japan K.K. + * + * xen dump-core file format follows ELF format specification. + * Analisys tools shouldn't depends on the order of sections. + * They should follow elf header and check section names. + * + * +--------------------------------------------------------+ + * |ELF header | + * +--------------------------------------------------------+ + * |section headers | + * | null section header | + * | .shstrtab | + * | .note.Xen | + * | .xen_prstatus | + * | .xen_ia64_mmapped_regs if ia64 | + * | .xen_shared_info if present | + * | .xen_p2m or .xen_pfn | + * | .xen_pages | + * +--------------------------------------------------------+ + * |.note.Xen:note section | + * | "Xen" is used as note name, | + * | types are defined in xen/include/public/elfnote.h | + * | and descriptors are defined in xc_core.h. | + * | dumpcore none | + * | dumpcore header | + * | dumpcore xen version | + * | dumpcore format version | + * +--------------------------------------------------------+ + * |.xen_prstatus | + * | vcpu_guest_context_t[nr_vcpus] | + * +--------------------------------------------------------+ + * |.xen_ia64_mmapped_regs if ia64 | + * | mmapped_regs_t[nr_vcpus] | + * +--------------------------------------------------------+ + * |.xen_shared_info if possible | + * +--------------------------------------------------------+ + * |.xen_p2m or .xen_pfn | + * | .xen_p2m: struct xen_dumpcore_p2m[nr_pages] | + * | .xen_pfn: uint64_t[nr_pages] | + * +--------------------------------------------------------+ + * |.xen_pages | + * | page * nr_pages | + * +--------------------------------------------------------+ + * |.shstrtab: section header string table | + * +--------------------------------------------------------+ + * + */ + #include "xg_private.h" +#include "xc_core.h" +#include "xc_dom.h" #include #include /* number of pages to write at a time */ #define DUMP_INCREMENT (4 * 1024) -#define round_pgup(_p) (((_p)+(PAGE_SIZE-1))&PAGE_MASK) static int copy_from_domain_page(int xc_handle, @@ -21,107 +73,712 @@ copy_from_domain_page(int xc_handle, return 0; } +/* string table */ +struct xc_core_strtab { + char *strings; + uint16_t current; + uint16_t max; +}; + +static struct xc_core_strtab* +xc_core_strtab_init(void) +{ + struct xc_core_strtab *strtab; + char *strings; + strtab = malloc(sizeof(*strtab)); + if ( strtab == NULL ) + return NULL; + + strings = malloc(PAGE_SIZE); + if ( strings == NULL ) + { + PERROR("Could not allocate string table init"); + free(strtab); + return NULL; + } + strtab->strings = strings; + strtab->max = PAGE_SIZE; + + /* index 0 represents none */ + strtab->strings[0] = '\0'; + strtab->current = 1; + + return strtab; +} + +static void +xc_core_strtab_free(struct xc_core_strtab *strtab) +{ + free(strtab->strings); + free(strtab); +} + +static uint16_t +xc_core_strtab_get(struct xc_core_strtab *strtab, const char *name) +{ + uint16_t ret = 0; + uint16_t len = strlen(name) + 1; + + if ( strtab->current + len > strtab->max ) + { + char *tmp; + if ( strtab->max * 2 < strtab->max ) + { + PERROR("too long string table"); + errno = ENOMEM; + return ret; + } + + + tmp = realloc(strtab->strings, strtab->max * 2); + if ( tmp == NULL ) + { + PERROR("Could not allocate string table"); + return ret; + } + + strtab->strings = tmp; + strtab->max *= 2; + } + + ret = strtab->current; + strcpy(strtab->strings + strtab->current, name); + strtab->current += len; + return ret; +} + + +/* section headers */ +struct xc_core_section_headers { + uint16_t num; + uint16_t num_max; + + Elf64_Shdr *shdrs; +}; +#define SHDR_INIT 16 +#define SHDR_INC 4 + +static struct xc_core_section_headers* +xc_core_shdr_init(void) +{ + struct xc_core_section_headers *sheaders; + sheaders = malloc(sizeof(*sheaders)); + if ( sheaders == NULL ) + return NULL; + + sheaders->num = 0; + sheaders->num_max = SHDR_INIT; + sheaders->shdrs = malloc(sizeof(sheaders->shdrs[0]) * sheaders->num_max); + if ( sheaders->shdrs == NULL ) + { + free(sheaders); + return NULL; + } + return sheaders; +} + +static void +xc_core_shdr_free(struct xc_core_section_headers *sheaders) +{ + free(sheaders->shdrs); + free(sheaders); +} + +Elf64_Shdr* +xc_core_shdr_get(struct xc_core_section_headers *sheaders) +{ + Elf64_Shdr *shdr; + + if ( sheaders->num == sheaders->num_max ) + { + Elf64_Shdr *shdrs; + if ( sheaders->num_max + SHDR_INC < sheaders->num_max ) + { + errno = E2BIG; + return NULL; + } + sheaders->num_max += SHDR_INC; + shdrs = realloc(sheaders->shdrs, + sizeof(sheaders->shdrs[0]) * sheaders->num_max); + if ( shdrs == NULL ) + return NULL; + sheaders->shdrs = shdrs; + } + + shdr = &sheaders->shdrs[sheaders->num]; + sheaders->num++; + memset(shdr, 0, sizeof(*shdr)); + return shdr; +} + +int +xc_core_shdr_set(Elf64_Shdr *shdr, + struct xc_core_strtab *strtab, + const char *name, uint32_t type, + uint64_t offset, uint64_t size, + uint64_t addralign, uint64_t entsize) +{ + uint64_t name_idx = xc_core_strtab_get(strtab, name); + if ( name_idx == 0 ) + return -1; + + shdr->sh_name = name_idx; + shdr->sh_type = type; + shdr->sh_offset = offset; + shdr->sh_size = size; + shdr->sh_addralign = addralign; + shdr->sh_entsize = entsize; + return 0; +} + +static int +elfnote_fill_xen_version(int xc_handle, + struct xen_dumpcore_elfnote_xen_version_desc + *xen_version) +{ + int rc; + memset(xen_version, 0, sizeof(*xen_version)); + + rc = xc_version(xc_handle, XENVER_version, NULL); + if ( rc < 0 ) + return rc; + xen_version->major_version = rc >> 16; + xen_version->minor_version = rc & ((1 << 16) - 1); + + rc = xc_version(xc_handle, XENVER_extraversion, + &xen_version->extra_version); + if ( rc < 0 ) + return rc; + + rc = xc_version(xc_handle, XENVER_compile_info, + &xen_version->compile_info); + if ( rc < 0 ) + return rc; + + rc = xc_version(xc_handle, + XENVER_capabilities, &xen_version->capabilities); + if ( rc < 0 ) + return rc; + + rc = xc_version(xc_handle, XENVER_changeset, &xen_version->changeset); + if ( rc < 0 ) + return rc; + + rc = xc_version(xc_handle, XENVER_platform_parameters, + &xen_version->platform_parameters); + if ( rc < 0 ) + return rc; + + rc = xc_version(xc_handle, XENVER_pagesize, NULL); + if ( rc < 0 ) + return rc; + xen_version->pagesize = rc; + + return 0; +} + +static int +elfnote_fill_format_version(struct xen_dumpcore_elfnote_format_version_desc + *format_version) +{ + format_version->version = XEN_DUMPCORE_FORMAT_VERSION_CURRENT; + return 0; +} + int xc_domain_dumpcore_via_callback(int xc_handle, uint32_t domid, void *args, dumpcore_rtn_t dump_rtn) { - unsigned long nr_pages; - uint64_t *page_array = NULL; xc_dominfo_t info; - int i, nr_vcpus = 0; + shared_info_t *live_shinfo = NULL; + + int nr_vcpus = 0; char *dump_mem, *dump_mem_start = NULL; - struct xc_core_header header; vcpu_guest_context_t ctxt[MAX_VIRT_CPUS]; + struct xc_core_arch_context arch_ctxt; char dummy[PAGE_SIZE]; int dummy_len; - int sts; + int sts = -1; + unsigned long i; + unsigned long j; + unsigned long nr_pages; + + xc_core_memory_map_t *memory_map = NULL; + unsigned int nr_memory_map; + unsigned int map_idx; + + int auto_translated_physmap; + xen_pfn_t *p2m = NULL; + unsigned long max_pfn = 0; + struct xen_dumpcore_p2m *p2m_array = NULL; + + uint64_t *pfn_array = NULL; + + Elf64_Ehdr ehdr; + uint64_t filesz; + uint64_t offset; + uint64_t fixup; + + struct xc_core_strtab *strtab = NULL; + uint16_t strtab_idx; + struct xc_core_section_headers *sheaders = NULL; + Elf64_Shdr *shdr; + + /* elf notes */ + struct elfnote elfnote; + struct xen_dumpcore_elfnote_none_desc none; + struct xen_dumpcore_elfnote_header_desc header; + struct xen_dumpcore_elfnote_xen_version_desc xen_version; + struct xen_dumpcore_elfnote_format_version_desc format_version; + + xc_core_arch_context_init(&arch_ctxt); if ( (dump_mem_start = malloc(DUMP_INCREMENT*PAGE_SIZE)) == NULL ) { PERROR("Could not allocate dump_mem"); - goto error_out; + goto out; } if ( xc_domain_getinfo(xc_handle, domid, 1, &info) != 1 ) { PERROR("Could not get info for domain"); - goto error_out; + goto out; } + /* Map the shared info frame */ + live_shinfo = xc_map_foreign_range(xc_handle, domid, PAGE_SIZE, + PROT_READ, info.shared_info_frame); + if ( !live_shinfo +#ifdef __ia64__ + && !info.hvm +#endif + ) + { + PERROR("Couldn't map live_shinfo"); + goto out; + } + auto_translated_physmap = xc_core_arch_auto_translated_physmap(&info); if ( domid != info.domid ) { PERROR("Domain %d does not exist", domid); - goto error_out; + goto out; } for ( i = 0; i <= info.max_vcpu_id; i++ ) - if ( xc_vcpu_getcontext(xc_handle, domid, i, &ctxt[nr_vcpus]) == 0) + { + if ( xc_vcpu_getcontext(xc_handle, domid, i, &ctxt[nr_vcpus]) == 0 ) + { + if ( xc_core_arch_context_get(&arch_ctxt, &ctxt[nr_vcpus], + xc_handle, domid) ) + continue; nr_vcpus++; + } + } + if ( nr_vcpus == 0 ) + { + PERROR("No VCPU context could be grabbed"); + goto out; + } + + /* obtain memory map */ + sts = xc_core_arch_memory_map_get(xc_handle, &info, live_shinfo, + &memory_map, &nr_memory_map); + if ( sts != 0 ) + goto out; nr_pages = info.nr_pages; + if ( !auto_translated_physmap ) + { + /* obtain p2m table */ + p2m_array = malloc(nr_pages * sizeof(p2m_array[0])); + if ( p2m_array == NULL ) + { + PERROR("Could not allocate p2m array"); + goto out; + } + sts = xc_core_arch_map_p2m(xc_handle, &info, live_shinfo, + &p2m, &max_pfn); + if ( sts != 0 ) + goto out; + } + else + { + pfn_array = malloc(nr_pages * sizeof(pfn_array[0])); + if ( pfn_array == NULL ) + { + PERROR("Could not allocate pfn array"); + goto out; + } + } + + /* create .xen_p2m or .xen_pfn */ + j = 0; + for ( map_idx = 0; map_idx < nr_memory_map; map_idx++ ) + { + uint64_t pfn_start; + uint64_t pfn_end; + + pfn_start = memory_map[map_idx].addr >> PAGE_SHIFT; + pfn_end = pfn_start + (memory_map[map_idx].size >> PAGE_SHIFT); + for ( i = pfn_start; i < pfn_end; i++ ) + { + if ( !auto_translated_physmap ) + { + if ( p2m[i] == INVALID_P2M_ENTRY ) + continue; + p2m_array[j].pfn = i; + p2m_array[j].gmfn = p2m[i]; + } + else + { + /* try to map page to determin wheter it has underlying page */ + void *vaddr = xc_map_foreign_range(xc_handle, domid, + PAGE_SIZE, PROT_READ, i); + if ( vaddr == NULL ) + continue; + munmap(vaddr, PAGE_SIZE); + pfn_array[j] = i; + } + + j++; + } + } + if ( j != nr_pages ) + { + PERROR("j (%ld) != nr_pages (%ld)", j , nr_pages); + /* When live dump-mode (-L option) is specified, + * guest domain may change its mapping. + */ + nr_pages = j; + } + + memset(&ehdr, 0, sizeof(ehdr)); + ehdr.e_ident[EI_MAG0] = ELFMAG0; + ehdr.e_ident[EI_MAG1] = ELFMAG1; + ehdr.e_ident[EI_MAG2] = ELFMAG2; + ehdr.e_ident[EI_MAG3] = ELFMAG3; + ehdr.e_ident[EI_CLASS] = ELFCLASS64; + ehdr.e_ident[EI_DATA] = ELF_ARCH_DATA; + ehdr.e_ident[EI_VERSION] = EV_CURRENT; + ehdr.e_ident[EI_OSABI] = ELFOSABI_SYSV; + ehdr.e_ident[EI_ABIVERSION] = EV_CURRENT; + + ehdr.e_type = ET_CORE; + ehdr.e_machine = ELF_ARCH_MACHINE; + ehdr.e_version = EV_CURRENT; + ehdr.e_entry = 0; + ehdr.e_phoff = 0; + ehdr.e_shoff = sizeof(ehdr); + ehdr.e_flags = ELF_CORE_EFLAGS; + ehdr.e_ehsize = sizeof(ehdr); + ehdr.e_phentsize = sizeof(Elf64_Phdr); + ehdr.e_phnum = 0; + ehdr.e_shentsize = sizeof(Elf64_Shdr); + /* ehdr.e_shnum and ehdr.e_shstrndx aren't known here yet. fill it later*/ + + /* create section header */ + strtab = xc_core_strtab_init(); + if ( strtab == NULL ) + { + PERROR("Could not allocate string table"); + goto out; + } + sheaders = xc_core_shdr_init(); + if ( sheaders == NULL ) + { + PERROR("Could not allocate section headers"); + goto out; + } + /* null section */ + shdr = xc_core_shdr_get(sheaders); + if ( shdr == NULL ) + { + PERROR("Could not get section header for null section"); + goto out; + } + + /* .shstrtab */ + shdr = xc_core_shdr_get(sheaders); + if ( shdr == NULL ) + { + PERROR("Could not get section header for shstrtab"); + goto out; + } + strtab_idx = shdr - sheaders->shdrs; + /* strtab_shdr.sh_offset, strtab_shdr.sh_size aren't unknown. + * fill it later + */ + sts = xc_core_shdr_set(shdr, strtab, ELF_SHSTRTAB, SHT_STRTAB, 0, 0, 0, 0); + if ( sts != 0 ) + goto out; + + /* elf note section */ + /* here the number of section header is unknown. fix up offset later. */ + offset = sizeof(ehdr); + filesz = + sizeof(struct xen_dumpcore_elfnote_none) + /* none */ + sizeof(struct xen_dumpcore_elfnote_header) + /* core header */ + sizeof(struct xen_dumpcore_elfnote_xen_version) + /* xen version */ + sizeof(struct xen_dumpcore_elfnote_format_version);/* format version */ + shdr = xc_core_shdr_get(sheaders); + if ( shdr == NULL ) + { + PERROR("Could not get section header for note section"); + goto out; + } + sts = xc_core_shdr_set(shdr, strtab, XEN_DUMPCORE_SEC_NOTE, SHT_NOTE, + offset, filesz, 0, 0); + if ( sts != 0 ) + goto out; + offset += filesz; + + /* prstatus */ + shdr = xc_core_shdr_get(sheaders); + if ( shdr == NULL ) + { + PERROR("Could not get section header for .xen_prstatus"); + goto out; + } + filesz = sizeof(ctxt[0]) * nr_vcpus; + sts = xc_core_shdr_set(shdr, strtab, XEN_DUMPCORE_SEC_PRSTATUS, + SHT_PROGBITS, offset, filesz, + __alignof__(ctxt[0]), sizeof(ctxt[0])); + if ( sts != 0 ) + goto out; + offset += filesz; + + /* arch context */ + sts = xc_core_arch_context_get_shdr(&arch_ctxt, sheaders, strtab, + &filesz, offset); + if ( sts != 0) + goto out; + offset += filesz; + + /* shared_info */ + if ( live_shinfo != NULL ) + { + shdr = xc_core_shdr_get(sheaders); + if ( shdr == NULL ) + { + PERROR("Could not get section header for .xen_shared_info"); + goto out; + } + filesz = PAGE_SIZE; + sts = xc_core_shdr_set(shdr, strtab, XEN_DUMPCORE_SEC_SHARED_INFO, + SHT_PROGBITS, offset, filesz, + __alignof__(*live_shinfo), PAGE_SIZE); + if ( sts != 0 ) + goto out; + offset += filesz; + } + + /* p2m/pfn table */ + shdr = xc_core_shdr_get(sheaders); + if ( shdr == NULL ) + { + PERROR("Could not get section header for .xen_{p2m, pfn} table"); + goto out; + } + if ( !auto_translated_physmap ) + { + filesz = nr_pages * sizeof(p2m_array[0]); + sts = xc_core_shdr_set(shdr, strtab, XEN_DUMPCORE_SEC_P2M, + SHT_PROGBITS, + offset, filesz, __alignof__(p2m_array[0]), + sizeof(p2m_array[0])); + if ( sts != 0 ) + goto out; + } + else + { + filesz = nr_pages * sizeof(pfn_array[0]); + sts = xc_core_shdr_set(shdr, strtab, XEN_DUMPCORE_SEC_PFN, + SHT_PROGBITS, + offset, filesz, __alignof__(pfn_array[0]), + sizeof(pfn_array[0])); + if ( sts != 0 ) + goto out; + } + offset += filesz; + + /* pages */ + shdr = xc_core_shdr_get(sheaders); + if ( shdr == NULL ) + { + PERROR("could not get section headers for .xen_pages"); + goto out; + } + + /* + * pages are the last section to allocate section headers + * so that we know the number of section headers here. + */ + fixup = sheaders->num * sizeof(*shdr); + /* zeroth section should have zero offset */ + for ( i = 1; i < sheaders->num; i++ ) + sheaders->shdrs[i].sh_offset += fixup; + offset += fixup; + dummy_len = ROUNDUP(offset, PAGE_SHIFT) - offset; /* padding length */ + offset += dummy_len; + + filesz = nr_pages * PAGE_SIZE; + sts = xc_core_shdr_set(shdr, strtab, XEN_DUMPCORE_SEC_PAGES, SHT_PROGBITS, + offset, filesz, PAGE_SIZE, PAGE_SIZE); + if ( sts != 0 ) + goto out; + offset += filesz; + + /* fixing up section header string table section header */ + filesz = strtab->current; + sheaders->shdrs[strtab_idx].sh_offset = offset; + sheaders->shdrs[strtab_idx].sh_size = filesz; + + /* write out elf header */ + ehdr.e_shnum = sheaders->num; + ehdr.e_shstrndx = strtab_idx; + sts = dump_rtn(args, (char*)&ehdr, sizeof(ehdr)); + if ( sts != 0 ) + goto out; + + /* section headers */ + sts = dump_rtn(args, (char*)sheaders->shdrs, + sheaders->num * sizeof(sheaders->shdrs[0])); + if ( sts != 0 ) + goto out; + + /* elf note section */ + memset(&elfnote, 0, sizeof(elfnote)); + elfnote.namesz = strlen(XEN_DUMPCORE_ELFNOTE_NAME) + 1; + strncpy(elfnote.name, XEN_DUMPCORE_ELFNOTE_NAME, sizeof(elfnote.name)); + + /* elf note section:xen core header */ + elfnote.descsz = sizeof(none); + elfnote.type = XEN_ELFNOTE_DUMPCORE_NONE; + sts = dump_rtn(args, (char*)&elfnote, sizeof(elfnote)); + if ( sts != 0 ) + goto out; + sts = dump_rtn(args, (char*)&none, sizeof(none)); + if ( sts != 0 ) + goto out; + + /* elf note section:xen core header */ + elfnote.descsz = sizeof(header); + elfnote.type = XEN_ELFNOTE_DUMPCORE_HEADER; header.xch_magic = info.hvm ? XC_CORE_MAGIC_HVM : XC_CORE_MAGIC; header.xch_nr_vcpus = nr_vcpus; header.xch_nr_pages = nr_pages; - header.xch_ctxt_offset = sizeof(struct xc_core_header); - header.xch_index_offset = sizeof(struct xc_core_header) + - sizeof(vcpu_guest_context_t)*nr_vcpus; - dummy_len = (sizeof(struct xc_core_header) + - (sizeof(vcpu_guest_context_t) * nr_vcpus) + - (nr_pages * sizeof(*page_array))); - header.xch_pages_offset = round_pgup(dummy_len); - - sts = dump_rtn(args, (char *)&header, sizeof(struct xc_core_header)); + header.xch_page_size = PAGE_SIZE; + sts = dump_rtn(args, (char*)&elfnote, sizeof(elfnote)); if ( sts != 0 ) - goto error_out; + goto out; + sts = dump_rtn(args, (char*)&header, sizeof(header)); + if ( sts != 0 ) + goto out; + /* elf note section: xen version */ + elfnote.descsz = sizeof(xen_version); + elfnote.type = XEN_ELFNOTE_DUMPCORE_XEN_VERSION; + elfnote_fill_xen_version(xc_handle, &xen_version); + sts = dump_rtn(args, (char*)&elfnote, sizeof(elfnote)); + if ( sts != 0 ) + goto out; + sts = dump_rtn(args, (char*)&xen_version, sizeof(xen_version)); + if ( sts != 0 ) + goto out; + + /* elf note section: format version */ + elfnote.descsz = sizeof(format_version); + elfnote.type = XEN_ELFNOTE_DUMPCORE_FORMAT_VERSION; + elfnote_fill_format_version(&format_version); + sts = dump_rtn(args, (char*)&elfnote, sizeof(elfnote)); + if ( sts != 0 ) + goto out; + sts = dump_rtn(args, (char*)&format_version, sizeof(format_version)); + if ( sts != 0 ) + goto out; + + /* prstatus: .xen_prstatus */ sts = dump_rtn(args, (char *)&ctxt, sizeof(ctxt[0]) * nr_vcpus); if ( sts != 0 ) - goto error_out; + goto out; - if ( (page_array = malloc(nr_pages * sizeof(*page_array))) == NULL ) + if ( live_shinfo != NULL ) { - IPRINTF("Could not allocate memory\n"); - goto error_out; + /* shared_info: .xen_shared_info */ + sts = dump_rtn(args, (char*)live_shinfo, PAGE_SIZE); + if ( sts != 0 ) + goto out; } - if ( xc_get_pfn_list(xc_handle, domid, page_array, nr_pages) != nr_pages ) - { - IPRINTF("Could not get the page frame list\n"); - goto error_out; - } - sts = dump_rtn(args, (char *)page_array, nr_pages * sizeof(*page_array)); + + /* arch specific context */ + sts = xc_core_arch_context_dump(&arch_ctxt, args, dump_rtn); if ( sts != 0 ) - goto error_out; + goto out; + + /* p2m/pfn table: .xen_p2m/.xen_pfn */ + if ( !auto_translated_physmap ) + sts = dump_rtn(args, (char *)p2m_array, + sizeof(p2m_array[0]) * nr_pages); + else + sts = dump_rtn(args, (char *)pfn_array, + sizeof(pfn_array[0]) * nr_pages); + if ( sts != 0 ) + goto out; /* Pad the output data to page alignment. */ memset(dummy, 0, PAGE_SIZE); - sts = dump_rtn(args, dummy, header.xch_pages_offset - dummy_len); + sts = dump_rtn(args, dummy, dummy_len); if ( sts != 0 ) - goto error_out; + goto out; + /* dump pages: .xen_pages */ for ( dump_mem = dump_mem_start, i = 0; i < nr_pages; i++ ) { - copy_from_domain_page(xc_handle, domid, page_array[i], dump_mem); + uint64_t gmfn; + if ( !auto_translated_physmap ) + gmfn = p2m_array[i].gmfn; + else + gmfn = pfn_array[i]; + + copy_from_domain_page(xc_handle, domid, gmfn, dump_mem); dump_mem += PAGE_SIZE; if ( ((i + 1) % DUMP_INCREMENT == 0) || ((i + 1) == nr_pages) ) { sts = dump_rtn(args, dump_mem_start, dump_mem - dump_mem_start); if ( sts != 0 ) - goto error_out; + goto out; dump_mem = dump_mem_start; } } - free(dump_mem_start); - free(page_array); - return 0; + /* elf section header string table: .shstrtab */ + sts = dump_rtn(args, strtab->strings, strtab->current); + if ( sts != 0 ) + goto out; - error_out: - free(dump_mem_start); - free(page_array); - return -1; + sts = 0; + +out: + if ( p2m != NULL ) + munmap(p2m, PAGE_SIZE * P2M_FL_ENTRIES); + if ( p2m_array != NULL ) + free(p2m_array); + if ( pfn_array != NULL ) + free(pfn_array); + if ( sheaders != NULL ) + xc_core_shdr_free(sheaders); + if ( strtab != NULL ) + xc_core_strtab_free(strtab); + if ( dump_mem_start != NULL ) + free(dump_mem_start); + if ( live_shinfo != NULL ) + munmap(live_shinfo, PAGE_SIZE); + xc_core_arch_context_free(&arch_ctxt); + + return sts; } /* Callback args for writing to a local dump file. */ @@ -145,6 +802,12 @@ static int local_file_dump(void *args, char *buffer, unsigned int length) } } + if (length >= DUMP_INCREMENT*PAGE_SIZE) { + // Now dumping pages -- make sure we discard clean pages from + // the cache after each write + discard_file_cache(da->fd, 0 /* no flush */); + } + return 0; } @@ -165,6 +828,9 @@ xc_domain_dumpcore(int xc_handle, sts = xc_domain_dumpcore_via_callback( xc_handle, domid, &da, &local_file_dump); + /* flush and discard any remaining portion of the file from cache */ + discard_file_cache(da.fd, 1/* flush first*/); + close(da.fd); return sts; diff --git a/tools/libxc/xc_core.h b/tools/libxc/xc_core.h new file mode 100644 index 0000000000..5b1c9b5a33 --- /dev/null +++ b/tools/libxc/xc_core.h @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2006 Isaku Yamahata + * VA Linux Systems Japan K.K. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef XC_CORE_H +#define XC_CORE_H + +#include "xen/version.h" +#include "xg_private.h" +#include "xen/elfstructs.h" + +/* section names */ +#define XEN_DUMPCORE_SEC_NOTE ".note.Xen" +#define XEN_DUMPCORE_SEC_PRSTATUS ".xen_prstatus" +#define XEN_DUMPCORE_SEC_SHARED_INFO ".xen_shared_info" +#define XEN_DUMPCORE_SEC_P2M ".xen_p2m" +#define XEN_DUMPCORE_SEC_PFN ".xen_pfn" +#define XEN_DUMPCORE_SEC_PAGES ".xen_pages" + +#define XEN_DUMPCORE_SEC_IA64_MAPPED_REGS ".xen_ia64_mapped_regs" + +/* elf note name */ +#define XEN_DUMPCORE_ELFNOTE_NAME "Xen" +/* note numbers are defined in xen/elfnote.h */ + +struct elfnote { + uint32_t namesz; /* Elf_Note note; */ + uint32_t descsz; + uint32_t type; + char name[4]; /* sizeof("Xen") = 4 + * Fotunately this is 64bit aligned so that + * we can use same structore for both 32/64bit + */ +}; + +struct xen_dumpcore_elfnote_none_desc { + /* nothing */ +}; + +struct xen_dumpcore_elfnote_header_desc { + uint64_t xch_magic; + uint64_t xch_nr_vcpus; + uint64_t xch_nr_pages; + uint64_t xch_page_size; +}; + +struct xen_dumpcore_elfnote_xen_version_desc { + uint64_t major_version; + uint64_t minor_version; + xen_extraversion_t extra_version; + xen_compile_info_t compile_info; + xen_capabilities_info_t capabilities; + xen_changeset_info_t changeset; + xen_platform_parameters_t platform_parameters; + uint64_t pagesize; +}; + +#define XEN_DUMPCORE_FORMAT_VERSION(major, minor) \ + ((major) << 32) | ((minor) & 0xffffffff) +#define XEN_DUMPCORE_FORMAT_MAJOR(version) ((major) >> 32) +#define XEN_DUMPCORE_FORMAT_MINOR(version) ((minor) & 0xffffffff) + +#define XEN_DUMPCORE_FORMAT_MAJOR_CURRENT ((uint64_t)0) +#define XEN_DUMPCORE_FORMAT_MINOR_CURRENT ((uint64_t)1) +#define XEN_DUMPCORE_FORMAT_VERSION_CURRENT \ + XEN_DUMPCORE_FORMAT_VERSION(XEN_DUMPCORE_FORMAT_MAJOR_CURRENT, \ + XEN_DUMPCORE_FORMAT_MINOR_CURRENT) + +struct xen_dumpcore_elfnote_format_version_desc { + uint64_t version; +}; + + +struct xen_dumpcore_elfnote_none { + struct elfnote elfnote; + struct xen_dumpcore_elfnote_none_desc none; +}; + +struct xen_dumpcore_elfnote_header { + struct elfnote elfnote; + struct xen_dumpcore_elfnote_header_desc header; +}; + +struct xen_dumpcore_elfnote_xen_version { + struct elfnote elfnote; + struct xen_dumpcore_elfnote_xen_version_desc xen_version; +}; + +struct xen_dumpcore_elfnote_format_version { + struct elfnote elfnote; + struct xen_dumpcore_elfnote_format_version_desc format_version; +}; + +struct xen_dumpcore_p2m { + uint64_t pfn; + uint64_t gmfn; +}; + + +struct xc_core_strtab; +struct xc_core_section_headers; + +Elf64_Shdr* +xc_core_shdr_get(struct xc_core_section_headers *sheaders); +int +xc_core_shdr_set(Elf64_Shdr *shdr, + struct xc_core_strtab *strtab, + const char *name, uint32_t type, + uint64_t offset, uint64_t size, + uint64_t addralign, uint64_t entsize); + +struct xc_core_memory_map { + uint64_t addr; + uint64_t size; +}; +typedef struct xc_core_memory_map xc_core_memory_map_t; +int xc_core_arch_auto_translated_physmap(const xc_dominfo_t *info); +int xc_core_arch_memory_map_get(int xc_handle, xc_dominfo_t *info, + shared_info_t *live_shinfo, + xc_core_memory_map_t **mapp, + unsigned int *nr_entries); +int xc_core_arch_map_p2m(int xc_handle, xc_dominfo_t *info, + shared_info_t *live_shinfo, xen_pfn_t **live_p2m, + unsigned long *pfnp); + + +#if defined (__i386__) || defined (__x86_64__) +# include "xc_core_x86.h" +#elif defined (__ia64__) +# include "xc_core_ia64.h" +#else +# error "unsupported architecture" +#endif + +#ifndef ELF_CORE_EFLAGS +# define ELF_CORE_EFLAGS 0 +#endif + +#endif /* XC_CORE_H */ + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/tools/libxc/xc_core_ia64.c b/tools/libxc/xc_core_ia64.c new file mode 100644 index 0000000000..455d532ee2 --- /dev/null +++ b/tools/libxc/xc_core_ia64.c @@ -0,0 +1,315 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Copyright (c) 2007 Isaku Yamahata + * VA Linux Systems Japan K.K. + * + */ + +#include "xg_private.h" +#include "xc_core.h" +#include "xc_efi.h" +#include "xc_dom.h" + +int +xc_core_arch_auto_translated_physmap(const xc_dominfo_t *info) +{ + /* + * on ia64, both paravirtualize domain and hvm domain are + * auto_translated_physmap mode + */ + return 1; +} + +/* see setup_guest() @ xc_linux_build.c */ +static int +memory_map_get_old_domu(int xc_handle, xc_dominfo_t *info, + shared_info_t *live_shinfo, + xc_core_memory_map_t **mapp, unsigned int *nr_entries) +{ + xc_core_memory_map_t *map = NULL; + + map = malloc(sizeof(*map)); + if ( map == NULL ) + { + PERROR("Could not allocate memory"); + goto out; + } + + map->addr = 0; + map->size = info->max_memkb * 1024; + + *mapp = map; + *nr_entries = 1; + return 0; + +out: + if ( map != NULL ) + free(map); + return -1; +} + +/* see setup_guest() @ xc_ia64_hvm_build.c */ +static int +memory_map_get_old_hvm(int xc_handle, xc_dominfo_t *info, + shared_info_t *live_shinfo, + xc_core_memory_map_t **mapp, unsigned int *nr_entries) +{ + const xc_core_memory_map_t gfw_map[] = { + {IO_PAGE_START, IO_PAGE_SIZE}, + {STORE_PAGE_START, STORE_PAGE_SIZE}, + {BUFFER_IO_PAGE_START, BUFFER_IO_PAGE_SIZE}, + {GFW_START, GFW_SIZE}, + }; + const unsigned int nr_gfw_map = sizeof(gfw_map)/sizeof(gfw_map[0]); + xc_core_memory_map_t *map = NULL; + unsigned int i; + +#define VGA_IO_END (VGA_IO_START + VGA_IO_SIZE) + /* [0, VGA_IO_START) [VGA_IO_END, 3GB), [4GB, ...) + gfw_map */ + map = malloc((3 + nr_gfw_map) * sizeof(*map)); + if ( map == NULL ) + { + PERROR("Could not allocate memory"); + goto out; + } + + for ( i = 0; i < nr_gfw_map; i++ ) + map[i] = gfw_map[i]; + map[i].addr = 0; + map[i].size = info->max_memkb * 1024; + i++; + if ( map[i - 1].size < VGA_IO_END ) + { + map[i - 1].size = VGA_IO_START; + } + else + { + map[i].addr = VGA_IO_END; + map[i].size = map[i - 1].size - VGA_IO_END; + map[i - 1].size = VGA_IO_START; + i++; + if ( map[i - 1].addr + map[i - 1].size > MMIO_START ) + { + map[i].addr = MMIO_START + 1 * MEM_G; + map[i].size = map[i - 1].addr + map[i - 1].size - MMIO_START; + map[i - 1].size = MMIO_START - map[i - 1].addr; + i++; + } + } + *mapp = map; + *nr_entries = i; + return 0; + +out: + if ( map != NULL ) + free(map); + return -1; +} + +static int +memory_map_get_old(int xc_handle, xc_dominfo_t *info, + shared_info_t *live_shinfo, + xc_core_memory_map_t **mapp, unsigned int *nr_entries) +{ + if ( info->hvm ) + return memory_map_get_old_hvm(xc_handle, info, live_shinfo, + mapp, nr_entries); + if ( live_shinfo == NULL ) + return -1; + return memory_map_get_old_domu(xc_handle, info, live_shinfo, + mapp, nr_entries); +} + +int +xc_core_arch_memory_map_get(int xc_handle, xc_dominfo_t *info, + shared_info_t *live_shinfo, + xc_core_memory_map_t **mapp, + unsigned int *nr_entries) +{ +#ifdef notyet + int ret = -1; + xen_ia64_memmap_info_t *memmap_info; + xc_core_memory_map_t *map; + char *start; + char *end; + char *p; + efi_memory_desc_t *md; + + if ( live_shinfo == NULL || live_shinfo->arch.memmap_info_pfn == 0 ) + goto old; + + memmap_info = xc_map_foreign_range(xc_handle, info->domid, + PAGE_SIZE, PROT_READ, + live_shinfo->arch.memmap_info_pfn); + if ( memmap_info == NULL ) + { + PERROR("Could not map memmap info."); + return -1; + } + if ( memmap_info->efi_memdesc_size != sizeof(*md) || + (memmap_info->efi_memmap_size / memmap_info->efi_memdesc_size) == 0 || + memmap_info->efi_memmap_size > PAGE_SIZE - sizeof(memmap_info) || + memmap_info->efi_memdesc_version != EFI_MEMORY_DESCRIPTOR_VERSION ) + { + PERROR("unknown memmap header. defaulting to compat mode."); + munmap(memmap_info, PAGE_SIZE); + goto old; + } + + *nr_entries = memmap_info->efi_memmap_size / memmap_info->efi_memdesc_size; + map = malloc(*nr_entries * sizeof(*md)); + if ( map == NULL ) + { + PERROR("Could not allocate memory for memmap."); + goto out; + } + *mapp = map; + + *nr_entries = 0; + start = (char*)&memmap_info->memdesc; + end = start + memmap_info->efi_memmap_size; + for ( p = start; p < end; p += memmap_info->efi_memdesc_size ) + { + md = (efi_memory_desc_t*)p; + if ( md->type != EFI_CONVENTIONAL_MEMORY || + md->attribute != EFI_MEMORY_WB || + md->num_pages == 0 ) + continue; + + map[*nr_entries].addr = md->phys_addr; + map[*nr_entries].size = md->num_pages << EFI_PAGE_SHIFT; + (*nr_entries)++; + } + ret = 0; +out: + munmap(memmap_info, PAGE_SIZE); + return ret; + +old: +#endif + return memory_map_get_old(xc_handle, info, live_shinfo, mapp, nr_entries); +} + +int +xc_core_arch_map_p2m(int xc_handle, xc_dominfo_t *info, + shared_info_t *live_shinfo, xen_pfn_t **live_p2m, + unsigned long *pfnp) +{ + /* + * on ia64, both paravirtualize domain and hvm domain are + * auto_translated_physmap mode + */ + errno = ENOSYS; + return -1; +} + +void +xc_core_arch_context_init(struct xc_core_arch_context* arch_ctxt) +{ + int i; + + arch_ctxt->mapped_regs_size = + (XMAPPEDREGS_SIZE < PAGE_SIZE) ? PAGE_SIZE: XMAPPEDREGS_SIZE; + arch_ctxt->nr_vcpus = 0; + for ( i = 0; i < MAX_VIRT_CPUS; i++ ) + arch_ctxt->mapped_regs[i] = NULL; +} + +void +xc_core_arch_context_free(struct xc_core_arch_context* arch_ctxt) +{ + int i; + for ( i = 0; i < arch_ctxt->nr_vcpus; i++ ) + if ( arch_ctxt->mapped_regs[i] != NULL ) + munmap(arch_ctxt->mapped_regs[i], arch_ctxt->mapped_regs_size); +} + +int +xc_core_arch_context_get(struct xc_core_arch_context* arch_ctxt, + vcpu_guest_context_t* ctxt, + int xc_handle, uint32_t domid) +{ + mapped_regs_t* mapped_regs; + if ( ctxt->privregs_pfn == INVALID_P2M_ENTRY ) + { + PERROR("Could not get mmapped privregs gmfn"); + errno = ENOENT; + return -1; + } + mapped_regs = xc_map_foreign_range(xc_handle, domid, + arch_ctxt->mapped_regs_size, + PROT_READ, ctxt->privregs_pfn); + if ( mapped_regs == NULL ) + { + PERROR("Could not map mapped privregs"); + return -1; + } + arch_ctxt->mapped_regs[arch_ctxt->nr_vcpus] = mapped_regs; + arch_ctxt->nr_vcpus++; + return 0; +} + +int +xc_core_arch_context_get_shdr(struct xc_core_arch_context *arch_ctxt, + struct xc_core_section_headers *sheaders, + struct xc_core_strtab *strtab, + uint64_t *filesz, uint64_t offset) +{ + int sts = -1; + Elf64_Shdr *shdr; + + /* mmapped priv regs */ + shdr = xc_core_shdr_get(sheaders); + if ( shdr == NULL ) + { + PERROR("Could not get section header for .xen_ia64_mapped_regs"); + return sts; + } + *filesz = arch_ctxt->mapped_regs_size * arch_ctxt->nr_vcpus; + sts = xc_core_shdr_set(shdr, strtab, XEN_DUMPCORE_SEC_IA64_MAPPED_REGS, + SHT_PROGBITS, offset, *filesz, + __alignof__(*arch_ctxt->mapped_regs[0]), + arch_ctxt->mapped_regs_size); + return sts; +} + +int +xc_core_arch_context_dump(struct xc_core_arch_context* arch_ctxt, + void* args, dumpcore_rtn_t dump_rtn) +{ + int sts = 0; + int i; + + /* ia64 mapped_regs: .xen_ia64_mapped_regs */ + for ( i = 0; i < arch_ctxt->nr_vcpus; i++ ) + { + sts = dump_rtn(args, (char*)arch_ctxt->mapped_regs[i], + arch_ctxt->mapped_regs_size); + if ( sts != 0 ) + break; + } + return sts; +} + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/tools/libxc/xc_core_ia64.h b/tools/libxc/xc_core_ia64.h new file mode 100644 index 0000000000..6357dfa20e --- /dev/null +++ b/tools/libxc/xc_core_ia64.h @@ -0,0 +1,60 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Copyright (c) 2007 Isaku Yamahata + * VA Linux Systems Japan K.K. + * + */ + +#ifndef XC_CORE_IA64_H +#define XC_CORE_IA64_H + +#define ELF_ARCH_DATA ELFDATA2LSB +#define ELF_ARCH_MACHINE EM_IA_64 + +struct xc_core_arch_context { + size_t mapped_regs_size; + int nr_vcpus; + mapped_regs_t* mapped_regs[MAX_VIRT_CPUS]; +}; + +void +xc_core_arch_context_init(struct xc_core_arch_context* arch_ctxt); +void +xc_core_arch_context_free(struct xc_core_arch_context* arch_ctxt); +int +xc_core_arch_context_get(struct xc_core_arch_context* arch_ctxt, + vcpu_guest_context_t* ctxt, + int xc_handle, uint32_t domid); +int +xc_core_arch_context_get_shdr(struct xc_core_arch_context* arch_ctxt, + struct xc_core_section_headers *sheaders, + struct xc_core_strtab *strtab, + uint64_t *filesz, uint64_t offset); +int +xc_core_arch_context_dump(struct xc_core_arch_context* arch_ctxt, + void* args, dumpcore_rtn_t dump_rtn); + +#endif /* XC_CORE_IA64_H */ + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/tools/libxc/xc_core_x86.c b/tools/libxc/xc_core_x86.c new file mode 100644 index 0000000000..6ea775aef6 --- /dev/null +++ b/tools/libxc/xc_core_x86.c @@ -0,0 +1,136 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Copyright (c) 2007 Isaku Yamahata + * VA Linux Systems Japan K.K. + * + */ + +#include "xg_private.h" +#include "xc_core.h" + +int +xc_core_arch_auto_translated_physmap(const xc_dominfo_t *info) +{ + if ( info->hvm ) + return 1; + return 0; +} + +int +xc_core_arch_memory_map_get(int xc_handle, xc_dominfo_t *info, + shared_info_t *live_shinfo, + xc_core_memory_map_t **mapp, + unsigned int *nr_entries) +{ + unsigned long max_pfn = live_shinfo->arch.max_pfn; + xc_core_memory_map_t *map = NULL; + + map = malloc(sizeof(*map)); + if ( !map ) + { + PERROR("Could not allocate memory"); + goto out; + } + + map->addr = 0; + map->size = max_pfn << PAGE_SHIFT; + + *mapp = map; + *nr_entries = 1; + return 0; + +out: + if ( map ) + free(map); + return -1; +} + +int +xc_core_arch_map_p2m(int xc_handle, xc_dominfo_t *info, + shared_info_t *live_shinfo, xen_pfn_t **live_p2m, + unsigned long *pfnp) +{ + /* Double and single indirect references to the live P2M table */ + xen_pfn_t *live_p2m_frame_list_list = NULL; + xen_pfn_t *live_p2m_frame_list = NULL; + uint32_t dom = info->domid; + unsigned long max_pfn = live_shinfo->arch.max_pfn; + int ret = -1; + int err; + + if ( max_pfn < info->nr_pages ) + { + ERROR("max_pfn < nr_pages -1 (%lx < %lx", max_pfn, info->nr_pages - 1); + goto out; + } + + live_p2m_frame_list_list = + xc_map_foreign_range(xc_handle, dom, PAGE_SIZE, PROT_READ, + live_shinfo->arch.pfn_to_mfn_frame_list_list); + + if ( !live_p2m_frame_list_list ) + { + PERROR("Couldn't map p2m_frame_list_list (errno %d)", errno); + goto out; + } + + live_p2m_frame_list = + xc_map_foreign_batch(xc_handle, dom, PROT_READ, + live_p2m_frame_list_list, + P2M_FLL_ENTRIES); + + if ( !live_p2m_frame_list ) + { + PERROR("Couldn't map p2m_frame_list"); + goto out; + } + + *live_p2m = xc_map_foreign_batch(xc_handle, dom, PROT_READ, + live_p2m_frame_list, + P2M_FL_ENTRIES); + + if ( !*live_p2m ) + { + PERROR("Couldn't map p2m table"); + goto out; + } + + *pfnp = max_pfn; + + ret = 0; + +out: + err = errno; + + if ( live_p2m_frame_list_list ) + munmap(live_p2m_frame_list_list, PAGE_SIZE); + + if ( live_p2m_frame_list ) + munmap(live_p2m_frame_list, P2M_FLL_ENTRIES * PAGE_SIZE); + + errno = err; + return ret; +} + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/tools/libxc/xc_core_x86.h b/tools/libxc/xc_core_x86.h new file mode 100644 index 0000000000..53ca48493d --- /dev/null +++ b/tools/libxc/xc_core_x86.h @@ -0,0 +1,64 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Copyright (c) 2007 Isaku Yamahata + * VA Linux Systems Japan K.K. + * + */ + +#ifndef XC_CORE_X86_H +#define XC_CORE_X86_H + +#if defined(__i386__) || defined(__x86_64__) +#define ELF_ARCH_DATA ELFDATA2LSB +#if defined (__i386__) +# define ELF_ARCH_MACHINE EM_386 +#else +# define ELF_ARCH_MACHINE EM_X86_64 +#endif +#endif /* __i386__ or __x86_64__ */ + + +struct xc_core_arch_context { + /* nothing */ +}; + +#define xc_core_arch_context_init(arch_ctxt) do {} while (0) +#define xc_core_arch_context_free(arch_ctxt) do {} while (0) +#define xc_core_arch_context_get(arch_ctxt, ctxt, xc_handle, domid) \ + (0) +#define xc_core_arch_context_dump(arch_ctxt, args, dump_rtn) (0) + +static inline int +xc_core_arch_context_get_shdr(struct xc_core_arch_context *arch_ctxt, + struct xc_core_section_headers *sheaders, + struct xc_core_strtab *strtab, + uint64_t *filesz, uint64_t offset) +{ + *filesz = 0; + return 0; +} + +#endif /* XC_CORE_X86_H */ + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/tools/libxc/xc_dom.h b/tools/libxc/xc_dom.h index 931d96acaf..9e0422a4b2 100644 --- a/tools/libxc/xc_dom.h +++ b/tools/libxc/xc_dom.h @@ -158,9 +158,9 @@ int xc_dom_try_gunzip(struct xc_dom_image *dom, void **blob, size_t * size); int xc_dom_kernel_file(struct xc_dom_image *dom, const char *filename); int xc_dom_ramdisk_file(struct xc_dom_image *dom, const char *filename); int xc_dom_kernel_mem(struct xc_dom_image *dom, const void *mem, - size_t memsize); + size_t memsize); int xc_dom_ramdisk_mem(struct xc_dom_image *dom, const void *mem, - size_t memsize); + size_t memsize); int xc_dom_parse_image(struct xc_dom_image *dom); int xc_dom_build_image(struct xc_dom_image *dom); @@ -169,7 +169,7 @@ int xc_dom_update_guest_p2m(struct xc_dom_image *dom); int xc_dom_boot_xen_init(struct xc_dom_image *dom, int xc, domid_t domid); int xc_dom_boot_mem_init(struct xc_dom_image *dom); void *xc_dom_boot_domU_map(struct xc_dom_image *dom, xen_pfn_t pfn, - xen_pfn_t count); + xen_pfn_t count); int xc_dom_boot_image(struct xc_dom_image *dom); int xc_dom_compat_check(struct xc_dom_image *dom); @@ -180,12 +180,12 @@ extern FILE *xc_dom_logfile; void xc_dom_loginit(void); int xc_dom_printf(const char *fmt, ...) __attribute__ ((format(printf, 1, 2))); int xc_dom_panic_func(const char *file, int line, xc_error_code err, - const char *fmt, ...) + const char *fmt, ...) __attribute__ ((format(printf, 4, 5))); #define xc_dom_panic(err, fmt, args...) \ - xc_dom_panic_func(__FILE__, __LINE__, err, fmt, ## args) + xc_dom_panic_func(__FILE__, __LINE__, err, fmt, ## args) #define xc_dom_trace(mark) \ - xc_dom_printf("%s:%d: trace %s\n", __FILE__, __LINE__, mark) + xc_dom_printf("%s:%d: trace %s\n", __FILE__, __LINE__, mark) void xc_dom_log_memory_footprint(struct xc_dom_image *dom); @@ -194,25 +194,25 @@ void xc_dom_log_memory_footprint(struct xc_dom_image *dom); void *xc_dom_malloc(struct xc_dom_image *dom, size_t size); void *xc_dom_malloc_page_aligned(struct xc_dom_image *dom, size_t size); void *xc_dom_malloc_filemap(struct xc_dom_image *dom, - const char *filename, size_t * size); + const char *filename, size_t * size); char *xc_dom_strdup(struct xc_dom_image *dom, const char *str); /* --- alloc memory pool ------------------------------------------- */ int xc_dom_alloc_page(struct xc_dom_image *dom, char *name); int xc_dom_alloc_segment(struct xc_dom_image *dom, - struct xc_dom_seg *seg, char *name, - xen_vaddr_t start, xen_vaddr_t size); + struct xc_dom_seg *seg, char *name, + xen_vaddr_t start, xen_vaddr_t size); /* --- misc bits --------------------------------------------------- */ void *xc_dom_pfn_to_ptr(struct xc_dom_image *dom, xen_pfn_t first, - xen_pfn_t count); + xen_pfn_t count); void xc_dom_unmap_one(struct xc_dom_image *dom, xen_pfn_t pfn); void xc_dom_unmap_all(struct xc_dom_image *dom); static inline void *xc_dom_seg_to_ptr(struct xc_dom_image *dom, - struct xc_dom_seg *seg) + struct xc_dom_seg *seg) { xen_vaddr_t segsize = seg->vend - seg->vstart; unsigned int page_size = XC_DOM_PAGE_SIZE(dom); @@ -222,16 +222,13 @@ static inline void *xc_dom_seg_to_ptr(struct xc_dom_image *dom, } static inline void *xc_dom_vaddr_to_ptr(struct xc_dom_image *dom, - xen_vaddr_t vaddr) + xen_vaddr_t vaddr) { unsigned int page_size = XC_DOM_PAGE_SIZE(dom); xen_pfn_t page = (vaddr - dom->parms.virt_base) / page_size; unsigned int offset = (vaddr - dom->parms.virt_base) % page_size; void *ptr = xc_dom_pfn_to_ptr(dom, page, 0); - - if (!ptr) - return NULL; - return ptr + offset; + return (ptr ? (ptr + offset) : NULL); } static inline int xc_dom_feature_translated(struct xc_dom_image *dom) @@ -242,17 +239,26 @@ static inline int xc_dom_feature_translated(struct xc_dom_image *dom) static inline xen_pfn_t xc_dom_p2m_host(struct xc_dom_image *dom, xen_pfn_t pfn) { if (dom->shadow_enabled) - return pfn; + return pfn; return dom->p2m_host[pfn]; } static inline xen_pfn_t xc_dom_p2m_guest(struct xc_dom_image *dom, - xen_pfn_t pfn) + xen_pfn_t pfn) { if (xc_dom_feature_translated(dom)) - return pfn; + return pfn; return dom->p2m_host[pfn]; } /* --- arch bits --------------------------------------------------- */ +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/tools/libxc/xc_dom_binloader.c b/tools/libxc/xc_dom_binloader.c index dfaef31f27..e887620659 100644 --- a/tools/libxc/xc_dom_binloader.c +++ b/tools/libxc/xc_dom_binloader.c @@ -95,7 +95,7 @@ struct xen_bin_image_table /* Flags we test for */ #define FLAGS_MASK ((~ 0) & (~ XEN_MULTIBOOT_FLAG_ALIGN4K) & \ - (~ XEN_MULTIBOOT_FLAG_PAE_MASK)) + (~ XEN_MULTIBOOT_FLAG_PAE_MASK)) #define FLAGS_REQUIRED XEN_MULTIBOOT_FLAG_ADDRSVALID /* --------------------------------------------------------------------- */ @@ -108,19 +108,17 @@ static struct xen_bin_image_table *find_table(struct xc_dom_image *dom) probe_ptr = dom->kernel_blob; probe_end = dom->kernel_blob + dom->kernel_size - sizeof(*table); - if ((void*)probe_end > dom->kernel_blob + 8192) + if ( (void*)probe_end > (dom->kernel_blob + 8192) ) probe_end = dom->kernel_blob + 8192; - for (table = NULL; probe_ptr < probe_end; probe_ptr++) + for ( table = NULL; probe_ptr < probe_end; probe_ptr++ ) { - if (XEN_MULTIBOOT_MAGIC3 == *probe_ptr) + if ( *probe_ptr == XEN_MULTIBOOT_MAGIC3 ) { table = (struct xen_bin_image_table *) probe_ptr; /* Checksum correct? */ - if (0 == table->magic + table->flags + table->checksum) - { + if ( (table->magic + table->flags + table->checksum) == 0 ) return table; - } } } return NULL; @@ -128,12 +126,7 @@ static struct xen_bin_image_table *find_table(struct xc_dom_image *dom) static int xc_dom_probe_bin_kernel(struct xc_dom_image *dom) { - struct xen_bin_image_table *table; - - table = find_table(dom); - if (!table) - return -EINVAL; - return 0; + return find_table(dom) ? 0 : -EINVAL; } static int xc_dom_parse_bin_kernel(struct xc_dom_image *dom) @@ -147,7 +140,7 @@ static int xc_dom_parse_bin_kernel(struct xc_dom_image *dom) uint32_t pae_flags; image_info = find_table(dom); - if (!image_info) + if ( !image_info ) return -EINVAL; xc_dom_printf("%s: multiboot header fields\n", __FUNCTION__); @@ -159,7 +152,7 @@ static int xc_dom_parse_bin_kernel(struct xc_dom_image *dom) xc_dom_printf(" entry_addr: 0x%" PRIx32 "\n", image_info->entry_addr); /* Check the flags */ - if ( FLAGS_REQUIRED != (image_info->flags & FLAGS_MASK) ) + if ( (image_info->flags & FLAGS_MASK) != FLAGS_REQUIRED ) { xc_dom_panic(XC_INVALID_KERNEL, "%s: xen_bin_image_table flags required " @@ -169,7 +162,7 @@ static int xc_dom_parse_bin_kernel(struct xc_dom_image *dom) } /* Sanity check on the addresses */ - if ( image_info->header_addr < image_info->load_addr || + if ( (image_info->header_addr < image_info->load_addr) || ((char *) image_info - image) < (image_info->header_addr - image_info->load_addr) ) { @@ -187,7 +180,7 @@ static int xc_dom_parse_bin_kernel(struct xc_dom_image *dom) xc_dom_printf(" load_end_addr: 0x%" PRIx32 "\n", load_end_addr); xc_dom_printf(" bss_end_addr: 0x%" PRIx32 "\n", bss_end_addr); - if ( start_addr + image_size < load_end_addr ) + if ( (start_addr + image_size) < load_end_addr ) { xc_dom_panic(XC_INVALID_KERNEL, "%s: Invalid load_end_addr.\n", __FUNCTION__); @@ -209,25 +202,26 @@ static int xc_dom_parse_bin_kernel(struct xc_dom_image *dom) pae_flags = image_info->flags & XEN_MULTIBOOT_FLAG_PAE_MASK; switch (pae_flags >> XEN_MULTIBOOT_FLAG_PAE_SHIFT) { case 0: - dom->guest_type = "xen-3.0-x86_32"; - break; + dom->guest_type = "xen-3.0-x86_32"; + break; case 1: - dom->guest_type = "xen-3.0-x86_32p"; - break; + dom->guest_type = "xen-3.0-x86_32p"; + break; case 2: - dom->guest_type = "xen-3.0-x86_64"; - break; + dom->guest_type = "xen-3.0-x86_64"; + break; case 3: - /* Kernel detects PAE at runtime. So try to figure whenever - * xen supports PAE and advertise a PAE-capable kernel in case - * it does. */ - dom->guest_type = "xen-3.0-x86_32"; - if (strstr(dom->xen_caps, "xen-3.0-x86_32p")) { - xc_dom_printf("%s: PAE fixup\n", __FUNCTION__); - dom->guest_type = "xen-3.0-x86_32p"; - dom->parms.pae = 2; - } - break; + /* Kernel detects PAE at runtime. So try to figure whenever + * xen supports PAE and advertise a PAE-capable kernel in case + * it does. */ + dom->guest_type = "xen-3.0-x86_32"; + if ( strstr(dom->xen_caps, "xen-3.0-x86_32p") ) + { + xc_dom_printf("%s: PAE fixup\n", __FUNCTION__); + dom->guest_type = "xen-3.0-x86_32p"; + dom->parms.pae = 2; + } + break; } return 0; } @@ -242,10 +236,9 @@ static int xc_dom_load_bin_kernel(struct xc_dom_image *dom) uint32_t load_end_addr; uint32_t bss_end_addr; uint32_t skip, text_size, bss_size; - uint32_t pae_flags; image_info = find_table(dom); - if (!image_info) + if ( !image_info ) return -EINVAL; start_addr = image_info->header_addr - ((char *)image_info - image); @@ -266,10 +259,6 @@ static int xc_dom_load_bin_kernel(struct xc_dom_image *dom) memcpy(dest, image + skip, text_size); memset(dest + text_size, 0, bss_size); - pae_flags = image_info->flags & XEN_MULTIBOOT_FLAG_PAE_MASK; - if (3 == (pae_flags >> XEN_MULTIBOOT_FLAG_PAE_SHIFT) && dom->guest_xc > 0) - { - } return 0; } @@ -289,6 +278,10 @@ static void __init register_loader(void) /* * Local variables: + * mode: C + * c-set-style: "BSD" * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil * End: */ diff --git a/tools/libxc/xc_dom_boot.c b/tools/libxc/xc_dom_boot.c index 83b1abe1eb..8644f0c24f 100644 --- a/tools/libxc/xc_dom_boot.c +++ b/tools/libxc/xc_dom_boot.c @@ -29,20 +29,20 @@ static int setup_hypercall_page(struct xc_dom_image *dom) xen_pfn_t pfn; int rc; - if (-1 == dom->parms.virt_hypercall) - return 0; + if ( dom->parms.virt_hypercall == -1 ) + return 0; pfn = (dom->parms.virt_hypercall - dom->parms.virt_base) - >> XC_DOM_PAGE_SHIFT(dom); + >> XC_DOM_PAGE_SHIFT(dom); xc_dom_printf("%s: vaddr=0x%" PRIx64 " pfn=0x%" PRIpfn "\n", __FUNCTION__, - dom->parms.virt_hypercall, pfn); + dom->parms.virt_hypercall, pfn); domctl.cmd = XEN_DOMCTL_hypercall_init; domctl.domain = dom->guest_domid; domctl.u.hypercall_init.gmfn = xc_dom_p2m_guest(dom, pfn); rc = do_domctl(dom->guest_xc, &domctl); - if (0 != rc) - xc_dom_panic(XC_INTERNAL_ERROR, "%s: HYPERCALL_INIT failed (rc=%d)\n", - __FUNCTION__, rc); + if ( rc != 0 ) + xc_dom_panic(XC_INTERNAL_ERROR, "%s: HYPERCALL_INIT failed (rc=%d)\n", + __FUNCTION__, rc); return rc; } @@ -58,9 +58,9 @@ static int launch_vm(int xc, domid_t domid, void *ctxt) domctl.u.vcpucontext.vcpu = 0; set_xen_guest_handle(domctl.u.vcpucontext.ctxt, ctxt); rc = do_domctl(xc, &domctl); - if (0 != rc) - xc_dom_panic(XC_INTERNAL_ERROR, - "%s: SETVCPUCONTEXT failed (rc=%d)\n", __FUNCTION__, rc); + if ( rc != 0 ) + xc_dom_panic(XC_INTERNAL_ERROR, + "%s: SETVCPUCONTEXT failed (rc=%d)\n", __FUNCTION__, rc); return rc; } @@ -69,17 +69,17 @@ static int clear_page(struct xc_dom_image *dom, xen_pfn_t pfn) xen_pfn_t dst; int rc; - if (0 == pfn) - return 0; + if ( pfn == 0 ) + return 0; dst = xc_dom_p2m_host(dom, pfn); xc_dom_printf("%s: pfn 0x%" PRIpfn ", mfn 0x%" PRIpfn "\n", - __FUNCTION__, pfn, dst); + __FUNCTION__, pfn, dst); rc = xc_clear_domain_page(dom->guest_xc, dom->guest_domid, dst); - if (0 != rc) - xc_dom_panic(XC_INTERNAL_ERROR, - "%s: xc_clear_domain_page failed (pfn 0x%" PRIpfn - ", rc=%d)\n", __FUNCTION__, pfn, rc); + if ( rc != 0 ) + xc_dom_panic(XC_INTERNAL_ERROR, + "%s: xc_clear_domain_page failed (pfn 0x%" PRIpfn + ", rc=%d)\n", __FUNCTION__, pfn, rc); return rc; } @@ -92,11 +92,11 @@ static int clear_page(struct xc_dom_image *dom, xen_pfn_t pfn) static int x86_compat(int xc, domid_t domid, char *guest_type) { static const struct { - char *guest; - uint32_t size; + char *guest; + uint32_t size; } types[] = { - { "xen-3.0-x86_32p", 32 }, - { "xen-3.0-x86_64", 64 }, + { "xen-3.0-x86_32p", 32 }, + { "xen-3.0-x86_64", 64 }, }; DECLARE_DOMCTL; int i,rc; @@ -104,19 +104,19 @@ static int x86_compat(int xc, domid_t domid, char *guest_type) memset(&domctl, 0, sizeof(domctl)); domctl.domain = domid; domctl.cmd = XEN_DOMCTL_set_address_size; - for (i = 0; i < sizeof(types)/sizeof(types[0]); i++) - if (0 == strcmp(types[i].guest, guest_type)) - domctl.u.address_size.size = types[i].size; - if (0 == domctl.u.address_size.size) - /* nothing to do */ - return 0; + for ( i = 0; i < sizeof(types)/sizeof(types[0]); i++ ) + if ( !strcmp(types[i].guest, guest_type) ) + domctl.u.address_size.size = types[i].size; + if ( domctl.u.address_size.size == 0 ) + /* nothing to do */ + return 0; xc_dom_printf("%s: guest %s, address size %" PRId32 "\n", __FUNCTION__, - guest_type, domctl.u.address_size.size); + guest_type, domctl.u.address_size.size); rc = do_domctl(xc, &domctl); - if (0 != rc) - xc_dom_printf("%s: warning: failed (rc=%d)\n", - __FUNCTION__, rc); + if ( rc != 0 ) + xc_dom_printf("%s: warning: failed (rc=%d)\n", + __FUNCTION__, rc); return rc; } @@ -128,17 +128,17 @@ static int x86_shadow(int xc, domid_t domid) xc_dom_printf("%s: called\n", __FUNCTION__); mode = XEN_DOMCTL_SHADOW_ENABLE_REFCOUNT | - XEN_DOMCTL_SHADOW_ENABLE_TRANSLATE; + XEN_DOMCTL_SHADOW_ENABLE_TRANSLATE; rc = xc_shadow_control(xc, domid, - XEN_DOMCTL_SHADOW_OP_ENABLE, - NULL, 0, NULL, mode, NULL); - if (0 != rc) + XEN_DOMCTL_SHADOW_OP_ENABLE, + NULL, 0, NULL, mode, NULL); + if ( rc != 0 ) { - xc_dom_panic(XC_INTERNAL_ERROR, - "%s: SHADOW_OP_ENABLE (mode=0x%x) failed (rc=%d)\n", - __FUNCTION__, mode, rc); - return rc; + xc_dom_panic(XC_INTERNAL_ERROR, + "%s: SHADOW_OP_ENABLE (mode=0x%x) failed (rc=%d)\n", + __FUNCTION__, mode, rc); + return rc; } xc_dom_printf("%s: shadow enabled (mode=0x%x)\n", __FUNCTION__, mode); return rc; @@ -149,10 +149,10 @@ static int arch_setup_meminit(struct xc_dom_image *dom) int rc = 0; x86_compat(dom->guest_xc, dom->guest_domid, dom->guest_type); - if (xc_dom_feature_translated(dom)) + if ( xc_dom_feature_translated(dom) ) { - dom->shadow_enabled = 1; - rc = x86_shadow(dom->guest_xc, dom->guest_domid); + dom->shadow_enabled = 1; + rc = x86_shadow(dom->guest_xc, dom->guest_domid); } return rc; } @@ -166,92 +166,92 @@ static int arch_setup_bootearly(struct xc_dom_image *dom) static int arch_setup_bootlate(struct xc_dom_image *dom) { static const struct { - char *guest; - unsigned long pgd_type; + char *guest; + unsigned long pgd_type; } types[] = { - { "xen-3.0-x86_32", MMUEXT_PIN_L2_TABLE}, - { "xen-3.0-x86_32p", MMUEXT_PIN_L3_TABLE}, - { "xen-3.0-x86_64", MMUEXT_PIN_L4_TABLE}, + { "xen-3.0-x86_32", MMUEXT_PIN_L2_TABLE}, + { "xen-3.0-x86_32p", MMUEXT_PIN_L3_TABLE}, + { "xen-3.0-x86_64", MMUEXT_PIN_L4_TABLE}, }; unsigned long pgd_type = 0; shared_info_t *shared_info; xen_pfn_t shinfo; int i, rc; - for (i = 0; i < sizeof(types) / sizeof(types[0]); i++) - if (0 == strcmp(types[i].guest, dom->guest_type)) - pgd_type = types[i].pgd_type; + for ( i = 0; i < sizeof(types) / sizeof(types[0]); i++ ) + if ( !strcmp(types[i].guest, dom->guest_type) ) + pgd_type = types[i].pgd_type; - if (!xc_dom_feature_translated(dom)) + if ( !xc_dom_feature_translated(dom) ) { - /* paravirtualized guest */ - xc_dom_unmap_one(dom, dom->pgtables_seg.pfn); - rc = pin_table(dom->guest_xc, pgd_type, - xc_dom_p2m_host(dom, dom->pgtables_seg.pfn), - dom->guest_domid); - if (0 != rc) - { - xc_dom_panic(XC_INTERNAL_ERROR, - "%s: pin_table failed (pfn 0x%" PRIpfn ", rc=%d)\n", - __FUNCTION__, dom->pgtables_seg.pfn, rc); - return rc; - } - shinfo = dom->shared_info_mfn; + /* paravirtualized guest */ + xc_dom_unmap_one(dom, dom->pgtables_seg.pfn); + rc = pin_table(dom->guest_xc, pgd_type, + xc_dom_p2m_host(dom, dom->pgtables_seg.pfn), + dom->guest_domid); + if ( rc != 0 ) + { + xc_dom_panic(XC_INTERNAL_ERROR, + "%s: pin_table failed (pfn 0x%" PRIpfn ", rc=%d)\n", + __FUNCTION__, dom->pgtables_seg.pfn, rc); + return rc; + } + shinfo = dom->shared_info_mfn; } else { - /* paravirtualized guest with auto-translation */ - struct xen_add_to_physmap xatp; - int i; + /* paravirtualized guest with auto-translation */ + struct xen_add_to_physmap xatp; + int i; - /* Map shared info frame into guest physmap. */ - xatp.domid = dom->guest_domid; - xatp.space = XENMAPSPACE_shared_info; - xatp.idx = 0; - xatp.gpfn = dom->shared_info_pfn; - rc = xc_memory_op(dom->guest_xc, XENMEM_add_to_physmap, &xatp); - if (rc != 0) - { - xc_dom_panic(XC_INTERNAL_ERROR, "%s: mapping shared_info failed " - "(pfn=0x%" PRIpfn ", rc=%d)\n", - __FUNCTION__, xatp.gpfn, rc); - return rc; - } + /* Map shared info frame into guest physmap. */ + xatp.domid = dom->guest_domid; + xatp.space = XENMAPSPACE_shared_info; + xatp.idx = 0; + xatp.gpfn = dom->shared_info_pfn; + rc = xc_memory_op(dom->guest_xc, XENMEM_add_to_physmap, &xatp); + if ( rc != 0 ) + { + xc_dom_panic(XC_INTERNAL_ERROR, "%s: mapping shared_info failed " + "(pfn=0x%" PRIpfn ", rc=%d)\n", + __FUNCTION__, xatp.gpfn, rc); + return rc; + } - /* Map grant table frames into guest physmap. */ - for (i = 0;; i++) - { - xatp.domid = dom->guest_domid; - xatp.space = XENMAPSPACE_grant_table; - xatp.idx = i; - xatp.gpfn = dom->total_pages + i; - rc = xc_memory_op(dom->guest_xc, XENMEM_add_to_physmap, &xatp); - if (rc != 0) - { - if (i > 0 && errno == EINVAL) - { - xc_dom_printf("%s: %d grant tables mapped\n", __FUNCTION__, - i); - break; - } - xc_dom_panic(XC_INTERNAL_ERROR, - "%s: mapping grant tables failed " "(pfn=0x%" - PRIpfn ", rc=%d)\n", __FUNCTION__, xatp.gpfn, rc); - return rc; - } - } - shinfo = dom->shared_info_pfn; + /* Map grant table frames into guest physmap. */ + for ( i = 0; ; i++ ) + { + xatp.domid = dom->guest_domid; + xatp.space = XENMAPSPACE_grant_table; + xatp.idx = i; + xatp.gpfn = dom->total_pages + i; + rc = xc_memory_op(dom->guest_xc, XENMEM_add_to_physmap, &xatp); + if ( rc != 0 ) + { + if ( (i > 0) && (errno == EINVAL) ) + { + xc_dom_printf("%s: %d grant tables mapped\n", __FUNCTION__, + i); + break; + } + xc_dom_panic(XC_INTERNAL_ERROR, + "%s: mapping grant tables failed " "(pfn=0x%" + PRIpfn ", rc=%d)\n", __FUNCTION__, xatp.gpfn, rc); + return rc; + } + } + shinfo = dom->shared_info_pfn; } /* setup shared_info page */ xc_dom_printf("%s: shared_info: pfn 0x%" PRIpfn ", mfn 0x%" PRIpfn "\n", - __FUNCTION__, dom->shared_info_pfn, dom->shared_info_mfn); + __FUNCTION__, dom->shared_info_pfn, dom->shared_info_mfn); shared_info = xc_map_foreign_range(dom->guest_xc, dom->guest_domid, - PAGE_SIZE_X86, - PROT_READ | PROT_WRITE, - shinfo); - if (NULL == shared_info) - return -1; + PAGE_SIZE_X86, + PROT_READ | PROT_WRITE, + shinfo); + if ( shared_info == NULL ) + return -1; dom->arch_hooks->shared_info(dom, shared_info); munmap(shared_info, PAGE_SIZE_X86); @@ -282,7 +282,7 @@ static int arch_setup_bootearly(struct xc_dom_image *dom) domctl.u.arch_setup.flags = 0; domctl.u.arch_setup.bp = (dom->start_info_pfn << PAGE_SHIFT) - + sizeof(start_info_t); + + sizeof(start_info_t); /* 3 = start info page, xenstore page and console page */ domctl.u.arch_setup.maxmem = (dom->total_pages - 3) << PAGE_SHIFT; rc = do_domctl(dom->guest_xc, &domctl); @@ -296,13 +296,13 @@ static int arch_setup_bootlate(struct xc_dom_image *dom) /* setup shared_info page */ xc_dom_printf("%s: shared_info: mfn 0x%" PRIpfn "\n", - __FUNCTION__, dom->shared_info_mfn); + __FUNCTION__, dom->shared_info_mfn); shared_info = xc_map_foreign_range(dom->guest_xc, dom->guest_domid, - page_size, - PROT_READ | PROT_WRITE, - dom->shared_info_mfn); - if (NULL == shared_info) - return -1; + page_size, + PROT_READ | PROT_WRITE, + dom->shared_info_mfn); + if ( shared_info == NULL ) + return -1; dom->arch_hooks->shared_info(dom, shared_info); munmap(shared_info, page_size); return 0; @@ -328,20 +328,20 @@ static int arch_setup_bootearly(struct xc_dom_image *dom) static int arch_setup_bootlate(struct xc_dom_image *dom) { start_info_t *si = - xc_dom_pfn_to_ptr(dom, dom->start_info_pfn, 1); + xc_dom_pfn_to_ptr(dom, dom->start_info_pfn, 1); xc_dom_printf("%s: TODO: setup devtree\n", __FUNCTION__); #if 0 load_devtree(dom->guest_xc, - dom->guest_domid, - dom->p2m_host, - devtree, // FIXME - devtree_addr, // FIXME - dom->ramdisk_seg.vstart, - dom->ramdisk_seg.vend - dom->ramdisk_seg.vstart, - si, - dom->start_info_pfn << PAGE_SHIFT); + dom->guest_domid, + dom->p2m_host, + devtree, // FIXME + devtree_addr, // FIXME + dom->ramdisk_seg.vstart, + dom->ramdisk_seg.vend - dom->ramdisk_seg.vstart, + si, + dom->start_info_pfn << PAGE_SHIFT); #endif return rc; } @@ -380,19 +380,19 @@ int xc_dom_compat_check(struct xc_dom_image *dom) int match, found = 0; strcpy(xen_caps, dom->xen_caps); - for (item = strtok_r(xen_caps, " ", &ptr); - NULL != item; item = strtok_r(NULL, " ", &ptr)) + for ( item = strtok_r(xen_caps, " ", &ptr); + item != NULL ; item = strtok_r(NULL, " ", &ptr) ) { - match = (0 == strcmp(dom->guest_type, item)); - xc_dom_printf("%s: supported guest type: %s%s\n", __FUNCTION__, - item, match ? " <= matches" : ""); - if (match) - found++; + match = !strcmp(dom->guest_type, item); + xc_dom_printf("%s: supported guest type: %s%s\n", __FUNCTION__, + item, match ? " <= matches" : ""); + if ( match ) + found++; } - if (!found) - xc_dom_panic(XC_INVALID_KERNEL, - "%s: guest type %s not supported by xen kernel, sorry\n", - __FUNCTION__, dom->guest_type); + if ( !found ) + xc_dom_panic(XC_INVALID_KERNEL, + "%s: guest type %s not supported by xen kernel, sorry\n", + __FUNCTION__, dom->guest_type); return found; } @@ -403,13 +403,14 @@ int xc_dom_boot_xen_init(struct xc_dom_image *dom, int xc, domid_t domid) dom->guest_domid = domid; dom->xen_version = xc_version(dom->guest_xc, XENVER_version, NULL); - if (xc_version(xc, XENVER_capabilities, &dom->xen_caps) < 0) { - xc_dom_panic(XC_INTERNAL_ERROR, "can't get xen capabilities"); - return -1; + if ( xc_version(xc, XENVER_capabilities, &dom->xen_caps) < 0 ) + { + xc_dom_panic(XC_INTERNAL_ERROR, "can't get xen capabilities"); + return -1; } xc_dom_printf("%s: ver %d.%d, caps %s\n", __FUNCTION__, - dom->xen_version >> 16, dom->xen_version & 0xff, - dom->xen_caps); + dom->xen_version >> 16, dom->xen_version & 0xff, + dom->xen_caps); return 0; } @@ -419,26 +420,26 @@ int xc_dom_boot_mem_init(struct xc_dom_image *dom) xc_dom_printf("%s: called\n", __FUNCTION__); - if (0 != (rc = arch_setup_meminit(dom))) - return rc; + if ( (rc = arch_setup_meminit(dom)) != 0 ) + return rc; /* allocate guest memory */ rc = xc_domain_memory_populate_physmap(dom->guest_xc, dom->guest_domid, - dom->total_pages, 0, 0, - dom->p2m_host); - if (0 != rc) + dom->total_pages, 0, 0, + dom->p2m_host); + if ( rc != 0 ) { - xc_dom_panic(XC_OUT_OF_MEMORY, - "%s: can't allocate low memory for domain\n", - __FUNCTION__); - return rc; + xc_dom_panic(XC_OUT_OF_MEMORY, + "%s: can't allocate low memory for domain\n", + __FUNCTION__); + return rc; } return 0; } void *xc_dom_boot_domU_map(struct xc_dom_image *dom, xen_pfn_t pfn, - xen_pfn_t count) + xen_pfn_t count) { int page_shift = XC_DOM_PAGE_SHIFT(dom); privcmd_mmap_entry_t *entries; @@ -446,38 +447,39 @@ void *xc_dom_boot_domU_map(struct xc_dom_image *dom, xen_pfn_t pfn, int i, rc; entries = xc_dom_malloc(dom, count * sizeof(privcmd_mmap_entry_t)); - if (NULL == entries) + if ( entries == NULL ) { - xc_dom_panic(XC_INTERNAL_ERROR, - "%s: failed to mmap domU pages 0x%" PRIpfn "+0x%" PRIpfn - " [malloc]\n", __FUNCTION__, pfn, count); - return NULL; + xc_dom_panic(XC_INTERNAL_ERROR, + "%s: failed to mmap domU pages 0x%" PRIpfn "+0x%" PRIpfn + " [malloc]\n", __FUNCTION__, pfn, count); + return NULL; } ptr = mmap(NULL, count << page_shift, PROT_READ | PROT_WRITE, - MAP_SHARED, dom->guest_xc, 0); - if (MAP_FAILED == ptr) + MAP_SHARED, dom->guest_xc, 0); + if ( ptr == MAP_FAILED ) { - xc_dom_panic(XC_INTERNAL_ERROR, - "%s: failed to mmap domU pages 0x%" PRIpfn "+0x%" PRIpfn - " [mmap]\n", __FUNCTION__, pfn, count); - return NULL; + xc_dom_panic(XC_INTERNAL_ERROR, + "%s: failed to mmap domU pages 0x%" PRIpfn "+0x%" PRIpfn + " [mmap]\n", __FUNCTION__, pfn, count); + return NULL; } - for (i = 0; i < count; i++) + for ( i = 0; i < count; i++ ) { - entries[i].va = (uintptr_t) ptr + (i << page_shift); - entries[i].mfn = xc_dom_p2m_host(dom, pfn + i); - entries[i].npages = 1; + entries[i].va = (uintptr_t) ptr + (i << page_shift); + entries[i].mfn = xc_dom_p2m_host(dom, pfn + i); + entries[i].npages = 1; } - rc = xc_map_foreign_ranges(dom->guest_xc, dom->guest_domid, entries, count); - if (rc < 0) + rc = xc_map_foreign_ranges(dom->guest_xc, dom->guest_domid, + entries, count); + if ( rc < 0 ) { - xc_dom_panic(XC_INTERNAL_ERROR, - "%s: failed to mmap domU pages 0x%" PRIpfn "+0x%" PRIpfn - " [xenctl, rc=%d]\n", __FUNCTION__, pfn, count, rc); - return NULL; + xc_dom_panic(XC_INTERNAL_ERROR, + "%s: failed to mmap domU pages 0x%" PRIpfn "+0x%" PRIpfn + " [xenctl, rc=%d]\n", __FUNCTION__, pfn, count, rc); + return NULL; } return ptr; } @@ -491,64 +493,74 @@ int xc_dom_boot_image(struct xc_dom_image *dom) xc_dom_printf("%s: called\n", __FUNCTION__); /* misc ia64 stuff*/ - if (0 != (rc = arch_setup_bootearly(dom))) - return rc; + if ( (rc = arch_setup_bootearly(dom)) != 0 ) + return rc; /* collect some info */ domctl.cmd = XEN_DOMCTL_getdomaininfo; domctl.domain = dom->guest_domid; rc = do_domctl(dom->guest_xc, &domctl); - if (0 != rc) + if ( rc != 0 ) { - xc_dom_panic(XC_INTERNAL_ERROR, - "%s: getdomaininfo failed (rc=%d)\n", __FUNCTION__, rc); - return rc; + xc_dom_panic(XC_INTERNAL_ERROR, + "%s: getdomaininfo failed (rc=%d)\n", __FUNCTION__, rc); + return rc; } - if (domctl.domain != dom->guest_domid) + if ( domctl.domain != dom->guest_domid ) { - xc_dom_panic(XC_INTERNAL_ERROR, - "%s: Huh? domid mismatch (%d != %d)\n", __FUNCTION__, - domctl.domain, dom->guest_domid); - return -1; + xc_dom_panic(XC_INTERNAL_ERROR, + "%s: Huh? domid mismatch (%d != %d)\n", __FUNCTION__, + domctl.domain, dom->guest_domid); + return -1; } dom->shared_info_mfn = domctl.u.getdomaininfo.shared_info_frame; /* sanity checks */ - if (!xc_dom_compat_check(dom)) - return -1; + if ( !xc_dom_compat_check(dom) ) + return -1; /* initial mm setup */ - if (0 != (rc = xc_dom_update_guest_p2m(dom))) - return rc; - if (dom->arch_hooks->setup_pgtables) - if (0 != (rc = dom->arch_hooks->setup_pgtables(dom))) - return rc; + if ( (rc = xc_dom_update_guest_p2m(dom)) != 0 ) + return rc; + if ( dom->arch_hooks->setup_pgtables ) + if ( (rc = dom->arch_hooks->setup_pgtables(dom)) != 0 ) + return rc; - if (0 != (rc = clear_page(dom, dom->console_pfn))) - return rc; - if (0 != (rc = clear_page(dom, dom->xenstore_pfn))) - return rc; + if ( (rc = clear_page(dom, dom->console_pfn)) != 0 ) + return rc; + if ( (rc = clear_page(dom, dom->xenstore_pfn)) != 0 ) + return rc; /* start info page */ - if (dom->arch_hooks->start_info) - dom->arch_hooks->start_info(dom); + if ( dom->arch_hooks->start_info ) + dom->arch_hooks->start_info(dom); /* hypercall page */ - if (0 != (rc = setup_hypercall_page(dom))) - return rc; + if ( (rc = setup_hypercall_page(dom)) != 0 ) + return rc; xc_dom_log_memory_footprint(dom); /* misc x86 stuff */ - if (0 != (rc = arch_setup_bootlate(dom))) - return rc; + if ( (rc = arch_setup_bootlate(dom)) != 0 ) + return rc; /* let the vm run */ ctxt = xc_dom_malloc(dom, PAGE_SIZE * 2 /* FIXME */ ); memset(ctxt, 0, PAGE_SIZE * 2); - if (0 != (rc = dom->arch_hooks->vcpu(dom, ctxt))) - return rc; + if ( (rc = dom->arch_hooks->vcpu(dom, ctxt)) != 0 ) + return rc; xc_dom_unmap_all(dom); rc = launch_vm(dom->guest_xc, dom->guest_domid, ctxt); return rc; } + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/tools/libxc/xc_dom_compat_linux.c b/tools/libxc/xc_dom_compat_linux.c index c387cb88fe..89265a6b37 100644 --- a/tools/libxc/xc_dom_compat_linux.c +++ b/tools/libxc/xc_dom_compat_linux.c @@ -22,103 +22,137 @@ /* ------------------------------------------------------------------------ */ static int xc_linux_build_internal(struct xc_dom_image *dom, - int xc_handle, uint32_t domid, - unsigned int mem_mb, - unsigned long flags, - unsigned int store_evtchn, - unsigned long *store_mfn, - unsigned int console_evtchn, - unsigned long *console_mfn) + int xc_handle, uint32_t domid, + unsigned int mem_mb, + unsigned long flags, + unsigned int store_evtchn, + unsigned long *store_mfn, + unsigned int console_evtchn, + unsigned long *console_mfn) { int rc; - if (0 != (rc = xc_dom_boot_xen_init(dom, xc_handle, domid))) - goto out; - if (0 != (rc = xc_dom_parse_image(dom))) - goto out; - if (0 != (rc = xc_dom_mem_init(dom, mem_mb))) - goto out; - if (0 != (rc = xc_dom_boot_mem_init(dom))) - goto out; - if (0 != (rc = xc_dom_build_image(dom))) - goto out; + if ( (rc = xc_dom_boot_xen_init(dom, xc_handle, domid)) != 0 ) + goto out; + if ( (rc = xc_dom_parse_image(dom)) != 0 ) + goto out; + if ( (rc = xc_dom_mem_init(dom, mem_mb)) != 0 ) + goto out; + if ( (rc = xc_dom_boot_mem_init(dom)) != 0 ) + goto out; + if ( (rc = xc_dom_build_image(dom)) != 0 ) + goto out; dom->flags = flags; dom->console_evtchn = console_evtchn; dom->xenstore_evtchn = store_evtchn; rc = xc_dom_boot_image(dom); - if (0 != rc) - goto out; + if ( rc != 0 ) + goto out; *console_mfn = xc_dom_p2m_host(dom, dom->console_pfn); *store_mfn = xc_dom_p2m_host(dom, dom->xenstore_pfn); - out: + out: return rc; } int xc_linux_build_mem(int xc_handle, uint32_t domid, - unsigned int mem_mb, - const char *image_buffer, - unsigned long image_size, - const char *initrd, - unsigned long initrd_len, - const char *cmdline, - const char *features, - unsigned long flags, - unsigned int store_evtchn, - unsigned long *store_mfn, - unsigned int console_evtchn, unsigned long *console_mfn) + unsigned int mem_mb, + const char *image_buffer, + unsigned long image_size, + const char *initrd, + unsigned long initrd_len, + const char *cmdline, + const char *features, + unsigned long flags, + unsigned int store_evtchn, + unsigned long *store_mfn, + unsigned int console_evtchn, unsigned long *console_mfn) { struct xc_dom_image *dom; int rc; xc_dom_loginit(); dom = xc_dom_allocate(cmdline, features); - if (0 != (rc = xc_dom_kernel_mem(dom, image_buffer, image_size))) - goto out; - if (initrd) - if (0 != (rc = xc_dom_ramdisk_mem(dom, initrd, initrd_len))) - goto out; + if ( (rc = xc_dom_kernel_mem(dom, image_buffer, image_size)) != 0 ) + goto out; + if ( initrd && ((rc = xc_dom_ramdisk_mem(dom, initrd, initrd_len)) != 0) ) + goto out; rc = xc_linux_build_internal(dom, xc_handle, domid, - mem_mb, flags, - store_evtchn, store_mfn, - console_evtchn, console_mfn); + mem_mb, flags, + store_evtchn, store_mfn, + console_evtchn, console_mfn); - out: + out: xc_dom_release(dom); return rc; } int xc_linux_build(int xc_handle, uint32_t domid, - unsigned int mem_mb, - const char *image_name, - const char *initrd_name, - const char *cmdline, - const char *features, - unsigned long flags, - unsigned int store_evtchn, - unsigned long *store_mfn, - unsigned int console_evtchn, unsigned long *console_mfn) + unsigned int mem_mb, + const char *image_name, + const char *initrd_name, + const char *cmdline, + const char *features, + unsigned long flags, + unsigned int store_evtchn, + unsigned long *store_mfn, + unsigned int console_evtchn, unsigned long *console_mfn) { struct xc_dom_image *dom; int rc; xc_dom_loginit(); dom = xc_dom_allocate(cmdline, features); - if (0 != (rc = xc_dom_kernel_file(dom, image_name))) - goto out; - if (initrd_name && strlen(initrd_name)) - if (0 != (rc = xc_dom_ramdisk_file(dom, initrd_name))) - goto out; + if ( (rc = xc_dom_kernel_file(dom, image_name)) != 0 ) + goto out; + if ( initrd_name && strlen(initrd_name) && + ((rc = xc_dom_ramdisk_file(dom, initrd_name)) != 0) ) + goto out; rc = xc_linux_build_internal(dom, xc_handle, domid, - mem_mb, flags, - store_evtchn, store_mfn, - console_evtchn, console_mfn); + mem_mb, flags, + store_evtchn, store_mfn, + console_evtchn, console_mfn); - out: + out: xc_dom_release(dom); return rc; } + +int xc_dom_linux_build(int xc_handle, + struct xc_dom_image *dom, + uint32_t domid, + unsigned int mem_mb, + const char *image_name, + const char *initrd_name, + unsigned long flags, + unsigned int store_evtchn, + unsigned long *store_mfn, + unsigned int console_evtchn, unsigned long *console_mfn) +{ + int rc; + + if ( (rc = xc_dom_kernel_file(dom, image_name)) != 0 ) + return rc; + if ( initrd_name && strlen(initrd_name) && + ((rc = xc_dom_ramdisk_file(dom, initrd_name)) != 0) ) + return rc; + + return xc_linux_build_internal(dom, xc_handle, domid, + mem_mb, flags, + store_evtchn, store_mfn, + console_evtchn, console_mfn); +} + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/tools/libxc/xc_dom_core.c b/tools/libxc/xc_dom_core.c index ae64972ed5..08d4696987 100644 --- a/tools/libxc/xc_dom_core.c +++ b/tools/libxc/xc_dom_core.c @@ -27,8 +27,8 @@ FILE *xc_dom_logfile = NULL; void xc_dom_loginit(void) { - if (xc_dom_logfile) - return; + if ( xc_dom_logfile ) + return; xc_dom_logfile = fopen("/var/log/xen/domain-builder-ng.log", "a"); setvbuf(xc_dom_logfile, NULL, _IONBF, 0); xc_dom_printf("### ----- xc domain builder logfile opened -----\n"); @@ -40,8 +40,8 @@ int xc_dom_printf(const char *fmt, ...) char buf[1024]; int rc; - if (!xc_dom_logfile) - return 0; + if ( !xc_dom_logfile ) + return 0; va_start(args, fmt); rc = vsnprintf(buf, sizeof(buf), fmt, args); @@ -52,7 +52,7 @@ int xc_dom_printf(const char *fmt, ...) } int xc_dom_panic_func(const char *file, int line, xc_error_code err, - const char *fmt, ...) + const char *fmt, ...) { va_list args; FILE *fp = stderr; @@ -60,8 +60,8 @@ int xc_dom_panic_func(const char *file, int line, xc_error_code err, char pos[256]; char msg[XC_MAX_ERROR_MSG_LEN]; - if (xc_dom_logfile) - fp = xc_dom_logfile; + if ( xc_dom_logfile ) + fp = xc_dom_logfile; snprintf(pos, sizeof(pos), "%s:%d: panic: ", file, line); va_start(args, fmt); @@ -74,12 +74,12 @@ int xc_dom_panic_func(const char *file, int line, xc_error_code err, static void print_mem(const char *name, size_t mem) { - if (mem > 32 * 1024 * 1024) - xc_dom_printf("%-24s : %zd MB\n", name, mem / (1024 * 1024)); - else if (mem > 32 * 1024) - xc_dom_printf("%-24s : %zd kB\n", name, mem / 1024); + if ( mem > (32 * 1024 * 1024) ) + xc_dom_printf("%-24s : %zd MB\n", name, mem / (1024 * 1024)); + else if ( mem > (32 * 1024) ) + xc_dom_printf("%-24s : %zd kB\n", name, mem / 1024); else - xc_dom_printf("%-24s : %zd bytes\n", name, mem); + xc_dom_printf("%-24s : %zd bytes\n", name, mem); } void xc_dom_log_memory_footprint(struct xc_dom_image *dom) @@ -101,14 +101,14 @@ void *xc_dom_malloc(struct xc_dom_image *dom, size_t size) struct xc_dom_mem *block; block = malloc(sizeof(*block) + size); - if (NULL == block) - return NULL; + if ( block == NULL ) + return NULL; memset(block, 0, sizeof(*block) + size); block->next = dom->memblocks; dom->memblocks = block; dom->alloc_malloc += sizeof(*block) + size; - if (size > 100 * 1024) - print_mem(__FUNCTION__, size); + if ( size > (100 * 1024) ) + print_mem(__FUNCTION__, size); return block->memory; } @@ -117,62 +117,63 @@ void *xc_dom_malloc_page_aligned(struct xc_dom_image *dom, size_t size) struct xc_dom_mem *block; block = malloc(sizeof(*block)); - if (NULL == block) - return NULL; + if ( block == NULL ) + return NULL; memset(block, 0, sizeof(*block)); block->mmap_len = size; block->mmap_ptr = mmap(NULL, block->mmap_len, - PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, - -1, 0); - if (MAP_FAILED == block->mmap_ptr) + PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, + -1, 0); + if ( block->mmap_ptr == MAP_FAILED ) { - free(block); - return NULL; + free(block); + return NULL; } block->next = dom->memblocks; dom->memblocks = block; dom->alloc_malloc += sizeof(*block); dom->alloc_mem_map += block->mmap_len; - if (size > 100 * 1024) - print_mem(__FUNCTION__, size); + if ( size > (100 * 1024) ) + print_mem(__FUNCTION__, size); return block->mmap_ptr; } void *xc_dom_malloc_filemap(struct xc_dom_image *dom, - const char *filename, size_t * size) + const char *filename, size_t * size) { struct xc_dom_mem *block = NULL; int fd = -1; fd = open(filename, O_RDONLY); - if (-1 == fd) - goto err; + if ( fd == -1 ) + goto err; lseek(fd, 0, SEEK_SET); *size = lseek(fd, 0, SEEK_END); block = malloc(sizeof(*block)); - if (NULL == block) - goto err; + if ( block == NULL ) + goto err; memset(block, 0, sizeof(*block)); block->mmap_len = *size; - block->mmap_ptr = mmap(NULL, block->mmap_len, PROT_READ, MAP_SHARED, fd, 0); - if (MAP_FAILED == block->mmap_ptr) - goto err; + block->mmap_ptr = mmap(NULL, block->mmap_len, PROT_READ, + MAP_SHARED, fd, 0); + if ( block->mmap_ptr == MAP_FAILED ) + goto err; block->next = dom->memblocks; dom->memblocks = block; dom->alloc_malloc += sizeof(*block); dom->alloc_file_map += block->mmap_len; close(fd); - if (*size > 100 * 1024) - print_mem(__FUNCTION__, *size); + if ( *size > (100 * 1024) ) + print_mem(__FUNCTION__, *size); return block->mmap_ptr; - err: - if (-1 != fd) - close(fd); - if (block) - free(block); + err: + if ( fd != -1 ) + close(fd); + if ( block != NULL ) + free(block); return NULL; } @@ -180,12 +181,12 @@ static void xc_dom_free_all(struct xc_dom_image *dom) { struct xc_dom_mem *block; - while (NULL != (block = dom->memblocks)) + while ( (block = dom->memblocks) != NULL ) { - dom->memblocks = block->next; - if (block->mmap_ptr) - munmap(block->mmap_ptr, block->mmap_len); - free(block); + dom->memblocks = block->next; + if ( block->mmap_ptr ) + munmap(block->mmap_ptr, block->mmap_len); + free(block); } } @@ -194,8 +195,8 @@ char *xc_dom_strdup(struct xc_dom_image *dom, const char *str) size_t len = strlen(str) + 1; char *nstr = xc_dom_malloc(dom, len); - if (NULL == nstr) - return NULL; + if ( nstr == NULL ) + return NULL; memcpy(nstr, str, len); return nstr; } @@ -208,18 +209,18 @@ size_t xc_dom_check_gzip(void *blob, size_t ziplen) unsigned char *gzlen; size_t unziplen; - if (0 != strncmp(blob, "\037\213", 2)) - /* not gzipped */ - return 0; + if (strncmp(blob, "\037\213", 2)) + /* not gzipped */ + return 0; gzlen = blob + ziplen - 4; unziplen = gzlen[3] << 24 | gzlen[2] << 16 | gzlen[1] << 8 | gzlen[0]; - if (unziplen < ziplen || unziplen > ziplen * 8) + if ( (unziplen < ziplen) || (unziplen > (ziplen * 8)) ) { - xc_dom_printf - ("%s: size (zip %zd, unzip %zd) looks insane, skip gunzip\n", - __FUNCTION__, ziplen, unziplen); - return 0; + xc_dom_printf + ("%s: size (zip %zd, unzip %zd) looks insane, skip gunzip\n", + __FUNCTION__, ziplen, unziplen); + return 0; } return unziplen + 16; @@ -235,23 +236,23 @@ int xc_dom_do_gunzip(void *src, size_t srclen, void *dst, size_t dstlen) zStream.avail_in = srclen; zStream.next_out = dst; zStream.avail_out = dstlen; - rc = inflateInit2(&zStream, (MAX_WBITS + 32)); /* +32 means "handle gzip" */ - if (rc != Z_OK) + rc = inflateInit2(&zStream, (MAX_WBITS + 32)); /* +32 means "handle gzip" */ + if ( rc != Z_OK ) { - xc_dom_panic(XC_INTERNAL_ERROR, - "%s: inflateInit2 failed (rc=%d)\n", __FUNCTION__, rc); - return -1; + xc_dom_panic(XC_INTERNAL_ERROR, + "%s: inflateInit2 failed (rc=%d)\n", __FUNCTION__, rc); + return -1; } rc = inflate(&zStream, Z_FINISH); - if (rc != Z_STREAM_END) + if ( rc != Z_STREAM_END ) { - xc_dom_panic(XC_INTERNAL_ERROR, - "%s: inflate failed (rc=%d)\n", __FUNCTION__, rc); - return -1; + xc_dom_panic(XC_INTERNAL_ERROR, + "%s: inflate failed (rc=%d)\n", __FUNCTION__, rc); + return -1; } xc_dom_printf("%s: unzip ok, 0x%zx -> 0x%zx\n", - __FUNCTION__, srclen, dstlen); + __FUNCTION__, srclen, dstlen); return 0; } @@ -261,15 +262,15 @@ int xc_dom_try_gunzip(struct xc_dom_image *dom, void **blob, size_t * size) size_t unziplen; unziplen = xc_dom_check_gzip(*blob, *size); - if (0 == unziplen) - return 0; + if ( unziplen == 0 ) + return 0; unzip = xc_dom_malloc(dom, unziplen); - if (NULL == unzip) - return -1; + if ( unzip == NULL ) + return -1; - if (-1 == xc_dom_do_gunzip(*blob, *size, unzip, unziplen)) - return -1; + if ( xc_dom_do_gunzip(*blob, *size, unzip, unziplen) == -1 ) + return -1; *blob = unzip; *size = unziplen; @@ -280,92 +281,94 @@ int xc_dom_try_gunzip(struct xc_dom_image *dom, void **blob, size_t * size) /* domain memory */ void *xc_dom_pfn_to_ptr(struct xc_dom_image *dom, xen_pfn_t pfn, - xen_pfn_t count) + xen_pfn_t count) { struct xc_dom_phys *phys; unsigned int page_shift = XC_DOM_PAGE_SHIFT(dom); char *mode = "unset"; - if (pfn > dom->total_pages) + if ( pfn > dom->total_pages ) { - xc_dom_printf("%s: pfn out of range (0x%" PRIpfn " > 0x%" PRIpfn ")\n", - __FUNCTION__, pfn, dom->total_pages); - return NULL; + xc_dom_printf("%s: pfn out of range (0x%" PRIpfn " > 0x%" PRIpfn ")\n", + __FUNCTION__, pfn, dom->total_pages); + return NULL; } /* already allocated? */ - for (phys = dom->phys_pages; NULL != phys; phys = phys->next) + for ( phys = dom->phys_pages; phys != NULL; phys = phys->next ) { - if (pfn >= phys->first + phys->count) - continue; - if (count) - { - /* size given: must be completely within the already allocated block */ - if (pfn + count <= phys->first) - continue; - if (pfn < phys->first || pfn + count > phys->first + phys->count) - { - xc_dom_printf("%s: request overlaps allocated block" - " (req 0x%" PRIpfn "+0x%" PRIpfn "," - " blk 0x%" PRIpfn "+0x%" PRIpfn ")\n", - __FUNCTION__, pfn, count, phys->first, - phys->count); - return NULL; - } - } - else - { - /* no size given: block must be allocated already, - just hand out a pointer to it */ - if (pfn < phys->first) - continue; - } - return phys->ptr + ((pfn - phys->first) << page_shift); + if ( pfn >= (phys->first + phys->count) ) + continue; + if ( count ) + { + /* size given: must be completely within the already allocated block */ + if ( (pfn + count) <= phys->first ) + continue; + if ( (pfn < phys->first) || + ((pfn + count) > (phys->first + phys->count)) ) + { + xc_dom_printf("%s: request overlaps allocated block" + " (req 0x%" PRIpfn "+0x%" PRIpfn "," + " blk 0x%" PRIpfn "+0x%" PRIpfn ")\n", + __FUNCTION__, pfn, count, phys->first, + phys->count); + return NULL; + } + } + else + { + /* no size given: block must be allocated already, + just hand out a pointer to it */ + if ( pfn < phys->first ) + continue; + } + return phys->ptr + ((pfn - phys->first) << page_shift); } /* allocating is allowed with size specified only */ - if (0 == count) + if ( count == 0 ) { - xc_dom_printf("%s: no block found, no size given," - " can't malloc (pfn 0x%" PRIpfn ")\n", __FUNCTION__, pfn); - return NULL; + xc_dom_printf("%s: no block found, no size given," + " can't malloc (pfn 0x%" PRIpfn ")\n", + __FUNCTION__, pfn); + return NULL; } /* not found, no overlap => allocate */ phys = xc_dom_malloc(dom, sizeof(*phys)); - if (NULL == phys) - return NULL; + if ( phys == NULL ) + return NULL; memset(phys, 0, sizeof(*phys)); phys->first = pfn; phys->count = count; - if (dom->guest_domid) + if ( dom->guest_domid ) { - mode = "domU mapping"; - phys->ptr = xc_dom_boot_domU_map(dom, phys->first, phys->count); - if (NULL == phys->ptr) - return NULL; - dom->alloc_domU_map += phys->count << page_shift; + mode = "domU mapping"; + phys->ptr = xc_dom_boot_domU_map(dom, phys->first, phys->count); + if ( phys->ptr == NULL ) + return NULL; + dom->alloc_domU_map += phys->count << page_shift; } else { - mode = "anonymous memory"; - phys->ptr = mmap(NULL, phys->count << page_shift, - PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, - -1, 0); - if (MAP_FAILED == phys->ptr) - { - xc_dom_panic(XC_OUT_OF_MEMORY, - "%s: oom: can't allocate 0x%" PRIpfn " pages\n", - __FUNCTION__, count); - return NULL; - } - dom->alloc_mem_map += phys->count << page_shift; + mode = "anonymous memory"; + phys->ptr = mmap(NULL, phys->count << page_shift, + PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, + -1, 0); + if ( phys->ptr == MAP_FAILED ) + { + xc_dom_panic(XC_OUT_OF_MEMORY, + "%s: oom: can't allocate 0x%" PRIpfn " pages\n", + __FUNCTION__, count); + return NULL; + } + dom->alloc_mem_map += phys->count << page_shift; } #if 1 xc_dom_printf("%s: %s: pfn 0x%" PRIpfn "+0x%" PRIpfn " at %p\n", - __FUNCTION__, mode, phys->first, phys->count, phys->ptr); + __FUNCTION__, mode, phys->first, phys->count, phys->ptr); #endif phys->next = dom->phys_pages; dom->phys_pages = phys; @@ -373,29 +376,29 @@ void *xc_dom_pfn_to_ptr(struct xc_dom_image *dom, xen_pfn_t pfn, } int xc_dom_alloc_segment(struct xc_dom_image *dom, - struct xc_dom_seg *seg, char *name, - xen_vaddr_t start, xen_vaddr_t size) + struct xc_dom_seg *seg, char *name, + xen_vaddr_t start, xen_vaddr_t size) { unsigned int page_size = XC_DOM_PAGE_SIZE(dom); xen_pfn_t pages = (size + page_size - 1) / page_size; void *ptr; - if (0 == start) - start = dom->virt_alloc_end; + if ( start == 0 ) + start = dom->virt_alloc_end; - if (start & (page_size - 1)) + if ( start & (page_size - 1) ) { - xc_dom_panic(XC_INTERNAL_ERROR, - "%s: segment start isn't page aligned (0x%" PRIx64 ")\n", - __FUNCTION__, start); - return -1; + xc_dom_panic(XC_INTERNAL_ERROR, + "%s: segment start isn't page aligned (0x%" PRIx64 ")\n", + __FUNCTION__, start); + return -1; } - if (start < dom->virt_alloc_end) + if ( start < dom->virt_alloc_end ) { - xc_dom_panic(XC_INTERNAL_ERROR, - "%s: segment start too low (0x%" PRIx64 " < 0x%" PRIx64 - ")\n", __FUNCTION__, start, dom->virt_alloc_end); - return -1; + xc_dom_panic(XC_INTERNAL_ERROR, + "%s: segment start too low (0x%" PRIx64 " < 0x%" PRIx64 + ")\n", __FUNCTION__, start, dom->virt_alloc_end); + return -1; } seg->vstart = start; @@ -404,13 +407,13 @@ int xc_dom_alloc_segment(struct xc_dom_image *dom, dom->virt_alloc_end = seg->vend; xc_dom_printf("%-20s: %-12s : 0x%" PRIx64 " -> 0x%" PRIx64 - " (pfn 0x%" PRIpfn " + 0x%" PRIpfn " pages)\n", - __FUNCTION__, name, seg->vstart, seg->vend, seg->pfn, pages); + " (pfn 0x%" PRIpfn " + 0x%" PRIpfn " pages)\n", + __FUNCTION__, name, seg->vstart, seg->vend, seg->pfn, pages); /* map and clear pages */ ptr = xc_dom_seg_to_ptr(dom, seg); - if (NULL == ptr) - return -1; + if ( ptr == NULL ) + return -1; memset(ptr, 0, pages * page_size); return 0; @@ -427,7 +430,7 @@ int xc_dom_alloc_page(struct xc_dom_image *dom, char *name) pfn = (start - dom->parms.virt_base) / page_size; xc_dom_printf("%-20s: %-12s : 0x%" PRIx64 " (pfn 0x%" PRIpfn ")\n", - __FUNCTION__, name, start, pfn); + __FUNCTION__, name, start, pfn); return pfn; } @@ -436,30 +439,30 @@ void xc_dom_unmap_one(struct xc_dom_image *dom, xen_pfn_t pfn) unsigned int page_shift = XC_DOM_PAGE_SHIFT(dom); struct xc_dom_phys *phys, *prev = NULL; - for (phys = dom->phys_pages; NULL != phys; phys = phys->next) + for ( phys = dom->phys_pages; phys != NULL; phys = phys->next ) { - if (pfn >= phys->first && pfn < phys->first + phys->count) - break; - prev = phys; + if ( (pfn >= phys->first) && (pfn < (phys->first + phys->count)) ) + break; + prev = phys; } - if (!phys) + if ( !phys ) { - xc_dom_printf("%s: Huh? no mapping with pfn 0x%" PRIpfn "\n", - __FUNCTION__, pfn); - return; + xc_dom_printf("%s: Huh? no mapping with pfn 0x%" PRIpfn "\n", + __FUNCTION__, pfn); + return; } munmap(phys->ptr, phys->count << page_shift); - if (prev) - prev->next = phys->next; + if ( prev ) + prev->next = phys->next; else - dom->phys_pages = phys->next; + dom->phys_pages = phys->next; } void xc_dom_unmap_all(struct xc_dom_image *dom) { - while (dom->phys_pages) - xc_dom_unmap_one(dom, dom->phys_pages->first); + while ( dom->phys_pages ) + xc_dom_unmap_one(dom, dom->phys_pages->first); } /* ------------------------------------------------------------------------ */ @@ -478,16 +481,16 @@ static struct xc_dom_loader *xc_dom_find_loader(struct xc_dom_image *dom) { struct xc_dom_loader *loader = first_loader; - while (NULL != loader) + while ( loader != NULL ) { - xc_dom_printf("%s: trying %s loader ... ", __FUNCTION__, loader->name); - if (0 == loader->probe(dom)) - { - xc_dom_printf("OK\n"); - return loader; - } - xc_dom_printf("failed\n"); - loader = loader->next; + xc_dom_printf("%s: trying %s loader ... ", __FUNCTION__, loader->name); + if ( loader->probe(dom) == 0 ) + { + xc_dom_printf("OK\n"); + return loader; + } + xc_dom_printf("failed\n"); + loader = loader->next; } xc_dom_panic(XC_INVALID_KERNEL, "%s: no loader found\n", __FUNCTION__); return NULL; @@ -503,14 +506,14 @@ static struct xc_dom_arch *xc_dom_find_arch_hooks(char *guest_type) { struct xc_dom_arch *hooks = first_hook; - while (NULL != hooks) + while ( hooks != NULL ) { - if (0 == strcmp(hooks->guest_type, guest_type)) - return hooks; - hooks = hooks->next; + if ( !strcmp(hooks->guest_type, guest_type)) + return hooks; + hooks = hooks->next; } xc_dom_panic(XC_INVALID_KERNEL, - "%s: not found (type %s)\n", __FUNCTION__, guest_type); + "%s: not found (type %s)\n", __FUNCTION__, guest_type); return NULL; } @@ -520,8 +523,8 @@ static struct xc_dom_arch *xc_dom_find_arch_hooks(char *guest_type) void xc_dom_release(struct xc_dom_image *dom) { xc_dom_printf("%s: called\n", __FUNCTION__); - if (dom->phys_pages) - xc_dom_unmap_all(dom); + if ( dom->phys_pages ) + xc_dom_unmap_all(dom); xc_dom_free_all(dom); free(dom); } @@ -531,16 +534,16 @@ struct xc_dom_image *xc_dom_allocate(const char *cmdline, const char *features) struct xc_dom_image *dom; xc_dom_printf("%s: cmdline=\"%s\", features=\"%s\"\n", - __FUNCTION__, cmdline, features); + __FUNCTION__, cmdline, features); dom = malloc(sizeof(*dom)); - if (!dom) - goto err; + if ( !dom ) + goto err; memset(dom, 0, sizeof(*dom)); - if (cmdline) - dom->cmdline = xc_dom_strdup(dom, cmdline); - if (features) - elf_xen_parse_features(features, dom->f_requested, NULL); + if ( cmdline ) + dom->cmdline = xc_dom_strdup(dom, cmdline); + if ( features ) + elf_xen_parse_features(features, dom->f_requested, NULL); dom->parms.virt_base = UNSET_ADDR; dom->parms.virt_entry = UNSET_ADDR; @@ -551,9 +554,9 @@ struct xc_dom_image *xc_dom_allocate(const char *cmdline, const char *features) dom->alloc_malloc += sizeof(*dom); return dom; - err: - if (dom) - xc_dom_release(dom); + err: + if ( dom ) + xc_dom_release(dom); return NULL; } @@ -561,8 +564,8 @@ int xc_dom_kernel_file(struct xc_dom_image *dom, const char *filename) { xc_dom_printf("%s: filename=\"%s\"\n", __FUNCTION__, filename); dom->kernel_blob = xc_dom_malloc_filemap(dom, filename, &dom->kernel_size); - if (NULL == dom->kernel_blob) - return -1; + if ( dom->kernel_blob == NULL ) + return -1; return xc_dom_try_gunzip(dom, &dom->kernel_blob, &dom->kernel_size); } @@ -570,9 +573,9 @@ int xc_dom_ramdisk_file(struct xc_dom_image *dom, const char *filename) { xc_dom_printf("%s: filename=\"%s\"\n", __FUNCTION__, filename); dom->ramdisk_blob = - xc_dom_malloc_filemap(dom, filename, &dom->ramdisk_size); - if (NULL == dom->ramdisk_blob) - return -1; + xc_dom_malloc_filemap(dom, filename, &dom->ramdisk_size); + if ( dom->ramdisk_blob == NULL ) + return -1; // return xc_dom_try_gunzip(dom, &dom->ramdisk_blob, &dom->ramdisk_size); return 0; } @@ -586,7 +589,7 @@ int xc_dom_kernel_mem(struct xc_dom_image *dom, const void *mem, size_t memsize) } int xc_dom_ramdisk_mem(struct xc_dom_image *dom, const void *mem, - size_t memsize) + size_t memsize) { xc_dom_printf("%s: called\n", __FUNCTION__); dom->ramdisk_blob = (void *)mem; @@ -603,32 +606,33 @@ int xc_dom_parse_image(struct xc_dom_image *dom) /* parse kernel image */ dom->kernel_loader = xc_dom_find_loader(dom); - if (NULL == dom->kernel_loader) - goto err; - if (0 != dom->kernel_loader->parser(dom)) - goto err; - if (NULL == dom->guest_type) + if ( dom->kernel_loader == NULL ) + goto err; + if ( dom->kernel_loader->parser(dom) != 0 ) + goto err; + if ( dom->guest_type == NULL ) { - xc_dom_panic(XC_INTERNAL_ERROR, - "%s: guest_type not set\n", __FUNCTION__); - goto err; + xc_dom_panic(XC_INTERNAL_ERROR, + "%s: guest_type not set\n", __FUNCTION__); + goto err; } /* check features */ - for (i = 0; i < XENFEAT_NR_SUBMAPS; i++) + for ( i = 0; i < XENFEAT_NR_SUBMAPS; i++ ) { - dom->f_active[i] |= dom->f_requested[i]; /* cmd line */ - dom->f_active[i] |= dom->parms.f_required[i]; /* kernel */ - if ((dom->f_active[i] & dom->parms.f_supported[i]) != dom->f_active[i]) - { - xc_dom_panic(XC_INVALID_PARAM, - "%s: unsupported feature requested\n", __FUNCTION__); - goto err; - } + dom->f_active[i] |= dom->f_requested[i]; /* cmd line */ + dom->f_active[i] |= dom->parms.f_required[i]; /* kernel */ + if ( (dom->f_active[i] & dom->parms.f_supported[i]) != + dom->f_active[i] ) + { + xc_dom_panic(XC_INVALID_PARAM, + "%s: unsupported feature requested\n", __FUNCTION__); + goto err; + } } return 0; - err: + err: return -1; } @@ -638,27 +642,27 @@ int xc_dom_mem_init(struct xc_dom_image *dom, unsigned int mem_mb) xen_pfn_t nr_pages, pfn; dom->arch_hooks = xc_dom_find_arch_hooks(dom->guest_type); - if (NULL == dom->arch_hooks) + if ( dom->arch_hooks == NULL ) { - xc_dom_panic(XC_INTERNAL_ERROR, "%s: arch hooks not set\n", - __FUNCTION__); - return -1; + xc_dom_panic(XC_INTERNAL_ERROR, "%s: arch hooks not set\n", + __FUNCTION__); + return -1; } page_shift = XC_DOM_PAGE_SHIFT(dom); nr_pages = mem_mb << (20 - page_shift); xc_dom_printf("%s: mem %d MB, pages 0x%" PRIpfn " pages, %dk each\n", - __FUNCTION__, mem_mb, nr_pages, 1 << (page_shift-10)); + __FUNCTION__, mem_mb, nr_pages, 1 << (page_shift-10)); dom->total_pages = nr_pages; xc_dom_printf("%s: 0x%" PRIpfn " pages\n", - __FUNCTION__, dom->total_pages); + __FUNCTION__, dom->total_pages); /* setup initial p2m */ dom->p2m_host = xc_dom_malloc(dom, sizeof(xen_pfn_t) * dom->total_pages); - for (pfn = 0; pfn < dom->total_pages; pfn++) - dom->p2m_host[pfn] = pfn; + for ( pfn = 0; pfn < dom->total_pages; pfn++ ) + dom->p2m_host[pfn] = pfn; return 0; } @@ -668,36 +672,36 @@ int xc_dom_update_guest_p2m(struct xc_dom_image *dom) uint64_t *p2m_64; xen_pfn_t i; - if (!dom->p2m_guest) - return 0; + if ( !dom->p2m_guest ) + return 0; - switch (dom->arch_hooks->sizeof_pfn) + switch ( dom->arch_hooks->sizeof_pfn ) { case 4: - xc_dom_printf("%s: dst 32bit, pages 0x%" PRIpfn " \n", - __FUNCTION__, dom->total_pages); - p2m_32 = dom->p2m_guest; - for (i = 0; i < dom->total_pages; i++) - if (INVALID_P2M_ENTRY != dom->p2m_host[i]) - p2m_32[i] = dom->p2m_host[i]; - else - p2m_32[i] = (uint32_t) - 1; - break; + xc_dom_printf("%s: dst 32bit, pages 0x%" PRIpfn " \n", + __FUNCTION__, dom->total_pages); + p2m_32 = dom->p2m_guest; + for ( i = 0; i < dom->total_pages; i++ ) + if ( dom->p2m_host[i] != INVALID_P2M_ENTRY ) + p2m_32[i] = dom->p2m_host[i]; + else + p2m_32[i] = (uint32_t) - 1; + break; case 8: - xc_dom_printf("%s: dst 64bit, pages 0x%" PRIpfn " \n", - __FUNCTION__, dom->total_pages); - p2m_64 = dom->p2m_guest; - for (i = 0; i < dom->total_pages; i++) - if (INVALID_P2M_ENTRY != dom->p2m_host[i]) - p2m_64[i] = dom->p2m_host[i]; - else - p2m_64[i] = (uint64_t) - 1; - break; + xc_dom_printf("%s: dst 64bit, pages 0x%" PRIpfn " \n", + __FUNCTION__, dom->total_pages); + p2m_64 = dom->p2m_guest; + for ( i = 0; i < dom->total_pages; i++ ) + if ( dom->p2m_host[i] != INVALID_P2M_ENTRY ) + p2m_64[i] = dom->p2m_host[i]; + else + p2m_64[i] = (uint64_t) - 1; + break; default: - xc_dom_panic(XC_INTERNAL_ERROR, - "sizeof_pfn is invalid (is %d, can be 4 or 8)", - dom->arch_hooks->sizeof_pfn); - return -1; + xc_dom_panic(XC_INTERNAL_ERROR, + "sizeof_pfn is invalid (is %d, can be 4 or 8)", + dom->arch_hooks->sizeof_pfn); + return -1; } return 0; } @@ -709,68 +713,74 @@ int xc_dom_build_image(struct xc_dom_image *dom) xc_dom_printf("%s: called\n", __FUNCTION__); /* check for arch hooks */ - if (NULL == dom->arch_hooks) + if ( dom->arch_hooks == NULL ) { - xc_dom_panic(XC_INTERNAL_ERROR, "%s: arch hooks not set\n", - __FUNCTION__); - goto err; + xc_dom_panic(XC_INTERNAL_ERROR, "%s: arch hooks not set\n", + __FUNCTION__); + goto err; } page_size = XC_DOM_PAGE_SIZE(dom); - /* 4MB align virtual base address */ - dom->parms.virt_base &= ~(((uint64_t)1<<22)-1); - /* load kernel */ - if (0 != xc_dom_alloc_segment(dom, &dom->kernel_seg, "kernel", - dom->kernel_seg.vstart, - dom->kernel_seg.vend - - dom->kernel_seg.vstart)) - goto err; - if (0 != dom->kernel_loader->loader(dom)) - goto err; + if ( xc_dom_alloc_segment(dom, &dom->kernel_seg, "kernel", + dom->kernel_seg.vstart, + dom->kernel_seg.vend - + dom->kernel_seg.vstart) != 0 ) + goto err; + if ( dom->kernel_loader->loader(dom) != 0 ) + goto err; /* load ramdisk */ - if (dom->ramdisk_blob) + if ( dom->ramdisk_blob ) { - size_t unziplen, ramdisklen; - void *ramdiskmap; + size_t unziplen, ramdisklen; + void *ramdiskmap; - unziplen = xc_dom_check_gzip(dom->ramdisk_blob, dom->ramdisk_size); - ramdisklen = unziplen ? unziplen : dom->ramdisk_size; - if (0 != xc_dom_alloc_segment(dom, &dom->ramdisk_seg, "ramdisk", 0, - ramdisklen)) - goto err; - ramdiskmap = xc_dom_seg_to_ptr(dom, &dom->ramdisk_seg); - if (unziplen) - { - if (-1 == xc_dom_do_gunzip(dom->ramdisk_blob, dom->ramdisk_size, - ramdiskmap, ramdisklen)) - goto err; - } - else - memcpy(ramdiskmap, dom->ramdisk_blob, dom->ramdisk_size); + unziplen = xc_dom_check_gzip(dom->ramdisk_blob, dom->ramdisk_size); + ramdisklen = unziplen ? unziplen : dom->ramdisk_size; + if ( xc_dom_alloc_segment(dom, &dom->ramdisk_seg, "ramdisk", 0, + ramdisklen) != 0 ) + goto err; + ramdiskmap = xc_dom_seg_to_ptr(dom, &dom->ramdisk_seg); + if ( unziplen ) + { + if ( xc_dom_do_gunzip(dom->ramdisk_blob, dom->ramdisk_size, + ramdiskmap, ramdisklen) == -1 ) + goto err; + } + else + memcpy(ramdiskmap, dom->ramdisk_blob, dom->ramdisk_size); } /* allocate other pages */ - if (0 != dom->arch_hooks->alloc_magic_pages(dom)) - goto err; - if (dom->arch_hooks->count_pgtables) + if ( dom->arch_hooks->alloc_magic_pages(dom) != 0 ) + goto err; + if ( dom->arch_hooks->count_pgtables ) { - dom->arch_hooks->count_pgtables(dom); - if (dom->pgtables > 0) - if (0 != - xc_dom_alloc_segment(dom, &dom->pgtables_seg, "page tables", 0, - dom->pgtables * page_size)) - goto err; + dom->arch_hooks->count_pgtables(dom); + if ( (dom->pgtables > 0) && + (xc_dom_alloc_segment(dom, &dom->pgtables_seg, "page tables", 0, + dom->pgtables * page_size) != 0) ) + goto err; } - if (dom->alloc_bootstack) - dom->bootstack_pfn = xc_dom_alloc_page(dom, "boot stack"); + if ( dom->alloc_bootstack ) + dom->bootstack_pfn = xc_dom_alloc_page(dom, "boot stack"); xc_dom_printf("%-20s: virt_alloc_end : 0x%" PRIx64 "\n", - __FUNCTION__, dom->virt_alloc_end); + __FUNCTION__, dom->virt_alloc_end); xc_dom_printf("%-20s: virt_pgtab_end : 0x%" PRIx64 "\n", - __FUNCTION__, dom->virt_pgtab_end); + __FUNCTION__, dom->virt_pgtab_end); return 0; - err: + err: return -1; } + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/tools/libxc/xc_dom_elfloader.c b/tools/libxc/xc_dom_elfloader.c index acb469ecec..c34c24d08a 100644 --- a/tools/libxc/xc_dom_elfloader.c +++ b/tools/libxc/xc_dom_elfloader.c @@ -19,33 +19,34 @@ /* ------------------------------------------------------------------------ */ static char *xc_dom_guest_type(struct xc_dom_image *dom, - struct elf_binary *elf) + struct elf_binary *elf) { uint64_t machine = elf_uval(elf, elf->ehdr, e_machine); - switch (machine) { + switch ( machine ) + { case EM_386: - switch (dom->parms.pae) { - case 3 /* PAEKERN_bimodal */: - if (strstr(dom->xen_caps, "xen-3.0-x86_32p")) - return "xen-3.0-x86_32p"; - return "xen-3.0-x86_32"; - case PAEKERN_extended_cr3: - case PAEKERN_yes: - return "xen-3.0-x86_32p"; - break; - case PAEKERN_no: - default: - return "xen-3.0-x86_32"; - } + switch ( dom->parms.pae ) + { + case 3 /* PAEKERN_bimodal */: + if ( strstr(dom->xen_caps, "xen-3.0-x86_32p") ) + return "xen-3.0-x86_32p"; + return "xen-3.0-x86_32"; + case PAEKERN_extended_cr3: + case PAEKERN_yes: + return "xen-3.0-x86_32p"; + case PAEKERN_no: + default: + return "xen-3.0-x86_32"; + } case EM_X86_64: - return "xen-3.0-x86_64"; + return "xen-3.0-x86_64"; case EM_IA_64: - return elf_msb(elf) ? "xen-3.0-ia64be" : "xen-3.0-ia64"; + return elf_msb(elf) ? "xen-3.0-ia64be" : "xen-3.0-ia64"; case EM_PPC64: - return "xen-3.0-powerpc64"; + return "xen-3.0-powerpc64"; default: - return "xen-3.0-unknown"; + return "xen-3.0-unknown"; } } @@ -54,20 +55,20 @@ static char *xc_dom_guest_type(struct xc_dom_image *dom, static int check_elf_kernel(struct xc_dom_image *dom, int verbose) { - if (NULL == dom->kernel_blob) + if ( dom->kernel_blob == NULL ) { - if (verbose) - xc_dom_panic(XC_INTERNAL_ERROR, "%s: no kernel image loaded\n", - __FUNCTION__); - return -EINVAL; + if ( verbose ) + xc_dom_panic(XC_INTERNAL_ERROR, "%s: no kernel image loaded\n", + __FUNCTION__); + return -EINVAL; } - if (!elf_is_elfbinary(dom->kernel_blob)) + if ( !elf_is_elfbinary(dom->kernel_blob) ) { - if (verbose) - xc_dom_panic(XC_INVALID_KERNEL, "%s: kernel is not an ELF image\n", - __FUNCTION__); - return -EINVAL; + if ( verbose ) + xc_dom_panic(XC_INVALID_KERNEL, "%s: kernel is not an ELF image\n", + __FUNCTION__); + return -EINVAL; } return 0; } @@ -78,7 +79,7 @@ static int xc_dom_probe_elf_kernel(struct xc_dom_image *dom) } static int xc_dom_load_elf_symtab(struct xc_dom_image *dom, - struct elf_binary *elf, int load) + struct elf_binary *elf, int load) { struct elf_binary syms; const elf_shdr *shdr, *shdr2; @@ -87,125 +88,135 @@ static int xc_dom_load_elf_symtab(struct xc_dom_image *dom, size_t size; int h, count, type, i, tables = 0; - if (elf_swap(elf)) { - xc_dom_printf("%s: non-native byte order, bsd symtab not supported\n", - __FUNCTION__); - return 0; + if ( elf_swap(elf) ) + { + xc_dom_printf("%s: non-native byte order, bsd symtab not supported\n", + __FUNCTION__); + return 0; } - if (load) { - if (!dom->bsd_symtab_start) - return 0; - size = dom->kernel_seg.vend - dom->bsd_symtab_start; - hdr = xc_dom_vaddr_to_ptr(dom, dom->bsd_symtab_start); - *(int *)hdr = size - sizeof(int); - } else { - size = sizeof(int) + elf_size(elf, elf->ehdr) + - elf_shdr_count(elf) * elf_size(elf, shdr); - hdr = xc_dom_malloc(dom, size); - if (hdr == NULL) - return 0; - dom->bsd_symtab_start = elf_round_up(&syms, dom->kernel_seg.vend); + if ( load ) + { + if ( !dom->bsd_symtab_start ) + return 0; + size = dom->kernel_seg.vend - dom->bsd_symtab_start; + hdr = xc_dom_vaddr_to_ptr(dom, dom->bsd_symtab_start); + *(int *)hdr = size - sizeof(int); + } + else + { + size = sizeof(int) + elf_size(elf, elf->ehdr) + + elf_shdr_count(elf) * elf_size(elf, shdr); + hdr = xc_dom_malloc(dom, size); + if ( hdr == NULL ) + return 0; + dom->bsd_symtab_start = elf_round_up(&syms, dom->kernel_seg.vend); } memcpy(hdr + sizeof(int), - elf->image, - elf_size(elf, elf->ehdr)); + elf->image, + elf_size(elf, elf->ehdr)); memcpy(hdr + sizeof(int) + elf_size(elf, elf->ehdr), - elf->image + elf_uval(elf, elf->ehdr, e_shoff), - elf_shdr_count(elf) * elf_size(elf, shdr)); - if (elf_64bit(elf)) { - Elf64_Ehdr *ehdr = (Elf64_Ehdr *)(hdr + sizeof(int)); - ehdr->e_phoff = 0; - ehdr->e_phentsize = 0; - ehdr->e_phnum = 0; - ehdr->e_shoff = elf_size(elf, elf->ehdr); - ehdr->e_shstrndx = SHN_UNDEF; - } else { - Elf32_Ehdr *ehdr = (Elf32_Ehdr *)(hdr + sizeof(int)); - ehdr->e_phoff = 0; - ehdr->e_phentsize = 0; - ehdr->e_phnum = 0; - ehdr->e_shoff = elf_size(elf, elf->ehdr); - ehdr->e_shstrndx = SHN_UNDEF; + elf->image + elf_uval(elf, elf->ehdr, e_shoff), + elf_shdr_count(elf) * elf_size(elf, shdr)); + if ( elf_64bit(elf) ) + { + Elf64_Ehdr *ehdr = (Elf64_Ehdr *)(hdr + sizeof(int)); + ehdr->e_phoff = 0; + ehdr->e_phentsize = 0; + ehdr->e_phnum = 0; + ehdr->e_shoff = elf_size(elf, elf->ehdr); + ehdr->e_shstrndx = SHN_UNDEF; } - if (0 != elf_init(&syms, hdr + sizeof(int), size - sizeof(int))) - return -1; - if (xc_dom_logfile) - elf_set_logfile(&syms, xc_dom_logfile, 1); + else + { + Elf32_Ehdr *ehdr = (Elf32_Ehdr *)(hdr + sizeof(int)); + ehdr->e_phoff = 0; + ehdr->e_phentsize = 0; + ehdr->e_phnum = 0; + ehdr->e_shoff = elf_size(elf, elf->ehdr); + ehdr->e_shstrndx = SHN_UNDEF; + } + if ( elf_init(&syms, hdr + sizeof(int), size - sizeof(int)) ) + return -1; + if ( xc_dom_logfile ) + elf_set_logfile(&syms, xc_dom_logfile, 1); symtab = dom->bsd_symtab_start + sizeof(int); maxaddr = elf_round_up(&syms, symtab + elf_size(&syms, syms.ehdr) + - elf_shdr_count(&syms) * elf_size(&syms, shdr)); + elf_shdr_count(&syms) * elf_size(&syms, shdr)); xc_dom_printf("%s/%s: bsd_symtab_start=%" PRIx64 ", kernel.end=0x%" PRIx64 - " -- symtab=0x%" PRIx64 ", maxaddr=0x%" PRIx64 "\n", - __FUNCTION__, load ? "load" : "parse", - dom->bsd_symtab_start, dom->kernel_seg.vend, symtab, maxaddr); + " -- symtab=0x%" PRIx64 ", maxaddr=0x%" PRIx64 "\n", + __FUNCTION__, load ? "load" : "parse", + dom->bsd_symtab_start, dom->kernel_seg.vend, + symtab, maxaddr); count = elf_shdr_count(&syms); - for (h = 0; h < count; h++) + for ( h = 0; h < count; h++ ) { - shdr = elf_shdr_by_index(&syms, h); - type = elf_uval(&syms, shdr, sh_type); - if (type == SHT_STRTAB) - { - /* Look for a strtab @i linked to symtab @h. */ - for (i = 0; i < count; i++) { - shdr2 = elf_shdr_by_index(&syms, i); - if ((elf_uval(&syms, shdr2, sh_type) == SHT_SYMTAB) && - (elf_uval(&syms, shdr2, sh_link) == h)) - break; - } - /* Skip symtab @h if we found no corresponding strtab @i. */ - if (i == count) - { - if (elf_64bit(&syms)) - *(Elf64_Off*)(&shdr->e64.sh_offset) = 0; - else - *(Elf32_Off*)(&shdr->e32.sh_offset) = 0; - continue; - } - } + shdr = elf_shdr_by_index(&syms, h); + type = elf_uval(&syms, shdr, sh_type); + if ( type == SHT_STRTAB ) + { + /* Look for a strtab @i linked to symtab @h. */ + for ( i = 0; i < count; i++ ) + { + shdr2 = elf_shdr_by_index(&syms, i); + if ( (elf_uval(&syms, shdr2, sh_type) == SHT_SYMTAB) && + (elf_uval(&syms, shdr2, sh_link) == h) ) + break; + } + /* Skip symtab @h if we found no corresponding strtab @i. */ + if ( i == count ) + { + if ( elf_64bit(&syms) ) + *(Elf64_Off*)(&shdr->e64.sh_offset) = 0; + else + *(Elf32_Off*)(&shdr->e32.sh_offset) = 0; + continue; + } + } - if ((type == SHT_STRTAB) || (type == SHT_SYMTAB)) - { - /* Mangled to be based on ELF header location. */ - if (elf_64bit(&syms)) - *(Elf64_Off*)(&shdr->e64.sh_offset) = maxaddr - symtab; - else - *(Elf32_Off*)(&shdr->e32.sh_offset) = maxaddr - symtab; - size = elf_uval(&syms, shdr, sh_size); - maxaddr = elf_round_up(&syms, maxaddr + size); - tables++; - xc_dom_printf("%s: h=%d %s, size=0x%zx, maxaddr=0x%" PRIx64 "\n", - __FUNCTION__, h, - type == SHT_SYMTAB ? "symtab" : "strtab", - size, maxaddr); + if ( (type == SHT_STRTAB) || (type == SHT_SYMTAB) ) + { + /* Mangled to be based on ELF header location. */ + if ( elf_64bit(&syms) ) + *(Elf64_Off*)(&shdr->e64.sh_offset) = maxaddr - symtab; + else + *(Elf32_Off*)(&shdr->e32.sh_offset) = maxaddr - symtab; + size = elf_uval(&syms, shdr, sh_size); + maxaddr = elf_round_up(&syms, maxaddr + size); + tables++; + xc_dom_printf("%s: h=%d %s, size=0x%zx, maxaddr=0x%" PRIx64 "\n", + __FUNCTION__, h, + type == SHT_SYMTAB ? "symtab" : "strtab", + size, maxaddr); - if (load) { - shdr2 = elf_shdr_by_index(elf, h); - memcpy((void*)elf_section_start(&syms, shdr), - elf_section_start(elf, shdr2), - size); - } - } + if ( load ) + { + shdr2 = elf_shdr_by_index(elf, h); + memcpy((void*)elf_section_start(&syms, shdr), + elf_section_start(elf, shdr2), + size); + } + } - /* Name is NULL. */ - if (elf_64bit(&syms)) - *(Elf64_Half*)(&shdr->e64.sh_name) = 0; - else - *(Elf32_Word*)(&shdr->e32.sh_name) = 0; + /* Name is NULL. */ + if ( elf_64bit(&syms) ) + *(Elf64_Half*)(&shdr->e64.sh_name) = 0; + else + *(Elf32_Word*)(&shdr->e32.sh_name) = 0; } - if (0 == tables) + if ( tables == 0 ) { - xc_dom_printf("%s: no symbol table present\n", __FUNCTION__); - dom->bsd_symtab_start = 0; - return 0; + xc_dom_printf("%s: no symbol table present\n", __FUNCTION__); + dom->bsd_symtab_start = 0; + return 0; } - if (!load) - dom->kernel_seg.vend = maxaddr; + if ( !load ) + dom->kernel_seg.vend = maxaddr; return 0; } @@ -215,45 +226,45 @@ static int xc_dom_parse_elf_kernel(struct xc_dom_image *dom) int rc; rc = check_elf_kernel(dom, 1); - if (0 != rc) - return rc; + if ( rc != 0 ) + return rc; elf = xc_dom_malloc(dom, sizeof(*elf)); dom->private_loader = elf; rc = elf_init(elf, dom->kernel_blob, dom->kernel_size); - if (xc_dom_logfile) - elf_set_logfile(elf, xc_dom_logfile, 1); - if (0 != rc) + if ( xc_dom_logfile ) + elf_set_logfile(elf, xc_dom_logfile, 1); + if ( rc != 0 ) { - xc_dom_panic(XC_INVALID_KERNEL, "%s: corrupted ELF image\n", - __FUNCTION__); - return rc; + xc_dom_panic(XC_INVALID_KERNEL, "%s: corrupted ELF image\n", + __FUNCTION__); + return rc; } /* Find the section-header strings table. */ - if (NULL == elf->sec_strtab) + if ( elf->sec_strtab == NULL ) { - xc_dom_panic(XC_INVALID_KERNEL, "%s: ELF image has no shstrtab\n", - __FUNCTION__); - return -EINVAL; + xc_dom_panic(XC_INVALID_KERNEL, "%s: ELF image has no shstrtab\n", + __FUNCTION__); + return -EINVAL; } /* parse binary and get xen meta info */ elf_parse_binary(elf); - if (0 != (rc = elf_xen_parse(elf, &dom->parms))) - return rc; + if ( (rc = elf_xen_parse(elf, &dom->parms)) != 0 ) + return rc; /* find kernel segment */ dom->kernel_seg.vstart = dom->parms.virt_kstart; dom->kernel_seg.vend = dom->parms.virt_kend; - if (dom->parms.bsd_symtab) - xc_dom_load_elf_symtab(dom, elf, 0); + if ( dom->parms.bsd_symtab ) + xc_dom_load_elf_symtab(dom, elf, 0); dom->guest_type = xc_dom_guest_type(dom, elf); xc_dom_printf("%s: %s: 0x%" PRIx64 " -> 0x%" PRIx64 "\n", - __FUNCTION__, dom->guest_type, - dom->kernel_seg.vstart, dom->kernel_seg.vend); + __FUNCTION__, dom->guest_type, + dom->kernel_seg.vstart, dom->kernel_seg.vend); return 0; } @@ -263,8 +274,8 @@ static int xc_dom_load_elf_kernel(struct xc_dom_image *dom) elf->dest = xc_dom_seg_to_ptr(dom, &dom->kernel_seg); elf_load_binary(elf); - if (dom->parms.bsd_symtab) - xc_dom_load_elf_symtab(dom, elf, 1); + if ( dom->parms.bsd_symtab ) + xc_dom_load_elf_symtab(dom, elf, 1); return 0; } @@ -281,3 +292,13 @@ static void __init register_loader(void) { xc_dom_register_loader(&elf_loader); } + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/tools/libxc/xc_dom_ia64.c b/tools/libxc/xc_dom_ia64.c index 2ffce5a4d7..4eef976154 100644 --- a/tools/libxc/xc_dom_ia64.c +++ b/tools/libxc/xc_dom_ia64.c @@ -33,9 +33,9 @@ static int alloc_magic_pages(struct xc_dom_image *dom) static int start_info_ia64(struct xc_dom_image *dom) { start_info_ia64_t *start_info = - xc_dom_pfn_to_ptr(dom, dom->start_info_pfn, 1); + xc_dom_pfn_to_ptr(dom, dom->start_info_pfn, 1); struct xen_ia64_boot_param_ia64 *bp = - (struct xen_ia64_boot_param_ia64 *)(start_info + 1); + (struct xen_ia64_boot_param_ia64 *)(start_info + 1); xc_dom_printf("%s\n", __FUNCTION__); @@ -48,19 +48,19 @@ static int start_info_ia64(struct xc_dom_image *dom) start_info->console.domU.mfn = dom->console_pfn; start_info->console.domU.evtchn = dom->console_evtchn; - if (dom->ramdisk_blob) + if ( dom->ramdisk_blob ) { - start_info->mod_start = dom->ramdisk_seg.vstart; - start_info->mod_len = dom->ramdisk_seg.vend - dom->ramdisk_seg.vstart; - bp->initrd_start = start_info->mod_start; - bp->initrd_size = start_info->mod_len; + start_info->mod_start = dom->ramdisk_seg.vstart; + start_info->mod_len = dom->ramdisk_seg.vend - dom->ramdisk_seg.vstart; + bp->initrd_start = start_info->mod_start; + bp->initrd_size = start_info->mod_len; } bp->command_line = (dom->start_info_pfn << PAGE_SHIFT_IA64) - + offsetof(start_info_t, cmd_line); - if (dom->cmdline) + + offsetof(start_info_t, cmd_line); + if ( dom->cmdline ) { - strncpy((char *)start_info->cmd_line, dom->cmdline, MAX_GUEST_CMDLINE); - start_info->cmd_line[MAX_GUEST_CMDLINE - 1] = '\0'; + strncpy((char *)start_info->cmd_line, dom->cmdline, MAX_GUEST_CMDLINE); + start_info->cmd_line[MAX_GUEST_CMDLINE - 1] = '\0'; } return 0; } @@ -74,7 +74,7 @@ static int shared_info_ia64(struct xc_dom_image *dom, void *ptr) memset(shared_info, 0, sizeof(*shared_info)); for (i = 0; i < MAX_VIRT_CPUS; i++) - shared_info->vcpu_info[i].evtchn_upcall_mask = 1; + shared_info->vcpu_info[i].evtchn_upcall_mask = 1; shared_info->arch.start_info_pfn = dom->start_info_pfn; return 0; } @@ -91,14 +91,14 @@ static int vcpu_ia64(struct xc_dom_image *dom, void *ptr) memset(ctxt, 0, sizeof(*ctxt)); ctxt->flags = 0; - ctxt->user_regs.cr_ipsr = 0; /* all necessary bits filled by hypervisor */ + ctxt->user_regs.cr_ipsr = 0; /* all necessary bits filled by hypervisor */ ctxt->user_regs.cr_iip = dom->parms.virt_entry; ctxt->user_regs.cr_ifs = (uint64_t) 1 << 63; -#ifdef __ia64__ /* FIXME */ +#ifdef __ia64__ /* FIXME */ ctxt->user_regs.ar_fpsr = xc_ia64_fpsr_default(); #endif ctxt->user_regs.r28 = (dom->start_info_pfn << PAGE_SHIFT_IA64) - + sizeof(start_info_ia64_t); + + sizeof(start_info_ia64_t); return 0; } @@ -113,7 +113,27 @@ static struct xc_dom_arch xc_dom_arch = { .vcpu = vcpu_ia64, }; +static struct xc_dom_arch xc_dom_arch_ia64be = { + .guest_type = "xen-3.0-ia64be", + .page_shift = PAGE_SHIFT_IA64, + .alloc_magic_pages = alloc_magic_pages, + .start_info = start_info_ia64, + .shared_info = shared_info_ia64, + .vcpu = vcpu_ia64, +}; + static void __init register_arch_hooks(void) { xc_dom_register_arch_hooks(&xc_dom_arch); + xc_dom_register_arch_hooks(&xc_dom_arch_ia64be); } + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/tools/libxc/xc_dom_x86.c b/tools/libxc/xc_dom_x86.c index fdc3d4ba5e..695e5a168d 100644 --- a/tools/libxc/xc_dom_x86.c +++ b/tools/libxc/xc_dom_x86.c @@ -29,37 +29,37 @@ #define round_down(addr, mask) ((addr) & ~(mask)) #define round_up(addr, mask) ((addr) | (mask)) -static inline unsigned long +static unsigned long nr_page_tables(xen_vaddr_t start, xen_vaddr_t end, unsigned long bits) { xen_vaddr_t mask = bits_to_mask(bits); int tables; - if (0 == bits) - return 0; /* unused */ + if ( bits == 0 ) + return 0; /* unused */ - if (8 * sizeof(unsigned long) == bits) + if ( bits == (8 * sizeof(unsigned long)) ) { - /* must be pgd, need one */ - start = 0; - end = -1; - tables = 1; + /* must be pgd, need one */ + start = 0; + end = -1; + tables = 1; } else { - start = round_down(start, mask); - end = round_up(end, mask); - tables = ((end - start) >> bits) + 1; + start = round_down(start, mask); + end = round_up(end, mask); + tables = ((end - start) >> bits) + 1; } xc_dom_printf("%s: 0x%016" PRIx64 "/%ld: 0x%016" PRIx64 - " -> 0x%016" PRIx64 ", %d table(s)\n", - __FUNCTION__, mask, bits, start, end, tables); + " -> 0x%016" PRIx64 ", %d table(s)\n", + __FUNCTION__, mask, bits, start, end, tables); return tables; } static int count_pgtables(struct xc_dom_image *dom, int pae, - int l4_bits, int l3_bits, int l2_bits, int l1_bits) + int l4_bits, int l3_bits, int l2_bits, int l1_bits) { int pages, extra_pages; xen_vaddr_t try_virt_end; @@ -68,27 +68,28 @@ static int count_pgtables(struct xc_dom_image *dom, int pae, extra_pages += dom->extra_pages; extra_pages += 128; /* 512kB padding */ pages = extra_pages; - for (;;) + for ( ; ; ) { - try_virt_end = round_up(dom->virt_alloc_end + pages * PAGE_SIZE_X86, - bits_to_mask(22)); /* 4MB alignment */ - dom->pg_l4 = - nr_page_tables(dom->parms.virt_base, try_virt_end, l4_bits); - dom->pg_l3 = - nr_page_tables(dom->parms.virt_base, try_virt_end, l3_bits); - dom->pg_l2 = - nr_page_tables(dom->parms.virt_base, try_virt_end, l2_bits); - dom->pg_l1 = - nr_page_tables(dom->parms.virt_base, try_virt_end, l1_bits); - if (pae && try_virt_end < 0xc0000000) - { - xc_dom_printf("%s: PAE: extra l2 page table for l3#3\n", __FUNCTION__); - dom->pg_l2++; - } - dom->pgtables = dom->pg_l4 + dom->pg_l3 + dom->pg_l2 + dom->pg_l1; - pages = dom->pgtables + extra_pages; - if (dom->virt_alloc_end + pages * PAGE_SIZE_X86 <= try_virt_end + 1) - break; + try_virt_end = round_up(dom->virt_alloc_end + pages * PAGE_SIZE_X86, + bits_to_mask(22)); /* 4MB alignment */ + dom->pg_l4 = + nr_page_tables(dom->parms.virt_base, try_virt_end, l4_bits); + dom->pg_l3 = + nr_page_tables(dom->parms.virt_base, try_virt_end, l3_bits); + dom->pg_l2 = + nr_page_tables(dom->parms.virt_base, try_virt_end, l2_bits); + dom->pg_l1 = + nr_page_tables(dom->parms.virt_base, try_virt_end, l1_bits); + if (pae && try_virt_end < 0xc0000000) + { + xc_dom_printf("%s: PAE: extra l2 page table for l3#3\n", + __FUNCTION__); + dom->pg_l2++; + } + dom->pgtables = dom->pg_l4 + dom->pg_l3 + dom->pg_l2 + dom->pg_l1; + pages = dom->pgtables + extra_pages; + if ( dom->virt_alloc_end + pages * PAGE_SIZE_X86 <= try_virt_end + 1 ) + break; } dom->virt_pgtab_end = try_virt_end + 1; return 0; @@ -109,7 +110,7 @@ static int count_pgtables_x86_32(struct xc_dom_image *dom) static int count_pgtables_x86_32_pae(struct xc_dom_image *dom) { return count_pgtables(dom, 1, 0, 32, - L3_PAGETABLE_SHIFT_PAE, L2_PAGETABLE_SHIFT_PAE); + L3_PAGETABLE_SHIFT_PAE, L2_PAGETABLE_SHIFT_PAE); } #define pfn_to_paddr(pfn) ((xen_paddr_t)(pfn) << PAGE_SHIFT_X86) @@ -124,28 +125,29 @@ static int setup_pgtables_x86_32(struct xc_dom_image *dom) xen_vaddr_t addr; xen_pfn_t pgpfn; - for (addr = dom->parms.virt_base; addr < dom->virt_pgtab_end; - addr += PAGE_SIZE_X86) + for ( addr = dom->parms.virt_base; addr < dom->virt_pgtab_end; + addr += PAGE_SIZE_X86 ) { - if (NULL == l1tab) - { - /* get L1 tab, make L2 entry */ - l1tab = xc_dom_pfn_to_ptr(dom, l1pfn, 1); - l2off = l2_table_offset_i386(addr); - l2tab[l2off] = - pfn_to_paddr(xc_dom_p2m_guest(dom, l1pfn)) | L2_PROT; - l1pfn++; - } + if ( l1tab == NULL ) + { + /* get L1 tab, make L2 entry */ + l1tab = xc_dom_pfn_to_ptr(dom, l1pfn, 1); + l2off = l2_table_offset_i386(addr); + l2tab[l2off] = + pfn_to_paddr(xc_dom_p2m_guest(dom, l1pfn)) | L2_PROT; + l1pfn++; + } - /* make L1 entry */ - l1off = l1_table_offset_i386(addr); - pgpfn = (addr - dom->parms.virt_base) >> PAGE_SHIFT_X86; - l1tab[l1off] = - pfn_to_paddr(xc_dom_p2m_guest(dom, pgpfn)) | L1_PROT; - if (addr >= dom->pgtables_seg.vstart && addr < dom->pgtables_seg.vend) - l1tab[l1off] &= ~_PAGE_RW; /* page tables are r/o */ - if (L1_PAGETABLE_ENTRIES_I386 - 1 == l1off) - l1tab = NULL; + /* make L1 entry */ + l1off = l1_table_offset_i386(addr); + pgpfn = (addr - dom->parms.virt_base) >> PAGE_SHIFT_X86; + l1tab[l1off] = + pfn_to_paddr(xc_dom_p2m_guest(dom, pgpfn)) | L1_PROT; + if ( (addr >= dom->pgtables_seg.vstart) && + (addr < dom->pgtables_seg.vend) ) + l1tab[l1off] &= ~_PAGE_RW; /* page tables are r/o */ + if ( l1off == (L1_PAGETABLE_ENTRIES_I386 - 1) ) + l1tab = NULL; } return 0; } @@ -162,46 +164,47 @@ static int setup_pgtables_x86_32_pae(struct xc_dom_image *dom) xen_vaddr_t addr; xen_pfn_t pgpfn; - for (addr = dom->parms.virt_base; addr < dom->virt_pgtab_end; - addr += PAGE_SIZE_X86) + for ( addr = dom->parms.virt_base; addr < dom->virt_pgtab_end; + addr += PAGE_SIZE_X86 ) { - if (NULL == l2tab) - { - /* get L2 tab, make L3 entry */ - l2tab = xc_dom_pfn_to_ptr(dom, l2pfn, 1); - l3off = l3_table_offset_pae(addr); - l3tab[l3off] = - pfn_to_paddr(xc_dom_p2m_guest(dom, l2pfn)) | L3_PROT; - l2pfn++; - } + if ( l2tab == NULL ) + { + /* get L2 tab, make L3 entry */ + l2tab = xc_dom_pfn_to_ptr(dom, l2pfn, 1); + l3off = l3_table_offset_pae(addr); + l3tab[l3off] = + pfn_to_paddr(xc_dom_p2m_guest(dom, l2pfn)) | L3_PROT; + l2pfn++; + } - if (NULL == l1tab) - { - /* get L1 tab, make L2 entry */ - l1tab = xc_dom_pfn_to_ptr(dom, l1pfn, 1); - l2off = l2_table_offset_pae(addr); - l2tab[l2off] = - pfn_to_paddr(xc_dom_p2m_guest(dom, l1pfn)) | L2_PROT; - if (L2_PAGETABLE_ENTRIES_PAE - 1 == l2off) - l2tab = NULL; - l1pfn++; - } + if ( l1tab == NULL ) + { + /* get L1 tab, make L2 entry */ + l1tab = xc_dom_pfn_to_ptr(dom, l1pfn, 1); + l2off = l2_table_offset_pae(addr); + l2tab[l2off] = + pfn_to_paddr(xc_dom_p2m_guest(dom, l1pfn)) | L2_PROT; + if ( l2off == (L2_PAGETABLE_ENTRIES_PAE - 1) ) + l2tab = NULL; + l1pfn++; + } - /* make L1 entry */ - l1off = l1_table_offset_pae(addr); - pgpfn = (addr - dom->parms.virt_base) >> PAGE_SHIFT_X86; - l1tab[l1off] = - pfn_to_paddr(xc_dom_p2m_guest(dom, pgpfn)) | L1_PROT; - if (addr >= dom->pgtables_seg.vstart && addr < dom->pgtables_seg.vend) - l1tab[l1off] &= ~_PAGE_RW; /* page tables are r/o */ - if (L1_PAGETABLE_ENTRIES_PAE - 1 == l1off) - l1tab = NULL; + /* make L1 entry */ + l1off = l1_table_offset_pae(addr); + pgpfn = (addr - dom->parms.virt_base) >> PAGE_SHIFT_X86; + l1tab[l1off] = + pfn_to_paddr(xc_dom_p2m_guest(dom, pgpfn)) | L1_PROT; + if ( (addr >= dom->pgtables_seg.vstart) && + (addr < dom->pgtables_seg.vend) ) + l1tab[l1off] &= ~_PAGE_RW; /* page tables are r/o */ + if ( l1off == (L1_PAGETABLE_ENTRIES_PAE - 1) ) + l1tab = NULL; } - if (dom->virt_pgtab_end <= 0xc0000000) + if ( dom->virt_pgtab_end <= 0xc0000000 ) { - xc_dom_printf("%s: PAE: extra l2 page table for l3#3\n", __FUNCTION__); - l3tab[3] = pfn_to_paddr(xc_dom_p2m_guest(dom, l2pfn)) | L3_PROT; + xc_dom_printf("%s: PAE: extra l2 page table for l3#3\n", __FUNCTION__); + l3tab[3] = pfn_to_paddr(xc_dom_p2m_guest(dom, l2pfn)) | L3_PROT; } return 0; } @@ -216,9 +219,10 @@ static int setup_pgtables_x86_32_pae(struct xc_dom_image *dom) static int count_pgtables_x86_64(struct xc_dom_image *dom) { return count_pgtables(dom, 0, - L4_PAGETABLE_SHIFT_X86_64 + 9, - L4_PAGETABLE_SHIFT_X86_64, - L3_PAGETABLE_SHIFT_X86_64, L2_PAGETABLE_SHIFT_X86_64); + L4_PAGETABLE_SHIFT_X86_64 + 9, + L4_PAGETABLE_SHIFT_X86_64, + L3_PAGETABLE_SHIFT_X86_64, + L2_PAGETABLE_SHIFT_X86_64); } #define L1_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED) @@ -232,7 +236,7 @@ static int setup_pgtables_x86_64(struct xc_dom_image *dom) xen_pfn_t l3pfn = dom->pgtables_seg.pfn + dom->pg_l4; xen_pfn_t l2pfn = dom->pgtables_seg.pfn + dom->pg_l4 + dom->pg_l3; xen_pfn_t l1pfn = - dom->pgtables_seg.pfn + dom->pg_l4 + dom->pg_l3 + dom->pg_l2; + dom->pgtables_seg.pfn + dom->pg_l4 + dom->pg_l3 + dom->pg_l2; l4_pgentry_64_t *l4tab = xc_dom_pfn_to_ptr(dom, l4pfn, 1); l3_pgentry_64_t *l3tab = NULL; l2_pgentry_64_t *l2tab = NULL; @@ -241,52 +245,53 @@ static int setup_pgtables_x86_64(struct xc_dom_image *dom) uint64_t addr; xen_pfn_t pgpfn; - for (addr = dom->parms.virt_base; addr < dom->virt_pgtab_end; - addr += PAGE_SIZE_X86) + for ( addr = dom->parms.virt_base; addr < dom->virt_pgtab_end; + addr += PAGE_SIZE_X86 ) { - if (NULL == l3tab) - { - /* get L3 tab, make L4 entry */ - l3tab = xc_dom_pfn_to_ptr(dom, l3pfn, 1); - l4off = l4_table_offset_x86_64(addr); - l4tab[l4off] = - pfn_to_paddr(xc_dom_p2m_guest(dom, l3pfn)) | L4_PROT; - l3pfn++; - } + if ( l3tab == NULL ) + { + /* get L3 tab, make L4 entry */ + l3tab = xc_dom_pfn_to_ptr(dom, l3pfn, 1); + l4off = l4_table_offset_x86_64(addr); + l4tab[l4off] = + pfn_to_paddr(xc_dom_p2m_guest(dom, l3pfn)) | L4_PROT; + l3pfn++; + } - if (NULL == l2tab) - { - /* get L2 tab, make L3 entry */ - l2tab = xc_dom_pfn_to_ptr(dom, l2pfn, 1); - l3off = l3_table_offset_x86_64(addr); - l3tab[l3off] = - pfn_to_paddr(xc_dom_p2m_guest(dom, l2pfn)) | L3_PROT; - if (L3_PAGETABLE_ENTRIES_X86_64 - 1 == l3off) - l3tab = NULL; - l2pfn++; - } + if ( l2tab == NULL ) + { + /* get L2 tab, make L3 entry */ + l2tab = xc_dom_pfn_to_ptr(dom, l2pfn, 1); + l3off = l3_table_offset_x86_64(addr); + l3tab[l3off] = + pfn_to_paddr(xc_dom_p2m_guest(dom, l2pfn)) | L3_PROT; + if ( l3off == (L3_PAGETABLE_ENTRIES_X86_64 - 1) ) + l3tab = NULL; + l2pfn++; + } - if (NULL == l1tab) - { - /* get L1 tab, make L2 entry */ - l1tab = xc_dom_pfn_to_ptr(dom, l1pfn, 1); - l2off = l2_table_offset_x86_64(addr); - l2tab[l2off] = - pfn_to_paddr(xc_dom_p2m_guest(dom, l1pfn)) | L2_PROT; - if (L2_PAGETABLE_ENTRIES_X86_64 - 1 == l2off) - l2tab = NULL; - l1pfn++; - } + if ( l1tab == NULL ) + { + /* get L1 tab, make L2 entry */ + l1tab = xc_dom_pfn_to_ptr(dom, l1pfn, 1); + l2off = l2_table_offset_x86_64(addr); + l2tab[l2off] = + pfn_to_paddr(xc_dom_p2m_guest(dom, l1pfn)) | L2_PROT; + if ( l2off == (L2_PAGETABLE_ENTRIES_X86_64 - 1) ) + l2tab = NULL; + l1pfn++; + } - /* make L1 entry */ - l1off = l1_table_offset_x86_64(addr); - pgpfn = (addr - dom->parms.virt_base) >> PAGE_SHIFT_X86; - l1tab[l1off] = - pfn_to_paddr(xc_dom_p2m_guest(dom, pgpfn)) | L1_PROT; - if (addr >= dom->pgtables_seg.vstart && addr < dom->pgtables_seg.vend) - l1tab[l1off] &= ~_PAGE_RW; /* page tables are r/o */ - if (L1_PAGETABLE_ENTRIES_X86_64 - 1 == l1off) - l1tab = NULL; + /* make L1 entry */ + l1off = l1_table_offset_x86_64(addr); + pgpfn = (addr - dom->parms.virt_base) >> PAGE_SHIFT_X86; + l1tab[l1off] = + pfn_to_paddr(xc_dom_p2m_guest(dom, pgpfn)) | L1_PROT; + if ( (addr >= dom->pgtables_seg.vstart) && + (addr < dom->pgtables_seg.vend) ) + l1tab[l1off] &= ~_PAGE_RW; /* page tables are r/o */ + if ( l1off == (L1_PAGETABLE_ENTRIES_X86_64 - 1) ) + l1tab = NULL; } return 0; } @@ -303,16 +308,16 @@ static int alloc_magic_pages(struct xc_dom_image *dom) size_t p2m_size = dom->total_pages * dom->arch_hooks->sizeof_pfn; /* allocate phys2mach table */ - if (0 != xc_dom_alloc_segment(dom, &dom->p2m_seg, "phys2mach", 0, p2m_size)) - return -1; + if ( xc_dom_alloc_segment(dom, &dom->p2m_seg, "phys2mach", 0, p2m_size) ) + return -1; dom->p2m_guest = xc_dom_seg_to_ptr(dom, &dom->p2m_seg); /* allocate special pages */ dom->start_info_pfn = xc_dom_alloc_page(dom, "start info"); dom->xenstore_pfn = xc_dom_alloc_page(dom, "xenstore"); dom->console_pfn = xc_dom_alloc_page(dom, "console"); - if (xc_dom_feature_translated(dom)) - dom->shared_info_pfn = xc_dom_alloc_page(dom, "shared info"); + if ( xc_dom_feature_translated(dom) ) + dom->shared_info_pfn = xc_dom_alloc_page(dom, "shared info"); dom->alloc_bootstack = 1; return 0; @@ -323,10 +328,10 @@ static int alloc_magic_pages(struct xc_dom_image *dom) static int start_info_x86_32(struct xc_dom_image *dom) { start_info_x86_32_t *start_info = - xc_dom_pfn_to_ptr(dom, dom->start_info_pfn, 1); + xc_dom_pfn_to_ptr(dom, dom->start_info_pfn, 1); xen_pfn_t shinfo = - xc_dom_feature_translated(dom) ? dom->shared_info_pfn : dom-> - shared_info_mfn; + xc_dom_feature_translated(dom) ? dom->shared_info_pfn : dom-> + shared_info_mfn; xc_dom_printf("%s: called\n", __FUNCTION__); @@ -343,26 +348,28 @@ static int start_info_x86_32(struct xc_dom_image *dom) start_info->console.domU.mfn = xc_dom_p2m_guest(dom, dom->console_pfn); start_info->console.domU.evtchn = dom->console_evtchn; - if (dom->ramdisk_blob) + if ( dom->ramdisk_blob ) { - start_info->mod_start = dom->ramdisk_seg.vstart; - start_info->mod_len = dom->ramdisk_seg.vend - dom->ramdisk_seg.vstart; + start_info->mod_start = dom->ramdisk_seg.vstart; + start_info->mod_len = dom->ramdisk_seg.vend - dom->ramdisk_seg.vstart; } - if (dom->cmdline) + + if ( dom->cmdline ) { - strncpy((char *)start_info->cmd_line, dom->cmdline, MAX_GUEST_CMDLINE); - start_info->cmd_line[MAX_GUEST_CMDLINE - 1] = '\0'; + strncpy((char *)start_info->cmd_line, dom->cmdline, MAX_GUEST_CMDLINE); + start_info->cmd_line[MAX_GUEST_CMDLINE - 1] = '\0'; } + return 0; } static int start_info_x86_64(struct xc_dom_image *dom) { start_info_x86_64_t *start_info = - xc_dom_pfn_to_ptr(dom, dom->start_info_pfn, 1); + xc_dom_pfn_to_ptr(dom, dom->start_info_pfn, 1); xen_pfn_t shinfo = - xc_dom_feature_translated(dom) ? dom->shared_info_pfn : dom-> - shared_info_mfn; + xc_dom_feature_translated(dom) ? dom->shared_info_pfn : dom-> + shared_info_mfn; xc_dom_printf("%s: called\n", __FUNCTION__); @@ -379,16 +386,18 @@ static int start_info_x86_64(struct xc_dom_image *dom) start_info->console.domU.mfn = xc_dom_p2m_guest(dom, dom->console_pfn); start_info->console.domU.evtchn = dom->console_evtchn; - if (dom->ramdisk_blob) + if ( dom->ramdisk_blob ) { - start_info->mod_start = dom->ramdisk_seg.vstart; - start_info->mod_len = dom->ramdisk_seg.vend - dom->ramdisk_seg.vstart; + start_info->mod_start = dom->ramdisk_seg.vstart; + start_info->mod_len = dom->ramdisk_seg.vend - dom->ramdisk_seg.vstart; } - if (dom->cmdline) + + if ( dom->cmdline ) { - strncpy((char *)start_info->cmd_line, dom->cmdline, MAX_GUEST_CMDLINE); - start_info->cmd_line[MAX_GUEST_CMDLINE - 1] = '\0'; + strncpy((char *)start_info->cmd_line, dom->cmdline, MAX_GUEST_CMDLINE); + start_info->cmd_line[MAX_GUEST_CMDLINE - 1] = '\0'; } + return 0; } @@ -400,8 +409,8 @@ static int shared_info_x86_32(struct xc_dom_image *dom, void *ptr) xc_dom_printf("%s: called\n", __FUNCTION__); memset(shared_info, 0, sizeof(*shared_info)); - for (i = 0; i < MAX_VIRT_CPUS; i++) - shared_info->vcpu_info[i].evtchn_upcall_mask = 1; + for ( i = 0; i < MAX_VIRT_CPUS; i++ ) + shared_info->vcpu_info[i].evtchn_upcall_mask = 1; return 0; } @@ -413,8 +422,8 @@ static int shared_info_x86_64(struct xc_dom_image *dom, void *ptr) xc_dom_printf("%s: called\n", __FUNCTION__); memset(shared_info, 0, sizeof(*shared_info)); - for (i = 0; i < MAX_VIRT_CPUS; i++) - shared_info->vcpu_info[i].evtchn_upcall_mask = 1; + for ( i = 0; i < MAX_VIRT_CPUS; i++ ) + shared_info->vcpu_info[i].evtchn_upcall_mask = 1; return 0; } @@ -432,10 +441,10 @@ static int vcpu_x86_32(struct xc_dom_image *dom, void *ptr) memset(ctxt, 0, sizeof(*ctxt)); /* Virtual IDT is empty at start-of-day. */ - for (i = 0; i < 256; i++) + for ( i = 0; i < 256; i++ ) { - ctxt->trap_ctxt[i].vector = i; - ctxt->trap_ctxt[i].cs = FLAT_KERNEL_CS_X86_32; + ctxt->trap_ctxt[i].vector = i; + ctxt->trap_ctxt[i].cs = FLAT_KERNEL_CS_X86_32; } /* No callback handlers. */ @@ -450,24 +459,24 @@ static int vcpu_x86_32(struct xc_dom_image *dom, void *ptr) ctxt->user_regs.cs = FLAT_KERNEL_CS_X86_32; ctxt->user_regs.eip = dom->parms.virt_entry; ctxt->user_regs.esp = - dom->parms.virt_base + (dom->bootstack_pfn + 1) * PAGE_SIZE_X86; + dom->parms.virt_base + (dom->bootstack_pfn + 1) * PAGE_SIZE_X86; ctxt->user_regs.esi = - dom->parms.virt_base + (dom->start_info_pfn) * PAGE_SIZE_X86; - ctxt->user_regs.eflags = 1 << 9; /* Interrupt Enable */ + dom->parms.virt_base + (dom->start_info_pfn) * PAGE_SIZE_X86; + ctxt->user_regs.eflags = 1 << 9; /* Interrupt Enable */ ctxt->kernel_ss = FLAT_KERNEL_SS_X86_32; ctxt->kernel_sp = - dom->parms.virt_base + (dom->bootstack_pfn + 1) * PAGE_SIZE_X86; + dom->parms.virt_base + (dom->bootstack_pfn + 1) * PAGE_SIZE_X86; ctxt->flags = VGCF_in_kernel_X86_32; - if (dom->parms.pae == 2 /* extended_cr3 */ || - dom->parms.pae == 3 /* bimodal */) - ctxt->vm_assist |= (1UL << VMASST_TYPE_pae_extended_cr3); + if ( dom->parms.pae == 2 /* extended_cr3 */ || + dom->parms.pae == 3 /* bimodal */ ) + ctxt->vm_assist |= (1UL << VMASST_TYPE_pae_extended_cr3); cr3_pfn = xc_dom_p2m_guest(dom, dom->pgtables_seg.pfn); ctxt->ctrlreg[3] = xen_pfn_to_cr3_x86_32(cr3_pfn); xc_dom_printf("%s: cr3: pfn 0x%" PRIpfn " mfn 0x%" PRIpfn "\n", - __FUNCTION__, dom->pgtables_seg.pfn, cr3_pfn); + __FUNCTION__, dom->pgtables_seg.pfn, cr3_pfn); return 0; } @@ -484,10 +493,10 @@ static int vcpu_x86_64(struct xc_dom_image *dom, void *ptr) memset(ctxt, 0, sizeof(*ctxt)); /* Virtual IDT is empty at start-of-day. */ - for (i = 0; i < 256; i++) + for ( i = 0; i < 256; i++ ) { - ctxt->trap_ctxt[i].vector = i; - ctxt->trap_ctxt[i].cs = FLAT_KERNEL_CS_X86_64; + ctxt->trap_ctxt[i].vector = i; + ctxt->trap_ctxt[i].cs = FLAT_KERNEL_CS_X86_64; } ctxt->user_regs.ds = FLAT_KERNEL_DS_X86_64; @@ -498,20 +507,20 @@ static int vcpu_x86_64(struct xc_dom_image *dom, void *ptr) ctxt->user_regs.cs = FLAT_KERNEL_CS_X86_64; ctxt->user_regs.rip = dom->parms.virt_entry; ctxt->user_regs.rsp = - dom->parms.virt_base + (dom->bootstack_pfn + 1) * PAGE_SIZE_X86; + dom->parms.virt_base + (dom->bootstack_pfn + 1) * PAGE_SIZE_X86; ctxt->user_regs.rsi = - dom->parms.virt_base + (dom->start_info_pfn) * PAGE_SIZE_X86; - ctxt->user_regs.rflags = 1 << 9; /* Interrupt Enable */ + dom->parms.virt_base + (dom->start_info_pfn) * PAGE_SIZE_X86; + ctxt->user_regs.rflags = 1 << 9; /* Interrupt Enable */ ctxt->kernel_ss = FLAT_KERNEL_SS_X86_64; ctxt->kernel_sp = - dom->parms.virt_base + (dom->bootstack_pfn + 1) * PAGE_SIZE_X86; + dom->parms.virt_base + (dom->bootstack_pfn + 1) * PAGE_SIZE_X86; ctxt->flags = VGCF_in_kernel_X86_64; cr3_pfn = xc_dom_p2m_guest(dom, dom->pgtables_seg.pfn); ctxt->ctrlreg[3] = xen_pfn_to_cr3_x86_64(cr3_pfn); xc_dom_printf("%s: cr3: pfn 0x%" PRIpfn " mfn 0x%" PRIpfn "\n", - __FUNCTION__, dom->pgtables_seg.pfn, cr3_pfn); + __FUNCTION__, dom->pgtables_seg.pfn, cr3_pfn); return 0; } @@ -559,3 +568,13 @@ static void __init register_arch_hooks(void) xc_dom_register_arch_hooks(&xc_dom_32_pae); xc_dom_register_arch_hooks(&xc_dom_64); } + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/tools/libxc/xc_domain.c b/tools/libxc/xc_domain.c index 6e3b0d9e82..1b6962d54d 100644 --- a/tools/libxc/xc_domain.c +++ b/tools/libxc/xc_domain.c @@ -642,6 +642,21 @@ int xc_domain_iomem_permission(int xc_handle, return do_domctl(xc_handle, &domctl); } +int xc_domain_send_trigger(int xc_handle, + uint32_t domid, + uint32_t trigger, + uint32_t vcpu) +{ + DECLARE_DOMCTL; + + domctl.cmd = XEN_DOMCTL_sendtrigger; + domctl.domain = domid; + domctl.u.sendtrigger.trigger = trigger; + domctl.u.sendtrigger.vcpu = vcpu; + + return do_domctl(xc_handle, &domctl); +} + /* * Local variables: * mode: C diff --git a/tools/libxc/xc_efi.h b/tools/libxc/xc_efi.h new file mode 100644 index 0000000000..95873173e2 --- /dev/null +++ b/tools/libxc/xc_efi.h @@ -0,0 +1,68 @@ +#ifndef XC_EFI_H +#define XC_EFI_H + +/* definitions from xen/include/asm-ia64/linux-xen/linux/efi.h */ + +/* + * Extensible Firmware Interface + * Based on 'Extensible Firmware Interface Specification' version 0.9, April 30, 1999 + * + * Copyright (C) 1999 VA Linux Systems + * Copyright (C) 1999 Walt Drummond + * Copyright (C) 1999, 2002-2003 Hewlett-Packard Co. + * David Mosberger-Tang + * Stephane Eranian + */ + +/* + * Memory map descriptor: + */ + +/* Memory types: */ +#define EFI_RESERVED_TYPE 0 +#define EFI_LOADER_CODE 1 +#define EFI_LOADER_DATA 2 +#define EFI_BOOT_SERVICES_CODE 3 +#define EFI_BOOT_SERVICES_DATA 4 +#define EFI_RUNTIME_SERVICES_CODE 5 +#define EFI_RUNTIME_SERVICES_DATA 6 +#define EFI_CONVENTIONAL_MEMORY 7 +#define EFI_UNUSABLE_MEMORY 8 +#define EFI_ACPI_RECLAIM_MEMORY 9 +#define EFI_ACPI_MEMORY_NVS 10 +#define EFI_MEMORY_MAPPED_IO 11 +#define EFI_MEMORY_MAPPED_IO_PORT_SPACE 12 +#define EFI_PAL_CODE 13 +#define EFI_MAX_MEMORY_TYPE 14 + +/* Attribute values: */ +#define EFI_MEMORY_UC ((uint64_t)0x0000000000000001ULL) /* uncached */ +#define EFI_MEMORY_WC ((uint64_t)0x0000000000000002ULL) /* write-coalescing */ +#define EFI_MEMORY_WT ((uint64_t)0x0000000000000004ULL) /* write-through */ +#define EFI_MEMORY_WB ((uint64_t)0x0000000000000008ULL) /* write-back */ +#define EFI_MEMORY_WP ((uint64_t)0x0000000000001000ULL) /* write-protect */ +#define EFI_MEMORY_RP ((uint64_t)0x0000000000002000ULL) /* read-protect */ +#define EFI_MEMORY_XP ((uint64_t)0x0000000000004000ULL) /* execute-protect */ +#define EFI_MEMORY_RUNTIME ((uint64_t)0x8000000000000000ULL) /* range requires runtime mapping */ +#define EFI_MEMORY_DESCRIPTOR_VERSION 1 + +#define EFI_PAGE_SHIFT 12 + +/* + * For current x86 implementations of EFI, there is + * additional padding in the mem descriptors. This is not + * the case in ia64. Need to have this fixed in the f/w. + */ +typedef struct { + uint32_t type; + uint32_t pad; + uint64_t phys_addr; + uint64_t virt_addr; + uint64_t num_pages; + uint64_t attribute; +#if defined (__i386__) + uint64_t pad1; +#endif +} efi_memory_desc_t; + +#endif /* XC_EFI_H */ diff --git a/tools/libxc/xc_hvm_build.c b/tools/libxc/xc_hvm_build.c index 28bc512218..2238d315bc 100644 --- a/tools/libxc/xc_hvm_build.c +++ b/tools/libxc/xc_hvm_build.c @@ -11,6 +11,8 @@ #include "xg_private.h" #include "xc_private.h" +#include +#include #include #include #include @@ -19,6 +21,15 @@ #define SCRATCH_PFN 0xFFFFF +/* Need to provide the right flavour of vcpu context for Xen */ +typedef union +{ + vcpu_guest_context_x86_64_t c64; + vcpu_guest_context_x86_32_t c32; + vcpu_guest_context_t c; +} vcpu_guest_context_either_t; + + int xc_set_hvm_param( int handle, domid_t dom, int param, unsigned long value) { @@ -182,7 +193,7 @@ loadelfimage(struct elf_binary *elf, int xch, uint32_t dom, unsigned long *parra static int setup_guest(int xc_handle, uint32_t dom, int memsize, char *image, unsigned long image_size, - vcpu_guest_context_t *ctxt) + vcpu_guest_context_either_t *ctxt) { xen_pfn_t *page_array = NULL; unsigned long i, nr_pages = (unsigned long)memsize << (20 - PAGE_SHIFT); @@ -193,6 +204,7 @@ static int setup_guest(int xc_handle, struct elf_binary elf; uint64_t v_start, v_end; int rc; + xen_capabilities_info_t caps; if (0 != elf_init(&elf, image, image_size)) goto error_out; @@ -200,6 +212,12 @@ static int setup_guest(int xc_handle, v_start = 0; v_end = (unsigned long long)memsize << 20; + if (xc_version(xc_handle, XENVER_capabilities, &caps) != 0) + { + PERROR("Could not get Xen capabilities\n"); + goto error_out; + } + if ( (elf.pstart & (PAGE_SIZE - 1)) != 0 ) { PERROR("Guest OS must load to a page boundary.\n"); @@ -262,6 +280,7 @@ static int setup_guest(int xc_handle, /* NB. evtchn_upcall_mask is unused: leave as zero. */ memset(&shared_info->evtchn_mask[0], 0xff, sizeof(shared_info->evtchn_mask)); + shared_info->arch.max_pfn = page_array[nr_pages - 1]; munmap(shared_info, PAGE_SIZE); if ( v_end > HVM_BELOW_4G_RAM_END ) @@ -281,7 +300,11 @@ static int setup_guest(int xc_handle, free(page_array); - ctxt->user_regs.eip = elf_uval(&elf, elf.ehdr, e_entry); + /* Set [er]ip in the way that's right for Xen */ + if ( strstr(caps, "x86_64") ) + ctxt->c64.user_regs.rip = elf_uval(&elf, elf.ehdr, e_entry); + else + ctxt->c32.user_regs.eip = elf_uval(&elf, elf.ehdr, e_entry); return 0; @@ -297,7 +320,7 @@ static int xc_hvm_build_internal(int xc_handle, unsigned long image_size) { struct xen_domctl launch_domctl; - vcpu_guest_context_t ctxt; + vcpu_guest_context_either_t ctxt; int rc; if ( (image == NULL) || (image_size == 0) ) @@ -322,7 +345,7 @@ static int xc_hvm_build_internal(int xc_handle, memset(&launch_domctl, 0, sizeof(launch_domctl)); launch_domctl.domain = (domid_t)domid; launch_domctl.u.vcpucontext.vcpu = 0; - set_xen_guest_handle(launch_domctl.u.vcpucontext.ctxt, &ctxt); + set_xen_guest_handle(launch_domctl.u.vcpucontext.ctxt, &ctxt.c); launch_domctl.cmd = XEN_DOMCTL_setvcpucontext; rc = xc_domctl(xc_handle, &launch_domctl); diff --git a/tools/libxc/xc_hvm_restore.c b/tools/libxc/xc_hvm_restore.c index ec3eeb8999..001fe2a6e4 100644 --- a/tools/libxc/xc_hvm_restore.c +++ b/tools/libxc/xc_hvm_restore.c @@ -86,6 +86,8 @@ int xc_hvm_restore(int xc_handle, int io_fd, uint8_t *hvm_buf = NULL; unsigned long long v_end, memsize; unsigned long shared_page_nr; + shared_info_t *shared_info = NULL; + xen_pfn_t arch_max_pfn; unsigned long pfn; unsigned int prev_pc, this_pc; @@ -104,22 +106,19 @@ int xc_hvm_restore(int xc_handle, int io_fd, v_end = memsize << 20; nr_pages = (unsigned long) memsize << (20 - PAGE_SHIFT); - DPRINTF("xc_hvm_restore:dom=%d, nr_pages=0x%lx, store_evtchn=%d, *store_mfn=%ld, pae=%u, apic=%u.\n", + DPRINTF("xc_hvm_restore:dom=%d, nr_pages=0x%lx, store_evtchn=%d, " + "*store_mfn=%ld, pae=%u, apic=%u.\n", dom, nr_pages, store_evtchn, *store_mfn, pae, apic); - if(!get_platform_info(xc_handle, dom, &max_mfn, &hvirt_start, &pt_levels)) { ERROR("Unable to get platform info."); return 1; } - DPRINTF("xc_hvm_restore start: nr_pages = %lx, max_pfn = %lx, max_mfn = %lx, hvirt_start=%lx, pt_levels=%d\n", - nr_pages, - max_pfn, - max_mfn, - hvirt_start, - pt_levels); + DPRINTF("xc_hvm_restore start: nr_pages = %lx, max_pfn = %lx, " + "max_mfn = %lx, hvirt_start=%lx, pt_levels=%d\n", + nr_pages, max_pfn, max_mfn, hvirt_start, pt_levels); if (mlock(&ctxt, sizeof(ctxt))) { /* needed for build dom0 op, but might as well do early */ @@ -144,6 +143,7 @@ int xc_hvm_restore(int xc_handle, int io_fd, pfns[i] = i; for ( i = HVM_BELOW_4G_RAM_END >> PAGE_SHIFT; i < max_pfn; i++ ) pfns[i] += HVM_BELOW_4G_MMIO_LENGTH >> PAGE_SHIFT; + arch_max_pfn = pfns[max_pfn - 1];/* used later */ /* Allocate memory for HVM guest, skipping VGA hole 0xA0000-0xC0000. */ rc = xc_domain_memory_populate_physmap( @@ -220,6 +220,9 @@ int xc_hvm_restore(int xc_handle, int io_fd, void *page; pfn = region_pfn_type[i]; + if ( pfn & XEN_DOMCTL_PFINFO_LTAB_MASK ) + continue; + if ( pfn > max_pfn ) { ERROR("pfn out of range"); @@ -350,6 +353,14 @@ int xc_hvm_restore(int xc_handle, int io_fd, ERROR("setting the shared-info pfn failed!\n"); goto out; } + if ( (xc_memory_op(xc_handle, XENMEM_add_to_physmap, &xatp) != 0) || + ((shared_info = xc_map_foreign_range( + xc_handle, dom, PAGE_SIZE, PROT_READ | PROT_WRITE, + shared_info_frame)) == NULL) ) + goto out; + /* shared_info.arch.max_pfn is used by dump-core */ + shared_info->arch.max_pfn = arch_max_pfn; + munmap(shared_info, PAGE_SIZE); rc = 0; goto out; diff --git a/tools/libxc/xc_hvm_save.c b/tools/libxc/xc_hvm_save.c index fdd2799743..d1b44bd1c6 100644 --- a/tools/libxc/xc_hvm_save.c +++ b/tools/libxc/xc_hvm_save.c @@ -265,7 +265,7 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, { xc_dominfo_t info; - int rc = 1, i, last_iter, iter = 0; + int rc = 1, i, j, last_iter, iter = 0; int live = (flags & XCFLAGS_LIVE); int debug = (flags & XCFLAGS_DEBUG); int sent_last_iter, skip_this_iter; @@ -289,7 +289,7 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, /* base of the region in which domain memory is mapped */ unsigned char *region_base = NULL; - uint32_t nr_pfns, rec_size, nr_vcpus; + uint32_t rec_size, nr_vcpus; /* power of 2 order of max_pfn */ int order_nr; @@ -339,14 +339,7 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, } shared_info_frame = info.shared_info_frame; - /* A cheesy test to see whether the domain contains valid state. */ - if (ctxt.ctrlreg[3] == 0) - { - ERROR("Domain is not in a valid HVM guest state"); - goto out; - } - - /* cheesy sanity check */ + /* cheesy sanity check */ if ((info.max_memkb >> (PAGE_SHIFT - 10)) > max_mfn) { ERROR("Invalid HVM state record -- pfn count out of range: %lu", (info.max_memkb >> (PAGE_SHIFT - 10))); @@ -360,7 +353,8 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, goto out; } - DPRINTF("saved hvm domain info:max_memkb=0x%lx, max_mfn=0x%lx, nr_pages=0x%lx\n", info.max_memkb, max_mfn, info.nr_pages); + DPRINTF("saved hvm domain info:max_memkb=0x%lx, max_mfn=0x%lx, " + "nr_pages=0x%lx\n", info.max_memkb, max_mfn, info.nr_pages); if (live) { ERROR("hvm domain doesn't support live migration now.\n"); @@ -373,10 +367,6 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, goto out; } - /* excludes vga acc mem */ - /* XXX will need to check whether acceleration is enabled here! */ - nr_pfns = info.nr_pages - 0x800; - last_iter = 0; DPRINTF("hvm domain live migration debug start: logdirty enable.\n"); } else { @@ -390,20 +380,15 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, ERROR("HVM Domain appears not to have suspended"); goto out; } - - nr_pfns = info.nr_pages; } - DPRINTF("after 1st handle hvm domain nr_pfns=0x%x, nr_pages=0x%lx, max_memkb=0x%lx, live=%d.\n", - nr_pfns, - info.nr_pages, - info.max_memkb, - live); + DPRINTF("after 1st handle hvm domain nr_pages=0x%lx, " + "max_memkb=0x%lx, live=%d.\n", + info.nr_pages, info.max_memkb, live); /* Calculate the highest PFN of "normal" memory: - * HVM memory is sequential except for the VGA and MMIO holes, and - * we have nr_pfns of it (which now excludes the cirrus video RAM) */ - max_pfn = nr_pfns; + * HVM memory is sequential except for the VGA and MMIO holes. */ + max_pfn = info.nr_pages; /* Skip the VGA hole from 0xa0000 to 0xc0000 */ max_pfn += 0x20; /* Skip the MMIO hole: 256MB just below 4GB */ @@ -556,9 +541,16 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, goto out; } - if (ratewrite(io_fd, region_base, PAGE_SIZE * batch) != PAGE_SIZE * batch) { - ERROR("ERROR when writting to state file (4)"); - goto out; + for ( j = 0; j < batch; j++ ) + { + if ( pfn_batch[j] & XEN_DOMCTL_PFINFO_LTAB_MASK ) + continue; + if ( ratewrite(io_fd, region_base + j*PAGE_SIZE, + PAGE_SIZE) != PAGE_SIZE ) + { + ERROR("ERROR when writing to state file (4)"); + goto out; + } } sent_this_iter += batch; diff --git a/tools/libxc/xc_linux.c b/tools/libxc/xc_linux.c index fa4927aafa..eac5acc793 100644 --- a/tools/libxc/xc_linux.c +++ b/tools/libxc/xc_linux.c @@ -328,6 +328,41 @@ int xc_evtchn_unmask(int xce_handle, evtchn_port_t port) return dorw(xce_handle, (char *)&port, sizeof(port), 1); } +/* Optionally flush file to disk and discard page cache */ +void discard_file_cache(int fd, int flush) +{ + off_t cur = 0; + int saved_errno = errno; + + if ( flush && (fsync(fd) < 0) ) + { + /*PERROR("Failed to flush file: %s", strerror(errno));*/ + goto out; + } + + /* + * Calculate last page boundary of amount written so far + * unless we are flushing in which case entire cache + * is discarded. + */ + if ( !flush ) + { + if ( (cur = lseek(fd, 0, SEEK_CUR)) == (off_t)-1 ) + cur = 0; + cur &= ~(PAGE_SIZE-1); + } + + /* Discard from the buffer cache. */ + if ( posix_fadvise64(fd, 0, cur, POSIX_FADV_DONTNEED) < 0 ) + { + /*PERROR("Failed to discard cache: %s", strerror(errno));*/ + goto out; + } + + out: + errno = saved_errno; +} + /* * Local variables: * mode: C diff --git a/tools/libxc/xc_linux_restore.c b/tools/libxc/xc_linux_restore.c index 822f3c5ec2..6fa0388d3f 100644 --- a/tools/libxc/xc_linux_restore.c +++ b/tools/libxc/xc_linux_restore.c @@ -11,6 +11,7 @@ #include "xg_private.h" #include "xg_save_restore.h" +#include "xc_dom.h" /* max mfn of the current host machine */ static unsigned long max_mfn; @@ -18,7 +19,7 @@ static unsigned long max_mfn; /* virtual starting address of the hypervisor */ static unsigned long hvirt_start; -/* #levels of page tables used by the currrent guest */ +/* #levels of page tables used by the current guest */ static unsigned int pt_levels; /* total number of pages used by the current guest */ @@ -143,7 +144,7 @@ int xc_linux_restore(int xc_handle, int io_fd, unsigned int console_evtchn, unsigned long *console_mfn) { DECLARE_DOMCTL; - int rc = 1, i, n, pae_extended_cr3 = 0; + int rc = 1, i, j, n, m, pae_extended_cr3 = 0; unsigned long mfn, pfn; unsigned int prev_pc, this_pc; int verify = 0; @@ -186,11 +187,26 @@ int xc_linux_restore(int xc_handle, int io_fd, struct mmuext_op pin[MAX_PIN_BATCH]; unsigned int nr_pins; + uint64_t vcpumap = 1ULL; + unsigned int max_vcpu_id = 0; max_pfn = nr_pfns; DPRINTF("xc_linux_restore start: max_pfn = %lx\n", max_pfn); + /* + * XXX For now, 32bit dom0's can only save/restore 32bit domUs + * on 64bit hypervisors. + */ + memset(&domctl, 0, sizeof(domctl)); + domctl.domain = dom; + domctl.cmd = XEN_DOMCTL_set_address_size; + domctl.u.address_size.size = sizeof(unsigned long) * 8; + rc = do_domctl(xc_handle, &domctl); + if ( rc != 0 ) { + ERROR("Unable to set guest address size."); + goto out; + } if(!get_platform_info(xc_handle, dom, &max_mfn, &hvirt_start, &pt_levels)) { @@ -330,7 +346,7 @@ int xc_linux_restore(int xc_handle, int io_fd, */ prev_pc = 0; - n = 0; + n = m = 0; while (1) { int j, nr_mfns = 0; @@ -355,6 +371,16 @@ int xc_linux_restore(int xc_handle, int io_fd, continue; } + if (j == -2) { + if (!read_exact(io_fd, &max_vcpu_id, sizeof(int)) || + (max_vcpu_id >= 64) || + !read_exact(io_fd, &vcpumap, sizeof(uint64_t))) { + ERROR("Error when reading max_vcpu_id"); + goto out; + } + continue; + } + if (j == 0) break; /* our work here is done */ @@ -529,6 +555,17 @@ int xc_linux_restore(int xc_handle, int io_fd, munmap(region_base, j*PAGE_SIZE); n+= j; /* crude stats */ + + /* + * Discard cache for portion of file read so far up to last + * page boundary every 16MB or so. + */ + m += j; + if ( m > MAX_PAGECACHE_USAGE ) + { + discard_file_cache(io_fd, 0 /* no flush */); + m = 0; + } } /* @@ -751,65 +788,113 @@ int xc_linux_restore(int xc_handle, int io_fd, } } - if (!read_exact(io_fd, &ctxt, sizeof(ctxt)) || - !read_exact(io_fd, shared_info_page, PAGE_SIZE)) { - ERROR("Error when reading ctxt or shared info page"); - goto out; - } + for (i = 0; i <= max_vcpu_id; i++) { + if (!(vcpumap & (1ULL << i))) + continue; - /* Uncanonicalise the suspend-record frame number and poke resume rec. */ - pfn = ctxt.user_regs.edx; - if ((pfn >= max_pfn) || (pfn_type[pfn] != XEN_DOMCTL_PFINFO_NOTAB)) { - ERROR("Suspend record frame number is bad"); - goto out; - } - ctxt.user_regs.edx = mfn = p2m[pfn]; - start_info = xc_map_foreign_range( - xc_handle, dom, PAGE_SIZE, PROT_READ | PROT_WRITE, mfn); - start_info->nr_pages = max_pfn; - start_info->shared_info = shared_info_frame << PAGE_SHIFT; - start_info->flags = 0; - *store_mfn = start_info->store_mfn = p2m[start_info->store_mfn]; - start_info->store_evtchn = store_evtchn; - start_info->console.domU.mfn = p2m[start_info->console.domU.mfn]; - start_info->console.domU.evtchn = console_evtchn; - *console_mfn = start_info->console.domU.mfn; - munmap(start_info, PAGE_SIZE); - - /* Uncanonicalise each GDT frame number. */ - if (ctxt.gdt_ents > 8192) { - ERROR("GDT entry count out of range"); - goto out; - } - - for (i = 0; (512*i) < ctxt.gdt_ents; i++) { - pfn = ctxt.gdt_frames[i]; - if ((pfn >= max_pfn) || (pfn_type[pfn] != XEN_DOMCTL_PFINFO_NOTAB)) { - ERROR("GDT frame number is bad"); + if (!read_exact(io_fd, &ctxt, sizeof(ctxt))) { + ERROR("Error when reading ctxt %d", i); + goto out; + } + + if (i == 0) { + /* + * Uncanonicalise the suspend-record frame number and poke + * resume record. + */ + pfn = ctxt.user_regs.edx; + if ((pfn >= max_pfn) || + (pfn_type[pfn] != XEN_DOMCTL_PFINFO_NOTAB)) { + ERROR("Suspend record frame number is bad"); + goto out; + } + ctxt.user_regs.edx = mfn = p2m[pfn]; + start_info = xc_map_foreign_range( + xc_handle, dom, PAGE_SIZE, PROT_READ | PROT_WRITE, mfn); + start_info->nr_pages = max_pfn; + start_info->shared_info = shared_info_frame << PAGE_SHIFT; + start_info->flags = 0; + *store_mfn = start_info->store_mfn = p2m[start_info->store_mfn]; + start_info->store_evtchn = store_evtchn; + start_info->console.domU.mfn = p2m[start_info->console.domU.mfn]; + start_info->console.domU.evtchn = console_evtchn; + *console_mfn = start_info->console.domU.mfn; + munmap(start_info, PAGE_SIZE); + } + + /* Uncanonicalise each GDT frame number. */ + if (ctxt.gdt_ents > 8192) { + ERROR("GDT entry count out of range"); + goto out; + } + + for (j = 0; (512*j) < ctxt.gdt_ents; j++) { + pfn = ctxt.gdt_frames[j]; + if ((pfn >= max_pfn) || + (pfn_type[pfn] != XEN_DOMCTL_PFINFO_NOTAB)) { + ERROR("GDT frame number is bad"); + goto out; + } + ctxt.gdt_frames[j] = p2m[pfn]; + } + + /* Uncanonicalise the page table base pointer. */ + pfn = xen_cr3_to_pfn(ctxt.ctrlreg[3]); + + if (pfn >= max_pfn) { + ERROR("PT base is bad: pfn=%lu max_pfn=%lu type=%08lx", + pfn, max_pfn, pfn_type[pfn]); + goto out; + } + + if ( (pfn_type[pfn] & XEN_DOMCTL_PFINFO_LTABTYPE_MASK) != + ((unsigned long)pt_levels<= max_pfn) { + ERROR("User PT base is bad: pfn=%lu max_pfn=%lu type=%08lx", + pfn, max_pfn, pfn_type[pfn]); + goto out; + } + + if ( (pfn_type[pfn] & XEN_DOMCTL_PFINFO_LTABTYPE_MASK) != + ((unsigned long)pt_levels<= max_pfn) { - ERROR("PT base is bad: pfn=%lu max_pfn=%lu type=%08lx", - pfn, max_pfn, pfn_type[pfn]); + if (!read_exact(io_fd, shared_info_page, PAGE_SIZE)) { + ERROR("Error when reading shared info page"); goto out; } - if ( (pfn_type[pfn] & XEN_DOMCTL_PFINFO_LTABTYPE_MASK) != - ((unsigned long)pt_levels<evtchn_pending[0]), 0, sizeof (shared_info->evtchn_pending)); @@ -845,17 +930,6 @@ int xc_linux_restore(int xc_handle, int io_fd, DPRINTF("Domain ready to be built.\n"); - domctl.cmd = XEN_DOMCTL_setvcpucontext; - domctl.domain = (domid_t)dom; - domctl.u.vcpucontext.vcpu = 0; - set_xen_guest_handle(domctl.u.vcpucontext.ctxt, &ctxt); - rc = xc_domctl(xc_handle, &domctl); - - if (rc != 0) { - ERROR("Couldn't build the domain"); - goto out; - } - out: if ( (rc != 0) && (dom != 0) ) xc_domain_destroy(xc_handle, dom); @@ -863,6 +937,9 @@ int xc_linux_restore(int xc_handle, int io_fd, free(p2m); free(pfn_type); + /* discard cache for save file */ + discard_file_cache(io_fd, 1 /*flush*/); + DPRINTF("Restore exit with rc=%d\n", rc); return rc; diff --git a/tools/libxc/xc_linux_save.c b/tools/libxc/xc_linux_save.c index 8930b9fc3c..f9800c4d5f 100644 --- a/tools/libxc/xc_linux_save.c +++ b/tools/libxc/xc_linux_save.c @@ -13,6 +13,7 @@ #include #include "xc_private.h" +#include "xc_dom.h" #include "xg_private.h" #include "xg_save_restore.h" @@ -33,7 +34,7 @@ static unsigned long max_mfn; /* virtual starting address of the hypervisor */ static unsigned long hvirt_start; -/* #levels of page tables used by the currrent guest */ +/* #levels of page tables used by the current guest */ static unsigned int pt_levels; /* total number of pages used by the current guest */ @@ -171,6 +172,22 @@ static uint64_t tv_delta(struct timeval *new, struct timeval *old) (new->tv_usec - old->tv_usec); } +static int noncached_write(int fd, int live, void *buffer, int len) +{ + static int write_count = 0; + + int rc = write(fd,buffer,len); + + write_count += len; + + if (write_count >= MAX_PAGECACHE_USAGE*PAGE_SIZE) { + /* Time to discard cache - dont care if this fails */ + discard_file_cache(fd, 0 /* no flush */); + write_count = 0; + } + + return rc; +} #ifdef ADAPTIVE_SAVE @@ -204,7 +221,7 @@ static inline void initialize_mbit_rate() } -static int ratewrite(int io_fd, void *buf, int n) +static int ratewrite(int io_fd, int live, void *buf, int n) { static int budget = 0; static int burst_time_us = -1; @@ -214,7 +231,7 @@ static int ratewrite(int io_fd, void *buf, int n) long long delta; if (START_MBIT_RATE == 0) - return write(io_fd, buf, n); + return noncached_write(io_fd, live, buf, n); budget -= n; if (budget < 0) { @@ -250,13 +267,13 @@ static int ratewrite(int io_fd, void *buf, int n) } } } - return write(io_fd, buf, n); + return noncached_write(io_fd, live, buf, n); } #else /* ! ADAPTIVE SAVE */ #define RATE_IS_MAX() (0) -#define ratewrite(_io_fd, _buf, _n) write((_io_fd), (_buf), (_n)) +#define ratewrite(_io_fd, _live, _buf, _n) noncached_write((_io_fd), (_live), (_buf), (_n)) #define initialize_mbit_rate() #endif @@ -474,7 +491,7 @@ static int canonicalize_pagetable(unsigned long type, unsigned long pfn, ** reserved hypervisor mappings. This depends on the current ** page table type as well as the number of paging levels. */ - xen_start = xen_end = pte_last = PAGE_SIZE / ((pt_levels == 2)? 4 : 8); + xen_start = xen_end = pte_last = PAGE_SIZE / ((pt_levels == 2) ? 4 : 8); if (pt_levels == 2 && type == XEN_DOMCTL_PFINFO_L2TAB) xen_start = (hvirt_start >> L2_PAGETABLE_SHIFT); @@ -490,7 +507,7 @@ static int canonicalize_pagetable(unsigned long type, unsigned long pfn, */ if (pt_levels == 3 && type == XEN_DOMCTL_PFINFO_L2TAB) { int hstart; - unsigned long he; + uint64_t he; hstart = (hvirt_start >> L2_PAGETABLE_SHIFT_PAE) & 0x1ff; he = ((const uint64_t *) spage)[hstart]; @@ -543,6 +560,18 @@ static int canonicalize_pagetable(unsigned long type, unsigned long pfn, pte &= ~MADDR_MASK_X86; pte |= (uint64_t)pfn << PAGE_SHIFT; + + /* + * PAE guest L3Es can contain these flags when running on + * a 64bit hypervisor. We zap these here to avoid any + * surprise at restore time... + */ + if ( pt_levels == 3 && + type == XEN_DOMCTL_PFINFO_L3TAB && + pte & (_PAGE_USER|_PAGE_RW|_PAGE_ACCESSED) ) + { + pte &= ~(_PAGE_USER|_PAGE_RW|_PAGE_ACCESSED); + } } if (pt_levels == 2) @@ -667,6 +696,7 @@ int xc_linux_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, unsigned long needed_to_fix = 0; unsigned long total_sent = 0; + uint64_t vcpumap = 1ULL; /* If no explicit control parameters given, use defaults */ if(!max_iters) @@ -687,25 +717,12 @@ int xc_linux_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, return 1; } - if (lock_pages(&ctxt, sizeof(ctxt))) { - ERROR("Unable to lock ctxt"); - return 1; - } - - /* Only have to worry about vcpu 0 even for SMP */ if (xc_vcpu_getcontext(xc_handle, dom, 0, &ctxt)) { ERROR("Could not get vcpu context"); goto out; } shared_info_frame = info.shared_info_frame; - /* A cheesy test to see whether the domain contains valid state. */ - if (ctxt.ctrlreg[3] == 0) - { - ERROR("Domain is not in a valid Linux guest OS state"); - goto out; - } - /* Map the shared info frame */ if(!(live_shinfo = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE, PROT_READ, shared_info_frame))) { @@ -1066,10 +1083,13 @@ int xc_linux_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, race = canonicalize_pagetable(pagetype, pfn, spage, page); - if(race && !live) - goto out; + if(race && !live) { + ERROR("Fatal PT race (pfn %lx, type %08lx)", pfn, + pagetype); + goto out; + } - if (ratewrite(io_fd, page, PAGE_SIZE) != PAGE_SIZE) { + if (ratewrite(io_fd, live, page, PAGE_SIZE) != PAGE_SIZE) { ERROR("Error when writing to state file (4)" " (errno %d)", errno); goto out; @@ -1078,7 +1098,7 @@ int xc_linux_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, } else { /* We have a normal page: just write it directly. */ - if (ratewrite(io_fd, spage, PAGE_SIZE) != PAGE_SIZE) { + if (ratewrite(io_fd, live, spage, PAGE_SIZE) != PAGE_SIZE) { ERROR("Error when writing to state file (5)" " (errno %d)", errno); goto out; @@ -1162,6 +1182,32 @@ int xc_linux_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, DPRINTF("All memory is saved\n"); + { + struct { + int minustwo; + int max_vcpu_id; + uint64_t vcpumap; + } chunk = { -2, info.max_vcpu_id }; + + if (info.max_vcpu_id >= 64) { + ERROR("Too many VCPUS in guest!"); + goto out; + } + + for (i = 1; i <= info.max_vcpu_id; i++) { + xc_vcpuinfo_t vinfo; + if ((xc_vcpu_getinfo(xc_handle, dom, i, &vinfo) == 0) && + vinfo.online) + vcpumap |= 1ULL << i; + } + + chunk.vcpumap = vcpumap; + if(!write_exact(io_fd, &chunk, sizeof(chunk))) { + ERROR("Error when writing to state file (errno %d)", errno); + goto out; + } + } + /* Zero terminate */ i = 0; if (!write_exact(io_fd, &i, sizeof(int))) { @@ -1208,30 +1254,55 @@ int xc_linux_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, goto out; } - /* Canonicalise each GDT frame number. */ - for ( i = 0; (512*i) < ctxt.gdt_ents; i++ ) { - if ( !translate_mfn_to_pfn(&ctxt.gdt_frames[i]) ) { - ERROR("GDT frame is not in range of pseudophys map"); + for (i = 0; i <= info.max_vcpu_id; i++) { + if (!(vcpumap & (1ULL << i))) + continue; + + if ((i != 0) && xc_vcpu_getcontext(xc_handle, dom, i, &ctxt)) { + ERROR("No context for VCPU%d", i); + goto out; + } + + /* Canonicalise each GDT frame number. */ + for ( j = 0; (512*j) < ctxt.gdt_ents; j++ ) { + if ( !translate_mfn_to_pfn(&ctxt.gdt_frames[j]) ) { + ERROR("GDT frame is not in range of pseudophys map"); + goto out; + } + } + + /* Canonicalise the page table base pointer. */ + if ( !MFN_IS_IN_PSEUDOPHYS_MAP(xen_cr3_to_pfn(ctxt.ctrlreg[3])) ) { + ERROR("PT base is not in range of pseudophys map"); + goto out; + } + ctxt.ctrlreg[3] = + xen_pfn_to_cr3(mfn_to_pfn(xen_cr3_to_pfn(ctxt.ctrlreg[3]))); + + /* Guest pagetable (x86/64) stored in otherwise-unused CR1. */ + if ( (pt_levels == 4) && ctxt.ctrlreg[1] ) + { + if ( !MFN_IS_IN_PSEUDOPHYS_MAP(xen_cr3_to_pfn(ctxt.ctrlreg[1])) ) { + ERROR("PT base is not in range of pseudophys map"); + goto out; + } + /* Least-significant bit means 'valid PFN'. */ + ctxt.ctrlreg[1] = 1 | + xen_pfn_to_cr3(mfn_to_pfn(xen_cr3_to_pfn(ctxt.ctrlreg[1]))); + } + + if (!write_exact(io_fd, &ctxt, sizeof(ctxt))) { + ERROR("Error when writing to state file (1) (errno %d)", errno); goto out; } } - /* Canonicalise the page table base pointer. */ - if ( !MFN_IS_IN_PSEUDOPHYS_MAP(xen_cr3_to_pfn(ctxt.ctrlreg[3])) ) { - ERROR("PT base is not in range of pseudophys map"); - goto out; - } - ctxt.ctrlreg[3] = - xen_pfn_to_cr3(mfn_to_pfn(xen_cr3_to_pfn(ctxt.ctrlreg[3]))); - /* * Reset the MFN to be a known-invalid value. See map_frame_list_list(). */ memcpy(page, live_shinfo, PAGE_SIZE); ((shared_info_t *)page)->arch.pfn_to_mfn_frame_list_list = 0; - - if (!write_exact(io_fd, &ctxt, sizeof(ctxt)) || - !write_exact(io_fd, page, PAGE_SIZE)) { + if (!write_exact(io_fd, page, PAGE_SIZE)) { ERROR("Error when writing to state file (1) (errno %d)", errno); goto out; } @@ -1249,6 +1320,9 @@ int xc_linux_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, } } + // flush last write and discard cache for file + discard_file_cache(io_fd, 1 /* flush */); + if (live_shinfo) munmap(live_shinfo, PAGE_SIZE); @@ -1258,10 +1332,10 @@ int xc_linux_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, if (live_p2m_frame_list) munmap(live_p2m_frame_list, P2M_FLL_ENTRIES * PAGE_SIZE); - if(live_p2m) + if (live_p2m) munmap(live_p2m, P2M_SIZE); - if(live_m2p) + if (live_m2p) munmap(live_m2p, M2P_SIZE(max_mfn)); free(pfn_type); diff --git a/tools/libxc/xc_private.c b/tools/libxc/xc_private.c index 0b2e10527a..77321c458b 100644 --- a/tools/libxc/xc_private.c +++ b/tools/libxc/xc_private.c @@ -100,7 +100,7 @@ int lock_pages(void *addr, size_t len) void unlock_pages(void *addr, size_t len) { #ifndef __sun__ - safe_munlock(addr, len); + safe_munlock(addr, len); #endif } diff --git a/tools/libxc/xc_private.h b/tools/libxc/xc_private.h index 7705063326..7fa3258db1 100644 --- a/tools/libxc/xc_private.h +++ b/tools/libxc/xc_private.h @@ -41,6 +41,13 @@ #define INFO 1 #define PROGRESS 0 +/* +** Define max dirty page cache to permit during save/restore -- need to balance +** keeping cache usage down with CPU impact of invalidating too often. +** (Currently 16MB) +*/ +#define MAX_PAGECACHE_USAGE (4*1024) + #if INFO #define IPRINTF(_f, _a...) printf(_f , ## _a) #else @@ -158,4 +165,7 @@ int xc_waitdomain_core(int xc_handle, int domain, int *status, void bitmap_64_to_byte(uint8_t *bp, const uint64_t *lp, int nbits); void bitmap_byte_to_64(uint64_t *lp, const uint8_t *bp, int nbits); +/* Optionally flush file to disk and discard page cache */ +void discard_file_cache(int fd, int flush); + #endif /* __XC_PRIVATE_H__ */ diff --git a/tools/libxc/xc_ptrace_core.c b/tools/libxc/xc_ptrace_core.c index 3ae69d3ac2..82d06bb2d8 100644 --- a/tools/libxc/xc_ptrace_core.c +++ b/tools/libxc/xc_ptrace_core.c @@ -1,32 +1,41 @@ +/* + * New elf format support. + * Copyright (c) 2007 Isaku Yamahata + * VA Linux Systems Japan K.K. + */ + #include #include #include "xc_private.h" #include "xg_private.h" #include "xc_ptrace.h" #include +#include +/* Leave the code for the old format as is. */ +/* --- compatible layer for old format ------------------------------------- */ /* XXX application state */ -static int current_is_hvm = 0; -static long nr_pages = 0; -static unsigned long *p2m_array = NULL; -static unsigned long *m2p_array = NULL; -static unsigned long pages_offset; -static unsigned long cr3[MAX_VIRT_CPUS]; +static int current_is_hvm_compat = 0; +static long nr_pages_compat = 0; +static unsigned long *p2m_array_compat = NULL; +static unsigned long *m2p_array_compat = NULL; +static unsigned long pages_offset_compat; +static unsigned long cr3_compat[MAX_VIRT_CPUS]; /* --------------------- */ static unsigned long -map_mtop_offset(unsigned long ma) +map_mtop_offset_compat(unsigned long ma) { - return pages_offset + (m2p_array[ma >> PAGE_SHIFT] << PAGE_SHIFT); + return pages_offset_compat + (m2p_array_compat[ma >> PAGE_SHIFT] << PAGE_SHIFT); return 0; } -void * -map_domain_va_core(unsigned long domfd, int cpu, void *guest_va, - vcpu_guest_context_t *ctxt) +static void * +map_domain_va_core_compat(unsigned long domfd, int cpu, void *guest_va, + vcpu_guest_context_t *ctxt) { unsigned long pde, page; unsigned long va = (unsigned long)guest_va; @@ -39,14 +48,14 @@ map_domain_va_core(unsigned long domfd, int cpu, void *guest_va, static unsigned long page_phys[MAX_VIRT_CPUS]; static unsigned long *page_virt[MAX_VIRT_CPUS]; - if (cr3[cpu] != cr3_phys[cpu]) + if (cr3_compat[cpu] != cr3_phys[cpu]) { - cr3_phys[cpu] = cr3[cpu]; + cr3_phys[cpu] = cr3_compat[cpu]; if (cr3_virt[cpu]) munmap(cr3_virt[cpu], PAGE_SIZE); v = mmap( NULL, PAGE_SIZE, PROT_READ, MAP_PRIVATE, domfd, - map_mtop_offset(xen_cr3_to_pfn(cr3_phys[cpu]))); + map_mtop_offset_compat(xen_cr3_to_pfn(cr3_phys[cpu]))); if (v == MAP_FAILED) { perror("mmap failed"); @@ -56,8 +65,8 @@ map_domain_va_core(unsigned long domfd, int cpu, void *guest_va, } if ((pde = cr3_virt[cpu][l2_table_offset_i386(va)]) == 0) /* logical address */ return NULL; - if (current_is_hvm) - pde = p2m_array[pde >> PAGE_SHIFT] << PAGE_SHIFT; + if (current_is_hvm_compat) + pde = p2m_array_compat[pde >> PAGE_SHIFT] << PAGE_SHIFT; if (pde != pde_phys[cpu]) { pde_phys[cpu] = pde; @@ -65,15 +74,15 @@ map_domain_va_core(unsigned long domfd, int cpu, void *guest_va, munmap(pde_virt[cpu], PAGE_SIZE); v = mmap( NULL, PAGE_SIZE, PROT_READ, MAP_PRIVATE, domfd, - map_mtop_offset(pde_phys[cpu])); + map_mtop_offset_compat(pde_phys[cpu])); if (v == MAP_FAILED) return NULL; pde_virt[cpu] = v; } if ((page = pde_virt[cpu][l1_table_offset_i386(va)]) == 0) /* logical address */ return NULL; - if (current_is_hvm) - page = p2m_array[page >> PAGE_SHIFT] << PAGE_SHIFT; + if (current_is_hvm_compat) + page = p2m_array_compat[page >> PAGE_SHIFT] << PAGE_SHIFT; if (page != page_phys[cpu]) { page_phys[cpu] = page; @@ -81,10 +90,10 @@ map_domain_va_core(unsigned long domfd, int cpu, void *guest_va, munmap(page_virt[cpu], PAGE_SIZE); v = mmap( NULL, PAGE_SIZE, PROT_READ, MAP_PRIVATE, domfd, - map_mtop_offset(page_phys[cpu])); + map_mtop_offset_compat(page_phys[cpu])); if (v == MAP_FAILED) { - IPRINTF("cr3 %lx pde %lx page %lx pti %lx\n", cr3[cpu], pde, page, l1_table_offset_i386(va)); + IPRINTF("cr3 %lx pde %lx page %lx pti %lx\n", cr3_compat[cpu], pde, page, l1_table_offset_i386(va)); page_phys[cpu] = 0; return NULL; } @@ -93,8 +102,8 @@ map_domain_va_core(unsigned long domfd, int cpu, void *guest_va, return (void *)(((unsigned long)page_virt[cpu]) | (va & BSD_PAGE_MASK)); } -int -xc_waitdomain_core( +static int +xc_waitdomain_core_compat( int xc_handle, int domfd, int *status, @@ -105,13 +114,13 @@ xc_waitdomain_core( int i; xc_core_header_t header; - if ( nr_pages == 0 ) + if ( nr_pages_compat == 0 ) { if (read(domfd, &header, sizeof(header)) != sizeof(header)) return -1; - current_is_hvm = (header.xch_magic == XC_CORE_MAGIC_HVM); - if ( !current_is_hvm && (header.xch_magic != XC_CORE_MAGIC) ) + current_is_hvm_compat = (header.xch_magic == XC_CORE_MAGIC_HVM); + if ( !current_is_hvm_compat && (header.xch_magic != XC_CORE_MAGIC) ) { IPRINTF("Magic number missmatch: 0x%08x (file) != " " 0x%08x (code)\n", header.xch_magic, @@ -119,40 +128,546 @@ xc_waitdomain_core( return -1; } - nr_pages = header.xch_nr_pages; + nr_pages_compat = header.xch_nr_pages; nr_vcpus = header.xch_nr_vcpus; - pages_offset = header.xch_pages_offset; + pages_offset_compat = header.xch_pages_offset; if (read(domfd, ctxt, sizeof(vcpu_guest_context_t)*nr_vcpus) != sizeof(vcpu_guest_context_t)*nr_vcpus) return -1; for (i = 0; i < nr_vcpus; i++) - cr3[i] = ctxt[i].ctrlreg[3]; + cr3_compat[i] = ctxt[i].ctrlreg[3]; - if ((p2m_array = malloc(nr_pages * sizeof(unsigned long))) == NULL) + if ((p2m_array_compat = malloc(nr_pages_compat * sizeof(unsigned long))) == NULL) { IPRINTF("Could not allocate p2m_array\n"); return -1; } - if (read(domfd, p2m_array, sizeof(unsigned long)*nr_pages) != - sizeof(unsigned long)*nr_pages) + if (read(domfd, p2m_array_compat, sizeof(unsigned long)*nr_pages_compat) != + sizeof(unsigned long)*nr_pages_compat) return -1; - if ((m2p_array = malloc((1<<20) * sizeof(unsigned long))) == NULL) + if ((m2p_array_compat = malloc((1<<20) * sizeof(unsigned long))) == NULL) { IPRINTF("Could not allocate m2p array\n"); return -1; } - bzero(m2p_array, sizeof(unsigned long)* 1 << 20); + bzero(m2p_array_compat, sizeof(unsigned long)* 1 << 20); - for (i = 0; i < nr_pages; i++) - m2p_array[p2m_array[i]] = i; + for (i = 0; i < nr_pages_compat; i++) + m2p_array_compat[p2m_array_compat[i]] = i; } return 0; } + +/* --- new format based on ELF -------------------------------------------- */ +#include "xc_core.h" + +static int +pread_exact(int fd, void* buffer, size_t size, off_t offset) +{ + off_t ret; + unsigned char *buf = buffer; + size_t done = 0; + ret = lseek(fd, offset, SEEK_SET); + if (ret < 0 || ret != offset) + return -1; + + while (done < size) { + ssize_t s = read(fd, buf, size - done); + if (s == -1 && errno == EINTR) + continue; + if (s <= 0) + return -1; + + done += s; + buf += s; + } + return 0; +} + +struct elf_core +{ + int domfd; + Elf64_Ehdr ehdr; + + char* shdr; + + char* shstrtab; + uint64_t shstrtab_size; + + char* note_sec; + uint64_t note_sec_size; +}; + +static int +elf_core_alloc_read_sec_by_index(struct elf_core* ecore, uint16_t index, + char** buf, uint64_t* size); +static int +elf_core_alloc_read_sec_by_name(struct elf_core* ecore, const char* name, + char** buf, uint64_t* size); + +static void +elf_core_free(struct elf_core* ecore) +{ + if (ecore->shdr != NULL) { + free(ecore->shdr); + ecore->shdr = NULL; + } + if (ecore->shstrtab != NULL) { + free(ecore->shstrtab); + ecore->shstrtab = NULL; + } + if (ecore->note_sec != NULL) { + free(ecore->note_sec); + ecore->note_sec = NULL; + } +} + +static int +elf_core_init(struct elf_core* ecore, int domfd) +{ + uint64_t sh_size; + ecore->domfd = domfd; + ecore->shdr = NULL; + ecore->shstrtab = NULL; + ecore->note_sec = NULL; + + if (pread_exact(ecore->domfd, &ecore->ehdr, sizeof(ecore->ehdr), 0) < 0) + goto out; + + /* check elf header */ + if (!IS_ELF(ecore->ehdr) || ecore->ehdr.e_type != ET_CORE) + goto out; + if (ecore->ehdr.e_ident[EI_CLASS] != ELFCLASS64) + goto out; + /* check elf header more: EI_DATA, EI_VERSION, e_machine... */ + + /* read section headers */ + sh_size = ecore->ehdr.e_shentsize * ecore->ehdr.e_shnum; + ecore->shdr = malloc(sh_size); + if (ecore->shdr == NULL) + goto out; + if (pread_exact(ecore->domfd, ecore->shdr, sh_size, + ecore->ehdr.e_shoff) < 0) + goto out; + + /* read shstrtab */ + if (elf_core_alloc_read_sec_by_index(ecore, ecore->ehdr.e_shstrndx, + &ecore->shstrtab, + &ecore->shstrtab_size) < 0) + goto out; + + /* read .note.Xen section */ + if (elf_core_alloc_read_sec_by_name(ecore, XEN_DUMPCORE_SEC_NOTE, + &ecore->note_sec, + &ecore->note_sec_size) < 0) + goto out; + + return 0; +out: + elf_core_free(ecore); + return -1; +} + +static int +elf_core_search_note(struct elf_core* ecore, const char* name, uint32_t type, + void** elfnotep) +{ + const char* note_sec_end = ecore->note_sec + ecore->note_sec_size; + const char* n; + + n = ecore->note_sec; + while (n < note_sec_end) { + const struct elfnote *elfnote = (const struct elfnote *)n; + if (elfnote->namesz == strlen(name) + 1 && + strncmp(elfnote->name, name, elfnote->namesz) == 0 && + elfnote->type == type) { + *elfnotep = (void*)elfnote; + return 0; + } + + n += sizeof(*elfnote) + elfnote->descsz; + } + return -1; +} + +static int +elf_core_alloc_read_sec(struct elf_core* ecore, const Elf64_Shdr* shdr, + char** buf) +{ + int ret; + *buf = malloc(shdr->sh_size); + if (*buf == NULL) + return -1; + ret = pread_exact(ecore->domfd, *buf, shdr->sh_size, shdr->sh_offset); + if (ret < 0) { + free(*buf); + *buf = NULL; + } + return ret; +} + +static Elf64_Shdr* +elf_core_shdr_by_index(struct elf_core* ecore, uint16_t index) +{ + if (index >= ecore->ehdr.e_shnum) + return NULL; + return (Elf64_Shdr*)(ecore->shdr + ecore->ehdr.e_shentsize * index); +} + +static int +elf_core_alloc_read_sec_by_index(struct elf_core* ecore, uint16_t index, + char** buf, uint64_t* size) +{ + Elf64_Shdr* shdr = elf_core_shdr_by_index(ecore, index); + if (shdr == NULL) + return -1; + if (size != NULL) + *size = shdr->sh_size; + return elf_core_alloc_read_sec(ecore, shdr, buf); +} + +static Elf64_Shdr* +elf_core_shdr_by_name(struct elf_core* ecore, const char* name) +{ + const char* s; + for (s = ecore->shdr; + s < ecore->shdr + ecore->ehdr.e_shentsize * ecore->ehdr.e_shnum; + s += ecore->ehdr.e_shentsize) { + Elf64_Shdr* shdr = (Elf64_Shdr*)s; + + if (strncmp(ecore->shstrtab + shdr->sh_name, name, strlen(name)) == 0) + return shdr; + } + + return NULL; +} + +static int +elf_core_read_sec_by_name(struct elf_core* ecore, const char* name, char* buf) +{ + Elf64_Shdr* shdr = elf_core_shdr_by_name(ecore, name); + return pread_exact(ecore->domfd, buf, shdr->sh_size, shdr->sh_offset); + +} + +static int +elf_core_alloc_read_sec_by_name(struct elf_core* ecore, const char* name, + char** buf, uint64_t* size) +{ + Elf64_Shdr* shdr = elf_core_shdr_by_name(ecore, name); + if (shdr == NULL) + return -1; + if (size != NULL) + *size = shdr->sh_size; + return elf_core_alloc_read_sec(ecore, shdr, buf); +} + +/* XXX application state */ +static int current_is_auto_translated_physmap = 0; +static struct xen_dumpcore_p2m* p2m_array = NULL; /* for non auto translated physmap mode */ +static uint64_t p2m_array_size = 0; +static uint64_t* pfn_array = NULL; /* for auto translated physmap mode */ +static uint64_t pfn_array_size = 0; +static long nr_pages = 0; +static uint64_t pages_offset; +static unsigned long cr3[MAX_VIRT_CPUS]; + +static const struct xen_dumpcore_elfnote_format_version_desc +known_format_version[] = +{ + {XEN_DUMPCORE_FORMAT_VERSION((uint64_t)0, (uint64_t)1)}, +}; +#define KNOWN_FORMAT_VERSION_NR \ + (sizeof(known_format_version)/sizeof(known_format_version[0])) + +static unsigned long +map_gmfn_to_offset_elf(unsigned long gmfn) +{ + /* + * linear search + * There is no gurantee that those tables are sorted. + */ + unsigned long i; + if (current_is_auto_translated_physmap) { + if (pfn_array == NULL) + return 0; + for (i = 0; i < pfn_array_size; i++) { + if (pfn_array[i] == gmfn) { + return pages_offset + (i << PAGE_SHIFT); + } + } + } else { + if (p2m_array == NULL) + return 0; + for (i = 0; i < p2m_array_size; i++) { + if (p2m_array[i].gmfn == gmfn) { + return pages_offset + (i << PAGE_SHIFT); + } + } + } + return 0; +} + +static void * +map_domain_va_core_elf(unsigned long domfd, int cpu, void *guest_va, + vcpu_guest_context_t *ctxt) +{ + unsigned long pde, page; + unsigned long va = (unsigned long)guest_va; + unsigned long offset; + void *v; + + static unsigned long cr3_phys[MAX_VIRT_CPUS]; + static unsigned long *cr3_virt[MAX_VIRT_CPUS]; + static unsigned long pde_phys[MAX_VIRT_CPUS]; + static unsigned long *pde_virt[MAX_VIRT_CPUS]; + static unsigned long page_phys[MAX_VIRT_CPUS]; + static unsigned long *page_virt[MAX_VIRT_CPUS]; + + if (cr3[cpu] != cr3_phys[cpu]) + { + if (cr3_virt[cpu]) + { + munmap(cr3_virt[cpu], PAGE_SIZE); + cr3_virt[cpu] = NULL; + cr3_phys[cpu] = 0; + } + offset = map_gmfn_to_offset_elf(xen_cr3_to_pfn(cr3[cpu])); + if (offset == 0) + return NULL; + v = mmap(NULL, PAGE_SIZE, PROT_READ, MAP_PRIVATE, domfd, offset); + if (v == MAP_FAILED) + { + perror("mmap failed"); + return NULL; + } + cr3_phys[cpu] = cr3[cpu]; + cr3_virt[cpu] = v; + } + if ((pde = cr3_virt[cpu][l2_table_offset_i386(va)]) == 0) /* logical address */ + return NULL; + if (pde != pde_phys[cpu]) + { + if (pde_virt[cpu]) + { + munmap(pde_virt[cpu], PAGE_SIZE); + pde_virt[cpu] = NULL; + pde_phys[cpu] = 0; + } + offset = map_gmfn_to_offset_elf(pde >> PAGE_SHIFT); + if (offset == 0) + return NULL; + v = mmap(NULL, PAGE_SIZE, PROT_READ, MAP_PRIVATE, domfd, offset); + if (v == MAP_FAILED) + return NULL; + pde_phys[cpu] = pde; + pde_virt[cpu] = v; + } + if ((page = pde_virt[cpu][l1_table_offset_i386(va)]) == 0) /* logical address */ + return NULL; + if (page != page_phys[cpu]) + { + if (page_virt[cpu]) + { + munmap(page_virt[cpu], PAGE_SIZE); + page_virt[cpu] = NULL; + page_phys[cpu] = 0; + } + offset = map_gmfn_to_offset_elf(page >> PAGE_SHIFT); + if (offset == 0) + return NULL; + v = mmap(NULL, PAGE_SIZE, PROT_READ, MAP_PRIVATE, domfd, offset); + if (v == MAP_FAILED) + { + IPRINTF("cr3 %lx pde %lx page %lx pti %lx\n", + cr3[cpu], pde, page, l1_table_offset_i386(va)); + return NULL; + } + page_phys[cpu] = page; + page_virt[cpu] = v; + } + return (void *)(((unsigned long)page_virt[cpu]) | (va & BSD_PAGE_MASK)); +} + +static int +xc_waitdomain_core_elf( + int xc_handle, + int domfd, + int *status, + int options, + vcpu_guest_context_t *ctxt) +{ + int i; + struct elf_core ecore; + + struct xen_dumpcore_elfnote_none *none; + struct xen_dumpcore_elfnote_header *header; + struct xen_dumpcore_elfnote_xen_version *xen_version; + struct xen_dumpcore_elfnote_format_version *format_version; + + Elf64_Shdr* table_shdr; + Elf64_Shdr* pages_shdr; + + if (elf_core_init(&ecore, domfd) < 0) + goto out; + + /* .note.Xen: none */ + if (elf_core_search_note(&ecore, XEN_DUMPCORE_ELFNOTE_NAME, + XEN_ELFNOTE_DUMPCORE_NONE, (void**)&none) < 0) + goto out; + + /* .note.Xen: header */ + if (elf_core_search_note(&ecore, XEN_DUMPCORE_ELFNOTE_NAME, + XEN_ELFNOTE_DUMPCORE_HEADER, (void**)&header) < 0) + goto out; + if ((header->header.xch_magic != XC_CORE_MAGIC && + header->header.xch_magic != XC_CORE_MAGIC_HVM) || + header->header.xch_nr_vcpus == 0 || + header->header.xch_nr_vcpus >= MAX_VIRT_CPUS || + header->header.xch_nr_pages == 0 || + header->header.xch_page_size != PAGE_SIZE) + goto out; + current_is_auto_translated_physmap = + (header->header.xch_magic == XC_CORE_MAGIC_HVM); + nr_pages = header->header.xch_nr_pages; + + /* .note.Xen: xen_version */ + if (elf_core_search_note(&ecore, XEN_DUMPCORE_ELFNOTE_NAME, + XEN_ELFNOTE_DUMPCORE_XEN_VERSION, + (void**)&xen_version) < 0) + goto out; + if (xen_version->xen_version.pagesize != PAGE_SIZE) + goto out; + + /* .note.Xen: format_version */ + if (elf_core_search_note(&ecore, XEN_DUMPCORE_ELFNOTE_NAME, + XEN_ELFNOTE_DUMPCORE_FORMAT_VERSION, + (void**)&format_version) < 0) + goto out; + for (i = 0; i < KNOWN_FORMAT_VERSION_NR; i++) { + if (format_version->format_version.version == + known_format_version[i].version) + break; + } + if (i == KNOWN_FORMAT_VERSION_NR) { + /* complain if unknown format */ + IPRINTF("warning:unknown format version. %"PRIx64"\n", + format_version->format_version.version); + } + + /* .xen_prstatus: read vcpu_guest_context_t*/ + if (elf_core_read_sec_by_name(&ecore, XEN_DUMPCORE_SEC_PRSTATUS, + (char*)ctxt) < 0) + goto out; + for (i = 0; i < header->header.xch_nr_vcpus; i++) + cr3[i] = ctxt[i].ctrlreg[3]; + + /* read .xen_p2m or .xen_pfn */ + if (current_is_auto_translated_physmap) { + table_shdr = elf_core_shdr_by_name(&ecore, XEN_DUMPCORE_SEC_PFN); + if (table_shdr == NULL) + goto out; + pfn_array_size = table_shdr->sh_size / table_shdr->sh_entsize; + if (pfn_array != NULL) + free(pfn_array); + if (elf_core_alloc_read_sec(&ecore, table_shdr, + (char**)&pfn_array) < 0) + goto out; + if (table_shdr->sh_entsize != sizeof(pfn_array[0])) + goto out; + } else { + table_shdr = elf_core_shdr_by_name(&ecore, XEN_DUMPCORE_SEC_P2M); + if (table_shdr == NULL) + goto out; + p2m_array_size = table_shdr->sh_size / table_shdr->sh_entsize; + if (p2m_array != NULL) + free(p2m_array); + if (elf_core_alloc_read_sec(&ecore, table_shdr, + (char**)&p2m_array) < 0) + goto out; + if (table_shdr->sh_entsize != sizeof(p2m_array[0])) + goto out; + } + if (table_shdr->sh_size / table_shdr->sh_entsize != nr_pages) + goto out; + + /* pages_offset and check the file size */ + pages_shdr = elf_core_shdr_by_name(&ecore, XEN_DUMPCORE_SEC_PAGES); + if (pages_shdr == NULL) + goto out; + pages_offset = pages_shdr->sh_offset; + if ((pages_shdr->sh_size / pages_shdr->sh_entsize) != nr_pages || + pages_shdr->sh_entsize != PAGE_SIZE || + (pages_shdr->sh_addralign % PAGE_SIZE) != 0 || + (pages_offset % PAGE_SIZE) != 0) + goto out; + + elf_core_free(&ecore); + return 0; + +out: + elf_core_free(&ecore); + return -1; +} + +/* --- interface ----------------------------------------------------------- */ + +typedef int (*xc_waitdomain_core_t)(int xc_handle, + int domfd, + int *status, + int options, + vcpu_guest_context_t *ctxt); +typedef void *(*map_domain_va_core_t)(unsigned long domfd, + int cpu, + void *guest_va, + vcpu_guest_context_t *ctxt); +struct xc_core_format_type { + xc_waitdomain_core_t waitdomain_core; + map_domain_va_core_t map_domain_va_core; +}; + +static const struct xc_core_format_type format_type[] = { + {xc_waitdomain_core_elf, map_domain_va_core_elf}, + {xc_waitdomain_core_compat, map_domain_va_core_compat}, +}; +#define NR_FORMAT_TYPE (sizeof(format_type)/sizeof(format_type[0])) + +/* XXX application state */ +static const struct xc_core_format_type* current_format_type = NULL; + +void * +map_domain_va_core(unsigned long domfd, int cpu, void *guest_va, + vcpu_guest_context_t *ctxt) +{ + if (current_format_type == NULL) + return NULL; + return (current_format_type->map_domain_va_core)(domfd, cpu, guest_va, + ctxt); +} + +int +xc_waitdomain_core(int xc_handle, int domfd, int *status, int options, + vcpu_guest_context_t *ctxt) +{ + int ret; + int i; + + for (i = 0; i < NR_FORMAT_TYPE; i++) { + ret = (format_type[i].waitdomain_core)(xc_handle, domfd, status, + options, ctxt); + if (ret == 0) { + current_format_type = &format_type[i]; + break; + } + } + return ret; +} + /* * Local variables: * mode: C diff --git a/tools/libxc/xc_resume.c b/tools/libxc/xc_resume.c index fec5a897c7..8e509b6fe3 100644 --- a/tools/libxc/xc_resume.c +++ b/tools/libxc/xc_resume.c @@ -169,13 +169,9 @@ static int xc_domain_resume_any(int xc_handle, uint32_t domid) * (2) should be used only for guests which cannot handle the special * new return code. (1) is always safe (but slower). */ -int xc_domain_resume(int xc_handle, uint32_t domid) +int xc_domain_resume(int xc_handle, uint32_t domid, int fast) { - /* - * XXX: Implement a way to select between options (1) and (2). - * Or expose the options as two different methods to Python. - */ - return (0 + return (fast ? xc_domain_resume_cooperative(xc_handle, domid) : xc_domain_resume_any(xc_handle, domid)); } diff --git a/tools/libxc/xc_solaris.c b/tools/libxc/xc_solaris.c index 889db6396d..65008115ea 100644 --- a/tools/libxc/xc_solaris.c +++ b/tools/libxc/xc_solaris.c @@ -242,3 +242,9 @@ int xc_evtchn_unmask(int xce_handle, evtchn_port_t port) { return dorw(xce_handle, (char *)&port, sizeof(port), 1); } + +/* Optionally flush file to disk and discard page cache */ +void discard_file_cache(int fd, int flush) +{ + // TODO: Implement for Solaris! +} diff --git a/tools/libxc/xenctrl.h b/tools/libxc/xenctrl.h index 14704e2e92..199750de73 100644 --- a/tools/libxc/xenctrl.h +++ b/tools/libxc/xenctrl.h @@ -243,10 +243,12 @@ int xc_domain_destroy(int xc_handle, * * @parm xc_handle a handle to an open hypervisor interface * @parm domid the domain id to resume + * @parm fast use cooperative resume (guest must support this) * return 0 on success, -1 on failure */ int xc_domain_resume(int xc_handle, - uint32_t domid); + uint32_t domid, + int fast); /** * This function will shutdown a domain. This is intended for use in @@ -414,6 +416,20 @@ int xc_sched_credit_domain_get(int xc_handle, uint32_t domid, struct xen_domctl_sched_credit *sdom); +/** + * This function sends a trigger to a domain. + * + * @parm xc_handle a handle to an open hypervisor interface + * @parm domid the domain id to send trigger + * @parm trigger the trigger type + * @parm vcpu the vcpu number to send trigger + * return 0 on success, -1 on failure + */ +int xc_domain_send_trigger(int xc_handle, + uint32_t domid, + uint32_t trigger, + uint32_t vcpu); + /* * EVENT CHANNEL FUNCTIONS */ @@ -556,6 +572,11 @@ void *xc_map_foreign_batch(int xc_handle, uint32_t dom, int prot, unsigned long xc_translate_foreign_address(int xc_handle, uint32_t dom, int vcpu, unsigned long long virt); + +/** + * DEPRECATED. Avoid using this, as it does not correctly account for PFNs + * without a backing MFN. + */ int xc_get_pfn_list(int xc_handle, uint32_t domid, uint64_t *pfn_buf, unsigned long max_pfns); diff --git a/tools/libxc/xenguest.h b/tools/libxc/xenguest.h index 2f0bb4234d..cb3c6a4d1c 100644 --- a/tools/libxc/xenguest.h +++ b/tools/libxc/xenguest.h @@ -91,6 +91,20 @@ int xc_linux_build(int xc_handle, unsigned int console_evtchn, unsigned long *console_mfn); +/** The same interface, but the dom structure is managed by the caller */ +struct xc_dom_image; +int xc_dom_linux_build(int xc_handle, + struct xc_dom_image *dom, + uint32_t domid, + unsigned int mem_mb, + const char *image_name, + const char *ramdisk_name, + unsigned long flags, + unsigned int store_evtchn, + unsigned long *store_mfn, + unsigned int console_evtchn, + unsigned long *console_mfn); + /** * This function will create a domain for a paravirtualized Linux * using buffers for kernel and initrd diff --git a/tools/libxc/xg_private.c b/tools/libxc/xg_private.c index 23d8f8b695..63ffea4aad 100644 --- a/tools/libxc/xg_private.c +++ b/tools/libxc/xg_private.c @@ -54,45 +54,45 @@ char *xc_read_image(const char *filename, unsigned long *size) #define CHUNK 1*1024*1024 while(1) { - if ( (tmp = realloc(image, *size + CHUNK)) == NULL ) - { - PERROR("Could not allocate memory for kernel image"); - free(image); - image = NULL; - goto out; - } - image = tmp; + if ( (tmp = realloc(image, *size + CHUNK)) == NULL ) + { + PERROR("Could not allocate memory for kernel image"); + free(image); + image = NULL; + goto out; + } + image = tmp; - bytes = gzread(kernel_gfd, image + *size, CHUNK); - switch (bytes) - { - case -1: - PERROR("Error reading kernel image"); - free(image); - image = NULL; - goto out; - case 0: /* EOF */ - goto out; - default: - *size += bytes; - break; - } + bytes = gzread(kernel_gfd, image + *size, CHUNK); + switch (bytes) + { + case -1: + PERROR("Error reading kernel image"); + free(image); + image = NULL; + goto out; + case 0: /* EOF */ + goto out; + default: + *size += bytes; + break; + } } #undef CHUNK out: if ( *size == 0 ) { - PERROR("Could not read kernel image"); - free(image); - image = NULL; + PERROR("Could not read kernel image"); + free(image); + image = NULL; } else if ( image ) { - /* Shrink allocation to fit image. */ - tmp = realloc(image, *size); - if ( tmp ) - image = tmp; + /* Shrink allocation to fit image. */ + tmp = realloc(image, *size); + if ( tmp ) + image = tmp; } if ( kernel_gfd != NULL ) @@ -189,29 +189,29 @@ unsigned long csum_page(void *page) } __attribute__((weak)) -int xc_hvm_build(int xc_handle, - uint32_t domid, - int memsize, - const char *image_name) + int xc_hvm_build(int xc_handle, + uint32_t domid, + int memsize, + const char *image_name) { errno = ENOSYS; return -1; } __attribute__((weak)) -int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, - uint32_t max_factor, uint32_t flags, - int (*suspend)(int domid)) + int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, + uint32_t max_factor, uint32_t flags, + int (*suspend)(int domid)) { errno = ENOSYS; return -1; } __attribute__((weak)) -int xc_hvm_restore(int xc_handle, int io_fd, uint32_t dom, - unsigned long max_pfn, unsigned int store_evtchn, - unsigned long *store_mfn, - unsigned int pae, unsigned int apic) + int xc_hvm_restore(int xc_handle, int io_fd, uint32_t dom, + unsigned long max_pfn, unsigned int store_evtchn, + unsigned long *store_mfn, + unsigned int pae, unsigned int apic) { errno = ENOSYS; return -1; @@ -228,3 +228,13 @@ __attribute__((weak)) int xc_set_hvm_param( { return -ENOSYS; } + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/tools/libxc/xg_private.h b/tools/libxc/xg_private.h index 3cf6fbf22a..2b66a29763 100644 --- a/tools/libxc/xg_private.h +++ b/tools/libxc/xg_private.h @@ -146,6 +146,23 @@ typedef l4_pgentry_64_t l4_pgentry_t; #define PAGE_SIZE_IA64 (1UL << PAGE_SHIFT_IA64) #define PAGE_MASK_IA64 (~(PAGE_SIZE_IA64-1)) +#define ROUNDUP(_x,_w) (((unsigned long)(_x)+(1UL<<(_w))-1) & ~((1UL<<(_w))-1)) + +/* Size in bytes of the P2M (rounded up to the nearest PAGE_SIZE bytes) */ +#define P2M_SIZE ROUNDUP((max_pfn * sizeof(xen_pfn_t)), PAGE_SHIFT) + +/* Number of xen_pfn_t in a page */ +#define fpp (PAGE_SIZE/sizeof(xen_pfn_t)) + +/* Number of entries in the pfn_to_mfn_frame_list_list */ +#define P2M_FLL_ENTRIES (((max_pfn)+(fpp*fpp)-1)/(fpp*fpp)) + +/* Number of entries in the pfn_to_mfn_frame_list */ +#define P2M_FL_ENTRIES (((max_pfn)+fpp-1)/fpp) + +/* Size in bytes of the pfn_to_mfn_frame_list */ +#define P2M_FL_SIZE ((P2M_FL_ENTRIES)*sizeof(unsigned long)) + #define PAEKERN_no 0 #define PAEKERN_yes 1 #define PAEKERN_extended_cr3 2 diff --git a/tools/libxc/xg_save_restore.h b/tools/libxc/xg_save_restore.h index 5496f02b70..8579ca8a5e 100644 --- a/tools/libxc/xg_save_restore.h +++ b/tools/libxc/xg_save_restore.h @@ -81,7 +81,6 @@ static inline int get_platform_info(int xc_handle, uint32_t dom, */ #define PFN_TO_KB(_pfn) ((_pfn) << (PAGE_SHIFT - 10)) -#define ROUNDUP(_x,_w) (((unsigned long)(_x)+(1UL<<(_w))-1) & ~((1UL<<(_w))-1)) /* @@ -94,25 +93,5 @@ static inline int get_platform_info(int xc_handle, uint32_t dom, #define M2P_SIZE(_m) ROUNDUP(((_m) * sizeof(xen_pfn_t)), M2P_SHIFT) #define M2P_CHUNKS(_m) (M2P_SIZE((_m)) >> M2P_SHIFT) -/* Size in bytes of the P2M (rounded up to the nearest PAGE_SIZE bytes) */ -#define P2M_SIZE ROUNDUP((max_pfn * sizeof(xen_pfn_t)), PAGE_SHIFT) - -/* Number of xen_pfn_t in a page */ -#define fpp (PAGE_SIZE/sizeof(xen_pfn_t)) - -/* Number of entries in the pfn_to_mfn_frame_list */ -#define P2M_FL_ENTRIES (((max_pfn)+fpp-1)/fpp) - -/* Size in bytes of the pfn_to_mfn_frame_list */ -#define P2M_FL_SIZE ((P2M_FL_ENTRIES)*sizeof(unsigned long)) - -/* Number of entries in the pfn_to_mfn_frame_list_list */ -#define P2M_FLL_ENTRIES (((max_pfn)+(fpp*fpp)-1)/(fpp*fpp)) - /* Returns TRUE if the PFN is currently mapped */ #define is_mapped(pfn_type) (!((pfn_type) & 0x80000000UL)) - -#define INVALID_P2M_ENTRY (~0UL) - - - diff --git a/tools/libxen/Makefile b/tools/libxen/Makefile index e2eeda74d8..58db515a72 100644 --- a/tools/libxen/Makefile +++ b/tools/libxen/Makefile @@ -57,8 +57,8 @@ test/test_hvm_bindings: test/test_hvm_bindings.o libxenapi.so .PHONY: install install: all - $(INSTALL_DIR) -p $(DESTDIR)/usr/include/xen/api - $(INSTALL_DIR) -p $(DESTDIR)/usr/$(LIBDIR) + $(INSTALL_DIR) $(DESTDIR)/usr/include/xen/api + $(INSTALL_DIR) $(DESTDIR)/usr/$(LIBDIR) $(INSTALL_PROG) libxenapi.so.$(MAJOR).$(MINOR) $(DESTDIR)/usr/$(LIBDIR) ln -sf libxenapi.so.$(MAJOR).$(MINOR) $(DESTDIR)/usr/$(LIBDIR)/libxenapi.so.$(MAJOR) ln -sf libxenapi.so.$(MAJOR) $(DESTDIR)/usr/$(LIBDIR)/libxenapi.so diff --git a/tools/libxen/include/xen_console.h b/tools/libxen/include/xen_console.h index ca4721c49d..5402ae9fbe 100644 --- a/tools/libxen/include/xen_console.h +++ b/tools/libxen/include/xen_console.h @@ -237,4 +237,11 @@ extern bool xen_console_remove_from_other_config(xen_session *session, xen_console console, char *key); +/** + * Return a list of all the consoles known to the system. + */ +extern bool +xen_console_get_all(xen_session *session, struct xen_console_set **result); + + #endif diff --git a/tools/libxen/include/xen_host.h b/tools/libxen/include/xen_host.h index 568973a464..f9919ad309 100644 --- a/tools/libxen/include/xen_host.h +++ b/tools/libxen/include/xen_host.h @@ -72,8 +72,13 @@ typedef struct xen_host_record char *uuid; char *name_label; char *name_description; + int64_t api_version_major; + int64_t api_version_minor; + char *api_version_vendor; + xen_string_string_map *api_version_vendor_implementation; xen_string_string_map *software_version; xen_string_string_map *other_config; + struct xen_string_set *capabilities; struct xen_string_set *supported_bootloaders; struct xen_vm_record_opt_set *resident_vms; xen_string_string_map *logging; @@ -206,6 +211,34 @@ extern bool xen_host_get_name_description(xen_session *session, char **result, xen_host host); +/** + * Get the API_version/major field of the given host. + */ +extern bool +xen_host_get_api_version_major(xen_session *session, int64_t *result, xen_host host); + + +/** + * Get the API_version/minor field of the given host. + */ +extern bool +xen_host_get_api_version_minor(xen_session *session, int64_t *result, xen_host host); + + +/** + * Get the API_version/vendor field of the given host. + */ +extern bool +xen_host_get_api_version_vendor(xen_session *session, char **result, xen_host host); + + +/** + * Get the API_version/vendor_implementation field of the given host. + */ +extern bool +xen_host_get_api_version_vendor_implementation(xen_session *session, xen_string_string_map **result, xen_host host); + + /** * Get the software_version field of the given host. */ @@ -220,6 +253,13 @@ extern bool xen_host_get_other_config(xen_session *session, xen_string_string_map **result, xen_host host); +/** + * Get the capabilities field of the given host. + */ +extern bool +xen_host_get_capabilities(xen_session *session, struct xen_string_set **result, xen_host host); + + /** * Get the supported_bootloaders field of the given host. */ diff --git a/tools/libxen/include/xen_host_cpu.h b/tools/libxen/include/xen_host_cpu.h index 945a7279d1..8b6d37f5e3 100644 --- a/tools/libxen/include/xen_host_cpu.h +++ b/tools/libxen/include/xen_host_cpu.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, XenSource Inc. + * 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 @@ -25,8 +25,8 @@ /* - * The host_cpu class. - * + * The host_cpu class. + * * A physical CPU. */ @@ -68,6 +68,8 @@ typedef struct xen_host_cpu_record char *vendor; int64_t speed; char *modelname; + char *stepping; + char *flags; double utilisation; } xen_host_cpu_record; @@ -164,20 +166,6 @@ extern bool xen_host_cpu_get_by_uuid(xen_session *session, xen_host_cpu *result, char *uuid); -/** - * Create a new host_cpu instance, and return its handle. - */ -extern bool -xen_host_cpu_create(xen_session *session, xen_host_cpu *result, xen_host_cpu_record *record); - - -/** - * Destroy the specified host_cpu instance. - */ -extern bool -xen_host_cpu_destroy(xen_session *session, xen_host_cpu host_cpu); - - /** * Get the uuid field of the given host_cpu. */ @@ -220,6 +208,20 @@ extern bool xen_host_cpu_get_modelname(xen_session *session, char **result, xen_host_cpu host_cpu); +/** + * Get the stepping field of the given host_cpu. + */ +extern bool +xen_host_cpu_get_stepping(xen_session *session, char **result, xen_host_cpu host_cpu); + + +/** + * Get the flags field of the given host_cpu. + */ +extern bool +xen_host_cpu_get_flags(xen_session *session, char **result, xen_host_cpu host_cpu); + + /** * Get the utilisation field of the given host_cpu. */ @@ -227,4 +229,11 @@ extern bool xen_host_cpu_get_utilisation(xen_session *session, double *result, xen_host_cpu host_cpu); +/** + * Return a list of all the host_cpus known to the system. + */ +extern bool +xen_host_cpu_get_all(xen_session *session, struct xen_host_cpu_set **result); + + #endif diff --git a/tools/libxen/include/xen_host_metrics.h b/tools/libxen/include/xen_host_metrics.h index 6ee609a9e9..31f3123364 100644 --- a/tools/libxen/include/xen_host_metrics.h +++ b/tools/libxen/include/xen_host_metrics.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, XenSource Inc. + * 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 @@ -20,7 +20,6 @@ #define XEN_HOST_METRICS_H #include "xen_common.h" -#include "xen_host_decl.h" #include "xen_host_metrics_decl.h" @@ -63,7 +62,6 @@ typedef struct xen_host_metrics_record { xen_host_metrics handle; char *uuid; - struct xen_host_record_opt *host; int64_t memory_total; int64_t memory_free; } xen_host_metrics_record; @@ -169,13 +167,6 @@ extern bool xen_host_metrics_get_uuid(xen_session *session, char **result, xen_host_metrics host_metrics); -/** - * Get the host field of the given host_metrics. - */ -extern bool -xen_host_metrics_get_host(xen_session *session, xen_host *result, xen_host_metrics host_metrics); - - /** * Get the memory/total field of the given host_metrics. */ @@ -190,4 +181,11 @@ extern bool xen_host_metrics_get_memory_free(xen_session *session, int64_t *result, xen_host_metrics host_metrics); +/** + * Return a list of all the host_metrics instances known to the system. + */ +extern bool +xen_host_metrics_get_all(xen_session *session, struct xen_host_metrics_set **result); + + #endif diff --git a/tools/libxen/include/xen_network.h b/tools/libxen/include/xen_network.h index 228c7c2ab4..f1bff0e229 100644 --- a/tools/libxen/include/xen_network.h +++ b/tools/libxen/include/xen_network.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, XenSource Inc. + * 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 @@ -26,8 +26,8 @@ /* - * The network class. - * + * The network class. + * * A virtual network. */ @@ -68,8 +68,6 @@ typedef struct xen_network_record char *name_description; struct xen_vif_record_opt_set *vifs; struct xen_pif_record_opt_set *pifs; - char *default_gateway; - char *default_netmask; } xen_network_record; /** @@ -221,20 +219,6 @@ extern bool xen_network_get_pifs(xen_session *session, struct xen_pif_set **result, xen_network network); -/** - * Get the default_gateway field of the given network. - */ -extern bool -xen_network_get_default_gateway(xen_session *session, char **result, xen_network network); - - -/** - * Get the default_netmask field of the given network. - */ -extern bool -xen_network_get_default_netmask(xen_session *session, char **result, xen_network network); - - /** * Set the name/label field of the given network. */ @@ -249,20 +233,6 @@ extern bool xen_network_set_name_description(xen_session *session, xen_network network, char *description); -/** - * Set the default_gateway field of the given network. - */ -extern bool -xen_network_set_default_gateway(xen_session *session, xen_network network, char *default_gateway); - - -/** - * Set the default_netmask field of the given network. - */ -extern bool -xen_network_set_default_netmask(xen_session *session, xen_network network, char *default_netmask); - - /** * Return a list of all the networks known to the system. */ diff --git a/tools/libxen/include/xen_pbd.h b/tools/libxen/include/xen_pbd.h index 6d0f6b449e..335d20b2ff 100644 --- a/tools/libxen/include/xen_pbd.h +++ b/tools/libxen/include/xen_pbd.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, XenSource Inc. + * 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 @@ -213,4 +213,11 @@ extern bool xen_pbd_get_currently_attached(xen_session *session, bool *result, xen_pbd pbd); +/** + * Return a list of all the PBDs known to the system. + */ +extern bool +xen_pbd_get_all(xen_session *session, struct xen_pbd_set **result); + + #endif diff --git a/tools/libxen/include/xen_pif.h b/tools/libxen/include/xen_pif.h index a4d6db7420..63fc88477b 100644 --- a/tools/libxen/include/xen_pif.h +++ b/tools/libxen/include/xen_pif.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, XenSource Inc. + * 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 @@ -267,4 +267,11 @@ extern bool xen_pif_destroy(xen_session *session, xen_pif self); +/** + * Return a list of all the PIFs known to the system. + */ +extern bool +xen_pif_get_all(xen_session *session, struct xen_pif_set **result); + + #endif diff --git a/tools/libxen/include/xen_pif_metrics.h b/tools/libxen/include/xen_pif_metrics.h index 420516d8b6..b8dad22afa 100644 --- a/tools/libxen/include/xen_pif_metrics.h +++ b/tools/libxen/include/xen_pif_metrics.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, XenSource Inc. + * 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 @@ -20,7 +20,6 @@ #define XEN_PIF_METRICS_H #include "xen_common.h" -#include "xen_pif_decl.h" #include "xen_pif_metrics_decl.h" @@ -63,7 +62,6 @@ typedef struct xen_pif_metrics_record { xen_pif_metrics handle; char *uuid; - struct xen_pif_record_opt *pif; double io_read_kbs; double io_write_kbs; } xen_pif_metrics_record; @@ -168,13 +166,6 @@ extern bool xen_pif_metrics_get_uuid(xen_session *session, char **result, xen_pif_metrics pif_metrics); -/** - * Get the PIF field of the given PIF_metrics. - */ -extern bool -xen_pif_metrics_get_pif(xen_session *session, xen_pif *result, xen_pif_metrics pif_metrics); - - /** * Get the io/read_kbs field of the given PIF_metrics. */ @@ -189,4 +180,11 @@ extern bool xen_pif_metrics_get_io_write_kbs(xen_session *session, double *result, xen_pif_metrics pif_metrics); +/** + * Return a list of all the PIF_metrics instances known to the system. + */ +extern bool +xen_pif_metrics_get_all(xen_session *session, struct xen_pif_metrics_set **result); + + #endif diff --git a/tools/libxen/include/xen_vbd.h b/tools/libxen/include/xen_vbd.h index 543a42288c..86ad38f207 100644 --- a/tools/libxen/include/xen_vbd.h +++ b/tools/libxen/include/xen_vbd.h @@ -20,6 +20,7 @@ #define XEN_VBD_H #include "xen_common.h" +#include "xen_string_set.h" #include "xen_string_string_map.h" #include "xen_vbd_decl.h" #include "xen_vbd_metrics_decl.h" @@ -75,8 +76,12 @@ typedef struct xen_vbd_record bool bootable; enum xen_vbd_mode mode; enum xen_vbd_type type; + bool currently_attached; + int64_t status_code; + char *status_detail; char *qos_algorithm_type; xen_string_string_map *qos_algorithm_params; + struct xen_string_set *qos_supported_algorithms; struct xen_vbd_metrics_record_opt *metrics; } xen_vbd_record; @@ -236,6 +241,27 @@ extern bool xen_vbd_get_type(xen_session *session, enum xen_vbd_type *result, xen_vbd vbd); +/** + * Get the currently_attached field of the given VBD. + */ +extern bool +xen_vbd_get_currently_attached(xen_session *session, bool *result, xen_vbd vbd); + + +/** + * Get the status_code field of the given VBD. + */ +extern bool +xen_vbd_get_status_code(xen_session *session, int64_t *result, xen_vbd vbd); + + +/** + * Get the status_detail field of the given VBD. + */ +extern bool +xen_vbd_get_status_detail(xen_session *session, char **result, xen_vbd vbd); + + /** * Get the qos/algorithm_type field of the given VBD. */ @@ -250,6 +276,13 @@ extern bool xen_vbd_get_qos_algorithm_params(xen_session *session, xen_string_string_map **result, xen_vbd vbd); +/** + * Get the qos/supported_algorithms field of the given VBD. + */ +extern bool +xen_vbd_get_qos_supported_algorithms(xen_session *session, struct xen_string_set **result, xen_vbd vbd); + + /** * Get the metrics field of the given VBD. */ @@ -324,4 +357,11 @@ extern bool xen_vbd_media_change(xen_session *session, xen_vbd vbd, xen_vdi vdi); +/** + * Return a list of all the VBDs known to the system. + */ +extern bool +xen_vbd_get_all(xen_session *session, struct xen_vbd_set **result); + + #endif diff --git a/tools/libxen/include/xen_vbd_metrics.h b/tools/libxen/include/xen_vbd_metrics.h index 8b3c1429d4..3cd507b31e 100644 --- a/tools/libxen/include/xen_vbd_metrics.h +++ b/tools/libxen/include/xen_vbd_metrics.h @@ -180,4 +180,11 @@ extern bool xen_vbd_metrics_get_io_write_kbs(xen_session *session, double *result, xen_vbd_metrics vbd_metrics); +/** + * Return a list of all the VBD_metrics instances known to the system. + */ +extern bool +xen_vbd_metrics_get_all(xen_session *session, struct xen_vbd_metrics_set **result); + + #endif diff --git a/tools/libxen/include/xen_vdi.h b/tools/libxen/include/xen_vdi.h index 8533df31a8..90120370d5 100644 --- a/tools/libxen/include/xen_vdi.h +++ b/tools/libxen/include/xen_vdi.h @@ -335,4 +335,11 @@ extern bool xen_vdi_resize(xen_session *session, xen_vdi vdi, int64_t size); +/** + * Return a list of all the VDIs known to the system. + */ +extern bool +xen_vdi_get_all(xen_session *session, struct xen_vdi_set **result); + + #endif diff --git a/tools/libxen/include/xen_vif.h b/tools/libxen/include/xen_vif.h index c6ec71ee03..05a070aff4 100644 --- a/tools/libxen/include/xen_vif.h +++ b/tools/libxen/include/xen_vif.h @@ -21,6 +21,7 @@ #include "xen_common.h" #include "xen_network_decl.h" +#include "xen_string_set.h" #include "xen_string_string_map.h" #include "xen_vif_decl.h" #include "xen_vif_metrics_decl.h" @@ -71,8 +72,12 @@ typedef struct xen_vif_record struct xen_vm_record_opt *vm; char *mac; int64_t mtu; + bool currently_attached; + int64_t status_code; + char *status_detail; char *qos_algorithm_type; xen_string_string_map *qos_algorithm_params; + struct xen_string_set *qos_supported_algorithms; struct xen_vif_metrics_record_opt *metrics; } xen_vif_record; @@ -225,6 +230,27 @@ extern bool xen_vif_get_mtu(xen_session *session, int64_t *result, xen_vif vif); +/** + * Get the currently_attached field of the given VIF. + */ +extern bool +xen_vif_get_currently_attached(xen_session *session, bool *result, xen_vif vif); + + +/** + * Get the status_code field of the given VIF. + */ +extern bool +xen_vif_get_status_code(xen_session *session, int64_t *result, xen_vif vif); + + +/** + * Get the status_detail field of the given VIF. + */ +extern bool +xen_vif_get_status_detail(xen_session *session, char **result, xen_vif vif); + + /** * Get the qos/algorithm_type field of the given VIF. */ @@ -239,6 +265,13 @@ extern bool xen_vif_get_qos_algorithm_params(xen_session *session, xen_string_string_map **result, xen_vif vif); +/** + * Get the qos/supported_algorithms field of the given VIF. + */ +extern bool +xen_vif_get_qos_supported_algorithms(xen_session *session, struct xen_string_set **result, xen_vif vif); + + /** * Get the metrics field of the given VIF. */ @@ -298,4 +331,11 @@ extern bool xen_vif_remove_from_qos_algorithm_params(xen_session *session, xen_vif vif, char *key); +/** + * Return a list of all the VIFs known to the system. + */ +extern bool +xen_vif_get_all(xen_session *session, struct xen_vif_set **result); + + #endif diff --git a/tools/libxen/include/xen_vif_metrics.h b/tools/libxen/include/xen_vif_metrics.h index 2b150d0a68..b5a26f25c6 100644 --- a/tools/libxen/include/xen_vif_metrics.h +++ b/tools/libxen/include/xen_vif_metrics.h @@ -180,4 +180,11 @@ extern bool xen_vif_metrics_get_io_write_kbs(xen_session *session, double *result, xen_vif_metrics vif_metrics); +/** + * Return a list of all the VIF_metrics instances known to the system. + */ +extern bool +xen_vif_metrics_get_all(xen_session *session, struct xen_vif_metrics_set **result); + + #endif diff --git a/tools/libxen/include/xen_vm.h b/tools/libxen/include/xen_vm.h index 3c23784cf5..71a3f62ca4 100644 --- a/tools/libxen/include/xen_vm.h +++ b/tools/libxen/include/xen_vm.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, XenSource Inc. + * 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 @@ -23,7 +23,6 @@ #include "xen_console_decl.h" #include "xen_crashdump_decl.h" #include "xen_host_decl.h" -#include "xen_int_float_map.h" #include "xen_on_crash_behaviour.h" #include "xen_on_normal_exit.h" #include "xen_string_string_map.h" @@ -31,6 +30,7 @@ #include "xen_vdi_decl.h" #include "xen_vif_decl.h" #include "xen_vm_decl.h" +#include "xen_vm_guest_metrics_decl.h" #include "xen_vm_metrics_decl.h" #include "xen_vm_power_state.h" #include "xen_vtpm_decl.h" @@ -124,8 +124,6 @@ typedef struct xen_vm_record xen_string_string_map *vcpus_params; int64_t vcpus_max; int64_t vcpus_at_startup; - int64_t vcpus_number; - xen_int_float_map *vcpus_utilisation; enum xen_on_normal_exit actions_after_shutdown; enum xen_on_normal_exit actions_after_reboot; enum xen_on_crash_behaviour actions_after_crash; @@ -147,10 +145,11 @@ typedef struct xen_vm_record bool platform_clock_offset; bool platform_enable_audio; char *pci_bus; - xen_string_string_map *tools_version; xen_string_string_map *other_config; + int64_t domid; bool is_control_domain; struct xen_vm_metrics_record_opt *metrics; + struct xen_vm_guest_metrics_record_opt *guest_metrics; } xen_vm_record; /** @@ -388,20 +387,6 @@ extern bool xen_vm_get_vcpus_at_startup(xen_session *session, int64_t *result, xen_vm vm); -/** - * Get the VCPUs/number field of the given VM. - */ -extern bool -xen_vm_get_vcpus_number(xen_session *session, int64_t *result, xen_vm vm); - - -/** - * Get the VCPUs/utilisation field of the given VM. - */ -extern bool -xen_vm_get_vcpus_utilisation(xen_session *session, xen_int_float_map **result, xen_vm vm); - - /** * Get the actions/after_shutdown field of the given VM. */ @@ -549,13 +534,6 @@ extern bool xen_vm_get_pci_bus(xen_session *session, char **result, xen_vm vm); -/** - * Get the tools_version field of the given VM. - */ -extern bool -xen_vm_get_tools_version(xen_session *session, xen_string_string_map **result, xen_vm vm); - - /** * Get the other_config field of the given VM. */ @@ -563,6 +541,13 @@ extern bool xen_vm_get_other_config(xen_session *session, xen_string_string_map **result, xen_vm vm); +/** + * Get the domid field of the given VM. + */ +extern bool +xen_vm_get_domid(xen_session *session, int64_t *result, xen_vm vm); + + /** * Get the is_control_domain field of the given VM. */ @@ -577,6 +562,13 @@ extern bool xen_vm_get_metrics(xen_session *session, xen_vm_metrics *result, xen_vm vm); +/** + * Get the guest_metrics field of the given VM. + */ +extern bool +xen_vm_get_guest_metrics(xen_session *session, xen_vm_guest_metrics *result, xen_vm vm); + + /** * Set the name/label field of the given VM. */ diff --git a/tools/libxen/include/xen_vm_guest_metrics.h b/tools/libxen/include/xen_vm_guest_metrics.h new file mode 100644 index 0000000000..61b8b5b2b7 --- /dev/null +++ b/tools/libxen/include/xen_vm_guest_metrics.h @@ -0,0 +1,226 @@ +/* + * 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_VM_GUEST_METRICS_H +#define XEN_VM_GUEST_METRICS_H + +#include "xen_common.h" +#include "xen_string_string_map.h" +#include "xen_vm_guest_metrics_decl.h" + + +/* + * The VM_guest_metrics class. + * + * The metrics reported by the guest (as opposed to inferred from outside). + */ + + +/** + * Free the given xen_vm_guest_metrics. The given handle must have + * been allocated by this library. + */ +extern void +xen_vm_guest_metrics_free(xen_vm_guest_metrics vm_guest_metrics); + + +typedef struct xen_vm_guest_metrics_set +{ + size_t size; + xen_vm_guest_metrics *contents[]; +} xen_vm_guest_metrics_set; + +/** + * Allocate a xen_vm_guest_metrics_set of the given size. + */ +extern xen_vm_guest_metrics_set * +xen_vm_guest_metrics_set_alloc(size_t size); + +/** + * Free the given xen_vm_guest_metrics_set. The given set must have + * been allocated by this library. + */ +extern void +xen_vm_guest_metrics_set_free(xen_vm_guest_metrics_set *set); + + +typedef struct xen_vm_guest_metrics_record +{ + xen_vm_guest_metrics handle; + char *uuid; + xen_string_string_map *os_version; + xen_string_string_map *pv_drivers_version; + xen_string_string_map *memory; + xen_string_string_map *disks; + xen_string_string_map *networks; + xen_string_string_map *other; +} xen_vm_guest_metrics_record; + +/** + * Allocate a xen_vm_guest_metrics_record. + */ +extern xen_vm_guest_metrics_record * +xen_vm_guest_metrics_record_alloc(void); + +/** + * Free the given xen_vm_guest_metrics_record, and all referenced + * values. The given record must have been allocated by this library. + */ +extern void +xen_vm_guest_metrics_record_free(xen_vm_guest_metrics_record *record); + + +typedef struct xen_vm_guest_metrics_record_opt +{ + bool is_record; + union + { + xen_vm_guest_metrics handle; + xen_vm_guest_metrics_record *record; + } u; +} xen_vm_guest_metrics_record_opt; + +/** + * Allocate a xen_vm_guest_metrics_record_opt. + */ +extern xen_vm_guest_metrics_record_opt * +xen_vm_guest_metrics_record_opt_alloc(void); + +/** + * Free the given xen_vm_guest_metrics_record_opt, and all referenced + * values. The given record_opt must have been allocated by this library. + */ +extern void +xen_vm_guest_metrics_record_opt_free(xen_vm_guest_metrics_record_opt *record_opt); + + +typedef struct xen_vm_guest_metrics_record_set +{ + size_t size; + xen_vm_guest_metrics_record *contents[]; +} xen_vm_guest_metrics_record_set; + +/** + * Allocate a xen_vm_guest_metrics_record_set of the given size. + */ +extern xen_vm_guest_metrics_record_set * +xen_vm_guest_metrics_record_set_alloc(size_t size); + +/** + * Free the given xen_vm_guest_metrics_record_set, and all referenced + * values. The given set must have been allocated by this library. + */ +extern void +xen_vm_guest_metrics_record_set_free(xen_vm_guest_metrics_record_set *set); + + + +typedef struct xen_vm_guest_metrics_record_opt_set +{ + size_t size; + xen_vm_guest_metrics_record_opt *contents[]; +} xen_vm_guest_metrics_record_opt_set; + +/** + * Allocate a xen_vm_guest_metrics_record_opt_set of the given size. + */ +extern xen_vm_guest_metrics_record_opt_set * +xen_vm_guest_metrics_record_opt_set_alloc(size_t size); + +/** + * Free the given xen_vm_guest_metrics_record_opt_set, and all + * referenced values. The given set must have been allocated by this library. + */ +extern void +xen_vm_guest_metrics_record_opt_set_free(xen_vm_guest_metrics_record_opt_set *set); + + +/** + * Get a record containing the current state of the given + * VM_guest_metrics. + */ +extern bool +xen_vm_guest_metrics_get_record(xen_session *session, xen_vm_guest_metrics_record **result, xen_vm_guest_metrics vm_guest_metrics); + + +/** + * Get a reference to the VM_guest_metrics instance with the specified + * UUID. + */ +extern bool +xen_vm_guest_metrics_get_by_uuid(xen_session *session, xen_vm_guest_metrics *result, char *uuid); + + +/** + * Get the uuid field of the given VM_guest_metrics. + */ +extern bool +xen_vm_guest_metrics_get_uuid(xen_session *session, char **result, xen_vm_guest_metrics vm_guest_metrics); + + +/** + * Get the os_version field of the given VM_guest_metrics. + */ +extern bool +xen_vm_guest_metrics_get_os_version(xen_session *session, xen_string_string_map **result, xen_vm_guest_metrics vm_guest_metrics); + + +/** + * Get the PV_drivers_version field of the given VM_guest_metrics. + */ +extern bool +xen_vm_guest_metrics_get_pv_drivers_version(xen_session *session, xen_string_string_map **result, xen_vm_guest_metrics vm_guest_metrics); + + +/** + * Get the memory field of the given VM_guest_metrics. + */ +extern bool +xen_vm_guest_metrics_get_memory(xen_session *session, xen_string_string_map **result, xen_vm_guest_metrics vm_guest_metrics); + + +/** + * Get the disks field of the given VM_guest_metrics. + */ +extern bool +xen_vm_guest_metrics_get_disks(xen_session *session, xen_string_string_map **result, xen_vm_guest_metrics vm_guest_metrics); + + +/** + * Get the networks field of the given VM_guest_metrics. + */ +extern bool +xen_vm_guest_metrics_get_networks(xen_session *session, xen_string_string_map **result, xen_vm_guest_metrics vm_guest_metrics); + + +/** + * Get the other field of the given VM_guest_metrics. + */ +extern bool +xen_vm_guest_metrics_get_other(xen_session *session, xen_string_string_map **result, xen_vm_guest_metrics vm_guest_metrics); + + +/** + * Return a list of all the VM_guest_metrics instances known to the + * system. + */ +extern bool +xen_vm_guest_metrics_get_all(xen_session *session, struct xen_vm_guest_metrics_set **result); + + +#endif diff --git a/tools/libxen/include/xen_vm_guest_metrics_decl.h b/tools/libxen/include/xen_vm_guest_metrics_decl.h new file mode 100644 index 0000000000..837528b919 --- /dev/null +++ b/tools/libxen/include/xen_vm_guest_metrics_decl.h @@ -0,0 +1,30 @@ +/* + * 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_VM_GUEST_METRICS_DECL_H +#define XEN_VM_GUEST_METRICS_DECL_H + +typedef void *xen_vm_guest_metrics; + +struct xen_vm_guest_metrics_set; +struct xen_vm_guest_metrics_record; +struct xen_vm_guest_metrics_record_set; +struct xen_vm_guest_metrics_record_opt; +struct xen_vm_guest_metrics_record_opt_set; + +#endif diff --git a/tools/libxen/include/xen_vm_metrics.h b/tools/libxen/include/xen_vm_metrics.h index e3b06c214b..b03c4d4e3c 100644 --- a/tools/libxen/include/xen_vm_metrics.h +++ b/tools/libxen/include/xen_vm_metrics.h @@ -189,4 +189,11 @@ extern bool xen_vm_metrics_get_vcpus_utilisation(xen_session *session, xen_int_float_map **result, xen_vm_metrics vm_metrics); +/** + * Return a list of all the VM_metrics instances known to the system. + */ +extern bool +xen_vm_metrics_get_all(xen_session *session, struct xen_vm_metrics_set **result); + + #endif diff --git a/tools/libxen/src/xen_console.c b/tools/libxen/src/xen_console.c index 0f61fdde6f..a5a5ad2bb2 100644 --- a/tools/libxen/src/xen_console.c +++ b/tools/libxen/src/xen_console.c @@ -269,6 +269,18 @@ xen_console_remove_from_other_config(xen_session *session, xen_console console, } +bool +xen_console_get_all(xen_session *session, struct xen_console_set **result) +{ + + abstract_type result_type = abstract_type_string_set; + + *result = NULL; + xen_call_(session, "console.get_all", NULL, 0, &result_type, result); + return session->ok; +} + + bool xen_console_get_uuid(xen_session *session, char **result, xen_console console) { diff --git a/tools/libxen/src/xen_host.c b/tools/libxen/src/xen_host.c index 24cc4140cc..204664ae3c 100644 --- a/tools/libxen/src/xen_host.c +++ b/tools/libxen/src/xen_host.c @@ -52,12 +52,27 @@ static const struct_member xen_host_record_struct_members[] = { .key = "name_description", .type = &abstract_type_string, .offset = offsetof(xen_host_record, name_description) }, + { .key = "API_version_major", + .type = &abstract_type_int, + .offset = offsetof(xen_host_record, api_version_major) }, + { .key = "API_version_minor", + .type = &abstract_type_int, + .offset = offsetof(xen_host_record, api_version_minor) }, + { .key = "API_version_vendor", + .type = &abstract_type_string, + .offset = offsetof(xen_host_record, api_version_vendor) }, + { .key = "API_version_vendor_implementation", + .type = &abstract_type_string_string_map, + .offset = offsetof(xen_host_record, api_version_vendor_implementation) }, { .key = "software_version", .type = &abstract_type_string_string_map, .offset = offsetof(xen_host_record, software_version) }, { .key = "other_config", .type = &abstract_type_string_string_map, .offset = offsetof(xen_host_record, other_config) }, + { .key = "capabilities", + .type = &abstract_type_string_set, + .offset = offsetof(xen_host_record, capabilities) }, { .key = "supported_bootloaders", .type = &abstract_type_string_set, .offset = offsetof(xen_host_record, supported_bootloaders) }, @@ -108,8 +123,11 @@ xen_host_record_free(xen_host_record *record) free(record->uuid); free(record->name_label); free(record->name_description); + free(record->api_version_vendor); + xen_string_string_map_free(record->api_version_vendor_implementation); xen_string_string_map_free(record->software_version); xen_string_string_map_free(record->other_config); + xen_string_set_free(record->capabilities); xen_string_set_free(record->supported_bootloaders); xen_vm_record_opt_set_free(record->resident_vms); xen_string_string_map_free(record->logging); @@ -214,6 +232,72 @@ xen_host_get_name_description(xen_session *session, char **result, xen_host host } +bool +xen_host_get_api_version_major(xen_session *session, int64_t *result, xen_host host) +{ + abstract_value param_values[] = + { + { .type = &abstract_type_string, + .u.string_val = host } + }; + + abstract_type result_type = abstract_type_int; + + XEN_CALL_("host.get_API_version_major"); + return session->ok; +} + + +bool +xen_host_get_api_version_minor(xen_session *session, int64_t *result, xen_host host) +{ + abstract_value param_values[] = + { + { .type = &abstract_type_string, + .u.string_val = host } + }; + + abstract_type result_type = abstract_type_int; + + XEN_CALL_("host.get_API_version_minor"); + return session->ok; +} + + +bool +xen_host_get_api_version_vendor(xen_session *session, char **result, xen_host host) +{ + abstract_value param_values[] = + { + { .type = &abstract_type_string, + .u.string_val = host } + }; + + abstract_type result_type = abstract_type_string; + + *result = NULL; + XEN_CALL_("host.get_API_version_vendor"); + return session->ok; +} + + +bool +xen_host_get_api_version_vendor_implementation(xen_session *session, xen_string_string_map **result, xen_host host) +{ + abstract_value param_values[] = + { + { .type = &abstract_type_string, + .u.string_val = host } + }; + + abstract_type result_type = abstract_type_string_string_map; + + *result = NULL; + XEN_CALL_("host.get_API_version_vendor_implementation"); + return session->ok; +} + + bool xen_host_get_software_version(xen_session *session, xen_string_string_map **result, xen_host host) { @@ -248,6 +332,23 @@ xen_host_get_other_config(xen_session *session, xen_string_string_map **result, } +bool +xen_host_get_capabilities(xen_session *session, struct xen_string_set **result, xen_host host) +{ + abstract_value param_values[] = + { + { .type = &abstract_type_string, + .u.string_val = host } + }; + + abstract_type result_type = abstract_type_string_set; + + *result = NULL; + XEN_CALL_("host.get_capabilities"); + return session->ok; +} + + bool xen_host_get_supported_bootloaders(xen_session *session, struct xen_string_set **result, xen_host host) { diff --git a/tools/libxen/src/xen_host_cpu.c b/tools/libxen/src/xen_host_cpu.c index 1300ce0e43..1494c10191 100644 --- a/tools/libxen/src/xen_host_cpu.c +++ b/tools/libxen/src/xen_host_cpu.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, XenSource Inc. + * 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 @@ -55,6 +55,12 @@ static const struct_member xen_host_cpu_record_struct_members[] = { .key = "modelname", .type = &abstract_type_string, .offset = offsetof(xen_host_cpu_record, modelname) }, + { .key = "stepping", + .type = &abstract_type_string, + .offset = offsetof(xen_host_cpu_record, stepping) }, + { .key = "flags", + .type = &abstract_type_string, + .offset = offsetof(xen_host_cpu_record, flags) }, { .key = "utilisation", .type = &abstract_type_float, .offset = offsetof(xen_host_cpu_record, utilisation) } @@ -82,6 +88,8 @@ xen_host_cpu_record_free(xen_host_cpu_record *record) xen_host_record_opt_free(record->host); free(record->vendor); free(record->modelname); + free(record->stepping); + free(record->flags); free(record); } @@ -126,37 +134,6 @@ xen_host_cpu_get_by_uuid(xen_session *session, xen_host_cpu *result, char *uuid) } -bool -xen_host_cpu_create(xen_session *session, xen_host_cpu *result, xen_host_cpu_record *record) -{ - abstract_value param_values[] = - { - { .type = &xen_host_cpu_record_abstract_type_, - .u.struct_val = record } - }; - - abstract_type result_type = abstract_type_string; - - *result = NULL; - XEN_CALL_("host_cpu.create"); - return session->ok; -} - - -bool -xen_host_cpu_destroy(xen_session *session, xen_host_cpu host_cpu) -{ - abstract_value param_values[] = - { - { .type = &abstract_type_string, - .u.string_val = host_cpu } - }; - - xen_call_(session, "host_cpu.destroy", param_values, 1, NULL, NULL); - return session->ok; -} - - bool xen_host_cpu_get_host(xen_session *session, xen_host *result, xen_host_cpu host_cpu) { @@ -240,6 +217,40 @@ xen_host_cpu_get_modelname(xen_session *session, char **result, xen_host_cpu hos } +bool +xen_host_cpu_get_stepping(xen_session *session, char **result, xen_host_cpu host_cpu) +{ + abstract_value param_values[] = + { + { .type = &abstract_type_string, + .u.string_val = host_cpu } + }; + + abstract_type result_type = abstract_type_string; + + *result = NULL; + XEN_CALL_("host_cpu.get_stepping"); + return session->ok; +} + + +bool +xen_host_cpu_get_flags(xen_session *session, char **result, xen_host_cpu host_cpu) +{ + abstract_value param_values[] = + { + { .type = &abstract_type_string, + .u.string_val = host_cpu } + }; + + abstract_type result_type = abstract_type_string; + + *result = NULL; + XEN_CALL_("host_cpu.get_flags"); + return session->ok; +} + + bool xen_host_cpu_get_utilisation(xen_session *session, double *result, xen_host_cpu host_cpu) { @@ -256,6 +267,18 @@ xen_host_cpu_get_utilisation(xen_session *session, double *result, xen_host_cpu } +bool +xen_host_cpu_get_all(xen_session *session, struct xen_host_cpu_set **result) +{ + + abstract_type result_type = abstract_type_string_set; + + *result = NULL; + xen_call_(session, "host_cpu.get_all", NULL, 0, &result_type, result); + return session->ok; +} + + bool xen_host_cpu_get_uuid(xen_session *session, char **result, xen_host_cpu host_cpu) { diff --git a/tools/libxen/src/xen_host_metrics.c b/tools/libxen/src/xen_host_metrics.c index 910ca229ec..d82994dfd0 100644 --- a/tools/libxen/src/xen_host_metrics.c +++ b/tools/libxen/src/xen_host_metrics.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, XenSource Inc. + * 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 @@ -21,7 +21,6 @@ #include #include "xen_common.h" -#include "xen_host.h" #include "xen_host_metrics.h" #include "xen_internal.h" @@ -40,9 +39,6 @@ static const struct_member xen_host_metrics_record_struct_members[] = { .key = "uuid", .type = &abstract_type_string, .offset = offsetof(xen_host_metrics_record, uuid) }, - { .key = "host", - .type = &abstract_type_ref, - .offset = offsetof(xen_host_metrics_record, host) }, { .key = "memory_total", .type = &abstract_type_int, .offset = offsetof(xen_host_metrics_record, memory_total) }, @@ -70,7 +66,6 @@ xen_host_metrics_record_free(xen_host_metrics_record *record) } free(record->handle); free(record->uuid); - xen_host_record_opt_free(record->host); free(record); } @@ -115,23 +110,6 @@ xen_host_metrics_get_by_uuid(xen_session *session, xen_host_metrics *result, cha } -bool -xen_host_metrics_get_host(xen_session *session, xen_host *result, xen_host_metrics host_metrics) -{ - abstract_value param_values[] = - { - { .type = &abstract_type_string, - .u.string_val = host_metrics } - }; - - abstract_type result_type = abstract_type_string; - - *result = NULL; - XEN_CALL_("host_metrics.get_host"); - return session->ok; -} - - bool xen_host_metrics_get_memory_total(xen_session *session, int64_t *result, xen_host_metrics host_metrics) { @@ -164,6 +142,18 @@ xen_host_metrics_get_memory_free(xen_session *session, int64_t *result, xen_host } +bool +xen_host_metrics_get_all(xen_session *session, struct xen_host_metrics_set **result) +{ + + abstract_type result_type = abstract_type_string_set; + + *result = NULL; + xen_call_(session, "host_metrics.get_all", NULL, 0, &result_type, result); + return session->ok; +} + + bool xen_host_metrics_get_uuid(xen_session *session, char **result, xen_host_metrics host_metrics) { diff --git a/tools/libxen/src/xen_network.c b/tools/libxen/src/xen_network.c index 4c56e6e41d..2351404705 100644 --- a/tools/libxen/src/xen_network.c +++ b/tools/libxen/src/xen_network.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, XenSource Inc. + * 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 @@ -52,13 +52,7 @@ static const struct_member xen_network_record_struct_members[] = .offset = offsetof(xen_network_record, vifs) }, { .key = "PIFs", .type = &abstract_type_ref_set, - .offset = offsetof(xen_network_record, pifs) }, - { .key = "default_gateway", - .type = &abstract_type_string, - .offset = offsetof(xen_network_record, default_gateway) }, - { .key = "default_netmask", - .type = &abstract_type_string, - .offset = offsetof(xen_network_record, default_netmask) } + .offset = offsetof(xen_network_record, pifs) } }; const abstract_type xen_network_record_abstract_type_ = @@ -84,8 +78,6 @@ xen_network_record_free(xen_network_record *record) free(record->name_description); xen_vif_record_opt_set_free(record->vifs); xen_pif_record_opt_set_free(record->pifs); - free(record->default_gateway); - free(record->default_netmask); free(record); } @@ -246,40 +238,6 @@ xen_network_get_pifs(xen_session *session, struct xen_pif_set **result, xen_netw } -bool -xen_network_get_default_gateway(xen_session *session, char **result, xen_network network) -{ - abstract_value param_values[] = - { - { .type = &abstract_type_string, - .u.string_val = network } - }; - - abstract_type result_type = abstract_type_string; - - *result = NULL; - XEN_CALL_("network.get_default_gateway"); - return session->ok; -} - - -bool -xen_network_get_default_netmask(xen_session *session, char **result, xen_network network) -{ - abstract_value param_values[] = - { - { .type = &abstract_type_string, - .u.string_val = network } - }; - - abstract_type result_type = abstract_type_string; - - *result = NULL; - XEN_CALL_("network.get_default_netmask"); - return session->ok; -} - - bool xen_network_set_name_label(xen_session *session, xen_network network, char *label) { @@ -312,38 +270,6 @@ xen_network_set_name_description(xen_session *session, xen_network network, char } -bool -xen_network_set_default_gateway(xen_session *session, xen_network network, char *default_gateway) -{ - abstract_value param_values[] = - { - { .type = &abstract_type_string, - .u.string_val = network }, - { .type = &abstract_type_string, - .u.string_val = default_gateway } - }; - - xen_call_(session, "network.set_default_gateway", param_values, 2, NULL, NULL); - return session->ok; -} - - -bool -xen_network_set_default_netmask(xen_session *session, xen_network network, char *default_netmask) -{ - abstract_value param_values[] = - { - { .type = &abstract_type_string, - .u.string_val = network }, - { .type = &abstract_type_string, - .u.string_val = default_netmask } - }; - - xen_call_(session, "network.set_default_netmask", param_values, 2, NULL, NULL); - return session->ok; -} - - bool xen_network_get_all(xen_session *session, struct xen_network_set **result) { diff --git a/tools/libxen/src/xen_pbd.c b/tools/libxen/src/xen_pbd.c index cb7ac9df72..1bdcd785fa 100644 --- a/tools/libxen/src/xen_pbd.c +++ b/tools/libxen/src/xen_pbd.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, XenSource Inc. + * 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 @@ -220,6 +220,18 @@ xen_pbd_get_currently_attached(xen_session *session, bool *result, xen_pbd pbd) } +bool +xen_pbd_get_all(xen_session *session, struct xen_pbd_set **result) +{ + + abstract_type result_type = abstract_type_string_set; + + *result = NULL; + xen_call_(session, "PBD.get_all", NULL, 0, &result_type, result); + return session->ok; +} + + bool xen_pbd_get_uuid(xen_session *session, char **result, xen_pbd pbd) { diff --git a/tools/libxen/src/xen_pif.c b/tools/libxen/src/xen_pif.c index 0e9af6a382..f710acef4b 100644 --- a/tools/libxen/src/xen_pif.c +++ b/tools/libxen/src/xen_pif.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, XenSource Inc. + * 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 @@ -351,6 +351,18 @@ xen_pif_destroy(xen_session *session, xen_pif self) } +bool +xen_pif_get_all(xen_session *session, struct xen_pif_set **result) +{ + + abstract_type result_type = abstract_type_string_set; + + *result = NULL; + xen_call_(session, "PIF.get_all", NULL, 0, &result_type, result); + return session->ok; +} + + bool xen_pif_get_uuid(xen_session *session, char **result, xen_pif pif) { diff --git a/tools/libxen/src/xen_pif_metrics.c b/tools/libxen/src/xen_pif_metrics.c index 3f09ae7dc1..65e3e22f3b 100644 --- a/tools/libxen/src/xen_pif_metrics.c +++ b/tools/libxen/src/xen_pif_metrics.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, XenSource Inc. + * 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 @@ -22,7 +22,6 @@ #include "xen_common.h" #include "xen_internal.h" -#include "xen_pif.h" #include "xen_pif_metrics.h" @@ -40,9 +39,6 @@ static const struct_member xen_pif_metrics_record_struct_members[] = { .key = "uuid", .type = &abstract_type_string, .offset = offsetof(xen_pif_metrics_record, uuid) }, - { .key = "PIF", - .type = &abstract_type_ref, - .offset = offsetof(xen_pif_metrics_record, pif) }, { .key = "io_read_kbs", .type = &abstract_type_float, .offset = offsetof(xen_pif_metrics_record, io_read_kbs) }, @@ -70,7 +66,6 @@ xen_pif_metrics_record_free(xen_pif_metrics_record *record) } free(record->handle); free(record->uuid); - xen_pif_record_opt_free(record->pif); free(record); } @@ -115,23 +110,6 @@ xen_pif_metrics_get_by_uuid(xen_session *session, xen_pif_metrics *result, char } -bool -xen_pif_metrics_get_pif(xen_session *session, xen_pif *result, xen_pif_metrics pif_metrics) -{ - abstract_value param_values[] = - { - { .type = &abstract_type_string, - .u.string_val = pif_metrics } - }; - - abstract_type result_type = abstract_type_string; - - *result = NULL; - XEN_CALL_("PIF_metrics.get_PIF"); - return session->ok; -} - - bool xen_pif_metrics_get_io_read_kbs(xen_session *session, double *result, xen_pif_metrics pif_metrics) { @@ -164,6 +142,18 @@ xen_pif_metrics_get_io_write_kbs(xen_session *session, double *result, xen_pif_m } +bool +xen_pif_metrics_get_all(xen_session *session, struct xen_pif_metrics_set **result) +{ + + abstract_type result_type = abstract_type_string_set; + + *result = NULL; + xen_call_(session, "PIF_metrics.get_all", NULL, 0, &result_type, result); + return session->ok; +} + + bool xen_pif_metrics_get_uuid(xen_session *session, char **result, xen_pif_metrics pif_metrics) { diff --git a/tools/libxen/src/xen_vbd.c b/tools/libxen/src/xen_vbd.c index 5e0b14dfbb..def7403ef9 100644 --- a/tools/libxen/src/xen_vbd.c +++ b/tools/libxen/src/xen_vbd.c @@ -66,12 +66,24 @@ static const struct_member xen_vbd_record_struct_members[] = { .key = "type", .type = &xen_vbd_type_abstract_type_, .offset = offsetof(xen_vbd_record, type) }, + { .key = "currently_attached", + .type = &abstract_type_bool, + .offset = offsetof(xen_vbd_record, currently_attached) }, + { .key = "status_code", + .type = &abstract_type_int, + .offset = offsetof(xen_vbd_record, status_code) }, + { .key = "status_detail", + .type = &abstract_type_string, + .offset = offsetof(xen_vbd_record, status_detail) }, { .key = "qos_algorithm_type", .type = &abstract_type_string, .offset = offsetof(xen_vbd_record, qos_algorithm_type) }, { .key = "qos_algorithm_params", .type = &abstract_type_string_string_map, .offset = offsetof(xen_vbd_record, qos_algorithm_params) }, + { .key = "qos_supported_algorithms", + .type = &abstract_type_string_set, + .offset = offsetof(xen_vbd_record, qos_supported_algorithms) }, { .key = "metrics", .type = &abstract_type_ref, .offset = offsetof(xen_vbd_record, metrics) } @@ -99,8 +111,10 @@ xen_vbd_record_free(xen_vbd_record *record) xen_vm_record_opt_free(record->vm); xen_vdi_record_opt_free(record->vdi); free(record->device); + free(record->status_detail); free(record->qos_algorithm_type); xen_string_string_map_free(record->qos_algorithm_params); + xen_string_set_free(record->qos_supported_algorithms); xen_vbd_metrics_record_opt_free(record->metrics); free(record); } @@ -274,6 +288,55 @@ xen_vbd_get_type(xen_session *session, enum xen_vbd_type *result, xen_vbd vbd) } +bool +xen_vbd_get_currently_attached(xen_session *session, bool *result, xen_vbd vbd) +{ + abstract_value param_values[] = + { + { .type = &abstract_type_string, + .u.string_val = vbd } + }; + + abstract_type result_type = abstract_type_bool; + + XEN_CALL_("VBD.get_currently_attached"); + return session->ok; +} + + +bool +xen_vbd_get_status_code(xen_session *session, int64_t *result, xen_vbd vbd) +{ + abstract_value param_values[] = + { + { .type = &abstract_type_string, + .u.string_val = vbd } + }; + + abstract_type result_type = abstract_type_int; + + XEN_CALL_("VBD.get_status_code"); + return session->ok; +} + + +bool +xen_vbd_get_status_detail(xen_session *session, char **result, xen_vbd vbd) +{ + abstract_value param_values[] = + { + { .type = &abstract_type_string, + .u.string_val = vbd } + }; + + abstract_type result_type = abstract_type_string; + + *result = NULL; + XEN_CALL_("VBD.get_status_detail"); + return session->ok; +} + + bool xen_vbd_get_qos_algorithm_type(xen_session *session, char **result, xen_vbd vbd) { @@ -308,6 +371,23 @@ xen_vbd_get_qos_algorithm_params(xen_session *session, xen_string_string_map **r } +bool +xen_vbd_get_qos_supported_algorithms(xen_session *session, struct xen_string_set **result, xen_vbd vbd) +{ + abstract_value param_values[] = + { + { .type = &abstract_type_string, + .u.string_val = vbd } + }; + + abstract_type result_type = abstract_type_string_set; + + *result = NULL; + XEN_CALL_("VBD.get_qos_supported_algorithms"); + return session->ok; +} + + bool xen_vbd_get_metrics(xen_session *session, xen_vbd_metrics *result, xen_vbd vbd) { @@ -471,6 +551,18 @@ xen_vbd_media_change(xen_session *session, xen_vbd vbd, xen_vdi vdi) } +bool +xen_vbd_get_all(xen_session *session, struct xen_vbd_set **result) +{ + + abstract_type result_type = abstract_type_string_set; + + *result = NULL; + xen_call_(session, "VBD.get_all", NULL, 0, &result_type, result); + return session->ok; +} + + bool xen_vbd_get_uuid(xen_session *session, char **result, xen_vbd vbd) { diff --git a/tools/libxen/src/xen_vbd_metrics.c b/tools/libxen/src/xen_vbd_metrics.c index f2f51506df..985553d5a0 100644 --- a/tools/libxen/src/xen_vbd_metrics.c +++ b/tools/libxen/src/xen_vbd_metrics.c @@ -142,6 +142,18 @@ xen_vbd_metrics_get_io_write_kbs(xen_session *session, double *result, xen_vbd_m } +bool +xen_vbd_metrics_get_all(xen_session *session, struct xen_vbd_metrics_set **result) +{ + + abstract_type result_type = abstract_type_string_set; + + *result = NULL; + xen_call_(session, "VBD_metrics.get_all", NULL, 0, &result_type, result); + return session->ok; +} + + bool xen_vbd_metrics_get_uuid(xen_session *session, char **result, xen_vbd_metrics vbd_metrics) { diff --git a/tools/libxen/src/xen_vdi.c b/tools/libxen/src/xen_vdi.c index 005425ebc1..150d341b1b 100644 --- a/tools/libxen/src/xen_vdi.c +++ b/tools/libxen/src/xen_vdi.c @@ -506,6 +506,18 @@ xen_vdi_resize(xen_session *session, xen_vdi vdi, int64_t size) } +bool +xen_vdi_get_all(xen_session *session, struct xen_vdi_set **result) +{ + + abstract_type result_type = abstract_type_string_set; + + *result = NULL; + xen_call_(session, "VDI.get_all", NULL, 0, &result_type, result); + return session->ok; +} + + bool xen_vdi_get_uuid(xen_session *session, char **result, xen_vdi vdi) { diff --git a/tools/libxen/src/xen_vif.c b/tools/libxen/src/xen_vif.c index 62a6ef16a2..11cba1dcbd 100644 --- a/tools/libxen/src/xen_vif.c +++ b/tools/libxen/src/xen_vif.c @@ -58,12 +58,24 @@ static const struct_member xen_vif_record_struct_members[] = { .key = "MTU", .type = &abstract_type_int, .offset = offsetof(xen_vif_record, mtu) }, + { .key = "currently_attached", + .type = &abstract_type_bool, + .offset = offsetof(xen_vif_record, currently_attached) }, + { .key = "status_code", + .type = &abstract_type_int, + .offset = offsetof(xen_vif_record, status_code) }, + { .key = "status_detail", + .type = &abstract_type_string, + .offset = offsetof(xen_vif_record, status_detail) }, { .key = "qos_algorithm_type", .type = &abstract_type_string, .offset = offsetof(xen_vif_record, qos_algorithm_type) }, { .key = "qos_algorithm_params", .type = &abstract_type_string_string_map, .offset = offsetof(xen_vif_record, qos_algorithm_params) }, + { .key = "qos_supported_algorithms", + .type = &abstract_type_string_set, + .offset = offsetof(xen_vif_record, qos_supported_algorithms) }, { .key = "metrics", .type = &abstract_type_ref, .offset = offsetof(xen_vif_record, metrics) } @@ -92,8 +104,10 @@ xen_vif_record_free(xen_vif_record *record) xen_network_record_opt_free(record->network); xen_vm_record_opt_free(record->vm); free(record->mac); + free(record->status_detail); free(record->qos_algorithm_type); xen_string_string_map_free(record->qos_algorithm_params); + xen_string_set_free(record->qos_supported_algorithms); xen_vif_metrics_record_opt_free(record->metrics); free(record); } @@ -254,6 +268,55 @@ xen_vif_get_mtu(xen_session *session, int64_t *result, xen_vif vif) } +bool +xen_vif_get_currently_attached(xen_session *session, bool *result, xen_vif vif) +{ + abstract_value param_values[] = + { + { .type = &abstract_type_string, + .u.string_val = vif } + }; + + abstract_type result_type = abstract_type_bool; + + XEN_CALL_("VIF.get_currently_attached"); + return session->ok; +} + + +bool +xen_vif_get_status_code(xen_session *session, int64_t *result, xen_vif vif) +{ + abstract_value param_values[] = + { + { .type = &abstract_type_string, + .u.string_val = vif } + }; + + abstract_type result_type = abstract_type_int; + + XEN_CALL_("VIF.get_status_code"); + return session->ok; +} + + +bool +xen_vif_get_status_detail(xen_session *session, char **result, xen_vif vif) +{ + abstract_value param_values[] = + { + { .type = &abstract_type_string, + .u.string_val = vif } + }; + + abstract_type result_type = abstract_type_string; + + *result = NULL; + XEN_CALL_("VIF.get_status_detail"); + return session->ok; +} + + bool xen_vif_get_qos_algorithm_type(xen_session *session, char **result, xen_vif vif) { @@ -288,6 +351,23 @@ xen_vif_get_qos_algorithm_params(xen_session *session, xen_string_string_map **r } +bool +xen_vif_get_qos_supported_algorithms(xen_session *session, struct xen_string_set **result, xen_vif vif) +{ + abstract_value param_values[] = + { + { .type = &abstract_type_string, + .u.string_val = vif } + }; + + abstract_type result_type = abstract_type_string_set; + + *result = NULL; + XEN_CALL_("VIF.get_qos_supported_algorithms"); + return session->ok; +} + + bool xen_vif_get_metrics(xen_session *session, xen_vif_metrics *result, xen_vif vif) { @@ -419,6 +499,18 @@ xen_vif_remove_from_qos_algorithm_params(xen_session *session, xen_vif vif, char } +bool +xen_vif_get_all(xen_session *session, struct xen_vif_set **result) +{ + + abstract_type result_type = abstract_type_string_set; + + *result = NULL; + xen_call_(session, "VIF.get_all", NULL, 0, &result_type, result); + return session->ok; +} + + bool xen_vif_get_uuid(xen_session *session, char **result, xen_vif vif) { diff --git a/tools/libxen/src/xen_vif_metrics.c b/tools/libxen/src/xen_vif_metrics.c index 1f43993024..78707b36f5 100644 --- a/tools/libxen/src/xen_vif_metrics.c +++ b/tools/libxen/src/xen_vif_metrics.c @@ -142,6 +142,18 @@ xen_vif_metrics_get_io_write_kbs(xen_session *session, double *result, xen_vif_m } +bool +xen_vif_metrics_get_all(xen_session *session, struct xen_vif_metrics_set **result) +{ + + abstract_type result_type = abstract_type_string_set; + + *result = NULL; + xen_call_(session, "VIF_metrics.get_all", NULL, 0, &result_type, result); + return session->ok; +} + + bool xen_vif_metrics_get_uuid(xen_session *session, char **result, xen_vif_metrics vif_metrics) { diff --git a/tools/libxen/src/xen_vm.c b/tools/libxen/src/xen_vm.c index e3f82575bd..910c9f8b31 100644 --- a/tools/libxen/src/xen_vm.c +++ b/tools/libxen/src/xen_vm.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, XenSource Inc. + * 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 @@ -24,7 +24,6 @@ #include "xen_console.h" #include "xen_crashdump.h" #include "xen_host.h" -#include "xen_int_float_map.h" #include "xen_internal.h" #include "xen_on_crash_behaviour_internal.h" #include "xen_on_normal_exit_internal.h" @@ -33,6 +32,7 @@ #include "xen_vdi.h" #include "xen_vif.h" #include "xen_vm.h" +#include "xen_vm_guest_metrics.h" #include "xen_vm_metrics.h" #include "xen_vm_power_state_internal.h" #include "xen_vtpm.h" @@ -100,12 +100,6 @@ static const struct_member xen_vm_record_struct_members[] = { .key = "VCPUs_at_startup", .type = &abstract_type_int, .offset = offsetof(xen_vm_record, vcpus_at_startup) }, - { .key = "VCPUs_number", - .type = &abstract_type_int, - .offset = offsetof(xen_vm_record, vcpus_number) }, - { .key = "VCPUs_utilisation", - .type = &abstract_type_int_float_map, - .offset = offsetof(xen_vm_record, vcpus_utilisation) }, { .key = "actions_after_shutdown", .type = &xen_on_normal_exit_abstract_type_, .offset = offsetof(xen_vm_record, actions_after_shutdown) }, @@ -169,18 +163,21 @@ static const struct_member xen_vm_record_struct_members[] = { .key = "PCI_bus", .type = &abstract_type_string, .offset = offsetof(xen_vm_record, pci_bus) }, - { .key = "tools_version", - .type = &abstract_type_string_string_map, - .offset = offsetof(xen_vm_record, tools_version) }, { .key = "other_config", .type = &abstract_type_string_string_map, .offset = offsetof(xen_vm_record, other_config) }, + { .key = "domid", + .type = &abstract_type_int, + .offset = offsetof(xen_vm_record, domid) }, { .key = "is_control_domain", .type = &abstract_type_bool, .offset = offsetof(xen_vm_record, is_control_domain) }, { .key = "metrics", .type = &abstract_type_ref, - .offset = offsetof(xen_vm_record, metrics) } + .offset = offsetof(xen_vm_record, metrics) }, + { .key = "guest_metrics", + .type = &abstract_type_ref, + .offset = offsetof(xen_vm_record, guest_metrics) } }; const abstract_type xen_vm_record_abstract_type_ = @@ -208,7 +205,6 @@ xen_vm_record_free(xen_vm_record *record) xen_host_record_opt_free(record->resident_on); free(record->vcpus_policy); xen_string_string_map_free(record->vcpus_params); - xen_int_float_map_free(record->vcpus_utilisation); xen_console_record_opt_set_free(record->consoles); xen_vif_record_opt_set_free(record->vifs); xen_vbd_record_opt_set_free(record->vbds); @@ -223,9 +219,9 @@ xen_vm_record_free(xen_vm_record *record) xen_string_string_map_free(record->hvm_boot_params); free(record->platform_serial); free(record->pci_bus); - xen_string_string_map_free(record->tools_version); xen_string_string_map_free(record->other_config); xen_vm_metrics_record_opt_free(record->metrics); + xen_vm_guest_metrics_record_opt_free(record->guest_metrics); free(record); } @@ -579,39 +575,6 @@ xen_vm_get_vcpus_at_startup(xen_session *session, int64_t *result, xen_vm vm) } -bool -xen_vm_get_vcpus_number(xen_session *session, int64_t *result, xen_vm vm) -{ - abstract_value param_values[] = - { - { .type = &abstract_type_string, - .u.string_val = vm } - }; - - abstract_type result_type = abstract_type_int; - - XEN_CALL_("VM.get_VCPUs_number"); - return session->ok; -} - - -bool -xen_vm_get_vcpus_utilisation(xen_session *session, xen_int_float_map **result, xen_vm vm) -{ - abstract_value param_values[] = - { - { .type = &abstract_type_string, - .u.string_val = vm } - }; - - abstract_type result_type = abstract_type_int_float_map; - - *result = NULL; - XEN_CALL_("VM.get_VCPUs_utilisation"); - return session->ok; -} - - bool xen_vm_get_actions_after_shutdown(xen_session *session, enum xen_on_normal_exit *result, xen_vm vm) { @@ -959,23 +922,6 @@ xen_vm_get_pci_bus(xen_session *session, char **result, xen_vm vm) } -bool -xen_vm_get_tools_version(xen_session *session, xen_string_string_map **result, xen_vm vm) -{ - abstract_value param_values[] = - { - { .type = &abstract_type_string, - .u.string_val = vm } - }; - - abstract_type result_type = abstract_type_string_string_map; - - *result = NULL; - XEN_CALL_("VM.get_tools_version"); - return session->ok; -} - - bool xen_vm_get_other_config(xen_session *session, xen_string_string_map **result, xen_vm vm) { @@ -993,6 +939,22 @@ xen_vm_get_other_config(xen_session *session, xen_string_string_map **result, xe } +bool +xen_vm_get_domid(xen_session *session, int64_t *result, xen_vm vm) +{ + abstract_value param_values[] = + { + { .type = &abstract_type_string, + .u.string_val = vm } + }; + + abstract_type result_type = abstract_type_int; + + XEN_CALL_("VM.get_domid"); + return session->ok; +} + + bool xen_vm_get_is_control_domain(xen_session *session, bool *result, xen_vm vm) { @@ -1026,6 +988,23 @@ xen_vm_get_metrics(xen_session *session, xen_vm_metrics *result, xen_vm vm) } +bool +xen_vm_get_guest_metrics(xen_session *session, xen_vm_guest_metrics *result, xen_vm vm) +{ + abstract_value param_values[] = + { + { .type = &abstract_type_string, + .u.string_val = vm } + }; + + abstract_type result_type = abstract_type_string; + + *result = NULL; + XEN_CALL_("VM.get_guest_metrics"); + return session->ok; +} + + bool xen_vm_set_name_label(xen_session *session, xen_vm vm, char *label) { diff --git a/tools/libxen/src/xen_vm_guest_metrics.c b/tools/libxen/src/xen_vm_guest_metrics.c new file mode 100644 index 0000000000..dd464c4806 --- /dev/null +++ b/tools/libxen/src/xen_vm_guest_metrics.c @@ -0,0 +1,251 @@ +/* + * 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 +#include + +#include "xen_common.h" +#include "xen_internal.h" +#include "xen_string_string_map.h" +#include "xen_vm_guest_metrics.h" + + +XEN_FREE(xen_vm_guest_metrics) +XEN_SET_ALLOC_FREE(xen_vm_guest_metrics) +XEN_ALLOC(xen_vm_guest_metrics_record) +XEN_SET_ALLOC_FREE(xen_vm_guest_metrics_record) +XEN_ALLOC(xen_vm_guest_metrics_record_opt) +XEN_RECORD_OPT_FREE(xen_vm_guest_metrics) +XEN_SET_ALLOC_FREE(xen_vm_guest_metrics_record_opt) + + +static const struct_member xen_vm_guest_metrics_record_struct_members[] = + { + { .key = "uuid", + .type = &abstract_type_string, + .offset = offsetof(xen_vm_guest_metrics_record, uuid) }, + { .key = "os_version", + .type = &abstract_type_string_string_map, + .offset = offsetof(xen_vm_guest_metrics_record, os_version) }, + { .key = "PV_drivers_version", + .type = &abstract_type_string_string_map, + .offset = offsetof(xen_vm_guest_metrics_record, pv_drivers_version) }, + { .key = "memory", + .type = &abstract_type_string_string_map, + .offset = offsetof(xen_vm_guest_metrics_record, memory) }, + { .key = "disks", + .type = &abstract_type_string_string_map, + .offset = offsetof(xen_vm_guest_metrics_record, disks) }, + { .key = "networks", + .type = &abstract_type_string_string_map, + .offset = offsetof(xen_vm_guest_metrics_record, networks) }, + { .key = "other", + .type = &abstract_type_string_string_map, + .offset = offsetof(xen_vm_guest_metrics_record, other) } + }; + +const abstract_type xen_vm_guest_metrics_record_abstract_type_ = + { + .typename = STRUCT, + .struct_size = sizeof(xen_vm_guest_metrics_record), + .member_count = + sizeof(xen_vm_guest_metrics_record_struct_members) / sizeof(struct_member), + .members = xen_vm_guest_metrics_record_struct_members + }; + + +void +xen_vm_guest_metrics_record_free(xen_vm_guest_metrics_record *record) +{ + if (record == NULL) + { + return; + } + free(record->handle); + free(record->uuid); + xen_string_string_map_free(record->os_version); + xen_string_string_map_free(record->pv_drivers_version); + xen_string_string_map_free(record->memory); + xen_string_string_map_free(record->disks); + xen_string_string_map_free(record->networks); + xen_string_string_map_free(record->other); + free(record); +} + + +bool +xen_vm_guest_metrics_get_record(xen_session *session, xen_vm_guest_metrics_record **result, xen_vm_guest_metrics vm_guest_metrics) +{ + abstract_value param_values[] = + { + { .type = &abstract_type_string, + .u.string_val = vm_guest_metrics } + }; + + abstract_type result_type = xen_vm_guest_metrics_record_abstract_type_; + + *result = NULL; + XEN_CALL_("VM_guest_metrics.get_record"); + + if (session->ok) + { + (*result)->handle = xen_strdup_((*result)->uuid); + } + + return session->ok; +} + + +bool +xen_vm_guest_metrics_get_by_uuid(xen_session *session, xen_vm_guest_metrics *result, char *uuid) +{ + abstract_value param_values[] = + { + { .type = &abstract_type_string, + .u.string_val = uuid } + }; + + abstract_type result_type = abstract_type_string; + + *result = NULL; + XEN_CALL_("VM_guest_metrics.get_by_uuid"); + return session->ok; +} + + +bool +xen_vm_guest_metrics_get_os_version(xen_session *session, xen_string_string_map **result, xen_vm_guest_metrics vm_guest_metrics) +{ + abstract_value param_values[] = + { + { .type = &abstract_type_string, + .u.string_val = vm_guest_metrics } + }; + + abstract_type result_type = abstract_type_string_string_map; + + *result = NULL; + XEN_CALL_("VM_guest_metrics.get_os_version"); + return session->ok; +} + + +bool +xen_vm_guest_metrics_get_pv_drivers_version(xen_session *session, xen_string_string_map **result, xen_vm_guest_metrics vm_guest_metrics) +{ + abstract_value param_values[] = + { + { .type = &abstract_type_string, + .u.string_val = vm_guest_metrics } + }; + + abstract_type result_type = abstract_type_string_string_map; + + *result = NULL; + XEN_CALL_("VM_guest_metrics.get_PV_drivers_version"); + return session->ok; +} + + +bool +xen_vm_guest_metrics_get_memory(xen_session *session, xen_string_string_map **result, xen_vm_guest_metrics vm_guest_metrics) +{ + abstract_value param_values[] = + { + { .type = &abstract_type_string, + .u.string_val = vm_guest_metrics } + }; + + abstract_type result_type = abstract_type_string_string_map; + + *result = NULL; + XEN_CALL_("VM_guest_metrics.get_memory"); + return session->ok; +} + + +bool +xen_vm_guest_metrics_get_disks(xen_session *session, xen_string_string_map **result, xen_vm_guest_metrics vm_guest_metrics) +{ + abstract_value param_values[] = + { + { .type = &abstract_type_string, + .u.string_val = vm_guest_metrics } + }; + + abstract_type result_type = abstract_type_string_string_map; + + *result = NULL; + XEN_CALL_("VM_guest_metrics.get_disks"); + return session->ok; +} + + +bool +xen_vm_guest_metrics_get_networks(xen_session *session, xen_string_string_map **result, xen_vm_guest_metrics vm_guest_metrics) +{ + abstract_value param_values[] = + { + { .type = &abstract_type_string, + .u.string_val = vm_guest_metrics } + }; + + abstract_type result_type = abstract_type_string_string_map; + + *result = NULL; + XEN_CALL_("VM_guest_metrics.get_networks"); + return session->ok; +} + + +bool +xen_vm_guest_metrics_get_other(xen_session *session, xen_string_string_map **result, xen_vm_guest_metrics vm_guest_metrics) +{ + abstract_value param_values[] = + { + { .type = &abstract_type_string, + .u.string_val = vm_guest_metrics } + }; + + abstract_type result_type = abstract_type_string_string_map; + + *result = NULL; + XEN_CALL_("VM_guest_metrics.get_other"); + return session->ok; +} + + +bool +xen_vm_guest_metrics_get_all(xen_session *session, struct xen_vm_guest_metrics_set **result) +{ + + abstract_type result_type = abstract_type_string_set; + + *result = NULL; + xen_call_(session, "VM_guest_metrics.get_all", NULL, 0, &result_type, result); + return session->ok; +} + + +bool +xen_vm_guest_metrics_get_uuid(xen_session *session, char **result, xen_vm_guest_metrics vm_guest_metrics) +{ + *result = session->ok ? xen_strdup_((char *)vm_guest_metrics) : NULL; + return session->ok; +} diff --git a/tools/libxen/src/xen_vm_metrics.c b/tools/libxen/src/xen_vm_metrics.c index 6f5e95166e..9bafa83aa0 100644 --- a/tools/libxen/src/xen_vm_metrics.c +++ b/tools/libxen/src/xen_vm_metrics.c @@ -164,6 +164,18 @@ xen_vm_metrics_get_vcpus_utilisation(xen_session *session, xen_int_float_map **r } +bool +xen_vm_metrics_get_all(xen_session *session, struct xen_vm_metrics_set **result) +{ + + abstract_type result_type = abstract_type_string_set; + + *result = NULL; + xen_call_(session, "VM_metrics.get_all", NULL, 0, &result_type, result); + return session->ok; +} + + bool xen_vm_metrics_get_uuid(xen_session *session, char **result, xen_vm_metrics vm_metrics) { diff --git a/tools/libxen/test/test_bindings.c b/tools/libxen/test/test_bindings.c index c76768af15..6a51cd3a05 100644 --- a/tools/libxen/test/test_bindings.c +++ b/tools/libxen/test/test_bindings.c @@ -238,6 +238,22 @@ int main(int argc, char **argv) return 1; } + xen_string_set *capabilities; + if (!xen_host_get_capabilities(session, &capabilities, host)) + { + print_error(session); + free(dmesg); + xen_string_set_free(supported_bootloaders); + xen_string_string_map_free(versions); + xen_host_free(host); + xen_vm_record_free(vm_record); + xen_uuid_bytes_free(vm_uuid_bytes); + xen_uuid_free(vm_uuid); + xen_vm_free(vm); + CLEANUP; + return 1; + } + printf("%s.\n", vm_uuid); fprintf(stderr, "In bytes, the VM UUID is "); @@ -264,6 +280,13 @@ int main(int argc, char **argv) } printf("\n"); + printf("Host has the following capabilities:"); + for (size_t i = 0; i < capabilities->size; i++) + { + printf(" %s", capabilities->contents[i]); + } + printf("\n"); + printf("%s.\n", vm_record->uuid); printf("Resident on %s.\n", (char *)vm_record->resident_on->u.handle); @@ -279,6 +302,7 @@ int main(int argc, char **argv) xen_string_string_map_free(versions); free(dmesg); xen_string_set_free(supported_bootloaders); + xen_string_set_free(capabilities); print_vm_metrics(session, vm); if (!session->ok) diff --git a/tools/misc/sxp-pretty b/tools/misc/sxp-pretty new file mode 100644 index 0000000000..4b8eaed335 --- /dev/null +++ b/tools/misc/sxp-pretty @@ -0,0 +1,45 @@ +#!/usr/bin/env python +# -*- mode: python; -*- +#============================================================================ +# 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. +#============================================================================ + + +import commands +import os.path +import pprint +import sys + +result = commands.getstatusoutput(os.path.join(os.path.dirname(sys.argv[0]), + 'xen-python-path')) +if result[0] != 0: + print >>sys.stderr, result[1] + sys.exit(1) + +sys.path.append(result[1]) + +import xen.xend.sxp as sxp + +def main(): + if len(sys.argv) == 1 or sys.argv[1] in ['', '-']: + s = sxp.parse(sys.stdin) + else: + s = sxp.parse(open(sys.argv[1])) + + pprint.pprint(s) + +if __name__ == '__main__': + sys.exit(main()) diff --git a/tools/ptsname/Makefile b/tools/ptsname/Makefile deleted file mode 100644 index a1db24c4c5..0000000000 --- a/tools/ptsname/Makefile +++ /dev/null @@ -1,22 +0,0 @@ - -XEN_ROOT = ../.. -include $(XEN_ROOT)/tools/Rules.mk - -.PHONY: all -all: build -.PHONY: build -build: - CC="$(CC)" CFLAGS="$(CFLAGS)" python setup.py build - -.PHONY: install -ifndef XEN_PYTHON_NATIVE_INSTALL -install: all - CC="$(CC)" CFLAGS="$(CFLAGS)" python setup.py install --home="$(DESTDIR)/usr" --prefix="" -else -install: all - CC="$(CC)" CFLAGS="$(CFLAGS)" python setup.py install --root="$(DESTDIR)" -endif - -.PHONY: clean -clean: - rm -rf build tmp *.pyc *.pyo *.o *.a *~ a.out diff --git a/tools/ptsname/setup.py b/tools/ptsname/setup.py deleted file mode 100644 index 5fbdfecd5c..0000000000 --- a/tools/ptsname/setup.py +++ /dev/null @@ -1,11 +0,0 @@ -from distutils.core import setup, Extension - -extra_compile_args = [ "-fno-strict-aliasing", "-Werror" ] - -setup(name = 'ptsname', - version = '1.0', - description = 'POSIX ptsname() function', - author = 'Tim Deegan', - author_email = 'Tim.Deegan@xensource.com', - license = 'GPL', - ext_modules = [ Extension("ptsname", [ "ptsname.c" ]) ]) diff --git a/tools/pygrub/Makefile b/tools/pygrub/Makefile index 2e7b3e4d21..3629d89742 100644 --- a/tools/pygrub/Makefile +++ b/tools/pygrub/Makefile @@ -10,13 +10,14 @@ build: .PHONY: install ifndef XEN_PYTHON_NATIVE_INSTALL +install: LIBPATH=$(shell PYTHONPATH=../python/xen/util python -c "import auxbin; print auxbin.libpath()") install: all - CC="$(CC)" CFLAGS="$(CFLAGS)" python setup.py install --home="$(DESTDIR)/usr" --prefix="" - $(INSTALL_DIR) -p $(DESTDIR)/var/run/xend/boot + CC="$(CC)" CFLAGS="$(CFLAGS)" python setup.py install --home="$(DESTDIR)/usr" --prefix="" --install-lib="$(DESTDIR)$(LIBPATH)/python" + $(INSTALL_DIR) $(DESTDIR)/var/run/xend/boot else install: all CC="$(CC)" CFLAGS="$(CFLAGS)" python setup.py install --root="$(DESTDIR)" - $(INSTALL_DIR) -p $(DESTDIR)/var/run/xend/boot + $(INSTALL_DIR) $(DESTDIR)/var/run/xend/boot endif .PHONY: clean diff --git a/tools/python/Makefile b/tools/python/Makefile index dfef918cb4..ae4254c6e6 100644 --- a/tools/python/Makefile +++ b/tools/python/Makefile @@ -18,8 +18,9 @@ build: .PHONY: install ifndef XEN_PYTHON_NATIVE_INSTALL +install: LIBPATH=$(shell PYTHONPATH=xen/util python -c "import auxbin; print auxbin.libpath()") install: install-messages - CC="$(CC)" CFLAGS="$(CFLAGS)" python setup.py install --home="$(DESTDIR)/usr" --prefix="" --force + CC="$(CC)" CFLAGS="$(CFLAGS)" python setup.py install --home="$(DESTDIR)/usr" --prefix="" --force --install-lib="$(DESTDIR)$(LIBPATH)/python" else install: install-messages CC="$(CC)" CFLAGS="$(CFLAGS)" python setup.py install --root="$(DESTDIR)" --force diff --git a/tools/ptsname/ptsname.c b/tools/python/ptsname/ptsname.c similarity index 100% rename from tools/ptsname/ptsname.c rename to tools/python/ptsname/ptsname.c diff --git a/tools/python/scripts/test_vm_create.py b/tools/python/scripts/test_vm_create.py index 84959c3e0d..e4d8f3023a 100644 --- a/tools/python/scripts/test_vm_create.py +++ b/tools/python/scripts/test_vm_create.py @@ -39,7 +39,7 @@ vm_cfg = { vdi_cfg = { 'name_label': 'API_VDI', 'name_description': '', - 'virtual_size': 100 * 1024, + 'virtual_size': 100 * 1024 * 1024, 'sector_size': 1024, 'type': 'system', 'parent': '', diff --git a/tools/python/scripts/xapi.py b/tools/python/scripts/xapi.py index b5fe8b3682..1e49f86d4c 100644 --- a/tools/python/scripts/xapi.py +++ b/tools/python/scripts/xapi.py @@ -569,7 +569,7 @@ def xapi_vdi_list(args, async = False): if not is_long: print VDI_LIST_FORMAT % {'name_label': 'VDI Label', 'uuid' : 'UUID', - 'virtual_size': 'Sectors', + 'virtual_size': 'Bytes', 'sector_size': 'Sector Size'} for vdi in vdis: @@ -628,7 +628,7 @@ def xapi_vdi_create(args, async = False): sr = srs[0] cfg['SR'] = sr - size = (cfg['virtual_size'] * cfg['sector_size'])/MB + size = cfg['virtual_size']/MB print 'Creating VDI of size: %dMB ..' % size, uuid = execute(server, 'VDI.create', (session, cfg), async = async) if async: diff --git a/tools/python/scripts/xapi.vdicfg.py b/tools/python/scripts/xapi.vdicfg.py index f694b83cf5..86129bfae9 100644 --- a/tools/python/scripts/xapi.vdicfg.py +++ b/tools/python/scripts/xapi.vdicfg.py @@ -1,6 +1,6 @@ name_label = 'VDI 1' name_description = '' -virtual_size = 10 * 1024 +virtual_size = 10 * 1024 * 1024 sector_size = 1024 type = 'system' sharable = False diff --git a/tools/python/setup.py b/tools/python/setup.py index 7b25025d9d..11ef487203 100644 --- a/tools/python/setup.py +++ b/tools/python/setup.py @@ -44,7 +44,14 @@ acm = Extension("acm", libraries = libraries, sources = [ "xen/lowlevel/acm/acm.c" ]) -modules = [ xc, xs, acm ] +ptsname = Extension("ptsname", + extra_compile_args = extra_compile_args, + include_dirs = include_dirs + [ "ptsname" ], + library_dirs = library_dirs, + libraries = libraries, + sources = [ "ptsname/ptsname.c" ]) + +modules = [ xc, xs, acm, ptsname ] if os.uname()[0] == 'SunOS': modules.append(scf) diff --git a/tools/python/xen/lowlevel/xc/xc.c b/tools/python/xen/lowlevel/xc/xc.c index 792f57f7d4..b3dbb20ed7 100644 --- a/tools/python/xen/lowlevel/xc/xc.c +++ b/tools/python/xen/lowlevel/xc/xc.c @@ -18,9 +18,13 @@ #include #include "xenctrl.h" +#include +#include "xc_dom.h" #include #include +#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) + /* Needed for Python versions earlier than 2.3. */ #ifndef PyMODINIT_FUNC #define PyMODINIT_FUNC DL_EXPORT(void) @@ -176,7 +180,17 @@ static PyObject *pyxc_domain_shutdown(XcObject *self, PyObject *args) static PyObject *pyxc_domain_resume(XcObject *self, PyObject *args) { - return dom_op(self, args, xc_domain_resume); + uint32_t dom; + int fast; + + if (!PyArg_ParseTuple(args, "ii", &dom, &fast)) + return NULL; + + if (xc_domain_resume(self->xc_handle, dom, fast) != 0) + return pyxc_error_to_exception(); + + Py_INCREF(zero); + return zero; } static PyObject *pyxc_vcpu_setaffinity(XcObject *self, @@ -371,13 +385,17 @@ static PyObject *pyxc_linux_build(XcObject *self, PyObject *args, PyObject *kwds) { - uint32_t dom; + uint32_t domid; + struct xc_dom_image *dom; char *image, *ramdisk = NULL, *cmdline = "", *features = NULL; int flags = 0; int store_evtchn, console_evtchn; unsigned int mem_mb; unsigned long store_mfn = 0; unsigned long console_mfn = 0; + PyObject* elfnote_dict; + PyObject* elfnote = NULL; + int i; static char *kwd_list[] = { "domid", "store_evtchn", "memsize", "console_evtchn", "image", @@ -386,22 +404,55 @@ static PyObject *pyxc_linux_build(XcObject *self, "features", NULL }; if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iiiis|ssis", kwd_list, - &dom, &store_evtchn, &mem_mb, + &domid, &store_evtchn, &mem_mb, &console_evtchn, &image, /* optional */ &ramdisk, &cmdline, &flags, &features) ) return NULL; - if ( xc_linux_build(self->xc_handle, dom, mem_mb, image, - ramdisk, cmdline, features, flags, - store_evtchn, &store_mfn, - console_evtchn, &console_mfn) != 0 ) { - return pyxc_error_to_exception(); + xc_dom_loginit(); + if (!(dom = xc_dom_allocate(cmdline, features))) + return pyxc_error_to_exception(); + + if ( xc_dom_linux_build(self->xc_handle, dom, domid, mem_mb, image, + ramdisk, flags, store_evtchn, &store_mfn, + console_evtchn, &console_mfn) != 0 ) { + goto out; } - return Py_BuildValue("{s:i,s:i}", + + if ( !(elfnote_dict = PyDict_New()) ) + goto out; + + for ( i = 0; i < ARRAY_SIZE(dom->parms.elf_notes); i++ ) + { + switch ( dom->parms.elf_notes[i].type ) + { + case XEN_ENT_NONE: + continue; + case XEN_ENT_LONG: + elfnote = Py_BuildValue("k", dom->parms.elf_notes[i].data.num); + break; + case XEN_ENT_STR: + elfnote = Py_BuildValue("s", dom->parms.elf_notes[i].data.str); + break; + } + PyDict_SetItemString(elfnote_dict, + dom->parms.elf_notes[i].name, + elfnote); + Py_DECREF(elfnote); + } + + xc_dom_release(dom); + + return Py_BuildValue("{s:i,s:i,s:N}", "store_mfn", store_mfn, - "console_mfn", console_mfn); + "console_mfn", console_mfn, + "notes", elfnote_dict); + + out: + xc_dom_release(dom); + return pyxc_error_to_exception(); } static PyObject *pyxc_hvm_build(XcObject *self, @@ -936,6 +987,26 @@ static PyObject *pyxc_domain_set_time_offset(XcObject *self, PyObject *args) return zero; } +static PyObject *pyxc_domain_send_trigger(XcObject *self, + PyObject *args, + PyObject *kwds) +{ + uint32_t dom; + int trigger, vcpu = 0; + + static char *kwd_list[] = { "domid", "trigger", "vcpu", NULL }; + + if ( !PyArg_ParseTupleAndKeywords(args, kwds, "ii|i", kwd_list, + &dom, &trigger, &vcpu) ) + return NULL; + + if (xc_domain_send_trigger(self->xc_handle, dom, trigger, vcpu) != 0) + return pyxc_error_to_exception(); + + Py_INCREF(zero); + return zero; +} + static PyObject *dom_op(XcObject *self, PyObject *args, int (*fn)(int, uint32_t)) { @@ -1068,7 +1139,8 @@ static PyMethodDef pyxc_methods[] = { (PyCFunction)pyxc_domain_resume, METH_VARARGS, "\n" "Resume execution of a suspended domain.\n" - " dom [int]: Identifier of domain to be resumed.\n\n" + " dom [int]: Identifier of domain to be resumed.\n" + " fast [int]: Use cooperative resume.\n\n" "Returns: [int] 0 on success; -1 on error.\n" }, { "domain_shutdown", @@ -1339,6 +1411,15 @@ static PyMethodDef pyxc_methods[] = { " dom [int]: Domain whose time offset is being set.\n" "Returns: [int] 0 on success; -1 on error.\n" }, + { "domain_send_trigger", + (PyCFunction)pyxc_domain_send_trigger, + METH_VARARGS | METH_KEYWORDS, "\n" + "Send trigger to a domain.\n" + " dom [int]: Identifier of domain to be sent trigger.\n" + " trigger [int]: Trigger type number.\n" + " vcpu [int]: VCPU to be sent trigger.\n" + "Returns: [int] 0 on success; -1 on error.\n" }, + #ifdef __powerpc__ { "arch_alloc_real_mode_area", (PyCFunction)pyxc_alloc_real_mode_area, diff --git a/tools/python/xen/util/xmlrpclib2.py b/tools/python/xen/util/xmlrpclib2.py index c701020b15..a77b61b5ee 100644 --- a/tools/python/xen/util/xmlrpclib2.py +++ b/tools/python/xen/util/xmlrpclib2.py @@ -238,8 +238,11 @@ class TCPXMLRPCServer(SocketServer.ThreadingMixIn, SimpleXMLRPCServer): notSupportedRE = re.compile(r'method "(.*)" is not supported') def _is_not_supported(exn): - m = notSupportedRE.search(exn[0]) - return m is not None + try: + m = notSupportedRE.search(exn[0]) + return m is not None + except TypeError, e: + return False # This is a XML-RPC server that sits on a Unix domain socket. diff --git a/tools/python/xen/xend/XendAPI.py b/tools/python/xen/xend/XendAPI.py index 277ef3b4c0..4ab6916b53 100644 --- a/tools/python/xen/xend/XendAPI.py +++ b/tools/python/xen/xend/XendAPI.py @@ -25,6 +25,7 @@ import threading from xen.xend import XendDomain, XendDomainInfo, XendNode, XendDmesg from xen.xend import XendLogging, XendTaskManager +from xen.xend.XendAPIVersion import * from xen.xend.XendAuthSessions import instance as auth_manager from xen.xend.XendError import * from xen.xend.XendClient import ERROR_INVALID_DOMAIN @@ -104,20 +105,22 @@ def catch_typeerror(func): except TypeError, exn: #log.exception('catch_typeerror') if hasattr(func, 'api') and func.api in argcounts: - # Assume that if the exception was thrown inside this - # file, then it is due to an invalid call from the client, - # but if it was thrown elsewhere, then it's an internal + # Assume that if the argument count was wrong and if the + # exception was thrown inside this file, then it is due to an + # invalid call from the client, otherwise it's an internal # error (which will be handled further up). - tb = sys.exc_info()[2] - try: - sourcefile = traceback.extract_tb(tb)[-1][0] - if sourcefile == inspect.getsourcefile(XendAPI): - return xen_api_error( - ['MESSAGE_PARAMETER_COUNT_MISMATCH', - func.api, argcounts[func.api], - len(args) + len(kwargs)]) - finally: - del tb + expected = argcounts[func.api] + actual = len(args) + len(kwargs) + if expected != actual: + tb = sys.exc_info()[2] + try: + sourcefile = traceback.extract_tb(tb)[-1][0] + if sourcefile == inspect.getsourcefile(XendAPI): + return xen_api_error( + ['MESSAGE_PARAMETER_COUNT_MISMATCH', + func.api, expected, actual]) + finally: + del tb raise return f @@ -627,7 +630,12 @@ class XendAPI(object): 'resident_VMs', 'host_CPUs', 'metrics', - 'supported_bootloaders'] + 'capabilities', + 'supported_bootloaders', + 'API_version_major', + 'API_version_minor', + 'API_version_vendor', + 'API_version_vendor_implementation'] host_attr_rw = ['name_label', 'name_description', @@ -671,6 +679,14 @@ class XendAPI(object): del node.other_config[key] node.save() return xen_api_success_void() + def host_get_API_version_major(self, _, ref): + return xen_api_success(XEN_API_VERSION_MAJOR) + def host_get_API_version_minor(self, _, ref): + return xen_api_success(XEN_API_VERSION_MINOR) + def host_get_API_version_vendor(self, _, ref): + return xen_api_success(XEN_API_VERSION_VENDOR) + def host_get_API_version_vendor_implementation(self, _, ref): + return xen_api_success(XEN_API_VERSION_VENDOR_IMPLEMENTATION) def host_get_software_version(self, session, host_ref): return xen_api_success(XendNode.instance().xen_version()) def host_get_resident_VMs(self, session, host_ref): @@ -679,6 +695,8 @@ class XendAPI(object): return xen_api_success(XendNode.instance().get_host_cpu_refs()) def host_get_metrics(self, _, ref): return xen_api_success(XendNode.instance().host_metrics_uuid) + def host_get_capabilities(self, session, host_ref): + return xen_api_success(XendNode.instance().get_capabilities()) def host_get_supported_bootloaders(self, session, host_ref): return xen_api_success(['pygrub']) @@ -707,10 +725,17 @@ class XendAPI(object): record = {'uuid': node.uuid, 'name_label': node.name, 'name_description': '', + 'API_version_major': XEN_API_VERSION_MAJOR, + 'API_version_minor': XEN_API_VERSION_MINOR, + 'API_version_vendor': XEN_API_VERSION_VENDOR, + 'API_version_vendor_implementation': + XEN_API_VERSION_VENDOR_IMPLEMENTATION, 'software_version': node.xen_version(), + 'other_config': node.other_config, 'resident_VMs': dom.get_domain_refs(), 'host_CPUs': node.get_host_cpu_refs(), 'metrics': node.host_metrics_uuid, + 'capabilities': node.get_capabilities(), 'supported_bootloaders': 'pygrub'} return xen_api_success(record) @@ -728,27 +753,44 @@ class XendAPI(object): host_cpu_attr_ro = ['host', 'number', + 'vendor', + 'speed', + 'modelname', + 'stepping', + 'flags', 'utilisation'] # attributes - def host_cpu_get_host(self, session, host_cpu_ref): + def _host_cpu_get(self, ref, field): + return xen_api_success( + XendNode.instance().get_host_cpu_field(ref, field)) + + def host_cpu_get_host(self, _, ref): return xen_api_success(XendNode.instance().uuid) - def host_cpu_get_utilisation(self, session, host_cpu_ref): - util = XendNode.instance().get_host_cpu_load(host_cpu_ref) - return xen_api_success(util) - def host_cpu_get_number(self, session, host_cpu_ref): - num = XendNode.instance().get_host_cpu_number(host_cpu_ref) - return xen_api_success(num) + def host_cpu_get_number(self, _, ref): + return self._host_cpu_get(ref, 'number') + def host_cpu_get_vendor(self, _, ref): + return self._host_cpu_get(ref, 'vendor') + def host_cpu_get_speed(self, _, ref): + return self._host_cpu_get(ref, 'speed') + def host_cpu_get_modelname(self, _, ref): + return self._host_cpu_get(ref, 'modelname') + def host_cpu_get_stepping(self, _, ref): + return self._host_cpu_get(ref, 'stepping') + def host_cpu_get_flags(self, _, ref): + return self._host_cpu_get(ref, 'flags') + def host_cpu_get_utilisation(self, _, ref): + return xen_api_success(XendNode.instance().get_host_cpu_load(ref)) # object methods - def host_cpu_destroy(self, session, host_cpu_ref): - return xen_api_error(XEND_ERROR_UNSUPPORTED) - def host_cpu_get_record(self, session, host_cpu_ref): + def host_cpu_get_record(self, _, ref): node = XendNode.instance() - record = {'uuid': host_cpu_ref, - 'host': node.uuid, - 'number': node.get_host_cpu_number(host_cpu_ref), - 'utilisation': node.get_host_cpu_load(host_cpu_ref)} + record = dict([(f, node.get_host_cpu_field(ref, f)) + for f in self.host_cpu_attr_ro + if f not in ['uuid', 'host', 'utilisation']]) + record['uuid'] = ref + record['host'] = node.uuid + record['utilisation'] = node.get_host_cpu_load(ref) return xen_api_success(record) # class methods @@ -760,25 +802,23 @@ class XendAPI(object): # ---------------------------------------------------------------- host_metrics_attr_ro = ['memory_total', - 'memory_free', - 'host'] + 'memory_free'] host_metrics_attr_rw = [] host_metrics_methods = [] + def host_metrics_get_all(self, _): + return xen_api_success([XendNode.instance().host_metrics_uuid]) + def _host_metrics_get(self, ref, f): return xen_api_success(getattr(node, f)()) def host_metrics_get_record(self, _, ref): return xen_api_success({ 'uuid' : ref, - 'host' : XendNode.instance().uuid, 'memory_total' : self._host_metrics_get_memory_total(), 'memory_free' : self._host_metrics_get_memory_free(), }) - def host_metrics_get_host(self, _, ref): - return xen_api_success(XendNode.instance().uuid) - def host_metrics_get_memory_total(self, _, ref): return xen_api_success(self._host_metrics_get_memory_total()) @@ -799,18 +839,13 @@ class XendAPI(object): network_attr_ro = ['VIFs', 'PIFs'] network_attr_rw = ['name_label', - 'name_description', - 'default_gateway', - 'default_netmask'] + 'name_description'] network_funcs = [('create', 'network')] - def network_create(self, _, name_label, name_description, - default_gateway, default_netmask): + def network_create(self, _, name_label, name_description): return xen_api_success( - XendNode.instance().network_create(name_label, name_description, - default_gateway, - default_netmask)) + XendNode.instance().network_create(name_label, name_description)) def network_destroy(self, _, ref): return xen_api_success(XendNode.instance().network_destroy(ref)) @@ -831,12 +866,6 @@ class XendAPI(object): def network_get_name_description(self, _, ref): return xen_api_success(self._get_network(ref).name_description) - def network_get_default_gateway(self, _, ref): - return xen_api_success(self._get_network(ref).default_gateway) - - def network_get_default_netmask(self, _, ref): - return xen_api_success(self._get_network(ref).default_netmask) - def network_get_VIFs(self, _, ref): return xen_api_success(self._get_network(ref).get_VIF_UUIDs()) @@ -849,13 +878,6 @@ class XendAPI(object): def network_set_name_description(self, _, ref, val): return xen_api_success(self._get_network(ref).set_name_description(val)) - def network_set_default_gateway(self, _, ref, val): - return xen_api_success(self._get_network(ref).set_default_gateway(val)) - - def network_set_default_netmask(self, _, ref, val): - return xen_api_success(self._get_network(ref).set_default_netmask(val)) - - # Xen API: Class PIF # ---------------------------------------------------------------- @@ -941,21 +963,20 @@ class XendAPI(object): # Xen API: Class PIF_metrics # ---------------------------------------------------------------- - PIF_metrics_attr_ro = ['PIF', - 'io_read_kbs', + PIF_metrics_attr_ro = ['io_read_kbs', 'io_write_kbs'] PIF_metrics_attr_rw = [] PIF_methods = [] + def PIF_metrics_get_all(self, _): + return xen_api_success(XendNode.instance().pif_metrics.keys()) + 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_PIF(self, _, ref): - return xen_api_success(self._PIF_metrics_get(ref).pif.uuid) - def PIF_metrics_get_io_read_kbs(self, _, ref): return xen_api_success(self._PIF_metrics_get(ref).get_io_read_kbs()) @@ -979,6 +1000,7 @@ class XendAPI(object): 'VTPMs', 'PCI_bus', 'tools_version', + 'domid', 'is_control_domain', ] @@ -1219,6 +1241,10 @@ class XendAPI(object): def VM_get_other_config(self, session, vm_ref): return self.VM_get('other_config', session, vm_ref) + def VM_get_domid(self, _, ref): + domid = XendDomain.instance().get_vm_by_uuid(ref).getDomid() + return xen_api_success(domid is None and -1 or domid) + def VM_get_is_control_domain(self, session, vm_ref): xd = XendDomain.instance() return xen_api_success( @@ -1375,7 +1401,9 @@ class XendAPI(object): xeninfo = xendom.get_vm_by_uuid(vm_ref) if not xeninfo: return xen_api_error(['HANDLE_INVALID', 'VM', vm_ref]) - + + domid = xeninfo.getDomid() + record = { 'uuid': xeninfo.get_uuid(), 'power_state': xeninfo.get_power_state(), @@ -1418,6 +1446,7 @@ class XendAPI(object): 'PCI_bus': xeninfo.get_pci_bus(), 'tools_version': xeninfo.get_tools_version(), 'other_config': xeninfo.info.get('other_config', {}), + 'domid': domid is None and -1 or domid, 'is_control_domain': xeninfo == xendom.privilegedDomain(), } return xen_api_success(record) @@ -2117,7 +2146,15 @@ class XendAPI(object): def debug_get_record(self, session, debug_ref): return xen_api_success({'uuid': debug_ref}) - + + def list_all_methods(self, _): + def _funcs(): + return [getattr(XendAPI, x) for x in XendAPI.__dict__] + + return xen_api_success([x.api for x in _funcs() + if hasattr(x, 'api')]) + list_all_methods.api = '_UNSUPPORTED_list_all_methods' + class XendAPIAsyncProxy: """ A redirector for Async.Class.function calls to XendAPI diff --git a/tools/python/xen/xend/XendAPIVersion.py b/tools/python/xen/xend/XendAPIVersion.py new file mode 100644 index 0000000000..82cc51af30 --- /dev/null +++ b/tools/python/xen/xend/XendAPIVersion.py @@ -0,0 +1,22 @@ +#============================================================================ +# 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. +#============================================================================ + + +XEN_API_VERSION_MAJOR = 0 +XEN_API_VERSION_MINOR = 5 +XEN_API_VERSION_VENDOR = 'xenbits' +XEN_API_VERSION_VENDOR_IMPLEMENTATION = {} diff --git a/tools/python/xen/xend/XendBootloader.py b/tools/python/xen/xend/XendBootloader.py index 4220cde6eb..9c5578f36b 100644 --- a/tools/python/xen/xend/XendBootloader.py +++ b/tools/python/xen/xend/XendBootloader.py @@ -21,7 +21,8 @@ from xen.util import mkdir from XendLogging import log from XendError import VmError -import pty, ptsname, termios, fcntl +import pty, termios, fcntl +from xen.lowlevel import ptsname def bootloader(blexec, disk, dom, quiet = False, blargs = '', kernel = '', ramdisk = '', kernel_args = ''): diff --git a/tools/python/xen/xend/XendCheckpoint.py b/tools/python/xen/xend/XendCheckpoint.py index 63368bd654..e94d9fbde7 100644 --- a/tools/python/xen/xend/XendCheckpoint.py +++ b/tools/python/xen/xend/XendCheckpoint.py @@ -54,7 +54,7 @@ def read_exact(fd, size, errmsg): return buf -def save(fd, dominfo, network, live, dst): +def save(fd, dominfo, network, live, dst, checkpoint=False): write_exact(fd, SIGNATURE, "could not write guest state file: signature") config = sxp.to_string(dominfo.sxpr()) @@ -121,9 +121,11 @@ def save(fd, dominfo, network, live, dst): os.close(qemu_fd) os.remove("/tmp/xen.qemu-dm.%d" % dominfo.getDomid()) - dominfo.destroyDomain() - dominfo.testDeviceComplete() - + if checkpoint: + dominfo.resumeDomain() + else: + dominfo.destroyDomain() + dominfo.testDeviceComplete() try: dominfo.setName(domain_name) except VmError: @@ -137,23 +139,6 @@ def save(fd, dominfo, network, live, dst): log.exception("Save failed on domain %s (%s).", domain_name, dominfo.getDomid()) - dominfo._releaseDevices() - dominfo.testDeviceComplete() - dominfo.testvifsComplete() - log.debug("XendCheckpoint.save: devices released") - - dominfo._resetChannels() - - dominfo._removeDom('control/shutdown') - dominfo._removeDom('device-misc/vif/nextDeviceID') - - dominfo._createChannels() - dominfo._introduceDomain() - dominfo._storeDomDetails() - - dominfo._createDevices() - log.debug("XendCheckpoint.save: devices created") - dominfo.resumeDomain() log.debug("XendCheckpoint.save: resumeDomain") @@ -245,11 +230,7 @@ def restore(xd, fd, dominfo = None, paused = False): if not is_hvm and handler.console_mfn is None: raise XendError('Could not read console MFN') - dominfo.waitForDevices() # Wait for backends to set up - if not paused: - dominfo.unpause() - - # get qemu state and create a tmp file for dm restore + # get qemu state and create a tmp file for dm restore if is_hvm: qemu_signature = read_exact(fd, len(QEMU_SIGNATURE), "invalid device model signature read") @@ -272,6 +253,10 @@ def restore(xd, fd, dominfo = None, paused = False): dominfo.completeRestore(handler.store_mfn, handler.console_mfn) + dominfo.waitForDevices() # Wait for backends to set up + if not paused: + dominfo.unpause() + return dominfo except: dominfo.destroy() diff --git a/tools/python/xen/xend/XendConfig.py b/tools/python/xen/xend/XendConfig.py index fa19165e77..ec8a66fb7e 100644 --- a/tools/python/xen/xend/XendConfig.py +++ b/tools/python/xen/xend/XendConfig.py @@ -729,6 +729,10 @@ class XendConfig(dict): image['hvm'] = image_hvm image['hvm']['devices'] = image_hvm_devices + notes = sxp.children(image_sxp, 'notes') + if notes: + image['notes'] = self.notes_from_sxp(notes[0]) + self['image'] = image for apikey, imgkey in XENAPI_HVM_CFG.items(): @@ -1363,6 +1367,9 @@ class XendConfig(dict): image.append([arg, val]) + if 'notes' in self['image']: + image.append(self.notes_sxp(self['image']['notes'])) + return image def update_with_image_sxp(self, image_sxp, bootloader = False): @@ -1420,6 +1427,10 @@ class XendConfig(dict): image['hvm'] = image_hvm image['hvm']['devices'] = image_hvm_devices + notes = sxp.children(image_sxp, 'notes') + if notes: + image['notes'] = self.notes_from_sxp(notes[0]) + self['image'] = image for apikey, imgkey in XENAPI_HVM_CFG.items(): @@ -1432,7 +1443,28 @@ class XendConfig(dict): self[apikey] = val self._hvm_boot_params_from_sxp(image_sxp) + def set_notes(self, notes): + 'Add parsed elfnotes to image' + self['image']['notes'] = notes + def get_notes(self): + try: + return self['image']['notes'] or {} + except KeyError: + return {} + + def notes_from_sxp(self, nsxp): + notes = {} + for note in sxp.children(nsxp): + notes[note[0]] = note[1] + return notes + + def notes_sxp(self, notes): + nsxp = ['notes'] + for k, v in notes.iteritems(): + nsxp.append([k, str(v)]) + return nsxp + def _hvm_boot_params_from_sxp(self, image_sxp): boot = sxp.child_value(image_sxp, 'boot', None) if boot is not None: diff --git a/tools/python/xen/xend/XendConstants.py b/tools/python/xen/xend/XendConstants.py index e42216d06b..e6bc787340 100644 --- a/tools/python/xen/xend/XendConstants.py +++ b/tools/python/xen/xend/XendConstants.py @@ -82,6 +82,16 @@ MINIMUM_RESTART_TIME = 20 RESTART_IN_PROGRESS = 'xend/restart_in_progress' LAST_SHUTDOWN_REASON = 'xend/last_shutdown_reason' +TRIGGER_NMI = 0 +TRIGGER_RESET = 1 +TRIGGER_INIT = 2 + +TRIGGER_TYPE = { + "nmi" : TRIGGER_NMI, + "reset" : TRIGGER_RESET, + "init" : TRIGGER_INIT +} + # # Device migration stages (eg. XendDomainInfo, XendCheckpoint, server.tpmif) # diff --git a/tools/python/xen/xend/XendDomain.py b/tools/python/xen/xend/XendDomain.py index 0c8cddde48..7e5f618870 100644 --- a/tools/python/xen/xend/XendDomain.py +++ b/tools/python/xen/xend/XendDomain.py @@ -32,7 +32,7 @@ import threading import xen.lowlevel.xc -from xen.xend import XendOptions, XendCheckpoint, XendDomainInfo, XendNode +from xen.xend import XendOptions, XendCheckpoint, XendDomainInfo from xen.xend.PrettyPrint import prettyprint from xen.xend.XendConfig import XendConfig from xen.xend.XendError import XendError, XendInvalidDomain, VmError @@ -43,6 +43,7 @@ from xen.xend.XendConstants import XS_VMROOT from xen.xend.XendConstants import DOM_STATE_HALTED, DOM_STATE_PAUSED from xen.xend.XendConstants import DOM_STATE_RUNNING, DOM_STATE_SUSPENDED from xen.xend.XendConstants import DOM_STATE_SHUTDOWN, DOM_STATE_UNKNOWN +from xen.xend.XendConstants import TRIGGER_TYPE from xen.xend.XendDevices import XendDevices from xen.xend.xenstore.xstransact import xstransact @@ -487,14 +488,14 @@ class XendDomain: @type domid: int or string @return: Found domain. @rtype: XendDomainInfo - @raise XendError: If domain is not found. + @raise XendInvalidDomain: If domain is not found. """ self.domains_lock.acquire() try: self._refresh(refresh_shutdown = False) dom = self.domain_lookup_nr(domid) if not dom: - raise XendError("No domain named '%s'." % str(domid)) + raise XendInvalidDomain("No domain named '%s'." % str(domid)) return dom finally: self.domains_lock.release() @@ -874,10 +875,6 @@ class XendDomain: self._refresh() dominfo = XendDomainInfo.create(config) - if XendNode.instance().xenschedinfo() == 'credit': - self.domain_sched_credit_set(dominfo.getDomid(), - dominfo.getWeight(), - dominfo.getCap()) return dominfo finally: self.domains_lock.release() @@ -894,10 +891,6 @@ class XendDomain: self._refresh() dominfo = XendDomainInfo.create_from_dict(config_dict) - if XendNode.instance().xenschedinfo() == 'credit': - self.domain_sched_credit_set(dominfo.getDomid(), - dominfo.getWeight(), - dominfo.getCap()) return dominfo finally: self.domains_lock.release() @@ -951,10 +944,6 @@ class XendDomain: POWER_STATE_NAMES[dominfo.state]) dominfo.start(is_managed = True) - if XendNode.instance().xenschedinfo() == 'credit': - self.domain_sched_credit_set(dominfo.getDomid(), - dominfo.getWeight(), - dominfo.getCap()) finally: self.domains_lock.release() dominfo.waitForDevices() @@ -1183,7 +1172,7 @@ class XendDomain: XendCheckpoint.save(sock.fileno(), dominfo, True, live, dst) sock.close() - def domain_save(self, domid, dst): + def domain_save(self, domid, dst, checkpoint): """Start saving a domain to file. @param domid: Domain ID or Name @@ -1207,8 +1196,8 @@ class XendDomain: oflags |= os.O_LARGEFILE fd = os.open(dst, oflags) try: - # For now we don't support 'live checkpoint' - XendCheckpoint.save(fd, dominfo, False, False, dst) + XendCheckpoint.save(fd, dominfo, False, False, dst, + checkpoint=checkpoint) finally: os.close(fd) except OSError, ex: @@ -1433,6 +1422,33 @@ class XendDomain: except Exception, ex: raise XendError(str(ex)) + def domain_send_trigger(self, domid, trigger_name, vcpu = 0): + """Send trigger to a domain. + + @param domid: Domain ID or Name + @type domid: int or string. + @param trigger_name: trigger type name + @type trigger_name: string + @param vcpu: VCPU to send trigger (default is 0) + @type vcpu: int + @raise XendError: failed to send trigger + @raise XendInvalidDomain: Domain is not valid + @rtype: 0 + """ + dominfo = self.domain_lookup_nr(domid) + if not dominfo: + raise XendInvalidDomain(str(domid)) + if trigger_name.lower() in TRIGGER_TYPE: + trigger = TRIGGER_TYPE[trigger_name.lower()] + else: + raise XendError("Invalid trigger: %s", trigger_name) + try: + return xc.domain_send_trigger(dominfo.getDomid(), + trigger, + vcpu) + except Exception, ex: + raise XendError(str(ex)) + def instance(): """Singleton constructor. Use this instead of the class constructor. diff --git a/tools/python/xen/xend/XendDomainInfo.py b/tools/python/xen/xend/XendDomainInfo.py index 615efbd56a..2689753266 100644 --- a/tools/python/xen/xend/XendDomainInfo.py +++ b/tools/python/xen/xend/XendDomainInfo.py @@ -302,6 +302,8 @@ class XendDomainInfo: @type store_mfn: int @ivar console_mfn: xenconsoled mfn @type console_mfn: int + @ivar notes: OS image notes + @type notes: dictionary @ivar vmWatch: reference to a watch on the xenstored vmpath @type vmWatch: xen.xend.xenstore.xswatch @ivar shutdownWatch: reference to watch on the xenstored domain shutdown @@ -396,11 +398,18 @@ class XendDomainInfo: XendTask.log_progress(81, 90, self._registerWatches) XendTask.log_progress(91, 100, self.refreshShutdown) + xendomains = XendDomain.instance() + xennode = XendNode.instance() + # save running configuration if XendDomains believe domain is # persistent if is_managed: - xendomains = XendDomain.instance() xendomains.managed_config_save(self) + + if xennode.xenschedinfo() == 'credit': + xendomains.domain_sched_credit_set(self.getDomid(), + self.getWeight(), + self.getCap()) except: log.exception('VM start failed') self.destroy() @@ -771,18 +780,35 @@ class XendDomainInfo: 'vm': self.vmpath, 'name': self.info['name_label'], 'console/limit': str(xoptions.get_console_limit() * 1024), - 'memory/target': str(self.info['memory_static_min'] * 1024) + 'memory/target': str(self.info['memory_static_min'] * 1024), + 'control/platform-feature-multiprocessor-suspend': str(1) } def f(n, v): if v is not None: - to_store[n] = str(v) + if type(v) == bool: + to_store[n] = v and "1" or "0" + else: + to_store[n] = str(v) f('console/port', self.console_port) f('console/ring-ref', self.console_mfn) f('store/port', self.store_port) f('store/ring-ref', self.store_mfn) + # elfnotes + for n, v in self.info.get_notes().iteritems(): + n = n.lower().replace('_', '-') + if n == 'features': + for v in v.split('|'): + v = v.replace('_', '-') + if v.startswith('!'): + f('image/%s/%s' % (n, v[1:]), False) + else: + f('image/%s/%s' % (n, v), True) + else: + f('image/%s' % n, v) + to_store.update(self._vcpuDomDetails()) log.debug("Storing domain details: %s", scrub_password(to_store)) @@ -913,6 +939,9 @@ class XendDomainInfo: return self.info['vcpus_number'] def setVCpuCount(self, vcpus): + if vcpus <= 0: + raise XendError('Invalid VCPUs') + self.info['vcpu_avail'] = (1 << vcpus) - 1 if self.domid >= 0: self.storeVm('vcpu_avail', self.info['vcpu_avail']) @@ -1462,6 +1491,8 @@ class XendDomainInfo: self.store_mfn = channel_details['store_mfn'] if 'console_mfn' in channel_details: self.console_mfn = channel_details['console_mfn'] + if 'notes' in channel_details: + self.info.set_notes(channel_details['notes']) self._introduceDomain() @@ -1472,7 +1503,7 @@ class XendDomainInfo: self.info['start_time'] = time.time() self._stateSet(DOM_STATE_RUNNING) - except RuntimeError, exn: + except (RuntimeError, VmError), exn: log.exception("XendDomainInfo.initDomain: exception occurred") self.image.cleanupBootloading() raise VmError(str(exn)) @@ -1632,10 +1663,31 @@ class XendDomainInfo: def resumeDomain(self): log.debug("XendDomainInfo.resumeDomain(%s)", str(self.domid)) + if self.domid is None: + return try: - if self.domid is not None: - xc.domain_resume(self.domid) - ResumeDomain(self.domid) + # could also fetch a parsed note from xenstore + fast = self.info.get_notes().get('SUSPEND_CANCEL') and 1 or 0 + if not fast: + self._releaseDevices() + self.testDeviceComplete() + self.testvifsComplete() + log.debug("XendDomainInfo.resumeDomain: devices released") + + self._resetChannels() + + self._removeDom('control/shutdown') + self._removeDom('device-misc/vif/nextDeviceID') + + self._createChannels() + self._introduceDomain() + self._storeDomDetails() + + self._createDevices() + log.debug("XendDomainInfo.resumeDomain: devices created") + + xc.domain_resume(self.domid, fast) + ResumeDomain(self.domid) except: log.exception("XendDomainInfo.resume: xc.domain_resume failed on domain %s." % (str(self.domid))) @@ -2038,26 +2090,26 @@ class XendDomainInfo: return self.info.get('tools_version', {}) def get_on_shutdown(self): - after_shutdown = self.info.get('action_after_shutdown') + after_shutdown = self.info.get('actions_after_shutdown') if not after_shutdown or after_shutdown not in XEN_API_ON_NORMAL_EXIT: return XEN_API_ON_NORMAL_EXIT[-1] return after_shutdown def get_on_reboot(self): - after_reboot = self.info.get('action_after_reboot') + after_reboot = self.info.get('actions_after_reboot') if not after_reboot or after_reboot not in XEN_API_ON_NORMAL_EXIT: return XEN_API_ON_NORMAL_EXIT[-1] return after_reboot def get_on_suspend(self): # TODO: not supported - after_suspend = self.info.get('action_after_suspend') + after_suspend = self.info.get('actions_after_suspend') if not after_suspend or after_suspend not in XEN_API_ON_NORMAL_EXIT: return XEN_API_ON_NORMAL_EXIT[-1] return after_suspend def get_on_crash(self): - after_crash = self.info.get('action_after_crash') + after_crash = self.info.get('actions_after_crash') if not after_crash or after_crash not in XEN_API_ON_CRASH_BEHAVIOUR: return XEN_API_ON_CRASH_BEHAVIOUR[0] return after_crash diff --git a/tools/python/xen/xend/XendNetwork.py b/tools/python/xen/xend/XendNetwork.py index 5e606957f1..b589545ca5 100644 --- a/tools/python/xen/xend/XendNetwork.py +++ b/tools/python/xen/xend/XendNetwork.py @@ -27,43 +27,11 @@ from XendLogging import log IP_ROUTE_RE = r'^default via ([\d\.]+) dev (\w+)' -def linux_get_default_network(): - """Returns the network details of the host.""" - - ip_cmd = '/sbin/ip route' - rc, output = commands.getstatusoutput(ip_cmd) - default_route = None - default_dev = None - default_netmask = None - if rc == 0: - # find default route/device - for line in output.split('\n'): - is_default = re.search(IP_ROUTE_RE, line) - if is_default: - default_route = is_default.group(1) - default_dev = is_default.group(2) - - # find network address and network mask - if default_dev: - dev_re = r'^([\d\.]+)/(\d+) dev %s' % default_dev - for line in output.split('\n'): - is_dev = re.search(dev_re, line) - if is_dev: - # convert integer netmask to string representation - netmask = 0xffffffff ^ (2**(32-int(is_dev.group(2))) - 1) - packed = struct.pack('!I', netmask) - default_netmask = socket.inet_ntoa(packed) - - return (default_route, default_netmask) - - class XendNetwork: - def __init__(self, uuid, name, description, gateway, netmask): + def __init__(self, uuid, name, description): self.uuid = uuid self.name_label = name self.name_description = description - self.default_gateway = gateway - self.default_netmask = netmask def set_name_label(self, new_name): self.name_label = new_name @@ -73,16 +41,6 @@ class XendNetwork: self.name_description = new_desc XendNode.instance().save_networks() - def set_default_gateway(self, new_gateway): - if re.search('^\d+\.\d+\.\d+\.\d+$', new_gateway): - self.default_gateway = new_gateway - XendNode.instance().save_networks() - - def set_default_netmask(self, new_netmask): - if re.search('^\d+\.\d+\.\d+\.\d+$', new_netmask): - self.default_netmask = new_netmask - XendNode.instance().save_networks() - def get_VIF_UUIDs(self): result = [] vms = XendDomain.instance().get_all_vms() @@ -103,8 +61,6 @@ class XendNetwork: 'uuid': self.uuid, 'name_label': self.name_label, 'name_description': self.name_description, - 'default_gateway': self.default_gateway, - 'default_netmask': self.default_netmask, } if transient: result['VIFs'] = self.get_VIF_UUIDs() diff --git a/tools/python/xen/xend/XendNode.py b/tools/python/xen/xend/XendNode.py index 294959752b..9d2a70dd9e 100644 --- a/tools/python/xen/xend/XendNode.py +++ b/tools/python/xen/xend/XendNode.py @@ -22,7 +22,7 @@ import xen.lowlevel.xc from xen.util import Brctl -from xen.xend import uuid +from xen.xend import uuid, arch from xen.xend.XendError import * from xen.xend.XendOptions import instance as xendoptions from xen.xend.XendQCoWStorageRepo import XendQCoWStorageRepo @@ -81,7 +81,7 @@ class XendNode: for cpu_uuid, cpu in saved_cpus.items(): self.cpus[cpu_uuid] = cpu - # verify we have enough cpus here + cpuinfo = parse_proc_cpuinfo() physinfo = self.physinfo_dict() cpu_count = physinfo['nr_cpus'] cpu_features = physinfo['hw_caps'] @@ -91,12 +91,44 @@ class XendNode: if cpu_count != len(self.cpus): self.cpus = {} for i in range(cpu_count): - cpu_uuid = uuid.createString() - cpu_info = {'uuid': cpu_uuid, - 'host': self.uuid, - 'number': i, - 'features': cpu_features} - self.cpus[cpu_uuid] = cpu_info + u = uuid.createString() + self.cpus[u] = {'uuid': u, 'number': i } + + for u in self.cpus.keys(): + log.error(self.cpus[u]) + number = self.cpus[u]['number'] + # We can run off the end of the cpuinfo list if domain0 does not + # have #vcpus == #pcpus. In that case we just replicate one that's + # in the hash table. + if not cpuinfo.has_key(number): + number = cpuinfo.keys()[0] + log.error(number) + log.error(cpuinfo) + if arch.type == "x86": + self.cpus[u].update( + { 'host' : self.uuid, + 'features' : cpu_features, + 'speed' : int(float(cpuinfo[number]['cpu MHz'])), + 'vendor' : cpuinfo[number]['vendor_id'], + 'modelname': cpuinfo[number]['model name'], + 'stepping' : cpuinfo[number]['stepping'], + 'flags' : cpuinfo[number]['flags'], + }) + elif arch.type == "ia64": + self.cpus[u].update( + { 'host' : self.uuid, + 'features' : cpu_features, + 'speed' : int(float(cpuinfo[number]['cpu MHz'])), + 'vendor' : cpuinfo[number]['vendor'], + 'modelname': cpuinfo[number]['family'], + 'stepping' : cpuinfo[number]['model'], + 'flags' : cpuinfo[number]['features'], + }) + else: + self.cpus[u].update( + { 'host' : self.uuid, + 'features' : cpu_features, + }) self.pifs = {} self.pif_metrics = {} @@ -109,12 +141,9 @@ class XendNode: for net_uuid, network in saved_networks.items(): self.network_create(network.get('name_label'), network.get('name_description', ''), - network.get('default_gateway', ''), - network.get('default_netmask', ''), False, net_uuid) else: - gateway, netmask = linux_get_default_network() - self.network_create('net0', '', gateway, netmask, False) + self.network_create('net0', '', False) # initialise PIFs saved_pifs = self.state_store.load_state('pif') @@ -168,15 +197,12 @@ class XendNode: - def network_create(self, name_label, name_description, - default_gateway, default_netmask, persist = True, + def network_create(self, name_label, name_description, 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, - default_gateway, - default_netmask) + name_description) if persist: self.save_networks() return net_uuid @@ -353,6 +379,9 @@ class XendNode: def get_uuid(self): return self.uuid + def get_capabilities(self): + return self.xc.xeninfo()['xen_caps'].split(" ") + # # Host CPU Functions # @@ -371,18 +400,12 @@ class XendNode: else: raise XendError('Invalid CPU Reference') - def get_host_cpu_features(self, host_cpu_ref): + def get_host_cpu_field(self, ref, field): try: - return self.cpus[host_cpu_ref]['features'] + return self.cpus[ref][field] except KeyError: raise XendError('Invalid CPU Reference') - def get_host_cpu_number(self, host_cpu_ref): - try: - return self.cpus[host_cpu_ref]['number'] - except KeyError: - raise XendError('Invalid CPU Reference') - def get_host_cpu_load(self, host_cpu_ref): host_cpu = self.cpus.get(host_cpu_ref) if not host_cpu: @@ -545,6 +568,31 @@ class XendNode: pif.refresh(Brctl.get_state()) +def parse_proc_cpuinfo(): + cpuinfo = {} + f = file('/proc/cpuinfo', 'r') + try: + p = -1 + d = {} + for line in f: + keyvalue = line.split(':') + if len(keyvalue) != 2: + continue + key = keyvalue[0].strip() + val = keyvalue[1].strip() + if key == 'processor': + if p != -1: + cpuinfo[p] = d + p = int(val) + d = {} + else: + d[key] = val + cpuinfo[p] = d + return cpuinfo + finally: + f.close() + + def instance(): global inst try: diff --git a/tools/python/xen/xend/XendQCoWStorageRepo.py b/tools/python/xen/xend/XendQCoWStorageRepo.py index 763d76da8b..ad4fa7fb88 100644 --- a/tools/python/xen/xend/XendQCoWStorageRepo.py +++ b/tools/python/xen/xend/XendQCoWStorageRepo.py @@ -326,7 +326,7 @@ class XendQCoWStorageRepo(XendStorageRepository): image = self.images[image_uuid] image_cfg = { 'sector_size': sector_size, - 'virtual_size': sector_count, + 'virtual_size': size_bytes, 'type': vdi_struct.get('type', 'system'), 'name_label': vdi_struct.get('name_label', ''), 'name_description': vdi_struct.get('name_description', ''), diff --git a/tools/python/xen/xend/image.py b/tools/python/xen/xend/image.py index d6aa9182de..ec3ce1fe30 100644 --- a/tools/python/xen/xend/image.py +++ b/tools/python/xen/xend/image.py @@ -572,8 +572,8 @@ class IA64_HVM_ImageHandler(HVMImageHandler): def getRequiredAvailableMemory(self, mem_kb): page_kb = 16 - # ROM size for guest firmware, ioreq page and xenstore page - extra_pages = 1024 + 3 + # ROM size for guest firmware, ioreq page, pio page and xenstore page + extra_pages = 1024 + 4 return mem_kb + extra_pages * page_kb def getRequiredInitialReservation(self): diff --git a/tools/python/xen/xend/server/SrvDomainDir.py b/tools/python/xen/xend/server/SrvDomainDir.py index 950b26316d..fdee1b75ca 100644 --- a/tools/python/xen/xend/server/SrvDomainDir.py +++ b/tools/python/xen/xend/server/SrvDomainDir.py @@ -42,8 +42,6 @@ class SrvDomainDir(SrvDir): def domain(self, x): dom = self.xd.domain_lookup(x) - if not dom: - raise XendError('No such domain ' + str(x)) return SrvDomain(dom) def get(self, x): diff --git a/tools/python/xen/xend/server/XMLRPCServer.py b/tools/python/xen/xend/server/XMLRPCServer.py index 09a66549e9..7c3a2a1a9d 100644 --- a/tools/python/xen/xend/server/XMLRPCServer.py +++ b/tools/python/xen/xend/server/XMLRPCServer.py @@ -43,8 +43,6 @@ def fixup_sxpr(sexpr): def lookup(domid): info = XendDomain.instance().domain_lookup(domid) - if not info: - raise XendInvalidDomain(str(domid)) return info def dispatch(domid, fn, args): diff --git a/tools/python/xen/xm/main.py b/tools/python/xen/xm/main.py index 7635b06c91..7075e95444 100644 --- a/tools/python/xen/xm/main.py +++ b/tools/python/xen/xm/main.py @@ -102,7 +102,7 @@ SUBCOMMAND_HELP = { 'reboot' : (' [-wa]', 'Reboot a domain.'), 'restore' : (' [-p]', 'Restore a domain from a saved state.'), - 'save' : (' ', + 'save' : ('[-c] ', 'Save a domain state to restore later.'), 'shutdown' : (' [-waRH]', 'Shutdown a domain.'), 'top' : ('', 'Monitor a host and the domains in real time.'), @@ -133,6 +133,8 @@ SUBCOMMAND_HELP = { 'sched-credit': ('[-d [-w[=WEIGHT]|-c[=CAP]]]', 'Get/set credit scheduler parameters.'), 'sysrq' : (' ', 'Send a sysrq to a domain.'), + 'trigger' : (' []', + 'Send a trigger to a domain.'), 'vcpu-list' : ('[]', 'List the VCPUs for a domain or all domains.'), 'vcpu-pin' : (' ', @@ -153,7 +155,7 @@ SUBCOMMAND_HELP = { 'List virtual block devices for a domain.'), 'network-attach': (' [type=] [mac=] [bridge=] ' '[ip=] [script=