From 79df8dc73786bf3b1c488b7f146c8716c517c1e8 Mon Sep 17 00:00:00 2001 From: Jacek Galowicz Date: Wed, 9 Nov 2011 16:37:31 +0100 Subject: [PATCH 1/5] Wrote a task starting tutorial article for the documentation. --- documentation/text/kernelspace.dox | 7 -- documentation/text/tasks.dox | 136 +++++++++++++++++++++++++++++ documentation/text/userspace.dox | 7 -- 3 files changed, 136 insertions(+), 14 deletions(-) delete mode 100644 documentation/text/kernelspace.dox create mode 100644 documentation/text/tasks.dox delete mode 100644 documentation/text/userspace.dox diff --git a/documentation/text/kernelspace.dox b/documentation/text/kernelspace.dox deleted file mode 100644 index 95e014d4..00000000 --- a/documentation/text/kernelspace.dox +++ /dev/null @@ -1,7 +0,0 @@ -/** - * @file kernelspace.dox - * @page kernelspace Development in kernel space - * - * @section kernelthreads Starting kernel threads - * - */ diff --git a/documentation/text/tasks.dox b/documentation/text/tasks.dox new file mode 100644 index 00000000..0b9bebaf --- /dev/null +++ b/documentation/text/tasks.dox @@ -0,0 +1,136 @@ +/** + * @file tasks.dox + * @page tasks Creating your own tasks in MetalSVM + * + * + * @section toc Table of Contents + * - @ref initd + * - @ref kerneltasks + * - @ref usertasks + * + * @section initd Where MetalSVM starts tasks after boot + * + * The last step after booting is starting the \c initd process: + * + * \c kernel/main.c: + * \code +... +create_kernel_task (&id, initd, NULL, NORMAL_PRIO); +...\endcode + * + * \c Initd starts all the other processes and then exits. + * The list of processes to start is defined in \c kernel/tests.c + * within \c test_init(): + * + * \code +int test_init(void) +{ + /* This is how the ARGV parameter list is defined */ + char* argv[] = {"/bin/tests", NULL}; + char* server_argv[] = {"/bin/server", "6789", NULL}; + char* client_argv[] = {"/bin/client", "192.168.0.1", "6789", NULL}; + + ... + + /* Starting kernel- and user space tasks */ + create_kernel_task(NULL, foo, "Hello from foo1", NORMAL_PRIO); + create_kernel_task(NULL, join_test, NULL, NORMAL_PRIO); + create_user_task(NULL, "/bin/tests", argv); + + return 0; +}\endcode + * + * @section kerneltasks Creating kernel tasks + * + * To create your own kernel task, you will need to write a task first. + * This can look like the following example task in \c kernel/tests.c: + * + * \code +static int foo(void* arg) +{ + int i; + + if (!arg) + return 0; + + for(i=0; i<5; i++) { + kprintf("%s\n", (char*) arg); + sleep(1); + } + + return 42; +}\endcode + * + * A kernel task is just a procedure within the scope of init_test(). + * Its signature should match the following pattern: + * \code int my_task(void* my_args)\endcode + * + * To make \c initd start your task after booting the system, you will need to + * write a \c create_kernel_task() call within \c test_init() which looks like + * the \c foo example from the section above: + * \code create_kernel_task(NULL, foo, "Hello from foo1", NORMAL_PRIO); \endcode + * + * The \c create_kernel_task procedure has the following signature: + * \code int create_kernel_task(tid_t* id, entry_point_t ep, void* args, uint8_t prio)\endcode + * Its parameters are the following: + * - \c id: Provide the address of a \c tid_t variable here, if you need the new + * task's ID. + * - \c ep: The entry point of your task is just its function/procedure symbol. + * - \c args: The address of the parameter structure your task expects. + * - \c prio: The priority your task shall be executed with. Priority levels are + * defined in \c include/metalsvm/tasks_types.h: + * \code +#define MAX_PRIO 31 +#define REALTIME_PRIO 31 +#define HIGH_PRIO 16 +#define NORMAL_PRIO 8 +#define LOW_PRIO 1 +#define IDLE_PRIO 0\endcode + * + * @section usertasks Creating user space tasks + * + * User space tasks are usually not defined within the kernel code, + * therefore they are launched differently. + * + * To write your own user space application, place your *.c source code within + * \c newlib/examples/ and add a target in the Makefile (\c newlib/examples/Makefile) + * to ensure that your application is built when you type \c "make" in the + * MetalSVM directory. + * + * If your code does not consist of just some *.c and *.h files and you rather want + * keep your own project folder: The only important thing for later is that your + * executables and other runtime-needed files lay in the \c newlib/examples/ directory + * during build of the initial ramdisk. + * + * The scripts which build MetalSVM's initial ramdisk are launched when the kernel + * itself is built. \c metalsvm.elf and \c tools/initrd.img together + * compose a bootable system which is rebuilt (if necessary) everytimes you run + * \c make in the project directory. + * + * The initrd building scripts include every file within the \c newlib/examples/ + * directory which is marked as \b execuable. Do not forget this if you use your + * own build scripts! + * + * After providing your own executable for the system within the initial ramdisk, + * it still needs to be executed after boot. This is done very similarly to + * launching kernel threads. + * + * Place your application launching \c create_user_task() call within \c test_init(): + * \code create_user_task(NULL, "/bin/tests", argv);\endcode + * + * In this case the executable \c tests is launched with the parameter array \c argv. + * Note that at build-time the executable is located at \c newlib/examples/tests. + * The \c argv array is constructed like in the example at the top of this page. + * + * \c create_user_task()'s signature looks like this: + * \code int create_user_task(tid_t* id, const char* fname, char** argv)\endcode + * Its parameters are the following: + * - \c id: Provide the address of a \c tid_t variable if you need the ID of your + * started process. + * - \c fname: This string denotes the path of your executable within the file system. + * Every executable which comes from \c newlib/examples/ will be located within + * \c /bin in MetalSVM's file system after boot. + * - \c argv: This is the ARGV-structure the task will be equipped with after launch. + * + * + */ diff --git a/documentation/text/userspace.dox b/documentation/text/userspace.dox deleted file mode 100644 index 9489f4d2..00000000 --- a/documentation/text/userspace.dox +++ /dev/null @@ -1,7 +0,0 @@ -/** - * @file userspace.dox - * @page userspace Development in user space - * - * @section ownapps Installing and launching your own applications - * - */ From 17da526f105db1f63bbb2c758c1b6d710b6b1ae5 Mon Sep 17 00:00:00 2001 From: Jacek Galowicz Date: Sat, 19 Nov 2011 12:18:39 +0100 Subject: [PATCH 2/5] Added cross compiler and stack protector variable to Makefile If using another tool chain to compile everything, like on the Intel SCC or OS X, there is only one variable in the Makefile to change the cross compiler prefix. Furthermore, there is another variable to remove the -fno-stack-protector setting, which is important for compiling on the SCC. Adapted the documentation to this, too. --- Makefile.example | 41 +++++++++++++++++------------- documentation/text/compilation.dox | 31 ++++++++++------------ 2 files changed, 36 insertions(+), 36 deletions(-) diff --git a/Makefile.example b/Makefile.example index fd93ee09..bb702c72 100644 --- a/Makefile.example +++ b/Makefile.example @@ -5,30 +5,35 @@ LWIPDIRS = lwip/src/arch lwip/src/api lwip/src/core lwip/src/core/ipv4 lwip/src/ DRIVERDIRS = drivers/net drivers/char KERNDIRS = libkern kernel mm fs apps arch/$(ARCH)/kernel arch/$(ARCH)/mm arch/$(ARCH)/scc $(LWIPDIRS) $(DRIVERDIRS) SUBDIRS = $(KERNDIRS) +STACKPROT=-fno-stack-protector -CC_FOR_TARGET=gcc -CXX_FOR_TARGET=g++ -GCC_FOR_TARGET=gcc -AR_FOR_TARGET=ar -AS_FOR_TARGET=as -LD_FOR_TARGET=ld -NM_FOR_TARGET=nm -OBJDUMP_FOR_TARGET=objdump -OBJCOPY_FOR_TARGET=objcopy -RANLIB_FOR_TARGET=ranlib -STRIP_FOR_TARGET=strip -READELF_FOR_TARGET=readelf -NASM = nasm -EMU=qemu -GDB=gdb +# Set your own cross compiler tool chain prefix here +CROSSCOMPREFIX= + +# Uncomment both lines if compiling for the SCC! +#CROSSCOMPREFIX=i386-unknown-linux-gnu- +#STACKPROT= + +CC_FOR_TARGET=$(CROSSCOMPREFIX)gcc +CXX_FOR_TARGET=$(CROSSCOMPREFIX)g++ +GCC_FOR_TARGET=$(CROSSCOMPREFIX)gcc +AR_FOR_TARGET=$(CROSSCOMPREFIX)ar +AS_FOR_TARGET=$(CROSSCOMPREFIX)as +LD_FOR_TARGET=$(CROSSCOMPREFIX)ld +NM_FOR_TARGET=$(CROSSCOMPREFIX)nm +OBJDUMP_FOR_TARGET=$(CROSSCOMPREFIX)objdump +OBJCOPY_FOR_TARGET=$(CROSSCOMPREFIX)objcopy +RANLIB_FOR_TARGET=$(CROSSCOMPREFIX)ranlib +STRIP_FOR_TARGET=$(CROSSCOMPREFIX)strip +READELF_FOR_TARGET=$(CROSSCOMPREFIX)readelf MAKE = make NASMFLAGS = -felf32 -g INCLUDE = -I$(TOPDIR)/include -I$(TOPDIR)/arch/$(ARCH)/include -I$(TOPDIR)/lwip/src/include -I$(TOPDIR)/lwip/src/include/ipv4 -I$(TOPDIR)/drivers # Compiler options for final code -CFLAGS = -g -m32 -march=i586 -Wall -O2 -fno-builtin -fstrength-reduce -fomit-frame-pointer -finline-functions -nostdinc $(INCLUDE) -fno-stack-protector +CFLAGS = -g -m32 -march=i586 -Wall -O2 -fno-builtin -fstrength-reduce -fomit-frame-pointer -finline-functions -nostdinc $(INCLUDE) $(STACKPROT) # Compiler options for debuuging -#CFLAGS = -g -O -m32 -march=i586 -Wall -fno-builtin -DWITH_FRAME_POINTER -nostdinc $(INCLUDE) -fno-stack-protector +#CFLAGS = -g -O -m32 -march=i586 -Wall -fno-builtin -DWITH_FRAME_POINTER -nostdinc $(INCLUDE) $(STACKPROT) ARFLAGS = rsv RM = rm -rf LDFLAGS = -T link.ld -z max-page-size=4096 --defsym __BUILD_DATE=$(shell date +'%Y%m%d') --defsym __BUILD_TIME=$(shell date +'%H%M%S') @@ -47,7 +52,7 @@ default: all all: newlib tools $(NAME).elf newlib: - $(MAKE) ARCH=$(ARCH) LDFLAGS="-m32" CFLAGS="-m32 -O2 -march=i586 -fno-stack-protector" NASMFLAGS="$(NASMFLAGS)" CC_FOR_TARGET=$(CC_FOR_TARGET) \ + $(MAKE) ARCH=$(ARCH) LDFLAGS="-m32" CFLAGS="-m32 -O2 -march=i586 $(STACKPROT)" NASMFLAGS="$(NASMFLAGS)" CC_FOR_TARGET=$(CC_FOR_TARGET) \ CXX_FOR_TARGET=$(CXX_FOR_TARGET) \ GCC_FOR_TARGET=$(GCC_FOR_TARGET) \ AR_FOR_TARGET=$(AR_FOR_TARGET) \ diff --git a/documentation/text/compilation.dox b/documentation/text/compilation.dox index 61739023..20f13d6a 100644 --- a/documentation/text/compilation.dox +++ b/documentation/text/compilation.dox @@ -45,23 +45,18 @@ $ cp include/metalsvm/config.h.example include/metalsvm/config.h \endverbatim * * -# Intel recommends to use their cross-compiler for generating code which is guaranteed to be SCC-compatible. Just set the environment variables with the following command: * \verbatim$ . /opt/compilerSetupFiles/crosscompile.sh \endverbatim - * -# The Makefile needs to be adapted to actually use the cross compiler: - * \verbatim -CC_FOR_TARGET=i386-unknown-linux-gnu-gcc -CXX_FOR_TARGET=i386-unknown-linux-gnu-g++ -GCC_FOR_TARGET=i386-unknown-linux-gnu-gcc -AR_FOR_TARGET=i386-unknown-linux-gnu-ar -AS_FOR_TARGET=i386-unknown-linux-gnu-as -LD_FOR_TARGET=i386-unknown-linux-gnu-ld -NM_FOR_TARGET=i386-unknown-linux-gnu-nm -OBJDUMP_FOR_TARGET=i386-unknown-linux-gnu-objdump -OBJCOPY_FOR_TARGET=i386-unknown-linux-gnu-objcopy -RANLIB_FOR_TARGET=i386-unknown-linux-gnu-ranlib -STRIP_FOR_TARGET=i386-unknown-linux-gnu-strip -READELF_FOR_TARGET=i386-unknown-linux-gnu-readelf \endverbatim + * -# The Makefile needs to be adapted to actually use the cross compiler. + * Just uncomment two lines like seen here: + * \code +# Set your own cross compiler tool chain prefix here +CROSSCOMPREFIX= + +# Uncomment both lines if compiling for the SCC! +CROSSCOMPREFIX=i386-unknown-linux-gnu- +STACKPROT=\endcode * -# Another important change in the Makefile is disabling the "-fno-stack-protector" option. It occurs several times. * -# The SCC requires a special configuration for the MetalSVM kernel: - * \verbatim + * \code //#define CONFIG_PCI //#define CONFIG_VGA //#define CONFIG_UART @@ -75,11 +70,11 @@ READELF_FOR_TARGET=i386-unknown-linux-gnu-readelf \endverbatim //#define GORY //#define SHMADD #define SHMDBG -//#define SHMADD_CACHEABLE \endverbatim +//#define SHMADD_CACHEABLE \endcode * -# There is only one core per tile, so it is adequate to reduce overhead by disabling SMP in MetalSVM: - * \verbatim#define MAX_CORES 1 \endverbatim + * \code#define MAX_CORES 1 \endcode * -# Cache-line size is 32 byte: - * \verbatim#define CACHE_LINE 32 \endverbatim + * \code#define CACHE_LINE 32 \endcode * -# MetalSVM can now be built using \c make. * -# Build the SCC tools: * \verbatim From 698759df759ae871625ca523e62ba6c6a2f9a666 Mon Sep 17 00:00:00 2001 From: Generic account for RWTHAachen Students Date: Mon, 21 Nov 2011 03:37:19 -0800 Subject: [PATCH 3/5] fix bug in Makefile.example --- Makefile.example | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Makefile.example b/Makefile.example index bb702c72..e5c6d694 100644 --- a/Makefile.example +++ b/Makefile.example @@ -27,6 +27,10 @@ RANLIB_FOR_TARGET=$(CROSSCOMPREFIX)ranlib STRIP_FOR_TARGET=$(CROSSCOMPREFIX)strip READELF_FOR_TARGET=$(CROSSCOMPREFIX)readelf +NASM = nasm +EMU=qemu +GDB=gdb + MAKE = make NASMFLAGS = -felf32 -g INCLUDE = -I$(TOPDIR)/include -I$(TOPDIR)/arch/$(ARCH)/include -I$(TOPDIR)/lwip/src/include -I$(TOPDIR)/lwip/src/include/ipv4 -I$(TOPDIR)/drivers From 4e53aa6f9587f1dbd9dfa38b2551c4b60883dcba Mon Sep 17 00:00:00 2001 From: Jacek Galowicz Date: Thu, 15 Dec 2011 18:34:27 +0100 Subject: [PATCH 4/5] Commented the PIT-initialization code to make it easier to understand. --- arch/x86/kernel/timer.c | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/arch/x86/kernel/timer.c b/arch/x86/kernel/timer.c index 0ea49d0b..d6b71d2c 100644 --- a/arch/x86/kernel/timer.c +++ b/arch/x86/kernel/timer.c @@ -127,6 +127,9 @@ int timer_wait(unsigned int ticks) } #define LATCH(f) ((CLOCK_TICK_RATE + f/2) / f) +#define WAIT_SOME_TIME() do { uint64_t start = rdtsc(); \ + while(rdtsc() - start < 1000000) ; \ + } while (0) /* * Sets up the system clock by installing the timer handler @@ -134,10 +137,6 @@ int timer_wait(unsigned int ticks) */ int timer_init(void) { -#ifndef CONFIG_ROCKCREEK - uint64_t start; -#endif - /* * Installs 'timer_handler' for the PIC and APIC timer, * only one handler will be later used. @@ -150,16 +149,27 @@ int timer_init(void) * Therefore, we have not to configure the PIC timer. */ #ifndef CONFIG_ROCKCREEK + /* + * Port 0x43 is for initializing the PIT: + * + * 0x34 means the following: + * 0b... (step-by-step binary representation) + * ... 00 - channel 0 + * ... 11 - write two values to counter register: + * first low-, then high-byte + * ... 010 - mode number 2: "rate generator" / frequency divider + * ... 0 - binary counter (the alternative is BCD) + */ outportb(0x43, 0x34); - /* before we write to 0x40, we wait some time */ - start = rdtsc(); - while(rdtsc() - start < 1000000) - ; + + WAIT_SOME_TIME(); + + /* Port 0x40 is for the counter register of channel 0 */ + outportb(0x40, LATCH(TIMER_FREQ) & 0xFF); /* low byte */ - /* before we write to 0x40, we wait some time */ - start = rdtsc(); - while(rdtsc() - start < 1000000) - ; + + WAIT_SOME_TIME(); + outportb(0x40, LATCH(TIMER_FREQ) >> 8); /* high byte */ #endif From bfbd560f709075ab3074a9472a74c0cfbbedad33 Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Thu, 2 Feb 2012 22:54:09 +0100 Subject: [PATCH 5/5] this fixes booting with initrd on qemu 1.0 patch submitted by Niels Ole Salscheider --- arch/x86/mm/page.c | 5 +++++ mm/memory.c | 6 ++++++ 2 files changed, 11 insertions(+) diff --git a/arch/x86/mm/page.c b/arch/x86/mm/page.c index 1e86cb53..b721ecf7 100644 --- a/arch/x86/mm/page.c +++ b/arch/x86/mm/page.c @@ -764,6 +764,11 @@ int arch_paging_init(void) if (mb_info && (mb_info->flags & MULTIBOOT_INFO_MODS)) { multiboot_module_t* mmodule = (multiboot_module_t*) mb_info->mods_addr; + npages = mb_info->mods_count * sizeof(multiboot_module_t) >> PAGE_SHIFT; + if (mb_info->mods_count * sizeof(multiboot_module_t) & (PAGE_SIZE-1)) + npages++; + map_region((size_t) (mb_info->mods_addr), (size_t) (mb_info->mods_addr), npages, MAP_KERNEL_SPACE); + for(i=0; imods_count; i++, mmodule++) { // map physical address to the same virtual address npages = (mmodule->mod_end - mmodule->mod_start) >> PAGE_SHIFT; diff --git a/mm/memory.c b/mm/memory.c index 6cad2520..2150243e 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -143,6 +143,12 @@ int mmu_init(void) atomic_int32_inc(&total_allocated_pages); atomic_int32_dec(&total_available_pages); + for(addr = mb_info->mods_addr; addr < mb_info->mods_addr + mb_info->mods_count * sizeof(multiboot_module_t); addr += PAGE_SIZE) { + page_set_mark(addr >> PAGE_SHIFT); + atomic_int32_inc(&total_allocated_pages); + atomic_int32_dec(&total_available_pages); + } + for(i=0; imods_count; i++, mmodule++) { for(addr=mmodule->mod_start; addrmod_end; addr+=PAGE_SIZE) { page_set_mark(addr >> PAGE_SHIFT);