Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/arch/x86/x86 Fixed a problem that caused a page fault wh...



details:   https://anonhg.NetBSD.org/src/rev/dc9f3ef915e5
branches:  trunk
changeset: 1010183:dc9f3ef915e5
user:      nonaka <nonaka%NetBSD.org@localhost>
date:      Sun May 17 11:54:39 2020 +0000

description:
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.

diffstat:

 sys/arch/x86/x86/hyperv.c |  40 +++++++++-------------------------------
 1 files changed, 9 insertions(+), 31 deletions(-)

diffs (75 lines):

diff -r 808e075b4861 -r dc9f3ef915e5 sys/arch/x86/x86/hyperv.c
--- a/sys/arch/x86/x86/hyperv.c Sun May 17 11:32:51 2020 +0000
+++ b/sys/arch/x86/x86/hyperv.c Sun May 17 11:54:39 2020 +0000
@@ -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 @@
 
 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 @@
 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 @@
 {
        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);



Home | Main Index | Thread Index | Old Index