diff options
author | Max Filippov <jcmvbkbc@gmail.com> | 2013-10-17 02:42:26 +0400 |
---|---|---|
committer | Chris Zankel <chris@zankel.net> | 2014-01-14 10:19:58 -0800 |
commit | f615136c06a791364f5afa8b8ba965315a6440f1 (patch) | |
tree | d9ced4cfdfd13438ce23384fbd64006bb74fd8b6 /arch/xtensa/mm | |
parent | 26a8e96a8b37e8070fa9dcb1b7490cf4d4492d50 (diff) | |
download | op-kernel-dev-f615136c06a791364f5afa8b8ba965315a6440f1.zip op-kernel-dev-f615136c06a791364f5afa8b8ba965315a6440f1.tar.gz |
xtensa: add SMP support
This is largely based on SMP code from the xtensa-2.6.29-smp tree by
Piet Delaney, Marc Gauthier, Joe Taylor, Christian Zankel (and possibly
other Tensilica folks).
Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
Signed-off-by: Chris Zankel <chris@zankel.net>
Diffstat (limited to 'arch/xtensa/mm')
-rw-r--r-- | arch/xtensa/mm/cache.c | 7 | ||||
-rw-r--r-- | arch/xtensa/mm/fault.c | 2 | ||||
-rw-r--r-- | arch/xtensa/mm/mmu.c | 4 | ||||
-rw-r--r-- | arch/xtensa/mm/tlb.c | 37 |
4 files changed, 28 insertions, 22 deletions
diff --git a/arch/xtensa/mm/cache.c b/arch/xtensa/mm/cache.c index 81edeab..ba4c47f 100644 --- a/arch/xtensa/mm/cache.c +++ b/arch/xtensa/mm/cache.c @@ -118,7 +118,7 @@ void flush_dcache_page(struct page *page) * For now, flush the whole cache. FIXME?? */ -void flush_cache_range(struct vm_area_struct* vma, +void local_flush_cache_range(struct vm_area_struct *vma, unsigned long start, unsigned long end) { __flush_invalidate_dcache_all(); @@ -132,7 +132,7 @@ void flush_cache_range(struct vm_area_struct* vma, * alias versions of the cache flush functions. */ -void flush_cache_page(struct vm_area_struct* vma, unsigned long address, +void local_flush_cache_page(struct vm_area_struct *vma, unsigned long address, unsigned long pfn) { /* Note that we have to use the 'alias' address to avoid multi-hit */ @@ -159,8 +159,7 @@ update_mmu_cache(struct vm_area_struct * vma, unsigned long addr, pte_t *ptep) /* Invalidate old entry in TLBs */ - invalidate_itlb_mapping(addr); - invalidate_dtlb_mapping(addr); + flush_tlb_page(vma, addr); #if (DCACHE_WAY_SIZE > PAGE_SIZE) && XCHAL_DCACHE_IS_WRITEBACK diff --git a/arch/xtensa/mm/fault.c b/arch/xtensa/mm/fault.c index 70fa7bc..b57c4f9 100644 --- a/arch/xtensa/mm/fault.c +++ b/arch/xtensa/mm/fault.c @@ -21,7 +21,7 @@ #include <asm/uaccess.h> #include <asm/pgalloc.h> -unsigned long asid_cache = ASID_USER_FIRST; +DEFINE_PER_CPU(unsigned long, asid_cache) = ASID_USER_FIRST; void bad_page_fault(struct pt_regs*, unsigned long, int); #undef DEBUG_PAGE_FAULT diff --git a/arch/xtensa/mm/mmu.c b/arch/xtensa/mm/mmu.c index c43771c..5bb8e3c 100644 --- a/arch/xtensa/mm/mmu.c +++ b/arch/xtensa/mm/mmu.c @@ -22,7 +22,7 @@ void __init paging_init(void) /* * Flush the mmu and reset associated register to default values. */ -void __init init_mmu(void) +void init_mmu(void) { #if !(XCHAL_HAVE_PTP_MMU && XCHAL_HAVE_SPANNING_WAY) /* @@ -37,7 +37,7 @@ void __init init_mmu(void) set_itlbcfg_register(0); set_dtlbcfg_register(0); #endif - flush_tlb_all(); + local_flush_tlb_all(); /* Set rasid register to a known value. */ diff --git a/arch/xtensa/mm/tlb.c b/arch/xtensa/mm/tlb.c index ca9d236..ade62382 100644 --- a/arch/xtensa/mm/tlb.c +++ b/arch/xtensa/mm/tlb.c @@ -48,7 +48,7 @@ static inline void __flush_dtlb_all (void) } -void flush_tlb_all (void) +void local_flush_tlb_all(void) { __flush_itlb_all(); __flush_dtlb_all(); @@ -60,19 +60,23 @@ void flush_tlb_all (void) * a new context will be assigned to it. */ -void flush_tlb_mm(struct mm_struct *mm) +void local_flush_tlb_mm(struct mm_struct *mm) { + int cpu = smp_processor_id(); + if (mm == current->active_mm) { unsigned long flags; local_irq_save(flags); - __get_new_mmu_context(mm); - __load_mmu_context(mm); + mm->context.asid[cpu] = NO_CONTEXT; + activate_context(mm, cpu); local_irq_restore(flags); + } else { + mm->context.asid[cpu] = NO_CONTEXT; + mm->context.cpu = -1; } - else - mm->context = 0; } + #define _ITLB_ENTRIES (ITLB_ARF_WAYS << XCHAL_ITLB_ARF_ENTRIES_LOG2) #define _DTLB_ENTRIES (DTLB_ARF_WAYS << XCHAL_DTLB_ARF_ENTRIES_LOG2) #if _ITLB_ENTRIES > _DTLB_ENTRIES @@ -81,24 +85,26 @@ void flush_tlb_mm(struct mm_struct *mm) # define _TLB_ENTRIES _DTLB_ENTRIES #endif -void flush_tlb_range (struct vm_area_struct *vma, - unsigned long start, unsigned long end) +void local_flush_tlb_range(struct vm_area_struct *vma, + unsigned long start, unsigned long end) { + int cpu = smp_processor_id(); struct mm_struct *mm = vma->vm_mm; unsigned long flags; - if (mm->context == NO_CONTEXT) + if (mm->context.asid[cpu] == NO_CONTEXT) return; #if 0 printk("[tlbrange<%02lx,%08lx,%08lx>]\n", - (unsigned long)mm->context, start, end); + (unsigned long)mm->context.asid[cpu], start, end); #endif local_irq_save(flags); if (end-start + (PAGE_SIZE-1) <= _TLB_ENTRIES << PAGE_SHIFT) { int oldpid = get_rasid_register(); - set_rasid_register (ASID_INSERT(mm->context)); + + set_rasid_register(ASID_INSERT(mm->context.asid[cpu])); start &= PAGE_MASK; if (vma->vm_flags & VM_EXEC) while(start < end) { @@ -114,24 +120,25 @@ void flush_tlb_range (struct vm_area_struct *vma, set_rasid_register(oldpid); } else { - flush_tlb_mm(mm); + local_flush_tlb_mm(mm); } local_irq_restore(flags); } -void flush_tlb_page (struct vm_area_struct *vma, unsigned long page) +void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page) { + int cpu = smp_processor_id(); struct mm_struct* mm = vma->vm_mm; unsigned long flags; int oldpid; - if(mm->context == NO_CONTEXT) + if (mm->context.asid[cpu] == NO_CONTEXT) return; local_irq_save(flags); oldpid = get_rasid_register(); - set_rasid_register(ASID_INSERT(mm->context)); + set_rasid_register(ASID_INSERT(mm->context.asid[cpu])); if (vma->vm_flags & VM_EXEC) invalidate_itlb_mapping(page); |