kernel: add soft interrupt support
authorAlan Cox <alan@linux.intel.com>
Sat, 5 Nov 2016 10:13:59 +0000 (10:13 +0000)
committerAlan Cox <alan@linux.intel.com>
Sat, 5 Nov 2016 10:13:59 +0000 (10:13 +0000)
Put the pieces in place so a platform can treat the kernel di/ei/irqrestore
as a software construct and implement its own hardware IRQ management eg
to allow for things like software uart fifos.

25 files changed:
Kernel/PORTING
Kernel/bank16k.c
Kernel/cpu-6502/cpu.h
Kernel/cpu-68000/cpu.h
Kernel/cpu-6809/cpu.h
Kernel/cpu-68hc11/cpu.h
Kernel/cpu-8086/cpu.h
Kernel/cpu-pdp11/cpu.h
Kernel/cpu-z80/cpu.h
Kernel/include/kernel.h
Kernel/lowlevel-8086.S
Kernel/lowlevel-pdp11.S
Kernel/lowlevel-z80-banked.s
Kernel/lowlevel-z80-cmos-banked.s
Kernel/lowlevel-z80-cmos.s
Kernel/lowlevel-z80-nmos-banked.s
Kernel/lowlevel-z80-nmos.s
Kernel/lowlevel-z80.s
Kernel/platform-coco2/coco2.s
Kernel/platform-coco3/coco3.s
Kernel/platform-dragon-nx32/dragon.s
Kernel/platform-dragon/p6809.s
Kernel/platform-multicomp09/multicomp09.s
Kernel/platform-tgl6502/tgl6502.s
Kernel/start.c

index 271ef00..eb19eb4 100644 (file)
@@ -539,15 +539,16 @@ should probably support vfork().
 Other Processors
 ----------------
 
-Currently only Z80 and 6809 are properly supported. Clones should also work as
-should FPGA cores like T80. The current build uses no undocumented instructions
-in any core code.
+Currently only 68000, 6809 and Z80 are properly supported. Clones should also
+work as should FPGA cores like T80. The current build uses no undocumented
+instructions in any core code but the SDCC library does use them for its
+float support.
 
 It ought to be possible to port UZI to any other small processor with
 banking. That would include banked 6809/6309 systems and perhaps 65C816
 (Apple IIGS anyone ?) with a suitable compiler. The current core code has
 been tested to some extent on 6502, and has been build tested on 8086 and
-68000. Various endianisms in the core code have been fixed but there may be
+PDP/11. Various endianisms in the core code have been fixed but there may be
 more.
 
 The constraints roughly speaking for any port are
@@ -568,8 +569,6 @@ and relocatable binaries. Doable as AmigaOS showed but forget swapping.
 
 As far as I can tell we have suitable open toolchains for
 
-6809 (gcc fork) - although 6809 is well served by NitrOS/9.
-
 68HC11/2 (for the variants with banked RAM)
 
 TI990 (gcc development) - http://www.cozx.com/~dpitts/tigccinst.html
@@ -588,13 +587,47 @@ in 64K and anyone ever built a banked 8080 who knows 8)
 
 Various other early minicomputers probably also fit the target.
 
-Going to early 32bit CPU is hard because
-- not all of the core code is 32bit clean (I've tried to begin marking out
-  the argument parameters and the like to fix it)
-- the fs code knows that you can't write a size bigger than the filesystem
-  so other sanity checks would need adding
+Interrupts
+----------
+
+The current default behaviour leaves interrupts off for long periods. In
+some cases such as floppy drivers this is hard to avoid on most 8bit
+machines. We try and minimise the harm this causes by loosely tying the
+system clock to the low part of any available RTC (the full RTC isn't used
+both because of the conversion costs, and because of Y2K issues on many
+systems).
+
+It is possible with care to re-enable interrupts during swapping on a task
+switch which is the big nasty but this requires care that mappings are
+always valid. With a fixed common space it isn't too bad.
+
+It's also now possible to define CONFIG_SOFT_IRQ in which case the platform
+provides its own routines for IRQ management and the kernel uses those. The
+requirements for this are:
+
+- You don't call any Fuzix core code while you are in 'di' state
+- You don't try and run extra timer ticks when the 'ei' or 'irqrestore'
+  occurs.
+
+You can thus keep system interrupts on a lot more and copy serial bytes
+into/out of a FIFO buffer or count missed timer ticks. Timer ticks need to
+be processed together in the timer interrupt. so you can call timer_interrupt()
+the correct number of times from the actual timer interrupt handler, but
+because of the context switching must not try and do it anywhere else.
+
+On a 68000 or a 6809 your vectors and stack are usually valid except during
+task switching (tricks.S) so it is fairly easy to handle. On a Z80 a lot of
+care is needed because we must avoid taking an interrupt while the mapped
+low bank does not have valid vectors. Bank16k uses __hard_di for a few
+cases because of this. For a Z80 platform with fixed common and low banks
+you should write the vectors into each bank at early boot time before
+interrupts are enabled.
+
+Fuzix expects physical interrupts to be off on entry, and it will call
+__hard_ei() at the right point in startup. It may call di/ei/irqrestore
+before that but with physical interrupts still off.
+
 
-A 2BSD/RetroBSD port might make a lot more sense anyway on such a system
 
 
 Other Things That Would Help
index 107abbc..e6f4f52 100644 (file)
@@ -126,7 +126,7 @@ int pagemap_realloc(usize_t size)
        /* We don't want to take an interrupt here while our page mappings are
           incomplete. We may restore bogus mappings and then take a second IRQ
           into hyperspace */
-       irq = di();
+       irq = __hard_di();
 
        if (have > want) {
                for (i = want; i < have; i++) {
@@ -145,7 +145,7 @@ int pagemap_realloc(usize_t size)
                update = 1;
 
        } else {
-               irqrestore(irq);
+               __hard_irqrestore(irq);
                return ENOMEM;
        }
        /* Copy the updated allocation into the ptab */
@@ -156,7 +156,7 @@ int pagemap_realloc(usize_t size)
           we switch to this memory map */
        if (update)
                program_vectors(&udata.u_page);
-       irqrestore(irq);
+       __hard_irqrestore(irq);
        return 0;
 }
 
index 9ddb68b..974c634 100644 (file)
@@ -21,10 +21,6 @@ typedef uint16_t uptr_t;             /* User pointer equivalent */
 #define uputi  uputw                   /* Copy user int type */
 #define ugeti  ugetw                   /* between user and kernel */
 
-extern void ei(void);
-extern irqflags_t di(void);
-extern void __fastcall__ irqrestore(irqflags_t f);
-
 extern void * __fastcall__ memcpy(void *, void *, size_t);
 extern void * __fastcall__ memset(void *, int, size_t);
 extern size_t __fastcall__ strlen(const char *);
index ee272b2..2302b71 100644 (file)
@@ -22,10 +22,6 @@ typedef uint32_t uptr_t;             /* User pointer equivalent */
 #define uputi  uputl                   /* Copy user int type */
 #define ugeti  ugetl                   /* between user and kernel */
 
-extern void ei(void);
-extern irqflags_t di(void);
-extern void irqrestore(irqflags_t f);
-
 extern void *memcpy(void *, const void  *, size_t);
 extern void *memset(void *, int, size_t);
 extern int memcmp(const void *, const void *, size_t);
index 2f6e5a7..8e73a0f 100644 (file)
@@ -21,10 +21,6 @@ typedef uint16_t uptr_t;             /* User pointer equivalent */
 #define uputi  uputw                   /* Copy user int type */
 #define ugeti  ugetw                   /* between user and kernel */
 
-extern void ei(void);
-extern irqflags_t di(void);
-extern void irqrestore(irqflags_t f);
-
 #define EMAGIC    0x7E    /* Header of executable  (JMP) */
 #define EMAGIC_2  0x20    /* BRA */
 /* Allow a minimum of 512 bytes gap between stack and top of allocations */
index f5592ce..ec9fea3 100644 (file)
@@ -20,10 +20,6 @@ typedef uint16_t uptr_t;             /* User pointer equivalent */
 #define uputi  uputw                   /* Copy user int type */
 #define ugeti  ugetw                   /* between user and kernel */
 
-extern void ei(void);
-extern irqflags_t di(void);
-extern void irqrestore(irqflags_t f);
-
 #define EMAGIC    0x7E    /* Header of executable  (JMP) */
 #define EMAGIC_2  0x20    /* BRA */
 /* Allow a minimum of 512 bytes gap between stack and top of allocations */
index c9b7f08..b95da69 100644 (file)
@@ -20,10 +20,6 @@ typedef uint16_t uptr_t;             /* User pointer equivalent */
 #define uputi  uputw                   /* Copy user int type */
 #define ugeti  ugetw                   /* between user and kernel */
 
-extern void ei(void);
-extern irqflags_t di(void);
-extern void irqrestore(irqflags_t f);
-
 extern void *  memcpy(void *, void *, size_t);
 extern void *  memset(void *, int, size_t);
 extern size_t  strlen(const char *);
index e4bb3b8..c74d6a5 100644 (file)
@@ -21,10 +21,6 @@ typedef uint16_t uptr_t;             /* User pointer equivalent */
 #define uputi  uputw                   /* Copy user int type */
 #define ugeti  ugetw                   /* between user and kernel */
 
-extern void ei(void);
-extern irqflags_t di(void);
-extern void irqrestore(irqflags_t f);
-
 /* FIXME: we actually want to use an a.out loader */
 
 #define EMAGIC    0x7E    /* Header of executable  (JMP) */
index e1d029b..37987d4 100644 (file)
@@ -20,12 +20,8 @@ typedef uint16_t uptr_t;             /* Userspace pointer equivalent */
 #define uputi  uputw                   /* Copy user int type */
 #define ugeti  ugetw                   /* between user and kernel */
 
-#define ei()   do {__asm ei __endasm; } while(0);
-
 typedef uint16_t irqflags_t;
 
-extern irqflags_t di(void);
-extern void irqrestore(irqflags_t f);
 extern void out(uint8_t addr, uint8_t val);
 extern uint8_t in(uint8_t addr);
 
index cb3c64c..0e6ebef 100644 (file)
@@ -904,6 +904,16 @@ extern uint8_t rtc_secs(void);
 extern void trap_reboot(void);
 extern uint8_t platform_param(char *p);
 
+extern irqflags_t __hard_di(void);
+extern void __hard_irqrestore(irqflags_t f);
+extern void __hard_ei(void);
+
+#ifndef CONFIG_SOFT_IRQ
+#define di __hard_di
+#define irqrestore __hard_irqrestore
+#define ei __hard_ei
+#endif
+
 /* Will need a uptr_t eventually */
 extern uaddr_t ramtop;      /* Note: ramtop must be in common in some cases */
 extern void platform_interrupt(void);
index ba31d82..0c20f1d 100644 (file)
@@ -136,14 +136,17 @@ outax:
 outcharhex:    
        ret
 
-_di:
+___hard_di:
        pushf
        pop ax
        cli
        ret
 
-_irqrestore:
+___hard_irqrestore:
        push ax
        popf
        ret
-       
\ No newline at end of file
+
+___hard_ei:
+       sti
+       ret
index 38491f3..56838b9 100644 (file)
@@ -1,8 +1,8 @@
 #include "kernel-pdp11.def"
 
-       .globl _di
-       .globl _ei
-       .globl _irqrestore
+       .globl ___hard_di
+       .globl ___hard_ei
+       .globl ___hard_irqrestore
        .globl _doexec
        .globl ___udivhi3
        .globl ___umodhi3
        address space - for now 077776 and the other control registers work
        in a very similar way */
 
-_di:
+___hard_di:
        mov 0177776,r0
        bis 0340,0177776
        rts pc
-_ei:
+___hard_ei:
        mov 0177776,r0
        bic 0340,0177776
        rts pc
-_irqrestore:
+___hard_irqrestore:
        mov 2(sp),0177776
        rts pc
 
index 736081c..7a67b43 100644 (file)
@@ -42,8 +42,9 @@
         .globl trap_illegal
        .globl nmi_handler
        .globl interrupt_handler
-       .globl _di
-       .globl _irqrestore
+       .globl ___hard_di
+       .globl ___hard_ei
+       .globl ___hard_irqrestore
        .globl _in
        .globl _out
 
index d32c1f5..c152a46 100644 (file)
@@ -3,13 +3,14 @@
                ; IRQ helpers, in common as they may get used by common C
                ; code (and are tiny)
 
-_di:           ld a, i
+___hard_di:    ld a, i
                push af
                pop hl
                di
                ret
 
-_irqrestore:   pop hl          ; sdcc needs to get register arg passing
+___hard_irqrestore:
+               pop hl          ; sdcc needs to get register arg passing
                pop de
                pop af          ; so badly
                jp po, was_di
index 4e39204..c81ee7f 100644 (file)
@@ -3,13 +3,14 @@
                ; IRQ helpers, in common as they may get used by common C
                ; code (and are tiny)
 
-_di:           ld a, i
+___hard_di:    ld a, i
                push af
                pop hl
                di
                ret
 
-_irqrestore:   pop hl          ; sdcc needs to get register arg passing
+___hard_irqrestore:
+               pop hl          ; sdcc needs to get register arg passing
                pop af          ; so badly
                jp po, was_di
                ei
index 725bc5a..a509c5e 100644 (file)
@@ -1,6 +1,6 @@
                .area _COMMONMEM
 
-_di:           xor a           ; NMOS Z80 bug work around as per CPU manual
+___hard_di:    xor a           ; NMOS Z80 bug work around as per CPU manual
                push af
                pop af          ; clear byte on stack below our usage
                ld a, i
@@ -16,7 +16,8 @@ was_ei:               push af
                di
                ret
 
-_irqrestore:   pop hl
+___hard_irqrestore:
+               pop hl
                pop de
                pop af
                jr c, was_di
index dae2dc5..86525fe 100644 (file)
@@ -1,6 +1,6 @@
                .area _COMMONMEM
 
-_di:           xor a           ; NMOS Z80 bug work around as per CPU manual
+___hard_di:    xor a           ; NMOS Z80 bug work around as per CPU manual
                push af
                pop af          ; clear byte on stack below our usage
                ld a, i
@@ -16,7 +16,8 @@ was_ei:               push af
                di
                ret
 
-_irqrestore:   pop hl
+___hard_irqrestore:
+               pop hl
                pop af
                jr c, was_di
                ei
index cc4a65a..5825da7 100644 (file)
@@ -42,8 +42,9 @@
         .globl trap_illegal
        .globl nmi_handler
        .globl interrupt_handler
-       .globl _di
-       .globl _irqrestore
+       .globl ___hard_ei
+       .globl ___hard_di
+       .globl ___hard_irqrestore
        .globl _out
        .globl _in
 
@@ -655,6 +656,13 @@ _in:
        in l, (c)
        ret
 
+;
+;      Enable interrupts
+;
+___hard_ei:
+       ei
+       ret
+
 ;
 ;      Pull in the CPU specific workarounds
 ;
index 6750c9a..b1bdcfa 100644 (file)
@@ -32,9 +32,9 @@
        .globl _trap_monitor
        .globl _trap_reboot
        .globl outchar
-       .globl _di
-       .globl _ei
-       .globl _irqrestore
+       .globl ___hard_di
+       .globl ___hard_ei
+       .globl ___hard_irqrestore
 
        include "kernel.def"
        include "../kernel09.def"
@@ -100,15 +100,15 @@ _trap_monitor:
        orcc #0x10
        bra _trap_monitor
 
-_di:
+___hard_di:
        tfr cc,b                ; return the old irq state
        orcc #0x10
        rts
-_ei:
+___hard_ei:
        andcc #0xef
        rts
 
-_irqrestore:                   ; B holds the data
+___hard_irqrestore:            ; B holds the data
        tfr b,cc
        rts
 
index b8f724f..8cd6e0f 100644 (file)
@@ -26,9 +26,9 @@
             .globl _trap_monitor
            .globl _trap_reboot
             .globl outchar
-           .globl _di
-           .globl _ei
-           .globl _irqrestore
+           .globl ___hard_di
+           .globl ___hard_ei
+           .globl ___hard_irqrestore
 
             ; imported symbols
             .globl _ramsize
@@ -98,7 +98,7 @@ bounce_end@
 ;;; Turn off interrupts
 ;;;    takes: nothing
 ;;;    returns: B = original irq (cc) state
-_di:
+___hard_di:
            tfr cc,b            ; return the old irq state
            orcc #0x10
            rts
@@ -106,14 +106,14 @@ _di:
 ;;; Turn on interrupts
 ;;;   takes: nothing
 ;;;   returns: nothing
-_ei:
+___hard_ei:
            andcc #0xef
            rts
 
 ;;; Restore interrupts to saved setting
 ;;;   takes: B = saved state (as returned from _di )
 ;;;   returns: nothing
-_irqrestore:                   ; B holds the data
+___hard_irqrestore:            ; B holds the data
            tfr b,cc
            rts
 
index f4dc9f5..4cde363 100644 (file)
@@ -28,9 +28,9 @@
        .globl _trap_monitor
        .globl _trap_reboot
        .globl outchar
-       .globl _di
-       .globl _ei
-       .globl _irqrestore
+       .globl ___hard_di
+       .globl ___hard_ei
+       .globl ___hard_irqrestore
 
         include "kernel.def"
         include "../kernel09.def"
@@ -107,15 +107,15 @@ _trap_monitor:
            orcc #0x10
            bra _trap_monitor
 
-_di:
+___hard_di:
            tfr cc,b            ; return the old irq state
            orcc #0x10
            rts
-_ei:
+___hard_ei:
            andcc #0xef
            rts
 
-_irqrestore:                   ; B holds the data
+___hard_irqrestore:            ; B holds the data
            tfr b,cc
            rts
 
index d86e4d2..b62d4d7 100644 (file)
@@ -20,9 +20,9 @@
             .globl _trap_monitor
             .globl _trap_reboot
             .globl outchar
-           .globl _di
-           .globl _ei
-           .globl _irqrestore
+           .globl ___hard_di
+           .globl ___hard_ei
+           .globl ___hard_irqrestore
 
             ; imported symbols
             .globl _ramsize
@@ -40,15 +40,15 @@ _trap_monitor:
            cwai #0
            bra _trap_monitor
 
-_di:
+___hard_di:
            tfr cc,b            ; return the old irq state
            orcc #0x10
            rts
-_ei:
+___hard_ei:
            andcc #0xef
            rts
 
-_irqrestore:                   ; B holds the data
+___hard_irqrestore:            ; B holds the data
            tfr b,cc
            rts
 
index d4b4433..d6118d8 100644 (file)
@@ -178,7 +178,7 @@ bounce_end@
 ;;; Turn off interrupts
 ;;;    takes: nothing
 ;;;    returns: B = original irq (cc) state
-_di:
+___hard_di:
        tfr     cc,b            ; return the old irq state
        orcc    #0x10
        rts
@@ -186,14 +186,14 @@ _di:
 ;;; Turn on interrupts
 ;;;   takes: nothing
 ;;;   returns: nothing
-_ei:
+___hard_ei:
        andcc   #0xef
        rts
 
 ;;; Restore interrupts to saved setting
 ;;;   takes: B = saved state (as returned from _di )
 ;;;   returns: nothing
-_irqrestore:                   ; B holds the data
+___hard_irqrestore:            ; B holds the data
        tfr     b,cc
        rts
 
index 6da7091..db1e4af 100644 (file)
@@ -19,9 +19,9 @@
             .export _trap_monitor
            .export _trap_reboot
             .export outchar
-           .export _di
-           .export _ei
-           .export _irqrestore
+           .export ___hard_di
+           .export ___hard_ei
+           .export ___hard_irqrestore
            .export vector
 
            .import interrupt_handler
@@ -71,16 +71,16 @@ _trap_monitor:
 _trap_reboot:
            jmp _trap_reboot    ; FIXME: original ROM map and jmp
 
-_di:
+___hard_di:
            php
            sei                 ; Save old state in return to C
            pla                 ; Old status
            rts
-_ei:
+___hard_ei:
            cli                 ; on 6502 cli enables IRQs!!!
            rts
 
-_irqrestore:
+___hard_irqrestore:
            and #4              ; IRQ flag
            beq irq_on
            cli
index e3579e1..d6558d9 100644 (file)
@@ -356,7 +356,7 @@ void fuzix_main(void)
        ticks_per_dsecond = TICKSPERSEC / 10;
 
        kputs("Enabling interrupts ... ");
-       ei();
+       __hard_ei();            /* Physical interrupts on */
        kputs("ok.\n");
 
        /* get the root device */