VirtualBox

source: vbox/trunk/src/VBox/Additions/common/VBoxGuest/VBoxGuest-haiku.c

Last change on this file was 100267, checked in by vboxsync, 10 months ago

Additions: Make the R0 physical heap configurable to allow for allocations >= 4GiB if supported by the VBox device (the MMIO request path is available), add support for the MMIO request path required for ARM, bugref:10457

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 17.0 KB
Line 
1/* $Id: VBoxGuest-haiku.c 100267 2023-06-23 14:57:53Z vboxsync $ */
2/** @file
3 * VBoxGuest kernel module, Haiku Guest Additions, implementation.
4 */
5
6/*
7 * Copyright (C) 2012-2023 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * The contents of this file may alternatively be used under the terms
26 * of the Common Development and Distribution License Version 1.0
27 * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
28 * in the VirtualBox distribution, in which case the provisions of the
29 * CDDL are applicable instead of those of the GPL.
30 *
31 * You may elect to license modified versions of this file under the
32 * terms and conditions of either the GPL or the CDDL or both.
33 *
34 * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
35 */
36
37/*
38 * This code is based on:
39 *
40 * VirtualBox Guest Additions for Haiku.
41 * Copyright (c) 2011 Mike Smith <mike@scgtrp.net>
42 * François Revol <revol@free.fr>
43 *
44 * Permission is hereby granted, free of charge, to any person
45 * obtaining a copy of this software and associated documentation
46 * files (the "Software"), to deal in the Software without
47 * restriction, including without limitation the rights to use,
48 * copy, modify, merge, publish, distribute, sublicense, and/or sell
49 * copies of the Software, and to permit persons to whom the
50 * Software is furnished to do so, subject to the following
51 * conditions:
52 *
53 * The above copyright notice and this permission notice shall be
54 * included in all copies or substantial portions of the Software.
55 *
56 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
57 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
58 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
59 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
60 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
61 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
62 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
63 * OTHER DEALINGS IN THE SOFTWARE.
64 */
65
66
67/*********************************************************************************************************************************
68* Header Files *
69*********************************************************************************************************************************/
70#define IN_VBOXGUEST
71#include <sys/param.h>
72#include <sys/types.h>
73#include <sys/uio.h>
74#include <OS.h>
75#include <Drivers.h>
76#include <KernelExport.h>
77#include <PCI.h>
78
79#include "VBoxGuest-haiku.h"
80#include "VBoxGuestInternal.h"
81#include <VBox/log.h>
82#include <iprt/assert.h>
83#include <iprt/initterm.h>
84#include <iprt/process.h>
85#include <iprt/mem.h>
86#include <iprt/memobj.h>
87#include <iprt/asm.h>
88#include <iprt/timer.h>
89#include <iprt/heap.h>
90
91
92/*********************************************************************************************************************************
93* Defined Constants And Macros *
94*********************************************************************************************************************************/
95#define MODULE_NAME VBOXGUEST_MODULE_NAME
96
97
98/*********************************************************************************************************************************
99* Internal Functions *
100*********************************************************************************************************************************/
101/*
102 * IRQ related functions.
103 */
104static void vgdrvHaikuRemoveIRQ(void *pvState);
105static int vgdrvHaikuAddIRQ(void *pvState);
106static int32 vgdrvHaikuISR(void *pvState);
107
108
109/*********************************************************************************************************************************
110* Global Variables *
111*********************************************************************************************************************************/
112static status_t std_ops(int32 op, ...);
113
114static RTSPINLOCK g_Spinlock = NIL_RTSPINLOCK;
115
116int32 api_version = B_CUR_DRIVER_API_VERSION;
117
118/** List of cloned device. Managed by the kernel. */
119//static struct clonedevs *g_pvgdrvHaikuClones;
120/** The dev_clone event handler tag. */
121//static eventhandler_tag g_vgdrvHaikuEHTag;
122/** selinfo structure used for polling. */
123//static struct selinfo g_SelInfo;
124/** PCI Bus Manager Module */
125static pci_module_info *gPCI;
126
127static struct vboxguest_module_info g_VBoxGuest =
128{
129 {
130 MODULE_NAME,
131 0,
132 std_ops
133 },
134 { 0 },
135 { 0 },
136 0,
137 RTLogBackdoorPrintf,
138 RTLogBackdoorPrintfV,
139 RTLogSetDefaultInstanceThread,
140 RTMemAllocExTag,
141 RTMemContAlloc,
142 RTMemContFree,
143 RTMemFreeEx,
144 RTMpIsCpuPossible,
145 RTMpNotificationDeregister,
146 RTMpNotificationRegister,
147 RTMpOnAll,
148 RTMpOnOthers,
149 RTMpOnSpecific,
150 RTPowerNotificationDeregister,
151 RTPowerNotificationRegister,
152 RTPowerSignalEvent,
153 RTR0AssertPanicSystem,
154 RTR0Init,
155 RTR0MemObjAddress,
156 RTR0MemObjAddressR3,
157 RTR0MemObjAllocContTag,
158 RTR0MemObjAllocLowTag,
159 RTR0MemObjAllocPageTag,
160 RTR0MemObjAllocPhysExTag,
161 RTR0MemObjAllocPhysNCTag,
162 RTR0MemObjAllocPhysTag,
163 RTR0MemObjEnterPhysTag,
164 RTR0MemObjFree,
165 RTR0MemObjGetPagePhysAddr,
166 RTR0MemObjIsMapping,
167 RTR0MemObjLockKernelTag,
168 RTR0MemObjLockUserTag,
169 RTR0MemObjMapKernelExTag,
170 RTR0MemObjMapKernelTag,
171 RTR0MemObjMapUserTag,
172 RTR0MemObjProtect,
173 RTR0MemObjReserveKernelTag,
174 RTR0MemObjReserveUserTag,
175 RTR0MemObjSize,
176 RTR0ProcHandleSelf,
177 RTR0Term,
178 RTR0TermForced,
179 RTProcSelf,
180 RTSemEventGetResolution,
181 RTSemEventMultiGetResolution,
182 RTSemEventMultiWaitEx,
183 RTSemEventMultiWaitExDebug,
184 RTSemEventWaitEx,
185 RTSemEventWaitExDebug,
186 RTThreadIsInInterrupt,
187 RTThreadPreemptDisable,
188 RTThreadPreemptIsEnabled,
189 RTThreadPreemptIsPending,
190 RTThreadPreemptIsPendingTrusty,
191 RTThreadPreemptIsPossible,
192 RTThreadPreemptRestore,
193 RTTimerGetSystemGranularity,
194 RTTimerReleaseSystemGranularity,
195 RTTimerRequestSystemGranularity,
196 RTSpinlockAcquire,
197 RTSpinlockRelease,
198 RTMemTmpAllocTag,
199 RTMemTmpFree,
200 RTLogDefaultInstance,
201 RTLogDefaultInstanceEx,
202 RTLogRelGetDefaultInstance,
203 RTLogRelGetDefaultInstanceEx,
204 RTErrConvertToErrno,
205 VGDrvCommonIoCtl,
206 VGDrvCommonCreateUserSession,
207 VGDrvCommonCloseSession,
208 VBoxGuestIDCOpen,
209 VBoxGuestIDCClose,
210 VBoxGuestIDCCall,
211 RTAssertMsg1Weak,
212 RTAssertMsg2Weak,
213 RTAssertMsg2WeakV,
214 RTAssertShouldPanic,
215 RTSemFastMutexCreate,
216 RTSemFastMutexDestroy,
217 RTSemFastMutexRelease,
218 RTSemFastMutexRequest,
219 RTSemMutexCreate,
220 RTSemMutexDestroy,
221 RTSemMutexRelease,
222 RTSemMutexRequest,
223 RTHeapSimpleRelocate,
224 RTHeapOffsetInit,
225 RTHeapSimpleInit,
226 RTHeapOffsetAlloc,
227 RTHeapSimpleAlloc,
228 RTHeapOffsetFree,
229 RTHeapSimpleFree
230};
231
232#if 0
233/**
234 * DEVFS event handler.
235 */
236static void vgdrvHaikuClone(void *pvArg, struct ucred *pCred, char *pszName, int cchName, struct cdev **ppDev)
237{
238 int iUnit;
239 int rc;
240
241 Log(("vgdrvHaikuClone: pszName=%s ppDev=%p\n", pszName, ppDev));
242
243 /*
244 * One device node per user, si_drv1 points to the session.
245 * /dev/vboxguest<N> where N = {0...255}.
246 */
247 if (!ppDev)
248 return;
249 if (strcmp(pszName, "vboxguest") == 0)
250 iUnit = -1;
251 else if (dev_stdclone(pszName, NULL, "vboxguest", &iUnit) != 1)
252 return;
253 if (iUnit >= 256)
254 {
255 Log(("vgdrvHaikuClone: iUnit=%d >= 256 - rejected\n", iUnit));
256 return;
257 }
258
259 Log(("vgdrvHaikuClone: pszName=%s iUnit=%d\n", pszName, iUnit));
260
261 rc = clone_create(&g_pvgdrvHaikuClones, &g_vgdrvHaikuDeviceHooks, &iUnit, ppDev, 0);
262 Log(("vgdrvHaikuClone: clone_create -> %d; iUnit=%d\n", rc, iUnit));
263 if (rc)
264 {
265 *ppDev = make_dev(&g_vgdrvHaikuDeviceHooks,
266 iUnit,
267 UID_ROOT,
268 GID_WHEEL,
269 0644,
270 "vboxguest%d", iUnit);
271 if (*ppDev)
272 {
273 dev_ref(*ppDev);
274 (*ppDev)->si_flags |= SI_CHEAPCLONE;
275 Log(("vgdrvHaikuClone: Created *ppDev=%p iUnit=%d si_drv1=%p si_drv2=%p\n",
276 *ppDev, iUnit, (*ppDev)->si_drv1, (*ppDev)->si_drv2));
277 (*ppDev)->si_drv1 = (*ppDev)->si_drv2 = NULL;
278 }
279 else
280 Log(("vgdrvHaikuClone: make_dev iUnit=%d failed\n", iUnit));
281 }
282 else
283 Log(("vgdrvHaikuClone: Existing *ppDev=%p iUnit=%d si_drv1=%p si_drv2=%p\n",
284 *ppDev, iUnit, (*ppDev)->si_drv1, (*ppDev)->si_drv2));
285}
286#endif
287
288
289static status_t vgdrvHaikuDetach(void)
290{
291 struct VBoxGuestDeviceState *pState = &sState;
292
293 if (cUsers > 0)
294 return EBUSY;
295
296 /*
297 * Reverse what we did in vgdrvHaikuAttach.
298 */
299 vgdrvHaikuRemoveIRQ(pState);
300
301 if (pState->iVMMDevMemAreaId)
302 delete_area(pState->iVMMDevMemAreaId);
303
304 VGDrvCommonDeleteDevExt(&g_DevExt);
305
306#ifdef DO_LOG
307 RTLogDestroy(RTLogRelSetDefaultInstance(NULL));
308 RTLogSetDefaultInstance(NULL);
309// RTLogDestroy(RTLogSetDefaultInstance(NULL));
310#endif
311
312 RTSpinlockDestroy(g_Spinlock);
313 g_Spinlock = NIL_RTSPINLOCK;
314
315 RTR0Term();
316 return B_OK;
317}
318
319
320/**
321 * Interrupt service routine.
322 *
323 * @returns Whether the interrupt was from VMMDev.
324 * @param pvState Opaque pointer to the device state.
325 */
326static int32 vgdrvHaikuISR(void *pvState)
327{
328 LogFlow((MODULE_NAME ":vgdrvHaikuISR pvState=%p\n", pvState));
329
330 bool fOurIRQ = VGDrvCommonISR(&g_DevExt);
331 if (fOurIRQ)
332 return B_HANDLED_INTERRUPT;
333 return B_UNHANDLED_INTERRUPT;
334}
335
336
337void VGDrvNativeISRMousePollEvent(PVBOXGUESTDEVEXT pDevExt)
338{
339 LogFlow(("VGDrvNativeISRMousePollEvent:\n"));
340
341 status_t err = B_OK;
342 //dprintf(MODULE_NAME ": isr mouse\n");
343
344 /*
345 * Wake up poll waiters.
346 */
347 //selwakeup(&g_SelInfo);
348 //XXX:notify_select_event();
349 RTSpinlockAcquire(g_Spinlock);
350
351 if (sState.selectSync)
352 {
353 //dprintf(MODULE_NAME ": isr mouse: notify\n");
354 notify_select_event(sState.selectSync, sState.selectEvent);
355 sState.selectEvent = (uint8_t)0;
356 sState.selectRef = (uint32_t)0;
357 sState.selectSync = NULL;
358 }
359 else
360 err = B_ERROR;
361
362 RTSpinlockRelease(g_Spinlock);
363}
364
365
366bool VGDrvNativeProcessOption(PVBOXGUESTDEVEXT pDevExt, const char *pszName, const char *pszValue)
367{
368 RT_NOREF(pDevExt); RT_NOREF(pszName); RT_NOREF(pszValue);
369 return false;
370}
371
372
373/**
374 * Sets IRQ for VMMDev.
375 *
376 * @returns Haiku error code.
377 * @param pvState Pointer to the state info structure.
378 */
379static int vgdrvHaikuAddIRQ(void *pvState)
380{
381 status_t err;
382 struct VBoxGuestDeviceState *pState = (struct VBoxGuestDeviceState *)pvState;
383
384 AssertReturn(pState, VERR_INVALID_PARAMETER);
385
386 err = install_io_interrupt_handler(pState->iIrqResId, vgdrvHaikuISR, pState, 0);
387 if (err == B_OK)
388 return VINF_SUCCESS;
389 return VERR_DEV_IO_ERROR;
390}
391
392
393/**
394 * Removes IRQ for VMMDev.
395 *
396 * @param pvState Opaque pointer to the state info structure.
397 */
398static void vgdrvHaikuRemoveIRQ(void *pvState)
399{
400 struct VBoxGuestDeviceState *pState = (struct VBoxGuestDeviceState *)pvState;
401 AssertPtr(pState);
402
403 remove_io_interrupt_handler(pState->iIrqResId, vgdrvHaikuISR, pState);
404}
405
406
407static status_t vgdrvHaikuAttach(const pci_info *pDevice)
408{
409 status_t status;
410 int rc;
411 int iResId;
412 struct VBoxGuestDeviceState *pState = &sState;
413 static const char *const s_apszGroups[] = VBOX_LOGGROUP_NAMES;
414 PRTLOGGER pRelLogger;
415
416 AssertReturn(pDevice, B_BAD_VALUE);
417
418 cUsers = 0;
419
420 /*
421 * Initialize IPRT R0 driver, which internally calls OS-specific r0 init.
422 */
423 rc = RTR0Init(0);
424 if (RT_FAILURE(rc))
425 {
426 dprintf(MODULE_NAME ": RTR0Init failed: %d\n", rc);
427 return ENXIO;
428 }
429
430 rc = RTSpinlockCreate(&g_Spinlock, RTSPINLOCK_FLAGS_INTERRUPT_SAFE, "vgdrvHaiku");
431 if (RT_FAILURE(rc))
432 {
433 LogRel(("vgdrvHaikuAttach: RTSpinlock create failed. rc=%Rrc\n", rc));
434 return ENXIO;
435 }
436
437#ifdef DO_LOG
438 /*
439 * Create the release log.
440 * (We do that here instead of common code because we want to log
441 * early failures using the LogRel macro.)
442 */
443 rc = RTLogCreate(&pRelLogger, 0 | RTLOGFLAGS_PREFIX_THREAD /* fFlags */, "all",
444 "VBOX_RELEASE_LOG", RT_ELEMENTS(s_apszGroups), s_apszGroups,
445 RTLOGDEST_STDOUT | RTLOGDEST_DEBUGGER | RTLOGDEST_USER, NULL);
446 dprintf(MODULE_NAME ": RTLogCreate: %d\n", rc);
447 if (RT_SUCCESS(rc))
448 {
449 //RTLogGroupSettings(pRelLogger, g_szLogGrp);
450 //RTLogFlags(pRelLogger, g_szLogFlags);
451 //RTLogDestinations(pRelLogger, "/var/log/vboxguest.log");
452 RTLogRelSetDefaultInstance(pRelLogger);
453 RTLogSetDefaultInstance(pRelLogger); //XXX
454 }
455#endif
456
457 /*
458 * Allocate I/O port resource.
459 */
460 pState->uIOPortBase = pDevice->u.h0.base_registers[0];
461 /** @todo check flags for IO? */
462 if (pState->uIOPortBase)
463 {
464 /*
465 * Map the MMIO region.
466 */
467 uint32 phys = pDevice->u.h0.base_registers[1];
468 /** @todo Check flags for mem? */
469 pState->VMMDevMemSize = pDevice->u.h0.base_register_sizes[1];
470 pState->iVMMDevMemAreaId = map_physical_memory("VirtualBox Guest MMIO", phys, pState->VMMDevMemSize,
471 B_ANY_KERNEL_BLOCK_ADDRESS, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA,
472 &pState->pMMIOBase);
473 if (pState->iVMMDevMemAreaId > 0 && pState->pMMIOBase)
474 {
475 /*
476 * Call the common device extension initializer.
477 */
478 rc = VGDrvCommonInitDevExt(&g_DevExt, pState->uIOPortBase, NULL /*pvMmioReq*/,
479 pState->pMMIOBase, pState->VMMDevMemSize,
480#if ARCH_BITS == 64
481 VBOXOSTYPE_Haiku_x64,
482#else
483 VBOXOSTYPE_Haiku,
484#endif
485 VMMDEV_EVENT_MOUSE_POSITION_CHANGED);
486 if (RT_SUCCESS(rc))
487 {
488 /*
489 * Add IRQ of VMMDev.
490 */
491 pState->iIrqResId = pDevice->u.h0.interrupt_line;
492 rc = vgdrvHaikuAddIRQ(pState);
493 if (RT_SUCCESS(rc))
494 {
495 /*
496 * Read host configuration.
497 */
498 VGDrvCommonProcessOptionsFromHost(&g_DevExt);
499
500 LogRel((MODULE_NAME ": loaded successfully\n"));
501 return B_OK;
502 }
503
504 LogRel((MODULE_NAME ": VGDrvCommonInitDevExt failed.\n"));
505 VGDrvCommonDeleteDevExt(&g_DevExt);
506 }
507 else
508 LogRel((MODULE_NAME ": vgdrvHaikuAddIRQ failed.\n"));
509 }
510 else
511 LogRel((MODULE_NAME ": MMIO region setup failed.\n"));
512 }
513 else
514 LogRel((MODULE_NAME ": IOport setup failed.\n"));
515
516 RTR0Term();
517 return ENXIO;
518}
519
520
521static status_t vgdrvHaikuProbe(pci_info *pDevice)
522{
523 if ( pDevice->vendor_id == VMMDEV_VENDORID
524 && pDevice->device_id == VMMDEV_DEVICEID)
525 return B_OK;
526
527 return ENXIO;
528}
529
530
531status_t init_module(void)
532{
533 status_t err = B_ENTRY_NOT_FOUND;
534 pci_info info;
535 int ix = 0;
536
537 err = get_module(B_PCI_MODULE_NAME, (module_info **)&gPCI);
538 if (err != B_OK)
539 return err;
540
541 while ((*gPCI->get_nth_pci_info)(ix++, &info) == B_OK)
542 {
543 if (vgdrvHaikuProbe(&info) == 0)
544 {
545 /* We found it */
546 err = vgdrvHaikuAttach(&info);
547 return err;
548 }
549 }
550
551 return B_ENTRY_NOT_FOUND;
552}
553
554
555void uninit_module(void)
556{
557 vgdrvHaikuDetach();
558 put_module(B_PCI_MODULE_NAME);
559}
560
561
562static status_t std_ops(int32 op, ...)
563{
564 switch (op)
565 {
566 case B_MODULE_INIT:
567 return init_module();
568
569 case B_MODULE_UNINIT:
570 {
571 uninit_module();
572 return B_OK;
573 }
574
575 default:
576 return B_ERROR;
577 }
578}
579
580
581_EXPORT module_info *modules[] =
582{
583 (module_info *)&g_VBoxGuest,
584 NULL
585};
586
587/* Common code that depend on g_DevExt. */
588#include "VBoxGuestIDC-unix.c.h"
589
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use