Module Name:    src
Committed By:   bouyer
Date:           Sat Aug 27 13:34:29 UTC 2011

Modified Files:
        src/sys/arch/evbmips/conf: files.evbmips
Added Files:
        src/sys/arch/mips/pmon: pmon.c pmon.h pmon32.S

Log Message:
Add pmon (firmware used by loongson2-based systems and maybe others) support,
from OpenBSD.
This includes code to call back pmon routines from a 64bit kernel,
as well code to read pmon arguments and variables.


To generate a diff of this commit:
cvs rdiff -u -r1.6 -r1.7 src/sys/arch/evbmips/conf/files.evbmips
cvs rdiff -u -r0 -r1.1 src/sys/arch/mips/pmon/pmon.c \
    src/sys/arch/mips/pmon/pmon.h src/sys/arch/mips/pmon/pmon32.S

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/arch/evbmips/conf/files.evbmips
diff -u src/sys/arch/evbmips/conf/files.evbmips:1.6 src/sys/arch/evbmips/conf/files.evbmips:1.7
--- src/sys/arch/evbmips/conf/files.evbmips:1.6	Tue Mar 20 08:52:01 2007
+++ src/sys/arch/evbmips/conf/files.evbmips	Sat Aug 27 13:34:29 2011
@@ -1,4 +1,4 @@
-#	$NetBSD: files.evbmips,v 1.6 2007/03/20 08:52:01 dyoung Exp $
+#	$NetBSD: files.evbmips,v 1.7 2011/08/27 13:34:29 bouyer Exp $
 
 # maxpartitions must be the first item in files.${ARCH}
 maxpartitions 16
@@ -20,4 +20,9 @@
 # Console glue.
 file	dev/cons.c
 
+# PMON suport
+defflag	PMON
+file	arch/mips/pmon/pmon.c		pmon
+file	arch/mips/pmon/pmon32.S		pmon
+
 include	"arch/evbmips/conf/majors.evbmips"

Added files:

Index: src/sys/arch/mips/pmon/pmon.c
diff -u /dev/null src/sys/arch/mips/pmon/pmon.c:1.1
--- /dev/null	Sat Aug 27 13:34:29 2011
+++ src/sys/arch/mips/pmon/pmon.c	Sat Aug 27 13:34:29 2011
@@ -0,0 +1,99 @@
+/*	$OpenBSD: pmon.c,v 1.4 2010/02/16 21:29:54 miod Exp $	*/
+
+/*
+ * Copyright (c) 2009 Miodrag Vallat.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/proc.h>
+
+#include <machine/cpu.h>
+#include <mips/pmon/pmon.h>
+
+int	pmon_argc;
+int32_t	*pmon_argv;
+int32_t	*pmon_envp;
+
+void
+pmon_init(int32_t argc, int32_t argv, int32_t envp, int32_t callvec)
+{
+	pmon_callvec = callvec;
+
+	pmon_argc = argc;
+	/* sign extend pointers */
+	pmon_argv = (int32_t *)(vaddr_t)argv;
+	pmon_envp = (int32_t *)(vaddr_t)envp;
+}
+
+const char *
+pmon_getarg(const int argno)
+{
+	if (argno < 0 || argno >= pmon_argc)
+		return NULL;
+
+	return (const char *)(vaddr_t)pmon_argv[argno];
+}
+
+const char *
+pmon_getenv(const char *var)
+{
+	int32_t *envptr = pmon_envp;
+	const char *envstr;
+	size_t varlen;
+
+	if (envptr == NULL)
+		return NULL;
+
+	varlen = strlen(var);
+	while (*envptr != 0) {
+		envstr = (const char *)(vaddr_t)*envptr;
+		/*
+		 * There is a PMON2000 bug, at least on Lemote Yeeloong,
+		 * which causes it to override part of the environment
+		 * pointers array with the environment data itself.
+		 *
+		 * This only happens on cold boot, and if the BSD kernel
+		 * is loaded without symbols (i.e. no option -k passed
+		 * to the boot command).
+		 *
+		 * Until a suitable workaround is found or the bug is
+		 * fixed, ignore broken environment information and
+		 * tell the user (in case this prevents us from finding
+		 * important information).
+		 */
+		if ((vaddr_t)envstr < (vaddr_t)MIPS_KSEG1_START ||
+		    (vaddr_t)envstr >= (vaddr_t)MIPS_KSEG2_START) {
+			printf("WARNING! CORRUPTED ENVIRONMENT!\n");
+			printf("Unable to search for %s.\n", var);
+#ifdef _STANDALONE
+			printf("If boot fails, power-cycle the machine.\n");
+#else
+			printf("If the kernel fails to identify the system"
+			    " type, please boot it again with `-k' option.\n");
+#endif
+
+			/* terminate environment for further calls */
+			*envptr = 0;
+			break;
+		}
+		if (strncmp(envstr, var, varlen) == 0 &&
+		    envstr[varlen] == '=')
+			return envstr + varlen + 1;
+		envptr++;
+	}
+
+	return NULL;
+}
Index: src/sys/arch/mips/pmon/pmon.h
diff -u /dev/null src/sys/arch/mips/pmon/pmon.h:1.1
--- /dev/null	Sat Aug 27 13:34:29 2011
+++ src/sys/arch/mips/pmon/pmon.h	Sat Aug 27 13:34:29 2011
@@ -0,0 +1,52 @@
+/*	$OpenBSD: pmon.h,v 1.2 2010/02/14 22:39:33 miod Exp $	*/
+
+/*
+ * Copyright (c) 2009 Miodrag Vallat.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef	_MACHINE_PMON_H_
+#define	_MACHINE_PMON_H_
+
+#if defined(_KERNEL) || defined(_STANDALONE)
+
+/*
+ * PMON2000 callvec definitions
+ */
+
+/* 32-bit compatible types */
+typedef	uint32_t	pmon_size_t;
+typedef	int32_t		pmon_ssize_t;
+typedef int64_t		pmon_off_t;
+
+int		pmon_open(const char *, int, ...);
+int		pmon_close(int);
+int		pmon_read(int, void *, pmon_size_t);
+pmon_ssize_t	pmon_write(int, const void *, pmon_size_t);
+pmon_off_t	pmon_lseek(int, pmon_off_t, int);
+int		pmon_printf(const char *, ...);
+void		pmon_cacheflush(void);
+char *		pmon_gets(char *);
+
+#define	PMON_MAXLN	256	/* internal gets() size limit */
+
+extern int32_t pmon_callvec;
+
+const char	*pmon_getarg(const int);
+const char	*pmon_getenv(const char *);
+void		 pmon_init(int32_t, int32_t, int32_t, int32_t);
+
+#endif	/* _KERNEL || _STANDALONE */
+
+#endif	/* _MACHINE_PMON_H_ */
Index: src/sys/arch/mips/pmon/pmon32.S
diff -u /dev/null src/sys/arch/mips/pmon/pmon32.S:1.1
--- /dev/null	Sat Aug 27 13:34:29 2011
+++ src/sys/arch/mips/pmon/pmon32.S	Sat Aug 27 13:34:29 2011
@@ -0,0 +1,100 @@
+/*	$NetBSD: pmon32.S,v 1.1 2011/08/27 13:34:29 bouyer Exp $ */
+/*	OpenBSD: pmon32.S,v 1.4 2010/02/18 18:53:33 miod Exp 	*/
+
+/*
+ * Copyright (c) 2009 Miodrag Vallat.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * Wrapper routines to invoke PMON2000 functions from 64-bit code.
+ *
+ * PMON is compiled as 64 bit code, using the gcc o64 ABI (similar to the o32
+ * ABI, but using 64 bit registers).
+ *
+ * As a result, only up to four arguments to functions will be passed through
+ * registers.  It's up to the caller to never invoke pmon_printf() with more
+ * than four arguments; other functions are not affected.
+ */
+
+#include <machine/param.h>
+#include <machine/asm.h>
+
+#ifndef _STANDALONE
+#include "assym.h"
+#endif
+
+	.set	mips3
+
+	.data
+	.globl	pmon_callvec
+pmon_callvec:
+	.word	0
+
+	.text
+#define PMON_CALLFRAME_SIZ (CALLFRAME_SIZ)
+/*
+ * Note that we need to provide a PMON_CALLFRAME_SIZ untouched area above sp,
+ * or we'll risk our stack being corrupted upon return.
+ */
+
+#define FRAMESZ(sz)     (((sz) + ALSK) & ~ALSK)
+
+#define	PMON_WRAP(name, index) \
+	NNON_LEAF(name, FRAMESZ(PMON_CALLFRAME_SIZ + 11 * SZREG),  ra); \
+	PTR_SUBU sp, sp, FRAMESZ(PMON_CALLFRAME_SIZ + 11 * SZREG); \
+	REG_S	ra, (10 * SZREG + PMON_CALLFRAME_SIZ)(sp); \
+	.mask	0xc0ff0000, (CALLFRAME_RA - FRAMESZ(PMON_CALLFRAME_SIZ + 10 * SZREG)); \
+	REG_S	s0, (0 * SZREG + PMON_CALLFRAME_SIZ)(sp); \
+	REG_S	s1, (1 * SZREG + PMON_CALLFRAME_SIZ)(sp); \
+	REG_S	s2, (2 * SZREG + PMON_CALLFRAME_SIZ)(sp); \
+	REG_S	s3, (3 * SZREG + PMON_CALLFRAME_SIZ)(sp); \
+	REG_S	s4, (4 * SZREG + PMON_CALLFRAME_SIZ)(sp); \
+	REG_S	s5, (5 * SZREG + PMON_CALLFRAME_SIZ)(sp); \
+	REG_S	s6, (6 * SZREG + PMON_CALLFRAME_SIZ)(sp); \
+	REG_S	s7, (7 * SZREG + PMON_CALLFRAME_SIZ)(sp); \
+	REG_S	s8, (8 * SZREG + PMON_CALLFRAME_SIZ)(sp); \
+	REG_S	t8, (9 * SZREG + PMON_CALLFRAME_SIZ)(sp); \
+	lw	t0, pmon_callvec; \
+	lw	t0, (index) * 4 (t0); \
+	jalr	t0; \
+	nop; \
+	REG_L	t8, (9 * SZREG + PMON_CALLFRAME_SIZ)(sp); \
+	REG_L	s8, (8 * SZREG + PMON_CALLFRAME_SIZ)(sp); \
+	REG_L	s7, (7 * SZREG + PMON_CALLFRAME_SIZ)(sp); \
+	REG_L	s6, (6 * SZREG + PMON_CALLFRAME_SIZ)(sp); \
+	REG_L	s5, (5 * SZREG + PMON_CALLFRAME_SIZ)(sp); \
+	REG_L	s4, (4 * SZREG + PMON_CALLFRAME_SIZ)(sp); \
+	REG_L	s3, (3 * SZREG + PMON_CALLFRAME_SIZ)(sp); \
+	REG_L	s2, (2 * SZREG + PMON_CALLFRAME_SIZ)(sp); \
+	REG_L	s1, (1 * SZREG + PMON_CALLFRAME_SIZ)(sp); \
+	REG_L	s0, (0 * SZREG + PMON_CALLFRAME_SIZ)(sp); \
+	REG_L	ra, (10 * SZREG + PMON_CALLFRAME_SIZ)(sp); \
+	PTR_ADDU sp, sp, FRAMESZ(PMON_CALLFRAME_SIZ + 11 * SZREG); \
+	jr	ra; \
+	nop; \
+	END(name)
+
+PMON_WRAP(pmon_printf, 5)
+PMON_WRAP(pmon_gets, 7)
+#ifdef _STANDALONE
+PMON_WRAP(pmon_open, 0)
+PMON_WRAP(pmon_close, 1)
+PMON_WRAP(pmon_read, 2)
+PMON_WRAP(pmon_lseek, 4)
+PMON_WRAP(pmon_cacheflush, 6)
+#endif
+#if 0	/* unused */
+PMON_WRAP(pmon_write, 3)
+#endif

Reply via email to