summaryrefslogtreecommitdiffstats
path: root/include/asm-sparc/processor.h
blob: 7e18bfb2f61bf017493ab71837381e49eb319ce5 (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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
/* include/asm-sparc/processor.h
 *
 * Copyright (C) 1994 David S. Miller (davem@caip.rutgers.edu)
 */

#ifndef __ASM_SPARC_PROCESSOR_H
#define __ASM_SPARC_PROCESSOR_H

/*
 * Bus types
 */
#define EISA_bus 1
#define EISA_bus__is_a_macro /* for versions in ksyms.c */
#define MCA_bus 0
#define MCA_bus__is_a_macro /* for versions in ksyms.c */

/*
 * Write Protection works right in supervisor mode on the Sparc
 */

#define wp_works_ok 1
#define wp_works_ok__is_a_macro /* for versions in ksyms.c */

/*
 * User space process size: 3GB. This is hardcoded into a few places,
 * so don't change it unless you know what you are doing.
 *
 * "this is gonna have to change to 1gig for the sparc" - David S. Miller
 */
#define TASK_SIZE	(0xC0000000UL)

/*
 * Size of io_bitmap in longwords: 32 is ports 0-0x3ff.
 */
#define IO_BITMAP_SIZE	32

/* The first five entries here MUST be the first four. This allows me to
 * do %lo(offset) loads and stores in entry.S. See TRAP_WIN_CLEAN to see
 * why.
 */

struct thread_struct {
	unsigned long uwindows;       /* how many user windows are in the set */
	unsigned long wim;            /* user's window invalid mask */
	unsigned long w_saved;        /* how many windows saved in reg_window[] */
	unsigned long ksp;          /* kernel stack pointer */
	unsigned long usp;          /* user's sp, throw reg windows here */
	unsigned long psr;          /* save for condition codes */
	unsigned long reg_window[16*24];
	unsigned long cr3;          /* why changed from ptbr? */
	unsigned int pcc;
	unsigned int asn;
	unsigned long unique;
	unsigned long flags;
	unsigned long res1, res2;
	unsigned long pc;           /* program counter */
	unsigned long npc;          /* next program counter */

/* 8 local registers + 8 in registers * 24 register windows.
 * Most sparcs I know of only have 8 windows implemented,
 * we determine how many at boot time and store that value
 * in nwindows.
 */
	unsigned long globl_regs[8];  /* global regs need to be saved too */
	unsigned long yreg;
	unsigned long float_regs[64]; /* V8 and below have 32, V9 has 64 */
};

#define INIT_MMAP { &init_task, 0x0, 0x40000000, \
		      PAGE_SHARED , VM_READ | VM_WRITE | VM_EXEC }

#define INIT_TSS  { \
	0, 0, 0, 0, 0, 0, \
        { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, \
	0, 0, 0, 0, 0, 0, 0, 0, 0, \
        { 0, 0, 0, 0, 0, 0, 0, 0, }, \
        0, \
        { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, \
}

/* The thread_frame is what needs to be set up in certain circumstances
 * upon entry to a trap. It is also loaded sometimes during a window
 * spill if things don't go right (bad user stack pointer). In reality
 * it is not per-process per se, it just sits in the kernel stack while
 * the current process is in a handler then it is basically forgotten
 * about.
 */

struct thread_frame {
  unsigned int thr_psr;
  unsigned int thr_pc;
  unsigned int thr_npc;
  unsigned int thr_y;
  unsigned int thr_globals[8];
  unsigned int thr_outs[8];
};

/*
 * These are the "cli()" and "sti()" for software interrupts
 * They work by increasing/decreasing the "intr_count" value, 
 * and as such can be nested arbitrarily.
 */
extern inline void start_bh_atomic(void)
{
	unsigned long dummy, psr;
	__asm__ __volatile__("rd %%psr, %2\n\t"
			     "wr %2, 0x20, %%psr\n\t"  /* disable traps */
			     "ld %1,%0\n\t"
			     "add %0,1,%0\n\t"
			     "st %0,%1\n\t"
			     "wr %2, 0x0, %%psr\n\t"   /* enable traps */
			     : "=r" (dummy), "=m" (intr_count)
			     : "0" (0), "r" (psr=0));
}

extern inline void end_bh_atomic(void)
{
	unsigned long dummy, psr;
	__asm__ __volatile__("rd %%psr, %2\n\t"
			     "wr %2, 0x20, %%psr\n\t"
			     "ld %1,%0\n\t"
			     "sub %0,1,%0\n\t"
			     "st %0,%1\n\t"
			     "wr %2, 0x0, %%psr\n\t"
			     : "=r" (dummy), "=m" (intr_count)
			     : "0" (0), "r" (psr=0));
}

#endif /* __ASM_SPARC_PROCESSOR_H */