mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-23 15:32:25 +00:00
os: add platform_drv config generator for virt_qemu
The VirtIO device configuration on Qemu is dynamic. The order and presence of different command line switches affects base address and interrupt assignment of each device. One could probably hard-code the necessary switches and resulting XML ARM platform driver configuration in each run script, but this seems like troublesome and hard to maintain solution. This patch explores an alternative approach to the problem. It implements a ROM driver which probes the address space region Qemu virt machines assign to VirtIO MMIO devices and exposes the result as XML via a ROM session. This XML output can be fed directly as config to the generic ARM platform driver. Ref #3825
This commit is contained in:
parent
fe0ad0addb
commit
9bd548c4bd
2
repos/os/recipes/src/virtdev_rom/content.mk
Normal file
2
repos/os/recipes/src/virtdev_rom/content.mk
Normal file
@ -0,0 +1,2 @@
|
||||
SRC_DIR = src/drivers/virtdev_rom
|
||||
include $(GENODE_DIR)/repos/base/recipes/src/content.inc
|
1
repos/os/recipes/src/virtdev_rom/hash
Normal file
1
repos/os/recipes/src/virtdev_rom/hash
Normal file
@ -0,0 +1 @@
|
||||
2020-07-03 e1c0e261929b71468814fdbcba02c7e0f6455c25
|
2
repos/os/recipes/src/virtdev_rom/used_apis
Normal file
2
repos/os/recipes/src/virtdev_rom/used_apis
Normal file
@ -0,0 +1,2 @@
|
||||
base
|
||||
os
|
31
repos/os/src/drivers/virtdev_rom/README
Normal file
31
repos/os/src/drivers/virtdev_rom/README
Normal file
@ -0,0 +1,31 @@
|
||||
This driver probes available VirtIO MMIO devices on Qemu's virt platform and
|
||||
exports the results in XML format via a ROM session. The exported ROM module
|
||||
is suitable as configuration for the generic ARM platform driver.
|
||||
|
||||
This driver can currently recognize NIC, block, console, RNG, GPU, and
|
||||
input devices. When a device of a given type is detected, it is assigned a
|
||||
name based on its type and index on a bus. For example, if the system has
|
||||
two VirtIO NIC devices, their names will be "nic0" and "nic1".
|
||||
|
||||
To simplify probing devices of the same type, each XML device node has
|
||||
an additional "type" property node. The value of this property is simply
|
||||
set to a string indicating device type, without any extra indices, e.g.,
|
||||
"nic", "gpu", "input", etc.
|
||||
|
||||
! <device name="nic0">
|
||||
! <resource ... />
|
||||
! <property name="type" value="nic"/>
|
||||
! </device>
|
||||
|
||||
Configuration
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
The virtdev_rom component appends the unmodified content of its own configuration
|
||||
ROM to its output. This makes it possible to easily append extra policies
|
||||
to the device configuration produced by the driver, e.g.,:
|
||||
|
||||
! <config>
|
||||
! <policy label_prefix="virtio_nic"> <device name="nic0"> </policy>
|
||||
! <policy label_prefix="virtio_kbd> <device name="input0"> </policy>
|
||||
! <policy label_prefix="virtio_mouse> <device name="input1"> </policy>
|
||||
! </config>
|
200
repos/os/src/drivers/virtdev_rom/main.cc
Normal file
200
repos/os/src/drivers/virtdev_rom/main.cc
Normal file
@ -0,0 +1,200 @@
|
||||
/*
|
||||
* \brief Virt Qemu device config generator for ARM platform driver
|
||||
* \author Piotr Tworek
|
||||
* \date 2020-07-01
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2020 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU Affero General Public License version 3.
|
||||
*/
|
||||
|
||||
#include <base/attached_rom_dataspace.h>
|
||||
#include <base/component.h>
|
||||
#include <base/env.h>
|
||||
#include <base/heap.h>
|
||||
#include <base/log.h>
|
||||
#include <os/attached_mmio.h>
|
||||
#include <rom_session/rom_session.h>
|
||||
#include <root/component.h>
|
||||
#include <util/xml_generator.h>
|
||||
|
||||
namespace Virtdev_rom {
|
||||
using namespace Genode;
|
||||
class Session_component;
|
||||
class Root;
|
||||
struct Main;
|
||||
};
|
||||
|
||||
|
||||
class Virtdev_rom::Session_component : public Rpc_object<Rom_session>
|
||||
{
|
||||
private:
|
||||
|
||||
/*
|
||||
* Noncopyable
|
||||
*/
|
||||
Session_component(Session_component const &) = delete;
|
||||
Session_component &operator = (Session_component const &) = delete;
|
||||
|
||||
Rom_dataspace_capability const _rom_cap;
|
||||
|
||||
public:
|
||||
|
||||
Session_component(Rom_dataspace_capability cap) : _rom_cap(cap)
|
||||
{ }
|
||||
|
||||
Rom_dataspace_capability dataspace() override { return _rom_cap; }
|
||||
|
||||
void sigh(Signal_context_capability) override { }
|
||||
};
|
||||
|
||||
|
||||
class Virtdev_rom::Root : public Root_component<Session_component>
|
||||
{
|
||||
private:
|
||||
|
||||
/*
|
||||
* Noncopyable
|
||||
*/
|
||||
Root(Root const &) = delete;
|
||||
Root &operator = (Root const &) = delete;
|
||||
|
||||
Env &_env;
|
||||
Ram_dataspace_capability _ds;
|
||||
|
||||
Session_component *_create_session(const char *) override
|
||||
{
|
||||
auto cap = static_cap_cast<Dataspace>(_ds);
|
||||
return new (md_alloc()) Session_component(
|
||||
static_cap_cast<Rom_dataspace>(cap));
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
Root(Env &env, Allocator &md_alloc, Ram_dataspace_capability &cap)
|
||||
: Root_component<Session_component>(env.ep(), md_alloc),
|
||||
_env(env),
|
||||
_ds(cap)
|
||||
{ }
|
||||
};
|
||||
|
||||
|
||||
struct Virtdev_rom::Main
|
||||
{
|
||||
enum {
|
||||
/* Taken from include/hw/arm/virt.h in Qemu source tree. */
|
||||
NUM_VIRTIO_TRANSPORTS = 32,
|
||||
/* Taken from hw/arm/virt.c in Qemu source tree. */
|
||||
BASE_ADDRESS = 0x0A000000,
|
||||
DEVICE_SIZE = 0x200,
|
||||
IRQ_BASE = 48,
|
||||
VIRTIO_MMIO_MAGIC = 0x74726976,
|
||||
};
|
||||
|
||||
enum { MAX_ROM_SIZE = 4096, DEVICE_NAME_LEN = 64 };
|
||||
|
||||
Env &_env;
|
||||
Ram_dataspace_capability _ds { _env.ram().alloc(MAX_ROM_SIZE) };
|
||||
Sliced_heap _heap { _env.ram(), _env.rm() };
|
||||
Virtdev_rom::Root _root { _env, _heap, _ds };
|
||||
|
||||
struct Device : public Attached_mmio
|
||||
{
|
||||
struct Magic : Register<0x000, 32> { };
|
||||
struct Id : Register<0x008, 32> {
|
||||
enum Value {
|
||||
INVALID = 0,
|
||||
NIC = 1,
|
||||
BLOCK = 2,
|
||||
CONSOLE = 3,
|
||||
RNG = 4,
|
||||
GPU = 16,
|
||||
INPUT = 18,
|
||||
MAX_VAL = INPUT,
|
||||
};
|
||||
};
|
||||
|
||||
Device(Env &env, addr_t base, size_t size)
|
||||
: Attached_mmio(env, base, size, false) { }
|
||||
};
|
||||
|
||||
static char const *_name_for_id(unsigned id)
|
||||
{
|
||||
switch (id) {
|
||||
case Device::Id::NIC : return "nic";
|
||||
case Device::Id::BLOCK : return "block";
|
||||
case Device::Id::CONSOLE : return "console";
|
||||
case Device::Id::RNG : return "rng";
|
||||
case Device::Id::GPU : return "gpu";
|
||||
case Device::Id::INPUT : return "input";
|
||||
default: {
|
||||
warning("Unhandled VirtIO device ID: ", Hex(id));
|
||||
return "virtio";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void _probe_devices()
|
||||
{
|
||||
Attached_dataspace ds(_env.rm(), _ds);
|
||||
Attached_rom_dataspace config { _env, "config" };
|
||||
|
||||
Xml_generator xml(ds.local_addr<char>(), ds.size(), "config", [&] ()
|
||||
{
|
||||
uint8_t device_type_idx[Device::Id::MAX_VAL] = { 0 };
|
||||
|
||||
for (size_t idx = 0; idx < NUM_VIRTIO_TRANSPORTS; ++idx) {
|
||||
addr_t addr = BASE_ADDRESS + idx * DEVICE_SIZE;
|
||||
Device device { _env, BASE_ADDRESS + idx * DEVICE_SIZE, DEVICE_SIZE };
|
||||
|
||||
if (device.read<Device::Magic>() != VIRTIO_MMIO_MAGIC) {
|
||||
warning("Found non VirrtIO MMIO device @ ", addr);
|
||||
continue;
|
||||
}
|
||||
|
||||
auto id = device.read<Device::Id>();
|
||||
if (id == Device::Id::INVALID)
|
||||
continue;
|
||||
|
||||
xml.node("device", [&] ()
|
||||
{
|
||||
static char name[DEVICE_NAME_LEN];
|
||||
snprintf(name, sizeof(name), "%s%u", _name_for_id(id), device_type_idx[id - 1]++);
|
||||
xml.attribute("name", name);
|
||||
xml.node("io_mem", [&] () {
|
||||
xml.attribute("address", addr);
|
||||
xml.attribute("size", DEVICE_SIZE);
|
||||
});
|
||||
xml.node("irq", [&] () {
|
||||
xml.attribute("number", IRQ_BASE + idx);
|
||||
});
|
||||
xml.node("property", [&] () {
|
||||
xml.attribute("name", "type");
|
||||
xml.attribute("value", _name_for_id(id));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
config.xml().with_raw_content([&] (char const *txt, size_t sz) {
|
||||
xml.append(txt, sz);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
Main(Env &env) : _env(env)
|
||||
{
|
||||
_probe_devices();
|
||||
env.parent().announce(_env.ep().manage(_root));
|
||||
}
|
||||
|
||||
~Main() { _env.ram().free(_ds); }
|
||||
};
|
||||
|
||||
|
||||
void Component::construct(Genode::Env &env)
|
||||
{
|
||||
static Virtdev_rom::Main main(env);
|
||||
}
|
3
repos/os/src/drivers/virtdev_rom/target.mk
Normal file
3
repos/os/src/drivers/virtdev_rom/target.mk
Normal file
@ -0,0 +1,3 @@
|
||||
TARGET = virtdev_rom
|
||||
SRC_CC = main.cc
|
||||
LIBS = base
|
Loading…
Reference in New Issue
Block a user