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); }
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(); }
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(); }
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); }
/** 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; }