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