merge with xen-unstable.hg

This commit is contained in:
awilliam@xenbuild2.aw committed 2007-02-04 12:24:53 -07:00
commit a6e547a237
74 files changed
+1559 -455

No files matched your search

+1
View File
@@ -1268,6 +1268,7 @@ CONFIG_IEEE1394_RAWIO=m
CONFIG_I2O=m
CONFIG_I2O_LCT_NOTIFY_ON_CHANGES=y
CONFIG_I2O_EXT_ADAPTEC=y
CONFIG_I2O_EXT_ADAPTEC_DMA64=y
CONFIG_I2O_CONFIG=m
CONFIG_I2O_CONFIG_OLD_IOCTL=y
CONFIG_I2O_BUS=m
+196 -13
View File
@@ -142,7 +142,6 @@ The following enumeration types are used:
\hspace{0.5cm}{\tt Paused} & Paused \\
\hspace{0.5cm}{\tt Running} & Running \\
\hspace{0.5cm}{\tt Suspended} & Suspended \\
\hspace{0.5cm}{\tt ShuttingDown} & Shutting Down \\
\hspace{0.5cm}{\tt Unknown} & Some other unknown state \\
\hline
\end{longtable}
@@ -1026,9 +1025,9 @@ references to objects with match names
virtual machine (or 'guest').
VM booting is controlled by setting one of the two mutually exclusive
groups: "PV", and "HVM". If HVM.boot is the empty string, then paravirtual
domain building and booting will be used; otherwise the VM will be loaded
as an HVM domain, and booted using an emulated BIOS.
groups: "PV", and "HVM". If HVM.boot\_policy is the empty string, then
paravirtual domain building and booting will be used; otherwise the VM will
be loaded as an HVM domain, and booted using an emulated BIOS.
When paravirtual booting is in use, the PV/bootloader field indicates the
bootloader to use. It may be "pygrub", in which case the platform's
@@ -1053,7 +1052,10 @@ ramdisk values will be treated as paths within the control domain. If both
PV/bootloader and PV/kernel are empty, then the behaviour is as if
PV/bootloader was specified as "pygrub".
When using HVM booting, HVM/boot specifies the order of the boot devices.}} \\
When using HVM booting, HVM/boot\_policy and HVM/boot\_params specify the
boot handling. Only one policy is currently defined: "BIOS order". In
this case, HVM/boot\_params should contain one key-value pair "order" = "N"
where N is the string that will be passed to QEMU.}} \\
\hline
Quals & Field & Type & Description \\
\hline
@@ -1089,7 +1091,8 @@ $\mathit{RW}$ & {\tt PV/kernel} & string & path to the kernel \\
$\mathit{RW}$ & {\tt PV/ramdisk} & string & path to the initrd \\
$\mathit{RW}$ & {\tt PV/args} & string & kernel command-line arguments \\
$\mathit{RW}$ & {\tt PV/bootloader\_args} & string & miscellaneous arguments for the bootloader \\
$\mathit{RW}$ & {\tt HVM/boot} & string & device boot order \\
$\mathit{RW}$ & {\tt HVM/boot\_policy} & string & HVM boot policy \\
$\mathit{RW}$ & {\tt HVM/boot\_params} & (string $\rightarrow$ string) Map & HVM boot params \\
$\mathit{RW}$ & {\tt platform/std\_VGA} & bool & emulate standard VGA instead of cirrus logic \\
$\mathit{RW}$ & {\tt platform/serial} & string & redirect serial port to pty \\
$\mathit{RW}$ & {\tt platform/localtime} & bool & set RTC to local time \\
@@ -3297,13 +3300,13 @@ void
\vspace{0.3cm}
\vspace{0.3cm}
\vspace{0.3cm}
\subsubsection{RPC name:~get\_HVM\_boot}
\subsubsection{RPC name:~get\_HVM\_boot\_policy}
{\bf Overview:}
Get the HVM/boot field of the given VM.
Get the HVM/boot\_policy field of the given VM.
\noindent {\bf Signature:}
\begin{verbatim} string get_HVM_boot (session_id s, VM ref self)\end{verbatim}
\begin{verbatim} string get_HVM_boot_policy (session_id s, VM ref self)\end{verbatim}
\noindent{\bf Arguments:}
@@ -3329,13 +3332,13 @@ value of the field
\vspace{0.3cm}
\vspace{0.3cm}
\vspace{0.3cm}
\subsubsection{RPC name:~set\_HVM\_boot}
\subsubsection{RPC name:~set\_HVM\_boot\_policy}
{\bf Overview:}
Set the HVM/boot field of the given VM.
Set the HVM/boot\_policy field of the given VM.
\noindent {\bf Signature:}
\begin{verbatim} void set_HVM_boot (session_id s, VM ref self, string value)\end{verbatim}
\begin{verbatim} void set_HVM_boot_policy (session_id s, VM ref self, string value)\end{verbatim}
\noindent{\bf Arguments:}
@@ -3360,6 +3363,143 @@ void
\vspace{0.3cm}
\vspace{0.3cm}
\vspace{0.3cm}
\subsubsection{RPC name:~get\_HVM\_boot\_params}
{\bf Overview:}
Get the HVM/boot\_params field of the given VM.
\noindent {\bf Signature:}
\begin{verbatim} ((string -> string) Map) get_HVM_boot_params (session_id s, VM ref self)\end{verbatim}
\noindent{\bf Arguments:}
\vspace{0.3cm}
\begin{tabular}{|c|c|p{7cm}|}
\hline
{\bf type} & {\bf name} & {\bf description} \\ \hline
{\tt VM ref } & self & reference to the object \\ \hline
\end{tabular}
\vspace{0.3cm}
\noindent {\bf Return Type:}
{\tt
(string $\rightarrow$ string) Map
}
value of the field
\vspace{0.3cm}
\vspace{0.3cm}
\vspace{0.3cm}
\subsubsection{RPC name:~set\_HVM\_boot\_params}
{\bf Overview:}
Set the HVM/boot\_params field of the given VM.
\noindent {\bf Signature:}
\begin{verbatim} void set_HVM_boot_params (session_id s, VM 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 VM 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\_HVM\_boot\_params}
{\bf Overview:}
Add the given key-value pair to the HVM/boot\_params field of the given VM.
\noindent {\bf Signature:}
\begin{verbatim} void add_to_HVM_boot_params (session_id s, VM 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 VM 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\_HVM\_boot\_params}
{\bf Overview:}
Remove the given key and its corresponding value from the HVM/boot\_params
field of the given VM. If the key is not in that Map, then do nothing.
\noindent {\bf Signature:}
\begin{verbatim} void remove_from_HVM_boot_params (session_id s, VM 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 VM 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}
@@ -4521,13 +4661,45 @@ void
\vspace{0.3cm}
\vspace{0.3cm}
\vspace{0.3cm}
\subsubsection{RPC name:~dmesg}
{\bf Overview:}
Get the host xen dmesg.
\noindent {\bf Signature:}
\begin{verbatim} string dmesg (session_id s, host ref host)\end{verbatim}
\noindent{\bf Arguments:}
\vspace{0.3cm}
\begin{tabular}{|c|c|p{7cm}|}
\hline
{\bf type} & {\bf name} & {\bf description} \\ \hline
{\tt host ref } & host & The Host to query \\ \hline
\end{tabular}
\vspace{0.3cm}
\noindent {\bf Return Type:}
{\tt
string
}
dmesg string
\vspace{0.3cm}
\vspace{0.3cm}
\vspace{0.3cm}
\subsubsection{RPC name:~get\_all}
{\bf Overview:}
Return a list of all the hosts known to the system
Return a list of all the hosts known to the system.
\noindent {\bf Signature:}
\begin{verbatim} ((host ref) Set) get_all (session_id s)\end{verbatim}
@@ -11758,6 +11930,17 @@ The handle parameter echoes the bad value given.
\begin{verbatim}TASK_HANDLE_INVALID(handle)\end{verbatim}
\begin{center}\rule{10em}{0.1pt}\end{center}
\subsubsection{VALUE\_NOT\_SUPPORTED}
You attempted to set a value that is not supported by this implementation.
The fully-qualified field name and the value that you tried to set are
returned. Also returned is a developer-only diagnostic reason.
\vspace{0.3cm}
{\bf Signature:}
\begin{verbatim}VALUE_NOT_SUPPORTED(field, value, reason)\end{verbatim}
\begin{center}\rule{10em}{0.1pt}\end{center}
\subsubsection{VBD\_HANDLE\_INVALID}
You gave an invalid VBD handle. The VBD may have recently been deleted.
+4 -5
View File
@@ -69,7 +69,7 @@ CS = 0x2C
popl %ds; \
popl %es; \
addl $4,%esp; \
iret; \
iret;
ENTRY(divide_error)
pushl $0 # no error code
@@ -101,10 +101,9 @@ do_exception:
jmp ret_from_exception
ret_from_exception:
movb CS(%esp),%cl
test $2,%cl # slow return to ring 2 or 3
jne safesti
RESTORE_ALL
movb CS(%esp),%cl
addl $8,%esp
RESTORE_ALL
# A note on the "critical region" in our callback handler.
# We want to avoid stacking callback handlers due to events occurring
+2
View File
@@ -178,6 +178,7 @@ static void release_xenbus_id(int id)
BUG_ON(!req_info[id].in_use);
spin_lock(&req_lock);
nr_live_reqs--;
req_info[id].in_use = 0;
if (nr_live_reqs == NR_REQS - 1)
wake_up(&req_wq);
spin_unlock(&req_lock);
@@ -212,6 +213,7 @@ static int allocate_xenbus_id(void)
probe = o_probe + 1;
spin_unlock(&req_lock);
init_waitqueue_head(&req_info[o_probe].waitq);
return o_probe;
}
@@ -1935,8 +1935,6 @@ static struct net_device * __devinit create_netdev(struct xenbus_device *dev)
np = netdev_priv(netdev);
np->xbdev = dev;
netif_carrier_off(netdev);
spin_lock_init(&np->tx_lock);
spin_lock_init(&np->rx_lock);
@@ -1991,6 +1989,9 @@ static struct net_device * __devinit create_netdev(struct xenbus_device *dev)
SET_NETDEV_DEV(netdev, &dev->dev);
np->netdev = netdev;
netif_carrier_off(netdev);
return netdev;
exit_free_tx:
@@ -42,9 +42,9 @@
#define DPRINTK(fmt, args...) \
pr_debug("xenbus_client (%s:%d) " fmt ".\n", __FUNCTION__, __LINE__, ##args)
char *xenbus_strstate(enum xenbus_state state)
const char *xenbus_strstate(enum xenbus_state state)
{
static char *name[] = {
static const char *const name[] = {
[ XenbusStateUnknown ] = "Unknown",
[ XenbusStateInitialising ] = "Initialising",
[ XenbusStateInitWait ] = "InitWait",
@@ -55,6 +55,7 @@ char *xenbus_strstate(enum xenbus_state state)
};
return (state < ARRAY_SIZE(name)) ? name[state] : "INVALID";
}
EXPORT_SYMBOL_GPL(xenbus_strstate);
int xenbus_watch_path(struct xenbus_device *dev, const char *path,
struct xenbus_watch *watch,
+1 -1
View File
@@ -295,7 +295,7 @@ void xenbus_dev_fatal(struct xenbus_device *dev, int err, const char *fmt,
int __init xenbus_dev_init(void);
char *xenbus_strstate(enum xenbus_state state);
const char *xenbus_strstate(enum xenbus_state state);
int xenbus_dev_is_online(struct xenbus_device *dev);
int xenbus_frontend_closed(struct xenbus_device *dev);
+4 -4
View File
@@ -363,9 +363,9 @@ diff -pruN ../orig-linux-2.6.18/drivers/oprofile/oprof.c ./drivers/oprofile/opro
+ if (!oprofile_ops.set_active)
+ return -EINVAL;
+
+ down(&start_sem);
+ mutex_lock(&start_mutex);
+ err = oprofile_ops.set_active(active_domains, adomains);
+ up(&start_sem);
+ mutex_unlock(&start_mutex);
+ return err;
+}
+
@@ -376,9 +376,9 @@ diff -pruN ../orig-linux-2.6.18/drivers/oprofile/oprof.c ./drivers/oprofile/opro
+ if (!oprofile_ops.set_passive)
+ return -EINVAL;
+
+ down(&start_sem);
+ mutex_lock(&start_mutex);
+ err = oprofile_ops.set_passive(passive_domains, pdomains);
+ up(&start_sem);
+ mutex_unlock(&start_mutex);
+ return err;
+}
+
+1 -1
View File
@@ -56,6 +56,6 @@ mk-symlinks-xen:
( cd xen/foreign && ln -sf ../../$(XEN_ROOT)/xen/include/public/foreign/Makefile . )
( cd xen/foreign && ln -sf ../../$(XEN_ROOT)/xen/include/public/foreign/reference.size . )
( cd xen/foreign && ln -sf ../../$(XEN_ROOT)/xen/include/public/foreign/*.py . )
make -C xen/foreign
$(MAKE) -C xen/foreign
mk-symlinks: mk-symlinks-xen mk-symlinks-$(XEN_OS)
+18 -21
View File
@@ -144,7 +144,7 @@ static int x86_shadow(int xc, domid_t domid)
return rc;
}
static int arch_setup_early(struct xc_dom_image *dom)
static int arch_setup_meminit(struct xc_dom_image *dom)
{
int rc = 0;
@@ -157,13 +157,13 @@ static int arch_setup_early(struct xc_dom_image *dom)
return rc;
}
static int arch_setup_middle(struct xc_dom_image *dom)
static int arch_setup_bootearly(struct xc_dom_image *dom)
{
xc_dom_printf("%s: doing nothing\n", __FUNCTION__);
return 0;
}
static int arch_setup_late(struct xc_dom_image *dom)
static int arch_setup_bootlate(struct xc_dom_image *dom)
{
static const struct {
char *guest;
@@ -263,13 +263,13 @@ static int arch_setup_late(struct xc_dom_image *dom)
#elif defined(__ia64__)
static int arch_setup_early(struct xc_dom_image *dom)
static int arch_setup_meminit(struct xc_dom_image *dom)
{
xc_dom_printf("%s: doing nothing\n", __FUNCTION__);
return 0;
}
static int arch_setup_middle(struct xc_dom_image *dom)
static int arch_setup_bootearly(struct xc_dom_image *dom)
{
DECLARE_DOMCTL;
int rc;
@@ -281,10 +281,6 @@ static int arch_setup_middle(struct xc_dom_image *dom)
domctl.domain = dom->guest_domid;
domctl.u.arch_setup.flags = 0;
/* dom->start_info_pfn should be initialized by alloc_magic_pages().
* However it is called later. So we initialize here.
*/
dom->start_info_pfn = dom->total_pages - 3;
domctl.u.arch_setup.bp = (dom->start_info_pfn << PAGE_SHIFT)
+ sizeof(start_info_t);
/* 3 = start info page, xenstore page and console page */
@@ -293,7 +289,7 @@ static int arch_setup_middle(struct xc_dom_image *dom)
return rc;
}
static int arch_setup_late(struct xc_dom_image *dom)
static int arch_setup_bootlate(struct xc_dom_image *dom)
{
unsigned int page_size = XC_DOM_PAGE_SIZE(dom);
shared_info_t *shared_info;
@@ -317,19 +313,19 @@ static int arch_setup_late(struct xc_dom_image *dom)
#elif defined(__powerpc64__)
static int arch_setup_early(struct xc_dom_image *dom)
static int arch_setup_meminit(struct xc_dom_image *dom)
{
xc_dom_printf("%s: doing nothing\n", __FUNCTION__);
return 0;
}
static int arch_setup_middle(struct xc_dom_image *dom)
static int arch_setup_bootearly(struct xc_dom_image *dom)
{
xc_dom_printf("%s: doing nothing\n", __FUNCTION__);
return 0;
}
static int arch_setup_late(struct xc_dom_image *dom)
static int arch_setup_bootlate(struct xc_dom_image *dom)
{
start_info_t *si =
xc_dom_pfn_to_ptr(dom, dom->start_info_pfn, 1);
@@ -355,19 +351,19 @@ static int arch_setup_late(struct xc_dom_image *dom)
#else
static int arch_setup_early(struct xc_dom_image *dom)
static int arch_setup_meminit(struct xc_dom_image *dom)
{
xc_dom_printf("%s: doing nothing\n", __FUNCTION__);
return 0;
}
static int arch_setup_middle(struct xc_dom_image *dom)
static int arch_setup_bootearly(struct xc_dom_image *dom)
{
xc_dom_printf("%s: doing nothing\n", __FUNCTION__);
return 0;
}
static int arch_setup_late(struct xc_dom_image *dom)
static int arch_setup_bootlate(struct xc_dom_image *dom)
{
xc_dom_printf("%s: doing nothing\n", __FUNCTION__);
return 0;
@@ -423,7 +419,7 @@ int xc_dom_boot_mem_init(struct xc_dom_image *dom)
xc_dom_printf("%s: called\n", __FUNCTION__);
if (0 != (rc = arch_setup_early(dom)))
if (0 != (rc = arch_setup_meminit(dom)))
return rc;
/* allocate guest memory */
@@ -438,9 +434,6 @@ int xc_dom_boot_mem_init(struct xc_dom_image *dom)
return rc;
}
if (0 != (rc = arch_setup_middle(dom)))
return rc;
return 0;
}
@@ -497,6 +490,10 @@ int xc_dom_boot_image(struct xc_dom_image *dom)
xc_dom_printf("%s: called\n", __FUNCTION__);
/* misc ia64 stuff*/
if (0 != (rc = arch_setup_bootearly(dom)))
return rc;
/* collect some info */
domctl.cmd = XEN_DOMCTL_getdomaininfo;
domctl.domain = dom->guest_domid;
@@ -542,7 +539,7 @@ int xc_dom_boot_image(struct xc_dom_image *dom)
xc_dom_log_memory_footprint(dom);
/* misc x86 stuff */
if (0 != (rc = arch_setup_late(dom)))
if (0 != (rc = arch_setup_bootlate(dom)))
return rc;
/* let the vm run */
+3
View File
@@ -717,6 +717,9 @@ int xc_dom_build_image(struct xc_dom_image *dom)
}
page_size = XC_DOM_PAGE_SIZE(dom);
/* 4MB align virtual base address */
dom->parms.virt_base &= ~(((uint64_t)1<<22)-1);
/* load kernel */
if (0 != xc_dom_alloc_segment(dom, &dom->kernel_seg, "kernel",
dom->kernel_seg.vstart,
+1 -5
View File
@@ -26,11 +26,7 @@ static int alloc_magic_pages(struct xc_dom_image *dom)
/* allocate special pages */
dom->console_pfn = dom->total_pages -1;
dom->xenstore_pfn = dom->total_pages -2;
/*
* this is initialized by arch_setup_middle().
* dom->start_info_pfn = dom->total_pages -3;
*/
dom->start_info_pfn = dom->total_pages -3;
return 0;
}
+3 -1
View File
@@ -66,11 +66,12 @@ static int count_pgtables(struct xc_dom_image *dom, int pae,
extra_pages = dom->alloc_bootstack ? 1 : 0;
extra_pages += dom->extra_pages;
extra_pages += 128; /* 512kB padding */
pages = extra_pages;
for (;;)
{
try_virt_end = round_up(dom->virt_alloc_end + pages * PAGE_SIZE_X86,
bits_to_mask(l1_bits));
bits_to_mask(22)); /* 4MB alignment */
dom->pg_l4 =
nr_page_tables(dom->parms.virt_base, try_virt_end, l4_bits);
dom->pg_l3 =
@@ -313,6 +314,7 @@ static int alloc_magic_pages(struct xc_dom_image *dom)
if (xc_dom_feature_translated(dom))
dom->shared_info_pfn = xc_dom_alloc_page(dom, "shared info");
dom->alloc_bootstack = 1;
return 0;
}
+20 -16
View File
@@ -241,45 +241,49 @@ int xc_domain_getinfolist(int xc_handle,
/* get info from hvm guest for save */
int xc_domain_hvm_getcontext(int xc_handle,
uint32_t domid,
hvm_domain_context_t *hvm_ctxt)
uint8_t *ctxt_buf,
uint32_t size)
{
int rc;
int ret;
DECLARE_DOMCTL;
domctl.cmd = XEN_DOMCTL_gethvmcontext;
domctl.domain = (domid_t)domid;
set_xen_guest_handle(domctl.u.hvmcontext.ctxt, hvm_ctxt);
domctl.u.hvmcontext.size = size;
set_xen_guest_handle(domctl.u.hvmcontext.buffer, ctxt_buf);
if ( (rc = mlock(hvm_ctxt, sizeof(*hvm_ctxt))) != 0 )
return rc;
if ( (ret = lock_pages(ctxt_buf, size)) != 0 )
return ret;
rc = do_domctl(xc_handle, &domctl);
ret = do_domctl(xc_handle, &domctl);
safe_munlock(hvm_ctxt, sizeof(*hvm_ctxt));
unlock_pages(ctxt_buf, size);
return rc;
return (ret < 0 ? -1 : domctl.u.hvmcontext.size);
}
/* set info to hvm guest for restore */
int xc_domain_hvm_setcontext(int xc_handle,
uint32_t domid,
hvm_domain_context_t *hvm_ctxt)
uint8_t *ctxt_buf,
uint32_t size)
{
int rc;
int ret;
DECLARE_DOMCTL;
domctl.cmd = XEN_DOMCTL_sethvmcontext;
domctl.domain = domid;
set_xen_guest_handle(domctl.u.hvmcontext.ctxt, hvm_ctxt);
domctl.u.hvmcontext.size = size;
set_xen_guest_handle(domctl.u.hvmcontext.buffer, ctxt_buf);
if ( (rc = mlock(hvm_ctxt, sizeof(*hvm_ctxt))) != 0 )
return rc;
if ( (ret = lock_pages(ctxt_buf, size)) != 0 )
return ret;
rc = do_domctl(xc_handle, &domctl);
ret = do_domctl(xc_handle, &domctl);
safe_munlock(hvm_ctxt, sizeof(*hvm_ctxt));
unlock_pages(ctxt_buf, size);
return rc;
return ret;
}
int xc_vcpu_getcontext(int xc_handle,
+12 -9
View File
@@ -87,7 +87,7 @@ int xc_hvm_restore(int xc_handle, int io_fd,
xc_dominfo_t info;
unsigned int rc = 1, n, i;
uint32_t rec_len, nr_vcpus;
hvm_domain_context_t hvm_ctxt;
uint8_t *hvm_buf = NULL;
unsigned long long v_end, memsize;
unsigned long shared_page_nr;
@@ -128,8 +128,7 @@ int xc_hvm_restore(int xc_handle, int io_fd,
}
p2m = malloc(max_pfn * sizeof(xen_pfn_t));
p2m = malloc(max_pfn * sizeof(xen_pfn_t));
if (p2m == NULL) {
ERROR("memory alloc failed");
errno = ENOMEM;
@@ -297,18 +296,21 @@ int xc_hvm_restore(int xc_handle, int io_fd,
ERROR("error read hvm context size!\n");
goto out;
}
if (rec_len != sizeof(hvm_ctxt)) {
ERROR("hvm context size dismatch!\n");
hvm_buf = malloc(rec_len);
if (hvm_buf == NULL) {
ERROR("memory alloc for hvm context buffer failed");
errno = ENOMEM;
goto out;
}
if (!read_exact(io_fd, &hvm_ctxt, sizeof(hvm_ctxt))) {
ERROR("error read hvm context!\n");
if (!read_exact(io_fd, hvm_buf, rec_len)) {
ERROR("error read hvm buffer!\n");
goto out;
}
if (( rc = xc_domain_hvm_setcontext(xc_handle, dom, &hvm_ctxt))) {
ERROR("error set hvm context!\n");
if (( rc = xc_domain_hvm_setcontext(xc_handle, dom, hvm_buf, rec_len))) {
ERROR("error set hvm buffer!\n");
goto out;
}
@@ -361,6 +363,7 @@ int xc_hvm_restore(int xc_handle, int io_fd,
if ( (rc != 0) && (dom != 0) )
xc_domain_destroy(xc_handle, dom);
free(p2m);
free(hvm_buf);
DPRINTF("Restore exit with rc=%d\n", rc);
+20 -20
View File
@@ -32,6 +32,12 @@
#include "xg_private.h"
#include "xg_save_restore.h"
/*
* Size of a buffer big enough to take the HVM state of a domain.
* Ought to calculate this a bit more carefully, or maybe ask Xen.
*/
#define HVM_CTXT_SIZE 8192
/*
** Default values for important tuning parameters. Can override by passing
** non-zero replacement values to xc_hvm_save().
@@ -279,8 +285,8 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
unsigned long *pfn_type = NULL;
unsigned long *pfn_batch = NULL;
/* A copy of hvm domain context */
hvm_domain_context_t hvm_ctxt;
/* A copy of hvm domain context buffer*/
uint8_t *hvm_buf = NULL;
/* Live mapping of shared info structure */
shared_info_t *live_shinfo = NULL;
@@ -423,8 +429,12 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
to_send = malloc(BITMAP_SIZE);
to_skip = malloc(BITMAP_SIZE);
if (!to_send ||!to_skip) {
ERROR("Couldn't allocate to_send array");
page_array = (unsigned long *) malloc( sizeof(unsigned long) * max_pfn);
hvm_buf = malloc(HVM_CTXT_SIZE);
if (!to_send ||!to_skip ||!page_array ||!hvm_buf ) {
ERROR("Couldn't allocate memory");
goto out;
}
@@ -444,11 +454,6 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
analysis_phase(xc_handle, dom, max_pfn, to_skip, 0);
/* get all the HVM domain pfns */
if ( (page_array = (unsigned long *) malloc (sizeof(unsigned long) * max_pfn)) == NULL) {
ERROR("HVM:malloc fail!\n");
goto out;
}
for ( i = 0; i < max_pfn; i++)
page_array[i] = i;
@@ -655,24 +660,18 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
goto out;
}
/* save hvm hypervisor state including pic/pit/shpage */
if (mlock(&hvm_ctxt, sizeof(hvm_ctxt))) {
ERROR("Unable to mlock ctxt");
return 1;
}
if (xc_domain_hvm_getcontext(xc_handle, dom, &hvm_ctxt)){
ERROR("HVM:Could not get hvm context");
if ( (rec_size = xc_domain_hvm_getcontext(xc_handle, dom, hvm_buf,
HVM_CTXT_SIZE)) == -1) {
ERROR("HVM:Could not get hvm buffer");
goto out;
}
rec_size = sizeof(hvm_ctxt);
if (!write_exact(io_fd, &rec_size, sizeof(uint32_t))) {
ERROR("error write hvm ctxt size");
ERROR("error write hvm buffer size");
goto out;
}
if ( !write_exact(io_fd, &hvm_ctxt, sizeof(hvm_ctxt)) ) {
if ( !write_exact(io_fd, hvm_buf, rec_size) ) {
ERROR("write HVM info failed!\n");
}
@@ -722,6 +721,7 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
}
}
free(hvm_buf);
free(page_array);
free(pfn_type);
-2
View File
@@ -536,8 +536,6 @@ static int canonicalize_pagetable(unsigned long type, unsigned long pfn,
if (!MFN_IS_IN_PSEUDOPHYS_MAP(mfn)) {
/* This will happen if the type info is stale which
is quite feasible under live migration */
DPRINTF("PT Race: [%08lx,%d] pte=%llx, mfn=%08lx\n",
type, i, (unsigned long long)pte, mfn);
pfn = 0; /* zap it - we'll retransmit this page later */
race = 1; /* inform the caller of race; fatal if !live */
} else
+8 -4
View File
@@ -328,13 +328,15 @@ int xc_domain_getinfolist(int xc_handle,
* This function returns information about the context of a hvm domain
* @parm xc_handle a handle to an open hypervisor interface
* @parm domid the domain to get information from
* @parm hvm_ctxt a pointer to a structure to store the execution context of the
* hvm domain
* @parm ctxt_buf a pointer to a structure to store the execution context of
* the hvm domain
* @parm size the size of ctxt_buf in bytes
* @return 0 on success, -1 on failure
*/
int xc_domain_hvm_getcontext(int xc_handle,
uint32_t domid,
hvm_domain_context_t *hvm_ctxt);
uint8_t *ctxt_buf,
uint32_t size);
/**
* This function will set the context for hvm domain
@@ -342,11 +344,13 @@ int xc_domain_hvm_getcontext(int xc_handle,
* @parm xc_handle a handle to an open hypervisor interface
* @parm domid the domain to set the hvm domain context for
* @parm hvm_ctxt pointer to the the hvm context with the values to set
* @parm size the size of hvm_ctxt in bytes
* @return 0 on success, -1 on failure
*/
int xc_domain_hvm_setcontext(int xc_handle,
uint32_t domid,
hvm_domain_context_t *hvm_ctxt);
uint8_t *hvm_ctxt,
uint32_t size);
/**
* This function returns information about the execution context of a
+3
View File
@@ -51,6 +51,9 @@ libxenapi.a: $(LIBXENAPI_OBJS)
test/test_bindings: test/test_bindings.o libxenapi.so
$(CC) $(LDFLAGS) -o $@ $< -L . -lxenapi
test/test_hvm_bindings: test/test_hvm_bindings.o libxenapi.so
$(CC) $(LDFLAGS) -o $@ $< -L . -lxenapi
.PHONY: install
install: all
+7
View File
@@ -393,6 +393,13 @@ extern bool
xen_host_reboot(xen_session *session, xen_host host);
/**
* Get the host xen dmesg.
*/
extern bool
xen_host_dmesg(xen_session *session, char **result, xen_host host);
/**
* Return a list of all the hosts known to the system.
*/
+1
View File
@@ -74,6 +74,7 @@ typedef struct xen_vdi_record
int64_t virtual_size;
int64_t physical_utilisation;
int64_t sector_size;
char *location;
enum xen_vdi_type type;
bool sharable;
bool read_only;
+44 -9
View File
@@ -42,9 +42,9 @@
* A virtual machine (or 'guest').
*
* VM booting is controlled by setting one of the two mutually exclusive
* groups: "PV", and "HVM". If HVM.boot is the empty string, then paravirtual
* domain building and booting will be used; otherwise the VM will be loaded
* as an HVM domain, and booted using an emulated BIOS.
* groups: "PV", and "HVM". If HVM.boot_policy is the empty string, then
* paravirtual domain building and booting will be used; otherwise the VM will
* be loaded as an HVM domain, and booted using an emulated BIOS.
*
* When paravirtual booting is in use, the PV/bootloader field indicates the
* bootloader to use. It may be "pygrub", in which case the platform's
@@ -69,7 +69,10 @@
* PV/bootloader and PV/kernel are empty, then the behaviour is as if
* PV/bootloader was specified as "pygrub".
*
* When using HVM booting, HVM/boot specifies the order of the boot devices.
* When using HVM booting, HVM/boot_policy and HVM/boot_params specify the
* boot handling. Only one policy is currently defined: "BIOS order". In
* this case, HVM/boot_params should contain one key-value pair "order" = "N"
* where N is the string that will be passed to QEMU..
*/
@@ -136,7 +139,8 @@ typedef struct xen_vm_record
char *pv_ramdisk;
char *pv_args;
char *pv_bootloader_args;
char *hvm_boot;
char *hvm_boot_policy;
xen_string_string_map *hvm_boot_params;
bool platform_std_vga;
char *platform_serial;
bool platform_localtime;
@@ -490,10 +494,17 @@ xen_vm_get_pv_bootloader_args(xen_session *session, char **result, xen_vm vm);
/**
* Get the HVM/boot field of the given VM.
* Get the HVM/boot_policy field of the given VM.
*/
extern bool
xen_vm_get_hvm_boot(xen_session *session, char **result, xen_vm vm);
xen_vm_get_hvm_boot_policy(xen_session *session, char **result, xen_vm vm);
/**
* Get the HVM/boot_params field of the given VM.
*/
extern bool
xen_vm_get_hvm_boot_params(xen_session *session, xen_string_string_map **result, xen_vm vm);
/**
@@ -731,10 +742,34 @@ xen_vm_set_pv_bootloader_args(xen_session *session, xen_vm vm, char *bootloader_
/**
* Set the HVM/boot field of the given VM.
* Set the HVM/boot_policy field of the given VM.
*/
extern bool
xen_vm_set_hvm_boot(xen_session *session, xen_vm vm, char *boot);
xen_vm_set_hvm_boot_policy(xen_session *session, xen_vm vm, char *boot_policy);
/**
* Set the HVM/boot_params field of the given VM.
*/
extern bool
xen_vm_set_hvm_boot_params(xen_session *session, xen_vm vm, xen_string_string_map *boot_params);
/**
* Add the given key-value pair to the HVM/boot_params field of the
* given VM.
*/
extern bool
xen_vm_add_to_hvm_boot_params(xen_session *session, xen_vm vm, char *key, char *value);
/**
* Remove the given key and its corresponding value from the
* HVM/boot_params field of the given VM. If the key is not in that Map, then
* do nothing.
*/
extern bool
xen_vm_remove_from_hvm_boot_params(xen_session *session, xen_vm vm, char *key);
/**
@@ -45,11 +45,6 @@ enum xen_vm_power_state
*/
XEN_VM_POWER_STATE_SUSPENDED,
/**
* Shutting Down
*/
XEN_VM_POWER_STATE_SHUTTINGDOWN,
/**
* Some other unknown state
*/
+106 -38
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
@@ -86,6 +86,8 @@ static xmlNode *
add_param_struct(xmlNode *);
static xmlNode *
add_struct_array(xmlNode *, const char *);
static xmlNode *
add_nested_struct(xmlNode *, const char *);
static void
add_struct_member(xmlNode *, const char *, const char *, const char *);
static void
@@ -107,6 +109,9 @@ parse_structmap_value(xen_session *, xmlNode *, const abstract_type *,
static size_t size_of_member(const abstract_type *);
static const char *
get_val_as_string(const struct abstract_type *, void *, char *);
void
xen_init(void)
@@ -1174,37 +1179,12 @@ add_struct_value(const struct abstract_type *type, void *value,
switch (type->typename)
{
case REF:
{
arbitrary_record_opt *val = *(arbitrary_record_opt **)value;
if (val != NULL)
{
if (val->is_record)
{
adder(node, key, "string", val->u.record->handle);
}
else
{
adder(node, key, "string", val->u.handle);
}
}
}
break;
case STRING:
{
char *val = *(char **)value;
if (val != NULL)
{
adder(node, key, "string", val);
}
}
break;
case INT:
case ENUM:
{
int64_t val = *(int64_t *)value;
snprintf(buf, sizeof(buf), "%"PRId64, val);
adder(node, key, "string", buf);
const char *val_as_string = get_val_as_string(type, value, buf);
adder(node, key, "string", val_as_string);
}
break;
@@ -1223,13 +1203,6 @@ add_struct_value(const struct abstract_type *type, void *value,
}
break;
case ENUM:
{
int val = *(int *)value;
adder(node, key, "string", type->enum_marshaller(val));
}
break;
case SET:
{
const struct abstract_type *member_type = type->child;
@@ -1251,12 +1224,95 @@ add_struct_value(const struct abstract_type *type, void *value,
break;
case STRUCT:
case MAP:
{
assert(false);
/* XXX Nested structures aren't supported yet, but
fortunately we don't need them, because we don't have
any "deep create" calls. This will need to be
fixed. We don't need maps either. */
fixed. */
}
break;
case MAP:
{
size_t member_size = type->struct_size;
const struct abstract_type *l_type = type->members[0].type;
const struct abstract_type *r_type = type->members[1].type;
int l_offset = type->members[0].offset;
int r_offset = type->members[1].offset;
arbitrary_map *map_val = *(arbitrary_map **)value;
if (map_val != NULL)
{
xmlNode *struct_node = add_nested_struct(node, key);
for (size_t i = 0; i < map_val->size; i++)
{
void *contents = (void *)map_val->contents;
void *l_value = contents + (i * member_size) + l_offset;
void *r_value = contents + (i * member_size) + r_offset;
const char *l_value_as_string =
get_val_as_string(l_type, l_value, buf);
add_struct_value(r_type, r_value, add_struct_member,
l_value_as_string, struct_node);
}
}
}
break;
default:
assert(false);
}
}
static const char *
get_val_as_string(const struct abstract_type *type, void *value, char *buf)
{
switch (type->typename)
{
case REF:
{
arbitrary_record_opt *val = *(arbitrary_record_opt **)value;
if (val != NULL)
{
if (val->is_record)
{
return val->u.record->handle;
}
else
{
return val->u.handle;
}
}
else
{
return NULL;
}
}
break;
case STRING:
{
return *(char **)value;
}
break;
case INT:
{
int64_t val = *(int64_t *)value;
snprintf(buf, sizeof(buf), "%"PRId64, val);
return buf;
}
break;
case ENUM:
{
int val = *(int *)value;
return type->enum_marshaller(val);
}
break;
@@ -1331,7 +1387,19 @@ add_struct_array(xmlNode *struct_node, const char *name)
xmlNode *array_node = add_container(value_node, "array");
return add_container(array_node, "data");
}
static xmlNode *
add_nested_struct(xmlNode *struct_node, const char *name)
{
xmlNode *member_node = add_container(struct_node, "member");
xmlNewChild(member_node, NULL, BAD_CAST "name", BAD_CAST name);
xmlNode *value_node = add_container(member_node, "value");
return add_container(value_node, "struct");
}
+17
View File
@@ -631,6 +631,23 @@ xen_host_reboot(xen_session *session, xen_host host)
}
bool
xen_host_dmesg(xen_session *session, char **result, xen_host host)
{
abstract_value param_values[] =
{
{ .type = &abstract_type_string,
.u.string_val = host }
};
abstract_type result_type = abstract_type_string;
*result = NULL;
XEN_CALL_("host.dmesg");
return session->ok;
}
bool
xen_host_get_all(xen_session *session, struct xen_host_set **result)
{
+4 -2
View File
@@ -25,8 +25,10 @@
xen_int_float_map *
xen_int_float_map_alloc(size_t size)
{
return calloc(1, sizeof(xen_int_float_map) +
size * sizeof(struct xen_int_float_map_contents));
xen_int_float_map *result = calloc(1, sizeof(xen_int_float_map) +
size * sizeof(struct xen_int_float_map_contents));
result->size = size;
return result;
}
+4 -2
View File
@@ -25,8 +25,10 @@
xen_string_string_map *
xen_string_string_map_alloc(size_t size)
{
return calloc(1, sizeof(xen_string_string_map) +
size * sizeof(struct xen_string_string_map_contents));
xen_string_string_map *result = calloc(1, sizeof(xen_string_string_map) +
size * sizeof(struct xen_string_string_map_contents));
result->size = size;
return result;
}
+3
View File
@@ -67,6 +67,9 @@ static const struct_member xen_vdi_record_struct_members[] =
{ .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) },
+79 -8
View File
@@ -145,9 +145,12 @@ static const struct_member xen_vm_record_struct_members[] =
{ .key = "PV_bootloader_args",
.type = &abstract_type_string,
.offset = offsetof(xen_vm_record, pv_bootloader_args) },
{ .key = "HVM_boot",
{ .key = "HVM_boot_policy",
.type = &abstract_type_string,
.offset = offsetof(xen_vm_record, hvm_boot) },
.offset = offsetof(xen_vm_record, hvm_boot_policy) },
{ .key = "HVM_boot_params",
.type = &abstract_type_string_string_map,
.offset = offsetof(xen_vm_record, hvm_boot_params) },
{ .key = "platform_std_VGA",
.type = &abstract_type_bool,
.offset = offsetof(xen_vm_record, platform_std_vga) },
@@ -216,7 +219,8 @@ xen_vm_record_free(xen_vm_record *record)
free(record->pv_ramdisk);
free(record->pv_args);
free(record->pv_bootloader_args);
free(record->hvm_boot);
free(record->hvm_boot_policy);
xen_string_string_map_free(record->hvm_boot_params);
free(record->platform_serial);
free(record->pci_bus);
xen_string_string_map_free(record->tools_version);
@@ -824,7 +828,7 @@ xen_vm_get_pv_bootloader_args(xen_session *session, char **result, xen_vm vm)
bool
xen_vm_get_hvm_boot(xen_session *session, char **result, xen_vm vm)
xen_vm_get_hvm_boot_policy(xen_session *session, char **result, xen_vm vm)
{
abstract_value param_values[] =
{
@@ -835,7 +839,24 @@ xen_vm_get_hvm_boot(xen_session *session, char **result, xen_vm vm)
abstract_type result_type = abstract_type_string;
*result = NULL;
XEN_CALL_("VM.get_HVM_boot");
XEN_CALL_("VM.get_HVM_boot_policy");
return session->ok;
}
bool
xen_vm_get_hvm_boot_params(xen_session *session, xen_string_string_map **result, xen_vm vm)
{
abstract_value param_values[] =
{
{ .type = &abstract_type_string,
.u.string_val = vm }
};
abstract_type result_type = abstract_type_string_string_map;
*result = NULL;
XEN_CALL_("VM.get_HVM_boot_params");
return session->ok;
}
@@ -1376,17 +1397,67 @@ xen_vm_set_pv_bootloader_args(xen_session *session, xen_vm vm, char *bootloader_
bool
xen_vm_set_hvm_boot(xen_session *session, xen_vm vm, char *boot)
xen_vm_set_hvm_boot_policy(xen_session *session, xen_vm vm, char *boot_policy)
{
abstract_value param_values[] =
{
{ .type = &abstract_type_string,
.u.string_val = vm },
{ .type = &abstract_type_string,
.u.string_val = boot }
.u.string_val = boot_policy }
};
xen_call_(session, "VM.set_HVM_boot", param_values, 2, NULL, NULL);
xen_call_(session, "VM.set_HVM_boot_policy", param_values, 2, NULL, NULL);
return session->ok;
}
bool
xen_vm_set_hvm_boot_params(xen_session *session, xen_vm vm, xen_string_string_map *boot_params)
{
abstract_value param_values[] =
{
{ .type = &abstract_type_string,
.u.string_val = vm },
{ .type = &abstract_type_string_string_map,
.u.set_val = (arbitrary_set *)boot_params }
};
xen_call_(session, "VM.set_HVM_boot_params", param_values, 2, NULL, NULL);
return session->ok;
}
bool
xen_vm_add_to_hvm_boot_params(xen_session *session, xen_vm vm, char *key, char *value)
{
abstract_value param_values[] =
{
{ .type = &abstract_type_string,
.u.string_val = vm },
{ .type = &abstract_type_string,
.u.string_val = key },
{ .type = &abstract_type_string,
.u.string_val = value }
};
xen_call_(session, "VM.add_to_HVM_boot_params", param_values, 3, NULL, NULL);
return session->ok;
}
bool
xen_vm_remove_from_hvm_boot_params(xen_session *session, xen_vm vm, char *key)
{
abstract_value param_values[] =
{
{ .type = &abstract_type_string,
.u.string_val = vm },
{ .type = &abstract_type_string,
.u.string_val = key }
};
xen_call_(session, "VM.remove_from_HVM_boot_params", param_values, 2, NULL, NULL);
return session->ok;
}
-1
View File
@@ -32,7 +32,6 @@ static const char *lookup_table[] =
"Paused",
"Running",
"Suspended",
"ShuttingDown",
"Unknown"
};
+89 -17
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
@@ -29,6 +29,7 @@
#include "xen_sr.h"
#include "xen_vbd.h"
#include "xen_vdi.h"
#include "xen_console.h"
#include "xen_vm.h"
@@ -58,7 +59,7 @@ typedef struct
} xen_comms;
static xen_vm create_new_vm(xen_session *session);
static xen_vm create_new_vm(xen_session *session, bool hvm);
static void print_vm_power_state(xen_session *session, xen_vm vm);
@@ -205,6 +206,20 @@ int main(int argc, char **argv)
return 1;
}
char *dmesg;
if (!xen_host_dmesg(session, &dmesg, host))
{
print_error(session);
xen_string_string_map_free(versions);
xen_host_free(host);
xen_vm_record_free(vm_record);
xen_uuid_bytes_free(vm_uuid_bytes);
xen_uuid_free(vm_uuid);
xen_vm_free(vm);
CLEANUP;
return 1;
}
printf("%s.\n", vm_uuid);
fprintf(stderr, "In bytes, the VM UUID is ");
@@ -222,6 +237,8 @@ int main(int argc, char **argv)
versions->contents[i].val);
}
printf("Host dmesg follows:\n%s\n\n", dmesg);
printf("%s.\n", vm_record->uuid);
printf("Resident on %s.\n", (char *)vm_record->resident_on->u.handle);
@@ -243,9 +260,10 @@ int main(int argc, char **argv)
xen_host_free(host);
xen_string_string_map_free(versions);
free(dmesg);
xen_vm new_vm = create_new_vm(session);
xen_vm new_vm = create_new_vm(session, true);
if (!session->ok)
{
/* Error has been logged, just clean up. */
@@ -275,13 +293,28 @@ int main(int argc, char **argv)
* allocation patterns can be used, as long as the allocation and free are
* paired correctly.
*/
static xen_vm create_new_vm(xen_session *session)
static xen_vm create_new_vm(xen_session *session, bool hvm)
{
xen_string_string_map *vcpus_params = xen_string_string_map_alloc(1);
vcpus_params->contents[0].key = strdup("weight");
vcpus_params->contents[0].val = strdup("300");
xen_string_string_map *hvm_boot_params;
if (hvm)
{
hvm_boot_params = xen_string_string_map_alloc(1);
hvm_boot_params->contents[0].key = strdup("order");
hvm_boot_params->contents[0].val = strdup("cd");
}
else
{
hvm_boot_params = NULL;
}
xen_vm_record vm_record =
{
.name_label = "NewVM",
.name_description = "New VM Description",
.name_label = hvm ? "NewHVM" : "NewPV",
.name_description = hvm ? "New HVM VM" : "New PV VM",
.user_version = 1,
.is_a_template = false,
.memory_static_max = 256,
@@ -294,18 +327,18 @@ static xen_vm create_new_vm(xen_session *session)
.actions_after_shutdown = XEN_ON_NORMAL_EXIT_DESTROY,
.actions_after_reboot = XEN_ON_NORMAL_EXIT_RESTART,
.actions_after_crash = XEN_ON_CRASH_BEHAVIOUR_PRESERVE,
.hvm_boot = "",
.pv_bootloader = "pygrub",
.pv_kernel = "/boot/vmlinuz-2.6.16.33-xen",
.pv_ramdisk = "",
.pv_args = "",
.pv_bootloader_args = ""
.hvm_boot_policy = hvm ? "BIOS order" : NULL,
.hvm_boot_params = hvm ? hvm_boot_params : NULL,
.pv_bootloader = hvm ? NULL : "pygrub",
.pv_kernel = hvm ? NULL : "/boot/vmlinuz-2.6.16.33-xen",
};
xen_vm vm;
xen_vm_create(session, &vm, &vm_record);
xen_string_string_map_free(vcpus_params);
xen_string_string_map_free(hvm_boot_params);
if (!session->ok)
{
fprintf(stderr, "VM creation failed.\n");
@@ -368,7 +401,8 @@ static xen_vm create_new_vm(xen_session *session)
.vm = &vm_record_opt,
.vdi = &vdi0_record_opt,
.device = "xvda1",
.mode = XEN_VBD_MODE_RW
.mode = XEN_VBD_MODE_RW,
.bootable = 1,
};
xen_vbd vbd0;
@@ -383,13 +417,38 @@ static xen_vm create_new_vm(xen_session *session)
return NULL;
}
xen_console vnc_console = NULL;
if (hvm) {
xen_console_record vnc_console_record =
{
.protocol = XEN_CONSOLE_PROTOCOL_RFB,
.vm = &vm_record_opt,
};
if (!xen_console_create(session, &vnc_console, &vnc_console_record))
{
fprintf(stderr, "VNC console creation failed.\n");
print_error(session);
xen_vbd_free(vbd0);
xen_vdi_free(vdi0);
xen_sr_set_free(srs);
xen_vm_free(vm);
return NULL;
}
}
char *vm_uuid;
char *vdi0_uuid;
char *vbd0_uuid;
char *vnc_uuid = NULL;
xen_vm_get_uuid(session, &vm_uuid, vm);
xen_vdi_get_uuid(session, &vdi0_uuid, vdi0);
xen_vbd_get_uuid(session, &vbd0_uuid, vbd0);
if (hvm) {
xen_console_get_uuid(session, &vnc_uuid, vnc_console);
}
if (!session->ok)
{
@@ -399,22 +458,35 @@ static xen_vm create_new_vm(xen_session *session)
xen_uuid_free(vm_uuid);
xen_uuid_free(vdi0_uuid);
xen_uuid_free(vbd0_uuid);
xen_uuid_free(vnc_uuid);
xen_vbd_free(vbd0);
xen_vdi_free(vdi0);
xen_console_free(vnc_console);
xen_sr_set_free(srs);
xen_vm_free(vm);
return NULL;
}
fprintf(stderr,
"Created a new VM, with UUID %s, VDI UUID %s, and VBD UUID %s.\n",
vm_uuid, vdi0_uuid, vbd0_uuid);
if (hvm) {
fprintf(stderr,
"Created a new HVM VM, with UUID %s, VDI UUID %s, VBD "
"UUID %s, and VNC console UUID %s.\n",
vm_uuid, vdi0_uuid, vbd0_uuid, vnc_uuid);
}
else {
fprintf(stderr,
"Created a new PV VM, with UUID %s, VDI UUID %s, and VBD "
"UUID %s.\n",
vm_uuid, vdi0_uuid, vbd0_uuid);
}
xen_uuid_free(vm_uuid);
xen_uuid_free(vdi0_uuid);
xen_uuid_free(vbd0_uuid);
xen_uuid_free(vnc_uuid);
xen_vbd_free(vbd0);
xen_vdi_free(vdi0);
xen_console_free(vnc_console);
xen_sr_set_free(srs);
return vm;
+445
View File
@@ -0,0 +1,445 @@
/*
* Copyright (c) 2006 XenSource, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#define _GNU_SOURCE
#include <inttypes.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <libxml/parser.h>
#include <curl/curl.h>
#include "xen_host.h"
#include "xen_sr.h"
#include "xen_vbd.h"
#include "xen_vdi.h"
#include "xen_vm.h"
static void usage()
{
fprintf(stderr,
"Usage:\n"
"\n"
" test_bindings <url> <username> <password>\n"
"\n"
"where\n"
" <url> is a fragment of the server's URL, e.g. localhost:8005/RPC2;\n"
" <username> is the username to use at the server; and\n"
" <password> is the password.\n");
exit(EXIT_FAILURE);
}
static char *url;
typedef struct
{
xen_result_func func;
void *handle;
} xen_comms;
static xen_vm create_new_vm(xen_session *session);
static void print_vm_power_state(xen_session *session, xen_vm vm);
static size_t
write_func(void *ptr, size_t size, size_t nmemb, xen_comms *comms)
{
size_t n = size * nmemb;
return comms->func(ptr, n, comms->handle) ? n : 0;
}
static int
call_func(const void *data, size_t len, void *user_handle,
void *result_handle, xen_result_func result_func)
{
(void)user_handle;
CURL *curl = curl_easy_init();
if (!curl) {
return -1;
}
xen_comms comms = {
.func = result_func,
.handle = result_handle
};
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 1);
curl_easy_setopt(curl, CURLOPT_MUTE, 1);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &write_func);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &comms);
curl_easy_setopt(curl, CURLOPT_POST, 1);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data);
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, len);
CURLcode result = curl_easy_perform(curl);
curl_easy_cleanup(curl);
return result;
}
static void print_error(xen_session *session)
{
fprintf(stderr, "Error: %d", session->error_description_count);
for (int i = 0; i < session->error_description_count; i++)
{
fprintf(stderr, "%s ", session->error_description[i]);
}
fprintf(stderr, "\n");
}
int main(int argc, char **argv)
{
if (argc != 4)
{
usage();
}
url = argv[1];
char *username = argv[2];
char *password = argv[3];
xmlInitParser();
xen_init();
curl_global_init(CURL_GLOBAL_ALL);
#define CLEANUP \
do { \
xen_session_logout(session); \
curl_global_cleanup(); \
xen_fini(); \
xmlCleanupParser(); \
} while(0) \
xen_session *session =
xen_session_login_with_password(call_func, NULL, username, password);
xen_vm vm;
if (!xen_vm_get_by_uuid(session, &vm,
"00000000-0000-0000-0000-000000000000"))
{
print_error(session);
CLEANUP;
return 1;
}
char *vm_uuid;
if (!xen_vm_get_uuid(session, &vm_uuid, vm))
{
print_error(session);
xen_vm_free(vm);
CLEANUP;
return 1;
}
char *vm_uuid_bytes;
if (!xen_uuid_string_to_bytes(vm_uuid, &vm_uuid_bytes))
{
fprintf(stderr, "xen_uuid_string_to_bytes failed.\n");
xen_uuid_free(vm_uuid);
xen_vm_free(vm);
CLEANUP;
return 1;
}
xen_vm_record *vm_record;
if (!xen_vm_get_record(session, &vm_record, vm))
{
print_error(session);
xen_uuid_bytes_free(vm_uuid_bytes);
xen_uuid_free(vm_uuid);
xen_vm_free(vm);
CLEANUP;
return 1;
}
xen_host host;
if (!xen_session_get_this_host(session, &host))
{
print_error(session);
xen_vm_record_free(vm_record);
xen_uuid_bytes_free(vm_uuid_bytes);
xen_uuid_free(vm_uuid);
xen_vm_free(vm);
CLEANUP;
return 1;
}
xen_string_string_map *versions;
if (!xen_host_get_software_version(session, &versions, host))
{
print_error(session);
xen_host_free(host);
xen_vm_record_free(vm_record);
xen_uuid_bytes_free(vm_uuid_bytes);
xen_uuid_free(vm_uuid);
xen_vm_free(vm);
CLEANUP;
return 1;
}
printf("%s.\n", vm_uuid);
fprintf(stderr, "In bytes, the VM UUID is ");
for (int i = 0; i < 15; i++)
{
fprintf(stderr, "%x, ", (unsigned int)vm_uuid_bytes[i]);
}
fprintf(stderr, "%x.\n", (unsigned int)vm_uuid_bytes[15]);
printf("%zd.\n", versions->size);
for (size_t i = 0; i < versions->size; i++)
{
printf("%s -> %s.\n", versions->contents[i].key,
versions->contents[i].val);
}
printf("%s.\n", vm_record->uuid);
printf("Resident on %s.\n", (char *)vm_record->resident_on->u.handle);
printf("%s.\n", xen_vm_power_state_to_string(vm_record->power_state));
for (size_t i = 0; i < vm_record->vcpus_utilisation->size; i++)
{
printf("%"PRId64" -> %lf.\n",
vm_record->vcpus_utilisation->contents[i].key,
vm_record->vcpus_utilisation->contents[i].val);
}
xen_uuid_bytes_free(vm_uuid_bytes);
xen_uuid_free(vm_uuid);
xen_vm_free(vm);
xen_vm_record_free(vm_record);
xen_host_free(host);
xen_string_string_map_free(versions);
xen_vm new_vm = create_new_vm(session);
if (!session->ok)
{
/* Error has been logged, just clean up. */
CLEANUP;
return 1;
}
print_vm_power_state(session, new_vm);
if (!session->ok)
{
/* Error has been logged, just clean up. */
xen_vm_free(new_vm);
CLEANUP;
return 1;
}
xen_vm_free(new_vm);
CLEANUP;
return 0;
}
/**
* Creation of a new VM, using the Named Parameters idiom. Allocate the
* xen_vm_record here, but the sets through the library. Either
* allocation patterns can be used, as long as the allocation and free are
* paired correctly.
*/
static xen_vm create_new_vm(xen_session *session)
{
xen_string_string_map *vcpus_params = xen_string_string_map_alloc(1);
xen_vm_record vm_record =
{
.name_label = "NewHVM",
.name_description = "New HVM Description",
.user_version = 1,
.is_a_template = false,
.memory_static_max = 256,
.memory_dynamic_max = 256,
.memory_dynamic_min = 128,
.memory_static_min = 128,
.vcpus_policy = "credit",
.vcpus_params = vcpus_params,
.vcpus_number = 2,
.actions_after_shutdown = XEN_ON_NORMAL_EXIT_DESTROY,
.actions_after_reboot = XEN_ON_NORMAL_EXIT_RESTART,
.actions_after_crash = XEN_ON_CRASH_BEHAVIOUR_PRESERVE,
.hvm_boot = "cda",
};
xen_vm vm;
xen_vm_create(session, &vm, &vm_record);
if (!session->ok)
{
fprintf(stderr, "VM creation failed.\n");
print_error(session);
return NULL;
}
/*
* Create a new disk for the new VM.
*/
xen_sr_set *srs;
if (!xen_sr_get_by_name_label(session, &srs, "Local") ||
srs->size < 1)
{
fprintf(stderr, "SR lookup failed.\n");
print_error(session);
xen_vm_free(vm);
return NULL;
}
xen_sr_record_opt sr_record =
{
.u.handle = srs->contents[0]
};
xen_vdi_record vdi0_record =
{
.name_label = "MyRootFS",
.name_description = "MyRootFS description",
.sr = &sr_record,
.virtual_size = (1 << 21), // 1GiB / 512 bytes/sector
.sector_size = 512,
.location = "file:/root/gentoo.amd64.hvm.img",
.type = XEN_VDI_TYPE_SYSTEM,
.sharable = false,
.read_only = false
};
xen_vdi vdi0;
if (!xen_vdi_create(session, &vdi0, &vdi0_record))
{
fprintf(stderr, "VDI creation failed.\n");
print_error(session);
xen_sr_set_free(srs);
xen_vm_free(vm);
return NULL;
}
xen_vm_record_opt vm_record_opt =
{
.u.handle = vm
};
xen_vdi_record_opt vdi0_record_opt =
{
.u.handle = vdi0
};
xen_vbd_record vbd0_record =
{
.vm = &vm_record_opt,
.vdi = &vdi0_record_opt,
.device = "xvda1",
.mode = XEN_VBD_MODE_RW
};
xen_vbd vbd0;
if (!xen_vbd_create(session, &vbd0, &vbd0_record))
{
fprintf(stderr, "VBD creation failed.\n");
print_error(session);
xen_vdi_free(vdi0);
xen_sr_set_free(srs);
xen_vm_free(vm);
return NULL;
}
char *vm_uuid;
char *vdi0_uuid;
char *vbd0_uuid;
xen_vm_get_uuid(session, &vm_uuid, vm);
xen_vdi_get_uuid(session, &vdi0_uuid, vdi0);
xen_vbd_get_uuid(session, &vbd0_uuid, vbd0);
if (!session->ok)
{
fprintf(stderr, "get_uuid call failed.\n");
print_error(session);
xen_uuid_free(vm_uuid);
xen_uuid_free(vdi0_uuid);
xen_uuid_free(vbd0_uuid);
xen_vbd_free(vbd0);
xen_vdi_free(vdi0);
xen_sr_set_free(srs);
xen_vm_free(vm);
return NULL;
}
fprintf(stderr,
"Created a new VM, with UUID %s, VDI UUID %s, and VBD UUID %s.\n",
vm_uuid, vdi0_uuid, vbd0_uuid);
xen_uuid_free(vm_uuid);
xen_uuid_free(vdi0_uuid);
xen_uuid_free(vbd0_uuid);
xen_vbd_free(vbd0);
xen_vdi_free(vdi0);
xen_sr_set_free(srs);
return vm;
}
/**
* Print the power state for the given VM.
*/
static void print_vm_power_state(xen_session *session, xen_vm vm)
{
char *vm_uuid;
enum xen_vm_power_state power_state;
if (!xen_vm_get_uuid(session, &vm_uuid, vm))
{
print_error(session);
return;
}
if (!xen_vm_get_power_state(session, &power_state, vm))
{
xen_uuid_free(vm_uuid);
print_error(session);
return;
}
printf("VM %s power state is %s.\n", vm_uuid,
xen_vm_power_state_to_string(power_state));
xen_uuid_free(vm_uuid);
}
+1 -1
View File
@@ -12,7 +12,7 @@ HDRS = $(wildcard *.h)
TARGETS = xenperf xc_shadow
INSTALL_BIN = $(TARGETS) xencons
INSTALL_SBIN = netfix xm xen-bugtool xend xenperf
INSTALL_SBIN = netfix xm xen-bugtool xen-python-path xend xenperf
.PHONY: all
all: build
+41
View File
@@ -0,0 +1,41 @@
#!/usr/bin/env python
# -*- mode: python; -*-
#============================================================================
# This library is free software; you can redistribute it and/or
# modify it under the terms of version 2.1 of the GNU Lesser General Public
# License as published by the Free Software Foundation.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#============================================================================
# Copyright (C) 2007 XenSource Inc.
#============================================================================
# Use the auxbin module in Xend to determine the correct Python path. We
# take the first installed instance of auxbin that we find, and then run it
# to determine the correct path, appending that to sys.path.
AUXBIN = 'xen/util/auxbin.py'
import os
import os.path
import sys
for p in ['python%s' % sys.version[:3], 'python']:
for l in ['/usr/lib64', '/usr/lib']:
d = os.path.join(l, p)
if os.path.exists(os.path.join(d, AUXBIN)):
sys.path.append(d)
import xen.util.auxbin
print os.path.join(xen.util.auxbin.libpath(), p)
sys.exit(0)
print >>sys.stderr, "Cannot find Xen Python modules."
sys.exit(1)
+6 -16
View File
@@ -31,23 +31,13 @@ import signal
import time
import commands
result = commands.getstatusoutput(os.path.join(os.path.dirname(sys.argv[0]),
'xen-python-path'))
if result[0] != 0:
print >>sys.stderr, result[1]
sys.exit(1)
# Use the auxbin module in Xend to determine the correct Python path. We
# take the first installed instance of auxbin that we find, and then run it
# to determine the correct path, appending that to sys.path.
AUXBIN = 'xen/util/auxbin.py'
for p in ['python%s' % sys.version[:3], 'python']:
for l in ['/usr/lib64', '/usr/lib']:
d = os.path.join(l, p)
if os.path.exists(os.path.join(d, AUXBIN)):
sys.path.append(d)
import xen.util.auxbin
libpath = os.path.join(xen.util.auxbin.libpath(), p)
sys.path = sys.path[:-1]
sys.path.append(libpath)
break
sys.path.append(result[1])
from xen.xend.server import SrvDaemon
+4 -1
View File
@@ -197,7 +197,10 @@ class Grub:
self.screen = curses.initscr()
self.screen.timeout(1000)
if hasattr(curses, 'use_default_colors'):
curses.use_default_colors()
try:
curses.use_default_colors()
except:
pass # Not important if we can't use colour
enable_cursor(False)
self.entry_win = curses.newwin(10, 74, 2, 1)
self.text_win = curses.newwin(10, 70, 12, 5)
+2 -7
View File
@@ -13,16 +13,11 @@ vm_cfg = {
'VCPUs_policy': 'credit',
'VCPUs_params': '',
'VCPUs_params': {},
'VCPUs_number': 2,
'VCPUs_features_required': '',
'VCPUs_features_can_use': '',
'VCPUs_features_force_on': '',
'VCPUs_features_force_off': '',
'actions_after_shutdown': 'destroy',
'actions_after_reboot': 'restart',
'actions_after_suspend': 'destroy',
'actions_after_crash': 'destroy',
'PV_bootloader': '',
@@ -44,7 +39,7 @@ vm_cfg = {
local_vdi_cfg = {
'name_label': 'gentoo.hvm',
'name_description': '',
'uri': 'file:/root/gentoo.amd64.hvm.img',
'location': 'file:/root/gentoo.amd64.hvm.img',
'virtual_size': 0,
'sector_size': 0,
'type': 'system',
+3 -8
View File
@@ -15,14 +15,9 @@ vm_cfg = {
'VCPUs_policy': 'credit',
'VCPUs_params': '',
'VCPUs_number': 2,
'VCPUs_features_required': '',
'VCPUs_features_can_use': '',
'VCPUs_features_force_on': '',
'VCPUs_features_force_off': '',
'actions_after_shutdown': 'destroy',
'actions_after_reboot': 'restart',
'actions_after_suspend': 'destroy',
'actions_after_crash': 'destroy',
'PV_bootloader': '',
@@ -65,7 +60,7 @@ vbd_cfg = {
local_vdi_cfg = {
'name_label': 'gentoo.amd64.img',
'name_description': '',
'uri': 'file:/root/gentoo.amd64.img',
'location': 'file:/root/gentoo.amd64.img',
'virtual_size': 0,
'sector_size': 0,
'type': 'system',
@@ -183,13 +178,13 @@ def test_vm_create():
execute(server, 'VM.resume', (session, vm_uuid, False))
print 'Resumed VM.'
finally:
# Wait for user to say we're good to shut it down
while True:
destroy = raw_input('destroy VM? ')
if destroy[0] in ('y', 'Y'):
break
finally:
# Clean up
if vif_uuid:
execute(server, 'VIF.destroy', (session, vif_uuid))
+48 -16
View File
@@ -22,7 +22,7 @@ import sys
import traceback
import threading
from xen.xend import XendDomain, XendDomainInfo, XendNode
from xen.xend import XendDomain, XendDomainInfo, XendNode, XendDmesg
from xen.xend import XendLogging, XendTaskManager
from xen.xend.XendAuthSessions import instance as auth_manager
@@ -615,7 +615,8 @@ class XendAPI(object):
('reboot', None),
('shutdown', None),
('add_to_other_config', None),
('remove_from_other_config', None)]
('remove_from_other_config', None),
('dmesg', 'String')]
host_funcs = [('get_by_name_label', 'Set(host)')]
@@ -674,6 +675,9 @@ class XendAPI(object):
return xen_api_error(XEND_ERROR_HOST_RUNNING)
return xen_api_error(XEND_ERROR_UNSUPPORTED)
def host_dmesg(self, session, host_ref):
return xen_api_success(XendDmesg.instance().info())
def host_get_record(self, session, host_ref):
node = XendNode.instance()
dom = XendDomain.instance()
@@ -737,7 +741,7 @@ class XendAPI(object):
'memory_free',
'host']
host_metrics_attr_rw = []
host_methods = []
host_metrics_methods = []
def _host_metrics_get(self, ref, f):
return xen_api_success(getattr(node, f)())
@@ -974,7 +978,8 @@ class XendAPI(object):
'PV_ramdisk',
'PV_args',
'PV_bootloader_args',
'HVM_boot',
'HVM_boot_policy',
'HVM_boot_params',
'platform_std_VGA',
'platform_serial',
'platform_localtime',
@@ -1020,7 +1025,8 @@ class XendAPI(object):
'PV_ramdisk',
'PV_args',
'PV_bootloader_args',
'HVM_boot',
'HVM_boot_policy',
'HVM_boot_params',
'platform_std_VGA',
'platform_serial',
'platform_localtime',
@@ -1121,11 +1127,11 @@ class XendAPI(object):
def VM_get_VCPUs_policy(self, session, vm_ref):
dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
return dom.get_vcpus_policy()
return xen_api_success(dom.get_vcpus_policy())
def VM_get_VCPUs_params(self, session, vm_ref):
dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
return xen_api_todo() # need access to scheduler
return xen_api_success(dom.get_vcpus_params())
def VM_get_actions_after_shutdown(self, session, vm_ref):
dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
@@ -1158,8 +1164,11 @@ class XendAPI(object):
def VM_get_PV_bootloader_args(self, session, vm_ref):
return self.VM_get('PV_bootloader_args', session, vm_ref)
def VM_get_HVM_boot(self, session, vm_ref):
return self.VM_get('HVM_boot', session, vm_ref)
def VM_get_HVM_boot_policy(self, session, vm_ref):
return self.VM_get('HVM_boot_policy', session, vm_ref)
def VM_get_HVM_boot_params(self, session, vm_ref):
return self.VM_get('HVM_boot_params', session, vm_ref)
def VM_get_platform_std_VGA(self, session, vm_ref):
dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
@@ -1186,7 +1195,7 @@ class XendAPI(object):
return xen_api_success(dom.get_platform_keymap())
def VM_get_other_config(self, session, vm_ref):
return self.VM_get('otherconfig', session, vm_ref)
return self.VM_get('other_config', session, vm_ref)
def VM_get_is_control_domain(self, session, vm_ref):
xd = XendDomain.instance()
@@ -1246,8 +1255,30 @@ class XendAPI(object):
return xen_api_error(['VM_ON_CRASH_BEHAVIOUR_INVALID', vm_ref])
return self.VM_set('actions_after_crash', session, vm_ref, action)
def VM_set_HVM_boot(self, session, vm_ref, value):
return self.VM_set('HVM_boot', session, vm_ref, value)
def VM_set_HVM_boot_policy(self, session, vm_ref, value):
if value != "" and value != "BIOS order":
return xen_api_error(
['VALUE_NOT_SUPPORTED', 'VM.HVM_boot_policy', value,
'Xend supports only the "BIOS order" boot policy.'])
else:
return self.VM_set('HVM_boot_policy', session, vm_ref, value)
def VM_set_HVM_boot_params(self, session, vm_ref, value):
return self.VM_set('HVM_boot_params', session, vm_ref, value)
def VM_add_to_HVM_boot_params(self, session, vm_ref, key, value):
dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
if 'HVM_boot_params' not in dom.info:
dom.info['HVM_boot_params'] = {}
dom.info['HVM_boot_params'][key] = value
return xen_api_success_void()
def VM_remove_from_HVM_boot_params(self, session, vm_ref, key):
dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
if 'HVM_boot_params' in dom.info \
and key in dom.info['HVM_boot_params']:
del dom.info['HVM_boot_params'][key]
return xen_api_success_void()
def VM_set_PV_bootloader(self, session, vm_ref, value):
return self.VM_set('PV_bootloader', session, vm_ref, value)
@@ -1354,7 +1385,8 @@ class XendAPI(object):
'PV_ramdisk': xeninfo.info.get('PV_ramdisk'),
'PV_args': xeninfo.info.get('PV_args'),
'PV_bootloader_args': xeninfo.info.get('PV_bootloader_args'),
'HVM_boot': xeninfo.info.get('HVM_boot'),
'HVM_boot_policy': xeninfo.info.get('HVM_boot_policy'),
'HVM_boot_params': xeninfo.info.get('HVM_boot_params'),
'platform_std_VGA': xeninfo.get_platform_std_vga(),
'platform_serial': xeninfo.get_platform_serial(),
'platform_localtime': xeninfo.get_platform_localtime(),
@@ -1363,7 +1395,7 @@ class XendAPI(object):
'platform_keymap': xeninfo.get_platform_keymap(),
'PCI_bus': xeninfo.get_pci_bus(),
'tools_version': xeninfo.get_tools_version(),
'other_config': xeninfo.info.get('otherconfig'),
'other_config': xeninfo.info.get('other_config', {}),
'is_control_domain': xeninfo == xendom.privilegedDomain(),
}
return xen_api_success(record)
@@ -1469,7 +1501,7 @@ class XendAPI(object):
vdi = XendNode.instance().get_vdi_by_uuid(vdi_ref)
if not vdi:
return xen_api_error(['VDI_HANDLE_INVALID', vdi_ref])
vdi_image = vdi.get_image_uri()
vdi_image = vdi.get_location()
vbd_ref = XendTask.log_progress(0, 100,
dom.create_vbd,
vbd_struct, vdi_image)
@@ -1622,7 +1654,7 @@ class XendAPI(object):
xendom = XendDomain.instance()
return xen_api_success(xendom.get_dev_property_by_uuid('vif', vif_ref,
'io_write_kbs'))
def VIF_get_all(self, session):
xendom = XendDomain.instance()
vifs = [d.get_vifs() for d in XendDomain.instance().list('all')]
+2 -10
View File
@@ -12,7 +12,7 @@
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#============================================================================
# Copyright (C) 2006 XenSource Ltd.
# Copyright (C) 2006-2007 XenSource Ltd.
#============================================================================
#
@@ -24,7 +24,7 @@ XEN_API_VM_POWER_STATE = [
'Paused',
'Running',
'Suspended',
'ShuttingDown',
'Halted',
'Unknown'
]
@@ -49,16 +49,8 @@ XEN_API_ON_CRASH_BEHAVIOUR = [
'rename_restart'
]
XEN_API_BOOT_TYPE = [
'bios',
'grub',
'kernel_external',
'kernel_internal'
]
XEN_API_VBD_MODE = ['RO', 'RW']
XEN_API_VDI_TYPE = ['system', 'user', 'ephemeral']
XEN_API_DRIVER_TYPE = ['ioemu', 'paravirtualised']
XEN_API_VBD_TYPE = ['CD', 'Disk']
XEN_API_TASK_STATUS_TYPE = ['pending', 'success', 'failure']
XEN_API_CONSOLE_PROTOCOL = ['vt100', 'rfb', 'rdp']
+3 -1
View File
@@ -97,7 +97,9 @@ def bootloader(blexec, disk, dom, quiet = False, blargs = '', kernel = '',
try:
log.debug("Launching bootloader as %s." % str(args))
os.execvp(args[0], args)
env = os.environ.copy()
env['TERM'] = 'vt100'
os.execvpe(args[0], args, env)
except OSError, e:
print e
pass
+70 -34
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.WARN)
log.setLevel(logging.DEBUG)
"""
@@ -125,8 +125,7 @@ XENAPI_HVM_CFG = {
'platform_std_vga': 'stdvga',
'platform_serial' : 'serial',
'platform_localtime': 'localtime',
'platform_keymap' : 'keymap',
'HVM_boot': 'boot',
'platform_keymap' : 'keymap'
}
# List of XendConfig configuration keys that have no direct equivalent
@@ -147,24 +146,19 @@ XENAPI_CFG_TYPES = {
'memory_actual': int,
'cpus': list,
'vcpus_policy': str,
'vcpus_params': str,
'vcpus_params': dict,
'vcpus_number': int,
'vcpus_features_required': list,
'vcpus_features_can_use': list,
'vcpus_features_force_on': list,
'vcpus_features_force_off': list,
'actions_after_shutdown': str,
'actions_after_reboot': str,
'actions_after_suspend': str,
'actions_after_crash': str,
'tpm_instance': int,
'tpm_backend': int,
'PV_bootloader': str,
'PV_kernel': str,
'PV_ramdisk': str,
'PV_args': str,
'PV_bootloader_args': str,
'HVM_boot': str,
'HVM_boot_policy': str,
'HVM_boot_params': dict,
'platform_std_vga': bool0,
'platform_serial': str,
'platform_localtime': bool0,
@@ -349,7 +343,6 @@ class XendConfig(dict):
def _defaults(self):
defaults = {
'uuid': uuid.createString(),
'name_label': 'Domain-Unnamed',
'actions_after_shutdown': 'destroy',
'actions_after_reboot': 'restart',
@@ -361,7 +354,8 @@ class XendConfig(dict):
'PV_ramdisk': '',
'PV_args': '',
'PV_bootloader_args': '',
'HVM_boot': '',
'HVM_boot_policy': '',
'HVM_boot_params': {},
'memory_static_min': 0,
'memory_dynamic_min': 0,
'shadow_memory': 0,
@@ -377,6 +371,7 @@ class XendConfig(dict):
'cpu_weight': 256,
'cpu_cap': 0,
'vcpus_number': 1,
'vcpus_params': {},
'console_refs': [],
'vif_refs': [],
'vbd_refs': [],
@@ -384,7 +379,6 @@ class XendConfig(dict):
'other_config': {},
}
defaults['name_label'] = 'Domain-' + defaults['uuid']
return defaults
def _memory_sanity_check(self):
@@ -414,13 +408,21 @@ class XendConfig(dict):
def _uuid_sanity_check(self):
"""Make sure UUID is in proper string format with hyphens."""
self['uuid'] = uuid.toString(uuid.fromString(self['uuid']))
if 'uuid' not in self or not self['uuid']:
self['uuid'] = uuid.createString()
else:
self['uuid'] = uuid.toString(uuid.fromString(self['uuid']))
def _name_sanity_check(self):
if 'name_label' not in self:
self['name_label'] = 'Domain-' + self['uuid']
def validate(self):
self._uuid_sanity_check()
self._name_sanity_check()
self._memory_sanity_check()
self._actions_sanity_check()
self._vcpus_sanity_check()
self._uuid_sanity_check()
def _dominfo_to_xapi(self, dominfo):
self['domid'] = dominfo['domid']
@@ -496,6 +498,12 @@ class XendConfig(dict):
log.warn("Unable to parse key %s: %s: %s" %
(key, str(val), e))
# Compatibility hack -- can go soon.
boot_order = sxp.child_value(sxp_cfg, 'HVM_boot')
if boot_order:
cfg['HVM_boot_policy'] = 'BIOS order'
cfg['HVM_boot_params'] = { 'order' : boot_order }
# Parsing the device SXP's. In most cases, the SXP looks
# like this:
#
@@ -671,6 +679,9 @@ class XendConfig(dict):
if self['devices'][console_uuid][1].get('protocol') == 'rfb':
has_rfb = True
break
if self['devices'][console_uuid][0] == 'vfb':
has_rfb = True
break
if not has_rfb:
dev_config = ['vfb']
@@ -724,6 +735,7 @@ class XendConfig(dict):
val = sxp.child_value(image_sxp, imgkey, None)
if val != None:
self[apikey] = val
self._hvm_boot_params_from_sxp(image_sxp)
# extract backend value
@@ -768,7 +780,7 @@ class XendConfig(dict):
if 'image' in xapi_dict:
self['image'].update(xapi_dict['image'])
else:
hvm = self['HVM_boot'] != ''
hvm = self['HVM_boot_policy'] != ''
self['image']['type'] = hvm and 'hvm' or 'linux'
if hvm:
self['image']['hvm'] = {'devices': {}}
@@ -829,8 +841,6 @@ class XendConfig(dict):
else:
self[key] = val
self.validate()
def to_sxp(self, domain = None, ignore_devices = False, ignore = [],
legacy_only = True):
""" Get SXP representation of this config object.
@@ -854,9 +864,13 @@ class XendConfig(dict):
sxpr.append(['domid', domain.getDomid()])
if not legacy_only:
for name in XENAPI_CFG_TYPES.keys():
for name, typ in XENAPI_CFG_TYPES.items():
if name in self and self[name] not in (None, []):
sxpr.append([name, str(self[name])])
if typ == dict:
s = self[name].items()
else:
s = str(self[name])
sxpr.append([name, s])
for xenapi, legacy in XENAPI_CFG_TO_LEGACY_CFG.items():
if self.has_key(xenapi) and self[xenapi] not in (None, []):
@@ -905,7 +919,7 @@ class XendConfig(dict):
# store as part of the device config.
dev_uuid = sxp.child_value(config, 'uuid')
dev_type, dev_cfg = self['devices'][dev_uuid]
is_bootable = dev_cfg.get('bootable', False)
is_bootable = dev_cfg.get('bootable', 0)
config.append(['bootable', int(is_bootable)])
sxpr.append(['device', config])
@@ -978,14 +992,16 @@ class XendConfig(dict):
pass
if dev_type == 'vbd':
dev_info['bootable'] = False
dev_info['bootable'] = 0
if dev_info.get('dev', '').startswith('ioemu:'):
dev_info['driver'] = 'ioemu'
else:
dev_info['driver'] = 'paravirtualised'
# create uuid if it doesn't exist
dev_uuid = dev_info.get('uuid', uuid.createString())
dev_uuid = dev_info.get('uuid', None)
if not dev_uuid:
dev_uuid = uuid.createString()
dev_info['uuid'] = dev_uuid
# store dev references by uuid for certain device types
@@ -998,7 +1014,7 @@ class XendConfig(dict):
if dev_type == 'vbd' and not target[param]:
# Compat hack -- this is the first disk, so mark it
# bootable.
dev_info['bootable'] = True
dev_info['bootable'] = 1
target[param].append(dev_uuid)
elif dev_type == 'tap':
if 'vbd_refs' not in target:
@@ -1007,7 +1023,7 @@ class XendConfig(dict):
if not target['vbd_refs']:
# Compat hack -- this is the first disk, so mark it
# bootable.
dev_info['bootable'] = True
dev_info['bootable'] = 1
target['vbd_refs'].append(dev_uuid)
elif dev_type == 'vfb':
@@ -1055,7 +1071,9 @@ class XendConfig(dict):
if cfg_xenapi.get('name'):
dev_info['name'] = cfg_xenapi.get('name')
dev_uuid = cfg_xenapi.get('uuid', uuid.createString())
dev_uuid = cfg_xenapi.get('uuid', None)
if not dev_uuid:
dev_uuid = uuid.createString()
dev_info['uuid'] = dev_uuid
target['devices'][dev_uuid] = (dev_type, dev_info)
target['vif_refs'].append(dev_uuid)
@@ -1070,8 +1088,8 @@ class XendConfig(dict):
dev_info['uname'] = cfg_xenapi.get('image', '')
dev_info['dev'] = '%s:%s' % (cfg_xenapi.get('device'),
old_vbd_type)
dev_info['bootable'] = cfg_xenapi.get('bootable', False)
dev_info['driver'] = cfg_xenapi.get('driver')
dev_info['bootable'] = int(cfg_xenapi.get('bootable', 0))
dev_info['driver'] = cfg_xenapi.get('driver', '')
dev_info['VDI'] = cfg_xenapi.get('VDI', '')
if cfg_xenapi.get('mode') == 'RW':
@@ -1079,7 +1097,9 @@ class XendConfig(dict):
else:
dev_info['mode'] = 'r'
dev_uuid = cfg_xenapi.get('uuid', uuid.createString())
dev_uuid = cfg_xenapi.get('uuid', None)
if not dev_uuid:
dev_uuid = uuid.createString()
dev_info['uuid'] = dev_uuid
target['devices'][dev_uuid] = (dev_type, dev_info)
target['vbd_refs'].append(dev_uuid)
@@ -1088,13 +1108,17 @@ class XendConfig(dict):
if cfg_xenapi.get('type'):
dev_info['type'] = cfg_xenapi.get('type')
dev_uuid = cfg_xenapi.get('uuid', uuid.createString())
dev_uuid = cfg_xenapi.get('uuid', None)
if not dev_uuid:
dev_uuid = uuid.createString()
dev_info['uuid'] = dev_uuid
target['devices'][dev_uuid] = (dev_type, dev_info)
target['vtpm_refs'].append(dev_uuid)
elif dev_type == 'console':
dev_uuid = cfg_xenapi.get('uuid', uuid.createString())
dev_uuid = cfg_xenapi.get('uuid', None)
if not dev_uuid:
dev_uuid = uuid.createString()
dev_info['uuid'] = dev_uuid
dev_info['protocol'] = cfg_xenapi.get('protocol', 'rfb')
dev_info['other_config'] = cfg_xenapi.get('other_config', {})
@@ -1223,7 +1247,12 @@ class XendConfig(dict):
"configuration dictionary.")
sxpr.append(dev_type)
config = [(opt, val) for opt, val in dev_info.items()]
if dev_type in ('console', 'vfb'):
config = [(opt, val) for opt, val in dev_info.items()
if opt != 'other_config']
else:
config = [(opt, val) for opt, val in dev_info.items()]
sxpr += config
return sxpr
@@ -1356,12 +1385,19 @@ class XendConfig(dict):
val = sxp.child_value(image_sxp, imgkey, None)
if val != None:
type_conv = XENAPI_CFG_TYPES[apikey]
if callable(conv):
if callable(type_conv):
self[apikey] = type_conv(val)
else:
self[apikey] = val
self._hvm_boot_params_from_sxp(image_sxp)
def _hvm_boot_params_from_sxp(self, image_sxp):
boot = sxp.child_value(image_sxp, 'boot', None)
if boot is not None:
self['HVM_boot_policy'] = 'BIOS order'
self['HVM_boot_params'] = { 'order' : boot }
#
# debugging
+8 -3
View File
@@ -1648,14 +1648,15 @@ class XendDomainInfo:
kernel = self.info['PV_kernel']
ramdisk = self.info['PV_ramdisk']
args = self.info['PV_args']
boot = self.info['HVM_boot']
boot = self.info['HVM_boot_policy']
if boot:
# HVM booting.
self.info['image']['type'] = 'hvm'
if not 'devices' in self.info['image']:
self.info['image']['devices'] = {}
self.info['image']['devices']['boot'] = boot
self.info['image']['devices']['boot'] = \
self.info['HVM_boot_params'].get('order', 'dc')
elif not blexec and kernel:
# Boot from dom0. Nothing left to do -- the kernel and ramdisk
# will be picked up by image.py.
@@ -1976,7 +1977,11 @@ class XendDomainInfo:
else:
return 'unknown'
def get_vcpus_params(self):
return '' # TODO
if self.getDomid() is None:
return self.info['vcpus_params']
retval = xc.sched_credit_domain_get(self.getDomid())
return retval
def get_power_state(self):
return XEN_API_VM_POWER_STATE[self.state]
def get_platform_std_vga(self):
+9 -6
View File
@@ -73,6 +73,7 @@ class XendVDI(AutoSaveObject):
self.sharable = False
self.read_only = False
self.type = "system"
self.location = ''
def load_config_dict(self, cfg):
"""Loads configuration into the object from a dict.
@@ -147,9 +148,10 @@ class XendVDI(AutoSaveObject):
'sharable': False,
'readonly': False,
'SR': self.sr_uuid,
'location': self.get_location(),
'VBDs': []}
def get_image_uri(self):
def get_location(self):
raise NotImplementedError()
@@ -163,9 +165,10 @@ class XendQCoWVDI(XendVDI):
self.virtual_size = vsize
self.sector_size = 512
self.auto_save = True
self.location = 'tap:qcow:%s' % self.qcow_path
def get_image_uri(self):
return 'tap:qcow:%s' % self.qcow_path
def get_location(self):
return self.location
class XendLocalVDI(XendVDI):
def __init__(self, vdi_struct):
@@ -183,7 +186,7 @@ class XendLocalVDI(XendVDI):
self.type = vdi_struct.get('type', '')
self.sharable = vdi_struct.get('sharable', False)
self.read_only = vdi_struct.get('read_only', False)
self.image_uri = vdi_struct.get('uri', 'file:/dev/null')
self.location = vdi_struct.get('location', 'file:/dev/null')
def get_image_uri(self):
return self.image_uri
def get_location(self):
return self.location
+37 -35
View File
@@ -449,48 +449,50 @@ class HVMImageHandler(ImageHandler):
return ret
vnc_config = {}
has_vfb = False
has_vnc = int(vmConfig['image'].get('vnc')) != 0
has_vnc = int(vmConfig['image'].get('vnc', 0)) != 0
has_sdl = int(vmConfig['image'].get('sdl', 0)) != 0
for dev_uuid in vmConfig['console_refs']:
dev_type, dev_info = vmConfig['devices'][devuuid]
if dev_type == 'rfb':
dev_type, dev_info = vmConfig['devices'][dev_uuid]
if dev_type == 'vfb':
vnc_config = dev_info.get('other_config', {})
has_vfb = True
has_vnc = True
break
if not vnc_config:
for key in ('vncunused', 'vnclisten', 'vncdisplay', 'vncpasswd'):
if key in vmConfig['image']:
vnc_config[key] = vmConfig['image'][key]
if has_vnc:
if not vnc_config:
for key in ('vncunused', 'vnclisten', 'vncdisplay',
'vncpasswd'):
if key in vmConfig['image']:
vnc_config[key] = vmConfig['image'][key]
if not has_vfb and not has_vnc:
ret.append('-nographic')
return ret
if not vnc_config.get('vncunused', 0) and \
vnc_config.get('vncdisplay', 0):
ret.append('-vnc')
ret.append(str(vncdisplay))
else:
ret.append('-vncunused')
if not vnc_config.get('vncunused', 0) and \
vnc_config.get('vncdisplay', 0):
ret.append('-vnc')
ret.append(str(vncdisplay))
vnclisten = vnc_config.get('vnclisten',
xenopts().get_vnclisten_address())
ret.append('-vnclisten')
ret.append(str(vnclisten))
# Store vncpassword in xenstore
vncpasswd = vnc_config.get('vncpasswd')
if not vncpasswd:
vncpasswd = xenopts().get_vncpasswd_default()
if vncpasswd is None:
raise VmError('vncpasswd is not setup in vmconfig or '
'xend-config.sxp')
if vncpasswd != '':
self.vm.storeVm('vncpasswd', vncpasswd)
elif has_sdl:
# SDL is default in QEMU.
pass
else:
ret.append('-vncunused')
vnclisten = vnc_config.get('vnclisten',
xenopts().get_vnclisten_address())
ret.append('-vnclisten')
ret.append(str(vnclisten))
# Store vncpassword in xenstore
vncpasswd = vnc_config.get('vncpasswd')
if not vncpasswd:
vncpasswd = xenopts().get_vncpasswd_default()
if vncpasswd is None:
raise VmError('vncpasswd is not setup in vmconfig or '
'xend-config.sxp')
if vncpasswd != '':
self.vm.storeVm('vncpasswd', vncpasswd)
ret.append('-nographic')
return ret
+7 -7
View File
@@ -46,7 +46,7 @@ class VfbifController(DevController):
def createDevice(self, config):
DevController.createDevice(self, config)
if self.vm.info.get('HVM_boot'):
if self.vm.info.get('HVM_boot_policy'):
# is HVM, so qemu-dm will handle the vfb.
return
@@ -90,7 +90,7 @@ class VfbifController(DevController):
def waitForDevice(self, devid):
if self.vm.info.get('HVM_boot'):
if self.vm.info.get('HVM_boot_policy'):
log.debug('skip waiting for HVM vfb')
# is a qemu-dm managed device, don't wait for hotplug for these.
return
@@ -110,7 +110,7 @@ class VfbifController(DevController):
raise VmError('Refusing to reconfigure device vfb:%d' % devid)
def destroyDevice(self, devid, force):
if self.vm.info.get('HVM_boot'):
if self.vm.info.get('HVM_boot_policy'):
# remove the backend xenstore entries for HVM guests no matter
# what
DevController.destroyDevice(self, devid, True)
@@ -119,7 +119,7 @@ class VfbifController(DevController):
def migrate(self, deviceConfig, network, dst, step, domName):
if self.vm.info.get('HVM_boot'):
if self.vm.info.get('HVM_boot_policy'):
return 0
return DevController.migrate(self, deviceConfig, network, dst, step,
domName)
@@ -136,14 +136,14 @@ class VkbdifController(DevController):
return (devid, back, front)
def waitForDevice(self, config):
if self.vm.info.get('HVM_boot'):
if self.vm.info.get('HVM_boot_policy'):
# is a qemu-dm managed device, don't wait for hotplug for these.
return
DevController.waitForDevice(self, config)
def destroyDevice(self, devid, force):
if self.vm.info.get('HVM_boot'):
if self.vm.info.get('HVM_boot_policy'):
# remove the backend xenstore entries for HVM guests no matter
# what
DevController.destroyDevice(self, devid, True)
@@ -151,7 +151,7 @@ class VkbdifController(DevController):
DevController.destroyDevice(self, devid, force)
def migrate(self, deviceConfig, network, dst, step, domName):
if self.vm.info.get('HVM_boot'):
if self.vm.info.get('HVM_boot_policy'):
return 0
return DevController.migrate(self, deviceConfig, network, dst, step,
domName)
+4 -1
View File
@@ -19,7 +19,7 @@
msgid ""
msgstr ""
"Project-Id-Version: Xen-xm 3.0\n"
"PO-Revision-Date: 2007-01-30 17:15+0000\n"
"PO-Revision-Date: 2007-01-31 12:34+0000\n"
"Last-Translator: Ewan Mellor <ewan@xensource.com>\n"
"Language-Team: xen-devel <xen-devel@lists.xensource.com>\n"
"MIME-Version: 1.0\n"
@@ -41,6 +41,9 @@ msgstr "The method %(1)s takes %(2)s argument(s) (%(3)s given)."
msgid "SESSION_AUTHENTICATION_FAILED"
msgstr "Permission denied."
msgid "VALUE_NOT_SUPPORTED"
msgstr "Value \"%(2)s\" for %(1)s is not supported by this server. The server said \"%(3)s\"."
msgid "HOST_CPU_HANDLE_INVALID"
msgstr "The host_cpu handle %(1)s is invalid."
+2 -2
View File
@@ -72,8 +72,8 @@ int main(int argc, char **argv)
usize = xc_dom_check_gzip(image, st.st_size);
if (usize)
{
tmp = malloc(size);
xc_dom_do_gunzip(image, st.st_size, tmp, size);
tmp = malloc(usize);
xc_dom_do_gunzip(image, st.st_size, tmp, usize);
image = tmp;
size = usize;
}
+3 -1
View File
@@ -11,10 +11,12 @@ AC_PROG_CC
#AC_PROG_INSTALL
AC_CHECK_PROG([LILO], lilo, lilo, "no", [$PATH])
XEN_PYTHON_PATH=$(/usr/sbin/xen-python-path)
# Right now, we can assume that the lib/ directory
# is two levels above the tests
TESTLIB=../../lib
TENV="PYTHONPATH=$PYTHONPATH:$TESTLIB"
TENV="PYTHONPATH=$PYTHONPATH:$TESTLIB:$XEN_PYTHON_PATH"
AC_ARG_ENABLE(hvm-support,
[[ --enable-hvm-support enable hardware virtual machine assist]],
+3
View File
@@ -33,6 +33,9 @@ from DomainTracking import *
from acm import *
DOM0_UUID = "00000000-0000-0000-0000-000000000000"
def getDefaultKernel():
return arch.getDefaultKernel()
-20
View File
@@ -3,26 +3,6 @@
# Author: Dan Smith <danms@us.ibm.com>
#
import os.path
import sys
# Use the auxbin module in Xend to determine the correct Python path. We
# take the first installed instance of auxbin that we find, and then run it
# to determine the correct path, appending that to sys.path.
AUXBIN = 'xen/util/auxbin.py'
for p in ['python%s' % sys.version[:3], 'python']:
for l in ['/usr/lib64', '/usr/lib']:
d = os.path.join(l, p)
if os.path.exists(os.path.join(d, AUXBIN)):
sys.path.append(d)
import xen.util.auxbin
libpath = xen.util.auxbin.libpath()
sys.path = sys.path[:-1]
sys.path.append(libpath)
break
from Console import *
from Test import *
from Xm import *
+1 -2
View File
@@ -13,7 +13,6 @@
from XmTestLib import xapi
from XmTestLib.XenAPIDomain import XmTestAPIDomain
from XmTestLib import *
from xen.xend import XendDomain
from vtpm_utils import *
import commands
import os
@@ -28,7 +27,7 @@ except Exception, e:
vm_uuid = domain.get_uuid()
vtpmcfg = {}
vtpmcfg['backend'] = XendDomain.DOM0_UUID
vtpmcfg['backend'] = DOM0_UUID
vtpmcfg['VM'] = vm_uuid
session = xapi.connect()
+1 -1
View File
@@ -159,7 +159,7 @@ static void __init dmi_save_ident(struct dmi_header *dm, int slot, int string)
return;
dmi_ident[slot] = alloc_bootmem(strlen(p)+1);
if(dmi_ident[slot])
safe_strcpy(dmi_ident[slot], p);
strlcpy(dmi_ident[slot], p, strlen(p)+1);
else
printk(KERN_ERR "dmi_save_ident: out of memory.\n");
}
+32 -30
View File
@@ -288,71 +288,73 @@ long arch_do_domctl(
case XEN_DOMCTL_sethvmcontext:
{
struct hvm_domain_context *c;
struct hvm_domain_context c;
struct domain *d;
c.cur = 0;
c.size = domctl->u.hvmcontext.size;
c.data = NULL;
ret = -ESRCH;
if ( (d = get_domain_by_id(domctl->domain)) == NULL )
break;
ret = -ENOMEM;
if ( (c = xmalloc(struct hvm_domain_context)) == NULL )
goto sethvmcontext_out;
ret = -EFAULT;
if ( copy_from_guest(c, domctl->u.hvmcontext.ctxt, 1) != 0 )
goto sethvmcontext_out;
c->size = sizeof (c->data);
c->cur = 0;
ret = -EINVAL;
if ( !is_hvm_domain(d) )
goto sethvmcontext_out;
ret = hvm_load(d, c);
ret = -ENOMEM;
if ( (c.data = xmalloc_bytes(c.size)) == NULL )
goto sethvmcontext_out;
xfree(c);
ret = -EFAULT;
if ( copy_from_guest(c.data, domctl->u.hvmcontext.buffer, c.size) != 0)
goto sethvmcontext_out;
ret = hvm_load(d, &c);
sethvmcontext_out:
put_domain(d);
if ( c.data != NULL )
xfree(c.data);
put_domain(d);
}
break;
case XEN_DOMCTL_gethvmcontext:
{
struct hvm_domain_context *c;
struct hvm_domain_context c;
struct domain *d;
c.cur = 0;
c.size = domctl->u.hvmcontext.size;
c.data = NULL;
ret = -ESRCH;
if ( (d = get_domain_by_id(domctl->domain)) == NULL )
break;
ret = -ENOMEM;
if ( (c = xmalloc(struct hvm_domain_context)) == NULL )
goto gethvmcontext_out;
memset(c, 0, sizeof(*c));
c->size = sizeof (c->data);
ret = -ENODATA;
ret = -EINVAL;
if ( !is_hvm_domain(d) )
goto gethvmcontext_out;
ret = 0;
if (hvm_save(d, c) != 0)
ret = -EFAULT;
if ( copy_to_guest(domctl->u.hvmcontext.ctxt, c, 1) )
ret = -EFAULT;
ret = -ENOMEM;
if ( (c.data = xmalloc_bytes(c.size)) == NULL )
goto gethvmcontext_out;
xfree(c);
ret = hvm_save(d, &c);
if ( copy_to_guest(domctl->u.hvmcontext.buffer, c.data, c.size) != 0 )
ret = -EFAULT;
if ( copy_to_guest(u_domctl, domctl, 1) )
ret = -EFAULT;
gethvmcontext_out:
put_domain(d);
if ( c.data != NULL )
xfree(c.data);
put_domain(d);
}
break;
+36 -6
View File
@@ -279,7 +279,7 @@ static void hpet_write(
(h->hpet.timers[tn].config & HPET_TN_SETVAL) )
h->hpet.timers[tn].cmp = new_val;
else
h->period[tn] = new_val;
h->hpet.period[tn] = new_val;
h->hpet.timers[tn].config &= ~HPET_TN_SETVAL;
if ( hpet_enabled(h) && timer_enabled(h, tn) )
hpet_set_timer(h, tn);
@@ -289,7 +289,7 @@ static void hpet_write(
case HPET_T1_ROUTE:
case HPET_T2_ROUTE:
tn = (addr - HPET_T0_ROUTE) >> 5;
h->hpet.timers[tn].hpet_fsb[0] = new_val;
h->hpet.timers[tn].fsb = new_val;
break;
default:
@@ -351,21 +351,22 @@ static void hpet_timer_fn(void *opaque)
hpet_route_interrupt(h, tn);
if ( timer_is_periodic(h, tn) && (h->period[tn] != 0) )
if ( timer_is_periodic(h, tn) && (h->hpet.period[tn] != 0) )
{
uint64_t mc = hpet_read_maincounter(h);
if ( timer_is_32bit(h, tn) )
{
while ( hpet_time_after(mc, h->hpet.timers[tn].cmp) )
h->hpet.timers[tn].cmp = (uint32_t)(
h->hpet.timers[tn].cmp + h->period[tn]);
h->hpet.timers[tn].cmp + h->hpet.period[tn]);
}
else
{
while ( hpet_time_after64(mc, h->hpet.timers[tn].cmp) )
h->hpet.timers[tn].cmp += h->period[tn];
h->hpet.timers[tn].cmp += h->hpet.period[tn];
}
set_timer(&h->timers[tn], NOW() + hpet_tick_to_ns(h, h->period[tn]));
set_timer(&h->timers[tn],
NOW() + hpet_tick_to_ns(h, h->hpet.period[tn]));
}
}
@@ -378,6 +379,35 @@ void hpet_migrate_timers(struct vcpu *v)
migrate_timer(&h->timers[i], v->processor);
}
static int hpet_save(struct domain *d, hvm_domain_context_t *h)
{
HPETState *hp = &d->arch.hvm_domain.pl_time.vhpet;
/* Save the HPET registers */
return hvm_save_entry(HPET, 0, h, &hp->hpet);
}
static int hpet_load(struct domain *d, hvm_domain_context_t *h)
{
HPETState *hp = &d->arch.hvm_domain.pl_time.vhpet;
int i;
/* Reload the HPET registers */
if ( hvm_load_entry(HPET, h, &hp->hpet) )
return -EINVAL;
/* Recalculate the offset between the main counter and guest time */
hp->mc_offset = hp->hpet.mc64 - hvm_get_guest_time(hp->vcpu);
/* Restart the timers */
for ( i = 0; i < HPET_TIMER_NUM; i++ )
hpet_set_timer(hp, i);
return 0;
}
HVM_REGISTER_SAVE_RESTORE(HPET, hpet_save, hpet_load);
void hpet_init(struct vcpu *v)
{
HPETState *h = &v->domain->arch.hvm_domain.pl_time.vhpet;
+3 -3
View File
@@ -205,7 +205,7 @@ int hvm_save(struct domain *d, hvm_domain_context_t *h)
if ( hvm_save_entry(HEADER, 0, h, &hdr) != 0 )
{
gdprintk(XENLOG_ERR, "HVM save: failed to write header\n");
return -1;
return -EFAULT;
}
/* Save all available kinds of state */
@@ -219,7 +219,7 @@ int hvm_save(struct domain *d, hvm_domain_context_t *h)
{
gdprintk(XENLOG_ERR,
"HVM save: failed to save type %"PRIu16"\n", i);
return -1;
return -EFAULT;
}
}
}
@@ -229,7 +229,7 @@ int hvm_save(struct domain *d, hvm_domain_context_t *h)
{
/* Run out of data */
gdprintk(XENLOG_ERR, "HVM save: no room for end marker.\n");
return -1;
return -EFAULT;
}
/* Save macros should not have let us overrun */
+10
View File
@@ -660,6 +660,13 @@ void svm_update_guest_cr3(struct vcpu *v)
v->arch.hvm_svm.vmcb->cr3 = v->arch.hvm_vcpu.hw_cr3;
}
static void svm_update_vtpr(struct vcpu *v, unsigned long value)
{
struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
vmcb->vintr.fields.tpr = value & 0x0f;
}
unsigned long svm_get_ctrl_reg(struct vcpu *v, unsigned int num)
{
switch ( num )
@@ -1048,6 +1055,8 @@ int start_svm(void)
hvm_funcs.update_host_cr3 = svm_update_host_cr3;
hvm_funcs.update_guest_cr3 = svm_update_guest_cr3;
hvm_funcs.update_vtpr = svm_update_vtpr;
hvm_funcs.stts = svm_stts;
hvm_funcs.set_tsc_offset = svm_set_tsc_offset;
@@ -1939,6 +1948,7 @@ static int mov_to_cr(int gpreg, int cr, struct cpu_user_regs *regs)
case 8:
vlapic_set_reg(vlapic, APIC_TASKPRI, ((value & 0x0F) << 4));
vmcb->vintr.fields.tpr = value & 0x0F;
break;
default:
+1
View File
@@ -593,6 +593,7 @@ static void vlapic_write(struct vcpu *v, unsigned long address,
{
case APIC_TASKPRI:
vlapic_set_reg(vlapic, APIC_TASKPRI, val & 0xff);
hvm_update_vtpr(v, (val >> 4) & 0x0f);
break;
case APIC_EOI:
+7
View File
@@ -986,6 +986,11 @@ static void vmx_inject_exception(
v->arch.hvm_vmx.cpu_cr2 = cr2;
}
static void vmx_update_vtpr(struct vcpu *v, unsigned long value)
{
/* VMX doesn't have a V_TPR field */
}
/* Setup HVM interfaces */
static void vmx_setup_hvm_funcs(void)
{
@@ -1011,6 +1016,8 @@ static void vmx_setup_hvm_funcs(void)
hvm_funcs.update_host_cr3 = vmx_update_host_cr3;
hvm_funcs.update_guest_cr3 = vmx_update_guest_cr3;
hvm_funcs.update_vtpr = vmx_update_vtpr;
hvm_funcs.stts = vmx_stts;
hvm_funcs.set_tsc_offset = vmx_set_tsc_offset;
+5
View File
@@ -597,6 +597,11 @@ static int emulate_forced_invalid_op(struct cpu_user_regs *regs)
if ( !IS_PRIV(current->domain) )
clear_bit(X86_FEATURE_MTRR, &d);
}
else if ( regs->eax == 0x80000001 )
{
/* Modify Feature Information. */
clear_bit(X86_FEATURE_RDTSCP % 32, &d);
}
else
{
(void)cpuid_hypervisor_leaves(regs->eax, &a, &b, &c, &d);
+2 -5
View File
@@ -281,9 +281,6 @@ CFIX14:
.quad CFLT14,CFIX14
.previous
compat_domctl:
compat_sysctl:
.section .rodata, "a", @progbits
ENTRY(compat_hypercall_table)
@@ -365,8 +362,8 @@ ENTRY(compat_hypercall_args_table)
.byte 2 /* compat_event_channel_op */
.byte 2 /* compat_physdev_op */
.byte 2 /* do_hvm_op */
.byte 1 /* compat_sysctl */ /* 35 */
.byte 1 /* compat_domctl */
.byte 1 /* do_sysctl */ /* 35 */
.byte 1 /* do_domctl */
.byte 2 /* compat_kexec_op */
.rept NR_hypercalls-(.-compat_hypercall_args_table)
.byte 0 /* compat_ni_hypercall */
+16 -7
View File
@@ -131,12 +131,20 @@ __initcall(register_crashdump_trigger);
static void setup_note(Elf_Note *n, const char *name, int type, int descsz)
{
safe_strcpy(ELFNOTE_NAME(n), name);
n->namesz = strlen(name);
int l = strlen(name) + 1;
strlcpy(ELFNOTE_NAME(n), name, l);
n->namesz = l;
n->descsz = descsz;
n->type = type;
}
static int sizeof_note(const char *name, int descsz)
{
return (sizeof(Elf_Note) +
ELFNOTE_ALIGN(strlen(name)+1) +
ELFNOTE_ALIGN(descsz));
}
#define kexec_get(x) kexec_get_##x
#endif
@@ -155,23 +163,24 @@ static int kexec_get(reserve)(xen_kexec_range_t *range)
static int kexec_get(xen)(xen_kexec_range_t *range)
{
range->start = virt_to_maddr(_start);
range->size = (unsigned long)_end - (unsigned long)_start;
range->size = (unsigned long)xenheap_phys_end - (unsigned long)range->start;
return 0;
}
static int kexec_get(cpu)(xen_kexec_range_t *range)
{
int nr = range->nr;
int nr_bytes = sizeof(Elf_Note) * 2
+ ELFNOTE_ALIGN(sizeof(ELF_Prstatus))
+ ELFNOTE_ALIGN(sizeof(crash_xen_core_t));
int nr_bytes = 0;
if ( nr < 0 || nr >= num_present_cpus() )
return -EINVAL;
nr_bytes += sizeof_note("CORE", sizeof(ELF_Prstatus));
nr_bytes += sizeof_note("Xen", sizeof(crash_xen_core_t));
/* The Xen info note is included in CPU0's range. */
if ( nr == 0 )
nr_bytes += sizeof(Elf_Note) + ELFNOTE_ALIGN(sizeof(crash_xen_info_t));
nr_bytes += sizeof_note("Xen", sizeof(crash_xen_info_t));
if ( per_cpu(crash_notes, nr) == NULL )
{
+13 -4
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_64(xen_sysctl_perfc_desc_t) desc,
XEN_GUEST_HANDLE_64(xen_sysctl_perfc_val_t) val)
static int perfc_copy_info(XEN_GUEST_HANDLE(xen_sysctl_perfc_desc_t) desc,
XEN_GUEST_HANDLE(xen_sysctl_perfc_val_t) val)
{
unsigned int i, j;
unsigned int v = 0;
@@ -217,20 +217,29 @@ static int perfc_copy_info(XEN_GUEST_HANDLE_64(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(pc->desc, pc->val);
perfc_copy_info(desc, val);
perfc_reset(0);
rc = 0;
break;
case XEN_SYSCTL_PERFCOP_query:
perfc_copy_info(pc->desc, pc->val);
perfc_copy_info(desc, val);
rc = 0;
break;
+1
View File
@@ -49,6 +49,7 @@
#define X86_FEATURE_MP (1*32+19) /* MP Capable. */
#define X86_FEATURE_NX (1*32+20) /* Execute Disable */
#define X86_FEATURE_MMXEXT (1*32+22) /* AMD MMX extensions */
#define X86_FEATURE_RDTSCP (1*32+27) /* RDTSCP */
#define X86_FEATURE_LM (1*32+29) /* Long Mode (x86-64) */
#define X86_FEATURE_3DNOWEXT (1*32+30) /* AMD 3DNow! extensions */
#define X86_FEATURE_3DNOW (1*32+31) /* 3DNow! */
-2
View File
@@ -49,8 +49,6 @@ struct hvm_domain {
spinlock_t pbuf_lock;
uint64_t params[HVM_NR_PARAMS];
struct hvm_domain_context *hvm_ctxt;
};
#endif /* __ASM_X86_HVM_DOMAIN_H__ */
+11
View File
@@ -114,6 +114,11 @@ struct hvm_function_table {
*/
void (*update_guest_cr3)(struct vcpu *v);
/*
* Reflect the virtual APIC's value in the guest's V_TPR register
*/
void (*update_vtpr)(struct vcpu *v, unsigned long value);
/*
* Update specifics of the guest state:
* 1) TS bit in guest cr0
@@ -203,6 +208,12 @@ hvm_update_host_cr3(struct vcpu *v)
hvm_funcs.update_host_cr3(v);
}
static inline void
hvm_update_vtpr(struct vcpu *v, unsigned long value)
{
hvm_funcs.update_vtpr(v, value);
}
void hvm_update_guest_cr3(struct vcpu *v, unsigned long guest_cr3);
void hvm_hypercall_page_initialise(struct domain *d,
+7
View File
@@ -123,6 +123,13 @@ extern unsigned int opt_hvm_debug_level;
* Save/restore support
*/
/* Marshalling and unmarshalling uses a buffer with size and cursor. */
typedef struct hvm_domain_context {
uint32_t cur;
uint32_t size;
uint8_t *data;
} hvm_domain_context_t;
/* Marshalling an entry: check space and fill in the header */
static inline int _hvm_init_entry(struct hvm_domain_context *h,
uint16_t tc, uint16_t inst, uint32_t len)
+4 -21
View File
@@ -31,22 +31,6 @@
#include <asm/hvm/vpic.h>
#include <public/hvm/save.h>
#define HPET_TIMER_NUM 3 /* 3 timers supported now */
struct HPET {
uint64_t capability; /* capabilities */
uint64_t res0; /* reserved */
uint64_t config; /* configuration */
uint64_t res1; /* reserved */
uint64_t isr; /* interrupt status reg */
uint64_t res2[25]; /* reserved */
uint64_t mc64; /* main counter */
uint64_t res3; /* reserved */
struct { /* timers */
uint64_t config; /* configuration/cap */
uint64_t cmp; /* comparator */
uint64_t hpet_fsb[2]; /* FSB route, not supported now */
} timers[HPET_TIMER_NUM];
};
struct HPETState;
struct HPET_timer_fn_info {
@@ -55,11 +39,10 @@ struct HPET_timer_fn_info {
};
typedef struct HPETState {
struct HPET hpet;
struct vcpu *vcpu;
uint64_t tsc_freq;
uint64_t mc_offset;
uint64_t period[HPET_TIMER_NUM];
struct hvm_hw_hpet hpet;
struct vcpu *vcpu;
uint64_t tsc_freq;
uint64_t mc_offset;
struct timer timers[HPET_TIMER_NUM];
struct HPET_timer_fn_info timer_fn_info[HPET_TIMER_NUM];
} HPETState;
+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
#define XEN_GUEST_HANDLE_64(name) __guest_handle_64_ ## name __attribute__((aligned(8)))
#endif
#ifndef __ASSEMBLY__
+2 -9
View File
@@ -386,18 +386,11 @@ struct xen_domctl_settimeoffset {
typedef struct xen_domctl_settimeoffset xen_domctl_settimeoffset_t;
DEFINE_XEN_GUEST_HANDLE(xen_domctl_settimeoffset_t);
#define HVM_CTXT_SIZE 8192
typedef struct hvm_domain_context {
uint32_t cur;
uint32_t size;
uint8_t data[HVM_CTXT_SIZE];
} hvm_domain_context_t;
DEFINE_XEN_GUEST_HANDLE(hvm_domain_context_t);
#define XEN_DOMCTL_gethvmcontext 33
#define XEN_DOMCTL_sethvmcontext 34
typedef struct xen_domctl_hvmcontext {
XEN_GUEST_HANDLE_64(hvm_domain_context_t) ctxt; /* IN/OUT */
uint32_t size; /* IN/OUT: size of buffer / bytes filled */
XEN_GUEST_HANDLE(uint8_t) buffer; /* IN/OUT */
} xen_domctl_hvmcontext_t;
DEFINE_XEN_GUEST_HANDLE(xen_domctl_hvmcontext_t);
+7 -3
View File
@@ -13,9 +13,16 @@ clean:
rm -f checker checker.c $(XEN_TARGET_ARCH).size
rm -f *.pyc *.o *~
ifeq ($(CROSS_COMPILE),)
check-headers: checker
./checker > $(XEN_TARGET_ARCH).size
diff -u reference.size $(XEN_TARGET_ARCH).size
checker: checker.c $(headers)
$(HOSTCC) $(CFLAGS) -o $@ $<
else
check-headers:
@echo "cross build: skipping check"
endif
x86_32.h: ../arch-x86/xen-x86_32.h ../arch-x86/xen.h ../xen.h $(scripts)
python mkheader.py $* $@ $(filter %.h,$^)
@@ -26,8 +33,5 @@ x86_64.h: ../arch-x86/xen-x86_64.h ../arch-x86/xen.h ../xen.h $(scripts)
ia64.h: ../arch-ia64.h ../xen.h $(scripts)
python mkheader.py $* $@ $(filter %.h,$^)
checker: checker.c $(headers)
$(HOSTCC) $(CFLAGS) -o $@ $<
checker.c: $(scripts)
python mkchecker.py $(XEN_TARGET_ARCH) $@ $(architectures)
+31 -1
View File
@@ -381,10 +381,40 @@ struct hvm_hw_rtc {
DECLARE_HVM_SAVE_TYPE(RTC, 9, struct hvm_hw_rtc);
/*
* HPET
*/
#define HPET_TIMER_NUM 3 /* 3 timers supported now */
struct hvm_hw_hpet {
/* Memory-mapped, software visible registers */
uint64_t capability; /* capabilities */
uint64_t res0; /* reserved */
uint64_t config; /* configuration */
uint64_t res1; /* reserved */
uint64_t isr; /* interrupt status reg */
uint64_t res2[25]; /* reserved */
uint64_t mc64; /* main counter */
uint64_t res3; /* reserved */
struct { /* timers */
uint64_t config; /* configuration/cap */
uint64_t cmp; /* comparator */
uint64_t fsb; /* FSB route, not supported now */
uint64_t res4; /* reserved */
} timers[HPET_TIMER_NUM];
uint64_t res5[4*(24-HPET_TIMER_NUM)]; /* reserved, up to 0x3ff */
/* Hidden register state */
uint64_t period[HPET_TIMER_NUM]; /* Last value written to comparator */
};
DECLARE_HVM_SAVE_TYPE(HPET, 10, struct hvm_hw_hpet);
/*
* Largest type-code in use
*/
#define HVM_SAVE_CODE_MAX 9
#define HVM_SAVE_CODE_MAX 10
/*
+10 -2
View File
@@ -82,8 +82,16 @@ extern void * memchr(const void *,int,__kernel_size_t);
}
#endif
#define is_char_array(x) __builtin_types_compatible_p(typeof(x), char[])
/* safe_xxx always NUL-terminates and returns !=0 if result is truncated. */
#define safe_strcpy(d, s) (strlcpy(d, s, sizeof(d)) >= sizeof(d))
#define safe_strcat(d, s) (strlcat(d, s, sizeof(d)) >= sizeof(d))
#define safe_strcpy(d, s) ({ \
BUILD_BUG_ON(!is_char_array(d)); \
(strlcpy(d, s, sizeof(d)) >= sizeof(d)); \
})
#define safe_strcat(d, s) ({ \
BUILD_BUG_ON(!is_char_array(d)); \
(strlcat(d, s, sizeof(d)) >= sizeof(d)); \
})
#endif /* _LINUX_STRING_H_ */
+3 -1
View File
@@ -227,7 +227,7 @@ handle_array() {
build_body() {
echo
echo -n "#define XLAT_$1(_d_, _s_)"
echo -n "#define XLAT_$1(_d_, _s_) do {"
local level=1 fields= id= array= arrlvl=1 array_type= type= token
for token in $2
do
@@ -303,6 +303,8 @@ build_body() {
esac
test -z "$fields" || fields="$fields $token"
done
echo " \\"
echo "} while (0)"
echo ""
}
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.