vbox: add network support

- support e1000 model by default and add support for pcnet model
- add Genode xml config option to enable network models

Fixes #1201
This commit is contained in:
Alexander Boettcher 2014-07-02 17:35:56 +02:00 committed by Norman Feske
parent 46124546f0
commit c5380674df
17 changed files with 733 additions and 23 deletions

View File

@ -37,6 +37,8 @@ VBOX_CC_OPT += -DUSE_SDL
VBOX_CC_OPT += -DRTLOG_REL_ENABLED -DRT_STRICT -DVBOX_STRICT
# Enable Intel Network model E1000
VBOX_CC_OPT += -DVBOX_WITH_E1000
VIRTUALBOX_VERSION_MAJOR := $(shell cat $(VIRTUALBOX_DIR)/Config.kmk | grep "VBOX_VERSION_MAJOR = " | grep -v "'VBOX_VERSION_MAJOR" | sed "s/^.*= //")
VIRTUALBOX_VERSION_MINOR := $(shell cat $(VIRTUALBOX_DIR)/Config.kmk | grep "VBOX_VERSION_MINOR = " | grep -v "'VBOX_VERSION_MINOR" | sed "s/^.*= //")

View File

@ -23,6 +23,9 @@ SRC_CC += Devices/Storage/DevATA.cpp
SRC_CC += Devices/Storage/Debug.cpp
SRC_CC += Devices/Storage/fdc.c
SRC_CC += Devices/Storage/DrvRawImage.cpp
SRC_CC += Devices/Network/DevE1000.cpp
SRC_CC += Devices/Network/DevE1000Phy.cpp
SRC_CC += Devices/Network/DevEEPROM.cpp
SRC_CC += Devices/Network/DevPCNet.cpp
SRC_CC += Devices/VMMDev/VMMDev.cpp
SRC_CC += Devices/VMMDev/VMMDevHGCM.cpp

View File

@ -11,6 +11,10 @@ SRC_CC += Devices/Serial/DrvRawFile.cpp
SRC_CC += Devices/Serial/DrvHostSerial.cpp
SRC_CC += Main/src-client/MouseImpl.cpp
SRC_CC += network.cpp
vpath network.cpp $(REP_DIR)/src/virtualbox
# includes needed by 'MouseImpl.cpp'
INC_DIR += $(VBOX_DIR)/Main/include
INC_DIR += $(VBOX_DIR)/Frontends/VBoxBFE

View File

@ -34,7 +34,9 @@ SRC_CC += Runtime/common/log/logrel.cpp \
SRC_CC += Runtime/common/err/RTErrConvertFromErrno.cpp
SRC_CC += Runtime/common/alloc/memcache.cpp
SRC_CC += Runtime/common/alloc/heapoffset.cpp
SRC_CC += Runtime/common/checksum/crc32.cpp
SRC_CC += Runtime/common/checksum/md5.cpp
SRC_CC += Runtime/common/checksum/ipv4.cpp
SRC_CC += Runtime/common/log/log.cpp
SRC_CC += Runtime/common/log/log.cpp
SRC_CC += Runtime/common/log/logellipsis.cpp

View File

@ -1 +1 @@
a1463e45f4bcb23ee32da9cce87bc1a85289e165
64bd2d2de0305c36048e46c05af5bc6578533ed3

View File

@ -1,3 +1,5 @@
set use_net 0
set build_components {
core init virtualbox
drivers/input
@ -9,6 +11,8 @@ lappend_if [have_spec acpi] build_components drivers/acpi
lappend_if [have_spec pci] build_components drivers/pci
lappend_if [have_spec x86] build_components drivers/rtc
lappend_if [expr $use_net] build_components drivers/nic
build $build_components
create_boot_directory
@ -38,7 +42,7 @@ set config {
append_if [have_spec acpi] config {
<start name="acpi" priority="-1">
<resource name="RAM" quantum="5M"/>
<resource name="RAM" quantum="8M"/>
<binary name="acpi_drv"/>
<provides>
<service name="PCI"/>
@ -85,13 +89,25 @@ append_if [have_spec x86] config {
</provides>
</start>}
append_if [expr $use_net] config {
<start name="nic_drv" priority="-1">
<resource name="RAM" quantum="4M"/>
<provides><service name="Nic"/></provides>
</start>
}
append config {
<start name="virtualbox" priority="-2">
<resource name="RAM" quantum="1G"/>
<config>
<image type="iso" file="test.iso" />
<!-- <ioapic/> -->
<!-- <noacpi/> -->
<!-- <noacpi/> -->}
append_if [expr $use_net] config {
<net model="e1000"/>}
append config {
<libc stdout="/dev/log" stderr="/dev/log">
<vfs>
<dir name="dev"> <log/> </dir>
@ -120,6 +136,8 @@ append boot_modules { ld.lib.so libc.lib.so libm.lib.so pthread.lib.so
libc_lock_pipe.lib.so libc_terminal.lib.so
libiconv.lib.so }
append_if [expr $use_net] boot_modules { nic_drv }
build_boot_image $boot_modules
append qemu_args " -m 512 "

View File

@ -97,6 +97,11 @@ extern "C" int VBoxDevicesRegister(PPDMDEVREGCB pCallbacks, uint32_t u32Version)
if (RT_FAILURE(rc))
return rc;
/* Ethernet E1000 controller */
rc = pCallbacks->pfnRegister(pCallbacks, &g_DeviceE1000);
if (RT_FAILURE(rc))
return rc;
/* Serial device */
rc = pCallbacks->pfnRegister(pCallbacks, &g_DeviceSerialPort);
if (RT_FAILURE(rc))

View File

@ -33,6 +33,7 @@ extern "C" int VBoxDriversRegister(PCPDMDRVREGCB pCallbacks, uint32_t u32Version
&g_DrvRawFile,
&g_DrvHostSerial,
&g_DrvVD,
&g_DrvHostInterface,
0
};

View File

@ -161,10 +161,6 @@ DUMMY(-1, PGMGetHostMode)
CHECKED_DUMMY(0, poll) /* needed by 'DrvHostSerial.cpp' */
DUMMY(-1, pthread_key_delete)
DUMMY(-1, RTCrc32);
DUMMY(-1, RTCrc32Start)
DUMMY(-1, RTCrc32Finish)
DUMMY(-1, RTCrc32Process)
DUMMY(-1, RTMemExecFree)
DUMMY(-1, RTMemPageFree)
DUMMY(-1, RTPathAppend)
@ -218,7 +214,6 @@ DUMMY(-1, RTAvlU32Insert)
CHECKED_DUMMY( 0, IOMR3Init)
int IOMR3IOPortRegisterR0() { return 0; }
int IOMR3IOPortRegisterRC() { return 0; }
DUMMY(-1, IOMR3MmioDeregister)
CHECKED_DUMMY( 0, IOMR3MmioRegisterR0)
CHECKED_DUMMY( 0, IOMR3MmioRegisterRC)
void IOMR3Relocate() { }
@ -281,6 +276,8 @@ DUMMY(-1, RTSymlinkCreate)
DUMMY(-1, RTSymlinkRead)
DUMMY(-1, RTSymlinkDelete)
DUMMY(-1, RTNetIPv6PseudoChecksumEx)
CHECKED_DUMMY(0, futimes)
CHECKED_DUMMY(0, lutimes)

View File

@ -257,6 +257,19 @@ class Guest_memory
pfnReadCallback, pfnFillCallback, fFlags));
}
bool remove_mmio_mapping(RTGCPHYS const GCPhys, RTGCPHYS const size)
{
Region *r = _lookup(GCPhys, _mmio_regions, size);
if (!r)
return false;
_mmio_regions.remove(r);
delete r;
return true;
}
void dump() const
{
Genode::printf("guest-physical to VMM-local RAM mappings:\n");

View File

@ -29,8 +29,9 @@ int IOMR3MmioRegisterR3(PVM pVM, PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart,
R3PTRTYPE(PFNIOMMMIOFILL) pfnFillCallback,
uint32_t fFlags, const char *pszDesc)
{
PLOG("IOMR3MmioRegisterR3: GCPhys=0x%lx cb=0x%zx pszDesc=%s rd=%p wr=%p fl=%p",
(long)GCPhysStart, (size_t)cbRange, pszDesc,
PLOG("%s: GCPhys=0x%lx cb=0x%x pszDesc=%s rd=%p wr=%p fl=%p",
__PRETTY_FUNCTION__,
(long)GCPhysStart, cbRange, pszDesc,
pfnWriteCallback, pfnReadCallback, pfnFillCallback);
REMR3NotifyHandlerPhysicalRegister(pVM, PGMPHYSHANDLERTYPE_MMIO,
@ -45,6 +46,20 @@ int IOMR3MmioRegisterR3(PVM pVM, PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart,
}
int IOMR3MmioDeregister(PVM pVM, PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart,
uint32_t cbRange)
{
PLOG("%s: GCPhys=0x%lx cb=0x%x", __PRETTY_FUNCTION__, GCPhysStart, cbRange);
bool status = guest_memory()->remove_mmio_mapping(GCPhysStart, cbRange);
if (status)
return VINF_SUCCESS;
return !VINF_SUCCESS;
}
VBOXSTRICTRC IOMMMIOWrite(PVM pVM, RTGCPHYS GCPhys, uint32_t u32Value, size_t cbValue)
{
// PDBG("GCPhys=0x%x, u32Value=0x%x, cbValue=%zd", GCPhys, u32Value, cbValue);

View File

@ -22,6 +22,8 @@
#include <VBox/err.h>
#include <VBox/vmm/pdmdev.h>
static bool verbose = false;
class Guest_ioports
{
struct Range;
@ -263,8 +265,9 @@ IOMR3IOPortRegisterR3(PVM pVM, PPDMDEVINS pDevIns,
R3PTRTYPE(PFNIOMIOPORTINSTRING) pfnInStringCallback,
const char *pszDesc)
{
PLOG("register I/O port range 0x%x-0x%x '%s'",
PortStart, PortStart + cPorts - 1, pszDesc);
if (verbose)
PLOG("register I/O port range 0x%x-0x%x '%s'",
PortStart, PortStart + cPorts - 1, pszDesc);
return guest_ioports()->add_range(pDevIns, PortStart, cPorts, pvUser,
pfnOutCallback, pfnInCallback,
@ -275,8 +278,9 @@ IOMR3IOPortRegisterR3(PVM pVM, PPDMDEVINS pDevIns,
int IOMR3IOPortDeregister(PVM pVM, PPDMDEVINS pDevIns, RTIOPORT PortStart,
RTUINT cPorts)
{
PLOG("deregister I/O port range 0x%x-0x%x",
PortStart, PortStart + cPorts - 1);
if (verbose)
PLOG("deregister I/O port range 0x%x-0x%x",
PortStart, PortStart + cPorts - 1);
return guest_ioports()->remove_range(pDevIns, PortStart, cPorts);
}

View File

@ -105,6 +105,7 @@ extern "C" char *getenv(const char *name)
// "+rem_run.e.l.f"
// "+pgm.e.l.f"
"+pdm"
// "+dev_pcnet.e.l.f"
// "+dev_pic.e.l.f"
// "+dev_apic.e.l.f"
// "+dev_vmm.e.l.f"

View File

@ -20,6 +20,7 @@
/* libc includes */
#include <stdio.h>
#include <string.h>
/* libc memory allocator */
#include <libc_mem_alloc.h>
@ -65,9 +66,7 @@ namespace {
if (_argc >= MAX_ARGS - 1)
throw Too_many_arguments();
/* XXX yes const-casting hurts but main() needs char**, if in
* doubt we should strdup() here, right? */
_argv[_argc++] = const_cast<char *>(arg);
_argv[_argc++] = strdup(arg);
}
char *** argvp() {
@ -170,7 +169,7 @@ int main()
try {
Xml_node::Attribute overlay = node.attribute("overlay");
overlay.value(c_type, sizeof(c_type));
if (!strcmp(c_type, "yes"))
if (!Genode::strcmp(c_type, "yes"))
bOverlay = true;
} catch (...) { }
type.value(c_type, sizeof(c_type));
@ -239,9 +238,35 @@ int main()
}
} catch(Genode::Xml_node::Nonexistent_sub_node) { }
PINF("start %s image '%s' with %zu MB guest memory=%zu and %u shared folders",
/* network setup */
unsigned net = 0;
try {
using namespace Genode;
for (Xml_node node = config()->xml_node().sub_node("net");
true; node = node.next("net")) {
net ++;
char buf [10];
Genode::snprintf(buf, sizeof(buf), "-hifdev%d", net);
args.add(buf);
/* read out network model, if not set use e1000 */
try {
Xml_node::Attribute model = node.attribute("model");
char * c_model = new char[model.value_size() + 1];
model.value(c_model, model.value_size() + 1);
args.add(c_model);
} catch(Genode::Xml_node::Nonexistent_attribute) {
args.add("e1000");
}
}
} catch(Genode::Xml_node::Nonexistent_sub_node) { }
PINF("start %s image '%s' with %zu MB guest memory=%zu, %u shared folders,"
" %u network connections",
c_type, c_file, vm_size / 1024 / 1024,
Genode::env()->ram_session()->avail(), shares);
Genode::env()->ram_session()->avail(), shares, net);
if (RT_FAILURE(RTR3InitExe(args.argc(), args.argvp(), 0))) {
PERR("Intialization of VBox Runtime failed.");

View File

@ -0,0 +1,492 @@
/**
* Genode network session driver,
* derived from src/VBox/Devices/Network/DrvTAP.cpp.
*/
/*
* Copyright (C) 2014 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
/*
* Copyright (C) 2006-2012 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.
*/
/*******************************************************************************
* Header Files *
*******************************************************************************/
#define LOG_GROUP LOG_GROUP_DRV_TUN
#include <VBox/log.h>
#include <VBox/vmm/pdmdrv.h>
#include <VBox/vmm/pdmnetifs.h>
#include <VBox/vmm/pdmnetinline.h>
#include <iprt/mem.h>
#include <iprt/uuid.h>
#include "VBoxDD.h"
#include <nic_session/connection.h>
#include <nic/packet_allocator.h>
/*******************************************************************************
* Structures and Typedefs *
*******************************************************************************/
/**
* TAP driver instance data.
*
* @implements PDMINETWORKUP
*/
typedef struct DRVTAP
{
/** The network interface. */
PDMINETWORKUP INetworkUp;
/** The network interface. */
PPDMINETWORKDOWN pIAboveNet;
/** Pointer to the driver instance. */
PPDMDRVINS pDrvIns;
/** Reader thread. */
PPDMTHREAD pThread;
/** @todo The transmit thread. */
/** Transmit lock used by drvTAPNetworkUp_BeginXmit. */
RTCRITSECT XmitLock;
Nic::Session *nic_session;
PDMINETWORKCONFIG INetworkConfig;
} DRVTAP, *PDRVTAP;
/** Converts a pointer to TAP::INetworkUp to a PRDVTAP. */
#define PDMINETWORKUP_2_DRVTAP(pInterface) ( (PDRVTAP)((uintptr_t)pInterface - RT_OFFSETOF(DRVTAP, INetworkUp)) )
#define PDMINETWORKCONFIG_2_DRVTAP(pInterface) ( (PDRVTAP)((uintptr_t)pInterface - RT_OFFSETOF(DRVTAP, INetworkConfig)) )
/*******************************************************************************
* Internal Functions *
*******************************************************************************/
static int net_send_packet(void * packet, uint32_t packet_len, Nic::Session * nic) {
/* allocate transmit packet */
Packet_descriptor tx_packet;
try {
tx_packet = nic->tx()->alloc_packet(packet_len);
} catch (Nic::Session::Tx::Source::Packet_alloc_failed) {
PERR("tx packet alloc failed");
return VERR_NO_MEMORY;
}
/* fill packet with content */
char * stream_buffer = nic->tx()->packet_content(tx_packet);
memcpy(stream_buffer, packet, packet_len);
nic->tx()->submit_packet(tx_packet);
/* wait for acknowledgement */
Packet_descriptor ack_tx_packet = nic->tx()->get_acked_packet();
if (ack_tx_packet.size() != tx_packet.size() ||
ack_tx_packet.offset() != tx_packet.offset())
PERR("unexpected acked packet");
nic->tx()->release_packet(tx_packet);
return VINF_SUCCESS;
}
/**
* @interface_method_impl{PDMINETWORKUP,pfnBeginXmit}
*/
static DECLCALLBACK(int) drvTAPNetworkUp_BeginXmit(PPDMINETWORKUP pInterface, bool fOnWorkerThread)
{
PDRVTAP pThis = PDMINETWORKUP_2_DRVTAP(pInterface);
int rc = RTCritSectTryEnter(&pThis->XmitLock);
if (RT_FAILURE(rc))
{
/** @todo XMIT thread */
rc = VERR_TRY_AGAIN;
}
return rc;
}
/**
* @interface_method_impl{PDMINETWORKUP,pfnAllocBuf}
*/
static DECLCALLBACK(int) drvTAPNetworkUp_AllocBuf(PPDMINETWORKUP pInterface, size_t cbMin,
PCPDMNETWORKGSO pGso, PPPDMSCATTERGATHER ppSgBuf)
{
PDRVTAP pThis = PDMINETWORKUP_2_DRVTAP(pInterface);
Assert(RTCritSectIsOwner(&pThis->XmitLock));
/*
* Allocate a scatter / gather buffer descriptor that is immediately
* followed by the buffer space of its single segment. The GSO context
* comes after that again.
*/
PPDMSCATTERGATHER pSgBuf = (PPDMSCATTERGATHER)RTMemAlloc( RT_ALIGN_Z(sizeof(*pSgBuf), 16)
+ RT_ALIGN_Z(cbMin, 16)
+ (pGso ? RT_ALIGN_Z(sizeof(*pGso), 16) : 0));
if (!pSgBuf)
return VERR_NO_MEMORY;
/*
* Initialize the S/G buffer and return.
*/
pSgBuf->fFlags = PDMSCATTERGATHER_FLAGS_MAGIC | PDMSCATTERGATHER_FLAGS_OWNER_1;
pSgBuf->cbUsed = 0;
pSgBuf->cbAvailable = RT_ALIGN_Z(cbMin, 16);
pSgBuf->pvAllocator = NULL;
if (!pGso)
pSgBuf->pvUser = NULL;
else
{
pSgBuf->pvUser = (uint8_t *)(pSgBuf + 1) + pSgBuf->cbAvailable;
*(PPDMNETWORKGSO)pSgBuf->pvUser = *pGso;
}
pSgBuf->cSegs = 1;
pSgBuf->aSegs[0].cbSeg = pSgBuf->cbAvailable;
pSgBuf->aSegs[0].pvSeg = pSgBuf + 1;
#if 0 /* poison */
memset(pSgBuf->aSegs[0].pvSeg, 'F', pSgBuf->aSegs[0].cbSeg);
#endif
*ppSgBuf = pSgBuf;
return VINF_SUCCESS;
}
/**
* @interface_method_impl{PDMINETWORKUP,pfnFreeBuf}
*/
static DECLCALLBACK(int) drvTAPNetworkUp_FreeBuf(PPDMINETWORKUP pInterface, PPDMSCATTERGATHER pSgBuf)
{
PDRVTAP pThis = PDMINETWORKUP_2_DRVTAP(pInterface);
Assert(RTCritSectIsOwner(&pThis->XmitLock));
if (pSgBuf)
{
Assert((pSgBuf->fFlags & PDMSCATTERGATHER_FLAGS_MAGIC_MASK) == PDMSCATTERGATHER_FLAGS_MAGIC);
pSgBuf->fFlags = 0;
RTMemFree(pSgBuf);
}
return VINF_SUCCESS;
}
/**
* @interface_method_impl{PDMINETWORKUP,pfnSendBuf}
*/
static DECLCALLBACK(int) drvTAPNetworkUp_SendBuf(PPDMINETWORKUP pInterface, PPDMSCATTERGATHER pSgBuf, bool fOnWorkerThread)
{
PDRVTAP pThis = PDMINETWORKUP_2_DRVTAP(pInterface);
AssertPtr(pSgBuf);
Assert((pSgBuf->fFlags & PDMSCATTERGATHER_FLAGS_MAGIC_MASK) == PDMSCATTERGATHER_FLAGS_MAGIC);
Assert(RTCritSectIsOwner(&pThis->XmitLock));
/* Set an FTM checkpoint as this operation changes the state permanently. */
PDMDrvHlpFTSetCheckpoint(pThis->pDrvIns, FTMCHECKPOINTTYPE_NETWORK);
int rc;
if (!pSgBuf->pvUser)
{
Log2(("drvTAPSend: pSgBuf->aSegs[0].pvSeg=%p pSgBuf->cbUsed=%#x\n"
"%.*Rhxd\n",
pSgBuf->aSegs[0].pvSeg, pSgBuf->cbUsed, pSgBuf->cbUsed, pSgBuf->aSegs[0].pvSeg));
rc = net_send_packet(pSgBuf->aSegs[0].pvSeg, pSgBuf->cbUsed, pThis->nic_session);
}
else
{
uint8_t abHdrScratch[256];
uint8_t const *pbFrame = (uint8_t const *)pSgBuf->aSegs[0].pvSeg;
PCPDMNETWORKGSO pGso = (PCPDMNETWORKGSO)pSgBuf->pvUser;
uint32_t const cSegs = PDMNetGsoCalcSegmentCount(pGso, pSgBuf->cbUsed); Assert(cSegs > 1);
rc = VINF_SUCCESS;
for (size_t iSeg = 0; iSeg < cSegs; iSeg++)
{
uint32_t cbSegFrame;
void *pvSegFrame = PDMNetGsoCarveSegmentQD(pGso, (uint8_t *)pbFrame, pSgBuf->cbUsed, abHdrScratch,
iSeg, cSegs, &cbSegFrame);
rc = net_send_packet(pvSegFrame, cbSegFrame, pThis->nic_session);
if (RT_FAILURE(rc))
break;
}
}
pSgBuf->fFlags = 0;
RTMemFree(pSgBuf);
AssertRC(rc);
if (RT_FAILURE(rc))
rc = rc == VERR_NO_MEMORY ? VERR_NET_NO_BUFFER_SPACE : VERR_NET_DOWN;
return rc;
}
/**
* @interface_method_impl{PDMINETWORKUP,pfnEndXmit}
*/
static DECLCALLBACK(void) drvTAPNetworkUp_EndXmit(PPDMINETWORKUP pInterface)
{
PDRVTAP pThis = PDMINETWORKUP_2_DRVTAP(pInterface);
RTCritSectLeave(&pThis->XmitLock);
}
/**
* @interface_method_impl{PDMINETWORKUP,pfnSetPromiscuousMode}
*/
static DECLCALLBACK(void) drvTAPNetworkUp_SetPromiscuousMode(PPDMINETWORKUP pInterface, bool fPromiscuous)
{
LogFlow(("drvTAPNetworkUp_SetPromiscuousMode: fPromiscuous=%d\n", fPromiscuous));
/* nothing to do */
}
/**
* Notification on link status changes.
*
* @param pInterface Pointer to the interface structure containing the called function pointer.
* @param enmLinkState The new link state.
* @thread EMT
*/
static DECLCALLBACK(void) drvTAPNetworkUp_NotifyLinkChanged(PPDMINETWORKUP pInterface, PDMNETWORKLINKSTATE enmLinkState)
{
LogFlow(("drvTAPNetworkUp_NotifyLinkChanged: enmLinkState=%d\n", enmLinkState));
/** @todo take action on link down and up. Stop the polling and such like. */
}
static DECLCALLBACK(int) drvGetMac(PPDMINETWORKCONFIG pInterface, PRTMAC pMac)
{
PDRVTAP pThis = PDMINETWORKCONFIG_2_DRVTAP(pInterface);
static_assert (sizeof(*pMac) == sizeof(pThis->nic_session->mac_address()),
"should be equal");
memcpy(pMac, pThis->nic_session->mac_address().addr, sizeof(*pMac));
return VINF_SUCCESS;
}
/**
* Asynchronous I/O thread for handling receive.
*
* @returns VINF_SUCCESS (ignored).
* @param Thread Thread handle.
* @param pvUser Pointer to a DRVTAP structure.
*/
static DECLCALLBACK(int) drvTAPAsyncIoThread(PPDMDRVINS pDrvIns, PPDMTHREAD pThread)
{
PDRVTAP pThis = PDMINS_2_DATA(pDrvIns, PDRVTAP);
LogFlow(("drvTAPAsyncIoThread: pThis=%p\n", pThis));
if (pThread->enmState == PDMTHREADSTATE_INITIALIZING)
return VINF_SUCCESS;
Nic::Session * nic = pThis->nic_session;
while (pThread->enmState == PDMTHREADSTATE_RUNNING)
{
Packet_descriptor rx_packet = nic->rx()->get_packet();
/* send it to the network bus */
char * rx_content = nic->rx()->packet_content(rx_packet);
int rc1 = pThis->pIAboveNet->pfnWaitReceiveAvail(pThis->pIAboveNet,
RT_INDEFINITE_WAIT);
if (RT_FAILURE(rc1))
continue;
rc1 = pThis->pIAboveNet->pfnReceive(pThis->pIAboveNet, rx_content,
rx_packet.size());
AssertRC(rc1);
/* acknowledge received packet */
nic->rx()->acknowledge_packet(rx_packet);
}
return VINF_SUCCESS;
}
/**
* Unblock the send thread so it can respond to a state change.
*
* @returns VBox status code.
* @param pDevIns The pcnet device instance.
* @param pThread The send thread.
*/
static DECLCALLBACK(int) drvTapAsyncIoWakeup(PPDMDRVINS pDrvIns, PPDMTHREAD pThread)
{
PDRVTAP pThis = PDMINS_2_DATA(pDrvIns, PDRVTAP);
Assert(!"Not implemented");
return VINF_SUCCESS;
}
/* -=-=-=-=- PDMIBASE -=-=-=-=- */
/**
* @interface_method_impl{PDMIBASE,pfnQueryInterface}
*/
static DECLCALLBACK(void *) drvTAPQueryInterface(PPDMIBASE pInterface, const char *pszIID)
{
PPDMDRVINS pDrvIns = PDMIBASE_2_PDMDRV(pInterface);
PDRVTAP pThis = PDMINS_2_DATA(pDrvIns, PDRVTAP);
PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pDrvIns->IBase);
PDMIBASE_RETURN_INTERFACE(pszIID, PDMINETWORKUP, &pThis->INetworkUp);
PDMIBASE_RETURN_INTERFACE(pszIID, PDMINETWORKCONFIG, &pThis->INetworkConfig);
return NULL;
}
/* -=-=-=-=- PDMDRVREG -=-=-=-=- */
static DECLCALLBACK(void) drvTAPDestruct(PPDMDRVINS pDrvIns)
{
Assert(!"Not implemented");
}
/**
* Construct a TAP network transport driver instance.
*
* @copydoc FNPDMDRVCONSTRUCT
*/
static DECLCALLBACK(int) drvTAPConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint32_t fFlags)
{
PDRVTAP pThis = PDMINS_2_DATA(pDrvIns, PDRVTAP);
PDMDRV_CHECK_VERSIONS_RETURN(pDrvIns);
/*
* Init the static parts.
*/
pThis->pDrvIns = pDrvIns;
/* IBase */
pDrvIns->IBase.pfnQueryInterface = drvTAPQueryInterface;
/* INetwork */
pThis->INetworkUp.pfnBeginXmit = drvTAPNetworkUp_BeginXmit;
pThis->INetworkUp.pfnAllocBuf = drvTAPNetworkUp_AllocBuf;
pThis->INetworkUp.pfnFreeBuf = drvTAPNetworkUp_FreeBuf;
pThis->INetworkUp.pfnSendBuf = drvTAPNetworkUp_SendBuf;
pThis->INetworkUp.pfnEndXmit = drvTAPNetworkUp_EndXmit;
pThis->INetworkUp.pfnSetPromiscuousMode = drvTAPNetworkUp_SetPromiscuousMode;
pThis->INetworkUp.pfnNotifyLinkChanged = drvTAPNetworkUp_NotifyLinkChanged;
/* INetworkConfig - used on Genode to request Mac address of nic_session */
pThis->INetworkConfig.pfnGetMac = drvGetMac;
/*
* Setup Genode nic_session connection
*/
Nic::Packet_allocator *tx_block_alloc =
new (Genode::env()->heap()) Nic::Packet_allocator(Genode::env()->heap());
enum {
PACKET_SIZE = Nic::Packet_allocator::DEFAULT_PACKET_SIZE,
BUF_SIZE = Nic::Session::QUEUE_SIZE * PACKET_SIZE,
};
try {
pThis->nic_session = new Nic::Connection(tx_block_alloc, BUF_SIZE,
BUF_SIZE);
} catch (...) {
return VERR_HOSTIF_INIT_FAILED;
}
/*
* Check that no-one is attached to us.
*/
AssertMsgReturn(PDMDrvHlpNoAttach(pDrvIns) == VERR_PDM_NO_ATTACHED_DRIVER,
("Configuration error: Not possible to attach anything to this driver!\n"),
VERR_PDM_DRVINS_NO_ATTACH);
/*
* Query the network port interface.
*/
pThis->pIAboveNet = PDMIBASE_QUERY_INTERFACE(pDrvIns->pUpBase, PDMINETWORKDOWN);
if (!pThis->pIAboveNet)
return PDMDRV_SET_ERROR(pDrvIns, VERR_PDM_MISSING_INTERFACE_ABOVE,
N_("Configuration error: The above device/driver didn't export the network port interface"));
/*
* Create the transmit lock.
*/
int rc = RTCritSectInit(&pThis->XmitLock);
AssertRCReturn(rc, rc);
/*
* Create the async I/O thread.
*/
rc = PDMDrvHlpThreadCreate(pDrvIns, &pThis->pThread, pThis, drvTAPAsyncIoThread, drvTapAsyncIoWakeup, 128 * _1K, RTTHREADTYPE_IO, "TAP");
AssertRCReturn(rc, rc);
return rc;
}
/**
* TAP network transport driver registration record.
*/
const PDMDRVREG g_DrvHostInterface =
{
/* u32Version */
PDM_DRVREG_VERSION,
/* szName */
"HostInterface",
/* szRCMod */
"",
/* szR0Mod */
"",
/* pszDescription */
"Genode Network Session Driver",
/* fFlags */
PDM_DRVREG_FLAGS_HOST_BITS_DEFAULT,
/* fClass. */
PDM_DRVREG_CLASS_NETWORK,
/* cMaxInstances */
~0U,
/* cbInstance */
sizeof(DRVTAP),
/* pfnConstruct */
drvTAPConstruct,
/* pfnDestruct */
drvTAPDestruct,
/* pfnRelocate */
NULL,
/* pfnIOCtl */
NULL,
/* pfnPowerOn */
NULL,
/* pfnReset */
NULL,
/* pfnSuspend */
NULL, /** @todo Do power on, suspend and resume handlers! */
/* pfnResume */
NULL,
/* pfnAttach */
NULL,
/* pfnDetach */
NULL,
/* pfnPowerOff */
NULL,
/* pfnSoftReset */
NULL,
/* u32EndVersion */
PDM_DRVREG_VERSION
};

View File

@ -0,0 +1,131 @@
+++ src/app/virtualbox/src/VBox/Devices/Network/DevE1000.cpp
@@ -7536,6 +7536,39 @@
pState->INetworkConfig.pfnGetLinkState = e1kGetLinkState;
pState->INetworkConfig.pfnSetLinkState = e1kSetLinkState;
+ /* For Genode attach already here to be able to overwrite mac address */
+ rc = PDMDevHlpDriverAttach(pDevIns, 0, &pState->IBase, &pState->pDrvBase, "Network Port");
+ if (RT_SUCCESS(rc))
+ {
+ /* Genode: read out the mac address from nic_session interface */
+ PPDMINETWORKCONFIG pDrvConfig = PDMIBASE_QUERY_INTERFACE(pState->pDrvBase, PDMINETWORKCONFIG);
+ Assert(pDrvConfig && pDrvConfig->pfnGetMac);
+ pDrvConfig->pfnGetMac(pDrvConfig, &pState->macConfigured);
+
+ if (rc == VINF_NAT_DNS)
+ {
+ PDMDevHlpVMSetRuntimeError(pDevIns, 0 /*fFlags*/, "NoDNSforNAT",
+ N_("A Domain Name Server (DNS) for NAT networking could not be determined. Ensure that your host is correctly connected to an ISP. If you ignore this warning the guest will not be able to perform nameserver lookups and it will probably observe delays if trying so"));
+ }
+ pState->pDrvR3 = PDMIBASE_QUERY_INTERFACE(pState->pDrvBase, PDMINETWORKUP);
+ AssertMsgReturn(pState->pDrvR3, ("Failed to obtain the PDMINETWORKUP interface!\n"),
+ VERR_PDM_MISSING_INTERFACE_BELOW);
+
+ pState->pDrvR0 = PDMIBASER0_QUERY_INTERFACE(PDMIBASE_QUERY_INTERFACE(pState->pDrvBase, PDMIBASER0), PDMINETWORKUP);
+ pState->pDrvRC = PDMIBASERC_QUERY_INTERFACE(PDMIBASE_QUERY_INTERFACE(pState->pDrvBase, PDMIBASERC), PDMINETWORKUP);
+ }
+ else if ( rc == VERR_PDM_NO_ATTACHED_DRIVER
+ || rc == VERR_PDM_CFG_MISSING_DRIVER_NAME)
+ {
+ /* No error! */
+ E1kLog(("%s This adapter is not attached to any network!\n", INSTANCE(pState)));
+ }
+ else
+ return PDMDEV_SET_ERROR(pDevIns, rc, N_("Failed to attach the network LUN"));
+
+
+
+
/* Initialize the EEPROM */
pState->eeprom.init(pState->macConfigured);
@@ -7696,30 +7729,6 @@
return PDMDEV_SET_ERROR(pDevIns, rc, N_("Failed to attach the status LUN"));
pState->pLedsConnector = PDMIBASE_QUERY_INTERFACE(pBase, PDMILEDCONNECTORS);
- rc = PDMDevHlpDriverAttach(pDevIns, 0, &pState->IBase, &pState->pDrvBase, "Network Port");
- if (RT_SUCCESS(rc))
- {
- if (rc == VINF_NAT_DNS)
- {
- PDMDevHlpVMSetRuntimeError(pDevIns, 0 /*fFlags*/, "NoDNSforNAT",
- N_("A Domain Name Server (DNS) for NAT networking could not be determined. Ensure that your host is correctly connected to an ISP. If you ignore this warning the guest will not be able to perform nameserver lookups and it will probably observe delays if trying so"));
- }
- pState->pDrvR3 = PDMIBASE_QUERY_INTERFACE(pState->pDrvBase, PDMINETWORKUP);
- AssertMsgReturn(pState->pDrvR3, ("Failed to obtain the PDMINETWORKUP interface!\n"),
- VERR_PDM_MISSING_INTERFACE_BELOW);
-
- pState->pDrvR0 = PDMIBASER0_QUERY_INTERFACE(PDMIBASE_QUERY_INTERFACE(pState->pDrvBase, PDMIBASER0), PDMINETWORKUP);
- pState->pDrvRC = PDMIBASERC_QUERY_INTERFACE(PDMIBASE_QUERY_INTERFACE(pState->pDrvBase, PDMIBASERC), PDMINETWORKUP);
- }
- else if ( rc == VERR_PDM_NO_ATTACHED_DRIVER
- || rc == VERR_PDM_CFG_MISSING_DRIVER_NAME)
- {
- /* No error! */
- E1kLog(("%s This adapter is not attached to any network!\n", INSTANCE(pState)));
- }
- else
- return PDMDEV_SET_ERROR(pDevIns, rc, N_("Failed to attach the network LUN"));
-
rc = RTSemEventCreate(&pState->hEventMoreRxDescAvail);
if (RT_FAILURE(rc))
return rc;
+++ src/app/virtualbox/src/VBox/Devices/Network/DevPCNet.cpp
@@ -5331,6 +5331,11 @@
rc = PDMDevHlpDriverAttach(pDevIns, 0, &pThis->IBase, &pThis->pDrvBase, "Network Port");
if (RT_SUCCESS(rc))
{
+ /* Genode: read out the mac address from nic_session interface */
+ PPDMINETWORKCONFIG pDrvConfig = PDMIBASE_QUERY_INTERFACE(pThis->pDrvBase, PDMINETWORKCONFIG);
+ Assert(pDrvConfig && pDrvConfig->pfnGetMac);
+ pDrvConfig->pfnGetMac(pDrvConfig, &pThis->MacConfigured);
+
if (rc == VINF_NAT_DNS)
{
#ifdef RT_OS_LINUX
+++ src/app/virtualbox/src/VBox/Frontends/VBoxBFE/VBoxBFE.cpp
@@ -1601,11 +1630,14 @@
/*
* Network adapters
*/
- rc = CFGMR3InsertNode(pDevices, "pcnet", &pDev); UPDATE_RC();
for (ULONG ulInstance = 0; ulInstance < NetworkAdapterCount; ulInstance++)
{
if (g_aNetDevs[ulInstance].enmType != BFENETDEV::NOT_CONFIGURED)
{
+ /* On Genode we use pszName to select the device model */
+ const char * device_model = g_aNetDevs[ulInstance].pszName;
+ rc = CFGMR3InsertNode(pDevices, device_model, &pDev); UPDATE_RC();
+
char szInstance[4];
RTStrPrintf(szInstance, sizeof(szInstance), "%lu", ulInstance);
rc = CFGMR3InsertNode(pDev, szInstance, &pInst); UPDATE_RC();
@@ -1616,6 +1650,10 @@
rc = CFGMR3InsertNode(pInst, "Config", &pCfg); UPDATE_RC();
rc = CFGMR3InsertBytes(pCfg, "MAC", &g_aNetDevs[ulInstance].Mac, sizeof(RTMAC));
UPDATE_RC();
+ if (!strcmp("e1000", device_model)) {
+ rc = CFGMR3InsertInteger(pCfg, "CableConnected", 1); UPDATE_RC();
+ rc = CFGMR3InsertInteger(pCfg, "AdapterType", 0); UPDATE_RC();
+ }
/*
* Enable the packet sniffer if requested.
@@ -1747,10 +1785,15 @@
#else
- FatalError("Name based HIF devices not implemented yet for this host platform\n");
- return VERR_NOT_IMPLEMENTED;
+// FatalError("Name based HIF devices not implemented yet for this host platform\n");
+// return VERR_NOT_IMPLEMENTED;
#endif
}
+
+ rc = CFGMR3InsertNode(pInst, "LUN#999", &pLunL0); UPDATE_RC();
+ rc = CFGMR3InsertString(pLunL0, "Driver", "MainStatus"); UPDATE_RC();
+ rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); UPDATE_RC();
+ rc = CFGMR3InsertInteger(pCfg, "papLeds", (uintptr_t)&mapFDLeds[0]); UPDATE_RC();
}
else if (g_aNetDevs[ulInstance].enmType == BFENETDEV::INTNET)
{

View File

@ -57,7 +57,6 @@ int PGMR3PhysRomRegister(PVM pVM, PPDMDEVINS pDevIns, RTGCPHYS GCPhys,
try {
guest_memory()->add_rom_mapping(GCPhys, cb, pvBinary, pDevIns);
guest_memory()->dump();
/*
* XXX Try to understand the fShadowed condition
@ -256,8 +255,6 @@ int PGMR3PhysRegisterRam(PVM pVM, RTGCPHYS GCPhys, RTGCPHYS cb,
guest_memory()->add_ram_mapping(GCPhys, cb, pv);
guest_memory()->dump();
REMR3NotifyPhysRamRegister(pVM, GCPhys, cb, REM_NOTIFY_PHYS_RAM_FLAGS_RAM);
}
catch (Guest_memory::Region_conflict) {