From b38fee28672a9ba2ad4c94b1f5c69317b90f8712 Mon Sep 17 00:00:00 2001 From: Christian Prochaska Date: Wed, 6 Mar 2013 15:34:08 +0100 Subject: [PATCH] L4Linux stability improvements - search for alternative virtual address regions upwards, starting from the given start address, in the 'l4re_rm_attach()' and 'Region_manager::reserve_range()' functions - don't treat memory locations above 0x80000000 in l4linux's virtual address space as device memory - align the start address of the vmalloc area according to the assumption in 'devicemaps_init()' Fixes #414. --- ports-foc/patches/l4lx_genode.patch | 400 +++++++++++++++------------ ports-foc/src/lib/l4lx/l4_io.cc | 7 +- ports-foc/src/lib/l4lx/l4_re_c_rm.cc | 41 ++- ports-foc/src/lib/l4lx/rm.cc | 42 ++- 4 files changed, 294 insertions(+), 196 deletions(-) diff --git a/ports-foc/patches/l4lx_genode.patch b/ports-foc/patches/l4lx_genode.patch index d85887f4b..820af3f85 100644 --- a/ports-foc/patches/l4lx_genode.patch +++ b/ports-foc/patches/l4lx_genode.patch @@ -1,64 +1,3 @@ -Index: arch/l4/boot/Makefile -=================================================================== ---- arch/l4/boot/Makefile (revision 25) -+++ arch/l4/boot/Makefile (working copy) -@@ -10,7 +10,7 @@ - $(call if_changed,objcopy) - @echo ' Kernel: $@ is ready' - --lImage: $(obj)/Image vmlinuz$(VMLINUZ_SUFFIX) l4linux$(VMLINUZ_SUFFIX) -+lImage: $(obj)/Image - - vmlinuz$(VMLINUZ_SUFFIX): ldrImage FORCE - $(call if_changed,gzip) -@@ -21,8 +21,8 @@ - - objects-y := ldr.o res.o image.o - --include $(L4OBJ)/l4defs.mk.inc -- -+#include $(L4OBJ)/l4defs.mk.inc -+KBUILD_CFLAGS_i386 = -m32 - KBUILD_CFLAGS := $(filter-out -mregparm=3,$(KBUILD_CFLAGS)) \ - $(L4INC) -I$(L4OBJ)/include/uclibc \ - -Wall -fno-strict-aliasing -O2 -pipe \ -Index: arch/l4/lib/pte.c -=================================================================== ---- arch/l4/lib/pte.c (revision 25) -+++ arch/l4/lib/pte.c (working copy) -@@ -18,7 +18,10 @@ - #include - #include - #include -+#include - -+extern void l4lx_memory_map_physical_page(unsigned long address); -+ - static void l4x_flush_page(struct mm_struct *mm, - unsigned long address, - unsigned long vaddr, -@@ -77,7 +80,7 @@ - if (mm && !l4_is_invalid_cap(mm->context.task)) { - L4XV_V(f); - if (!mm->context.task) -- l4x_printf("%s: Ups, task == 0\n", __func__); -+ LOG_printf("%s: Ups, task == 0\n", __func__); - /* Direct flush in the child, use virtual address in the - * child address space */ - L4XV_L(f); -@@ -93,10 +96,11 @@ - tag = l4_task_unmap(L4RE_THIS_TASK_CAP, - l4_fpage(address & PAGE_MASK, size, flush_rights), - L4_FP_OTHER_SPACES); -+ l4lx_memory_map_physical_page(address); - L4XV_U(f); - } - if (l4_error(tag)) -- l4x_printf("l4_task_unmap error %ld\n", l4_error(tag)); -+ LOG_printf("l4_task_unmap error %ld\n", l4_error(tag)); - } - - #ifdef ARCH_arm Index: arch/l4/Makefile =================================================================== --- arch/l4/Makefile (revision 25) @@ -190,28 +129,6 @@ Index: arch/l4/Kconfig endmenu # stub drivers menu "Debugging options" -Index: arch/l4/kernel/dispatch.c -=================================================================== ---- arch/l4/kernel/dispatch.c (revision 25) -+++ arch/l4/kernel/dispatch.c (working copy) -@@ -271,7 +271,7 @@ - return 0; - - if (l4_msgtag_is_page_fault(tag)) { -- l4x_printf("HYBRID PF!!\n"); -+ LOG_printf("HYBRID PF!!\n"); - /* No exception IPC, it's a page fault, but shouldn't happen */ - goto out_fail; - } -@@ -695,7 +695,7 @@ - enter_kdebug("non hybrid in idle?!"); - } else { - if (unlikely(l4x_handle_async_event(label, utcb, tag))) -- l4x_printf("Async return with error\n"); -+ LOG_printf("Async return with error\n"); - } - } - } Index: arch/l4/kernel/arch-arm/traps.c =================================================================== --- arch/l4/kernel/arch-arm/traps.c (revision 25) @@ -385,19 +302,53 @@ Index: arch/l4/kernel/arch-arm/vmlinux.lds.S _end = .; STABS_DEBUG -Index: arch/l4/kernel/arch-x86/x86_init.c +Index: arch/l4/kernel/arch-x86/rtc.c =================================================================== ---- arch/l4/kernel/arch-x86/x86_init.c (revision 25) -+++ arch/l4/kernel/arch-x86/x86_init.c (working copy) -@@ -42,7 +42,7 @@ - struct x86_init_ops x86_init __initdata = { +--- arch/l4/kernel/arch-x86/rtc.c (revision 25) ++++ arch/l4/kernel/arch-x86/rtc.c (working copy) +@@ -163,6 +163,7 @@ + /* Routines for accessing the CMOS RAM/RTC. */ + unsigned char rtc_cmos_read(unsigned char addr) + { ++#ifdef NOT_GENODE + #ifndef CONFIG_L4_EXTERNAL_RTC + unsigned char val; + +@@ -175,17 +176,22 @@ + #else + return 0; + #endif ++#else /* NOT_GENODE */ ++ return 0; ++#endif /* NOT_GENODE */ + } + EXPORT_SYMBOL(rtc_cmos_read); + + void rtc_cmos_write(unsigned char val, unsigned char addr) + { ++#ifdef NOT_GENODE + #ifndef CONFIG_L4_EXTERNAL_RTC + lock_cmos_prefix(addr); + outb(addr, RTC_PORT(0)); + outb(val, RTC_PORT(1)); + lock_cmos_suffix(addr); + #endif ++#endif /* NOT_GENODE */ + } + EXPORT_SYMBOL(rtc_cmos_write); + +Index: arch/l4/kernel/arch-x86/dispatch.c +=================================================================== +--- arch/l4/kernel/arch-x86/dispatch.c (revision 25) ++++ arch/l4/kernel/arch-x86/dispatch.c (working copy) +@@ -749,6 +749,7 @@ + + TBUF_LOG_EXCP(fiasco_tbuf_log_3val("except ", TBUF_TID(t->user_thread_id), t->trap_nr, t->error_code)); + ++ fiasco_tbuf_log_3val("except ", t->trap_nr, regs->ip, 0); + if (l4x_deliver_signal(r_trapno(t, v), r_err(t, v))) + return 0; /* handled signal, reply */ - .resources = { -- .probe_roms = probe_roms, -+ .probe_roms = x86_init_noop, - .reserve_resources = reserve_standard_io_resources, - .memory_setup = l4x_memory_setup, - }, Index: arch/l4/kernel/arch-x86/vmlinux.lds.S =================================================================== --- arch/l4/kernel/arch-x86/vmlinux.lds.S (revision 25) @@ -600,18 +551,19 @@ Index: arch/l4/kernel/arch-x86/vmlinux.lds.S _end = .; STABS_DEBUG -Index: arch/l4/kernel/arch-x86/dispatch.c +Index: arch/l4/kernel/arch-x86/x86_init.c =================================================================== ---- arch/l4/kernel/arch-x86/dispatch.c (revision 25) -+++ arch/l4/kernel/arch-x86/dispatch.c (working copy) -@@ -749,6 +749,7 @@ - - TBUF_LOG_EXCP(fiasco_tbuf_log_3val("except ", TBUF_TID(t->user_thread_id), t->trap_nr, t->error_code)); - -+ fiasco_tbuf_log_3val("except ", t->trap_nr, regs->ip, 0); - if (l4x_deliver_signal(r_trapno(t, v), r_err(t, v))) - return 0; /* handled signal, reply */ +--- arch/l4/kernel/arch-x86/x86_init.c (revision 25) ++++ arch/l4/kernel/arch-x86/x86_init.c (working copy) +@@ -42,7 +42,7 @@ + struct x86_init_ops x86_init __initdata = { + .resources = { +- .probe_roms = probe_roms, ++ .probe_roms = x86_init_noop, + .reserve_resources = reserve_standard_io_resources, + .memory_setup = l4x_memory_setup, + }, Index: arch/l4/kernel/timer.c =================================================================== --- arch/l4/kernel/timer.c (revision 25) @@ -808,13 +760,14 @@ Index: arch/l4/kernel/main.c return 1; } -@@ -1283,15 +1307,17 @@ +@@ -1283,16 +1307,19 @@ 0, "Main memory"); /* Reserve some part of the virtual address space for vmalloc */ - l4x_vmalloc_memory_start = (unsigned long)l4x_main_memory_start; - if (l4re_rm_reserve_area(&l4x_vmalloc_memory_start, -+ l4x_vmalloc_memory_start = (unsigned long)l4x_main_memory_start + l4x_mainmem_size; ++ l4x_vmalloc_memory_start = ((((unsigned long)l4x_main_memory_start + l4x_mainmem_size) + ++ VMALLOC_OFFSET) & ~(VMALLOC_OFFSET - 1)); #ifdef CONFIG_X86_32 - __VMALLOC_RESERVE, + l4x_vmalloc_memory_size = __VMALLOC_RESERVE; @@ -825,13 +778,15 @@ Index: arch/l4/kernel/main.c - VMALLOC_SIZE << 20, + l4x_vmalloc_memory_size = VMALLOC_SIZE << 20; #endif +- L4RE_RM_SEARCH_ADDR, PGDIR_SHIFT)) { + + if (l4re_rm_reserve_area(&l4x_vmalloc_memory_start, + l4x_vmalloc_memory_size, - L4RE_RM_SEARCH_ADDR, PGDIR_SHIFT)) { ++ L4RE_RM_SEARCH_ADDR, ilog2(VMALLOC_OFFSET))) { LOG_printf("%s: Error reserving vmalloc memory area!\n", __func__); l4x_exit_l4linux(); -@@ -1305,7 +1331,7 @@ + } +@@ -1305,7 +1332,7 @@ #ifdef ARCH_x86 // fixmap area @@ -840,7 +795,7 @@ Index: arch/l4/kernel/main.c if (l4re_rm_reserve_area(&l4x_fixmap_space_start, __end_of_fixed_addresses * PAGE_SIZE, L4RE_RM_SEARCH_ADDR, PAGE_SHIFT) < 0) { -@@ -1416,6 +1442,10 @@ +@@ -1416,6 +1443,10 @@ static void l4x_create_ugate(l4_cap_idx_t forthread, unsigned cpu) { @@ -851,7 +806,7 @@ Index: arch/l4/kernel/main.c l4_msgtag_t r; l4x_user_gate[cpu] = l4x_cap_alloc_noctx(); -@@ -1436,6 +1466,7 @@ +@@ -1436,6 +1467,7 @@ l4_debugger_set_object_name(l4x_user_gate[cpu], n); #endif } @@ -859,7 +814,7 @@ Index: arch/l4/kernel/main.c } #ifdef CONFIG_HOTPLUG_CPU -@@ -1641,11 +1672,15 @@ +@@ -1641,11 +1673,15 @@ l4x_exit_l4linux(); } @@ -875,7 +830,7 @@ Index: arch/l4/kernel/main.c #ifdef CONFIG_L4_DEBUG_REGISTER_NAMES l4_debugger_set_object_name(c, s); -@@ -1906,8 +1941,12 @@ +@@ -1906,8 +1942,12 @@ static int l4x_cpu_virt_phys_map_init(const char *boot_command_line) { @@ -888,7 +843,7 @@ Index: arch/l4/kernel/main.c unsigned i; #ifdef CONFIG_SMP -@@ -1923,9 +1962,10 @@ +@@ -1923,9 +1963,10 @@ } } @@ -900,7 +855,7 @@ Index: arch/l4/kernel/main.c if ((p = strstr(boot_command_line, "l4x_cpus_map="))) { // l4x_cpus_map=0,1,2,3,4,... // the list specifies the physical CPU for each -@@ -1947,10 +1987,12 @@ +@@ -1947,10 +1988,12 @@ LOG_printf("ERROR: Error parsing l4x_cpus_map option\n"); return 1; } @@ -913,7 +868,7 @@ Index: arch/l4/kernel/main.c l4x_cpu_physmap[l4x_nr_cpus].phys_id = pcpu; for (i = 0; i < l4x_nr_cpus; ++i) overbooking |= -@@ -1974,12 +2016,16 @@ +@@ -1974,12 +2017,16 @@ l4x_nr_cpus = v; } @@ -930,7 +885,7 @@ Index: arch/l4/kernel/main.c if (l4_error(l4_scheduler_info(l4re_env()->scheduler, &max_cpus, &cs)) == L4_EOK) { -@@ -1989,6 +2035,8 @@ +@@ -1989,6 +2036,8 @@ l4x_cpu_physmap[0].phys_id = p; } #endif @@ -939,7 +894,7 @@ Index: arch/l4/kernel/main.c LOG_printf("CPU mapping (l:p)[%d]: ", l4x_nr_cpus); for (i = 0; i < l4x_nr_cpus; i++) -@@ -2034,6 +2082,7 @@ +@@ -2034,6 +2083,7 @@ printk("panic: going to sleep forever, bye\n"); L4XV_L(f); LOG_printf("panic: going to sleep forever, bye\n"); @@ -947,7 +902,7 @@ Index: arch/l4/kernel/main.c l4_sleep_forever(); return 0; } -@@ -2302,7 +2351,7 @@ +@@ -2302,7 +2352,7 @@ LOG_printf("Device scan done.\n"); } @@ -956,7 +911,7 @@ Index: arch/l4/kernel/main.c { l4lx_thread_t main_id; struct l4lx_thread_start_info_t si; -@@ -2414,10 +2463,13 @@ +@@ -2414,10 +2464,13 @@ l4x_start_thread_id = l4re_env()->main_thread; @@ -970,7 +925,7 @@ Index: arch/l4/kernel/main.c #ifndef CONFIG_L4_VCPU #ifdef CONFIG_L4_TAMED -@@ -3223,6 +3275,10 @@ +@@ -3223,6 +3276,10 @@ /* Not resolvable: Ooops */ LOG_printf("Non-resolvable page fault at %lx, ip %lx.\n", pfa, ip); // will trigger an oops in caller @@ -981,7 +936,7 @@ Index: arch/l4/kernel/main.c return 0; } -@@ -3419,7 +3475,9 @@ +@@ -3419,7 +3476,9 @@ void exit(int code) { __cxa_finalize(0); @@ -991,6 +946,69 @@ Index: arch/l4/kernel/main.c LOG_printf("Still alive, going zombie???\n"); l4_sleep_forever(); } +Index: arch/l4/kernel/tamed.c +=================================================================== +--- arch/l4/kernel/tamed.c (revision 25) ++++ arch/l4/kernel/tamed.c (working copy) +@@ -366,8 +366,12 @@ + #ifdef CONFIG_L4_VCPU + void l4x_global_halt(void) + { +- l4vcpu_halt(l4x_vcpu_state_current(), l4x_utcb_current(), +- do_vcpu_irq, l4x_srv_setup_recv_wrap); ++ l4vcpu_wait_for_event(l4x_vcpu_state_current(), l4x_utcb_current(), ++ do_vcpu_irq, l4x_srv_setup_recv_wrap); ++#ifdef CONFIG_X86 ++ // on x86, interrupts are enabled after hlt ++ l4x_global_sti(); ++#endif + } + EXPORT_SYMBOL(l4x_global_halt); + +Index: arch/l4/kernel/dispatch.c +=================================================================== +--- arch/l4/kernel/dispatch.c (revision 25) ++++ arch/l4/kernel/dispatch.c (working copy) +@@ -121,6 +121,9 @@ + { + unsigned long devmem; + ++ printk("l4x_handle_dev_mem(%lx) called - currently not supported on Genode.\n", phy); ++ return 0; ++ + #ifdef CONFIG_X86 + if (phy > 0x80000000U) { + if (!(devmem = find_ioremap_entry(phy)) +@@ -271,7 +274,7 @@ + return 0; + + if (l4_msgtag_is_page_fault(tag)) { +- l4x_printf("HYBRID PF!!\n"); ++ LOG_printf("HYBRID PF!!\n"); + /* No exception IPC, it's a page fault, but shouldn't happen */ + goto out_fail; + } +@@ -695,7 +698,7 @@ + enter_kdebug("non hybrid in idle?!"); + } else { + if (unlikely(l4x_handle_async_event(label, utcb, tag))) +- l4x_printf("Async return with error\n"); ++ LOG_printf("Async return with error\n"); + } + } + } +Index: arch/l4/include/asm/arch-arm/pgtable.h +=================================================================== +--- arch/l4/include/asm/arch-arm/pgtable.h (revision 25) ++++ arch/l4/include/asm/arch-arm/pgtable.h (working copy) +@@ -42,6 +42,7 @@ + + #include + ++#define VMALLOC_OFFSET (8*1024*1024) + #define VMALLOC_SIZE 128 + + #define VMALLOC_START l4x_vmalloc_memory_start Index: arch/l4/include/asm/generic/l4lib.h =================================================================== --- arch/l4/include/asm/generic/l4lib.h (revision 25) @@ -1025,6 +1043,92 @@ Index: arch/l4/include/asm/l4lxapi/thread.h /** * \brief Create a thread. * \ingroup thread +Index: arch/l4/boot/Makefile +=================================================================== +--- arch/l4/boot/Makefile (revision 25) ++++ arch/l4/boot/Makefile (working copy) +@@ -10,7 +10,7 @@ + $(call if_changed,objcopy) + @echo ' Kernel: $@ is ready' + +-lImage: $(obj)/Image vmlinuz$(VMLINUZ_SUFFIX) l4linux$(VMLINUZ_SUFFIX) ++lImage: $(obj)/Image + + vmlinuz$(VMLINUZ_SUFFIX): ldrImage FORCE + $(call if_changed,gzip) +@@ -21,8 +21,8 @@ + + objects-y := ldr.o res.o image.o + +-include $(L4OBJ)/l4defs.mk.inc +- ++#include $(L4OBJ)/l4defs.mk.inc ++KBUILD_CFLAGS_i386 = -m32 + KBUILD_CFLAGS := $(filter-out -mregparm=3,$(KBUILD_CFLAGS)) \ + $(L4INC) -I$(L4OBJ)/include/uclibc \ + -Wall -fno-strict-aliasing -O2 -pipe \ +Index: arch/l4/lib/pte.c +=================================================================== +--- arch/l4/lib/pte.c (revision 25) ++++ arch/l4/lib/pte.c (working copy) +@@ -18,7 +18,10 @@ + #include + #include + #include ++#include + ++extern void l4lx_memory_map_physical_page(unsigned long address); ++ + static void l4x_flush_page(struct mm_struct *mm, + unsigned long address, + unsigned long vaddr, +@@ -45,6 +48,12 @@ + } + } else + #endif ++#ifdef NOT_GENODE ++ /* ++ * Device memory is currently not supported on Genode. If this changes, ++ * a check for overlapping 'low memory' and 'device memory' regions ++ * must get added. ++ */ + if (address > 0x80000000UL) { + unsigned long remap; + remap = find_ioremap_entry(address); +@@ -57,8 +66,10 @@ + return; + + address = remap; ++ } else ++#endif /* NOT_GENODE */ + +- } else if ((address & PAGE_MASK) == 0) ++ if ((address & PAGE_MASK) == 0) + address = PAGE0_PAGE_ADDRESS; + + #if 0 +@@ -77,7 +88,7 @@ + if (mm && !l4_is_invalid_cap(mm->context.task)) { + L4XV_V(f); + if (!mm->context.task) +- l4x_printf("%s: Ups, task == 0\n", __func__); ++ LOG_printf("%s: Ups, task == 0\n", __func__); + /* Direct flush in the child, use virtual address in the + * child address space */ + L4XV_L(f); +@@ -93,10 +104,11 @@ + tag = l4_task_unmap(L4RE_THIS_TASK_CAP, + l4_fpage(address & PAGE_MASK, size, flush_rights), + L4_FP_OTHER_SPACES); ++ l4lx_memory_map_physical_page(address); + L4XV_U(f); + } + if (l4_error(tag)) +- l4x_printf("l4_task_unmap error %ld\n", l4_error(tag)); ++ LOG_printf("l4_task_unmap error %ld\n", l4_error(tag)); + } + + #ifdef ARCH_arm Index: arch/x86/lib/memcpy_32.c =================================================================== --- arch/x86/lib/memcpy_32.c (revision 25) @@ -1158,57 +1262,3 @@ Index: include/asm-generic/vmlinux.lds.h . = ALIGN((align)); \ VMLINUX_SYMBOL(__end_rodata) = .; \ } \ -Index: arch/l4/kernel/tamed.c -=================================================================== ---- arch/l4/kernel/tamed.c (revision 25) -+++ arch/l4/kernel/tamed.c (working copy) -@@ -366,8 +366,12 @@ - #ifdef CONFIG_L4_VCPU - void l4x_global_halt(void) - { -- l4vcpu_halt(l4x_vcpu_state_current(), l4x_utcb_current(), -- do_vcpu_irq, l4x_srv_setup_recv_wrap); -+ l4vcpu_wait_for_event(l4x_vcpu_state_current(), l4x_utcb_current(), -+ do_vcpu_irq, l4x_srv_setup_recv_wrap); -+#ifdef CONFIG_X86 -+ // on x86, interrupts are enabled after hlt -+ l4x_global_sti(); -+#endif - } - EXPORT_SYMBOL(l4x_global_halt); - -Index: arch/l4/kernel/arch-x86/rtc.c -=================================================================== ---- arch/l4/kernel/arch-x86/rtc.c (revision 25) -+++ arch/l4/kernel/arch-x86/rtc.c (working copy) -@@ -163,6 +163,7 @@ - /* Routines for accessing the CMOS RAM/RTC. */ - unsigned char rtc_cmos_read(unsigned char addr) - { -+#ifdef NOT_GENODE - #ifndef CONFIG_L4_EXTERNAL_RTC - unsigned char val; - -@@ -175,17 +176,22 @@ - #else - return 0; - #endif -+#else /* NOT_GENODE */ -+ return 0; -+#endif /* NOT_GENODE */ - } - EXPORT_SYMBOL(rtc_cmos_read); - - void rtc_cmos_write(unsigned char val, unsigned char addr) - { -+#ifdef NOT_GENODE - #ifndef CONFIG_L4_EXTERNAL_RTC - lock_cmos_prefix(addr); - outb(addr, RTC_PORT(0)); - outb(val, RTC_PORT(1)); - lock_cmos_suffix(addr); - #endif -+#endif /* NOT_GENODE */ - } - EXPORT_SYMBOL(rtc_cmos_write); - diff --git a/ports-foc/src/lib/l4lx/l4_io.cc b/ports-foc/src/lib/l4lx/l4_io.cc index 95ce4eeb5..5136f59ad 100644 --- a/ports-foc/src/lib/l4lx/l4_io.cc +++ b/ports-foc/src/lib/l4lx/l4_io.cc @@ -71,7 +71,12 @@ extern "C" { Io_mem_connection *iomem = new (env()->heap()) Io_mem_connection(phys, size); L4lx::Dataspace *ds = L4lx::Env::env()->dataspaces()->insert("iomem", iomem->dataspace()); - L4lx::Env::env()->rm()->attach_at(ds, size, 0, (void*)virt); + if (!L4lx::Env::env()->rm()->attach_at(ds, size, 0, (void*)virt)) { + PERR("Could not reserve IO mem region at %lx", virt); + L4lx::Env::env()->dataspaces()->remove(ds); + destroy(env()->heap(), iomem); + return 1; + } return 0; } diff --git a/ports-foc/src/lib/l4lx/l4_re_c_rm.cc b/ports-foc/src/lib/l4lx/l4_re_c_rm.cc index 6a0ea58d2..16fabb64d 100644 --- a/ports-foc/src/lib/l4lx/l4_re_c_rm.cc +++ b/ports-foc/src/lib/l4lx/l4_re_c_rm.cc @@ -27,8 +27,10 @@ namespace Fiasco { using namespace Fiasco; -static const bool DEBUG = false; /* print usage of region map functions */ -static const bool DEBUG_FIND = false; /* print also usage of region map lookups */ +static const bool DEBUG = false; /* print usage of region map functions */ +static const bool DEBUG_FIND = false; /* print also usage of region map lookups */ +static const bool DEBUG_SEARCH = false; /* print also information about the + search for alternative address ranges */ enum { L4RE_SEARCH_FOR_REGION = 0x20, @@ -67,8 +69,10 @@ extern "C" { { using namespace Genode; + void *original_start = *start; + if (DEBUG) - PDBG("start=%p size=%lx flags=%lx mem=%lx offs=%lx align=%x", + PDBG("start=%p size=%lx flags=%lx mem=%lx offs=%lx align=%u", *start, size, flags, mem, offs, align); L4lx::Dataspace *ds = L4lx::Env::env()->dataspaces()->find_by_ref(mem); @@ -77,11 +81,30 @@ extern "C" { return -L4_ERANGE; } - if(!L4lx::Env::env()->rm()->attach_at(ds, size, offs, *start)) { - if (flags & L4RE_SEARCH_FOR_REGION) /* search flag */ - *start = L4lx::Env::env()->rm()->attach(ds); - else { - PWRN("Couldn't attach ds of size %lx at %p", size, *start); + while (!L4lx::Env::env()->rm()->attach_at(ds, size, offs, *start)) { + if (flags & L4RE_SEARCH_FOR_REGION) /* search flag */ { + /* the original start address might have a different alignment */ + l4_addr_t start_addr = (l4_addr_t)*start; + l4_addr_t aligned_start_addr = align_addr(start_addr, align); + if (aligned_start_addr != start_addr) { + if (DEBUG_SEARCH) + PDBG("attach failed: start=%lx, trying %lx instead", + start_addr, aligned_start_addr); + *start = (void*)aligned_start_addr; + } else { + if (start_addr <= ((addr_t)~0 - 2*(1 << align) + 1)) { + if (DEBUG_SEARCH) + PDBG("attach failed: start=%lx, trying %lx instead", + start_addr, start_addr + (1 << align)); + start_addr += (1 << align); + *start = (void*)start_addr; + } else { + PWRN("Couldn't attach ds of size 0x%lx at %p", size, original_start); + return -L4_ERANGE; + } + } + } else { + PWRN("Couldn't attach ds of size 0x%lx at %p", size, original_start); return -L4_ERANGE; } } @@ -116,7 +139,7 @@ extern "C" { unsigned flags, unsigned char align) { if (DEBUG) - PDBG("*start=%lx size=%lx align=%x flags=%x", + PDBG("*start=%lx size=%lx align=%u flags=%x", *start, size, align, flags); L4lx::Region *r = L4lx::Env::env()->rm()->reserve_range(size, align, *start); diff --git a/ports-foc/src/lib/l4lx/rm.cc b/ports-foc/src/lib/l4lx/rm.cc index 65dfb7a8d..4165c284f 100644 --- a/ports-foc/src/lib/l4lx/rm.cc +++ b/ports-foc/src/lib/l4lx/rm.cc @@ -15,6 +15,7 @@ #include #include #include +#include /* L4lx includes */ #include @@ -27,6 +28,8 @@ namespace Fiasco { using namespace L4lx; +static const bool DEBUG_SEARCH = false; /* print information about the search + for alternative address ranges */ Region* Region_manager::find_region(Genode::addr_t *addr, Genode::size_t *size) { @@ -85,12 +88,6 @@ bool Region_manager::attach_at(Dataspace *ds, Genode::size_t size, Genode::env()->rm_session()->attach(ds->cap(), size, offset, true, (Genode::addr_t) addr); } catch(...) { - /* - * This should happen only when Linux uses some special address, - * already used by Genode's heap, for instance some iomem for - * a directly used device. - */ - PERR("Region conflict at %p", addr); return false; } metadata(addr, Region((Genode::addr_t)addr, ds->size(), ds)); @@ -103,25 +100,48 @@ Region* Region_manager::reserve_range(Genode::size_t size, int align, { using namespace Genode; void* addr = 0; + addr_t original_start = start; while (true) { + Rm_connection *rmc = 0; + try { /* * We attach a managed-dataspace as a placeholder to * Genode's region-map */ - Rm_connection *rmc = new (env()->heap()) Rm_connection(0, size); + rmc = new (env()->heap()) Rm_connection(0, size); addr = start ? env()->rm_session()->attach_at(rmc->dataspace(), start) : env()->rm_session()->attach(rmc->dataspace()); //PDBG("attach done addr=%p!", addr); break; } catch(Rm_session::Attach_failed e) { - PWRN("attach failed start=%lx", start); - if (start) /* attach with pre-defined address failed, so search one */ - start = 0; - else + destroy(env()->heap(), rmc); + /* attach with pre-defined address failed, so search one */ + if (start) { + /* the original start address might have a different alignment */ + addr_t aligned_start = align_addr(start, align); + if (aligned_start != start) { + if (DEBUG_SEARCH) + PDBG("attach failed: start=%lx, trying %lx instead", + start, aligned_start); + start = aligned_start; + } else { + if (start <= ((addr_t)~0 - 2*(1 << align) + 1)) { + if (DEBUG_SEARCH) + PDBG("attach failed: start=%lx, trying %lx instead", + start, start + (1 << align)); + start += (1 << align); + } else { + PWRN("attach failed: start=%lx, size=0x%zx, align=%d", original_start, size, align); + return 0; + } + } + } else { + PWRN("attach failed: start=0, size=0x%zx, align=%d", size, align); return 0; + } } }