Unverified Commit ce6c0a59 authored by Thomas Bogendoerfer's avatar Thomas Bogendoerfer Committed by Paul Burton
Browse files

MIPS: fw: arc: use call_o32 to call ARC prom from 64bit kernel



When using a 64bit kernel with generic spaces setup stack is
also placed in XKPYHS, which the 32bit PROM can't handle.
By using call_o32 for ARC_CALLs a stack placed in KSEG0 is used
when calling PROM.

Signed-off-by: default avatarThomas Bogendoerfer <tbogendoerfer@suse.de>
Signed-off-by: default avatarPaul Burton <paul.burton@mips.com>
Cc: Ralf Baechle <ralf@linux-mips.org>
Cc: James Hogan <jhogan@kernel.org>
Cc: linux-mips@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
parent d11646b5
Loading
Loading
Loading
Loading
+5 −0
Original line number Original line Diff line number Diff line
@@ -21,6 +21,11 @@ struct linux_romvec *romvec;
int prom_argc;
int prom_argc;
LONG *_prom_argv, *_prom_envp;
LONG *_prom_argv, *_prom_envp;


#if defined(CONFIG_64BIT) && defined(CONFIG_FW_ARC32)
/* stack for calling 32bit ARC prom */
u64 o32_stk[4096];
#endif

void __init prom_init(void)
void __init prom_init(void)
{
{
	PSYSTEM_PARAMETER_BLOCK pb = PROMBLOCK;
	PSYSTEM_PARAMETER_BLOCK pb = PROMBLOCK;
+30 −73
Original line number Original line Diff line number Diff line
@@ -12,6 +12,8 @@
#ifndef _ASM_SGIARCS_H
#ifndef _ASM_SGIARCS_H
#define _ASM_SGIARCS_H
#define _ASM_SGIARCS_H


#include <linux/kernel.h>

#include <asm/types.h>
#include <asm/types.h>
#include <asm/fw/arc/types.h>
#include <asm/fw/arc/types.h>


@@ -368,110 +370,65 @@ struct linux_smonblock {


#if defined(CONFIG_64BIT) && defined(CONFIG_FW_ARC32)
#if defined(CONFIG_64BIT) && defined(CONFIG_FW_ARC32)


#define __arc_clobbers							\
extern long call_o32(long vec, void *stack, ...);
	"$2", "$3" /* ... */, "$8", "$9", "$10", "$11",				\

	"$12", "$13", "$14", "$15", "$16", "$24", "$25", "$31"
extern u64 o32_stk[4096];
#define O32_STK	(&o32_stk[ARRAY_SIZE(o32_stk)])


#define ARC_CALL0(dest)							\
#define ARC_CALL0(dest)							\
({	long __res;							\
({	long __res;							\
	long __vec = (long) romvec->dest;				\
	long __vec = (long) romvec->dest;				\
	__asm__ __volatile__(						\
	__res = call_o32(__vec, O32_STK);				\
	"dsubu\t$29, 32\n\t"						\
	__res;								\
	"jalr\t%1\n\t"							\
	"daddu\t$29, 32\n\t"						\
	"move\t%0, $2"							\
	: "=r" (__res), "=r" (__vec)					\
	: "1" (__vec)							\
	: __arc_clobbers, "$4", "$5", "$6", "$7");			\
	(unsigned long) __res;						\
})
})


#define ARC_CALL1(dest, a1)						\
#define ARC_CALL1(dest, a1)						\
({	long __res;							\
({	long __res;							\
	register signed int __a1 __asm__("$4") = (int) (long) (a1);	\
	int  __a1 = (int) (long) (a1);					\
	long __vec = (long) romvec->dest;				\
	long __vec = (long) romvec->dest;				\
	__asm__ __volatile__(						\
	__res = call_o32(__vec, O32_STK, __a1);				\
	"dsubu\t$29, 32\n\t"						\
	__res;								\
	"jalr\t%1\n\t"							\
	"daddu\t$29, 32\n\t"						\
	"move\t%0, $2"							\
	: "=r" (__res), "=r" (__vec)					\
	: "1" (__vec), "r" (__a1)					\
	: __arc_clobbers, "$5", "$6", "$7");				\
	(unsigned long) __res;						\
})
})


#define ARC_CALL2(dest, a1, a2)						\
#define ARC_CALL2(dest, a1, a2)						\
({	long __res;							\
({	long __res;							\
	register signed int __a1 __asm__("$4") = (int) (long) (a1);	\
	int  __a1 = (int) (long) (a1);					\
	register signed int __a2 __asm__("$5") = (int) (long) (a2);	\
	int  __a2 = (int) (long) (a2);					\
	long __vec = (long) romvec->dest;				\
	long __vec = (long) romvec->dest;				\
	__asm__ __volatile__(						\
	__res = call_o32(__vec, O32_STK, __a1, __a2);			\
	"dsubu\t$29, 32\n\t"						\
	"jalr\t%1\n\t"							\
	"daddu\t$29, 32\n\t"						\
	"move\t%0, $2"							\
	: "=r" (__res), "=r" (__vec)					\
	: "1" (__vec), "r" (__a1), "r" (__a2)				\
	: __arc_clobbers, "$6", "$7");					\
	__res;								\
	__res;								\
})
})


#define ARC_CALL3(dest, a1, a2, a3)					\
#define ARC_CALL3(dest, a1, a2, a3)					\
({	long __res;							\
({	long __res;							\
	register signed int __a1 __asm__("$4") = (int) (long) (a1);	\
	int  __a1 = (int) (long) (a1);					\
	register signed int __a2 __asm__("$5") = (int) (long) (a2);	\
	int  __a2 = (int) (long) (a2);					\
	register signed int __a3 __asm__("$6") = (int) (long) (a3);	\
	int  __a3 = (int) (long) (a3);					\
	long __vec = (long) romvec->dest;				\
	long __vec = (long) romvec->dest;				\
	__asm__ __volatile__(						\
	__res = call_o32(__vec, O32_STK, __a1, __a2, __a3);		\
	"dsubu\t$29, 32\n\t"						\
	"jalr\t%1\n\t"							\
	"daddu\t$29, 32\n\t"						\
	"move\t%0, $2"							\
	: "=r" (__res), "=r" (__vec)					\
	: "1" (__vec), "r" (__a1), "r" (__a2), "r" (__a3)		\
	: __arc_clobbers, "$7");					\
	__res;								\
	__res;								\
})
})


#define ARC_CALL4(dest, a1, a2, a3, a4)					\
#define ARC_CALL4(dest, a1, a2, a3, a4)					\
({	long __res;							\
({	long __res;							\
	register signed int __a1 __asm__("$4") = (int) (long) (a1);	\
	int  __a1 = (int) (long) (a1);					\
	register signed int __a2 __asm__("$5") = (int) (long) (a2);	\
	int  __a2 = (int) (long) (a2);					\
	register signed int __a3 __asm__("$6") = (int) (long) (a3);	\
	int  __a3 = (int) (long) (a3);					\
	register signed int __a4 __asm__("$7") = (int) (long) (a4);	\
	int  __a4 = (int) (long) (a4);					\
	long __vec = (long) romvec->dest;				\
	long __vec = (long) romvec->dest;				\
	__asm__ __volatile__(						\
	__res = call_o32(__vec, O32_STK, __a1, __a2, __a3, __a4);	\
	"dsubu\t$29, 32\n\t"						\
	"jalr\t%1\n\t"							\
	"daddu\t$29, 32\n\t"						\
	"move\t%0, $2"							\
	: "=r" (__res), "=r" (__vec)					\
	: "1" (__vec), "r" (__a1), "r" (__a2), "r" (__a3),		\
	  "r" (__a4)							\
	: __arc_clobbers);						\
	__res;								\
	__res;								\
})
})


#define ARC_CALL5(dest, a1, a2, a3, a4, a5)				\
#define ARC_CALL5(dest, a1, a2, a3, a4, a5)				\
({	long __res;							\
({	long __res;							\
	register signed int __a1 __asm__("$4") = (int) (long) (a1);	\
	int  __a1 = (int) (long) (a1);					\
	register signed int __a2 __asm__("$5") = (int) (long) (a2);	\
	int  __a2 = (int) (long) (a2);					\
	register signed int __a3 __asm__("$6") = (int) (long) (a3);	\
	int  __a3 = (int) (long) (a3);					\
	register signed int __a4 __asm__("$7") = (int) (long) (a4);	\
	int  __a4 = (int) (long) (a4);					\
	register signed int __a5 = (int) (long) (a5);			\
	int  __a5 = (int) (long) (a5);					\
	long __vec = (long) romvec->dest;				\
	long __vec = (long) romvec->dest;				\
	__asm__ __volatile__(						\
	__res = call_o32(__vec, O32_STK, __a1, __a2, __a3, __a4, __a5);	\
	"dsubu\t$29, 32\n\t"						\
	"sw\t%7, 16($29)\n\t"						\
	"jalr\t%1\n\t"							\
	"daddu\t$29, 32\n\t"						\
	"move\t%0, $2"							\
	: "=r" (__res), "=r" (__vec)					\
	: "1" (__vec),							\
	  "r" (__a1), "r" (__a2), "r" (__a3), "r" (__a4),		\
	  "r" (__a5)							\
	: __arc_clobbers);						\
	__res;								\
	__res;								\
})
})