Signed-off-by: --- linux-2.6.14-rc3/include/asm-ia64/mmu_context.h 2005-10-26 10:54:53.000000000 -0400 +++ linux-2.6.14-rc3pmk/include/asm-ia64/mmu_context.h 2005-10-06 16:39:27.000000000 -0400 @@ -34,11 +34,13 @@ unsigned int next; /* next context number to use */ unsigned int limit; /* next >= limit => must call wrap_mmu_context() */ unsigned int max_ctx; /* max. context value supported by all CPUs */ + unsigned long *bitmap; /* bitmap size is max_ctx+1 */ }; extern struct ia64_ctx ia64_ctx; DECLARE_PER_CPU(u8, ia64_need_tlb_flush); +extern void mmu_context_init (void); extern void wrap_mmu_context (struct mm_struct *mm); static inline void @@ -86,6 +88,7 @@ if (ia64_ctx.next >= ia64_ctx.limit) wrap_mmu_context(mm); mm->context = context = ia64_ctx.next++; + set_bit(context, ia64_ctx.bitmap); } } spin_unlock_irqrestore(&ia64_ctx.lock, flags); --- linux-2.6.14-rc3/include/asm-ia64/tlbflush.h 2005-08-28 19:41:01.000000000 -0400 +++ linux-2.6.14-rc3pmk/include/asm-ia64/tlbflush.h 2005-10-06 16:15:47.000000000 -0400 @@ -51,6 +51,7 @@ if (!mm) return; + clear_bit(mm->context, ia64_ctx.bitmap); mm->context = 0; if (atomic_read(&mm->mm_users) == 0) --- linux-2.6.14-rc3/arch/ia64/mm/tlb.c 2005-08-28 19:41:01.000000000 -0400 +++ linux-2.6.14-rc3pmk/arch/ia64/mm/tlb.c 2005-10-25 14:55:25.000000000 -0400 @@ -16,12 +16,14 @@ #include #include #include +#include #include #include #include #include #include +#include static struct { unsigned long mask; /* mask of supported purge page-sizes */ @@ -38,13 +40,32 @@ DEFINE_PER_CPU(u8, ia64_need_tlb_flush); /* + * Initializes the ia64_ctx.bitmap array based on max_ctx+1. + * Called after cpu_init() has setup ia64_ctx.max_ctx based on + * maximum RID that is supported by all CPUs. + */ +void __init +mmu_context_init (void) +{ + unsigned long flags; + + spin_lock_irqsave(&ia64_ctx.lock, flags); + if (ia64_ctx.bitmap == NULL) { + ia64_ctx.bitmap = (unsigned long *)__alloc_bootmem( + (ia64_ctx.max_ctx+1)>>3, + PAGE_SIZE, + __pa(MAX_DMA_ADDRESS)); + } + spin_unlock_irqrestore(&ia64_ctx.lock, flags); +} + +/* * Acquire the ia64_ctx.lock before calling this function! */ void wrap_mmu_context (struct mm_struct *mm) { - unsigned long tsk_context, max_ctx = ia64_ctx.max_ctx; - struct task_struct *tsk; + unsigned int next_ctx, max_ctx = ia64_ctx.max_ctx; int i; if (ia64_ctx.next > max_ctx) @@ -52,28 +73,23 @@ ia64_ctx.limit = max_ctx + 1; /* - * Scan all the task's mm->context and set proper safe range + * Scan the ia64_ctx bitmap and set proper safe range */ +repeat: + next_ctx = find_next_zero_bit(ia64_ctx.bitmap, ia64_ctx.limit, ia64_ctx.next); + if (next_ctx >= ia64_ctx.limit) { + smp_mb(); + ia64_ctx.next = 300; /* skip daemons */ + goto repeat; + } + ia64_ctx.next = next_ctx; - read_lock(&tasklist_lock); - repeat: - for_each_process(tsk) { - if (!tsk->mm) - continue; - tsk_context = tsk->mm->context; - if (tsk_context == ia64_ctx.next) { - if (++ia64_ctx.next >= ia64_ctx.limit) { - /* empty range: reset the range limit and start over */ - if (ia64_ctx.next > max_ctx) - ia64_ctx.next = 300; - ia64_ctx.limit = max_ctx + 1; - goto repeat; - } - } - if ((tsk_context > ia64_ctx.next) && (tsk_context < ia64_ctx.limit)) - ia64_ctx.limit = tsk_context; + next_ctx = find_next_bit(ia64_ctx.bitmap, ia64_ctx.limit, ia64_ctx.next); + if (next_ctx >= ia64_ctx.limit) { + next_ctx = ia64_ctx.limit; } - read_unlock(&tasklist_lock); + ia64_ctx.limit = next_ctx; + /* can't call flush_tlb_all() here because of race condition with O(1) scheduler [EF] */ { int cpu = get_cpu(); /* prevent preemption/migration */ --- linux-2.6.14-rc3/arch/ia64/kernel/setup.c 2005-10-26 10:54:06.000000000 -0400 +++ linux-2.6.14-rc3pmk/arch/ia64/kernel/setup.c 2005-10-25 14:53:59.000000000 -0400 @@ -419,6 +419,7 @@ #endif cpu_init(); /* initialize the bootstrap CPU */ + mmu_context_init(); /* initialize context_id bitmap */ #ifdef CONFIG_ACPI acpi_boot_init(); @@ -798,9 +799,13 @@ #endif /* set ia64_ctx.max_rid to the maximum RID that is supported by all CPUs: */ - if (ia64_pal_vm_summary(NULL, &vmi) == 0) + if (ia64_pal_vm_summary(NULL, &vmi) == 0) { max_ctx = (1U << (vmi.pal_vm_info_2_s.rid_size - 3)) - 1; - else { + if (max_ctx > (1U << 21)) { + max_ctx = (1U << 21) - 1; /* limit to 2^21 */ + printk(KERN_WARNING "cpu_init: max_ctx limited to 21 RID bits for bitmap size\n"); + } + } else { printk(KERN_WARNING "cpu_init: PAL VM summary failed, assuming 18 RID bits\n"); max_ctx = (1U << 15) - 1; /* use architected minimum */ }