1 /*-
2  * Copyright (c) 2010 Isilon Systems, Inc.
3  * Copyright (c) 2016 Matt Macy (mmacy@nextbsd.org)
4  * Copyright (c) 2017 Mellanox Technologies, Ltd.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice unmodified, this list of conditions, and the following
12  *    disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 #ifndef _LINUXKPI_ASM_SET_MEMORY_H_
30 #define	_LINUXKPI_ASM_SET_MEMORY_H_
31 
32 #include <linux/page.h>
33 
34 static inline int
35 set_memory_uc(unsigned long addr, int numpages)
36 {
37 	vm_offset_t va;
38 	vm_size_t len;
39 
40 	va = PHYS_TO_DMAP(addr);
41 	len = numpages << PAGE_SHIFT;
42 
43 	return (-pmap_change_attr(va, len, VM_MEMATTR_UNCACHEABLE));
44 }
45 
46 static inline int
47 set_memory_wc(unsigned long addr, int numpages)
48 {
49 #ifdef VM_MEMATTR_WRITE_COMBINING
50 	vm_offset_t va;
51 	vm_size_t len;
52 
53 	va = PHYS_TO_DMAP(addr);
54 	len = numpages << PAGE_SHIFT;
55 
56 	return (-pmap_change_attr(va, len, VM_MEMATTR_WRITE_COMBINING));
57 #else
58 	return (set_memory_uc(addr, numpages));
59 #endif
60 }
61 
62 static inline int
63 set_memory_wb(unsigned long addr, int numpages)
64 {
65 	vm_offset_t va;
66 	vm_size_t len;
67 
68 	va = PHYS_TO_DMAP(addr);
69 	len = numpages << PAGE_SHIFT;
70 
71 	return (-pmap_change_attr(va, len, VM_MEMATTR_WRITE_BACK));
72 }
73 
74 static inline int
75 set_pages_uc(struct page *page, int numpages)
76 {
77 	KASSERT(numpages == 1, ("%s: numpages %d", __func__, numpages));
78 
79 	pmap_page_set_memattr(page, VM_MEMATTR_UNCACHEABLE);
80 	return (0);
81 }
82 
83 static inline int
84 set_pages_wc(struct page *page, int numpages)
85 {
86 	KASSERT(numpages == 1, ("%s: numpages %d", __func__, numpages));
87 
88 #ifdef VM_MEMATTR_WRITE_COMBINING
89 	pmap_page_set_memattr(page, VM_MEMATTR_WRITE_COMBINING);
90 #else
91 	return (set_pages_uc(page, numpages));
92 #endif
93 	return (0);
94 }
95 
96 static inline int
97 set_pages_wb(struct page *page, int numpages)
98 {
99 	KASSERT(numpages == 1, ("%s: numpages %d", __func__, numpages));
100 
101 	pmap_page_set_memattr(page, VM_MEMATTR_WRITE_BACK);
102 	return (0);
103 }
104 
105 static inline int
106 set_pages_array_wb(struct page **pages, int addrinarray)
107 {
108 	int i;
109 
110 	for (i = 0; i < addrinarray; i++)
111 		set_pages_wb(pages[i], 1);
112 	return (0);
113 }
114 
115 static inline int
116 set_pages_array_wc(struct page **pages, int addrinarray)
117 {
118 	int i;
119 
120 	for (i = 0; i < addrinarray; i++)
121 		set_pages_wc(pages[i], 1);
122 	return (0);
123 }
124 
125 static inline int
126 set_pages_array_uc(struct page **pages, int addrinarray)
127 {
128 	int i;
129 
130 	for (i = 0; i < addrinarray; i++)
131 		set_pages_uc(pages[i], 1);
132 	return (0);
133 }
134 
135 #endif	/* _LINUXKPI_ASM_SET_MEMORY_H_ */
136