Update Linux kernel release to v7.2.8-2 for base and BORE kernels
Signed-off-by: Krzysztof Wilczyński <kwilczynski@omarchy.org>
This commit is contained in:
524 files changed
+147294
-88760
No files matched your search
@@ -22,19 +22,6 @@ diff --git a/arch/x86/include/asm/pgtable_types.h b/arch/x86/include/asm/pgtable
|
||||
typedef struct page *pgtable_t;
|
||||
|
||||
extern pteval_t __supported_pte_mask;
|
||||
diff --git a/arch/x86/include/asm/pkeys.h b/arch/x86/include/asm/pkeys.h
|
||||
--- a/arch/x86/include/asm/pkeys.h
|
||||
+++ b/arch/x86/include/asm/pkeys.h
|
||||
@@ -88,6 +88,9 @@ int mm_pkey_alloc(struct mm_struct *mm)
|
||||
u16 all_pkeys_mask = ((1U << arch_max_pkey()) - 1);
|
||||
int ret;
|
||||
|
||||
+ if (!arch_pkeys_enabled())
|
||||
+ return -1;
|
||||
+
|
||||
/*
|
||||
* Are we out of pkeys? We must handle this specially
|
||||
* because ffz() behavior is undefined if there are no
|
||||
diff --git a/arch/x86/include/asm/tlbflush.h b/arch/x86/include/asm/tlbflush.h
|
||||
--- a/arch/x86/include/asm/tlbflush.h
|
||||
+++ b/arch/x86/include/asm/tlbflush.h
|
||||
@@ -168,35 +155,7 @@ diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c
|
||||
diff --git a/arch/x86/mm/pat/set_memory.c b/arch/x86/mm/pat/set_memory.c
|
||||
--- a/arch/x86/mm/pat/set_memory.c
|
||||
+++ b/arch/x86/mm/pat/set_memory.c
|
||||
@@ -62,18 +62,18 @@ enum cpa_warn {
|
||||
static const int cpa_warn_level = CPA_PROTECT;
|
||||
|
||||
/*
|
||||
- * Serialize cpa() (for !DEBUG_PAGEALLOC which uses large identity mappings)
|
||||
- * using cpa_lock. So that we don't allow any other cpu, with stale large tlb
|
||||
- * entries change the page attribute in parallel to some other cpu
|
||||
- * splitting a large page entry along with changing the attribute.
|
||||
+ * Serialize cpa() using cpa_lock so that we don't allow any other cpu, with
|
||||
+ * stale large tlb entries, to change the page attribute in parallel to some
|
||||
+ * other cpu splitting a large page entry along with changing the attribute.
|
||||
*/
|
||||
static DEFINE_SPINLOCK(cpa_lock);
|
||||
|
||||
-#define CPA_FLUSHTLB 1
|
||||
-#define CPA_ARRAY 2
|
||||
-#define CPA_PAGES_ARRAY 4
|
||||
-#define CPA_NO_CHECK_ALIAS 8 /* Do not search for aliases */
|
||||
-#define CPA_COLLAPSE 16 /* try to collapse large pages */
|
||||
+#define CPA_FLUSHTLB 0x01
|
||||
+#define CPA_ARRAY 0x02
|
||||
+#define CPA_PAGES_ARRAY 0x04
|
||||
+#define CPA_NO_CHECK_ALIAS 0x08 /* Do not search for aliases */
|
||||
+#define CPA_COLLAPSE 0x10 /* try to collapse large pages */
|
||||
+#define CPA_DEBUG_PAGEALLOC 0x20
|
||||
|
||||
static inline pgprot_t cachemode2pgprot(enum page_cache_mode pcm)
|
||||
{
|
||||
@@ -86,9 +86,8 @@ static unsigned long direct_pages_count[PG_LEVEL_NUM];
|
||||
@@ -88,9 +88,8 @@ static unsigned long direct_pages_count[PG_LEVEL_NUM];
|
||||
void update_page_count(int level, unsigned long pages)
|
||||
{
|
||||
/* Protect against CPA */
|
||||
@@ -207,16 +166,37 @@ diff --git a/arch/x86/mm/pat/set_memory.c b/arch/x86/mm/pat/set_memory.c
|
||||
}
|
||||
|
||||
static void split_page_count(int level)
|
||||
@@ -418,6 +417,8 @@ static void cpa_collapse_large_pages(struct cpa_data *cpa)
|
||||
@@ -420,7 +419,7 @@ static void __cpa_collapse_large_pages(struct cpa_data *cpa)
|
||||
int collapsed = 0;
|
||||
int i;
|
||||
|
||||
- spin_lock(&cpa_lock);
|
||||
+ guard(spinlock)(&cpa_lock);
|
||||
+
|
||||
|
||||
if (cpa->flags & (CPA_PAGES_ARRAY | CPA_ARRAY)) {
|
||||
for (i = 0; i < cpa->numpages; i++)
|
||||
collapsed += collapse_large_pages(__cpa_addr(cpa, i),
|
||||
@@ -888,24 +889,23 @@ static void __set_pmd_pte(pte_t *kpte, unsigned long address, pte_t pte)
|
||||
@@ -435,10 +434,8 @@ static void __cpa_collapse_large_pages(struct cpa_data *cpa)
|
||||
collapsed += collapse_large_pages(addr, &pgtables);
|
||||
}
|
||||
|
||||
- if (!collapsed) {
|
||||
- spin_unlock(&cpa_lock);
|
||||
+ if (!collapsed)
|
||||
return;
|
||||
- }
|
||||
|
||||
flush_tlb_all();
|
||||
|
||||
@@ -454,8 +451,6 @@ static void __cpa_collapse_large_pages(struct cpa_data *cpa)
|
||||
else
|
||||
pagetable_free(ptdesc);
|
||||
}
|
||||
-
|
||||
- spin_unlock(&cpa_lock);
|
||||
}
|
||||
|
||||
static void cpa_collapse_large_pages(struct cpa_data *cpa)
|
||||
@@ -916,24 +911,23 @@ static void __set_pmd_pte(pte_t *kpte, unsigned long address, pte_t pte)
|
||||
{
|
||||
/* change init_mm */
|
||||
set_pte_atomic(kpte, pte);
|
||||
@@ -246,7 +226,7 @@ diff --git a/arch/x86/mm/pat/set_memory.c b/arch/x86/mm/pat/set_memory.c
|
||||
}
|
||||
|
||||
static pgprot_t pgprot_clear_protnone_bits(pgprot_t prot)
|
||||
@@ -1075,16 +1075,11 @@ static int __should_split_large_page(pte_t *kpte, unsigned long address,
|
||||
@@ -1103,16 +1097,11 @@ static int __should_split_large_page(pte_t *kpte, unsigned long address,
|
||||
static int should_split_large_page(pte_t *kpte, unsigned long address,
|
||||
struct cpa_data *cpa)
|
||||
{
|
||||
@@ -265,7 +245,7 @@ diff --git a/arch/x86/mm/pat/set_memory.c b/arch/x86/mm/pat/set_memory.c
|
||||
}
|
||||
|
||||
static void split_set_pte(struct cpa_data *cpa, pte_t *pte, unsigned long pfn,
|
||||
@@ -1135,16 +1130,14 @@ __split_large_page(struct cpa_data *cpa, pte_t *kpte, unsigned long address,
|
||||
@@ -1162,16 +1151,14 @@ __split_large_page(struct cpa_data *cpa, pte_t *kpte, unsigned long address,
|
||||
bool nx, rw;
|
||||
pte_t *tmp;
|
||||
|
||||
@@ -284,7 +264,7 @@ diff --git a/arch/x86/mm/pat/set_memory.c b/arch/x86/mm/pat/set_memory.c
|
||||
|
||||
paravirt_alloc_pte(&init_mm, page_to_pfn(base));
|
||||
|
||||
@@ -1177,7 +1170,6 @@ __split_large_page(struct cpa_data *cpa, pte_t *kpte, unsigned long address,
|
||||
@@ -1204,7 +1191,6 @@ __split_large_page(struct cpa_data *cpa, pte_t *kpte, unsigned long address,
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -292,7 +272,7 @@ diff --git a/arch/x86/mm/pat/set_memory.c b/arch/x86/mm/pat/set_memory.c
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -1225,7 +1217,6 @@ __split_large_page(struct cpa_data *cpa, pte_t *kpte, unsigned long address,
|
||||
@@ -1252,7 +1238,6 @@ __split_large_page(struct cpa_data *cpa, pte_t *kpte, unsigned long address,
|
||||
* just split large page entry.
|
||||
*/
|
||||
flush_tlb_all();
|
||||
@@ -300,21 +280,7 @@ diff --git a/arch/x86/mm/pat/set_memory.c b/arch/x86/mm/pat/set_memory.c
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1235,11 +1226,9 @@ static int split_large_page(struct cpa_data *cpa, pte_t *kpte,
|
||||
{
|
||||
struct ptdesc *ptdesc;
|
||||
|
||||
- if (!debug_pagealloc_enabled())
|
||||
- spin_unlock(&cpa_lock);
|
||||
+ spin_unlock(&cpa_lock);
|
||||
ptdesc = pagetable_alloc(GFP_KERNEL, 0);
|
||||
- if (!debug_pagealloc_enabled())
|
||||
- spin_lock(&cpa_lock);
|
||||
+ spin_lock(&cpa_lock);
|
||||
if (!ptdesc)
|
||||
return -ENOMEM;
|
||||
|
||||
@@ -1298,11 +1287,11 @@ static int collapse_pmd_page(pmd_t *pmd, unsigned long addr,
|
||||
@@ -1327,11 +1312,11 @@ static int collapse_pmd_page(pmd_t *pmd, unsigned long addr,
|
||||
list_add(&page_ptdesc(pmd_page(old_pmd))->pt_list, pgtables);
|
||||
|
||||
if (IS_ENABLED(CONFIG_X86_32)) {
|
||||
@@ -329,7 +295,7 @@ diff --git a/arch/x86/mm/pat/set_memory.c b/arch/x86/mm/pat/set_memory.c
|
||||
p4d_t *p4d = p4d_offset(pgd, addr);
|
||||
pud_t *pud = pud_offset(p4d, addr);
|
||||
pmd_t *pmd = pmd_offset(pud, addr);
|
||||
@@ -1376,7 +1365,7 @@ static int collapse_pud_page(pud_t *pud, unsigned long addr,
|
||||
@@ -1405,7 +1390,7 @@ static int collapse_pud_page(pud_t *pud, unsigned long addr,
|
||||
*/
|
||||
static int collapse_large_pages(unsigned long addr, struct list_head *pgtables)
|
||||
{
|
||||
@@ -338,7 +304,7 @@ diff --git a/arch/x86/mm/pat/set_memory.c b/arch/x86/mm/pat/set_memory.c
|
||||
pgd_t *pgd;
|
||||
p4d_t *p4d;
|
||||
pud_t *pud;
|
||||
@@ -1384,26 +1373,24 @@ static int collapse_large_pages(unsigned long addr, struct list_head *pgtables)
|
||||
@@ -1413,26 +1398,24 @@ static int collapse_large_pages(unsigned long addr, struct list_head *pgtables)
|
||||
|
||||
addr &= PMD_MASK;
|
||||
|
||||
@@ -370,153 +336,6 @@ diff --git a/arch/x86/mm/pat/set_memory.c b/arch/x86/mm/pat/set_memory.c
|
||||
return collapsed;
|
||||
}
|
||||
|
||||
@@ -2004,6 +1991,7 @@ static int __change_page_attr_set_clr(struct cpa_data *cpa, int primary)
|
||||
{
|
||||
unsigned long numpages = cpa->numpages;
|
||||
unsigned long rempages = numpages;
|
||||
+ bool lock = true;
|
||||
int ret = 0;
|
||||
|
||||
/*
|
||||
@@ -2013,6 +2001,29 @@ static int __change_page_attr_set_clr(struct cpa_data *cpa, int primary)
|
||||
!cpa->force_split)
|
||||
return ret;
|
||||
|
||||
+ /*
|
||||
+ * DEBUG_PAGEALLOC is special; it is called from any context the
|
||||
+ * page-allocator is, which violates the normal cpa_lock locking
|
||||
+ * rules.
|
||||
+ *
|
||||
+ * However, since it is part of the page-allocator, things are still
|
||||
+ * properly serialized by the page-allocator locking and the fact that
|
||||
+ * when a page is owned by the page-allocator, it isn't owned by
|
||||
+ * anybody else. That is, you *SHOULD NOT* be calling cpa() on memory
|
||||
+ * that isn't allocated.
|
||||
+ *
|
||||
+ * Additionally, DEBUG_PAGEALLOC ensures (per probe_page_size_mask())
|
||||
+ * that the kernel mapping is 4k pages, therefore there are no large
|
||||
+ * pages to split/collapse.
|
||||
+ *
|
||||
+ * Furthermore, the page-allocator strictly manages pages that
|
||||
+ * *exist*, avoiding pgd_lock.
|
||||
+ *
|
||||
+ * Therefore, it is safe to not take cpa_lock.
|
||||
+ */
|
||||
+ if (debug_pagealloc_enabled() && (cpa->flags & CPA_DEBUG_PAGEALLOC))
|
||||
+ lock = false;
|
||||
+
|
||||
while (rempages) {
|
||||
/*
|
||||
* Store the remaining nr of pages for the large page
|
||||
@@ -2023,11 +2034,12 @@ static int __change_page_attr_set_clr(struct cpa_data *cpa, int primary)
|
||||
if (cpa->flags & (CPA_ARRAY | CPA_PAGES_ARRAY))
|
||||
cpa->numpages = 1;
|
||||
|
||||
- if (!debug_pagealloc_enabled())
|
||||
- spin_lock(&cpa_lock);
|
||||
- ret = __change_page_attr(cpa, primary);
|
||||
- if (!debug_pagealloc_enabled())
|
||||
- spin_unlock(&cpa_lock);
|
||||
+ if (lock) {
|
||||
+ guard(spinlock)(&cpa_lock);
|
||||
+ ret = __change_page_attr(cpa, primary);
|
||||
+ } else {
|
||||
+ ret = __change_page_attr(cpa, primary);
|
||||
+ }
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
@@ -2606,7 +2618,7 @@ int set_pages_rw(struct page *page, int numpages)
|
||||
return set_memory_rw(addr, numpages);
|
||||
}
|
||||
|
||||
-static int __set_pages_p(struct page *page, int numpages)
|
||||
+static int __set_pages_p(struct page *page, int numpages, unsigned int cpa_flags)
|
||||
{
|
||||
unsigned long tempaddr = (unsigned long) page_address(page);
|
||||
struct cpa_data cpa = { .vaddr = &tempaddr,
|
||||
@@ -2614,7 +2626,7 @@ static int __set_pages_p(struct page *page, int numpages)
|
||||
.numpages = numpages,
|
||||
.mask_set = __pgprot(_PAGE_PRESENT | _PAGE_RW),
|
||||
.mask_clr = __pgprot(0),
|
||||
- .flags = CPA_NO_CHECK_ALIAS };
|
||||
+ .flags = CPA_NO_CHECK_ALIAS | cpa_flags };
|
||||
|
||||
/*
|
||||
* No alias checking needed for setting present flag. otherwise,
|
||||
@@ -2625,7 +2637,7 @@ static int __set_pages_p(struct page *page, int numpages)
|
||||
return __change_page_attr_set_clr(&cpa, 1);
|
||||
}
|
||||
|
||||
-static int __set_pages_np(struct page *page, int numpages)
|
||||
+static int __set_pages_np(struct page *page, int numpages, unsigned int cpa_flags)
|
||||
{
|
||||
unsigned long tempaddr = (unsigned long) page_address(page);
|
||||
struct cpa_data cpa = { .vaddr = &tempaddr,
|
||||
@@ -2633,7 +2645,7 @@ static int __set_pages_np(struct page *page, int numpages)
|
||||
.numpages = numpages,
|
||||
.mask_set = __pgprot(0),
|
||||
.mask_clr = __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY),
|
||||
- .flags = CPA_NO_CHECK_ALIAS };
|
||||
+ .flags = CPA_NO_CHECK_ALIAS | cpa_flags };
|
||||
|
||||
/*
|
||||
* No alias checking needed for setting not present flag. otherwise,
|
||||
@@ -2646,20 +2658,20 @@ static int __set_pages_np(struct page *page, int numpages)
|
||||
|
||||
int set_direct_map_invalid_noflush(struct page *page)
|
||||
{
|
||||
- return __set_pages_np(page, 1);
|
||||
+ return __set_pages_np(page, 1, 0);
|
||||
}
|
||||
|
||||
int set_direct_map_default_noflush(struct page *page)
|
||||
{
|
||||
- return __set_pages_p(page, 1);
|
||||
+ return __set_pages_p(page, 1, 0);
|
||||
}
|
||||
|
||||
int set_direct_map_valid_noflush(struct page *page, unsigned nr, bool valid)
|
||||
{
|
||||
if (valid)
|
||||
- return __set_pages_p(page, nr);
|
||||
+ return __set_pages_p(page, nr, 0);
|
||||
|
||||
- return __set_pages_np(page, nr);
|
||||
+ return __set_pages_np(page, nr, 0);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_DEBUG_PAGEALLOC
|
||||
@@ -2678,15 +2690,23 @@ void __kernel_map_pages(struct page *page, int numpages, int enable)
|
||||
* and hence no memory allocations during large page split.
|
||||
*/
|
||||
if (enable)
|
||||
- __set_pages_p(page, numpages);
|
||||
+ __set_pages_p(page, numpages, CPA_DEBUG_PAGEALLOC);
|
||||
else
|
||||
- __set_pages_np(page, numpages);
|
||||
+ __set_pages_np(page, numpages, CPA_DEBUG_PAGEALLOC);
|
||||
|
||||
/*
|
||||
- * We should perform an IPI and flush all tlbs,
|
||||
- * but that can deadlock->flush only current cpu.
|
||||
- * Preemption needs to be disabled around __flush_tlb_all() due to
|
||||
- * CR3 reload in __native_flush_tlb().
|
||||
+ * We should perform an IPI and flush all tlbs, but that can
|
||||
+ * deadlock, settle for a local flush.
|
||||
+ *
|
||||
+ * Not doing a global TLB flush means that remote CPUs will retain
|
||||
+ * stale TLB entries. In case of P->NP (on free) this means the remote
|
||||
+ * CPUs will not take the faults, making the debug scheme less
|
||||
+ * reliable. On the NP->P (on alloc) this means the remote CPUs can
|
||||
+ * take a spurious fault. However spurious_kernel_fault() will observe
|
||||
+ * *_present() and fix it up.
|
||||
+ *
|
||||
+ * Preemption needs to be disabled around __flush_tlb_all() due to CR3
|
||||
+ * reload in __native_flush_tlb().
|
||||
*/
|
||||
preempt_disable();
|
||||
__flush_tlb_all();
|
||||
diff --git a/arch/x86/mm/pgtable.c b/arch/x86/mm/pgtable.c
|
||||
--- a/arch/x86/mm/pgtable.c
|
||||
+++ b/arch/x86/mm/pgtable.c
|
||||
|
||||
Reference in new issue
Block a user