aboutsummaryrefslogtreecommitdiffstats
path: root/tools/libxc
diff options
context:
space:
mode:
authorIsaku Yamahata <yamahata@valinux.co.jp>2008-06-19 12:46:26 +0900
committerIsaku Yamahata <yamahata@valinux.co.jp>2008-06-19 12:46:26 +0900
commitd20f38afdaf61331547a3436e9d7311b75628d21 (patch)
tree0eab6105ee58ad8397365ce5d4d598ad049f70e7 /tools/libxc
parent006dff9e0417b59020b675f1b0ee49713a9a5739 (diff)
parentd9a2559fc45a21e727e44a5261695dbbba8a517b (diff)
downloadxen-d20f38afdaf61331547a3436e9d7311b75628d21.tar.gz
xen-d20f38afdaf61331547a3436e9d7311b75628d21.tar.bz2
xen-d20f38afdaf61331547a3436e9d7311b75628d21.zip
merge with xen-unstable.hg
Diffstat (limited to 'tools/libxc')
-rw-r--r--tools/libxc/Makefile2
-rw-r--r--tools/libxc/ia64/dom_fw_acpi.c29
-rw-r--r--tools/libxc/xc_cpuid_x86.c216
-rw-r--r--tools/libxc/xc_dom.h3
-rw-r--r--tools/libxc/xc_dom_core.c6
-rw-r--r--tools/libxc/xc_dom_x86.c4
-rw-r--r--tools/libxc/xc_domain_restore.c16
-rw-r--r--tools/libxc/xc_domain_save.c19
-rw-r--r--tools/libxc/xc_netbsd.c6
9 files changed, 236 insertions, 65 deletions
diff --git a/tools/libxc/Makefile b/tools/libxc/Makefile
index d685419da6..c68a0f0d9e 100644
--- a/tools/libxc/Makefile
+++ b/tools/libxc/Makefile
@@ -32,7 +32,7 @@ GUEST_SRCS-y += xg_private.c
GUEST_SRCS-$(CONFIG_MIGRATE) += xc_domain_restore.c xc_domain_save.c
GUEST_SRCS-$(CONFIG_HVM) += xc_hvm_build.c
-VPATH = ../../xen/common/libelf
+vpath %.c ../../xen/common/libelf
CFLAGS += -I../../xen/common/libelf
GUEST_SRCS-y += libelf-tools.c libelf-loader.c
diff --git a/tools/libxc/ia64/dom_fw_acpi.c b/tools/libxc/ia64/dom_fw_acpi.c
index cb13a94ea5..493a5adbaf 100644
--- a/tools/libxc/ia64/dom_fw_acpi.c
+++ b/tools/libxc/ia64/dom_fw_acpi.c
@@ -1,14 +1,31 @@
#include <inttypes.h>
#include "xc_dom_ia64_util.h"
#include <xen/acpi.h>
+#include <acpi/actables.h>
-uint8_t
-generate_acpi_checksum(void *tbl, unsigned long len)
+/* stolen from xen/drivers/acpi/tables/tbutils.c */
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_tb_checksum
+ *
+ * PARAMETERS: Buffer - Pointer to memory region to be checked
+ * Length - Length of this memory region
+ *
+ * RETURN: Checksum (u8)
+ *
+ * DESCRIPTION: Calculates circular checksum of memory region.
+ *
+ ******************************************************************************/
+
+u8 acpi_tb_checksum(u8 * buffer, acpi_native_uint length)
{
- uint8_t *ptr, sum = 0;
+ u8 sum = 0;
+ u8 *end = buffer + length;
- for ( ptr = tbl; len > 0 ; len--, ptr++ )
- sum += *ptr;
+ while (buffer < end) {
+ sum = (u8) (sum + *(buffer++));
+ }
- return 0 - sum;
+ return sum;
}
diff --git a/tools/libxc/xc_cpuid_x86.c b/tools/libxc/xc_cpuid_x86.c
index febf97c607..2f08182bfd 100644
--- a/tools/libxc/xc_cpuid_x86.c
+++ b/tools/libxc/xc_cpuid_x86.c
@@ -25,19 +25,50 @@
#include <xen/hvm/params.h>
#define bitmaskof(idx) (1u << ((idx) & 31))
-#define clear_bit(idx, dst) ((dst) &= ~(1u << (idx)))
-#define set_bit(idx, dst) ((dst) |= (1u << (idx)))
+#define clear_bit(idx, dst) ((dst) &= ~(1u << ((idx) & 31)))
+#define set_bit(idx, dst) ((dst) |= (1u << ((idx) & 31)))
#define DEF_MAX_BASE 0x00000004u
#define DEF_MAX_EXT 0x80000008u
-static void amd_xc_cpuid_policy(
- int xc, domid_t domid, const unsigned int *input, unsigned int *regs)
+static int hypervisor_is_64bit(int xc)
{
- unsigned long pae = 0;
+ xen_capabilities_info_t xen_caps = "";
+ return ((xc_version(xc, XENVER_capabilities, &xen_caps) == 0) &&
+ (strstr(xen_caps, "x86_64") != NULL));
+}
- xc_get_hvm_param(xc, domid, HVM_PARAM_PAE_ENABLED, &pae);
+static void cpuid(const unsigned int *input, unsigned int *regs)
+{
+ unsigned int count = (input[1] == XEN_CPUID_INPUT_UNUSED) ? 0 : input[1];
+ asm (
+#ifdef __i386__
+ "push %%ebx; cpuid; mov %%ebx,%1; pop %%ebx"
+#else
+ "push %%rbx; cpuid; mov %%ebx,%1; pop %%rbx"
+#endif
+ : "=a" (regs[0]), "=r" (regs[1]), "=c" (regs[2]), "=d" (regs[3])
+ : "0" (input[0]), "2" (count) );
+}
+
+/* Get the manufacturer brand name of the host processor. */
+static void xc_cpuid_brand_get(char *str)
+{
+ unsigned int input[2] = { 0, 0 };
+ unsigned int regs[4];
+
+ cpuid(input, regs);
+
+ *(uint32_t *)(str + 0) = regs[1];
+ *(uint32_t *)(str + 4) = regs[3];
+ *(uint32_t *)(str + 8) = regs[2];
+ str[12] = '\0';
+}
+static void amd_xc_cpuid_policy(
+ int xc, domid_t domid, const unsigned int *input, unsigned int *regs,
+ int is_pae)
+{
switch ( input[0] )
{
case 0x00000001:
@@ -52,21 +83,23 @@ static void amd_xc_cpuid_policy(
regs[0] = regs[1] = regs[2] = 0;
break;
- case 0x80000001:
- if ( !pae )
- clear_bit(X86_FEATURE_PAE & 31, regs[3]);
- clear_bit(X86_FEATURE_PSE36 & 31, regs[3]);
+ case 0x80000001: {
+ int is_64bit = hypervisor_is_64bit(xc) && is_pae;
+
+ if ( !is_pae )
+ clear_bit(X86_FEATURE_PAE, regs[3]);
+ clear_bit(X86_FEATURE_PSE36, regs[3]);
/* Filter all other features according to a whitelist. */
- regs[2] &= (bitmaskof(X86_FEATURE_LAHF_LM) |
+ regs[2] &= ((is_64bit ? bitmaskof(X86_FEATURE_LAHF_LM) : 0) |
bitmaskof(X86_FEATURE_ALTMOVCR) |
bitmaskof(X86_FEATURE_ABM) |
bitmaskof(X86_FEATURE_SSE4A) |
bitmaskof(X86_FEATURE_MISALIGNSSE) |
bitmaskof(X86_FEATURE_3DNOWPF));
regs[3] &= (0x0183f3ff | /* features shared with 0x00000001:EDX */
- bitmaskof(X86_FEATURE_NX) |
- bitmaskof(X86_FEATURE_LM) |
+ (is_pae ? bitmaskof(X86_FEATURE_NX) : 0) |
+ (is_64bit ? bitmaskof(X86_FEATURE_LM) : 0) |
bitmaskof(X86_FEATURE_SYSCALL) |
bitmaskof(X86_FEATURE_MP) |
bitmaskof(X86_FEATURE_MMXEXT) |
@@ -75,10 +108,12 @@ static void amd_xc_cpuid_policy(
bitmaskof(X86_FEATURE_3DNOWEXT));
break;
}
+ }
}
static void intel_xc_cpuid_policy(
- int xc, domid_t domid, const unsigned int *input, unsigned int *regs)
+ int xc, domid_t domid, const unsigned int *input, unsigned int *regs,
+ int is_pae)
{
switch ( input[0] )
{
@@ -92,52 +127,30 @@ static void intel_xc_cpuid_policy(
regs[3] &= 0x3FF;
break;
- case 0x80000001:
+ case 0x80000001: {
+ int is_64bit = hypervisor_is_64bit(xc) && is_pae;
+
/* Only a few features are advertised in Intel's 0x80000001. */
- regs[2] &= (bitmaskof(X86_FEATURE_LAHF_LM));
- regs[3] &= (bitmaskof(X86_FEATURE_NX) |
- bitmaskof(X86_FEATURE_LM) |
- bitmaskof(X86_FEATURE_SYSCALL));
+ regs[2] &= (is_64bit ? bitmaskof(X86_FEATURE_LAHF_LM) : 0);
+ regs[3] &= ((is_pae ? bitmaskof(X86_FEATURE_NX) : 0) |
+ (is_64bit ? bitmaskof(X86_FEATURE_LM) : 0) |
+ (is_64bit ? bitmaskof(X86_FEATURE_SYSCALL) : 0));
break;
}
+ }
}
-static void cpuid(const unsigned int *input, unsigned int *regs)
-{
- unsigned int count = (input[1] == XEN_CPUID_INPUT_UNUSED) ? 0 : input[1];
- asm (
-#ifdef __i386__
- "push %%ebx; cpuid; mov %%ebx,%1; pop %%ebx"
-#else
- "push %%rbx; cpuid; mov %%ebx,%1; pop %%rbx"
-#endif
- : "=a" (regs[0]), "=r" (regs[1]), "=c" (regs[2]), "=d" (regs[3])
- : "0" (input[0]), "2" (count) );
-}
-
-/* Get the manufacturer brand name of the host processor. */
-static void xc_cpuid_brand_get(char *str)
-{
- unsigned int input[2] = { 0, 0 };
- unsigned int regs[4];
-
- cpuid(input, regs);
-
- *(uint32_t *)(str + 0) = regs[1];
- *(uint32_t *)(str + 4) = regs[3];
- *(uint32_t *)(str + 8) = regs[2];
- str[12] = '\0';
-}
-
-static void xc_cpuid_policy(
+static void xc_cpuid_hvm_policy(
int xc, domid_t domid, const unsigned int *input, unsigned int *regs)
{
char brand[13];
unsigned long pae;
+ int is_pae;
xc_get_hvm_param(xc, domid, HVM_PARAM_PAE_ENABLED, &pae);
+ is_pae = !!pae;
- switch( input[0] )
+ switch ( input[0] )
{
case 0x00000000:
if ( regs[0] > DEF_MAX_BASE )
@@ -177,8 +190,8 @@ static void xc_cpuid_policy(
/* We always support MTRR MSRs. */
regs[3] |= bitmaskof(X86_FEATURE_MTRR);
- if ( !pae )
- clear_bit(X86_FEATURE_PAE & 31, regs[3]);
+ if ( !is_pae )
+ clear_bit(X86_FEATURE_PAE, regs[3]);
break;
case 0x80000000:
@@ -187,8 +200,8 @@ static void xc_cpuid_policy(
break;
case 0x80000001:
- if ( !pae )
- clear_bit(X86_FEATURE_NX & 31, regs[3]);
+ if ( !is_pae )
+ clear_bit(X86_FEATURE_NX, regs[3]);
break;
@@ -212,9 +225,104 @@ static void xc_cpuid_policy(
xc_cpuid_brand_get(brand);
if ( strstr(brand, "AMD") )
- amd_xc_cpuid_policy(xc, domid, input, regs);
+ amd_xc_cpuid_policy(xc, domid, input, regs, is_pae);
else
- intel_xc_cpuid_policy(xc, domid, input, regs);
+ intel_xc_cpuid_policy(xc, domid, input, regs, is_pae);
+
+}
+
+static void xc_cpuid_pv_policy(
+ int xc, domid_t domid, const unsigned int *input, unsigned int *regs)
+{
+ DECLARE_DOMCTL;
+ int guest_64bit, xen_64bit = hypervisor_is_64bit(xc);
+ char brand[13];
+
+ xc_cpuid_brand_get(brand);
+
+ memset(&domctl, 0, sizeof(domctl));
+ domctl.domain = domid;
+ domctl.cmd = XEN_DOMCTL_get_address_size;
+ do_domctl(xc, &domctl);
+ guest_64bit = (domctl.u.address_size.size == 64);
+
+ if ( (input[0] & 0x7fffffff) == 1 )
+ {
+ clear_bit(X86_FEATURE_VME, regs[3]);
+ clear_bit(X86_FEATURE_PSE, regs[3]);
+ clear_bit(X86_FEATURE_PGE, regs[3]);
+ clear_bit(X86_FEATURE_MCE, regs[3]);
+ clear_bit(X86_FEATURE_MCA, regs[3]);
+ clear_bit(X86_FEATURE_MTRR, regs[3]);
+ clear_bit(X86_FEATURE_PSE36, regs[3]);
+ }
+
+ switch ( input[0] )
+ {
+ case 1:
+ if ( !xen_64bit || strstr(brand, "AMD") )
+ clear_bit(X86_FEATURE_SEP, regs[3]);
+ clear_bit(X86_FEATURE_DS, regs[3]);
+ clear_bit(X86_FEATURE_ACC, regs[3]);
+ clear_bit(X86_FEATURE_PBE, regs[3]);
+
+ clear_bit(X86_FEATURE_DTES64, regs[2]);
+ clear_bit(X86_FEATURE_MWAIT, regs[2]);
+ clear_bit(X86_FEATURE_DSCPL, regs[2]);
+ clear_bit(X86_FEATURE_VMXE, regs[2]);
+ clear_bit(X86_FEATURE_SMXE, regs[2]);
+ clear_bit(X86_FEATURE_EST, regs[2]);
+ clear_bit(X86_FEATURE_TM2, regs[2]);
+ if ( !guest_64bit )
+ clear_bit(X86_FEATURE_CX16, regs[2]);
+ clear_bit(X86_FEATURE_XTPR, regs[2]);
+ clear_bit(X86_FEATURE_PDCM, regs[2]);
+ clear_bit(X86_FEATURE_DCA, regs[2]);
+ break;
+ case 0x80000001:
+ if ( !guest_64bit )
+ {
+ clear_bit(X86_FEATURE_LM, regs[3]);
+ clear_bit(X86_FEATURE_LAHF_LM, regs[2]);
+ if ( !strstr(brand, "AMD") )
+ clear_bit(X86_FEATURE_SYSCALL, regs[3]);
+ }
+ else
+ {
+ set_bit(X86_FEATURE_SYSCALL, regs[3]);
+ }
+ clear_bit(X86_FEATURE_PAGE1GB, regs[3]);
+ clear_bit(X86_FEATURE_RDTSCP, regs[3]);
+
+ clear_bit(X86_FEATURE_SVME, regs[2]);
+ clear_bit(X86_FEATURE_OSVW, regs[2]);
+ clear_bit(X86_FEATURE_IBS, regs[2]);
+ clear_bit(X86_FEATURE_SKINIT, regs[2]);
+ clear_bit(X86_FEATURE_WDT, regs[2]);
+ break;
+ case 5: /* MONITOR/MWAIT */
+ case 0xa: /* Architectural Performance Monitor Features */
+ case 0x8000000a: /* SVM revision and features */
+ case 0x8000001b: /* Instruction Based Sampling */
+ regs[0] = regs[1] = regs[2] = regs[3] = 0;
+ break;
+ }
+}
+
+static int xc_cpuid_policy(
+ int xc, domid_t domid, const unsigned int *input, unsigned int *regs)
+{
+ xc_dominfo_t info;
+
+ if ( xc_domain_getinfo(xc, domid, 1, &info) == 0 )
+ return -EINVAL;
+
+ if ( info.hvm )
+ xc_cpuid_hvm_policy(xc, domid, input, regs);
+ else
+ xc_cpuid_pv_policy(xc, domid, input, regs);
+
+ return 0;
}
static int xc_cpuid_do_domctl(
diff --git a/tools/libxc/xc_dom.h b/tools/libxc/xc_dom.h
index 30111c98e2..770e00bba2 100644
--- a/tools/libxc/xc_dom.h
+++ b/tools/libxc/xc_dom.h
@@ -107,6 +107,8 @@ struct xc_dom_image {
/* kernel loader */
struct xc_dom_arch *arch_hooks;
+ /* allocate up to virt_alloc_end */
+ int (*allocate) (struct xc_dom_image * dom, xen_vaddr_t up_to);
};
/* --- pluggable kernel loader ------------------------------------- */
@@ -167,6 +169,7 @@ int xc_dom_ramdisk_mem(struct xc_dom_image *dom, const void *mem,
size_t memsize);
int xc_dom_parse_image(struct xc_dom_image *dom);
+struct xc_dom_arch *xc_dom_find_arch_hooks(char *guest_type);
int xc_dom_build_image(struct xc_dom_image *dom);
int xc_dom_update_guest_p2m(struct xc_dom_image *dom);
diff --git a/tools/libxc/xc_dom_core.c b/tools/libxc/xc_dom_core.c
index 9a158ef5e2..2b6f6b6868 100644
--- a/tools/libxc/xc_dom_core.c
+++ b/tools/libxc/xc_dom_core.c
@@ -409,6 +409,8 @@ int xc_dom_alloc_segment(struct xc_dom_image *dom,
seg->vend = start + pages * page_size;
seg->pfn = (seg->vstart - dom->parms.virt_base) / page_size;
dom->virt_alloc_end = seg->vend;
+ if (dom->allocate)
+ dom->allocate(dom, dom->virt_alloc_end);
xc_dom_printf("%-20s: %-12s : 0x%" PRIx64 " -> 0x%" PRIx64
" (pfn 0x%" PRIpfn " + 0x%" PRIpfn " pages)\n",
@@ -431,6 +433,8 @@ int xc_dom_alloc_page(struct xc_dom_image *dom, char *name)
start = dom->virt_alloc_end;
dom->virt_alloc_end += page_size;
+ if (dom->allocate)
+ dom->allocate(dom, dom->virt_alloc_end);
pfn = (start - dom->parms.virt_base) / page_size;
xc_dom_printf("%-20s: %-12s : 0x%" PRIx64 " (pfn 0x%" PRIpfn ")\n",
@@ -506,7 +510,7 @@ void xc_dom_register_arch_hooks(struct xc_dom_arch *hooks)
first_hook = hooks;
}
-static struct xc_dom_arch *xc_dom_find_arch_hooks(char *guest_type)
+struct xc_dom_arch *xc_dom_find_arch_hooks(char *guest_type)
{
struct xc_dom_arch *hooks = first_hook;
diff --git a/tools/libxc/xc_dom_x86.c b/tools/libxc/xc_dom_x86.c
index 2ed298907c..f96ec3f7ab 100644
--- a/tools/libxc/xc_dom_x86.c
+++ b/tools/libxc/xc_dom_x86.c
@@ -418,7 +418,7 @@ static int start_info_x86_32(struct xc_dom_image *dom)
xc_dom_printf("%s: called\n", __FUNCTION__);
memset(start_info, 0, sizeof(*start_info));
- sprintf(start_info->magic, dom->guest_type);
+ snprintf(start_info->magic, sizeof(start_info->magic), dom->guest_type);
start_info->nr_pages = dom->total_pages;
start_info->shared_info = shinfo << PAGE_SHIFT_X86;
start_info->pt_base = dom->pgtables_seg.vstart;
@@ -457,7 +457,7 @@ static int start_info_x86_64(struct xc_dom_image *dom)
xc_dom_printf("%s: called\n", __FUNCTION__);
memset(start_info, 0, sizeof(*start_info));
- sprintf(start_info->magic, dom->guest_type);
+ snprintf(start_info->magic, sizeof(start_info->magic), dom->guest_type);
start_info->nr_pages = dom->total_pages;
start_info->shared_info = shinfo << PAGE_SHIFT_X86;
start_info->pt_base = dom->pgtables_seg.vstart;
diff --git a/tools/libxc/xc_domain_restore.c b/tools/libxc/xc_domain_restore.c
index b7b74352e1..46859f63cf 100644
--- a/tools/libxc/xc_domain_restore.c
+++ b/tools/libxc/xc_domain_restore.c
@@ -474,6 +474,22 @@ int xc_domain_restore(int xc_handle, int io_fd, uint32_t dom,
continue;
}
+ if ( j == -3 )
+ {
+ uint64_t ident_pt;
+
+ /* Skip padding 4 bytes then read the EPT identity PT location. */
+ if ( read_exact(io_fd, &ident_pt, sizeof(uint32_t)) ||
+ read_exact(io_fd, &ident_pt, sizeof(uint64_t)) )
+ {
+ ERROR("error read the address of the EPT identity map");
+ goto out;
+ }
+
+ xc_set_hvm_param(xc_handle, dom, HVM_PARAM_IDENT_PT, ident_pt);
+ continue;
+ }
+
if ( j == 0 )
break; /* our work here is done */
diff --git a/tools/libxc/xc_domain_save.c b/tools/libxc/xc_domain_save.c
index 636bb78e7f..7b8a1317a4 100644
--- a/tools/libxc/xc_domain_save.c
+++ b/tools/libxc/xc_domain_save.c
@@ -1429,6 +1429,25 @@ int xc_domain_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
}
}
+ if ( hvm )
+ {
+ struct {
+ int minusthree;
+ uint32_t pad;
+ uint64_t ident_pt;
+ } chunk = { -3, 0 };
+
+ xc_get_hvm_param(xc_handle, dom, HVM_PARAM_IDENT_PT,
+ (unsigned long *)&chunk.ident_pt);
+
+ if ( (chunk.ident_pt != 0) &&
+ write_exact(io_fd, &chunk, sizeof(chunk)) )
+ {
+ PERROR("Error when writing the ident_pt for EPT guest");
+ goto out;
+ }
+ }
+
/* Zero terminate */
i = 0;
if ( write_exact(io_fd, &i, sizeof(int)) )
diff --git a/tools/libxc/xc_netbsd.c b/tools/libxc/xc_netbsd.c
index 81c86d1064..036f64879c 100644
--- a/tools/libxc/xc_netbsd.c
+++ b/tools/libxc/xc_netbsd.c
@@ -142,9 +142,13 @@ static int do_privcmd(int xc_handle, unsigned int cmd, unsigned long data)
int do_xen_hypercall(int xc_handle, privcmd_hypercall_t *hypercall)
{
- return do_privcmd(xc_handle,
+ int error = do_privcmd(xc_handle,
IOCTL_PRIVCMD_HYPERCALL,
(unsigned long)hypercall);
+ if (error)
+ return error;
+ else
+ return (hypercall->retval);
}
#define EVTCHN_DEV_NAME "/dev/xenevt"