source: mainline/kernel/arch/sparc64/src/smp/sun4u/ipi.c

Last change on this file was d19b3fc, checked in by Jakub Jermar <jakub@…>, 7 years ago

Remove smp_call

  • Property mode set to 100644
File size: 5.0 KB
Line 
1/*
2 * Copyright (c) 2006 Jakub Jermar
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup kernel_sparc64
30 * @{
31 */
32/** @file
33 */
34
35#include <smp/ipi.h>
36#include <arch/barrier.h>
37#include <assert.h>
38#include <cpu.h>
39#include <arch.h>
40#include <arch/cpu.h>
41#include <arch/asm.h>
42#include <config.h>
43#include <mm/tlb.h>
44#include <arch/interrupt.h>
45#include <arch/trap/interrupt.h>
46#include <barrier.h>
47#include <preemption.h>
48#include <time/delay.h>
49#include <panic.h>
50
51/** Set the contents of the outgoing interrupt vector data.
52 *
53 * The first data item (data 0) will be set to the value of func, the
54 * rest of the vector will contain zeros.
55 *
56 * This is a helper function used from within the cross_call function.
57 *
58 * @param func value the first data item of the vector will be set to
59 */
60static inline void set_intr_w_data(void (*func)(void))
61{
62#if defined (US)
63 asi_u64_write(ASI_INTR_W, ASI_UDB_INTR_W_DATA_0, (uintptr_t) func);
64 asi_u64_write(ASI_INTR_W, ASI_UDB_INTR_W_DATA_1, 0);
65 asi_u64_write(ASI_INTR_W, ASI_UDB_INTR_W_DATA_2, 0);
66#elif defined (US3)
67 asi_u64_write(ASI_INTR_W, VA_INTR_W_DATA_0, (uintptr_t) func);
68 asi_u64_write(ASI_INTR_W, VA_INTR_W_DATA_1, 0);
69 asi_u64_write(ASI_INTR_W, VA_INTR_W_DATA_2, 0);
70 asi_u64_write(ASI_INTR_W, VA_INTR_W_DATA_3, 0);
71 asi_u64_write(ASI_INTR_W, VA_INTR_W_DATA_4, 0);
72 asi_u64_write(ASI_INTR_W, VA_INTR_W_DATA_5, 0);
73 asi_u64_write(ASI_INTR_W, VA_INTR_W_DATA_6, 0);
74 asi_u64_write(ASI_INTR_W, VA_INTR_W_DATA_7, 0);
75#endif
76}
77
78/** Invoke function on another processor.
79 *
80 * Currently, only functions without arguments are supported.
81 * Supporting more arguments in the future should be no big deal.
82 *
83 * Interrupts must be disabled prior to this call.
84 *
85 * @param mid MID of the target processor.
86 * @param func Function to be invoked.
87 */
88static void cross_call(int mid, void (*func)(void))
89{
90 uint64_t status;
91 bool done;
92
93 /*
94 * This function might enable interrupts for a while.
95 * In order to prevent migration to another processor,
96 * we explicitly disable preemption.
97 */
98
99 preemption_disable();
100
101 status = asi_u64_read(ASI_INTR_DISPATCH_STATUS, 0);
102 if (status & INTR_DISPATCH_STATUS_BUSY)
103 panic("Interrupt Dispatch Status busy bit set\n");
104
105 assert(!(pstate_read() & PSTATE_IE_BIT));
106
107 do {
108 set_intr_w_data(func);
109 asi_u64_write(ASI_INTR_W,
110 (mid << INTR_VEC_DISPATCH_MID_SHIFT) |
111 VA_INTR_W_DISPATCH, 0);
112
113 membar();
114
115 do {
116 status = asi_u64_read(ASI_INTR_DISPATCH_STATUS, 0);
117 } while (status & INTR_DISPATCH_STATUS_BUSY);
118
119 done = !(status & INTR_DISPATCH_STATUS_NACK);
120 if (!done) {
121 /*
122 * Prevent deadlock.
123 */
124 (void) interrupts_enable();
125 delay(20 + (tick_read() & 0xff));
126 (void) interrupts_disable();
127 }
128 } while (!done);
129
130 preemption_enable();
131}
132
133/*
134 * Deliver IPI to all processors except the current one.
135 *
136 * The sparc64 architecture does not support any group addressing
137 * which is found, for instance, on ia32 and amd64. Therefore we
138 * need to simulate the broadcast by sending the message to
139 * all target processors step by step.
140 *
141 * We assume that interrupts are disabled.
142 *
143 * @param ipi IPI number.
144 */
145void ipi_broadcast_arch(int ipi)
146{
147 unsigned int i;
148
149 void (*func)(void);
150
151 switch (ipi) {
152 case IPI_TLB_SHOOTDOWN:
153 func = tlb_shootdown_ipi_recv;
154 break;
155 default:
156 panic("Unknown IPI (%d).\n", ipi);
157 break;
158 }
159
160 /*
161 * As long as we don't support hot-plugging
162 * or hot-unplugging of CPUs, we can walk
163 * the cpus array and read processor's MID
164 * without locking.
165 */
166
167 for (i = 0; i < config.cpu_active; i++) {
168 if (&cpus[i] == CPU)
169 continue; /* skip the current CPU */
170
171 cross_call(cpus[i].arch.mid, func);
172 }
173}
174
175/** @}
176 */
Note: See TracBrowser for help on using the repository browser.