On Fri, Dec 04, 2020 at 08:57:37AM +0100, Helge Deller wrote: > On 12/4/20 4:48 AM, Matthew Wilcox wrote: > > On Thu, Dec 03, 2020 at 04:33:10PM -0800, James Bottomley wrote: > >> These platforms define PMD_ORDER in asm/pgtable.h > > > > I think that's the real problem, though. > > > > #define PGD_ORDER 1 /* Number of pages per pgd */ > > #define PMD_ORDER 1 /* Number of pages per pmd */ > > #define PGD_ALLOC_ORDER (2 + 1) /* first pgd contains pmd */ > > #else > > #define PGD_ORDER 1 /* Number of pages per pgd */ > > #define PGD_ALLOC_ORDER (PGD_ORDER + 1) > > > > That should clearly be PMD_ALLOC_ORDER, not PMD_ORDER. Or even > > PAGES_PER_PMD like the comment calls it, because I really think > > that doing an order-3 (8 pages) allocation for the PGD is wrong. > > We need a spinlock to protect parallel accesses to the PGD, > search for pgd_spinlock(). > This spinlock is stored behind the memory used for the PGD, which > is why we allocate more memory (and waste 3 pages). There are better places to store it than that! For example, storing it in the struct page, like many architectures do for split ptlocks. You'll have to skip the _pt_pad_1 so it doesn't get confused with being a compound_head, but soemthing like this: struct { /* PA-RISC PGD */ unsigned long _pa_pad_1; /* compound_head */ #if ALLOC_SPLIT_PA_PTLOCKS spinlock_t *pa_ptl; #else spinlock_t pa_ptl; #endif }; inside struct page (linux/mm_types.h) should do the trick. You'll still need to allocate them separately if various debugging options are enabled (see the ALLOC_SPLIT_PTLOCKS for details), but usually this will save you a lot of memory. You could also fill in pt_mm like x86 does for its pgds, and then use mm->page_table_lock to protect whatever the PGD lock currently protects. Maybe page_table_lock is sometimes held when calling ptep_set_wrprotect() and sometimes isn't; then this wouldn't work. Also, could you fix the comments? They don't match the code: #define PGD_ORDER 1 /* Number of pages per pgd */ should be #define PGD_ALLOC_ORDER 1 /* 2 pages (8KiB) per pgd */