[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] merge with xen-unstable.hg
# HG changeset patch # User awilliam@xxxxxxxxxxxx # Date 1174425578 21600 # Node ID 2216a45bf0582b36f7e0efb0dde0abbacdd8b895 # Parent f74e837c3902f85f775986b8f0235daadd2eb269 # Parent 3fd9b0c71b8c687b108a8bf671c9c4fc47046a0a merge with xen-unstable.hg --- patches/linux-2.6.18/crash-kernel-32-on-64.patch | 9 Config.mk | 6 docs/xen-api/xenapi-datamodel.tex | 241 ++- extras/mini-os/arch/x86/mm.c | 4 extras/mini-os/gnttab.c | 2 extras/mini-os/hypervisor.c | 4 extras/mini-os/include/wait.h | 7 extras/mini-os/include/xenbus.h | 1 extras/mini-os/xenbus/xenbus.c | 3 linux-2.6-xen-sparse/arch/i386/kernel/vsyscall-note-xen.S | 2 linux-2.6-xen-sparse/arch/i386/mm/pgtable-xen.c | 14 linux-2.6-xen-sparse/arch/x86_64/mm/init-xen.c | 6 linux-2.6-xen-sparse/arch/x86_64/mm/pageattr-xen.c | 98 - linux-2.6-xen-sparse/drivers/xen/netback/netback.c | 2 linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.c | 13 linux-2.6-xen-sparse/include/asm-i386/kexec.h | 3 linux-2.6-xen-sparse/mm/Kconfig | 157 ++ patches/linux-2.6.18/allow-i386-crash-kernels-to-handle-x86_64-dumps-fix.patch | 28 patches/linux-2.6.18/allow-i386-crash-kernels-to-handle-x86_64-dumps.patch | 51 patches/linux-2.6.18/series | 3 tools/Rules.mk | 5 tools/blktap/drivers/block-qcow.c | 1 tools/firmware/Makefile | 2 tools/firmware/hvmloader/32bitbios_support.c | 178 +- tools/firmware/hvmloader/acpi/build.c | 1 tools/firmware/hvmloader/hvmloader.c | 67 - tools/firmware/hvmloader/smbios.c | 48 tools/firmware/hvmloader/util.c | 21 tools/firmware/hvmloader/util.h | 12 tools/firmware/rombios/rombios.c | 242 +-- tools/ioemu/target-i386-dm/exec-dm.c | 16 tools/ioemu/target-i386-dm/helper2.c | 15 tools/ioemu/xenstore.c | 179 ++ tools/libxc/Makefile | 2 tools/libxc/xc_core.c | 6 tools/libxc/xc_core_x86.c | 24 tools/libxc/xc_hvm_build.c | 7 tools/libxc/xc_hvm_restore.c | 31 tools/libxc/xc_hvm_save.c | 69 - tools/libxc/xc_private.c | 14 tools/libxc/xenguest.h | 6 tools/libxc/xg_private.c | 4 tools/libxen/include/xen_vbd.h | 1 tools/libxen/include/xen_vdi.h | 44 tools/libxen/src/xen_vbd.c | 3 tools/libxen/src/xen_vdi.c | 98 + tools/libxen/test/test_bindings.c | 3 tools/python/scripts/test_hvm_create.py | 3 tools/python/scripts/test_vm_create.py | 6 tools/python/scripts/xapi.py | 11 tools/python/scripts/xapi.vdicfg.py | 3 tools/python/xen/lowlevel/xc/xc.c | 72 - tools/python/xen/util/blkif.py | 17 tools/python/xen/util/xmlrpclib2.py | 40 tools/python/xen/xend/XendAPI.py | 153 +- tools/python/xen/xend/XendCheckpoint.py | 4 tools/python/xen/xend/XendConfig.py | 107 + tools/python/xen/xend/XendDomain.py | 2 tools/python/xen/xend/XendDomainInfo.py | 108 + tools/python/xen/xend/XendLogging.py | 12 tools/python/xen/xend/XendNode.py | 3 tools/python/xen/xend/XendVDI.py | 27 tools/python/xen/xm/create.dtd | 118 + tools/python/xen/xm/create.py | 83 - tools/python/xen/xm/main.py | 370 ++++- tools/python/xen/xm/new.py | 13 tools/python/xen/xm/shutdown.py | 26 tools/python/xen/xm/xenapi_create.py | 636 ++++++++++ tools/xcutils/Makefile | 6 tools/xcutils/xc_save.c | 129 +- tools/xm-test/tests/block-create/07_block_attach_baddevice_neg.py | 4 tools/xm-test/tests/block-create/08_block_attach_bad_filedevice_neg.py | 4 tools/xm-test/tests/network-attach/network_utils.py | 19 unmodified_drivers/linux-2.6/platform-pci/evtchn.c | 3 xen/arch/x86/Rules.mk | 18 xen/arch/x86/hvm/hpet.c | 24 xen/arch/x86/hvm/platform.c | 11 xen/arch/x86/hvm/svm/svm.c | 100 - xen/arch/x86/hvm/svm/vmcb.c | 14 xen/arch/x86/hvm/svm/x86_32/exits.S | 40 xen/arch/x86/hvm/svm/x86_64/exits.S | 34 xen/arch/x86/hvm/vpic.c | 4 xen/arch/x86/mm.c | 6 xen/arch/x86/mm/shadow/common.c | 6 xen/arch/x86/x86_64/asm-offsets.c | 1 xen/arch/x86/x86_64/compat/entry.S | 4 xen/arch/x86/x86_64/compat/traps.c | 4 xen/arch/x86/x86_64/entry.S | 30 xen/arch/x86/x86_64/traps.c | 18 xen/common/compat/memory.c | 2 xen/common/memory.c | 15 xen/common/perfc.c | 17 xen/include/asm-ia64/mm.h | 2 xen/include/asm-powerpc/mm.h | 2 xen/include/asm-x86/domain.h | 3 xen/include/asm-x86/hvm/svm/svm.h | 2 xen/include/asm-x86/hvm/svm/vmcb.h | 2 xen/include/asm-x86/mm.h | 1 xen/include/asm-x86/processor.h | 6 xen/include/public/arch-x86/xen-x86_32.h | 2 xen/include/public/foreign/Makefile | 2 xen/include/public/memory.h | 5 xen/include/xen/trace.h | 10 103 files changed, 3032 insertions(+), 1085 deletions(-) diff -r f74e837c3902 -r 2216a45bf058 Config.mk --- a/Config.mk Tue Mar 20 10:07:11 2007 -0600 +++ b/Config.mk Tue Mar 20 15:19:38 2007 -0600 @@ -35,6 +35,12 @@ endif # Usage: cflags-y += $(call cc-option,$(CC),-march=winchip-c6,-march=i586) cc-option = $(shell if test -z "`$(1) $(2) -S -o /dev/null -xc \ /dev/null 2>&1`"; then echo "$(2)"; else echo "$(3)"; fi ;) + +# cc-ver +# 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 diff -r f74e837c3902 -r 2216a45bf058 docs/xen-api/xenapi-datamodel.tex --- a/docs/xen-api/xenapi-datamodel.tex Tue Mar 20 10:07:11 2007 -0600 +++ b/docs/xen-api/xenapi-datamodel.tex Tue Mar 20 15:19:38 2007 -0600 @@ -9359,10 +9359,10 @@ Quals & Field & Type & Description \\ $\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} - -{\bf Overview:} -Get the sector\_size field of the given VDI. - - \noindent {\bf Signature:} -\begin{verbatim} int get_sector_size (session_id s, VDI ref self)\end{verbatim} +\subsubsection{RPC name:~get\_type} + +{\bf Overview:} +Get the type field of the given VDI. + + \noindent {\bf Signature:} +\begin{verbatim} (vdi_type) get_type (session_id s, VDI ref self)\end{verbatim} \noindent{\bf Arguments:} @@ -9836,21 +9836,21 @@ Get the sector\_size field of the given \noindent {\bf Return Type:} {\tt -int -} - - -value of the field -\vspace{0.3cm} -\vspace{0.3cm} -\vspace{0.3cm} -\subsubsection{RPC name:~get\_type} - -{\bf Overview:} -Get the type field of the given VDI. - - \noindent {\bf Signature:} -\begin{verbatim} (vdi_type) get_type (session_id s, VDI ref self)\end{verbatim} +vdi\_type +} + + +value of the field +\vspace{0.3cm} +\vspace{0.3cm} +\vspace{0.3cm} +\subsubsection{RPC name:~get\_sharable} + +{\bf Overview:} +Get the sharable field of the given VDI. + + \noindent {\bf Signature:} +\begin{verbatim} bool get_sharable (session_id s, VDI ref self)\end{verbatim} \noindent{\bf Arguments:} @@ -9868,21 +9868,21 @@ Get the type field of the given VDI. \noindent {\bf Return Type:} {\tt -vdi\_type -} - - -value of the field -\vspace{0.3cm} -\vspace{0.3cm} -\vspace{0.3cm} -\subsubsection{RPC name:~get\_sharable} - -{\bf Overview:} -Get the sharable field of the given VDI. - - \noindent {\bf Signature:} -\begin{verbatim} bool get_sharable (session_id s, VDI ref self)\end{verbatim} +bool +} + + +value of the field +\vspace{0.3cm} +\vspace{0.3cm} +\vspace{0.3cm} +\subsubsection{RPC name:~set\_sharable} + +{\bf Overview:} +Set the sharable field of the given VDI. + + \noindent {\bf Signature:} +\begin{verbatim} void set_sharable (session_id s, VDI ref self, bool value)\end{verbatim} \noindent{\bf Arguments:} @@ -9894,6 +9894,40 @@ Get the sharable 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 + +\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:} + + +\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 + \end{tabular} \vspace{0.3cm} @@ -9908,13 +9942,13 @@ value of the field \vspace{0.3cm} \vspace{0.3cm} \vspace{0.3cm} -\subsubsection{RPC name:~set\_sharable} - -{\bf Overview:} -Set the sharable field of the given VDI. - - \noindent {\bf Signature:} -\begin{verbatim} void set_sharable (session_id s, VDI ref self, bool value)\end{verbatim} +\subsubsection{RPC name:~set\_read\_only} + +{\bf Overview:} +Set the read\_only field of the given VDI. + + \noindent {\bf Signature:} +\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} - -{\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} +\subsubsection{RPC name:~get\_other\_config} + +{\bf Overview:} +Get the other\_config field of the given VDI. + + \noindent {\bf Signature:} +\begin{verbatim} ((string -> string) Map) get_other_config (session_id s, VDI ref self)\end{verbatim} \noindent{\bf Arguments:} @@ -9966,21 +10000,21 @@ Get the read\_only field of the given VD \noindent {\bf Return Type:} {\tt -bool -} - - -value of the field -\vspace{0.3cm} -\vspace{0.3cm} -\vspace{0.3cm} -\subsubsection{RPC name:~set\_read\_only} - -{\bf Overview:} -Set the read\_only field of the given VDI. - - \noindent {\bf Signature:} -\begin{verbatim} void set_read_only (session_id s, VDI ref self, bool value)\end{verbatim} +(string $\rightarrow$ string) Map +} + + +value of the field +\vspace{0.3cm} +\vspace{0.3cm} +\vspace{0.3cm} +\subsubsection{RPC name:~set\_other\_config} + +{\bf Overview:} +Set the other\_config field of the given VDI. + + \noindent {\bf Signature:} +\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 VD {\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 -r f74e837c3902 -r 2216a45bf058 extras/mini-os/arch/x86/mm.c --- a/extras/mini-os/arch/x86/mm.c Tue Mar 20 10:07:11 2007 -0600 +++ b/extras/mini-os/arch/x86/mm.c Tue Mar 20 15:19:38 2007 -0600 @@ -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_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 -r f74e837c3902 -r 2216a45bf058 extras/mini-os/gnttab.c --- a/extras/mini-os/gnttab.c Tue Mar 20 10:07:11 2007 -0600 +++ b/extras/mini-os/gnttab.c Tue Mar 20 15:19:38 2007 -0600 @@ -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 -r f74e837c3902 -r 2216a45bf058 extras/mini-os/hypervisor.c --- a/extras/mini-os/hypervisor.c Tue Mar 20 10:07:11 2007 -0600 +++ b/extras/mini-os/hypervisor.c Tue Mar 20 15:19:38 2007 -0600 @@ -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 -r f74e837c3902 -r 2216a45bf058 extras/mini-os/include/wait.h --- a/extras/mini-os/include/wait.h Tue Mar 20 10:07:11 2007 -0600 +++ b/extras/mini-os/include/wait.h Tue Mar 20 15:19:38 2007 -0600 @@ -74,6 +74,13 @@ static inline void wake_up(struct wait_q 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 -r f74e837c3902 -r 2216a45bf058 extras/mini-os/include/xenbus.h --- a/extras/mini-os/include/xenbus.h Tue Mar 20 10:07:11 2007 -0600 +++ b/extras/mini-os/include/xenbus.h Tue Mar 20 15:19:38 2007 -0600 @@ -13,6 +13,7 @@ char *xenbus_read(xenbus_transaction_t x 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 -r f74e837c3902 -r 2216a45bf058 extras/mini-os/xenbus/xenbus.c --- a/extras/mini-os/xenbus/xenbus.c Tue Mar 20 10:07:11 2007 -0600 +++ b/extras/mini-os/xenbus/xenbus.c Tue Mar 20 15:19:38 2007 -0600 @@ -72,11 +72,12 @@ static void memcpy_from_ring(const void 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 -r f74e837c3902 -r 2216a45bf058 linux-2.6-xen-sparse/arch/i386/kernel/vsyscall-note-xen.S --- a/linux-2.6-xen-sparse/arch/i386/kernel/vsyscall-note-xen.S Tue Mar 20 10:07:11 2007 -0600 +++ b/linux-2.6-xen-sparse/arch/i386/kernel/vsyscall-note-xen.S Tue Mar 20 15:19:38 2007 -0600 @@ -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 -r f74e837c3902 -r 2216a45bf058 linux-2.6-xen-sparse/arch/i386/mm/pgtable-xen.c --- a/linux-2.6-xen-sparse/arch/i386/mm/pgtable-xen.c Tue Mar 20 10:07:11 2007 -0600 +++ b/linux-2.6-xen-sparse/arch/i386/mm/pgtable-xen.c Tue Mar 20 15:19:38 2007 -0600 @@ -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_pin_all(void) 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 -r f74e837c3902 -r 2216a45bf058 linux-2.6-xen-sparse/arch/x86_64/mm/init-xen.c --- a/linux-2.6-xen-sparse/arch/x86_64/mm/init-xen.c Tue Mar 20 10:07:11 2007 -0600 +++ b/linux-2.6-xen-sparse/arch/x86_64/mm/init-xen.c Tue Mar 20 15:19:38 2007 -0600 @@ -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 -r f74e837c3902 -r 2216a45bf058 linux-2.6-xen-sparse/arch/x86_64/mm/pageattr-xen.c --- a/linux-2.6-xen-sparse/arch/x86_64/mm/pageattr-xen.c Tue Mar 20 10:07:11 2007 -0600 +++ b/linux-2.6-xen-sparse/arch/x86_64/mm/pageattr-xen.c Tue Mar 20 15:19:38 2007 -0600 @@ -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; - - 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); - - switch_mm(mm, &init_mm, tsk); - - atomic_dec(&mm->mm_count); - BUG_ON(atomic_read(&mm->mm_count) == 0); - } - - task_unlock(tsk); - - if ( mm->context.pinned && (atomic_read(&mm->mm_count) == 1) && - !mm->context.has_foreign_mappings ) - mm_unpin(mm); + struct task_struct *tsk = current; + + 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); + + switch_mm(mm, &init_mm, tsk); + + atomic_dec(&mm->mm_count); + BUG_ON(atomic_read(&mm->mm_count) == 0); + } + + task_unlock(tsk); + + 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 -r f74e837c3902 -r 2216a45bf058 linux-2.6-xen-sparse/drivers/xen/netback/netback.c --- a/linux-2.6-xen-sparse/drivers/xen/netback/netback.c Tue Mar 20 10:07:11 2007 -0600 +++ b/linux-2.6-xen-sparse/drivers/xen/netback/netback.c Tue Mar 20 15:19:38 2007 -0600 @@ -1267,7 +1267,7 @@ static void net_tx_action(unsigned long /* 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 -r f74e837c3902 -r 2216a45bf058 linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.c --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.c Tue Mar 20 10:07:11 2007 -0600 +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.c Tue Mar 20 15:19:38 2007 -0600 @@ -110,7 +110,6 @@ int xb_write(const void *data, unsigned /* 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 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 -r f74e837c3902 -r 2216a45bf058 linux-2.6-xen-sparse/include/asm-i386/kexec.h --- a/linux-2.6-xen-sparse/include/asm-i386/kexec.h Tue Mar 20 10:07:11 2007 -0600 +++ b/linux-2.6-xen-sparse/include/asm-i386/kexec.h Tue Mar 20 15:19:38 2007 -0600 @@ -46,6 +46,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 diff -r f74e837c3902 -r 2216a45bf058 linux-2.6-xen-sparse/mm/Kconfig --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/linux-2.6-xen-sparse/mm/Kconfig Tue Mar 20 15:19:38 2007 -0600 @@ -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 -r f74e837c3902 -r 2216a45bf058 patches/linux-2.6.18/allow-i386-crash-kernels-to-handle-x86_64-dumps-fix.patch --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/patches/linux-2.6.18/allow-i386-crash-kernels-to-handle-x86_64-dumps-fix.patch Tue Mar 20 15:19:38 2007 -0600 @@ -0,0 +1,30 @@ +From: Andrew Morton <akpm@xxxxxxxxxxxxxxxxxxxx> + +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@xxxxxxxxxxxx> +Cc: Andi Kleen <ak@xxxxxxx> +Cc: Horms <horms@xxxxxxxxxxxx> +Cc: Ian Campbell <ian.campbell@xxxxxxxxxxxxx> +Cc: Magnus Damm <magnus.damm@xxxxxxxxx> +Cc: Vivek Goyal <vgoyal@xxxxxxxxxx> +Signed-off-by: Andrew Morton <akpm@xxxxxxxxxxxxxxxxxxxx> +--- + + 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 -r f74e837c3902 -r 2216a45bf058 patches/linux-2.6.18/allow-i386-crash-kernels-to-handle-x86_64-dumps.patch --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/patches/linux-2.6.18/allow-i386-crash-kernels-to-handle-x86_64-dumps.patch Tue Mar 20 15:19:38 2007 -0600 @@ -0,0 +1,66 @@ +From: Ian Campbell <ian.campbell@xxxxxxxxxxxxx> + +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@xxxxxxxxxxxxx> +Acked-by: Vivek Goyal <vgoyal@xxxxxxxxxx> +Cc: Horms <horms@xxxxxxxxxxxx> +Cc: Magnus Damm <magnus.damm@xxxxxxxxx> +Cc: "Eric W. Biederman" <ebiederm@xxxxxxxxxxxx> +Cc: Andi Kleen <ak@xxxxxxx> +Signed-off-by: Andrew Morton <akpm@xxxxxxxxxxxxxxxxxxxx> +--- + + 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 -r f74e837c3902 -r 2216a45bf058 patches/linux-2.6.18/crash-kernel-32-on-64.patch --- a/patches/linux-2.6.18/crash-kernel-32-on-64.patch Tue Mar 20 10:07:11 2007 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -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 -r f74e837c3902 -r 2216a45bf058 patches/linux-2.6.18/series --- a/patches/linux-2.6.18/series Tue Mar 20 10:07:11 2007 -0600 +++ b/patches/linux-2.6.18/series Tue Mar 20 15:19:38 2007 -0600 @@ -19,4 +19,5 @@ fixaddr-top.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 -r f74e837c3902 -r 2216a45bf058 tools/Rules.mk --- a/tools/Rules.mk Tue Mar 20 10:07:11 2007 -0600 +++ b/tools/Rules.mk Tue Mar 20 15:19:38 2007 -0600 @@ -22,6 +22,11 @@ LDFLAGS += $(shell getconf LFS_LDFLAGS) # 32-bit x86 does not perform well with -ve segment accesses on Xen. 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 -r f74e837c3902 -r 2216a45bf058 tools/blktap/drivers/block-qcow.c --- a/tools/blktap/drivers/block-qcow.c Tue Mar 20 10:07:11 2007 -0600 +++ b/tools/blktap/drivers/block-qcow.c Tue Mar 20 15:19:38 2007 -0600 @@ -1057,6 +1057,7 @@ int tdqcow_queue_write(struct disk_drive 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 -r f74e837c3902 -r 2216a45bf058 tools/firmware/Makefile --- a/tools/firmware/Makefile Tue Mar 20 10:07:11 2007 -0600 +++ b/tools/firmware/Makefile Tue Mar 20 15:19:38 2007 -0600 @@ -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 -r f74e837c3902 -r 2216a45bf058 tools/firmware/hvmloader/32bitbios_support.c --- a/tools/firmware/hvmloader/32bitbios_support.c Tue Mar 20 10:07:11 2007 -0600 +++ b/tools/firmware/hvmloader/32bitbios_support.c Tue Mar 20 15:19:38 2007 -0600 @@ -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; + Elf32_Sym *syms, *sym; + Elf32_Rel *rels; + char *code; + uint32_t *loc, fix; + int i, j; - 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; - } - - 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; + for ( i = 0; i < ehdr->e_shnum; i++ ) + { + if ( shdr[i].sh_type == SHT_RELA ) + printf("Unsupported section type SHT_RELA\n"); - /* must not have been stripped */ - if (shdr[i].sh_size == 0) - return -6; + if ( shdr[i].sh_type != SHT_REL ) + continue; - 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; + 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; - switch (ELF32_R_TYPE(rels[j].r_info)) { - case R_386_PC32: - *loc += (fix - (uint32_t)loc); - break; + 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; - case R_386_32: - *loc += fix; - break; - } + 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) ) + break; + + if ( i == ehdr->e_shnum ) + { + printf("Could not find " JUMPTABLE_SECTION_NAME " section in file.\n"); + return; } - /* 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); - } - } - break; - } + if ( jump_table == NULL ) + { + printf("Could not find jump table in file.\n"); + return; } - if (biosjumptable == NULL) { - printf("Could not find " JUMPTABLE_SECTION_NAME " section in file.\n"); - rc = -4; + memcpy(jump_table, (char *)shdr[i].sh_addr, shdr[i].sh_size); +} + +static void relocate_32bitbios(char *elfarray, uint32_t elfarraysize) +{ + uint32_t mask = (64 * 1024) - 1; + 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 0; + memcpy(highbiosarea, elfarray, elfarraysize); + relocate_elf(highbiosarea); + copy_jumptable(highbiosarea); } -static int relocate_32bitbios(unsigned char *elfarray, uint32_t elfarraysize) +void highbios_setup(void) { - 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; - } - - return rc; + relocate_32bitbios((char *)highbios_array, sizeof(highbios_array)); } - -int highbios_setup(void) -{ - return relocate_32bitbios((unsigned char *)highbios_array, - sizeof(highbios_array)); -} diff -r f74e837c3902 -r 2216a45bf058 tools/firmware/hvmloader/acpi/build.c --- a/tools/firmware/hvmloader/acpi/build.c Tue Mar 20 10:07:11 2007 -0600 +++ b/tools/firmware/hvmloader/acpi/build.c Tue Mar 20 15:19:38 2007 -0600 @@ -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 -r f74e837c3902 -r 2216a45bf058 tools/firmware/hvmloader/hvmloader.c --- a/tools/firmware/hvmloader/hvmloader.c Tue Mar 20 10:07:11 2007 -0600 +++ b/tools/firmware/hvmloader/hvmloader.c Tue Mar 20 15:19:38 2007 -0600 @@ -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. */ +/* + * 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) +{ 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 ) + /* 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; - /* Read CMOS register 0x38 (boot choice 2 and FDD test flag) */ - outb(0x70, 0x38); - boot_order = inb(0x71); - if ( (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) @@ -365,6 +396,8 @@ int main(void) acpi_sz = acpi_build_tables((uint8_t *)ACPI_PHYSICAL_ADDRESS); ASSERT((ACPI_PHYSICAL_ADDRESS + acpi_sz) <= 0xF0000); } + + cmos_write_memory_size(); if ( !check_amd() ) { diff -r f74e837c3902 -r 2216a45bf058 tools/firmware/hvmloader/smbios.c --- a/tools/firmware/hvmloader/smbios.c Tue Mar 20 10:07:11 2007 -0600 +++ b/tools/firmware/hvmloader/smbios.c Tue Mar 20 15:19:38 2007 -0600 @@ -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 -r f74e837c3902 -r 2216a45bf058 tools/firmware/hvmloader/util.c --- a/tools/firmware/hvmloader/util.c Tue Mar 20 10:07:11 2007 -0600 +++ b/tools/firmware/hvmloader/util.c Tue Mar 20 15:19:38 2007 -0600 @@ -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) @@ -59,6 +59,18 @@ uint32_t inl(uint16_t addr) uint32_t val; __asm__ __volatile__ ( "inl %%dx,%%eax" : "=a" (val) : "d" (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) @@ -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 -r f74e837c3902 -r 2216a45bf058 tools/firmware/hvmloader/util.h --- a/tools/firmware/hvmloader/util.h Tue Mar 20 10:07:11 2007 -0600 +++ b/tools/firmware/hvmloader/util.h Tue Mar 20 15:19:38 2007 -0600 @@ -25,6 +25,10 @@ uint8_t inb(uint16_t addr); 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); @@ -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); +/* 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 */ -int highbios_setup(void); - +void highbios_setup(void); #define isdigit(c) ((c) >= '0' && (c) <= '9') diff -r f74e837c3902 -r 2216a45bf058 tools/firmware/rombios/rombios.c --- a/tools/firmware/rombios/rombios.c Tue Mar 20 10:07:11 2007 -0600 +++ b/tools/firmware/rombios/rombios.c Tue Mar 20 15:19:38 2007 -0600 @@ -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(); - - // 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; - - // Get the amount of extended memory (above 1M) - regs.u.r8.cl = inb_cmos(0x30); - regs.u.r8.ch = inb_cmos(0x31); + } + + case 0x01: { + Bit16u off, e820_table_size = read_word(0xe000, 0x8) * 0x14; + Bit32u base, type, size; + + // 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); - // limit to 15M - if(regs.u.r16.cx > 0x3c00) - { - regs.u.r16.cx = 0x3c00; - } - - // 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); - - // Set configured memory equal to extended memory - regs.u.r16.ax = regs.u.r16.cx; - regs.u.r16.bx = regs.u.r16.dx; - break; + // 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; + } + + // 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; + } default: /* AH=0xE8?? but not implemented */ - goto int15_unimplemented; - } - break; + goto int15_unimplemented; + } + break; int15_unimplemented: // fall into the default default: diff -r f74e837c3902 -r 2216a45bf058 tools/ioemu/target-i386-dm/exec-dm.c --- a/tools/ioemu/target-i386-dm/exec-dm.c Tue Mar 20 10:07:11 2007 -0600 +++ b/tools/ioemu/target-i386-dm/exec-dm.c Tue Mar 20 15:19:38 2007 -0600 @@ -450,6 +450,9 @@ static inline int paddr_is_ram(target_ph #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_ 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 -r f74e837c3902 -r 2216a45bf058 tools/ioemu/target-i386-dm/helper2.c --- a/tools/ioemu/target-i386-dm/helper2.c Tue Mar 20 10:07:11 2007 -0600 +++ b/tools/ioemu/target-i386-dm/helper2.c Tue Mar 20 15:19:38 2007 -0600 @@ -439,6 +439,18 @@ void cpu_ioreq_xor(CPUState *env, ioreq_ 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) @@ -462,6 +474,9 @@ void __handle_ioreq(CPUState *env, ioreq break; 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 -r f74e837c3902 -r 2216a45bf058 tools/ioemu/xenstore.c --- a/tools/ioemu/xenstore.c Tue Mar 20 10:07:11 2007 -0600 +++ b/tools/ioemu/xenstore.c Tue Mar 20 15:19:38 2007 -0600 @@ -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 do 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 do 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,37 +149,41 @@ void xenstore_parse_domain_config(int do 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); @@ -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; @@ -209,6 +321,11 @@ void xenstore_process_event(void *opaque vec = xs_read_watch(xsh, &num); 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) @@ -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 -r f74e837c3902 -r 2216a45bf058 tools/libxc/Makefile --- a/tools/libxc/Makefile Tue Mar 20 10:07:11 2007 -0600 +++ b/tools/libxc/Makefile Tue Mar 20 15:19:38 2007 -0600 @@ -57,7 +57,7 @@ GUEST_SRCS-$(CONFIG_IA64) += xc_dom_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 -r f74e837c3902 -r 2216a45bf058 tools/libxc/xc_core.c --- a/tools/libxc/xc_core.c Tue Mar 20 10:07:11 2007 -0600 +++ b/tools/libxc/xc_core.c Tue Mar 20 15:19:38 2007 -0600 @@ -349,11 +349,7 @@ xc_domain_dumpcore_via_callback(int xc_h /* 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 -r f74e837c3902 -r 2216a45bf058 tools/libxc/xc_core_x86.c --- a/tools/libxc/xc_core_x86.c Tue Mar 20 10:07:11 2007 -0600 +++ b/tools/libxc/xc_core_x86.c Tue Mar 20 15:19:38 2007 -0600 @@ -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_handl 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_handl *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_d 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 -r f74e837c3902 -r 2216a45bf058 tools/libxc/xc_hvm_build.c --- a/tools/libxc/xc_hvm_build.c Tue Mar 20 10:07:11 2007 -0600 +++ b/tools/libxc/xc_hvm_build.c Tue Mar 20 15:19:38 2007 -0600 @@ -137,6 +137,12 @@ static void build_e820map(void *e820_pag 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 -r f74e837c3902 -r 2216a45bf058 tools/libxc/xc_hvm_restore.c --- a/tools/libxc/xc_hvm_restore.c Tue Mar 20 10:07:11 2007 -0600 +++ b/tools/libxc/xc_hvm_restore.c Tue Mar 20 15:19:38 2007 -0600 @@ -70,9 +70,6 @@ int xc_hvm_restore(int xc_handle, int io { 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 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; @@ -95,8 +90,6 @@ int xc_hvm_restore(int xc_handle, int io /* Types of the pfns in the current region */ unsigned long region_pfn_type[MAX_BATCH_SIZE]; - - 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 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 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 -r f74e837c3902 -r 2216a45bf058 tools/libxc/xc_hvm_save.c --- a/tools/libxc/xc_hvm_save.c Tue Mar 20 10:07:11 2007 -0600 +++ b/tools/libxc/xc_hvm_save.c Tue Mar 20 15:19:38 2007 -0600 @@ -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 */ #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] @@ -123,6 +129,7 @@ static inline int permute( int i, int nr return i; } + static uint64_t tv_to_us(struct timeval *new) { @@ -277,7 +284,9 @@ static int suspend_and_state(int (*suspe } 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 /* 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; @@ -308,9 +314,6 @@ int xc_hvm_save(int xc_handle, int io_fd /* A copy of hvm domain context buffer*/ 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,19 +366,11 @@ int xc_hvm_save(int xc_handle, int io_fd 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) { ERROR("Invalid HVM state record -- pfn count out of range: %lu", (info.max_memkb >> (PAGE_SHIFT - 10))); - 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; } @@ -392,8 +387,6 @@ int xc_hvm_save(int xc_handle, int io_fd "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 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 ) { @@ -508,13 +510,6 @@ int xc_hvm_save(int xc_handle, int io_fd N=0; 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 ){ @@ -663,8 +658,7 @@ int xc_hvm_save(int xc_handle, int io_fd 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 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 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 -r f74e837c3902 -r 2216a45bf058 tools/libxc/xc_private.c --- a/tools/libxc/xc_private.c Tue Mar 20 10:07:11 2007 -0600 +++ b/tools/libxc/xc_private.c Tue Mar 20 15:19:38 2007 -0600 @@ -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); @@ -286,6 +295,11 @@ int xc_memory_op(int xc_handle, break; 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; } diff -r f74e837c3902 -r 2216a45bf058 tools/libxc/xenguest.h --- a/tools/libxc/xenguest.h Tue Mar 20 10:07:11 2007 -0600 +++ b/tools/libxc/xenguest.h Tue Mar 20 15:19:38 2007 -0600 @@ -32,8 +32,10 @@ int xc_linux_save(int xc_handle, int io_ * @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 -r f74e837c3902 -r 2216a45bf058 tools/libxc/xg_private.c --- a/tools/libxc/xg_private.c Tue Mar 20 10:07:11 2007 -0600 +++ b/tools/libxc/xg_private.c Tue Mar 20 15:19:38 2007 -0600 @@ -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 -r f74e837c3902 -r 2216a45bf058 tools/libxen/include/xen_vbd.h --- a/tools/libxen/include/xen_vbd.h Tue Mar 20 10:07:11 2007 -0600 +++ b/tools/libxen/include/xen_vbd.h Tue Mar 20 15:19:38 2007 -0600 @@ -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 -r f74e837c3902 -r 2216a45bf058 tools/libxen/include/xen_vdi.h --- a/tools/libxen/include/xen_vdi.h Tue Mar 20 10:07:11 2007 -0600 +++ b/tools/libxen/include/xen_vdi.h Tue Mar 20 15:19:38 2007 -0600 @@ -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_ses /** - * 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 *sessi /** + * 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 @@ -311,6 +311,30 @@ xen_vdi_set_sharable(xen_session *sessio */ extern bool 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); /** diff -r f74e837c3902 -r 2216a45bf058 tools/libxen/src/xen_vbd.c --- a/tools/libxen/src/xen_vbd.c Tue Mar 20 10:07:11 2007 -0600 +++ b/tools/libxen/src/xen_vbd.c Tue Mar 20 15:19:38 2007 -0600 @@ -54,9 +54,6 @@ static const struct_member xen_vbd_recor { .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 -r f74e837c3902 -r 2216a45bf058 tools/libxen/src/xen_vdi.c --- a/tools/libxen/src/xen_vdi.c Tue Mar 20 10:07:11 2007 -0600 +++ b/tools/libxen/src/xen_vdi.c Tue Mar 20 15:19:38 2007 -0600 @@ -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_recor { .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_recor .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 *reco 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,22 +314,6 @@ xen_vdi_get_physical_utilisation(xen_ses bool -xen_vdi_get_sector_size(xen_session *session, int64_t *result, xen_vdi vdi) -{ - abstract_value param_values[] = - { - { .type = &abstract_type_string, - .u.string_val = vdi } - }; - - abstract_type result_type = abstract_type_int; - - XEN_CALL_("VDI.get_sector_size"); - return session->ok; -} - - -bool xen_vdi_get_type(xen_session *session, enum xen_vdi_type *result, xen_vdi vdi) { abstract_value param_values[] = @@ -378,6 +361,23 @@ xen_vdi_get_read_only(xen_session *sessi bool +xen_vdi_get_other_config(xen_session *session, xen_string_string_map **result, xen_vdi vdi) +{ + abstract_value param_values[] = + { + { .type = &abstract_type_string, + .u.string_val = vdi } + }; + + abstract_type result_type = abstract_type_string_string_map; + + *result = NULL; + XEN_CALL_("VDI.get_other_config"); + return session->ok; +} + + +bool xen_vdi_set_name_label(xen_session *session, xen_vdi vdi, char *label) { abstract_value param_values[] = @@ -458,6 +458,56 @@ xen_vdi_set_read_only(xen_session *sessi 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 -r f74e837c3902 -r 2216a45bf058 tools/libxen/test/test_bindings.c --- a/tools/libxen/test/test_bindings.c Tue Mar 20 10:07:11 2007 -0600 +++ b/tools/libxen/test/test_bindings.c Tue Mar 20 15:19:38 2007 -0600 @@ -421,8 +421,7 @@ static xen_vm create_new_vm(xen_session .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 -r f74e837c3902 -r 2216a45bf058 tools/python/scripts/test_hvm_create.py --- a/tools/python/scripts/test_hvm_create.py Tue Mar 20 10:07:11 2007 -0600 +++ b/tools/python/scripts/test_hvm_create.py Tue Mar 20 15:19:38 2007 -0600 @@ -39,14 +39,13 @@ local_vdi_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 -r f74e837c3902 -r 2216a45bf058 tools/python/scripts/test_vm_create.py --- a/tools/python/scripts/test_vm_create.py Tue Mar 20 10:07:11 2007 -0600 +++ b/tools/python/scripts/test_vm_create.py Tue Mar 20 15:19:38 2007 -0600 @@ -39,8 +39,7 @@ vdi_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 @@ local_vdi_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 -r f74e837c3902 -r 2216a45bf058 tools/python/scripts/xapi.py --- a/tools/python/scripts/xapi.py Tue Mar 20 10:07:11 2007 -0600 +++ b/tools/python/scripts/xapi.py Tue Mar 20 15:19:38 2007 -0600 @@ -40,8 +40,7 @@ VM_LIST_FORMAT = '%(name_label)-18s %(me ' %(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 -r f74e837c3902 -r 2216a45bf058 tools/python/scripts/xapi.vdicfg.py --- a/tools/python/scripts/xapi.vdicfg.py Tue Mar 20 10:07:11 2007 -0600 +++ b/tools/python/scripts/xapi.vdicfg.py Tue Mar 20 15:19:38 2007 -0600 @@ -1,7 +1,6 @@ name_label = 'VDI 1' 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 -r f74e837c3902 -r 2216a45bf058 tools/python/xen/lowlevel/xc/xc.c --- a/tools/python/xen/lowlevel/xc/xc.c Tue Mar 20 10:07:11 2007 -0600 +++ b/tools/python/xen/lowlevel/xc/xc.c Tue Mar 20 15:19:38 2007 -0600 @@ -50,17 +50,21 @@ static PyObject *pyxc_error_to_exception 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(Xc 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(Xc { 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(XcOb uint32_t dom; int fast; - if (!PyArg_ParseTuple(args, "ii", &dom, &fast)) - return NULL; - - if (xc_domain_resume(self->xc_handle, dom, fast) != 0) + if ( !PyArg_ParseTuple(args, "ii", &dom, &fast) ) + return NULL; + + if ( xc_domain_resume(self->xc_handle, dom, fast) != 0 ) return pyxc_error_to_exception(); Py_INCREF(zero); @@ -282,7 +286,7 @@ static PyObject *pyxc_domain_getinfo(XcO 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(XcO 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 -r f74e837c3902 -r 2216a45bf058 tools/python/xen/util/blkif.py --- a/tools/python/xen/util/blkif.py Tue Mar 20 10:07:11 2007 -0600 +++ b/tools/python/xen/util/blkif.py Tue Mar 20 15:19:38 2007 -0600 @@ -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 -r f74e837c3902 -r 2216a45bf058 tools/python/xen/util/xmlrpclib2.py --- a/tools/python/xen/util/xmlrpclib2.py Tue Mar 20 10:07:11 2007 -0600 +++ b/tools/python/xen/util/xmlrpclib2.py Tue Mar 20 15:19:38 2007 -0600 @@ -227,24 +227,30 @@ class TCPXMLRPCServer(SocketServer.Threa 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 -r f74e837c3902 -r 2216a45bf058 tools/python/xen/xend/XendAPI.py --- a/tools/python/xen/xend/XendAPI.py Tue Mar 20 10:07:11 2007 -0600 +++ b/tools/python/xen/xend/XendAPI.py Tue Mar 20 15:19:38 2007 -0600 @@ -35,6 +35,9 @@ from xen.xend.XendVMMetrics import XendV 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)')] @@ -748,6 +752,11 @@ class XendAPI(object): log_file = open(XendLogging.getLogFilename()) 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() @@ -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): @@ -1623,6 +1665,24 @@ class XendAPI(object): # attributes (ro) 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): @@ -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) @@ -1863,6 +1942,14 @@ class XendAPI(object): def VDI_set_read_only(self, session, vdi_ref, value): 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 @@ -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 -r f74e837c3902 -r 2216a45bf058 tools/python/xen/xend/XendCheckpoint.py --- a/tools/python/xen/xend/XendCheckpoint.py Tue Mar 20 10:07:11 2007 -0600 +++ b/tools/python/xen/xend/XendCheckpoint.py Tue Mar 20 15:19:38 2007 -0600 @@ -193,8 +193,8 @@ def restore(xd, fd, dominfo = None, paus 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 -r f74e837c3902 -r 2216a45bf058 tools/python/xen/xend/XendConfig.py --- a/tools/python/xen/xend/XendConfig.py Tue Mar 20 10:07:11 2007 -0600 +++ b/tools/python/xen/xend/XendConfig.py Tue Mar 20 15:19:38 2007 -0600 @@ -28,7 +28,7 @@ from xen.xend.XendConstants import DOM_S 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, '') @@ -631,13 +672,6 @@ class XendConfig(dict): for key in XENAPI_PLATFORM_CFG: 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', {}) @@ -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 -r f74e837c3902 -r 2216a45bf058 tools/python/xen/xend/XendDomain.py --- a/tools/python/xen/xend/XendDomain.py Tue Mar 20 10:07:11 2007 -0600 +++ b/tools/python/xen/xend/XendDomain.py Tue Mar 20 15:19:38 2007 -0600 @@ -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 -r f74e837c3902 -r 2216a45bf058 tools/python/xen/xend/XendDomainInfo.py --- a/tools/python/xen/xend/XendDomainInfo.py Tue Mar 20 10:07:11 2007 -0600 +++ b/tools/python/xen/xend/XendDomainInfo.py Tue Mar 20 15:19:38 2007 -0600 @@ -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 @@ -1898,6 +1926,11 @@ class XendDomainInfo: info_key = XendConfig.LEGACY_CFG_TO_XENAPI_CFG.get(key, key) if self._infoIsSet(info_key): to_store[key] = str(self.info[info_key]) + + if self._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: @@ -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 -r f74e837c3902 -r 2216a45bf058 tools/python/xen/xend/XendLogging.py --- a/tools/python/xen/xend/XendLogging.py Tue Mar 20 10:07:11 2007 -0600 +++ b/tools/python/xen/xend/XendLogging.py Tue Mar 20 15:19:38 2007 -0600 @@ -58,6 +58,18 @@ if 'TRACE' not in logging.__dict__: else: 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 -r f74e837c3902 -r 2216a45bf058 tools/python/xen/xend/XendNode.py --- a/tools/python/xen/xend/XendNode.py Tue Mar 20 10:07:11 2007 -0600 +++ b/tools/python/xen/xend/XendNode.py Tue Mar 20 15:19:38 2007 -0600 @@ -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 -r f74e837c3902 -r 2216a45bf058 tools/python/xen/xend/XendVDI.py --- a/tools/python/xen/xend/XendVDI.py Tue Mar 20 10:07:11 2007 -0600 +++ b/tools/python/xen/xend/XendVDI.py Tue Mar 20 15:19:38 2007 -0600 @@ -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 -r f74e837c3902 -r 2216a45bf058 tools/python/xen/xm/create.dtd --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/python/xen/xm/create.dtd Tue Mar 20 15:19:38 2007 -0600 @@ -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 -r f74e837c3902 -r 2216a45bf058 tools/python/xen/xm/create.py --- a/tools/python/xen/xm/create.py Tue Mar 20 10:07:11 2007 -0600 +++ b/tools/python/xen/xm/create.py Tue Mar 20 15:19:38 2007 -0600 @@ -28,12 +28,13 @@ import xmlrpclib 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 * @@ -96,6 +97,11 @@ gopts.opt('dryrun', short='n', gopts.opt('dryrun', short='n', fn=set_true, default=0, 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', @@ -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 -r f74e837c3902 -r 2216a45bf058 tools/python/xen/xm/main.py --- a/tools/python/xen/xm/main.py Tue Mar 20 10:07:11 2007 -0600 +++ b/tools/python/xen/xm/main.py Tue Mar 20 15:19:38 2007 -0600 @@ -33,11 +33,11 @@ import socket 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,10 +49,10 @@ 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 @@ -60,7 +60,8 @@ if not hasattr(getopt, 'gnu_getopt'): 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_c # 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] - else: - return server.xend.domains_with_state(True, state, full) + 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: + 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,19 +780,38 @@ 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: @@ -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 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: - devs = server.xend.domain.getDeviceSxprs(dom, 'vif') 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 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: - devs = server.xend.domain.getDeviceSxprs(dom, 'vbd') 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 xm_block_attach(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) - - server.xend.domain.device_create(dom, vif) + 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]) + + 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@xxxxxxxxxxxxxxxxxxx" - 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@xxxxxxxxxxxxxxxxxxx" + raise return False, 1 diff -r f74e837c3902 -r 2216a45bf058 tools/python/xen/xm/new.py --- a/tools/python/xen/xm/new.py Tue Mar 20 10:07:11 2007 -0600 +++ b/tools/python/xen/xm/new.py Tue Mar 20 15:19:38 2007 -0600 @@ -21,6 +21,9 @@ from xen.xend import PrettyPrint 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 -r f74e837c3902 -r 2216a45bf058 tools/python/xen/xm/shutdown.py --- a/tools/python/xen/xm/shutdown.py Tue Mar 20 10:07:11 2007 -0600 +++ b/tools/python/xen/xm/shutdown.py Tue Mar 20 15:19:38 2007 -0600 @@ -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_shutdown(opts, doms): 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 shutdown(opts, doms, mode, wait): 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 -r f74e837c3902 -r 2216a45bf058 tools/python/xen/xm/xenapi_create.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/python/xen/xm/xenapi_create.py Tue Mar 20 15:19:38 2007 -0600 @@ -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@xxxxxxxxx> +#============================================================================ +"""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 -r f74e837c3902 -r 2216a45bf058 tools/xcutils/Makefile --- a/tools/xcutils/Makefile Tue Mar 20 10:07:11 2007 -0600 +++ b/tools/xcutils/Makefile Tue Mar 20 15:19:38 2007 -0600 @@ -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 += -Wp,-MD,.$(@F).d 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 -r f74e837c3902 -r 2216a45bf058 tools/xcutils/xc_save.c --- a/tools/xcutils/xc_save.c Tue Mar 20 10:07:11 2007 -0600 +++ b/tools/xcutils/xc_save.c Tue Mar 20 15:19:38 2007 -0600 @@ -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> @@ -29,6 +35,123 @@ static int suspend(int domid) return (fgets(ans, sizeof(ans), stdin) != NULL && !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; } @@ -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 -r f74e837c3902 -r 2216a45bf058 tools/xm-test/tests/block-create/07_block_attach_baddevice_neg.py --- a/tools/xm-test/tests/block-create/07_block_attach_baddevice_neg.py Tue Mar 20 10:07:11 2007 -0600 +++ b/tools/xm-test/tests/block-create/07_block_attach_baddevice_neg.py Tue Mar 20 15:19:38 2007 -0600 @@ -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 -r f74e837c3902 -r 2216a45bf058 tools/xm-test/tests/block-create/08_block_attach_bad_filedevice_neg.py --- a/tools/xm-test/tests/block-create/08_block_attach_bad_filedevice_neg.py Tue Mar 20 10:07:11 2007 -0600 +++ b/tools/xm-test/tests/block-create/08_block_attach_bad_filedevice_neg.py Tue Mar 20 15:19:38 2007 -0600 @@ -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 -r f74e837c3902 -r 2216a45bf058 tools/xm-test/tests/network-attach/network_utils.py --- a/tools/xm-test/tests/network-attach/network_utils.py Tue Mar 20 10:07:11 2007 -0600 +++ b/tools/xm-test/tests/network-attach/network_utils.py Tue Mar 20 15:19:38 2007 -0600 @@ -11,6 +11,18 @@ def count_eth(console): except ConsoleError, e: 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) @@ -30,6 +42,13 @@ def network_detach(domain_name, console, 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 -r f74e837c3902 -r 2216a45bf058 unmodified_drivers/linux-2.6/platform-pci/evtchn.c --- a/unmodified_drivers/linux-2.6/platform-pci/evtchn.c Tue Mar 20 10:07:11 2007 -0600 +++ b/unmodified_drivers/linux-2.6/platform-pci/evtchn.c Tue Mar 20 15:19:38 2007 -0600 @@ -167,7 +167,8 @@ irqreturn_t evtchn_interrupt(int irq, vo 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 -r f74e837c3902 -r 2216a45bf058 xen/arch/x86/Rules.mk --- a/xen/arch/x86/Rules.mk Tue Mar 20 10:07:11 2007 -0600 +++ b/xen/arch/x86/Rules.mk Tue Mar 20 15:19:38 2007 -0600 @@ -58,19 +58,7 @@ HDRS += $(wildcard $(BASEDIR)/include/as 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) +# 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 -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 -endif diff -r f74e837c3902 -r 2216a45bf058 xen/arch/x86/hvm/hpet.c --- a/xen/arch/x86/hvm/hpet.c Tue Mar 20 10:07:11 2007 -0600 +++ b/xen/arch/x86/hvm/hpet.c Tue Mar 20 15:19:38 2007 -0600 @@ -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 uint64_t hpet_read_maincou 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 /* 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, 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, 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 -r f74e837c3902 -r 2216a45bf058 xen/arch/x86/hvm/platform.c --- a/xen/arch/x86/hvm/platform.c Tue Mar 20 10:07:11 2007 -0600 +++ b/xen/arch/x86/hvm/platform.c Tue Mar 20 15:19:38 2007 -0600 @@ -415,6 +415,17 @@ static int mmio_decode(int address_bytes 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 -r f74e837c3902 -r 2216a45bf058 xen/arch/x86/hvm/svm/svm.c --- a/xen/arch/x86/hvm/svm/svm.c Tue Mar 20 10:07:11 2007 -0600 +++ b/xen/arch/x86/hvm/svm/svm.c Tue Mar 20 15:19:38 2007 -0600 @@ -449,6 +449,9 @@ int svm_vmcb_restore(struct vcpu *v, str 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, str * 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, 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, 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_init_ap_context( 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 = ¤t->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,15 +941,29 @@ static void svm_ctxt_switch_to(struct vc 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 ) { @@ -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. */ } @@ -1073,24 +1089,6 @@ int start_svm(void) hvm_enable(&svm_function_table); 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) diff -r f74e837c3902 -r 2216a45bf058 xen/arch/x86/hvm/svm/vmcb.c --- a/xen/arch/x86/hvm/svm/vmcb.c Tue Mar 20 10:07:11 2007 -0600 +++ b/xen/arch/x86/hvm/svm/vmcb.c Tue Mar 20 15:19:38 2007 -0600 @@ -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; @@ -245,16 +247,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) diff -r f74e837c3902 -r 2216a45bf058 xen/arch/x86/hvm/svm/x86_32/exits.S --- a/xen/arch/x86/hvm/svm/x86_32/exits.S Tue Mar 20 10:07:11 2007 -0600 +++ b/xen/arch/x86/hvm/svm/x86_32/exits.S Tue Mar 20 15:19:38 2007 -0600 @@ -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 -r f74e837c3902 -r 2216a45bf058 xen/arch/x86/hvm/svm/x86_64/exits.S --- a/xen/arch/x86/hvm/svm/x86_64/exits.S Tue Mar 20 10:07:11 2007 -0600 +++ b/xen/arch/x86/hvm/svm/x86_64/exits.S Tue Mar 20 15:19:38 2007 -0600 @@ -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 -r f74e837c3902 -r 2216a45bf058 xen/arch/x86/hvm/vpic.c --- a/xen/arch/x86/hvm/vpic.c Tue Mar 20 10:07:11 2007 -0600 +++ b/xen/arch/x86/hvm/vpic.c Tue Mar 20 15:19:38 2007 -0600 @@ -54,8 +54,8 @@ static int vpic_get_priority(struct hvm_ 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 -r f74e837c3902 -r 2216a45bf058 xen/arch/x86/mm.c --- a/xen/arch/x86/mm.c Tue Mar 20 10:07:11 2007 -0600 +++ b/xen/arch/x86/mm.c Tue Mar 20 15:19:38 2007 -0600 @@ -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) @@ -244,6 +245,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( diff -r f74e837c3902 -r 2216a45bf058 xen/arch/x86/mm/shadow/common.c --- a/xen/arch/x86/mm/shadow/common.c Tue Mar 20 10:07:11 2007 -0600 +++ b/xen/arch/x86/mm/shadow/common.c Tue Mar 20 15:19:38 2007 -0600 @@ -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 { 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->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 -r f74e837c3902 -r 2216a45bf058 xen/arch/x86/x86_64/asm-offsets.c --- a/xen/arch/x86/x86_64/asm-offsets.c Tue Mar 20 10:07:11 2007 -0600 +++ b/xen/arch/x86/x86_64/asm-offsets.c Tue Mar 20 15:19:38 2007 -0600 @@ -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 -r f74e837c3902 -r 2216a45bf058 xen/arch/x86/x86_64/compat/entry.S --- a/xen/arch/x86/x86_64/compat/entry.S Tue Mar 20 10:07:11 2007 -0600 +++ b/xen/arch/x86/x86_64/compat/entry.S Tue Mar 20 15:19:38 2007 -0600 @@ -186,6 +186,10 @@ ENTRY(compat_post_handle_exception) jz compat_test_all_events 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]} */ diff -r f74e837c3902 -r 2216a45bf058 xen/arch/x86/x86_64/compat/traps.c --- a/xen/arch/x86/x86_64/compat/traps.c Tue Mar 20 10:07:11 2007 -0600 +++ b/xen/arch/x86/x86_64/compat/traps.c Tue Mar 20 15:19:38 2007 -0600 @@ -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_HAND XLAT_trap_info(dst + cur.vector, &cur); + if ( cur.vector == 0x80 ) + init_int80_direct_trap(current); + guest_handle_add_offset(traps, 1); } diff -r f74e837c3902 -r 2216a45bf058 xen/arch/x86/x86_64/entry.S --- a/xen/arch/x86/x86_64/entry.S Tue Mar 20 10:07:11 2007 -0600 +++ b/xen/arch/x86/x86_64/entry.S Tue Mar 20 15:19:38 2007 -0600 @@ -221,6 +221,35 @@ bad_hypercall: 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 } */ @@ -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 -r f74e837c3902 -r 2216a45bf058 xen/arch/x86/x86_64/traps.c --- a/xen/arch/x86/x86_64/traps.c Tue Mar 20 10:07:11 2007 -0600 +++ b/xen/arch/x86/x86_64/traps.c Tue Mar 20 15:19:38 2007 -0600 @@ -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 } @@ -344,6 +346,22 @@ void __init percpu_traps_init(void) wrmsr(MSR_STAR, 0, (FLAT_RING3_CS32<<16) | __HYPERVISOR_CS); 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) diff -r f74e837c3902 -r 2216a45bf058 xen/common/compat/memory.c --- a/xen/common/compat/memory.c Tue Mar 20 10:07:11 2007 -0600 +++ b/xen/common/compat/memory.c Tue Mar 20 15:19:38 2007 -0600 @@ -170,6 +170,7 @@ int compat_memory_op(unsigned int cmd, X 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, X case XENMEM_maximum_ram_page: case XENMEM_current_reservation: case XENMEM_maximum_reservation: + case XENMEM_maximum_gpfn: break; case XENMEM_translate_gpfn_list: diff -r f74e837c3902 -r 2216a45bf058 xen/common/memory.c --- a/xen/common/memory.c Tue Mar 20 10:07:11 2007 -0600 +++ b/xen/common/memory.c Tue Mar 20 15:19:38 2007 -0600 @@ -584,6 +584,7 @@ long do_memory_op(unsigned long cmd, XEN 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 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 -r f74e837c3902 -r 2216a45bf058 xen/common/perfc.c --- a/xen/common/perfc.c Tue Mar 20 10:07:11 2007 -0600 +++ b/xen/common/perfc.c Tue Mar 20 15:19:38 2007 -0600 @@ -136,8 +136,8 @@ static xen_sysctl_perfc_val_t *perfc_val 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 @@ int perfc_control(xen_sysctl_perfc_op_t 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 -r f74e837c3902 -r 2216a45bf058 xen/include/asm-ia64/mm.h --- a/xen/include/asm-ia64/mm.h Tue Mar 20 10:07:11 2007 -0600 +++ b/xen/include/asm-ia64/mm.h Tue Mar 20 15:19:38 2007 -0600 @@ -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 -r f74e837c3902 -r 2216a45bf058 xen/include/asm-powerpc/mm.h --- a/xen/include/asm-powerpc/mm.h Tue Mar 20 10:07:11 2007 -0600 +++ b/xen/include/asm-powerpc/mm.h Tue Mar 20 15:19:38 2007 -0600 @@ -278,4 +278,6 @@ extern int steal_page(struct domain *d, #define domain_clamp_alloc_bitsize(d, b) (b) +#define domain_get_maximum_gpfn(d) (-ENOSYS) + #endif diff -r f74e837c3902 -r 2216a45bf058 xen/include/asm-x86/domain.h --- a/xen/include/asm-x86/domain.h Tue Mar 20 10:07:11 2007 -0600 +++ b/xen/include/asm-x86/domain.h Tue Mar 20 15:19:38 2007 -0600 @@ -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 -r f74e837c3902 -r 2216a45bf058 xen/include/asm-x86/hvm/svm/svm.h --- a/xen/include/asm-x86/hvm/svm/svm.h Tue Mar 20 10:07:11 2007 -0600 +++ b/xen/include/asm-x86/hvm/svm/svm.h Tue Mar 20 15:19:38 2007 -0600 @@ -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 -r f74e837c3902 -r 2216a45bf058 xen/include/asm-x86/hvm/svm/vmcb.h --- a/xen/include/asm-x86/hvm/svm/vmcb.h Tue Mar 20 10:07:11 2007 -0600 +++ b/xen/include/asm-x86/hvm/svm/vmcb.h Tue Mar 20 15:19:38 2007 -0600 @@ -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 -r f74e837c3902 -r 2216a45bf058 xen/include/asm-x86/mm.h --- a/xen/include/asm-x86/mm.h Tue Mar 20 10:07:11 2007 -0600 +++ b/xen/include/asm-x86/mm.h Tue Mar 20 15:19:38 2007 -0600 @@ -404,5 +404,6 @@ unsigned int domain_clamp_alloc_bitsize( # define domain_clamp_alloc_bitsize(d, b) (b) #endif +unsigned long domain_get_maximum_gpfn(struct domain *d); #endif /* __ASM_X86_MM_H__ */ diff -r f74e837c3902 -r 2216a45bf058 xen/include/asm-x86/processor.h --- a/xen/include/asm-x86/processor.h Tue Mar 20 10:07:11 2007 -0600 +++ b/xen/include/asm-x86/processor.h Tue Mar 20 15:19:38 2007 -0600 @@ -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 -r f74e837c3902 -r 2216a45bf058 xen/include/public/arch-x86/xen-x86_32.h --- a/xen/include/public/arch-x86/xen-x86_32.h Tue Mar 20 10:07:11 2007 -0600 +++ b/xen/include/public/arch-x86/xen-x86_32.h Tue Mar 20 15:19:38 2007 -0600 @@ -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 -r f74e837c3902 -r 2216a45bf058 xen/include/public/foreign/Makefile --- a/xen/include/public/foreign/Makefile Tue Mar 20 10:07:11 2007 -0600 +++ b/xen/include/public/foreign/Makefile Tue Mar 20 15:19:38 2007 -0600 @@ -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 -r f74e837c3902 -r 2216a45bf058 xen/include/public/memory.h --- a/xen/include/public/memory.h Tue Mar 20 10:07:11 2007 -0600 +++ b/xen/include/public/memory.h Tue Mar 20 15:19:38 2007 -0600 @@ -129,6 +129,11 @@ DEFINE_XEN_GUEST_HANDLE(xen_memory_excha #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 -r f74e837c3902 -r 2216a45bf058 xen/include/xen/trace.h --- a/xen/include/xen/trace.h Tue Mar 20 10:07:11 2007 -0600 +++ b/xen/include/xen/trace.h Tue Mar 20 15:19:38 2007 -0600 @@ -41,11 +41,11 @@ void trace(u32 event, unsigned long d1, 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. */ _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |