diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-06 03:01:46 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-06 03:01:46 +0000 |
commit | f8fe689a81f906d1b91bb3220acde2a4ecb14c5b (patch) | |
tree | 26484e9d7e2c67806c2d1760196ff01aaa858e8c /src/VBox/Runtime/r0drv/netbsd | |
parent | Initial commit. (diff) | |
download | virtualbox-upstream.tar.xz virtualbox-upstream.zip |
Adding upstream version 6.0.4-dfsg.upstream/6.0.4-dfsgupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/VBox/Runtime/r0drv/netbsd')
19 files changed, 2852 insertions, 0 deletions
diff --git a/src/VBox/Runtime/r0drv/netbsd/Makefile.kup b/src/VBox/Runtime/r0drv/netbsd/Makefile.kup new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/src/VBox/Runtime/r0drv/netbsd/Makefile.kup diff --git a/src/VBox/Runtime/r0drv/netbsd/RTLogWriteStdOut-r0drv-netbsd.c b/src/VBox/Runtime/r0drv/netbsd/RTLogWriteStdOut-r0drv-netbsd.c new file mode 100644 index 00000000..df61da3a --- /dev/null +++ b/src/VBox/Runtime/r0drv/netbsd/RTLogWriteStdOut-r0drv-netbsd.c @@ -0,0 +1,39 @@ +/* $Id: RTLogWriteStdOut-r0drv-netbsd.c $ */ +/** @file + * IPRT - Log To StdOut, Ring-0 Driver, NetBSD. + */ + +/* + * Copyright (C) 2006-2019 Oracle Corporation + * + * This file is part of VirtualBox Open Source Edition (OSE), as + * available from http://www.virtualbox.org. This file is free software; + * you can redistribute it and/or modify it under the terms of the GNU + * General Public License (GPL) as published by the Free Software + * Foundation, in version 2 as it comes in the "COPYING" file of the + * VirtualBox OSE distribution. VirtualBox OSE is distributed in the + * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL) only, as it comes in the "COPYING.CDDL" file of the + * VirtualBox OSE distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "the-netbsd-kernel.h" +#include "internal/iprt.h" +#include <iprt/log.h> + + +RTDECL(void) RTLogWriteStdOut(const char *pch, size_t cb) +{ + printf("%.*s", (int)cb, pch); +} diff --git a/src/VBox/Runtime/r0drv/netbsd/alloc-r0drv-netbsd.c b/src/VBox/Runtime/r0drv/netbsd/alloc-r0drv-netbsd.c new file mode 100644 index 00000000..8c0f7621 --- /dev/null +++ b/src/VBox/Runtime/r0drv/netbsd/alloc-r0drv-netbsd.c @@ -0,0 +1,165 @@ +/* $Id: alloc-r0drv-netbsd.c $ */ +/** @file + * IPRT - Memory Allocation, Ring-0 Driver, NetBSD. + */ +/* + * Copyright (C) 2014-2019 Oracle Corporation + * + * This file is part of VirtualBox Open Source Edition (OSE), as + * available from http://www.virtualbox.org. This file is free software; + * you can redistribute it and/or modify it under the terms of the GNU + * General Public License (GPL) as published by the Free Software + * Foundation, in version 2 as it comes in the "COPYING" file of the + * VirtualBox OSE distribution. VirtualBox OSE is distributed in the + * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL) only, as it comes in the "COPYING.CDDL" file of the + * VirtualBox OSE distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * --------------------------------------------------------------------------- + * + * This code is based on: + * + * Copyright (c) 2014 Arto Huusko + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "the-netbsd-kernel.h" +#include "internal/iprt.h" +#include <iprt/mem.h> + +#include <iprt/assert.h> +#include <iprt/errcore.h> +#include <iprt/param.h> + +#include "r0drv/alloc-r0drv.h" + + +DECLHIDDEN(int) rtR0MemAllocEx(size_t cb, uint32_t fFlags, PRTMEMHDR *ppHdr) +{ + size_t cbAllocated = cb; + PRTMEMHDR pHdr = NULL; + + if (fFlags & RTMEMHDR_FLAG_ZEROED) + pHdr = kmem_zalloc(cb + sizeof(RTMEMHDR), KM_NOSLEEP); + else + pHdr = kmem_alloc(cb + sizeof(RTMEMHDR), KM_NOSLEEP); + + if (RT_UNLIKELY(!pHdr)) + return VERR_NO_MEMORY; + + pHdr->u32Magic = RTMEMHDR_MAGIC; + pHdr->fFlags = fFlags; + pHdr->cb = cbAllocated; + pHdr->cbReq = cb; + + *ppHdr = pHdr; + return VINF_SUCCESS; +} + + +DECLHIDDEN(void) rtR0MemFree(PRTMEMHDR pHdr) +{ + pHdr->u32Magic += 1; + + kmem_free(pHdr, pHdr->cb + sizeof(RTMEMHDR)); +} + +RTR0DECL(void) RTMemContFree(void *pv, size_t cb) +{ + if (pv) + { + cb = round_page(cb); + + paddr_t pa; + pmap_extract(pmap_kernel(), (vaddr_t)pv, &pa); + + /* + * Reconstruct pglist to free the physical pages + */ + struct pglist rlist; + TAILQ_INIT(&rlist); + + for (paddr_t pa2 = pa ; pa2 < pa + cb ; pa2 += PAGE_SIZE) { + struct vm_page *page = PHYS_TO_VM_PAGE(pa2); + TAILQ_INSERT_TAIL(&rlist, page, pageq.queue); + } + + /* Unmap */ + pmap_kremove((vaddr_t)pv, cb); + + /* Free the virtual space */ + uvm_km_free(kernel_map, (vaddr_t)pv, cb, UVM_KMF_VAONLY); + + /* Free the physical pages */ + uvm_pglistfree(&rlist); + } +} + +RTR0DECL(void *) RTMemContAlloc(PRTCCPHYS pPhys, size_t cb) +{ + /* + * Validate input. + */ + AssertPtr(pPhys); + Assert(cb > 0); + + cb = round_page(cb); + + vaddr_t virt = uvm_km_alloc(kernel_map, cb, 0, + UVM_KMF_VAONLY | UVM_KMF_WAITVA | UVM_KMF_CANFAIL); + if (virt == 0) + return NULL; + + struct pglist rlist; + + if (uvm_pglistalloc(cb, 0, (paddr_t)0xFFFFFFFF, + PAGE_SIZE, 0, &rlist, 1, 1) != 0) + { + uvm_km_free(kernel_map, virt, cb, UVM_KMF_VAONLY); + return NULL; + } + + struct vm_page *page; + vaddr_t virt2 = virt; + TAILQ_FOREACH(page, &rlist, pageq.queue) + { + pmap_kenter_pa(virt2, VM_PAGE_TO_PHYS(page), + VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE, 0); + virt2 += PAGE_SIZE; + } + + page = TAILQ_FIRST(&rlist); + *pPhys = VM_PAGE_TO_PHYS(page); + + return (void *)virt; +} diff --git a/src/VBox/Runtime/r0drv/netbsd/assert-r0drv-netbsd.c b/src/VBox/Runtime/r0drv/netbsd/assert-r0drv-netbsd.c new file mode 100644 index 00000000..43872a23 --- /dev/null +++ b/src/VBox/Runtime/r0drv/netbsd/assert-r0drv-netbsd.c @@ -0,0 +1,63 @@ +/* $Id: assert-r0drv-netbsd.c $ */ +/** @file + * IPRT - Assertion Workers, Ring-0 Drivers, NetBSD. + */ + +/* + * Copyright (c) 2007 knut st. osmundsen <bird-src-spam@anduin.net> + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "the-netbsd-kernel.h" + +#include <iprt/assert.h> +#include <iprt/log.h> +#include <iprt/stdarg.h> + +#include "internal/assert.h" + + +DECLHIDDEN(void) rtR0AssertNativeMsg1(const char *pszExpr, unsigned uLine, const char *pszFile, const char *pszFunction) +{ + printf("\r\n!!Assertion Failed!!\r\n" + "Expression: %s\r\n" + "Location : %s(%d) %s\r\n", + pszExpr, pszFile, uLine, pszFunction); +} + + +DECLHIDDEN(void) rtR0AssertNativeMsg2V(bool fInitial, const char *pszFormat, va_list va) +{ + /** @todo implement rtR0AssertNativeMsg2V. */ +} + + +RTR0DECL(void) RTR0AssertPanicSystem(void) +{ + panic("%s%s", g_szRTAssertMsg1, g_szRTAssertMsg2); + +} diff --git a/src/VBox/Runtime/r0drv/netbsd/initterm-r0drv-netbsd.c b/src/VBox/Runtime/r0drv/netbsd/initterm-r0drv-netbsd.c new file mode 100644 index 00000000..99a511c2 --- /dev/null +++ b/src/VBox/Runtime/r0drv/netbsd/initterm-r0drv-netbsd.c @@ -0,0 +1,52 @@ +/* $Id: initterm-r0drv-netbsd.c $ */ +/** @file + * IPRT - Initialization & Termination, Ring-0 Driver, NetBSD. + */ + +/* + * Copyright (c) 2007 knut st. osmundsen <bird-src-spam@anduin.net> + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "the-netbsd-kernel.h" + +#include <iprt/errcore.h> + +#include "internal/initterm.h" + + +DECLHIDDEN(int) rtR0InitNative(void) +{ + /* nothing to do */ + return VINF_SUCCESS; +} + + +DECLHIDDEN(void) rtR0TermNative(void) +{ + /* nothing to undo */ +} diff --git a/src/VBox/Runtime/r0drv/netbsd/memobj-r0drv-netbsd.c b/src/VBox/Runtime/r0drv/netbsd/memobj-r0drv-netbsd.c new file mode 100644 index 00000000..4d4b5bba --- /dev/null +++ b/src/VBox/Runtime/r0drv/netbsd/memobj-r0drv-netbsd.c @@ -0,0 +1,558 @@ +/* $Id: memobj-r0drv-netbsd.c $ */ +/** @file + * IPRT - Ring-0 Memory Objects, NetBSD. + */ + +/* + * Copyright (c) 2007 knut st. osmundsen <bird-src-spam@anduin.net> + * Copyright (c) 2011 Andriy Gapon <avg@FreeBSD.org> + * Copyright (c) 2014 Arto Huusko + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "the-netbsd-kernel.h" + +#include <iprt/memobj.h> +#include <iprt/mem.h> +#include <iprt/err.h> +#include <iprt/assert.h> +#include <iprt/log.h> +#include <iprt/param.h> +#include <iprt/process.h> +#include "internal/memobj.h" + + +/********************************************************************************************************************************* +* Structures and Typedefs * +*********************************************************************************************************************************/ +/** + * The NetBSD version of the memory object structure. + */ +typedef struct RTR0MEMOBJNETBSD +{ + /** The core structure. */ + RTR0MEMOBJINTERNAL Core; + size_t size; + struct pglist pglist; +} RTR0MEMOBJNETBSD, *PRTR0MEMOBJNETBSD; + + +typedef struct vm_map* vm_map_t; + +/** + * Gets the virtual memory map the specified object is mapped into. + * + * @returns VM map handle on success, NULL if no map. + * @param pMem The memory object. + */ +static vm_map_t rtR0MemObjNetBSDGetMap(PRTR0MEMOBJINTERNAL pMem) +{ + switch (pMem->enmType) + { + case RTR0MEMOBJTYPE_PAGE: + case RTR0MEMOBJTYPE_LOW: + case RTR0MEMOBJTYPE_CONT: + return kernel_map; + + case RTR0MEMOBJTYPE_PHYS: + case RTR0MEMOBJTYPE_PHYS_NC: + return NULL; /* pretend these have no mapping atm. */ + + case RTR0MEMOBJTYPE_LOCK: + return pMem->u.Lock.R0Process == NIL_RTR0PROCESS + ? kernel_map + : &((struct proc *)pMem->u.Lock.R0Process)->p_vmspace->vm_map; + + case RTR0MEMOBJTYPE_RES_VIRT: + return pMem->u.ResVirt.R0Process == NIL_RTR0PROCESS + ? kernel_map + : &((struct proc *)pMem->u.ResVirt.R0Process)->p_vmspace->vm_map; + + case RTR0MEMOBJTYPE_MAPPING: + return pMem->u.Mapping.R0Process == NIL_RTR0PROCESS + ? kernel_map + : &((struct proc *)pMem->u.Mapping.R0Process)->p_vmspace->vm_map; + + default: + return NULL; + } +} + + +DECLHIDDEN(int) rtR0MemObjNativeFree(RTR0MEMOBJ pMem) +{ + PRTR0MEMOBJNETBSD pMemNetBSD = (PRTR0MEMOBJNETBSD)pMem; + int rc; + + switch (pMemNetBSD->Core.enmType) + { + case RTR0MEMOBJTYPE_PAGE: + { + kmem_free(pMemNetBSD->Core.pv, pMemNetBSD->Core.cb); + break; + } + case RTR0MEMOBJTYPE_LOW: + case RTR0MEMOBJTYPE_CONT: + { + /* Unmap */ + pmap_kremove((vaddr_t)pMemNetBSD->Core.pv, pMemNetBSD->Core.cb); + /* Free the virtual space */ + uvm_km_free(kernel_map, (vaddr_t)pMemNetBSD->Core.pv, pMemNetBSD->Core.cb, UVM_KMF_VAONLY); + /* Free the physical pages */ + uvm_pglistfree(&pMemNetBSD->pglist); + break; + } + case RTR0MEMOBJTYPE_PHYS: + case RTR0MEMOBJTYPE_PHYS_NC: + { + /* Free the physical pages */ + uvm_pglistfree(&pMemNetBSD->pglist); + break; + } + case RTR0MEMOBJTYPE_LOCK: + if (pMemNetBSD->Core.u.Lock.R0Process != NIL_RTR0PROCESS) + { + uvm_map_pageable( + &((struct proc *)pMemNetBSD->Core.u.Lock.R0Process)->p_vmspace->vm_map, + (vaddr_t)pMemNetBSD->Core.pv, + ((vaddr_t)pMemNetBSD->Core.pv) + pMemNetBSD->Core.cb, + 1, 0); + } + break; + case RTR0MEMOBJTYPE_RES_VIRT: + if (pMemNetBSD->Core.u.Lock.R0Process == NIL_RTR0PROCESS) + { + uvm_km_free(kernel_map, (vaddr_t)pMemNetBSD->Core.pv, pMemNetBSD->Core.cb, UVM_KMF_VAONLY); + } + break; + case RTR0MEMOBJTYPE_MAPPING: + if (pMemNetBSD->Core.u.Lock.R0Process == NIL_RTR0PROCESS) + { + pmap_kremove((vaddr_t)pMemNetBSD->Core.pv, pMemNetBSD->Core.cb); + uvm_km_free(kernel_map, (vaddr_t)pMemNetBSD->Core.pv, pMemNetBSD->Core.cb, UVM_KMF_VAONLY); + } + break; + + default: + AssertMsgFailed(("enmType=%d\n", pMemNetBSD->Core.enmType)); + return VERR_INTERNAL_ERROR; + } + + return VINF_SUCCESS; +} + +static int rtR0MemObjNetBSDAllocHelper(PRTR0MEMOBJNETBSD pMemNetBSD, size_t cb, bool fExecutable, + paddr_t VmPhysAddrHigh, bool fContiguous) +{ + /* Virtual space first */ + vaddr_t virt = uvm_km_alloc(kernel_map, cb, 0, + UVM_KMF_VAONLY | UVM_KMF_WAITVA | UVM_KMF_CANFAIL); + if (virt == 0) + return VERR_NO_MEMORY; + + struct pglist *rlist = &pMemNetBSD->pglist; + + int nsegs = fContiguous ? 1 : INT_MAX; + + /* Physical pages */ + if (uvm_pglistalloc(cb, 0, VmPhysAddrHigh, + PAGE_SIZE, 0, rlist, nsegs, 1) != 0) + { + uvm_km_free(kernel_map, virt, cb, UVM_KMF_VAONLY); + return VERR_NO_MEMORY; + } + + /* Map */ + struct vm_page *page; + vm_prot_t prot = VM_PROT_READ | VM_PROT_WRITE; + if (fExecutable) + prot |= VM_PROT_EXECUTE; + vaddr_t virt2 = virt; + TAILQ_FOREACH(page, rlist, pageq.queue) + { + pmap_kenter_pa(virt2, VM_PAGE_TO_PHYS(page), prot, 0); + virt2 += PAGE_SIZE; + } + + pMemNetBSD->Core.pv = (void *)virt; + if (fContiguous) + { + page = TAILQ_FIRST(rlist); + pMemNetBSD->Core.u.Cont.Phys = VM_PAGE_TO_PHYS(page); + } + return VINF_SUCCESS; +} + +DECLHIDDEN(int) rtR0MemObjNativeAllocPage(PPRTR0MEMOBJINTERNAL ppMem, size_t cb, bool fExecutable) +{ + PRTR0MEMOBJNETBSD pMemNetBSD = (PRTR0MEMOBJNETBSD)rtR0MemObjNew(sizeof(*pMemNetBSD), + RTR0MEMOBJTYPE_PAGE, NULL, cb); + if (!pMemNetBSD) + return VERR_NO_MEMORY; + + void *pvMem = kmem_alloc(cb, KM_SLEEP); + if (RT_UNLIKELY(!pvMem)) + { + rtR0MemObjDelete(&pMemNetBSD->Core); + return VERR_NO_PAGE_MEMORY; + } + if (fExecutable) + { + pmap_protect(pmap_kernel(), (vaddr_t)pvMem, ((vaddr_t)pvMem) + cb, + VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE); + } + + pMemNetBSD->Core.pv = pvMem; + *ppMem = &pMemNetBSD->Core; + return VINF_SUCCESS; +} + + +DECLHIDDEN(int) rtR0MemObjNativeAllocLow(PPRTR0MEMOBJINTERNAL ppMem, size_t cb, bool fExecutable) +{ + PRTR0MEMOBJNETBSD pMemNetBSD = (PRTR0MEMOBJNETBSD)rtR0MemObjNew(sizeof(*pMemNetBSD), + RTR0MEMOBJTYPE_LOW, NULL, cb); + if (!pMemNetBSD) + return VERR_NO_MEMORY; + + int rc = rtR0MemObjNetBSDAllocHelper(pMemNetBSD, cb, fExecutable, _4G - 1, false); + if (rc) + { + rtR0MemObjDelete(&pMemNetBSD->Core); + return rc; + } + + *ppMem = &pMemNetBSD->Core; + return VINF_SUCCESS; +} + + +DECLHIDDEN(int) rtR0MemObjNativeAllocCont(PPRTR0MEMOBJINTERNAL ppMem, size_t cb, bool fExecutable) +{ + PRTR0MEMOBJNETBSD pMemNetBSD = (PRTR0MEMOBJNETBSD)rtR0MemObjNew(sizeof(*pMemNetBSD), + RTR0MEMOBJTYPE_CONT, NULL, cb); + if (!pMemNetBSD) + return VERR_NO_MEMORY; + + int rc = rtR0MemObjNetBSDAllocHelper(pMemNetBSD, cb, fExecutable, _4G - 1, true); + if (rc) + { + rtR0MemObjDelete(&pMemNetBSD->Core); + return rc; + } + + *ppMem = &pMemNetBSD->Core; + return VINF_SUCCESS; +} + + +static int rtR0MemObjNetBSDAllocPhysPages(PPRTR0MEMOBJINTERNAL ppMem, RTR0MEMOBJTYPE enmType, + size_t cb, + RTHCPHYS PhysHighest, size_t uAlignment, + bool fContiguous) +{ + paddr_t VmPhysAddrHigh; + + /* create the object. */ + PRTR0MEMOBJNETBSD pMemNetBSD = (PRTR0MEMOBJNETBSD)rtR0MemObjNew(sizeof(*pMemNetBSD), + enmType, NULL, cb); + if (!pMemNetBSD) + return VERR_NO_MEMORY; + + if (PhysHighest != NIL_RTHCPHYS) + VmPhysAddrHigh = PhysHighest; + else + VmPhysAddrHigh = ~(paddr_t)0; + + int nsegs = fContiguous ? 1 : INT_MAX; + + int error = uvm_pglistalloc(cb, 0, VmPhysAddrHigh, uAlignment, 0, &pMemNetBSD->pglist, nsegs, 1); + if (error) + { + rtR0MemObjDelete(&pMemNetBSD->Core); + return VERR_NO_MEMORY; + } + + if (fContiguous) + { + Assert(enmType == RTR0MEMOBJTYPE_PHYS); + const struct vm_page * const pg = TAILQ_FIRST(&pMemNetBSD->pglist); + pMemNetBSD->Core.u.Phys.PhysBase = VM_PAGE_TO_PHYS(pg); + pMemNetBSD->Core.u.Phys.fAllocated = true; + } + *ppMem = &pMemNetBSD->Core; + + return VINF_SUCCESS; +} + + +DECLHIDDEN(int) rtR0MemObjNativeAllocPhys(PPRTR0MEMOBJINTERNAL ppMem, size_t cb, RTHCPHYS PhysHighest, size_t uAlignment) +{ + return rtR0MemObjNetBSDAllocPhysPages(ppMem, RTR0MEMOBJTYPE_PHYS, cb, PhysHighest, uAlignment, true); +} + + +DECLHIDDEN(int) rtR0MemObjNativeAllocPhysNC(PPRTR0MEMOBJINTERNAL ppMem, size_t cb, RTHCPHYS PhysHighest) +{ + return rtR0MemObjNetBSDAllocPhysPages(ppMem, RTR0MEMOBJTYPE_PHYS_NC, cb, PhysHighest, PAGE_SIZE, false); +} + + +DECLHIDDEN(int) rtR0MemObjNativeEnterPhys(PPRTR0MEMOBJINTERNAL ppMem, RTHCPHYS Phys, size_t cb, uint32_t uCachePolicy) +{ + AssertReturn(uCachePolicy == RTMEM_CACHE_POLICY_DONT_CARE, VERR_NOT_SUPPORTED); + + /* create the object. */ + PRTR0MEMOBJNETBSD pMemNetBSD = (PRTR0MEMOBJNETBSD)rtR0MemObjNew(sizeof(*pMemNetBSD), RTR0MEMOBJTYPE_PHYS, NULL, cb); + if (!pMemNetBSD) + return VERR_NO_MEMORY; + + /* there is no allocation here, it needs to be mapped somewhere first. */ + pMemNetBSD->Core.u.Phys.fAllocated = false; + pMemNetBSD->Core.u.Phys.PhysBase = Phys; + pMemNetBSD->Core.u.Phys.uCachePolicy = uCachePolicy; + TAILQ_INIT(&pMemNetBSD->pglist); + *ppMem = &pMemNetBSD->Core; + return VINF_SUCCESS; +} + + +DECLHIDDEN(int) rtR0MemObjNativeLockUser(PPRTR0MEMOBJINTERNAL ppMem, RTR3PTR R3Ptr, size_t cb, uint32_t fAccess, RTR0PROCESS R0Process) +{ + PRTR0MEMOBJNETBSD pMemNetBSD = (PRTR0MEMOBJNETBSD)rtR0MemObjNew(sizeof(*pMemNetBSD), RTR0MEMOBJTYPE_LOCK, (void *)R3Ptr, cb); + if (!pMemNetBSD) + return VERR_NO_MEMORY; + + int rc = uvm_map_pageable( + &((struct proc *)R0Process)->p_vmspace->vm_map, + R3Ptr, + R3Ptr + cb, + 0, 0); + if (rc) + { + rtR0MemObjDelete(&pMemNetBSD->Core); + return VERR_NO_MEMORY; + } + + pMemNetBSD->Core.u.Lock.R0Process = R0Process; + *ppMem = &pMemNetBSD->Core; + return VINF_SUCCESS; +} + + +DECLHIDDEN(int) rtR0MemObjNativeLockKernel(PPRTR0MEMOBJINTERNAL ppMem, void *pv, size_t cb, uint32_t fAccess) +{ + /* Kernel memory (always?) wired; all memory allocated by vbox code is? */ + PRTR0MEMOBJNETBSD pMemNetBSD = (PRTR0MEMOBJNETBSD)rtR0MemObjNew(sizeof(*pMemNetBSD), RTR0MEMOBJTYPE_LOCK, pv, cb); + if (!pMemNetBSD) + return VERR_NO_MEMORY; + + pMemNetBSD->Core.u.Lock.R0Process = NIL_RTR0PROCESS; + pMemNetBSD->Core.pv = pv; + *ppMem = &pMemNetBSD->Core; + return VINF_SUCCESS; +} + +DECLHIDDEN(int) rtR0MemObjNativeReserveKernel(PPRTR0MEMOBJINTERNAL ppMem, void *pvFixed, size_t cb, size_t uAlignment) +{ + if (pvFixed != (void *)-1) + { + /* can we support this? or can we assume the virtual space is already reserved? */ + printf("reserve specified kernel virtual address not supported\n"); + return VERR_NOT_SUPPORTED; + } + + PRTR0MEMOBJNETBSD pMemNetBSD = (PRTR0MEMOBJNETBSD)rtR0MemObjNew(sizeof(*pMemNetBSD), RTR0MEMOBJTYPE_RES_VIRT, NULL, cb); + if (!pMemNetBSD) + return VERR_NO_MEMORY; + + vaddr_t virt = uvm_km_alloc(kernel_map, cb, uAlignment, + UVM_KMF_VAONLY | UVM_KMF_WAITVA | UVM_KMF_CANFAIL); + if (virt == 0) + { + rtR0MemObjDelete(&pMemNetBSD->Core); + return VERR_NO_MEMORY; + } + + pMemNetBSD->Core.u.ResVirt.R0Process = NIL_RTR0PROCESS; + pMemNetBSD->Core.pv = (void *)virt; + *ppMem = &pMemNetBSD->Core; + return VINF_SUCCESS; +} + + +DECLHIDDEN(int) rtR0MemObjNativeReserveUser(PPRTR0MEMOBJINTERNAL ppMem, RTR3PTR R3PtrFixed, size_t cb, size_t uAlignment, RTR0PROCESS R0Process) +{ + printf("NativeReserveUser\n"); + return VERR_NOT_SUPPORTED; +} + + +DECLHIDDEN(int) rtR0MemObjNativeMapKernel(PPRTR0MEMOBJINTERNAL ppMem, RTR0MEMOBJ pMemToMap, void *pvFixed, size_t uAlignment, + unsigned fProt, size_t offSub, size_t cbSub) +{ + if (pvFixed != (void *)-1) + { + /* can we support this? or can we assume the virtual space is already reserved? */ + printf("map to specified kernel virtual address not supported\n"); + return VERR_NOT_SUPPORTED; + } + + PRTR0MEMOBJNETBSD pMemNetBSD0 = (PRTR0MEMOBJNETBSD)pMemToMap; + if ((pMemNetBSD0->Core.enmType != RTR0MEMOBJTYPE_PHYS) + && (pMemNetBSD0->Core.enmType != RTR0MEMOBJTYPE_PHYS_NC)) + { + printf("memory to map is not physical\n"); + return VERR_NOT_SUPPORTED; + } + size_t sz = cbSub > 0 ? cbSub : pMemNetBSD0->Core.cb; + + PRTR0MEMOBJNETBSD pMemNetBSD = (PRTR0MEMOBJNETBSD)rtR0MemObjNew(sizeof(*pMemNetBSD), RTR0MEMOBJTYPE_MAPPING, NULL, sz); + + vaddr_t virt = uvm_km_alloc(kernel_map, sz, uAlignment, + UVM_KMF_VAONLY | UVM_KMF_WAITVA | UVM_KMF_CANFAIL); + if (virt == 0) + { + rtR0MemObjDelete(&pMemNetBSD->Core); + return VERR_NO_MEMORY; + } + + vm_prot_t prot = 0; + + if ((fProt & RTMEM_PROT_READ) == RTMEM_PROT_READ) + prot |= VM_PROT_READ; + if ((fProt & RTMEM_PROT_WRITE) == RTMEM_PROT_WRITE) + prot |= VM_PROT_WRITE; + if ((fProt & RTMEM_PROT_EXEC) == RTMEM_PROT_EXEC) + prot |= VM_PROT_EXECUTE; + + struct vm_page *page; + vaddr_t virt2 = virt; + size_t map_pos = 0; + TAILQ_FOREACH(page, &pMemNetBSD0->pglist, pageq.queue) + { + if (map_pos >= offSub) + { + if (cbSub > 0 && (map_pos >= offSub + cbSub)) + break; + + pmap_kenter_pa(virt2, VM_PAGE_TO_PHYS(page), prot, 0); + virt2 += PAGE_SIZE; + } + map_pos += PAGE_SIZE; + } + + pMemNetBSD->Core.pv = (void *)virt; + pMemNetBSD->Core.u.Mapping.R0Process = NIL_RTR0PROCESS; + *ppMem = &pMemNetBSD->Core; + + return VINF_SUCCESS; +} + + +DECLHIDDEN(int) rtR0MemObjNativeMapUser(PPRTR0MEMOBJINTERNAL ppMem, RTR0MEMOBJ pMemToMap, RTR3PTR R3PtrFixed, size_t uAlignment, + unsigned fProt, RTR0PROCESS R0Process) +{ + printf("NativeMapUser\n"); + return VERR_NOT_SUPPORTED; +} + + +DECLHIDDEN(int) rtR0MemObjNativeProtect(PRTR0MEMOBJINTERNAL pMem, size_t offSub, size_t cbSub, uint32_t fProt) +{ + vm_prot_t ProtectionFlags = 0; + vaddr_t AddrStart = (vaddr_t)pMem->pv + offSub; + vm_map_t pVmMap = rtR0MemObjNetBSDGetMap(pMem); + + if (!pVmMap) + return VERR_NOT_SUPPORTED; + + if ((fProt & RTMEM_PROT_READ) == RTMEM_PROT_READ) + ProtectionFlags |= UVM_PROT_R; + if ((fProt & RTMEM_PROT_WRITE) == RTMEM_PROT_WRITE) + ProtectionFlags |= UVM_PROT_W; + if ((fProt & RTMEM_PROT_EXEC) == RTMEM_PROT_EXEC) + ProtectionFlags |= UVM_PROT_X; + + int error = uvm_map_protect(pVmMap, AddrStart, AddrStart + cbSub, + ProtectionFlags, 0); + if (!error) + return VINF_SUCCESS; + + return VERR_NOT_SUPPORTED; +} + + +DECLHIDDEN(RTHCPHYS) rtR0MemObjNativeGetPagePhysAddr(PRTR0MEMOBJINTERNAL pMem, size_t iPage) +{ + PRTR0MEMOBJNETBSD pMemNetBSD = (PRTR0MEMOBJNETBSD)pMem; + + switch (pMemNetBSD->Core.enmType) + { + case RTR0MEMOBJTYPE_PAGE: + case RTR0MEMOBJTYPE_LOW: + { + vaddr_t va = (vaddr_t)pMemNetBSD->Core.pv + ptoa(iPage); + paddr_t pa = 0; + pmap_extract(pmap_kernel(), va, &pa); + return pa; + } + case RTR0MEMOBJTYPE_CONT: + return pMemNetBSD->Core.u.Cont.Phys + ptoa(iPage); + case RTR0MEMOBJTYPE_PHYS: + return pMemNetBSD->Core.u.Phys.PhysBase + ptoa(iPage); + case RTR0MEMOBJTYPE_PHYS_NC: + { + struct vm_page *page; + size_t i = 0; + TAILQ_FOREACH(page, &pMemNetBSD->pglist, pageq.queue) + { + if (i == iPage) + break; + i++; + } + return VM_PAGE_TO_PHYS(page); + } + case RTR0MEMOBJTYPE_LOCK: + case RTR0MEMOBJTYPE_MAPPING: + { + pmap_t pmap; + if (pMem->u.Lock.R0Process == NIL_RTR0PROCESS) + pmap = pmap_kernel(); + else + pmap = ((struct proc *)pMem->u.Lock.R0Process)->p_vmspace->vm_map.pmap; + vaddr_t va = (vaddr_t)pMemNetBSD->Core.pv + ptoa(iPage); + paddr_t pa = 0; + pmap_extract(pmap, va, &pa); + return pa; + } + case RTR0MEMOBJTYPE_RES_VIRT: + return NIL_RTHCPHYS; + default: + return NIL_RTHCPHYS; + } +} diff --git a/src/VBox/Runtime/r0drv/netbsd/memuserkernel-r0drv-netbsd.c b/src/VBox/Runtime/r0drv/netbsd/memuserkernel-r0drv-netbsd.c new file mode 100644 index 00000000..cf67730d --- /dev/null +++ b/src/VBox/Runtime/r0drv/netbsd/memuserkernel-r0drv-netbsd.c @@ -0,0 +1,82 @@ +/* $Id: memuserkernel-r0drv-netbsd.c $ */ +/** @file + * IPRT - User & Kernel Memory, Ring-0 Driver, NetBSD. + */ + +/* + * Copyright (C) 2009-2019 Oracle Corporation + * + * This file is part of VirtualBox Open Source Edition (OSE), as + * available from http://www.virtualbox.org. This file is free software; + * you can redistribute it and/or modify it under the terms of the GNU + * General Public License (GPL) as published by the Free Software + * Foundation, in version 2 as it comes in the "COPYING" file of the + * VirtualBox OSE distribution. VirtualBox OSE is distributed in the + * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL) only, as it comes in the "COPYING.CDDL" file of the + * VirtualBox OSE distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "the-netbsd-kernel.h" + +#include <iprt/mem.h> +#include <iprt/errcore.h> + + +RTR0DECL(int) RTR0MemUserCopyFrom(void *pvDst, RTR3PTR R3PtrSrc, size_t cb) +{ + int rc = copyin((const void *)R3PtrSrc, pvDst, cb); + if (RT_LIKELY(rc == 0)) + return VINF_SUCCESS; + return VERR_ACCESS_DENIED; +} + + +RTR0DECL(int) RTR0MemUserCopyTo(RTR3PTR R3PtrDst, void const *pvSrc, size_t cb) +{ + int rc = copyout(pvSrc, (void *)R3PtrDst, cb); + if (RT_LIKELY(rc == 0)) + return VINF_SUCCESS; + return VERR_ACCESS_DENIED; +} + + +RTR0DECL(bool) RTR0MemUserIsValidAddr(RTR3PTR R3Ptr) +{ + return R3Ptr < VM_MAXUSER_ADDRESS; +} + + +RTR0DECL(bool) RTR0MemKernelIsValidAddr(void *pv) +{ + return (uintptr_t)pv >= VM_MAXUSER_ADDRESS; +} + + +RTR0DECL(bool) RTR0MemAreKrnlAndUsrDifferent(void) +{ + return true; +} + + +RTR0DECL(int) RTR0MemKernelCopyFrom(void *pvDst, void const *pvSrc, size_t cb) +{ + return VERR_NOT_SUPPORTED; +} + + +RTR0DECL(int) RTR0MemKernelCopyTo(void *pvDst, void const *pvSrc, size_t cb) +{ + return VERR_NOT_SUPPORTED; +} diff --git a/src/VBox/Runtime/r0drv/netbsd/mp-r0drv-netbsd.c b/src/VBox/Runtime/r0drv/netbsd/mp-r0drv-netbsd.c new file mode 100644 index 00000000..29472496 --- /dev/null +++ b/src/VBox/Runtime/r0drv/netbsd/mp-r0drv-netbsd.c @@ -0,0 +1,43 @@ +/* $Id: mp-r0drv-netbsd.c $ */ +/** @file + * IPRT - Multiprocessor, Ring-0 Driver, NetBSD. + */ + +/* + * Copyright (C) 2008-2019 Oracle Corporation + * + * This file is part of VirtualBox Open Source Edition (OSE), as + * available from http://www.virtualbox.org. This file is free software; + * you can redistribute it and/or modify it under the terms of the GNU + * General Public License (GPL) as published by the Free Software + * Foundation, in version 2 as it comes in the "COPYING" file of the + * VirtualBox OSE distribution. VirtualBox OSE is distributed in the + * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL) only, as it comes in the "COPYING.CDDL" file of the + * VirtualBox OSE distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "the-netbsd-kernel.h" + +#include <iprt/mp.h> +#include <iprt/errcore.h> +#include <iprt/asm.h> +#include <iprt/cpuset.h> +#include "r0drv/mp-r0drv.h" + + +RTDECL(RTCPUID) RTMpCpuId(void) +{ + return cpu_number(); +} diff --git a/src/VBox/Runtime/r0drv/netbsd/process-r0drv-netbsd.c b/src/VBox/Runtime/r0drv/netbsd/process-r0drv-netbsd.c new file mode 100644 index 00000000..5b58bfe2 --- /dev/null +++ b/src/VBox/Runtime/r0drv/netbsd/process-r0drv-netbsd.c @@ -0,0 +1,51 @@ +/* $Id: process-r0drv-netbsd.c $ */ +/** @file + * IPRT - Process Management, Ring-0 Driver, NetBSD. + */ + +/* + * Copyright (c) 2007 knut st. osmundsen <bird-src-spam@anduin.net> + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "the-netbsd-kernel.h" + +#include <iprt/process.h> + + +RTDECL(RTPROCESS) RTProcSelf(void) +{ + struct proc *pSelf = curproc; + return pSelf->p_pid; +} + + +RTR0DECL(RTR0PROCESS) RTR0ProcHandleSelf(void) +{ + return (RTR0PROCESS)curproc; +} + diff --git a/src/VBox/Runtime/r0drv/netbsd/semevent-r0drv-netbsd.c b/src/VBox/Runtime/r0drv/netbsd/semevent-r0drv-netbsd.c new file mode 100644 index 00000000..716e5396 --- /dev/null +++ b/src/VBox/Runtime/r0drv/netbsd/semevent-r0drv-netbsd.c @@ -0,0 +1,255 @@ +/* $Id: semevent-r0drv-netbsd.c $ */ +/** @file + * IPRT - Single Release Event Semaphores, Ring-0 Driver, NetBSD. + */ + +/* + * Copyright (c) 2007 knut st. osmundsen <bird-src-spam@anduin.net> + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#define RTSEMEVENT_WITHOUT_REMAPPING +#include "the-netbsd-kernel.h" +#include "internal/iprt.h" +#include <iprt/semaphore.h> + +#include <iprt/asm.h> +#include <iprt/assert.h> +#include <iprt/err.h> +#include <iprt/lockvalidator.h> +#include <iprt/mem.h> + +#include "sleepqueue-r0drv-netbsd.h" +#include "internal/magics.h" + + +/********************************************************************************************************************************* +* Structures and Typedefs * +*********************************************************************************************************************************/ +/** + * NetBSD event semaphore. + */ +typedef struct RTSEMEVENTINTERNAL +{ + /** Magic value (RTSEMEVENT_MAGIC). */ + uint32_t volatile u32Magic; + /** The object status - !0 when signaled and 0 when reset. */ + uint32_t volatile fState; + /** Reference counter. */ + uint32_t volatile cRefs; +} RTSEMEVENTINTERNAL, *PRTSEMEVENTINTERNAL; + + +RTDECL(int) RTSemEventCreate(PRTSEMEVENT phEventSem) +{ + return RTSemEventCreateEx(phEventSem, 0 /*fFlags*/, NIL_RTLOCKVALCLASS, NULL); +} + + +RTDECL(int) RTSemEventCreateEx(PRTSEMEVENT phEventSem, uint32_t fFlags, RTLOCKVALCLASS hClass, const char *pszNameFmt, ...) +{ + AssertCompile(sizeof(RTSEMEVENTINTERNAL) > sizeof(void *)); + AssertReturn(!(fFlags & ~(RTSEMEVENT_FLAGS_NO_LOCK_VAL | RTSEMEVENT_FLAGS_BOOTSTRAP_HACK)), VERR_INVALID_PARAMETER); + Assert(!(fFlags & RTSEMEVENT_FLAGS_BOOTSTRAP_HACK) || (fFlags & RTSEMEVENT_FLAGS_NO_LOCK_VAL)); + AssertPtrReturn(phEventSem, VERR_INVALID_POINTER); + + PRTSEMEVENTINTERNAL pThis = (PRTSEMEVENTINTERNAL)RTMemAllocZ(sizeof(*pThis)); + if (!pThis) + return VERR_NO_MEMORY; + + pThis->u32Magic = RTSEMEVENT_MAGIC; + pThis->cRefs = 1; + pThis->fState = 0; + + *phEventSem = pThis; + return VINF_SUCCESS; +} + + +/** + * Retains a reference to the event semaphore. + * + * @param pThis The event semaphore. + */ +DECLINLINE(void) rtR0SemEventBsdRetain(PRTSEMEVENTINTERNAL pThis) +{ + uint32_t cRefs = ASMAtomicIncU32(&pThis->cRefs); + Assert(cRefs < 100000); NOREF(cRefs); +} + + +/** + * Releases a reference to the event semaphore. + * + * @param pThis The event semaphore. + */ +DECLINLINE(void) rtR0SemEventBsdRelease(PRTSEMEVENTINTERNAL pThis) +{ + if (RT_UNLIKELY(ASMAtomicDecU32(&pThis->cRefs) == 0)) + RTMemFree(pThis); +} + + +RTDECL(int) RTSemEventDestroy(RTSEMEVENT hEventSem) +{ + /* + * Validate input. + */ + PRTSEMEVENTINTERNAL pThis = hEventSem; + if (pThis == NIL_RTSEMEVENT) + return VINF_SUCCESS; + AssertMsgReturn(pThis->u32Magic == RTSEMEVENT_MAGIC, ("pThis->u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis), VERR_INVALID_HANDLE); + Assert(pThis->cRefs > 0); + + /* + * Invalidate it and signal the object just in case. + */ + ASMAtomicWriteU32(&pThis->u32Magic, ~RTSEMEVENT_MAGIC); + ASMAtomicWriteU32(&pThis->fState, 0); + rtR0SemBsdBroadcast(pThis); + rtR0SemEventBsdRelease(pThis); + return VINF_SUCCESS; +} + + +RTDECL(int) RTSemEventSignal(RTSEMEVENT hEventSem) +{ + /* + * Validate input. + */ + PRTSEMEVENTINTERNAL pThis = (PRTSEMEVENTINTERNAL)hEventSem; + AssertPtrReturn(pThis, VERR_INVALID_HANDLE); + AssertMsgReturn(pThis->u32Magic == RTSEMEVENT_MAGIC, ("pThis->u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis), VERR_INVALID_HANDLE); + rtR0SemEventBsdRetain(pThis); + + /* + * Signal the event object. + */ + ASMAtomicWriteU32(&pThis->fState, 1); + rtR0SemBsdSignal(pThis); + rtR0SemEventBsdRelease(pThis); + return VINF_SUCCESS; +} + +/** + * Worker for RTSemEventWaitEx and RTSemEventWaitExDebug. + * + * @returns VBox status code. + * @param pThis The event semaphore. + * @param fFlags See RTSemEventWaitEx. + * @param uTimeout See RTSemEventWaitEx. + * @param pSrcPos The source code position of the wait. + */ +static int rtR0SemEventWait(PRTSEMEVENTINTERNAL pThis, uint32_t fFlags, uint64_t uTimeout, + PCRTLOCKVALSRCPOS pSrcPos) +{ + int rc; + + /* + * Validate the input. + */ + AssertPtrReturn(pThis, VERR_INVALID_PARAMETER); + AssertMsgReturn(pThis->u32Magic == RTSEMEVENT_MAGIC, ("%p u32Magic=%RX32\n", pThis, pThis->u32Magic), VERR_INVALID_PARAMETER); + AssertReturn(RTSEMWAIT_FLAGS_ARE_VALID(fFlags), VERR_INVALID_PARAMETER); + rtR0SemEventBsdRetain(pThis); + + /* + * Try grab the event without setting up the wait. + */ + if (ASMAtomicCmpXchgU32(&pThis->fState, 0, 1)) + rc = VINF_SUCCESS; + else + { + /* + * We have to wait. + */ + RTR0SEMBSDSLEEP Wait; + rc = rtR0SemBsdWaitInit(&Wait, fFlags, uTimeout, pThis); + if (RT_SUCCESS(rc)) + { + for (;;) + { + /* The destruction test. */ + if (RT_UNLIKELY(pThis->u32Magic != RTSEMEVENT_MAGIC)) + rc = VERR_SEM_DESTROYED; + else + { + rtR0SemBsdWaitPrepare(&Wait); + + /* Check the exit conditions. */ + if (RT_UNLIKELY(pThis->u32Magic != RTSEMEVENT_MAGIC)) + rc = VERR_SEM_DESTROYED; + else if (ASMAtomicCmpXchgU32(&pThis->fState, 0, 1)) + rc = VINF_SUCCESS; + else if (rtR0SemBsdWaitHasTimedOut(&Wait)) + rc = VERR_TIMEOUT; + else if (rtR0SemBsdWaitWasInterrupted(&Wait)) + rc = VERR_INTERRUPTED; + else + { + /* Do the wait and then recheck the conditions. */ + rtR0SemBsdWaitDoIt(&Wait); + continue; + } + } + break; + } + + rtR0SemBsdWaitDelete(&Wait); + } + } + + rtR0SemEventBsdRelease(pThis); + return rc; +} + + +RTDECL(int) RTSemEventWaitEx(RTSEMEVENT hEventSem, uint32_t fFlags, uint64_t uTimeout) +{ +#ifndef RTSEMEVENT_STRICT + return rtR0SemEventWait(hEventSem, fFlags, uTimeout, NULL); +#else + RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_NORMAL_API(); + return rtR0SemEventWait(hEventSem, fFlags, uTimeout, &SrcPos); +#endif +} +RT_EXPORT_SYMBOL(RTSemEventWaitEx); + + +RTDECL(int) RTSemEventWaitExDebug(RTSEMEVENT hEventSem, uint32_t fFlags, uint64_t uTimeout, + RTHCUINTPTR uId, RT_SRC_POS_DECL) +{ + RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_DEBUG_API(); + return rtR0SemEventWait(hEventSem, fFlags, uTimeout, &SrcPos); +} +RT_EXPORT_SYMBOL(RTSemEventWaitExDebug); + + +RTDECL(uint32_t) RTSemEventGetResolution(void) +{ + return 1000000000 / hz; +} diff --git a/src/VBox/Runtime/r0drv/netbsd/semeventmulti-r0drv-netbsd.c b/src/VBox/Runtime/r0drv/netbsd/semeventmulti-r0drv-netbsd.c new file mode 100644 index 00000000..48c2cec8 --- /dev/null +++ b/src/VBox/Runtime/r0drv/netbsd/semeventmulti-r0drv-netbsd.c @@ -0,0 +1,319 @@ +/* $Id: semeventmulti-r0drv-netbsd.c $ */ +/** @file + * IPRT - Multiple Release Event Semaphores, Ring-0 Driver, NetBSD. + */ + +/* + * Copyright (c) 2007 knut st. osmundsen <bird-src-spam@anduin.net> + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#define RTSEMEVENTMULTI_WITHOUT_REMAPPING +#include "the-netbsd-kernel.h" +#include "internal/iprt.h" +#include <iprt/semaphore.h> + +#include <iprt/assert.h> +#include <iprt/asm.h> +#include <iprt/err.h> +#include <iprt/mem.h> +#include <iprt/lockvalidator.h> + +#include "sleepqueue-r0drv-netbsd.h" +#include "internal/magics.h" + + +/********************************************************************************************************************************* +* Defined Constants And Macros * +*********************************************************************************************************************************/ +/** @name fStateAndGen values + * @{ */ +/** The state bit number. */ +#define RTSEMEVENTMULTIBSD_STATE_BIT 0 +/** The state mask. */ +#define RTSEMEVENTMULTIBSD_STATE_MASK RT_BIT_32(RTSEMEVENTMULTIBSD_STATE_BIT) +/** The generation mask. */ +#define RTSEMEVENTMULTIBSD_GEN_MASK ~RTSEMEVENTMULTIBSD_STATE_MASK +/** The generation shift. */ +#define RTSEMEVENTMULTIBSD_GEN_SHIFT 1 +/** The initial variable value. */ +#define RTSEMEVENTMULTIBSD_STATE_GEN_INIT UINT32_C(0xfffffffc) +/** @} */ + + +/********************************************************************************************************************************* +* Structures and Typedefs * +*********************************************************************************************************************************/ +/** + * NetBSD multiple release event semaphore. + */ +typedef struct RTSEMEVENTMULTIINTERNAL +{ + /** Magic value (RTSEMEVENTMULTI_MAGIC). */ + uint32_t volatile u32Magic; + /** The object state bit and generation counter. + * The generation counter is incremented every time the object is + * signalled. */ + uint32_t volatile fStateAndGen; + /** Reference counter. */ + uint32_t volatile cRefs; +} RTSEMEVENTMULTIINTERNAL, *PRTSEMEVENTMULTIINTERNAL; + + +RTDECL(int) RTSemEventMultiCreate(PRTSEMEVENTMULTI phEventMultiSem) +{ + return RTSemEventMultiCreateEx(phEventMultiSem, 0 /*fFlags*/, NIL_RTLOCKVALCLASS, NULL); +} + + +RTDECL(int) RTSemEventMultiCreateEx(PRTSEMEVENTMULTI phEventMultiSem, uint32_t fFlags, RTLOCKVALCLASS hClass, + const char *pszNameFmt, ...) +{ + PRTSEMEVENTMULTIINTERNAL pThis; + + AssertReturn(!(fFlags & ~RTSEMEVENTMULTI_FLAGS_NO_LOCK_VAL), VERR_INVALID_PARAMETER); + pThis = (PRTSEMEVENTMULTIINTERNAL)RTMemAlloc(sizeof(*pThis)); + if (pThis) + { + pThis->u32Magic = RTSEMEVENTMULTI_MAGIC; + pThis->fStateAndGen = RTSEMEVENTMULTIBSD_STATE_GEN_INIT; + pThis->cRefs = 1; + + *phEventMultiSem = pThis; + return VINF_SUCCESS; + } + return VERR_NO_MEMORY; +} + + +/** + * Retain a reference to the semaphore. + * + * @param pThis The semaphore. + */ +DECLINLINE(void) rtR0SemEventMultiBsdRetain(PRTSEMEVENTMULTIINTERNAL pThis) +{ + uint32_t cRefs = ASMAtomicIncU32(&pThis->cRefs); + Assert(cRefs && cRefs < 100000); +} + + +/** + * Release a reference, destroy the thing if necessary. + * + * @param pThis The semaphore. + */ +DECLINLINE(void) rtR0SemEventMultiBsdRelease(PRTSEMEVENTMULTIINTERNAL pThis) +{ + if (RT_UNLIKELY(ASMAtomicDecU32(&pThis->cRefs) == 0)) + { + Assert(pThis->u32Magic != RTSEMEVENTMULTI_MAGIC); + RTMemFree(pThis); + } +} + + +RTDECL(int) RTSemEventMultiDestroy(RTSEMEVENTMULTI hEventMultiSem) +{ + /* + * Validate input. + */ + PRTSEMEVENTMULTIINTERNAL pThis = (PRTSEMEVENTMULTIINTERNAL)hEventMultiSem; + if (pThis == NIL_RTSEMEVENTMULTI) + return VINF_SUCCESS; + AssertPtrReturn(pThis, VERR_INVALID_PARAMETER); + AssertMsgReturn(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC, ("%p u32Magic=%RX32\n", pThis, pThis->u32Magic), VERR_INVALID_PARAMETER); + Assert(pThis->cRefs > 0); + + /* + * Invalidate it and signal the object just in case. + */ + ASMAtomicWriteU32(&pThis->u32Magic, ~RTSEMEVENTMULTI_MAGIC); + ASMAtomicAndU32(&pThis->fStateAndGen, RTSEMEVENTMULTIBSD_GEN_MASK); + rtR0SemBsdBroadcast(pThis); + rtR0SemEventMultiBsdRelease(pThis); + return VINF_SUCCESS; +} + + +RTDECL(int) RTSemEventMultiSignal(RTSEMEVENTMULTI hEventMultiSem) +{ + uint32_t fNew; + uint32_t fOld; + + /* + * Validate input. + */ + PRTSEMEVENTMULTIINTERNAL pThis = (PRTSEMEVENTMULTIINTERNAL)hEventMultiSem; + if (!pThis) + return VERR_INVALID_PARAMETER; + AssertPtrReturn(pThis, VERR_INVALID_PARAMETER); + AssertMsgReturn(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC, ("%p u32Magic=%RX32\n", pThis, pThis->u32Magic), VERR_INVALID_PARAMETER); + rtR0SemEventMultiBsdRetain(pThis); + + /* + * Signal the event object. The cause of the parnoia here is racing to try + * deal with racing RTSemEventMultiSignal calls (should probably be + * forbidden, but it's relatively easy to handle). + */ + do + { + fNew = fOld = ASMAtomicUoReadU32(&pThis->fStateAndGen); + fNew += 1 << RTSEMEVENTMULTIBSD_GEN_SHIFT; + fNew |= RTSEMEVENTMULTIBSD_STATE_MASK; + } + while (!ASMAtomicCmpXchgU32(&pThis->fStateAndGen, fNew, fOld)); + + rtR0SemBsdBroadcast(pThis); + rtR0SemEventMultiBsdRelease(pThis); + return VINF_SUCCESS; +} + + +RTDECL(int) RTSemEventMultiReset(RTSEMEVENTMULTI hEventMultiSem) +{ + /* + * Validate input. + */ + PRTSEMEVENTMULTIINTERNAL pThis = (PRTSEMEVENTMULTIINTERNAL)hEventMultiSem; + if (!pThis) + return VERR_INVALID_PARAMETER; + AssertPtrReturn(pThis, VERR_INVALID_PARAMETER); + AssertMsgReturn(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC, ("%p u32Magic=%RX32\n", pThis, pThis->u32Magic), VERR_INVALID_PARAMETER); + rtR0SemEventMultiBsdRetain(pThis); + + /* + * Reset it. + */ + ASMAtomicAndU32(&pThis->fStateAndGen, ~RTSEMEVENTMULTIBSD_STATE_MASK); + + rtR0SemEventMultiBsdRelease(pThis); + return VINF_SUCCESS; +} + + +/** + * Worker for RTSemEventMultiWaitEx and RTSemEventMultiWaitExDebug. + * + * @returns VBox status code. + * @param pThis The event semaphore. + * @param fFlags See RTSemEventMultiWaitEx. + * @param uTimeout See RTSemEventMultiWaitEx. + * @param pSrcPos The source code position of the wait. + */ +static int rtR0SemEventMultiBsdWait(PRTSEMEVENTMULTIINTERNAL pThis, uint32_t fFlags, uint64_t uTimeout, + PCRTLOCKVALSRCPOS pSrcPos) +{ + uint32_t fOrgStateAndGen; + int rc; + + /* + * Validate the input. + */ + AssertPtrReturn(pThis, VERR_INVALID_PARAMETER); + AssertMsgReturn(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC, ("%p u32Magic=%RX32\n", pThis, pThis->u32Magic), VERR_INVALID_PARAMETER); + AssertReturn(RTSEMWAIT_FLAGS_ARE_VALID(fFlags), VERR_INVALID_PARAMETER); + rtR0SemEventMultiBsdRetain(pThis); + + /* + * Is the event already signalled or do we have to wait? + */ + fOrgStateAndGen = ASMAtomicUoReadU32(&pThis->fStateAndGen); + if (fOrgStateAndGen & RTSEMEVENTMULTIBSD_STATE_MASK) + rc = VINF_SUCCESS; + else + { + /* + * We have to wait. + */ + RTR0SEMBSDSLEEP Wait; + rc = rtR0SemBsdWaitInit(&Wait, fFlags, uTimeout, pThis); + if (RT_SUCCESS(rc)) + { + for (;;) + { + /* The destruction test. */ + if (RT_UNLIKELY(pThis->u32Magic != RTSEMEVENTMULTI_MAGIC)) + rc = VERR_SEM_DESTROYED; + else + { + rtR0SemBsdWaitPrepare(&Wait); + + /* Check the exit conditions. */ + if (RT_UNLIKELY(pThis->u32Magic != RTSEMEVENTMULTI_MAGIC)) + rc = VERR_SEM_DESTROYED; + else if (ASMAtomicUoReadU32(&pThis->fStateAndGen) != fOrgStateAndGen) + rc = VINF_SUCCESS; + else if (rtR0SemBsdWaitHasTimedOut(&Wait)) + rc = VERR_TIMEOUT; + else if (rtR0SemBsdWaitWasInterrupted(&Wait)) + rc = VERR_INTERRUPTED; + else + { + /* Do the wait and then recheck the conditions. */ + rtR0SemBsdWaitDoIt(&Wait); + continue; + } + } + break; + } + + rtR0SemBsdWaitDelete(&Wait); + } + } + + rtR0SemEventMultiBsdRelease(pThis); + return rc; +} + + +RTDECL(int) RTSemEventMultiWaitEx(RTSEMEVENTMULTI hEventMultiSem, uint32_t fFlags, uint64_t uTimeout) +{ +#ifndef RTSEMEVENT_STRICT + return rtR0SemEventMultiBsdWait(hEventMultiSem, fFlags, uTimeout, NULL); +#else + RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_NORMAL_API(); + return rtR0SemEventMultiBsdWait(hEventMultiSem, fFlags, uTimeout, &SrcPos); +#endif +} +RT_EXPORT_SYMBOL(RTSemEventMultiWaitEx); + + +RTDECL(int) RTSemEventMultiWaitExDebug(RTSEMEVENTMULTI hEventMultiSem, uint32_t fFlags, uint64_t uTimeout, + RTHCUINTPTR uId, RT_SRC_POS_DECL) +{ + RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_DEBUG_API(); + return rtR0SemEventMultiBsdWait(hEventMultiSem, fFlags, uTimeout, &SrcPos); +} +RT_EXPORT_SYMBOL(RTSemEventMultiWaitExDebug); + + +RTDECL(uint32_t) RTSemEventMultiGetResolution(void) +{ + return rtR0SemBsdWaitGetResolution(); +} +RT_EXPORT_SYMBOL(RTSemEventMultiGetResolution); diff --git a/src/VBox/Runtime/r0drv/netbsd/semfastmutex-r0drv-netbsd.c b/src/VBox/Runtime/r0drv/netbsd/semfastmutex-r0drv-netbsd.c new file mode 100644 index 00000000..8327ae4b --- /dev/null +++ b/src/VBox/Runtime/r0drv/netbsd/semfastmutex-r0drv-netbsd.c @@ -0,0 +1,114 @@ +/* $Id: semfastmutex-r0drv-netbsd.c $ */ +/** @file + * IPRT - Fast Mutex Semaphores, Ring-0 Driver, NetBSD. + */ + +/* + * Copyright (c) 2007 knut st. osmundsen <bird-src-spam@anduin.net> + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "the-netbsd-kernel.h" + +#include <iprt/semaphore.h> +#include <iprt/errcore.h> +#include <iprt/alloc.h> +#include <iprt/assert.h> +#include <iprt/asm.h> + +#include "internal/magics.h" + + +/********************************************************************************************************************************* +* Structures and Typedefs * +*********************************************************************************************************************************/ +/** + * Wrapper for the NetBSD (sleep) mutex. + */ +typedef struct RTSEMFASTMUTEXINTERNAL +{ + /** Magic value (RTSEMFASTMUTEX_MAGIC). */ + uint32_t u32Magic; + /** The NetBSD shared/exclusive lock mutex. */ + krwlock_t Mtx; +} RTSEMFASTMUTEXINTERNAL, *PRTSEMFASTMUTEXINTERNAL; + + +RTDECL(int) RTSemFastMutexCreate(PRTSEMFASTMUTEX phFastMtx) +{ + AssertCompile(sizeof(RTSEMFASTMUTEXINTERNAL) > sizeof(void *)); + AssertPtrReturn(phFastMtx, VERR_INVALID_POINTER); + + PRTSEMFASTMUTEXINTERNAL pThis = (PRTSEMFASTMUTEXINTERNAL)RTMemAllocZ(sizeof(*pThis)); + if (pThis) + { + pThis->u32Magic = RTSEMFASTMUTEX_MAGIC; + rw_init(&pThis->Mtx); + + *phFastMtx = pThis; + return VINF_SUCCESS; + } + return VERR_NO_MEMORY; +} + + +RTDECL(int) RTSemFastMutexDestroy(RTSEMFASTMUTEX hFastMtx) +{ + PRTSEMFASTMUTEXINTERNAL pThis = hFastMtx; + if (pThis == NIL_RTSEMFASTMUTEX) + return VINF_SUCCESS; + AssertPtrReturn(pThis, VERR_INVALID_HANDLE); + AssertMsgReturn(pThis->u32Magic == RTSEMFASTMUTEX_MAGIC, ("%p: u32Magic=%RX32\n", pThis, pThis->u32Magic), VERR_INVALID_HANDLE); + + ASMAtomicWriteU32(&pThis->u32Magic, RTSEMFASTMUTEX_MAGIC_DEAD); + rw_destroy(&pThis->Mtx); + RTMemFree(pThis); + + return VINF_SUCCESS; +} + + +RTDECL(int) RTSemFastMutexRequest(RTSEMFASTMUTEX hFastMtx) +{ + PRTSEMFASTMUTEXINTERNAL pThis = hFastMtx; + AssertPtrReturn(pThis, VERR_INVALID_HANDLE); + AssertMsgReturn(pThis->u32Magic == RTSEMFASTMUTEX_MAGIC, ("%p: u32Magic=%RX32\n", pThis, pThis->u32Magic), VERR_INVALID_HANDLE); + + rw_enter(&pThis->Mtx, RW_WRITER); + return VINF_SUCCESS; +} + + +RTDECL(int) RTSemFastMutexRelease(RTSEMFASTMUTEX hFastMtx) +{ + PRTSEMFASTMUTEXINTERNAL pThis = hFastMtx; + AssertPtrReturn(pThis, VERR_INVALID_HANDLE); + AssertMsgReturn(pThis->u32Magic == RTSEMFASTMUTEX_MAGIC, ("%p: u32Magic=%RX32\n", pThis, pThis->u32Magic), VERR_INVALID_HANDLE); + + rw_exit(&pThis->Mtx); + return VINF_SUCCESS; +} diff --git a/src/VBox/Runtime/r0drv/netbsd/semmutex-r0drv-netbsd.c b/src/VBox/Runtime/r0drv/netbsd/semmutex-r0drv-netbsd.c new file mode 100644 index 00000000..e815ae6c --- /dev/null +++ b/src/VBox/Runtime/r0drv/netbsd/semmutex-r0drv-netbsd.c @@ -0,0 +1,218 @@ +/* $Id: semmutex-r0drv-netbsd.c $ */ +/** @file + * IPRT - Mutex Semaphores, Ring-0 Driver, NetBSD. + */ + +/* + * Copyright (C) 2010-2019 Oracle Corporation + * + * This file is part of VirtualBox Open Source Edition (OSE), as + * available from http://www.virtualbox.org. This file is free software; + * you can redistribute it and/or modify it under the terms of the GNU + * General Public License (GPL) as published by the Free Software + * Foundation, in version 2 as it comes in the "COPYING" file of the + * VirtualBox OSE distribution. VirtualBox OSE is distributed in the + * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL) only, as it comes in the "COPYING.CDDL" file of the + * VirtualBox OSE distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#define RTSEMMUTEX_WITHOUT_REMAPPING +#include "the-netbsd-kernel.h" +#include "internal/iprt.h" +#include <iprt/semaphore.h> + +#include <iprt/asm.h> +#include <iprt/assert.h> +#include <iprt/errcore.h> +#include <iprt/mem.h> +#include <iprt/thread.h> +#include <iprt/time.h> + +#include "internal/magics.h" + + +/********************************************************************************************************************************* +* Structures and Typedefs * +*********************************************************************************************************************************/ +/** + * Wrapper for the NetBSD (sleep) mutex. + */ +typedef struct RTSEMMUTEXINTERNAL +{ + /** Magic value (RTSEMMUTEX_MAGIC). */ + uint32_t u32Magic; + /** The NetBSD shared/exclusive lock mutex. */ + struct sx SxLock; +} RTSEMMUTEXINTERNAL, *PRTSEMMUTEXINTERNAL; + + +RTDECL(int) RTSemMutexCreate(PRTSEMMUTEX phMutexSem) +{ + AssertCompile(sizeof(RTSEMMUTEXINTERNAL) > sizeof(void *)); + AssertPtrReturn(phMutexSem, VERR_INVALID_POINTER); + + PRTSEMMUTEXINTERNAL pThis = (PRTSEMMUTEXINTERNAL)RTMemAllocZ(sizeof(*pThis)); + if (pThis) + { + pThis->u32Magic = RTSEMMUTEX_MAGIC; + sx_init_flags(&pThis->SxLock, "IPRT Mutex Semaphore", SX_RECURSE); + + *phMutexSem = pThis; + return VINF_SUCCESS; + } + return VERR_NO_MEMORY; +} + + +RTDECL(int) RTSemMutexDestroy(RTSEMMUTEX hMutexSem) +{ + PRTSEMMUTEXINTERNAL pThis = hMutexSem; + if (pThis == NIL_RTSEMMUTEX) + return VINF_SUCCESS; + AssertPtrReturn(pThis, VERR_INVALID_HANDLE); + AssertMsgReturn(pThis->u32Magic == RTSEMMUTEX_MAGIC, ("%p: u32Magic=%RX32\n", pThis, pThis->u32Magic), VERR_INVALID_HANDLE); + + AssertReturn(ASMAtomicCmpXchgU32(&pThis->u32Magic, RTSEMMUTEX_MAGIC_DEAD, RTSEMMUTEX_MAGIC), VERR_INVALID_HANDLE); + + sx_destroy(&pThis->SxLock); + RTMemFree(pThis); + + return VINF_SUCCESS; +} + + +RTDECL(int) RTSemMutexRequest(RTSEMMUTEX hMutexSem, RTMSINTERVAL cMillies) +{ + PRTSEMMUTEXINTERNAL pThis = hMutexSem; + int rc; + AssertPtrReturn(pThis, VERR_INVALID_HANDLE); + AssertMsgReturn(pThis->u32Magic == RTSEMMUTEX_MAGIC, ("%p: u32Magic=%RX32\n", pThis, pThis->u32Magic), VERR_INVALID_HANDLE); + + if (cMillies == RT_INDEFINITE_WAIT) + { + sx_xlock(&pThis->SxLock); + rc = VINF_SUCCESS; + } + else if (!cMillies) + { + if (sx_try_xlock(&pThis->SxLock)) + rc = VINF_SUCCESS; + else + rc = VERR_TIMEOUT; + } + /* + * GROSS HACK: poll implementation of timeout. + */ + /** @todo Implement timeouts in RTSemMutexRequest. */ + else if (sx_try_xlock(&pThis->SxLock)) + rc = VINF_SUCCESS; + else + { + uint64_t StartTS = RTTimeSystemMilliTS(); + rc = VERR_TIMEOUT; + do + { + RTThreadSleep(1); + if (sx_try_xlock(&pThis->SxLock)) + { + rc = VINF_SUCCESS; + break; + } + } while (RTTimeSystemMilliTS() - StartTS < cMillies); + } + + return rc; +} + + +RTDECL(int) RTSemMutexRequestDebug(RTSEMMUTEX hMutexSem, RTMSINTERVAL cMillies, RTHCUINTPTR uId, RT_SRC_POS_DECL) +{ + return RTSemMutexRequest(hMutexSem, cMillies); +} + + +RTDECL(int) RTSemMutexRequestNoResume(RTSEMMUTEX hMutexSem, RTMSINTERVAL cMillies) +{ + PRTSEMMUTEXINTERNAL pThis = hMutexSem; + int rc; + AssertPtrReturn(pThis, VERR_INVALID_HANDLE); + AssertMsgReturn(pThis->u32Magic == RTSEMMUTEX_MAGIC, ("%p: u32Magic=%RX32\n", pThis, pThis->u32Magic), VERR_INVALID_HANDLE); + + if (cMillies == RT_INDEFINITE_WAIT) + { + if (!sx_xlock_sig(&pThis->SxLock)) + rc = VINF_SUCCESS; + else + rc = VERR_INTERRUPTED; + } + else if (!cMillies) + { + if (sx_try_xlock(&pThis->SxLock)) + rc = VINF_SUCCESS; + else + rc = VERR_TIMEOUT; + } + /* + * GROSS HACK: poll implementation of timeout. + */ + /** @todo Implement timeouts and interrupt checks in + * RTSemMutexRequestNoResume. */ + else if (sx_try_xlock(&pThis->SxLock)) + rc = VINF_SUCCESS; + else + { + uint64_t StartTS = RTTimeSystemMilliTS(); + rc = VERR_TIMEOUT; + do + { + RTThreadSleep(1); + if (sx_try_xlock(&pThis->SxLock)) + { + rc = VINF_SUCCESS; + break; + } + } while (RTTimeSystemMilliTS() - StartTS < cMillies); + } + + return rc; +} + + +RTDECL(int) RTSemMutexRequestNoResumeDebug(RTSEMMUTEX hMutexSem, RTMSINTERVAL cMillies, RTHCUINTPTR uId, RT_SRC_POS_DECL) +{ + return RTSemMutexRequestNoResume(hMutexSem, cMillies); +} + + +RTDECL(int) RTSemMutexRelease(RTSEMMUTEX hMutexSem) +{ + PRTSEMMUTEXINTERNAL pThis = hMutexSem; + AssertPtrReturn(pThis, VERR_INVALID_HANDLE); + AssertMsgReturn(pThis->u32Magic == RTSEMMUTEX_MAGIC, ("%p: u32Magic=%RX32\n", pThis, pThis->u32Magic), VERR_INVALID_HANDLE); + + sx_xunlock(&pThis->SxLock); + return VINF_SUCCESS; +} + + + +RTDECL(bool) RTSemMutexIsOwned(RTSEMMUTEX hMutexSem) +{ + PRTSEMMUTEXINTERNAL pThis = hMutexSem; + AssertPtrReturn(pThis, false); + AssertMsgReturn(pThis->u32Magic == RTSEMMUTEX_MAGIC, ("%p: u32Magic=%RX32\n", pThis, pThis->u32Magic), false); + + return sx_xlocked(&pThis->SxLock); +} diff --git a/src/VBox/Runtime/r0drv/netbsd/sleepqueue-r0drv-netbsd.h b/src/VBox/Runtime/r0drv/netbsd/sleepqueue-r0drv-netbsd.h new file mode 100644 index 00000000..2a153786 --- /dev/null +++ b/src/VBox/Runtime/r0drv/netbsd/sleepqueue-r0drv-netbsd.h @@ -0,0 +1,281 @@ +/* $Id: sleepqueue-r0drv-netbsd.h $ */ +/** @file + * IPRT - NetBSD Ring-0 Driver Helpers for Abstracting Sleep Queues, + */ + +/* + * Copyright (C) 2006-2019 Oracle Corporation + * + * This file is part of VirtualBox Open Source Edition (OSE), as + * available from http://www.virtualbox.org. This file is free software; + * you can redistribute it and/or modify it under the terms of the GNU + * General Public License (GPL) as published by the Free Software + * Foundation, in version 2 as it comes in the "COPYING" file of the + * VirtualBox OSE distribution. VirtualBox OSE is distributed in the + * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL) only, as it comes in the "COPYING.CDDL" file of the + * VirtualBox OSE distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + */ + +#ifndef IPRT_INCLUDED_SRC_r0drv_netbsd_sleepqueue_r0drv_netbsd_h +#define IPRT_INCLUDED_SRC_r0drv_netbsd_sleepqueue_r0drv_netbsd_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include "the-netbsd-kernel.h" + +#include <iprt/asm-math.h> +#include <iprt/err.h> +#include <iprt/time.h> + +static syncobj_t vbox_syncobj = { + SOBJ_SLEEPQ_FIFO, + sleepq_unsleep, + sleepq_changepri, + sleepq_lendpri, + syncobj_noowner, +}; + +/** + * Kernel mode Linux wait state structure. + */ +typedef struct RTR0SEMBSDSLEEP +{ + /** The absolute timeout given as nano seconds since the start of the + * monotonic clock. */ + uint64_t uNsAbsTimeout; + /** The timeout in ticks. Updated after waiting. */ + int iTimeout; + /** Set if it's an indefinite wait. */ + bool fIndefinite; + /** Set if we've already timed out. + * Set by rtR0SemBsdWaitDoIt and read by rtR0SemBsdWaitHasTimedOut. */ + bool fTimedOut; + /** Flag whether the wait was interrupted. */ + bool fInterrupted; + /** flag whether the wait is interruptible or not. */ + bool fInterruptible; + /** Opaque wait channel id. */ + wchan_t wchan; + sleepq_t *sq; + kmutex_t *sq_lock; +} RTR0SEMBSDSLEEP; +/** Pointer to a NetBSD wait state. */ +typedef RTR0SEMBSDSLEEP *PRTR0SEMBSDSLEEP; + + +/** + * Updates the timeout of the NetBSD wait. + * + * @returns RTSEMWAIT_FLAGS_INDEFINITE if the timeout value is too big. + * 0 otherwise + * @param pWait The wait structure. + * @param uTimeout The relative timeout in nanoseconds. + */ +DECLINLINE(void) rtR0SemBsdWaitUpdateTimeout(PRTR0SEMBSDSLEEP pWait) +{ + /* Convert absolute timeout to ticks */ + uint64_t now = RTTimeNanoTS(); + if (now >= pWait->uNsAbsTimeout) { + pWait->iTimeout = 0; + } else { + uint64_t nanos = pWait->uNsAbsTimeout - now; + pWait->iTimeout = hz * nanos / 1000000000; + /* for 1ms wait, wait at least one tick ?? */ + if ((pWait->iTimeout == 0) && (nanos >= 1000000)) { + pWait->iTimeout = 1; + } + } +} + +/** + * Initializes a wait. + * + * The caller MUST check the wait condition BEFORE calling this function or the + * timeout logic will be flawed. + * + * @returns VINF_SUCCESS or VERR_TIMEOUT. + * @param pWait The wait structure. + * @param fFlags The wait flags. + * @param uTimeout The timeout. + * @param pvWaitChan The opaque wait channel. + */ +DECLINLINE(int) rtR0SemBsdWaitInit(PRTR0SEMBSDSLEEP pWait, uint32_t fFlags, uint64_t uTimeout, + void *pvWaitChan) +{ + if (fFlags & RTSEMWAIT_FLAGS_INDEFINITE) { + pWait->fIndefinite = true; + pWait->iTimeout = 0; + pWait->uNsAbsTimeout = 0; + } else { + if (fFlags & RTSEMWAIT_FLAGS_RELATIVE) { + if (fFlags & RTSEMWAIT_FLAGS_MILLISECS) { + pWait->uNsAbsTimeout = uTimeout * 1000000 + RTTimeSystemNanoTS(); + } else { + pWait->uNsAbsTimeout = uTimeout + RTTimeSystemNanoTS(); + } + } else { + if (fFlags & RTSEMWAIT_FLAGS_MILLISECS) { + pWait->uNsAbsTimeout = uTimeout * 1000000; + } else { + pWait->uNsAbsTimeout = uTimeout; + } + } + rtR0SemBsdWaitUpdateTimeout(pWait); + if (pWait->iTimeout == 0) { + return VERR_TIMEOUT; + } + } + + pWait->fTimedOut = false; + /* + * Initialize the wait queue related bits. + */ + pWait->fInterruptible = fFlags & RTSEMWAIT_FLAGS_INTERRUPTIBLE + ? true : false; + pWait->fInterrupted = false; + pWait->wchan = pvWaitChan; + pWait->sq = NULL; + pWait->sq_lock = NULL; + + return VINF_SUCCESS; +} + +/** + * Prepares the next wait. + * + * This must be called before rtR0SemBsdWaitDoIt, and the caller should check + * the exit conditions inbetween the two calls. + * + * @param pWait The wait structure. + */ +DECLINLINE(void) rtR0SemBsdWaitPrepare(PRTR0SEMBSDSLEEP pWait) +{ + pWait->sq = sleeptab_lookup(&sleeptab, pWait->wchan, &pWait->sq_lock); +} + +/** + * Do the actual wait. + * + * @param pWait The wait structure. + */ +DECLINLINE(void) rtR0SemBsdWaitDoIt(PRTR0SEMBSDSLEEP pWait) +{ + sleepq_enter(pWait->sq, curlwp, pWait->sq_lock); + sleepq_enqueue(pWait->sq, pWait->wchan, "VBoxIS", &vbox_syncobj); + + pWait->sq = NULL; + pWait->sq_lock = NULL; + + int error = sleepq_block(pWait->iTimeout, pWait->fInterruptible); + if (error == EWOULDBLOCK) { + if (!pWait->fIndefinite) { + pWait->fTimedOut = true; + } + } else if (error == ERESTART) { + if (pWait->fInterruptible) { + pWait->fInterrupted = true; + } else if (!pWait->fIndefinite) { + rtR0SemBsdWaitUpdateTimeout(pWait); + if (pWait->iTimeout == 0) { + pWait->fTimedOut = true; + } + } + } else if (error == EINTR) { + if (pWait->fInterruptible) { + pWait->fInterrupted = true; + } else if (!pWait->fIndefinite) { + rtR0SemBsdWaitUpdateTimeout(pWait); + if (pWait->iTimeout == 0) { + pWait->fTimedOut = true; + } + } + } else if (error) { + AssertMsgFailed(("sleepq_block -> %d\n", error)); + } +} + + +/** + * Checks if a NetBSD wait was interrupted. + * + * @returns true / false + * @param pWait The wait structure. + * @remarks This shall be called before the first rtR0SemLnxWaitDoIt(). + */ +DECLINLINE(bool) rtR0SemBsdWaitWasInterrupted(PRTR0SEMBSDSLEEP pWait) +{ + return pWait->fInterrupted; +} + + +/** + * Checks if a NetBSD wait has timed out. + * + * @returns true / false + * @param pWait The wait structure. + */ +DECLINLINE(bool) rtR0SemBsdWaitHasTimedOut(PRTR0SEMBSDSLEEP pWait) +{ + return pWait->fTimedOut; +} + + +/** + * Deletes a NetBSD wait. + * + * @param pWait The wait structure. + */ +DECLINLINE(void) rtR0SemBsdWaitDelete(PRTR0SEMBSDSLEEP pWait) +{ + if (pWait->sq_lock != NULL) { + mutex_spin_exit(pWait->sq_lock); + pWait->sq = NULL; + pWait->sq_lock = NULL; + } +} + + +/** + * Signals the wait channel. + * + * @param pvWaitChan The opaque wait channel handle. + */ +DECLINLINE(void) rtR0SemBsdSignal(void *pvWaitChan) +{ + kmutex_t *mp; + sleepq_t *sq = sleeptab_lookup(&sleeptab, pvWaitChan, &mp); + sleepq_wake(sq, pvWaitChan, 1, mp); +} + +/** + * Wakes up all waiters on the wait channel. + * + * @param pvWaitChan The opaque wait channel handle. + */ +DECLINLINE(void) rtR0SemBsdBroadcast(void *pvWaitChan) +{ + kmutex_t *mp; + sleepq_t *sq = sleeptab_lookup(&sleeptab, pvWaitChan, &mp); + sleepq_wake(sq, pvWaitChan, ~0u, mp); +} + +/** + * Gets the max resolution of the timeout machinery. + * + * @returns Resolution specified in nanoseconds. + */ +DECLINLINE(uint32_t) rtR0SemBsdWaitGetResolution(void) +{ + return 1000000000 / hz; /* ns */ +} + +#endif /* !IPRT_INCLUDED_SRC_r0drv_netbsd_sleepqueue_r0drv_netbsd_h */ diff --git a/src/VBox/Runtime/r0drv/netbsd/spinlock-r0drv-netbsd.c b/src/VBox/Runtime/r0drv/netbsd/spinlock-r0drv-netbsd.c new file mode 100644 index 00000000..44c6714d --- /dev/null +++ b/src/VBox/Runtime/r0drv/netbsd/spinlock-r0drv-netbsd.c @@ -0,0 +1,148 @@ +/* $Id: spinlock-r0drv-netbsd.c $ */ +/** @file + * IPRT - Spinlocks, Ring-0 Driver, NetBSD. + */ + +/* + * Copyright (c) 2007 knut st. osmundsen <bird-src-spam@anduin.net> + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "the-netbsd-kernel.h" +#include "internal/iprt.h" + +#include <iprt/spinlock.h> +#include <iprt/errcore.h> +#include <iprt/alloc.h> +#include <iprt/assert.h> +#include <iprt/asm.h> +#include <iprt/asm-amd64-x86.h> +#include <iprt/thread.h> +#include <iprt/mp.h> + +#include "internal/magics.h" + + +/********************************************************************************************************************************* +* Structures and Typedefs * +*********************************************************************************************************************************/ +/** + * Wrapper for the struct mtx type. + */ +typedef struct RTSPINLOCKINTERNAL +{ + /** Spinlock magic value (RTSPINLOCK_MAGIC). */ + uint32_t volatile u32Magic; + /** The spinlock. */ + kmutex_t pSpinLock; + /** Saved interrupt flag. */ + uint32_t volatile fIntSaved; + /** The spinlock creation flags. */ + uint32_t fFlags; +} RTSPINLOCKINTERNAL, *PRTSPINLOCKINTERNAL; + + +RTDECL(int) RTSpinlockCreate(PRTSPINLOCK pSpinlock, uint32_t fFlags, const char *pszName) +{ + RT_ASSERT_PREEMPTIBLE(); + AssertReturn(fFlags == RTSPINLOCK_FLAGS_INTERRUPT_SAFE || fFlags == RTSPINLOCK_FLAGS_INTERRUPT_UNSAFE, VERR_INVALID_PARAMETER); + + /* + * Allocate. + */ + AssertCompile(sizeof(RTSPINLOCKINTERNAL) > sizeof(void *)); + PRTSPINLOCKINTERNAL pThis = (PRTSPINLOCKINTERNAL)RTMemAllocZ(sizeof(*pThis)); + if (!pThis) + return VERR_NO_MEMORY; + + /* + * Initialize & return. + */ + pThis->u32Magic = RTSPINLOCK_MAGIC; + pThis->fFlags = fFlags; + pThis->fIntSaved = 0; + if (fFlags & RTSPINLOCK_FLAGS_INTERRUPT_SAFE) { + mutex_init(&pThis->pSpinLock, MUTEX_DEFAULT, IPL_BIO); + } else { + mutex_init(&pThis->pSpinLock, MUTEX_DEFAULT, IPL_NONE); + } + + *pSpinlock = pThis; + return VINF_SUCCESS; +} + + +RTDECL(int) RTSpinlockDestroy(RTSPINLOCK Spinlock) +{ + /* + * Validate input. + */ + RT_ASSERT_INTS_ON(); + PRTSPINLOCKINTERNAL pThis = (PRTSPINLOCKINTERNAL)Spinlock; + if (!pThis) + return VERR_INVALID_PARAMETER; + AssertMsgReturn(pThis->u32Magic == RTSPINLOCK_MAGIC, + ("Invalid spinlock %p magic=%#x\n", pThis, pThis->u32Magic), + VERR_INVALID_PARAMETER); + + /* + * Make the lock invalid and release the memory. + */ + ASMAtomicIncU32(&pThis->u32Magic); + mutex_destroy(&pThis->pSpinLock); + RTMemFree(pThis); + return VINF_SUCCESS; +} + + +RTDECL(void) RTSpinlockAcquire(RTSPINLOCK Spinlock) +{ + PRTSPINLOCKINTERNAL pThis = (PRTSPINLOCKINTERNAL)Spinlock; + RT_ASSERT_PREEMPT_CPUID_VAR(); + AssertPtr(pThis); + Assert(pThis->u32Magic == RTSPINLOCK_MAGIC); + + if (pThis->fFlags & RTSPINLOCK_FLAGS_INTERRUPT_SAFE) { + mutex_spin_enter(&pThis->pSpinLock); + } else { + mutex_enter(&pThis->pSpinLock); + } +} + + +RTDECL(void) RTSpinlockRelease(RTSPINLOCK Spinlock) +{ + PRTSPINLOCKINTERNAL pThis = (PRTSPINLOCKINTERNAL)Spinlock; + AssertPtr(pThis); + Assert(pThis->u32Magic == RTSPINLOCK_MAGIC); + + if (pThis->fFlags & RTSPINLOCK_FLAGS_INTERRUPT_SAFE) { + mutex_spin_exit(&pThis->pSpinLock); + } else { + mutex_exit(&pThis->pSpinLock); + } +} diff --git a/src/VBox/Runtime/r0drv/netbsd/the-netbsd-kernel.h b/src/VBox/Runtime/r0drv/netbsd/the-netbsd-kernel.h new file mode 100644 index 00000000..8bc61190 --- /dev/null +++ b/src/VBox/Runtime/r0drv/netbsd/the-netbsd-kernel.h @@ -0,0 +1,75 @@ +/* $Id: the-netbsd-kernel.h $ */ +/** @file + * IPRT - Ring-0 Driver, The NetBSD Kernel Headers. + */ + +/* + * Copyright (c) 2007 knut st. osmundsen <bird-src-spam@anduin.net> + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef IPRT_INCLUDED_SRC_r0drv_netbsd_the_netbsd_kernel_h +#define IPRT_INCLUDED_SRC_r0drv_netbsd_the_netbsd_kernel_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include <iprt/types.h> + +/* Deal with conflicts first. */ +#include <sys/param.h> +#undef PVM +#include <sys/bus.h> +#include <sys/types.h> +#include <sys/errno.h> +#include <sys/kernel.h> +#include <sys/uio.h> +#include <sys/systm.h> +#include <sys/malloc.h> +#include <sys/proc.h> +#include <sys/syslimits.h> +#include <sys/sleepq.h> +#include <sys/unistd.h> +#include <sys/kthread.h> +#include <sys/lock.h> +#include <sys/mutex.h> +#include <sys/sched.h> +#include <sys/callout.h> +#include <sys/rwlock.h> +#include <sys/kmem.h> +#include <sys/cpu.h> +#include <sys/vmmeter.h> /* cnt */ +#include <sys/resourcevar.h> +#include <uvm/uvm.h> +#include <uvm/uvm_extern.h> +#include <uvm/uvm_page.h> +#include <machine/cpu.h> + +/** + * Check whether we can use kmem_alloc_prot. + */ +#if 0 /** @todo Not available yet. */ +# define USE_KMEM_ALLOC_PROT +#endif + +#endif /* !IPRT_INCLUDED_SRC_r0drv_netbsd_the_netbsd_kernel_h */ diff --git a/src/VBox/Runtime/r0drv/netbsd/thread-r0drv-netbsd.c b/src/VBox/Runtime/r0drv/netbsd/thread-r0drv-netbsd.c new file mode 100644 index 00000000..17f07e8a --- /dev/null +++ b/src/VBox/Runtime/r0drv/netbsd/thread-r0drv-netbsd.c @@ -0,0 +1,181 @@ +/* $Id: thread-r0drv-netbsd.c $ */ +/** @file + * IPRT - Threads (Part 1), Ring-0 Driver, NetBSD. + */ + +/* + * Copyright (C) 2007-2019 Oracle Corporation + * + * This file is part of VirtualBox Open Source Edition (OSE), as + * available from http://www.virtualbox.org. This file is free software; + * you can redistribute it and/or modify it under the terms of the GNU + * General Public License (GPL) as published by the Free Software + * Foundation, in version 2 as it comes in the "COPYING" file of the + * VirtualBox OSE distribution. VirtualBox OSE is distributed in the + * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL) only, as it comes in the "COPYING.CDDL" file of the + * VirtualBox OSE distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "the-netbsd-kernel.h" +#include "internal/iprt.h" +#include <iprt/thread.h> + +#include <iprt/asm.h> +#include <iprt/asm-amd64-x86.h> +#include <iprt/assert.h> +#include <iprt/err.h> +#include <iprt/mp.h> +#include "internal/thread.h" + + +RTDECL(RTNATIVETHREAD) RTThreadNativeSelf(void) +{ + return (RTNATIVETHREAD)curlwp; +} + + +static int rtR0ThreadNbsdSleepCommon(RTMSINTERVAL cMillies) +{ + int rc; + int cTicks; + + /* + * 0 ms sleep -> yield. + */ + if (!cMillies) + { + RTThreadYield(); + return VINF_SUCCESS; + } + + /* + * Translate milliseconds into ticks and go to sleep. + */ + if (cMillies != RT_INDEFINITE_WAIT) + { + if (hz == 1000) + cTicks = cMillies; + else if (hz == 100) + cTicks = cMillies / 10; + else + { + int64_t cTicks64 = ((uint64_t)cMillies * hz) / 1000; + cTicks = (int)cTicks64; + if (cTicks != cTicks64) + cTicks = INT_MAX; + } + } + else + cTicks = 0; /* requires giant lock! */ + + rc = tsleep((void *)RTThreadSleep, + PZERO | PCATCH, + "iprtsl", /* max 6 chars */ + cTicks); + switch (rc) + { + case 0: + return VINF_SUCCESS; + case EWOULDBLOCK: + return VERR_TIMEOUT; + case EINTR: + case ERESTART: + return VERR_INTERRUPTED; + default: + AssertMsgFailed(("%d\n", rc)); + return VERR_NO_TRANSLATION; + } +} + + +RTDECL(int) RTThreadSleep(RTMSINTERVAL cMillies) +{ + return rtR0ThreadNbsdSleepCommon(cMillies); +} + + +RTDECL(int) RTThreadSleepNoLog(RTMSINTERVAL cMillies) +{ + return rtR0ThreadNbsdSleepCommon(cMillies); +} + + +RTDECL(bool) RTThreadYield(void) +{ + yield(); + return true; +} + + +RTDECL(bool) RTThreadPreemptIsEnabled(RTTHREAD hThread) +{ + Assert(hThread == NIL_RTTHREAD); + + return curlwp->l_dopreempt == 0 + && ASMIntAreEnabled(); /** @todo is there a native netbsd function/macro for this? */ +} + + +RTDECL(bool) RTThreadPreemptIsPending(RTTHREAD hThread) +{ + Assert(hThread == NIL_RTTHREAD); + + return curlwp->l_dopreempt; +} + + +RTDECL(bool) RTThreadPreemptIsPendingTrusty(void) +{ + /* yes, RTThreadPreemptIsPending is reliable. */ + return true; +} + + +RTDECL(bool) RTThreadPreemptIsPossible(void) +{ + /* yes, kernel preemption is possible. */ + return true; +} + + +RTDECL(void) RTThreadPreemptDisable(PRTTHREADPREEMPTSTATE pState) +{ + AssertPtr(pState); + + curlwp->l_nopreempt++; + __insn_barrier(); +} + + +RTDECL(void) RTThreadPreemptRestore(PRTTHREADPREEMPTSTATE pState) +{ + AssertPtr(pState); + __insn_barrier(); + if (--curlwp->l_nopreempt != 0) + return; + __insn_barrier(); + if (__predict_false(curlwp->l_dopreempt)) + kpreempt(0); + __insn_barrier(); +} + + +RTDECL(bool) RTThreadIsInInterrupt(RTTHREAD hThread) +{ + Assert(hThread == NIL_RTTHREAD); NOREF(hThread); + /** @todo NetBSD: Implement RTThreadIsInInterrupt. Required for guest + * additions! */ + return !ASMIntAreEnabled(); +} diff --git a/src/VBox/Runtime/r0drv/netbsd/thread2-r0drv-netbsd.c b/src/VBox/Runtime/r0drv/netbsd/thread2-r0drv-netbsd.c new file mode 100644 index 00000000..f7faaae7 --- /dev/null +++ b/src/VBox/Runtime/r0drv/netbsd/thread2-r0drv-netbsd.c @@ -0,0 +1,135 @@ +/* $Id: thread2-r0drv-netbsd.c $ */ +/** @file + * IPRT - Threads (Part 2), Ring-0 Driver, NetBSD. + */ + +/* + * Copyright (c) 2007 knut st. osmundsen <bird-src-spam@anduin.net> + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "the-netbsd-kernel.h" + +#include <iprt/thread.h> +#include <iprt/errcore.h> +#include <iprt/assert.h> + +#include "internal/thread.h" + + +DECLHIDDEN(int) rtThreadNativeInit(void) +{ + return VINF_SUCCESS; +} + + +RTDECL(RTTHREAD) RTThreadSelf(void) +{ + return rtThreadGetByNative(RTThreadNativeSelf()); +} + + +DECLHIDDEN(int) rtThreadNativeSetPriority(PRTTHREADINT pThread, RTTHREADTYPE enmType) +{ + int iPriority; + + switch (enmType) + { + case RTTHREADTYPE_INFREQUENT_POLLER: iPriority = PZERO + 8; break; + case RTTHREADTYPE_EMULATION: iPriority = PZERO + 4; break; + case RTTHREADTYPE_DEFAULT: iPriority = PZERO; break; + case RTTHREADTYPE_MSG_PUMP: iPriority = PZERO - 4; break; + case RTTHREADTYPE_IO: iPriority = PRIBIO; break; + case RTTHREADTYPE_TIMER: iPriority = PSWP; break; + default: + AssertMsgFailed(("enmType=%d\n", enmType)); + return VERR_INVALID_PARAMETER; + } + + lwp_lock(curlwp); + lwp_changepri(curlwp, iPriority); + lwp_unlock(curlwp); + + return VINF_SUCCESS; +} + + +DECLHIDDEN(int) rtThreadNativeAdopt(PRTTHREADINT pThread) +{ + NOREF(pThread); + /* There is nothing special that needs doing here, but the + user really better know what he's cooking. */ + return VINF_SUCCESS; +} + + +DECLHIDDEN(void) rtThreadNativeWaitKludge(PRTTHREADINT pThread) +{ + /** @todo fix RTThreadWait/RTR0Term race on netbsd. */ + RTThreadSleep(1); +} + + +DECLHIDDEN(void) rtThreadNativeDestroy(PRTTHREADINT pThread) +{ + NOREF(pThread); +} + + +/** + * Native thread main function. + * + * @param pvThreadInt The thread structure. + */ +static void rtThreadNativeMain(void *pvThreadInt) +{ + const struct lwp *Self = curlwp; + PRTTHREADINT pThreadInt = (PRTTHREADINT)pvThreadInt; + int rc; + + rc = rtThreadMain(pThreadInt, (RTNATIVETHREAD)Self, &pThreadInt->szName[0]); + + kthread_exit(rc); +} + + +DECLHIDDEN(int) rtThreadNativeCreate(PRTTHREADINT pThreadInt, PRTNATIVETHREAD pNativeThread) +{ + int rc; + struct lwp *l; + + rc = kthread_create(PRI_NONE, 0, NULL, rtThreadNativeMain, (void *)pThreadInt, &l, "%s", pThreadInt->szName); + + if (!rc) + { + *pNativeThread = (RTNATIVETHREAD)l; + rc = VINF_SUCCESS; + } + else + rc = RTErrConvertFromErrno(rc); + return rc; +} diff --git a/src/VBox/Runtime/r0drv/netbsd/time-r0drv-netbsd.c b/src/VBox/Runtime/r0drv/netbsd/time-r0drv-netbsd.c new file mode 100644 index 00000000..162fceb5 --- /dev/null +++ b/src/VBox/Runtime/r0drv/netbsd/time-r0drv-netbsd.c @@ -0,0 +1,73 @@ +/* $Id: time-r0drv-netbsd.c $ */ +/** @file + * IPRT - Time, Ring-0 Driver, NetBSD. + */ + +/* + * Copyright (c) 2007 knut st. osmundsen <bird-src-spam@anduin.net> + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "the-netbsd-kernel.h" +#define RTTIME_INCL_TIMESPEC + +#include <iprt/time.h> + + +RTDECL(uint64_t) RTTimeNanoTS(void) +{ + struct timespec tsp; + nanotime(&tsp); + return tsp.tv_sec * RT_NS_1SEC_64 + + tsp.tv_nsec; +} + + +RTDECL(uint64_t) RTTimeMilliTS(void) +{ + return RTTimeNanoTS() / RT_NS_1MS; +} + + +RTDECL(uint64_t) RTTimeSystemNanoTS(void) +{ + return RTTimeNanoTS(); +} + + +RTDECL(uint64_t) RTTimeSystemMilliTS(void) +{ + return RTTimeMilliTS(); +} + + +RTDECL(PRTTIMESPEC) RTTimeNow(PRTTIMESPEC pTime) +{ + struct timespec tsp; + nanotime(&tsp); + return RTTimeSpecSetTimespec(pTime, &tsp); +} |