1 // SPDX-License-Identifier: GPL-2.0
3 * safe read and write memory routines callable while atomic
5 * Copyright 2012 Imagination Technologies
8 #include <linux/uaccess.h>
12 * The generic probe_kernel_write() uses the user copy code which can split the
13 * writes if the source is unaligned, and repeats writes to make exceptions
14 * precise. We override it here to avoid these things happening to memory mapped
15 * IO memory where they could have undesired effects.
16 * Due to the use of CACHERD instruction this only works on Meta2 onwards.
18 #ifdef CONFIG_METAG_META21
19 long probe_kernel_write(void *dst
, const void *src
, size_t size
)
21 unsigned long ldst
= (unsigned long)dst
;
22 void __iomem
*iodst
= (void __iomem
*)dst
;
23 unsigned long lsrc
= (unsigned long)src
;
24 const u8
*psrc
= (u8
*)src
;
26 u8 bounce
[8] __aligned(8);
31 /* Use the write combine bit to decide is the destination is MMIO. */
32 pte
= __builtin_meta2_cacherd(dst
);
34 /* Check the mapping is valid and writeable. */
35 if ((pte
& (MMCU_ENTRY_WR_BIT
| MMCU_ENTRY_VAL_BIT
))
36 != (MMCU_ENTRY_WR_BIT
| MMCU_ENTRY_VAL_BIT
))
39 /* Fall back to generic version for cases we're not interested in. */
40 if (pte
& MMCU_ENTRY_WRC_BIT
|| /* write combined memory */
41 (ldst
& (size
- 1)) || /* destination unaligned */
42 size
> 8 || /* more than max write size */
43 (size
& (size
- 1))) /* non power of 2 size */
44 return __probe_kernel_write(dst
, src
, size
);
46 /* If src is unaligned, copy to the aligned bounce buffer first. */
47 if (lsrc
& (size
- 1)) {
48 for (i
= 0; i
< size
; ++i
)
58 writew(*(const u16
*)psrc
, iodst
);
61 writel(*(const u32
*)psrc
, iodst
);
64 writeq(*(const u64
*)psrc
, iodst
);