ARCH_OPT := -D__ARCH_IA32
O := -O2
-W := -Wall -Wextra
+W := -Wall -Wextra -Wno-unknown-pragmas
CFLAGS := -std=gnu99 -ffreestanding $(O) $(W) $(ARCH_OPT)
LDFLAGS := -ffreestanding $(O) -nostdlib -lgcc
\ No newline at end of file
void cpu_get_model(char* model_out) {
uint32_t* out = (uint32_t*)model_out;
- reg32 eax, ebx, edx, ecx;
+ reg32 eax = 0, ebx = 0, edx = 0, ecx = 0;
__get_cpuid(0, &eax, &ebx, &ecx, &edx);
brand_out[1] = '\0';
}
uint32_t* out = (uint32_t*) brand_out;
- reg32 eax, ebx, edx, ecx;
+ reg32 eax = 0, ebx = 0, edx = 0, ecx = 0;
for (uint32_t i = 2, j = 0; i < 5; i++)
{
__get_cpuid(BRAND_LEAF + i, &eax, &ebx, &ecx, &edx);
brand_out[48] = '\0';
}
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wreturn-type"
reg32 cpu_r_cr0() {
asm volatile ("mov %cr0, %eax");
}
reg32 cpu_r_cr3() {
asm volatile ("mov %cr3, %eax");
}
+#pragma GCC diagnostic push
void cpu_w_cr0(reg32 v) {
asm volatile (
#ifndef __LUNAIX_CPU_H
#define __LUNAIX_CPU_H
-typedef unsigned long reg32;
+typedef unsigned int reg32;
typedef unsigned short reg16;
typedef struct {
// 用来获取特定的页表的虚拟地址
#define PT_VADDR(pd_offset) (PT_BASE_VADDR | (pd_offset << 12))
-typedef unsigned int ptd_t;
-typedef unsigned int pt_t;
+typedef unsigned long ptd_t;
+typedef unsigned long pt_t;
typedef unsigned int pt_attr;
#include <libc/stdio.h>
void isr0 (isr_param* param) {
- tty_clear();
printf("[PANIC] Exception (%d) CS=0x%X, EIP=0x%X", param->vector, param->cs, param->eip);
}
#include <libc/stdio.h>
-extern void __kernel_start;
-extern void __kernel_end;
-extern void __init_hhk_end;
+extern uint8_t __kernel_start;
+extern uint8_t __kernel_end;
+extern uint8_t __init_hhk_end;
void
_kernel_init(multiboot_info_t* mb_info)
#pragma region INIT_MM
// 初始化物理内存管理器
- pmm_init(MEM_1MB + mb_info->mem_upper << 10);
+ pmm_init(MEM_1MB + (mb_info->mem_upper << 10));
vmm_init();
#pragma endregion
// 初始化VGA
- tty_init(VGA_BUFFER_PADDR);
+ tty_init((void*)VGA_BUFFER_PADDR);
tty_set_theme(VGA_COLOR_GREEN, VGA_COLOR_BLACK);
printf("[KERNEL] === Initialization === \n");
// 重映射VGA文本缓冲区(以后会变成显存,i.e., framebuffer)
for (size_t i = 0; i < vga_buf_pgs; i++)
{
- vmm_map_page(VGA_BUFFER_VADDR + (i << 12), VGA_BUFFER_PADDR + (i << 12), PG_PREM_RW, PG_PREM_RW);
+ vmm_map_page(
+ (void*)(VGA_BUFFER_VADDR + (i << 12)),
+ (void*)(VGA_BUFFER_PADDR + (i << 12)),
+ PG_PREM_RW, PG_PREM_RW
+ );
}
// 更新VGA缓冲区位置至虚拟地址
- tty_set_buffer(VGA_BUFFER_VADDR);
+ tty_set_buffer((void*)VGA_BUFFER_VADDR);
printf("[MM] Mapped VGA to %p.\n", VGA_BUFFER_VADDR);
// 为内核创建一个专属栈空间。
for (size_t i = 0; i < (K_STACK_SIZE >> 12); i++) {
- vmm_alloc_page(K_STACK_START + (i << 12), PG_PREM_RW, PG_PREM_RW);
+ vmm_alloc_page((void*)(K_STACK_START + (i << 12)), PG_PREM_RW, PG_PREM_RW);
}
printf("[MM] Allocated %d pages for stack start at %p\n", K_STACK_SIZE>>12, K_STACK_START);
// 清除 hhk_init 与前1MiB的映射
for (size_t i = 0; i < hhk_init_pg_count; i++) {
- vmm_unmap_page((i << 12));
+ vmm_unmap_page((void*)(i << 12));
}
printf("[KERNEL] === Post Initialization Done === \n\n");
}
void
_kernel_main()
{
- char* buf[64];
+ char buf[64];
printf("Hello higher half kernel world!\nWe are now running in virtual "
"address space!\n\n");
cpu_get_brand(buf);
printf("CPU: %s\n\n", buf);
- uintptr_t k_start = vmm_v2p(&__kernel_start);
+ void* k_start = vmm_v2p(&__kernel_start);
printf("The kernel's base address mapping: %p->%p\n", &__kernel_start, k_start);
// __asm__("int $0\n");
}
\ No newline at end of file
pmm_alloc_page()
{
// Next fit approach. Maximize the throughput!
- uintptr_t good_page_found = NULL;
+ uintptr_t good_page_found = (uintptr_t)NULL;
size_t old_pg_ptr = pg_lookup_ptr;
size_t upper_lim = max_pg;
uint8_t chunk = 0;
+#include <libc/string.h>
#include <lunaix/mm/page.h>
-#include <lunaix/mm/vmm.h>
#include <lunaix/mm/pmm.h>
-#include <libc/string.h>
+#include <lunaix/mm/vmm.h>
// TODO: Move these nasty inline asm stuff into hal
// These should be arch dependent
-ptd_t* get_pd() {
+ptd_t*
+get_pd()
+{
ptd_t* pd;
- #ifdef __ARCH_IA32
- __asm__(
- "movl %%cr3, %0\n"
- "andl $0xfffff000, %0"
- : "=r"(pd)
- );
- #endif
- return P2V(pd);
+#ifdef __ARCH_IA32
+ __asm__("movl %%cr3, %0\n"
+ "andl $0xfffff000, %0"
+ : "=r"(pd));
+#endif
+ return (ptd_t*)P2V(pd);
}
-void set_pd(ptd_t* pd) {
- #ifdef __ARCH_IA32
- __asm__(
- "movl %0, %%eax\n"
- "andl $0xfffff000, %%eax\n"
- "movl %%eax, %%cr3\n"
- :
- : "r" (pd)
- );
- #endif
+void
+set_pd(ptd_t* pd)
+{
+#ifdef __ARCH_IA32
+ __asm__("movl %0, %%eax\n"
+ "andl $0xfffff000, %%eax\n"
+ "movl %%eax, %%cr3\n"
+ :
+ : "r"(pd));
+#endif
}
-void vmm_init() {
+void
+vmm_init()
+{
// TODO: something here?
}
-ptd_t* vmm_init_pd() {
+ptd_t*
+vmm_init_pd()
+{
ptd_t* dir = pmm_alloc_page();
- for (size_t i = 0; i < 1024; i++)
- {
+ for (size_t i = 0; i < 1024; i++) {
dir[i] = 0;
}
-
+
// 自己映射自己,方便我们在软件层面进行查表地址转换
dir[1023] = PDE(T_SELF_REF_PERM, dir);
return dir;
}
-void* vmm_map_page(void* va, void* pa, pt_attr dattr, pt_attr tattr) {
+void*
+vmm_map_page(void* va, void* pa, pt_attr dattr, pt_attr tattr)
+{
// 显然,对空指针进行映射没有意义。
if (!pa || !va) {
return NULL;
ptd_t* ptd = (ptd_t*)PTD_BASE_VADDR;
// 在页表与页目录中找到一个可用的空位进行映射(位于va或其附近)
- ptd_t* pde = ptd[pd_offset];
- pt_t* pt = (uintptr_t)PT_VADDR(pd_offset);
+ ptd_t pde = ptd[pd_offset];
+ pt_t* pt = (pt_t*)PT_VADDR(pd_offset);
while (pde && pd_offset < 1024) {
if (pt_offset == 1024) {
pd_offset++;
// 页表有空位,只需要开辟一个新的 PTE
if (pt && !pt[pt_offset]) {
pt[pt_offset] = PTE(tattr, pa);
- return V_ADDR(pd_offset, pt_offset, PG_OFFSET(va));
+ return (void*)V_ADDR(pd_offset, pt_offset, PG_OFFSET(va));
}
pt_offset++;
}
-
+
// 页目录与所有页表已满!
if (pd_offset > 1024) {
return NULL;
// 页目录有空位,需要开辟一个新的 PDE
uint8_t* new_pt_pa = pmm_alloc_page();
-
+
// 物理内存已满!
if (!new_pt_pa) {
return NULL;
}
-
+
ptd[pd_offset] = PDE(dattr, new_pt_pa);
-
+
memset((void*)PT_VADDR(pd_offset), 0, PM_PAGE_SIZE);
pt[pt_offset] = PTE(tattr, pa);
- return V_ADDR(pd_offset, pt_offset, PG_OFFSET(va));
+ return (void*)V_ADDR(pd_offset, pt_offset, PG_OFFSET(va));
}
-void* vmm_alloc_page(void* vpn, pt_attr dattr, pt_attr tattr) {
+void*
+vmm_alloc_page(void* vpn, pt_attr dattr, pt_attr tattr)
+{
void* pp = pmm_alloc_page();
void* result = vmm_map_page(vpn, pp, dattr, tattr);
if (!result) {
return result;
}
-void vmm_unmap_page(void* vpn) {
+void
+vmm_unmap_page(void* vpn)
+{
uintptr_t pd_offset = PD_INDEX(vpn);
uintptr_t pt_offset = PT_INDEX(vpn);
- ptd_t* self_pde = PTD_BASE_VADDR;
+ ptd_t* self_pde = (ptd_t*)PTD_BASE_VADDR;
ptd_t pde = self_pde[pd_offset];
if (pde) {
pt_t* pt = (pt_t*)PT_VADDR(pd_offset);
uint32_t pte = pt[pt_offset];
- if (IS_CACHED(pte) && pmm_free_page(pte)) {
- // 刷新TLB
- #ifdef __ARCH_IA32
- __asm__("invlpg (%0)" :: "r"((uintptr_t)vpn) : "memory");
- #endif
+ if (IS_CACHED(pte) && pmm_free_page((void*)pte)) {
+// 刷新TLB
+#ifdef __ARCH_IA32
+ __asm__("invlpg (%0)" ::"r"((uintptr_t)vpn) : "memory");
+#endif
}
pt[pt_offset] = 0;
}
}
-void* vmm_v2p(void* va) {
+void*
+vmm_v2p(void* va)
+{
uintptr_t pd_offset = PD_INDEX(va);
uintptr_t pt_offset = PT_INDEX(va);
uintptr_t po = PG_OFFSET(va);
- ptd_t* self_pde = PTD_BASE_VADDR;
+ ptd_t* self_pde = (ptd_t*)PTD_BASE_VADDR;
ptd_t pde = self_pde[pd_offset];
if (pde) {
__uitoa_internal(unsigned int value, char* str, int base, unsigned int* size)
{
unsigned int ptr = 0;
- if (value == 0) {
- str[0] = '0';
+ do {
+ str[ptr] = base_char[value % base];
+ value = value / base;
ptr++;
- } else {
- while (value) {
- str[ptr] = base_char[value % base];
- value = value / base;
- ptr++;
- }
-
- for (unsigned int i = 0; i < (ptr >> 1); i++) {
- char c = str[i];
- str[i] = str[ptr - i - 1];
- str[ptr - i - 1] = c;
- }
+ } while (value);
+ for (unsigned int i = 0; i < (ptr >> 1); i++) {
+ char c = str[i];
+ str[i] = str[ptr - i - 1];
+ str[ptr - i - 1] = c;
}
str[ptr] = '\0';
if (size) {
$(OBJECT_DIR)/%.S.o: %.S
@mkdir -p $(@D)
- @echo "Compiling: $< -> $@"
+ @echo "$@"
@$(CC) $(INCLUDES) -c $< -o $@
$(OBJECT_DIR)/%.c.o: %.c
@mkdir -p $(@D)
- @echo "Compiling: $< -> $@"
+ @echo "$@"
@$(CC) $(INCLUDES) -c $< -o $@ $(CFLAGS)
$(BIN_DIR)/$(OS_BIN): $(OBJECT_DIR) $(BIN_DIR) $(SRC)
- @echo "Linking ..."
+ @echo "Generating $(BIN_DIR)/$(OS_BIN)"
@$(CC) -T linker.ld -o $(BIN_DIR)/$(OS_BIN) $(SRC) $(LDFLAGS)
$(BUILD_DIR)/$(OS_ISO): $(ISO_DIR) $(BIN_DIR)/$(OS_BIN) GRUB_TEMPLATE