Messages in this thread | | | Date | Thu, 14 Apr 2022 11:43:10 +0800 | Subject | Re: [PATCH RFC v1] arm64: mm: change mem_map to use block/section mapping with crashkernel | From | "guanghui.fgh" <> |
| |
Thanks for your response!
在 2022/4/14 0:53, Catalin Marinas 写道: > On Tue, Apr 12, 2022 at 05:07:56PM +0800, Guanghui Feng wrote: >> There are many changes and discussions: >> commit 031495635b46 >> commit 1a8e1cef7603 >> commit 8424ecdde7df >> commit 0a30c53573b0 >> commit 2687275a5843 >> >> When using DMA/DMA32 zone and crashkernel, disable rodata full and kfence, >> mem_map will use non block/section mapping(for crashkernel requires to shrink >> the region in page granularity). But it will degrade performance when doing >> larging continuous mem access in kernel(memcpy/memmove, etc). >> >> This patch firstly do block/section mapping at mem_map, reserve crashkernel >> memory. And then walking pagetable to split block/section mapping >> to non block/section mapping [only] for crashkernel mem. We will accelerate >> mem access about 10-20% performance improvement, and reduce the cpu dTLB miss >> conspicuously on some platform with this optimization. > Do you actually have some real world use-cases where this improvement > matters? I don't deny that large memcpy over the kernel linear map may > be slightly faster but where does this really matter? When doing fio test, there may be about 10-20% performance gap. The test method: 1.prepare env with shell script
set -x modprobe -r brd modprobe brd rd_nr=1 rd_size=134217728 dmsetup remove_all wipefs -a --force /dev/ram0 mkfs -t ext4 -E lazy_itable_init=0,lazy_journal_init=0 -q -F /dev/ram0 mkdir -p /fs/ram0 mount -t ext4 /dev/ram0 /fs/ram0 #sed -i s/scan_lvs = 1/scan_lvs = 1/ /etc/lvm/lvm.conf
2.prepare fio env with setting file in [x.fio]:
[global] bs=4k ioengine=psync iodepth=128 size=8G direct=1 runtime=30 invalidate=1 #fallocate=native group_reporting thread=1 time_based=1 rw=read directory=/fs/ram0 #filename=/dev/ram0 numjobs=1
[task_0] cpus_allowed=16 stonewall=1
3.running fio testcase: sudo fio x.fio ----------------------------------------------------- At the same time, I have test memcpy in the double envs (block/section mapping + non block/section mapping): 1.alloc many continuous pages(src/dst: 10000 * 2^10 bytes): alloc_pages(GFP_KERNEL, 10) 2.memcpy for src to dst
>> +static void init_crashkernel_pmd(pud_t *pudp, unsigned long addr, >> + unsigned long end, phys_addr_t phys, >> + pgprot_t prot, >> + phys_addr_t (*pgtable_alloc)(int), int flags) >> +{ >> + phys_addr_t map_offset; >> + unsigned long next; >> + pmd_t *pmdp; >> + pmdval_t pmdval; >> + >> + pmdp = pmd_offset(pudp, addr); >> + do { >> + next = pmd_addr_end(addr, end); >> + if (!pmd_none(*pmdp) && pmd_sect(*pmdp)) { >> + phys_addr_t pte_phys = pgtable_alloc(PAGE_SHIFT); >> + pmd_clear(pmdp); >> + pmdval = PMD_TYPE_TABLE | PMD_TABLE_UXN; >> + if (flags & NO_EXEC_MAPPINGS) >> + pmdval |= PMD_TABLE_PXN; >> + __pmd_populate(pmdp, pte_phys, pmdval); >> + flush_tlb_kernel_range(addr, addr + PAGE_SIZE); > The architecture requires us to do a break-before-make here, so > pmd_clear(), TLBI, __pmd_populate() - in this order. And that's where it > gets tricky, if the kernel happens to access this pmd range while it is > unmapped, you'd get a translation fault. OK, Thanks.
+ if (map_offset) + alloc_init_cont_pte(pmdp, addr & PMD_MASK, addr, + phys - map_offset, prot, + pgtable_alloc, flags); +
+ + map_offset = addr - (addr & PUD_MASK); + if (map_offset) + alloc_init_cont_pmd(pudp, addr & PUD_MASK, addr, + phys - map_offset, prot, + pgtable_alloc, flags); +
Sorry,There is a defect. When rebuilding normal pmd/pte(out of crashkernel mem), the flags should strip NO_BLOCK_MAPPINGS | NO_CONT_MAPPINGS on some scenes: !(can_set_direct_map() || IS_ENABLED(CONFIG_KFENCE)). So we will use as many as possible block/section mapping.
| |