aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc64/kernel/setup.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sparc64/kernel/setup.c')
-rw-r--r--arch/sparc64/kernel/setup.c409
1 files changed, 124 insertions, 285 deletions
diff --git a/arch/sparc64/kernel/setup.c b/arch/sparc64/kernel/setup.c
index 158bd31e15b7..7d0e67c1ce50 100644
--- a/arch/sparc64/kernel/setup.c
+++ b/arch/sparc64/kernel/setup.c
@@ -64,12 +64,6 @@ struct screen_info screen_info = {
64 16 /* orig-video-points */ 64 16 /* orig-video-points */
65}; 65};
66 66
67/* Typing sync at the prom prompt calls the function pointed to by
68 * the sync callback which I set to the following function.
69 * This should sync all filesystems and return, for now it just
70 * prints out pretty messages and returns.
71 */
72
73void (*prom_palette)(int); 67void (*prom_palette)(int);
74void (*prom_keyboard)(void); 68void (*prom_keyboard)(void);
75 69
@@ -79,259 +73,6 @@ prom_console_write(struct console *con, const char *s, unsigned n)
79 prom_write(s, n); 73 prom_write(s, n);
80} 74}
81 75
82static struct console prom_console = {
83 .name = "prom",
84 .write = prom_console_write,
85 .flags = CON_CONSDEV | CON_ENABLED,
86 .index = -1,
87};
88
89#define PROM_TRUE -1
90#define PROM_FALSE 0
91
92/* Pretty sick eh? */
93int prom_callback(long *args)
94{
95 struct console *cons, *saved_console = NULL;
96 unsigned long flags;
97 char *cmd;
98 extern spinlock_t prom_entry_lock;
99
100 if (!args)
101 return -1;
102 if (!(cmd = (char *)args[0]))
103 return -1;
104
105 /*
106 * The callback can be invoked on the cpu that first dropped
107 * into prom_cmdline after taking the serial interrupt, or on
108 * a slave processor that was smp_captured() if the
109 * administrator has done a switch-cpu inside obp. In either
110 * case, the cpu is marked as in-interrupt. Drop IRQ locks.
111 */
112 irq_exit();
113
114 /* XXX Revisit the locking here someday. This is a debugging
115 * XXX feature so it isnt all that critical. -DaveM
116 */
117 local_irq_save(flags);
118
119 spin_unlock(&prom_entry_lock);
120 cons = console_drivers;
121 while (cons) {
122 unregister_console(cons);
123 cons->flags &= ~(CON_PRINTBUFFER);
124 cons->next = saved_console;
125 saved_console = cons;
126 cons = console_drivers;
127 }
128 register_console(&prom_console);
129 if (!strcmp(cmd, "sync")) {
130 prom_printf("PROM `%s' command...\n", cmd);
131 show_free_areas();
132 if (current->pid != 0) {
133 local_irq_enable();
134 sys_sync();
135 local_irq_disable();
136 }
137 args[2] = 0;
138 args[args[1] + 3] = -1;
139 prom_printf("Returning to PROM\n");
140 } else if (!strcmp(cmd, "va>tte-data")) {
141 unsigned long ctx, va;
142 unsigned long tte = 0;
143 long res = PROM_FALSE;
144
145 ctx = args[3];
146 va = args[4];
147 if (ctx) {
148 /*
149 * Find process owning ctx, lookup mapping.
150 */
151 struct task_struct *p;
152 struct mm_struct *mm = NULL;
153 pgd_t *pgdp;
154 pud_t *pudp;
155 pmd_t *pmdp;
156 pte_t *ptep;
157 pte_t pte;
158
159 for_each_process(p) {
160 mm = p->mm;
161 if (CTX_NRBITS(mm->context) == ctx)
162 break;
163 }
164 if (!mm ||
165 CTX_NRBITS(mm->context) != ctx)
166 goto done;
167
168 pgdp = pgd_offset(mm, va);
169 if (pgd_none(*pgdp))
170 goto done;
171 pudp = pud_offset(pgdp, va);
172 if (pud_none(*pudp))
173 goto done;
174 pmdp = pmd_offset(pudp, va);
175 if (pmd_none(*pmdp))
176 goto done;
177
178 /* Preemption implicitly disabled by virtue of
179 * being called from inside OBP.
180 */
181 ptep = pte_offset_map(pmdp, va);
182 pte = *ptep;
183 if (pte_present(pte)) {
184 tte = pte_val(pte);
185 res = PROM_TRUE;
186 }
187 pte_unmap(ptep);
188 goto done;
189 }
190
191 if ((va >= KERNBASE) && (va < (KERNBASE + (4 * 1024 * 1024)))) {
192 extern unsigned long sparc64_kern_pri_context;
193
194 /* Spitfire Errata #32 workaround */
195 __asm__ __volatile__("stxa %0, [%1] %2\n\t"
196 "flush %%g6"
197 : /* No outputs */
198 : "r" (sparc64_kern_pri_context),
199 "r" (PRIMARY_CONTEXT),
200 "i" (ASI_DMMU));
201
202 /*
203 * Locked down tlb entry.
204 */
205
206 if (tlb_type == spitfire)
207 tte = spitfire_get_dtlb_data(SPITFIRE_HIGHEST_LOCKED_TLBENT);
208 else if (tlb_type == cheetah || tlb_type == cheetah_plus)
209 tte = cheetah_get_ldtlb_data(CHEETAH_HIGHEST_LOCKED_TLBENT);
210
211 res = PROM_TRUE;
212 goto done;
213 }
214
215 if (va < PGDIR_SIZE) {
216 /*
217 * vmalloc or prom_inherited mapping.
218 */
219 pgd_t *pgdp;
220 pud_t *pudp;
221 pmd_t *pmdp;
222 pte_t *ptep;
223 pte_t pte;
224 int error;
225
226 if ((va >= LOW_OBP_ADDRESS) && (va < HI_OBP_ADDRESS)) {
227 tte = prom_virt_to_phys(va, &error);
228 if (!error)
229 res = PROM_TRUE;
230 goto done;
231 }
232 pgdp = pgd_offset_k(va);
233 if (pgd_none(*pgdp))
234 goto done;
235 pudp = pud_offset(pgdp, va);
236 if (pud_none(*pudp))
237 goto done;
238 pmdp = pmd_offset(pudp, va);
239 if (pmd_none(*pmdp))
240 goto done;
241
242 /* Preemption implicitly disabled by virtue of
243 * being called from inside OBP.
244 */
245 ptep = pte_offset_kernel(pmdp, va);
246 pte = *ptep;
247 if (pte_present(pte)) {
248 tte = pte_val(pte);
249 res = PROM_TRUE;
250 }
251 goto done;
252 }
253
254 if (va < PAGE_OFFSET) {
255 /*
256 * No mappings here.
257 */
258 goto done;
259 }
260
261 if (va & (1UL << 40)) {
262 /*
263 * I/O page.
264 */
265
266 tte = (__pa(va) & _PAGE_PADDR) |
267 _PAGE_VALID | _PAGE_SZ4MB |
268 _PAGE_E | _PAGE_P | _PAGE_W;
269 res = PROM_TRUE;
270 goto done;
271 }
272
273 /*
274 * Normal page.
275 */
276 tte = (__pa(va) & _PAGE_PADDR) |
277 _PAGE_VALID | _PAGE_SZ4MB |
278 _PAGE_CP | _PAGE_CV | _PAGE_P | _PAGE_W;
279 res = PROM_TRUE;
280
281 done:
282 if (res == PROM_TRUE) {
283 args[2] = 3;
284 args[args[1] + 3] = 0;
285 args[args[1] + 4] = res;
286 args[args[1] + 5] = tte;
287 } else {
288 args[2] = 2;
289 args[args[1] + 3] = 0;
290 args[args[1] + 4] = res;
291 }
292 } else if (!strcmp(cmd, ".soft1")) {
293 unsigned long tte;
294
295 tte = args[3];
296 prom_printf("%lx:\"%s%s%s%s%s\" ",
297 (tte & _PAGE_SOFT) >> 7,
298 tte & _PAGE_MODIFIED ? "M" : "-",
299 tte & _PAGE_ACCESSED ? "A" : "-",
300 tte & _PAGE_READ ? "W" : "-",
301 tte & _PAGE_WRITE ? "R" : "-",
302 tte & _PAGE_PRESENT ? "P" : "-");
303
304 args[2] = 2;
305 args[args[1] + 3] = 0;
306 args[args[1] + 4] = PROM_TRUE;
307 } else if (!strcmp(cmd, ".soft2")) {
308 unsigned long tte;
309
310 tte = args[3];
311 prom_printf("%lx ", (tte & 0x07FC000000000000UL) >> 50);
312
313 args[2] = 2;
314 args[args[1] + 3] = 0;
315 args[args[1] + 4] = PROM_TRUE;
316 } else {
317 prom_printf("unknown PROM `%s' command...\n", cmd);
318 }
319 unregister_console(&prom_console);
320 while (saved_console) {
321 cons = saved_console;
322 saved_console = cons->next;
323 register_console(cons);
324 }
325 spin_lock(&prom_entry_lock);
326 local_irq_restore(flags);
327
328 /*
329 * Restore in-interrupt status for a resume from obp.
330 */
331 irq_enter();
332 return 0;
333}
334
335unsigned int boot_flags = 0; 76unsigned int boot_flags = 0;
336#define BOOTME_DEBUG 0x1 77#define BOOTME_DEBUG 0x1
337#define BOOTME_SINGLE 0x2 78#define BOOTME_SINGLE 0x2
@@ -479,15 +220,99 @@ char reboot_command[COMMAND_LINE_SIZE];
479 220
480static struct pt_regs fake_swapper_regs = { { 0, }, 0, 0, 0, 0 }; 221static struct pt_regs fake_swapper_regs = { { 0, }, 0, 0, 0, 0 };
481 222
482void register_prom_callbacks(void) 223static void __init per_cpu_patch(void)
483{ 224{
484 prom_setcallback(prom_callback); 225 struct cpuid_patch_entry *p;
485 prom_feval(": linux-va>tte-data 2 \" va>tte-data\" $callback drop ; " 226 unsigned long ver;
486 "' linux-va>tte-data to va>tte-data"); 227 int is_jbus;
487 prom_feval(": linux-.soft1 1 \" .soft1\" $callback 2drop ; " 228
488 "' linux-.soft1 to .soft1"); 229 if (tlb_type == spitfire && !this_is_starfire)
489 prom_feval(": linux-.soft2 1 \" .soft2\" $callback 2drop ; " 230 return;
490 "' linux-.soft2 to .soft2"); 231
232 is_jbus = 0;
233 if (tlb_type != hypervisor) {
234 __asm__ ("rdpr %%ver, %0" : "=r" (ver));
235 is_jbus = ((ver >> 32UL) == __JALAPENO_ID ||
236 (ver >> 32UL) == __SERRANO_ID);
237 }
238
239 p = &__cpuid_patch;
240 while (p < &__cpuid_patch_end) {
241 unsigned long addr = p->addr;
242 unsigned int *insns;
243
244 switch (tlb_type) {
245 case spitfire:
246 insns = &p->starfire[0];
247 break;
248 case cheetah:
249 case cheetah_plus:
250 if (is_jbus)
251 insns = &p->cheetah_jbus[0];
252 else
253 insns = &p->cheetah_safari[0];
254 break;
255 case hypervisor:
256 insns = &p->sun4v[0];
257 break;
258 default:
259 prom_printf("Unknown cpu type, halting.\n");
260 prom_halt();
261 };
262
263 *(unsigned int *) (addr + 0) = insns[0];
264 wmb();
265 __asm__ __volatile__("flush %0" : : "r" (addr + 0));
266
267 *(unsigned int *) (addr + 4) = insns[1];
268 wmb();
269 __asm__ __volatile__("flush %0" : : "r" (addr + 4));
270
271 *(unsigned int *) (addr + 8) = insns[2];
272 wmb();
273 __asm__ __volatile__("flush %0" : : "r" (addr + 8));
274
275 *(unsigned int *) (addr + 12) = insns[3];
276 wmb();
277 __asm__ __volatile__("flush %0" : : "r" (addr + 12));
278
279 p++;
280 }
281}
282
283static void __init sun4v_patch(void)
284{
285 struct sun4v_1insn_patch_entry *p1;
286 struct sun4v_2insn_patch_entry *p2;
287
288 if (tlb_type != hypervisor)
289 return;
290
291 p1 = &__sun4v_1insn_patch;
292 while (p1 < &__sun4v_1insn_patch_end) {
293 unsigned long addr = p1->addr;
294
295 *(unsigned int *) (addr + 0) = p1->insn;
296 wmb();
297 __asm__ __volatile__("flush %0" : : "r" (addr + 0));
298
299 p1++;
300 }
301
302 p2 = &__sun4v_2insn_patch;
303 while (p2 < &__sun4v_2insn_patch_end) {
304 unsigned long addr = p2->addr;
305
306 *(unsigned int *) (addr + 0) = p2->insns[0];
307 wmb();
308 __asm__ __volatile__("flush %0" : : "r" (addr + 0));
309
310 *(unsigned int *) (addr + 4) = p2->insns[1];
311 wmb();
312 __asm__ __volatile__("flush %0" : : "r" (addr + 4));
313
314 p2++;
315 }
491} 316}
492 317
493void __init setup_arch(char **cmdline_p) 318void __init setup_arch(char **cmdline_p)
@@ -496,7 +321,10 @@ void __init setup_arch(char **cmdline_p)
496 *cmdline_p = prom_getbootargs(); 321 *cmdline_p = prom_getbootargs();
497 strcpy(saved_command_line, *cmdline_p); 322 strcpy(saved_command_line, *cmdline_p);
498 323
499 printk("ARCH: SUN4U\n"); 324 if (tlb_type == hypervisor)
325 printk("ARCH: SUN4V\n");
326 else
327 printk("ARCH: SUN4U\n");
500 328
501#ifdef CONFIG_DUMMY_CONSOLE 329#ifdef CONFIG_DUMMY_CONSOLE
502 conswitchp = &dummy_con; 330 conswitchp = &dummy_con;
@@ -507,6 +335,13 @@ void __init setup_arch(char **cmdline_p)
507 /* Work out if we are starfire early on */ 335 /* Work out if we are starfire early on */
508 check_if_starfire(); 336 check_if_starfire();
509 337
338 /* Now we know enough to patch the get_cpuid sequences
339 * used by trap code.
340 */
341 per_cpu_patch();
342
343 sun4v_patch();
344
510 boot_flags_init(*cmdline_p); 345 boot_flags_init(*cmdline_p);
511 346
512 idprom_init(); 347 idprom_init();
@@ -514,7 +349,7 @@ void __init setup_arch(char **cmdline_p)
514 if (!root_flags) 349 if (!root_flags)
515 root_mountflags &= ~MS_RDONLY; 350 root_mountflags &= ~MS_RDONLY;
516 ROOT_DEV = old_decode_dev(root_dev); 351 ROOT_DEV = old_decode_dev(root_dev);
517#ifdef CONFIG_BLK_DEV_INITRD 352#ifdef CONFIG_BLK_DEV_RAM
518 rd_image_start = ram_flags & RAMDISK_IMAGE_START_MASK; 353 rd_image_start = ram_flags & RAMDISK_IMAGE_START_MASK;
519 rd_prompt = ((ram_flags & RAMDISK_PROMPT_FLAG) != 0); 354 rd_prompt = ((ram_flags & RAMDISK_PROMPT_FLAG) != 0);
520 rd_doload = ((ram_flags & RAMDISK_LOAD_FLAG) != 0); 355 rd_doload = ((ram_flags & RAMDISK_LOAD_FLAG) != 0);
@@ -544,6 +379,9 @@ void __init setup_arch(char **cmdline_p)
544 379
545 smp_setup_cpu_possible_map(); 380 smp_setup_cpu_possible_map();
546 381
382 /* Get boot processor trap_block[] setup. */
383 init_cur_cpu_trap(current_thread_info());
384
547 paging_init(); 385 paging_init();
548} 386}
549 387
@@ -565,6 +403,12 @@ static int __init set_preferred_console(void)
565 serial_console = 2; 403 serial_console = 2;
566 } else if (idev == PROMDEV_IRSC && odev == PROMDEV_ORSC) { 404 } else if (idev == PROMDEV_IRSC && odev == PROMDEV_ORSC) {
567 serial_console = 3; 405 serial_console = 3;
406 } else if (idev == PROMDEV_IVCONS && odev == PROMDEV_OVCONS) {
407 /* sunhv_console_init() doesn't check the serial_console
408 * value anyways...
409 */
410 serial_console = 4;
411 return add_preferred_console("ttyHV", 0, NULL);
568 } else { 412 } else {
569 prom_printf("Inconsistent console: " 413 prom_printf("Inconsistent console: "
570 "input %d, output %d\n", 414 "input %d, output %d\n",
@@ -598,9 +442,8 @@ static int show_cpuinfo(struct seq_file *m, void *__unused)
598 seq_printf(m, 442 seq_printf(m,
599 "cpu\t\t: %s\n" 443 "cpu\t\t: %s\n"
600 "fpu\t\t: %s\n" 444 "fpu\t\t: %s\n"
601 "promlib\t\t: Version 3 Revision %d\n" 445 "prom\t\t: %s\n"
602 "prom\t\t: %d.%d.%d\n" 446 "type\t\t: %s\n"
603 "type\t\t: sun4u\n"
604 "ncpus probed\t: %d\n" 447 "ncpus probed\t: %d\n"
605 "ncpus active\t: %d\n" 448 "ncpus active\t: %d\n"
606 "D$ parity tl1\t: %u\n" 449 "D$ parity tl1\t: %u\n"
@@ -612,10 +455,10 @@ static int show_cpuinfo(struct seq_file *m, void *__unused)
612 , 455 ,
613 sparc_cpu_type, 456 sparc_cpu_type,
614 sparc_fpu_type, 457 sparc_fpu_type,
615 prom_rev, 458 prom_version,
616 prom_prev >> 16, 459 ((tlb_type == hypervisor) ?
617 (prom_prev >> 8) & 0xff, 460 "sun4v" :
618 prom_prev & 0xff, 461 "sun4u"),
619 ncpus_probed, 462 ncpus_probed,
620 num_online_cpus(), 463 num_online_cpus(),
621 dcache_parity_tl1_occurred, 464 dcache_parity_tl1_occurred,
@@ -692,15 +535,11 @@ static int __init topology_init(void)
692 while (!cpu_find_by_instance(ncpus_probed, NULL, NULL)) 535 while (!cpu_find_by_instance(ncpus_probed, NULL, NULL))
693 ncpus_probed++; 536 ncpus_probed++;
694 537
695 for (i = 0; i < NR_CPUS; i++) { 538 for_each_cpu(i) {
696 if (cpu_possible(i)) { 539 struct cpu *p = kzalloc(sizeof(*p), GFP_KERNEL);
697 struct cpu *p = kmalloc(sizeof(*p), GFP_KERNEL); 540 if (p) {
698 541 register_cpu(p, i, NULL);
699 if (p) { 542 err = 0;
700 memset(p, 0, sizeof(*p));
701 register_cpu(p, i, NULL);
702 err = 0;
703 }
704 } 543 }
705 } 544 }
706 545