Example #1
0
ARMProcess::ARMProcess(ProcessID id, Address entry, bool privileged)
    : Process(id, entry, privileged)
{
    DEBUG("id =" << id << " entry =" << entry << " privileged = " << privileged);

    Size size = PAGEDIR_SIZE;
    BitAllocator *memory = Kernel::instance->getMemory();
    Memory::Range range;
    Size framesize = (14+17)*sizeof(u32);

    // Allocate first level page table
    memory->allocate(&size, &m_pageDirectory, KiloByte(16));

    // Initialize memory context
    Arch::Memory mem(m_pageDirectory, memory);
    mem.create();

    // User stack.
    range.phys   = 0;
    range.virt   = mem.range(Memory::UserStack).virt;
    range.size   = mem.range(Memory::UserStack).size;
    range.access = Memory::Present |
                   Memory::User |
                   Memory::Readable |
                   Memory::Writable;
    mem.mapRange(&range);
    setUserStack(range.virt + range.size - MEMALIGN);

    // Kernel stack.
    range.phys   = 0;
    range.virt   = mem.range(Memory::KernelStack).virt;
    range.size   = mem.range(Memory::KernelStack).size;
    range.access = Memory::Present | Memory::Readable | Memory::Writable;
    mem.mapRange(&range);
    setKernelStack(range.virt + range.size - MEMALIGN - framesize);

    // Map kernel stack.
    Arch::Memory local(0, memory);
    range.virt = local.findFree(range.size, Memory::KernelPrivate);
    local.mapRange(&range);
    Address *stack = (Address *) (range.virt + range.size - framesize - MEMALIGN);

    // Zero kernel stack
    MemoryBlock::set((void *)range.virt, 0, range.size);

    // restoreState: fill kernel register state
    stack[0] = (Address) loadCoreState0; /* restoreState: pop {lr} */
    stack += 14;

    // loadCoreState0: fill user register state
    stack[0] = (privileged ? SYS_MODE : USR_MODE) | FIQ_BIT | IRQ_BIT; /* user program status (CPSR) */
    stack++;
    stack[0] = m_userStack; /* user program SP */
    stack[1] = 0;           /* user program LR */
    stack+=15;
    stack[0] = entry;       /* user program entry (PC) */

    local.unmapRange(&range);
}
Example #2
0
IntelProcess::IntelProcess(ProcessID id, Address entry, bool privileged)
    : Process(id, entry, privileged)
{
    Address stack, stackBase, *pageDir;
    BitAllocator *memory = Kernel::instance->getMemory();
    CPUState *regs;
    Arch::Memory local(0, memory);
    Arch::Memory::Range range;
    Size dirSize = PAGESIZE;
    u16 dataSel = privileged ? KERNEL_DS_SEL : USER_DS_SEL;
    u16 codeSel = privileged ? KERNEL_CS_SEL : USER_CS_SEL;

    // Allocate and map page directory
    memory->allocate(&dirSize, &m_pageDirectory);

    pageDir = (Address *) local.findFree(PAGESIZE, Memory::KernelPrivate);
    local.map(m_pageDirectory, (Address) pageDir,
              Arch::Memory::Present |
              Arch::Memory::Readable |
              Arch::Memory::Writable);

    // Initialize page directory
    for (Size i = 0; i < PAGEDIR_MAX; i++)
        pageDir[i] = 0;

    pageDir[0] = kernelPageDir[0];
    // TODO: this should not be done here. Try to use libarch's Memory class.
    pageDir[DIRENTRY(PAGEDIR_LOCAL) ] = m_pageDirectory | PAGE_PRESENT | PAGE_USER;
    local.unmap((Address)pageDir);

    // Obtain memory mappings
    // TODO: use Memory::create()
    Arch::Memory mem(m_pageDirectory, memory);

    // User stack.
    range.phys   = 0;
    range.virt   = mem.range(Memory::UserStack).virt;
    range.size   = mem.range(Memory::UserStack).size;
    range.access = Arch::Memory::Present |
                   Arch::Memory::User |
                   Arch::Memory::Readable |
                   Arch::Memory::Writable;
    mem.mapRange(&range);
    setUserStack(range.virt + range.size - MEMALIGN);

    // Kernel stack.
    range.phys   = 0;
    range.virt   = mem.range(Memory::KernelStack).virt;
    range.size   = mem.range(Memory::KernelStack).size;
    range.access = Arch::Memory::Present |
                   Arch::Memory::Writable;
    mem.mapRange(&range);
    setKernelStack(range.virt + range.size - sizeof(CPUState)
                                           - sizeof(IRQRegs0)
                                           - sizeof(CPURegs));

    // Map kernel stack
    range.virt = local.findFree(range.size, Memory::KernelPrivate);
    stack      = range.virt;
    local.mapRange(&range);
    stackBase  = stack + range.size;

    // loadCoreState: struct CPUState
    regs = (CPUState *) stackBase - 1;
    MemoryBlock::set(regs, 0, sizeof(CPUState));
    regs->seg.ss0    = KERNEL_DS_SEL;
    regs->seg.fs     = dataSel;
    regs->seg.gs     = dataSel;
    regs->seg.es     = dataSel;
    regs->seg.ds     = dataSel;
    regs->regs.ebp   = m_userStack;
    regs->regs.esp0  = m_kernelStack;
    regs->irq.eip    = entry;
    regs->irq.cs     = codeSel;
    regs->irq.eflags = INTEL_EFLAGS_DEFAULT |
                       INTEL_EFLAGS_IRQ;
    regs->irq.esp3   = m_userStack;
    regs->irq.ss3    = dataSel;

    // restoreState: iret
    IRQRegs0 *irq = (IRQRegs0 *) regs - 1;
    irq->eip = (Address) loadCoreState;
    irq->cs  = KERNEL_CS_SEL;
    irq->eflags = INTEL_EFLAGS_DEFAULT;

    // restoreState: popa
    CPURegs *pusha = (CPURegs *) irq - 1;
    MemoryBlock::set(pusha, 0, sizeof(CPURegs));
    pusha->ebp  = m_kernelStack - sizeof(CPURegs);
    pusha->esp0 = pusha->ebp;

    local.unmapRange(&range);
}