some test things
This commit is contained in:
+101
-75
@@ -1,96 +1,122 @@
|
||||
bits 32
|
||||
|
||||
section .multiboot
|
||||
align 4
|
||||
dd 0x1BADB002
|
||||
dd 0x00
|
||||
dd - (0x1BADB002+0x00)
|
||||
%define CR0_MP 0x00000002 /* bit 01 -> enable monitor coprocessor */
|
||||
%define CR0_NE 0x00000020 /* bit 05 -> enable native x87 FPU mode */
|
||||
%define CR0_WP 0x00010000 /* bit 16 -> enable write protect (for CoW) */
|
||||
%define CR0_AM 0x00040000 /* bit 18 -> enable alignment checking */
|
||||
%define CR0_PG 0x80000000 /* bit 31 -> enable paging */
|
||||
|
||||
section .data
|
||||
%define PAGE_OFFSET 0xC0000000
|
||||
%define GDT_BASE (0xFFFFFFFF - (PAGE_OFFSET - 1))
|
||||
|
||||
section .setup
|
||||
align 4
|
||||
multiboot_info:
|
||||
dd 0
|
||||
dd 0
|
||||
dd 0
|
||||
dd 0
|
||||
dd 0
|
||||
dd 0
|
||||
dd 0
|
||||
tmp_gdtr:
|
||||
dw ((3 * 8) - 1)
|
||||
tmp_gdta:
|
||||
dd tmp_gdt
|
||||
|
||||
global tss
|
||||
global tss_end
|
||||
align 4
|
||||
tss:
|
||||
dd 0 ; 0-3
|
||||
dd stack_top ; 4-7
|
||||
dd DATA_SEG ; 8-11
|
||||
dd 0 ; 12-15
|
||||
dd 0 ; 16-19
|
||||
dd 0 ; 20-23
|
||||
dd 0 ; 24-27
|
||||
dd 0 ; 28-31
|
||||
dd 0 ; 32-35
|
||||
dd 0 ; 36-39
|
||||
dd 0 ; 40-43
|
||||
dd 0 ; 44-47
|
||||
dd 0 ; 48-51
|
||||
dd 0 ; 52-55
|
||||
dd 0 ; 56-59
|
||||
dd 0 ; 60-63
|
||||
dd 0 ; 64-67
|
||||
dd 0 ; 68-71
|
||||
dd DATA_SEG ; 72-75
|
||||
dd CODE_SEG ; 76-79
|
||||
dd DATA_SEG ; 80-83
|
||||
dd DATA_SEG ; 84-87
|
||||
dd DATA_SEG ; 88-91
|
||||
dd DATA_SEG ; 92-95
|
||||
dd 0 ; 96-99
|
||||
dw 0 ; 100-101
|
||||
dw 104 ; 102-103
|
||||
tss_end:
|
||||
tmp_gdt:
|
||||
; null entry
|
||||
dw 0x0000
|
||||
dw 0x0000
|
||||
dw 0x0000
|
||||
dw 0x0000
|
||||
|
||||
section .bss
|
||||
stack_bottom:
|
||||
resb 16384
|
||||
stack_top:
|
||||
; /* KERNEL CODE */
|
||||
dw 0xFFFF ; /* segment limit 15-00 */
|
||||
dw 0x0000 ; /* base address 15-00 */
|
||||
db 0x00 ; /* base address 23-16 */
|
||||
db 0x9A ; /* P=1 DPL=00 S=1 TYPE=1010 (exec/read) */
|
||||
db 0xCF ; /* G=1 DB=1 0=0 AVL=0 SEGLIM=1111 */
|
||||
db GDT_BASE >> 24 ; /* base address 31-24 */
|
||||
|
||||
; /* KERNEL DATA */
|
||||
dw 0xFFFF ; /* segment limit 15-00 */
|
||||
dw 0x0000 ; /* base address 15-00 */
|
||||
db 0x00 ; /* base address 23-16 */
|
||||
db 0x92 ; /* P=1 DPL=00 S=1 TYPE=0010 (read/write) */
|
||||
db 0xCF ; /* G=1 DB=1 0=0 AVL=0 SEGLIM=1111 */
|
||||
db GDT_BASE >> 24 ; /* base address 31-24 */
|
||||
|
||||
section .gdt
|
||||
%include "src/gdt.asm"
|
||||
align 4
|
||||
multiboot_header:
|
||||
dd 0x1BADB002
|
||||
dd 0x00
|
||||
dd - (0x1BADB002 + 0x00)
|
||||
|
||||
section .text
|
||||
dd 0
|
||||
dd 0
|
||||
dd 0
|
||||
dd 0
|
||||
dd 0
|
||||
dd 0
|
||||
dd 0
|
||||
dd 0
|
||||
dd 0
|
||||
|
||||
; section .text
|
||||
global start:function (start.end - start)
|
||||
extern kmain ; this function is gonna be located in our c code(kernel.c)
|
||||
extern get_last_boot_addr
|
||||
extern gdt_init
|
||||
extern bss_init
|
||||
extern setup_tmp_pgdir
|
||||
|
||||
align 4
|
||||
start:
|
||||
mov esp, stack_top
|
||||
; mov esp, stack_top
|
||||
cli
|
||||
push ebx ; Сохраняем оригинальный ebx (указатель Multiboot)
|
||||
; push ebx ; Сохраняем оригинальный ebx (указатель Multiboot)
|
||||
|
||||
lgdt [gdt]
|
||||
;lgdt [gdt]
|
||||
lgdt [tmp_gdtr]
|
||||
|
||||
; Заполняем адрес TSS в дескрипторе GDT
|
||||
mov eax, tss ; Получаем 32-битный адрес tss
|
||||
mov ebx, gdt_tss ; Адрес дескриптора TSS в GDT
|
||||
mov [ebx + 2], ax ; Нижние 16 бит адреса TSS
|
||||
shr eax, 16 ; Сдвигаем для доступа к старшим битам
|
||||
mov [ebx + 4], al ; Средние 8 бит адреса TSS
|
||||
mov [ebx + 7], ah ; Верхние 8 бит адреса TSS
|
||||
mov cx, 0x10 ; data segment
|
||||
mov ds, cx
|
||||
mov es, cx
|
||||
mov fs, cx
|
||||
mov gs, cx
|
||||
mov ss, cx
|
||||
jmp 0x8:.huita ; 0x8 - code segment
|
||||
|
||||
mov ax, DATA_SEG
|
||||
mov ds, ax
|
||||
mov es, ax
|
||||
mov fs, ax
|
||||
mov gs, ax
|
||||
mov ss, ax
|
||||
jmp CODE_SEG:.huita
|
||||
.text
|
||||
|
||||
align 4
|
||||
.huita:
|
||||
mov ax, TSS_SEG
|
||||
ltr ax
|
||||
pop ebx ; Восстанавливаем оригинальный ebx
|
||||
push ebx ; Передаем его в kmain
|
||||
call kmain
|
||||
hlt
|
||||
mov esp, PAGE_OFFSET + 0x10000 ; default stack address
|
||||
push 0
|
||||
popf ; reset EFLAGS
|
||||
|
||||
push ebx ; save Multiboot info structure
|
||||
push eax ; save Multiboot magic value
|
||||
|
||||
call setup_tmp_pgdir
|
||||
mov cr3, eax
|
||||
|
||||
mov eax, cr0
|
||||
and eax, 0x00000011 ; disable all, preserve ET & PE (GRUB)
|
||||
or eax, 0x80000000 ; CR0_PG ; enable PG
|
||||
or eax, 0x40000 ; CR0_AM ; enable AM
|
||||
or eax, 0x10000 ; CR0_WP ; enable WP
|
||||
or eax, 0x20 ; CR0_NE ; enable NE
|
||||
or eax, 0x2 ; CR0_MP ; enable MP
|
||||
mov cr0, eax
|
||||
|
||||
call bss_init ; initialize BSS segment
|
||||
call gdt_init ; setup and load definitive GDT
|
||||
call get_last_boot_addr
|
||||
|
||||
pop ecx ; restore Multiboot magic value
|
||||
pop ebx ; restore Multiboot info structure
|
||||
|
||||
push eax ; save last boot address
|
||||
push ebx ; save Multiboot info structure
|
||||
push ecx ; save Multiboot magic value
|
||||
|
||||
pop ebx ; Восстанавливаем оригинальный ebx
|
||||
push ebx ; Передаем его в kmain
|
||||
call kmain
|
||||
hlt
|
||||
.end:
|
||||
|
||||
@@ -0,0 +1,171 @@
|
||||
//#include "../include/gdt.h"
|
||||
#include <stdint.h>
|
||||
#include "../include/string.h"
|
||||
|
||||
struct desc_r {
|
||||
uint16_t limit;
|
||||
uint32_t base_addr;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct seg_desc {
|
||||
unsigned sd_lolimit : 16; /* segment limit 0-15 bits */
|
||||
unsigned sd_lobase : 24; /* base address 0-23 bits */
|
||||
unsigned sd_loflags : 8; /* flags (P, DPL, S and TYPE) */
|
||||
unsigned sd_hilimit : 4; /* segment limit 16-19 bits */
|
||||
unsigned sd_hiflags : 4; /* flags (G, DB, 0 and AVL) */
|
||||
unsigned sd_hibase : 8; /* base address 24-31 bits */
|
||||
} __attribute__((packed));
|
||||
|
||||
struct gate_desc {
|
||||
unsigned gd_looffset: 16; /* offset 0-15 bits */
|
||||
unsigned gd_selector: 16; /* segment selector */
|
||||
unsigned gd_flags : 16; /* flags (P, DPL, TYPE, 0 and NULL) */
|
||||
unsigned gd_hioffset: 16; /* offset 16-31 bits */
|
||||
} __attribute__((packed));
|
||||
|
||||
extern char _end[], _edata[];
|
||||
|
||||
#define KERNEL_CS 0x08 /* kernel code segment */
|
||||
#define KERNEL_DS 0x10 /* kernel data segment */
|
||||
#define USER_CS 0x18 /* user code segment */
|
||||
#define USER_DS 0x20 /* user data segment */
|
||||
#define TSS 0x28 /* TSS segment */
|
||||
|
||||
|
||||
void load_gdt(uint32_t gdt_ptr) {
|
||||
asm volatile (
|
||||
"lgdt (%0)\n\t"
|
||||
"movw %1, %%ax\n\t"
|
||||
"movw %%ax, %%ds\n\t"
|
||||
"movw %%ax, %%es\n\t"
|
||||
"movw %%ax, %%fs\n\t"
|
||||
"movw %%ax, %%gs\n\t"
|
||||
"movw %%ax, %%ss\n\t"
|
||||
"ljmp %2, $1f\n\t"
|
||||
"1:\n\t"
|
||||
:
|
||||
: "r" (gdt_ptr), "i" (KERNEL_DS), "i" (KERNEL_CS)
|
||||
: "eax"
|
||||
);
|
||||
}
|
||||
|
||||
#define PAGE_SIZE 4096
|
||||
#define PAGE_SHIFT 0x0C
|
||||
|
||||
#define PAGE_MASK ~(PAGE_SIZE - 1) /* 0xFFFFF000 */
|
||||
#define PAGE_ALIGN(addr) (((addr) + (PAGE_SIZE - 1)) & PAGE_MASK)
|
||||
|
||||
#define KERNEL_BSS_SIZE ((int)_end - (int)_edata)
|
||||
|
||||
#define NR_GDT_ENTRIES 6 /* entries in GDT descriptor */
|
||||
#define NR_IDT_ENTRIES 256 /* entries in IDT descriptor */
|
||||
|
||||
/* low flags of Segment Descriptors */
|
||||
#define SD_CODE 0x0A /* CODE Exec/Read */
|
||||
#define SD_DATA 0x02 /* DATA Read/Write */
|
||||
|
||||
#define SD_32INTRGATE 0x0E /* 32-bit Interrupt Gate (0D110) */
|
||||
#define SD_32TRAPGATE 0x0F /* 32-bit Trap Gate (0D111) */
|
||||
|
||||
#define SD_CD 0x10 /* 0 = system / 1 = code/data */
|
||||
#define SD_DPL0 0x00 /* priority level 0 (kernel) */
|
||||
#define SD_DPL3 0x60 /* priority level 3 (user) */
|
||||
#define SD_PRESENT 0x80 /* segment present or valid */
|
||||
|
||||
/* high flags Segment Descriptors */
|
||||
#define SD_OPSIZE32 0x04 /* 32-bit code and data segments */
|
||||
#define SD_PAGE4KB 0x08 /* page granularity (4KB) */
|
||||
|
||||
/* low flags of the TSS Descriptors */
|
||||
#define SD_TSSPRESENT 0x89 /* TSS present and not busy flag */
|
||||
|
||||
/* EFLAGS */
|
||||
#define EF_IOPL 12 /* IOPL bit */
|
||||
|
||||
#define KERNEL_CS 0x08 /* kernel code segment */
|
||||
#define KERNEL_DS 0x10 /* kernel data segment */
|
||||
#define USER_CS 0x18 /* user code segment */
|
||||
#define USER_DS 0x20 /* user data segment */
|
||||
#define TSS 0x28 /* TSS segment */
|
||||
|
||||
|
||||
struct tss_entry_struct {
|
||||
uint32_t prev_tss; // The previous TSS - with hardware task switching these form a kind of backward linked list.
|
||||
uint32_t esp0; // The stack pointer to load when changing to kernel mode.
|
||||
uint32_t ss0; // The stack segment to load when changing to kernel mode.
|
||||
// Everything below here is unused.
|
||||
uint32_t esp1; // esp and ss 1 and 2 would be used when switching to rings 1 or 2.
|
||||
uint32_t ss1;
|
||||
uint32_t esp2;
|
||||
uint32_t ss2;
|
||||
uint32_t cr3;
|
||||
uint32_t eip;
|
||||
uint32_t eflags;
|
||||
uint32_t eax;
|
||||
uint32_t ecx;
|
||||
uint32_t edx;
|
||||
uint32_t ebx;
|
||||
uint32_t esp;
|
||||
uint32_t ebp;
|
||||
uint32_t esi;
|
||||
uint32_t edi;
|
||||
uint32_t es;
|
||||
uint32_t cs;
|
||||
uint32_t ss;
|
||||
uint32_t ds;
|
||||
uint32_t fs;
|
||||
uint32_t gs;
|
||||
uint32_t ldt;
|
||||
uint16_t trap;
|
||||
uint16_t iomap_base;
|
||||
} __packed;
|
||||
|
||||
void bss_init()
|
||||
{
|
||||
memset((void *)((int)_edata), 0, KERNEL_BSS_SIZE);
|
||||
}
|
||||
|
||||
uint32_t get_last_boot_addr()
|
||||
{
|
||||
return ((unsigned int)_end & PAGE_MASK) + PAGE_SIZE;
|
||||
}
|
||||
|
||||
struct seg_desc gdt[NR_GDT_ENTRIES];
|
||||
|
||||
struct desc_r gdtr = {
|
||||
sizeof(gdt) - 1,
|
||||
(unsigned int)&gdt
|
||||
};
|
||||
|
||||
static void gdt_set_entry(int num, unsigned int base_addr, unsigned int limit, char loflags, char hiflags)
|
||||
{
|
||||
num /= sizeof(struct seg_desc);
|
||||
gdt[num].sd_lolimit = limit & 0xFFFF;
|
||||
gdt[num].sd_lobase = base_addr & 0xFFFFFF;
|
||||
gdt[num].sd_loflags = loflags;
|
||||
gdt[num].sd_hilimit = (limit >> 16) & 0x0F;
|
||||
gdt[num].sd_hiflags = hiflags;
|
||||
gdt[num].sd_hibase = (base_addr >> 24) & 0xFF;
|
||||
}
|
||||
|
||||
void gdt_init(void)
|
||||
{
|
||||
unsigned char loflags;
|
||||
|
||||
gdt_set_entry(0, 0, 0, 0, 0); /* null descriptor */
|
||||
|
||||
loflags = SD_CODE | SD_CD | SD_DPL0 | SD_PRESENT;
|
||||
gdt_set_entry(KERNEL_CS, 0, 0xFFFFFFFF, loflags, SD_OPSIZE32 | SD_PAGE4KB);
|
||||
loflags = SD_DATA | SD_CD | SD_DPL0 | SD_PRESENT;
|
||||
gdt_set_entry(KERNEL_DS, 0, 0xFFFFFFFF, loflags, SD_OPSIZE32 | SD_PAGE4KB);
|
||||
|
||||
loflags = SD_CODE | SD_CD | SD_DPL3 | SD_PRESENT;
|
||||
gdt_set_entry(USER_CS, 0, 0xFFFFFFFF, loflags, SD_OPSIZE32 | SD_PAGE4KB);
|
||||
loflags = SD_DATA | SD_CD | SD_DPL3 | SD_PRESENT;
|
||||
gdt_set_entry(USER_DS, 0, 0xFFFFFFFF, loflags, SD_OPSIZE32 | SD_PAGE4KB);
|
||||
|
||||
loflags = SD_TSSPRESENT;
|
||||
gdt_set_entry(TSS, 0, sizeof(struct tss_entry_struct), loflags, SD_OPSIZE32);
|
||||
|
||||
load_gdt((unsigned int)&gdtr);
|
||||
}
|
||||
@@ -1,10 +1,77 @@
|
||||
#include "../include/paging.h"
|
||||
#include <stdint.h>
|
||||
#include "../include/multiboot.h"
|
||||
#include "../include/string.h"
|
||||
|
||||
uint32_t kernel_page_directory[1024] __attribute__((aligned(4096)));
|
||||
uint32_t kernel_page_table[1024] __attribute__((aligned(4096)));
|
||||
uint32_t user_page_table[1024] __attribute__((aligned(4096)));
|
||||
|
||||
#define PAGE_OFFSET 0xC0000000
|
||||
#define PAGE_SIZE 4096
|
||||
|
||||
#define PAGE_PRESENT 0x1
|
||||
#define PAGE_RW 0x002 /* Read/Write */
|
||||
#define PAGE_USER 0x004 /* User */
|
||||
#define PAGE_NOALLOC 0x200 /* No Page Allocated (OS managed) */
|
||||
|
||||
#define PAGE_SHIFT 0x0C
|
||||
#define PAGE_MASK ~(PAGE_SIZE - 1) /* 0xFFFFF000 */
|
||||
|
||||
#define GDT_BASE (0xFFFFFFFF - (PAGE_OFFSET - 1))
|
||||
|
||||
#define GET_PGDIR(address) ((unsigned int)((address) >> 22) & 0x3FF)
|
||||
#define GET_PGTBL(address) ((unsigned int)((address) >> 12) & 0x3FF)
|
||||
|
||||
#define PAGE_ALIGN(addr) (((addr) + (PAGE_SIZE - 1)) & PAGE_MASK)
|
||||
|
||||
unsigned int *kpage_dir;
|
||||
|
||||
unsigned int setup_tmp_pgdir(unsigned int magic, unsigned int info)
|
||||
{
|
||||
int n, pd;
|
||||
unsigned int addr, memksize;
|
||||
unsigned int *pgtbl;
|
||||
struct multiboot_info *mbi;
|
||||
|
||||
if(magic != MULTIBOOT_BOOTLOADER_MAGIC) {
|
||||
/* 4MB of memory assumed */
|
||||
memksize = 4096;
|
||||
} else {
|
||||
mbi = (struct multiboot_info *)(PAGE_OFFSET + info);
|
||||
if(!(mbi->flags & MULTIBOOT_INFO_MEMORY)) {
|
||||
/* 4MB of memory assumed */
|
||||
memksize = 4096;
|
||||
} else {
|
||||
/* we need to add the first 1MB to memksize */
|
||||
memksize = (unsigned int)mbi->mem_upper + 1024;
|
||||
/* CONFIG_VM_SPLIT22 marks the maximum physical memory supported */
|
||||
if(memksize > ((0xFFFFFFFF - PAGE_OFFSET) / 1024)) {
|
||||
memksize = (0xFFFFFFFF - PAGE_OFFSET) / 1024;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
addr = PAGE_OFFSET + (memksize * 1024) - memksize;
|
||||
addr = PAGE_ALIGN(addr);
|
||||
|
||||
kpage_dir = (unsigned int *)addr;
|
||||
memset(kpage_dir, 0, PAGE_SIZE);
|
||||
|
||||
addr += PAGE_SIZE;
|
||||
pgtbl = (unsigned int *)addr;
|
||||
memset(pgtbl, 0, memksize);
|
||||
|
||||
for(n = 0; n < memksize / sizeof(unsigned int); n++) {
|
||||
pgtbl[n] = (n << PAGE_SHIFT) | PAGE_PRESENT | PAGE_RW;
|
||||
if(!(n % 1024)) {
|
||||
pd = n / 1024;
|
||||
kpage_dir[pd] = (unsigned int)(addr + (PAGE_SIZE * pd) + GDT_BASE) | PAGE_PRESENT | PAGE_RW;
|
||||
kpage_dir[GET_PGDIR(PAGE_OFFSET) + pd] = (unsigned int)(addr + (PAGE_SIZE * pd) + GDT_BASE) | PAGE_PRESENT | PAGE_RW;
|
||||
}
|
||||
}
|
||||
return (unsigned int)kpage_dir - PAGE_OFFSET;
|
||||
}
|
||||
|
||||
void enablePaging() {
|
||||
asm volatile (
|
||||
|
||||
Reference in New Issue
Block a user