summaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2001-03-28 01:35:12 +0000
committerRalf Baechle <ralf@linux-mips.org>2001-03-28 01:35:12 +0000
commit0b9049739779f6052eb8069f3dde7c3a7f14a591 (patch)
tree9630c1ea481dd1c429a2692067316237957d6e07 /include
parent12e00f34ea0db712ce70bc3eed334c81b3d6a344 (diff)
SMP for 32-bit kernel, support for Sibyte SB1. Patch from Justin
with minor changes by me.
Diffstat (limited to 'include')
-rw-r--r--include/asm-mips/hardirq.h49
-rw-r--r--include/asm-mips/mmu_context.h22
-rw-r--r--include/asm-mips/pgalloc.h2
-rw-r--r--include/asm-mips/processor.h1
-rw-r--r--include/asm-mips/smp.h30
-rw-r--r--include/asm-mips/spinlock.h3
-rw-r--r--include/asm-mips/stackframe.h24
-rw-r--r--include/asm-mips/system.h29
8 files changed, 143 insertions, 17 deletions
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 <linux/config.h>
#include <linux/threads.h>
#include <linux/irq.h>
+#include <linux/spinlock.h>
/* 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 <asm/atomic.h>
+#include <linux/spinlock.h>
+#include <asm/smp.h>
+
+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 <linux/config.h>
+#include <linux/slab.h>
#include <asm/pgalloc.h>
/* 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 <linux/config.h>
+#include <linux/mm.h>
/* 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 <asm/system.h>
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 <linux/config.h>
+#include <asm/spinlock.h>
+#include <asm/atomic.h>
+#include <asm/current.h>
+
+#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 <asm/addrspace.h>
+#include <asm/mipsregs.h>
+#include <asm/processor.h>
#include <asm/asm.h>
#include <asm/offset.h>
#include <linux/config.h>
@@ -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);