/* * \brief CPU driver for core * \author Martin stein * \author Stefan Kalkowski * \date 2012-09-11 */ /* * Copyright (C) 2012-2017 Genode Labs GmbH * * This file is part of the Genode OS framework, which is distributed * under the terms of the GNU Affero General Public License version 3. */ #ifndef _CORE__SPEC__ARM__CPU_SUPPORT_H_ #define _CORE__SPEC__ARM__CPU_SUPPORT_H_ /* Genode includes */ #include #include #include #include /* local includes */ #include #include #include #include namespace Kernel { struct Thread_fault; } namespace Genode { using sizet_arithm_t = Genode::uint64_t; struct Arm_cpu; } struct Genode::Arm_cpu : public Hw::Arm_cpu { struct Fpu_context { uint32_t fpscr { 1UL << 24 }; /* VFP/SIMD - status/control register */ uint64_t d0_d31[32]; /* VFP/SIMD - general purpose registers */ }; struct alignas(4) Context : Cpu_state, Fpu_context { Context(bool privileged); }; /** * This class comprises ARM specific protection domain attributes */ struct Mmu_context { Cidr::access_t cidr; Ttbr0::access_t ttbr0; Mmu_context(addr_t page_table_base); ~Mmu_context(); uint8_t id() { return cidr; } }; /** * Invalidate all entries of all instruction caches */ static void invalidate_instr_cache() { asm volatile ("mcr p15, 0, %0, c7, c5, 0" :: "r" (0) : ); } /** * Invalidate all branch predictions */ static void invalidate_branch_predicts() { asm volatile ("mcr p15, 0, r0, c7, c5, 6" ::: "r0"); }; static constexpr addr_t line_size = 1 << Board::CACHE_LINE_SIZE_LOG2; static constexpr addr_t line_align_mask = ~(line_size - 1); /** * Clean and invalidate data-cache for virtual region * 'base' - 'base + size' */ static void clean_invalidate_data_cache_by_virt_region(addr_t base, size_t const size) { addr_t const top = base + size; base &= line_align_mask; for (; base < top; base += line_size) { Dccimvac::write(base); } } /** * Invalidate instruction-cache for virtual region * 'base' - 'base + size' */ void invalidate_instr_cache_by_virt_region(addr_t base, size_t const size) { addr_t const top = base + size; base &= line_align_mask; for (; base < top; base += line_size) { Icimvau::write(base); } } /** * Invalidate TLB regarding the given address space id */ static void invalidate_tlb(unsigned asid) { if (asid) Tlbiasid::write(asid); else Tlbiall::write(0); } void switch_to(Context&, Mmu_context & o) { if (o.cidr == 0) return; Cidr::access_t cidr = Cidr::read(); if (cidr != o.cidr) { Cidr::write(o.cidr); Ttbr0::write(o.ttbr0); } } static void mmu_fault(Context & c, Kernel::Thread_fault & fault); static void mmu_fault_status(Fsr::access_t fsr, Kernel::Thread_fault & fault); /************* ** Dummies ** *************/ /** * Return kernel name of the executing CPU */ static unsigned executing_id() { return 0; } }; #endif /* _CORE__SPEC__ARM__CPU_SUPPORT_H_ */