Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 191d0d24 authored by Paul Mundt's avatar Paul Mundt
Browse files

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: default avatarPaul Mundt <lethal@linux-sh.org>
parent ee2760ea
Loading
Loading
Loading
Loading
+12 −2
Original line number Diff line number Diff line
#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);
@@ -15,4 +15,14 @@ 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 */
+2 −6
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@
#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,
@@ -28,7 +29,6 @@ typedef void (*relocate_new_kernel_t)(unsigned long indirection_page,

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)
@@ -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;
+37 −0
Original line number Diff line number Diff line
@@ -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"
		);
}
+4 −25
Original line number Diff line number Diff line
@@ -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
@@ -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.  */
@@ -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();
}