/* 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);
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)
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)
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 */
/* 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);
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)
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)
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);
}
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;
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 */
/* 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. */
}
}
-
unsigned long hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
unsigned long len, unsigned long pgoff,
unsigned long flags)
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;
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))
addr = ptep_to_address(ptep);
if (REGION_ID(addr) == USER_REGION_ID)
- context = mm->context;
+ context = mm->context.id;
i = batch->index;
/*
#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
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;
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);
}
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;
#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);
}
{
unsigned long ordinal, vsid;
- context &= ~CONTEXT_LOW_HPAGES;
-
ordinal = (((ea >> 28) & 0x1fffff) * LAST_USER_CONTEXT) | context;
vsid = (ordinal * VSID_RANDOMIZER) & VSID_MASK;
/* 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)
#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
#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 */