merge with xen-unstable.hg

This commit is contained in:
awilliam@xenbuild2.aw committed 2007-03-20 15:19:38 -06:00
commit ebdb5845be
103 files changed
+2987 -1025

No files matched your search

+6
View File
@@ -36,6 +36,12 @@ endif
cc-option = $(shell if test -z "`$(1) $(2) -S -o /dev/null -xc \
/dev/null 2>&1`"; then echo "$(2)"; else echo "$(3)"; fi ;)
# cc-ver
# Usage: ifeq ($(call cc-ver,$(CC),0x030400),y)
cc-ver = $(shell if [ $$((`$(1) -dumpversion | awk -F. \
'{ printf "0x%02x%02x%02x", $$1, $$2, $$3}'`)) -ge $$(($(2))) ]; \
then echo y; else echo n; fi ;)
ifneq ($(debug),y)
CFLAGS += -DNDEBUG
else
+138 -33
View File
@@ -9359,10 +9359,10 @@ $\mathit{RO}_\mathit{run}$ & {\tt VBDs} & (VBD ref) Set & list of vbds that ref
$\mathit{RO}_\mathit{run}$ & {\tt crash\_dumps} & (crashdump ref) Set & list of crash dumps that refer to this disk \\
$\mathit{RW}$ & {\tt virtual\_size} & int & size of disk as presented to the guest (in bytes). Note that, depending on storage backend type, requested size may not be respected exactly \\
$\mathit{RO}_\mathit{run}$ & {\tt physical\_utilisation} & int & amount of physical space that the disk image is currently taking up on the storage repository (in bytes) \\
$\mathit{RO}_\mathit{ins}$ & {\tt sector\_size} & int & sector size of VDI (in bytes) \\
$\mathit{RO}_\mathit{ins}$ & {\tt type} & vdi\_type & type of the VDI \\
$\mathit{RW}$ & {\tt sharable} & bool & true if this disk may be shared \\
$\mathit{RW}$ & {\tt read\_only} & bool & true if this disk may ONLY be mounted read-only \\
$\mathit{RW}$ & {\tt other\_config} & (string $\rightarrow$ string) Map & additional configuration \\
\hline
\end{longtable}
\subsection{RPCs associated with class: VDI}
@@ -9808,38 +9808,6 @@ int
}
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}
\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}
\noindent {\bf Return Type:}
{\tt
int
}
value of the field
\vspace{0.3cm}
\vspace{0.3cm}
@@ -10005,6 +9973,143 @@ void
\vspace{0.3cm}
\vspace{0.3cm}
\vspace{0.3cm}
\subsubsection{RPC name:~get\_other\_config}
{\bf Overview:}
Get the other\_config field of the given VDI.
\noindent {\bf Signature:}
\begin{verbatim} ((string -> string) Map) get_other_config (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}
\noindent {\bf Return Type:}
{\tt
(string $\rightarrow$ string) Map
}
value of the field
\vspace{0.3cm}
\vspace{0.3cm}
\vspace{0.3cm}
\subsubsection{RPC name:~set\_other\_config}
{\bf Overview:}
Set the other\_config field of the given 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:}
\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 $\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}
\vspace{0.3cm}
\noindent {\bf Return Type:}
{\tt
void
}
\vspace{0.3cm}
\vspace{0.3cm}
\vspace{0.3cm}
+2 -2
View File
@@ -49,7 +49,7 @@
#endif
unsigned long *phys_to_machine_mapping;
extern char *stack;
extern char stack[];
extern void page_walk(unsigned long virt_addr);
void new_pt_frame(unsigned long *pt_pfn, unsigned long prev_l_mfn,
@@ -453,7 +453,7 @@ void arch_init_mm(unsigned long* start_pfn_p, unsigned long* max_pfn_p)
printk(" _text: %p\n", &_text);
printk(" _etext: %p\n", &_etext);
printk(" _edata: %p\n", &_edata);
printk(" stack start: %p\n", &stack);
printk(" stack start: %p\n", stack);
printk(" _end: %p\n", &_end);
/* First page follows page table pages and 3 more pages (store page etc) */
+1 -1
View File
@@ -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)
+2 -2
View File
@@ -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];
+7
View File
@@ -74,6 +74,13 @@ static inline void wake_up(struct wait_queue_head *head)
local_irq_restore(flags); \
} while (0)
#define remove_waiter(w) do { \
unsigned long flags; \
local_irq_save(flags); \
remove_wait_queue(&w); \
local_irq_restore(flags); \
} while (0)
#define wait_event(wq, condition) do{ \
unsigned long flags; \
if(condition) \
+1
View File
@@ -13,6 +13,7 @@ void init_xenbus(void);
char *xenbus_read(xenbus_transaction_t xbt, const char *path, char **value);
char *xenbus_watch_path(xenbus_transaction_t xbt, const char *path);
void wait_for_watch(void);
char* xenbus_wait_for_value(const char*,const char*);
/* Associates a value with a path. Returns a malloc'd error string on
+2 -1
View File
@@ -72,11 +72,12 @@ static void memcpy_from_ring(const void *Ring,
memcpy(dest + c1, ring, c2);
}
static inline void wait_for_watch(void)
void wait_for_watch(void)
{
DEFINE_WAIT(w);
add_waiter(w,watch_queue);
schedule();
remove_waiter(w);
wake(current);
}
@@ -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
@@ -256,8 +256,9 @@ void pte_free(struct page *pte)
unsigned long va = (unsigned long)__va(pfn << PAGE_SHIFT);
if (!pte_write(*virt_to_ptep(va)))
BUG_ON(HYPERVISOR_update_va_mapping(
va, pfn_pte(pfn, PAGE_KERNEL), 0));
if (HYPERVISOR_update_va_mapping(
va, pfn_pte(pfn, PAGE_KERNEL), 0))
BUG();
} else
clear_bit(PG_pinned, &pte->flags);
@@ -672,14 +673,23 @@ void mm_unpin(struct mm_struct *mm)
void mm_pin_all(void)
{
struct page *page;
unsigned long flags;
if (xen_feature(XENFEAT_writable_page_tables))
return;
/*
* Allow uninterrupted access to the pgd_list. Also protects
* __pgd_pin() by disabling preemption.
* All other CPUs must be at a safe point (e.g., in stop_machine
* or offlined entirely).
*/
spin_lock_irqsave(&pgd_lock, flags);
for (page = pgd_list; page; page = (struct page *)page->index) {
if (!test_bit(PG_pinned, &page->flags))
__pgd_pin((pgd_t *)page_address(page));
}
spin_unlock_irqrestore(&pgd_lock, flags);
}
void _arch_dup_mmap(struct mm_struct *mm)
@@ -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)));
@@ -79,14 +79,17 @@ void mm_pin(struct mm_struct *mm)
spin_lock(&mm->page_table_lock);
mm_walk(mm, PAGE_KERNEL_RO);
BUG_ON(HYPERVISOR_update_va_mapping(
(unsigned long)mm->pgd,
pfn_pte(virt_to_phys(mm->pgd)>>PAGE_SHIFT, PAGE_KERNEL_RO),
UVMF_TLB_FLUSH));
BUG_ON(HYPERVISOR_update_va_mapping(
(unsigned long)__user_pgd(mm->pgd),
pfn_pte(virt_to_phys(__user_pgd(mm->pgd))>>PAGE_SHIFT, PAGE_KERNEL_RO),
UVMF_TLB_FLUSH));
if (HYPERVISOR_update_va_mapping(
(unsigned long)mm->pgd,
pfn_pte(virt_to_phys(mm->pgd)>>PAGE_SHIFT, PAGE_KERNEL_RO),
UVMF_TLB_FLUSH))
BUG();
if (HYPERVISOR_update_va_mapping(
(unsigned long)__user_pgd(mm->pgd),
pfn_pte(virt_to_phys(__user_pgd(mm->pgd))>>PAGE_SHIFT,
PAGE_KERNEL_RO),
UVMF_TLB_FLUSH))
BUG();
xen_pgd_pin(__pa(mm->pgd)); /* kernel */
xen_pgd_pin(__pa(__user_pgd(mm->pgd))); /* user */
mm->context.pinned = 1;
@@ -106,12 +109,15 @@ void mm_unpin(struct mm_struct *mm)
xen_pgd_unpin(__pa(mm->pgd));
xen_pgd_unpin(__pa(__user_pgd(mm->pgd)));
BUG_ON(HYPERVISOR_update_va_mapping(
(unsigned long)mm->pgd,
pfn_pte(virt_to_phys(mm->pgd)>>PAGE_SHIFT, PAGE_KERNEL), 0));
BUG_ON(HYPERVISOR_update_va_mapping(
(unsigned long)__user_pgd(mm->pgd),
pfn_pte(virt_to_phys(__user_pgd(mm->pgd))>>PAGE_SHIFT, PAGE_KERNEL), 0));
if (HYPERVISOR_update_va_mapping(
(unsigned long)mm->pgd,
pfn_pte(virt_to_phys(mm->pgd)>>PAGE_SHIFT, PAGE_KERNEL), 0))
BUG();
if (HYPERVISOR_update_va_mapping(
(unsigned long)__user_pgd(mm->pgd),
pfn_pte(virt_to_phys(__user_pgd(mm->pgd))>>PAGE_SHIFT,
PAGE_KERNEL), 0))
BUG();
mm_walk(mm, PAGE_KERNEL);
xen_tlb_flush();
mm->context.pinned = 0;
@@ -127,43 +133,50 @@ void mm_pin_all(void)
if (xen_feature(XENFEAT_writable_page_tables))
return;
/*
* Allow uninterrupted access to the mm_unpinned list. We don't
* actually take the mm_unpinned_lock as it is taken inside mm_pin().
* All other CPUs must be at a safe point (e.g., in stop_machine
* or offlined entirely).
*/
preempt_disable();
while (!list_empty(&mm_unpinned))
mm_pin(list_entry(mm_unpinned.next, struct mm_struct,
context.unpinned));
preempt_enable();
}
void _arch_dup_mmap(struct mm_struct *mm)
{
if (!mm->context.pinned)
mm_pin(mm);
if (!mm->context.pinned)
mm_pin(mm);
}
void _arch_exit_mmap(struct mm_struct *mm)
{
struct task_struct *tsk = current;
struct task_struct *tsk = current;
task_lock(tsk);
task_lock(tsk);
/*
* We aggressively remove defunct pgd from cr3. We execute unmap_vmas()
* *much* faster this way, as no tlb flushes means bigger wrpt batches.
*/
if ( tsk->active_mm == mm )
{
tsk->active_mm = &init_mm;
atomic_inc(&init_mm.mm_count);
/*
* We aggressively remove defunct pgd from cr3. We execute unmap_vmas()
* *much* faster this way, as no tlb flushes means bigger wrpt batches.
*/
if (tsk->active_mm == mm) {
tsk->active_mm = &init_mm;
atomic_inc(&init_mm.mm_count);
switch_mm(mm, &init_mm, tsk);
switch_mm(mm, &init_mm, tsk);
atomic_dec(&mm->mm_count);
BUG_ON(atomic_read(&mm->mm_count) == 0);
}
atomic_dec(&mm->mm_count);
BUG_ON(atomic_read(&mm->mm_count) == 0);
}
task_unlock(tsk);
task_unlock(tsk);
if ( mm->context.pinned && (atomic_read(&mm->mm_count) == 1) &&
!mm->context.has_foreign_mappings )
mm_unpin(mm);
if ( mm->context.pinned && (atomic_read(&mm->mm_count) == 1) &&
!mm->context.has_foreign_mappings )
mm_unpin(mm);
}
struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address)
@@ -183,8 +196,9 @@ void pte_free(struct page *pte)
unsigned long va = (unsigned long)__va(page_to_pfn(pte)<<PAGE_SHIFT);
if (!pte_write(*virt_to_ptep(va)))
BUG_ON(HYPERVISOR_update_va_mapping(
va, pfn_pte(page_to_pfn(pte), PAGE_KERNEL), 0));
if (HYPERVISOR_update_va_mapping(
va, pfn_pte(page_to_pfn(pte), PAGE_KERNEL), 0))
BUG();
ClearPageForeign(pte);
init_page_count(pte);
@@ -1267,7 +1267,7 @@ static void net_tx_action(unsigned long unused)
/* Check the remap error code. */
if (unlikely(netbk_tx_check_mop(skb, &mop))) {
printk(KERN_ALERT "#### netback grant fails\n");
DPRINTK("netback grant failed.\n");
skb_shinfo(skb)->nr_frags = 0;
kfree_skb(skb);
continue;
@@ -110,7 +110,6 @@ int xb_write(const void *data, unsigned len)
/* Read indexes, then verify. */
cons = intf->req_cons;
prod = intf->req_prod;
mb();
if (!check_indexes(cons, prod)) {
intf->req_cons = intf->req_prod = 0;
return -EIO;
@@ -122,15 +121,18 @@ int xb_write(const void *data, unsigned len)
if (avail > len)
avail = len;
/* Must write data /after/ reading the consumer index. */
mb();
memcpy(dst, data, avail);
data += avail;
len -= avail;
/* Other side must not see new header until data is there. */
/* Other side must not see new producer until data is there. */
wmb();
intf->req_prod += avail;
/* This implies mb() before other side sees interrupt. */
/* Implies mb(): other side will see the updated producer. */
notify_remote_via_evtchn(xen_store_evtchn);
}
@@ -165,7 +167,6 @@ int xb_read(void *data, unsigned len)
/* Read indexes, then verify. */
cons = intf->rsp_cons;
prod = intf->rsp_prod;
mb();
if (!check_indexes(cons, prod)) {
intf->rsp_cons = intf->rsp_prod = 0;
return -EIO;
@@ -177,7 +178,7 @@ int xb_read(void *data, unsigned len)
if (avail > len)
avail = len;
/* We must read header before we read data. */
/* Must read data /after/ reading the producer index. */
rmb();
memcpy(data, src, avail);
@@ -190,7 +191,7 @@ int xb_read(void *data, unsigned len)
pr_debug("Finished read of %i bytes (%i to go)\n", avail, len);
/* Implies mb(): they will see new header. */
/* Implies mb(): other side will see the updated consumer. */
notify_remote_via_evtchn(xen_store_evtchn);
}
@@ -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
+157
View File
@@ -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.
@@ -0,0 +1,30 @@
From: Andrew Morton <akpm@linux-foundation.org>
In file included from arch/i386/kernel/setup.c:46:
include/linux/crash_dump.h:19:36: warning: extra tokens at end of #ifndef directive
Cc: "Eric W. Biederman" <ebiederm@xmission.com>
Cc: Andi Kleen <ak@suse.de>
Cc: Horms <horms@verge.net.au>
Cc: Ian Campbell <ian.campbell@xensource.com>
Cc: Magnus Damm <magnus.damm@gmail.com>
Cc: Vivek Goyal <vgoyal@in.ibm.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
---
include/linux/crash_dump.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff -puN include/linux/crash_dump.h~allow-i386-crash-kernels-to-handle-x86_64-dumps-fix include/linux/crash_dump.h
--- a/include/linux/crash_dump.h~allow-i386-crash-kernels-to-handle-x86_64-dumps-fix
+++ a/include/linux/crash_dump.h
@@ -16,7 +16,7 @@ extern struct proc_dir_entry *proc_vmcor
/* Architecture code defines this if there are other possible ELF
* machine types, e.g. on bi-arch capable hardware. */
-#ifndef vmcore_elf_check_arch_cross(x)
+#ifndef vmcore_elf_check_arch_cross
#define vmcore_elf_check_arch_cross(x) 0
#endif
_
@@ -0,0 +1,66 @@
From: Ian Campbell <ian.campbell@xensource.com>
The specific case I am encountering is kdump under Xen with a 64 bit
hypervisor and 32 bit kernel/userspace. The dump created is 64 bit due to
the hypervisor but the dump kernel is 32 bit for maximum compatibility.
It's possibly less likely to be useful in a purely native scenario but I
see no reason to disallow it.
Signed-off-by: Ian Campbell <ian.campbell@xensource.com>
Acked-by: Vivek Goyal <vgoyal@in.ibm.com>
Cc: Horms <horms@verge.net.au>
Cc: Magnus Damm <magnus.damm@gmail.com>
Cc: "Eric W. Biederman" <ebiederm@xmission.com>
Cc: Andi Kleen <ak@suse.de>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
---
fs/proc/vmcore.c | 2 +-
include/asm-i386/kexec.h | 3 +++
include/linux/crash_dump.h | 8 ++++++++
3 files changed, 12 insertions(+), 1 deletion(-)
diff -puN fs/proc/vmcore.c~allow-i386-crash-kernels-to-handle-x86_64-dumps fs/proc/vmcore.c
--- a/fs/proc/vmcore.c~allow-i386-crash-kernels-to-handle-x86_64-dumps
+++ a/fs/proc/vmcore.c
@@ -514,7 +514,7 @@ static int __init parse_crash_elf64_head
/* Do some basic Verification. */
if (memcmp(ehdr.e_ident, ELFMAG, SELFMAG) != 0 ||
(ehdr.e_type != ET_CORE) ||
- !elf_check_arch(&ehdr) ||
+ !vmcore_elf_check_arch(&ehdr) ||
ehdr.e_ident[EI_CLASS] != ELFCLASS64 ||
ehdr.e_ident[EI_VERSION] != EV_CURRENT ||
ehdr.e_version != EV_CURRENT ||
diff -puN include/asm-i386/kexec.h~allow-i386-crash-kernels-to-handle-x86_64-dumps include/asm-i386/kexec.h
--- a/include/asm-i386/kexec.h~allow-i386-crash-kernels-to-handle-x86_64-dumps
+++ a/include/asm-i386/kexec.h
@@ -47,6 +47,9 @@
/* The native architecture */
#define KEXEC_ARCH KEXEC_ARCH_386
+/* We can also handle crash dumps from 64 bit kernel. */
+#define vmcore_elf_check_arch_cross(x) ((x)->e_machine == EM_X86_64)
+
#define MAX_NOTE_BYTES 1024
/* CPU does not save ss and esp on stack if execution is already
diff -puN include/linux/crash_dump.h~allow-i386-crash-kernels-to-handle-x86_64-dumps include/linux/crash_dump.h
--- a/include/linux/crash_dump.h~allow-i386-crash-kernels-to-handle-x86_64-dumps
+++ a/include/linux/crash_dump.h
@@ -14,5 +14,13 @@ extern ssize_t copy_oldmem_page(unsigned
extern const struct file_operations proc_vmcore_operations;
extern struct proc_dir_entry *proc_vmcore;
+/* Architecture code defines this if there are other possible ELF
+ * machine types, e.g. on bi-arch capable hardware. */
+#ifndef vmcore_elf_check_arch_cross(x)
+#define vmcore_elf_check_arch_cross(x) 0
+#endif
+
+#define vmcore_elf_check_arch(x) (elf_check_arch(x) || vmcore_elf_check_arch_cross(x))
+
#endif /* CONFIG_CRASH_DUMP */
#endif /* LINUX_CRASHDUMP_H */
_
@@ -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.
+2 -1
View File
@@ -19,4 +19,5 @@ x86-elfnote-as-preprocessor-macro.patch
fixaddr-top.patch
git-c06cb8b1c4d25e5b4d7a2d7c2462619de1e0dbc4.patch
softlockup-no-idle-hz.patch
crash-kernel-32-on-64.patch
allow-i386-crash-kernels-to-handle-x86_64-dumps.patch
allow-i386-crash-kernels-to-handle-x86_64-dumps-fix.patch
+5
View File
@@ -23,6 +23,11 @@ LDFLAGS += $(shell getconf LFS_LDFLAGS)
CFLAGS-$(CONFIG_X86_32) += $(call cc-option,$(CC),-mno-tls-direct-seg-refs)
CFLAGS += $(CFLAGS-y)
# Require GCC v3.4+ (to avoid issues with alignment constraints in Xen headers)
ifeq ($(CONFIG_X86)$(call cc-ver,$(CC),0x030400),yn)
$(error Xen tools require at least gcc-3.4)
endif
%.opic: %.c
$(CC) $(CPPFLAGS) -DPIC $(CFLAGS) -fPIC -c -o $@ $<
+1
View File
@@ -1057,6 +1057,7 @@ int tdqcow_queue_write(struct disk_driver *dd, uint64_t sector,
index_in_cluster+n);
if (!cluster_offset) {
DPRINTF("Ooops, no write cluster offset!\n");
aio_unlock(s, sector);
return cb(dd, -EIO, sector, nb_sectors, id, private);
}
+1 -1
View File
@@ -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)"; \
+69 -97
View File
@@ -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)) {
uint32_t biosjumptableentries;
biosjumptable = (uint32_t *)shdr[i].sh_addr;
biosjumptableentries = shdr[i].sh_size / 4;
for (int j = 0; j < biosjumptableentries; j++) {
rombiosjumptable[j] = biosjumptable[j];
if (biosjumptable[j] == 0 &&
j < (biosjumptableentries - 1)) {
printf("WARNING: jumptable entry %d is NULL!\n",j);
}
}
/* Find the section with the jump table and copy to lower BIOS memory. */
for ( i = 0; i < ehdr->e_shnum; i++ )
if ( !strcmp(JUMPTABLE_SECTION_NAME, secstrings + shdr[i].sh_name) )
break;
}
}
if (biosjumptable == NULL) {
if ( i == ehdr->e_shnum )
{
printf("Could not find " JUMPTABLE_SECTION_NAME " section in file.\n");
rc = -4;
return;
}
return 0;
if ( jump_table == NULL )
{
printf("Could not find jump table in file.\n");
return;
}
memcpy(jump_table, (char *)shdr[i].sh_addr, shdr[i].sh_size);
}
static int relocate_32bitbios(unsigned char *elfarray, uint32_t elfarraysize)
static void relocate_32bitbios(char *elfarray, uint32_t elfarraysize)
{
int rc = 0;
uint32_t mask = (64 * 1024) - 1;
uint32_t to_malloc = (elfarraysize + mask) & ~mask; /* round to 64kb */
unsigned char *highbiosarea;
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;
highbiosarea = (char *)(long)
e820_malloc((elfarraysize + mask) & ~mask, /* round to 64kb */
E820_RESERVED,
(uint64_t)0xffffffff);
if ( highbiosarea == NULL )
{
printf("No available memory for BIOS high memory area\n");
return;
}
return rc;
memcpy(highbiosarea, elfarray, elfarraysize);
relocate_elf(highbiosarea);
copy_jumptable(highbiosarea);
}
int highbios_setup(void)
void highbios_setup(void)
{
return relocate_32bitbios((unsigned char *)highbios_array,
sizeof(highbios_array));
relocate_32bitbios((char *)highbios_array, sizeof(highbios_array));
}
-1
View File
@@ -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))
+49 -16
View File
@@ -29,7 +29,6 @@
#include "pci_regs.h"
#include <xen/version.h>
#include <xen/hvm/params.h>
#include <xen/hvm/e820.h>
/* memory map */
#define HYPERCALL_PHYSICAL_ADDRESS 0x00080000
@@ -297,25 +296,57 @@ static void pci_setup(void)
}
}
static
int must_load_nic(void)
/*
* If the network card is in the boot order, load the Etherboot option ROM.
* Read the boot order bytes from CMOS and check if any of them are 0x4.
*/
static int must_load_nic(void)
{
/* If the network card is in the boot order, load the Etherboot
* option ROM. Read the boot order bytes from CMOS and check
* if any of them are 0x4. */
uint8_t boot_order;
/* Read CMOS register 0x3d (boot choices 0 and 1) */
outb(0x70, 0x3d);
boot_order = inb(0x71);
if ( (boot_order & 0xf) == 0x4 || (boot_order & 0xf0) == 0x40 )
/* 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)
@@ -366,6 +397,8 @@ int main(void)
ASSERT((ACPI_PHYSICAL_ADDRESS + acpi_sz) <= 0xF0000);
}
cmos_write_memory_size();
if ( !check_amd() )
{
printf("Loading VMXAssist ...\n");
+15 -31
View File
@@ -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
+15 -6
View File
@@ -27,17 +27,17 @@
void outb(uint16_t addr, uint8_t val)
{
__asm__ __volatile__ ( "outb %%al, %%dx" :: "d"(addr), "a"(val) );
__asm__ __volatile__ ( "outb %%al, %%dx" : : "d" (addr), "a" (val) );
}
void outw(uint16_t addr, uint16_t val)
{
__asm__ __volatile__ ( "outw %%ax, %%dx" :: "d"(addr), "a"(val) );
__asm__ __volatile__ ( "outw %%ax, %%dx" : : "d" (addr), "a" (val) );
}
void outl(uint16_t addr, uint32_t val)
{
__asm__ __volatile__ ( "outl %%eax, %%dx" :: "d"(addr), "a"(val) );
__asm__ __volatile__ ( "outl %%eax, %%dx" : : "d" (addr), "a" (val) );
}
uint8_t inb(uint16_t addr)
@@ -61,6 +61,18 @@ uint32_t inl(uint16_t addr)
return val;
}
uint8_t cmos_inb(uint8_t idx)
{
outb(0x70, idx);
return inb(0x71);
}
void cmos_outb(uint8_t idx, uint8_t val)
{
outb(0x70, idx);
outb(0x71, val);
}
char *itoa(char *a, unsigned int i)
{
unsigned int _i = i, x = 0;
@@ -280,9 +292,6 @@ uuid_to_string(char *dest, uint8_t *uuid)
*p = '\0';
}
#include <xen/hvm/e820.h>
#define E820_MAP_NR ((unsigned char *)E820_MAP_PAGE + E820_MAP_NR_OFFSET)
#define E820_MAP ((struct e820entry *)(E820_MAP_PAGE + E820_MAP_OFFSET))
uint64_t e820_malloc(uint64_t size, uint32_t type, uint64_t mask)
{
uint64_t addr = 0;
+10 -2
View File
@@ -26,6 +26,10 @@ uint8_t inb(uint16_t addr);
uint16_t inw(uint16_t addr);
uint32_t inl(uint16_t addr);
/* CMOS access */
uint8_t cmos_inb(uint8_t idx);
void cmos_outb(uint8_t idx, uint8_t val);
/* APIC access */
uint32_t ioapic_read(uint32_t reg);
void ioapic_write(uint32_t reg, uint32_t val);
@@ -78,9 +82,13 @@ int vprintf(const char *fmt, va_list ap);
/* Allocate region of specified type in the e820 table. */
uint64_t e820_malloc(uint64_t size, uint32_t type, uint64_t mask);
/* Prepare the 32bit BIOS */
int highbios_setup(void);
/* General e820 access. */
#include <xen/hvm/e820.h>
#define E820_MAP_NR ((unsigned char *)E820_MAP_PAGE + E820_MAP_NR_OFFSET)
#define E820_MAP ((struct e820entry *)(E820_MAP_PAGE + E820_MAP_OFFSET))
/* Prepare the 32bit BIOS */
void highbios_setup(void);
#define isdigit(c) ((c) >= '0' && (c) <= '9')
+68 -160
View File
@@ -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;
case 0x20: {
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 (regs.u.r32.edx != 0x534D4150) /* SMAP */
goto int15_unimplemented;
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;
if ((regs.u.r16.bx / 0x14) * 0x14 == regs.u.r16.bx) {
if (regs.u.r16.bx + 0x14 <= e820_table_size)
memcpyb(ES, regs.u.r16.di,
0xe000, 0x10 + regs.u.r16.bx, 0x14);
regs.u.r32.ebx += 0x14;
if ((regs.u.r32.ebx + 0x14 - 1) > e820_table_size)
regs.u.r32.ebx = 0;
} else if (regs.u.r16.bx == 1) {
Bit32u base, type;
Bit16u off;
for (off = 0; off < e820_table_size; off += 0x14) {
base = read_dword(0xe000, 0x10 + off);
type = read_dword(0xe000, 0x20 + off);
if ((base >= 0x100000) && (type == 1))
break;
}
#endif
} else {
// if DX != 0x534D4150)
goto int15_unimplemented;
}
if (off == e820_table_size) {
SET_CF();
break;
}
memcpyb(ES, regs.u.r16.di, 0xe000, 0x10 + off, 0x14);
regs.u.r32.ebx = 0;
} else { /* AX=E820, DX=534D4150, BX unrecognized */
goto int15_unimplemented;
}
regs.u.r32.eax = 0x534D4150;
regs.u.r32.ecx = 0x14;
CLEAR_CF();
break;
}
case 0x01:
// do we have any reason to fail here ?
CLEAR_CF();
case 0x01: {
Bit16u off, e820_table_size = read_word(0xe000, 0x8) * 0x14;
Bit32u base, type, size;
// my real system sets ax and bx to 0
// this is confirmed by Ralph Brown list
// but syslinux v1.48 is known to behave
// strangely if ax is set to 0
// regs.u.r16.ax = 0;
// regs.u.r16.bx = 0;
// do we have any reason to fail here ?
CLEAR_CF();
// Get the amount of extended memory (above 1M)
regs.u.r8.cl = inb_cmos(0x30);
regs.u.r8.ch = inb_cmos(0x31);
// Get the amount of extended memory (above 1M)
regs.u.r8.cl = inb_cmos(0x30);
regs.u.r8.ch = inb_cmos(0x31);
// limit to 15M
if(regs.u.r16.cx > 0x3c00)
{
regs.u.r16.cx = 0x3c00;
}
// limit to 15M
if (regs.u.r16.cx > (15*1024))
regs.u.r16.cx = 15*1024;
// 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);
// 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;
}
// Set configured memory equal to extended memory
regs.u.r16.ax = regs.u.r16.cx;
regs.u.r16.bx = regs.u.r16.dx;
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:
+15 -1
View File
@@ -450,6 +450,9 @@ static inline int paddr_is_ram(target_phys_addr_t addr)
#define phys_ram_addr(x) (phys_ram_base + (x))
#endif
extern unsigned long *logdirty_bitmap;
extern unsigned long logdirty_bitmap_size;
void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf,
int len, int is_write)
{
@@ -485,9 +488,20 @@ void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf,
l = 1;
}
} else if (paddr_is_ram(addr)) {
/* Reading from RAM */
/* Writing to RAM */
ptr = phys_ram_addr(addr);
memcpy(ptr, buf, l);
if (logdirty_bitmap != NULL) {
/* Record that we have dirtied this frame */
unsigned long pfn = addr >> TARGET_PAGE_BITS;
if (pfn / 8 >= logdirty_bitmap_size) {
fprintf(logfile, "dirtying pfn %x >= bitmap size %x\n",
pfn, logdirty_bitmap_size * 8);
} else {
logdirty_bitmap[pfn / HOST_LONG_BITS]
|= 1UL << pfn % HOST_LONG_BITS;
}
}
#ifdef __ia64__
sync_icache(ptr, l);
#endif
+15
View File
@@ -439,6 +439,18 @@ void cpu_ioreq_xor(CPUState *env, ioreq_t *req)
req->data = tmp1;
}
void cpu_ioreq_xchg(CPUState *env, ioreq_t *req)
{
unsigned long tmp1;
if (req->data_is_ptr != 0)
hw_error("expected scalar value");
read_physical(req->addr, req->size, &tmp1);
write_physical(req->addr, req->size, &req->data);
req->data = tmp1;
}
void __handle_ioreq(CPUState *env, ioreq_t *req)
{
if (!req->data_is_ptr && req->dir == IOREQ_WRITE && req->size != 4)
@@ -463,6 +475,9 @@ void __handle_ioreq(CPUState *env, ioreq_t *req)
case IOREQ_TYPE_XOR:
cpu_ioreq_xor(env, req);
break;
case IOREQ_TYPE_XCHG:
cpu_ioreq_xchg(env, req);
break;
default:
hw_error("Invalid ioreq type 0x%x\n", req->type);
}
+148 -31
View File
@@ -11,9 +11,14 @@
#include "vl.h"
#include "block_int.h"
#include <unistd.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
static struct xs_handle *xsh = NULL;
static char *hd_filename[MAX_DISKS];
static char *media_filename[MAX_DISKS];
static QEMUTimer *insert_timer = NULL;
#define UWAIT_MAX (30*1000000) /* thirty seconds */
@@ -40,10 +45,10 @@ static void insert_media(void *opaque)
int i;
for (i = 0; i < MAX_DISKS; i++) {
if (hd_filename[i]) {
do_change(bs_table[i]->device_name, hd_filename[i]);
free(hd_filename[i]);
hd_filename[i] = NULL;
if (media_filename[i] && bs_table[i]) {
do_change(bs_table[i]->device_name, media_filename[i]);
free(media_filename[i]);
media_filename[i] = NULL;
}
}
}
@@ -82,7 +87,7 @@ void xenstore_parse_domain_config(int domid)
unsigned int len, num, hd_index;
for(i = 0; i < MAX_DISKS; i++)
hd_filename[i] = NULL;
media_filename[i] = NULL;
xsh = xs_daemon_open();
if (xsh == NULL) {
@@ -128,19 +133,12 @@ void xenstore_parse_domain_config(int domid)
continue;
free(type);
type = xs_read(xsh, XBT_NULL, buf, &len);
/* read params to get the patch of the image -- read it last
* so that we have its path in buf when setting up the
* watch */
if (pasprintf(&buf, "%s/params", bpath) == -1)
continue;
free(params);
params = xs_read(xsh, XBT_NULL, buf, &len);
if (params == NULL)
continue;
if (params[0]) {
hd_filename[hd_index] = params; /* strdup() */
params = NULL; /* don't free params on re-use */
}
/*
* check if device has a phantom vbd; the phantom is hooked
* to the frontend device (for ease of cleanup), so lookup
@@ -151,38 +149,42 @@ void xenstore_parse_domain_config(int domid)
continue;
free(fpath);
fpath = xs_read(xsh, XBT_NULL, buf, &len);
if (fpath != NULL) {
if (fpath) {
if (pasprintf(&buf, "%s/dev", fpath) == -1)
continue;
free(params);
params = xs_read(xsh, XBT_NULL, buf , &len);
if (params != NULL) {
free(hd_filename[hd_index]);
hd_filename[hd_index] = params;
params = NULL; /* don't free params on re-use */
if (params) {
/*
* wait for device, on timeout silently fail because we will
* fail to open below
*/
waitForDevice(hd_filename[hd_index]);
waitForDevice(params);
}
}
bs_table[hd_index] = bdrv_new(dev);
/* re-establish buf */
if (pasprintf(&buf, "%s/params", bpath) == -1)
continue;
/* check if it is a cdrom */
if (type && !strcmp(type, "cdrom")) {
bdrv_set_type_hint(bs_table[hd_index], BDRV_TYPE_CDROM);
xs_watch(xsh, buf, dev);
if (pasprintf(&buf, "%s/params", bpath) != -1)
xs_watch(xsh, buf, dev);
}
if (hd_filename[hd_index]) {
if (bdrv_open(bs_table[hd_index], hd_filename[hd_index],
0 /* snapshot */) < 0)
/* open device now if media present */
if (params[0]) {
if (bdrv_open(bs_table[hd_index], params, 0 /* snapshot */) < 0)
fprintf(stderr, "qemu: could not open hard disk image '%s'\n",
hd_filename[hd_index]);
params);
}
}
/* Set a watch for log-dirty requests from the migration tools */
if (pasprintf(&buf, "%s/logdirty/next-active", path) != -1) {
xs_watch(xsh, buf, "logdirty");
fprintf(logfile, "Watching %s\n", buf);
}
out:
free(type);
free(params);
@@ -201,6 +203,116 @@ int xenstore_fd(void)
return -1;
}
unsigned long *logdirty_bitmap = NULL;
unsigned long logdirty_bitmap_size;
extern int vga_ram_size, bios_size;
void xenstore_process_logdirty_event(void)
{
char *act;
static char *active_path = NULL;
static char *next_active_path = NULL;
static char *seg = NULL;
unsigned int len;
int i;
fprintf(logfile, "Triggered log-dirty buffer switch\n");
if (!seg) {
char *path, *p, *key_ascii, key_terminated[17] = {0,};
key_t key;
int shmid;
/* Find and map the shared memory segment for log-dirty bitmaps */
if (!(path = xs_get_domain_path(xsh, domid))) {
fprintf(logfile, "Log-dirty: can't get domain path in store\n");
exit(1);
}
if (!(path = realloc(path, strlen(path)
+ strlen("/logdirty/next-active") + 1))) {
fprintf(logfile, "Log-dirty: out of memory\n");
exit(1);
}
strcat(path, "/logdirty/");
p = path + strlen(path);
strcpy(p, "key");
key_ascii = xs_read(xsh, XBT_NULL, path, &len);
if (!key_ascii) {
/* No key yet: wait for the next watch */
free(path);
return;
}
strncpy(key_terminated, key_ascii, 16);
free(key_ascii);
key = (key_t) strtoull(key_terminated, NULL, 16);
/* Figure out how bit the log-dirty bitmaps are */
logdirty_bitmap_size = ((phys_ram_size + 0x20
- (vga_ram_size + bios_size))
>> (TARGET_PAGE_BITS)); /* nr of bits in map*/
if (logdirty_bitmap_size > HVM_BELOW_4G_MMIO_START >> TARGET_PAGE_BITS)
logdirty_bitmap_size +=
HVM_BELOW_4G_MMIO_LENGTH >> TARGET_PAGE_BITS; /* still bits */
logdirty_bitmap_size = ((logdirty_bitmap_size + HOST_LONG_BITS - 1)
/ HOST_LONG_BITS); /* longs */
logdirty_bitmap_size *= sizeof (unsigned long); /* bytes */
/* Map the shared-memory segment */
if ((shmid = shmget(key,
2 * logdirty_bitmap_size,
S_IRUSR|S_IWUSR)) == -1
|| (seg = shmat(shmid, NULL, 0)) == (void *)-1) {
fprintf(logfile, "Log-dirty: can't map segment %16.16llx (%s)\n",
(unsigned long long) key, strerror(errno));
exit(1);
}
fprintf(logfile, "Log-dirty: mapped segment at %p\n", seg);
/* Double-check that the bitmaps are the size we expect */
if (logdirty_bitmap_size != *(uint32_t *)seg) {
fprintf(logfile, "Log-dirty: got %lu, calc %lu\n",
*(uint32_t *)seg, logdirty_bitmap_size);
return;
}
/* Remember the paths for the next-active and active entries */
strcpy(p, "active");
if (!(active_path = strdup(path))) {
fprintf(logfile, "Log-dirty: out of memory\n");
exit(1);
}
strcpy(p, "next-active");
if (!(next_active_path = strdup(path))) {
fprintf(logfile, "Log-dirty: out of memory\n");
exit(1);
}
free(path);
}
/* Read the required active buffer from the store */
act = xs_read(xsh, XBT_NULL, next_active_path, &len);
if (!act) {
fprintf(logfile, "Log-dirty: can't read next-active\n");
exit(1);
}
/* Switch buffers */
i = act[0] - '0';
if (i != 0 && i != 1) {
fprintf(logfile, "Log-dirty: bad next-active entry: %s\n", act);
exit(1);
}
logdirty_bitmap = seg + i * logdirty_bitmap_size;
/* Ack that we've switched */
xs_write(xsh, XBT_NULL, active_path, act, len);
free(act);
}
void xenstore_process_event(void *opaque)
{
char **vec, *image = NULL;
@@ -210,6 +322,11 @@ void xenstore_process_event(void *opaque)
if (!vec)
return;
if (!strcmp(vec[XS_WATCH_TOKEN], "logdirty")) {
xenstore_process_logdirty_event();
goto out;
}
if (strncmp(vec[XS_WATCH_TOKEN], "hd", 2) ||
strlen(vec[XS_WATCH_TOKEN]) != 3)
goto out;
@@ -220,13 +337,13 @@ void xenstore_process_event(void *opaque)
do_eject(0, vec[XS_WATCH_TOKEN]);
bs_table[hd_index]->filename[0] = 0;
if (hd_filename[hd_index]) {
free(hd_filename[hd_index]);
hd_filename[hd_index] = NULL;
if (media_filename[hd_index]) {
free(media_filename[hd_index]);
media_filename[hd_index] = NULL;
}
if (image[0]) {
hd_filename[hd_index] = strdup(image);
media_filename[hd_index] = strdup(image);
xenstore_check_new_media_present(5000);
}
+1 -1
View File
@@ -57,7 +57,7 @@ GUEST_SRCS-$(CONFIG_IA64) += xc_dom_compat_linux.c
CFLAGS += -Werror -Wmissing-prototypes
CFLAGS += -fno-strict-aliasing
CFLAGS += $(INCLUDES) -I.
CFLAGS += $(INCLUDES) -I. -I../xenstore
# Needed for posix_fadvise64() in xc_linux.c
CFLAGS-$(CONFIG_Linux) += -D_GNU_SOURCE
+1 -5
View File
@@ -349,11 +349,7 @@ xc_domain_dumpcore_via_callback(int xc_handle,
/* Map the shared info frame */
live_shinfo = xc_map_foreign_range(xc_handle, domid, PAGE_SIZE,
PROT_READ, info.shared_info_frame);
if ( !live_shinfo
#ifdef __ia64__
&& !info.hvm
#endif
)
if ( !live_shinfo && !info.hvm )
{
PERROR("Couldn't map live_shinfo");
goto out;
+11 -13
View File
@@ -21,12 +21,15 @@
#include "xg_private.h"
#include "xc_core.h"
static int max_gpfn(int xc_handle, domid_t domid)
{
return xc_memory_op(xc_handle, XENMEM_maximum_gpfn, &domid);
}
int
xc_core_arch_auto_translated_physmap(const xc_dominfo_t *info)
{
if ( info->hvm )
return 1;
return 0;
return info->hvm;
}
int
@@ -35,14 +38,14 @@ xc_core_arch_memory_map_get(int xc_handle, xc_dominfo_t *info,
xc_core_memory_map_t **mapp,
unsigned int *nr_entries)
{
unsigned long max_pfn = live_shinfo->arch.max_pfn;
xc_core_memory_map_t *map = NULL;
unsigned long max_pfn = max_gpfn(xc_handle, info->domid);
xc_core_memory_map_t *map;
map = malloc(sizeof(*map));
if ( !map )
if ( map == NULL )
{
PERROR("Could not allocate memory");
goto out;
return -1;
}
map->addr = 0;
@@ -51,11 +54,6 @@ xc_core_arch_memory_map_get(int xc_handle, xc_dominfo_t *info,
*mapp = map;
*nr_entries = 1;
return 0;
out:
if ( map )
free(map);
return -1;
}
int
@@ -67,7 +65,7 @@ xc_core_arch_map_p2m(int xc_handle, xc_dominfo_t *info,
xen_pfn_t *live_p2m_frame_list_list = NULL;
xen_pfn_t *live_p2m_frame_list = NULL;
uint32_t dom = info->domid;
unsigned long max_pfn = live_shinfo->arch.max_pfn;
unsigned long max_pfn = max_gpfn(xc_handle, info->domid);
int ret = -1;
int err;
+6 -1
View File
@@ -137,6 +137,12 @@ static void build_e820map(void *e820_page, unsigned long long mem_size)
e820entry[nr_map].type = E820_RAM;
nr_map++;
/* Explicitly reserve space for special pages (ioreq and xenstore). */
e820entry[nr_map].addr = mem_size - PAGE_SIZE * 3;
e820entry[nr_map].size = PAGE_SIZE * 3;
e820entry[nr_map].type = E820_RESERVED;
nr_map++;
if ( extra_mem_size )
{
e820entry[nr_map].addr = (1ULL << 32);
@@ -280,7 +286,6 @@ static int setup_guest(int xc_handle,
/* NB. evtchn_upcall_mask is unused: leave as zero. */
memset(&shared_info->evtchn_mask[0], 0xff,
sizeof(shared_info->evtchn_mask));
shared_info->arch.max_pfn = page_array[nr_pages - 1];
munmap(shared_info, PAGE_SIZE);
if ( v_end > HVM_BELOW_4G_RAM_END )
-31
View File
@@ -70,9 +70,6 @@ int xc_hvm_restore(int xc_handle, int io_fd,
{
DECLARE_DOMCTL;
/* The new domain's shared-info frame number. */
unsigned long shared_info_frame;
/* A copy of the CPU context of the guest. */
vcpu_guest_context_t ctxt;
@@ -86,8 +83,6 @@ int xc_hvm_restore(int xc_handle, int io_fd,
uint8_t *hvm_buf = NULL;
unsigned long long v_end, memsize;
unsigned long shared_page_nr;
shared_info_t *shared_info = NULL;
xen_pfn_t arch_max_pfn;
unsigned long pfn;
unsigned int prev_pc, this_pc;
@@ -96,8 +91,6 @@ int xc_hvm_restore(int xc_handle, int io_fd,
/* Types of the pfns in the current region */
unsigned long region_pfn_type[MAX_BATCH_SIZE];
struct xen_add_to_physmap xatp;
/* Number of pages of memory the guest has. *Not* the same as max_pfn. */
unsigned long nr_pages;
@@ -146,7 +139,6 @@ int xc_hvm_restore(int xc_handle, int io_fd,
pfns[i] = i;
for ( i = HVM_BELOW_4G_RAM_END >> PAGE_SHIFT; i < pfn_array_size; i++ )
pfns[i] += HVM_BELOW_4G_MMIO_LENGTH >> PAGE_SHIFT;
arch_max_pfn = pfns[max_pfn];/* used later */
/* Allocate memory for HVM guest, skipping VGA hole 0xA0000-0xC0000. */
rc = xc_domain_memory_populate_physmap(
@@ -350,29 +342,6 @@ int xc_hvm_restore(int xc_handle, int io_fd,
goto out;
}
/* Shared-info pfn */
if (!read_exact(io_fd, &(shared_info_frame), sizeof(uint32_t)) ) {
ERROR("reading the shared-info pfn failed!\n");
goto out;
}
/* Map the shared-info frame where it was before */
xatp.domid = dom;
xatp.space = XENMAPSPACE_shared_info;
xatp.idx = 0;
xatp.gpfn = shared_info_frame;
if ( (rc = xc_memory_op(xc_handle, XENMEM_add_to_physmap, &xatp)) != 0 ) {
ERROR("setting the shared-info pfn failed!\n");
goto out;
}
if ( (xc_memory_op(xc_handle, XENMEM_add_to_physmap, &xatp) != 0) ||
((shared_info = xc_map_foreign_range(
xc_handle, dom, PAGE_SIZE, PROT_READ | PROT_WRITE,
shared_info_frame)) == NULL) )
goto out;
/* shared_info.arch.max_pfn is used by dump-core */
shared_info->arch.max_pfn = arch_max_pfn;
munmap(shared_info, PAGE_SIZE);
rc = 0;
goto out;
+35 -34
View File
@@ -54,6 +54,11 @@ static unsigned long hvirt_start;
/* #levels of page tables used by the current guest */
static unsigned int pt_levels;
/* Shared-memory bitmaps for getting log-dirty bits from qemu */
static unsigned long *qemu_bitmaps[2];
static int qemu_active;
static int qemu_non_active;
int xc_hvm_drain_io(int handle, domid_t dom)
{
DECLARE_HYPERCALL;
@@ -77,7 +82,8 @@ int xc_hvm_drain_io(int handle, domid_t dom)
*/
#define BITS_PER_LONG (sizeof(unsigned long) * 8)
#define BITMAP_SIZE ((pfn_array_size + BITS_PER_LONG - 1) / 8)
#define BITS_TO_LONGS(bits) (((bits)+BITS_PER_LONG-1)/BITS_PER_LONG)
#define BITMAP_SIZE (BITS_TO_LONGS(pfn_array_size) * sizeof(unsigned long))
#define BITMAP_ENTRY(_nr,_bmap) \
((unsigned long *)(_bmap))[(_nr)/BITS_PER_LONG]
@@ -124,6 +130,7 @@ static inline int permute( int i, int nr, int order_nr )
return i;
}
static uint64_t tv_to_us(struct timeval *new)
{
return (new->tv_sec * 1000000) + new->tv_usec;
@@ -277,7 +284,9 @@ static int suspend_and_state(int (*suspend)(int), int xc_handle, int io_fd,
}
int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
uint32_t max_factor, uint32_t flags, int (*suspend)(int))
uint32_t max_factor, uint32_t flags, int (*suspend)(int),
void *(*init_qemu_maps)(int, unsigned),
void (*qemu_flip_buffer)(int, int))
{
xc_dominfo_t info;
@@ -293,9 +302,6 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
/* The size of an array big enough to contain all guest pfns */
unsigned long pfn_array_size;
/* The new domain's shared-info frame number. */
unsigned long shared_info_frame;
/* Other magic frames: ioreqs and xenstore comms */
unsigned long ioreq_pfn, bufioreq_pfn, store_pfn;
@@ -309,9 +315,6 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
uint32_t hvm_buf_size;
uint8_t *hvm_buf = NULL;
/* Live mapping of shared info structure */
shared_info_t *live_shinfo = NULL;
/* base of the region in which domain memory is mapped */
unsigned char *region_base = NULL;
@@ -363,7 +366,6 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
ERROR("HVM:Could not get vcpu context");
goto out;
}
shared_info_frame = info.shared_info_frame;
/* cheesy sanity check */
if ((info.max_memkb >> (PAGE_SHIFT - 10)) > max_mfn) {
@@ -372,13 +374,6 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
goto out;
}
/* Map the shared info frame */
if(!(live_shinfo = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE,
PROT_READ, shared_info_frame))) {
ERROR("HVM:Couldn't map live_shinfo");
goto out;
}
if ( xc_get_hvm_param(xc_handle, dom, HVM_PARAM_STORE_PFN, &store_pfn)
|| xc_get_hvm_param(xc_handle, dom, HVM_PARAM_IOREQ_PFN, &ioreq_pfn)
|| xc_get_hvm_param(xc_handle, dom,
@@ -392,8 +387,6 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
"nr_pages=0x%lx\n", info.max_memkb, max_mfn, info.nr_pages);
if (live) {
ERROR("hvm domain doesn't support live migration now.\n");
goto out;
if (xc_shadow_control(xc_handle, dom,
XEN_DOMCTL_SHADOW_OP_ENABLE_LOGDIRTY,
@@ -453,6 +446,15 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
to_skip = malloc(BITMAP_SIZE);
if (live) {
/* Get qemu-dm logging dirty pages too */
void *seg = init_qemu_maps(dom, BITMAP_SIZE);
qemu_bitmaps[0] = seg;
qemu_bitmaps[1] = seg + BITMAP_SIZE;
qemu_active = 0;
qemu_non_active = 1;
}
hvm_buf_size = xc_domain_hvm_getcontext(xc_handle, dom, 0, 0);
if ( hvm_buf_size == -1 )
{
@@ -509,13 +511,6 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
DPRINTF("Saving HVM domain memory pages: iter %d 0%%", iter);
if (last_iter && (max_pfn != live_shinfo->arch.max_pfn)) {
DPRINTF("calculated max_pfn as %#lx, shinfo says %#lx\n",
max_pfn, live_shinfo->arch.max_pfn);
ERROR("Max pfn doesn't match shared info");
goto out;
}
while( N < pfn_array_size ){
unsigned int this_pc = (N * 100) / pfn_array_size;
@@ -663,8 +658,7 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
goto out;
}
DPRINTF("SUSPEND shinfo %08lx eip %08lx edx %08lx\n",
info.shared_info_frame,
DPRINTF("SUSPEND eip %08lx edx %08lx\n",
(unsigned long)ctxt.user_regs.eip,
(unsigned long)ctxt.user_regs.edx);
}
@@ -677,10 +671,23 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
goto out;
}
/* Pull in the dirty bits from qemu too */
if (!last_iter) {
qemu_active = qemu_non_active;
qemu_non_active = qemu_active ? 0 : 1;
qemu_flip_buffer(dom, qemu_active);
for (j = 0; j < BITMAP_SIZE / sizeof(unsigned long); j++) {
to_send[j] |= qemu_bitmaps[qemu_non_active][j];
qemu_bitmaps[qemu_non_active][j] = 0;
}
} else {
for (j = 0; j < BITMAP_SIZE / sizeof(unsigned long); j++)
to_send[j] |= qemu_bitmaps[qemu_active][j];
}
sent_last_iter = sent_this_iter;
print_stats(xc_handle, dom, sent_this_iter, &stats, 1);
}
@@ -739,12 +746,6 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
ERROR("write HVM info failed!\n");
}
/* Shared-info pfn */
if (!write_exact(io_fd, &(shared_info_frame), sizeof(uint32_t)) ) {
ERROR("write shared-info pfn failed!\n");
goto out;
}
/* Success! */
rc = 0;
+14
View File
@@ -263,6 +263,15 @@ int xc_memory_op(int xc_handle,
goto out1;
}
break;
case XENMEM_current_reservation:
case XENMEM_maximum_reservation:
case XENMEM_maximum_gpfn:
if ( lock_pages(arg, sizeof(domid_t)) )
{
PERROR("Could not lock");
goto out1;
}
break;
}
ret = do_xen_hypercall(xc_handle, &hypercall);
@@ -287,6 +296,11 @@ int xc_memory_op(int xc_handle,
case XENMEM_add_to_physmap:
unlock_pages(arg, sizeof(struct xen_add_to_physmap));
break;
case XENMEM_current_reservation:
case XENMEM_maximum_reservation:
case XENMEM_maximum_gpfn:
unlock_pages(arg, sizeof(domid_t));
break;
}
out1:
+4 -2
View File
@@ -32,8 +32,10 @@ int xc_linux_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
* @return 0 on success, -1 on failure
*/
int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
uint32_t max_factor, uint32_t flags /* XCFLAGS_xxx */,
int (*suspend)(int domid));
uint32_t max_factor, uint32_t flags /* XCFLAGS_xxx */,
int (*suspend)(int domid),
void *(*init_qemu_maps)(int, unsigned),
void (*qemu_flip_buffer)(int, int));
/**
* This function will restore a saved domain running Linux.
+3 -1
View File
@@ -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;
-1
View File
@@ -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;
+34 -10
View File
@@ -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;
/**
@@ -250,13 +250,6 @@ extern bool
xen_vdi_get_physical_utilisation(xen_session *session, int64_t *result, xen_vdi vdi);
/**
* Get the sector_size field of the given VDI.
*/
extern bool
xen_vdi_get_sector_size(xen_session *session, int64_t *result, xen_vdi vdi);
/**
* Get the type field of the given VDI.
*/
@@ -278,6 +271,13 @@ extern bool
xen_vdi_get_read_only(xen_session *session, bool *result, xen_vdi vdi);
/**
* Get the other_config field of the given VDI.
*/
extern bool
xen_vdi_get_other_config(xen_session *session, xen_string_string_map **result, xen_vdi vdi);
/**
* Set the name/label field of the given VDI.
*/
@@ -313,6 +313,30 @@ 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);
/**
* Take an exact copy of the VDI; the snapshot lives in the same
* Storage Repository as its parent.
-3
View File
@@ -54,9 +54,6 @@ static const struct_member xen_vbd_record_struct_members[] =
{ .key = "device",
.type = &abstract_type_string,
.offset = offsetof(xen_vbd_record, device) },
{ .key = "image",
.type = &abstract_type_string,
.offset = offsetof(xen_vbd_record, image) },
{ .key = "bootable",
.type = &abstract_type_bool,
.offset = offsetof(xen_vbd_record, bootable) },
+74 -24
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2006, XenSource Inc.
* Copyright (c) 2006-2007, XenSource Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -24,6 +24,7 @@
#include "xen_crashdump.h"
#include "xen_internal.h"
#include "xen_sr.h"
#include "xen_string_string_map.h"
#include "xen_vbd.h"
#include "xen_vdi.h"
#include "xen_vdi_type_internal.h"
@@ -64,12 +65,6 @@ static const struct_member xen_vdi_record_struct_members[] =
{ .key = "physical_utilisation",
.type = &abstract_type_int,
.offset = offsetof(xen_vdi_record, physical_utilisation) },
{ .key = "sector_size",
.type = &abstract_type_int,
.offset = offsetof(xen_vdi_record, sector_size) },
{ .key = "location",
.type = &abstract_type_string,
.offset = offsetof(xen_vdi_record, location) },
{ .key = "type",
.type = &xen_vdi_type_abstract_type_,
.offset = offsetof(xen_vdi_record, type) },
@@ -78,7 +73,10 @@ static const struct_member xen_vdi_record_struct_members[] =
.offset = offsetof(xen_vdi_record, sharable) },
{ .key = "read_only",
.type = &abstract_type_bool,
.offset = offsetof(xen_vdi_record, read_only) }
.offset = offsetof(xen_vdi_record, read_only) },
{ .key = "other_config",
.type = &abstract_type_string_string_map,
.offset = offsetof(xen_vdi_record, other_config) }
};
const abstract_type xen_vdi_record_abstract_type_ =
@@ -105,6 +103,7 @@ xen_vdi_record_free(xen_vdi_record *record)
xen_sr_record_opt_free(record->sr);
xen_vbd_record_opt_set_free(record->vbds);
xen_crashdump_record_opt_set_free(record->crash_dumps);
xen_string_string_map_free(record->other_config);
free(record);
}
@@ -314,22 +313,6 @@ xen_vdi_get_physical_utilisation(xen_session *session, int64_t *result, xen_vdi
}
bool
xen_vdi_get_sector_size(xen_session *session, int64_t *result, xen_vdi vdi)
{
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)
{
@@ -377,6 +360,23 @@ xen_vdi_get_read_only(xen_session *session, bool *result, xen_vdi vdi)
}
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)
{
@@ -457,6 +457,56 @@ xen_vdi_set_read_only(xen_session *session, xen_vdi vdi, bool read_only)
}
bool
xen_vdi_set_other_config(xen_session *session, xen_vdi vdi, xen_string_string_map *other_config)
{
abstract_value param_values[] =
{
{ .type = &abstract_type_string,
.u.string_val = vdi },
{ .type = &abstract_type_string_string_map,
.u.set_val = (arbitrary_set *)other_config }
};
xen_call_(session, "VDI.set_other_config", param_values, 2, NULL, NULL);
return session->ok;
}
bool
xen_vdi_add_to_other_config(xen_session *session, xen_vdi vdi, char *key, char *value)
{
abstract_value param_values[] =
{
{ .type = &abstract_type_string,
.u.string_val = vdi },
{ .type = &abstract_type_string,
.u.string_val = key },
{ .type = &abstract_type_string,
.u.string_val = value }
};
xen_call_(session, "VDI.add_to_other_config", param_values, 3, NULL, NULL);
return session->ok;
}
bool
xen_vdi_remove_from_other_config(xen_session *session, xen_vdi vdi, char *key)
{
abstract_value param_values[] =
{
{ .type = &abstract_type_string,
.u.string_val = vdi },
{ .type = &abstract_type_string,
.u.string_val = key }
};
xen_call_(session, "VDI.remove_from_other_config", param_values, 2, NULL, NULL);
return session->ok;
}
bool
xen_vdi_snapshot(xen_session *session, xen_vdi *result, xen_vdi vdi)
{
+1 -2
View File
@@ -421,8 +421,7 @@ static xen_vm create_new_vm(xen_session *session, bool hvm)
.name_label = "MyRootFS",
.name_description = "MyRootFS description",
.sr = &sr_record,
.virtual_size = (1 << 21), // 1GiB / 512 bytes/sector
.sector_size = 512,
.virtual_size = (INT64_C(1) << 30), // 1GiB
.type = XEN_VDI_TYPE_SYSTEM,
.sharable = false,
.read_only = false
+1 -2
View File
@@ -39,14 +39,13 @@ vm_cfg = {
local_vdi_cfg = {
'name_label': 'gentoo.hvm',
'name_description': '',
'location': 'file:/root/gentoo.amd64.hvm.img',
'virtual_size': 0,
'sector_size': 0,
'type': 'system',
'parent': '',
'SR_name': 'Local',
'sharable': False,
'read_only': False,
'other_config': {'location': 'file:/root/gentoo.amd64.hvm.img'},
}
local_vbd_cfg = {
+2 -4
View File
@@ -39,8 +39,7 @@ vm_cfg = {
vdi_cfg = {
'name_label': 'API_VDI',
'name_description': '',
'virtual_size': 100 * 1024 * 1024,
'sector_size': 1024,
'virtual_size': 100 * 1024 * 1024 * 1024,
'type': 'system',
'parent': '',
'SR_name': 'QCoW',
@@ -60,14 +59,13 @@ vbd_cfg = {
local_vdi_cfg = {
'name_label': 'gentoo.amd64.img',
'name_description': '',
'location': 'file:/root/gentoo.amd64.img',
'virtual_size': 0,
'sector_size': 0,
'type': 'system',
'parent': '',
'SR_name': 'Local',
'sharable': False,
'read_only': False,
'other_config': {'location': 'file:/root/gentoo.amd64.img'},
}
local_vbd_cfg = {
+3 -8
View File
@@ -40,8 +40,7 @@ VM_LIST_FORMAT = '%(name_label)-18s %(memory_actual)-5s %(VCPUs_number)-5s'\
' %(power_state)-10s %(uuid)-36s'
SR_LIST_FORMAT = '%(name_label)-18s %(uuid)-36s %(physical_size)-10s' \
'%(type)-10s'
VDI_LIST_FORMAT = '%(name_label)-18s %(uuid)-36s %(virtual_size)-8s '\
'%(sector_size)-8s'
VDI_LIST_FORMAT = '%(name_label)-18s %(uuid)-36s %(virtual_size)-8s'
VBD_LIST_FORMAT = '%(device)-6s %(uuid)-36s %(VDI)-8s'
TASK_LIST_FORMAT = '%(name_label)-18s %(uuid)-36s %(status)-8s %(progress)-4s'
VIF_LIST_FORMAT = '%(name)-8s %(device)-7s %(uuid)-36s %(MAC)-10s'
@@ -96,12 +95,9 @@ OPTIONS = {
'vdi-create': [(('--name-label',), {'help': 'Name for VDI'}),
(('--name-description',), {'help': 'Description for VDI'}),
(('--sector-size',), {'type': 'int',
'help': 'Sector size',
'default': 0}),
(('--virtual-size',), {'type': 'int',
'default': 0,
'help': 'Size of VDI in sectors'}),
'help': 'Size of VDI in bytes'}),
(('--type',), {'choices': ['system', 'user', 'ephemeral'],
'default': 'system',
'help': 'VDI type'}),
@@ -569,8 +565,7 @@ def xapi_vdi_list(args, async = False):
if not is_long:
print VDI_LIST_FORMAT % {'name_label': 'VDI Label',
'uuid' : 'UUID',
'virtual_size': 'Bytes',
'sector_size': 'Sector Size'}
'virtual_size': 'Bytes'}
for vdi in vdis:
vdi_struct = execute(server, 'VDI.get_record', (session, vdi))
+1 -2
View File
@@ -1,7 +1,6 @@
name_label = 'VDI 1'
name_description = ''
virtual_size = 10 * 1024 * 1024
sector_size = 1024
virtual_size = 10 * 1024 * 1024 * 1024
type = 'system'
sharable = False
read_only = False
+40 -28
View File
@@ -50,17 +50,21 @@ static PyObject *pyxc_error_to_exception(void)
const xc_error *err = xc_get_last_error();
const char *desc = xc_error_code_to_desc(err->code);
if (err->code == XC_ERROR_NONE)
if ( err->code == XC_ERROR_NONE )
return PyErr_SetFromErrno(xc_error_obj);
if (err->message[0] != '\0')
if ( err->message[0] != '\0' )
pyerr = Py_BuildValue("(iss)", err->code, desc, err->message);
else
pyerr = Py_BuildValue("(is)", err->code, desc);
xc_clear_last_error();
PyErr_SetObject(xc_error_obj, pyerr);
if ( pyerr != NULL )
{
PyErr_SetObject(xc_error_obj, pyerr);
Py_DECREF(pyerr);
}
return NULL;
}
@@ -70,13 +74,13 @@ static PyObject *pyxc_domain_dumpcore(XcObject *self, PyObject *args)
uint32_t dom;
char *corefile;
if (!PyArg_ParseTuple(args, "is", &dom, &corefile))
if ( !PyArg_ParseTuple(args, "is", &dom, &corefile) )
return NULL;
if ( (corefile == NULL) || (corefile[0] == '\0') )
return NULL;
if (xc_domain_dumpcore(self->xc_handle, dom, corefile) != 0)
if ( xc_domain_dumpcore(self->xc_handle, dom, corefile) != 0 )
return pyxc_error_to_exception();
Py_INCREF(zero);
@@ -168,10 +172,10 @@ static PyObject *pyxc_domain_shutdown(XcObject *self, PyObject *args)
{
uint32_t dom, reason;
if (!PyArg_ParseTuple(args, "ii", &dom, &reason))
if ( !PyArg_ParseTuple(args, "ii", &dom, &reason) )
return NULL;
if (xc_domain_shutdown(self->xc_handle, dom, reason) != 0)
if ( xc_domain_shutdown(self->xc_handle, dom, reason) != 0 )
return pyxc_error_to_exception();
Py_INCREF(zero);
@@ -183,10 +187,10 @@ static PyObject *pyxc_domain_resume(XcObject *self, PyObject *args)
uint32_t dom;
int fast;
if (!PyArg_ParseTuple(args, "ii", &dom, &fast))
if ( !PyArg_ParseTuple(args, "ii", &dom, &fast) )
return NULL;
if (xc_domain_resume(self->xc_handle, dom, fast) != 0)
if ( xc_domain_resume(self->xc_handle, dom, fast) != 0 )
return pyxc_error_to_exception();
Py_INCREF(zero);
@@ -282,7 +286,7 @@ static PyObject *pyxc_domain_getinfo(XcObject *self,
PyObject *args,
PyObject *kwds)
{
PyObject *list, *info_dict;
PyObject *list, *info_dict, *pyhandle;
uint32_t first_dom = 0;
int max_doms = 1024, nr_doms, i, j;
@@ -308,26 +312,34 @@ static PyObject *pyxc_domain_getinfo(XcObject *self,
list = PyList_New(nr_doms);
for ( i = 0 ; i < nr_doms; i++ )
{
PyObject *pyhandle = PyList_New(sizeof(xen_domain_handle_t));
info_dict = Py_BuildValue(
"{s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i"
",s:L,s:L,s:L,s:i,s:i}",
"domid", (int)info[i].domid,
"online_vcpus", info[i].nr_online_vcpus,
"max_vcpu_id", info[i].max_vcpu_id,
"hvm", info[i].hvm,
"dying", info[i].dying,
"crashed", info[i].crashed,
"shutdown", info[i].shutdown,
"paused", info[i].paused,
"blocked", info[i].blocked,
"running", info[i].running,
"mem_kb", (long long)info[i].nr_pages*(XC_PAGE_SIZE/1024),
"cpu_time", (long long)info[i].cpu_time,
"maxmem_kb", (long long)info[i].max_memkb,
"ssidref", (int)info[i].ssidref,
"shutdown_reason", info[i].shutdown_reason);
pyhandle = PyList_New(sizeof(xen_domain_handle_t));
if ( (pyhandle == NULL) || (info_dict == NULL) )
{
Py_DECREF(list);
if ( pyhandle != NULL ) { Py_DECREF(pyhandle); }
if ( info_dict != NULL ) { Py_DECREF(info_dict); }
return NULL;
}
for ( j = 0; j < sizeof(xen_domain_handle_t); j++ )
PyList_SetItem(pyhandle, j, PyInt_FromLong(info[i].handle[j]));
info_dict = Py_BuildValue("{s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i"
",s:l,s:L,s:l,s:i,s:i}",
"domid", info[i].domid,
"online_vcpus", info[i].nr_online_vcpus,
"max_vcpu_id", info[i].max_vcpu_id,
"hvm", info[i].hvm,
"dying", info[i].dying,
"crashed", info[i].crashed,
"shutdown", info[i].shutdown,
"paused", info[i].paused,
"blocked", info[i].blocked,
"running", info[i].running,
"mem_kb", info[i].nr_pages*(XC_PAGE_SIZE/1024),
"cpu_time", info[i].cpu_time,
"maxmem_kb", info[i].max_memkb,
"ssidref", info[i].ssidref,
"shutdown_reason", info[i].shutdown_reason);
PyDict_SetItemString(info_dict, "handle", pyhandle);
Py_DECREF(pyhandle);
PyList_SetItem(list, i, info_dict);
+12 -5
View File
@@ -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
+23 -17
View File
@@ -227,24 +227,30 @@ class TCPXMLRPCServer(SocketServer.ThreadingMixIn, SimpleXMLRPCServer):
response = xmlrpclib.dumps(response,
methodresponse=1,
allow_none=1)
except xmlrpclib.Fault, fault:
response = xmlrpclib.dumps(fault)
except Exception, exn:
if self.xenapi:
if _is_not_supported(exn):
errdesc = ['MESSAGE_METHOD_UNKNOWN', method]
try:
if self.xenapi:
if _is_not_supported(exn):
errdesc = ['MESSAGE_METHOD_UNKNOWN', method]
else:
log.exception('Internal error handling %s', method)
errdesc = ['INTERNAL_ERROR', str(exn)]
response = xmlrpclib.dumps(
({ "Status": "Failure",
"ErrorDescription": errdesc },),
methodresponse = 1)
else:
log.exception('Internal error handling %s', method)
errdesc = ['INTERNAL_ERROR', str(exn)]
response = xmlrpclib.dumps(
({ "Status": "Failure",
"ErrorDescription": errdesc },),
methodresponse = 1)
else:
log.exception('Internal error handling %s', method)
import xen.xend.XendClient
response = xmlrpclib.dumps(
xmlrpclib.Fault(xen.xend.XendClient.ERROR_INTERNAL, str(exn)))
import xen.xend.XendClient
if isinstance(exn, xmlrpclib.Fault):
response = xmlrpclib.dumps(exn)
else:
log.exception('Internal error handling %s', method)
response = xmlrpclib.dumps(
xmlrpclib.Fault(xen.xend.XendClient.ERROR_INTERNAL, str(exn)))
except:
log.exception('Internal error handling error')
return response
@@ -253,7 +259,7 @@ def _is_not_supported(exn):
try:
m = notSupportedRE.search(exn[0])
return m is not None
except TypeError, e:
except:
return False
+120 -33
View File
@@ -36,6 +36,9 @@ from xen.xend.XendVMMetrics import XendVMMetrics
from xen.xend.XendAPIConstants import *
from xen.util.xmlrpclib2 import stringify
from xen.util.blkif import blkdev_name_to_number
AUTH_NONE = 'none'
AUTH_PAM = 'pam'
@@ -662,7 +665,8 @@ class XendAPI(object):
('add_to_other_config', None),
('remove_from_other_config', None),
('dmesg', 'String'),
('get_log', 'String')]
('get_log', 'String'),
('send_debug_keys', None)]
host_funcs = [('get_by_name_label', 'Set(host)')]
@@ -749,6 +753,11 @@ class XendAPI(object):
log_buffer = log_file.read()
return xen_api_success(log_buffer)
def host_send_debug_keys(self, _, host_ref, keys):
node = XendNode.instance()
node.send_debug_keys(keys)
return xen_api_success_void()
def host_get_record(self, session, host_ref):
node = XendNode.instance()
dom = XendDomain.instance()
@@ -1070,6 +1079,7 @@ class XendAPI(object):
('hard_reboot', None),
('suspend', None),
('resume', None),
('send_sysrq', None),
('add_to_HVM_boot_params', None),
('remove_from_HVM_boot_params', None),
('add_to_VCPUs_params', None),
@@ -1077,7 +1087,8 @@ class XendAPI(object):
('add_to_platform', None),
('remove_from_platform', None),
('add_to_other_config', None),
('remove_from_other_config', None)]
('remove_from_other_config', None),
('send_trigger', None)]
VM_funcs = [('create', 'VM'),
('get_by_name_label', 'Set(VM)')]
@@ -1513,6 +1524,24 @@ class XendAPI(object):
return XendTask.log_progress(0, 100, do_vm_func,
"domain_unpause", vm_ref)
def VM_send_sysrq(self, _, vm_ref, req):
xeninfo = XendDomain.instance().get_vm_by_uuid(vm_ref)
if xeninfo.state != XEN_API_VM_POWER_STATE_RUNNING:
return xen_api_error(
['VM_BAD_POWER_STATE', vm_ref,
XendDomain.POWER_STATE_NAMES[XEN_API_VM_POWER_STATE_RUNNING],
XendDomain.POWER_STATE_NAMES[xeninfo.state]])
xeninfo.send_sysrq(req)
return xen_api_success_void()
def VM_send_trigger(self, _, vm_ref, trigger, vcpu):
xendom = XendDomain.instance()
xeninfo = xendom.get_vm_by_uuid(vm_ref)
xendom.domain_send_trigger(xeninfo.getDomid(), trigger, vcpu)
return xen_api_success_void()
# Xen API: Class VM_metrics
# ----------------------------------------------------------------
@@ -1538,12 +1567,13 @@ class XendAPI(object):
return xen_api_success(self._VM_metrics_get(ref).get_vcpus_number())
def VM_metrics_get_vcpus_utilisation(self, _, ref):
return xen_api_success(self._VM_metrics_get(ref).get_metrics_get_vcpus_utilisation())
return xen_api_success(self._VM_metrics_get(ref).get_vcpus_utilisation())
# Xen API: Class VBD
# ----------------------------------------------------------------
VBD_attr_ro = ['metrics']
VBD_attr_ro = ['metrics',
'runtime_properties']
VBD_attr_rw = ['VM',
'VDI',
'device',
@@ -1584,23 +1614,28 @@ class XendAPI(object):
# class methods
def VBD_create(self, session, vbd_struct):
xendom = XendDomain.instance()
xennode = XendNode.instance()
if not xendom.is_valid_vm(vbd_struct['VM']):
return xen_api_error(['HANDLE_INVALID', 'VM', vbd_struct['VM']])
dom = xendom.get_vm_by_uuid(vbd_struct['VM'])
vbd_ref = ''
vdi = xennode.get_vdi_by_uuid(vbd_struct['VDI'])
if not vdi:
return xen_api_error(['HANDLE_INVALID', 'VDI', vdi_ref])
# new VBD via VDI/SR
vdi_image = vdi.get_location()
try:
# new VBD via VDI/SR
vdi_ref = vbd_struct.get('VDI')
vdi = XendNode.instance().get_vdi_by_uuid(vdi_ref)
if not vdi:
return xen_api_error(['HANDLE_INVALID', 'VDI', vdi_ref])
vdi_image = vdi.get_location()
vbd_ref = XendTask.log_progress(0, 100,
dom.create_vbd,
vbd_struct, vdi_image)
except XendError:
return xen_api_todo()
except XendError, e:
log.exception("Error in VBD_create")
return xen_api_error(['INTERNAL_ERROR', str(e)])
vdi.addVBD(vbd_ref)
xendom.managed_config_save(dom)
return xen_api_success(vbd_ref)
@@ -1612,7 +1647,14 @@ class XendAPI(object):
if not vm:
return xen_api_error(['HANDLE_INVALID', 'VBD', vbd_ref])
vdi_ref = XendDomain.instance()\
.get_dev_property_by_uuid('vbd', vbd_ref, "VDI")
vdi = XendNode.instance().get_vdi_by_uuid(vdi_ref)
XendTask.log_progress(0, 100, vm.destroy_vbd, vbd_ref)
vdi.removeVBD(vbd_ref)
return xen_api_success_void()
def _VBD_get(self, vbd_ref, prop):
@@ -1624,6 +1666,24 @@ class XendAPI(object):
def VBD_get_metrics(self, _, vbd_ref):
return xen_api_success(vbd_ref)
def VBD_get_runtime_properties(self, _, vbd_ref):
xendom = XendDomain.instance()
dominfo = xendom.get_vm_with_dev_uuid('vbd', vbd_ref)
device = dominfo.get_dev_config_by_uuid('vbd', vbd_ref)
try:
devid = int(device['id'])
device_sxps = dominfo.getDeviceSxprs('vbd')
device_dicts = [dict(device_sxp[1][1:]) for device_sxp in device_sxps]
device_dict = [device_dict
for device_dict in device_dicts
if int(device_dict['virtual-device']) == devid][0]
return xen_api_success(device_dict)
except Exception, exn:
log.exception(exn)
return xen_api_success({})
# attributes (rw)
def VBD_get_VM(self, session, vbd_ref):
return self._VBD_get(vbd_ref, 'VM')
@@ -1684,7 +1744,8 @@ class XendAPI(object):
# Xen API: Class VIF
# ----------------------------------------------------------------
VIF_attr_ro = ['metrics']
VIF_attr_ro = ['metrics',
'runtime_properties']
VIF_attr_rw = ['device',
'network',
'VM',
@@ -1721,18 +1782,17 @@ class XendAPI(object):
# class methods
def VIF_create(self, session, vif_struct):
xendom = XendDomain.instance()
if xendom.is_valid_vm(vif_struct['VM']):
dom = xendom.get_vm_by_uuid(vif_struct['VM'])
try:
vif_ref = dom.create_vif(vif_struct)
xendom.managed_config_save(dom)
return xen_api_success(vif_ref)
except XendError:
return xen_api_error(XEND_ERROR_TODO)
else:
if not xendom.is_valid_vm(vif_struct['VM']):
return xen_api_error(['HANDLE_INVALID', 'VM', vif_struct['VM']])
dom = xendom.get_vm_by_uuid(vif_struct['VM'])
try:
vif_ref = dom.create_vif(vif_struct)
xendom.managed_config_save(dom)
return xen_api_success(vif_ref)
except XendError:
return xen_api_error(XEND_ERROR_TODO)
def VIF_destroy(self, session, vif_ref):
xendom = XendDomain.instance()
vm = xendom.get_vm_with_dev_uuid('vif', vif_ref)
@@ -1770,6 +1830,27 @@ class XendAPI(object):
vifs = reduce(lambda x, y: x + y, vifs)
return xen_api_success(vifs)
def VIF_get_runtime_properties(self, _, vif_ref):
xendom = XendDomain.instance()
dominfo = xendom.get_vm_with_dev_uuid('vif', vif_ref)
device = dominfo.get_dev_config_by_uuid('vif', vif_ref)
try:
devid = int(device['id'])
device_sxps = dominfo.getDeviceSxprs('vif')
device_dicts = [dict(device_sxp[1][1:])
for device_sxp in device_sxps]
device_dict = [device_dict
for device_dict in device_dicts
if int(device_dict['handle']) == devid][0]
return xen_api_success(device_dict)
except Exception, exn:
log.exception(exn)
return xen_api_success({})
# Xen API: Class VIF_metrics
# ----------------------------------------------------------------
@@ -1799,13 +1880,13 @@ class XendAPI(object):
VDI_attr_ro = ['SR',
'VBDs',
'physical_utilisation',
'sector_size',
'type']
VDI_attr_rw = ['name_label',
'name_description',
'virtual_size',
'sharable',
'read_only']
'read_only',
'other_config']
VDI_attr_inst = VDI_attr_ro + VDI_attr_rw
VDI_methods = [('snapshot', 'VDI')]
@@ -1816,14 +1897,12 @@ class XendAPI(object):
return XendNode.instance().get_vdi_by_uuid(ref)
def VDI_get_VBDs(self, session, vdi_ref):
return xen_api_todo()
vdi = XendNode.instance().get_vdi_by_uuid(vdi_ref)
return xen_api_success(vdi.getVBDs())
def VDI_get_physical_utilisation(self, session, vdi_ref):
return xen_api_success(self._get_VDI(vdi_ref).
get_physical_utilisation())
def VDI_get_sector_size(self, session, vdi_ref):
return xen_api_success(self._get_VDI(vdi_ref).sector_size)
get_physical_utilisation())
def VDI_get_type(self, session, vdi_ref):
return xen_api_success(self._get_VDI(vdi_ref).type)
@@ -1865,6 +1944,14 @@ class XendAPI(object):
self._get_VDI(vdi_ref).read_only = bool(value)
return xen_api_success_void()
def VDI_get_other_config(self, session, vdi_ref):
return xen_api_success(
self._get_VDI(vdi_ref).other_config)
def VDI_set_other_config(self, session, vdi_ref, other_config):
self._get_VDI(vdi_ref).other_config = other_config
return xen_api_success_void()
# Object Methods
def VDI_snapshot(self, session, vdi_ref):
return xen_api_todo()
@@ -1881,13 +1968,13 @@ class XendAPI(object):
'name_label': image.name_label,
'name_description': image.name_description,
'SR': image.sr_uuid,
'VBDs': [], # TODO
'VBDs': image.getVBDs(),
'virtual_size': image.virtual_size,
'physical_utilisation': image.physical_utilisation,
'sector_size': image.sector_size,
'type': image.type,
'sharable': image.sharable,
'read_only': image.read_only,
'other_config': image.other_config
})
# Class Functions
+2 -2
View File
@@ -193,8 +193,8 @@ def restore(xd, fd, dominfo = None, paused = False):
is_hvm = dominfo.info.is_hvm()
if is_hvm:
hvm = dominfo.info['memory_static_min']
apic = dominfo.info['platform'].get('apic', 0)
pae = dominfo.info['platform'].get('pae', 0)
apic = int(dominfo.info['platform'].get('apic', 0))
pae = int(dominfo.info['platform'].get('pae', 0))
log.info("restore hvm domain %d, mem=%d, apic=%d, pae=%d",
dominfo.domid, hvm, apic, pae)
else:
+77 -30
View File
@@ -28,7 +28,7 @@ from xen.xend.PrettyPrint import prettyprintstring
from xen.xend.XendConstants import DOM_STATE_HALTED
log = logging.getLogger("xend.XendConfig")
log.setLevel(logging.DEBUG)
log.setLevel(logging.WARN)
"""
@@ -105,8 +105,6 @@ XENAPI_CFG_TO_LEGACY_CFG = {
'uuid': 'uuid',
'vcpus_number': 'vcpus',
'cpus': 'cpus',
'memory_static_min': 'memory',
'memory_static_max': 'maxmem',
'name_label': 'name',
'actions_after_shutdown': 'on_poweroff',
'actions_after_reboot': 'on_reboot',
@@ -136,11 +134,10 @@ XENAPI_CFG_TYPES = {
'user_version': str,
'is_a_template': bool0,
'resident_on': str,
'memory_static_min': int,
'memory_static_min': int, # note these are stored in bytes, not KB!
'memory_static_max': int,
'memory_dynamic_min': int,
'memory_dynamic_max': int,
'memory_actual': int,
'cpus': list,
'vcpus_policy': str,
'vcpus_params': dict,
@@ -314,7 +311,6 @@ class XendConfig(dict):
'shadow_memory': 0,
'memory_static_max': 0,
'memory_dynamic_max': 0,
'memory_actual': 0,
'devices': {},
'security': None,
'on_xend_start': 'ignore',
@@ -334,20 +330,39 @@ class XendConfig(dict):
return defaults
#
# Here we assume these values exist in the dict.
# If they don't we have a bigger problem, lets not
# try and 'fix it up' but acutually fix the cause ;-)
#
def _memory_sanity_check(self):
if self['memory_static_min'] == 0:
self['memory_static_min'] = self['memory_dynamic_min']
# If the static max is not set, let's set it to dynamic max.
# If the static max is smaller than static min, then fix it!
self['memory_static_max'] = max(self['memory_static_max'],
self['memory_dynamic_max'],
self['memory_static_min'])
for mem_type in ('memory_static_min', 'memory_static_max'):
if self[mem_type] <= 0:
raise XendConfigError('Memory value too low for %s: %d' %
(mem_type, self[mem_type]))
log.debug("_memory_sanity_check memory_static_min: %s, "
"memory_static_max: %i, "
"memory_dynamic_min: %i, "
"memory_dynamic_max: %i",
self["memory_static_min"],
self["memory_static_max"],
self["memory_dynamic_min"],
self["memory_dynamic_max"])
if not self["memory_static_min"] <= self["memory_static_max"]:
raise XendConfigError("memory_static_min must be less " \
"than or equal to memory_static_max")
if not self["memory_dynamic_min"] <= self["memory_dynamic_max"]:
raise XendConfigError("memory_dynamic_min must be less " \
"than or equal to memory_dynamic_max")
if not self["memory_static_min"] <= self["memory_dynamic_min"]:
raise XendConfigError("memory_static_min must be less " \
"than or equal to memory_dynamic_min")
if not self["memory_dynamic_max"] <= self["memory_static_max"]:
raise XendConfigError("memory_dynamic_max must be less " \
"than or equal to memory_static_max")
if not self["memory_dynamic_max"] > 0:
raise XendConfigError("memory_dynamic_max must be greater " \
"than zero")
if not self["memory_static_max"] > 0:
raise XendConfigError("memory_static_max must be greater " \
"than zero")
def _actions_sanity_check(self):
for event in ['shutdown', 'reboot', 'crash']:
@@ -392,8 +407,12 @@ class XendConfig(dict):
self['domid'] = dominfo['domid']
self['online_vcpus'] = dominfo['online_vcpus']
self['vcpus_number'] = dominfo['max_vcpu_id'] + 1
self['memory_dynamic_min'] = (dominfo['mem_kb'] + 1023)/1024
self['memory_dynamic_max'] = (dominfo['maxmem_kb'] + 1023)/1024
self['memory_dynamic_min'] = dominfo['mem_kb'] * 1024
self['memory_dynamic_max'] = dominfo['mem_kb'] * 1024
self['memory_static_min'] = 0
self['memory_static_max'] = dominfo['maxmem_kb'] * 1024
self['cpu_time'] = dominfo['cpu_time']/1e9
# TODO: i don't know what the security stuff expects here
if dominfo.get('ssidref'):
@@ -447,6 +466,13 @@ class XendConfig(dict):
log.warn('Ignoring unrecognised value for deprecated option:'
'restart = \'%s\'', restart)
# Handle memory, passed in as MiB
if sxp.child_value(sxp_cfg, "memory") != None:
cfg["memory"] = int(sxp.child_value(sxp_cfg, "memory"))
if sxp.child_value(sxp_cfg, "maxmem") != None:
cfg["maxmem"] = int(sxp.child_value(sxp_cfg, "maxmem"))
# Only extract options we know about.
extract_keys = LEGACY_UNSUPPORTED_BY_XENAPI_CFG
extract_keys += XENAPI_CFG_TO_LEGACY_CFG.values()
@@ -616,6 +642,21 @@ class XendConfig(dict):
except KeyError:
pass
# Lets try and handle memory correctly
MiB = 1024 * 1024
if "memory" in cfg:
self["memory_static_min"] = 0
self["memory_static_max"] = int(cfg["memory"]) * MiB
self["memory_dynamic_min"] = int(cfg["memory"]) * MiB
self["memory_dynamic_max"] = int(cfg["memory"]) * MiB
if "maxmem" in cfg:
self["memory_static_max"] = int(cfg["maxmem"]) * MiB
self._memory_sanity_check()
def update_with(n, o):
if not self.get(n):
self[n] = cfg.get(o, '')
@@ -632,13 +673,6 @@ class XendConfig(dict):
if key in cfg:
self['platform'][key] = cfg[key]
# make sure a sane maximum is set
if self['memory_static_max'] <= 0:
self['memory_static_max'] = self['memory_static_min']
self['memory_dynamic_max'] = self['memory_static_max']
self['memory_dynamic_min'] = self['memory_static_min']
# set device references in the configuration
self['devices'] = cfg.get('devices', {})
self['console_refs'] = cfg.get('console_refs', [])
@@ -812,6 +846,21 @@ class XendConfig(dict):
else:
sxpr.append([legacy, self[xenapi]])
MiB = 1024*1024
sxpr.append(["maxmem", int(self["memory_static_max"])/MiB])
sxpr.append(["memory", int(self["memory_dynamic_max"])/MiB])
if not legacy_only:
sxpr.append(['memory_dynamic_min',
int(self.get('memory_dynamic_min'))])
sxpr.append(['memory_dynamic_max',
int(self.get('memory_dynamic_max'))])
sxpr.append(['memory_static_max',
int(self.get('memory_static_max'))])
sxpr.append(['memory_static_min',
int(self.get('memory_static_min'))])
for legacy in LEGACY_UNSUPPORTED_BY_XENAPI_CFG:
if legacy in ('domid', 'uuid'): # skip these
continue
@@ -820,8 +869,6 @@ class XendConfig(dict):
sxpr.append(['image', self.image_sxpr()])
sxpr.append(['status', domain.state])
sxpr.append(['memory_dynamic_min', self.get('memory_dynamic_min')])
sxpr.append(['memory_dynamic_max', self.get('memory_dynamic_max')])
if domain.getDomid() is not None:
sxpr.append(['state', self._get_old_state_string()])
+1 -1
View File
@@ -674,7 +674,7 @@ class XendDomain:
else:
return domid
raise XendInvalidDomain("Domain does not exist")
raise XendInvalidDomain(vm_uuid)
finally:
self.domains_lock.release()
+81 -25
View File
@@ -34,7 +34,7 @@ from types import StringTypes
import xen.lowlevel.xc
from xen.util import asserts
from xen.util.blkif import blkdev_uname_to_file
from xen.util.blkif import blkdev_uname_to_file, blkdev_uname_to_taptype
from xen.util import security
from xen.xend import balloon, sxp, uuid, image, arch, osdep
@@ -576,12 +576,14 @@ class XendDomainInfo:
if target <= 0:
raise XendError('Invalid memory size')
self.info['memory_static_min'] = target
MiB = 1024 * 1024
self.info['memory_dynamic_min'] = target * MiB
self.info['memory_dynamic_max'] = target * MiB
if self.domid >= 0:
self.storeVm("memory", target)
self.storeDom("memory/target", target << 10)
else:
self.info['memory_dynamic_min'] = target
xen.xend.XendDomain.instance().managed_config_save(self)
def setMemoryMaximum(self, limit):
@@ -664,6 +666,10 @@ class XendDomainInfo:
if arg in XendConfig.LEGACY_CFG_TO_XENAPI_CFG:
xapiarg = XendConfig.LEGACY_CFG_TO_XENAPI_CFG[arg]
self.info[xapiarg] = val
elif arg == "memory":
self.info["static_memory_min"] = val
elif arg == "maxmem":
self.info["static_memory_max"] = val
else:
self.info[arg] = val
@@ -780,7 +786,7 @@ class XendDomainInfo:
'vm': self.vmpath,
'name': self.info['name_label'],
'console/limit': str(xoptions.get_console_limit() * 1024),
'memory/target': str(self.info['memory_static_min'] * 1024),
'memory/target': str(self.info['memory_dynamic_max'] / 1024),
}
def f(n, v):
@@ -864,7 +870,15 @@ class XendDomainInfo:
xapiarg = XendConfig.LEGACY_CFG_TO_XENAPI_CFG[arg]
if val != None and val != self.info[xapiarg]:
self.info[xapiarg] = val
changed= True
changed = True
elif arg == "memory":
if val != None and val != self.info["static_memory_min"]:
self.info["static_memory_min"] = val
changed = True
elif arg == "maxmem":
if val != None and val != self.info["static_memory_max"]:
self.info["static_memory_max"] = val
changed = True
# Check whether image definition has been updated
image_sxp = self._readVm('image')
@@ -969,11 +983,12 @@ class XendDomainInfo:
def getMemoryTarget(self):
"""Get this domain's target memory size, in KB."""
return self.info['memory_static_min'] * 1024
return self.info['memory_dynamic_max'] / 1024
def getMemoryMaximum(self):
"""Get this domain's maximum memory size, in KB."""
return self.info['memory_static_max'] * 1024
# remember, info now stores memory in bytes
return self.info['memory_static_max'] / 1024
def getResume(self):
return str(self._resume)
@@ -1455,13 +1470,14 @@ class XendDomainInfo:
# Use architecture- and image-specific calculations to determine
# the various headrooms necessary, given the raw configured
# values. maxmem, memory, and shadow are all in KiB.
# but memory_static_max etc are all stored in bytes now.
memory = self.image.getRequiredAvailableMemory(
self.info['memory_static_min'] * 1024)
self.info['memory_dynamic_max'] / 1024)
maxmem = self.image.getRequiredAvailableMemory(
self.info['memory_static_max'] * 1024)
self.info['memory_static_max'] / 1024)
shadow = self.image.getRequiredShadowMemory(
self.info['shadow_memory'] * 1024,
self.info['memory_static_max'] * 1024)
self.info['shadow_memory'] / 1024,
self.info['memory_static_max'] / 1024)
log.debug("_initDomain:shadow_memory=0x%x, memory_static_max=0x%x, memory_static_min=0x%x.", self.info['shadow_memory'], self.info['memory_static_max'], self.info['memory_static_min'],)
# Round shadow up to a multiple of a MiB, as shadow_mem_control
@@ -1650,7 +1666,18 @@ class XendDomainInfo:
log.exception("XendDomainInfo.destroy: xc.domain_destroy failed.")
from xen.xend import XendDomain
XendDomain.instance().remove_domain(self)
if "transient" in self.info["other_config"]\
and bool(self.info["other_config"]["transient"]):
xendDomainInstance = XendDomain.instance()
xendDomainInstance.domains_lock.acquire()
xendDomainInstance._refresh(refresh_shutdown = False)
xendDomainInstance.domains_lock.release()
xendDomainInstance.domain_delete(self.info["name_label"])
else:
XendDomain.instance().remove_domain(self)
self.cleanupDomain()
self._cleanup_phantom_devs(paths)
@@ -1759,7 +1786,8 @@ class XendDomainInfo:
disk = devinfo[1]['uname']
fn = blkdev_uname_to_file(disk)
mounted = devtype == 'tap' and not os.stat(fn).st_rdev
taptype = blkdev_uname_to_taptype(disk)
mounted = devtype == 'tap' and taptype != 'aio' and taptype != 'sync' and not os.stat(fn).st_rdev
if mounted:
# This is a file, not a device. pygrub can cope with a
# file if it's raw, but if it's QCOW or other such formats
@@ -1775,7 +1803,7 @@ class XendDomainInfo:
from xen.xend import XendDomain
dom0 = XendDomain.instance().privilegedDomain()
dom0._waitForDeviceUUID(dom0.create_vbd(vbd, fn))
dom0._waitForDeviceUUID(dom0.create_vbd(vbd, disk))
fn = BOOTLOADER_LOOPBACK_DEVICE
try:
@@ -1833,7 +1861,7 @@ class XendDomainInfo:
# 1MB per vcpu plus 4Kib/Mib of RAM. This is higher than
# the minimum that Xen would allocate if no value were given.
overhead_kb = self.info['vcpus_number'] * 1024 + \
self.info['memory_static_max'] * 4
(self.info['memory_static_max'] / 1024 / 1024) * 4
overhead_kb = ((overhead_kb + 1023) / 1024) * 1024
# The domain might already have some shadow memory
overhead_kb -= xc.shadow_mem_control(self.domid) * 1024
@@ -1899,6 +1927,11 @@ class XendDomainInfo:
if self._infoIsSet(info_key):
to_store[key] = str(self.info[info_key])
if self._infoIsSet("static_memory_min"):
to_store["memory"] = str(self.info["static_memory_min"])
if self._infoIsSet("static_memory_max"):
to_store["maxmem"] = str(self.info["static_memory_max"])
image_sxpr = self.info.image_sxpr()
if image_sxpr:
to_store['image'] = sxp.to_string(image_sxpr)
@@ -1988,7 +2021,11 @@ class XendDomainInfo:
info = dom_get(self.domid)
if not info:
return
if info["maxmem_kb"] < 0:
info["maxmem_kb"] = XendNode.instance() \
.physinfo_dict()['total_memory'] * 1024
#manually update ssidref / security fields
if security.on() and info.has_key('ssidref'):
if (info['ssidref'] != 0) and self.info.has_key('security'):
@@ -2249,8 +2286,6 @@ class XendDomainInfo:
@return: uuid of the device
"""
xenapi_vbd['image'] = vdi_image_path
log.debug('create_vbd: %s' % xenapi_vbd)
dev_uuid = ''
if vdi_image_path.startswith('tap'):
dev_uuid = self.info.device_add('tap', cfg_xenapi = xenapi_vbd)
else:
@@ -2260,16 +2295,25 @@ class XendDomainInfo:
raise XendError('Failed to create device')
if self.state == XEN_API_VM_POWER_STATE_RUNNING:
_, config = self.info['devices'][dev_uuid]
dev_control = None
if vdi_image_path.startswith('tap'):
dev_control = self.getDeviceController('tap')
dev_control = self.getDeviceController('tap')
else:
dev_control = self.getDeviceController('vbd')
config['devid'] = dev_control.createDevice(config)
try:
devid = dev_control.createDevice(config)
dev_control.waitForDevice(devid)
self.info.device_update(dev_uuid,
cfg_xenapi = {'devid': devid})
except Exception, exn:
log.exception(exn)
del self.info['devices'][dev_uuid]
self.info['vbd_refs'].remove(dev_uuid)
raise
return dev_uuid
def create_phantom_vbd_with_vdi(self, xenapi_vbd, vdi_image_path):
@@ -2303,9 +2347,21 @@ class XendDomainInfo:
raise XendError('Failed to create device')
if self.state == XEN_API_VM_POWER_STATE_RUNNING:
_, config = self.info['devices'][dev_uuid]
config['devid'] = self.getDeviceController('vif').createDevice(config)
_, config = self.info['devices'][dev_uuid]
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__
+12
View File
@@ -59,6 +59,18 @@ if 'TRACE' not in logging.__dict__:
return filename, frame[2]
logging.Logger.findCaller = findCaller
# Work around a bug in Python's inspect module: findsource is supposed to
# raise IOError if it fails, with other functions in that module coping
# with that, but some people are seeing IndexError raised from there.
if hasattr(inspect, 'findsource'):
real_findsource = getattr(inspect, 'findsource')
def findsource(*args, **kwargs):
try:
return real_findsource(*args, **kwargs)
except IndexError, exn:
raise IOError(exn)
inspect.findsource = findsource
log = logging.getLogger("xend")
+2 -1
View File
@@ -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
+16 -11
View File
@@ -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']
+118
View File
@@ -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>
+57 -26
View File
@@ -28,12 +28,13 @@ import time
import xmlrpclib
from xen.xend import sxp
from xen.xend import PrettyPrint
from xen.xend import PrettyPrint as SXPPrettyPrint
from xen.xend import osdep
import xen.xend.XendClient
from xen.xend.XendBootloader import bootloader
from xen.util import blkif
from xen.util import security
from xen.xm.main import serverType, SERVER_XEN_API, get_single_vm
from xen.xm.opts import *
@@ -98,6 +99,11 @@ gopts.opt('dryrun', short='n',
use="Dry run - prints the resulting configuration in SXP but "
"does not create the domain.")
gopts.opt('xmldryrun', short='x',
fn=set_true, default=0,
use="XML dry run - prints the resulting configuration in XML but "
"does not create the domain.")
gopts.opt('paused', short='p',
fn=set_true, default=0,
use='Leave the domain paused after it is created.')
@@ -1241,34 +1247,59 @@ def main(argv):
except IOError, exn:
raise OptionError("Cannot read file %s: %s" % (config, exn[1]))
if serverType == SERVER_XEN_API:
from xen.xm.xenapi_create import sxp2xml
sxp2xml_inst = sxp2xml()
doc = sxp2xml_inst.convert_sxp_to_xml(config, transient=True)
if opts.vals.dryrun:
PrettyPrint.prettyprint(config)
SXPPrettyPrint.prettyprint(config)
if opts.vals.xmldryrun and serverType == SERVER_XEN_API:
from xml.dom.ext import PrettyPrint as XMLPrettyPrint
XMLPrettyPrint(doc)
if opts.vals.dryrun or opts.vals.xmldryrun:
return
if opts.vals.console_autoconnect:
do_console(sxp.child_value(config, 'name', -1))
if serverType == SERVER_XEN_API:
from xen.xm.xenapi_create import xenapi_create
xenapi_create_inst = xenapi_create()
vm_refs = xenapi_create_inst.create(document = doc)
map(lambda vm_ref: server.xenapi.VM.start(vm_ref, 0), vm_refs)
else:
if not create_security_check(config):
raise security.ACMError('Security Configuration prevents domain from starting')
else:
if opts.vals.console_autoconnect:
cpid = os.fork()
if cpid != 0:
for i in range(10):
# Catch failure of the create process
time.sleep(1)
(p, rv) = os.waitpid(cpid, os.WNOHANG)
if os.WIFEXITED(rv):
if os.WEXITSTATUS(rv) != 0:
sys.exit(os.WEXITSTATUS(rv))
try:
# Acquire the console of the created dom
name = sxp.child_value(config, 'name', -1)
dom = server.xend.domain(name)
domid = int(sxp.child_value(dom, 'domid', '-1'))
console.execConsole(domid)
except:
pass
print("Could not start console\n");
sys.exit(0)
dom = make_domain(opts, config)
raise security.ACMError(
'Security Configuration prevents domain from starting')
dom = make_domain(opts, config)
def do_console(domain_name):
cpid = os.fork()
if cpid != 0:
for i in range(10):
# Catch failure of the create process
time.sleep(1)
(p, rv) = os.waitpid(cpid, os.WNOHANG)
if os.WIFEXITED(rv):
if os.WEXITSTATUS(rv) != 0:
sys.exit(os.WEXITSTATUS(rv))
try:
# Acquire the console of the created dom
if serverType == SERVER_XEN_API:
domid = server.xenapi.VM.get_domid(
get_single_vm(domain_name))
else:
dom = server.xend.domain(domain_name)
domid = int(sxp.child_value(dom, 'domid', '-1'))
console.execConsole(domid)
except:
pass
print("Could not start console\n");
sys.exit(0)
if __name__ == '__main__':
main(sys.argv)
+298 -66
View File
@@ -33,11 +33,11 @@ import getopt
import socket
import traceback
import xmlrpclib
import traceback
import time
import datetime
from select import select
import xml.dom.minidom
from xen.util.blkif import blkdev_name_to_number
import warnings
warnings.filterwarnings('ignore', category=FutureWarning)
@@ -49,18 +49,19 @@ from xen.xend.XendConstants import *
from xen.xm.opts import OptionError, Opts, wrap, set_true
from xen.xm import console
from xen.util import security
from xen.util.xmlrpclib2 import ServerProxy
import XenAPI
# getopt.gnu_getopt is better, but only exists in Python 2.3+. Use
# getopt.getopt if gnu_getopt is not available. This will mean that options
# may only be specified before positional arguments.
if not hasattr(getopt, 'gnu_getopt'):
getopt.gnu_getopt = getopt.getopt
XM_CONFIG_FILE = '/etc/xen/xm-config.xml'
XM_CONFIG_FILE_ENVVAR = 'XM_CONFIG_FILE'
XM_CONFIG_FILE_DEFAULT = '/etc/xen/xm-config.xml'
# Supported types of server
SERVER_LEGACY_XMLRPC = 'LegacyXMLRPC'
@@ -351,13 +352,14 @@ all_commands = (domain_commands + host_commands + scheduler_commands +
# Configuration File Parsing
##
xmConfigFile = os.getenv(XM_CONFIG_FILE_ENVVAR, XM_CONFIG_FILE_DEFAULT)
config = None
if os.path.isfile(XM_CONFIG_FILE):
if os.path.isfile(xmConfigFile):
try:
config = xml.dom.minidom.parse(XM_CONFIG_FILE)
config = xml.dom.minidom.parse(xmConfigFile)
except:
print >>sys.stderr, ('Ignoring invalid configuration file %s.' %
XM_CONFIG_FILE)
xmConfigFile)
def parseServer():
if config:
@@ -491,6 +493,18 @@ def usage(cmd = None):
#
####################################################################
def get_default_SR():
return [sr_ref
for sr_ref in server.xenapi.SR.get_all()
if server.xenapi.SR.get_type(sr_ref) == "local"][0]
def get_default_Network():
return [network_ref
for network_ref in server.xenapi.network.get_all()][0]
def map2sxp(m):
return [[k, m[k]] for k in m.keys()]
def arg_check(args, name, lo, hi = -1):
n = len([i for i in args if i != '--'])
@@ -673,10 +687,41 @@ def xm_restore(args):
def getDomains(domain_names, state, full = 0):
if domain_names:
return [server.xend.domain(dom, full) for dom in domain_names]
if serverType == SERVER_XEN_API:
doms_sxp = []
doms_dict = []
dom_refs = server.xenapi.VM.get_all()
for dom_ref in dom_refs:
dom_rec = server.xenapi.VM.get_record(dom_ref)
dom_metrics_ref = server.xenapi.VM.get_metrics(dom_ref)
dom_metrics = server.xenapi.VM_metrics.get_record(dom_metrics_ref)
dom_rec.update({'name': dom_rec['name_label'],
'memory_actual': int(dom_metrics['memory_actual'])/1024,
'vcpus': dom_metrics['vcpus_number'],
'state': '-----',
'cpu_time': dom_metrics['vcpus_utilisation']})
doms_sxp.append(['domain'] + map2sxp(dom_rec))
doms_dict.append(dom_rec)
if domain_names:
doms = [['domain'] + map2sxp(dom) for dom in doms_dict
if dom["name"] in domain_names]
if len(doms) > 0:
return doms
else:
print "Error: no domain%s named %s" % \
(len(domain_names) > 1 and 's' or '',
', '.join(domain_names))
sys.exit(-1)
else:
return doms_sxp
else:
return server.xend.domains_with_state(True, state, full)
if domain_names:
return [server.xend.domain(dom, full) for dom in domain_names]
else:
return server.xend.domains_with_state(True, state, full)
def xm_list(args):
@@ -735,20 +780,39 @@ def parse_doms_info(info):
else:
up_time = time.time() - start_time
return {
parsed_info = {
'domid' : get_info('domid', str, ''),
'name' : get_info('name', str, '??'),
'mem' : get_info('memory_dynamic_min', int, 0),
'state' : get_info('state', str, ''),
'cpu_time' : get_info('cpu_time', float, 0.0),
# VCPUs is the number online when the VM is up, or the number
# configured otherwise.
'vcpus' : get_info('online_vcpus', int,
get_info('vcpus', int, 0)),
'up_time' : up_time,
'seclabel' : security.get_security_printlabel(info),
'up_time' : up_time
}
# We're not supporting security stuff just yet via XenAPI
if serverType != SERVER_XEN_API:
from xen.util import security
parsed_info['seclabel'] = security.get_security_printlabel(info)
else:
parsed_info['seclabel'] = ""
if serverType == SERVER_XEN_API:
parsed_info['mem'] = get_info('memory_actual', int, 0) / 1024
cpu_times = get_info('cpu_time', lambda x : (x), 0.0)
if sum(cpu_times.values()) > 0:
parsed_info['cpu_time'] = sum(cpu_times.values()) / float(len(cpu_times.values()))
else:
parsed_info['cpu_time'] = 0
else:
parsed_info['mem'] = get_info('memory', int,0)
parsed_info['cpu_time'] = get_info('cpu_time', float, 0.0)
return parsed_info
def check_sched_type(sched):
if serverType == SERVER_XEN_API:
current = server.xenapi.host.get_sched_policy(server.xenapi.session.get_this_host())
@@ -797,17 +861,22 @@ def xm_label_list(doms):
output = []
format = '%(name)-32s %(domid)3s %(mem)5d %(vcpus)5d %(state)10s ' \
'%(cpu_time)8.1f %(seclabel)9s'
for dom in doms:
d = parse_doms_info(dom)
if security.active_policy not in ['INACTIVE', 'NULL', 'DEFAULT']:
if not d['seclabel']:
d['seclabel'] = 'ERROR'
elif security.active_policy in ['DEFAULT']:
d['seclabel'] = 'DEFAULT'
else:
d['seclabel'] = 'INACTIVE'
output.append((format % d, d['seclabel']))
if serverType != SERVER_XEN_API:
from xen.util import security
for dom in doms:
d = parse_doms_info(dom)
if security.active_policy not in ['INACTIVE', 'NULL', 'DEFAULT']:
if not d['seclabel']:
d['seclabel'] = 'ERROR'
elif security.active_policy in ['DEFAULT']:
d['seclabel'] = 'DEFAULT'
else:
d['seclabel'] = 'INACTIVE'
output.append((format % d, d['seclabel']))
#sort by labels
output.sort(lambda x,y: cmp( x[1].lower(), y[1].lower()))
@@ -816,7 +885,6 @@ def xm_label_list(doms):
def xm_vcpu_list(args):
if args:
dominfo = map(server.xend.domain.getVCPUInfo, args)
else:
@@ -1112,7 +1180,7 @@ def xm_mem_set(args):
dom = args[0]
if serverType == SERVER_XEN_API:
mem_target = int_unit(args[1], 'k') * 1024
mem_target = int_unit(args[1], 'm') * 1024 * 1024
server.xenapi.VM.set_memory_dynamic_max(get_single_vm(dom), mem_target)
server.xenapi.VM.set_memory_dynamic_min(get_single_vm(dom), mem_target)
else:
@@ -1464,7 +1532,10 @@ def xm_sysrq(args):
arg_check(args, "sysrq", 2)
dom = args[0]
req = args[1]
server.xend.domain.send_sysrq(dom, req)
if serverType == SERVER_XEN_API:
server.xenapi.VM.send_sysrq(get_single_vm(dom), req)
else:
server.xend.domain.send_sysrq(dom, req)
def xm_trigger(args):
vcpu = 0
@@ -1474,12 +1545,23 @@ def xm_trigger(args):
trigger = args[1]
if len(args) == 3:
vcpu = int(args[2])
server.xend.domain.send_trigger(dom, trigger, vcpu)
if serverType == SERVER_XEN_API:
server.xenapi.VM.send_trigger(get_single_vm(dom), trigger, vcpu)
else:
server.xend.domain.send_trigger(dom, trigger, vcpu)
def xm_debug_keys(args):
arg_check(args, "debug-keys", 1)
server.xend.node.send_debug_keys(str(args[0]))
keys = str(args[0])
if serverType == SERVER_XEN_API:
server.xenapi.host.send_debug_keys(
server.xenapi.session.get_this_host(),
keys)
else:
server.xend.node.send_debug_keys(keys)
def xm_top(args):
arg_check(args, "top", 0)
@@ -1605,12 +1687,21 @@ def xm_network_list(args):
(use_long, params) = arg_check_for_resource_list(args, "network-list")
dom = params[0]
if use_long:
if serverType == SERVER_XEN_API:
vif_refs = server.xenapi.VM.get_VIFs(get_single_vm(dom))
vif_properties = \
map(server.xenapi.VIF.get_runtime_properties, vif_refs)
devs = map(lambda (handle, properties): [handle, map2sxp(properties)],
zip(range(len(vif_properties)), vif_properties))
else:
devs = server.xend.domain.getDeviceSxprs(dom, 'vif')
if use_long:
map(PrettyPrint.prettyprint, devs)
else:
hdr = 0
for x in server.xend.domain.getDeviceSxprs(dom, 'vif'):
for x in devs:
if hdr == 0:
print 'Idx BE MAC Addr. handle state evt-ch tx-/rx-ring-ref BE-path'
hdr = 1
@@ -1630,12 +1721,25 @@ def xm_block_list(args):
(use_long, params) = arg_check_for_resource_list(args, "block-list")
dom = params[0]
if use_long:
if serverType == SERVER_XEN_API:
vbd_refs = server.xenapi.VM.get_VBDs(get_single_vm(dom))
vbd_properties = \
map(server.xenapi.VBD.get_runtime_properties, vbd_refs)
vbd_devs = \
map(server.xenapi.VBD.get_device, vbd_refs)
vbd_devids = \
map(blkdev_name_to_number, vbd_devs)
devs = map(lambda (devid, prop): [devid, map2sxp(prop)],
zip(vbd_devids, vbd_properties))
else:
devs = server.xend.domain.getDeviceSxprs(dom, 'vbd')
if use_long:
map(PrettyPrint.prettyprint, devs)
else:
hdr = 0
for x in server.xend.domain.getDeviceSxprs(dom, 'vbd'):
for x in devs:
if hdr == 0:
print 'Vdev BE handle state evt-ch ring-ref BE-path'
hdr = 1
@@ -1690,13 +1794,17 @@ def parse_block_configuration(args):
if len(args) == 5:
vbd.append(['backend', args[4]])
# verify that policy permits attaching this resource
if security.on():
dominfo = server.xend.domain(dom)
label = security.get_security_printlabel(dominfo)
else:
label = None
security.res_security_check(args[1], label)
if serverType != SERVER_XEN_API:
# verify that policy permits attaching this resource
from xen.util import security
if security.on():
dominfo = server.xend.domain(dom)
label = security.get_security_printlabel(dominfo)
else:
label = None
security.res_security_check(args[1], label)
return (dom, vbd)
@@ -1704,8 +1812,45 @@ def parse_block_configuration(args):
def xm_block_attach(args):
arg_check(args, 'block-attach', 4, 5)
(dom, vbd) = parse_block_configuration(args)
server.xend.domain.device_create(dom, vbd)
if serverType == SERVER_XEN_API:
dom = args[0]
uname = args[1]
dev = args[2]
mode = args[3]
# First create new VDI
vdi_record = {
"name_label": "vdi" + str(uname.__hash__()),
"name_description": "",
"SR": get_default_SR(),
"virtual_size": 0,
"sector_size": 512,
"type": "system",
"sharable": False,
"read_only": mode!="w",
"other_config": {"location": uname}
}
vdi_ref = server.xenapi.VDI.create(vdi_record)
# Now create new VBD
vbd_record = {
"VM": get_single_vm(dom),
"VDI": vdi_ref,
"device": dev,
"bootable": True,
"mode": mode=="w" and "RW" or "RO",
"type": "Disk",
"qos_algorithm_type": "",
"qos_algorithm_params": {}
}
server.xenapi.VBD.create(vbd_record)
else:
(dom, vbd) = parse_block_configuration(args)
server.xend.domain.device_create(dom, vbd)
def xm_block_configure(args):
@@ -1723,15 +1868,65 @@ def xm_network_attach(args):
vif_params = ['type', 'mac', 'bridge', 'ip', 'script', \
'backend', 'vifname', 'rate', 'model']
for a in args[1:]:
vif_param = a.split("=")
if len(vif_param) != 2 or vif_param[1] == '' or \
vif_param[0] not in vif_params:
err("Invalid argument: %s" % a)
usage('network-attach')
vif.append(vif_param)
if serverType == SERVER_XEN_API:
vif_record = {
"device": "eth0",
"network": get_default_Network(),
"VM": get_single_vm(dom),
"MAC": "",
"MTU": "",
"qos_algorithm_type": "",
"qos_algorithm_params": {},
"other_config": {}
}
server.xend.domain.device_create(dom, vif)
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@lists.xensource.com"
raise
except Exception, e:
if serverType != SERVER_XEN_API:
from xen.util import security
if isinstance(e, security.ACMError):
err(str(e))
return False, 1
else:
print "Unexpected error:", sys.exc_info()[0]
print
print "Please report to xen-devel@lists.xensource.com"
raise
return False, 1
+12 -1
View File
@@ -22,6 +22,9 @@ from xen.xend import PrettyPrint
from xen.xend import sxp
from xen.xend import XendClient
from xen.xm.main import serverType, SERVER_XEN_API
from xen.xm.xenapi_create import *
from opts import *
from create import *
@@ -65,7 +68,15 @@ def main(argv):
if opts.vals.dryrun:
PrettyPrint.prettyprint(config)
else:
return
if serverType == SERVER_XEN_API:
sxp2xml_inst = sxp2xml()
doc = sxp2xml_inst.convert_sxp_to_xml(config)
xenapi_create_inst = xenapi_create()
vm_refs = xenapi_create_inst.create(document = doc)
else:
make_unstarted_domain(opts, config)
if __name__ == '__main__':
+13 -13
View File
@@ -51,7 +51,7 @@ gopts.opt('reboot', short='R',
def wait_reboot(opts, doms, rcs):
if serverType == SERVER_XEN_API:
opts.err("Cannot wait for reboot w/ XenAPI (yet)")
opts.err("Cannot wait for reboot w/ XenAPI (yet)")
while doms:
alive = server.xend.domains(0)
@@ -73,7 +73,7 @@ def wait_reboot(opts, doms, rcs):
def wait_shutdown(opts, doms):
while doms:
if serverType == SERVER_XEN_API:
alive = [dom for dom in server.xenapi.VM.get_all()
alive = [dom for dom in server.xenapi.VM.get_all()
if server.xenapi.VM.get_power_state(dom) ==
XEN_API_VM_POWER_STATE[XEN_API_VM_POWER_STATE_RUNNING]]
else:
@@ -91,16 +91,16 @@ def wait_shutdown(opts, doms):
def shutdown(opts, doms, mode, wait):
rcs = {}
for d in doms:
if serverType == SERVER_XEN_API:
if mode == 'halt':
server.xenapi.VM.clean_shutdown(d)
if mode == 'reboot':
server.xenapi.VM.clean_reboot(d)
if mode == 'poweroff':
server.xenapi.VM.clean_shutdown(d)
else:
rcs[d] = server.xend.domain.getRestartCount(d)
server.xend.domain.shutdown(d, mode)
if serverType == SERVER_XEN_API:
if mode == 'halt':
server.xenapi.VM.clean_shutdown(d)
if mode == 'reboot':
server.xenapi.VM.clean_reboot(d)
if mode == 'poweroff':
server.xenapi.VM.clean_shutdown(d)
else:
rcs[d] = server.xend.domain.getRestartCount(d)
server.xend.domain.shutdown(d, mode)
if wait:
if mode == 'reboot':
@@ -135,7 +135,7 @@ def main_dom(opts, args):
if len(args) > 1: opts.err('No multiple domain parameters allowed')
dom = args[0]
if serverType == SERVER_XEN_API:
dom = get_single_vm(dom)
dom = get_single_vm(dom)
mode = shutdown_mode(opts)
shutdown(opts, [ dom ], mode, opts.vals.wait)
+636
View File
@@ -0,0 +1,636 @@
#!/usr/bin/python
#============================================================================
# This library is free software; you can redistribute it and/or
# modify it under the terms of version 2.1 of the GNU Lesser General Public
# License as published by the Free Software Foundation.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#============================================================================
# Copyright (C) 2007 Tom Wilkie <tom.wilkie@gmail.com>
#============================================================================
"""Domain creation using new XenAPI
"""
from xen.xm.main import server, get_default_SR
from xml.dom.minidom import parse, getDOMImplementation
from xml.dom.ext import PrettyPrint
from xml.parsers.xmlproc import xmlproc, xmlval, xmldtd
from xen.xend import sxp
from xen.xend.XendAPIConstants import XEN_API_ON_NORMAL_EXIT, \
XEN_API_ON_CRASH_BEHAVIOUR
import sys
import os
import traceback
def log(_, msg):
#print "> " + msg
pass
DEBUG = 0
def get_name_label(node):
name_node = node.getElementsByTagName("name")[0]
label_node = name_node.getElementsByTagName("label")[0]
return " ".join([child.nodeValue for child in label_node.childNodes])
def get_name_description(node):
name_node = node.getElementsByTagName("name")[0]
description_node = name_node.getElementsByTagName("description")[0]
return " ".join([child.nodeValue for child in description_node.childNodes])
def get_text_in_child_node(node, child):
tag_node = node.getElementsByTagName(child)[0]
return tag_node.nodeValue
def get_child_node_attribute(node, child, attribute):
tag_node = node.getElementsByTagName(child)[0]
return tag_node.attributes[attribute].value
def get_child_nodes_as_dict(node, child_name,
key_attribute_name,
value_attribute_name):
return dict([(child.attributes[key_attribute_name].value,
child.attributes[value_attribute_name].value)
for child in node.getElementsByTagName(child_name)])
def try_quietly(fn, *args):
try:
return fn(*args)
except:
return None
class xenapi_create:
def __init__(self):
self.DEFAULT_STORAGE_REPOSITORY = get_default_SR()
self.dtd = "/usr/lib/python/xen/xm/create.dtd"
def create(self, filename=None, document=None):
"""
Create a domain from an XML file or DOM tree
"""
if filename is not None:
self.check_dtd(file)
document = parse(file)
elif document is not None:
self.check_dom_against_dtd(document)
self.check_doc(document)
vdis = document.getElementsByTagName("vdi")
vdi_refs_dict = self.create_vdis(vdis)
try:
vms = document.getElementsByTagName("vm")
return self.create_vms(vms, vdi_refs_dict)
except Exception, exn:
try_quietly(self.cleanup_vdis(vdi_refs_dict))
raise exn
# Methods to check xml file
# try to use dtd to check where possible
def check_dtd(self, file):
"""
Check file against DTD.
Use this if possible as it gives nice
error messages
"""
dtd = xmldtd.load_dtd(self.dtd)
parser = xmlproc.XMLProcessor()
parser.set_application(xmlval.ValidatingApp(dtd, parser))
parser.dtd = dtd
parser.ent = dtd
parser.parse_resource(file)
def check_dom_against_dtd(self, dom):
"""
Check DOM again DTD.
Doesn't give as nice error messages.
(no location info)
"""
dtd = xmldtd.load_dtd(self.dtd)
app = xmlval.ValidatingApp(dtd, self)
app.set_locator(self)
self.dom2sax(dom, app)
# Get errors back from ValidatingApp
def report_error(self, number, args=None):
self.errors = xmlproc.errors.english
try:
msg = self.errors[number]
if args != None:
msg = msg % args
except KeyError:
msg = self.errors[4002] % number # Unknown err msg :-)
print msg
sys.exit(-1)
# Here for compatibility with ValidatingApp
def get_line(self):
return -1
def get_column(self):
return -1
def dom2sax(self, dom, app):
"""
Take a dom tree and tarverse it,
issuing SAX calls to app.
"""
for child in dom.childNodes:
if child.nodeType == child.TEXT_NODE:
data = child.nodeValue
app.handle_data(data, 0, len(data))
else:
app.handle_start_tag(
child.nodeName,
self.attrs_to_dict(child.attributes))
self.dom2sax(child, app)
app.handle_end_tag(child.nodeName)
def attrs_to_dict(self, attrs):
return dict(attrs.items())
#
# Checks which cannot be done with dtd
#
def check_doc(self, doc):
vms = doc.getElementsByTagName("vm")
self.check_vms(vms)
def check_vms(self, vms):
map(self.check_vm, vms)
def check_vm(self, vm):
vifs = vm.getElementsByTagName("vif")
self.check_vifs(vifs)
def check_vifs(self, vifs):
map(self.check_vif, vifs)
def check_vif(self, vif):
"""
Check that the vif has
either a bridge or network
name but not both
"""
if "bridge" in vif.attributes.keys() \
and "network" in vif.attributes.keys():
raise "You cannot specify both a bridge and\
a network name."
# Cleanup methods here
def cleanup_vdis(self, vdi_refs_dict):
map(self.cleanup_vdi, vdi_refs_dict.values())
def cleanup_vdi(self, vdi_ref):
server.xenapi.VDI.destroy(vdi_ref)
def cleanup_vms(self, vm_refs):
map(self.cleanup_vm, vm_refs)
def cleanup_vm(self, vm_ref):
server.xenapi.VM.destroy(vm_ref)
# Create methods here
def create_vdis(self, vdis):
log(DEBUG, "create_vdis")
return dict(map(self.create_vdi, vdis))
def create_vdi(self, vdi):
log(DEBUG, "create_vdi")
vdi_record = {
"name_label": get_name_label(vdi),
"name_description": get_name_description(vdi),
"SR": self.DEFAULT_STORAGE_REPOSITORY,
"virtual_size": vdi.attributes["size"].value,
"type": vdi.attributes["type"].value,
"shareable": vdi.attributes["shareable"].value,
"read_only": vdi.attributes["read_only"].value,
"other_config": {"location":
vdi.attributes["src"].value}
}
key = vdi.attributes["name"].value
value = server.xenapi.VDI.create(vdi_record)
return (key, value)
def create_vms(self, vms, vdis):
log(DEBUG, "create_vms")
return map(lambda vm: self.create_vm(vm, vdis), vms)
def create_vm(self, vm, vdis):
log(DEBUG, "create_vm")
vm_record = {
"name_label":
get_name_label(vm),
"name_description":
get_name_description(vm),
"user_version":
get_text_in_child_node(vm, "version"),
"is_a_template":
vm.attributes["is_a_template"].value,
"auto_power_on":
vm.attributes["auto_power_on"].value,
"memory_static_max":
get_child_node_attribute(vm, "memory", "static_max"),
"memory_static_min":
get_child_node_attribute(vm, "memory", "static_min"),
"memory_dynamic_max":
get_child_node_attribute(vm, "memory", "dynamic_max"),
"memory_dynamic_min":
get_child_node_attribute(vm, "memory", "dynamic_min"),
"vcpus_params":
get_child_nodes_as_dict(vm, "vcpu_param", "key", "value"),
"vcpus_max":
vm.attributes["vcpus_max"].value,
"vcpus_at_startup":
vm.attributes["vcpus_at_startup"].value,
"actions_after_shutdown":
vm.attributes["actions_after_shutdown"].value,
"actions_after_reboot":
vm.attributes["actions_after_reboot"].value,
"actions_after_crash":
vm.attributes["actions_after_crash"].value,
"platform_std_VGA":
vm.attributes["platform_std_VGA"].value,
"platform_serial":
vm.attributes["platform_serial"].value,
"platform_localtime":
vm.attributes["platform_localtime"].value,
"platform_clock_offet":
vm.attributes["platform_clock_offet"].value,
"platform_enable_audio":
vm.attributes["platform_enable_audio"].value,
"PCI_bus":
vm.attributes["platform_enable_audio"].value,
"other_config":
get_child_nodes_as_dict(vm, "other_config", "key", "value")
}
if len(vm.getElementsByTagName("pv")) > 0:
vm_record.update({
"PV_bootloader":
get_child_node_attribute(vm, "pv", "bootloader"),
"PV_kernel":
get_child_node_attribute(vm, "pv", "kernel"),
"PV_ramdisk":
get_child_node_attribute(vm, "pv", "ramdisk"),
"PV_args":
get_child_node_attribute(vm, "pv", "args"),
"PV_bootloader_args":
get_child_node_attribute(vm, "pv", "bootloader_args")
})
else:
hvm = vm.getElementsByTagName("hvm")[0]
vm_record.update({
"HVM_boot_policy":
get_child_node_attribute(vm, "hvm", "boot_policy"),
"HVM_boot_params":
get_child_nodes_as_dict(hvm, "boot_params", "key", "value")
})
try:
vm_ref = server.xenapi.VM.create(vm_record)
except:
traceback.print_exc()
sys.exit(-1)
# Now create vbds
vbds = vm.getElementsByTagName("vbd")
self.create_vbds(vm_ref, vbds, vdis)
# Now create vifs
vifs = vm.getElementsByTagName("vif")
self.create_vifs(vm_ref, vifs)
return vm_ref
def create_vbds(self, vm_ref, vbds, vdis):
log(DEBUG, "create_vbds")
return map(lambda vbd: self.create_vbd(vm_ref, vbd, vdis), vbds)
def create_vbd(self, vm_ref, vbd, vdis):
log(DEBUG, "create_vbd")
vbd_record = {
"VM":
vm_ref,
"VDI":
vdis[vbd.attributes["vdi"].value],
"device":
vbd.attributes["device"].value,
"bootable":
vbd.attributes["bootable"].value,
"mode":
vbd.attributes["mode"].value,
"type":
vbd.attributes["type"].value,
"qos_algorithm_type":
vbd.attributes["qos_algorithm_type"].value,
"qos_algorithm_params":
get_child_nodes_as_dict(vbd,
"qos_algorithm_param", "key", "value")
}
return server.xenapi.VBD.create(vbd_record)
def create_vifs(self, vm_ref, vifs):
log(DEBUG, "create_vifs")
return map(lambda vif: self.create_vif(vm_ref, vif), vifs)
def create_vif(self, vm_ref, vif):
log(DEBUG, "create_vif")
if "bridge" in vif.attributes.keys():
raise "Not allowed to add by bridge just yet"
elif "network" in vif.attributes.keys():
network = [network_ref
for network_ref in server.xenapi.network.get_all()
if server.xenapi.network.get_name_label(network_ref)
== vif.attributes["network"].value][0]
else:
network = self._get_network_ref()
vif_record = {
"device":
vif.attributes["device"].value,
"network":
network,
"VM":
vm_ref,
"MAC":
vif.attributes["mac"].value,
"MTU":
vif.attributes["mtu"].value,
"qos_algorithm_type":
vif.attributes["qos_algorithm_type"].value,
"qos_algorithm_params":
get_child_nodes_as_dict(vif,
"qos_algorithm_param", "key", "value")
}
return server.xenapi.VIF.create(vif_record)
_network_refs = []
def _get_network_ref(self):
try:
return self._network_refs.pop(0)
except IndexError:
self._network_refs = server.xenapi.network.get_all()
return self._network_refs.pop(0)
def get_child_by_name(exp, childname, default = None):
try:
return [child for child in sxp.children(exp)
if child[0] == childname][0][1]
except:
return default
# Convert old sxp into new xml
class sxp2xml:
def convert_sxp_to_xml(self, config, transient=False):
devices = [child for child in sxp.children(config)
if len(child) > 0 and child[0] == "device"]
vbds_sxp = map(lambda x: x[1], [device for device in devices
if device[1][0] == "vbd"])
vifs_sxp = map(lambda x: x[1], [device for device in devices
if device[1][0] == "vif"])
# Create XML Document
impl = getDOMImplementation()
document = impl.createDocument(None, "xm", None)
# Lets make the VM tag..
vm = document.createElement("vm")
# Some string compatibility
actions_after_shutdown \
= get_child_by_name(config, "on_poweroff", "destroy")
actions_after_reboot \
= get_child_by_name(config, "on_reboot", "restart")
actions_after_crash \
= get_child_by_name(config, "on_crash", "restart")
def conv_chk(val, vals):
val.replace("-", "_")
if val not in vals:
raise "Invalid value: " + val
else:
return val
actions_after_shutdown = conv_chk(actions_after_shutdown,\
XEN_API_ON_NORMAL_EXIT)
actions_after_reboot = conv_chk(actions_after_reboot, \
XEN_API_ON_NORMAL_EXIT)
actions_after_crash = conv_chk(actions_after_crash, \
XEN_API_ON_CRASH_BEHAVIOUR)
# Flesh out tag attributes
vm.attributes["is_a_template"] = "false"
vm.attributes["auto_power_on"] = "false"
vm.attributes["actions_after_shutdown"] \
= actions_after_shutdown
vm.attributes["actions_after_reboot"] \
= actions_after_reboot
vm.attributes["actions_after_crash"] \
= actions_after_crash
vm.attributes["platform_std_VGA"] = "false"
vm.attributes["platform_serial"] = ""
vm.attributes["platform_localtime"] = ""
vm.attributes["platform_clock_offet"] = ""
vm.attributes["platform_enable_audio"] = ""
vm.attributes["PCI_bus"] = ""
vm.attributes["vcpus_max"] \
= str(get_child_by_name(config, "vcpus", 1))
vm.attributes["vcpus_at_startup"] \
= str(get_child_by_name(config, "vcpus", 1))
# Make the name tag
vm.appendChild(self.make_name_tag(
get_child_by_name(config, "name"), document))
# Make version tag
version = document.createElement("version")
version.appendChild(document.createTextNode("1.0"))
vm.appendChild(version)
# Make pv or hvm tag
image = get_child_by_name(config, "image")
if image[0] == "linux":
pv = document.createElement("pv")
pv.attributes["kernel"] \
= get_child_by_name(image, "kernel", "")
pv.attributes["bootloader"] = ""
pv.attributes["ramdisk"] \
= get_child_by_name(image, "ramdisk", "")
pv.attributes["args"] \
= "root=" + get_child_by_name(image, "root", "") \
+ " " + get_child_by_name(image, "args", "")
pv.attributes["bootloader_args"] = ""
vm.appendChild(pv)
elif image[0] == "hvm":
hvm = document.createElement("hvm")
hvm.attributes["boot_policy"] = ""
vm.appendChild(hvm)
# Make memory tag
memory = document.createElement("memory")
memory_str = str(int(
get_child_by_name(config, "memory"))*1024*1024)
memory.attributes["static_min"] = str(0)
memory.attributes["static_max"] = memory_str
memory.attributes["dynamic_min"] = memory_str
memory.attributes["dynamic_max"] = memory_str
if get_child_by_name(config, "maxmem"):
memory.attributes["static_max"] = \
str(int(get_child_by_name(config, "maxmem")*1024*1024))
vm.appendChild(memory)
# And now the vbds
vbds = map(lambda vbd: self.extract_vbd(vbd, document), vbds_sxp)
map(vm.appendChild, vbds)
# And now the vifs
vifs = map(lambda vif: self.extract_vif(vif, document), vifs_sxp)
map(vm.appendChild, vifs)
# transient?
if transient:
other_config = document.createElement("other_config")
other_config.attributes["key"] = "transient"
other_config.attributes["value"] = "True"
vm.appendChild(other_config)
# Add it to doc_root
document.documentElement.appendChild(vm)
# We want to pull out vdis
vdis = map(lambda vdb: self.extract_vdi(vdb, document), vbds_sxp)
map(document.documentElement.appendChild, vdis)
return document
def make_name_tag(self, label_text, document):
name = document.createElement("name")
label = document.createElement("label")
label.appendChild(document.createTextNode(str(label_text)))
name.appendChild(label)
description = document.createElement("description")
description.appendChild(document.createTextNode(" "))
name.appendChild(description)
return name
def extract_vbd(self, vbd_sxp, document):
src = get_child_by_name(vbd_sxp, "uname")
name = str(src.__hash__())
vbd = document.createElement("vbd")
vbd.attributes["name"] = "vdb" + name
vbd.attributes["vdi"] = "vdi" + name
vbd.attributes["mode"] \
= get_child_by_name(vbd_sxp, "mode") != "w" \
and "RO" or "RW"
vbd.attributes["device"] \
= get_child_by_name(vbd_sxp, "dev")
vbd.attributes["bootable"] = "1"
vbd.attributes["type"] = "disk"
vbd.attributes["qos_algorithm_type"] = ""
return vbd
def extract_vdi(self, vbd_sxp, document):
src = get_child_by_name(vbd_sxp, "uname")
name = "vdi" + str(src.__hash__())
path = src[src.find(":")+1:]
vdi = document.createElement("vdi")
vdi.attributes["src"] = src
vdi.attributes["read_only"] \
= (get_child_by_name(vbd_sxp, "mode") != "w") \
and "true" or "false"
vdi.attributes["size"] \
= str(os.path.getsize(path))
vdi.attributes["type"] = "system"
vdi.attributes["shareable"] = "false"
vdi.attributes["name"] = name
vdi.appendChild(self.make_name_tag(name, document))
return vdi
def extract_vif(self, vif_sxp, document):
vif = document.createElement("vif")
dev = get_child_by_name(vif_sxp, "vifname", "eth0")
vif.attributes["name"] \
= "vif" + str(dev.__hash__())
vif.attributes["mac"] \
= get_child_by_name(vif_sxp, "mac", "")
vif.attributes["mtu"] \
= get_child_by_name(vif_sxp, "mtu", "")
vif.attributes["device"] = dev
vif.attributes["qos_algorithm_type"] = ""
if get_child_by_name(vif_sxp, "bridge") is not None:
vif.attributes["bridge"] \
= get_child_by_name(vif_sxp, "bridge")
return vif
+3 -3
View File
@@ -13,7 +13,7 @@ include $(XEN_ROOT)/tools/Rules.mk
PROGRAMS_INSTALL_DIR = /usr/$(LIBDIR)/xen/bin
INCLUDES += -I $(XEN_LIBXC)
INCLUDES += -I $(XEN_LIBXC) -I $(XEN_XENSTORE)
CFLAGS += -Werror -fno-strict-aliasing
CFLAGS += $(INCLUDES)
@@ -22,9 +22,9 @@ CFLAGS += $(INCLUDES)
CFLAGS += -Wp,-MD,.$(@F).d
PROG_DEP = .*.d
PROGRAMS = xc_restore xc_save readnotes
PROGRAMS = xc_restore xc_save readnotes
LDLIBS = -L$(XEN_LIBXC) -lxenguest -lxenctrl
LDLIBS = -L$(XEN_LIBXC) -L$(XEN_XENSTORE) -lxenguest -lxenctrl -lxenstore
.PHONY: all
all: build
+127 -2
View File
@@ -12,7 +12,13 @@
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <xs.h>
#include <xenctrl.h>
#include <xenguest.h>
@@ -31,6 +37,123 @@ static int suspend(int domid)
!strncmp(ans, "done\n", 5));
}
/* For HVM guests, there are two sources of dirty pages: the Xen shadow
* log-dirty bitmap, which we get with a hypercall, and qemu's version.
* The protocol for getting page-dirtying data from qemu uses a
* double-buffered shared memory interface directly between xc_save and
* qemu-dm.
*
* xc_save calculates the size of the bitmaps and notifies qemu-dm
* through the store that it wants to share the bitmaps. qemu-dm then
* starts filling in the 'active' buffer.
*
* To change the buffers over, xc_save writes the other buffer number to
* the store and waits for qemu to acknowledge that it is now writing to
* the new active buffer. xc_save can then process and clear the old
* active buffer. */
static char *qemu_active_path;
static char *qemu_next_active_path;
static struct xs_handle *xs;
/* Get qemu to change buffers. */
static void qemu_flip_buffer(int domid, int next_active)
{
char digit = '0' + next_active;
unsigned int len;
char *active_str, **watch;
struct timeval tv;
fd_set fdset;
/* Tell qemu that we want it to start writing log-dirty bits to the
* other buffer */
if (!xs_write(xs, XBT_NULL, qemu_next_active_path, &digit, 1)) {
errx(1, "can't write next-active to store path (%s)\n",
qemu_next_active_path);
exit(1);
}
/* Wait a while for qemu to signal that it has switched to the new
* active buffer */
read_again:
tv.tv_sec = 5;
tv.tv_usec = 0;
FD_ZERO(&fdset);
FD_SET(xs_fileno(xs), &fdset);
if ((select(xs_fileno(xs) + 1, &fdset, NULL, NULL, &tv)) != 1) {
errx(1, "timed out waiting for qemu to switch buffers\n");
exit(1);
}
watch = xs_read_watch(xs, &len);
free(watch);
active_str = xs_read(xs, XBT_NULL, qemu_active_path, &len);
if (active_str == NULL || active_str[0] - '0' != next_active)
/* Watch fired but value is not yet right */
goto read_again;
}
static void * init_qemu_maps(int domid, unsigned int bitmap_size)
{
key_t key;
char key_ascii[17] = {0,};
int shmid = -1;
void *seg;
char *path, *p;
/* Make a shared-memory segment */
while (shmid == -1)
{
key = rand(); /* No security, just a sequence of numbers */
shmid = shmget(key, 2 * bitmap_size,
IPC_CREAT|IPC_EXCL|S_IRUSR|S_IWUSR);
if (shmid == -1 && errno != EEXIST)
errx(1, "can't get shmem to talk to qemu-dm");
}
/* Map it into our address space */
seg = shmat(shmid, NULL, 0);
if (seg == (void *) -1)
errx(1, "can't map shmem to talk to qemu-dm");
memset(seg, 0, 2 * bitmap_size);
/* Write the size of it into the first 32 bits */
*(uint32_t *)seg = bitmap_size;
/* Tell qemu about it */
if ((xs = xs_daemon_open()) == NULL)
errx(1, "Couldn't contact xenstore");
if (!(path = xs_get_domain_path(xs, domid)))
errx(1, "can't get domain path in store");
if (!(path = realloc(path, strlen(path)
+ strlen("/logdirty/next-active") + 1)))
errx(1, "no memory for constructing xenstore path");
strcat(path, "/logdirty/");
p = path + strlen(path);
strcpy(p, "key");
snprintf(key_ascii, 17, "%16.16llx", (unsigned long long) key);
if (!xs_write(xs, XBT_NULL, path, key_ascii, 16))
errx(1, "can't write key (%s) to store path (%s)\n", key_ascii, path);
/* Watch for qemu's indication of the active buffer, and request it
* to start writing to buffer 0 */
strcpy(p, "active");
if (!xs_watch(xs, path, "qemu-active-buffer"))
errx(1, "can't set watch in store (%s)\n", path);
if (!(qemu_active_path = strdup(path)))
errx(1, "no memory for copying xenstore path");
strcpy(p, "next-active");
if (!(qemu_next_active_path = strdup(path)))
errx(1, "no memory for copying xenstore path");
qemu_flip_buffer(domid, 0);
free(path);
return seg;
}
int
main(int argc, char **argv)
@@ -52,9 +175,11 @@ main(int argc, char **argv)
flags = atoi(argv[5]);
if (flags & XCFLAGS_HVM)
ret = xc_hvm_save(xc_fd, io_fd, domid, maxit, max_f, flags, &suspend);
ret = xc_hvm_save(xc_fd, io_fd, domid, maxit, max_f, flags,
&suspend, &init_qemu_maps, &qemu_flip_buffer);
else
ret = xc_linux_save(xc_fd, io_fd, domid, maxit, max_f, flags, &suspend);
ret = xc_linux_save(xc_fd, io_fd, domid, maxit, max_f, flags,
&suspend);
xc_interface_close(xc_fd);
@@ -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:
@@ -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:
@@ -12,6 +12,18 @@ def count_eth(console):
FAIL(str(e))
return len(run['output'].splitlines())
def get_state(domain_name, number):
s, o = traceCommand("xm network-list %s | awk '/^%d/ {print $5}'" %
(domain_name, number))
print o
if s != 0:
FAIL("network-list failed")
if o == "":
return 0
else:
return int(o)
def network_attach(domain_name, console):
eths_before = count_eth(console)
status, output = traceCommand("xm network-attach %s" % domain_name)
@@ -30,6 +42,13 @@ def network_detach(domain_name, console, num=0):
if status != 0:
return -1, "xm network-detach returned invalid %i != 0" % status
for i in range(10):
if get_state(domain_name, num) == 0:
break
time.sleep(1)
else:
FAIL("network-detach failed: device did not disappear")
eths_after = count_eth(console)
if eths_after != (eths_before-1):
return -2, "Network device was not actually disconnected from domU"
@@ -167,7 +167,8 @@ EXPORT_SYMBOL(notify_remote_via_irq);
irqreturn_t evtchn_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
unsigned int l1i, port;
int cpu = smp_processor_id();
/* XXX: All events are bound to vcpu0 but irq may be redirected. */
int cpu = 0; /*smp_processor_id();*/
irqreturn_t(*handler) (int, void *, struct pt_regs *);
shared_info_t *s = shared_info_area;
vcpu_info_t *v = &s->vcpu_info[cpu];
+3 -15
View File
@@ -58,19 +58,7 @@ HDRS += $(wildcard $(BASEDIR)/include/asm-x86/hvm/*.h)
HDRS += $(wildcard $(BASEDIR)/include/asm-x86/hvm/svm/*.h)
HDRS += $(wildcard $(BASEDIR)/include/asm-x86/hvm/vmx/*.h)
# Test for at least GCC v3.2.x.
gcc-ver = $(shell $(CC) -dumpversion | sed -e 's/^\(.\)\.\(.\)\.\(.\)/\$(1)/')
ifeq ($(call gcc-ver,1),1)
$(error gcc-1.x.x unsupported - upgrade to at least gcc-3.2.x)
endif
ifeq ($(call gcc-ver,1),2)
$(error gcc-2.x.x unsupported - upgrade to at least gcc-3.2.x)
endif
ifeq ($(call gcc-ver,1),3)
ifeq ($(call gcc-ver,2),0)
$(error gcc-3.0.x unsupported - upgrade to at least gcc-3.2.x)
endif
ifeq ($(call gcc-ver,2),1)
$(error gcc-3.1.x unsupported - upgrade to at least gcc-3.2.x)
endif
# Require GCC v3.4+ (to avoid issues with alignment constraints in Xen headers)
ifneq ($(call cc-ver,$(CC),0x030400),y)
$(error Xen requires at least gcc-3.4)
endif
+15 -9
View File
@@ -29,6 +29,10 @@
#define S_TO_NS 1000000000ULL /* 1s = 10^9 ns */
#define S_TO_FS 1000000000000000ULL /* 1s = 10^15 fs */
/* Frequency_of_TSC / frequency_of_HPET = 32 */
#define TSC_PER_HPET_TICK 32
#define guest_time_hpet(v) (hvm_get_guest_time(v) / TSC_PER_HPET_TICK)
#define HPET_ID 0x000
#define HPET_PERIOD 0x004
#define HPET_CFG 0x010
@@ -67,7 +71,9 @@
#define HPET_TN_INT_ROUTE_CAP_MASK (0xffffffffULL \
<< HPET_TN_INT_ROUTE_CAP_SHIFT)
#define hpet_tick_to_ns(h, tick) ((s_time_t)(tick)*S_TO_NS/h->tsc_freq)
#define hpet_tick_to_ns(h, tick) ((s_time_t)(tick)* \
(S_TO_NS*TSC_PER_HPET_TICK)/h->tsc_freq)
#define timer_config(h, n) (h->hpet.timers[n].config)
#define timer_enabled(h, n) (timer_config(h, n) & HPET_TN_ENABLE)
#define timer_is_periodic(h, n) (timer_config(h, n) & HPET_TN_PERIODIC)
@@ -108,7 +114,7 @@ static inline int hpet_check_access_length(
static inline uint64_t hpet_read_maincounter(HPETState *h)
{
if ( hpet_enabled(h) )
return hvm_get_guest_time(h->vcpu) + h->mc_offset;
return guest_time_hpet(h->vcpu) + h->mc_offset;
else
return h->hpet.mc64;
}
@@ -144,7 +150,7 @@ static void hpet_stop_timer(HPETState *h, unsigned int tn)
/* the number of HPET tick that stands for
* 1/(2^10) second, namely, 0.9765625 milliseconds */
#define HPET_TINY_TIME_SPAN (h->tsc_freq >> 10)
#define HPET_TINY_TIME_SPAN ((h->tsc_freq >> 10) / TSC_PER_HPET_TICK)
static void hpet_set_timer(HPETState *h, unsigned int tn)
{
@@ -225,14 +231,14 @@ static void hpet_write(
if ( !(old_val & HPET_CFG_ENABLE) && (new_val & HPET_CFG_ENABLE) )
{
/* Enable main counter and interrupt generation. */
h->mc_offset = h->hpet.mc64 - hvm_get_guest_time(h->vcpu);
h->mc_offset = h->hpet.mc64 - guest_time_hpet(h->vcpu);
for ( i = 0; i < HPET_TIMER_NUM; i++ )
hpet_set_timer(h, i);
}
else if ( (old_val & HPET_CFG_ENABLE) && !(new_val & HPET_CFG_ENABLE) )
{
/* Halt main counter and disable interrupt generation. */
h->hpet.mc64 = h->mc_offset + hvm_get_guest_time(h->vcpu);
h->hpet.mc64 = h->mc_offset + guest_time_hpet(h->vcpu);
for ( i = 0; i < HPET_TIMER_NUM; i++ )
hpet_stop_timer(h, i);
}
@@ -384,7 +390,7 @@ static int hpet_save(struct domain *d, hvm_domain_context_t *h)
HPETState *hp = &d->arch.hvm_domain.pl_time.vhpet;
/* Write the proper value into the main counter */
hp->hpet.mc64 = hp->mc_offset + hvm_get_guest_time(hp->vcpu);
hp->hpet.mc64 = hp->mc_offset + guest_time_hpet(hp->vcpu);
/* Save the HPET registers */
return hvm_save_entry(HPET, 0, h, &hp->hpet);
@@ -400,7 +406,7 @@ static int hpet_load(struct domain *d, hvm_domain_context_t *h)
return -EINVAL;
/* Recalculate the offset between the main counter and guest time */
hp->mc_offset = hp->hpet.mc64 - hvm_get_guest_time(hp->vcpu);
hp->mc_offset = hp->hpet.mc64 - guest_time_hpet(hp->vcpu);
/* Restart the timers */
for ( i = 0; i < HPET_TIMER_NUM; i++ )
@@ -425,8 +431,8 @@ void hpet_init(struct vcpu *v)
h->hpet.capability = 0x8086A201ULL;
/* This is the number of femptoseconds per HPET tick. */
/* Here we define HPET's frequency to be the same as the TSC's. */
h->hpet.capability |= ((S_TO_FS/h->tsc_freq) << 32);
/* Here we define HPET's frequency to be 1/32 of the TSC's */
h->hpet.capability |= ((S_TO_FS*TSC_PER_HPET_TICK/h->tsc_freq) << 32);
for ( i = 0; i < HPET_TIMER_NUM; i++ )
{
+11
View File
@@ -415,6 +415,17 @@ static int mmio_decode(int address_bytes, unsigned char *opcode,
GET_OP_SIZE_FOR_NONEBYTE(*op_size);
return mem_reg(*op_size, opcode, mmio_op, rex);
case 0x08: /* or r8, m8 */
mmio_op->instr = INSTR_OR;
*op_size = BYTE;
GET_OP_SIZE_FOR_BYTE(size_reg);
return reg_mem(size_reg, opcode, mmio_op, rex);
case 0x09: /* or r32/16, m32/16 */
mmio_op->instr = INSTR_OR;
GET_OP_SIZE_FOR_NONEBYTE(*op_size);
return reg_mem(*op_size, opcode, mmio_op, rex);
case 0x0A: /* or m8, r8 */
mmio_op->instr = INSTR_OR;
*op_size = BYTE;
+49 -51
View File
@@ -449,6 +449,9 @@ int svm_vmcb_restore(struct vcpu *v, struct hvm_hw_cpu *c)
vmcb->rflags = c->eflags;
v->arch.hvm_svm.cpu_shadow_cr0 = c->cr0;
vmcb->cr0 = c->cr0 | X86_CR0_WP | X86_CR0_ET;
if ( !paging_mode_hap(v->domain) )
vmcb->cr0 |= X86_CR0_PG;
#ifdef HVM_DEBUG_SUSPEND
printk("%s: cr3=0x%"PRIx64", cr0=0x%"PRIx64", cr4=0x%"PRIx64".\n",
@@ -482,7 +485,6 @@ int svm_vmcb_restore(struct vcpu *v, struct hvm_hw_cpu *c)
* first.
*/
HVM_DBG_LOG(DBG_LEVEL_VMMU, "CR3 c->cr3 = %"PRIx64"", c->cr3);
/* current!=vcpu as not called by arch_vmx_do_launch */
mfn = gmfn_to_mfn(v->domain, c->cr3 >> PAGE_SHIFT);
if( !mfn_valid(mfn) || !get_page(mfn_to_page(mfn), v->domain) )
goto bad_cr3;
@@ -566,7 +568,7 @@ void svm_save_cpu_state(struct vcpu *v, struct hvm_hw_cpu *data)
data->msr_star = vmcb->star;
data->msr_cstar = vmcb->cstar;
data->msr_syscall_mask = vmcb->sfmask;
data->msr_efer = vmcb->efer;
data->msr_efer = v->arch.hvm_svm.cpu_shadow_efer;
data->tsc = hvm_get_guest_time(v);
}
@@ -581,7 +583,12 @@ void svm_load_cpu_state(struct vcpu *v, struct hvm_hw_cpu *data)
vmcb->star = data->msr_star;
vmcb->cstar = data->msr_cstar;
vmcb->sfmask = data->msr_syscall_mask;
vmcb->efer = data->msr_efer;
v->arch.hvm_svm.cpu_shadow_efer = data->msr_efer;
vmcb->efer = data->msr_efer | EFER_SVME;
/* VMCB's EFER.LME isn't set unless we're actually in long mode
* (see long_mode_do_msr_write()) */
if ( !(vmcb->efer & EFER_LMA) )
vmcb->efer &= ~EFER_LME;
hvm_set_guest_time(v, data->tsc);
}
@@ -741,6 +748,14 @@ static void svm_set_tsc_offset(struct vcpu *v, u64 offset)
static void svm_init_ap_context(
struct vcpu_guest_context *ctxt, int vcpuid, int trampoline_vector)
{
struct vcpu *v;
cpu_user_regs_t *regs;
u16 cs_sel;
/* We know this is safe because hvm_bringup_ap() does it */
v = current->domain->vcpu[vcpuid];
regs = &v->arch.guest_context.user_regs;
memset(ctxt, 0, sizeof(*ctxt));
/*
@@ -748,8 +763,19 @@ static void svm_init_ap_context(
* passed to us is page alligned and is the physicall frame number for
* the code. We will execute this code in real mode.
*/
cs_sel = trampoline_vector << 8;
ctxt->user_regs.eip = 0x0;
ctxt->user_regs.cs = (trampoline_vector << 8);
ctxt->user_regs.cs = cs_sel;
/*
* This is the launch of an AP; set state so that we begin executing
* the trampoline code in real-mode.
*/
svm_do_vmmcall_reset_to_realmode(v, regs);
/* Adjust the vmcb's hidden register state. */
v->arch.hvm_svm.vmcb->rip = 0;
v->arch.hvm_svm.vmcb->cs.sel = cs_sel;
v->arch.hvm_svm.vmcb->cs.base = (cs_sel << 4);
}
static void svm_init_hypercall_page(struct domain *d, void *hypercall_page)
@@ -894,32 +920,6 @@ static void svm_load_cpu_guest_regs(
svm_load_cpu_user_regs(v, regs);
}
static void arch_svm_do_launch(struct vcpu *v)
{
svm_do_launch(v);
if ( paging_mode_hap(v->domain) ) {
v->arch.hvm_svm.vmcb->h_cr3 = pagetable_get_paddr(v->domain->arch.phys_table);
}
if ( v->vcpu_id != 0 )
{
cpu_user_regs_t *regs = &current->arch.guest_context.user_regs;
u16 cs_sel = regs->cs;
/*
* This is the launch of an AP; set state so that we begin executing
* the trampoline code in real-mode.
*/
svm_do_vmmcall_reset_to_realmode(v, regs);
/* Adjust the state to execute the trampoline code.*/
v->arch.hvm_svm.vmcb->rip = 0;
v->arch.hvm_svm.vmcb->cs.sel= cs_sel;
v->arch.hvm_svm.vmcb->cs.base = (cs_sel << 4);
}
reset_stack_and_jump(svm_asm_do_launch);
}
static void svm_ctxt_switch_from(struct vcpu *v)
{
svm_save_dr(v);
@@ -941,16 +941,30 @@ static void svm_ctxt_switch_to(struct vcpu *v)
svm_restore_dr(v);
}
static void arch_svm_do_resume(struct vcpu *v)
{
if ( v->arch.hvm_svm.launch_core != smp_processor_id() )
{
v->arch.hvm_svm.launch_core = smp_processor_id();
hvm_migrate_timers(v);
}
hvm_do_resume(v);
reset_stack_and_jump(svm_asm_do_resume);
}
static int svm_vcpu_initialise(struct vcpu *v)
{
int rc;
v->arch.schedule_tail = arch_svm_do_launch;
v->arch.schedule_tail = arch_svm_do_resume;
v->arch.ctxt_switch_from = svm_ctxt_switch_from;
v->arch.ctxt_switch_to = svm_ctxt_switch_to;
v->arch.hvm_svm.saved_irq_vector = -1;
v->arch.hvm_svm.launch_core = -1;
if ( (rc = svm_create_vmcb(v)) != 0 )
{
dprintk(XENLOG_WARNING,
@@ -1014,10 +1028,12 @@ void svm_npt_detect(void)
/* check CPUID for nested paging support */
cpuid(0x8000000A, &eax, &ebx, &ecx, &edx);
if ( edx & 0x01 ) { /* nested paging */
if ( edx & 0x01 ) /* nested paging */
{
hap_capable_system = 1;
}
else if ( opt_hap_enabled ) {
else if ( opt_hap_enabled )
{
printk(" nested paging is not supported by this CPU.\n");
hap_capable_system = 0; /* no nested paging, we disable flag. */
}
@@ -1075,24 +1091,6 @@ int start_svm(void)
return 1;
}
void arch_svm_do_resume(struct vcpu *v)
{
/* pinning VCPU to a different core? */
if ( v->arch.hvm_svm.launch_core == smp_processor_id()) {
hvm_do_resume( v );
reset_stack_and_jump( svm_asm_do_resume );
}
else {
if (svm_dbg_on)
printk("VCPU core pinned: %d to %d\n",
v->arch.hvm_svm.launch_core, smp_processor_id() );
v->arch.hvm_svm.launch_core = smp_processor_id();
hvm_migrate_timers( v );
hvm_do_resume( v );
reset_stack_and_jump( svm_asm_do_resume );
}
}
static int svm_do_nested_pgfault(paddr_t gpa, struct cpu_user_regs *regs)
{
if (mmio_space(gpa)) {
+3 -11
View File
@@ -196,11 +196,13 @@ static int construct_vmcb(struct vcpu *v)
arch_svm->vmcb->exception_intercepts = MONITOR_DEFAULT_EXCEPTION_BITMAP;
if ( paging_mode_hap(v->domain) ) {
if ( paging_mode_hap(v->domain) )
{
vmcb->cr0 = arch_svm->cpu_shadow_cr0;
vmcb->np_enable = 1; /* enable nested paging */
vmcb->g_pat = 0x0007040600070406ULL; /* guest PAT */
vmcb->exception_intercepts &= ~EXCEPTION_BITMAP_PG;
vmcb->h_cr3 = pagetable_get_paddr(v->domain->arch.phys_table);
}
return 0;
@@ -247,16 +249,6 @@ void svm_destroy_vmcb(struct vcpu *v)
arch_svm->vmcb = NULL;
}
void svm_do_launch(struct vcpu *v)
{
hvm_stts(v);
/* current core is the one we intend to perform the VMRUN on */
v->arch.hvm_svm.launch_core = smp_processor_id();
v->arch.schedule_tail = arch_svm_do_resume;
}
static void svm_dump_sel(char *name, svm_segment_register_t *s)
{
printk("%s: sel=0x%04x, attr=0x%04x, limit=0x%08x, base=0x%016llx\n",
+13 -27
View File
@@ -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)
@@ -134,31 +143,8 @@ svm_stgi_label:
addl $4,%esp
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
+12 -22
View File
@@ -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
+2 -2
View File
@@ -54,8 +54,8 @@ static int vpic_get_priority(struct hvm_hw_vpic *vpic, uint8_t mask)
if ( mask == 0 )
return VPIC_PRIO_NONE;
/* prio = ffs(mask ROL vpic->priority_add); */
asm ( "rol %%cl,%b1 ; bsf %1,%0"
/* prio = ffs(mask ROR vpic->priority_add); */
asm ( "ror %%cl,%b1 ; bsf %1,%0"
: "=r" (prio) : "r" ((uint32_t)mask), "c" (vpic->priority_add) );
return prio;
}
+6
View File
@@ -108,6 +108,7 @@
#include <asm/x86_emulate.h>
#include <asm/e820.h>
#include <asm/hypercall.h>
#include <asm/shared.h>
#include <public/memory.h>
#define MEM_LOG(_f, _a...) gdprintk(XENLOG_WARNING , _f "\n" , ## _a)
@@ -246,6 +247,11 @@ int memory_is_conventional_ram(paddr_t p)
return 0;
}
unsigned long domain_get_maximum_gpfn(struct domain *d)
{
return is_hvm_domain(d) ? d->arch.p2m.max_mapped_pfn : arch_get_max_pfn(d);
}
void share_xen_page_with_guest(
struct page_info *page, struct domain *d, int readonly)
{
+3 -3
View File
@@ -36,7 +36,6 @@
#include <asm/current.h>
#include <asm/flushtlb.h>
#include <asm/shadow.h>
#include <asm/shared.h>
#include "private.h"
@@ -2672,7 +2671,7 @@ sh_alloc_log_dirty_bitmap(struct domain *d)
{
ASSERT(d->arch.paging.shadow.dirty_bitmap == NULL);
d->arch.paging.shadow.dirty_bitmap_size =
(arch_get_max_pfn(d) + (BITS_PER_LONG - 1)) &
(domain_get_maximum_gpfn(d) + (BITS_PER_LONG - 1)) &
~(BITS_PER_LONG - 1);
d->arch.paging.shadow.dirty_bitmap =
xmalloc_array(unsigned long,
@@ -2682,7 +2681,8 @@ sh_alloc_log_dirty_bitmap(struct domain *d)
d->arch.paging.shadow.dirty_bitmap_size = 0;
return -ENOMEM;
}
memset(d->arch.paging.shadow.dirty_bitmap, 0, d->arch.paging.shadow.dirty_bitmap_size/8);
memset(d->arch.paging.shadow.dirty_bitmap, 0,
d->arch.paging.shadow.dirty_bitmap_size/8);
return 0;
}
+1
View File
@@ -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);
+4
View File
@@ -187,6 +187,10 @@ ENTRY(compat_post_handle_exception)
call compat_create_bounce_frame
jmp compat_test_all_events
ENTRY(compat_int80_direct_trap)
call compat_create_bounce_frame
jmp compat_restore_all_guest
/* CREATE A BASIC EXCEPTION FRAME ON GUEST OS (RING-1) STACK: */
/* {[ERRCODE,] EIP, CS, EFLAGS, [ESP, SS]} */
/* %rdx: trap_bounce, %rbx: struct vcpu */
+4
View File
@@ -1,6 +1,7 @@
#ifdef CONFIG_COMPAT
#include <xen/event.h>
#include <asm/regs.h>
#include <compat/callback.h>
#include <compat/arch-x86_32.h>
@@ -291,6 +292,9 @@ int compat_set_trap_table(XEN_GUEST_HANDLE(trap_info_compat_t) traps)
XLAT_trap_info(dst + cur.vector, &cur);
if ( cur.vector == 0x80 )
init_int80_direct_trap(current);
guest_handle_add_offset(traps, 1);
}
+30
View File
@@ -222,6 +222,35 @@ bad_hypercall:
movq $-ENOSYS,UREGS_rax(%rsp)
jmp test_all_events
ENTRY(int80_direct_trap)
pushq $0
SAVE_ALL
GET_CURRENT(%rbx)
/* Check that the callback is non-null. */
leaq VCPU_int80_bounce(%rbx),%rdx
cmp $0, TRAPBOUNCE_flags(%rdx)
jz int80_slow_path
movq VCPU_domain(%rbx),%rax
btl $_DOMF_compat,DOMAIN_domain_flags(%rax)
jc compat_int80_direct_trap
call create_bounce_frame
jmp restore_all_guest
int80_slow_path:
/*
* Setup entry vector and error code as if this was a GPF caused by an
* IDT entry with DPL==0.
*/
movl $((0x80 << 3) | 0x2),UREGS_error_code(%rsp)
movl $TRAP_gp_fault,UREGS_entry_vector(%rsp)
/* A GPF wouldn't have incremented the instruction pointer. */
sub $2,UREGS_rip(%rsp)
jmp handle_exception_saved
/* CREATE A BASIC EXCEPTION FRAME ON GUEST OS STACK: */
/* { RCX, R11, [DS-GS,] [CR2,] [ERRCODE,] RIP, CS, RFLAGS, RSP, SS } */
/* %rdx: trap_bounce, %rbx: struct vcpu */
@@ -359,6 +388,7 @@ ENTRY(ret_from_intr)
/* No special register assumptions. */
ENTRY(handle_exception)
SAVE_ALL
handle_exception_saved:
testb $X86_EFLAGS_IF>>8,UREGS_eflags+1(%rsp)
jz exception_with_ints_disabled
sti
+18
View File
@@ -247,6 +247,7 @@ unsigned long do_iret(void)
asmlinkage void syscall_enter(void);
asmlinkage void compat_hypercall(void);
asmlinkage void int80_direct_trap(void);
void __init percpu_traps_init(void)
{
char *stack_bottom, *stack;
@@ -262,6 +263,7 @@ void __init percpu_traps_init(void)
#ifdef CONFIG_COMPAT
/* The hypercall entry vector is only accessible from ring 1. */
_set_gate(idt_table+HYPERCALL_VECTOR, 15, 1, &compat_hypercall);
_set_gate(idt_table+0x80, 15, 3, &int80_direct_trap);
#endif
}
@@ -346,6 +348,22 @@ void __init percpu_traps_init(void)
wrmsr(MSR_SYSCALL_MASK, EF_VM|EF_RF|EF_NT|EF_DF|EF_IE|EF_TF, 0U);
}
void init_int80_direct_trap(struct vcpu *v)
{
struct trap_info *ti = &v->arch.guest_context.trap_ctxt[0x80];
struct trap_bounce *tb = &v->arch.int80_bounce;
if ( !guest_gate_selector_okay(v->domain, ti->cs) )
return;
tb->flags = TBF_EXCEPTION;
tb->cs = ti->cs;
tb->eip = ti->address;
if ( null_trap_bounce(v, tb) )
tb->flags = 0;
}
static long register_guest_callback(struct callback_register *reg)
{
long ret = 0;
+2
View File
@@ -170,6 +170,7 @@ int compat_memory_op(unsigned int cmd, XEN_GUEST_HANDLE(void) compat)
case XENMEM_current_reservation:
case XENMEM_maximum_reservation:
case XENMEM_maximum_gpfn:
{
#define xen_domid_t domid_t
#define compat_domid_t domid_compat_t
@@ -325,6 +326,7 @@ int compat_memory_op(unsigned int cmd, XEN_GUEST_HANDLE(void) compat)
case XENMEM_maximum_ram_page:
case XENMEM_current_reservation:
case XENMEM_maximum_reservation:
case XENMEM_maximum_gpfn:
break;
case XENMEM_translate_gpfn_list:
+14 -1
View File
@@ -584,6 +584,7 @@ long do_memory_op(unsigned long cmd, XEN_GUEST_HANDLE(void) arg)
case XENMEM_current_reservation:
case XENMEM_maximum_reservation:
case XENMEM_maximum_gpfn:
if ( copy_from_guest(&domid, arg, 1) )
return -EFAULT;
@@ -594,7 +595,19 @@ long do_memory_op(unsigned long cmd, XEN_GUEST_HANDLE(void) arg)
else if ( (d = rcu_lock_domain_by_id(domid)) == NULL )
return -ESRCH;
rc = (op == XENMEM_current_reservation) ? d->tot_pages : d->max_pages;
switch ( op )
{
case XENMEM_current_reservation:
rc = d->tot_pages;
break;
case XENMEM_maximum_reservation:
rc = d->max_pages;
break;
default:
ASSERT(op == XENMEM_maximum_gpfn);
rc = domain_get_maximum_gpfn(d);
break;
}
if ( unlikely(domid != DOMID_SELF) )
rcu_unlock_domain(d);
+4 -13
View File
@@ -136,8 +136,8 @@ static xen_sysctl_perfc_desc_t perfc_d[NR_PERFCTRS];
static xen_sysctl_perfc_val_t *perfc_vals;
static int perfc_nbr_vals;
static int perfc_init = 0;
static int perfc_copy_info(XEN_GUEST_HANDLE(xen_sysctl_perfc_desc_t) desc,
XEN_GUEST_HANDLE(xen_sysctl_perfc_val_t) val)
static int perfc_copy_info(XEN_GUEST_HANDLE_64(xen_sysctl_perfc_desc_t) desc,
XEN_GUEST_HANDLE_64(xen_sysctl_perfc_val_t) val)
{
unsigned int i, j;
unsigned int v = 0;
@@ -217,29 +217,20 @@ static int perfc_copy_info(XEN_GUEST_HANDLE(xen_sysctl_perfc_desc_t) desc,
int perfc_control(xen_sysctl_perfc_op_t *pc)
{
static DEFINE_SPINLOCK(lock);
XEN_GUEST_HANDLE(xen_sysctl_perfc_desc_t) desc;
XEN_GUEST_HANDLE(xen_sysctl_perfc_val_t) val;
int rc;
/*
* 64 bit guest handles cannot be passed as parameters to
* functions so cast to a regular guest handle.
*/
desc = guest_handle_cast(pc->desc, xen_sysctl_perfc_desc_t);
val = guest_handle_cast(pc->val, xen_sysctl_perfc_val_t);
spin_lock(&lock);
switch ( pc->cmd )
{
case XEN_SYSCTL_PERFCOP_reset:
perfc_copy_info(desc, val);
perfc_copy_info(pc->desc, pc->val);
perfc_reset(0);
rc = 0;
break;
case XEN_SYSCTL_PERFCOP_query:
perfc_copy_info(desc, val);
perfc_copy_info(pc->desc, pc->val);
rc = 0;
break;
+2
View File
@@ -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__ */
+2
View File
@@ -278,4 +278,6 @@ extern int steal_page(struct domain *d, struct page_info *page,
#define domain_clamp_alloc_bitsize(d, b) (b)
#define domain_get_maximum_gpfn(d) (-ENOSYS)
#endif
+3
View File
@@ -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;
-2
View File
@@ -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];
+1 -1
View File
@@ -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 */
+1
View File
@@ -404,5 +404,6 @@ unsigned int domain_clamp_alloc_bitsize(struct domain *d, unsigned int bits);
# define domain_clamp_alloc_bitsize(d, b) (b)
#endif
unsigned long domain_get_maximum_gpfn(struct domain *d);
#endif /* __ASM_X86_MM_H__ */
+3 -3
View File
@@ -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
+1 -1
View File
@@ -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__
Loaded 100 of 103 files, more files were not shown because too many files have changed in this diff. Show more
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.