3b2: Soft-power shutdown via TIMER command

This change enables the simulator to be shut down cleanly via a
soft-power shutdown command. This is implemented in the real 3B2/400
through the sanity timer, which, if it reaches zero, sets a bus timeout
flag in the CSR and issues an interrupt at IPL 15. The operating
system (System V UNIX) treats this as a shutdown request and enters
runlevel 0.

To use this change in a SIMH startup script, for example to implement a
3B2 simulator as a service, one could add these commands:

    # [... simulator setup ...]
    BOOT
    SET TIMER SHUTDOWN
    CONTINUE
    EXIT

On catching a SIGTERM, SIGINT, or SIGHUP, the simulator would return to
SCP control, set the soft power shutdown flag, and then continue
simulator execution. After the system is cleanly shut down, the
simulator would then exit back to the operating system.
This commit is contained in:
Seth Morabito 2019-04-13 11:36:02 -07:00
parent ad9cb1d42d
commit 7455d28126
3 changed files with 32 additions and 2 deletions

View file

@ -3455,7 +3455,7 @@ static void cpu_calc_ints()
cpu_int_ipl = cpu_int_vec = CPU_ID_IF_IPL;
} else if ((csr_data & CSRUART) || (csr_data & CSRDMA)) {
cpu_int_ipl = cpu_int_vec = CPU_IU_DMA_IPL;
} else if (csr_data & CSRCLK) {
} else if ((csr_data & CSRCLK) || (csr_data & CSRTIMO)) {
cpu_int_ipl = cpu_int_vec = CPU_TMR_IPL;
} else {
cpu_int_ipl = cpu_int_vec = 0;

View file

@ -433,8 +433,14 @@ REG timer_reg[] = {
{ NULL }
};
MTAB timer_mod[] = {
{ MTAB_XTD|MTAB_VDV|MTAB_VALR|MTAB_NC, 0, NULL, "SHUTDOWN",
&timer_set_shutdown, NULL, NULL, "Soft Power Shutdown" },
{ 0 }
};
DEVICE timer_dev = {
"TIMER", timer_unit, timer_reg, NULL,
"TIMER", timer_unit, timer_reg, timer_mod,
1, 16, 8, 4, 16, 32,
NULL, NULL, &timer_reset,
NULL, NULL, NULL, NULL,
@ -468,6 +474,23 @@ t_stat timer_reset(DEVICE *dptr) {
return SCPE_OK;
}
t_stat timer_set_shutdown(UNIT *uptr, int32 val, CONST char* cptr, void* desc)
{
struct timer_ctr *sanity = timer_unit[0].tmr;
sim_debug(EXECUTE_MSG, &timer_dev,
"[%08x] Setting sanity timer to 0 for shutdown.\n", R[NUM_PC]);
sanity->val = 0;
csr_data &= ~CSRCLK;
csr_data |= CSRTIMO;
return SCPE_OK;
}
/*
* Sanity Timer
*/
t_stat timer0_svc(UNIT *uptr)
{
struct timer_ctr *ctr;
@ -486,6 +509,9 @@ t_stat timer0_svc(UNIT *uptr)
return SCPE_OK;
}
/*
* Interval Timer
*/
t_stat timer1_svc(UNIT *uptr)
{
struct timer_ctr *ctr;
@ -505,6 +531,9 @@ t_stat timer1_svc(UNIT *uptr)
return SCPE_OK;
}
/*
* Bus Timeout Timer
*/
t_stat timer2_svc(UNIT *uptr)
{
struct timer_ctr *ctr;

View file

@ -69,6 +69,7 @@ void timer_write(uint32 pa, uint32 val, size_t size);
t_stat timer0_svc(UNIT *uptr);
t_stat timer1_svc(UNIT *uptr);
t_stat timer2_svc(UNIT *uptr);
t_stat timer_set_shutdown(UNIT *uptr, int32 val, CONST char *cptr, void *desc);
/* CSR */
t_stat csr_svc(UNIT *uptr);