0001
0002
0003
0004
0005
0006
0007
0008 #ifndef _ASM_POWERPC_DBELL_H
0009 #define _ASM_POWERPC_DBELL_H
0010
0011 #include <linux/smp.h>
0012 #include <linux/threads.h>
0013
0014 #include <asm/cputhreads.h>
0015 #include <asm/ppc-opcode.h>
0016 #include <asm/feature-fixups.h>
0017 #include <asm/kvm_ppc.h>
0018
0019 #define PPC_DBELL_MSG_BRDCAST (0x04000000)
0020 #define PPC_DBELL_TYPE(x) (((x) & 0xf) << (63-36))
0021 #define PPC_DBELL_TYPE_MASK PPC_DBELL_TYPE(0xf)
0022 #define PPC_DBELL_LPID(x) ((x) << (63 - 49))
0023 #define PPC_DBELL_PIR_MASK 0x3fff
0024 enum ppc_dbell {
0025 PPC_DBELL = 0,
0026 PPC_DBELL_CRIT = 1,
0027 PPC_G_DBELL = 2,
0028 PPC_G_DBELL_CRIT = 3,
0029 PPC_G_DBELL_MC = 4,
0030 PPC_DBELL_SERVER = 5,
0031 };
0032
0033 #ifdef CONFIG_PPC_BOOK3S
0034
0035 #define PPC_DBELL_MSGTYPE PPC_DBELL_SERVER
0036
0037 static inline void _ppc_msgsnd(u32 msg)
0038 {
0039 __asm__ __volatile__ (ASM_FTR_IFSET(PPC_MSGSND(%1), PPC_MSGSNDP(%1), %0)
0040 : : "i" (CPU_FTR_HVMODE), "r" (msg));
0041 }
0042
0043
0044 static inline void ppc_msgsnd_sync(void)
0045 {
0046 __asm__ __volatile__ ("sync" : : : "memory");
0047 }
0048
0049
0050 static inline void ppc_msgsync(void)
0051 {
0052
0053 __asm__ __volatile__ (ASM_FTR_IFSET(PPC_MSGSYNC " ; lwsync", "", %0)
0054 : : "i" (CPU_FTR_HVMODE|CPU_FTR_ARCH_300));
0055 }
0056
0057 static inline void _ppc_msgclr(u32 msg)
0058 {
0059 __asm__ __volatile__ (ASM_FTR_IFSET(PPC_MSGCLR(%1), PPC_MSGCLRP(%1), %0)
0060 : : "i" (CPU_FTR_HVMODE), "r" (msg));
0061 }
0062
0063 static inline void ppc_msgclr(enum ppc_dbell type)
0064 {
0065 u32 msg = PPC_DBELL_TYPE(type);
0066
0067 _ppc_msgclr(msg);
0068 }
0069
0070 #else
0071
0072 #define PPC_DBELL_MSGTYPE PPC_DBELL
0073
0074 static inline void _ppc_msgsnd(u32 msg)
0075 {
0076 __asm__ __volatile__ (PPC_MSGSND(%0) : : "r" (msg));
0077 }
0078
0079
0080 static inline void ppc_msgsnd_sync(void)
0081 {
0082 __asm__ __volatile__ ("sync" : : : "memory");
0083 }
0084
0085
0086 static inline void ppc_msgsync(void)
0087 {
0088 }
0089
0090 #endif
0091
0092 extern void doorbell_exception(struct pt_regs *regs);
0093
0094 static inline void ppc_msgsnd(enum ppc_dbell type, u32 flags, u32 tag)
0095 {
0096 u32 msg = PPC_DBELL_TYPE(type) | (flags & PPC_DBELL_MSG_BRDCAST) |
0097 (tag & 0x07ffffff);
0098
0099 _ppc_msgsnd(msg);
0100 }
0101
0102 #ifdef CONFIG_SMP
0103
0104
0105
0106
0107
0108
0109
0110
0111
0112
0113
0114
0115 static inline void doorbell_global_ipi(int cpu)
0116 {
0117 u32 tag = get_hard_smp_processor_id(cpu);
0118
0119 kvmppc_set_host_ipi(cpu);
0120
0121 ppc_msgsnd_sync();
0122 ppc_msgsnd(PPC_DBELL_MSGTYPE, 0, tag);
0123 }
0124
0125
0126
0127
0128
0129
0130 static inline void doorbell_core_ipi(int cpu)
0131 {
0132 u32 tag = cpu_thread_in_core(cpu);
0133
0134 kvmppc_set_host_ipi(cpu);
0135
0136 ppc_msgsnd_sync();
0137 ppc_msgsnd(PPC_DBELL_MSGTYPE, 0, tag);
0138 }
0139
0140
0141
0142
0143
0144 static inline int doorbell_try_core_ipi(int cpu)
0145 {
0146 int this_cpu = get_cpu();
0147 int ret = 0;
0148
0149 if (cpumask_test_cpu(cpu, cpu_sibling_mask(this_cpu))) {
0150 doorbell_core_ipi(cpu);
0151 ret = 1;
0152 }
0153
0154 put_cpu();
0155
0156 return ret;
0157 }
0158
0159 #endif
0160
0161 #endif