base-hw: Implement CPU core identification for Cortex-A55.

According to ARM Cortex-A55 Core Technical Reference Manual r1p0 the
lowest 8 bits (Aff0) of MPIDR register represent thread IDs within a
multi-threaded core. The actual core identification bits are in Aff1.
This layout can be identified by checking the MT bit of MPIDR register.
Basically, if MT=1 core id is in Aff1, if MT=0 core id is in Aff0.

Without this change Genode will identify all CPU cores on A55 as primary
(0) core.

Its worth to mention that Cortex-A55 by itself is not a multi-threaded
CPU. Aff0 values are always expected to be 0 for pure A55 cores. A55
cores can however be paired with cores that are multi-threaded. To
support such big.LITTLE CPUs in Genode we'd probably need to add a
different mechanism for mapping MPIDR values to logical, contignous
core IDs which Genode expects.

Ref:
https://developer.arm.com/documentation/100442/0100/register-descriptions/aarch64-system-registers/mpidr-el1--multiprocessor-affinity-register--el1?lang=en
This commit is contained in:
Piotr Tworek 2022-02-11 00:36:49 +01:00 committed by Norman Feske
parent c265218ba8
commit bade0a85e7
4 changed files with 21 additions and 7 deletions

View File

@ -138,11 +138,8 @@ static inline void prepare_hypervisor(Cpu::Ttbr::access_t const ttbr,
unsigned Bootstrap::Platform::enable_mmu()
{
static volatile bool primary_cpu = true;
bool primary = primary_cpu;
if (primary) primary_cpu = false;
unsigned cpu_id = (Cpu::Mpidr::read() & 0xff);
unsigned const cpu_id { Cpu::current_core_id() };
bool const primary { cpu_id == 0 };
Cpu::Ttbr::access_t ttbr =
Cpu::Ttbr::Baddr::masked((Genode::addr_t)core_pd->table_base);

View File

@ -16,6 +16,10 @@
*/
.macro _cpu_number
mrs x0, mpidr_el1
and x8, x0, #(1<<24) /* MT bit */
cbz x8, 1f
lsr x0, x0, #8
1:
and x0, x0, #0b11111111
.endm

View File

@ -106,7 +106,7 @@ struct Genode::Cpu : Hw::Arm_64_cpu
/**
* Return kernel name of the executing CPU
*/
static unsigned executing_id() { return Cpu::Mpidr::read() & 0xff; }
static unsigned executing_id() { return Cpu::current_core_id(); }
static size_t cache_line_size();
static void clear_memory_region(addr_t const addr,

View File

@ -141,7 +141,12 @@ struct Hw::Arm_64_cpu
SYSTEM_REGISTER(64, Mair_el1, mair_el1);
SYSTEM_REGISTER(64, Mair_el2, mair_el2);
SYSTEM_REGISTER(64, Mpidr, mpidr_el1);
SYSTEM_REGISTER(64, Mpidr, mpidr_el1,
struct Aff0 : Bitfield<0, 8> {};
struct Aff1 : Bitfield<8, 8> {};
struct Aff2 : Bitfield<16, 8> {};
struct MT : Bitfield<24, 1> {};
);
SYSTEM_REGISTER(32, Pmcr_el0, pmcr_el0);
SYSTEM_REGISTER(32, Pmcntenset_el0, pmcntenset_el0);
@ -256,6 +261,14 @@ struct Hw::Arm_64_cpu
using Cntpct = Cntpct_el0;
using Cntp_tval = Cntp_tval_el0;
static inline unsigned current_core_id()
{
Mpidr::access_t mpidr = Mpidr::read();
if (Mpidr::MT::get(mpidr))
return (unsigned)Mpidr::Aff1::get(mpidr);
return (unsigned)Mpidr::Aff0::get(mpidr);
}
static inline void wait_for_xchg(volatile int * addr,
int new_value,
int expected_value)