初始化内存管理

master
阳光少年 1 year ago
parent 976d3a4017
commit d1c8001c2b

@ -27,6 +27,7 @@
"*.inc": "c", "*.inc": "c",
"clock.h": "c", "clock.h": "c",
"time.h": "c", "time.h": "c",
"rtc.h": "c" "rtc.h": "c",
"memory.h": "c"
} }
} }

@ -55,6 +55,7 @@ $(BUILD_PATH)/kernel.bin:$(BUILD_PATH)/kernel/start.o \
$(BUILD_PATH)/kernel/clock.o\ $(BUILD_PATH)/kernel/clock.o\
$(BUILD_PATH)/kernel/time.o\ $(BUILD_PATH)/kernel/time.o\
$(BUILD_PATH)/kernel/rtc.o\ $(BUILD_PATH)/kernel/rtc.o\
$(BUILD_PATH)/kernel/memory.o\
$(shell mkdir -p $(dir $@)) $(shell mkdir -p $(dir $@))
ld -m elf_i386 -static $^ -o $@ -Ttext $(KERNEL_ENTRY_POINT) ld -m elf_i386 -static $^ -o $@ -Ttext $(KERNEL_ENTRY_POINT)

@ -16,7 +16,7 @@ detect_memory:
; 设置检测内存的buffer位置 ; 设置检测内存的buffer位置
mov ax, 0 mov ax, 0
mov es, ax mov es, ax
mov edi, mem_task_buffer mov edi, mem_struct_buffer
; 固定签名 ; 固定签名
mov edx, 0x534d4150 mov edx, 0x534d4150
@ -25,7 +25,7 @@ detect_memory:
xor ebx, ebx xor ebx, ebx
; 保存的目的地 ; 保存的目的地
mov di, mem_task_buffer mov di, mem_struct_buffer
.next: .next:
; 子功能号 ; 子功能号
@ -40,7 +40,7 @@ detect_memory:
; 计算下一个内存结构体保存的首地址 ; 计算下一个内存结构体保存的首地址
add di, cx add di, cx
inc word [mem_task_count] inc word [mem_struct_count]
; 不为0 说明检查未完成 ; 不为0 说明检查未完成
cmp ebx, 0 cmp ebx, 0
@ -52,13 +52,13 @@ detect_memory:
ret ret
; ; 循环结构体内的值(我们只读取低32位相关的信息, 高32位的暂时不需要) ; ; 循环结构体内的值(我们只读取低32位相关的信息, 高32位的暂时不需要)
; mov cx, [mem_task_count] ; mov cx, [mem_struct_count]
; ; 初始偏移量 ; ; 初始偏移量
; mov si, 0 ; mov si, 0
; .show ; .show
; mov eax, [mem_task_buffer + si] ; 基地址 低32位 ; mov eax, [mem_struct_buffer + si] ; 基地址 低32位
; mov ebx, [mem_task_buffer + si + 8] ; 内存长度的低32位 ; mov ebx, [mem_struct_buffer + si + 8] ; 内存长度的低32位
; mov edx, [mem_task_buffer + si + 16] ; 本段内存类型 1: 可以使用, 2: 内存使用或者被保留中, 其他: 未定义 ; mov edx, [mem_struct_buffer + si + 16] ; 本段内存类型 1: 可以使用, 2: 内存使用或者被保留中, 其他: 未定义
; add si, 20 ; add si, 20
; ; xchg bx, bx ; bochs 的魔数, 代码执行到这里会停下 ; ; xchg bx, bx ; bochs 的魔数, 代码执行到这里会停下
@ -129,6 +129,9 @@ protect_mode:
mov cl, 200 mov cl, 200
call read_disk call read_disk
mov eax, 0x20220205 ; 内核魔数
mov ebx, mem_struct_count ; 内存结构体 数量统计
mov ecx, mem_struct_buffer ; 内存结构体 的起始位置
jmp dword code_selecter:0x10000 jmp dword code_selecter:0x10000
ud2 ; 执行到这里直接出错(不可能执行到这里) ud2 ; 执行到这里直接出错(不可能执行到这里)
jmp $ jmp $
@ -232,11 +235,11 @@ error:
ret ret
.error_msg db "Loader Error!!!", 10, 13, 0 .error_msg db "Loader Error!!!", 10, 13, 0
mem_task_count: mem_struct_count: ; 一共多少内存结构体
dw 0 dd 0
; 用来存放检测内存结果的结构体 ; 用来存放检测内存结果的结构体
mem_task_buffer: mem_struct_buffer:
times 20*10 db 0 times 20*10 db 0
@ -273,12 +276,9 @@ gdt_start:
db 0b_1_1_0_0_0000 | limit >> 16 ; G_D/B_L_AVL | 段界限16~19 db 0b_1_1_0_0_0000 | limit >> 16 ; G_D/B_L_AVL | 段界限16~19
db base >> 24 ; 段基址24~31 db base >> 24 ; 段基址24~31
gdt_padding: gdt_padding:
times 2<<16-($-gdt_start) db 0 times 2<<15-($-gdt_start) db 0
gdt_end: gdt_end:
loading_log: loading_log:
db 'Loader Start', 13, 10, 0 db 'Loader Start', 13, 10, 0

@ -0,0 +1,27 @@
#ifndef ONIX_MEMORY_H
#define ONIX_MEMORY_H
#include <onix/types.h>
#include <onix/onix.h>
#include <onix/printk.h>
#include <onix/assert.h>
#define PAGE_SIZE 0x1000 // 一页的大小 4K
#define MEMORY_BASE 0x100000 // 1M可用内存开始的位置
#define ZONE_VALID 1 // 可用内存区域
#define ZONE_RESERVED 2 // 不可用内存区域
#define IDX(addr) (((usize)addr) >> 12) // 获得 addr 的页索引, 每页是4k大小, 2的12次方 是4k, 地址直接除以4096就得到了地址所在页的索引
void memory_init(u32 magic, u32* addr, u8* mem_struct_buffer_addr);
typedef struct mem_struct
{
u64 base; // 内存基地址
u64 size; // 内存长度
u32 type; // 类型
} _packed mem_struct;
#endif

@ -18,4 +18,6 @@
void kernel_init(); void kernel_init();
#define ONIX_MAGIC 0x20220205 // 内核魔数, 用于校验错误
#endif #endif

@ -36,5 +36,7 @@ void cmos_write(u8 addr, u8 value);
void rtc_init(); void rtc_init();
void set_alarm(u32 secs);
#endif #endif

@ -22,8 +22,10 @@ void kernel_init(){
// 初始化时间 // 初始化时间
// time_init(); // time_init();
// 闹钟中断 // 实时时钟中断
rtc_init(); // rtc_init();
asm volatile("sti\n"); asm volatile("sti\n");

@ -0,0 +1,42 @@
#include <onix/memory.h>
static usize memory_base = 0; // 可用内存基地址,应该等于 1M
static usize memory_size = 0; // 可用内存大小
static usize total_pages = 0; // 所有内存页数
static usize free_pages = 0; // 空闲内存页数
// 找到一块最大的物理页, 且是0x10000为初始位置的
void memory_init(u32 magic, u32* mem_struct_count_addr, u8* mem_struct_buffer_addr){
u32 mem_struct_count = *mem_struct_count_addr;
if(ONIX_MAGIC != magic) {
panic("memory magic error");
}
for (usize i = 0; i < mem_struct_count; i++){
mem_struct* ms = (mem_struct*)(mem_struct_buffer_addr + sizeof(mem_struct) * i);
printk("Memory base 0x%p size 0x%p type %d\n", (u32)ms->base, (u32)ms->size, (u32)ms->type);
// 找到最大的一块内存
if (ms->type == ZONE_VALID && ms->size > memory_size) {
memory_base = (u32)ms->base;
memory_size = (u32)ms->size;
}
}
assert(memory_base == MEMORY_BASE); // 内存开始的位置为 1M
assert((memory_size & 0xfff) == 0); // 要求按页对齐
free_pages = IDX(memory_size);
total_pages = free_pages + IDX(memory_base);
printk("mem_struct_count %d\n", mem_struct_count);
printk("Memory base 0x%p\n", (u32)memory_base);
printk("Memory size 0x%p\n", (u32)memory_size);
printk("free_pages %d\n", free_pages);
printk("total_pages %d\n", total_pages);
}

@ -32,9 +32,8 @@ void rtc_handler(int handle_num)
time_read(&time); time_read(&time);
u32 now_time = mktime(&time); u32 now_time = mktime(&time);
if (next_time <= mktime(&time)) { if (next_time <= mktime(&time)) {
DEBUGK("rtc handler %d... %d %d \n", counter++, now_time, next_time); DEBUGK("rtc handler %d... %d %d", counter++, now_time, next_time);
next_time = 0xffffffff; next_time = 0xffffffff;
set_alarm(1);
} }
} }
@ -72,20 +71,22 @@ void set_alarm(u32 secs)
} }
next_time = mktime(&time); next_time = mktime(&time);
printk("set alarm...\n");
cmos_write(CMOS_B, 0b01000010); // bocsh 中无法打开闹钟中断, 未知bug, 这里使用周期中断 实现的伪闹钟
cmos_read(CMOS_C); // 读 C 寄存器,以允许 CMOS 中断
} }
void rtc_init() void rtc_init()
{ {
cmos_write(CMOS_B, 0b01000010); // 打开周期中断 // cmos_write(CMOS_B, 0b01000010); // 打开周期中断(当达到寄存器 A 中 RS 所设定的时间基准时,允许产生中断, 24小时制)
// cmos_write(CMOS_B, 0b00100010); // 打开闹钟中断 // // cmos_write(CMOS_B, 0b00100010); // 打开闹钟中断
cmos_read(CMOS_C); // 读 C 寄存器,以允许 CMOS 中断 // cmos_read(CMOS_C); // 读 C 寄存器,以允许 CMOS 中断
// 设置中断频率
out_8(CMOS_A, (in_8(CMOS_A) & 0xf) | 0b1110);
set_alarm(3); // // 设置中断频率
// out_8(CMOS_A, (in_8(CMOS_A) & 0xf) | 0b1110); // 250 ms 触发一次中断
// 设置自定义中断处理函数 // 设置自定义中断处理函数
set_interrupt_handler(IRQ_RTC, rtc_handler); set_interrupt_handler(IRQ_RTC, rtc_handler);

@ -2,13 +2,20 @@
; 导入外部符号 ; 导入外部符号
extern kernel_init extern kernel_init
extern memory_init
; 导出符号 ; 导出符号
global _start global _start
_start: _start:
call kernel_init push ecx ; 内存结构体的buffer起始位置
push ebx ; 内存结构体的数量 u32 ptr 起始位置
push eax ; magic
call memory_init ; 初始化内存
; call kernel_init
jmp $ jmp $

Loading…
Cancel
Save