#2 bi-weekly progress report

Published: Mon 04 November 2019

Kernel finally runs in virtual space!

Well, not quite, but let us introduce some context first. For the time being the only platform supported by Mimiker is MIPS 24KEc 32-bit processor on Malta board. The address space of 4GiB is split into two haves: useg for user programs and ksegX for kernel. There’re four ksegX segments, 512MiB each. Physical memory is accessible directly through kseg0 and kseg1 segments. For useg, kseg2, kseg3 segments, virtual to physical address translation is performed in hardware using TLB (Translation Lookaside Buffer). Unfortunately, most MIPS processors don’t support hardware page table walkers. The processor invokes exception handling routine whenever it can translate address using entries present in TLB. Operating system is responsible for replacing entries in TLB. This introduces extra level of complexity and caused several failed attempts to move kernel to virtual addresses.

While there’s nothing fundamentally wrong in running kernel in kseg0, such address space organization is not compatible with Aarch64 nor x86-64. This prevents us from porting Mimiker to Raspberry Pi3. Moreover, fully fledged kernels require to be run in memory that is pageable, for instance to enable swapping kernel buffers to disk.

The #406181a commit brings kernel image (i.e. text, data, bss) sections to TLB managed virtual memory. But, there’s still some work do be done. Namely, kernel stacks and dynamic memory allocators still operate in kseg0. (by Cahir)

Signal handlers work!

Manpower shortage forces us to take lazy approach to Mimiker development: we only fix things that are really broken. There are multiple reasons for Korn shell (ksh) doesn’t behave correctly. One of them was buggy implementation of return from user-defined signal handlers. Since signals are delivered during return to user-space, returning from signal handler should restore user context. But signal handler is just a user defined C function, not pretending to know its real purpose. Upon return it acts according to SysV-ABI trying to jump back to a non-existing caller routine, what definitely leads to a crash. That was solved by using trampoline approach. When preparing a stack frame of signal handler, the return address is set to point to a piece of code (called the trampoline) which simply invokes a sigreturn syscall, which responsibility is to restore the required user context. The trampoline resides in user space at the bottom of the stack. This will lead to serious problems when we make user stack non-executable, but this won’t happen soon :) (by JPsz)

siglongjmp and sigsetjmp tests

siglongjmp/sigsetjmp works exactly as longjmp/setjmp and in addition restore/save blocked signal mask. Some tests were added to certify, that those system calls work as expected. Unfortunately sigprocmask implementation is a dummy, but we’ll take care of it later. (by JPsz)

Other contributions:

  • Backtrace command in GNU debugger passes kernel-user boundary (by JMzr)
  • Fix pipe(2) read not returning short counts (by JPsz)
  • First attempt to create files & directories in tmpfs (by JUrb)
  • Implement fcntl syscall (only F_DUPFD command) (by JPsz)
  • Adapt full FAT implementation for Aarch64 kernel prototype (by PJas)