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
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();
}
Example #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();
}
Example #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);
}
Example #5
0
File: boot.c Project: seL4/seL4
/** This and only this function initialises the CPU.
 *
 * It does NOT initialise any kernel state.
 * @return For the verification build, this currently returns true always.
 */
BOOT_CODE static bool_t init_cpu(void)
{
    bool_t haveHWFPU;

#ifdef CONFIG_ARCH_AARCH64
    if (config_set(CONFIG_ARM_HYPERVISOR_SUPPORT)) {
        if (!checkTCR_EL2()) {
            return false;
        }
    }
#endif

    activate_global_pd();
    if (config_set(CONFIG_ARM_HYPERVISOR_SUPPORT)) {
        vcpu_boot_init();
    }

#ifdef CONFIG_HARDWARE_DEBUG_API
    if (!Arch_initHardwareBreakpoints()) {
        printf("Kernel built with CONFIG_HARDWARE_DEBUG_API, but this board doesn't "
               "reliably support it.\n");
        return false;
    }
#endif

    /* Setup kernel stack pointer.
     * On ARM SMP, the array index here is the CPU ID
     */
#ifndef CONFIG_ARCH_ARM_V6
    word_t stack_top = ((word_t) kernel_stack_alloc[SMP_TERNARY(getCurrentCPUIndex(), 0)]) + BIT(CONFIG_KERNEL_STACK_BITS);
#if defined(ENABLE_SMP_SUPPORT) && defined(CONFIG_ARCH_AARCH64)
    /* the least 12 bits are used to store logical core ID */
    stack_top |= getCurrentCPUIndex();
#endif
    setKernelStack(stack_top);
#endif /* CONFIG_ARCH_ARM_V6 */

#ifdef CONFIG_ARCH_AARCH64
    /* initialise CPU's exception vector table */
    setVtable((pptr_t)arm_vector_table);
#endif /* CONFIG_ARCH_AARCH64 */

    haveHWFPU = fpsimd_HWCapTest();

    /* Disable FPU to avoid channels where a platform has an FPU but doesn't make use of it */
    if (haveHWFPU) {
        disableFpu();
    }

#ifdef CONFIG_HAVE_FPU
    if (haveHWFPU) {
        if (!fpsimd_init()) {
            return false;
        }
    } else {
        printf("Platform claims to have FP hardware, but does not!");
        return false;
    }
#endif /* CONFIG_HAVE_FPU */

    cpu_initLocalIRQController();

#ifdef CONFIG_ENABLE_BENCHMARKS
    armv_init_ccnt();
#endif /* CONFIG_ENABLE_BENCHMARKS */

    /* Export selected CPU features for access by PL0 */
    armv_init_user_access();

    initTimer();

    return true;
}