Skip to content

Commit 6f14293

Browse files
gclementtsbogend
authored andcommitted
MIPS: Allow using more than 32-bit addresses for reset vectors when possible
While most MIPS64 CPUs use 32-bit values for their VP Local Reset Exception Base registers, some I6500 CPUs can utilize a 64-bit value, allowing addressing up to 47 bits of physical memory. For the EyeQ6H CPU, where physical memory addresses exceed the 4GB limit, utilizing this feature is mandatory to enable SMP support. Unfortunately, there is no way to detect this capability based solely on the ID of the CPU. According to Imagination, which designed the CPU, the only reliable method is to fill the reset base field with 0xFF and then read back its value. If the upper part of the read-back value is zero, it indicates that the address space is limited to 32 bits. Signed-off-by: Gregory CLEMENT <[email protected]> Signed-off-by: Thomas Bogendoerfer <[email protected]>
1 parent da09935 commit 6f14293

File tree

2 files changed

+41
-7
lines changed

2 files changed

+41
-7
lines changed

arch/mips/include/asm/mips-cm.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -326,7 +326,9 @@ GCR_CX_ACCESSOR_RW(32, 0x018, other)
326326

327327
/* GCR_Cx_RESET_BASE - Configure where powered up cores will fetch from */
328328
GCR_CX_ACCESSOR_RW(32, 0x020, reset_base)
329+
GCR_CX_ACCESSOR_RW(64, 0x020, reset64_base)
329330
#define CM_GCR_Cx_RESET_BASE_BEVEXCBASE GENMASK(31, 12)
331+
#define CM_GCR_Cx_RESET64_BASE_BEVEXCBASE GENMASK_ULL(47, 12)
330332
#define CM_GCR_Cx_RESET_BASE_MODE BIT(1)
331333

332334
/* GCR_Cx_ID - Identify the current core */

arch/mips/kernel/smp-cps.c

Lines changed: 39 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ enum label_id {
3737
UASM_L_LA(_not_nmi)
3838

3939
static DECLARE_BITMAP(core_power, NR_CPUS);
40-
static uint32_t core_entry_reg;
40+
static u64 core_entry_reg;
4141
static phys_addr_t cps_vec_pa;
4242

4343
struct core_boot_config *mips_cps_core_bootcfg;
@@ -94,6 +94,20 @@ static void __init *mips_cps_build_core_entry(void *addr)
9494
return p;
9595
}
9696

97+
static bool __init check_64bit_reset(void)
98+
{
99+
bool cx_64bit_reset = false;
100+
101+
mips_cm_lock_other(0, 0, 0, CM_GCR_Cx_OTHER_BLOCK_LOCAL);
102+
write_gcr_co_reset64_base(CM_GCR_Cx_RESET64_BASE_BEVEXCBASE);
103+
if ((read_gcr_co_reset64_base() & CM_GCR_Cx_RESET64_BASE_BEVEXCBASE) ==
104+
CM_GCR_Cx_RESET64_BASE_BEVEXCBASE)
105+
cx_64bit_reset = true;
106+
mips_cm_unlock_other();
107+
108+
return cx_64bit_reset;
109+
}
110+
97111
static int __init allocate_cps_vecs(void)
98112
{
99113
/* Try to allocate in KSEG1 first */
@@ -105,11 +119,23 @@ static int __init allocate_cps_vecs(void)
105119
CM_GCR_Cx_RESET_BASE_BEVEXCBASE;
106120

107121
if (!cps_vec_pa && mips_cm_is64) {
108-
cps_vec_pa = memblock_phys_alloc_range(BEV_VEC_SIZE, BEV_VEC_ALIGN,
109-
0x0, SZ_4G - 1);
110-
if (cps_vec_pa)
111-
core_entry_reg = (cps_vec_pa & CM_GCR_Cx_RESET_BASE_BEVEXCBASE) |
122+
phys_addr_t end;
123+
124+
if (check_64bit_reset()) {
125+
pr_info("VP Local Reset Exception Base support 47 bits address\n");
126+
end = MEMBLOCK_ALLOC_ANYWHERE;
127+
} else {
128+
end = SZ_4G - 1;
129+
}
130+
cps_vec_pa = memblock_phys_alloc_range(BEV_VEC_SIZE, BEV_VEC_ALIGN, 0, end);
131+
if (cps_vec_pa) {
132+
if (check_64bit_reset())
133+
core_entry_reg = (cps_vec_pa & CM_GCR_Cx_RESET64_BASE_BEVEXCBASE) |
134+
CM_GCR_Cx_RESET_BASE_MODE;
135+
else
136+
core_entry_reg = (cps_vec_pa & CM_GCR_Cx_RESET_BASE_BEVEXCBASE) |
112137
CM_GCR_Cx_RESET_BASE_MODE;
138+
}
113139
}
114140

115141
if (!cps_vec_pa)
@@ -308,7 +334,10 @@ static void boot_core(unsigned int core, unsigned int vpe_id)
308334
mips_cm_lock_other(0, core, 0, CM_GCR_Cx_OTHER_BLOCK_LOCAL);
309335

310336
/* Set its reset vector */
311-
write_gcr_co_reset_base(core_entry_reg);
337+
if (mips_cm_is64)
338+
write_gcr_co_reset64_base(core_entry_reg);
339+
else
340+
write_gcr_co_reset_base(core_entry_reg);
312341

313342
/* Ensure its coherency is disabled */
314343
write_gcr_co_coherence(0);
@@ -411,7 +440,10 @@ static int cps_boot_secondary(int cpu, struct task_struct *idle)
411440

412441
if (cpu_has_vp) {
413442
mips_cm_lock_other(0, core, vpe_id, CM_GCR_Cx_OTHER_BLOCK_LOCAL);
414-
write_gcr_co_reset_base(core_entry_reg);
443+
if (mips_cm_is64)
444+
write_gcr_co_reset64_base(core_entry_reg);
445+
else
446+
write_gcr_co_reset_base(core_entry_reg);
415447
mips_cm_unlock_other();
416448
}
417449

0 commit comments

Comments
 (0)