finished rewriting a lot of the BoredOS netstack
▲ 40 r/osdevel+1 crossposts

finished rewriting a lot of the BoredOS netstack

Hey reddit!

I've spent the last few weeks rewriting the network stack for my hobby OS, BoredOS.

Before i start yapping about what i changed, i'll quickly explain the netstack. BoredOS uses the lwIP stack to handle IPv4, Ipv6 (experimental), TCP, UDP and ICMP. The nice thing about LwIP is that i only have to supply hardware driver ring buffers, VFS fd's, some splinlock synchro, socket wait queues and a few syscalls.

Previously i was using a custom sysfs file interface to handle network traffic.. Which was quite shit imo. It didn't fit standard C lib calls or allow multiplexing network I/O alongside regular files. I replaced this monstrosity with a BSD socket layer and standard POSIX system calls like: socket, bind, connect, listen, accept, send, recv, select, poll, sendmsg, and recvmsg. Wiring sockets directly into the VFS fd table allows read/write and close to work on net sockets the same way they do on regular files and pipes.

BoredOS previously also had DHCP and DNS baked into the kernel with some very messy way of interacting with them, these have now all been moved into userspace with my own versions of standard fbsd netutils.

For packet handling, i moved processing out of the hardware interrupt handlers into a dedicated kernel worker thread. Processing packets directly in interrupt context was increasing interrupt latency and causing frame drops in heavy bursts, therefore hardware ISRs now just dump incoming frames into ring buffers and wake up a dedicated kernel worker thread via a wait queue. The worker thread sleeps when idle, wakes up on IRQs to drain the buffers into lwIP, and manages background timers for TCP retransmissions and ARP timeouts. For socket storage, i added kernel ring buffers backed by spinlocks and wait queues to handle blocking and non-blocking backpressure properly.

To allow my netutils and custom protocols to run without needing to ensloppify the kernel, i wrote a virtual TUN and TAP device driver. It supports layer 3 IP tunneling feeding into lwIP and Layer 2 Eth frame mode through TUNSETIFF ioctls. I also added raw socket support with AF_PACKET so userland packet sniffers can capture and inject raw ethernet frames directly. Of course meant for the skids to larp that they're hacking something xD.

For device management i added BSD style interface naming like em0 for intel gigabit cards, re0 and re1 for RealTek cards, vtnet0 for VirtIO, and tun0 for virtual devices.

With all these changes i also managed to speed up the stack by a LOT. Previously i was limited to a few Mbit/s and i am now able to push 800 Mbit/s in QEMU emulating an E1000 nic (maybe VirtIO is even faster? too lazy to test though) which basically maxes out the host machine connection.

EDIT:
Forgot to attach the gh:
https://github.com/BoredOS

u/christiaansp — 14 days ago
▲ 10 r/osdev

I've had enough.

As stated in this post the moderator is simply trying to hide everything and as stated by mykesx on r/osdevel "He has a bot that replies to a post by HIS users calling out AI slop that is overwhelming the sub with "human slop"" The whole subreddit is almost entirely filled with completely ai-generated software. While AI isn't necessarily bad, replacing all creativity and hard work by letting an AI do everything is imo not okay. This sub being filled with that doesn't make it a fun subreddit. I will simply stop posting here and move to r/kerneldevelopment unless this situation is fixed by Tim Schwartz.

Until then, cya. This post will probably be removed in the next 15 minutes anyways.

reddit.com
u/christiaansp — 15 days ago
▲ 45 r/kerneldevelopment+2 crossposts

I finally got an AC'97 driver working in BoredOS!

After about 2.5 weeks of banging my head against this (alongside building out NTK), I've got a proper AC97 driver in a solid state and wanted to share. The driver is interrupt-driven with a kernel mixer thread that handles up to 8 concurrent clients. Each client gets its own ring buffer and linear-interpolated sample-rate conversion to 48 kHz. One thing that bit me early on: QEMU's AC97 emulation doesn't actually apply the NAM register gains to the DMA stream, so volume control has to live in the software mixer path instead. Userspace talks to it through /dev/dsp using the standard OSS ioctls (SNDCTL_DSP_SPEED, SNDCTL_DSP_SETFMT, etc.) and just writes PCM. There's also a /dev/mixer node for master/PCM gain. I also wrote a simple utility that handles WAV and MP3 files (via minimp3), feeding into a ring of 32 pre-allocated 16 KB DMA buffers.

shit, almost forgot:

https://github.com/boredos

u/christiaansp — 2 months ago

Hey r/Operatingsystems,

I’ve been working on an x86_64 hobby operating system called BoredOS for a while now, and I figured it was a good time to share my progress!

What started as just a learning exercise kind of snowballed into a full system. It’s now got a kernel, userspace apps, a custom desktop environment, and a growing SDK for app development.

The Setup

  • Bootloader: Limine (handling hybrid BIOS + UEFI)
  • Arch: x86_64 long mode
  • Kernel: Preemptive multitasking with SMP support
  • Graphics: Custom in-kernel WM/compositor (BoredWM)
  • Filesystem: Linux-style VFS rooted at / (backed by FAT32)
  • Network: lwIP wired up to a few different NIC drivers
  • Userspace: Ring 3 ELF binaries, a custom libc, and APIs for both CLI and GUI apps.

What's working right now

CPU & Scheduling SMP is up and running via the Limine SMP protocol. I’m currently using the PIT for preemption on the BSP, and relying on LAPIC + IPIs to trigger cross-core rescheduling. Processes (ELF binaries) are assigned round-robin across the AP cores. The Ring 3 transition is pretty standard: load the ELF, map the segments, and iretq out.

Memory Management I built a two-tier kernel allocator. For the small stuff, there's a slab allocator handling classes from 8 bytes up to 512 bytes. For larger or aligned allocations, it falls back to a block-list allocator that handles splitting and coalescing.

Storage & VFS The VFS layer abstracts the usual suspects (open, read, write, close, seek, readdir) with descriptor mapping. Everything is rooted at / , and both boot modules and ATA-backed files live in the exact same tree. I've also made sure the VFS paths and filesystem locks are SMP-safe.

Networking I ported lwIP to handle the IPv4 stack (TCP/UDP/ICMP/DHCP/DNS) and wrote drivers for e1000, rtl8139, rtl8111, and virtio-net. Right now, packet processing is poll-driven (network_process_frames).

Desktop & Apps There’s a custom window manager (BoredWM) with overlapping windows, an event loop, input routing, and framebuffer rendering. The userland ecosystem is actually getting pretty decent—it currently has a terminal, a text editor, some utilities, a simple browser, and a few games. I also put together an SDK to make writing new apps easier.

Some weird design choices (and why I made them)

You might notice a few quirks in the architecture. First, keeping the network flow poll-driven was a deliberate choice to avoid stack re-entrancy headaches and simplify debugging while the stack is still evolving.

Second, I originally started with a "kernel-first" monolithic design where everything lived in Ring 0. I’ve since moved the application boundaries out to userspace through syscalls, but because of how it evolved, the window manager currently still lives inside the kernel.

https://preview.redd.it/gs7vjuqfdsxg1.jpg?width=1920&format=pjpg&auto=webp&s=600851cfc7d5370befad2bd533b3a79acb8a2bc4

Links

Huge shoutout to Lluciocc for his PRs and improvements over the last couple of weeks, too!

reddit.com
u/christiaansp — 4 months ago
▲ 0 r/osdev

Hey r/osdev,

I’ve been working on an x86_64 hobby operating system called BoredOS for a while now, and I figured it was a good time to share my progress and hopefully get some feedback from you guys.

What started as just a learning exercise kind of snowballed into a full system. It’s now got a kernel, userspace apps, a custom desktop environment, and a growing SDK for app development.

The Setup

  • Bootloader: Limine (handling hybrid BIOS + UEFI)
  • Arch: x86_64 long mode
  • Kernel: Preemptive multitasking with SMP support
  • Graphics: Custom in-kernel WM/compositor (BoredWM)
  • Filesystem: Linux-style VFS rooted at / (backed by FAT32)
  • Network: lwIP wired up to a few different NIC drivers
  • Userspace: Ring 3 ELF binaries, a custom libc, and APIs for both CLI and GUI apps.

What's working right now

CPU & Scheduling SMP is up and running via the Limine SMP protocol. I’m currently using the PIT for preemption on the BSP, and relying on LAPIC + IPIs to trigger cross-core rescheduling. Processes (ELF binaries) are assigned round-robin across the AP cores. The Ring 3 transition is pretty standard: load the ELF, map the segments, and iretq out.

Memory Management I built a two-tier kernel allocator. For the small stuff, there's a slab allocator handling classes from 8 bytes up to 512 bytes. For larger or aligned allocations, it falls back to a block-list allocator that handles splitting and coalescing.

Storage & VFS The VFS layer abstracts the usual suspects (open, read, write, close, seek, readdir) with descriptor mapping. Everything is rooted at / , and both boot modules and ATA-backed files live in the exact same tree. I've also made sure the VFS paths and filesystem locks are SMP-safe.

Networking I ported lwIP to handle the IPv4 stack (TCP/UDP/ICMP/DHCP/DNS) and wrote drivers for e1000, rtl8139, rtl8111, and virtio-net. Right now, packet processing is poll-driven (network_process_frames).

Desktop & Apps There’s a custom window manager (BoredWM) with overlapping windows, an event loop, input routing, and framebuffer rendering. The userland ecosystem is actually getting pretty decent—it currently has a terminal, a text editor, some utilities, a simple browser, and a few games. I also put together an SDK to make writing new apps easier.

Some weird design choices (and why I made them)

You might notice a few quirks in the architecture. First, keeping the network flow poll-driven was a deliberate choice to avoid stack re-entrancy headaches and simplify debugging while the stack is still evolving.

Second, I originally started with a "kernel-first" monolithic design where everything lived in Ring 0. I’ve since moved the application boundaries out to userspace through syscalls, but because of how it evolved, the window manager currently still lives inside the kernel.

Links

Where I could use some advice

I’d really appreciate any critiques, especially on these fronts:

  1. SMP Scheduling: Are there any common pitfalls I should watch out for with per-core round-robin and IPI nudging?
  2. Memory Management: How do you guys usually validate your allocator state? I'm a bit worried I have blind spots here.
  3. Networking: Should I stick with the poll-driven model a bit longer, or is it worth aggressively moving to interrupt-driven processing?
  4. VFS: Any tips on cleaner design patterns for scaling up to more filesystems long-term?

Huge shoutout to Lluciocc for his PRs and improvements over the last couple of weeks, too!

reddit.com
u/christiaansp — 4 months ago