diff options
author | Isaku Yamahata <yamahata@valinux.co.jp> | 2008-06-19 12:46:26 +0900 |
---|---|---|
committer | Isaku Yamahata <yamahata@valinux.co.jp> | 2008-06-19 12:46:26 +0900 |
commit | d20f38afdaf61331547a3436e9d7311b75628d21 (patch) | |
tree | 0eab6105ee58ad8397365ce5d4d598ad049f70e7 /tools/libxc | |
parent | 006dff9e0417b59020b675f1b0ee49713a9a5739 (diff) | |
parent | d9a2559fc45a21e727e44a5261695dbbba8a517b (diff) | |
download | xen-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/Makefile | 2 | ||||
-rw-r--r-- | tools/libxc/ia64/dom_fw_acpi.c | 29 | ||||
-rw-r--r-- | tools/libxc/xc_cpuid_x86.c | 216 | ||||
-rw-r--r-- | tools/libxc/xc_dom.h | 3 | ||||
-rw-r--r-- | tools/libxc/xc_dom_core.c | 6 | ||||
-rw-r--r-- | tools/libxc/xc_dom_x86.c | 4 | ||||
-rw-r--r-- | tools/libxc/xc_domain_restore.c | 16 | ||||
-rw-r--r-- | tools/libxc/xc_domain_save.c | 19 | ||||
-rw-r--r-- | tools/libxc/xc_netbsd.c | 6 |
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" |