1/** 2 * \file 3 * \brief Implementation of the BF ARMv7 boot protocol. 4 */ 5 6/* 7 * Copyright (c) 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, Universitaetstrasse 6, CH-8092 Zurich. Attn: Systems Group. 13 */ 14 15#include <kernel.h> 16 17#include <assert.h> 18#include <boot_protocol.h> 19#include <cp15.h> 20#include <paging_kernel_arch.h> 21#include <arch/arm/platform.h> 22#include <startup_arch.h> 23 24/* 25 * \brief Boot an ARM APP core 26 * 27 * \param core_id MPID of the core to try booting 28 * \param entry Entry address for new kernel in the destination 29 * architecture's lvaddr_t 30 * 31 * \returns Zero on successful boot, non-zero (error code) on failure 32 */ 33errval_t boot_aps(hwid_t target, genpaddr_t gen_entry, genpaddr_t context) 34{ 35 36 assert(paging_mmu_enabled()); 37 38 /* XXX - we're abusing the gen_entry pointer here. Change the interface 39 * to make this arch-specific. */ 40 lpaddr_t new_core_data_ptr= (lpaddr_t)gen_entry; 41 42 /* This mailbox is in the boot driver's BSS. */ 43 struct armv7_boot_record *br= 44 (struct armv7_boot_record *)core_data->target_bootrecs; 45 46 /* Acquire the lock on the boot record. */ 47 spinlock_acquire(&br->lock); 48 49 /* Pass the core data pointer. */ 50 br->core_data= new_core_data_ptr; 51 52 /* Clear the completion notification. */ 53 br->done= 0; 54 55 /* Flag which core should boot. */ 56 /* XXX - this will only work for single-cluster systems, whose MPID fits 57 * entirely within the low 8 bits. Make core IDs bigger! */ 58 br->target_mpid= target; 59 60 /* The boot driver will read this value with its MMU and caches disabled, 61 * so we need to make sure it's visible. */ 62 dmb(); isb(); 63 clean_invalidate_to_poc(&br->core_data); 64 clean_invalidate_to_poc(&br->done); 65 clean_invalidate_to_poc(&br->target_mpid); 66 67 /* We need to ensure that the clean has finished before we wake them. */ 68 dmb(); isb(); 69 70 /* Wake all sleeping cores. */ 71 sev(); 72 73 /* The target core will let us know that it's exited the boot driver by 74 * setting done to one *with its MMU, and hence coherency, enabled*. */ 75 volatile uint32_t *mailbox= &br->done; 76 while(!*mailbox) wfe(); 77 78 /* Release the lock on the boot record. */ 79 spinlock_release(&br->lock); 80 81 return 0; 82} 83 84void 85platform_notify_bsp(uint32_t *mailbox) { 86 assert(paging_mmu_enabled()); 87 88 /* Set the flag to one (this is br->done, above). */ 89 *mailbox= 1; 90 91 /* Make sure that the write has completed. */ 92 dmb(); isb(); 93 94 /* Wake the booting core. */ 95 sev(); 96} 97