This is the next version of the fixes for memory unplug on radix.
The issues and the fix are described in the actual patches.
Changes from v1:
- Added back patch to drop split_kernel_mapping
- Most of the split_kernel_mapping related issues are now described
in the removal patch
- drop pte fragment change
- use lmb size as the max mapping size.
- Radix baremetal now use memory block size of 1G.
Changes from v0:
==============
- Rebased to latest kernel.
- Took care of p4d changes.
- Addressed Aneesh's review feedback:
- Added comments.
- Indentation fixed.
- Dropped the 1st patch (setting DRCONF_MEM_HOTREMOVABLE lmb flags) as
it is debatable if this flag should be set in the device tree by OS
and not by platform in case of hotplug. This can be looked at separately.
(The fixes in this patchset remain valid without the dropped patch)
- Dropped the last patch that removed split_kernel_mapping() to ensure
that spilitting code is available for any radix guest running on
platforms that don't set DRCONF_MEM_HOTREMOVABLE.
Aneesh Kumar K.V (2):
powerpc/mm/radix: Fix PTE/PMD fragment count for early page table
mappings
powerpc/mm/radix: Create separate mappings for hot-plugged memory
Bharata B Rao (2):
powerpc/mm/radix: Free PUD table when freeing pagetable
powerpc/mm/radix: Remove split_kernel_mapping()
arch/powerpc/include/asm/book3s/64/pgalloc.h | 16 +-
arch/powerpc/mm/book3s64/pgtable.c | 5 +-
arch/powerpc/mm/book3s64/radix_pgtable.c | 199 +++++++++++--------
arch/powerpc/mm/pgtable-frag.c | 3 +
arch/powerpc/platforms/powernv/setup.c | 10 +-
5 files changed, 144 insertions(+), 89 deletions(-)
--
2.26.2
We can hit the following BUG_ON during memory unplug:
kernel BUG at arch/powerpc/mm/book3s64/pgtable.c:342!
Oops: Exception in kernel mode, sig: 5 [#1]
LE PAGE_SIZE=64K MMU=Radix SMP NR_CPUS=2048 NUMA pSeries
NIP [c000000000093308] pmd_fragment_free+0x48/0xc0
LR [c00000000147bfec] remove_pagetable+0x578/0x60c
Call Trace:
0xc000008050000000 (unreliable)
remove_pagetable+0x384/0x60c
radix__remove_section_mapping+0x18/0x2c
remove_section_mapping+0x1c/0x3c
arch_remove_memory+0x11c/0x180
try_remove_memory+0x120/0x1b0
__remove_memory+0x20/0x40
dlpar_remove_lmb+0xc0/0x114
dlpar_memory+0x8b0/0xb20
handle_dlpar_errorlog+0xc0/0x190
pseries_hp_work_fn+0x2c/0x60
process_one_work+0x30c/0x810
worker_thread+0x98/0x540
kthread+0x1c4/0x1d0
ret_from_kernel_thread+0x5c/0x74
This occurs when unplug is attempted for such memory which has
been mapped using memblock pages as part of early kernel page
table setup. We wouldn't have initialized the PMD or PTE fragment
count for those PMD or PTE pages.
Fixing this includes 3 parts:
- Re-walk the init_mm page tables from mem_init() and initialize
the PMD and PTE fragment count to 1.
- When freeing PUD, PMD and PTE page table pages, check explicitly
if they come from memblock and if so free then appropriately.
- When we do early memblock based allocation of PMD and PUD pages,
allocate in PAGE_SIZE granularity so that we are sure the
complete page is used as pagetable page.
Since we now do PAGE_SIZE allocations for both PUD table and
PMD table (Note that PTE table allocation is already of PAGE_SIZE),
we end up allocating more memory for the same amount of system RAM.
Here is a comparision of how much more we need for a 64T and 2G
system after this patch:
1. 64T system
-------------
64T RAM would need 64G for vmemmap with struct page size being 64B.
128 PUD tables for 64T memory (1G mappings)
1 PUD table and 64 PMD tables for 64G vmemmap (2M mappings)
With default PUD[PMD]_TABLE_SIZE(4K), (128+1+64)*4K=772K
With PAGE_SIZE(64K) table allocations, (128+1+64)*64K=12352K
2. 2G system
------------
2G RAM would need 2M for vmemmap with struct page size being 64B.
1 PUD table for 2G memory (1G mapping)
1 PUD table and 1 PMD table for 2M vmemmap (2M mappings)
With default PUD[PMD]_TABLE_SIZE(4K), (1+1+1)*4K=12K
With new PAGE_SIZE(64K) table allocations, (1+1+1)*64K=192K
Signed-off-by: Bharata B Rao <redacted>
Signed-off-by: Aneesh Kumar K.V <redacted>
---
arch/powerpc/include/asm/book3s/64/pgalloc.h | 16 +++++++++++++++-
arch/powerpc/mm/book3s64/pgtable.c | 5 ++++-
arch/powerpc/mm/book3s64/radix_pgtable.c | 15 +++++++++++----
arch/powerpc/mm/pgtable-frag.c | 3 +++
4 files changed, 33 insertions(+), 6 deletions(-)
@@ -57,6 +57,13 @@ static __ref void *early_alloc_pgtable(unsigned long size, int nid,returnptr;}+/*+*Whenallocatingpudorpmdpointers,weallocateacompletepage+*ofPAGE_SIZEratherthanPUD_TABLE_SIZEorPMD_TABLE_SIZE.This+*istoensurethatthepageobtainedfromthememblockallocator+*canbecompletelyusedaspagetablepageandcanbefreed+*correctlywhenthepagetableentriesareremoved.+*/staticintearly_map_kernel_page(unsignedlongea,unsignedlongpa,pgprot_tflags,unsignedintmap_page_size,
@@ -73,8 +80,8 @@ static int early_map_kernel_page(unsigned long ea, unsigned long pa,pgdp=pgd_offset_k(ea);p4dp=p4d_offset(pgdp,ea);if(p4d_none(*p4dp)){-pudp=early_alloc_pgtable(PUD_TABLE_SIZE,nid,-region_start,region_end);+pudp=early_alloc_pgtable(PAGE_SIZE,nid,+region_start,region_end);p4d_populate(&init_mm,p4dp,pudp);}pudp=pud_offset(p4dp,ea);
@@ -83,8 +90,8 @@ static int early_map_kernel_page(unsigned long ea, unsigned long pa,gotoset_the_pte;}if(pud_none(*pudp)){-pmdp=early_alloc_pgtable(PMD_TABLE_SIZE,nid,-region_start,region_end);+pmdp=early_alloc_pgtable(PAGE_SIZE,nid,region_start,+region_end);pud_populate(&init_mm,pudp,pmdp);}pmdp=pmd_offset(pudp,ea);
@@ -110,6 +110,9 @@ void pte_fragment_free(unsigned long *table, int kernel){structpage*page=virt_to_page(table);+if(PageReserved(page))+returnfree_reserved_page(page);+BUG_ON(atomic_read(&page->pt_frag_refcount)<=0);if(atomic_dec_and_test(&page->pt_frag_refcount)){if(!kernel)
From: Bharata B Rao <redacted>
We split the page table mapping on memory unplug if the
linear range was mapped with huge page mapping (for ex: 1G)
The page table splitting code has a few issues:
1. Recursive locking
--------------------
Memory unplug path takes cpu_hotplug_lock and calls stop_machine()
for splitting the mappings. However stop_machine() takes
cpu_hotplug_lock again causing deadlock.
2. BUG: sleeping function called from in_atomic() context
---------------------------------------------------------
Memory unplug path (remove_pagetable) takes init_mm.page_table_lock
spinlock and later calls stop_machine() which does wait_for_completion()
3. Bad unlock unbalance
-----------------------
Memory unplug path takes init_mm.page_table_lock spinlock and calls
stop_machine(). The stop_machine thread function runs in a different
thread context (migration thread) which tries to release and reaquire
ptl. Releasing ptl from a different thread than which acquired it
causes bad unlock unbalance.
These problems can be avoided if we avoid mapping hot-plugged memory
with 1G mapping, thereby removing the need for splitting them during
unplug. The kernel always make sure the minimum unplug request is
SUBSECTION_SIZE for device memory and SECTION_SIZE for regular memory.
In preparation for such a change remove page table splitting support.
This essentially is a revert of
commit 4dd5f8a99e791 ("powerpc/mm/radix: Split linear mapping on hot-unplug")
Signed-off-by: Bharata B Rao <redacted>
Signed-off-by: Aneesh Kumar K.V <redacted>
---
arch/powerpc/mm/book3s64/radix_pgtable.c | 95 +++++-------------------
1 file changed, 19 insertions(+), 76 deletions(-)
To enable memory unplug without splitting kernel page table
mapping, we force the max mapping size to the LMB size. LMB
size is the unit in which hypervisor will do memory add/remove
operation.
This implies on pseries system, we now end up mapping
memory with 2M page size instead of 1G. To improve
that we want hypervisor to hint the kernel about the hotplug
memory range. This was added that as part of
commit b6eca183e23e ("powerpc/kernel: Enables memory
hot-remove after reboot on pseries guests")
But we still don't do that on PowerVM. Once we get PowerVM
updated, we can then force the 2M mapping only to hot-pluggable
memory region using memblock_is_hotpluggable(). Till then
let's depend on LMB size for finding the mapping page size
for linear range.
Signed-off-by: Bharata B Rao <redacted>
Signed-off-by: Aneesh Kumar K.V <redacted>
---
arch/powerpc/mm/book3s64/radix_pgtable.c | 83 ++++++++++++++++++++----
arch/powerpc/platforms/powernv/setup.c | 10 ++-
2 files changed, 81 insertions(+), 12 deletions(-)
@@ -266,6 +268,7 @@ static unsigned long next_boundary(unsigned long addr, unsigned long end)staticint__meminitcreate_physical_mapping(unsignedlongstart,unsignedlongend,+unsignedlongmax_mapping_size,intnid,pgprot_t_prot){unsignedlongvaddr,addr,mapping_size=0;
@@ -279,6 +282,8 @@ static int __meminit create_physical_mapping(unsigned long start,intrc;gap=next_boundary(addr,end)-addr;+if(gap>max_mapping_size)+gap=max_mapping_size;previous_size=mapping_size;prev_exec=exec;
@@ -329,8 +334,9 @@ static void __init radix_init_pgtable(void)/* We don't support slb for radix */mmu_slb_size=0;+/*-*Createthelinearmapping,usingstandardpagesizefornow+*Createthelinearmapping*/for_each_memblock(memory,reg){/*
@@ -486,6 +493,49 @@ static int __init radix_dt_scan_page_sizes(unsigned long node,return1;}+staticint__initprobe_memory_block_size(unsignedlongnode,constchar*uname,int+depth,void*data)+{+const__be32*block_size;+intlen;++if(depth!=1)+return0;++if(!strcmp(uname,"ibm,dynamic-reconfiguration-memory")){++block_size=of_get_flat_dt_prop(node,"ibm,lmb-size",&len);+if(!block_size||len<dt_root_size_cells*sizeof(__be32))+/*+*Nothinginthedevicetree+*/+returnMIN_MEMORY_BLOCK_SIZE;++returndt_mem_next_cell(dt_root_size_cells,&block_size);++}++return0;+}++staticunsignedlongradix_memory_block_size(void)+{+unsignedlongmem_block_size=MIN_MEMORY_BLOCK_SIZE;++if(firmware_has_feature(FW_FEATURE_OPAL)){++mem_block_size=1UL*1024*1024*1024;++}elseif(firmware_has_feature(FW_FEATURE_LPAR)){+mem_block_size=of_scan_flat_dt(probe_memory_block_size,NULL);+if(!mem_block_size)+mem_block_size=MIN_MEMORY_BLOCK_SIZE;+}++returnmem_block_size;+}++void__initradix__early_init_devtree(void){intrc;
@@ -494,17 +544,27 @@ void __init radix__early_init_devtree(void)*Trytofindtheavailablepagesizesinthedevice-tree*/rc=of_scan_flat_dt(radix_dt_scan_page_sizes,NULL);-if(rc!=0)/* Found */-gotofound;+if(rc==0){+/*+*nopagesizedetailsfoundindevicetree+*let'sassumewehavepage4kand64ksupport+*/+mmu_psize_defs[MMU_PAGE_4K].shift=12;+mmu_psize_defs[MMU_PAGE_4K].ap=0x0;++mmu_psize_defs[MMU_PAGE_64K].shift=16;+mmu_psize_defs[MMU_PAGE_64K].ap=0x5;+}+/*-*let'sassumewehavepage4kand64ksupport+*Maxmappingsizeusedwhenmappingpages.Wedon'tuse+*ppc_md.memory_block_size()herebecausethisgetcalled+*earlyandwedon'thavemachineprobecalledyet.Also+*thepseriesimplementationonlycheckforibm,lmb-size.+*Allhypervisorsupportingradixdoexposethatdevice+*treenode.*/-mmu_psize_defs[MMU_PAGE_4K].shift=12;-mmu_psize_defs[MMU_PAGE_4K].ap=0x0;--mmu_psize_defs[MMU_PAGE_64K].shift=16;-mmu_psize_defs[MMU_PAGE_64K].ap=0x5;-found:+radix_mem_block_size=radix_memory_block_size();return;}
@@ -856,7 +916,8 @@ int __meminit radix__create_section_mapping(unsigned long start,return-1;}-returncreate_physical_mapping(__pa(start),__pa(end),nid,prot);+returncreate_physical_mapping(__pa(start),__pa(end),+radix_mem_block_size,nid,prot);}int__meminitradix__remove_section_mapping(unsignedlongstart,unsignedlongend)
Fixing this includes 3 parts:
- Re-walk the init_mm page tables from mem_init() and initialize
the PMD and PTE fragment count to 1.
- When freeing PUD, PMD and PTE page table pages, check explicitly
if they come from memblock and if so free then appropriately.
- When we do early memblock based allocation of PMD and PUD pages,
allocate in PAGE_SIZE granularity so that we are sure the
complete page is used as pagetable page.
Since we now do PAGE_SIZE allocations for both PUD table and
PMD table (Note that PTE table allocation is already of PAGE_SIZE),
we end up allocating more memory for the same amount of system RAM.
Here is a comparision of how much more we need for a 64T and 2G
system after this patch:
Missed updating the commit message w.r.t page table fragments. Updated
one below.
powerpc/mm/radix: Fix PTE/PMD fragment count for early page table mappings
We can hit the following BUG_ON during memory unplug:
kernel BUG at arch/powerpc/mm/book3s64/pgtable.c:342!
Oops: Exception in kernel mode, sig: 5 [#1]
LE PAGE_SIZE=64K MMU=Radix SMP NR_CPUS=2048 NUMA pSeries
NIP [c000000000093308] pmd_fragment_free+0x48/0xc0
LR [c00000000147bfec] remove_pagetable+0x578/0x60c
Call Trace:
0xc000008050000000 (unreliable)
remove_pagetable+0x384/0x60c
radix__remove_section_mapping+0x18/0x2c
remove_section_mapping+0x1c/0x3c
arch_remove_memory+0x11c/0x180
try_remove_memory+0x120/0x1b0
__remove_memory+0x20/0x40
dlpar_remove_lmb+0xc0/0x114
dlpar_memory+0x8b0/0xb20
handle_dlpar_errorlog+0xc0/0x190
pseries_hp_work_fn+0x2c/0x60
process_one_work+0x30c/0x810
worker_thread+0x98/0x540
kthread+0x1c4/0x1d0
ret_from_kernel_thread+0x5c/0x74
This occurs when unplug is attempted for such memory which has
been mapped using memblock pages as part of early kernel page
table setup. We wouldn't have initialized the PMD or PTE fragment
count for those PMD or PTE pages.
This can be fixed by allocating memory in PAGE_SIZE granularity
during early page table allocation. This makes sure a specific
page is not shared for another memblock allocation and we can
free them correctly on removing page-table pages.
Since we now do PAGE_SIZE allocations for both PUD table and
PMD table (Note that PTE table allocation is already of PAGE_SIZE),
we end up allocating more memory for the same amount of system RAM.
Here is a comparision of how much more we need for a 64T and 2G
system after this patch:
1. 64T system
-------------
64T RAM would need 64G for vmemmap with struct page size being 64B.
128 PUD tables for 64T memory (1G mappings)
1 PUD table and 64 PMD tables for 64G vmemmap (2M mappings)
With default PUD[PMD]_TABLE_SIZE(4K), (128+1+64)*4K=772K
With PAGE_SIZE(64K) table allocations, (128+1+64)*64K=12352K
2. 2G system
------------
2G RAM would need 2M for vmemmap with struct page size being 64B.
1 PUD table for 2G memory (1G mapping)
1 PUD table and 1 PMD table for 2M vmemmap (2M mappings)
With default PUD[PMD]_TABLE_SIZE(4K), (1+1+1)*4K=12K
With new PAGE_SIZE(64K) table allocations, (1+1+1)*64K=192K
Signed-off-by: Bharata B Rao <redacted>
Signed-off-by: Aneesh Kumar K.V <redacted>
-aneesh
From: Michael Ellerman <mpe@ellerman.id.au> Date: 2020-07-08 04:43:40
"Aneesh Kumar K.V" [off-list ref] writes:
To enable memory unplug without splitting kernel page table
mapping, we force the max mapping size to the LMB size. LMB
size is the unit in which hypervisor will do memory add/remove
operation.
This implies on pseries system, we now end up mapping
Please expand on why it "implies" that for pseries.
memory with 2M page size instead of 1G. To improve
that we want hypervisor to hint the kernel about the hotplug
memory range. This was added that as part of
That
commit b6eca183e23e ("powerpc/kernel: Enables memory
hot-remove after reboot on pseries guests")
But we still don't do that on PowerVM. Once we get PowerVM
I think you mean PowerVM doesn't provide that hint yet?
Realistically it won't until P10. So this means we'll always use 2MB on
Power9 PowerVM doesn't it?
What about KVM?
Have you done any benchmarking on the impact of switching the linear
mapping to 2MB pages?
quoted hunk
updated, we can then force the 2M mapping only to hot-pluggable
memory region using memblock_is_hotpluggable(). Till then
let's depend on LMB size for finding the mapping page size
for linear range.
Signed-off-by: Bharata B Rao <redacted>
Signed-off-by: Aneesh Kumar K.V <redacted>
---
arch/powerpc/mm/book3s64/radix_pgtable.c | 83 ++++++++++++++++++++----
arch/powerpc/platforms/powernv/setup.c | 10 ++-
2 files changed, 81 insertions(+), 12 deletions(-)
@@ -266,6 +268,7 @@ static unsigned long next_boundary(unsigned long addr, unsigned long end) static int __meminit create_physical_mapping(unsigned long start, unsigned long end,+ unsigned long max_mapping_size, int nid, pgprot_t _prot) { unsigned long vaddr, addr, mapping_size = 0;
@@ -279,6 +282,8 @@ static int __meminit create_physical_mapping(unsigned long start, int rc; gap = next_boundary(addr, end) - addr;+ if (gap > max_mapping_size)+ gap = max_mapping_size; previous_size = mapping_size; prev_exec = exec;
@@ -329,8 +334,9 @@ static void __init radix_init_pgtable(void) /* We don't support slb for radix */ mmu_slb_size = 0;+ /*- * Create the linear mapping, using standard page size for now+ * Create the linear mapping */ for_each_memblock(memory, reg) { /*
Just of_read_number() ?
This is misusing the return value, as I explained on one of your other
recent patches. You should return !0 to indicate that scanning should
stop, and the actual value can go via the data pointer, or better just
set the global.
+ }
+
+ return 0;
+}
+
+static unsigned long radix_memory_block_size(void)
+{
+ unsigned long mem_block_size = MIN_MEMORY_BLOCK_SIZE;
It would probably be simpler if that was just inlined below.
quoted hunk
+
+
void __init radix__early_init_devtree(void)
{
int rc;
@@ -494,17 +544,27 @@ void __init radix__early_init_devtree(void) * Try to find the available page sizes in the device-tree */ rc = of_scan_flat_dt(radix_dt_scan_page_sizes, NULL);- if (rc != 0) /* Found */- goto found;+ if (rc == 0) {+ /*+ * no page size details found in device tree+ * let's assume we have page 4k and 64k support
Moving that seems like an unrelated change. It's a reasonable change but
I'd rather you did it in a standalone patch.
/*
- * let's assume we have page 4k and 64k support
+ * Max mapping size used when mapping pages. We don't use
+ * ppc_md.memory_block_size() here because this get called
+ * early and we don't have machine probe called yet. Also
+ * the pseries implementation only check for ibm,lmb-size.
+ * All hypervisor supporting radix do expose that device
+ * tree node.
*/
- mmu_psize_defs[MMU_PAGE_4K].shift = 12;
- mmu_psize_defs[MMU_PAGE_4K].ap = 0x0;
-
- mmu_psize_defs[MMU_PAGE_64K].shift = 16;
- mmu_psize_defs[MMU_PAGE_64K].ap = 0x5;
-found:
+ radix_mem_block_size = radix_memory_block_size();
If you did that earlier in the function, before
radix_dt_scan_page_sizes(), the logic would be simpler.
quoted hunk
return;
}
@@ -856,7 +916,8 @@ int __meminit radix__create_section_mapping(unsigned long start, return -1; }- return create_physical_mapping(__pa(start), __pa(end), nid, prot);+ return create_physical_mapping(__pa(start), __pa(end),+ radix_mem_block_size, nid, prot); } int __meminit radix__remove_section_mapping(unsigned long start, unsigned long end)
To enable memory unplug without splitting kernel page table
mapping, we force the max mapping size to the LMB size. LMB
size is the unit in which hypervisor will do memory add/remove
operation.
This implies on pseries system, we now end up mapping
Please expand on why it "implies" that for pseries.
quoted
memory with 2M page size instead of 1G. To improve
that we want hypervisor to hint the kernel about the hotplug
memory range. This was added that as part of
That
quoted
commit b6eca183e23e ("powerpc/kernel: Enables memory
hot-remove after reboot on pseries guests")
But we still don't do that on PowerVM. Once we get PowerVM
I think you mean PowerVM doesn't provide that hint yet?
Realistically it won't until P10. So this means we'll always use 2MB on
Power9 PowerVM doesn't it?
What about KVM?
Have you done any benchmarking on the impact of switching the linear
mapping to 2MB pages?
The TLB impact should be minimal because with a 256M LMB size partition
scoped entries are still 2M and hence we end up with TLBs of 2M size.
quoted
updated, we can then force the 2M mapping only to hot-pluggable
memory region using memblock_is_hotpluggable(). Till then
let's depend on LMB size for finding the mapping page size
for linear range.
updated
powerpc/mm/radix: Create separate mappings for hot-plugged memory
To enable memory unplug without splitting kernel page table
mapping, we force the max mapping size to the LMB size. LMB
size is the unit in which hypervisor will do memory add/remove
operation.
Pseries systems supports max LMB size of 256MB. Hence on pseries,
we now end up mapping memory with 2M page size instead of 1G. To improve
that we want hypervisor to hint the kernel about the hotplug
memory range. That was added that as part of
commit b6eca18 ("powerpc/kernel: Enables memory
hot-remove after reboot on pseries guests")
But PowerVM doesn't provide that hint yet. Once we get PowerVM
updated, we can then force the 2M mapping only to hot-pluggable
memory region using memblock_is_hotpluggable(). Till then
let's depend on LMB size for finding the mapping page size
for linear range.
With this change KVM guest will also be doing linear mapping with
2M page size.
@@ -266,6 +268,7 @@ static unsigned long next_boundary(unsigned long addr, unsigned long end) static int __meminit create_physical_mapping(unsigned long start, unsigned long end,+ unsigned long max_mapping_size, int nid, pgprot_t _prot) { unsigned long vaddr, addr, mapping_size = 0;
@@ -279,6 +282,8 @@ static int __meminit create_physical_mapping(unsigned long start, int rc; gap = next_boundary(addr, end) - addr;+ if (gap > max_mapping_size)+ gap = max_mapping_size; previous_size = mapping_size; prev_exec = exec;
@@ -329,8 +334,9 @@ static void __init radix_init_pgtable(void) /* We don't support slb for radix */ mmu_slb_size = 0;+ /*- * Create the linear mapping, using standard page size for now+ * Create the linear mapping */ for_each_memblock(memory, reg) { /*
Just of_read_number() ?
This is misusing the return value, as I explained on one of your other
recent patches. You should return !0 to indicate that scanning should
stop, and the actual value can go via the data pointer, or better just
set the global.
updated
quoted
+ }
+
+ return 0;
+}
+
+static unsigned long radix_memory_block_size(void)
+{
+ unsigned long mem_block_size = MIN_MEMORY_BLOCK_SIZE;
It would probably be simpler if that was just inlined below.
quoted
+
+
void __init radix__early_init_devtree(void)
{
int rc;
@@ -494,17 +544,27 @@ void __init radix__early_init_devtree(void) * Try to find the available page sizes in the device-tree */ rc = of_scan_flat_dt(radix_dt_scan_page_sizes, NULL);- if (rc != 0) /* Found */- goto found;+ if (rc == 0) {+ /*+ * no page size details found in device tree+ * let's assume we have page 4k and 64k support
Moving that seems like an unrelated change. It's a reasonable change but
I'd rather you did it in a standalone patch.
we needed that change so that we can call radix_memory_block_size() for
both found and !found case.
quoted
/*
- * let's assume we have page 4k and 64k support
+ * Max mapping size used when mapping pages. We don't use
+ * ppc_md.memory_block_size() here because this get called
+ * early and we don't have machine probe called yet. Also
+ * the pseries implementation only check for ibm,lmb-size.
+ * All hypervisor supporting radix do expose that device
+ * tree node.
*/
- mmu_psize_defs[MMU_PAGE_4K].shift = 12;
- mmu_psize_defs[MMU_PAGE_4K].ap = 0x0;
-
- mmu_psize_defs[MMU_PAGE_64K].shift = 16;
- mmu_psize_defs[MMU_PAGE_64K].ap = 0x5;
-found:
+ radix_mem_block_size = radix_memory_block_size();
If you did that earlier in the function, before
radix_dt_scan_page_sizes(), the logic would be simpler.
quoted
return;
}
@@ -856,7 +916,8 @@ int __meminit radix__create_section_mapping(unsigned long start, return -1; }- return create_physical_mapping(__pa(start), __pa(end), nid, prot);+ return create_physical_mapping(__pa(start), __pa(end),+ radix_mem_block_size, nid, prot); } int __meminit radix__remove_section_mapping(unsigned long start, unsigned long end)
From: Michael Ellerman <mpe@ellerman.id.au> Date: 2020-07-08 12:14:57
"Aneesh Kumar K.V" [off-list ref] writes:
On 7/8/20 10:14 AM, Michael Ellerman wrote:
quoted
"Aneesh Kumar K.V" [off-list ref] writes:
quoted
To enable memory unplug without splitting kernel page table
mapping, we force the max mapping size to the LMB size. LMB
size is the unit in which hypervisor will do memory add/remove
operation.
This implies on pseries system, we now end up mapping
Please expand on why it "implies" that for pseries.
quoted
memory with 2M page size instead of 1G. To improve
that we want hypervisor to hint the kernel about the hotplug
memory range. This was added that as part of
That
quoted
commit b6eca183e23e ("powerpc/kernel: Enables memory
hot-remove after reboot on pseries guests")
But we still don't do that on PowerVM. Once we get PowerVM
I think you mean PowerVM doesn't provide that hint yet?
Realistically it won't until P10. So this means we'll always use 2MB on
Power9 PowerVM doesn't it?
What about KVM?
Have you done any benchmarking on the impact of switching the linear
mapping to 2MB pages?
The TLB impact should be minimal because with a 256M LMB size partition
scoped entries are still 2M and hence we end up with TLBs of 2M size.
quoted
quoted
updated, we can then force the 2M mapping only to hot-pluggable
memory region using memblock_is_hotpluggable(). Till then
let's depend on LMB size for finding the mapping page size
for linear range.
updated
powerpc/mm/radix: Create separate mappings for hot-plugged memory
To enable memory unplug without splitting kernel page table
mapping, we force the max mapping size to the LMB size. LMB
size is the unit in which hypervisor will do memory add/remove
operation.
Pseries systems supports max LMB size of 256MB. Hence on pseries,
we now end up mapping memory with 2M page size instead of 1G. To improve
that we want hypervisor to hint the kernel about the hotplug
memory range. That was added that as part of
commit b6eca18 ("powerpc/kernel: Enables memory
hot-remove after reboot on pseries guests")
But PowerVM doesn't provide that hint yet. Once we get PowerVM
updated, we can then force the 2M mapping only to hot-pluggable
memory region using memblock_is_hotpluggable(). Till then
let's depend on LMB size for finding the mapping page size
for linear range.
With this change KVM guest will also be doing linear mapping with
2M page size.
...
quoted
quoted
@@ -494,17 +544,27 @@ void __init radix__early_init_devtree(void) * Try to find the available page sizes in the device-tree */ rc = of_scan_flat_dt(radix_dt_scan_page_sizes, NULL);- if (rc != 0) /* Found */- goto found;+ if (rc == 0) {+ /*+ * no page size details found in device tree+ * let's assume we have page 4k and 64k support
Moving that seems like an unrelated change. It's a reasonable change but
I'd rather you did it in a standalone patch.
we needed that change so that we can call radix_memory_block_size() for
both found and !found case.
But the found and !found cases converge at found:, which is where you
call it. So I don't understand.
But as I said below, it would be even simpler if you worked out the
memory block size first.
cheers
quoted
quoted
/*
- * let's assume we have page 4k and 64k support
+ * Max mapping size used when mapping pages. We don't use
+ * ppc_md.memory_block_size() here because this get called
+ * early and we don't have machine probe called yet. Also
+ * the pseries implementation only check for ibm,lmb-size.
+ * All hypervisor supporting radix do expose that device
+ * tree node.
*/
- mmu_psize_defs[MMU_PAGE_4K].shift = 12;
- mmu_psize_defs[MMU_PAGE_4K].ap = 0x0;
-
- mmu_psize_defs[MMU_PAGE_64K].shift = 16;
- mmu_psize_defs[MMU_PAGE_64K].ap = 0x5;
-found:
+ radix_mem_block_size = radix_memory_block_size();
If you did that earlier in the function, before
radix_dt_scan_page_sizes(), the logic would be simpler.