mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-18 21:27:56 +00:00
nova: make write-combined unit test more robust
- touch all memory before time measurements, to reduce lazy paging jitter - diff of 100us between 2 memset runs are now considered a failure (before 10us) - add refrence measurements of same region size which is not write-combined - make the output easier parse able of write-combined test Fixes #5342
This commit is contained in:
parent
09461c51bd
commit
4554ec42da
@ -297,27 +297,27 @@ void test_pat(Genode::Env &env)
|
|||||||
Xml_node const hardware = platform_info.xml().sub_node("hardware");
|
Xml_node const hardware = platform_info.xml().sub_node("hardware");
|
||||||
uint64_t const tsc_freq = hardware.sub_node("tsc").attribute_value("freq_khz", 1ULL);
|
uint64_t const tsc_freq = hardware.sub_node("tsc").attribute_value("freq_khz", 1ULL);
|
||||||
|
|
||||||
enum { DS_ORDER = 12, PAGE_4K = 12 };
|
enum { DS_ORDER = 12, PAGE_4K = 12, DS_SIZE = 1ul << (DS_ORDER + PAGE_4K) };
|
||||||
|
|
||||||
Attached_dataspace ds { env.rm(), env.ram().alloc (1 << (DS_ORDER + PAGE_4K),
|
Genode::Rm_connection rm(env);
|
||||||
WRITE_COMBINED) };
|
Genode::Region_map_client rm_unused(rm.create(DS_SIZE));
|
||||||
addr_t const map_addr = addr_t(ds.local_addr<void>());
|
|
||||||
|
|
||||||
enum { STACK_SIZE = 4096 };
|
Attached_dataspace ds_wc { env.rm(), env.ram().alloc (DS_SIZE, WRITE_COMBINED) };
|
||||||
|
Attached_dataspace ds { env.rm(), env.ram().alloc (DS_SIZE) };
|
||||||
|
Attached_dataspace remap { env.rm(), rm_unused.dataspace() };
|
||||||
|
|
||||||
static Rpc_entrypoint ep(&env.pd(), STACK_SIZE, "rpc_ep_pat",
|
auto const memory = addr_t(ds .local_addr<void>());
|
||||||
|
auto const memory_wc = addr_t(ds_wc.local_addr<void>());
|
||||||
|
auto const memory_remap = addr_t(remap.local_addr<void>());
|
||||||
|
|
||||||
|
static Rpc_entrypoint ep(&env.pd(), 4096 /* STACK */, "rpc_ep_pat",
|
||||||
Affinity::Location());
|
Affinity::Location());
|
||||||
|
|
||||||
Genode::Rm_connection rm(env);
|
|
||||||
Genode::Region_map_client rm_free_area(rm.create(1 << (DS_ORDER + PAGE_4K)));
|
|
||||||
|
|
||||||
Attached_dataspace remap { env.rm(), rm_free_area.dataspace() };
|
|
||||||
|
|
||||||
addr_t const remap_addr = addr_t(remap.local_addr<void>());
|
|
||||||
|
|
||||||
/* trigger mapping of whole area */
|
/* trigger mapping of whole area */
|
||||||
for (addr_t i = map_addr; i < map_addr + (1 << (DS_ORDER + PAGE_4K)); i += (1 << PAGE_4K))
|
for (auto offset = 0; offset < DS_SIZE; offset += (1u << PAGE_4K)) {
|
||||||
touch_read(reinterpret_cast<unsigned char *>(map_addr));
|
touch_read_write(reinterpret_cast<unsigned char *>(memory_wc + offset));
|
||||||
|
touch_read_write(reinterpret_cast<unsigned char *>( memory + offset));
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Establish memory mapping with evilly wrong mapping attributes
|
* Establish memory mapping with evilly wrong mapping attributes
|
||||||
@ -331,8 +331,8 @@ void test_pat(Genode::Env &env)
|
|||||||
native_pd.alloc_rpc_cap(thread_cap, (addr_t)portal_entry, 0 /* MTD */);
|
native_pd.alloc_rpc_cap(thread_cap, (addr_t)portal_entry, 0 /* MTD */);
|
||||||
|
|
||||||
Nova::Rights const all(true, true, true);
|
Nova::Rights const all(true, true, true);
|
||||||
Nova::Mem_crd const rcv_crd(remap_addr >> PAGE_4K, DS_ORDER, all);
|
Nova::Mem_crd const rcv_crd(memory_remap >> PAGE_4K, DS_ORDER, all);
|
||||||
Nova::Mem_crd const snd_crd(map_addr >> PAGE_4K, DS_ORDER, all);
|
Nova::Mem_crd const snd_crd(memory_wc >> PAGE_4K, DS_ORDER, all);
|
||||||
Nova::Crd const old_crd = utcb.crd_rcv;
|
Nova::Crd const old_crd = utcb.crd_rcv;
|
||||||
|
|
||||||
utcb.crd_rcv = rcv_crd;
|
utcb.crd_rcv = rcv_crd;
|
||||||
@ -348,36 +348,45 @@ void test_pat(Genode::Env &env)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* sanity check - touch re-mapped area */
|
/* sanity check - touch re-mapped area */
|
||||||
for (addr_t i = remap_addr; i < remap_addr + (1 << (DS_ORDER + PAGE_4K)); i += (1 << PAGE_4K))
|
for (auto offset = 0; offset < DS_SIZE; offset += (1 << PAGE_4K))
|
||||||
touch_read(reinterpret_cast<unsigned char *>(remap_addr));
|
touch_read_write(reinterpret_cast<unsigned char *>(memory_remap + offset));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* measure time to write to the memory
|
* measure time to write to the memory
|
||||||
*/
|
*/
|
||||||
memset(reinterpret_cast<void *>(map_addr), 0, 1 << (DS_ORDER + PAGE_4K));
|
memset(reinterpret_cast<void *>(memory), 0, DS_SIZE);
|
||||||
|
Trace::Timestamp normal_start = Trace::timestamp();
|
||||||
|
memset(reinterpret_cast<void *>(memory), 0, DS_SIZE);
|
||||||
|
Trace::Timestamp normal_end = Trace::timestamp();
|
||||||
|
|
||||||
|
memset(reinterpret_cast<void *>(memory_wc), 0, DS_SIZE);
|
||||||
Trace::Timestamp map_start = Trace::timestamp();
|
Trace::Timestamp map_start = Trace::timestamp();
|
||||||
memset(reinterpret_cast<void *>(map_addr), 0, 1 << (DS_ORDER + PAGE_4K));
|
memset(reinterpret_cast<void *>(memory_wc), 0, DS_SIZE);
|
||||||
Trace::Timestamp map_end = Trace::timestamp();
|
Trace::Timestamp map_end = Trace::timestamp();
|
||||||
|
|
||||||
memset(reinterpret_cast<void *>(remap_addr), 0, 1 << (DS_ORDER + PAGE_4K));
|
memset(reinterpret_cast<void *>(memory_remap), 0, DS_SIZE);
|
||||||
Trace::Timestamp remap_start = Trace::timestamp();
|
Trace::Timestamp remap_start = Trace::timestamp();
|
||||||
memset(reinterpret_cast<void *>(remap_addr), 0, 1 << (DS_ORDER + PAGE_4K));
|
memset(reinterpret_cast<void *>(memory_remap), 0, DS_SIZE);
|
||||||
Trace::Timestamp remap_end = Trace::timestamp();
|
Trace::Timestamp remap_end = Trace::timestamp();
|
||||||
|
|
||||||
Trace::Timestamp map_run = map_end - map_start;
|
auto normal_run = normal_end - normal_start;
|
||||||
Trace::Timestamp remap_run = remap_end - remap_start;
|
auto map_run = map_end - map_start;
|
||||||
|
auto remap_run = remap_end - remap_start;
|
||||||
|
|
||||||
Trace::Timestamp diff_run = map_run > remap_run ? map_run - remap_run : remap_run - map_run;
|
auto diff_run = map_run > remap_run ? map_run - remap_run : remap_run - map_run;
|
||||||
|
|
||||||
if (check_pat && diff_run * 100 / tsc_freq) {
|
log("memory non writecombined ", normal_run * 1000 / tsc_freq, " us");
|
||||||
|
log("memory writecombined ", map_run * 1000 / tsc_freq, " us");
|
||||||
|
log("memory writecombined remapped ", remap_run * 1000 / tsc_freq, " us");
|
||||||
|
log("variance writecombined tests ", diff_run * 1000 / tsc_freq, " us");
|
||||||
|
|
||||||
|
if (check_pat && diff_run * 10 / tsc_freq) {
|
||||||
failed ++;
|
failed ++;
|
||||||
|
|
||||||
error("map=", Hex(map_run), " remap=", Hex(remap_run), " --> "
|
error("PAT test considered failed - time difference above 100us");
|
||||||
"diff=", Hex(diff_run), " freq_tsc=", tsc_freq, " ",
|
|
||||||
diff_run * 1000 / tsc_freq, " us");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Nova::revoke(Nova::Mem_crd(remap_addr >> PAGE_4K, DS_ORDER, all));
|
Nova::revoke(Nova::Mem_crd(memory_remap >> PAGE_4K, DS_ORDER, all));
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_server_oom(Genode::Env &env)
|
void test_server_oom(Genode::Env &env)
|
||||||
|
Loading…
Reference in New Issue
Block a user