aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/mm/kmmio.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/mm/kmmio.c')
-rw-r--r--arch/x86/mm/kmmio.c41
1 files changed, 22 insertions, 19 deletions
diff --git a/arch/x86/mm/kmmio.c b/arch/x86/mm/kmmio.c
index be361eb828c8..d29777520af3 100644
--- a/arch/x86/mm/kmmio.c
+++ b/arch/x86/mm/kmmio.c
@@ -107,12 +107,29 @@ static struct kmmio_fault_page *get_kmmio_fault_page(unsigned long page)
107 return NULL; 107 return NULL;
108} 108}
109 109
110static void set_pmd_presence(pmd_t *pmd, bool present, bool *old)
111{
112 pmdval_t v = pmd_val(*pmd);
113 *old = !!(v & _PAGE_PRESENT);
114 v &= ~_PAGE_PRESENT;
115 if (present)
116 v |= _PAGE_PRESENT;
117 set_pmd(pmd, __pmd(v));
118}
119
120static void set_pte_presence(pte_t *pte, bool present, bool *old)
121{
122 pteval_t v = pte_val(*pte);
123 *old = !!(v & _PAGE_PRESENT);
124 v &= ~_PAGE_PRESENT;
125 if (present)
126 v |= _PAGE_PRESENT;
127 set_pte_atomic(pte, __pte(v));
128}
129
110static int set_page_presence(unsigned long addr, bool present, bool *old) 130static int set_page_presence(unsigned long addr, bool present, bool *old)
111{ 131{
112 pteval_t pteval;
113 pmdval_t pmdval;
114 unsigned int level; 132 unsigned int level;
115 pmd_t *pmd;
116 pte_t *pte = lookup_address(addr, &level); 133 pte_t *pte = lookup_address(addr, &level);
117 134
118 if (!pte) { 135 if (!pte) {
@@ -122,31 +139,17 @@ static int set_page_presence(unsigned long addr, bool present, bool *old)
122 139
123 switch (level) { 140 switch (level) {
124 case PG_LEVEL_2M: 141 case PG_LEVEL_2M:
125 pmd = (pmd_t *)pte; 142 set_pmd_presence((pmd_t *)pte, present, old);
126 pmdval = pmd_val(*pmd);
127 *old = !!(pmdval & _PAGE_PRESENT);
128 pmdval &= ~_PAGE_PRESENT;
129 if (present)
130 pmdval |= _PAGE_PRESENT;
131 set_pmd(pmd, __pmd(pmdval));
132 break; 143 break;
133
134 case PG_LEVEL_4K: 144 case PG_LEVEL_4K:
135 pteval = pte_val(*pte); 145 set_pte_presence(pte, present, old);
136 *old = !!(pteval & _PAGE_PRESENT);
137 pteval &= ~_PAGE_PRESENT;
138 if (present)
139 pteval |= _PAGE_PRESENT;
140 set_pte_atomic(pte, __pte(pteval));
141 break; 146 break;
142
143 default: 147 default:
144 pr_err("kmmio: unexpected page level 0x%x.\n", level); 148 pr_err("kmmio: unexpected page level 0x%x.\n", level);
145 return -1; 149 return -1;
146 } 150 }
147 151
148 __flush_tlb_one(addr); 152 __flush_tlb_one(addr);
149
150 return 0; 153 return 0;
151} 154}
152 155