1 /* SPDX-License-Identifier: GPL-2.0 */
2 /*
3  *    Copyright IBM Corp. 2017
4  *    Author(s): Claudio Imbrenda <imbrenda@linux.vnet.ibm.com>
5  */
6 
7 #ifndef PAGE_STATES_H
8 #define PAGE_STATES_H
9 
10 #include <asm/sections.h>
11 #include <asm/page.h>
12 
13 #define ESSA_GET_STATE			0
14 #define ESSA_SET_STABLE			1
15 #define ESSA_SET_UNUSED			2
16 #define ESSA_SET_VOLATILE		3
17 #define ESSA_SET_POT_VOLATILE		4
18 #define ESSA_SET_STABLE_RESIDENT	5
19 #define ESSA_SET_STABLE_IF_RESIDENT	6
20 #define ESSA_SET_STABLE_NODAT		7
21 
22 #define ESSA_MAX	ESSA_SET_STABLE_NODAT
23 
24 extern int __bootdata_preserved(cmma_flag);
25 
essa(unsigned long paddr,unsigned char cmd)26 static __always_inline unsigned long essa(unsigned long paddr, unsigned char cmd)
27 {
28 	unsigned long rc;
29 
30 	asm volatile(
31 		"	.insn	rrf,0xb9ab0000,%[rc],%[paddr],%[cmd],0"
32 		: [rc] "=d" (rc)
33 		: [paddr] "d" (paddr),
34 		  [cmd] "i" (cmd));
35 	return rc;
36 }
37 
__set_page_state(void * addr,unsigned long num_pages,unsigned char cmd)38 static __always_inline void __set_page_state(void *addr, unsigned long num_pages, unsigned char cmd)
39 {
40 	unsigned long paddr = __pa(addr) & PAGE_MASK;
41 
42 	while (num_pages--) {
43 		essa(paddr, cmd);
44 		paddr += PAGE_SIZE;
45 	}
46 }
47 
__set_page_unused(void * addr,unsigned long num_pages)48 static inline void __set_page_unused(void *addr, unsigned long num_pages)
49 {
50 	__set_page_state(addr, num_pages, ESSA_SET_UNUSED);
51 }
52 
__set_page_stable_dat(void * addr,unsigned long num_pages)53 static inline void __set_page_stable_dat(void *addr, unsigned long num_pages)
54 {
55 	__set_page_state(addr, num_pages, ESSA_SET_STABLE);
56 }
57 
__set_page_stable_nodat(void * addr,unsigned long num_pages)58 static inline void __set_page_stable_nodat(void *addr, unsigned long num_pages)
59 {
60 	__set_page_state(addr, num_pages, ESSA_SET_STABLE_NODAT);
61 }
62 
__arch_set_page_nodat(void * addr,unsigned long num_pages)63 static inline void __arch_set_page_nodat(void *addr, unsigned long num_pages)
64 {
65 	if (!cmma_flag)
66 		return;
67 	if (cmma_flag < 2)
68 		__set_page_stable_dat(addr, num_pages);
69 	else
70 		__set_page_stable_nodat(addr, num_pages);
71 }
72 
__arch_set_page_dat(void * addr,unsigned long num_pages)73 static inline void __arch_set_page_dat(void *addr, unsigned long num_pages)
74 {
75 	if (!cmma_flag)
76 		return;
77 	__set_page_stable_dat(addr, num_pages);
78 }
79 
80 #endif
81