diff --git a/ski-bootloader/boot_head.S b/ski-bootloader/boot_head.S index 5931117..9499fb9 100644 --- a/ski-bootloader/boot_head.S +++ b/ski-bootloader/boot_head.S @@ -5,6 +5,10 @@ */ #include +#ifndef __ASSEMBLY__ +#define __ASSEMBLY__ +#endif +#include "ssc.h" #define ENTRY(name) \ .align 32; \ @@ -157,6 +161,11 @@ static: cmp.eq p6,p7=PAL_PTCE_INFO,r28 mov r8=0 /* status = 0 */ mov r9=0x80|0x01 /* NatPage|WB */ ;; +1: cmp.eq p6,p7=PAL_HALT_LIGHT,r28 +(p7) br.cond.sptk.few 1f + mov r15=SSC_HALT_LIGHT + break 0x80001 + ;; 1: br.cond.sptk.few rp stacked: br.ret.sptk.few rp diff --git a/ski-bootloader/include/ia64/pal.h b/ski-bootloader/include/ia64/pal.h index 048060c..95f8911 100644 --- a/ski-bootloader/include/ia64/pal.h +++ b/ski-bootloader/include/ia64/pal.h @@ -8,5 +8,6 @@ #define PAL_FREQ_RATIOS 14 #define PAL_PERF_MON_INFO 15 #define PAL_RSE_INFO 19 +#define PAL_HALT_LIGHT 29 /* enter the low power light halt state */ #endif /* _INCLUDE_PAL_H_ */ diff --git a/ski-bootloader/ssc.h b/ski-bootloader/ssc.h index 7ce12cc..a3a0c06 100644 --- a/ski-bootloader/ssc.h +++ b/ski-bootloader/ssc.h @@ -9,6 +9,7 @@ /* Simulator system calls: */ +#define SSC_HALT_LIGHT 19 #define SSC_CONSOLE_INIT 20 #define SSC_GETCHAR 21 #define SSC_PUTCHAR 31 @@ -28,9 +29,13 @@ #define SSC_GET_ARGS 75 #define SSC_GET_INITRAMFS 77 +#ifndef __ASSEMBLY__ + /* * Simulator system call. */ extern long ssc (long arg0, long arg1, long arg2, long arg3, int nr); +#endif /* !__ASSEMBLY */ + #endif /* ssc_h */ diff --git a/ski-efi/boot_head.S b/ski-efi/boot_head.S index 5931117..9499fb9 100644 --- a/ski-efi/boot_head.S +++ b/ski-efi/boot_head.S @@ -5,6 +5,10 @@ */ #include +#ifndef __ASSEMBLY__ +#define __ASSEMBLY__ +#endif +#include "ssc.h" #define ENTRY(name) \ .align 32; \ @@ -157,6 +161,11 @@ static: cmp.eq p6,p7=PAL_PTCE_INFO,r28 mov r8=0 /* status = 0 */ mov r9=0x80|0x01 /* NatPage|WB */ ;; +1: cmp.eq p6,p7=PAL_HALT_LIGHT,r28 +(p7) br.cond.sptk.few 1f + mov r15=SSC_HALT_LIGHT + break 0x80001 + ;; 1: br.cond.sptk.few rp stacked: br.ret.sptk.few rp diff --git a/ski-efi/include/ia64/pal.h b/ski-efi/include/ia64/pal.h index 048060c..95f8911 100644 --- a/ski-efi/include/ia64/pal.h +++ b/ski-efi/include/ia64/pal.h @@ -8,5 +8,6 @@ #define PAL_FREQ_RATIOS 14 #define PAL_PERF_MON_INFO 15 #define PAL_RSE_INFO 19 +#define PAL_HALT_LIGHT 29 /* enter the low power light halt state */ #endif /* _INCLUDE_PAL_H_ */ diff --git a/ski-efi/ssc.h b/ski-efi/ssc.h index 7ce12cc..a3a0c06 100644 --- a/ski-efi/ssc.h +++ b/ski-efi/ssc.h @@ -9,6 +9,7 @@ /* Simulator system calls: */ +#define SSC_HALT_LIGHT 19 #define SSC_CONSOLE_INIT 20 #define SSC_GETCHAR 21 #define SSC_PUTCHAR 31 @@ -28,9 +29,13 @@ #define SSC_GET_ARGS 75 #define SSC_GET_INITRAMFS 77 +#ifndef __ASSEMBLY__ + /* * Simulator system call. */ extern long ssc (long arg0, long arg1, long arg2, long arg3, int nr); +#endif /* !__ASSEMBLY */ + #endif /* ssc_h */ diff --git a/src/linux/syscall-linux.c b/src/linux/syscall-linux.c index 9f4fe1a..0b12011 100644 --- a/src/linux/syscall-linux.c +++ b/src/linux/syscall-linux.c @@ -95,6 +95,7 @@ #include "os_support.h" #include "syscall_api.h" #include "ui.h" +#include "itc.h" #if defined NEW_MP # error "not supported" @@ -4501,6 +4502,50 @@ asynckb (int sig) #endif +/* + * Sleep until SIGIO or SIGALRM is received; this relies on + * keyboard/ethernet input being detected via SIGIO, and the + * ITC now being emulated via setitimer() and SIGALRM. + * + * A SIGALRM might be delivered just before we enter the + * blocking (but interruptible) system call. To ensure that + * we notice that SIGALRM, the protocol is: + * + * 1. We atomically retrieve the current signal mask and block SIGALRM. + * + * 2. We check if an ITC SIGALRM has been received, if so we + * restore the signal mask and return. + * + * 3. We call pselect to atomically unblock SIGALRM and block until + * a signal is delivered. + * + * 4. We unblock SIGALRM since pselect re-blocks it. + * + * Any SIGALRM before step 1 is detected by step 2, and any SIGALRM + * after step 1 is detected via the pselect in step 3. + */ +static void +doSSC_HALT_LIGHT (void) +{ + sigset_t set, oldset; + + sigemptyset(&set); + sigaddset(&set, SIGALRM); + + if (sigprocmask(SIG_BLOCK, &set, &oldset) == -1) { + perror("sigprocmask"); + exit(1); + } + + if (itc_itimer_fired) { + sigprocmask(SIG_SETMASK, &oldset, NULL); + return; + } + + pselect (0, NULL, NULL, NULL, NULL, &oldset); + sigprocmask(SIG_SETMASK, &oldset, NULL); +} + void doSSC (HWORD num, REG arg0, REG arg1, REG arg2, REG arg3, REG *ret) { @@ -4530,6 +4575,10 @@ doSSC (HWORD num, REG arg0, REG arg1, REG arg2, REG arg3, REG *ret) progStop ("SSC breakpoint\n"); break; + case SSC_HALT_LIGHT: + doSSC_HALT_LIGHT (); + break; + case SSC_CTL_TRACE: #ifdef TRACE_DAVIDM { diff --git a/src/ssc.h b/src/ssc.h index 077c8b2..96ac2a1 100644 --- a/src/ssc.h +++ b/src/ssc.h @@ -30,6 +30,7 @@ #define SSC_STOP 0 +#define SSC_HALT_LIGHT 19 #define SSC_CONSOLE_INIT 20 #define SSC_GETCHAR 21 #define SSC_PUTCHAR 31