Rearranged the memory layout so udata is at the top of userspace, above
authorDavid Given <dg@cowlark.com>
Mon, 29 Jun 2015 21:28:59 +0000 (23:28 +0200)
committerDavid Given <dg@cowlark.com>
Mon, 29 Jun 2015 21:28:59 +0000 (23:28 +0200)
the environment; implemented dofork and fixed switchin and switchout.
init loads! And runs! And tries to exec /bin/sh! Which fails, because
the environment's mangled by a user-vs-kernel pointer size mismatch.

Kernel/lowlevel-msp430x.c
Kernel/platform-msp430fr5969/build.mk
Kernel/platform-msp430fr5969/config.h
Kernel/platform-msp430fr5969/crt0.S
Kernel/platform-msp430fr5969/devtty.c
Kernel/platform-msp430fr5969/msp430fr5969.ld
Kernel/platform-msp430fr5969/tricks.S

index 01f26f3..3795bc4 100644 (file)
@@ -60,10 +60,3 @@ __attribute__ ((naked)) void unix_syscall_entry(void)
                  "g" (udata.u_error)
        );
 }
-
-int16_t dofork(ptptr child)
-{
-       kprintf("dofork\n");
-       for (;;);
-}
-
index aa3978d..41c8d30 100644 (file)
@@ -54,6 +54,7 @@ kernel.asflags += \
        -g \
 
 kernel.ldflags += \
+       --relax \
        -s 
 
 kernel.libgcc = $(shell $(TARGETCC) -mlarge --print-libgcc)
index 90c82ef..64c7b4c 100644 (file)
@@ -7,7 +7,7 @@
 /* Multiple processes in memory at once */
 #undef CONFIG_MULTI
 /* Single tasking - for now while we get it booting */
-#define PTABSIZE 1
+#define PTABSIZE 4
 
 #define CONFIG_NO_STARTUP_MESSAGE
 
 extern int __user_base;
 extern int __user_top;
 
+extern int __swap_base;
+extern int __swap_top;
+
 #define TICKSPERSEC 64   /* Ticks per second */
 #define PROGBASE    ((uaddr_t)&__user_base)  /* also data base */
 #define PROGLOAD    PROGBASE /* also data base */
 #define PROGTOP     ((uaddr_t)&__user_top)  /* Top of program */
 
-#define SWAPBASE    PROGBASE
-#define SWAPTOP            PROGTOP
+#define SWAPBASE    ((uaddr_t)&__swap_base)
+#define SWAPTOP            ((uaddr_t)&__swap_top)
 #define SWAP_SIZE   ((SWAPTOP - SWAPBASE)/512)
 #define MAX_SWAPS      8
 #define swap_map(x) ((uint8_t*)(x))
index eacfaeb..357efce 100644 (file)
@@ -40,14 +40,18 @@ lowproc trap_reboot
 
        ; Wipe BSS.
        mov.w #__bssstart, r12
-       mov #0, r13
-       mov.w #__bsssize, r14
-       calla #memset
+1:
+       clr.b @r12
+       inc r12
+       cmp.w #__bssend, r12
+       jnz 1b
 
        mov.w #__bss2start, r12
-       mov #0, r13
-       mov.w #__bss2size, r14
-       calla #memset
+1:
+       clr.b @r12
+       inc r12
+       cmp.w #__bss2end, r12
+       jnz 1b
 
        ; Set some kernel variables.
        mov.w #64, &ramsize
index 89f2a33..62ccba3 100644 (file)
@@ -65,7 +65,7 @@ void tty_sleeping(uint8_t minor)
 
 ttyready_t tty_writeready(uint8_t minor)
 {
-       return (UCA0IFG & UCTXIFG) ? TTY_READY_NOW : TTY_READY_LATER;
+       return (UCA0IFG & UCTXIFG) ? TTY_READY_NOW : TTY_READY_SOON;
 }
 
 void tty_setup(uint8_t minor)
index 580316d..c15fa13 100644 (file)
@@ -104,20 +104,32 @@ MEMORY {
   RESETVEC         : ORIGIN = 0xFFFE, LENGTH = 0x0002
   BSL              : ORIGIN = 0x1000, LENGTH = 0x0800
 
-  SRAMLO           : ORIGIN = 0x1C00, LENGTH = 0x0400
-  SRAMHI           : ORIGIN = 0x2000, LENGTH = 0x0400
-  LOROM            : ORIGIN = 0x4400, LENGTH = 0x7ffc-0x4400
+  SRAM             : ORIGIN = 0x1C00, LENGTH = 0x0800
+
+  /* The kstack is at 0x7e00, and extends up to 0x8000, with four bytes
+   * reserved under 0x8000 for the syscall vector; UDATA goes at the top
+   * of userspace, just below 0xfe00. */
+  LOROM            : ORIGIN = 0x4400, LENGTH = 0x7e00-0x4400
+  KSTACK           : ORIGIN = 0x7e00, LENGTH = 0x1fc
   SYSCALL          : ORIGIN = 0x7ffc, LENGTH = 0x0004
-  USER             : ORIGIN = 0x8000, LENGTH = 0xfe00-0x8000
+  USER             : ORIGIN = 0x8000, LENGTH = 0xfe00-0x8000-240
+  UDATA            : ORIGIN = 0xfe00-240, LENGTH = 240
+
+  /* Desperately pack more variables into the 384-byte space between
+   * 0xfe00 and 0xff80 (where the system vectors start). */
   LOROMX           : ORIGIN = 0xfe00, LENGTH = 0xff80-0xfe00
+
   HIROM            : ORIGIN = 0x10000, LENGTH = 0x3FFF
 }
 
+PROVIDE(__swap_base = 0x7e00);
+PROVIDE(__swap_top = 0xfe00);
+
 PROVIDE(__user_base = ORIGIN(USER));
 PROVIDE(__user_length = LENGTH(USER));
 PROVIDE(__user_top = ORIGIN(USER) + LENGTH(USER));
-PROVIDE(udata = ORIGIN(SRAMLO));
-PROVIDE(kstack_top = ORIGIN(SRAMLO) + LENGTH(SRAMLO));
+PROVIDE(udata = ORIGIN(UDATA));
+PROVIDE(kstack_top = ORIGIN(KSTACK) + LENGTH(KSTACK));
 
 SECTIONS
 {
@@ -204,6 +216,10 @@ SECTIONS
        *(.text.fuzix_main)
        *(.text.sgrpsig)
        *(.text.srch_dir)
+       *(.text.switchout)
+       *(.text.dofork)
+       *(.text.getproc)
+       *(.text.rargs)
   } > LOROM
     
   .text : {
@@ -215,21 +231,25 @@ SECTIONS
     PROVIDE (etext = .);
   } > HIROM
 
+  .bss : {
+    . = ALIGN(2);
+    PROVIDE (__bssstart = .);
+    *(.bss.bufpool);
+       *(.bss.blkdev_table);
+       *(.bss.tod);
+       *(.bss.ttydata);
+    . = ALIGN(2);
+    PROVIDE (__bssend = .);
+  } > LOROM
+  PROVIDE (__bsssize = SIZEOF(.bss));
+
   .sram : {
        . = ALIGN(2);
        PROVIDE (__bss2start = .);
-       *(.bss.ptab)
-       *(.bss.blk_op)
-       *(.bss.of_tab)
-       *(.bss.tbuf1)
-       *(.bss.blkdev_table)
-       *(.bss.fs_tab)
-       *(.bss.ttydata)
-       *(.bss.ticks)
-       *(.bss.tod)
+       *(.bss.*)
        . = ALIGN(2);
        PROVIDE (__bss2end = .);
-  } > SRAMHI
+  } > SRAM
   PROVIDE (__bss2size = SIZEOF(.sram));
 
   .data : {
@@ -257,15 +277,6 @@ SECTIONS
   PROVIDE(__romdatastart = LOADADDR(.data));
   PROVIDE (__romdatacopysize = SIZEOF(.data));
 
-  .bss : {
-    . = ALIGN(2);
-    PROVIDE (__bssstart = .);
-    *(.bss .bss.* .gnu.linkonce.b.*)
-    . = ALIGN(2);
-    PROVIDE (__bssend = .);
-  } > LOROM
-  PROVIDE (__bsssize = SIZEOF(.bss));
-
   .MP430.attributes 0 :
   {
     KEEP (*(.MSP430.attributes))
index a1efa04..ba5994d 100644 (file)
@@ -6,28 +6,63 @@
 ; possibly the same process, and switches it in.  When a process is
 ; restarted after calling switchout, it thinks it has just returned
 ; from switchout().
-; 
-; This function can have no arguments or auto variables.
 
-.globl switchout
-switchout:
-       bic.w #GIE, SR                     ; interrupts off
-       mov #0, r12                        ; set return code
+.globl switchin
+proc switchout
+       dint                               ; interrupts off
+       clr r12                            ; set return code
        pushm.a #12, r15                   ; save all registers (r15 to r4)
        push SR                            ; ...and the status register
-       movx SP, &U_DATA__U_SP             ; save stack pointer
-       clra &inint
-
-       ;calla #getproc
-       jmp switchin                    ; switch in new process
-       calla #trap_monitor                ; should never reach here
+       mov SP, &U_DATA__U_SP              ; save stack pointer
+       clr &inint
 
-.globl switchin
+       calla #getproc                     ; find a new process to run
 switchin:
-       bic.w #GIE, SR                     ; interrupts off
+       dint                               ; interrupts off
+       mov.w #U_DATA__U_PTAB, r12
+       mov.b #P_RUNNING, P_TAB__P_STATUS_OFFSET(r12) ; mark process as running
+
        movx &U_DATA__U_SP, SP             ; restore stack pointer
+    clr &runticks                      ; reset process run count
        pop SR                             ; restore status register
        popm.a #12, r15                    ; restore all registers (r15 to r4)
-       bis.w #GIE, SR                     ; interrupts on
+       eint                               ; interrupts on
        reta
 
+; Forks to swap. On entry, r12 is the process pointer.
+
+proc dofork
+       dint
+
+       ; dofork suspends the parent; the scheduler will resume it again with
+       ; switchin. So we need to save the parent's state is if it had been
+       ; saved with switchout.
+
+       pushm.a #12, r15                   ; save all registers (r15 to r4)
+       push SR                            ; ...and the status register
+       mov SP, &U_DATA__U_SP              ; save stack pointer
+       clr &inint
+
+       ; Save the parent process to disk.
+
+       pushx.a r12
+       movx.a &U_DATA__U_PTAB, r12
+       calla #swapout
+       popx.a r12
+
+       ; Okay, done. Anything we change now won't affect the parent. Create the
+       ; child process. First we get rid of all the junk we put on the stack for
+       ; switchin.
+
+       add #12*4 + 2, sp
+
+       ; Now create the child process. (r12 is still the process pointer.)
+
+       calla #newproc
+
+       ; ...and we're ready to go.
+
+       clr &runticks                      ; reset process run count
+       clr r12                            ; child fork returns zero!
+       eint                               ; interrupts on
+       reta