aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Config.mk6
-rw-r--r--docs/xen-api/xenapi-datamodel.tex151
-rw-r--r--extras/mini-os/arch/x86/mm.c4
-rw-r--r--extras/mini-os/gnttab.c2
-rw-r--r--extras/mini-os/hypervisor.c4
-rw-r--r--extras/mini-os/include/wait.h7
-rw-r--r--extras/mini-os/include/xenbus.h1
-rw-r--r--extras/mini-os/xenbus/xenbus.c3
-rw-r--r--linux-2.6-xen-sparse/arch/i386/kernel/vsyscall-note-xen.S2
-rw-r--r--linux-2.6-xen-sparse/arch/i386/mm/pgtable-xen.c14
-rw-r--r--linux-2.6-xen-sparse/arch/x86_64/mm/init-xen.c6
-rw-r--r--linux-2.6-xen-sparse/arch/x86_64/mm/pageattr-xen.c86
-rw-r--r--linux-2.6-xen-sparse/drivers/xen/netback/netback.c2
-rw-r--r--linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.c13
-rw-r--r--linux-2.6-xen-sparse/include/asm-i386/kexec.h3
-rw-r--r--linux-2.6-xen-sparse/mm/Kconfig157
-rw-r--r--patches/linux-2.6.18/allow-i386-crash-kernels-to-handle-x86_64-dumps-fix.patch30
-rw-r--r--patches/linux-2.6.18/allow-i386-crash-kernels-to-handle-x86_64-dumps.patch66
-rw-r--r--patches/linux-2.6.18/crash-kernel-32-on-64.patch11
-rw-r--r--patches/linux-2.6.18/series3
-rw-r--r--tools/Rules.mk5
-rw-r--r--tools/blktap/drivers/block-qcow.c1
-rw-r--r--tools/firmware/Makefile2
-rw-r--r--tools/firmware/hvmloader/32bitbios_support.c176
-rw-r--r--tools/firmware/hvmloader/acpi/build.c1
-rw-r--r--tools/firmware/hvmloader/hvmloader.c65
-rw-r--r--tools/firmware/hvmloader/smbios.c46
-rw-r--r--tools/firmware/hvmloader/util.c21
-rw-r--r--tools/firmware/hvmloader/util.h12
-rw-r--r--tools/firmware/rombios/rombios.c232
-rw-r--r--tools/ioemu/target-i386-dm/exec-dm.c16
-rw-r--r--tools/ioemu/target-i386-dm/helper2.c15
-rw-r--r--tools/ioemu/xenstore.c179
-rw-r--r--tools/libxc/Makefile2
-rw-r--r--tools/libxc/xc_core.c6
-rw-r--r--tools/libxc/xc_core_x86.c24
-rw-r--r--tools/libxc/xc_hvm_build.c7
-rw-r--r--tools/libxc/xc_hvm_restore.c31
-rw-r--r--tools/libxc/xc_hvm_save.c69
-rw-r--r--tools/libxc/xc_private.c14
-rw-r--r--tools/libxc/xenguest.h6
-rw-r--r--tools/libxc/xg_private.c4
-rw-r--r--tools/libxen/include/xen_vbd.h1
-rw-r--r--tools/libxen/include/xen_vdi.h44
-rw-r--r--tools/libxen/src/xen_vbd.c3
-rw-r--r--tools/libxen/src/xen_vdi.c90
-rw-r--r--tools/libxen/test/test_bindings.c3
-rw-r--r--tools/python/scripts/test_hvm_create.py3
-rw-r--r--tools/python/scripts/test_vm_create.py6
-rw-r--r--tools/python/scripts/xapi.py11
-rw-r--r--tools/python/scripts/xapi.vdicfg.py3
-rw-r--r--tools/python/xen/lowlevel/xc/xc.c68
-rw-r--r--tools/python/xen/util/blkif.py17
-rw-r--r--tools/python/xen/util/xmlrpclib2.py40
-rw-r--r--tools/python/xen/xend/XendAPI.py153
-rw-r--r--tools/python/xen/xend/XendCheckpoint.py4
-rw-r--r--tools/python/xen/xend/XendConfig.py107
-rw-r--r--tools/python/xen/xend/XendDomain.py2
-rw-r--r--tools/python/xen/xend/XendDomainInfo.py104
-rw-r--r--tools/python/xen/xend/XendLogging.py12
-rw-r--r--tools/python/xen/xend/XendNode.py3
-rw-r--r--tools/python/xen/xend/XendVDI.py27
-rw-r--r--tools/python/xen/xm/create.dtd118
-rw-r--r--tools/python/xen/xm/create.py83
-rw-r--r--tools/python/xen/xm/main.py366
-rw-r--r--tools/python/xen/xm/new.py13
-rw-r--r--tools/python/xen/xm/shutdown.py26
-rw-r--r--tools/python/xen/xm/xenapi_create.py636
-rw-r--r--tools/xcutils/Makefile6
-rw-r--r--tools/xcutils/xc_save.c129
-rw-r--r--tools/xm-test/tests/block-create/07_block_attach_baddevice_neg.py4
-rw-r--r--tools/xm-test/tests/block-create/08_block_attach_bad_filedevice_neg.py4
-rw-r--r--tools/xm-test/tests/network-attach/network_utils.py19
-rw-r--r--unmodified_drivers/linux-2.6/platform-pci/evtchn.c3
-rw-r--r--xen/arch/x86/Rules.mk18
-rw-r--r--xen/arch/x86/hvm/hpet.c24
-rw-r--r--xen/arch/x86/hvm/platform.c11
-rw-r--r--xen/arch/x86/hvm/svm/svm.c100
-rw-r--r--xen/arch/x86/hvm/svm/vmcb.c14
-rw-r--r--xen/arch/x86/hvm/svm/x86_32/exits.S40
-rw-r--r--xen/arch/x86/hvm/svm/x86_64/exits.S34
-rw-r--r--xen/arch/x86/hvm/vpic.c4
-rw-r--r--xen/arch/x86/mm.c6
-rw-r--r--xen/arch/x86/mm/shadow/common.c6
-rw-r--r--xen/arch/x86/x86_64/asm-offsets.c1
-rw-r--r--xen/arch/x86/x86_64/compat/entry.S4
-rw-r--r--xen/arch/x86/x86_64/compat/traps.c4
-rw-r--r--xen/arch/x86/x86_64/entry.S30
-rw-r--r--xen/arch/x86/x86_64/traps.c18
-rw-r--r--xen/common/compat/memory.c2
-rw-r--r--xen/common/memory.c15
-rw-r--r--xen/common/perfc.c17
-rw-r--r--xen/include/asm-ia64/mm.h2
-rw-r--r--xen/include/asm-powerpc/mm.h2
-rw-r--r--xen/include/asm-x86/domain.h3
-rw-r--r--xen/include/asm-x86/hvm/svm/svm.h2
-rw-r--r--xen/include/asm-x86/hvm/svm/vmcb.h2
-rw-r--r--xen/include/asm-x86/mm.h1
-rw-r--r--xen/include/asm-x86/processor.h6
-rw-r--r--xen/include/public/arch-x86/xen-x86_32.h2
-rw-r--r--xen/include/public/foreign/Makefile2
-rw-r--r--xen/include/public/memory.h5
-rw-r--r--xen/include/xen/trace.h10
103 files changed, 2980 insertions, 1018 deletions
diff --git a/Config.mk b/Config.mk
index 6f9f970fe6..0181cc3ad1 100644
--- a/Config.mk
+++ b/Config.mk
@@ -36,6 +36,12 @@ endif
cc-option = $(shell if test -z "`$(1) $(2) -S -o /dev/null -xc \
/dev/null 2>&1`"; then echo "$(2)"; else echo "$(3)"; fi ;)
+# cc-ver
+# Usage: ifeq ($(call cc-ver,$(CC),0x030400),y)
+cc-ver = $(shell if [ $$((`$(1) -dumpversion | awk -F. \
+ '{ printf "0x%02x%02x%02x", $$1, $$2, $$3}'`)) -ge $$(($(2))) ]; \
+ then echo y; else echo n; fi ;)
+
ifneq ($(debug),y)
CFLAGS += -DNDEBUG
else
diff --git a/docs/xen-api/xenapi-datamodel.tex b/docs/xen-api/xenapi-datamodel.tex
index 1b18834d03..4a11ef0d9b 100644
--- a/docs/xen-api/xenapi-datamodel.tex
+++ b/docs/xen-api/xenapi-datamodel.tex
@@ -9359,10 +9359,10 @@ $\mathit{RO}_\mathit{run}$ & {\tt VBDs} & (VBD ref) Set & list of vbds that ref
$\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 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 \\
$\mathit{RW}$ & {\tt sharable} & bool & true if this disk may be shared \\
$\mathit{RW}$ & {\tt read\_only} & bool & true if this disk may ONLY be mounted read-only \\
+$\mathit{RW}$ & {\tt other\_config} & (string $\rightarrow$ string) Map & additional configuration \\
\hline
\end{longtable}
\subsection{RPCs associated with class: VDI}
@@ -9812,13 +9812,13 @@ value of the field
\vspace{0.3cm}
\vspace{0.3cm}
\vspace{0.3cm}
-\subsubsection{RPC name:~get\_sector\_size}
+\subsubsection{RPC name:~get\_type}
{\bf Overview:}
-Get the sector\_size field of the given VDI.
+Get the type field of the given VDI.
\noindent {\bf Signature:}
-\begin{verbatim} int get_sector_size (session_id s, VDI ref self)\end{verbatim}
+\begin{verbatim} (vdi_type) get_type (session_id s, VDI ref self)\end{verbatim}
\noindent{\bf Arguments:}
@@ -9836,7 +9836,7 @@ Get the sector\_size field of the given VDI.
\noindent {\bf Return Type:}
{\tt
-int
+vdi\_type
}
@@ -9844,13 +9844,13 @@ value of the field
\vspace{0.3cm}
\vspace{0.3cm}
\vspace{0.3cm}
-\subsubsection{RPC name:~get\_type}
+\subsubsection{RPC name:~get\_sharable}
{\bf Overview:}
-Get the type field of the given VDI.
+Get the sharable field of the given VDI.
\noindent {\bf Signature:}
-\begin{verbatim} (vdi_type) get_type (session_id s, VDI ref self)\end{verbatim}
+\begin{verbatim} bool get_sharable (session_id s, VDI ref self)\end{verbatim}
\noindent{\bf Arguments:}
@@ -9868,7 +9868,7 @@ Get the type field of the given VDI.
\noindent {\bf Return Type:}
{\tt
-vdi\_type
+bool
}
@@ -9876,13 +9876,47 @@ value of the field
\vspace{0.3cm}
\vspace{0.3cm}
\vspace{0.3cm}
-\subsubsection{RPC name:~get\_sharable}
+\subsubsection{RPC name:~set\_sharable}
{\bf Overview:}
-Get the sharable field of the given VDI.
+Set the sharable field of the given VDI.
\noindent {\bf Signature:}
-\begin{verbatim} bool get_sharable (session_id s, VDI ref self)\end{verbatim}
+\begin{verbatim} void set_sharable (session_id s, VDI ref self, bool value)\end{verbatim}
+
+
+\noindent{\bf Arguments:}
+
+
+\vspace{0.3cm}
+\begin{tabular}{|c|c|p{7cm}|}
+ \hline
+{\bf type} & {\bf name} & {\bf description} \\ \hline
+{\tt VDI ref } & self & reference to the object \\ \hline
+
+{\tt bool } & 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\_read\_only}
+
+{\bf Overview:}
+Get the read\_only field of the given VDI.
+
+ \noindent {\bf Signature:}
+\begin{verbatim} bool get_read_only (session_id s, VDI ref self)\end{verbatim}
\noindent{\bf Arguments:}
@@ -9908,13 +9942,13 @@ value of the field
\vspace{0.3cm}
\vspace{0.3cm}
\vspace{0.3cm}
-\subsubsection{RPC name:~set\_sharable}
+\subsubsection{RPC name:~set\_read\_only}
{\bf Overview:}
-Set the sharable field of the given VDI.
+Set the read\_only field of the given VDI.
\noindent {\bf Signature:}
-\begin{verbatim} void set_sharable (session_id s, VDI ref self, bool value)\end{verbatim}
+\begin{verbatim} void set_read_only (session_id s, VDI ref self, bool value)\end{verbatim}
\noindent{\bf Arguments:}
@@ -9942,13 +9976,13 @@ void
\vspace{0.3cm}
\vspace{0.3cm}
\vspace{0.3cm}
-\subsubsection{RPC name:~get\_read\_only}
+\subsubsection{RPC name:~get\_other\_config}
{\bf Overview:}
-Get the read\_only field of the given VDI.
+Get the other\_config field of the given VDI.
\noindent {\bf Signature:}
-\begin{verbatim} bool get_read_only (session_id s, VDI ref self)\end{verbatim}
+\begin{verbatim} ((string -> string) Map) get_other_config (session_id s, VDI ref self)\end{verbatim}
\noindent{\bf Arguments:}
@@ -9966,7 +10000,7 @@ Get the read\_only field of the given VDI.
\noindent {\bf Return Type:}
{\tt
-bool
+(string $\rightarrow$ string) Map
}
@@ -9974,13 +10008,13 @@ value of the field
\vspace{0.3cm}
\vspace{0.3cm}
\vspace{0.3cm}
-\subsubsection{RPC name:~set\_read\_only}
+\subsubsection{RPC name:~set\_other\_config}
{\bf Overview:}
-Set the read\_only field of the given VDI.
+Set the other\_config field of the given VDI.
\noindent {\bf Signature:}
-\begin{verbatim} void set_read_only (session_id s, VDI ref self, bool value)\end{verbatim}
+\begin{verbatim} void set_other_config (session_id s, VDI ref self, (string -> string) Map value)\end{verbatim}
\noindent{\bf Arguments:}
@@ -9992,7 +10026,78 @@ Set the read\_only field of the given VDI.
{\bf type} & {\bf name} & {\bf description} \\ \hline
{\tt VDI ref } & self & reference to the object \\ \hline
-{\tt bool } & value & New value to set \\ \hline
+{\tt (string $\rightarrow$ string) Map } & value & New value to set \\ \hline
+
+\end{tabular}
+
+\vspace{0.3cm}
+
+ \noindent {\bf Return Type:}
+{\tt
+void
+}
+
+
+
+\vspace{0.3cm}
+\vspace{0.3cm}
+\vspace{0.3cm}
+\subsubsection{RPC name:~add\_to\_other\_config}
+
+{\bf Overview:}
+Add the given key-value pair to the other\_config field of the given VDI.
+
+ \noindent {\bf Signature:}
+\begin{verbatim} void add_to_other_config (session_id s, VDI ref self, string key, string value)\end{verbatim}
+
+
+\noindent{\bf Arguments:}
+
+
+\vspace{0.3cm}
+\begin{tabular}{|c|c|p{7cm}|}
+ \hline
+{\bf type} & {\bf name} & {\bf description} \\ \hline
+{\tt VDI ref } & self & reference to the object \\ \hline
+
+{\tt string } & key & Key to add \\ \hline
+
+{\tt string } & value & Value to add \\ \hline
+
+\end{tabular}
+
+\vspace{0.3cm}
+
+ \noindent {\bf Return Type:}
+{\tt
+void
+}
+
+
+
+\vspace{0.3cm}
+\vspace{0.3cm}
+\vspace{0.3cm}
+\subsubsection{RPC name:~remove\_from\_other\_config}
+
+{\bf Overview:}
+Remove the given key and its corresponding value from the other\_config
+field of the given VDI. If the key is not in that Map, then do nothing.
+
+ \noindent {\bf Signature:}
+\begin{verbatim} void remove_from_other_config (session_id s, VDI ref self, string key)\end{verbatim}
+
+
+\noindent{\bf Arguments:}
+
+
+\vspace{0.3cm}
+\begin{tabular}{|c|c|p{7cm}|}
+ \hline
+{\bf type} & {\bf name} & {\bf description} \\ \hline
+{\tt VDI ref } & self & reference to the object \\ \hline
+
+{\tt string } & key & Key to remove \\ \hline
\end{tabular}
diff --git a/extras/mini-os/arch/x86/mm.c b/extras/mini-os/arch/x86/mm.c
index d1508f8263..15ed4877a8 100644
--- a/extras/mini-os/arch/x86/mm.c
+++ b/extras/mini-os/arch/x86/mm.c
@@ -49,7 +49,7 @@
#endif
unsigned long *phys_to_machine_mapping;
-extern char *stack;
+extern char stack[];
extern void page_walk(unsigned long virt_addr);
void new_pt_frame(unsigned long *pt_pfn, unsigned long prev_l_mfn,
@@ -453,7 +453,7 @@ void arch_init_mm(unsigned long* start_pfn_p, unsigned long* max_pfn_p)
printk(" _text: %p\n", &_text);
printk(" _etext: %p\n", &_etext);
printk(" _edata: %p\n", &_edata);
- printk(" stack start: %p\n", &stack);
+ printk(" stack start: %p\n", stack);
printk(" _end: %p\n", &_end);
/* First page follows page table pages and 3 more pages (store page etc) */
diff --git a/extras/mini-os/gnttab.c b/extras/mini-os/gnttab.c
index 4d75897a98..b22f51ceae 100644
--- a/extras/mini-os/gnttab.c
+++ b/extras/mini-os/gnttab.c
@@ -135,7 +135,7 @@ gnttab_alloc_and_grant(void **map)
return gref;
}
-static const char *gnttabop_error_msgs[] = GNTTABOP_error_msgs;
+static const char * const gnttabop_error_msgs[] = GNTTABOP_error_msgs;
const char *
gnttabop_error(int16_t status)
diff --git a/extras/mini-os/hypervisor.c b/extras/mini-os/hypervisor.c
index 2c2efa7e46..ed87845195 100644
--- a/extras/mini-os/hypervisor.c
+++ b/extras/mini-os/hypervisor.c
@@ -35,8 +35,8 @@
void do_hypervisor_callback(struct pt_regs *regs)
{
- u32 l1, l2;
- unsigned int l1i, l2i, port;
+ unsigned long l1, l2, l1i, l2i;
+ unsigned int port;
int cpu = 0;
shared_info_t *s = HYPERVISOR_shared_info;
vcpu_info_t *vcpu_info = &s->vcpu_info[cpu];
diff --git a/extras/mini-os/include/wait.h b/extras/mini-os/include/wait.h
index f581db9109..d8338fbd8e 100644
--- a/extras/mini-os/include/wait.h
+++ b/extras/mini-os/include/wait.h
@@ -74,6 +74,13 @@ static inline void wake_up(struct wait_queue_head *head)
local_irq_restore(flags); \
} while (0)
+#define remove_waiter(w) do { \
+ unsigned long flags; \
+ local_irq_save(flags); \
+ remove_wait_queue(&w); \
+ local_irq_restore(flags); \
+} while (0)
+
#define wait_event(wq, condition) do{ \
unsigned long flags; \
if(condition) \
diff --git a/extras/mini-os/include/xenbus.h b/extras/mini-os/include/xenbus.h
index 3866a8bbce..cd4e85d122 100644
--- a/extras/mini-os/include/xenbus.h
+++ b/extras/mini-os/include/xenbus.h
@@ -13,6 +13,7 @@ void init_xenbus(void);
char *xenbus_read(xenbus_transaction_t xbt, const char *path, char **value);
char *xenbus_watch_path(xenbus_transaction_t xbt, const char *path);
+void wait_for_watch(void);
char* xenbus_wait_for_value(const char*,const char*);
/* Associates a value with a path. Returns a malloc'd error string on
diff --git a/extras/mini-os/xenbus/xenbus.c b/extras/mini-os/xenbus/xenbus.c
index f483211947..9433b22b02 100644
--- a/extras/mini-os/xenbus/xenbus.c
+++ b/extras/mini-os/xenbus/xenbus.c
@@ -72,11 +72,12 @@ static void memcpy_from_ring(const void *Ring,
memcpy(dest + c1, ring, c2);
}
-static inline void wait_for_watch(void)
+void wait_for_watch(void)
{
DEFINE_WAIT(w);
add_waiter(w,watch_queue);
schedule();
+ remove_waiter(w);
wake(current);
}
diff --git a/linux-2.6-xen-sparse/arch/i386/kernel/vsyscall-note-xen.S b/linux-2.6-xen-sparse/arch/i386/kernel/vsyscall-note-xen.S
index c2d6dbf159..019d9afb83 100644
--- a/linux-2.6-xen-sparse/arch/i386/kernel/vsyscall-note-xen.S
+++ b/linux-2.6-xen-sparse/arch/i386/kernel/vsyscall-note-xen.S
@@ -28,5 +28,5 @@
#define NOTE_KERNELCAP_END ASM_ELF_NOTE_END
NOTE_KERNELCAP_BEGIN(1, 1)
-NOTE_KERNELCAP(1, "nosegneg") /* Change 1 back to 0 when glibc is fixed! */
+NOTE_KERNELCAP(0, "nosegneg")
NOTE_KERNELCAP_END
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 28752922e3..df20e591c1 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
@@ -256,8 +256,9 @@ void pte_free(struct page *pte)
unsigned long va = (unsigned long)__va(pfn << PAGE_SHIFT);
if (!pte_write(*virt_to_ptep(va)))
- BUG_ON(HYPERVISOR_update_va_mapping(
- va, pfn_pte(pfn, PAGE_KERNEL), 0));
+ if (HYPERVISOR_update_va_mapping(
+ va, pfn_pte(pfn, PAGE_KERNEL), 0))
+ BUG();
} else
clear_bit(PG_pinned, &pte->flags);
@@ -672,14 +673,23 @@ void mm_unpin(struct mm_struct *mm)
void mm_pin_all(void)
{
struct page *page;
+ unsigned long flags;
if (xen_feature(XENFEAT_writable_page_tables))
return;
+ /*
+ * Allow uninterrupted access to the pgd_list. Also protects
+ * __pgd_pin() by disabling preemption.
+ * All other CPUs must be at a safe point (e.g., in stop_machine
+ * or offlined entirely).
+ */
+ spin_lock_irqsave(&pgd_lock, flags);
for (page = pgd_list; page; page = (struct page *)page->index) {
if (!test_bit(PG_pinned, &page->flags))
__pgd_pin((pgd_t *)page_address(page));
}
+ spin_unlock_irqrestore(&pgd_lock, flags);
}
void _arch_dup_mmap(struct mm_struct *mm)
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 de7c80dfb8..40bd5d235e 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
@@ -597,8 +597,10 @@ void __init xen_init_pt(void)
early_make_page_readonly(level2_kernel_pgt,
XENFEAT_writable_page_tables);
- xen_pgd_pin(__pa_symbol(init_level4_pgt));
- xen_pgd_pin(__pa_symbol(init_level4_user_pgt));
+ if (!xen_feature(XENFEAT_writable_page_tables)) {
+ xen_pgd_pin(__pa_symbol(init_level4_pgt));
+ xen_pgd_pin(__pa_symbol(init_level4_user_pgt));
+ }
set_pgd((pgd_t *)(init_level4_user_pgt + 511),
mk_kernel_pgd(__pa_symbol(level3_user_pgt)));
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 ae434e6be4..3b5fc26e84 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
@@ -79,14 +79,17 @@ void mm_pin(struct mm_struct *mm)
spin_lock(&mm->page_table_lock);
mm_walk(mm, PAGE_KERNEL_RO);
- BUG_ON(HYPERVISOR_update_va_mapping(
- (unsigned long)mm->pgd,
- pfn_pte(virt_to_phys(mm->pgd)>>PAGE_SHIFT, PAGE_KERNEL_RO),
- UVMF_TLB_FLUSH));
- BUG_ON(HYPERVISOR_update_va_mapping(
- (unsigned long)__user_pgd(mm->pgd),
- pfn_pte(virt_to_phys(__user_pgd(mm->pgd))>>PAGE_SHIFT, PAGE_KERNEL_RO),
- UVMF_TLB_FLUSH));
+ if (HYPERVISOR_update_va_mapping(
+ (unsigned long)mm->pgd,
+ pfn_pte(virt_to_phys(mm->pgd)>>PAGE_SHIFT, PAGE_KERNEL_RO),
+ UVMF_TLB_FLUSH))
+ BUG();
+ if (HYPERVISOR_update_va_mapping(
+ (unsigned long)__user_pgd(mm->pgd),
+ pfn_pte(virt_to_phys(__user_pgd(mm->pgd))>>PAGE_SHIFT,
+ PAGE_KERNEL_RO),
+ UVMF_TLB_FLUSH))
+ BUG();
xen_pgd_pin(__pa(mm->pgd)); /* kernel */
xen_pgd_pin(__pa(__user_pgd(mm->pgd))); /* user */
mm->context.pinned = 1;
@@ -106,12 +109,15 @@ void mm_unpin(struct mm_struct *mm)
xen_pgd_unpin(__pa(mm->pgd));
xen_pgd_unpin(__pa(__user_pgd(mm->pgd)));
- BUG_ON(HYPERVISOR_update_va_mapping(
- (unsigned long)mm->pgd,
- pfn_pte(virt_to_phys(mm->pgd)>>PAGE_SHIFT, PAGE_KERNEL), 0));
- BUG_ON(HYPERVISOR_update_va_mapping(
- (unsigned long)__user_pgd(mm->pgd),
- pfn_pte(virt_to_phys(__user_pgd(mm->pgd))>>PAGE_SHIFT, PAGE_KERNEL), 0));
+ if (HYPERVISOR_update_va_mapping(
+ (unsigned long)mm->pgd,
+ pfn_pte(virt_to_phys(mm->pgd)>>PAGE_SHIFT, PAGE_KERNEL), 0))
+ BUG();
+ if (HYPERVISOR_update_va_mapping(
+ (unsigned long)__user_pgd(mm->pgd),
+ pfn_pte(virt_to_phys(__user_pgd(mm->pgd))>>PAGE_SHIFT,
+ PAGE_KERNEL), 0))
+ BUG();
mm_walk(mm, PAGE_KERNEL);
xen_tlb_flush();
mm->context.pinned = 0;
@@ -127,43 +133,50 @@ void mm_pin_all(void)
if (xen_feature(XENFEAT_writable_page_tables))
return;
+ /*
+ * Allow uninterrupted access to the mm_unpinned list. We don't
+ * actually take the mm_unpinned_lock as it is taken inside mm_pin().
+ * All other CPUs must be at a safe point (e.g., in stop_machine
+ * or offlined entirely).
+ */
+ preempt_disable();
while (!list_empty(&mm_unpinned))
mm_pin(list_entry(mm_unpinned.next, struct mm_struct,
context.unpinned));
+ preempt_enable();
}
void _arch_dup_mmap(struct mm_struct *mm)
{
- if (!mm->context.pinned)
- mm_pin(mm);
+ if (!mm->context.pinned)
+ mm_pin(mm);
}
void _arch_exit_mmap(struct mm_struct *mm)
{
- struct task_struct *tsk = current;
+ struct task_struct *tsk = current;
- task_lock(tsk);
+ task_lock(tsk);
- /*
- * We aggressively remove defunct pgd from cr3. We execute unmap_vmas()
- * *much* faster this way, as no tlb flushes means bigger wrpt batches.
- */
- if ( tsk->active_mm == mm )
- {
- tsk->active_mm = &init_mm;
- atomic_inc(&init_mm.mm_count);
+ /*
+ * We aggressively remove defunct pgd from cr3. We execute unmap_vmas()
+ * *much* faster this way, as no tlb flushes means bigger wrpt batches.
+ */
+ if (tsk->active_mm == mm) {
+ tsk->active_mm = &init_mm;
+ atomic_inc(&init_mm.mm_count);
- switch_mm(mm, &init_mm, tsk);
+ switch_mm(mm, &init_mm, tsk);
- atomic_dec(&mm->mm_count);
- BUG_ON(atomic_read(&mm->mm_count) == 0);
- }
+ atomic_dec(&mm->mm_count);
+ BUG_ON(atomic_read(&mm->mm_count) == 0);
+ }
- task_unlock(tsk);
+ task_unlock(tsk);
- if ( mm->context.pinned && (atomic_read(&mm->mm_count) == 1) &&
- !mm->context.has_foreign_mappings )
- mm_unpin(mm);
+ if ( mm->context.pinned && (atomic_read(&mm->mm_count) == 1) &&
+ !mm->context.has_foreign_mappings )
+ mm_unpin(mm);
}
struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address)
@@ -183,8 +196,9 @@ void pte_free(struct page *pte)
unsigned long va = (unsigned long)__va(page_to_pfn(pte)<<PAGE_SHIFT);
if (!pte_write(*virt_to_ptep(va)))
- BUG_ON(HYPERVISOR_update_va_mapping(
- va, pfn_pte(page_to_pfn(pte), PAGE_KERNEL), 0));
+ if (HYPERVISOR_update_va_mapping(
+ va, pfn_pte(page_to_pfn(pte), PAGE_KERNEL), 0))
+ BUG();
ClearPageForeign(pte);
init_page_count(pte);
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 7e0c340832..98072726cb 100644
--- a/linux-2.6-xen-sparse/drivers/xen/netback/netback.c
+++ b/linux-2.6-xen-sparse/drivers/xen/netback/netback.c
@@ -1267,7 +1267,7 @@ static void net_tx_action(unsigned long unused)
/* Check the remap error code. */
if (unlikely(netbk_tx_check_mop(skb, &mop))) {
- printk(KERN_ALERT "#### netback grant fails\n");
+ DPRINTK("netback grant failed.\n");
skb_shinfo(skb)->nr_frags = 0;
kfree_skb(skb);
continue;
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 c00aaf7f6f..2521b8203d 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
@@ -110,7 +110,6 @@ int xb_write(const void *data, unsigned len)
/* Read indexes, then verify. */
cons = intf->req_cons;
prod = intf->req_prod;
- mb();
if (!check_indexes(cons, prod)) {
intf->req_cons = intf->req_prod = 0;
return -EIO;
@@ -122,15 +121,18 @@ int xb_write(const void *data, unsigned len)
if (avail > len)
avail = len;
+ /* Must write data /after/ reading the consumer index. */
+ mb();
+
memcpy(dst, data, avail);
data += avail;
len -= avail;
- /* Other side must not see new header until data is there. */
+ /* Other side must not see new producer until data is there. */
wmb();
intf->req_prod += avail;
- /* This implies mb() before other side sees interrupt. */
+ /* Implies mb(): other side will see the updated producer. */
notify_remote_via_evtchn(xen_store_evtchn);
}
@@ -165,7 +167,6 @@ int xb_read(void *data, unsigned len)
/* Read indexes, then verify. */
cons = intf->rsp_cons;
prod = intf->rsp_prod;
- mb();
if (!check_indexes(cons, prod)) {
intf->rsp_cons = intf->rsp_prod = 0;
return -EIO;
@@ -177,7 +178,7 @@ int xb_read(void *data, unsigned len)
if (avail > len)
avail = len;
- /* We must read header before we read data. */
+ /* Must read data /after/ reading the producer index. */
rmb();
memcpy(data, src, avail);
@@ -190,7 +191,7 @@ int xb_read(void *data, unsigned len)
pr_debug("Finished read of %i bytes (%i to go)\n", avail, len);
- /* Implies mb(): they will see new header. */
+ /* Implies mb(): other side will see the updated consumer. */
notify_remote_via_evtchn(xen_store_evtchn);
}
diff --git a/linux-2.6-xen-sparse/include/asm-i386/kexec.h b/linux-2.6-xen-sparse/include/asm-i386/kexec.h
index 4610897c78..abddf7b4d2 100644
--- a/linux-2.6-xen-sparse/include/asm-i386/kexec.h
+++ b/linux-2.6-xen-sparse/include/asm-i386/kexec.h
@@ -47,6 +47,9 @@
/* The native architecture */
#define KEXEC_ARCH KEXEC_ARCH_386
+/* We can also handle crash dumps from 64 bit kernel. */
+#define vmcore_elf_check_arch_cross(x) ((x)->e_machine == EM_X86_64)
+
#define MAX_NOTE_BYTES 1024
/* CPU does not save ss and esp on stack if execution is already
diff --git a/linux-2.6-xen-sparse/mm/Kconfig b/linux-2.6-xen-sparse/mm/Kconfig
new file mode 100644
index 0000000000..14492aaa5b
--- /dev/null
+++ b/linux-2.6-xen-sparse/mm/Kconfig
@@ -0,0 +1,157 @@
+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/allow-i386-crash-kernels-to-handle-x86_64-dumps-fix.patch b/patches/linux-2.6.18/allow-i386-crash-kernels-to-handle-x86_64-dumps-fix.patch
new file mode 100644
index 0000000000..2d60059ca7
--- /dev/null
+++ b/patches/linux-2.6.18/allow-i386-crash-kernels-to-handle-x86_64-dumps-fix.patch
@@ -0,0 +1,30 @@
+From: Andrew Morton <akpm@linux-foundation.org>
+
+In file included from arch/i386/kernel/setup.c:46:
+include/linux/crash_dump.h:19:36: warning: extra tokens at end of #ifndef directive
+
+Cc: "Eric W. Biederman" <ebiederm@xmission.com>
+Cc: Andi Kleen <ak@suse.de>
+Cc: Horms <horms@verge.net.au>
+Cc: Ian Campbell <ian.campbell@xensource.com>
+Cc: Magnus Damm <magnus.damm@gmail.com>
+Cc: Vivek Goyal <vgoyal@in.ibm.com>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+---
+
+ include/linux/crash_dump.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff -puN include/linux/crash_dump.h~allow-i386-crash-kernels-to-handle-x86_64-dumps-fix include/linux/crash_dump.h
+--- a/include/linux/crash_dump.h~allow-i386-crash-kernels-to-handle-x86_64-dumps-fix
++++ a/include/linux/crash_dump.h
+@@ -16,7 +16,7 @@ extern struct proc_dir_entry *proc_vmcor
+
+ /* Architecture code defines this if there are other possible ELF
+ * machine types, e.g. on bi-arch capable hardware. */
+-#ifndef vmcore_elf_check_arch_cross(x)
++#ifndef vmcore_elf_check_arch_cross
+ #define vmcore_elf_check_arch_cross(x) 0
+ #endif
+
+_
diff --git a/patches/linux-2.6.18/allow-i386-crash-kernels-to-handle-x86_64-dumps.patch b/patches/linux-2.6.18/allow-i386-crash-kernels-to-handle-x86_64-dumps.patch
new file mode 100644
index 0000000000..ad9eb93b3b
--- /dev/null
+++ b/patches/linux-2.6.18/allow-i386-crash-kernels-to-handle-x86_64-dumps.patch
@@ -0,0 +1,66 @@
+From: Ian Campbell <ian.campbell@xensource.com>
+
+The specific case I am encountering is kdump under Xen with a 64 bit
+hypervisor and 32 bit kernel/userspace. The dump created is 64 bit due to
+the hypervisor but the dump kernel is 32 bit for maximum compatibility.
+
+It's possibly less likely to be useful in a purely native scenario but I
+see no reason to disallow it.
+
+Signed-off-by: Ian Campbell <ian.campbell@xensource.com>
+Acked-by: Vivek Goyal <vgoyal@in.ibm.com>
+Cc: Horms <horms@verge.net.au>
+Cc: Magnus Damm <magnus.damm@gmail.com>
+Cc: "Eric W. Biederman" <ebiederm@xmission.com>
+Cc: Andi Kleen <ak@suse.de>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+---
+
+ fs/proc/vmcore.c | 2 +-
+ include/asm-i386/kexec.h | 3 +++
+ include/linux/crash_dump.h | 8 ++++++++
+ 3 files changed, 12 insertions(+), 1 deletion(-)
+
+diff -puN fs/proc/vmcore.c~allow-i386-crash-kernels-to-handle-x86_64-dumps fs/proc/vmcore.c
+--- a/fs/proc/vmcore.c~allow-i386-crash-kernels-to-handle-x86_64-dumps
++++ a/fs/proc/vmcore.c
+@@ -514,7 +514,7 @@ static int __init parse_crash_elf64_head
+ /* Do some basic Verification. */
+ if (memcmp(ehdr.e_ident, ELFMAG, SELFMAG) != 0 ||
+ (ehdr.e_type != ET_CORE) ||
+- !elf_check_arch(&ehdr) ||
++ !vmcore_elf_check_arch(&ehdr) ||
+ ehdr.e_ident[EI_CLASS] != ELFCLASS64 ||
+ ehdr.e_ident[EI_VERSION] != EV_CURRENT ||
+ ehdr.e_version != EV_CURRENT ||
+diff -puN include/asm-i386/kexec.h~allow-i386-crash-kernels-to-handle-x86_64-dumps include/asm-i386/kexec.h
+--- a/include/asm-i386/kexec.h~allow-i386-crash-kernels-to-handle-x86_64-dumps
++++ a/include/asm-i386/kexec.h
+@@ -47,6 +47,9 @@
+ /* The native architecture */
+ #define KEXEC_ARCH KEXEC_ARCH_386
+
++/* We can also handle crash dumps from 64 bit kernel. */
++#define vmcore_elf_check_arch_cross(x) ((x)->e_machine == EM_X86_64)
++
+ #define MAX_NOTE_BYTES 1024
+
+ /* CPU does not save ss and esp on stack if execution is already
+diff -puN include/linux/crash_dump.h~allow-i386-crash-kernels-to-handle-x86_64-dumps include/linux/crash_dump.h
+--- a/include/linux/crash_dump.h~allow-i386-crash-kernels-to-handle-x86_64-dumps
++++ a/include/linux/crash_dump.h
+@@ -14,5 +14,13 @@ extern ssize_t copy_oldmem_page(unsigned
+ extern const struct file_operations proc_vmcore_operations;
+ extern struct proc_dir_entry *proc_vmcore;
+
++/* Architecture code defines this if there are other possible ELF
++ * machine types, e.g. on bi-arch capable hardware. */
++#ifndef vmcore_elf_check_arch_cross(x)
++#define vmcore_elf_check_arch_cross(x) 0
++#endif
++
++#define vmcore_elf_check_arch(x) (elf_check_arch(x) || vmcore_elf_check_arch_cross(x))
++
+ #endif /* CONFIG_CRASH_DUMP */
+ #endif /* LINUX_CRASHDUMP_H */
+_
diff --git a/patches/linux-2.6.18/crash-kernel-32-on-64.patch b/patches/linux-2.6.18/crash-kernel-32-on-64.patch
deleted file mode 100644
index 8ea9378188..0000000000
--- a/patches/linux-2.6.18/crash-kernel-32-on-64.patch
+++ /dev/null
@@ -1,11 +0,0 @@
---- pristine-linux-2.6.18/include/asm-i386/elf.h 2006-09-20 04:42:06.000000000 +0100
-+++ linux-2.6.18-xen/include/asm-i386/elf.h 2007-03-14 16:42:30.000000000 +0000
-@@ -36,7 +36,7 @@
- * This is used to ensure we don't load something for the wrong architecture.
- */
- #define elf_check_arch(x) \
-- (((x)->e_machine == EM_386) || ((x)->e_machine == EM_486))
-+ (((x)->e_machine == EM_386) || ((x)->e_machine == EM_486) || ((x)->e_machine == EM_X86_64))
-
- /*
- * These are used to set parameters in the core dumps.
diff --git a/patches/linux-2.6.18/series b/patches/linux-2.6.18/series
index 978fdacc42..a3597cd5a0 100644
--- a/patches/linux-2.6.18/series
+++ b/patches/linux-2.6.18/series
@@ -19,4 +19,5 @@ x86-elfnote-as-preprocessor-macro.patch
fixaddr-top.patch
git-c06cb8b1c4d25e5b4d7a2d7c2462619de1e0dbc4.patch
softlockup-no-idle-hz.patch
-crash-kernel-32-on-64.patch
+allow-i386-crash-kernels-to-handle-x86_64-dumps.patch
+allow-i386-crash-kernels-to-handle-x86_64-dumps-fix.patch
diff --git a/tools/Rules.mk b/tools/Rules.mk
index df3b231a1a..3e13eceb55 100644
--- a/tools/Rules.mk
+++ b/tools/Rules.mk
@@ -23,6 +23,11 @@ LDFLAGS += $(shell getconf LFS_LDFLAGS)
CFLAGS-$(CONFIG_X86_32) += $(call cc-option,$(CC),-mno-tls-direct-seg-refs)
CFLAGS += $(CFLAGS-y)
+# Require GCC v3.4+ (to avoid issues with alignment constraints in Xen headers)
+ifeq ($(CONFIG_X86)$(call cc-ver,$(CC),0x030400),yn)
+$(error Xen tools require at least gcc-3.4)
+endif
+
%.opic: %.c
$(CC) $(CPPFLAGS) -DPIC $(CFLAGS) -fPIC -c -o $@ $<
diff --git a/tools/blktap/drivers/block-qcow.c b/tools/blktap/drivers/block-qcow.c
index 36f77e6f05..b0822f729d 100644
--- a/tools/blktap/drivers/block-qcow.c
+++ b/tools/blktap/drivers/block-qcow.c
@@ -1057,6 +1057,7 @@ int tdqcow_queue_write(struct disk_driver *dd, uint64_t sector,
index_in_cluster+n);
if (!cluster_offset) {
DPRINTF("Ooops, no write cluster offset!\n");
+ aio_unlock(s, sector);
return cb(dd, -EIO, sector, nb_sectors, id, private);
}
diff --git a/tools/firmware/Makefile b/tools/firmware/Makefile
index b924fde793..38338471fd 100644
--- a/tools/firmware/Makefile
+++ b/tools/firmware/Makefile
@@ -14,7 +14,7 @@ SUBDIRS += hvmloader
.PHONY: all
all:
- @set -e; if [ $$((`bcc -v 2>&1 | grep version | cut -d' ' -f 3 | awk -F. '{ printf "0x%02x%02x%02x", $$1, $$2, $$3}'`)) -lt $$((0x00100e)) ] ; then \
+ @set -e; if [ $$((`( bcc -v 2>&1 | grep version || echo 0.0.0 ) | cut -d' ' -f 3 | awk -F. '{ printf "0x%02x%02x%02x", $$1, $$2, $$3}'`)) -lt $$((0x00100e)) ] ; then \
echo "***********************************************************"; \
echo "Require dev86 package version >= 0.16.14 to build firmware!"; \
echo "(visit http://www.cix.co.uk/~mayday for more information)"; \
diff --git a/tools/firmware/hvmloader/32bitbios_support.c b/tools/firmware/hvmloader/32bitbios_support.c
index bfde19577f..7cb32a299d 100644
--- a/tools/firmware/hvmloader/32bitbios_support.c
+++ b/tools/firmware/hvmloader/32bitbios_support.c
@@ -17,157 +17,129 @@
* this program; if not, write to the Free Software Foundation, Inc., 59 Temple
* Place - Suite 330, Boston, MA 02111-1307 USA.
*/
+
#include <inttypes.h>
#include <elf.h>
#ifdef __sun__
#include <sys/machelf.h>
#endif
-#include <xen/hvm/e820.h>
#include "util.h"
#include "config.h"
#include "../rombios/32bit/32bitbios_flat.h"
#include "../rombios/32bit/jumptable.h"
-
-/*
- * relocate ELF file of type ET_REL
- */
-static int relocate_elf(unsigned char *elfarray) {
+/* Relocate ELF file of type ET_REL */
+static void relocate_elf(char *elfarray)
+{
Elf32_Ehdr *ehdr = (Elf32_Ehdr *)elfarray;
Elf32_Shdr *shdr = (Elf32_Shdr *)&elfarray[ehdr->e_shoff];
- int i;
-
- if (ehdr->e_type != ET_REL) {
- printf("Not a relocatable BIOS object file. Has type %d, need %d\n",
- ehdr->e_type, ET_REL);
- return -1;
- }
+ Elf32_Sym *syms, *sym;
+ Elf32_Rel *rels;
+ char *code;
+ uint32_t *loc, fix;
+ int i, j;
- for (i = 0; i < ehdr->e_shnum; i++)
+ for ( i = 0; i < ehdr->e_shnum; i++ )
shdr[i].sh_addr = (Elf32_Addr)&elfarray[shdr[i].sh_offset];
- for (i = 0; i < ehdr->e_shnum; i++) {
- if (shdr[i].sh_type == SHT_REL) {
- Elf32_Shdr *targetsec = (Elf32_Shdr *)&(shdr[shdr[i].sh_info]);
- Elf32_Shdr *symtabsec = (Elf32_Shdr *)&(shdr[shdr[i].sh_link]);
- Elf32_Sym *syms = (Elf32_Sym *)symtabsec->sh_addr;
- Elf32_Rel *rels = (Elf32_Rel *)shdr[i].sh_addr;
- unsigned char *code = (unsigned char *)targetsec->sh_addr;
- int j;
-
- /* must not have been stripped */
- if (shdr[i].sh_size == 0)
- return -6;
-
- for (j = 0; j < shdr[i].sh_size / sizeof(Elf32_Rel); j++) {
- int idx = ELF32_R_SYM(rels[j].r_info);
- Elf32_Sym *symbol = &syms[idx];
- uint32_t *loc = (uint32_t *)&code[rels[j].r_offset];
- uint32_t fix = shdr[symbol->st_shndx].sh_addr +
- symbol->st_value;
-
- switch (ELF32_R_TYPE(rels[j].r_info)) {
- case R_386_PC32:
- *loc += (fix - (uint32_t)loc);
- break;
-
- case R_386_32:
- *loc += fix;
- break;
- }
+ for ( i = 0; i < ehdr->e_shnum; i++ )
+ {
+ if ( shdr[i].sh_type == SHT_RELA )
+ printf("Unsupported section type SHT_RELA\n");
+
+ if ( shdr[i].sh_type != SHT_REL )
+ continue;
+
+ syms = (Elf32_Sym *)shdr[shdr[i].sh_link].sh_addr;
+ rels = (Elf32_Rel *)shdr[i].sh_addr;
+ code = (char *)shdr[shdr[i].sh_info].sh_addr;
+
+ for ( j = 0; j < shdr[i].sh_size / sizeof(Elf32_Rel); j++ )
+ {
+ sym = &syms[ELF32_R_SYM(rels[j].r_info)];
+ loc = (uint32_t *)&code[rels[j].r_offset];
+ fix = shdr[sym->st_shndx].sh_addr + sym->st_value;
+
+ switch ( ELF32_R_TYPE(rels[j].r_info) )
+ {
+ case R_386_PC32:
+ *loc += fix - (uint32_t)loc;
+ break;
+
+ case R_386_32:
+ *loc += fix;
+ break;
}
- } else if (shdr[i].sh_type == SHT_RELA) {
- return -2;
}
}
- return 0;
}
-/* scan the rombios for the destination of the jumptable */
-static char* get_jump_table_start(void)
+/* Scan the rombios for the destination of the jump table. */
+static char *get_jump_table_start(void)
{
char *bios_mem;
for ( bios_mem = (char *)ROMBIOS_BEGIN;
bios_mem != (char *)ROMBIOS_END;
- bios_mem++ ) {
- if (strncmp(bios_mem, "___JMPT", 7) == 0)
+ bios_mem++ )
+ if ( !strncmp(bios_mem, "___JMPT", 7) )
return bios_mem;
- }
return NULL;
}
-/* copy relocated jumptable into the rombios */
-static int copy_jumptable(unsigned char *elfarray)
+/* Copy relocated jumptable into the rombios. */
+static void copy_jumptable(char *elfarray)
{
- int rc = 0;
Elf32_Ehdr *ehdr = (Elf32_Ehdr *)elfarray;
Elf32_Shdr *shdr = (Elf32_Shdr *)&elfarray[ehdr->e_shoff];
- Elf32_Shdr *shdr_strings = (Elf32_Shdr *)&shdr[ehdr->e_shstrndx];
- char *secstrings = (char *)&elfarray[shdr_strings->sh_offset];
- uint32_t *rombiosjumptable = (uint32_t *)get_jump_table_start();
- uint32_t *biosjumptable = NULL;
+ char *secstrings = &elfarray[shdr[ehdr->e_shstrndx].sh_offset];
+ char *jump_table = get_jump_table_start();
int i;
- if (rombiosjumptable == NULL) {
- return -3;
- }
-
- /* find the section with the jump table and copy to lower BIOS memory */
- for (i = 0; i < ehdr->e_shnum; i++) {
- if (!strcmp(JUMPTABLE_SECTION_NAME, secstrings + shdr[i].sh_name)) {
- uint32_t biosjumptableentries;
- biosjumptable = (uint32_t *)shdr[i].sh_addr;
- biosjumptableentries = shdr[i].sh_size / 4;
- for (int j = 0; j < biosjumptableentries; j++) {
- rombiosjumptable[j] = biosjumptable[j];
- if (biosjumptable[j] == 0 &&
- j < (biosjumptableentries - 1)) {
- printf("WARNING: jumptable entry %d is NULL!\n",j);
- }
- }
+ /* Find the section with the jump table and copy to lower BIOS memory. */
+ for ( i = 0; i < ehdr->e_shnum; i++ )
+ if ( !strcmp(JUMPTABLE_SECTION_NAME, secstrings + shdr[i].sh_name) )
break;
- }
- }
- if (biosjumptable == NULL) {
+ if ( i == ehdr->e_shnum )
+ {
printf("Could not find " JUMPTABLE_SECTION_NAME " section in file.\n");
- rc = -4;
+ return;
+ }
+
+ if ( jump_table == NULL )
+ {
+ printf("Could not find jump table in file.\n");
+ return;
}
- return 0;
+ memcpy(jump_table, (char *)shdr[i].sh_addr, shdr[i].sh_size);
}
-static int relocate_32bitbios(unsigned char *elfarray, uint32_t elfarraysize)
+static void relocate_32bitbios(char *elfarray, uint32_t elfarraysize)
{
- int rc = 0;
uint32_t mask = (64 * 1024) - 1;
- uint32_t to_malloc = (elfarraysize + mask) & ~mask; /* round to 64kb */
- unsigned char *highbiosarea;
-
- highbiosarea = (unsigned char *)(long)
- e820_malloc((uint64_t)to_malloc,
- E820_RESERVED,
- (uint64_t)0xffffffff);
-
- if (highbiosarea != 0) {
- memcpy(highbiosarea, elfarray, elfarraysize);
- rc = relocate_elf(highbiosarea);
- if (rc == 0) {
- rc = copy_jumptable(highbiosarea);
- }
- } else {
- rc = -5;
+ char *highbiosarea;
+
+ highbiosarea = (char *)(long)
+ e820_malloc((elfarraysize + mask) & ~mask, /* round to 64kb */
+ E820_RESERVED,
+ (uint64_t)0xffffffff);
+ if ( highbiosarea == NULL )
+ {
+ printf("No available memory for BIOS high memory area\n");
+ return;
}
- return rc;
+ memcpy(highbiosarea, elfarray, elfarraysize);
+ relocate_elf(highbiosarea);
+ copy_jumptable(highbiosarea);
}
-int highbios_setup(void)
+void highbios_setup(void)
{
- return relocate_32bitbios((unsigned char *)highbios_array,
- sizeof(highbios_array));
+ relocate_32bitbios((char *)highbios_array, sizeof(highbios_array));
}
diff --git a/tools/firmware/hvmloader/acpi/build.c b/tools/firmware/hvmloader/acpi/build.c
index 3db71cabfe..7be1ea4a71 100644
--- a/tools/firmware/hvmloader/acpi/build.c
+++ b/tools/firmware/hvmloader/acpi/build.c
@@ -20,7 +20,6 @@
#include "ssdt_tpm.h"
#include "../config.h"
#include "../util.h"
-#include <xen/hvm/e820.h>
#define align16(sz) (((sz) + 15) & ~15)
#define fixed_strcpy(d, s) strncpy((d), (s), sizeof(d))
diff --git a/tools/firmware/hvmloader/hvmloader.c b/tools/firmware/hvmloader/hvmloader.c
index 8bed54835a..beabd06248 100644
--- a/tools/firmware/hvmloader/hvmloader.c
+++ b/tools/firmware/hvmloader/hvmloader.c
@@ -29,7 +29,6 @@
#include "pci_regs.h"
#include <xen/version.h>
#include <xen/hvm/params.h>
-#include <xen/hvm/e820.h>
/* memory map */
#define HYPERCALL_PHYSICAL_ADDRESS 0x00080000
@@ -297,25 +296,57 @@ static void pci_setup(void)
}
}
-static
-int must_load_nic(void)
+/*
+ * If the network card is in the boot order, load the Etherboot option ROM.
+ * Read the boot order bytes from CMOS and check if any of them are 0x4.
+ */
+static int must_load_nic(void)
{
- /* If the network card is in the boot order, load the Etherboot
- * option ROM. Read the boot order bytes from CMOS and check
- * if any of them are 0x4. */
uint8_t boot_order;
- /* Read CMOS register 0x3d (boot choices 0 and 1) */
- outb(0x70, 0x3d);
- boot_order = inb(0x71);
- if ( (boot_order & 0xf) == 0x4 || (boot_order & 0xf0) == 0x40 )
- return 1;
- /* Read CMOS register 0x38 (boot choice 2 and FDD test flag) */
- outb(0x70, 0x38);
- boot_order = inb(0x71);
- if ( (boot_order & 0xf0) == 0x40 )
+ /* Read CMOS register 0x3d (boot choices 0 and 1). */
+ boot_order = cmos_inb(0x3d);
+ if ( ((boot_order & 0xf) == 0x4) || ((boot_order & 0xf0) == 0x40) )
return 1;
- return 0;
+
+ /* Read CMOS register 0x38 (boot choice 2 and FDD test flag). */
+ boot_order = cmos_inb(0x38);
+ return ((boot_order & 0xf0) == 0x40);
+}
+
+/* Replace possibly erroneous memory-size CMOS fields with correct values. */
+static void cmos_write_memory_size(void)
+{
+ struct e820entry *map = E820_MAP;
+ int i, nr = *E820_MAP_NR;
+ uint32_t base_mem = 640, ext_mem = 0, alt_mem = 0;
+
+ for ( i = 0; i < nr; i++ )
+ if ( (map[i].addr >= 0x100000) && (map[i].type == E820_RAM) )
+ break;
+
+ if ( i != nr )
+ {
+ alt_mem = ext_mem = map[i].addr + map[i].size;
+ ext_mem = (ext_mem > 0x0100000) ? (ext_mem - 0x0100000) >> 10 : 0;
+ if ( ext_mem > 0xffff )
+ ext_mem = 0xffff;
+ alt_mem = (alt_mem > 0x1000000) ? (alt_mem - 0x1000000) >> 16 : 0;
+ }
+
+ /* All BIOSes: conventional memory (640kB). */
+ cmos_outb(0x15, (uint8_t)(base_mem >> 0));
+ cmos_outb(0x16, (uint8_t)(base_mem >> 8));
+
+ /* All BIOSes: extended memory (1kB chunks above 1MB). */
+ cmos_outb(0x17, (uint8_t)( ext_mem >> 0));
+ cmos_outb(0x18, (uint8_t)( ext_mem >> 8));
+ cmos_outb(0x30, (uint8_t)( ext_mem >> 0));
+ cmos_outb(0x31, (uint8_t)( ext_mem >> 8));
+
+ /* Some BIOSes: alternative extended memory (64kB chunks above 16MB). */
+ cmos_outb(0x34, (uint8_t)( alt_mem >> 0));
+ cmos_outb(0x35, (uint8_t)( alt_mem >> 8));
}
int main(void)
@@ -366,6 +397,8 @@ int main(void)
ASSERT((ACPI_PHYSICAL_ADDRESS + acpi_sz) <= 0xF0000);
}
+ cmos_write_memory_size();
+
if ( !check_amd() )
{
printf("Loading VMXAssist ...\n");
diff --git a/tools/firmware/hvmloader/smbios.c b/tools/firmware/hvmloader/smbios.c
index df25999c3a..c9a4992e4c 100644
--- a/tools/firmware/hvmloader/smbios.c
+++ b/tools/firmware/hvmloader/smbios.c
@@ -22,7 +22,6 @@
#include <stdint.h>
#include <xen/version.h>
-#include <xen/hvm/e820.h>
#include "smbios.h"
#include "smbios_types.h"
#include "util.h"
@@ -129,47 +128,32 @@ write_smbios_tables(void *start,
return (size_t)((char *)p - (char *)start);
}
-/* This tries to figure out how much pseudo-physical memory (in MB)
- is allocated to the current domU.
-
- It iterates through the e820 table, adding up the 'usable' and
- 'reserved' entries and rounding up to the nearest MB.
-
- The e820map is not at e820 in hvmloader, so this uses the
- E820_MAP_* constants from e820.h to pick it up where libxenguest
- left it.
- */
+/* Calculate how much pseudo-physical memory (in MB) is allocated to us. */
static uint64_t
get_memsize(void)
{
- struct e820entry *map = NULL;
- uint8_t num_entries = 0;
+ struct e820entry *map = E820_MAP;
+ uint8_t num_entries = *E820_MAP_NR;
uint64_t memsize = 0;
- uint8_t i;
-
- map = (struct e820entry *) (E820_MAP_PAGE + E820_MAP_OFFSET);
- num_entries = *((uint8_t *) (E820_MAP_PAGE + E820_MAP_NR_OFFSET));
-
- /* walk through e820map, ignoring any entries that aren't marked
- as usable or reserved. */
+ int i;
+ /*
+ * Walk through e820map, ignoring any entries that aren't marked
+ * as usable or reserved.
+ */
for ( i = 0; i < num_entries; i++ )
{
- if (map->type == E820_RAM || map->type == E820_RESERVED)
+ if ( (map->type == E820_RAM) || (map->type == E820_RESERVED) )
memsize += map->size;
map++;
}
- /* Round up to the nearest MB. The user specifies domU
- pseudo-physical memory in megabytes, so not doing this
- could easily lead to reporting one less MB than the user
- specified. */
- if ( memsize & ((1<<20)-1) )
- memsize = (memsize >> 20) + 1;
- else
- memsize = (memsize >> 20);
-
- return memsize;
+ /*
+ * Round up to the nearest MB. The user specifies domU pseudo-physical
+ * memory in megabytes, so not doing this could easily lead to reporting
+ * one less MB than the user specified.
+ */
+ return (memsize + (1 << 20) - 1) >> 20;
}
void
diff --git a/tools/firmware/hvmloader/util.c b/tools/firmware/hvmloader/util.c
index ce32a9001e..2f5f23d1e5 100644
--- a/tools/firmware/hvmloader/util.c
+++ b/tools/firmware/hvmloader/util.c
@@ -27,17 +27,17 @@
void outb(uint16_t addr, uint8_t val)
{
- __asm__ __volatile__ ( "outb %%al, %%dx" :: "d"(addr), "a"(val) );
+ __asm__ __volatile__ ( "outb %%al, %%dx" : : "d" (addr), "a" (val) );
}
void outw(uint16_t addr, uint16_t val)
{
- __asm__ __volatile__ ( "outw %%ax, %%dx" :: "d"(addr), "a"(val) );
+ __asm__ __volatile__ ( "outw %%ax, %%dx" : : "d" (addr), "a" (val) );
}
void outl(uint16_t addr, uint32_t val)
{
- __asm__ __volatile__ ( "outl %%eax, %%dx" :: "d"(addr), "a"(val) );
+ __asm__ __volatile__ ( "outl %%eax, %%dx" : : "d" (addr), "a" (val) );
}
uint8_t inb(uint16_t addr)
@@ -61,6 +61,18 @@ uint32_t inl(uint16_t addr)
return val;
}
+uint8_t cmos_inb(uint8_t idx)
+{
+ outb(0x70, idx);
+ return inb(0x71);
+}
+
+void cmos_outb(uint8_t idx, uint8_t val)
+{
+ outb(0x70, idx);
+ outb(0x71, val);
+}
+
char *itoa(char *a, unsigned int i)
{
unsigned int _i = i, x = 0;
@@ -280,9 +292,6 @@ uuid_to_string(char *dest, uint8_t *uuid)
*p = '\0';
}
-#include <xen/hvm/e820.h>
-#define E820_MAP_NR ((unsigned char *)E820_MAP_PAGE + E820_MAP_NR_OFFSET)
-#define E820_MAP ((struct e820entry *)(E820_MAP_PAGE + E820_MAP_OFFSET))
uint64_t e820_malloc(uint64_t size, uint32_t type, uint64_t mask)
{
uint64_t addr = 0;
diff --git a/tools/firmware/hvmloader/util.h b/tools/firmware/hvmloader/util.h
index 368f93ddda..cc1f42dba9 100644
--- a/tools/firmware/hvmloader/util.h
+++ b/tools/firmware/hvmloader/util.h
@@ -26,6 +26,10 @@ uint8_t inb(uint16_t addr);
uint16_t inw(uint16_t addr);
uint32_t inl(uint16_t addr);
+/* CMOS access */
+uint8_t cmos_inb(uint8_t idx);
+void cmos_outb(uint8_t idx, uint8_t val);
+
/* APIC access */
uint32_t ioapic_read(uint32_t reg);
void ioapic_write(uint32_t reg, uint32_t val);
@@ -78,9 +82,13 @@ int vprintf(const char *fmt, va_list ap);
/* Allocate region of specified type in the e820 table. */
uint64_t e820_malloc(uint64_t size, uint32_t type, uint64_t mask);
-/* Prepare the 32bit BIOS */
-int highbios_setup(void);
+/* General e820 access. */
+#include <xen/hvm/e820.h>
+#define E820_MAP_NR ((unsigned char *)E820_MAP_PAGE + E820_MAP_NR_OFFSET)
+#define E820_MAP ((struct e820entry *)(E820_MAP_PAGE + E820_MAP_OFFSET))
+/* Prepare the 32bit BIOS */
+void highbios_setup(void);
#define isdigit(c) ((c) >= '0' && (c) <= '9')
diff --git a/tools/firmware/rombios/rombios.c b/tools/firmware/rombios/rombios.c
index c8fbb92ab1..eb288a80fa 100644
--- a/tools/firmware/rombios/rombios.c
+++ b/tools/firmware/rombios/rombios.c
@@ -4196,178 +4196,86 @@ ASM_END
case 0xe8:
switch(regs.u.r8.al)
{
- case 0x20: // coded by osmaker aka K.J.
- if(regs.u.r32.edx == 0x534D4150) /* SMAP */
- {
-#ifdef HVMASSIST
- if ((regs.u.r16.bx / 0x14) * 0x14 == regs.u.r16.bx) {
- Bit16u e820_table_size = read_word(0xe000, 0x8) * 0x14;
-
- if (regs.u.r16.bx + 0x14 <= e820_table_size) {
- memcpyb(ES, regs.u.r16.di,
- 0xe000, 0x10 + regs.u.r16.bx, 0x14);
- }
- regs.u.r32.ebx += 0x14;
- if ((regs.u.r32.ebx + 0x14 - 1) > e820_table_size)
- regs.u.r32.ebx = 0;
- regs.u.r32.eax = 0x534D4150;
- regs.u.r32.ecx = 0x14;
- CLEAR_CF();
- return;
- } else if (regs.u.r16.bx == 1) {
- extended_memory_size = inb_cmos(0x35);
- extended_memory_size <<= 8;
- extended_memory_size |= inb_cmos(0x34);
- extended_memory_size *= 64;
- if (extended_memory_size > 0x3bc000) // greater than EFF00000???
- {
- extended_memory_size = 0x3bc000; // everything after this is reserved memory until we get to 0x100000000
- }
- extended_memory_size *= 1024;
- extended_memory_size += 15728640; // make up for the 16mb of memory that is chopped off
-
- if (extended_memory_size <= 15728640)
- {
- extended_memory_size = inb_cmos(0x31);
- extended_memory_size <<= 8;
- extended_memory_size |= inb_cmos(0x30);
- extended_memory_size *= 1024;
- }
-
- write_word(ES, regs.u.r16.di, 0x0000);
- write_word(ES, regs.u.r16.di+2, 0x0010);
- write_word(ES, regs.u.r16.di+4, 0x0000);
- write_word(ES, regs.u.r16.di+6, 0x0000);
-
- write_word(ES, regs.u.r16.di+8, extended_memory_size);
- extended_memory_size >>= 16;
- write_word(ES, regs.u.r16.di+10, extended_memory_size);
- extended_memory_size >>= 16;
- write_word(ES, regs.u.r16.di+12, extended_memory_size);
- extended_memory_size >>= 16;
- write_word(ES, regs.u.r16.di+14, extended_memory_size);
-
- write_word(ES, regs.u.r16.di+16, 0x1);
- write_word(ES, regs.u.r16.di+18, 0x0);
-
- regs.u.r32.ebx = 0;
- regs.u.r32.eax = 0x534D4150;
- regs.u.r32.ecx = 0x14;
- CLEAR_CF();
- return;
- } else { /* AX=E820, DX=534D4150, BX unrecognized */
- goto int15_unimplemented;
- }
-#else
- switch(regs.u.r16.bx)
- {
- case 0:
- write_word(ES, regs.u.r16.di, 0x00);
- write_word(ES, regs.u.r16.di+2, 0x00);
- write_word(ES, regs.u.r16.di+4, 0x00);
- write_word(ES, regs.u.r16.di+6, 0x00);
-
- write_word(ES, regs.u.r16.di+8, 0xFC00);
- write_word(ES, regs.u.r16.di+10, 0x0009);
- write_word(ES, regs.u.r16.di+12, 0x0000);
- write_word(ES, regs.u.r16.di+14, 0x0000);
-
- write_word(ES, regs.u.r16.di+16, 0x1);
- write_word(ES, regs.u.r16.di+18, 0x0);
-
- regs.u.r32.ebx = 1;
-
- regs.u.r32.eax = 0x534D4150;
- regs.u.r32.ecx = 0x14;
- CLEAR_CF();
- return;
- break;
- case 1:
- extended_memory_size = inb_cmos(0x35);
- extended_memory_size <<= 8;
- extended_memory_size |= inb_cmos(0x34);
- extended_memory_size *= 64;
- if(extended_memory_size > 0x3bc000) // greater than EFF00000???
- {
- extended_memory_size = 0x3bc000; // everything after this is reserved memory until we get to 0x100000000
- }
- extended_memory_size *= 1024;
- extended_memory_size += 15728640; // make up for the 16mb of memory that is chopped off
-
- if(extended_memory_size <= 15728640)
- {
- extended_memory_size = inb_cmos(0x31);
- extended_memory_size <<= 8;
- extended_memory_size |= inb_cmos(0x30);
- extended_memory_size *= 1024;
- }
-
- write_word(ES, regs.u.r16.di, 0x0000);
- write_word(ES, regs.u.r16.di+2, 0x0010);
- write_word(ES, regs.u.r16.di+4, 0x0000);
- write_word(ES, regs.u.r16.di+6, 0x0000);
-
- write_word(ES, regs.u.r16.di+8, extended_memory_size);
- extended_memory_size >>= 16;
- write_word(ES, regs.u.r16.di+10, extended_memory_size);
- extended_memory_size >>= 16;
- write_word(ES, regs.u.r16.di+12, extended_memory_size);
- extended_memory_size >>= 16;
- write_word(ES, regs.u.r16.di+14, extended_memory_size);
-
- write_word(ES, regs.u.r16.di+16, 0x1);
- write_word(ES, regs.u.r16.di+18, 0x0);
-
- regs.u.r32.ebx = 0;
- regs.u.r32.eax = 0x534D4150;
- regs.u.r32.ecx = 0x14;
- CLEAR_CF();
- return;
- break;
- default: /* AX=E820, DX=534D4150, BX unrecognized */
- goto int15_unimplemented;
+ case 0x20: {
+ Bit16u e820_table_size = read_word(0xe000, 0x8) * 0x14;
+
+ if (regs.u.r32.edx != 0x534D4150) /* SMAP */
+ goto int15_unimplemented;
+
+ if ((regs.u.r16.bx / 0x14) * 0x14 == regs.u.r16.bx) {
+ if (regs.u.r16.bx + 0x14 <= e820_table_size)
+ memcpyb(ES, regs.u.r16.di,
+ 0xe000, 0x10 + regs.u.r16.bx, 0x14);
+ regs.u.r32.ebx += 0x14;
+ if ((regs.u.r32.ebx + 0x14 - 1) > e820_table_size)
+ regs.u.r32.ebx = 0;
+ } else if (regs.u.r16.bx == 1) {
+ Bit32u base, type;
+ Bit16u off;
+ for (off = 0; off < e820_table_size; off += 0x14) {
+ base = read_dword(0xe000, 0x10 + off);
+ type = read_dword(0xe000, 0x20 + off);
+ if ((base >= 0x100000) && (type == 1))
break;
}
-#endif
- } else {
- // if DX != 0x534D4150)
- goto int15_unimplemented;
- }
+ if (off == e820_table_size) {
+ SET_CF();
+ break;
+ }
+ memcpyb(ES, regs.u.r16.di, 0xe000, 0x10 + off, 0x14);
+ regs.u.r32.ebx = 0;
+ } else { /* AX=E820, DX=534D4150, BX unrecognized */
+ goto int15_unimplemented;
+ }
+
+ regs.u.r32.eax = 0x534D4150;
+ regs.u.r32.ecx = 0x14;
+ CLEAR_CF();
break;
+ }
- case 0x01:
- // do we have any reason to fail here ?
- CLEAR_CF();
+ case 0x01: {
+ Bit16u off, e820_table_size = read_word(0xe000, 0x8) * 0x14;
+ Bit32u base, type, size;
- // my real system sets ax and bx to 0
- // this is confirmed by Ralph Brown list
- // but syslinux v1.48 is known to behave
- // strangely if ax is set to 0
- // regs.u.r16.ax = 0;
- // regs.u.r16.bx = 0;
+ // do we have any reason to fail here ?
+ CLEAR_CF();
- // Get the amount of extended memory (above 1M)
- regs.u.r8.cl = inb_cmos(0x30);
- regs.u.r8.ch = inb_cmos(0x31);
+ // Get the amount of extended memory (above 1M)
+ regs.u.r8.cl = inb_cmos(0x30);
+ regs.u.r8.ch = inb_cmos(0x31);
- // limit to 15M
- if(regs.u.r16.cx > 0x3c00)
- {
- regs.u.r16.cx = 0x3c00;
- }
+ // limit to 15M
+ if (regs.u.r16.cx > (15*1024))
+ regs.u.r16.cx = 15*1024;
+
+ // Find first RAM E820 entry >= 1MB.
+ for (off = 0; off < e820_table_size; off += 0x14) {
+ base = read_dword(0xe000, 0x10 + off);
+ type = read_dword(0xe000, 0x20 + off);
+ if ((base >= 0x100000) && (type == 1))
+ break;
+ }
- // Get the amount of extended memory above 16M in 64k blocs
- regs.u.r8.dl = inb_cmos(0x34);
- regs.u.r8.dh = inb_cmos(0x35);
+ // If there is RAM above 16MB, return amount in 64kB chunks.
+ regs.u.r16.dx = 0;
+ if (off != e820_table_size) {
+ size = base + read_dword(0xe000, 0x18 + off);
+ if (size > 0x1000000) {
+ size -= 0x1000000;
+ regs.u.r16.dx = (Bit16u)(size >> 16);
+ }
+ }
- // Set configured memory equal to extended memory
- regs.u.r16.ax = regs.u.r16.cx;
- regs.u.r16.bx = regs.u.r16.dx;
- break;
+ // Set configured memory equal to extended memory
+ regs.u.r16.ax = regs.u.r16.cx;
+ regs.u.r16.bx = regs.u.r16.dx;
+ break;
+ }
default: /* AH=0xE8?? but not implemented */
- goto int15_unimplemented;
- }
- break;
+ goto int15_unimplemented;
+ }
+ break;
int15_unimplemented:
// fall into the default
default:
diff --git a/tools/ioemu/target-i386-dm/exec-dm.c b/tools/ioemu/target-i386-dm/exec-dm.c
index 35891ed064..225f8b6f3a 100644
--- a/tools/ioemu/target-i386-dm/exec-dm.c
+++ b/tools/ioemu/target-i386-dm/exec-dm.c
@@ -450,6 +450,9 @@ static inline int paddr_is_ram(target_phys_addr_t addr)
#define phys_ram_addr(x) (phys_ram_base + (x))
#endif
+extern unsigned long *logdirty_bitmap;
+extern unsigned long logdirty_bitmap_size;
+
void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf,
int len, int is_write)
{
@@ -485,9 +488,20 @@ void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf,
l = 1;
}
} else if (paddr_is_ram(addr)) {
- /* Reading from RAM */
+ /* Writing to RAM */
ptr = phys_ram_addr(addr);
memcpy(ptr, buf, l);
+ if (logdirty_bitmap != NULL) {
+ /* Record that we have dirtied this frame */
+ unsigned long pfn = addr >> TARGET_PAGE_BITS;
+ if (pfn / 8 >= logdirty_bitmap_size) {
+ fprintf(logfile, "dirtying pfn %x >= bitmap size %x\n",
+ pfn, logdirty_bitmap_size * 8);
+ } else {
+ logdirty_bitmap[pfn / HOST_LONG_BITS]
+ |= 1UL << pfn % HOST_LONG_BITS;
+ }
+ }
#ifdef __ia64__
sync_icache(ptr, l);
#endif
diff --git a/tools/ioemu/target-i386-dm/helper2.c b/tools/ioemu/target-i386-dm/helper2.c
index 7a5f3412c9..17261e632d 100644
--- a/tools/ioemu/target-i386-dm/helper2.c
+++ b/tools/ioemu/target-i386-dm/helper2.c
@@ -439,6 +439,18 @@ void cpu_ioreq_xor(CPUState *env, ioreq_t *req)
req->data = tmp1;
}
+void cpu_ioreq_xchg(CPUState *env, ioreq_t *req)
+{
+ unsigned long tmp1;
+
+ if (req->data_is_ptr != 0)
+ hw_error("expected scalar value");
+
+ read_physical(req->addr, req->size, &tmp1);
+ write_physical(req->addr, req->size, &req->data);
+ req->data = tmp1;
+}
+
void __handle_ioreq(CPUState *env, ioreq_t *req)
{
if (!req->data_is_ptr && req->dir == IOREQ_WRITE && req->size != 4)
@@ -463,6 +475,9 @@ void __handle_ioreq(CPUState *env, ioreq_t *req)
case IOREQ_TYPE_XOR:
cpu_ioreq_xor(env, req);
break;
+ case IOREQ_TYPE_XCHG:
+ cpu_ioreq_xchg(env, req);
+ break;
default:
hw_error("Invalid ioreq type 0x%x\n", req->type);
}
diff --git a/tools/ioemu/xenstore.c b/tools/ioemu/xenstore.c
index edaf741c3d..26063f5a93 100644
--- a/tools/ioemu/xenstore.c
+++ b/tools/ioemu/xenstore.c
@@ -11,9 +11,14 @@
#include "vl.h"
#include "block_int.h"
#include <unistd.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
static struct xs_handle *xsh = NULL;
-static char *hd_filename[MAX_DISKS];
+static char *media_filename[MAX_DISKS];
static QEMUTimer *insert_timer = NULL;
#define UWAIT_MAX (30*1000000) /* thirty seconds */
@@ -40,10 +45,10 @@ static void insert_media(void *opaque)
int i;
for (i = 0; i < MAX_DISKS; i++) {
- if (hd_filename[i]) {
- do_change(bs_table[i]->device_name, hd_filename[i]);
- free(hd_filename[i]);
- hd_filename[i] = NULL;
+ if (media_filename[i] && bs_table[i]) {
+ do_change(bs_table[i]->device_name, media_filename[i]);
+ free(media_filename[i]);
+ media_filename[i] = NULL;
}
}
}
@@ -82,7 +87,7 @@ void xenstore_parse_domain_config(int domid)
unsigned int len, num, hd_index;
for(i = 0; i < MAX_DISKS; i++)
- hd_filename[i] = NULL;
+ media_filename[i] = NULL;
xsh = xs_daemon_open();
if (xsh == NULL) {
@@ -128,19 +133,12 @@ void xenstore_parse_domain_config(int domid)
continue;
free(type);
type = xs_read(xsh, XBT_NULL, buf, &len);
- /* read params to get the patch of the image -- read it last
- * so that we have its path in buf when setting up the
- * watch */
if (pasprintf(&buf, "%s/params", bpath) == -1)
continue;
free(params);
params = xs_read(xsh, XBT_NULL, buf, &len);
if (params == NULL)
continue;
- if (params[0]) {
- hd_filename[hd_index] = params; /* strdup() */
- params = NULL; /* don't free params on re-use */
- }
/*
* check if device has a phantom vbd; the phantom is hooked
* to the frontend device (for ease of cleanup), so lookup
@@ -151,38 +149,42 @@ void xenstore_parse_domain_config(int domid)
continue;
free(fpath);
fpath = xs_read(xsh, XBT_NULL, buf, &len);
- if (fpath != NULL) {
+ if (fpath) {
if (pasprintf(&buf, "%s/dev", fpath) == -1)
continue;
+ free(params);
params = xs_read(xsh, XBT_NULL, buf , &len);
- if (params != NULL) {
- free(hd_filename[hd_index]);
- hd_filename[hd_index] = params;
- params = NULL; /* don't free params on re-use */
+ if (params) {
/*
* wait for device, on timeout silently fail because we will
* fail to open below
*/
- waitForDevice(hd_filename[hd_index]);
+ waitForDevice(params);
}
}
+
bs_table[hd_index] = bdrv_new(dev);
- /* re-establish buf */
- if (pasprintf(&buf, "%s/params", bpath) == -1)
- continue;
/* check if it is a cdrom */
if (type && !strcmp(type, "cdrom")) {
bdrv_set_type_hint(bs_table[hd_index], BDRV_TYPE_CDROM);
- xs_watch(xsh, buf, dev);
+ if (pasprintf(&buf, "%s/params", bpath) != -1)
+ xs_watch(xsh, buf, dev);
}
- if (hd_filename[hd_index]) {
- if (bdrv_open(bs_table[hd_index], hd_filename[hd_index],
- 0 /* snapshot */) < 0)
+ /* open device now if media present */
+ if (params[0]) {
+ if (bdrv_open(bs_table[hd_index], params, 0 /* snapshot */) < 0)
fprintf(stderr, "qemu: could not open hard disk image '%s'\n",
- hd_filename[hd_index]);
+ params);
}
}
+ /* Set a watch for log-dirty requests from the migration tools */
+ if (pasprintf(&buf, "%s/logdirty/next-active", path) != -1) {
+ xs_watch(xsh, buf, "logdirty");
+ fprintf(logfile, "Watching %s\n", buf);
+ }
+
+
out:
free(type);
free(params);
@@ -201,6 +203,116 @@ int xenstore_fd(void)
return -1;
}
+unsigned long *logdirty_bitmap = NULL;
+unsigned long logdirty_bitmap_size;
+extern int vga_ram_size, bios_size;
+
+void xenstore_process_logdirty_event(void)
+{
+ char *act;
+ static char *active_path = NULL;
+ static char *next_active_path = NULL;
+ static char *seg = NULL;
+ unsigned int len;
+ int i;
+
+ fprintf(logfile, "Triggered log-dirty buffer switch\n");
+
+ if (!seg) {
+ char *path, *p, *key_ascii, key_terminated[17] = {0,};
+ key_t key;
+ int shmid;
+
+ /* Find and map the shared memory segment for log-dirty bitmaps */
+ if (!(path = xs_get_domain_path(xsh, domid))) {
+ fprintf(logfile, "Log-dirty: can't get domain path in store\n");
+ exit(1);
+ }
+ if (!(path = realloc(path, strlen(path)
+ + strlen("/logdirty/next-active") + 1))) {
+ fprintf(logfile, "Log-dirty: out of memory\n");
+ exit(1);
+ }
+ strcat(path, "/logdirty/");
+ p = path + strlen(path);
+ strcpy(p, "key");
+
+ key_ascii = xs_read(xsh, XBT_NULL, path, &len);
+ if (!key_ascii) {
+ /* No key yet: wait for the next watch */
+ free(path);
+ return;
+ }
+ strncpy(key_terminated, key_ascii, 16);
+ free(key_ascii);
+ key = (key_t) strtoull(key_terminated, NULL, 16);
+
+ /* Figure out how bit the log-dirty bitmaps are */
+ logdirty_bitmap_size = ((phys_ram_size + 0x20
+ - (vga_ram_size + bios_size))
+ >> (TARGET_PAGE_BITS)); /* nr of bits in map*/
+ if (logdirty_bitmap_size > HVM_BELOW_4G_MMIO_START >> TARGET_PAGE_BITS)
+ logdirty_bitmap_size +=
+ HVM_BELOW_4G_MMIO_LENGTH >> TARGET_PAGE_BITS; /* still bits */
+ logdirty_bitmap_size = ((logdirty_bitmap_size + HOST_LONG_BITS - 1)
+ / HOST_LONG_BITS); /* longs */
+ logdirty_bitmap_size *= sizeof (unsigned long); /* bytes */
+
+ /* Map the shared-memory segment */
+ if ((shmid = shmget(key,
+ 2 * logdirty_bitmap_size,
+ S_IRUSR|S_IWUSR)) == -1
+ || (seg = shmat(shmid, NULL, 0)) == (void *)-1) {
+ fprintf(logfile, "Log-dirty: can't map segment %16.16llx (%s)\n",
+ (unsigned long long) key, strerror(errno));
+ exit(1);
+ }
+
+ fprintf(logfile, "Log-dirty: mapped segment at %p\n", seg);
+
+ /* Double-check that the bitmaps are the size we expect */
+ if (logdirty_bitmap_size != *(uint32_t *)seg) {
+ fprintf(logfile, "Log-dirty: got %lu, calc %lu\n",
+ *(uint32_t *)seg, logdirty_bitmap_size);
+ return;
+ }
+
+ /* Remember the paths for the next-active and active entries */
+ strcpy(p, "active");
+ if (!(active_path = strdup(path))) {
+ fprintf(logfile, "Log-dirty: out of memory\n");
+ exit(1);
+ }
+ strcpy(p, "next-active");
+ if (!(next_active_path = strdup(path))) {
+ fprintf(logfile, "Log-dirty: out of memory\n");
+ exit(1);
+ }
+ free(path);
+ }
+
+ /* Read the required active buffer from the store */
+ act = xs_read(xsh, XBT_NULL, next_active_path, &len);
+ if (!act) {
+ fprintf(logfile, "Log-dirty: can't read next-active\n");
+ exit(1);
+ }
+
+ /* Switch buffers */
+ i = act[0] - '0';
+ if (i != 0 && i != 1) {
+ fprintf(logfile, "Log-dirty: bad next-active entry: %s\n", act);
+ exit(1);
+ }
+ logdirty_bitmap = seg + i * logdirty_bitmap_size;
+
+ /* Ack that we've switched */
+ xs_write(xsh, XBT_NULL, active_path, act, len);
+ free(act);
+}
+
+
+
void xenstore_process_event(void *opaque)
{
char **vec, *image = NULL;
@@ -210,6 +322,11 @@ void xenstore_process_event(void *opaque)
if (!vec)
return;
+ if (!strcmp(vec[XS_WATCH_TOKEN], "logdirty")) {
+ xenstore_process_logdirty_event();
+ goto out;
+ }
+
if (strncmp(vec[XS_WATCH_TOKEN], "hd", 2) ||
strlen(vec[XS_WATCH_TOKEN]) != 3)
goto out;
@@ -220,13 +337,13 @@ void xenstore_process_event(void *opaque)
do_eject(0, vec[XS_WATCH_TOKEN]);
bs_table[hd_index]->filename[0] = 0;
- if (hd_filename[hd_index]) {
- free(hd_filename[hd_index]);
- hd_filename[hd_index] = NULL;
+ if (media_filename[hd_index]) {
+ free(media_filename[hd_index]);
+ media_filename[hd_index] = NULL;
}
if (image[0]) {
- hd_filename[hd_index] = strdup(image);
+ media_filename[hd_index] = strdup(image);
xenstore_check_new_media_present(5000);
}
diff --git a/tools/libxc/Makefile b/tools/libxc/Makefile
index 6dc76ae782..04705086de 100644
--- a/tools/libxc/Makefile
+++ b/tools/libxc/Makefile
@@ -57,7 +57,7 @@ GUEST_SRCS-$(CONFIG_IA64) += xc_dom_compat_linux.c
CFLAGS += -Werror -Wmissing-prototypes
CFLAGS += -fno-strict-aliasing
-CFLAGS += $(INCLUDES) -I.
+CFLAGS += $(INCLUDES) -I. -I../xenstore
# Needed for posix_fadvise64() in xc_linux.c
CFLAGS-$(CONFIG_Linux) += -D_GNU_SOURCE
diff --git a/tools/libxc/xc_core.c b/tools/libxc/xc_core.c
index 3dcf51e131..3c1ff185a6 100644
--- a/tools/libxc/xc_core.c
+++ b/tools/libxc/xc_core.c
@@ -349,11 +349,7 @@ xc_domain_dumpcore_via_callback(int xc_handle,
/* 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
- )
+ if ( !live_shinfo && !info.hvm )
{
PERROR("Couldn't map live_shinfo");
goto out;
diff --git a/tools/libxc/xc_core_x86.c b/tools/libxc/xc_core_x86.c
index 6ea775aef6..bd82110713 100644
--- a/tools/libxc/xc_core_x86.c
+++ b/tools/libxc/xc_core_x86.c
@@ -21,12 +21,15 @@
#include "xg_private.h"
#include "xc_core.h"
+static int max_gpfn(int xc_handle, domid_t domid)
+{
+ return xc_memory_op(xc_handle, XENMEM_maximum_gpfn, &domid);
+}
+
int
xc_core_arch_auto_translated_physmap(const xc_dominfo_t *info)
{
- if ( info->hvm )
- return 1;
- return 0;
+ return info->hvm;
}
int
@@ -35,14 +38,14 @@ xc_core_arch_memory_map_get(int xc_handle, xc_dominfo_t *info,
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;
+ unsigned long max_pfn = max_gpfn(xc_handle, info->domid);
+ xc_core_memory_map_t *map;
map = malloc(sizeof(*map));
- if ( !map )
+ if ( map == NULL )
{
PERROR("Could not allocate memory");
- goto out;
+ return -1;
}
map->addr = 0;
@@ -51,11 +54,6 @@ xc_core_arch_memory_map_get(int xc_handle, xc_dominfo_t *info,
*mapp = map;
*nr_entries = 1;
return 0;
-
-out:
- if ( map )
- free(map);
- return -1;
}
int
@@ -67,7 +65,7 @@ xc_core_arch_map_p2m(int xc_handle, xc_dominfo_t *info,
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;
+ unsigned long max_pfn = max_gpfn(xc_handle, info->domid);
int ret = -1;
int err;
diff --git a/tools/libxc/xc_hvm_build.c b/tools/libxc/xc_hvm_build.c
index 00f4624501..751aa9cf7a 100644
--- a/tools/libxc/xc_hvm_build.c
+++ b/tools/libxc/xc_hvm_build.c
@@ -137,6 +137,12 @@ static void build_e820map(void *e820_page, unsigned long long mem_size)
e820entry[nr_map].type = E820_RAM;
nr_map++;
+ /* Explicitly reserve space for special pages (ioreq and xenstore). */
+ e820entry[nr_map].addr = mem_size - PAGE_SIZE * 3;
+ e820entry[nr_map].size = PAGE_SIZE * 3;
+ e820entry[nr_map].type = E820_RESERVED;
+ nr_map++;
+
if ( extra_mem_size )
{
e820entry[nr_map].addr = (1ULL << 32);
@@ -280,7 +286,6 @@ 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 )
diff --git a/tools/libxc/xc_hvm_restore.c b/tools/libxc/xc_hvm_restore.c
index 0dafa82874..4b54b0aaf5 100644
--- a/tools/libxc/xc_hvm_restore.c
+++ b/tools/libxc/xc_hvm_restore.c
@@ -70,9 +70,6 @@ int xc_hvm_restore(int xc_handle, int io_fd,
{
DECLARE_DOMCTL;
- /* The new domain's shared-info frame number. */
- unsigned long shared_info_frame;
-
/* A copy of the CPU context of the guest. */
vcpu_guest_context_t ctxt;
@@ -86,8 +83,6 @@ 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;
@@ -96,8 +91,6 @@ int xc_hvm_restore(int xc_handle, int io_fd,
/* Types of the pfns in the current region */
unsigned long region_pfn_type[MAX_BATCH_SIZE];
- struct xen_add_to_physmap xatp;
-
/* Number of pages of memory the guest has. *Not* the same as max_pfn. */
unsigned long nr_pages;
@@ -146,7 +139,6 @@ int xc_hvm_restore(int xc_handle, int io_fd,
pfns[i] = i;
for ( i = HVM_BELOW_4G_RAM_END >> PAGE_SHIFT; i < pfn_array_size; i++ )
pfns[i] += HVM_BELOW_4G_MMIO_LENGTH >> PAGE_SHIFT;
- arch_max_pfn = pfns[max_pfn];/* used later */
/* Allocate memory for HVM guest, skipping VGA hole 0xA0000-0xC0000. */
rc = xc_domain_memory_populate_physmap(
@@ -350,29 +342,6 @@ int xc_hvm_restore(int xc_handle, int io_fd,
goto out;
}
- /* Shared-info pfn */
- if (!read_exact(io_fd, &(shared_info_frame), sizeof(uint32_t)) ) {
- ERROR("reading the shared-info pfn failed!\n");
- goto out;
- }
- /* Map the shared-info frame where it was before */
- xatp.domid = dom;
- xatp.space = XENMAPSPACE_shared_info;
- xatp.idx = 0;
- xatp.gpfn = shared_info_frame;
- if ( (rc = xc_memory_op(xc_handle, XENMEM_add_to_physmap, &xatp)) != 0 ) {
- 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 ac06db72a1..75a017cf7c 100644
--- a/tools/libxc/xc_hvm_save.c
+++ b/tools/libxc/xc_hvm_save.c
@@ -54,6 +54,11 @@ static unsigned long hvirt_start;
/* #levels of page tables used by the current guest */
static unsigned int pt_levels;
+/* Shared-memory bitmaps for getting log-dirty bits from qemu */
+static unsigned long *qemu_bitmaps[2];
+static int qemu_active;
+static int qemu_non_active;
+
int xc_hvm_drain_io(int handle, domid_t dom)
{
DECLARE_HYPERCALL;
@@ -77,7 +82,8 @@ int xc_hvm_drain_io(int handle, domid_t dom)
*/
#define BITS_PER_LONG (sizeof(unsigned long) * 8)
-#define BITMAP_SIZE ((pfn_array_size + BITS_PER_LONG - 1) / 8)
+#define BITS_TO_LONGS(bits) (((bits)+BITS_PER_LONG-1)/BITS_PER_LONG)
+#define BITMAP_SIZE (BITS_TO_LONGS(pfn_array_size) * sizeof(unsigned long))
#define BITMAP_ENTRY(_nr,_bmap) \
((unsigned long *)(_bmap))[(_nr)/BITS_PER_LONG]
@@ -124,6 +130,7 @@ static inline int permute( int i, int nr, int order_nr )
return i;
}
+
static uint64_t tv_to_us(struct timeval *new)
{
return (new->tv_sec * 1000000) + new->tv_usec;
@@ -277,7 +284,9 @@ static int suspend_and_state(int (*suspend)(int), int xc_handle, int io_fd,
}
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))
+ uint32_t max_factor, uint32_t flags, int (*suspend)(int),
+ void *(*init_qemu_maps)(int, unsigned),
+ void (*qemu_flip_buffer)(int, int))
{
xc_dominfo_t info;
@@ -293,9 +302,6 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
/* The size of an array big enough to contain all guest pfns */
unsigned long pfn_array_size;
- /* The new domain's shared-info frame number. */
- unsigned long shared_info_frame;
-
/* Other magic frames: ioreqs and xenstore comms */
unsigned long ioreq_pfn, bufioreq_pfn, store_pfn;
@@ -309,9 +315,6 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
uint32_t hvm_buf_size;
uint8_t *hvm_buf = NULL;
- /* Live mapping of shared info structure */
- shared_info_t *live_shinfo = NULL;
-
/* base of the region in which domain memory is mapped */
unsigned char *region_base = NULL;
@@ -363,7 +366,6 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
ERROR("HVM:Could not get vcpu context");
goto out;
}
- shared_info_frame = info.shared_info_frame;
/* cheesy sanity check */
if ((info.max_memkb >> (PAGE_SHIFT - 10)) > max_mfn) {
@@ -372,13 +374,6 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
goto out;
}
- /* Map the shared info frame */
- if(!(live_shinfo = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE,
- PROT_READ, shared_info_frame))) {
- ERROR("HVM:Couldn't map live_shinfo");
- goto out;
- }
-
if ( xc_get_hvm_param(xc_handle, dom, HVM_PARAM_STORE_PFN, &store_pfn)
|| xc_get_hvm_param(xc_handle, dom, HVM_PARAM_IOREQ_PFN, &ioreq_pfn)
|| xc_get_hvm_param(xc_handle, dom,
@@ -392,8 +387,6 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
"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");
- goto out;
if (xc_shadow_control(xc_handle, dom,
XEN_DOMCTL_SHADOW_OP_ENABLE_LOGDIRTY,
@@ -453,6 +446,15 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
to_skip = malloc(BITMAP_SIZE);
+ if (live) {
+ /* Get qemu-dm logging dirty pages too */
+ void *seg = init_qemu_maps(dom, BITMAP_SIZE);
+ qemu_bitmaps[0] = seg;
+ qemu_bitmaps[1] = seg + BITMAP_SIZE;
+ qemu_active = 0;
+ qemu_non_active = 1;
+ }
+
hvm_buf_size = xc_domain_hvm_getcontext(xc_handle, dom, 0, 0);
if ( hvm_buf_size == -1 )
{
@@ -509,13 +511,6 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
DPRINTF("Saving HVM domain memory pages: iter %d 0%%", iter);
- if (last_iter && (max_pfn != live_shinfo->arch.max_pfn)) {
- DPRINTF("calculated max_pfn as %#lx, shinfo says %#lx\n",
- max_pfn, live_shinfo->arch.max_pfn);
- ERROR("Max pfn doesn't match shared info");
- goto out;
- }
-
while( N < pfn_array_size ){
unsigned int this_pc = (N * 100) / pfn_array_size;
@@ -663,8 +658,7 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
goto out;
}
- DPRINTF("SUSPEND shinfo %08lx eip %08lx edx %08lx\n",
- info.shared_info_frame,
+ DPRINTF("SUSPEND eip %08lx edx %08lx\n",
(unsigned long)ctxt.user_regs.eip,
(unsigned long)ctxt.user_regs.edx);
}
@@ -677,10 +671,23 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
goto out;
}
+ /* Pull in the dirty bits from qemu too */
+ if (!last_iter) {
+ qemu_active = qemu_non_active;
+ qemu_non_active = qemu_active ? 0 : 1;
+ qemu_flip_buffer(dom, qemu_active);
+ for (j = 0; j < BITMAP_SIZE / sizeof(unsigned long); j++) {
+ to_send[j] |= qemu_bitmaps[qemu_non_active][j];
+ qemu_bitmaps[qemu_non_active][j] = 0;
+ }
+ } else {
+ for (j = 0; j < BITMAP_SIZE / sizeof(unsigned long); j++)
+ to_send[j] |= qemu_bitmaps[qemu_active][j];
+ }
+
sent_last_iter = sent_this_iter;
print_stats(xc_handle, dom, sent_this_iter, &stats, 1);
-
}
@@ -739,12 +746,6 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
ERROR("write HVM info failed!\n");
}
- /* Shared-info pfn */
- if (!write_exact(io_fd, &(shared_info_frame), sizeof(uint32_t)) ) {
- ERROR("write shared-info pfn failed!\n");
- goto out;
- }
-
/* Success! */
rc = 0;
diff --git a/tools/libxc/xc_private.c b/tools/libxc/xc_private.c
index 3816b0a83b..3e2557e581 100644
--- a/tools/libxc/xc_private.c
+++ b/tools/libxc/xc_private.c
@@ -263,6 +263,15 @@ int xc_memory_op(int xc_handle,
goto out1;
}
break;
+ case XENMEM_current_reservation:
+ case XENMEM_maximum_reservation:
+ case XENMEM_maximum_gpfn:
+ if ( lock_pages(arg, sizeof(domid_t)) )
+ {
+ PERROR("Could not lock");
+ goto out1;
+ }
+ break;
}
ret = do_xen_hypercall(xc_handle, &hypercall);
@@ -287,6 +296,11 @@ int xc_memory_op(int xc_handle,
case XENMEM_add_to_physmap:
unlock_pages(arg, sizeof(struct xen_add_to_physmap));
break;
+ case XENMEM_current_reservation:
+ case XENMEM_maximum_reservation:
+ case XENMEM_maximum_gpfn:
+ unlock_pages(arg, sizeof(domid_t));
+ break;
}
out1:
diff --git a/tools/libxc/xenguest.h b/tools/libxc/xenguest.h
index 5b6e7c6d2a..76b7413f15 100644
--- a/tools/libxc/xenguest.h
+++ b/tools/libxc/xenguest.h
@@ -32,8 +32,10 @@ int xc_linux_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
* @return 0 on success, -1 on failure
*/
int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
- uint32_t max_factor, uint32_t flags /* XCFLAGS_xxx */,
- int (*suspend)(int domid));
+ uint32_t max_factor, uint32_t flags /* XCFLAGS_xxx */,
+ int (*suspend)(int domid),
+ void *(*init_qemu_maps)(int, unsigned),
+ void (*qemu_flip_buffer)(int, int));
/**
* This function will restore a saved domain running Linux.
diff --git a/tools/libxc/xg_private.c b/tools/libxc/xg_private.c
index 2332ef4c6c..1014131004 100644
--- a/tools/libxc/xg_private.c
+++ b/tools/libxc/xg_private.c
@@ -201,7 +201,9 @@ __attribute__((weak))
__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 (*suspend)(int domid),
+ void *(*init_qemu_maps)(int, unsigned),
+ void (*qemu_flip_buffer)(int, int))
{
errno = ENOSYS;
return -1;
diff --git a/tools/libxen/include/xen_vbd.h b/tools/libxen/include/xen_vbd.h
index 7b36266a04..14a6685a95 100644
--- a/tools/libxen/include/xen_vbd.h
+++ b/tools/libxen/include/xen_vbd.h
@@ -72,7 +72,6 @@ typedef struct xen_vbd_record
struct xen_vm_record_opt *vm;
struct xen_vdi_record_opt *vdi;
char *device;
- char *image;
bool bootable;
enum xen_vbd_mode mode;
enum xen_vbd_type type;
diff --git a/tools/libxen/include/xen_vdi.h b/tools/libxen/include/xen_vdi.h
index 26e147250e..9ebb8fd9ee 100644
--- a/tools/libxen/include/xen_vdi.h
+++ b/tools/libxen/include/xen_vdi.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
@@ -22,6 +22,7 @@
#include "xen_common.h"
#include "xen_crashdump_decl.h"
#include "xen_sr_decl.h"
+#include "xen_string_string_map.h"
#include "xen_vbd_decl.h"
#include "xen_vdi_decl.h"
#include "xen_vdi_type.h"
@@ -73,11 +74,10 @@ typedef struct xen_vdi_record
struct xen_crashdump_record_opt_set *crash_dumps;
int64_t virtual_size;
int64_t physical_utilisation;
- int64_t sector_size;
- char *location;
enum xen_vdi_type type;
bool sharable;
bool read_only;
+ xen_string_string_map *other_config;
} xen_vdi_record;
/**
@@ -251,13 +251,6 @@ xen_vdi_get_physical_utilisation(xen_session *session, int64_t *result, xen_vdi
/**
- * Get the sector_size field of the given VDI.
- */
-extern bool
-xen_vdi_get_sector_size(xen_session *session, int64_t *result, xen_vdi vdi);
-
-
-/**
* Get the type field of the given VDI.
*/
extern bool
@@ -279,6 +272,13 @@ xen_vdi_get_read_only(xen_session *session, bool *result, xen_vdi vdi);
/**
+ * Get the other_config field of the given VDI.
+ */
+extern bool
+xen_vdi_get_other_config(xen_session *session, xen_string_string_map **result, xen_vdi vdi);
+
+
+/**
* Set the name/label field of the given VDI.
*/
extern bool
@@ -314,6 +314,30 @@ xen_vdi_set_read_only(xen_session *session, xen_vdi vdi, bool read_only);
/**
+ * Set the other_config field of the given VDI.
+ */
+extern bool
+xen_vdi_set_other_config(xen_session *session, xen_vdi vdi, xen_string_string_map *other_config);
+
+
+/**
+ * Add the given key-value pair to the other_config field of the given
+ * VDI.
+ */
+extern bool
+xen_vdi_add_to_other_config(xen_session *session, xen_vdi vdi, char *key, char *value);
+
+
+/**
+ * Remove the given key and its corresponding value from the
+ * other_config field of the given VDI. If the key is not in that Map, then
+ * do nothing.
+ */
+extern bool
+xen_vdi_remove_from_other_config(xen_session *session, xen_vdi vdi, char *key);
+
+
+/**
* Take an exact copy of the VDI; the snapshot lives in the same
* Storage Repository as its parent.
*/
diff --git a/tools/libxen/src/xen_vbd.c b/tools/libxen/src/xen_vbd.c
index 300f1d857d..893bf70958 100644
--- a/tools/libxen/src/xen_vbd.c
+++ b/tools/libxen/src/xen_vbd.c
@@ -54,9 +54,6 @@ static const struct_member xen_vbd_record_struct_members[] =
{ .key = "device",
.type = &abstract_type_string,
.offset = offsetof(xen_vbd_record, device) },
- { .key = "image",
- .type = &abstract_type_string,
- .offset = offsetof(xen_vbd_record, image) },
{ .key = "bootable",
.type = &abstract_type_bool,
.offset = offsetof(xen_vbd_record, bootable) },
diff --git a/tools/libxen/src/xen_vdi.c b/tools/libxen/src/xen_vdi.c
index 2e50db9e80..10f3fc4066 100644
--- a/tools/libxen/src/xen_vdi.c
+++ b/tools/libxen/src/xen_vdi.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,6 +24,7 @@
#include "xen_crashdump.h"
#include "xen_internal.h"
#include "xen_sr.h"
+#include "xen_string_string_map.h"
#include "xen_vbd.h"
#include "xen_vdi.h"
#include "xen_vdi_type_internal.h"
@@ -64,12 +65,6 @@ static const struct_member xen_vdi_record_struct_members[] =
{ .key = "physical_utilisation",
.type = &abstract_type_int,
.offset = offsetof(xen_vdi_record, physical_utilisation) },
- { .key = "sector_size",
- .type = &abstract_type_int,
- .offset = offsetof(xen_vdi_record, sector_size) },
- { .key = "location",
- .type = &abstract_type_string,
- .offset = offsetof(xen_vdi_record, location) },
{ .key = "type",
.type = &xen_vdi_type_abstract_type_,
.offset = offsetof(xen_vdi_record, type) },
@@ -78,7 +73,10 @@ static const struct_member xen_vdi_record_struct_members[] =
.offset = offsetof(xen_vdi_record, sharable) },
{ .key = "read_only",
.type = &abstract_type_bool,
- .offset = offsetof(xen_vdi_record, read_only) }
+ .offset = offsetof(xen_vdi_record, read_only) },
+ { .key = "other_config",
+ .type = &abstract_type_string_string_map,
+ .offset = offsetof(xen_vdi_record, other_config) }
};
const abstract_type xen_vdi_record_abstract_type_ =
@@ -105,6 +103,7 @@ xen_vdi_record_free(xen_vdi_record *record)
xen_sr_record_opt_free(record->sr);
xen_vbd_record_opt_set_free(record->vbds);
xen_crashdump_record_opt_set_free(record->crash_dumps);
+ xen_string_string_map_free(record->other_config);
free(record);
}
@@ -315,7 +314,7 @@ xen_vdi_get_physical_utilisation(xen_session *session, int64_t *result, xen_vdi
bool
-xen_vdi_get_sector_size(xen_session *session, int64_t *result, xen_vdi vdi)
+xen_vdi_get_type(xen_session *session, enum xen_vdi_type *result, xen_vdi vdi)
{
abstract_value param_values[] =
{
@@ -323,15 +322,14 @@ xen_vdi_get_sector_size(xen_session *session, int64_t *result, xen_vdi vdi)
.u.string_val = vdi }
};
- abstract_type result_type = abstract_type_int;
-
- XEN_CALL_("VDI.get_sector_size");
+ abstract_type result_type = xen_vdi_type_abstract_type_;
+ XEN_CALL_("VDI.get_type");
return session->ok;
}
bool
-xen_vdi_get_type(xen_session *session, enum xen_vdi_type *result, xen_vdi vdi)
+xen_vdi_get_sharable(xen_session *session, bool *result, xen_vdi vdi)
{
abstract_value param_values[] =
{
@@ -339,14 +337,15 @@ xen_vdi_get_type(xen_session *session, enum xen_vdi_type *result, xen_vdi vdi)
.u.string_val = vdi }
};
- abstract_type result_type = xen_vdi_type_abstract_type_;
- XEN_CALL_("VDI.get_type");
+ abstract_type result_type = abstract_type_bool;
+
+ XEN_CALL_("VDI.get_sharable");
return session->ok;
}
bool
-xen_vdi_get_sharable(xen_session *session, bool *result, xen_vdi vdi)
+xen_vdi_get_read_only(xen_session *session, bool *result, xen_vdi vdi)
{
abstract_value param_values[] =
{
@@ -356,13 +355,13 @@ xen_vdi_get_sharable(xen_session *session, bool *result, xen_vdi vdi)
abstract_type result_type = abstract_type_bool;
- XEN_CALL_("VDI.get_sharable");
+ XEN_CALL_("VDI.get_read_only");
return session->ok;
}
bool
-xen_vdi_get_read_only(xen_session *session, bool *result, xen_vdi vdi)
+xen_vdi_get_other_config(xen_session *session, xen_string_string_map **result, xen_vdi vdi)
{
abstract_value param_values[] =
{
@@ -370,9 +369,10 @@ xen_vdi_get_read_only(xen_session *session, bool *result, xen_vdi vdi)
.u.string_val = vdi }
};
- abstract_type result_type = abstract_type_bool;
+ abstract_type result_type = abstract_type_string_string_map;
- XEN_CALL_("VDI.get_read_only");
+ *result = NULL;
+ XEN_CALL_("VDI.get_other_config");
return session->ok;
}
@@ -458,6 +458,56 @@ xen_vdi_set_read_only(xen_session *session, xen_vdi vdi, bool read_only)
bool
+xen_vdi_set_other_config(xen_session *session, xen_vdi vdi, xen_string_string_map *other_config)
+{
+ abstract_value param_values[] =
+ {
+ { .type = &abstract_type_string,
+ .u.string_val = vdi },
+ { .type = &abstract_type_string_string_map,
+ .u.set_val = (arbitrary_set *)other_config }
+ };
+
+ xen_call_(session, "VDI.set_other_config", param_values, 2, NULL, NULL);
+ return session->ok;
+}
+
+
+bool
+xen_vdi_add_to_other_config(xen_session *session, xen_vdi vdi, char *key, char *value)
+{
+ abstract_value param_values[] =
+ {
+ { .type = &abstract_type_string,
+ .u.string_val = vdi },
+ { .type = &abstract_type_string,
+ .u.string_val = key },
+ { .type = &abstract_type_string,
+ .u.string_val = value }
+ };
+
+ xen_call_(session, "VDI.add_to_other_config", param_values, 3, NULL, NULL);
+ return session->ok;
+}
+
+
+bool
+xen_vdi_remove_from_other_config(xen_session *session, xen_vdi vdi, char *key)
+{
+ abstract_value param_values[] =
+ {
+ { .type = &abstract_type_string,
+ .u.string_val = vdi },
+ { .type = &abstract_type_string,
+ .u.string_val = key }
+ };
+
+ xen_call_(session, "VDI.remove_from_other_config", param_values, 2, NULL, NULL);
+ return session->ok;
+}
+
+
+bool
xen_vdi_snapshot(xen_session *session, xen_vdi *result, xen_vdi vdi)
{
abstract_value param_values[] =
diff --git a/tools/libxen/test/test_bindings.c b/tools/libxen/test/test_bindings.c
index f18c5c5ac5..92f2d9b6ca 100644
--- a/tools/libxen/test/test_bindings.c
+++ b/tools/libxen/test/test_bindings.c
@@ -421,8 +421,7 @@ static xen_vm create_new_vm(xen_session *session, bool hvm)
.name_label = "MyRootFS",
.name_description = "MyRootFS description",
.sr = &sr_record,
- .virtual_size = (1 << 21), // 1GiB / 512 bytes/sector
- .sector_size = 512,
+ .virtual_size = (INT64_C(1) << 30), // 1GiB
.type = XEN_VDI_TYPE_SYSTEM,
.sharable = false,
.read_only = false
diff --git a/tools/python/scripts/test_hvm_create.py b/tools/python/scripts/test_hvm_create.py
index 7cae70539a..35abfe0396 100644
--- a/tools/python/scripts/test_hvm_create.py
+++ b/tools/python/scripts/test_hvm_create.py
@@ -39,14 +39,13 @@ vm_cfg = {
local_vdi_cfg = {
'name_label': 'gentoo.hvm',
'name_description': '',
- 'location': 'file:/root/gentoo.amd64.hvm.img',
'virtual_size': 0,
- 'sector_size': 0,
'type': 'system',
'parent': '',
'SR_name': 'Local',
'sharable': False,
'read_only': False,
+ 'other_config': {'location': 'file:/root/gentoo.amd64.hvm.img'},
}
local_vbd_cfg = {
diff --git a/tools/python/scripts/test_vm_create.py b/tools/python/scripts/test_vm_create.py
index e4d8f3023a..6575f153ea 100644
--- a/tools/python/scripts/test_vm_create.py
+++ b/tools/python/scripts/test_vm_create.py
@@ -39,8 +39,7 @@ vm_cfg = {
vdi_cfg = {
'name_label': 'API_VDI',
'name_description': '',
- 'virtual_size': 100 * 1024 * 1024,
- 'sector_size': 1024,
+ 'virtual_size': 100 * 1024 * 1024 * 1024,
'type': 'system',
'parent': '',
'SR_name': 'QCoW',
@@ -60,14 +59,13 @@ vbd_cfg = {
local_vdi_cfg = {
'name_label': 'gentoo.amd64.img',
'name_description': '',
- 'location': 'file:/root/gentoo.amd64.img',
'virtual_size': 0,
- 'sector_size': 0,
'type': 'system',
'parent': '',
'SR_name': 'Local',
'sharable': False,
'read_only': False,
+ 'other_config': {'location': 'file:/root/gentoo.amd64.img'},
}
local_vbd_cfg = {
diff --git a/tools/python/scripts/xapi.py b/tools/python/scripts/xapi.py
index 1e49f86d4c..1a07795212 100644
--- a/tools/python/scripts/xapi.py
+++ b/tools/python/scripts/xapi.py
@@ -40,8 +40,7 @@ VM_LIST_FORMAT = '%(name_label)-18s %(memory_actual)-5s %(VCPUs_number)-5s'\
' %(power_state)-10s %(uuid)-36s'
SR_LIST_FORMAT = '%(name_label)-18s %(uuid)-36s %(physical_size)-10s' \
'%(type)-10s'
-VDI_LIST_FORMAT = '%(name_label)-18s %(uuid)-36s %(virtual_size)-8s '\
- '%(sector_size)-8s'
+VDI_LIST_FORMAT = '%(name_label)-18s %(uuid)-36s %(virtual_size)-8s'
VBD_LIST_FORMAT = '%(device)-6s %(uuid)-36s %(VDI)-8s'
TASK_LIST_FORMAT = '%(name_label)-18s %(uuid)-36s %(status)-8s %(progress)-4s'
VIF_LIST_FORMAT = '%(name)-8s %(device)-7s %(uuid)-36s %(MAC)-10s'
@@ -96,12 +95,9 @@ OPTIONS = {
'vdi-create': [(('--name-label',), {'help': 'Name for VDI'}),
(('--name-description',), {'help': 'Description for VDI'}),
- (('--sector-size',), {'type': 'int',
- 'help': 'Sector size',
- 'default': 0}),
(('--virtual-size',), {'type': 'int',
'default': 0,
- 'help': 'Size of VDI in sectors'}),
+ 'help': 'Size of VDI in bytes'}),
(('--type',), {'choices': ['system', 'user', 'ephemeral'],
'default': 'system',
'help': 'VDI type'}),
@@ -569,8 +565,7 @@ def xapi_vdi_list(args, async = False):
if not is_long:
print VDI_LIST_FORMAT % {'name_label': 'VDI Label',
'uuid' : 'UUID',
- 'virtual_size': 'Bytes',
- 'sector_size': 'Sector Size'}
+ 'virtual_size': 'Bytes'}
for vdi in vdis:
vdi_struct = execute(server, 'VDI.get_record', (session, vdi))
diff --git a/tools/python/scripts/xapi.vdicfg.py b/tools/python/scripts/xapi.vdicfg.py
index 86129bfae9..cb63653550 100644
--- a/tools/python/scripts/xapi.vdicfg.py
+++ b/tools/python/scripts/xapi.vdicfg.py
@@ -1,7 +1,6 @@
name_label = 'VDI 1'
name_description = ''
-virtual_size = 10 * 1024 * 1024
-sector_size = 1024
+virtual_size = 10 * 1024 * 1024 * 1024
type = 'system'
sharable = False
read_only = False
diff --git a/tools/python/xen/lowlevel/xc/xc.c b/tools/python/xen/lowlevel/xc/xc.c
index 804adc3104..e3b3d4c0e6 100644
--- a/tools/python/xen/lowlevel/xc/xc.c
+++ b/tools/python/xen/lowlevel/xc/xc.c
@@ -50,17 +50,21 @@ static PyObject *pyxc_error_to_exception(void)
const xc_error *err = xc_get_last_error();
const char *desc = xc_error_code_to_desc(err->code);
- if (err->code == XC_ERROR_NONE)
+ if ( err->code == XC_ERROR_NONE )
return PyErr_SetFromErrno(xc_error_obj);
- if (err->message[0] != '\0')
+ if ( err->message[0] != '\0' )
pyerr = Py_BuildValue("(iss)", err->code, desc, err->message);
else
pyerr = Py_BuildValue("(is)", err->code, desc);
xc_clear_last_error();
- PyErr_SetObject(xc_error_obj, pyerr);
+ if ( pyerr != NULL )
+ {
+ PyErr_SetObject(xc_error_obj, pyerr);
+ Py_DECREF(pyerr);
+ }
return NULL;
}
@@ -70,13 +74,13 @@ static PyObject *pyxc_domain_dumpcore(XcObject *self, PyObject *args)
uint32_t dom;
char *corefile;
- if (!PyArg_ParseTuple(args, "is", &dom, &corefile))
+ if ( !PyArg_ParseTuple(args, "is", &dom, &corefile) )
return NULL;
if ( (corefile == NULL) || (corefile[0] == '\0') )
return NULL;
- if (xc_domain_dumpcore(self->xc_handle, dom, corefile) != 0)
+ if ( xc_domain_dumpcore(self->xc_handle, dom, corefile) != 0 )
return pyxc_error_to_exception();
Py_INCREF(zero);
@@ -168,10 +172,10 @@ static PyObject *pyxc_domain_shutdown(XcObject *self, PyObject *args)
{
uint32_t dom, reason;
- if (!PyArg_ParseTuple(args, "ii", &dom, &reason))
+ if ( !PyArg_ParseTuple(args, "ii", &dom, &reason) )
return NULL;
- if (xc_domain_shutdown(self->xc_handle, dom, reason) != 0)
+ if ( xc_domain_shutdown(self->xc_handle, dom, reason) != 0 )
return pyxc_error_to_exception();
Py_INCREF(zero);
@@ -183,10 +187,10 @@ static PyObject *pyxc_domain_resume(XcObject *self, PyObject *args)
uint32_t dom;
int fast;
- if (!PyArg_ParseTuple(args, "ii", &dom, &fast))
+ if ( !PyArg_ParseTuple(args, "ii", &dom, &fast) )
return NULL;
- if (xc_domain_resume(self->xc_handle, dom, fast) != 0)
+ if ( xc_domain_resume(self->xc_handle, dom, fast) != 0 )
return pyxc_error_to_exception();
Py_INCREF(zero);
@@ -282,7 +286,7 @@ static PyObject *pyxc_domain_getinfo(XcObject *self,
PyObject *args,
PyObject *kwds)
{
- PyObject *list, *info_dict;
+ PyObject *list, *info_dict, *pyhandle;
uint32_t first_dom = 0;
int max_doms = 1024, nr_doms, i, j;
@@ -308,26 +312,34 @@ static PyObject *pyxc_domain_getinfo(XcObject *self,
list = PyList_New(nr_doms);
for ( i = 0 ; i < nr_doms; i++ )
{
- PyObject *pyhandle = PyList_New(sizeof(xen_domain_handle_t));
+ info_dict = Py_BuildValue(
+ "{s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i"
+ ",s:L,s:L,s:L,s:i,s:i}",
+ "domid", (int)info[i].domid,
+ "online_vcpus", info[i].nr_online_vcpus,
+ "max_vcpu_id", info[i].max_vcpu_id,
+ "hvm", info[i].hvm,
+ "dying", info[i].dying,
+ "crashed", info[i].crashed,
+ "shutdown", info[i].shutdown,
+ "paused", info[i].paused,
+ "blocked", info[i].blocked,
+ "running", info[i].running,
+ "mem_kb", (long long)info[i].nr_pages*(XC_PAGE_SIZE/1024),
+ "cpu_time", (long long)info[i].cpu_time,
+ "maxmem_kb", (long long)info[i].max_memkb,
+ "ssidref", (int)info[i].ssidref,
+ "shutdown_reason", info[i].shutdown_reason);
+ pyhandle = PyList_New(sizeof(xen_domain_handle_t));
+ if ( (pyhandle == NULL) || (info_dict == NULL) )
+ {
+ Py_DECREF(list);
+ if ( pyhandle != NULL ) { Py_DECREF(pyhandle); }
+ if ( info_dict != NULL ) { Py_DECREF(info_dict); }
+ return NULL;
+ }
for ( j = 0; j < sizeof(xen_domain_handle_t); j++ )
PyList_SetItem(pyhandle, j, PyInt_FromLong(info[i].handle[j]));
- info_dict = Py_BuildValue("{s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i"
- ",s:l,s:L,s:l,s:i,s:i}",
- "domid", info[i].domid,
- "online_vcpus", info[i].nr_online_vcpus,
- "max_vcpu_id", info[i].max_vcpu_id,
- "hvm", info[i].hvm,
- "dying", info[i].dying,
- "crashed", info[i].crashed,
- "shutdown", info[i].shutdown,
- "paused", info[i].paused,
- "blocked", info[i].blocked,
- "running", info[i].running,
- "mem_kb", info[i].nr_pages*(XC_PAGE_SIZE/1024),
- "cpu_time", info[i].cpu_time,
- "maxmem_kb", info[i].max_memkb,
- "ssidref", info[i].ssidref,
- "shutdown_reason", info[i].shutdown_reason);
PyDict_SetItemString(info_dict, "handle", pyhandle);
Py_DECREF(pyhandle);
PyList_SetItem(list, i, info_dict);
diff --git a/tools/python/xen/util/blkif.py b/tools/python/xen/util/blkif.py
index 363bd41dd2..15d20dde8c 100644
--- a/tools/python/xen/util/blkif.py
+++ b/tools/python/xen/util/blkif.py
@@ -66,16 +66,23 @@ def blkdev_segment(name):
'type' : 'Disk' }
return val
-def blkdev_uname_to_file(uname):
- """Take a blkdev uname and return the corresponding filename."""
- fn = None
+def _parse_uname(uname):
+ fn = taptype = None
if uname.find(":") != -1:
(typ, fn) = uname.split(":", 1)
if typ == "phy" and not fn.startswith("/"):
fn = "/dev/%s" %(fn,)
if typ == "tap":
- (typ, fn) = fn.split(":", 1)
- return fn
+ (taptype, fn) = fn.split(":", 1)
+ return (fn, taptype)
+
+def blkdev_uname_to_file(uname):
+ """Take a blkdev uname and return the corresponding filename."""
+ return _parse_uname(uname)[0]
+
+def blkdev_uname_to_taptype(uname):
+ """Take a blkdev uname and return the blktap type."""
+ return _parse_uname(uname)[1]
def mount_mode(name):
mode = None
diff --git a/tools/python/xen/util/xmlrpclib2.py b/tools/python/xen/util/xmlrpclib2.py
index 0d0f3ade20..3bdd717de2 100644
--- a/tools/python/xen/util/xmlrpclib2.py
+++ b/tools/python/xen/util/xmlrpclib2.py
@@ -227,24 +227,30 @@ class TCPXMLRPCServer(SocketServer.ThreadingMixIn, SimpleXMLRPCServer):
response = xmlrpclib.dumps(response,
methodresponse=1,
allow_none=1)
- except xmlrpclib.Fault, fault:
- response = xmlrpclib.dumps(fault)
except Exception, exn:
- if self.xenapi:
- if _is_not_supported(exn):
- errdesc = ['MESSAGE_METHOD_UNKNOWN', method]
+ try:
+ if self.xenapi:
+ if _is_not_supported(exn):
+ errdesc = ['MESSAGE_METHOD_UNKNOWN', method]
+ else:
+ log.exception('Internal error handling %s', method)
+ errdesc = ['INTERNAL_ERROR', str(exn)]
+
+ response = xmlrpclib.dumps(
+ ({ "Status": "Failure",
+ "ErrorDescription": errdesc },),
+ methodresponse = 1)
else:
- log.exception('Internal error handling %s', method)
- errdesc = ['INTERNAL_ERROR', str(exn)]
- response = xmlrpclib.dumps(
- ({ "Status": "Failure",
- "ErrorDescription": errdesc },),
- methodresponse = 1)
- else:
- log.exception('Internal error handling %s', method)
- import xen.xend.XendClient
- response = xmlrpclib.dumps(
- xmlrpclib.Fault(xen.xend.XendClient.ERROR_INTERNAL, str(exn)))
+ import xen.xend.XendClient
+ if isinstance(exn, xmlrpclib.Fault):
+ response = xmlrpclib.dumps(exn)
+ else:
+ log.exception('Internal error handling %s', method)
+ response = xmlrpclib.dumps(
+ xmlrpclib.Fault(xen.xend.XendClient.ERROR_INTERNAL, str(exn)))
+ except:
+ log.exception('Internal error handling error')
+
return response
@@ -253,7 +259,7 @@ def _is_not_supported(exn):
try:
m = notSupportedRE.search(exn[0])
return m is not None
- except TypeError, e:
+ except:
return False
diff --git a/tools/python/xen/xend/XendAPI.py b/tools/python/xen/xend/XendAPI.py
index 7d3e29e693..a0f7c351b4 100644
--- a/tools/python/xen/xend/XendAPI.py
+++ b/tools/python/xen/xend/XendAPI.py
@@ -36,6 +36,9 @@ from xen.xend.XendVMMetrics import XendVMMetrics
from xen.xend.XendAPIConstants import *
from xen.util.xmlrpclib2 import stringify
+from xen.util.blkif import blkdev_name_to_number
+
+
AUTH_NONE = 'none'
AUTH_PAM = 'pam'
@@ -662,7 +665,8 @@ class XendAPI(object):
('add_to_other_config', None),
('remove_from_other_config', None),
('dmesg', 'String'),
- ('get_log', 'String')]
+ ('get_log', 'String'),
+ ('send_debug_keys', None)]
host_funcs = [('get_by_name_label', 'Set(host)')]
@@ -749,6 +753,11 @@ class XendAPI(object):
log_buffer = log_file.read()
return xen_api_success(log_buffer)
+ def host_send_debug_keys(self, _, host_ref, keys):
+ node = XendNode.instance()
+ node.send_debug_keys(keys)
+ return xen_api_success_void()
+
def host_get_record(self, session, host_ref):
node = XendNode.instance()
dom = XendDomain.instance()
@@ -1070,6 +1079,7 @@ class XendAPI(object):
('hard_reboot', None),
('suspend', None),
('resume', None),
+ ('send_sysrq', None),
('add_to_HVM_boot_params', None),
('remove_from_HVM_boot_params', None),
('add_to_VCPUs_params', None),
@@ -1077,7 +1087,8 @@ class XendAPI(object):
('add_to_platform', None),
('remove_from_platform', None),
('add_to_other_config', None),
- ('remove_from_other_config', None)]
+ ('remove_from_other_config', None),
+ ('send_trigger', None)]
VM_funcs = [('create', 'VM'),
('get_by_name_label', 'Set(VM)')]
@@ -1513,6 +1524,24 @@ class XendAPI(object):
return XendTask.log_progress(0, 100, do_vm_func,
"domain_unpause", vm_ref)
+ def VM_send_sysrq(self, _, vm_ref, req):
+ xeninfo = XendDomain.instance().get_vm_by_uuid(vm_ref)
+ if xeninfo.state != XEN_API_VM_POWER_STATE_RUNNING:
+ return xen_api_error(
+ ['VM_BAD_POWER_STATE', vm_ref,
+ XendDomain.POWER_STATE_NAMES[XEN_API_VM_POWER_STATE_RUNNING],
+ XendDomain.POWER_STATE_NAMES[xeninfo.state]])
+ xeninfo.send_sysrq(req)
+ return xen_api_success_void()
+
+
+ def VM_send_trigger(self, _, vm_ref, trigger, vcpu):
+ xendom = XendDomain.instance()
+ xeninfo = xendom.get_vm_by_uuid(vm_ref)
+ xendom.domain_send_trigger(xeninfo.getDomid(), trigger, vcpu)
+ return xen_api_success_void()
+
+
# Xen API: Class VM_metrics
# ----------------------------------------------------------------
@@ -1538,12 +1567,13 @@ class XendAPI(object):
return xen_api_success(self._VM_metrics_get(ref).get_vcpus_number())
def VM_metrics_get_vcpus_utilisation(self, _, ref):
- return xen_api_success(self._VM_metrics_get(ref).get_metrics_get_vcpus_utilisation())
+ return xen_api_success(self._VM_metrics_get(ref).get_vcpus_utilisation())
# Xen API: Class VBD
# ----------------------------------------------------------------
- VBD_attr_ro = ['metrics']
+ VBD_attr_ro = ['metrics',
+ 'runtime_properties']
VBD_attr_rw = ['VM',
'VDI',
'device',
@@ -1584,23 +1614,28 @@ class XendAPI(object):
# class methods
def VBD_create(self, session, vbd_struct):
xendom = XendDomain.instance()
+ xennode = XendNode.instance()
+
if not xendom.is_valid_vm(vbd_struct['VM']):
return xen_api_error(['HANDLE_INVALID', 'VM', vbd_struct['VM']])
dom = xendom.get_vm_by_uuid(vbd_struct['VM'])
- vbd_ref = ''
+ vdi = xennode.get_vdi_by_uuid(vbd_struct['VDI'])
+ if not vdi:
+ return xen_api_error(['HANDLE_INVALID', 'VDI', vdi_ref])
+
+ # new VBD via VDI/SR
+ vdi_image = vdi.get_location()
+
try:
- # new VBD via VDI/SR
- vdi_ref = vbd_struct.get('VDI')
- vdi = XendNode.instance().get_vdi_by_uuid(vdi_ref)
- if not vdi:
- return xen_api_error(['HANDLE_INVALID', 'VDI', vdi_ref])
- vdi_image = vdi.get_location()
vbd_ref = XendTask.log_progress(0, 100,
dom.create_vbd,
vbd_struct, vdi_image)
- except XendError:
- return xen_api_todo()
+ except XendError, e:
+ log.exception("Error in VBD_create")
+ return xen_api_error(['INTERNAL_ERROR', str(e)])
+
+ vdi.addVBD(vbd_ref)
xendom.managed_config_save(dom)
return xen_api_success(vbd_ref)
@@ -1612,7 +1647,14 @@ class XendAPI(object):
if not vm:
return xen_api_error(['HANDLE_INVALID', 'VBD', vbd_ref])
+ vdi_ref = XendDomain.instance()\
+ .get_dev_property_by_uuid('vbd', vbd_ref, "VDI")
+ vdi = XendNode.instance().get_vdi_by_uuid(vdi_ref)
+
XendTask.log_progress(0, 100, vm.destroy_vbd, vbd_ref)
+
+ vdi.removeVBD(vbd_ref)
+
return xen_api_success_void()
def _VBD_get(self, vbd_ref, prop):
@@ -1624,6 +1666,24 @@ class XendAPI(object):
def VBD_get_metrics(self, _, vbd_ref):
return xen_api_success(vbd_ref)
+ def VBD_get_runtime_properties(self, _, vbd_ref):
+ xendom = XendDomain.instance()
+ dominfo = xendom.get_vm_with_dev_uuid('vbd', vbd_ref)
+ device = dominfo.get_dev_config_by_uuid('vbd', vbd_ref)
+
+ try:
+ devid = int(device['id'])
+ device_sxps = dominfo.getDeviceSxprs('vbd')
+ device_dicts = [dict(device_sxp[1][1:]) for device_sxp in device_sxps]
+ device_dict = [device_dict
+ for device_dict in device_dicts
+ if int(device_dict['virtual-device']) == devid][0]
+
+ return xen_api_success(device_dict)
+ except Exception, exn:
+ log.exception(exn)
+ return xen_api_success({})
+
# attributes (rw)
def VBD_get_VM(self, session, vbd_ref):
return self._VBD_get(vbd_ref, 'VM')
@@ -1684,7 +1744,8 @@ class XendAPI(object):
# Xen API: Class VIF
# ----------------------------------------------------------------
- VIF_attr_ro = ['metrics']
+ VIF_attr_ro = ['metrics',
+ 'runtime_properties']
VIF_attr_rw = ['device',
'network',
'VM',
@@ -1721,18 +1782,17 @@ class XendAPI(object):
# class methods
def VIF_create(self, session, vif_struct):
xendom = XendDomain.instance()
- if xendom.is_valid_vm(vif_struct['VM']):
- dom = xendom.get_vm_by_uuid(vif_struct['VM'])
- try:
- vif_ref = dom.create_vif(vif_struct)
- xendom.managed_config_save(dom)
- return xen_api_success(vif_ref)
- except XendError:
- return xen_api_error(XEND_ERROR_TODO)
- else:
+ if not xendom.is_valid_vm(vif_struct['VM']):
return xen_api_error(['HANDLE_INVALID', 'VM', vif_struct['VM']])
-
+ dom = xendom.get_vm_by_uuid(vif_struct['VM'])
+ try:
+ vif_ref = dom.create_vif(vif_struct)
+ xendom.managed_config_save(dom)
+ return xen_api_success(vif_ref)
+ except XendError:
+ return xen_api_error(XEND_ERROR_TODO)
+
def VIF_destroy(self, session, vif_ref):
xendom = XendDomain.instance()
vm = xendom.get_vm_with_dev_uuid('vif', vif_ref)
@@ -1770,6 +1830,27 @@ class XendAPI(object):
vifs = reduce(lambda x, y: x + y, vifs)
return xen_api_success(vifs)
+ def VIF_get_runtime_properties(self, _, vif_ref):
+ xendom = XendDomain.instance()
+ dominfo = xendom.get_vm_with_dev_uuid('vif', vif_ref)
+ device = dominfo.get_dev_config_by_uuid('vif', vif_ref)
+
+ try:
+ devid = int(device['id'])
+
+ device_sxps = dominfo.getDeviceSxprs('vif')
+ device_dicts = [dict(device_sxp[1][1:])
+ for device_sxp in device_sxps]
+
+ device_dict = [device_dict
+ for device_dict in device_dicts
+ if int(device_dict['handle']) == devid][0]
+
+ return xen_api_success(device_dict)
+
+ except Exception, exn:
+ log.exception(exn)
+ return xen_api_success({})
# Xen API: Class VIF_metrics
# ----------------------------------------------------------------
@@ -1799,13 +1880,13 @@ class XendAPI(object):
VDI_attr_ro = ['SR',
'VBDs',
'physical_utilisation',
- 'sector_size',
'type']
VDI_attr_rw = ['name_label',
'name_description',
'virtual_size',
'sharable',
- 'read_only']
+ 'read_only',
+ 'other_config']
VDI_attr_inst = VDI_attr_ro + VDI_attr_rw
VDI_methods = [('snapshot', 'VDI')]
@@ -1816,14 +1897,12 @@ class XendAPI(object):
return XendNode.instance().get_vdi_by_uuid(ref)
def VDI_get_VBDs(self, session, vdi_ref):
- return xen_api_todo()
+ vdi = XendNode.instance().get_vdi_by_uuid(vdi_ref)
+ return xen_api_success(vdi.getVBDs())
def VDI_get_physical_utilisation(self, session, vdi_ref):
return xen_api_success(self._get_VDI(vdi_ref).
- get_physical_utilisation())
-
- def VDI_get_sector_size(self, session, vdi_ref):
- return xen_api_success(self._get_VDI(vdi_ref).sector_size)
+ get_physical_utilisation())
def VDI_get_type(self, session, vdi_ref):
return xen_api_success(self._get_VDI(vdi_ref).type)
@@ -1865,6 +1944,14 @@ class XendAPI(object):
self._get_VDI(vdi_ref).read_only = bool(value)
return xen_api_success_void()
+ def VDI_get_other_config(self, session, vdi_ref):
+ return xen_api_success(
+ self._get_VDI(vdi_ref).other_config)
+
+ def VDI_set_other_config(self, session, vdi_ref, other_config):
+ self._get_VDI(vdi_ref).other_config = other_config
+ return xen_api_success_void()
+
# Object Methods
def VDI_snapshot(self, session, vdi_ref):
return xen_api_todo()
@@ -1881,13 +1968,13 @@ class XendAPI(object):
'name_label': image.name_label,
'name_description': image.name_description,
'SR': image.sr_uuid,
- 'VBDs': [], # TODO
+ 'VBDs': image.getVBDs(),
'virtual_size': image.virtual_size,
'physical_utilisation': image.physical_utilisation,
- 'sector_size': image.sector_size,
'type': image.type,
'sharable': image.sharable,
'read_only': image.read_only,
+ 'other_config': image.other_config
})
# Class Functions
diff --git a/tools/python/xen/xend/XendCheckpoint.py b/tools/python/xen/xend/XendCheckpoint.py
index be8c299634..3982188016 100644
--- a/tools/python/xen/xend/XendCheckpoint.py
+++ b/tools/python/xen/xend/XendCheckpoint.py
@@ -193,8 +193,8 @@ def restore(xd, fd, dominfo = None, paused = False):
is_hvm = dominfo.info.is_hvm()
if is_hvm:
hvm = dominfo.info['memory_static_min']
- apic = dominfo.info['platform'].get('apic', 0)
- pae = dominfo.info['platform'].get('pae', 0)
+ apic = int(dominfo.info['platform'].get('apic', 0))
+ pae = int(dominfo.info['platform'].get('pae', 0))
log.info("restore hvm domain %d, mem=%d, apic=%d, pae=%d",
dominfo.domid, hvm, apic, pae)
else:
diff --git a/tools/python/xen/xend/XendConfig.py b/tools/python/xen/xend/XendConfig.py
index bdf9370380..d8f5c3fe66 100644
--- a/tools/python/xen/xend/XendConfig.py
+++ b/tools/python/xen/xend/XendConfig.py
@@ -28,7 +28,7 @@ from xen.xend.PrettyPrint import prettyprintstring
from xen.xend.XendConstants import DOM_STATE_HALTED
log = logging.getLogger("xend.XendConfig")
-log.setLevel(logging.DEBUG)
+log.setLevel(logging.WARN)
"""
@@ -105,8 +105,6 @@ XENAPI_CFG_TO_LEGACY_CFG = {
'uuid': 'uuid',
'vcpus_number': 'vcpus',
'cpus': 'cpus',
- 'memory_static_min': 'memory',
- 'memory_static_max': 'maxmem',
'name_label': 'name',
'actions_after_shutdown': 'on_poweroff',
'actions_after_reboot': 'on_reboot',
@@ -136,11 +134,10 @@ XENAPI_CFG_TYPES = {
'user_version': str,
'is_a_template': bool0,
'resident_on': str,
- 'memory_static_min': int,
+ 'memory_static_min': int, # note these are stored in bytes, not KB!
'memory_static_max': int,
'memory_dynamic_min': int,
'memory_dynamic_max': int,
- 'memory_actual': int,
'cpus': list,
'vcpus_policy': str,
'vcpus_params': dict,
@@ -314,7 +311,6 @@ class XendConfig(dict):
'shadow_memory': 0,
'memory_static_max': 0,
'memory_dynamic_max': 0,
- 'memory_actual': 0,
'devices': {},
'security': None,
'on_xend_start': 'ignore',
@@ -334,20 +330,39 @@ class XendConfig(dict):
return defaults
+ #
+ # Here we assume these values exist in the dict.
+ # If they don't we have a bigger problem, lets not
+ # try and 'fix it up' but acutually fix the cause ;-)
+ #
def _memory_sanity_check(self):
- if self['memory_static_min'] == 0:
- self['memory_static_min'] = self['memory_dynamic_min']
-
- # If the static max is not set, let's set it to dynamic max.
- # If the static max is smaller than static min, then fix it!
- self['memory_static_max'] = max(self['memory_static_max'],
- self['memory_dynamic_max'],
- self['memory_static_min'])
-
- for mem_type in ('memory_static_min', 'memory_static_max'):
- if self[mem_type] <= 0:
- raise XendConfigError('Memory value too low for %s: %d' %
- (mem_type, self[mem_type]))
+ log.debug("_memory_sanity_check memory_static_min: %s, "
+ "memory_static_max: %i, "
+ "memory_dynamic_min: %i, "
+ "memory_dynamic_max: %i",
+ self["memory_static_min"],
+ self["memory_static_max"],
+ self["memory_dynamic_min"],
+ self["memory_dynamic_max"])
+
+ if not self["memory_static_min"] <= self["memory_static_max"]:
+ raise XendConfigError("memory_static_min must be less " \
+ "than or equal to memory_static_max")
+ if not self["memory_dynamic_min"] <= self["memory_dynamic_max"]:
+ raise XendConfigError("memory_dynamic_min must be less " \
+ "than or equal to memory_dynamic_max")
+ if not self["memory_static_min"] <= self["memory_dynamic_min"]:
+ raise XendConfigError("memory_static_min must be less " \
+ "than or equal to memory_dynamic_min")
+ if not self["memory_dynamic_max"] <= self["memory_static_max"]:
+ raise XendConfigError("memory_dynamic_max must be less " \
+ "than or equal to memory_static_max")
+ if not self["memory_dynamic_max"] > 0:
+ raise XendConfigError("memory_dynamic_max must be greater " \
+ "than zero")
+ if not self["memory_static_max"] > 0:
+ raise XendConfigError("memory_static_max must be greater " \
+ "than zero")
def _actions_sanity_check(self):
for event in ['shutdown', 'reboot', 'crash']:
@@ -392,8 +407,12 @@ class XendConfig(dict):
self['domid'] = dominfo['domid']
self['online_vcpus'] = dominfo['online_vcpus']
self['vcpus_number'] = dominfo['max_vcpu_id'] + 1
- self['memory_dynamic_min'] = (dominfo['mem_kb'] + 1023)/1024
- self['memory_dynamic_max'] = (dominfo['maxmem_kb'] + 1023)/1024
+
+ self['memory_dynamic_min'] = dominfo['mem_kb'] * 1024
+ self['memory_dynamic_max'] = dominfo['mem_kb'] * 1024
+ self['memory_static_min'] = 0
+ self['memory_static_max'] = dominfo['maxmem_kb'] * 1024
+
self['cpu_time'] = dominfo['cpu_time']/1e9
# TODO: i don't know what the security stuff expects here
if dominfo.get('ssidref'):
@@ -447,6 +466,13 @@ class XendConfig(dict):
log.warn('Ignoring unrecognised value for deprecated option:'
'restart = \'%s\'', restart)
+ # Handle memory, passed in as MiB
+
+ if sxp.child_value(sxp_cfg, "memory") != None:
+ cfg["memory"] = int(sxp.child_value(sxp_cfg, "memory"))
+ if sxp.child_value(sxp_cfg, "maxmem") != None:
+ cfg["maxmem"] = int(sxp.child_value(sxp_cfg, "maxmem"))
+
# Only extract options we know about.
extract_keys = LEGACY_UNSUPPORTED_BY_XENAPI_CFG
extract_keys += XENAPI_CFG_TO_LEGACY_CFG.values()
@@ -616,6 +642,21 @@ class XendConfig(dict):
except KeyError:
pass
+ # Lets try and handle memory correctly
+
+ MiB = 1024 * 1024
+
+ if "memory" in cfg:
+ self["memory_static_min"] = 0
+ self["memory_static_max"] = int(cfg["memory"]) * MiB
+ self["memory_dynamic_min"] = int(cfg["memory"]) * MiB
+ self["memory_dynamic_max"] = int(cfg["memory"]) * MiB
+
+ if "maxmem" in cfg:
+ self["memory_static_max"] = int(cfg["maxmem"]) * MiB
+
+ self._memory_sanity_check()
+
def update_with(n, o):
if not self.get(n):
self[n] = cfg.get(o, '')
@@ -632,13 +673,6 @@ class XendConfig(dict):
if key in cfg:
self['platform'][key] = cfg[key]
- # make sure a sane maximum is set
- if self['memory_static_max'] <= 0:
- self['memory_static_max'] = self['memory_static_min']
-
- self['memory_dynamic_max'] = self['memory_static_max']
- self['memory_dynamic_min'] = self['memory_static_min']
-
# set device references in the configuration
self['devices'] = cfg.get('devices', {})
self['console_refs'] = cfg.get('console_refs', [])
@@ -812,6 +846,21 @@ class XendConfig(dict):
else:
sxpr.append([legacy, self[xenapi]])
+ MiB = 1024*1024
+
+ sxpr.append(["maxmem", int(self["memory_static_max"])/MiB])
+ sxpr.append(["memory", int(self["memory_dynamic_max"])/MiB])
+
+ if not legacy_only:
+ sxpr.append(['memory_dynamic_min',
+ int(self.get('memory_dynamic_min'))])
+ sxpr.append(['memory_dynamic_max',
+ int(self.get('memory_dynamic_max'))])
+ sxpr.append(['memory_static_max',
+ int(self.get('memory_static_max'))])
+ sxpr.append(['memory_static_min',
+ int(self.get('memory_static_min'))])
+
for legacy in LEGACY_UNSUPPORTED_BY_XENAPI_CFG:
if legacy in ('domid', 'uuid'): # skip these
continue
@@ -820,8 +869,6 @@ class XendConfig(dict):
sxpr.append(['image', self.image_sxpr()])
sxpr.append(['status', domain.state])
- sxpr.append(['memory_dynamic_min', self.get('memory_dynamic_min')])
- sxpr.append(['memory_dynamic_max', self.get('memory_dynamic_max')])
if domain.getDomid() is not None:
sxpr.append(['state', self._get_old_state_string()])
diff --git a/tools/python/xen/xend/XendDomain.py b/tools/python/xen/xend/XendDomain.py
index 4ec8334aa1..18aad354b4 100644
--- a/tools/python/xen/xend/XendDomain.py
+++ b/tools/python/xen/xend/XendDomain.py
@@ -674,7 +674,7 @@ class XendDomain:
else:
return domid
- raise XendInvalidDomain("Domain does not exist")
+ raise XendInvalidDomain(vm_uuid)
finally:
self.domains_lock.release()
diff --git a/tools/python/xen/xend/XendDomainInfo.py b/tools/python/xen/xend/XendDomainInfo.py
index 58af5f28ad..bd4c595797 100644
--- a/tools/python/xen/xend/XendDomainInfo.py
+++ b/tools/python/xen/xend/XendDomainInfo.py
@@ -34,7 +34,7 @@ from types import StringTypes
import xen.lowlevel.xc
from xen.util import asserts
-from xen.util.blkif import blkdev_uname_to_file
+from xen.util.blkif import blkdev_uname_to_file, blkdev_uname_to_taptype
from xen.util import security
from xen.xend import balloon, sxp, uuid, image, arch, osdep
@@ -576,12 +576,14 @@ class XendDomainInfo:
if target <= 0:
raise XendError('Invalid memory size')
- self.info['memory_static_min'] = target
+ MiB = 1024 * 1024
+ self.info['memory_dynamic_min'] = target * MiB
+ self.info['memory_dynamic_max'] = target * MiB
+
if self.domid >= 0:
self.storeVm("memory", target)
self.storeDom("memory/target", target << 10)
else:
- self.info['memory_dynamic_min'] = target
xen.xend.XendDomain.instance().managed_config_save(self)
def setMemoryMaximum(self, limit):
@@ -664,6 +666,10 @@ class XendDomainInfo:
if arg in XendConfig.LEGACY_CFG_TO_XENAPI_CFG:
xapiarg = XendConfig.LEGACY_CFG_TO_XENAPI_CFG[arg]
self.info[xapiarg] = val
+ elif arg == "memory":
+ self.info["static_memory_min"] = val
+ elif arg == "maxmem":
+ self.info["static_memory_max"] = val
else:
self.info[arg] = val
@@ -780,7 +786,7 @@ 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_dynamic_max'] / 1024),
}
def f(n, v):
@@ -864,7 +870,15 @@ class XendDomainInfo:
xapiarg = XendConfig.LEGACY_CFG_TO_XENAPI_CFG[arg]
if val != None and val != self.info[xapiarg]:
self.info[xapiarg] = val
- changed= True
+ changed = True
+ elif arg == "memory":
+ if val != None and val != self.info["static_memory_min"]:
+ self.info["static_memory_min"] = val
+ changed = True
+ elif arg == "maxmem":
+ if val != None and val != self.info["static_memory_max"]:
+ self.info["static_memory_max"] = val
+ changed = True
# Check whether image definition has been updated
image_sxp = self._readVm('image')
@@ -969,11 +983,12 @@ class XendDomainInfo:
def getMemoryTarget(self):
"""Get this domain's target memory size, in KB."""
- return self.info['memory_static_min'] * 1024
+ return self.info['memory_dynamic_max'] / 1024
def getMemoryMaximum(self):
"""Get this domain's maximum memory size, in KB."""
- return self.info['memory_static_max'] * 1024
+ # remember, info now stores memory in bytes
+ return self.info['memory_static_max'] / 1024
def getResume(self):
return str(self._resume)
@@ -1455,13 +1470,14 @@ class XendDomainInfo:
# Use architecture- and image-specific calculations to determine
# the various headrooms necessary, given the raw configured
# values. maxmem, memory, and shadow are all in KiB.
+ # but memory_static_max etc are all stored in bytes now.
memory = self.image.getRequiredAvailableMemory(
- self.info['memory_static_min'] * 1024)
+ self.info['memory_dynamic_max'] / 1024)
maxmem = self.image.getRequiredAvailableMemory(
- self.info['memory_static_max'] * 1024)
+ self.info['memory_static_max'] / 1024)
shadow = self.image.getRequiredShadowMemory(
- self.info['shadow_memory'] * 1024,
- self.info['memory_static_max'] * 1024)
+ self.info['shadow_memory'] / 1024,
+ self.info['memory_static_max'] / 1024)
log.debug("_initDomain:shadow_memory=0x%x, memory_static_max=0x%x, memory_static_min=0x%x.", self.info['shadow_memory'], self.info['memory_static_max'], self.info['memory_static_min'],)
# Round shadow up to a multiple of a MiB, as shadow_mem_control
@@ -1650,7 +1666,18 @@ class XendDomainInfo:
log.exception("XendDomainInfo.destroy: xc.domain_destroy failed.")
from xen.xend import XendDomain
- XendDomain.instance().remove_domain(self)
+
+ if "transient" in self.info["other_config"]\
+ and bool(self.info["other_config"]["transient"]):
+ xendDomainInstance = XendDomain.instance()
+
+ xendDomainInstance.domains_lock.acquire()
+ xendDomainInstance._refresh(refresh_shutdown = False)
+ xendDomainInstance.domains_lock.release()
+
+ xendDomainInstance.domain_delete(self.info["name_label"])
+ else:
+ XendDomain.instance().remove_domain(self)
self.cleanupDomain()
self._cleanup_phantom_devs(paths)
@@ -1759,7 +1786,8 @@ class XendDomainInfo:
disk = devinfo[1]['uname']
fn = blkdev_uname_to_file(disk)
- mounted = devtype == 'tap' and not os.stat(fn).st_rdev
+ taptype = blkdev_uname_to_taptype(disk)
+ mounted = devtype == 'tap' and taptype != 'aio' and taptype != 'sync' and not os.stat(fn).st_rdev
if mounted:
# This is a file, not a device. pygrub can cope with a
# file if it's raw, but if it's QCOW or other such formats
@@ -1775,7 +1803,7 @@ class XendDomainInfo:
from xen.xend import XendDomain
dom0 = XendDomain.instance().privilegedDomain()
- dom0._waitForDeviceUUID(dom0.create_vbd(vbd, fn))
+ dom0._waitForDeviceUUID(dom0.create_vbd(vbd, disk))
fn = BOOTLOADER_LOOPBACK_DEVICE
try:
@@ -1833,7 +1861,7 @@ class XendDomainInfo:
# 1MB per vcpu plus 4Kib/Mib of RAM. This is higher than
# the minimum that Xen would allocate if no value were given.
overhead_kb = self.info['vcpus_number'] * 1024 + \
- self.info['memory_static_max'] * 4
+ (self.info['memory_static_max'] / 1024 / 1024) * 4
overhead_kb = ((overhead_kb + 1023) / 1024) * 1024
# The domain might already have some shadow memory
overhead_kb -= xc.shadow_mem_control(self.domid) * 1024
@@ -1899,6 +1927,11 @@ class XendDomainInfo:
if self._infoIsSet(info_key):
to_store[key] = str(self.info[info_key])
+ if self._infoIsSet("static_memory_min"):
+ to_store["memory"] = str(self.info["static_memory_min"])
+ if self._infoIsSet("static_memory_max"):
+ to_store["maxmem"] = str(self.info["static_memory_max"])
+
image_sxpr = self.info.image_sxpr()
if image_sxpr:
to_store['image'] = sxp.to_string(image_sxpr)
@@ -1988,7 +2021,11 @@ class XendDomainInfo:
info = dom_get(self.domid)
if not info:
return
-
+
+ if info["maxmem_kb"] < 0:
+ info["maxmem_kb"] = XendNode.instance() \
+ .physinfo_dict()['total_memory'] * 1024
+
#manually update ssidref / security fields
if security.on() and info.has_key('ssidref'):
if (info['ssidref'] != 0) and self.info.has_key('security'):
@@ -2249,8 +2286,6 @@ class XendDomainInfo:
@return: uuid of the device
"""
xenapi_vbd['image'] = vdi_image_path
- log.debug('create_vbd: %s' % xenapi_vbd)
- dev_uuid = ''
if vdi_image_path.startswith('tap'):
dev_uuid = self.info.device_add('tap', cfg_xenapi = xenapi_vbd)
else:
@@ -2260,16 +2295,25 @@ class XendDomainInfo:
raise XendError('Failed to create device')
if self.state == XEN_API_VM_POWER_STATE_RUNNING:
+
_, config = self.info['devices'][dev_uuid]
- dev_control = None
if vdi_image_path.startswith('tap'):
- dev_control = self.getDeviceController('tap')
+ dev_control = self.getDeviceController('tap')
else:
dev_control = self.getDeviceController('vbd')
-
- config['devid'] = dev_control.createDevice(config)
+ try:
+ devid = dev_control.createDevice(config)
+ dev_control.waitForDevice(devid)
+ self.info.device_update(dev_uuid,
+ cfg_xenapi = {'devid': devid})
+ except Exception, exn:
+ log.exception(exn)
+ del self.info['devices'][dev_uuid]
+ self.info['vbd_refs'].remove(dev_uuid)
+ raise
+
return dev_uuid
def create_phantom_vbd_with_vdi(self, xenapi_vbd, vdi_image_path):
@@ -2303,9 +2347,21 @@ class XendDomainInfo:
raise XendError('Failed to create device')
if self.state == XEN_API_VM_POWER_STATE_RUNNING:
+
_, config = self.info['devices'][dev_uuid]
- config['devid'] = self.getDeviceController('vif').createDevice(config)
+ dev_control = self.getDeviceController('vif')
+ try:
+ devid = dev_control.createDevice(config)
+ dev_control.waitForDevice(devid)
+ self.info.device_update(dev_uuid,
+ cfg_xenapi = {'devid': devid})
+ except Exception, exn:
+ log.exception(exn)
+ del self.info['devices'][dev_uuid]
+ self.info['vif_refs'].remove(dev_uuid)
+ raise
+
return dev_uuid
def create_vtpm(self, xenapi_vtpm):
@@ -2372,7 +2428,7 @@ class XendDomainInfo:
def __str__(self):
return '<domain id=%s name=%s memory=%s state=%s>' % \
(str(self.domid), self.info['name_label'],
- str(self.info['memory_static_min']), DOM_STATES[self.state])
+ str(self.info['memory_dynamic_max']), DOM_STATES[self.state])
__repr__ = __str__
diff --git a/tools/python/xen/xend/XendLogging.py b/tools/python/xen/xend/XendLogging.py
index 6d6140188d..3d6b678f1d 100644
--- a/tools/python/xen/xend/XendLogging.py
+++ b/tools/python/xen/xend/XendLogging.py
@@ -59,6 +59,18 @@ if 'TRACE' not in logging.__dict__:
return filename, frame[2]
logging.Logger.findCaller = findCaller
+ # Work around a bug in Python's inspect module: findsource is supposed to
+ # raise IOError if it fails, with other functions in that module coping
+ # with that, but some people are seeing IndexError raised from there.
+ if hasattr(inspect, 'findsource'):
+ real_findsource = getattr(inspect, 'findsource')
+ def findsource(*args, **kwargs):
+ try:
+ return real_findsource(*args, **kwargs)
+ except IndexError, exn:
+ raise IOError(exn)
+ inspect.findsource = findsource
+
log = logging.getLogger("xend")
diff --git a/tools/python/xen/xend/XendNode.py b/tools/python/xen/xend/XendNode.py
index 954b57a2de..3917c8080c 100644
--- a/tools/python/xen/xend/XendNode.py
+++ b/tools/python/xen/xend/XendNode.py
@@ -530,7 +530,8 @@ class XendNode:
info['cores_per_socket'] *
info['threads_per_core'])
info['cpu_mhz'] = info['cpu_khz'] / 1000
- # physinfo is in KiB
+
+ # physinfo is in KiB, need it in MiB
info['total_memory'] = info['total_memory'] / 1024
info['free_memory'] = info['free_memory'] / 1024
diff --git a/tools/python/xen/xend/XendVDI.py b/tools/python/xen/xend/XendVDI.py
index f0dda203a8..140ca01226 100644
--- a/tools/python/xen/xend/XendVDI.py
+++ b/tools/python/xen/xend/XendVDI.py
@@ -54,7 +54,6 @@ class XendVDI(AutoSaveObject):
SAVED_CFG = ['name_label',
'name_description',
- 'sector_size',
'virtual_size',
'physical_utilisation',
'sharable',
@@ -67,13 +66,22 @@ class XendVDI(AutoSaveObject):
self.sr_uuid = sr_uuid
self.name_label = ""
self.name_description = ""
- self.sector_size = 1024
self.virtual_size = 0
self.physical_utilisation = 0
self.sharable = False
self.read_only = False
self.type = "system"
- self.location = ''
+ self.other_config = {}
+ self.vbds = []
+
+ def addVBD(self, vbd_ref):
+ self.vbds.append(vbd_ref)
+
+ def removeVBD(self, vbd_ref):
+ self.vbds.remove(vbd_ref)
+
+ def getVBDs(self):
+ return self.vbds
def load_config_dict(self, cfg):
"""Loads configuration into the object from a dict.
@@ -144,11 +152,10 @@ class XendVDI(AutoSaveObject):
'name_description': self.name_description,
'virtual_size': self.virtual_size,
'physical_utilisation': self.physical_utilisation,
- 'sector_size': self.sector_size,
'sharable': False,
'readonly': False,
'SR': self.sr_uuid,
- 'location': self.get_location(),
+ 'other_config': self.other_config,
'VBDs': []}
def get_location(self):
@@ -163,12 +170,11 @@ class XendQCoWVDI(XendVDI):
self.cfg_path = cfg_path
self.physical_utilisation = psize
self.virtual_size = vsize
- self.sector_size = 512
self.auto_save = True
- self.location = 'tap:qcow:%s' % self.qcow_path
+ self.other_config['location'] = 'tap:qcow:%s' % self.qcow_path
def get_location(self):
- return self.location
+ return self.other_config['location']
class XendLocalVDI(XendVDI):
def __init__(self, vdi_struct):
@@ -182,11 +188,10 @@ class XendLocalVDI(XendVDI):
self.name_description = vdi_struct.get('name_description', '')
self.physical_utilisation = 0
self.virtual_size = 0
- self.sector_size = 0
self.type = vdi_struct.get('type', '')
self.sharable = vdi_struct.get('sharable', False)
self.read_only = vdi_struct.get('read_only', False)
- self.location = vdi_struct.get('location', 'file:/dev/null')
+ self.other_config = vdi_struct.get('other_config', {})
def get_location(self):
- return self.location
+ return self.other_config['location']
diff --git a/tools/python/xen/xm/create.dtd b/tools/python/xen/xm/create.dtd
new file mode 100644
index 0000000000..b544edc5bd
--- /dev/null
+++ b/tools/python/xen/xm/create.dtd
@@ -0,0 +1,118 @@
+<!ENTITY % HTMLlat1 PUBLIC
+ "-//W3C//ENTITIES Latin 1 for XHTML//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml-lat1.ent">
+%HTMLlat1;
+<!ENTITY % HTMLsymbol PUBLIC
+ "-//W3C//ENTITIES Symbols for XHTML//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml-symbol.ent">
+%HTMLsymbol;
+<!ENTITY % HTMLspecial PUBLIC
+ "-//W3C//ENTITIES Special for XHTML//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml-special.ent">
+%HTMLspecial;
+<!-- a Uniform Resource Identifier, see [RFC2396] -->
+<!ENTITY % URI "CDATA">
+<!ENTITY % NAMEID "name ID #REQUIRED">
+<!ENTITY % CRASH_BEHAVIOUR "( destroy
+ | coredump_and_destroy
+ | restart
+ | coredump_and_restart
+ | preserve
+ | rename_restart )">
+<!ENTITY % NORMAL_EXIT "( destroy | restart )">
+<!ENTITY % VDI_TYPE "( system
+ | user
+ | ephemeral
+ | suspend
+ | crashdump )">
+
+<!ELEMENT xm (vm*,
+ vdi*)>
+
+<!ELEMENT version (#PCDATA)>
+
+<!ELEMENT vm (name,
+ version,
+ (pv|hvm),
+ memory,
+ vbd*,
+ vif*,
+ vcpu_param*,
+ other_config*)>
+<!ATTLIST vm is_a_template CDATA #REQUIRED
+ auto_power_on CDATA #REQUIRED
+ vcpus_max CDATA #REQUIRED
+ vcpus_at_startup CDATA #REQUIRED
+ actions_after_shutdown %NORMAL_EXIT; #REQUIRED
+ actions_after_reboot %NORMAL_EXIT; #REQUIRED
+ actions_after_crash %CRASH_BEHAVIOUR; #REQUIRED
+ platform_std_VGA CDATA #REQUIRED
+ platform_serial CDATA #REQUIRED
+ platform_localtime CDATA #REQUIRED
+ platform_clock_offet CDATA #REQUIRED
+ platform_enable_audio CDATA #REQUIRED
+ PCI_bus CDATA #REQUIRED>
+
+<!ELEMENT memory EMPTY>
+<!ATTLIST memory static_min CDATA #REQUIRED
+ static_max CDATA #REQUIRED
+ dynamic_min CDATA #REQUIRED
+ dynamic_max CDATA #REQUIRED>
+
+<!ELEMENT vbd (qos_algorithm_param*)>
+<!ATTLIST vbd %NAMEID;
+ mode (RO | RW) #REQUIRED
+ vdi IDREF #REQUIRED
+ device CDATA #REQUIRED
+ bootable CDATA #REQUIRED
+ type (CD | disk) #REQUIRED
+ qos_algorithm_type CDATA #REQUIRED>
+
+<!ELEMENT vif (qos_algorithm_param*)>
+<!ATTLIST vif %NAMEID;
+ mac CDATA #REQUIRED
+ mtu CDATA #REQUIRED
+ device CDATA #REQUIRED
+ qos_algorithm_type CDATA #REQUIRED
+ bridge CDATA #IMPLIED
+ network CDATA #IMPLIED>
+
+<!ELEMENT pv EMPTY>
+<!ATTLIST pv kernel CDATA #REQUIRED
+ bootloader CDATA #REQUIRED
+ ramdisk CDATA #REQUIRED
+ args CDATA #REQUIRED
+ bootloader_args CDATA #REQUIRED>
+
+<!ELEMENT hvm (boot_param*)>
+<!ATTLIST hvm boot_policy CDATA #REQUIRED>
+
+<!ELEMENT boot_param EMPTY>
+<!ATTLIST boot_param key CDATA #REQUIRED
+ value CDATA #REQUIRED>
+
+<!ELEMENT vdi (name)>
+<!ATTLIST vdi %NAMEID;
+ src %URI; #REQUIRED
+ type %VDI_TYPE; #REQUIRED
+ size CDATA #REQUIRED
+ shareable CDATA #REQUIRED
+ read_only CDATA #REQUIRED>
+
+<!ELEMENT name (label,
+ description)>
+
+<!ELEMENT label (#PCDATA)>
+<!ELEMENT description (#PCDATA)>
+
+<!ELEMENT vcpu_param EMPTY>
+<!ATTLIST vcpu_param key CDATA #REQUIRED
+ value CDATA #REQUIRED>
+
+<!ELEMENT other_config EMPTY>
+<!ATTLIST other_config key CDATA #REQUIRED
+ value CDATA #REQUIRED>
+
+<!ELEMENT qos_algorithm_param EMPTY>
+<!ATTLIST qos_algorithm_param key CDATA #REQUIRED
+ value CDATA #REQUIRED>
diff --git a/tools/python/xen/xm/create.py b/tools/python/xen/xm/create.py
index 450e3283d1..abdfa22031 100644
--- a/tools/python/xen/xm/create.py
+++ b/tools/python/xen/xm/create.py
@@ -28,12 +28,13 @@ import time
import xmlrpclib
from xen.xend import sxp
-from xen.xend import PrettyPrint
+from xen.xend import PrettyPrint as SXPPrettyPrint
from xen.xend import osdep
import xen.xend.XendClient
from xen.xend.XendBootloader import bootloader
from xen.util import blkif
from xen.util import security
+from xen.xm.main import serverType, SERVER_XEN_API, get_single_vm
from xen.xm.opts import *
@@ -98,6 +99,11 @@ gopts.opt('dryrun', short='n',
use="Dry run - prints the resulting configuration in SXP but "
"does not create the domain.")
+gopts.opt('xmldryrun', short='x',
+ fn=set_true, default=0,
+ use="XML dry run - prints the resulting configuration in XML but "
+ "does not create the domain.")
+
gopts.opt('paused', short='p',
fn=set_true, default=0,
use='Leave the domain paused after it is created.')
@@ -1241,34 +1247,59 @@ def main(argv):
except IOError, exn:
raise OptionError("Cannot read file %s: %s" % (config, exn[1]))
+ if serverType == SERVER_XEN_API:
+ from xen.xm.xenapi_create import sxp2xml
+ sxp2xml_inst = sxp2xml()
+ doc = sxp2xml_inst.convert_sxp_to_xml(config, transient=True)
+
if opts.vals.dryrun:
- PrettyPrint.prettyprint(config)
+ SXPPrettyPrint.prettyprint(config)
+
+ if opts.vals.xmldryrun and serverType == SERVER_XEN_API:
+ from xml.dom.ext import PrettyPrint as XMLPrettyPrint
+ XMLPrettyPrint(doc)
+
+ if opts.vals.dryrun or opts.vals.xmldryrun:
+ return
+
+ if opts.vals.console_autoconnect:
+ do_console(sxp.child_value(config, 'name', -1))
+
+ if serverType == SERVER_XEN_API:
+ from xen.xm.xenapi_create import xenapi_create
+ xenapi_create_inst = xenapi_create()
+ vm_refs = xenapi_create_inst.create(document = doc)
+
+ map(lambda vm_ref: server.xenapi.VM.start(vm_ref, 0), vm_refs)
else:
if not create_security_check(config):
- raise security.ACMError('Security Configuration prevents domain from starting')
- else:
- if opts.vals.console_autoconnect:
- cpid = os.fork()
- if cpid != 0:
- for i in range(10):
- # Catch failure of the create process
- time.sleep(1)
- (p, rv) = os.waitpid(cpid, os.WNOHANG)
- if os.WIFEXITED(rv):
- if os.WEXITSTATUS(rv) != 0:
- sys.exit(os.WEXITSTATUS(rv))
- try:
- # Acquire the console of the created dom
- name = sxp.child_value(config, 'name', -1)
- dom = server.xend.domain(name)
- domid = int(sxp.child_value(dom, 'domid', '-1'))
- console.execConsole(domid)
- except:
- pass
- print("Could not start console\n");
- sys.exit(0)
- dom = make_domain(opts, config)
-
+ raise security.ACMError(
+ 'Security Configuration prevents domain from starting')
+ dom = make_domain(opts, config)
+
+def do_console(domain_name):
+ cpid = os.fork()
+ if cpid != 0:
+ for i in range(10):
+ # Catch failure of the create process
+ time.sleep(1)
+ (p, rv) = os.waitpid(cpid, os.WNOHANG)
+ if os.WIFEXITED(rv):
+ if os.WEXITSTATUS(rv) != 0:
+ sys.exit(os.WEXITSTATUS(rv))
+ try:
+ # Acquire the console of the created dom
+ if serverType == SERVER_XEN_API:
+ domid = server.xenapi.VM.get_domid(
+ get_single_vm(domain_name))
+ else:
+ dom = server.xend.domain(domain_name)
+ domid = int(sxp.child_value(dom, 'domid', '-1'))
+ console.execConsole(domid)
+ except:
+ pass
+ print("Could not start console\n");
+ sys.exit(0)
if __name__ == '__main__':
main(sys.argv)
diff --git a/tools/python/xen/xm/main.py b/tools/python/xen/xm/main.py
index 152c1a69f7..66a5951f7f 100644
--- a/tools/python/xen/xm/main.py
+++ b/tools/python/xen/xm/main.py
@@ -33,11 +33,11 @@ import getopt
import socket
import traceback
import xmlrpclib
-import traceback
import time
import datetime
from select import select
import xml.dom.minidom
+from xen.util.blkif import blkdev_name_to_number
import warnings
warnings.filterwarnings('ignore', category=FutureWarning)
@@ -49,18 +49,19 @@ from xen.xend.XendConstants import *
from xen.xm.opts import OptionError, Opts, wrap, set_true
from xen.xm import console
-from xen.util import security
from xen.util.xmlrpclib2 import ServerProxy
import XenAPI
+
# getopt.gnu_getopt is better, but only exists in Python 2.3+. Use
# getopt.getopt if gnu_getopt is not available. This will mean that options
# may only be specified before positional arguments.
if not hasattr(getopt, 'gnu_getopt'):
getopt.gnu_getopt = getopt.getopt
-XM_CONFIG_FILE = '/etc/xen/xm-config.xml'
+XM_CONFIG_FILE_ENVVAR = 'XM_CONFIG_FILE'
+XM_CONFIG_FILE_DEFAULT = '/etc/xen/xm-config.xml'
# Supported types of server
SERVER_LEGACY_XMLRPC = 'LegacyXMLRPC'
@@ -351,13 +352,14 @@ all_commands = (domain_commands + host_commands + scheduler_commands +
# Configuration File Parsing
##
+xmConfigFile = os.getenv(XM_CONFIG_FILE_ENVVAR, XM_CONFIG_FILE_DEFAULT)
config = None
-if os.path.isfile(XM_CONFIG_FILE):
+if os.path.isfile(xmConfigFile):
try:
- config = xml.dom.minidom.parse(XM_CONFIG_FILE)
+ config = xml.dom.minidom.parse(xmConfigFile)
except:
print >>sys.stderr, ('Ignoring invalid configuration file %s.' %
- XM_CONFIG_FILE)
+ xmConfigFile)
def parseServer():
if config:
@@ -491,6 +493,18 @@ def usage(cmd = None):
#
####################################################################
+def get_default_SR():
+ return [sr_ref
+ for sr_ref in server.xenapi.SR.get_all()
+ if server.xenapi.SR.get_type(sr_ref) == "local"][0]
+
+def get_default_Network():
+ return [network_ref
+ for network_ref in server.xenapi.network.get_all()][0]
+
+def map2sxp(m):
+ return [[k, m[k]] for k in m.keys()]
+
def arg_check(args, name, lo, hi = -1):
n = len([i for i in args if i != '--'])
@@ -673,10 +687,41 @@ def xm_restore(args):
def getDomains(domain_names, state, full = 0):
- if domain_names:
- return [server.xend.domain(dom, full) for dom in domain_names]
+ if serverType == SERVER_XEN_API:
+ doms_sxp = []
+ doms_dict = []
+ dom_refs = server.xenapi.VM.get_all()
+ for dom_ref in dom_refs:
+ dom_rec = server.xenapi.VM.get_record(dom_ref)
+ dom_metrics_ref = server.xenapi.VM.get_metrics(dom_ref)
+ dom_metrics = server.xenapi.VM_metrics.get_record(dom_metrics_ref)
+ dom_rec.update({'name': dom_rec['name_label'],
+ 'memory_actual': int(dom_metrics['memory_actual'])/1024,
+ 'vcpus': dom_metrics['vcpus_number'],
+ 'state': '-----',
+ 'cpu_time': dom_metrics['vcpus_utilisation']})
+
+ doms_sxp.append(['domain'] + map2sxp(dom_rec))
+ doms_dict.append(dom_rec)
+
+ if domain_names:
+ doms = [['domain'] + map2sxp(dom) for dom in doms_dict
+ if dom["name"] in domain_names]
+
+ if len(doms) > 0:
+ return doms
+ else:
+ print "Error: no domain%s named %s" % \
+ (len(domain_names) > 1 and 's' or '',
+ ', '.join(domain_names))
+ sys.exit(-1)
+ else:
+ return doms_sxp
else:
- return server.xend.domains_with_state(True, state, full)
+ if domain_names:
+ return [server.xend.domain(dom, full) for dom in domain_names]
+ else:
+ return server.xend.domains_with_state(True, state, full)
def xm_list(args):
@@ -735,20 +780,39 @@ def parse_doms_info(info):
else:
up_time = time.time() - start_time
- return {
+ parsed_info = {
'domid' : get_info('domid', str, ''),
'name' : get_info('name', str, '??'),
- 'mem' : get_info('memory_dynamic_min', int, 0),
'state' : get_info('state', str, ''),
- 'cpu_time' : get_info('cpu_time', float, 0.0),
+
# VCPUs is the number online when the VM is up, or the number
# configured otherwise.
'vcpus' : get_info('online_vcpus', int,
get_info('vcpus', int, 0)),
- 'up_time' : up_time,
- 'seclabel' : security.get_security_printlabel(info),
+ 'up_time' : up_time
}
+ # We're not supporting security stuff just yet via XenAPI
+
+ if serverType != SERVER_XEN_API:
+ from xen.util import security
+ parsed_info['seclabel'] = security.get_security_printlabel(info)
+ else:
+ parsed_info['seclabel'] = ""
+
+ if serverType == SERVER_XEN_API:
+ parsed_info['mem'] = get_info('memory_actual', int, 0) / 1024
+ cpu_times = get_info('cpu_time', lambda x : (x), 0.0)
+ if sum(cpu_times.values()) > 0:
+ parsed_info['cpu_time'] = sum(cpu_times.values()) / float(len(cpu_times.values()))
+ else:
+ parsed_info['cpu_time'] = 0
+ else:
+ parsed_info['mem'] = get_info('memory', int,0)
+ parsed_info['cpu_time'] = get_info('cpu_time', float, 0.0)
+
+ return parsed_info
+
def check_sched_type(sched):
if serverType == SERVER_XEN_API:
current = server.xenapi.host.get_sched_policy(server.xenapi.session.get_this_host())
@@ -797,17 +861,22 @@ def xm_label_list(doms):
output = []
format = '%(name)-32s %(domid)3s %(mem)5d %(vcpus)5d %(state)10s ' \
'%(cpu_time)8.1f %(seclabel)9s'
-
- for dom in doms:
- d = parse_doms_info(dom)
- if security.active_policy not in ['INACTIVE', 'NULL', 'DEFAULT']:
- if not d['seclabel']:
- d['seclabel'] = 'ERROR'
- elif security.active_policy in ['DEFAULT']:
- d['seclabel'] = 'DEFAULT'
- else:
- d['seclabel'] = 'INACTIVE'
- output.append((format % d, d['seclabel']))
+
+ if serverType != SERVER_XEN_API:
+ from xen.util import security
+
+ for dom in doms:
+ d = parse_doms_info(dom)
+
+ if security.active_policy not in ['INACTIVE', 'NULL', 'DEFAULT']:
+ if not d['seclabel']:
+ d['seclabel'] = 'ERROR'
+ elif security.active_policy in ['DEFAULT']:
+ d['seclabel'] = 'DEFAULT'
+ else:
+ d['seclabel'] = 'INACTIVE'
+
+ output.append((format % d, d['seclabel']))
#sort by labels
output.sort(lambda x,y: cmp( x[1].lower(), y[1].lower()))
@@ -816,7 +885,6 @@ def xm_label_list(doms):
def xm_vcpu_list(args):
-
if args:
dominfo = map(server.xend.domain.getVCPUInfo, args)
else:
@@ -1112,7 +1180,7 @@ def xm_mem_set(args):
dom = args[0]
if serverType == SERVER_XEN_API:
- mem_target = int_unit(args[1], 'k') * 1024
+ mem_target = int_unit(args[1], 'm') * 1024 * 1024
server.xenapi.VM.set_memory_dynamic_max(get_single_vm(dom), mem_target)
server.xenapi.VM.set_memory_dynamic_min(get_single_vm(dom), mem_target)
else:
@@ -1464,7 +1532,10 @@ def xm_sysrq(args):
arg_check(args, "sysrq", 2)
dom = args[0]
req = args[1]
- server.xend.domain.send_sysrq(dom, req)
+ if serverType == SERVER_XEN_API:
+ server.xenapi.VM.send_sysrq(get_single_vm(dom), req)
+ else:
+ server.xend.domain.send_sysrq(dom, req)
def xm_trigger(args):
vcpu = 0
@@ -1474,12 +1545,23 @@ def xm_trigger(args):
trigger = args[1]
if len(args) == 3:
vcpu = int(args[2])
-
- server.xend.domain.send_trigger(dom, trigger, vcpu)
+
+ if serverType == SERVER_XEN_API:
+ server.xenapi.VM.send_trigger(get_single_vm(dom), trigger, vcpu)
+ else:
+ server.xend.domain.send_trigger(dom, trigger, vcpu)
def xm_debug_keys(args):
arg_check(args, "debug-keys", 1)
- server.xend.node.send_debug_keys(str(args[0]))
+
+ keys = str(args[0])
+
+ if serverType == SERVER_XEN_API:
+ server.xenapi.host.send_debug_keys(
+ server.xenapi.session.get_this_host(),
+ keys)
+ else:
+ server.xend.node.send_debug_keys(keys)
def xm_top(args):
arg_check(args, "top", 0)
@@ -1605,12 +1687,21 @@ def xm_network_list(args):
(use_long, params) = arg_check_for_resource_list(args, "network-list")
dom = params[0]
- if use_long:
+
+ if serverType == SERVER_XEN_API:
+ vif_refs = server.xenapi.VM.get_VIFs(get_single_vm(dom))
+ vif_properties = \
+ map(server.xenapi.VIF.get_runtime_properties, vif_refs)
+ devs = map(lambda (handle, properties): [handle, map2sxp(properties)],
+ zip(range(len(vif_properties)), vif_properties))
+ else:
devs = server.xend.domain.getDeviceSxprs(dom, 'vif')
+
+ if use_long:
map(PrettyPrint.prettyprint, devs)
else:
hdr = 0
- for x in server.xend.domain.getDeviceSxprs(dom, 'vif'):
+ for x in devs:
if hdr == 0:
print 'Idx BE MAC Addr. handle state evt-ch tx-/rx-ring-ref BE-path'
hdr = 1
@@ -1630,12 +1721,25 @@ def xm_block_list(args):
(use_long, params) = arg_check_for_resource_list(args, "block-list")
dom = params[0]
- if use_long:
+
+ if serverType == SERVER_XEN_API:
+ vbd_refs = server.xenapi.VM.get_VBDs(get_single_vm(dom))
+ vbd_properties = \
+ map(server.xenapi.VBD.get_runtime_properties, vbd_refs)
+ vbd_devs = \
+ map(server.xenapi.VBD.get_device, vbd_refs)
+ vbd_devids = \
+ map(blkdev_name_to_number, vbd_devs)
+ devs = map(lambda (devid, prop): [devid, map2sxp(prop)],
+ zip(vbd_devids, vbd_properties))
+ else:
devs = server.xend.domain.getDeviceSxprs(dom, 'vbd')
+
+ if use_long:
map(PrettyPrint.prettyprint, devs)
else:
hdr = 0
- for x in server.xend.domain.getDeviceSxprs(dom, 'vbd'):
+ for x in devs:
if hdr == 0:
print 'Vdev BE handle state evt-ch ring-ref BE-path'
hdr = 1
@@ -1690,13 +1794,17 @@ def parse_block_configuration(args):
if len(args) == 5:
vbd.append(['backend', args[4]])
- # verify that policy permits attaching this resource
- if security.on():
- dominfo = server.xend.domain(dom)
- label = security.get_security_printlabel(dominfo)
- else:
- label = None
- security.res_security_check(args[1], label)
+ if serverType != SERVER_XEN_API:
+ # verify that policy permits attaching this resource
+ from xen.util import security
+
+ if security.on():
+ dominfo = server.xend.domain(dom)
+ label = security.get_security_printlabel(dominfo)
+ else:
+ label = None
+
+ security.res_security_check(args[1], label)
return (dom, vbd)
@@ -1704,8 +1812,45 @@ def parse_block_configuration(args):
def xm_block_attach(args):
arg_check(args, 'block-attach', 4, 5)
- (dom, vbd) = parse_block_configuration(args)
- server.xend.domain.device_create(dom, vbd)
+ if serverType == SERVER_XEN_API:
+ dom = args[0]
+ uname = args[1]
+ dev = args[2]
+ mode = args[3]
+
+ # First create new VDI
+ vdi_record = {
+ "name_label": "vdi" + str(uname.__hash__()),
+ "name_description": "",
+ "SR": get_default_SR(),
+ "virtual_size": 0,
+ "sector_size": 512,
+ "type": "system",
+ "sharable": False,
+ "read_only": mode!="w",
+ "other_config": {"location": uname}
+ }
+
+ vdi_ref = server.xenapi.VDI.create(vdi_record)
+
+ # Now create new VBD
+
+ vbd_record = {
+ "VM": get_single_vm(dom),
+ "VDI": vdi_ref,
+ "device": dev,
+ "bootable": True,
+ "mode": mode=="w" and "RW" or "RO",
+ "type": "Disk",
+ "qos_algorithm_type": "",
+ "qos_algorithm_params": {}
+ }
+
+ server.xenapi.VBD.create(vbd_record)
+
+ else:
+ (dom, vbd) = parse_block_configuration(args)
+ server.xend.domain.device_create(dom, vbd)
def xm_block_configure(args):
@@ -1723,15 +1868,65 @@ def xm_network_attach(args):
vif_params = ['type', 'mac', 'bridge', 'ip', 'script', \
'backend', 'vifname', 'rate', 'model']
- for a in args[1:]:
- vif_param = a.split("=")
- if len(vif_param) != 2 or vif_param[1] == '' or \
- vif_param[0] not in vif_params:
- err("Invalid argument: %s" % a)
- usage('network-attach')
- vif.append(vif_param)
+ if serverType == SERVER_XEN_API:
+ vif_record = {
+ "device": "eth0",
+ "network": get_default_Network(),
+ "VM": get_single_vm(dom),
+ "MAC": "",
+ "MTU": "",
+ "qos_algorithm_type": "",
+ "qos_algorithm_params": {},
+ "other_config": {}
+ }
+
+ def set(keys, val):
+ record = vif_record
+ for key in keys[:-1]:
+ record = record[key]
+ record[keys[-1]] = val
+
+ vif_conv = {
+ 'type':
+ lambda x: None,
+ 'mac':
+ lambda x: set(['MAC'], x),
+ 'bridge':
+ lambda x: set(['network'], get_net_from_bridge(x)),
+ 'ip':
+ lambda x: set(['other_config', 'ip'], x),
+ 'script':
+ lambda x: set(['other_config', 'script'], x),
+ 'backend':
+ lambda x: set(['other_config', 'backend'], x),
+ 'vifname':
+ lambda x: set(['device'], x),
+ 'rate':
+ lambda x: set(['qos_algorithm_params', 'rate'], x),
+ 'model':
+ lambda x: None
+ }
+
+ for a in args[1:]:
+ vif_param = a.split("=")
+ if len(vif_param) != 2 or vif_param[1] == '' or \
+ vif_param[0] not in vif_params:
+ err("Invalid argument: %s" % a)
+ usage('network-attach')
+ else:
+ vif_conv[vif_param[0]](vif_param[1])
- server.xend.domain.device_create(dom, vif)
+ print str(vif_record)
+ server.xenapi.VIF.create(vif_record)
+ else:
+ for a in args[1:]:
+ vif_param = a.split("=")
+ if len(vif_param) != 2 or vif_param[1] == '' or \
+ vif_param[0] not in vif_params:
+ err("Invalid argument: %s" % a)
+ usage('network-attach')
+ vif.append(vif_param)
+ server.xend.domain.device_create(dom, vif)
def detach(args, command, deviceClass):
@@ -1751,16 +1946,49 @@ def detach(args, command, deviceClass):
def xm_block_detach(args):
- try:
- detach(args, 'block-detach', 'vbd')
- return
- except:
- pass
- detach(args, 'block-detach', 'tap')
-
+ if serverType == SERVER_XEN_API:
+ arg_check(args, "xm_block_detach", 2, 3)
+ dom = args[0]
+ dev = args[1]
+ vbd_refs = server.xenapi.VM.get_VBDs(get_single_vm(dom))
+ vbd_refs = [vbd_ref for vbd_ref in vbd_refs
+ if server.xenapi.VBD.get_device(vbd_ref) == dev]
+ if len(vbd_refs) > 0:
+ vbd_ref = vbd_refs[0]
+ vdi_ref = server.xenapi.VBD.get_VDI(vbd_ref)
+
+ server.xenapi.VBD.destroy(vbd_ref)
+
+ if len(server.xenapi.VDI.get_VBDs(vdi_ref)) <= 0:
+ server.xenapi.VDI.destroy(vdi_ref)
+ else:
+ raise OptionError("Cannot find device '%s' in domain '%s'"
+ % (dev,dom))
+ else:
+ try:
+ detach(args, 'block-detach', 'vbd')
+ return
+ except:
+ pass
+ detach(args, 'block-detach', 'tap')
def xm_network_detach(args):
- detach(args, 'network-detach', 'vif')
+ if serverType == SERVER_XEN_API:
+ arg_check(args, "xm_block_detach", 2, 3)
+ dom = args[0]
+ devid = args[1]
+ vif_refs = server.xenapi.VM.get_VIFs(get_single_vm(dom))
+ vif_refs = [vif_ref for vif_ref in vif_refs
+ if server.xenapi.VIF.\
+ get_runtime_properties(vif_ref)["handle"] == devid]
+ if len(vif_refs) > 0:
+ vif_ref = vif_refs[0]
+
+ server.xenapi.VIF.destroy(vif_ref)
+ else:
+ print "Cannot find device '%s' in domain '%s'" % (devid,dom)
+ else:
+ detach(args, 'network-detach', 'vif')
def xm_vnet_list(args):
@@ -2001,13 +2229,17 @@ def _run_cmd(cmd, cmd_name, args):
err(str(e))
_usage(cmd_name)
print e.usage
- except security.ACMError, e:
- err(str(e))
- except:
- print "Unexpected error:", sys.exc_info()[0]
- print
- print "Please report to xen-devel@lists.xensource.com"
- raise
+ except Exception, e:
+ if serverType != SERVER_XEN_API:
+ from xen.util import security
+ if isinstance(e, security.ACMError):
+ err(str(e))
+ return False, 1
+ else:
+ print "Unexpected error:", sys.exc_info()[0]
+ print
+ print "Please report to xen-devel@lists.xensource.com"
+ raise
return False, 1
diff --git a/tools/python/xen/xm/new.py b/tools/python/xen/xm/new.py
index 2c6cae84b6..742c7ff8fd 100644
--- a/tools/python/xen/xm/new.py
+++ b/tools/python/xen/xm/new.py
@@ -22,6 +22,9 @@ from xen.xend import PrettyPrint
from xen.xend import sxp
from xen.xend import XendClient
+from xen.xm.main import serverType, SERVER_XEN_API
+from xen.xm.xenapi_create import *
+
from opts import *
from create import *
@@ -65,7 +68,15 @@ def main(argv):
if opts.vals.dryrun:
PrettyPrint.prettyprint(config)
- else:
+ return
+
+ if serverType == SERVER_XEN_API:
+ sxp2xml_inst = sxp2xml()
+ doc = sxp2xml_inst.convert_sxp_to_xml(config)
+
+ xenapi_create_inst = xenapi_create()
+ vm_refs = xenapi_create_inst.create(document = doc)
+ else:
make_unstarted_domain(opts, config)
if __name__ == '__main__':
diff --git a/tools/python/xen/xm/shutdown.py b/tools/python/xen/xm/shutdown.py
index 8ada520e62..8284a73bca 100644
--- a/tools/python/xen/xm/shutdown.py
+++ b/tools/python/xen/xm/shutdown.py
@@ -51,7 +51,7 @@ gopts.opt('reboot', short='R',
def wait_reboot(opts, doms, rcs):
if serverType == SERVER_XEN_API:
- opts.err("Cannot wait for reboot w/ XenAPI (yet)")
+ opts.err("Cannot wait for reboot w/ XenAPI (yet)")
while doms:
alive = server.xend.domains(0)
@@ -73,7 +73,7 @@ def wait_reboot(opts, doms, rcs):
def wait_shutdown(opts, doms):
while doms:
if serverType == SERVER_XEN_API:
- alive = [dom for dom in server.xenapi.VM.get_all()
+ alive = [dom for dom in server.xenapi.VM.get_all()
if server.xenapi.VM.get_power_state(dom) ==
XEN_API_VM_POWER_STATE[XEN_API_VM_POWER_STATE_RUNNING]]
else:
@@ -91,16 +91,16 @@ def wait_shutdown(opts, doms):
def shutdown(opts, doms, mode, wait):
rcs = {}
for d in doms:
- if serverType == SERVER_XEN_API:
- if mode == 'halt':
- server.xenapi.VM.clean_shutdown(d)
- if mode == 'reboot':
- server.xenapi.VM.clean_reboot(d)
- if mode == 'poweroff':
- server.xenapi.VM.clean_shutdown(d)
- else:
- rcs[d] = server.xend.domain.getRestartCount(d)
- server.xend.domain.shutdown(d, mode)
+ if serverType == SERVER_XEN_API:
+ if mode == 'halt':
+ server.xenapi.VM.clean_shutdown(d)
+ if mode == 'reboot':
+ server.xenapi.VM.clean_reboot(d)
+ if mode == 'poweroff':
+ server.xenapi.VM.clean_shutdown(d)
+ else:
+ rcs[d] = server.xend.domain.getRestartCount(d)
+ server.xend.domain.shutdown(d, mode)
if wait:
if mode == 'reboot':
@@ -135,7 +135,7 @@ def main_dom(opts, args):
if len(args) > 1: opts.err('No multiple domain parameters allowed')
dom = args[0]
if serverType == SERVER_XEN_API:
- dom = get_single_vm(dom)
+ dom = get_single_vm(dom)
mode = shutdown_mode(opts)
shutdown(opts, [ dom ], mode, opts.vals.wait)
diff --git a/tools/python/xen/xm/xenapi_create.py b/tools/python/xen/xm/xenapi_create.py
new file mode 100644
index 0000000000..52d91e101b
--- /dev/null
+++ b/tools/python/xen/xm/xenapi_create.py
@@ -0,0 +1,636 @@
+#!/usr/bin/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 Tom Wilkie <tom.wilkie@gmail.com>
+#============================================================================
+"""Domain creation using new XenAPI
+"""
+
+from xen.xm.main import server, get_default_SR
+from xml.dom.minidom import parse, getDOMImplementation
+from xml.dom.ext import PrettyPrint
+from xml.parsers.xmlproc import xmlproc, xmlval, xmldtd
+from xen.xend import sxp
+from xen.xend.XendAPIConstants import XEN_API_ON_NORMAL_EXIT, \
+ XEN_API_ON_CRASH_BEHAVIOUR
+
+
+import sys
+import os
+import traceback
+
+def log(_, msg):
+ #print "> " + msg
+ pass
+
+DEBUG = 0
+
+def get_name_label(node):
+ name_node = node.getElementsByTagName("name")[0]
+ label_node = name_node.getElementsByTagName("label")[0]
+ return " ".join([child.nodeValue for child in label_node.childNodes])
+
+def get_name_description(node):
+ name_node = node.getElementsByTagName("name")[0]
+ description_node = name_node.getElementsByTagName("description")[0]
+ return " ".join([child.nodeValue for child in description_node.childNodes])
+
+def get_text_in_child_node(node, child):
+ tag_node = node.getElementsByTagName(child)[0]
+ return tag_node.nodeValue
+
+def get_child_node_attribute(node, child, attribute):
+ tag_node = node.getElementsByTagName(child)[0]
+ return tag_node.attributes[attribute].value
+
+def get_child_nodes_as_dict(node, child_name,
+ key_attribute_name,
+ value_attribute_name):
+ return dict([(child.attributes[key_attribute_name].value,
+ child.attributes[value_attribute_name].value)
+ for child in node.getElementsByTagName(child_name)])
+
+def try_quietly(fn, *args):
+ try:
+ return fn(*args)
+ except:
+ return None
+
+class xenapi_create:
+
+ def __init__(self):
+ self.DEFAULT_STORAGE_REPOSITORY = get_default_SR()
+
+ self.dtd = "/usr/lib/python/xen/xm/create.dtd"
+
+ def create(self, filename=None, document=None):
+ """
+ Create a domain from an XML file or DOM tree
+ """
+ if filename is not None:
+ self.check_dtd(file)
+ document = parse(file)
+ elif document is not None:
+ self.check_dom_against_dtd(document)
+
+ self.check_doc(document)
+
+ vdis = document.getElementsByTagName("vdi")
+ vdi_refs_dict = self.create_vdis(vdis)
+
+ try:
+ vms = document.getElementsByTagName("vm")
+ return self.create_vms(vms, vdi_refs_dict)
+ except Exception, exn:
+ try_quietly(self.cleanup_vdis(vdi_refs_dict))
+ raise exn
+
+ # Methods to check xml file
+ # try to use dtd to check where possible
+ def check_dtd(self, file):
+ """
+ Check file against DTD.
+ Use this if possible as it gives nice
+ error messages
+ """
+ dtd = xmldtd.load_dtd(self.dtd)
+ parser = xmlproc.XMLProcessor()
+ parser.set_application(xmlval.ValidatingApp(dtd, parser))
+ parser.dtd = dtd
+ parser.ent = dtd
+ parser.parse_resource(file)
+
+ def check_dom_against_dtd(self, dom):
+ """
+ Check DOM again DTD.
+ Doesn't give as nice error messages.
+ (no location info)
+ """
+ dtd = xmldtd.load_dtd(self.dtd)
+ app = xmlval.ValidatingApp(dtd, self)
+ app.set_locator(self)
+ self.dom2sax(dom, app)
+
+ # Get errors back from ValidatingApp
+ def report_error(self, number, args=None):
+ self.errors = xmlproc.errors.english
+ try:
+ msg = self.errors[number]
+ if args != None:
+ msg = msg % args
+ except KeyError:
+ msg = self.errors[4002] % number # Unknown err msg :-)
+ print msg
+ sys.exit(-1)
+
+ # Here for compatibility with ValidatingApp
+ def get_line(self):
+ return -1
+
+ def get_column(self):
+ return -1
+
+ def dom2sax(self, dom, app):
+ """
+ Take a dom tree and tarverse it,
+ issuing SAX calls to app.
+ """
+ for child in dom.childNodes:
+ if child.nodeType == child.TEXT_NODE:
+ data = child.nodeValue
+ app.handle_data(data, 0, len(data))
+ else:
+ app.handle_start_tag(
+ child.nodeName,
+ self.attrs_to_dict(child.attributes))
+ self.dom2sax(child, app)
+ app.handle_end_tag(child.nodeName)
+
+ def attrs_to_dict(self, attrs):
+ return dict(attrs.items())
+
+ #
+ # Checks which cannot be done with dtd
+ #
+ def check_doc(self, doc):
+ vms = doc.getElementsByTagName("vm")
+ self.check_vms(vms)
+
+ def check_vms(self, vms):
+ map(self.check_vm, vms)
+
+ def check_vm(self, vm):
+ vifs = vm.getElementsByTagName("vif")
+ self.check_vifs(vifs)
+
+ def check_vifs(self, vifs):
+ map(self.check_vif, vifs)
+
+ def check_vif(self, vif):
+ """
+ Check that the vif has
+ either a bridge or network
+ name but not both
+ """
+ if "bridge" in vif.attributes.keys() \
+ and "network" in vif.attributes.keys():
+ raise "You cannot specify both a bridge and\
+ a network name."
+
+ # Cleanup methods here
+ def cleanup_vdis(self, vdi_refs_dict):
+ map(self.cleanup_vdi, vdi_refs_dict.values())
+
+ def cleanup_vdi(self, vdi_ref):
+ server.xenapi.VDI.destroy(vdi_ref)
+
+ def cleanup_vms(self, vm_refs):
+ map(self.cleanup_vm, vm_refs)
+
+ def cleanup_vm(self, vm_ref):
+ server.xenapi.VM.destroy(vm_ref)
+
+ # Create methods here
+ def create_vdis(self, vdis):
+ log(DEBUG, "create_vdis")
+ return dict(map(self.create_vdi, vdis))
+
+ def create_vdi(self, vdi):
+ log(DEBUG, "create_vdi")
+
+ vdi_record = {
+ "name_label": get_name_label(vdi),
+ "name_description": get_name_description(vdi),
+ "SR": self.DEFAULT_STORAGE_REPOSITORY,
+ "virtual_size": vdi.attributes["size"].value,
+ "type": vdi.attributes["type"].value,
+ "shareable": vdi.attributes["shareable"].value,
+ "read_only": vdi.attributes["read_only"].value,
+ "other_config": {"location":
+ vdi.attributes["src"].value}
+ }
+
+ key = vdi.attributes["name"].value
+ value = server.xenapi.VDI.create(vdi_record)
+
+ return (key, value)
+
+ def create_vms(self, vms, vdis):
+ log(DEBUG, "create_vms")
+ return map(lambda vm: self.create_vm(vm, vdis), vms)
+
+ def create_vm(self, vm, vdis):
+ log(DEBUG, "create_vm")
+
+ vm_record = {
+ "name_label":
+ get_name_label(vm),
+ "name_description":
+ get_name_description(vm),
+ "user_version":
+ get_text_in_child_node(vm, "version"),
+ "is_a_template":
+ vm.attributes["is_a_template"].value,
+ "auto_power_on":
+ vm.attributes["auto_power_on"].value,
+ "memory_static_max":
+ get_child_node_attribute(vm, "memory", "static_max"),
+ "memory_static_min":
+ get_child_node_attribute(vm, "memory", "static_min"),
+ "memory_dynamic_max":
+ get_child_node_attribute(vm, "memory", "dynamic_max"),
+ "memory_dynamic_min":
+ get_child_node_attribute(vm, "memory", "dynamic_min"),
+ "vcpus_params":
+ get_child_nodes_as_dict(vm, "vcpu_param", "key", "value"),
+ "vcpus_max":
+ vm.attributes["vcpus_max"].value,
+ "vcpus_at_startup":
+ vm.attributes["vcpus_at_startup"].value,
+ "actions_after_shutdown":
+ vm.attributes["actions_after_shutdown"].value,
+ "actions_after_reboot":
+ vm.attributes["actions_after_reboot"].value,
+ "actions_after_crash":
+ vm.attributes["actions_after_crash"].value,
+ "platform_std_VGA":
+ vm.attributes["platform_std_VGA"].value,
+ "platform_serial":
+ vm.attributes["platform_serial"].value,
+ "platform_localtime":
+ vm.attributes["platform_localtime"].value,
+ "platform_clock_offet":
+ vm.attributes["platform_clock_offet"].value,
+ "platform_enable_audio":
+ vm.attributes["platform_enable_audio"].value,
+ "PCI_bus":
+ vm.attributes["platform_enable_audio"].value,
+ "other_config":
+ get_child_nodes_as_dict(vm, "other_config", "key", "value")
+ }
+
+ if len(vm.getElementsByTagName("pv")) > 0:
+ vm_record.update({
+ "PV_bootloader":
+ get_child_node_attribute(vm, "pv", "bootloader"),
+ "PV_kernel":
+ get_child_node_attribute(vm, "pv", "kernel"),
+ "PV_ramdisk":
+ get_child_node_attribute(vm, "pv", "ramdisk"),
+ "PV_args":
+ get_child_node_attribute(vm, "pv", "args"),
+ "PV_bootloader_args":
+ get_child_node_attribute(vm, "pv", "bootloader_args")
+ })
+ else:
+ hvm = vm.getElementsByTagName("hvm")[0]
+ vm_record.update({
+ "HVM_boot_policy":
+ get_child_node_attribute(vm, "hvm", "boot_policy"),
+ "HVM_boot_params":
+ get_child_nodes_as_dict(hvm, "boot_params", "key", "value")
+ })
+ try:
+ vm_ref = server.xenapi.VM.create(vm_record)
+ except:
+ traceback.print_exc()
+ sys.exit(-1)
+
+ # Now create vbds
+
+ vbds = vm.getElementsByTagName("vbd")
+
+ self.create_vbds(vm_ref, vbds, vdis)
+
+ # Now create vifs
+
+ vifs = vm.getElementsByTagName("vif")
+
+ self.create_vifs(vm_ref, vifs)
+
+ return vm_ref
+
+ def create_vbds(self, vm_ref, vbds, vdis):
+ log(DEBUG, "create_vbds")
+ return map(lambda vbd: self.create_vbd(vm_ref, vbd, vdis), vbds)
+
+ def create_vbd(self, vm_ref, vbd, vdis):
+ log(DEBUG, "create_vbd")
+
+ vbd_record = {
+ "VM":
+ vm_ref,
+ "VDI":
+ vdis[vbd.attributes["vdi"].value],
+ "device":
+ vbd.attributes["device"].value,
+ "bootable":
+ vbd.attributes["bootable"].value,
+ "mode":
+ vbd.attributes["mode"].value,
+ "type":
+ vbd.attributes["type"].value,
+ "qos_algorithm_type":
+ vbd.attributes["qos_algorithm_type"].value,
+ "qos_algorithm_params":
+ get_child_nodes_as_dict(vbd,
+ "qos_algorithm_param", "key", "value")
+ }
+
+ return server.xenapi.VBD.create(vbd_record)
+
+ def create_vifs(self, vm_ref, vifs):
+ log(DEBUG, "create_vifs")
+ return map(lambda vif: self.create_vif(vm_ref, vif), vifs)
+
+ def create_vif(self, vm_ref, vif):
+ log(DEBUG, "create_vif")
+
+ if "bridge" in vif.attributes.keys():
+ raise "Not allowed to add by bridge just yet"
+ elif "network" in vif.attributes.keys():
+ network = [network_ref
+ for network_ref in server.xenapi.network.get_all()
+ if server.xenapi.network.get_name_label(network_ref)
+ == vif.attributes["network"].value][0]
+ else:
+ network = self._get_network_ref()
+
+ vif_record = {
+ "device":
+ vif.attributes["device"].value,
+ "network":
+ network,
+ "VM":
+ vm_ref,
+ "MAC":
+ vif.attributes["mac"].value,
+ "MTU":
+ vif.attributes["mtu"].value,
+ "qos_algorithm_type":
+ vif.attributes["qos_algorithm_type"].value,
+ "qos_algorithm_params":
+ get_child_nodes_as_dict(vif,
+ "qos_algorithm_param", "key", "value")
+ }
+
+ return server.xenapi.VIF.create(vif_record)
+
+ _network_refs = []
+
+ def _get_network_ref(self):
+ try:
+ return self._network_refs.pop(0)
+ except IndexError:
+ self._network_refs = server.xenapi.network.get_all()
+ return self._network_refs.pop(0)
+
+def get_child_by_name(exp, childname, default = None):
+ try:
+ return [child for child in sxp.children(exp)
+ if child[0] == childname][0][1]
+ except:
+ return default
+
+# Convert old sxp into new xml
+
+class sxp2xml:
+
+ def convert_sxp_to_xml(self, config, transient=False):
+
+ devices = [child for child in sxp.children(config)
+ if len(child) > 0 and child[0] == "device"]
+
+ vbds_sxp = map(lambda x: x[1], [device for device in devices
+ if device[1][0] == "vbd"])
+
+ vifs_sxp = map(lambda x: x[1], [device for device in devices
+ if device[1][0] == "vif"])
+ # Create XML Document
+
+ impl = getDOMImplementation()
+
+ document = impl.createDocument(None, "xm", None)
+
+ # Lets make the VM tag..
+
+ vm = document.createElement("vm")
+
+ # Some string compatibility
+
+ actions_after_shutdown \
+ = get_child_by_name(config, "on_poweroff", "destroy")
+ actions_after_reboot \
+ = get_child_by_name(config, "on_reboot", "restart")
+ actions_after_crash \
+ = get_child_by_name(config, "on_crash", "restart")
+
+ def conv_chk(val, vals):
+ val.replace("-", "_")
+ if val not in vals:
+ raise "Invalid value: " + val
+ else:
+ return val
+
+ actions_after_shutdown = conv_chk(actions_after_shutdown,\
+ XEN_API_ON_NORMAL_EXIT)
+ actions_after_reboot = conv_chk(actions_after_reboot, \
+ XEN_API_ON_NORMAL_EXIT)
+ actions_after_crash = conv_chk(actions_after_crash, \
+ XEN_API_ON_CRASH_BEHAVIOUR)
+ # Flesh out tag attributes
+
+ vm.attributes["is_a_template"] = "false"
+ vm.attributes["auto_power_on"] = "false"
+ vm.attributes["actions_after_shutdown"] \
+ = actions_after_shutdown
+ vm.attributes["actions_after_reboot"] \
+ = actions_after_reboot
+ vm.attributes["actions_after_crash"] \
+ = actions_after_crash
+ vm.attributes["platform_std_VGA"] = "false"
+ vm.attributes["platform_serial"] = ""
+ vm.attributes["platform_localtime"] = ""
+ vm.attributes["platform_clock_offet"] = ""
+ vm.attributes["platform_enable_audio"] = ""
+ vm.attributes["PCI_bus"] = ""
+
+ vm.attributes["vcpus_max"] \
+ = str(get_child_by_name(config, "vcpus", 1))
+ vm.attributes["vcpus_at_startup"] \
+ = str(get_child_by_name(config, "vcpus", 1))
+
+ # Make the name tag
+
+ vm.appendChild(self.make_name_tag(
+ get_child_by_name(config, "name"), document))
+
+ # Make version tag
+
+ version = document.createElement("version")
+ version.appendChild(document.createTextNode("1.0"))
+ vm.appendChild(version)
+
+ # Make pv or hvm tag
+
+ image = get_child_by_name(config, "image")
+
+ if image[0] == "linux":
+ pv = document.createElement("pv")
+ pv.attributes["kernel"] \
+ = get_child_by_name(image, "kernel", "")
+ pv.attributes["bootloader"] = ""
+ pv.attributes["ramdisk"] \
+ = get_child_by_name(image, "ramdisk", "")
+ pv.attributes["args"] \
+ = "root=" + get_child_by_name(image, "root", "") \
+ + " " + get_child_by_name(image, "args", "")
+ pv.attributes["bootloader_args"] = ""
+
+ vm.appendChild(pv)
+ elif image[0] == "hvm":
+ hvm = document.createElement("hvm")
+ hvm.attributes["boot_policy"] = ""
+
+ vm.appendChild(hvm)
+
+ # Make memory tag
+
+ memory = document.createElement("memory")
+
+ memory_str = str(int(
+ get_child_by_name(config, "memory"))*1024*1024)
+
+ memory.attributes["static_min"] = str(0)
+ memory.attributes["static_max"] = memory_str
+ memory.attributes["dynamic_min"] = memory_str
+ memory.attributes["dynamic_max"] = memory_str
+
+ if get_child_by_name(config, "maxmem"):
+ memory.attributes["static_max"] = \
+ str(int(get_child_by_name(config, "maxmem")*1024*1024))
+
+ vm.appendChild(memory)
+
+ # And now the vbds
+
+ vbds = map(lambda vbd: self.extract_vbd(vbd, document), vbds_sxp)
+
+ map(vm.appendChild, vbds)
+
+ # And now the vifs
+
+ vifs = map(lambda vif: self.extract_vif(vif, document), vifs_sxp)
+
+ map(vm.appendChild, vifs)
+
+ # transient?
+
+ if transient:
+ other_config = document.createElement("other_config")
+ other_config.attributes["key"] = "transient"
+ other_config.attributes["value"] = "True"
+ vm.appendChild(other_config)
+
+ # Add it to doc_root
+
+ document.documentElement.appendChild(vm)
+
+ # We want to pull out vdis
+
+ vdis = map(lambda vdb: self.extract_vdi(vdb, document), vbds_sxp)
+
+ map(document.documentElement.appendChild, vdis)
+
+ return document
+
+ def make_name_tag(self, label_text, document):
+ name = document.createElement("name")
+
+ label = document.createElement("label")
+ label.appendChild(document.createTextNode(str(label_text)))
+ name.appendChild(label)
+
+ description = document.createElement("description")
+ description.appendChild(document.createTextNode(" "))
+ name.appendChild(description)
+
+ return name
+
+ def extract_vbd(self, vbd_sxp, document):
+ src = get_child_by_name(vbd_sxp, "uname")
+ name = str(src.__hash__())
+
+ vbd = document.createElement("vbd")
+
+ vbd.attributes["name"] = "vdb" + name
+ vbd.attributes["vdi"] = "vdi" + name
+ vbd.attributes["mode"] \
+ = get_child_by_name(vbd_sxp, "mode") != "w" \
+ and "RO" or "RW"
+ vbd.attributes["device"] \
+ = get_child_by_name(vbd_sxp, "dev")
+ vbd.attributes["bootable"] = "1"
+ vbd.attributes["type"] = "disk"
+ vbd.attributes["qos_algorithm_type"] = ""
+
+ return vbd
+
+ def extract_vdi(self, vbd_sxp, document):
+ src = get_child_by_name(vbd_sxp, "uname")
+ name = "vdi" + str(src.__hash__())
+ path = src[src.find(":")+1:]
+
+ vdi = document.createElement("vdi")
+
+ vdi.attributes["src"] = src
+ vdi.attributes["read_only"] \
+ = (get_child_by_name(vbd_sxp, "mode") != "w") \
+ and "true" or "false"
+ vdi.attributes["size"] \
+ = str(os.path.getsize(path))
+ vdi.attributes["type"] = "system"
+ vdi.attributes["shareable"] = "false"
+ vdi.attributes["name"] = name
+
+ vdi.appendChild(self.make_name_tag(name, document))
+
+ return vdi
+
+ def extract_vif(self, vif_sxp, document):
+
+ vif = document.createElement("vif")
+
+ dev = get_child_by_name(vif_sxp, "vifname", "eth0")
+
+ vif.attributes["name"] \
+ = "vif" + str(dev.__hash__())
+ vif.attributes["mac"] \
+ = get_child_by_name(vif_sxp, "mac", "")
+ vif.attributes["mtu"] \
+ = get_child_by_name(vif_sxp, "mtu", "")
+ vif.attributes["device"] = dev
+ vif.attributes["qos_algorithm_type"] = ""
+
+ if get_child_by_name(vif_sxp, "bridge") is not None:
+ vif.attributes["bridge"] \
+ = get_child_by_name(vif_sxp, "bridge")
+
+ return vif
+
+
+
+
+
diff --git a/tools/xcutils/Makefile b/tools/xcutils/Makefile
index 6022505577..f8ac92f7d9 100644
--- a/tools/xcutils/Makefile
+++ b/tools/xcutils/Makefile
@@ -13,7 +13,7 @@ include $(XEN_ROOT)/tools/Rules.mk
PROGRAMS_INSTALL_DIR = /usr/$(LIBDIR)/xen/bin
-INCLUDES += -I $(XEN_LIBXC)
+INCLUDES += -I $(XEN_LIBXC) -I $(XEN_XENSTORE)
CFLAGS += -Werror -fno-strict-aliasing
CFLAGS += $(INCLUDES)
@@ -22,9 +22,9 @@ CFLAGS += $(INCLUDES)
CFLAGS += -Wp,-MD,.$(@F).d
PROG_DEP = .*.d
-PROGRAMS = xc_restore xc_save readnotes
+PROGRAMS = xc_restore xc_save readnotes
-LDLIBS = -L$(XEN_LIBXC) -lxenguest -lxenctrl
+LDLIBS = -L$(XEN_LIBXC) -L$(XEN_XENSTORE) -lxenguest -lxenctrl -lxenstore
.PHONY: all
all: build
diff --git a/tools/xcutils/xc_save.c b/tools/xcutils/xc_save.c
index 0c9530da4d..2285af4b97 100644
--- a/tools/xcutils/xc_save.c
+++ b/tools/xcutils/xc_save.c
@@ -12,7 +12,13 @@
#include <stdint.h>
#include <string.h>
#include <stdio.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <xs.h>
#include <xenctrl.h>
#include <xenguest.h>
@@ -31,6 +37,123 @@ static int suspend(int domid)
!strncmp(ans, "done\n", 5));
}
+/* For HVM guests, there are two sources of dirty pages: the Xen shadow
+ * log-dirty bitmap, which we get with a hypercall, and qemu's version.
+ * The protocol for getting page-dirtying data from qemu uses a
+ * double-buffered shared memory interface directly between xc_save and
+ * qemu-dm.
+ *
+ * xc_save calculates the size of the bitmaps and notifies qemu-dm
+ * through the store that it wants to share the bitmaps. qemu-dm then
+ * starts filling in the 'active' buffer.
+ *
+ * To change the buffers over, xc_save writes the other buffer number to
+ * the store and waits for qemu to acknowledge that it is now writing to
+ * the new active buffer. xc_save can then process and clear the old
+ * active buffer. */
+
+static char *qemu_active_path;
+static char *qemu_next_active_path;
+static struct xs_handle *xs;
+
+/* Get qemu to change buffers. */
+static void qemu_flip_buffer(int domid, int next_active)
+{
+ char digit = '0' + next_active;
+ unsigned int len;
+ char *active_str, **watch;
+ struct timeval tv;
+ fd_set fdset;
+
+ /* Tell qemu that we want it to start writing log-dirty bits to the
+ * other buffer */
+ if (!xs_write(xs, XBT_NULL, qemu_next_active_path, &digit, 1)) {
+ errx(1, "can't write next-active to store path (%s)\n",
+ qemu_next_active_path);
+ exit(1);
+ }
+
+ /* Wait a while for qemu to signal that it has switched to the new
+ * active buffer */
+ read_again:
+ tv.tv_sec = 5;
+ tv.tv_usec = 0;
+ FD_ZERO(&fdset);
+ FD_SET(xs_fileno(xs), &fdset);
+ if ((select(xs_fileno(xs) + 1, &fdset, NULL, NULL, &tv)) != 1) {
+ errx(1, "timed out waiting for qemu to switch buffers\n");
+ exit(1);
+ }
+ watch = xs_read_watch(xs, &len);
+ free(watch);
+
+ active_str = xs_read(xs, XBT_NULL, qemu_active_path, &len);
+ if (active_str == NULL || active_str[0] - '0' != next_active)
+ /* Watch fired but value is not yet right */
+ goto read_again;
+}
+
+static void * init_qemu_maps(int domid, unsigned int bitmap_size)
+{
+ key_t key;
+ char key_ascii[17] = {0,};
+ int shmid = -1;
+ void *seg;
+ char *path, *p;
+
+ /* Make a shared-memory segment */
+ while (shmid == -1)
+ {
+ key = rand(); /* No security, just a sequence of numbers */
+ shmid = shmget(key, 2 * bitmap_size,
+ IPC_CREAT|IPC_EXCL|S_IRUSR|S_IWUSR);
+ if (shmid == -1 && errno != EEXIST)
+ errx(1, "can't get shmem to talk to qemu-dm");
+ }
+
+ /* Map it into our address space */
+ seg = shmat(shmid, NULL, 0);
+ if (seg == (void *) -1)
+ errx(1, "can't map shmem to talk to qemu-dm");
+ memset(seg, 0, 2 * bitmap_size);
+
+ /* Write the size of it into the first 32 bits */
+ *(uint32_t *)seg = bitmap_size;
+
+ /* Tell qemu about it */
+ if ((xs = xs_daemon_open()) == NULL)
+ errx(1, "Couldn't contact xenstore");
+ if (!(path = xs_get_domain_path(xs, domid)))
+ errx(1, "can't get domain path in store");
+ if (!(path = realloc(path, strlen(path)
+ + strlen("/logdirty/next-active") + 1)))
+ errx(1, "no memory for constructing xenstore path");
+ strcat(path, "/logdirty/");
+ p = path + strlen(path);
+
+ strcpy(p, "key");
+ snprintf(key_ascii, 17, "%16.16llx", (unsigned long long) key);
+ if (!xs_write(xs, XBT_NULL, path, key_ascii, 16))
+ errx(1, "can't write key (%s) to store path (%s)\n", key_ascii, path);
+
+ /* Watch for qemu's indication of the active buffer, and request it
+ * to start writing to buffer 0 */
+ strcpy(p, "active");
+ if (!xs_watch(xs, path, "qemu-active-buffer"))
+ errx(1, "can't set watch in store (%s)\n", path);
+ if (!(qemu_active_path = strdup(path)))
+ errx(1, "no memory for copying xenstore path");
+
+ strcpy(p, "next-active");
+ if (!(qemu_next_active_path = strdup(path)))
+ errx(1, "no memory for copying xenstore path");
+
+ qemu_flip_buffer(domid, 0);
+
+ free(path);
+ return seg;
+}
+
int
main(int argc, char **argv)
@@ -52,9 +175,11 @@ main(int argc, char **argv)
flags = atoi(argv[5]);
if (flags & XCFLAGS_HVM)
- ret = xc_hvm_save(xc_fd, io_fd, domid, maxit, max_f, flags, &suspend);
+ ret = xc_hvm_save(xc_fd, io_fd, domid, maxit, max_f, flags,
+ &suspend, &init_qemu_maps, &qemu_flip_buffer);
else
- ret = xc_linux_save(xc_fd, io_fd, domid, maxit, max_f, flags, &suspend);
+ ret = xc_linux_save(xc_fd, io_fd, domid, maxit, max_f, flags,
+ &suspend);
xc_interface_close(xc_fd);
diff --git a/tools/xm-test/tests/block-create/07_block_attach_baddevice_neg.py b/tools/xm-test/tests/block-create/07_block_attach_baddevice_neg.py
index 3e9f0f2514..5d435e27c6 100644
--- a/tools/xm-test/tests/block-create/07_block_attach_baddevice_neg.py
+++ b/tools/xm-test/tests/block-create/07_block_attach_baddevice_neg.py
@@ -32,10 +32,10 @@ except ConsoleError, e:
status, output = traceCommand("xm block-attach %s phy:NOT-EXIST xvda1 w" % domain.getName())
eyecatcher = "Error"
-where = output.find(eyecatcher)
+where = re.compile(eyecatcher, re.IGNORECASE).search(output)
if status == 0:
FAIL("xm block-attach returned bad status, expected non 0, status is: %i" % status )
-elif where == -1:
+elif where is None:
FAIL("xm block-attach returned bad output, expected Error, output is: %s" % output )
try:
diff --git a/tools/xm-test/tests/block-create/08_block_attach_bad_filedevice_neg.py b/tools/xm-test/tests/block-create/08_block_attach_bad_filedevice_neg.py
index 802e101147..2fa482414a 100644
--- a/tools/xm-test/tests/block-create/08_block_attach_bad_filedevice_neg.py
+++ b/tools/xm-test/tests/block-create/08_block_attach_bad_filedevice_neg.py
@@ -31,10 +31,10 @@ except ConsoleError, e:
status, output = traceCommand("xm block-attach %s file:/dev/NOT-EXIST xvda1 w" % domain.getName())
eyecatcher = "Error"
-where = output.find(eyecatcher)
+where = re.compile(eyecatcher, re.IGNORECASE).search(output)
if status == 0:
FAIL("xm block-attach returned bad status, expected non 0, status is: %i" % status )
-elif where == -1:
+elif where is None:
FAIL("xm block-attach returned bad output, expected Error, output is: %s" % output )
try:
diff --git a/tools/xm-test/tests/network-attach/network_utils.py b/tools/xm-test/tests/network-attach/network_utils.py
index 084b5ebd90..93fe72a811 100644
--- a/tools/xm-test/tests/network-attach/network_utils.py
+++ b/tools/xm-test/tests/network-attach/network_utils.py
@@ -12,6 +12,18 @@ def count_eth(console):
FAIL(str(e))
return len(run['output'].splitlines())
+def get_state(domain_name, number):
+ s, o = traceCommand("xm network-list %s | awk '/^%d/ {print $5}'" %
+ (domain_name, number))
+ print o
+
+ if s != 0:
+ FAIL("network-list failed")
+ if o == "":
+ return 0
+ else:
+ return int(o)
+
def network_attach(domain_name, console):
eths_before = count_eth(console)
status, output = traceCommand("xm network-attach %s" % domain_name)
@@ -30,6 +42,13 @@ def network_detach(domain_name, console, num=0):
if status != 0:
return -1, "xm network-detach returned invalid %i != 0" % status
+ for i in range(10):
+ if get_state(domain_name, num) == 0:
+ break
+ time.sleep(1)
+ else:
+ FAIL("network-detach failed: device did not disappear")
+
eths_after = count_eth(console)
if eths_after != (eths_before-1):
return -2, "Network device was not actually disconnected from domU"
diff --git a/unmodified_drivers/linux-2.6/platform-pci/evtchn.c b/unmodified_drivers/linux-2.6/platform-pci/evtchn.c
index 9063e37f17..0c19cf5cda 100644
--- a/unmodified_drivers/linux-2.6/platform-pci/evtchn.c
+++ b/unmodified_drivers/linux-2.6/platform-pci/evtchn.c
@@ -167,7 +167,8 @@ EXPORT_SYMBOL(notify_remote_via_irq);
irqreturn_t evtchn_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
unsigned int l1i, port;
- int cpu = smp_processor_id();
+ /* XXX: All events are bound to vcpu0 but irq may be redirected. */
+ int cpu = 0; /*smp_processor_id();*/
irqreturn_t(*handler) (int, void *, struct pt_regs *);
shared_info_t *s = shared_info_area;
vcpu_info_t *v = &s->vcpu_info[cpu];
diff --git a/xen/arch/x86/Rules.mk b/xen/arch/x86/Rules.mk
index 899f28129c..86b9f33ab1 100644
--- a/xen/arch/x86/Rules.mk
+++ b/xen/arch/x86/Rules.mk
@@ -58,19 +58,7 @@ HDRS += $(wildcard $(BASEDIR)/include/asm-x86/hvm/*.h)
HDRS += $(wildcard $(BASEDIR)/include/asm-x86/hvm/svm/*.h)
HDRS += $(wildcard $(BASEDIR)/include/asm-x86/hvm/vmx/*.h)
-# Test for at least GCC v3.2.x.
-gcc-ver = $(shell $(CC) -dumpversion | sed -e 's/^\(.\)\.\(.\)\.\(.\)/\$(1)/')
-ifeq ($(call gcc-ver,1),1)
-$(error gcc-1.x.x unsupported - upgrade to at least gcc-3.2.x)
-endif
-ifeq ($(call gcc-ver,1),2)
-$(error gcc-2.x.x unsupported - upgrade to at least gcc-3.2.x)
-endif
-ifeq ($(call gcc-ver,1),3)
-ifeq ($(call gcc-ver,2),0)
-$(error gcc-3.0.x unsupported - upgrade to at least gcc-3.2.x)
-endif
-ifeq ($(call gcc-ver,2),1)
-$(error gcc-3.1.x unsupported - upgrade to at least gcc-3.2.x)
-endif
+# Require GCC v3.4+ (to avoid issues with alignment constraints in Xen headers)
+ifneq ($(call cc-ver,$(CC),0x030400),y)
+$(error Xen requires at least gcc-3.4)
endif
diff --git a/xen/arch/x86/hvm/hpet.c b/xen/arch/x86/hvm/hpet.c
index 419a886eba..b3fb6ffe29 100644
--- a/xen/arch/x86/hvm/hpet.c
+++ b/xen/arch/x86/hvm/hpet.c
@@ -29,6 +29,10 @@
#define S_TO_NS 1000000000ULL /* 1s = 10^9 ns */
#define S_TO_FS 1000000000000000ULL /* 1s = 10^15 fs */
+/* Frequency_of_TSC / frequency_of_HPET = 32 */
+#define TSC_PER_HPET_TICK 32
+#define guest_time_hpet(v) (hvm_get_guest_time(v) / TSC_PER_HPET_TICK)
+
#define HPET_ID 0x000
#define HPET_PERIOD 0x004
#define HPET_CFG 0x010
@@ -67,7 +71,9 @@
#define HPET_TN_INT_ROUTE_CAP_MASK (0xffffffffULL \
<< HPET_TN_INT_ROUTE_CAP_SHIFT)
-#define hpet_tick_to_ns(h, tick) ((s_time_t)(tick)*S_TO_NS/h->tsc_freq)
+#define hpet_tick_to_ns(h, tick) ((s_time_t)(tick)* \
+ (S_TO_NS*TSC_PER_HPET_TICK)/h->tsc_freq)
+
#define timer_config(h, n) (h->hpet.timers[n].config)
#define timer_enabled(h, n) (timer_config(h, n) & HPET_TN_ENABLE)
#define timer_is_periodic(h, n) (timer_config(h, n) & HPET_TN_PERIODIC)
@@ -108,7 +114,7 @@ static inline int hpet_check_access_length(
static inline uint64_t hpet_read_maincounter(HPETState *h)
{
if ( hpet_enabled(h) )
- return hvm_get_guest_time(h->vcpu) + h->mc_offset;
+ return guest_time_hpet(h->vcpu) + h->mc_offset;
else
return h->hpet.mc64;
}
@@ -144,7 +150,7 @@ static void hpet_stop_timer(HPETState *h, unsigned int tn)
/* the number of HPET tick that stands for
* 1/(2^10) second, namely, 0.9765625 milliseconds */
-#define HPET_TINY_TIME_SPAN (h->tsc_freq >> 10)
+#define HPET_TINY_TIME_SPAN ((h->tsc_freq >> 10) / TSC_PER_HPET_TICK)
static void hpet_set_timer(HPETState *h, unsigned int tn)
{
@@ -225,14 +231,14 @@ static void hpet_write(
if ( !(old_val & HPET_CFG_ENABLE) && (new_val & HPET_CFG_ENABLE) )
{
/* Enable main counter and interrupt generation. */
- h->mc_offset = h->hpet.mc64 - hvm_get_guest_time(h->vcpu);
+ h->mc_offset = h->hpet.mc64 - guest_time_hpet(h->vcpu);
for ( i = 0; i < HPET_TIMER_NUM; i++ )
hpet_set_timer(h, i);
}
else if ( (old_val & HPET_CFG_ENABLE) && !(new_val & HPET_CFG_ENABLE) )
{
/* Halt main counter and disable interrupt generation. */
- h->hpet.mc64 = h->mc_offset + hvm_get_guest_time(h->vcpu);
+ h->hpet.mc64 = h->mc_offset + guest_time_hpet(h->vcpu);
for ( i = 0; i < HPET_TIMER_NUM; i++ )
hpet_stop_timer(h, i);
}
@@ -384,7 +390,7 @@ static int hpet_save(struct domain *d, hvm_domain_context_t *h)
HPETState *hp = &d->arch.hvm_domain.pl_time.vhpet;
/* Write the proper value into the main counter */
- hp->hpet.mc64 = hp->mc_offset + hvm_get_guest_time(hp->vcpu);
+ hp->hpet.mc64 = hp->mc_offset + guest_time_hpet(hp->vcpu);
/* Save the HPET registers */
return hvm_save_entry(HPET, 0, h, &hp->hpet);
@@ -400,7 +406,7 @@ static int hpet_load(struct domain *d, hvm_domain_context_t *h)
return -EINVAL;
/* Recalculate the offset between the main counter and guest time */
- hp->mc_offset = hp->hpet.mc64 - hvm_get_guest_time(hp->vcpu);
+ hp->mc_offset = hp->hpet.mc64 - guest_time_hpet(hp->vcpu);
/* Restart the timers */
for ( i = 0; i < HPET_TIMER_NUM; i++ )
@@ -425,8 +431,8 @@ void hpet_init(struct vcpu *v)
h->hpet.capability = 0x8086A201ULL;
/* This is the number of femptoseconds per HPET tick. */
- /* Here we define HPET's frequency to be the same as the TSC's. */
- h->hpet.capability |= ((S_TO_FS/h->tsc_freq) << 32);
+ /* Here we define HPET's frequency to be 1/32 of the TSC's */
+ h->hpet.capability |= ((S_TO_FS*TSC_PER_HPET_TICK/h->tsc_freq) << 32);
for ( i = 0; i < HPET_TIMER_NUM; i++ )
{
diff --git a/xen/arch/x86/hvm/platform.c b/xen/arch/x86/hvm/platform.c
index 9ba8c3e4a3..185a7c2f55 100644
--- a/xen/arch/x86/hvm/platform.c
+++ b/xen/arch/x86/hvm/platform.c
@@ -415,6 +415,17 @@ static int mmio_decode(int address_bytes, unsigned char *opcode,
GET_OP_SIZE_FOR_NONEBYTE(*op_size);
return mem_reg(*op_size, opcode, mmio_op, rex);
+ case 0x08: /* or r8, m8 */
+ mmio_op->instr = INSTR_OR;
+ *op_size = BYTE;
+ GET_OP_SIZE_FOR_BYTE(size_reg);
+ return reg_mem(size_reg, opcode, mmio_op, rex);
+
+ case 0x09: /* or r32/16, m32/16 */
+ mmio_op->instr = INSTR_OR;
+ GET_OP_SIZE_FOR_NONEBYTE(*op_size);
+ return reg_mem(*op_size, opcode, mmio_op, rex);
+
case 0x0A: /* or m8, r8 */
mmio_op->instr = INSTR_OR;
*op_size = BYTE;
diff --git a/xen/arch/x86/hvm/svm/svm.c b/xen/arch/x86/hvm/svm/svm.c
index c6faddcd95..abff76a2b8 100644
--- a/xen/arch/x86/hvm/svm/svm.c
+++ b/xen/arch/x86/hvm/svm/svm.c
@@ -449,6 +449,9 @@ int svm_vmcb_restore(struct vcpu *v, struct hvm_hw_cpu *c)
vmcb->rflags = c->eflags;
v->arch.hvm_svm.cpu_shadow_cr0 = c->cr0;
+ vmcb->cr0 = c->cr0 | X86_CR0_WP | X86_CR0_ET;
+ if ( !paging_mode_hap(v->domain) )
+ vmcb->cr0 |= X86_CR0_PG;
#ifdef HVM_DEBUG_SUSPEND
printk("%s: cr3=0x%"PRIx64", cr0=0x%"PRIx64", cr4=0x%"PRIx64".\n",
@@ -482,7 +485,6 @@ int svm_vmcb_restore(struct vcpu *v, struct hvm_hw_cpu *c)
* first.
*/
HVM_DBG_LOG(DBG_LEVEL_VMMU, "CR3 c->cr3 = %"PRIx64"", c->cr3);
- /* current!=vcpu as not called by arch_vmx_do_launch */
mfn = gmfn_to_mfn(v->domain, c->cr3 >> PAGE_SHIFT);
if( !mfn_valid(mfn) || !get_page(mfn_to_page(mfn), v->domain) )
goto bad_cr3;
@@ -566,7 +568,7 @@ void svm_save_cpu_state(struct vcpu *v, struct hvm_hw_cpu *data)
data->msr_star = vmcb->star;
data->msr_cstar = vmcb->cstar;
data->msr_syscall_mask = vmcb->sfmask;
- data->msr_efer = vmcb->efer;
+ data->msr_efer = v->arch.hvm_svm.cpu_shadow_efer;
data->tsc = hvm_get_guest_time(v);
}
@@ -581,7 +583,12 @@ void svm_load_cpu_state(struct vcpu *v, struct hvm_hw_cpu *data)
vmcb->star = data->msr_star;
vmcb->cstar = data->msr_cstar;
vmcb->sfmask = data->msr_syscall_mask;
- vmcb->efer = data->msr_efer;
+ v->arch.hvm_svm.cpu_shadow_efer = data->msr_efer;
+ vmcb->efer = data->msr_efer | EFER_SVME;
+ /* VMCB's EFER.LME isn't set unless we're actually in long mode
+ * (see long_mode_do_msr_write()) */
+ if ( !(vmcb->efer & EFER_LMA) )
+ vmcb->efer &= ~EFER_LME;
hvm_set_guest_time(v, data->tsc);
}
@@ -741,6 +748,14 @@ static void svm_set_tsc_offset(struct vcpu *v, u64 offset)
static void svm_init_ap_context(
struct vcpu_guest_context *ctxt, int vcpuid, int trampoline_vector)
{
+ struct vcpu *v;
+ cpu_user_regs_t *regs;
+ u16 cs_sel;
+
+ /* We know this is safe because hvm_bringup_ap() does it */
+ v = current->domain->vcpu[vcpuid];
+ regs = &v->arch.guest_context.user_regs;
+
memset(ctxt, 0, sizeof(*ctxt));
/*
@@ -748,8 +763,19 @@ static void svm_init_ap_context(
* passed to us is page alligned and is the physicall frame number for
* the code. We will execute this code in real mode.
*/
+ cs_sel = trampoline_vector << 8;
ctxt->user_regs.eip = 0x0;
- ctxt->user_regs.cs = (trampoline_vector << 8);
+ ctxt->user_regs.cs = cs_sel;
+
+ /*
+ * This is the launch of an AP; set state so that we begin executing
+ * the trampoline code in real-mode.
+ */
+ svm_do_vmmcall_reset_to_realmode(v, regs);
+ /* Adjust the vmcb's hidden register state. */
+ v->arch.hvm_svm.vmcb->rip = 0;
+ v->arch.hvm_svm.vmcb->cs.sel = cs_sel;
+ v->arch.hvm_svm.vmcb->cs.base = (cs_sel << 4);
}
static void svm_init_hypercall_page(struct domain *d, void *hypercall_page)
@@ -894,32 +920,6 @@ static void svm_load_cpu_guest_regs(
svm_load_cpu_user_regs(v, regs);
}
-static void arch_svm_do_launch(struct vcpu *v)
-{
- svm_do_launch(v);
-
- if ( paging_mode_hap(v->domain) ) {
- v->arch.hvm_svm.vmcb->h_cr3 = pagetable_get_paddr(v->domain->arch.phys_table);
- }
-
- if ( v->vcpu_id != 0 )
- {
- cpu_user_regs_t *regs = &current->arch.guest_context.user_regs;
- u16 cs_sel = regs->cs;
- /*
- * This is the launch of an AP; set state so that we begin executing
- * the trampoline code in real-mode.
- */
- svm_do_vmmcall_reset_to_realmode(v, regs);
- /* Adjust the state to execute the trampoline code.*/
- v->arch.hvm_svm.vmcb->rip = 0;
- v->arch.hvm_svm.vmcb->cs.sel= cs_sel;
- v->arch.hvm_svm.vmcb->cs.base = (cs_sel << 4);
- }
-
- reset_stack_and_jump(svm_asm_do_launch);
-}
-
static void svm_ctxt_switch_from(struct vcpu *v)
{
svm_save_dr(v);
@@ -941,16 +941,30 @@ static void svm_ctxt_switch_to(struct vcpu *v)
svm_restore_dr(v);
}
+static void arch_svm_do_resume(struct vcpu *v)
+{
+ if ( v->arch.hvm_svm.launch_core != smp_processor_id() )
+ {
+ v->arch.hvm_svm.launch_core = smp_processor_id();
+ hvm_migrate_timers(v);
+ }
+
+ hvm_do_resume(v);
+ reset_stack_and_jump(svm_asm_do_resume);
+}
+
static int svm_vcpu_initialise(struct vcpu *v)
{
int rc;
- v->arch.schedule_tail = arch_svm_do_launch;
+ v->arch.schedule_tail = arch_svm_do_resume;
v->arch.ctxt_switch_from = svm_ctxt_switch_from;
v->arch.ctxt_switch_to = svm_ctxt_switch_to;
v->arch.hvm_svm.saved_irq_vector = -1;
+ v->arch.hvm_svm.launch_core = -1;
+
if ( (rc = svm_create_vmcb(v)) != 0 )
{
dprintk(XENLOG_WARNING,
@@ -1014,10 +1028,12 @@ void svm_npt_detect(void)
/* check CPUID for nested paging support */
cpuid(0x8000000A, &eax, &ebx, &ecx, &edx);
- if ( edx & 0x01 ) { /* nested paging */
+ if ( edx & 0x01 ) /* nested paging */
+ {
hap_capable_system = 1;
}
- else if ( opt_hap_enabled ) {
+ else if ( opt_hap_enabled )
+ {
printk(" nested paging is not supported by this CPU.\n");
hap_capable_system = 0; /* no nested paging, we disable flag. */
}
@@ -1075,24 +1091,6 @@ int start_svm(void)
return 1;
}
-void arch_svm_do_resume(struct vcpu *v)
-{
- /* pinning VCPU to a different core? */
- if ( v->arch.hvm_svm.launch_core == smp_processor_id()) {
- hvm_do_resume( v );
- reset_stack_and_jump( svm_asm_do_resume );
- }
- else {
- if (svm_dbg_on)
- printk("VCPU core pinned: %d to %d\n",
- v->arch.hvm_svm.launch_core, smp_processor_id() );
- v->arch.hvm_svm.launch_core = smp_processor_id();
- hvm_migrate_timers( v );
- hvm_do_resume( v );
- reset_stack_and_jump( svm_asm_do_resume );
- }
-}
-
static int svm_do_nested_pgfault(paddr_t gpa, struct cpu_user_regs *regs)
{
if (mmio_space(gpa)) {
diff --git a/xen/arch/x86/hvm/svm/vmcb.c b/xen/arch/x86/hvm/svm/vmcb.c
index 1d9c1569c3..446ddbb968 100644
--- a/xen/arch/x86/hvm/svm/vmcb.c
+++ b/xen/arch/x86/hvm/svm/vmcb.c
@@ -196,11 +196,13 @@ static int construct_vmcb(struct vcpu *v)
arch_svm->vmcb->exception_intercepts = MONITOR_DEFAULT_EXCEPTION_BITMAP;
- if ( paging_mode_hap(v->domain) ) {
+ if ( paging_mode_hap(v->domain) )
+ {
vmcb->cr0 = arch_svm->cpu_shadow_cr0;
vmcb->np_enable = 1; /* enable nested paging */
vmcb->g_pat = 0x0007040600070406ULL; /* guest PAT */
vmcb->exception_intercepts &= ~EXCEPTION_BITMAP_PG;
+ vmcb->h_cr3 = pagetable_get_paddr(v->domain->arch.phys_table);
}
return 0;
@@ -247,16 +249,6 @@ void svm_destroy_vmcb(struct vcpu *v)
arch_svm->vmcb = NULL;
}
-void svm_do_launch(struct vcpu *v)
-{
- hvm_stts(v);
-
- /* current core is the one we intend to perform the VMRUN on */
- v->arch.hvm_svm.launch_core = smp_processor_id();
-
- v->arch.schedule_tail = arch_svm_do_resume;
-}
-
static void svm_dump_sel(char *name, svm_segment_register_t *s)
{
printk("%s: sel=0x%04x, attr=0x%04x, limit=0x%08x, base=0x%016llx\n",
diff --git a/xen/arch/x86/hvm/svm/x86_32/exits.S b/xen/arch/x86/hvm/svm/x86_32/exits.S
index c465e3b7fa..604fa94c9e 100644
--- a/xen/arch/x86/hvm/svm/x86_32/exits.S
+++ b/xen/arch/x86/hvm/svm/x86_32/exits.S
@@ -80,15 +80,24 @@
popl %eax; \
addl $(NR_SKIPPED_REGS*4), %esp
- ALIGN
-
#define VMRUN .byte 0x0F,0x01,0xD8
#define VMLOAD .byte 0x0F,0x01,0xDA
#define VMSAVE .byte 0x0F,0x01,0xDB
#define STGI .byte 0x0F,0x01,0xDC
#define CLGI .byte 0x0F,0x01,0xDD
-ENTRY(svm_asm_do_launch)
+ENTRY(svm_asm_do_resume)
+ GET_CURRENT(%ebx)
+ xorl %ecx,%ecx
+ notl %ecx
+ cli # tests must not race interrupts
+ movl VCPU_processor(%ebx),%eax
+ shl $IRQSTAT_shift,%eax
+ test %ecx,irq_stat(%eax,1)
+ jnz svm_process_softirqs
+ call svm_intr_assist
+ call svm_load_cr2
+
CLGI
sti
GET_CURRENT(%ebx)
@@ -135,30 +144,7 @@ svm_stgi_label:
jmp svm_asm_do_resume
ALIGN
-
-ENTRY(svm_asm_do_resume)
-svm_test_all_events:
- GET_CURRENT(%ebx)
-/*test_all_events:*/
- xorl %ecx,%ecx
- notl %ecx
- cli # tests must not race interrupts
-/*test_softirqs:*/
- movl VCPU_processor(%ebx),%eax
- shl $IRQSTAT_shift,%eax
- test %ecx,irq_stat(%eax,1)
- jnz svm_process_softirqs
-svm_restore_all_guest:
- call svm_intr_assist
- call svm_load_cr2
- /*
- * Check if we are going back to AMD-V based VM
- * By this time, all the setups in the VMCB must be complete.
- */
- jmp svm_asm_do_launch
-
- ALIGN
svm_process_softirqs:
sti
call do_softirq
- jmp svm_test_all_events
+ jmp svm_asm_do_resume
diff --git a/xen/arch/x86/hvm/svm/x86_64/exits.S b/xen/arch/x86/hvm/svm/x86_64/exits.S
index 042cd6dc8e..cbff00cb5c 100644
--- a/xen/arch/x86/hvm/svm/x86_64/exits.S
+++ b/xen/arch/x86/hvm/svm/x86_64/exits.S
@@ -98,7 +98,17 @@
#define STGI .byte 0x0F,0x01,0xDC
#define CLGI .byte 0x0F,0x01,0xDD
-ENTRY(svm_asm_do_launch)
+ENTRY(svm_asm_do_resume)
+ GET_CURRENT(%rbx)
+ cli # tests must not race interrupts
+ movl VCPU_processor(%rbx),%eax
+ shl $IRQSTAT_shift, %rax
+ leaq irq_stat(%rip), %rdx
+ testl $~0, (%rdx, %rax, 1)
+ jnz svm_process_softirqs
+ call svm_intr_assist
+ call svm_load_cr2
+
CLGI
sti
GET_CURRENT(%rbx)
@@ -150,28 +160,8 @@ svm_stgi_label:
call svm_vmexit_handler
jmp svm_asm_do_resume
-ENTRY(svm_asm_do_resume)
-svm_test_all_events:
- GET_CURRENT(%rbx)
-/*test_all_events:*/
- cli # tests must not race interrupts
-/*test_softirqs:*/
- movl VCPU_processor(%rbx),%eax
- shl $IRQSTAT_shift, %rax
- leaq irq_stat(%rip), %rdx
- testl $~0, (%rdx, %rax, 1)
- jnz svm_process_softirqs
-svm_restore_all_guest:
- call svm_intr_assist
- call svm_load_cr2
- /*
- * Check if we are going back to AMD-V based VM
- * By this time, all the setups in the VMCB must be complete.
- */
- jmp svm_asm_do_launch
-
ALIGN
svm_process_softirqs:
sti
call do_softirq
- jmp svm_test_all_events
+ jmp svm_asm_do_resume
diff --git a/xen/arch/x86/hvm/vpic.c b/xen/arch/x86/hvm/vpic.c
index 3a5b2a16a8..5dfe1e4a6b 100644
--- a/xen/arch/x86/hvm/vpic.c
+++ b/xen/arch/x86/hvm/vpic.c
@@ -54,8 +54,8 @@ static int vpic_get_priority(struct hvm_hw_vpic *vpic, uint8_t mask)
if ( mask == 0 )
return VPIC_PRIO_NONE;
- /* prio = ffs(mask ROL vpic->priority_add); */
- asm ( "rol %%cl,%b1 ; bsf %1,%0"
+ /* prio = ffs(mask ROR vpic->priority_add); */
+ asm ( "ror %%cl,%b1 ; bsf %1,%0"
: "=r" (prio) : "r" ((uint32_t)mask), "c" (vpic->priority_add) );
return prio;
}
diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c
index 1c65070d15..e0590f33a2 100644
--- a/xen/arch/x86/mm.c
+++ b/xen/arch/x86/mm.c
@@ -108,6 +108,7 @@
#include <asm/x86_emulate.h>
#include <asm/e820.h>
#include <asm/hypercall.h>
+#include <asm/shared.h>
#include <public/memory.h>
#define MEM_LOG(_f, _a...) gdprintk(XENLOG_WARNING , _f "\n" , ## _a)
@@ -246,6 +247,11 @@ int memory_is_conventional_ram(paddr_t p)
return 0;
}
+unsigned long domain_get_maximum_gpfn(struct domain *d)
+{
+ return is_hvm_domain(d) ? d->arch.p2m.max_mapped_pfn : arch_get_max_pfn(d);
+}
+
void share_xen_page_with_guest(
struct page_info *page, struct domain *d, int readonly)
{
diff --git a/xen/arch/x86/mm/shadow/common.c b/xen/arch/x86/mm/shadow/common.c
index 15ebf1d541..efabba8223 100644
--- a/xen/arch/x86/mm/shadow/common.c
+++ b/xen/arch/x86/mm/shadow/common.c
@@ -36,7 +36,6 @@
#include <asm/current.h>
#include <asm/flushtlb.h>
#include <asm/shadow.h>
-#include <asm/shared.h>
#include "private.h"
@@ -2672,7 +2671,7 @@ sh_alloc_log_dirty_bitmap(struct domain *d)
{
ASSERT(d->arch.paging.shadow.dirty_bitmap == NULL);
d->arch.paging.shadow.dirty_bitmap_size =
- (arch_get_max_pfn(d) + (BITS_PER_LONG - 1)) &
+ (domain_get_maximum_gpfn(d) + (BITS_PER_LONG - 1)) &
~(BITS_PER_LONG - 1);
d->arch.paging.shadow.dirty_bitmap =
xmalloc_array(unsigned long,
@@ -2682,7 +2681,8 @@ sh_alloc_log_dirty_bitmap(struct domain *d)
d->arch.paging.shadow.dirty_bitmap_size = 0;
return -ENOMEM;
}
- memset(d->arch.paging.shadow.dirty_bitmap, 0, d->arch.paging.shadow.dirty_bitmap_size/8);
+ memset(d->arch.paging.shadow.dirty_bitmap, 0,
+ d->arch.paging.shadow.dirty_bitmap_size/8);
return 0;
}
diff --git a/xen/arch/x86/x86_64/asm-offsets.c b/xen/arch/x86/x86_64/asm-offsets.c
index 001a781235..93a047db3a 100644
--- a/xen/arch/x86/x86_64/asm-offsets.c
+++ b/xen/arch/x86/x86_64/asm-offsets.c
@@ -59,6 +59,7 @@ void __dummy__(void)
OFFSET(VCPU_domain, struct vcpu, domain);
OFFSET(VCPU_vcpu_info, struct vcpu, vcpu_info);
OFFSET(VCPU_trap_bounce, struct vcpu, arch.trap_bounce);
+ OFFSET(VCPU_int80_bounce, struct vcpu, arch.int80_bounce);
OFFSET(VCPU_thread_flags, struct vcpu, arch.flags);
OFFSET(VCPU_event_addr, struct vcpu,
arch.guest_context.event_callback_eip);
diff --git a/xen/arch/x86/x86_64/compat/entry.S b/xen/arch/x86/x86_64/compat/entry.S
index 3f1d1b8d07..095bd61f73 100644
--- a/xen/arch/x86/x86_64/compat/entry.S
+++ b/xen/arch/x86/x86_64/compat/entry.S
@@ -187,6 +187,10 @@ ENTRY(compat_post_handle_exception)
call compat_create_bounce_frame
jmp compat_test_all_events
+ENTRY(compat_int80_direct_trap)
+ call compat_create_bounce_frame
+ jmp compat_restore_all_guest
+
/* CREATE A BASIC EXCEPTION FRAME ON GUEST OS (RING-1) STACK: */
/* {[ERRCODE,] EIP, CS, EFLAGS, [ESP, SS]} */
/* %rdx: trap_bounce, %rbx: struct vcpu */
diff --git a/xen/arch/x86/x86_64/compat/traps.c b/xen/arch/x86/x86_64/compat/traps.c
index a7f24cecf8..0172e846c4 100644
--- a/xen/arch/x86/x86_64/compat/traps.c
+++ b/xen/arch/x86/x86_64/compat/traps.c
@@ -1,6 +1,7 @@
#ifdef CONFIG_COMPAT
#include <xen/event.h>
+#include <asm/regs.h>
#include <compat/callback.h>
#include <compat/arch-x86_32.h>
@@ -291,6 +292,9 @@ int compat_set_trap_table(XEN_GUEST_HANDLE(trap_info_compat_t) traps)
XLAT_trap_info(dst + cur.vector, &cur);
+ if ( cur.vector == 0x80 )
+ init_int80_direct_trap(current);
+
guest_handle_add_offset(traps, 1);
}
diff --git a/xen/arch/x86/x86_64/entry.S b/xen/arch/x86/x86_64/entry.S
index cffd89dced..17311c7242 100644
--- a/xen/arch/x86/x86_64/entry.S
+++ b/xen/arch/x86/x86_64/entry.S
@@ -222,6 +222,35 @@ bad_hypercall:
movq $-ENOSYS,UREGS_rax(%rsp)
jmp test_all_events
+ENTRY(int80_direct_trap)
+ pushq $0
+ SAVE_ALL
+
+ GET_CURRENT(%rbx)
+
+ /* Check that the callback is non-null. */
+ leaq VCPU_int80_bounce(%rbx),%rdx
+ cmp $0, TRAPBOUNCE_flags(%rdx)
+ jz int80_slow_path
+
+ movq VCPU_domain(%rbx),%rax
+ btl $_DOMF_compat,DOMAIN_domain_flags(%rax)
+ jc compat_int80_direct_trap
+
+ call create_bounce_frame
+ jmp restore_all_guest
+
+int80_slow_path:
+ /*
+ * Setup entry vector and error code as if this was a GPF caused by an
+ * IDT entry with DPL==0.
+ */
+ movl $((0x80 << 3) | 0x2),UREGS_error_code(%rsp)
+ movl $TRAP_gp_fault,UREGS_entry_vector(%rsp)
+ /* A GPF wouldn't have incremented the instruction pointer. */
+ sub $2,UREGS_rip(%rsp)
+ jmp handle_exception_saved
+
/* CREATE A BASIC EXCEPTION FRAME ON GUEST OS STACK: */
/* { RCX, R11, [DS-GS,] [CR2,] [ERRCODE,] RIP, CS, RFLAGS, RSP, SS } */
/* %rdx: trap_bounce, %rbx: struct vcpu */
@@ -359,6 +388,7 @@ ENTRY(ret_from_intr)
/* No special register assumptions. */
ENTRY(handle_exception)
SAVE_ALL
+handle_exception_saved:
testb $X86_EFLAGS_IF>>8,UREGS_eflags+1(%rsp)
jz exception_with_ints_disabled
sti
diff --git a/xen/arch/x86/x86_64/traps.c b/xen/arch/x86/x86_64/traps.c
index 0c6ee1de35..7a255c291f 100644
--- a/xen/arch/x86/x86_64/traps.c
+++ b/xen/arch/x86/x86_64/traps.c
@@ -247,6 +247,7 @@ unsigned long do_iret(void)
asmlinkage void syscall_enter(void);
asmlinkage void compat_hypercall(void);
+asmlinkage void int80_direct_trap(void);
void __init percpu_traps_init(void)
{
char *stack_bottom, *stack;
@@ -262,6 +263,7 @@ void __init percpu_traps_init(void)
#ifdef CONFIG_COMPAT
/* The hypercall entry vector is only accessible from ring 1. */
_set_gate(idt_table+HYPERCALL_VECTOR, 15, 1, &compat_hypercall);
+ _set_gate(idt_table+0x80, 15, 3, &int80_direct_trap);
#endif
}
@@ -346,6 +348,22 @@ void __init percpu_traps_init(void)
wrmsr(MSR_SYSCALL_MASK, EF_VM|EF_RF|EF_NT|EF_DF|EF_IE|EF_TF, 0U);
}
+void init_int80_direct_trap(struct vcpu *v)
+{
+ struct trap_info *ti = &v->arch.guest_context.trap_ctxt[0x80];
+ struct trap_bounce *tb = &v->arch.int80_bounce;
+
+ if ( !guest_gate_selector_okay(v->domain, ti->cs) )
+ return;
+
+ tb->flags = TBF_EXCEPTION;
+ tb->cs = ti->cs;
+ tb->eip = ti->address;
+
+ if ( null_trap_bounce(v, tb) )
+ tb->flags = 0;
+}
+
static long register_guest_callback(struct callback_register *reg)
{
long ret = 0;
diff --git a/xen/common/compat/memory.c b/xen/common/compat/memory.c
index 1301e42f04..53628d7a35 100644
--- a/xen/common/compat/memory.c
+++ b/xen/common/compat/memory.c
@@ -170,6 +170,7 @@ int compat_memory_op(unsigned int cmd, XEN_GUEST_HANDLE(void) compat)
case XENMEM_current_reservation:
case XENMEM_maximum_reservation:
+ case XENMEM_maximum_gpfn:
{
#define xen_domid_t domid_t
#define compat_domid_t domid_compat_t
@@ -325,6 +326,7 @@ int compat_memory_op(unsigned int cmd, XEN_GUEST_HANDLE(void) compat)
case XENMEM_maximum_ram_page:
case XENMEM_current_reservation:
case XENMEM_maximum_reservation:
+ case XENMEM_maximum_gpfn:
break;
case XENMEM_translate_gpfn_list:
diff --git a/xen/common/memory.c b/xen/common/memory.c
index f7e5efc0a5..edd2ebe8d5 100644
--- a/xen/common/memory.c
+++ b/xen/common/memory.c
@@ -584,6 +584,7 @@ long do_memory_op(unsigned long cmd, XEN_GUEST_HANDLE(void) arg)
case XENMEM_current_reservation:
case XENMEM_maximum_reservation:
+ case XENMEM_maximum_gpfn:
if ( copy_from_guest(&domid, arg, 1) )
return -EFAULT;
@@ -594,7 +595,19 @@ long do_memory_op(unsigned long cmd, XEN_GUEST_HANDLE(void) arg)
else if ( (d = rcu_lock_domain_by_id(domid)) == NULL )
return -ESRCH;
- rc = (op == XENMEM_current_reservation) ? d->tot_pages : d->max_pages;
+ switch ( op )
+ {
+ case XENMEM_current_reservation:
+ rc = d->tot_pages;
+ break;
+ case XENMEM_maximum_reservation:
+ rc = d->max_pages;
+ break;
+ default:
+ ASSERT(op == XENMEM_maximum_gpfn);
+ rc = domain_get_maximum_gpfn(d);
+ break;
+ }
if ( unlikely(domid != DOMID_SELF) )
rcu_unlock_domain(d);
diff --git a/xen/common/perfc.c b/xen/common/perfc.c
index d5bcd9b2e1..bbff5d7b5c 100644
--- a/xen/common/perfc.c
+++ b/xen/common/perfc.c
@@ -136,8 +136,8 @@ static xen_sysctl_perfc_desc_t perfc_d[NR_PERFCTRS];
static xen_sysctl_perfc_val_t *perfc_vals;
static int perfc_nbr_vals;
static int perfc_init = 0;
-static int perfc_copy_info(XEN_GUEST_HANDLE(xen_sysctl_perfc_desc_t) desc,
- XEN_GUEST_HANDLE(xen_sysctl_perfc_val_t) val)
+static int perfc_copy_info(XEN_GUEST_HANDLE_64(xen_sysctl_perfc_desc_t) desc,
+ XEN_GUEST_HANDLE_64(xen_sysctl_perfc_val_t) val)
{
unsigned int i, j;
unsigned int v = 0;
@@ -217,29 +217,20 @@ static int perfc_copy_info(XEN_GUEST_HANDLE(xen_sysctl_perfc_desc_t) desc,
int perfc_control(xen_sysctl_perfc_op_t *pc)
{
static DEFINE_SPINLOCK(lock);
- XEN_GUEST_HANDLE(xen_sysctl_perfc_desc_t) desc;
- XEN_GUEST_HANDLE(xen_sysctl_perfc_val_t) val;
int rc;
- /*
- * 64 bit guest handles cannot be passed as parameters to
- * functions so cast to a regular guest handle.
- */
- desc = guest_handle_cast(pc->desc, xen_sysctl_perfc_desc_t);
- val = guest_handle_cast(pc->val, xen_sysctl_perfc_val_t);
-
spin_lock(&lock);
switch ( pc->cmd )
{
case XEN_SYSCTL_PERFCOP_reset:
- perfc_copy_info(desc, val);
+ perfc_copy_info(pc->desc, pc->val);
perfc_reset(0);
rc = 0;
break;
case XEN_SYSCTL_PERFCOP_query:
- perfc_copy_info(desc, val);
+ perfc_copy_info(pc->desc, pc->val);
rc = 0;
break;
diff --git a/xen/include/asm-ia64/mm.h b/xen/include/asm-ia64/mm.h
index 166c22b1fe..e992f148ab 100644
--- a/xen/include/asm-ia64/mm.h
+++ b/xen/include/asm-ia64/mm.h
@@ -511,4 +511,6 @@ int steal_page(
#define domain_clamp_alloc_bitsize(d, b) (b)
+#define domain_get_maximum_gpfn(d) (-ENOSYS)
+
#endif /* __ASM_IA64_MM_H__ */
diff --git a/xen/include/asm-powerpc/mm.h b/xen/include/asm-powerpc/mm.h
index e258d5eb1b..ed6a10c67b 100644
--- a/xen/include/asm-powerpc/mm.h
+++ b/xen/include/asm-powerpc/mm.h
@@ -278,4 +278,6 @@ extern int steal_page(struct domain *d, struct page_info *page,
#define domain_clamp_alloc_bitsize(d, b) (b)
+#define domain_get_maximum_gpfn(d) (-ENOSYS)
+
#endif
diff --git a/xen/include/asm-x86/domain.h b/xen/include/asm-x86/domain.h
index 6c88e5abb0..bdc2f16f12 100644
--- a/xen/include/asm-x86/domain.h
+++ b/xen/include/asm-x86/domain.h
@@ -248,6 +248,9 @@ struct arch_vcpu
#ifdef CONFIG_X86_32
struct desc_struct int80_desc;
#endif
+#ifdef CONFIG_X86_64
+ struct trap_bounce int80_bounce;
+#endif
/* Virtual Machine Extensions */
struct hvm_vcpu hvm_vcpu;
diff --git a/xen/include/asm-x86/hvm/svm/svm.h b/xen/include/asm-x86/hvm/svm/svm.h
index b72eff2bc9..12459c72ef 100644
--- a/xen/include/asm-x86/hvm/svm/svm.h
+++ b/xen/include/asm-x86/hvm/svm/svm.h
@@ -29,8 +29,6 @@
#include <asm/i387.h>
extern void svm_dump_vmcb(const char *from, struct vmcb_struct *vmcb);
-extern void svm_do_launch(struct vcpu *v);
-extern void arch_svm_do_resume(struct vcpu *v);
extern u64 root_vmcb_pa[NR_CPUS];
diff --git a/xen/include/asm-x86/hvm/svm/vmcb.h b/xen/include/asm-x86/hvm/svm/vmcb.h
index 9dff3e65af..efedf27ae9 100644
--- a/xen/include/asm-x86/hvm/svm/vmcb.h
+++ b/xen/include/asm-x86/hvm/svm/vmcb.h
@@ -447,7 +447,7 @@ struct arch_svm_struct {
u32 *msrpm;
u64 vmexit_tsc; /* tsc read at #VMEXIT. for TSC_OFFSET */
int saved_irq_vector;
- u32 launch_core;
+ int launch_core;
unsigned long flags; /* VMCB flags */
unsigned long cpu_shadow_cr0; /* Guest value for CR0 */
diff --git a/xen/include/asm-x86/mm.h b/xen/include/asm-x86/mm.h
index b240e4b5ca..225605efd4 100644
--- a/xen/include/asm-x86/mm.h
+++ b/xen/include/asm-x86/mm.h
@@ -404,5 +404,6 @@ unsigned int domain_clamp_alloc_bitsize(struct domain *d, unsigned int bits);
# define domain_clamp_alloc_bitsize(d, b) (b)
#endif
+unsigned long domain_get_maximum_gpfn(struct domain *d);
#endif /* __ASM_X86_MM_H__ */
diff --git a/xen/include/asm-x86/processor.h b/xen/include/asm-x86/processor.h
index 321219c853..a878d86303 100644
--- a/xen/include/asm-x86/processor.h
+++ b/xen/include/asm-x86/processor.h
@@ -455,16 +455,16 @@ extern idt_entry_t *idt_tables[];
extern struct tss_struct init_tss[NR_CPUS];
-#ifdef CONFIG_X86_32
-
extern void init_int80_direct_trap(struct vcpu *v);
+
+#if defined(CONFIG_X86_32)
+
#define set_int80_direct_trap(_ed) \
(memcpy(idt_tables[(_ed)->processor] + 0x80, \
&((_ed)->arch.int80_desc), 8))
#else
-#define init_int80_direct_trap(_ed) ((void)0)
#define set_int80_direct_trap(_ed) ((void)0)
#endif
diff --git a/xen/include/public/arch-x86/xen-x86_32.h b/xen/include/public/arch-x86/xen-x86_32.h
index 2633ff082f..6728b818cd 100644
--- a/xen/include/public/arch-x86/xen-x86_32.h
+++ b/xen/include/public/arch-x86/xen-x86_32.h
@@ -103,7 +103,7 @@
(hnd).p = val; \
} while ( 0 )
#define uint64_aligned_t uint64_t __attribute__((aligned(8)))
-#define XEN_GUEST_HANDLE_64(name) __guest_handle_64_ ## name __attribute__((aligned(8)))
+#define XEN_GUEST_HANDLE_64(name) __guest_handle_64_ ## name
#endif
#ifndef __ASSEMBLY__
diff --git a/xen/include/public/foreign/Makefile b/xen/include/public/foreign/Makefile
index 7bf028e72a..c107c5ab7f 100644
--- a/xen/include/public/foreign/Makefile
+++ b/xen/include/public/foreign/Makefile
@@ -18,7 +18,7 @@ check-headers: checker
./checker > $(XEN_TARGET_ARCH).size
diff -u reference.size $(XEN_TARGET_ARCH).size
checker: checker.c $(headers)
- $(HOSTCC) $(CFLAGS) -o $@ $<
+ $(HOSTCC) $(HOSTCFLAGS) -o $@ $<
else
check-headers:
@echo "cross build: skipping check"
diff --git a/xen/include/public/memory.h b/xen/include/public/memory.h
index 97a6bbfea2..7b1ef44d32 100644
--- a/xen/include/public/memory.h
+++ b/xen/include/public/memory.h
@@ -129,6 +129,11 @@ DEFINE_XEN_GUEST_HANDLE(xen_memory_exchange_t);
#define XENMEM_maximum_reservation 4
/*
+ * Returns the maximum GPFN in use by the guest, or -ve errcode on failure.
+ */
+#define XENMEM_maximum_gpfn 14
+
+/*
* Returns a list of MFN bases of 2MB extents comprising the machine_to_phys
* mapping table. Architectures which do not have a m2p table do not implement
* this command.
diff --git a/xen/include/xen/trace.h b/xen/include/xen/trace.h
index 4f3649a394..cd1422bc09 100644
--- a/xen/include/xen/trace.h
+++ b/xen/include/xen/trace.h
@@ -41,11 +41,11 @@ void trace(u32 event, unsigned long d1, unsigned long d2,
do { \
if ( unlikely(tb_init_done) ) \
trace(e, \
- (unsigned long)d1, \
- (unsigned long)d2, \
- (unsigned long)d3, \
- (unsigned long)d4, \
- (unsigned long)d5); \
+ (unsigned long)(d1), \
+ (unsigned long)(d2), \
+ (unsigned long)(d3), \
+ (unsigned long)(d4), \
+ (unsigned long)(d5)); \
} while ( 0 )
/* Convenience macros for calling the trace function. */