diff options
author | Jan Kiszka | 2018-01-21 10:32:32 -0600 |
---|---|---|
committer | Jan Kiszka | 2018-01-26 10:46:16 -0600 |
commit | a88684048228fc15bc979abcd533e433f038b370 (patch) | |
tree | 001b76863d316f93b8cd4153f938c8ebef63e9ad | |
parent | 74ed7fecb6d3f6c3f944c3c2e154ec55b6f679f7 (diff) | |
download | jailhouse-a88684048228fc15bc979abcd533e433f038b370.tar.gz jailhouse-a88684048228fc15bc979abcd533e433f038b370.tar.xz jailhouse-a88684048228fc15bc979abcd533e433f038b370.zip |
driver: Avoid dependency on additional kernel symbol exports
If CONFIG_KALLSYMS_ALL is enabled, we can get symbol addresses that the
upstream kernel does not export via kallsyms_lookup_name. We can use
this to avoid a number of kernel patches. Specifically, x86 can become
patch-free once all guest-side support is merged and ivshmem-net is
built as external module (or merged as well).
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
-rw-r--r-- | driver/main.c | 51 |
1 files changed, 42 insertions, 9 deletions
diff --git a/driver/main.c b/driver/main.c index af4930f3..ee585848 100644 --- a/driver/main.c +++ b/driver/main.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <linux/miscdevice.h> | 22 | #include <linux/miscdevice.h> |
23 | #include <linux/firmware.h> | 23 | #include <linux/firmware.h> |
24 | #include <linux/mm.h> | 24 | #include <linux/mm.h> |
25 | #include <linux/kallsyms.h> | ||
25 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(4,11,0) | 26 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(4,11,0) |
26 | #include <linux/sched/signal.h> | 27 | #include <linux/sched/signal.h> |
27 | #endif | 28 | #endif |
@@ -75,9 +76,7 @@ MODULE_FIRMWARE(JAILHOUSE_FW_NAME); | |||
75 | #endif | 76 | #endif |
76 | MODULE_VERSION(JAILHOUSE_VERSION); | 77 | MODULE_VERSION(JAILHOUSE_VERSION); |
77 | 78 | ||
78 | #if defined(CONFIG_ARM) || defined(CONFIG_ARM64) | ||
79 | extern unsigned int __hyp_stub_vectors[]; | 79 | extern unsigned int __hyp_stub_vectors[]; |
80 | #endif | ||
81 | 80 | ||
82 | struct console_state { | 81 | struct console_state { |
83 | unsigned int head; | 82 | unsigned int head; |
@@ -96,6 +95,17 @@ static struct jailhouse_console* volatile console_page; | |||
96 | static bool console_available; | 95 | static bool console_available; |
97 | static struct resource *hypervisor_mem_res; | 96 | static struct resource *hypervisor_mem_res; |
98 | 97 | ||
98 | static typeof(ioremap_page_range) *ioremap_page_range_sym; | ||
99 | #ifdef CONFIG_X86 | ||
100 | static typeof(lapic_timer_frequency) *lapic_timer_frequency_sym; | ||
101 | #endif | ||
102 | #ifdef CONFIG_ARM | ||
103 | static typeof(__boot_cpu_mode) *__boot_cpu_mode_sym; | ||
104 | #endif | ||
105 | #if defined(CONFIG_ARM) || defined(CONFIG_ARM64) | ||
106 | static typeof(__hyp_stub_vectors) *__hyp_stub_vectors_sym; | ||
107 | #endif | ||
108 | |||
99 | /* last_console contains three members: | 109 | /* last_console contains three members: |
100 | * - valid: indicates if content in the page member is present | 110 | * - valid: indicates if content in the page member is present |
101 | * - id: hint for the consumer if it already consumed the content | 111 | * - id: hint for the consumer if it already consumed the content |
@@ -191,9 +201,9 @@ void *jailhouse_ioremap(phys_addr_t phys, unsigned long virt, | |||
191 | return NULL; | 201 | return NULL; |
192 | vma->phys_addr = phys; | 202 | vma->phys_addr = phys; |
193 | 203 | ||
194 | if (ioremap_page_range((unsigned long)vma->addr, | 204 | if (ioremap_page_range_sym((unsigned long)vma->addr, |
195 | (unsigned long)vma->addr + size, phys, | 205 | (unsigned long)vma->addr + size, phys, |
196 | PAGE_KERNEL_EXEC)) { | 206 | PAGE_KERNEL_EXEC)) { |
197 | vunmap(vma->addr); | 207 | vunmap(vma->addr); |
198 | return NULL; | 208 | return NULL; |
199 | } | 209 | } |
@@ -374,7 +384,9 @@ static int jailhouse_cmd_enable(struct jailhouse_system __user *arg) | |||
374 | goto error_unlock; | 384 | goto error_unlock; |
375 | 385 | ||
376 | #ifdef CONFIG_ARM | 386 | #ifdef CONFIG_ARM |
377 | if (!is_hyp_mode_available()) { | 387 | /* open-coded is_hyp_mode_available to use __boot_cpu_mode_sym */ |
388 | if ((*__boot_cpu_mode_sym & MODE_MASK) != HYP_MODE || | ||
389 | (*__boot_cpu_mode_sym) & BOOT_CPU_MODE_MISMATCH) { | ||
378 | pr_err("jailhouse: HYP mode not available\n"); | 390 | pr_err("jailhouse: HYP mode not available\n"); |
379 | err = -ENODEV; | 391 | err = -ENODEV; |
380 | goto error_put_module; | 392 | goto error_put_module; |
@@ -444,7 +456,7 @@ static int jailhouse_cmd_enable(struct jailhouse_system __user *arg) | |||
444 | header->max_cpus = max_cpus; | 456 | header->max_cpus = max_cpus; |
445 | 457 | ||
446 | #if defined(CONFIG_ARM) || defined(CONFIG_ARM64) | 458 | #if defined(CONFIG_ARM) || defined(CONFIG_ARM64) |
447 | header->arm_linux_hyp_vectors = virt_to_phys(__hyp_stub_vectors); | 459 | header->arm_linux_hyp_vectors = virt_to_phys(*__hyp_stub_vectors_sym); |
448 | #if LINUX_VERSION_CODE < KERNEL_VERSION(4,12,0) | 460 | #if LINUX_VERSION_CODE < KERNEL_VERSION(4,12,0) |
449 | header->arm_linux_hyp_abi = HYP_STUB_ABI_LEGACY; | 461 | header->arm_linux_hyp_abi = HYP_STUB_ABI_LEGACY; |
450 | #else | 462 | #else |
@@ -511,7 +523,7 @@ static int jailhouse_cmd_enable(struct jailhouse_system __user *arg) | |||
511 | config->platform_info.x86.tsc_khz = tsc_khz; | 523 | config->platform_info.x86.tsc_khz = tsc_khz; |
512 | if (config->platform_info.x86.apic_khz == 0) | 524 | if (config->platform_info.x86.apic_khz == 0) |
513 | config->platform_info.x86.apic_khz = | 525 | config->platform_info.x86.apic_khz = |
514 | lapic_timer_frequency / (1000 / HZ); | 526 | *lapic_timer_frequency_sym / (1000 / HZ); |
515 | #endif | 527 | #endif |
516 | 528 | ||
517 | err = jailhouse_cell_prepare_root(&config->root_cell); | 529 | err = jailhouse_cell_prepare_root(&config->root_cell); |
@@ -649,7 +661,7 @@ static int jailhouse_cmd_disable(void) | |||
649 | * This flag has been set when onlining a CPU under Jailhouse | 661 | * This flag has been set when onlining a CPU under Jailhouse |
650 | * supervision into SVC instead of HYP mode. | 662 | * supervision into SVC instead of HYP mode. |
651 | */ | 663 | */ |
652 | __boot_cpu_mode &= ~BOOT_CPU_MODE_MISMATCH; | 664 | *__boot_cpu_mode_sym &= ~BOOT_CPU_MODE_MISMATCH; |
653 | #endif | 665 | #endif |
654 | 666 | ||
655 | atomic_set(&call_done, 0); | 667 | atomic_set(&call_done, 0); |
@@ -850,6 +862,27 @@ static int __init jailhouse_init(void) | |||
850 | { | 862 | { |
851 | int err; | 863 | int err; |
852 | 864 | ||
865 | #ifdef CONFIG_KALLSYMS_ALL | ||
866 | #define RESOLVE_EXTERNAL_SYMBOL(symbol) \ | ||
867 | symbol##_sym = (void *)kallsyms_lookup_name(#symbol); \ | ||
868 | if (!symbol##_sym) \ | ||
869 | return -EINVAL | ||
870 | #else | ||
871 | #define RESOLVE_EXTERNAL_SYMBOL(symbol) \ | ||
872 | symbol##_sym = &symbol | ||
873 | #endif | ||
874 | |||
875 | RESOLVE_EXTERNAL_SYMBOL(ioremap_page_range); | ||
876 | #ifdef CONFIG_X86 | ||
877 | RESOLVE_EXTERNAL_SYMBOL(lapic_timer_frequency); | ||
878 | #endif | ||
879 | #ifdef CONFIG_ARM | ||
880 | RESOLVE_EXTERNAL_SYMBOL(__boot_cpu_mode); | ||
881 | #endif | ||
882 | #if defined(CONFIG_ARM) || defined(CONFIG_ARM64) | ||
883 | RESOLVE_EXTERNAL_SYMBOL(__hyp_stub_vectors); | ||
884 | #endif | ||
885 | |||
853 | jailhouse_dev = root_device_register("jailhouse"); | 886 | jailhouse_dev = root_device_register("jailhouse"); |
854 | if (IS_ERR(jailhouse_dev)) | 887 | if (IS_ERR(jailhouse_dev)) |
855 | return PTR_ERR(jailhouse_dev); | 888 | return PTR_ERR(jailhouse_dev); |