changeset 23:e7b9148156c4

arch: hopefully the rest of the SVC related code
author Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
date Wed, 27 Apr 2011 14:48:56 -0400
parents 5f3618fbf9ae
children f9ae64d35e81
files Makefile arch/svc.c arch/svcint.h include/svc.h include/svc_prog.h
diffstat 5 files changed, 132 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/Makefile	Wed Apr 27 13:00:16 2011 -0400
+++ b/Makefile	Wed Apr 27 14:48:56 2011 -0400
@@ -40,7 +40,7 @@
 	$(AR) rc $@ $^
 
 %.o: %.S
-	$(AS) -m64 -o $@ $<
+	$(CC) $(CFLAGS) -c -o $@ $<
 
 %.o: %.c
 	$(CC) $(CFLAGS) -include include/system.h -c -o $@ $<
--- a/arch/svc.c	Wed Apr 27 13:00:16 2011 -0400
+++ b/arch/svc.c	Wed Apr 27 14:48:56 2011 -0400
@@ -20,14 +20,29 @@
 	die();
 }
 
+void savecontext(struct psw *psw, u64 *regs)
+{
+	__builtin_memcpy(psw, PSA_OLD_SVC_PSW, sizeof(struct psw));
+	__builtin_memcpy(regs, PSA_GPRS, 16*sizeof(u64));
+}
+
+extern void *SVCINT;
 u64 _SVC_HANDLER;
 u64 _SVC_STACK;
 
 void set_svc_handler(u64(*f)(u64, u64, u64, u64), void *stack)
 {
+	struct psw psw;
+
 	if (((u64)stack) & 7)
 		die();
 
 	_SVC_HANDLER = (u64) f;
 	_SVC_STACK   = (u64) stack;
+
+	__builtin_memset(&psw, 0, sizeof(struct psw));
+	psw.ea = 1;
+	psw.ba = 1;
+	psw.ptr = (u64) &SVCINT;
+	__builtin_memcpy(PSA_NEW_SVC_PSW, &psw, sizeof(struct psw));
 }
--- a/arch/svcint.h	Wed Apr 27 13:00:16 2011 -0400
+++ b/arch/svcint.h	Wed Apr 27 14:48:56 2011 -0400
@@ -1,10 +1,16 @@
 #ifndef __SVCINT_H
 #define __SVCINT_H
 
+#define _PSA_OLD_SVC_PSW	0x140
+#define _PSA_NEW_SVC_PSW	0x1c0
+
 #define _PSA_SVC_ID	0x88
 #define _PSA_GPRS	0x200
 #define _PSA_PSW_TMP	0x280
 
+#define PSA_OLD_SVC_PSW		((struct psw*) _PSA_OLD_SVC_PSW)
+#define PSA_NEW_SVC_PSW		((struct psw*) _PSA_NEW_SVC_PSW)
+
 #define PSA_GPRS	((u64*) _PSA_GPRS)
 #define PSA_PSW_TMP	((struct psw*) _PSA_PSW_TMP)
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/include/svc.h	Wed Apr 27 14:48:56 2011 -0400
@@ -0,0 +1,10 @@
+#ifndef __SVC_H
+#define __SVC_H
+
+#include <psw.h>
+
+extern void setcontext(struct psw *psw, u64 *regs);
+extern void savecontext(struct psw *psw, u64 *regs);
+extern void set_svc_handler(u64(*f)(u64, u64, u64, u64), void *stack);
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/include/svc_prog.h	Wed Apr 27 14:48:56 2011 -0400
@@ -0,0 +1,100 @@
+#ifndef __SVC_PROG_H
+#define __SVC_PROG_H
+
+/* invokes the specified SVC with 0 to 4 args */
+
+#define invoke_svc0(n) ({ \
+				u64 _ret; \
+				asm volatile( \
+					"svc	%1\n" \
+					"lgr	%0,%%r2\n" \
+				: /* output */ \
+				  "=r" (_ret) \
+				: /* input */ \
+				  "i" (n) \
+				: /* clobber */ \
+				  "cc", "r2", "r3" \
+				); \
+				_ret; \
+			})
+
+#define invoke_svc1(n, a1) ({ \
+				u64 _ret; \
+				asm volatile( \
+					"lgr	%%r2,%2\n" \
+					"svc	%1\n" \
+					"lgr	%0,%%r2\n" \
+				: /* output */ \
+				  "=r" (_ret) \
+				: /* input */ \
+				  "i" (n) \
+				  "d" (a1) \
+				: /* clobber */ \
+				  "cc", "r2", "r3" \
+				); \
+				_ret; \
+			})
+
+#define invoke_svc2(n, a1, a2) ({ \
+				u64 _ret; \
+				asm volatile( \
+					"lgr	%%r2,%2\n" \
+					"lgr	%%r3,%3\n" \
+					"svc	%1\n" \
+					"lgr	%0,%%r2\n" \
+				: /* output */ \
+				  "=r" (_ret) \
+				: /* input */ \
+				  "i" (n) \
+				  "d" (a1) \
+				  "d" (a2) \
+				: /* clobber */ \
+				  "cc", "r2", "r3" \
+				); \
+				_ret; \
+			})
+
+#define invoke_svc3(n, a1, a2, a3) ({ \
+				u64 _ret; \
+				asm volatile( \
+					"lgr	%%r2,%2\n" \
+					"lgr	%%r3,%3\n" \
+					"lgr	%%r4,%4\n" \
+					"svc	%1\n" \
+					"lgr	%0,%%r2\n" \
+				: /* output */ \
+				  "=r" (_ret) \
+				: /* input */ \
+				  "i" (n) \
+				  "d" (a1) \
+				  "d" (a2) \
+				  "d" (a3) \
+				: /* clobber */ \
+				  "cc", "r2", "r3", "r4" \
+				); \
+				_ret; \
+			})
+
+#define invoke_svc4(n, a1, a2, a3, a4) ({ \
+				u64 _ret; \
+				asm volatile( \
+					"lgr	%%r2,%2\n" \
+					"lgr	%%r3,%3\n" \
+					"lgr	%%r4,%4\n" \
+					"lgr	%%r5,%5\n" \
+					"svc	%1\n" \
+					"lgr	%0,%%r2\n" \
+				: /* output */ \
+				  "=r" (_ret) \
+				: /* input */ \
+				  "i" (n) \
+				  "d" (a1) \
+				  "d" (a2) \
+				  "d" (a3) \
+				: /* clobber */ \
+				  "cc", "r2", "r3", "r4", "r5" \
+				); \
+				_ret; \
+			})
+
+#endif