Module Name: src Committed By: nonaka Date: Sun May 17 11:54:40 UTC 2020
Modified Files: src/sys/arch/x86/x86: hyperv.c Log Message: Fixed a problem that caused a page fault when attaching vmbus(4). Dynamically allocate a page of memory with uvm_km_alloc(kernel_map, ...) for Hyper-V hypercall. However, this method can no longer be used to make an executable page. So we prevent it by using statically allocated memory for text segment. To generate a diff of this commit: cvs rdiff -u -r1.8 -r1.9 src/sys/arch/x86/x86/hyperv.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/arch/x86/x86/hyperv.c diff -u src/sys/arch/x86/x86/hyperv.c:1.8 src/sys/arch/x86/x86/hyperv.c:1.9 --- src/sys/arch/x86/x86/hyperv.c:1.8 Sat Apr 25 15:26:18 2020 +++ src/sys/arch/x86/x86/hyperv.c Sun May 17 11:54:39 2020 @@ -1,4 +1,4 @@ -/* $NetBSD: hyperv.c,v 1.8 2020/04/25 15:26:18 bouyer Exp $ */ +/* $NetBSD: hyperv.c,v 1.9 2020/05/17 11:54:39 nonaka Exp $ */ /*- * Copyright (c) 2009-2012,2016-2017 Microsoft Corp. @@ -33,7 +33,7 @@ */ #include <sys/cdefs.h> #ifdef __KERNEL_RCSID -__KERNEL_RCSID(0, "$NetBSD: hyperv.c,v 1.8 2020/04/25 15:26:18 bouyer Exp $"); +__KERNEL_RCSID(0, "$NetBSD: hyperv.c,v 1.9 2020/05/17 11:54:39 nonaka Exp $"); #endif #ifdef __FBSDID __FBSDID("$FreeBSD: head/sys/dev/hyperv/vmbus/hyperv.c 331757 2018-03-30 02:25:12Z emaste $"); @@ -97,6 +97,9 @@ struct hyperv_hypercall_ctx { static struct hyperv_hypercall_ctx hyperv_hypercall_ctx; +static char hyperv_hypercall_page[PAGE_SIZE] + __section(".text") __aligned(PAGE_SIZE) = { 0xcc }; + static u_int hyperv_get_timecount(struct timecounter *); static u_int hyperv_ver_major; @@ -703,11 +706,7 @@ static void hyperv_hypercall_memfree(void) { - if (hyperv_hypercall_ctx.hc_addr != NULL) { - uvm_km_free(kernel_map, (vaddr_t)hyperv_hypercall_ctx.hc_addr, - PAGE_SIZE, UVM_KMF_WIRED); - hyperv_hypercall_ctx.hc_addr = NULL; - } + hyperv_hypercall_ctx.hc_addr = NULL; } static bool @@ -715,30 +714,9 @@ hyperv_init_hypercall(void) { uint64_t hc, hc_orig; - hyperv_hypercall_ctx.hc_addr = (void *)uvm_km_alloc(kernel_map, - PAGE_SIZE, PAGE_SIZE, - UVM_KMF_WIRED | UVM_KMF_EXEC | (cold ? UVM_KMF_NOWAIT : 0)); - if (hyperv_hypercall_ctx.hc_addr == NULL) { - aprint_error("Hyper-V: Hypercall page allocation failed\n"); - return false; - } - - memset(hyperv_hypercall_ctx.hc_addr, 0xcc, PAGE_SIZE); - wbinvd(); - x86_flush(); - - /* The hypercall page must be both readable and executable */ - uvm_km_protect(kernel_map, (vaddr_t)hyperv_hypercall_ctx.hc_addr, - PAGE_SIZE, VM_PROT_READ | VM_PROT_EXECUTE); - - if (!pmap_extract(pmap_kernel(), (vaddr_t)hyperv_hypercall_ctx.hc_addr, - &hyperv_hypercall_ctx.hc_paddr)) { - aprint_error("Hyper-V: Hypercall page setup failed\n"); - hyperv_hypercall_memfree(); - /* Can't perform any Hyper-V specific actions */ - vm_guest = VM_GUEST_VM; - return false; - } + hyperv_hypercall_ctx.hc_addr = hyperv_hypercall_page; + hyperv_hypercall_ctx.hc_paddr = vtophys((vaddr_t)hyperv_hypercall_page); + KASSERT(hyperv_hypercall_ctx.hc_paddr != 0); /* Get the 'reserved' bits, which requires preservation. */ hc_orig = rdmsr(MSR_HV_HYPERCALL);