diff options
Diffstat (limited to 'arch/x86/kernel/kvmclock.c')
-rw-r--r-- | arch/x86/kernel/kvmclock.c | 52 |
1 files changed, 49 insertions, 3 deletions
diff --git a/arch/x86/kernel/kvmclock.c b/arch/x86/kernel/kvmclock.c index 1e6764648af3..013fe3d21dbb 100644 --- a/arch/x86/kernel/kvmclock.c +++ b/arch/x86/kernel/kvmclock.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include <linux/sched/clock.h> | 28 | #include <linux/sched/clock.h> |
29 | #include <linux/mm.h> | 29 | #include <linux/mm.h> |
30 | #include <linux/slab.h> | 30 | #include <linux/slab.h> |
31 | #include <linux/set_memory.h> | ||
31 | 32 | ||
32 | #include <asm/hypervisor.h> | 33 | #include <asm/hypervisor.h> |
33 | #include <asm/mem_encrypt.h> | 34 | #include <asm/mem_encrypt.h> |
@@ -61,9 +62,10 @@ early_param("no-kvmclock-vsyscall", parse_no_kvmclock_vsyscall); | |||
61 | (PAGE_SIZE / sizeof(struct pvclock_vsyscall_time_info)) | 62 | (PAGE_SIZE / sizeof(struct pvclock_vsyscall_time_info)) |
62 | 63 | ||
63 | static struct pvclock_vsyscall_time_info | 64 | static struct pvclock_vsyscall_time_info |
64 | hv_clock_boot[HVC_BOOT_ARRAY_SIZE] __aligned(PAGE_SIZE); | 65 | hv_clock_boot[HVC_BOOT_ARRAY_SIZE] __bss_decrypted __aligned(PAGE_SIZE); |
65 | static struct pvclock_wall_clock wall_clock; | 66 | static struct pvclock_wall_clock wall_clock __bss_decrypted; |
66 | static DEFINE_PER_CPU(struct pvclock_vsyscall_time_info *, hv_clock_per_cpu); | 67 | static DEFINE_PER_CPU(struct pvclock_vsyscall_time_info *, hv_clock_per_cpu); |
68 | static struct pvclock_vsyscall_time_info *hvclock_mem; | ||
67 | 69 | ||
68 | static inline struct pvclock_vcpu_time_info *this_cpu_pvti(void) | 70 | static inline struct pvclock_vcpu_time_info *this_cpu_pvti(void) |
69 | { | 71 | { |
@@ -236,6 +238,45 @@ static void kvm_shutdown(void) | |||
236 | native_machine_shutdown(); | 238 | native_machine_shutdown(); |
237 | } | 239 | } |
238 | 240 | ||
241 | static void __init kvmclock_init_mem(void) | ||
242 | { | ||
243 | unsigned long ncpus; | ||
244 | unsigned int order; | ||
245 | struct page *p; | ||
246 | int r; | ||
247 | |||
248 | if (HVC_BOOT_ARRAY_SIZE >= num_possible_cpus()) | ||
249 | return; | ||
250 | |||
251 | ncpus = num_possible_cpus() - HVC_BOOT_ARRAY_SIZE; | ||
252 | order = get_order(ncpus * sizeof(*hvclock_mem)); | ||
253 | |||
254 | p = alloc_pages(GFP_KERNEL, order); | ||
255 | if (!p) { | ||
256 | pr_warn("%s: failed to alloc %d pages", __func__, (1U << order)); | ||
257 | return; | ||
258 | } | ||
259 | |||
260 | hvclock_mem = page_address(p); | ||
261 | |||
262 | /* | ||
263 | * hvclock is shared between the guest and the hypervisor, must | ||
264 | * be mapped decrypted. | ||
265 | */ | ||
266 | if (sev_active()) { | ||
267 | r = set_memory_decrypted((unsigned long) hvclock_mem, | ||
268 | 1UL << order); | ||
269 | if (r) { | ||
270 | __free_pages(p, order); | ||
271 | hvclock_mem = NULL; | ||
272 | pr_warn("kvmclock: set_memory_decrypted() failed. Disabling\n"); | ||
273 | return; | ||
274 | } | ||
275 | } | ||
276 | |||
277 | memset(hvclock_mem, 0, PAGE_SIZE << order); | ||
278 | } | ||
279 | |||
239 | static int __init kvm_setup_vsyscall_timeinfo(void) | 280 | static int __init kvm_setup_vsyscall_timeinfo(void) |
240 | { | 281 | { |
241 | #ifdef CONFIG_X86_64 | 282 | #ifdef CONFIG_X86_64 |
@@ -250,6 +291,9 @@ static int __init kvm_setup_vsyscall_timeinfo(void) | |||
250 | 291 | ||
251 | kvm_clock.archdata.vclock_mode = VCLOCK_PVCLOCK; | 292 | kvm_clock.archdata.vclock_mode = VCLOCK_PVCLOCK; |
252 | #endif | 293 | #endif |
294 | |||
295 | kvmclock_init_mem(); | ||
296 | |||
253 | return 0; | 297 | return 0; |
254 | } | 298 | } |
255 | early_initcall(kvm_setup_vsyscall_timeinfo); | 299 | early_initcall(kvm_setup_vsyscall_timeinfo); |
@@ -269,8 +313,10 @@ static int kvmclock_setup_percpu(unsigned int cpu) | |||
269 | /* Use the static page for the first CPUs, allocate otherwise */ | 313 | /* Use the static page for the first CPUs, allocate otherwise */ |
270 | if (cpu < HVC_BOOT_ARRAY_SIZE) | 314 | if (cpu < HVC_BOOT_ARRAY_SIZE) |
271 | p = &hv_clock_boot[cpu]; | 315 | p = &hv_clock_boot[cpu]; |
316 | else if (hvclock_mem) | ||
317 | p = hvclock_mem + cpu - HVC_BOOT_ARRAY_SIZE; | ||
272 | else | 318 | else |
273 | p = kzalloc(sizeof(*p), GFP_KERNEL); | 319 | return -ENOMEM; |
274 | 320 | ||
275 | per_cpu(hv_clock_per_cpu, cpu) = p; | 321 | per_cpu(hv_clock_per_cpu, cpu) = p; |
276 | return p ? 0 : -ENOMEM; | 322 | return p ? 0 : -ENOMEM; |