]> rtime.felk.cvut.cz Git - jailhouse.git/commitdiff
x86: Implement standard hypervisor detection protocol
authorJan Kiszka <jan.kiszka@siemens.com>
Fri, 1 May 2015 11:00:09 +0000 (13:00 +0200)
committerJan Kiszka <jan.kiszka@siemens.com>
Fri, 22 May 2015 04:55:21 +0000 (06:55 +0200)
This provides cpuid-based Jailhouse detection conforming to the protocol
also used by other major hypervisors: set bit 31 of ecx for function
0x01, provide a signature via function 0x40000000 and a so far empty
feature set via function 0x40000001.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
Documentation/hypervisor-interfaces.txt
hypervisor/arch/x86/include/asm/jailhouse_hypercall.h
hypervisor/arch/x86/include/asm/processor.h
hypervisor/arch/x86/vcpu.c

index 517c30c5218d769d2df59387d9831db6369ec4b0..e9f0ae0efc8a6133160810e23fd7a4296e9e721b 100644 (file)
@@ -1,12 +1,55 @@
 Hypervisor Interface for Cells
 ==============================
 
-The Jailhouse hypervisor provides two kinds of interfaces to interact with its
-cells during runtime. One is a set of hypercalls which cells can be invoked
-synchronously by executing architecture specific instructions that switch to
-hypervisor mode. The other interface consists of variables located in a
-per-cell memory region that is shared between hypervisor and that particular
-cell.
+The Jailhouse hypervisor provides three kinds of interfaces to interact with
+its cells during runtime. The first is a read-only detection interface. The
+second is a set of hypercalls which cells can invoke synchronously by executing
+architecture specific instructions that switch to hypervisor mode. The third
+interface consists of variables located in a per-cell memory region that is
+shared between hypervisor and that particular cell.
+
+
+Detection
+---------
+
+This interface is useful for cell code that should work not only inside a
+Jailhouse cell. The ABI is architecture specific.
+
+
+x86 ABI
+- - - -
+
+On x86, Jailhouse modifies the register values returned when executing the
+cpuid instruction as follows:
+
+
+Function (EAX): 0x01
+Result in EAX:  passed unmodified
+          EBX:  passed unmodified
+          ECX:  bit 31 ("hypervisor") set, all other bits passed unmodified
+          EDX:  passed unmodified
+
+Note: A cell should first check if bit 31 is set in ECX before querying the
+signature function 0x40000000.
+
+
+Function (EAX): 0x40000000 (signature)
+Result in EAX:  highest supported hypervisor function, currently 0x40000001
+          EBX:  0x6c69614a ("Jail")
+          ECX:  0x73756f68 ("hous")
+          EDX:  0x00000065 ("e")
+
+Note: A cell should first validate the presence of Jailhouse via both checking
+the hypervisor feature bit (function 31) and then the signature (function
+0x40000000) before evaluating the returned values of the feature function
+0x40000001.
+
+
+Function (EAX): 0x40000001 (features)
+Result in EAX:  0
+          EBX:  0
+          ECX:  0
+          EDX:  0
 
 
 Hypercalls
index db3ed592ac4c92d3e4966b2f5820959e8a121d62..b128447cc45c229a35f08b3e97fe1cc8a6229561 100644 (file)
 #define JAILHOUSE_CPU_STAT_VMEXITS_XSETBV      JAILHOUSE_GENERIC_CPU_STATS + 5
 #define JAILHOUSE_NUM_CPU_STATS                        JAILHOUSE_GENERIC_CPU_STATS + 6
 
+/* CPUID interface */
+#define JAILHOUSE_CPUID_SIGNATURE              0x40000000
+#define JAILHOUSE_CPUID_FEATURES               0x40000001
+
 #ifdef __ASSEMBLY__
 
 #define __MAKE_UL(x)   x
index 74673ed8412da19f6753c206f6e8d4e044e70514..7dfc84615ff7efc7c79d8c4d38262035dc30b044 100644 (file)
@@ -25,6 +25,7 @@
 /* leaf 0x01, ECX */
 #define X86_FEATURE_VMX                                        (1 << 5)
 #define X86_FEATURE_XSAVE                              (1 << 26)
+#define X86_FEATURE_HYPERVISOR                         (1 << 31)
 
 /* leaf 0x80000001, ECX */
 #define X86_FEATURE_SVM                                        (1 << 2)
index 16b5db232a3ad73af0d03c5245e2740469369f67..c72ccd917834d36134c6f6bcca3bce7d77ea9865 100644 (file)
@@ -313,18 +313,38 @@ bool vcpu_handle_msr_write(void)
 
 void vcpu_handle_cpuid(void)
 {
+       static const char signature[12] = "Jailhouse";
        union registers *guest_regs = &this_cpu_data()->guest_regs;
+       u32 function = guest_regs->rax;
 
        this_cpu_data()->stats[JAILHOUSE_CPU_STAT_VMEXITS_CPUID]++;
 
-       /* clear upper 32 bits of the involved registers */
-       guest_regs->rax &= 0xffffffff;
-       guest_regs->rbx &= 0xffffffff;
-       guest_regs->rcx &= 0xffffffff;
-       guest_regs->rdx &= 0xffffffff;
-
-       cpuid((u32 *)&guest_regs->rax, (u32 *)&guest_regs->rbx,
-             (u32 *)&guest_regs->rcx, (u32 *)&guest_regs->rdx);
+       switch (function) {
+       case JAILHOUSE_CPUID_SIGNATURE:
+               guest_regs->rax = JAILHOUSE_CPUID_FEATURES;
+               guest_regs->rbx = *(u32 *)signature;
+               guest_regs->rcx = *(u32 *)(signature + 4);
+               guest_regs->rdx = *(u32 *)(signature + 8);
+               break;
+       case JAILHOUSE_CPUID_FEATURES:
+               guest_regs->rax = 0;
+               guest_regs->rbx = 0;
+               guest_regs->rcx = 0;
+               guest_regs->rdx = 0;
+               break;
+       default:
+               /* clear upper 32 bits of the involved registers */
+               guest_regs->rax &= 0xffffffff;
+               guest_regs->rbx &= 0xffffffff;
+               guest_regs->rcx &= 0xffffffff;
+               guest_regs->rdx &= 0xffffffff;
+
+               cpuid((u32 *)&guest_regs->rax, (u32 *)&guest_regs->rbx,
+                     (u32 *)&guest_regs->rcx, (u32 *)&guest_regs->rdx);
+               if (function == 0x01)
+                       guest_regs->rcx |= X86_FEATURE_HYPERVISOR;
+               break;
+       }
 
        vcpu_skip_emulated_instruction(X86_INST_LEN_CPUID);
 }