From owner-svn-src-stable-11@freebsd.org Thu Apr 25 00:58:13 2019 Return-Path: Delivered-To: svn-src-stable-11@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 260B915869B1; Thu, 25 Apr 2019 00:58:13 +0000 (UTC) (envelope-from gonzo@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) server-signature RSA-PSS (4096 bits) client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id BE1DF88CCF; Thu, 25 Apr 2019 00:58:12 +0000 (UTC) (envelope-from gonzo@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 97C231C36C; Thu, 25 Apr 2019 00:58:12 +0000 (UTC) (envelope-from gonzo@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id x3P0wCDO016572; Thu, 25 Apr 2019 00:58:12 GMT (envelope-from gonzo@FreeBSD.org) Received: (from gonzo@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id x3P0wCtx016571; Thu, 25 Apr 2019 00:58:12 GMT (envelope-from gonzo@FreeBSD.org) Message-Id: <201904250058.x3P0wCtx016571@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: gonzo set sender to gonzo@FreeBSD.org using -f From: Oleksandr Tymoshenko Date: Thu, 25 Apr 2019 00:58:12 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org Subject: svn commit: r346656 - stable/11/sys/compat/ndis X-SVN-Group: stable-11 X-SVN-Commit-Author: gonzo X-SVN-Commit-Paths: stable/11/sys/compat/ndis X-SVN-Commit-Revision: 346656 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Rspamd-Queue-Id: BE1DF88CCF X-Spamd-Bar: -- Authentication-Results: mx1.freebsd.org X-Spamd-Result: default: False [-2.96 / 15.00]; local_wl_from(0.00)[FreeBSD.org]; NEURAL_HAM_MEDIUM(-1.00)[-0.999,0]; NEURAL_HAM_LONG(-1.00)[-1.000,0]; NEURAL_HAM_SHORT(-0.96)[-0.963,0]; ASN(0.00)[asn:11403, ipnet:2610:1c1:1::/48, country:US] X-BeenThere: svn-src-stable-11@freebsd.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: SVN commit messages for only the 11-stable src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 25 Apr 2019 00:58:13 -0000 Author: gonzo Date: Thu Apr 25 00:58:11 2019 New Revision: 346656 URL: https://svnweb.freebsd.org/changeset/base/346656 Log: MFC r343298: [ndis] Fix unregistered use of FPU by NDIS in kernel on amd64 amd64 miniport drivers are allowed to use FPU which triggers "Unregistered use of FPU in kernel" panic. Wrap all variants of MSCALL with fpu_kern_enter/fpu_kern_leave. To reduce amount of allocations/deallocations done via fpu_kern_alloc_ctx/fpu_kern_free_ctx maintain cache of fpu_kern_ctx elements. Based on the patch by Paul B Mahol PR: 165622 Submitted by: Vlad Movchan Modified: stable/11/sys/compat/ndis/kern_windrv.c stable/11/sys/compat/ndis/pe_var.h Directory Properties: stable/11/ (props changed) Modified: stable/11/sys/compat/ndis/kern_windrv.c ============================================================================== --- stable/11/sys/compat/ndis/kern_windrv.c Thu Apr 25 00:56:11 2019 (r346655) +++ stable/11/sys/compat/ndis/kern_windrv.c Thu Apr 25 00:58:11 2019 (r346656) @@ -56,6 +56,10 @@ __FBSDID("$FreeBSD$"); #include #endif +#ifdef __amd64__ +#include +#endif + #include #include @@ -66,6 +70,19 @@ __FBSDID("$FreeBSD$"); #include #include +#ifdef __amd64__ +struct fpu_cc_ent { + struct fpu_kern_ctx *ctx; + LIST_ENTRY(fpu_cc_ent) entries; +}; +static LIST_HEAD(fpu_ctx_free, fpu_cc_ent) fpu_free_head = + LIST_HEAD_INITIALIZER(fpu_free_head); +static LIST_HEAD(fpu_ctx_busy, fpu_cc_ent) fpu_busy_head = + LIST_HEAD_INITIALIZER(fpu_busy_head); +static struct mtx fpu_free_mtx; +static struct mtx fpu_busy_mtx; +#endif + static struct mtx drvdb_mtx; static STAILQ_HEAD(drvdb, drvdb_ent) drvdb_head; @@ -96,6 +113,13 @@ windrv_libinit(void) mtx_init(&drvdb_mtx, "Windows driver DB lock", "Windows internal lock", MTX_DEF); +#ifdef __amd64__ + LIST_INIT(&fpu_free_head); + LIST_INIT(&fpu_busy_head); + mtx_init(&fpu_free_mtx, "free fpu context list lock", NULL, MTX_DEF); + mtx_init(&fpu_busy_mtx, "busy fpu context list lock", NULL, MTX_DEF); +#endif + /* * PCI and pccard devices don't need to use IRPs to * interact with their bus drivers (usually), so our @@ -130,6 +154,9 @@ int windrv_libfini(void) { struct drvdb_ent *d; +#ifdef __amd64__ + struct fpu_cc_ent *ent; +#endif mtx_lock(&drvdb_mtx); while(STAILQ_FIRST(&drvdb_head) != NULL) { @@ -148,6 +175,18 @@ windrv_libfini(void) smp_rendezvous(NULL, x86_oldldt, NULL, NULL); ExFreePool(my_tids); #endif +#ifdef __amd64__ + while ((ent = LIST_FIRST(&fpu_free_head)) != NULL) { + LIST_REMOVE(ent, entries); + fpu_kern_free_ctx(ent->ctx); + free(ent, M_DEVBUF); + } + mtx_destroy(&fpu_free_mtx); + + ent = LIST_FIRST(&fpu_busy_head); + KASSERT(ent == NULL, ("busy fpu context list is not empty")); + mtx_destroy(&fpu_busy_mtx); +#endif return (0); } @@ -612,6 +651,148 @@ windrv_wrap(func, wrap, argcnt, ftype) *wrap = p; return (0); +} + +static struct fpu_cc_ent * +request_fpu_cc_ent(void) +{ + struct fpu_cc_ent *ent; + + mtx_lock(&fpu_free_mtx); + if ((ent = LIST_FIRST(&fpu_free_head)) != NULL) { + LIST_REMOVE(ent, entries); + mtx_unlock(&fpu_free_mtx); + mtx_lock(&fpu_busy_mtx); + LIST_INSERT_HEAD(&fpu_busy_head, ent, entries); + mtx_unlock(&fpu_busy_mtx); + return (ent); + } + mtx_unlock(&fpu_free_mtx); + + if ((ent = malloc(sizeof(struct fpu_cc_ent), M_DEVBUF, M_NOWAIT | + M_ZERO)) != NULL) { + ent->ctx = fpu_kern_alloc_ctx(FPU_KERN_NORMAL | + FPU_KERN_NOWAIT); + if (ent->ctx != NULL) { + mtx_lock(&fpu_busy_mtx); + LIST_INSERT_HEAD(&fpu_busy_head, ent, entries); + mtx_unlock(&fpu_busy_mtx); + } else { + free(ent, M_DEVBUF); + ent = NULL; + } + } + + return (ent); +} + +static void +release_fpu_cc_ent(struct fpu_cc_ent *ent) +{ + mtx_lock(&fpu_busy_mtx); + LIST_REMOVE(ent, entries); + mtx_unlock(&fpu_busy_mtx); + mtx_lock(&fpu_free_mtx); + LIST_INSERT_HEAD(&fpu_free_head, ent, entries); + mtx_unlock(&fpu_free_mtx); +} + +uint64_t +_x86_64_call1(void *fn, uint64_t a) +{ + struct fpu_cc_ent *ent; + uint64_t ret; + + if ((ent = request_fpu_cc_ent()) == NULL) + return (ENOMEM); + fpu_kern_enter(curthread, ent->ctx, FPU_KERN_NORMAL); + ret = x86_64_call1(fn, a); + fpu_kern_leave(curthread, ent->ctx); + release_fpu_cc_ent(ent); + + return (ret); +} + +uint64_t +_x86_64_call2(void *fn, uint64_t a, uint64_t b) +{ + struct fpu_cc_ent *ent; + uint64_t ret; + + if ((ent = request_fpu_cc_ent()) == NULL) + return (ENOMEM); + fpu_kern_enter(curthread, ent->ctx, FPU_KERN_NORMAL); + ret = x86_64_call2(fn, a, b); + fpu_kern_leave(curthread, ent->ctx); + release_fpu_cc_ent(ent); + + return (ret); +} + +uint64_t +_x86_64_call3(void *fn, uint64_t a, uint64_t b, uint64_t c) +{ + struct fpu_cc_ent *ent; + uint64_t ret; + + if ((ent = request_fpu_cc_ent()) == NULL) + return (ENOMEM); + fpu_kern_enter(curthread, ent->ctx, FPU_KERN_NORMAL); + ret = x86_64_call3(fn, a, b, c); + fpu_kern_leave(curthread, ent->ctx); + release_fpu_cc_ent(ent); + + return (ret); +} + +uint64_t +_x86_64_call4(void *fn, uint64_t a, uint64_t b, uint64_t c, uint64_t d) +{ + struct fpu_cc_ent *ent; + uint64_t ret; + + if ((ent = request_fpu_cc_ent()) == NULL) + return (ENOMEM); + fpu_kern_enter(curthread, ent->ctx, FPU_KERN_NORMAL); + ret = x86_64_call4(fn, a, b, c, d); + fpu_kern_leave(curthread, ent->ctx); + release_fpu_cc_ent(ent); + + return (ret); +} + +uint64_t +_x86_64_call5(void *fn, uint64_t a, uint64_t b, uint64_t c, uint64_t d, + uint64_t e) +{ + struct fpu_cc_ent *ent; + uint64_t ret; + + if ((ent = request_fpu_cc_ent()) == NULL) + return (ENOMEM); + fpu_kern_enter(curthread, ent->ctx, FPU_KERN_NORMAL); + ret = x86_64_call5(fn, a, b, c, d, e); + fpu_kern_leave(curthread, ent->ctx); + release_fpu_cc_ent(ent); + + return (ret); +} + +uint64_t +_x86_64_call6(void *fn, uint64_t a, uint64_t b, uint64_t c, uint64_t d, + uint64_t e, uint64_t f) +{ + struct fpu_cc_ent *ent; + uint64_t ret; + + if ((ent = request_fpu_cc_ent()) == NULL) + return (ENOMEM); + fpu_kern_enter(curthread, ent->ctx, FPU_KERN_NORMAL); + ret = x86_64_call6(fn, a, b, c, d, e, f); + fpu_kern_leave(curthread, ent->ctx); + release_fpu_cc_ent(ent); + + return (ret); } #endif /* __amd64__ */ Modified: stable/11/sys/compat/ndis/pe_var.h ============================================================================== --- stable/11/sys/compat/ndis/pe_var.h Thu Apr 25 00:56:11 2019 (r346655) +++ stable/11/sys/compat/ndis/pe_var.h Thu Apr 25 00:58:11 2019 (r346656) @@ -458,22 +458,30 @@ extern uint64_t x86_64_call5(void *, uint64_t, uint64_ extern uint64_t x86_64_call6(void *, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t); +uint64_t _x86_64_call1(void *, uint64_t); +uint64_t _x86_64_call2(void *, uint64_t, uint64_t); +uint64_t _x86_64_call3(void *, uint64_t, uint64_t, uint64_t); +uint64_t _x86_64_call4(void *, uint64_t, uint64_t, uint64_t, uint64_t); +uint64_t _x86_64_call5(void *, uint64_t, uint64_t, uint64_t, uint64_t, + uint64_t); +uint64_t _x86_64_call6(void *, uint64_t, uint64_t, uint64_t, uint64_t, + uint64_t, uint64_t); #define MSCALL1(fn, a) \ - x86_64_call1((fn), (uint64_t)(a)) + _x86_64_call1((fn), (uint64_t)(a)) #define MSCALL2(fn, a, b) \ - x86_64_call2((fn), (uint64_t)(a), (uint64_t)(b)) + _x86_64_call2((fn), (uint64_t)(a), (uint64_t)(b)) #define MSCALL3(fn, a, b, c) \ - x86_64_call3((fn), (uint64_t)(a), (uint64_t)(b), \ + _x86_64_call3((fn), (uint64_t)(a), (uint64_t)(b), \ (uint64_t)(c)) #define MSCALL4(fn, a, b, c, d) \ - x86_64_call4((fn), (uint64_t)(a), (uint64_t)(b), \ + _x86_64_call4((fn), (uint64_t)(a), (uint64_t)(b), \ (uint64_t)(c), (uint64_t)(d)) #define MSCALL5(fn, a, b, c, d, e) \ - x86_64_call5((fn), (uint64_t)(a), (uint64_t)(b), \ + _x86_64_call5((fn), (uint64_t)(a), (uint64_t)(b), \ (uint64_t)(c), (uint64_t)(d), (uint64_t)(e)) #define MSCALL6(fn, a, b, c, d, e, f) \ - x86_64_call6((fn), (uint64_t)(a), (uint64_t)(b), \ + _x86_64_call6((fn), (uint64_t)(a), (uint64_t)(b), \ (uint64_t)(c), (uint64_t)(d), (uint64_t)(e), (uint64_t)(f)) #endif /* __amd64__ */