2
* Copyright (c) 2006 Jakub Jermar
5
* Redistribution and use in source and binary forms, with or without
6
* modification, are permitted provided that the following conditions
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.
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.
29
/** @addtogroup sparc64
42
#include <arch/interrupt.h>
43
#include <arch/trap/interrupt.h>
44
#include <arch/barrier.h>
45
#include <preemption.h>
46
#include <time/delay.h>
49
/** Set the contents of the outgoing interrupt vector data.
51
* The first data item (data 0) will be set to the value of func, the
52
* rest of the vector will contain zeros.
54
* This is a helper function used from within the cross_call function.
56
* @param func value the first data item of the vector will be set to
58
static inline void set_intr_w_data(void (* func)(void))
61
asi_u64_write(ASI_INTR_W, ASI_UDB_INTR_W_DATA_0, (uintptr_t) func);
62
asi_u64_write(ASI_INTR_W, ASI_UDB_INTR_W_DATA_1, 0);
63
asi_u64_write(ASI_INTR_W, ASI_UDB_INTR_W_DATA_2, 0);
65
asi_u64_write(ASI_INTR_W, VA_INTR_W_DATA_0, (uintptr_t) func);
66
asi_u64_write(ASI_INTR_W, VA_INTR_W_DATA_1, 0);
67
asi_u64_write(ASI_INTR_W, VA_INTR_W_DATA_2, 0);
68
asi_u64_write(ASI_INTR_W, VA_INTR_W_DATA_3, 0);
69
asi_u64_write(ASI_INTR_W, VA_INTR_W_DATA_4, 0);
70
asi_u64_write(ASI_INTR_W, VA_INTR_W_DATA_5, 0);
71
asi_u64_write(ASI_INTR_W, VA_INTR_W_DATA_6, 0);
72
asi_u64_write(ASI_INTR_W, VA_INTR_W_DATA_7, 0);
76
/** Invoke function on another processor.
78
* Currently, only functions without arguments are supported.
79
* Supporting more arguments in the future should be no big deal.
81
* Interrupts must be disabled prior to this call.
83
* @param mid MID of the target processor.
84
* @param func Function to be invoked.
86
static void cross_call(int mid, void (* func)(void))
92
* This function might enable interrupts for a while.
93
* In order to prevent migration to another processor,
94
* we explicitly disable preemption.
99
status = asi_u64_read(ASI_INTR_DISPATCH_STATUS, 0);
100
if (status & INTR_DISPATCH_STATUS_BUSY)
101
panic("Interrupt Dispatch Status busy bit set.");
103
ASSERT(!(pstate_read() & PSTATE_IE_BIT));
106
set_intr_w_data(func);
107
asi_u64_write(ASI_INTR_W,
108
(mid << INTR_VEC_DISPATCH_MID_SHIFT) |
109
VA_INTR_W_DISPATCH, 0);
114
status = asi_u64_read(ASI_INTR_DISPATCH_STATUS, 0);
115
} while (status & INTR_DISPATCH_STATUS_BUSY);
117
done = !(status & INTR_DISPATCH_STATUS_NACK);
122
(void) interrupts_enable();
123
delay(20 + (tick_read() & 0xff));
124
(void) interrupts_disable();
132
* Deliver IPI to all processors except the current one.
134
* The sparc64 architecture does not support any group addressing
135
* which is found, for instance, on ia32 and amd64. Therefore we
136
* need to simulate the broadcast by sending the message to
137
* all target processors step by step.
139
* We assume that interrupts are disabled.
141
* @param ipi IPI number.
143
void ipi_broadcast_arch(int ipi)
150
case IPI_TLB_SHOOTDOWN:
151
func = tlb_shootdown_ipi_recv;
154
panic("Unknown IPI (%d).", ipi);
159
* As long as we don't support hot-plugging
160
* or hot-unplugging of CPUs, we can walk
161
* the cpus array and read processor's MID
165
for (i = 0; i < config.cpu_active; i++) {
167
continue; /* skip the current CPU */
169
cross_call(cpus[i].arch.mid, func);