sculpt: host NVMe driver in runtime

As the NVMe driver was the last remaining driver controlled by the
driver manager, this patch removes the 'drivers -> dynamic' subsystem
along with the driver manager from sculpt/drivers/pc.

Issue #5150
This commit is contained in:
Norman Feske 2024-03-22 15:22:11 +01:00 committed by Christian Helmuth
parent 206bf856bb
commit fe596f2219
13 changed files with 270 additions and 82 deletions

View File

@ -11,8 +11,6 @@
<service name="LOG"/>
<service name="Timer"/>
<service name="Report"/>
<service name="Capture"/>
<service name="Event"/>
</parent-provides>
<report child_caps="true" child_ram="true" init_caps="true" init_ram="true" delay_ms="5000"/>
@ -23,30 +21,18 @@
<default caps="100"/>
<service name="Block">
<default-policy> <child name="dynamic"/> </default-policy> </service>
<service name="Platform">
<default-policy> <child name="platform_drv"/> </default-policy> </service>
<service name="Gpu">
<default-policy> <child name="dynamic"/> </default-policy> </service>
<start name="report_rom">
<resource name="RAM" quantum="2M"/>
<provides> <service name="Report"/> <service name="ROM"/> </provides>
<config verbose="no">
<policy label="pci_decode -> system" report="acpi_drv -> acpi"/>
<policy label="platform_drv -> acpi" report="acpi_drv -> acpi"/>
<policy label="platform_drv -> devices" report="pci_decode -> devices"/>
<policy label="dynamic -> config" report="driver_manager -> init.config"/>
<policy label="driver_manager -> devices" report="platform_drv -> devices"/>
<policy label="driver_manager -> dynamic_state" report="dynamic -> state"/>
<policy label="driver_manager -> nvme_ns" report="dynamic -> nvme_ns"/>
<policy label="rom_reporter -> acpi" report="acpi_drv -> acpi"/>
<policy label="rom_reporter -> devices" report="platform_drv -> devices"/>
<policy label="rom_reporter -> pci_devices" report="pci_decode -> devices"/>
<policy label="rom_reporter -> dynamic_state" report="dynamic -> state"/>
<policy label="pci_decode -> system" report="acpi_drv -> acpi"/>
<policy label="platform_drv -> acpi" report="acpi_drv -> acpi"/>
<policy label="platform_drv -> devices" report="pci_decode -> devices"/>
<policy label="rom_reporter -> acpi" report="acpi_drv -> acpi"/>
<policy label="rom_reporter -> devices" report="platform_drv -> devices"/>
</config>
</start>
@ -54,19 +40,13 @@
<resource name="RAM" quantum="1M"/>
<config>
<rom label="acpi"/>
<rom label="pci_devices"/>
<rom label="devices"/>
<rom label="dynamic_state"/>
</config>
<route>
<service name="ROM" label="acpi"> <child name="report_rom"/> </service>
<service name="ROM" label="pci_devices"> <child name="report_rom"/> </service>
<service name="ROM" label="devices"> <child name="report_rom"/> </service>
<service name="ROM" label="dynamic_state"> <child name="report_rom"/> </service>
<service name="Report" label="acpi"> <parent label="acpi"/> </service>
<service name="Report" label="pci_devices"> <parent label="pci_devices"/> </service>
<service name="Report" label="devices"> <parent label="devices"/> </service>
<service name="Report" label="dynamic_state"> <parent label="dynamic -> state"/> </service>
<service name="ROM" label="acpi"> <child name="report_rom"/> </service>
<service name="ROM" label="devices"> <child name="report_rom"/> </service>
<service name="Report" label="acpi"> <parent label="acpi"/> </service>
<service name="Report" label="devices"> <parent label="devices"/> </service>
<service name="LOG"> <parent/> </service>
<service name="PD"> <parent/> </service>
<service name="CPU"> <parent/> </service>
@ -79,7 +59,7 @@
<route>
<service name="Report" label="acpi"> <child name="report_rom"/> </service>
<service name="Report" label="intel_opregion"> <parent label="intel_opregion"/> </service>
<service name="Report" label="smbios_table"> <parent label="smbios_table"/> </service>
<service name="Report" label="smbios_table"> <parent label="smbios_table"/> </service>
<service name="IO_MEM"> <parent/> </service>
<service name="LOG"> <parent/> </service>
<service name="PD"> <parent/> </service>
@ -125,10 +105,10 @@
<config>
<report devices="yes" iommu="yes"/>
<policy label_prefix="runtime -> ps2"> <device name="ps2"/> </policy>
<policy label_prefix="runtime -> vesa_fb" info="yes"> <pci class="VGA"/> </policy>
<policy label_prefix="runtime -> ahci"> <pci class="AHCI"/> </policy>
<policy label_prefix="dynamic -> nvme_drv" info="yes"> <pci class="NVME"/> </policy>
<policy label_prefix="runtime -> usb" info="yes"> <pci class="USB"/> </policy>
<policy label_prefix="runtime -> vesa_fb" info="yes"> <pci class="VGA"/> </policy>
<policy label_prefix="runtime -> ahci"> <pci class="AHCI"/> </policy>
<policy label_prefix="runtime -> nvme" info="yes"> <pci class="NVME"/> </policy>
<policy label_prefix="runtime -> usb" info="yes"> <pci class="USB"/> </policy>
<policy label_prefix="runtime -> intel_gpu" info="yes">
<pci class="VGA"/>
<pci class="ISABRIDGE"/>
@ -140,45 +120,4 @@
</config>
</start>
<start name="driver_manager">
<resource name="RAM" quantum="1M"/>
<route>
<service name="Report" label="init.config"> <child name="report_rom"/> </service>
<service name="Report" label="block_devices"> <parent label="block_devices"/> </service>
<service name="ROM" label="devices"> <child name="report_rom"/> </service>
<service name="ROM" label="nvme_ns"> <child name="report_rom"/> </service>
<service name="ROM" label="dynamic_state"> <child name="report_rom"/> </service>
<service name="LOG"> <parent/> </service>
<service name="PD"> <parent/> </service>
<service name="CPU"> <parent/> </service>
<service name="ROM"> <parent/> </service>
</route>
</start>
<start name="dynamic" caps="2600">
<binary name="init"/>
<resource name="RAM" quantum="1G"/>
<provides>
<service name="Framebuffer"/>
<service name="Block"/>
<service name="Gpu"/>
</provides>
<route>
<service name="Platform"> <child name="platform_drv"/> </service>
<service name="Report" label="nvme_ns"> <child name="report_rom"/> </service>
<service name="Report" label="state"> <child name="report_rom"/> </service>
<service name="Report"> <parent/> </service>
<service name="ROM" label="config"> <child name="report_rom"/> </service>
<service name="LOG"> <parent/> </service>
<service name="PD"> <parent/> </service>
<service name="RM"> <parent/> </service>
<service name="CPU"> <parent/> </service>
<service name="ROM"> <parent/> </service>
<service name="IO_MEM"> <parent/> </service>
<service name="IO_PORT"> <parent/> </service>
<service name="Timer"> <parent/> </service>
<service name="Capture"> <parent/> </service>
</route>
</start>
</config>

View File

@ -329,6 +329,7 @@ struct Sculpt::Main : Input_event_handler,
_usb_driver.with_devices([&] (Xml_node const &usb_devices) {
_storage.update(usb_devices,
Xml_node { "<empty/> " }, /* ahci */
Xml_node { "<empty/> " }, /* nvme */
_block_devices_rom.xml(),
_block_devices_handler);
});

View File

@ -120,6 +120,10 @@ void Graph::_view_selected_node_content(Scope<Depgraph, Frame, Vbox> &s,
if (name == "ahci")
s.sub_scope<Frame>([&] (Scope<Depgraph, Frame, Vbox, Frame> &s) {
s.widget(_ahci_devices_widget); });
if (name == "nvme")
s.sub_scope<Frame>([&] (Scope<Depgraph, Frame, Vbox, Frame> &s) {
s.widget(_nvme_devices_widget); });
}
@ -291,6 +295,7 @@ void Graph::click(Clicked_at const &at, Action &action)
_ram_fs_widget .propagate(at, _sculpt_partition, action);
_block_devices_widget.propagate(at, action);
_ahci_devices_widget .propagate(at, action);
_nvme_devices_widget .propagate(at, action);
_usb_devices_widget .propagate(at, action);
_remove .propagate(at);
@ -303,6 +308,7 @@ void Graph::clack(Clacked_at const &at, Action &action, Ram_fs_widget::Action &r
_ram_fs_widget .propagate(at, ram_fs_action);
_block_devices_widget.propagate(at, action);
_ahci_devices_widget .propagate(at, action);
_nvme_devices_widget .propagate(at, action);
_usb_devices_widget .propagate(at, action);
_remove.propagate(at, [&] {

View File

@ -62,6 +62,10 @@ struct Sculpt::Graph : Widget<Depgraph>
_ahci_devices_widget { Id { "ahci_devices" },
_storage_devices, _sculpt_partition };
Hosted<Depgraph, Frame, Vbox, Frame, Nvme_devices_widget>
_nvme_devices_widget { Id { "nvme_devices" },
_storage_devices, _sculpt_partition };
Hosted<Depgraph, Frame, Vbox, Frame, Usb_devices_widget>
_usb_devices_widget { Id { "usb_devices" },
_storage_devices, _sculpt_partition };
@ -104,6 +108,7 @@ struct Sculpt::Graph : Widget<Depgraph>
{
_block_devices_widget.reset_operation();
_ahci_devices_widget.reset_operation();
_nvme_devices_widget.reset_operation();
_usb_devices_widget.reset_operation();
}
};

View File

@ -48,6 +48,7 @@
#include <ps2_driver.h>
#include <usb_driver.h>
#include <ahci_driver.h>
#include <nvme_driver.h>
#include <gui.h>
#include <keyboard_focus.h>
#include <network.h>
@ -78,7 +79,8 @@ struct Sculpt::Main : Input_event_handler,
Popup_dialog::Refresh,
Screensaver::Action,
Usb_driver::Action,
Ahci_driver::Action
Ahci_driver::Action,
Nvme_driver::Action
{
Env &_env;
@ -228,6 +230,7 @@ struct Sculpt::Main : Input_event_handler,
_fb_driver .update(_child_states, _board_info, _platform.xml());
_ps2_driver .update(_child_states, _board_info);
_ahci_driver.update(_child_states, _board_info);
_nvme_driver.update(_child_states, _board_info);
_update_usb_drivers();
update_network_dialog();
@ -238,6 +241,7 @@ struct Sculpt::Main : Input_event_handler,
Fb_driver _fb_driver { };
Usb_driver _usb_driver { _env, *this };
Ahci_driver _ahci_driver { _env, *this };
Nvme_driver _nvme_driver { _env, *this };
void _update_usb_drivers()
{
@ -275,9 +279,11 @@ struct Sculpt::Main : Input_event_handler,
_block_devices_rom.update();
_usb_driver.with_devices([&] (Xml_node const &usb_devices) {
_ahci_driver.with_ahci_ports([&] (Xml_node const &ahci_ports) {
_storage.update(usb_devices, ahci_ports,
_block_devices_rom.xml(),
_block_devices_handler);
_nvme_driver.with_nvme_namespaces([&] (Xml_node const &nvme_namespaces) {
_storage.update(usb_devices, ahci_ports, nvme_namespaces,
_block_devices_rom.xml(),
_block_devices_handler);
});
});
});
@ -305,6 +311,11 @@ struct Sculpt::Main : Input_event_handler,
*/
void handle_ahci_discovered() override { _handle_block_devices(); }
/**
* Nvme_driver::Action
*/
void handle_nvme_discovered() override { _handle_block_devices(); }
/**
* Storage::Action interface
*/
@ -2131,6 +2142,7 @@ void Sculpt::Main::_generate_runtime_config(Xml_generator &xml) const
_fb_driver .gen_start_nodes(xml);
_usb_driver .gen_start_nodes(xml);
_ahci_driver.gen_start_node (xml);
_nvme_driver.gen_start_node (xml);
_dialog_runtime.gen_start_nodes(xml);

View File

@ -52,7 +52,7 @@ struct Sculpt::Board_info
LAN = 0x20000,
VGA = 0x30000,
AHCI = 0x10601,
NVME = 0x10800,
NVME = 0x10802,
UHCI = 0xc0300, OHCI = 0xc0310, EHCI = 0xc0320, XHCI = 0xc0330,
};

View File

@ -0,0 +1,57 @@
/*
* \brief Representation of NVMe devices
* \author Norman Feske
* \date 2024-04-22
*/
/*
* Copyright (C) 2024 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.
*/
#ifndef _MODEL__NVME_DEVICE_H_
#define _MODEL__NVME_DEVICE_H_
#include <model/storage_device.h>
namespace Sculpt {
struct Nvme_device;
using Nvme_devices = List_model<Nvme_device>;
};
struct Sculpt::Nvme_device : List_model<Nvme_device>::Element, Storage_device
{
using Model = String<16>;
Model const model;
static Port _port(Xml_node const &node)
{
return node.attribute_value("id", Port());
}
static Capacity _capacity(Xml_node const &node)
{
return { node.attribute_value("block_size", 0ULL)
* node.attribute_value("block_count", 0ULL) };
}
Nvme_device(Env &env, Allocator &alloc, Signal_context_capability sigh,
Model const &model, Xml_node const &node)
:
Storage_device(env, alloc, Storage_device::Provider::RUNTIME,
"nvme", _port(node), _capacity(node), sigh),
model(model)
{ }
bool matches(Xml_node const &node) const { return _port(node) == port; }
static bool type_matches(Xml_node const &) { return true; }
};
#endif /* _MODEL__NVME_DEVICE_H_ */

View File

@ -17,6 +17,7 @@
#include <types.h>
#include <model/block_device.h>
#include <model/ahci_device.h>
#include <model/nvme_device.h>
#include <model/usb_storage_device.h>
namespace Sculpt { struct Storage_devices; }
@ -26,6 +27,7 @@ struct Sculpt::Storage_devices
{
Block_devices block_devices { };
Ahci_devices ahci_devices { };
Nvme_devices nvme_devices { };
Usb_storage_devices usb_storage_devices { };
bool _block_devices_report_valid = false;
@ -86,6 +88,32 @@ struct Sculpt::Storage_devices
return progress;
}
bool update_nvme_devices_from_xml(Env &env, Allocator &alloc, Xml_node node,
Signal_context_capability sigh)
{
auto const model = node.attribute_value("model", Nvme_device::Model());
bool progress = false;
nvme_devices.update_from_xml(node,
/* create */
[&] (Xml_node const &node) -> Nvme_device & {
progress = true;
return *new (alloc) Nvme_device(env, alloc, sigh, model, node);
},
/* destroy */
[&] (Nvme_device &a) {
destroy(alloc, &a);
progress = true;
},
/* update */
[&] (Nvme_device &, Xml_node const &) { }
);
return progress;
}
/**
* Update 'usb_storage_devices' from USB devices report
*
@ -154,6 +182,9 @@ struct Sculpt::Storage_devices
ahci_devices.for_each([&] (Ahci_device const &dev) {
fn(dev); });
nvme_devices.for_each([&] (Nvme_device const &dev) {
fn(dev); });
usb_storage_devices.for_each([&] (Usb_storage_device const &dev) {
fn(dev); });
}
@ -167,6 +198,9 @@ struct Sculpt::Storage_devices
ahci_devices.for_each([&] (Ahci_device &dev) {
fn(dev); });
nvme_devices.for_each([&] (Nvme_device &dev) {
fn(dev); });
usb_storage_devices.for_each([&] (Usb_storage_device &dev) {
fn(dev); });
}

View File

@ -61,6 +61,7 @@ struct Sculpt::Storage_target
{
bool const usb = (Label(Cstring(device.string(), 3)) == "usb");
bool const ahci = (Label(Cstring(device.string(), 4)) == "ahci");
bool const nvme = (Label(Cstring(device.string(), 4)) == "nvme");
bool const whole_device = !partition.valid();
@ -69,7 +70,7 @@ struct Sculpt::Storage_target
if (whole_device) {
if (usb || ahci)
if (usb || ahci || nvme)
xml.node("child", [&] () {
xml.attribute("name", device);
if (port.valid())

View File

@ -0,0 +1,96 @@
/*
* \brief Sculpt NVME-driver management
* \author Norman Feske
* \date 2024-03-21
*/
/*
* Copyright (C) 2024 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.
*/
#ifndef _NVME_DRIVER_H_
#define _NVME_DRIVER_H_
/* Genode includes */
#include <block_session/block_session.h>
/* local includes */
#include <model/child_exit_state.h>
#include <model/board_info.h>
#include <runtime.h>
namespace Sculpt { struct Nvme_driver; }
struct Sculpt::Nvme_driver : private Noncopyable
{
struct Action : Interface
{
virtual void handle_nvme_discovered() = 0;
};
Env &_env;
Action &_action;
Constructible<Child_state> _nvme { };
Attached_rom_dataspace _namespaces { _env, "report -> runtime/nvme/controller" };
Signal_handler<Nvme_driver> _namespaces_handler {
_env.ep(), *this, &Nvme_driver::_handle_namespaces };
void _handle_namespaces()
{
_namespaces.update();
_action.handle_nvme_discovered();
}
Nvme_driver(Env &env, Action &action) : _env(env), _action(action)
{
_namespaces.sigh(_namespaces_handler);
_namespaces_handler.local_submit();
}
void gen_start_node(Xml_generator &xml) const
{
if (!_nvme.constructed())
return;
xml.node("start", [&] {
_nvme->gen_start_node_content(xml);
gen_named_node(xml, "binary", "nvme_drv");
gen_provides<Block::Session>(xml);
xml.node("config", [&] {
xml.node("report", [&] { xml.attribute("namespaces", "yes"); });
xml.node("policy", [&] {
xml.attribute("label", 1);
xml.attribute("namespace", 1);
xml.attribute("writeable", "yes"); });
});
xml.node("route", [&] {
gen_parent_route<Platform::Session>(xml);
gen_parent_rom_route(xml, "system", "config -> managed/system");
gen_parent_route<Rom_session> (xml);
gen_parent_route<Cpu_session> (xml);
gen_parent_route<Pd_session> (xml);
gen_parent_route<Log_session> (xml);
gen_parent_route<Timer::Session> (xml);
gen_parent_route<Report::Session> (xml);
});
});
};
void update(Registry<Child_state> &registry, Board_info const &board_info)
{
_nvme.conditional(board_info.nvme_present,
registry, "nvme", Priority::DEFAULT,
Ram_quota { 8*1024*1024 }, Cap_quota { 100 });
}
void with_nvme_namespaces(auto const &fn) const { fn(_namespaces.xml()); }
};
#endif /* _NVME_DRIVER_H_ */

View File

@ -17,6 +17,7 @@
void Sculpt::Storage::update(Xml_node const &usb_devices,
Xml_node const &ahci_ports,
Xml_node const &nvme_namespaces,
Xml_node const &block_devices,
Signal_context_capability sigh)
{
@ -42,6 +43,15 @@ void Sculpt::Storage::update(Xml_node const &usb_devices,
process_part_block_report(dev); });
}
{
reconfigure_runtime |=
_storage_devices.update_nvme_devices_from_xml(_env, _alloc, nvme_namespaces,
sigh);
_storage_devices.nvme_devices.for_each([&] (Nvme_device &dev) {
process_part_block_report(dev); });
}
{
_storage_devices.update_block_devices_from_xml(_env, _alloc, block_devices,
sigh);

View File

@ -54,7 +54,7 @@ struct Sculpt::Storage : Storage_device_widget::Action, Ram_fs_widget::Action
Inspect_view_version _inspect_view_version { 0 };
void update(Xml_node const &usb_devices, Xml_node const &ahci_ports,
Xml_node const &block_devices,
Xml_node const &nvme_namespaces, Xml_node const &block_devices,
Signal_context_capability sigh);
/*

View File

@ -184,6 +184,33 @@ struct Sculpt::Ahci_devices_widget : Storage_devices_widget_base
};
namespace Sculpt { struct Nvme_devices_widget; }
struct Sculpt::Nvme_devices_widget : Storage_devices_widget_base
{
using Storage_devices_widget_base::Storage_devices_widget_base;
void view(Scope<Vbox> &s) const
{
s.sub_scope<Min_ex>(35);
_storage_devices.nvme_devices.for_each([&] (Nvme_device const &dev) {
Hosted<Vbox, Storage_device_button> button { Id { dev.name() }, dev.model };
_view_device(s, dev, button);
});
}
void click(Clicked_at const &at, Storage_device_widget::Action &action)
{
_click_device<Storage_device_button>(at, action);
}
void clack(Clacked_at const &at, Storage_device_widget::Action &action)
{
_clack_device(at, action);
}
};
namespace Sculpt { struct Usb_storage_device_button; }
struct Sculpt::Usb_storage_device_button : Widget<Button>