summaryrefslogtreecommitdiffstats
path: root/src/VBox/Runtime/r0drv/netbsd
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-06 03:01:46 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-06 03:01:46 +0000
commitf8fe689a81f906d1b91bb3220acde2a4ecb14c5b (patch)
tree26484e9d7e2c67806c2d1760196ff01aaa858e8c /src/VBox/Runtime/r0drv/netbsd
parentInitial commit. (diff)
downloadvirtualbox-f8fe689a81f906d1b91bb3220acde2a4ecb14c5b.tar.xz
virtualbox-f8fe689a81f906d1b91bb3220acde2a4ecb14c5b.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')
-rw-r--r--src/VBox/Runtime/r0drv/netbsd/Makefile.kup0
-rw-r--r--src/VBox/Runtime/r0drv/netbsd/RTLogWriteStdOut-r0drv-netbsd.c39
-rw-r--r--src/VBox/Runtime/r0drv/netbsd/alloc-r0drv-netbsd.c165
-rw-r--r--src/VBox/Runtime/r0drv/netbsd/assert-r0drv-netbsd.c63
-rw-r--r--src/VBox/Runtime/r0drv/netbsd/initterm-r0drv-netbsd.c52
-rw-r--r--src/VBox/Runtime/r0drv/netbsd/memobj-r0drv-netbsd.c558
-rw-r--r--src/VBox/Runtime/r0drv/netbsd/memuserkernel-r0drv-netbsd.c82
-rw-r--r--src/VBox/Runtime/r0drv/netbsd/mp-r0drv-netbsd.c43
-rw-r--r--src/VBox/Runtime/r0drv/netbsd/process-r0drv-netbsd.c51
-rw-r--r--src/VBox/Runtime/r0drv/netbsd/semevent-r0drv-netbsd.c255
-rw-r--r--src/VBox/Runtime/r0drv/netbsd/semeventmulti-r0drv-netbsd.c319
-rw-r--r--src/VBox/Runtime/r0drv/netbsd/semfastmutex-r0drv-netbsd.c114
-rw-r--r--src/VBox/Runtime/r0drv/netbsd/semmutex-r0drv-netbsd.c218
-rw-r--r--src/VBox/Runtime/r0drv/netbsd/sleepqueue-r0drv-netbsd.h281
-rw-r--r--src/VBox/Runtime/r0drv/netbsd/spinlock-r0drv-netbsd.c148
-rw-r--r--src/VBox/Runtime/r0drv/netbsd/the-netbsd-kernel.h75
-rw-r--r--src/VBox/Runtime/r0drv/netbsd/thread-r0drv-netbsd.c181
-rw-r--r--src/VBox/Runtime/r0drv/netbsd/thread2-r0drv-netbsd.c135
-rw-r--r--src/VBox/Runtime/r0drv/netbsd/time-r0drv-netbsd.c73
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);
+}