diff --git a/.gitignore b/.gitignore index f0d2611f..5b44aa35 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,7 @@ *.img *.a *.log +*.swp *.DS_Store *.swp tags @@ -14,6 +15,7 @@ include/metalsvm/config.h Makefile tools/make_initrd newlib/examples/hello +newlib/examples/jacobi newlib/examples/echo newlib/examples/tests newlib/tmp/* diff --git a/arch/x86/include/asm/icc.h b/arch/x86/include/asm/icc.h new file mode 100644 index 00000000..31fdb2ef --- /dev/null +++ b/arch/x86/include/asm/icc.h @@ -0,0 +1,63 @@ +/* + * Copyright 2011 Stefan Lankes, Chair for Operating Systems, + * RWTH Aachen University + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of MetalSVM. + */ + +/* + * Function and prototypes for MetalSVM's inter core communication + */ + +#ifndef __ARCH_ICC_H__ +#define __ARCH_ICC_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef CONFIG_ROCKCREEK + +typedef struct { + uint32_t addr; // address of the initrd + uint32_t size; // size of the initrd + int32_t argc; // number of RCCE arguments + char** argv; // RCCE arguments +} bootinfo_t; + +extern bootinfo_t* bootinfo; + +typedef struct { + uint8_t type; + uint8_t tag; + uint32_t length; +} icc_header_t; + +#define ICC_TYPE_IP (1 << 0) +#define ICC_TYPE_SVM (1 << 1) +#define ICC_TYPE_PINGREQUEST (1 << 2) +#define ICC_TYPE_PINGRESPONSE (1 << 3) + +int icc_init(void); +int icc_ping(); +void icc_check(void); + +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h index faea9d96..a1f6246a 100644 --- a/arch/x86/include/asm/processor.h +++ b/arch/x86/include/asm/processor.h @@ -39,19 +39,6 @@ extern "C" { #endif -#ifdef CONFIG_ROCKCREEK -typedef struct { - uint32_t addr; // address of the initrd - uint32_t size; // size of the initrd - int32_t argc; // number of RCCE arguments - char** argv; // RCCE arguments -} bootinfo_t; - -extern bootinfo_t* bootinfo; - -int scc_init(void); -#endif - /** @brief Read out time stamp counter * * The rdtsc asm command puts a 64 bit time stamp value diff --git a/arch/x86/include/asm/tasks_types.h b/arch/x86/include/asm/tasks_types.h new file mode 100644 index 00000000..138fbd1c --- /dev/null +++ b/arch/x86/include/asm/tasks_types.h @@ -0,0 +1,71 @@ +/* + * Copyright 2011 Stefan Lankes, Chair for Operating Systems, + * RWTH Aachen University + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of MetalSVM. + * + */ + +#ifndef __ARCH_TASKS_TYPES__ +#define __ARCH_TASKS_TYPES__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + long cwd; + long swd; + long twd; + long fip; + long fcs; + long foo; + long fos; + long st_space[20]; + long status; +} i387_fsave_t; + +typedef struct i387_fxsave_struct { + unsigned short cwd; + unsigned short swd; + unsigned short twd; + unsigned short fop; + long fip; + long fcs; + long foo; + long fos; + long mxcsr; + long reserved; + long st_space[32]; + long xmm_space[32]; + long padding[56]; +} i387_fxsave_t __attribute__ ((aligned (16))); + +union fpu_state { + i387_fsave_t fsave; + i387_fxsave_t fxsave; +}; + +static inline void save_fpu_state(union fpu_state* state) { + asm volatile ("fsave %0; fwait" : "=m"((*state).fsave)); +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/arch/x86/kernel/entry.asm b/arch/x86/kernel/entry.asm index 1a325dba..5610c6b8 100644 --- a/arch/x86/kernel/entry.asm +++ b/arch/x86/kernel/entry.asm @@ -64,16 +64,19 @@ ALIGN 4 stublet: ; initialize stack pointer. mov esp, default_stack_pointer -; enable cache and turn on FPU exceptions mov eax, cr0 - ; enable cache - and eax, 0x9fffffff - ; ...and turn on FPU exceptions - or eax, 0x20 +; enable caching, disable paging and fpu emulation + and eax, 0x1ffffffb +; ...and turn on FPU exceptions + or eax, 0x22 mov cr0, eax ; clears the current pgd entry xor eax, eax mov cr3, eax +; disable SSE support (TODO) + mov eax, cr4 + and eax, 0xfffbf9ff + mov cr4, eax ; interpret multiboot information extern multiboot_init push ebx diff --git a/arch/x86/kernel/isrs.c b/arch/x86/kernel/isrs.c index 63075d00..cfb45389 100644 --- a/arch/x86/kernel/isrs.c +++ b/arch/x86/kernel/isrs.c @@ -74,6 +74,7 @@ extern void isr30(void); extern void isr31(void); static void fault_handler(struct state *s); +static void fpu_handler(struct state *s); /* * This is a very repetitive function... it's not hard, it's @@ -158,6 +159,26 @@ void isrs_install(void) // install the default handler for(i=0; i<32; i++) irq_install_handler(i, fault_handler); + + // set hanlder for fpu exceptions + irq_uninstall_handler(7); + irq_install_handler(7, fpu_handler); +} + +static void fpu_handler(struct state *s) +{ + task_t* task = per_core(current_task); + + asm volatile ("clts"); // clear the TS flag of cr0 + if (!(task->flags & TASK_FPU_INIT)) { + // use the FPU at the first time => Initialize FPU + asm volatile ("finit"); + task->flags = task->flags|TASK_FPU_INIT|TASK_FPU_USED; + } else { + // restore the FPU context + asm volatile ("frstor %0" :: "m"(task->fpu.fsave)); // restore fpu state + task->flags |= TASK_FPU_USED; + } } /** @brief Exception messages @@ -189,7 +210,7 @@ static void fault_handler(struct state *s) { if (s->int_no < 32) { kputs(exception_messages[s->int_no]); - kputs(" Exception.\n"); + kprintf(" Exception. (%d)\n", s->int_no); /* Now, we signalize that we have handled the interrupt */ if (apic_is_enabled()) diff --git a/arch/x86/kernel/timer.c b/arch/x86/kernel/timer.c index b66646ba..617d47d9 100644 --- a/arch/x86/kernel/timer.c +++ b/arch/x86/kernel/timer.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -39,6 +40,19 @@ uint64_t get_clock_tick(void) return timer_ticks; } +int sys_times(struct tms* buffer, clock_t* clock) +{ + if (BUILTIN_EXPECT(!buffer, 0)) + return -EINVAL; + if (BUILTIN_EXPECT(!clock, 0)) + return -EINVAL; + + memset(buffer, 0x00, sizeof(struct tms)); + *clock = buffer->tms_utime = (clock_t) ((timer_ticks - per_core(current_task)->start_tick) * CLOCKS_PER_SEC / TIMER_FREQ); + + return 0; +} + /* * Handles the timer. In this case, it's very simple: We * increment the 'timer_ticks' variable every time the diff --git a/arch/x86/mm/page.c b/arch/x86/mm/page.c index cd3f210b..184f8865 100644 --- a/arch/x86/mm/page.c +++ b/arch/x86/mm/page.c @@ -33,6 +33,7 @@ #ifdef CONFIG_ROCKCREEK #include #include +#include #endif /* @@ -588,7 +589,28 @@ int print_paging_tree(size_t viraddr) static void pagefault_handler(struct state *s) { - kprintf("PAGE FAULT: Task %u got page fault at %p (irq %d)\n", per_core(current_task)->id, read_cr2(), s->int_no); + task_t* task = per_core(current_task); + size_t viraddr = read_cr2(); + size_t phyaddr; + + if ((viraddr >= task->start_heap) && (viraddr <= task->end_heap) && (viraddr > KERNEL_SPACE)) { + viraddr = viraddr & 0xFFFFF000; + + phyaddr = get_page(); + if (BUILTIN_EXPECT(!phyaddr, 0)) + goto default_handler; + + if (map_region(viraddr, phyaddr, 1, MAP_USER_SPACE) == viraddr) { + memset((void*) viraddr, 0x00, PAGE_SIZE); + return; + } + + kprintf("Could not map 0x%x at 0x%x\n", phyaddr, viraddr); + put_page(phyaddr); + } + +default_handler: + kprintf("PAGE FAULT: Task %u got page fault at %p (irq %d)\n", task->id, viraddr, s->int_no); kprintf("Register state: eax = 0x%x, ebx = 0x%x, ecx = 0x%x, edx = 0x%x, edi = 0x%x, esi = 0x%x, ebp = 0x%x, esp = 0x%x\n", s->eax, s->ebx, s->ecx, s->edx, s->edi, s->esi, s->ebp, s->esp); @@ -640,8 +662,8 @@ int arch_paging_init(void) * Set the page table and page directory entries for the kernel. We map the kernel's physical address * to the same virtual address. */ - npages = ((size_t) &kernel_end - (size_t) &kernel_start) / PAGE_SIZE; - if ((size_t)&kernel_end % PAGE_SIZE) + npages = ((size_t) &kernel_end - (size_t) &kernel_start) >> PAGE_SHIFT; + if ((size_t)&kernel_end & (PAGE_SIZE-1)) npages++; map_region((size_t)&kernel_start, (size_t)&kernel_start, npages, MAP_KERNEL_SPACE); @@ -686,8 +708,8 @@ int arch_paging_init(void) for(i=0; imods_count; i++, mmodule++) { // map physical address to the same virtual address - npages = (mmodule->mod_end - mmodule->mod_start) / PAGE_SIZE; - if (mmodule->mod_end % PAGE_SIZE) + npages = (mmodule->mod_end - mmodule->mod_start) >> PAGE_SHIFT; + if (mmodule->mod_end & (PAGE_SIZE-1)) npages++; map_region((size_t) (mmodule->mod_start), (size_t) (mmodule->mod_start), npages, MAP_KERNEL_SPACE); } @@ -699,17 +721,17 @@ int arch_paging_init(void) map_region(SCC_BOOTINFO, SCC_BOOTINFO, 1, MAP_KERNEL_SPACE); // map the initial ramdisk - npages = bootinfo->size / PAGE_SIZE; - if (bootinfo->size % PAGE_SIZE) + npages = bootinfo->size >> PAGE_SHIFT; + if (bootinfo->size & (PAGE_SIZE-1)) npages++; map_region(bootinfo->addr, bootinfo->addr, npages, MAP_KERNEL_SPACE); // map SCC's configuration registers - viraddr = map_region(CRB_X0_Y0, CRB_X0_Y0, (CRB_OWN-CRB_X0_Y0+16*1024*1024)/PAGE_SIZE, MAP_KERNEL_SPACE|MAP_NO_CACHE); + viraddr = map_region(CRB_X0_Y0, CRB_X0_Y0, (CRB_OWN-CRB_X0_Y0+16*1024*1024) >> PAGE_SHIFT, MAP_KERNEL_SPACE|MAP_NO_CACHE); kprintf("Map configuration registers at 0x%x\n", viraddr); // map SCC's message passing buffers - viraddr = map_region(MPB_X0_Y0, MPB_X0_Y0, (MPB_OWN-MPB_X0_Y0+16*1024*1024)/PAGE_SIZE, MAP_KERNEL_SPACE|MAP_MPE); + viraddr = map_region(MPB_X0_Y0, MPB_X0_Y0, (MPB_OWN-MPB_X0_Y0+16*1024*1024) >> PAGE_SHIFT, MAP_KERNEL_SPACE|MAP_MPE); kprintf("Map message passing buffers at 0x%x\n", viraddr); #endif diff --git a/arch/x86/scc/Makefile b/arch/x86/scc/Makefile index f32bc11f..2003a259 100644 --- a/arch/x86/scc/Makefile +++ b/arch/x86/scc/Makefile @@ -1,4 +1,4 @@ -C_source := scc_init.c SCC_API.c iRCCE_admin.c iRCCE_send.c iRCCE_isend.c iRCCE_irecv.c iRCCE_recv.c iRCCE_get.c iRCCE_put.c iRCCE_synch.c RCCE_malloc.c RCCE_shmalloc.c RCCE_debug.c RCCE_qsort.c RCCE_DCMflush.c RCCE_send.c RCCE_recv.c RCCE_flags.c RCCE_comm.c RCCE_put.c RCCE_get.c RCCE_synch.c RCCE_bcast.c RCCE_admin.c # RCCE_power_management.c +C_source := icc.c SCC_API.c iRCCE_admin.c iRCCE_send.c iRCCE_isend.c iRCCE_irecv.c iRCCE_recv.c iRCCE_get.c iRCCE_put.c iRCCE_synch.c RCCE_malloc.c RCCE_shmalloc.c RCCE_debug.c RCCE_qsort.c RCCE_DCMflush.c RCCE_send.c RCCE_recv.c RCCE_flags.c RCCE_comm.c RCCE_put.c RCCE_get.c RCCE_synch.c RCCE_bcast.c RCCE_admin.c # RCCE_power_management.c ASM_source := MODULE := arch_x86_scc diff --git a/arch/x86/scc/scc_init.c b/arch/x86/scc/icc.c similarity index 53% rename from arch/x86/scc/scc_init.c rename to arch/x86/scc/icc.c index d9f2628a..58a89be5 100644 --- a/arch/x86/scc/scc_init.c +++ b/arch/x86/scc/icc.c @@ -17,17 +17,22 @@ #include #include #include +#include +#ifdef CONFIG_ROCKCREEK #include #include #include - -#ifdef CONFIG_ROCKCREEK +#include bootinfo_t* bootinfo = (bootinfo_t*) SCC_BOOTINFO; +static int num_ues, my_ue; /* PSE bit for Pentium+ equals MPE (message buffer enable) flag in RCK! So, use it to create _PAGE_MPB symbol... */ #define _CR4_MPE 0x00000800 +/* maximal number of SCC's cores */ +#define MAX_SCC_CORES (NUM_ROWS*NUM_COLS*NUM_CORES) + /* * This is the modified MPB program, which is part of the RCCE distribution (src/mpb.c). * @@ -67,10 +72,9 @@ static int scc_clear(void) return 0; } -int scc_init(void) +int icc_init(void) { - int num_ranks; - int i, my_rank; + int i; uint64_t start, end, ticks, freq = 533; uint32_t cr4, msg = 0; @@ -109,9 +113,9 @@ int scc_init(void) // enable additional outputs RCCE_debug_set(RCCE_DEBUG_ALL); - my_rank = RCCE_ue(); - num_ranks = RCCE_num_ues(); - kprintf("Got rank %d of %d ranks\n", my_rank, num_ranks); + my_ue = RCCE_ue(); + num_ues = RCCE_num_ues(); + kprintf("Got rank %d of %d ranks\n", my_ue, num_ues); i = ReadConfigReg(CRB_OWN+GLCFG0); kprintf("glcfg0 0x%x\n", i); @@ -119,7 +123,7 @@ int scc_init(void) RCCE_barrier(&RCCE_COMM_WORLD); kputs("RCCE test...\t"); - if (my_rank == 0) + if (my_ue == 0) msg = 0x4711; if (RCCE_bcast((char*) &msg, sizeof(msg), 0, RCCE_COMM_WORLD) == RCCE_SUCCESS) kprintf("successfull! (0x%x)\n", msg); @@ -131,4 +135,102 @@ int scc_init(void) return 0; } +int icc_ping(int ue) +{ + icc_header_t ping_header = {ICC_TYPE_PINGREQUEST, 0, sizeof(uint64_t)}; + uint64_t tsc; + uint32_t flags; + iRCCE_SEND_REQUEST send_request; + + if (BUILTIN_EXPECT(ue == my_ue, 0)) + return -EINVAL; + if (BUILTIN_EXPECT((ue < 0) || (ue >= num_ues), 0)) + return -EINVAL; + + tsc = rdtsc(); + + // iRCCE is not thread save => disable interrupts + flags = irq_nested_disable(); + + iRCCE_isend((char*) &ping_header, sizeof(icc_header_t), ue, NULL); + iRCCE_isend((char*) &tsc, sizeof(uint64_t), ue, &send_request); + + // waiting for the completion + while(iRCCE_isend_test(&send_request, NULL) != iRCCE_SUCCESS) + icc_check(); // oh, we have time to check incoming requests + + irq_nested_enable(flags); + + return 0; +} + +static void interpret_header(icc_header_t* header, int recv_ue) +{ + //kprintf("Got ICC message %d from %d\n", header->type, recv_ue); + + switch(header->type) + { + case ICC_TYPE_PINGREQUEST: { + icc_header_t response = {ICC_TYPE_PINGRESPONSE, 0, sizeof(uint64_t)}; + iRCCE_RECV_REQUEST recv_req; + uint64_t tsc; + + iRCCE_isend((char*) &response, sizeof(icc_header_t), recv_ue, NULL); + if (iRCCE_irecv((char*) &tsc, sizeof(uint64_t), recv_ue, &recv_req) != iRCCE_SUCCESS) + iRCCE_irecv_wait(&recv_req); + + iRCCE_isend((char*) &tsc, sizeof(uint64_t), recv_ue, NULL); + iRCCE_isend_push(); + } + break; + case ICC_TYPE_PINGRESPONSE: { + uint64_t start, end; + iRCCE_RECV_REQUEST recv_req; + + if (iRCCE_irecv((char*) &start, sizeof(uint64_t), recv_ue, &recv_req) != iRCCE_SUCCESS) + iRCCE_irecv_wait(&recv_req); + end = rdtsc(); + kprintf("Receive ping response. Ticks: %d\n", end-start); + } + break; + default: + kprintf("Receive unknown ICC message (%d)\n", header->type); + } +} + +/* + * By entering this function, interrupts are already disables + * => No race by using the static variables + */ +void icc_check(void) +{ + static icc_header_t header[MAX_SCC_CORES]; + static iRCCE_RECV_REQUEST request[MAX_SCC_CORES]; + static int8_t pending[MAX_SCC_CORES] = {[0 ... MAX_SCC_CORES-1] = 0}; + int i, ret; + + // pushes the progress of non-blocking communication requests + iRCCE_isend_push(); + iRCCE_irecv_push(); + + for(i=0; irx_buffer = mem_allocation(8192+16, MAP_KERNEL_SPACE|MAP_HEAP|MAP_NO_CACHE); + rtl8139if->rx_buffer = mem_allocation(8192+16, MAP_KERNEL_SPACE|MAP_NO_CACHE); if (!(rtl8139if->rx_buffer)) { LWIP_DEBUGF(NETIF_DEBUG, ("rtl8139if_init: out of memory\n")); kfree(rtl8139if, sizeof(rtl1839if_t)); @@ -336,7 +336,7 @@ err_t rtl8139if_init(struct netif* netif) memset(rtl8139if->rx_buffer, 0, 8192+16); /* allocate the send buffers */ - rtl8139if->tx_buffer[0] = mem_allocation(4*4096, MAP_KERNEL_SPACE|MAP_HEAP|MAP_NO_CACHE); + rtl8139if->tx_buffer[0] = mem_allocation(4*4096, MAP_KERNEL_SPACE|MAP_NO_CACHE); if (!(rtl8139if->tx_buffer[0])) { LWIP_DEBUGF(NETIF_DEBUG, ("rtl8139if_init: out of memory\n")); kfree(rtl8139if->rx_buffer, 8192+16); @@ -482,7 +482,7 @@ err_t rtl8139if_init(struct netif* netif) /* maximum transfer unit */ netif->mtu = 1500; /* broadcast capability */ - netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP; + netif->flags |= NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP; /* hardware address length */ netif->hwaddr_len = 6; diff --git a/drivers/net/rtl8139.h b/drivers/net/rtl8139.h index e0b9de05..43bd6fe4 100644 --- a/drivers/net/rtl8139.h +++ b/drivers/net/rtl8139.h @@ -19,8 +19,8 @@ * This code based mostly on the online manual http://www.lowlevel.eu/wiki/RTL8139 */ -#ifndef __HAVE_RTL839_H__ -#define __HAVE_RL8139_H__ +#ifndef __HAVE_RTL8139_H__ +#define __HAVE_RTL8139_H__ #include #include diff --git a/drivers/stderr/Makefile b/drivers/stderr/Makefile index f0b38c86..05d06d5c 100644 --- a/drivers/stderr/Makefile +++ b/drivers/stderr/Makefile @@ -1,5 +1,4 @@ C_source := stderr.c - MODULE := drivers_stderr include $(TOPDIR)/Makefile.inc diff --git a/drivers/stderr/stderr.c b/drivers/stderr/stderr.c index effc5942..80b83300 100644 --- a/drivers/stderr/stderr.c +++ b/drivers/stderr/stderr.c @@ -33,7 +33,11 @@ static ssize_t stderr_read(vfs_node_t* node, uint8_t* buffer, size_t size, off_t static ssize_t stderr_write(vfs_node_t* node, uint8_t* buffer, size_t size, off_t offset) { - kprintf("\nFehler: %s", buffer); + kprintf("\nFehler: "); + int i; + for (i = 0; i #include #include +#include + +#ifdef CONFIG_ROCKCREEK +#include +#endif static vfs_node_t initrd_root; @@ -93,13 +98,85 @@ static ssize_t initrd_read(vfs_node_t* node, uint8_t* buffer, size_t size, off_t static ssize_t initrd_write(vfs_node_t* node, uint8_t* buffer, size_t size, off_t offset) { + uint32_t i, writtenbytes = 0, writebytes = 0; + char* data = NULL; block_list_t* blist = &node->block_list; - char* data = (char*) blist->data[0]; - //////////ACHTUNG keine Überprüfung der Blcoklängen etc. - memcpy(data, buffer, size); + do { + data = (char*) blist->data[0]; + if ((size - writtenbytes) >= MAX_DATABLOCKS) + writebytes = MAX_DATABLOCKS; + else + writebytes = size - writtenbytes; + + memcpy(data, buffer, writebytes); + writtenbytes += writebytes; + //kprintf("geschrieben: %i", writtenbytes); - return size; + if (!blist->next) { + blist->next = (block_list_t*) kmalloc(sizeof(block_list_t)); + if (blist->next) { + memset(blist->next, 0x00, sizeof(block_list_t)); + } + } + + blist = blist->next; + } while(size > writtenbytes); + + return writtenbytes; + +/* + uint32_t i, pos = 0, found = 0; + char* data = NULL; + block_list_t* blist = &node->block_list; + + kprintf("tatsachen offset %i\n", offset); + + // searching for the valid data block + if (offset) { + pos = offset / node->block_size; + offset = offset % node->block_size; + } + kprintf("Pos: %i, Offset: %i, %i", pos, offset, node->block_size); + + + + do { + for(i=0; idata[i]) { + found++; + if (found > pos) + data = (char*) blist->data[i]; + break; + } + } + if all blocks have already been used, we have to allocate a new one + if (!blist->next) { + blist->next = (block_list_t*) kmalloc(sizeof(block_list_t)); + if (blist->next) { + kprintf("?"); + memset(blist->next, 0x00, sizeof(block_list_t)); + } + } + + blist = blist->next; + } while(blist && !data); + + if (BUILTIN_EXPECT(!data, 0)) + return 0; +*/ + /* + * If the data block is not large engough, + * we copy only the rest of the current block. + * The user has to restart the write operation + * for the next block. + */ +/* if (offset+size >= node->block_size) + size = node->block_size - offset; + + memcpy(data + offset, buffer, size); + +*/ //return size; } @@ -268,9 +345,12 @@ int initrd_init(void) tmp = mkdir_fs(fs_root, "dev"); /* create the character device "null" */ null_init(tmp, "null"); - //stdin_init(tmp, "stdin"); - //stdout_init(tmp, "stdout"); - //stderr_init(tmp, "stderr"); + /* create the standart input device "stdin" */ + stdin_init(tmp, "stdin"); + /* create the standart output device "stdout" */ + stdout_init(tmp, "stdout"); + /* create the standart error-output device "stderr" */ + stderr_init(tmp, "stderr"); /* For every module.. */ #ifdef CONFIG_MULTIBOOT diff --git a/include/metalsvm/config.h.example b/include/metalsvm/config.h.example index b5c0536e..bb405699 100644 --- a/include/metalsvm/config.h.example +++ b/include/metalsvm/config.h.example @@ -32,6 +32,7 @@ extern "C" { #define KERNEL_STACK_SIZE 8192 #define KMSG_SIZE (128*1024) #define PAGE_SIZE 4096 +#define PAGE_SHIFT 12 #define CACHE_LINE 64 #define MAILBOX_SIZE 8 #define TIMER_FREQ 100 /* in HZ */ diff --git a/include/metalsvm/fs.h b/include/metalsvm/fs.h index b9dbfb2e..58897aa2 100644 --- a/include/metalsvm/fs.h +++ b/include/metalsvm/fs.h @@ -196,6 +196,9 @@ vfs_node_t* findnode_fs(const char* name); /* @} */ int null_init(vfs_node_t* node, const char* name); +int stdin_init(vfs_node_t* node, const char* name); +int stdout_init(vfs_node_t* node, const char* name); +int stderr_init(vfs_node_t* node, const char* name); int initrd_init(void); #endif diff --git a/include/metalsvm/fs_types.h b/include/metalsvm/fs_types.h index c065312b..9b9df7e3 100644 --- a/include/metalsvm/fs_types.h +++ b/include/metalsvm/fs_types.h @@ -1,20 +1,20 @@ /* - * Copyright 2011 Stefan Lankes, Chair for Operating Systems, - * RWTH Aachen University - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of MetalSVM. ++ * Copyright 2011 Stefan Lankes, Chair for Operating Systems, ++ * RWTH Aachen University ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an "AS IS" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ * ++ * This file is part of MetalSVM. */ #ifndef __FS_TYPES_H__ diff --git a/include/metalsvm/stdlib.h b/include/metalsvm/stdlib.h index fe824207..ad1cecdb 100644 --- a/include/metalsvm/stdlib.h +++ b/include/metalsvm/stdlib.h @@ -41,8 +41,8 @@ extern "C" { #define MAP_USER_SPACE (1 << 1) #define MAP_PAGE_TABLE (1 << 2) #define MAP_NO_CACHE (1 << 3) -#define MAP_STACK (1 << 4) -#define MAP_HEAP (1 << 5) +//#define MAP_STACK (1 << 4) +//#define MAP_HEAP (1 << 5) #define MAP_CODE (1 << 6) #define MAP_READONLY (1 << 7) #ifdef CONFIG_ROCKCREEK diff --git a/include/metalsvm/syscall.h b/include/metalsvm/syscall.h index 97785247..b47fc284 100644 --- a/include/metalsvm/syscall.h +++ b/include/metalsvm/syscall.h @@ -49,6 +49,7 @@ extern "C" { #define __NR_fork 12 #define __NR_wait 13 #define __NR_execve 14 +#define __NR_times 15 #ifdef __cplusplus } diff --git a/include/metalsvm/tasks.h b/include/metalsvm/tasks.h index 904f737a..5329fc61 100644 --- a/include/metalsvm/tasks.h +++ b/include/metalsvm/tasks.h @@ -32,6 +32,10 @@ #include #include #include +#include +#ifdef CONFIG_ROCKCREEK +#include +#endif #ifdef __cplusplus extern "C" { @@ -134,6 +138,17 @@ int sys_fork(void); */ int sys_execve(const char* fname, char** argv, char** env); +static inline void check_workqueues(void) +{ + uint32_t flags = irq_nested_disable(); + +#ifdef CONFIG_ROCKCREEK + icc_check(); +#endif + + irq_nested_enable(flags); +} + #ifdef __cplusplus } #endif diff --git a/include/metalsvm/tasks_types.h b/include/metalsvm/tasks_types.h index 221e5ba3..3aef1dc1 100644 --- a/include/metalsvm/tasks_types.h +++ b/include/metalsvm/tasks_types.h @@ -34,6 +34,8 @@ #include #include #include +#include +#include #include #ifdef __cplusplus @@ -47,6 +49,10 @@ extern "C" { #define TASK_FINISHED 4 #define TASK_IDLE 5 +#define TASK_DEFAULT_FLAGS 0 +#define TASK_FPU_INIT (1 << 0) +#define TASK_FPU_USED (1 << 1) + typedef int (STDCALL *entry_point_t)(void*); struct page_dir; @@ -58,9 +64,9 @@ typedef struct task { uint32_t status; /// Usage in number of pages atomic_int32_t user_usage; - /// Avoids concurrent access to the page directory + /// Avoids concurrent access to the page directory spinlock_t pgd_lock; - /// pointer to the page directory + /// pointer to the page directory struct page_dir* pgd; /// Lock for the VMA_list spinlock_t vma_lock; @@ -68,10 +74,20 @@ typedef struct task { vma_t* vma_list; /// Filedescriptor table fildes_t fildes_table[MAX_FILDES]; + /// Additional status flags. For instance, to signalize the using of the FPU + uint32_t flags; + /// starting time/tick of the task + uint64_t start_tick; + /// Start address of the heap + uint32_t start_heap; + /// End address of the heap + uint32_t end_heap; /// Mail inbox mailbox_wait_msg_t inbox; /// Mail outbox array mailbox_wait_msg_t* outbox[MAX_TASKS]; + /// FPU state + union fpu_state fpu; } __attribute__((packed)) task_t; #ifdef __cplusplus diff --git a/include/metalsvm/time.h b/include/metalsvm/time.h index 4c2cdf51..aa47e47a 100644 --- a/include/metalsvm/time.h +++ b/include/metalsvm/time.h @@ -30,6 +30,26 @@ extern "C" { #endif +typedef uint32_t clock_t; + +struct tms { + clock_t tms_utime; + clock_t tms_stime; + clock_t tms_cutime; + clock_t tms_cstime; +}; + +#ifndef CLOCKS_PER_SEC +// newlib's default value +#define CLOCKS_PER_SEC 1000 +#endif + +/** @brief Determines the time in CLK_TCK's + * + * System call, which returns the value of time in CLK_TCK's + */ +int sys_times(struct tms*, clock_t* clock); + /** @brief Initialize Timer interrupts * * This procedure installs IRQ handlers for timer interrupts @@ -49,7 +69,13 @@ void timer_wait(unsigned int ticks); */ uint64_t get_clock_tick(void); -static inline void sleep(unsigned int i) { timer_wait(i*TIMER_FREQ); } +/** @brief sleep some seconds + * + * This function sleeps some seconds + * + * @paran sec Amount of seconds to wait + */ +static inline void sleep(unsigned int sec) { timer_wait(sec*TIMER_FREQ); } #ifdef __cplusplus } diff --git a/kernel/main.c b/kernel/main.c index 8be29f22..0b7ef87f 100644 --- a/kernel/main.c +++ b/kernel/main.c @@ -30,6 +30,9 @@ #include #include #include +#ifdef CONFIG_ROCKCREEK +#include +#endif extern int test_init(void); @@ -90,7 +93,7 @@ int main(void) multitasking_init(); mmu_init(); #ifdef CONFIG_ROCKCREEK - scc_init(); + icc_init(); #endif initrd_init(); diff --git a/kernel/syscall.c b/kernel/syscall.c index df1e5030..cbeccb7b 100644 --- a/kernel/syscall.c +++ b/kernel/syscall.c @@ -23,6 +23,8 @@ #include #include #include +#include +#include static int sys_read(int fd, const char *buf, size_t len) { @@ -32,20 +34,16 @@ static int sys_read(int fd, const char *buf, size_t len) (uint8_t*)buf, len, per_core(current_task)->fildes_table[fd].offset); per_core(current_task)->fildes_table[fd].offset += readbytes; - /*kprintf("fd:%i, Dateilaenge:%i, Dateiinhalt: %s \n", fd, len, buf);*/ + //kprintf("fd:%i, Dateilaenge:%i, Dateiinhalt: %s \n", fd, len, buf); /* Beware: still reading above file limit! */ return readbytes; } - + static int sys_write(int fd, const char *buf, size_t len) { unsigned int wrotebytes; - /* per_core(current_task)->fildes_table[fd].node->write = 1; */ - wrotebytes = write_fs( - per_core(current_task)->fildes_table[fd].node, - (uint8_t*)buf, len, 0); - /* per_core(current_task)->fildes_table[fd].offset); */ - /* kprintf("ins Dateis. geschr. -- fd:%i, Dateilaenge:%i, Dateiinhalt: %s \n", fd, len, buf); */ + wrotebytes = write_fs(per_core(current_task)->fildes_table[fd].node, (uint8_t*)buf, len, per_core(current_task)->fildes_table[fd].offset); + //kprintf("ins Dateis. geschr. -- fd:%i, Dateilaenge:%i, Schreiblaenge: %i, Dateiinhalt: %s \n", fd, len, wrotebytes, buf); per_core(current_task)->fildes_table[fd].offset += wrotebytes; return wrotebytes; @@ -54,12 +52,12 @@ static int sys_write(int fd, const char *buf, size_t len) static int sys_open(const char* file, int flags, int mode) { int fd; - for (fd = 0; fd < MAX_FILDES; fd++) { + for (fd = 3; fd < MAX_FILDES; fd++) { if (per_core(current_task)->fildes_table[fd].node == NULL) { per_core(current_task)->fildes_table[fd].node = findnode_fs((char*) file); return fd; } - } + } if (fd >= MAX_FILDES) { kprintf("Unable to create filedescriptor"); return -EINVAL; @@ -73,6 +71,32 @@ static int sys_close(int fd) per_core(current_task)->fildes_table[fd].offset = 0; return 0; + } + +static int sys_sbrk(int incr) +{ + task_t* task = per_core(current_task); + vma_t* tmp = NULL; + int ret; + + spinlock_lock(&task->vma_lock); + + tmp = task->vma_list; + while(tmp && !((task->end_heap >= tmp->start) && (task->end_heap <= tmp->end))) + tmp = tmp->next; + + ret = (int) task->end_heap; + task->end_heap += incr; + if (task->end_heap < task->start_heap) + task->end_heap = task->start_heap; + + // resize virtual memory area + if (tmp && (tmp->end <= task->end_heap)) + tmp->end = task->end_heap; + + spinlock_unlock(&task->vma_lock); + + return ret; } int syscall_handler(uint32_t sys_nr, ...) @@ -80,6 +104,8 @@ int syscall_handler(uint32_t sys_nr, ...) int ret = -EINVAL; va_list vl; + check_workqueues(); + va_start(vl, sys_nr); switch(sys_nr) @@ -92,28 +118,32 @@ int syscall_handler(uint32_t sys_nr, ...) int fd = va_arg(vl, int); const char* buf = va_arg(vl, const char*); size_t len = va_arg(vl, size_t); - kprintf("%s", buf); - //ret = sys_read(fd, buf, len); + ret = sys_read(fd, buf, len); break; } case __NR_write: { int fd = va_arg(vl, int); const char* buf = va_arg(vl, const char*); size_t len = va_arg(vl, size_t); - kprintf("%s", buf); - //ret = sys_write(fd, buf, len); + ret = sys_write(fd, buf, len); break; } case __NR_open: { const char* file = va_arg(vl, const char*); int flags = va_arg(vl, int); int mode = va_arg(vl, int); - //ret = sys_open(file, flags, mode); + ret = sys_open(file, flags, mode); break; } case __NR_close: { int fd = va_arg(vl, int); - //ret = sys_close(fd); + ret = sys_close(fd); + break; + } + case __NR_sbrk: { + int incr = va_arg(vl, int); + + ret = sys_sbrk(incr); break; } case __NR_getpid: @@ -124,7 +154,7 @@ int syscall_handler(uint32_t sys_nr, ...) break; case __NR_wait: { int32_t* status = va_arg(vl, int32_t*); - + ret = wait(status); break; } @@ -136,6 +166,13 @@ int syscall_handler(uint32_t sys_nr, ...) ret = sys_execve(name, argv, env); break; } + case __NR_times: { + struct tms* buffer = va_arg(vl, struct tms*); + clock_t* clock = va_arg(vl, clock_t*); + + ret = sys_times(buffer, clock); + break; + } default: kputs("invalid system call\n"); ret = -ENOSYS; diff --git a/kernel/tasks.c b/kernel/tasks.c index 5cf3e718..88a9bfba 100644 --- a/kernel/tasks.c +++ b/kernel/tasks.c @@ -38,6 +38,7 @@ #include #include #include +#include #include #include @@ -48,7 +49,7 @@ DEFINE_PER_CORE(task_t*, current_task, NULL); * A task's id will be its position in this array. */ static task_t task_table[MAX_TASKS] = {[0 ... MAX_TASKS-1] = {0, TASK_INVALID, ATOMIC_INIT(0), \ - SPINLOCK_INIT, NULL, SPINLOCK_INIT, NULL, FS_INIT}}; + SPINLOCK_INIT, NULL, SPINLOCK_INIT, NULL, FS_INIT, 0, 0, 0, 0}}; static spinlock_irqsave_t table_lock = SPINLOCK_IRQSAVE_INIT; /** @brief helper function for the assembly code to determine the current task @@ -67,6 +68,7 @@ int multitasking_init(void) { memset(task_table[0].outbox, 0x00, sizeof(mailbox_wait_msg_t*)*MAX_TASKS); per_core(current_task) = task_table+0; per_core(current_task)->pgd = get_boot_pgd(); + task_table[0].flags = TASK_DEFAULT_FLAGS; return 0; } @@ -183,12 +185,20 @@ static int create_task(tid_t* id, entry_point_t ep, void* arg) mailbox_wait_msg_init(&task_table[i].inbox); memset(task_table[i].outbox, 0x00, sizeof(mailbox_wait_msg_t*)*MAX_TASKS); task_table[i].outbox[per_core(current_task)->id] = &per_core(current_task)->inbox; + task_table[i].fildes_table[0].node = findnode_fs("/dev/stdin"); + task_table[i].fildes_table[1].node = findnode_fs("/dev/stdout"); + task_table[i].fildes_table[2].node = findnode_fs("/dev/stderr"); + if (id) *id = i; ret = create_default_frame(task_table+i, ep, arg); + task_table[i].flags = TASK_DEFAULT_FLAGS; + task_table[i].start_heap = 0; + task_table[i].end_heap = 0; + task_table[i].start_tick = get_clock_tick(); task_table[i].status = TASK_READY; break; } @@ -250,6 +260,11 @@ int sys_fork(void) mailbox_wait_msg_init(&task_table[i].inbox); memset(task_table[i].outbox, 0x00, sizeof(mailbox_wait_msg_t*)*MAX_TASKS); task_table[i].outbox[per_core(current_task)->id] = &per_core(current_task)->inbox; + task_table[i].flags = per_core(current_task)->flags; + memcpy(&(task_table[i].fpu), &(per_core(current_task)->fpu), sizeof(union fpu_state)); + task_table[i].start_tick = get_clock_tick(); + task_table[i].start_heap = 0; + task_table[i].end_heap = 0; ret = arch_fork(task_table+i); @@ -349,8 +364,8 @@ static int load_task(load_args_t* largs) if (!prog_header.virt_addr) continue; - npages = (prog_header.mem_size / PAGE_SIZE); - if (prog_header.mem_size % PAGE_SIZE) + npages = (prog_header.mem_size >> PAGE_SHIFT); + if (prog_header.mem_size & (PAGE_SIZE-1)) npages++; addr = get_pages(npages); @@ -366,6 +381,10 @@ static int load_task(load_args_t* largs) // clear pages memset((void*) prog_header.virt_addr, 0, npages*PAGE_SIZE); + // set starting point of the heap + if (per_core(current_task)->start_heap < prog_header.virt_addr+prog_header.mem_size) + per_core(current_task)->start_heap = per_core(current_task)->end_heap = prog_header.virt_addr+prog_header.mem_size; + // load program read_fs(node, (uint8_t*)prog_header.virt_addr, prog_header.file_size, prog_header.offset); @@ -384,8 +403,8 @@ static int load_task(load_args_t* largs) case ELF_PT_GNU_STACK: // Indicates stack executability // create user-level stack - npages = DEFAULT_STACK_SIZE / PAGE_SIZE; - if (DEFAULT_STACK_SIZE % PAGE_SIZE) + npages = DEFAULT_STACK_SIZE >> PAGE_SHIFT; + if (DEFAULT_STACK_SIZE & (PAGE_SIZE-1)) npages++; addr = get_pages(npages); @@ -472,6 +491,9 @@ static int load_task(load_args_t* largs) kfree(largs, sizeof(load_args_t)); + // clear fpu state + per_core(current_task)->flags &= ~(TASK_FPU_USED|TASK_FPU_INIT); + jump_to_user_code(header.entry, stack+offset); return 0; @@ -692,6 +714,8 @@ void scheduler(void) unsigned int i; unsigned int new_id; + check_workqueues(); + #if MAX_CORES > 1 spinlock_irqsave_lock(&table_lock); #endif @@ -700,6 +724,12 @@ void scheduler(void) if (per_core(current_task)->status == TASK_FINISHED) per_core(current_task)->status = TASK_INVALID; + /* if the task is using the FPU, we need to save the FPU context */ + if (per_core(current_task)->flags & TASK_FPU_USED) { + save_fpu_state(&(per_core(current_task)->fpu)); + per_core(current_task)->flags &= ~TASK_FPU_USED; + } + for(i=1, new_id=(per_core(current_task)->id + 1) % MAX_TASKS; istatus == TASK_RUNNING) per_core(current_task)->status = TASK_READY; task_table[new_id].status = TASK_RUNNING; - per_core(current_task) = task_table+new_id; + goto get_task_out; } } diff --git a/kernel/tests.c b/kernel/tests.c index 596b1e51..eae9d856 100644 --- a/kernel/tests.c +++ b/kernel/tests.c @@ -24,6 +24,9 @@ #include #include #include +#ifdef CONFIG_ROCKCREEK +#include +#endif static sem_t consuming, producing; static mailbox_int32_t mbox; @@ -83,6 +86,20 @@ static int STDCALL foo(void* arg) return 42; } +#ifdef CONFIG_ROCKCREEK +static int STDCALL ping(void* arg) +{ + int i; + + for(i=0; i<20; i++) { + icc_ping(1); + sleep(1); + } + + return 0; +} +#endif + static int STDCALL join_test(void* arg) { tid_t id, ret; @@ -102,7 +119,7 @@ static int STDCALL join_test(void* arg) int test_init(void) { - char* argv[] = {"/bin/tests", NULL}; + char* argv[] = {"/bin/hello", NULL}; //sem_init(&producing, 1); //sem_init(&consuming, 0); @@ -112,8 +129,10 @@ int test_init(void) //create_kernel_task(NULL, join_test, NULL); //create_kernel_task(NULL, producer, NULL); //create_kernel_task(NULL, consumer, NULL); - create_user_task(NULL, "/bin/hello", NULL); - //create_user_task(NULL, "/bin/tests", argv); + //create_kernel_task(NULL, ping, NULL); + //create_user_task(NULL, "/bin/hello", argv); + create_user_task(NULL, "/bin/hello", argv); + //create_user_task(NULL, "/bin/jacobi", argv); return 0; } diff --git a/mm/memory.c b/mm/memory.c index cf7f5e48..f70a84ee 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -29,6 +29,9 @@ #ifdef CONFIG_MULTIBOOT #include #endif +#ifdef CONFIG_ROCKCREEK +#include +#endif /* * 0 => free @@ -52,8 +55,8 @@ extern const void kernel_end; inline static int page_marked(unsigned int i) { - unsigned int index = i / 8; - unsigned int mod = i % 8; + unsigned int index = i >> 3; + unsigned int mod = i & 0x7; return (bitmap[index] & (1 << mod)); } @@ -65,8 +68,8 @@ inline static int page_unmarked(unsigned int i) inline static void page_set_mark(unsigned int i) { - unsigned int index = i / 8; - unsigned int mod = i % 8; + unsigned int index = i >> 3; + unsigned int mod = i & 0x7; //if (page_marked(i)) // kprintf("page %u is alread marked\n", i); @@ -104,7 +107,7 @@ int mmu_init(void) end_addr = addr + mmap->len; while (addr < end_addr) { - page_clear_mark(addr / PAGE_SIZE); + page_clear_mark(addr >> PAGE_SHIFT); addr += PAGE_SIZE; atomic_int32_inc(&total_pages); atomic_int32_inc(&total_available_pages); @@ -129,13 +132,13 @@ int mmu_init(void) /* * Mark the mb_info as used. */ - page_set_mark((size_t)mb_info / PAGE_SIZE); + page_set_mark((size_t)mb_info >> 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_SIZE); + page_set_mark(addr >> PAGE_SHIFT); atomic_int32_inc(&total_allocated_pages); atomic_int32_dec(&total_available_pages); } @@ -143,7 +146,7 @@ int mmu_init(void) } #elif defined(CONFIG_ROCKCREEK) for(addr=PRIVATE_MEM1_START; addr> PAGE_SHIFT); if (addr > addr + PAGE_SIZE) break; atomic_int32_inc(&total_pages); @@ -151,7 +154,7 @@ int mmu_init(void) } for(addr=PRIVATE_MEM2_START; addr> PAGE_SHIFT); if (addr > addr + PAGE_SIZE) break; atomic_int32_inc(&total_pages); @@ -161,7 +164,7 @@ int mmu_init(void) /* * Mark the bootinfo as used. */ - page_set_mark((size_t)bootinfo / PAGE_SIZE); + page_set_mark((size_t)bootinfo >> PAGE_SHIFT); atomic_int32_inc(&total_allocated_pages); atomic_int32_dec(&total_available_pages); @@ -170,7 +173,7 @@ int mmu_init(void) * Therefore, we set these pages as used. */ for(addr=bootinfo->addr; addr < bootinfo->addr+bootinfo->size; addr+=PAGE_SIZE) { - page_set_mark(addr / PAGE_SIZE); + page_set_mark(addr >> PAGE_SHIFT); atomic_int32_inc(&total_allocated_pages); atomic_int32_dec(&total_available_pages); } @@ -179,19 +182,19 @@ int mmu_init(void) #endif kernel_size = (size_t) &kernel_end - (size_t) &kernel_start; - if (kernel_size % PAGE_SIZE) - kernel_size += PAGE_SIZE - kernel_size % PAGE_SIZE; - atomic_int32_add(&total_allocated_pages, kernel_size/PAGE_SIZE); - atomic_int32_sub(&total_available_pages, kernel_size/PAGE_SIZE); + if (kernel_size & (PAGE_SIZE-1)) + kernel_size += PAGE_SIZE - (kernel_size & (PAGE_SIZE-1)); + atomic_int32_add(&total_allocated_pages, kernel_size >> PAGE_SHIFT); + atomic_int32_sub(&total_available_pages, kernel_size >> PAGE_SHIFT); /* set kernel space as used */ - for(i=(size_t) &kernel_start / PAGE_SIZE; i < (size_t) &kernel_end / PAGE_SIZE; i++) + for(i=(size_t) &kernel_start >> PAGE_SHIFT; i < (size_t) &kernel_end >> PAGE_SHIFT; i++) page_set_mark(i); - if ((size_t) &kernel_end % PAGE_SIZE) + if ((size_t) &kernel_end & (PAGE_SIZE-1)) page_set_mark(i); - alloc_start = (size_t) &kernel_end / PAGE_SIZE; - if ((size_t) &kernel_end % PAGE_SIZE) + alloc_start = (size_t) &kernel_end >> PAGE_SHIFT; + if ((size_t) &kernel_end & (PAGE_SIZE-1)) alloc_start++; return paging_init(); @@ -217,7 +220,7 @@ size_t get_pages(uint32_t npages) next_try: while((k < BITMAP_SIZE) && page_marked(i)) { k++; - i = (i+1) % BITMAP_SIZE; + i = (i+1) & (BITMAP_SIZE-1); } if (k >= BITMAP_SIZE) @@ -225,7 +228,7 @@ next_try: for(j=1; (j> PAGE_SHIFT; if (BUILTIN_EXPECT(!phyaddr, 0)) return -EINVAL; @@ -277,9 +280,9 @@ int put_page(size_t phyaddr) void* mem_allocation(size_t sz, uint32_t flags) { size_t phyaddr, viraddr; - uint32_t npages = sz / PAGE_SIZE; + uint32_t npages = sz >> PAGE_SHIFT; - if (sz % PAGE_SIZE) + if (sz & (PAGE_SIZE-1)) npages++; phyaddr = get_pages(npages); @@ -293,7 +296,7 @@ void* mem_allocation(size_t sz, uint32_t flags) void* kmalloc(size_t sz) { - return mem_allocation(sz, MAP_KERNEL_SPACE|MAP_HEAP); + return mem_allocation(sz, MAP_KERNEL_SPACE); } void kfree(void* addr, size_t sz) @@ -304,8 +307,8 @@ void kfree(void* addr, size_t sz) if (BUILTIN_EXPECT(!addr && !sz, 0)) return; - npages = sz / PAGE_SIZE; - if (sz % PAGE_SIZE) + npages = sz >> PAGE_SHIFT; + if (sz & (PAGE_SIZE-1)) npages++; spinlock_lock(&bitmap_lock); @@ -316,7 +319,7 @@ void kfree(void* addr, size_t sz) if (!phyaddr) continue; - index = phyaddr / PAGE_SIZE; + index = phyaddr >> PAGE_SHIFT; page_clear_mark(index); } diff --git a/newlib/examples/Makefile b/newlib/examples/Makefile index 38a21cc6..e1a373f9 100644 --- a/newlib/examples/Makefile +++ b/newlib/examples/Makefile @@ -3,6 +3,7 @@ NEWLIB = ../x86/i586-metalsvm-elf32 MAKE = make STRIP_DEBUG = --strip-debug KEEP_DEBUG = --only-keep-debug +LDFLAGS = # other implicit rules %.o : %.c @@ -10,7 +11,13 @@ KEEP_DEBUG = --only-keep-debug default: all -all: hello tests +all: hello tests jacobi + +jacobi: jacobi.o + $(CC_FOR_TARGET) -T link.ld -o $@ $(LDFLAGS) $< -lm + $(OBJCOPY_FOR_TARGET) $(KEEP_DEBUG) $@ $@.sym + $(OBJCOPY_FOR_TARGET) $(STRIP_DEBUG) $@ + chmod a-x $@.sym tests: tests.o $(CC_FOR_TARGET) -T link.ld -o $@ $(LDFLAGS) $< diff --git a/newlib/examples/hello.c b/newlib/examples/hello.c index f22e16f6..ea9756b8 100644 --- a/newlib/examples/hello.c +++ b/newlib/examples/hello.c @@ -28,8 +28,19 @@ extern int errno; int main(int argc, char** argv) { //int i; - char* str = (char *)malloc(40 * sizeof(char)); + char* str = (char *)malloc(20 * sizeof(char)); FILE* testfile; + testfile = fopen("/bin/test", "w+r"); + setbuf(testfile, NULL); + fflush(NULL); + fwrite("wsblablaxxxyyyyzzzzzz", 1, 19, testfile); + fclose(testfile); + + testfile = fopen("/bin/test", "w+r"); + setbuf(testfile, NULL); + fread(str, 1, 20, testfile); + fflush(NULL); + printf("Aus Datei gelesen (/bin/test):%s\n", str); testfile = fopen("/bin/test", "w+r"); setbuf(testfile, NULL); diff --git a/newlib/examples/jacobi.c b/newlib/examples/jacobi.c new file mode 100644 index 00000000..f4804aa3 --- /dev/null +++ b/newlib/examples/jacobi.c @@ -0,0 +1,196 @@ +/* + * Copyright 2010-2011 Stefan Lankes + * Chair for Operating Systems, RWTH Aachen University + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#undef errno +extern int errno; + +#define MATRIX_SIZE 128 +#define MAXVALUE 1337 +#define PAGE_SIZE 4096 +#define CACHE_SIZE (256*1024) +#define ALIGN(x,a) (((x)+(a)-1)&~((a)-1)) + +static int generate_empty_matrix(double*** A , unsigned int N) { + unsigned int iCnt; + int i,j; + + *A = (double**) malloc((N+1)*sizeof(double*)); + + if (*A == NULL) + return -2; /* Error */ + + (*A)[0] = (double*) malloc((N+1)*N*sizeof(double)); + + if (**A == NULL) + return -2; /* Error */ + + for(iCnt=1; iCnt Sum |A[i][j]| with (i != j) + */ + + (*A)[i][i] = sum + 2.0; + (*A)[i][N] += sum + 2.0; + } + + return 0; +} + +int main(int argc, char **argv) +{ + double* temp; + unsigned int i, j, iter_start, iter_end; + unsigned int iterations = 0; + double error, norm, max = 0.0; + double** A=0; + double* X; + double* X_old, xi; + clock_t start, end; + + if (generate_empty_matrix(&A,MATRIX_SIZE) < 0) + { + printf("generate_empty_matrix() failed...\n"); + exit(-1); + + } + + printf("generate_empty_matrix() done...\n"); + + X = (double*) malloc(MATRIX_SIZE*sizeof(double)); + X_old = (double*) malloc(MATRIX_SIZE*sizeof(double)); + if(X == NULL || X_old == NULL) + { + printf("X or X_old is NULL...\n"); + exit(-1); + } + + for(i=0; i 0.01f) + printf("Result is on position %d wrong (%f != 1.0)\n", i, X[i]); + } + printf("maximal error is %f\n", max); + + printf("\nmatrix size: %d x %d\n", MATRIX_SIZE, MATRIX_SIZE); + printf("number of iterations: %d\n", iterations); + printf("calculation time: %f s\n", (float) (end-start) / (float) CLOCKS_PER_SEC); + + free((void*) X_old); + free((void*) X); + + return 0; +} diff --git a/newlib/examples/test b/newlib/examples/test index 8c6e99a9..1454edfe 100644 --- a/newlib/examples/test +++ b/newlib/examples/test @@ -1 +1 @@ -HalloXA! \ No newline at end of file +HalloXA! diff --git a/newlib/src/libgloss/metalsvm/sbrk.c b/newlib/src/libgloss/metalsvm/sbrk.c index 356c5ee7..78002469 100644 --- a/newlib/src/libgloss/metalsvm/sbrk.c +++ b/newlib/src/libgloss/metalsvm/sbrk.c @@ -22,23 +22,20 @@ #include #undef errno extern int errno; +#include "warning.h" +#include "syscall.h" -#ifndef NULL -#define NULL ((void*) 0) -#endif +void* +_DEFUN (sbrk, (incr), + int incr) +{ + int ret; -void * -sbrk (incr) - int incr; -{ - extern char _end; // set by linker - static char *heap_end = NULL; - char *prev_heap_end; + ret = SYSCALL1(__NR_sbrk, incr); + if (ret < 0x1000) { + errno = -ret; + ret = -1; + } - if (!heap_end) - heap_end = &_end; - prev_heap_end = heap_end; - heap_end += incr; - - return (void *) prev_heap_end; + return (void*) ret; } diff --git a/newlib/src/libgloss/metalsvm/syscall.h b/newlib/src/libgloss/metalsvm/syscall.h index 5390a27b..6d137508 100644 --- a/newlib/src/libgloss/metalsvm/syscall.h +++ b/newlib/src/libgloss/metalsvm/syscall.h @@ -38,6 +38,7 @@ extern "C" { #define __NR_fork 12 #define __NR_wait 13 #define __NR_execve 14 +#define __NR_times 15 #define _STR(token) #token #define _SYSCALLSTR(x) "int $" _STR(x) " " diff --git a/newlib/src/libgloss/metalsvm/times.c b/newlib/src/libgloss/metalsvm/times.c index ed7baa16..5c4ebcd7 100644 --- a/newlib/src/libgloss/metalsvm/times.c +++ b/newlib/src/libgloss/metalsvm/times.c @@ -24,14 +24,20 @@ #include #undef errno extern int errno; -#include "warning.h" +#include "syscall.h" clock_t _DEFUN (_times, (buf), struct tms *buf) { - errno = ENOSYS; - return -1; -} + clock_t clock = 0; + int ret; -stub_warning(_times) + ret = SYSCALL2(__NR_times, buf, &clock); + if (ret < 0) { + errno = -ret; + return (clock_t) -1; + } + + return clock; +} diff --git a/tools/Makefile b/tools/Makefile index 2cf44f06..68348fcb 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -7,7 +7,7 @@ LDFLGAS = DEFINES= NASM = nasm NASMFLAGS = -fbin -EXECFILES = $(shell find ../newlib/examples -perm -u+r+x -type f) ../newlib/examples/test +EXECFILES = $(shell find ../newlib/examples -perm -u+r+x -type f) ../newlib/examples/test # other implicit rules %.o : %.c