paging done
This commit is contained in:
parent
97aa541b34
commit
07089c2ea1
17 changed files with 247 additions and 253 deletions
|
|
@ -29,3 +29,8 @@ slowly porting from rust.
|
||||||
## interrupts
|
## interrupts
|
||||||
|
|
||||||
`interrupt` -> `idt[n]` -> `isrN` -> `isrDispatch` -> `handlers[n]` (default `unhandled()`)
|
`interrupt` -> `idt[n]` -> `isrN` -> `isrDispatch` -> `handlers[n]` (default `unhandled()`)
|
||||||
|
|
||||||
|
## layout
|
||||||
|
|
||||||
|
`0->4Mib` kernel reserved
|
||||||
|
`1Mib` interrupt stack
|
||||||
|
|
|
||||||
3
qemu.sh
3
qemu.sh
|
|
@ -12,10 +12,11 @@ start() {
|
||||||
-m 1337M \
|
-m 1337M \
|
||||||
-curses \
|
-curses \
|
||||||
-append "Hello" \
|
-append "Hello" \
|
||||||
|
-drive file=disk.img,if=virtio\
|
||||||
-kernel ${KERNEL}
|
-kernel ${KERNEL}
|
||||||
|
# -no-reboot \
|
||||||
# -device virtio-net,netdev=network0 -netdev tap,id=network0,ifname=tap0,script=no,downscript=no \
|
# -device virtio-net,netdev=network0 -netdev tap,id=network0,ifname=tap0,script=no,downscript=no \
|
||||||
# build/kernel.iso
|
# build/kernel.iso
|
||||||
"$@"
|
|
||||||
|
|
||||||
# this allows this switch to monitor with ^a-c, but doesn't
|
# this allows this switch to monitor with ^a-c, but doesn't
|
||||||
# play nice with irqs apparently...
|
# play nice with irqs apparently...
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ __start:
|
||||||
|
|
||||||
push %ebx // Pass multiboot info structure.
|
push %ebx // Pass multiboot info structure.
|
||||||
push %eax // Pass multiboot magic code.
|
push %eax // Pass multiboot magic code.
|
||||||
|
|
||||||
call kmain // Call the kernel.
|
call kmain // Call the kernel.
|
||||||
|
|
||||||
// Halt the CPU.
|
// Halt the CPU.
|
||||||
|
|
|
||||||
|
|
@ -125,9 +125,9 @@ pub fn initialize() void {
|
||||||
loadGDT(&gdtr);
|
loadGDT(&gdtr);
|
||||||
|
|
||||||
// Initialize TSS.
|
// Initialize TSS.
|
||||||
const tss_entry = makeEntry(@ptrToInt(&tss), @sizeOf(TSS) - 1, TSS_ACCESS, PROTECTED);
|
// const tss_entry = makeEntry(@ptrToInt(&tss), @sizeOf(TSS) - 1, TSS_ACCESS, PROTECTED);
|
||||||
gdt[TSS_DESC / @sizeOf(GDTEntry)] = tss_entry;
|
// gdt[TSS_DESC / @sizeOf(GDTEntry)] = tss_entry;
|
||||||
x86.ltr(TSS_DESC);
|
// x86.ltr(TSS_DESC);
|
||||||
|
|
||||||
// tty.stepOK();
|
// tty.stepOK();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
// Kernel stack for interrupt handling.
|
// Kernel stack for interrupt handling.
|
||||||
KERNEL_STACK = 0x800000
|
KERNEL_STACK = 0x10000
|
||||||
// GDT selectors.
|
// GDT selectors.
|
||||||
KERNEL_DS = 0x10
|
KERNEL_DS = 0x10
|
||||||
|
|
||||||
|
|
|
||||||
6
src/arch/x86/layout.zig
Normal file
6
src/arch/x86/layout.zig
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
//https://wiki.osdev.org/Memory_Map_(x86)
|
||||||
|
|
||||||
|
pub const KSTACK = 0x80000; // todo: move to .bss
|
||||||
|
pub const KERNEL = 0x100000;
|
||||||
|
pub const IDENTITY = 0x400000; // 0->4MiB
|
||||||
|
pub const HEAP = 0x800000;
|
||||||
|
|
@ -8,7 +8,7 @@ SECTIONS {
|
||||||
. = 0xb8000;
|
. = 0xb8000;
|
||||||
. += 80 * 25 * 2;
|
. += 80 * 25 * 2;
|
||||||
|
|
||||||
/* lower half kernel */
|
/* lower half kernel <1MiB */
|
||||||
. = 0x10000;
|
. = 0x10000;
|
||||||
|
|
||||||
/* ensure that the multiboot header is at the beginning */
|
/* ensure that the multiboot header is at the beginning */
|
||||||
|
|
@ -37,32 +37,12 @@ SECTIONS {
|
||||||
. = ALIGN(4K);
|
. = ALIGN(4K);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* NOT A GOOD IDEA TO GROUP debug_* SYMBOLS ! */
|
|
||||||
/* .debug : */
|
|
||||||
/* { */
|
|
||||||
/* /1* KEEP(*(.debug_*)) *1/ */
|
|
||||||
/* *(.debug_*) */
|
|
||||||
/* . = ALIGN(4K); */
|
|
||||||
/* } */
|
|
||||||
|
|
||||||
.gdt :
|
.gdt :
|
||||||
{
|
{
|
||||||
*(.gdt)
|
*(.gdt)
|
||||||
. = ALIGN(4K);
|
. = ALIGN(4K);
|
||||||
}
|
}
|
||||||
|
|
||||||
.got :
|
|
||||||
{
|
|
||||||
*(.got)
|
|
||||||
. = ALIGN(4K);
|
|
||||||
}
|
|
||||||
|
|
||||||
.got.plt :
|
|
||||||
{
|
|
||||||
*(.got.plt)
|
|
||||||
. = ALIGN(4K);
|
|
||||||
}
|
|
||||||
|
|
||||||
.bss :
|
.bss :
|
||||||
{
|
{
|
||||||
*(.bss .bss.*)
|
*(.bss .bss.*)
|
||||||
|
|
|
||||||
|
|
@ -12,26 +12,11 @@ const x86 = @import("lib/index.zig");
|
||||||
/// x86 specific intialization
|
/// x86 specific intialization
|
||||||
/// first entry point (see linker.ld)
|
/// first entry point (see linker.ld)
|
||||||
pub fn x86_main(info: *const MultibootInfo) void {
|
pub fn x86_main(info: *const MultibootInfo) void {
|
||||||
// set up the physical frame allocator
|
|
||||||
memory.initialize(info);
|
|
||||||
|
|
||||||
println("{}", memory.allocator.allocate(1));
|
|
||||||
// println("{}", memory.allocator.allocate(1));
|
|
||||||
// println("{}", memory.allocator.allocate(1));
|
|
||||||
// println("{}", memory.allocator.allocate(1));
|
|
||||||
|
|
||||||
// setup memory segmentation
|
|
||||||
gdt.initialize();
|
gdt.initialize();
|
||||||
|
|
||||||
// setup interrupts
|
|
||||||
idt.initialize();
|
idt.initialize();
|
||||||
|
memory.initialize(info);
|
||||||
|
paging.initialize();
|
||||||
|
|
||||||
// enable interrupts
|
// enable interrupts
|
||||||
x86.sti();
|
x86.sti();
|
||||||
|
|
||||||
// set up the virtual page mapper
|
|
||||||
paging.initialize();
|
|
||||||
|
|
||||||
// test breakpoint
|
|
||||||
// x86.int3();
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,124 +1,88 @@
|
||||||
usingnamespace @import("kernel").multiboot;
|
usingnamespace @import("kernel").multiboot;
|
||||||
usingnamespace @import("../../vga.zig");
|
usingnamespace @import("kernel").vga;
|
||||||
const assert = @import("std").debug.assert;
|
const assert = @import("std").debug.assert;
|
||||||
const std = @import("std");
|
|
||||||
|
|
||||||
pub var allocator: bumpAllocator = undefined;
|
var stack: [*]usize = undefined; // Stack of free physical page.
|
||||||
|
var stack_index: usize = 0; // Index into the stack.
|
||||||
|
|
||||||
|
// Boundaries of the frame stack.
|
||||||
|
pub var stack_size: usize = undefined;
|
||||||
|
pub var stack_end: usize = undefined;
|
||||||
|
|
||||||
|
pub const PAGE_SIZE: usize = 4096;
|
||||||
|
// 4095 -> 4096
|
||||||
|
// 4096 -> 4096
|
||||||
|
// 4097 -> 8192
|
||||||
|
pub fn pageAlign(address: u32) u32 {
|
||||||
|
return (address + PAGE_SIZE - 1) & (~PAGE_SIZE +% 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
////
|
||||||
|
// Return the amount of variable elements (in bytes).
|
||||||
|
//
|
||||||
|
pub fn available() usize {
|
||||||
|
return stack_index * PAGE_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
////
|
||||||
|
// Request a free physical page and return its address.
|
||||||
|
//
|
||||||
|
pub fn allocate() ?usize {
|
||||||
|
if (available() == 0) {
|
||||||
|
println("out of memory");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
stack_index -= 1;
|
||||||
|
return stack[stack_index];
|
||||||
|
}
|
||||||
|
|
||||||
|
////
|
||||||
|
// Free a previously allocated physical page.
|
||||||
|
//
|
||||||
|
// Arguments:
|
||||||
|
// address: Address of the page to be freed.
|
||||||
|
//
|
||||||
|
pub fn free(address: usize) void {
|
||||||
|
stack[stack_index] = address;
|
||||||
|
stack_index += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
////
|
||||||
|
// Scan the memory map to index all available memory.
|
||||||
|
//
|
||||||
|
// Arguments:
|
||||||
|
// info: Information structure from bootloader.
|
||||||
|
//
|
||||||
pub fn initialize(info: *const MultibootInfo) void {
|
pub fn initialize(info: *const MultibootInfo) void {
|
||||||
|
// Ensure the bootloader has given us the memory map.
|
||||||
assert((info.flags & MULTIBOOT_INFO_MEMORY) != 0);
|
assert((info.flags & MULTIBOOT_INFO_MEMORY) != 0);
|
||||||
assert((info.flags & MULTIBOOT_INFO_MEM_MAP) != 0);
|
assert((info.flags & MULTIBOOT_INFO_MEM_MAP) != 0);
|
||||||
|
|
||||||
format_multibootinfo(info);
|
// Place the stack of free pages after the last Multiboot module.
|
||||||
allocator = bumpAllocator.new(info);
|
stack = @intToPtr([*]usize, 0x200000);
|
||||||
}
|
// stack = @intToPtr([*]usize, pageAlign(info.mods_addr));
|
||||||
|
// Calculate the approximate size of the stack based on the amount of total upper memory.
|
||||||
fn format_multibootentry(entry: *MultibootMMapEntry) void {
|
stack_size = ((info.mem_upper * 1024) / PAGE_SIZE) * @sizeOf(usize);
|
||||||
if (entry.type == MULTIBOOT_MEMORY_AVAILABLE) {
|
stack_end = pageAlign(@ptrToInt(stack) + stack_size);
|
||||||
print(" AVAILABLE: ");
|
|
||||||
} else {
|
|
||||||
print("NOT AVAILABLE: ");
|
|
||||||
}
|
|
||||||
print("{x} ", entry.addr);
|
|
||||||
if (entry.len / (1024 * 1024) > 0) {
|
|
||||||
println("({} MB)", entry.len / (1024 * 1024));
|
|
||||||
} else {
|
|
||||||
println("({} kB)", entry.len / (1024));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn format_multibootinfo(info: *const MultibootInfo) void {
|
|
||||||
var cmdline_ptr = @intToPtr([*c]const u8, info.cmdline);
|
|
||||||
var cmdline = @ptrCast([*c]const u8, cmdline_ptr);
|
|
||||||
// var cmdline = std.cstr.toSliceConst(info.cmdline);
|
|
||||||
println("flags: {b}", info.flags);
|
|
||||||
println("lower: {x}", info.mem_lower);
|
|
||||||
println("upper: {x}", info.mem_upper);
|
|
||||||
println("mmap_l: {}", info.mmap_length);
|
|
||||||
println("mmap_a: {x}", info.mmap_addr);
|
|
||||||
println("cmdline: {x}", cmdline_ptr);
|
|
||||||
println("cmdline: {}", cmdline);
|
|
||||||
|
|
||||||
var map: usize = info.mmap_addr;
|
var map: usize = info.mmap_addr;
|
||||||
while (map < info.mmap_addr + info.mmap_length) {
|
while (map < info.mmap_addr + info.mmap_length) {
|
||||||
var entry = @intToPtr(*MultibootMMapEntry, map);
|
var entry = @intToPtr(*MultibootMMapEntry, map);
|
||||||
format_multibootentry(entry);
|
|
||||||
|
// Calculate the start and end of this memory area.
|
||||||
|
var start = @truncate(usize, entry.addr);
|
||||||
|
var end = @truncate(usize, start + entry.len);
|
||||||
|
// Anything that comes before the end of the stack of free pages is reserved.
|
||||||
|
start = if (start >= stack_end) start else stack_end;
|
||||||
|
|
||||||
|
// Flag all the pages in this memory area as free.
|
||||||
|
if (entry.type == MULTIBOOT_MEMORY_AVAILABLE) while (start < end) : (start += PAGE_SIZE)
|
||||||
|
free(start);
|
||||||
|
|
||||||
|
// Go to the next entry in the memory map.
|
||||||
map += entry.size + @sizeOf(@typeOf(entry.size));
|
map += entry.size + @sizeOf(@typeOf(entry.size));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
println("available memory: {d} MiB ", available() / 1024 / 1024);
|
||||||
}
|
}
|
||||||
|
|
||||||
// returns each available physical frame one by one in order
|
|
||||||
pub const bumpAllocator = struct {
|
|
||||||
next_free_frame: PhysFrame,
|
|
||||||
current_area: ?*MultibootMMapEntry,
|
|
||||||
info: *const MultibootInfo,
|
|
||||||
|
|
||||||
pub fn new(info: *const MultibootInfo) bumpAllocator {
|
|
||||||
const first_area = @intToPtr(*MultibootMMapEntry, info.mmap_addr);
|
|
||||||
var allocato = bumpAllocator{
|
|
||||||
.current_area = first_area,
|
|
||||||
.next_free_frame = PhysFrame.from_addr(@intCast(u32, first_area.addr)),
|
|
||||||
.info = info,
|
|
||||||
};
|
|
||||||
return allocato;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn allocate(self: var, count: u32) ?PhysFrame {
|
|
||||||
if (count == 0) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
if (self.current_area == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
if (self.current_area.?.type != MULTIBOOT_MEMORY_AVAILABLE) {
|
|
||||||
self.choose_next_area();
|
|
||||||
return self.allocate(count);
|
|
||||||
}
|
|
||||||
// <4MB identity mapped kernel, lazy trick
|
|
||||||
if (PhysFrame.start_addr(self.next_free_frame) < 0x400000) {
|
|
||||||
self.next_free_frame.number += 1;
|
|
||||||
return self.allocate(count);
|
|
||||||
}
|
|
||||||
|
|
||||||
const start_frame = self.next_free_frame;
|
|
||||||
const end_frame = self.next_free_frame.add(count - 1);
|
|
||||||
const current_area_last_frame = PhysFrame.from_addr(@intCast(u32, self.current_area.?.addr + self.current_area.?.len));
|
|
||||||
if (end_frame.number > current_area_last_frame.number) {
|
|
||||||
self.choose_next_area();
|
|
||||||
return self.allocate(count);
|
|
||||||
}
|
|
||||||
self.next_free_frame.number += count;
|
|
||||||
return start_frame;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn choose_next_area(self: var) void {
|
|
||||||
println("choosing next area");
|
|
||||||
const current = self.current_area.?;
|
|
||||||
var next_area = @ptrToInt(current) + current.size + @sizeOf(@typeOf(current));
|
|
||||||
if (next_area >= self.info.mmap_addr + self.info.mmap_length) {
|
|
||||||
self.current_area = null;
|
|
||||||
} else {
|
|
||||||
self.current_area = @intToPtr(*MultibootMMapEntry, next_area);
|
|
||||||
format_multibootentry(self.current_area.?);
|
|
||||||
self.next_free_frame = PhysFrame.from_addr(@intCast(u32, self.current_area.?.addr));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
pub const PAGE_SIZE = 4096;
|
|
||||||
|
|
||||||
pub const PhysFrame = struct {
|
|
||||||
number: u32,
|
|
||||||
|
|
||||||
pub fn from_addr(addr: u32) PhysFrame {
|
|
||||||
return PhysFrame{ .number = @divTrunc(addr, PAGE_SIZE) };
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn add(self: PhysFrame, count: u32) PhysFrame {
|
|
||||||
return PhysFrame{ .number = self.number + count };
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn start_addr(self: PhysFrame) u32 {
|
|
||||||
return (self.number * PAGE_SIZE);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
|
||||||
|
|
@ -11,13 +11,15 @@ setupPaging:
|
||||||
mov +4(%esp), %eax // Fetch the phys_pd parameter.
|
mov +4(%esp), %eax // Fetch the phys_pd parameter.
|
||||||
mov %eax, %cr3 // Point CR3 to the page directory.
|
mov %eax, %cr3 // Point CR3 to the page directory.
|
||||||
|
|
||||||
// Enable Page Size Extension and Page Global.
|
// Enable Page Size Extension
|
||||||
mov %cr4, %eax
|
mov %cr4, %eax
|
||||||
or $0b00010000, %eax
|
or $0x10, %eax
|
||||||
mov %eax, %cr4
|
mov %eax, %cr4
|
||||||
|
|
||||||
// Enable Paging.
|
// Enable Paging.
|
||||||
mov %cr0, %eax
|
mov %cr0, %eax
|
||||||
|
mov $1, %eax
|
||||||
|
or $(1 << 0), %eax
|
||||||
or $(1 << 31), %eax
|
or $(1 << 31), %eax
|
||||||
mov %eax, %cr0
|
mov %eax, %cr0
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,89 +1,102 @@
|
||||||
const x86 = @import("lib/index.zig");
|
const x86 = @import("lib/index.zig");
|
||||||
const allocator = @import("memory.zig").allocator;
|
const memory = @import("memory.zig");
|
||||||
|
const interrupt = @import("interrupt.zig");
|
||||||
const assert = @import("std").debug.assert;
|
const assert = @import("std").debug.assert;
|
||||||
const println = @import("../../vga.zig").println;
|
const println = @import("../../vga.zig").println;
|
||||||
|
|
||||||
extern fn setupPaging(phys_pd: usize) void;
|
extern fn setupPaging(phys_pd: usize) void;
|
||||||
|
|
||||||
pub var mapper: Mapper = undefined;
|
const PageEntry = usize;
|
||||||
pub const PAGE_SIZE = 4096;
|
pub const PAGE_SIZE = 4096;
|
||||||
|
pub const PT = @intToPtr([*]PageEntry, 0xFFC00000);
|
||||||
|
pub const PD = @intToPtr([*]PageEntry, 0xFFFFF000);
|
||||||
|
const PRESENT = 0x1;
|
||||||
|
const WRITE = 0x2;
|
||||||
|
const USER = 0x4;
|
||||||
|
const WRITE_THRU = 0x8;
|
||||||
|
const NOCACHE = 0x10;
|
||||||
|
const ACCESSED = 0x20;
|
||||||
|
const HUGE = 0x80;
|
||||||
|
|
||||||
|
pub var pageDirectory: [1024]PageEntry align(4096) linksection(".bss") = [_]PageEntry{0} ** 1024;
|
||||||
|
|
||||||
|
fn pageFault() void {
|
||||||
|
println("pagefault");
|
||||||
|
while (true) {
|
||||||
|
asm volatile ("hlt");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn pageBase(addr: usize) usize {
|
||||||
|
return addr & (~PAGE_SIZE +% 1);
|
||||||
|
}
|
||||||
|
fn pde(addr: usize) *PageEntry {
|
||||||
|
return &PD[addr >> 22];
|
||||||
|
}
|
||||||
|
fn pte(addr: usize) *PageEntry {
|
||||||
|
return &PT[addr >> 12];
|
||||||
|
}
|
||||||
|
|
||||||
|
// virtual to physical
|
||||||
|
pub fn translate(virt: usize) ?usize {
|
||||||
|
if (pde(virt).* == 0) return null;
|
||||||
|
return pageBase(pte(virt).*);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn unmap(virt: usize) void {
|
||||||
|
var pte = pte(virt);
|
||||||
|
if (pte.* == 0) {
|
||||||
|
println("can't unmap 0x{x}, map is empty.", addr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
pte.* = 0;
|
||||||
|
memory.free(translate(virt));
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn mmap(virt: usize, phys: ?usize) void {
|
||||||
|
var pde: *PageEntry = &PD[virt >> 22];
|
||||||
|
if (pde.* == 0) {
|
||||||
|
pde.* = memory.allocate() | WRITE | PRESENT;
|
||||||
|
}
|
||||||
|
var pte: *PageEntry = &PT[virt >> 12];
|
||||||
|
pte.* = if (phys) |p| p else allocate() | PRESENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn addrspace() void {
|
||||||
|
var i: usize = 1;
|
||||||
|
i = 0;
|
||||||
|
while (i < 1024) : (i += 1) {
|
||||||
|
if (PD[i] == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
println("p2[{}] -> 0x{x}", i, PD[i]);
|
||||||
|
if (PD[i] & HUGE != 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
var j: usize = 0;
|
||||||
|
while (j < 1024) : (j += 1) {
|
||||||
|
var entry: PageEntry = PT[i * 1024 + j];
|
||||||
|
if (entry != 0) {
|
||||||
|
println("p2[{}]p1[{}] -> 0x{x}", i, j, entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn initialize() void {
|
pub fn initialize() void {
|
||||||
const empty_page = PageDirectoryEntry{};
|
var p2 = pageDirectory[0..];
|
||||||
// var p2 = allocator.allocate(1);
|
|
||||||
var p2 = [_]PageDirectoryEntry{empty_page} ** 1024;
|
|
||||||
// var p2 = [_]u32{0} ** 1024;
|
|
||||||
|
|
||||||
// identity map 0 -> 4MB
|
// identity map 0 -> 4MB
|
||||||
p2[0].pageTable = 0x0;
|
|
||||||
p2[0].present = true;
|
|
||||||
p2[0].read_write = true;
|
|
||||||
p2[0].huge = true;
|
|
||||||
// p2[0] = @bitReverse(u32, 0b10000011);
|
|
||||||
|
|
||||||
println("p2[0] {b}", p2[0]);
|
p2[0] = 0x000000 | PRESENT | WRITE | HUGE;
|
||||||
println("p2[0] {b}", @bitCast(u32, p2[0]));
|
p2[1023] = @ptrToInt(&p2[0]) | PRESENT | WRITE;
|
||||||
// x86.hang();
|
|
||||||
// paging.s
|
|
||||||
// setupPaging(@ptrToInt(&p2));
|
|
||||||
|
|
||||||
// mapper = Mapper{
|
assert(memory.stack_end < 0x400000);
|
||||||
// .p2 = p2,
|
// const first: *u32 = @ptrCast(*u32, p2);
|
||||||
// };
|
// println("p2[0] {b}", first.*);
|
||||||
const addr = mapper.translate(0xfffff000);
|
|
||||||
}
|
interrupt.register(14, pageFault);
|
||||||
|
setupPaging(@ptrToInt(&pageDirectory[0]));
|
||||||
const builtin = @import("builtin");
|
|
||||||
const Mapper = struct {
|
addrspace();
|
||||||
p2: PageDirectory,
|
// const addr = mapper.translate(0xfffff000);
|
||||||
|
|
||||||
// virt to phys
|
|
||||||
pub fn translate(self: Mapper, virt: u32) ?u32 {
|
|
||||||
const map = @bitCast(VirtAddr, virt);
|
|
||||||
println("{}", builtin.endian);
|
|
||||||
println("virt {x} -> {}-{}-{x}", virt, map.page_directory, map.page_table, map.offset);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
pub const VirtAddr = packed struct {
|
|
||||||
page_directory: u10,
|
|
||||||
page_table: u10,
|
|
||||||
offset: u12,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub const PageDirectoryEntry = packed struct {
|
|
||||||
pageTable: u20 = 0,
|
|
||||||
available: u3 = 0,
|
|
||||||
ignored: bool = false,
|
|
||||||
huge: bool = false,
|
|
||||||
zero: bool = false,
|
|
||||||
accessed: bool = false,
|
|
||||||
cache_disabled: bool = false,
|
|
||||||
write_thru: bool = false,
|
|
||||||
supervisor: bool = false,
|
|
||||||
read_write: bool = false,
|
|
||||||
present: bool = false,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub const PageTableEntry = packed struct {
|
|
||||||
addr: u20 = 0,
|
|
||||||
available: u3 = 0,
|
|
||||||
global: bool = false,
|
|
||||||
zero: bool = false,
|
|
||||||
dirty: bool = false,
|
|
||||||
accessed: bool = false,
|
|
||||||
cache_disabled: bool = false,
|
|
||||||
write_thru: bool = false,
|
|
||||||
supervisor: bool = false,
|
|
||||||
read_write: bool = false,
|
|
||||||
present: bool = false,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub const PageTable = [1024]PageTableEntry;
|
|
||||||
pub const PageDirectory = [1024]PageDirectoryEntry;
|
|
||||||
|
|
||||||
comptime {
|
|
||||||
assert(@sizeOf(PageDirectoryEntry) == 4); //32 bits
|
|
||||||
assert(@sizeOf(PageTableEntry) == 4); //32 bits
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,6 @@ pub fn keypress(char: u8) void {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn initialize() void {
|
pub fn initialize() void {
|
||||||
// vga.clear();
|
|
||||||
interrupt.registerIRQ(1, ps2.keyboard_handler);
|
interrupt.registerIRQ(1, ps2.keyboard_handler);
|
||||||
vga.writeString("> ");
|
vga.writeString("> ");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,9 +8,11 @@ const assert = @import("std").debug.assert;
|
||||||
|
|
||||||
// arch independant initialization
|
// arch independant initialization
|
||||||
export fn kmain(magic: u32, info: *const MultibootInfo) noreturn {
|
export fn kmain(magic: u32, info: *const MultibootInfo) noreturn {
|
||||||
|
clear();
|
||||||
assert(magic == MULTIBOOT_BOOTLOADER_MAGIC);
|
assert(magic == MULTIBOOT_BOOTLOADER_MAGIC);
|
||||||
|
|
||||||
println("--- x86 initialization ---");
|
println("--- x86 initialization ---");
|
||||||
|
|
||||||
x86.x86_main(info);
|
x86.x86_main(info);
|
||||||
|
|
||||||
// pagefault_test(0xfeffc000);
|
// pagefault_test(0xfeffc000);
|
||||||
|
|
|
||||||
8
src/memory.zig
Normal file
8
src/memory.zig
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
const paging = @import("arch/x86/paging.zig");
|
||||||
|
|
||||||
|
pub fn alloc(size: usize) usize {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn free() {
|
||||||
|
}
|
||||||
|
|
@ -81,8 +81,12 @@ pub const MultibootInfo = packed struct {
|
||||||
// Return the ending address of the last module.
|
// Return the ending address of the last module.
|
||||||
//
|
//
|
||||||
pub fn lastModuleEnd(self: *const MultibootInfo) usize {
|
pub fn lastModuleEnd(self: *const MultibootInfo) usize {
|
||||||
|
if (self.mods_count > 0) {
|
||||||
const mods = @intToPtr([*]MultibootModule, self.mods_addr);
|
const mods = @intToPtr([*]MultibootModule, self.mods_addr);
|
||||||
return mods[self.mods_count - 1].mod_end;
|
return mods[self.mods_count - 1].mod_end;
|
||||||
|
} else {
|
||||||
|
return self.mods_addr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
////
|
////
|
||||||
|
|
|
||||||
61
src/pci.zig
61
src/pci.zig
|
|
@ -17,31 +17,28 @@ pub const PciDevice = struct {
|
||||||
bus: u8,
|
bus: u8,
|
||||||
slot: u5,
|
slot: u5,
|
||||||
function: u3,
|
function: u3,
|
||||||
device: u16,
|
device: u16 = undefined,
|
||||||
vendor: u16,
|
vendor: u16 = undefined,
|
||||||
class: u8,
|
class: u8 = undefined,
|
||||||
subclass: u8,
|
subclass: u8 = undefined,
|
||||||
header_type: u8,
|
header_type: u8 = undefined,
|
||||||
|
driver: ?Driver = null,
|
||||||
|
|
||||||
pub fn init(bus: u8, slot: u5, function: u3) ?PciDevice {
|
pub fn init(bus: u8, slot: u5, function: u3) ?PciDevice {
|
||||||
var pcidevice = PciDevice{
|
var dev = PciDevice{
|
||||||
.bus = bus,
|
.bus = bus,
|
||||||
.slot = slot,
|
.slot = slot,
|
||||||
.function = function,
|
.function = function,
|
||||||
.device = undefined,
|
|
||||||
.class = undefined,
|
|
||||||
.subclass = undefined,
|
|
||||||
.header_type = undefined,
|
|
||||||
.vendor = undefined,
|
|
||||||
};
|
};
|
||||||
pcidevice.vendor = pci_config_read_word(pcidevice, 0);
|
dev.vendor = dev.pci_config_read_word(0);
|
||||||
if (pcidevice.vendor == 0xffff)
|
if (dev.vendor == 0xffff)
|
||||||
return null;
|
return null;
|
||||||
pcidevice.device = pci_config_read_word(pcidevice, 2);
|
dev.device = dev.pci_config_read_word(2);
|
||||||
pcidevice.subclass = pci_config_read_byte(pcidevice, 10);
|
dev.subclass = dev.pci_config_read_byte(10);
|
||||||
pcidevice.class = pci_config_read_byte(pcidevice, 11);
|
dev.class = dev.pci_config_read_byte(11);
|
||||||
pcidevice.header_type = pci_config_read_byte(pcidevice, 14);
|
dev.header_type = dev.pci_config_read_byte(14);
|
||||||
return (pcidevice);
|
dev.driver = dev.get_driver();
|
||||||
|
return (dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn address(self: PciDevice, offset: u8) u32 {
|
pub fn address(self: PciDevice, offset: u8) u32 {
|
||||||
|
|
@ -57,7 +54,11 @@ pub const PciDevice = struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn format(self: PciDevice) void {
|
pub fn format(self: PciDevice) void {
|
||||||
println("{}:{}.{} {x},{x}: {x} {x}", self.bus, self.slot, self.function, self.class, self.subclass, self.vendor, self.device);
|
print("{}:{}.{}", self.bus, self.slot, self.function);
|
||||||
|
print(" {x},{x}: {x} {x}", self.class, self.subclass, self.vendor, self.device);
|
||||||
|
if (self.driver) |d|
|
||||||
|
print(" {}", d.name);
|
||||||
|
println("");
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn access(self: PciDevice, offset: u8) void {
|
pub fn access(self: PciDevice, offset: u8) void {
|
||||||
|
|
@ -78,13 +79,33 @@ pub const PciDevice = struct {
|
||||||
self.access(offset);
|
self.access(offset);
|
||||||
return (arch.inl(PCI_CONFIG_DATA));
|
return (arch.inl(PCI_CONFIG_DATA));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_driver(self: PciDevice) ?Driver {
|
||||||
|
var i: usize = 0;
|
||||||
|
while (i < Drivers.len) : (i += 1) {
|
||||||
|
var driver = Drivers[i];
|
||||||
|
if (self.class == driver.class and self.subclass == driver.subclass and (driver.vendor == null or self.vendor == driver.vendor.?)) {
|
||||||
|
return driver;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const Driver = struct {
|
||||||
|
name: [*]u8,
|
||||||
|
class: u8,
|
||||||
|
subclass: u8,
|
||||||
|
vendor: ?u16 = null,
|
||||||
|
};
|
||||||
|
|
||||||
|
const name = "virtio-blk";
|
||||||
|
pub var Drivers: [1]Driver = [_]Driver{Driver{ .name = &name, .class = 0x1, .subclass = 0x0, .vendor = 0x1af4 }};
|
||||||
|
|
||||||
pub fn lspci() void {
|
pub fn lspci() void {
|
||||||
var slot: u5 = 0;
|
var slot: u5 = 0;
|
||||||
while (true) {
|
while (true) {
|
||||||
if (PciDevice.init(0, slot, 0)) |device| {
|
if (PciDevice.init(0, slot, 0)) |device| {
|
||||||
device.format();
|
|
||||||
var function: u3 = 0;
|
var function: u3 = 0;
|
||||||
while (true) {
|
while (true) {
|
||||||
if (PciDevice.init(0, slot, function)) |vf|
|
if (PciDevice.init(0, slot, function)) |vf|
|
||||||
|
|
|
||||||
|
|
@ -63,6 +63,9 @@ pub fn print(comptime format: []const u8, args: ...) void {
|
||||||
pub fn println(comptime format: []const u8, args: ...) void {
|
pub fn println(comptime format: []const u8, args: ...) void {
|
||||||
var a = std.fmt.format({}, Errors, printCallback, format ++ "\n", args);
|
var a = std.fmt.format({}, Errors, printCallback, format ++ "\n", args);
|
||||||
}
|
}
|
||||||
|
pub fn clear() void {
|
||||||
|
vga.clear();
|
||||||
|
}
|
||||||
|
|
||||||
fn printCallback(context: void, string: []const u8) Errors!void {
|
fn printCallback(context: void, string: []const u8) Errors!void {
|
||||||
vga.writeString(string);
|
vga.writeString(string);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue