[RFC] implicit hugetlb pages (mmu_context_to_struct)

David Gibson david at gibson.dropbear.id.au
Mon Feb 2 17:48:41 EST 2004


On Fri, Jan 09, 2004 at 01:29:38PM -0800, Adam Litke wrote:
>
> mmu_context_to_struct (2.6.0):
>    This patch converts the mmu_context variable to a structure.  It is
> needed for the dynamic address space resizing patch.

Ok, I've made a revised version of this patch.  As well as handling
the various changes in ameslab since Adam's version, it uses a better
name for the mm_context fields, separates out the low_hpages flag, and
avoids putting extraneous info in the mmu_context_queue.

I'm slightly concerned about whether it has zero-impact in the
!CONFIG_HUGETLB_PAGE case.  I think theoretically it could/should, but
there's a couple of cases where I don't know if gcc will be clever
enough to optimise everything away.

Anton, if you approve I can push this to ameslab and/or akpm.

mmu-context-struct (2.6.0):
   This patch converts the mmu_context variable to a structure.  It is
needed for the dynamic HTLB address space resizing patch.

Index: working-2.6/arch/ppc64/kernel/stab.c
===================================================================
--- working-2.6.orig/arch/ppc64/kernel/stab.c	2004-02-02 17:04:37.000000000 +1100
+++ working-2.6/arch/ppc64/kernel/stab.c	2004-02-02 17:36:30.961032128 +1100
@@ -175,13 +175,13 @@
 	/* Kernel or user address? */
 	if (REGION_ID(ea) >= KERNEL_REGION_ID) {
 		vsid = get_kernel_vsid(ea);
-		context = REGION_ID(ea);
+		context = KERNEL_CONTEXT(ea);
 	} else {
 		if (!current->mm)
 			return 1;

 		context = current->mm->context;
-		vsid = get_vsid(context, ea);
+		vsid = get_vsid(context.id, ea);
 	}

 	esid = GET_ESID(ea);
@@ -214,7 +214,7 @@

 	if (!IS_VALID_EA(pc) || (REGION_ID(pc) >= KERNEL_REGION_ID))
 		return;
-	vsid = get_vsid(mm->context, pc);
+	vsid = get_vsid(mm->context.id, pc);
 	__ste_allocate(pc_esid, vsid);

 	if (pc_esid == stack_esid)
@@ -222,7 +222,7 @@

 	if (!IS_VALID_EA(stack) || (REGION_ID(stack) >= KERNEL_REGION_ID))
 		return;
-	vsid = get_vsid(mm->context, stack);
+	vsid = get_vsid(mm->context.id, stack);
 	__ste_allocate(stack_esid, vsid);

 	if (pc_esid == unmapped_base_esid || stack_esid == unmapped_base_esid)
@@ -231,7 +231,7 @@
 	if (!IS_VALID_EA(unmapped_base) ||
 	    (REGION_ID(unmapped_base) >= KERNEL_REGION_ID))
 		return;
-	vsid = get_vsid(mm->context, unmapped_base);
+	vsid = get_vsid(mm->context.id, unmapped_base);
 	__ste_allocate(unmapped_base_esid, vsid);

 	/* Order update */
@@ -396,14 +396,14 @@

 	/* Kernel or user address? */
 	if (REGION_ID(ea) >= KERNEL_REGION_ID) {
-		context = REGION_ID(ea);
+		context = KERNEL_CONTEXT(ea);
 		vsid = get_kernel_vsid(ea);
 	} else {
 		if (unlikely(!current->mm))
 			return 1;

 		context = current->mm->context;
-		vsid = get_vsid(context, ea);
+		vsid = get_vsid(context.id, ea);
 	}

 	esid = GET_ESID(ea);
@@ -434,7 +434,7 @@

 	if (!IS_VALID_EA(pc) || (REGION_ID(pc) >= KERNEL_REGION_ID))
 		return;
-	vsid = get_vsid(mm->context, pc);
+	vsid = get_vsid(mm->context.id, pc);
 	__slb_allocate(pc_esid, vsid, mm->context);

 	if (pc_esid == stack_esid)
@@ -442,7 +442,7 @@

 	if (!IS_VALID_EA(stack) || (REGION_ID(stack) >= KERNEL_REGION_ID))
 		return;
-	vsid = get_vsid(mm->context, stack);
+	vsid = get_vsid(mm->context.id, stack);
 	__slb_allocate(stack_esid, vsid, mm->context);

 	if (pc_esid == unmapped_base_esid || stack_esid == unmapped_base_esid)
@@ -451,7 +451,7 @@
 	if (!IS_VALID_EA(unmapped_base) ||
 	    (REGION_ID(unmapped_base) >= KERNEL_REGION_ID))
 		return;
-	vsid = get_vsid(mm->context, unmapped_base);
+	vsid = get_vsid(mm->context.id, unmapped_base);
 	__slb_allocate(unmapped_base_esid, vsid, mm->context);
 }

Index: working-2.6/arch/ppc64/mm/hugetlbpage.c
===================================================================
--- working-2.6.orig/arch/ppc64/mm/hugetlbpage.c	2004-02-02 10:44:47.000000000 +1100
+++ working-2.6/arch/ppc64/mm/hugetlbpage.c	2004-02-02 17:36:30.964031672 +1100
@@ -244,7 +244,7 @@
 	struct vm_area_struct *vma;
 	unsigned long addr;

-	if (mm->context & CONTEXT_LOW_HPAGES)
+	if (mm->context.low_hpages)
 		return 0; /* The window is already open */

 	/* Check no VMAs are in the region */
@@ -281,7 +281,7 @@

 	/* FIXME: do we need to scan for PTEs too? */

-	mm->context |= CONTEXT_LOW_HPAGES;
+	mm->context.low_hpages = 1;

 	/* the context change must make it to memory before the slbia,
 	 * so that further SLB misses do the right thing. */
@@ -589,7 +589,6 @@
 	}
 }

-
 unsigned long hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
 					unsigned long len, unsigned long pgoff,
 					unsigned long flags)
@@ -778,7 +777,7 @@
 	BUG_ON(hugepte_bad(pte));
 	BUG_ON(!in_hugepage_area(context, ea));

-	vsid = get_vsid(context, ea);
+	vsid = get_vsid(context.id, ea);

 	va = (vsid << 28) | (ea & 0x0fffffff);
 	vpn = va >> LARGE_PAGE_SHIFT;
Index: working-2.6/arch/ppc64/mm/init.c
===================================================================
--- working-2.6.orig/arch/ppc64/mm/init.c	2004-01-22 10:53:08.000000000 +1100
+++ working-2.6/arch/ppc64/mm/init.c	2004-02-02 17:36:30.967031216 +1100
@@ -502,7 +502,7 @@
 		break;
 	case USER_REGION_ID:
 		pgd = pgd_offset( vma->vm_mm, vmaddr );
-		context = vma->vm_mm->context;
+		context = vma->vm_mm->context.id;

 		/* XXX are there races with checking cpu_vm_mask? - Anton */
 		tmp = cpumask_of_cpu(smp_processor_id());
@@ -554,7 +554,7 @@
 		break;
 	case USER_REGION_ID:
 		pgd = pgd_offset(mm, start);
-		context = mm->context;
+		context = mm->context.id;

 		/* XXX are there races with checking cpu_vm_mask? - Anton */
 		tmp = cpumask_of_cpu(smp_processor_id());
@@ -943,7 +943,7 @@
 	if (!ptep)
 		return;

-	vsid = get_vsid(vma->vm_mm->context, ea);
+	vsid = get_vsid(vma->vm_mm->context.id, ea);

 	tmp = cpumask_of_cpu(smp_processor_id());
 	if (cpus_equal(vma->vm_mm->cpu_vm_mask, tmp))
Index: working-2.6/arch/ppc64/mm/hash_utils.c
===================================================================
--- working-2.6.orig/arch/ppc64/mm/hash_utils.c	2004-01-22 10:53:08.000000000 +1100
+++ working-2.6/arch/ppc64/mm/hash_utils.c	2004-02-02 15:16:34.000000000 +1100
@@ -237,7 +237,7 @@
 		if (mm == NULL)
 			return 1;

-		vsid = get_vsid(mm->context, ea);
+		vsid = get_vsid(mm->context.id, ea);
 		break;
 	case IO_REGION_ID:
 		mm = &ioremap_mm;
Index: working-2.6/arch/ppc64/xmon/xmon.c
===================================================================
--- working-2.6.orig/arch/ppc64/xmon/xmon.c	2004-01-22 10:53:08.000000000 +1100
+++ working-2.6/arch/ppc64/xmon/xmon.c	2004-02-02 17:36:30.972030456 +1100
@@ -1952,7 +1952,7 @@
 		// if in user range, use the current task's page directory
 		else if ( ( ea >= USER_START ) && ( ea <= USER_END ) ) {
 			mm = current->mm;
-			vsid = get_vsid(mm->context, ea );
+			vsid = get_vsid(mm->context.id, ea );
 		}
 		pgdir = mm->pgd;
 		va = ( vsid << 28 ) | ( ea & 0x0fffffff );
Index: working-2.6/include/asm-ppc64/mmu.h
===================================================================
--- working-2.6.orig/include/asm-ppc64/mmu.h	2004-02-02 10:44:49.000000000 +1100
+++ working-2.6/include/asm-ppc64/mmu.h	2004-02-02 17:36:30.975030000 +1100
@@ -18,15 +18,25 @@

 #ifndef __ASSEMBLY__

-/* Default "unsigned long" context */
-typedef unsigned long mm_context_t;
+/* Time to allow for more things here */
+typedef unsigned long mm_context_id_t;
+typedef struct {
+	mm_context_id_t id;
+#ifdef CONFIG_HUGETLB_PAGE
+	int low_hpages;
+#endif
+} mm_context_t;

 #ifdef CONFIG_HUGETLB_PAGE
-#define CONTEXT_LOW_HPAGES	(1UL<<63)
+#define KERNEL_LOW_HPAGES	.low_hpages = 0,
 #else
-#define CONTEXT_LOW_HPAGES	0
+#define KERNEL_LOW_HPAGES
 #endif

+#define KERNEL_CONTEXT(ea) ({ \
+		mm_context_t ctx = { .id = REGION_ID(ea), KERNEL_LOW_HPAGES}; \
+		ctx; })
+
 /*
  * Hardware Segment Lookaside Buffer Entry
  * This structure has been padded out to two 64b doublewords (actual SLBE's are
Index: working-2.6/include/asm-ppc64/mmu_context.h
===================================================================
--- working-2.6.orig/include/asm-ppc64/mmu_context.h	2004-02-02 10:44:49.000000000 +1100
+++ working-2.6/include/asm-ppc64/mmu_context.h	2004-02-02 17:36:30.977029696 +1100
@@ -52,7 +52,7 @@
 	long head;
 	long tail;
 	long size;
-	mm_context_t elements[LAST_USER_CONTEXT];
+	mm_context_id_t elements[LAST_USER_CONTEXT];
 };

 extern struct mmu_context_queue_t mmu_context_queue;
@@ -83,7 +83,6 @@
 	long head;
 	unsigned long flags;
 	/* This does the right thing across a fork (I hope) */
-	unsigned long low_hpages = mm->context & CONTEXT_LOW_HPAGES;

 	spin_lock_irqsave(&mmu_context_queue.lock, flags);

@@ -93,8 +92,7 @@
 	}

 	head = mmu_context_queue.head;
-	mm->context = mmu_context_queue.elements[head];
-	mm->context |= low_hpages;
+	mm->context.id = mmu_context_queue.elements[head];

 	head = (head < LAST_USER_CONTEXT-1) ? head+1 : 0;
 	mmu_context_queue.head = head;
@@ -132,8 +130,7 @@
 #endif

 	mmu_context_queue.size++;
-	mmu_context_queue.elements[index] =
-		mm->context & ~CONTEXT_LOW_HPAGES;
+	mmu_context_queue.elements[index] = mm->context.id;

 	spin_unlock_irqrestore(&mmu_context_queue.lock, flags);
 }
@@ -210,8 +207,6 @@
 {
 	unsigned long ordinal, vsid;

-	context &= ~CONTEXT_LOW_HPAGES;
-
 	ordinal = (((ea >> 28) & 0x1fffff) * LAST_USER_CONTEXT) | context;
 	vsid = (ordinal * VSID_RANDOMIZER) & VSID_MASK;

Index: working-2.6/include/asm-ppc64/page.h
===================================================================
--- working-2.6.orig/include/asm-ppc64/page.h	2004-01-09 11:11:12.000000000 +1100
+++ working-2.6/include/asm-ppc64/page.h	2004-02-02 17:36:30.979029392 +1100
@@ -32,6 +32,7 @@
 /* For 64-bit processes the hugepage range is 1T-1.5T */
 #define TASK_HPAGE_BASE 	(0x0000010000000000UL)
 #define TASK_HPAGE_END 	(0x0000018000000000UL)
+
 /* For 32-bit processes the hugepage range is 2-3G */
 #define TASK_HPAGE_BASE_32	(0x80000000UL)
 #define TASK_HPAGE_END_32	(0xc0000000UL)
@@ -39,7 +40,7 @@
 #define ARCH_HAS_HUGEPAGE_ONLY_RANGE
 #define is_hugepage_only_range(addr, len) \
 	( ((addr > (TASK_HPAGE_BASE-len)) && (addr < TASK_HPAGE_END)) || \
-	  ((current->mm->context & CONTEXT_LOW_HPAGES) && \
+	  (current->mm->context.low_hpages && \
 	   (addr > (TASK_HPAGE_BASE_32-len)) && (addr < TASK_HPAGE_END_32)) )
 #define hugetlb_free_pgtables free_pgtables
 #define HAVE_ARCH_HUGETLB_UNMAPPED_AREA
@@ -47,7 +48,7 @@
 #define in_hugepage_area(context, addr) \
 	((cur_cpu_spec->cpu_features & CPU_FTR_16M_PAGE) && \
 	 ((((addr) >= TASK_HPAGE_BASE) && ((addr) < TASK_HPAGE_END)) || \
-	  (((context) & CONTEXT_LOW_HPAGES) && \
+	  ((context).low_hpages && \
 	   (((addr) >= TASK_HPAGE_BASE_32) && ((addr) < TASK_HPAGE_END_32)))))

 #else /* !CONFIG_HUGETLB_PAGE */
Index: working-2.6/include/asm-ppc64/tlb.h
===================================================================
--- working-2.6.orig/include/asm-ppc64/tlb.h	2004-01-22 10:53:21.000000000 +1100
+++ working-2.6/include/asm-ppc64/tlb.h	2004-02-02 17:36:30.980029240 +1100
@@ -65,7 +65,7 @@
 				if (cpus_equal(tlb->mm->cpu_vm_mask, local_cpumask))
 					local = 1;

-				flush_hash_range(tlb->mm->context, i, local);
+				flush_hash_range(tlb->mm->context.id, i, local);
 				i = 0;
 			}
 		}
@@ -86,7 +86,7 @@
 	if (cpus_equal(tlb->mm->cpu_vm_mask, local_cpumask))
 		local = 1;

-	flush_hash_range(tlb->mm->context, batch->index, local);
+	flush_hash_range(tlb->mm->context.id, batch->index, local);
 	batch->index = 0;

 	pte_free_finish();

--
David Gibson			| For every complex problem there is a
david AT gibson.dropbear.id.au	| solution which is simple, neat and
				| wrong.
http://www.ozlabs.org/people/dgibson

** Sent via the linuxppc64-dev mail list. See http://lists.linuxppc.org/





More information about the Linuxppc64-dev mailing list