From nobody Fri Apr 19 00:59:41 2024 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id DA51DC7618A for ; Sun, 19 Mar 2023 03:43:44 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229862AbjCSDiS (ORCPT ); Sat, 18 Mar 2023 23:38:18 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59392 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229561AbjCSDiO (ORCPT ); Sat, 18 Mar 2023 23:38:14 -0400 Received: from bg4.exmail.qq.com (bg4.exmail.qq.com [43.155.67.158]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 11EB51C33E for ; Sat, 18 Mar 2023 20:38:07 -0700 (PDT) X-QQ-mid: bizesmtp87t1679197076tawonyos Received: from localhost.localdomain ( [60.186.52.194]) by bizesmtp.qq.com (ESMTP) with id ; Sun, 19 Mar 2023 11:37:52 +0800 (CST) X-QQ-SSF: 01000000006000101000B00A0000000 X-QQ-FEAT: PXtIlpCZyqct4D9A6UijQTb/of6mMAcUFFGfIr9JXjdhBQPb6LhUTp6o5fZpi zPo0BEnuM3Vrq7aTWcaITofmY07dr+PAk/rGBrE82G7CvJjxC0BNcAv96c9+YFsAP5iH+91 0wcOlPG1Cj8kJObOJiJyBOoOboJQ68dxkhblpS5CLpnmtIbtPi8ACMQE270ZUJSpqUZe+xr A8Yf8+rvCbqnGHPyV71H8GD3bIdYn6J+bm8LUSq0nKLuaJVl0o63gRnX+uQVrCzFdk84nfW Kxw27yyJcDAyhx1VzQCm8FqwRJVCbxK32SxFTaGMr1fuCNnr4ez+6PmqPj/ALcdg52yf1/3 zBcW2y3 X-QQ-GoodBg: 0 From: "buddy.zhang" To: akpm@linux-foundation.org Cc: linux-mm@kvack.org, linux-kernel@vger.kernel.org, "buddy.zhang" Subject: [PATCH] mm: Keep memory type same on DEVMEM Page-Fault Date: Sun, 19 Mar 2023 11:37:50 +0800 Message-Id: <20230319033750.475200-1-buddy.zhang@biscuitos.cn> X-Mailer: git-send-email 2.25.1 MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-QQ-SENDSIZE: 520 Feedback-ID: bizesmtp:biscuitos.cn:qybglogicsvr:qybglogicsvr2 Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" On X86 architecture, supports memory type on Page-table, such as PTE is PAT/PCD/PWD, which can setup up Memory Type as WC/WB/WT/UC etc. Then, Virtual address from userspace or kernel space can map to same physical page, if each page table has different memory type, then it's confused to have more memory type for same physical page. On DEVMEM, the 'remap_pfn_range()' keep memory type same on different mapping. But if it happen on Page-Fault route, such as code: 19 static vm_fault_t vm_fault(struct vm_fault *vmf) 20 { 21 struct vm_area_struct *vma =3D vmf->vma; 22 unsigned long address =3D vmf->address; 23 struct page *fault_page; 24 unsigned long pfn; 25 int r; 26 27 /* Allocate Page as DEVMEM */ 28 fault_page =3D alloc_page(GFP_KERNEL); 29 if (!fault_page) { 30 printk("ERROR: NO Free Memory from DEVMEM.\n"); 31 r =3D -ENOMEM; 32 goto err_alloc; 33 } 34 pfn =3D page_to_pfn(fault_page); 35 36 /* Clear PAT Attribute */ 37 pgprot_val(vma->vm_page_prot) &=3D ~(_PAGE_PCD | _PAGE_PWT | _P= AGE_PAT); 38 39 /* Change Memory Type for Direct-Mapping Area */ 40 arch_io_reserve_memtype_wc(PFN_PHYS(pfn), PAGE_SIZE); 41 pgprot_val(vma->vm_page_prot) |=3D cachemode2protval(_PAGE_CACH= E_MODE_WT); 42 43 /* Establish pte and INC _mapcount for page */ 44 vm_flags_set(vma, VM_MIXEDMAP); 45 if (vm_insert_page(vma, address, fault_page)) 46 return -EAGAIN; 47 48 /* Add refcount for page */ 49 atomic_inc(&fault_page->_refcount); 50 /* bind fault page */ 51 vmf->page =3D fault_page; 52 53 return 0; 54 55 err_alloc: 56 return r; 57 } 58 59 static const struct vm_operations_struct BiscuitOS_vm_ops =3D { 60 .fault =3D vm_fault, 61 }; 62 63 static int BiscuitOS_mmap(struct file *filp, struct vm_area_struct *vma) 64 { 65 /* setup vm_ops */ 66 vma->vm_ops =3D &BiscuitOS_vm_ops; 67 68 return 0; 69 } If invoke arch_io_reserve_memtype_wc() on Line-40, and modify memory type as WC for Direct-Mapping area, and then setup meory type as WT on Line-41, then invoke 'vm_insert_page()' to create mapping, so you can see: | <----- Usespace -----> | <- Kernel space -> | ----+------+---+-------------+---+---+------------+-- | | | | | | | ----+------+---+-------------+---+---+------------+-- WT| |WC o-------o o--------o WT| |WC V V -------------------+--------+------------------------ | DEVMEM | -------------------+--------+------------------------ Physical Address Space For this case, OS should check memory type before mapping on 'vm_insert_pag= e()', and keep memory type same, so add check on function: 07 int vm_insert_page(struct vm_area_struct *vma, unsigned long addr, 08 struct page *page) 09 { 10 if (addr < vma->vm_start || addr >=3D vma->vm_end) 11 return -EFAULT; 12 if (!page_count(page)) 13 return -EINVAL; 14 if (!(vma->vm_flags & VM_MIXEDMAP)) { 15 BUG_ON(mmap_read_trylock(vma->vm_mm)); 16 BUG_ON(vma->vm_flags & VM_PFNMAP); 17 vm_flags_set(vma, VM_MIXEDMAP); 18 } 19 if (track_pfn_remap(vma, &vma->vm_page_prot, 20 page_to_pfn(page), addr, PAGE_SIZE)) 21 return -EINVAL; 22 return insert_page(vma, addr, page, vma->vm_page_prot); 23 } And line 19 to 21, when mapping different memory type on this route, the 'track_pfn_remap()' will notify error and change request as current, e.g. x86/PAT: APP:88 map pfn RAM range req write-through for [mem 0x025c1000-0x0= 25c1fff], got write-combining And then, we can keep memory type same on Page-fault route for DEVMEM, the = end: | <----- Usespace -----> | <- Kernel space -> | ----+------+---+-------------+---+---+------------+-- | | | | | | | ----+------+---+-------------+---+---+------------+-- WT| |WC o---(X)----o----------o |WC V -------------------+--------+------------------------ | DEVMEM | -------------------+--------+------------------------ Signed-off-by: buddy.zhang@biscuitos.cn --- mm/memory.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/mm/memory.c b/mm/memory.c index f456f3b5049c..ed3d09f513f1 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -1989,6 +1989,9 @@ int vm_insert_page(struct vm_area_struct *vma, unsign= ed long addr, BUG_ON(vma->vm_flags & VM_PFNMAP); vm_flags_set(vma, VM_MIXEDMAP); } + if (track_pfn_remap(vma, &vma->vm_page_prot, + page_to_pfn(page), addr, PAGE_SIZE)) + return -EINVAL; return insert_page(vma, addr, page, vma->vm_page_prot); } EXPORT_SYMBOL(vm_insert_page); --=20 2.25.1