--- a/src/xs_internal.c +++ b/src/xs_internal.c @@ -35,7 +35,7 @@ #ifdef __linux__ #define XEN_HYPERVISOR_SOCKET "/proc/xen/privcmd" -#elif define(__sun__) +#elif defined(__sun) #define XEN_HYPERVISOR_SOCKET "/dev/xen/privcmd" #else #error "unsupported platform" --- a/src/xen_internal.c +++ b/src/xen_internal.c @@ -75,7 +75,7 @@ typedef struct v1_hypercall_struct #define XEN_V1_IOCTL_HYPERCALL_CMD \ _IOC(_IOC_NONE, 'P', 0, sizeof(v1_hypercall_t)) typedef v1_hypercall_t hypercall_t; -#elif define(__sun__) +#elif defined(__sun) typedef privcmd_hypercall_t hypercall_t; #else #error "unsupported platform" @@ -340,8 +340,10 @@ lock_pages(void *addr, size_t len) { #ifdef __linux__ return (mlock(addr, len)); -#elif define(__sun) +#elif defined(__sun) return (0); +#else +#error "unsupported platform" #endif } @@ -350,8 +352,10 @@ unlock_pages(void *addr, size_t len) { #ifdef __linux__ return (munlock(addr, len)); -#elif define(__sun) +#elif defined(__sun) return (0); +#else +#error "unsupported platform" #endif } @@ -666,7 +670,7 @@ typedef struct xen_op_v2_dom xen_op_v2_d #define XEN_HYPERVISOR_SOCKET "/proc/xen/privcmd" #define HYPERVISOR_CAPABILITIES "/sys/hypervisor/properties/capabilities" #define CPUINFO "/proc/cpuinfo" -#elif define(__sun__) +#elif defined(__sun) #define XEN_HYPERVISOR_SOCKET "/dev/xen/privcmd" #define HYPERVISOR_CAPABILITIES "" #define CPUINFO "/dev/cpu/self/cpuid" @@ -1948,7 +1952,7 @@ xenHypervisorInit(void) goto detect_v2; } -#ifndef __sun__ +#ifndef __sun /* * check if the old hypercall are actually working */ @@ -2265,6 +2269,92 @@ xenHypervisorBuildCapabilities(virConnec return NULL; } +#ifdef __linux__ +void +loadCapabilities(FILE *cpuinfo, FILE *capabilities, char *hvm_type, + int *host_pae, char *line, int LINE_SIZE) +{ + regmatch_t subs[4]; + + /* /proc/cpuinfo: flags: Intel calls HVM "vmx", AMD calls it "svm". + * It's not clear if this will work on IA64, let alone other + * architectures and non-Linux. (XXX) + */ + if (cpuinfo) { + while (fgets (line, LINE_SIZE, cpuinfo)) { + if (regexec (&flags_hvm_rec, line, + sizeof(subs)/sizeof(regmatch_t), subs, 0) == 0 + && subs[0].rm_so != -1) { + strncpy (hvm_type, + &line[subs[1].rm_so], subs[1].rm_eo-subs[1].rm_so+1); + hvm_type[subs[1].rm_eo-subs[1].rm_so] = '\0'; + } else if (regexec (&flags_pae_rec, line, 0, NULL, 0) == 0) + *host_pae = 1; + } + } + + /* Expecting one line in this file - ignore any more. */ + (void) fgets(line, LINE_SIZE, capabilities); +} + +#else +void +loadCapabilities(FILE *cpuinfo, FILE *capabilities, char *hvm_type, + int *host_pae, char *line, int LINE_SIZE) +{ + struct { + uint32_t r_eax, r_ebx, r_ecx, r_edx; + } _r, *rp = &_r; + int d, cmd; + char *s; + hypercall_t hc; + + + if ((d = open(CPUINFO, O_RDONLY)) == -1) { + goto cpuinfo_open_fail; + } + + if (pread(d, rp, sizeof (*rp), 0) != sizeof (*rp)) { + goto cpuinfo_pread_fail; + } + + s = (char *)&rp->r_ebx; + if (strncmp(s, "Auth" "cAMD" "enti", 12) == 0) { + if (pread(d, rp, sizeof (*rp), 0x80000001) == sizeof (*rp)) { + /* Read secure virtual machine bit (bit 2 of ECX feature ID) */ + if ((rp->r_ecx >> 2) & 1) { + strcpy(hvm_type, "svm"); + } + if ((rp->r_edx >> 6) & 1) { + *host_pae = 1; + } + } + } else if (strncmp(s, "Genu" "ntel" "ineI", 12) == 0) { + if (pread(d, rp, sizeof (*rp), 0x00000001) == sizeof (*rp)) { + /* Read VMXE feature bit (bit 5 of ECX feature ID) */ + if ((rp->r_ecx >> 5) & 1) { + strcpy(hvm_type, "vmx"); + } + if ((rp->r_edx >> 6) & 1) { + *host_pae = 1; + } + } + } +cpuinfo_pread_fail: + (void) close(d); +cpuinfo_open_fail: + + d = open(XEN_HYPERVISOR_SOCKET, O_RDWR); + hc.op = __HYPERVISOR_xen_version; + hc.arg[0] = (unsigned long) XENVER_capabilities; + hc.arg[1] = (unsigned long) line; + cmd = IOCTL_PRIVCMD_HYPERCALL; + (void) ioctl(d, cmd, (unsigned long) &hc); + close(d); +} + +#endif + /** * xenHypervisorGetCapabilities: * @conn: pointer to the connection block @@ -2278,7 +2368,8 @@ xenHypervisorMakeCapabilitiesXML(virConn const char *hostmachine, FILE *cpuinfo, FILE *capabilities) { - char line[1024], *str, *token; + const int LINE_SIZE = 1024; + char line[LINE_SIZE], *str, *token; regmatch_t subs[4]; char *saveptr = NULL; int i; @@ -2295,24 +2386,12 @@ xenHypervisorMakeCapabilitiesXML(virConn memset(guest_archs, 0, sizeof(guest_archs)); - /* /proc/cpuinfo: flags: Intel calls HVM "vmx", AMD calls it "svm". - * It's not clear if this will work on IA64, let alone other - * architectures and non-Linux. (XXX) - */ - if (cpuinfo) { - while (fgets (line, sizeof line, cpuinfo)) { - if (regexec (&flags_hvm_rec, line, sizeof(subs)/sizeof(regmatch_t), subs, 0) == 0 - && subs[0].rm_so != -1) { - strncpy (hvm_type, - &line[subs[1].rm_so], subs[1].rm_eo-subs[1].rm_so+1); - hvm_type[subs[1].rm_eo-subs[1].rm_so] = '\0'; - } else if (regexec (&flags_pae_rec, line, 0, NULL, 0) == 0) - host_pae = 1; - } - } + memset(line, 0, sizeof(line)); + loadCapabilities(cpuinfo, capabilities, hvm_type, &host_pae, line, + LINE_SIZE); - /* Most of the useful info is in /sys/hypervisor/properties/capabilities - * which is documented in the code in xen-unstable.hg/xen/arch/.../setup.c. + /* The capabilities line is documented in the code in + * xen-unstable.hg/xen/arch/.../setup.c. * * It is a space-separated list of supported guest architectures. * @@ -2335,80 +2414,77 @@ xenHypervisorMakeCapabilitiesXML(virConn * +--------------- "xen" or "hvm" for para or full virt respectively */ - /* Expecting one line in this file - ignore any more. */ - if ((capabilities) && (fgets (line, sizeof line, capabilities))) { - /* Split the line into tokens. strtok_r is OK here because we "own" - * this buffer. Parse out the features from each token. - */ - for (str = line, nr_guest_archs = 0; - nr_guest_archs < sizeof guest_archs / sizeof guest_archs[0] - && (token = strtok_r (str, " ", &saveptr)) != NULL; - str = NULL) { - - if (regexec (&xen_cap_rec, token, sizeof subs / sizeof subs[0], - subs, 0) == 0) { - int hvm = STRPREFIX(&token[subs[1].rm_so], "hvm"); - const char *model; - int bits, pae = 0, nonpae = 0, ia64_be = 0; - - if (STRPREFIX(&token[subs[2].rm_so], "x86_32")) { - model = "i686"; - bits = 32; - if (subs[3].rm_so != -1 && - STRPREFIX(&token[subs[3].rm_so], "p")) - pae = 1; - else - nonpae = 1; - } - else if (STRPREFIX(&token[subs[2].rm_so], "x86_64")) { - model = "x86_64"; - bits = 64; - } - else if (STRPREFIX(&token[subs[2].rm_so], "ia64")) { - model = "ia64"; - bits = 64; - if (subs[3].rm_so != -1 && - STRPREFIX(&token[subs[3].rm_so], "be")) - ia64_be = 1; - } - else if (STRPREFIX(&token[subs[2].rm_so], "powerpc64")) { - model = "ppc64"; - bits = 64; - } else { - /* XXX surely no other Xen archs exist */ - continue; - } + /* Split the line into tokens. strtok_r is OK here because we "own" + * this buffer. Parse out the features from each token. + */ + for (str = line, nr_guest_archs = 0; + nr_guest_archs < sizeof guest_archs / sizeof guest_archs[0] + && (token = strtok_r (str, " ", &saveptr)) != NULL; + str = NULL) { + + if (regexec (&xen_cap_rec, token, sizeof subs / sizeof subs[0], + subs, 0) == 0) { + int hvm = STRPREFIX(&token[subs[1].rm_so], "hvm"); + const char *model; + int bits, pae = 0, nonpae = 0, ia64_be = 0; + + if (STRPREFIX(&token[subs[2].rm_so], "x86_32")) { + model = "i686"; + bits = 32; + if (subs[3].rm_so != -1 && + STRPREFIX(&token[subs[3].rm_so], "p")) + pae = 1; + else + nonpae = 1; + } + else if (STRPREFIX(&token[subs[2].rm_so], "x86_64")) { + model = "x86_64"; + bits = 64; + } + else if (STRPREFIX(&token[subs[2].rm_so], "ia64")) { + model = "ia64"; + bits = 64; + if (subs[3].rm_so != -1 && + STRPREFIX(&token[subs[3].rm_so], "be")) + ia64_be = 1; + } + else if (STRPREFIX(&token[subs[2].rm_so], "powerpc64")) { + model = "ppc64"; + bits = 64; + } else { + /* XXX surely no other Xen archs exist */ + continue; + } - /* Search for existing matching (model,hvm) tuple */ - for (i = 0 ; i < nr_guest_archs ; i++) { - if (STREQ(guest_archs[i].model, model) && - guest_archs[i].hvm == hvm) { - break; - } + /* Search for existing matching (model,hvm) tuple */ + for (i = 0 ; i < nr_guest_archs ; i++) { + if (STREQ(guest_archs[i].model, model) && + guest_archs[i].hvm == hvm) { + break; } - - /* Too many arch flavours - highly unlikely ! */ - if (i >= sizeof(guest_archs)/sizeof(guest_archs[0])) - continue; - /* Didn't find a match, so create a new one */ - if (i == nr_guest_archs) - nr_guest_archs++; - - guest_archs[i].model = model; - guest_archs[i].bits = bits; - guest_archs[i].hvm = hvm; - - /* Careful not to overwrite a previous positive - setting with a negative one here - some archs - can do both pae & non-pae, but Xen reports - separately capabilities so we're merging archs */ - if (pae) - guest_archs[i].pae = pae; - if (nonpae) - guest_archs[i].nonpae = nonpae; - if (ia64_be) - guest_archs[i].ia64_be = ia64_be; } + + /* Too many arch flavours - highly unlikely ! */ + if (i >= sizeof(guest_archs)/sizeof(guest_archs[0])) + continue; + /* Didn't find a match, so create a new one */ + if (i == nr_guest_archs) + nr_guest_archs++; + + guest_archs[i].model = model; + guest_archs[i].bits = bits; + guest_archs[i].hvm = hvm; + + /* Careful not to overwrite a previous positive + setting with a negative one here - some archs + can do both pae & non-pae, but Xen reports + separately capabilities so we're merging archs */ + if (pae) + guest_archs[i].pae = pae; + if (nonpae) + guest_archs[i].nonpae = nonpae; + if (ia64_be) + guest_archs[i].ia64_be = ia64_be; } } @@ -2447,29 +2523,33 @@ xenHypervisorGetCapabilities (virConnect /* Really, this never fails - look at the man-page. */ uname (&utsname); - cpuinfo = fopen ("/proc/cpuinfo", "r"); +#ifdef __linux__ + cpuinfo = fopen (CPUINFO, "r"); if (cpuinfo == NULL) { if (errno != ENOENT) { - virXenPerror (conn, "/proc/cpuinfo"); + virXenPerror (conn, CPUINFO); return NULL; } } - capabilities = fopen ("/sys/hypervisor/properties/capabilities", "r"); + capabilities = fopen (HYPERVISOR_CAPABILITIES, "r"); if (capabilities == NULL) { if (errno != ENOENT) { fclose(cpuinfo); - virXenPerror (conn, "/sys/hypervisor/properties/capabilities"); + virXenPerror (conn, HYPERVISOR_CAPABILITIES); return NULL; } } +#endif xml = xenHypervisorMakeCapabilitiesXML(conn, utsname.machine, cpuinfo, capabilities); +#ifdef __linux__ if (cpuinfo) fclose(cpuinfo); if (capabilities) fclose(capabilities); +#endif return xml; }