diff options
Diffstat (limited to 'arch/x86/mm')
| -rw-r--r-- | arch/x86/mm/fault.c | 2 | ||||
| -rw-r--r-- | arch/x86/mm/mem_encrypt_identity.c | 4 | ||||
| -rw-r--r-- | arch/x86/mm/pageattr.c | 50 |
3 files changed, 28 insertions, 28 deletions
diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c index 2ff25ad33233..9d5c75f02295 100644 --- a/arch/x86/mm/fault.c +++ b/arch/x86/mm/fault.c | |||
| @@ -595,7 +595,7 @@ static void show_ldttss(const struct desc_ptr *gdt, const char *name, u16 index) | |||
| 595 | return; | 595 | return; |
| 596 | } | 596 | } |
| 597 | 597 | ||
| 598 | addr = desc.base0 | (desc.base1 << 16) | (desc.base2 << 24); | 598 | addr = desc.base0 | (desc.base1 << 16) | ((unsigned long)desc.base2 << 24); |
| 599 | #ifdef CONFIG_X86_64 | 599 | #ifdef CONFIG_X86_64 |
| 600 | addr |= ((u64)desc.base3 << 32); | 600 | addr |= ((u64)desc.base3 << 32); |
| 601 | #endif | 601 | #endif |
diff --git a/arch/x86/mm/mem_encrypt_identity.c b/arch/x86/mm/mem_encrypt_identity.c index a19ef1a416ff..4aa9b1480866 100644 --- a/arch/x86/mm/mem_encrypt_identity.c +++ b/arch/x86/mm/mem_encrypt_identity.c | |||
| @@ -158,8 +158,8 @@ static void __init sme_populate_pgd(struct sme_populate_pgd_data *ppd) | |||
| 158 | pmd = pmd_offset(pud, ppd->vaddr); | 158 | pmd = pmd_offset(pud, ppd->vaddr); |
| 159 | if (pmd_none(*pmd)) { | 159 | if (pmd_none(*pmd)) { |
| 160 | pte = ppd->pgtable_area; | 160 | pte = ppd->pgtable_area; |
| 161 | memset(pte, 0, sizeof(pte) * PTRS_PER_PTE); | 161 | memset(pte, 0, sizeof(*pte) * PTRS_PER_PTE); |
| 162 | ppd->pgtable_area += sizeof(pte) * PTRS_PER_PTE; | 162 | ppd->pgtable_area += sizeof(*pte) * PTRS_PER_PTE; |
| 163 | set_pmd(pmd, __pmd(PMD_FLAGS | __pa(pte))); | 163 | set_pmd(pmd, __pmd(PMD_FLAGS | __pa(pte))); |
| 164 | } | 164 | } |
| 165 | 165 | ||
diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c index 4f8972311a77..14e6119838a6 100644 --- a/arch/x86/mm/pageattr.c +++ b/arch/x86/mm/pageattr.c | |||
| @@ -230,6 +230,29 @@ static bool __cpa_pfn_in_highmap(unsigned long pfn) | |||
| 230 | 230 | ||
| 231 | #endif | 231 | #endif |
| 232 | 232 | ||
| 233 | /* | ||
| 234 | * See set_mce_nospec(). | ||
| 235 | * | ||
| 236 | * Machine check recovery code needs to change cache mode of poisoned pages to | ||
| 237 | * UC to avoid speculative access logging another error. But passing the | ||
| 238 | * address of the 1:1 mapping to set_memory_uc() is a fine way to encourage a | ||
| 239 | * speculative access. So we cheat and flip the top bit of the address. This | ||
| 240 | * works fine for the code that updates the page tables. But at the end of the | ||
| 241 | * process we need to flush the TLB and cache and the non-canonical address | ||
| 242 | * causes a #GP fault when used by the INVLPG and CLFLUSH instructions. | ||
| 243 | * | ||
| 244 | * But in the common case we already have a canonical address. This code | ||
| 245 | * will fix the top bit if needed and is a no-op otherwise. | ||
| 246 | */ | ||
| 247 | static inline unsigned long fix_addr(unsigned long addr) | ||
| 248 | { | ||
| 249 | #ifdef CONFIG_X86_64 | ||
| 250 | return (long)(addr << 1) >> 1; | ||
| 251 | #else | ||
| 252 | return addr; | ||
| 253 | #endif | ||
| 254 | } | ||
| 255 | |||
| 233 | static unsigned long __cpa_addr(struct cpa_data *cpa, unsigned long idx) | 256 | static unsigned long __cpa_addr(struct cpa_data *cpa, unsigned long idx) |
| 234 | { | 257 | { |
| 235 | if (cpa->flags & CPA_PAGES_ARRAY) { | 258 | if (cpa->flags & CPA_PAGES_ARRAY) { |
| @@ -313,7 +336,7 @@ void __cpa_flush_tlb(void *data) | |||
| 313 | unsigned int i; | 336 | unsigned int i; |
| 314 | 337 | ||
| 315 | for (i = 0; i < cpa->numpages; i++) | 338 | for (i = 0; i < cpa->numpages; i++) |
| 316 | __flush_tlb_one_kernel(__cpa_addr(cpa, i)); | 339 | __flush_tlb_one_kernel(fix_addr(__cpa_addr(cpa, i))); |
| 317 | } | 340 | } |
| 318 | 341 | ||
| 319 | static void cpa_flush(struct cpa_data *data, int cache) | 342 | static void cpa_flush(struct cpa_data *data, int cache) |
| @@ -347,7 +370,7 @@ static void cpa_flush(struct cpa_data *data, int cache) | |||
| 347 | * Only flush present addresses: | 370 | * Only flush present addresses: |
| 348 | */ | 371 | */ |
| 349 | if (pte && (pte_val(*pte) & _PAGE_PRESENT)) | 372 | if (pte && (pte_val(*pte) & _PAGE_PRESENT)) |
| 350 | clflush_cache_range_opt((void *)addr, PAGE_SIZE); | 373 | clflush_cache_range_opt((void *)fix_addr(addr), PAGE_SIZE); |
| 351 | } | 374 | } |
| 352 | mb(); | 375 | mb(); |
| 353 | } | 376 | } |
| @@ -1627,29 +1650,6 @@ out: | |||
| 1627 | return ret; | 1650 | return ret; |
| 1628 | } | 1651 | } |
| 1629 | 1652 | ||
| 1630 | /* | ||
| 1631 | * Machine check recovery code needs to change cache mode of poisoned | ||
| 1632 | * pages to UC to avoid speculative access logging another error. But | ||
| 1633 | * passing the address of the 1:1 mapping to set_memory_uc() is a fine | ||
| 1634 | * way to encourage a speculative access. So we cheat and flip the top | ||
| 1635 | * bit of the address. This works fine for the code that updates the | ||
| 1636 | * page tables. But at the end of the process we need to flush the cache | ||
| 1637 | * and the non-canonical address causes a #GP fault when used by the | ||
| 1638 | * CLFLUSH instruction. | ||
| 1639 | * | ||
| 1640 | * But in the common case we already have a canonical address. This code | ||
| 1641 | * will fix the top bit if needed and is a no-op otherwise. | ||
| 1642 | */ | ||
| 1643 | static inline unsigned long make_addr_canonical_again(unsigned long addr) | ||
| 1644 | { | ||
| 1645 | #ifdef CONFIG_X86_64 | ||
| 1646 | return (long)(addr << 1) >> 1; | ||
| 1647 | #else | ||
| 1648 | return addr; | ||
| 1649 | #endif | ||
| 1650 | } | ||
| 1651 | |||
| 1652 | |||
| 1653 | static int change_page_attr_set_clr(unsigned long *addr, int numpages, | 1653 | static int change_page_attr_set_clr(unsigned long *addr, int numpages, |
| 1654 | pgprot_t mask_set, pgprot_t mask_clr, | 1654 | pgprot_t mask_set, pgprot_t mask_clr, |
| 1655 | int force_split, int in_flag, | 1655 | int force_split, int in_flag, |
