···11-/*22- * Written by: Patricia Gaughen <gone@us.ibm.com>, IBM Corporation33- * August 2002: added remote node KVA remap - Martin J. Bligh 44- *55- * Copyright (C) 2002, IBM Corp.66- *77- * All rights reserved. 88- *99- * This program is free software; you can redistribute it and/or modify1010- * it under the terms of the GNU General Public License as published by1111- * the Free Software Foundation; either version 2 of the License, or1212- * (at your option) any later version.1313- *1414- * This program is distributed in the hope that it will be useful, but1515- * WITHOUT ANY WARRANTY; without even the implied warranty of1616- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or1717- * NON INFRINGEMENT. See the GNU General Public License for more1818- * details.1919- *2020- * You should have received a copy of the GNU General Public License2121- * along with this program; if not, write to the Free Software2222- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.2323- */2424-2525-#include <linux/memblock.h>2626-#include <linux/init.h>2727-#include <linux/vmalloc.h>2828-#include <asm/pgtable_areas.h>2929-3030-#include "numa_internal.h"3131-3232-extern unsigned long highend_pfn, highstart_pfn;3333-3434-void __init initmem_init(void)3535-{3636- x86_numa_init();3737-3838-#ifdef CONFIG_HIGHMEM3939- highstart_pfn = highend_pfn = max_pfn;4040- if (max_pfn > max_low_pfn)4141- highstart_pfn = max_low_pfn;4242- printk(KERN_NOTICE "%ldMB HIGHMEM available.\n",4343- pages_to_mb(highend_pfn - highstart_pfn));4444- high_memory = (void *) __va(highstart_pfn * PAGE_SIZE - 1) + 1;4545-#else4646- high_memory = (void *) __va(max_low_pfn * PAGE_SIZE - 1) + 1;4747-#endif4848- printk(KERN_NOTICE "%ldMB LOWMEM available.\n",4949- pages_to_mb(max_low_pfn));5050- printk(KERN_DEBUG "max_low_pfn = %lx, highstart_pfn = %lx\n",5151- max_low_pfn, highstart_pfn);5252-5353- printk(KERN_DEBUG "Low memory ends at vaddr %08lx\n",5454- (ulong) pfn_to_kaddr(max_low_pfn));5555-5656- printk(KERN_DEBUG "High memory starts at vaddr %08lx\n",5757- (ulong) pfn_to_kaddr(highstart_pfn));5858-5959- __vmalloc_start_set = true;6060- setup_bootmem_allocator();6161-}
-13
arch/x86/mm/numa_64.c
···11-// SPDX-License-Identifier: GPL-2.022-/*33- * Generic VM initialization for x86-64 NUMA setups.44- * Copyright 2002,2003 Andi Kleen, SuSE Labs.55- */66-#include <linux/memblock.h>77-88-#include "numa_internal.h"99-1010-void __init initmem_init(void)1111-{1212- x86_numa_init();1313-}
···3838#include <linux/kernel.h>3939#include <linux/pfn_t.h>4040#include <linux/slab.h>4141+#include <linux/io.h>4142#include <linux/mm.h>4243#include <linux/highmem.h>4344#include <linux/fs.h>···774773 return vma_prot;775774}776775777777-#ifdef CONFIG_STRICT_DEVMEM778778-/* This check is done in drivers/char/mem.c in case of STRICT_DEVMEM */779779-static inline int range_is_allowed(unsigned long pfn, unsigned long size)780780-{781781- return 1;782782-}783783-#else784784-/* This check is needed to avoid cache aliasing when PAT is enabled */785785-static inline int range_is_allowed(unsigned long pfn, unsigned long size)786786-{787787- u64 from = ((u64)pfn) << PAGE_SHIFT;788788- u64 to = from + size;789789- u64 cursor = from;790790-791791- if (!pat_enabled())792792- return 1;793793-794794- while (cursor < to) {795795- if (!devmem_is_allowed(pfn))796796- return 0;797797- cursor += PAGE_SIZE;798798- pfn++;799799- }800800- return 1;801801-}802802-#endif /* CONFIG_STRICT_DEVMEM */803803-804776int phys_mem_access_prot_allowed(struct file *file, unsigned long pfn,805777 unsigned long size, pgprot_t *vma_prot)806778{807779 enum page_cache_mode pcm = _PAGE_CACHE_MODE_WB;780780+781781+ if (!pat_enabled())782782+ return 1;808783809784 if (!range_is_allowed(pfn, size))810785 return 0;
+2-2
arch/x86/mm/pat/set_memory.c
···889889 /* change init_mm */890890 set_pte_atomic(kpte, pte);891891#ifdef CONFIG_X86_32892892- if (!SHARED_KERNEL_PMD) {892892+ {893893 struct page *page;894894895895 list_for_each_entry(page, &pgd_list, lru) {···12931293 /* Queue the page table to be freed after TLB flush */12941294 list_add(&page_ptdesc(pmd_page(old_pmd))->pt_list, pgtables);1295129512961296- if (IS_ENABLED(CONFIG_X86_32) && !SHARED_KERNEL_PMD) {12961296+ if (IS_ENABLED(CONFIG_X86_32)) {12971297 struct page *page;1298129812991299 /* Update all PGD tables to use the same large page */
+16-87
arch/x86/mm/pgtable.c
···6969 list_del(&ptdesc->pt_list);7070}71717272-#define UNSHARED_PTRS_PER_PGD \7373- (SHARED_KERNEL_PMD ? KERNEL_PGD_BOUNDARY : PTRS_PER_PGD)7474-#define MAX_UNSHARED_PTRS_PER_PGD \7575- MAX_T(size_t, KERNEL_PGD_BOUNDARY, PTRS_PER_PGD)7676-7777-7872static void pgd_set_mm(pgd_t *pgd, struct mm_struct *mm)7973{8074 virt_to_ptdesc(pgd)->pt_mm = mm;···81878288static void pgd_ctor(struct mm_struct *mm, pgd_t *pgd)8389{8484- /* If the pgd points to a shared pagetable level (either the8585- ptes in non-PAE, or shared PMD in PAE), then just copy the8686- references from swapper_pg_dir. */8787- if (CONFIG_PGTABLE_LEVELS == 2 ||8888- (CONFIG_PGTABLE_LEVELS == 3 && SHARED_KERNEL_PMD) ||8989- CONFIG_PGTABLE_LEVELS >= 4) {9090+ /* PAE preallocates all its PMDs. No cloning needed. */9191+ if (!IS_ENABLED(CONFIG_X86_PAE))9092 clone_pgd_range(pgd + KERNEL_PGD_BOUNDARY,9193 swapper_pg_dir + KERNEL_PGD_BOUNDARY,9294 KERNEL_PGD_PTRS);9393- }94959595- /* list required to sync kernel mapping updates */9696- if (!SHARED_KERNEL_PMD) {9797- pgd_set_mm(pgd, mm);9898- pgd_list_add(pgd);9999- }9696+ /* List used to sync kernel mapping updates */9797+ pgd_set_mm(pgd, mm);9898+ pgd_list_add(pgd);10099}101100102101static void pgd_dtor(pgd_t *pgd)103102{104104- if (SHARED_KERNEL_PMD)105105- return;106106-107103 spin_lock(&pgd_lock);108104 pgd_list_del(pgd);109105 spin_unlock(&pgd_lock);···117133 * processor notices the update. Since this is expensive, and118134 * all 4 top-level entries are used almost immediately in a119135 * new process's life, we just pre-populate them here.120120- *121121- * Also, if we're in a paravirt environment where the kernel pmd is122122- * not shared between pagetables (!SHARED_KERNEL_PMDS), we allocate123123- * and initialize the kernel pmds here.124136 */125125-#define PREALLOCATED_PMDS UNSHARED_PTRS_PER_PGD126126-#define MAX_PREALLOCATED_PMDS MAX_UNSHARED_PTRS_PER_PGD137137+#define PREALLOCATED_PMDS PTRS_PER_PGD127138128139/*140140+ * "USER_PMDS" are the PMDs for the user copy of the page tables when141141+ * PTI is enabled. They do not exist when PTI is disabled. Note that142142+ * this is distinct from the user _portion_ of the kernel page tables143143+ * which always exists.144144+ *129145 * We allocate separate PMDs for the kernel part of the user page-table130146 * when PTI is enabled. We need them to map the per-process LDT into the131147 * user-space page-table.···154170155171/* No need to prepopulate any pagetable entries in non-PAE modes. */156172#define PREALLOCATED_PMDS 0157157-#define MAX_PREALLOCATED_PMDS 0158173#define PREALLOCATED_USER_PMDS 0159174#define MAX_PREALLOCATED_USER_PMDS 0160175#endif /* CONFIG_X86_PAE */···302319{303320}304321#endif305305-/*306306- * Xen paravirt assumes pgd table should be in one page. 64 bit kernel also307307- * assumes that pgd should be in one page.308308- *309309- * But kernel with PAE paging that is not running as a Xen domain310310- * only needs to allocate 32 bytes for pgd instead of one page.311311- */312312-#ifdef CONFIG_X86_PAE313313-314314-#include <linux/slab.h>315315-316316-#define PGD_SIZE (PTRS_PER_PGD * sizeof(pgd_t))317317-#define PGD_ALIGN 32318318-319319-static struct kmem_cache *pgd_cache;320320-321321-void __init pgtable_cache_init(void)322322-{323323- /*324324- * When PAE kernel is running as a Xen domain, it does not use325325- * shared kernel pmd. And this requires a whole page for pgd.326326- */327327- if (!SHARED_KERNEL_PMD)328328- return;329329-330330- /*331331- * when PAE kernel is not running as a Xen domain, it uses332332- * shared kernel pmd. Shared kernel pmd does not require a whole333333- * page for pgd. We are able to just allocate a 32-byte for pgd.334334- * During boot time, we create a 32-byte slab for pgd table allocation.335335- */336336- pgd_cache = kmem_cache_create("pgd_cache", PGD_SIZE, PGD_ALIGN,337337- SLAB_PANIC, NULL);338338-}339322340323static inline pgd_t *_pgd_alloc(struct mm_struct *mm)341324{342325 /*343343- * If no SHARED_KERNEL_PMD, PAE kernel is running as a Xen domain.344344- * We allocate one page for pgd.326326+ * PTI and Xen need a whole page for the PAE PGD327327+ * even though the hardware only needs 32 bytes.328328+ *329329+ * For simplicity, allocate a page for all users.345330 */346346- if (!SHARED_KERNEL_PMD)347347- return __pgd_alloc(mm, pgd_allocation_order());348348-349349- /*350350- * Now PAE kernel is not running as a Xen domain. We can allocate351351- * a 32-byte slab for pgd to save memory space.352352- */353353- return kmem_cache_alloc(pgd_cache, GFP_PGTABLE_USER);354354-}355355-356356-static inline void _pgd_free(struct mm_struct *mm, pgd_t *pgd)357357-{358358- if (!SHARED_KERNEL_PMD)359359- __pgd_free(mm, pgd);360360- else361361- kmem_cache_free(pgd_cache, pgd);362362-}363363-#else364364-365365-static inline pgd_t *_pgd_alloc(struct mm_struct *mm)366366-{367331 return __pgd_alloc(mm, pgd_allocation_order());368332}369333···318388{319389 __pgd_free(mm, pgd);320390}321321-#endif /* CONFIG_X86_PAE */322391323392pgd_t *pgd_alloc(struct mm_struct *mm)324393{325394 pgd_t *pgd;326395 pmd_t *u_pmds[MAX_PREALLOCATED_USER_PMDS];327327- pmd_t *pmds[MAX_PREALLOCATED_PMDS];396396+ pmd_t *pmds[PREALLOCATED_PMDS];328397329398 pgd = _pgd_alloc(mm);330399
+2-2
arch/x86/mm/pti.c
···185185186186 set_pgd(pgd, __pgd(_KERNPG_TABLE | __pa(new_p4d_page)));187187 }188188- BUILD_BUG_ON(pgd_leaf(*pgd) != 0);188188+ BUILD_BUG_ON(pgd_leaf(*pgd));189189190190 return p4d_offset(pgd, address);191191}···206206 if (!p4d)207207 return NULL;208208209209- BUILD_BUG_ON(p4d_leaf(*p4d) != 0);209209+ BUILD_BUG_ON(p4d_leaf(*p4d));210210 if (p4d_none(*p4d)) {211211 unsigned long new_pud_page = __get_free_page(gfp);212212 if (WARN_ON_ONCE(!new_pud_page))
+34-29
arch/x86/mm/tlb.c
···215215216216atomic64_t last_mm_ctx_id = ATOMIC64_INIT(1);217217218218+struct new_asid {219219+ unsigned int asid : 16;220220+ unsigned int need_flush : 1;221221+};218222219219-static void choose_new_asid(struct mm_struct *next, u64 next_tlb_gen,220220- u16 *new_asid, bool *need_flush)223223+static struct new_asid choose_new_asid(struct mm_struct *next, u64 next_tlb_gen)221224{225225+ struct new_asid ns;222226 u16 asid;223227224228 if (!static_cpu_has(X86_FEATURE_PCID)) {225225- *new_asid = 0;226226- *need_flush = true;227227- return;229229+ ns.asid = 0;230230+ ns.need_flush = 1;231231+ return ns;228232 }229233230234 /*···239235 u16 global_asid = mm_global_asid(next);240236241237 if (global_asid) {242242- *new_asid = global_asid;243243- *need_flush = false;244244- return;238238+ ns.asid = global_asid;239239+ ns.need_flush = 0;240240+ return ns;245241 }246242 }247243···253249 next->context.ctx_id)254250 continue;255251256256- *new_asid = asid;257257- *need_flush = (this_cpu_read(cpu_tlbstate.ctxs[asid].tlb_gen) <258258- next_tlb_gen);259259- return;252252+ ns.asid = asid;253253+ ns.need_flush = (this_cpu_read(cpu_tlbstate.ctxs[asid].tlb_gen) < next_tlb_gen);254254+ return ns;260255 }261256262257 /*263258 * We don't currently own an ASID slot on this CPU.264259 * Allocate a slot.265260 */266266- *new_asid = this_cpu_add_return(cpu_tlbstate.next_asid, 1) - 1;267267- if (*new_asid >= TLB_NR_DYN_ASIDS) {268268- *new_asid = 0;261261+ ns.asid = this_cpu_add_return(cpu_tlbstate.next_asid, 1) - 1;262262+ if (ns.asid >= TLB_NR_DYN_ASIDS) {263263+ ns.asid = 0;269264 this_cpu_write(cpu_tlbstate.next_asid, 1);270265 }271271- *need_flush = true;266266+ ns.need_flush = true;267267+268268+ return ns;272269}273270274271/*···786781 bool was_lazy = this_cpu_read(cpu_tlbstate_shared.is_lazy);787782 unsigned cpu = smp_processor_id();788783 unsigned long new_lam;784784+ struct new_asid ns;789785 u64 next_tlb_gen;790790- bool need_flush;791791- u16 new_asid;786786+792787793788 /* We don't want flush_tlb_func() to run concurrently with us. */794789 if (IS_ENABLED(CONFIG_PROVE_LOCKING))···860855 /* Check if the current mm is transitioning to a global ASID */861856 if (mm_needs_global_asid(next, prev_asid)) {862857 next_tlb_gen = atomic64_read(&next->context.tlb_gen);863863- choose_new_asid(next, next_tlb_gen, &new_asid, &need_flush);858858+ ns = choose_new_asid(next, next_tlb_gen);864859 goto reload_tlb;865860 }866861···895890 * TLB contents went out of date while we were in lazy896891 * mode. Fall through to the TLB switching code below.897892 */898898- new_asid = prev_asid;899899- need_flush = true;893893+ ns.asid = prev_asid;894894+ ns.need_flush = true;900895 } else {901896 /*902897 * Apply process to process speculation vulnerability···917912 cpumask_set_cpu(cpu, mm_cpumask(next));918913 next_tlb_gen = atomic64_read(&next->context.tlb_gen);919914920920- choose_new_asid(next, next_tlb_gen, &new_asid, &need_flush);915915+ ns = choose_new_asid(next, next_tlb_gen);921916 }922917923918reload_tlb:924919 new_lam = mm_lam_cr3_mask(next);925925- if (need_flush) {926926- VM_WARN_ON_ONCE(is_global_asid(new_asid));927927- this_cpu_write(cpu_tlbstate.ctxs[new_asid].ctx_id, next->context.ctx_id);928928- this_cpu_write(cpu_tlbstate.ctxs[new_asid].tlb_gen, next_tlb_gen);929929- load_new_mm_cr3(next->pgd, new_asid, new_lam, true);920920+ if (ns.need_flush) {921921+ VM_WARN_ON_ONCE(is_global_asid(ns.asid));922922+ this_cpu_write(cpu_tlbstate.ctxs[ns.asid].ctx_id, next->context.ctx_id);923923+ this_cpu_write(cpu_tlbstate.ctxs[ns.asid].tlb_gen, next_tlb_gen);924924+ load_new_mm_cr3(next->pgd, ns.asid, new_lam, true);930925931926 trace_tlb_flush(TLB_FLUSH_ON_TASK_SWITCH, TLB_FLUSH_ALL);932927 } else {933928 /* The new ASID is already up to date. */934934- load_new_mm_cr3(next->pgd, new_asid, new_lam, false);929929+ load_new_mm_cr3(next->pgd, ns.asid, new_lam, false);935930936931 trace_tlb_flush(TLB_FLUSH_ON_TASK_SWITCH, 0);937932 }···940935 barrier();941936942937 this_cpu_write(cpu_tlbstate.loaded_mm, next);943943- this_cpu_write(cpu_tlbstate.loaded_mm_asid, new_asid);938938+ this_cpu_write(cpu_tlbstate.loaded_mm_asid, ns.asid);944939 cpu_tlbstate_update_lam(new_lam, mm_untag_mask(next));945940946941 if (next != prev) {
-18
drivers/char/mem.c
···6161{6262 return devmem_is_allowed(pfn);6363}6464-static inline int range_is_allowed(unsigned long pfn, unsigned long size)6565-{6666- u64 from = ((u64)pfn) << PAGE_SHIFT;6767- u64 to = from + size;6868- u64 cursor = from;6969-7070- while (cursor < to) {7171- if (!devmem_is_allowed(pfn))7272- return 0;7373- cursor += PAGE_SIZE;7474- pfn++;7575- }7676- return 1;7777-}7864#else7965static inline int page_is_allowed(unsigned long pfn)8080-{8181- return 1;8282-}8383-static inline int range_is_allowed(unsigned long pfn, unsigned long size)8466{8567 return 1;8668}
+21
include/linux/io.h
···183183int devm_arch_io_reserve_memtype_wc(struct device *dev, resource_size_t start,184184 resource_size_t size);185185186186+#ifdef CONFIG_STRICT_DEVMEM187187+static inline int range_is_allowed(unsigned long pfn, unsigned long size)188188+{189189+ u64 from = ((u64)pfn) << PAGE_SHIFT;190190+ u64 to = from + size;191191+ u64 cursor = from;192192+193193+ while (cursor < to) {194194+ if (!devmem_is_allowed(pfn))195195+ return 0;196196+ cursor += PAGE_SIZE;197197+ pfn++;198198+ }199199+ return 1;200200+}201201+#else202202+static inline int range_is_allowed(unsigned long pfn, unsigned long size)203203+{204204+ return 1;205205+}206206+#endif186207#endif /* _LINUX_IO_H */