Files
genode/repos/base-hw/src/include/hw/spec/arm/cpu.h
Stefan Kalkowski 202333c881 hw: cortex a9 diagnostic register initialization
We cannot count on the correct initialization of the diagnostic register
of the secondary cores. But the boot core gets initialized by the bootchain,
so we can copy over those values.

Fix #3639
2020-02-20 12:08:17 +01:00

327 lines
9.2 KiB
C++

/*
* \brief CPU definitions for ARM
* \author Stefan Kalkowski
* \date 2017-02-02
*/
/*
* Copyright (C) 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 _SRC__LIB__HW__SPEC__ARM__CPU_H_
#define _SRC__LIB__HW__SPEC__ARM__CPU_H_
#include <hw/spec/arm/register_macros.h>
namespace Hw { struct Arm_cpu; }
struct Hw::Arm_cpu
{
/***************************************
** System Coprocessor 15 Definitions **
***************************************/
/* Main ID Register */
ARM_CP15_REGISTER_32BIT(Midr, c0, c0, 0, 0);
/* Cache Type Register */
ARM_CP15_REGISTER_32BIT(Ctr, c0, c0, 0, 1);
/* Multiprocessor Affinity Register */
ARM_CP15_REGISTER_32BIT(Mpidr, c0, c0, 0, 5,
struct Aff_0 : Bitfield<0, 8> { }; /* affinity value 0 */
struct Me : Bitfield<31, 1> { }; /* multiprocessing extension */
);
/* System Control Register */
ARM_CP15_REGISTER_32BIT(Sctlr, c1, c0, 0, 0,
struct M : Bitfield<0,1> { }; /* enable MMU */
struct A : Bitfield<1,1> { }; /* enable alignment checks */
struct C : Bitfield<2,1> { }; /* enable data cache */
struct I : Bitfield<12,1> { }; /* enable instruction caches */
struct Z : Bitfield<11,1> { }; /* enable program flow prediction */
struct V : Bitfield<13,1> { }; /* select exception entry */
);
/* Auxiliary Control Register */
ARM_CP15_REGISTER_32BIT(Actlr, c1, c0, 0, 1);
/* Coprocessor Access Control Register */
ARM_CP15_REGISTER_32BIT(Cpacr, c1, c0, 0, 2,
struct Cp10 : Bitfield<20, 2> { };
struct Cp11 : Bitfield<22, 2> { };
);
/* Hyp System Control Register */
ARM_CP15_REGISTER_32BIT(Hsctlr, c1, c0, 4, 0);
/* Secure Configuration Register */
ARM_CP15_REGISTER_32BIT(Scr, c1, c1, 0, 0,
struct Ns : Bitfield<0, 1> { }; /* not secure */
struct Fw : Bitfield<4, 1> { }; /* F bit writeable */
struct Aw : Bitfield<5, 1> { }; /* A bit writeable */
struct Scd : Bitfield<7, 1> { }; /* smc call disable */
struct Hce : Bitfield<8, 1> { }; /* hyp call enable */
struct Sif : Bitfield<9, 1> { }; /* secure instruction fetch */
);
/* Secure Debug Enable Register */
ARM_CP15_REGISTER_32BIT(Sder, c1, c1, 0, 1);
/* Non-Secure Access Control Register */
ARM_CP15_REGISTER_32BIT(Nsacr, c1, c1, 0, 2,
struct Cpnsae10 : Bitfield<10, 1> { }; /* Co-processor 10 access */
struct Cpnsae11 : Bitfield<11, 1> { }; /* Co-processor 11 access */
struct Ns_smp : Bitfield<18,1> { };
);
/* Hyp Coprocessor Trap Register */
ARM_CP15_REGISTER_32BIT(Hcptr, c1, c1, 4, 2,
template <unsigned N> struct Tcp : Bitfield<N, 1> {};
struct Tase : Bitfield<15, 1> { };
struct Tta : Bitfield<20, 1> { };
struct Tcpac : Bitfield<31, 1> { };
);
/**
* Common translation table base register
*/
struct Ttbr : Genode::Register<32>
{
enum Memory_region { CACHEABLE = 1 };
struct C : Bitfield<0,1> { }; /* inner cacheable */
struct S : Bitfield<1,1> { }; /* shareable */
struct Rgn : Bitfield<3,2> { }; /* outer cachable mode */
struct Nos : Bitfield<5,1> { }; /* not outer shareable */
struct Ba : Bitfield<14, 18> { }; /* translation table base */
/*********************************
* Multiprocessing Extensions **
*********************************/
struct Irgn_1 : Bitfield<0,1> { };
struct Irgn_0 : Bitfield<6,1> { };
struct Irgn : Genode::Bitset_2<Irgn_0, Irgn_1> { }; /* inner cache mode */
static access_t init(Genode::addr_t table)
{
access_t v = Ttbr::Ba::masked(table);
Ttbr::Rgn::set(v, Ttbr::CACHEABLE);
if (Mpidr::Me::get(Mpidr::read())) { /* check for SMP system */
Ttbr::Irgn::set(v, Ttbr::CACHEABLE);
Ttbr::S::set(v, 1);
} else
Ttbr::C::set(v, 1);
return v;
};
};
struct Ttbr_64bit : Genode::Register<64>
{
struct Ba : Bitfield<4, 35> { }; /* translation table base */
struct Asid : Bitfield<48,8> { };
};
/* Translation Table Base Control Register */
ARM_CP15_REGISTER_32BIT(Ttbcr, c2, c0, 0, 2,
/***************************************
** Large Physical Address Extensions **
***************************************/
struct T0sz : Bitfield<0, 3> { };
struct Irgn0 : Bitfield<8, 2> { };
struct Orgn0 : Bitfield<10, 2> { };
struct Sh0 : Bitfield<12, 2> { };
struct T1sz : Bitfield<16, 3> { };
struct Irgn1 : Bitfield<24, 2> { };
struct Orgn1 : Bitfield<26, 2> { };
struct Sh1 : Bitfield<28, 2> { };
struct Eae : Bitfield<31, 1> { }; /* extended address enable */
);
/* Translation Table Base Register 0 */
ARM_CP15_REGISTER_32BIT(Ttbr0, c2, c0, 0, 0);
ARM_CP15_REGISTER_64BIT(Ttbr0_64bit, c2, 0);
/* Translation Table Base Register 1 */
ARM_CP15_REGISTER_32BIT(Ttbr1, c2, c0, 0, 1);
ARM_CP15_REGISTER_64BIT(Ttbr1_64bit, c2, 1);
/* Hyp Translation Control Register */
ARM_CP15_REGISTER_32BIT(Htcr, c2, c0, 4, 2);
/* Hyp Translation Table Base Register */
ARM_CP15_REGISTER_64BIT(Httbr_64bit, c2, 4);
/* Virtualization Translation Control Register */
ARM_CP15_REGISTER_32BIT(Vtcr, c2, c1, 4, 2,
struct Sl0 : Bitfield<6,2> {}; /* starting level for table walks */
);
/* Domain Access Control Register */
ARM_CP15_REGISTER_32BIT(Dacr, c3, c0, 0, 0,
struct D0 : Bitfield<0,2> { }; /* access mode for domain 0 */
);
/**
* Common fault status register
*/
struct Fsr : Genode::Register<32>
{
struct Fs_0 : Bitfield<0, 4> { };
struct Fs_1 : Bitfield<10, 1> { };
struct Fs : Genode::Bitset_2<Fs_0, Fs_1> { }; /* fault status */
};
/* Data Fault Status Register */
ARM_CP15_REGISTER_32BIT(Dfsr, c5, c0, 0, 0,
struct Wnr : Bitfield<11, 1> { }; /* write not read bit */
);
/* Instruction Fault Status Register */
ARM_CP15_REGISTER_32BIT(Ifsr, c5, c0, 0, 1);
/* Data Fault Address Register */
ARM_CP15_REGISTER_32BIT(Dfar, c6, c0, 0, 0);
/* Instruction Fault Address Register */
ARM_CP15_REGISTER_32BIT(Ifar, c6, c0, 0, 2);
/* Invalidate instruction cache line by MVA to PoU */
ARM_CP15_REGISTER_32BIT(Icimvau, c7, c5, 0, 1);
/* Branch predictor invalidate all */
ARM_CP15_REGISTER_32BIT(Bpiall, c7, c5, 0, 6);
/* Data Cache Clean and Invalidate by MVA to PoC */
ARM_CP15_REGISTER_32BIT(Dccimvac, c7, c14, 0, 1);
/* Invalidate entire unified TLB */
ARM_CP15_REGISTER_32BIT(Tlbiall, c8, c7, 0, 0);
/* Invalidate entire unified TLB (inner-shareable) */
ARM_CP15_REGISTER_32BIT(Tlbiallis, c8, c3, 0, 0);
/* Invalidate unified TLB by ASID */
ARM_CP15_REGISTER_32BIT(Tlbiasid, c8, c7, 0, 2);
/* Invalidate unified TLB by ASID (inner-shareable) */
ARM_CP15_REGISTER_32BIT(Tlbiasidis, c8, c3, 0, 2);
/* Memory Attribute Indirection Register 0 */
ARM_CP15_REGISTER_32BIT(Mair0, c10, c2, 0, 0,
struct Attr0 : Bitfield<0, 8> { };
struct Attr1 : Bitfield<8, 8> { };
struct Attr2 : Bitfield<16, 8> { };
struct Attr3 : Bitfield<24, 8> { };
);
/* Hyp Memory Attribute Indirection Register 0 */
ARM_CP15_REGISTER_32BIT(Hmair0, c10, c2, 4, 0);
/* Monitor Vector Base Address Register */
ARM_CP15_REGISTER_32BIT(Mvbar, c12, c0, 0, 1);
/* Hyp Vector Base Address Register */
ARM_CP15_REGISTER_32BIT(Hvbar, c12, c0, 4, 0);
/* Context ID Register */
ARM_CP15_REGISTER_32BIT(Cidr, c13, c0, 0, 1);
/* Counter Frequency register */
ARM_CP15_REGISTER_32BIT(Cntfrq, c14, c0, 0, 0);
/* Physical Timer Value register */
ARM_CP15_REGISTER_32BIT(Cntp_tval, c14, c2, 0, 0);
/* Physical Timer Control register */
ARM_CP15_REGISTER_32BIT(Cntp_ctl, c14, c2, 0, 1,
struct Enable : Bitfield<0, 1> {};
struct Istatus : Bitfield<2, 1> {};
);
/* Physical Count register */
ARM_CP15_REGISTER_64BIT(Cntpct, c14, 0);
/* Diagnostic register */
ARM_CP15_REGISTER_32BIT(Diag, c15, c0, 0, 1);
/******************************
** Program status registers **
******************************/
/**
* Common program status register
*/
struct Psr : Genode::Register<32>
{
/*
* CPU mode
*/
struct M : Bitfield<0,5>
{
enum {
USR = 16,
SVC = 19,
MON = 22,
HYP = 26,
SYS = 31,
};
};
struct F : Bitfield<6,1> { }; /* FIQ disable */
struct I : Bitfield<7,1> { }; /* IRQ disable */
struct A : Bitfield<8,1> { }; /* async. abort disable */
};
ARM_BANKED_REGISTER(Cpsr, cpsr);
/**********************************
** Cache maintainance functions **
**********************************/
static inline void synchronization_barrier()
{
asm volatile("dsb\n"
"isb\n");
}
static inline void wait_for_xchg(volatile void * addr,
unsigned long new_value,
unsigned long expected_value)
{
asm volatile(
/* check if load value of 'addr' is as expected */
"1: ldrex r7, [%0] \n"
"cmp r7, %2 \n"
/* if not, wait for other CPU to send us an event */
"wfene \n"
/* if yes, attempt to write 'new_value' to 'addr' */
"strexeq r7, %1, [%0] \n"
/* if write failed, restart */
"cmpeq r7, #0 \n"
"bne 1b \n"
"dmb \n"
:: "r"(addr), "r"(new_value), "r"(expected_value) : "cc", "r7");
}
static inline void wakeup_waiting_cpus()
{
asm volatile(
"dsb \n"
"sev \n"
);
}
};
#endif /* _SRC__LIB__HW__SPEC__ARM__CPU_H_ */