mirror of
https://github.com/genodelabs/genode.git
synced 2025-04-01 16:42:06 +00:00
ahci & exynos5: opt-in app and part in ahci_bench
This commit is contained in:
parent
118ca20a2f
commit
4fe093b01b
@ -1,66 +1,120 @@
|
||||
|
||||
#
|
||||
# Select benchmark layer
|
||||
#
|
||||
# 0: driver internal
|
||||
# 1: native Genode app
|
||||
# 2: native Genode app with partition manager
|
||||
#
|
||||
set layer 0
|
||||
|
||||
#
|
||||
# Build
|
||||
#
|
||||
|
||||
build {
|
||||
set build_components {
|
||||
core init
|
||||
drivers/timer
|
||||
drivers/ahci
|
||||
drivers/platform
|
||||
}
|
||||
|
||||
create_boot_directory
|
||||
lappend_if [expr ($layer == 1 || $layer == 2)] build_components test/block_bench
|
||||
lappend_if [expr ($layer == 2)] build_components server/part_blk
|
||||
|
||||
build $build_components
|
||||
|
||||
create_boot_directory
|
||||
|
||||
#
|
||||
# Config
|
||||
#
|
||||
|
||||
install_config {
|
||||
<config>
|
||||
<parent-provides>
|
||||
<service name="ROM"/>
|
||||
<service name="RAM"/>
|
||||
<service name="IRQ"/>
|
||||
<service name="IO_MEM"/>
|
||||
<service name="CAP"/>
|
||||
<service name="PD"/>
|
||||
<service name="RM"/>
|
||||
<service name="CPU"/>
|
||||
<service name="LOG"/>
|
||||
<service name="SIGNAL"/>
|
||||
</parent-provides>
|
||||
<default-route>
|
||||
<any-service> <parent/> <any-child/> </any-service>
|
||||
</default-route>
|
||||
# basic config for all layers
|
||||
set config {
|
||||
<config>
|
||||
<parent-provides>
|
||||
<service name="ROM"/>
|
||||
<service name="RAM"/>
|
||||
<service name="IRQ"/>
|
||||
<service name="IO_MEM"/>
|
||||
<service name="CAP"/>
|
||||
<service name="PD"/>
|
||||
<service name="RM"/>
|
||||
<service name="CPU"/>
|
||||
<service name="LOG"/>
|
||||
<service name="SIGNAL"/>
|
||||
</parent-provides>
|
||||
<default-route>
|
||||
<any-service><parent/><any-child/></any-service>
|
||||
</default-route>
|
||||
<start name="platform_drv">
|
||||
<resource name="RAM" quantum="1M"/>
|
||||
<provides><service name="Regulator"/></provides>
|
||||
</start>
|
||||
<start name="timer">
|
||||
<resource name="RAM" quantum="1M"/>
|
||||
<provides><service name="Timer"/></provides>
|
||||
</start> }
|
||||
|
||||
<start name="platform_drv">
|
||||
<resource name="RAM" quantum="1M"/>
|
||||
<provides><service name="Regulator"/></provides>
|
||||
</start>
|
||||
<start name="timer">
|
||||
<resource name="RAM" quantum="1M"/>
|
||||
<provides><service name="Timer"/></provides>
|
||||
</start>
|
||||
<start name="ahci_bench">
|
||||
<resource name="RAM" quantum="1G"/>
|
||||
<provides><service name="Block"/></provides>
|
||||
</start>
|
||||
</config>
|
||||
}
|
||||
# start driver internal bench (wich a the driver itself) with layer 0
|
||||
append_if [expr $layer == 0] config {
|
||||
<start name="ahci_bench">
|
||||
<resource name="RAM" quantum="1G"/>
|
||||
<provides><service name="Block"/></provides>
|
||||
</start> }
|
||||
|
||||
# start part_blk with layer 1
|
||||
append_if [expr $layer == 2] config {
|
||||
<start name="part_blk">
|
||||
<resource name="RAM" quantum="10M" />
|
||||
<provides><service name="Block" /></provides>
|
||||
<route>
|
||||
<service name="Block"><child name="ahci" /></service>
|
||||
<any-service><parent/><any-child/></any-service>
|
||||
</route>
|
||||
<config>
|
||||
<policy label="test-block_bench" partition="0"/>
|
||||
</config>
|
||||
</start> }
|
||||
|
||||
# start normal AHCI driver and bench app with layer 1 or 2
|
||||
append_if [expr ($layer == 1 || $layer == 2)] config {
|
||||
<start name="ahci">
|
||||
<resource name="RAM" quantum="10M"/>
|
||||
<provides><service name="Block"/></provides>
|
||||
</start>
|
||||
<start name="test-block_bench">
|
||||
<resource name="RAM" quantum="1G"/> }
|
||||
|
||||
# if layer is 2 route block requests of bench app to part_blk
|
||||
append_if [expr $layer == 2] config {
|
||||
<route>
|
||||
<service name="Block"><child name="part_blk" /></service>
|
||||
<any-service><parent/><any-child/></any-service>
|
||||
</route> }
|
||||
|
||||
# end start node of bench app if layer 1 or 2
|
||||
append_if [expr ($layer == 1 || $layer == 2)] config {
|
||||
</start> }
|
||||
|
||||
# end config
|
||||
append config {
|
||||
</config> }
|
||||
|
||||
install_config $config
|
||||
|
||||
#
|
||||
# Boot modules
|
||||
#
|
||||
|
||||
build_boot_image {
|
||||
core init
|
||||
timer
|
||||
platform_drv
|
||||
ahci_bench
|
||||
}
|
||||
set boot_modules { core init timer platform_drv }
|
||||
|
||||
lappend_if [expr ($layer == 0)] boot_modules ahci_bench
|
||||
lappend_if [expr ($layer == 1 || $layer == 2)] boot_modules ahci
|
||||
lappend_if [expr ($layer == 1 || $layer == 2)] boot_modules test-block_bench
|
||||
lappend_if [expr ($layer == 2)] boot_modules part_blk
|
||||
|
||||
build_boot_image $boot_modules
|
||||
|
||||
run_genode_until forever
|
||||
|
||||
# vi: set ft=tcl :
|
||||
|
213
os/src/test/block_bench/main.cc
Normal file
213
os/src/test/block_bench/main.cc
Normal file
@ -0,0 +1,213 @@
|
||||
/*
|
||||
* \brief Block driver interface test
|
||||
* \author Sebastian Sumpf
|
||||
* \date 2011-08-11
|
||||
*
|
||||
* Test block device, read blocks add one to the data, write block back, read
|
||||
* block again and compare outputs
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2011-2013 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/allocator_avl.h>
|
||||
#include <base/printf.h>
|
||||
#include <base/sleep.h>
|
||||
#include <block_session/connection.h>
|
||||
#include <util/string.h>
|
||||
#include <timer_session/connection.h>
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
enum { VERBOSE = 0 };
|
||||
|
||||
/*
|
||||
* Do a bench for a specific access command and request size
|
||||
*
|
||||
* \param timer timer for measurements
|
||||
* \param request_size number of bytes per request
|
||||
* \param source block session packet sink
|
||||
* \param block_size block size of the targeted device
|
||||
* \param max_lba maximum logical block address of the device
|
||||
*/
|
||||
static void run_benchmark(
|
||||
Timer::Session & timer,
|
||||
Genode::size_t request_size,
|
||||
Block::Session::Tx::Source * source,
|
||||
size_t block_size,
|
||||
unsigned max_lba,
|
||||
void * buf,
|
||||
bool write)
|
||||
{
|
||||
/*
|
||||
* request_size: how many bytes are accessed by one command
|
||||
* block_size: raw block size that is used by the drive (not the software)
|
||||
* block_count: how many raw blocks are accessed by one command
|
||||
*/
|
||||
size_t const block_count = request_size / block_size;
|
||||
/*
|
||||
* The goal is to get 5 test repetitions that took 2 s < time < 2.3 s,
|
||||
* each. Thus we start with count = 32 and then adjust the count
|
||||
* for a retry if the test time is not in range.
|
||||
*/
|
||||
unsigned tmp_bytes = 64 * request_size;;
|
||||
unsigned bytes = 0;
|
||||
unsigned ms = 0;
|
||||
unsigned reps = 0;
|
||||
float sec = 0;
|
||||
float mb_per_sec = 0;
|
||||
while (1)
|
||||
{
|
||||
size_t num_requests = tmp_bytes / request_size;
|
||||
if ((num_requests * block_count) >= max_lba) { PERR("X"); while(1); }
|
||||
|
||||
/* do measurement */
|
||||
unsigned const time_before_ms = timer.elapsed_ms();
|
||||
for (unsigned i = 0; i < num_requests; i++)
|
||||
{
|
||||
/* create packet */
|
||||
addr_t const lba = i * block_count;
|
||||
Block::Packet_descriptor p(
|
||||
source->alloc_packet(request_size),
|
||||
write ? Block::Packet_descriptor::WRITE :
|
||||
Block::Packet_descriptor::READ,
|
||||
lba, block_count);
|
||||
|
||||
/* simulate payload */
|
||||
void * pptr = source->packet_content(p);
|
||||
if (write) memcpy(pptr, buf, request_size);
|
||||
|
||||
/* submit packet */
|
||||
source->submit_packet(p);
|
||||
p = source->get_acked_packet();
|
||||
if (!p.succeeded()) {
|
||||
PERR("could not access block %lu", lba);
|
||||
while (1) ;
|
||||
}
|
||||
/* simulate payload */
|
||||
if (!write) memcpy(buf, pptr, request_size);
|
||||
|
||||
/* release packet */
|
||||
source->release_packet(p);
|
||||
}
|
||||
/* read results */
|
||||
unsigned const time_after_ms = timer.elapsed_ms();
|
||||
ms = time_after_ms - time_before_ms;
|
||||
|
||||
/* trial log */
|
||||
if (VERBOSE)
|
||||
printf("%s %u bytes in %u ms\n",
|
||||
write ? "written" : "read", tmp_bytes, ms);
|
||||
|
||||
/* check if test time in range */
|
||||
if (ms < 2000 || ms >= 2300) {
|
||||
/*
|
||||
* adjust transfer amount according to measured time
|
||||
*
|
||||
* FIXME implement static inertia
|
||||
*/
|
||||
tmp_bytes = (((float) 2150 / ms) * tmp_bytes);
|
||||
tmp_bytes &= 0xfffffe00; /* align to 512 byte blocks */
|
||||
} else {
|
||||
/* if new result is better than the last one do update */
|
||||
float const tmp_mb = ((float)tmp_bytes / 1000) / 1000;
|
||||
float const tmp_sec = (float)ms / 1000;
|
||||
float const tmp_mb_per_sec = (float)tmp_mb / tmp_sec;
|
||||
if (tmp_mb_per_sec > mb_per_sec) {
|
||||
sec = tmp_sec;
|
||||
mb_per_sec = tmp_mb_per_sec;
|
||||
bytes = tmp_bytes;
|
||||
}
|
||||
/* check if we need more repetitions */
|
||||
reps++;
|
||||
if (reps == 5) break;
|
||||
}
|
||||
}
|
||||
unsigned const sec_left = sec;
|
||||
unsigned const sec_right = 1000 * ((float)sec - sec_left);
|
||||
unsigned const mb_per_sec_left = mb_per_sec;
|
||||
unsigned const mb_per_sec_right = 1000 * ((float)mb_per_sec - mb_per_sec_left);
|
||||
PLOG(" %10u %10u %u.%03u %10u.%03u", request_size, bytes, sec_left, sec_right, mb_per_sec_left, mb_per_sec_right);
|
||||
}
|
||||
|
||||
void print_bench_head()
|
||||
{
|
||||
printf("\n");
|
||||
printf("bytes/block bytes sec MB/sec\n");
|
||||
printf("----------------------------------------------\n");
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
using namespace Genode;
|
||||
|
||||
printf("AHCI bench\n");
|
||||
printf("==========\n");
|
||||
|
||||
enum { TX_BUF_SIZE = 2 * 1024 * 1024 };
|
||||
|
||||
/* get block connection */
|
||||
Genode::Allocator_avl block_alloc(Genode::env()->heap());
|
||||
Block::Connection _blk_con(&block_alloc, TX_BUF_SIZE);
|
||||
Block::Session::Tx::Source * source = _blk_con.tx();
|
||||
|
||||
/* check block-connection info */
|
||||
Genode::size_t _blk_size = 0;
|
||||
size_t blk_cnt = 0;
|
||||
Block::Session::Operations ops;
|
||||
_blk_con.info(&blk_cnt, &_blk_size, &ops);
|
||||
if (!ops.supported(Block::Packet_descriptor::READ)) {
|
||||
PERR("Block device not readable!");
|
||||
while(1); }
|
||||
if (!ops.supported(Block::Packet_descriptor::WRITE)) {
|
||||
PERR("Block device not writeable!");
|
||||
while(1); }
|
||||
|
||||
/* data for payload simulation */
|
||||
enum { BUF_SIZE = 1 * 1024 * 1024 };
|
||||
void * buf = env()->heap()->alloc(BUF_SIZE);
|
||||
for (unsigned o = 0; o < BUF_SIZE; o += sizeof(unsigned))
|
||||
*(unsigned volatile *)((addr_t)buf + o) = 0x12345678;
|
||||
|
||||
static Timer::Connection timer;
|
||||
|
||||
long const request_sizes[] = {
|
||||
1048576, 262144, 16384, 8192, 4096, 2048, 1024, 512, 0 };
|
||||
|
||||
/*
|
||||
* Benchmark reading from SATA device
|
||||
*/
|
||||
|
||||
printf("\n");
|
||||
printf("read\n");
|
||||
printf("~~~~\n");
|
||||
print_bench_head();
|
||||
|
||||
for (unsigned i = 0; request_sizes[i]; i++)
|
||||
run_benchmark(timer, request_sizes[i], source, _blk_size, blk_cnt, buf, 0);
|
||||
|
||||
/*
|
||||
* Benchmark writing to SATA device
|
||||
*
|
||||
* Attention: Original data will be overridden on target drive
|
||||
*/
|
||||
|
||||
printf("\n");
|
||||
printf("write\n");
|
||||
printf("~~~~~\n");
|
||||
print_bench_head();
|
||||
|
||||
for (unsigned i = 0; request_sizes[i]; i++)
|
||||
run_benchmark(timer, request_sizes[i], source, _blk_size, blk_cnt, buf, 1);
|
||||
|
||||
printf("\n");
|
||||
printf("benchmark finished\n");
|
||||
sleep_forever();
|
||||
return 0;
|
||||
}
|
||||
|
3
os/src/test/block_bench/target.mk
Normal file
3
os/src/test/block_bench/target.mk
Normal file
@ -0,0 +1,3 @@
|
||||
TARGET = test-block_bench
|
||||
SRC_CC = main.cc
|
||||
LIBS = base
|
Loading…
x
Reference in New Issue
Block a user