summaryrefslogtreecommitdiffstats
path: root/include/asm-sparc/system.h
blob: 3c4a62c9adaeab7ab0f38ec5cd494e976fc6f777 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
#ifndef __SPARC_SYSTEM_H
#define __SPARC_SYSTEM_H

#include <asm/segment.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/openprom.h>
#include <asm/psr.h>

#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.
				       */

#ifndef __ASSEMBLY__

extern void wrent(void *, unsigned long);
extern void wrkgp(unsigned long);
extern struct linux_romvec *romvec;

#define halt() { romvec->pv_halt(); }
#define move_to_user_mode() halt()
#define switch_to(x) halt()

#ifndef stbar  /* store barrier Sparc insn to synchronize stores in PSO */
#define stbar() __asm__ __volatile__("stbar": : :"memory")
#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.
 */

#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)

#define set_system_gate(n,addr) \
	_set_gate(&idt[n],15,3,addr)

#define set_call_gate(a,addr) \
	_set_gate(a,12,3,addr)


extern inline unsigned int get_psr(void)
{
  unsigned int ret_val;
  __asm__("rd %%psr, %0\n\t" :
	  "=r" (ret_val));
  return ret_val;
}

extern inline void put_psr(unsigned int new_psr)
{
  __asm__("wr %0, 0x0, %%psr\n\t" : :
	  "r" (new_psr));
}

/* Must this be atomic? */

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;
}


/* 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.
 */

extern inline void *xchg_ptr(void *m, void *val)
{
	return (void *) xchg_u32((int *) m, (unsigned long) val);
}



#endif /* __ASSEMBLY__ */

#endif