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

TOMOYO Linux Cross Reference
Linux/arch/mips/sibyte/sb1250/smp.c

Version: ~ [ linux-5.8 ] ~ [ linux-5.7.14 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.57 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.138 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.193 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.232 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.232 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.140 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.85 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ 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.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  * Copyright (C) 2001 Broadcom Corporation
  3  *
  4  * This program is free software; you can redistribute it and/or
  5  * modify it under the terms of the GNU General Public License
  6  * as published by the Free Software Foundation; either version 2
  7  * of the License, or (at your option) any later version.
  8  *
  9  * This program is distributed in the hope that it will be useful,
 10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 12  * GNU General Public License for more details.
 13  *
 14  * You should have received a copy of the GNU General Public License
 15  * along with this program; if not, write to the Free Software
 16  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 17  */
 18 
 19 #include <linux/init.h>
 20 #include <linux/delay.h>
 21 #include <linux/interrupt.h>
 22 #include <linux/smp.h>
 23 #include <linux/kernel_stat.h>
 24 
 25 #include <asm/mmu_context.h>
 26 #include <asm/io.h>
 27 #include <asm/sibyte/sb1250.h>
 28 #include <asm/sibyte/sb1250_regs.h>
 29 #include <asm/sibyte/sb1250_int.h>
 30 
 31 extern irqreturn_t smp_call_function_interrupt(int irq, void *dev,
 32         struct pt_regs *regs);
 33 extern void smp_tune_scheduling(void);
 34 
 35 /*
 36  * These are routines for dealing with the sb1250 smp capabilities
 37  * independent of board/firmware
 38  */
 39 
 40 static u64 mailbox_set_regs[] = {
 41         KSEG1 + A_IMR_CPU0_BASE + R_IMR_MAILBOX_SET_CPU,
 42         KSEG1 + A_IMR_CPU1_BASE + R_IMR_MAILBOX_SET_CPU
 43 };
 44 
 45 static u64 mailbox_clear_regs[] = {
 46         KSEG1 + A_IMR_CPU0_BASE + R_IMR_MAILBOX_CLR_CPU,
 47         KSEG1 + A_IMR_CPU1_BASE + R_IMR_MAILBOX_CLR_CPU
 48 };
 49 
 50 static u64 mailbox_regs[] = {
 51         KSEG1 + A_IMR_CPU0_BASE + R_IMR_MAILBOX_CPU,
 52         KSEG1 + A_IMR_CPU1_BASE + R_IMR_MAILBOX_CPU
 53 };
 54 
 55 
 56 /*
 57  * Simple enough; everything is set up, so just poke the appropriate mailbox
 58  * register, and we should be set
 59  */
 60 void core_send_ipi(int cpu, unsigned int action)
 61 {
 62         __raw_writeq((((u64)action)<< 48), mailbox_set_regs[cpu]);
 63 }
 64 
 65 
 66 void sb1250_smp_finish(void)
 67 {
 68         extern void sb1_sanitize_tlb(void);
 69 
 70         sb1_sanitize_tlb();
 71         sb1250_time_init();
 72 }
 73 
 74 void sb1250_mailbox_interrupt(struct pt_regs *regs)
 75 {
 76         int cpu = smp_processor_id();
 77         unsigned int action;
 78 
 79         kstat_this_cpu.irqs[K_INT_MBOX_0]++;
 80         /* Load the mailbox register to figure out what we're supposed to do */
 81         action = (__raw_readq(mailbox_regs[cpu]) >> 48) & 0xffff;
 82 
 83         /* Clear the mailbox to clear the interrupt */
 84         __raw_writeq(((u64)action)<<48, mailbox_clear_regs[cpu]);
 85 
 86         /*
 87          * Nothing to do for SMP_RESCHEDULE_YOURSELF; returning from the
 88          * interrupt will do the reschedule for us
 89          */
 90 
 91         if (action & SMP_CALL_FUNCTION) {
 92                 smp_call_function_interrupt(0, NULL, regs);
 93         }
 94 }
 95 
 96 extern atomic_t cpus_booted;
 97 extern void prom_setup_smp(void);
 98 extern int prom_boot_secondary(int cpu, unsigned long sp, unsigned long gp);
 99 
100 void __init smp_boot_cpus(void)
101 {
102         int cur_cpu = 0;
103         int cpu;
104 
105         prom_setup_smp();
106         init_new_context(current, &init_mm);
107         current_thread_info()->cpu = 0;
108         cpu_data[0].udelay_val = loops_per_jiffy;
109         cpu_data[0].asid_cache = ASID_FIRST_VERSION;
110         cpus_clear(cpu_online_map);
111         cpu_set(0, cpu_online_map);
112         atomic_set(&cpus_booted, 1);  /* Master CPU is already booted... */
113         smp_tune_scheduling();
114 
115         /*
116          * This loop attempts to compensate for "holes" in the CPU
117          * numbering.  It's overkill, but general.
118          */
119         for (cpu = 1; cpu < num_online_cpus(); ) {
120                 struct task_struct *idle;
121                 struct pt_regs regs;
122                 int retval;
123                 printk("Starting CPU %d... ", cpu);
124 
125                 /* Spawn a new process normally.  Grab a pointer to
126                    its task struct so we can mess with it */
127                 idle = copy_process(CLONE_VM | CLONE_IDLETASK, 0, &regs, 0,
128                                     NULL, NULL);
129                 if (IS_ERR(idle))
130                         panic("failed fork for CPU %d", cpu);
131 
132                 /*
133                  * We remove it from the pidhash and the runqueue
134                  * once we got the process:
135                  */
136                 init_idle(idle, cpu);
137 
138                 unhash_process(idle);
139 
140                 do {
141                         /* Iterate until we find a CPU that comes up */
142                         cur_cpu++;
143                         retval = prom_boot_secondary(cur_cpu,
144                                             (unsigned long)idle + THREAD_SIZE - 32,
145                                             (unsigned long)idle);
146                 } while (!retval && (cur_cpu < NR_CPUS));
147                 if (retval) {
148                         cpu++;
149                 } else {
150                         panic("CPU discovery disaster");
151                 }
152         }
153 
154         /* Wait for everyone to come up */
155         while (atomic_read(&cpus_booted) != num_online_cpus());
156         smp_threads_ready = 1;
157 }
158 

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

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | 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.

osdn.jp