[libvirt] [PATCH] Implement capabilities for Solaris

# HG changeset patch # User John Levon <john.levon@sun.com> # Date 1231940906 28800 # Node ID a0d98d39955f4f304d318c7c780742ab929eb351 # Parent ddfcba6b4181ab433dce345d66dc399a81c92a3b Implement capabilities for Solaris Use Solaris interfaces to derive the hypervisor capabilities. Signed-off-by: John Levon <john.levon@sun.com> diff --git a/src/xen_internal.c b/src/xen_internal.c --- a/src/xen_internal.c +++ b/src/xen_internal.c @@ -35,6 +35,10 @@ #ifdef HAVE_XEN_SYS_PRIVCMD_H #include <xen/sys/privcmd.h> #endif +#endif + +#ifdef __sun +#include <sys/systeminfo.h> #endif /* required for shutdown flags */ @@ -662,11 +666,8 @@ typedef struct xen_op_v2_dom xen_op_v2_d #ifdef __linux__ #define XEN_HYPERVISOR_SOCKET "/proc/xen/privcmd" #define HYPERVISOR_CAPABILITIES "/sys/hypervisor/properties/capabilities" -#define CPUINFO "/proc/cpuinfo" #elif defined(__sun) #define XEN_HYPERVISOR_SOCKET "/dev/xen/privcmd" -#define HYPERVISOR_CAPABILITIES "" -#define CPUINFO "/dev/cpu/self/cpuid" #else #error "unsupported platform" #endif @@ -2123,7 +2124,7 @@ xenHypervisorBuildCapabilities(virConnec xenHypervisorBuildCapabilities(virConnectPtr conn, const char *hostmachine, int host_pae, - char *hvm_type, + const char *hvm_type, struct guest_arch *guest_archs, int nr_guest_archs) { virCapsPtr caps; @@ -2227,8 +2228,126 @@ xenHypervisorBuildCapabilities(virConnec return NULL; } -/** - * xenHypervisorGetCapabilities: +#ifdef __sun + +static int +get_cpu_flags(virConnectPtr conn, const char **hvm, int *pae, int *longmode) +{ + struct { + uint32_t r_eax, r_ebx, r_ecx, r_edx; + } regs; + + char tmpbuf[20]; + int fd = -1; + int ret = 0; + + /* returns -1, errno 22 if in 32-bit mode */ + *longmode = (sysinfo(SI_ARCHITECTURE_64, tmpbuf, 20) != -1); + + if ((fd = open("/dev/cpu/self/cpuid", O_RDONLY)) == -1 || + pread(fd, ®s, sizeof(regs), 0) != sizeof(regs)) { + virXenError(conn, VIR_ERR_SYSTEM_ERROR, + "couldn't read CPU flags: %s", strerror(errno)); + goto out; + } + + *pae = 0; + *hvm = ""; + + if (strncmp((const char *)®s.r_ebx, "AuthcAMDenti", 12) == 0) { + if (pread(fd, ®s, sizeof (regs), 0x80000001) == sizeof (regs)) { + /* Read secure virtual machine bit (bit 2 of ECX feature ID) */ + if ((regs.r_ecx >> 2) & 1) { + *hvm = "svm"; + } + if ((regs.r_edx >> 6) & 1) + *pae = 1; + } + } else if (strncmp((const char *)®s.r_ebx, "GenuntelineI", 12) == 0) { + if (pread(fd, ®s, sizeof (regs), 0x00000001) == sizeof (regs)) { + /* Read VMXE feature bit (bit 5 of ECX feature ID) */ + if ((regs.r_ecx >> 5) & 1) + *hvm = "vmx"; + if ((regs.r_edx >> 6) & 1) + *pae = 1; + } + } + + ret = 1; + +out: + if (fd != -1) + close(fd); + return ret; +} + +static virCapsPtr +xenHypervisorMakeCapabilitiesSunOS(virConnectPtr conn) +{ + struct guest_arch guest_arches[32]; + int i = 0; + virCapsPtr caps = NULL; + struct utsname utsname; + int pae, longmode; + const char *hvm; + + if (!get_cpu_flags(conn, &hvm, &pae, &longmode)) + return NULL; + + /* Really, this never fails - look at the man-page. */ + uname (&utsname); + + guest_arches[i].model = "i686"; + guest_arches[i].bits = 32; + guest_arches[i].hvm = 0; + guest_arches[i].pae = pae; + guest_arches[i].nonpae = 1; + guest_arches[i].ia64_be = 0; + i++; + + if (longmode) { + guest_arches[i].model = "x86_64"; + guest_arches[i].bits = 64; + guest_arches[i].hvm = 0; + guest_arches[i].pae = 0; + guest_arches[i].nonpae = 1; + guest_arches[i].ia64_be = 0; + i++; + } + + if (hvm[0] != '\0') { + guest_arches[i].model = "i686"; + guest_arches[i].bits = 32; + guest_arches[i].hvm = 1; + guest_arches[i].pae = pae; + guest_arches[i].nonpae = 1; + guest_arches[i].ia64_be = 0; + i++; + + if (longmode) { + guest_arches[i].model = "x86_64"; + guest_arches[i].bits = 64; + guest_arches[i].hvm = 1; + guest_arches[i].pae = 0; + guest_arches[i].nonpae = 1; + guest_arches[i].ia64_be = 0; + i++; + } + } + + if ((caps = xenHypervisorBuildCapabilities(conn, + utsname.machine, + pae, hvm, + guest_arches, i)) == NULL) + virXenError(NULL, VIR_ERR_NO_MEMORY, NULL); + + return caps; +} + +#endif /* __sun */ + +/** + * xenHypervisorMakeCapabilitiesInternal: * @conn: pointer to the connection block * @cpuinfo: file handle containing /proc/cpuinfo data, or NULL * @capabilities: file handle containing /sys/hypervisor/properties/capabilities data, or NULL @@ -2394,6 +2513,9 @@ virCapsPtr virCapsPtr xenHypervisorMakeCapabilities(virConnectPtr conn) { +#ifdef __sun + return xenHypervisorMakeCapabilitiesSunOS(conn); +#else virCapsPtr caps; FILE *cpuinfo, *capabilities; struct utsname utsname; @@ -2432,6 +2554,7 @@ xenHypervisorMakeCapabilities(virConnect fclose(capabilities); return caps; +#endif /* __sun */ }

On Wed, Jan 14, 2009 at 07:20:12AM -0800, john.levon@sun.com wrote:
# HG changeset patch # User John Levon <john.levon@sun.com> # Date 1231940906 28800 # Node ID a0d98d39955f4f304d318c7c780742ab929eb351 # Parent ddfcba6b4181ab433dce345d66dc399a81c92a3b Implement capabilities for Solaris
Use Solaris interfaces to derive the hypervisor capabilities.
Previously your patch for this did a hypercall to fetch the capabilities straight from the hypervisor. Out of interest, why did you chance to deriving everything from CPU ID ? ACK to the patch Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

On Wed, Jan 14, 2009 at 03:38:52PM +0000, Daniel P. Berrange wrote:
Implement capabilities for Solaris
Use Solaris interfaces to derive the hypervisor capabilities.
Previously your patch for this did a hypercall to fetch the capabilities straight from the hypervisor. Out of interest, why did you chance to deriving everything from CPU ID ?
It just seemed unnecessary, as it bought us precisely nothing.
ACK to the patch
As I mentioned on IRC I realised I hadn't quite tested properly, and need more changes... will send out a new version later thanks john

john.levon@sun.com wrote: ... Hi John, This looks fine, but there are a couple of nits.
+#ifdef __sun + +static int +get_cpu_flags(virConnectPtr conn, const char **hvm, int *pae, int *longmode) +{ + struct { + uint32_t r_eax, r_ebx, r_ecx, r_edx; + } regs; + + char tmpbuf[20]; + int fd = -1;
No need to initialize.
+ int ret = 0; + + /* returns -1, errno 22 if in 32-bit mode */ + *longmode = (sysinfo(SI_ARCHITECTURE_64, tmpbuf, 20) != -1);
It'd be nice to use "sizeof tmpbuf", rather than repeating the literal size, "20".
+ if ((fd = open("/dev/cpu/self/cpuid", O_RDONLY)) == -1 || + pread(fd, ®s, sizeof(regs), 0) != sizeof(regs)) { + virXenError(conn, VIR_ERR_SYSTEM_ERROR, + "couldn't read CPU flags: %s", strerror(errno)); + goto out; + } + + *pae = 0; + *hvm = ""; + + if (strncmp((const char *)®s.r_ebx, "AuthcAMDenti", 12) == 0) {
You'll have to use STREQLEN in place of that strncmp, in order for "make syntax-check" to pass.
+ if (pread(fd, ®s, sizeof (regs), 0x80000001) == sizeof (regs)) { + /* Read secure virtual machine bit (bit 2 of ECX feature ID) */ + if ((regs.r_ecx >> 2) & 1) { + *hvm = "svm"; + } + if ((regs.r_edx >> 6) & 1) + *pae = 1; + } + } else if (strncmp((const char *)®s.r_ebx, "GenuntelineI", 12) == 0) {
Here, too. ... + /* Really, this never fails - look at the man-page. */ + uname (&utsname);
participants (4)
-
Daniel P. Berrange
-
Jim Meyering
-
John Levon
-
john.levon@sun.com