#tabula imaginarium: osdev experiments in zig

1 messages · Page 7 of 1

haughty cipher
#

it gets called by the arm stuff where i needed it for and also by the amd and intel iommu code according to elixir so ig it is relevant for iommu

last pebble
#

Makes sense

haughty cipher
#

though thats with a variety of callbacks

#

the function to get requester id specifically using it is only called by the arm interrupt controller hell

last pebble
#

This is for finding who generated the irq?

haughty cipher
#

this is for finding out what itll tell the interrupt controller generated the irq lmao

#

mapping backwards generally wont be needed because your irq abstraction will probably handle that

last pebble
#

Oh ok

haughty cipher
#

but generally this number is what indexes the tables in the iommu and/or this one arm hell interrupt controller in particular

#

so you need it to write to those tables correctly

last pebble
#

Why couldn't bridges just preserve the requester id

#

So strange

haughty cipher
#

idk its fuckin stupid

last pebble
#

Yep

haughty cipher
#

heres the relevant section of the spec btw

last pebble
#

That probably means something to PCI people

haughty cipher
#

yeah ikr

#

i copied the linux code i linked earlier instead of actually understanding this shit

#

i think what it is is if theres a possibility of the ids overlapping then the bridge is required to note who its from and take ownership

#

and then a reply goes to the bridge who looks up backwards and that way the things behind it cant conflict

#

the relevant part for MSI is the last bullet though

#

wait not thats reads im dumb

#

my logic diverges from linux and i just realised its wrong and specifically it wasnt working when i matched linux because the nvme was behind a pcie-pci bridge lmao

last pebble
#

Yeah this is some cursed stuff

haughty cipher
#

yeah

#

welcome to pci ig

haughty cipher
#

btw im also open to feedback/suggestions on my driver stuff not just questions

last pebble
#

Oh im definitely not in that position, never written an nvme driver and dont understand zig concepts

haughty cipher
#

i was thinking more if you happen to also look at the other drivers (esp the acpi one) you might have thoughts too, but fair

last pebble
#

Oh ok

haughty cipher
#

nw if you dont want to look elsewhere though lol

last pebble
#

Im gonna sleep now anyways but yeah might give a look tmrw

haughty cipher
#

sleep well

last pebble
#

Thanks

haughty cipher
#

god its so nice writing code that doesnt depend on architecture now

#

im still habitually checking on both arches but its still so nice

#

almost feels weird but its very nice

#

pushed the site to update the autodocs but havent updated the actual docs yet

haughty cipher
#

well fortunately ive got a ton of old fat code still from before i started using uefi for bootloader filesystem stuff

#

so that fs will be relatively painless to implement i hope

#

at least for reading

#

i dont have writing at all yet KEKW

#

(theres some stuff i need to fix with my build system to better support getting both initial and final disk images out that i can inspect before i want to add writing, and also ive got to wrap my head around how the fuck to change the size of a file in FAT)

haughty cipher
#

ok time to see if i can read a bpb

#

and thats a nope

#

oh that was a super shrimple bug

#

ok i should make the two FAT systems different sizes so i can actually tell its reading the right partitions here

#

part of me gets concerned when things just work 😅

polar pilot
#

holy shit that's so cool

haughty cipher
#

the ultimate plan here

#

once i get fatfs working

#

is itll be told by the bootloader what the partition guid the kernel is on is

#

(and maybe the esp too i havent decided there)

#

itll load a fat filesystem on the kernel boot partition

#

and then using the alias i give that partition in the object namespace itll be able to load the stuff that something like linux would put in initramfs

#

most importantly: fstab

#

which will then let it assemble the actual vfs

haughty cipher
#

i love logging

#

ok time to absolutely hammer the nvme driver by reading the entire FAT into memory at once

#

wtf that worked???

last pebble
#

Real hw test time

haughty cipher
#

im still not set up to do a real hw test 😭

#

unless i pci passthrough the nvme controller of my actual hard drive with its actual efi system partition which is the only fat partition i have to test with on real hardware

#

which sounds uh dangerous

kindred isle
#

(I have personal beef with IOMMU group 15 and my motherboard)

last pebble
haughty cipher
#

also dont have any way to get log output other than port e9

last pebble
#

Hack a quick flanterm integration

last pebble
#

Took me 5 mins

haughty cipher
last pebble
#

Damn

haughty cipher
# kindred isle UART serial?

havent written the driver yet, will soon™ but also i dont think any of my actual hardware has uart serial ports other than my main dev machine

kindred isle
#

I have one you can steal and port to zig troll2

haughty cipher
# last pebble Damn

my end goal is to run this thing on a serial terminal (ideally a teletypewriter if i can get my hands on one) anyway so framebuffer has been low priority

#

i have an old laptop i could absolutely turn into a real hardware test machine sometime and probably will

#

ill have to figure out what its serial situation is

haughty cipher
kindred isle
#

You can just grab the GOP and pass it over in like 20 minutes

haughty cipher
#

i could absolutely get that doing ive just been too lazy™

kindred isle
#

Go do it

haughty cipher
#

i even had a poll here and people voted for storage so im doing storage

#

one thing at a time lol

kindred isle
#

Okay

#

Wait

haughty cipher
#

framebuffer and framebuffer-based logger/terminal is probably the next thing ill do after storage

kindred isle
#

My desktop has a windows NVMe

#

With a fat partition

#

I’m sure it would be fineee to test it there

#

And I have a serial port

#

Lowk been meaning to make it a game partition anyways

#

If you happened to break it

#

Soooooo just make sure it won’t touch my main nvme and I’m good to test ts

haughty cipher
#

well rn it doesnt even issue a write command

#

so probs fine there

#

the only partitions itll touch rn are efi system partitions or ones with the special partition type guid i use for my imaginarium boot partition

#

but once i get a uart driver ill be happy to see it tested on real hardware

kindred isle
#

My Linux drive does have one of thoes

#

You can probably blacklist the pcie ID tho to be safe

#

Want me to cleanup my UART driver and send it over for portage so you can test it real quick

haughty cipher
#

nah ill do my own when i get there

kindred isle
#

Fair

haughty cipher
#

the goal with this project is learning not getting it working as fast as possible

#

so i wanna do it myself

kindred isle
#

Feel free to ping me when you wana destroy my windows install

haughty cipher
kindred isle
#

I have it do two seperate self tests with warnings if it fails the first due to how messy it wants to be

haughty cipher
#

mhm good to know

#

anyway im hitting a wall now

#

where i gotta figure out how the fuck i want to abstract files

kindred isle
kindred isle
#

Where the vnode abstracts to the backend device

haughty cipher
#

im already leaning very NT-like for things and i know i want files to be objects in the object manager

kindred isle
#

And the FD/FDR abstract the file its self

#

Fair fair

haughty cipher
#

the issue is the details and the api design

kindred isle
#

That may be out of the realm of my knowledge sadly

haughty cipher
#

i mean im not really copying windows fully here either

#

im just more NT-inspired than unix-inspired

#

mostly because theres some things about how *nix handles filesystems/devices in particular that i hate lmao

kindred isle
#

May I inquire what that is?

#

(Also iirc TECHNICSLY vnodes are a bsdism?)

haughty cipher
#

devices as part of the filesystem is the main thing i hate

#

and the resulting overreliance on ioctl

kindred isle
#

You could do an NT style device abstraction and a Unix Style VFS for standard files?

haughty cipher
#

that and i find the *nix file permissions model overly restrictive

kindred isle
#

And you can still have NT style ACLs etc ontop

haughty cipher
#

yeah

#

as i said, the problem rn is the details

kindred isle
#

That would be pretty based

haughty cipher
#

honestly the first big question is do i make the fs data use containerof or do i make the file object carry an opaque pointer

polar pilot
#

containerof will always be my favorite

haughty cipher
#

yeah i lean that way too

#

thats the biggest thing ive actually learned doing osdev

#

is that containerof is goated

polar pilot
#

intrusive data structures in general

haughty cipher
#

i didnt even know containerof existed before starting this os and it took me a while to get it and now its one of my favorite things

#

ive seen people ask in other discords what the biggest thing to learn going into osdev is and honestly my answer has been to learn intrusive linked lists and containerof lmao

haughty cipher
#

ok lets see if we can read the FAT chain for the root dir

#

apparently yes 🎉

haughty cipher
#

ok time to try iterating a directory

#

this is thoroughly not working lol

#

oh god a race condition again 💀

#

and/or deadlock i legit cant tell

haughty cipher
#

ok i think i found the bug and its way stupider than that lmao

#

nope

#

that wasnt it

#

ok i dont have tha brain power to figure out what the fuck is wrong here rn

#

reverted my wrong fix and we'll stick with the weird edge case still existing

#

for now its working theres just something fucked up i dont understand here giving rise to an edge case

haughty cipher
#

probably not going to get much work at all done this week, lot of irl stuff happening

haughty cipher
#

somehow i have time today

#

so time to get back to work

#

kinda want to get open working for fatfs but also not sure on some nitpicky details there yet and the docs desparately need updating

#

ive got a whole docs page about my interrupt handling thats just completely incorrect now 😅

haughty cipher
#

time to get out my frustration at how annoying the GITS was by writing it all out as a slightly-snarky devlog

haughty cipher
#

wrote a devlog thats like 80% ranting about the GIC ITS and 20% talking about the new irq design for imaginarium lol

haughty cipher
#

i can open files and read subdirs \o/

last pebble
#

moving quite fast

haughty cipher
#

i cant read files though

#

only readdir and open are implemented

haughty cipher
#

ok now to see if i cant read from a file

#

oh i think i see the bug here

#

does this look like a reasonable elf header start to yall?

#

other than being cut off for whatever reason

#

opened the elf in imhex and got this and that looks the same?

#

so ig were working

#

🎉

#

the elf is like the only file i have here to try reading 😅

haughty cipher
#

race conditions are going to kill me

#

aarch64 keeps having them

#

i mean its probably also happening on x86 tbh

#

but just cant reproduce it

#

so im gonna go to bed and come back if not saturday then fuckin probably thursday with how busy the coming week looks

finite ether
#

arm has a much weaker memory model

haughty cipher
#

im getting 100% success rate on x86 so far but like half the time arm deadlocks

finite ether
#

idk if qemu emulates it properly

haughty cipher
#

qemu should be emulating it stronger than the real hardware would

#

in any case its not a memory order thing afaict its a straight up race condition deadlock in my io asynchrony

finite ether
#

ah well deadlocks are like the easiest concurrency bugs at least

haughty cipher
#

yeah the code is just complex

#

specifically whats happening is:

  • thread starts io operation
  • thread calls wait on event object associated with io
  • event object is unset so the thread branches into enqueue_wait
  • the io completion interrupt fires
  • the io completion interrupt sets the event
  • theres nothing waiting on the event yet so noone to free
  • thread queues itself on already set event and sits there forever
#

and idk how to fix this

#

because if i mask all interrupts during the whole check and enqueue for wait process thats a) inefficient and b) sometimes causes the interrupt to be dropped so instead it hangs for that reason

#

the solution might actually be a thread pool/threaded dpcs tbh

#

because then the callback that releases the thread runs at passive whereas the wait runs at dispatch

#

wait no that wont work, because smp

#

fuck

#

this would be a lot easier to solve if i didnt want to support wait on multiple objects as a primitive

haughty cipher
#

ok wont be working on anything for another like 5-6 hours probs but ive got a few goals coming up that are left turns from the filesystem/io ive been working on

#

going to add two things to the bootloader and then work on the mm some

#

bootloader things:

  • actually parsing two (2) acpi tables
    • DBG2 and as a fallback DBGP to let me pass along earlycon info to the kernel
  • GOP and a framebuffer finally just so i can have something to map when im reworking mm things
#

mm things:

  • my pmm and page allocator are ass (rn its a single free list and a virtual buddy allocator that allocates bunches of pages from the single page free list)
  • i want to look into SRAT things and numa
  • need better mapping api and pte abstraction
  • map the framebuffer while im at it
  • the newly parsed earlycon from the loader might need mapping (i may actually legit construct an acpi-style GAS for it in the cases where im not somehow getting one from the tables)
#

for the new pmm/page allocator im debating between:

  • map all usable memory in what amounts to an hhdm with the holes removed and just use the buddy on that (i can cram buddy order into it ez)
  • figure out what llfree is and how it works since i keep hearing about it
#

(if you have opinions please do tell but like give a justification for it, and note that while i do care about perf i will sacrifice small amounts of perf for readability and simplicity of the code since this is a learning project)

tiny summit
#

There is also SPCR

haughty cipher
#

oh right that thing

tiny summit
#

for uart discovery

#

And it's inconsistent whether real hw exposes spcr or dbg2

haughty cipher
#

thanks for the reminder to look at it when i get there lol

tiny summit
#

On arm, spcr is usually exposed though since linux relies on it for uart

haughty cipher
#

good to know

#

qemu virt-acpi machine uses dbg2 for earlycon

#

so thats my initial focus

#

but def good to know about spcr

#

the idea with the earlycon thing btw, is that itll effectively be passing to the kernel a tagged union:

union(enum) {
  e9,
  uart16650: GAS,
  pl011: GAS,
  ... // more as i encounter them
}
#

and also probably pass the namepath in addition to the GAS for the earlycon setup

#

(bootloader will map it)

#

too bad qemu is dumb and doesnt actually adhere to the standards correctly for the namepath field of dbg2 at least in the arm virt-acpi machine

#

(in that the namepath is relative to \_SB instead of being fully qualified like its supposed to be)

#

i was going to account for shit like that anyway because never trust the firmware but still annoys me

haughty cipher
#

did the GOP stuff today so now i have framebuffers enumerated and set up ig

#

not mapped or using but yknow

#

it exists at least

#

so i can have it when i go to town on my mm

#

next thing im going to work on isnt quite the mm actually, im going to be working on enumeration stuff

#

i want to figure out cpu hierarchy stuff, generate my own cpu ids, and then parse the SRAT

#

new mm gonna support numa

#

(by which i mean each nume node gets its own instance of the page allocator)

#

(also updated to uacpi 5.0 preview branch which saves having to trim trailing whitespace every log message)

haughty cipher
#

added quick and dirty srat parsing

#

and starting writing up some initial stuff reworking early init until i started getting sleepy lol

#

we goin numa compat this version

#

will need to rework a lot of stuff in the init especially in the mm which is daunting but i wanna do it semi-right this time lmao

#

new setup plans (roughly):

  • all usable phys mem mapped always in a compacted single region
  • segments in regions keep the same virtual alignment relative to 2mb blocks as physical and never share a 2mb block
    • so the last page in a 1gb block will still be the last page in a 2mb block but may not be the last in a 1gb virtual block
    • this means a gap will never exceed 4mb - 8k (segment ends on first page of 2mb block, next starts on last page of 2mb block)
    • allows physical allocations up to 2mb if the physmem is arranged in a cooperative way
  • pfms in the pfmdb point to their pte in this compacted region so phys->virt is doable with simple indirection, virt to phys is easy already because of recursive paging
  • buddy order is stored in the pfmdb for free buddies instead of using the page itself
  • each numa node gets its own page allocator
  • pfm stores numa node id to allow freeing to the correct page allocator
    • because there's no longer linked-list-of-pages bullshit going on i can free up 72(!) bits in the pfmdb from free pages to use for all this
    • cant remove locks yet though, because im too stupid to figure out a lock-free buddy on my own
      • if you got info on lock-free buddy alloc HMU
  • devices associated with a node can allocate from that node (duh), otherwise default is to allocate from current-cpu
  • memory pages not listed in SRAT get assigned to existing nodes round-robin in 2mb-minimum 2mb-aligned 3mb-max blocks
  • other things not in SRAT get assigned to numa node 0 or round robin depending on what it is
  • if theres no SRAT then a default numa node 0 gets created and then put in node 0 and round-robin work out to the same exact algorithm
  • im open to other allocators like llfree but i dont get llfree yet so im sticking with my already working buddy allocator
  • going to try and add limited resize to the buddy at some point maybe?
  • parse cpu hierarchy on x86 (its literally just free info on arm too so no issues there) so i can set up cpu ids and masks too
haughty cipher
#

for when i get around to graphical terminal stuff

haughty cipher
#

is it really worth worrying about numa nodes for the page tables themselves?

kindred isle
haughty cipher
#

ugh

polar pilot
#

it's still a memory access

haughty cipher
#

i hate mm bootstrapping lmao

#

makes sense that itd be good to have separate tables per node but it kinda sucks to bootstrap

#

should i even bother with numa tbh

kindred isle
#

somthing like an IPI?

polar pilot
#

hm good point

#

might not be worth the complexity

haughty cipher
#

but also the TLB id expect to absorb most of the issues with tables being on the wrong node

polar pilot
#

i also thought about that

kindred isle
kindred isle
#

though for HHDM or other kinds it couldnt hurt if you make it simple to work in

haughty cipher
#

i do use global mappings

#

except for the page tables themselves, which cant be because i do recursive page tables and amd has the global bit as reserved-must-be-0 on the higher level page tables

kindred isle
#

no HHDM slongeslab

#

tho fair fair

#

btw RISC-V cant do recurrsive tables

haughty cipher
#

even if i had an hhdm id use recursive page tables

haughty cipher
kindred isle
#

fair fair

#

just thought id mention is all

haughty cipher
#

yeah

#

nw

kindred isle
#

oh btw did you ever wana get arround to me testing the nvme?

haughty cipher
#

not ready yet because im still E9 only for logs

#

im closer than i was tho lol

#

the other numa thing im concern about is the PFMdb

#

because the boundary between numa segments dont have to align on the edge of pages-of-pfms

kindred isle
#

i am gonna have to use my other testing device for nvme tho so you will need FB logs and not jusr UART

haughty cipher
kindred isle
haughty cipher
#

esp now that ive picked out a font and i even have the GOP stuff done in the loader now so i can do that eventually

haughty cipher
#

does mean i need to split my early mm init function tho

#

oh hm

#

i need the pfmdb to properly map the acpi stuff for uacpi

#

but i need the numa stuff from acpi to set up the pfmdb properly

kindred isle
#

only init the first NUMA node on the BSP then on AP init i would do NUMA crap then

#

and if you cant detect it right away just reinit things as NUMA aware later

haughty cipher
#

most numa stuff will init on-demand

#

but as a bare minimum i need to allocate single pages for the pfmdb

#

(and for other early init stuff)

#

which means i need to know what memory regions are node 0 super early

#

maybe i just parse the SRAT in the bootloader for memory info tbh

kindred isle
#

you could use your loader to parse the ACPI/SMBios for NUMA

haughty cipher
#

yeah

kindred isle
#

and avoid issues

#

@ mint when is this added to limine

haughty cipher
#

i can have the bootloader put the numa node id into the memmap yeah

finite ether
#

or prekernel or whatever

kindred isle
#

id prolly have a seperate map imo?

#

because the main map may have more fragmentation

#

and could make the parsing more annoying pre mem

haughty cipher
#

not really

kindred isle
#

i mean the limine memory map was like 50 entries trl it would be nice to have a simpler one for nodes as a total as id want to make my own table for that regardless

#

idk how your loader sorts it though

haughty cipher
#

the node of a page will be in the pfmdb when im done setting it up

#

so i dont really care how fragmented the memmap is since i dont keep it long term

kindred isle
#

fair

#

maybe we just have diffrent ideas on how we set it uo

haughty cipher
#

yeah

kindred isle
#

and thats okay

haughty cipher
#

my loader does drop reserved entries and stuff like that

kindred isle
#

when i init my pdnfb it would be nice to check a seperate thing for the NUMA node as i think it would be an easier check to have it there when making it more aware

haughty cipher
#

this is the final memmap its passing to kernel

haughty cipher
#

so as long as i can make the loader split entries properly to set node then its fine

kindred isle
#

shouldnt pfndb entries be 64 bytes anyways for cache lines & locks n crap

haughty cipher
#

mine are 32 atm

#

NT uses 48 which is disgust

kindred isle
#

i was planning to keep them always padded to 64 to have them sit on thier own cache line

kindred isle
#

iirc linux uses 64

#

and the worlds most fucked up union

#

well @rigid python's union may take the cake but

haughty cipher
#

i insist on mine being a power of 2 so if i have to grow my worlds most fucked up union itll go to 64

kindred isle
#

64 is better for optimization anyways

haughty cipher
#

yeah but i want it smaller to save space in the pfmdb

#

and i like the challenge of cramming shit into fucked up unions

kindred isle
#

fair fair

#

@rigid python managed 16 bytes

haughty cipher
#

damn nice

kindred isle
#

go get the screenshot

#

you could share the idea

rigid python
kindred isle
#

yeah your a fucking wizard

rigid python
rigid python
haughty cipher
rigid python
#

also i dont store much into the structure at all which im sure will get more problematic as i go forward too :P

haughty cipher
#

mhm

#

i prefer virtually sparse personally

#

oh god

#

i forgot how ass debugging the bootloader is

last pebble
#

yeah lol pe stuff is undebuggable

haughty cipher
#

fun fact that idk if its llvm or zigs fault

#

but the unwind info for the pdb

#

just doesnt exist

last pebble
#

tbh printf is usually enough

#

like its a single threaded program its easy to debug

haughty cipher
#

yeah but i cant get a fuckin backtrace

#

which sucks ass

last pebble
#

low level handover code i had to debug with bochs every now and again

last pebble
haughty cipher
#

ok i found a spot that lets me get error return traces at least

#

ok theres some definitely wrong logic here

kindred isle
#

And then have an option to have a compact PFNdb or the more normal one

#

And you have to have the normal one for extended features

#

That way you can have the compact one for memory constrained systems

rigid python
kindred isle
#

I think yours should be fine for a UNIX like kernel

#

And I’d probably not store page cache stuff in there but part of the page cache it’s self lol

#

Though maybe it could be useful?

#

Could also reuse the double linkage there for page cache

#

Etc etc

#

You gotta think with portals

rigid python
rigid python
kindred isle
#

Damn slongeslab

#

(Tho let’s not hyjack this thread

rigid python
#

right
apologies to the author if i did..

haughty cipher
#

no worries

#

yallre good

#

testing with actually two nodes

#

seems to work

#

not sure how much im gonna do today tbh

#

next step is to make a proper memmap allocator that can request a node

#

instead of relying on single large free block

#

once i do that i can work on new mm

#

order of ops for new mm init will be:

  • sysptes and pfmdb as now, but allocate pfmdb pages from best-guess nodes
  • also map all pages that have pfms in a compacted way as i talked about [here](#1312232715193683988 message)
  • return back to the main kmain for uacpi early tables
    • parse MADT and allocate processor control regions as now (but from the right node mem for the cpu)
    • parse SRAT
      • use the memmap allocator to allocate one page per node to hold the node info struct
      • give each percpu a pointer to its node struct
  • instead of a single buddy, create a buddy tree per node here
  • add all usable memory from the memmap to its node's buddy
#

result of all this is buddy alloc becomes phys-contiguous which means i can remove my kludge for the GIC ITS bullshit on aarch64

#

(oh and before creating the buddies and stuff the arch gets to reserve any page it wants for whatever, which is currently only used by x86 to reserve one (1) page for the ap trampoline)

#

aarch64 will need to have an ap trampoline but it doesnt need to manually alloc because theres no restriction to where it is in memory it just happens to run in no-mmu mode so all phys addresses

#

my brain is turning to mush so im calling it a night early i think, ill take having the numa node info at all for now lol

haughty cipher
#

not sure if ill get anything done today but if i do itll be memblock

#

i dont think ill actually implement memblock free tho

#

since i dont really expect to need it

haughty cipher
#

tho actually

#

memblock ought to make this easier

haughty cipher
#

ok lets see if it works with this memblock setup

#

nvm first to find out why theres some weird program header page overlap perms shit with my new .init section stuff

#

oh lmao

#

it isnt even because of that

#

im just stupid

#

eyyyyy the memblock thingy works

haughty cipher
#

next thing to do is probably mapping all normal-mem so i can get phys-contig allocation

#

idk if ill do that quite yet though, having a bit of mental struggle figuring out how to do it and got other stuff going on in life

#

(may also take a sidequest to write a BDF parser tool to process a font into a data structure i can include in the compilation using zon)

haughty cipher
#

ok time for that mapping-all-normal-mem thing

haughty cipher
#

ok lets see if this works lmao

#

thats a nope lmao

#

oh i unmapped a thing im stupid lmao

haughty cipher
#

slowly inching towards having this working lmao

haughty cipher
#

oh god

#

i hate debugging this thing

#

mostly because i cant get good stack traces without it lmao

haughty cipher
#

ok it might be working now actually

#

nvm

#

agony

kindred isle
#

The cycle of osDev in three messages

haughty cipher
#

i love when the allocator page faults in the middle of trying to stack trace

#

so i just. dont get a trace

#

oh cool its page faulting in memset

#

even better

#

ok i found the assert thats panicking here

#

now to figure out why

#

oh

#

im stupid

#

yo progress

kindred isle
#

Wait page faults are considered unhandled?

haughty cipher
#

so yeah

kindred isle
#

Fair fair just didn’t expect that lol

#

What are you working on rn btw?

#

I forget 💀

haughty cipher
#

reworking my mm

kindred isle
#

Ahhh cool cool

haughty cipher
kindred isle
#

Yeah yeah that’s normal

haughty cipher
#

this error makes no sense

#

because the page shouldnt have been able to be freed

#

so why is it trying to fiddle with it

#

time to add more printfs

#

OH

#

maybe i found it idk

#

scared to call it but this bug feels like an obvious reason

#

and it wouldnt have occurred in the old model

#

because in the old model the buddy alloc couldnt have holes

#

there was one page of acpi nvs in the middle of two usable sections

#

and the thing didnt detect the size mismatch so it merged the two on either side

#

and blobbed hte acpi nvs in

#

but the acpi nvs bit wasnt mapped in that virt area

#

so it page faulted later trying to split that again

#

and now suddenly i have an allocator

#

which means i can see the stupid stack trace for the outer error here lmao

#

and that looks like tiny fix

#

ok now its triple faulting later which is weirdge

#

somehow the percpu block is getting unmapped

#

and if i turn on the accel it spams this

#

not sure how long ill keep going tonight

#

oh that one is a different issue now solved

#

GOT IT

#

IT WORKS

#

the nonpaged pool is now physically contiguous and numa aware

#

aarch64 doesnt compile anymore because the GIC ITS code relies on now-removed apis but that shouldnt be too bad to update once i have the energy

#

one asterisk to numa-aware is the that kernel page tables are not per-node

#

but i expect TLBs to take up a lot of the downside there

#

(and i dont want to deal with syncing a bunch of page tables on top of syncing tlbs)

#

sadly i have to nest iterating the srat inside iterating the madt for this

#

at least to do it semi-sanely

#

but thats a small cost taken only once so whatevs

#

ill also be able to remove my fixed dma allocation on aarch64 now

#

because it only existed to force a physically contiguous pool to allocate ITS tables from

#

(which in practice multi-page tables really arent needed unless you have thousands of MSIs on a single device or the ITS doesnt support two-level device tables, both of which are unlikely)

#

(ig they are needed for the LPI tables but theres one of that total)

#

the its setup on the virt machine has enough device bits that for two-level device tables which take up a full page at the lower level the upper level needs 1024 bytes, aka a quarter of a page

#

so the only one that actually needs multiple physically contiguous pages is the LPI configuration table

#

of which there is one per system

#

which needs minimum two physically contiguous pages (and must be a power of 2 pages)

#

so that isnt bad at all even without physically contiguous pages

#

theres two (2) things that are a bit fiddly with the new mm setup tho

#

that being freeing the x86 ap trampoline and freeing the uacpi early tables block

#

and thats only because those start out as memblock allocations which are identity physical addresses in the uefi tables, but have to be freed as virtual addresses

#

the only thing id want to fix rn is the adding pages to the buddy

#

which rn is done one page at a time so i dont have to properly handle grouping up blocks to free, but thats slow af

#

lord that sucked to work on though

#

i hate debugging early init related things

haughty cipher
#

i may also ditch mapping acpi tables in the bootloader

#

ill keep mapping the FACS tho since thats permanent

#

but if the acpi tables are marked reclaimable then the new mm setup will map them anyway

#

and because the loader is getting numa info from the srat i dont need the tables until after that mapping occurs

#

which would allow freeing the tables in theory

#

in theory i could probably ditch early tables now too but the code is cleaner if i dont

#

(early tables lets me map the percpu blocks which then lets the allocator use percpu to get the current core's numa node, instead of having to special case for before percpu is set up to have an allocator for uacpi init)

haughty cipher
#

next thing to do after i get the mm up is probably reworking sync stuff

#

cause rn its in a bad spot (or rather an unreliable spot)

#

it works most of the time

#

but most is kinda not good enough for a sync primitive lol

#

@finite ether how do you prevent the race condition where a sync object gets signalled after the initial trylock check but before the thread is queued into the wait list?

finite ether
#

youd need to be mroe specific

#

but what I do is the windows 7 way

haughty cipher
# finite ether what trylock check?

like if you wait on a sync object presumably it checks if it its already signalled so you dont wait on an unlocked mutex for example, but im running into issues where after that check the thing gets signalled but before i can get into the queue to get the thread released

haughty cipher
finite ether
#

so this wouldnt happen

haughty cipher
#

it still takes time between stopping spinning and actually being on the list to wait though, no?

finite ether
#

ahh ok I get it

#

you mean

#
A:
tries to acquire lock, fails
<B unlocks lock, signals waiters>
blocks until lock is signalled
finite ether
# haughty cipher exactly

one thing you could do is have a lock protecting the mutex state such that when you go to sleep that lock is released

#

I think this is a case where solaris' weird thread-lock-is-a-pointer thing could be useful

haughty cipher
finite ether
tiny summit
#

what does blocks until lock is signalled entail? how is signaling handled?

#

how you best handle this depends on how you implement signaling

finite ether
#

yeah that's pretty much it

haughty cipher
finite ether
haughty cipher
#

i give each thread a list of wait blocks and each waithandle a list of wait blocks and the object provides a check_wait function for the waithandle it owns to use

haughty cipher
#

for example

tiny summit
#

if you have something like a wait queue, you can use sequence numbers to do a wait-only-if-no-wakes-happened

finite ether
tiny summit
#

if you're using a semaphore, you get this "for free"

haughty cipher
#

i use wait queues

haughty cipher
finite ether
#

because blocking is expensive when you could just grab it

haughty cipher
#

yeah but again if you dont add to a queue first the intermediate state solution wouldnt solve the race condition

tiny summit
#

with wait queues you always want to have a (potentially restricted to only certain predicates) wait_if primitive

#

and not a wait() primitive

haughty cipher
finite ether
#

but you were talking about the "fast path"

#

the fast path is grabbing the lock uncontended

haughty cipher
finite ether
#

when you do need to block, you need to avoid the race condition by doing a cmpxchg

haughty cipher
finite ether
#

if it fails -> someone satisfied the wait while it was prepared, back out

#

if not -> block

tiny summit
haughty cipher
tiny summit
#

yeah sure but the predicate should be checked at add-to-the-list time

haughty cipher
finite ether
haughty cipher
finite ether
#

then to wake up you do a cmpxchg too

haughty cipher
#

sorta

tiny summit
#

it should be something like

if mutex.try_lock() {
    return;
}
if waitq.wait_if(|| mutex.is_taken()) == predicate_fail {
    goto retry;
}
finite ether
#
  // Three cases may occur here:
        // 1. The wait was still preparing (status == .InProgress) and we interrupted it.
        // 2. The wait was already committed (status == .Committed) and we satisfied it.
        // 3. The wait was already satisfied by another object (status == .Satisfied).

        // 1.
        if (td.wait_status.cmpxchgStrong(.InProgress, .Satisfied, .acq_rel, .monotonic) == null) {
            // ...
        }

        // 2.
        else if (td.wait_status.cmpxchgStrong(.Committed, .Satisfied, .acq_rel, .monotonic) == null) {
            // ...
        }

        // 3.
        else if (td.wait_status.load(.acquire) == .Satisfied) {
            // ...
        }

#

and you only unblock in 2.

haughty cipher
#

mhm

tiny summit
haughty cipher
tiny summit
#

between the setup and the CAS

haughty cipher
#

ok cool

#

thats what i was missing

tiny summit
#

basically this splits the wait into a prepare() + commit()

finite ether
#

exactly

#

this is what allowed the windows devs to break the dispatcher lock

#

to me this seems more intuitive, I'm not sure how wait_if works

haughty cipher
#

i assume wait_if is basically the same thing but with a callback

#

instead of splitting it

tiny summit
#

there are multiple possible implementation strategies, but that is one of them, yeah

#

others are sequence numbers or protecting both the queue and the predicate by a spinlock

haughty cipher
#

mhm

#

ill work on fixing my code to actually do this right after i get aarch64 updated to my new mm then

tiny summit
#

sequence numbers in the sense of:

s = seqnum.load()
p = check_predicate()
if (!p)
    bail out
atomically_check_if_s_did_not_increase_and_add_waiter(self)
haughty cipher
#

mhm

tiny summit
#

the last step can be done by a DWCAS or a spinlock

haughty cipher
#

i think ill go with the intermediate state version since thats the most intuitive to me

finite ether
#

the windows video explains this really well

haughty cipher
#

yeah ill def watch that one before actually writing the code

tiny summit
#

the prepare() + commit() impl has higher overhead on predicate failure (since you're doing + undoing the list manipulation)

#

but ig this doesn't matter in the mutex case since you can just check before calling into it

haughty cipher
#

yeah ill always be checking the predicate before preparing as a fast path anyway

finite ether
tiny summit
#

yeah that's true

haughty cipher
#

tbh thats true for most things

#

if youre going to try to block thats the slow path

tiny summit
#

well, there could be cases where checking the predicate is expensive

#

but yes, it mostly doesn't matter

tiny summit
haughty cipher
#

anyway this is all gonna have to wait because i got distracted by space things

#

did get aarch64 updated to the new mm things tho

#

but now its late and im gonna go do not-coding things for the rest of the evening

haughty cipher
#

and removed the old dmamem reservation stuff since I don't need it anymore

#

the new mm being physically continuous and all

haughty cipher
#

suddenly it freezes always and i was confused for a while until i realised i typed != instead of == somewhere 😭

#

turns out i was shockingly close to having the dispatcher already correct

#

just sucks ass to try and be certain here lmao

#

no its still fucked

#

damnit

haughty cipher
#

actually hang on

#

dont need to do wait list cleanup in signal_wait_block

#

fuckin hell

#

ok the completion callback variant of IRPs is clearly thoroughly fucked

#

if i change the partition manager stuff to not use it suddenly its working every time

#

ok now to quickly make the memblock -> buddy conversion not slow af

#

(it was freeing one page at a time which is uh. not ideal)

#

actually hang on

#

i dont think thats the main culprit

#

i bet the culprit is me memsetting freed blocks to 0 lmao

#

memsetting all usable memory sounds slow to me

#

and sure enough

#

alright thats all fixed now too

#

so the dispatcher is more reliable, i killed a feature in IRP to fix a bug with it i couldnt isolate which i originally thought was the dispatchers fault, the mm init is way way way faster now and using the new mm that is set up a good bit better

#

next task: a font

#

going to be taking a diversion to write a tool that preprocesses a bdf font into something i can just include in the kernel, and then ill have to do framebuffer work to draw the font

#

and then ill make an fb terminal to actually log to

#

doing that should let me test on real hardware finally too!

haughty cipher
#

ok time to see if the shit i transformed this font into actually compiles

haughty cipher
#

maybe lmao

#

now its triple faulting when i actually map the fb to vmem lmao

#

oh that was just me being stupid lmao

#

ez fix

haughty cipher
#

tiny fix

#

ok gonna try printing out the device tree to this fb now

#

next up ill hook this up to the log ring but thatll have to wait for morrow

#

(shouldnt be that bad though)

#

once this is hooked into logging i can theoretically try it on real hardware too

#

my hopes of it working on real hw arent that high tho lol

haughty cipher
#

def liking this font too

polar pilot
#

yeah the font is very nice

haughty cipher
#

im tempted to add padding as an option for the framebuffer logs

#

like half a character rounded down on each side or something

kindred isle
haughty cipher
#

picked what?

kindred isle
#

The cool sentence

#

Sphinx of black quartz, hear my vow

haughty cipher
#

oh yeah duh ofc

#

i always use it

haughty cipher
#

im debating if i want to actually make any changes to the font tbh

#

make the lowercase x connected

tiny summit
#

did you make the font yourself?

haughty cipher
#

MIT licensed

finite ether
kindred isle
#

I think it is

#

Crap

finite ether
#

I prefer the quick brown fox

haughty cipher
#

quick brown fox is a classic but im bored of it lol

#

i think i might make a halfway abstraction for simple log outputs tbh

#

something that exposes functions to set fg and bg color and write text

#

and then therell be a thing to make a log output out of that that uses a standard output format and consumes the structured log records

haughty cipher
#

ok time to try logging to framebuffer

toxic iris
haughty cipher
#

anyway i forgot to fill with bg when advancing a line whoops

hardy cloud
haughty cipher
haughty cipher
#

idk what nanoprintf is tbh

meager mauve
#

why would you use printf with zig lmao

meager mauve
hardy cloud
#

idk

#

i tought they meant that XD

haughty cipher
#

but also yeah why the hell would you want that?

meager mauve
#

why would you want printf in general tbh

#

its a shit api

haughty cipher
hardy cloud
#

oh XD

haughty cipher
#

and yeah zig has a really good fmt api anyway

hardy cloud
haughty cipher
#

anyway

#

i may fiddle with the colors a bit

meager mauve
haughty cipher
#

but its still super nice as an api

meager mauve
#

yea

#

about as nice as my c++ based api except without the awful macros

hardy cloud
#

wait, can i see that?

haughty cipher
#

and the impl lmao

#

zig comptime is goated for exactly this sort of thing

hardy cloud
#

oh i meant pitust's api XD

haughty cipher
#

oh yeah i cant link you that lmao

hardy cloud
#

thx

haughty cipher
#

ok these colors are a tad better for sure

hardy cloud
#

these are mine

#
  • orange for warning
haughty cipher
#

yeah

#

im using the same palette as zig's default logger does as far as chocies go

#

im just fiddling with the exact rgb for them

hardy cloud
#

wait rgb?

#

i'm stuck with terminal colors for now, lol

haughty cipher
#

for encoding the pixels on the framebuffer yeah

haughty cipher
hardy cloud
#

i'm using flanterm

haughty cipher
#

ah

#

im doing this project for the learning so no flanterm for me lmao

kindred isle
#

use the RGB ansi codes :p

hardy cloud
#

they exist????

kindred isle
#

flanterm supports these

hardy cloud
#

bruh

haughty cipher
#

im debating if i want to wire in ansi code parsing lol

kindred isle
#

me when i dont google;

haughty cipher
#

rn the fbterm has a function for setting color based on a terminal color enum

kindred isle
#

it does more than color too

haughty cipher
#

not for an actual full scale terminal

kindred isle
#

whats your plan when you want that tho mmLol

#

also some ANSI codes are useful for logging somtimes

#

like cursor possision etc

#

or clearing the screen

#

cursor on/off

haughty cipher
#

ill do it eventually

#

zig has an abstraction over terminal code stuff anyway

#

because windows doesnt do ansi codes by default

meager mauve
#

ansi code parsing is really painful tbh

haughty cipher
#

also that lol

kindred isle
#

its a giant state machine isnt it?

meager mauve
#

yeah its a giant really complicated state machine

haughty cipher
#

the only downside with the zig abstraction is it doesnt let me plug in my own vtable atm

#

so im making my own copy of it

meager mauve
#

flanterm handles the linux standard escape codes but, no offence mint, its not a very good terminal emulator (i.e. me when no unicode)

and it doesnt handle the extra stuff you need to make a good terminal emulator in 2026 (like the kitty extension that lets you do actually reliable keyboard input lol)

meager mauve
#

lol

meager mauve
kindred isle
#

tbf if you need more than flanterm your prolly in the spot where X11 and xterm/others can be ran

kindred isle
meager mauve
#

i want to do reliable keyboard input in my tui app 🙃

meager mauve
kindred isle
#

damn

#

💀

meager mauve
#

i mean doing unicode requires doing font rendering so like

#

so you need to do most of the text rendering pipeline (you can mostly skip shaping and layout at least), you likely need a rasterizer, you need to do all of the crap relating to segmentation, and the state machine itself is not simple as well

#
  • flanterm doesnt handle resizing which is also "fun"
#

idk which exact features flanterm has apart from that

kindred isle
#

It’s easy to drop into any project in a bare environment?

meager mauve
#

flanterm? yes

kindred isle
#

Yeah, idk what else FT has either

meager mauve
#

flanterm is codepage 437 in general which kinda sucks

#

and it seems like flanterm doesnt have alternate buffer support?

#

which also sucks

last pebble
haughty cipher
#

gave it a bit of padding

last pebble
#

Add two c files and call one function

last pebble
meager mauve
#

honestly if your terminal cant draw a firefighter (dark skin tone) emoji its a shit terminal

kindred isle
#

Flanterm did manage to print out a ralsei with the block characters so it can’t be that bad?

last pebble
#

Tbh im glad it doesn't support Unicode, I dont need that shit in the kernel terminal emulator

meager mauve
#

its not good for a proper terminal

meager mauve
last pebble
#

Is the Linux built-in text terminal better?

meager mauve
toxic iris
#

Or just use serial and don't print anything to the screen

meager mauve
hardy cloud
#

XD

meager mauve
#

so is this: 🇵🇱🇵🇱🇵🇱🇵🇱

toxic iris
#

👨🟫🚒

kindred isle
meager mauve
haughty cipher
meager mauve
#

each flag is two code points

kindred isle
#

Oh I remember that fucking up emoji parsing

#

Because some emojis are multible charaters

#

Meaning I can’t properly track shit when I needed to

#

With regular JS stuff

haughty cipher
#

flag emojis just seem to not render on my computer idk why

meager mauve
kindred isle
#

Then what happened?

finite ether
kindred isle
#

I needed some funky things iirc

meager mauve
#

its also the case for certain forms of the german letters ü, ö and ä among others; and for hangul (which is korean writing) and some indic scripts

kindred isle
#

Ahhh

haughty cipher
kindred isle
#

I thought you said it didn’t happen to emoji

#

💀

finite ether
haughty cipher
#

yeah

meager mauve
#

its the case for many emoji including all flags

#

and the firefighter emoji

#

and for some hangul

toxic iris
#

A lot of emojis are combining shi

meager mauve
#

and indic scripts which are mostly the same as emoji

meager mauve
toxic iris
finite ether
#

It's completely freestanding afaik

haughty cipher
#

my font rendering rn only renders single codepoints and only if theyre present in the font

#

zig std has a codepoint iterator for utf8 its great

meager mauve
finite ether
#

No it's freestanding

#

libghostty

meager mauve
#

oh is there a parser thats freestanding

#

that would be awesome

finite ether
#

They have a toy terminal with raylib

#

Yes

meager mauve
#

oh neat

finite ether
#

Handles kitty protocol too

#

and other stuff

meager mauve
finite ether
#

It's a C library

meager mauve
#

they make it way too easy to write broken code that falls apart with emoji

#

or with you know. some languages that arent english

haughty cipher
meager mauve
#

just iterate over the bytes for that tbh

finite ether
#

You don't need emojis in a tty

meager mauve
#

and assume utf8 == ascii == latin-1 == code page 437

haughty cipher
meager mauve
#

oh okay

#

thats neat

haughty cipher
#

i do have to convert to the bullshit encoding this font uses

#

which doesnt seem to match any of those normal ones for box drawing chars

#

this also lets me use the visible control variants ␀␌␍␊␉

toxic iris
haughty cipher
#

so the way i handle this rn is the fbterm iterates codepoints (since i only handle single-codepoint chars) and then have a switch that converts \r into resetting the column, \n into advancing the line, \t into four spaces worth of bg, and the visible controls and box drawing unicode chars into the encoding the font uses

haughty cipher
meager mauve
#

(hint: its not, in fact, that easy; the state machine is fucking pain)

haughty cipher
#

fair lol

#

one of these days ill actually learn it

toxic iris
#

Terminal emulator state machines are painful

haughty cipher
#

mhm

#

this is why im using the most shrimple possible setup for my debug log output

haughty cipher
#

wonder if ive got an unused usb stick i can put this disk image on tbh

#

since in theory im now set to at least make a first attempt at real hardware

#

oh yeah

#

zig 0.16.0 got tagged

#

so i should probs work on updating and pinning to that sometime

haughty cipher
#

taking a break both for irl reasons and also because the language updated and all my deps are now temporarily broken and id rather be lazy and wait on others to update them instead of doing it myself

#

and by all my deps i mean my one dep and its sub-deps

toxic iris
#

Curse of Zig

haughty cipher
#

ig

#

i could just not update

#

but i want to actually pin to a version that isnt a random nightly

haughty cipher
#

in the meantime i might whip up a devlog about the silly trick i found for making the lookup of char to glyph at comptime for my basic fbterm rendering

#

zig has a type called EnumIndexer which lets you convert from values of a (possibly sparse) enum into a compact index space, and a type called EnumArray thats basically just an array mapped to by an EnumIndexer

#

so what i do is i generate an enum whose values are all the character encoding values the font uses, and construct at comptime an EnumArray from that enum. then i can use @enumFromInt (or the fallible std one that lets me have a fallback) to convert from codepoint to enum value and then the EnumArray to get the glyph

haughty cipher
#

decided on a whim to look at FRED and holy shit this is amazing

pallid plaza
#

yes

#

kinda crazy how we were already discussing FRED since 2021 in here

haughty cipher
#

reminds me a lot of how exception handling stuff works on aarch64 actually

#

in a positive way

haughty cipher
#

its true ive been saying this lmao

kindred isle
haughty cipher
kindred isle
#

Lmfao XD

#

It did the same to me

#

Mint wondered who would be the first hobby kernel to implement it

#

I skimmed over it and was convinced

#

Until I spent 70% of the time it took to finish it trying to get a working emulator

#

💀

haughty cipher
#

lmao

kindred isle
#

That’s also why I got the cool role lol

haughty cipher
#

ok as soon as i get dressed and boot up the main computer im migrating this thread to #1495061753715884222

#

would be nice if it could easily just be moved lol