logo

drewdevault.com

[mirror] blog and personal website of Drew DeVault git clone https://hacktivis.me/git/mirror/drewdevault.com.git

Status-update-October-2022.md (7000B)


  1. ---
  2. title: Status update, October 2022
  3. date: 2022-10-15
  4. ---
  5. After a few busy and stressful months, I decided to set aside October to rest.
  6. Of course, for me, rest does not mean a cessation of programming, but rather a
  7. shift in priorities towards more fun and experimental projects. Consequently, it
  8. has been a great month for Helios!
  9. Hare upstream has enjoyed some minor improvements, such as from Pierre Curto's
  10. patch to support parsing IPv6 addresses with a port (e.g. "[::1]:80") and Kirill
  11. Primak's improvements to the UTF-8 decoder. On the whole, improvements have been
  12. conservative. However, queued up for integration once qbe upstream support is
  13. merged is support for @threadlocal variables, which are useful for Helios and for
  14. ABI compatibility with C. I also drafted up a proof-of-concept for @inline
  15. functions, but it still needs work.
  16. Now for the main event: Helios. The large-scale redesign and refactoring I
  17. mentioned in the previous status update is essentially complete, and the kernel
  18. reached (and exceeded) feature parity with the previous status quo. Since Helios
  19. has been my primary focus for the past couple of weeks, I have a lot of news to
  20. share about it.
  21. First, I got back into userspace a few days after the last status update, and
  22. shortly thereafter implemented a new scheduler. I then began to rework the
  23. userspace API (uapi) in the kernel, which differs substantially from its prior
  24. incarnation. The kernel object implementations present themselves as a library
  25. for kernel use, and the new uapi module handles all interactions with this
  26. module from userspace, providing a nice separation of concerns. The uapi module
  27. handles more than syscalls now — it also implements send/recv for kernel
  28. objects, for instance. As of a few days ago, uapi also supports delivering
  29. faults to userspace supervisor processes:
  30. ![A screenshot of a thread on Helios causing a page fault, then its parent
  31. thread receives details of the fault and maps a page onto the address of the
  32. attempted write. The child thread is resumed and is surprised to find that the
  33. write succeeded (because a page was mapped underneath the write).](https://l.sr.ht/YvMX.png)
  34. ```hare
  35. @test fn task::pagefault() void = {
  36. const fault = helios::newendpoint()!;
  37. defer helios::destroy(fault)!;
  38. const thread = threads::new(&_task_pagefault)!;
  39. threads::set_fault(thread, fault)!;
  40. threads::start(thread)!;
  41. const fault = helios::recv_fault(fault);
  42. assert(fault.addr == 0x100);
  43. const page = helios::newpage()!;
  44. defer helios::destroy(page)!;
  45. helios::map(rt::vspace, 0, map_flags::W | map_flags::FIXED, page)!;
  46. threads::resume(thread)!;
  47. threads::join(thread)!;
  48. };
  49. fn _task_pagefault() void = {
  50. let ptr: *int = 0x100: uintptr: *int;
  51. *ptr = 1337;
  52. assert(*ptr == 1337);
  53. };
  54. ```
  55. The new userspace threading API is much improved over the hack job in the
  56. earlier design. It supports TLS and many typical threading operations, such as
  57. join and detach. This API exists mainly for testing the kernel via Vulcan, and
  58. is not anticipated to see much use beyond this (though I will implement pthreads
  59. for the POSIX C environment at some point). For more details, see [this blog
  60. post][0]. Alongside this and other userspace libraries, Vulcan has been fleshed
  61. out into a kernel test suite once again, which I have been frequently testing on
  62. real hardware:
  63. [0]: https://drewdevault.com/2022/10/02/Kernel-hacking-with-Hare-part-2.html
  64. ![A picture of a laptop showing 15 passing kernel tests](https://l.sr.ht/RMAS.jpg)
  65. [Here's an ISO](https://l.sr.ht/NwsO.iso) you can boot on your own x86\_64
  66. hardware to see if it works for you, too. If you have problems, take a picture
  67. of the issue, boot Linux and [email me](mailto:sir@cmpwn.com) said picture, the
  68. output of lscpu, and any other details you deem relevant.
  69. The kernel now supports automatic capability address allocation, which is a
  70. marked improvement over seL4. The new physical page allocator is also much
  71. improved, as it supports allocation and freeing and can either allocate pages
  72. sparsely or continuously depending on the need. Mapping these pages in userspace
  73. was also much improved, with a better design of the userspace virtual memory map
  74. and a better heap, complete with a (partial) implementation of mmap.
  75. I have also broken ground on the next component of the OS, [Mercury][1], which
  76. provides a more complete userspace environment for writing drivers. It has a
  77. simple tar-based initramfs based on Hare's format::tar implementation, which I
  78. wrote in June for this purpose. It can load ELF files from this tarball into new
  79. processes, and implements some extensions that are useful for driver loading.
  80. Consequently, the first Mercury driver is up and running:
  81. [1]: https://git.sr.ht/~sircmpwn/mercury
  82. ![Demo of a working serial driver](https://l.sr.ht/PKZ6.png)
  83. This driver includes a simple driver manifest, which is embedded into its ELF
  84. file and processed by the driver loader to declaratively specify the
  85. capabilities it needs:
  86. ```hare
  87. [driver]
  88. name=pcserial
  89. desc=Serial driver for x86_64 PCs
  90. [cspace]
  91. radix=12
  92. [capabilities]
  93. 0:endpoint =
  94. 1:ioport = min=3F8, max=400
  95. 2:ioport = min=2E8, max=2F0
  96. 3:note =
  97. 4:irq = irq=3, note=3
  98. 5:irq = irq=4, note=3
  99. ```
  100. The driver loader prepares capabilities for the COM1 and COM2 I/O ports, as well
  101. as IRQ handlers for IRQ 3 and 4, based on this manifest, then loads them into
  102. the capability table for the driver process. The driver is sandboxed very
  103. effectively by this: it can *only* use these capabilities. It cannot allocate
  104. memory, modify its address space, or even destroy any of these capabilities. If
  105. a bad actor was on the other end of the serial port and exploited a bug, the
  106. worst thing it could do is crash the serial driver, which would then be rebooted
  107. by the supervisor. On Linux and other monolithic kernels like it, exploiting the
  108. serial driver compromises the entire operating system.
  109. The resulting serial driver implementation is pretty small and straightforward,
  110. [if you'd like to have a look][2].
  111. [2]: https://git.sr.ht/~sircmpwn/mercury/tree/master/item/drivers/x86_64/serial
  112. This manifest format will be expanded in the future for additional kinds of
  113. drivers, such as with details specific to each bus (i.e. PCI vendor information
  114. or USB details), and will also have details for device trees when RISC-V and
  115. ARM support (the former is already underway) are brought upstream.
  116. Next steps are to implement an I/O abstraction on top of IPC endpoints, which
  117. first requires call & reply support — the latter was implemented last
  118. night and requires additional testing. Following this, I plan on writing a
  119. getty-equivalent which utilizes this serial driver, and a future VGA terminal
  120. driver, to provide an environment in which a shell can be run. Then I'll
  121. implement a ramfs to host commands for the shell to run, and we'll really be
  122. cookin' at that point. Disk drivers and filesystem drivers will be next.
  123. That's all for now. Quite a lot of progress! I'll see you next time.