autopilot: automated stress test for platform_drv

Fix #4330
This commit is contained in:
Stefan Kalkowski 2021-12-02 17:18:41 +01:00 committed by Norman Feske
parent 132e4fe815
commit f11d2b5b54
4 changed files with 409 additions and 0 deletions

View File

@ -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 {
<config>
<parent-provides>
<service name="ROM"/>
<service name="IRQ"/>
<service name="IO_MEM"/>
<service name="PD"/>
<service name="RM"/>
<service name="CPU"/>
<service name="LOG"/>
</parent-provides>
<default-route>
<any-service> <parent/> </any-service>
</default-route>
<default caps="100"/>
<start name="timer">
<resource name="RAM" quantum="10M"/>
<provides><service name="Timer"/></provides>
</start>
<start name="report_fs">
<binary name="vfs"/>
<resource name="RAM" quantum="2M"/>
<provides> <service name="File_system"/> </provides>
<config>
<vfs>
<ram/>
<import>
<inline name="config"><config><default-policy/></config>
</inline>
</import>
</vfs>
<policy label="fs_report -> " root="/" writeable="yes"/>
<policy label="report_fs_rom -> " root="/"/>
</config>
</start>
<start name="fs_report">
<resource name="RAM" quantum="1M"/>
<provides> <service name="Report"/> </provides>
<config> <vfs> <fs/> </vfs> </config>
<route>
<service name="File_system"> <child name="report_fs"/> </service>
<any-service> <parent/> </any-service>
</route>
</start>
<start name="report_fs_rom">
<binary name="fs_rom"/>
<resource name="RAM" quantum="3M"/>
<provides> <service name="ROM"/> </provides>
<route>
<service name="File_system"> <child name="report_fs"/> </service>
<any-service> <parent/> </any-service>
</route>
</start>
<start name="platform_drv">
<resource name="RAM" quantum="1M"/>
<provides> <service name="Platform"/> </provides>
<route>
<service name="ROM" label="config"> <child name="report_fs_rom"/> </service>
<any-service> <parent/> </any-service>
</route>
</start>
<start name="test-platform_drv">
<resource name="RAM" quantum="1M"/>
<route>
<service name="Report"> <child name="fs_report" label="config"/> </service>
<service name="Platform"> <child name="platform_drv"/> </service>
<any-service> <parent/> </any-service>
</route>
</start>
</config>}
build_boot_image { test-platform_drv }
append qemu_args "-nographic "
set good_string {
[init -> test-platform_drv] <devices version="1">
[init -> test-platform_drv] <device name="0" type="dummy-device">
[init -> test-platform_drv] <io_mem phys_addr="0x40000000" size="0x1000"/>
[init -> test-platform_drv] <irq number="32"/>
[init -> test-platform_drv] </device>
[init -> test-platform_drv] <device name="1" type="dummy-device">
[init -> test-platform_drv] <io_mem phys_addr="0x40001000" size="0x1000"/>
[init -> test-platform_drv] <irq number="33"/>
[init -> test-platform_drv] </device>
[init -> test-platform_drv] <device name="2" type="dummy-device">
[init -> test-platform_drv] <io_mem phys_addr="0x40002000" size="0x1000"/>
[init -> test-platform_drv] <irq number="34"/>
[init -> test-platform_drv] </device>
[init -> test-platform_drv] </devices>
[init -> test-platform_drv] <devices version="2">
[init -> test-platform_drv] <device name="0" type="dummy-device">
[init -> test-platform_drv] <io_mem phys_addr="0x40000000" size="0x1000"/>
[init -> test-platform_drv] <irq number="32"/>
[init -> test-platform_drv] </device>
[init -> test-platform_drv] <device name="1" type="dummy-device">
[init -> test-platform_drv] <io_mem phys_addr="0x40001000" size="0x1000"/>
[init -> test-platform_drv] <irq number="33"/>
[init -> test-platform_drv] </device>
[init -> test-platform_drv] </devices>
[init -> test-platform_drv] <devices version="3"/>
[init -> test-platform_drv] <devices version="4">
[init -> test-platform_drv] <device name="0" type="dummy-device">
[init -> test-platform_drv] <io_mem phys_addr="0x40000000" size="0x1000"/>
[init -> test-platform_drv] <irq number="32"/>
[init -> test-platform_drv] </device>
[init -> test-platform_drv] <device name="1" type="dummy-device">
[init -> test-platform_drv] <io_mem phys_addr="0x40001000" size="0x1000"/>
[init -> test-platform_drv] <irq number="33"/>
[init -> test-platform_drv] </device>
[init -> test-platform_drv] <device name="2" type="dummy-device">
[init -> test-platform_drv] <io_mem phys_addr="0x40002000" size="0x1000"/>
[init -> test-platform_drv] <irq number="34"/>
[init -> test-platform_drv] </device>
[init -> test-platform_drv] <device name="3" type="dummy-device">
[init -> test-platform_drv] <io_mem phys_addr="0x40003000" size="0x1000"/>
[init -> test-platform_drv] <irq number="35"/>
[init -> test-platform_drv] </device>
[init -> test-platform_drv] </devices>
[init -> test-platform_drv] <devices version="5"/>
[init -> test-platform_drv] <devices version="6">
[init -> test-platform_drv] <device name="0" type="dummy-device">
[init -> test-platform_drv] <io_mem phys_addr="0x40000100" size="0x1000"/>
[init -> test-platform_drv] <irq number="32"/>
[init -> test-platform_drv] </device>
[init -> test-platform_drv] </devices>
[init -> test-platform_drv] Error: Device 0 not valid!
[init -> test-platform_drv] <devices version="7">
[init -> test-platform_drv] <device name="0" type="dummy-device">
[init -> test-platform_drv] <io_mem phys_addr="0x40000100" size="0x1000"/>
[init -> test-platform_drv] <irq number="32"/>
[init -> test-platform_drv] </device>
[init -> test-platform_drv] <device name="1" type="dummy-device">
[init -> test-platform_drv] <io_mem phys_addr="0x40001100" size="0x1000"/>
[init -> test-platform_drv] <irq number="33"/>
[init -> test-platform_drv] </device>
[init -> test-platform_drv] <device name="2" type="dummy-device">
[init -> test-platform_drv] <io_mem phys_addr="0x40002100" size="0x1000"/>
[init -> test-platform_drv] <irq number="34"/>
[init -> test-platform_drv] </device>
[init -> test-platform_drv] <device name="3" type="dummy-device">
[init -> test-platform_drv] <io_mem phys_addr="0x40003100" size="0x1000"/>
[init -> test-platform_drv] <irq number="35"/>
[init -> test-platform_drv] </device>
[init -> test-platform_drv] </devices>
[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

View File

@ -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 <base/component.h>
#include <base/log.h>
#include <os/reporter.h>
/* 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 <platform_session/device.h>
#undef private
/* WARNING DO NOT COPY THIS !!! */
using namespace Genode;
struct Main
{
struct Device
{
Constructible<Platform::Device> device {};
Constructible<Platform::Device::Mmio> mmio {};
Constructible<Platform::Device::Irq> 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::Connection> platform { env };
Constructible<Platform::Connection> platform_2 { };
Signal_handler<Main> device_rom_handler { env.ep(), *this,
&Main::handle_device_update };
Constructible<Device> 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); }

View File

@ -0,0 +1,4 @@
TARGET := test-platform_drv
REQUIRES = arm
SRC_CC = main.cc
LIBS = base

View File

@ -54,6 +54,7 @@ nvme
ping
ping_nic_router
platform
platform_drv
rtc
rump_ext2
sd_card_bench