Skip to content

Commit

Permalink
e820 memory info
Browse files Browse the repository at this point in the history
  • Loading branch information
BitInit committed Feb 4, 2024
1 parent df16823 commit 6b82e7c
Show file tree
Hide file tree
Showing 16 changed files with 286 additions and 5 deletions.
2 changes: 1 addition & 1 deletion arch/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ $(TARGET_ISO): clean $(kernel_target)
$(HIDE)mkdir -p build_dir/boot/grub
$(HIDE)cp $(kernel_target) build_dir/boot

$(HIDE)echo 'set timeout=1' > build_dir/boot/grub/grub.cfg
$(HIDE)echo 'set timeout=0' > build_dir/boot/grub/grub.cfg
$(HIDE)echo 'set default=0' >> build_dir/boot/grub/grub.cfg
$(HIDE)echo 'menuentry "HelloOS" {' >> build_dir/boot/grub/grub.cfg
$(HIDE)echo ' multiboot2 /boot/kernel.elf "HelloOS"' >> build_dir/boot/grub/grub.cfg
Expand Down
85 changes: 85 additions & 0 deletions arch/x86/kernel/e820.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
#include <asm/e820.h>
#include <asm/bootparam.h>

#include <os/types.h>
#include <os/kernel.h>

struct e820map e820;

static void early_panic(char *msg) {
early_printk(msg);
early_printk("\npanic in e820");
__asm__("hlt");
}

static void e820_print_map(char *who) {
int i;

for (i = 0; i < e820.nr_map; i++) {
printk(KERN_INFO " %s: %016Lx - %016Lx ", who,
(unsigned long long) e820.map[i].addr,
(unsigned long long)
(e820.map[i].addr + e820.map[i].size));
switch (e820.map[i].type) {
case E820_RAM:
printk(KERN_CONT "(usable)\n");
break;
case E820_RESERVED:
printk(KERN_CONT "(reserved)\n");
break;
case E820_ACPI:
printk(KERN_CONT "(ACPI data)\n");
break;
case E820_NVS:
printk(KERN_CONT "(ACPI NVS)\n");
break;
default:
printk(KERN_CONT "type %u\n", e820.map[i].type);
break;
}
}
}

static int copy_e820_map(struct e820entry *biosmap, int nr_map) {
if (nr_map < 2) {
return -1;
}

do {
uint64_t start = biosmap->addr;
uint64_t size = biosmap->size;
uint64_t end = start + size;
uint32_t type = biosmap->type;

/* Overflow in 64 bits? Ignore the memory map. */
if (start > end)
return -1;
int x = e820.nr_map;

if (x == E820MAX) {
printk(KERN_ERR "Ooops! Too many entries in the memory map!\n");
return;
}

e820.map[x].addr = start;
e820.map[x].size = size;
e820.map[x].type = type;
e820.nr_map++;
} while (biosmap++, --nr_map);
return 0;
}

char *machine_specific_memory_setup() {
char *who = "BIOS-e820";

// e820 数组中,可能存在某些内存段重复,需要将重复的部分分离;
// 而我们暂不处理这种情况,认为 multiboot2 中的内存段不存在重复。
// 复制 e820 信息
if (copy_e820_map(boot_params.e820_map, boot_params.e820_entries) < 0) {
early_panic("Cannot find a valid memory map");
}
printk(KERN_INFO "BIOS-provided physical RAM map:\n");

e820_print_map(who);
return who;
}
40 changes: 38 additions & 2 deletions arch/x86/kernel/head64.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,53 @@
#include <os/start_kernel.h>
#include <os/kernel.h>

#include <asm/bootparam.h>
#include <asm/multiboot2.h>

extern uint64_t mb2_info;

void clear_bss() {
memset(__bss_start, 0,
(unsigned long) __bss_stop - (unsigned long) __bss_start);
}

static void mem_info(struct multiboot_tag *tag) {
struct multiboot_tag_mmap *mmap = (struct multiboot_tag_mmap*) tag;
struct multiboot_mmap_entry *entry = mmap->entries;

void x86_64_start_kernel() {
early_printk("x86_64_start_kernel running...");
uint32_t i = 0;
while ((uint8_t*)entry < (uint8_t*)mmap + mmap->size) {
boot_params.e820_map[i].addr = entry->addr;
boot_params.e820_map[i].size = entry->len;
boot_params.e820_map[i].type = entry->type;

i++;
entry = (struct multiboot_mmap_entry*)((uint8_t*)entry + mmap->entry_size);
}
boot_params.e820_entries = i;
}

void parse_sys_info() {
struct multiboot_tag *tag;
for (tag = (struct multiboot_tag*)(mb2_info + MULTIBOOT_TAG_ALIGN);
tag->type != MULTIBOOT_TAG_TYPE_END;
tag = (struct multiboot_tag*)((multiboot_uint8_t *)tag + ((tag->size + 7) & ~7))) {
switch (tag->type) {
case MULTIBOOT_TAG_TYPE_MMAP:
mem_info(tag);
break;
default:
break;
}
}
}

void x86_64_start_kernel() {
early_printk("x86_64_start_kernel running\n");
// bss 段清零
clear_bss();
// 解析系统信息
parse_sys_info();

start_kernel();
}
4 changes: 4 additions & 0 deletions arch/x86/kernel/head_64.S
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
.global startup_64
.extern print
startup_64:
mov %ebx, mb2_info

/* 开启 PAE */
movl %cr4, %eax
btsl $5, %eax
Expand Down Expand Up @@ -63,6 +65,8 @@ secondary_startup_64:

ENTRY(init_rsp)
.quad init_thread_union+THREAD_SIZE-8
ENTRY(mb2_info)
.quad 0x00

.text
.code64
Expand Down
13 changes: 13 additions & 0 deletions arch/x86/kernel/setup.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#include <asm/bootparam.h>

#include <os/init.h>

struct boot_params boot_params;

void memory_setup() {
machine_specific_memory_setup();
}

void setup_arch() {
memory_setup();
}
13 changes: 13 additions & 0 deletions include/asm/bootparam.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#ifndef _ASM_X86_BOOTPARAM_H
#define _ASM_X86_BOOTPARAM_H

#include <asm/e820.h>

struct boot_params {
__u32 e820_entries;
struct e820entry e820_map[E820MAX];
};

extern struct boot_params boot_params;

#endif
67 changes: 67 additions & 0 deletions include/asm/desc.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
#ifndef _ASM_X86_DESC_H
#define _ASM_X86_DESC_H

#include <os/types.h>
#include <os/string.h>

#include <asm/segment.h>

#define PTR_LOW(x) ((unsigned long long)(x) & 0xFFFF)
#define PTR_MIDDLE(x) (((unsigned long long)(x) >> 16) & 0xFFFF)
#define PTR_HIGH(x) ((unsigned long long)(x) >> 32)

extern gate_desc idt_table[];

struct gate_struct64 {
uint16_t offset_low;
uint16_t segment;
unsigned ist : 3, zero0 : 5, type : 5, dpl : 2, p : 1;
uint16_t offset_middle;
uint32_t offset_high;
uint32_t zero1;
} __attribute__((packed));

typedef struct gate_struct64 gate_desc;

enum {
GATE_INTERRUPT = 0xE,
GATE_TRAP = 0xF,
GATE_CALL = 0xC,
GATE_TASK = 0x5,
};

static inline void pack_gate(gate_desc *gate, unsigned type, unsigned long func,
unsigned dpl, unsigned ist, unsigned seg) {
gate->offset_low = PTR_LOW(func);
gate->segment = __KERNEL_CS;
gate->ist = ist;
gate->p = 1;
gate->dpl = dpl;
gate->zero0 = 0;
gate->zero1 = 0;
gate->type = type;
gate->offset_middle = PTR_MIDDLE(func);
gate->offset_high = PTR_HIGH(func);
}

static inline void write_idt_entry(gate_desc *idt, int entry,
const gate_desc *gate) {
memcpy(&idt[entry], gate, sizeof(*gate));
}

static inline void _set_gate(int gate, unsigned type, void *addr,
unsigned dpl, unsigned ist, unsigned seg) {
gate_desc s;
pack_gate(&s, type, (unsigned long)addr, dpl, ist, seg);
/*
* does not need to be atomic because it is only done once at
* setup time
*/
write_idt_entry(idt_table, gate, &s);
}

static inline void set_intr_gate(unsigned int n, void *addr) {
_set_gate(n, GATE_INTERRUPT, addr, 0, 0, __KERNEL_CS);
}

#endif
13 changes: 12 additions & 1 deletion include/asm/e820.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,23 @@

#include <os/ioport.h>

#define E820MAX 128

#define E820_RAM 1
#define E820_RESERVED 2
#define E820_ACPI 3
#define E820_NVS 4

struct e820entry {
__u64 addr; /* start of memory segment */
__u64 size; /* size of memory segment */
__u32 type; /* type of memory segment */
} __attribute__((packed));

struct e820map {
__u32 nr_map;
struct e820entry map[E820MAX];
};


extern struct e820map e820;
#endif
2 changes: 2 additions & 0 deletions include/asm/page.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@
#define KERNEL_IMAGE_SIZE (512 * 1024 * 1024)
#define KERNEL_IMAGE_START _AC(0xffffffff80000000, UL)

#define __pa(x) ((unsigned long)(x)-PAGE_OFFSET)
#define __va(x) ((void *)((unsigned long)(x)+PAGE_OFFSET))


#endif
6 changes: 6 additions & 0 deletions include/asm/setup.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#ifndef _ASM_X86_SETUP_H
#define _ASM_X86_SETUP_H

char *machine_specific_memory_setup();

#endif
7 changes: 7 additions & 0 deletions include/os/init.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#ifndef _OS_INIT_H
#define _OS_INIT_H

void setup_arch();


#endif
17 changes: 17 additions & 0 deletions include/os/kernel.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,17 @@
#include <stdarg.h>
#include <os/types.h>

#define KERN_EMERG "<0>" /* system is unusable */
#define KERN_ALERT "<1>" /* action must be taken immediately */
#define KERN_CRIT "<2>" /* critical conditions */
#define KERN_ERR "<3>" /* error conditions */
#define KERN_WARNING "<4>" /* warning conditions */
#define KERN_NOTICE "<5>" /* normal but significant condition */
#define KERN_INFO "<6>" /* informational */
#define KERN_DEBUG "<7>" /* debug-level messages */

#define KERN_CONT ""

extern void __attribute__((format(printf, 1, 2)))
early_printk(const char *fmt, ...);

Expand All @@ -13,4 +24,10 @@ extern int vscnprintf(char *buf, size_t size, const char *fmt, va_list args)
extern int vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
__attribute__ ((format (printf, 3, 0)));

// extern int printk(const char * fmt, ...)
// __attribute__((format (printf, 1, 2)));
#define printk(...) { \
early_printk(__VA_ARGS__); \
}

#endif
4 changes: 4 additions & 0 deletions include/os/string.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,8 @@ extern void *memset(void *,int,__kernel_size_t);
extern __kernel_size_t strnlen(const char *,__kernel_size_t);
#endif

#ifndef __HAVE_ARCH_MEMCPY
extern void* memcpy(void *dest, const void *src, size_t count);
#endif

#endif
5 changes: 4 additions & 1 deletion init/main.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@

#include <os/init.h>

void start_kernel() {

setup_arch();

__asm__ __volatile__("hlt");
}

1 change: 1 addition & 0 deletions kernel/printk.c
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
#include <os/kernel.h>
12 changes: 12 additions & 0 deletions lib/string.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,16 @@ __kernel_size_t strnlen(const char *s, __kernel_size_t count) {
/* nothing */;
return sc - s;
}
#endif

#ifndef __HAVE_ARCH_MEMCPY
void *memcpy(void *dest, const void *src, size_t count)
{
char *tmp = dest;
const char *s = src;

while (count--)
*tmp++ = *s++;
return dest;
}
#endif

0 comments on commit 6b82e7c

Please sign in to comment.