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/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/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; 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 } 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 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/kernel/tests.c b/kernel/tests.c index 333885b6..062a4261 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/mshell", argv); //create_user_task(NULL, "/bin/jacobi", argv); + //create_user_task(NULL, "/bin/jacobi", argv); return 0; } diff --git a/libkern/printf.c b/libkern/printf.c index 780184bb..defa303f 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,67 @@ 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) +{ + 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; + +#ifdef CONFIG_VGA + settextcolor(fgstack[fgstack_pos], bgstack[bgstack_pos]); +#endif +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; + +#ifdef CONFIG_VGA + settextcolor(fgstack[fgstack_pos], bgstack[bgstack_pos]); +#endif +rel_pushbglock: + spinlock_unlock(&bglock); +} + +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) +{ + 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); +}