diff options
author | Dmitry Torokhov <dtor@insightbb.com> | 2007-02-10 01:26:32 -0500 |
---|---|---|
committer | Dmitry Torokhov <dtor@insightbb.com> | 2007-02-10 01:26:32 -0500 |
commit | b22364c8eec89e6b0c081a237f3b6348df87796f (patch) | |
tree | 233a923281fb640106465d076997ff511efb6edf /include/asm-s390 | |
parent | 2c8dc071517ec2843869024dc82be2e246f41064 (diff) | |
parent | 66efc5a7e3061c3597ac43a8bb1026488d57e66b (diff) |
Merge rsync://rsync.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
Diffstat (limited to 'include/asm-s390')
30 files changed, 844 insertions, 78 deletions
diff --git a/include/asm-s390/cacheflush.h b/include/asm-s390/cacheflush.h index e399a8ba2ed7..f7cade8083f3 100644 --- a/include/asm-s390/cacheflush.h +++ b/include/asm-s390/cacheflush.h | |||
@@ -7,6 +7,7 @@ | |||
7 | /* Caches aren't brain-dead on the s390. */ | 7 | /* Caches aren't brain-dead on the s390. */ |
8 | #define flush_cache_all() do { } while (0) | 8 | #define flush_cache_all() do { } while (0) |
9 | #define flush_cache_mm(mm) do { } while (0) | 9 | #define flush_cache_mm(mm) do { } while (0) |
10 | #define flush_cache_dup_mm(mm) do { } while (0) | ||
10 | #define flush_cache_range(vma, start, end) do { } while (0) | 11 | #define flush_cache_range(vma, start, end) do { } while (0) |
11 | #define flush_cache_page(vma, vmaddr, pfn) do { } while (0) | 12 | #define flush_cache_page(vma, vmaddr, pfn) do { } while (0) |
12 | #define flush_dcache_page(page) do { } while (0) | 13 | #define flush_dcache_page(page) do { } while (0) |
diff --git a/include/asm-s390/compat.h b/include/asm-s390/compat.h index 356a0b183539..296f4f1a20e1 100644 --- a/include/asm-s390/compat.h +++ b/include/asm-s390/compat.h | |||
@@ -6,6 +6,34 @@ | |||
6 | #include <linux/types.h> | 6 | #include <linux/types.h> |
7 | #include <linux/sched.h> | 7 | #include <linux/sched.h> |
8 | 8 | ||
9 | #define PSW32_MASK_PER 0x40000000UL | ||
10 | #define PSW32_MASK_DAT 0x04000000UL | ||
11 | #define PSW32_MASK_IO 0x02000000UL | ||
12 | #define PSW32_MASK_EXT 0x01000000UL | ||
13 | #define PSW32_MASK_KEY 0x00F00000UL | ||
14 | #define PSW32_MASK_MCHECK 0x00040000UL | ||
15 | #define PSW32_MASK_WAIT 0x00020000UL | ||
16 | #define PSW32_MASK_PSTATE 0x00010000UL | ||
17 | #define PSW32_MASK_ASC 0x0000C000UL | ||
18 | #define PSW32_MASK_CC 0x00003000UL | ||
19 | #define PSW32_MASK_PM 0x00000f00UL | ||
20 | |||
21 | #define PSW32_ADDR_AMODE31 0x80000000UL | ||
22 | #define PSW32_ADDR_INSN 0x7FFFFFFFUL | ||
23 | |||
24 | #define PSW32_BASE_BITS 0x00080000UL | ||
25 | |||
26 | #define PSW32_ASC_PRIMARY 0x00000000UL | ||
27 | #define PSW32_ASC_ACCREG 0x00004000UL | ||
28 | #define PSW32_ASC_SECONDARY 0x00008000UL | ||
29 | #define PSW32_ASC_HOME 0x0000C000UL | ||
30 | |||
31 | #define PSW32_MASK_MERGE(CURRENT,NEW) \ | ||
32 | (((CURRENT) & ~(PSW32_MASK_CC|PSW32_MASK_PM)) | \ | ||
33 | ((NEW) & (PSW32_MASK_CC|PSW32_MASK_PM))) | ||
34 | |||
35 | extern long psw32_user_bits; | ||
36 | |||
9 | #define COMPAT_USER_HZ 100 | 37 | #define COMPAT_USER_HZ 100 |
10 | 38 | ||
11 | typedef u32 compat_size_t; | 39 | typedef u32 compat_size_t; |
diff --git a/include/asm-s390/dasd.h b/include/asm-s390/dasd.h index c042f9578081..604f68fa6f56 100644 --- a/include/asm-s390/dasd.h +++ b/include/asm-s390/dasd.h | |||
@@ -69,11 +69,13 @@ typedef struct dasd_information2_t { | |||
69 | * 0x01: readonly (ro) | 69 | * 0x01: readonly (ro) |
70 | * 0x02: use diag discipline (diag) | 70 | * 0x02: use diag discipline (diag) |
71 | * 0x04: set the device initially online (internal use only) | 71 | * 0x04: set the device initially online (internal use only) |
72 | * 0x08: enable ERP related logging | ||
72 | */ | 73 | */ |
73 | #define DASD_FEATURE_DEFAULT 0x00 | 74 | #define DASD_FEATURE_DEFAULT 0x00 |
74 | #define DASD_FEATURE_READONLY 0x01 | 75 | #define DASD_FEATURE_READONLY 0x01 |
75 | #define DASD_FEATURE_USEDIAG 0x02 | 76 | #define DASD_FEATURE_USEDIAG 0x02 |
76 | #define DASD_FEATURE_INITIAL_ONLINE 0x04 | 77 | #define DASD_FEATURE_INITIAL_ONLINE 0x04 |
78 | #define DASD_FEATURE_ERPLOG 0x08 | ||
77 | 79 | ||
78 | #define DASD_PARTN_BITS 2 | 80 | #define DASD_PARTN_BITS 2 |
79 | 81 | ||
diff --git a/include/asm-s390/etr.h b/include/asm-s390/etr.h new file mode 100644 index 000000000000..b498f19bb9a7 --- /dev/null +++ b/include/asm-s390/etr.h | |||
@@ -0,0 +1,219 @@ | |||
1 | /* | ||
2 | * include/asm-s390/etr.h | ||
3 | * | ||
4 | * Copyright IBM Corp. 2006 | ||
5 | * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com) | ||
6 | */ | ||
7 | #ifndef __S390_ETR_H | ||
8 | #define __S390_ETR_H | ||
9 | |||
10 | /* ETR attachment control register */ | ||
11 | struct etr_eacr { | ||
12 | unsigned int e0 : 1; /* port 0 stepping control */ | ||
13 | unsigned int e1 : 1; /* port 1 stepping control */ | ||
14 | unsigned int _pad0 : 5; /* must be 00100 */ | ||
15 | unsigned int dp : 1; /* data port control */ | ||
16 | unsigned int p0 : 1; /* port 0 change recognition control */ | ||
17 | unsigned int p1 : 1; /* port 1 change recognition control */ | ||
18 | unsigned int _pad1 : 3; /* must be 000 */ | ||
19 | unsigned int ea : 1; /* ETR alert control */ | ||
20 | unsigned int es : 1; /* ETR sync check control */ | ||
21 | unsigned int sl : 1; /* switch to local control */ | ||
22 | } __attribute__ ((packed)); | ||
23 | |||
24 | /* Port state returned by steai */ | ||
25 | enum etr_psc { | ||
26 | etr_psc_operational = 0, | ||
27 | etr_psc_semi_operational = 1, | ||
28 | etr_psc_protocol_error = 4, | ||
29 | etr_psc_no_symbols = 8, | ||
30 | etr_psc_no_signal = 12, | ||
31 | etr_psc_pps_mode = 13 | ||
32 | }; | ||
33 | |||
34 | /* Logical port state returned by stetr */ | ||
35 | enum etr_lpsc { | ||
36 | etr_lpsc_operational_step = 0, | ||
37 | etr_lpsc_operational_alt = 1, | ||
38 | etr_lpsc_semi_operational = 2, | ||
39 | etr_lpsc_protocol_error = 4, | ||
40 | etr_lpsc_no_symbol_sync = 8, | ||
41 | etr_lpsc_no_signal = 12, | ||
42 | etr_lpsc_pps_mode = 13 | ||
43 | }; | ||
44 | |||
45 | /* ETR status words */ | ||
46 | struct etr_esw { | ||
47 | struct etr_eacr eacr; /* attachment control register */ | ||
48 | unsigned int y : 1; /* stepping mode */ | ||
49 | unsigned int _pad0 : 5; /* must be 00000 */ | ||
50 | unsigned int p : 1; /* stepping port number */ | ||
51 | unsigned int q : 1; /* data port number */ | ||
52 | unsigned int psc0 : 4; /* port 0 state code */ | ||
53 | unsigned int psc1 : 4; /* port 1 state code */ | ||
54 | } __attribute__ ((packed)); | ||
55 | |||
56 | /* Second level data register status word */ | ||
57 | struct etr_slsw { | ||
58 | unsigned int vv1 : 1; /* copy of validity bit data frame 1 */ | ||
59 | unsigned int vv2 : 1; /* copy of validity bit data frame 2 */ | ||
60 | unsigned int vv3 : 1; /* copy of validity bit data frame 3 */ | ||
61 | unsigned int vv4 : 1; /* copy of validity bit data frame 4 */ | ||
62 | unsigned int _pad0 : 19; /* must by all zeroes */ | ||
63 | unsigned int n : 1; /* EAF port number */ | ||
64 | unsigned int v1 : 1; /* validity bit ETR data frame 1 */ | ||
65 | unsigned int v2 : 1; /* validity bit ETR data frame 2 */ | ||
66 | unsigned int v3 : 1; /* validity bit ETR data frame 3 */ | ||
67 | unsigned int v4 : 1; /* validity bit ETR data frame 4 */ | ||
68 | unsigned int _pad1 : 4; /* must be 0000 */ | ||
69 | } __attribute__ ((packed)); | ||
70 | |||
71 | /* ETR data frames */ | ||
72 | struct etr_edf1 { | ||
73 | unsigned int u : 1; /* untuned bit */ | ||
74 | unsigned int _pad0 : 1; /* must be 0 */ | ||
75 | unsigned int r : 1; /* service request bit */ | ||
76 | unsigned int _pad1 : 4; /* must be 0000 */ | ||
77 | unsigned int a : 1; /* time adjustment bit */ | ||
78 | unsigned int net_id : 8; /* ETR network id */ | ||
79 | unsigned int etr_id : 8; /* id of ETR which sends data frames */ | ||
80 | unsigned int etr_pn : 8; /* port number of ETR output port */ | ||
81 | } __attribute__ ((packed)); | ||
82 | |||
83 | struct etr_edf2 { | ||
84 | unsigned int etv : 32; /* Upper 32 bits of TOD. */ | ||
85 | } __attribute__ ((packed)); | ||
86 | |||
87 | struct etr_edf3 { | ||
88 | unsigned int rc : 8; /* failure reason code */ | ||
89 | unsigned int _pad0 : 3; /* must be 000 */ | ||
90 | unsigned int c : 1; /* ETR coupled bit */ | ||
91 | unsigned int tc : 4; /* ETR type code */ | ||
92 | unsigned int blto : 8; /* biased local time offset */ | ||
93 | /* (blto - 128) * 15 = minutes */ | ||
94 | unsigned int buo : 8; /* biased utc offset */ | ||
95 | /* (buo - 128) = leap seconds */ | ||
96 | } __attribute__ ((packed)); | ||
97 | |||
98 | struct etr_edf4 { | ||
99 | unsigned int ed : 8; /* ETS device dependent data */ | ||
100 | unsigned int _pad0 : 1; /* must be 0 */ | ||
101 | unsigned int buc : 5; /* biased ut1 correction */ | ||
102 | /* (buc - 16) * 0.1 seconds */ | ||
103 | unsigned int em : 6; /* ETS error magnitude */ | ||
104 | unsigned int dc : 6; /* ETS drift code */ | ||
105 | unsigned int sc : 6; /* ETS steering code */ | ||
106 | } __attribute__ ((packed)); | ||
107 | |||
108 | /* | ||
109 | * ETR attachment information block, two formats | ||
110 | * format 1 has 4 reserved words with a size of 64 bytes | ||
111 | * format 2 has 16 reserved words with a size of 96 bytes | ||
112 | */ | ||
113 | struct etr_aib { | ||
114 | struct etr_esw esw; | ||
115 | struct etr_slsw slsw; | ||
116 | unsigned long long tsp; | ||
117 | struct etr_edf1 edf1; | ||
118 | struct etr_edf2 edf2; | ||
119 | struct etr_edf3 edf3; | ||
120 | struct etr_edf4 edf4; | ||
121 | unsigned int reserved[16]; | ||
122 | } __attribute__ ((packed,aligned(8))); | ||
123 | |||
124 | /* ETR interruption parameter */ | ||
125 | struct etr_interruption_parameter { | ||
126 | unsigned int _pad0 : 8; | ||
127 | unsigned int pc0 : 1; /* port 0 state change */ | ||
128 | unsigned int pc1 : 1; /* port 1 state change */ | ||
129 | unsigned int _pad1 : 3; | ||
130 | unsigned int eai : 1; /* ETR alert indication */ | ||
131 | unsigned int _pad2 : 18; | ||
132 | } __attribute__ ((packed)); | ||
133 | |||
134 | /* Query TOD offset result */ | ||
135 | struct etr_ptff_qto { | ||
136 | unsigned long long physical_clock; | ||
137 | unsigned long long tod_offset; | ||
138 | unsigned long long logical_tod_offset; | ||
139 | unsigned long long tod_epoch_difference; | ||
140 | } __attribute__ ((packed)); | ||
141 | |||
142 | /* Inline assembly helper functions */ | ||
143 | static inline int etr_setr(struct etr_eacr *ctrl) | ||
144 | { | ||
145 | int rc = -ENOSYS; | ||
146 | |||
147 | asm volatile( | ||
148 | " .insn s,0xb2160000,0(%2)\n" | ||
149 | "0: la %0,0\n" | ||
150 | "1:\n" | ||
151 | EX_TABLE(0b,1b) | ||
152 | : "+d" (rc) : "m" (*ctrl), "a" (ctrl)); | ||
153 | return rc; | ||
154 | } | ||
155 | |||
156 | /* Stores a format 1 aib with 64 bytes */ | ||
157 | static inline int etr_stetr(struct etr_aib *aib) | ||
158 | { | ||
159 | int rc = -ENOSYS; | ||
160 | |||
161 | asm volatile( | ||
162 | " .insn s,0xb2170000,0(%2)\n" | ||
163 | "0: la %0,0\n" | ||
164 | "1:\n" | ||
165 | EX_TABLE(0b,1b) | ||
166 | : "+d" (rc) : "m" (*aib), "a" (aib)); | ||
167 | return rc; | ||
168 | } | ||
169 | |||
170 | /* Stores a format 2 aib with 96 bytes for specified port */ | ||
171 | static inline int etr_steai(struct etr_aib *aib, unsigned int func) | ||
172 | { | ||
173 | register unsigned int reg0 asm("0") = func; | ||
174 | int rc = -ENOSYS; | ||
175 | |||
176 | asm volatile( | ||
177 | " .insn s,0xb2b30000,0(%2)\n" | ||
178 | "0: la %0,0\n" | ||
179 | "1:\n" | ||
180 | EX_TABLE(0b,1b) | ||
181 | : "+d" (rc) : "m" (*aib), "a" (aib), "d" (reg0)); | ||
182 | return rc; | ||
183 | } | ||
184 | |||
185 | /* Function codes for the steai instruction. */ | ||
186 | #define ETR_STEAI_STEPPING_PORT 0x10 | ||
187 | #define ETR_STEAI_ALTERNATE_PORT 0x11 | ||
188 | #define ETR_STEAI_PORT_0 0x12 | ||
189 | #define ETR_STEAI_PORT_1 0x13 | ||
190 | |||
191 | static inline int etr_ptff(void *ptff_block, unsigned int func) | ||
192 | { | ||
193 | register unsigned int reg0 asm("0") = func; | ||
194 | register unsigned long reg1 asm("1") = (unsigned long) ptff_block; | ||
195 | int rc = -ENOSYS; | ||
196 | |||
197 | asm volatile( | ||
198 | " .word 0x0104\n" | ||
199 | " ipm %0\n" | ||
200 | " srl %0,28\n" | ||
201 | : "=d" (rc), "=m" (ptff_block) | ||
202 | : "d" (reg0), "d" (reg1), "m" (ptff_block) : "cc"); | ||
203 | return rc; | ||
204 | } | ||
205 | |||
206 | /* Function codes for the ptff instruction. */ | ||
207 | #define ETR_PTFF_QAF 0x00 /* query available functions */ | ||
208 | #define ETR_PTFF_QTO 0x01 /* query tod offset */ | ||
209 | #define ETR_PTFF_QSI 0x02 /* query steering information */ | ||
210 | #define ETR_PTFF_ATO 0x40 /* adjust tod offset */ | ||
211 | #define ETR_PTFF_STO 0x41 /* set tod offset */ | ||
212 | #define ETR_PTFF_SFS 0x42 /* set fine steering rate */ | ||
213 | #define ETR_PTFF_SGS 0x43 /* set gross steering rate */ | ||
214 | |||
215 | /* Functions needed by the machine check handler */ | ||
216 | extern void etr_switch_to_local(void); | ||
217 | extern void etr_sync_check(void); | ||
218 | |||
219 | #endif /* __S390_ETR_H */ | ||
diff --git a/include/asm-s390/futex.h b/include/asm-s390/futex.h index 5e261e1de671..5c5d02de49e9 100644 --- a/include/asm-s390/futex.h +++ b/include/asm-s390/futex.h | |||
@@ -4,8 +4,8 @@ | |||
4 | #ifdef __KERNEL__ | 4 | #ifdef __KERNEL__ |
5 | 5 | ||
6 | #include <linux/futex.h> | 6 | #include <linux/futex.h> |
7 | #include <linux/uaccess.h> | ||
7 | #include <asm/errno.h> | 8 | #include <asm/errno.h> |
8 | #include <asm/uaccess.h> | ||
9 | 9 | ||
10 | static inline int futex_atomic_op_inuser (int encoded_op, int __user *uaddr) | 10 | static inline int futex_atomic_op_inuser (int encoded_op, int __user *uaddr) |
11 | { | 11 | { |
@@ -21,7 +21,9 @@ static inline int futex_atomic_op_inuser (int encoded_op, int __user *uaddr) | |||
21 | if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int))) | 21 | if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int))) |
22 | return -EFAULT; | 22 | return -EFAULT; |
23 | 23 | ||
24 | pagefault_disable(); | ||
24 | ret = uaccess.futex_atomic_op(op, uaddr, oparg, &oldval); | 25 | ret = uaccess.futex_atomic_op(op, uaddr, oparg, &oldval); |
26 | pagefault_enable(); | ||
25 | 27 | ||
26 | if (!ret) { | 28 | if (!ret) { |
27 | switch (cmp) { | 29 | switch (cmp) { |
diff --git a/include/asm-s390/hardirq.h b/include/asm-s390/hardirq.h index c2f6a8782d31..31beb18cb3d1 100644 --- a/include/asm-s390/hardirq.h +++ b/include/asm-s390/hardirq.h | |||
@@ -32,6 +32,6 @@ typedef struct { | |||
32 | 32 | ||
33 | #define HARDIRQ_BITS 8 | 33 | #define HARDIRQ_BITS 8 |
34 | 34 | ||
35 | extern void account_ticks(void); | 35 | extern void account_ticks(u64 time); |
36 | 36 | ||
37 | #endif /* __ASM_HARDIRQ_H */ | 37 | #endif /* __ASM_HARDIRQ_H */ |
diff --git a/include/asm-s390/io.h b/include/asm-s390/io.h index efb7de9c1c6b..a4c2d550dad4 100644 --- a/include/asm-s390/io.h +++ b/include/asm-s390/io.h | |||
@@ -28,11 +28,7 @@ static inline unsigned long virt_to_phys(volatile void * address) | |||
28 | { | 28 | { |
29 | unsigned long real_address; | 29 | unsigned long real_address; |
30 | asm volatile( | 30 | asm volatile( |
31 | #ifndef __s390x__ | ||
32 | " lra %0,0(%1)\n" | 31 | " lra %0,0(%1)\n" |
33 | #else /* __s390x__ */ | ||
34 | " lrag %0,0(%1)\n" | ||
35 | #endif /* __s390x__ */ | ||
36 | " jz 0f\n" | 32 | " jz 0f\n" |
37 | " la %0,0\n" | 33 | " la %0,0\n" |
38 | "0:" | 34 | "0:" |
diff --git a/include/asm-s390/kdebug.h b/include/asm-s390/kdebug.h index 40cc68025e01..1b50f89819a4 100644 --- a/include/asm-s390/kdebug.h +++ b/include/asm-s390/kdebug.h | |||
@@ -26,7 +26,6 @@ extern int register_page_fault_notifier(struct notifier_block *); | |||
26 | extern int unregister_page_fault_notifier(struct notifier_block *); | 26 | extern int unregister_page_fault_notifier(struct notifier_block *); |
27 | extern struct atomic_notifier_head s390die_chain; | 27 | extern struct atomic_notifier_head s390die_chain; |
28 | 28 | ||
29 | |||
30 | enum die_val { | 29 | enum die_val { |
31 | DIE_OOPS = 1, | 30 | DIE_OOPS = 1, |
32 | DIE_BPT, | 31 | DIE_BPT, |
@@ -56,4 +55,6 @@ static inline int notify_die(enum die_val val, const char *str, | |||
56 | return atomic_notifier_call_chain(&s390die_chain, val, &args); | 55 | return atomic_notifier_call_chain(&s390die_chain, val, &args); |
57 | } | 56 | } |
58 | 57 | ||
58 | extern void die(const char *, struct pt_regs *, long); | ||
59 | |||
59 | #endif | 60 | #endif |
diff --git a/include/asm-s390/lowcore.h b/include/asm-s390/lowcore.h index 74f7389bd3ee..4a31d0a7ee83 100644 --- a/include/asm-s390/lowcore.h +++ b/include/asm-s390/lowcore.h | |||
@@ -220,7 +220,8 @@ struct _lowcore | |||
220 | __u32 kernel_asce; /* 0xc4c */ | 220 | __u32 kernel_asce; /* 0xc4c */ |
221 | __u32 user_asce; /* 0xc50 */ | 221 | __u32 user_asce; /* 0xc50 */ |
222 | __u32 panic_stack; /* 0xc54 */ | 222 | __u32 panic_stack; /* 0xc54 */ |
223 | __u8 pad10[0xc60-0xc58]; /* 0xc58 */ | 223 | __u32 user_exec_asce; /* 0xc58 */ |
224 | __u8 pad10[0xc60-0xc5c]; /* 0xc5c */ | ||
224 | /* entry.S sensitive area start */ | 225 | /* entry.S sensitive area start */ |
225 | struct cpuinfo_S390 cpu_data; /* 0xc60 */ | 226 | struct cpuinfo_S390 cpu_data; /* 0xc60 */ |
226 | __u32 ipl_device; /* 0xc7c */ | 227 | __u32 ipl_device; /* 0xc7c */ |
@@ -310,7 +311,8 @@ struct _lowcore | |||
310 | __u64 kernel_asce; /* 0xd58 */ | 311 | __u64 kernel_asce; /* 0xd58 */ |
311 | __u64 user_asce; /* 0xd60 */ | 312 | __u64 user_asce; /* 0xd60 */ |
312 | __u64 panic_stack; /* 0xd68 */ | 313 | __u64 panic_stack; /* 0xd68 */ |
313 | __u8 pad10[0xd80-0xd70]; /* 0xd70 */ | 314 | __u64 user_exec_asce; /* 0xd70 */ |
315 | __u8 pad10[0xd80-0xd78]; /* 0xd78 */ | ||
314 | /* entry.S sensitive area start */ | 316 | /* entry.S sensitive area start */ |
315 | struct cpuinfo_S390 cpu_data; /* 0xd80 */ | 317 | struct cpuinfo_S390 cpu_data; /* 0xd80 */ |
316 | __u32 ipl_device; /* 0xdb8 */ | 318 | __u32 ipl_device; /* 0xdb8 */ |
diff --git a/include/asm-s390/mmu_context.h b/include/asm-s390/mmu_context.h index bcf24a873874..1d21da220d49 100644 --- a/include/asm-s390/mmu_context.h +++ b/include/asm-s390/mmu_context.h | |||
@@ -9,6 +9,7 @@ | |||
9 | #ifndef __S390_MMU_CONTEXT_H | 9 | #ifndef __S390_MMU_CONTEXT_H |
10 | #define __S390_MMU_CONTEXT_H | 10 | #define __S390_MMU_CONTEXT_H |
11 | 11 | ||
12 | #include <asm/pgalloc.h> | ||
12 | /* | 13 | /* |
13 | * get a new mmu context.. S390 don't know about contexts. | 14 | * get a new mmu context.. S390 don't know about contexts. |
14 | */ | 15 | */ |
@@ -16,29 +17,44 @@ | |||
16 | 17 | ||
17 | #define destroy_context(mm) do { } while (0) | 18 | #define destroy_context(mm) do { } while (0) |
18 | 19 | ||
20 | #ifndef __s390x__ | ||
21 | #define LCTL_OPCODE "lctl" | ||
22 | #define PGTABLE_BITS (_SEGMENT_TABLE|USER_STD_MASK) | ||
23 | #else | ||
24 | #define LCTL_OPCODE "lctlg" | ||
25 | #define PGTABLE_BITS (_REGION_TABLE|USER_STD_MASK) | ||
26 | #endif | ||
27 | |||
19 | static inline void enter_lazy_tlb(struct mm_struct *mm, | 28 | static inline void enter_lazy_tlb(struct mm_struct *mm, |
20 | struct task_struct *tsk) | 29 | struct task_struct *tsk) |
21 | { | 30 | { |
22 | } | 31 | } |
23 | 32 | ||
24 | static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, | 33 | static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, |
25 | struct task_struct *tsk) | 34 | struct task_struct *tsk) |
26 | { | 35 | { |
27 | if (prev != next) { | 36 | pgd_t *shadow_pgd = get_shadow_pgd(next->pgd); |
28 | #ifndef __s390x__ | 37 | |
29 | S390_lowcore.user_asce = (__pa(next->pgd)&PAGE_MASK) | | 38 | if (prev != next) { |
30 | (_SEGMENT_TABLE|USER_STD_MASK); | 39 | S390_lowcore.user_asce = (__pa(next->pgd) & PAGE_MASK) | |
31 | /* Load home space page table origin. */ | 40 | PGTABLE_BITS; |
32 | asm volatile("lctl 13,13,%0" | 41 | if (shadow_pgd) { |
33 | : : "m" (S390_lowcore.user_asce) ); | 42 | /* Load primary/secondary space page table origin. */ |
34 | #else /* __s390x__ */ | 43 | S390_lowcore.user_exec_asce = |
35 | S390_lowcore.user_asce = (__pa(next->pgd) & PAGE_MASK) | | 44 | (__pa(shadow_pgd) & PAGE_MASK) | PGTABLE_BITS; |
36 | (_REGION_TABLE|USER_STD_MASK); | 45 | asm volatile(LCTL_OPCODE" 1,1,%0\n" |
37 | /* Load home space page table origin. */ | 46 | LCTL_OPCODE" 7,7,%1" |
38 | asm volatile("lctlg 13,13,%0" | 47 | : : "m" (S390_lowcore.user_exec_asce), |
39 | : : "m" (S390_lowcore.user_asce) ); | 48 | "m" (S390_lowcore.user_asce) ); |
40 | #endif /* __s390x__ */ | 49 | } else if (switch_amode) { |
41 | } | 50 | /* Load primary space page table origin. */ |
51 | asm volatile(LCTL_OPCODE" 1,1,%0" | ||
52 | : : "m" (S390_lowcore.user_asce) ); | ||
53 | } else | ||
54 | /* Load home space page table origin. */ | ||
55 | asm volatile(LCTL_OPCODE" 13,13,%0" | ||
56 | : : "m" (S390_lowcore.user_asce) ); | ||
57 | } | ||
42 | cpu_set(smp_processor_id(), next->cpu_vm_mask); | 58 | cpu_set(smp_processor_id(), next->cpu_vm_mask); |
43 | } | 59 | } |
44 | 60 | ||
@@ -51,4 +67,4 @@ static inline void activate_mm(struct mm_struct *prev, | |||
51 | set_fs(current->thread.mm_segment); | 67 | set_fs(current->thread.mm_segment); |
52 | } | 68 | } |
53 | 69 | ||
54 | #endif | 70 | #endif /* __S390_MMU_CONTEXT_H */ |
diff --git a/include/asm-s390/page.h b/include/asm-s390/page.h index 363ea761d5ee..05ea6f172786 100644 --- a/include/asm-s390/page.h +++ b/include/asm-s390/page.h | |||
@@ -127,6 +127,26 @@ page_get_storage_key(unsigned long addr) | |||
127 | return skey; | 127 | return skey; |
128 | } | 128 | } |
129 | 129 | ||
130 | extern unsigned long max_pfn; | ||
131 | |||
132 | static inline int pfn_valid(unsigned long pfn) | ||
133 | { | ||
134 | unsigned long dummy; | ||
135 | int ccode; | ||
136 | |||
137 | if (pfn >= max_pfn) | ||
138 | return 0; | ||
139 | |||
140 | asm volatile( | ||
141 | " lra %0,0(%2)\n" | ||
142 | " ipm %1\n" | ||
143 | " srl %1,28\n" | ||
144 | : "=d" (dummy), "=d" (ccode) | ||
145 | : "a" (pfn << PAGE_SHIFT) | ||
146 | : "cc"); | ||
147 | return !ccode; | ||
148 | } | ||
149 | |||
130 | #endif /* !__ASSEMBLY__ */ | 150 | #endif /* !__ASSEMBLY__ */ |
131 | 151 | ||
132 | /* to align the pointer to the (next) page boundary */ | 152 | /* to align the pointer to the (next) page boundary */ |
@@ -138,8 +158,6 @@ page_get_storage_key(unsigned long addr) | |||
138 | #define __va(x) (void *)(unsigned long)(x) | 158 | #define __va(x) (void *)(unsigned long)(x) |
139 | #define virt_to_page(kaddr) pfn_to_page(__pa(kaddr) >> PAGE_SHIFT) | 159 | #define virt_to_page(kaddr) pfn_to_page(__pa(kaddr) >> PAGE_SHIFT) |
140 | #define page_to_phys(page) (page_to_pfn(page) << PAGE_SHIFT) | 160 | #define page_to_phys(page) (page_to_pfn(page) << PAGE_SHIFT) |
141 | |||
142 | #define pfn_valid(pfn) ((pfn) < max_mapnr) | ||
143 | #define virt_addr_valid(kaddr) pfn_valid(__pa(kaddr) >> PAGE_SHIFT) | 161 | #define virt_addr_valid(kaddr) pfn_valid(__pa(kaddr) >> PAGE_SHIFT) |
144 | 162 | ||
145 | #define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \ | 163 | #define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \ |
diff --git a/include/asm-s390/pgalloc.h b/include/asm-s390/pgalloc.h index 28619de5ecae..56c8a6c80e2e 100644 --- a/include/asm-s390/pgalloc.h +++ b/include/asm-s390/pgalloc.h | |||
@@ -25,8 +25,11 @@ extern void diag10(unsigned long addr); | |||
25 | * Page allocation orders. | 25 | * Page allocation orders. |
26 | */ | 26 | */ |
27 | #ifndef __s390x__ | 27 | #ifndef __s390x__ |
28 | # define PTE_ALLOC_ORDER 0 | ||
29 | # define PMD_ALLOC_ORDER 0 | ||
28 | # define PGD_ALLOC_ORDER 1 | 30 | # define PGD_ALLOC_ORDER 1 |
29 | #else /* __s390x__ */ | 31 | #else /* __s390x__ */ |
32 | # define PTE_ALLOC_ORDER 0 | ||
30 | # define PMD_ALLOC_ORDER 2 | 33 | # define PMD_ALLOC_ORDER 2 |
31 | # define PGD_ALLOC_ORDER 2 | 34 | # define PGD_ALLOC_ORDER 2 |
32 | #endif /* __s390x__ */ | 35 | #endif /* __s390x__ */ |
@@ -44,6 +47,17 @@ static inline pgd_t *pgd_alloc(struct mm_struct *mm) | |||
44 | 47 | ||
45 | if (!pgd) | 48 | if (!pgd) |
46 | return NULL; | 49 | return NULL; |
50 | if (s390_noexec) { | ||
51 | pgd_t *shadow_pgd = (pgd_t *) | ||
52 | __get_free_pages(GFP_KERNEL, PGD_ALLOC_ORDER); | ||
53 | struct page *page = virt_to_page(pgd); | ||
54 | |||
55 | if (!shadow_pgd) { | ||
56 | free_pages((unsigned long) pgd, PGD_ALLOC_ORDER); | ||
57 | return NULL; | ||
58 | } | ||
59 | page->lru.next = (void *) shadow_pgd; | ||
60 | } | ||
47 | for (i = 0; i < PTRS_PER_PGD; i++) | 61 | for (i = 0; i < PTRS_PER_PGD; i++) |
48 | #ifndef __s390x__ | 62 | #ifndef __s390x__ |
49 | pmd_clear(pmd_offset(pgd + i, i*PGDIR_SIZE)); | 63 | pmd_clear(pmd_offset(pgd + i, i*PGDIR_SIZE)); |
@@ -55,6 +69,10 @@ static inline pgd_t *pgd_alloc(struct mm_struct *mm) | |||
55 | 69 | ||
56 | static inline void pgd_free(pgd_t *pgd) | 70 | static inline void pgd_free(pgd_t *pgd) |
57 | { | 71 | { |
72 | pgd_t *shadow_pgd = get_shadow_pgd(pgd); | ||
73 | |||
74 | if (shadow_pgd) | ||
75 | free_pages((unsigned long) shadow_pgd, PGD_ALLOC_ORDER); | ||
58 | free_pages((unsigned long) pgd, PGD_ALLOC_ORDER); | 76 | free_pages((unsigned long) pgd, PGD_ALLOC_ORDER); |
59 | } | 77 | } |
60 | 78 | ||
@@ -68,6 +86,7 @@ static inline void pgd_free(pgd_t *pgd) | |||
68 | #define pmd_free(x) do { } while (0) | 86 | #define pmd_free(x) do { } while (0) |
69 | #define __pmd_free_tlb(tlb,x) do { } while (0) | 87 | #define __pmd_free_tlb(tlb,x) do { } while (0) |
70 | #define pgd_populate(mm, pmd, pte) BUG() | 88 | #define pgd_populate(mm, pmd, pte) BUG() |
89 | #define pgd_populate_kernel(mm, pmd, pte) BUG() | ||
71 | #else /* __s390x__ */ | 90 | #else /* __s390x__ */ |
72 | static inline pmd_t * pmd_alloc_one(struct mm_struct *mm, unsigned long vmaddr) | 91 | static inline pmd_t * pmd_alloc_one(struct mm_struct *mm, unsigned long vmaddr) |
73 | { | 92 | { |
@@ -76,6 +95,17 @@ static inline pmd_t * pmd_alloc_one(struct mm_struct *mm, unsigned long vmaddr) | |||
76 | 95 | ||
77 | if (!pmd) | 96 | if (!pmd) |
78 | return NULL; | 97 | return NULL; |
98 | if (s390_noexec) { | ||
99 | pmd_t *shadow_pmd = (pmd_t *) | ||
100 | __get_free_pages(GFP_KERNEL, PMD_ALLOC_ORDER); | ||
101 | struct page *page = virt_to_page(pmd); | ||
102 | |||
103 | if (!shadow_pmd) { | ||
104 | free_pages((unsigned long) pmd, PMD_ALLOC_ORDER); | ||
105 | return NULL; | ||
106 | } | ||
107 | page->lru.next = (void *) shadow_pmd; | ||
108 | } | ||
79 | for (i=0; i < PTRS_PER_PMD; i++) | 109 | for (i=0; i < PTRS_PER_PMD; i++) |
80 | pmd_clear(pmd + i); | 110 | pmd_clear(pmd + i); |
81 | return pmd; | 111 | return pmd; |
@@ -83,6 +113,10 @@ static inline pmd_t * pmd_alloc_one(struct mm_struct *mm, unsigned long vmaddr) | |||
83 | 113 | ||
84 | static inline void pmd_free (pmd_t *pmd) | 114 | static inline void pmd_free (pmd_t *pmd) |
85 | { | 115 | { |
116 | pmd_t *shadow_pmd = get_shadow_pmd(pmd); | ||
117 | |||
118 | if (shadow_pmd) | ||
119 | free_pages((unsigned long) shadow_pmd, PMD_ALLOC_ORDER); | ||
86 | free_pages((unsigned long) pmd, PMD_ALLOC_ORDER); | 120 | free_pages((unsigned long) pmd, PMD_ALLOC_ORDER); |
87 | } | 121 | } |
88 | 122 | ||
@@ -92,11 +126,22 @@ static inline void pmd_free (pmd_t *pmd) | |||
92 | pmd_free(pmd); \ | 126 | pmd_free(pmd); \ |
93 | } while (0) | 127 | } while (0) |
94 | 128 | ||
95 | static inline void pgd_populate(struct mm_struct *mm, pgd_t *pgd, pmd_t *pmd) | 129 | static inline void |
130 | pgd_populate_kernel(struct mm_struct *mm, pgd_t *pgd, pmd_t *pmd) | ||
96 | { | 131 | { |
97 | pgd_val(*pgd) = _PGD_ENTRY | __pa(pmd); | 132 | pgd_val(*pgd) = _PGD_ENTRY | __pa(pmd); |
98 | } | 133 | } |
99 | 134 | ||
135 | static inline void pgd_populate(struct mm_struct *mm, pgd_t *pgd, pmd_t *pmd) | ||
136 | { | ||
137 | pgd_t *shadow_pgd = get_shadow_pgd(pgd); | ||
138 | pmd_t *shadow_pmd = get_shadow_pmd(pmd); | ||
139 | |||
140 | if (shadow_pgd && shadow_pmd) | ||
141 | pgd_populate_kernel(mm, shadow_pgd, shadow_pmd); | ||
142 | pgd_populate_kernel(mm, pgd, pmd); | ||
143 | } | ||
144 | |||
100 | #endif /* __s390x__ */ | 145 | #endif /* __s390x__ */ |
101 | 146 | ||
102 | static inline void | 147 | static inline void |
@@ -116,7 +161,13 @@ pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmd, pte_t *pte) | |||
116 | static inline void | 161 | static inline void |
117 | pmd_populate(struct mm_struct *mm, pmd_t *pmd, struct page *page) | 162 | pmd_populate(struct mm_struct *mm, pmd_t *pmd, struct page *page) |
118 | { | 163 | { |
119 | pmd_populate_kernel(mm, pmd, (pte_t *)page_to_phys(page)); | 164 | pte_t *pte = (pte_t *)page_to_phys(page); |
165 | pmd_t *shadow_pmd = get_shadow_pmd(pmd); | ||
166 | pte_t *shadow_pte = get_shadow_pte(pte); | ||
167 | |||
168 | pmd_populate_kernel(mm, pmd, pte); | ||
169 | if (shadow_pmd && shadow_pte) | ||
170 | pmd_populate_kernel(mm, shadow_pmd, shadow_pte); | ||
120 | } | 171 | } |
121 | 172 | ||
122 | /* | 173 | /* |
@@ -130,6 +181,17 @@ pte_alloc_one_kernel(struct mm_struct *mm, unsigned long vmaddr) | |||
130 | 181 | ||
131 | if (!pte) | 182 | if (!pte) |
132 | return NULL; | 183 | return NULL; |
184 | if (s390_noexec) { | ||
185 | pte_t *shadow_pte = (pte_t *) | ||
186 | __get_free_page(GFP_KERNEL|__GFP_REPEAT); | ||
187 | struct page *page = virt_to_page(pte); | ||
188 | |||
189 | if (!shadow_pte) { | ||
190 | free_page((unsigned long) pte); | ||
191 | return NULL; | ||
192 | } | ||
193 | page->lru.next = (void *) shadow_pte; | ||
194 | } | ||
133 | for (i=0; i < PTRS_PER_PTE; i++) { | 195 | for (i=0; i < PTRS_PER_PTE; i++) { |
134 | pte_clear(mm, vmaddr, pte + i); | 196 | pte_clear(mm, vmaddr, pte + i); |
135 | vmaddr += PAGE_SIZE; | 197 | vmaddr += PAGE_SIZE; |
@@ -148,14 +210,30 @@ pte_alloc_one(struct mm_struct *mm, unsigned long vmaddr) | |||
148 | 210 | ||
149 | static inline void pte_free_kernel(pte_t *pte) | 211 | static inline void pte_free_kernel(pte_t *pte) |
150 | { | 212 | { |
151 | free_page((unsigned long) pte); | 213 | pte_t *shadow_pte = get_shadow_pte(pte); |
214 | |||
215 | if (shadow_pte) | ||
216 | free_page((unsigned long) shadow_pte); | ||
217 | free_page((unsigned long) pte); | ||
152 | } | 218 | } |
153 | 219 | ||
154 | static inline void pte_free(struct page *pte) | 220 | static inline void pte_free(struct page *pte) |
155 | { | 221 | { |
156 | __free_page(pte); | 222 | struct page *shadow_page = get_shadow_page(pte); |
223 | |||
224 | if (shadow_page) | ||
225 | __free_page(shadow_page); | ||
226 | __free_page(pte); | ||
157 | } | 227 | } |
158 | 228 | ||
159 | #define __pte_free_tlb(tlb,pte) tlb_remove_page(tlb,pte) | 229 | #define __pte_free_tlb(tlb, pte) \ |
230 | ({ \ | ||
231 | struct mmu_gather *__tlb = (tlb); \ | ||
232 | struct page *__pte = (pte); \ | ||
233 | struct page *shadow_page = get_shadow_page(__pte); \ | ||
234 | if (shadow_page) \ | ||
235 | tlb_remove_page(__tlb, shadow_page); \ | ||
236 | tlb_remove_page(__tlb, __pte); \ | ||
237 | }) | ||
160 | 238 | ||
161 | #endif /* _S390_PGALLOC_H */ | 239 | #endif /* _S390_PGALLOC_H */ |
diff --git a/include/asm-s390/pgtable.h b/include/asm-s390/pgtable.h index 2d968a69ed1f..13c16546eff5 100644 --- a/include/asm-s390/pgtable.h +++ b/include/asm-s390/pgtable.h | |||
@@ -40,6 +40,7 @@ struct mm_struct; | |||
40 | 40 | ||
41 | extern pgd_t swapper_pg_dir[] __attribute__ ((aligned (4096))); | 41 | extern pgd_t swapper_pg_dir[] __attribute__ ((aligned (4096))); |
42 | extern void paging_init(void); | 42 | extern void paging_init(void); |
43 | extern void vmem_map_init(void); | ||
43 | 44 | ||
44 | /* | 45 | /* |
45 | * The S390 doesn't have any external MMU info: the kernel page | 46 | * The S390 doesn't have any external MMU info: the kernel page |
@@ -107,23 +108,25 @@ extern char empty_zero_page[PAGE_SIZE]; | |||
107 | * The vmalloc() routines leaves a hole of 4kB between each vmalloced | 108 | * The vmalloc() routines leaves a hole of 4kB between each vmalloced |
108 | * area for the same reason. ;) | 109 | * area for the same reason. ;) |
109 | */ | 110 | */ |
111 | extern unsigned long vmalloc_end; | ||
110 | #define VMALLOC_OFFSET (8*1024*1024) | 112 | #define VMALLOC_OFFSET (8*1024*1024) |
111 | #define VMALLOC_START (((unsigned long) high_memory + VMALLOC_OFFSET) \ | 113 | #define VMALLOC_START (((unsigned long) high_memory + VMALLOC_OFFSET) \ |
112 | & ~(VMALLOC_OFFSET-1)) | 114 | & ~(VMALLOC_OFFSET-1)) |
115 | #define VMALLOC_END vmalloc_end | ||
113 | 116 | ||
114 | /* | 117 | /* |
115 | * We need some free virtual space to be able to do vmalloc. | 118 | * We need some free virtual space to be able to do vmalloc. |
116 | * VMALLOC_MIN_SIZE defines the minimum size of the vmalloc | 119 | * VMALLOC_MIN_SIZE defines the minimum size of the vmalloc |
117 | * area. On a machine with 2GB memory we make sure that we | 120 | * area. On a machine with 2GB memory we make sure that we |
118 | * have at least 128MB free space for vmalloc. On a machine | 121 | * have at least 128MB free space for vmalloc. On a machine |
119 | * with 4TB we make sure we have at least 1GB. | 122 | * with 4TB we make sure we have at least 128GB. |
120 | */ | 123 | */ |
121 | #ifndef __s390x__ | 124 | #ifndef __s390x__ |
122 | #define VMALLOC_MIN_SIZE 0x8000000UL | 125 | #define VMALLOC_MIN_SIZE 0x8000000UL |
123 | #define VMALLOC_END 0x80000000UL | 126 | #define VMALLOC_END_INIT 0x80000000UL |
124 | #else /* __s390x__ */ | 127 | #else /* __s390x__ */ |
125 | #define VMALLOC_MIN_SIZE 0x40000000UL | 128 | #define VMALLOC_MIN_SIZE 0x2000000000UL |
126 | #define VMALLOC_END 0x40000000000UL | 129 | #define VMALLOC_END_INIT 0x40000000000UL |
127 | #endif /* __s390x__ */ | 130 | #endif /* __s390x__ */ |
128 | 131 | ||
129 | /* | 132 | /* |
@@ -221,6 +224,8 @@ extern char empty_zero_page[PAGE_SIZE]; | |||
221 | #define _PAGE_TYPE_FILE 0x601 /* bit 0x002 is used for offset !! */ | 224 | #define _PAGE_TYPE_FILE 0x601 /* bit 0x002 is used for offset !! */ |
222 | #define _PAGE_TYPE_RO 0x200 | 225 | #define _PAGE_TYPE_RO 0x200 |
223 | #define _PAGE_TYPE_RW 0x000 | 226 | #define _PAGE_TYPE_RW 0x000 |
227 | #define _PAGE_TYPE_EX_RO 0x202 | ||
228 | #define _PAGE_TYPE_EX_RW 0x002 | ||
224 | 229 | ||
225 | /* | 230 | /* |
226 | * PTE type bits are rather complicated. handle_pte_fault uses pte_present, | 231 | * PTE type bits are rather complicated. handle_pte_fault uses pte_present, |
@@ -241,11 +246,13 @@ extern char empty_zero_page[PAGE_SIZE]; | |||
241 | * _PAGE_TYPE_FILE 11?1 -> 11?1 | 246 | * _PAGE_TYPE_FILE 11?1 -> 11?1 |
242 | * _PAGE_TYPE_RO 0100 -> 1100 | 247 | * _PAGE_TYPE_RO 0100 -> 1100 |
243 | * _PAGE_TYPE_RW 0000 -> 1000 | 248 | * _PAGE_TYPE_RW 0000 -> 1000 |
249 | * _PAGE_TYPE_EX_RO 0110 -> 1110 | ||
250 | * _PAGE_TYPE_EX_RW 0010 -> 1010 | ||
244 | * | 251 | * |
245 | * pte_none is true for bits combinations 1000, 1100 | 252 | * pte_none is true for bits combinations 1000, 1010, 1100, 1110 |
246 | * pte_present is true for bits combinations 0000, 0010, 0100, 0110, 1001 | 253 | * pte_present is true for bits combinations 0000, 0010, 0100, 0110, 1001 |
247 | * pte_file is true for bits combinations 1101, 1111 | 254 | * pte_file is true for bits combinations 1101, 1111 |
248 | * swap pte is 1011 and 0001, 0011, 0101, 0111, 1010 and 1110 are invalid. | 255 | * swap pte is 1011 and 0001, 0011, 0101, 0111 are invalid. |
249 | */ | 256 | */ |
250 | 257 | ||
251 | #ifndef __s390x__ | 258 | #ifndef __s390x__ |
@@ -310,33 +317,100 @@ extern char empty_zero_page[PAGE_SIZE]; | |||
310 | #define PAGE_NONE __pgprot(_PAGE_TYPE_NONE) | 317 | #define PAGE_NONE __pgprot(_PAGE_TYPE_NONE) |
311 | #define PAGE_RO __pgprot(_PAGE_TYPE_RO) | 318 | #define PAGE_RO __pgprot(_PAGE_TYPE_RO) |
312 | #define PAGE_RW __pgprot(_PAGE_TYPE_RW) | 319 | #define PAGE_RW __pgprot(_PAGE_TYPE_RW) |
320 | #define PAGE_EX_RO __pgprot(_PAGE_TYPE_EX_RO) | ||
321 | #define PAGE_EX_RW __pgprot(_PAGE_TYPE_EX_RW) | ||
313 | 322 | ||
314 | #define PAGE_KERNEL PAGE_RW | 323 | #define PAGE_KERNEL PAGE_RW |
315 | #define PAGE_COPY PAGE_RO | 324 | #define PAGE_COPY PAGE_RO |
316 | 325 | ||
317 | /* | 326 | /* |
318 | * The S390 can't do page protection for execute, and considers that the | 327 | * Dependent on the EXEC_PROTECT option s390 can do execute protection. |
319 | * same are read. Also, write permissions imply read permissions. This is | 328 | * Write permission always implies read permission. In theory with a |
320 | * the closest we can get.. | 329 | * primary/secondary page table execute only can be implemented but |
330 | * it would cost an additional bit in the pte to distinguish all the | ||
331 | * different pte types. To avoid that execute permission currently | ||
332 | * implies read permission as well. | ||
321 | */ | 333 | */ |
322 | /*xwr*/ | 334 | /*xwr*/ |
323 | #define __P000 PAGE_NONE | 335 | #define __P000 PAGE_NONE |
324 | #define __P001 PAGE_RO | 336 | #define __P001 PAGE_RO |
325 | #define __P010 PAGE_RO | 337 | #define __P010 PAGE_RO |
326 | #define __P011 PAGE_RO | 338 | #define __P011 PAGE_RO |
327 | #define __P100 PAGE_RO | 339 | #define __P100 PAGE_EX_RO |
328 | #define __P101 PAGE_RO | 340 | #define __P101 PAGE_EX_RO |
329 | #define __P110 PAGE_RO | 341 | #define __P110 PAGE_EX_RO |
330 | #define __P111 PAGE_RO | 342 | #define __P111 PAGE_EX_RO |
331 | 343 | ||
332 | #define __S000 PAGE_NONE | 344 | #define __S000 PAGE_NONE |
333 | #define __S001 PAGE_RO | 345 | #define __S001 PAGE_RO |
334 | #define __S010 PAGE_RW | 346 | #define __S010 PAGE_RW |
335 | #define __S011 PAGE_RW | 347 | #define __S011 PAGE_RW |
336 | #define __S100 PAGE_RO | 348 | #define __S100 PAGE_EX_RO |
337 | #define __S101 PAGE_RO | 349 | #define __S101 PAGE_EX_RO |
338 | #define __S110 PAGE_RW | 350 | #define __S110 PAGE_EX_RW |
339 | #define __S111 PAGE_RW | 351 | #define __S111 PAGE_EX_RW |
352 | |||
353 | #ifndef __s390x__ | ||
354 | # define PMD_SHADOW_SHIFT 1 | ||
355 | # define PGD_SHADOW_SHIFT 1 | ||
356 | #else /* __s390x__ */ | ||
357 | # define PMD_SHADOW_SHIFT 2 | ||
358 | # define PGD_SHADOW_SHIFT 2 | ||
359 | #endif /* __s390x__ */ | ||
360 | |||
361 | static inline struct page *get_shadow_page(struct page *page) | ||
362 | { | ||
363 | if (s390_noexec && !list_empty(&page->lru)) | ||
364 | return virt_to_page(page->lru.next); | ||
365 | return NULL; | ||
366 | } | ||
367 | |||
368 | static inline pte_t *get_shadow_pte(pte_t *ptep) | ||
369 | { | ||
370 | unsigned long pteptr = (unsigned long) (ptep); | ||
371 | |||
372 | if (s390_noexec) { | ||
373 | unsigned long offset = pteptr & (PAGE_SIZE - 1); | ||
374 | void *addr = (void *) (pteptr ^ offset); | ||
375 | struct page *page = virt_to_page(addr); | ||
376 | if (!list_empty(&page->lru)) | ||
377 | return (pte_t *) ((unsigned long) page->lru.next | | ||
378 | offset); | ||
379 | } | ||
380 | return NULL; | ||
381 | } | ||
382 | |||
383 | static inline pmd_t *get_shadow_pmd(pmd_t *pmdp) | ||
384 | { | ||
385 | unsigned long pmdptr = (unsigned long) (pmdp); | ||
386 | |||
387 | if (s390_noexec) { | ||
388 | unsigned long offset = pmdptr & | ||
389 | ((PAGE_SIZE << PMD_SHADOW_SHIFT) - 1); | ||
390 | void *addr = (void *) (pmdptr ^ offset); | ||
391 | struct page *page = virt_to_page(addr); | ||
392 | if (!list_empty(&page->lru)) | ||
393 | return (pmd_t *) ((unsigned long) page->lru.next | | ||
394 | offset); | ||
395 | } | ||
396 | return NULL; | ||
397 | } | ||
398 | |||
399 | static inline pgd_t *get_shadow_pgd(pgd_t *pgdp) | ||
400 | { | ||
401 | unsigned long pgdptr = (unsigned long) (pgdp); | ||
402 | |||
403 | if (s390_noexec) { | ||
404 | unsigned long offset = pgdptr & | ||
405 | ((PAGE_SIZE << PGD_SHADOW_SHIFT) - 1); | ||
406 | void *addr = (void *) (pgdptr ^ offset); | ||
407 | struct page *page = virt_to_page(addr); | ||
408 | if (!list_empty(&page->lru)) | ||
409 | return (pgd_t *) ((unsigned long) page->lru.next | | ||
410 | offset); | ||
411 | } | ||
412 | return NULL; | ||
413 | } | ||
340 | 414 | ||
341 | /* | 415 | /* |
342 | * Certain architectures need to do special things when PTEs | 416 | * Certain architectures need to do special things when PTEs |
@@ -345,7 +419,16 @@ extern char empty_zero_page[PAGE_SIZE]; | |||
345 | */ | 419 | */ |
346 | static inline void set_pte(pte_t *pteptr, pte_t pteval) | 420 | static inline void set_pte(pte_t *pteptr, pte_t pteval) |
347 | { | 421 | { |
422 | pte_t *shadow_pte = get_shadow_pte(pteptr); | ||
423 | |||
348 | *pteptr = pteval; | 424 | *pteptr = pteval; |
425 | if (shadow_pte) { | ||
426 | if (!(pte_val(pteval) & _PAGE_INVALID) && | ||
427 | (pte_val(pteval) & _PAGE_SWX)) | ||
428 | pte_val(*shadow_pte) = pte_val(pteval) | _PAGE_RO; | ||
429 | else | ||
430 | pte_val(*shadow_pte) = _PAGE_TYPE_EMPTY; | ||
431 | } | ||
349 | } | 432 | } |
350 | #define set_pte_at(mm,addr,ptep,pteval) set_pte(ptep,pteval) | 433 | #define set_pte_at(mm,addr,ptep,pteval) set_pte(ptep,pteval) |
351 | 434 | ||
@@ -463,7 +546,7 @@ static inline int pte_read(pte_t pte) | |||
463 | 546 | ||
464 | static inline void pgd_clear(pgd_t * pgdp) { } | 547 | static inline void pgd_clear(pgd_t * pgdp) { } |
465 | 548 | ||
466 | static inline void pmd_clear(pmd_t * pmdp) | 549 | static inline void pmd_clear_kernel(pmd_t * pmdp) |
467 | { | 550 | { |
468 | pmd_val(pmdp[0]) = _PAGE_TABLE_INV; | 551 | pmd_val(pmdp[0]) = _PAGE_TABLE_INV; |
469 | pmd_val(pmdp[1]) = _PAGE_TABLE_INV; | 552 | pmd_val(pmdp[1]) = _PAGE_TABLE_INV; |
@@ -471,24 +554,55 @@ static inline void pmd_clear(pmd_t * pmdp) | |||
471 | pmd_val(pmdp[3]) = _PAGE_TABLE_INV; | 554 | pmd_val(pmdp[3]) = _PAGE_TABLE_INV; |
472 | } | 555 | } |
473 | 556 | ||
557 | static inline void pmd_clear(pmd_t * pmdp) | ||
558 | { | ||
559 | pmd_t *shadow_pmd = get_shadow_pmd(pmdp); | ||
560 | |||
561 | pmd_clear_kernel(pmdp); | ||
562 | if (shadow_pmd) | ||
563 | pmd_clear_kernel(shadow_pmd); | ||
564 | } | ||
565 | |||
474 | #else /* __s390x__ */ | 566 | #else /* __s390x__ */ |
475 | 567 | ||
476 | static inline void pgd_clear(pgd_t * pgdp) | 568 | static inline void pgd_clear_kernel(pgd_t * pgdp) |
477 | { | 569 | { |
478 | pgd_val(*pgdp) = _PGD_ENTRY_INV | _PGD_ENTRY; | 570 | pgd_val(*pgdp) = _PGD_ENTRY_INV | _PGD_ENTRY; |
479 | } | 571 | } |
480 | 572 | ||
481 | static inline void pmd_clear(pmd_t * pmdp) | 573 | static inline void pgd_clear(pgd_t * pgdp) |
574 | { | ||
575 | pgd_t *shadow_pgd = get_shadow_pgd(pgdp); | ||
576 | |||
577 | pgd_clear_kernel(pgdp); | ||
578 | if (shadow_pgd) | ||
579 | pgd_clear_kernel(shadow_pgd); | ||
580 | } | ||
581 | |||
582 | static inline void pmd_clear_kernel(pmd_t * pmdp) | ||
482 | { | 583 | { |
483 | pmd_val(*pmdp) = _PMD_ENTRY_INV | _PMD_ENTRY; | 584 | pmd_val(*pmdp) = _PMD_ENTRY_INV | _PMD_ENTRY; |
484 | pmd_val1(*pmdp) = _PMD_ENTRY_INV | _PMD_ENTRY; | 585 | pmd_val1(*pmdp) = _PMD_ENTRY_INV | _PMD_ENTRY; |
485 | } | 586 | } |
486 | 587 | ||
588 | static inline void pmd_clear(pmd_t * pmdp) | ||
589 | { | ||
590 | pmd_t *shadow_pmd = get_shadow_pmd(pmdp); | ||
591 | |||
592 | pmd_clear_kernel(pmdp); | ||
593 | if (shadow_pmd) | ||
594 | pmd_clear_kernel(shadow_pmd); | ||
595 | } | ||
596 | |||
487 | #endif /* __s390x__ */ | 597 | #endif /* __s390x__ */ |
488 | 598 | ||
489 | static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep) | 599 | static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep) |
490 | { | 600 | { |
601 | pte_t *shadow_pte = get_shadow_pte(ptep); | ||
602 | |||
491 | pte_val(*ptep) = _PAGE_TYPE_EMPTY; | 603 | pte_val(*ptep) = _PAGE_TYPE_EMPTY; |
604 | if (shadow_pte) | ||
605 | pte_val(*shadow_pte) = _PAGE_TYPE_EMPTY; | ||
492 | } | 606 | } |
493 | 607 | ||
494 | /* | 608 | /* |
@@ -606,8 +720,11 @@ ptep_clear_flush(struct vm_area_struct *vma, | |||
606 | unsigned long address, pte_t *ptep) | 720 | unsigned long address, pte_t *ptep) |
607 | { | 721 | { |
608 | pte_t pte = *ptep; | 722 | pte_t pte = *ptep; |
723 | pte_t *shadow_pte = get_shadow_pte(ptep); | ||
609 | 724 | ||
610 | __ptep_ipte(address, ptep); | 725 | __ptep_ipte(address, ptep); |
726 | if (shadow_pte) | ||
727 | __ptep_ipte(address, shadow_pte); | ||
611 | return pte; | 728 | return pte; |
612 | } | 729 | } |
613 | 730 | ||
@@ -815,11 +932,17 @@ static inline pte_t mk_swap_pte(unsigned long type, unsigned long offset) | |||
815 | 932 | ||
816 | #define kern_addr_valid(addr) (1) | 933 | #define kern_addr_valid(addr) (1) |
817 | 934 | ||
935 | extern int add_shared_memory(unsigned long start, unsigned long size); | ||
936 | extern int remove_shared_memory(unsigned long start, unsigned long size); | ||
937 | |||
818 | /* | 938 | /* |
819 | * No page table caches to initialise | 939 | * No page table caches to initialise |
820 | */ | 940 | */ |
821 | #define pgtable_cache_init() do { } while (0) | 941 | #define pgtable_cache_init() do { } while (0) |
822 | 942 | ||
943 | #define __HAVE_ARCH_MEMMAP_INIT | ||
944 | extern void memmap_init(unsigned long, int, unsigned long, unsigned long); | ||
945 | |||
823 | #define __HAVE_ARCH_PTEP_ESTABLISH | 946 | #define __HAVE_ARCH_PTEP_ESTABLISH |
824 | #define __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS | 947 | #define __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS |
825 | #define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG | 948 | #define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG |
diff --git a/include/asm-s390/posix_types.h b/include/asm-s390/posix_types.h index b94c98856e12..397d93fba3a7 100644 --- a/include/asm-s390/posix_types.h +++ b/include/asm-s390/posix_types.h | |||
@@ -104,7 +104,7 @@ static inline int __FD_ISSET(unsigned long fd, const __kernel_fd_set *fdsetp) | |||
104 | 104 | ||
105 | #undef __FD_ZERO | 105 | #undef __FD_ZERO |
106 | #define __FD_ZERO(fdsetp) \ | 106 | #define __FD_ZERO(fdsetp) \ |
107 | ((void) memset ((__ptr_t) (fdsetp), 0, sizeof (__kernel_fd_set))) | 107 | ((void) memset ((void *) (fdsetp), 0, sizeof (__kernel_fd_set))) |
108 | 108 | ||
109 | #endif /* __KERNEL__ */ | 109 | #endif /* __KERNEL__ */ |
110 | 110 | ||
diff --git a/include/asm-s390/processor.h b/include/asm-s390/processor.h index cbbedc63ba25..4c1b73940351 100644 --- a/include/asm-s390/processor.h +++ b/include/asm-s390/processor.h | |||
@@ -50,6 +50,7 @@ struct cpuinfo_S390 | |||
50 | unsigned long pgtable_cache_sz; | 50 | unsigned long pgtable_cache_sz; |
51 | }; | 51 | }; |
52 | 52 | ||
53 | extern void s390_adjust_jiffies(void); | ||
53 | extern void print_cpu_info(struct cpuinfo_S390 *); | 54 | extern void print_cpu_info(struct cpuinfo_S390 *); |
54 | 55 | ||
55 | /* Lazy FPU handling on uni-processor */ | 56 | /* Lazy FPU handling on uni-processor */ |
@@ -144,7 +145,8 @@ struct stack_frame { | |||
144 | #ifndef __s390x__ | 145 | #ifndef __s390x__ |
145 | 146 | ||
146 | #define start_thread(regs, new_psw, new_stackp) do { \ | 147 | #define start_thread(regs, new_psw, new_stackp) do { \ |
147 | regs->psw.mask = PSW_USER_BITS; \ | 148 | set_fs(USER_DS); \ |
149 | regs->psw.mask = psw_user_bits; \ | ||
148 | regs->psw.addr = new_psw | PSW_ADDR_AMODE; \ | 150 | regs->psw.addr = new_psw | PSW_ADDR_AMODE; \ |
149 | regs->gprs[15] = new_stackp ; \ | 151 | regs->gprs[15] = new_stackp ; \ |
150 | } while (0) | 152 | } while (0) |
@@ -152,13 +154,15 @@ struct stack_frame { | |||
152 | #else /* __s390x__ */ | 154 | #else /* __s390x__ */ |
153 | 155 | ||
154 | #define start_thread(regs, new_psw, new_stackp) do { \ | 156 | #define start_thread(regs, new_psw, new_stackp) do { \ |
155 | regs->psw.mask = PSW_USER_BITS; \ | 157 | set_fs(USER_DS); \ |
158 | regs->psw.mask = psw_user_bits; \ | ||
156 | regs->psw.addr = new_psw; \ | 159 | regs->psw.addr = new_psw; \ |
157 | regs->gprs[15] = new_stackp; \ | 160 | regs->gprs[15] = new_stackp; \ |
158 | } while (0) | 161 | } while (0) |
159 | 162 | ||
160 | #define start_thread31(regs, new_psw, new_stackp) do { \ | 163 | #define start_thread31(regs, new_psw, new_stackp) do { \ |
161 | regs->psw.mask = PSW_USER32_BITS; \ | 164 | set_fs(USER_DS); \ |
165 | regs->psw.mask = psw_user32_bits; \ | ||
162 | regs->psw.addr = new_psw; \ | 166 | regs->psw.addr = new_psw; \ |
163 | regs->gprs[15] = new_stackp; \ | 167 | regs->gprs[15] = new_stackp; \ |
164 | } while (0) | 168 | } while (0) |
@@ -201,9 +205,8 @@ unsigned long get_wchan(struct task_struct *p); | |||
201 | static inline void cpu_relax(void) | 205 | static inline void cpu_relax(void) |
202 | { | 206 | { |
203 | if (MACHINE_HAS_DIAG44) | 207 | if (MACHINE_HAS_DIAG44) |
204 | asm volatile("diag 0,0,68" : : : "memory"); | 208 | asm volatile("diag 0,0,68"); |
205 | else | 209 | barrier(); |
206 | barrier(); | ||
207 | } | 210 | } |
208 | 211 | ||
209 | /* | 212 | /* |
@@ -328,6 +331,18 @@ static inline void disabled_wait(unsigned long code) | |||
328 | } | 331 | } |
329 | 332 | ||
330 | /* | 333 | /* |
334 | * Basic Machine Check/Program Check Handler. | ||
335 | */ | ||
336 | |||
337 | extern void s390_base_mcck_handler(void); | ||
338 | extern void s390_base_pgm_handler(void); | ||
339 | extern void s390_base_ext_handler(void); | ||
340 | |||
341 | extern void (*s390_base_mcck_handler_fn)(void); | ||
342 | extern void (*s390_base_pgm_handler_fn)(void); | ||
343 | extern void (*s390_base_ext_handler_fn)(void); | ||
344 | |||
345 | /* | ||
331 | * CPU idle notifier chain. | 346 | * CPU idle notifier chain. |
332 | */ | 347 | */ |
333 | #define CPU_IDLE 0 | 348 | #define CPU_IDLE 0 |
diff --git a/include/asm-s390/ptrace.h b/include/asm-s390/ptrace.h index 7b768c5c68a8..fa6ca87080e8 100644 --- a/include/asm-s390/ptrace.h +++ b/include/asm-s390/ptrace.h | |||
@@ -266,17 +266,12 @@ typedef struct | |||
266 | #define PSW_ASC_SECONDARY 0x0000800000000000UL | 266 | #define PSW_ASC_SECONDARY 0x0000800000000000UL |
267 | #define PSW_ASC_HOME 0x0000C00000000000UL | 267 | #define PSW_ASC_HOME 0x0000C00000000000UL |
268 | 268 | ||
269 | #define PSW_USER32_BITS (PSW_BASE32_BITS | PSW_MASK_DAT | PSW_ASC_HOME | \ | 269 | extern long psw_user32_bits; |
270 | PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK | \ | ||
271 | PSW_MASK_PSTATE | PSW_DEFAULT_KEY) | ||
272 | 270 | ||
273 | #endif /* __s390x__ */ | 271 | #endif /* __s390x__ */ |
274 | 272 | ||
275 | #define PSW_KERNEL_BITS (PSW_BASE_BITS | PSW_MASK_DAT | PSW_ASC_PRIMARY | \ | 273 | extern long psw_kernel_bits; |
276 | PSW_MASK_MCHECK | PSW_DEFAULT_KEY) | 274 | extern long psw_user_bits; |
277 | #define PSW_USER_BITS (PSW_BASE_BITS | PSW_MASK_DAT | PSW_ASC_HOME | \ | ||
278 | PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK | \ | ||
279 | PSW_MASK_PSTATE | PSW_DEFAULT_KEY) | ||
280 | 275 | ||
281 | /* This macro merges a NEW PSW mask specified by the user into | 276 | /* This macro merges a NEW PSW mask specified by the user into |
282 | the currently active PSW mask CURRENT, modifying only those | 277 | the currently active PSW mask CURRENT, modifying only those |
diff --git a/include/asm-s390/qdio.h b/include/asm-s390/qdio.h index 7189c79bc673..127f72e77419 100644 --- a/include/asm-s390/qdio.h +++ b/include/asm-s390/qdio.h | |||
@@ -34,6 +34,7 @@ | |||
34 | #define QDIO_QETH_QFMT 0 | 34 | #define QDIO_QETH_QFMT 0 |
35 | #define QDIO_ZFCP_QFMT 1 | 35 | #define QDIO_ZFCP_QFMT 1 |
36 | #define QDIO_IQDIO_QFMT 2 | 36 | #define QDIO_IQDIO_QFMT 2 |
37 | #define QDIO_IQDIO_QFMT_ASYNCH 3 | ||
37 | 38 | ||
38 | struct qdio_buffer_element{ | 39 | struct qdio_buffer_element{ |
39 | unsigned int flags; | 40 | unsigned int flags; |
diff --git a/include/asm-s390/reset.h b/include/asm-s390/reset.h index 9b439cf67800..f584f4a52581 100644 --- a/include/asm-s390/reset.h +++ b/include/asm-s390/reset.h | |||
@@ -18,6 +18,4 @@ struct reset_call { | |||
18 | extern void register_reset_call(struct reset_call *reset); | 18 | extern void register_reset_call(struct reset_call *reset); |
19 | extern void unregister_reset_call(struct reset_call *reset); | 19 | extern void unregister_reset_call(struct reset_call *reset); |
20 | extern void s390_reset_system(void); | 20 | extern void s390_reset_system(void); |
21 | extern void (*s390_reset_mcck_handler)(void); | ||
22 | |||
23 | #endif /* _ASM_S390_RESET_H */ | 21 | #endif /* _ASM_S390_RESET_H */ |
diff --git a/include/asm-s390/sclp.h b/include/asm-s390/sclp.h new file mode 100644 index 000000000000..468b97018405 --- /dev/null +++ b/include/asm-s390/sclp.h | |||
@@ -0,0 +1,39 @@ | |||
1 | /* | ||
2 | * include/asm-s390/sclp.h | ||
3 | * | ||
4 | * Copyright IBM Corp. 2007 | ||
5 | * Author(s): Heiko Carstens <heiko.carstens@de.ibm.com> | ||
6 | */ | ||
7 | |||
8 | #ifndef _ASM_S390_SCLP_H | ||
9 | #define _ASM_S390_SCLP_H | ||
10 | |||
11 | #include <linux/types.h> | ||
12 | |||
13 | struct sccb_header { | ||
14 | u16 length; | ||
15 | u8 function_code; | ||
16 | u8 control_mask[3]; | ||
17 | u16 response_code; | ||
18 | } __attribute__((packed)); | ||
19 | |||
20 | #define LOADPARM_LEN 8 | ||
21 | |||
22 | struct sclp_readinfo_sccb { | ||
23 | struct sccb_header header; /* 0-7 */ | ||
24 | u16 rnmax; /* 8-9 */ | ||
25 | u8 rnsize; /* 10 */ | ||
26 | u8 _reserved0[24 - 11]; /* 11-23 */ | ||
27 | u8 loadparm[LOADPARM_LEN]; /* 24-31 */ | ||
28 | u8 _reserved1[91 - 32]; /* 32-90 */ | ||
29 | u8 flags; /* 91 */ | ||
30 | u8 _reserved2[100 - 92]; /* 92-99 */ | ||
31 | u32 rnsize2; /* 100-103 */ | ||
32 | u64 rnmax2; /* 104-111 */ | ||
33 | u8 _reserved3[4096 - 112]; /* 112-4095 */ | ||
34 | } __attribute__((packed, aligned(4096))); | ||
35 | |||
36 | extern struct sclp_readinfo_sccb s390_readinfo_sccb; | ||
37 | extern void sclp_readinfo_early(void); | ||
38 | |||
39 | #endif /* _ASM_S390_SCLP_H */ | ||
diff --git a/include/asm-s390/sections.h b/include/asm-s390/sections.h index 3a0b8ffeab7a..1c5a2c4ccdad 100644 --- a/include/asm-s390/sections.h +++ b/include/asm-s390/sections.h | |||
@@ -3,4 +3,6 @@ | |||
3 | 3 | ||
4 | #include <asm-generic/sections.h> | 4 | #include <asm-generic/sections.h> |
5 | 5 | ||
6 | extern char _eshared[]; | ||
7 | |||
6 | #endif | 8 | #endif |
diff --git a/include/asm-s390/setup.h b/include/asm-s390/setup.h index 9574fe80a046..3388bb52597c 100644 --- a/include/asm-s390/setup.h +++ b/include/asm-s390/setup.h | |||
@@ -42,6 +42,18 @@ struct mem_chunk { | |||
42 | 42 | ||
43 | extern struct mem_chunk memory_chunk[]; | 43 | extern struct mem_chunk memory_chunk[]; |
44 | 44 | ||
45 | #ifdef CONFIG_S390_SWITCH_AMODE | ||
46 | extern unsigned int switch_amode; | ||
47 | #else | ||
48 | #define switch_amode (0) | ||
49 | #endif | ||
50 | |||
51 | #ifdef CONFIG_S390_EXEC_PROTECT | ||
52 | extern unsigned int s390_noexec; | ||
53 | #else | ||
54 | #define s390_noexec (0) | ||
55 | #endif | ||
56 | |||
45 | /* | 57 | /* |
46 | * Machine features detected in head.S | 58 | * Machine features detected in head.S |
47 | */ | 59 | */ |
@@ -74,6 +86,9 @@ extern unsigned int console_mode; | |||
74 | extern unsigned int console_devno; | 86 | extern unsigned int console_devno; |
75 | extern unsigned int console_irq; | 87 | extern unsigned int console_irq; |
76 | 88 | ||
89 | extern char vmhalt_cmd[]; | ||
90 | extern char vmpoff_cmd[]; | ||
91 | |||
77 | #define CONSOLE_IS_UNDEFINED (console_mode == 0) | 92 | #define CONSOLE_IS_UNDEFINED (console_mode == 0) |
78 | #define CONSOLE_IS_SCLP (console_mode == 1) | 93 | #define CONSOLE_IS_SCLP (console_mode == 1) |
79 | #define CONSOLE_IS_3215 (console_mode == 2) | 94 | #define CONSOLE_IS_3215 (console_mode == 2) |
@@ -141,13 +156,19 @@ struct ipl_parameter_block { | |||
141 | extern u32 ipl_flags; | 156 | extern u32 ipl_flags; |
142 | extern u16 ipl_devno; | 157 | extern u16 ipl_devno; |
143 | 158 | ||
144 | void do_reipl(void); | 159 | extern void do_reipl(void); |
160 | extern void ipl_save_parameters(void); | ||
145 | 161 | ||
146 | enum { | 162 | enum { |
147 | IPL_DEVNO_VALID = 1, | 163 | IPL_DEVNO_VALID = 1, |
148 | IPL_PARMBLOCK_VALID = 2, | 164 | IPL_PARMBLOCK_VALID = 2, |
165 | IPL_NSS_VALID = 4, | ||
149 | }; | 166 | }; |
150 | 167 | ||
168 | #define NSS_NAME_SIZE 8 | ||
169 | |||
170 | extern char kernel_nss_name[]; | ||
171 | |||
151 | #define IPL_PARMBLOCK_START ((struct ipl_parameter_block *) \ | 172 | #define IPL_PARMBLOCK_START ((struct ipl_parameter_block *) \ |
152 | IPL_PARMBLOCK_ORIGIN) | 173 | IPL_PARMBLOCK_ORIGIN) |
153 | #define IPL_PARMBLOCK_SIZE (IPL_PARMBLOCK_START->hdr.len) | 174 | #define IPL_PARMBLOCK_SIZE (IPL_PARMBLOCK_START->hdr.len) |
diff --git a/include/asm-s390/sfp-util.h b/include/asm-s390/sfp-util.h new file mode 100644 index 000000000000..8cabcd23d976 --- /dev/null +++ b/include/asm-s390/sfp-util.h | |||
@@ -0,0 +1,66 @@ | |||
1 | #include <linux/kernel.h> | ||
2 | #include <linux/sched.h> | ||
3 | #include <linux/types.h> | ||
4 | #include <asm/byteorder.h> | ||
5 | |||
6 | #define add_ssaaaa(sh, sl, ah, al, bh, bl) ({ \ | ||
7 | unsigned int __sh = (ah); \ | ||
8 | unsigned int __sl = (al); \ | ||
9 | asm volatile( \ | ||
10 | " alr %1,%3\n" \ | ||
11 | " brc 12,0f\n" \ | ||
12 | " ahi %0,1\n" \ | ||
13 | "0: alr %0,%2" \ | ||
14 | : "+&d" (__sh), "+d" (__sl) \ | ||
15 | : "d" (bh), "d" (bl) : "cc"); \ | ||
16 | (sh) = __sh; \ | ||
17 | (sl) = __sl; \ | ||
18 | }) | ||
19 | |||
20 | #define sub_ddmmss(sh, sl, ah, al, bh, bl) ({ \ | ||
21 | unsigned int __sh = (ah); \ | ||
22 | unsigned int __sl = (al); \ | ||
23 | asm volatile( \ | ||
24 | " slr %1,%3\n" \ | ||
25 | " brc 3,0f\n" \ | ||
26 | " ahi %0,-1\n" \ | ||
27 | "0: slr %0,%2" \ | ||
28 | : "+&d" (__sh), "+d" (__sl) \ | ||
29 | : "d" (bh), "d" (bl) : "cc"); \ | ||
30 | (sh) = __sh; \ | ||
31 | (sl) = __sl; \ | ||
32 | }) | ||
33 | |||
34 | /* a umul b = a mul b + (a>=2<<31) ? b<<32:0 + (b>=2<<31) ? a<<32:0 */ | ||
35 | #define umul_ppmm(wh, wl, u, v) ({ \ | ||
36 | unsigned int __wh = u; \ | ||
37 | unsigned int __wl = v; \ | ||
38 | asm volatile( \ | ||
39 | " ltr 1,%0\n" \ | ||
40 | " mr 0,%1\n" \ | ||
41 | " jnm 0f\n" \ | ||
42 | " alr 0,%1\n" \ | ||
43 | "0: ltr %1,%1\n" \ | ||
44 | " jnm 1f\n" \ | ||
45 | " alr 0,%0\n" \ | ||
46 | "1: lr %0,0\n" \ | ||
47 | " lr %1,1\n" \ | ||
48 | : "+d" (__wh), "+d" (__wl) \ | ||
49 | : : "0", "1", "cc"); \ | ||
50 | wh = __wh; \ | ||
51 | wl = __wl; \ | ||
52 | }) | ||
53 | |||
54 | #define udiv_qrnnd(q, r, n1, n0, d) \ | ||
55 | do { unsigned int __r; \ | ||
56 | (q) = __udiv_qrnnd (&__r, (n1), (n0), (d)); \ | ||
57 | (r) = __r; \ | ||
58 | } while (0) | ||
59 | extern unsigned long __udiv_qrnnd (unsigned int *, unsigned int, | ||
60 | unsigned int , unsigned int); | ||
61 | |||
62 | #define UDIV_NEEDS_NORMALIZATION 0 | ||
63 | |||
64 | #define abort() return 0 | ||
65 | |||
66 | #define __BYTE_ORDER __BIG_ENDIAN | ||
diff --git a/include/asm-s390/smp.h b/include/asm-s390/smp.h index 7097c96ed026..b957e4cda464 100644 --- a/include/asm-s390/smp.h +++ b/include/asm-s390/smp.h | |||
@@ -31,6 +31,10 @@ typedef struct | |||
31 | __u16 cpu; | 31 | __u16 cpu; |
32 | } sigp_info; | 32 | } sigp_info; |
33 | 33 | ||
34 | extern void machine_restart_smp(char *); | ||
35 | extern void machine_halt_smp(void); | ||
36 | extern void machine_power_off_smp(void); | ||
37 | |||
34 | extern void smp_setup_cpu_possible_map(void); | 38 | extern void smp_setup_cpu_possible_map(void); |
35 | extern int smp_call_function_on(void (*func) (void *info), void *info, | 39 | extern int smp_call_function_on(void (*func) (void *info), void *info, |
36 | int nonatomic, int wait, int cpu); | 40 | int nonatomic, int wait, int cpu); |
@@ -106,7 +110,7 @@ smp_call_function_on(void (*func) (void *info), void *info, | |||
106 | static inline void smp_send_stop(void) | 110 | static inline void smp_send_stop(void) |
107 | { | 111 | { |
108 | /* Disable all interrupts/machine checks */ | 112 | /* Disable all interrupts/machine checks */ |
109 | __load_psw_mask(PSW_KERNEL_BITS & ~PSW_MASK_MCHECK); | 113 | __load_psw_mask(psw_kernel_bits & ~PSW_MASK_MCHECK); |
110 | } | 114 | } |
111 | 115 | ||
112 | #define smp_cpu_not_running(cpu) 1 | 116 | #define smp_cpu_not_running(cpu) 1 |
diff --git a/include/asm-s390/system.h b/include/asm-s390/system.h index bd0b05ae87d2..bbe137c3ed69 100644 --- a/include/asm-s390/system.h +++ b/include/asm-s390/system.h | |||
@@ -373,8 +373,8 @@ __set_psw_mask(unsigned long mask) | |||
373 | __load_psw_mask(mask | (__raw_local_irq_stosm(0x00) & ~(-1UL >> 8))); | 373 | __load_psw_mask(mask | (__raw_local_irq_stosm(0x00) & ~(-1UL >> 8))); |
374 | } | 374 | } |
375 | 375 | ||
376 | #define local_mcck_enable() __set_psw_mask(PSW_KERNEL_BITS) | 376 | #define local_mcck_enable() __set_psw_mask(psw_kernel_bits) |
377 | #define local_mcck_disable() __set_psw_mask(PSW_KERNEL_BITS & ~PSW_MASK_MCHECK) | 377 | #define local_mcck_disable() __set_psw_mask(psw_kernel_bits & ~PSW_MASK_MCHECK) |
378 | 378 | ||
379 | #ifdef CONFIG_SMP | 379 | #ifdef CONFIG_SMP |
380 | 380 | ||
diff --git a/include/asm-s390/tape390.h b/include/asm-s390/tape390.h index f1d66ba0deef..884fba48f1ff 100644 --- a/include/asm-s390/tape390.h +++ b/include/asm-s390/tape390.h | |||
@@ -1,11 +1,11 @@ | |||
1 | /************************************************************************* | 1 | /************************************************************************* |
2 | * | 2 | * |
3 | * tape390.h | 3 | * tape390.h |
4 | * enables user programs to display messages on the tape device | 4 | * enables user programs to display messages and control encryption |
5 | * on s390 tape devices | ||
5 | * | 6 | * |
6 | * S390 and zSeries version | 7 | * Copyright IBM Corp. 2001,2006 |
7 | * Copyright (C) 2001 IBM Corporation | 8 | * Author(s): Michael Holzheu <holzheu@de.ibm.com> |
8 | * Author(s): Despina Papadopoulou <despina_p@de.ibm.com> | ||
9 | * | 9 | * |
10 | *************************************************************************/ | 10 | *************************************************************************/ |
11 | 11 | ||
@@ -36,4 +36,68 @@ typedef struct display_struct { | |||
36 | char message2[8]; | 36 | char message2[8]; |
37 | } display_struct; | 37 | } display_struct; |
38 | 38 | ||
39 | /* | ||
40 | * Tape encryption support | ||
41 | */ | ||
42 | |||
43 | struct tape390_crypt_info { | ||
44 | char capability; | ||
45 | char status; | ||
46 | char medium_status; | ||
47 | } __attribute__ ((packed)); | ||
48 | |||
49 | |||
50 | /* Macros for "capable" field */ | ||
51 | #define TAPE390_CRYPT_SUPPORTED_MASK 0x01 | ||
52 | #define TAPE390_CRYPT_SUPPORTED(x) \ | ||
53 | ((x.capability & TAPE390_CRYPT_SUPPORTED_MASK)) | ||
54 | |||
55 | /* Macros for "status" field */ | ||
56 | #define TAPE390_CRYPT_ON_MASK 0x01 | ||
57 | #define TAPE390_CRYPT_ON(x) (((x.status) & TAPE390_CRYPT_ON_MASK)) | ||
58 | |||
59 | /* Macros for "medium status" field */ | ||
60 | #define TAPE390_MEDIUM_LOADED_MASK 0x01 | ||
61 | #define TAPE390_MEDIUM_ENCRYPTED_MASK 0x02 | ||
62 | #define TAPE390_MEDIUM_ENCRYPTED(x) \ | ||
63 | (((x.medium_status) & TAPE390_MEDIUM_ENCRYPTED_MASK)) | ||
64 | #define TAPE390_MEDIUM_LOADED(x) \ | ||
65 | (((x.medium_status) & TAPE390_MEDIUM_LOADED_MASK)) | ||
66 | |||
67 | /* | ||
68 | * The TAPE390_CRYPT_SET ioctl is used to switch on/off encryption. | ||
69 | * The "encryption_capable" and "tape_status" fields are ignored for this ioctl! | ||
70 | */ | ||
71 | #define TAPE390_CRYPT_SET _IOW('d', 2, struct tape390_crypt_info) | ||
72 | |||
73 | /* | ||
74 | * The TAPE390_CRYPT_QUERY ioctl is used to query the encryption state. | ||
75 | */ | ||
76 | #define TAPE390_CRYPT_QUERY _IOR('d', 3, struct tape390_crypt_info) | ||
77 | |||
78 | /* Values for "kekl1/2_type" and "kekl1/2_type_on_tape" fields */ | ||
79 | #define TAPE390_KEKL_TYPE_NONE 0 | ||
80 | #define TAPE390_KEKL_TYPE_LABEL 1 | ||
81 | #define TAPE390_KEKL_TYPE_HASH 2 | ||
82 | |||
83 | struct tape390_kekl { | ||
84 | unsigned char type; | ||
85 | unsigned char type_on_tape; | ||
86 | char label[65]; | ||
87 | } __attribute__ ((packed)); | ||
88 | |||
89 | struct tape390_kekl_pair { | ||
90 | struct tape390_kekl kekl[2]; | ||
91 | } __attribute__ ((packed)); | ||
92 | |||
93 | /* | ||
94 | * The TAPE390_KEKL_SET ioctl is used to set Key Encrypting Key labels. | ||
95 | */ | ||
96 | #define TAPE390_KEKL_SET _IOW('d', 4, struct tape390_kekl_pair) | ||
97 | |||
98 | /* | ||
99 | * The TAPE390_KEKL_QUERY ioctl is used to query Key Encrypting Key labels. | ||
100 | */ | ||
101 | #define TAPE390_KEKL_QUERY _IOR('d', 5, struct tape390_kekl_pair) | ||
102 | |||
39 | #endif | 103 | #endif |
diff --git a/include/asm-s390/termbits.h b/include/asm-s390/termbits.h index eb3f8bfabf61..585c78a6e407 100644 --- a/include/asm-s390/termbits.h +++ b/include/asm-s390/termbits.h | |||
@@ -25,6 +25,17 @@ struct termios { | |||
25 | cc_t c_cc[NCCS]; /* control characters */ | 25 | cc_t c_cc[NCCS]; /* control characters */ |
26 | }; | 26 | }; |
27 | 27 | ||
28 | struct ktermios { | ||
29 | tcflag_t c_iflag; /* input mode flags */ | ||
30 | tcflag_t c_oflag; /* output mode flags */ | ||
31 | tcflag_t c_cflag; /* control mode flags */ | ||
32 | tcflag_t c_lflag; /* local mode flags */ | ||
33 | cc_t c_line; /* line discipline */ | ||
34 | cc_t c_cc[NCCS]; /* control characters */ | ||
35 | speed_t c_ispeed; /* input speed */ | ||
36 | speed_t c_ospeed; /* output speed */ | ||
37 | }; | ||
38 | |||
28 | /* c_cc characters */ | 39 | /* c_cc characters */ |
29 | #define VINTR 0 | 40 | #define VINTR 0 |
30 | #define VQUIT 1 | 41 | #define VQUIT 1 |
diff --git a/include/asm-s390/timer.h b/include/asm-s390/timer.h index 30e5cbe570f2..adb34860a543 100644 --- a/include/asm-s390/timer.h +++ b/include/asm-s390/timer.h | |||
@@ -45,6 +45,9 @@ extern void add_virt_timer_periodic(void *new); | |||
45 | extern int mod_virt_timer(struct vtimer_list *timer, __u64 expires); | 45 | extern int mod_virt_timer(struct vtimer_list *timer, __u64 expires); |
46 | extern int del_virt_timer(struct vtimer_list *timer); | 46 | extern int del_virt_timer(struct vtimer_list *timer); |
47 | 47 | ||
48 | extern void init_cpu_vtimer(void); | ||
49 | extern void vtime_init(void); | ||
50 | |||
48 | #endif /* __KERNEL__ */ | 51 | #endif /* __KERNEL__ */ |
49 | 52 | ||
50 | #endif /* _ASM_S390_TIMER_H */ | 53 | #endif /* _ASM_S390_TIMER_H */ |
diff --git a/include/asm-s390/timex.h b/include/asm-s390/timex.h index 4df4a41029a3..98229db24314 100644 --- a/include/asm-s390/timex.h +++ b/include/asm-s390/timex.h | |||
@@ -11,6 +11,41 @@ | |||
11 | #ifndef _ASM_S390_TIMEX_H | 11 | #ifndef _ASM_S390_TIMEX_H |
12 | #define _ASM_S390_TIMEX_H | 12 | #define _ASM_S390_TIMEX_H |
13 | 13 | ||
14 | /* Inline functions for clock register access. */ | ||
15 | static inline int set_clock(__u64 time) | ||
16 | { | ||
17 | int cc; | ||
18 | |||
19 | asm volatile( | ||
20 | " sck 0(%2)\n" | ||
21 | " ipm %0\n" | ||
22 | " srl %0,28\n" | ||
23 | : "=d" (cc) : "m" (time), "a" (&time) : "cc"); | ||
24 | return cc; | ||
25 | } | ||
26 | |||
27 | static inline int store_clock(__u64 *time) | ||
28 | { | ||
29 | int cc; | ||
30 | |||
31 | asm volatile( | ||
32 | " stck 0(%2)\n" | ||
33 | " ipm %0\n" | ||
34 | " srl %0,28\n" | ||
35 | : "=d" (cc), "=m" (*time) : "a" (time) : "cc"); | ||
36 | return cc; | ||
37 | } | ||
38 | |||
39 | static inline void set_clock_comparator(__u64 time) | ||
40 | { | ||
41 | asm volatile("sckc 0(%1)" : : "m" (time), "a" (&time)); | ||
42 | } | ||
43 | |||
44 | static inline void store_clock_comparator(__u64 *time) | ||
45 | { | ||
46 | asm volatile("stckc 0(%1)" : "=m" (*time) : "a" (time)); | ||
47 | } | ||
48 | |||
14 | #define CLOCK_TICK_RATE 1193180 /* Underlying HZ */ | 49 | #define CLOCK_TICK_RATE 1193180 /* Underlying HZ */ |
15 | 50 | ||
16 | typedef unsigned long long cycles_t; | 51 | typedef unsigned long long cycles_t; |
@@ -27,9 +62,24 @@ static inline unsigned long long get_clock (void) | |||
27 | return clk; | 62 | return clk; |
28 | } | 63 | } |
29 | 64 | ||
65 | static inline void get_clock_extended(void *dest) | ||
66 | { | ||
67 | typedef struct { unsigned long long clk[2]; } __clock_t; | ||
68 | |||
69 | #if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 2) | ||
70 | asm volatile("stcke %0" : "=Q" (*((__clock_t *)dest)) : : "cc"); | ||
71 | #else /* __GNUC__ */ | ||
72 | asm volatile("stcke 0(%1)" : "=m" (*((__clock_t *)dest)) | ||
73 | : "a" ((__clock_t *)dest) : "cc"); | ||
74 | #endif /* __GNUC__ */ | ||
75 | } | ||
76 | |||
30 | static inline cycles_t get_cycles(void) | 77 | static inline cycles_t get_cycles(void) |
31 | { | 78 | { |
32 | return (cycles_t) get_clock() >> 2; | 79 | return (cycles_t) get_clock() >> 2; |
33 | } | 80 | } |
34 | 81 | ||
82 | int get_sync_clock(unsigned long long *clock); | ||
83 | void init_cpu_timer(void); | ||
84 | |||
35 | #endif | 85 | #endif |
diff --git a/include/asm-s390/tlbflush.h b/include/asm-s390/tlbflush.h index fa4dc916a9bf..66793f55c8b2 100644 --- a/include/asm-s390/tlbflush.h +++ b/include/asm-s390/tlbflush.h | |||
@@ -3,6 +3,7 @@ | |||
3 | 3 | ||
4 | #include <linux/mm.h> | 4 | #include <linux/mm.h> |
5 | #include <asm/processor.h> | 5 | #include <asm/processor.h> |
6 | #include <asm/pgalloc.h> | ||
6 | 7 | ||
7 | /* | 8 | /* |
8 | * TLB flushing: | 9 | * TLB flushing: |
@@ -102,6 +103,14 @@ static inline void __flush_tlb_mm(struct mm_struct * mm) | |||
102 | if (unlikely(cpus_empty(mm->cpu_vm_mask))) | 103 | if (unlikely(cpus_empty(mm->cpu_vm_mask))) |
103 | return; | 104 | return; |
104 | if (MACHINE_HAS_IDTE) { | 105 | if (MACHINE_HAS_IDTE) { |
106 | pgd_t *shadow_pgd = get_shadow_pgd(mm->pgd); | ||
107 | |||
108 | if (shadow_pgd) { | ||
109 | asm volatile( | ||
110 | " .insn rrf,0xb98e0000,0,%0,%1,0" | ||
111 | : : "a" (2048), | ||
112 | "a" (__pa(shadow_pgd) & PAGE_MASK) : "cc" ); | ||
113 | } | ||
105 | asm volatile( | 114 | asm volatile( |
106 | " .insn rrf,0xb98e0000,0,%0,%1,0" | 115 | " .insn rrf,0xb98e0000,0,%0,%1,0" |
107 | : : "a" (2048), "a" (__pa(mm->pgd)&PAGE_MASK) : "cc"); | 116 | : : "a" (2048), "a" (__pa(mm->pgd)&PAGE_MASK) : "cc"); |
diff --git a/include/asm-s390/uaccess.h b/include/asm-s390/uaccess.h index 73ac4e82217b..0235970278f0 100644 --- a/include/asm-s390/uaccess.h +++ b/include/asm-s390/uaccess.h | |||
@@ -90,6 +90,8 @@ struct uaccess_ops { | |||
90 | extern struct uaccess_ops uaccess; | 90 | extern struct uaccess_ops uaccess; |
91 | extern struct uaccess_ops uaccess_std; | 91 | extern struct uaccess_ops uaccess_std; |
92 | extern struct uaccess_ops uaccess_mvcos; | 92 | extern struct uaccess_ops uaccess_mvcos; |
93 | extern struct uaccess_ops uaccess_mvcos_switch; | ||
94 | extern struct uaccess_ops uaccess_pt; | ||
93 | 95 | ||
94 | static inline int __put_user_fn(size_t size, void __user *ptr, void *x) | 96 | static inline int __put_user_fn(size_t size, void __user *ptr, void *x) |
95 | { | 97 | { |