mirror of
https://github.com/genodelabs/genode.git
synced 2025-02-20 17:52:52 +00:00
pc: add linux driver timer test
The test runs as lx_user task and uses several *delay and wait queue test cases happened to be used in real ported linux drivers. The test shows the time spent with several time sources, e.g. jiffies, rdtsc, lx_time_counter_count etc. Issue #4540
This commit is contained in:
parent
46b487c2f7
commit
b03cb94b43
96
repos/pc/run/driver_time.run
Normal file
96
repos/pc/run/driver_time.run
Normal file
@ -0,0 +1,96 @@
|
||||
#
|
||||
# Build
|
||||
#
|
||||
|
||||
if {[expr ![have_spec x86_64]]} {
|
||||
puts "Run script is not supported on this platform."
|
||||
exit 0
|
||||
}
|
||||
|
||||
set use_top 0
|
||||
|
||||
set build_components {
|
||||
core init timer
|
||||
test/driver_time
|
||||
}
|
||||
|
||||
|
||||
append_if $use_top build_components { app/top }
|
||||
|
||||
source ${genode_dir}/repos/base/run/platform_drv.inc
|
||||
append_platform_drv_build_components
|
||||
|
||||
build $build_components
|
||||
|
||||
create_boot_directory
|
||||
|
||||
# override default platform driver policy
|
||||
proc platform_drv_policy {} {
|
||||
return {
|
||||
<policy label_prefix="test-driver_time"> <device name="PS2"/> </policy>
|
||||
}
|
||||
}
|
||||
|
||||
#
|
||||
# Generate config
|
||||
#
|
||||
|
||||
append config {
|
||||
<config verbose="yes" prio_levels="4">
|
||||
<parent-provides>
|
||||
<service name="ROM"/>
|
||||
<service name="IRQ"/>
|
||||
<service name="IO_MEM"/>
|
||||
<service name="IO_PORT"/>
|
||||
<service name="PD"/>
|
||||
<service name="RM"/>
|
||||
<service name="CPU"/>
|
||||
<service name="LOG"/>
|
||||
<service name="TRACE"/>
|
||||
</parent-provides>
|
||||
<default-route>
|
||||
<any-service> <parent/> <any-child/> </any-service>
|
||||
</default-route>
|
||||
<default caps="100"/>
|
||||
|
||||
<start name="timer">
|
||||
<resource name="RAM" quantum="1M"/>
|
||||
<provides><service name="Timer"/></provides>
|
||||
</start>
|
||||
|
||||
<start name="test-driver_time" priority="-1">
|
||||
<resource name="RAM" quantum="2M"/>
|
||||
</start>}
|
||||
|
||||
append_platform_drv_config
|
||||
|
||||
append_if $use_top config {
|
||||
<start name="top">
|
||||
<resource name="RAM" quantum="2M"/>
|
||||
<config period_ms="40000"/>
|
||||
</start>}
|
||||
|
||||
append config {
|
||||
</config>}
|
||||
|
||||
install_config $config
|
||||
|
||||
#
|
||||
# Boot modules
|
||||
#
|
||||
|
||||
# generic modules
|
||||
set boot_modules {
|
||||
core ld.lib.so init timer
|
||||
test-driver_time
|
||||
}
|
||||
|
||||
append_if $use_top boot_modules { top }
|
||||
|
||||
append_platform_drv_boot_modules
|
||||
|
||||
build_boot_image $boot_modules
|
||||
|
||||
append qemu_args "-nographic "
|
||||
|
||||
run_genode_until forever
|
71
repos/pc/src/test/driver_time/dummies.c
Normal file
71
repos/pc/src/test/driver_time/dummies.c
Normal file
@ -0,0 +1,71 @@
|
||||
/*
|
||||
* \brief Dummy definitions of Linux Kernel functions - handled manually
|
||||
* \author Alexander Boettcher
|
||||
* \date 2022-07-01
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2022 Genode Labs GmbH
|
||||
*
|
||||
* This file is distributed under the terms of the GNU General Public License
|
||||
* version 2.
|
||||
*/
|
||||
|
||||
#include <lx_emul/debug.h>
|
||||
#include <linux/math64.h>
|
||||
|
||||
#include <linux/clocksource.h>
|
||||
#include <linux/cpuhotplug.h>
|
||||
#include <linux/kernel_stat.h>
|
||||
#include <linux/kernfs.h>
|
||||
#include <linux/kobject.h>
|
||||
#include <linux/nls.h>
|
||||
#include <linux/property.h>
|
||||
#include <linux/random.h>
|
||||
#include <linux/rcupdate.h>
|
||||
#include <linux/sched/loadavg.h>
|
||||
#include <linux/sched/signal.h>
|
||||
#include <linux/syscore_ops.h>
|
||||
#include <linux/timekeeper_internal.h>
|
||||
|
||||
|
||||
void calc_load_nohz_start(void)
|
||||
{
|
||||
lx_emul_trace(__func__);
|
||||
}
|
||||
|
||||
|
||||
void calc_load_nohz_stop(void)
|
||||
{
|
||||
lx_emul_trace(__func__);
|
||||
}
|
||||
|
||||
|
||||
void account_idle_ticks(unsigned long ticks)
|
||||
{
|
||||
lx_emul_trace(__func__);
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool irq_work_needs_cpu(void)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
int ___ratelimit(struct ratelimit_state * rs, const char * func)
|
||||
{
|
||||
/*
|
||||
* from lib/ratelimit.c:
|
||||
* " 0 means callbacks will be suppressed.
|
||||
* 1 means go ahead and do it. "
|
||||
*/
|
||||
lx_emul_trace(__func__);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void register_syscore_ops(struct syscore_ops * ops)
|
||||
{
|
||||
lx_emul_trace(__func__);
|
||||
}
|
234
repos/pc/src/test/driver_time/generated_dummies.c
Normal file
234
repos/pc/src/test/driver_time/generated_dummies.c
Normal file
@ -0,0 +1,234 @@
|
||||
/*
|
||||
* \brief Dummy definitions of Linux Kernel functions
|
||||
* \author Automatically generated file - do no edit
|
||||
* \date 2022-05-06
|
||||
*/
|
||||
|
||||
#include <lx_emul.h>
|
||||
|
||||
|
||||
#include <linux/proc_fs.h>
|
||||
|
||||
void * PDE_DATA(const struct inode * inode)
|
||||
{
|
||||
lx_emul_trace_and_stop(__func__);
|
||||
}
|
||||
|
||||
|
||||
#include <linux/clk-provider.h>
|
||||
|
||||
const char * __clk_get_name(const struct clk * clk)
|
||||
{
|
||||
lx_emul_trace_and_stop(__func__);
|
||||
}
|
||||
|
||||
|
||||
#include <linux/printk.h>
|
||||
|
||||
int printk_deferred(const char * fmt,...)
|
||||
{
|
||||
lx_emul_trace_and_stop(__func__);
|
||||
}
|
||||
|
||||
|
||||
#include <linux/irq_work.h>
|
||||
|
||||
void irq_work_tick(void)
|
||||
{
|
||||
lx_emul_trace_and_stop(__func__);
|
||||
}
|
||||
|
||||
|
||||
#include <linux/printk.h>
|
||||
|
||||
asmlinkage __visible void dump_stack(void)
|
||||
{
|
||||
lx_emul_trace_and_stop(__func__);
|
||||
}
|
||||
|
||||
|
||||
#include <linux/sched.h>
|
||||
|
||||
int io_schedule_prepare(void)
|
||||
{
|
||||
lx_emul_trace_and_stop(__func__);
|
||||
}
|
||||
|
||||
|
||||
#include <linux/sched.h>
|
||||
|
||||
void io_schedule_finish(int token)
|
||||
{
|
||||
lx_emul_trace_and_stop(__func__);
|
||||
}
|
||||
|
||||
|
||||
#include <linux/sched.h>
|
||||
|
||||
long io_schedule_timeout(long timeout)
|
||||
{
|
||||
lx_emul_trace_and_stop(__func__);
|
||||
}
|
||||
|
||||
|
||||
extern void ack_bad_irq(unsigned int irq);
|
||||
void ack_bad_irq(unsigned int irq)
|
||||
{
|
||||
lx_emul_trace_and_stop(__func__);
|
||||
}
|
||||
|
||||
|
||||
#include <linux/kobject.h>
|
||||
|
||||
int kobject_synth_uevent(struct kobject * kobj,const char * buf,size_t count)
|
||||
{
|
||||
lx_emul_trace_and_stop(__func__);
|
||||
}
|
||||
|
||||
|
||||
#include <linux/srcutiny.h>
|
||||
|
||||
void synchronize_srcu(struct srcu_struct * ssp)
|
||||
{
|
||||
lx_emul_trace_and_stop(__func__);
|
||||
}
|
||||
|
||||
|
||||
#include <linux/srcu.h>
|
||||
|
||||
void __srcu_read_unlock(struct srcu_struct * ssp,int idx)
|
||||
{
|
||||
lx_emul_trace_and_stop(__func__);
|
||||
}
|
||||
|
||||
|
||||
#include <linux/kobject.h>
|
||||
|
||||
int add_uevent_var(struct kobj_uevent_env * env,const char * format,...)
|
||||
{
|
||||
lx_emul_trace_and_stop(__func__);
|
||||
}
|
||||
|
||||
|
||||
#include <linux/init.h>
|
||||
|
||||
bool initcall_debug;
|
||||
|
||||
|
||||
#include <linux/irq.h>
|
||||
|
||||
struct irq_chip no_irq_chip;
|
||||
|
||||
|
||||
#include <linux/kobject.h>
|
||||
|
||||
struct kobject *kernel_kobj;
|
||||
|
||||
|
||||
#include <linux/fs.h>
|
||||
|
||||
void kill_anon_super(struct super_block * sb)
|
||||
{
|
||||
lx_emul_trace_and_stop(__func__);
|
||||
}
|
||||
|
||||
|
||||
#include <linux/property.h>
|
||||
|
||||
bool is_software_node(const struct fwnode_handle * fwnode)
|
||||
{
|
||||
lx_emul_trace_and_stop(__func__);
|
||||
}
|
||||
|
||||
|
||||
#include <linux/property.h>
|
||||
|
||||
void fwnode_remove_software_node(struct fwnode_handle * fwnode)
|
||||
{
|
||||
lx_emul_trace_and_stop(__func__);
|
||||
}
|
||||
|
||||
|
||||
#include <linux/sched/task.h>
|
||||
|
||||
void __put_task_struct(struct task_struct * tsk)
|
||||
{
|
||||
lx_emul_trace_and_stop(__func__);
|
||||
}
|
||||
|
||||
|
||||
#include <linux/kernel.h>
|
||||
|
||||
int get_option(char ** str,int * pint)
|
||||
{
|
||||
lx_emul_trace_and_stop(__func__);
|
||||
}
|
||||
|
||||
|
||||
#include <linux/sched/wake_q.h>
|
||||
|
||||
void wake_q_add_safe(struct wake_q_head * head,struct task_struct * task)
|
||||
{
|
||||
lx_emul_trace_and_stop(__func__);
|
||||
}
|
||||
|
||||
|
||||
#include <linux/capability.h>
|
||||
|
||||
bool file_ns_capable(const struct file * file,struct user_namespace * ns,int cap)
|
||||
{
|
||||
lx_emul_trace_and_stop(__func__);
|
||||
}
|
||||
|
||||
|
||||
#include <linux/seq_file.h>
|
||||
|
||||
void seq_printf(struct seq_file * m,const char * f,...)
|
||||
{
|
||||
lx_emul_trace_and_stop(__func__);
|
||||
}
|
||||
|
||||
|
||||
#include <linux/pseudo_fs.h>
|
||||
|
||||
struct pseudo_fs_context * init_pseudo(struct fs_context * fc,unsigned long magic)
|
||||
{
|
||||
lx_emul_trace_and_stop(__func__);
|
||||
}
|
||||
|
||||
|
||||
#include <linux/smp.h>
|
||||
|
||||
int smp_call_function_single(int cpu,void (* func)(void * info),void * info,int wait)
|
||||
{
|
||||
lx_emul_trace_and_stop(__func__);
|
||||
}
|
||||
|
||||
|
||||
#include <linux/srcutiny.h>
|
||||
|
||||
void srcu_drive_gp(struct work_struct * wp)
|
||||
{
|
||||
lx_emul_trace_and_stop(__func__);
|
||||
}
|
||||
|
||||
|
||||
#include <linux/uaccess.h>
|
||||
|
||||
unsigned long _copy_to_user(void __user * to,const void * from,unsigned long n)
|
||||
{
|
||||
lx_emul_trace_and_stop(__func__);
|
||||
}
|
||||
|
||||
|
||||
#include <linux/jump_label.h>
|
||||
|
||||
bool static_key_initialized;
|
||||
|
||||
|
||||
#include <linux/string_helpers.h>
|
||||
|
||||
int string_escape_mem(const char * src,size_t isz,char * dst,size_t osz,unsigned int flags,const char * only)
|
||||
{
|
||||
lx_emul_trace_and_stop(__func__);
|
||||
}
|
23
repos/pc/src/test/driver_time/lx_emul.h
Normal file
23
repos/pc/src/test/driver_time/lx_emul.h
Normal file
@ -0,0 +1,23 @@
|
||||
/**
|
||||
* \brief Dummy definitions of Linux Kernel functions
|
||||
* \author Alexander Boettcher
|
||||
* \date 2022-07-01
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2022 Genode Labs GmbH
|
||||
*
|
||||
* This file is distributed under the terms of the GNU General Public License
|
||||
* version 2.
|
||||
*/
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void lx_emul_time_udelay(unsigned long usec);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
270
repos/pc/src/test/driver_time/lx_user.c
Normal file
270
repos/pc/src/test/driver_time/lx_user.c
Normal file
@ -0,0 +1,270 @@
|
||||
/*
|
||||
* \brief Post kernel activity
|
||||
* \author Alexander Boettcher
|
||||
* \date 2022-07-01
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2022 Genode Labs GmbH
|
||||
*
|
||||
* This file is distributed under the terms of the GNU General Public License
|
||||
* version 2.
|
||||
*/
|
||||
|
||||
|
||||
#include <linux/sched/task.h>
|
||||
|
||||
#include <linux/delay.h>
|
||||
|
||||
#include "i915_drv.h" /* test wait_for() macro */
|
||||
|
||||
#include <lx_emul/time.h>
|
||||
|
||||
|
||||
extern uint64_t tsc_freq_khz;
|
||||
|
||||
|
||||
static int timing_tests(void *);
|
||||
|
||||
|
||||
void lx_user_init(void)
|
||||
{
|
||||
kernel_thread(timing_tests, NULL, CLONE_FS | CLONE_FILES);
|
||||
}
|
||||
|
||||
|
||||
struct measure {
|
||||
uint64_t start;
|
||||
uint64_t end;
|
||||
uint64_t diff;
|
||||
};
|
||||
|
||||
#define test_timing(fn_test, fn_evaluation) \
|
||||
{ \
|
||||
struct measure m_lxemul, m_jiffies, m_rdtsc; \
|
||||
uint64_t jiffies_in_us; \
|
||||
\
|
||||
m_lxemul.start = lx_emul_time_counter(); \
|
||||
m_jiffies.start = jiffies_64; \
|
||||
m_rdtsc.start = rdtsc(); \
|
||||
\
|
||||
{ \
|
||||
fn_test \
|
||||
} \
|
||||
\
|
||||
m_rdtsc.end = rdtsc(); \
|
||||
m_jiffies.end = jiffies_64; \
|
||||
m_lxemul.end = lx_emul_time_counter(); \
|
||||
\
|
||||
m_rdtsc.diff = m_rdtsc.end - m_rdtsc.start; \
|
||||
m_lxemul.diff = m_lxemul.end - m_lxemul.start; \
|
||||
m_jiffies.diff = m_jiffies.end - m_jiffies.start; \
|
||||
\
|
||||
jiffies_in_us = (m_jiffies.diff) * (1000ull * 1000 / CONFIG_HZ); \
|
||||
\
|
||||
{ \
|
||||
fn_evaluation \
|
||||
} \
|
||||
\
|
||||
}
|
||||
|
||||
#define test_timing_no_ret(text, fn_test) \
|
||||
{ \
|
||||
test_timing( \
|
||||
fn_test \
|
||||
, \
|
||||
if (rdtsc_freq_mhz) \
|
||||
printk(text \
|
||||
" %6llu:%10llu:%10llu:%10llu:%8lld\n", \
|
||||
m_jiffies.diff, jiffies_in_us, m_lxemul.diff, \
|
||||
m_rdtsc.diff / rdtsc_freq_mhz, \
|
||||
jiffies_in_us - m_lxemul.diff); \
|
||||
else \
|
||||
printk(text \
|
||||
" %6llu:%10llu:%10llu:%8lld\n", \
|
||||
m_jiffies.diff, jiffies_in_us, m_lxemul.diff, \
|
||||
jiffies_in_us - m_lxemul.diff); \
|
||||
); \
|
||||
/* trigger to update jiffies to avoid printk time part of next test */ \
|
||||
msleep(1); \
|
||||
}
|
||||
|
||||
|
||||
#define test_timing_with_ret(text, fn_test) \
|
||||
{ \
|
||||
test_timing( \
|
||||
fn_test \
|
||||
, \
|
||||
if (rdtsc_freq_mhz) \
|
||||
printk(text \
|
||||
" %6llu:%10llu:%10llu:%10llu:%8lld " \
|
||||
"ret=%d%s\n", \
|
||||
m_jiffies.diff, jiffies_in_us, m_lxemul.diff, \
|
||||
m_rdtsc.diff / rdtsc_freq_mhz, \
|
||||
jiffies_in_us - m_lxemul.diff, \
|
||||
ret, ret == -ETIMEDOUT ? " (ETIMEDOUT)" : ""); \
|
||||
else \
|
||||
printk(text \
|
||||
" %6llu:%10llu:%10llu:%8lld " \
|
||||
"ret=%d%s\n", \
|
||||
m_jiffies.diff, jiffies_in_us, m_lxemul.diff, \
|
||||
jiffies_in_us - m_lxemul.diff, \
|
||||
ret, ret == -ETIMEDOUT ? " (ETIMEDOUT)" : ""); \
|
||||
); \
|
||||
/* trigger to update jiffies to avoid printk time part of next test */ \
|
||||
msleep(1); \
|
||||
}
|
||||
|
||||
|
||||
static int timing_tests(void * data)
|
||||
{
|
||||
DEFINE_WAIT(wait);
|
||||
wait_queue_head_t wq;
|
||||
int ret;
|
||||
uint64_t const rdtsc_freq_mhz = tsc_freq_khz / 1000;
|
||||
|
||||
init_waitqueue_head(&wq);
|
||||
|
||||
while (true) {
|
||||
if (rdtsc_freq_mhz)
|
||||
printk("test(parameters) -> "
|
||||
"jiffies:jiff_us:lx_time_us:rdtsc_us:diff_jiff_lx_time "
|
||||
"tsc=%lluMhz\n", rdtsc_freq_mhz);
|
||||
else
|
||||
printk("test(parameters) -> "
|
||||
"jiffies:jiff_us:lx_time_us:diff_jiff_lx_time\n");
|
||||
|
||||
test_timing_no_ret ("udelay(40) ->",
|
||||
udelay(40);
|
||||
);
|
||||
|
||||
test_timing_no_ret ("ndelay(4000) ->",
|
||||
ndelay(4000);
|
||||
);
|
||||
|
||||
test_timing_no_ret ("msleep(5000) ->",
|
||||
msleep(5000);
|
||||
);
|
||||
|
||||
test_timing_with_ret("wait_for(cond,10ms) A ->",
|
||||
add_wait_queue(&wq, &wait);
|
||||
ret = wait_for((0), 10);
|
||||
remove_wait_queue(&wq, &wait);
|
||||
);
|
||||
|
||||
test_timing_with_ret("wait_for(cond,5ms) B ->",
|
||||
add_wait_queue(&wq, &wait);
|
||||
ret = wait_for((0), 5);
|
||||
remove_wait_queue(&wq, &wait);
|
||||
);
|
||||
|
||||
test_timing_with_ret("wait_for(cond,2ms) C ->",
|
||||
add_wait_queue(&wq, &wait);
|
||||
ret = wait_for((0), 2);
|
||||
remove_wait_queue(&wq, &wait);
|
||||
);
|
||||
|
||||
test_timing_with_ret("wait_for(cond,10ms) D ->",
|
||||
add_wait_queue(&wq, &wait);
|
||||
ret = wait_for((0), 10);
|
||||
remove_wait_queue(&wq, &wait);
|
||||
);
|
||||
|
||||
/* do some work, so that jiffies becomes a bit outdated */
|
||||
{
|
||||
unsigned long long i = 0;
|
||||
printk("cause some long running load in task ...\n");
|
||||
for (i = 0; i < (1ull << 24); i++) {
|
||||
asm volatile("pause":::"memory");
|
||||
}
|
||||
}
|
||||
|
||||
/* display driver test case -> waking up too early before irq triggered */
|
||||
test_timing_with_ret("wait_for(cond,10ms) E ->",
|
||||
add_wait_queue(&wq, &wait);
|
||||
ret = wait_for((0), 10);
|
||||
remove_wait_queue(&wq, &wait);
|
||||
);
|
||||
|
||||
test_timing_with_ret("wait_for(cond,5ms) F ->",
|
||||
add_wait_queue(&wq, &wait);
|
||||
ret = wait_for((0), 5);
|
||||
remove_wait_queue(&wq, &wait);
|
||||
);
|
||||
|
||||
test_timing_with_ret("wait_for(cond,2ms) G ->",
|
||||
add_wait_queue(&wq, &wait);
|
||||
ret = wait_for((0), 2);
|
||||
remove_wait_queue(&wq, &wait);
|
||||
);
|
||||
|
||||
test_timing_with_ret("wait_for(cond,10ms) H ->",
|
||||
add_wait_queue(&wq, &wait);
|
||||
ret = wait_for((0), 10);
|
||||
remove_wait_queue(&wq, &wait);
|
||||
);
|
||||
|
||||
test_timing_with_ret("wait_for(cond,5000ms) ->",
|
||||
add_wait_queue(&wq, &wait);
|
||||
ret = wait_for((0), 5000);
|
||||
remove_wait_queue(&wq, &wait);
|
||||
);
|
||||
|
||||
test_timing_with_ret("wait_for(cond,4000ms) ->",
|
||||
add_wait_queue(&wq, &wait);
|
||||
ret = wait_for((0), 4000);
|
||||
remove_wait_queue(&wq, &wait);
|
||||
);
|
||||
|
||||
test_timing_with_ret("wait_for(cond,3000ms) ->",
|
||||
add_wait_queue(&wq, &wait);
|
||||
ret = wait_for((0), 3000);
|
||||
remove_wait_queue(&wq, &wait);
|
||||
);
|
||||
|
||||
test_timing_with_ret("wait_for(cond,2000ms) ->",
|
||||
add_wait_queue(&wq, &wait);
|
||||
ret = wait_for((0), 2000);
|
||||
remove_wait_queue(&wq, &wait);
|
||||
);
|
||||
|
||||
test_timing_with_ret("wait_for(cond,500ms) ->",
|
||||
add_wait_queue(&wq, &wait);
|
||||
ret = wait_for((0), 500);
|
||||
remove_wait_queue(&wq, &wait);
|
||||
);
|
||||
|
||||
test_timing_with_ret("wait_for(cond,200ms) ->",
|
||||
add_wait_queue(&wq, &wait);
|
||||
ret = wait_for((0), 200);
|
||||
remove_wait_queue(&wq, &wait);
|
||||
);
|
||||
|
||||
test_timing_with_ret("wait_for(cond,100ms) ->",
|
||||
add_wait_queue(&wq, &wait);
|
||||
ret = wait_for((0), 100);
|
||||
remove_wait_queue(&wq, &wait);
|
||||
);
|
||||
|
||||
test_timing_with_ret("wait_for(cond,50ms) ->",
|
||||
add_wait_queue(&wq, &wait);
|
||||
ret = wait_for((0), 50);
|
||||
remove_wait_queue(&wq, &wait);
|
||||
);
|
||||
|
||||
/* audio driver test case -> sleeping too short or long is bad */
|
||||
test_timing_no_ret ("usleep_range(20,21) ->",
|
||||
usleep_range(20, 21);
|
||||
);
|
||||
|
||||
test_timing_no_ret ("usleep_range(40,41) ->",
|
||||
usleep_range(40, 41);
|
||||
);
|
||||
|
||||
test_timing_no_ret ("usleep_range(400,410) ->",
|
||||
usleep_range(400, 410);
|
||||
);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
67
repos/pc/src/test/driver_time/main.cc
Normal file
67
repos/pc/src/test/driver_time/main.cc
Normal file
@ -0,0 +1,67 @@
|
||||
/*
|
||||
* \brief Linux test driver
|
||||
* \author Alexander Boettcher
|
||||
* \date 2022-07-01
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2022 Genode Labs GmbH
|
||||
*
|
||||
* This file is distributed under the terms of the GNU General Public License
|
||||
* version 2.
|
||||
*/
|
||||
|
||||
#include <base/attached_rom_dataspace.h>
|
||||
#include <base/component.h>
|
||||
|
||||
/* emulation includes */
|
||||
#include <lx_emul/init.h>
|
||||
#include <lx_kit/env.h>
|
||||
|
||||
|
||||
namespace Test {
|
||||
using namespace Genode;
|
||||
struct Driver;
|
||||
}
|
||||
|
||||
|
||||
unsigned long long tsc_freq_khz;
|
||||
|
||||
|
||||
struct Test::Driver
|
||||
{
|
||||
Env &env;
|
||||
|
||||
Driver(Env &env) : env(env)
|
||||
{
|
||||
Lx_kit::initialize(env);
|
||||
|
||||
env.exec_static_constructors();
|
||||
|
||||
try {
|
||||
Attached_rom_dataspace info(env, "platform_info");
|
||||
tsc_freq_khz = info.xml().sub_node("hardware").sub_node("tsc")
|
||||
.attribute_value("freq_khz", 0ULL);
|
||||
} catch (...) { };
|
||||
}
|
||||
|
||||
void start()
|
||||
{
|
||||
log("--- Test driver started ---");
|
||||
|
||||
lx_emul_start_kernel(nullptr);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
static Test::Driver &driver(Genode::Env & env)
|
||||
{
|
||||
static Test::Driver driver(env);
|
||||
return driver;
|
||||
}
|
||||
|
||||
|
||||
void Component::construct(Genode::Env &env)
|
||||
{
|
||||
driver(env).start();
|
||||
}
|
77
repos/pc/src/test/driver_time/source.list
Normal file
77
repos/pc/src/test/driver_time/source.list
Normal file
@ -0,0 +1,77 @@
|
||||
drivers/base/bus.c
|
||||
drivers/base/class.c
|
||||
drivers/base/component.c
|
||||
drivers/base/core.c
|
||||
drivers/base/dd.c
|
||||
drivers/base/devres.c
|
||||
drivers/base/driver.c
|
||||
drivers/base/platform.c
|
||||
drivers/base/property.c
|
||||
kernel/async.c
|
||||
kernel/irq/chip.c
|
||||
kernel/irq/devres.c
|
||||
kernel/irq/handle.c
|
||||
kernel/irq/irqdesc.c
|
||||
kernel/irq/irqdomain.c
|
||||
kernel/irq/manage.c
|
||||
kernel/irq/resend.c
|
||||
kernel/kthread.c
|
||||
kernel/locking/mutex.c
|
||||
kernel/locking/osq_lock.c
|
||||
kernel/locking/rtmutex.c
|
||||
kernel/locking/rwsem.c
|
||||
kernel/notifier.c
|
||||
kernel/panic.c
|
||||
kernel/resource.c
|
||||
kernel/sched/clock.c
|
||||
kernel/sched/completion.c
|
||||
kernel/sched/swait.c
|
||||
kernel/sched/wait.c
|
||||
kernel/sched/wait_bit.c
|
||||
kernel/smpboot.c
|
||||
kernel/time/clockevents.c
|
||||
kernel/time/clocksource.c
|
||||
kernel/time/hrtimer.c
|
||||
kernel/time/jiffies.c
|
||||
kernel/time/ntp.c
|
||||
kernel/time/tick-broadcast.c
|
||||
kernel/time/tick-common.c
|
||||
kernel/time/tick-oneshot.c
|
||||
kernel/time/tick-sched.c
|
||||
kernel/time/time.c
|
||||
kernel/time/timeconv.c
|
||||
kernel/time/timecounter.c
|
||||
kernel/time/timekeeping.c
|
||||
kernel/time/timer.c
|
||||
kernel/time/timer_list.c
|
||||
kernel/workqueue.c
|
||||
lib/bitmap.c
|
||||
lib/crc32.c
|
||||
lib/ctype.c
|
||||
lib/debug_locks.c
|
||||
lib/dec_and_lock.c
|
||||
lib/find_bit.c
|
||||
lib/hexdump.c
|
||||
lib/hweight.c
|
||||
lib/idr.c
|
||||
lib/iomap.c
|
||||
lib/irq_regs.c
|
||||
lib/kasprintf.c
|
||||
lib/klist.c
|
||||
lib/kobject.c
|
||||
lib/kstrtox.c
|
||||
lib/list_sort.c
|
||||
lib/llist.c
|
||||
lib/radix-tree.c
|
||||
lib/rbtree.c
|
||||
lib/refcount.c
|
||||
lib/scatterlist.c
|
||||
lib/siphash.c
|
||||
lib/sort.c
|
||||
lib/string.c
|
||||
lib/timerqueue.c
|
||||
lib/uuid.c
|
||||
lib/vsprintf.c
|
||||
lib/xarray.c
|
||||
mm/mempool.c
|
||||
mm/util.c
|
28
repos/pc/src/test/driver_time/target.mk
Normal file
28
repos/pc/src/test/driver_time/target.mk
Normal file
@ -0,0 +1,28 @@
|
||||
REQUIRES := x86_64
|
||||
|
||||
TARGET := test-driver_time
|
||||
LIBS := base pc_lx_emul jitterentropy
|
||||
|
||||
SRC_CC += main.cc time.cc
|
||||
SRC_C += lx_user.c
|
||||
SRC_C += dummies.c
|
||||
SRC_C += generated_dummies.c
|
||||
|
||||
SRC_C += lx_emul/common_dummies.c
|
||||
SRC_C += lx_emul/shadow/lib/kobject_uevent.c
|
||||
SRC_C += lx_emul/shadow/drivers/char/random.c
|
||||
SRC_C += lx_emul/shadow/kernel/softirq.c
|
||||
|
||||
vpath %.c $(REP_DIR)/src/lib/pc
|
||||
vpath %.cc $(REP_DIR)/src/lib/pc
|
||||
|
||||
LX_SRC_DIR := $(call select_from_ports,linux)/src/linux
|
||||
ifeq ($(wildcard $(LX_SRC_DIR)),)
|
||||
LX_SRC_DIR := $(call select_from_repositories,src/linux)
|
||||
endif
|
||||
ifeq ($(wildcard $(LX_SRC_DIR)),)
|
||||
fail
|
||||
endif
|
||||
|
||||
INC_DIR += $(PRG_DIR)
|
||||
INC_DIR += $(LX_SRC_DIR)/drivers/gpu/drm/i915
|
25
repos/pc/src/test/driver_time/time.cc
Normal file
25
repos/pc/src/test/driver_time/time.cc
Normal file
@ -0,0 +1,25 @@
|
||||
/*
|
||||
* \brief Lx_emul udelay function for very short delays
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2021-07-10
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2021 Genode Labs GmbH
|
||||
*
|
||||
* This file is distributed under the terms of the GNU General Public License
|
||||
* version 2.
|
||||
*/
|
||||
|
||||
#include <base/log.h>
|
||||
#include <lx_kit/env.h>
|
||||
|
||||
extern "C" void lx_emul_time_udelay(unsigned long usec);
|
||||
extern "C" void lx_emul_time_udelay(unsigned long usec)
|
||||
{
|
||||
if (usec > 100)
|
||||
Genode::error("Cannot delay that long ", usec, " microseconds");
|
||||
|
||||
unsigned long long start = Lx_kit::env().timer.curr_time().trunc_to_plain_us().value;
|
||||
while (Lx_kit::env().timer.curr_time().trunc_to_plain_us().value < (start + usec)) { ; }
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user