From f11d2b5b5460a9676820138a4b8a9ae6a3166720 Mon Sep 17 00:00:00 2001 From: Stefan Kalkowski Date: Thu, 2 Dec 2021 17:18:41 +0100 Subject: [PATCH] autopilot: automated stress test for platform_drv Fix #4330 --- repos/os/run/platform_drv.run | 176 +++++++++++++++++ repos/os/src/test/platform_drv/main.cc | 228 +++++++++++++++++++++++ repos/os/src/test/platform_drv/target.mk | 4 + tool/autopilot.list | 1 + 4 files changed, 409 insertions(+) create mode 100644 repos/os/run/platform_drv.run create mode 100644 repos/os/src/test/platform_drv/main.cc create mode 100644 repos/os/src/test/platform_drv/target.mk diff --git a/repos/os/run/platform_drv.run b/repos/os/run/platform_drv.run new file mode 100644 index 0000000000..6bdaadce94 --- /dev/null +++ b/repos/os/run/platform_drv.run @@ -0,0 +1,176 @@ +if { ![have_board pbxa9] } { + puts "Platform is unsupported." + exit 0 +} + +create_boot_directory + +import_from_depot [depot_user]/src/[base_src] \ + [depot_user]/src/init \ + [depot_user]/src/fs_report \ + [depot_user]/src/fs_rom \ + [depot_user]/src/platform_drv \ + [depot_user]/src/vfs_import \ + [depot_user]/src/vfs + +build { test/platform_drv } + +install_config { + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +} + + +build_boot_image { test-platform_drv } + +append qemu_args "-nographic " + +set good_string { +[init -> test-platform_drv] +[init -> test-platform_drv] +[init -> test-platform_drv] +[init -> test-platform_drv] +[init -> test-platform_drv] +[init -> test-platform_drv] +[init -> test-platform_drv] +[init -> test-platform_drv] +[init -> test-platform_drv] +[init -> test-platform_drv] +[init -> test-platform_drv] +[init -> test-platform_drv] +[init -> test-platform_drv] +[init -> test-platform_drv] +[init -> test-platform_drv] +[init -> test-platform_drv] +[init -> test-platform_drv] +[init -> test-platform_drv] +[init -> test-platform_drv] +[init -> test-platform_drv] +[init -> test-platform_drv] +[init -> test-platform_drv] +[init -> test-platform_drv] +[init -> test-platform_drv] +[init -> test-platform_drv] +[init -> test-platform_drv] +[init -> test-platform_drv] +[init -> test-platform_drv] +[init -> test-platform_drv] +[init -> test-platform_drv] +[init -> test-platform_drv] +[init -> test-platform_drv] +[init -> test-platform_drv] +[init -> test-platform_drv] +[init -> test-platform_drv] +[init -> test-platform_drv] +[init -> test-platform_drv] +[init -> test-platform_drv] +[init -> test-platform_drv] +[init -> test-platform_drv] +[init -> test-platform_drv] +[init -> test-platform_drv] +[init -> test-platform_drv] +[init -> test-platform_drv] +[init -> test-platform_drv] +[init -> test-platform_drv] +[init -> test-platform_drv] +[init -> test-platform_drv] +[init -> test-platform_drv] +[init -> test-platform_drv] +[init -> test-platform_drv] Error: Device 0 not valid! +[init -> test-platform_drv] +[init -> test-platform_drv] +[init -> test-platform_drv] +[init -> test-platform_drv] +[init -> test-platform_drv] +[init -> test-platform_drv] +[init -> test-platform_drv] +[init -> test-platform_drv] +[init -> test-platform_drv] +[init -> test-platform_drv] +[init -> test-platform_drv] +[init -> test-platform_drv] +[init -> test-platform_drv] +[init -> test-platform_drv] +[init -> test-platform_drv] +[init -> test-platform_drv] +[init -> test-platform_drv] +[init -> test-platform_drv] +[init -> test-platform_drv] Found next valid device of dummy type +[init -> test-platform_drv] Test has ended! +} + +run_genode_until "No matching policy for 'test-platform_drv -> ' anymore, will close the session!.*\n" 100 +grep_output "init -> test-platform_drv" +compare_output_to $good_string diff --git a/repos/os/src/test/platform_drv/main.cc b/repos/os/src/test/platform_drv/main.cc new file mode 100644 index 0000000000..1990dc5867 --- /dev/null +++ b/repos/os/src/test/platform_drv/main.cc @@ -0,0 +1,228 @@ +/* + * \brief Test platform driver API + * \author Stefan Kalkowski + * \date 2021-12-02 + */ + +/* + * Copyright (C) 2021 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 +#include +#include + +/* WARNING DO NOT COPY THIS !!! */ +/* + * We make everything public from the platform device classes + * to be able to check all corner cases while stressing the API + */ +#define private public +#include +#undef private +/* WARNING DO NOT COPY THIS !!! */ + +using namespace Genode; + +struct Main +{ + struct Device + { + Constructible device {}; + Constructible mmio {}; + Constructible irq {}; + + Device(Platform::Connection & plat, Platform::Device::Name name) + { + device.construct(plat, name); + if (!device->_cap.valid()) { + error("Device ", name, " not valid!"); + return; + } + + mmio.construct(*device, Platform::Device::Mmio::Index{0}); + irq.construct(*device, Platform::Device::Irq::Index{0}); + } + + ~Device() + { + if (mmio.constructed()) mmio.destruct(); + if (irq.constructed()) irq.destruct(); + if (device.constructed()) device.destruct(); + } + }; + + Env & env; + Reporter config_reporter { env, "config" }; + + Reconstructible platform { env }; + Constructible platform_2 { }; + + Signal_handler
device_rom_handler { env.ep(), *this, + &Main::handle_device_update }; + + Constructible devices[4] {}; + unsigned state = 0; + + void next_step(unsigned assigned, unsigned total, + addr_t iomem_base, unsigned irq_base) + { + state++; + + Reporter::Xml_generator xml(config_reporter, [&] () + { + for (unsigned idx = 0; idx < total; idx++) { + xml.node("device", [&] + { + xml.attribute("name", idx); + xml.attribute("type", "dummy-device"); + xml.node("io_mem", [&] + { + xml.attribute("address", + String<16>(Hex(iomem_base + idx*0x1000UL))); + xml.attribute("size", String<16>(Hex(0x1000UL))); + }); + xml.node("irq", [&] + { + xml.attribute("number", irq_base + idx); + }); + }); + } + + xml.node("policy", [&] + { + xml.attribute("label", "test-platform_drv -> "); + xml.attribute("info", true); + xml.attribute("version", state); + + for (unsigned idx = 0; idx < assigned; idx++) { + xml.node("device", [&] + { + xml.attribute("name", idx); + }); + }; + }); + }); + } + + void start_driver(unsigned idx) + { + if (!devices[idx].constructed()) + devices[idx].construct(*platform, Platform::Device::Name(idx)); + } + + void stop_driver(unsigned idx) + { + if (devices[idx].constructed()) + devices[idx].destruct(); + } + + void step() + { + switch (state) { + case 0: + /* report 3 out of 6 devices */ + next_step(3, 6, 0x40000000, 32); + return; + case 1: + /* start all drivers for the 3 devices, then destroy one, and let it vanish */ + start_driver(0); + start_driver(1); + start_driver(2); + stop_driver(2); + next_step(2, 2, 0x40000000, 32); + return; + case 2: + /* repeatedly start and destroy device sessions to detect leakages */ + for (unsigned idx = 0; idx < 100; idx++) { + start_driver(0); + start_driver(1); + stop_driver(0); + stop_driver(1); + } + /* now let all devices vanish */ + next_step(0, 2, 0x40000000, 32); + return; + case 3: + next_step(4, 4, 0x40000000, 32); + return; + case 4: + /* Instantiate and destroy all devices */ + start_driver(0); + start_driver(1); + start_driver(2); + start_driver(3); + stop_driver(0); + stop_driver(1); + stop_driver(2); + stop_driver(3); + /* allocate big DMA dataspace */ + platform->alloc_dma_buffer(0x80000, UNCACHED); + /* close the whole session */ + platform.destruct(); + platform.construct(env); + platform->sigh(device_rom_handler); + start_driver(0); + start_driver(1); + start_driver(2); + start_driver(3); + /* repeatedly start and destroy device sessions to detect leakages */ + for (unsigned idx = 0; idx < 1000; idx++) { + platform->free_dma_buffer(platform->alloc_dma_buffer(0x4000, UNCACHED)); + } + next_step(0, 0, 0x40000000, 32); + return; + case 5: + stop_driver(0); + stop_driver(1); + stop_driver(2); + stop_driver(3); + next_step(1, 1, 0x40000100, 32); + return; + case 6: + start_driver(0); + platform_2.construct(env); + devices[1].construct(*platform_2, Platform::Device::Name(0)); + stop_driver(1); + platform_2.destruct(); + next_step(4, 4, 0x40000100, 32); + return; + case 7: + { + Platform::Device dev (*platform, Platform::Device::Type({"dummy-device"})); + if (dev._cap.valid()) log("Found next valid device of dummy type"); + Reporter::Xml_generator xml(config_reporter, [&] () {}); + break; + } + default: + error("Invalid state++ something went wrong"); + }; + + log("Test has ended!"); + } + + void handle_device_update() + { + platform->update(); + + platform->with_xml([&] (Xml_node & xml) + { + if (state == xml.attribute_value("version", 0U)) { + log(xml); + step(); + } + }); + } + + Main(Env &env) : env(env) + { + platform->sigh(device_rom_handler); + config_reporter.enabled(true); + step(); + } +}; + +void Component::construct(Genode::Env &env) { static Main main(env); } diff --git a/repos/os/src/test/platform_drv/target.mk b/repos/os/src/test/platform_drv/target.mk new file mode 100644 index 0000000000..6ca1a75675 --- /dev/null +++ b/repos/os/src/test/platform_drv/target.mk @@ -0,0 +1,4 @@ +TARGET := test-platform_drv +REQUIRES = arm +SRC_CC = main.cc +LIBS = base diff --git a/tool/autopilot.list b/tool/autopilot.list index 2706a8245b..637430295c 100644 --- a/tool/autopilot.list +++ b/tool/autopilot.list @@ -54,6 +54,7 @@ nvme ping ping_nic_router platform +platform_drv rtc rump_ext2 sd_card_bench