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