[4/5] MIPS: Handle mips_cps_core_entry within lower 4G
Commit Message
Set CM_GCR_Cx_RESET_BASE_MODE and use XKPHYS base address for
core_entry for 64bit CM when mips_cps_core_entry is beyond
KSEG1.
Also disable SMP and warn user if mips_cps_core_entry is
unsuitable as reset vector.
Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
---
Note: IMO it does not solve the problem of MobileEye,
which have mips_cps_core_entry beyond lower 4G,
it just enables me to test kernel in XKPHYS on boston.
---
arch/mips/include/asm/mips-cm.h | 1 +
arch/mips/kernel/smp-cps.c | 27 +++++++++++++++++++++------
2 files changed, 22 insertions(+), 6 deletions(-)
Comments
Jiaxun Yang <jiaxun.yang@flygoat.com> writes:
> Set CM_GCR_Cx_RESET_BASE_MODE and use XKPHYS base address for
> core_entry for 64bit CM when mips_cps_core_entry is beyond
> KSEG1.
>
> Also disable SMP and warn user if mips_cps_core_entry is
> unsuitable as reset vector.
>
> Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
> ---
> Note: IMO it does not solve the problem of MobileEye,
> which have mips_cps_core_entry beyond lower 4G,
> it just enables me to test kernel in XKPHYS on boston.
> ---
> arch/mips/include/asm/mips-cm.h | 1 +
> arch/mips/kernel/smp-cps.c | 27 +++++++++++++++++++++------
> 2 files changed, 22 insertions(+), 6 deletions(-)
>
> diff --git a/arch/mips/include/asm/mips-cm.h b/arch/mips/include/asm/mips-cm.h
> index 23c67c0871b1..15d8d69de455 100644
> --- a/arch/mips/include/asm/mips-cm.h
> +++ b/arch/mips/include/asm/mips-cm.h
> @@ -311,6 +311,7 @@ GCR_CX_ACCESSOR_RW(32, 0x018, other)
> /* GCR_Cx_RESET_BASE - Configure where powered up cores will fetch from */
> GCR_CX_ACCESSOR_RW(32, 0x020, reset_base)
> #define CM_GCR_Cx_RESET_BASE_BEVEXCBASE GENMASK(31, 12)
> +#define CM_GCR_Cx_RESET_BASE_MODE BIT(1)
>
> /* GCR_Cx_ID - Identify the current core */
> GCR_CX_ACCESSOR_RO(32, 0x028, id)
> diff --git a/arch/mips/kernel/smp-cps.c b/arch/mips/kernel/smp-cps.c
> index dd55d59b88db..623dfd05585b 100644
> --- a/arch/mips/kernel/smp-cps.c
> +++ b/arch/mips/kernel/smp-cps.c
> @@ -26,6 +26,7 @@
> #include <asm/uasm.h>
>
> static DECLARE_BITMAP(core_power, NR_CPUS);
> +static uint32_t core_entry_reg;
>
> struct core_boot_config *mips_cps_core_bootcfg;
>
> @@ -37,7 +38,6 @@ static unsigned __init core_vpe_count(unsigned int cluster, unsigned core)
> static void __init cps_smp_setup(void)
> {
> unsigned int nclusters, ncores, nvpes, core_vpes;
> - unsigned long core_entry;
> int cl, c, v;
>
> /* Detect & record VPE topology */
> @@ -94,10 +94,20 @@ static void __init cps_smp_setup(void)
> /* Make core 0 coherent with everything */
> write_gcr_cl_coherence(0xff);
>
> - if (mips_cm_revision() >= CM_REV_CM3) {
> - core_entry = CKSEG1ADDR((unsigned long)mips_cps_core_entry);
> - write_gcr_bev_base(core_entry);
> - }
> + /*
> + * Set up the core entry address
> + * If accessible in KSEG1 just use KSEG1
> + */
> + if (__pa_symbol(mips_cps_core_entry) < SZ_512M)
> + core_entry_reg = CKSEG1ADDR(__pa_symbol(mips_cps_core_entry));
> +
> + /* If CM is 64bit and with-in low 4G just use XKPHYS */
> + if (mips_cm_is64 && __pa_symbol(mips_cps_core_entry) < SZ_4G)
> + core_entry_reg = __pa_symbol(mips_cps_core_entry) |
> + CM_GCR_Cx_RESET_BASE_MODE;
> +
> + if (core_entry_reg && mips_cm_revision() >= CM_REV_CM3)
> + write_gcr_bev_base(core_entry_reg);
>
> #ifdef CONFIG_MIPS_MT_FPAFF
> /* If we have an FPU, enroll ourselves in the FPU-full mask */
> @@ -114,6 +124,11 @@ static void __init cps_prepare_cpus(unsigned int max_cpus)
>
> mips_mt_set_cpuoptions();
>
> + if (!core_entry_reg) {
> + pr_err("core_entry address unsuitable, disabling smp-cps\n");
> + goto err_out;
> + }
> +
> /* Detect whether the CCA is unsuited to multi-core SMP */
> cca = read_c0_config() & CONF_CM_CMASK;
> switch (cca) {
> @@ -213,7 +228,7 @@ static void boot_core(unsigned int core, unsigned int vpe_id)
> mips_cm_lock_other(0, core, 0, CM_GCR_Cx_OTHER_BLOCK_LOCAL);
>
> /* Set its reset vector */
> - write_gcr_co_reset_base(CKSEG1ADDR((unsigned long)mips_cps_core_entry));
> + write_gcr_co_reset_base(core_entry_reg);
>
> /* Ensure its coherency is disabled */
> write_gcr_co_coherence(0);
For my point of view the following chunk is missing, and in my tests it
was needed to have this part to fully boot.
Maybe you don't have VP core in tour hardware.
@@ -349,8 +355,8 @@ static int cps_boot_secondary(int cpu, struct task_struct *idle)
if (cpu_has_vp) {
mips_cm_lock_other(0, core, vpe_id, CM_GCR_Cx_OTHER_BLOCK_LOCAL);
- core_entry = CKSEG1ADDR((unsigned long)mips_cps_core_entry);
- write_gcr_co_reset_base(core_entry);
+ write_gcr_co_reset_base(core_entry_reg);
+
mips_cm_unlock_other();
}
> --
> 2.34.1
>
@@ -311,6 +311,7 @@ GCR_CX_ACCESSOR_RW(32, 0x018, other)
/* GCR_Cx_RESET_BASE - Configure where powered up cores will fetch from */
GCR_CX_ACCESSOR_RW(32, 0x020, reset_base)
#define CM_GCR_Cx_RESET_BASE_BEVEXCBASE GENMASK(31, 12)
+#define CM_GCR_Cx_RESET_BASE_MODE BIT(1)
/* GCR_Cx_ID - Identify the current core */
GCR_CX_ACCESSOR_RO(32, 0x028, id)
@@ -26,6 +26,7 @@
#include <asm/uasm.h>
static DECLARE_BITMAP(core_power, NR_CPUS);
+static uint32_t core_entry_reg;
struct core_boot_config *mips_cps_core_bootcfg;
@@ -37,7 +38,6 @@ static unsigned __init core_vpe_count(unsigned int cluster, unsigned core)
static void __init cps_smp_setup(void)
{
unsigned int nclusters, ncores, nvpes, core_vpes;
- unsigned long core_entry;
int cl, c, v;
/* Detect & record VPE topology */
@@ -94,10 +94,20 @@ static void __init cps_smp_setup(void)
/* Make core 0 coherent with everything */
write_gcr_cl_coherence(0xff);
- if (mips_cm_revision() >= CM_REV_CM3) {
- core_entry = CKSEG1ADDR((unsigned long)mips_cps_core_entry);
- write_gcr_bev_base(core_entry);
- }
+ /*
+ * Set up the core entry address
+ * If accessible in KSEG1 just use KSEG1
+ */
+ if (__pa_symbol(mips_cps_core_entry) < SZ_512M)
+ core_entry_reg = CKSEG1ADDR(__pa_symbol(mips_cps_core_entry));
+
+ /* If CM is 64bit and with-in low 4G just use XKPHYS */
+ if (mips_cm_is64 && __pa_symbol(mips_cps_core_entry) < SZ_4G)
+ core_entry_reg = __pa_symbol(mips_cps_core_entry) |
+ CM_GCR_Cx_RESET_BASE_MODE;
+
+ if (core_entry_reg && mips_cm_revision() >= CM_REV_CM3)
+ write_gcr_bev_base(core_entry_reg);
#ifdef CONFIG_MIPS_MT_FPAFF
/* If we have an FPU, enroll ourselves in the FPU-full mask */
@@ -114,6 +124,11 @@ static void __init cps_prepare_cpus(unsigned int max_cpus)
mips_mt_set_cpuoptions();
+ if (!core_entry_reg) {
+ pr_err("core_entry address unsuitable, disabling smp-cps\n");
+ goto err_out;
+ }
+
/* Detect whether the CCA is unsuited to multi-core SMP */
cca = read_c0_config() & CONF_CM_CMASK;
switch (cca) {
@@ -213,7 +228,7 @@ static void boot_core(unsigned int core, unsigned int vpe_id)
mips_cm_lock_other(0, core, 0, CM_GCR_Cx_OTHER_BLOCK_LOCAL);
/* Set its reset vector */
- write_gcr_co_reset_base(CKSEG1ADDR((unsigned long)mips_cps_core_entry));
+ write_gcr_co_reset_base(core_entry_reg);
/* Ensure its coherency is disabled */
write_gcr_co_coherence(0);