diff options
Diffstat (limited to 'arch/x86/kernel/espfix_64.c')
| -rw-r--r-- | arch/x86/kernel/espfix_64.c | 28 |
1 files changed, 16 insertions, 12 deletions
diff --git a/arch/x86/kernel/espfix_64.c b/arch/x86/kernel/espfix_64.c index f5d0730e7b08..ce95676abd60 100644 --- a/arch/x86/kernel/espfix_64.c +++ b/arch/x86/kernel/espfix_64.c | |||
| @@ -131,25 +131,24 @@ void __init init_espfix_bsp(void) | |||
| 131 | init_espfix_random(); | 131 | init_espfix_random(); |
| 132 | 132 | ||
| 133 | /* The rest is the same as for any other processor */ | 133 | /* The rest is the same as for any other processor */ |
| 134 | init_espfix_ap(); | 134 | init_espfix_ap(0); |
| 135 | } | 135 | } |
| 136 | 136 | ||
| 137 | void init_espfix_ap(void) | 137 | void init_espfix_ap(int cpu) |
| 138 | { | 138 | { |
| 139 | unsigned int cpu, page; | 139 | unsigned int page; |
| 140 | unsigned long addr; | 140 | unsigned long addr; |
| 141 | pud_t pud, *pud_p; | 141 | pud_t pud, *pud_p; |
| 142 | pmd_t pmd, *pmd_p; | 142 | pmd_t pmd, *pmd_p; |
| 143 | pte_t pte, *pte_p; | 143 | pte_t pte, *pte_p; |
| 144 | int n; | 144 | int n, node; |
| 145 | void *stack_page; | 145 | void *stack_page; |
| 146 | pteval_t ptemask; | 146 | pteval_t ptemask; |
| 147 | 147 | ||
| 148 | /* We only have to do this once... */ | 148 | /* We only have to do this once... */ |
| 149 | if (likely(this_cpu_read(espfix_stack))) | 149 | if (likely(per_cpu(espfix_stack, cpu))) |
| 150 | return; /* Already initialized */ | 150 | return; /* Already initialized */ |
| 151 | 151 | ||
| 152 | cpu = smp_processor_id(); | ||
| 153 | addr = espfix_base_addr(cpu); | 152 | addr = espfix_base_addr(cpu); |
| 154 | page = cpu/ESPFIX_STACKS_PER_PAGE; | 153 | page = cpu/ESPFIX_STACKS_PER_PAGE; |
| 155 | 154 | ||
| @@ -165,12 +164,15 @@ void init_espfix_ap(void) | |||
| 165 | if (stack_page) | 164 | if (stack_page) |
| 166 | goto unlock_done; | 165 | goto unlock_done; |
| 167 | 166 | ||
| 167 | node = cpu_to_node(cpu); | ||
| 168 | ptemask = __supported_pte_mask; | 168 | ptemask = __supported_pte_mask; |
| 169 | 169 | ||
| 170 | pud_p = &espfix_pud_page[pud_index(addr)]; | 170 | pud_p = &espfix_pud_page[pud_index(addr)]; |
| 171 | pud = *pud_p; | 171 | pud = *pud_p; |
| 172 | if (!pud_present(pud)) { | 172 | if (!pud_present(pud)) { |
| 173 | pmd_p = (pmd_t *)__get_free_page(PGALLOC_GFP); | 173 | struct page *page = alloc_pages_node(node, PGALLOC_GFP, 0); |
| 174 | |||
| 175 | pmd_p = (pmd_t *)page_address(page); | ||
| 174 | pud = __pud(__pa(pmd_p) | (PGTABLE_PROT & ptemask)); | 176 | pud = __pud(__pa(pmd_p) | (PGTABLE_PROT & ptemask)); |
| 175 | paravirt_alloc_pmd(&init_mm, __pa(pmd_p) >> PAGE_SHIFT); | 177 | paravirt_alloc_pmd(&init_mm, __pa(pmd_p) >> PAGE_SHIFT); |
| 176 | for (n = 0; n < ESPFIX_PUD_CLONES; n++) | 178 | for (n = 0; n < ESPFIX_PUD_CLONES; n++) |
| @@ -180,7 +182,9 @@ void init_espfix_ap(void) | |||
| 180 | pmd_p = pmd_offset(&pud, addr); | 182 | pmd_p = pmd_offset(&pud, addr); |
| 181 | pmd = *pmd_p; | 183 | pmd = *pmd_p; |
| 182 | if (!pmd_present(pmd)) { | 184 | if (!pmd_present(pmd)) { |
| 183 | pte_p = (pte_t *)__get_free_page(PGALLOC_GFP); | 185 | struct page *page = alloc_pages_node(node, PGALLOC_GFP, 0); |
| 186 | |||
| 187 | pte_p = (pte_t *)page_address(page); | ||
| 184 | pmd = __pmd(__pa(pte_p) | (PGTABLE_PROT & ptemask)); | 188 | pmd = __pmd(__pa(pte_p) | (PGTABLE_PROT & ptemask)); |
| 185 | paravirt_alloc_pte(&init_mm, __pa(pte_p) >> PAGE_SHIFT); | 189 | paravirt_alloc_pte(&init_mm, __pa(pte_p) >> PAGE_SHIFT); |
| 186 | for (n = 0; n < ESPFIX_PMD_CLONES; n++) | 190 | for (n = 0; n < ESPFIX_PMD_CLONES; n++) |
| @@ -188,7 +192,7 @@ void init_espfix_ap(void) | |||
| 188 | } | 192 | } |
| 189 | 193 | ||
| 190 | pte_p = pte_offset_kernel(&pmd, addr); | 194 | pte_p = pte_offset_kernel(&pmd, addr); |
| 191 | stack_page = (void *)__get_free_page(GFP_KERNEL); | 195 | stack_page = page_address(alloc_pages_node(node, GFP_KERNEL, 0)); |
| 192 | pte = __pte(__pa(stack_page) | (__PAGE_KERNEL_RO & ptemask)); | 196 | pte = __pte(__pa(stack_page) | (__PAGE_KERNEL_RO & ptemask)); |
| 193 | for (n = 0; n < ESPFIX_PTE_CLONES; n++) | 197 | for (n = 0; n < ESPFIX_PTE_CLONES; n++) |
| 194 | set_pte(&pte_p[n*PTE_STRIDE], pte); | 198 | set_pte(&pte_p[n*PTE_STRIDE], pte); |
| @@ -199,7 +203,7 @@ void init_espfix_ap(void) | |||
| 199 | unlock_done: | 203 | unlock_done: |
| 200 | mutex_unlock(&espfix_init_mutex); | 204 | mutex_unlock(&espfix_init_mutex); |
| 201 | done: | 205 | done: |
| 202 | this_cpu_write(espfix_stack, addr); | 206 | per_cpu(espfix_stack, cpu) = addr; |
| 203 | this_cpu_write(espfix_waddr, (unsigned long)stack_page | 207 | per_cpu(espfix_waddr, cpu) = (unsigned long)stack_page |
| 204 | + (addr & ~PAGE_MASK)); | 208 | + (addr & ~PAGE_MASK); |
| 205 | } | 209 | } |
