1/** 2 * \file 3 * \brief ARM execution and miscellany 4 */ 5 6/* 7 * Copyright (c) 2007-2009,2016 ETH Zurich. 8 * All rights reserved. 9 * 10 * This file is distributed under the terms in the attached LICENSE file. 11 * If you do not find this file, copies can be found by writing to: 12 * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group. 13 */ 14 15#include <kernel.h> 16 17#include <cache.h> 18#include <dispatch.h> 19#include <init.h> 20#include <arm.h> 21#include <platform.h> 22#include <exec.h> 23#include <exceptions.h> 24#include <misc.h> 25/* XXX - not AArch64-compatible. */ 26#include <cp15.h> // for invalidating tlb and cache 27 28static arch_registers_state_t upcall_state = 29{ 30 .named.fpscr = 0x01000000 31}; 32 33extern uint32_t ctr; 34 35STATIC_ASSERT(CPSR_REG == 0, ""); 36STATIC_ASSERT(R0_REG == 1, ""); 37STATIC_ASSERT(PC_REG == 16, ""); 38 39void __attribute__((noreturn)) do_resume(uint32_t *regs); 40 41/// Ensure context is for user-mode with interrupts enabled. 42static inline void 43ensure_user_mode_policy(arch_registers_state_t *state) 44{ 45 uintptr_t cpsr_if_mode = CPSR_F_MASK | ARM_MODE_USR; 46 47 if ((state->named.cpsr & (CPSR_IF_MASK | ARM_MODE_MASK)) != cpsr_if_mode) { 48 assert(0 == (state->named.cpsr & ARM_MODE_PRIV)); 49 state->named.cpsr &= CPSR_IF_MASK | ARM_MODE_MASK; 50 state->named.cpsr |= cpsr_if_mode; 51 } 52} 53 54/** 55 * \brief Go to user-space at entry point 'entry'. 56 * 57 * This function goes to user-space and starts executing the program at 58 * its entry point at virtual address 'entry'. 59 * 60 * \param entry Entry point address of program to execute. 61 */ 62void __attribute__ ((noreturn)) 63execute(lvaddr_t entry) 64{ 65 dispatcher_handle_t handle = dcb_current->disp; 66 struct dispatcher_shared_arm *disp_arm = get_dispatcher_shared_arm(handle); 67 68 arch_registers_state_t *state = &upcall_state; 69 assert(0 != disp_arm->got_base); 70 71 /* XXX - not AArch64-compatible. */ 72 state->named.r9 = disp_arm->got_base; 73 74 state->named.pc = entry; 75 ensure_user_mode_policy(state); 76 do_resume(state->regs); 77} 78 79/** 80 * \brief Resume the given user-space snapshot. 81 * 82 * This function resumes user-space execution by restoring the CPU 83 * registers with the ones given in the array, pointed to by 'state'. 84 */ 85uint32_t ctr=0; 86void __attribute__ ((noreturn)) resume(arch_registers_state_t *state) 87{ 88 ctr++; 89 ensure_user_mode_policy(state); 90 91 /* 92 This function succeeds the first time executed, i.e. 93 when init is started for the first time. 94 If we hold the execution here after the first execption, we are still good 95 */ 96 // while(ctr>1); 97 do_resume(state->regs); 98} 99 100bool waiting_for_interrupt= 0; 101 102/* XXX - not AArch64-compatible. */ 103void wait_for_interrupt(void) 104{ 105 // XXX - is this true? 106 // REVIEW: Timer interrupt could be masked here. 107 108 /* If we're waiting on an interrupt in the kernel, it must be because 109 * there was no runnable dispatcher. */ 110 assert(dcb_current == NULL); 111 112 /* Let the IRQ handler know that we expect an interrupt in kernel mode, so 113 * it shouldn't panic. */ 114 waiting_for_interrupt= 1; 115 116 /* Unmask IRQ and wait. */ 117 __asm volatile("cpsie i"); 118 while(1) __asm volatile("wfi"); 119} 120