More fixup in the signal area.

64-bit syscall cleanup.

Add emulation for some new FPU insns: conversion to 64-bit long int and
conditional moves.
This commit is contained in:
eeh 1998-09-22 02:48:42 +00:00
parent 5a0ae6393f
commit 1cc6223a9c
18 changed files with 689 additions and 519 deletions

View File

@ -1,4 +1,4 @@
# $NetBSD: Makefile,v 1.4 1998/09/13 16:02:47 eeh Exp $
# $NetBSD: Makefile,v 1.5 1998/09/22 02:48:42 eeh Exp $
# Makefile for sparc64 tags file and boot blocks
@ -10,6 +10,8 @@ ASPARC64= ../sparc64/sparc64/*.s
# Directories in which to place tags links
DSPARC64= conf dev fpu include sparc64
.include "../../kern/Make.tags.inc"
tags:
-ctags -wdtf ${TSPARC64} ${SSPARC64} ${COMM}
egrep "^ENTRY(.*)|^ALTENTRY(.*)" ${ASPARC64} | \
@ -18,8 +20,8 @@ tags:
sort -o ${TSPARC64} ${TSPARC64}
TAGS:
etags ${TSPARC64} ${SSPARC64} ${COMM} \
"--regex=/ENTRY(.*)|FUNC(.*)|SYSCALL(.*)/" ${ASPARC64}
etags ${SSPARC64} ${COMM} "--regex=/ENTRY(.*)/" \
"--regex=/FUNC(.*)/" "--regex=/SYSCALL(.*)/" ${ASPARC64}
links:
-for i in ${DSPARC64}; do \

View File

@ -1,4 +1,4 @@
/* $NetBSD: fpu.c,v 1.1.1.1 1998/06/20 04:58:51 eeh Exp $ */
/* $NetBSD: fpu.c,v 1.2 1998/09/22 02:48:42 eeh Exp $ */
/*
* Copyright (c) 1992, 1993
@ -245,7 +245,7 @@ fpu_execute(fe, instr)
union instr instr;
{
register struct fpn *fp;
register int opf, rs1, rs2, rd, type, mask, fsr, cx;
register int opf, rs1, rs2, rd, type, mask, fsr, cx, i, cond;
register struct fpstate *fs;
u_int space[4];
@ -267,6 +267,117 @@ fpu_execute(fe, instr)
fs = fe->fe_fpstate;
fe->fe_fsr = fs->fs_fsr & ~FSR_CX;
fe->fe_cx = 0;
/*
* Check to see if we're dealing with a fancy cmove and handle
* it first.
*/
if (instr.i_op3.i_op3 == IOP3_FPop2 && (opf&0xff0) != (FCMP&0xff0)) {
switch (opf >>= 2) {
case FMVFC0 >> 2:
cond = (fs->fs_fsr>>FSR_FCC_SHIFT)&FSR_FCC_MASK;
if (instr.i_fmovcc.i_cond != cond) return(0); /* success */
rs1 = fs->fs_regs[rs2];
goto mov;
case FMVFC1 >> 2:
cond = (fs->fs_fsr>>FSR_FCC1_SHIFT)&FSR_FCC_MASK;
if (instr.i_fmovcc.i_cond != cond) return(0); /* success */
rs1 = fs->fs_regs[rs2];
goto mov;
case FMVFC2 >> 2:
cond = (fs->fs_fsr>>FSR_FCC2_SHIFT)&FSR_FCC_MASK;
if (instr.i_fmovcc.i_cond != cond) return(0); /* success */
rs1 = fs->fs_regs[rs2];
goto mov;
case FMVFC3 >> 2:
cond = (fs->fs_fsr>>FSR_FCC3_SHIFT)&FSR_FCC_MASK;
if (instr.i_fmovcc.i_cond != cond) return(0); /* success */
rs1 = fs->fs_regs[rs2];
goto mov;
case FMVIC >> 2:
/* Presume we're curproc */
cond = (curproc->p_md.md_tf->tf_tstate>>TSTATE_CCR_SHIFT)&PSR_ICC;
if (instr.i_fmovcc.i_cond != cond) return(0); /* success */
rs1 = fs->fs_regs[rs2];
goto mov;
case FMVXC >> 2:
/* Presume we're curproc */
cond = (curproc->p_md.md_tf->tf_tstate>>(TSTATE_CCR_SHIFT+XCC_SHIFT))&PSR_ICC;
if (instr.i_fmovcc.i_cond != cond) return(0); /* success */
rs1 = fs->fs_regs[rs2];
goto mov;
case FMVRZ >> 2:
/* Presume we're curproc */
rs1 = instr.i_fmovr.i_rs1;
if (rs1 != 0 && (int64_t)curproc->p_md.md_tf->tf_global[rs1] != 0)
return (0); /* success */
rs1 = fs->fs_regs[rs2];
goto mov;
case FMVRLEZ >> 2:
/* Presume we're curproc */
rs1 = instr.i_fmovr.i_rs1;
if (rs1 != 0 && (int64_t)curproc->p_md.md_tf->tf_global[rs1] > 0)
return (0); /* success */
rs1 = fs->fs_regs[rs2];
goto mov;
case FMVRLZ >> 2:
/* Presume we're curproc */
rs1 = instr.i_fmovr.i_rs1;
if (rs1 == 0 || (int64_t)curproc->p_md.md_tf->tf_global[rs1] >= 0)
return (0); /* success */
rs1 = fs->fs_regs[rs2];
goto mov;
case FMVRNZ >> 2:
/* Presume we're curproc */
rs1 = instr.i_fmovr.i_rs1;
if (rs1 == 0 || (int64_t)curproc->p_md.md_tf->tf_global[rs1] == 0)
return (0); /* success */
rs1 = fs->fs_regs[rs2];
goto mov;
case FMVRGZ >> 2:
/* Presume we're curproc */
rs1 = instr.i_fmovr.i_rs1;
if (rs1 == 0 || (int64_t)curproc->p_md.md_tf->tf_global[rs1] <= 0)
return (0); /* success */
rs1 = fs->fs_regs[rs2];
goto mov;
case FMVRGEZ >> 2:
/* Presume we're curproc */
rs1 = instr.i_fmovr.i_rs1;
if (rs1 != 0 && (int64_t)curproc->p_md.md_tf->tf_global[rs1] < 0)
return (0); /* success */
rs1 = fs->fs_regs[rs2];
goto mov;
case FCMP >> 2:
fpu_explode(fe, &fe->fe_f1, type, rs1);
fpu_explode(fe, &fe->fe_f2, type, rs2);
fpu_compare(fe, 0);
goto cmpdone;
case FCMPE >> 2:
fpu_explode(fe, &fe->fe_f1, type, rs1);
fpu_explode(fe, &fe->fe_f2, type, rs2);
fpu_compare(fe, 1);
cmpdone:
/*
* The only possible exception here is NV; catch it
* early and get out, as there is no result register.
*/
cx = fe->fe_cx;
fsr = fe->fe_fsr | (cx << FSR_CX_SHIFT);
if (cx != 0) {
if (fsr & (FSR_NV << FSR_TEM_SHIFT)) {
fs->fs_fsr = (fsr & ~FSR_FTT) |
(FSR_TT_IEEE << FSR_FTT_SHIFT);
return (FPE);
}
fsr |= FSR_NV << FSR_AX_SHIFT;
}
fs->fs_fsr = fsr;
return (0);
default:
return (NOTFPU);
}
}
switch (opf >>= 2) {
default:
@ -283,7 +394,10 @@ fpu_execute(fe, instr)
case FABS >> 2:
rs1 = fs->fs_regs[rs2] & ~(1 << 31);
mov:
fs->fs_regs[rd] = rs1;
i = 1<<type;
fs->fs_regs[rd++] = rs1;
while (--i)
fs->fs_regs[rd++] = fs->fs_regs[++rs2];
fs->fs_fsr = fe->fe_fsr;
return (0); /* success */
@ -316,34 +430,6 @@ fpu_execute(fe, instr)
fp = fpu_div(fe);
break;
case FCMP >> 2:
fpu_explode(fe, &fe->fe_f1, type, rs1);
fpu_explode(fe, &fe->fe_f2, type, rs2);
fpu_compare(fe, 0);
goto cmpdone;
case FCMPE >> 2:
fpu_explode(fe, &fe->fe_f1, type, rs1);
fpu_explode(fe, &fe->fe_f2, type, rs2);
fpu_compare(fe, 1);
cmpdone:
/*
* The only possible exception here is NV; catch it
* early and get out, as there is no result register.
*/
cx = fe->fe_cx;
fsr = fe->fe_fsr | (cx << FSR_CX_SHIFT);
if (cx != 0) {
if (fsr & (FSR_NV << FSR_TEM_SHIFT)) {
fs->fs_fsr = (fsr & ~FSR_FTT) |
(FSR_TT_IEEE << FSR_FTT_SHIFT);
return (FPE);
}
fsr |= FSR_NV << FSR_AX_SHIFT;
}
fs->fs_fsr = fsr;
return (0);
case FSMULD >> 2:
case FDMULX >> 2:
if (type == FTYPE_EXT)
@ -354,13 +440,23 @@ fpu_execute(fe, instr)
fp = fpu_mul(fe);
break;
case FXTOS >> 2:
case FXTOD >> 2:
case FXTOQ >> 2:
type = FTYPE_LNG;
fpu_explode(fe, fp = &fe->fe_f1, type, rs2);
type = opf & 3; /* sneaky; depends on instruction encoding */
break;
case FTOS >> 2:
case FTOD >> 2:
case FTOX >> 2:
case FTOQ >> 2:
case FTOI >> 2:
fpu_explode(fe, fp = &fe->fe_f1, type, rs2);
type = opf & 3; /* sneaky; depends on instruction encoding */
break;
case FTOX >> 2:
fpu_explode(fe, fp = &fe->fe_f1, type, rs2);
type = FTYPE_LNG;
}
/*
@ -385,7 +481,7 @@ fpu_execute(fe, instr)
}
fs->fs_fsr = fsr;
fs->fs_regs[rd] = space[0];
if (type >= FTYPE_DBL) {
if (type >= FTYPE_DBL || type == FTYPE_LNG) {
fs->fs_regs[rd + 1] = space[1];
if (type > FTYPE_DBL) {
fs->fs_regs[rd + 2] = space[2];

View File

@ -1,4 +1,4 @@
/* $NetBSD: fpu_emu.h,v 1.1.1.1 1998/06/20 04:58:51 eeh Exp $ */
/* $NetBSD: fpu_emu.h,v 1.2 1998/09/22 02:48:42 eeh Exp $ */
/*
* Copyright (c) 1992, 1993
@ -90,6 +90,7 @@ struct fpn {
#define FP_NMANT 115 /* total bits in mantissa (incl g,r) */
#define FP_NG 2 /* number of low-order guard bits */
#define FP_LG ((FP_NMANT - 1) & 31) /* log2(1.0) for fp_mant[0] */
#define FP_LG2 ((FP_NMANT - 1) & 63) /* log2(1.0) for fp_mant[0] and fp_mant[1] */
#define FP_QUIETBIT (1 << (FP_LG - 1)) /* Quiet bit in NaNs (0.5) */
#define FP_1 (1 << FP_LG) /* 1.0 in fp_mant[0] */
#define FP_2 (1 << (FP_LG + 1)) /* 2.0 in fp_mant[0] */

View File

@ -1,4 +1,4 @@
/* $NetBSD: fpu_explode.c,v 1.1.1.1 1998/06/20 04:58:51 eeh Exp $ */
/* $NetBSD: fpu_explode.c,v 1.2 1998/09/22 02:48:43 eeh Exp $ */
/*
* Copyright (c) 1992, 1993
@ -105,6 +105,31 @@ fpu_itof(fp, i)
return (FPC_NUM);
}
/*
* 64-bit int -> fpn.
*/
int
fpu_xitof(fp, i)
register struct fpn *fp;
register u_int64_t i;
{
if (i == 0)
return (FPC_ZERO);
/*
* The value FP_1 represents 2^FP_LG, so set the exponent
* there and let normalization fix it up. Convert negative
* numbers to sign-and-magnitude. Note that this relies on
* fpu_norm()'s handling of `supernormals'; see fpu_subr.c.
*/
fp->fp_exp = FP_LG2;
*((int64_t*)fp->fp_mant) = (int64_t)i < 0 ? -i : i;
fp->fp_mant[2] = 0;
fp->fp_mant[3] = 0;
fpu_norm(fp);
return (FPC_NUM);
}
#define mask(nbits) ((1 << (nbits)) - 1)
/*
@ -220,13 +245,20 @@ fpu_explode(fe, fp, type, reg)
int type, reg;
{
register u_int s, *space;
u_int64_t l, *xspace;
space = &fe->fe_fpstate->fs_regs[reg];
xspace = &fe->fe_fpstate->fs_regs[reg & ~1];
s = space[0];
l = xspace[0];
fp->fp_sign = s >> 31;
fp->fp_sticky = 0;
switch (type) {
case FTYPE_LNG:
s = fpu_xitof(fp, l);
break;
case FTYPE_INT:
s = fpu_itof(fp, s);
break;

View File

@ -1,4 +1,4 @@
/* $NetBSD: fpu_extern.h,v 1.2 1998/09/05 15:28:09 christos Exp $ */
/* $NetBSD: fpu_extern.h,v 1.3 1998/09/22 02:48:43 eeh Exp $ */
/*-
* Copyright (c) 1995 The NetBSD Foundation, Inc.
@ -59,6 +59,7 @@ struct fpn *fpu_div __P((struct fpemu *));
/* fpu_explode.c */
int fpu_itof __P((struct fpn *, u_int));
int fpu_ixtof __P((struct fpn *, u_int64_t));
int fpu_stof __P((struct fpn *, u_int));
int fpu_dtof __P((struct fpn *, u_int, u_int ));
int fpu_xtof __P((struct fpn *, u_int, u_int , u_int , u_int ));
@ -66,6 +67,7 @@ void fpu_explode __P((struct fpemu *, struct fpn *, int, int ));
/* fpu_implode.c */
u_int fpu_ftoi __P((struct fpemu *, struct fpn *));
u_int fpu_ftoix __P((struct fpemu *, struct fpn *, u_int *));
u_int fpu_ftos __P((struct fpemu *, struct fpn *));
u_int fpu_ftod __P((struct fpemu *, struct fpn *, u_int *));
u_int fpu_ftox __P((struct fpemu *, struct fpn *, u_int *));

View File

@ -1,4 +1,4 @@
/* $NetBSD: fpu_implode.c,v 1.1.1.1 1998/06/20 04:58:51 eeh Exp $ */
/* $NetBSD: fpu_implode.c,v 1.2 1998/09/22 02:48:43 eeh Exp $ */
/*
* Copyright (c) 1992, 1993
@ -238,6 +238,57 @@ fpu_ftoi(fe, fp)
return (0x7fffffff + sign);
}
/*
* fpn -> extended int (high bits of int value returned as return value).
*
* N.B.: this conversion always rounds towards zero (this is a peculiarity
* of the SPARC instruction set).
*/
u_int
fpu_ftoxi(fe, fp, res)
struct fpemu *fe;
register struct fpn *fp;
u_int *res;
{
register u_int64_t i;
register int sign, exp;
sign = fp->fp_sign;
switch (fp->fp_class) {
case FPC_ZERO:
res[1] = 0;
return (0);
case FPC_NUM:
/*
* If exp >= 2^64, overflow. Otherwise shift value right
* into last mantissa word (this will not exceed 0xffffffffffffffff),
* shifting any guard and round bits out into the sticky
* bit. Then ``round'' towards zero, i.e., just set an
* inexact exception if sticky is set (see round()).
* If the result is > 0x8000000000000000, or is positive and equals
* 0x8000000000000000, overflow; otherwise the last fraction word
* is the result.
*/
if ((exp = fp->fp_exp) >= 64)
break;
/* NB: the following includes exp < 0 cases */
if (fpu_shr(fp, FP_NMANT - 1 - exp) != 0)
fe->fe_cx |= FSR_NX;
i = (fp->fp_mant[2]<<32)|fp->fp_mant[3];
if (i >= ((u_int64_t)0x8000000000000000LL + sign))
break;
return (sign ? -i : i);
default: /* Inf, qNaN, sNaN */
break;
}
/* overflow: replace any inexact exception with invalid */
fe->fe_cx = (fe->fe_cx & ~FSR_NX) | FSR_NV;
return (0x7fffffffffffffffLL + sign);
}
/*
* fpn -> single (32 bit single returned as return value).
* We assume <= 29 bits in a single-precision fraction (1.f part).
@ -457,6 +508,10 @@ fpu_implode(fe, fp, type, space)
switch (type) {
case FTYPE_LNG:
space[0] = fpu_ftoxi(fe, fp, space);
break;
case FTYPE_INT:
space[0] = fpu_ftoi(fe, fp);
break;

View File

@ -1,4 +1,4 @@
/* $NetBSD: frame.h,v 1.4 1998/09/07 23:46:26 eeh Exp $ */
/* $NetBSD: frame.h,v 1.5 1998/09/22 02:48:43 eeh Exp $ */
/*
* Copyright (c) 1992, 1993
@ -99,17 +99,15 @@ struct frame64 {
/*
* SVR4 reserves a bunch of extra stuff.
*/
int64_t fr_argd[6]; /* `arg dump area' (lunacy) */
int64_t fr_argx[1]; /* arg extension (args 7..n; variable size) */
int64_t fr_argd[6]; /* `register save area' (lunacy) */
int64_t fr_argx[0]; /* arg extension (args 7..n; variable size) */
};
#endif
#define v9next_frame(f) ((struct frame64*)(f->fr_fp+BIAS))
/*
* CC64FSZ (C Compiler 64-bit Frame SiZe) is the size of a stack frame used
* by the compiler in 64-bit mode. It is (16+1+6)*8; space for 8 ins, 8 outs,
* one "hidden parameter", and 6 extended words where the callee can save its
* arguments.
* by the compiler in 64-bit mode. It is (16)*8; space for 8 ins, 8 outs.
*/
#define CC64FSZ 176
#define STACK_ALIGN64 16

View File

@ -1,4 +1,4 @@
/* $NetBSD: instr.h,v 1.1.1.1 1998/06/20 04:58:51 eeh Exp $ */
/* $NetBSD: instr.h,v 1.2 1998/09/22 02:48:43 eeh Exp $ */
/*
* Copyright (c) 1992, 1993
@ -257,6 +257,52 @@ union instr {
u_int i_rs2:5; /* source register 2 */
} i_opf;
/*
* Format 4 instructions (movcc, fmovr, fmovcc, and tcc). The
* second-level decode almost always makes use of an `rd' and either
* `rs1' or `cond'.
*
* Beyond that, the low 14 bits may be broken up in one of three
* different ways, if at all:
* 1 bit of imm=0 + 8 bits of asi + 5 bits of rs2 [reg & mem]
* 1 bit of imm=1 + 13 bits of signed immediate [reg & mem]
* 9 bits of copressor `opf' opcode + 5 bits of rs2 [reg only] */
struct {
u_int :2; /* 10 */
u_int i_rd:5; /* destination register */
u_int i_op3:6; /* second-level decode */
u_int i_rs1:5; /* source register 1 */
u_int i_low14:14; /* varies */
} i_op4;
/*
* Move fp register on condition codes.
*/
struct {
u_int :2; /* 10 */
u_int i_rd:5; /* destination register */
u_int i_op3:6; /* second-level decode */
u_int :1;
u_int i_cond:4; /* condition */
u_int i_opf_cc:3; /* condition code register */
u_int i_opf_low:6; /* third level decode */
u_int i_rs2:5; /* source register */
} i_fmovcc;
/*
* Move fp register on integer register.
*/
struct {
u_int :2; /* 10 */
u_int i_rd:5; /* destination register */
u_int i_op3:6; /* second-level decode */
u_int i_rs1:5; /* source register 1 */
u_int :1;
u_int i_rcond:3; /* register condition */
u_int i_opf_low:6;
u_int i_rs2:5; /* source register 2 */
} i_fmovr;
};
/*
@ -347,14 +393,33 @@ union instr {
#define FCMPE 0x54
#define FSMULD 0x68
#define FDMULX 0x6c
#define FTOX 0x80
#define FXTOS 0x84
#define FXTOD 0x88
#define FXTOQ 0x8c
#define FTOS 0xc4
#define FTOD 0xc8
#define FTOX 0xcc
#define FTOQ 0xcc
#define FTOI 0xd0
/* These are in FPop2 space */
#define FMVFC0 0x00
#define FMVRZ 0x24
#define FMVFC1 0x40
#define FMVRLEZ 0x44
#define FMVRLZ 0x64
#define FMVFC2 0x80
#define FMVRNZ 0xa4
#define FMVFC3 0xc0
#define FMVRGZ 0xc4
#define FMVRGEZ 0xe4
#define FMVIC 0x100
#define FMVXC 0x180
/*
* FPU data types.
*/
#define FTYPE_LNG -1 /* data = 64-bit signed long integer */
#define FTYPE_INT 0 /* data = 32-bit signed integer */
#define FTYPE_SNG 1 /* data = 32-bit float */
#define FTYPE_DBL 2 /* data = 64-bit double */

View File

@ -1,4 +1,4 @@
/* $NetBSD: pmap.h,v 1.7 1998/09/13 16:02:48 eeh Exp $ */
/* $NetBSD: pmap.h,v 1.8 1998/09/22 02:48:43 eeh Exp $ */
/*-
* Copyright (C) 1995, 1996 Wolfgang Solfrank.
@ -119,14 +119,6 @@ struct pmap {
*/
paddr_t pm_physaddr; /* physical address of pm_segs */
int64_t *pm_segs;
/* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
/*
* Here's a really ugly hack: all processes now allocate
* one 8K page that is mapped little endian so we can do the
* syscall args properly.
*/
void *syscallargs;
/* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
};
/*

View File

@ -1,7 +1,8 @@
/* $NetBSD: setjmp.h,v 1.1.1.1 1998/06/20 04:58:52 eeh Exp $ */
/* $NetBSD: setjmp.h,v 1.2 1998/09/22 02:48:43 eeh Exp $ */
/*
* machine/setjmp.h: machine dependent setjmp-related information.
*/
#define _JBLEN 10 /* size, in longs, of a jmp_buf */
#define _JBLEN 14 /* size, in longs, of a jmp_buf */
/* A sigcontext is 10 longs */

View File

@ -1,4 +1,4 @@
/* $NetBSD: signal.h,v 1.4 1998/09/17 04:51:29 thorpej Exp $ */
/* $NetBSD: signal.h,v 1.5 1998/09/22 02:48:43 eeh Exp $ */
/*
* Copyright (c) 1992, 1993
@ -65,6 +65,7 @@ typedef int sig_atomic_t;
* All machines must have an sc_onstack and sc_mask.
*/
#if defined(__LIBC12_SOURCE__) || defined(_KERNEL)
/* Since we didn't start at 1.3, this is only for sparc32 code */
struct sigcontext13 {
int sc_onstack; /* sigstack state to restore */
int sc_mask; /* signal mask to restore (old style) */
@ -72,35 +73,22 @@ struct sigcontext13 {
int sc_sp; /* %sp to restore */
int sc_pc; /* pc to restore */
int sc_npc; /* npc to restore */
int sc_psr; /* psr to restore */
int sc_psr; /* pstate to restore */
int sc_g1; /* %g1 to restore */
int sc_o0; /* %o0 to restore */
};
#endif /* __LIBC12_SOURCE__ || _KERNEL */
struct sigcontext {
#ifdef _LP64
/* XXX Could just use register_t, but it's unsigned! */
long sc_onstack; /* sigstack state to restore */
long __sc_mask13; /* signal mask to restore (old style) */
long sc_sp; /* %sp to restore */
long sc_pc; /* pc to restore */
long sc_npc; /* npc to restore */
long sc_psr; /* psr to restore */
long sc_g1; /* %g1 to restore */
long sc_o0; /* %o0 to restore */
sigset_t sc_mask; /* signal mask to restore (new style) */
#else
int sc_onstack; /* sigstack state to restore */
int __sc_mask13; /* signal mask to restore (old style) */
/* begin machine dependent portion */
int sc_sp; /* %sp to restore */
int sc_pc; /* pc to restore */
int sc_npc; /* npc to restore */
int sc_psr; /* psr to restore */
int sc_g1; /* %g1 to restore */
int sc_o0; /* %o0 to restore */
long sc_sp; /* %sp to restore */
long sc_pc; /* pc to restore */
long sc_npc; /* npc to restore */
long sc_tstate; /* pstate to restore */
long sc_g1; /* %g1 to restore */
long sc_o0; /* %o0 to restore */
sigset_t sc_mask; /* signal mask to restore (new style) */
#endif /* _LP64 */
};
#else /* _LOCORE */
#define SC_SP_OFFSET 8

View File

@ -1,4 +1,4 @@
/* $NetBSD: db_interface.c,v 1.8 1998/09/09 02:48:15 eeh Exp $ */
/* $NetBSD: db_interface.c,v 1.9 1998/09/22 02:48:43 eeh Exp $ */
/*
* Mach Operating System
@ -124,6 +124,7 @@ void db_lock __P((db_expr_t, int, db_expr_t, char *));
void db_traptrace __P((db_expr_t, int, db_expr_t, char *));
void db_dump_buf __P((db_expr_t, int, db_expr_t, char *));
void db_dump_espcmd __P((db_expr_t, int, db_expr_t, char *));
void db_watch __P((db_expr_t, int, db_expr_t, char *));
static void db_dump_pmap __P((struct pmap*));
@ -140,6 +141,9 @@ kdb_kbd_trap(tf)
}
}
/* Flip this to turn on traptrace */
int traptrace_enabled = 0;
/*
* kdb_trap - field a TRACE or BPT trap
*/
@ -157,7 +161,9 @@ kdb_trap(type, tf)
} ts[5];
extern int savetstate(struct trapstate ts[]);
extern void restoretstate(int tl, struct trapstate ts[]);
extern int trap_trace_dis;
trap_trace_dis = 1;
fb_unblank();
switch (type) {
@ -170,10 +176,12 @@ kdb_trap(type, tf)
default:
printf("kernel trap %x: %s\n", type, trap_type[type & 0x1ff]);
if (db_recover != 0) {
#if 0
#ifdef _LP64
/* For now, don't get into infinite DDB trap loop */
printf("Faulted in DDB; going to OBP...\n");
OF_enter();
#endif
#endif
db_error("Faulted in DDB; continuing...\n");
OF_enter();
@ -182,10 +190,6 @@ kdb_trap(type, tf)
}
/* Should switch to kdb`s own stack here. */
{
extern int trap_trace_dis;
trap_trace_dis = 1;
}
write_all_windows();
ddb_regs.ddb_tf = *tf;
@ -238,10 +242,7 @@ kdb_trap(type, tf)
*(struct frame *)tf->tf_out[6] = ddb_regs.ddb_fr;
*tf = ddb_regs.ddb_tf;
#endif
{
extern int trap_trace_dis;
trap_trace_dis = 0;
}
trap_trace_dis = traptrace_enabled;
return (1);
}
@ -590,30 +591,30 @@ db_dump_pcb(addr, have_addr, count, modif)
if (have_addr)
pcb = (struct pcb*) addr;
db_printf("pcb@%x sp:%x pc:%x cwp:%d pil:%d nsaved:%x onfault:%p\nlastcall:%s\nfull windows:\n",
pcb, (int)pcb->pcb_sp, (int)pcb->pcb_pc, pcb->pcb_cwp,
db_printf("pcb@%x sp:%p pc:%p cwp:%d pil:%d nsaved:%x onfault:%p\nlastcall:%s\nfull windows:\n",
pcb, pcb->pcb_sp, pcb->pcb_pc, pcb->pcb_cwp,
pcb->pcb_pil, pcb->pcb_nsaved, pcb->pcb_onfault,
(pcb->lastcall)?pcb->lastcall:"Null");
for (i=0; i<pcb->pcb_nsaved; i++) {
db_printf("win %d: at %p:%p local, in\n", i,
pcb->pcb_rw[i+1].rw_in[6]);
db_printf("%8x:%8x %8x:%8x %8x:%8x %8x:%8x\n",
db_printf("%16lx %16lx %16lx %16lx\n",
pcb->pcb_rw[i].rw_local[0],
pcb->pcb_rw[i].rw_local[1],
pcb->pcb_rw[i].rw_local[2],
pcb->pcb_rw[i].rw_local[3]);
db_printf("%8x:%8x %8x:%8x %8x:%8x %8x:%8x\n",
db_printf("%16lx %16lx %16lx %16lx\n",
pcb->pcb_rw[i].rw_local[4],
pcb->pcb_rw[i].rw_local[5],
pcb->pcb_rw[i].rw_local[6],
pcb->pcb_rw[i].rw_local[7]);
db_printf("%8x:%8x %8x:%8x %8x:%8x %8x:%8x\n",
db_printf("%16lx %16lx %16lx %16lx\n",
pcb->pcb_rw[i].rw_in[0],
pcb->pcb_rw[i].rw_in[1],
pcb->pcb_rw[i].rw_in[2],
pcb->pcb_rw[i].rw_in[3]);
db_printf("%8x:%8x %8x:%8x %8x:%8x %8x:%8x\n",
db_printf("%16lx %16lx %16lx %16lx\n",
pcb->pcb_rw[i].rw_in[4],
pcb->pcb_rw[i].rw_in[5],
pcb->pcb_rw[i].rw_in[6],
@ -666,41 +667,90 @@ db_traptrace(addr, have_addr, count, modif)
extern struct traptrace {
unsigned short tl:3, ns:4, tt:9;
unsigned short pid;
int tstate;
int tsp;
int tpc;
u_int tstate;
u_int tsp;
u_int tpc;
} trap_trace[], trap_trace_end[];
int i, j;
if (have_addr) {
i=addr;
db_printf("%d:%d p:%d:%d tt:%x ts:%1x sp:%p tpc:%p ", i,
db_printf("%d:%d p:%d:%d tt:%x ts:%lx sp:%p tpc:%p ", i,
(int)trap_trace[i].tl, (int)trap_trace[i].pid,
(int)trap_trace[i].ns, (int)trap_trace[i].tt,
(int)trap_trace[i].tstate, (int)trap_trace[i].tsp,
(int)trap_trace[i].tpc);
db_printsym((int)trap_trace[i].tpc, DB_STGY_PROC);
(u_long)trap_trace[i].tstate, (u_long)trap_trace[i].tsp,
(u_long)trap_trace[i].tpc);
db_printsym((u_long)trap_trace[i].tpc, DB_STGY_PROC);
db_printf(": ");
if ((int)trap_trace[i].tpc && !(trap_trace[i].tpc&0x3)) {
db_disasm((int)trap_trace[i].tpc, 0);
if (trap_trace[i].tpc && !(trap_trace[i].tpc&0x3)) {
db_disasm((u_long)trap_trace[i].tpc, 0);
} else db_printf("\n");
return;
}
for (i=0; &trap_trace[i] < &trap_trace_end[0] ; i++) {
db_printf("%d:%d p:%d:%d tt:%x ts:%1x sp:%p tpc:%p ", i,
db_printf("%d:%d p:%d:%d tt:%x ts:%lx sp:%p tpc:%p ", i,
(int)trap_trace[i].tl, (int)trap_trace[i].pid,
(int)trap_trace[i].ns, (int)trap_trace[i].tt,
(int)trap_trace[i].tstate, (int)trap_trace[i].tsp,
(int)trap_trace[i].tpc);
db_printsym((int)trap_trace[i].tpc, DB_STGY_PROC);
(u_long)trap_trace[i].tstate, (u_long)trap_trace[i].tsp,
(u_long)trap_trace[i].tpc);
db_printsym((u_long)trap_trace[i].tpc, DB_STGY_PROC);
db_printf(": ");
if ((int)trap_trace[i].tpc && !(trap_trace[i].tpc&0x3)) {
db_disasm((int)trap_trace[i].tpc, 0);
if (trap_trace[i].tpc && !(trap_trace[i].tpc&0x3)) {
db_disasm((u_long)trap_trace[i].tpc, 0);
} else db_printf("\n");
}
}
/*
* Use physical or virtual watchpoint registers -- ugh
*/
void
db_watch(addr, have_addr, count, modif)
db_expr_t addr;
int have_addr;
db_expr_t count;
char *modif;
{
int phys = 0;
#define WATCH_VR (1L<<22)
#define WATCH_VW (1L<<21)
#define WATCH_PR (1L<<24)
#define WATCH_PW (1L<<23)
#define WATCH_PM (0xffffL<<33)
#define WATCH_VM (0xffffL<<25)
{
register char c, *cp = modif;
if (modif)
while ((c = *cp++) != 0)
if (c == 'p')
phys = 1;
}
if (have_addr) {
/* turn on the watchpoint */
int64_t tmp = ldxa(0, ASI_MCCR);
if (phys) {
tmp &= ~(WATCH_PM|WATCH_PR|WATCH_PW);
stxa(PHYSICAL_WATCHPOINT, ASI_DMMU, addr);
} else {
tmp &= ~(WATCH_VM|WATCH_VR|WATCH_VW);
stxa(VIRTUAL_WATCHPOINT, ASI_DMMU, addr);
}
stxa(0, ASI_MCCR, tmp);
} else {
/* turn off the watchpoint */
int64_t tmp = ldxa(0, ASI_MCCR);
if (phys) tmp &= ~(WATCH_PM);
else tmp &= ~(WATCH_VM);
stxa(0, ASI_MCCR, tmp);
}
}
#include <sys/buf.h>
void
@ -769,6 +819,7 @@ struct db_command sparc_db_command_table[] = {
{ "window", db_dump_window, 0, 0 },
{ "traptrace", db_traptrace, 0, 0 },
{ "uvmdump", db_uvmhistdump, 0, 0 },
{ "watch", db_watch, 0, 0 },
{ (char *)0, }
};

View File

@ -1,4 +1,4 @@
/* $NetBSD: db_trace.c,v 1.5 1998/09/11 00:16:59 eeh Exp $ */
/* $NetBSD: db_trace.c,v 1.6 1998/09/22 02:48:44 eeh Exp $ */
/*
* Mach Operating System
@ -263,7 +263,7 @@ db_dump_stack(addr, have_addr, count, modif)
db_printf("Window %x ", i);
db_print_window(frame - BIAS);
if (!INKERNEL(((struct frame64 *)(frame))))
copyin(((caddr_t)&((struct frame64 *)frame)->fr_fp)+4, &frame, sizeof(frame));
copyin(((caddr_t)&((struct frame64 *)frame)->fr_fp), &frame, sizeof(frame));
else
frame = ((struct frame64 *)frame)->fr_fp;
} else {

View File

@ -687,8 +687,8 @@ _C_LABEL(trapbase):
UTRAP(0x056); UTRAP(0x057); UTRAP(0x058); UTRAP(0x059); UTRAP(0x05a); UTRAP(0x05b)
UTRAP(0x05c); UTRAP(0x05d); UTRAP(0x05e); UTRAP(0x05f)
VTRAP(0x060, interrupt_vector); ! 060 = interrupt vector
UTRAP(T_PA_WATCHPT) ! 061 = physical address data watchpoint
UTRAP(T_VA_WATCHPT) ! 062 = virtual address data watchpoint
TRAP(T_PA_WATCHPT) ! 061 = physical address data watchpoint
TRAP(T_VA_WATCHPT) ! 062 = virtual address data watchpoint
UTRAP(T_ECCERR) ! We'll implement this one later
ufast_IMMU_miss: ! 063 = fast instr access MMU miss
TRACEFLT ! DEBUG
@ -913,8 +913,8 @@ kdatafault:
UTRAP(0x031) ! 031 = data MMU miss -- no MMU
VTRAP(T_DATA_ERROR, winfault) ! 032 = data fetch fault
VTRAP(T_DATA_PROT, winfault) ! 033 = data fetch fault
! TRAP(T_ALIGN) ! 034 = address alignment error -- we could fix it inline...
sir; nop; TA8 ! DEBUG -- trap all kernel alignment errors
TRAP(T_ALIGN) ! 034 = address alignment error -- we could fix it inline...
! sir; nop; TA8 ! DEBUG -- trap all kernel alignment errors
TRAP(T_LDDF_ALIGN) ! 035 = LDDF address alignment error -- we could fix it inline...
TRAP(T_STDF_ALIGN) ! 036 = STDF address alignment error -- we could fix it inline...
TRAP(T_PRIVACT) ! 037 = privileged action
@ -940,8 +940,8 @@ kdatafault:
UTRAP(0x056); UTRAP(0x057); UTRAP(0x058); UTRAP(0x059); UTRAP(0x05a); UTRAP(0x05b)
UTRAP(0x05c); UTRAP(0x05d); UTRAP(0x05e); UTRAP(0x05f)
VTRAP(0x060, interrupt_vector); ! 060 = interrupt vector
UTRAP(T_PA_WATCHPT) ! 061 = physical address data watchpoint
UTRAP(T_VA_WATCHPT) ! 062 = virtual address data watchpoint
TRAP(T_PA_WATCHPT) ! 061 = physical address data watchpoint
TRAP(T_VA_WATCHPT) ! 062 = virtual address data watchpoint
UTRAP(T_ECCERR) ! We'll implement this one later
kfast_IMMU_miss: ! 063 = fast instr access MMU miss
TRACEFLT ! DEBUG
@ -3130,7 +3130,7 @@ softtrap:
nop
sethi %hi(_C_LABEL(cpcb)), %g7
LDPTR [%g7 + %lo(_C_LABEL(cpcb))], %g7
set USPACE-CC64FSZ-TF_SIZE, %g5
set USPACE-CC64FSZ-TF_SIZE-STKB, %g5
add %g7, %g5, %g6
SET_SP_REDZONE(%g7, %g5)
stx %g1, [%g6 + CC64FSZ + STKB + TF_FAULT] ! Generate a new trapframe
@ -3446,25 +3446,25 @@ syscall_setup:
stx %g2, [%sp + CC64FSZ + STKB + TF_G + ( 2*8)]
rdpr %tstate, %g1
stx %g3, [%sp + CC64FSZ + STKB + TF_G + ( 3*8)]
rdpr %tnpc, %g3
rdpr %tnpc, %o3
stx %g4, [%sp + CC64FSZ + STKB + TF_G + ( 4*8)]
rd %y, %g4
rd %y, %o4
stx %g5, [%sp + CC64FSZ + STKB + TF_G + ( 5*8)]
stx %g6, [%sp + CC64FSZ + STKB + TF_G + ( 6*8)]
CHKPT(%g5,%g6,0x31)
wrpr %g0, 0, %tl ! return to tl=0
wrpr %g0, 0, %tl ! return to tl=0
stx %g7, [%sp + CC64FSZ + STKB + TF_G + ( 7*8)]
add %sp, CC64FSZ + STKB, %o1 ! (&tf)
add %sp, CC64FSZ + STKB, %o1 ! (&tf)
stx %g1, [%sp + CC64FSZ + STKB + TF_TSTATE]
stx %o2, [%sp + CC64FSZ + STKB + TF_PC]
stx %g3, [%sp + CC64FSZ + STKB + TF_NPC]
st %g4, [%sp + CC64FSZ + STKB + TF_Y]
stx %o3, [%sp + CC64FSZ + STKB + TF_NPC]
st %o4, [%sp + CC64FSZ + STKB + TF_Y]
rdpr %pil, %g5
stb %g5, [%sp + CC64FSZ + STKB + TF_PIL]
stb %g5, [%sp + CC64FSZ + STKB + TF_OLDPIL]
!! In the medium anywhere model %g4 points to the start of the data segment.
!! In our case we need to clear it before calling any C-code
clr %g4
@ -3905,6 +3905,13 @@ zshard:
* If there are any, reload them
*/
return_from_trap:
#ifdef DEBUG
!! Make sure we don't have pc == npc or we suck.
ldx [%sp + CC64FSZ + STKB + TF_PC], %g2
ldx [%sp + CC64FSZ + STKB + TF_NPC], %g3
cmp %g2, %g3
tz %icc, 1
#endif
#ifdef NOTDEF_DEBUG
mov %i6, %o1
save %sp, -CC64FSZ, %sp
@ -5315,7 +5322,9 @@ _C_LABEL(sigcode):
* enabled and dirty.
*/
rd %fprs, %l0
btst 1, %l0 ! test dl
btst 3, %l0 ! All clean?
bz,pt %icc, 2f
btst 1, %l0 ! test dl
bz,pt %icc, 1f
btst 2, %l0 ! test du
@ -5334,17 +5343,18 @@ _C_LABEL(sigcode):
inc BLOCK_SIZE, %l0
stda %f48, [%l0] ASI_BLK_COMMIT_P
2:
ldx [%fp + BIAS + 64], %o0 ! sig
ldx [%fp + BIAS + 64], %o1 ! code
ldx [%fp + BIAS + 76], %o3 ! arg3
call %g1 ! (*sa->sa_handler)(sig,code,scp,arg3)
add %fp, BIAS + 64 + 16, %o2 ! scp
lduw [%fp + BIAS + CC64FSZ], %o0 ! sig
lduw [%fp + BIAS + CC64FSZ + 4], %o1 ! code
call %g1 ! (*sa->sa_handler)(sig,code,scp)
add %fp, BIAS + CC64FSZ + 8, %o2 ! scp
/*
* Now that the handler has returned, re-establish all the state
* we just saved above, then do a sigreturn.
*/
btst 1, %l0 ! test dl
btst 3, %l0 ! All clean?
bz,pt %icc, 2f
btst 1, %l0 ! test dl
bz,pt %icc, 1f
btst 2, %l0 ! test du
@ -5355,7 +5365,7 @@ _C_LABEL(sigcode):
inc BLOCK_SIZE, %o0
ldda [%l0] ASI_BLK_P, %f16
1:
bz,pt %icc, 1f
bz,pt %icc, 2f
wr %l1, %g0, %y ! in any case, restore %y
inc BLOCK_SIZE, %o0
ldda [%l0] ASI_BLK_P, %f32
@ -5370,7 +5380,7 @@ _C_LABEL(sigcode):
mov %l7, %g7
restore %g0, SYS___sigreturn14, %g1 ! get registers back & set syscall #
add %sp, 64 + 16, %o0 ! compute scp
add %sp, BIAS + CC64FSZ + 8, %o0! compute scp
t ST_SYSCALL ! sigreturn(scp)
! sigreturn does not return unless it fails
mov SYS_exit, %g1 ! exit(errno)
@ -6597,12 +6607,12 @@ Lsw_scan:
ld [%g2 + %lo(_C_LABEL(whichqs))], %o3
#ifndef POPC
.globl ffstab
.globl _C_LABEL(__ffstab)
/*
* Optimized inline expansion of `which = ffs(whichqs) - 1';
* branches to idle if ffs(whichqs) was 0.
*/
set ffstab, %o2
set _C_LABEL(__ffstab), %o2
andcc %o3, 0xff, %o1 ! byte 0 zero?
bz,a,pn %icc, 1f ! yes, try byte 1
srl %o3, 8, %o0
@ -8599,7 +8609,7 @@ ENTRY(ienab_bic)
* The process switch code shares the table, so we just put the
* whole thing here.
*/
ffstab:
_C_LABEL(__ffstab):
.byte -24,1,2,1,3,1,2,1,4,1,2,1,3,1,2,1 /* 00-0f */
.byte 5,1,2,1,3,1,2,1,4,1,2,1,3,1,2,1 /* 10-1f */
.byte 6,1,2,1,3,1,2,1,4,1,2,1,3,1,2,1 /* 20-2f */
@ -8628,7 +8638,7 @@ ffstab:
* that ffstab[0] must be -24 so that ffs(0) will return 0.
*/
ENTRY(ffs)
set ffstab, %o2
set _C_LABEL(__ffstab), %o2
andcc %o0, 0xff, %o1 ! get low byte
bz,a 1f ! try again if 0
srl %o0, 8, %o0 ! delay slot, get ready for next byte
@ -8753,6 +8763,12 @@ ENTRY(random)
*
* If we used the %tick register we could go into the nano-seconds,
* and it must run for at least 10 years according to the v9 spec.
*
* For some insane reason timeval structure members are `long's so
* we need to change this code depending on the memory model.
*
* NB: if somehow time was 128-bit aligned we could use an atomic
* quad load to read it in and not bother de-bouncing it.
*/
#define MICROPERSEC (1000000)
@ -8763,12 +8779,6 @@ _C_LABEL(cpu_clockrate):
.xword 142857143 ! 1/7ns or ~ 143MHz Really should be 142857142.85
.text
#ifdef _LP64
/* Use %tick on 64-bit kernels 'cause the other stuff don't work */
#define TRY_TICK
#endif
ENTRY(microtime)
#ifdef TRY_TICK
rdpr %tick, %o1
@ -8786,19 +8796,19 @@ ENTRY(microtime)
stx %o1, [%o0]
1:
srlx %o1, 32, %o3 ! Isolate high word
st %o3, [%o0] ! and store it
STPTR %o3, [%o0] ! and store it
retl
st %o1, [%o0+4] ! Save time_t low word
STPTR %o1, [%o0+PTRSZ] ! Save time_t low word
#else
sethi %hi(timerreg_4u), %g3
sethi %hi(_C_LABEL(time)), %g2
LDPTR [%g3+%lo(timerreg_4u)], %g3 ! usec counter
2:
ld [%g2+%lo(_C_LABEL(time))], %o2 ! time.tv_sec & time.tv_usec
ld [%g2+%lo(_C_LABEL(time))+4], %o3 ! time.tv_sec & time.tv_usec
LDPTR [%g2+%lo(_C_LABEL(time))], %o2 ! time.tv_sec & time.tv_usec
LDPTR [%g2+%lo(_C_LABEL(time))+PTRSZ], %o3 ! time.tv_sec & time.tv_usec
ldx [%g3], %g7 ! Load usec timer valuse
ld [%g2+%lo(_C_LABEL(time))], %g1 ! see if time values changed
ld [%g2+%lo(_C_LABEL(time))+4], %g5 ! see if time values changed
LDPTR [%g2+%lo(_C_LABEL(time))], %g1 ! see if time values changed
LDPTR [%g2+%lo(_C_LABEL(time))+PTRSZ], %g5 ! see if time values changed
cmp %g1, %o2
bne 2b ! if time.tv_sec changed
cmp %g5, %o3
@ -8817,13 +8827,13 @@ ENTRY(microtime)
set 1000000, %g5 ! normalize usec value
cmp %o3, %g5
bl,a 4f
st %o2, [%o0] ! (should be able to std here)
STPTR %o2, [%o0] ! (should be able to std here)
add %o2, 1, %o2 ! overflow
sub %o3, %g5, %o3
st %o2, [%o0] ! (should be able to std here)
STPTR %o2, [%o0] ! (should be able to std here)
4:
retl
st %o3, [%o0+4]
STPTR %o3, [%o0+PTRSZ]
#endif
/*
* delay function

View File

@ -1,4 +1,4 @@
/* $NetBSD: machdep.c,v 1.17 1998/09/17 04:52:17 thorpej Exp $ */
/* $NetBSD: machdep.c,v 1.18 1998/09/22 02:48:44 eeh Exp $ */
/*-
* Copyright (c) 1996, 1997, 1998 The NetBSD Foundation, Inc.
@ -474,6 +474,8 @@ allocsys(v)
#define rwindow rwindow64
#define STACK_OFFSET BIAS
#define CPOUTREG(l,v) copyout(&(v), (l), sizeof(v))
#undef CCFSZ
#define CCFSZ CC64FSZ
#else
#define rwindow rwindow32
#define STACK_OFFSET 0
@ -623,6 +625,7 @@ sendsig(catcher, sig, mask, code)
psp->ps_sigstk.ss_size);
else
fp = (struct sigframe *)oldsp;
/* Allocate an aligned sigframe */
fp = (struct sigframe *)((long)(fp - 1) & ~0x0f);
#ifdef DEBUG
@ -660,13 +663,15 @@ sendsig(catcher, sig, mask, code)
*/
native_sigset_to_sigset13(mask, &frame.sf_sc.__sc_mask13);
#endif
/* Save register context. */
sf.sf_sc.sc_sp = (long)tf->tf_out[6];
sf.sf_sc.sc_pc = tf->tf_pc;
sf.sf_sc.sc_npc = tf->tf_npc;
sf.sf_sc.sc_psr = TSTATECCR_TO_PSR(tf->tf_tstate); /* XXX */
sf.sf_sc.sc_tstate = tf->tf_tstate; /* XXX */
sf.sf_sc.sc_g1 = tf->tf_global[1];
sf.sf_sc.sc_o0 = tf->tf_out[0];
/*
* Put the stack in a consistent state before we whack away
* at it. Note that write_user_windows may just dump the
@ -676,7 +681,7 @@ sendsig(catcher, sig, mask, code)
* joins seamlessly with the frame it was in when the signal occurred,
* so that the debugger and _longjmp code can back up through it.
*/
newsp = (struct rwindow *)((vaddr_t)fp - sizeof(struct rwindow));
newsp = (struct rwindow *)((vaddr_t)fp - CC64FSZ);
write_user_windows();
#ifdef DEBUG
if ((sigdebug & SDB_KSTACK))
@ -684,7 +689,7 @@ sendsig(catcher, sig, mask, code)
fp, &(((struct rwindow *)newsp)->rw_in[6]), (vaddr_t)tf->tf_out[6]);
#endif
if (rwindow_save(p) || copyout((caddr_t)&sf, (caddr_t)fp, sizeof sf) ||
#ifdef DEBUG
#ifdef NOT_DEBUG
copyin(oldsp, &tmpwin, sizeof(tmpwin)) || copyout(&tmpwin, newsp, sizeof(tmpwin)) ||
#endif
CPOUTREG(&(((struct rwindow *)newsp)->rw_in[6]), tf->tf_out[6])) {
@ -781,7 +786,7 @@ sys___sigreturn14(p, v, retval)
if ((vaddr_t)scp & 3 || (copyin((caddr_t)scp, &sc, sizeof sc) != 0))
#ifdef DEBUG
{
printf("sigreturn: copyin failed\n");
printf("sigreturn: copyin failed: scp=%p\n", scp);
Debugger();
return (EINVAL);
}
@ -807,7 +812,7 @@ sys___sigreturn14(p, v, retval)
return (EINVAL);
#endif
/* take only psr ICC field */
tf->tf_tstate = (int64_t)(tf->tf_tstate & ~TSTATE_CCR) | PSRCC_TO_TSTATE(scp->sc_psr);
tf->tf_tstate = (int64_t)(tf->tf_tstate & ~TSTATE_CCR) | (scp->sc_tstate & TSTATE_CCR);
tf->tf_pc = (int64_t)scp->sc_pc;
tf->tf_npc = (int64_t)scp->sc_npc;
tf->tf_global[1] = (int64_t)scp->sc_g1;

View File

@ -1,4 +1,4 @@
/* $NetBSD: pmap.c,v 1.15 1998/09/13 16:02:49 eeh Exp $ */
/* $NetBSD: pmap.c,v 1.16 1998/09/22 02:48:44 eeh Exp $ */
/* #define NO_VCACHE /* Don't forget the locked TLB in dostart */
#define HWREF
/* #define BOOT_DEBUG */
@ -1216,15 +1216,6 @@ pmap_pinit(pm)
printf("pmap_pinit: segs %p == %p\n", pm->pm_segs, (void*)page->phys_addr);
#endif
ctx_alloc(pm);
/* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
/* Allocate an empty page */
pm->syscallargs = malloc(NBPG, M_TEMP, M_WAITOK);
/* Make it little endian */
pseg_set(pmap_kernel(), pm->syscallargs, pseg_get(pmap_kernel(), pm->syscallargs)|TLB_IE, NULL);
/* Flush all mappings */
tsb[ptelookup_va(pm->syscallargs)].data.data = 0LL;
tlb_flush_pte(pm->syscallargs, 0);
/* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
}
#ifdef DEBUG
if (pmapdebug & PDB_CREATE)
@ -1277,17 +1268,6 @@ pmap_release(pm)
#endif
s=splimp();
/* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
if (pm->syscallargs) {
/* Make it big endian again */
pseg_set(pmap_kernel(), pm->syscallargs, pseg_get(pmap_kernel(), pm->syscallargs)&(~TLB_IE), NULL);
/* Flush all mappings */
tsb[ptelookup_va(pm->syscallargs)].data.data = 0LL;
tlb_flush_pte(pm->syscallargs, 0);
/* Give it back to the system */
free(pm->syscallargs, M_TEMP);
}
/* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
for(i=0; i<STSZ; i++)
if((pdir = (paddr_t *)ldxa(&pm->pm_segs[i], ASI_PHYS_CACHED))) {
for (k=0; k<PDSZ; k++) {

View File

@ -1,4 +1,4 @@
/* $NetBSD: sunos_machdep.c,v 1.2 1998/09/13 16:02:49 eeh Exp $ */
/* $NetBSD: sunos_machdep.c,v 1.3 1998/09/22 02:48:45 eeh Exp $ */
/*
* Copyright (c) 1995 Matthew R. Green
@ -52,6 +52,148 @@
#include <sys/syscallargs.h>
#include <compat/sunos/sunos_syscallargs.h>
#include <machine/frame.h>
#include <machine/cpu.h>
#ifdef DEBUG
int sunos_sigdebug = 0;
int sunos_sigpid = 0;
#define SDB_FOLLOW 0x01
#define SDB_KSTACK 0x02
#define SDB_FPSTATE 0x04
#define SDB_DDB 0x08
#endif
struct sunos_sigframe {
int sf_signo; /* signal number */
int sf_code; /* code */
struct sigcontext13 *sf_scp; /* SunOS user addr of sigcontext */
int sf_addr; /* SunOS compat, always 0 for now */
struct sigcontext13 sf_sc; /* actual sigcontext */
};
void
sunos_sendsig(catcher, sig, mask, code)
sig_t catcher;
int sig;
sigset_t *mask;
u_long code;
{
register struct proc *p = curproc;
register struct sigacts *psp = p->p_sigacts;
register struct sunos_sigframe *fp;
register struct trapframe *tf;
register int addr, onstack;
struct rwindow32 *kwin, *oldsp, *newsp;
struct sunos_sigframe sf;
extern char sigcode[], esigcode[];
#define szsigcode (esigcode - sigcode)
tf = p->p_md.md_tf;
/* Need to attempt to zero extend this 32-bit pointer */
oldsp = (struct rwindow32 *)(u_long)(u_int)tf->tf_out[6];
/*
* Compute new user stack addresses, subtract off
* one signal frame, and align.
*/
onstack =
(psp->ps_sigstk.ss_flags & (SS_DISABLE | SS_ONSTACK)) == 0 &&
(psp->ps_sigact[sig].sa_flags & SA_ONSTACK) != 0;
if (onstack)
fp = (struct sunos_sigframe *)(psp->ps_sigstk.ss_sp +
psp->ps_sigstk.ss_size);
else
fp = (struct sunos_sigframe *)oldsp;
fp = (struct sunos_sigframe *)((long)(fp - 1) & ~7);
#ifdef DEBUG
sunos_sigpid = p->p_pid;
if ((sunos_sigdebug & SDB_KSTACK) && p->p_pid == sunos_sigpid) {
printf("sendsig: %s[%d] sig %d newusp %p scp %p oldsp %p\n",
p->p_comm, p->p_pid, sig, fp, &fp->sf_sc, oldsp);
if (sunos_sigdebug & SDB_DDB) Debugger();
}
#endif
/*
* Now set up the signal frame. We build it in kernel space
* and then copy it out. We probably ought to just build it
* directly in user space....
*/
sf.sf_signo = sig;
sf.sf_code = code;
sf.sf_scp = (u_long)&fp->sf_sc;
sf.sf_addr = 0; /* XXX */
/*
* Build the signal context to be used by sigreturn.
*/
sf.sf_sc.sc_onstack = psp->ps_sigstk.ss_flags & SS_ONSTACK;
native_sigset_to_sigset13(mask, &sf.sf_sc.sc_mask);
sf.sf_sc.sc_sp = (long)oldsp;
sf.sf_sc.sc_pc = tf->tf_pc;
sf.sf_sc.sc_npc = tf->tf_npc;
sf.sf_sc.sc_psr = TSTATECCR_TO_PSR(tf->tf_tstate); /* XXX */
sf.sf_sc.sc_g1 = tf->tf_global[1];
sf.sf_sc.sc_o0 = tf->tf_out[0];
/*
* Put the stack in a consistent state before we whack away
* at it. Note that write_user_windows may just dump the
* registers into the pcb; we need them in the process's memory.
* We also need to make sure that when we start the signal handler,
* its %i6 (%fp), which is loaded from the newly allocated stack area,
* joins seamlessly with the frame it was in when the signal occurred,
* so that the debugger and _longjmp code can back up through it.
*/
newsp = (struct rwindow32 *)((long)fp - sizeof(struct rwindow32));
write_user_windows();
#ifdef DEBUG
if ((sunos_sigdebug & SDB_KSTACK))
printf("sendsig: saving sf to %p, setting stack pointer %p to %p\n",
fp, &(((union rwindow *)newsp)->v8.rw_in[6]), oldsp);
#endif
kwin = (struct rwindow32 *)(((caddr_t)tf)-CCFSZ);
if (rwindow_save(p) ||
copyout((caddr_t)&sf, (caddr_t)fp, sizeof sf) ||
suword(&(((union rwindow *)newsp)->v8.rw_in[6]), (u_long)oldsp)) {
/*
* Process has trashed its stack; give it an illegal
* instruction to halt it in its tracks.
*/
#ifdef DEBUG
if ((sunos_sigdebug & SDB_KSTACK) && p->p_pid == sunos_sigpid)
printf("sendsig: window save or copyout error\n");
printf("sendsig: stack was trashed trying to send sig %d, sending SIGILL\n", sig);
if (sunos_sigdebug & SDB_DDB) Debugger();
#endif
sigexit(p, SIGILL);
/* NOTREACHED */
}
#ifdef DEBUG
if (sunos_sigdebug & SDB_FOLLOW) {
printf("sendsig: %s[%d] sig %d scp %p\n",
p->p_comm, p->p_pid, sig, &fp->sf_sc);
}
#endif
/*
* Arrange to continue execution at the code copied out in exec().
* It needs the function to call in %g1, and a new stack pointer.
*/
addr = (long)catcher; /* user does his own trampolining */
tf->tf_pc = addr;
tf->tf_npc = addr + 4;
tf->tf_out[6] = (u_int64_t)(u_int)(u_long)newsp;
#ifdef DEBUG
if ((sunos_sigdebug & SDB_KSTACK) && p->p_pid == sunos_sigpid) {
printf("sendsig: about to return to catcher %p thru %p\n",
catcher, addr);
if (sunos_sigdebug & SDB_DDB) Debugger();
}
#endif
}
int
sunos_sys_sigreturn(p, v, retval)
register struct proc *p;

View File

@ -1,4 +1,4 @@
/* $NetBSD: trap.c,v 1.16 1998/09/13 16:02:49 eeh Exp $ */
/* $NetBSD: trap.c,v 1.17 1998/09/22 02:48:45 eeh Exp $ */
/*
* Copyright (c) 1996
@ -141,7 +141,7 @@ extern int cold;
#define RW_64 0x1
#define RW_ERR 0x2
#define RW_FOLLOW 0x4
int rwindow_debug = RW_64|RW_ERR;
int rwindow_debug = RW_ERR;
#define TDB_ADDFLT 0x1
#define TDB_TXTFLT 0x2
#define TDB_TRAP 0x4
@ -499,6 +499,10 @@ trap(type, tstate, pc, tf)
#define ADVANCE (n = tf->tf_npc, tf->tf_pc = n, tf->tf_npc = n + 4)
#ifdef DEBUG
if (tf->tf_pc == tf->tf_npc) {
printf("trap: tpc %p == tnpc %p\n", tf->tf_pc, tf->tf_npc);
Debugger();
}
{
/* Check to make sure we're on the normal stack */
int* sp;
@ -563,6 +567,12 @@ trap(type, tstate, pc, tf)
return;
}
}
if (type == T_PA_WATCHPT || type == T_VA_WATCHPT) {
if (kdb_trap(type, tf)) {
/* DDB must turn off watchpoints or something */
return;
}
}
#endif
#ifdef DIAGNOSTIC
/*
@ -690,37 +700,6 @@ badtrap:
break;
}
#if 0
#define read_rw(src, dst) \
((src&1)?copyin((caddr_t)(src), (caddr_t)(dst), sizeof(struct rwindow32))\
:copyin((caddr_t)(src+BIAS), (caddr_t)(dst), sizeof(struct rwindow64)))
case T_RWRET:
/*
* T_RWRET is a window load needed in order to rett.
* It simply needs the window to which tf->tf_out[6]
* (%sp) points. There are no user or saved windows now.
* Copy the one from %sp into pcb->pcb_rw[0] and set
* nsaved to -1. If we decide to deliver a signal on
* our way out, we will clear nsaved.
*/
if (pcb->pcb_nsaved)
panic("trap T_RWRET 1");
#ifdef DEBUG
if (rwindow_debug&RW_FOLLOW)
printf("%s[%d]: rwindow: pcb<-stack: %lx\n",
p->p_comm, p->p_pid, tf->tf_out[6]);
printf("trap: T_RWRET sent!?!\n");
/* I don't think this is ever used */
Debugger();
#endif
if (read_rw(tf->tf_out[6], &pcb->pcb_rw[0]))
sigexit(p, SIGILL);
if (pcb->pcb_nsaved)
panic("trap T_RWRET 2");
pcb->pcb_nsaved = -1; /* mark success */
break;
#endif
case T_ALIGN:
case T_LDDF_ALIGN:
case T_STDF_ALIGN:
@ -986,6 +965,10 @@ data_access_fault(type, addr, pc, tf)
#endif
#ifdef DEBUG
if (tf->tf_pc == tf->tf_npc) {
printf("data_access_fault: tpc %p == tnpc %p\n", tf->tf_pc, tf->tf_npc);
Debugger();
}
if (protmmu || missmmu) {
extern int trap_trace_dis;
trap_trace_dis = 1;
@ -1206,6 +1189,10 @@ data_access_error(type, sfva, sfsr, afva, afsr, tf)
#endif
#if DEBUG
if (tf->tf_pc == tf->tf_npc) {
printf("data_access_error: tpc %p == tnpc %p\n", tf->tf_pc, tf->tf_npc);
Debugger();
}
if (protmmu || missmmu) {
extern int trap_trace_dis;
trap_trace_dis = 1;
@ -1452,6 +1439,10 @@ text_access_fault(type, pc, tf)
u_quad_t sticks;
#if DEBUG
if (tf->tf_pc == tf->tf_npc) {
printf("text_access_fault: tpc %p == tnpc %p\n", tf->tf_pc, tf->tf_npc);
Debugger();
}
if (protmmu || missmmu) {
extern int trap_trace_dis;
trap_trace_dis = 1;
@ -1586,6 +1577,10 @@ text_access_error(type, pc, sfsr, afva, afsr, tf)
#endif
#if DEBUG
if (tf->tf_pc == tf->tf_npc) {
printf("text_access_error: tpc %p == tnpc %p\n", tf->tf_pc, tf->tf_npc);
Debugger();
}
if (protmmu || missmmu) {
extern int trap_trace_dis;
trap_trace_dis = 1;
@ -1772,7 +1767,7 @@ syscall(code, tf, pc)
union args {
register32_t i[8];
register64_t l[8];
} args, *argsp = &args;
} args;
register_t rval[2];
u_quad_t sticks;
#ifdef DIAGNOSTIC
@ -1781,6 +1776,10 @@ syscall(code, tf, pc)
#ifdef DEBUG
write_user_windows();
if (tf->tf_pc == tf->tf_npc) {
printf("syscall: tpc %p == tnpc %p\n", tf->tf_pc, tf->tf_npc);
Debugger();
}
if ((trapdebug&TDB_NSAVED && cpcb->pcb_nsaved) || trapdebug&(TDB_SYSCALL|TDB_FOLLOW))
printf("%d syscall(%x, %x, %x)\n",
curproc?curproc->p_pid:-1, code, tf, pc);
@ -1865,7 +1864,6 @@ syscall(code, tf, pc)
callp += p->p_emul->e_nosys;
else if (tf->tf_out[6] & 1L) {
register64_t *argp;
argsp = p->p_vmspace->vm_map.pmap->syscallargs;
#ifndef _LP64
#ifdef DEBUG
printf("syscall(): 64-bit stack on a 32-bit kernel????\n");
@ -1874,44 +1872,55 @@ syscall(code, tf, pc)
#endif
/* 64-bit stack -- not really supported on 32-bit kernels */
callp += code;
#if 1
i = (long)callp->sy_argsize / sizeof(register64_t);
#else
i = callp->sy_narg; /* Why divide? */
#ifdef DEBUG
if (i != (long)callp->sy_argsize / sizeof(register64_t))
printf("syscall %s: narg=%hd, argsize=%hd, call=%p, argsz/reg64=%ld\n",
(code < 0 || code >= nsys)? "illegal syscall" : p->p_emul->e_syscallnames[code],
callp->sy_narg, callp->sy_argsize, callp->sy_call, (long)callp->sy_argsize / sizeof(register64_t));
#endif
if (i > nap) { /* usually false */
register64_t temp[6];
int j = 0;
#ifdef DEBUG
if (trapdebug&(TDB_SYSCALL|TDB_FOLLOW) || i>8)
if (trapdebug&(TDB_SYSCALL|TDB_FOLLOW) || i>8) {
printf("Args64 %d>%d -- need to copyin\n", i , nap);
}
#endif
if (i > 8)
panic("syscall nargs");
#if 0
/* Read the whole block in */
error = copyin((caddr_t)tf->tf_out[6] + BIAS +
offsetof(struct frame64, fr_argd),
offsetof(struct frame64, fr_argx),
(caddr_t)&temp, (i - nap) * sizeof(register64_t));
/* Copy each to the argument array */
for (j=0; nap+j < i; j++)
argsp->l[nap+j] = temp[j];
args.l[nap+j] = temp[j];
#else
/* Read the whole block in */
error = copyin((caddr_t)tf->tf_out[6] + BIAS +
offsetof(struct frame64, fr_argx),
(caddr_t)&args.l[nap], (i - nap) * sizeof(register64_t));
#endif
if (error) {
#ifdef KTRACE
if (KTRPOINT(p, KTR_SYSCALL))
ktrsyscall(p->p_tracep, code,
callp->sy_argsize, (register_t*)argsp->i);
callp->sy_argsize, (register_t*)args.l);
#endif
goto bad;
}
i = nap;
}
/* Need to convert from int64 to int32 or we lose */
for (argp = &argsp->l[0]; i--;)
*argp++ = *ap++;
/* It should be faster to do <=6 longword copies than call bcopy */
for (argp = &args.l[0]; i--;)
*argp++ = *ap++;
#ifdef DEBUG
if (trapdebug&(TDB_SYSCALL|TDB_FOLLOW)) {
for (i=0; i < (long)callp->sy_argsize / sizeof(register64_t); i++)
printf("arg[%d]=%x ", i, (long)(argsp->l[i]));
for (i=0; i < callp->sy_narg; i++)
printf("arg[%d]=%lx ", i, (long)(args.l[i]));
printf("\n");
}
if (trapdebug&(TDB_STOPCALL|TDB_SYSTOP)) {
@ -1923,6 +1932,13 @@ syscall(code, tf, pc)
register32_t *argp;
/* 32-bit stack */
callp += code;
#ifdef _LP64
#ifdef DEBUG
printf("syscall(): 32-bit stack on a 64-bit kernel????\n");
Debugger();
#endif
#endif
#if 1
i = (long)callp->sy_argsize / sizeof(register32_t);
#else
@ -1943,33 +1959,33 @@ syscall(code, tf, pc)
(caddr_t)&temp, (i - nap) * sizeof(register32_t));
/* Copy each to the argument array */
for (j=0; nap+j < i; j++)
argsp->i[nap+j] = temp[j];
args.i[nap+j] = temp[j];
#ifdef DEBUG
if (trapdebug&(TDB_SYSCALL|TDB_FOLLOW)) {
int k;
printf("Copyin args of %d from %p:\n", j,
(caddr_t)(tf->tf_out[6] + offsetof(struct frame32, fr_argx)));
for (k=0; k<j; k++)
printf("arg %d = %p at %d val %p\n", k, (long)temp[k], nap+k, (long)argsp->i[nap+k]);
printf("arg %d = %p at %d val %p\n", k, (long)temp[k], nap+k, (long)args.i[nap+k]);
}
#endif
if (error) {
#ifdef KTRACE
if (KTRPOINT(p, KTR_SYSCALL))
ktrsyscall(p->p_tracep, code,
callp->sy_argsize, (register_t *)argsp->i);
callp->sy_argsize, (register_t *)args.i);
#endif
goto bad;
}
i = nap;
}
/* Need to convert from int64 to int32 or we lose */
for (argp = &argsp->i[0]; i--;)
for (argp = &args.i[0]; i--;)
*argp++ = *ap++;
#ifdef DEBUG
if (trapdebug&(TDB_SYSCALL|TDB_FOLLOW)) {
for (i=0; i < (long)callp->sy_argsize / sizeof(register32_t); i++)
printf("arg[%d]=%x ", i, (int)(argsp->i[i]));
printf("arg[%d]=%x ", i, (int)(args.i[i]));
printf("\n");
}
if (trapdebug&(TDB_STOPCALL|TDB_SYSTOP)) {
@ -1980,43 +1996,44 @@ syscall(code, tf, pc)
}
#ifdef KTRACE
if (KTRPOINT(p, KTR_SYSCALL))
ktrsyscall(p->p_tracep, code, callp->sy_argsize, (register_t *)argsp->i);
ktrsyscall(p->p_tracep, code, callp->sy_argsize, (register_t *)args.i);
#endif
rval[0] = 0;
rval[1] = tf->tf_out[1];
error = (*callp->sy_call)(p, argsp, rval);
error = (*callp->sy_call)(p, &args, rval);
switch (error) {
vaddr_t dest;
case 0:
/* Note: fork() does not return here in the child */
tf->tf_out[0] = rval[0];
tf->tf_out[1] = rval[1];
if (new) {
/* jmp %g2 (or %g7, deprecated) on success */
i = tf->tf_global[new & SYSCALL_G2RFLAG ? 2 : 7];
dest = tf->tf_global[new & SYSCALL_G2RFLAG ? 2 : 7];
#ifdef DEBUG
if (trapdebug&(TDB_SYSCALL|TDB_FOLLOW))
printf("syscall: return tstate=%x:%x new success to %p retval %x:%x\n",
(int)(tf->tf_tstate>>32), (int)(tf->tf_tstate),
i, rval[0], rval[1]);
printf("syscall: return tstate=%llx new success to %p retval %x:%x\n",
tf->tf_tstate, dest, rval[0], rval[1]);
#endif
if (i & 3) {
if (dest & 3) {
error = EINVAL;
goto bad;
}
} else {
/* old system call convention: clear C on success */
tf->tf_tstate &= ~(((int64_t)(ICC_C|XCC_C))<<TSTATE_CCR_SHIFT); /* success */
i = tf->tf_npc;
dest = tf->tf_npc;
#ifdef DEBUG
if (trapdebug&(TDB_SYSCALL|TDB_FOLLOW))
printf("syscall: return tstate=%x:%x old success to %p retval %x:%x\n",
(int)(tf->tf_tstate>>32), (int)(tf->tf_tstate),
i, rval[0], rval[1]);
printf("syscall: return tstate=%llx old success to %p retval %x:%x\n",
tf->tf_tstate, dest, rval[0], rval[1]);
if (trapdebug&(TDB_SYSCALL|TDB_FOLLOW))
printf("old pc=%p npc=%p dest=%p\n", tf->tf_pc, tf->tf_npc, dest);
#endif
}
tf->tf_pc = i;
tf->tf_npc = i + 4;
tf->tf_pc = dest;
tf->tf_npc = dest + 4;
break;
case ERESTART:
@ -2030,14 +2047,13 @@ syscall(code, tf, pc)
error = p->p_emul->e_errno[error];
tf->tf_out[0] = error;
tf->tf_tstate |= (((int64_t)(ICC_C|XCC_C))<<TSTATE_CCR_SHIFT); /* fail */
i = tf->tf_npc;
tf->tf_pc = i;
tf->tf_npc = i + 4;
dest = tf->tf_npc;
tf->tf_pc = dest;
tf->tf_npc = dest + 4;
#ifdef DEBUG
if (trapdebug&(TDB_SYSCALL|TDB_FOLLOW))
printf("syscall: return tstate=%x:%x fail %d to %p\n",
(int)(tf->tf_tstate>>32), (int)(tf->tf_tstate),
error, i);
printf("syscall: return tstate=%llx fail %d to %p\n",
tf->tf_tstate, error, dest);
#endif
break;
}
@ -2088,269 +2104,3 @@ child_return(p)
#endif
}
/*
* Code to handle alignment faults on the sparc. This is enabled by sending
* a fixalign trap.
*
* Such code is generated by compiling with cc -misalign
* on SunOS, but we don't have such a feature yet on our gcc.
*
* We don't do any funny ASIs, so don't expect endianess-inversion to work.
*/
#ifdef DEBUG_ALIGN
# define DPRINTF(a) uprintf a
#else
# define DPRINTF(a)
#endif
#define GPR(tf, i) ((int64_t *) &tf->tf_global)[i]
#define IPR(tf, i) ((int64_t *) tf->tf_out[6])[i - 16]
#define FPR(p, i) ((int32_t) p->p_md.md_fpstate->fs_regs[i])
static __inline int readgpreg __P((struct trapframe *, int, void *));
static __inline int readfpreg __P((struct proc *, int, void *));
static __inline int writegpreg __P((struct trapframe *, int, const void *));
static __inline int writefpreg __P((struct proc *, int, const void *));
static __inline int
readgpreg(tf, i, val)
struct trapframe *tf;
int i;
void *val;
{
int error = 0;
if (i == 0)
*(int64_t *) val = 0;
else if (i < 16)
*(int64_t *) val = GPR(tf, i);
else
error = copyin(&IPR(tf, i), val, sizeof(int64_t));
return error;
}
static __inline int
writegpreg(tf, i, val)
struct trapframe *tf;
int i;
const void *val;
{
int error = 0;
if (i == 0)
return error;
else if (i < 16)
GPR(tf, i) = *(int64_t *) val;
else
/* XXX: Fix copyout prototype */
error = copyout((caddr_t) val, &IPR(tf, i), sizeof(int64_t));
return error;
}
static __inline int
readfpreg(p, i, val)
struct proc *p;
int i;
void *val;
{
*(int32_t *) val = FPR(p, i);
return 0;
}
static __inline int
writefpreg(p, i, val)
struct proc *p;
int i;
const void *val;
{
FPR(p, i) = *(const int32_t *) val;
return 0;
}
static int
fixalign(p, tf)
struct proc *p;
struct trapframe *tf;
{
static u_char sizedef[] = { 0x4, 0xff, 0x2, 0x8 };
/*
* The following is not really a general instruction format;
* it is tailored to our needs
*/
union {
struct {
unsigned fmt:2; /* 31..30 - 2 bit format */
unsigned rd:5; /* 29..25 - 5 bit destination reg */
unsigned fl:1; /* 24..24 - 1 bit float flag */
unsigned op:1; /* 23..23 - 1 bit opcode */
unsigned sgn:1; /* 22..22 - 1 bit sign */
unsigned st:1; /* 21..21 - 1 bit load/store */
unsigned sz:2; /* 20..19 - 2 bit size register */
unsigned rs1:5; /* 18..14 - 5 bit source reg 1 */
unsigned imm:1; /* 13..13 - 1 bit immediate flag */
unsigned asi:8; /* 12.. 5 - 8 bit asi bits */
unsigned rs2:5; /* 4.. 0 - 5 bit source reg 2 */
} bits;
int32_t word;
} code;
union {
double d;
int64_t l;
int32_t i[2];
int16_t s[4];
int8_t c[8];
} data;
size_t size;
int64_t offs, addr;
int error;
/* fetch and check the instruction that caused the fault */
error = copyin((caddr_t) tf->tf_pc, &code.word, sizeof(code.word));
if (error != 0) {
DPRINTF(("fixalign: Bad instruction fetch\n"));
return EINVAL;
}
/* Only support format 3 */
if (code.bits.fmt != 3) {
DPRINTF(("fixalign: Not a load or store\n"));
return EINVAL;
}
/* Check operand size */
if ((size = sizedef[code.bits.sz]) == 0xff) {
DPRINTF(("fixalign: Bad operand size\n"));
return EINVAL;
}
write_user_windows();
if ((error = readgpreg(tf, code.bits.rs1, &addr)) != 0) {
DPRINTF(("fixalign: read rs1 %d\n", error));
return error;
}
/* Handle immediate operands */
if (code.bits.imm) {
offs = code.word & 0x1fff;
if (offs & 0x1000) /* Sign extend */
offs |= 0xffffe;
}
else {
if (code.bits.asi) {
DPRINTF(("fixalign: Illegal instruction\n"));
return EINVAL;
}
if ((error = readgpreg(tf, code.bits.rs2, &offs)) != 0) {
DPRINTF(("fixalign: read rs2 %d\n", error));
return error;
}
}
addr += offs;
#ifdef DEBUG_ALIGN
uprintf("memalign %x: %s%c%c %c%d, r%d, ", code.word,
code.bits.st ? "st" : "ld", "us"[code.bits.sgn],
"w*hd"[code.bits.sz], "rf"[code.bits.fl], code.bits.rd,
code.bits.rs1);
if (code.bits.imm)
uprintf("0x%x\n", offs);
else
uprintf("r%d\n", code.bits.rs2);
#endif
#ifdef DIAGNOSTIC
if (code.bits.fl && p != fpproc)
panic("fp align without being the FP owning process");
#endif
if (code.bits.st) {
if (code.bits.fl) {
savefpstate(p->p_md.md_fpstate);
error = readfpreg(p, code.bits.rd, &data.i[0]);
if (error)
return error;
if (size == 8) {
error = readfpreg(p, code.bits.rd + 1,
&data.i[1]);
if (error)
return error;
}
}
else {
error = readgpreg(tf, code.bits.rd, &data.l);
if (error)
return error;
if (size == 8 && !code.bits.sgn) {
int64_t temp;
/* std or stda -- get things in the right regs. */
temp = data.l;
data.i[0] = temp;
error = readgpreg(tf, code.bits.rd + 1, &temp);
data.i[1] = temp;
if (error)
return error;
}
}
if (size == 2)
return copyout(&data.s[1], (caddr_t) addr, size);
else
return copyout(&data.d, (caddr_t) addr, size);
}
else { /* load */
if (size == 2) {
error = copyin((caddr_t) addr, &data.s[1], size);
if (error)
return error;
/* Sign extend if necessary */
if (code.bits.sgn && (data.s[1] & 0x8000) != 0)
data.s[0] = ~0;
else
data.s[0] = 0;
}
else
error = copyin((caddr_t) addr, &data.d, size);
if (error)
return error;
if (code.bits.fl) {
error = writefpreg(p, code.bits.rd, &data.i[0]);
if (error)
return error;
if (size == 8) {
error = writefpreg(p, code.bits.rd + 1,
&data.i[1]);
if (error)
return error;
}
loadfpstate(p->p_md.md_fpstate);
}
else {
if (size == 8 && !code.bits.sgn) {
u_int64_t temp;
/* ldd or ldda -- get things in the right regs. */
temp = (unsigned int)data.i[0]; /* Do not sign extend */
error = writegpreg(tf, code.bits.rd, &temp);
temp = (unsigned int)data.i[1]; /* Do not sign extend */
if (!error)
error = writegpreg(tf, code.bits.rd + 1, &temp);
} else error = writegpreg(tf, code.bits.rd, &data.i[0]);
}
}
return error;
}