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