initial
This commit is contained in:
commit
a9d4aa30ae
6
.gitignore
vendored
Normal file
6
.gitignore
vendored
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
.idea/
|
||||||
|
cmake-build-debug/
|
||||||
|
out/
|
||||||
|
user/out/
|
||||||
|
.vscode/
|
||||||
|
CMakeLists.txt
|
21
LICENSE
Normal file
21
LICENSE
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2018 Op52
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
14
README.md
Normal file
14
README.md
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
# CurrOS
|
||||||
|
CurrOS is a simple x86-64 kernel that supports interrupt, memory management, processes and threads, userspace and system calls.
|
||||||
|
|
||||||
|
## Toolchain
|
||||||
|
clang, lld, xorriso, grub-pc-bin, nasm
|
||||||
|
|
||||||
|
## Build
|
||||||
|
Run make inside "user" directory to build the test user program.
|
||||||
|
Run make in root dir and boot from out/curros.iso
|
||||||
|
|
||||||
|
## Clean
|
||||||
|
make clean
|
||||||
|
cd user
|
||||||
|
make clean
|
7
grub.cfg
Normal file
7
grub.cfg
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
set timeout=0
|
||||||
|
set default=0
|
||||||
|
|
||||||
|
menuentry "curros" {
|
||||||
|
multiboot2 /kernel.elf
|
||||||
|
module2 /hello.elf
|
||||||
|
}
|
47
inc/asm.inc
Normal file
47
inc/asm.inc
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
%macro PUSH_REGS 0
|
||||||
|
push rax ;save current rax
|
||||||
|
push rbx ;save current rbx
|
||||||
|
push rcx ;save current rcx
|
||||||
|
push rdx ;save current rdx
|
||||||
|
push rbp ;save current rbp
|
||||||
|
push rdi ;save current rdi
|
||||||
|
push rsi ;save current rsi
|
||||||
|
push r8 ;save current r8
|
||||||
|
push r9 ;save current r9
|
||||||
|
push r10 ;save current r10
|
||||||
|
push r11 ;save current r11
|
||||||
|
push r12 ;save current r12
|
||||||
|
push r13 ;save current r13
|
||||||
|
push r14 ;save current r14
|
||||||
|
push r15 ;save current r15
|
||||||
|
mov rax, ds
|
||||||
|
push rax
|
||||||
|
mov rax, es
|
||||||
|
push rax
|
||||||
|
push fs
|
||||||
|
push gs
|
||||||
|
%endmacro
|
||||||
|
|
||||||
|
%macro POP_REGS 0
|
||||||
|
pop gs
|
||||||
|
pop fs
|
||||||
|
pop rax
|
||||||
|
mov es, rax
|
||||||
|
pop rax
|
||||||
|
mov ds, rax
|
||||||
|
pop r15 ;restore current r15
|
||||||
|
pop r14 ;restore current r14
|
||||||
|
pop r13 ;restore current r13
|
||||||
|
pop r12 ;restore current r12
|
||||||
|
pop r11 ;restore current r11
|
||||||
|
pop r10 ;restore current r10
|
||||||
|
pop r9 ;restore current r9
|
||||||
|
pop r8 ;restore current r8
|
||||||
|
pop rsi ;restore current rsi
|
||||||
|
pop rdi ;restore current rdi
|
||||||
|
pop rbp ;restore current rbp
|
||||||
|
pop rdx ;restore current rdx
|
||||||
|
pop rcx ;restore current rcx
|
||||||
|
pop rbx ;restore current rbx
|
||||||
|
pop rax ;restore current rax
|
||||||
|
%endmacro
|
31
inc/cdef.h
Normal file
31
inc/cdef.h
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
typedef uint32_t uint32;
|
||||||
|
typedef int32_t int32;
|
||||||
|
typedef uint64_t uint64;
|
||||||
|
typedef int64_t int64;
|
||||||
|
typedef uintptr_t uintptr;
|
||||||
|
typedef uint16_t uint16;
|
||||||
|
typedef int16_t int16;
|
||||||
|
typedef uint8_t uint8;
|
||||||
|
typedef int8_t int8;
|
||||||
|
typedef size_t usize;
|
||||||
|
|
||||||
|
typedef _Bool bool;
|
||||||
|
|
||||||
|
#define TRUE (1)
|
||||||
|
#define FALSE (0)
|
||||||
|
#define ASM_F __attribute__((cdecl))
|
||||||
|
#define PACKED __attribute__((packed))
|
||||||
|
|
||||||
|
#define PRAGMA_PACKED __attribute__((packed))
|
||||||
|
|
||||||
|
#define ALIGN(type, num, align) (((type)(num) + ((type)align - 1)) & ~((type)align - 1))
|
||||||
|
|
||||||
|
#define UNREFERENCED(x) {(x) = (x);}
|
||||||
|
|
||||||
|
|
46
inc/clib.h
Normal file
46
inc/clib.h
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "cdef.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Common macros, etc
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define OBTAIN_STRUCT_ADDR(member_addr, struct_name, member_name) ((struct_name*)((uintptr)(member_addr) - (uintptr)(&(((struct_name*)0)->member_name))))
|
||||||
|
|
||||||
|
#define MAX(a, b) ((a) > (b) ? (a) : (b))
|
||||||
|
|
||||||
|
#define SWAP(a, b, T) do { T temp = *(a); *(a) = *(b); *(b) = temp; } while(0);
|
||||||
|
|
||||||
|
uint64
|
||||||
|
str_len(char const *str);
|
||||||
|
|
||||||
|
|
||||||
|
uint64
|
||||||
|
str_cmp(char const *str1, char const *str2);
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
mem_cpy(void *src, void *dst, uint64 size);
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
mem_mv(void *src, void *dst, uint64 size);
|
||||||
|
|
||||||
|
#define KASSERT(expr) kassert_ex(#expr, __FILE__, __LINE__, expr)
|
||||||
|
|
||||||
|
void
|
||||||
|
kassert_ex(const char *expr_str, const char *file, int32 line, int32 expr);
|
||||||
|
|
||||||
|
void
|
||||||
|
mem_set(void *src, uint8 val, uint64 size);
|
||||||
|
|
||||||
|
|
||||||
|
static inline uint64
|
||||||
|
bit_field_mask(uint32 low, uint32 high)
|
||||||
|
{
|
||||||
|
return ~((uint64)-1 << (high - low + 1)) << low;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
poor_sleep(uint32 dat);
|
44
inc/cpu.h
Normal file
44
inc/cpu.h
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "cdef.h"
|
||||||
|
|
||||||
|
void ASM_F out_8(uint16 port, uint8 data);
|
||||||
|
void ASM_F out_16(uint16 port, uint16 data);
|
||||||
|
void ASM_F out_32(uint16 port, uint32 data);
|
||||||
|
|
||||||
|
int32 ASM_F cmpxchg_32(int32 *dst, int32 old_val, int32 new_val);
|
||||||
|
int32 ASM_F xinc_32(int32* dst, int32 val);
|
||||||
|
|
||||||
|
uint8 ASM_F in_8(uint16 port);
|
||||||
|
uint16 ASM_F in_16(uint16 port);
|
||||||
|
uint32 ASM_F in_32(uint16 port);
|
||||||
|
|
||||||
|
void ASM_F flush_gdt(void *gdt_ptr, uint16 code_slct, uint16 data_slct);
|
||||||
|
|
||||||
|
void ASM_F flush_idt(void *idt_ptr);
|
||||||
|
|
||||||
|
void ASM_F flush_tss(uint16 tss_slct);
|
||||||
|
|
||||||
|
void ASM_F cpuid(uint32 *eax, uint32 *ebx, uint32 *ecx, uint32 *edx);
|
||||||
|
|
||||||
|
void ASM_F read_msr(uint32 *ecx, uint32 *edx, uint32 *eax);
|
||||||
|
|
||||||
|
void ASM_F write_msr(uint32 *ecx, uint32 *edx, uint32 *eax);
|
||||||
|
|
||||||
|
void ASM_F sti();
|
||||||
|
|
||||||
|
void ASM_F cli();
|
||||||
|
|
||||||
|
void ASM_F hlt();
|
||||||
|
|
||||||
|
uint64 ASM_F read_cr8();
|
||||||
|
|
||||||
|
void ASM_F write_cr8(uint64 val);
|
||||||
|
|
||||||
|
uint64 ASM_F read_cr3();
|
||||||
|
|
||||||
|
void ASM_F write_cr3(uint64 val);
|
||||||
|
|
||||||
|
void ASM_F flush_tlb();
|
||||||
|
|
||||||
|
#define BOCHS_BREAK __asm__("xchg %bx,%bx");
|
129
inc/elf64.h
Normal file
129
inc/elf64.h
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
/* ELF64 Object representation and parsing header. */
|
||||||
|
|
||||||
|
#include "cdef.h"
|
||||||
|
#include "proc.h"
|
||||||
|
|
||||||
|
typedef uint64 Elf64_Addr;
|
||||||
|
typedef uint64 Elf64_Off;
|
||||||
|
typedef uint16 Elf64_Half;
|
||||||
|
typedef uint32 Elf64_Word;
|
||||||
|
typedef uint32 Elf64_Sword;
|
||||||
|
typedef uint64 Elf64_Xword;
|
||||||
|
typedef uint64 Elf64_Sxword;
|
||||||
|
// This is custom
|
||||||
|
typedef uint8 uchar;
|
||||||
|
|
||||||
|
|
||||||
|
/* HEADER */
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
uchar e_ident[16];
|
||||||
|
Elf64_Half e_type;
|
||||||
|
Elf64_Half e_machine;
|
||||||
|
Elf64_Word e_version;
|
||||||
|
Elf64_Addr e_entry;
|
||||||
|
Elf64_Off e_phoff;
|
||||||
|
Elf64_Off e_shoff;
|
||||||
|
Elf64_Word e_flags;
|
||||||
|
Elf64_Half e_ehsize;
|
||||||
|
Elf64_Half e_phentsize;
|
||||||
|
Elf64_Half e_phnum;
|
||||||
|
Elf64_Half e_shentsize;
|
||||||
|
Elf64_Half e_shnum;
|
||||||
|
Elf64_Half e_shstrndx;
|
||||||
|
} elf64_hdr;
|
||||||
|
|
||||||
|
#define EI_MAG0 0 // should be \x7f
|
||||||
|
#define EI_MAG1 1 // E
|
||||||
|
#define EI_MAG2 2 // L
|
||||||
|
#define EI_MAG3 3 // F
|
||||||
|
|
||||||
|
#define ELFMAG0 '\x7f'
|
||||||
|
#define ELFMAG1 'E'
|
||||||
|
#define ELFMAG2 'L'
|
||||||
|
#define ELFMAG3 'F'
|
||||||
|
|
||||||
|
#define EI_CLASS 4
|
||||||
|
#define EI_DATA 5
|
||||||
|
#define EI_VERSION 6
|
||||||
|
#define EI_OSABI 7
|
||||||
|
#define EI_ABIVERSION 8
|
||||||
|
#define EI_PAD 9
|
||||||
|
#define EI_NIDENT 16
|
||||||
|
|
||||||
|
#define ELFCLASS32 1
|
||||||
|
#define ELFCLASS64 2
|
||||||
|
|
||||||
|
#define ELFDATA2LSB 1
|
||||||
|
#define ELFDATA2MSB 2
|
||||||
|
|
||||||
|
#define ELFOSABI_SYSV 0
|
||||||
|
#define ELFOSABI_HPUX 1
|
||||||
|
#define ELFOSABI_STANDALONE 255
|
||||||
|
|
||||||
|
#define ET_NONE 0
|
||||||
|
#define ET_REL 1
|
||||||
|
#define ET_EXEC 2
|
||||||
|
#define ET_DYN 3
|
||||||
|
#define ET_CORE 4
|
||||||
|
|
||||||
|
#define ET_LOOS 0xFE00
|
||||||
|
#define ET_HIOS 0XFEFF
|
||||||
|
#define ET_LOPROC 0XFF00
|
||||||
|
#define ET_HIPROC 0XFFFF
|
||||||
|
|
||||||
|
#define EV_CURRENT 1
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
Elf64_Word p_type; /* Segment type */
|
||||||
|
Elf64_Word p_flags; /* Segment flags */
|
||||||
|
Elf64_Off p_offset; /* Segment file offset */
|
||||||
|
Elf64_Addr p_vaddr; /* Segment virtual address */
|
||||||
|
Elf64_Addr p_paddr; /* Segment physical address */
|
||||||
|
Elf64_Xword p_filesz; /* Segment size in file */
|
||||||
|
Elf64_Xword p_memsz; /* Segment size in memory */
|
||||||
|
Elf64_Xword p_align; /* Segment alignment */
|
||||||
|
} elf64_phdr;
|
||||||
|
|
||||||
|
/* Special value for e_phnum. This indicates that the real number of
|
||||||
|
program headers is too large to fit into e_phnum. Instead the real
|
||||||
|
value is in the field sh_info of section 0. */
|
||||||
|
|
||||||
|
#define PN_XNUM 0xffff
|
||||||
|
|
||||||
|
/* Legal values for p_type (segment type). */
|
||||||
|
|
||||||
|
#define PT_NULL 0 /* Program header table entry unused */
|
||||||
|
#define PT_LOAD 1 /* Loadable program segment */
|
||||||
|
#define PT_DYNAMIC 2 /* Dynamic linking information */
|
||||||
|
#define PT_INTERP 3 /* Program interpreter */
|
||||||
|
#define PT_NOTE 4 /* Auxiliary information */
|
||||||
|
#define PT_SHLIB 5 /* Reserved */
|
||||||
|
#define PT_PHDR 6 /* Entry for header table itself */
|
||||||
|
#define PT_TLS 7 /* Thread-local storage segment */
|
||||||
|
#define PT_NUM 8 /* Number of defined types */
|
||||||
|
#define PT_LOOS 0x60000000 /* Start of OS-specific */
|
||||||
|
#define PT_GNU_EH_FRAME 0x6474e550 /* GCC .eh_frame_hdr segment */
|
||||||
|
#define PT_GNU_STACK 0x6474e551 /* Indicates stack executability */
|
||||||
|
#define PT_GNU_RELRO 0x6474e552 /* Read-only after relocation */
|
||||||
|
#define PT_LOSUNW 0x6ffffffa
|
||||||
|
#define PT_SUNWBSS 0x6ffffffa /* Sun Specific segment */
|
||||||
|
#define PT_SUNWSTACK 0x6ffffffb /* Stack segment */
|
||||||
|
#define PT_HISUNW 0x6fffffff
|
||||||
|
#define PT_HIOS 0x6fffffff /* End of OS-specific */
|
||||||
|
#define PT_LOPROC 0x70000000 /* Start of processor-specific */
|
||||||
|
#define PT_HIPROC 0x7fffffff /* End of processor-specific */
|
||||||
|
|
||||||
|
/* Legal values for p_flags (segment flags). */
|
||||||
|
|
||||||
|
#define PF_X (1 << 0) /* Segment is executable */
|
||||||
|
#define PF_W (1 << 1) /* Segment is writable */
|
||||||
|
#define PF_R (1 << 2) /* Segment is readable */
|
||||||
|
#define PF_MASKOS 0x0ff00000 /* OS-specific */
|
||||||
|
#define PF_MASKPROC 0xf0000000 /* Processor-specific */
|
||||||
|
|
||||||
|
|
||||||
|
int32 elf_load_file(struct pcb *proc, void *file, void **entry);
|
||||||
|
|
11
inc/error.h
Normal file
11
inc/error.h
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "cdef.h"
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
ESUCCESS = 0,
|
||||||
|
ENOSUPPORT = -1,
|
||||||
|
ENOMEM = -2,
|
||||||
|
EINVARG = -3,
|
||||||
|
};
|
113
inc/intr.h
Normal file
113
inc/intr.h
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "cdef.h"
|
||||||
|
#include "cpu.h"
|
||||||
|
|
||||||
|
#define READ_IRQ() read_cr8()
|
||||||
|
#define WRITE_IRQ(x) write_cr8(x)
|
||||||
|
|
||||||
|
#define NUM_IDT_DESC (256)
|
||||||
|
#define NUM_GDT_DESC (7)
|
||||||
|
#define IDT_DESC_SIZE (16)
|
||||||
|
#define GDT_DESC_SIZE (8)
|
||||||
|
// + 8 because TSS descriptor is 16 bytes instead
|
||||||
|
#define GDT_SIZE ((NUM_GDT_DESC) * (GDT_DESC_SIZE))
|
||||||
|
#define IDT_SIZE ((NUM_IDT_DESC) * (IDT_DESC_SIZE))
|
||||||
|
|
||||||
|
#define GDT_K_CODE (1)
|
||||||
|
#define GDT_NULL (0)
|
||||||
|
#define GDT_K_DATA (2)
|
||||||
|
#define GDT_U_CODE (3)
|
||||||
|
#define GDT_U_DATA (4)
|
||||||
|
#define GDT_U_TSS (5)
|
||||||
|
#define SEL(idx, TI, RPL) ((((uint16)idx) << 3) | (((uint16) TI) << 2) | ((uint16) RPL))
|
||||||
|
|
||||||
|
struct PACKED gdtr
|
||||||
|
{
|
||||||
|
uint16 size;
|
||||||
|
uint64 offset;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct PACKED idtr
|
||||||
|
{
|
||||||
|
uint16 size;
|
||||||
|
uint64 offset;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct PACKED gdt_desc
|
||||||
|
{
|
||||||
|
uint16 seg_l;
|
||||||
|
uint16 base_l;
|
||||||
|
uint8 base_m;
|
||||||
|
uint8 attr1;
|
||||||
|
uint8 attr2;
|
||||||
|
uint8 base_h;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct PACKED idt_desc
|
||||||
|
{
|
||||||
|
uint16 offset_l;
|
||||||
|
uint16 seg_sel;
|
||||||
|
uint16 attr;
|
||||||
|
uint16 offset_m;
|
||||||
|
uint32 offset_h;
|
||||||
|
uint32 reserved;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct PACKED intr_frame
|
||||||
|
{
|
||||||
|
uint64 gs;
|
||||||
|
uint64 fs;
|
||||||
|
uint64 es;
|
||||||
|
uint64 ds;
|
||||||
|
uint64 r15;
|
||||||
|
uint64 r14;
|
||||||
|
uint64 r13;
|
||||||
|
uint64 r12;
|
||||||
|
uint64 r11;
|
||||||
|
uint64 r10;
|
||||||
|
uint64 r9;
|
||||||
|
uint64 r8;
|
||||||
|
uint64 rsi;
|
||||||
|
uint64 rdi;
|
||||||
|
uint64 rbp;
|
||||||
|
uint64 rdx;
|
||||||
|
uint64 rcx;
|
||||||
|
uint64 rbx;
|
||||||
|
uint64 rax;
|
||||||
|
uint64 error_code;
|
||||||
|
uint64 rip;
|
||||||
|
uint64 cs;
|
||||||
|
uint64 rflags;
|
||||||
|
uint64 rsp;
|
||||||
|
uint64 ss;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct PACKED tss
|
||||||
|
{
|
||||||
|
uint32 unused0;
|
||||||
|
uint64 rsp0;
|
||||||
|
uint64 rsp1;
|
||||||
|
uint64 rsp2;
|
||||||
|
uint32 unused1[19];
|
||||||
|
};
|
||||||
|
|
||||||
|
#define INTR_VEC_TIMER (50)
|
||||||
|
#define INTR_VEC_SPURIOUS (255)
|
||||||
|
#define INTR_VEC_SYSCALL (51)
|
||||||
|
#define INTR_LIMIT_INTEL (31)
|
||||||
|
|
||||||
|
|
||||||
|
// returns the new exception frame pointer
|
||||||
|
// interrupt handlers should EOI
|
||||||
|
typedef void* (*intr_handler)(struct intr_frame *frame);
|
||||||
|
|
||||||
|
int32 intr_init();
|
||||||
|
|
||||||
|
void* ASM_F intr_dispatcher(uint32 vec, struct intr_frame *frame);
|
||||||
|
|
||||||
|
void set_intr_handler(uint32 vec, intr_handler handler);
|
||||||
|
|
||||||
|
void send_ipi(uint32 vec);
|
||||||
|
|
||||||
|
void stop_cpu();
|
70
inc/llist.h
Normal file
70
inc/llist.h
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "cdef.h"
|
||||||
|
|
||||||
|
struct llist_node
|
||||||
|
{
|
||||||
|
struct llist_node *prev;
|
||||||
|
struct llist_node *next;
|
||||||
|
void * data;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct llist
|
||||||
|
{
|
||||||
|
struct llist_node *head;
|
||||||
|
struct llist_node *tail;
|
||||||
|
uint32 size;
|
||||||
|
};
|
||||||
|
|
||||||
|
void
|
||||||
|
lb_llist_init(struct llist *list);
|
||||||
|
|
||||||
|
uint32
|
||||||
|
lb_llist_size(struct llist *list);
|
||||||
|
|
||||||
|
void
|
||||||
|
lb_llist_push_front(struct llist *list, struct llist_node *node);
|
||||||
|
|
||||||
|
void
|
||||||
|
lb_llist_push_back(struct llist *list, struct llist_node *node);
|
||||||
|
|
||||||
|
struct llist_node *
|
||||||
|
lb_llist_pop_front(struct llist *list);
|
||||||
|
|
||||||
|
|
||||||
|
struct llist_node *
|
||||||
|
lb_llist_pop_back(struct llist *list);
|
||||||
|
|
||||||
|
void
|
||||||
|
lb_llist_insert_by_idx(struct llist *list, uint32 index, struct llist_node *node);
|
||||||
|
|
||||||
|
struct llist_node *
|
||||||
|
lb_llist_remove_by_idx(struct llist *list, uint32 index);
|
||||||
|
|
||||||
|
|
||||||
|
struct llist_node *
|
||||||
|
lb_llist_get(struct llist *list, uint32 index);
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
lb_llist_insert_by_ref(struct llist *list, struct llist_node *cur_node, struct llist_node *new_node);
|
||||||
|
|
||||||
|
|
||||||
|
struct llist_node *
|
||||||
|
lb_llist_remove_by_ref(struct llist *list, struct llist_node *node);
|
||||||
|
|
||||||
|
|
||||||
|
struct llist_node *
|
||||||
|
lb_llist_next(struct llist_node *node);
|
||||||
|
|
||||||
|
|
||||||
|
struct llist_node *
|
||||||
|
lb_llist_prev(struct llist_node *node);
|
||||||
|
|
||||||
|
|
||||||
|
struct llist_node *
|
||||||
|
lb_llist_first(struct llist *list);
|
||||||
|
|
||||||
|
|
||||||
|
struct llist_node *
|
||||||
|
lb_llist_last(struct llist *list);
|
18
inc/memory_layout.h
Normal file
18
inc/memory_layout.h
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
/* System memory layout */
|
||||||
|
#pragma once
|
||||||
|
#define U_STACK_VADDR 0x90000000
|
||||||
|
|
||||||
|
#define K_START 0xFFFF800000000000
|
||||||
|
#define K_PMAP_VADDR 0xFFFF800000000000
|
||||||
|
#define K_DYNAMIC 0xFFFFFFFF00000000
|
||||||
|
#define K_DYN_END 0xFFFFFFFF70000000
|
||||||
|
#define K_IMAGE 0xFFFFFFFF80000000
|
||||||
|
|
||||||
|
#define PAGE_SIZE (0x1000)
|
||||||
|
|
||||||
|
#define K_IMAGE_PADDR (0x1000000)
|
||||||
|
// reserve 16MB
|
||||||
|
#define K_IMAGE_PRESRV (16 * 1024 * 1024)
|
||||||
|
|
||||||
|
#define R_PADDR(paddr) (void*)((paddr) + K_PMAP_VADDR)
|
||||||
|
#define IS_KERN_SPACE(vaddr) (((uintptr)vaddr) >= K_START)
|
434
inc/multiboot2.h
Normal file
434
inc/multiboot2.h
Normal file
@ -0,0 +1,434 @@
|
|||||||
|
/* multiboot2.h - Multiboot 2 header file. */
|
||||||
|
/* Copyright (C) 1999,2003,2007,2008,2009,2010 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to
|
||||||
|
* deal in the Software without restriction, including without limitation the
|
||||||
|
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||||
|
* sell copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ANY
|
||||||
|
* DEVELOPER OR DISTRIBUTOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
|
||||||
|
* IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef MULTIBOOT_HEADER
|
||||||
|
#define MULTIBOOT_HEADER 1
|
||||||
|
|
||||||
|
/* How many bytes from the start of the file we search for the header. */
|
||||||
|
#define MULTIBOOT_SEARCH 32768
|
||||||
|
#define MULTIBOOT_HEADER_ALIGN 8
|
||||||
|
|
||||||
|
/* The magic field should contain this. */
|
||||||
|
#define MULTIBOOT2_HEADER_MAGIC 0xe85250d6
|
||||||
|
|
||||||
|
/* This should be in %eax. */
|
||||||
|
#define MULTIBOOT2_BOOTLOADER_MAGIC 0x36d76289
|
||||||
|
|
||||||
|
/* Alignment of multiboot modules. */
|
||||||
|
#define MULTIBOOT_MOD_ALIGN 0x00001000
|
||||||
|
|
||||||
|
/* Alignment of the multiboot info structure. */
|
||||||
|
#define MULTIBOOT_INFO_ALIGN 0x00000008
|
||||||
|
|
||||||
|
/* Flags set in the 'flags' member of the multiboot header. */
|
||||||
|
|
||||||
|
#define MULTIBOOT_TAG_ALIGN 8
|
||||||
|
#define MULTIBOOT_TAG_TYPE_END 0
|
||||||
|
#define MULTIBOOT_TAG_TYPE_CMDLINE 1
|
||||||
|
#define MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME 2
|
||||||
|
#define MULTIBOOT_TAG_TYPE_MODULE 3
|
||||||
|
#define MULTIBOOT_TAG_TYPE_BASIC_MEMINFO 4
|
||||||
|
#define MULTIBOOT_TAG_TYPE_BOOTDEV 5
|
||||||
|
#define MULTIBOOT_TAG_TYPE_MMAP 6
|
||||||
|
#define MULTIBOOT_TAG_TYPE_VBE 7
|
||||||
|
#define MULTIBOOT_TAG_TYPE_FRAMEBUFFER 8
|
||||||
|
#define MULTIBOOT_TAG_TYPE_ELF_SECTIONS 9
|
||||||
|
#define MULTIBOOT_TAG_TYPE_APM 10
|
||||||
|
#define MULTIBOOT_TAG_TYPE_EFI32 11
|
||||||
|
#define MULTIBOOT_TAG_TYPE_EFI64 12
|
||||||
|
#define MULTIBOOT_TAG_TYPE_SMBIOS 13
|
||||||
|
#define MULTIBOOT_TAG_TYPE_ACPI_OLD 14
|
||||||
|
#define MULTIBOOT_TAG_TYPE_ACPI_NEW 15
|
||||||
|
#define MULTIBOOT_TAG_TYPE_NETWORK 16
|
||||||
|
#define MULTIBOOT_TAG_TYPE_EFI_MMAP 17
|
||||||
|
#define MULTIBOOT_TAG_TYPE_EFI_BS 18
|
||||||
|
#define MULTIBOOT_TAG_TYPE_EFI32_IH 19
|
||||||
|
#define MULTIBOOT_TAG_TYPE_EFI64_IH 20
|
||||||
|
#define MULTIBOOT_TAG_TYPE_LOAD_BASE_ADDR 21
|
||||||
|
|
||||||
|
#define MULTIBOOT_HEADER_TAG_END 0
|
||||||
|
#define MULTIBOOT_HEADER_TAG_INFORMATION_REQUEST 1
|
||||||
|
#define MULTIBOOT_HEADER_TAG_ADDRESS 2
|
||||||
|
#define MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS 3
|
||||||
|
#define MULTIBOOT_HEADER_TAG_CONSOLE_FLAGS 4
|
||||||
|
#define MULTIBOOT_HEADER_TAG_FRAMEBUFFER 5
|
||||||
|
#define MULTIBOOT_HEADER_TAG_MODULE_ALIGN 6
|
||||||
|
#define MULTIBOOT_HEADER_TAG_EFI_BS 7
|
||||||
|
#define MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS_EFI32 8
|
||||||
|
#define MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS_EFI64 9
|
||||||
|
#define MULTIBOOT_HEADER_TAG_RELOCATABLE 10
|
||||||
|
|
||||||
|
#define MULTIBOOT_ARCHITECTURE_I386 0
|
||||||
|
#define MULTIBOOT_ARCHITECTURE_MIPS32 4
|
||||||
|
#define MULTIBOOT_HEADER_TAG_OPTIONAL 1
|
||||||
|
|
||||||
|
#define MULTIBOOT_LOAD_PREFERENCE_NONE 0
|
||||||
|
#define MULTIBOOT_LOAD_PREFERENCE_LOW 1
|
||||||
|
#define MULTIBOOT_LOAD_PREFERENCE_HIGH 2
|
||||||
|
|
||||||
|
#define MULTIBOOT_CONSOLE_FLAGS_CONSOLE_REQUIRED 1
|
||||||
|
#define MULTIBOOT_CONSOLE_FLAGS_EGA_TEXT_SUPPORTED 2
|
||||||
|
|
||||||
|
#ifndef ASM_FILE
|
||||||
|
|
||||||
|
/* CurrOS */
|
||||||
|
#include "cdef.h"
|
||||||
|
/* CurrOS */
|
||||||
|
|
||||||
|
typedef unsigned char multiboot_uint8_t;
|
||||||
|
typedef unsigned short multiboot_uint16_t;
|
||||||
|
typedef unsigned int multiboot_uint32_t;
|
||||||
|
typedef unsigned long long multiboot_uint64_t;
|
||||||
|
|
||||||
|
struct multiboot_header
|
||||||
|
{
|
||||||
|
/* Must be MULTIBOOT_MAGIC - see above. */
|
||||||
|
multiboot_uint32_t magic;
|
||||||
|
|
||||||
|
/* ISA */
|
||||||
|
multiboot_uint32_t architecture;
|
||||||
|
|
||||||
|
/* Total header length. */
|
||||||
|
multiboot_uint32_t header_length;
|
||||||
|
|
||||||
|
/* The above fields plus this one must equal 0 mod 2^32. */
|
||||||
|
multiboot_uint32_t checksum;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct multiboot_header_tag
|
||||||
|
{
|
||||||
|
multiboot_uint16_t type;
|
||||||
|
multiboot_uint16_t flags;
|
||||||
|
multiboot_uint32_t size;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct multiboot_header_tag_information_request
|
||||||
|
{
|
||||||
|
multiboot_uint16_t type;
|
||||||
|
multiboot_uint16_t flags;
|
||||||
|
multiboot_uint32_t size;
|
||||||
|
multiboot_uint32_t requests[0];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct multiboot_header_tag_address
|
||||||
|
{
|
||||||
|
multiboot_uint16_t type;
|
||||||
|
multiboot_uint16_t flags;
|
||||||
|
multiboot_uint32_t size;
|
||||||
|
multiboot_uint32_t header_addr;
|
||||||
|
multiboot_uint32_t load_addr;
|
||||||
|
multiboot_uint32_t load_end_addr;
|
||||||
|
multiboot_uint32_t bss_end_addr;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct multiboot_header_tag_entry_address
|
||||||
|
{
|
||||||
|
multiboot_uint16_t type;
|
||||||
|
multiboot_uint16_t flags;
|
||||||
|
multiboot_uint32_t size;
|
||||||
|
multiboot_uint32_t entry_addr;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct multiboot_header_tag_console_flags
|
||||||
|
{
|
||||||
|
multiboot_uint16_t type;
|
||||||
|
multiboot_uint16_t flags;
|
||||||
|
multiboot_uint32_t size;
|
||||||
|
multiboot_uint32_t console_flags;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct multiboot_header_tag_framebuffer
|
||||||
|
{
|
||||||
|
multiboot_uint16_t type;
|
||||||
|
multiboot_uint16_t flags;
|
||||||
|
multiboot_uint32_t size;
|
||||||
|
multiboot_uint32_t width;
|
||||||
|
multiboot_uint32_t height;
|
||||||
|
multiboot_uint32_t depth;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct multiboot_header_tag_module_align
|
||||||
|
{
|
||||||
|
multiboot_uint16_t type;
|
||||||
|
multiboot_uint16_t flags;
|
||||||
|
multiboot_uint32_t size;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct multiboot_header_tag_relocatable
|
||||||
|
{
|
||||||
|
multiboot_uint16_t type;
|
||||||
|
multiboot_uint16_t flags;
|
||||||
|
multiboot_uint32_t size;
|
||||||
|
multiboot_uint32_t min_addr;
|
||||||
|
multiboot_uint32_t max_addr;
|
||||||
|
multiboot_uint32_t align;
|
||||||
|
multiboot_uint32_t preference;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct multiboot_color
|
||||||
|
{
|
||||||
|
multiboot_uint8_t red;
|
||||||
|
multiboot_uint8_t green;
|
||||||
|
multiboot_uint8_t blue;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct multiboot_mmap_entry
|
||||||
|
{
|
||||||
|
multiboot_uint64_t addr;
|
||||||
|
multiboot_uint64_t len;
|
||||||
|
#define MULTIBOOT_MEMORY_AVAILABLE 1
|
||||||
|
#define MULTIBOOT_MEMORY_RESERVED 2
|
||||||
|
#define MULTIBOOT_MEMORY_ACPI_RECLAIMABLE 3
|
||||||
|
#define MULTIBOOT_MEMORY_NVS 4
|
||||||
|
#define MULTIBOOT_MEMORY_BADRAM 5
|
||||||
|
multiboot_uint32_t type;
|
||||||
|
multiboot_uint32_t zero;
|
||||||
|
};
|
||||||
|
typedef struct multiboot_mmap_entry multiboot_memory_map_t;
|
||||||
|
|
||||||
|
struct multiboot_tag
|
||||||
|
{
|
||||||
|
multiboot_uint32_t type;
|
||||||
|
multiboot_uint32_t size;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct multiboot_tag_string
|
||||||
|
{
|
||||||
|
multiboot_uint32_t type;
|
||||||
|
multiboot_uint32_t size;
|
||||||
|
char string[0];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct multiboot_tag_module
|
||||||
|
{
|
||||||
|
multiboot_uint32_t type;
|
||||||
|
multiboot_uint32_t size;
|
||||||
|
multiboot_uint32_t mod_start;
|
||||||
|
multiboot_uint32_t mod_end;
|
||||||
|
char cmdline[0];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct multiboot_tag_basic_meminfo
|
||||||
|
{
|
||||||
|
multiboot_uint32_t type;
|
||||||
|
multiboot_uint32_t size;
|
||||||
|
multiboot_uint32_t mem_lower;
|
||||||
|
multiboot_uint32_t mem_upper;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct multiboot_tag_bootdev
|
||||||
|
{
|
||||||
|
multiboot_uint32_t type;
|
||||||
|
multiboot_uint32_t size;
|
||||||
|
multiboot_uint32_t biosdev;
|
||||||
|
multiboot_uint32_t slice;
|
||||||
|
multiboot_uint32_t part;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct multiboot_tag_mmap
|
||||||
|
{
|
||||||
|
multiboot_uint32_t type;
|
||||||
|
multiboot_uint32_t size;
|
||||||
|
multiboot_uint32_t entry_size;
|
||||||
|
multiboot_uint32_t entry_version;
|
||||||
|
struct multiboot_mmap_entry entries[0];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct multiboot_vbe_info_block
|
||||||
|
{
|
||||||
|
multiboot_uint8_t external_specification[512];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct multiboot_vbe_mode_info_block
|
||||||
|
{
|
||||||
|
multiboot_uint8_t external_specification[256];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct multiboot_tag_vbe
|
||||||
|
{
|
||||||
|
multiboot_uint32_t type;
|
||||||
|
multiboot_uint32_t size;
|
||||||
|
|
||||||
|
multiboot_uint16_t vbe_mode;
|
||||||
|
multiboot_uint16_t vbe_interface_seg;
|
||||||
|
multiboot_uint16_t vbe_interface_off;
|
||||||
|
multiboot_uint16_t vbe_interface_len;
|
||||||
|
|
||||||
|
struct multiboot_vbe_info_block vbe_control_info;
|
||||||
|
struct multiboot_vbe_mode_info_block vbe_mode_info;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct multiboot_tag_framebuffer_common
|
||||||
|
{
|
||||||
|
multiboot_uint32_t type;
|
||||||
|
multiboot_uint32_t size;
|
||||||
|
|
||||||
|
multiboot_uint64_t framebuffer_addr;
|
||||||
|
multiboot_uint32_t framebuffer_pitch;
|
||||||
|
multiboot_uint32_t framebuffer_width;
|
||||||
|
multiboot_uint32_t framebuffer_height;
|
||||||
|
multiboot_uint8_t framebuffer_bpp;
|
||||||
|
#define MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED 0
|
||||||
|
#define MULTIBOOT_FRAMEBUFFER_TYPE_RGB 1
|
||||||
|
#define MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT 2
|
||||||
|
multiboot_uint8_t framebuffer_type;
|
||||||
|
multiboot_uint16_t reserved;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct multiboot_tag_framebuffer
|
||||||
|
{
|
||||||
|
struct multiboot_tag_framebuffer_common common;
|
||||||
|
|
||||||
|
union
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
multiboot_uint16_t framebuffer_palette_num_colors;
|
||||||
|
struct multiboot_color framebuffer_palette[0];
|
||||||
|
};
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
multiboot_uint8_t framebuffer_red_field_position;
|
||||||
|
multiboot_uint8_t framebuffer_red_mask_size;
|
||||||
|
multiboot_uint8_t framebuffer_green_field_position;
|
||||||
|
multiboot_uint8_t framebuffer_green_mask_size;
|
||||||
|
multiboot_uint8_t framebuffer_blue_field_position;
|
||||||
|
multiboot_uint8_t framebuffer_blue_mask_size;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
struct multiboot_tag_elf_sections
|
||||||
|
{
|
||||||
|
multiboot_uint32_t type;
|
||||||
|
multiboot_uint32_t size;
|
||||||
|
multiboot_uint32_t num;
|
||||||
|
multiboot_uint32_t entsize;
|
||||||
|
multiboot_uint32_t shndx;
|
||||||
|
char sections[0];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct multiboot_tag_apm
|
||||||
|
{
|
||||||
|
multiboot_uint32_t type;
|
||||||
|
multiboot_uint32_t size;
|
||||||
|
multiboot_uint16_t version;
|
||||||
|
multiboot_uint16_t cseg;
|
||||||
|
multiboot_uint32_t offset;
|
||||||
|
multiboot_uint16_t cseg_16;
|
||||||
|
multiboot_uint16_t dseg;
|
||||||
|
multiboot_uint16_t flags;
|
||||||
|
multiboot_uint16_t cseg_len;
|
||||||
|
multiboot_uint16_t cseg_16_len;
|
||||||
|
multiboot_uint16_t dseg_len;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct multiboot_tag_efi32
|
||||||
|
{
|
||||||
|
multiboot_uint32_t type;
|
||||||
|
multiboot_uint32_t size;
|
||||||
|
multiboot_uint32_t pointer;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct multiboot_tag_efi64
|
||||||
|
{
|
||||||
|
multiboot_uint32_t type;
|
||||||
|
multiboot_uint32_t size;
|
||||||
|
multiboot_uint64_t pointer;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct multiboot_tag_smbios
|
||||||
|
{
|
||||||
|
multiboot_uint32_t type;
|
||||||
|
multiboot_uint32_t size;
|
||||||
|
multiboot_uint8_t major;
|
||||||
|
multiboot_uint8_t minor;
|
||||||
|
multiboot_uint8_t reserved[6];
|
||||||
|
multiboot_uint8_t tables[0];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct multiboot_tag_old_acpi
|
||||||
|
{
|
||||||
|
multiboot_uint32_t type;
|
||||||
|
multiboot_uint32_t size;
|
||||||
|
multiboot_uint8_t rsdp[0];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct multiboot_tag_new_acpi
|
||||||
|
{
|
||||||
|
multiboot_uint32_t type;
|
||||||
|
multiboot_uint32_t size;
|
||||||
|
multiboot_uint8_t rsdp[0];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct multiboot_tag_network
|
||||||
|
{
|
||||||
|
multiboot_uint32_t type;
|
||||||
|
multiboot_uint32_t size;
|
||||||
|
multiboot_uint8_t dhcpack[0];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct multiboot_tag_efi_mmap
|
||||||
|
{
|
||||||
|
multiboot_uint32_t type;
|
||||||
|
multiboot_uint32_t size;
|
||||||
|
multiboot_uint32_t descr_size;
|
||||||
|
multiboot_uint32_t descr_vers;
|
||||||
|
multiboot_uint8_t efi_mmap[0];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct multiboot_tag_efi32_ih
|
||||||
|
{
|
||||||
|
multiboot_uint32_t type;
|
||||||
|
multiboot_uint32_t size;
|
||||||
|
multiboot_uint32_t pointer;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct multiboot_tag_efi64_ih
|
||||||
|
{
|
||||||
|
multiboot_uint32_t type;
|
||||||
|
multiboot_uint32_t size;
|
||||||
|
multiboot_uint64_t pointer;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct multiboot_tag_load_base_addr
|
||||||
|
{
|
||||||
|
multiboot_uint32_t type;
|
||||||
|
multiboot_uint32_t size;
|
||||||
|
multiboot_uint32_t load_base_addr;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* CurrOS */
|
||||||
|
typedef struct multiboot2_entry
|
||||||
|
{
|
||||||
|
uint32 total_size;
|
||||||
|
uint32 reserved;
|
||||||
|
} mbentry;
|
||||||
|
|
||||||
|
typedef struct multiboot_header mheader;
|
||||||
|
typedef struct multiboot_header_tag htag;
|
||||||
|
typedef struct multiboot_tag_module mod_tag;
|
||||||
|
void parse_mb2(mbentry * mb, void ** module, char ** ld_name, uint64*, uint64*);
|
||||||
|
/* CurrOS */
|
||||||
|
|
||||||
|
#endif /* ! ASM_FILE */
|
||||||
|
|
||||||
|
#endif /* ! MULTIBOOT_HEADER */
|
43
inc/multiboot2.inc
Normal file
43
inc/multiboot2.inc
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
MULTIBOOT_SEARCH equ 32768
|
||||||
|
MULTIBOOT_HEADER_ALIGN equ 8
|
||||||
|
MULTIBOOT2_HEADER_MAGIC equ 0xe85250d6
|
||||||
|
MULTIBOOT2_BOOTLOADER_MAGIC equ 0x36d76289
|
||||||
|
MULTIBOOT_MOD_ALIGN equ 0x00001000
|
||||||
|
MULTIBOOT_INFO_ALIGN equ 0x00000008
|
||||||
|
|
||||||
|
MULTIBOOT_TAG_ALIGN equ 8
|
||||||
|
MULTIBOOT_TAG_TYPE_END equ 0
|
||||||
|
MULTIBOOT_TAG_TYPE_CMDLINE equ 1
|
||||||
|
MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME equ 2
|
||||||
|
MULTIBOOT_TAG_TYPE_MODULE equ 3
|
||||||
|
MULTIBOOT_TAG_TYPE_BASIC_MEMINFO equ 4
|
||||||
|
MULTIBOOT_TAG_TYPE_BOOTDEV equ 5
|
||||||
|
MULTIBOOT_TAG_TYPE_MMAP equ 6
|
||||||
|
MULTIBOOT_TAG_TYPE_VBE equ 7
|
||||||
|
MULTIBOOT_TAG_TYPE_FRAMEBUFFER equ 8
|
||||||
|
MULTIBOOT_TAG_TYPE_ELF_SECTIONS equ 9
|
||||||
|
MULTIBOOT_TAG_TYPE_APM equ 10
|
||||||
|
MULTIBOOT_TAG_TYPE_EFI32 equ 11
|
||||||
|
MULTIBOOT_TAG_TYPE_EFI64 equ 12
|
||||||
|
MULTIBOOT_TAG_TYPE_SMBIOS equ 13
|
||||||
|
MULTIBOOT_TAG_TYPE_ACPI_OLD equ 14
|
||||||
|
MULTIBOOT_TAG_TYPE_ACPI_NEW equ 15
|
||||||
|
MULTIBOOT_TAG_TYPE_NETWORK equ 16
|
||||||
|
MULTIBOOT_TAG_TYPE_EFI_MMAP equ 17
|
||||||
|
MULTIBOOT_TAG_TYPE_EFI_BS equ 18
|
||||||
|
|
||||||
|
MULTIBOOT_HEADER_TAG_END equ 0
|
||||||
|
MULTIBOOT_HEADER_TAG_INFORMATION_REQUEST equ 1
|
||||||
|
MULTIBOOT_HEADER_TAG_ADDRESS equ 2
|
||||||
|
MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS equ 3
|
||||||
|
MULTIBOOT_HEADER_TAG_CONSOLE_FLAGS equ 4
|
||||||
|
MULTIBOOT_HEADER_TAG_FRAMEBUFFER equ 5
|
||||||
|
MULTIBOOT_HEADER_TAG_MODULE_ALIGN equ 6
|
||||||
|
MULTIBOOT_HEADER_TAG_EFI_BS equ 7
|
||||||
|
|
||||||
|
MULTIBOOT_ARCHITECTURE_I386 equ 0
|
||||||
|
MULTIBOOT_ARCHITECTURE_MIPS32 equ 4
|
||||||
|
MULTIBOOT_HEADER_TAG_OPTIONAL equ 1
|
||||||
|
|
||||||
|
MULTIBOOT_CONSOLE_FLAGS_CONSOLE_REQUIRED equ 1
|
||||||
|
MULTIBOOT_CONSOLE_FLAGS_EGA_TEXT_SUPPORTED equ 2
|
15
inc/paging.h
Normal file
15
inc/paging.h
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "cdef.h"
|
||||||
|
#include "memory_layout.h"
|
||||||
|
|
||||||
|
#define PML4_ENTRY(vaddr) ((vaddr >> 39) & 0x1FF)
|
||||||
|
#define PDPT_ENTRY(vaddr) ((vaddr >> 30) & 0x1FF)
|
||||||
|
#define PD_ENTRY(vaddr) ((vaddr >> 21) & 0x1FF)
|
||||||
|
#define PT_ENTRY(vaddr) ((vaddr >> 12) & 0x1FF)
|
||||||
|
|
||||||
|
#define KERNEL_PAGE_SIZE (PAGE_SIZE)
|
||||||
|
|
||||||
|
uintptr get_paddr(uint64 cr3, uintptr vaddr);
|
||||||
|
|
||||||
|
int32 map_vmem(uint64 cr3, uintptr virt_addr, uintptr phys_addr);
|
28
inc/pmm.h
Normal file
28
inc/pmm.h
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
/* Header file for physical memory management */
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "cdef.h"
|
||||||
|
#include "llist.h"
|
||||||
|
#include "spin_lock.h"
|
||||||
|
|
||||||
|
typedef uintptr paddr;
|
||||||
|
|
||||||
|
typedef struct llist memlist;
|
||||||
|
typedef struct llist_node memnode;
|
||||||
|
|
||||||
|
typedef struct allocation_unit {
|
||||||
|
paddr head;
|
||||||
|
uint64 size;
|
||||||
|
uint8 status;
|
||||||
|
} allocu;
|
||||||
|
|
||||||
|
void * pmalloc(uint32 size); // Allocate a physical page
|
||||||
|
void pfree(paddr p); // Free physical page
|
||||||
|
|
||||||
|
// TODO : Setup methods
|
||||||
|
void pmm_init(uint64 low, uint64 high);
|
||||||
|
uint8 get_mem_phase();
|
||||||
|
void set_mmap_low(uint64 low, uint64 size);
|
||||||
|
void set_mmap_high(uint64 high, uint64 size);
|
||||||
|
|
||||||
|
|
9
inc/print.h
Normal file
9
inc/print.h
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "cdef.h"
|
||||||
|
|
||||||
|
void clear_screen(void);
|
||||||
|
|
||||||
|
void kprintf(char const *format, ...);
|
||||||
|
|
||||||
|
void print_init();
|
22
inc/proc.h
Normal file
22
inc/proc.h
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "cdef.h"
|
||||||
|
#include "llist.h"
|
||||||
|
#include "spin_lock.h"
|
||||||
|
|
||||||
|
struct pcb
|
||||||
|
{
|
||||||
|
uint64 cr3;
|
||||||
|
uint32 proc_id;
|
||||||
|
struct llist threads;
|
||||||
|
struct llist_node list_node;
|
||||||
|
struct spin_lock lock;
|
||||||
|
};
|
||||||
|
|
||||||
|
// procs now are simply cr3 holders
|
||||||
|
int32 proc_create(void* elf64, uint32* proc_id);
|
||||||
|
|
||||||
|
|
||||||
|
// proc init also makes the current address space process 0
|
||||||
|
// and creates a thread to run k_routine
|
||||||
|
int32 proc_init(void* k_routine);
|
18
inc/spin_lock.h
Normal file
18
inc/spin_lock.h
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "cdef.h"
|
||||||
|
|
||||||
|
struct spin_lock
|
||||||
|
{
|
||||||
|
int32 val;
|
||||||
|
};
|
||||||
|
|
||||||
|
void spin_init(struct spin_lock *lock);
|
||||||
|
|
||||||
|
void spin_lock(struct spin_lock *lock);
|
||||||
|
|
||||||
|
void spin_unlock(struct spin_lock *lock);
|
||||||
|
|
||||||
|
uint64 spin_lock_irq_save(struct spin_lock* lock);
|
||||||
|
|
||||||
|
void spin_unlock_irq_restore(struct spin_lock* lock, uint64 irq);
|
5
inc/syscall.h
Normal file
5
inc/syscall.h
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "cdef.h"
|
||||||
|
|
||||||
|
void syscall_init();
|
42
inc/thread.h
Normal file
42
inc/thread.h
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "proc.h"
|
||||||
|
|
||||||
|
struct tcb
|
||||||
|
{
|
||||||
|
struct pcb *proc;
|
||||||
|
uint32 tid;
|
||||||
|
int32 exit_code;
|
||||||
|
uint32 state;
|
||||||
|
|
||||||
|
uintptr ustack;
|
||||||
|
usize ustack_sz;
|
||||||
|
void* kstack;
|
||||||
|
usize kstack_sz;
|
||||||
|
|
||||||
|
uint64 rsp0; // kernel stack pointer for the stack, has context information
|
||||||
|
struct spin_lock lock;
|
||||||
|
struct llist_node list_node;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct tcb* get_cur_thread();
|
||||||
|
|
||||||
|
int32 thread_stop(uint32 tid, int32 code);
|
||||||
|
|
||||||
|
void list_threads();
|
||||||
|
|
||||||
|
int32 thread_create(struct pcb* proc, void* entry, void* args, uint32* tid);
|
||||||
|
|
||||||
|
void thread_init();
|
||||||
|
|
||||||
|
void thread_schedule();
|
||||||
|
|
||||||
|
int32 thread_get_exit_code(uint32 tid, int32* exit_code);
|
||||||
|
|
||||||
|
void thread_yield();
|
||||||
|
|
||||||
|
int32 thread_resume(uint32 tid);
|
||||||
|
|
||||||
|
void thread_exit(int32 code);
|
||||||
|
|
||||||
|
int32 thread_block(uint32 tid);
|
64
inc/vmm.h
Normal file
64
inc/vmm.h
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
#pragma once
|
||||||
|
/* Virtual memory management header */
|
||||||
|
|
||||||
|
#include "cdef.h"
|
||||||
|
#include "memory_layout.h"
|
||||||
|
#include "llist.h"
|
||||||
|
#include "pmm.h"
|
||||||
|
#include "spin_lock.h"
|
||||||
|
|
||||||
|
typedef uintptr vaddr;
|
||||||
|
typedef struct llist vmll;
|
||||||
|
typedef struct llist_node vm_node;
|
||||||
|
|
||||||
|
typedef struct virtual_page
|
||||||
|
{
|
||||||
|
vaddr address; // Init to 0x0
|
||||||
|
vaddr table_ptr;
|
||||||
|
vmll allocs; // Linked list of vm_atom
|
||||||
|
uint64 free;
|
||||||
|
uint8 status;
|
||||||
|
} vm_object;
|
||||||
|
|
||||||
|
typedef struct allocation
|
||||||
|
{
|
||||||
|
usize offset;
|
||||||
|
usize size;
|
||||||
|
vm_object *page_ptr;
|
||||||
|
} vm_atom;
|
||||||
|
|
||||||
|
typedef struct page_table
|
||||||
|
{
|
||||||
|
uint64 id;
|
||||||
|
usize size;
|
||||||
|
usize free;
|
||||||
|
vm_atom *map;
|
||||||
|
} vm_unit;
|
||||||
|
|
||||||
|
typedef struct allocation_sector
|
||||||
|
{
|
||||||
|
uint64 start;
|
||||||
|
uint64 end;
|
||||||
|
vm_object **actbck;
|
||||||
|
vm_object **resbck;
|
||||||
|
vm_object *largest_free;
|
||||||
|
uint16 dirty;
|
||||||
|
} vm_sector;
|
||||||
|
|
||||||
|
typedef struct page_table_entries
|
||||||
|
{
|
||||||
|
vm_unit *groups;
|
||||||
|
vm_sector sectors[3];
|
||||||
|
vm_object *pages;
|
||||||
|
|
||||||
|
vmll *global_alloc;
|
||||||
|
usize free_frames;
|
||||||
|
} vmem;
|
||||||
|
|
||||||
|
void init_vm();
|
||||||
|
|
||||||
|
void vm_issue_unit(uint64 id, usize size);
|
||||||
|
|
||||||
|
void *kalloc(usize size);
|
||||||
|
|
||||||
|
void kfree(void *ptr);
|
32
linker.ld
Normal file
32
linker.ld
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
ENTRY(sys_entry)
|
||||||
|
|
||||||
|
KERNEL_IMAGE_VADDR = 0xFFFFFFFF80000000;
|
||||||
|
KERNEL_IMAGE_PADDR = 0x1000000;
|
||||||
|
KERNEL_PAGE_SIZE = 0x1000;
|
||||||
|
|
||||||
|
SECTIONS
|
||||||
|
{
|
||||||
|
. = KERNEL_IMAGE_VADDR + KERNEL_IMAGE_PADDR;
|
||||||
|
|
||||||
|
.multiboot_header ALIGN(KERNEL_PAGE_SIZE) : AT(ADDR(.multiboot_header) - KERNEL_IMAGE_VADDR)
|
||||||
|
{
|
||||||
|
*(.multiboot_header)
|
||||||
|
}
|
||||||
|
|
||||||
|
.text ALIGN(KERNEL_PAGE_SIZE) : AT(ADDR(.text) - KERNEL_IMAGE_VADDR)
|
||||||
|
{
|
||||||
|
*(.text)
|
||||||
|
}
|
||||||
|
|
||||||
|
.data ALIGN(KERNEL_PAGE_SIZE) : AT(ADDR(.data) - KERNEL_IMAGE_VADDR)
|
||||||
|
{
|
||||||
|
*(.data)
|
||||||
|
*(.rodata*)
|
||||||
|
}
|
||||||
|
|
||||||
|
.bss ALIGN(KERNEL_PAGE_SIZE) : AT(ADDR(.bss) - KERNEL_IMAGE_VADDR)
|
||||||
|
{
|
||||||
|
*(.bss)
|
||||||
|
*(COMMON)
|
||||||
|
}
|
||||||
|
}
|
137
makefile
Normal file
137
makefile
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
|
||||||
|
AS := nasm
|
||||||
|
CC := clang-6.0
|
||||||
|
LD := lld-6.0
|
||||||
|
DAS := llvm-objdump-6.0
|
||||||
|
|
||||||
|
.DEFAULT_GOAL := all
|
||||||
|
|
||||||
|
C_FLAGS_ARCH_X86_64 := -mcmodel=kernel \
|
||||||
|
-target x86_64-pc-none-elf \
|
||||||
|
-mno-red-zone \
|
||||||
|
-mno-mmx \
|
||||||
|
-mno-sse \
|
||||||
|
-mno-sse2 \
|
||||||
|
-mno-sse3 \
|
||||||
|
-mno-3dnow
|
||||||
|
|
||||||
|
C_FLAGS = -x c \
|
||||||
|
-g \
|
||||||
|
-c \
|
||||||
|
-O0 \
|
||||||
|
-std=c17 \
|
||||||
|
-Wall \
|
||||||
|
-Werror \
|
||||||
|
-Wextra \
|
||||||
|
-Wpedantic \
|
||||||
|
-ffreestanding \
|
||||||
|
-fno-pic \
|
||||||
|
-fno-stack-protector \
|
||||||
|
-Wno-int-to-pointer-cast \
|
||||||
|
-Wno-zero-length-array \
|
||||||
|
$(C_FLAGS_ARCH_X86_64) \
|
||||||
|
-I$(INC)/ \
|
||||||
|
$(C_EFLAGS)
|
||||||
|
|
||||||
|
AS_FLAGS = -w+all \
|
||||||
|
-w+error \
|
||||||
|
-f elf64 \
|
||||||
|
-F dwarf \
|
||||||
|
-g \
|
||||||
|
-I$(INC)/ \
|
||||||
|
$(AS_FLAGS_$(MOD))
|
||||||
|
|
||||||
|
DUMP_FLAGS = -x86-asm-syntax=intel \
|
||||||
|
-disassemble \
|
||||||
|
-r \
|
||||||
|
-t \
|
||||||
|
-triple=x86_64-pc-none-elf \
|
||||||
|
-print-imm-hex
|
||||||
|
|
||||||
|
LD_FLAGS = -fuse-ld=$(LD) \
|
||||||
|
-nostdlib \
|
||||||
|
-Wl,-T,$(LD_SCRIPT) \
|
||||||
|
-Wl,--fatal-warnings
|
||||||
|
|
||||||
|
# ===============================
|
||||||
|
# HERE COMES file definitions
|
||||||
|
# ===============================
|
||||||
|
|
||||||
|
SRC := src
|
||||||
|
INC := inc
|
||||||
|
OUT := out
|
||||||
|
LD_SCRIPT := linker.ld
|
||||||
|
GRUB_CFG := grub.cfg
|
||||||
|
|
||||||
|
TGT := $(OUT)/kernel.elf
|
||||||
|
ISO := $(OUT)/curros.iso
|
||||||
|
DMP := $(OUT)/kernel.dmp
|
||||||
|
|
||||||
|
# ===============================
|
||||||
|
# Add additional c source files here
|
||||||
|
# ===============================
|
||||||
|
C_SRC := kmain.c \
|
||||||
|
llist.c \
|
||||||
|
intr.c \
|
||||||
|
clib.c \
|
||||||
|
print.c \
|
||||||
|
multiboot2.c \
|
||||||
|
pmm.c \
|
||||||
|
elf64.c \
|
||||||
|
vmm.c \
|
||||||
|
spin_lock.c \
|
||||||
|
thread.c \
|
||||||
|
proc.c \
|
||||||
|
paging.c \
|
||||||
|
syscall.c
|
||||||
|
|
||||||
|
# ===============================
|
||||||
|
# Add additional ASM source files here
|
||||||
|
# ===============================
|
||||||
|
ASM_SRC := boot.asm \
|
||||||
|
cpu.asm \
|
||||||
|
intr.asm
|
||||||
|
|
||||||
|
|
||||||
|
# ===============================
|
||||||
|
# Compilation rules
|
||||||
|
# ===============================
|
||||||
|
C_OBJ := $(addsuffix .o, $(addprefix $(OUT)/,$(C_SRC)))
|
||||||
|
|
||||||
|
ASM_OBJ := $(addsuffix .o, $(addprefix $(OUT)/,$(ASM_SRC)))
|
||||||
|
|
||||||
|
$(C_OBJ): $(OUT)/%.c.o : $(SRC)/%.c
|
||||||
|
$(CC) $(C_FLAGS) -o $@ $<
|
||||||
|
|
||||||
|
$(ASM_OBJ): $(OUT)/%.asm.o : $(SRC)/%.asm
|
||||||
|
$(AS) $(AS_FLAGS) -o $@ $<
|
||||||
|
|
||||||
|
$(TGT): $(C_OBJ) $(ASM_OBJ) $(LD_SCRIPT)
|
||||||
|
$(CC) $(LD_FLAGS) -o $@ $^
|
||||||
|
|
||||||
|
$(DMP): $(TGT)
|
||||||
|
$(DAS) $(DUMP_FLAGS) $< > $@
|
||||||
|
|
||||||
|
$(ISO): $(TGT) $(GRUB_CFG)
|
||||||
|
mkdir -p $(OUT)/temp/boot/grub
|
||||||
|
cp $(GRUB_CFG) $(OUT)/temp/boot/grub/
|
||||||
|
cp $(TGT) $(OUT)/temp/
|
||||||
|
cp ./user/out/hello.elf $(OUT)/temp/
|
||||||
|
grub-mkrescue -d /usr/lib/grub/i386-pc -o $(ISO) $(OUT)/temp
|
||||||
|
|
||||||
|
.PHONY: mkdir
|
||||||
|
mkdir:
|
||||||
|
mkdir -p out
|
||||||
|
|
||||||
|
.PHONY: clean
|
||||||
|
clean:
|
||||||
|
rm -rf $(OUT)
|
||||||
|
|
||||||
|
.PHONY: all
|
||||||
|
all: mkdir $(TGT) $(DMP) $(ISO)
|
||||||
|
|
||||||
|
.PHONY: debug
|
||||||
|
debug:
|
||||||
|
qemu-system-x86_64 -boot d -cdrom $(ISO)
|
||||||
|
|
||||||
|
|
14
paper/curros.tex
Normal file
14
paper/curros.tex
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
\title{CurrOS: A Work In Progress}
|
||||||
|
\author{
|
||||||
|
Mohammad Yazdani
|
||||||
|
}
|
||||||
|
\date{\today}
|
||||||
|
|
||||||
|
\documentclass[12pt]{article}
|
||||||
|
|
||||||
|
\begin{document}
|
||||||
|
\maketitle
|
||||||
|
|
||||||
|
\end{document}
|
||||||
|
|
||||||
|
|
269
src/boot.asm
Normal file
269
src/boot.asm
Normal file
@ -0,0 +1,269 @@
|
|||||||
|
%include "multiboot2.inc"
|
||||||
|
|
||||||
|
KERNEL_PAGE_SIZE equ 0x1000
|
||||||
|
KERNEL_IMAGE_VADDR equ 0xFFFFFFFF80000000
|
||||||
|
KERNEL_PMAP_VADDR equ 0xFFFF800000000000
|
||||||
|
|
||||||
|
%define GET_PADDR(x) ((x) - KERNEL_IMAGE_VADDR)
|
||||||
|
%define GET_PML4(vaddr) (((vaddr) >> 39 ) & 0x1FF)
|
||||||
|
%define GET_PDPT(vaddr) (((vaddr) >> 30 ) & 0x1FF)
|
||||||
|
|
||||||
|
global sys_entry
|
||||||
|
extern kmain
|
||||||
|
|
||||||
|
section .multiboot_header
|
||||||
|
|
||||||
|
ASM_MULTIBOOT_CHECK_SUM equ (0xFFFFFFFF - (MULTIBOOT2_HEADER_MAGIC + ASM_MULTIBOOT_HEADER_SIZE + MULTIBOOT_ARCHITECTURE_I386) + 1)
|
||||||
|
|
||||||
|
section .multiboot_header
|
||||||
|
bits 32
|
||||||
|
align KERNEL_PAGE_SIZE
|
||||||
|
;====================
|
||||||
|
align MULTIBOOT_HEADER_ALIGN
|
||||||
|
start_hdr:
|
||||||
|
dd MULTIBOOT2_HEADER_MAGIC
|
||||||
|
dd MULTIBOOT_ARCHITECTURE_I386
|
||||||
|
dd ASM_MULTIBOOT_HEADER_SIZE
|
||||||
|
dd ASM_MULTIBOOT_CHECK_SUM
|
||||||
|
;====================
|
||||||
|
align MULTIBOOT_INFO_ALIGN
|
||||||
|
dw MULTIBOOT_HEADER_TAG_INFORMATION_REQUEST
|
||||||
|
dw 0 ; flag
|
||||||
|
dd (8+4*3) ; size
|
||||||
|
dd MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME
|
||||||
|
dd MULTIBOOT_TAG_TYPE_MMAP
|
||||||
|
dd MULTIBOOT_TAG_TYPE_ACPI_NEW
|
||||||
|
;====================
|
||||||
|
align MULTIBOOT_INFO_ALIGN
|
||||||
|
dw MULTIBOOT_HEADER_TAG_MODULE_ALIGN; type=6
|
||||||
|
dw 0 ; flag
|
||||||
|
dd 8 ; size
|
||||||
|
;====================
|
||||||
|
align MULTIBOOT_INFO_ALIGN
|
||||||
|
dw MULTIBOOT_HEADER_TAG_END
|
||||||
|
dw 0 ; flag
|
||||||
|
dd 8 ; size
|
||||||
|
;====================
|
||||||
|
ASM_MULTIBOOT_HEADER_SIZE equ ($ - start_hdr)
|
||||||
|
|
||||||
|
section .text
|
||||||
|
bits 32
|
||||||
|
sys_entry:
|
||||||
|
cli
|
||||||
|
cld
|
||||||
|
cmp eax, MULTIBOOT2_BOOTLOADER_MAGIC
|
||||||
|
jne .end
|
||||||
|
|
||||||
|
; save multiboot info
|
||||||
|
mov dword [GET_PADDR(multiboot_info_ptr)], ebx
|
||||||
|
|
||||||
|
; setup stack
|
||||||
|
call check_long_mode ; check support for long mode
|
||||||
|
cmp eax, 1
|
||||||
|
jne .end
|
||||||
|
|
||||||
|
; disable paging first
|
||||||
|
mov eax, cr0 ; Set the A-register to control register 0.
|
||||||
|
and eax, ~(1 << 31) & 0xFFFFFFFF ; Clear the PG-bit, which is bit 31, and hack to get rid of warning
|
||||||
|
mov cr0, eax ; Set control register 0 to the A-register.
|
||||||
|
|
||||||
|
|
||||||
|
; point the first PML4 entry to the identity pdpt
|
||||||
|
mov eax, GET_PADDR(init_pml4)
|
||||||
|
mov dword [eax], GET_PADDR(init_pdpt_iden) + 11b ; write the lower bits, higher = 0
|
||||||
|
|
||||||
|
; point the nth PML4 entry to the kernel pdpt
|
||||||
|
mov eax, GET_PADDR(init_pml4) + GET_PML4(KERNEL_IMAGE_VADDR) * 8
|
||||||
|
mov dword [eax], GET_PADDR(init_pdpt_kern) + 11b
|
||||||
|
|
||||||
|
; point the nth PML4 entry to the kernel pmap pdpt
|
||||||
|
mov eax, GET_PADDR(init_pml4) + GET_PML4(KERNEL_PMAP_VADDR) * 8
|
||||||
|
mov dword [eax], GET_PADDR(init_pdpt_pmap) + 11b
|
||||||
|
|
||||||
|
; identity map the first 4GB and to kernel pmap region
|
||||||
|
mov eax, GET_PADDR(init_pdpt_iden)
|
||||||
|
mov edx, GET_PADDR(init_pdpt_pmap)
|
||||||
|
mov ebx, 10000011b ; R/W + SU + 1G page
|
||||||
|
mov ecx, 4 ; loop 4 times
|
||||||
|
.l0:
|
||||||
|
mov dword [eax], ebx
|
||||||
|
mov dword [edx], ebx
|
||||||
|
add ebx, 1*1024*1024*1024 ; 1G
|
||||||
|
add eax, 8
|
||||||
|
add edx, 8
|
||||||
|
loop .l0
|
||||||
|
|
||||||
|
; map the first 1 GB, which contains the kernel, to KERNEL_BASE_VADDR
|
||||||
|
mov eax, GET_PADDR(init_pdpt_kern)
|
||||||
|
; extract the PML4 entry
|
||||||
|
add eax, GET_PDPT(KERNEL_IMAGE_VADDR) * 8
|
||||||
|
mov ebx, 10000011b ; R/W + SU + 1G page
|
||||||
|
mov dword [eax], ebx
|
||||||
|
|
||||||
|
|
||||||
|
; enable PAE
|
||||||
|
mov eax, cr4 ; Set the A-register to control register 4.
|
||||||
|
or eax, 1 << 5 ; Set the PAE-bit, which is the 6th bit (bit 5).
|
||||||
|
mov cr4, eax ; Set control register 4 to the A-register.
|
||||||
|
|
||||||
|
; enable long mode
|
||||||
|
mov ecx, 0xC0000080 ; Set the C-register to 0xC0000080, which is the EFER MSR.
|
||||||
|
rdmsr ; Read from the model-specific register.
|
||||||
|
or eax, 1 << 8 ; Set the LM-bit which is the 9th bit (bit 8).
|
||||||
|
wrmsr ; Write to the model-specific register.
|
||||||
|
|
||||||
|
|
||||||
|
; let cr3 point at page table
|
||||||
|
mov eax, GET_PADDR(init_pml4)
|
||||||
|
mov cr3, eax
|
||||||
|
|
||||||
|
; enable paging, enter compatibility mode
|
||||||
|
mov eax, cr0 ; Set the A-register to control register 0.
|
||||||
|
or eax, 1 << 31 ; Set the PG-bit, which is bit 31.
|
||||||
|
mov cr0, eax ; Set control register 0 to the A-register.
|
||||||
|
|
||||||
|
; now we are in compat mode
|
||||||
|
|
||||||
|
; load the long mode GDT
|
||||||
|
lgdt [GET_PADDR(init_gdt.ptr)]
|
||||||
|
|
||||||
|
; switch to long mode
|
||||||
|
jmp init_gdt.code:GET_PADDR(sys_entry_64)
|
||||||
|
.end:
|
||||||
|
hlt
|
||||||
|
|
||||||
|
check_long_mode:
|
||||||
|
push ebp
|
||||||
|
mov ebp,esp
|
||||||
|
pushfd
|
||||||
|
pop eax
|
||||||
|
mov ecx, eax
|
||||||
|
xor eax, 1 << 21
|
||||||
|
push eax
|
||||||
|
popfd
|
||||||
|
pushfd
|
||||||
|
pop eax
|
||||||
|
push ecx
|
||||||
|
popfd
|
||||||
|
xor eax, ecx
|
||||||
|
jz .not_supported
|
||||||
|
mov eax, 0x80000000 ; Set the A-register to 0x80000000.
|
||||||
|
cpuid ; CPU identification.
|
||||||
|
cmp eax, 0x80000001 ; Compare the A-register with 0x80000001.
|
||||||
|
jb .not_supported ; It is less, there is no long mode.
|
||||||
|
mov eax, 0x80000001 ; Set the A-register to 0x80000001.
|
||||||
|
cpuid ; CPU identification.
|
||||||
|
test edx, 1 << 29 ; Test if the LM-bit, which is bit 29, is set in the D-register.
|
||||||
|
jz .not_supported ; They arent, there is no long mode.
|
||||||
|
mov eax,1
|
||||||
|
jmp .end
|
||||||
|
.not_supported:
|
||||||
|
xor eax,eax
|
||||||
|
.end:
|
||||||
|
mov esp,ebp
|
||||||
|
pop ebp
|
||||||
|
ret
|
||||||
|
|
||||||
|
section .data
|
||||||
|
bits 32
|
||||||
|
multiboot_info_ptr:
|
||||||
|
dd 0
|
||||||
|
|
||||||
|
section .text
|
||||||
|
bits 64
|
||||||
|
sys_entry_64:
|
||||||
|
; note that we are in long mode but rip is still lower
|
||||||
|
; switch to high address
|
||||||
|
mov rax, .high
|
||||||
|
jmp rax
|
||||||
|
.high:
|
||||||
|
|
||||||
|
; set ds segment
|
||||||
|
mov rax,init_gdt.data
|
||||||
|
mov ds, rax
|
||||||
|
|
||||||
|
; map GDT into virtual address space
|
||||||
|
mov qword [init_gdt.ptr + 2], init_gdt
|
||||||
|
lgdt [init_gdt.ptr]
|
||||||
|
|
||||||
|
;reload cs
|
||||||
|
push qword init_gdt.data ; ss
|
||||||
|
push qword init_stack ; rsp
|
||||||
|
pushfq
|
||||||
|
push qword init_gdt.code ; cs
|
||||||
|
push qword .reload ; rip
|
||||||
|
iretq
|
||||||
|
.reload:
|
||||||
|
mov rax, ss
|
||||||
|
mov ds, rax
|
||||||
|
mov es, rax
|
||||||
|
mov fs, rax
|
||||||
|
mov gs, rax
|
||||||
|
|
||||||
|
; unmap the first 4GB because we don't need them anymore
|
||||||
|
mov rax, GET_PADDR(init_pml4)
|
||||||
|
mov qword [rax], 0 ;
|
||||||
|
|
||||||
|
; flush TLB
|
||||||
|
mov rax, cr3
|
||||||
|
mov cr3, rax
|
||||||
|
|
||||||
|
; kernel is now in only -2GB mode
|
||||||
|
xor rdi, rdi
|
||||||
|
mov edi, dword [multiboot_info_ptr]
|
||||||
|
mov rax, KERNEL_PMAP_VADDR
|
||||||
|
add rdi, rax
|
||||||
|
|
||||||
|
call kmain
|
||||||
|
.end:
|
||||||
|
hlt
|
||||||
|
|
||||||
|
|
||||||
|
section .data
|
||||||
|
bits 64
|
||||||
|
align KERNEL_PAGE_SIZE
|
||||||
|
times KERNEL_PAGE_SIZE db 0
|
||||||
|
init_stack:
|
||||||
|
|
||||||
|
init_pml4:
|
||||||
|
align KERNEL_PAGE_SIZE
|
||||||
|
times KERNEL_PAGE_SIZE db 0
|
||||||
|
|
||||||
|
init_pdpt_iden:
|
||||||
|
align KERNEL_PAGE_SIZE
|
||||||
|
times KERNEL_PAGE_SIZE db 0
|
||||||
|
|
||||||
|
init_pdpt_pmap:
|
||||||
|
align KERNEL_PAGE_SIZE
|
||||||
|
times KERNEL_PAGE_SIZE db 0
|
||||||
|
|
||||||
|
init_pdpt_kern:
|
||||||
|
align KERNEL_PAGE_SIZE
|
||||||
|
times KERNEL_PAGE_SIZE db 0
|
||||||
|
|
||||||
|
init_gdt: ; Global Descriptor Table (long mode).
|
||||||
|
.null: equ $ - init_gdt ; The null descriptor.
|
||||||
|
dw 0 ; Limit (low).
|
||||||
|
dw 0 ; Base (low).
|
||||||
|
db 0 ; Base (middle)
|
||||||
|
db 0 ; Access.
|
||||||
|
db 0 ; Granularity.
|
||||||
|
db 0 ; Base (high).
|
||||||
|
.code: equ $ - init_gdt ; The code descriptor.
|
||||||
|
dw 0 ; Limit (low).
|
||||||
|
dw 0 ; Base (low).
|
||||||
|
db 0 ; Base (middle)
|
||||||
|
db 10011010b ; Access (exec/read).
|
||||||
|
db 00100000b ; Granularity.
|
||||||
|
db 0 ; Base (high).
|
||||||
|
.data: equ $ - init_gdt ; The data descriptor.
|
||||||
|
dw 0 ; Limit (low).
|
||||||
|
dw 0 ; Base (low).
|
||||||
|
db 0 ; Base (middle)
|
||||||
|
db 10010010b ; Access (read/write).
|
||||||
|
db 00100000b ; Granularity.
|
||||||
|
db 0 ; Base (high).
|
||||||
|
.ptr:
|
||||||
|
; GDT PTR
|
||||||
|
dw $ - init_gdt - 1 ; Limit.
|
||||||
|
dq GET_PADDR(init_gdt) ; Base.
|
89
src/clib.c
Normal file
89
src/clib.c
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
#include "clib.h"
|
||||||
|
#include "print.h"
|
||||||
|
#include "intr.h"
|
||||||
|
|
||||||
|
void
|
||||||
|
mem_cpy(void *src, void *dst, uint64 size)
|
||||||
|
{
|
||||||
|
char *cSrc = (char *) src;
|
||||||
|
char *cDst = (char *) dst;
|
||||||
|
while (size--)
|
||||||
|
{
|
||||||
|
*(cDst++) = *(cSrc++);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
mem_set(void *src, uint8 val, uint64 size)
|
||||||
|
{
|
||||||
|
while (size--)
|
||||||
|
{
|
||||||
|
*(uint8 *) src = val;
|
||||||
|
src = (void *) ((uintptr) src + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
mem_mv(void *src, void *dst, uint64 size)
|
||||||
|
{
|
||||||
|
if (src >= dst)
|
||||||
|
{
|
||||||
|
mem_cpy(src, dst, size);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
src = (void *) ((uintptr) src + size - 1);
|
||||||
|
dst = (void *) ((uintptr) dst + size - 1);
|
||||||
|
while (size--)
|
||||||
|
{
|
||||||
|
*(char *) dst = *(char *) src;
|
||||||
|
dst = (void *) ((uintptr) dst - 1);
|
||||||
|
src = (void *) ((uintptr) src - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64
|
||||||
|
str_len(char const *str)
|
||||||
|
{
|
||||||
|
uint64 length = 0;
|
||||||
|
while (*str != 0)
|
||||||
|
{
|
||||||
|
str++;
|
||||||
|
length++;
|
||||||
|
}
|
||||||
|
return length;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64
|
||||||
|
str_cmp(char const *str1, char const *str2)
|
||||||
|
{
|
||||||
|
uint64 length = str_len(str1);
|
||||||
|
if (length != str_len(str2))
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
while (length--)
|
||||||
|
{
|
||||||
|
if (*(str1 + length) != *(str2 + length))
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
poor_sleep(uint32 dat)
|
||||||
|
{
|
||||||
|
for(uint32 i = 0; i < dat; i++)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void kassert_ex(const char *expr_str, const char *file, int32 line, int32 expr)
|
||||||
|
{
|
||||||
|
if (!expr)
|
||||||
|
{
|
||||||
|
kprintf("Assertion \"%s\" failed at %s:%d.\n", expr_str, file, line);
|
||||||
|
stop_cpu();
|
||||||
|
}
|
||||||
|
}
|
201
src/cpu.asm
Normal file
201
src/cpu.asm
Normal file
@ -0,0 +1,201 @@
|
|||||||
|
section .text
|
||||||
|
bits 64
|
||||||
|
|
||||||
|
global out_8
|
||||||
|
global out_16
|
||||||
|
global out_32
|
||||||
|
global in_8
|
||||||
|
global in_16
|
||||||
|
global in_32
|
||||||
|
global read_msr
|
||||||
|
global read_cr8
|
||||||
|
global write_cr8
|
||||||
|
global write_msr
|
||||||
|
global cpuid
|
||||||
|
global flush_gdt
|
||||||
|
global flush_idt
|
||||||
|
global cmpxchg_32
|
||||||
|
global xinc_32
|
||||||
|
global cli
|
||||||
|
global sti
|
||||||
|
global read_cr3
|
||||||
|
global write_cr3
|
||||||
|
global flush_tlb
|
||||||
|
global hlt
|
||||||
|
global flush_tss
|
||||||
|
|
||||||
|
flush_tss:
|
||||||
|
mov ax, di
|
||||||
|
ltr ax
|
||||||
|
ret
|
||||||
|
|
||||||
|
hlt:
|
||||||
|
hlt
|
||||||
|
ret
|
||||||
|
|
||||||
|
flush_tlb:
|
||||||
|
mov rax, cr3
|
||||||
|
mov cr3, rax
|
||||||
|
ret
|
||||||
|
|
||||||
|
read_cr3:
|
||||||
|
mov rax, cr3
|
||||||
|
ret
|
||||||
|
|
||||||
|
write_cr3:
|
||||||
|
mov cr3, rdi
|
||||||
|
ret
|
||||||
|
|
||||||
|
read_cr8:
|
||||||
|
mov rax, cr8
|
||||||
|
ret
|
||||||
|
|
||||||
|
write_cr8:
|
||||||
|
mov cr8, rdi
|
||||||
|
ret
|
||||||
|
|
||||||
|
cli:
|
||||||
|
cli
|
||||||
|
ret
|
||||||
|
|
||||||
|
sti:
|
||||||
|
sti
|
||||||
|
ret
|
||||||
|
|
||||||
|
out_32:
|
||||||
|
mov rdx,rdi
|
||||||
|
mov rax,rsi
|
||||||
|
out dx,eax
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
out_16:
|
||||||
|
mov rdx,rdi
|
||||||
|
mov rax,rsi
|
||||||
|
out dx,ax
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
out_8:
|
||||||
|
mov rdx,rdi
|
||||||
|
mov rax,rsi
|
||||||
|
out dx,al
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
in_8:
|
||||||
|
mov rdx,rdi
|
||||||
|
xor rax,rax
|
||||||
|
in al,dx
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
ret
|
||||||
|
|
||||||
|
in_16:
|
||||||
|
mov rdx,rdi
|
||||||
|
xor rax,rax
|
||||||
|
in ax,dx
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
in_32:
|
||||||
|
mov rdx,rdi
|
||||||
|
xor rax,rax
|
||||||
|
in eax,dx
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
ret
|
||||||
|
|
||||||
|
read_msr:
|
||||||
|
; preserve rdx
|
||||||
|
push rdx
|
||||||
|
mov ecx, dword [rdi]
|
||||||
|
rdmsr
|
||||||
|
mov dword [rdi], ecx
|
||||||
|
mov dword [rsi], edx
|
||||||
|
pop r11
|
||||||
|
mov dword [r11], eax
|
||||||
|
ret
|
||||||
|
|
||||||
|
write_msr:
|
||||||
|
mov ecx, dword [rdi]
|
||||||
|
mov eax, dword [rdx]
|
||||||
|
mov edx, dword [rsi]
|
||||||
|
wrmsr
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
cpuid:
|
||||||
|
push rbp
|
||||||
|
mov rbp,rsp
|
||||||
|
; preserve rbx,rcx,rdx
|
||||||
|
push rbx
|
||||||
|
push rcx
|
||||||
|
push rdx
|
||||||
|
; cpuid parameters eax,ecx
|
||||||
|
mov eax, dword [rdi]
|
||||||
|
mov ecx, dword [rdx]
|
||||||
|
cpuid
|
||||||
|
; write results back to memory
|
||||||
|
mov dword [rdi], eax
|
||||||
|
mov dword [rsi], ebx
|
||||||
|
pop r11
|
||||||
|
mov dword [r11], ecx
|
||||||
|
pop r11
|
||||||
|
mov dword [r11], edx
|
||||||
|
pop rbx
|
||||||
|
mov rsp,rbp
|
||||||
|
pop rbp
|
||||||
|
ret
|
||||||
|
|
||||||
|
flush_gdt:
|
||||||
|
push rbp
|
||||||
|
mov rbp, rsp
|
||||||
|
lgdt [rdi]
|
||||||
|
|
||||||
|
;reload cs
|
||||||
|
push rdx ; data_slct : ss
|
||||||
|
push rbp ; rsp
|
||||||
|
pushfq
|
||||||
|
push rsi ; cs
|
||||||
|
mov rax, .reload
|
||||||
|
push rax ;rip
|
||||||
|
iretq
|
||||||
|
.reload:
|
||||||
|
mov es,rdx
|
||||||
|
mov fs,rdx
|
||||||
|
mov gs,rdx
|
||||||
|
mov ds,rdx
|
||||||
|
pop rbp
|
||||||
|
ret
|
||||||
|
|
||||||
|
flush_idt:
|
||||||
|
lidt [rdi]
|
||||||
|
ret
|
||||||
|
|
||||||
|
; ============================
|
||||||
|
cmpxchg_32:
|
||||||
|
mov eax, esi; eax = test_node_compare
|
||||||
|
lock cmpxchg dword [rdi], edx ; edx = val, rdi = ptr to dst
|
||||||
|
ret
|
||||||
|
|
||||||
|
; ============================
|
||||||
|
xinc_32:
|
||||||
|
lock xadd dword [rdi], esi ; [rdi] = [rdi] + esi, esi = old [rdi]
|
||||||
|
xor rax, rax
|
||||||
|
mov eax, esi
|
||||||
|
ret
|
145
src/elf64.c
Normal file
145
src/elf64.c
Normal file
@ -0,0 +1,145 @@
|
|||||||
|
#include <elf64.h>
|
||||||
|
#include <cdef.h>
|
||||||
|
#include <error.h>
|
||||||
|
#include <paging.h>
|
||||||
|
#include <pmm.h>
|
||||||
|
#include <print.h>
|
||||||
|
#include <clib.h>
|
||||||
|
|
||||||
|
bool
|
||||||
|
elf_check_file(elf64_hdr *hdr)
|
||||||
|
{
|
||||||
|
if (!hdr)
|
||||||
|
{ return 0; }
|
||||||
|
if (hdr->e_ident[EI_MAG0] != ELFMAG0)
|
||||||
|
{ return 0; }
|
||||||
|
if (hdr->e_ident[EI_MAG1] != ELFMAG1)
|
||||||
|
{ return 0; }
|
||||||
|
if (hdr->e_ident[EI_MAG2] != ELFMAG2)
|
||||||
|
{ return 0; }
|
||||||
|
if (hdr->e_ident[EI_MAG3] != ELFMAG3)
|
||||||
|
{ return 0; }
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
elf_check_supported(elf64_hdr *hdr)
|
||||||
|
{
|
||||||
|
if (!elf_check_file(hdr))
|
||||||
|
{ return 0; }
|
||||||
|
if (hdr->e_ident[EI_CLASS] != ELFCLASS64)
|
||||||
|
{ return 0; }
|
||||||
|
if (hdr->e_ident[EI_DATA] != ELFDATA2LSB)
|
||||||
|
{ return 0; } // TODO : May not be true
|
||||||
|
//if (hdr->e_machine != EM_386) return 0; // TODO : CHECK
|
||||||
|
if (hdr->e_ident[EI_VERSION] != EV_CURRENT)
|
||||||
|
{ return 0; }
|
||||||
|
if (hdr->e_type != ET_EXEC)
|
||||||
|
{ return 0; }
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int32 elf_load_seg(struct pcb *proc, void* file, elf64_phdr* hdr)
|
||||||
|
{
|
||||||
|
void *seg_start = (void*)((uintptr)file + hdr->p_offset);
|
||||||
|
void *vaddr = (void*)hdr->p_vaddr;
|
||||||
|
usize file_size = hdr->p_filesz;
|
||||||
|
usize mem_size = hdr->p_memsz;
|
||||||
|
|
||||||
|
int32 ret = ESUCCESS;
|
||||||
|
if (((uintptr) vaddr & 0xfff) != 0)
|
||||||
|
{
|
||||||
|
// alignment
|
||||||
|
ret = EINVARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret == ESUCCESS)
|
||||||
|
{
|
||||||
|
uint32 num_pages = ((uint32)mem_size + KERNEL_PAGE_SIZE - 1) / KERNEL_PAGE_SIZE;
|
||||||
|
|
||||||
|
// allocate memory
|
||||||
|
for (uint32 i = 0; i < num_pages; i++)
|
||||||
|
{
|
||||||
|
// map pages
|
||||||
|
uintptr page = (uintptr) pmalloc(KERNEL_PAGE_SIZE);
|
||||||
|
if (page == (uintptr) NULL)
|
||||||
|
{
|
||||||
|
ret = ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret == ESUCCESS)
|
||||||
|
{
|
||||||
|
ret = map_vmem(proc->cr3, (uintptr) vaddr, page);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret == ESUCCESS)
|
||||||
|
{
|
||||||
|
usize cpy_size = file_size > KERNEL_PAGE_SIZE ? KERNEL_PAGE_SIZE : (file_size % KERNEL_PAGE_SIZE);
|
||||||
|
// copy the current segment
|
||||||
|
mem_cpy(seg_start, R_PADDR(page), cpy_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret != ESUCCESS)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
vaddr = (void *) ((uintptr) vaddr + KERNEL_PAGE_SIZE);
|
||||||
|
seg_start = (void *) ((uintptr) seg_start + KERNEL_PAGE_SIZE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret != ESUCCESS)
|
||||||
|
{
|
||||||
|
// cleanup
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32
|
||||||
|
elf_load_file(struct pcb *proc, void *file, void **entry)
|
||||||
|
{
|
||||||
|
int32 ret = ESUCCESS;
|
||||||
|
elf64_hdr *hdr = (elf64_hdr *) file;
|
||||||
|
if (!elf_check_supported(hdr))
|
||||||
|
{
|
||||||
|
ret = EINVARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret == ESUCCESS)
|
||||||
|
{
|
||||||
|
elf64_phdr *phdr_start = (elf64_phdr *) ((uintptr) file + hdr->e_phoff);
|
||||||
|
// load program segments
|
||||||
|
for (int i = 0; i < hdr->e_phnum; i++)
|
||||||
|
{
|
||||||
|
elf64_phdr *each_seg = (elf64_phdr *) ((uintptr) phdr_start + i * hdr->e_phentsize);
|
||||||
|
if (each_seg->p_type == PT_LOAD)
|
||||||
|
{
|
||||||
|
// load segment
|
||||||
|
ret = elf_load_seg(proc, file, each_seg);
|
||||||
|
#ifdef KDBG
|
||||||
|
if (ret == ESUCCESS)
|
||||||
|
{
|
||||||
|
kprintf("Loaded segment offset 0x%x to vaddr 0x%x, fs: %d, ms: %d\n", (uint64) each_seg->p_offset,
|
||||||
|
(uint64) each_seg->p_vaddr, (uint64) each_seg->p_filesz, (uint64) each_seg->p_memsz);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
if (ret != ESUCCESS)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret == ESUCCESS)
|
||||||
|
{
|
||||||
|
// write back entry
|
||||||
|
*entry = (void *) hdr->e_entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
566
src/intr.asm
Normal file
566
src/intr.asm
Normal file
@ -0,0 +1,566 @@
|
|||||||
|
%include "asm.inc"
|
||||||
|
|
||||||
|
extern intr_dispatcher
|
||||||
|
global intr_stub_array
|
||||||
|
|
||||||
|
section .data
|
||||||
|
bits 64
|
||||||
|
intr_stub_array:
|
||||||
|
dq intr_stub_0
|
||||||
|
dq intr_stub_1
|
||||||
|
dq intr_stub_2
|
||||||
|
dq intr_stub_3
|
||||||
|
dq intr_stub_4
|
||||||
|
dq intr_stub_5
|
||||||
|
dq intr_stub_6
|
||||||
|
dq intr_stub_7
|
||||||
|
dq intr_stub_8
|
||||||
|
dq intr_stub_9
|
||||||
|
dq intr_stub_10
|
||||||
|
dq intr_stub_11
|
||||||
|
dq intr_stub_12
|
||||||
|
dq intr_stub_13
|
||||||
|
dq intr_stub_14
|
||||||
|
dq intr_stub_15
|
||||||
|
dq intr_stub_16
|
||||||
|
dq intr_stub_17
|
||||||
|
dq intr_stub_18
|
||||||
|
dq intr_stub_19
|
||||||
|
dq intr_stub_20
|
||||||
|
dq intr_stub_21
|
||||||
|
dq intr_stub_22
|
||||||
|
dq intr_stub_23
|
||||||
|
dq intr_stub_24
|
||||||
|
dq intr_stub_25
|
||||||
|
dq intr_stub_26
|
||||||
|
dq intr_stub_27
|
||||||
|
dq intr_stub_28
|
||||||
|
dq intr_stub_29
|
||||||
|
dq intr_stub_30
|
||||||
|
dq intr_stub_31
|
||||||
|
dq intr_stub_32
|
||||||
|
dq intr_stub_33
|
||||||
|
dq intr_stub_34
|
||||||
|
dq intr_stub_35
|
||||||
|
dq intr_stub_36
|
||||||
|
dq intr_stub_37
|
||||||
|
dq intr_stub_38
|
||||||
|
dq intr_stub_39
|
||||||
|
dq intr_stub_40
|
||||||
|
dq intr_stub_41
|
||||||
|
dq intr_stub_42
|
||||||
|
dq intr_stub_43
|
||||||
|
dq intr_stub_44
|
||||||
|
dq intr_stub_45
|
||||||
|
dq intr_stub_46
|
||||||
|
dq intr_stub_47
|
||||||
|
dq intr_stub_48
|
||||||
|
dq intr_stub_49
|
||||||
|
dq intr_stub_50
|
||||||
|
dq intr_stub_51
|
||||||
|
dq intr_stub_52
|
||||||
|
dq intr_stub_53
|
||||||
|
dq intr_stub_54
|
||||||
|
dq intr_stub_55
|
||||||
|
dq intr_stub_56
|
||||||
|
dq intr_stub_57
|
||||||
|
dq intr_stub_58
|
||||||
|
dq intr_stub_59
|
||||||
|
dq intr_stub_60
|
||||||
|
dq intr_stub_61
|
||||||
|
dq intr_stub_62
|
||||||
|
dq intr_stub_63
|
||||||
|
dq intr_stub_64
|
||||||
|
dq intr_stub_65
|
||||||
|
dq intr_stub_66
|
||||||
|
dq intr_stub_67
|
||||||
|
dq intr_stub_68
|
||||||
|
dq intr_stub_69
|
||||||
|
dq intr_stub_70
|
||||||
|
dq intr_stub_71
|
||||||
|
dq intr_stub_72
|
||||||
|
dq intr_stub_73
|
||||||
|
dq intr_stub_74
|
||||||
|
dq intr_stub_75
|
||||||
|
dq intr_stub_76
|
||||||
|
dq intr_stub_77
|
||||||
|
dq intr_stub_78
|
||||||
|
dq intr_stub_79
|
||||||
|
dq intr_stub_80
|
||||||
|
dq intr_stub_81
|
||||||
|
dq intr_stub_82
|
||||||
|
dq intr_stub_83
|
||||||
|
dq intr_stub_84
|
||||||
|
dq intr_stub_85
|
||||||
|
dq intr_stub_86
|
||||||
|
dq intr_stub_87
|
||||||
|
dq intr_stub_88
|
||||||
|
dq intr_stub_89
|
||||||
|
dq intr_stub_90
|
||||||
|
dq intr_stub_91
|
||||||
|
dq intr_stub_92
|
||||||
|
dq intr_stub_93
|
||||||
|
dq intr_stub_94
|
||||||
|
dq intr_stub_95
|
||||||
|
dq intr_stub_96
|
||||||
|
dq intr_stub_97
|
||||||
|
dq intr_stub_98
|
||||||
|
dq intr_stub_99
|
||||||
|
dq intr_stub_100
|
||||||
|
dq intr_stub_101
|
||||||
|
dq intr_stub_102
|
||||||
|
dq intr_stub_103
|
||||||
|
dq intr_stub_104
|
||||||
|
dq intr_stub_105
|
||||||
|
dq intr_stub_106
|
||||||
|
dq intr_stub_107
|
||||||
|
dq intr_stub_108
|
||||||
|
dq intr_stub_109
|
||||||
|
dq intr_stub_110
|
||||||
|
dq intr_stub_111
|
||||||
|
dq intr_stub_112
|
||||||
|
dq intr_stub_113
|
||||||
|
dq intr_stub_114
|
||||||
|
dq intr_stub_115
|
||||||
|
dq intr_stub_116
|
||||||
|
dq intr_stub_117
|
||||||
|
dq intr_stub_118
|
||||||
|
dq intr_stub_119
|
||||||
|
dq intr_stub_120
|
||||||
|
dq intr_stub_121
|
||||||
|
dq intr_stub_122
|
||||||
|
dq intr_stub_123
|
||||||
|
dq intr_stub_124
|
||||||
|
dq intr_stub_125
|
||||||
|
dq intr_stub_126
|
||||||
|
dq intr_stub_127
|
||||||
|
dq intr_stub_128
|
||||||
|
dq intr_stub_129
|
||||||
|
dq intr_stub_130
|
||||||
|
dq intr_stub_131
|
||||||
|
dq intr_stub_132
|
||||||
|
dq intr_stub_133
|
||||||
|
dq intr_stub_134
|
||||||
|
dq intr_stub_135
|
||||||
|
dq intr_stub_136
|
||||||
|
dq intr_stub_137
|
||||||
|
dq intr_stub_138
|
||||||
|
dq intr_stub_139
|
||||||
|
dq intr_stub_140
|
||||||
|
dq intr_stub_141
|
||||||
|
dq intr_stub_142
|
||||||
|
dq intr_stub_143
|
||||||
|
dq intr_stub_144
|
||||||
|
dq intr_stub_145
|
||||||
|
dq intr_stub_146
|
||||||
|
dq intr_stub_147
|
||||||
|
dq intr_stub_148
|
||||||
|
dq intr_stub_149
|
||||||
|
dq intr_stub_150
|
||||||
|
dq intr_stub_151
|
||||||
|
dq intr_stub_152
|
||||||
|
dq intr_stub_153
|
||||||
|
dq intr_stub_154
|
||||||
|
dq intr_stub_155
|
||||||
|
dq intr_stub_156
|
||||||
|
dq intr_stub_157
|
||||||
|
dq intr_stub_158
|
||||||
|
dq intr_stub_159
|
||||||
|
dq intr_stub_160
|
||||||
|
dq intr_stub_161
|
||||||
|
dq intr_stub_162
|
||||||
|
dq intr_stub_163
|
||||||
|
dq intr_stub_164
|
||||||
|
dq intr_stub_165
|
||||||
|
dq intr_stub_166
|
||||||
|
dq intr_stub_167
|
||||||
|
dq intr_stub_168
|
||||||
|
dq intr_stub_169
|
||||||
|
dq intr_stub_170
|
||||||
|
dq intr_stub_171
|
||||||
|
dq intr_stub_172
|
||||||
|
dq intr_stub_173
|
||||||
|
dq intr_stub_174
|
||||||
|
dq intr_stub_175
|
||||||
|
dq intr_stub_176
|
||||||
|
dq intr_stub_177
|
||||||
|
dq intr_stub_178
|
||||||
|
dq intr_stub_179
|
||||||
|
dq intr_stub_180
|
||||||
|
dq intr_stub_181
|
||||||
|
dq intr_stub_182
|
||||||
|
dq intr_stub_183
|
||||||
|
dq intr_stub_184
|
||||||
|
dq intr_stub_185
|
||||||
|
dq intr_stub_186
|
||||||
|
dq intr_stub_187
|
||||||
|
dq intr_stub_188
|
||||||
|
dq intr_stub_189
|
||||||
|
dq intr_stub_190
|
||||||
|
dq intr_stub_191
|
||||||
|
dq intr_stub_192
|
||||||
|
dq intr_stub_193
|
||||||
|
dq intr_stub_194
|
||||||
|
dq intr_stub_195
|
||||||
|
dq intr_stub_196
|
||||||
|
dq intr_stub_197
|
||||||
|
dq intr_stub_198
|
||||||
|
dq intr_stub_199
|
||||||
|
dq intr_stub_200
|
||||||
|
dq intr_stub_201
|
||||||
|
dq intr_stub_202
|
||||||
|
dq intr_stub_203
|
||||||
|
dq intr_stub_204
|
||||||
|
dq intr_stub_205
|
||||||
|
dq intr_stub_206
|
||||||
|
dq intr_stub_207
|
||||||
|
dq intr_stub_208
|
||||||
|
dq intr_stub_209
|
||||||
|
dq intr_stub_210
|
||||||
|
dq intr_stub_211
|
||||||
|
dq intr_stub_212
|
||||||
|
dq intr_stub_213
|
||||||
|
dq intr_stub_214
|
||||||
|
dq intr_stub_215
|
||||||
|
dq intr_stub_216
|
||||||
|
dq intr_stub_217
|
||||||
|
dq intr_stub_218
|
||||||
|
dq intr_stub_219
|
||||||
|
dq intr_stub_220
|
||||||
|
dq intr_stub_221
|
||||||
|
dq intr_stub_222
|
||||||
|
dq intr_stub_223
|
||||||
|
dq intr_stub_224
|
||||||
|
dq intr_stub_225
|
||||||
|
dq intr_stub_226
|
||||||
|
dq intr_stub_227
|
||||||
|
dq intr_stub_228
|
||||||
|
dq intr_stub_229
|
||||||
|
dq intr_stub_230
|
||||||
|
dq intr_stub_231
|
||||||
|
dq intr_stub_232
|
||||||
|
dq intr_stub_233
|
||||||
|
dq intr_stub_234
|
||||||
|
dq intr_stub_235
|
||||||
|
dq intr_stub_236
|
||||||
|
dq intr_stub_237
|
||||||
|
dq intr_stub_238
|
||||||
|
dq intr_stub_239
|
||||||
|
dq intr_stub_240
|
||||||
|
dq intr_stub_241
|
||||||
|
dq intr_stub_242
|
||||||
|
dq intr_stub_243
|
||||||
|
dq intr_stub_244
|
||||||
|
dq intr_stub_245
|
||||||
|
dq intr_stub_246
|
||||||
|
dq intr_stub_247
|
||||||
|
dq intr_stub_248
|
||||||
|
dq intr_stub_249
|
||||||
|
dq intr_stub_250
|
||||||
|
dq intr_stub_251
|
||||||
|
dq intr_stub_252
|
||||||
|
dq intr_stub_253
|
||||||
|
dq intr_stub_254
|
||||||
|
dq intr_stub_255
|
||||||
|
|
||||||
|
section .text
|
||||||
|
bits 64
|
||||||
|
|
||||||
|
%macro decl_err_intr_stub 1
|
||||||
|
intr_stub_%1:
|
||||||
|
; save context
|
||||||
|
PUSH_REGS
|
||||||
|
push qword %1
|
||||||
|
jmp intr_stub
|
||||||
|
%endmacro
|
||||||
|
|
||||||
|
%macro decl_intr_stub 1
|
||||||
|
intr_stub_%1:
|
||||||
|
; push dummy error code to have consistent frame
|
||||||
|
push qword 0
|
||||||
|
PUSH_REGS
|
||||||
|
push qword %1
|
||||||
|
jmp intr_stub
|
||||||
|
%endmacro
|
||||||
|
|
||||||
|
intr_stub:
|
||||||
|
pop rdi
|
||||||
|
mov rsi, rsp
|
||||||
|
call intr_dispatcher
|
||||||
|
; restore registers
|
||||||
|
POP_REGS
|
||||||
|
; skip error code
|
||||||
|
add rsp, 8
|
||||||
|
iretq
|
||||||
|
|
||||||
|
intr_stub_start:
|
||||||
|
decl_intr_stub 0
|
||||||
|
decl_intr_stub 1
|
||||||
|
decl_intr_stub 2
|
||||||
|
decl_intr_stub 3
|
||||||
|
decl_intr_stub 4
|
||||||
|
decl_intr_stub 5
|
||||||
|
decl_intr_stub 6
|
||||||
|
decl_intr_stub 7
|
||||||
|
decl_err_intr_stub 8
|
||||||
|
decl_intr_stub 9
|
||||||
|
decl_err_intr_stub 10
|
||||||
|
decl_err_intr_stub 11
|
||||||
|
decl_err_intr_stub 12
|
||||||
|
decl_err_intr_stub 13
|
||||||
|
decl_err_intr_stub 14
|
||||||
|
decl_intr_stub 15
|
||||||
|
decl_intr_stub 16
|
||||||
|
decl_err_intr_stub 17
|
||||||
|
decl_intr_stub 18
|
||||||
|
decl_intr_stub 19
|
||||||
|
decl_intr_stub 20
|
||||||
|
decl_intr_stub 21
|
||||||
|
decl_intr_stub 22
|
||||||
|
decl_intr_stub 23
|
||||||
|
decl_intr_stub 24
|
||||||
|
decl_intr_stub 25
|
||||||
|
decl_intr_stub 26
|
||||||
|
decl_intr_stub 27
|
||||||
|
decl_intr_stub 28
|
||||||
|
decl_intr_stub 29
|
||||||
|
decl_intr_stub 30
|
||||||
|
decl_intr_stub 31
|
||||||
|
decl_intr_stub 32
|
||||||
|
decl_intr_stub 33
|
||||||
|
decl_intr_stub 34
|
||||||
|
decl_intr_stub 35
|
||||||
|
decl_intr_stub 36
|
||||||
|
decl_intr_stub 37
|
||||||
|
decl_intr_stub 38
|
||||||
|
decl_intr_stub 39
|
||||||
|
decl_intr_stub 40
|
||||||
|
decl_intr_stub 41
|
||||||
|
decl_intr_stub 42
|
||||||
|
decl_intr_stub 43
|
||||||
|
decl_intr_stub 44
|
||||||
|
decl_intr_stub 45
|
||||||
|
decl_intr_stub 46
|
||||||
|
decl_intr_stub 47
|
||||||
|
decl_intr_stub 48
|
||||||
|
decl_intr_stub 49
|
||||||
|
|
||||||
|
intr_stub_50:
|
||||||
|
; push dummy error code to have consistent frame
|
||||||
|
push qword 0
|
||||||
|
PUSH_REGS
|
||||||
|
mov rdi, 50
|
||||||
|
mov rsi, rsp
|
||||||
|
call intr_dispatcher
|
||||||
|
xchg bx,bx
|
||||||
|
; now rax hows the next thread's rsp0
|
||||||
|
mov rsp, rax ; switch stack
|
||||||
|
POP_REGS ; restore registers
|
||||||
|
add rsp, 8 ; skip error code
|
||||||
|
iretq
|
||||||
|
|
||||||
|
decl_intr_stub 51
|
||||||
|
decl_intr_stub 52
|
||||||
|
decl_intr_stub 53
|
||||||
|
decl_intr_stub 54
|
||||||
|
decl_intr_stub 55
|
||||||
|
decl_intr_stub 56
|
||||||
|
decl_intr_stub 57
|
||||||
|
decl_intr_stub 58
|
||||||
|
decl_intr_stub 59
|
||||||
|
decl_intr_stub 60
|
||||||
|
decl_intr_stub 61
|
||||||
|
decl_intr_stub 62
|
||||||
|
decl_intr_stub 63
|
||||||
|
decl_intr_stub 64
|
||||||
|
decl_intr_stub 65
|
||||||
|
decl_intr_stub 66
|
||||||
|
decl_intr_stub 67
|
||||||
|
decl_intr_stub 68
|
||||||
|
decl_intr_stub 69
|
||||||
|
decl_intr_stub 70
|
||||||
|
decl_intr_stub 71
|
||||||
|
decl_intr_stub 72
|
||||||
|
decl_intr_stub 73
|
||||||
|
decl_intr_stub 74
|
||||||
|
decl_intr_stub 75
|
||||||
|
decl_intr_stub 76
|
||||||
|
decl_intr_stub 77
|
||||||
|
decl_intr_stub 78
|
||||||
|
decl_intr_stub 79
|
||||||
|
decl_intr_stub 80
|
||||||
|
decl_intr_stub 81
|
||||||
|
decl_intr_stub 82
|
||||||
|
decl_intr_stub 83
|
||||||
|
decl_intr_stub 84
|
||||||
|
decl_intr_stub 85
|
||||||
|
decl_intr_stub 86
|
||||||
|
decl_intr_stub 87
|
||||||
|
decl_intr_stub 88
|
||||||
|
decl_intr_stub 89
|
||||||
|
decl_intr_stub 90
|
||||||
|
decl_intr_stub 91
|
||||||
|
decl_intr_stub 92
|
||||||
|
decl_intr_stub 93
|
||||||
|
decl_intr_stub 94
|
||||||
|
decl_intr_stub 95
|
||||||
|
decl_intr_stub 96
|
||||||
|
decl_intr_stub 97
|
||||||
|
decl_intr_stub 98
|
||||||
|
decl_intr_stub 99
|
||||||
|
decl_intr_stub 100
|
||||||
|
decl_intr_stub 101
|
||||||
|
decl_intr_stub 102
|
||||||
|
decl_intr_stub 103
|
||||||
|
decl_intr_stub 104
|
||||||
|
decl_intr_stub 105
|
||||||
|
decl_intr_stub 106
|
||||||
|
decl_intr_stub 107
|
||||||
|
decl_intr_stub 108
|
||||||
|
decl_intr_stub 109
|
||||||
|
decl_intr_stub 110
|
||||||
|
decl_intr_stub 111
|
||||||
|
decl_intr_stub 112
|
||||||
|
decl_intr_stub 113
|
||||||
|
decl_intr_stub 114
|
||||||
|
decl_intr_stub 115
|
||||||
|
decl_intr_stub 116
|
||||||
|
decl_intr_stub 117
|
||||||
|
decl_intr_stub 118
|
||||||
|
decl_intr_stub 119
|
||||||
|
decl_intr_stub 120
|
||||||
|
decl_intr_stub 121
|
||||||
|
decl_intr_stub 122
|
||||||
|
decl_intr_stub 123
|
||||||
|
decl_intr_stub 124
|
||||||
|
decl_intr_stub 125
|
||||||
|
decl_intr_stub 126
|
||||||
|
decl_intr_stub 127
|
||||||
|
decl_intr_stub 128
|
||||||
|
decl_intr_stub 129
|
||||||
|
decl_intr_stub 130
|
||||||
|
decl_intr_stub 131
|
||||||
|
decl_intr_stub 132
|
||||||
|
decl_intr_stub 133
|
||||||
|
decl_intr_stub 134
|
||||||
|
decl_intr_stub 135
|
||||||
|
decl_intr_stub 136
|
||||||
|
decl_intr_stub 137
|
||||||
|
decl_intr_stub 138
|
||||||
|
decl_intr_stub 139
|
||||||
|
decl_intr_stub 140
|
||||||
|
decl_intr_stub 141
|
||||||
|
decl_intr_stub 142
|
||||||
|
decl_intr_stub 143
|
||||||
|
decl_intr_stub 144
|
||||||
|
decl_intr_stub 145
|
||||||
|
decl_intr_stub 146
|
||||||
|
decl_intr_stub 147
|
||||||
|
decl_intr_stub 148
|
||||||
|
decl_intr_stub 149
|
||||||
|
decl_intr_stub 150
|
||||||
|
decl_intr_stub 151
|
||||||
|
decl_intr_stub 152
|
||||||
|
decl_intr_stub 153
|
||||||
|
decl_intr_stub 154
|
||||||
|
decl_intr_stub 155
|
||||||
|
decl_intr_stub 156
|
||||||
|
decl_intr_stub 157
|
||||||
|
decl_intr_stub 158
|
||||||
|
decl_intr_stub 159
|
||||||
|
decl_intr_stub 160
|
||||||
|
decl_intr_stub 161
|
||||||
|
decl_intr_stub 162
|
||||||
|
decl_intr_stub 163
|
||||||
|
decl_intr_stub 164
|
||||||
|
decl_intr_stub 165
|
||||||
|
decl_intr_stub 166
|
||||||
|
decl_intr_stub 167
|
||||||
|
decl_intr_stub 168
|
||||||
|
decl_intr_stub 169
|
||||||
|
decl_intr_stub 170
|
||||||
|
decl_intr_stub 171
|
||||||
|
decl_intr_stub 172
|
||||||
|
decl_intr_stub 173
|
||||||
|
decl_intr_stub 174
|
||||||
|
decl_intr_stub 175
|
||||||
|
decl_intr_stub 176
|
||||||
|
decl_intr_stub 177
|
||||||
|
decl_intr_stub 178
|
||||||
|
decl_intr_stub 179
|
||||||
|
decl_intr_stub 180
|
||||||
|
decl_intr_stub 181
|
||||||
|
decl_intr_stub 182
|
||||||
|
decl_intr_stub 183
|
||||||
|
decl_intr_stub 184
|
||||||
|
decl_intr_stub 185
|
||||||
|
decl_intr_stub 186
|
||||||
|
decl_intr_stub 187
|
||||||
|
decl_intr_stub 188
|
||||||
|
decl_intr_stub 189
|
||||||
|
decl_intr_stub 190
|
||||||
|
decl_intr_stub 191
|
||||||
|
decl_intr_stub 192
|
||||||
|
decl_intr_stub 193
|
||||||
|
decl_intr_stub 194
|
||||||
|
decl_intr_stub 195
|
||||||
|
decl_intr_stub 196
|
||||||
|
decl_intr_stub 197
|
||||||
|
decl_intr_stub 198
|
||||||
|
decl_intr_stub 199
|
||||||
|
decl_intr_stub 200
|
||||||
|
decl_intr_stub 201
|
||||||
|
decl_intr_stub 202
|
||||||
|
decl_intr_stub 203
|
||||||
|
decl_intr_stub 204
|
||||||
|
decl_intr_stub 205
|
||||||
|
decl_intr_stub 206
|
||||||
|
decl_intr_stub 207
|
||||||
|
decl_intr_stub 208
|
||||||
|
decl_intr_stub 209
|
||||||
|
decl_intr_stub 210
|
||||||
|
decl_intr_stub 211
|
||||||
|
decl_intr_stub 212
|
||||||
|
decl_intr_stub 213
|
||||||
|
decl_intr_stub 214
|
||||||
|
decl_intr_stub 215
|
||||||
|
decl_intr_stub 216
|
||||||
|
decl_intr_stub 217
|
||||||
|
decl_intr_stub 218
|
||||||
|
decl_intr_stub 219
|
||||||
|
decl_intr_stub 220
|
||||||
|
decl_intr_stub 221
|
||||||
|
decl_intr_stub 222
|
||||||
|
decl_intr_stub 223
|
||||||
|
decl_intr_stub 224
|
||||||
|
decl_intr_stub 225
|
||||||
|
decl_intr_stub 226
|
||||||
|
decl_intr_stub 227
|
||||||
|
decl_intr_stub 228
|
||||||
|
decl_intr_stub 229
|
||||||
|
decl_intr_stub 230
|
||||||
|
decl_intr_stub 231
|
||||||
|
decl_intr_stub 232
|
||||||
|
decl_intr_stub 233
|
||||||
|
decl_intr_stub 234
|
||||||
|
decl_intr_stub 235
|
||||||
|
decl_intr_stub 236
|
||||||
|
decl_intr_stub 237
|
||||||
|
decl_intr_stub 238
|
||||||
|
decl_intr_stub 239
|
||||||
|
decl_intr_stub 240
|
||||||
|
decl_intr_stub 241
|
||||||
|
decl_intr_stub 242
|
||||||
|
decl_intr_stub 243
|
||||||
|
decl_intr_stub 244
|
||||||
|
decl_intr_stub 245
|
||||||
|
decl_intr_stub 246
|
||||||
|
decl_intr_stub 247
|
||||||
|
decl_intr_stub 248
|
||||||
|
decl_intr_stub 249
|
||||||
|
decl_intr_stub 250
|
||||||
|
decl_intr_stub 251
|
||||||
|
decl_intr_stub 252
|
||||||
|
decl_intr_stub 253
|
||||||
|
decl_intr_stub 254
|
||||||
|
decl_intr_stub 255
|
353
src/intr.c
Normal file
353
src/intr.c
Normal file
@ -0,0 +1,353 @@
|
|||||||
|
#include "intr.h"
|
||||||
|
#include "cpu.h"
|
||||||
|
#include "clib.h"
|
||||||
|
#include "memory_layout.h"
|
||||||
|
#include "print.h"
|
||||||
|
#include "paging.h"
|
||||||
|
#include "thread.h"
|
||||||
|
#include "error.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IDT Defns
|
||||||
|
*/
|
||||||
|
#define GATE_DPL_0 (0ull << 13)
|
||||||
|
#define GATE_DPL_1 (1ull << 13)
|
||||||
|
#define GATE_DPL_2 (2ull << 13)
|
||||||
|
#define GATE_DPL_3 (3ull << 13)
|
||||||
|
#define GATE_PRESENT (1ull << 15)
|
||||||
|
#define GATE_TYPE_CALL (12ull << 8)
|
||||||
|
#define GATE_TYPE_INTERRUPT (14ull << 8)
|
||||||
|
#define GATE_TYPE_TRAP (15ull << 8)
|
||||||
|
|
||||||
|
/**
|
||||||
|
GDT Defns
|
||||||
|
**/
|
||||||
|
#define SEG_GRANULARITY (1ull << 55)
|
||||||
|
#define SEG_LONG (1ull << 53)
|
||||||
|
#define SEG_DPL_0 (0ull << 45)
|
||||||
|
#define SEG_DPL_1 (1ull << 45)
|
||||||
|
#define SEG_DPL_2 (2ull << 45)
|
||||||
|
#define SEG_DPL_3 (3ull << 45)
|
||||||
|
#define SEG_PRESENT (1ull << 47)
|
||||||
|
#define SEG_CODE_DATA (1ull << 44)
|
||||||
|
#define SEG_TYPE_DATA_RW (2ull << 40)
|
||||||
|
#define SEG_TYPE_DATA_R (0ull << 40)
|
||||||
|
#define SEG_TYPE_CODE_X (8ull << 40)
|
||||||
|
#define SEG_TYPE_CODE_XR (10ull << 40)
|
||||||
|
#define SEG_TYPE_CODE_XC (12ull << 40)
|
||||||
|
#define SEG_TYPE_CODE_XRC (14ull << 40)
|
||||||
|
#define SEG_AVAILABLE (1ull << 52)
|
||||||
|
#define SEG_32_BITS (1ull << 54)
|
||||||
|
|
||||||
|
// APIC Interrupt vectors
|
||||||
|
#define EDX_MASK_APIC (1 << 9)
|
||||||
|
#define MSR_APIC_BASE (0x1b)
|
||||||
|
#define MSR_MASK_APIC (1 << 11)
|
||||||
|
|
||||||
|
// PIC defs
|
||||||
|
#define PIC1_COMMAND (0x20)
|
||||||
|
#define PIC1_DATA (PIC1_COMMAND+1)
|
||||||
|
#define PIC2_COMMAND (0xa0)
|
||||||
|
#define PIC2_DATA (PIC2_COMMAND+1)
|
||||||
|
|
||||||
|
#define APIC_REG_SPURIOUS (0xF0)
|
||||||
|
#define APIC_REG_TIMER (0x320)
|
||||||
|
#define APIC_REG_EOI (0xB0)
|
||||||
|
#define APIC_REG_TIMER_DIV (0x3E0)
|
||||||
|
#define APIC_REG_TIMER_INIT_CNT (0x380)
|
||||||
|
#define APIC_REG_TIMER_CUR_CNT (0x390)
|
||||||
|
#define APIC_REG_ID (0x20)
|
||||||
|
#define APIC_REG_LINT0 (0x350)
|
||||||
|
#define APIC_REG_LINT1 (0x360)
|
||||||
|
#define APIC_REG_ICR_L (0x300)
|
||||||
|
#define APIC_REG_ICR_H (0x310)
|
||||||
|
|
||||||
|
#define IPI_DLM_FIXED (0 << 8)
|
||||||
|
#define IPI_DLM_START_UP (6 << 8)
|
||||||
|
|
||||||
|
#define IPI_DSM_PHYS (0 << 11)
|
||||||
|
#define IPI_DSM_LOGI (1 << 11)
|
||||||
|
#define IPI_STATUS_MASK (1 << 12)
|
||||||
|
|
||||||
|
#define IPI_LVL_ASS (1 << 15)
|
||||||
|
#define IPI_LVL_DEA (0 << 15)
|
||||||
|
|
||||||
|
// base on 1Ghz CPU
|
||||||
|
#define APIC_TIMER_INIT_CNT (10000000)
|
||||||
|
#define REG_SPURIOUS_APIC_ENABLE (1 << 8)
|
||||||
|
|
||||||
|
extern void *intr_stub_array[NUM_IDT_DESC];
|
||||||
|
|
||||||
|
static void *apic_base;
|
||||||
|
static struct tss utss;
|
||||||
|
static struct gdtr gdtptr;
|
||||||
|
static struct idtr idtptr;
|
||||||
|
static struct gdt_desc gdt[NUM_GDT_DESC];
|
||||||
|
static struct idt_desc idt[NUM_IDT_DESC];
|
||||||
|
static intr_handler intr_disp_tbl[NUM_IDT_DESC];
|
||||||
|
|
||||||
|
static void write_idt_desc(void *gate, uint64 offset, uint32 selector, uint32 attr)
|
||||||
|
{
|
||||||
|
((uint8 *) gate)[0] = (uint8) (offset & 0xFF);
|
||||||
|
((uint8 *) gate)[1] = (uint8) ((offset >> 8) & 0xFF);
|
||||||
|
((uint8 *) gate)[2] = (uint8) (selector & 0xFF);
|
||||||
|
((uint8 *) gate)[3] = (uint8) ((selector >> 8) & 0xFF);
|
||||||
|
((uint8 *) gate)[4] = (uint8) (attr & 0xFF);
|
||||||
|
((uint8 *) gate)[5] = (uint8) ((attr >> 8) & 0xFF);
|
||||||
|
((uint8 *) gate)[6] = (uint8) ((offset >> 16) & 0xFF);
|
||||||
|
((uint8 *) gate)[7] = (uint8) ((offset >> 24) & 0xFF);
|
||||||
|
((uint8 *) gate)[8] = (uint8) ((offset >> 32) & 0xFF);
|
||||||
|
((uint8 *) gate)[9] = (uint8) ((offset >> 40) & 0xFF);
|
||||||
|
((uint8 *) gate)[10] = (uint8) ((offset >> 48) & 0xFF);
|
||||||
|
((uint8 *) gate)[11] = (uint8) ((offset >> 56) & 0xFF);
|
||||||
|
((uint8 *) gate)[12] = 0;
|
||||||
|
((uint8 *) gate)[13] = 0;
|
||||||
|
((uint8 *) gate)[14] = 0;
|
||||||
|
((uint8 *) gate)[15] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void write_gdt_desc(void *gdt, uint32 base, uint32 limit, uint64 attr)
|
||||||
|
{
|
||||||
|
uint64 seg_desc = (((uint64) base & 0xFFFF) << 16) | ((((uint64) base >> 16) & 0xFF) << 32) |
|
||||||
|
((((uint64) base >> 24) & 0xFF) << 56) | ((uint64) limit & 0xFFFF) |
|
||||||
|
((((uint64) limit >> 16) & 0xF) << 48) | attr;
|
||||||
|
((uint8 *) gdt)[0] = (uint8) (seg_desc & 0xFF);
|
||||||
|
((uint8 *) gdt)[1] = (uint8) ((seg_desc >> 8) & 0xFF);
|
||||||
|
((uint8 *) gdt)[2] = (uint8) ((seg_desc >> 16) & 0xFF);
|
||||||
|
((uint8 *) gdt)[3] = (uint8) ((seg_desc >> 24) & 0xFF);
|
||||||
|
((uint8 *) gdt)[4] = (uint8) ((seg_desc >> 32) & 0xFF);
|
||||||
|
((uint8 *) gdt)[5] = (uint8) ((seg_desc >> 40) & 0xFF);
|
||||||
|
((uint8 *) gdt)[6] = (uint8) ((seg_desc >> 48) & 0xFF);
|
||||||
|
((uint8 *) gdt)[7] = (uint8) ((seg_desc >> 56) & 0xFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void disable_pic()
|
||||||
|
{
|
||||||
|
out_8(PIC1_COMMAND, 0x11); // starts the initialization sequence (in cascade mode)
|
||||||
|
out_8(PIC2_COMMAND, 0x11);
|
||||||
|
|
||||||
|
out_8(PIC1_DATA, 32); // ICW2: Master PIC vector offset
|
||||||
|
out_8(PIC2_DATA, 40); // ICW2: Slave PIC vector offset
|
||||||
|
|
||||||
|
out_8(PIC1_DATA, 4); // ICW3: tell Master PIC that there is a slave PIC at IRQ2 (0000 0100)
|
||||||
|
out_8(PIC2_DATA, 2); // ICW3: tell Slave PIC its cascade identity (0000 0010)
|
||||||
|
|
||||||
|
out_8(PIC1_DATA, 0x1); // set their modes to 8086
|
||||||
|
out_8(PIC2_DATA, 0x1);
|
||||||
|
|
||||||
|
out_8(PIC1_DATA, 0xff);
|
||||||
|
out_8(PIC2_DATA, 0xff);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void write_apic_reg(uint32 reg, uint32 val)
|
||||||
|
{
|
||||||
|
*(uint32 *) ((uintptr) apic_base + reg) = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32 read_apic_reg(uint32 reg)
|
||||||
|
{
|
||||||
|
return *(uint32 *) ((uintptr) apic_base + reg);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int32 init_apic()
|
||||||
|
{
|
||||||
|
uint32 eax = 1, ebx, ecx, edx;
|
||||||
|
cpuid(&eax, &ebx, &ecx, &edx);
|
||||||
|
|
||||||
|
if (!(edx & EDX_MASK_APIC))
|
||||||
|
{
|
||||||
|
return ENOSUPPORT;
|
||||||
|
}
|
||||||
|
|
||||||
|
disable_pic();
|
||||||
|
|
||||||
|
// hardware enable APIC
|
||||||
|
ecx = MSR_APIC_BASE;
|
||||||
|
read_msr(&ecx, &edx, &eax);
|
||||||
|
apic_base = R_PADDR(eax & 0xFFFF0000);
|
||||||
|
eax |= MSR_MASK_APIC;
|
||||||
|
write_msr(&ecx, &edx, &eax);
|
||||||
|
#ifdef KDBG
|
||||||
|
kprintf("APIC base address: 0x%x\n", (uint64) apic_base);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// map spurious interrupt and software enable APIC
|
||||||
|
uint32 reg = read_apic_reg(APIC_REG_SPURIOUS);
|
||||||
|
write_apic_reg(APIC_REG_SPURIOUS, reg | REG_SPURIOUS_APIC_ENABLE);
|
||||||
|
|
||||||
|
// Mask LINT0 LINT1
|
||||||
|
reg = read_apic_reg(APIC_REG_LINT0);
|
||||||
|
write_apic_reg(APIC_REG_LINT0, reg | (1 << 16));
|
||||||
|
reg = read_apic_reg(APIC_REG_LINT1);
|
||||||
|
write_apic_reg(APIC_REG_LINT1, reg | (1 << 16));
|
||||||
|
|
||||||
|
// configure APIC timer
|
||||||
|
write_apic_reg(APIC_REG_TIMER_DIV, 0xB); // 0x1011, divide by 1
|
||||||
|
write_apic_reg(APIC_REG_TIMER_INIT_CNT, APIC_TIMER_INIT_CNT);
|
||||||
|
write_apic_reg(APIC_REG_TIMER_CUR_CNT, APIC_REG_TIMER_INIT_CNT);
|
||||||
|
write_apic_reg(APIC_REG_TIMER, 0xFF020000 | INTR_VEC_TIMER); // periodic
|
||||||
|
|
||||||
|
// unblock all interrupts
|
||||||
|
write_cr8(0);
|
||||||
|
|
||||||
|
return ESUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void *timer_intr_handler(struct intr_frame *frame)
|
||||||
|
{
|
||||||
|
struct tcb *cur = get_cur_thread();
|
||||||
|
|
||||||
|
if (cur != NULL)
|
||||||
|
{
|
||||||
|
// hack to get away first scheduling 1st time
|
||||||
|
// save the stack pointer of the current thread
|
||||||
|
cur->rsp0 = (uint64) frame;
|
||||||
|
}
|
||||||
|
|
||||||
|
// run the scheduler
|
||||||
|
thread_schedule();
|
||||||
|
|
||||||
|
cur = get_cur_thread();
|
||||||
|
// now cur is the next thread to run
|
||||||
|
// swap address space
|
||||||
|
// which shouldn't page fault as we are in kernel
|
||||||
|
write_cr3(cur->proc->cr3);
|
||||||
|
flush_tlb();
|
||||||
|
|
||||||
|
// write tss segment
|
||||||
|
utss.rsp0 = (uint64)((uintptr)cur->kstack + cur->kstack_sz);
|
||||||
|
|
||||||
|
// now we are in the target address space
|
||||||
|
// the only thing to do is to switch stack, which will be done in ASM handler
|
||||||
|
return (void *) cur->rsp0;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern char init_stack[];
|
||||||
|
|
||||||
|
int32 intr_init()
|
||||||
|
{
|
||||||
|
int32 ret;
|
||||||
|
// init GDT
|
||||||
|
write_gdt_desc(&gdt[GDT_NULL], 0, 0, 0); // empty desc
|
||||||
|
write_gdt_desc(&gdt[GDT_K_CODE], 0, 0xFFFFFFFF,
|
||||||
|
SEG_LONG | SEG_DPL_0 | SEG_PRESENT | SEG_GRANULARITY | SEG_CODE_DATA |
|
||||||
|
SEG_TYPE_CODE_XR); // kernel code
|
||||||
|
write_gdt_desc(&gdt[GDT_K_DATA], 0, 0xFFFFFFFF,
|
||||||
|
SEG_LONG | SEG_DPL_0 | SEG_PRESENT | SEG_GRANULARITY | SEG_CODE_DATA |
|
||||||
|
SEG_TYPE_DATA_RW); // kernel data
|
||||||
|
write_gdt_desc(&gdt[GDT_U_CODE], 0, 0xFFFFFFFF,
|
||||||
|
SEG_LONG | SEG_DPL_3 | SEG_PRESENT | SEG_GRANULARITY | SEG_CODE_DATA |
|
||||||
|
SEG_TYPE_CODE_XR); // user code
|
||||||
|
write_gdt_desc(&gdt[GDT_U_DATA], 0, 0xFFFFFFFF,
|
||||||
|
SEG_LONG | SEG_DPL_3 | SEG_PRESENT | SEG_GRANULARITY | SEG_CODE_DATA |
|
||||||
|
SEG_TYPE_DATA_RW); // user data
|
||||||
|
// write tss
|
||||||
|
write_gdt_desc(&gdt[GDT_U_TSS], (uint32) &utss, sizeof(struct tss),
|
||||||
|
SEG_PRESENT | SEG_DPL_3 | ((uint64)9 << 40));
|
||||||
|
// write high bits
|
||||||
|
*(uint64 *) &gdt[GDT_U_TSS + 1] = ((uintptr)&utss) >> 32;
|
||||||
|
|
||||||
|
// init tss
|
||||||
|
mem_set(&utss, 0, sizeof(struct tss));
|
||||||
|
|
||||||
|
gdtptr.size = GDT_SIZE - 1;
|
||||||
|
gdtptr.offset = (uintptr) gdt;
|
||||||
|
flush_gdt(&gdtptr, SEL(GDT_K_CODE, 0, 0), SEL(GDT_K_DATA, 0, 0));
|
||||||
|
flush_tss(SEL(GDT_U_TSS, 0, 3));
|
||||||
|
|
||||||
|
idtptr.offset = (uintptr) idt;
|
||||||
|
idtptr.size = IDT_SIZE - 1;
|
||||||
|
for (int i = 0; i < NUM_IDT_DESC; i++)
|
||||||
|
{
|
||||||
|
write_idt_desc(&idt[i], (uintptr) intr_stub_array[i],
|
||||||
|
SEL(GDT_K_CODE, 0, 0),
|
||||||
|
GATE_DPL_3 | GATE_TYPE_INTERRUPT | GATE_PRESENT);
|
||||||
|
}
|
||||||
|
mem_set(intr_disp_tbl, 0, sizeof(intr_disp_tbl));
|
||||||
|
flush_idt(&idtptr);
|
||||||
|
ret = init_apic();
|
||||||
|
|
||||||
|
if (ret == ESUCCESS)
|
||||||
|
{
|
||||||
|
// enable interrupt flag but mask all external interrupts
|
||||||
|
WRITE_IRQ(0xf);
|
||||||
|
sti();
|
||||||
|
|
||||||
|
set_intr_handler(INTR_VEC_TIMER, timer_intr_handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_intr_handler(uint32 vec, intr_handler handler)
|
||||||
|
{
|
||||||
|
intr_disp_tbl[vec] = handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
void stop_cpu()
|
||||||
|
{
|
||||||
|
// stop interrupt and halt
|
||||||
|
cli();
|
||||||
|
hlt();
|
||||||
|
}
|
||||||
|
|
||||||
|
// this returns info returned by intr_disp_tbl
|
||||||
|
// in case the assembly stub needs them (e.g. ctx swap)
|
||||||
|
void *intr_dispatcher(uint32 vec, struct intr_frame *frame)
|
||||||
|
{
|
||||||
|
void *ret = NULL;
|
||||||
|
|
||||||
|
if (intr_disp_tbl[vec] != NULL)
|
||||||
|
{
|
||||||
|
ret = intr_disp_tbl[vec](frame);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (vec <= INTR_LIMIT_INTEL)
|
||||||
|
{
|
||||||
|
kprintf("[PANIC] Exception %d has no handler. RIP: 0x%x ERR:0x%x\n", (uint64) vec, (uint64) frame->rip,
|
||||||
|
(uint64) frame->error_code);
|
||||||
|
stop_cpu();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
kprintf("[WARN] Interrupt %d has no handler. RIP: 0x%x\n", (uint64) vec, (uint64) frame->rip);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vec >= INTR_VEC_TIMER && vec != INTR_VEC_SPURIOUS)
|
||||||
|
{
|
||||||
|
// if it's delivered by local APIC, signal EOI
|
||||||
|
write_apic_reg(APIC_REG_EOI, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32 get_core()
|
||||||
|
{
|
||||||
|
return read_apic_reg(APIC_REG_ID) >> 24;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void send_ipi(uint32 vec)
|
||||||
|
{
|
||||||
|
// we decide to not support multicore for now. So hardcode to the current core
|
||||||
|
// used to emulate IO stuff
|
||||||
|
uint64 reg = ((uint64) get_core() << 56) | IPI_DLM_FIXED | IPI_DSM_PHYS | IPI_LVL_ASS | (vec & 0xff);
|
||||||
|
|
||||||
|
// block all interrupts because there is no context
|
||||||
|
uint64 irq = READ_IRQ();
|
||||||
|
WRITE_IRQ(0xf);
|
||||||
|
|
||||||
|
write_apic_reg(APIC_REG_ICR_L, (uint32)reg);
|
||||||
|
write_apic_reg(APIC_REG_ICR_H, (uint32)(reg >> 32));
|
||||||
|
// block until successfully delivered
|
||||||
|
while (reg & IPI_STATUS_MASK)
|
||||||
|
{
|
||||||
|
reg = read_apic_reg(APIC_REG_ICR_L);
|
||||||
|
}
|
||||||
|
|
||||||
|
WRITE_IRQ(irq);
|
||||||
|
}
|
||||||
|
|
138
src/kmain.c
Normal file
138
src/kmain.c
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
#include "multiboot2.h"
|
||||||
|
#include "intr.h"
|
||||||
|
#include "print.h"
|
||||||
|
#include "clib.h"
|
||||||
|
#include "cpu.h"
|
||||||
|
#include "thread.h"
|
||||||
|
#include "proc.h"
|
||||||
|
#include "pmm.h"
|
||||||
|
#include "syscall.h"
|
||||||
|
#include "error.h"
|
||||||
|
#include "vmm.h"
|
||||||
|
#include "elf64.h"
|
||||||
|
|
||||||
|
void kthread1(void *arg);
|
||||||
|
|
||||||
|
void kthread2(void *arg);
|
||||||
|
|
||||||
|
void kproc(void *arg);
|
||||||
|
|
||||||
|
void *_module;
|
||||||
|
|
||||||
|
void kmain(mbentry *mb)
|
||||||
|
{
|
||||||
|
char *ld_name = 0x0;
|
||||||
|
mod_tag *module = 0x0;
|
||||||
|
uint64 mem_low;
|
||||||
|
uint64 mem_high;
|
||||||
|
int32 status;
|
||||||
|
print_init();
|
||||||
|
|
||||||
|
parse_mb2(mb, (void **) &module, &ld_name, &mem_low, &mem_high);
|
||||||
|
|
||||||
|
kprintf("Bootloader: %s\n", ld_name);
|
||||||
|
kprintf("User executable loaded at 0x%x size %d.\n", (uint64) R_PADDR(module->mod_start), (uint64) (module->mod_end - module->mod_start));
|
||||||
|
|
||||||
|
kprintf("Initializing interrupt...\n");
|
||||||
|
status = intr_init();
|
||||||
|
kprintf("Initializing system call...\n");
|
||||||
|
syscall_init();
|
||||||
|
KASSERT(status == ESUCCESS);
|
||||||
|
|
||||||
|
_module = R_PADDR(module->mod_start);
|
||||||
|
|
||||||
|
kprintf("Initializing PMM...\n");
|
||||||
|
pmm_init(mem_low, mem_high);
|
||||||
|
kprintf("Initializing VMM...\n");
|
||||||
|
init_vm();
|
||||||
|
|
||||||
|
kprintf("Initializing threads...\n");
|
||||||
|
thread_init();
|
||||||
|
kprintf("Initializing processes...\n");
|
||||||
|
status = proc_init((void *) kproc);
|
||||||
|
KASSERT(status == ESUCCESS);
|
||||||
|
|
||||||
|
// unmask all interrupts
|
||||||
|
WRITE_IRQ(0x0);
|
||||||
|
|
||||||
|
send_ipi(INTR_VEC_TIMER);
|
||||||
|
KASSERT(FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define THREAD_DELAY (5000000*4)
|
||||||
|
|
||||||
|
static uint32 kt1id;
|
||||||
|
static uint32 kt2id;
|
||||||
|
|
||||||
|
void kthread1(void *arg)
|
||||||
|
{
|
||||||
|
UNREFERENCED(arg);
|
||||||
|
uint64 i = 0;
|
||||||
|
while (i != 0xFFFFFFFFFF)
|
||||||
|
{
|
||||||
|
poor_sleep(THREAD_DELAY);
|
||||||
|
kprintf("[KThread1] %d\n", i);
|
||||||
|
|
||||||
|
if (i == 10)
|
||||||
|
{
|
||||||
|
kprintf("[KThread1] Blocking KThread 2... \n", i);
|
||||||
|
thread_block(kt2id);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i == 20)
|
||||||
|
{
|
||||||
|
kprintf("[KThread1] Resuming KThread 2... \n", i);
|
||||||
|
thread_resume(kt2id);
|
||||||
|
}
|
||||||
|
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void kthread2(void *arg)
|
||||||
|
{
|
||||||
|
UNREFERENCED(arg);
|
||||||
|
bool thread1exited = FALSE;
|
||||||
|
uint64 i = 0;
|
||||||
|
int32 ex;
|
||||||
|
while (i != 0xFFFFFFFFFF)
|
||||||
|
{
|
||||||
|
poor_sleep(THREAD_DELAY);
|
||||||
|
|
||||||
|
kprintf("[KThread2] %d\n", i);
|
||||||
|
|
||||||
|
if (i == 40)
|
||||||
|
{
|
||||||
|
kprintf("[KThread2] Stopping KThread1 with exit code 0xdeadbeef\n", i);
|
||||||
|
thread_stop(kt1id, 0xDEADBEEF);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!thread1exited && thread_get_exit_code(kt1id, &ex) == ESUCCESS)
|
||||||
|
{
|
||||||
|
kprintf("[KThread2] KThread1 exited with 0x%x\n", (uint64) ex);
|
||||||
|
thread1exited = TRUE;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void kproc(void *arg)
|
||||||
|
{
|
||||||
|
// the idle thread
|
||||||
|
UNREFERENCED(arg);
|
||||||
|
int32 status;
|
||||||
|
status = thread_create(get_cur_thread()->proc, (void *) kthread1, NULL, &kt1id);
|
||||||
|
kprintf("[KIdle] Created KThread1... 0x%x\n", (uint64) status);
|
||||||
|
status = thread_create(get_cur_thread()->proc, (void *) kthread2, NULL, &kt2id);
|
||||||
|
kprintf("[KIdle] Created KThread2... 0x%x\n", (uint64) status);
|
||||||
|
uint32 id;
|
||||||
|
status = proc_create(_module, &id);
|
||||||
|
kprintf("[KIdle] Created process from module... 0x%x\n", (uint64) status);
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
#ifdef KDBG
|
||||||
|
kprintf("[KIdle] Yielding...\n");
|
||||||
|
#endif
|
||||||
|
thread_yield();
|
||||||
|
}
|
||||||
|
}
|
250
src/llist.c
Normal file
250
src/llist.c
Normal file
@ -0,0 +1,250 @@
|
|||||||
|
#include "llist.h"
|
||||||
|
|
||||||
|
static void
|
||||||
|
llist_node_init(struct llist_node *node)
|
||||||
|
{
|
||||||
|
node->next = NULL;
|
||||||
|
node->prev = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
lb_llist_init(struct llist *list)
|
||||||
|
{
|
||||||
|
list->head = NULL;
|
||||||
|
list->tail = NULL;
|
||||||
|
list->size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint32
|
||||||
|
lb_llist_size(struct llist *list)
|
||||||
|
{
|
||||||
|
return list->size;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
lb_llist_push_front(struct llist *list, struct llist_node *node)
|
||||||
|
{
|
||||||
|
llist_node_init(node);
|
||||||
|
lb_llist_insert_by_ref(list, NULL, node);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
lb_llist_push_back(struct llist *list, struct llist_node *node)
|
||||||
|
{
|
||||||
|
llist_node_init(node);
|
||||||
|
lb_llist_insert_by_ref(list, list->tail, node);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct llist_node *
|
||||||
|
lb_llist_pop_front(struct llist *list)
|
||||||
|
{
|
||||||
|
struct llist_node *ret;
|
||||||
|
|
||||||
|
ret = list->head;
|
||||||
|
lb_llist_remove_by_ref(list, list->head);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct llist_node *
|
||||||
|
lb_llist_pop_back(struct llist *list)
|
||||||
|
{
|
||||||
|
struct llist_node *ret;
|
||||||
|
|
||||||
|
ret = list->tail;
|
||||||
|
lb_llist_remove_by_ref(list, list->tail);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
lb_llist_insert_by_ref(struct llist *list, struct llist_node *cur_node, struct llist_node *new_node)
|
||||||
|
{
|
||||||
|
struct llist_node *left_node;
|
||||||
|
struct llist_node *right_node;
|
||||||
|
|
||||||
|
if (list == NULL || new_node == NULL)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
llist_node_init(new_node);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* adjust the current node
|
||||||
|
*/
|
||||||
|
if (cur_node == NULL)
|
||||||
|
{
|
||||||
|
new_node->next = list->head;
|
||||||
|
new_node->prev = NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
new_node->prev = cur_node;
|
||||||
|
new_node->next = cur_node->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* assign left and treenode node
|
||||||
|
*/
|
||||||
|
if (cur_node == NULL)
|
||||||
|
{
|
||||||
|
left_node = NULL;
|
||||||
|
right_node = list->head == NULL ? NULL : list->head;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
left_node = cur_node;
|
||||||
|
right_node = cur_node->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* adjust left and treenode node accordingly
|
||||||
|
*/
|
||||||
|
if (left_node != NULL)
|
||||||
|
{
|
||||||
|
left_node->next = new_node;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
list->head = new_node;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (right_node != NULL)
|
||||||
|
{
|
||||||
|
right_node->prev = new_node;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
list->tail = new_node;
|
||||||
|
}
|
||||||
|
|
||||||
|
list->size++;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
lb_llist_insert_by_idx(struct llist *list, uint32 index, struct llist_node *node)
|
||||||
|
{
|
||||||
|
struct llist_node *prev_node;
|
||||||
|
|
||||||
|
prev_node = lb_llist_get(list, index - 1);
|
||||||
|
llist_node_init(node);
|
||||||
|
|
||||||
|
if (prev_node == NULL)
|
||||||
|
{
|
||||||
|
if (index == 0)
|
||||||
|
{
|
||||||
|
lb_llist_insert_by_ref(list, NULL, node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
lb_llist_insert_by_ref(list, prev_node, node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct llist_node *
|
||||||
|
lb_llist_remove_by_idx(struct llist *list, uint32 index)
|
||||||
|
{
|
||||||
|
struct llist_node *cur_node;
|
||||||
|
|
||||||
|
cur_node = lb_llist_get(list, index);
|
||||||
|
|
||||||
|
if (cur_node == NULL)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return lb_llist_remove_by_ref(list, cur_node);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* returns the next node
|
||||||
|
*/
|
||||||
|
struct llist_node *
|
||||||
|
lb_llist_remove_by_ref(struct llist *list, struct llist_node *node)
|
||||||
|
{
|
||||||
|
struct llist_node *ret;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Adjust the left and treenode node
|
||||||
|
*/
|
||||||
|
if (node->prev != NULL)
|
||||||
|
{
|
||||||
|
node->prev->next = node->next;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
list->head = node->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node->next != NULL)
|
||||||
|
{
|
||||||
|
node->next->prev = node->prev;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
list->tail = node->prev;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = node->next;
|
||||||
|
|
||||||
|
llist_node_init(node);
|
||||||
|
|
||||||
|
list->size--;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct llist_node *
|
||||||
|
lb_llist_get(struct llist *list, uint32 index)
|
||||||
|
{
|
||||||
|
if (list->head == NULL)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
struct llist_node *cur_node = list->head;
|
||||||
|
while (index-- && (cur_node = cur_node->next) != NULL)
|
||||||
|
{}
|
||||||
|
return cur_node;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct llist_node *
|
||||||
|
lb_llist_next(struct llist_node *node)
|
||||||
|
{
|
||||||
|
return node->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct llist_node *
|
||||||
|
lb_llist_prev(struct llist_node *node)
|
||||||
|
{
|
||||||
|
return node->prev;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct llist_node *
|
||||||
|
lb_llist_first(struct llist *list)
|
||||||
|
{
|
||||||
|
return list->head;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct llist_node *
|
||||||
|
lb_llist_last(struct llist *list)
|
||||||
|
{
|
||||||
|
return list->tail;
|
||||||
|
}
|
||||||
|
|
96
src/multiboot2.c
Normal file
96
src/multiboot2.c
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
#include <multiboot2.h>
|
||||||
|
#include <pmm.h>
|
||||||
|
#include <cdef.h>
|
||||||
|
#include <print.h>
|
||||||
|
#include <memory_layout.h>
|
||||||
|
|
||||||
|
|
||||||
|
// Putting multiboot device info here
|
||||||
|
static char *loader_name = 0x0;
|
||||||
|
static void *file_mod = 0x0;
|
||||||
|
|
||||||
|
// OH BOY DON"T I FUCKING LOVE THIS SHIT
|
||||||
|
static uint64 _low = 0;
|
||||||
|
static uint64 _high = 0;
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
process_mmap(struct multiboot_tag_mmap *mmap)
|
||||||
|
{
|
||||||
|
struct multiboot_mmap_entry entry;
|
||||||
|
|
||||||
|
uint16 num_entries = (mmap->size - sizeof(*mmap)) / mmap->entry_size;
|
||||||
|
for (uint16 i = 0; i < num_entries; i++)
|
||||||
|
{
|
||||||
|
entry = mmap->entries[i];
|
||||||
|
if ((entry.type == 1) && (entry.len > _high - _low))
|
||||||
|
{
|
||||||
|
#ifdef KDBG
|
||||||
|
kprintf("Update low: 0x%x high: 0x%x\n", (uint64) entry.addr, (uint64) (entry.addr + entry.len));
|
||||||
|
#endif
|
||||||
|
_high = entry.addr + entry.len;
|
||||||
|
_low = entry.addr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
process_tag(htag *tag)
|
||||||
|
{
|
||||||
|
struct multiboot_tag_mmap *mmap_tag;
|
||||||
|
struct multiboot_tag_string *strtag;
|
||||||
|
struct multiboot_tag_module *modtag;
|
||||||
|
while(1)
|
||||||
|
{
|
||||||
|
if(tag->type == MULTIBOOT_HEADER_TAG_END)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (tag->type)
|
||||||
|
{
|
||||||
|
case MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME:
|
||||||
|
strtag = (struct multiboot_tag_string *) tag;
|
||||||
|
loader_name = &strtag->string[0];
|
||||||
|
tag = (void*)ALIGN(uintptr, (uintptr)tag + tag->size, MULTIBOOT_TAG_ALIGN);
|
||||||
|
break;
|
||||||
|
case MULTIBOOT_TAG_TYPE_MMAP:
|
||||||
|
mmap_tag = (struct multiboot_tag_mmap *) tag;
|
||||||
|
process_mmap(mmap_tag);
|
||||||
|
tag = (void*)ALIGN(uintptr, (uintptr)tag + tag->size, MULTIBOOT_TAG_ALIGN);
|
||||||
|
break;
|
||||||
|
case MULTIBOOT_TAG_TYPE_MODULE:
|
||||||
|
modtag = (struct multiboot_tag_module *)tag;
|
||||||
|
file_mod = modtag;
|
||||||
|
tag = (void*)ALIGN(uintptr, (uintptr)tag + tag->size, MULTIBOOT_TAG_ALIGN);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
tag = (void*)ALIGN(uintptr, (uintptr)tag + tag->size, MULTIBOOT_TAG_ALIGN);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void parse_mb2(mbentry *mb, void **module, char **ld_name, uint64 *low, uint64 *high)
|
||||||
|
{
|
||||||
|
uint64 tag_base0 = (uint64) mb;
|
||||||
|
uint64 next_entry;
|
||||||
|
uint64 last_entry;
|
||||||
|
|
||||||
|
next_entry = tag_base0 + 8;
|
||||||
|
last_entry = tag_base0 + mb->total_size - 8;
|
||||||
|
|
||||||
|
htag *last_tag = (htag *) last_entry;
|
||||||
|
if (!(last_tag->type == 0 && last_tag->size == 8))
|
||||||
|
{ return; }
|
||||||
|
|
||||||
|
htag *tag = (htag *) next_entry;
|
||||||
|
process_tag(tag);
|
||||||
|
|
||||||
|
*module = file_mod;
|
||||||
|
*ld_name = loader_name;
|
||||||
|
*low = _low;
|
||||||
|
*high = _high;
|
||||||
|
}
|
||||||
|
|
159
src/paging.c
Normal file
159
src/paging.c
Normal file
@ -0,0 +1,159 @@
|
|||||||
|
#include <memory_layout.h>
|
||||||
|
#include <print.h>
|
||||||
|
#include "paging.h"
|
||||||
|
#include "pmm.h"
|
||||||
|
#include "cpu.h"
|
||||||
|
#include "clib.h"
|
||||||
|
#include "error.h"
|
||||||
|
|
||||||
|
#define ENTRY_SIZE (8)
|
||||||
|
|
||||||
|
#define NEXT_LEVEL_MASK bit_field_mask(12,51)
|
||||||
|
|
||||||
|
#define BIT_PRESENT (1ull)
|
||||||
|
#define BIT_WRITEABLE (1ull << 1)
|
||||||
|
#define BIT_USER (1ull << 2)
|
||||||
|
#define BIT_WRITE_THROUGH (1ull << 3)
|
||||||
|
#define BIT_CACHE_DISABLED (1ull << 4)
|
||||||
|
#define BIT_ACCESSED (1ull << 5)
|
||||||
|
#define BIT_PS (1ull << 7)
|
||||||
|
#define BIT_EXECUTION_DISABLED (1ull << 63)
|
||||||
|
|
||||||
|
static void
|
||||||
|
write_page_table(void *const base, uintptr const p_addr, uint64 const attr)
|
||||||
|
{
|
||||||
|
uint64 entry = (p_addr & 0xFFFFFFFFFF000) | attr;
|
||||||
|
((uint8 *) base)[0] = (uint8) (entry & 0xFF);
|
||||||
|
((uint8 *) base)[1] = (uint8) ((entry >> 8) & 0xFF);
|
||||||
|
((uint8 *) base)[2] = (uint8) ((entry >> 16) & 0xFF);
|
||||||
|
((uint8 *) base)[3] = (uint8) ((entry >> 24) & 0xFF);
|
||||||
|
((uint8 *) base)[4] = (uint8) ((entry >> 32) & 0xFF);
|
||||||
|
((uint8 *) base)[5] = (uint8) ((entry >> 40) & 0xFF);
|
||||||
|
((uint8 *) base)[6] = (uint8) ((entry >> 48) & 0xFF);
|
||||||
|
((uint8 *) base)[7] = (uint8) ((entry >> 56) & 0xFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int32 ensure_present(uint64 *entry, uint64 attr, uintptr *alloc)
|
||||||
|
{
|
||||||
|
uint32 ret = ESUCCESS;
|
||||||
|
|
||||||
|
uintptr p_alloc = (uintptr) NULL;
|
||||||
|
|
||||||
|
if (!(*entry & BIT_PRESENT))
|
||||||
|
{
|
||||||
|
p_alloc = (uintptr) pmalloc(KERNEL_PAGE_SIZE);
|
||||||
|
if (p_alloc == (uintptr) NULL)
|
||||||
|
{
|
||||||
|
ret = ENOMEM;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mem_set(R_PADDR(p_alloc), 0, KERNEL_PAGE_SIZE);
|
||||||
|
write_page_table(entry, p_alloc, attr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret == ESUCCESS)
|
||||||
|
{
|
||||||
|
*alloc = p_alloc;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 map_vmem(uint64 cr3, uintptr vaddr, uintptr paddr)
|
||||||
|
{
|
||||||
|
int32 ret;
|
||||||
|
|
||||||
|
vaddr &= ~(uintptr)0xfff;
|
||||||
|
paddr &= ~(uintptr)0xfff;
|
||||||
|
|
||||||
|
uint64 *pml4_e = R_PADDR(cr3 + ENTRY_SIZE * PML4_ENTRY(vaddr));
|
||||||
|
uintptr pdpt_alloc = (uintptr) NULL;
|
||||||
|
ret = ensure_present(pml4_e, BIT_PRESENT | BIT_WRITEABLE | (IS_KERN_SPACE(vaddr) ? 0 : BIT_USER), &pdpt_alloc);
|
||||||
|
|
||||||
|
uint64 *pdpt_e = NULL;
|
||||||
|
uintptr pd_alloc = (uintptr) NULL;
|
||||||
|
if (ret == ESUCCESS)
|
||||||
|
{
|
||||||
|
pdpt_e = R_PADDR((*pml4_e & NEXT_LEVEL_MASK) + ENTRY_SIZE * PDPT_ENTRY(vaddr));
|
||||||
|
ret = ensure_present(pdpt_e, BIT_PRESENT | BIT_WRITEABLE | (IS_KERN_SPACE(vaddr) ? 0 : BIT_USER), &pd_alloc);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64 *pd_e = NULL;
|
||||||
|
uintptr pt_alloc = (uintptr) NULL;
|
||||||
|
if (ret == ESUCCESS)
|
||||||
|
{
|
||||||
|
pd_e = R_PADDR((*pdpt_e & NEXT_LEVEL_MASK) + ENTRY_SIZE * PD_ENTRY(vaddr));
|
||||||
|
ret = ensure_present(pd_e, BIT_PRESENT | BIT_WRITEABLE | (IS_KERN_SPACE(vaddr) ? 0 : BIT_USER), &pt_alloc);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret == ESUCCESS)
|
||||||
|
{
|
||||||
|
uint64 *pt_e = R_PADDR((*pd_e & NEXT_LEVEL_MASK) + ENTRY_SIZE * PT_ENTRY(vaddr));
|
||||||
|
write_page_table(pt_e, paddr, BIT_PRESENT | BIT_WRITEABLE | (IS_KERN_SPACE(vaddr) ? 0 : BIT_USER));
|
||||||
|
#ifdef KDBG
|
||||||
|
kprintf("Mapped 0x%x to 0x%x\n", vaddr, paddr);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret != ESUCCESS)
|
||||||
|
{
|
||||||
|
if (pdpt_alloc != (uintptr) NULL)
|
||||||
|
{
|
||||||
|
pfree(pdpt_alloc);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pd_alloc != (uintptr) NULL)
|
||||||
|
{
|
||||||
|
pfree(pd_alloc);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pt_alloc != (uintptr) NULL)
|
||||||
|
{
|
||||||
|
pfree(pt_alloc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
uintptr get_paddr(uint64 cr3, uintptr vaddr)
|
||||||
|
{
|
||||||
|
uint64 pml4_e = *(uint64 *) R_PADDR(cr3 + ENTRY_SIZE * PML4_ENTRY(vaddr));
|
||||||
|
|
||||||
|
if (!(pml4_e & BIT_PRESENT))
|
||||||
|
{
|
||||||
|
// not present in PML4
|
||||||
|
return (uintptr) NULL;
|
||||||
|
}
|
||||||
|
uint64 pdpt_e = *(uint64 *) R_PADDR((pml4_e & NEXT_LEVEL_MASK) + ENTRY_SIZE * PDPT_ENTRY((uintptr)vaddr));
|
||||||
|
|
||||||
|
if (!(pdpt_e & BIT_PRESENT))
|
||||||
|
{
|
||||||
|
return (uintptr) NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pdpt_e & BIT_PS)
|
||||||
|
{
|
||||||
|
// 1GB page
|
||||||
|
return (pdpt_e & bit_field_mask(30, 51)) + ((uintptr)vaddr & (0x3FFFFFFF));
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64 pd_e = *(uint64 *) R_PADDR((pdpt_e & NEXT_LEVEL_MASK) + ENTRY_SIZE * PD_ENTRY((uintptr)vaddr));
|
||||||
|
|
||||||
|
if (!(pdpt_e & BIT_PRESENT) || (pdpt_e & BIT_PS))
|
||||||
|
{
|
||||||
|
// don't support 2MB pages yet
|
||||||
|
return (uintptr) NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64 pt_e = *(uint64 *) R_PADDR((pd_e & NEXT_LEVEL_MASK) + ENTRY_SIZE * PT_ENTRY(vaddr));
|
||||||
|
|
||||||
|
if (!(pt_e & BIT_PRESENT))
|
||||||
|
{
|
||||||
|
return (uintptr) NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (pt_e & bit_field_mask(12, 51)) + (uintptr)vaddr & 0xFFF;
|
||||||
|
}
|
48
src/pmm.c
Normal file
48
src/pmm.c
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
#include <print.h>
|
||||||
|
#include <paging.h>
|
||||||
|
#include "memory_layout.h"
|
||||||
|
#include "pmm.h"
|
||||||
|
#include "clib.h"
|
||||||
|
|
||||||
|
static uint64 mem_low;
|
||||||
|
static uint64 mem_high;
|
||||||
|
static uint64 ptr;
|
||||||
|
static struct spin_lock pm_global_lock;
|
||||||
|
|
||||||
|
void
|
||||||
|
pfree(paddr p)
|
||||||
|
{
|
||||||
|
UNREFERENCED(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
void* pmalloc(uint32 size)
|
||||||
|
{
|
||||||
|
void* ret = NULL;
|
||||||
|
|
||||||
|
spin_lock(&pm_global_lock);
|
||||||
|
if((size > KERNEL_PAGE_SIZE) || (ptr >= mem_high))
|
||||||
|
{
|
||||||
|
ret = NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ret = (void *) ptr;
|
||||||
|
ptr = ptr + KERNEL_PAGE_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
spin_unlock(&pm_global_lock);
|
||||||
|
|
||||||
|
#ifdef KDBG
|
||||||
|
kprintf("Allocated physical: 0x%x, size: %d\n", (uint64)ptr, (uint64)size);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void pmm_init(uint64 low, uint64 high)
|
||||||
|
{
|
||||||
|
mem_low = MAX(K_IMAGE_PADDR + K_IMAGE_PRESRV, low);
|
||||||
|
ptr = mem_low;
|
||||||
|
mem_high = high;
|
||||||
|
spin_init(&pm_global_lock);
|
||||||
|
}
|
212
src/print.c
Normal file
212
src/print.c
Normal file
@ -0,0 +1,212 @@
|
|||||||
|
#include "print.h"
|
||||||
|
#include "clib.h"
|
||||||
|
#include "memory_layout.h"
|
||||||
|
#include "spin_lock.h"
|
||||||
|
|
||||||
|
#define FBUF (uintptr)R_PADDR(0xb8000)
|
||||||
|
#define GET_ROW(pos) ((pos) / 80)
|
||||||
|
#define GET_POS(row, col) ((row) * 80 + (col))
|
||||||
|
|
||||||
|
static struct spin_lock lock;
|
||||||
|
static uint64 text_pos;
|
||||||
|
|
||||||
|
void print_init()
|
||||||
|
{
|
||||||
|
spin_init(&lock);
|
||||||
|
text_pos = 0;
|
||||||
|
clear_screen();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
print_scroll(void)
|
||||||
|
{
|
||||||
|
mem_mv((void*)(FBUF + GET_POS(1, 0) * 2), (void *) (FBUF + GET_POS(0, 0) * 2), (80 * 24) * 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
print_str(char const *str)
|
||||||
|
{
|
||||||
|
if (str == NULL)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
while (*str != 0)
|
||||||
|
{
|
||||||
|
if (*str == '\n')
|
||||||
|
{
|
||||||
|
text_pos = 80 * (GET_ROW(text_pos) + 1);
|
||||||
|
if (text_pos > 80 * 25 - 1)
|
||||||
|
{
|
||||||
|
//can't hold
|
||||||
|
print_scroll();
|
||||||
|
mem_set((void *) (FBUF + 80 * 24 * 2), 0, 80 * 2); // clear last row
|
||||||
|
text_pos = 80 * 24;
|
||||||
|
}
|
||||||
|
str++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (text_pos > 80 * 25 - 1)
|
||||||
|
{
|
||||||
|
//can't hold
|
||||||
|
print_scroll();
|
||||||
|
text_pos = 80 * 24;
|
||||||
|
}
|
||||||
|
*((char *) (FBUF) + text_pos * 2) = *str;
|
||||||
|
*((char *) (FBUF) + text_pos * 2 + 1) = 7;
|
||||||
|
str++;
|
||||||
|
text_pos++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
print_uint(uint64 number)
|
||||||
|
{
|
||||||
|
char arr[21]; // do not need to initialize
|
||||||
|
arr[20] = 0; //zero-terminated
|
||||||
|
uint32 index = 19;
|
||||||
|
uint32 const div = 10;
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
uint64 quo = number / div;
|
||||||
|
uint64 rmd = number % div;
|
||||||
|
number = quo;
|
||||||
|
arr[index--] = (char) ('0' + rmd);
|
||||||
|
if (number == 0)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
print_str(&(arr[index + 1]));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
print_int(int64 number)
|
||||||
|
{
|
||||||
|
char arr[21]; // do not need to initialize
|
||||||
|
arr[20] = 0; //zero-terminated
|
||||||
|
uint32 index = 19;
|
||||||
|
uint32 isNegative = 0;
|
||||||
|
uint32 const div = 10;
|
||||||
|
if (number < 0)
|
||||||
|
{
|
||||||
|
isNegative = 1;
|
||||||
|
number *= -1;
|
||||||
|
}
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
int64 quo = number / div;
|
||||||
|
int64 rmd = number % div;
|
||||||
|
number = quo;
|
||||||
|
arr[index--] = (char) ('0' + rmd);
|
||||||
|
if (number == 0)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (isNegative)
|
||||||
|
{
|
||||||
|
arr[index--] = '-';
|
||||||
|
}
|
||||||
|
print_str(&(arr[index + 1]));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
print_hex(uint64 number, uint64 capital)
|
||||||
|
{
|
||||||
|
char const lookup_table_cap[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
|
||||||
|
char const lookup_table[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
|
||||||
|
char const *const look_up = capital == 1 ? &lookup_table_cap[0] : &lookup_table[0];
|
||||||
|
char arr[17];
|
||||||
|
arr[16] = 0; //zero-terminated
|
||||||
|
uint32 index = 15;
|
||||||
|
uint32 const div = 16;
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
uint64 quo = number / div;
|
||||||
|
uint64 rmd = number % div;
|
||||||
|
number = quo;
|
||||||
|
arr[index--] = look_up[rmd];
|
||||||
|
if (number == 0)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
print_str(&(arr[index + 1]));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
clear_screen(void)
|
||||||
|
{
|
||||||
|
uint64 irq;
|
||||||
|
irq = spin_lock_irq_save(&lock);
|
||||||
|
text_pos = 0; // reset text_pos
|
||||||
|
mem_set((void *) FBUF, 0, 25 * 80 * 2);
|
||||||
|
spin_unlock_irq_restore(&lock, irq);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
kvprintf(char const *format, va_list args)
|
||||||
|
{
|
||||||
|
char buf[2];
|
||||||
|
int64 d;
|
||||||
|
uint64 u;
|
||||||
|
char *s;
|
||||||
|
|
||||||
|
buf[1] = '\0';
|
||||||
|
for (; *format != '\0'; format++)
|
||||||
|
{
|
||||||
|
if (*format != '%')
|
||||||
|
{
|
||||||
|
buf[0] = *format;
|
||||||
|
print_str(buf);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
format++;
|
||||||
|
switch (*format)
|
||||||
|
{
|
||||||
|
case 'd':
|
||||||
|
d = va_arg(args, int64);
|
||||||
|
print_int(d);
|
||||||
|
break;
|
||||||
|
case 'u':
|
||||||
|
u = va_arg(args, uint64);
|
||||||
|
print_uint(u);
|
||||||
|
break;
|
||||||
|
case 's':
|
||||||
|
s = va_arg(args, char *);
|
||||||
|
print_str(s);
|
||||||
|
break;
|
||||||
|
case 'x':
|
||||||
|
u = va_arg(args, uint64);
|
||||||
|
print_hex(u, 0);
|
||||||
|
break;
|
||||||
|
case 'X':
|
||||||
|
u = va_arg(args, uint64);
|
||||||
|
print_hex(u, 1);
|
||||||
|
break;
|
||||||
|
case '%':
|
||||||
|
buf[0] = '%';
|
||||||
|
print_str(buf);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
buf[0] = '%';
|
||||||
|
print_str(buf);
|
||||||
|
format--;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
kprintf(char const *format, ...)
|
||||||
|
{
|
||||||
|
va_list args;
|
||||||
|
va_start(args, format);
|
||||||
|
uint64 irq;
|
||||||
|
irq = spin_lock_irq_save(&lock);
|
||||||
|
kvprintf(format, args);
|
||||||
|
spin_unlock_irq_restore(&lock, irq);
|
||||||
|
va_end(args);
|
||||||
|
}
|
132
src/proc.c
Normal file
132
src/proc.c
Normal file
@ -0,0 +1,132 @@
|
|||||||
|
#include "error.h"
|
||||||
|
#include "proc.h"
|
||||||
|
#include "pmm.h"
|
||||||
|
#include "vmm.h"
|
||||||
|
#include "thread.h"
|
||||||
|
#include "elf64.h"
|
||||||
|
#include "cpu.h"
|
||||||
|
#include "paging.h"
|
||||||
|
#include "memory_layout.h"
|
||||||
|
|
||||||
|
static struct spin_lock proc_list_lock;
|
||||||
|
static struct llist proc_list;
|
||||||
|
static uint32 proc_id;
|
||||||
|
|
||||||
|
int32 proc_init(void* k_routine)
|
||||||
|
{
|
||||||
|
uint32 tid;
|
||||||
|
int32 ret = ESUCCESS;
|
||||||
|
spin_init(&proc_list_lock);
|
||||||
|
lb_llist_init(&proc_list);
|
||||||
|
proc_id = 0;
|
||||||
|
|
||||||
|
// hack to make the first process
|
||||||
|
struct pcb *pcb = kalloc(sizeof(struct pcb));
|
||||||
|
if (pcb == NULL)
|
||||||
|
{
|
||||||
|
ret = ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret == ESUCCESS)
|
||||||
|
{
|
||||||
|
pcb->cr3 = read_cr3();
|
||||||
|
pcb->proc_id = (uint32) xinc_32((int32 *) &proc_id, 1);
|
||||||
|
spin_init(&pcb->lock);
|
||||||
|
lb_llist_init(&pcb->threads);
|
||||||
|
|
||||||
|
ret = thread_create(pcb, k_routine, NULL, &tid);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret != ESUCCESS)
|
||||||
|
{
|
||||||
|
kfree(pcb);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 proc_create(void* elf64, uint32 *pid)
|
||||||
|
{
|
||||||
|
int32 ret = ESUCCESS;
|
||||||
|
|
||||||
|
// allocate struct pcb
|
||||||
|
struct pcb *pcb = kalloc(sizeof(struct pcb));
|
||||||
|
if (pcb == NULL)
|
||||||
|
{
|
||||||
|
ret = ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
// allocate pml4
|
||||||
|
uintptr cr3 = (uintptr) NULL;
|
||||||
|
if (ret == ESUCCESS)
|
||||||
|
{
|
||||||
|
cr3 = (uintptr) pmalloc(PAGE_SIZE);
|
||||||
|
if (cr3 == (uintptr) NULL)
|
||||||
|
{
|
||||||
|
ret = ENOMEM;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void* entry = NULL;
|
||||||
|
bool pushed = FALSE;
|
||||||
|
if (ret == ESUCCESS)
|
||||||
|
{
|
||||||
|
// init pcb
|
||||||
|
pcb->cr3 = cr3;
|
||||||
|
pcb->proc_id = (uint32) xinc_32((int32 *) &proc_id, 1);
|
||||||
|
spin_init(&pcb->lock);
|
||||||
|
lb_llist_init(&pcb->threads);
|
||||||
|
|
||||||
|
// write page tables
|
||||||
|
uintptr cur_cr3 = read_cr3();
|
||||||
|
uint64 *cur_pml4 = R_PADDR(cur_cr3);
|
||||||
|
|
||||||
|
uint64 *pml4 = R_PADDR(cr3);
|
||||||
|
// identity map the kernel space
|
||||||
|
for (uint32 i = PML4_ENTRY(K_START); i < 512; i++)
|
||||||
|
{
|
||||||
|
pml4[i] = cur_pml4[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
// register the process
|
||||||
|
spin_lock(&proc_list_lock);
|
||||||
|
lb_llist_push_front(&proc_list, &pcb->list_node);
|
||||||
|
spin_unlock(&proc_list_lock);
|
||||||
|
pushed = TRUE;
|
||||||
|
|
||||||
|
ret = elf_load_file(pcb, elf64, &entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret == ESUCCESS)
|
||||||
|
{
|
||||||
|
// create the thread
|
||||||
|
uint32 tid;
|
||||||
|
ret = thread_create(pcb, entry, (void*)0x13141516, &tid);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret == ESUCCESS)
|
||||||
|
{
|
||||||
|
*pid = pcb->proc_id;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (pcb != NULL)
|
||||||
|
{
|
||||||
|
if (pushed)
|
||||||
|
{
|
||||||
|
spin_lock(&proc_list_lock);
|
||||||
|
lb_llist_remove_by_ref(&proc_list, &pcb->list_node);
|
||||||
|
spin_unlock(&proc_list_lock);
|
||||||
|
}
|
||||||
|
kfree(pcb);
|
||||||
|
}
|
||||||
|
|
||||||
|
// need to properly unmap everything
|
||||||
|
if (cr3 != (uintptr) NULL)
|
||||||
|
{
|
||||||
|
pfree(cr3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
47
src/spin_lock.c
Normal file
47
src/spin_lock.c
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
#include "spin_lock.h"
|
||||||
|
#include "cpu.h"
|
||||||
|
#include "intr.h"
|
||||||
|
|
||||||
|
void
|
||||||
|
spin_init(struct spin_lock *lock)
|
||||||
|
{
|
||||||
|
if (lock != NULL)
|
||||||
|
{
|
||||||
|
lock->val = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
spin_lock(struct spin_lock *lock)
|
||||||
|
{
|
||||||
|
if (lock != NULL)
|
||||||
|
{
|
||||||
|
while (cmpxchg_32(&lock->val, 0, 1) != 0)
|
||||||
|
{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
spin_unlock(struct spin_lock *lock)
|
||||||
|
{
|
||||||
|
if (lock != NULL)
|
||||||
|
{
|
||||||
|
lock->val = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64 spin_lock_irq_save(struct spin_lock* lock)
|
||||||
|
{
|
||||||
|
uint64 ret = READ_IRQ();
|
||||||
|
WRITE_IRQ(0xf);
|
||||||
|
spin_lock(lock);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void spin_unlock_irq_restore(struct spin_lock* lock, uint64 irq)
|
||||||
|
{
|
||||||
|
spin_unlock(lock);
|
||||||
|
WRITE_IRQ(irq);
|
||||||
|
}
|
28
src/syscall.c
Normal file
28
src/syscall.c
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
#include <print.h>
|
||||||
|
#include "syscall.h"
|
||||||
|
#include "thread.h"
|
||||||
|
#include "intr.h"
|
||||||
|
|
||||||
|
void *syscall_handler(struct intr_frame *frame)
|
||||||
|
{
|
||||||
|
uint64 vec = (uint32)frame->rdi;
|
||||||
|
if (vec == 0)
|
||||||
|
{
|
||||||
|
// print
|
||||||
|
kprintf("%s", (char*)frame->rsi);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
kprintf("[WARN] Unrecognized syscall from proc %d, thread %d, function %d\n", (uint64) get_cur_thread()->proc->proc_id,
|
||||||
|
(uint64) get_cur_thread()->tid,
|
||||||
|
vec);
|
||||||
|
}
|
||||||
|
|
||||||
|
// nothing for the handler
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void syscall_init()
|
||||||
|
{
|
||||||
|
set_intr_handler(INTR_VEC_SYSCALL, syscall_handler);
|
||||||
|
}
|
420
src/thread.c
Normal file
420
src/thread.c
Normal file
@ -0,0 +1,420 @@
|
|||||||
|
#include <print.h>
|
||||||
|
#include <paging.h>
|
||||||
|
#include "thread.h"
|
||||||
|
#include "error.h"
|
||||||
|
#include "proc.h"
|
||||||
|
#include "clib.h"
|
||||||
|
#include "vmm.h"
|
||||||
|
#include "cpu.h"
|
||||||
|
#include "intr.h"
|
||||||
|
#include "memory_layout.h"
|
||||||
|
|
||||||
|
#define THREAD_STACK_SIZE (PAGE_SIZE)
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
THREAD_STATE_RDY = 0,
|
||||||
|
THREAD_STATE_BLK = 1,
|
||||||
|
THREAD_STATE_ZOM = 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
static uint32 thread_id;
|
||||||
|
static struct tcb *cur_thread;
|
||||||
|
static struct llist thread_list;
|
||||||
|
static struct spin_lock thread_list_lock;
|
||||||
|
|
||||||
|
void list_threads()
|
||||||
|
{
|
||||||
|
struct llist_node *node = lb_llist_first(&thread_list);
|
||||||
|
struct tcb *tcb = NULL;
|
||||||
|
while (node != NULL)
|
||||||
|
{
|
||||||
|
tcb = OBTAIN_STRUCT_ADDR(node, struct tcb, list_node);
|
||||||
|
// reading no need to lock thread lock
|
||||||
|
kprintf("Thread %d\n", (uint64) tcb->tid);
|
||||||
|
node = lb_llist_next(node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct tcb *get_tcb_by_id(uint32 tid)
|
||||||
|
{
|
||||||
|
// the thread list lock must be held
|
||||||
|
struct llist_node *node = lb_llist_first(&thread_list);
|
||||||
|
struct tcb *tcb = NULL;
|
||||||
|
while (node != NULL)
|
||||||
|
{
|
||||||
|
tcb = OBTAIN_STRUCT_ADDR(node, struct tcb, list_node);
|
||||||
|
// reading no need to lock thread lock
|
||||||
|
if (tcb->tid == tid)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
node = lb_llist_next(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
return tcb;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 thread_get_exit_code(uint32 tid, int32 *exit_code)
|
||||||
|
{
|
||||||
|
int32 ret = ESUCCESS;
|
||||||
|
|
||||||
|
struct tcb *tcb;
|
||||||
|
uint64 irq = spin_lock_irq_save(&thread_list_lock);
|
||||||
|
tcb = get_tcb_by_id(tid);
|
||||||
|
spin_unlock_irq_restore(&thread_list_lock, irq);
|
||||||
|
|
||||||
|
if (tcb == NULL)
|
||||||
|
{
|
||||||
|
ret = EINVARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret == ESUCCESS)
|
||||||
|
{
|
||||||
|
if (tcb->state == THREAD_STATE_ZOM)
|
||||||
|
{
|
||||||
|
*exit_code = tcb->exit_code;
|
||||||
|
|
||||||
|
// this is unfair but do it for now
|
||||||
|
thread_yield();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ret = EINVARG;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 thread_stop(uint32 tid, int32 code)
|
||||||
|
{
|
||||||
|
int32 ret = ESUCCESS;
|
||||||
|
|
||||||
|
struct tcb *tcb;
|
||||||
|
uint64 irq = spin_lock_irq_save(&thread_list_lock);
|
||||||
|
tcb = get_tcb_by_id(tid);
|
||||||
|
spin_unlock_irq_restore(&thread_list_lock, irq);
|
||||||
|
|
||||||
|
if (tcb == NULL)
|
||||||
|
{
|
||||||
|
ret = EINVARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret == ESUCCESS)
|
||||||
|
{
|
||||||
|
spin_lock(&tcb->lock);
|
||||||
|
if (tcb->state != THREAD_STATE_ZOM)
|
||||||
|
{
|
||||||
|
tcb->state = THREAD_STATE_ZOM;
|
||||||
|
tcb->exit_code = code;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ret = EINVARG;
|
||||||
|
}
|
||||||
|
spin_unlock(&tcb->lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret == ESUCCESS)
|
||||||
|
{
|
||||||
|
// well this is unfair
|
||||||
|
// but do this for now
|
||||||
|
thread_yield();
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_cur_thread(struct tcb *t)
|
||||||
|
{
|
||||||
|
// first time setting
|
||||||
|
KASSERT(cur_thread == NULL);
|
||||||
|
cur_thread = t;
|
||||||
|
}
|
||||||
|
|
||||||
|
// this guy picks the next thread to run
|
||||||
|
// by updating cur_thread
|
||||||
|
// timer interrupt always
|
||||||
|
// the actual context swap is done elsewhere
|
||||||
|
void thread_schedule()
|
||||||
|
{
|
||||||
|
// only timer interrupt context
|
||||||
|
spin_lock(&thread_list_lock);
|
||||||
|
|
||||||
|
if (cur_thread == NULL)
|
||||||
|
{
|
||||||
|
// first thread hack
|
||||||
|
cur_thread = OBTAIN_STRUCT_ADDR(lb_llist_first(&thread_list), struct tcb, list_node);
|
||||||
|
}
|
||||||
|
|
||||||
|
KASSERT(cur_thread != NULL);
|
||||||
|
|
||||||
|
struct llist_node *next_node = &cur_thread->list_node;
|
||||||
|
// since there must be a null thread, node cannot be null
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
// get the next tcb in a round robbin fashion
|
||||||
|
next_node = lb_llist_next(next_node);
|
||||||
|
if (next_node == NULL)
|
||||||
|
{
|
||||||
|
next_node = lb_llist_first(&thread_list);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct tcb *next = OBTAIN_STRUCT_ADDR(next_node, struct tcb, list_node);
|
||||||
|
|
||||||
|
// we are only checking states here so no need to worry
|
||||||
|
// since thread_block always fires an timer interrupt, which will be served immediately after this returns
|
||||||
|
// so even if someone else from another core blocks this thread during this window
|
||||||
|
// this thread will get descheduled right after the current timer interrupt deasserts
|
||||||
|
// the worst case is someone unblocked a thread right after we checked it, but it doesn't break integrity
|
||||||
|
if (next->state == THREAD_STATE_RDY)
|
||||||
|
{
|
||||||
|
cur_thread = next;
|
||||||
|
// stop looping, scheduler runs fast, although o(n)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (next->state == THREAD_STATE_ZOM)
|
||||||
|
{
|
||||||
|
// zombie thread, should use ref count to properly deallocate stuff
|
||||||
|
// TODO: clean up zombie threads
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
spin_unlock(&thread_list_lock);
|
||||||
|
#ifdef KDBG
|
||||||
|
kprintf("[Scheduler] Next Proc: %d. Next Thread: %d\n", (uint64)cur_thread->proc->proc_id, (uint64)cur_thread->tid);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void thread_exit(int32 code)
|
||||||
|
{
|
||||||
|
spin_lock(&cur_thread->lock);
|
||||||
|
KASSERT(cur_thread->state == THREAD_STATE_RDY);
|
||||||
|
cur_thread->exit_code = code;
|
||||||
|
cur_thread->state = THREAD_STATE_ZOM;
|
||||||
|
spin_unlock(&cur_thread->lock);
|
||||||
|
thread_yield();
|
||||||
|
// shouldn't get here
|
||||||
|
KASSERT(FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 thread_resume(uint32 tid)
|
||||||
|
{
|
||||||
|
int32 ret = ESUCCESS;
|
||||||
|
|
||||||
|
struct tcb *tcb;
|
||||||
|
uint64 irq = spin_lock_irq_save(&thread_list_lock);
|
||||||
|
tcb = get_tcb_by_id(tid);
|
||||||
|
spin_unlock_irq_restore(&thread_list_lock, irq);
|
||||||
|
|
||||||
|
if (tcb == NULL)
|
||||||
|
{
|
||||||
|
ret = EINVARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret == ESUCCESS)
|
||||||
|
{
|
||||||
|
spin_lock(&tcb->lock);
|
||||||
|
if (tcb->state == THREAD_STATE_BLK)
|
||||||
|
{
|
||||||
|
tcb->state = THREAD_STATE_RDY;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ret = EINVARG;
|
||||||
|
}
|
||||||
|
spin_unlock(&tcb->lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 thread_block(uint32 tid)
|
||||||
|
{
|
||||||
|
int32 ret = ESUCCESS;
|
||||||
|
|
||||||
|
struct tcb *tcb;
|
||||||
|
uint64 irq = spin_lock_irq_save(&thread_list_lock);
|
||||||
|
tcb = get_tcb_by_id(tid);
|
||||||
|
spin_unlock_irq_restore(&thread_list_lock, irq);
|
||||||
|
|
||||||
|
if (tcb == NULL)
|
||||||
|
{
|
||||||
|
ret = EINVARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret == ESUCCESS)
|
||||||
|
{
|
||||||
|
spin_lock(&tcb->lock);
|
||||||
|
if (tcb->state == THREAD_STATE_RDY)
|
||||||
|
{
|
||||||
|
tcb->state = THREAD_STATE_BLK;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ret = EINVARG;
|
||||||
|
}
|
||||||
|
spin_unlock(&tcb->lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret == ESUCCESS)
|
||||||
|
{
|
||||||
|
// this is unfair but do it for now
|
||||||
|
thread_yield();
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void thread_yield()
|
||||||
|
{
|
||||||
|
// emulate a timer interrupt on target core
|
||||||
|
send_ipi(INTR_VEC_TIMER);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define MODE_K (0)
|
||||||
|
#define MODE_U (1)
|
||||||
|
|
||||||
|
static void write_intr_frame(struct intr_frame *frame, uint32 mode, uint64 iret_addr, uint64 iret_stack, uint64 arg)
|
||||||
|
{
|
||||||
|
uint64 dsel = mode == MODE_K ? SEL(GDT_K_DATA, 0, 0) : SEL(GDT_U_DATA, 0, 3);
|
||||||
|
uint64 csel = mode == MODE_K ? SEL(GDT_K_CODE, 0, 0) : SEL(GDT_U_CODE, 0, 3);
|
||||||
|
frame->ss = dsel;
|
||||||
|
frame->ds = dsel;
|
||||||
|
frame->es = dsel;
|
||||||
|
frame->fs = dsel;
|
||||||
|
frame->gs = dsel;
|
||||||
|
frame->cs = csel;
|
||||||
|
frame->rip = (uint64) iret_addr;
|
||||||
|
frame->rdi = arg;
|
||||||
|
frame->rsp = iret_stack;
|
||||||
|
|
||||||
|
// only set interrupt enable flag
|
||||||
|
frame->rflags = (0x200);
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 thread_create(struct pcb *proc, void *entry, void *args, uint32 *tid)
|
||||||
|
{
|
||||||
|
int32 ret = ESUCCESS;
|
||||||
|
|
||||||
|
struct tcb *tcb = kalloc(sizeof(struct tcb));
|
||||||
|
|
||||||
|
if (tcb == NULL)
|
||||||
|
{
|
||||||
|
ret = ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
// allocate thread kernel stack
|
||||||
|
// 4k stack for now
|
||||||
|
// no stack overflow
|
||||||
|
uintptr ustack = (uintptr) NULL;
|
||||||
|
uint64 *kstack = NULL;
|
||||||
|
uint64 *kstack_top = NULL;
|
||||||
|
if (ret == ESUCCESS)
|
||||||
|
{
|
||||||
|
kstack = kalloc(THREAD_STACK_SIZE);
|
||||||
|
|
||||||
|
if (kstack == NULL)
|
||||||
|
{
|
||||||
|
ret = ENOMEM;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
kstack_top = (uint64 *) ((uintptr) kstack + THREAD_STACK_SIZE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// allocate ustack always
|
||||||
|
if (ret == ESUCCESS)
|
||||||
|
{
|
||||||
|
ustack = (uintptr) pmalloc(THREAD_STACK_SIZE);
|
||||||
|
|
||||||
|
if (ustack == (uintptr) NULL)
|
||||||
|
{
|
||||||
|
ret = ENOMEM;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct intr_frame *frame = NULL;
|
||||||
|
if (ret == ESUCCESS)
|
||||||
|
{
|
||||||
|
tcb->tid = (uint32) xinc_32((int32 *) &thread_id, 1);
|
||||||
|
spin_init(&tcb->lock);
|
||||||
|
tcb->exit_code = 0;
|
||||||
|
tcb->state = THREAD_STATE_RDY;
|
||||||
|
tcb->proc = proc;
|
||||||
|
tcb->kstack = kstack;
|
||||||
|
tcb->kstack_sz = THREAD_STACK_SIZE;
|
||||||
|
tcb->ustack_sz = THREAD_STACK_SIZE;
|
||||||
|
tcb->ustack = ustack;
|
||||||
|
|
||||||
|
// write initial context information on the kernel stack
|
||||||
|
frame = (struct intr_frame *) ((uintptr) kstack_top - sizeof(struct intr_frame));
|
||||||
|
mem_set(frame, 0, sizeof(struct intr_frame));
|
||||||
|
|
||||||
|
// here we wanna check if the entrance is user mode
|
||||||
|
if (IS_KERN_SPACE(entry))
|
||||||
|
{
|
||||||
|
write_intr_frame(frame, MODE_K, (uint64) entry, (uint64) kstack_top, (uint64) args);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// map ustack to the user address space
|
||||||
|
ret = map_vmem(proc->cr3, U_STACK_VADDR, ustack);
|
||||||
|
|
||||||
|
if (ret == ESUCCESS)
|
||||||
|
{
|
||||||
|
write_intr_frame(frame, MODE_U, (uint64) entry, (uint64) (U_STACK_VADDR + THREAD_STACK_SIZE),
|
||||||
|
(uint64) args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret == ESUCCESS)
|
||||||
|
{
|
||||||
|
// update interrupt stack pointer
|
||||||
|
tcb->rsp0 = (uint64) frame;
|
||||||
|
|
||||||
|
// add to thread list
|
||||||
|
uint64 irq;
|
||||||
|
irq = spin_lock_irq_save(&thread_list_lock);
|
||||||
|
lb_llist_push_back(&thread_list, &tcb->list_node);
|
||||||
|
spin_unlock_irq_restore(&thread_list_lock, irq);
|
||||||
|
*tid = tcb->tid;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret != ESUCCESS)
|
||||||
|
{
|
||||||
|
// clean up
|
||||||
|
if (tcb != NULL)
|
||||||
|
{
|
||||||
|
kfree(tcb);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ustack != (uintptr) NULL)
|
||||||
|
{
|
||||||
|
pfree(ustack);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (kstack != NULL)
|
||||||
|
{
|
||||||
|
kfree(kstack);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void thread_init()
|
||||||
|
{
|
||||||
|
cur_thread = NULL;
|
||||||
|
lb_llist_init(&thread_list);
|
||||||
|
spin_init(&thread_list_lock);
|
||||||
|
thread_id = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct tcb *get_cur_thread()
|
||||||
|
{
|
||||||
|
return cur_thread;
|
||||||
|
}
|
69
src/vmm.c
Normal file
69
src/vmm.c
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
#include <cdef.h>
|
||||||
|
#include <vmm.h>
|
||||||
|
#include <pmm.h>
|
||||||
|
#include <paging.h>
|
||||||
|
#include <memory_layout.h>
|
||||||
|
#include <error.h>
|
||||||
|
#include <cpu.h>
|
||||||
|
#include <print.h>
|
||||||
|
|
||||||
|
static void *pointer;
|
||||||
|
static struct spin_lock lock;
|
||||||
|
|
||||||
|
void *kalloc(usize size)
|
||||||
|
{
|
||||||
|
spin_lock(&lock);
|
||||||
|
|
||||||
|
void *ret;
|
||||||
|
if ((size > KERNEL_PAGE_SIZE) || ((uintptr) pointer + size >= K_DYN_END))
|
||||||
|
{
|
||||||
|
ret = NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ret = pointer;
|
||||||
|
pointer = (void *) ((uintptr) pointer + KERNEL_PAGE_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
spin_unlock(&lock);
|
||||||
|
|
||||||
|
/* Hack */
|
||||||
|
int32 status = ESUCCESS;
|
||||||
|
if (ret != NULL)
|
||||||
|
{
|
||||||
|
// check if the target page is already mapped
|
||||||
|
// ret val does not cross page boundries
|
||||||
|
if (get_paddr(read_cr3(), (uintptr) ret) == (uintptr) NULL)
|
||||||
|
{
|
||||||
|
uintptr frame = (uintptr) pmalloc(PAGE_SIZE);
|
||||||
|
status = (frame != (uintptr) NULL) && (map_vmem(read_cr3(), (uintptr) ret, frame) != ESUCCESS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status != ESUCCESS)
|
||||||
|
{
|
||||||
|
ret = NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
flush_tlb();
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef KDBG
|
||||||
|
kprintf("Allocated Virtual: 0x%x Size: %d\n", ret, (uint64) size);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void init_vm()
|
||||||
|
{
|
||||||
|
pointer = (void *) K_DYNAMIC;
|
||||||
|
spin_init(&lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
kfree(void *ptr)
|
||||||
|
{
|
||||||
|
UNREFERENCED(ptr);
|
||||||
|
}
|
6
test/bochsrc
Normal file
6
test/bochsrc
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
display_library: x, options="gui_debug"
|
||||||
|
cpuid: 1g_pages=1
|
||||||
|
ata0-master: type=cdrom, path="out/curros.iso", status=inserted
|
||||||
|
boot: cdrom
|
||||||
|
magic_break: enabled=1
|
||||||
|
memory: guest=512, host=512
|
4
test/qemu.sh
Executable file
4
test/qemu.sh
Executable file
@ -0,0 +1,4 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
qemu-system-x86_64 -m 128 -monitor stdio -cdrom out/curros.iso -s -S -d cpu_reset
|
||||||
|
|
||||||
|
|
12
user/curros.asm
Normal file
12
user/curros.asm
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
SYSCALL_VEC equ 51
|
||||||
|
|
||||||
|
SECTION .text
|
||||||
|
BITS 64
|
||||||
|
|
||||||
|
GLOBAL syscall
|
||||||
|
|
||||||
|
syscall:
|
||||||
|
; rdi = function number
|
||||||
|
; rsi = args
|
||||||
|
int SYSCALL_VEC
|
||||||
|
ret
|
36
user/hello.c
Normal file
36
user/hello.c
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
#include <stdint.h>
|
||||||
|
#include <cdef.h>
|
||||||
|
#include <curros.h>
|
||||||
|
|
||||||
|
#define THREAD_DELAY (5000000*4)
|
||||||
|
|
||||||
|
void
|
||||||
|
main(void *dat)
|
||||||
|
{
|
||||||
|
char *msg_ok = "[UThread3] Magic number OK.\n";
|
||||||
|
char *msg_bad = "[UThread3] Magic number FAILED.\n";
|
||||||
|
char msg[] = "[UThread3] \n";
|
||||||
|
|
||||||
|
uint32 success = 0;
|
||||||
|
uint32 magic = 0x13141516;
|
||||||
|
if ((uint32) dat == magic)
|
||||||
|
{
|
||||||
|
syscall(SYSCALL_FUNC_PRINT, msg_ok);
|
||||||
|
success = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
syscall(SYSCALL_FUNC_PRINT, msg_bad);
|
||||||
|
success = 0;
|
||||||
|
}
|
||||||
|
int i = 0;
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
poor_sleep(THREAD_DELAY);
|
||||||
|
i = i % 10;
|
||||||
|
msg[11] = i + 48;
|
||||||
|
syscall(SYSCALL_FUNC_PRINT, msg);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
// don't return here, need to call thread exit
|
||||||
|
}
|
22
user/inc/cdef.h
Normal file
22
user/inc/cdef.h
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
typedef uint32_t uint32;
|
||||||
|
typedef int32_t int32;
|
||||||
|
typedef uint64_t uint64;
|
||||||
|
typedef int64_t int64;
|
||||||
|
typedef uintptr_t uintptr;
|
||||||
|
typedef uint16_t uint16;
|
||||||
|
typedef int16_t int16;
|
||||||
|
typedef uint8_t uint8;
|
||||||
|
typedef int8_t int8;
|
||||||
|
typedef size_t usize;
|
||||||
|
typedef _Bool bool;
|
||||||
|
|
||||||
|
#define TRUE (1)
|
||||||
|
#define FALSE (0)
|
||||||
|
|
||||||
|
|
14
user/inc/curros.h
Normal file
14
user/inc/curros.h
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "cdef.h"
|
||||||
|
|
||||||
|
#define SYSCALL_FUNC_PRINT (0)
|
||||||
|
|
||||||
|
void syscall(uint32 func, void* args);
|
||||||
|
|
||||||
|
static inline void poor_sleep(uint32 dat)
|
||||||
|
{
|
||||||
|
for(uint32 i = 0; i < dat; i++)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
26
user/linker.ld
Normal file
26
user/linker.ld
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
ENTRY(main)
|
||||||
|
|
||||||
|
KERNEL_PAGE_SIZE = 0x1000;
|
||||||
|
USER_APPLICATION_VADDR = 0x1000000;
|
||||||
|
|
||||||
|
SECTIONS
|
||||||
|
{
|
||||||
|
. = USER_APPLICATION_VADDR;
|
||||||
|
|
||||||
|
.text ALIGN(KERNEL_PAGE_SIZE):
|
||||||
|
{
|
||||||
|
*(.text)
|
||||||
|
}
|
||||||
|
|
||||||
|
.data ALIGN(KERNEL_PAGE_SIZE):
|
||||||
|
{
|
||||||
|
*(.data)
|
||||||
|
*(.rodata*)
|
||||||
|
}
|
||||||
|
|
||||||
|
.bss ALIGN(KERNEL_PAGE_SIZE):
|
||||||
|
{
|
||||||
|
*(.bss)
|
||||||
|
*(COMMON)
|
||||||
|
}
|
||||||
|
}
|
91
user/makefile
Normal file
91
user/makefile
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
|
||||||
|
AS := nasm
|
||||||
|
CC := clang-6.0
|
||||||
|
LD := lld-6.0
|
||||||
|
DAS := llvm-objdump-6.0
|
||||||
|
|
||||||
|
.DEFAULT_GOAL := all
|
||||||
|
|
||||||
|
C_FLAGS_ARCH_X86_64 := -target x86_64-pc-none-elf \
|
||||||
|
-mno-red-zone \
|
||||||
|
-mno-mmx \
|
||||||
|
-mno-sse \
|
||||||
|
-mno-sse2 \
|
||||||
|
-mno-sse3 \
|
||||||
|
-mno-3dnow
|
||||||
|
|
||||||
|
C_FLAGS = -x c \
|
||||||
|
-g \
|
||||||
|
-c \
|
||||||
|
-O0 \
|
||||||
|
-std=c17 \
|
||||||
|
-Wall \
|
||||||
|
-Werror \
|
||||||
|
-Wextra \
|
||||||
|
-Wpedantic \
|
||||||
|
-ffreestanding \
|
||||||
|
-fno-pic \
|
||||||
|
-fno-stack-protector \
|
||||||
|
-Wno-error=int-to-pointer-cast \
|
||||||
|
-Wno-error=zero-length-array \
|
||||||
|
$(C_FLAGS_ARCH_X86_64) \
|
||||||
|
-I$(INC)/
|
||||||
|
|
||||||
|
AS_FLAGS = -w+all \
|
||||||
|
-w+error \
|
||||||
|
-f elf64 \
|
||||||
|
-F dwarf \
|
||||||
|
-g \
|
||||||
|
-I$(INC)/ \
|
||||||
|
|
||||||
|
LD_FLAGS = -fuse-ld=$(LD) \
|
||||||
|
-nostdlib \
|
||||||
|
-Wl, linker.ld \
|
||||||
|
-Wl,--fatal-warnings
|
||||||
|
|
||||||
|
# ===============================
|
||||||
|
# HERE COMES file definitions
|
||||||
|
# ===============================
|
||||||
|
|
||||||
|
INC := inc
|
||||||
|
SRC := .
|
||||||
|
OUT := out
|
||||||
|
TGT := $(OUT)/hello.elf
|
||||||
|
|
||||||
|
# ===============================
|
||||||
|
# Add additional c source files here
|
||||||
|
# ===============================
|
||||||
|
C_SRC := hello.c
|
||||||
|
|
||||||
|
# ===============================
|
||||||
|
# Add additional ASM source files here
|
||||||
|
# ===============================
|
||||||
|
ASM_SRC := curros.asm
|
||||||
|
|
||||||
|
# ===============================
|
||||||
|
# Compilation rules
|
||||||
|
# ===============================
|
||||||
|
C_OBJ := $(addsuffix .o, $(addprefix $(OUT)/,$(C_SRC)))
|
||||||
|
|
||||||
|
ASM_OBJ := $(addsuffix .o, $(addprefix $(OUT)/,$(ASM_SRC)))
|
||||||
|
|
||||||
|
$(C_OBJ): $(OUT)/%.c.o : %.c
|
||||||
|
$(CC) $(C_FLAGS) -o $@ $<
|
||||||
|
|
||||||
|
$(ASM_OBJ): $(OUT)/%.asm.o : %.asm
|
||||||
|
$(AS) $(AS_FLAGS) -o $@ $<
|
||||||
|
|
||||||
|
$(TGT): $(C_OBJ) $(ASM_OBJ)
|
||||||
|
$(CC) $(LD_FLAGS) -o $@ $^
|
||||||
|
|
||||||
|
.PHONY: mkdir
|
||||||
|
mkdir:
|
||||||
|
mkdir -p out
|
||||||
|
|
||||||
|
.PHONY: clean
|
||||||
|
clean:
|
||||||
|
rm -rf $(OUT)
|
||||||
|
|
||||||
|
.PHONY: all
|
||||||
|
all: mkdir $(TGT)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user