diff options
Diffstat (limited to 'arch/x86/mm/kmmio.c')
-rw-r--r-- | arch/x86/mm/kmmio.c | 41 |
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 | ||
110 | static 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 | |||
120 | static 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 | |||
110 | static int set_page_presence(unsigned long addr, bool present, bool *old) | 130 | static 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 | ||