▲ 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 — 11 days 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 — 2 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 — 2 months ago