Skip to content

Commit

Permalink
sh: Tidy up the sh bios VBR handling.
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Paul Mundt committed Jan 12, 2010
1 parent ee2760e commit 191d0d2
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 33 deletions.
14 changes: 12 additions & 2 deletions arch/sh/include/asm/sh_bios.h
Original file line number Diff line number Diff line change
@@ -1,18 +1,28 @@
#ifndef __ASM_SH_BIOS_H
#define __ASM_SH_BIOS_H

#ifdef CONFIG_SH_STANDARD_BIOS

/*
* Copyright (C) 2000 Greg Banks, Mitch Davis
* C API to interface to the standard LinuxSH BIOS
* usually from within the early stages of kernel boot.
*/


extern void sh_bios_console_write(const char *buf, unsigned int len);
extern void sh_bios_char_out(char ch);
extern void sh_bios_gdb_detach(void);

extern void sh_bios_get_node_addr(unsigned char *node_addr);
extern void sh_bios_shutdown(unsigned int how);

extern void sh_bios_vbr_init(void);
extern void sh_bios_vbr_reload(void);

#else

static inline void sh_bios_vbr_init(void) { }
static inline void sh_bios_vbr_reload(void) { }

#endif /* CONFIG_SH_STANDARD_BIOS */

#endif /* __ASM_SH_BIOS_H */
8 changes: 2 additions & 6 deletions arch/sh/kernel/machine_kexec.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,14 @@
#include <asm/mmu_context.h>
#include <asm/io.h>
#include <asm/cacheflush.h>
#include <asm/sh_bios.h>

typedef void (*relocate_new_kernel_t)(unsigned long indirection_page,
unsigned long reboot_code_buffer,
unsigned long start_address);

extern const unsigned char relocate_new_kernel[];
extern const unsigned int relocate_new_kernel_size;
extern void *gdb_vbr_vector;
extern void *vbr_base;

void machine_shutdown(void)
Expand Down Expand Up @@ -117,11 +117,7 @@ void machine_kexec(struct kimage *image)
kexec_info(image);
flush_cache_all();

#if defined(CONFIG_SH_STANDARD_BIOS)
asm volatile("ldc %0, vbr" :
: "r" (((unsigned long) gdb_vbr_vector) - 0x100)
: "memory");
#endif
sh_bios_vbr_reload();

/* now call it */
rnk = (relocate_new_kernel_t) reboot_code_buffer;
Expand Down
37 changes: 37 additions & 0 deletions arch/sh/kernel/sh_bios.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,3 +55,40 @@ void sh_bios_shutdown(unsigned int how)
{
sh_bios_call(BIOS_CALL_SHUTDOWN, how, 0, 0, 0);
}

void *gdb_vbr_vector = NULL;

/*
* Read the old value of the VBR register to initialise the vector
* through which debug and BIOS traps are delegated by the Linux trap
* handler.
*/
void sh_bios_vbr_init(void)
{
unsigned long vbr;

if (unlikely(gdb_vbr_vector))
return;

__asm__ __volatile__ ("stc vbr, %0" : "=r" (vbr));

gdb_vbr_vector = (void *)(vbr + 0x100);
printk(KERN_NOTICE "Setting GDB trap vector to %p\n", gdb_vbr_vector);
}

/**
* sh_bios_vbr_reload - Re-load the system VBR from the BIOS vector.
*
* This can be used by save/restore code to reinitialize the system VBR
* from the fixed BIOS VBR. A no-op if no BIOS VBR is known.
*/
void sh_bios_vbr_reload(void)
{
if (gdb_vbr_vector)
__asm__ __volatile__ (
"ldc %0, vbr"
:
: "r" (((unsigned long) gdb_vbr_vector) - 0x100)
: "memory"
);
}
29 changes: 4 additions & 25 deletions arch/sh/kernel/traps_32.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#include <asm/uaccess.h>
#include <asm/fpu.h>
#include <asm/kprobes.h>
#include <asm/sh_bios.h>

#ifdef CONFIG_CPU_SH2
# define TRAP_RESERVED_INST 4
Expand Down Expand Up @@ -876,35 +877,10 @@ asmlinkage void do_exception_error(unsigned long r4, unsigned long r5,
die_if_kernel("exception", regs, ex);
}

#if defined(CONFIG_SH_STANDARD_BIOS)
void *gdb_vbr_vector;

static inline void __init gdb_vbr_init(void)
{
register unsigned long vbr;

/*
* Read the old value of the VBR register to initialise
* the vector through which debug and BIOS traps are
* delegated by the Linux trap handler.
*/
asm volatile("stc vbr, %0" : "=r" (vbr));

gdb_vbr_vector = (void *)(vbr + 0x100);
printk("Setting GDB trap vector to 0x%08lx\n",
(unsigned long)gdb_vbr_vector);
}
#endif

void __cpuinit per_cpu_trap_init(void)
{
extern void *vbr_base;

#ifdef CONFIG_SH_STANDARD_BIOS
if (raw_smp_processor_id() == 0)
gdb_vbr_init();
#endif

/* NOTE: The VBR value should be at P1
(or P2, virtural "fixed" address space).
It's definitely should not in physical address. */
Expand Down Expand Up @@ -959,6 +935,9 @@ void __init trap_init(void)
set_exception_table_vec(TRAP_UBC, break_point_trap);
#endif

/* Save off the BIOS VBR, if there is one */
sh_bios_vbr_init();

/* Setup VBR for boot cpu */
per_cpu_trap_init();
}
Expand Down

0 comments on commit 191d0d2

Please sign in to comment.