From 0b9049739779f6052eb8069f3dde7c3a7f14a591 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Wed, 28 Mar 2001 01:35:12 +0000 Subject: SMP for 32-bit kernel, support for Sibyte SB1. Patch from Justin with minor changes by me. --- include/asm-mips/hardirq.h | 49 +++++++++++++++++++++++++++++++++++++++++- include/asm-mips/mmu_context.h | 22 ++++++++++++++----- include/asm-mips/pgalloc.h | 2 ++ include/asm-mips/processor.h | 1 + include/asm-mips/smp.h | 30 ++++++++++++++++++++++++++ include/asm-mips/spinlock.h | 3 +++ include/asm-mips/stackframe.h | 24 ++++++++++++++++++--- include/asm-mips/system.h | 29 ++++++++++++++++++------- 8 files changed, 143 insertions(+), 17 deletions(-) (limited to 'include') diff --git a/include/asm-mips/hardirq.h b/include/asm-mips/hardirq.h index 3896706c7..28340dff3 100644 --- a/include/asm-mips/hardirq.h +++ b/include/asm-mips/hardirq.h @@ -12,6 +12,7 @@ #include #include #include +#include /* entry.S is sensitive to the offsets of these fields */ typedef struct { @@ -44,7 +45,53 @@ typedef struct { #else -#error No habla MIPS SMP +#include +#include +#include + +extern int global_irq_holder; +extern spinlock_t global_irq_lock; + +static inline int irqs_running (void) +{ + int i; + + for (i = 0; i < smp_num_cpus; i++) + if (local_irq_count(i)) + return 1; + return 0; +} + +static inline void release_irqlock(int cpu) +{ + /* if we didn't own the irq lock, just ignore.. */ + if (global_irq_holder == cpu) { + global_irq_holder = NO_PROC_ID; + spin_unlock(&global_irq_lock); + } +} + +static inline int hardirq_trylock(int cpu) +{ + return !local_irq_count(cpu) && !spin_is_locked(&global_irq_lock); +} + +#define hardirq_endlock(cpu) do { } while (0) + +static inline void irq_enter(int cpu, int irq) +{ + ++local_irq_count(cpu); + + while (spin_is_locked(&global_irq_lock)) + barrier(); +} + +static inline void irq_exit(int cpu, int irq) +{ + --local_irq_count(cpu); +} + +extern void synchronize_irq(void); #endif /* CONFIG_SMP */ #endif /* _ASM_HARDIRQ_H */ diff --git a/include/asm-mips/mmu_context.h b/include/asm-mips/mmu_context.h index 5912b9966..775e2d370 100644 --- a/include/asm-mips/mmu_context.h +++ b/include/asm-mips/mmu_context.h @@ -1,5 +1,4 @@ -/* $Id: mmu_context.h,v 1.7 2000/02/04 07:40:53 ralf Exp $ - * +/* * Switch a MMU context. * * This file is subject to the terms and conditions of the GNU General Public @@ -13,11 +12,12 @@ #define _ASM_MMU_CONTEXT_H #include +#include #include /* Fuck. The f-word is here so you can grep for it :-) */ extern unsigned long asid_cache; -extern pgd_t *current_pgd; +extern pgd_t *current_pgd[]; #if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_R3912) @@ -60,7 +60,19 @@ get_new_mmu_context(struct mm_struct *mm, unsigned long asid) extern inline int init_new_context(struct task_struct *tsk, struct mm_struct *mm) { +#ifndef CONFIG_SMP mm->context = 0; +#else + mm->context = (unsigned long)kmalloc(smp_num_cpus * + sizeof(unsigned long), GFP_KERNEL); + /* + * Init the "context" values so that a tlbpid allocation + * happens on the first switch. + */ + if (mm->context == 0) + return -ENOMEM; + memset((void *)mm->context, 0, smp_num_cpus * sizeof(unsigned long)); +#endif return 0; } @@ -73,7 +85,7 @@ extern inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, if ((next->context ^ asid) & ASID_VERSION_MASK) get_new_mmu_context(next, asid); - current_pgd = next->pgd; + current_pgd[cpu] = next->pgd; set_entryhi(next->context); } @@ -96,7 +108,7 @@ activate_mm(struct mm_struct *prev, struct mm_struct *next) /* Unconditionally get a new ASID. */ get_new_mmu_context(next, asid_cache); - current_pgd = next->pgd; + current_pgd[smp_processor_id()] = next->pgd; set_entryhi(next->context); } diff --git a/include/asm-mips/pgalloc.h b/include/asm-mips/pgalloc.h index 4f8c74dcf..0fa39f666 100644 --- a/include/asm-mips/pgalloc.h +++ b/include/asm-mips/pgalloc.h @@ -10,6 +10,7 @@ #define _ASM_PGALLOC_H #include +#include /* TLB flushing: * @@ -177,6 +178,7 @@ extern inline void pmd_free(pmd_t * pmd) extern inline pmd_t * pmd_alloc(pgd_t * pgd, unsigned long address) { + /* Two level page tables. This level is a nop */ return (pmd_t *) pgd; } diff --git a/include/asm-mips/processor.h b/include/asm-mips/processor.h index d658a010e..b0273cca1 100644 --- a/include/asm-mips/processor.h +++ b/include/asm-mips/processor.h @@ -29,6 +29,7 @@ #include struct mips_cpuinfo { + unsigned long udelay_val; unsigned long *pgd_quick; unsigned long *pte_quick; unsigned long pgtable_cache_sz; diff --git a/include/asm-mips/smp.h b/include/asm-mips/smp.h index 601826429..831dccafd 100644 --- a/include/asm-mips/smp.h +++ b/include/asm-mips/smp.h @@ -1,6 +1,36 @@ #ifndef __ASM_MIPS_SMP_H #define __ASM_MIPS_SMP_H +#include +#include +#include +#include + +#ifdef CONFIG_SMP + + +/* Mappings are straight across. If we want + to add support for disabling cpus and such, + we'll have to do what the mips64 port does here */ #define cpu_logical_map(cpu) (cpu) +#define cpu_number_map(cpu) (cpu) + +#define smp_processor_id() (current->processor) + + +/* I've no idea what the real meaning of this is */ +#define PROC_CHANGE_PENALTY 20 + +#define NO_PROC_ID (-1) + +struct smp_fn_call_struct { + spinlock_t lock; + atomic_t finished; + void (*fn)(void *); + void *data; +}; + +extern struct smp_fn_call_struct smp_fn_call; +#endif /* CONFIG_SMP */ #endif /* __ASM_MIPS_SMP_H */ diff --git a/include/asm-mips/spinlock.h b/include/asm-mips/spinlock.h index 4ac282bbc..61ebfa660 100644 --- a/include/asm-mips/spinlock.h +++ b/include/asm-mips/spinlock.h @@ -21,6 +21,9 @@ typedef struct { #define spin_lock_init(x) do { (x)->lock = 0; } while(0); +#define spin_is_locked(x) ((x)->lock != 0) +#define spin_unlock_wait(x) ({ do { barrier(); } while ((x)->lock); }) + /* * Simple spin lock operations. There are two variants, one clears IRQ's * on the local processor, one does not. diff --git a/include/asm-mips/stackframe.h b/include/asm-mips/stackframe.h index 2f436e79f..127654aab 100644 --- a/include/asm-mips/stackframe.h +++ b/include/asm-mips/stackframe.h @@ -8,6 +8,9 @@ #ifndef __ASM_MIPS_STACKFRAME_H #define __ASM_MIPS_STACKFRAME_H +#include +#include +#include #include #include #include @@ -70,6 +73,22 @@ __asm__ ( \ /* Used in declaration of save_static functions. */ #define static_unused static __attribute__((unused)) + +#ifdef CONFIG_SMP +# define GET_SAVED_SP \ + mfc0 k0, CP0_CONTEXT; \ + lui k1, %hi(kernelsp); \ + srl k0, k0, 23; \ + sll k0, k0, 2; \ + addu k1, k0; \ + lw k1, %lo(kernelsp)(k1); + +#else +# define GET_SAVED_SP \ + lui k1, %hi(kernelsp); \ + lw k1, %lo(kernelsp)(k1); +#endif + #define SAVE_SOME \ .set push; \ .set reorder; \ @@ -80,13 +99,12 @@ __asm__ ( \ move k1, sp; \ .set reorder; \ /* Called from user mode, new stack. */ \ - lui k1, %hi(kernelsp); \ - lw k1, %lo(kernelsp)(k1); \ + GET_SAVED_SP \ 8: \ move k0, sp; \ subu sp, k1, PT_SIZE; \ sw k0, PT_R29(sp); \ - sw $3, PT_R3(sp); \ + sw $3, PT_R3(sp); \ sw $0, PT_R0(sp); \ mfc0 v1, CP0_STATUS; \ sw $2, PT_R2(sp); \ diff --git a/include/asm-mips/system.h b/include/asm-mips/system.h index 68117be89..1c1c8c575 100644 --- a/include/asm-mips/system.h +++ b/include/asm-mips/system.h @@ -115,14 +115,27 @@ do { \ : "$1", "memory"); \ } while(0) -/* - * Non-SMP versions ... - */ -#define sti() __sti() -#define cli() __cli() -#define save_flags(x) __save_flags(x) -#define save_and_cli(x) __save_and_cli(x) -#define restore_flags(x) __restore_flags(x) +#ifdef CONFIG_SMP + +extern void __global_sti(void); +extern void __global_cli(void); +extern unsigned long __global_save_flags(void); +extern void __global_restore_flags(unsigned long); +# define sti() __global_sti() +# define cli() __global_cli() +# define save_flags(x) do { x = __global_save_flags(); } while (0) +# define restore_flags(x) __global_restore_flags(x) +# define save_and_cli(x) do { save_flags(x); cli(); } while(0) + +#else /* Single processor */ + +# define sti() __sti() +# define cli() __cli() +# define save_flags(x) __save_flags(x) +# define save_and_cli(x) __save_and_cli(x) +# define restore_flags(x) __restore_flags(x) + +#endif /* SMP */ /* For spinlocks etc */ #define local_irq_save(x) __save_and_cli(x); -- cgit v1.2.3