From 2357d65a09d911cfa190cdc8fcd0340c502afce7 Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Tue, 24 May 2011 15:04:44 -0700 Subject: [PATCH 1/7] add baremetal version of coreid, readLUT and writeLUT --- arch/x86/scc/RCCE_admin.c | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/arch/x86/scc/RCCE_admin.c b/arch/x86/scc/RCCE_admin.c index 34f0e677..a9a624ae 100644 --- a/arch/x86/scc/RCCE_admin.c +++ b/arch/x86/scc/RCCE_admin.c @@ -337,7 +337,7 @@ int RCCE_init( RCCE_shmalloc_init(RC_SHM_BUFFER_START()+RCCE_SHM_BUFFER_offset ,RCCE_SHM_SIZE_MAX); #ifdef SHMDBG - printf("\n%d:%s:%d: RCCE_SHM_BUFFER_offset, RCCE_SHM_SIZE_MAX: % x %x\n", RCCE_IAM, + kprintf("\n%d:%s:%d: RCCE_SHM_BUFFER_offset, RCCE_SHM_SIZE_MAX: % x %x\n", RCCE_IAM, __FILE__,__LINE__,RCCE_SHM_BUFFER_offset ,RCCE_SHM_SIZE_MAX); #endif #else @@ -439,8 +439,10 @@ int RCCE_num_ues(void) {return(RCCE_NP);} //-------------------------------------------------------------------------------------- void writeLUT(unsigned int lutSlot, unsigned int value) { -int PAGE_SIZE, NCMDeviceFD; +#ifndef MS_BAREMETAL +int page_size, NCMDeviceFD; // NCMDeviceFD is the file descriptor for non-cacheable memory (e.g. config regs). +#endif unsigned int result; @@ -453,6 +455,7 @@ unsigned int myCoreID, alignedAddr, pageOffset, ConfigAddr; else ConfigAddr = CRB_OWN+LUT0 + (lutSlot*0x08); +#ifndef MS_BAREMETAL PAGE_SIZE = getpagesize(); if ((NCMDeviceFD=open("/dev/rckncm", O_RDWR|O_SYNC))<0) { @@ -471,16 +474,19 @@ unsigned int myCoreID, alignedAddr, pageOffset, ConfigAddr; *(int*)(MappedAddr+pageOffset) = value; munmap((void*)MappedAddr, PAGE_SIZE); - +#else + *(int*)(ConfigAddr) = value; +#endif } //-------------------------------------------------------------------------------------- // FUNCTION: readLUT //-------------------------------------------------------------------------------------- unsigned int readLUT(unsigned int lutSlot) { - +#ifndef MS_BAREMETAL int PAGE_SIZE, NCMDeviceFD; // NCMDeviceFD is the file descriptor for non-cacheable memory (e.g. config regs). +#endif unsigned int result; t_vcharp MappedAddr; @@ -492,6 +498,7 @@ unsigned int myCoreID, alignedAddr, pageOffset, ConfigAddr; else ConfigAddr = CRB_OWN+LUT0 + (lutSlot*0x08); +#ifndef MS_BAREMETAL PAGE_SIZE = getpagesize(); if ((NCMDeviceFD=open("/dev/rckncm", O_RDWR|O_SYNC))<0) { @@ -510,6 +517,9 @@ unsigned int myCoreID, alignedAddr, pageOffset, ConfigAddr; result = *(unsigned int*)(MappedAddr+pageOffset); munmap((void*)MappedAddr, PAGE_SIZE); +#else + result = *(unsigned int*)(ConfigAddr); +#endif return result; } @@ -519,14 +529,16 @@ unsigned int myCoreID, alignedAddr, pageOffset, ConfigAddr; //-------------------------------------------------------------------------------------- unsigned int getCOREID() { +#ifndef MS_BAREMETAL int PAGE_SIZE, NCMDeviceFD; // NCMDeviceFD is the file descriptor for non-cacheable memory (e.g. config regs). - +#endif t_vcharp MappedAddr; unsigned int coreID,result, alignedAddr, pageOffset, ConfigAddr, coreID_mask=0x00000007; ConfigAddr = CRB_OWN+MYTILEID; +#ifndef MS_BAREMETAL PAGE_SIZE = getpagesize(); if ((NCMDeviceFD=open("/dev/rckncm", O_RDWR|O_SYNC))<0) { @@ -545,6 +557,9 @@ unsigned int coreID,result, alignedAddr, pageOffset, ConfigAddr, coreID_mask=0x result = *(unsigned int*)(MappedAddr+pageOffset); munmap((void*)MappedAddr, PAGE_SIZE); +#else + result = *(unsigned int*)(ConfigAddr); +#endif coreID = result & coreID_mask; return coreID; From f51b24a45f0aeced7a2c11113eb8e02a90a32bc8 Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Tue, 24 May 2011 15:05:29 -0700 Subject: [PATCH 2/7] using of kprintf instead of printf --- arch/x86/scc/RCCE_shmalloc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/scc/RCCE_shmalloc.c b/arch/x86/scc/RCCE_shmalloc.c index 915eef1d..c0e13309 100644 --- a/arch/x86/scc/RCCE_shmalloc.c +++ b/arch/x86/scc/RCCE_shmalloc.c @@ -56,7 +56,7 @@ void RCCE_shmalloc_init( /* make a circular list by connecting tail to itself */ RCCE_spacep->tail->next = RCCE_spacep->tail; #ifdef SHMDBG -printf("%s: %d: RCCE_spacep->tail->free_size, RCCE_spacep->tail->space: %x %x\n", +kprintf("%s: %d: RCCE_spacep->tail->free_size, RCCE_spacep->tail->space: %x %x\n", __FILE__, __LINE__,RCCE_spacep->tail->free_size, RCCE_spacep->tail->space); #endif } From 394befa3a8d9fcf8f8507d0f94aa08ff440ab669 Mon Sep 17 00:00:00 2001 From: Jacek Galowicz Date: Sat, 21 May 2011 11:51:22 +0200 Subject: [PATCH 3/7] Color management for procedures using vga_putchar As seen in some BSD operating systems, you can now push and pop foreground and background colors onto a stack to change the colors you see on the screen whenever kprintf/kputchar is used. This could become useful if one wants to see kernel space kprintfs in other colors than user space printfs or error messages in red and other debugging purposes. Beware: This is just a small and dirty hack which protects the colorstack with locks and so on. But on task switching the color will not be switched. That makes different colors for different colors persistent for all the time difficult/impossible. But I considered adding colors to the task structures a bit overdone for a small debugging-help. [Sorry for those commit-and-pull-back-mails. Forgot that I had this stuff on the master branch while pushing my own branch onto the server.] --- arch/x86/kernel/vga.c | 8 ++--- include/metalsvm/stdio.h | 39 +++++++++++++++++++++++++ kernel/main.c | 5 +++- libkern/printf.c | 63 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 110 insertions(+), 5 deletions(-) diff --git a/arch/x86/kernel/vga.c b/arch/x86/kernel/vga.c index 18cd183a..3b66f271 100644 --- a/arch/x86/kernel/vga.c +++ b/arch/x86/kernel/vga.c @@ -209,15 +209,15 @@ int vga_puts(const char *text) } /* Sets the forecolor and backcolor we will use */ -//void settextcolor(unsigned char forecolor, unsigned char backcolor) -//{ +void settextcolor(unsigned char forecolor, unsigned char backcolor) +{ /* * Top 4 bytes are the background, bottom 4 bytes * are the foreground color */ -// attrib = (backcolor << 4) | (forecolor & 0x0F); -//} + attrib = ((backcolor & 0x0F) << 4) | (forecolor & 0x0F); +} /* Sets our text-mode VGA pointer, then clears the screen for us */ void vga_init(void) diff --git a/include/metalsvm/stdio.h b/include/metalsvm/stdio.h index 6f9fc20e..cd5d2a61 100644 --- a/include/metalsvm/stdio.h +++ b/include/metalsvm/stdio.h @@ -74,6 +74,45 @@ int koutput_init(void); */ int kvprintf(char const *fmt, void (*func) (int, void *), void *arg, int radix, va_list ap); +/** @brief Set a new foreground color for kprintf and kputchar. + * + * The color change will affect any procedure using vga_putchar()/vga_puts(). + * This procedure pushes the color onto a colorstack making you + * able to revert this change just with a popfg(). + * */ +void pushfg(unsigned char fgcol); + +/** @brief Set a new background color for kprintf and kputchar. + * + * The color change will affect any procedure using vga_putchar()/vga_puts(). + * This procedure pushes the color onto a colorstack making you + * able to revert this change just with a popbg(). + * */ +void pushbg(unsigned char bgcol); + +#define COL_BLACK 0 +#define COL_BLUE 1 +#define COL_GREEN 2 +#define COL_CYAN 3 +#define COL_RED 4 +#define COL_MAGENTA 5 +#define COL_BROWN 6 +#define COL_LGRAY 7 +#define COL_DGRAY 8 +#define COL_LBLUE 9 +#define COL_LGREEN 10 +#define COL_LCYAN 11 +#define COL_LRED 12 +#define COL_LMAGENTA 13 +#define COL_LYELLOW 14 +#define COL_WHITE 15 + +/** @brief Revert the last foreground color change introduced by pushfg() */ +void popfg(); + +/** @brief Revert the last background color change introduced by pushfg() */ +void popbg(); + #ifdef __cplusplus } #endif diff --git a/kernel/main.c b/kernel/main.c index 2d9caca9..daf7f3af 100644 --- a/kernel/main.c +++ b/kernel/main.c @@ -82,7 +82,10 @@ int main(void) { lowlevel_init(); - kprintf("This is MetalSVM %s Build %u, %u\n", METALSVM_VERSION, &__BUILD_DATE, &__BUILD_TIME); + pushbg(COL_BLUE); + kprintf("This is MetalSVM %s Build %u, %u\n", + METALSVM_VERSION, &__BUILD_DATE, &__BUILD_TIME); + popbg(); system_init(); irq_init(); diff --git a/libkern/printf.c b/libkern/printf.c index 780184bb..416d2893 100644 --- a/libkern/printf.c +++ b/libkern/printf.c @@ -45,6 +45,7 @@ */ #include +#include #define __64BIT__ @@ -74,6 +75,14 @@ char const hex2ascii_data[] = "0123456789abcdefghijklmnopqrstuvwxyz"; /* Max number conversion buffer length: a u_quad_t in base 2, plus NUL byte. */ #define MAXNBUF (sizeof(intmax_t) * NBBY + 1) +#define COLOR_STACK_SIZE 10 +static int fgstack[COLOR_STACK_SIZE] = {0xf}; +static int bgstack[COLOR_STACK_SIZE] = {0x0}; +static unsigned int fgstack_pos = 0; +static unsigned int bgstack_pos = 0; +static spinlock_t fglock = SPINLOCK_INIT; +static spinlock_t bglock = SPINLOCK_INIT; + /* * Put a NUL-terminated ASCII number (base <= 36) in a buffer in reverse * order; return an optional length and a pointer to the last character @@ -483,3 +492,57 @@ int kprintf(const char *fmt, ...) return ret; } + +extern void settextcolor(unsigned char forecolor, unsigned char backcolor); + +void pushfg(unsigned char fgcol) +{ + spinlock_lock(&fglock); + /* Ignore this request if the stack is full */ + if (fgstack_pos == COLOR_STACK_SIZE) goto rel_pushfglock; + + ++fgstack_pos; + fgstack[fgstack_pos] = fgcol; + + settextcolor(fgstack[fgstack_pos], bgstack[bgstack_pos]); +rel_pushfglock: + spinlock_unlock(&fglock); +} + +void pushbg(unsigned char bgcol) +{ + spinlock_lock(&bglock); + /* Ignore this request if the stack is full */ + if (bgstack_pos == COLOR_STACK_SIZE) goto rel_pushbglock; + + ++bgstack_pos; + bgstack[bgstack_pos] = bgcol; + + settextcolor(fgstack[fgstack_pos], bgstack[bgstack_pos]); +rel_pushbglock: + spinlock_unlock(&bglock); +} + +void popfg() +{ + spinlock_lock(&fglock); + /* Ignore if we're already at the stack's bottom */ + if (!fgstack_pos) goto rel_popfglock; + + --fgstack_pos; + settextcolor(fgstack[fgstack_pos], bgstack[bgstack_pos]); +rel_popfglock: + spinlock_unlock(&fglock); +} + +void popbg() +{ + spinlock_lock(&bglock); + /* Ignore if we're already at the stack's bottom */ + if (!bgstack_pos) goto rel_popbglock; + + --bgstack_pos; + settextcolor(fgstack[fgstack_pos], bgstack[bgstack_pos]); +rel_popbglock: + spinlock_unlock(&bglock); +} From 5d702411ab72ea3e7b11919767f5dd807e7e3cab Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Wed, 25 May 2011 15:28:20 -0700 Subject: [PATCH 4/7] enable in RCCE the shared memory support --- include/metalsvm/config.h.example | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/metalsvm/config.h.example b/include/metalsvm/config.h.example index bb405699..f5b35948 100644 --- a/include/metalsvm/config.h.example +++ b/include/metalsvm/config.h.example @@ -60,7 +60,8 @@ extern "C" { #define SCC #define MS_BAREMETAL //#define GORY -//#define SHMADD +#define SHMADD +#define SHMDBG //#define SHMADD_CACHEABLE /* default values for 16 GB system */ #define PRIVATE_MEM1_START 0x00000000 From b5066036ab659233e0542dec8a66f3a1ac84f780 Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Wed, 25 May 2011 15:42:10 -0700 Subject: [PATCH 5/7] only if the macro CONFIG_VGA is set, the function settextcolor will be used --- libkern/printf.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/libkern/printf.c b/libkern/printf.c index 416d2893..defa303f 100644 --- a/libkern/printf.c +++ b/libkern/printf.c @@ -493,7 +493,9 @@ int kprintf(const char *fmt, ...) return ret; } +#ifdef CONFIG_VGA extern void settextcolor(unsigned char forecolor, unsigned char backcolor); +#endif void pushfg(unsigned char fgcol) { @@ -504,7 +506,9 @@ void pushfg(unsigned char fgcol) ++fgstack_pos; fgstack[fgstack_pos] = fgcol; +#ifdef CONFIG_VGA settextcolor(fgstack[fgstack_pos], bgstack[bgstack_pos]); +#endif rel_pushfglock: spinlock_unlock(&fglock); } @@ -518,31 +522,37 @@ void pushbg(unsigned char bgcol) ++bgstack_pos; bgstack[bgstack_pos] = bgcol; +#ifdef CONFIG_VGA settextcolor(fgstack[fgstack_pos], bgstack[bgstack_pos]); +#endif rel_pushbglock: spinlock_unlock(&bglock); } -void popfg() +void popfg(void) { spinlock_lock(&fglock); /* Ignore if we're already at the stack's bottom */ if (!fgstack_pos) goto rel_popfglock; --fgstack_pos; +#ifdef CONFIG_VGA settextcolor(fgstack[fgstack_pos], bgstack[bgstack_pos]); +#endif rel_popfglock: spinlock_unlock(&fglock); } -void popbg() +void popbg(void) { spinlock_lock(&bglock); /* Ignore if we're already at the stack's bottom */ if (!bgstack_pos) goto rel_popbglock; --bgstack_pos; +#ifdef CONFIG_VGA settextcolor(fgstack[fgstack_pos], bgstack[bgstack_pos]); +#endif rel_popbglock: spinlock_unlock(&bglock); } From cdd16a2b9ffd9640c38da58846678927d81b2d11 Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Sat, 28 May 2011 23:35:46 +0200 Subject: [PATCH 6/7] add the SSE support => context switch stores also the SSE registers --- arch/x86/include/asm/processor.h | 41 ++++++++++++++++++++++++++++++ arch/x86/include/asm/tasks_types.h | 6 ++++- arch/x86/kernel/isrs.c | 35 ++++++++++++++++++++----- arch/x86/kernel/processor.c | 23 +++++++++++++++++ kernel/tests.c | 1 + 5 files changed, 99 insertions(+), 7 deletions(-) diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h index a1f6246a..cbab6148 100644 --- a/arch/x86/include/asm/processor.h +++ b/arch/x86/include/asm/processor.h @@ -39,6 +39,45 @@ extern "C" { #endif +// feature list 1 +#define CPU_FEATURE_FPU (1 << 0) +#define CPU_FEATURE_MMX (1 << 23) +#define CPU_FEATURE_FXSR (1 << 24) +#define CPU_FEATURE_SSE (1 << 25) +#define CPU_FEATURE_SSE2 (1 << 26) + +// feature list 2 +#define CPU_FEATURE_AVX (1 << 28) + +typedef struct { + uint32_t feature1, feature2; +} cpu_info_t; + +extern cpu_info_t cpu_info; + +// determine the cpu features +int cpu_detection(void); + +inline static uint32_t has_fpu(void) +{ + return (cpu_info.feature1 & CPU_FEATURE_FPU); +} + +inline static uint32_t has_fxsr(void) +{ + return (cpu_info.feature1 & CPU_FEATURE_FXSR); +} + +inline static uint32_t has_xmm(void) +{ + return (cpu_info.feature1 & CPU_FEATURE_SSE); +} + +inline static uint32_t has_avx(void) +{ + return (cpu_info.feature2 & CPU_FEATURE_AVX); +} + /** @brief Read out time stamp counter * * The rdtsc asm command puts a 64 bit time stamp value @@ -250,6 +289,8 @@ inline static int system_init(void) #ifdef CONFIG_PCI pci_init(); #endif + cpu_detection(); + return 0; } diff --git a/arch/x86/include/asm/tasks_types.h b/arch/x86/include/asm/tasks_types.h index 138fbd1c..ffaee4fd 100644 --- a/arch/x86/include/asm/tasks_types.h +++ b/arch/x86/include/asm/tasks_types.h @@ -22,6 +22,7 @@ #define __ARCH_TASKS_TYPES__ #include +#include #ifdef __cplusplus extern "C" { @@ -61,7 +62,10 @@ union fpu_state { }; static inline void save_fpu_state(union fpu_state* state) { - asm volatile ("fsave %0; fwait" : "=m"((*state).fsave)); + if (has_fxsr()) + asm volatile ("fxsave %0; fnclex" : "=m"((*state).fxsave)); + else + asm volatile ("fsave %0; fwait" : "=m"((*state).fsave)); } #ifdef __cplusplus diff --git a/arch/x86/kernel/isrs.c b/arch/x86/kernel/isrs.c index cfb45389..4c461894 100644 --- a/arch/x86/kernel/isrs.c +++ b/arch/x86/kernel/isrs.c @@ -165,6 +165,26 @@ void isrs_install(void) irq_install_handler(7, fpu_handler); } +static void fpu_init(union fpu_state* fpu) +{ + if (has_fxsr()) { + i387_fxsave_t* fx = &fpu->fxsave; + + memset(fx, 0, sizeof(union fpu_state)); + fx->cwd = 0x37f; + if (has_xmm) + fx->mxcsr = 0x1f80; + } else { + i387_fsave_t *fp = &fpu->fsave; + memset(fp, 0, sizeof(union fpu_state)); + fp->cwd = 0xffff037fu; + fp->swd = 0xffff0000u; + fp->twd = 0xffffffffu; + fp->fos = 0xffff0000u; + } + +} + static void fpu_handler(struct state *s) { task_t* task = per_core(current_task); @@ -172,13 +192,16 @@ static void fpu_handler(struct state *s) 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; + fpu_init(&task->fpu); + task->flags |= TASK_FPU_INIT; } + + // restore the FPU context + if (has_fxsr()) + asm volatile ("fxrstor %0" :: "m"(task->fpu.fxsave)); + else + asm volatile ("frstor %0" :: "m"(task->fpu.fsave)); + task->flags |= TASK_FPU_USED; } /** @brief Exception messages diff --git a/arch/x86/kernel/processor.c b/arch/x86/kernel/processor.c index aa4988f4..4210c38f 100644 --- a/arch/x86/kernel/processor.c +++ b/arch/x86/kernel/processor.c @@ -25,8 +25,31 @@ #include #endif +cpu_info_t cpu_info = { 0, 0 }; static uint32_t cpu_freq = 0; +int cpu_detection(void) +{ + uint32_t a, b, cr4; + + cpuid(1, &a, &b, &cpu_info.feature2, &cpu_info.feature1); + + cr4 = read_cr4(); + if (has_fxsr()) + cr4 |= 0x200; // set the OSFXSR bit + if (has_xmm()) + cr4 |= 0x400; // set the OSXMMEXCPT bit + write_cr4(cr4); + + if (has_avx()) + kprintf("The CPU owns the Advanced Vector Extensions (AVX). However, MetalSVM doesn't support AVX!\n"); + + if (has_fpu()) + asm volatile ("fninit"); + + return 0; +} + uint32_t detect_cpu_frequency(void) { #ifdef CONFIG_ROCKCREEK diff --git a/kernel/tests.c b/kernel/tests.c index 5c26d41d..e8d8a828 100644 --- a/kernel/tests.c +++ b/kernel/tests.c @@ -133,6 +133,7 @@ int test_init(void) //create_user_task(NULL, "/bin/hello", argv); create_user_task(NULL, "/bin/tests", argv); //create_user_task(NULL, "/bin/jacobi", argv); + //create_user_task(NULL, "/bin/jacobi", argv); return 0; } From 3ff984a21c76ec277d5b4f475e8a07299a7b32f2 Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Sat, 28 May 2011 23:37:15 +0200 Subject: [PATCH 7/7] add the example jacobi to the git ignore list --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 391bf0f5..2cd48104 100644 --- a/.gitignore +++ b/.gitignore @@ -15,6 +15,7 @@ tools/make_initrd newlib/examples/hello newlib/examples/echo newlib/examples/tests +newlib/examples/jacobi newlib/tmp/* newlib/x86/* metalsvm.elf