diff --git a/arch/x86/include/asm/multiboot.h b/arch/x86/include/asm/multiboot.h new file mode 100644 index 00000000..bd7de519 --- /dev/null +++ b/arch/x86/include/asm/multiboot.h @@ -0,0 +1,137 @@ +/* + * Copyright 2010 Stefan Lankes, Chair for Operating Systems, + * RWTH Aachen University + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of MetalSVM. + */ +#ifndef __ARCH_MULTIBOOT_H__ +#define __ARCH_MULTIBOOT_H__ + +#include + +#ifdef USE_MULTIBOOT + +/* + * MetalSVM is able to use Multiboot (http://www.gnu.org/software/grub/manual/multiboot/), + * which specifies an interface between a boot loader and a operating system + */ + +typedef uint16_t multiboot_uint16_t; +typedef uint32_t multiboot_uint32_t; +typedef uint64_t multiboot_uint64_t; + +/* The symbol table for a.out. */ +struct multiboot_aout_symbol_table +{ + multiboot_uint32_t tabsize; + multiboot_uint32_t strsize; + multiboot_uint32_t addr; + multiboot_uint32_t reserved; +}; +typedef struct multiboot_aout_symbol_table multiboot_aout_symbol_table_t; + +/* The section header table for ELF. */ +struct multiboot_elf_section_header_table +{ + multiboot_uint32_t num; + multiboot_uint32_t size; + multiboot_uint32_t addr; + multiboot_uint32_t shndx; +}; +typedef struct multiboot_elf_section_header_table multiboot_elf_section_header_table_t; + +struct multiboot_info +{ + /* Multiboot info version number */ + multiboot_uint32_t flags; + + /* Available memory from BIOS */ + multiboot_uint32_t mem_lower; + multiboot_uint32_t mem_upper; + + /* "root" partition */ + multiboot_uint32_t boot_device; + + /* Kernel command line */ + multiboot_uint32_t cmdline; + + /* Boot-Module list */ + multiboot_uint32_t mods_count; + multiboot_uint32_t mods_addr; + + union + { + multiboot_aout_symbol_table_t aout_sym; + multiboot_elf_section_header_table_t elf_sec; + } u; + + /* Memory Mapping buffer */ + multiboot_uint32_t mmap_length; + multiboot_uint32_t mmap_addr; + + /* Drive Info buffer */ + multiboot_uint32_t drives_length; + multiboot_uint32_t drives_addr; + + /* ROM configuration table */ + multiboot_uint32_t config_table; + + /* Boot Loader Name */ + multiboot_uint32_t boot_loader_name; + + /* APM table */ + multiboot_uint32_t apm_table; + + /* Video */ + multiboot_uint32_t vbe_control_info; + multiboot_uint32_t vbe_mode_info; + multiboot_uint16_t vbe_mode; + multiboot_uint16_t vbe_interface_seg; + multiboot_uint16_t vbe_interface_off; + multiboot_uint16_t vbe_interface_len; +}; + +typedef struct multiboot_info multiboot_info_t; + +struct multiboot_mmap_entry +{ + multiboot_uint32_t size; + multiboot_uint64_t addr; + multiboot_uint64_t len; +#define MULTIBOOT_MEMORY_AVAILABLE 1 +#define MULTIBOOT_MEMORY_RESERVED 2 + multiboot_uint32_t type; +} __attribute__((packed)); +typedef struct multiboot_mmap_entry multiboot_memory_map_t; + +struct multiboot_mod_list +{ + /* the memory used goes from bytes ’mod start’ to ’mod end-1’ inclusive */ + multiboot_uint32_t mod_start; + multiboot_uint32_t mod_end; + + /* Module command line */ + multiboot_uint32_t cmdline; + + /* padding to take it to 16 bytes (must be zero) */ + multiboot_uint32_t pad; +}; +typedef struct multiboot_mod_list multiboot_module_t; + +extern multiboot_info_t* mb_info; + +#endif + +#endif diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile index adb3245f..865e80ed 100644 --- a/arch/x86/kernel/Makefile +++ b/arch/x86/kernel/Makefile @@ -1,4 +1,4 @@ -C_source = gdt.c idt.c isrs.c irq.c vga.c kb.c timer.c +C_source = gdt.c idt.c isrs.c irq.c vga.c kb.c timer.c multiboot.c ASM_source = schedule.asm OBJS += $(patsubst %.c, %.o, $(filter %.c, $(C_source))) diff --git a/arch/x86/kernel/entry.asm b/arch/x86/kernel/entry.asm index 0aa91af0..84f179ec 100644 --- a/arch/x86/kernel/entry.asm +++ b/arch/x86/kernel/entry.asm @@ -55,10 +55,16 @@ mboot: dd end dd start +stublet: + ; interpret multiboot information + extern multiboot_init + push ebx + call multiboot_init + pop ebp + ; This is an endless loop here. Make a note of this: Later on, we ; will insert an 'extern _main', followed by 'call _main', right ; before the 'jmp $'. -stublet: extern main call main jmp $ diff --git a/arch/x86/kernel/multiboot.c b/arch/x86/kernel/multiboot.c new file mode 100644 index 00000000..cb4b610e --- /dev/null +++ b/arch/x86/kernel/multiboot.c @@ -0,0 +1,38 @@ +/* + * Copyright 2010 Stefan Lankes, Chair for Operating Systems, + * RWTH Aachen University + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of MetalSVM. + */ + +#include + +#ifdef USE_MULTIBOOT + +#include + +/* + * MetalSVM is able to use Multiboot (http://www.gnu.org/software/grub/manual/multiboot/), + * which specifies an interface between a boot loader and a operating system + */ + +multiboot_info_t* mb_info = NULL; + +void multiboot_init(void* mb) +{ + mb_info = (multiboot_info_t*) mb; +} + +#endif diff --git a/include/metalsvm/config.h.example b/include/metalsvm/config.h.example index 9cca9106..e3c16477 100644 --- a/include/metalsvm/config.h.example +++ b/include/metalsvm/config.h.example @@ -43,6 +43,8 @@ extern "C" { //#undef USE_VGA #define USE_KEYBOARD //#undef USE_KEYBOARD +#define USE_MULTIBOOT +//#undef USE_MULTIBOOT #define BUILTIN_EXPECT(exp, b) __builtin_expect((exp), (b)) //#define BUILTIN_EXPECT(exp, b) (exp) diff --git a/include/metalsvm/mmu.h b/include/metalsvm/mmu.h index 8e05e08e..cbc01f25 100644 --- a/include/metalsvm/mmu.h +++ b/include/metalsvm/mmu.h @@ -28,7 +28,9 @@ extern "C" { #endif -extern atomic_size_t total_usage; +extern atomic_size_t total_memory; +extern atomic_size_t total_allocated_memory; +extern atomic_size_t total_available_memory; typedef struct { atomic_size_t usage; diff --git a/kernel/main.c b/kernel/main.c index 3f733939..dd6ae482 100644 --- a/kernel/main.c +++ b/kernel/main.c @@ -63,7 +63,9 @@ int main(void) detect_cpu_frequency(); kprintf("Processor frequency: %d MHz\n", get_cpu_frequency()/1000000); - kprintf("Kernel size: %u KBytes\n", atomic_size_read(&total_usage)/1024); + kprintf("Total memory: %u MBytes\n", atomic_size_read(&total_memory)/(1024*1024)); + kprintf("Current allocated memory: %u KBytes\n", atomic_size_read(&total_allocated_memory)/1024); + kprintf("Current available memory: %u MBytes\n", atomic_size_read(&total_available_memory)/(1024*1024)); timer_set_frequency(TIMER_FREQ); diff --git a/mm/alloc.c b/mm/alloc.c index 516f7b21..9118ac76 100644 --- a/mm/alloc.c +++ b/mm/alloc.c @@ -21,6 +21,9 @@ #include #include #include +#ifdef USE_MULTIBOOT +#include +#endif /* * 0 => free @@ -29,7 +32,9 @@ static uint8_t bitmap[BITMAP_SIZE]; static spinlock_t bitmap_lock = SPINLOCK_INIT; static size_t alloc_start; -atomic_size_t total_usage; +atomic_size_t total_memory = 0; +atomic_size_t total_allocated_memory = 0; +atomic_size_t total_available_memory = 0; extern const void kernel_start; extern const void kernel_end; @@ -71,12 +76,40 @@ void mmu_init(void) size_t kernel_size; unsigned int i; - memset(bitmap, 0x00, sizeof(uint8_t)*BITMAP_SIZE); + /* set whole address space as occupied */ + memset(bitmap, 0xFF, sizeof(uint8_t)*BITMAP_SIZE); + +#ifdef USE_MULTIBOOT + if (mb_info) { + multiboot_memory_map_t* mmap = (multiboot_memory_map_t*) mb_info->mmap_addr; + multiboot_memory_map_t* mmap_end = (void*) ((size_t) mb_info->mmap_addr + mb_info->mmap_length); + + while (mmap < mmap_end) { + if (mmap->type == MULTIBOOT_MEMORY_AVAILABLE) { + /* set the available memory as "unused" */ + size_t addr = mmap->addr; + size_t end_addr = addr + mmap->len; + + while (addr < end_addr) { + page_unmarked(addr / PAGE_SIZE); + addr += PAGE_SIZE; + atomic_size_add(&total_memory, PAGE_SIZE); + atomic_size_add(&total_available_memory, PAGE_SIZE); + } + } + mmap++; + } + } +#else + #error Currently, MetalSVM needs multiboot! +#endif /* kernel is aligned to page size */ kernel_size = (size_t) &kernel_end - (size_t) &kernel_start; - atomic_size_set(&total_usage, kernel_size); + atomic_size_set(&total_allocated_memory, kernel_size); + atomic_size_sub(&total_available_memory, kernel_size); + /* set kernel space as used */ for(i=(size_t) &kernel_start / PAGE_SIZE; i < (size_t) &kernel_end / PAGE_SIZE; i++) page_marked(i); @@ -129,7 +162,8 @@ next_try: page_marked(l); alloc_start = i+j-1; - atomic_size_add(&total_usage, npages*PAGE_SIZE); + atomic_size_add(&total_allocated_memory, npages*PAGE_SIZE); + atomic_size_sub(&total_available_memory, npages*PAGE_SIZE); if (task) atomic_size_add(&(task->mm.usage), npages*PAGE_SIZE); oom: @@ -168,7 +202,8 @@ static void task_free(task_t* task, void* addr, size_t sz) for(i=index; imm.usage), npages*PAGE_SIZE);