From ffe0c1d806410af2e897428d6125a9f402f45b9c Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Mon, 4 Apr 2011 08:51:15 +0200 Subject: [PATCH 01/28] add standard C function strtoul --- include/metalsvm/stdlib.h | 1 + libkern/Makefile | 2 +- libkern/strtoul.c | 112 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 114 insertions(+), 1 deletion(-) create mode 100644 libkern/strtoul.c diff --git a/include/metalsvm/stdlib.h b/include/metalsvm/stdlib.h index 883818b6..6a74fac6 100644 --- a/include/metalsvm/stdlib.h +++ b/include/metalsvm/stdlib.h @@ -43,6 +43,7 @@ void* mem_allocation(size_t sz, uint32_t flags); void kfree(void*, size_t); long strtol(const char* str, char** endptr, int base); +unsigned long strtoul(const char* nptr, char** endptr, int base); static inline int atoi(const char *str) { diff --git a/libkern/Makefile b/libkern/Makefile index 6ed0f196..e21e0c9b 100644 --- a/libkern/Makefile +++ b/libkern/Makefile @@ -1,4 +1,4 @@ -C_source := string.c stdio.c printf.c sprintf.c ucmpdi2.c lshrdi3.c qdivrem.c udivdi3.c divdi3.c moddi3.c umoddi3.c strtol.c +C_source := string.c stdio.c printf.c sprintf.c ucmpdi2.c lshrdi3.c qdivrem.c udivdi3.c divdi3.c moddi3.c umoddi3.c strtol.c strtoul.c MODULE := libkern include $(TOPDIR)/Makefile.inc diff --git a/libkern/strtoul.c b/libkern/strtoul.c new file mode 100644 index 00000000..d54ce48e --- /dev/null +++ b/libkern/strtoul.c @@ -0,0 +1,112 @@ +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * From: @(#)strtoul.c 8.1 (Berkeley) 6/4/93 + */ + +/* + * The code has been taken from FreeBSD (sys/libkern/strtoul.c) and is therefore + * BSD-licensed. Unnecessary functions have been removed and all typedefs required + * have been added. + */ + +/* MetalSVM prelude */ +#include +#include +#include + +/* + * Convert a string to an unsigned long integer. + * + * Ignores `locale' stuff. Assumes that the upper and lower case + * alphabets and digits are each contiguous. + */ +unsigned long +strtoul(nptr, endptr, base) + const char *nptr; + char **endptr; + int base; +{ + const char *s = nptr; + unsigned long acc; + unsigned char c; + unsigned long cutoff; + int neg = 0, any, cutlim; + + /* + * See strtol for comments as to the logic used. + */ + do { + c = *s++; + } while (isspace(c)); + if (c == '-') { + neg = 1; + c = *s++; + } else if (c == '+') + c = *s++; + if ((base == 0 || base == 16) && + c == '0' && (*s == 'x' || *s == 'X')) { + c = s[1]; + s += 2; + base = 16; + } + if (base == 0) + base = c == '0' ? 8 : 10; + cutoff = (unsigned long)ULONG_MAX / (unsigned long)base; + cutlim = (unsigned long)ULONG_MAX % (unsigned long)base; + for (acc = 0, any = 0;; c = *s++) { + if (!isascii(c)) + break; + if (isdigit(c)) + c -= '0'; + else if (isalpha(c)) + c -= isupper(c) ? 'A' - 10 : 'a' - 10; + else + break; + if (c >= base) + break; + if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) + any = -1; + else { + any = 1; + acc *= base; + acc += c; + } + } + if (any < 0) { + acc = ULONG_MAX; + } else if (neg) + acc = -acc; + if (endptr != 0) + *((const char **)endptr) = any ? s - 1 : nptr; + return (acc); +} + From 8a707cf2bde2da1489a6407ac7d37781680f6754 Mon Sep 17 00:00:00 2001 From: Jacek Galowicz Date: Mon, 4 Apr 2011 17:12:04 +0200 Subject: [PATCH 02/28] The procedure name "network_shotdown()" did indeed sound a bit too violent, so i renamed it to "network_shutdown()", just like the header file says. --- kernel/init.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/init.c b/kernel/init.c index 2fafb5b9..307d17f4 100644 --- a/kernel/init.c +++ b/kernel/init.c @@ -107,7 +107,7 @@ int STDCALL network_task(void* arg) } #endif -int network_shotdown(void) +int network_shutdown(void) { done = 1; From 31d14370c44c2cec77f91df01b74d2a43edccd8a Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Tue, 5 Apr 2011 01:50:57 -0700 Subject: [PATCH 03/28] redesign of the SCC bootloader --- tools/scc_setup.asm | 42 ------------------------------------------ 1 file changed, 42 deletions(-) diff --git a/tools/scc_setup.asm b/tools/scc_setup.asm index 2dd77af4..aacf105e 100644 --- a/tools/scc_setup.asm +++ b/tools/scc_setup.asm @@ -28,53 +28,11 @@ _start: msg db "?ello from MetalSVM bootloader!!",0 -enable_A20: - call a20wait - mov al,0xAD - out 0x64,al - - call a20wait - mov al,0xD0 - out 0x64,al - - call a20wait2 - in al,0x60 - push eax - - call a20wait - mov al,0xD1 - out 0x64,al - - call a20wait - pop eax - or al,2 - out 0x60,al - - call a20wait - mov al,0xAE - out 0x64,al - - call a20wait - ret - -a20wait: - in al,0x64 - test al,2 - jnz a20wait - ret - -a20wait2: - in al,0x64 - test al,1 - jz a20wait2 - ret - _realstart: ; IRQs are already disabled by reset_vector ; cli lgdt [gdtr] - ; call enable_A20 ; switch to protected mode by setting PE bit mov eax, cr0 From 9918db81ec41a359db255e4511c46cb8cd06454b Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Tue, 5 Apr 2011 01:55:02 -0700 Subject: [PATCH 04/28] fix bugs in initialization of RCCE at first, we have to enable paging and to disable caching for the configuration registers --- arch/x86/include/asm/processor.h | 19 ------- arch/x86/mm/page.c | 14 ++++++ arch/x86/scc/RCCE_admin.c | 4 +- arch/x86/scc/scc_init.c | 85 +++++++------------------------- 4 files changed, 34 insertions(+), 88 deletions(-) diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h index a8e1daaf..27294236 100644 --- a/arch/x86/include/asm/processor.h +++ b/arch/x86/include/asm/processor.h @@ -32,22 +32,6 @@ extern "C" { #endif #ifdef CONFIG_ROCKCREEK -/*#define SCC_PMEM_REGIONS 2 - -typedef struct { - uint32_t low; - uint32_t high; -} mem_region_t; - -typedef struct { - uint32_t pid; - uint32_t tile_frequency; // in MHz - uint32_t router_frequency; // in MHz - mem_region_t private_mem[SCC_PMEM_REGIONS]; -} scc_info_t; - -extern scc_info_t scc_info;*/ - int scc_init(void); #endif @@ -158,9 +142,6 @@ uint32_t read_eip(void); inline static int system_init(void) { -#ifdef CONFIG_ROCKCREEK - scc_init(); -#endif gdt_install(); apic_init(); #ifdef CONFIG_PCI diff --git a/arch/x86/mm/page.c b/arch/x86/mm/page.c index 6711bc47..114f2a66 100644 --- a/arch/x86/mm/page.c +++ b/arch/x86/mm/page.c @@ -30,6 +30,10 @@ #include #include #include +#ifdef CONFIG_ROCKCREEK +#include +#include +#endif /* * Virtual Memory Layout of the standard configuration @@ -675,6 +679,16 @@ int arch_paging_init(void) } #endif +#ifdef CONFIG_ROCKCREEK + // 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); + kprintf("Map configuration registers at 0x%x\n", viraddr); + + // map SCC's configuration registers + viraddr = map_region(MPB_X0_Y0, MPB_X0_Y0, (MPB_OWN-MPB_X0_Y0+16*1024*1024)/PAGE_SIZE, MAP_KERNEL_SPACE); + kprintf("Map message passing buffers at 0x%x\n", viraddr); +#endif + /* enable paging */ write_cr3((uint32_t) &boot_pgd); i = read_cr0(); diff --git a/arch/x86/scc/RCCE_admin.c b/arch/x86/scc/RCCE_admin.c index 4316b216..8b4cbccc 100644 --- a/arch/x86/scc/RCCE_admin.c +++ b/arch/x86/scc/RCCE_admin.c @@ -51,7 +51,7 @@ // GLOBAL VARIABLES USED BY THE LIBRARY //...................................................................................... int RCCE_NP; // number of participating cores -int RC_REFCLOCKMHZ=533; // baseline CPU frequency (MHz) +int RC_REFCLOCKMHZ; // baseline CPU frequency (MHz) int RC_MY_COREID; // physical ID of calling core int RC_COREID[RCCE_MAXNP]; // array of physical core IDs for all participating // cores, sorted by rank @@ -232,7 +232,7 @@ int RCCE_init( unsigned int RCCE_SHM_BUFFER_offset ,result, rd_slot_nbr, wr_slot_nbr; #endif void *nothing = NULL; - + #ifdef SCC // Copperridge specific initialization... InitAPI(0); //fflush(0) diff --git a/arch/x86/scc/scc_init.c b/arch/x86/scc/scc_init.c index b3ef5cbd..0e3a2197 100644 --- a/arch/x86/scc/scc_init.c +++ b/arch/x86/scc/scc_init.c @@ -27,22 +27,23 @@ #ifdef CONFIG_ROCKCREEK -#define CCR_INTR_ACTIVE 0x02 - -//scc_info_t scc_info; -static char* rcce_argv[] = {"MetalSVM", "1", "533", "0"}; +/* + * Workaround to create a suitable argv array + */ +static char* argv_strings[] = {"MetalSVM", "1", "533", "0"}; +static char* argv[4] = {[0 ... 3] = NULL}; +static char** rcce_argv = argv; static int rcce_argc = 4; /* - * This is a modified MPB program, which is part of the RCCE distribution (src/mpb.c). + * This is the modified MPB program, which is part of the RCCE distribution (src/mpb.c). + * + * This function clears the local MPB and resets the test&set register. */ -static int scc_reset(void) +static int scc_clear(void) { int tmp, x, y, z, offset; - - // Initialize API - InitAPI(0); - + // Find out who I am... tmp=ReadConfigReg(CRB_OWN+MYTILEID); x=(tmp>>3) & 0x0f; // bits 06:03 @@ -69,14 +70,12 @@ static int scc_reset(void) int scc_init(void) { -// uint32_t x, y, z; -// uint32_t tmp; int num_ranks; - int my_rank; - - return 0; + int i, my_rank; kprintf("Initialize Rock Creek!\n"); + for(i=0; i>3) & 0x0f; // bits 06:03 - y=(tmp>>7) & 0x0f; // bits 10:07 - z=(tmp ) & 0x07; // bits 02:00 - scc_info.pid = PID(x, y, z); - kprintf("SCC Processor Id: %u (%u,%u,%u)\n", scc_info.pid, x, y, z); -*/ - /* default values for 16 GB system */ - /*scc_info.private_mem[0].low = 0x00; - scc_info.private_mem[0].high = 0x13FFFFFF; - scc_info.private_mem[1].low = 0xFF000000; - scc_info.private_mem[1].high = 0xFFFFFFFF; -*/ -// tmp = *((uint32_t*) (CRB_OWN+GCBCFG)); -// tmp = (tmp & 0x3FFFFFF) >> 7; - //kprintf("Own GCBCFG is 0x%x\n", tmp); -/* if (tmp == 0x70E1) { - scc_info.tile_frequency = 800; - scc_info.router_frequency = 1600; - } else { - scc_info.tile_frequency = 533; - scc_info.router_frequency = 800; - } -*/ - -/* kprintf("The default tile frequency is %u MHz\nThe default router frequency is %u MHz\n", - scc_info.tile_frequency, scc_info.router_frequency); - - if (z == 0) - tmp = *((uint32_t*) (CRB_OWN+GLCFG0)); - else if (z == 1) - tmp = *((uint32_t*) (CRB_OWN+GLCFG1)); - else - tmp = 0; -*/ - /* set INTR to enable maskable interrupts */ -/* tmp = tmp | CCR_INTR_ACTIVE; - if (z == 0) - *((uint32_t*) (CRB_OWN+GLCFG0)) = tmp; - else if (z == 1) - *((uint32_t*) (CRB_OWN+GLCFG1)) = tmp; -*/ - /* reload core configuration */ -/* tmp = 0; - if (z == 0) - tmp = *((uint32_t*) (CRB_OWN+GLCFG0)); - else if (z == 1) - tmp = *((uint32_t*) (CRB_OWN+GLCFG1)); - kprintf("Core Configuration %u: 0x%x\n", z, tmp); -*/ + //RCCE_barrier(&RCCE_COMM_WORLD); kputs("Now, the SCC is initialized!\n"); From e8abd6f33631485c1522a6a6e7615d687feb84c9 Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Tue, 5 Apr 2011 02:00:02 -0700 Subject: [PATCH 05/28] minor improvements and cosmetic changes to increase the readability --- arch/x86/include/asm/apic.h | 1 + arch/x86/kernel/apic.c | 54 ++++++++++++++++++++++++++++++------- 2 files changed, 45 insertions(+), 10 deletions(-) diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h index 8ea0d1e6..d5f21089 100644 --- a/arch/x86/include/asm/apic.h +++ b/arch/x86/include/asm/apic.h @@ -36,6 +36,7 @@ extern "C" { #define APIC_ICR1 0x0300 // Interrupt Command Register [0-31] #define APIC_ICR2 0x0310 // Interrupt Command Register [32-63] #define APIC_LVT_T 0x0320 // LVT Timer Register +#define APIC_LVT_TSR 0x0330 // LVT Thermal Sensor Register #define APIC_LVT_PMC 0x0340 // LVT Performance Monitoring Counters Register #define APIC_LINT0 0x0350 // LVT LINT0 Register #define APIC_LINT1 0x0360 // LVT LINT1 Register diff --git a/arch/x86/kernel/apic.c b/arch/x86/kernel/apic.c index e134483b..206619ef 100644 --- a/arch/x86/kernel/apic.c +++ b/arch/x86/kernel/apic.c @@ -76,6 +76,7 @@ static inline void lapic_write(uint32_t addr, uint32_t value) * to avoid a pentium bug, we have to read a apic register * before we write a value to this register */ + //asm volatile ("cmpl (%0), %%eax; movl %1, (%0)" :: "r"(lapic+addr), "r"(value)); asm volatile ("movl (%%eax), %%edx; movl %%ebx, (%%eax)" :: "a"(lapic+addr), "b"(value) : "%edx"); //*((volatile uint32_t*) (lapic+addr)) = value; } @@ -109,6 +110,26 @@ uint32_t apic_cpu_id(void) return 0; } +static inline uint32_t apic_version(void) +{ + if (lapic) { + uint32_t i = *((uint32_t*) (lapic+APIC_VERSION)); + return i & 0xFF; + } + + return 0; +} + +static inline uint32_t apic_lvt_entries(void) +{ + if (lapic) { + uint32_t i = *((uint32_t*) (lapic+APIC_VERSION)); + return (i >> 16) & 0xFF; + } + + return 0; +} + int has_apic(void) { return (lapic != 0); @@ -276,10 +297,11 @@ int apic_calibration(void) ; diff = 0xFFFFFFFF - lapic_read(APIC_CCR); + diff = diff / 3; lapic_write(APIC_DCR, 0xB); // set it to 1 clock increments lapic_write(APIC_LVT_T, 0x2007B); // connects the timer to 123 and enables it - lapic_write(APIC_ICR, diff / 3); + lapic_write(APIC_ICR, diff); // Now, MetalSVM is able to use the APIC => Therefore, we disable the PIC outportb(0xA1, 0xFF); @@ -316,13 +338,14 @@ int apic_calibration(void) } while(ticks*TIMER_FREQ < 3*RC_REFCLOCKMHZ*1000000); diff = 0xFFFFFFFF - lapic_read(APIC_CCR); + diff = diff / 3; lapic_write(APIC_DCR, 0xB); // set it to 1 clock increments lapic_write(APIC_LVT_T, 0x2007B); // connects the timer to 123 and enables it - lapic_write(APIC_ICR, diff / 3); + lapic_write(APIC_ICR, diff); #endif - kprintf("APIC calibration determines an ICR of 0x%x\n", diff / 3); + kprintf("APIC calibration determines an ICR of 0x%x\n", diff); flags = irq_nested_disable(); #if MAX_CORES > 1 @@ -471,16 +494,20 @@ check_lapic: if (!lapic) goto out; - i = *((uint32_t*) (lapic+APIC_VERSION)); kprintf("Found APIC at 0x%x\n", lapic); - kprintf("Maximum LVT Entry: 0x%x\n", (i >> 16) & 0xFF); - kprintf("APIC Version: 0x%x\n", i & 0xFF); + kprintf("Maximum LVT Entry: 0x%x\n", apic_lvt_entries()); + kprintf("APIC Version: 0x%x\n", apic_version()); - if (!((i & 0xFF) >> 4)) { + if (!((apic_version() >> 4))) { kprintf("Currently, MetalSVM didn't supports extern APICs!\n"); goto out; } + if (apic_lvt_entries() < 3) { + kprintf("LVT is too small\n"); + goto out; + } + return 0; out: @@ -501,18 +528,25 @@ int apic_init(void) { int ret; uint8_t i; - + uint32_t v; + uint32_t max_lvt; + ret = apic_probe(); if (!ret) return ret; + max_lvt = apic_lvt_entries(); + + lapic_write(APIC_SVR, 0x17F); // enable the apic and connect to the idt entry 127 lapic_write(APIC_TPR, 0x00); // allow all interrupts lapic_write(APIC_LVT_T, 0x10000); // disable timer interrupt - lapic_write(APIC_LVT_PMC, 0x10000);// disable performance counter interrupt + if (max_lvt >= 4) + lapic_write(APIC_LVT_TSR, 0x10000); // disable thermal sensor interrupt + if (max_lvt >= 5) + lapic_write(APIC_LVT_PMC, 0x10000); // disable performance counter interrupt lapic_write(APIC_LINT0, 0x7C); // connect LINT0 to idt entry 124 lapic_write(APIC_LINT1, 0x7D); // connect LINT1 to idt entry 125 lapic_write(APIC_LVT_ER, 0x7E); // connect error to idt entry 126 - lapic_write(APIC_SVR, 0x17F); // enable the apic and connect to the idt entry 127 if (0) { //ioapic) { // enable timer interrupt From b46664b3758261867815b82125014543439ee107 Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Tue, 5 Apr 2011 11:33:41 +0200 Subject: [PATCH 06/28] increasing the readability --- arch/x86/kernel/apic.c | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/arch/x86/kernel/apic.c b/arch/x86/kernel/apic.c index 206619ef..b2edcebd 100644 --- a/arch/x86/kernel/apic.c +++ b/arch/x86/kernel/apic.c @@ -76,8 +76,8 @@ static inline void lapic_write(uint32_t addr, uint32_t value) * to avoid a pentium bug, we have to read a apic register * before we write a value to this register */ - //asm volatile ("cmpl (%0), %%eax; movl %1, (%0)" :: "r"(lapic+addr), "r"(value)); - asm volatile ("movl (%%eax), %%edx; movl %%ebx, (%%eax)" :: "a"(lapic+addr), "b"(value) : "%edx"); + asm volatile ("cmpl (%0), %%eax; movl %1, (%0)" :: "r"(lapic+addr), "r"(value)); + //asm volatile ("movl (%%eax), %%edx; movl %%ebx, (%%eax)" :: "a"(lapic+addr), "b"(value) : "%edx"); //*((volatile uint32_t*) (lapic+addr)) = value; } @@ -112,20 +112,16 @@ uint32_t apic_cpu_id(void) static inline uint32_t apic_version(void) { - if (lapic) { - uint32_t i = *((uint32_t*) (lapic+APIC_VERSION)); - return i & 0xFF; - } + if (lapic) + return lapic_read(APIC_VERSION) & 0xFF; return 0; } static inline uint32_t apic_lvt_entries(void) { - if (lapic) { - uint32_t i = *((uint32_t*) (lapic+APIC_VERSION)); - return (i >> 16) & 0xFF; - } + if (lapic) + return (lapic_read(APIC_VERSION) >> 16) & 0xFF; return 0; } From e599063dd2f54cc8923b327751f3bd6e8ca5ce65 Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Tue, 5 Apr 2011 11:37:20 +0200 Subject: [PATCH 07/28] cosmetic changes --- arch/x86/kernel/apic.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/arch/x86/kernel/apic.c b/arch/x86/kernel/apic.c index b2edcebd..f7eee024 100644 --- a/arch/x86/kernel/apic.c +++ b/arch/x86/kernel/apic.c @@ -286,13 +286,13 @@ int apic_calibration(void) lapic_write(APIC_DCR, 0xB); // set it to 1 clock increments lapic_write(APIC_LVT_T, 0x2007B); // connects the timer to 123 and enables it - lapic_write(APIC_ICR, 0xFFFFFFFF); + lapic_write(APIC_ICR, 0xFFFFFFFFUL); /* wait 3 time slices to determine a ICR */ while(get_clock_tick() - ticks < 3) ; - diff = 0xFFFFFFFF - lapic_read(APIC_CCR); + diff = 0xFFFFFFFFUL - lapic_read(APIC_CCR); diff = diff / 3; lapic_write(APIC_DCR, 0xB); // set it to 1 clock increments @@ -323,7 +323,7 @@ int apic_calibration(void) lapic_write(APIC_DCR, 0xB); // set it to 1 clock increments lapic_write(APIC_LVT_T, 0x2007B); // connects the timer to 123 and enables it - lapic_write(APIC_ICR, 0xFFFFFFFF); + lapic_write(APIC_ICR, 0xFFFFFFFFUL); /* wait 3 time slices to determine a ICR */ start = rdtsc(); @@ -331,9 +331,9 @@ int apic_calibration(void) flush_pipeline(); end = rdtsc(); ticks = end > start ? end - start : start - end; - } while(ticks*TIMER_FREQ < 3*RC_REFCLOCKMHZ*1000000); + } while(ticks*TIMER_FREQ < 3*RC_REFCLOCKMHZ*1000000UL); - diff = 0xFFFFFFFF - lapic_read(APIC_CCR); + diff = 0xFFFFFFFFUL - lapic_read(APIC_CCR); diff = diff / 3; lapic_write(APIC_DCR, 0xB); // set it to 1 clock increments From f0e4a2b8335dd29aa3f2b0a9772c1a02036edecb Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Tue, 5 Apr 2011 23:43:44 -0700 Subject: [PATCH 08/28] add the support of the memory type MPBT => seesection "10.1.2 Internal Cache Changes" of SCC External Architecture Specification (R1.1) --- arch/x86/include/asm/page.h | 1 + arch/x86/include/asm/processor.h | 10 ++++++++++ arch/x86/mm/page.c | 8 ++++++-- arch/x86/scc/scc_init.c | 8 ++++++++ include/metalsvm/stdlib.h | 4 +++- 5 files changed, 28 insertions(+), 3 deletions(-) diff --git a/arch/x86/include/asm/page.h b/arch/x86/include/asm/page.h index 553a2584..6f62bc32 100644 --- a/arch/x86/include/asm/page.h +++ b/arch/x86/include/asm/page.h @@ -48,6 +48,7 @@ #define PG_ACCESSED (1 << _PAGE_BIT_ACCESSED) #define PG_DIRTY (1 << _PAGE_BIT_DIRTY) #define PG_PSE (1 << _PAGE_BIT_PSE) +#define PG_MPE PG_PSE #define PG_GLOBAL (1 << _PAGE_BIT_GLOBAL) #define PG_RESERVED (1 << _PAGE_BIT_RESERVED) #define PG_PAT (1 << _PAGE_BIT_PAT) diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h index 27294236..b79a4b60 100644 --- a/arch/x86/include/asm/processor.h +++ b/arch/x86/include/asm/processor.h @@ -113,6 +113,16 @@ static inline void write_cr3(uint32_t val) { asm volatile("mov %0, %%cr3" : : "r"(val)); } +static inline uint32_t read_cr4(void) { + uint32_t val; + asm volatile("mov %%cr4, %0" : "=r"(val)); + return val; +} + +static inline void write_cr4(uint32_t val) { + asm volatile("mov %0, %%cr4" : : "r"(val)); +} + static inline void tlb_flush_one_page(uint32_t addr) { asm volatile("invlpg (%0)" : : "r"(addr) : "memory"); diff --git a/arch/x86/mm/page.c b/arch/x86/mm/page.c index 114f2a66..993ccc3d 100644 --- a/arch/x86/mm/page.c +++ b/arch/x86/mm/page.c @@ -339,6 +339,10 @@ size_t map_region(size_t viraddr, size_t phyaddr, uint32_t npages, uint32_t flag if (flags & MAP_NO_CACHE) pgt->entries[index] |= PG_PCD; +#ifdef CONFIG_ROCKCREEK + if (flags & MAP_MPE) + pgt->entries[index] |= PG_MPE; +#endif if (flags & MAP_USER_SPACE) atomic_int32_inc(&task->user_usage); @@ -684,8 +688,8 @@ int arch_paging_init(void) 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); kprintf("Map configuration registers at 0x%x\n", viraddr); - // map SCC's configuration registers - viraddr = map_region(MPB_X0_Y0, MPB_X0_Y0, (MPB_OWN-MPB_X0_Y0+16*1024*1024)/PAGE_SIZE, MAP_KERNEL_SPACE); + // 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); kprintf("Map message passing buffers at 0x%x\n", viraddr); #endif diff --git a/arch/x86/scc/scc_init.c b/arch/x86/scc/scc_init.c index 0e3a2197..02b6057f 100644 --- a/arch/x86/scc/scc_init.c +++ b/arch/x86/scc/scc_init.c @@ -27,6 +27,9 @@ #ifdef CONFIG_ROCKCREEK +/* PSE bit for Pentium+ equals MPE (message buffer enable) flag in RCK! So, use it to create _PAGE_MPB symbol... */ +#define _CR4_MPE 0x00000800 + /* * Workaround to create a suitable argv array */ @@ -83,6 +86,11 @@ int scc_init(void) num_ranks = RCCE_num_ues(); kprintf("Got rank %d of %d ranks\n", my_rank, num_ranks); + /* Enable Messagepassing in CR4 */ + uint32_t cr4 = read_cr4(); + cr4 = cr4 | _CR4_MPE; + write_cr4(cr4); + i = ReadConfigReg(CRB_OWN+GLCFG0); kprintf("glcfg0 0x%x\n", i); diff --git a/include/metalsvm/stdlib.h b/include/metalsvm/stdlib.h index 6a74fac6..ca6d3d91 100644 --- a/include/metalsvm/stdlib.h +++ b/include/metalsvm/stdlib.h @@ -36,7 +36,9 @@ extern "C" { #define MAP_HEAP (1 << 5) #define MAP_CODE (1 << 6) #define MAP_READONLY (1 << 7) - +#ifdef CONFIG_ROCKCREEK +#define MAP_MPE (1 << 8) +#endif void NORETURN abort(void); void* kmalloc(size_t); void* mem_allocation(size_t sz, uint32_t flags); From 683f8cca1eae1bb6d9330b822d7c3a4aea470e51 Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Wed, 6 Apr 2011 05:38:44 -0700 Subject: [PATCH 09/28] add macro to simplify the using of th hlt instruction --- arch/x86/include/asm/processor.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h index b79a4b60..9e44bf1d 100644 --- a/arch/x86/include/asm/processor.h +++ b/arch/x86/include/asm/processor.h @@ -145,10 +145,11 @@ static inline uint32_t read_eflags(void) uint32_t read_eip(void); -#define NOP1 asm volatile ("nop") -#define NOP2 asm volatile ("nop;nop") -#define NOP4 asm volatile ("nop;nop;nop;nop") -#define NOP8 asm volatile ("nop;nop;nop;nop;nop;nop;nop;nop") +#define NOP1 asm volatile ("nop") +#define NOP2 asm volatile ("nop;nop") +#define NOP4 asm volatile ("nop;nop;nop;nop") +#define NOP8 asm volatile ("nop;nop;nop;nop;nop;nop;nop;nop") +#define HALT asm volatile ("hlt"); inline static int system_init(void) { From 73eab577a66c25bd5a24d33f756ddbe594205301 Mon Sep 17 00:00:00 2001 From: Marian Ohligs Date: Thu, 7 Apr 2011 15:58:37 +0200 Subject: [PATCH 10/28] add some git .ignore filetypes --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index da271bff..8ff138b1 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,6 @@ *.sym *.pcap *.img +*.log +*.a +*.DS_Store From 6b86f3c5727ff3e8d40215c9681116ab6cac910b Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Thu, 7 Apr 2011 20:25:49 +0200 Subject: [PATCH 11/28] add the address of error status register --- arch/x86/include/asm/apic.h | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h index d5f21089..d791ba46 100644 --- a/arch/x86/include/asm/apic.h +++ b/arch/x86/include/asm/apic.h @@ -33,6 +33,7 @@ extern "C" { #define APIC_TPR 0x0080 // Task Priority Regster #define APIC_EOI 0x00B0 // EOI Register #define APIC_SVR 0x00F0 // Spurious Interrupt Vector Register +#define APIC_ESR 0x0280 // Error Status Regsiter #define APIC_ICR1 0x0300 // Interrupt Command Register [0-31] #define APIC_ICR2 0x0310 // Interrupt Command Register [32-63] #define APIC_LVT_T 0x0320 // LVT Timer Register From 030243f200cd23e98a0d441cb19fdb61bc7c2709 Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Thu, 7 Apr 2011 20:30:23 +0200 Subject: [PATCH 12/28] introduce the hlt instruction --- arch/x86/include/asm/processor.h | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h index 27294236..63c5b08c 100644 --- a/arch/x86/include/asm/processor.h +++ b/arch/x86/include/asm/processor.h @@ -71,14 +71,6 @@ inline static void cpuid(uint32_t code, uint32_t* a, uint32_t* b, uint32_t* c, u asm volatile ("cpuid" : "=a"(*a), "=b"(*b), "=c"(*c), "=d"(*d) : "0"(code)); } -inline static void flush_pipeline(void) { - uint32_t low = 0; - uint32_t high = 0; - uint32_t code = 0; - - asm volatile ("cpuid" : "=a"(low), "=d"(high) : "0"(code) : "%ebx", "%ecx"); -} - inline static uint64_t rdmsr(uint32_t msr) { uint32_t low, high; @@ -135,10 +127,11 @@ static inline uint32_t read_eflags(void) uint32_t read_eip(void); -#define NOP1 asm volatile ("nop") -#define NOP2 asm volatile ("nop;nop") -#define NOP4 asm volatile ("nop;nop;nop;nop") -#define NOP8 asm volatile ("nop;nop;nop;nop;nop;nop;nop;nop") +#define NOP1 asm volatile ("nop") +#define NOP2 asm volatile ("nop;nop") +#define NOP4 asm volatile ("nop;nop;nop;nop") +#define NOP8 asm volatile ("nop;nop;nop;nop;nop;nop;nop;nop") +#define HALT asm volatile ("hlt"); inline static int system_init(void) { From e96a5493494ad04d38262ac3435c4d4a550d4b54 Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Thu, 7 Apr 2011 20:31:10 +0200 Subject: [PATCH 13/28] more accurate calculation of the processor frequency --- arch/x86/kernel/processor.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/arch/x86/kernel/processor.c b/arch/x86/kernel/processor.c index f2237f17..2b1c84bf 100644 --- a/arch/x86/kernel/processor.c +++ b/arch/x86/kernel/processor.c @@ -23,16 +23,10 @@ #include #ifdef CONFIG_ROCKCREEK #include -#else -/* disable optimization for the following functions */ -uint32_t detect_cpu_frequency(void) __attribute__((optimize(0))); #endif static uint32_t cpu_freq = 0; -/* disable optimization for the following functions */ -void udelay(uint32_t usecs) __attribute__((optimize(0))); - uint32_t detect_cpu_frequency(void) { #ifdef CONFIG_ROCKCREEK @@ -53,12 +47,14 @@ uint32_t detect_cpu_frequency(void) /* wait for the next time slice */ while((ticks = get_clock_tick()) - old == 0) - ; + HALT; + rmb(); start = rdtsc(); /* wait a second to determine the frequency */ while(get_clock_tick() - ticks < TIMER_FREQ) - ; + HALT; + rmb(); end = rdtsc(); diff = end > start ? end - start : start - end; @@ -82,6 +78,7 @@ void udelay(uint32_t usecs) uint64_t deadline = get_cpu_frequency() * usecs; do { + rmb(); end = rdtsc(); diff = end > start ? end - start : start - end; } while(diff < deadline); From ea5b7e4930e6d184fb1e60bfa8516e08e6105804 Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Thu, 7 Apr 2011 20:35:13 +0200 Subject: [PATCH 14/28] reset APIC before timer initialization --- arch/x86/kernel/apic.c | 95 +++++++++++++++++++++++++++--------------- 1 file changed, 61 insertions(+), 34 deletions(-) diff --git a/arch/x86/kernel/apic.c b/arch/x86/kernel/apic.c index f7eee024..9b80a700 100644 --- a/arch/x86/kernel/apic.c +++ b/arch/x86/kernel/apic.c @@ -76,8 +76,7 @@ static inline void lapic_write(uint32_t addr, uint32_t value) * to avoid a pentium bug, we have to read a apic register * before we write a value to this register */ - asm volatile ("cmpl (%0), %%eax; movl %1, (%0)" :: "r"(lapic+addr), "r"(value)); - //asm volatile ("movl (%%eax), %%edx; movl %%ebx, (%%eax)" :: "a"(lapic+addr), "b"(value) : "%edx"); + asm volatile ("movl (%%eax), %%edx; movl %%ebx, (%%eax)" :: "a"(lapic+addr), "b"(value) : "%edx"); //*((volatile uint32_t*) (lapic+addr)) = value; } @@ -255,6 +254,24 @@ int smp_init(void) } #endif +static int lapic_reset(void) +{ + uint32_t max_lvt = apic_lvt_entries(); + + lapic_write(APIC_SVR, 0x17F); // enable the apic and connect to the idt entry 127 + lapic_write(APIC_TPR, 0x00); // allow all interrupts + lapic_write(APIC_LVT_T, 0x10000); // disable timer interrupt + if (max_lvt >= 4) + lapic_write(APIC_LVT_TSR, 0x10000); // disable thermal sensor interrupt + if (max_lvt >= 5) + lapic_write(APIC_LVT_PMC, 0x10000); // disable performance counter interrupt + lapic_write(APIC_LINT0, 0x7C); // connect LINT0 to idt entry 124 + lapic_write(APIC_LINT1, 0x7D); // connect LINT1 to idt entry 125 + lapic_write(APIC_LVT_ER, 0x7E); // connect error to idt entry 126 + + return 0; +} + /* * detects the timer frequency of the APIC and restart * the APIC timer with the correct period @@ -263,10 +280,13 @@ int apic_calibration(void) { uint8_t i; uint32_t flags; - #ifndef CONFIG_ROCKCREEK uint64_t ticks, old; uint32_t diff; +#else + uint64_t start, end, ticks; + uint32_t diff; +#endif if (!has_apic()) return -ENXIO; @@ -274,30 +294,47 @@ int apic_calibration(void) lapic = map_region(0 /*lapic*/, lapic, 1, MAP_KERNEL_SPACE|MAP_NO_CACHE); if (BUILTIN_EXPECT(!lapic, 0)) return -ENXIO; + kprintf("Mapped LAPIC at 0x%x\n", lapic); + + if (ioapic) { + size_t old = 0; - if (ioapic) ioapic = (ioapic_t*) map_region(0 /*(size_t)ioapic*/, (size_t) ioapic, 1, MAP_KERNEL_SPACE|MAP_NO_CACHE); + kprintf("Mapped IOAPIC at 0x%x\n", ioapic); + // map all processor entries + for(i=0; i Therefore, we disable the PIC outportb(0xA1, 0xFF); @@ -308,27 +345,17 @@ int apic_calibration(void) * and possess no PIC timer. Therfore, we use the rdtsc to * to calibrate the APIC timer. */ - uint64_t start, end, ticks; - uint32_t diff; - - if (!has_apic()) - return -ENXIO; - - lapic = map_region(0 /*lapic*/, lapic, 1, MAP_KERNEL_SPACE|MAP_NO_CACHE); - if (BUILTIN_EXPECT(!lapic, 0)) - return -ENXIO; - - if (ioapic) - ioapic = (ioapic_t*) map_region(0 /*(size_t)ioapic*/, (size_t)ioapic, 1, MAP_KERNEL_SPACE|MAP_NO_CACHE); + flags = irq_nested_disable(); lapic_write(APIC_DCR, 0xB); // set it to 1 clock increments lapic_write(APIC_LVT_T, 0x2007B); // connects the timer to 123 and enables it lapic_write(APIC_ICR, 0xFFFFFFFFUL); /* wait 3 time slices to determine a ICR */ + rmb(); start = rdtsc(); do { - flush_pipeline(); + rmb(); end = rdtsc(); ticks = end > start ? end - start : start - end; } while(ticks*TIMER_FREQ < 3*RC_REFCLOCKMHZ*1000000UL); @@ -336,9 +363,12 @@ int apic_calibration(void) diff = 0xFFFFFFFFUL - lapic_read(APIC_CCR); diff = diff / 3; + lapic_reset(); lapic_write(APIC_DCR, 0xB); // set it to 1 clock increments lapic_write(APIC_LVT_T, 0x2007B); // connects the timer to 123 and enables it lapic_write(APIC_ICR, diff); + + irq_nested_enable(flags); #endif kprintf("APIC calibration determines an ICR of 0x%x\n", diff); @@ -520,31 +550,28 @@ no_mp: goto check_lapic; } +static void apic_err_handler(struct state *s) +{ + kprintf("Got APIC error 0x%x\n", lapic_read(APIC_ESR)); +} + int apic_init(void) { int ret; uint8_t i; - uint32_t v; - uint32_t max_lvt; ret = apic_probe(); if (!ret) return ret; - max_lvt = apic_lvt_entries(); + // set APIC error handler + irq_install_handler(126, apic_err_handler); - lapic_write(APIC_SVR, 0x17F); // enable the apic and connect to the idt entry 127 - lapic_write(APIC_TPR, 0x00); // allow all interrupts - lapic_write(APIC_LVT_T, 0x10000); // disable timer interrupt - if (max_lvt >= 4) - lapic_write(APIC_LVT_TSR, 0x10000); // disable thermal sensor interrupt - if (max_lvt >= 5) - lapic_write(APIC_LVT_PMC, 0x10000); // disable performance counter interrupt - lapic_write(APIC_LINT0, 0x7C); // connect LINT0 to idt entry 124 - lapic_write(APIC_LINT1, 0x7D); // connect LINT1 to idt entry 125 - lapic_write(APIC_LVT_ER, 0x7E); // connect error to idt entry 126 + ret = lapic_reset(); + if (!ret) + return ret; - if (0) { //ioapic) { + if (ioapic) { // enable timer interrupt ioapic_inton(0, apic_processors[boot_processor]->id); // now lets turn everything else off From 1ff9c397a978a18b4b2560a6164f7c9d9fbc1d41 Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Thu, 7 Apr 2011 20:36:43 +0200 Subject: [PATCH 15/28] fix bug in the debug messages --- arch/x86/mm/page.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/arch/x86/mm/page.c b/arch/x86/mm/page.c index 114f2a66..db9aca11 100644 --- a/arch/x86/mm/page.c +++ b/arch/x86/mm/page.c @@ -328,7 +328,7 @@ size_t map_region(size_t viraddr, size_t phyaddr, uint32_t npages, uint32_t flag index = (viraddr >> 12) & 0x3FF; if (BUILTIN_EXPECT(pgt->entries[index], 0)) { spinlock_unlock(pgd_lock); - kprintf("0x%x is already maped\n"); + kprintf("0x%x is already maped\n", viraddr); return 0; } @@ -642,8 +642,9 @@ int arch_paging_init(void) * of course, mb_info has to map into the kernel space */ if (mb_info) - map_region((size_t) mb_info, (size_t) mb_info, 1, MAP_KERNEL_SPACE); + map_region((size_t) mb_info & 0xFFFFF000, (size_t) mb_info & 0xFFFFF000, 1, MAP_KERNEL_SPACE); +#if 0 /* * Map reserved memory regions into the kernel space */ @@ -661,6 +662,7 @@ int arch_paging_init(void) mmap++; } } +#endif /* * Modules like the init ram disk are already loaded. From c43efee104768bf6ea0973e57f6d7fe9c757561f Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Fri, 8 Apr 2011 15:55:49 +0200 Subject: [PATCH 16/28] use HALT instead of NOP --- kernel/tasks.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/tasks.c b/kernel/tasks.c index 144026fc..3f7a1b7a 100644 --- a/kernel/tasks.c +++ b/kernel/tasks.c @@ -104,7 +104,7 @@ static void NORETURN do_exit(int arg) { kputs("Kernel panic: scheduler found no valid task\n"); while(1) { - NOP8; + HALT; } } From 4d14ec6aa71f18e59bd83deae7b79288f6af73d5 Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Fri, 8 Apr 2011 15:56:03 +0200 Subject: [PATCH 17/28] use HALT instead of NOP8 --- kernel/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/main.c b/kernel/main.c index eae0ec05..d58d8ce7 100644 --- a/kernel/main.c +++ b/kernel/main.c @@ -111,7 +111,7 @@ int main(void) reschedule(); while(1) { - NOP8; + HALT; } return 0; From 8868900e193dfcd5a4517e68ca55467f17fb8464 Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Fri, 8 Apr 2011 15:56:09 +0200 Subject: [PATCH 18/28] redesign of nested if flag handling => only clearing and setting of the IF flag --- arch/x86/include/asm/irqflags.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/arch/x86/include/asm/irqflags.h b/arch/x86/include/asm/irqflags.h index 4a79d9ec..f8289b10 100644 --- a/arch/x86/include/asm/irqflags.h +++ b/arch/x86/include/asm/irqflags.h @@ -31,7 +31,9 @@ inline static void irq_disable(void) { inline static uint32_t irq_nested_disable(void) { uint32_t flags; asm volatile("pushf; cli; popl %0": "=r"(flags) : : "memory"); - return flags; + if (flags & (1 << 9)) + return 1; + return 0; } inline static void irq_enable(void) { @@ -39,7 +41,8 @@ inline static void irq_enable(void) { } inline static void irq_nested_enable(uint32_t flags) { - asm volatile("pushl %0; popf" : : "r"(flags) : "memory"); + if (flags) + irq_enable(); } #ifdef __cplusplus From ab78beb85983e47f88ae81cbbacbe0d9ffa5206a Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Fri, 8 Apr 2011 15:56:22 +0200 Subject: [PATCH 19/28] cosemtic changes --- arch/x86/kernel/gdt.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/arch/x86/kernel/gdt.c b/arch/x86/kernel/gdt.c index 084f071c..b4fd61ae 100644 --- a/arch/x86/kernel/gdt.c +++ b/arch/x86/kernel/gdt.c @@ -69,6 +69,8 @@ int arch_fork(task_t* task) memcpy(kstacks[id], kstacks[curr_task->id], KERNEL_STACK_SIZE); task_state_segments[id].cr3 = (uint32_t) (virt_to_phys((size_t)task->pgd)); task_state_segments[id].eflags = read_eflags(); + // the parent task will enable the IF flag + task_state_segments[id].eflags |= (1 << 9); task_state_segments[id].esp0 = (uint32_t) kstacks[id] + KERNEL_STACK_SIZE - sizeof(size_t); asm volatile("mov %%esp, %0" : "=r"(task_state_segments[id].esp)); @@ -76,18 +78,18 @@ int arch_fork(task_t* task) task_state_segments[id].esp += (uint32_t) kstacks[id]; asm volatile ("pusha"); - asm volatile ("pop %%eax" : "=a"(task_state_segments[id].edi)); - asm volatile ("pop %%eax" : "=a"(task_state_segments[id].esi)); - asm volatile ("pop %%eax" : "=a"(task_state_segments[id].ebp)); + asm volatile ("pop %0" : "=r"(task_state_segments[id].edi)); + asm volatile ("pop %0" : "=r"(task_state_segments[id].esi)); + asm volatile ("pop %0" : "=r"(task_state_segments[id].ebp)); #ifdef WITH_FRAME_POINTER task_state_segments[id].ebp -= (uint32_t) kstacks[curr_task->id]; task_state_segments[id].ebp += (uint32_t) kstacks[id]; #endif asm volatile ("add $4, %%esp" ::: "%esp"); - asm volatile ("pop %%eax" : "=a"(task_state_segments[id].ebx)); - asm volatile ("pop %%eax" : "=a"(task_state_segments[id].edx)); - asm volatile ("pop %%eax" : "=a"(task_state_segments[id].ecx)); - asm volatile ("pop %%eax" : "=a"(task_state_segments[id].eax)); + asm volatile ("pop %0" : "=r"(task_state_segments[id].ebx)); + asm volatile ("pop %0" : "=r"(task_state_segments[id].edx)); + asm volatile ("pop %0" : "=r"(task_state_segments[id].ecx)); + asm volatile ("pop %0" : "=r"(task_state_segments[id].eax)); // This will be the entry point for the new task. task_state_segments[id].eip = read_eip(); From 92c5917ef485b84241f3d9e6b9fd107b30d5a18f Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Fri, 8 Apr 2011 15:56:28 +0200 Subject: [PATCH 20/28] add support to map kernel pages above 1GB --- arch/x86/mm/page.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/arch/x86/mm/page.c b/arch/x86/mm/page.c index db9aca11..1d64bbba 100644 --- a/arch/x86/mm/page.c +++ b/arch/x86/mm/page.c @@ -87,6 +87,12 @@ inline static size_t copy_page_table(task_t* task, uint32_t pgd_index, page_tabl for(i=0; i<1024; i++) { if (pgt->entries[i] & 0xFFFFF000) { + if (!(pgt->entries[i] & PG_USER)) { + // Kernel page => copy only page entries + new_pgt->entries[i] = pgt->entries[i]; + continue; + } + phyaddr = get_page(); if (!phyaddr) continue; @@ -140,9 +146,10 @@ int create_pgd(task_t* task, int copy) spinlock_lock(&kslock); - for(i=0; ientries[i] = boot_pgd.entries[i]; - if (pgd->entries[i]) + // only kernel entries will be copied + if (pgd->entries[i] && !(pgd->entries[i] & PG_USER)) pgt->entries[i] = pgt_container->entries[i]; } @@ -165,6 +172,8 @@ int create_pgd(task_t* task, int copy) for (i=KERNEL_SPACE/(1024*PAGE_SIZE); i<1024; i++) { if (!(curr_task->pgd->entries[i])) continue; + if (!(curr_task->pgd->entries[i] & PG_USER)) + continue; phyaddr = copy_page_table(task, i, (page_table_t*) ((KERNEL_SPACE - 1024*PAGE_SIZE + i*PAGE_SIZE) & 0xFFFFF000), &counter); if (phyaddr) { @@ -194,8 +203,8 @@ int drop_pgd(void) spinlock_lock(&task->pgd_lock); - for(i=KERNEL_SPACE/(1024*PAGE_SIZE); i<1024; i++) { - if (pgd->entries[i] & 0xFFFFF000) { + for(i=0; i<1024; i++) { + if (pgd->entries[i] & PG_USER) { put_page(pgd->entries[i] & 0xFFFFF000); pgd->entries[i] = 0; } From e3e06fe5234d89f9297c083b893647c7b442c0a1 Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Fri, 8 Apr 2011 15:56:36 +0200 Subject: [PATCH 21/28] set APICID of the boot processor to 0 --- arch/x86/kernel/apic.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/x86/kernel/apic.c b/arch/x86/kernel/apic.c index 9b80a700..151b9143 100644 --- a/arch/x86/kernel/apic.c +++ b/arch/x86/kernel/apic.c @@ -268,6 +268,7 @@ static int lapic_reset(void) lapic_write(APIC_LINT0, 0x7C); // connect LINT0 to idt entry 124 lapic_write(APIC_LINT1, 0x7D); // connect LINT1 to idt entry 125 lapic_write(APIC_LVT_ER, 0x7E); // connect error to idt entry 126 + lapic_write(APIC_ID, 0x00); // reset boot processor id return 0; } From d3ad7e1c665e0871bd72e8c40d2125847a00da12 Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Fri, 8 Apr 2011 07:24:47 -0700 Subject: [PATCH 22/28] move the call of scc_init to main function --- kernel/main.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/kernel/main.c b/kernel/main.c index eae0ec05..3cf4aa07 100644 --- a/kernel/main.c +++ b/kernel/main.c @@ -89,6 +89,9 @@ int main(void) #endif multitasking_init(); mmu_init(); +#ifdef CONFIG_ROCKCREEK + scc_init(); +#endif initrd_init(); irq_enable(); From 0fbf2df5ac200f8f25802c41322a13cb942a08e4 Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Fri, 8 Apr 2011 10:45:26 -0700 Subject: [PATCH 23/28] use inline assembler to load the IDT --- arch/x86/kernel/entry.asm | 9 +-------- arch/x86/kernel/idt.c | 7 ++----- 2 files changed, 3 insertions(+), 13 deletions(-) diff --git a/arch/x86/kernel/entry.asm b/arch/x86/kernel/entry.asm index a9d85364..f24b33dd 100644 --- a/arch/x86/kernel/entry.asm +++ b/arch/x86/kernel/entry.asm @@ -103,14 +103,7 @@ gdt_flush: flush2: ret -; Loads the IDT defined in '_idtp' into the processor. -; This is declared in C as 'extern void idt_load();' -global idt_load -extern idtp -idt_load: - lidt [idtp] - ret - +; determines the current instruction pointer (after the jmp) global read_eip read_eip: pop eax ; Get the return address diff --git a/arch/x86/kernel/idt.c b/arch/x86/kernel/idt.c index 20f620a1..0f231931 100644 --- a/arch/x86/kernel/idt.c +++ b/arch/x86/kernel/idt.c @@ -43,10 +43,7 @@ typedef struct { * "Unhandled Interrupt" exception */ static idt_entry_t idt[256] = {[0 ... 255] = {0, 0, 0, 0, 0}}; -idt_ptr_t idtp; - -/* This exists in 'start.asm', and is used to load our IDT */ -extern void idt_load(void); +static idt_ptr_t idtp; /* * Use this function to set an entry in the IDT. Alot simpler @@ -81,5 +78,5 @@ void idt_install(void) IDT_FLAG_PRESENT|IDT_FLAG_RING3|IDT_FLAG_32BIT|IDT_FLAG_TRAPGATE); /* Points the processor's internal register to the new IDT */ - idt_load(); + asm volatile("lidt %0" : : "m" (idtp)); } From 12fb2a60f2c9c51a36b5ab1102d45a7a676a4e8f Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Wed, 13 Apr 2011 07:04:50 -0700 Subject: [PATCH 24/28] create a dynamic region, which specifies the boot parameters --- arch/x86/mm/page.c | 3 +++ arch/x86/scc/scc_init.c | 27 ++++++++++++++++----------- tools/Makefile | 8 +++++++- tools/bootinfo.sh | 39 +++++++++++++++++++++++++++++++++++++++ tools/load.map | 1 + 5 files changed, 66 insertions(+), 12 deletions(-) create mode 100755 tools/bootinfo.sh diff --git a/arch/x86/mm/page.c b/arch/x86/mm/page.c index 533f4a5c..b8c37884 100644 --- a/arch/x86/mm/page.c +++ b/arch/x86/mm/page.c @@ -695,6 +695,9 @@ int arch_paging_init(void) #endif #ifdef CONFIG_ROCKCREEK + // map SCC's bootinfo + map_region(SCC_BOOTINFO, SCC_BOOTINFO, 1, 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); kprintf("Map configuration registers at 0x%x\n", viraddr); diff --git a/arch/x86/scc/scc_init.c b/arch/x86/scc/scc_init.c index 02b6057f..1f7d0c5a 100644 --- a/arch/x86/scc/scc_init.c +++ b/arch/x86/scc/scc_init.c @@ -27,17 +27,18 @@ #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; + +static bootinfo_t* bootinfo = (bootinfo_t*) SCC_BOOTINFO; + /* PSE bit for Pentium+ equals MPE (message buffer enable) flag in RCK! So, use it to create _PAGE_MPB symbol... */ #define _CR4_MPE 0x00000800 -/* - * Workaround to create a suitable argv array - */ -static char* argv_strings[] = {"MetalSVM", "1", "533", "0"}; -static char* argv[4] = {[0 ... 3] = NULL}; -static char** rcce_argv = argv; -static int rcce_argc = 4; - /* * This is the modified MPB program, which is part of the RCCE distribution (src/mpb.c). * @@ -77,9 +78,13 @@ int scc_init(void) int i, my_rank; kprintf("Initialize Rock Creek!\n"); - for(i=0; iaddr); + kprintf("size of the initrd: %d\n", bootinfo->size); + kprintf("rcce argc = %d\n", bootinfo->argc); + for(i=0; iargc; i++) + kprintf("rcce argv[%d] = %s\n", i, bootinfo->argv[i]); + + if (RCCE_init(&bootinfo->argc, &bootinfo->argv) != RCCE_SUCCESS) return -ENODEV; my_rank = RCCE_ue(); diff --git a/tools/Makefile b/tools/Makefile index 38d44d7f..cde604ef 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -35,7 +35,13 @@ scc_setup.bin: scc_setup.asm reset_vector.bin: reset_vector.o ld --oformat binary -Ttext 0 -melf_i386 -o $@ $< -SCC: scc_setup.bin reset_vector.bin +scc_bootinfo.asm: bootinfo.sh + ./bootinfo.sh 0x00400000 initrd.img 1 533 0 > scc_bootinfo.asm + +scc_bootinfo.bin: scc_bootinfo.asm + $(NASM) $(NASMFLAGS) -o $@ $< + +SCC: scc_bootinfo.bin scc_setup.bin reset_vector.bin cp ../metalsvm.elf . $(CROSS_OBJCOPY) -j .mboot -j .text -j .data -j .rodata -j .bss -O binary metalsvm.elf metalsvm.bin chmod a-x *.bin diff --git a/tools/bootinfo.sh b/tools/bootinfo.sh new file mode 100755 index 00000000..7e308278 --- /dev/null +++ b/tools/bootinfo.sh @@ -0,0 +1,39 @@ +#!/bin/sh +# +IMAGESIZE=$(stat -c%s "$2") +NCORES=$3 +ORG=0x80000 +echo "[BITS 16]" +echo "SECTION .data" +echo "ORG $ORG" +echo "addr DD $1 ; start addresss of the initrd" +echo "size DD $IMAGESIZE ; size of the initrd" + +shift +shift +shift +ARGC=`expr $# + 2` + +echo "argc DD $ARGC" +echo "argv DD Largv" +echo "Largv EQU \$" +echo -n " DD name, ncores" +for i in $* +do + echo -n ", L$i" +done +echo "" + +echo "name EQU \$" +echo " DB \"MetalSVM\", 0" +echo "ncores EQU \$" +echo " DB \"$NCORES\", 0" + +for i in $* +do + echo "L$i EQU \$" + echo " DB \"$i\", 0" +done + +echo "gap:" +echo "TIMES 4096-(\$-\$\$) DB 0" diff --git a/tools/load.map b/tools/load.map index d759ed64..6263ab88 100644 --- a/tools/load.map +++ b/tools/load.map @@ -1,3 +1,4 @@ +0x00080000 scc_bootinfo.bin 0x00090200 scc_setup.bin 0x00100000 metalsvm.bin 0x00400000 initrd.img From 4da0a6e15efae6c92e6ee90a428d2c18b93b7a59 Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Wed, 13 Apr 2011 11:01:24 -0700 Subject: [PATCH 25/28] set correct dependencies between the rules --- tools/Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/Makefile b/tools/Makefile index cde604ef..e0375ae0 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -17,7 +17,7 @@ default: all all: make_initrd initrd.img -initrd.img: $(EXECFILES) +initrd.img: $(EXECFILES) make_initrd ./make_initrd /bin $(foreach FILE, $(EXECFILES), $(FILE) $(shell basename $(FILE))) make_initrd: make_initrd.o @@ -41,7 +41,7 @@ scc_bootinfo.asm: bootinfo.sh scc_bootinfo.bin: scc_bootinfo.asm $(NASM) $(NASMFLAGS) -o $@ $< -SCC: scc_bootinfo.bin scc_setup.bin reset_vector.bin +SCC: scc_bootinfo.bin scc_setup.bin reset_vector.bin initrd.img cp ../metalsvm.elf . $(CROSS_OBJCOPY) -j .mboot -j .text -j .data -j .rodata -j .bss -O binary metalsvm.elf metalsvm.bin chmod a-x *.bin @@ -50,7 +50,7 @@ SCC: scc_bootinfo.bin scc_setup.bin reset_vector.bin sccMerge -noimage -m 8 -n 12 -force ./metalsvm.mt clean: - $(RM) -rf *.o *~ make_initrd *.bin *.obj *.hex *.elf obj + $(RM) -rf *.o *~ make_initrd initrd.img *.bin *.obj *.hex *.elf obj depend: $(CC) -MM $(CFLAGS) *.c > Makefile.dep From eeb49cdb90290e3396db500014c8ec62a26dc3a2 Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Wed, 13 Apr 2011 11:03:34 -0700 Subject: [PATCH 26/28] add the SCC support of a initial ramdisk --- arch/x86/include/asm/processor.h | 9 +++++++++ arch/x86/mm/page.c | 6 ++++++ arch/x86/scc/scc_init.c | 16 ++-------------- fs/initrd.c | 10 +++++++++- mm/memory.c | 24 ++++++++++++++++++++++++ 5 files changed, 50 insertions(+), 15 deletions(-) diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h index d8e3d698..a6ed0c13 100644 --- a/arch/x86/include/asm/processor.h +++ b/arch/x86/include/asm/processor.h @@ -32,6 +32,15 @@ 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 diff --git a/arch/x86/mm/page.c b/arch/x86/mm/page.c index b8c37884..8f8ab109 100644 --- a/arch/x86/mm/page.c +++ b/arch/x86/mm/page.c @@ -698,6 +698,12 @@ int arch_paging_init(void) // map SCC's bootinfo 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++; + 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); kprintf("Map configuration registers at 0x%x\n", viraddr); diff --git a/arch/x86/scc/scc_init.c b/arch/x86/scc/scc_init.c index 1f7d0c5a..3279c967 100644 --- a/arch/x86/scc/scc_init.c +++ b/arch/x86/scc/scc_init.c @@ -10,12 +10,7 @@ * * 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. - */ + * WITHOUT WARRANTIES OR COND */ #include #include @@ -27,14 +22,7 @@ #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; - -static bootinfo_t* bootinfo = (bootinfo_t*) SCC_BOOTINFO; +bootinfo_t* bootinfo = (bootinfo_t*) SCC_BOOTINFO; /* PSE bit for Pentium+ equals MPE (message buffer enable) flag in RCK! So, use it to create _PAGE_MPB symbol... */ #define _CR4_MPE 0x00000800 diff --git a/fs/initrd.c b/fs/initrd.c index b836d79e..c3094b44 100644 --- a/fs/initrd.c +++ b/fs/initrd.c @@ -23,6 +23,7 @@ #include #include #include +#include static vfs_node_t initrd_root; @@ -213,8 +214,10 @@ int initrd_init(void) { dir_block_t* dir_block; vfs_node_t* tmp; -#ifdef CONFIG_MULTIBOOT +#if defined(CONFIG_ROCKCREEK) || defined(CONFIG_MULTIBOOT) uint32_t i, j, k, l; +#endif +#ifdef CONFIG_MULTIBOOT uint32_t mods_count = 0; multiboot_module_t* mmodule = NULL; @@ -256,6 +259,10 @@ int initrd_init(void) #ifdef CONFIG_MULTIBOOT for(i=0; iaddr; +#endif initrd_file_desc_t* file_desc; vfs_node_t* new_node; @@ -328,6 +335,7 @@ int initrd_init(void) next_file: file_desc++; } +#if defined(CONFIG_ROCKCREEK) || defined(CONFIG_MULTIBOOT) } #endif diff --git a/mm/memory.c b/mm/memory.c index d920aed3..cf7f5e48 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -126,6 +126,13 @@ int mmu_init(void) if (mb_info && (mb_info->flags & MULTIBOOT_INFO_MODS)) { multiboot_module_t* mmodule = (multiboot_module_t*) mb_info->mods_addr; + /* + * Mark the mb_info as used. + */ + page_set_mark((size_t)mb_info / PAGE_SIZE); + 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); @@ -150,6 +157,23 @@ int mmu_init(void) atomic_int32_inc(&total_pages); atomic_int32_inc(&total_available_pages); } + + /* + * Mark the bootinfo as used. + */ + page_set_mark((size_t)bootinfo / PAGE_SIZE); + atomic_int32_inc(&total_allocated_pages); + atomic_int32_dec(&total_available_pages); + + /* + * The init ram disk are already loaded. + * 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); + atomic_int32_inc(&total_allocated_pages); + atomic_int32_dec(&total_available_pages); + } #else #error Currently, MetalSVM supports only the Multiboot specification or the RockCreek processor! #endif From 9fb28ccfd9a7a47f369baf8113b4b85c5496e001 Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Wed, 13 Apr 2011 11:04:46 -0700 Subject: [PATCH 27/28] currently, a fork doesn't work on all architectures => disable this feature in our examples --- newlib/examples/tests.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/newlib/examples/tests.c b/newlib/examples/tests.c index e2bc27d3..7288ed82 100644 --- a/newlib/examples/tests.c +++ b/newlib/examples/tests.c @@ -34,7 +34,7 @@ int main(int argc, char** argv) printf("Create child process...\n"); - pid = fork(); + pid = 42; //fork(); if (pid == 0) { // child char* newargs[] = {"/bin/hello", "one", "two", "three", NULL}; char* newenv[] = {"USER=root", "PATH=/bin:/sbin:/usr/bin", "PWD=/", "TEMP=/tmp", NULL}; From a9ce93d119c2709a766c19b9cfa32a0b594b1100 Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Wed, 13 Apr 2011 11:10:47 -0700 Subject: [PATCH 28/28] define the macro SCC_BOOTINFO, which defines the address of the boot parameters --- include/metalsvm/config.h.example | 1 + 1 file changed, 1 insertion(+) diff --git a/include/metalsvm/config.h.example b/include/metalsvm/config.h.example index 6549d1d1..31c02682 100644 --- a/include/metalsvm/config.h.example +++ b/include/metalsvm/config.h.example @@ -66,6 +66,7 @@ extern "C" { #define PRIVATE_MEM1_END 0x13FFFFFF #define PRIVATE_MEM2_START 0xFF000000 #define PRIVATE_MEM2_END 0xFFFFFFFF +#define SCC_BOOTINFO 0x80000 #define BUILTIN_EXPECT(exp, b) __builtin_expect((exp), (b)) //#define BUILTIN_EXPECT(exp, b) (exp)