genode/repos/base-hw/src/core/spec/arm/cpu_support.h
Stefan Kalkowski 5c7436bf10 hw: remove SMP variable from board.h
Whether an SoC has the multiprocessing extensions can be read out
from the identification registers, and does not need to be specified
in each board header.

Ref #3445
2019-08-13 12:02:26 +02:00

140 lines
3.2 KiB
C++

/*
* \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 <util/register.h>
#include <cpu/cpu_state.h>
#include <base/internal/align_at.h>
#include <hw/spec/arm/cpu.h>
/* local includes */
#include <kernel/interface_support.h>
#include <kernel/kernel.h>
#include <board.h>
#include <util.h>
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_ */