diff --git a/repos/base/run/rm_nested.run b/repos/base/run/rm_nested.run index 054ac9eae..c87a0960e 100644 --- a/repos/base/run/rm_nested.run +++ b/repos/base/run/rm_nested.run @@ -29,3 +29,6 @@ build_boot_image "core ld.lib.so init test-rm_nested" append qemu_args "-nographic " run_genode_until ".*--- finished nested region map test ---.*\n" 300 + +grep_output {(Error)} +compare_output_to {} diff --git a/repos/base/src/test/rm_nested/main.cc b/repos/base/src/test/rm_nested/main.cc index e69f2438a..440f2568d 100644 --- a/repos/base/src/test/rm_nested/main.cc +++ b/repos/base/src/test/rm_nested/main.cc @@ -42,11 +42,14 @@ class Local_fault_handler : public Entrypoint Env & _env; Region_map & _region_map; Signal_handler _handler; + volatile unsigned _fault_cnt { 0 }; void _handle_fault() { Region_map::State state = _region_map.state(); + _fault_cnt ++; + log("region-map state is ", state.type == Region_map::State::READ_FAULT ? "READ_FAULT" : state.type == Region_map::State::WRITE_FAULT ? "WRITE_FAULT" : @@ -74,9 +77,125 @@ class Local_fault_handler : public Entrypoint } void dissolve() { Entrypoint::dissolve(_handler); } + + unsigned fault_count() { asm volatile ("":::"memory"); return _fault_cnt; } }; +void nested_regions(Genode::Env &env) +{ + enum { + MANAGED_REGION_TOP_SIZE = 40UL * 1024, + MANAGED_REGION_SHIM1_SIZE = 24UL * 1024, + MANAGED_REGION_SHIM2_SIZE = 16UL * 1024, + MANAGED_REGION_BOTTOM_SIZE = 40UL * 1024, + }; + + Rm_connection rm(env); + + /* top region */ + Region_map_client rm_top(rm.create(MANAGED_REGION_TOP_SIZE)); + Dataspace_client rm_top_client(rm_top.dataspace()); + + void *ptr_top = env.rm().attach(rm_top.dataspace()); + addr_t const addr_top = reinterpret_cast(ptr_top); + log(" region top ", + Hex_range(addr_top, rm_top_client.size())); + + /* shim region 1 */ + Region_map_client rm_shim1(rm.create(MANAGED_REGION_SHIM1_SIZE)); + Dataspace_client rm_shim1_client(rm_shim1.dataspace()); + void *ptr_shim1 = rm_top.attach(rm_shim1.dataspace()); + addr_t const addr_shim1 = reinterpret_cast(ptr_shim1); + + /* shim region 2 */ + Region_map_client rm_shim2(rm.create(MANAGED_REGION_SHIM2_SIZE)); + Dataspace_client rm_shim2_client(rm_shim2.dataspace()); + void *ptr_shim2 = rm_top.attach(rm_shim2.dataspace()); + addr_t const addr_shim2 = reinterpret_cast(ptr_shim2); + + log(" region shim ", + Hex_range(addr_top + addr_shim1, rm_shim1_client.size()), " ", + Hex_range(addr_top + addr_shim2, rm_shim2_client.size())); + + /* attach some memory to region 2 as readonly and touch/map it */ + size_t const shim2_ram_size = PAGE_SIZE * 2; + Dataspace_capability shim2_ram_ds = env.ram().alloc(shim2_ram_size); + enum { + COMPLETE_SIZE = 0, OFFSET_0 = 0, OFFSET_1000 = 0x1000, + USE_LOCAL_ADDR = true, LOCAL_ADDR_0 = 0, LOCAL_ADDR_1000 = 0x1000, + NON_EXECUTABLE = false, + READONLY = false, WRITEABLE = true + }; + void * ptr_shim2_ram = rm_shim2.attach(shim2_ram_ds, COMPLETE_SIZE, + OFFSET_0, USE_LOCAL_ADDR, + LOCAL_ADDR_1000, NON_EXECUTABLE, + READONLY); + addr_t const addr_shim2_ram = reinterpret_cast(ptr_shim2_ram); + addr_t const read_shim2 = addr_top + addr_shim2 + addr_shim2_ram; + + log(" attached mem ", + (sizeof(void *) == 8) ? " " : "", + Hex_range(read_shim2, shim2_ram_size)); + + log(" read mem ", + (sizeof(void *) == 8) ? " " : "", + Hex_range(read_shim2, shim2_ram_size), " value=", + Hex(*(unsigned *)(read_shim2))); + + /* bottom region */ + Region_map_client rm_bottom(rm.create(MANAGED_REGION_BOTTOM_SIZE)); + Dataspace_client rm_bottom_client(rm_bottom.dataspace()); + size_t const size_bottom = MANAGED_REGION_BOTTOM_SIZE - MANAGED_REGION_SHIM2_SIZE; + void const *ptr_bottom = rm_shim1.attach(rm_bottom.dataspace(), size_bottom); + addr_t const addr_bottom = reinterpret_cast(ptr_bottom); + + log(" bottom shim (r) ", + Hex_range(addr_top + addr_shim1 + addr_bottom, rm_bottom_client.size())); + log(" bottom shim (s) ", + Hex_range(addr_top + addr_shim1 + addr_bottom, size_bottom)); + + /* attach some memory to bottom as writeable */ + Dataspace_capability bottom_ram_ds = env.ram().alloc(MANAGED_REGION_BOTTOM_SIZE); + { + void * base_rw = env.rm().attach(bottom_ram_ds); + memset(base_rw, 0xff, MANAGED_REGION_BOTTOM_SIZE); + env.rm().detach(base_rw); + } + void * ptr_bottom_ram = rm_bottom.attach(bottom_ram_ds, COMPLETE_SIZE, + OFFSET_0, USE_LOCAL_ADDR, + LOCAL_ADDR_0, NON_EXECUTABLE, + WRITEABLE); + addr_t const addr_bottom_ram = reinterpret_cast(ptr_bottom_ram); + addr_t const write_bottom = addr_top + addr_shim1 + addr_bottom + addr_bottom_ram; + + log(" attached mem ", + Hex_range(write_bottom, size_bottom)); + + log(" wrote mem ", + Hex_range(write_bottom, size_bottom), " with value=", + Hex(*(unsigned *)write_bottom)); + + log(" try reading mem ", Hex(read_shim2), " - should succeed"); + unsigned value = *(unsigned *)(read_shim2); + if (value != 0) + error(" wrong content read - expected 0, got ", Hex(value)); + + log(" try reading mem ", Hex(read_shim2 + PAGE_SIZE), " - should succeed"); + value = *(unsigned *)(read_shim2 + PAGE_SIZE); + if (value != 0) + error(" wrong content read - expected 0, got ", Hex(value)); + + Local_fault_handler fault_handler(env, rm_shim2); + + log(" try reading mem ", Hex(read_shim2 - PAGE_SIZE), " - should fail"); + value = *(unsigned *)(read_shim2 - PAGE_SIZE); + + if (fault_handler.fault_count() != 1) + error(" could read memory without region attached, value=", Hex(value)); +} + + void Component::construct(Genode::Env & env) { log("--- nested region map test ---"); @@ -113,5 +232,8 @@ void Component::construct(Genode::Env & env) Capability rcap = rm.create(4096); rm.destroy(rcap); + log("test multiple nested regions stacked"); + nested_regions(env); + log("--- finished nested region map test ---"); } diff --git a/tool/autopilot.list b/tool/autopilot.list index 87a66fc14..090050335 100644 --- a/tool/autopilot.list +++ b/tool/autopilot.list @@ -3,6 +3,7 @@ ldso timer lwip rm_fault +rm_nested rom_blk tar_rom noux