Пример #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);
}
Пример #2
0
Process::Result ARMProcess::initialize()
{
    Memory::Range range;
    Size framesize = (14+17)*sizeof(u32);
    Address stackAddr;

    // Create MMU context
    m_memoryContext = new ARMPaging(
        &m_map,
        Kernel::instance->getAllocator()
    );
    if (!m_memoryContext)
        return OutOfMemory;

    // User stack (high memory).
    range = m_map.range(MemoryMap::UserStack);
    range.access = Memory::Readable | Memory::Writable | Memory::User;
    if (Kernel::instance->getAllocator()->allocate(&range.size, &range.phys) != Allocator::Success)
        return OutOfMemory;

    if (m_memoryContext->mapRange(&range) != MemoryContext::Success)
        return MemoryMapError;
    setUserStack(range.virt + range.size - MEMALIGN8);

    // Kernel stack (low memory).
    Size stackSize = PAGESIZE;
    if (Kernel::instance->getAllocator()->allocateLow(stackSize, &stackAddr) != Allocator::Success)
        return OutOfMemory;

    stackAddr = (Address) Kernel::instance->getAllocator()->toVirtual(stackAddr);
    m_kernelStackBase = stackAddr + stackSize;
    setKernelStack(m_kernelStackBase - framesize - MEMALIGN8);
    Address *stack = (Address *) m_kernelStack;

    // Zero kernel stack
    MemoryBlock::set((void *) stackAddr, 0, stackSize);

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

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

    // Finalize with generic initialization
    return Process::initialize();
}
Пример #3
0
Process::Result IntelProcess::initialize()
{
    Address stackSize, stackAddr;
    Memory::Range range;
    CPUState *regs;
    u16 dataSel = m_privileged ? KERNEL_DS_SEL : USER_DS_SEL;
    u16 codeSel = m_privileged ? KERNEL_CS_SEL : USER_CS_SEL;

    // Create MMU context
    m_memoryContext = new IntelPaging(
        &m_map,
        Kernel::instance->getAllocator()
    );
    if (!m_memoryContext)
        return OutOfMemory;

    // User stack (high memory).
    range = m_map.range(MemoryMap::UserStack);
    range.access = Memory::Readable | Memory::Writable | Memory::User;
    if (Kernel::instance->getAllocator()->allocate(&range.size, &range.phys) != Allocator::Success)
        return OutOfMemory;

    if (m_memoryContext->mapRange(&range) != MemoryContext::Success)
        return MemoryMapError;
    setUserStack(range.virt + range.size - MEMALIGN);

    // Kernel stack (low memory).
    stackSize = PAGESIZE;
    if (Kernel::instance->getAllocator()->allocateLow(stackSize, &stackAddr) != Allocator::Success)
        return OutOfMemory;

    stackAddr = (Address) Kernel::instance->getAllocator()->toVirtual(stackAddr);
    m_kernelStackBase = stackAddr + stackSize;
    setKernelStack(m_kernelStackBase - sizeof(CPUState)
                   - sizeof(IRQRegs0)
                   - sizeof(CPURegs));

    // Fill kernel stack with initial (user)registers to restore
    // loadCoreState: struct CPUState
    regs = (CPUState *) m_kernelStackBase - 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    = m_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_kernelStackBase - sizeof(CPURegs);
    pusha->esp0 = pusha->ebp;

    // Finalize with generic initialization
    return Process::initialize();
}
Пример #4
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);
}