Reimplement e820 support

This commit is contained in:
Baptiste Wicht 2013-12-16 21:31:23 +01:00
parent 0c30f2ef46
commit 0d0ab18b45
5 changed files with 192 additions and 3 deletions

56
kernel/include/e820.hpp Normal file
View File

@ -0,0 +1,56 @@
//=======================================================================
// Copyright Baptiste Wicht 2013.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================
/*
* The implementation of the memory detection is made in boot_16.cpp
* The finalization of the memory detection is made in e820.cpp once in long
* mode.
*/
#ifndef CODE_16
#include "types.hpp"
#endif
#ifndef E820_HPP
#define E820_HPP
namespace e820 {
constexpr const uint32_t MAX_E820_ENTRIES = 25;
struct bios_e820_entry {
uint32_t base_low;
uint32_t base_high;
uint32_t length_low;
uint32_t length_high;
uint16_t type;
uint16_t acpi;
// uint32_t damn_padding;
} __attribute__((packed));
extern int16_t bios_e820_entry_count;
extern bios_e820_entry bios_e820_entries[MAX_E820_ENTRIES];
struct mmapentry {
uint64_t base;
uint64_t size;
uint64_t type;
};
//Must be called by the kernel to transform e820 entries into mmap entries
void finalize_memory_detection();
bool mmap_failed();
uint64_t mmap_entry_count();
const mmapentry& mmap_entry(uint64_t i);
const char* str_e820_type(uint64_t type);
size_t available_memory();
} //end of namespace e820
#endif

View File

@ -14,11 +14,14 @@ typedef unsigned int uint32_t __attribute__ ((__mode__ (__SI__)));
typedef unsigned int uint32_t __attribute__ ((__mode__ (__SI__)));
typedef unsigned int uint64_t __attribute__ ((__mode__ (__DI__)));
typedef unsigned int int16_t __attribute__ ((__mode__ (__HI__)));
typedef uint64_t uintptr_t;
typedef uint64_t size_t;
static_assert(sizeof(uint8_t) == 1, "uint32_t must be 1 byte long");
static_assert(sizeof(uint16_t) == 2, "uint32_t must be 2 bytes long");
static_assert(sizeof(uint8_t) == 1, "uint8_t must be 1 byte long");
static_assert(sizeof(uint16_t) == 2, "uint16_t must be 2 bytes long");
static_assert(sizeof(int16_t) == 2, "int16_t must be 2 bytes long");
static_assert(sizeof(uint32_t) == 4, "uint32_t must be 4 bytes long");
static_assert(sizeof(uint64_t) == 8, "uint64_t must be 8 bytes long");
static_assert(sizeof(size_t) == 8, "size_t must be 8 bytes long");

View File

@ -12,14 +12,27 @@ namespace {
typedef unsigned int uint8_t __attribute__((__mode__(__QI__)));
typedef unsigned int uint16_t __attribute__ ((__mode__ (__HI__)));
typedef int int16_t __attribute__ ((__mode__ (__HI__)));
typedef unsigned int uint32_t __attribute__ ((__mode__ (__SI__)));
typedef unsigned int uint64_t __attribute__ ((__mode__ (__DI__)));
static_assert(sizeof(uint8_t) == 1, "uint8_t must be 1 byte long");
static_assert(sizeof(uint16_t) == 2, "uint16_t must be 2 bytes long");
static_assert(sizeof(int16_t) == 2, "int16_t must be 2 bytes long");
static_assert(sizeof(uint32_t) == 4, "uint32_t must be 4 bytes long");
static_assert(sizeof(uint64_t) == 8, "uint64_t must be 8 bytes long");
//Just here to be able to compile e820.hpp, should not be
//used in boot_16.cpp
typedef uint64_t size_t;
} //end of anonymous namespace
#define CODE_16
#include "e820.hpp" //Just for the address of the e820 map
namespace {
struct gdt_ptr {
uint16_t length;
uint32_t pointer;
@ -43,6 +56,41 @@ void reset_segments(){
set_ds(0);
}
int detect_memory_e820(){
auto* smap = &e820::bios_e820_entries[0];
uint16_t entries = 0;
uint32_t contID = 0;
int signature;
int bytes;
do {
asm volatile ("int 0x15"
: "=a"(signature), "=c"(bytes), "=b"(contID)
: "a"(0xE820), "b"(contID), "c"(24), "d"(0x534D4150), "D"(smap));
if (signature != 0x534D4150){
return -1;
}
if (bytes > 20 && (smap->acpi & 0x0001) == 0){
// ignore this entry
} else {
smap++;
entries++;
}
} while (contID != 0 && entries < e820::MAX_E820_ENTRIES);
return entries;
}
void detect_memory(){
//TODO If e820 fails, try other solutions to get memory map
e820::bios_e820_entry_count = detect_memory_e820();
}
void disable_interrupts(){
__asm__ __volatile__ ("cli");
}
@ -181,7 +229,8 @@ void __attribute__ ((noreturn)) rm_main(){
//Make sure segments are clean
reset_segments();
//TODO Detect memory
//Analyze memory
detect_memory();
//Disable interrupts
disable_interrupts();

78
kernel/src/e820.cpp Normal file
View File

@ -0,0 +1,78 @@
//=======================================================================
// Copyright Baptiste Wicht 2013.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================
#include "e820.hpp"
e820::bios_e820_entry e820::bios_e820_entries[e820::MAX_E820_ENTRIES];
int16_t e820::bios_e820_entry_count = 0;
namespace {
e820::mmapentry e820_mmap[e820::MAX_E820_ENTRIES];
size_t _available_memory;
} //end of namespace anonymous
void e820::finalize_memory_detection(){
if(!mmap_failed()){
for(uint64_t i = 0; i < bios_e820_entry_count; ++i){
auto& bios_entry = bios_e820_entries[i];
auto& os_entry = e820_mmap[i];
uint64_t base = bios_entry.base_low + (static_cast<uint64_t>(bios_entry.base_high) << 32);
uint64_t length = bios_entry.length_low + (static_cast<uint64_t>(bios_entry.length_high) << 32);
os_entry.base = base;
os_entry.size = length;
os_entry.type = bios_entry.type;
if(os_entry.base == 0 && os_entry.type == 1){
os_entry.type = 7;
}
if(os_entry.type == 1){
_available_memory += os_entry.size;
}
}
}
}
uint64_t e820::mmap_entry_count(){
return bios_e820_entry_count;
}
bool e820::mmap_failed(){
return bios_e820_entry_count <= 0;
}
const e820::mmapentry& e820::mmap_entry(uint64_t i){
return e820_mmap[i];
}
const char* e820::str_e820_type(uint64_t type){
switch(type){
case 1:
return "Free";
case 2:
return "Reserved";
case 3:
case 4:
return "ACPI";
case 5:
return "Unusable";
case 6:
return "Disabled";
case 7:
return "Kernel";
default:
return "Unknown";
}
}
size_t e820::available_memory(){
return _available_memory;
}

View File

@ -14,6 +14,7 @@
#include "acpi.hpp"
#include "interrupts.hpp"
#include "arch.hpp"
#include "e820.hpp"
extern "C" {
@ -22,6 +23,8 @@ void _init();
void kernel_main(){
arch::enable_sse();
e820::finalize_memory_detection();
interrupt::install_idt();
interrupt::install_isrs();
interrupt::remap_irqs();