Merge branch 'ohligs' into readwrite

Conflicts:
	drivers/char/null.c
	drivers/stderr/Makefile
	drivers/stderr/stderr.c
	drivers/stdin/Makefile
	drivers/stdin/stdin.c
	drivers/stdout/Makefile
	drivers/stdout/stdout.c
	fs/initrd.c
	include/metalsvm/fs_types.h
	include/metalsvm/tasks_types.h
	kernel/syscall.c
	kernel/tasks.c
	kernel/tests.c
	newlib/examples/hello.c
	newlib/examples/test
	tools/Makefile
This commit is contained in:
Marian Ohligs 2011-04-26 17:27:42 +02:00
commit 0ac95a30b3
40 changed files with 900 additions and 157 deletions

2
.gitignore vendored
View file

@ -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/*

View file

@ -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

View file

@ -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

View file

@ -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 <metalsvm/stddef.h>
#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

View file

@ -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

View file

@ -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())

View file

@ -22,6 +22,7 @@
#include <metalsvm/tasks.h>
#include <metalsvm/time.h>
#include <metalsvm/processor.h>
#include <metalsvm/errno.h>
#include <asm/irq.h>
#include <asm/irqflags.h>
#include <asm/gdt.h>
@ -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

View file

@ -33,6 +33,7 @@
#ifdef CONFIG_ROCKCREEK
#include <asm/RCCE_lib.h>
#include <asm/SCC_API.h>
#include <asm/icc.h>
#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; i<mb_info->mods_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

View file

@ -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

View file

@ -17,17 +17,22 @@
#include <metalsvm/processor.h>
#include <metalsvm/errno.h>
#include <asm/io.h>
#include <asm/irqflags.h>
#ifdef CONFIG_ROCKCREEK
#include <asm/RCCE.h>
#include <asm/iRCCE.h>
#include <asm/SCC_API.h>
#ifdef CONFIG_ROCKCREEK
#include <asm/icc.h>
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; i<num_ues; i++) {
if (i == my_ue)
continue;
if (!pending[i]) {
ret = iRCCE_irecv((char*) (header+i), sizeof(icc_header_t), i, request+i);
if (ret == iRCCE_SUCCESS)
interpret_header(header+i, i);
else
pending[i] = 1;
} else {
ret = iRCCE_irecv_test(request+i, NULL);
if (ret == iRCCE_SUCCESS) {
interpret_header(header+i, i);
pending[i] = 0;
}
}
}
}
#endif

View file

@ -327,7 +327,7 @@ err_t rtl8139if_init(struct netif* netif)
memset(rtl8139if, 0, sizeof(rtl1839if_t));
/* allocate the receive buffer */
rtl8139if->rx_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;

View file

@ -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 <metalsvm/stddef.h>
#include <metalsvm/mailbox.h>

View file

@ -1,5 +1,4 @@
C_source := stderr.c
MODULE := drivers_stderr
include $(TOPDIR)/Makefile.inc

View file

@ -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<size; i++, buffer++) {
kputchar(*buffer);
}
return size;
}

View file

@ -1,5 +1,4 @@
C_source := stdin.c
MODULE := drivers_stdin
include $(TOPDIR)/Makefile.inc

View file

@ -28,7 +28,9 @@
static ssize_t stdin_read(vfs_node_t* node, uint8_t* buffer, size_t size, off_t offset)
{
kprintf("Keine Eingabe implementiert");
while(size) {
size = kputs((char*)buffer);
}
return size;
}

View file

@ -1,5 +1,4 @@
C_source := stdout.c
MODULE := drivers_stdout
include $(TOPDIR)/Makefile.inc

View file

@ -33,7 +33,10 @@ static ssize_t stdout_read(vfs_node_t* node, uint8_t* buffer, size_t size, off_t
static ssize_t stdout_write(vfs_node_t* node, uint8_t* buffer, size_t size, off_t offset)
{
kprintf("%s", buffer);
int i;
for (i = 0; i<size; i++, buffer++) {
kputchar(*buffer);
}
return size;
}

View file

@ -25,6 +25,11 @@
#include <asm/multiboot.h>
#include <metalsvm/spinlock.h>
#include <asm/processor.h>
#include <metalsvm/spinlock.h>
#ifdef CONFIG_ROCKCREEK
#include <asm/icc.h>
#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; i<MAX_DATABLOCKS && !data; i++) {
if (blist->data[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

View file

@ -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 */

View file

@ -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

View file

@ -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__

View file

@ -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

View file

@ -49,6 +49,7 @@ extern "C" {
#define __NR_fork 12
#define __NR_wait 13
#define __NR_execve 14
#define __NR_times 15
#ifdef __cplusplus
}

View file

@ -32,6 +32,10 @@
#include <metalsvm/stddef.h>
#include <metalsvm/tasks_types.h>
#include <asm/tasks.h>
#include <asm/irqflags.h>
#ifdef CONFIG_ROCKCREEK
#include <asm/icc.h>
#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

View file

@ -34,6 +34,8 @@
#include <metalsvm/spinlock_types.h>
#include <metalsvm/fs_types.h>
#include <metalsvm/mailbox_types.h>
#include <asm/tasks_types.h>
#include <metalsvm/fs_types.h>
#include <asm/atomic.h>
#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

View file

@ -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
}

View file

@ -30,6 +30,9 @@
#include <asm/irq.h>
#include <asm/irqflags.h>
#include <asm/kb.h>
#ifdef CONFIG_ROCKCREEK
#include <asm/icc.h>
#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();

View file

@ -23,6 +23,8 @@
#include <metalsvm/tasks.h>
#include <metalsvm/string.h>
#include <metalsvm/errno.h>
#include <metalsvm/spinlock.h>
#include <metalsvm/time.h>
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;

View file

@ -38,6 +38,7 @@
#include <metalsvm/mailbox.h>
#include <metalsvm/syscall.h>
#include <metalsvm/fs.h>
#include <metalsvm/time.h>
#include <asm/apic.h>
#include <asm/elf.h>
@ -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;
i<MAX_TASKS; i++, new_id=(new_id+1) % MAX_TASKS)
{
@ -707,8 +737,8 @@ void scheduler(void)
if (per_core(current_task)->status == 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;
}
}

View file

@ -24,6 +24,9 @@
#include <metalsvm/semaphore.h>
#include <metalsvm/mailbox.h>
#include <metalsvm/syscall.h>
#ifdef CONFIG_ROCKCREEK
#include <asm/icc.h>
#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;
}

View file

@ -29,6 +29,9 @@
#ifdef CONFIG_MULTIBOOT
#include <asm/multiboot.h>
#endif
#ifdef CONFIG_ROCKCREEK
#include <asm/icc.h>
#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; i<mb_info->mods_count; i++, mmodule++) {
for(addr=mmodule->mod_start; addr<mmodule->mod_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<PRIVATE_MEM1_END; addr+=PAGE_SIZE) {
page_clear_mark(addr / PAGE_SIZE);
page_clear_mark(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<PRIVATE_MEM2_END; addr+=PAGE_SIZE) {
page_clear_mark(addr / PAGE_SIZE);
page_clear_mark(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<npages) && (i+j < BITMAP_SIZE) && (k < BITMAP_SIZE); j++, k++) {
if (page_marked(i+j)) {
i = (i+j) % BITMAP_SIZE;
i = (i+j) & (BITMAP_SIZE-1);
goto next_try;
}
}
@ -259,7 +262,7 @@ oom:
int put_page(size_t phyaddr)
{
uint32_t index = phyaddr / PAGE_SIZE;
uint32_t index = phyaddr >> 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);
}

View file

@ -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) $<

View file

@ -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);

196
newlib/examples/jacobi.c Normal file
View file

@ -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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <time.h>
#include <unistd.h>
#include <errno.h>
#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<N; iCnt++) { /* Assign pointers in the first "real index"; Value from 1 to N (0 yet set, value N means N+1) */
(*A)[iCnt] = &((*A)[0][iCnt*(N+1)]);
}
memset(**A, 0, (N+1)*N*sizeof(double)); /* Fill matrix values with 0 */
srand( 42 /*(unsigned) time(NULL)*/ ) ; /* init random number generator */
/*
* initialize the system of linear equations
* the result vector is one
*/
for (i = 0; i < N; i++)
{
double sum = 0.0;
for (j = 0; j < N; j++)
{
if (i != j)
{
double c = ((double)rand()) / ((double)RAND_MAX) * MAXVALUE;
sum += fabs(c);
(*A)[i][j] = c;
(*A)[i][N] += c;
}
}
/*
* The Jacobi method will always converge if the matrix A is strictly or irreducibly diagonally dominant.
* Strict row diagonal dominance means that for each row, the absolute value of the diagonal term is
* greater than the sum of absolute values of other terms: |A[i][i]| > 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<MATRIX_SIZE; i++)
{
X[i] = ((double)rand()) / ((double)RAND_MAX) * 10.0;
X_old[i] = 0.0;
}
printf("start calculation...\n");
iter_start = 0;
iter_end = MATRIX_SIZE;
start = clock();
while(1)
{
iterations++;
temp = X_old;
X_old = X;
X = temp;
for (i=iter_start; i<iter_end; i++)
{
for(j=0, xi=0.0; j<i; j++)
xi += A[i][j] * X_old[j];
for(j=i+1; j<MATRIX_SIZE; j++)
xi += A[i][j] * X_old[j];
X[i] = (A[i][MATRIX_SIZE] - xi) / A[i][i];
}
if (iterations % 5000 == 0 ) {/* calculate the Euclidean norm between X_old and X*/
norm = 0.0;
for (i=iter_start; i<iter_end; i++)
norm += (X_old[i] - X[i]) * (X_old[i] - X[i]);
/* check the break condition */
norm /= (double) MATRIX_SIZE;
if (norm < 0.0000001)
break;
}
}
end = clock();
if (MATRIX_SIZE < 16) {
printf("Print the solution...\n");
/* print solution */
for(i=0; i<MATRIX_SIZE; i++) {
for(j=0; j<MATRIX_SIZE; j++)
printf("%8.2f\t", A[i][j]);
printf("*\t%8.2f\t=\t%8.2f\n", X[i], A[i][MATRIX_SIZE]);
}
}
printf("Check the result...\n");
/*
* check the result
* X[i] have to be 1
*/
for(i=0; i<MATRIX_SIZE; i++) {
error = fabs(X[i] - 1.0f);
if (max < error)
max = error;
if (error > 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;
}

View file

@ -1 +1 @@
HalloXA!
HalloXA!

View file

@ -22,23 +22,20 @@
#include <errno.h>
#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;
}

View file

@ -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) " "

View file

@ -24,14 +24,20 @@
#include <errno.h>
#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;
}

View file

@ -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