Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/xtensa/kernel/setup.c
10817 views
1
/*
2
* arch/xtensa/kernel/setup.c
3
*
4
* This file is subject to the terms and conditions of the GNU General Public
5
* License. See the file "COPYING" in the main directory of this archive
6
* for more details.
7
*
8
* Copyright (C) 1995 Linus Torvalds
9
* Copyright (C) 2001 - 2005 Tensilica Inc.
10
*
11
* Chris Zankel <[email protected]>
12
* Joe Taylor <[email protected], [email protected]>
13
* Kevin Chea
14
* Marc Gauthier<[email protected]> <[email protected]>
15
*/
16
17
#include <linux/errno.h>
18
#include <linux/init.h>
19
#include <linux/mm.h>
20
#include <linux/proc_fs.h>
21
#include <linux/screen_info.h>
22
#include <linux/bootmem.h>
23
#include <linux/kernel.h>
24
25
#if defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_DUMMY_CONSOLE)
26
# include <linux/console.h>
27
#endif
28
29
#ifdef CONFIG_RTC
30
# include <linux/timex.h>
31
#endif
32
33
#ifdef CONFIG_PROC_FS
34
# include <linux/seq_file.h>
35
#endif
36
37
#include <asm/system.h>
38
#include <asm/bootparam.h>
39
#include <asm/pgtable.h>
40
#include <asm/processor.h>
41
#include <asm/timex.h>
42
#include <asm/platform.h>
43
#include <asm/page.h>
44
#include <asm/setup.h>
45
#include <asm/param.h>
46
47
#include <platform/hardware.h>
48
49
#if defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_DUMMY_CONSOLE)
50
struct screen_info screen_info = { 0, 24, 0, 0, 0, 80, 0, 0, 0, 24, 1, 16};
51
#endif
52
53
#ifdef CONFIG_BLK_DEV_FD
54
extern struct fd_ops no_fd_ops;
55
struct fd_ops *fd_ops;
56
#endif
57
58
extern struct rtc_ops no_rtc_ops;
59
struct rtc_ops *rtc_ops;
60
61
#ifdef CONFIG_BLK_DEV_INITRD
62
extern void *initrd_start;
63
extern void *initrd_end;
64
extern void *__initrd_start;
65
extern void *__initrd_end;
66
int initrd_is_mapped = 0;
67
extern int initrd_below_start_ok;
68
#endif
69
70
unsigned char aux_device_present;
71
extern unsigned long loops_per_jiffy;
72
73
/* Command line specified as configuration option. */
74
75
static char __initdata command_line[COMMAND_LINE_SIZE];
76
77
#ifdef CONFIG_CMDLINE_BOOL
78
static char default_command_line[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE;
79
#endif
80
81
sysmem_info_t __initdata sysmem;
82
83
#ifdef CONFIG_BLK_DEV_INITRD
84
int initrd_is_mapped;
85
#endif
86
87
#ifdef CONFIG_MMU
88
extern void init_mmu(void);
89
#else
90
static inline void init_mmu(void) { }
91
#endif
92
93
extern void zones_init(void);
94
95
/*
96
* Boot parameter parsing.
97
*
98
* The Xtensa port uses a list of variable-sized tags to pass data to
99
* the kernel. The first tag must be a BP_TAG_FIRST tag for the list
100
* to be recognised. The list is terminated with a zero-sized
101
* BP_TAG_LAST tag.
102
*/
103
104
typedef struct tagtable {
105
u32 tag;
106
int (*parse)(const bp_tag_t*);
107
} tagtable_t;
108
109
#define __tagtable(tag, fn) static tagtable_t __tagtable_##fn \
110
__attribute__((unused, __section__(".taglist"))) = { tag, fn }
111
112
/* parse current tag */
113
114
static int __init parse_tag_mem(const bp_tag_t *tag)
115
{
116
meminfo_t *mi = (meminfo_t*)(tag->data);
117
118
if (mi->type != MEMORY_TYPE_CONVENTIONAL)
119
return -1;
120
121
if (sysmem.nr_banks >= SYSMEM_BANKS_MAX) {
122
printk(KERN_WARNING
123
"Ignoring memory bank 0x%08lx size %ldKB\n",
124
(unsigned long)mi->start,
125
(unsigned long)mi->end - (unsigned long)mi->start);
126
return -EINVAL;
127
}
128
sysmem.bank[sysmem.nr_banks].type = mi->type;
129
sysmem.bank[sysmem.nr_banks].start = PAGE_ALIGN(mi->start);
130
sysmem.bank[sysmem.nr_banks].end = mi->end & PAGE_SIZE;
131
sysmem.nr_banks++;
132
133
return 0;
134
}
135
136
__tagtable(BP_TAG_MEMORY, parse_tag_mem);
137
138
#ifdef CONFIG_BLK_DEV_INITRD
139
140
static int __init parse_tag_initrd(const bp_tag_t* tag)
141
{
142
meminfo_t* mi;
143
mi = (meminfo_t*)(tag->data);
144
initrd_start = (void*)(mi->start);
145
initrd_end = (void*)(mi->end);
146
147
return 0;
148
}
149
150
__tagtable(BP_TAG_INITRD, parse_tag_initrd);
151
152
#endif /* CONFIG_BLK_DEV_INITRD */
153
154
static int __init parse_tag_cmdline(const bp_tag_t* tag)
155
{
156
strncpy(command_line, (char*)(tag->data), COMMAND_LINE_SIZE);
157
command_line[COMMAND_LINE_SIZE - 1] = '\0';
158
return 0;
159
}
160
161
__tagtable(BP_TAG_COMMAND_LINE, parse_tag_cmdline);
162
163
static int __init parse_bootparam(const bp_tag_t* tag)
164
{
165
extern tagtable_t __tagtable_begin, __tagtable_end;
166
tagtable_t *t;
167
168
/* Boot parameters must start with a BP_TAG_FIRST tag. */
169
170
if (tag->id != BP_TAG_FIRST) {
171
printk(KERN_WARNING "Invalid boot parameters!\n");
172
return 0;
173
}
174
175
tag = (bp_tag_t*)((unsigned long)tag + sizeof(bp_tag_t) + tag->size);
176
177
/* Parse all tags. */
178
179
while (tag != NULL && tag->id != BP_TAG_LAST) {
180
for (t = &__tagtable_begin; t < &__tagtable_end; t++) {
181
if (tag->id == t->tag) {
182
t->parse(tag);
183
break;
184
}
185
}
186
if (t == &__tagtable_end)
187
printk(KERN_WARNING "Ignoring tag "
188
"0x%08x\n", tag->id);
189
tag = (bp_tag_t*)((unsigned long)(tag + 1) + tag->size);
190
}
191
192
return 0;
193
}
194
195
/*
196
* Initialize architecture. (Early stage)
197
*/
198
199
void __init init_arch(bp_tag_t *bp_start)
200
{
201
202
#ifdef CONFIG_BLK_DEV_INITRD
203
initrd_start = &__initrd_start;
204
initrd_end = &__initrd_end;
205
#endif
206
207
sysmem.nr_banks = 0;
208
209
#ifdef CONFIG_CMDLINE_BOOL
210
strcpy(command_line, default_command_line);
211
#endif
212
213
/* Parse boot parameters */
214
215
if (bp_start)
216
parse_bootparam(bp_start);
217
218
if (sysmem.nr_banks == 0) {
219
sysmem.nr_banks = 1;
220
sysmem.bank[0].start = PLATFORM_DEFAULT_MEM_START;
221
sysmem.bank[0].end = PLATFORM_DEFAULT_MEM_START
222
+ PLATFORM_DEFAULT_MEM_SIZE;
223
}
224
225
/* Early hook for platforms */
226
227
platform_init(bp_start);
228
229
/* Initialize MMU. */
230
231
init_mmu();
232
}
233
234
/*
235
* Initialize system. Setup memory and reserve regions.
236
*/
237
238
extern char _end;
239
extern char _stext;
240
extern char _WindowVectors_text_start;
241
extern char _WindowVectors_text_end;
242
extern char _DebugInterruptVector_literal_start;
243
extern char _DebugInterruptVector_text_end;
244
extern char _KernelExceptionVector_literal_start;
245
extern char _KernelExceptionVector_text_end;
246
extern char _UserExceptionVector_literal_start;
247
extern char _UserExceptionVector_text_end;
248
extern char _DoubleExceptionVector_literal_start;
249
extern char _DoubleExceptionVector_text_end;
250
251
void __init setup_arch(char **cmdline_p)
252
{
253
extern int mem_reserve(unsigned long, unsigned long, int);
254
extern void bootmem_init(void);
255
256
memcpy(boot_command_line, command_line, COMMAND_LINE_SIZE);
257
boot_command_line[COMMAND_LINE_SIZE-1] = '\0';
258
*cmdline_p = command_line;
259
260
/* Reserve some memory regions */
261
262
#ifdef CONFIG_BLK_DEV_INITRD
263
if (initrd_start < initrd_end) {
264
initrd_is_mapped = mem_reserve(__pa(initrd_start),
265
__pa(initrd_end), 0);
266
initrd_below_start_ok = 1;
267
} else {
268
initrd_start = 0;
269
}
270
#endif
271
272
mem_reserve(__pa(&_stext),__pa(&_end), 1);
273
274
mem_reserve(__pa(&_WindowVectors_text_start),
275
__pa(&_WindowVectors_text_end), 0);
276
277
mem_reserve(__pa(&_DebugInterruptVector_literal_start),
278
__pa(&_DebugInterruptVector_text_end), 0);
279
280
mem_reserve(__pa(&_KernelExceptionVector_literal_start),
281
__pa(&_KernelExceptionVector_text_end), 0);
282
283
mem_reserve(__pa(&_UserExceptionVector_literal_start),
284
__pa(&_UserExceptionVector_text_end), 0);
285
286
mem_reserve(__pa(&_DoubleExceptionVector_literal_start),
287
__pa(&_DoubleExceptionVector_text_end), 0);
288
289
bootmem_init();
290
291
platform_setup(cmdline_p);
292
293
294
paging_init();
295
zones_init();
296
297
#ifdef CONFIG_VT
298
# if defined(CONFIG_VGA_CONSOLE)
299
conswitchp = &vga_con;
300
# elif defined(CONFIG_DUMMY_CONSOLE)
301
conswitchp = &dummy_con;
302
# endif
303
#endif
304
305
#ifdef CONFIG_PCI
306
platform_pcibios_init();
307
#endif
308
}
309
310
void machine_restart(char * cmd)
311
{
312
platform_restart();
313
}
314
315
void machine_halt(void)
316
{
317
platform_halt();
318
while (1);
319
}
320
321
void machine_power_off(void)
322
{
323
platform_power_off();
324
while (1);
325
}
326
#ifdef CONFIG_PROC_FS
327
328
/*
329
* Display some core information through /proc/cpuinfo.
330
*/
331
332
static int
333
c_show(struct seq_file *f, void *slot)
334
{
335
/* high-level stuff */
336
seq_printf(f,"processor\t: 0\n"
337
"vendor_id\t: Tensilica\n"
338
"model\t\t: Xtensa " XCHAL_HW_VERSION_NAME "\n"
339
"core ID\t\t: " XCHAL_CORE_ID "\n"
340
"build ID\t: 0x%x\n"
341
"byte order\t: %s\n"
342
"cpu MHz\t\t: %lu.%02lu\n"
343
"bogomips\t: %lu.%02lu\n",
344
XCHAL_BUILD_UNIQUE_ID,
345
XCHAL_HAVE_BE ? "big" : "little",
346
CCOUNT_PER_JIFFY/(1000000/HZ),
347
(CCOUNT_PER_JIFFY/(10000/HZ)) % 100,
348
loops_per_jiffy/(500000/HZ),
349
(loops_per_jiffy/(5000/HZ)) % 100);
350
351
seq_printf(f,"flags\t\t: "
352
#if XCHAL_HAVE_NMI
353
"nmi "
354
#endif
355
#if XCHAL_HAVE_DEBUG
356
"debug "
357
# if XCHAL_HAVE_OCD
358
"ocd "
359
# endif
360
#endif
361
#if XCHAL_HAVE_DENSITY
362
"density "
363
#endif
364
#if XCHAL_HAVE_BOOLEANS
365
"boolean "
366
#endif
367
#if XCHAL_HAVE_LOOPS
368
"loop "
369
#endif
370
#if XCHAL_HAVE_NSA
371
"nsa "
372
#endif
373
#if XCHAL_HAVE_MINMAX
374
"minmax "
375
#endif
376
#if XCHAL_HAVE_SEXT
377
"sext "
378
#endif
379
#if XCHAL_HAVE_CLAMPS
380
"clamps "
381
#endif
382
#if XCHAL_HAVE_MAC16
383
"mac16 "
384
#endif
385
#if XCHAL_HAVE_MUL16
386
"mul16 "
387
#endif
388
#if XCHAL_HAVE_MUL32
389
"mul32 "
390
#endif
391
#if XCHAL_HAVE_MUL32_HIGH
392
"mul32h "
393
#endif
394
#if XCHAL_HAVE_FP
395
"fpu "
396
#endif
397
"\n");
398
399
/* Registers. */
400
seq_printf(f,"physical aregs\t: %d\n"
401
"misc regs\t: %d\n"
402
"ibreak\t\t: %d\n"
403
"dbreak\t\t: %d\n",
404
XCHAL_NUM_AREGS,
405
XCHAL_NUM_MISC_REGS,
406
XCHAL_NUM_IBREAK,
407
XCHAL_NUM_DBREAK);
408
409
410
/* Interrupt. */
411
seq_printf(f,"num ints\t: %d\n"
412
"ext ints\t: %d\n"
413
"int levels\t: %d\n"
414
"timers\t\t: %d\n"
415
"debug level\t: %d\n",
416
XCHAL_NUM_INTERRUPTS,
417
XCHAL_NUM_EXTINTERRUPTS,
418
XCHAL_NUM_INTLEVELS,
419
XCHAL_NUM_TIMERS,
420
XCHAL_DEBUGLEVEL);
421
422
/* Cache */
423
seq_printf(f,"icache line size: %d\n"
424
"icache ways\t: %d\n"
425
"icache size\t: %d\n"
426
"icache flags\t: "
427
#if XCHAL_ICACHE_LINE_LOCKABLE
428
"lock"
429
#endif
430
"\n"
431
"dcache line size: %d\n"
432
"dcache ways\t: %d\n"
433
"dcache size\t: %d\n"
434
"dcache flags\t: "
435
#if XCHAL_DCACHE_IS_WRITEBACK
436
"writeback"
437
#endif
438
#if XCHAL_DCACHE_LINE_LOCKABLE
439
"lock"
440
#endif
441
"\n",
442
XCHAL_ICACHE_LINESIZE,
443
XCHAL_ICACHE_WAYS,
444
XCHAL_ICACHE_SIZE,
445
XCHAL_DCACHE_LINESIZE,
446
XCHAL_DCACHE_WAYS,
447
XCHAL_DCACHE_SIZE);
448
449
return 0;
450
}
451
452
/*
453
* We show only CPU #0 info.
454
*/
455
static void *
456
c_start(struct seq_file *f, loff_t *pos)
457
{
458
return (void *) ((*pos == 0) ? (void *)1 : NULL);
459
}
460
461
static void *
462
c_next(struct seq_file *f, void *v, loff_t *pos)
463
{
464
return NULL;
465
}
466
467
static void
468
c_stop(struct seq_file *f, void *v)
469
{
470
}
471
472
const struct seq_operations cpuinfo_op =
473
{
474
start: c_start,
475
next: c_next,
476
stop: c_stop,
477
show: c_show
478
};
479
480
#endif /* CONFIG_PROC_FS */
481
482
483