]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
x86/jailhouse: Add infrastructure for running in non-root cell
authorJan Kiszka <jan.kiszka@siemens.com>
Mon, 27 Nov 2017 08:11:46 +0000 (09:11 +0100)
committerThomas Gleixner <tglx@linutronix.de>
Sun, 14 Jan 2018 20:11:54 +0000 (21:11 +0100)
The Jailhouse hypervisor is able to statically partition a multicore
system into multiple so-called cells. Linux is used as boot loader and
continues to run in the root cell after Jailhouse is enabled. Linux can
also run in non-root cells.

Jailhouse does not emulate usual x86 devices. It also provides no
complex ACPI but basic platform information that the boot loader
forwards via setup data. This adds the infrastructure to detect when
running in a non-root cell so that the platform can be configured as
required in succeeding steps.

Support is limited to x86-64 so far, primarily because no boot loader
stub exists for i386 and, thus, we wouldn't be able to test the 32-bit
path.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: jailhouse-dev@googlegroups.com
Link: https://lkml.kernel.org/r/7f823d077b38b1a70c526b40b403f85688c137d3.1511770314.git.jan.kiszka@siemens.com
arch/x86/Kconfig
arch/x86/include/asm/hypervisor.h
arch/x86/include/asm/jailhouse_para.h [new file with mode: 0644]
arch/x86/include/uapi/asm/bootparam.h
arch/x86/kernel/Makefile
arch/x86/kernel/cpu/hypervisor.c
arch/x86/kernel/jailhouse.c [new file with mode: 0644]

index ff4e9cd998544c00db08b44f8dd0ee91b7a1ad58..fbea8d15fcfbb6adb2cdffe9c35c5f8fd3d23d7c 100644 (file)
@@ -796,6 +796,14 @@ config PARAVIRT_TIME_ACCOUNTING
 config PARAVIRT_CLOCK
        bool
 
+config JAILHOUSE_GUEST
+       bool "Jailhouse non-root cell support"
+       depends on X86_64
+       ---help---
+         This option allows to run Linux as guest in a Jailhouse non-root
+         cell. You can leave this option disabled if you only want to start
+         Jailhouse and run Linux afterwards in the root cell.
+
 endif #HYPERVISOR_GUEST
 
 config NO_BOOTMEM
index 96aa6b9884dc5b3bc8d54c9ef1c6258eea13a0d0..8c5aaba6633f207e6374f875cd073e8bb2133464 100644 (file)
@@ -28,6 +28,7 @@ enum x86_hypervisor_type {
        X86_HYPER_XEN_PV,
        X86_HYPER_XEN_HVM,
        X86_HYPER_KVM,
+       X86_HYPER_JAILHOUSE,
 };
 
 #ifdef CONFIG_HYPERVISOR_GUEST
diff --git a/arch/x86/include/asm/jailhouse_para.h b/arch/x86/include/asm/jailhouse_para.h
new file mode 100644 (file)
index 0000000..875b543
--- /dev/null
@@ -0,0 +1,26 @@
+/* SPDX-License-Identifier: GPL2.0 */
+
+/*
+ * Jailhouse paravirt_ops implementation
+ *
+ * Copyright (c) Siemens AG, 2015-2017
+ *
+ * Authors:
+ *  Jan Kiszka <jan.kiszka@siemens.com>
+ */
+
+#ifndef _ASM_X86_JAILHOUSE_PARA_H
+#define _ASM_X86_JAILHOUSE_PARA_H
+
+#include <linux/types.h>
+
+#ifdef CONFIG_JAILHOUSE_GUEST
+bool jailhouse_paravirt(void);
+#else
+static inline bool jailhouse_paravirt(void)
+{
+       return false;
+}
+#endif
+
+#endif /* _ASM_X86_JAILHOUSE_PARA_H */
index afdd5ae0fcc41db304db3be9cd88761143dc2d4b..aebf603577587680efaa12d6b44d1b849dfa9eb4 100644 (file)
@@ -9,6 +9,7 @@
 #define SETUP_PCI                      3
 #define SETUP_EFI                      4
 #define SETUP_APPLE_PROPERTIES         5
+#define SETUP_JAILHOUSE                        6
 
 /* ram_size flags */
 #define RAMDISK_IMAGE_START_MASK       0x07FF
@@ -126,6 +127,27 @@ struct boot_e820_entry {
        __u32 type;
 } __attribute__((packed));
 
+/*
+ * Smallest compatible version of jailhouse_setup_data required by this kernel.
+ */
+#define JAILHOUSE_SETUP_REQUIRED_VERSION       1
+
+/*
+ * The boot loader is passing platform information via this Jailhouse-specific
+ * setup data structure.
+ */
+struct jailhouse_setup_data {
+       u16     version;
+       u16     compatible_version;
+       u16     pm_timer_address;
+       u16     num_cpus;
+       u64     pci_mmconfig_base;
+       u32     tsc_khz;
+       u32     apic_khz;
+       u8      standard_ioapic;
+       u8      cpu_ids[255];
+} __attribute__((packed));
+
 /* The so-called "zeropage" */
 struct boot_params {
        struct screen_info screen_info;                 /* 0x000 */
index 81bb565f449740c1d94e057c541db3c84df8bc46..aed9296dccd3288dee7d6c4dc249fd5fc3ddd49a 100644 (file)
@@ -112,6 +112,8 @@ obj-$(CONFIG_PARAVIRT_SPINLOCKS)+= paravirt-spinlocks.o
 obj-$(CONFIG_PARAVIRT_CLOCK)   += pvclock.o
 obj-$(CONFIG_X86_PMEM_LEGACY_DEVICE) += pmem.o
 
+obj-$(CONFIG_JAILHOUSE_GUEST)  += jailhouse.o
+
 obj-$(CONFIG_EISA)             += eisa.o
 obj-$(CONFIG_PCSPKR_PLATFORM)  += pcspeaker.o
 
index bea8d3e24f508704ca80210e6b864bd07e51bfc5..479ca4728de01a698412e4499fc6ac574ef74d78 100644 (file)
@@ -31,6 +31,7 @@ extern const struct hypervisor_x86 x86_hyper_ms_hyperv;
 extern const struct hypervisor_x86 x86_hyper_xen_pv;
 extern const struct hypervisor_x86 x86_hyper_xen_hvm;
 extern const struct hypervisor_x86 x86_hyper_kvm;
+extern const struct hypervisor_x86 x86_hyper_jailhouse;
 
 static const __initconst struct hypervisor_x86 * const hypervisors[] =
 {
@@ -45,6 +46,9 @@ static const __initconst struct hypervisor_x86 * const hypervisors[] =
 #ifdef CONFIG_KVM_GUEST
        &x86_hyper_kvm,
 #endif
+#ifdef CONFIG_JAILHOUSE_GUEST
+       &x86_hyper_jailhouse,
+#endif
 };
 
 enum x86_hypervisor_type x86_hyper_type;
diff --git a/arch/x86/kernel/jailhouse.c b/arch/x86/kernel/jailhouse.c
new file mode 100644 (file)
index 0000000..1186b89
--- /dev/null
@@ -0,0 +1,73 @@
+// SPDX-License-Identifier: GPL2.0
+/*
+ * Jailhouse paravirt_ops implementation
+ *
+ * Copyright (c) Siemens AG, 2015-2017
+ *
+ * Authors:
+ *  Jan Kiszka <jan.kiszka@siemens.com>
+ */
+
+#include <linux/kernel.h>
+#include <asm/cpu.h>
+#include <asm/hypervisor.h>
+#include <asm/setup.h>
+
+static __initdata struct jailhouse_setup_data setup_data;
+
+static uint32_t jailhouse_cpuid_base(void)
+{
+       if (boot_cpu_data.cpuid_level < 0 ||
+           !boot_cpu_has(X86_FEATURE_HYPERVISOR))
+               return 0;
+
+       return hypervisor_cpuid_base("Jailhouse\0\0\0", 0);
+}
+
+static uint32_t __init jailhouse_detect(void)
+{
+       return jailhouse_cpuid_base();
+}
+
+static void __init jailhouse_init_platform(void)
+{
+       u64 pa_data = boot_params.hdr.setup_data;
+       struct setup_data header;
+       void *mapping;
+
+       while (pa_data) {
+               mapping = early_memremap(pa_data, sizeof(header));
+               memcpy(&header, mapping, sizeof(header));
+               early_memunmap(mapping, sizeof(header));
+
+               if (header.type == SETUP_JAILHOUSE &&
+                   header.len >= sizeof(setup_data)) {
+                       pa_data += offsetof(struct setup_data, data);
+
+                       mapping = early_memremap(pa_data, sizeof(setup_data));
+                       memcpy(&setup_data, mapping, sizeof(setup_data));
+                       early_memunmap(mapping, sizeof(setup_data));
+
+                       break;
+               }
+
+               pa_data = header.next;
+       }
+
+       if (!pa_data)
+               panic("Jailhouse: No valid setup data found");
+
+       if (setup_data.compatible_version > JAILHOUSE_SETUP_REQUIRED_VERSION)
+               panic("Jailhouse: Unsupported setup data structure");
+}
+
+bool jailhouse_paravirt(void)
+{
+       return jailhouse_cpuid_base() != 0;
+}
+
+const struct hypervisor_x86 x86_hyper_jailhouse __refconst = {
+       .name                   = "Jailhouse",
+       .detect                 = jailhouse_detect,
+       .init.init_platform     = jailhouse_init_platform,
+};