···33 *44 * CPU init code55 *66- * Copyright (C) 2002, 2003 Paul Mundt66+ * Copyright (C) 2002 - 2006 Paul Mundt77 * Copyright (C) 2003 Richard Curnow88 *99 * This file is subject to the terms and conditions of the GNU General Public···1212 */1313#include <linux/init.h>1414#include <linux/kernel.h>1515+#include <linux/mm.h>1616+#include <asm/mmu_context.h>1517#include <asm/processor.h>1618#include <asm/uaccess.h>1719#include <asm/page.h>···220218 clear_used_math();221219 }222220221221+ /*222222+ * Initialize the per-CPU ASID cache very early, since the223223+ * TLB flushing routines depend on this being setup.224224+ */225225+ current_cpu_data.asid_cache = NO_CONTEXT;226226+223227#ifdef CONFIG_SH_DSP224228 /* Probe for DSP */225229 dsp_init();···248240 ubc_wakeup();249241#endif250242}251251-
+28-38
arch/sh/kernel/process.c
···11-/* $Id: process.c,v 1.28 2004/05/05 16:54:23 lethal Exp $11+/*22+ * arch/sh/kernel/process.c23 *33- * linux/arch/sh/kernel/process.c44+ * This file handles the architecture-dependent parts of process handling..45 *56 * Copyright (C) 1995 Linus Torvalds67 *78 * SuperH version: Copyright (C) 1999, 2000 Niibe Yutaka & Kaz Kojima89 * Copyright (C) 2006 Lineo Solutions Inc. support SH4A UBC1010+ * Copyright (C) 2002 - 2006 Paul Mundt911 */1010-1111-/*1212- * This file handles the architecture-dependent parts of process handling..1313- */1414-1512#include <linux/module.h>1616-#include <linux/unistd.h>1713#include <linux/mm.h>1814#include <linux/elfcore.h>1919-#include <linux/a.out.h>2020-#include <linux/slab.h>2115#include <linux/pm.h>2222-#include <linux/ptrace.h>2316#include <linux/kallsyms.h>2417#include <linux/kexec.h>2525-2626-#include <asm/io.h>2718#include <asm/uaccess.h>2819#include <asm/mmu_context.h>2929-#include <asm/elf.h>3020#include <asm/ubc.h>31213232-static int hlt_counter=0;3333-2222+static int hlt_counter;3423int ubc_usercnt = 0;35243625#define HARD_IDLE_TIMEOUT (HZ / 3)37263827void (*pm_idle)(void);3939-4028void (*pm_power_off)(void);4129EXPORT_SYMBOL(pm_power_off);4230···3244{3345 hlt_counter++;3446}3535-3647EXPORT_SYMBOL(disable_hlt);37483849void enable_hlt(void)3950{4051 hlt_counter--;4152}4242-4353EXPORT_SYMBOL(enable_hlt);44544555void default_idle(void)···138152 ".align 2\n\t"139153 "1:.long do_exit");140154155155+/* Don't use this in BL=1(cli). Or else, CPU resets! */141156int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)142142-{ /* Don't use this in BL=1(cli). Or else, CPU resets! */157157+{143158 struct pt_regs regs;144159145160 memset(®s, 0, sizeof(regs));146146- regs.regs[4] = (unsigned long) arg;147147- regs.regs[5] = (unsigned long) fn;161161+ regs.regs[4] = (unsigned long)arg;162162+ regs.regs[5] = (unsigned long)fn;148163149149- regs.pc = (unsigned long) kernel_thread_helper;164164+ regs.pc = (unsigned long)kernel_thread_helper;150165 regs.sr = (1 << 30);151166152167 /* Ok, create the new process.. */153153- return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, ®s, 0, NULL, NULL);168168+ return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0,169169+ ®s, 0, NULL, NULL);154170}155171156172/*···199211 return fpvalid;200212}201213202202-/* 214214+/*203215 * Capture the user space registers if the task is not running (in user space)204216 */205217int dump_task_regs(struct task_struct *tsk, elf_gregset_t *regs)206218{207219 struct pt_regs ptregs;208208-220220+209221 ptregs = *task_pt_regs(tsk);210222 elf_core_copy_regs(regs, &ptregs);211223212224 return 1;213225}214226215215-int216216-dump_task_fpu (struct task_struct *tsk, elf_fpregset_t *fpu)227227+int dump_task_fpu(struct task_struct *tsk, elf_fpregset_t *fpu)217228{218229 int fpvalid = 0;219230···250263 childregs->regs[15] = usp;251264 ti->addr_limit = USER_DS;252265 } else {253253- childregs->regs[15] = (unsigned long)task_stack_page(p) + THREAD_SIZE;266266+ childregs->regs[15] = (unsigned long)task_stack_page(p) +267267+ THREAD_SIZE;254268 ti->addr_limit = KERNEL_DS;255269 }256256- if (clone_flags & CLONE_SETTLS) {270270+271271+ if (clone_flags & CLONE_SETTLS)257272 childregs->gbr = childregs->regs[0];258258- }273273+259274 childregs->regs[0] = 0; /* Set return value for child */260275261276 p->thread.sp = (unsigned long) childregs;···269280}270281271282/* Tracing by user break controller. */272272-static void273273-ubc_set_tracing(int asid, unsigned long pc)283283+static void ubc_set_tracing(int asid, unsigned long pc)274284{275285#if defined(CONFIG_CPU_SH4A)276286 unsigned long val;···285297 val = (UBC_CRR_RES | UBC_CRR_PCB | UBC_CRR_BIE);286298 ctrl_outl(val, UBC_CRR0);287299288288- /* Read UBC register that we writed last. For chekking UBC Register changed */300300+ /* Read UBC register that we wrote last, for checking update */289301 val = ctrl_inl(UBC_CRR0);290302291303#else /* CONFIG_CPU_SH4A */···313325 * switch_to(x,y) should switch tasks from x to y.314326 *315327 */316316-struct task_struct *__switch_to(struct task_struct *prev, struct task_struct *next)328328+struct task_struct *__switch_to(struct task_struct *prev,329329+ struct task_struct *next)317330{318331#if defined(CONFIG_SH_FPU)319332 unlazy_fpu(prev, task_pt_regs(prev));···343354#ifdef CONFIG_MMU344355 /*345356 * Restore the kernel mode register346346- * k7 (r7_bank1)357357+ * k7 (r7_bank1)347358 */348359 asm volatile("ldc %0, r7_bank"349360 : /* no output */···356367 else if (next->thread.ubc_pc && next->mm) {357368 int asid = 0;358369#ifdef CONFIG_MMU359359- asid |= next->mm->context.id & MMU_CONTEXT_ASID_MASK;370370+ asid |= cpu_asid(smp_processor_id(), next->mm);360371#endif361372 ubc_set_tracing(asid, next->thread.ubc_pc);362373 } else {···394405 if (!newsp)395406 newsp = regs->regs[15];396407 return do_fork(clone_flags, newsp, regs, 0,397397- (int __user *)parent_tidptr, (int __user *)child_tidptr);408408+ (int __user *)parent_tidptr,409409+ (int __user *)child_tidptr);398410}399411400412/*
-5
arch/sh/mm/init.c
···3939DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);4040pgd_t swapper_pg_dir[PTRS_PER_PGD];41414242-/*4343- * Cache of MMU context last used.4444- */4545-unsigned long mmu_context_cache = NO_CONTEXT;4646-4742#ifdef CONFIG_MMU4843/* It'd be good if these lines were in the standard header file. */4944#define START_PFN (NODE_DATA(0)->bdata->node_boot_start >> PAGE_SHIFT)
+16-10
arch/sh/mm/tlb-flush.c
···16161717void flush_tlb_page(struct vm_area_struct *vma, unsigned long page)1818{1919- if (vma->vm_mm && vma->vm_mm->context.id != NO_CONTEXT) {1919+ unsigned int cpu = smp_processor_id();2020+2121+ if (vma->vm_mm && cpu_context(cpu, vma->vm_mm) != NO_CONTEXT) {2022 unsigned long flags;2123 unsigned long asid;2224 unsigned long saved_asid = MMU_NO_ASID;23252424- asid = vma->vm_mm->context.id & MMU_CONTEXT_ASID_MASK;2626+ asid = cpu_asid(cpu, vma->vm_mm);2527 page &= PAGE_MASK;26282729 local_irq_save(flags);···4240 unsigned long end)4341{4442 struct mm_struct *mm = vma->vm_mm;4343+ unsigned int cpu = smp_processor_id();45444646- if (mm->context.id != NO_CONTEXT) {4545+ if (cpu_context(cpu, mm) != NO_CONTEXT) {4746 unsigned long flags;4847 int size;49485049 local_irq_save(flags);5150 size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT;5251 if (size > (MMU_NTLB_ENTRIES/4)) { /* Too many TLB to flush */5353- mm->context.id = NO_CONTEXT;5252+ cpu_context(cpu, mm) = NO_CONTEXT;5453 if (mm == current->mm)5555- activate_context(mm);5454+ activate_context(mm, cpu);5655 } else {5756 unsigned long asid;5857 unsigned long saved_asid = MMU_NO_ASID;59586060- asid = mm->context.id & MMU_CONTEXT_ASID_MASK;5959+ asid = cpu_asid(cpu, mm);6160 start &= PAGE_MASK;6261 end += (PAGE_SIZE - 1);6362 end &= PAGE_MASK;···79768077void flush_tlb_kernel_range(unsigned long start, unsigned long end)8178{7979+ unsigned int cpu = smp_processor_id();8280 unsigned long flags;8381 int size;8482···9187 unsigned long asid;9288 unsigned long saved_asid = get_asid();93899494- asid = init_mm.context.id & MMU_CONTEXT_ASID_MASK;9090+ asid = cpu_asid(cpu, &init_mm);9591 start &= PAGE_MASK;9692 end += (PAGE_SIZE - 1);9793 end &= PAGE_MASK;···107103108104void flush_tlb_mm(struct mm_struct *mm)109105{106106+ unsigned int cpu = smp_processor_id();107107+110108 /* Invalidate all TLB of this process. */111109 /* Instead of invalidating each TLB, we get new MMU context. */112112- if (mm->context.id != NO_CONTEXT) {110110+ if (cpu_context(cpu, mm) != NO_CONTEXT) {113111 unsigned long flags;114112115113 local_irq_save(flags);116116- mm->context.id = NO_CONTEXT;114114+ cpu_context(cpu, mm) = NO_CONTEXT;117115 if (mm == current->mm)118118- activate_context(mm);116116+ activate_context(mm, cpu);119117 local_irq_restore(flags);120118 }121119}
···11/*22 * Copyright (C) 1999 Niibe Yutaka33- * Copyright (C) 2003 Paul Mundt33+ * Copyright (C) 2003 - 2006 Paul Mundt44 *55 * ASID handling idea taken from MIPS implementation.66 */···1919 * (b) ASID (Address Space IDentifier)2020 */21212222-/*2323- * Cache of MMU context last used.2424- */2525-extern unsigned long mmu_context_cache;2626-2722#define MMU_CONTEXT_ASID_MASK 0x000000ff2823#define MMU_CONTEXT_VERSION_MASK 0xffffff002924#define MMU_CONTEXT_FIRST_VERSION 0x00000100···26312732/* ASID is 8-bit value, so it can't be 0x100 */2833#define MMU_NO_ASID 0x1003434+3535+#define cpu_context(cpu, mm) ((mm)->context.id[cpu])3636+#define cpu_asid(cpu, mm) (cpu_context((cpu), (mm)) & \3737+ MMU_CONTEXT_ASID_MASK)3838+#define asid_cache(cpu) (cpu_data[cpu].asid_cache)29393040/*3141 * Virtual Page Number mask···4141/*4242 * Get MMU context if needed.4343 */4444-static inline void get_mmu_context(struct mm_struct *mm)4444+static inline void get_mmu_context(struct mm_struct *mm, unsigned int cpu)4545{4646- unsigned long mc = mmu_context_cache;4646+ unsigned long asid = asid_cache(cpu);47474848 /* Check if we have old version of context. */4949- if (((mm->context.id ^ mc) & MMU_CONTEXT_VERSION_MASK) == 0)4949+ if (((cpu_context(cpu, mm) ^ asid) & MMU_CONTEXT_VERSION_MASK) == 0)5050 /* It's up to date, do nothing */5151 return;52525353 /* It's old, we need to get new context with new version. */5454- mc = ++mmu_context_cache;5555- if (!(mc & MMU_CONTEXT_ASID_MASK)) {5454+ if (!(++asid & MMU_CONTEXT_ASID_MASK)) {5655 /*5756 * We exhaust ASID of this version.5857 * Flush all TLB and start new cycle.···6263 * Fix version; Note that we avoid version #06364 * to distingush NO_CONTEXT.6465 */6565- if (!mc)6666- mmu_context_cache = mc = MMU_CONTEXT_FIRST_VERSION;6666+ if (!asid)6767+ asid = MMU_CONTEXT_FIRST_VERSION;6768 }6868- mm->context.id = mc;6969+7070+ cpu_context(cpu, mm) = asid_cache(cpu) = asid;6971}70727173/*···7474 * instance.7575 */7676static inline int init_new_context(struct task_struct *tsk,7777- struct mm_struct *mm)7777+ struct mm_struct *mm)7878{7979- mm->context.id = NO_CONTEXT;7979+ int i;8080+8181+ for (i = 0; i < num_online_cpus(); i++)8282+ cpu_context(i, mm) = NO_CONTEXT;8383+8084 return 0;8185}8286···121117 * After we have set current->mm to a new value, this activates122118 * the context for the new mm so we see the new mappings.123119 */124124-static inline void activate_context(struct mm_struct *mm)120120+static inline void activate_context(struct mm_struct *mm, unsigned int cpu)125121{126126- get_mmu_context(mm);127127- set_asid(mm->context.id & MMU_CONTEXT_ASID_MASK);122122+ get_mmu_context(mm, cpu);123123+ set_asid(cpu_asid(cpu, mm));128124}129125130126/* MMU_TTB is used for optimizing the fault handling. */···142138 struct mm_struct *next,143139 struct task_struct *tsk)144140{141141+ unsigned int cpu = smp_processor_id();142142+145143 if (likely(prev != next)) {144144+ cpu_set(cpu, next->cpu_vm_mask);146145 set_TTB(next->pgd);147147- activate_context(next);148148- }146146+ activate_context(next, cpu);147147+ } else148148+ if (!cpu_test_and_set(cpu, next->cpu_vm_mask))149149+ activate_context(next, cpu);149150}150151151152#define deactivate_mm(tsk,mm) do { } while (0)···168159#define destroy_context(mm) do { } while (0)169160#define set_asid(asid) do { } while (0)170161#define get_asid() (0)171171-#define activate_context(mm) do { } while (0)162162+#define activate_context(mm,cpu) do { } while (0)172163#define switch_mm(prev,next,tsk) do { } while (0)173164#define deactivate_mm(tsk,mm) do { } while (0)174165#define activate_mm(prev,next) do { } while (0)···183174 */184175static inline void enable_mmu(void)185176{177177+ unsigned int cpu = smp_processor_id();178178+186179 /* Enable MMU */187180 ctrl_outl(MMU_CONTROL_INIT, MMUCR);188181 ctrl_barrier();189182190190- if (mmu_context_cache == NO_CONTEXT)191191- mmu_context_cache = MMU_CONTEXT_FIRST_VERSION;183183+ if (asid_cache(cpu) == NO_CONTEXT)184184+ asid_cache(cpu) = MMU_CONTEXT_FIRST_VERSION;192185193193- set_asid(mmu_context_cache & MMU_CONTEXT_ASID_MASK);186186+ set_asid(asid_cache(cpu) & MMU_CONTEXT_ASID_MASK);194187}195188196189static inline void disable_mmu(void)
+1
include/asm-sh/processor.h
···6666struct sh_cpuinfo {6767 unsigned int type;6868 unsigned long loops_per_jiffy;6969+ unsigned long asid_cache;69707071 struct cache_info icache; /* Primary I-cache */7172 struct cache_info dcache; /* Primary D-cache */