hrev45998 adds 4 changesets to branch 'master' old head: 8f7f28a7c3db28711920ad5d15df401fae90bcf1 new head: 86af5f159bbd93b977407e8df5ac5f5fe04c2b05 overview: http://cgit.haiku-os.org/haiku/log/?qt=range&q=86af5f1+%5E8f7f28a ---------------------------------------------------------------------------- f73fb10: random: added a bus interface for RNG modules. * Yarrow RNG is the default RNG module. eb5639c: device_manager: tune the search paths * the Virtio RNG PCI device has the class 0, so can't be found using usual paths. Add 0 to _AlwaysRegisterDynamic() and "busses/virtio" in _GetNextDriverPath() for non generic drivers to help finding virtio_pci. * The RNG Virtio device is generic and needs "busses/random" to find virtio_rng. 8d2bf69: random: add a Virtio RNG module * The default module is replaced by the Virtio RNG module when found. * This can have the undesired effect of rendering /dev/urandom slow. * Tested with the following QEmu command line option: -device virtio-rng-pci,rng=rng0 -object rng-random,filename=/dev/random,id=rng0 * moved random.h to private/drivers headers. 86af5f1: VirtioRNG: add to the image [ Jérôme Duval <jerome.duval@xxxxxxxxx> ] ---------------------------------------------------------------------------- 13 files changed, 575 insertions(+), 59 deletions(-) build/jam/HaikuImage | 2 + headers/private/drivers/random.h | 31 +++ src/add-ons/kernel/bus_managers/random/Jamfile | 1 + .../kernel/bus_managers/random/driver.cpp | 76 ++++++- src/add-ons/kernel/bus_managers/random/random.h | 20 -- .../kernel/bus_managers/random/yarrow_rng.cpp | 84 +++++--- .../kernel/bus_managers/random/yarrow_rng.h | 5 +- src/add-ons/kernel/busses/Jamfile | 1 + src/add-ons/kernel/busses/random/Jamfile | 9 + .../kernel/busses/random/VirtioRNGDevice.cpp | 134 +++++++++++++ .../kernel/busses/random/VirtioRNGPrivate.h | 67 +++++++ src/add-ons/kernel/busses/random/virtio_rng.cpp | 197 +++++++++++++++++++ .../kernel/device_manager/device_manager.cpp | 7 +- ############################################################################ Commit: f73fb1051dbdebede4a6ecec5b37674237f0b528 URL: http://cgit.haiku-os.org/haiku/commit/?id=f73fb10 Author: Jérôme Duval <jerome.duval@xxxxxxxxx> Date: Tue Aug 27 22:07:17 2013 UTC random: added a bus interface for RNG modules. * Yarrow RNG is the default RNG module. ---------------------------------------------------------------------------- diff --git a/src/add-ons/kernel/bus_managers/random/driver.cpp b/src/add-ons/kernel/bus_managers/random/driver.cpp index 151a178..715f1691 100644 --- a/src/add-ons/kernel/bus_managers/random/driver.cpp +++ b/src/add-ons/kernel/bus_managers/random/driver.cpp @@ -32,7 +32,8 @@ static mutex sRandomLock; -static device_manager_info* sDeviceManager; +static random_sim_interface *sRandomModule; +device_manager_info* gDeviceManager; typedef struct { @@ -47,14 +48,13 @@ static status_t random_init_device(void* _info, void** _cookie) { mutex_init(&sRandomLock, "/dev/random lock"); - return gYarrowRandomModule->init(); + return B_OK; } static void random_uninit_device(void* _cookie) { - gYarrowRandomModule->uninit(); mutex_destroy(&sRandomLock); } @@ -73,7 +73,7 @@ random_read(void *cookie, off_t position, void *_buffer, size_t *_numBytes) TRACE("read(%Ld,, %ld)\n", position, *_numBytes); MutexLocker locker(&sRandomLock); - return gYarrowRandomModule->read(_buffer, _numBytes); + return sRandomModule->read(_buffer, _numBytes); } @@ -82,7 +82,7 @@ random_write(void *cookie, off_t position, const void *buffer, size_t *_numBytes { TRACE("write(%Ld,, %ld)\n", position, *_numBytes); MutexLocker locker(&sRandomLock); - return gYarrowRandomModule->write(buffer, _numBytes); + return sRandomModule->write(buffer, _numBytes); } @@ -152,7 +152,7 @@ random_supports_device(device_node *parent) const char *bus; // make sure parent is really device root - if (sDeviceManager->get_attr_string(parent, B_DEVICE_BUS, &bus, false)) + if (gDeviceManager->get_attr_string(parent, B_DEVICE_BUS, &bus, false)) return -1; if (strcmp(bus, "root")) @@ -174,7 +174,7 @@ random_register_device(device_node *node) { NULL } }; - return sDeviceManager->register_node(node, RANDOM_DRIVER_MODULE_NAME, + return gDeviceManager->register_node(node, RANDOM_DRIVER_MODULE_NAME, attrs, NULL, NULL); } @@ -212,25 +212,57 @@ random_register_child_devices(void* _cookie) { CALLED(); random_driver_info* info = (random_driver_info*)_cookie; - status_t status = sDeviceManager->publish_device(info->node, "random", + status_t status = gDeviceManager->publish_device(info->node, "random", RANDOM_DEVICE_MODULE_NAME); if (status == B_OK) { - sDeviceManager->publish_device(info->node, "urandom", + gDeviceManager->publish_device(info->node, "urandom", RANDOM_DEVICE_MODULE_NAME); } + // add the default Yarrow RNG + device_attr attrs[] = { + { B_DEVICE_PRETTY_NAME, B_STRING_TYPE, + { string: "Yarrow RNG" }}, + { B_DEVICE_FIXED_CHILD, B_STRING_TYPE, + { string: RANDOM_FOR_CONTROLLER_MODULE_NAME }}, + { NULL } + }; + + device_node* node; + return gDeviceManager->register_node(info->node, + YARROW_RNG_SIM_MODULE_NAME, attrs, NULL, &node); + + return status; +} + + +// #pragma mark - + + +status_t +random_added_device(device_node *node) +{ + CALLED(); + + void *cookie; + + status_t status = gDeviceManager->get_driver(node, + (driver_module_info **)&sRandomModule, &cookie); + return status; } + // #pragma mark - module_dependency module_dependencies[] = { - {B_DEVICE_MANAGER_MODULE_NAME, (module_info**)&sDeviceManager}, + {B_DEVICE_MANAGER_MODULE_NAME, (module_info**)&gDeviceManager}, {} }; + struct device_module_info sRandomDevice = { { RANDOM_DEVICE_MODULE_NAME, @@ -254,6 +286,7 @@ struct device_module_info sRandomDevice = { random_deselect, }; + struct driver_module_info sRandomDriver = { { RANDOM_DRIVER_MODULE_NAME, @@ -270,8 +303,28 @@ struct driver_module_info sRandomDriver = { NULL, // removed }; + +random_for_controller_interface sRandomForControllerModule = { + { + { + RANDOM_FOR_CONTROLLER_MODULE_NAME, + 0, + NULL + }, + + NULL, // supported devices + random_added_device, + NULL, + NULL, + NULL + } +}; + + module_info* modules[] = { (module_info*)&sRandomDriver, (module_info*)&sRandomDevice, + (module_info*)&sRandomForControllerModule, + (module_info*)&gYarrowRandomModule, NULL }; diff --git a/src/add-ons/kernel/bus_managers/random/random.h b/src/add-ons/kernel/bus_managers/random/random.h index 743305f..23c9d10 100644 --- a/src/add-ons/kernel/bus_managers/random/random.h +++ b/src/add-ons/kernel/bus_managers/random/random.h @@ -9,12 +9,25 @@ #define _RANDOM_H +#include <device_manager.h> + + +typedef struct { + driver_module_info info; +} random_for_controller_interface; + + +#define RANDOM_FOR_CONTROLLER_MODULE_NAME "bus_managers/random/controller/driver_v1" + +// Bus manager interface used by Random controller drivers. typedef struct random_module_info { + driver_module_info info; + status_t (*init)(); void (*uninit)(); status_t (*read)(void *_buffer, size_t *_numBytes); status_t (*write)(const void *_buffer, size_t *_numBytes); -} random_module_info; +} random_sim_interface; #endif /* _RANDOM_H */ diff --git a/src/add-ons/kernel/bus_managers/random/yarrow_rng.cpp b/src/add-ons/kernel/bus_managers/random/yarrow_rng.cpp index d144d34..6be1acb 100644 --- a/src/add-ons/kernel/bus_managers/random/yarrow_rng.cpp +++ b/src/add-ons/kernel/bus_managers/random/yarrow_rng.cpp @@ -12,6 +12,15 @@ #include <thread.h> +//#define TRACE_DRIVER +#ifdef TRACE_DRIVER +# define TRACE(x...) dprintf("random: " x) +#else +# define TRACE(x...) ; +#endif +#define CALLED() TRACE("CALLED %s\n", __PRETTY_FUNCTION__) + + #define rotr32(x, n) ((((uint32)(x)) >> ((int) ((n) & 31))) | (((uint32)(x)) << ((int) ((32 - ((n) & 31)))))) #define rotl32(x, n) ((((uint32)(x)) << ((int) ((n) & 31))) | (((uint32)(x)) >> ((int) ((32 - ((n) & 31)))))) @@ -335,12 +344,53 @@ yarrow_rng_write(const void *buffer, size_t *_numBytes) } -random_module_info sYarrowRandomModule = { +// #pragma mark - + + +static status_t +yarrow_init_bus(device_node* node, void** bus_cookie) +{ + CALLED(); + return yarrow_rng_init(); +} + + +static void +yarrow_uninit_bus(void* bus_cookie) +{ + CALLED(); + yarrow_rng_uninit(); +} + + +static void +yarrow_bus_removed(void* bus_cookie) +{ + return; +} + + +// #pragma mark - + + +random_module_info gYarrowRandomModule = { + { + { + YARROW_RNG_SIM_MODULE_NAME, + 0, + NULL + }, + + NULL, // supports_device, + NULL, // register_device, + yarrow_init_bus, + yarrow_uninit_bus, + NULL, // register child devices + NULL, // rescan + yarrow_bus_removed, + }, yarrow_rng_init, yarrow_rng_uninit, yarrow_rng_read, yarrow_rng_write }; - - -random_module_info *gYarrowRandomModule = &sYarrowRandomModule; diff --git a/src/add-ons/kernel/bus_managers/random/yarrow_rng.h b/src/add-ons/kernel/bus_managers/random/yarrow_rng.h index 9f73719..b76f314 100644 --- a/src/add-ons/kernel/bus_managers/random/yarrow_rng.h +++ b/src/add-ons/kernel/bus_managers/random/yarrow_rng.h @@ -14,12 +14,15 @@ #include "random.h" +#define YARROW_RNG_SIM_MODULE_NAME "bus_managers/random/yarrow_rng/device/v1" + + #ifdef __cplusplus extern "C" { #endif -extern random_module_info* gYarrowRandomModule; +extern random_module_info gYarrowRandomModule; #ifdef __cplusplus ############################################################################ Commit: eb5639c43ec74cf0fd714685a6add1c54a2388ac URL: http://cgit.haiku-os.org/haiku/commit/?id=eb5639c Author: Jérôme Duval <jerome.duval@xxxxxxxxx> Date: Thu Aug 29 16:30:48 2013 UTC device_manager: tune the search paths * the Virtio RNG PCI device has the class 0, so can't be found using usual paths. Add 0 to _AlwaysRegisterDynamic() and "busses/virtio" in _GetNextDriverPath() for non generic drivers to help finding virtio_pci. * The RNG Virtio device is generic and needs "busses/random" to find virtio_rng. ---------------------------------------------------------------------------- diff --git a/src/system/kernel/device_manager/device_manager.cpp b/src/system/kernel/device_manager/device_manager.cpp index fff9626..e73c025 100644 --- a/src/system/kernel/device_manager/device_manager.cpp +++ b/src/system/kernel/device_manager/device_manager.cpp @@ -1608,6 +1608,7 @@ device_node::_GetNextDriverPath(void*& cookie, KPath& _path) _AddPath(*stack, "busses/pci"); _AddPath(*stack, "bus_managers"); } else if (!generic) { + _AddPath(*stack, "busses", "virtio"); _AddPath(*stack, "drivers"); } else { // For generic drivers, we only allow busses when the @@ -1619,7 +1620,8 @@ device_node::_GetNextDriverPath(void*& cookie, KPath& _path) _AddPath(*stack, "busses"); } _AddPath(*stack, "drivers", sGenericContextPath); - _AddPath(*stack, "busses/scsi"); + _AddPath(*stack, "busses/scsi"); + _AddPath(*stack, "busses/random"); } break; } @@ -1736,7 +1738,7 @@ device_node::_AlwaysRegisterDynamic() get_attr_uint16(this, B_DEVICE_TYPE, &type, false); get_attr_uint16(this, B_DEVICE_SUB_TYPE, &subType, false); - return type == PCI_serial_bus || type == PCI_bridge; + return type == PCI_serial_bus || type == PCI_bridge || type == 0; // TODO: we may want to be a bit more specific in the future } @@ -2308,4 +2310,3 @@ device_manager_init_post_modules(struct kernel_args* args) RecursiveLocker _(sLock); return sRootNode->Reprobe(); } - ############################################################################ Commit: 8d2bf6953e851d431fc67de1bc970c40afa79e9f URL: http://cgit.haiku-os.org/haiku/commit/?id=8d2bf69 Author: Jérôme Duval <jerome.duval@xxxxxxxxx> Date: Thu Aug 29 16:38:46 2013 UTC random: add a Virtio RNG module * The default module is replaced by the Virtio RNG module when found. * This can have the undesired effect of rendering /dev/urandom slow. * Tested with the following QEmu command line option: -device virtio-rng-pci,rng=rng0 -object rng-random,filename=/dev/random,id=rng0 * moved random.h to private/drivers headers. ---------------------------------------------------------------------------- diff --git a/src/add-ons/kernel/bus_managers/random/random.h b/headers/private/drivers/random.h similarity index 75% rename from src/add-ons/kernel/bus_managers/random/random.h rename to headers/private/drivers/random.h index 23c9d10..cc4d1d5 100644 --- a/src/add-ons/kernel/bus_managers/random/random.h +++ b/headers/private/drivers/random.h @@ -23,11 +23,9 @@ typedef struct { typedef struct random_module_info { driver_module_info info; - status_t (*init)(); - void (*uninit)(); - status_t (*read)(void *_buffer, size_t *_numBytes); - status_t (*write)(const void *_buffer, size_t *_numBytes); -} random_sim_interface; + status_t (*read)(void* cookie, void *_buffer, size_t *_numBytes); + status_t (*write)(void* cookie, const void *_buffer, size_t *_numBytes); +} random_module_info; #endif /* _RANDOM_H */ diff --git a/src/add-ons/kernel/bus_managers/random/Jamfile b/src/add-ons/kernel/bus_managers/random/Jamfile index f5a33f9..8772580 100644 --- a/src/add-ons/kernel/bus_managers/random/Jamfile +++ b/src/add-ons/kernel/bus_managers/random/Jamfile @@ -1,5 +1,6 @@ SubDir HAIKU_TOP src add-ons kernel bus_managers random ; +UsePrivateHeaders drivers ; UsePrivateKernelHeaders ; KernelAddon random : diff --git a/src/add-ons/kernel/bus_managers/random/driver.cpp b/src/add-ons/kernel/bus_managers/random/driver.cpp index 715f1691..deb937a 100644 --- a/src/add-ons/kernel/bus_managers/random/driver.cpp +++ b/src/add-ons/kernel/bus_managers/random/driver.cpp @@ -32,7 +32,8 @@ static mutex sRandomLock; -static random_sim_interface *sRandomModule; +static random_module_info *sRandomModule; +static void *sRandomCookie; device_manager_info* gDeviceManager; @@ -73,7 +74,7 @@ random_read(void *cookie, off_t position, void *_buffer, size_t *_numBytes) TRACE("read(%Ld,, %ld)\n", position, *_numBytes); MutexLocker locker(&sRandomLock); - return sRandomModule->read(_buffer, _numBytes); + return sRandomModule->read(sRandomCookie, _buffer, _numBytes); } @@ -82,7 +83,11 @@ random_write(void *cookie, off_t position, const void *buffer, size_t *_numBytes { TRACE("write(%Ld,, %ld)\n", position, *_numBytes); MutexLocker locker(&sRandomLock); - return sRandomModule->write(buffer, _numBytes); + if (sRandomModule->write == NULL) { + *_numBytes = 0; + return EINVAL; + } + return sRandomModule->write(sRandomCookie, buffer, _numBytes); } @@ -244,10 +249,8 @@ random_added_device(device_node *node) { CALLED(); - void *cookie; - status_t status = gDeviceManager->get_driver(node, - (driver_module_info **)&sRandomModule, &cookie); + (driver_module_info **)&sRandomModule, &sRandomCookie); return status; } diff --git a/src/add-ons/kernel/bus_managers/random/yarrow_rng.cpp b/src/add-ons/kernel/bus_managers/random/yarrow_rng.cpp index 6be1acb..bab1123 100644 --- a/src/add-ons/kernel/bus_managers/random/yarrow_rng.cpp +++ b/src/add-ons/kernel/bus_managers/random/yarrow_rng.cpp @@ -290,24 +290,7 @@ kill_chrand(ch_randgen *randgen) static status_t -yarrow_rng_init() -{ - sRandomEnv = new_chrand(8); - if (sRandomEnv == NULL) - return B_NO_MEMORY; - return B_OK; -} - - -static void -yarrow_rng_uninit() -{ - kill_chrand(sRandomEnv); -} - - -static status_t -yarrow_rng_read(void *_buffer, size_t *_numBytes) +yarrow_rng_read(void* cookie, void *_buffer, size_t *_numBytes) { sRandomCount += *_numBytes; @@ -333,7 +316,7 @@ yarrow_rng_read(void *_buffer, size_t *_numBytes) static status_t -yarrow_rng_write(const void *buffer, size_t *_numBytes) +yarrow_rng_write(void* cookie, const void *buffer, size_t *_numBytes) { OCTET* data = (OCTET*)buffer; for (size_t i = 0; i < *_numBytes / sizeof(OCTET); i++) { @@ -351,7 +334,10 @@ static status_t yarrow_init_bus(device_node* node, void** bus_cookie) { CALLED(); - return yarrow_rng_init(); + sRandomEnv = new_chrand(8); + if (sRandomEnv == NULL) + return B_NO_MEMORY; + return B_OK; } @@ -359,7 +345,7 @@ static void yarrow_uninit_bus(void* bus_cookie) { CALLED(); - yarrow_rng_uninit(); + kill_chrand(sRandomEnv); } @@ -389,8 +375,6 @@ random_module_info gYarrowRandomModule = { NULL, // rescan yarrow_bus_removed, }, - yarrow_rng_init, - yarrow_rng_uninit, yarrow_rng_read, yarrow_rng_write }; diff --git a/src/add-ons/kernel/busses/Jamfile b/src/add-ons/kernel/busses/Jamfile index 2c9ee48..74adc1b 100644 --- a/src/add-ons/kernel/busses/Jamfile +++ b/src/add-ons/kernel/busses/Jamfile @@ -8,6 +8,7 @@ if $(HAIKU_ATA_STACK) = 1 { } SubInclude HAIKU_TOP src add-ons kernel busses agp_gart ; +SubInclude HAIKU_TOP src add-ons kernel busses random ; SubInclude HAIKU_TOP src add-ons kernel busses scsi ; SubInclude HAIKU_TOP src add-ons kernel busses usb ; SubInclude HAIKU_TOP src add-ons kernel busses virtio ; diff --git a/src/add-ons/kernel/busses/random/Jamfile b/src/add-ons/kernel/busses/random/Jamfile new file mode 100644 index 0000000..d1d610b --- /dev/null +++ b/src/add-ons/kernel/busses/random/Jamfile @@ -0,0 +1,9 @@ +SubDir HAIKU_TOP src add-ons kernel busses random ; + +UsePrivateHeaders drivers virtio ; +UsePrivateKernelHeaders ; + +KernelAddon virtio_rng : + virtio_rng.cpp + VirtioRNGDevice.cpp +; diff --git a/src/add-ons/kernel/busses/random/VirtioRNGDevice.cpp b/src/add-ons/kernel/busses/random/VirtioRNGDevice.cpp new file mode 100644 index 0000000..7aa9ae0 --- /dev/null +++ b/src/add-ons/kernel/busses/random/VirtioRNGDevice.cpp @@ -0,0 +1,134 @@ +/* + * Copyright 2013, Jérôme Duval, korli@xxxxxxxxxxxxxxxx. + * Distributed under the terms of the MIT License. + */ + + +#include "VirtioRNGPrivate.h" + +#include <new> +#include <stdlib.h> +#include <string.h> + +#include <util/AutoLock.h> + + +const char * +get_feature_name(uint32 feature) +{ + switch (feature) { + } + return NULL; +} + + +VirtioRNGDevice::VirtioRNGDevice(device_node *node) + : + fNode(node), + fVirtio(NULL), + fVirtioDevice(NULL), + fStatus(B_NO_INIT), + fOffset(BUFFER_SIZE) +{ + CALLED(); + + B_INITIALIZE_SPINLOCK(&fInterruptLock); + fInterruptCondition.Init(this, "virtio rng transfer"); + + get_memory_map(fBuffer, BUFFER_SIZE, &fEntry, 1); + + // get the Virtio device from our parent's parent + device_node *parent = gDeviceManager->get_parent_node(node); + device_node *virtioParent = gDeviceManager->get_parent_node(parent); + gDeviceManager->put_node(parent); + + gDeviceManager->get_driver(virtioParent, (driver_module_info **)&fVirtio, + (void **)&fVirtioDevice); + gDeviceManager->put_node(virtioParent); + + fVirtio->negociate_features(fVirtioDevice, + 0, &fFeatures, &get_feature_name); + + fStatus = fVirtio->alloc_queues(fVirtioDevice, 1, &fVirtioQueue); + if (fStatus != B_OK) { + ERROR("queue allocation failed (%s)\n", strerror(fStatus)); + return; + } + + fStatus = fVirtio->setup_interrupt(fVirtioDevice, NULL, this); + if (fStatus != B_OK) { + ERROR("interrupt setup failed (%s)\n", strerror(fStatus)); + return; + } +} + + +VirtioRNGDevice::~VirtioRNGDevice() +{ +} + + +status_t +VirtioRNGDevice::InitCheck() +{ + return fStatus; +} + + +status_t +VirtioRNGDevice::Read(void* _buffer, size_t* _numBytes) +{ + CALLED(); + + if (fOffset >= BUFFER_SIZE) { + { + InterruptsSpinLocker locker(fInterruptLock); + fExpectsInterrupt = true; + fInterruptCondition.Add(&fInterruptConditionEntry); + } + status_t result = fVirtio->queue_request(fVirtioQueue, NULL, &fEntry, + _RequestCallback, this); + if (result != B_OK) { + ERROR("queueing failed (%s)\n", strerror(result)); + return result; + } + + result = fInterruptConditionEntry.Wait(B_CAN_INTERRUPT); + + { + InterruptsSpinLocker locker(fInterruptLock); + fExpectsInterrupt = false; + } + + if (result == B_OK) { + fOffset = 0; + } else if (result != B_INTERRUPTED) { + ERROR("request failed (%s)\n", strerror(result)); + } + } + + if (fOffset < BUFFER_SIZE) { + size_t size = min_c(BUFFER_SIZE - fOffset, *_numBytes); + memcpy(_buffer, fBuffer + fOffset, size); + fOffset += size; + *_numBytes = size; + } else + *_numBytes = 0; + return B_OK; +} + + +void +VirtioRNGDevice::_RequestCallback(void* driverCookie, void* cookie) +{ + VirtioRNGDevice* device = (VirtioRNGDevice*)driverCookie; + device->_RequestInterrupt(); +} + + +void +VirtioRNGDevice::_RequestInterrupt() +{ + SpinLocker locker(fInterruptLock); + fInterruptCondition.NotifyAll(); +} diff --git a/src/add-ons/kernel/busses/random/VirtioRNGPrivate.h b/src/add-ons/kernel/busses/random/VirtioRNGPrivate.h new file mode 100644 index 0000000..60a4921 --- /dev/null +++ b/src/add-ons/kernel/busses/random/VirtioRNGPrivate.h @@ -0,0 +1,67 @@ +/* + * Copyright 2013, Jérôme Duval, korli@xxxxxxxxxxxxxxxx. + * Distributed under the terms of the MIT License. + */ +#ifndef VIRTIO_RNG_PRIVATE_H +#define VIRTIO_RNG_PRIVATE_H + + +#include <condition_variable.h> +#include <lock.h> +#include "random.h" +#include <virtio.h> + + +//#define TRACE_VIRTIO_RNG +#ifdef TRACE_VIRTIO_RNG +# define TRACE(x...) dprintf("virtio_rng: " x) +#else +# define TRACE(x...) ; +#endif +#define ERROR(x...) dprintf("\33[33mvirtio_rng:\33[0m " x) +#define CALLED() TRACE("CALLED %s\n", __PRETTY_FUNCTION__) + + +extern device_manager_info* gDeviceManager; +extern random_for_controller_interface *gRandom; + + +#define BUFFER_SIZE 16 + + +class VirtioRNGDevice { +public: + VirtioRNGDevice(device_node* node); + ~VirtioRNGDevice(); + + status_t InitCheck(); + + status_t Read(void* buffer, size_t* numBytes); + + +private: + static void _RequestCallback(void* driverCookie, + void *cookie); + void _RequestInterrupt(); + + device_node* fNode; + + virtio_device_interface* fVirtio; + virtio_device* fVirtioDevice; + + status_t fStatus; + uint32 fFeatures; + ::virtio_queue fVirtioQueue; + + physical_entry fEntry; + uint8 fBuffer[BUFFER_SIZE]; + uint32 fOffset; + + spinlock fInterruptLock; + ConditionVariable fInterruptCondition; + ConditionVariableEntry fInterruptConditionEntry; + bool fExpectsInterrupt; +}; + + +#endif // VIRTIO_RNG_PRIVATE_H diff --git a/src/add-ons/kernel/busses/random/virtio_rng.cpp b/src/add-ons/kernel/busses/random/virtio_rng.cpp new file mode 100644 index 0000000..951c4eb --- /dev/null +++ b/src/add-ons/kernel/busses/random/virtio_rng.cpp @@ -0,0 +1,197 @@ +/* + * Copyright 2013, Jérôme Duval, korli@xxxxxxxxxxxxxxxx. + * Distributed under the terms of the MIT License. + */ + + +#include "VirtioRNGPrivate.h" + +#include <new> +#include <stdlib.h> +#include <string.h> + + +#define VIRTIO_RNG_CONTROLLER_PRETTY_NAME "Virtio RNG Device" + +#define VIRTIO_RNG_DRIVER_MODULE_NAME "busses/random/virtio_rng/driver_v1" +#define VIRTIO_RNG_DEVICE_MODULE_NAME "busses/random/virtio_rng/device_v1" + + +device_manager_info *gDeviceManager; +random_for_controller_interface *gRandom; + + +// #pragma mark - Random module interface + + +static status_t +sim_init_bus(device_node *node, void **_cookie) +{ + CALLED(); + + VirtioRNGDevice *device = new(std::nothrow) + VirtioRNGDevice(node); + if (device == NULL) + return B_NO_MEMORY; + status_t status = device->InitCheck(); + if (status < B_OK) { + delete device; + return status; + } + + *_cookie = device; + return B_OK; +} + + +static void +sim_uninit_bus(void *cookie) +{ + CALLED(); + VirtioRNGDevice *device = (VirtioRNGDevice*)cookie; + + delete device; +} + + +static status_t +sim_read(void* cookie, void *_buffer, size_t *_numBytes) +{ + VirtioRNGDevice *device = (VirtioRNGDevice*)cookie; + return device->Read(_buffer, _numBytes); +} + + +// #pragma mark - Driver module interface + + +static float +virtio_rng_supports_device(device_node *parent) +{ + const char *bus; + uint16 deviceType; + + // make sure parent is really the Virtio bus manager + if (gDeviceManager->get_attr_string(parent, B_DEVICE_BUS, &bus, false)) + return -1; + + if (strcmp(bus, "virtio")) + return 0.0; + + // check whether it's really a Virtio Entropy Device + if (gDeviceManager->get_attr_uint16(parent, VIRTIO_DEVICE_TYPE_ITEM, + &deviceType, true) != B_OK || deviceType != VIRTIO_DEVICE_ID_ENTROPY) + return 0.0; + + TRACE("Virtio RNG device found!\n"); + + return 0.6f; +} + + +static status_t +virtio_rng_register_device(device_node *parent) +{ + CALLED(); + + device_attr attrs[] = { + { NULL } + }; + + return gDeviceManager->register_node(parent, VIRTIO_RNG_DRIVER_MODULE_NAME, + attrs, NULL, NULL); +} + + +static status_t +virtio_rng_init_driver(device_node *node, void **_cookie) +{ + CALLED(); + *_cookie = node; + return B_OK; +} + + +static status_t +virtio_rng_register_child_devices(void *cookie) +{ + CALLED(); + device_node *node = (device_node *)cookie; + + device_attr attrs[] = { + { B_DEVICE_FIXED_CHILD, B_STRING_TYPE, + { string: RANDOM_FOR_CONTROLLER_MODULE_NAME }}, + { B_DEVICE_PRETTY_NAME, B_STRING_TYPE, + { string: VIRTIO_RNG_CONTROLLER_PRETTY_NAME }}, + { NULL } + }; + + return gDeviceManager->register_node(node, + VIRTIO_RNG_DEVICE_MODULE_NAME, attrs, NULL, NULL); +} + + +static status_t +std_ops(int32 op, ...) +{ + switch (op) { + case B_MODULE_INIT: + case B_MODULE_UNINIT: + return B_OK; + + default: + return B_ERROR; + } +} + + +static random_module_info sVirtioRNGDeviceInterface = { + { + { + VIRTIO_RNG_DEVICE_MODULE_NAME, + 0, + std_ops + }, + NULL, // supported devices + NULL, // register node + sim_init_bus, + sim_uninit_bus, + NULL, // register child devices + NULL, // rescan + NULL // bus_removed + }, + + sim_read, + NULL // write + +}; + + +static driver_module_info sVirtioRNGDriver = { + { + VIRTIO_RNG_DRIVER_MODULE_NAME, + 0, + std_ops + }, + virtio_rng_supports_device, + virtio_rng_register_device, + virtio_rng_init_driver, + NULL, // uninit_driver, + virtio_rng_register_child_devices, + NULL, // rescan + NULL, // device_removed +}; + + +module_dependency module_dependencies[] = { + { B_DEVICE_MANAGER_MODULE_NAME, (module_info **)&gDeviceManager }, + { RANDOM_FOR_CONTROLLER_MODULE_NAME, (module_info **)&gRandom }, + {} +}; + + +module_info *modules[] = { + (module_info *)&sVirtioRNGDriver, + (module_info *)&sVirtioRNGDeviceInterface, + NULL +}; ############################################################################ Revision: hrev45998 Commit: 86af5f159bbd93b977407e8df5ac5f5fe04c2b05 URL: http://cgit.haiku-os.org/haiku/commit/?id=86af5f1 Author: Jérôme Duval <jerome.duval@xxxxxxxxx> Date: Thu Aug 29 16:43:51 2013 UTC VirtioRNG: add to the image ---------------------------------------------------------------------------- diff --git a/build/jam/HaikuImage b/build/jam/HaikuImage index 88da45e..84b2500 100644 --- a/build/jam/HaikuImage +++ b/build/jam/HaikuImage @@ -226,6 +226,8 @@ if $(HAIKU_ATA_STACK) = 1 { : generic_ide_pci it8211 legacy_sata silicon_image_3112 ide_isa@x86 ; } +AddFilesToHaikuImage system add-ons kernel busses random + : virtio_rng ; AddFilesToHaikuImage system add-ons kernel busses scsi : ahci virtio_scsi ; AddFilesToHaikuImage system add-ons kernel busses usb