diff options
-rw-r--r-- | configure.ac | 5 | ||||
-rw-r--r-- | libl4/l4/compat/types.h | 150 | ||||
-rw-r--r-- | physmem/Makefile.am | 36 | ||||
-rw-r--r-- | physmem/README | 6 | ||||
-rw-r--r-- | physmem/ia32-cmain.c | 55 | ||||
-rw-r--r-- | physmem/ia32-crt0.S | 47 | ||||
-rw-r--r-- | physmem/output.c | 206 | ||||
-rw-r--r-- | physmem/output.h | 35 | ||||
-rw-r--r-- | physmem/physmem.c | 42 | ||||
-rw-r--r-- | physmem/physmem.h | 31 | ||||
-rw-r--r-- | wortel/README | 9 | ||||
-rw-r--r-- | wortel/ia32-cmain.c | 76 | ||||
-rw-r--r-- | wortel/wortel.c | 256 | ||||
-rw-r--r-- | wortel/wortel.h | 12 |
14 files changed, 892 insertions, 74 deletions
diff --git a/configure.ac b/configure.ac index fe6dc87..44429a9 100644 --- a/configure.ac +++ b/configure.ac @@ -76,9 +76,10 @@ fi # Checks for library functions. AC_CONFIG_FILES([Makefile - laden/Makefile - wortel/Makefile libl4/ia32/Makefile libl4/Makefile + laden/Makefile + wortel/Makefile + physmem/Makefile libhurd-slab/Makefile libhurd-ihash/Makefile doc/Makefile]) diff --git a/libl4/l4/compat/types.h b/libl4/l4/compat/types.h index 9f7d0fd..a8df02b 100644 --- a/libl4/l4/compat/types.h +++ b/libl4/l4/compat/types.h @@ -1,86 +1,98 @@ -/********************************************************************* - * - * Copyright (C) 2001, 2002, 2003, Karlsruhe University - * - * File path: l4/types.h - * Description: Commonly used L4 types - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $Id: types.h,v 1.1 2003/07/26 17:26:09 marcus Exp $ - * - ********************************************************************/ +/* types.h - Public interface for L4 compatibility types. + Copyright (C) 2003 Free Software Foundation, Inc. + Written by Marcus Brinkmann <marcus@gnu.org>. -#if defined(__cplusplus) -static inline L4_Clock_t operator + (const L4_Clock_t &l, const int r) -{ - return (L4_Clock_t) { raw : l.raw + r }; -} + This file is part of the GNU L4 library. + + The GNU L4 library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License + as published by the Free Software Foundation; either version 2.1 of + the License, or (at your option) any later version. + + The GNU L4 library is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU L4 library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. */ -static inline L4_Clock_t operator + (const L4_Clock_t & l, const L4_Uint64 t) -{ - return (L4_Clock_t) { raw : l.raw + t }; -} +#ifndef _L4_TYPES_H +# error "Never use <l4/compat/types.h> directly; include <l4/types.h> instead." +#endif + +typedef l4_word_t L4_Word_t; +typedef l4_uint64_t L4_Word64_t; +typedef l4_word_t L4_Bool_t; -static inline L4_Clock_t operator - (const L4_Clock_t & c, const int r) -{ - return (L4_Clock_t) { raw : c.raw - r }; + +/* Clock interface. */ + +typedef _L4_RAW +(L4_Word64_t, _L4_STRUCT1 + ({ + l4_clock_t clock; + })) L4_Clock_t; + + + +#define _L4_CLOCK_OP(name, op) \ +static inline L4_Clock_t \ +L4_Clock ## name ## Usec (const L4_Clock_t clock, const L4_Word64_t usec) \ +{ \ + return ((L4_Clock_t) { .clock = clock.clock op usec }); \ } -static inline L4_Clock_t operator - (const L4_Clock_t & c, const L4_Uint64 r) -{ - return (L4_Clock_t) { raw : c.raw - r }; +_L4_CLOCK_OP(Add, +) +_L4_CLOCK_OP(Sub, -) +#undef _L4_CLOCK_OP + + +#define _L4_CLOCK_OP(name, op) \ +static inline L4_Bool_t \ +L4_Clock ## name (const L4_Clock_t clock1, const L4_Clock_t clock2) \ +{ \ + return clock1.clock op clock2.clock; \ } -#endif /* __cplusplus */ +_L4_CLOCK_OP(Earlier, <) +_L4_CLOCK_OP(Later, >) +_L4_CLOCK_OP(Equal, =) +_L4_CLOCK_OP(NotEqual, !=) +#undef _L4_CLOCK_OP + #if defined(__cplusplus) -static inline L4_Bool_t operator < (const L4_Clock_t &l, const L4_Clock_t &r) -{ - return l.raw < r.raw; -} -static inline L4_Bool_t operator > (const L4_Clock_t &l, const L4_Clock_t &r) -{ - return l.raw > r.raw; +#define _L4_CLOCK_OP(op, type) \ +static inline L4_Clock_t \ +operator ## op ## (const L4_Clock_t& clock, const type usec) \ +{ \ + return ((L4_Clock_t) { .clock = clock.clock op usec }); \ } -static inline L4_Bool_t operator <= (const L4_Clock_t &l, const L4_Clock_t &r) -{ - return l.raw <= r.raw; -} +_L4_CLOCK_OP(+, int) +_L4_CLOCK_OP(+, L4_Word64_t) +_L4_CLOCK_OP(-, int) +_L4_CLOCK_OP(-, L4_Word64_t) +#undef _L4_CLOCK_OP -static inline L4_Bool_t operator >= (const L4_Clock_t &l, const L4_Clock_t &r) -{ - return l.raw >= r.raw; -} -static inline L4_Bool_t operator == (const L4_Clock_t &l, const L4_Clock_t &r) -{ - return l.raw == r.raw; +#define _L4_CLOCK_OP(op) \ +static inline L4_Bool_t \ +operator ## op ## (const L4_Clock_t& clock1, const L4_Clock_t& clock2) \ +{ \ + return clock1.clock op clock2.clock; \ } -static inline L4_Bool_t operator != (const L4_Clock_t &l, const L4_Clock_t &r) -{ - return l.raw != r.raw; -} +_L4_CLOCK_OP(<) +_L4_CLOCK_OP(>) +_L4_CLOCK_OP(<=) +_L4_CLOCK_OP(>=) +_L4_CLOCK_OP(==) +_L4_CLOCK_OP(!=) +#undef _L4_CLOCK_OP + #endif /* __cplusplus */ diff --git a/physmem/Makefile.am b/physmem/Makefile.am new file mode 100644 index 0000000..a81ab8a --- /dev/null +++ b/physmem/Makefile.am @@ -0,0 +1,36 @@ +# Makefile.am - Makefile template for the physical memory server. +# Copyright (C) 2003 Free Software Foundation, Inc. +# Written by Marcus Brinkmann. +# +# This file is part of the GNU Hurd. +# +# The GNU Hurd is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# The GNU Hurd is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + +if ARCH_IA32 + ARCH_SOURCES = ia32-crt0.S ia32-cmain.c +endif + +noinst_PROGRAMS = physmem + +physmem_CFLAGS = -I$(srcdir) $(AM_CFLAGS) + +physmem_SOURCES = $(ARCH_SOURCES) \ + output.h output.c \ + physmem.h physmem.c + +/* FIXME: Make linkbase configurable. */ +physmem_LDFLAGS = -u_start -e_start -N -nostdlib -Ttext=0x350000 + +physmem_LDADD = -lgcc
\ No newline at end of file diff --git a/physmem/README b/physmem/README new file mode 100644 index 0000000..5239e80 --- /dev/null +++ b/physmem/README @@ -0,0 +1,6 @@ +physmem +======= + +For now, this is only a small dummy program, not the real physical +memory server. + diff --git a/physmem/ia32-cmain.c b/physmem/ia32-cmain.c new file mode 100644 index 0000000..cc628a6 --- /dev/null +++ b/physmem/ia32-cmain.c @@ -0,0 +1,55 @@ +/* ia32-cmain.c - Startup code for the ia32. + Copyright (C) 2003 Free Software Foundation, Inc. + Written by Marcus Brinkmann. + + This file is part of the GNU Hurd. + + The GNU Hurd is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + The GNU Hurd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. */ + +#if HAVE_CONFIG_H +#include <config.h> +#endif + +#include <alloca.h> +#include <stdint.h> + +#include <l4/globals.h> +#include <l4/stubs.h> +#include <l4/stubs-init.h> + +#include "physmem.h" + + +/* Initialize libl4, setup the argument vector, and pass control over + to the main function. */ +void +cmain (void) +{ + int argc = 0; + char **argv = 0; + + l4_init (); + l4_init_stubs (); + + argc = 1; + argv = alloca (sizeof (char *) * 2); + argv[0] = program_name; + argv[1] = 0; + + /* Now invoke the main function. */ + main (argc, argv); + + /* Never reached. */ +} diff --git a/physmem/ia32-crt0.S b/physmem/ia32-crt0.S new file mode 100644 index 0000000..2b34590 --- /dev/null +++ b/physmem/ia32-crt0.S @@ -0,0 +1,47 @@ +/* ia32-crt0.S - Startup code for ia32. + Copyright (C) 2003 Free Software Foundation, Inc. + Written by Marcus Brinkmann. + + This file is part of the GNU Hurd. + + The GNU Hurd is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + The GNU Hurd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. */ + +#define ASM 1 +#include "multiboot.h" + +/* The size of our stack (4KB). */ +#define STACK_SIZE 0x1000 + + .text + + .globl start, _start +start: +_start: + /* Initialize the stack pointer. */ + movl $(stack + STACK_SIZE), %esp + + /* Reset EFLAGS. */ + pushl $0 + popf + + /* Now enter the cmain function. */ + call cmain + + /* Not reached. */ +loop: hlt + jmp loop + + /* Our stack area. */ + .comm stack, STACK_SIZE diff --git a/physmem/output.c b/physmem/output.c new file mode 100644 index 0000000..60dbcb1 --- /dev/null +++ b/physmem/output.c @@ -0,0 +1,206 @@ +/* output.c - Output routines. + Copyright (C) 2003 Free Software Foundation, Inc. + Written by Marcus Brinkmann. + + This file is part of the GNU Hurd. + + The GNU Hurd is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + The GNU Hurd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. */ + +#if HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdarg.h> + +#include <l4.h> + +#include "output.h" + + +/* True if debugging is enabled. */ +int output_debug; + + +/* Print the single character CHR on the output device. */ +void +putchar (int chr) +{ + l4_msg_t msg; + + l4_msg_clear (&msg); + /* FIXME: Hard coded message label. */ +#define WORTEL_MSG_PUTCHAR 1 + l4_set_msg_label (&msg, WORTEL_MSG_PUTCHAR); + l4_msg_append_word (&msg, (l4_word_t) chr); + l4_msg_load (&msg); + /* FIXME: Hard coded thread ID. */ + l4_send (l4_global_id (l4_thread_user_base () + 2, 1)); + /* FIXME: No error handling. */ +} + + +static void +print_nr (unsigned long long nr, int base) +{ + static char *digits = "0123456789abcdef"; + char str[30]; + int i = 0; + + do + { + str[i++] = digits[nr % base]; + nr = nr / base; + } + while (nr); + + i--; + while (i >= 0) + putchar (str[i--]); +} + + +static void +print_signed_nr (long long nr, int base) +{ + unsigned long long unr; + + if (nr < 0) + { + putchar ('-'); + unr = -nr; + } + else + unr = nr; + + print_nr (unr, base); +} + + +void +printf (const char *fmt, ...) +{ + va_list ap; + + va_start (ap, fmt); + const char *p = fmt; + + while (*p != '\0') + { + if (*p != '%') + { + putchar (*(p++)); + continue; + } + + p++; + switch (*p) + { + case '%': + putchar ('%'); + p++; + break; + + case 'l': + p++; + if (*p != 'l') + { + putchar ('%'); + putchar ('l'); + putchar (*(p++)); + continue; + } + p++; + switch (*p) + { + case 'o': + print_nr (va_arg (ap, unsigned long long), 8); + p++; + break; + + case 'd': + case 'i': + print_signed_nr (va_arg (ap, long long), 10); + p++; + break; + + case 'x': + case 'X': + print_nr (va_arg (ap, unsigned long long), 16); + p++; + break; + + case 'u': + print_nr (va_arg (ap, unsigned long long), 10); + p++; + break; + + default: + putchar ('%'); + putchar ('l'); + putchar ('l'); + putchar (*(p++)); + break; + } + break; + + case 'o': + print_nr (va_arg (ap, unsigned int), 8); + p++; + break; + + case 'd': + case 'i': + print_signed_nr (va_arg (ap, int), 10); + p++; + break; + + case 'x': + case 'X': + print_nr (va_arg (ap, unsigned int), 16); + p++; + break; + + case 'u': + print_nr (va_arg (ap, unsigned int), 10); + p++; + break; + + case 'c': + putchar (va_arg (ap, int)); + p++; + break; + + case 's': + { + char *str = va_arg (ap, char *); + while (*str) + putchar (*(str++)); + } + p++; + break; + + case 'p': + print_nr ((unsigned int) va_arg (ap, void *), 16); + p++; + break; + + default: + putchar ('%'); + putchar (*p); + p++; + break; + } + } +} diff --git a/physmem/output.h b/physmem/output.h new file mode 100644 index 0000000..247ea98 --- /dev/null +++ b/physmem/output.h @@ -0,0 +1,35 @@ +/* output.h - Output routines interfaces. + Copyright (C) 2003 Free Software Foundation, Inc. + Written by Marcus Brinkmann. + + This file is part of the GNU Hurd. + + The GNU Hurd is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + The GNU Hurd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. */ + +#ifndef _OUTPUT_H +#define _OUTPUT_H 1 + +/* Print the single character CHR on the output device. */ +void putchar (int chr); + +void printf (const char *fmt, ...); + +/* True if debug mode is enabled. */ +extern int output_debug; + +/* Print a debug message. */ +#define debug(...) do { if (output_debug) printf (__VA_ARGS__); } while (0) + +#endif /* _OUTPUT_H */ diff --git a/physmem/physmem.c b/physmem/physmem.c new file mode 100644 index 0000000..cef9958 --- /dev/null +++ b/physmem/physmem.c @@ -0,0 +1,42 @@ +/* Main function for physical memory server. + Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU Hurd. + + The GNU Hurd is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU Hurd is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#if HAVE_CONFIG_H +#include <config.h> +#endif + +#include "physmem.h" + + +/* The program name. */ +char *program_name = "physmem"; + + +int +main (int argc, char *argv[]) +{ + output_debug = 1; + + debug ("%s " PACKAGE_VERSION "\n", program_name); + + while (1) + l4_sleep (l4_never); + + return 0; +} diff --git a/physmem/physmem.h b/physmem/physmem.h new file mode 100644 index 0000000..8e0fea4 --- /dev/null +++ b/physmem/physmem.h @@ -0,0 +1,31 @@ +/* physmem.h - Generic definitions. + Copyright (C) 2003 Free Software Foundation, Inc. + Written by Marcus Brinkmann. + + This file is part of the GNU Hurd. + + The GNU Hurd is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + The GNU Hurd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. */ + +#include <l4.h> +#include "string.h" +#include "output.h" + + +/* The program name. */ +extern char *program_name; + +#define BUG_ADDRESS "<bug-hurd@gnu.org>" + +int main (int argc, char *argv[]); diff --git a/wortel/README b/wortel/README new file mode 100644 index 0000000..6dc0af8 --- /dev/null +++ b/wortel/README @@ -0,0 +1,9 @@ +wortel +====== + +wortel is the rootserver of the Hurd on L4. It is responsible for +booting up the system and wrapping privileged L4 operations. + +For now, only a rudimentary part of the loader is written, and the +only useful thing wortel can do is to start the dummy physmem server +for a small demonstration. diff --git a/wortel/ia32-cmain.c b/wortel/ia32-cmain.c index d801836..a8b58e6 100644 --- a/wortel/ia32-cmain.c +++ b/wortel/ia32-cmain.c @@ -124,3 +124,79 @@ cmain (void) /* Never reached. */ } + + +/* The following must be defined and are used to calculate the extents + of the laden binary itself. */ +extern char _start; +extern char _end; + + +/* Find the kernel, the initial servers and the other information + required for booting. */ +void +find_components (void) +{ + multiboot_info_t *mbi = (multiboot_info_t *) l4_boot_info (); + l4_word_t start; + l4_word_t end; + +#if 0 + debug_dump (); +#endif + + /* Load the module information. */ + if (CHECK_FLAG (mbi->flags, 3)) + { + module_t *mod = (module_t *) mbi->mods_addr; + + if (mbi->mods_count > 0) + { + /* Skip the entry for the rootserver. */ + mod++; + } + + if (mbi->mods_count > 1) + { + physmem.low = mod->mod_start; + physmem.high = mod->mod_end; + mod++; + } + } + + /* Now protect ourselves and the mulitboot info (at least the module + configuration. */ + loader_add_region (program_name, (l4_word_t) &_start, (l4_word_t) &_end); + + start = (l4_word_t) mbi; + end = start + sizeof (*mbi) - 1; + loader_add_region ("grub-mbi", start, end); + + if (CHECK_FLAG (mbi->flags, 3) && mbi->mods_count) + { + module_t *mod = (module_t *) mbi->mods_addr; + int nr; + + start = (l4_word_t) mod; + end = ((l4_word_t) mod) + mbi->mods_count * sizeof (*mod); + loader_add_region ("grub-mods", start, end); + + start = (l4_word_t) mod[0].string; + end = start; + for (nr = 0; nr < mbi->mods_count; nr++) + { + char *str = (char *) mod[nr].string; + + if (str) + { + if (((l4_word_t) str) < start) + start = (l4_word_t) str; + while (*str) + str++; + if (((l4_word_t) str) > end) + end = (l4_word_t) str; + } + } + loader_add_region ("grub-mods-cmdlines", start, end); + } +} diff --git a/wortel/wortel.c b/wortel/wortel.c index 246a11a..cc72381 100644 --- a/wortel/wortel.c +++ b/wortel/wortel.c @@ -27,6 +27,8 @@ /* The program name. */ char *program_name = "wortel"; +rootserver_t physmem; + /* Return the number of memory descriptors. */ l4_word_t @@ -45,10 +47,178 @@ loader_get_memory_desc (l4_word_t nr) } -/* True if debug mode is enabled. */ -int debug; +static void +load_components (void) +{ + if (!physmem.low) + panic ("No physical memory server found"); + loader_add_region ("physmem-mod", physmem.low, physmem.high); + + loader_elf_load ("physmem-server", physmem.low, physmem.high, + &physmem.low, &physmem.high, &physmem.ip); + loader_remove_region ("physmem-mod"); +} + + +static void +start_components (void) +{ + l4_word_t ret; + l4_word_t control; + l4_msg_t msg; + l4_msg_tag_t msg_tag; + unsigned int io_map = 0; + + /* Thread nr is next available after rootserver thread nr, + version part is 2 (rootserver is 1). */ + l4_thread_id_t physmem_server + = l4_global_id (l4_thread_no (l4_myself ()) + 2, + 2); + /* The UTCB location below is only a hack. We also need a way to + specify the maximum number of threads (ie the size of the UTCB + area), for example via ELF symbols, or via the command line. + This can also be used to actually create these threads up + front. */ + ret = l4_thread_control (physmem_server, physmem_server, l4_myself (), + l4_nilthread, (void *) 0x2000000); + if (!ret) + panic ("Creation of initial physmem thread failed"); + + /* The UTCB area must be controllable in some way, see above. Same + for KIP area. */ + ret = l4_space_control (physmem_server, 0, + l4_fpage_log2 (0x2400000, l4_kip_area_size_log2 ()), + l4_fpage_log2 (0x2000000, 14), + l4_anythread, &control); + if (!ret) + panic ("Creation of physmem address space failed"); + + ret = l4_thread_control (physmem_server, physmem_server, l4_nilthread, + l4_myself (), (void *) -1); + if (!ret) + panic ("Activation of initial physmem thread failed"); + + l4_msg_clear (&msg); + l4_set_msg_label (&msg, 0); + l4_msg_append_word (&msg, physmem.ip); + l4_msg_append_word (&msg, 0); + l4_msg_load (&msg); + msg_tag = l4_send (physmem_server); + if (l4_ipc_failed (msg_tag)) + panic ("Sending startup message to physmemserver thread failed: %u", + l4_error_code ()); + + do + { + l4_word_t label; + + msg_tag = l4_receive (physmem_server); + if (l4_ipc_failed (msg_tag)) + panic ("Receiving messages from physmemserver thread failed: %u", + (l4_error_code () >> 1) & 0x7); + + /* FIXME: Check sender, etc. */ + + label = l4_label (msg_tag); + l4_msg_store (msg_tag, &msg); + if ((label >> 4) == 0xffe) + { + l4_grant_item_t grant_item; + l4_fpage_t fpage; + l4_word_t addr; + + /* This is a page fault. */ + if (l4_untyped_words (msg_tag) != 2 + || l4_typed_words (msg_tag) != 0) + panic ("Invalid format of page fault msg"); + + if (!io_map) + { + l4_map_item_t map_item; + + /* FIXME: This is a hack. The first time we map the I/O + ports into the task. The kernel will repeat the page + fault. */ + io_map = 1; + + /* Now we can grant the mapping to the physmem server. + FIXME: Should use the fpage returned by sigma0. */ + l4_msg_clear (&msg); + l4_set_msg_label (&msg, 0); + /* FIXME: Try to use largest fpage possible for the image. + Keep track of mappings already provided. Possibly map + text section rx and data rw. */ + map_item = l4_map_item (l4_fpage_add_rights + (l4_io_fpage (0, 10), + l4_fully_accessible), 0); + l4_msg_append_map_item (&msg, map_item); + l4_msg_load (&msg); + l4_reply (physmem_server); + continue; + } + + addr = l4_msg_word (&msg, 0) & ~((1 << 12) - 1); + fpage = l4_fpage_add_rights (l4_fpage_log2 (addr, 12), + l4_fully_accessible); + debug ("Serving Page Fault: %c%c%c at 0x%x (IP: 0x%x)\n", + label & 4 ? 'x' : '-', label & 2 ? 'w' : '-', + label & 1 ? 'r' : '-', addr, + l4_msg_word (&msg, 1)); + + /* First we have to request the fpage from sigma0. */ + l4_accept (l4_map_grant_items (l4_complete_address_space)); + l4_msg_clear (&msg); + l4_set_msg_label (&msg, 0xffa0); + l4_msg_append_word (&msg, fpage.raw); + l4_msg_append_word (&msg, L4_DEFAULT_MEMORY); + l4_msg_load (&msg); + msg_tag = l4_call (l4_global_id (l4_thread_user_base (), 1)); + if (l4_ipc_failed (msg_tag)) + panic ("sigma0 request failed during %s: %u", + l4_error_code () & 1 ? "receive" : "send", + (l4_error_code () >> 1) & 0x7); + if (l4_untyped_words (msg_tag) != 0 + || l4_typed_words (msg_tag) != 2) + panic ("Invalid format of sigma0 reply"); + l4_msg_store (msg_tag, &msg); + if (l4_msg_word (&msg, 1) == l4_nilpage.raw) + panic ("sigma0 rejected mapping"); + + /* Now we can grant the mapping to the physmem server. + FIXME: Should use the fpage returned by sigma0. */ + l4_msg_clear (&msg); + l4_set_msg_label (&msg, 0); + /* FIXME: Try to use largest fpage possible for the image. + Keep track of mappings already provided. Possibly map + text section rx and data rw. */ + grant_item = l4_grant_item (fpage, addr); + l4_msg_append_grant_item (&msg, grant_item); + l4_msg_load (&msg); + } +#define WORTEL_MSG_PUTCHAR 1 + else if (label == WORTEL_MSG_PUTCHAR) + { + int chr; + /* This is a putchar() message. */ + if (l4_untyped_words (msg_tag) != 1 + || l4_typed_words (msg_tag) != 0) + panic ("Invalid format of putchar msg"); + chr = (int) l4_msg_word (&msg, 0); + putchar (chr); + /* No reply needed. */ + continue; + } + else + panic ("Invalid message with tag 0x%x", msg_tag); + + l4_reply (physmem_server); + } + while (1); +} + + static void parse_args (int argc, char *argv[]) { @@ -126,7 +296,7 @@ parse_args (int argc, char *argv[]) else if (!strcmp (argv[i], "-D") || !strcmp (argv[i], "--debug")) { i++; - debug = 1; + output_debug = 1; } else if (argv[i][0] == '-') panic ("Unsupported option %s", argv[i]); @@ -137,6 +307,78 @@ parse_args (int argc, char *argv[]) +#define STACK_SIZE 4096 +char exception_handler_stack[STACK_SIZE]; + +void +exception_handler (void) +{ + int count = 0; + + while (count < 10) + { + l4_msg_tag_t tag; + l4_thread_id_t from; + l4_word_t mr[12]; + + tag = l4_wait (&from); + debug ("EXCEPTION HANDLER: Received message from: "); + debug ("0x%x", from); + debug ("\n"); + debug ("Tag: 0x%x", tag.raw); + debug ("Label: %u Untyped: %u Typed: %u\n", + l4_label (tag), l4_untyped_words (tag), l4_typed_words (tag)); + + l4_store_mrs (1, 12, mr); + debug ("Succeeded: %u Propagated: %u Redirected: %u Xcpu: %u\n", + l4_ipc_succeeded (tag), l4_ipc_propagated (tag), + l4_ipc_redirected (tag), l4_ipc_xcpu (tag)); + debug ("Error Code: 0x%x\n", l4_error_code ()); + debug ("EIP: 0x%x EFLAGS: 0x%x Exception: %u ErrCode: %u\n", + mr[0], mr[1], mr[2], mr[3]); + debug ("EDI: 0x%x ESI: 0x%x EBP: 0x%x ESP: 0x%x\n", + mr[4], mr[5], mr[6], mr[7]); + debug ("EAX: 0x%x EBX: 0x%x ECX: 0x%x EDX: 0x%x\n", + mr[11], mr[8], mr[10], mr[9]); + } + + debug ("EXCEPTION HANDLER: Too many exceptions.\n"); + + while (1) + l4_yield (); +} + + +static void +setup (void) +{ + l4_thread_id_t thread; + l4_word_t result; + void *utcb; + + /* FIXME: This is not specified by the standard. We don't know + where and how much space we have for other thread's UTCB + areas in the root server. */ + utcb = (void *) ((l4_my_local_id ().raw & ~(l4_utcb_size () - 1)) + + l4_utcb_size ()); + thread = l4_global_id (l4_thread_no (l4_myself ()) + 1, 1); + debug ("Creating exception handler thread at utcb 0x%x: ", + (l4_word_t) utcb); + result = l4_thread_control (thread, l4_myself (), l4_myself (), + l4_global_id (l4_thread_no (l4_myself()) - 2, 1), + utcb); + debug ("%s\n", result ? "successful" : "failed"); + /* Set the priority of the other thread to our priority. Otherwise + it is 100 and will never be scheduled as long as we are not in a + blocking receive. */ + l4_set_priority (thread, 255); + l4_start_sp_ip (thread, ((l4_word_t) exception_handler_stack) + + sizeof (exception_handler_stack), + (l4_word_t) exception_handler); + l4_set_exception_handler (thread); +} + + int main (int argc, char *argv[]) { @@ -144,6 +386,14 @@ main (int argc, char *argv[]) debug ("%s " PACKAGE_VERSION "\n", program_name); + setup (); + + find_components (); + + load_components (); + + start_components (); + while (1) l4_yield (); diff --git a/wortel/wortel.h b/wortel/wortel.h index e576855..670ac7f 100644 --- a/wortel/wortel.h +++ b/wortel/wortel.h @@ -30,4 +30,16 @@ extern char *program_name; #define BUG_ADDRESS "<bug-hurd@gnu.org>" + +typedef __l4_rootserver_t rootserver_t; + +/* For the boot components, find_components() must fill in the start + and end address of the ELF images in memory. The end address is + one more than the last byte in the image. */ +extern rootserver_t physmem; + +/* Find the kernel, the initial servers and the other information + required for booting. */ +void find_components (void); + int main (int argc, char *argv[]); |