summaryrefslogtreecommitdiffstats
path: root/include/asm-sparc/system.h
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>1997-01-07 02:33:00 +0000
committer <ralf@linux-mips.org>1997-01-07 02:33:00 +0000
commitbeb116954b9b7f3bb56412b2494b562f02b864b1 (patch)
tree120e997879884e1b9d93b265221b939d2ef1ade1 /include/asm-sparc/system.h
parent908d4681a1dc3792ecafbe64265783a86c4cccb6 (diff)
Import of Linux/MIPS 2.1.14
Diffstat (limited to 'include/asm-sparc/system.h')
-rw-r--r--include/asm-sparc/system.h311
1 files changed, 213 insertions, 98 deletions
diff --git a/include/asm-sparc/system.h b/include/asm-sparc/system.h
index 3c4a62c9a..34800571c 100644
--- a/include/asm-sparc/system.h
+++ b/include/asm-sparc/system.h
@@ -1,135 +1,250 @@
+/* $Id: system.h,v 1.42 1996/09/30 02:23:21 davem Exp $ */
#ifndef __SPARC_SYSTEM_H
#define __SPARC_SYSTEM_H
-#include <asm/segment.h>
+#include <linux/kernel.h>
-/*
- * System defines.. Note that this is included both from .c and .S
- * files, so it does only defines, not any C code.
- */
-
-/*
- * I wish the boot time image was as beautiful as the Alpha's
- * but no such luck. The icky PROM loads us at 0x0, and jumps
- * to magic address 0x4000 to start thing going. This means that
- * I can stick the pcb and user/kernel stacks in the area from
- * 0x0-0x4000 and be reasonably sure that this is sane.
- *
- * Sorry, I can't impress people with cool looking 64-bit values
- * yet. ;-)
- */
+#include <asm/segment.h>
-#include <asm/openprom.h>
+#ifdef __KERNEL__
+#include <asm/page.h>
+#include <asm/oplib.h>
#include <asm/psr.h>
+#endif
-#define INIT_PCB 0x00011fe0
-#define INIT_STACK 0x00013fe0
-#define START_ADDR 0x00004000
-#define START_SIZE (32*1024)
-#define EMPTY_PGT 0x00001000
-#define EMPTY_PGE 0x00001000
-#define ZERO_PGE 0x00001000
-
-#define IRQ_ENA_ADR 0x2000 /* This is a bitmap of all activated IRQ's
- * which is mapped in head.S during boot.
- */
+#define EMPTY_PGT (&empty_bad_page)
+#define EMPTY_PGE (&empty_bad_page_table)
#ifndef __ASSEMBLY__
-extern void wrent(void *, unsigned long);
-extern void wrkgp(unsigned long);
-extern struct linux_romvec *romvec;
+/*
+ * Sparc (general) CPU types
+ */
+enum sparc_cpu {
+ sun4 = 0x00,
+ sun4c = 0x01,
+ sun4m = 0x02,
+ sun4d = 0x03,
+ sun4e = 0x04,
+ sun4u = 0x05, /* V8 ploos ploos */
+ sun_unknown = 0x06,
+};
+
+extern enum sparc_cpu sparc_cpu_model;
+
+extern unsigned long empty_bad_page;
+extern unsigned long empty_bad_page_table;
+extern unsigned long empty_zero_page;
-#define halt() { romvec->pv_halt(); }
-#define move_to_user_mode() halt()
-#define switch_to(x) halt()
+extern struct linux_romvec *romvec;
+#define halt() romvec->pv_halt()
-#ifndef stbar /* store barrier Sparc insn to synchronize stores in PSO */
-#define stbar() __asm__ __volatile__("stbar": : :"memory")
+/* When a context switch happens we must flush all user windows so that
+ * the windows of the current process are flushed onto its stack. This
+ * way the windows are all clean for the next process and the stack
+ * frames are up to date.
+ */
+extern void flush_user_windows(void);
+extern void synchronize_user_stack(void);
+extern void fpsave(unsigned long *fpregs, unsigned long *fsr,
+ void *fpqueue, unsigned long *fpqdepth);
+
+#ifdef __SMP__
+#define SWITCH_ENTER \
+ cli(); \
+ if(prev->flags & PF_USEDFPU) { \
+ fpsave(&prev->tss.float_regs[0], &prev->tss.fsr, \
+ &prev->tss.fpqueue[0], &prev->tss.fpqdepth); \
+ prev->flags &= ~PF_USEDFPU; \
+ prev->tss.kregs->psr &= ~PSR_EF; \
+ } \
+ prev->lock_depth = syscall_count; \
+ kernel_counter += (next->lock_depth - prev->lock_depth); \
+ syscall_count = next->lock_depth;
+
+#define SWITCH_EXIT sti();
+#define SWITCH_DO_LAZY_FPU
+#else
+#define SWITCH_ENTER
+#define SWITCH_EXIT
+#define SWITCH_DO_LAZY_FPU if(last_task_used_math != next) next->tss.kregs->psr&=~PSR_EF;
#endif
-/* Changing the PIL on the sparc is a bit hairy. I'll figure out some
- * more optimized way of doing this soon. This is bletcherous code.
+ /* Much care has gone into this code, do not touch it. */
+#define switch_to(prev, next) do { \
+ __label__ here; \
+ register unsigned long task_pc asm("o7"); \
+ SWITCH_ENTER \
+ SWITCH_DO_LAZY_FPU \
+ __asm__ __volatile__( \
+ ".globl\tflush_patch_switch\nflush_patch_switch:\n\t" \
+ "save %sp, -0x40, %sp; save %sp, -0x40, %sp; save %sp, -0x40, %sp\n\t" \
+ "save %sp, -0x40, %sp; save %sp, -0x40, %sp; save %sp, -0x40, %sp\n\t" \
+ "save %sp, -0x40, %sp\n\t" \
+ "restore; restore; restore; restore; restore; restore; restore"); \
+ if(!(next->tss.flags & SPARC_FLAG_KTHREAD) && \
+ !(next->flags & PF_EXITING)) \
+ switch_to_context(next); \
+ task_pc = ((unsigned long) &&here) - 0x8; \
+ __asm__ __volatile__( \
+ "rd\t%%psr, %%g4\n\t" \
+ "std\t%%sp, [%%g6 + %3]\n\t" \
+ "rd\t%%wim, %%g5\n\t" \
+ "wr\t%%g4, 0x20, %%psr\n\t" \
+ "std\t%%g4, [%%g6 + %2]\n\t" \
+ "mov\t%1, %%g6\n\t" \
+ "ldd\t[%%g6 + %2], %%g4\n\t" \
+ "st\t%1, [%0]\n\t" \
+ "wr\t%%g4, 0x20, %%psr\n\t" \
+ "ldd\t[%%g6 + %3], %%sp\n\t" \
+ "wr\t%%g5, 0x0, %%wim\n\t" \
+ "ldd\t[%%sp + 0x00], %%l0\n\t" \
+ "ldd\t[%%sp + 0x08], %%l2\n\t" \
+ "ldd\t[%%sp + 0x10], %%l4\n\t" \
+ "ldd\t[%%sp + 0x18], %%l6\n\t" \
+ "ldd\t[%%sp + 0x20], %%i0\n\t" \
+ "ldd\t[%%sp + 0x28], %%i2\n\t" \
+ "ldd\t[%%sp + 0x30], %%i4\n\t" \
+ "ldd\t[%%sp + 0x38], %%i6\n\t" \
+ "wr\t%%g4, 0x0, %%psr\n\t" \
+ "nop\n\t" \
+ "jmpl\t%%o7 + 0x8, %%g0\n\t" \
+ " nop\n\t" : : "r" (&(current_set[smp_processor_id()])), "r" (next), \
+ "i" ((const unsigned long)(&((struct task_struct *)0)->tss.kpsr)), \
+ "i" ((const unsigned long)(&((struct task_struct *)0)->tss.ksp)), \
+ "r" (task_pc) : "g4", "g5"); \
+here: SWITCH_EXIT } while(0)
+
+/* Changing the IRQ level on the Sparc. We now avoid writing the psr
+ * whenever possible.
*/
+extern __inline__ void setipl(unsigned long __orig_psr)
+{
+ __asm__ __volatile__("wr\t%0, 0x0, %%psr\n\t"
+ "nop; nop; nop;" : : "r" (__orig_psr) : "memory");
+}
-#define swpipl(__new_ipl) \
-({ unsigned long psr, retval; \
-__asm__ __volatile__( \
- "rd %%psr, %0\n\t" : "=&r" (psr)); \
-retval = psr; \
-psr = (psr & ~(PSR_PIL)); \
-psr |= ((__new_ipl << 8) & PSR_PIL); \
-__asm__ __volatile__( \
- "wr %0, 0x0, %%psr\n\t" \
- : : "r" (psr)); \
-retval = ((retval>>8)&15); \
-retval; })
-
-#define cli() swpipl(15) /* 15 = no int's except nmi's */
-#define sti() swpipl(0) /* I'm scared */
-#define save_flags(flags) do { flags = swpipl(15); } while (0)
-#define restore_flags(flags) swpipl(flags)
-
-#define iret() __asm__ __volatile__ ("jmp %%l1\n\t" \
- "rett %%l2\n\t": : :"memory")
-
-#define _set_gate(gate_addr,type,dpl,addr) \
-__asm__ __volatile__ ("nop\n\t")
-
-#define set_intr_gate(n,addr) \
- _set_gate(&idt[n],14,0,addr)
-
-#define set_trap_gate(n,addr) \
- _set_gate(&idt[n],15,0,addr)
+extern __inline__ void cli(void)
+{
+ unsigned long tmp;
+
+ __asm__ __volatile__("rd\t%%psr, %0\n\t"
+ "andcc\t%0, %1, %%g0\n\t"
+ "be,a\t1f\n\t"
+ " wr\t%0, %1, %%psr\n"
+ "1:\tnop; nop"
+ : "=r" (tmp)
+ : "i" (PSR_PIL)
+ : "memory");
+}
-#define set_system_gate(n,addr) \
- _set_gate(&idt[n],15,3,addr)
+extern __inline__ void sti(void)
+{
+ unsigned long tmp;
+
+ __asm__ __volatile__("rd\t%%psr, %0\n\t"
+ "andcc\t%0, %1, %%g0\n\t"
+ "bne,a\t1f\n\t"
+ " wr\t%0, %1, %%psr\n"
+ "1:\tnop; nop"
+ : "=r" (tmp)
+ : "i" (PSR_PIL)
+ : "memory");
+}
-#define set_call_gate(a,addr) \
- _set_gate(a,12,3,addr)
+extern __inline__ unsigned long getipl(void)
+{
+ unsigned long retval;
+ __asm__ __volatile__("rd\t%%psr, %0" : "=r" (retval));
+ return retval;
+}
-extern inline unsigned int get_psr(void)
+extern __inline__ unsigned long swap_pil(unsigned long __new_psr)
{
- unsigned int ret_val;
- __asm__("rd %%psr, %0\n\t" :
- "=r" (ret_val));
- return ret_val;
+ unsigned long retval, tmp1, tmp2;
+
+ __asm__ __volatile__("rd\t%%psr, %0\n\t"
+ "and\t%0, %4, %1\n\t"
+ "and\t%3, %4, %2\n\t"
+ "xorcc\t%1, %2, %%g0\n\t"
+ "bne,a\t1f\n\t"
+ " wr %0, %4, %%psr\n"
+ "1:\tnop; nop"
+ : "=r" (retval), "=r" (tmp1), "=r" (tmp2)
+ : "r" (__new_psr), "i" (PSR_PIL)
+ : "memory");
+ return retval;
}
-extern inline void put_psr(unsigned int new_psr)
+extern __inline__ unsigned long read_psr_and_cli(void)
{
- __asm__("wr %0, 0x0, %%psr\n\t" : :
- "r" (new_psr));
+ unsigned long retval;
+
+ __asm__ __volatile__("rd\t%%psr, %0\n\t"
+ "andcc\t%0, %1, %%g0\n\t"
+ "be,a\t1f\n\t"
+ " wr\t%0, %1, %%psr\n"
+ "1:\tnop; nop"
+ : "=r" (retval)
+ : "i" (PSR_PIL)
+ : "memory");
+ return retval;
}
-/* Must this be atomic? */
+extern char spdeb_buf[256];
-extern inline void *xchg_u32(int * m, unsigned long val)
-{
- unsigned long dummy;
-
- __asm__ __volatile__(
- "ld %1,%2 ! xchg_u32() is here\n\t"
- "st %0, %1\n\t"
- "or %%g0, %2, %0"
- : "=r" (val), "=m" (*m), "=r" (dummy)
- : "0" (val));
- return (void *) val;
-}
+#define save_flags(flags) ((flags) = getipl())
+#define save_and_cli(flags) ((flags) = read_psr_and_cli())
+#define restore_flags(flags) setipl((flags))
+/* XXX Change this if we ever use a PSO mode kernel. */
+#define mb() __asm__ __volatile__ ("" : : : "memory")
-/* pointers are 32 bits on the sparc (at least the v8, and they'll work
- * on the V9 none the less). I don't need the xchg_u64 routine for now.
- */
+#define nop() __asm__ __volatile__ ("nop");
-extern inline void *xchg_ptr(void *m, void *val)
+extern __inline__ unsigned long xchg_u32(__volatile__ unsigned long *m, unsigned long val)
{
- return (void *) xchg_u32((int *) m, (unsigned long) val);
+ __asm__ __volatile__("
+ rd %%psr, %%g3
+ andcc %%g3, %3, %%g0
+ be,a 1f
+ wr %%g3, %3, %%psr
+1: ld [%1], %%g2
+ andcc %%g3, %3, %%g0
+ st %2, [%1]
+ be,a 1f
+ wr %%g3, 0x0, %%psr
+1: nop
+ mov %%g2, %0
+ "
+ : "=&r" (val)
+ : "r" (m), "0" (val), "i" (PSR_PIL)
+ : "g2", "g3");
+
+ return val;
}
+#define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
+#define tas(ptr) (xchg((ptr),1))
+
+extern void __xchg_called_with_bad_pointer(void);
+static __inline__ unsigned long __xchg(unsigned long x, __volatile__ void * ptr, int size)
+{
+ switch (size) {
+ case 4:
+ return xchg_u32(ptr, x);
+ };
+ __xchg_called_with_bad_pointer();
+ return x;
+}
#endif /* __ASSEMBLY__ */
-#endif
+/*
+ * Reset the machine.
+ */
+extern void hard_reset_now(void);
+
+#endif /* !(__SPARC_SYSTEM_H) */