#ifndef __LUNAIX_INTERRUPTS_H
#define __LUNAIX_INTERRUPTS_H
-#define FAULT_DIVISION_ERROR 0x0
-#define FAULT_TRAP_DEBUG_EXCEPTION 0x1
-#define INT_NMI 0x2
-#define TRAP_BREAKPOINT 0x3
-#define TRAP_OVERFLOW 0x4
-#define FAULT_BOUND_EXCEED 0x5
-#define FAULT_INVALID_OPCODE 0x6
-#define FAULT_NO_MATH_PROCESSOR 0x7
-#define ABORT_DOUBLE_FAULT 0x8
-#define FAULT_RESERVED_0 0x9
-#define FAULT_INVALID_TSS 0xa
-#define FAULT_SEG_NOT_PRESENT 0xb
-#define FAULT_STACK_SEG_FAULT 0xc
-#define FAULT_GENERAL_PROTECTION 0xd
-#define FAULT_PAGE_FAULT 0xe
-#define FAULT_RESERVED_1 0xf
-#define FAULT_X87_FAULT 0x10
-#define FAULT_ALIGNMENT_CHECK 0x11
-#define ABORT_MACHINE_CHECK 0x12
-#define FAULT_SIMD_FP_EXCEPTION 0x13
-#define FAULT_VIRTUALIZATION_EXCEPTION 0x14
-#define FAULT_CONTROL_PROTECTION 0x15
+#define FAULT_DIVISION_ERROR 0
+#define FAULT_TRAP_DEBUG_EXCEPTION 1
+#define INT_NMI 2
+#define TRAP_BREAKPOINT 3
+#define TRAP_OVERFLOW 4
+#define FAULT_BOUND_EXCEED 5
+#define FAULT_INVALID_OPCODE 6
+#define FAULT_NO_MATH_PROCESSOR 7
+#define ABORT_DOUBLE_FAULT 8
+#define FAULT_RESERVED_0 9
+#define FAULT_INVALID_TSS 10
+#define FAULT_SEG_NOT_PRESENT 11
+#define FAULT_STACK_SEG_FAULT 12
+#define FAULT_GENERAL_PROTECTION 13
+#define FAULT_PAGE_FAULT 14
+#define FAULT_RESERVED_1 15
+#define FAULT_X87_FAULT 16
+#define FAULT_ALIGNMENT_CHECK 17
+#define ABORT_MACHINE_CHECK 18
+#define FAULT_SIMD_FP_EXCEPTION 19
+#define FAULT_VIRTUALIZATION_EXCEPTION 20
+#define FAULT_CONTROL_PROTECTION 21
+
+#define LUNAIX_SYS_PANIC 32
+
+#ifndef __ASM__
+#include <hal/cpu.h>
typedef struct {
+ gp_regs registers;
unsigned int vector;
unsigned int err_code;
unsigned int eip;
void
_asm_isr0();
+void
+_asm_isr1();
+
+void
+_asm_isr2();
+
+void
+_asm_isr3();
+
+void
+_asm_isr4();
+
+void
+_asm_isr5();
+
+void
+_asm_isr6();
+
+void
+_asm_isr7();
+
+void
+_asm_isr8();
+
+void
+_asm_isr9();
+
+void
+_asm_isr10();
+
+void
+_asm_isr11();
+
+void
+_asm_isr12();
+
void
_asm_isr13();
void
_asm_isr14();
+void
+_asm_isr15();
+
+void
+_asm_isr16();
+
+void
+_asm_isr17();
+
+void
+_asm_isr18();
+
+void
+_asm_isr19();
+
+void
+_asm_isr20();
+
+void
+_asm_isr21();
+
+
+void
+_asm_isr32();
+
void
interrupt_handler(isr_param* param);
+#endif
+
#endif /* __LUNAIX_INTERRUPTS_H */
typedef unsigned int reg32;
typedef unsigned short reg16;
-typedef struct {
+typedef struct
+{
reg32 eax;
reg32 ebx;
reg32 ecx;
reg32 ebp;
reg32 esi;
reg32 esp;
- reg32 cs;
- reg32 eip;
-} __attribute__((packed)) registers;
+} __attribute__((packed)) gp_regs;
+
+typedef struct
+{
+ reg16 ss;
+ reg16 es;
+ reg16 ds;
+ reg16 fs;
+ reg16 gs;
+ reg16 cs;
+} __attribute__((packed)) sg_reg;
+
+void
+cpu_get_brand(char* brand_out);
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wreturn-type"
-static inline reg32 cpu_rcr0() {
- asm volatile ("mov %cr0, %eax");
+static inline reg32
+cpu_rcr0()
+{
+ asm("mov %cr0, %eax");
}
-static inline reg32 cpu_rcr2() {
- asm volatile ("mov %cr2, %eax");
+static inline reg32
+cpu_rcr2()
+{
+ asm("mov %cr2, %eax");
}
-static inline reg32 cpu_rcr3() {
- asm volatile ("mov %cr3, %eax");
+static inline reg32
+cpu_rcr3()
+{
+ asm("mov %cr3, %eax");
}
#pragma GCC diagnostic pop
-static inline void cpu_lcr0(reg32 v) {
- asm volatile (
- "mov %0, %%cr0"
- :: "r"(v)
- );
+static inline void
+cpu_lcr0(reg32 v)
+{
+ asm("mov %0, %%cr0" ::"r"(v));
+}
+
+static inline void
+cpu_lcr2(reg32 v)
+{
+ asm("mov %0, %%cr2" ::"r"(v));
+}
+
+static inline void
+cpu_lcr3(reg32 v)
+{
+ asm("mov %0, %%cr3" ::"r"(v));
}
-static inline void cpu_lcr2(reg32 v) {
- asm volatile (
- "mov %0, %%cr2"
- :: "r"(v)
- );
+static inline void
+cpu_invplg(void* va)
+{
+ asm("invlpg (%0)" ::"r"((uintptr_t)va) : "memory");
}
-static inline void cpu_lcr3(reg32 v) {
- asm volatile (
- "mov %0, %%cr3"
- :: "r"(v)
- );
+static inline void
+cpu_enable_interrupt()
+{
+ asm("sti");
}
-static inline void cpu_invplg(void* va) {
- __asm__("invlpg (%0)" ::"r"((uintptr_t)va) : "memory");
+static inline void
+cpu_disable_interrupt()
+{
+ asm("cli");
}
-static inline void cpu_invtlb() {
+static inline void
+cpu_invtlb()
+{
reg32 interm;
- __asm__(
- "movl %%cr3, %0\n"
+ asm("movl %%cr3, %0\n"
"movl %0, %%cr3"
- :"=r"(interm)
- :"r"(interm)
- );
+ : "=r"(interm)
+ : "r"(interm));
}
#endif
\ No newline at end of file
char*
strcpy(char* dest, const char* src);
+size_t
+strnlen(const char* str, size_t max_len);
+
+const char*
+strchr(const char* str, int character);
+
#endif /* __LUNAIX_STRING_H */
+++ /dev/null
-#ifndef __LUNAIX_ASSERT_H
-#define __LUNAIX_ASSERT_H
-
-#include <libc/stdio.h>
-#include <lunaix/tty/tty.h>
-
-#ifdef __LUNAIXOS_DEBUG__
-#define assert(cond) \
- if (!(cond)) { \
- __assert_fail(#cond, __FILE__, __LINE__); \
- }
-#else
-#define assert(cond) //nothing
-#endif
-
-
-void __assert_fail(const char* expr, const char* file, unsigned int line) __attribute__((noinline, noreturn));
-
-#endif /* __LUNAIX_ASSERT_H */
#define PG_LAST_TABLE PG_MAX_ENTRIES - 1
#define PG_FIRST_TABLE 0
+#define PTE_NULL 0
+
#define P2V(paddr) ((uintptr_t)(paddr) + HIGHER_HLF_BASE)
#define V2P(vaddr) ((uintptr_t)(vaddr) - HIGHER_HLF_BASE)
uint16_t flags;
} v_mapping;
+typedef uint32_t x86_pte_t;
+typedef struct
+{
+ x86_pte_t entry[PG_MAX_ENTRIES];
+} __attribute__((packed)) x86_page_table;
+
+
#endif /* __LUNAIX_PAGE_H */
*
* @return ptd_entry* 页目录的物理地址,随时可以加载进CR3
*/
-ptd_t*
+x86_page_table*
vmm_init_pd();
/**
// 获取v最近的最小k倍数
#define ROUNDDOWN(v, k) ((v) & ~((k) - 1))
-static void inline spin() {
+inline static void spin() {
while(1);
}
+#ifdef __LUNAIXOS_DEBUG__
+#define assert(cond) \
+ if (!(cond)) { \
+ __assert_fail(#cond, __FILE__, __LINE__); \
+ }
+void __assert_fail(const char* expr, const char* file, unsigned int line) __attribute__((noinline, noreturn));
+#else
+#define assert(cond) //nothing
+#endif
+
+
+
#endif /* __LUNAIX_SPIKE_H */
#include <arch/x86/interrupts.h>
#include <stdint.h>
-#define IDT_ENTRY 32
+#define IDT_ENTRY 256
uint64_t _idt[IDT_ENTRY];
uint16_t _idt_limit = sizeof(_idt) - 1;
void
_init_idt() {
+ // CPU defined interrupts
_set_idt_entry(FAULT_DIVISION_ERROR, 0x08, _asm_isr0, 0);
_set_idt_entry(FAULT_GENERAL_PROTECTION, 0x08, _asm_isr13, 0);
_set_idt_entry(FAULT_PAGE_FAULT, 0x08, _asm_isr14, 0);
+
+ // system defined interrupts
+ _set_idt_entry(LUNAIX_SYS_PANIC, 0x08, _asm_isr32, 0);
}
\ No newline at end of file
+#define __ASM__
+#include <arch/x86/interrupts.h>
+
.macro isr_template vector, no_error_code=1
.global _asm_isr\vector
.type _asm_isr\vector, @function
.endm
.section .text
- isr_template 0
- isr_template 13, no_error_code=0
- isr_template 14, no_error_code=0
+ isr_template FAULT_DIVISION_ERROR
+ isr_template FAULT_GENERAL_PROTECTION, no_error_code=0
+ isr_template FAULT_PAGE_FAULT, no_error_code=0
+
+ isr_template LUNAIX_SYS_PANIC
interrupt_wrapper:
+ pushl %esp
+ pushl %esi
+ pushl %ebp
+ pushl %edi
+ pushl %edx
+ pushl %ecx
+ pushl %ebx
+ pushl %eax
movl %esp, %eax
andl $0xfffffff0, %esp
movl %eax, (%esp)
call interrupt_handler
- pop %eax
+ popl %eax
movl %eax, %esp
+
+ popl %eax
+ popl %ebx
+ popl %ecx
+ popl %edx
+ popl %edi
+ popl %ebp
+ popl %esi
+ popl %esp
+
addl $8, %esp
iret
\ No newline at end of file
#include <arch/x86/interrupts.h>
-#include <lunaix/assert.h>
+#include <lunaix/tty/tty.h>
#include <libc/stdio.h>
-void panic (const char* msg, isr_param* param) {
+void panic_msg(const char* msg) {
tty_set_theme(VGA_COLOR_WHITE, VGA_COLOR_RED);
tty_clear_line(10);
tty_clear_line(11);
tty_clear_line(12);
tty_set_cpos(0, 11);
- printf(" INT %u: (%x) [0x%x: 0x%x] %s", param->vector, param->err_code, param->cs, param->eip, msg);
+ printf(" %s", msg);
+}
+
+void panic (const char* msg, isr_param* param) {
+ char buf[1024];
+ sprintf(buf, "INT %u: (%x) [%p: %p] %s", param->vector, param->err_code, param->cs, param->eip, msg);
+ panic_msg(buf);
while(1);
}
case FAULT_PAGE_FAULT:
panic("Page Fault", param);
break; // never reach
+ case LUNAIX_SYS_PANIC:
+ panic_msg((char*)(param->registers.edi));
+ while(1);
+ break; // never reach
default:
panic("Unknown Interrupt", param);
break; // never reach
addl $6, %esp
- movl $mb_info, (%esp)
call _kernel_init
/*
+++ /dev/null
-#include <lunaix/assert.h>
-
-void __assert_fail(const char* expr, const char* file, unsigned int line) {
- tty_set_theme(VGA_COLOR_BLACK, VGA_COLOR_LIGHT_RED);
- tty_clear_line(10);
- tty_clear_line(11);
- tty_clear_line(12);
- tty_set_cpos(0, 11);
- printf(" Assert %s failed (%s:%u)", expr, file, line);
- __spin:
- goto __spin;
-}
\ No newline at end of file
#include <lunaix/mm/page.h>
#include <lunaix/mm/pmm.h>
#include <lunaix/mm/vmm.h>
+#include <lunaix/mm/dmm.h>
+#include <lunaix/spike.h>
#include <arch/x86/boot/multiboot.h>
+#include <arch/x86/idt.h>
+
+#include <libc/stdio.h>
#include <stdint.h>
#include <stddef.h>
extern uint8_t __kernel_end;
extern uint8_t __init_hhk_end;
+void
+setup_memory(multiboot_memory_map_t* map, size_t map_size);
+
+void
+setup_kernel_runtime();
+
void
_kernel_pre_init(multiboot_info_t* mb_info) {
_init_idt();
mb_info->mem_upper);
unsigned int map_size = mb_info->mmap_length / sizeof(multiboot_memory_map_t);
- setup_memory(mb_info->mmap_addr, map_size);
+ setup_memory((multiboot_memory_map_t*)mb_info->mmap_addr, map_size);
setup_kernel_runtime();
}
for (size_t i = 0; i < hhk_init_pg_count; i++) {
vmm_unmap_page((void*)(i << PG_SIZE_BITS));
}
+
+ assert(dmm_init());
}
// 按照 Memory map 标识可用的物理页
#include <lunaix/mm/dmm.h>
#include <hal/cpu.h>
#include <libc/stdio.h>
+#include <lunaix/spike.h>
extern uint8_t __kernel_start;
void* k_start = vmm_v2p(&__kernel_start);
printf("The kernel's base address mapping: %p->%p\n", &__kernel_start, k_start);
- dmm_init();
-
// test malloc & free
uint32_t** arr = (uint32_t**) lx_malloc(10 * sizeof(uint32_t*));
lx_free(arr);
lx_free(big_);
- // assert(0);
}
\ No newline at end of file
*
*/
+// TODO: Make the dmm portable
+
#include <lunaix/mm/dmm.h>
#include <lunaix/mm/page.h>
#include <lunaix/mm/vmm.h>
-#include <lunaix/assert.h>
#include <lunaix/constants.h>
#include <lunaix/spike.h>
SW(heap_start + WSIZE, PACK(0, M_ALLOCATED));
current_heap_top += WSIZE;
- return lx_grow_heap(HEAP_INIT_SIZE);
+ return lx_grow_heap(HEAP_INIT_SIZE) != NULL;
}
int
lxbrk(size_t size)
{
if (size == 0) {
- return NULL;
+ return current_heap_top;
}
// plus WSIZE is the overhead for epilogue marker
size += WSIZE;
void* next = current_heap_top + ROUNDUP((uintptr_t)size, WSIZE);
- if (next >= K_STACK_START) {
+ if ((uintptr_t)next >= K_STACK_START) {
return NULL;
}
if (heap_top_pg != PG_ALIGN(next))
{
// if next do require new pages to be allocated
- if (!vmm_alloc_pages(heap_top_pg + PG_SIZE, ROUNDUP(size, PG_SIZE), PG_PRESENT | PG_WRITE)) {
+ if (!vmm_alloc_pages((void*)(heap_top_pg + PG_SIZE), ROUNDUP(size, PG_SIZE), PG_PREM_RW)) {
return NULL;
}
}
- uintptr_t old = current_heap_top;
+ void* old = current_heap_top;
current_heap_top = next - WSIZE;
return old;
}
void*
lx_grow_heap(size_t sz) {
- uintptr_t start;
+ void* start;
sz = ROUNDUP(sz, BOUNDARY);
if (!(start = lxbrk(sz))) {
// round to largest 4B aligned value
// and space for header
size = ROUNDUP(size, BOUNDARY) + WSIZE;
- while (ptr < current_heap_top) {
+ while (ptr < (uint8_t*)current_heap_top) {
uint32_t header = *((uint32_t*)ptr);
size_t chunk_size = CHUNK_S(header);
if (chunk_size >= size && !CHUNK_A(header)) {
uint32_t hdr = LW(chunk_ptr);
uint32_t pf = CHUNK_PF(hdr);
uint32_t sz = CHUNK_S(hdr);
- uint32_t ftr = LW(chunk_ptr + sz - WSIZE);
uint32_t n_hdr = LW(chunk_ptr + sz);
--- /dev/null
+#include <lunaix/mm/page.h>
\ No newline at end of file
+#include <hal/cpu.h>
#include <libc/string.h>
#include <lunaix/mm/page.h>
#include <lunaix/mm/pmm.h>
#include <lunaix/mm/vmm.h>
-#include <lunaix/assert.h>
-#include <hal/cpu.h>
+#include <lunaix/spike.h>
#include <stdbool.h>
// TODO: something here?
}
-ptd_t*
+x86_page_table*
vmm_init_pd()
{
- ptd_t* dir = pmm_alloc_page();
+ x86_page_table* dir = (x86_page_table*)pmm_alloc_page();
for (size_t i = 0; i < PG_MAX_ENTRIES; i++) {
- dir[i] = 0;
+ dir->entry[i] = PTE_NULL;
}
// 递归映射,方便我们在软件层面进行查表地址转换
- dir[PG_MAX_ENTRIES - 1] = NEW_L1_ENTRY(T_SELF_REF_PERM, dir);
+ dir->entry[PG_MAX_ENTRIES - 1] = NEW_L1_ENTRY(T_SELF_REF_PERM, dir);
return dir;
}
int
-__vmm_map_internal(uint32_t l1_inx, uint32_t l2_inx, uintptr_t pa, pt_attr attr, int forced) {
- ptd_t* l1pt = (ptd_t*)L1_BASE_VADDR;
- pt_t* l2pt = (pt_t*)L2_VADDR(l1_inx);
+__vmm_map_internal(uint32_t l1_inx,
+ uint32_t l2_inx,
+ uintptr_t pa,
+ pt_attr attr,
+ int forced)
+{
+ x86_page_table* l1pt = (x86_page_table*)L1_BASE_VADDR;
+ x86_page_table* l2pt = (x86_page_table*)L2_VADDR(l1_inx);
// See if attr make sense
assert(attr <= 128);
- if(!l1pt[l1_inx]) {
- uint8_t* new_l1pt_pa = pmm_alloc_page();
+ if (!l1pt->entry[l1_inx]) {
+ x86_page_table* new_l1pt_pa = pmm_alloc_page();
// 物理内存已满!
if (!new_l1pt_pa) {
return 0;
}
- l1pt[l1_inx] = NEW_L1_ENTRY(attr, new_l1pt_pa);
+ l1pt->entry[l1_inx] = NEW_L1_ENTRY(attr, new_l1pt_pa);
memset((void*)L2_VADDR(l1_inx), 0, PG_SIZE);
}
- if (!forced && l2pt[l2_inx]) {
+ if (!forced && l2pt->entry[l2_inx]) {
return 0;
}
- l2pt[l2_inx] = NEW_L2_ENTRY(attr, pa);
+ l2pt->entry[l2_inx] = NEW_L2_ENTRY(attr, pa);
return 1;
}
return NULL;
}
- assert(((uintptr_t)va & 0xFFFU) == 0)
- assert(((uintptr_t)pa & 0xFFFU) == 0)
+ assert(((uintptr_t)va & 0xFFFU) == 0) assert(((uintptr_t)pa & 0xFFFU) == 0);
uint32_t l1_index = L1_INDEX(va);
uint32_t l2_index = L2_INDEX(va);
- ptd_t* l1pt = (ptd_t*)L1_BASE_VADDR;
+ x86_page_table* l1pt = (x86_page_table*)L1_BASE_VADDR;
// 在页表与页目录中找到一个可用的空位进行映射(位于va或其附近)
- ptd_t l1pte = l1pt[l1_index];
- pt_t* l2pt = (pt_t*)L2_VADDR(l1_index);
+ x86_pte_t l1pte = l1pt->entry[l1_index];
+ x86_page_table* l2pt = (x86_page_table*)L2_VADDR(l1_index);
while (l1pte && l1_index < PG_MAX_ENTRIES) {
if (l2_index == PG_MAX_ENTRIES) {
l1_index++;
l2_index = 0;
- l1pte = l1pt[l1_index];
- l2pt = (pt_t*)L2_VADDR(l1_index);
+ l1pte = l1pt->entry[l1_index];
+ l2pt = (x86_page_table*)L2_VADDR(l1_index);
}
// 页表有空位,只需要开辟一个新的 PTE (Level 2)
- if (l2pt && !l2pt[l2_index]) {
- l2pt[l2_index] = NEW_L2_ENTRY(tattr, pa);
+ if (l2pt && !l2pt->entry[l2_index]) {
+ l2pt->entry[l2_index] = NEW_L2_ENTRY(tattr, pa);
return (void*)V_ADDR(l1_index, l2_index, PG_OFFSET(va));
}
l2_index++;
return NULL;
}
- if (!__vmm_map_internal(l1_index, l2_index, pa, tattr, false)) {
+ if (!__vmm_map_internal(l1_index, l2_index, (uintptr_t)pa, tattr, false)) {
return NULL;
}
}
void*
-vmm_fmap_page(void* va, void* pa, pt_attr tattr) {
+vmm_fmap_page(void* va, void* pa, pt_attr tattr)
+{
if (!pa || !va) {
return NULL;
}
- assert(((uintptr_t)va & 0xFFFU) == 0)
- assert(((uintptr_t)pa & 0xFFFU) == 0)
+ assert(((uintptr_t)va & 0xFFFU) == 0) assert(((uintptr_t)pa & 0xFFFU) == 0);
uint32_t l1_index = L1_INDEX(va);
uint32_t l2_index = L2_INDEX(va);
- if (!__vmm_map_internal(l1_index, l2_index, pa, tattr, true)) {
+ if (!__vmm_map_internal(l1_index, l2_index, (uintptr_t)pa, tattr, true)) {
return NULL;
}
}
int
-vmm_alloc_pages(void* va, size_t sz, pt_attr tattr) {
- assert((uintptr_t)va % PG_SIZE == 0)
- assert(sz % PG_SIZE == 0)
-
+vmm_alloc_pages(void* va, size_t sz, pt_attr tattr)
+{
+ assert((uintptr_t)va % PG_SIZE == 0) assert(sz % PG_SIZE == 0);
+
void* va_ = va;
- for (size_t i = 0; i < (sz >> PG_SIZE_BITS); i++, va_ += PG_SIZE)
- {
+ for (size_t i = 0; i < (sz >> PG_SIZE_BITS); i++, va_ += PG_SIZE) {
void* pp = pmm_alloc_page();
uint32_t l1_index = L1_INDEX(va_);
uint32_t l2_index = L2_INDEX(va_);
- if (!pp || !__vmm_map_internal(l1_index, l2_index, pp, tattr, false)) {
+ if (!pp || !__vmm_map_internal(
+ l1_index, l2_index, (uintptr_t)pp, tattr, false)) {
// if one failed, release previous allocated pages.
va_ = va;
- for (size_t j = 0; j < i; j++, va_ += PG_SIZE)
- {
+ for (size_t j = 0; j < i; j++, va_ += PG_SIZE) {
vmm_unmap_page(va_);
}
-
+
return false;
}
}
-
+
return true;
}
void
vmm_unmap_page(void* va)
{
- assert(((uintptr_t)va & 0xFFFU) == 0)
+ assert(((uintptr_t)va & 0xFFFU) == 0);
uint32_t l1_index = L1_INDEX(va);
uint32_t l2_index = L2_INDEX(va);
- ptd_t* l1pt = (ptd_t*)L1_BASE_VADDR;
+ x86_page_table* l1pt = (x86_page_table*)L1_BASE_VADDR;
- ptd_t l1pte = l1pt[l1_index];
+ x86_pte_t l1pte = l1pt->entry[l1_index];
if (l1pte) {
- pt_t* l2pt = (pt_t*)L2_VADDR(l1_index);
- uint32_t l2pte = l2pt[l2_index];
+ x86_page_table* l2pt = (x86_page_table*)L2_VADDR(l1_index);
+ x86_pte_t l2pte = l2pt->entry[l2_index];
if (IS_CACHED(l2pte)) {
pmm_free_page((void*)l2pte);
}
cpu_invplg(va);
- l2pt[l2_index] = 0;
+ l2pt->entry[l2_index] = PTE_NULL;
}
}
v_mapping
vmm_lookup(void* va)
{
- assert(((uintptr_t)va & 0xFFFU) == 0)
+ assert(((uintptr_t)va & 0xFFFU) == 0);
uint32_t l1_index = L1_INDEX(va);
uint32_t l2_index = L2_INDEX(va);
- uint32_t po = PG_OFFSET(va);
- ptd_t* l1pt = (ptd_t*)L1_BASE_VADDR;
- ptd_t l1pte = l1pt[l1_index];
+ x86_page_table* l1pt = (x86_page_table*)L1_BASE_VADDR;
+ x86_pte_t l1pte = l1pt->entry[l1_index];
v_mapping mapping = { .flags = 0, .pa = 0, .pn = 0 };
if (l1pte) {
- pt_t l2pte = ((pt_t*)L2_VADDR(l1_index))[l2_index];
+ x86_pte_t l2pte =
+ ((x86_page_table*)L2_VADDR(l1_index))->entry[l2_index];
if (l2pte) {
- uintptr_t ppn = l2pte >> PG_SIZE_BITS;
mapping.flags = PG_ENTRY_FLAGS(l2pte);
mapping.pa = PG_ENTRY_ADDR(l2pte);
mapping.pn = mapping.pa >> PG_SIZE_BITS;
}
void*
-vmm_v2p(void* va) {
- return vmm_lookup(va).pa;
+vmm_v2p(void* va)
+{
+ return (void*)vmm_lookup(va).pa;
}
\ No newline at end of file
--- /dev/null
+#include <lunaix/spike.h>
+#include <arch/x86/interrupts.h>
+#include <libc/stdio.h>
+
+static char buffer[1024];
+
+void __assert_fail(const char* expr, const char* file, unsigned int line) {
+ sprintf(buffer, "Assert %s failed (%s:%u)", expr, file, line);
+
+ // Here we load the buffer's address into %edi ("D" constraint)
+ // This is a convention we made that the LUNAIX_SYS_PANIC syscall will
+ // print the panic message passed via %edi. (see kernel/asm/x86/interrupts.c)
+ asm(
+ "int %0"
+ ::"i"(LUNAIX_SYS_PANIC), "D"(buffer)
+ );
+
+ spin(); // never reach
+}
\ No newline at end of file
#include <libc/string.h>
#include <stdint.h>
+#define NUMBUFSIZ 24
+
+static const char flag_chars[] = "#0- +";
+
+#define FLAG_ALT (1<<0)
+#define FLAG_ZERO (1<<1)
+#define FLAG_LEFTJUSTIFY (1<<2)
+#define FLAG_SPACEPOSITIVE (1<<3)
+#define FLAG_PLUSPOSITIVE (1<<4)
+#define FLAG_NUMERIC (1<<5)
+#define FLAG_SIGNED (1<<6)
+#define FLAG_NEGATIVE (1<<7)
+#define FLAG_ALT2 (1<<8)
+#define FLAG_CAPS (1<<9)
+
+
+// FIXME: use something like IO_FILE to abstract this into a more flexible, stream based, vprintf
void
-__sprintf_internal(char* buffer, char* fmt, va_list args)
+__sprintf_internal(char* buffer, char* fmt, va_list vargs)
{
- char c;
- int num;
- unsigned int ptr = 0;
- unsigned int adv = 0;
- while ((c = *fmt)) {
- if (c != '%') {
- buffer[ptr] = c;
- adv = 1;
- } else {
- adv = 0;
- fmt++;
- switch (c = *fmt) {
- case 'c': {
- buffer[ptr] = (char)va_arg(args, int);
- adv = 1;
- break;
- }
- case 's': {
- char* str = va_arg(args, char*);
- strcpy(buffer + ptr, str);
- adv = strlen(str);
- break;
- }
- case 'i':
- // fall through
- case 'd': {
- num = va_arg(args, int);
- __itoa_internal(num, buffer + ptr, 10, &adv);
- break;
- }
- case 'u': {
- unsigned int unum = va_arg(args, unsigned int);
- __uitoa_internal(unum, buffer + ptr, 10, &adv);
- break;
- }
- case 'o': {
- num = va_arg(args, int);
- __itoa_internal(num, buffer + ptr, 8, &adv);
- break;
- }
- case 'x':
- // fall through
- case 'X': {
- num = va_arg(args, int);
- __itoa_internal(num, buffer + ptr, 16, &adv);
- if (c == 'X') {
- int p = ptr;
- char c_;
- while ((c_ = buffer[p])) {
- buffer[p] = c_ & ~((c_ & 0x40) >> 1);
- p++;
- }
- }
- break;
- }
- case 'p': {
- uintptr_t dptr = va_arg(args, uintptr_t);
- buffer[ptr] = '0';
- buffer[ptr+1] = 'x';
- __itoa_internal((int)dptr, buffer + ptr + 2, 16, &adv);
- adv+=2;
- break;
- }
- case '%': {
- buffer[ptr] = c;
- adv = 1;
- break;
+ // This sprintf just a random implementation I found it on Internet . lol.
+ // Of course, with some modifications for porting to LunaixOS :)
+
+ // TODO: support floating point.
+
+ char numbuf[NUMBUFSIZ];
+ uint32_t ptr = 0;
+ for (; *fmt; ++fmt) {
+ if (*fmt != '%') {
+ buffer[ptr++] = *fmt;
+ continue;
+ }
+
+ // process flags
+ int flags = 0;
+ for (++fmt; *fmt; ++fmt) {
+ const char* flagc = strchr(flag_chars, *fmt);
+ if (flagc) {
+ flags |= 1 << (flagc - flag_chars);
+ } else {
+ break;
+ }
+ }
+
+ // process width
+ int width = -1;
+ if (*fmt >= '1' && *fmt <= '9') {
+ for (width = 0; *fmt >= '0' && *fmt <= '9'; ) {
+ width = 10 * width + *fmt++ - '0';
+ }
+ } else if (*fmt == '*') {
+ width = va_arg(vargs, int);
+ ++fmt;
+ }
+
+ // process precision
+ int precision = -1;
+ if (*fmt == '.') {
+ ++fmt;
+ if (*fmt >= '0' && *fmt <= '9') {
+ for (precision = 0; *fmt >= '0' && *fmt <= '9'; ) {
+ precision = 10 * precision + *fmt++ - '0';
}
- default:
- // unknown
- break;
+ } else if (*fmt == '*') {
+ precision = va_arg(vargs, int);
+ ++fmt;
}
+ if (precision < 0) {
+ precision = 0;
+ }
+ }
+
+ // process main conversion character
+ int base = 10;
+ unsigned long num = 0;
+ int length = 0;
+ char* data = "";
+ again:
+ switch (*fmt) {
+ case 'l':
+ case 'z':
+ length = 1;
+ ++fmt;
+ goto again;
+ case 'd':
+ case 'i': {
+ long x = length ? va_arg(vargs, long) : va_arg(vargs, int);
+ int negative = x < 0 ? FLAG_NEGATIVE : 0;
+ num = negative ? -x : x;
+ flags |= FLAG_NUMERIC | FLAG_SIGNED | negative;
+ break;
+ }
+ case 'u':
+ format_unsigned:
+ num = length ? va_arg(vargs, unsigned long) : va_arg(vargs, unsigned);
+ flags |= FLAG_NUMERIC;
+ break;
+ case 'x':
+ base = 16;
+ goto format_unsigned;
+ case 'X':
+ flags = flags | FLAG_CAPS;
+ base = 16;
+ goto format_unsigned;
+ case 'p':
+ num = (uintptr_t) va_arg(vargs, void*);
+ base = 16;
+ flags |= FLAG_ALT | FLAG_ALT2 | FLAG_NUMERIC;
+ break;
+ case 's':
+ data = va_arg(vargs, char*);
+ break;
+ case 'c':
+ data = numbuf;
+ numbuf[0] = va_arg(vargs, int);
+ numbuf[1] = '\0';
+ break;
+ default:
+ data = numbuf;
+ numbuf[0] = (*fmt ? *fmt : '%');
+ numbuf[1] = '\0';
+ if (!*fmt) {
+ fmt--;
+ }
+ break;
+ }
+
+ if (flags & FLAG_NUMERIC) {
+ data = itoa(num, numbuf, base);
+ int i = 0;
+ char c;
+ while ((flags & FLAG_CAPS) && (c = data[i]))
+ {
+ data[i] = c & ~((c & 0x40) >> 1);
+ i++;
+ }
+ }
+
+ const char* prefix = "";
+ if ((flags & FLAG_NUMERIC) && (flags & FLAG_SIGNED)) {
+ if (flags & FLAG_NEGATIVE) {
+ prefix = "-";
+ } else if (flags & FLAG_PLUSPOSITIVE) {
+ prefix = "+";
+ } else if (flags & FLAG_SPACEPOSITIVE) {
+ prefix = " ";
+ }
+ } else if ((flags & FLAG_NUMERIC) && (flags & FLAG_ALT)
+ && (base == 16 || base == -16)
+ && (num || (flags & FLAG_ALT2))) {
+ prefix = "0x";
+ }
+
+ int len;
+ if (precision >= 0 && !(flags & FLAG_NUMERIC)) {
+ len = strnlen(data, precision);
+ } else {
+ len = strlen(data);
+ }
+ int zeros;
+ if ((flags & FLAG_NUMERIC) && precision >= 0) {
+ zeros = precision > len ? precision - len : 0;
+ } else if ((flags & FLAG_NUMERIC) && (flags & FLAG_ZERO)
+ && !(flags & FLAG_LEFTJUSTIFY)
+ && len + (int) strlen(prefix) < width) {
+ zeros = width - len - strlen(prefix);
+ } else {
+ zeros = 0;
+ }
+ width -= len + zeros + strlen(prefix);
+ for (; !(flags & FLAG_LEFTJUSTIFY) && width > 0; --width) {
+ buffer[ptr++] = ' ';
+ }
+ for (; *prefix; ++prefix) {
+ buffer[ptr++] = *prefix;
+ }
+ for (; zeros > 0; --zeros) {
+ buffer[ptr++] = '0';
+ }
+ for (; len > 0; ++data, --len) {
+ buffer[ptr++] = *data;
+ }
+ for (; width > 0; --width) {
+ buffer[ptr++] = ' ';
}
- fmt++;
- ptr += adv;
}
- buffer[ptr] = '\0';
+ buffer[ptr++] = '\0';
}
void
--- /dev/null
+#include <libc/string.h>
+
+const char*
+strchr(const char* str, int character)
+{
+ char c = (char)character;
+ while ((*str)) {
+ if (*str == c) {
+ return str;
+ }
+ str++;
+ }
+ return c == '\0' ? str : NULL;
+}
\ No newline at end of file
while (str[len])
len++;
return len;
+}
+
+size_t
+strnlen(const char* str, size_t max_len) {
+ size_t len = 0;
+ while (str[len] && len <= max_len)
+ len++;
+ return len;
}
\ No newline at end of file
$(OBJECT_DIR)/%.S.o: %.S
@mkdir -p $(@D)
- @echo "$@"
+ @echo " BUILD: $<"
@$(CC) $(INCLUDES) -c $< -o $@
$(OBJECT_DIR)/%.c.o: %.c
@mkdir -p $(@D)
- @echo "$@"
+ @echo " BUILD: $<"
@$(CC) $(INCLUDES) -c $< -o $@ $(CFLAGS)
$(BIN_DIR)/$(OS_BIN): $(OBJECT_DIR) $(BIN_DIR) $(SRC)
- @echo "Generating $(BIN_DIR)/$(OS_BIN)"
- @$(CC) -T linker.ld -o $(BIN_DIR)/$(OS_BIN) $(SRC) $(LDFLAGS)
+ @echo " LINK: $(BIN_DIR)/$(OS_BIN)"
+ @$(CC) -T link/linker.ld -o $(BIN_DIR)/$(OS_BIN) $(SRC) $(LDFLAGS)
$(BUILD_DIR)/$(OS_ISO): $(ISO_DIR) $(BIN_DIR)/$(OS_BIN) GRUB_TEMPLATE
@./config-grub.sh ${OS_NAME} $(ISO_GRUB_DIR)/grub.cfg
all: clean $(BUILD_DIR)/$(OS_ISO)
all-debug: O := -Og
-all-debug: CFLAGS := -g -std=gnu99 -ffreestanding $(O) $(W) $(ARCH_OPT)
+all-debug: CFLAGS := -g -std=gnu99 -ffreestanding $(O) $(W) $(ARCH_OPT) -D__LUNAIXOS_DEBUG__
all-debug: LDFLAGS := -g -ffreestanding $(O) -nostdlib -lgcc
all-debug: clean $(BUILD_DIR)/$(OS_ISO)
- @echo "Dumping the disassembled kernel code to $(BUILD_DIR)/kdump.txt"
- @i686-elf-objdump -D $(BIN_DIR)/$(OS_BIN) > $(BUILD_DIR)/kdump.txt
+ # @echo "Dumping the disassembled kernel code to $(BUILD_DIR)/kdump.txt"
+ # @i686-elf-objdump -D $(BIN_DIR)/$(OS_BIN) > $(BUILD_DIR)/kdump.txt
clean:
@rm -rf $(BUILD_DIR)