Path: utzoo!utgpu!news-server.csri.toronto.edu!mailrus!uwm.edu!zaphod.mps.ohio-state.edu!mips!sgi!rpw3@rigden.wpd.sgi.com From: rpw3@rigden.wpd.sgi.com (Rob Warnock) Newsgroups: comp.arch Subject: Re: Interrupts in user space; Lightweight Traps Summary: Lightweight traps-to-user-mode exist today... and in far yesterday! Message-ID: <70576@sgi.sgi.com> Date: 28 Sep 90 06:31:08 GMT References: <12738@encore.Encore.COM> <413@data.UUCP> Sender: guest@sgi.sgi.com Reply-To: rpw3@sgi.com (Rob Warnock) Organization: Silicon Graphics, Inc., Mountain View, CA Lines: 69 In article <413@data.UUCP> kend@data.UUCP (Ken Dickey) writes: +--------------- | I think that the thing to concentrate on is design of HW architectures | which support the above so that there are a set of "lightweight traps" | which can be safely reflected to the runtime system. This could lead | to a large savings in code size. +--------------- In both of the Unix ports done to the Am29000 (S5 & BSD), the "spill/fill" assertion traps [used to shift the register window] were "trampolined" back to user mode code to perform the actual operation. In addition, a user program could request that most other (synchronous) traps also "bounce" back to a user-mode handler. The trampoline code was quite short. In the case of spill & fill, the address of the user-mode handler was kept in a kernel- protected register, thus the trampoline code was only 5 instructions: uspilltrap: mfsr tpc, PC1 ; save return address mtsr PC1, uspill ; "branch" add tav, uspill, 4 ; (sequential fetch) mtsr PC0, tav ; "branch" completely iret This was done for a couple of reasons reasons: - The copying done in a spill/fill might result in page faults or stack growth, both of which were a lot easier to handle if they came from user mode rather than from some random kernel trap handler. - You have to save/restore a dozen+ words of 29k CPU state before you can safely "come off freeze mode", which you have to do to use things like load & store multiple (which the spill/fill code wants to use!), so bouncing straight back to user mode saves all that saving/restoring. [None of that state is actually useful in the case of a synchronous trap from an "ASSERT" or "EMULATE" instruction, so nothing is "lost".] Other uses than spill/fill were found for this feature. Since in the 29k BCS different operating systems use different trap vector numbers, is was possible to write a user-mode syscall-emulation routine that could be bound with an object module from another operating system, so that system calls from that other system could be emulated under Unix by the user-mode library. Most of the compiler/assembler/tool vendors for the 29k targeted their tools for a small "operating system" (originally called "HIF", later changed to some other name -- I forgot what) that ran on an AMD prototyping board (PCEB/29k) that plugged into a PC. HIF provided a POSIX-subset interface, which was mapped to MS/DOS calls (by a program running in the PC). But the above "trampoline" feature made it possible for us to write a HIF system call emulator that was bound with the HIF object files, so we could instantly run all the PC-targeted tools under Unix! [No, nobody ever tried to emulate Sys-V under BSD or vice-versa! ;-} ] And if you want to go back *really* far, the DEC PDP-10 hardware dispatched half of the "UUO"s (Unimplemented User Operations -- trap/emulate instructions, really) to kernel mode (where they were used for system calls), and the other half directly back to the user process. Many of the compilers (especially FORTRAN) used trap-to-user UUOs to synthesize "fat instructions" which were implemented by the run-time libraries. The generated code for FORTRAN I/O was full of these things... -Rob ----- Rob Warnock, MS-9U/510 rpw3@sgi.com rpw3@pei.com Silicon Graphics, Inc. (415)335-1673 Protocol Engines, Inc. 2011 N. Shoreline Blvd. Mountain View, CA 94039-7311