platform_drv: provide Virtio PCI information

Ref genodelabs/genode#4578
This commit is contained in:
Stefan Kalkowski 2022-09-20 12:01:21 +02:00 committed by Christian Helmuth
parent de0c339e0b
commit fdba7259ab
4 changed files with 129 additions and 5 deletions

View File

@ -228,7 +228,7 @@ class Driver::Device : private List_model<Device>::Element
{
unsigned idx = 0;
_io_mem_list.for_each([&] (Io_mem const & iomem) {
fn(idx++, iomem.range); });
fn(idx++, iomem.range, iomem.bar); });
}
template <typename FN> void for_each_io_port_range(FN const & fn) const

View File

@ -159,7 +159,7 @@ Device_component::Device_component(Registry<Device_component> & registry,
new (session.heap()) Irq(_irq_registry, idx, nr, type, polarity, mode);
});
device.for_each_io_mem([&] (unsigned idx, Range range)
device.for_each_io_mem([&] (unsigned idx, Range range, Device::Pci_bar)
{
session.ram_quota_guard().withdraw(Ram_quota{Io_mem_session::RAM_QUOTA});
_ram_quota += Io_mem_session::RAM_QUOTA;

View File

@ -21,6 +21,7 @@
#include <pci_uhci.h>
#include <pci_intel_graphics.h>
#include <pci_hd_audio.h>
#include <pci_virtio.h>
using namespace Genode;
using namespace Pci;
@ -51,7 +52,8 @@ struct Config_helper
Config::Command::Bus_master_enable::set(cmd, 1);
/* enable memory space when I/O mem is defined */
_dev.for_each_io_mem([&] (unsigned, Driver::Device::Io_mem::Range) {
_dev.for_each_io_mem([&] (unsigned, Driver::Device::Io_mem::Range,
Driver::Device::Pci_bar) {
Config::Command::Memory_space_enable::set(cmd, 1); });
/* enable i/o space when I/O ports are defined */
@ -182,6 +184,9 @@ void Driver::pci_device_specific_info(Device const & dev,
Device_model & model,
Xml_generator & xml)
{
dev.for_pci_config([&] (Device::Pci_config const cfg) {
Driver::pci_intel_graphics_info(cfg, env, model, xml); });
dev.for_pci_config([&] (Device::Pci_config const cfg)
{
Driver::pci_intel_graphics_info(cfg, env, model, xml);
Driver::pci_virtio_info(dev, cfg, env, xml);
});
}

View File

@ -0,0 +1,119 @@
/*
* \brief Platform driver - PCI Virtio utilities
* \author Stefan Kalkowski
* \date 2022-09-19
*/
/*
* Copyright (C) 2022 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 <util/mmio.h>
#include <pci/config.h>
#include <device.h>
namespace Driver {
void pci_virtio_info(Device const & dev,
Device::Pci_config cfg,
Env & env,
Xml_generator & xml);
}
void Driver::pci_virtio_info(Device const & dev,
Device::Pci_config cfg,
Env & env,
Xml_generator & xml)
{
enum { VENDOR_RED_HAT = 0x1af4 };
if (cfg.vendor_id != VENDOR_RED_HAT)
return;
struct Virtio : Pci::Config
{
struct Capability : Pci::Config::Pci_capability
{
enum { COMMON = 1, NOTIFY = 2, ISR = 3, DEVICE = 4 };
struct Type : Register<0x3, 8> {};
struct Bar : Register<0x4, 8> {};
struct Offset : Register<0x8, 32> {};
struct Length : Register<0xc, 32> {};
struct Offset_factor : Register<0x10, 32> {};
using Pci::Config::Pci_capability::Pci_capability;
bool valid()
{
switch (read<Type>()) {
case COMMON:
case NOTIFY:
case ISR:
case DEVICE:
return true;
};
return false;
}
String<16> name()
{
switch (read<Type>()) {
case COMMON: return "common";
case NOTIFY: return "notify";
case ISR: return "irq_status";
case DEVICE: return "device";
};
return "unknown";
}
};
using Pci::Config::Config;
void capability(Capability & cap,
Driver::Device const & dev,
Xml_generator & xml)
{
unsigned idx = ~0U;
dev.for_each_io_mem([&] (unsigned i,
Driver::Device::Io_mem::Range,
Driver::Device::Pci_bar bar) {
if (bar.number == cap.read<Capability::Bar>()) idx = i; });
xml.node("virtio_range", [&] () {
xml.attribute("type", cap.name());
xml.attribute("index", idx);
xml.attribute("offset", cap.read<Capability::Offset>());
xml.attribute("size", cap.read<Capability::Length>());
if (cap.read<Capability::Type>() == Capability::NOTIFY)
xml.attribute("factor",
cap.read<Capability::Offset_factor>());
});
}
void for_each_capability(Driver::Device const & dev,
Xml_generator & xml)
{
if (!read<Status::Capabilities>())
return;
uint16_t off = read<Capability_pointer>();
while (off) {
Capability cap(base() + off);
if (cap.read<Pci_capability::Id>() ==
Pci_capability::Id::VENDOR &&
cap.valid())
capability(cap, dev, xml);
off = cap.read<Pci_capability::Pointer>();
}
}
};
Attached_io_mem_dataspace io_mem(env, cfg.addr, 0x1000);
Virtio config((addr_t)io_mem.local_addr<void>());
config.for_each_capability(dev, xml);
}