/* SPDX-License-Identifier: GPL-2.0 */1#ifndef __PARISC_LDCW_H2#define __PARISC_LDCW_H34/* Because kmalloc only guarantees 8-byte alignment for kmalloc'd data,5and GCC only guarantees 8-byte alignment for stack locals, we can't6be assured of 16-byte alignment for atomic lock data even if we7specify "__attribute ((aligned(16)))" in the type declaration. So,8we use a struct containing an array of four ints for the atomic lock9type and dynamically select the 16-byte aligned int from the array10for the semaphore. */1112/* From: "Jim Hull" <jim.hull of hp.com>13I've attached a summary of the change, but basically, for PA 2.0, as14long as the ",CO" (coherent operation) completer is implemented, then the1516-byte alignment requirement for ldcw and ldcd is relaxed, and instead16they only require "natural" alignment (4-byte for ldcw, 8-byte for17ldcd).1819Although the cache control hint is accepted by all PA 2.0 processors,20it is only implemented on PA8800/PA8900 CPUs. Prior PA8X00 CPUs still21require 16-byte alignment. If the address is unaligned, the operation22of the instruction is undefined. The ldcw instruction does not generate23unaligned data reference traps so misaligned accesses are not detected.24This hid the problem for years. So, restore the 16-byte alignment dropped25by Kyle McMartin in "Remove __ldcw_align for PA-RISC 2.0 processors". */2627#define __PA_LDCW_ALIGNMENT 1628#define __ldcw_align(a) ({ \29unsigned long __ret = (unsigned long) &(a)->lock[0]; \30__ret = (__ret + __PA_LDCW_ALIGNMENT - 1) \31& ~(__PA_LDCW_ALIGNMENT - 1); \32(volatile unsigned int *) __ret; \33})3435#ifdef CONFIG_PA2036#define __LDCW "ldcw,co"37#else38#define __LDCW "ldcw"39#endif4041/* LDCW, the only atomic read-write operation PA-RISC has. *sigh*.42We don't explicitly expose that "*a" may be written as reload43fails to find a register in class R1_REGS when "a" needs to be44reloaded when generating 64-bit PIC code. Instead, we clobber45memory to indicate to the compiler that the assembly code reads46or writes to items other than those listed in the input and output47operands. This may pessimize the code somewhat but __ldcw is48usually used within code blocks surrounded by memory barriers. */49#define __ldcw(a) ({ \50unsigned __ret; \51__asm__ __volatile__(__LDCW " 0(%1),%0" \52: "=r" (__ret) : "r" (a) : "memory"); \53__ret; \54})5556#ifdef CONFIG_SMP57# define __lock_aligned __section(".data..lock_aligned") __aligned(16)58#endif5960#endif /* __PARISC_LDCW_H */616263