diff options
Diffstat (limited to 'arch/sh')
-rw-r--r-- | arch/sh/include/asm/sh_bios.h | 14 | ||||
-rw-r--r-- | arch/sh/kernel/machine_kexec.c | 8 | ||||
-rw-r--r-- | arch/sh/kernel/sh_bios.c | 37 | ||||
-rw-r--r-- | arch/sh/kernel/traps_32.c | 29 |
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 | |||
11 | extern void sh_bios_console_write(const char *buf, unsigned int len); | 11 | extern void sh_bios_console_write(const char *buf, unsigned int len); |
12 | extern void sh_bios_char_out(char ch); | 12 | extern void sh_bios_char_out(char ch); |
13 | extern void sh_bios_gdb_detach(void); | 13 | extern void sh_bios_gdb_detach(void); |
@@ -15,4 +15,14 @@ extern void sh_bios_gdb_detach(void); | |||
15 | extern void sh_bios_get_node_addr(unsigned char *node_addr); | 15 | extern void sh_bios_get_node_addr(unsigned char *node_addr); |
16 | extern void sh_bios_shutdown(unsigned int how); | 16 | extern void sh_bios_shutdown(unsigned int how); |
17 | 17 | ||
18 | extern void sh_bios_vbr_init(void); | ||
19 | extern void sh_bios_vbr_reload(void); | ||
20 | |||
21 | #else | ||
22 | |||
23 | static inline void sh_bios_vbr_init(void) { } | ||
24 | static 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 | ||
25 | typedef void (*relocate_new_kernel_t)(unsigned long indirection_page, | 26 | typedef 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 | ||
29 | extern const unsigned char relocate_new_kernel[]; | 30 | extern const unsigned char relocate_new_kernel[]; |
30 | extern const unsigned int relocate_new_kernel_size; | 31 | extern const unsigned int relocate_new_kernel_size; |
31 | extern void *gdb_vbr_vector; | ||
32 | extern void *vbr_base; | 32 | extern void *vbr_base; |
33 | 33 | ||
34 | void machine_shutdown(void) | 34 | void 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 | |||
59 | void *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 | */ | ||
66 | void 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 | */ | ||
85 | void 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) | ||
880 | void *gdb_vbr_vector; | ||
881 | |||
882 | static 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 | |||
899 | void __cpuinit per_cpu_trap_init(void) | 880 | void __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 | } |