From beb116954b9b7f3bb56412b2494b562f02b864b1 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Tue, 7 Jan 1997 02:33:00 +0000 Subject: Import of Linux/MIPS 2.1.14 --- include/asm-sparc/system.h | 311 +++++++++++++++++++++++++++++++-------------- 1 file changed, 213 insertions(+), 98 deletions(-) (limited to 'include/asm-sparc/system.h') 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 +#include -/* - * 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 -#include +#ifdef __KERNEL__ +#include +#include #include +#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) */ -- cgit v1.2.3