Delete device names from all the drivers. Move device inslude files from include/sys to include/machine directory. Only include files which have something useful for user layer (like special ioctls codes) should be placed into sys.
568 lines
19 KiB
C
568 lines
19 KiB
C
/*
|
|
* Copyright (c) 1986 Regents of the University of California.
|
|
* All rights reserved. The Berkeley software License Agreement
|
|
* specifies the terms and conditions for redistribution.
|
|
*/
|
|
#include <sys/param.h>
|
|
#include <sys/signalvar.h>
|
|
#include <sys/systm.h>
|
|
#include <sys/user.h>
|
|
#include <sys/proc.h>
|
|
#include <sys/vm.h>
|
|
#include <sys/tty.h>
|
|
#include <machine/uart.h>
|
|
#include <machine/usb_uart.h>
|
|
|
|
//#define TRACE_EXCEPTIONS
|
|
|
|
#ifdef POWER_ENABLED
|
|
extern void power_switch_check();
|
|
#endif
|
|
|
|
/*
|
|
* Copy of COP0 Debug register, saved by exception handler (in startup.S).
|
|
*/
|
|
int c0_debug;
|
|
|
|
volatile unsigned int ct_ticks = 0;
|
|
|
|
#ifdef TRACE_EXCEPTIONS
|
|
static void
|
|
print_args(narg, arg0, arg1, arg2, arg3, arg4, arg5)
|
|
{
|
|
void print_arg(val) {
|
|
if (val & 0xff000000)
|
|
printf("%08x", val);
|
|
else
|
|
printf("%u", val);
|
|
}
|
|
|
|
print_arg(arg0);
|
|
if (narg > 1) { printf(", "); print_arg(arg1); }
|
|
if (narg > 2) { printf(", "); print_arg(arg2); }
|
|
if (narg > 3) { printf(", "); print_arg(arg3); }
|
|
if (narg > 4) { printf(", "); print_arg(arg4); }
|
|
if (narg > 5) { printf(", "); print_arg(arg5); }
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
* Translate interrupt vector number to IRQ mask.
|
|
*/
|
|
static const unsigned mask_by_vector[] = {
|
|
(1 << PIC32_IRQ_CT), /* 0 - Core Timer Interrupt */
|
|
(1 << PIC32_IRQ_CS0), /* 1 - Core Software Interrupt 0 */
|
|
(1 << PIC32_IRQ_CS1), /* 2 - Core Software Interrupt 1 */
|
|
(1 << PIC32_IRQ_INT0), /* 3 - External Interrupt 0 */
|
|
(1 << PIC32_IRQ_T1), /* 4 - Timer1 */
|
|
(1 << PIC32_IRQ_IC1), /* 5 - Input Capture 1 */
|
|
(1 << PIC32_IRQ_OC1), /* 6 - Output Compare 1 */
|
|
(1 << PIC32_IRQ_INT1), /* 7 - External Interrupt 1 */
|
|
(1 << PIC32_IRQ_T2), /* 8 - Timer2 */
|
|
(1 << PIC32_IRQ_IC2), /* 9 - Input Capture 2 */
|
|
(1 << PIC32_IRQ_OC2), /* 10 - Output Compare 2 */
|
|
(1 << PIC32_IRQ_INT2), /* 11 - External Interrupt 2 */
|
|
(1 << PIC32_IRQ_T3), /* 12 - Timer3 */
|
|
(1 << PIC32_IRQ_IC3), /* 13 - Input Capture 3 */
|
|
(1 << PIC32_IRQ_OC3), /* 14 - Output Compare 3 */
|
|
(1 << PIC32_IRQ_INT3), /* 15 - External Interrupt 3 */
|
|
(1 << PIC32_IRQ_T4), /* 16 - Timer4 */
|
|
(1 << PIC32_IRQ_IC4), /* 17 - Input Capture 4 */
|
|
(1 << PIC32_IRQ_OC4), /* 18 - Output Compare 4 */
|
|
(1 << PIC32_IRQ_INT4), /* 19 - External Interrupt 4 */
|
|
(1 << PIC32_IRQ_T5), /* 20 - Timer5 */
|
|
(1 << PIC32_IRQ_IC5), /* 21 - Input Capture 5 */
|
|
(1 << PIC32_IRQ_OC5), /* 22 - Output Compare 5 */
|
|
(1 << PIC32_IRQ_SPI1E) | /* 23 - SPI1 */
|
|
(1 << PIC32_IRQ_SPI1TX) |
|
|
(1 << PIC32_IRQ_SPI1RX),
|
|
|
|
(1 << PIC32_IRQ_U1E) | /* 24 - UART1 */
|
|
(1 << PIC32_IRQ_U1RX) |
|
|
(1 << PIC32_IRQ_U1TX) |
|
|
(1 << PIC32_IRQ_SPI3E) | /* 24 - SPI3 */
|
|
(1 << PIC32_IRQ_SPI3TX) |
|
|
(1 << PIC32_IRQ_SPI3RX) |
|
|
(1 << PIC32_IRQ_I2C3B) | /* 24 - I2C3 */
|
|
(1 << PIC32_IRQ_I2C3S) |
|
|
(1 << PIC32_IRQ_I2C3M),
|
|
|
|
(1 << PIC32_IRQ_I2C1B) | /* 25 - I2C1 */
|
|
(1 << PIC32_IRQ_I2C1S) |
|
|
(1 << PIC32_IRQ_I2C1M),
|
|
(1 << (PIC32_IRQ_CN-32)), /* 26 - Input Change Interrupt */
|
|
(1 << (PIC32_IRQ_AD1-32)), /* 27 - ADC1 Convert Done */
|
|
(1 << (PIC32_IRQ_PMP-32)), /* 28 - Parallel Master Port */
|
|
(1 << (PIC32_IRQ_CMP1-32)), /* 29 - Comparator Interrupt */
|
|
(1 << (PIC32_IRQ_CMP2-32)), /* 30 - Comparator Interrupt */
|
|
|
|
(1 << (PIC32_IRQ_U3E-32)) | /* 31 - UART3 */
|
|
(1 << (PIC32_IRQ_U3E-32)) |
|
|
(1 << (PIC32_IRQ_U3E-32)) |
|
|
(1 << (PIC32_IRQ_SPI2E-32)) | /* 31 - SPI2 */
|
|
(1 << (PIC32_IRQ_SPI2TX-32)) |
|
|
(1 << (PIC32_IRQ_SPI2RX-32)) |
|
|
(1 << (PIC32_IRQ_I2C4B-32)) | /* 31 - I2C4 */
|
|
(1 << (PIC32_IRQ_I2C4S-32)) |
|
|
(1 << (PIC32_IRQ_I2C4M-32)),
|
|
|
|
(1 << (PIC32_IRQ_U2E-32)) | /* 32 - UART2 */
|
|
(1 << (PIC32_IRQ_U2RX-32)) |
|
|
(1 << (PIC32_IRQ_U2TX-32)) |
|
|
(1 << (PIC32_IRQ_SPI4E-32)) | /* 32 - SPI4 */
|
|
(1 << (PIC32_IRQ_SPI4TX-32)) |
|
|
(1 << (PIC32_IRQ_SPI4RX-32)) |
|
|
(1 << (PIC32_IRQ_I2C5B-32)) | /* 32 - I2C5 */
|
|
(1 << (PIC32_IRQ_I2C5S-32)) |
|
|
(1 << (PIC32_IRQ_I2C5M-32)),
|
|
|
|
(1 << (PIC32_IRQ_I2C2B-32)) | /* 33 - I2C2 */
|
|
(1 << (PIC32_IRQ_I2C2S-32)) |
|
|
(1 << (PIC32_IRQ_I2C2M-32)),
|
|
(1 << (PIC32_IRQ_FSCM-32)), /* 34 - Fail-Safe Clock Monitor */
|
|
(1 << (PIC32_IRQ_RTCC-32)), /* 35 - Real-Time Clock and Calendar */
|
|
(1 << (PIC32_IRQ_DMA0-32)), /* 36 - DMA Channel 0 */
|
|
(1 << (PIC32_IRQ_DMA1-32)), /* 37 - DMA Channel 1 */
|
|
(1 << (PIC32_IRQ_DMA2-32)), /* 38 - DMA Channel 2 */
|
|
(1 << (PIC32_IRQ_DMA3-32)), /* 39 - DMA Channel 3 */
|
|
(1 << (PIC32_IRQ_DMA4-32)), /* 40 - DMA Channel 4 */
|
|
(1 << (PIC32_IRQ_DMA5-32)), /* 41 - DMA Channel 5 */
|
|
(1 << (PIC32_IRQ_DMA6-32)), /* 42 - DMA Channel 6 */
|
|
(1 << (PIC32_IRQ_DMA7-32)), /* 43 - DMA Channel 7 */
|
|
(1 << (PIC32_IRQ_FCE-32)), /* 44 - Flash Control Event */
|
|
(1 << (PIC32_IRQ_USB-32)), /* 45 - USB */
|
|
(1 << (PIC32_IRQ_CAN1-32)), /* 46 - Control Area Network 1 */
|
|
(1 << (PIC32_IRQ_CAN2-32)), /* 47 - Control Area Network 2 */
|
|
(1 << (PIC32_IRQ_ETH-32)), /* 48 - Ethernet Controller */
|
|
(1 << (PIC32_IRQ_U4E-64)) | /* 49 - UART4 */
|
|
(1 << (PIC32_IRQ_U4RX-64)) |
|
|
(1 << (PIC32_IRQ_U4TX-64)),
|
|
(1 << (PIC32_IRQ_U6E-64)) | /* 50 - UART6 */
|
|
(1 << (PIC32_IRQ_U6RX-64)) |
|
|
(1 << (PIC32_IRQ_U6TX-64)),
|
|
(1 << (PIC32_IRQ_U5E-64)) | /* 51 - UART5 */
|
|
(1 << (PIC32_IRQ_U5RX-64)) |
|
|
(1 << (PIC32_IRQ_U5TX-64))
|
|
};
|
|
|
|
static void
|
|
dumpregs(frame)
|
|
int *frame;
|
|
{
|
|
unsigned int cause;
|
|
const char *code = 0;
|
|
unsigned *stacktop = (unsigned*) 0x80007ffc;
|
|
unsigned *p = (unsigned*) frame;
|
|
|
|
printf("\n*** 0x%08x: exception ", frame [FRAME_PC]);
|
|
|
|
cause = mips_read_c0_register(C0_CAUSE, 0);
|
|
switch (cause & CA_EXC_CODE) {
|
|
case CA_Int: code = "Interrupt"; break;
|
|
case CA_AdEL: code = "Address Load"; break;
|
|
case CA_AdES: code = "Address Save"; break;
|
|
case CA_IBE: code = "Bus fetch"; break;
|
|
case CA_DBE: code = "Bus load/store"; break;
|
|
case CA_Sys: code = "Syscall"; break;
|
|
case CA_Bp: code = "Breakpoint"; break;
|
|
case CA_RI: code = "Reserved Instruction"; break;
|
|
case CA_CPU: code = "Coprocessor Unusable"; break;
|
|
case CA_Ov: code = "Arithmetic Overflow"; break;
|
|
case CA_Tr: code = "Trap"; break;
|
|
}
|
|
if (code)
|
|
printf("'%s'\n", code);
|
|
else
|
|
printf("%d\n", cause >> 2 & 31);
|
|
|
|
switch (cause & CA_EXC_CODE) {
|
|
case CA_AdEL:
|
|
case CA_AdES:
|
|
printf("*** badvaddr = 0x%08x\n",
|
|
mips_read_c0_register(C0_BADVADDR, 0));
|
|
}
|
|
|
|
printf("*** stack frame at %8x\n", frame);
|
|
while (p <= stacktop) {
|
|
printf(" %8x", *p++);
|
|
if (p <= stacktop)
|
|
printf(" %8x", *p++);
|
|
if (p <= stacktop)
|
|
printf(" %8x", *p++);
|
|
if (p <= stacktop)
|
|
printf(" %8x", *p++);
|
|
printf("\n");
|
|
}
|
|
|
|
printf("*** registers:\n");
|
|
printf(" t0 = %8x s0 = %8x t8 = %8x lo = %8x\n",
|
|
frame [FRAME_R8], frame [FRAME_R16],
|
|
frame [FRAME_R24], frame [FRAME_LO]);
|
|
printf("at = %8x t1 = %8x s1 = %8x t9 = %8x hi = %8x\n",
|
|
frame [FRAME_R1], frame [FRAME_R9], frame [FRAME_R17],
|
|
frame [FRAME_R25], frame [FRAME_HI]);
|
|
printf("v0 = %8x t2 = %8x s2 = %8x status = %8x\n",
|
|
frame [FRAME_R2], frame [FRAME_R10],
|
|
frame [FRAME_R18], frame [FRAME_STATUS]);
|
|
printf("v1 = %8x t3 = %8x s3 = %8x cause = %8x\n",
|
|
frame [FRAME_R3], frame [FRAME_R11],
|
|
frame [FRAME_R19], cause);
|
|
printf("a0 = %8x t4 = %8x s4 = %8x gp = %8x epc = %8x\n",
|
|
frame [FRAME_R4], frame [FRAME_R12],
|
|
frame [FRAME_R20], frame [FRAME_GP], frame [FRAME_PC]);
|
|
printf("a1 = %8x t5 = %8x s5 = %8x sp = %8x\n",
|
|
frame [FRAME_R5], frame [FRAME_R13],
|
|
frame [FRAME_R21], frame [FRAME_SP]);
|
|
printf("a2 = %8x t6 = %8x s6 = %8x fp = %8x\n",
|
|
frame [FRAME_R6], frame [FRAME_R14],
|
|
frame [FRAME_R22], frame [FRAME_FP]);
|
|
printf("a3 = %8x t7 = %8x s7 = %8x ra = %8x\n",
|
|
frame [FRAME_R7], frame [FRAME_R15],
|
|
frame [FRAME_R23], frame [FRAME_RA]);
|
|
}
|
|
|
|
/*
|
|
* User mode flag added to cause code if exception is from user space.
|
|
*/
|
|
#define USER 1
|
|
|
|
/*
|
|
* Called from startup.S when a processor exception occurs.
|
|
* The argument is the array of registers saved on the system stack
|
|
* by the hardware and software during the exception processing.
|
|
*/
|
|
void
|
|
exception(frame)
|
|
int *frame;
|
|
{
|
|
register int psig;
|
|
time_t syst;
|
|
unsigned c, irq, status, cause, sp;
|
|
|
|
led_control(LED_KERNEL, 1);
|
|
if ((unsigned) frame < (unsigned) &u + sizeof(u)) {
|
|
dumpregs(frame);
|
|
panic("stack overflow");
|
|
/*NOTREACHED*/
|
|
}
|
|
/* Switch to kernel mode, keep interrupts disabled. */
|
|
status = frame [FRAME_STATUS];
|
|
mips_write_c0_register(C0_STATUS, 0,
|
|
status & ~(ST_UM | ST_EXL | ST_IE));
|
|
|
|
if (c0_debug & DB_DM) {
|
|
cause = CA_Bp;
|
|
c0_debug = 0;
|
|
// TODO: save DBD bit
|
|
} else {
|
|
cause = mips_read_c0_register(C0_CAUSE, 0);
|
|
cause &= CA_EXC_CODE;
|
|
}
|
|
if (USERMODE(status))
|
|
cause |= USER;
|
|
|
|
syst = u.u_ru.ru_stime;
|
|
|
|
switch (cause) {
|
|
|
|
/*
|
|
* Exception.
|
|
*/
|
|
default:
|
|
#ifdef UCB_METER
|
|
cnt.v_trap++;
|
|
#endif
|
|
switch (cause) {
|
|
default: /* Unknown exception: fatal kernel error */
|
|
dumpregs(frame);
|
|
panic("unexpected exception");
|
|
/*NOTREACHED*/
|
|
case CA_IBE + USER: /* Bus error, instruction fetch */
|
|
case CA_DBE + USER: /* Bus error, load or store */
|
|
printf("*** 0x%08x: %s: bus error\n", frame [FRAME_PC], u.u_comm);
|
|
psig = SIGBUS;
|
|
break;
|
|
case CA_RI + USER: /* Reserved instruction */
|
|
psig = SIGILL;
|
|
break;
|
|
case CA_Bp + USER: /* Breakpoint */
|
|
psig = SIGTRAP;
|
|
break;
|
|
case CA_Tr + USER: /* Trap */
|
|
psig = SIGIOT;
|
|
break;
|
|
case CA_CPU + USER: /* Coprocessor unusable */
|
|
psig = SIGEMT;
|
|
break;
|
|
case CA_Ov: /* Arithmetic overflow */
|
|
case CA_Ov + USER:
|
|
psig = SIGFPE;
|
|
break;
|
|
case CA_AdEL + USER: /* Address error, load or instruction fetch */
|
|
case CA_AdES + USER: /* Address error, store */
|
|
printf("*** 0x%08x: %s: bad address 0x%08x\n",
|
|
frame [FRAME_PC], u.u_comm, mips_read_c0_register(C0_BADVADDR, 0));
|
|
psig = SIGSEGV;
|
|
break;
|
|
}
|
|
/* Enable interrupts. */
|
|
mips_intr_enable();
|
|
break;
|
|
|
|
/*
|
|
* Hardware interrupt.
|
|
*/
|
|
case CA_Int: /* Interrupt */
|
|
case CA_Int + USER:
|
|
#ifdef UCB_METER
|
|
cnt.v_intr++;
|
|
#endif
|
|
/* Get the current irq number */
|
|
c = INTSTAT;
|
|
if ((c & PIC32_INTSTAT_SRIPL_MASK) == 0) {
|
|
//printf("*** unexpected interrupt: INTSTAT %08x\n", c);
|
|
goto ret;
|
|
}
|
|
irq = PIC32_INTSTAT_VEC(c);
|
|
|
|
|
|
/* Handle the interrupt. */
|
|
switch (irq) {
|
|
case PIC32_VECT_CT: /* Core Timer */
|
|
ct_ticks++;
|
|
/* Increment COMPARE register. */
|
|
IFSCLR(0) = 1 << PIC32_IRQ_CT;
|
|
c = mips_read_c0_register(C0_COMPARE, 0);
|
|
do {
|
|
c += (CPU_KHZ * 1000 / HZ + 1) / 2;
|
|
mips_write_c0_register(C0_COMPARE, 0, c);
|
|
} while ((int) (c - (unsigned)mips_read_c0_register(C0_COUNT, 0)) < 0);
|
|
hardclock((caddr_t) frame [FRAME_PC], status);
|
|
|
|
#ifdef POWER_ENABLED
|
|
power_switch_check();
|
|
#endif
|
|
|
|
#ifdef UARTUSB_ENABLED
|
|
/* Poll USB on every timer tick. */
|
|
usbintr(0);
|
|
#endif
|
|
break;
|
|
#ifdef UART1_ENABLED
|
|
case PIC32_VECT_U1: /* UART1 */
|
|
uartintr(makedev(UART_MAJOR, 0));
|
|
break;
|
|
#endif
|
|
#ifdef UART2_ENABLED
|
|
case PIC32_VECT_U2: /* UART2 */
|
|
uartintr(makedev(UART_MAJOR, 1));
|
|
break;
|
|
#endif
|
|
#ifdef UART3_ENABLED
|
|
case PIC32_VECT_U3: /* UART3 */
|
|
uartintr(makedev(UART_MAJOR, 2));
|
|
break;
|
|
#endif
|
|
#ifdef UART4_ENABLED
|
|
case PIC32_VECT_U4: /* UART4 */
|
|
uartintr(makedev(UART_MAJOR, 3));
|
|
break;
|
|
#endif
|
|
#ifdef UART5_ENABLED
|
|
case PIC32_VECT_U5: /* UART5 */
|
|
uartintr(makedev(UART_MAJOR, 4));
|
|
break;
|
|
#endif
|
|
#ifdef UART6_ENABLED
|
|
case PIC32_VECT_U6: /* UART6 */
|
|
uartintr(makedev(UART_MAJOR, 5));
|
|
break;
|
|
#endif
|
|
#ifdef UARTUSB_ENABLED
|
|
case PIC32_VECT_USB: /* USB */
|
|
IFSCLR(1) = 1 << (PIC32_IRQ_USB - 32);
|
|
usbintr(0);
|
|
break;
|
|
#endif
|
|
|
|
default:
|
|
/* Disable the irq, to avoid loops */
|
|
printf("*** irq %u\n", irq);
|
|
if (irq < PIC32_VECT_CN) {
|
|
IECCLR(0) = mask_by_vector [irq];
|
|
IFSCLR(0) = mask_by_vector [irq];
|
|
} else {
|
|
IECCLR(1) = mask_by_vector [irq];
|
|
IFSCLR(1) = mask_by_vector [irq];
|
|
}
|
|
break;
|
|
}
|
|
if ((cause & USER) && runrun) {
|
|
/* Need to switch processes: in user mode only.
|
|
* Enable interrupts first. */
|
|
// MADSCIFI start new code
|
|
//u.u_error = 0;
|
|
u.u_frame = frame;
|
|
u.u_code = frame [FRAME_PC]; /* For signal handler */
|
|
|
|
/* Check stack. */
|
|
sp = frame [FRAME_SP];
|
|
if (sp < u.u_procp->p_daddr + u.u_dsize) {
|
|
/* Process has trashed its stack; give it an illegal
|
|
* instruction violation to halt it in its tracks. */
|
|
panic("unexpected exception 2");
|
|
psig = SIGSEGV;
|
|
break;
|
|
}
|
|
if (u.u_procp->p_ssize < USER_DATA_END - sp) {
|
|
/* Expand stack. */
|
|
u.u_procp->p_ssize = USER_DATA_END - sp;
|
|
u.u_procp->p_saddr = sp;
|
|
u.u_ssize = u.u_procp->p_ssize;
|
|
}
|
|
// MADSCIFI end new code
|
|
|
|
mips_intr_enable();
|
|
goto out;
|
|
}
|
|
goto ret;
|
|
|
|
/*
|
|
* System call.
|
|
*/
|
|
case CA_Sys + USER: /* Syscall */
|
|
#ifdef UCB_METER
|
|
cnt.v_syscall++;
|
|
#endif
|
|
/* Enable interrupts. */
|
|
mips_intr_enable();
|
|
u.u_error = 0;
|
|
u.u_frame = frame;
|
|
u.u_code = frame [FRAME_PC]; /* For signal handler */
|
|
|
|
/* Check stack. */
|
|
sp = frame [FRAME_SP];
|
|
if (sp < u.u_procp->p_daddr + u.u_dsize) {
|
|
/* Process has trashed its stack; give it an illegal
|
|
* instruction violation to halt it in its tracks. */
|
|
psig = SIGSEGV;
|
|
break;
|
|
}
|
|
if (u.u_procp->p_ssize < USER_DATA_END - sp) {
|
|
/* Expand stack. */
|
|
u.u_procp->p_ssize = USER_DATA_END - sp;
|
|
u.u_procp->p_saddr = sp;
|
|
u.u_ssize = u.u_procp->p_ssize;
|
|
}
|
|
|
|
/* Original pc for restarting syscalls */
|
|
int opc = frame [FRAME_PC]; /* opc points at syscall */
|
|
frame [FRAME_PC] = opc + 3*NBPW; /* no errors - skip 2 next instructions */
|
|
|
|
const struct sysent *callp = &sysent[0];
|
|
int code = (*(u_int*) opc >> 6) & 0377; /* bottom 8 bits are index */
|
|
if (code < nsysent)
|
|
callp += code;
|
|
|
|
if (callp->sy_narg) {
|
|
u.u_arg[0] = frame [FRAME_R4]; /* $a0 */
|
|
u.u_arg[1] = frame [FRAME_R5]; /* $a1 */
|
|
u.u_arg[2] = frame [FRAME_R6]; /* $a2 */
|
|
u.u_arg[3] = frame [FRAME_R7]; /* $a3 */
|
|
if (callp->sy_narg > 4) {
|
|
unsigned addr = (frame [FRAME_SP] + 16) & ~3;
|
|
if (! baduaddr((caddr_t) addr))
|
|
u.u_arg[4] = *(unsigned*) addr;
|
|
}
|
|
if (callp->sy_narg > 5) {
|
|
unsigned addr = (frame [FRAME_SP] + 20) & ~3;
|
|
if (! baduaddr((caddr_t) addr))
|
|
u.u_arg[5] = *(unsigned*) addr;
|
|
}
|
|
}
|
|
#ifdef TRACE_EXCEPTIONS
|
|
printf("--- (%u)syscall: %s (", u.u_procp->p_pid,
|
|
syscallnames [code >= nsysent ? 0 : code]);
|
|
if (callp->sy_narg > 0)
|
|
print_args(callp->sy_narg, u.u_arg[0], u.u_arg[1],
|
|
u.u_arg[2], u.u_arg[3], u.u_arg[4], u.u_arg[5]);
|
|
printf(") at %08x\n", opc);
|
|
#endif
|
|
u.u_rval = 0;
|
|
if (setjmp(&u.u_qsave) == 0) {
|
|
(*callp->sy_call)();
|
|
}
|
|
switch (u.u_error) {
|
|
case 0:
|
|
#ifdef TRACE_EXCEPTIONS
|
|
printf(" (%u)syscall returned %u\n", u.u_procp->p_pid, u.u_rval);
|
|
#endif
|
|
frame [FRAME_R2] = u.u_rval; /* $v0 - result */
|
|
break;
|
|
case ERESTART:
|
|
#ifdef TRACE_EXCEPTIONS
|
|
printf(" (%u)syscall restarted at %#x\n", u.u_procp->p_pid, opc);
|
|
#endif
|
|
frame [FRAME_PC] = opc; /* return to syscall */
|
|
break;
|
|
case EJUSTRETURN: /* return from signal handler */
|
|
#ifdef TRACE_EXCEPTIONS
|
|
printf(" (%u)jump to %#x, stack %#x\n", u.u_procp->p_pid, frame [FRAME_PC], frame [FRAME_SP]);
|
|
#endif
|
|
break;
|
|
default:
|
|
#ifdef TRACE_EXCEPTIONS
|
|
printf(" (%u)syscall failed, errno %d\n", u.u_procp->p_pid, u.u_error);
|
|
#endif
|
|
frame [FRAME_PC] = opc + NBPW; /* return to next instruction */
|
|
frame [FRAME_R2] = -1; /* $v0 - result */
|
|
frame [FRAME_R8] = u.u_error; /* $t0 - errno */
|
|
break;
|
|
}
|
|
goto out;
|
|
}
|
|
/* From this point and further the interrupts must be enabled. */
|
|
psignal(u.u_procp, psig);
|
|
out:
|
|
/* Process all received signals. */
|
|
for (;;) {
|
|
psig = CURSIG(u.u_procp);
|
|
if (psig <= 0)
|
|
break;
|
|
postsig(psig);
|
|
}
|
|
curpri = setpri(u.u_procp);
|
|
|
|
/* Switch to another process. */
|
|
if (runrun) {
|
|
setrq(u.u_procp);
|
|
u.u_ru.ru_nivcsw++;
|
|
swtch();
|
|
}
|
|
|
|
/* Update profiling information. */
|
|
if (u.u_prof.pr_scale)
|
|
addupc((caddr_t) frame [FRAME_PC],
|
|
&u.u_prof, (int) (u.u_ru.ru_stime - syst));
|
|
ret:
|
|
led_control(LED_KERNEL, 0);
|
|
}
|
|
|
|
/*
|
|
* nonexistent system call-- signal process (may want to handle it)
|
|
* flag error if process won't see signal immediately
|
|
* Q: should we do that all the time ??
|
|
*/
|
|
void
|
|
nosys()
|
|
{
|
|
if (u.u_signal[SIGSYS] == SIG_IGN || u.u_signal[SIGSYS] == SIG_HOLD)
|
|
u.u_error = EINVAL;
|
|
psignal(u.u_procp, SIGSYS);
|
|
}
|
|
|
|
void sc_msec()
|
|
{
|
|
u.u_rval = ct_ticks * (1000 / HZ);
|
|
}
|