]> rtime.felk.cvut.cz Git - jailhouse.git/blob - driver/main.c
39ab7946cff56f13efce6ff7721a99c43a510924
[jailhouse.git] / driver / main.c
1 /*
2  * Jailhouse, a Linux-based partitioning hypervisor
3  *
4  * Copyright (c) Siemens AG, 2013-2015
5  * Copyright (c) Valentine Sinitsyn, 2014
6  *
7  * Authors:
8  *  Jan Kiszka <jan.kiszka@siemens.com>
9  *  Valentine Sinitsyn <valentine.sinitsyn@gmail.com>
10  *
11  * This work is licensed under the terms of the GNU GPL, version 2.  See
12  * the COPYING file in the top-level directory.
13  */
14
15 #include <linux/kernel.h>
16 #include <linux/module.h>
17 #include <linux/device.h>
18 #include <linux/fs.h>
19 #include <linux/miscdevice.h>
20 #include <linux/firmware.h>
21 #include <linux/mm.h>
22 #include <linux/smp.h>
23 #include <linux/uaccess.h>
24 #include <linux/reboot.h>
25 #include <linux/vmalloc.h>
26 #include <linux/io.h>
27 #include <asm/smp.h>
28 #include <asm/cacheflush.h>
29 #include <asm/tlbflush.h>
30
31 #include "cell.h"
32 #include "jailhouse.h"
33 #include "main.h"
34 #include "pci.h"
35 #include "sysfs.h"
36
37 #include <jailhouse/header.h>
38 #include <jailhouse/hypercall.h>
39 #include <generated/version.h>
40
41 #ifdef CONFIG_X86_32
42 #error 64-bit kernel required!
43 #endif
44
45 #if JAILHOUSE_CELL_ID_NAMELEN != JAILHOUSE_CELL_NAME_MAXLEN
46 # warning JAILHOUSE_CELL_ID_NAMELEN and JAILHOUSE_CELL_NAME_MAXLEN out of sync!
47 #endif
48
49 /* For compatibility with older kernel versions */
50 #include <linux/version.h>
51
52 #ifdef CONFIG_X86
53 #define JAILHOUSE_AMD_FW_NAME   "jailhouse-amd.bin"
54 #define JAILHOUSE_INTEL_FW_NAME "jailhouse-intel.bin"
55 #else
56 #define JAILHOUSE_FW_NAME       "jailhouse.bin"
57 #endif
58
59 MODULE_DESCRIPTION("Management driver for Jailhouse partitioning hypervisor");
60 MODULE_LICENSE("GPL");
61 #ifdef CONFIG_X86
62 MODULE_FIRMWARE(JAILHOUSE_AMD_FW_NAME);
63 MODULE_FIRMWARE(JAILHOUSE_INTEL_FW_NAME);
64 #else
65 MODULE_FIRMWARE(JAILHOUSE_FW_NAME);
66 #endif
67 MODULE_VERSION(JAILHOUSE_VERSION);
68
69 DEFINE_MUTEX(jailhouse_lock);
70 bool jailhouse_enabled;
71
72 static struct device *jailhouse_dev;
73 static void *hypervisor_mem;
74 static unsigned long hv_core_and_percpu_size;
75 static atomic_t call_done;
76 static int error_code;
77
78 #ifdef CONFIG_X86
79 bool jailhouse_use_vmcall;
80
81 static void init_hypercall(void)
82 {
83         jailhouse_use_vmcall = boot_cpu_has(X86_FEATURE_VMX);
84 }
85 #else /* !CONFIG_X86 */
86 static void init_hypercall(void)
87 {
88 }
89 #endif
90
91 static long get_max_cpus(u32 cpu_set_size,
92                          const struct jailhouse_system __user *system_config)
93 {
94         u8 __user *cpu_set =
95                 (u8 __user *)jailhouse_cell_cpu_set(
96                                 (const struct jailhouse_cell_desc * __force)
97                                 &system_config->root_cell);
98         unsigned int pos = cpu_set_size;
99         long max_cpu_id;
100         u8 bitmap;
101
102         while (pos-- > 0) {
103                 if (get_user(bitmap, cpu_set + pos))
104                         return -EFAULT;
105                 max_cpu_id = fls(bitmap);
106                 if (max_cpu_id > 0)
107                         return pos * 8 + max_cpu_id;
108         }
109         return -EINVAL;
110 }
111
112 void *jailhouse_ioremap(phys_addr_t phys, unsigned long virt,
113                         unsigned long size)
114 {
115         struct vm_struct *vma;
116
117         size = PAGE_ALIGN(size);
118         if (virt)
119                 vma = __get_vm_area(size, VM_IOREMAP, virt,
120                                     virt + size + PAGE_SIZE);
121         else
122                 vma = __get_vm_area(size, VM_IOREMAP, VMALLOC_START,
123                                     VMALLOC_END);
124         if (!vma)
125                 return NULL;
126         vma->phys_addr = phys;
127
128         if (ioremap_page_range((unsigned long)vma->addr,
129                                (unsigned long)vma->addr + size, phys,
130                                PAGE_KERNEL_EXEC)) {
131                 vunmap(vma->addr);
132                 return NULL;
133         }
134
135         return vma->addr;
136 }
137
138 static void enter_hypervisor(void *info)
139 {
140         struct jailhouse_header *header = info;
141         unsigned int cpu = smp_processor_id();
142         int err;
143
144         if (cpu < header->max_cpus)
145                 /* either returns 0 or the same error code across all CPUs */
146                 err = header->entry(cpu);
147         else
148                 err = -EINVAL;
149
150         if (err)
151                 error_code = err;
152
153 #if defined(CONFIG_X86) && LINUX_VERSION_CODE >= KERNEL_VERSION(4,0,0)
154         /* on Intel, VMXE is now on - update the shadow */
155         cr4_init_shadow();
156 #endif
157
158         atomic_inc(&call_done);
159 }
160
161 static inline const char * jailhouse_fw_name(void)
162 {
163 #ifdef CONFIG_X86
164         if (boot_cpu_has(X86_FEATURE_SVM))
165                 return JAILHOUSE_AMD_FW_NAME;
166         if (boot_cpu_has(X86_FEATURE_VMX))
167                 return JAILHOUSE_INTEL_FW_NAME;
168         return NULL;
169 #else
170         return JAILHOUSE_FW_NAME;
171 #endif
172 }
173
174 static int jailhouse_cmd_enable(struct jailhouse_system __user *arg)
175 {
176         const struct firmware *hypervisor;
177         struct jailhouse_system config_header;
178         struct jailhouse_system *config;
179         struct jailhouse_memory *hv_mem = &config_header.hypervisor_memory;
180         struct jailhouse_header *header;
181         void __iomem *console = NULL;
182         unsigned long config_size;
183         const char *fw_name;
184         long max_cpus;
185         int err;
186
187         fw_name = jailhouse_fw_name();
188         if (!fw_name) {
189                 pr_err("jailhouse: Missing or unsupported HVM technology\n");
190                 return -ENODEV;
191         }
192
193         if (copy_from_user(&config_header, arg, sizeof(config_header)))
194                 return -EFAULT;
195
196         if (memcmp(config_header.signature, JAILHOUSE_SYSTEM_SIGNATURE,
197                    sizeof(config_header.signature)) != 0) {
198                 pr_err("jailhouse: Not a system configuration\n");
199                 return -EINVAL;
200         }
201
202         config_header.root_cell.name[JAILHOUSE_CELL_NAME_MAXLEN] = 0;
203
204         max_cpus = get_max_cpus(config_header.root_cell.cpu_set_size, arg);
205         if (max_cpus < 0)
206                 return max_cpus;
207         if (max_cpus > UINT_MAX)
208                 return -EINVAL;
209
210         if (mutex_lock_interruptible(&jailhouse_lock) != 0)
211                 return -EINTR;
212
213         err = -EBUSY;
214         if (jailhouse_enabled || !try_module_get(THIS_MODULE))
215                 goto error_unlock;
216
217         err = request_firmware(&hypervisor, fw_name, jailhouse_dev);
218         if (err) {
219                 pr_err("jailhouse: Missing hypervisor image %s\n", fw_name);
220                 goto error_put_module;
221         }
222
223         header = (struct jailhouse_header *)hypervisor->data;
224
225         err = -EINVAL;
226         if (memcmp(header->signature, JAILHOUSE_SIGNATURE,
227                    sizeof(header->signature)) != 0 ||
228             hypervisor->size >= hv_mem->size)
229                 goto error_release_fw;
230
231         hv_core_and_percpu_size = header->core_size +
232                 max_cpus * header->percpu_size;
233         config_size = jailhouse_system_config_size(&config_header);
234         if (hv_core_and_percpu_size >= hv_mem->size ||
235             config_size >= hv_mem->size - hv_core_and_percpu_size)
236                 goto error_release_fw;
237
238         hypervisor_mem = jailhouse_ioremap(hv_mem->phys_start, JAILHOUSE_BASE,
239                                            hv_mem->size);
240         if (!hypervisor_mem) {
241                 pr_err("jailhouse: Unable to map RAM reserved for hypervisor "
242                        "at %08lx\n", (unsigned long)hv_mem->phys_start);
243                 goto error_release_fw;
244         }
245
246         memcpy(hypervisor_mem, hypervisor->data, hypervisor->size);
247         memset(hypervisor_mem + hypervisor->size, 0,
248                hv_mem->size - hypervisor->size);
249
250         header = (struct jailhouse_header *)hypervisor_mem;
251         header->max_cpus = max_cpus;
252
253         config = (struct jailhouse_system *)
254                 (hypervisor_mem + hv_core_and_percpu_size);
255         if (copy_from_user(config, arg, config_size)) {
256                 err = -EFAULT;
257                 goto error_unmap;
258         }
259
260         if (config->debug_console.flags & JAILHOUSE_MEM_IO) {
261                 console = ioremap(config->debug_console.phys_start,
262                                   config->debug_console.size);
263                 if (!console) {
264                         err = -EINVAL;
265                         pr_err("jailhouse: Unable to map hypervisor debug "
266                                "console at %08lx\n",
267                                (unsigned long)config->debug_console.phys_start);
268                         goto error_unmap;
269                 }
270                 /* The hypervisor has no notion of address spaces, so we need
271                  * to enforce conversion. */
272                 header->debug_console_base = (void * __force)console;
273         }
274
275         err = jailhouse_cell_prepare_root(&config->root_cell);
276         if (err)
277                 goto error_unmap;
278
279         error_code = 0;
280
281         preempt_disable();
282
283         header->online_cpus = num_online_cpus();
284
285         atomic_set(&call_done, 0);
286         on_each_cpu(enter_hypervisor, header, 0);
287         while (atomic_read(&call_done) != num_online_cpus())
288                 cpu_relax();
289
290         preempt_enable();
291
292         if (error_code) {
293                 err = error_code;
294                 goto error_free_cell;
295         }
296
297         if (console)
298                 iounmap(console);
299
300         release_firmware(hypervisor);
301
302         jailhouse_cell_register_root();
303
304         jailhouse_enabled = true;
305
306         mutex_unlock(&jailhouse_lock);
307
308         pr_info("The Jailhouse is opening.\n");
309
310         return 0;
311
312 error_free_cell:
313         jailhouse_cell_delete_root();
314
315 error_unmap:
316         vunmap(hypervisor_mem);
317         if (console)
318                 iounmap(console);
319
320 error_release_fw:
321         release_firmware(hypervisor);
322
323 error_put_module:
324         module_put(THIS_MODULE);
325
326 error_unlock:
327         mutex_unlock(&jailhouse_lock);
328         return err;
329 }
330
331 static void leave_hypervisor(void *info)
332 {
333         void *page;
334         int err;
335
336         /* Touch each hypervisor page we may need during the switch so that
337          * the active mm definitely contains all mappings. At least x86 does
338          * not support taking any faults while switching worlds. */
339         for (page = hypervisor_mem;
340              page < hypervisor_mem + hv_core_and_percpu_size;
341              page += PAGE_SIZE)
342                 readl((void __iomem *)page);
343
344         /* either returns 0 or the same error code across all CPUs */
345         err = jailhouse_call(JAILHOUSE_HC_DISABLE);
346         if (err)
347                 error_code = err;
348
349 #if defined(CONFIG_X86) && LINUX_VERSION_CODE >= KERNEL_VERSION(4,0,0)
350         /* on Intel, VMXE is now off - update the shadow */
351         cr4_init_shadow();
352 #endif
353
354         atomic_inc(&call_done);
355 }
356
357 static int jailhouse_cmd_disable(void)
358 {
359         int err;
360
361         if (mutex_lock_interruptible(&jailhouse_lock) != 0)
362                 return -EINTR;
363
364         if (!jailhouse_enabled) {
365                 err = -EINVAL;
366                 goto unlock_out;
367         }
368
369         error_code = 0;
370
371         preempt_disable();
372
373         if (num_online_cpus() != cpumask_weight(&root_cell->cpus_assigned)) {
374                 /*
375                  * Not all assigned CPUs are currently online. If we disable
376                  * now, we will loose the offlined ones.
377                  */
378
379                 preempt_enable();
380
381                 err = -EBUSY;
382                 goto unlock_out;
383         }
384
385         atomic_set(&call_done, 0);
386         on_each_cpu(leave_hypervisor, NULL, 0);
387         while (atomic_read(&call_done) != num_online_cpus())
388                 cpu_relax();
389
390         preempt_enable();
391
392         err = error_code;
393         if (err)
394                 goto unlock_out;
395
396         vunmap(hypervisor_mem);
397
398         jailhouse_cell_delete_all();
399         jailhouse_enabled = false;
400         module_put(THIS_MODULE);
401
402         pr_info("The Jailhouse was closed.\n");
403
404 unlock_out:
405         mutex_unlock(&jailhouse_lock);
406
407         return err;
408 }
409
410 static long jailhouse_ioctl(struct file *file, unsigned int ioctl,
411                             unsigned long arg)
412 {
413         long err;
414
415         switch (ioctl) {
416         case JAILHOUSE_ENABLE:
417                 err = jailhouse_cmd_enable(
418                         (struct jailhouse_system __user *)arg);
419                 break;
420         case JAILHOUSE_DISABLE:
421                 err = jailhouse_cmd_disable();
422                 break;
423         case JAILHOUSE_CELL_CREATE:
424                 err = jailhouse_cmd_cell_create(
425                         (struct jailhouse_cell_create __user *)arg);
426                 break;
427         case JAILHOUSE_CELL_LOAD:
428                 err = jailhouse_cmd_cell_load(
429                         (struct jailhouse_cell_load __user *)arg);
430                 break;
431         case JAILHOUSE_CELL_START:
432                 err = jailhouse_cmd_cell_start((const char __user *)arg);
433                 break;
434         case JAILHOUSE_CELL_DESTROY:
435                 err = jailhouse_cmd_cell_destroy((const char __user *)arg);
436                 break;
437         default:
438                 err = -EINVAL;
439                 break;
440         }
441
442         return err;
443 }
444
445 static const struct file_operations jailhouse_fops = {
446         .owner = THIS_MODULE,
447         .unlocked_ioctl = jailhouse_ioctl,
448         .compat_ioctl = jailhouse_ioctl,
449         .llseek = noop_llseek,
450 };
451
452 static struct miscdevice jailhouse_misc_dev = {
453         .minor = MISC_DYNAMIC_MINOR,
454         .name = "jailhouse",
455         .fops = &jailhouse_fops,
456 };
457
458 static int jailhouse_shutdown_notify(struct notifier_block *unused1,
459                                      unsigned long unused2, void *unused3)
460 {
461         int err;
462
463         err = jailhouse_cmd_disable();
464         if (err && err != -EINVAL)
465                 pr_emerg("jailhouse: ordered shutdown failed!\n");
466
467         return NOTIFY_DONE;
468 }
469
470 static struct notifier_block jailhouse_shutdown_nb = {
471         .notifier_call = jailhouse_shutdown_notify,
472 };
473
474 static int __init jailhouse_init(void)
475 {
476         int err;
477
478         jailhouse_dev = root_device_register("jailhouse");
479         if (IS_ERR(jailhouse_dev))
480                 return PTR_ERR(jailhouse_dev);
481
482         err = jailhouse_sysfs_init(jailhouse_dev);
483         if (err)
484                 goto unreg_dev;
485
486         err = misc_register(&jailhouse_misc_dev);
487         if (err)
488                 goto exit_sysfs;
489
490         err = jailhouse_pci_register();
491         if (err)
492                 goto exit_misc;
493
494         register_reboot_notifier(&jailhouse_shutdown_nb);
495
496         init_hypercall();
497
498         return 0;
499 exit_misc:
500         misc_deregister(&jailhouse_misc_dev);
501
502 exit_sysfs:
503         jailhouse_sysfs_exit(jailhouse_dev);
504
505 unreg_dev:
506         root_device_unregister(jailhouse_dev);
507         return err;
508 }
509
510 static void __exit jailhouse_exit(void)
511 {
512         unregister_reboot_notifier(&jailhouse_shutdown_nb);
513         misc_deregister(&jailhouse_misc_dev);
514         jailhouse_sysfs_exit(jailhouse_dev);
515         jailhouse_pci_unregister();
516         root_device_unregister(jailhouse_dev);
517 }
518
519 module_init(jailhouse_init);
520 module_exit(jailhouse_exit);