The GNU Hurd ============ This is not the GNU Hurd. But it might become it at some day. The intention is to port the GNU Hurd to run on the L4 microkernel. This is work in progress. How to build ------------ Building the code is straight forward: $ autoreconf -f -i -s $ ./configure --enable-maintainer-mode --prefix=/l4 $ make $ make install $ mkdir /l4/boot $ install -s laden/laden /l4/boot $ install -s wortel/wortel /l4/boot $ install -s physmem/physmem /l4/boot $ install -s task/task /l4/boot $ install -s deva/deva /l4/boot $ install -s ruth/ruth /l4/boot You need at least automake 1.7 and autoconf 2.53. Note that the binaries MUST be stripped, otherwise they will overlap in memory (or you can adjust the load addresses). Installation on ia32 -------------------- Prerequisites: Pistachio-0.4 (or CVS) with the patch below. You can find information about how to download the Pistachio source distribution (which includes the kernel and sigma0) at the following URL: http://www.l4ka.org/projects/pistachio/download.php sigma0 must be built with a different link base than the default value 0x20000, because that conflicts with GRUB (on ia32). I have successfully used a link base of 0x40000. Use the configure option --with-s0-linkbase=0x40000 when configuring the user space of the L4 distribution. You only need the ia32-kernel and sigma0 binary from the L4 distribution. You may want to install the other programs and utilities as well to test your L4 kernel, though. Then set up GRUB to boot laden as the kernel, and the L4 kernel, sigma0, wortel (the rootserver), physmem and task as its modules (in that order). Also, add some dummy entries for the not-yet-existing modules deva, deva-store and rootfs (just repeat the task server entry another three times) Try the debug option (-D) to laden and wortel to see some output from them. They are silent by default. Here is an example menu.lst file for GNU GRUB: title The GNU Hurd on L4 root (hd0,0) kernel /boot/laden -D module /boot/ia32-kernel module /boot/sigma0 module /boot/wortel -D module /boot/physmem module /boot/task module /boot/deva module /boot/task module /boot/ruth Pistachio Patch --------------- There are a couple of patches you need to apply to the L4 kernel to be able to use it with the Hurd on L4 servers. These patches add missing features, or tweak the kernel interfaces to meet our requirements. You can apply all patches in one go by changing your working directory to the pistachio source tree, and feed this README file through patch: $ cd pistachio $ patch -p1 < /my/path/to/hurd-l4/README The following patch fixes a problem with IPC propagation and with receiving from any local thread. 2004-10-28 Marcus Brinkmann * src/api/v4/ipc.cc (SYS_IPC): If receiving from any local thread, look up the first sending local thread. 2004-10-23 Marcus Brinkmann * src/api/v4/ipc.cc (SYS_IPC): If propagating, modify the originator's partner to wait for the new receiver if the originator is in a closed wait for the sender. Check if the receiver is waiting for the current sender, not for the originator thread. Index: kernel/src/api/v4/ipc.cc =================================================================== RCS file: /public-cvs/pistachio/kernel/src/api/v4/ipc.cc,v retrieving revision 1.57.4.6 diff -u -r1.57.4.6 ipc.cc --- pistachio/kernel/src/api/v4/ipc.cc 3 Jun 2004 13:58:57 -0000 1.57.4.6 +++ pistachio/kernel/src/api/v4/ipc.cc 23 Oct 2004 00:33:45 -0000 @@ -292,6 +292,9 @@ && (current->get_space() == virt_sender->get_space() || current->get_space() == to_tcb->get_space())) { + if (virt_sender->get_state().is_waiting() && + virt_sender->get_partner() == sender_id) + virt_sender->set_partner(to_tid); sender_id = current->get_virtual_sender(); } else @@ -313,7 +316,7 @@ // optimized for receive and wait any if (EXPECT_FALSE( (!to_tcb->get_state().is_waiting()) || - ( to_tcb->get_partner() != sender_id && + ( to_tcb->get_partner() != current->get_global_id() && !to_tcb->get_partner().is_anythread() && !( to_tcb->get_partner().is_anylocalthread() && to_tcb->get_space() == current->get_space() ) ) )) @@ -517,9 +520,24 @@ SYS_IPC (threadid_t to_tid, threadid_t f } } else - { /* anylocal */ -#warning wait_local incorrect - from_tcb = current->send_head; + { + /* anylocal */ + + tcb_t *head = current->send_head; + from_tcb = NULL; + + if (head) + { + tcb_t *tcb = head; + + do + { + if (tcb->get_space () == current->get_space ()) + from_tcb = tcb; + tcb = tcb->send_list.next; + } + while (!from_tcb && tcb != head); + } } TRACE_IPC("receive phase curr=%t, from=%t\n", current, from_tcb); The following patch adds support for the ELF TLS ABI to L4Ka::Pistachio. This is based on Espen's suggestion to use %gs:4 instead of %gs:0 for the UTCB, to free %gs:0 for the ELF thread pointer. I am not sure this patch helps anybody here. It certainly won't do the trick for the L4Linux guys. But it opens a compromise path were L4 still supports the ELF standard (although not the GNU variant) on ia32. I am posting this patch just so that you know what I am up to, and to define more precisely one of the possible options in the stale-mate ELF TLS ABI vs L4 ABI discussion. I will also work on alternatives to this, so this is not the last word. I chose to not save/restore the value in %gs:0, but to add a system call to set it. This is the simplest approach I can think of, and should also be the fastest for now, as setting the value is rare (if you have one user thread per kernel thread). I also put the value into the kernel tcb, not in the UTCB, because I think this matches existing precedence (ie, on ia64, gr13 is also not preserved across IPC). So, this is a really simple patch. Doesn't do much, but works for me. The costs (apart from setting up the desired value) is writing the value from the ktcb to %gs:0 on every thread switch except fast path of IPC. That's all. I suck at hand-written assembler. So the ordering of the commands possibly can be further optimized (move the pop %edx down a bit?). ===File l4-tls-ia32.patch=============== 2004-11-19 Marcus Brinkmann * kernel/include/glue/v4-ia32/config.h (ARCH_SYSCALL0): New macro. (user_set_gs0) [!ASSEMBLY && __cplusplus]: Define prototype. * kernel/include/glue/v4-ia32/ktcb.h (arch_ktcb_t): Add new member user_gs0. * kernel/include/glue/v4-ia32/syscalls.h (sys_set_gs0): New prototype. * kernel/include/glue/v4-ia32/tcb.h (tcb_t::init_stack): Initialize ARCH.user_gs0. (tcb_t::switch_to): Use %gs:4 for the UTCB, and set %gs:0 to the user-settable value DEST->get_arch()->user_gs0. * kernel/src/glue/v4-ia32/gs0.cc: New file. * kernel/src/glue/v4-ia32/init.cc: Make the IA32_UTCB segment two words large. * kernel/src/glue/v4-ia32/Makeconf (SOURCES): Add gs0.cc. * kernel/src/glue/v4-ia32/trap.S: Use %gs:4 for the UTCB. * kernel/src/glue/v4-ia32/user.cc (SYSCALL_STUB(system_clock)): Use %gs:4 for the UTCB. (SYSCALL_STUB(set_gs0)): New syscall stub. (exc_user_syscall): Handle SYSCALL_STUB(set_gs0). * user/include/l4/ia32/vregs.h (__L4_X86_Utcb): Use %gs:4 instead of %gs:0. diff -rupN pistachio/kernel/include/glue/v4-ia32/config.h pistachio/kernel/include/glue/v4-ia32/config.h --- pistachio/kernel/include/glue/v4-ia32/config.h 2005-01-22 01:45:47.000000000 +0100 +++ pistachio/kernel/include/glue/v4-ia32/config.h 2005-01-22 02:14:14.000000000 +0100 @@ -54,6 +54,11 @@ #define KIP_ARCH_PAGEINFO {SHUFFLE2(rwx:6, size_mask:((1 << IA32_PAGE_BITS)) >> 10)} #endif #define KIP_SYSCALL(x) ((u8_t*)(x) - (u8_t*)&kip) +#define ARCH_SYSCALL0 KIP_SYSCALL (user_set_gs0) + +#if !defined(ASSEMBLY) && defined(__cplusplus) +extern "C" void SECTION (".user.syscall.set_gs0") user_set_gs0 (void); +#endif /* configuration for KTCBs * make sure the KTCBs fit entirely into the TCB area @@ -103,7 +108,7 @@ #define PAGEDIR_STUFF_END (THREAD_COUNT + IA32_PAGEDIR_SIZE) #endif -/* V4 UTCB addressed via %gs:0 */ +/* V4 UTCB addressed via %gs:4 */ #define MYUTCB_MAPPING __UL(0xDF000000) /* trampoline to set up segment registers after sysexit */ diff -rupN pistachio/kernel/include/glue/v4-ia32/ktcb.h pistachio/kernel/include/glue/v4-ia32/ktcb.h --- pistachio/kernel/include/glue/v4-ia32/ktcb.h 2004-10-06 21:13:40.000000000 +0200 +++ pistachio/kernel/include/glue/v4-ia32/ktcb.h 2005-01-22 02:14:14.000000000 +0100 @@ -34,6 +34,8 @@ typedef struct { + /* The value the user wants to see in %gs:0. */ + word_t user_gs0; } arch_ktcb_t; diff -rupN pistachio/kernel/include/glue/v4-ia32/syscalls.h pistachio/kernel/include/glue/v4-ia32/syscalls.h --- pistachio/kernel/include/glue/v4-ia32/syscalls.h 2003-09-24 21:12:22.000000000 +0200 +++ pistachio/kernel/include/glue/v4-ia32/syscalls.h 2005-01-22 02:14:14.000000000 +0100 @@ -184,6 +184,8 @@ #define return_memory_control() return +void sys_set_gs0 (word_t user_gs0, ia32_exceptionframe_t *__frame); + /* entry functions for exceptions */ extern "C" void exc_user_sysipc(void); diff -rupN pistachio/kernel/include/glue/v4-ia32/tcb.h pistachio/kernel/include/glue/v4-ia32/tcb.h --- pistachio/kernel/include/glue/v4-ia32/tcb.h 2005-01-22 01:45:47.000000000 +0100 +++ pistachio/kernel/include/glue/v4-ia32/tcb.h 2005-01-22 02:14:14.000000000 +0100 @@ -173,6 +173,8 @@ INLINE void tcb_t::init_stack() { stack = get_stack_top(); //TRACE("stack = %p\n", stack); + + arch.user_gs0 = 0; } @@ -254,7 +256,7 @@ INLINE void tcb_t::switch_to(tcb_t * des " jne 1f \n" " movl $1, __is_small \n" "1: popl %%eax \n" - " movl %3, %%gs:0 \n" + " movl %3, %%gs:4 \n" " jmp *%%eax \n" "2: /* switch to large space */ \n" @@ -281,7 +283,10 @@ INLINE void tcb_t::switch_to(tcb_t * des " movl %%ecx, %%cr3 \n" "4: popl %%edx /* activation addr */ \n" - " movl %3, %%gs:0 /* update current UTCB */ \n" + " movl %3, %%gs:4 /* update current UTCB */ \n" + + " movl %c8(%2), %%ecx /* get dest.arch.user_gs0 */ \n" + " movl %%ecx, %%gs:0 /* install it */ \n" " jmp *%%edx \n" "9: movl %2, %1 /* restore 'this' */ \n" @@ -298,7 +303,8 @@ INLINE void tcb_t::switch_to(tcb_t * des "i" (OFS_TCB_PDIR_CACHE), // 6 "a" ((word_t) dest->space + (CONFIG_SMP_MAX_CPUS * IA32_PAGE_SIZE) - + (SMALL_SPACE_ID >> IA32_PAGEDIR_BITS) * 4) // 7 + + (SMALL_SPACE_ID >> IA32_PAGEDIR_BITS) * 4), // 7 + "i" (OFS_TCB_ARCH) // 8 : "ecx", "edx", "memory"); @@ -330,7 +336,10 @@ INLINE void tcb_t::switch_to(tcb_t * des "movl %7, %%cr3 \n\t" /* reload pagedir */ "2: \n\t" "popl %%edx \n\t" /* load activation addr */ - "movl %3, %%gs:0 \n\t" /* update current UTCB */ + "movl %3, %%gs:4 \n\t" /* update current UTCB */ + + "movl %c9(%2), %%ecx \n\t" /* get dest.arch.user_gs0 */ + "movl %%ecx, %%gs:0 \n\t" /* install it */ "jmp *%%edx \n\t" "3: \n\t" @@ -348,10 +357,11 @@ INLINE void tcb_t::switch_to(tcb_t * des "i" (OFS_TCB_PDIR_CACHE), // 6 "a" (dest->pdir_cache), // 7 #ifdef CONFIG_CPU_IA32_P4 - "c" (this->pdir_cache) // 8 + "c" (this->pdir_cache), // 8 #else - "c" (dest->pdir_cache) // dummy + "c" (dest->pdir_cache), // dummy #endif + "i" (OFS_TCB_ARCH) // 9 : "edx", "memory" ); diff -rupN pistachio/kernel/src/glue/v4-ia32/gs0.cc pistachio/kernel/src/glue/v4-ia32/gs0.cc --- pistachio/kernel/src/glue/v4-ia32/gs0.cc 1970-01-01 01:00:00.000000000 +0100 +++ pistachio/kernel/src/glue/v4-ia32/gs0.cc 2005-01-22 02:14:14.000000000 +0100 @@ -0,0 +1,15 @@ +#include INC_API(tcb.h) +#include INC_ARCH(trapgate.h) + +void +sys_set_gs0 (word_t user_gs0, + ia32_exceptionframe_t *__frame) +{ + get_current_tcb()->get_arch()->user_gs0 = user_gs0; + + asm volatile (" movl %0, %%gs:0 \n" + : + : "r" (user_gs0)); + + return; +} diff -rupN pistachio/kernel/src/glue/v4-ia32/init.cc pistachio/kernel/src/glue/v4-ia32/init.cc --- pistachio/kernel/src/glue/v4-ia32/init.cc 2005-01-22 01:45:49.000000000 +0100 +++ pistachio/kernel/src/glue/v4-ia32/init.cc 2005-01-22 02:14:14.000000000 +0100 @@ -222,12 +222,13 @@ static void setup_gdt(ia32_tss_t & tss, gdt[gdt_idx(IA32_UDS)].set_seg(0, ~0, 3, ia32_segdesc_t::data); /* MyUTCB pointer, - * we use a separate page for all processors allocated in space_t - * and have one UTCB entry per cache line in the SMP case */ + * we use a separate page for all processors allocated in space_t + * and have one user word and one UTCB entry per cache line in the + * SMP case */ ASSERT(unsigned(cpuid * CACHE_LINE_SIZE) < IA32_PAGE_SIZE); gdt[gdt_idx(IA32_UTCB)].set_seg((u32_t)MYUTCB_MAPPING + (cpuid * CACHE_LINE_SIZE), - sizeof(threadid_t) - 1, + sizeof (word_t) + sizeof(threadid_t) - 1, 3, ia32_segdesc_t::data); /* the TSS diff -rupN pistachio/kernel/src/glue/v4-ia32/Makeconf pistachio/kernel/src/glue/v4-ia32/Makeconf --- pistachio/kernel/src/glue/v4-ia32/Makeconf 2004-03-16 05:05:06.000000000 +0100 +++ pistachio/kernel/src/glue/v4-ia32/Makeconf 2005-01-22 02:14:14.000000000 +0100 @@ -3,7 +3,7 @@ LDSCRIPT = $(SRCDIR)/src/glue/$(API)-$(A CURDIR = src/glue/v4-ia32 SOURCES += $(addprefix $(CURDIR)/, init.cc idt.cc exception.cc \ space.cc debug.cc resources.cc thread.cc user.cc trap.S \ - ctors.cc smp.cc trampoline.S) + ctors.cc smp.cc trampoline.S gs0.cc) SOURCES+= src/generic/linear_ptab_walker.cc \ src/generic/mapping_alloc.cc \ diff -rupN pistachio/kernel/src/glue/v4-ia32/space.cc pistachio/kernel/src/glue/v4-ia32/space.cc --- pistachio/kernel/src/glue/v4-ia32/space.cc 2005-01-22 01:45:49.000000000 +0100 +++ pistachio/kernel/src/glue/v4-ia32/space.cc 2005-01-22 02:14:14.000000000 +0100 @@ -329,7 +329,7 @@ void SECTION(".init.memory") space_t::in /* MYUTCB mapping * allocate a full page for all myutcb pointers. - * access must be performed via gs:0, when setting up the gdt + * access must be performed via gs:4, when setting up the gdt * each processor gets a full cache line to avoid bouncing * page is user-writable and global */ diff -rupN pistachio/kernel/src/glue/v4-ia32/trap.S pistachio/kernel/src/glue/v4-ia32/trap.S --- pistachio/kernel/src/glue/v4-ia32/trap.S 2004-11-17 01:48:13.000000000 +0100 +++ pistachio/kernel/src/glue/v4-ia32/trap.S 2005-01-22 02:14:14.000000000 +0100 @@ -175,7 +175,7 @@ fp_save_resources_done: pushl $fp_ipc_done movl OFS_TCB_MYSELF_LOCAL(%esi), %edi // local id movl OFS_TCB_PDIR_CACHE(%esi), %eax // new PDIR - movl %edi, %gs:0 + movl %edi, %gs:4 movl %esp, OFS_TCB_STACK(%ebx) // store stack ptr movl OFS_TCB_STACK(%esi), %esp // load stack ptr popl %ecx // load dest addr @@ -241,7 +241,7 @@ fp_save_resources_done: movl %ecx, %gs movl $1, __is_small 1: popl %ecx - movl %edi, %gs:0 + movl %edi, %gs:4 jmp *%ecx 2: /* switch to large space */ @@ -268,7 +268,7 @@ fp_save_resources_done: movl %ecx, %cr3 9: popl %ecx - movl %edi, %gs:0 + movl %edi, %gs:4 #endif /* CONFIG_IA32_SMALL_SPACES */ diff -rupN pistachio/kernel/src/glue/v4-ia32/user.cc pistachio/kernel/src/glue/v4-ia32/user.cc --- pistachio/kernel/src/glue/v4-ia32/user.cc 2005-01-22 01:45:49.000000000 +0100 +++ pistachio/kernel/src/glue/v4-ia32/user.cc 2005-01-22 02:14:14.000000000 +0100 @@ -172,7 +172,7 @@ SYSCALL_STUB(system_clock) "add %c0(%%ecx), %%ecx \n" /* procdesc */ #ifdef CONFIG_SMP /* get processor # --> allow for differently clocked CPUs */ - "mov %%gs:0, %%eax \n" /* myutcb */ + "mov %%gs:4, %%eax \n" /* myutcb */ "mov %c2(%%eax), %%eax \n" "shl %3, %%eax \n" "add %%eax, %%ecx \n" @@ -344,6 +344,14 @@ SYSCALL_STUB(memory_control) : "i"(SYS_SYSCALL_NUM)); } +SYSCALL_STUB(set_gs0) +{ + __asm__ __volatile__( + SYSCALL_LABEL (set_gs0) + : + : "i"(SYS_SYSCALL_NUM)); +} + #define IS_SYSCALL(x) ((frame->eip - (u32_t)get_current_space()->get_kip_page_area().get_base()) == ((u32_t)(&entry_##x) - (u32_t)get_kip() + 2)) @@ -399,6 +407,11 @@ IA32_EXC_NO_ERRORCODE(exc_user_syscall, frame); } + else if (IS_SYSCALL(set_gs0)) + { + sys_set_gs0(frame->eax, frame); + } + else printf("unknown syscall\n"); return; diff -rupN pistachio/user/include/l4/ia32/vregs.h pistachio/user/include/l4/ia32/vregs.h --- pistachio/user/include/l4/ia32/vregs.h 2004-11-17 01:48:13.000000000 +0100 +++ pistachio/user/include/l4/ia32/vregs.h 2005-01-22 02:14:14.000000000 +0100 @@ -48,7 +48,7 @@ L4_INLINE L4_Word_t * __L4_X86_Utcb (voi __asm__ __volatile__ ( "/* __L4_X86_Utcb() */ \n" - " mov %%gs:0, %0 \n" + " mov %%gs:4, %0 \n" : /* outputs */ "=r"(utcb)