From 12fb2a60f2c9c51a36b5ab1102d45a7a676a4e8f Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Wed, 13 Apr 2011 07:04:50 -0700 Subject: [PATCH 1/7] 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 2/7] 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 3/7] 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 4/7] 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 5/7] 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) From 02cf1d87f228a0b7289b238cffad69f3045553ae Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Thu, 14 Apr 2011 08:58:07 +0200 Subject: [PATCH 6/7] resolve some merge conflicts --- arch/x86/include/asm/apic.h | 4 ++++ arch/x86/include/asm/processor.h | 28 ++++++++-------------------- 2 files changed, 12 insertions(+), 20 deletions(-) diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h index 1109f69d..f649a479 100644 --- a/arch/x86/include/asm/apic.h +++ b/arch/x86/include/asm/apic.h @@ -38,12 +38,16 @@ extern "C" { #define APIC_EOI 0x00B0 /// Spurious Interrupt Vector Register #define APIC_SVR 0x00F0 +/// Error Status Register +#define APIC_ESR 0x0280 /// Interrupt Command Register [bits 0-31] #define APIC_ICR1 0x0300 /// Interrupt Command Register [bits 32-63] #define APIC_ICR2 0x0310 /// LVT Timer Register #define APIC_LVT_T 0x0320 +/// LVT Thermal Sensor Register +#define APIC_LVT_TSR 0x0330 /// LVT Performance Monitoring Counters Register #define APIC_LVT_PMC 0x0340 /// LVT LINT0 Register diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h index 108907f7..5246fc4f 100644 --- a/arch/x86/include/asm/processor.h +++ b/arch/x86/include/asm/processor.h @@ -128,19 +128,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)); } -<<<<<<< HEAD -/** @brief Flush the pipeline - * - * The cpuid-instruction is used to flush the pipeline. - */ -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"); -} - /** @brief Read MSR * * The asm instruction rdmsr which stands for "Read from model specific register" @@ -149,8 +136,6 @@ inline static void flush_pipeline(void) { * @param msr The parameter which rdmsr assumes in ECX * @return The value rdmsr put into EDX:EAX */ -======= ->>>>>>> a9ce93d119c2709a766c19b9cfa32a0b594b1100 inline static uint64_t rdmsr(uint32_t msr) { uint32_t low, high; @@ -200,22 +185,25 @@ static inline void write_cr3(uint32_t val) { asm volatile("mov %0, %%cr3" : : "r"(val)); } -<<<<<<< HEAD -/** @brief Flush a specific page entry in TLB - * @param addr The (virtual) address of the page to flush +/** @brief Read cr4 register + * @return cr4's value */ -======= static inline uint32_t read_cr4(void) { uint32_t val; asm volatile("mov %%cr4, %0" : "=r"(val)); return val; } +/** @brief Write a value into cr4 register + * @param val The value you want to write into cr4 + */ static inline void write_cr4(uint32_t val) { asm volatile("mov %0, %%cr4" : : "r"(val)); } ->>>>>>> a9ce93d119c2709a766c19b9cfa32a0b594b1100 +/** @brief Flush a specific page entry in TLB + * @param addr The (virtual) address of the page to flush + */ static inline void tlb_flush_one_page(uint32_t addr) { asm volatile("invlpg (%0)" : : "r"(addr) : "memory"); From b9b7841dc3f940a839632db84f35bf6332deadf1 Mon Sep 17 00:00:00 2001 From: Jacek Galowicz Date: Fri, 15 Apr 2011 15:08:41 +0200 Subject: [PATCH 7/7] Moved IDT related structs from idt.c to idt.h. --- arch/x86/include/asm/idt.h | 34 ++++++++++++++++++++++++++++++++++ arch/x86/kernel/idt.c | 32 -------------------------------- 2 files changed, 34 insertions(+), 32 deletions(-) diff --git a/arch/x86/include/asm/idt.h b/arch/x86/include/asm/idt.h index c589c682..a43d4383 100644 --- a/arch/x86/include/asm/idt.h +++ b/arch/x86/include/asm/idt.h @@ -63,6 +63,40 @@ extern "C" { #endif +/** @brief Defines an IDT entry + * + * This structure defines interrupt descriptor table entries.\n + * They consist of the handling function's base address, some flags + * and a segment selector. + */ +typedef struct { + /// Handler function's lower 16 address bits + unsigned short base_lo; + /// Handler function's segment selector. + unsigned short sel; + /// These bits are reserved by Intel + unsigned char always0; + /// These 8 bits contain flags. Exact use depends on the type of interrupt gate. + unsigned char flags; + /// Higher 16 bits of handler function's base address + unsigned short base_hi; +} __attribute__ ((packed)) idt_entry_t; + + +/** @brief Defines the idt pointer structure. + * + * This structure keeps information about + * base address and size of the interrupt descriptor table. + */ +typedef struct { + /// Size of the IDT in bytes (not the number of entries!) + unsigned short limit; + /// Base address of the IDT + unsigned int base; +} __attribute__ ((packed)) idt_ptr_t; + + + /** @brief Installs IDT * * The installation involves the following steps: diff --git a/arch/x86/kernel/idt.c b/arch/x86/kernel/idt.c index d2fa1095..fd8156c4 100644 --- a/arch/x86/kernel/idt.c +++ b/arch/x86/kernel/idt.c @@ -31,38 +31,6 @@ #include #include -/** @brief Defines an IDT entry - * - * This structure defines interrupt descriptor table entries.\n - * They consist of the handling function's base address, some flags - * and a segment selector. - */ -typedef struct { - /// Handler function's lower 16 address bits - unsigned short base_lo; - /// Handler function's segment selector. - unsigned short sel; - /// These bits are reserved by Intel - unsigned char always0; - /// These 8 bits contain flags. Exact use depends on the type of interrupt gate. - unsigned char flags; - /// Higher 16 bits of handler function's base address - unsigned short base_hi; -} __attribute__ ((packed)) idt_entry_t; - - -/** @brief Defines the idt pointer structure. - * - * This structure keeps information about - * base address and size of the interrupt descriptor table. - */ -typedef struct { - /// Size of the IDT in bytes (not the number of entries!) - unsigned short limit; - /// Base address of the IDT - unsigned int base; -} __attribute__ ((packed)) idt_ptr_t; - /* * Declare an IDT of 256 entries. Although we will only use the * first 32 entries in this tutorial, the rest exists as a bit