Revision: e57baf916576 Author: Niek Linnenbank <nieklinnenbank@xxxxxxxxx> Date: Wed Jan 21 18:25:37 2015 UTCLog: Updated Scons build scripts for kernel and boot image. Move boot/ to kernel.
https://code.google.com/p/freenos/source/detail?r=e57baf916576 Added: /kernel/x86/pc/Kernel.cpp /kernel/x86/pc/Memory.cpp /kernel/x86/pc/Process.cpp /kernel/x86/pc/SConscript /kernel/x86/pc/boot.S /kernel/x86/pc/boot.imgdesc /kernel/x86/pc/boot.isodesc /kernel/x86/pc/cd.img /kernel/x86/pc/contextSwitch.S /kernel/x86/pc/grub.cfg Deleted: /boot/boot.imgdesc /boot/boot.isodesc /boot/grub/menu.lst /boot/grub/stage1 /boot/grub/stage2_eltorito /kernel/SConscript /kernel/X86/Kernel.cpp /kernel/X86/Memory.cpp /kernel/X86/Process.cpp /kernel/X86/boot.S /kernel/X86/contextSwitch.S Modified: /SConstruct /bin/img/Main.cpp /site_scons/bootimage.py /site_scons/build.py /site_scons/iso.py /site_scons/version.py ======================================= --- /dev/null +++ /kernel/x86/pc/Kernel.cpp Wed Jan 21 18:25:37 2015 UTC @@ -0,0 +1,194 @@ +/* + * Copyright (C) 2009 Niek Linnenbank + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <FreeNOS/Kernel.h> +#include <FreeNOS/CPU.h> +#include <FreeNOS/API.h> +#include <FreeNOS/Init.h> +#include <FreeNOS/Interrupt.h> +#include <FreeNOS/Scheduler.h> +#include <Macros.h> +#include <List.h> +#include <ListIterator.h> +#include <Array.h> + +/** Interrupt handlers. */ +Array<List<InterruptHook> > interrupts(256); + +/** API handlers. */ +Array<APIHandler> apis(16); + +void executeInterrupt(CPUState state) +{ + /* Fetch the list of interrupt hooks (for this vector). */ + List<InterruptHook> *lst = interrupts[state.vector]; + + /* Does at least one handler exist? */ + if (!lst) return; + + /* Execute them all. */ + for (ListIterator<InterruptHook> i(lst); i.hasNext(); i.next()) + { + i.current()->handler(&state, i.current()->param); + } +} + +X86Kernel::X86Kernel() : ticks(0) +{ + /* ICW1: Initialize PIC's (Edge triggered, Cascade) */ + outb(PIC1_CMD, 0x11); + outb(PIC2_CMD, 0x11); + + /* ICW2: Remap IRQ's to interrupts 32-47. */ + outb(PIC1_DATA, PIC_IRQ_BASE); + outb(PIC2_DATA, PIC_IRQ_BASE + 8); + + /* ICW3: PIC2 is connected to PIC1 via IRQ2. */ + outb(PIC1_DATA, 0x04); + outb(PIC2_DATA, 0x02); + + /* ICW4: 8086 mode, fully nested, not buffered, no implicit EOI. */ + outb(PIC1_DATA, 0x01); + outb(PIC2_DATA, 0x01); + + /* OCW1: Disable all IRQ's for now. */ + outb(PIC1_DATA, 0xff); + outb(PIC2_DATA, 0xff); + + /* Let the i8253 timer run continuously (square wave). */ + outb(PIT_CMD, 0x36); + outb(PIT_CHAN0, PIT_DIVISOR & 0xff); + outb(PIT_CHAN0, PIT_DIVISOR >> 8); + + /* Make sure to enable PIC2 and the i8253. */ + enableIRQ(2, true); + enableIRQ(0, true); + + /* Setup exception handlers. */ + for (int i = 0; i < 17; i++) + { + hookInterrupt(i, exception, 0); + } + /* Setup IRQ handlers. */ + for (int i = 17; i < 256; i++) + { + /* Trap gate. */ + if (i == 0x90) + hookInterrupt(0x90, trap, 0); + + /* Hardware Interrupt. */ + else + hookInterrupt(i, interrupt, 0); + } + /* Install PIT (i8253) IRQ handler. */ + hookInterrupt(IRQ(0), clocktick, 0); + + /* Initialize TSS Segment. */ + gdt[USER_TSS].limitLow = sizeof(TSS) + (0xfff / 8); + gdt[USER_TSS].baseLow = ((Address) &kernelTss) & 0xffff; + gdt[USER_TSS].baseMid = (((Address) &kernelTss) >> 16) & 0xff; + gdt[USER_TSS].type = 9; + gdt[USER_TSS].privilege = 0; + gdt[USER_TSS].present = 1; + gdt[USER_TSS].limitHigh = 0; + gdt[USER_TSS].granularity = 8; + gdt[USER_TSS].baseHigh = (((Address) &kernelTss) >> 24) & 0xff; + + /* Let TSS point to I/O bitmap page. */ + kernelTss.bitmap = PAGESIZE << 16; + + /* Load Task State Register. */ + ltr(USER_TSS_SEL); +} + +void X86Kernel::hookInterrupt(int vec, InterruptHandler h, ulong p) +{ + InterruptHook hook(h, p); + + /* Insert into interrupts; create List if neccessary. */ + if (!interrupts[vec]) + { + interrupts.insert(vec, new List<InterruptHook>()); + } + /* Just append it. */ + if (!interrupts[vec]->contains(&hook)) + { + interrupts[vec]->insertTail(new InterruptHook(h, p)); + } +} + +void X86Kernel::enableIRQ(uint irq, bool enabled) +{ + if (enabled) + { + if (irq < 8) + outb(PIC1_DATA, inb(PIC1_DATA) & ~(1 << irq)); + else + outb(PIC2_DATA, inb(PIC2_DATA) & ~(1 << (irq - 8))); + } + else + { + if (irq < 8) + outb(PIC1_DATA, inb(PIC1_DATA) | (1 << irq)); + else + outb(PIC2_DATA, inb(PIC2_DATA) | (1 << (irq - 8))); + } +} + +void X86Kernel::exception(CPUState *state, ulong param) +{ + assert(scheduler->current() != ZERO); + delete scheduler->current(); + scheduler->executeNext(); +} + +void X86Kernel::interrupt(CPUState *state, ulong param) +{ + /* End of Interrupt to slave. */ + if (IRQ(state->vector) >= 8) + { + outb(PIC2_CMD, PIC_EOI); + } + /* End of Interrupt to master. */ + outb(PIC1_CMD, PIC_EOI); +} + +void X86Kernel::trap(CPUState *state, ulong param) +{ + APIHandler *h = apis[state->eax]; + + if (h) + { + state->eax = h(state->ecx, state->ebx, state->edx, + state->esi, state->edi); + } +} + +void X86Kernel::clocktick(CPUState *state, ulong param) +{ + /* Quantum reached? */ + if ((++kernel->ticks % 2) == 0) + { + /* Reset. */ + kernel->ticks = 0; + + /* Reschedule. */ + scheduler->executeNext(); + } +} + +INITOBJ(X86Kernel, kernel, KERNEL) ======================================= --- /dev/null +++ /kernel/x86/pc/Memory.cpp Wed Jan 21 18:25:37 2015 UTC @@ -0,0 +1,193 @@ +/* + * Copyright (C) 2009 Niek Linnenbank + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <FreeNOS/Memory.h> +#include <FreeNOS/Init.h> +#include <FreeNOS/Process.h> +#include <Types.h> +#include <string.h> + +X86Memory::X86Memory() : Memory(), remPageDir(PAGEDIRADDR_REMOTE), + remPageTab(ZERO), myPageDir(PAGEDIRADDR), + myPageTab(ZERO) +{ +} + +Address X86Memory::mapVirtual(Address paddr, Address vaddr, ulong prot) +{ + /* Virtual address specified? */ + if (vaddr == ZERO) + { + vaddr = findFree(PAGETABFROM, PAGEDIRADDR); + } + /* Point to the correct page table. */ + myPageTab = PAGETABADDR(vaddr); + + /* Do we have the page table in memory? */ + if (!(myPageDir[DIRENTRY(vaddr)] & PAGE_PRESENT)) + { + /* Then first allocate new page table. */ + Address newPageTab = memory->allocatePhysical(PAGESIZE); + newPageTab |= PAGE_PRESENT | PAGE_RW | prot; + + /* Map the new page table into memory. */ + myPageDir[DIRENTRY(vaddr)] = newPageTab; + tlb_flush(myPageTab); + + /* Zero the new page table. */ + memset(myPageTab, 0, PAGESIZE); + } + /* Map physical to virtual address. */ + myPageTab[TABENTRY(vaddr)] = (paddr & PAGEMASK) | prot; + tlb_flush(vaddr); + + /* Success. */ + return vaddr; +} + +Address X86Memory::mapVirtual(X86Process *p, Address paddr, + Address vaddr, ulong prot) +{ + /* Map remote pages. */ + mapRemote(p, vaddr); + + /* Virtual address specified? */ + if (vaddr == ZERO) + { + vaddr = findFree(PAGETABFROM_REMOTE, remPageDir); + } + /* Repoint to the correct (remote) page table. */ + remPageTab = PAGETABADDR_FROM(vaddr, PAGETABFROM_REMOTE); + + /* Does the remote process have the page table in memory? */ + if (!(remPageDir[DIRENTRY(vaddr)] & PAGE_PRESENT)) + { + /* Nope, allocate a page table first. */ + Address newPageTab = memory->allocatePhysical(PAGESIZE); + newPageTab |= PAGE_PRESENT | PAGE_RW | prot; + + /* Map the new page table into remote memory. */ + remPageDir[DIRENTRY(vaddr)] = newPageTab; + + /* Update caches. */ + tlb_flush(remPageTab); + + /* Zero the new page. */ + memset(remPageTab, 0, PAGESIZE); + } + /* Map physical address to remote virtual address. */ + remPageTab[TABENTRY(vaddr)] = (paddr & PAGEMASK) | prot; + tlb_flush(vaddr); + + /* Success. */ + return (Address) vaddr; +} + +Address X86Memory::findFree(Address pageTabFrom, Address *pageDirPtr) +{ + Address vaddr = 0xa0000000; + Address *pageTabPtr = PAGETABADDR_FROM(vaddr, pageTabFrom); + + /* Find a free virtual address. */ + while (pageDirPtr[DIRENTRY(vaddr)] & PAGE_PRESENT && + pageTabPtr[TABENTRY(vaddr)] & PAGE_PRESENT) + { + /* Look for the next page in line. */ + vaddr += PAGESIZE; + pageTabPtr = PAGETABADDR_FROM(vaddr, pageTabFrom); + } + return vaddr; +} + +Address X86Memory::lookupVirtual(X86Process *p, Address vaddr) +{ + Address ret = ZERO; + + /* Map remote page tables. */ + mapRemote(p, vaddr); + + /* Lookup the address, if mapped. */ + if (remPageDir[DIRENTRY(vaddr)] & PAGE_PRESENT && + remPageTab[TABENTRY(vaddr)] & PAGE_PRESENT) + { + ret = remPageTab[TABENTRY(vaddr)]; + } + return ret; +} + +void X86Memory::mapRemote(X86Process *p, Address pageTabAddr, + Address pageDirAddr, ulong prot) +{ + /* Map remote page directory and page table. */ + myPageDir[DIRENTRY(pageDirAddr)] = + p->getPageDirectory() | (PAGE_PRESENT|PAGE_RW|PAGE_PINNED|prot); + remPageTab = PAGETABADDR_FROM(pageTabAddr, PAGETABFROM_REMOTE); + + /* Refresh entire TLB cache. */ + tlb_flush_all(); +} + +bool X86Memory::access(X86Process *p, Address vaddr, Size sz, ulong prot) +{ + Size bytes = 0; + Address vfrom = vaddr; + + /* Map remote pages. */ + mapRemote(p, vaddr); + + /* Verify protection bits. */ + while (bytes < sz && + remPageDir[DIRENTRY(vaddr)] & prot && + remPageTab[TABENTRY(vaddr)] & prot) + { + vaddr += PAGESIZE; + bytes += ((vfrom & PAGEMASK) + PAGESIZE) - vfrom; + vfrom = vaddr & PAGEMASK; + remPageTab = PAGETABADDR_FROM(vaddr, PAGETABFROM_REMOTE); + } + /* Do we have a match? */ + return (bytes >= sz); +} + +void X86Memory::releaseAll(X86Process *p) +{ + /* Map page tables. */ + mapRemote(p, 0x0); + + /* Mark all our physical pages free. */ + for (Size i = 0; i < 1024; i++) + { + /* May we release these physical pages? */+ if ((remPageDir[i] & PAGE_PRESENT) && !(remPageDir[i] & PAGE_PINNED))
+ { + /* Repoint page table. */ + remPageTab = PAGETABADDR_FROM(i * PAGESIZE * 1024, + PAGETABFROM_REMOTE); + + /* Scan page table. */ + for (Size j = 0; j < 1024; j++) + {+ if (remPageTab[j] & PAGE_PRESENT && !(remPageTab[j] & PAGE_PINNED))
+ { + memory->releasePhysical(remPageTab[j]); + } + } + } + } +} + +INITOBJ(X86Memory, memory, VMEMORY) ======================================= --- /dev/null +++ /kernel/x86/pc/Process.cpp Wed Jan 21 18:25:37 2015 UTC @@ -0,0 +1,117 @@ +/* + * Copyright (C) 2009 Niek Linnenbank + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <FreeNOS/Process.h> +#include <FreeNOS/Memory.h> +#include <FreeNOS/CPU.h> +#include <FreeNOS/Scheduler.h> +#include <Types.h> +#include <string.h> +#include <ListIterator.h> + +X86Process::X86Process(Address entry) : Process(entry) +{ + Address *pageDir, *tmpStack, *ioMap; + CPUState *regs; + + /* Allocate page directory. */ + pageDirAddr = memory->allocatePhysical(PAGESIZE); + pageDir = (Address *) memory->mapVirtual(pageDirAddr); + + /* One page for the I/O bitmap. */ + ioMapAddr = memory->allocatePhysical(PAGESIZE); + ioMap = (Address *) memory->mapVirtual(ioMapAddr); + + /* Clear them first. */ + memset(pageDir, 0, PAGESIZE); + memset(ioMap, 0xff, PAGESIZE); + + /* Setup mappings. */ + pageDir[0] = kernelPageDir[0]; + pageDir[DIRENTRY(PAGETABFROM) ] = pageDirAddr | PAGE_PRESENT | PAGE_RW; + pageDir[DIRENTRY(PAGEUSERFROM)] = pageDirAddr | PAGE_PRESENT | PAGE_RW; + + /* Point stacks. */ + stackAddr = 0xc0000000 - MEMALIGN; + kernelStackAddr = 0xd0000000 - MEMALIGN; + + /* Allocate stacks. */ + for (int i = 0; i < 4; i++) + { + memory->allocateVirtual(this, stackAddr - (i * PAGESIZE), + PAGE_PRESENT | PAGE_USER | PAGE_RW); + memory->allocateVirtual(this, kernelStackAddr - (i * PAGESIZE), + PAGE_PRESENT | PAGE_RW); + } + /* Map kernel stack. */ + tmpStack = (Address *) memory->mapVirtual( + memory->lookupVirtual(this, kernelStackAddr) & PAGEMASK); + + /* Setup initial registers. */ + regs = (CPUState *) (((u32)tmpStack) + PAGESIZE - sizeof(CPUState)); + memset(regs, 0, sizeof(CPUState)); + regs->ss0 = KERNEL_DS_SEL; + regs->fs = USER_DS_SEL; + regs->gs = USER_DS_SEL; + regs->es = USER_DS_SEL; + regs->ds = USER_DS_SEL; + regs->ebp = stackAddr; + regs->esp0 = kernelStackAddr; + regs->eip = entry; + regs->cs = USER_CS_SEL; + regs->eflags = 0x202; + regs->esp3 = stackAddr; + regs->ss3 = USER_DS_SEL; + + /* Repoint our stack. */ + stackAddr = kernelStackAddr - sizeof(CPUState) + MEMALIGN; + + /* Release temporary mappings. */ + memory->mapVirtual((Address) 0, (Address) pageDir, 0); + memory->mapVirtual((Address) 0, (Address) tmpStack, 0); + memory->mapVirtual((Address) 0, (Address) ioMap, 0); +} + +X86Process::~X86Process() +{ + /* Remove ourselves from the scheduler. */ + scheduler->dequeue(this); + + /* Mark all our pages free. */ + memory->releaseAll(this); +} + +void X86Process::IOPort(u16 port, bool enabled) +{ + Address tmp = memory->mapVirtual(ioMapAddr); + kernelTss.setPort(port, enabled, (u8 *) tmp); + memory->mapVirtual((Address) 0, tmp, 0); +} + +void X86Process::execute() +{ + /* Refresh I/O bitmap. */ + memory->mapVirtual(ioMapAddr, (Address) &kernelioBitMap); + + /* Perform a context switch. */ + contextSwitch( scheduler->old() ? &scheduler->old()->stackAddr + : ZERO, + pageDirAddr, + stackAddr, + &kernelTss, + kernelStackAddr); +} ======================================= --- /dev/null +++ /kernel/x86/pc/SConscript Wed Jan 21 18:25:37 2015 UTC @@ -0,0 +1,48 @@ +# +# Copyright (C) 2015 Niek Linnenbank +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# + +Import('build_env') + +env = build_env.Clone() + +for item in env['LINKUSER']: + env['LINKFLAGS'].remove(item) +env.Append(LINKFLAGS = env['LINKKERN']) + +env.UseLibraries([ 'libposix', 'libc', 'liballoc', 'libexec' ]) +env.UseServers(['process', 'filesystem', 'memory']) +env.TargetProgram('kernel', [ Glob('*.cpp'), + Glob('*.S'), + Glob('#' + env['BUILDROOT'] + '/kernel/*.cpp'), + Glob('#' + env['BUILDROOT'] + '/kernel/API/*.cpp') ]) + +# +# Boot Image +# +env.BootImage('#${BUILDROOT}/boot.img', '#${BUILDROOT}/kernel/x86/pc/boot.imgdesc') + +# +# Make a bootable LiveCD. +# +cd = env.ISO('#${BUILDROOT}/boot.iso', + [ '#kernel/x86/pc/cd.img', + '#kernel/x86/pc/grub.cfg', + '#${BUILDROOT}/kernel/x86/pc/kernel', + '#${BUILDROOT}/boot.img' ]) + +# Shortcut to build the ISO. +Alias('iso', cd) ======================================= --- /dev/null +++ /kernel/x86/pc/boot.S Wed Jan 21 18:25:37 2015 UTC @@ -0,0 +1,323 @@ +/* + * Copyright (C) 2009 Niek Linnenbank + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <FreeNOS/Multiboot.h> +#include <FreeNOS/CPU.h> +#include <FreeNOS/Memory.h> + +/* The size of our stack (16KB). */ +#define STACK_SIZE 0x4000 + +/** + * Generates interrupt handlers. + */ +.macro interruptHandler vnum, verr +i\vnum: +.if !\verr + pushl $0 +.endif + pushl $\vnum + jmp invokeHandler +.endm + +/** + * Fills in IDT entries. + */ +.macro idtEntry vnum, vtype + mov $8, %eax + mov $\vnum, %ebx + imul %ebx + add $idt, %eax + mov $i\vnum, %ebx + movw %bx, (%eax) /* Offset low */ + shrl $16, %ebx + movw %bx, 6(%eax) /* Offset high */ + movw $KERNEL_CS_SEL, 2(%eax) /* Kernel CS */ + movb $0, 4(%eax) /* Zeroes */ + movb $\vtype, 5(%eax) /* Present, 32 bits, 01110 */ +.endm ++.global _start, multibootHeader, multibootInfo, gdt, kernelPageDir, kernelPageTab, kernelTss, kernelioBitMap
+ +.section ".text" + +/** + * Entry point. + */ +_start: + jmp _jump_entry + +/* + * Multiboot header, 32-bit aligned. + */ +.align 4 + +multibootHeader: + .long (MULTIBOOT_HEADER_MAGIC) + .long (MULTIBOOT_HEADER_FLAGS) + .long -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS) + .long (multibootHeader) + +_jump_entry: + /* Disable interrupts. */ + cli + + /* Setup temporary boot stack. */ + movl $(stack + STACK_SIZE), %esp + movl %esp, %ebp + + /* Multiboot magic + struct. */ + cmpl $MULTIBOOT_BOOTLOADER_MAGIC, %eax + jnz halt + movl $multibootInfo, %eax + movl $MULTIBOOT_HEADER_SIZE, %ecx +1: + movl (%ebx), %edx + movl %edx, (%eax) + addl $4, %ebx + addl $4, %eax + subl $4, %ecx + jnz 1b + + /* Load GDT. */ + lgdt gdtPtr + + /* Fill in IDT entries 0 - 16, and 32 - 47. */ + idtEntry 0, 0x8f + idtEntry 1, 0x8f + idtEntry 2, 0x8f + idtEntry 3, 0x8f + idtEntry 4, 0x8f + idtEntry 5, 0x8f + idtEntry 6, 0x8f + idtEntry 7, 0x8f + idtEntry 8, 0x8f + idtEntry 9, 0x8f + idtEntry 10, 0x8f + idtEntry 11, 0x8f + idtEntry 12, 0x8f + idtEntry 13, 0x8f + idtEntry 14, 0x8f + idtEntry 15, 0x8f + idtEntry 16, 0x8f + idtEntry 32, 0x8e + idtEntry 33, 0x8e + idtEntry 34, 0x8e + idtEntry 35, 0x8e + idtEntry 36, 0x8e + idtEntry 37, 0x8e + idtEntry 38, 0x8e + idtEntry 39, 0x8e + idtEntry 40, 0x8e + idtEntry 41, 0x8e + idtEntry 42, 0x8e + idtEntry 43, 0x8e + idtEntry 44, 0x8e + idtEntry 45, 0x8e + idtEntry 46, 0x8e + idtEntry 47, 0x8e + idtEntry 0x90, 0xee + + /* Load IDT. */ + lidt idtPtr + + /* Setup segments. */ + movl $KERNEL_DS_SEL, %eax + movl %eax, %ds + movl %eax, %es + movl %eax, %ss + + /* Kernel page directory. */ + movl $kernelPageDir, %eax + movl $kernelPageTab, %ebx + orl $(PAGE_PRESENT | PAGE_RW | PAGE_PINNED), %ebx + movl %ebx, (%eax) + + /* Identity map the first 4MB. */ + movl $kernelPageTab, %eax + xorl %ebx, %ebx + orl $(PAGE_PRESENT | PAGE_RW | PAGE_PINNED), %ebx + movl $1024, %ecx +1: + movl %ebx, (%eax) + addl $PAGESIZE, %ebx + addl $4, %eax + decl %ecx + jnz 1b + + /* Map page directory into itself. */ + movl $4, %eax + movl $PAGETABFROM, %ebx + shrl $DIRSHIFT, %ebx + imul %ebx + movl $kernelPageDir, %ebx + addl %eax, %ebx + movl %ebx, %eax + movl $kernelPageDir, %ebx + orl $(PAGE_PRESENT | PAGE_RW | PAGE_PINNED), %ebx + movl %ebx, (%eax) + + /* Enter paged mode. */ + movl $kernelPageDir, %eax + movl %eax, %cr3 + movl %cr0, %eax + orl $(CR0_PG), %eax + movl %eax, %cr0 + + /* Enable timestamp counter. */ + movl %cr4, %eax + andl $(~CR4_TSD), %eax + movl %eax, %cr4 + + /* Invoke kernel. */ + call kmain + +/** + * Stop execution immediately. + */ +halt: + cli + hlt + jmp halt + +/** + * Generated interrupt handlers. + */ +interruptHandler 0, 0 +interruptHandler 1, 0 +interruptHandler 2, 0 +interruptHandler 3, 0 +interruptHandler 4, 0 +interruptHandler 5, 0 +interruptHandler 6, 0 +interruptHandler 7, 0 +interruptHandler 8, 1 +interruptHandler 9, 0 +interruptHandler 10, 1 +interruptHandler 11, 1 +interruptHandler 12, 1 +interruptHandler 13, 1 +interruptHandler 14, 1 +interruptHandler 15, 0 +interruptHandler 16, 0 +interruptHandler 32, 0 +interruptHandler 33, 0 +interruptHandler 34, 0 +interruptHandler 35, 0 +interruptHandler 36, 0 +interruptHandler 37, 0 +interruptHandler 38, 0 +interruptHandler 39, 0 +interruptHandler 40, 0 +interruptHandler 41, 0 +interruptHandler 42, 0 +interruptHandler 43, 0 +interruptHandler 44, 0 +interruptHandler 45, 0 +interruptHandler 46, 0 +interruptHandler 47, 0 +interruptHandler 0x90, 0 + +/** + * Invokes the correct interrupt handler. + */ +invokeHandler: + + /* Make a CPUState. */ + pusha + pushl %ss + pushl %ds + pushl %es + pushl %fs + pushl %gs + + /* Replace data segments. */ + pushl %eax + mov $KERNEL_DS_SEL, %ax + mov %ax, %ds + mov %ax, %es + mov %ax, %fs + mov %ax, %gs + popl %eax + + /* Now call the correct C++ handler. */ + call executeInterrupt + + /* Restore data segments. */ + popl %gs + popl %fs + popl %es + popl %ds + add $4, %esp + + /* Continue program. */ + popa + add $8, %esp + iret + +.section ".bss" + +/** + * Multiboot information struct. + */ +multibootInfo: .fill MULTIBOOT_HEADER_SIZE, 1, 0 + +/** + * Kernel boot stack. + */ +.align PAGESIZE +stack: .fill STACK_SIZE, 1, 0 + +/** + * Kernel Page Tables. + */ +.align PAGESIZE +kernelPageDir: .fill PAGESIZE, 1, 0 +kernelPageTab: .fill PAGESIZE, 1, 0 +kernelTss: .fill PAGESIZE, 1, 0 +kernelioBitMap: .fill PAGESIZE, 1, 1 + +.section ".data" + +/** + * Global Descriptor Table. + */ +gdt: + .quad 0x0000000000000000 /* NULL descriptor. */ + .quad 0x00cf9a000000ffff /* Kernel CS. */ + .quad 0x00cf92000000ffff /* Kernel DS. */ + .quad 0x00cffa000000ffff /* User CS. */ + .quad 0x00cff2000000ffff /* User DS. */ + .quad 0x0000000000000000 /* TSS descriptor. */ +gdt_end: + +gdtPtr: + .word gdt_end - gdt + .long gdt + .word 0 + +/** + * Interrupt Descriptor Table. + */ +idt: + .fill 256, 8, 0 /* Empty IDT space. */ + +idtPtr: /* 256 IDT entries. */ + .word 256*8-1 + .long idt + +.align PAGESIZE ======================================= --- /dev/null +++ /kernel/x86/pc/boot.imgdesc Wed Jan 21 18:25:37 2015 UTC @@ -0,0 +1,6 @@ +./srv/process/server +./srv/memory/server +./srv/filesystem/tmp/server +./srv/filesystem/linn/server +./srv/idle/server +./bin/init/init ======================================= --- /dev/null +++ /kernel/x86/pc/boot.isodesc Wed Jan 21 18:25:37 2015 UTC @@ -0,0 +1,6 @@ +./boot/grub/stage1 +./boot/grub/stage2_eltorito +./boot/boot.linn.gz +./boot/boot.img.gz +./boot/grub/menu.lst +./kernel/kernel ======================================= --- /dev/null +++ /kernel/x86/pc/cd.img Wed Jan 21 18:25:37 2015 UTC Binary file, no diff available. ======================================= --- /dev/null +++ /kernel/x86/pc/contextSwitch.S Wed Jan 21 18:25:37 2015 UTC @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2009 Niek Linnenbank + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +.global contextSwitch +.section ".text" + +/* + * contextSwitch(oldStackPtr, pageDirAddr, stackAddr, + * kernelTssAddr, kernelStackAddr) + */ +contextSwitch: + + /* Setup correct stackframe. */ + push %ebp + mov %esp, %ebp + + /* Saves the current process state, if any. */ + mov 8(%ebp), %eax + cmpl $0, %eax + je restoreState + + /* Setup stack for IRETD later on. */ + pushf + push %cs + push $resume + + /* Save registers on the current stack (CPUState). */ + pushl $0 + pushl $0 + pusha + pushl %ss + pushl %ds + pushl %es + pushl %fs + pushl %gs + + /* Save stack pointer of current process in oldStackPtr. */ + pushl %esp + popl %ebx + movl %ebx, (%eax) + + /* + * Switch context to new process. + */ +restoreState: + + /* Retrieve arguments. */ + movl 12(%ebp), %eax + movl 16(%ebp), %ebx + movl 20(%ebp), %ecx + movl 24(%ebp), %edx + + /* Reload page directory, stack and TSS. */ + movl %eax, %cr3 + movl %edx, 4(%ecx) + movl $0x10, 8(%ecx) + movl %ebx, %esp + + /* Restore CPU registers. */ + popl %gs + popl %fs + popl %es + popl %ds + popl %ss + popa + addl $8, %esp + + /* Resume execution. */ + iret + +resume: + pop %ebp + ret ======================================= --- /dev/null +++ /kernel/x86/pc/grub.cfg Wed Jan 21 18:25:37 2015 UTC @@ -0,0 +1,27 @@ +# +# Copyright (C) 2010 Niek Linnenbank +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# + +set timeout=0 +set default=0 + +menuentry "FreeNOS" +{ + multiboot /kernel + module /boot/boot.img.gz + module /boot/boot.linn.gz + boot +} ======================================= --- /boot/boot.imgdesc Sun Aug 2 10:44:51 2009 UTC +++ /dev/null @@ -1,6 +0,0 @@ -./srv/process/server -./srv/memory/server -./srv/filesystem/tmp/server -./srv/filesystem/linn/server -./srv/idle/server -./sbin/init/init ======================================= --- /boot/boot.isodesc Fri Jul 10 06:12:51 2009 UTC +++ /dev/null @@ -1,6 +0,0 @@ -./boot/grub/stage1 -./boot/grub/stage2_eltorito -./boot/boot.linn.gz -./boot/boot.img.gz -./boot/grub/menu.lst -./kernel/kernel ======================================= --- /boot/grub/menu.lst Fri Jul 10 06:12:51 2009 UTC +++ /dev/null @@ -1,7 +0,0 @@ -timeout 0 - -title FreeNOS -root (cd) -kernel /kernel/kernel -module /boot/boot.img.gz -module /boot/boot.linn.gz ======================================= --- /boot/grub/stage1 Sun Jun 7 12:57:09 2009 UTC +++ /dev/null @@ -1,14 +0,0 @@-ëHÿúëöÂu²êY| 1ÀØм û @|<ÿtÂR¾}è4öÂtT´A»ªUÍZRrIûUªuC A|Àuát7fL¾|ÆDÿf
-D|ÇÇDf\ÇDpf1ÀDfD -´BÍr»pë}´Ís -öÂêé¾|ÆDÿf1Àð@fD1ÒÊÁâèô@D1ÀÐÀèff¡D|f1Òf÷4T -f1Òf÷tT -D -;D}<T -ÀâL -þÁÑl -Zt -»pÃ1Û¸Ír*ÃH|` -¹Û1ö1ÿüó¥aÿ&B|¾-}è@ë¾}è8ë¾}è0¾}è*ëþGRUB GeomHard DiskRead Error»´Í¬<uôÃ$ ¾½}1ÀÍF
-ùu¾Ú}èÏÿëFloppy»p¸µ¶Ír׶µOéæþUª ======================================= --- /boot/grub/stage2_eltorito Sun Jun 7 12:57:09 2009 UTC +++ /dev/null Binary file, no diff available. ======================================= --- /kernel/SConscript Sun Aug 17 18:01:48 2014 UTC +++ /dev/null @@ -1,32 +0,0 @@ -# -# Copyright (C) 2009 Niek Linnenbank -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see <http://www.gnu.org/licenses/>. -# - -from build import * --env = Prepare(target, [ 'libparse', 'liballoc', 'libposix', 'libexec', 'libc' ],
- [ 'process', 'memory', 'filesystem' ]) -env['LINKFLAGS'] = ' -T kernel/X86/kernel.ld -melf_i386' - -env.Program('kernel', [ 'X86/boot.S', 'X86/contextSwitch.S', - 'Kernel.cpp', 'Main.cpp', 'Memory.cpp', - 'Process.cpp', 'Scheduler.cpp', 'Support.cpp', - 'API/IPCMessage.cpp', 'API/PrivExec.cpp', - 'API/ProcessCtl.cpp', 'API/SystemInfo.cpp', - 'API/VMCopy.cpp', 'API/VMCtl.cpp', - 'X86/Kernel.cpp','X86/Memory.cpp', - 'X86/Process.cpp' ], - LIBS = env['LIBS'], LIBPATH = env['LIBPATH']) ======================================= --- /kernel/X86/Kernel.cpp Sun Aug 17 18:01:48 2014 UTC +++ /dev/null @@ -1,194 +0,0 @@ -/* - * Copyright (C) 2009 Niek Linnenbank - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include <FreeNOS/Kernel.h> -#include <FreeNOS/CPU.h> -#include <FreeNOS/API.h> -#include <FreeNOS/Init.h> -#include <FreeNOS/Interrupt.h> -#include <FreeNOS/Scheduler.h> -#include <Macros.h> -#include <List.h> -#include <ListIterator.h> -#include <Array.h> - -/** Interrupt handlers. */ -Array<List<InterruptHook> > interrupts(256); - -/** API handlers. */ -Array<APIHandler> apis(16); - -void executeInterrupt(CPUState state) -{ - /* Fetch the list of interrupt hooks (for this vector). */ - List<InterruptHook> *lst = interrupts[state.vector]; - - /* Does at least one handler exist? */ - if (!lst) return; - - /* Execute them all. */ - for (ListIterator<InterruptHook> i(lst); i.hasNext(); i.next()) - { - i.current()->handler(&state, i.current()->param); - } -} - -X86Kernel::X86Kernel() : ticks(0) -{ - /* ICW1: Initialize PIC's (Edge triggered, Cascade) */ - outb(PIC1_CMD, 0x11); - outb(PIC2_CMD, 0x11); - - /* ICW2: Remap IRQ's to interrupts 32-47. */ - outb(PIC1_DATA, PIC_IRQ_BASE); - outb(PIC2_DATA, PIC_IRQ_BASE + 8); - - /* ICW3: PIC2 is connected to PIC1 via IRQ2. */ - outb(PIC1_DATA, 0x04); - outb(PIC2_DATA, 0x02); - - /* ICW4: 8086 mode, fully nested, not buffered, no implicit EOI. */ - outb(PIC1_DATA, 0x01); - outb(PIC2_DATA, 0x01); - - /* OCW1: Disable all IRQ's for now. */ - outb(PIC1_DATA, 0xff); - outb(PIC2_DATA, 0xff); - - /* Let the i8253 timer run continuously (square wave). */ - outb(PIT_CMD, 0x36); - outb(PIT_CHAN0, PIT_DIVISOR & 0xff); - outb(PIT_CHAN0, PIT_DIVISOR >> 8); - - /* Make sure to enable PIC2 and the i8253. */ - enableIRQ(2, true); - enableIRQ(0, true); - - /* Setup exception handlers. */ - for (int i = 0; i < 17; i++) - { - hookInterrupt(i, exception, 0); - } - /* Setup IRQ handlers. */ - for (int i = 17; i < 256; i++) - { - /* Trap gate. */ - if (i == 0x90) - hookInterrupt(0x90, trap, 0); - - /* Hardware Interrupt. */ - else - hookInterrupt(i, interrupt, 0); - } - /* Install PIT (i8253) IRQ handler. */ - hookInterrupt(IRQ(0), clocktick, 0); - - /* Initialize TSS Segment. */ - gdt[USER_TSS].limitLow = sizeof(TSS) + (0xfff / 8); - gdt[USER_TSS].baseLow = ((Address) &kernelTss) & 0xffff; - gdt[USER_TSS].baseMid = (((Address) &kernelTss) >> 16) & 0xff; - gdt[USER_TSS].type = 9; - gdt[USER_TSS].privilege = 0; - gdt[USER_TSS].present = 1; - gdt[USER_TSS].limitHigh = 0; - gdt[USER_TSS].granularity = 8; - gdt[USER_TSS].baseHigh = (((Address) &kernelTss) >> 24) & 0xff; - - /* Let TSS point to I/O bitmap page. */ - kernelTss.bitmap = PAGESIZE << 16; - - /* Load Task State Register. */ - ltr(USER_TSS_SEL); -} - -void X86Kernel::hookInterrupt(int vec, InterruptHandler h, ulong p) -{ - InterruptHook hook(h, p); - - /* Insert into interrupts; create List if neccessary. */ - if (!interrupts[vec]) - { - interrupts.insert(vec, new List<InterruptHook>()); - } - /* Just append it. */ - if (!interrupts[vec]->contains(&hook)) - { - interrupts[vec]->insertTail(new InterruptHook(h, p)); - } -} - -void X86Kernel::enableIRQ(uint irq, bool enabled) -{ - if (enabled) - { - if (irq < 8) - outb(PIC1_DATA, inb(PIC1_DATA) & ~(1 << irq)); - else - outb(PIC2_DATA, inb(PIC2_DATA) & ~(1 << (irq - 8))); - } - else - { - if (irq < 8) - outb(PIC1_DATA, inb(PIC1_DATA) | (1 << irq)); - else - outb(PIC2_DATA, inb(PIC2_DATA) | (1 << (irq - 8))); - } -} - -void X86Kernel::exception(CPUState *state, ulong param) -{ - assert(scheduler->current() != ZERO); - delete scheduler->current(); - scheduler->executeNext(); -} - -void X86Kernel::interrupt(CPUState *state, ulong param) -{ - /* End of Interrupt to slave. */ - if (IRQ(state->vector) >= 8) - { - outb(PIC2_CMD, PIC_EOI); - } - /* End of Interrupt to master. */ - outb(PIC1_CMD, PIC_EOI); -} - -void X86Kernel::trap(CPUState *state, ulong param) -{ - APIHandler *h = apis[state->eax]; - - if (h) - { - state->eax = h(state->ecx, state->ebx, state->edx, - state->esi, state->edi); - } -} - -void X86Kernel::clocktick(CPUState *state, ulong param) -{ - /* Quantum reached? */ - if ((++kernel->ticks % 2) == 0) - { - /* Reset. */ - kernel->ticks = 0; - - /* Reschedule. */ - scheduler->executeNext(); - } -} - -INITOBJ(X86Kernel, kernel, KERNEL) ======================================= --- /kernel/X86/Memory.cpp Mon Jun 29 00:23:04 2009 UTC +++ /dev/null @@ -1,193 +0,0 @@ -/* - * Copyright (C) 2009 Niek Linnenbank - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include <FreeNOS/Memory.h> -#include <FreeNOS/Init.h> -#include <FreeNOS/Process.h> -#include <Types.h> -#include <string.h> - -X86Memory::X86Memory() : Memory(), remPageDir(PAGEDIRADDR_REMOTE), - remPageTab(ZERO), myPageDir(PAGEDIRADDR), - myPageTab(ZERO) -{ -} - -Address X86Memory::mapVirtual(Address paddr, Address vaddr, ulong prot) -{ - /* Virtual address specified? */ - if (vaddr == ZERO) - { - vaddr = findFree(PAGETABFROM, PAGEDIRADDR); - } - /* Point to the correct page table. */ - myPageTab = PAGETABADDR(vaddr); - - /* Do we have the page table in memory? */ - if (!(myPageDir[DIRENTRY(vaddr)] & PAGE_PRESENT)) - { - /* Then first allocate new page table. */ - Address newPageTab = memory->allocatePhysical(PAGESIZE); - newPageTab |= PAGE_PRESENT | PAGE_RW | prot; - - /* Map the new page table into memory. */ - myPageDir[DIRENTRY(vaddr)] = newPageTab; - tlb_flush(myPageTab); - - /* Zero the new page table. */ - memset(myPageTab, 0, PAGESIZE); - } - /* Map physical to virtual address. */ - myPageTab[TABENTRY(vaddr)] = (paddr & PAGEMASK) | prot; - tlb_flush(vaddr); - - /* Success. */ - return vaddr; -} - -Address X86Memory::mapVirtual(X86Process *p, Address paddr, - Address vaddr, ulong prot) -{ - /* Map remote pages. */ - mapRemote(p, vaddr); - - /* Virtual address specified? */ - if (vaddr == ZERO) - { - vaddr = findFree(PAGETABFROM_REMOTE, remPageDir); - } - /* Repoint to the correct (remote) page table. */ - remPageTab = PAGETABADDR_FROM(vaddr, PAGETABFROM_REMOTE); - - /* Does the remote process have the page table in memory? */ - if (!(remPageDir[DIRENTRY(vaddr)] & PAGE_PRESENT)) - { - /* Nope, allocate a page table first. */ - Address newPageTab = memory->allocatePhysical(PAGESIZE); - newPageTab |= PAGE_PRESENT | PAGE_RW | prot; - - /* Map the new page table into remote memory. */ - remPageDir[DIRENTRY(vaddr)] = newPageTab; - - /* Update caches. */ - tlb_flush(remPageTab); - - /* Zero the new page. */ - memset(remPageTab, 0, PAGESIZE); - } - /* Map physical address to remote virtual address. */ - remPageTab[TABENTRY(vaddr)] = (paddr & PAGEMASK) | prot; - tlb_flush(vaddr); - - /* Success. */ - return (Address) vaddr; -} - -Address X86Memory::findFree(Address pageTabFrom, Address *pageDirPtr) -{ - Address vaddr = 0xa0000000; - Address *pageTabPtr = PAGETABADDR_FROM(vaddr, pageTabFrom); - - /* Find a free virtual address. */ - while (pageDirPtr[DIRENTRY(vaddr)] & PAGE_PRESENT && - pageTabPtr[TABENTRY(vaddr)] & PAGE_PRESENT) - { - /* Look for the next page in line. */ - vaddr += PAGESIZE; - pageTabPtr = PAGETABADDR_FROM(vaddr, pageTabFrom); - } - return vaddr; -} - -Address X86Memory::lookupVirtual(X86Process *p, Address vaddr) -{ - Address ret = ZERO; - - /* Map remote page tables. */ - mapRemote(p, vaddr); - - /* Lookup the address, if mapped. */ - if (remPageDir[DIRENTRY(vaddr)] & PAGE_PRESENT && - remPageTab[TABENTRY(vaddr)] & PAGE_PRESENT) - { - ret = remPageTab[TABENTRY(vaddr)]; - } - return ret; -} - -void X86Memory::mapRemote(X86Process *p, Address pageTabAddr, - Address pageDirAddr, ulong prot) -{ - /* Map remote page directory and page table. */ - myPageDir[DIRENTRY(pageDirAddr)] = - p->getPageDirectory() | (PAGE_PRESENT|PAGE_RW|PAGE_PINNED|prot); - remPageTab = PAGETABADDR_FROM(pageTabAddr, PAGETABFROM_REMOTE); - - /* Refresh entire TLB cache. */ - tlb_flush_all(); -} - -bool X86Memory::access(X86Process *p, Address vaddr, Size sz, ulong prot) -{ - Size bytes = 0; - Address vfrom = vaddr; - - /* Map remote pages. */ - mapRemote(p, vaddr); - - /* Verify protection bits. */ - while (bytes < sz && - remPageDir[DIRENTRY(vaddr)] & prot && - remPageTab[TABENTRY(vaddr)] & prot) - { - vaddr += PAGESIZE; - bytes += ((vfrom & PAGEMASK) + PAGESIZE) - vfrom; - vfrom = vaddr & PAGEMASK; - remPageTab = PAGETABADDR_FROM(vaddr, PAGETABFROM_REMOTE); - } - /* Do we have a match? */ - return (bytes >= sz); -} - -void X86Memory::releaseAll(X86Process *p) -{ - /* Map page tables. */ - mapRemote(p, 0x0); - - /* Mark all our physical pages free. */ - for (Size i = 0; i < 1024; i++) - { - /* May we release these physical pages? */- if ((remPageDir[i] & PAGE_PRESENT) && !(remPageDir[i] & PAGE_PINNED))
- { - /* Repoint page table. */ - remPageTab = PAGETABADDR_FROM(i * PAGESIZE * 1024, - PAGETABFROM_REMOTE); - - /* Scan page table. */ - for (Size j = 0; j < 1024; j++) - {- if (remPageTab[j] & PAGE_PRESENT && !(remPageTab[j] & PAGE_PINNED))
- { - memory->releasePhysical(remPageTab[j]); - } - } - } - } -} - -INITOBJ(X86Memory, memory, VMEMORY) ======================================= --- /kernel/X86/Process.cpp Mon Jun 29 00:23:04 2009 UTC +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright (C) 2009 Niek Linnenbank - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include <FreeNOS/Process.h> -#include <FreeNOS/Memory.h> -#include <FreeNOS/CPU.h> -#include <FreeNOS/Scheduler.h> -#include <Types.h> -#include <string.h> -#include <ListIterator.h> - -X86Process::X86Process(Address entry) : Process(entry) -{ - Address *pageDir, *tmpStack, *ioMap; - CPUState *regs; - - /* Allocate page directory. */ - pageDirAddr = memory->allocatePhysical(PAGESIZE); - pageDir = (Address *) memory->mapVirtual(pageDirAddr); - - /* One page for the I/O bitmap. */ - ioMapAddr = memory->allocatePhysical(PAGESIZE); - ioMap = (Address *) memory->mapVirtual(ioMapAddr); - - /* Clear them first. */ - memset(pageDir, 0, PAGESIZE); - memset(ioMap, 0xff, PAGESIZE); - - /* Setup mappings. */ - pageDir[0] = kernelPageDir[0]; - pageDir[DIRENTRY(PAGETABFROM) ] = pageDirAddr | PAGE_PRESENT | PAGE_RW; - pageDir[DIRENTRY(PAGEUSERFROM)] = pageDirAddr | PAGE_PRESENT | PAGE_RW; - - /* Point stacks. */ - stackAddr = 0xc0000000 - MEMALIGN; - kernelStackAddr = 0xd0000000 - MEMALIGN; - - /* Allocate stacks. */ - for (int i = 0; i < 4; i++) - { - memory->allocateVirtual(this, stackAddr - (i * PAGESIZE), - PAGE_PRESENT | PAGE_USER | PAGE_RW); - memory->allocateVirtual(this, kernelStackAddr - (i * PAGESIZE), - PAGE_PRESENT | PAGE_RW); - } - /* Map kernel stack. */ - tmpStack = (Address *) memory->mapVirtual( - memory->lookupVirtual(this, kernelStackAddr) & PAGEMASK); - - /* Setup initial registers. */ - regs = (CPUState *) (((u32)tmpStack) + PAGESIZE - sizeof(CPUState)); - memset(regs, 0, sizeof(CPUState)); - regs->ss0 = KERNEL_DS_SEL; - regs->fs = USER_DS_SEL; - regs->gs = USER_DS_SEL; - regs->es = USER_DS_SEL; - regs->ds = USER_DS_SEL; - regs->ebp = stackAddr; - regs->esp0 = kernelStackAddr; - regs->eip = entry; - regs->cs = USER_CS_SEL; - regs->eflags = 0x202; - regs->esp3 = stackAddr; - regs->ss3 = USER_DS_SEL; - - /* Repoint our stack. */ - stackAddr = kernelStackAddr - sizeof(CPUState) + MEMALIGN; - - /* Release temporary mappings. */ - memory->mapVirtual((Address) 0, (Address) pageDir, 0); - memory->mapVirtual((Address) 0, (Address) tmpStack, 0); - memory->mapVirtual((Address) 0, (Address) ioMap, 0); -} - -X86Process::~X86Process() -{ - /* Remove ourselves from the scheduler. */ - scheduler->dequeue(this); - - /* Mark all our pages free. */ - memory->releaseAll(this); -} - -void X86Process::IOPort(u16 port, bool enabled) -{ - Address tmp = memory->mapVirtual(ioMapAddr); - kernelTss.setPort(port, enabled, (u8 *) tmp); - memory->mapVirtual((Address) 0, tmp, 0); -} - -void X86Process::execute() -{ - /* Refresh I/O bitmap. */ - memory->mapVirtual(ioMapAddr, (Address) &kernelioBitMap); - - /* Perform a context switch. */ - contextSwitch( scheduler->old() ? &scheduler->old()->stackAddr - : ZERO, - pageDirAddr, - stackAddr, - &kernelTss, - kernelStackAddr); -} ======================================= --- /kernel/X86/boot.S Sun Aug 17 18:01:48 2014 UTC +++ /dev/null @@ -1,323 +0,0 @@ -/* - * Copyright (C) 2009 Niek Linnenbank - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include <FreeNOS/Multiboot.h> -#include <FreeNOS/CPU.h> -#include <FreeNOS/Memory.h> - -/* The size of our stack (16KB). */ -#define STACK_SIZE 0x4000 - -/** - * Generates interrupt handlers. - */ -.macro interruptHandler vnum, verr -i\vnum: -.if !\verr - pushl $0 -.endif - pushl $\vnum - jmp invokeHandler -.endm - -/** - * Fills in IDT entries. - */ -.macro idtEntry vnum, vtype - mov $8, %eax - mov $\vnum, %ebx - imul %ebx - add $idt, %eax - mov $i\vnum, %ebx - movw %bx, (%eax) /* Offset low */ - shrl $16, %ebx - movw %bx, 6(%eax) /* Offset high */ - movw $KERNEL_CS_SEL, 2(%eax) /* Kernel CS */ - movb $0, 4(%eax) /* Zeroes */ - movb $\vtype, 5(%eax) /* Present, 32 bits, 01110 */ -.endm --.global _start, multibootHeader, multibootInfo, gdt, kernelPageDir, kernelPageTab, kernelTss, kernelioBitMap
- -.section ".text" - -/** - * Entry point. - */ -_start: - jmp _jump_entry - -/* - * Multiboot header, 32-bit aligned. - */ -.align 4 - -multibootHeader: - .long (MULTIBOOT_HEADER_MAGIC) - .long (MULTIBOOT_HEADER_FLAGS) - .long -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS) - .long (multibootHeader) - -_jump_entry: - /* Disable interrupts. */ - cli - - /* Setup temporary boot stack. */ - movl $(stack + STACK_SIZE), %esp - movl %esp, %ebp - - /* Multiboot magic + struct. */ - cmpl $MULTIBOOT_BOOTLOADER_MAGIC, %eax - jnz halt - movl $multibootInfo, %eax - movl $MULTIBOOT_HEADER_SIZE, %ecx -1: - movl (%ebx), %edx - movl %edx, (%eax) - addl $4, %ebx - addl $4, %eax - subl $4, %ecx - jnz 1b - - /* Load GDT. */ - lgdt gdtPtr - - /* Fill in IDT entries 0 - 16, and 32 - 47. */ - idtEntry 0, 0x8f - idtEntry 1, 0x8f - idtEntry 2, 0x8f - idtEntry 3, 0x8f - idtEntry 4, 0x8f - idtEntry 5, 0x8f - idtEntry 6, 0x8f - idtEntry 7, 0x8f - idtEntry 8, 0x8f - idtEntry 9, 0x8f - idtEntry 10, 0x8f - idtEntry 11, 0x8f - idtEntry 12, 0x8f - idtEntry 13, 0x8f - idtEntry 14, 0x8f - idtEntry 15, 0x8f - idtEntry 16, 0x8f - idtEntry 32, 0x8e - idtEntry 33, 0x8e - idtEntry 34, 0x8e - idtEntry 35, 0x8e - idtEntry 36, 0x8e - idtEntry 37, 0x8e - idtEntry 38, 0x8e - idtEntry 39, 0x8e - idtEntry 40, 0x8e - idtEntry 41, 0x8e - idtEntry 42, 0x8e - idtEntry 43, 0x8e - idtEntry 44, 0x8e - idtEntry 45, 0x8e - idtEntry 46, 0x8e - idtEntry 47, 0x8e - idtEntry 0x90, 0xee - - /* Load IDT. */ - lidt idtPtr - - /* Setup segments. */ - movl $KERNEL_DS_SEL, %eax - movl %eax, %ds - movl %eax, %es - movl %eax, %ss - - /* Kernel page directory. */ - movl $kernelPageDir, %eax - movl $kernelPageTab, %ebx - orl $(PAGE_PRESENT | PAGE_RW | PAGE_PINNED), %ebx - movl %ebx, (%eax) - - /* Identity map the first 4MB. */ - movl $kernelPageTab, %eax - xorl %ebx, %ebx - orl $(PAGE_PRESENT | PAGE_RW | PAGE_PINNED), %ebx - movl $1024, %ecx -1: - movl %ebx, (%eax) - addl $PAGESIZE, %ebx - addl $4, %eax - decl %ecx - jnz 1b - - /* Map page directory into itself. */ - movl $4, %eax - movl $PAGETABFROM, %ebx - shrl $DIRSHIFT, %ebx - imul %ebx - movl $kernelPageDir, %ebx - addl %eax, %ebx - movl %ebx, %eax - movl $kernelPageDir, %ebx - orl $(PAGE_PRESENT | PAGE_RW | PAGE_PINNED), %ebx - movl %ebx, (%eax) - - /* Enter paged mode. */ - movl $kernelPageDir, %eax - movl %eax, %cr3 - movl %cr0, %eax - orl $(CR0_PG), %eax - movl %eax, %cr0 - - /* Enable timestamp counter. */ - movl %cr4, %eax - andl $(~CR4_TSD), %eax - movl %eax, %cr4 - - /* Invoke kernel. */ - call kmain - -/** - * Stop execution immediately. - */ -halt: - cli - hlt - jmp halt - -/** - * Generated interrupt handlers. - */ -interruptHandler 0, 0 -interruptHandler 1, 0 -interruptHandler 2, 0 -interruptHandler 3, 0 -interruptHandler 4, 0 -interruptHandler 5, 0 -interruptHandler 6, 0 -interruptHandler 7, 0 -interruptHandler 8, 1 -interruptHandler 9, 0 -interruptHandler 10, 1 -interruptHandler 11, 1 -interruptHandler 12, 1 -interruptHandler 13, 1 -interruptHandler 14, 1 -interruptHandler 15, 0 -interruptHandler 16, 0 -interruptHandler 32, 0 -interruptHandler 33, 0 -interruptHandler 34, 0 -interruptHandler 35, 0 -interruptHandler 36, 0 -interruptHandler 37, 0 -interruptHandler 38, 0 -interruptHandler 39, 0 -interruptHandler 40, 0 -interruptHandler 41, 0 -interruptHandler 42, 0 -interruptHandler 43, 0 -interruptHandler 44, 0 -interruptHandler 45, 0 -interruptHandler 46, 0 -interruptHandler 47, 0 -interruptHandler 0x90, 0 - -/** - * Invokes the correct interrupt handler. - */ -invokeHandler: - - /* Make a CPUState. */ - pusha - pushl %ss - pushl %ds - pushl %es - pushl %fs - pushl %gs - - /* Replace data segments. */ - pushl %eax - mov $KERNEL_DS_SEL, %ax - mov %ax, %ds - mov %ax, %es - mov %ax, %fs - mov %ax, %gs - popl %eax - - /* Now call the correct C++ handler. */ - call executeInterrupt - - /* Restore data segments. */ - popl %gs - popl %fs - popl %es - popl %ds - add $4, %esp - - /* Continue program. */ - popa - add $8, %esp - iret - -.section ".bss" - -/** - * Multiboot information struct. - */ -multibootInfo: .fill MULTIBOOT_HEADER_SIZE, 1, 0 - -/** - * Kernel boot stack. - */ -.align PAGESIZE -stack: .fill STACK_SIZE, 1, 0 - -/** - * Kernel Page Tables. - */ -.align PAGESIZE -kernelPageDir: .fill PAGESIZE, 1, 0 -kernelPageTab: .fill PAGESIZE, 1, 0 -kernelTss: .fill PAGESIZE, 1, 0 -kernelioBitMap: .fill PAGESIZE, 1, 1 - -.section ".data" - -/** - * Global Descriptor Table. - */ -gdt: - .quad 0x0000000000000000 /* NULL descriptor. */ - .quad 0x00cf9a000000ffff /* Kernel CS. */ - .quad 0x00cf92000000ffff /* Kernel DS. */ - .quad 0x00cffa000000ffff /* User CS. */ - .quad 0x00cff2000000ffff /* User DS. */ - .quad 0x0000000000000000 /* TSS descriptor. */ -gdt_end: - -gdtPtr: - .word gdt_end - gdt - .long gdt - .word 0 - -/** - * Interrupt Descriptor Table. - */ -idt: - .fill 256, 8, 0 /* Empty IDT space. */ - -idtPtr: /* 256 IDT entries. */ - .word 256*8-1 - .long idt - -.align PAGESIZE ======================================= --- /kernel/X86/contextSwitch.S Sun Jun 7 12:40:11 2009 UTC +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (C) 2009 Niek Linnenbank - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -.global contextSwitch -.section ".text" - -/* - * contextSwitch(oldStackPtr, pageDirAddr, stackAddr, - * kernelTssAddr, kernelStackAddr) - */ -contextSwitch: - - /* Setup correct stackframe. */ - push %ebp - mov %esp, %ebp - - /* Saves the current process state, if any. */ - mov 8(%ebp), %eax - cmpl $0, %eax - je restoreState - - /* Setup stack for IRETD later on. */ - pushf - push %cs - push $resume - - /* Save registers on the current stack (CPUState). */ - pushl $0 - pushl $0 - pusha - pushl %ss - pushl %ds - pushl %es - pushl %fs - pushl %gs - - /* Save stack pointer of current process in oldStackPtr. */ - pushl %esp - popl %ebx - movl %ebx, (%eax) - - /* - * Switch context to new process. - */ -restoreState: - - /* Retrieve arguments. */ - movl 12(%ebp), %eax - movl 16(%ebp), %ebx - movl 20(%ebp), %ecx - movl 24(%ebp), %edx - - /* Reload page directory, stack and TSS. */ - movl %eax, %cr3 - movl %edx, 4(%ecx) - movl $0x10, 8(%ecx) - movl %ebx, %esp - - /* Restore CPU registers. */ - popl %gs - popl %fs - popl %es - popl %ds - popl %ss - popa - addl $8, %esp - - /* Resume execution. */ - iret - -resume: - pop %ebp - ret ======================================= --- /SConstruct Tue Jan 20 18:37:02 2015 UTC +++ /SConstruct Wed Jan 21 18:25:37 2015 UTC @@ -1,5 +1,5 @@ # -# Copyright (C) 2010 Niek Linnenbank +# Copyright (C) 2015 Niek Linnenbank # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -30,9 +30,13 @@ VariantDir(target['BUILDROOT'] + '/lib', '#lib', duplicate = 0) VariantDir(target['BUILDROOT'] + '/bin', '#bin', duplicate = 0) VariantDir(target['BUILDROOT'] + '/srv', '#srv', duplicate = 0) +VariantDir(target['BUILDROOT'] + '/kernel', '#kernel', duplicate = 0)+#VariantDir(target['BUILDROOT'] + '/kernel/' + target['ARCH'] + '/' + target['SYSTEM'],
+# '#kernel/' + target['ARCH'] + '/' + target['SYSTEM'], duplicate = 0) SConscript(target['BUILDROOT'] + '/lib/SConscript') SConscript(target['BUILDROOT'] + '/bin/SConscript') SConscript(target['BUILDROOT'] + '/srv/SConscript')+SConscript(target['BUILDROOT'] + '/kernel/' + target['ARCH'] + '/' + target['SYSTEM'] + '/SConscript')
# # Host build @@ -47,15 +51,3 @@ SConscript(host['BUILDROOT'] + '/lib/SConscript') SConscript(host['BUILDROOT'] + '/bin/SConscript') SConscript(host['BUILDROOT'] + '/srv/SConscript') - -# -# Kernel build -# -build_env = kernel -Export('build_env') - -# Build the kernel. -VariantDir(kernel['BUILDROOT'] + '/kernel', - '#kernel/' + kernel['ARCH'] + '/' + kernel['SYSTEM'], duplicate = 0) -SConscript(kernel['BUILDROOT'] + '/kernel/SConscript') - ======================================= --- /bin/img/Main.cpp Tue Jan 20 18:37:02 2015 UTC +++ /bin/img/Main.cpp Wed Jan 21 18:25:37 2015 UTC @@ -100,7 +100,7 @@ /* Verify command-line arguments. */ if (argc < 3) { - fprintf(stderr, "usage: %s FILE FILE\n", + fprintf(stderr, "usage: %s CONFFILE OUTFILE\n", argv[0]); return EXIT_FAILURE; } ======================================= --- /site_scons/bootimage.py Mon Jan 19 19:58:13 2015 UTC +++ /site_scons/bootimage.py Wed Jan 21 18:25:37 2015 UTC @@ -41,7 +41,7 @@ source.append('#' + env['BUILDROOT'] + '/' + line.strip()) # We also depend on the mkimage utility. - source.append('#' + build.host['BUILDROOT'] + '/bin/mkimage') + source.append('#' + build.host['BUILDROOT'] + '/bin/img/img') # All done. f.close() @@ -53,14 +53,17 @@ def boot_image_func(target, source, env): # Invoke the mkimage utility to generate a boot image. - os.system("build/host/bin/mkimage " + - "kernel/" + env['ARCH'] + "/" + - env['SYSTEM'] + "/config/boot_image.conf " + - env['BUILDROOT'] + " " + str(target[0])) + d = os.getcwd() + + os.chdir(env['BUILDROOT']) + os.system(d + "/" + build.host['BUILDROOT'] + "/bin/img/img " + + d + "/" + str(source[0]) + " " + + d + "/" + str(target[0])) + os.chdir(d) def boot_image_str(target, source, env): - return " IMG " + str(target[0]) + return " IMG " + str(target[0]) # # Add ourselves to the given environment. ======================================= --- /site_scons/build.py Tue Jan 20 18:37:02 2015 UTC +++ /site_scons/build.py Wed Jan 21 18:25:37 2015 UTC @@ -77,10 +77,8 @@ host.AddMethod(TargetLibrary, "TargetLibrary") host.AddMethod(UseLibraries, "UseLibraries") host.AddMethod(UseServers, "UseServers") - target = host.Clone(tools = ["default", "bootimage", "iso", "binary"], toolpath = ["site_scons"]) -kernel = None # Global top-level configuration. global_vars = Variables('build.conf') @@ -108,6 +106,7 @@ system_vars.Add('LINKUSER', 'Linker flags for user programs linker script') system_vars.Add('CPPPATH', 'C Preprocessor include directories') system_vars.Update(target) +target.Append(LINKFLAGS = target['LINKUSER']) # Enables verbose compilation command output. if not target['VERBOSE']: @@ -124,13 +123,6 @@ CheckCCFlags(target) CheckCXXFlags(target) -# Kernel environment is the same as target, except for linker scripts. -kernel = target.Clone() - -# Append linker script flags. -kernel.Append(LINKFLAGS = target['LINKKERN']) -target.Append(LINKFLAGS = target['LINKUSER']) - # Host environment uses a different output directory. host.Replace(ARCH = 'host') host.Replace(SYSTEM = 'host') ======================================= --- /site_scons/iso.py Mon Jan 19 19:58:13 2015 UTC +++ /site_scons/iso.py Wed Jan 21 18:25:37 2015 UTC @@ -44,7 +44,7 @@ # def iso_str(target, source, env): - return " ISO " + str(target[0]) + return " ISO " + str(target[0]) # # Add ourselves to the given environment. ======================================= --- /site_scons/version.py Mon Jan 19 19:58:13 2015 UTC +++ /site_scons/version.py Wed Jan 21 18:25:37 2015 UTC @@ -63,7 +63,6 @@ # Set the full version revision in environments. target['RELEASE'] = currentRev -kernel['RELEASE'] = currentRev host['RELEASE'] = currentRev # Attempt to retrieve the correct compiler version