All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] Enable mprotect on huge pages
@ 2006-02-23  3:19 Zhang, Yanmin
  2006-02-24 22:28 ` Andrew Morton
  2006-02-25  8:54 ` Christoph Hellwig
  0 siblings, 2 replies; 23+ messages in thread
From: Zhang, Yanmin @ 2006-02-23  3:19 UTC (permalink / raw)
  To: linux-kernel; +Cc: kenneth.w.chen, yanmin.zhang@intel.com

From: Zhang, Yanmin <yanmin.zhang@intel.com>

2.6.16-rc3 uses hugetlb on-demand paging, but it doesn’t support hugetlb
mprotect. My patch against 2.6.16-rc3 enables this capability.

Signed-off-by: Zhang Yanmin <yanmin.zhang@intel.com> 

Discussion is welcomed.

---

diff -Nraup linux-2.6.16-rc3/include/linux/hugetlb.h linux-2.6.16-rc3_mprotect/include/linux/hugetlb.h
--- linux-2.6.16-rc3/include/linux/hugetlb.h	2006-02-14 16:43:50.000000000 +0800
+++ linux-2.6.16-rc3_mprotect/include/linux/hugetlb.h	2006-02-22 00:12:35.000000000 +0800
@@ -41,6 +41,8 @@ struct page *follow_huge_pmd(struct mm_s
 				pmd_t *pmd, int write);
 int is_aligned_hugepage_range(unsigned long addr, unsigned long len);
 int pmd_huge(pmd_t pmd);
+void hugetlb_change_protection(struct vm_area_struct *vma,
+		unsigned long address, unsigned long end, pgprot_t newprot);
 
 #ifndef ARCH_HAS_HUGEPAGE_ONLY_RANGE
 #define is_hugepage_only_range(mm, addr, len)	0
@@ -101,6 +103,8 @@ static inline unsigned long hugetlb_tota
 #define free_huge_page(p)			({ (void)(p); BUG(); })
 #define hugetlb_fault(mm, vma, addr, write)	({ BUG(); 0; })
 
+#define	hugetlb_change_protection(vma, address, end, newprot)
+
 #ifndef HPAGE_MASK
 #define HPAGE_MASK	PAGE_MASK		/* Keep the compiler happy */
 #define HPAGE_SIZE	PAGE_SIZE
diff -Nraup linux-2.6.16-rc3/mm/hugetlb.c linux-2.6.16-rc3_mprotect/mm/hugetlb.c
--- linux-2.6.16-rc3/mm/hugetlb.c	2006-02-14 16:43:50.000000000 +0800
+++ linux-2.6.16-rc3_mprotect/mm/hugetlb.c	2006-02-22 00:12:35.000000000 +0800
@@ -572,3 +572,32 @@ int follow_hugetlb_page(struct mm_struct
 
 	return i;
 }
+
+void hugetlb_change_protection(struct vm_area_struct *vma,
+		unsigned long address, unsigned long end, pgprot_t newprot)
+{
+	struct mm_struct *mm = vma->vm_mm;
+	unsigned long start = address;
+	pte_t *ptep;
+	pte_t pte;
+
+	BUG_ON(address >= end);
+	flush_cache_range(vma, address, end);
+
+	spin_lock(&mm->page_table_lock);
+	for (; address < end; address += HPAGE_SIZE) {
+		ptep = huge_pte_offset(mm, address);
+		if (!ptep)
+			continue;
+		if (pte_present(*ptep)) {
+			pte = ptep_get_and_clear(mm, address, ptep);
+			pte = pte_modify(pte, newprot);
+			set_huge_pte_at(mm, addr, ptep, pte);
+			lazy_mmu_prot_update(pte);
+		}
+	}
+	spin_unlock(&mm->page_table_lock);
+
+	flush_tlb_range(vma, start, end);
+}
+
diff -Nraup linux-2.6.16-rc3/mm/mprotect.c linux-2.6.16-rc3_mprotect/mm/mprotect.c
--- linux-2.6.16-rc3/mm/mprotect.c	2006-01-25 21:54:15.000000000 +0800
+++ linux-2.6.16-rc3_mprotect/mm/mprotect.c	2006-02-22 00:13:34.000000000 +0800
@@ -124,7 +124,7 @@ mprotect_fixup(struct vm_area_struct *vm
 	 * a MAP_NORESERVE private mapping to writable will now reserve.
 	 */
 	if (newflags & VM_WRITE) {
-		if (!(oldflags & (VM_ACCOUNT|VM_WRITE|VM_SHARED|VM_HUGETLB))) {
+		if (!(oldflags & (VM_ACCOUNT|VM_WRITE|VM_SHARED))) {
 			charged = nrpages;
 			if (security_vm_enough_memory(charged))
 				return -ENOMEM;
@@ -166,7 +166,10 @@ success:
 	 */
 	vma->vm_flags = newflags;
 	vma->vm_page_prot = newprot;
-	change_protection(vma, start, end, newprot);
+	if (is_vm_hugetlb_page(vma))
+		hugetlb_change_protection(vma, start, end, newprot);
+	else
+		change_protection(vma, start, end, newprot);
 	vm_stat_account(mm, oldflags, vma->vm_file, -nrpages);
 	vm_stat_account(mm, newflags, vma->vm_file, nrpages);
 	return 0;
@@ -240,11 +243,6 @@ sys_mprotect(unsigned long start, size_t
 
 		/* Here we know that  vma->vm_start <= nstart < vma->vm_end. */
 
-		if (is_vm_hugetlb_page(vma)) {
-			error = -EACCES;
-			goto out;
-		}
-
 		newflags = vm_flags | (vma->vm_flags & ~(VM_READ | VM_WRITE | VM_EXEC));
 
 		/* newflags >> 4 shift VM_MAY% in place of VM_% */
@@ -260,6 +258,12 @@ sys_mprotect(unsigned long start, size_t
 		tmp = vma->vm_end;
 		if (tmp > end)
 			tmp = end;
+		if (is_vm_hugetlb_page(vma) &&
+			is_aligned_hugepage_range(nstart, tmp - nstart)) {
+			error = -EINVAL;
+			goto out;
+		}
+
 		error = mprotect_fixup(vma, &prev, nstart, tmp, newflags);
 		if (error)
 			goto out;



^ permalink raw reply	[flat|nested] 23+ messages in thread

end of thread, other threads:[~2006-02-28 10:46 UTC | newest]

Thread overview: 23+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-02-23  3:19 [PATCH] Enable mprotect on huge pages Zhang, Yanmin
2006-02-24 22:28 ` Andrew Morton
2006-02-26 23:09   ` David Gibson
2006-02-27  5:36     ` Zhang, Yanmin
2006-02-27  6:33       ` Zhang, Yanmin
2006-02-28  1:34         ` Andrew Morton
2006-02-28  3:23           ` Zhang, Yanmin
2006-02-28  3:32             ` David Gibson
2006-02-28  3:37               ` Zhang, Yanmin
2006-02-28  8:24             ` David Gibson
2006-02-27  7:26       ` David Gibson
2006-02-25  8:54 ` Christoph Hellwig
2006-02-25 10:08   ` [2.4.32 - 2.6.15.4] e1000 - Fix mii interface Paul Rolland
2006-02-26 10:42     ` Willy TARREAU
2006-02-26 11:39       ` Paul Rolland
2006-02-26 12:59     ` Jesper Juhl
2006-02-26 14:55       ` Paul Rolland
2006-02-26 15:00         ` Jesper Juhl
2006-02-26 15:12           ` Paul Rolland
2006-02-27 19:26             ` Jesse Brandeburg
     [not found]     ` <4807377b0602271234v4b6cdeecpbcf8d4a6ac51cd20@mail.gmail.com>
2006-02-28  2:31       ` Jesse Brandeburg
2006-02-28 10:46         ` Paul Rolland
2006-02-27  5:09   ` [PATCH] Enable mprotect on huge pages Zhang, Yanmin

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.