Blame view

arch/s390/kernel/setup.c 28.7 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
  /*
   *  arch/s390/kernel/setup.c
   *
   *  S390 version
cd3b70f5d   Carsten Otte   [S390] virtualiza...
5
   *    Copyright (C) IBM Corp. 1999,2010
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6
7
8
9
10
11
12
13
14
15
   *    Author(s): Hartmut Penner (hp@de.ibm.com),
   *               Martin Schwidefsky (schwidefsky@de.ibm.com)
   *
   *  Derived from "arch/i386/kernel/setup.c"
   *    Copyright (C) 1995, Linus Torvalds
   */
  
  /*
   * This file handles the architecture-dependent parts of initialization
   */
3b6ed4ab4   Martin Schwidefsky   [S390] convert se...
16
17
  #define KMSG_COMPONENT "setup"
  #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
18
19
20
21
  #include <linux/errno.h>
  #include <linux/module.h>
  #include <linux/sched.h>
  #include <linux/kernel.h>
ff38df377   Tejun Heo   s390: Use HAVE_ME...
22
  #include <linux/memblock.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
23
24
25
26
  #include <linux/mm.h>
  #include <linux/stddef.h>
  #include <linux/unistd.h>
  #include <linux/ptrace.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
27
  #include <linux/user.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
28
29
30
  #include <linux/tty.h>
  #include <linux/ioport.h>
  #include <linux/delay.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
31
32
33
34
35
  #include <linux/init.h>
  #include <linux/initrd.h>
  #include <linux/bootmem.h>
  #include <linux/root_dev.h>
  #include <linux/console.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
36
  #include <linux/kernel_stat.h>
1e8e33832   Heiko Carstens   [PATCH] s390: exp...
37
  #include <linux/device.h>
585c3047a   Peter Oberparleiter   [S390] Add vmpani...
38
  #include <linux/notifier.h>
65912a84c   Heiko Carstens   [S390] initrd vs....
39
  #include <linux/pfn.h>
fe355b7f1   Hongjie Yang   [S390] boot from ...
40
  #include <linux/ctype.h>
2b67fc460   Heiko Carstens   [S390] Get rid of...
41
  #include <linux/reboot.h>
dbd70fb49   Heiko Carstens   [S390] cpu topolo...
42
  #include <linux/topology.h>
dfd9f7abc   Heiko Carstens   [S390] ftrace: ad...
43
  #include <linux/ftrace.h>
60a0c68df   Michael Holzheu   [S390] kdump back...
44
45
46
  #include <linux/kexec.h>
  #include <linux/crash_dump.h>
  #include <linux/memory.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
47

46b05d261   Michael Holzheu   [S390] New header...
48
  #include <asm/ipl.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
49
50
51
52
53
54
55
  #include <asm/uaccess.h>
  #include <asm/system.h>
  #include <asm/smp.h>
  #include <asm/mmu_context.h>
  #include <asm/cpcmd.h>
  #include <asm/lowcore.h>
  #include <asm/irq.h>
0b642ede4   Peter Oberparleiter   [PATCH] s390: def...
56
57
  #include <asm/page.h>
  #include <asm/ptrace.h>
cc13ad621   Heiko Carstens   [PATCH] s390: set...
58
  #include <asm/sections.h>
fe355b7f1   Hongjie Yang   [S390] boot from ...
59
  #include <asm/ebcdic.h>
c1821c2e9   Gerald Schaefer   [S390] noexec pro...
60
  #include <asm/compat.h>
faeba830b   Christian Borntraeger   s390: use virtio_...
61
  #include <asm/kvm_virtio.h>
60a0c68df   Michael Holzheu   [S390] kdump back...
62
  #include <asm/diag.h>
c1821c2e9   Gerald Schaefer   [S390] noexec pro...
63

b50511e41   Martin Schwidefsky   [S390] cleanup ps...
64
65
66
67
68
  long psw_kernel_bits	= PSW_DEFAULT_KEY | PSW_MASK_BASE | PSW_ASC_PRIMARY |
  			  PSW_MASK_EA | PSW_MASK_BA;
  long psw_user_bits	= PSW_MASK_DAT | PSW_MASK_IO | PSW_MASK_EXT |
  			  PSW_DEFAULT_KEY | PSW_MASK_BASE | PSW_MASK_MCHECK |
  			  PSW_MASK_PSTATE | PSW_ASC_HOME;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
69
70
  
  /*
d02765d1a   Gerald Schaefer   [S390] Make user-...
71
72
73
   * User copy operations.
   */
  struct uaccess_ops uaccess;
d4ee453bc   Martin Schwidefsky   [S390] Export uac...
74
  EXPORT_SYMBOL(uaccess);
d02765d1a   Gerald Schaefer   [S390] Make user-...
75
76
  
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
77
78
79
   * Machine setup..
   */
  unsigned int console_mode = 0;
1485c5c88   Heiko Carstens   [S390] move EXPOR...
80
  EXPORT_SYMBOL(console_mode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
81
  unsigned int console_devno = -1;
1485c5c88   Heiko Carstens   [S390] move EXPOR...
82
  EXPORT_SYMBOL(console_devno);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
83
  unsigned int console_irq = -1;
1485c5c88   Heiko Carstens   [S390] move EXPOR...
84
  EXPORT_SYMBOL(console_irq);
cf8ba7a95   Martin Schwidefsky   [S390] add hardwa...
85
86
  unsigned long elf_hwcap = 0;
  char elf_platform[ELF_PLATFORM_SIZE];
36a2bd425   Heiko Carstens   [S390] Cleanup me...
87

23d174217   Heiko Carstens   [S390] Move memor...
88
  struct mem_chunk __initdata memory_chunk[MEMORY_CHUNKS];
23d75d9ca   Heiko Carstens   [S390] fix "mem="...
89
90
91
  
  int __initdata memory_end_set;
  unsigned long __initdata memory_end;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
92

14045ebf1   Martin Schwidefsky   [S390] add suppor...
93
94
95
96
97
98
99
100
  unsigned long VMALLOC_START;
  EXPORT_SYMBOL(VMALLOC_START);
  
  unsigned long VMALLOC_END;
  EXPORT_SYMBOL(VMALLOC_END);
  
  struct page *vmemmap;
  EXPORT_SYMBOL(vmemmap);
099b76513   Frank Munzert   [S390] Automatic ...
101
102
103
  /* An array with a pointer to the lowcore of every CPU. */
  struct _lowcore *lowcore_ptr[NR_CPUS];
  EXPORT_SYMBOL(lowcore_ptr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
104
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
105
106
107
108
109
110
   * This is set up by the setup-routine at boot-time
   * for S390 need to find out, what we have to setup
   * using address 0x10400 ...
   */
  
  #include <asm/setup.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
111
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
   * condev= and conmode= setup parameter.
   */
  
  static int __init condev_setup(char *str)
  {
  	int vdev;
  
  	vdev = simple_strtoul(str, &str, 0);
  	if (vdev >= 0 && vdev < 65536) {
  		console_devno = vdev;
  		console_irq = -1;
  	}
  	return 1;
  }
  
  __setup("condev=", condev_setup);
637952ca6   Hendrik Brueckner   [S390] set prefer...
128
129
  static void __init set_preferred_console(void)
  {
c4de0c1a1   Hendrik Brueckner   [S390] kvm: use c...
130
  	if (MACHINE_IS_KVM)
637952ca6   Hendrik Brueckner   [S390] set prefer...
131
  		add_preferred_console("hvc", 0, NULL);
c4de0c1a1   Hendrik Brueckner   [S390] kvm: use c...
132
  	else if (CONSOLE_IS_3215 || CONSOLE_IS_SCLP)
637952ca6   Hendrik Brueckner   [S390] set prefer...
133
  		add_preferred_console("ttyS", 0, NULL);
c4de0c1a1   Hendrik Brueckner   [S390] kvm: use c...
134
  	else if (CONSOLE_IS_3270)
637952ca6   Hendrik Brueckner   [S390] set prefer...
135
136
  		add_preferred_console("tty3270", 0, NULL);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
137
138
  static int __init conmode_setup(char *str)
  {
8c0933eeb   Peter Oberparleiter   [S390] console: a...
139
  #if defined(CONFIG_SCLP_CONSOLE) || defined(CONFIG_SCLP_VT220_CONSOLE)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
140
141
142
143
144
145
146
147
148
149
150
  	if (strncmp(str, "hwc", 4) == 0 || strncmp(str, "sclp", 5) == 0)
                  SET_CONSOLE_SCLP;
  #endif
  #if defined(CONFIG_TN3215_CONSOLE)
  	if (strncmp(str, "3215", 5) == 0)
  		SET_CONSOLE_3215;
  #endif
  #if defined(CONFIG_TN3270_CONSOLE)
  	if (strncmp(str, "3270", 5) == 0)
  		SET_CONSOLE_3270;
  #endif
637952ca6   Hendrik Brueckner   [S390] set prefer...
151
  	set_preferred_console();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
152
153
154
155
156
157
158
159
160
161
162
          return 1;
  }
  
  __setup("conmode=", conmode_setup);
  
  static void __init conmode_default(void)
  {
  	char query_buffer[1024];
  	char *ptr;
  
          if (MACHINE_IS_VM) {
740b5706b   Heiko Carstens   [S390] cpcmd <-> ...
163
  		cpcmd("QUERY CONSOLE", query_buffer, 1024, NULL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
164
165
166
  		console_devno = simple_strtoul(query_buffer + 5, NULL, 16);
  		ptr = strstr(query_buffer, "SUBCHANNEL =");
  		console_irq = simple_strtoul(ptr + 13, NULL, 16);
740b5706b   Heiko Carstens   [S390] cpcmd <-> ...
167
  		cpcmd("QUERY TERM", query_buffer, 1024, NULL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
168
169
170
171
172
173
174
175
  		ptr = strstr(query_buffer, "CONMODE");
  		/*
  		 * Set the conmode to 3215 so that the device recognition 
  		 * will set the cu_type of the console to 3215. If the
  		 * conmode is 3270 and we don't set it back then both
  		 * 3215 and the 3270 driver will try to access the console
  		 * device (3215 as console and 3270 as normal tty).
  		 */
740b5706b   Heiko Carstens   [S390] cpcmd <-> ...
176
  		cpcmd("TERM CONMODE 3215", NULL, 0, NULL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
177
  		if (ptr == NULL) {
8c0933eeb   Peter Oberparleiter   [S390] console: a...
178
  #if defined(CONFIG_SCLP_CONSOLE) || defined(CONFIG_SCLP_VT220_CONSOLE)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
179
180
181
182
183
184
185
186
187
  			SET_CONSOLE_SCLP;
  #endif
  			return;
  		}
  		if (strncmp(ptr + 8, "3270", 4) == 0) {
  #if defined(CONFIG_TN3270_CONSOLE)
  			SET_CONSOLE_3270;
  #elif defined(CONFIG_TN3215_CONSOLE)
  			SET_CONSOLE_3215;
8c0933eeb   Peter Oberparleiter   [S390] console: a...
188
  #elif defined(CONFIG_SCLP_CONSOLE) || defined(CONFIG_SCLP_VT220_CONSOLE)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
189
190
191
192
193
194
195
  			SET_CONSOLE_SCLP;
  #endif
  		} else if (strncmp(ptr + 8, "3215", 4) == 0) {
  #if defined(CONFIG_TN3215_CONSOLE)
  			SET_CONSOLE_3215;
  #elif defined(CONFIG_TN3270_CONSOLE)
  			SET_CONSOLE_3270;
8c0933eeb   Peter Oberparleiter   [S390] console: a...
196
  #elif defined(CONFIG_SCLP_CONSOLE) || defined(CONFIG_SCLP_VT220_CONSOLE)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
197
198
199
  			SET_CONSOLE_SCLP;
  #endif
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
200
  	} else {
8c0933eeb   Peter Oberparleiter   [S390] console: a...
201
  #if defined(CONFIG_SCLP_CONSOLE) || defined(CONFIG_SCLP_VT220_CONSOLE)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
202
203
204
205
  		SET_CONSOLE_SCLP;
  #endif
  	}
  }
59f2e69d0   Michael Holzheu   [S390] zfcpdump: ...
206
  #ifdef CONFIG_ZFCPDUMP
411ed3225   Michael Holzheu   [S390] zfcpdump s...
207
208
  static void __init setup_zfcpdump(unsigned int console_devno)
  {
a0443fbb4   Hendrik Brueckner   [S390] Extra Kern...
209
  	static char str[41];
411ed3225   Michael Holzheu   [S390] zfcpdump s...
210
211
212
  
  	if (ipl_info.type != IPL_TYPE_FCP_DUMP)
  		return;
3f25dc4fc   Michael Holzheu   [S390] zfcpdump: ...
213
214
  	if (OLDMEM_BASE)
  		return;
411ed3225   Michael Holzheu   [S390] zfcpdump s...
215
  	if (console_devno != -1)
a0443fbb4   Hendrik Brueckner   [S390] Extra Kern...
216
  		sprintf(str, " cio_ignore=all,!0.0.%04x,!0.0.%04x",
411ed3225   Michael Holzheu   [S390] zfcpdump s...
217
218
  			ipl_info.data.fcp.dev_id.devno, console_devno);
  	else
a0443fbb4   Hendrik Brueckner   [S390] Extra Kern...
219
  		sprintf(str, " cio_ignore=all,!0.0.%04x",
411ed3225   Michael Holzheu   [S390] zfcpdump s...
220
  			ipl_info.data.fcp.dev_id.devno);
a0443fbb4   Hendrik Brueckner   [S390] Extra Kern...
221
  	strcat(boot_command_line, str);
411ed3225   Michael Holzheu   [S390] zfcpdump s...
222
223
224
225
226
  	console_loglevel = 2;
  }
  #else
  static inline void setup_zfcpdump(unsigned int console_devno) {}
  #endif /* CONFIG_ZFCPDUMP */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
227
228
229
230
231
232
233
   /*
   * Reboot, halt and power_off stubs. They just call _machine_restart,
   * _machine_halt or _machine_power_off. 
   */
  
  void machine_restart(char *command)
  {
7aa8dac7a   Christian Borntraeger   [S390] magic sysr...
234
  	if ((!in_interrupt() && !in_atomic()) || oops_in_progress)
06fa46a2f   Martin Schwidefsky   [S390] console_un...
235
236
237
238
239
  		/*
  		 * Only unblank the console if we are called in enabled
  		 * context or a bust_spinlocks cleared the way for us.
  		 */
  		console_unblank();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
240
241
  	_machine_restart(command);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
242
243
  void machine_halt(void)
  {
06fa46a2f   Martin Schwidefsky   [S390] console_un...
244
245
246
247
248
249
  	if (!in_interrupt() || oops_in_progress)
  		/*
  		 * Only unblank the console if we are called in enabled
  		 * context or a bust_spinlocks cleared the way for us.
  		 */
  		console_unblank();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
250
251
  	_machine_halt();
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
252
253
  void machine_power_off(void)
  {
06fa46a2f   Martin Schwidefsky   [S390] console_un...
254
255
256
257
258
259
  	if (!in_interrupt() || oops_in_progress)
  		/*
  		 * Only unblank the console if we are called in enabled
  		 * context or a bust_spinlocks cleared the way for us.
  		 */
  		console_unblank();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
260
261
  	_machine_power_off();
  }
53df751cc   Martin Schwidefsky   [PATCH] s390: add...
262
263
264
265
  /*
   * Dummy power off function.
   */
  void (*pm_power_off)(void) = machine_power_off;
596852967   Heiko Carstens   [PATCH] s390: ear...
266
267
268
  static int __init early_parse_mem(char *p)
  {
  	memory_end = memparse(p, &p);
23d75d9ca   Heiko Carstens   [S390] fix "mem="...
269
  	memory_end_set = 1;
596852967   Heiko Carstens   [PATCH] s390: ear...
270
271
272
  	return 0;
  }
  early_param("mem", early_parse_mem);
14045ebf1   Martin Schwidefsky   [S390] add suppor...
273
274
275
276
277
278
279
280
  static int __init parse_vmalloc(char *arg)
  {
  	if (!arg)
  		return -EINVAL;
  	VMALLOC_END = (memparse(arg, &arg) + PAGE_SIZE - 1) & PAGE_MASK;
  	return 0;
  }
  early_param("vmalloc", parse_vmalloc);
b11b53342   Martin Schwidefsky   [S390] Improve ad...
281
282
  unsigned int user_mode = HOME_SPACE_MODE;
  EXPORT_SYMBOL_GPL(user_mode);
c1821c2e9   Gerald Schaefer   [S390] noexec pro...
283

b50511e41   Martin Schwidefsky   [S390] cleanup ps...
284
  static int set_amode_primary(void)
c1821c2e9   Gerald Schaefer   [S390] noexec pro...
285
  {
b50511e41   Martin Schwidefsky   [S390] cleanup ps...
286
287
  	psw_kernel_bits = (psw_kernel_bits & ~PSW_MASK_ASC) | PSW_ASC_HOME;
  	psw_user_bits = (psw_user_bits & ~PSW_MASK_ASC) | PSW_ASC_PRIMARY;
c1821c2e9   Gerald Schaefer   [S390] noexec pro...
288
  #ifdef CONFIG_COMPAT
b50511e41   Martin Schwidefsky   [S390] cleanup ps...
289
290
  	psw32_user_bits =
  		(psw32_user_bits & ~PSW32_MASK_ASC) | PSW32_ASC_PRIMARY;
c1821c2e9   Gerald Schaefer   [S390] noexec pro...
291
  #endif
c1821c2e9   Gerald Schaefer   [S390] noexec pro...
292
293
  
  	if (MACHINE_HAS_MVCOS) {
c1821c2e9   Gerald Schaefer   [S390] noexec pro...
294
  		memcpy(&uaccess, &uaccess_mvcos_switch, sizeof(uaccess));
3b6ed4ab4   Martin Schwidefsky   [S390] convert se...
295
  		return 1;
c1821c2e9   Gerald Schaefer   [S390] noexec pro...
296
  	} else {
c1821c2e9   Gerald Schaefer   [S390] noexec pro...
297
  		memcpy(&uaccess, &uaccess_pt, sizeof(uaccess));
3b6ed4ab4   Martin Schwidefsky   [S390] convert se...
298
  		return 0;
c1821c2e9   Gerald Schaefer   [S390] noexec pro...
299
300
301
302
303
304
305
306
  	}
  }
  
  /*
   * Switch kernel/user addressing modes?
   */
  static int __init early_parse_switch_amode(char *p)
  {
043d07084   Martin Schwidefsky   [S390] Remove dat...
307
  	user_mode = PRIMARY_SPACE_MODE;
c1821c2e9   Gerald Schaefer   [S390] noexec pro...
308
309
310
  	return 0;
  }
  early_param("switch_amode", early_parse_switch_amode);
b11b53342   Martin Schwidefsky   [S390] Improve ad...
311
  static int __init early_parse_user_mode(char *p)
c1821c2e9   Gerald Schaefer   [S390] noexec pro...
312
  {
b11b53342   Martin Schwidefsky   [S390] Improve ad...
313
314
  	if (p && strcmp(p, "primary") == 0)
  		user_mode = PRIMARY_SPACE_MODE;
b11b53342   Martin Schwidefsky   [S390] Improve ad...
315
316
317
318
  	else if (!p || strcmp(p, "home") == 0)
  		user_mode = HOME_SPACE_MODE;
  	else
  		return 1;
3b6ed4ab4   Martin Schwidefsky   [S390] convert se...
319
  	return 0;
c1821c2e9   Gerald Schaefer   [S390] noexec pro...
320
  }
b11b53342   Martin Schwidefsky   [S390] Improve ad...
321
  early_param("user_mode", early_parse_user_mode);
c1821c2e9   Gerald Schaefer   [S390] noexec pro...
322

c1821c2e9   Gerald Schaefer   [S390] noexec pro...
323
324
  static void setup_addressing_mode(void)
  {
043d07084   Martin Schwidefsky   [S390] Remove dat...
325
  	if (user_mode == PRIMARY_SPACE_MODE) {
b50511e41   Martin Schwidefsky   [S390] cleanup ps...
326
  		if (set_amode_primary())
3b6ed4ab4   Martin Schwidefsky   [S390] convert se...
327
328
329
330
331
332
333
  			pr_info("Address spaces switched, "
  				"mvcos available
  ");
  		else
  			pr_info("Address spaces switched, "
  				"mvcos not available
  ");
c1821c2e9   Gerald Schaefer   [S390] noexec pro...
334
335
  	}
  }
c9e373535   Heiko Carstens   [PATCH] s390: fix...
336
337
338
339
  static void __init
  setup_lowcore(void)
  {
  	struct _lowcore *lc;
c9e373535   Heiko Carstens   [PATCH] s390: fix...
340
341
342
343
  
  	/*
  	 * Setup lowcore for boot cpu
  	 */
cbb870c82   Heiko Carstens   [S390] Cleanup st...
344
  	BUILD_BUG_ON(sizeof(struct _lowcore) != LC_PAGES * 4096);
a08786568   Heiko Carstens   [S390] smp: fix l...
345
  	lc = __alloc_bootmem_low(LC_PAGES * PAGE_SIZE, LC_PAGES * PAGE_SIZE, 0);
b50511e41   Martin Schwidefsky   [S390] cleanup ps...
346
  	lc->restart_psw.mask = psw_kernel_bits;
c9e373535   Heiko Carstens   [PATCH] s390: fix...
347
  	lc->restart_psw.addr =
7dd6b3343   Michael Holzheu   [S390] Add PSW re...
348
  		PSW_ADDR_AMODE | (unsigned long) psw_restart_int_handler;
b50511e41   Martin Schwidefsky   [S390] cleanup ps...
349
350
  	lc->external_new_psw.mask = psw_kernel_bits |
  		PSW_MASK_DAT | PSW_MASK_MCHECK;
c9e373535   Heiko Carstens   [PATCH] s390: fix...
351
352
  	lc->external_new_psw.addr =
  		PSW_ADDR_AMODE | (unsigned long) ext_int_handler;
b50511e41   Martin Schwidefsky   [S390] cleanup ps...
353
354
  	lc->svc_new_psw.mask = psw_kernel_bits |
  		PSW_MASK_DAT | PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK;
c9e373535   Heiko Carstens   [PATCH] s390: fix...
355
  	lc->svc_new_psw.addr = PSW_ADDR_AMODE | (unsigned long) system_call;
b50511e41   Martin Schwidefsky   [S390] cleanup ps...
356
357
  	lc->program_new_psw.mask = psw_kernel_bits |
  		PSW_MASK_DAT | PSW_MASK_MCHECK;
c9e373535   Heiko Carstens   [PATCH] s390: fix...
358
  	lc->program_new_psw.addr =
b50511e41   Martin Schwidefsky   [S390] cleanup ps...
359
360
  		PSW_ADDR_AMODE | (unsigned long) pgm_check_handler;
  	lc->mcck_new_psw.mask = psw_kernel_bits;
c9e373535   Heiko Carstens   [PATCH] s390: fix...
361
362
  	lc->mcck_new_psw.addr =
  		PSW_ADDR_AMODE | (unsigned long) mcck_int_handler;
b50511e41   Martin Schwidefsky   [S390] cleanup ps...
363
364
  	lc->io_new_psw.mask = psw_kernel_bits |
  		PSW_MASK_DAT | PSW_MASK_MCHECK;
c9e373535   Heiko Carstens   [PATCH] s390: fix...
365
  	lc->io_new_psw.addr = PSW_ADDR_AMODE | (unsigned long) io_int_handler;
5a62b1921   Heiko Carstens   [S390] Convert s3...
366
  	lc->clock_comparator = -1ULL;
c9e373535   Heiko Carstens   [PATCH] s390: fix...
367
368
369
  	lc->kernel_stack = ((unsigned long) &init_thread_union) + THREAD_SIZE;
  	lc->async_stack = (unsigned long)
  		__alloc_bootmem(ASYNC_SIZE, ASYNC_SIZE, 0) + ASYNC_SIZE;
c9e373535   Heiko Carstens   [PATCH] s390: fix...
370
371
  	lc->panic_stack = (unsigned long)
  		__alloc_bootmem(PAGE_SIZE, PAGE_SIZE, 0) + PAGE_SIZE;
c9e373535   Heiko Carstens   [PATCH] s390: fix...
372
373
  	lc->current_task = (unsigned long) init_thread_union.thread_info.task;
  	lc->thread_info = (unsigned long) &init_thread_union;
25097bf15   Christian Ehrhardt   [S390] s390: move...
374
  	lc->machine_flags = S390_lowcore.machine_flags;
14375bc4e   Martin Schwidefsky   [S390] cleanup fa...
375
376
377
  	lc->stfl_fac_list = S390_lowcore.stfl_fac_list;
  	memcpy(lc->stfle_fac_list, S390_lowcore.stfle_fac_list,
  	       MAX_FACILITY_BIT/8);
347a8dc3b   Martin Schwidefsky   [PATCH] s390: cle...
378
  #ifndef CONFIG_64BIT
77fa22450   Heiko Carstens   [PATCH] s390: imp...
379
380
  	if (MACHINE_HAS_IEEE) {
  		lc->extended_save_area_addr = (__u32)
a08786568   Heiko Carstens   [S390] smp: fix l...
381
  			__alloc_bootmem_low(PAGE_SIZE, PAGE_SIZE, 0);
77fa22450   Heiko Carstens   [PATCH] s390: imp...
382
  		/* enable extended save area */
c4972f331   Heiko Carstens   [S390] IRQs too e...
383
  		__ctl_set_bit(14, 29);
77fa22450   Heiko Carstens   [PATCH] s390: imp...
384
  	}
c742b31c0   Martin Schwidefsky   [PATCH] fast vdso...
385
386
  #else
  	lc->vdso_per_cpu_data = (unsigned long) &lc->paste[0];
77fa22450   Heiko Carstens   [PATCH] s390: imp...
387
  #endif
ab96e798c   Martin Schwidefsky   [S390] boot cputi...
388
389
390
391
392
393
394
395
  	lc->sync_enter_timer = S390_lowcore.sync_enter_timer;
  	lc->async_enter_timer = S390_lowcore.async_enter_timer;
  	lc->exit_timer = S390_lowcore.exit_timer;
  	lc->user_timer = S390_lowcore.user_timer;
  	lc->system_timer = S390_lowcore.system_timer;
  	lc->steal_timer = S390_lowcore.steal_timer;
  	lc->last_update_timer = S390_lowcore.last_update_timer;
  	lc->last_update_clock = S390_lowcore.last_update_clock;
dfd9f7abc   Heiko Carstens   [S390] ftrace: ad...
396
  	lc->ftrace_func = S390_lowcore.ftrace_func;
c9e373535   Heiko Carstens   [PATCH] s390: fix...
397
  	set_prefix((u32)(unsigned long) lc);
099b76513   Frank Munzert   [S390] Automatic ...
398
  	lowcore_ptr[0] = lc;
c9e373535   Heiko Carstens   [PATCH] s390: fix...
399
  }
71189284e   Heiko Carstens   [S390] setup: sim...
400
401
402
403
404
405
406
407
408
  static struct resource code_resource = {
  	.name  = "Kernel code",
  	.flags = IORESOURCE_BUSY | IORESOURCE_MEM,
  };
  
  static struct resource data_resource = {
  	.name = "Kernel data",
  	.flags = IORESOURCE_BUSY | IORESOURCE_MEM,
  };
4cc69531f   Heiko Carstens   [S390] setup: reg...
409
410
411
412
  static struct resource bss_resource = {
  	.name = "Kernel bss",
  	.flags = IORESOURCE_BUSY | IORESOURCE_MEM,
  };
71189284e   Heiko Carstens   [S390] setup: sim...
413
414
415
  static struct resource __initdata *standard_resources[] = {
  	&code_resource,
  	&data_resource,
4cc69531f   Heiko Carstens   [S390] setup: reg...
416
  	&bss_resource,
71189284e   Heiko Carstens   [S390] setup: sim...
417
418
419
  };
  
  static void __init setup_resources(void)
c9e373535   Heiko Carstens   [PATCH] s390: fix...
420
  {
71189284e   Heiko Carstens   [S390] setup: sim...
421
422
  	struct resource *res, *std_res, *sub_res;
  	int i, j;
c9e373535   Heiko Carstens   [PATCH] s390: fix...
423

cc13ad621   Heiko Carstens   [PATCH] s390: set...
424
425
426
427
  	code_resource.start = (unsigned long) &_text;
  	code_resource.end = (unsigned long) &_etext - 1;
  	data_resource.start = (unsigned long) &_etext;
  	data_resource.end = (unsigned long) &_edata - 1;
4cc69531f   Heiko Carstens   [S390] setup: reg...
428
429
  	bss_resource.start = (unsigned long) &__bss_start;
  	bss_resource.end = (unsigned long) &__bss_stop - 1;
cc13ad621   Heiko Carstens   [PATCH] s390: set...
430

9f4b0ba81   Heiko Carstens   [S390] Get rid of...
431
432
433
  	for (i = 0; i < MEMORY_CHUNKS; i++) {
  		if (!memory_chunk[i].size)
  			continue;
60a0c68df   Michael Holzheu   [S390] kdump back...
434
435
436
  		if (memory_chunk[i].type == CHUNK_OLDMEM ||
  		    memory_chunk[i].type == CHUNK_CRASHK)
  			continue;
71189284e   Heiko Carstens   [S390] setup: sim...
437
  		res = alloc_bootmem_low(sizeof(*res));
c9e373535   Heiko Carstens   [PATCH] s390: fix...
438
439
440
  		res->flags = IORESOURCE_BUSY | IORESOURCE_MEM;
  		switch (memory_chunk[i].type) {
  		case CHUNK_READ_WRITE:
dab7a7b15   Michael Holzheu   [S390] Add archit...
441
  		case CHUNK_CRASHK:
c9e373535   Heiko Carstens   [PATCH] s390: fix...
442
443
444
445
446
447
448
449
450
451
  			res->name = "System RAM";
  			break;
  		case CHUNK_READ_ONLY:
  			res->name = "System ROM";
  			res->flags |= IORESOURCE_READONLY;
  			break;
  		default:
  			res->name = "reserved";
  		}
  		res->start = memory_chunk[i].addr;
71189284e   Heiko Carstens   [S390] setup: sim...
452
  		res->end = res->start + memory_chunk[i].size - 1;
c9e373535   Heiko Carstens   [PATCH] s390: fix...
453
  		request_resource(&iomem_resource, res);
fe355b7f1   Hongjie Yang   [S390] boot from ...
454

71189284e   Heiko Carstens   [S390] setup: sim...
455
456
457
458
459
460
461
462
463
464
465
466
467
468
  		for (j = 0; j < ARRAY_SIZE(standard_resources); j++) {
  			std_res = standard_resources[j];
  			if (std_res->start < res->start ||
  			    std_res->start > res->end)
  				continue;
  			if (std_res->end > res->end) {
  				sub_res = alloc_bootmem_low(sizeof(*sub_res));
  				*sub_res = *std_res;
  				sub_res->end = res->end;
  				std_res->start = res->end + 1;
  				request_resource(res, sub_res);
  			} else {
  				request_resource(res, std_res);
  			}
fe355b7f1   Hongjie Yang   [S390] boot from ...
469
  		}
c9e373535   Heiko Carstens   [PATCH] s390: fix...
470
471
  	}
  }
411ed3225   Michael Holzheu   [S390] zfcpdump s...
472
473
  unsigned long real_memory_size;
  EXPORT_SYMBOL_GPL(real_memory_size);
8b62bc964   Heiko Carstens   [S390] Memory det...
474
475
  static void __init setup_memory_end(void)
  {
14045ebf1   Martin Schwidefsky   [S390] add suppor...
476
  	unsigned long vmax, vmalloc_size, tmp;
8b62bc964   Heiko Carstens   [S390] Memory det...
477
  	int i;
60a0c68df   Michael Holzheu   [S390] kdump back...
478

59f2e69d0   Michael Holzheu   [S390] zfcpdump: ...
479
  #ifdef CONFIG_ZFCPDUMP
3f25dc4fc   Michael Holzheu   [S390] zfcpdump: ...
480
  	if (ipl_info.type == IPL_TYPE_FCP_DUMP && !OLDMEM_BASE) {
411ed3225   Michael Holzheu   [S390] zfcpdump s...
481
  		memory_end = ZFCPDUMP_HSA_SIZE;
23d75d9ca   Heiko Carstens   [S390] fix "mem="...
482
483
  		memory_end_set = 1;
  	}
411ed3225   Michael Holzheu   [S390] zfcpdump s...
484
  #endif
14045ebf1   Martin Schwidefsky   [S390] add suppor...
485
  	real_memory_size = 0;
8b62bc964   Heiko Carstens   [S390] Memory det...
486
  	memory_end &= PAGE_MASK;
9f4b0ba81   Heiko Carstens   [S390] Get rid of...
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
  	/*
  	 * Make sure all chunks are MAX_ORDER aligned so we don't need the
  	 * extra checks that HOLES_IN_ZONE would require.
  	 */
  	for (i = 0; i < MEMORY_CHUNKS; i++) {
  		unsigned long start, end;
  		struct mem_chunk *chunk;
  		unsigned long align;
  
  		chunk = &memory_chunk[i];
  		align = 1UL << (MAX_ORDER + PAGE_SHIFT - 1);
  		start = (chunk->addr + align - 1) & ~(align - 1);
  		end = (chunk->addr + chunk->size) & ~(align - 1);
  		if (start >= end)
  			memset(chunk, 0, sizeof(*chunk));
  		else {
  			chunk->addr = start;
  			chunk->size = end - start;
  		}
14045ebf1   Martin Schwidefsky   [S390] add suppor...
506
507
  		real_memory_size = max(real_memory_size,
  				       chunk->addr + chunk->size);
9f4b0ba81   Heiko Carstens   [S390] Get rid of...
508
  	}
14045ebf1   Martin Schwidefsky   [S390] add suppor...
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
  	/* Choose kernel address space layout: 2, 3, or 4 levels. */
  #ifdef CONFIG_64BIT
  	vmalloc_size = VMALLOC_END ?: 128UL << 30;
  	tmp = (memory_end ?: real_memory_size) / PAGE_SIZE;
  	tmp = tmp * (sizeof(struct page) + PAGE_SIZE) + vmalloc_size;
  	if (tmp <= (1UL << 42))
  		vmax = 1UL << 42;	/* 3-level kernel page table */
  	else
  		vmax = 1UL << 53;	/* 4-level kernel page table */
  #else
  	vmalloc_size = VMALLOC_END ?: 96UL << 20;
  	vmax = 1UL << 31;		/* 2-level kernel page table */
  #endif
  	/* vmalloc area is at the end of the kernel address space. */
  	VMALLOC_END = vmax;
  	VMALLOC_START = vmax - vmalloc_size;
  
  	/* Split remaining virtual space between 1:1 mapping & vmemmap array */
  	tmp = VMALLOC_START / (PAGE_SIZE + sizeof(struct page));
  	tmp = VMALLOC_START - tmp * sizeof(struct page);
  	tmp &= ~((vmax >> 11) - 1);	/* align to page table level */
  	tmp = min(tmp, 1UL << MAX_PHYSMEM_BITS);
  	vmemmap = (struct page *) tmp;
  
  	/* Take care that memory_end is set and <= vmemmap */
  	memory_end = min(memory_end ?: real_memory_size, tmp);
  
  	/* Fixup memory chunk array to fit into 0..memory_end */
8b62bc964   Heiko Carstens   [S390] Memory det...
537
538
  	for (i = 0; i < MEMORY_CHUNKS; i++) {
  		struct mem_chunk *chunk = &memory_chunk[i];
14045ebf1   Martin Schwidefsky   [S390] add suppor...
539
  		if (chunk->addr >= memory_end) {
8b62bc964   Heiko Carstens   [S390] Memory det...
540
541
542
  			memset(chunk, 0, sizeof(*chunk));
  			continue;
  		}
14045ebf1   Martin Schwidefsky   [S390] add suppor...
543
544
  		if (chunk->addr + chunk->size > memory_end)
  			chunk->size = memory_end - chunk->addr;
8b62bc964   Heiko Carstens   [S390] Memory det...
545
  	}
8b62bc964   Heiko Carstens   [S390] Memory det...
546
  }
7dd6b3343   Michael Holzheu   [S390] Add PSW re...
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
  void *restart_stack __attribute__((__section__(".data")));
  
  /*
   * Setup new PSW and allocate stack for PSW restart interrupt
   */
  static void __init setup_restart_psw(void)
  {
  	psw_t psw;
  
  	restart_stack = __alloc_bootmem(ASYNC_SIZE, ASYNC_SIZE, 0);
  	restart_stack += ASYNC_SIZE;
  
  	/*
  	 * Setup restart PSW for absolute zero lowcore. This is necesary
  	 * if PSW restart is done on an offline CPU that has lowcore zero
  	 */
b50511e41   Martin Schwidefsky   [S390] cleanup ps...
563
  	psw.mask = PSW_DEFAULT_KEY | PSW_MASK_BASE | PSW_MASK_EA | PSW_MASK_BA;
7dd6b3343   Michael Holzheu   [S390] Add PSW re...
564
565
566
  	psw.addr = PSW_ADDR_AMODE | (unsigned long) psw_restart_int_handler;
  	copy_to_absolute_zero(&S390_lowcore.restart_psw, &psw, sizeof(psw));
  }
d38593f93   Michael Holzheu   [S390] Export vmc...
567
568
569
570
571
572
573
574
  static void __init setup_vmcoreinfo(void)
  {
  #ifdef CONFIG_KEXEC
  	unsigned long ptr = paddr_vmcoreinfo_note();
  
  	copy_to_absolute_zero(&S390_lowcore.vmcore_info, &ptr, sizeof(ptr));
  #endif
  }
60a0c68df   Michael Holzheu   [S390] kdump back...
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
  #ifdef CONFIG_CRASH_DUMP
  
  /*
   * Find suitable location for crashkernel memory
   */
  static unsigned long __init find_crash_base(unsigned long crash_size,
  					    char **msg)
  {
  	unsigned long crash_base;
  	struct mem_chunk *chunk;
  	int i;
  
  	if (memory_chunk[0].size < crash_size) {
  		*msg = "first memory chunk must be at least crashkernel size";
  		return 0;
  	}
5f894cbb6   Michael Holzheu   [S390] kdump: Rep...
591
  	if (OLDMEM_BASE && crash_size == OLDMEM_SIZE)
60a0c68df   Michael Holzheu   [S390] kdump back...
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
  		return OLDMEM_BASE;
  
  	for (i = MEMORY_CHUNKS - 1; i >= 0; i--) {
  		chunk = &memory_chunk[i];
  		if (chunk->size == 0)
  			continue;
  		if (chunk->type != CHUNK_READ_WRITE)
  			continue;
  		if (chunk->size < crash_size)
  			continue;
  		crash_base = (chunk->addr + chunk->size) - crash_size;
  		if (crash_base < crash_size)
  			continue;
  		if (crash_base < ZFCPDUMP_HSA_SIZE_MAX)
  			continue;
  		if (crash_base < (unsigned long) INITRD_START + INITRD_SIZE)
  			continue;
  		return crash_base;
  	}
  	*msg = "no suitable area found";
  	return 0;
  }
  
  /*
   * Check if crash_base and crash_size is valid
   */
  static int __init verify_crash_base(unsigned long crash_base,
  				    unsigned long crash_size,
  				    char **msg)
  {
  	struct mem_chunk *chunk;
  	int i;
  
  	/*
  	 * Because we do the swap to zero, we must have at least 'crash_size'
  	 * bytes free space before crash_base
  	 */
  	if (crash_size > crash_base) {
  		*msg = "crashkernel offset must be greater than size";
  		return -EINVAL;
  	}
  
  	/* First memory chunk must be at least crash_size */
  	if (memory_chunk[0].size < crash_size) {
  		*msg = "first memory chunk must be at least crashkernel size";
  		return -EINVAL;
  	}
  	/* Check if we fit into the respective memory chunk */
  	for (i = 0; i < MEMORY_CHUNKS; i++) {
  		chunk = &memory_chunk[i];
  		if (chunk->size == 0)
  			continue;
  		if (crash_base < chunk->addr)
  			continue;
  		if (crash_base >= chunk->addr + chunk->size)
  			continue;
  		/* we have found the memory chunk */
  		if (crash_base + crash_size > chunk->addr + chunk->size) {
  			*msg = "selected memory chunk is too small for "
  				"crashkernel memory";
  			return -EINVAL;
  		}
  		return 0;
  	}
  	*msg = "invalid memory range specified";
  	return -EINVAL;
  }
  
  /*
   * Reserve kdump memory by creating a memory hole in the mem_chunk array
   */
  static void __init reserve_kdump_bootmem(unsigned long addr, unsigned long size,
  					 int type)
  {
60a0c68df   Michael Holzheu   [S390] kdump back...
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
  	create_mem_hole(memory_chunk, addr, size, type);
  }
  
  /*
   * When kdump is enabled, we have to ensure that no memory from
   * the area [0 - crashkernel memory size] and
   * [crashk_res.start - crashk_res.end] is set offline.
   */
  static int kdump_mem_notifier(struct notifier_block *nb,
  			      unsigned long action, void *data)
  {
  	struct memory_notify *arg = data;
  
  	if (arg->start_pfn < PFN_DOWN(resource_size(&crashk_res)))
  		return NOTIFY_BAD;
  	if (arg->start_pfn > PFN_DOWN(crashk_res.end))
  		return NOTIFY_OK;
  	if (arg->start_pfn + arg->nr_pages - 1 < PFN_DOWN(crashk_res.start))
  		return NOTIFY_OK;
  	return NOTIFY_BAD;
  }
  
  static struct notifier_block kdump_mem_nb = {
  	.notifier_call = kdump_mem_notifier,
  };
  
  #endif
  
  /*
   * Make sure that oldmem, where the dump is stored, is protected
   */
  static void reserve_oldmem(void)
  {
  #ifdef CONFIG_CRASH_DUMP
  	if (!OLDMEM_BASE)
  		return;
  
  	reserve_kdump_bootmem(OLDMEM_BASE, OLDMEM_SIZE, CHUNK_OLDMEM);
  	reserve_kdump_bootmem(OLDMEM_SIZE, memory_end - OLDMEM_SIZE,
  			      CHUNK_OLDMEM);
  	if (OLDMEM_BASE + OLDMEM_SIZE == real_memory_size)
  		saved_max_pfn = PFN_DOWN(OLDMEM_BASE) - 1;
  	else
  		saved_max_pfn = PFN_DOWN(real_memory_size) - 1;
  #endif
  }
  
  /*
   * Reserve memory for kdump kernel to be loaded with kexec
   */
  static void __init reserve_crashkernel(void)
  {
  #ifdef CONFIG_CRASH_DUMP
  	unsigned long long crash_base, crash_size;
  	char *msg;
  	int rc;
  
  	rc = parse_crashkernel(boot_command_line, memory_end, &crash_size,
  			       &crash_base);
  	if (rc || crash_size == 0)
  		return;
dab7a7b15   Michael Holzheu   [S390] Add archit...
727
728
  	crash_base = ALIGN(crash_base, KEXEC_CRASH_MEM_ALIGN);
  	crash_size = ALIGN(crash_size, KEXEC_CRASH_MEM_ALIGN);
60a0c68df   Michael Holzheu   [S390] kdump back...
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
  	if (register_memory_notifier(&kdump_mem_nb))
  		return;
  	if (!crash_base)
  		crash_base = find_crash_base(crash_size, &msg);
  	if (!crash_base) {
  		pr_info("crashkernel reservation failed: %s
  ", msg);
  		unregister_memory_notifier(&kdump_mem_nb);
  		return;
  	}
  	if (verify_crash_base(crash_base, crash_size, &msg)) {
  		pr_info("crashkernel reservation failed: %s
  ", msg);
  		unregister_memory_notifier(&kdump_mem_nb);
  		return;
  	}
  	if (!OLDMEM_BASE && MACHINE_IS_VM)
  		diag10_range(PFN_DOWN(crash_base), PFN_DOWN(crash_size));
  	crashk_res.start = crash_base;
  	crashk_res.end = crash_base + crash_size - 1;
  	insert_resource(&iomem_resource, &crashk_res);
dab7a7b15   Michael Holzheu   [S390] Add archit...
750
  	reserve_kdump_bootmem(crash_base, crash_size, CHUNK_CRASHK);
60a0c68df   Michael Holzheu   [S390] kdump back...
751
752
753
754
755
756
  	pr_info("Reserving %lluMB of memory at %lluMB "
  		"for crashkernel (System RAM: %luMB)
  ",
  		crash_size >> 20, crash_base >> 20, memory_end >> 20);
  #endif
  }
c9e373535   Heiko Carstens   [PATCH] s390: fix...
757
758
759
760
  static void __init
  setup_memory(void)
  {
          unsigned long bootmap_size;
fe355b7f1   Hongjie Yang   [S390] boot from ...
761
  	unsigned long start_pfn, end_pfn;
c9e373535   Heiko Carstens   [PATCH] s390: fix...
762
  	int i;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
763
764
765
766
767
  
  	/*
  	 * partially used pages are not usable - thus
  	 * we are rounding upwards:
  	 */
65912a84c   Heiko Carstens   [S390] initrd vs....
768
769
  	start_pfn = PFN_UP(__pa(&_end));
  	end_pfn = max_pfn = PFN_DOWN(memory_end);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
770

65912a84c   Heiko Carstens   [S390] initrd vs....
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
  #ifdef CONFIG_BLK_DEV_INITRD
  	/*
  	 * Move the initrd in case the bitmap of the bootmem allocater
  	 * would overwrite it.
  	 */
  
  	if (INITRD_START && INITRD_SIZE) {
  		unsigned long bmap_size;
  		unsigned long start;
  
  		bmap_size = bootmem_bootmap_pages(end_pfn - start_pfn + 1);
  		bmap_size = PFN_PHYS(bmap_size);
  
  		if (PFN_PHYS(start_pfn) + bmap_size > INITRD_START) {
  			start = PFN_PHYS(start_pfn) + bmap_size + PAGE_SIZE;
60a0c68df   Michael Holzheu   [S390] kdump back...
786
787
788
789
790
791
792
793
  #ifdef CONFIG_CRASH_DUMP
  			if (OLDMEM_BASE) {
  				/* Move initrd behind kdump oldmem */
  				if (start + INITRD_SIZE > OLDMEM_BASE &&
  				    start < OLDMEM_BASE + OLDMEM_SIZE)
  					start = OLDMEM_BASE + OLDMEM_SIZE;
  			}
  #endif
65912a84c   Heiko Carstens   [S390] initrd vs....
794
  			if (start + INITRD_SIZE > memory_end) {
3b6ed4ab4   Martin Schwidefsky   [S390] convert se...
795
796
  				pr_err("initrd extends beyond end of "
  				       "memory (0x%08lx > 0x%08lx) "
65912a84c   Heiko Carstens   [S390] initrd vs....
797
798
799
800
801
  				       "disabling initrd
  ",
  				       start + INITRD_SIZE, memory_end);
  				INITRD_START = INITRD_SIZE = 0;
  			} else {
3b6ed4ab4   Martin Schwidefsky   [S390] convert se...
802
803
804
805
  				pr_info("Moving initrd (0x%08lx -> "
  					"0x%08lx, size: %ld)
  ",
  					INITRD_START, start, INITRD_SIZE);
65912a84c   Heiko Carstens   [S390] initrd vs....
806
807
808
809
810
811
812
  				memmove((void *) start, (void *) INITRD_START,
  					INITRD_SIZE);
  				INITRD_START = start;
  			}
  		}
  	}
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
813
  	/*
7676bef9c   Heiko Carstens   [S390] Have s390 ...
814
  	 * Initialize the boot-time allocator
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
815
816
817
818
819
820
  	 */
  	bootmap_size = init_bootmem(start_pfn, end_pfn);
  
  	/*
  	 * Register RAM areas with the bootmem allocator.
  	 */
c9e373535   Heiko Carstens   [PATCH] s390: fix...
821

0b642ede4   Peter Oberparleiter   [PATCH] s390: def...
822
  	for (i = 0; i < MEMORY_CHUNKS && memory_chunk[i].size > 0; i++) {
39b742f95   Heiko Carstens   [S390] Use add_ac...
823
  		unsigned long start_chunk, end_chunk, pfn;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
824

dab7a7b15   Michael Holzheu   [S390] Add archit...
825
826
  		if (memory_chunk[i].type != CHUNK_READ_WRITE &&
  		    memory_chunk[i].type != CHUNK_CRASHK)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
827
  			continue;
39b742f95   Heiko Carstens   [S390] Use add_ac...
828
  		start_chunk = PFN_DOWN(memory_chunk[i].addr);
fb2e7c5e3   Gerald Schaefer   [S390] Fix range ...
829
  		end_chunk = start_chunk + PFN_DOWN(memory_chunk[i].size);
39b742f95   Heiko Carstens   [S390] Use add_ac...
830
831
832
  		end_chunk = min(end_chunk, end_pfn);
  		if (start_chunk >= end_chunk)
  			continue;
ff38df377   Tejun Heo   s390: Use HAVE_ME...
833
834
  		memblock_add_node(PFN_PHYS(start_chunk),
  				  PFN_PHYS(end_chunk - start_chunk), 0);
39b742f95   Heiko Carstens   [S390] Use add_ac...
835
  		pfn = max(start_chunk, start_pfn);
fb2e7c5e3   Gerald Schaefer   [S390] Fix range ...
836
  		for (; pfn < end_chunk; pfn++)
e2b8d7af0   Martin Schwidefsky   [S390] add suppor...
837
838
  			page_set_storage_key(PFN_PHYS(pfn),
  					     PAGE_DEFAULT_KEY, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
839
  	}
0b642ede4   Peter Oberparleiter   [PATCH] s390: def...
840
  	psw_set_key(PAGE_DEFAULT_KEY);
39b742f95   Heiko Carstens   [S390] Use add_ac...
841
  	free_bootmem_with_active_regions(0, max_pfn);
c9e373535   Heiko Carstens   [PATCH] s390: fix...
842
843
  
  	/*
615b04b30   Heiko Carstens   [S390] nss: Free ...
844
845
  	 * Reserve memory used for lowcore/command line/kernel image.
  	 */
72a7fe396   Bernhard Walle   Introduce flags f...
846
  	reserve_bootmem(0, (unsigned long)_ehead, BOOTMEM_DEFAULT);
615b04b30   Heiko Carstens   [S390] nss: Free ...
847
  	reserve_bootmem((unsigned long)_stext,
72a7fe396   Bernhard Walle   Introduce flags f...
848
849
  			PFN_PHYS(start_pfn) - (unsigned long)_stext,
  			BOOTMEM_DEFAULT);
615b04b30   Heiko Carstens   [S390] nss: Free ...
850
  	/*
c9e373535   Heiko Carstens   [PATCH] s390: fix...
851
852
853
854
855
  	 * Reserve the bootmem bitmap itself as well. We do this in two
  	 * steps (first step was init_bootmem()) because this catches
  	 * the (very unlikely) case of us accidentally initializing the
  	 * bootmem allocator with an invalid RAM area.
  	 */
72a7fe396   Bernhard Walle   Introduce flags f...
856
857
  	reserve_bootmem(start_pfn << PAGE_SHIFT, bootmap_size,
  			BOOTMEM_DEFAULT);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
858

60a0c68df   Michael Holzheu   [S390] kdump back...
859
860
861
862
863
864
865
866
867
  #ifdef CONFIG_CRASH_DUMP
  	if (crashk_res.start)
  		reserve_bootmem(crashk_res.start,
  				crashk_res.end - crashk_res.start + 1,
  				BOOTMEM_DEFAULT);
  	if (is_kdump_kernel())
  		reserve_bootmem(elfcorehdr_addr - OLDMEM_BASE,
  				PAGE_ALIGN(elfcorehdr_size), BOOTMEM_DEFAULT);
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
868
  #ifdef CONFIG_BLK_DEV_INITRD
65912a84c   Heiko Carstens   [S390] initrd vs....
869
  	if (INITRD_START && INITRD_SIZE) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
870
  		if (INITRD_START + INITRD_SIZE <= memory_end) {
72a7fe396   Bernhard Walle   Introduce flags f...
871
872
  			reserve_bootmem(INITRD_START, INITRD_SIZE,
  					BOOTMEM_DEFAULT);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
873
874
875
  			initrd_start = INITRD_START;
  			initrd_end = initrd_start + INITRD_SIZE;
  		} else {
3b6ed4ab4   Martin Schwidefsky   [S390] convert se...
876
877
878
879
  			pr_err("initrd extends beyond end of "
  			       "memory (0x%08lx > 0x%08lx) "
  			       "disabling initrd
  ",
c9e373535   Heiko Carstens   [PATCH] s390: fix...
880
881
  			       initrd_start + INITRD_SIZE, memory_end);
  			initrd_start = initrd_end = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
882
  		}
c9e373535   Heiko Carstens   [PATCH] s390: fix...
883
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
884
  #endif
c9e373535   Heiko Carstens   [PATCH] s390: fix...
885
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
886

cf8ba7a95   Martin Schwidefsky   [S390] add hardwa...
887
888
889
890
891
892
  /*
   * Setup hardware capabilities.
   */
  static void __init setup_hwcaps(void)
  {
  	static const int stfl_bits[6] = { 0, 2, 7, 17, 19, 21 };
94038a991   Martin Schwidefsky   [S390] More clean...
893
  	struct cpuid cpu_id;
cf8ba7a95   Martin Schwidefsky   [S390] add hardwa...
894
  	int i;
cf8ba7a95   Martin Schwidefsky   [S390] add hardwa...
895
896
897
898
899
900
901
902
903
904
  	/*
  	 * The store facility list bits numbers as found in the principles
  	 * of operation are numbered with bit 1UL<<31 as number 0 to
  	 * bit 1UL<<0 as number 31.
  	 *   Bit 0: instructions named N3, "backported" to esa-mode
  	 *   Bit 2: z/Architecture mode is active
  	 *   Bit 7: the store-facility-list-extended facility is installed
  	 *   Bit 17: the message-security assist is installed
  	 *   Bit 19: the long-displacement facility is installed
  	 *   Bit 21: the extended-immediate facility is installed
488253ce4   Andreas Krebbel   [S390] Add hwcap ...
905
906
  	 *   Bit 22: extended-translation facility 3 is installed
  	 *   Bit 30: extended-translation facility 3 enhancement facility
cf8ba7a95   Martin Schwidefsky   [S390] add hardwa...
907
908
909
  	 * These get translated to:
  	 *   HWCAP_S390_ESAN3 bit 0, HWCAP_S390_ZARCH bit 1,
  	 *   HWCAP_S390_STFLE bit 2, HWCAP_S390_MSA bit 3,
488253ce4   Andreas Krebbel   [S390] Add hwcap ...
910
911
  	 *   HWCAP_S390_LDISP bit 4, HWCAP_S390_EIMM bit 5 and
  	 *   HWCAP_S390_ETF3EH bit 8 (22 && 30).
cf8ba7a95   Martin Schwidefsky   [S390] add hardwa...
912
913
  	 */
  	for (i = 0; i < 6; i++)
14375bc4e   Martin Schwidefsky   [S390] cleanup fa...
914
  		if (test_facility(stfl_bits[i]))
cf8ba7a95   Martin Schwidefsky   [S390] add hardwa...
915
  			elf_hwcap |= 1UL << i;
14375bc4e   Martin Schwidefsky   [S390] cleanup fa...
916
  	if (test_facility(22) && test_facility(30))
ea2a4d3a3   Heiko Carstens   [S390] 64-bit reg...
917
  		elf_hwcap |= HWCAP_S390_ETF3EH;
488253ce4   Andreas Krebbel   [S390] Add hwcap ...
918

cf8ba7a95   Martin Schwidefsky   [S390] add hardwa...
919
920
921
922
923
924
  	/*
  	 * Check for additional facilities with store-facility-list-extended.
  	 * stfle stores doublewords (8 byte) with bit 1ULL<<63 as bit 0
  	 * and 1ULL<<0 as bit 63. Bits 0-31 contain the same information
  	 * as stored by stfl, bits 32-xxx contain additional facilities.
  	 * How many facility words are stored depends on the number of
25985edce   Lucas De Marchi   Fix common misspe...
925
  	 * doublewords passed to the instruction. The additional facilities
cf8ba7a95   Martin Schwidefsky   [S390] add hardwa...
926
  	 * are:
2ac3307f2   Christian Ehrhardt   [S390] fix dfp el...
927
928
  	 *   Bit 42: decimal floating point facility is installed
  	 *   Bit 44: perform floating point operation facility is installed
cf8ba7a95   Martin Schwidefsky   [S390] add hardwa...
929
  	 * translated to:
488253ce4   Andreas Krebbel   [S390] Add hwcap ...
930
  	 *   HWCAP_S390_DFP bit 6 (42 && 44).
cf8ba7a95   Martin Schwidefsky   [S390] add hardwa...
931
  	 */
14375bc4e   Martin Schwidefsky   [S390] cleanup fa...
932
933
  	if ((elf_hwcap & (1UL << 2)) && test_facility(42) && test_facility(44))
  		elf_hwcap |= HWCAP_S390_DFP;
cf8ba7a95   Martin Schwidefsky   [S390] add hardwa...
934

ea2a4d3a3   Heiko Carstens   [S390] 64-bit reg...
935
936
937
  	/*
  	 * Huge page support HWCAP_S390_HPAGE is bit 7.
  	 */
53492b1de   Gerald Schaefer   [S390] System z l...
938
  	if (MACHINE_HAS_HPAGE)
ea2a4d3a3   Heiko Carstens   [S390] 64-bit reg...
939
940
941
942
943
944
945
  		elf_hwcap |= HWCAP_S390_HPAGE;
  
  	/*
  	 * 64-bit register support for 31-bit processes
  	 * HWCAP_S390_HIGH_GPRS is bit 9.
  	 */
  	elf_hwcap |= HWCAP_S390_HIGH_GPRS;
53492b1de   Gerald Schaefer   [S390] System z l...
946

94038a991   Martin Schwidefsky   [S390] More clean...
947
948
  	get_cpu_id(&cpu_id);
  	switch (cpu_id.machine) {
cf8ba7a95   Martin Schwidefsky   [S390] add hardwa...
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
  	case 0x9672:
  #if !defined(CONFIG_64BIT)
  	default:	/* Use "g5" as default for 31 bit kernels. */
  #endif
  		strcpy(elf_platform, "g5");
  		break;
  	case 0x2064:
  	case 0x2066:
  #if defined(CONFIG_64BIT)
  	default:	/* Use "z900" as default for 64 bit kernels. */
  #endif
  		strcpy(elf_platform, "z900");
  		break;
  	case 0x2084:
  	case 0x2086:
  		strcpy(elf_platform, "z990");
  		break;
  	case 0x2094:
9fee8db22   Martin Schwidefsky   [S390] add new ma...
967
  	case 0x2096:
cf8ba7a95   Martin Schwidefsky   [S390] add hardwa...
968
969
  		strcpy(elf_platform, "z9-109");
  		break;
9fee8db22   Martin Schwidefsky   [S390] add new ma...
970
971
972
973
  	case 0x2097:
  	case 0x2098:
  		strcpy(elf_platform, "z10");
  		break;
c84b9051d   Heiko Carstens   [S390] Add z196 m...
974
  	case 0x2817:
3a81b1714   Heiko Carstens   [S390] Add suppor...
975
  	case 0x2818:
c84b9051d   Heiko Carstens   [S390] Add z196 m...
976
977
  		strcpy(elf_platform, "z196");
  		break;
cf8ba7a95   Martin Schwidefsky   [S390] add hardwa...
978
979
  	}
  }
c9e373535   Heiko Carstens   [PATCH] s390: fix...
980
981
982
983
  /*
   * Setup function called from init/main.c just after the banner
   * was printed.
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
984

c9e373535   Heiko Carstens   [PATCH] s390: fix...
985
986
987
  void __init
  setup_arch(char **cmdline_p)
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
988
          /*
c9e373535   Heiko Carstens   [PATCH] s390: fix...
989
           * print what head.S has found out about the machine
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
990
           */
347a8dc3b   Martin Schwidefsky   [PATCH] s390: cle...
991
  #ifndef CONFIG_64BIT
3b6ed4ab4   Martin Schwidefsky   [S390] convert se...
992
993
994
995
  	if (MACHINE_IS_VM)
  		pr_info("Linux is running as a z/VM "
  			"guest operating system in 31-bit mode
  ");
27d71602b   Martin Schwidefsky   [S390] add MACHIN...
996
  	else if (MACHINE_IS_LPAR)
3b6ed4ab4   Martin Schwidefsky   [S390] convert se...
997
998
999
1000
1001
1002
1003
1004
1005
1006
  		pr_info("Linux is running natively in 31-bit mode
  ");
  	if (MACHINE_HAS_IEEE)
  		pr_info("The hardware system has IEEE compatible "
  			"floating point units
  ");
  	else
  		pr_info("The hardware system has no IEEE compatible "
  			"floating point units
  ");
347a8dc3b   Martin Schwidefsky   [PATCH] s390: cle...
1007
  #else /* CONFIG_64BIT */
fa5877439   Carsten Otte   s390: KVM guest: ...
1008
  	if (MACHINE_IS_VM)
3b6ed4ab4   Martin Schwidefsky   [S390] convert se...
1009
1010
1011
  		pr_info("Linux is running as a z/VM "
  			"guest operating system in 64-bit mode
  ");
637952ca6   Hendrik Brueckner   [S390] set prefer...
1012
  	else if (MACHINE_IS_KVM)
3b6ed4ab4   Martin Schwidefsky   [S390] convert se...
1013
1014
  		pr_info("Linux is running under KVM in 64-bit mode
  ");
27d71602b   Martin Schwidefsky   [S390] add MACHIN...
1015
  	else if (MACHINE_IS_LPAR)
3b6ed4ab4   Martin Schwidefsky   [S390] convert se...
1016
1017
  		pr_info("Linux is running natively in 64-bit mode
  ");
347a8dc3b   Martin Schwidefsky   [PATCH] s390: cle...
1018
  #endif /* CONFIG_64BIT */
c9e373535   Heiko Carstens   [PATCH] s390: fix...
1019

a0443fbb4   Hendrik Brueckner   [S390] Extra Kern...
1020
1021
1022
  	/* Have one command line that is parsed and saved in /proc/cmdline */
  	/* boot_command_line has been already set up in early.c */
  	*cmdline_p = boot_command_line;
596852967   Heiko Carstens   [PATCH] s390: ear...
1023

c9e373535   Heiko Carstens   [PATCH] s390: fix...
1024
          ROOT_DEV = Root_RAM0;
596852967   Heiko Carstens   [PATCH] s390: ear...
1025
1026
1027
1028
1029
  
  	init_mm.start_code = PAGE_OFFSET;
  	init_mm.end_code = (unsigned long) &_etext;
  	init_mm.end_data = (unsigned long) &_edata;
  	init_mm.brk = (unsigned long) &_end;
6c2a9e6df   Gerald Schaefer   [S390] Use altern...
1030
1031
1032
1033
  	if (MACHINE_HAS_MVCOS)
  		memcpy(&uaccess, &uaccess_mvcos, sizeof(uaccess));
  	else
  		memcpy(&uaccess, &uaccess_std, sizeof(uaccess));
596852967   Heiko Carstens   [PATCH] s390: ear...
1034
  	parse_early_param();
99ca4e582   Michael Holzheu   [S390] kernel: Sh...
1035
  	setup_ipl();
8b62bc964   Heiko Carstens   [S390] Memory det...
1036
  	setup_memory_end();
c1821c2e9   Gerald Schaefer   [S390] noexec pro...
1037
  	setup_addressing_mode();
60a0c68df   Michael Holzheu   [S390] kdump back...
1038
1039
  	reserve_oldmem();
  	reserve_crashkernel();
c9e373535   Heiko Carstens   [PATCH] s390: fix...
1040
1041
  	setup_memory();
  	setup_resources();
d38593f93   Michael Holzheu   [S390] Export vmc...
1042
  	setup_vmcoreinfo();
7dd6b3343   Michael Holzheu   [S390] Add PSW re...
1043
  	setup_restart_psw();
c9e373535   Heiko Carstens   [PATCH] s390: fix...
1044
  	setup_lowcore();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1045
          cpu_init();
dbd70fb49   Heiko Carstens   [S390] cpu topolo...
1046
  	s390_init_cpu_topology();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1047
1048
  
  	/*
cf8ba7a95   Martin Schwidefsky   [S390] add hardwa...
1049
1050
1051
1052
1053
  	 * Setup capabilities (ELF_HWCAP & ELF_PLATFORM).
  	 */
  	setup_hwcaps();
  
  	/*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1054
1055
1056
1057
1058
1059
  	 * Create kernel page tables and switch to virtual addressing.
  	 */
          paging_init();
  
          /* Setup default console */
  	conmode_default();
637952ca6   Hendrik Brueckner   [S390] set prefer...
1060
  	set_preferred_console();
411ed3225   Michael Holzheu   [S390] zfcpdump s...
1061
1062
1063
  
  	/* Setup zfcpdump support */
  	setup_zfcpdump(console_devno);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1064
  }