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);