~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/mips/sgi-ip30/ip30-smp.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0
  2 /*
  3  * ip30-smp.c: SMP on IP30 architecture.
  4  * Based off of the original IP30 SMP code, with inspiration from ip27-smp.c
  5  * and smp-bmips.c.
  6  *
  7  * Copyright (C) 2005-2007 Stanislaw Skowronek <skylark@unaligned.org>
  8  *               2006-2007, 2014-2015 Joshua Kinard <kumba@gentoo.org>
  9  *               2009 Johannes Dickgreber <tanzy@gmx.de>
 10  */
 11 
 12 #include <linux/init.h>
 13 #include <linux/sched.h>
 14 #include <linux/sched/task_stack.h>
 15 
 16 #include <asm/time.h>
 17 #include <asm/sgi/heart.h>
 18 
 19 #include "ip30-common.h"
 20 
 21 #define MPCONF_MAGIC    0xbaddeed2
 22 #define MPCONF_ADDR     0xa800000000000600L
 23 #define MPCONF_SIZE     0x80
 24 #define MPCONF(x)       (MPCONF_ADDR + (x) * MPCONF_SIZE)
 25 
 26 /* HEART can theoretically do 4 CPUs, but only 2 are physically possible */
 27 #define MP_NCPU         2
 28 
 29 struct mpconf {
 30         u32 magic;
 31         u32 prid;
 32         u32 physid;
 33         u32 virtid;
 34         u32 scachesz;
 35         u16 fanloads;
 36         u16 res;
 37         void *launch;
 38         void *rendezvous;
 39         u64 res2[3];
 40         void *stackaddr;
 41         void *lnch_parm;
 42         void *rndv_parm;
 43         u32 idleflag;
 44 };
 45 
 46 static void ip30_smp_send_ipi_single(int cpu, u32 action)
 47 {
 48         int irq;
 49 
 50         switch (action) {
 51         case SMP_RESCHEDULE_YOURSELF:
 52                 irq = HEART_L2_INT_RESCHED_CPU_0;
 53                 break;
 54         case SMP_CALL_FUNCTION:
 55                 irq = HEART_L2_INT_CALL_CPU_0;
 56                 break;
 57         default:
 58                 panic("IP30: Unknown action value in %s!\n", __func__);
 59         }
 60 
 61         irq += cpu;
 62 
 63         /* Poke the other CPU -- it's got mail! */
 64         heart_write(BIT_ULL(irq), &heart_regs->set_isr);
 65 }
 66 
 67 static void ip30_smp_send_ipi_mask(const struct cpumask *mask, u32 action)
 68 {
 69         u32 i;
 70 
 71         for_each_cpu(i, mask)
 72                 ip30_smp_send_ipi_single(i, action);
 73 }
 74 
 75 static void __init ip30_smp_setup(void)
 76 {
 77         int i;
 78         int ncpu = 0;
 79         struct mpconf *mpc;
 80 
 81         init_cpu_possible(cpumask_of(0));
 82 
 83         /* Scan the MPCONF structure and enumerate available CPUs. */
 84         for (i = 0; i < MP_NCPU; i++) {
 85                 mpc = (struct mpconf *)MPCONF(i);
 86                 if (mpc->magic == MPCONF_MAGIC) {
 87                         set_cpu_possible(i, true);
 88                         __cpu_number_map[i] = ++ncpu;
 89                         __cpu_logical_map[ncpu] = i;
 90                         pr_info("IP30: Slot: %d, PrID: %.8x, PhyID: %d, VirtID: %d\n",
 91                                 i, mpc->prid, mpc->physid, mpc->virtid);
 92                 }
 93         }
 94         pr_info("IP30: Detected %d CPU(s) present.\n", ncpu);
 95 
 96         /*
 97          * Set the coherency algorithm to '5' (cacheable coherent
 98          * exclusive on write).  This is needed on IP30 SMP, especially
 99          * for R14000 CPUs, otherwise, instruction bus errors will
100          * occur upon reaching userland.
101          */
102         change_c0_config(CONF_CM_CMASK, CONF_CM_CACHABLE_COW);
103 }
104 
105 static void __init ip30_smp_prepare_cpus(unsigned int max_cpus)
106 {
107         /* nothing to do here */
108 }
109 
110 static int __init ip30_smp_boot_secondary(int cpu, struct task_struct *idle)
111 {
112         struct mpconf *mpc = (struct mpconf *)MPCONF(cpu);
113 
114         /* Stack pointer (sp). */
115         mpc->stackaddr = (void *)__KSTK_TOS(idle);
116 
117         /* Global pointer (gp). */
118         mpc->lnch_parm = task_thread_info(idle);
119 
120         mb(); /* make sure stack and lparm are written */
121 
122         /* Boot CPUx. */
123         mpc->launch = smp_bootstrap;
124 
125         /* CPUx now executes smp_bootstrap, then ip30_smp_finish */
126         return 0;
127 }
128 
129 static void __init ip30_smp_init_cpu(void)
130 {
131         ip30_per_cpu_init();
132 }
133 
134 static void __init ip30_smp_finish(void)
135 {
136         enable_percpu_irq(get_c0_compare_int(), IRQ_TYPE_NONE);
137         local_irq_enable();
138 }
139 
140 struct plat_smp_ops __read_mostly ip30_smp_ops = {
141         .send_ipi_single        = ip30_smp_send_ipi_single,
142         .send_ipi_mask          = ip30_smp_send_ipi_mask,
143         .smp_setup              = ip30_smp_setup,
144         .prepare_cpus           = ip30_smp_prepare_cpus,
145         .boot_secondary         = ip30_smp_boot_secondary,
146         .init_secondary         = ip30_smp_init_cpu,
147         .smp_finish             = ip30_smp_finish,
148         .prepare_boot_cpu       = ip30_smp_init_cpu,
149 };
150 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php