Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/arch/powerpc/include/asm/dbell.h
26481 views
1
/* SPDX-License-Identifier: GPL-2.0-or-later */
2
/*
3
* Copyright 2009 Freescale Semiconductor, Inc.
4
*
5
* provides masks and opcode images for use by code generation, emulation
6
* and for instructions that older assemblers might not know about
7
*/
8
#ifndef _ASM_POWERPC_DBELL_H
9
#define _ASM_POWERPC_DBELL_H
10
11
#include <linux/smp.h>
12
#include <linux/threads.h>
13
14
#include <asm/cputhreads.h>
15
#include <asm/ppc-opcode.h>
16
#include <asm/feature-fixups.h>
17
#include <asm/kvm_ppc.h>
18
19
#define PPC_DBELL_MSG_BRDCAST (0x04000000)
20
#define PPC_DBELL_TYPE(x) (((x) & 0xf) << (63-36))
21
#define PPC_DBELL_TYPE_MASK PPC_DBELL_TYPE(0xf)
22
#define PPC_DBELL_LPID(x) ((x) << (63 - 49))
23
#define PPC_DBELL_PIR_MASK 0x3fff
24
enum ppc_dbell {
25
PPC_DBELL = 0, /* doorbell */
26
PPC_DBELL_CRIT = 1, /* critical doorbell */
27
PPC_G_DBELL = 2, /* guest doorbell */
28
PPC_G_DBELL_CRIT = 3, /* guest critical doorbell */
29
PPC_G_DBELL_MC = 4, /* guest mcheck doorbell */
30
PPC_DBELL_SERVER = 5, /* doorbell on server */
31
};
32
33
#ifdef CONFIG_PPC_BOOK3S
34
35
#define PPC_DBELL_MSGTYPE PPC_DBELL_SERVER
36
37
static inline void _ppc_msgsnd(u32 msg)
38
{
39
__asm__ __volatile__ (ASM_FTR_IFSET(PPC_MSGSND(%1), PPC_MSGSNDP(%1), %0)
40
: : "i" (CPU_FTR_HVMODE), "r" (msg));
41
}
42
43
/* sync before sending message */
44
static inline void ppc_msgsnd_sync(void)
45
{
46
__asm__ __volatile__ ("sync" : : : "memory");
47
}
48
49
/* sync after taking message interrupt */
50
static inline void ppc_msgsync(void)
51
{
52
/* sync is not required when taking messages from the same core */
53
__asm__ __volatile__ (ASM_FTR_IFSET(PPC_MSGSYNC " ; lwsync", "", %0)
54
: : "i" (CPU_FTR_HVMODE|CPU_FTR_ARCH_300));
55
}
56
57
static inline void _ppc_msgclr(u32 msg)
58
{
59
__asm__ __volatile__ (ASM_FTR_IFSET(PPC_MSGCLR(%1), PPC_MSGCLRP(%1), %0)
60
: : "i" (CPU_FTR_HVMODE), "r" (msg));
61
}
62
63
static inline void ppc_msgclr(enum ppc_dbell type)
64
{
65
u32 msg = PPC_DBELL_TYPE(type);
66
67
_ppc_msgclr(msg);
68
}
69
70
#else /* CONFIG_PPC_BOOK3S */
71
72
#define PPC_DBELL_MSGTYPE PPC_DBELL
73
74
static inline void _ppc_msgsnd(u32 msg)
75
{
76
__asm__ __volatile__ (PPC_MSGSND(%0) : : "r" (msg));
77
}
78
79
/* sync before sending message */
80
static inline void ppc_msgsnd_sync(void)
81
{
82
__asm__ __volatile__ ("sync" : : : "memory");
83
}
84
85
/* sync after taking message interrupt */
86
static inline void ppc_msgsync(void)
87
{
88
}
89
90
#endif /* CONFIG_PPC_BOOK3S */
91
92
extern void doorbell_exception(struct pt_regs *regs);
93
94
static inline void ppc_msgsnd(enum ppc_dbell type, u32 flags, u32 tag)
95
{
96
u32 msg = PPC_DBELL_TYPE(type) | (flags & PPC_DBELL_MSG_BRDCAST) |
97
(tag & 0x07ffffff);
98
99
_ppc_msgsnd(msg);
100
}
101
102
#ifdef CONFIG_SMP
103
104
/*
105
* Doorbells must only be used if CPU_FTR_DBELL is available.
106
* msgsnd is used in HV, and msgsndp is used in !HV.
107
*
108
* These should be used by platform code that is aware of restrictions.
109
* Other arch code should use ->cause_ipi.
110
*
111
* doorbell_global_ipi() sends a dbell to any target CPU.
112
* Must be used only by architectures that address msgsnd target
113
* by PIR/get_hard_smp_processor_id.
114
*/
115
static inline void doorbell_global_ipi(int cpu)
116
{
117
u32 tag = get_hard_smp_processor_id(cpu);
118
119
kvmppc_set_host_ipi(cpu);
120
/* Order previous accesses vs. msgsnd, which is treated as a store */
121
ppc_msgsnd_sync();
122
ppc_msgsnd(PPC_DBELL_MSGTYPE, 0, tag);
123
}
124
125
/*
126
* doorbell_core_ipi() sends a dbell to a target CPU in the same core.
127
* Must be used only by architectures that address msgsnd target
128
* by TIR/cpu_thread_in_core.
129
*/
130
static inline void doorbell_core_ipi(int cpu)
131
{
132
u32 tag = cpu_thread_in_core(cpu);
133
134
kvmppc_set_host_ipi(cpu);
135
/* Order previous accesses vs. msgsnd, which is treated as a store */
136
ppc_msgsnd_sync();
137
ppc_msgsnd(PPC_DBELL_MSGTYPE, 0, tag);
138
}
139
140
/*
141
* Attempt to cause a core doorbell if destination is on the same core.
142
* Returns 1 on success, 0 on failure.
143
*/
144
static inline int doorbell_try_core_ipi(int cpu)
145
{
146
int this_cpu = get_cpu();
147
int ret = 0;
148
149
if (cpumask_test_cpu(cpu, cpu_sibling_mask(this_cpu))) {
150
doorbell_core_ipi(cpu);
151
ret = 1;
152
}
153
154
put_cpu();
155
156
return ret;
157
}
158
159
#endif /* CONFIG_SMP */
160
161
#endif /* _ASM_POWERPC_DBELL_H */
162
163