--- 2.2.18pre21aa2/arch/alpha/kernel/smp.c.~1~ Wed Nov 22 02:32:53 2000 +++ 2.2.18pre21aa2/arch/alpha/kernel/smp.c Thu Nov 23 04:48:24 2000 @@ -95,8 +95,7 @@ smp_store_cpu_info(int cpuid) { cpu_data[cpuid].loops_per_jiffy = loops_per_jiffy; - cpu_data[cpuid].last_asn - = (cpuid << WIDTH_HARDWARE_ASN) + ASN_FIRST_VERSION; + cpu_data[cpuid].last_asn = ASN_FIRST_VERSION; cpu_data[cpuid].irq_count = 0; cpu_data[cpuid].bh_count = 0; @@ -905,6 +904,8 @@ struct mm_struct *mm = (struct mm_struct *) x; if (mm == current->mm) flush_tlb_current(mm); + else + flush_tlb_other(mm); } void @@ -912,10 +913,17 @@ { if (mm == current->mm) { flush_tlb_current(mm); - if (atomic_read(&mm->count) == 1) + if (atomic_read(&mm->count) == 1) { + int i, cpu, this_cpu = smp_processor_id(); + for (i = 0; i < smp_num_cpus; i++) { + cpu = cpu_logical_map(i); + if (cpu == this_cpu) + continue; + mm->context[cpu] = 0; + } return; - } else - flush_tlb_other(mm); + } + } if (smp_call_function(ipi_flush_tlb_mm, mm, 1, 1)) { printk(KERN_CRIT "flush_tlb_mm: timed out\n"); @@ -932,8 +940,12 @@ ipi_flush_tlb_page(void *x) { struct flush_tlb_page_struct *data = (struct flush_tlb_page_struct *)x; - if (data->mm == current->mm) - flush_tlb_current_page(data->mm, data->vma, data->addr); + struct mm_struct * mm = data->mm; + + if (mm == current->mm) + flush_tlb_current_page(mm, data->vma, data->addr); + else + flush_tlb_other(mm); } void @@ -944,10 +956,17 @@ if (mm == current->mm) { flush_tlb_current_page(mm, vma, addr); - if (atomic_read(¤t->mm->count) == 1) + if (atomic_read(¤t->mm->count) == 1) { + int i, cpu, this_cpu = smp_processor_id(); + for (i = 0; i < smp_num_cpus; i++) { + cpu = cpu_logical_map(i); + if (cpu == this_cpu) + continue; + mm->context[cpu] = 0; + } return; - } else - flush_tlb_other(mm); + } + } data.vma = vma; data.mm = mm; --- 2.2.18pre21aa2/arch/alpha/mm/fault.c.~1~ Wed Nov 22 02:32:53 2000 +++ 2.2.18pre21aa2/arch/alpha/mm/fault.c Wed Nov 22 22:39:50 2000 @@ -41,7 +41,7 @@ get_new_mmu_context(struct task_struct *p, struct mm_struct *mm) { unsigned long new = __get_new_mmu_context(); - mm->context = new; + mm->context[smp_processor_id()] = new; p->tss.asn = new & HARDWARE_ASN_MASK; } --- 2.2.18pre21aa2/include/asm-alpha/mmu_context.h.~1~ Wed Nov 22 02:32:53 2000 +++ 2.2.18pre21aa2/include/asm-alpha/mmu_context.h Thu Nov 23 21:59:06 2000 @@ -65,12 +65,7 @@ #endif /* __SMP__ */ #define WIDTH_HARDWARE_ASN 8 -#ifdef __SMP__ -#define WIDTH_THIS_PROCESSOR 5 -#else -#define WIDTH_THIS_PROCESSOR 0 -#endif -#define ASN_FIRST_VERSION (1UL << (WIDTH_THIS_PROCESSOR + WIDTH_HARDWARE_ASN)) +#define ASN_FIRST_VERSION (1UL << WIDTH_HARDWARE_ASN) #define HARDWARE_ASN_MASK ((1UL << WIDTH_HARDWARE_ASN) - 1) /* @@ -100,6 +95,7 @@ /* If we've wrapped, flush the whole user TLB. */ if ((asn & HARDWARE_ASN_MASK) >= MAX_ASN) { tbiap(); + imb(); next = (asn & ~HARDWARE_ASN_MASK) + ASN_FIRST_VERSION; } cpu_last_asn(smp_processor_id()) = next; @@ -125,19 +121,21 @@ __EXTERN_INLINE void ev5_get_mmu_context(struct task_struct *p) { - /* Check if our ASN is of an older version, or on a different CPU, - and thus invalid. */ - /* ??? If we have two threads on different cpus, we'll continually - fight over the context. Find a way to record a per-mm, per-cpu - value for the asn. */ - - unsigned long asn = cpu_last_asn(smp_processor_id()); - struct mm_struct *mm = p->mm; - unsigned long mmc = mm->context; + /* Check if our ASN is of an older version, and thus invalid. */ + int cpu; + unsigned long asn; + struct mm_struct *mm; + unsigned long mmc; + cpu = smp_processor_id(); + mm = p->mm; + ctx_cli(); + asn = cpu_last_asn(cpu); + mmc = mm->context[cpu]; + if ((mmc ^ asn) & ~HARDWARE_ASN_MASK) { mmc = __get_new_mmu_context(); - mm->context = mmc; + mm->context[cpu] = mmc; } /* Always update the PCB ASN. Another thread may have allocated @@ -159,7 +157,10 @@ extern inline void init_new_context(struct mm_struct *mm) { - mm->context = 0; + int i; + + for (i = 0; i < smp_num_cpus; i++) + mm->context[cpu_logical_map(i)] = 0; } extern inline void @@ -213,6 +214,13 @@ extern inline void activate_context(struct task_struct *task) { + int i, cpu, this_cpu = smp_processor_id(); + for (i = 0; i < smp_num_cpus; i++) { + cpu = cpu_logical_map(i); + if (cpu == this_cpu) + continue; + task->mm->context[cpu] = 0; + } get_new_mmu_context(task, task->mm); reload_context(task); } --- 2.2.18pre21aa2/include/asm-alpha/pgtable.h.~1~ Wed Nov 22 05:30:43 2000 +++ 2.2.18pre21aa2/include/asm-alpha/pgtable.h Thu Nov 23 05:55:22 2000 @@ -73,7 +73,7 @@ __EXTERN_INLINE void ev5_flush_tlb_other(struct mm_struct *mm) { - mm->context = 0; + mm->context[smp_processor_id()] = 0; } /* --- 2.2.18pre21aa2/include/asm-alpha/system.h.~1~ Thu Nov 16 17:55:21 2000 +++ 2.2.18pre21aa2/include/asm-alpha/system.h Thu Nov 23 21:58:57 2000 @@ -112,12 +112,21 @@ extern void halt(void) __attribute__((noreturn)); +#ifdef CONFIG_SMP +#define ctx_cli() __cli() +#define ctx_sti() __sti() +#else +#define ctx_cli() do { } while(0) +#define ctx_sti() do { } while(0) +#endif + #define switch_to(prev,next,last) \ do { \ unsigned long pcbb; \ current = (next); \ pcbb = virt_to_phys(¤t->tss); \ (last) = alpha_switch_to(pcbb, (prev)); \ + ctx_sti(); \ } while (0) extern struct task_struct* alpha_switch_to(unsigned long, struct task_struct*); --- 2.2.18pre21aa2/include/linux/sched.h.~1~ Wed Nov 22 02:32:53 2000 +++ 2.2.18pre21aa2/include/linux/sched.h Thu Nov 23 22:02:53 2000 @@ -181,7 +181,11 @@ atomic_t count; int map_count; /* number of VMAs */ struct semaphore mmap_sem; +#ifdef __alpha__ + unsigned long context[NR_CPUS]; +#else unsigned long context; +#endif unsigned long start_code, end_code, start_data, end_data; unsigned long start_brk, brk, start_stack; unsigned long arg_start, arg_end, env_start, env_end; @@ -197,12 +201,18 @@ void * segments; }; +#ifdef __alpha__ +#define CONTEXT_INIT { 0, } +#else +#define CONTEXT_INIT 0 +#endif + #define INIT_MM { \ &init_mmap, NULL, NULL, \ swapper_pg_dir, \ ATOMIC_INIT(1), 1, \ MUTEX, \ - 0, \ + CONTEXT_INIT, \ 0, 0, 0, 0, \ 0, 0, 0, \ 0, 0, 0, 0, \