aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sh
diff options
context:
space:
mode:
authorPaul Mundt <lethal@linux-sh.org>2010-01-12 00:50:43 -0500
committerPaul Mundt <lethal@linux-sh.org>2010-01-12 00:50:43 -0500
commit191d0d24b632eb69767705acded5cbf7449ad457 (patch)
tree4fda30db2941692bea884685f1df2e751468bd6f /arch/sh
parentee2760ea58d81fc00bcc2137232ed9bc28202aec (diff)
sh: Tidy up the sh bios VBR handling.
This moves the VBR handling out of the main trap handling code and in to the sh-bios helper code. A couple of accessors are added in order to permit other kernel code to get at the VBR value for state save/restore paths. Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'arch/sh')
-rw-r--r--arch/sh/include/asm/sh_bios.h14
-rw-r--r--arch/sh/kernel/machine_kexec.c8
-rw-r--r--arch/sh/kernel/sh_bios.c37
-rw-r--r--arch/sh/kernel/traps_32.c29
4 files changed, 55 insertions, 33 deletions
diff --git a/arch/sh/include/asm/sh_bios.h b/arch/sh/include/asm/sh_bios.h
index d9c96d7cf6c7..d8a67a17777c 100644
--- a/arch/sh/include/asm/sh_bios.h
+++ b/arch/sh/include/asm/sh_bios.h
@@ -1,13 +1,13 @@
1#ifndef __ASM_SH_BIOS_H 1#ifndef __ASM_SH_BIOS_H
2#define __ASM_SH_BIOS_H 2#define __ASM_SH_BIOS_H
3 3
4#ifdef CONFIG_SH_STANDARD_BIOS
5
4/* 6/*
5 * Copyright (C) 2000 Greg Banks, Mitch Davis 7 * Copyright (C) 2000 Greg Banks, Mitch Davis
6 * C API to interface to the standard LinuxSH BIOS 8 * C API to interface to the standard LinuxSH BIOS
7 * usually from within the early stages of kernel boot. 9 * usually from within the early stages of kernel boot.
8 */ 10 */
9
10
11extern void sh_bios_console_write(const char *buf, unsigned int len); 11extern void sh_bios_console_write(const char *buf, unsigned int len);
12extern void sh_bios_char_out(char ch); 12extern void sh_bios_char_out(char ch);
13extern void sh_bios_gdb_detach(void); 13extern void sh_bios_gdb_detach(void);
@@ -15,4 +15,14 @@ extern void sh_bios_gdb_detach(void);
15extern void sh_bios_get_node_addr(unsigned char *node_addr); 15extern void sh_bios_get_node_addr(unsigned char *node_addr);
16extern void sh_bios_shutdown(unsigned int how); 16extern void sh_bios_shutdown(unsigned int how);
17 17
18extern void sh_bios_vbr_init(void);
19extern void sh_bios_vbr_reload(void);
20
21#else
22
23static inline void sh_bios_vbr_init(void) { }
24static inline void sh_bios_vbr_reload(void) { }
25
26#endif /* CONFIG_SH_STANDARD_BIOS */
27
18#endif /* __ASM_SH_BIOS_H */ 28#endif /* __ASM_SH_BIOS_H */
diff --git a/arch/sh/kernel/machine_kexec.c b/arch/sh/kernel/machine_kexec.c
index 76f280223ebd..f52d8ed69e12 100644
--- a/arch/sh/kernel/machine_kexec.c
+++ b/arch/sh/kernel/machine_kexec.c
@@ -21,6 +21,7 @@
21#include <asm/mmu_context.h> 21#include <asm/mmu_context.h>
22#include <asm/io.h> 22#include <asm/io.h>
23#include <asm/cacheflush.h> 23#include <asm/cacheflush.h>
24#include <asm/sh_bios.h>
24 25
25typedef void (*relocate_new_kernel_t)(unsigned long indirection_page, 26typedef void (*relocate_new_kernel_t)(unsigned long indirection_page,
26 unsigned long reboot_code_buffer, 27 unsigned long reboot_code_buffer,
@@ -28,7 +29,6 @@ typedef void (*relocate_new_kernel_t)(unsigned long indirection_page,
28 29
29extern const unsigned char relocate_new_kernel[]; 30extern const unsigned char relocate_new_kernel[];
30extern const unsigned int relocate_new_kernel_size; 31extern const unsigned int relocate_new_kernel_size;
31extern void *gdb_vbr_vector;
32extern void *vbr_base; 32extern void *vbr_base;
33 33
34void machine_shutdown(void) 34void machine_shutdown(void)
@@ -117,11 +117,7 @@ void machine_kexec(struct kimage *image)
117 kexec_info(image); 117 kexec_info(image);
118 flush_cache_all(); 118 flush_cache_all();
119 119
120#if defined(CONFIG_SH_STANDARD_BIOS) 120 sh_bios_vbr_reload();
121 asm volatile("ldc %0, vbr" :
122 : "r" (((unsigned long) gdb_vbr_vector) - 0x100)
123 : "memory");
124#endif
125 121
126 /* now call it */ 122 /* now call it */
127 rnk = (relocate_new_kernel_t) reboot_code_buffer; 123 rnk = (relocate_new_kernel_t) reboot_code_buffer;
diff --git a/arch/sh/kernel/sh_bios.c b/arch/sh/kernel/sh_bios.c
index c852f7805728..2a5f2e0d505d 100644
--- a/arch/sh/kernel/sh_bios.c
+++ b/arch/sh/kernel/sh_bios.c
@@ -55,3 +55,40 @@ void sh_bios_shutdown(unsigned int how)
55{ 55{
56 sh_bios_call(BIOS_CALL_SHUTDOWN, how, 0, 0, 0); 56 sh_bios_call(BIOS_CALL_SHUTDOWN, how, 0, 0, 0);
57} 57}
58
59void *gdb_vbr_vector = NULL;
60
61/*
62 * Read the old value of the VBR register to initialise the vector
63 * through which debug and BIOS traps are delegated by the Linux trap
64 * handler.
65 */
66void sh_bios_vbr_init(void)
67{
68 unsigned long vbr;
69
70 if (unlikely(gdb_vbr_vector))
71 return;
72
73 __asm__ __volatile__ ("stc vbr, %0" : "=r" (vbr));
74
75 gdb_vbr_vector = (void *)(vbr + 0x100);
76 printk(KERN_NOTICE "Setting GDB trap vector to %p\n", gdb_vbr_vector);
77}
78
79/**
80 * sh_bios_vbr_reload - Re-load the system VBR from the BIOS vector.
81 *
82 * This can be used by save/restore code to reinitialize the system VBR
83 * from the fixed BIOS VBR. A no-op if no BIOS VBR is known.
84 */
85void sh_bios_vbr_reload(void)
86{
87 if (gdb_vbr_vector)
88 __asm__ __volatile__ (
89 "ldc %0, vbr"
90 :
91 : "r" (((unsigned long) gdb_vbr_vector) - 0x100)
92 : "memory"
93 );
94}
diff --git a/arch/sh/kernel/traps_32.c b/arch/sh/kernel/traps_32.c
index 86639beac3a2..efcbdfe52f52 100644
--- a/arch/sh/kernel/traps_32.c
+++ b/arch/sh/kernel/traps_32.c
@@ -31,6 +31,7 @@
31#include <asm/uaccess.h> 31#include <asm/uaccess.h>
32#include <asm/fpu.h> 32#include <asm/fpu.h>
33#include <asm/kprobes.h> 33#include <asm/kprobes.h>
34#include <asm/sh_bios.h>
34 35
35#ifdef CONFIG_CPU_SH2 36#ifdef CONFIG_CPU_SH2
36# define TRAP_RESERVED_INST 4 37# define TRAP_RESERVED_INST 4
@@ -876,35 +877,10 @@ asmlinkage void do_exception_error(unsigned long r4, unsigned long r5,
876 die_if_kernel("exception", regs, ex); 877 die_if_kernel("exception", regs, ex);
877} 878}
878 879
879#if defined(CONFIG_SH_STANDARD_BIOS)
880void *gdb_vbr_vector;
881
882static inline void __init gdb_vbr_init(void)
883{
884 register unsigned long vbr;
885
886 /*
887 * Read the old value of the VBR register to initialise
888 * the vector through which debug and BIOS traps are
889 * delegated by the Linux trap handler.
890 */
891 asm volatile("stc vbr, %0" : "=r" (vbr));
892
893 gdb_vbr_vector = (void *)(vbr + 0x100);
894 printk("Setting GDB trap vector to 0x%08lx\n",
895 (unsigned long)gdb_vbr_vector);
896}
897#endif
898
899void __cpuinit per_cpu_trap_init(void) 880void __cpuinit per_cpu_trap_init(void)
900{ 881{
901 extern void *vbr_base; 882 extern void *vbr_base;
902 883
903#ifdef CONFIG_SH_STANDARD_BIOS
904 if (raw_smp_processor_id() == 0)
905 gdb_vbr_init();
906#endif
907
908 /* NOTE: The VBR value should be at P1 884 /* NOTE: The VBR value should be at P1
909 (or P2, virtural "fixed" address space). 885 (or P2, virtural "fixed" address space).
910 It's definitely should not in physical address. */ 886 It's definitely should not in physical address. */
@@ -959,6 +935,9 @@ void __init trap_init(void)
959 set_exception_table_vec(TRAP_UBC, break_point_trap); 935 set_exception_table_vec(TRAP_UBC, break_point_trap);
960#endif 936#endif
961 937
938 /* Save off the BIOS VBR, if there is one */
939 sh_bios_vbr_init();
940
962 /* Setup VBR for boot cpu */ 941 /* Setup VBR for boot cpu */
963 per_cpu_trap_init(); 942 per_cpu_trap_init();
964} 943}