#tabula imaginarium: osdev experiments in zig
1 messages · Page 4 of 1
and all processor-local interrupts (like the timer, or other PPIs and SGIs on aarch64) will be configured by scheduling a DPC to all targets after the smp is initialized
and/or ill make a list of them somewhere and hardcode this tbh
id like to keep this generic-ish though
if i dont do the list thing then DPC irq init (and tbh maybe also timers) will definitely be hardcoded during smp startup because dpcs will be how to have more added later if needed by devices
what do yall think on that front actually?
may as well take advice if anyone has it
I dont know if this is useful advice for you but I do DPCs entirely in software
I have an ipl for dpcs, and they're executed whenever a cpu lowers from/past that ipl
that could work and I considered it but I didn't want to do that route
mostly because thatd be yet more shit i have to cram into my post-context switch handler
which is already getting painfully complex lmao
had a somewhat obvious and simple idea to solve half of this tbh
which is to just give my percpu modules an "init on AP" function
im actually very happy with how i did percpu storage btw
my hal/smp.zig PCR (processor control region) struct gets padded to page-length and then instantiated once on each cpu.
it has, besides the smp-general support stuff, a field called module, which points to a struct defined in my root krnl.zig file
each field of the modules struct has to either define a default value or a .init function and can optionally define other functions for other points in init
i had late_init for after the mm is fully up already (used for allocating the idle thread stacks for instance)
now adding ap_init which is called during ap startup, for setting up anything that needs to happen on a target processor
and confirmed i can now receive a DPC on other cores
on x86_64 anyway lmao
i uh dont have smp set up for aarch64 yet lol
tbh it looks easier than the x86_64 version overall, just because im not fiddling with getting perfect codes onto the apic
or dealing with real mode lmao
starting up a cpu on aarch64:
- put 0xC4000003 in w0
- put the MPIDR of the processor in x1
- put the ap startup function pointer in x2
- put the first argument of the ap startup function in x3
- run either
smcorhvcdepending on the value of a flag in the acpi tables/devicetree
it does have to be a physaddr function pointer
and the mmu will be disabled
but this still slaps compared to having to figure out real mode segmentation bullshit for the trampoline on x86
i wont even have to relocate it to lowmem or anything
shit fuckin slaps
anyway not sure if ill get anything else done today but im glad i did that before i forgot how i was going to do it
https://codeberg.org/Khitiara/imaginarium/src/commit/25f37b8846ce8902ae25e319a5201039a54d2180/docs/interrupts.txt wrote a bunch of docs/specs for my irq handling setup
found a weird maybe bug I'll need to investigate
where it looks like my gic priority code has an off by one but when I fixed that it suddenly didn't work at all even though in theory everything is using this same function for priority stuff
(I need to remap 0-f to f0-00 with that reverse in there, and was subtracting from 16 instead of 15)
how much yall wanna bet I forgot to set the priority mask during setup
yup
sure enough
now I don't know why it works anyway when the math is wrong
because dispatch is irql 2
so the bad math is turning that into 0xE0 when it should be 0xD0, but that should still be masking it?
unless the pmr has an undefined reset value?
can't check rn I'm in a car lmao (not driving)
got home and checked and it seems its architecturally defined for warm reset but i see nothing about other resets
o h im stupid lmao
turns out my set_group function for gic irqs was accessing the wrong registers 😅
so the call to set_group was just. disabling the interupt instead of changing the group
ok fixed that and one other off-by-one and now we good
ok ive got a docs site now
not published or anythin yet
but ive got a semblance of one in progress
thanks xq of the ashet project for the css theme lol
even got autodoc for the kernel on it
not sure how ill host it yet, dunno if codeberg has a gh pages like thing but if not ill cram it on a subdomain of my site probably
did run into https://github.com/ziglang/zig/issues/20283 though so for some reason it cant find the namespaces in there, dunno why
i honestly might do autodocs my own way instead of using the zig buildin setup
another pic of the docs before i get back to work on the actual kernel
though idk what part of this i actually wanna work on next
pub const TimerDivisor = enum(u32) {
@"2" = 0,
@"4" = 1,
@"8" = 2,
@"16" = 3,
@"32" = 8,
@"64" = 9,
@"128" = 10,
@"1" = 11,
};
ok the apic timer divide config is fucked up actually
tick tick tick :D
what to do with it? dunno wasnt trying to actually do anything interesting yet just wanted it ticking lol
(just figured out how to get the frequencies from WHPX and stubbed out manual calibration with a panic for now on x86. aarch64 will be easier, theres a fuckin cntfrq register i can just read lmao)
next up when im not feeling just really sleepy for no reason is the arm generic timer
and then after that we back in acpi land with device enumeration
(technically we'll be in acpi land for the generic timer too, im using an acpi table to get the interrupt number, but whatever dont worry about that lol)
alright we tickin on arm too now
copied a bunch of my driver registration stuff in and now to see if it works on the new kernel lmao
once i test this im going to bed tho lmao
(well test and fix some of the stupider bugs)
yknow idk why i wasnt expecting this known working code to still work in the new context but after a few quick compile error fixes it does seem to be
albeit shockingly slowly
esp in context of what uacpi is doing up above
def going to try and profile this shit at some point but whatever the baseline works i can start copying in actual drivers soon
oh also forgot to mention but we got hypervisor msrs working for getting tsc and apic frequencies now
which means i can keep putting off apic timer calibration

(msrs is for hyperv. can use cpuid to get the frequency under kvm, at least with qemu. not sure if raw kvm does the cpuid leaf)
also did do some tweaks to how devices and irps are structured thatll hopefully help make this slightly more sane lmao
its a lot closer to the NT kernel device model now actually, albeit with the benefit of not overloading terms like they do
the new scheme is:
- theres a global tree of struct Device
- each Device has one root Function and zero or more leaf Functions
- the root Function of the Device is installed by the bus driver which discovered the device
- all other Functions have a Driver and a parent Function, which chain must eventually terminate at the root Function
- a Driver has an attach function which takes a Device and returns bool. if attach returns true, the Driver has installed Function(s) in the device's function tree
- a Driver has a dispatch function which takes an Irp
- an Irp has a stack of Entries, and each Entry has an associated Function and Operation (a bigass union of different methods and parameters a device can have)
- a Driver's dispatch function peeks the top Entry of the Irp and attempts to perform the specified Operation on the attached device Function, possibly pushing a new Entry to the Irp to dispatch to a lower level device
- when dispatch returns, the caller can peek the top Entry to check its status
- if/when an Entry is completed, the caller or callback can pop the Entry to get the result and do whatever with it
as an example chain, a filesystem function would be on top of a volume io function, which could either be virtual (for spanning multiple disks) or on top of a disk partition function, and the disk partition would be on a device having the actual disk as a parent etc
or as a lower level example, a device on the pci bus with acpi provided methods additionally would have a root acpi or pci function with the other on top of it, and the actual driver would be on top of that. the top driver could ask to enumerate some generic property of the device and whichever of the pci and acpi drivers can provide that property then answers
each function can be containerof'd to get a driver-specific structure with bonus stuff on it also
(also while what i described is the theory, in practice i expect to keep the leaf functions and the bus functions on separate lists where each leaf gets a singly linked list and if it has no parent then the function to get parent will return the head of the bus list)
i learned about containerof/@fieldParentPtr in may 2024 and just fuckin never looked back lmao
im also considering giving each device node an attached buffer to allocate Functions from, make freeing the whole mess easier
(also open to alternative names to Function, but i didnt want to call them devices because NT does that and it makes it so confusing when device nodes also exist at the same time)
out here implementing the for_each_node myself in zig because roundtripping through a callback nukes zig's error tracing etc but i dont want to use a ton of stack with recursion lmao
anyway
wonder how badly this will die if i try to do it on aarch64 without changing anything lmao
not. the answer is it does not die
fuckin hell yeah
I do NOT recognize most of these device ids lmao
do recognize ACPI0007 though, thats the processor object
and im going to guess ADMH0011 is a PL011 uart based on the id and name being COM0
apparently LNRO0005 is virtio-iommu
anyway next up is to figure out how im going to do generic pnp property storage and then once thats done ill be able to cram the last few bits i need from acpi enumeration into this and get started on pci enumeration
and then ill add a noop driver for processor objects/acpi processor devices and then ill be fully caught up to pre-rewrite imaginarium
never know what to do when the code just works first try lmao
the old version had a processor driver and a pci enumerator/bus driver; the new version has timer interrupts, a real slab, aarch64 support, and uefi runtime services
everything else both have
fn recurse(drv: *Driver, root: *Device, gpa: std.mem.Allocator, root_node: *ns.NamespaceNode) !void {
var iter: ?*ns.NamespaceNode = null;
var parent = root;
var parent_node: *ns.NamespaceNode = root_node;
var depth: u32 = 1;
while (depth > 0) {
if (try ns.node_next_typed(parent_node, &iter, .initMany(&.{ .device, .processor }))) |node| {
parent = try descend(drv, parent, gpa, node);
depth += 1;
parent_node = node;
iter = null;
} else {
iter = parent_node;
parent_node = parent_node.get_parent() orelse break;
depth -= 1;
}
}
}
yknow maybe i shouldnt call it recurse anymore, given its no longer recursive
though there is an (easily fixed) bug here actually that i just noticed
i think ill also make a function to print out the devie tree at some point
Never seen those before
what cpuid leaf are you using, and do you check the max hypervisor leaf? Because qemu + kvm reports the max leaf as 0x40000001 for me.
40000010, and I do check the max leaf
welcome to aarch64 qemu virt,acpi=on machine
idk how much dev ill do today but the plan if i do is to:
a) fix the bug i found late last night after id already shut down
b) maybe print the device tree to console
i really got to make hashing the kernel not the default or at least make a way to turn it off, it takes longer than all other build steps combined using my shitty tool lmao
ok for acpi-only enumeration this looks fairly reasonable to me
also looks reasonable on aarch64
ignore that integer overflow idk why thats happening though it is happening on both arches at least?
set virtio-mmio-transports to 0 and this is so nice
im using none of them and doing device discovery i dont need them yet lmao
Not bad
with PCI
(it stores all HIDs and CIDs, just only prints the "primary" one)
think ill change which pci cid is picks though, this one isnt useful
yeah thats better
final output for aarch64 too
with this we are tantalizingly close to having full parity with the pre-rewrite version
alright added one more file and we're not officially caught up to pre-rewrite imaginarium 🎉
up next: idk
maybe ill start fiddling with thread quanta so i can actually make use of the timer interrupt idk
maybe resource enumeration for devices and then work on storage or serial? idk
other thing coming soon will have to be docs for the io system, because that def needs it
(i also might work on my object manager setup too, undecided)
me: yknow i should look into codeberg pages so i can put up the imaginarium docs somewhere
codeberg: gets DDOSd outta nowhere
will work on that tomorrow™ sometime
basically only the stuff under docs works rn, apart from source being a link to the repo
api docs are struggling because of https://github.com/ziglang/zig/issues/20283
i think i found the bug
PR'd a one-liner change up to zig and now the api docs are actually fully working
https://khitiara.codeberg.page/imaginarium/docs/systems/io/ and docs up for the io/device/driver system
ok im completely redoing how my device properties are handled lmao
didnt actually speed anything up but now property-getting doesnt require going through a full driver chain and allocating an irp and the whole thing lmao
instead it requires a lookup in a hashmap which idk if thats better or worse but it feels better structured at least
fascinating that q35 is out here giving me a screen, keyboard, mouse, etc but no network by default and ahci 1.0 storage
and virt-acpi for aarch64 is giving no screen keyboard or mouse but a scsi storage controller and an ethernet controller
ok cool the autodocs fix i figured out got merged
me rn about my os
btw @last pebble does #1312232715193683988 message look logically correct? id use the callback thing but i lose a lot of zig ergonomics doing that
i basically tried to copy how your for each device method works
and it seems to be working?
Makes sense
well i swapped to doing apic base properly (aka ignore madt use msr) and also made it enable x2apic
and now im gp faulting in yield somehow
oh nvm
its on the EOI in my irq dispatcher
apparently either qemu or whpx enforces that you write 0 for eoi but only on x2apic
so thats funky
yknow i think something might be incorrect here lmao
ok this looks more like it lmao
ok yeah this shouldve been expected lol, but now i know whats making enumeration take as long as it is
the numbers are very inconsistent though so im not touching it atm
decided on a whim to configure qemu for an nvme controller behind a pcie-pci bridge and forgot that acpi will enumerate the empty slots lol
(also moved the nvme controller to addr 1 instead of 0 so aarch64 qemu doesnt get mad about it, but this is working there too)
(funny enough aarch64 isnt giving all those empty nodes from acpi, dunno why x86_64 is doing it tbh)
woke up today and decided to fix my memory caching shit
so now i got mair and pat set up
or will have once i finish fixing all the compiler errors my renaming things has introduced and test everything lol
simple thing i did that im quite happy with is i gave each device object an arena
used to manage the device's string table, property bag, and functions
was lookin through my ioapic code thanks to talk in #1385970208631427173 and now realised theres an error in my implementation lmao
one that ill fix later as part of some refactoring around the same code
so my future self doesnt forget, im currently only adding the 0x10 for the actual redirection table base when the GSI is one of the bottom 32 with possible isa irq redirection applications
gods im sleepy today lmao
anyway fixed that but idk if ive got it in me to actually do the refactor i was considering today
did it anyway
ioapics now have methods and also get stored instead of it re-iterating to find them literally every time
not sure how i want to handle empty pci slots tbh
like do i want to make acpi not create device objects for ADR-only devices and instead just do some form of lookup table for them so it can attach later above the pci driver?
@outer pawn if youre willing to share since i had a hard time figuring this part of the code out, how does reactos's acpi stuff handle that case? where acpi enumerates first and finds a device with just an ADR which then gets filled out by pci later?
It ignores it
Windows has a table of IDs that make actual PDOs out of. It doesn’t just make PDOs out of everything
so then how does the pci driver attach the acpi functions afterwards for the ones that do exist?
Through a private dispatch interface.
It pretty much manually retriggers the parse
that’s what windows 11 does right now
ah ok, good to know
yup, I wouldn’t bother mimicking the windows one though, it changes everyday few updates
yeah im not mimicking exactly more looking for the general ideas as inspo
not trying to be nt-compatible here just nt-inspired
Sounds good, you got it then good luck 
thanks!
im going to literally make one of my irp payloads just pass a GUID and an opaque pointer and then return an optional opaque pointer or error, and then drivers can use that for private dispatch extensions
initial version of that typed up so time to test
and it panicked
to the shock of noone probably
fixed the panic and now its page faulting 
and now its sorta but not quite working
oh fuck
yknow it might help if i actually appending this thing i make to the list it goes in
and now it works perfectly
lmao
actually taking this idea but backwards and making a set of ids to exclude (only one so far as PNP0C0F the pci interrupt link thingy)
need to double check this is still working on aarch64
yup
still good
this is a nice looking device tree for x86_64
and aarch64
next up probably resources but I'm really not sure how I want to handle those
probably going to take a bit of a break and ruminate on that
ok so the initial thoughts:
- device provides EITHER fixed resources or sets of alternatives for possible resources
- todo look into how acpi PRS works because i dont understand it yet
- if its mixed fixed and possible then the fixed ones are just a set with only one alternative
- io manager picks from alternatives to assign resources without conflicts, ideally prefer the default setup in PRS if applicable
- we only use consumer resources from acpi? im still not 100% on how producer/consumer resources work in acpi
- PCI BARs and MSIs count as resources
- because of the way i changed the ADR stuff earlier, the order of acpi vs pci resources is always fixed
- therefore, device drivers can rely on resources always being in a fixed order
@last pebble so you happen to understand how PRS works as compared to CRS? because i struggle to understand how its setting alternatives with the same abi
didnt get the last part
but _PRS is just a list of possible alternatives
whereas _CRS is the currently set resources
yeah that i get
are you asking who generates the correct data?
the thing i dont get is e.g. if a device has two irq resources how does it specify two different sets of alternatives there
because it cant just do more than two irq resources
can u show an example of what u mean
i still dont get it 
an irq resource can accept up to 65k different irqs
so it would be one resources with multiple irqs
if thats what u mean
i dont have one in ASL which is part of the confusion tbh
but the idea is: my device of whatever kind has two interrupts. in CRS itd put an irq resource for the first one with, say, GSI 36, and an irq resource for the second interrupt with GSI 37. if it wants to say that the first one can be any of GSIs 32-36 and the second can be anything 37-42 how would it do that
(in PRS)
resources are delimited with a different resource type
so itd put something else in between the two interrupts then?
lemme find an example
describes a group of resources which must be selected together
these
so at the root level of PRS each entry is an alternative and start/end dependent make groups of resources interpreted as a unit then?
yep
is the interrupt list in the irq resource a list of options or a list of separate interrupts?
because if each in the list is an option for that interrupt then suddenly this is making more sense lol
Some examples from real hw:
separate interrupts
if it wanted to specify exactly what you mentioned it would have to generate every combination
at least if i understand it correctly
could be wrong
so where it says IRQNoFlags {3,4,5,7,9,10,11,12} that means it uses all of those GSIs?
guess so
that sounds so wrong but ig lol
https://uefi.org/specs/ACPI/6.5/06_Device_Configuration.html#extended-interrupt-descriptor oh wait hang on i found a spec statement
we're wrong there
"To specify multiple interrupt numbers, this descriptor allows vendors to list an array of possible interrupt numbers, any one of which can be used." .... "Interrupt Table Length: Indicates the number of interrupt numbers that follow. When this descriptor is returned from _CRS, or when OSPM passes this descriptor to _SRS, this field must be set to 1."
oh cool then
the basic irq descriptor is way more vague about it
mood
but yeah thats the only option that makes remote sense
yeah
cool
ok now that i understand this time to actually figure out some dang data structures for my kernel side lmao
well pulled in my avl tree from the pre-rewrite because ill need it if i plan to actually check resource collisions
and surprisingly after fixing the compiler errors resulting from the breaking changes to zig since i wrote it it still passes tests
i mean yeah im exaggerating
/s
well the acpi resource listing didnt crash but i forgot to call the other half of it
i kinda want to do something similar to what you're doing now lol
the nt like driver/io model seems really nice
it slaps
i do have some nits but the overall design is excellent
um you drunk mate
i was forgetting to initialize the union
but idk why it output like that lmao
pci root port acpi resources, we poppin off now
that is awesome
its actually slightly wrong because i dont really want to enumerate produced resources like the bus numbers there
in general tho
and now that thats fixed
one of my favorite functions in zig continues to be ArrayList.shrinkRetainingCapacity
its great for printing shit to an arraylist buffer and then freeing the space without resizing the list if the followup to the print fails
did forget somethin though that i gotta fix rq
which is that its not enumerating properly for stuff that doesnt get accepted by a high level driver
oh welp
did that change and now its gp faulting lmao
well theres youre problem
yeah that could cause some problems
ok the freeing of the setup resources is causing memory corruption of some sort
and i dont know why
i hate diagnosing memory corruption 😭
ok i think this is an uncaught use-after-free
this is going to destroy me
gonna give up for the night shortly lol
one last attempt
going to swap this function to use the debug allocator in std and see if that complains
oh fuck
i think i found it
nope
fuckin bedge time
https://codeberg.org/Khitiara/imaginarium/commit/f7e518d10b4c2a2aff580d7aec62dca831ed2780 heres the relevant code if anyone is feeling up to read through and try to find the problem
i aint looking at it until tomorrow earliest and honestly even then idk givne im coming down with a cold lmao
and i know it isnt the allocator because im currently bypassing the allocator to use the debug one in the zig std
yup definitely got a cold
oh god the memory corruption bug was so fuckin stupid lmao
and i still dont entirely understand it tbqh
but it is fixed now
the pattern wasnt what i thought it was which really didnt help
i thought it was that it was failing for things with resources that had no driver to attach to
in reality, it was failing on things enumerated from the nested private dispatch from the pci enumeration
and the first device with no driver yet that had resources was one from the nested dispatch
theres some confusion still because the thing that finally fixed it was making it pass the allocator through IRPs but the irp was hardcoding to the same allocator as the other side was using before so that should only have been an issue with using the debug one and shouldnt have fixed anything by changing
but it somehow did
either that or that different-allocators error was masking my accidentally fixing the original issue? idk
anyway now that its working im quite happy with it lmaoooo
(i was already happy with the design it was just broken af earlier)
continue to be shocked every time i get something working on one arch and it suddenly works on the other one lmao
anyone happen to know how either windows or linux handle pci interrupt link devices?
im really not sure what i want to do with them
I sent u code with srs for it yesterday I think
oh lmao i was so focused on the irq resource bit i didnt notice what device it was
tbh im generally more curious about how nt does it atm because my driver/device model is much more similar to theirs, but still good to have the linux version
should probably redo some of the docs for io stuff since ive made a bunch of changes but too much feeling sick rn to do that
other next thing fwiw is pci BARs
and then maybe eventually ill get actual resource assignment instead of just using whatever the firmware gives me
qemu out here being weird with its aml again
instead of using the 0-for-namepath version for the PRT in apic mode, it uses a whole second pci interrupt link device instead
ok i think i know how i want to handle PRT stuff but not 100% sure
anyway first BAR time
bar enumeration done, forgot to post somethin here about it earlier lol
part of me isnt sure whether i want to leave the pci/acpi backchannel as a private backchannel or make it public. gonna document it either way though because this is an open source to try and learn with not undocumented enterprise hell lmao
more sick today than yesterday but still might get some osdev work done
https://khitiara.codeberg.page/imaginarium/devlog/26q1/ made a devlog setup albeit not much there, since i dont have much energy for involved coding rn
also updated docs
wild that im too sick to do osdev so i fall back on fuckin webdev of all things as something im capable of still
did you mean to type –? :^)
yes lmao
although i don't see why you'd place a dash there
also capitalize Zig programming language maybe, idk 🙏
very cool that you've set up a blog, i like reading stuff like that
ye me too, thats why i made it lol
fixed this and capitalized Zig
idk how to describe but its the way i write lol.
ah no sorry, it makes sense now
i was confused by the semicolon after the html entity
yeah it makes more sense when its actually a dash lol
ah yeah the semi always throws me off reading them too
oh also fwiw, the site's source is at https://codeberg.org/Khitiara/imaginarium/src/branch/rewrite/docs if anyone is curious
(except the actual autodocs wasm/js which is part of zig and output by the compiler because of a flag ive set, along with a tarball of the sources)
also worth noting that home and about have nothing on them yet so theyre just the contents of the template for the ssg im using, but devlog and docs are fully set up (apart from sparse content in the former case) and the source link works
Cool
its automatically set up so the devlog link at the top goes to the newest quarterly page and newer posts are put up top, with the left side nav sorted by date newest to oldest
unrelated, i love StringIndexContext/StringIndexAdapter in zig
its two types that i think are mainly for use for the compiler but are in the std so i can use em too
what they do is provide functionality to make a hashset/hashmap with u32 keys act like a set/map of strings, where the strings are stored in an arraylist
so i can call getOrPutContextAdapted on the hashmap with a string key and itll tell me if that string is already in the table but its only actually storing indices into the arraylist in the map
lets you just store 4 bytes to refer to a string while having O(1) access to the actual string bytes and it keeps the strings contiguous in memory and allows resizing the string byte array without invalidating all the u32s
i may rework the device properties stuff to have a single string table instead of 2.5
one think i definitely need to figure out and write is an RWLock
or whatever variant name you wanna use for it
a threaded one that is, not an rwspinlock i already got one of those
that and condition variables would be good to have i think
yeah i think ill do the string table change
im still so happy just to be seeing this output lol
nope, dont really mind it tbh
i was thinking of doing that since its considered redundant technically
i wouldnt mind either way tbh
the path is here purely as an informative thing, not to actually be used for anything too too important - the acpi driver keeps a pointer to the namespace_node with each kernel device object
fair
oh for completeness, aarch64 output
find() already accepts either option but generate does the full thing
cool
though idk if NT actually associates it with the _SB namespace object but i figured that makes sense
where did u see that id then?
my tree is almost identical to the NT one if you go to device manager on any nt-based system and do view->devices by connection
is there a chance your aml actually has that id somewhere?
if i go to the PCI root complex the path is there for it
hm
nope i checked, at least not on _SB
theres actually a bunch of devices under PCI0 on this system that are hardcoded to return 0 for STA but do have that HID lmao
but no hid on the root _SB
afaik this HID is hardcoded
i dont have the same thing as u
view -> devices by connection
the default view groups by kind
the one labeled "ACPI x64-based PC" corresponds to me ACPI_HAL device, the one labeled "Microsoft ACPI-Compliant System" corresponds to my PNP0C08 and you can confirm that yours matches that HID
yeah it does
my ACPI_HAL also matches the HID of the corresponding one on NT fwiw
but i also have an amd pc so its not a good test 
lol
hang on my laptop is intel ill check there
well the HIDs all match i know that
but idk if the node path is in the system board device on it
is your mobo asus?
my desktop is MSI mobo, my laptop is dell all the way
mhm
that devices by connection menu is like 99% of why i ended up taking inspo from NT's device model for this kernel lmao
because that view is so clear and also exactly how id intuitively want to structure things
i might give uefi runtime services a driver which would match that uefi-compliant system thing but idk
undecided
why not
true
no goddamn clue lmao
exact same setup on a random asrock mobo
are they stealing bs code from each other
lmao probably
yep
$ git grep PNP0C08 | sort -u | wc -l
163
like one third
or actually wait, this is a crappy query
infy@DESKTOP-IGT40G0:/mnt/d/uACPI/tests/acpi-dumps$ git grep -l PNP0C08 | sort -u | wc -l
163
infy@DESKTOP-IGT40G0:/mnt/d/uACPI/tests/acpi-dumps$ git grep -l DefinitionBlock | sort -u | wc -l
783
Yeah this is more like it
163/783
mhm
so its relatively common I guess, although usually just weird dead code
yeah
wrote an extremely tentative rwlock but dont have time or energy to make code actually use it lmao
its upgradable and reentrant too, which are nice for an rwlock
(it stores the state of being either a reader or a writer and has two queues. reader state stores the number of readers and writer state stores the writer's threadid and a depth. if the lock is taken for writing and the thread matches than any lock or upgrade increases depth. upgrade when the lock is shared succeeds if theres one reader and otherwise drops the read and enters the write queue. downgrade and unlock for writing decrease depth but downgrade sets share count to 1 if depth hits 0 whereas unlock sets share count to 0, and both then free everything in the read queue. if unlock would set depth or share count to 0 it tries to signal a writer before releasing the readers. lock for writing succeeds if share count is 0 and lock for reading succeeds if its in reading state at all)
the downside with that rwlock setup is that the sequence read() read() upgrade() will deadlock
but e.g. read() upgrade() read() is fine and uses the write reentrancy
might keep working on non-coding os projects today if anything
still sick
i kinda wanna make a logo for the project
somethin i can put on the website and also use a splash screen in the far future when i get the os doin graphical stuff
and officially got a logo now, based on editing some clipart lmao
https://khitiara.codeberg.page/imaginarium/ logo, admonitions, the devlog has an rss feed now, and home and about have content now
not really been as productive on the actual os last few days as id like because of being sick (but also simultaneously more productive on that than expected tbh) but at least i got some periphery stuff like the site going at this point
lmao, love it
and the blog is cool
I just realized the logo isnt meant to be a computer with a face
computer witg a map but I intentionally left it this way around so it could have face energy
updated my dep versions today and then spent all day trying to debug them instead of actually working on my kernel lmao
otoh the newest qemu published version no longer needs my whpx workaround
so im gonna swap that to be default not used
yknow what
i might work on vfs next
been trying to avoid it for a hot minute now
but maybe i should actualy work on it sometime lmao
i do already have sorta a plan for layout at least
which is that im using nt-style object paths internally, therell be a root file system using some complex fs (probably something custom tbh), and a boot partition using fat (not necessarily the ESP)
kernel will get told by the bootloader the partition uuid it booted from
and then it can load an fstab from the boot partition, and maybe some other stuff too
(could also do a tar initramfs since zigs got a tar reader that works in-memory but idk i lean a bit away from using that)
the boot partition and root partition will be put at some fixed object paths as volume objects
and also the boot partition will generally be mounted at /boot on the root partition, but that isnt actually a requirement
actually to be extra specific: all volumes have a uuid derived from the filesystem and/or the raw disk(s) the volume encompasses. they are then put at /?/volumes/{uuid}. the root and boot partitions get named symlinks to those volume objects. volume objects are able to override object resolution, where they get given a subpath and create a file object with the joined path as its name
normal filesystem syscalls will take file paths which are then converted into object paths by prepending the root filesystem name
file paths are a null terminated byte array with some reasonably large but fixed maximum length and the only restriction is that a path must not start with /?/ (using the basic unicode values for those characters)
though tbh i probably dont even need that restriction
oh yeah no dont need that one
so file paths are just 0-terminated sequences of non-0 bytes
as are object paths
with one extra feature: a non-absolute object path evaluated with no explicit parent is evaluated relative to the object /?. this allows creating global shortname aliases for things
its like the PATH env var but for objects and hardcoded
if this sounds familiar it probably should, this is by far the most nt-inspired part of the os
idk lmao
i ramble a lot
accurate
fun fact btw this exact mechanism is how drive letters on windows work, except their thing is called /GLOBAL?? instead of /?
(well ok its more involved than that but there is an object /GLOBAL??/C: (note the trailing colon) that is a symlink to the os partition)
hey i have a few questions about zig osdev 
ive always been a bit inrerested in the language
go ahead and ask em
how does the stdlib get used in freestanding?
i know in rust osdev you can get things ported there?
eg like btrees etc if you get an allocator etc
zig has two big things going for it on that front
- allocator is a type you can make one and pass it around
- the compiler is so lazy about compiling shit in that if you never call a function that uses the os it literally wont be compiled lmao
legit the only part of std i cant use rn is the IO part and theres literally an open pr to allow overriding the like 3 types id need to do to get even the working
would IO be printf etc?
file io
ahh
i mean the stdin/out/err counts for that too but the print function is a function on writer not a global so i just make my own writer implementation and use it there
this part of me reading the samples intrested me alot
huh neat
and i presume i can just import say flanterm and implement that right there etc?
yeah you can import c libraries, thats how i use uacpi
and the less c headers they need the better, zig doesnt import any libc
so it shouldnt be too bad to get to started?
theres also a build system step that translates c headers into a zig module with externs thats basically bindgen
how does using zig in userspace work for poirting to a kernel
yeah i didnt find it hard at all to start
DebugAllocator (they renamed it lately when they added a no-assertions fast one for release modes) has a backing allocator field that defaults to the os page allocator, but you can just override that
you could go with a libc for it, or you could write your own zig os layer too, the pr i mentioned that will let you use the std file io stuff but even without that you can just have people call your functions instead (thats what @hoary aurora is doing with ashet - sorry for the ping mate - but hes got userspace programs in zig for his zig os working)
yup
thats how the first version of imaginarium worked, i wrote a buddy allocator and then plugged it in the backend of the DebugAllocator and got free allocation for literally all object sizes with leak, double free, invalid free, etc protection
(well i started with a stack of free lists that could allocate like a buddy but not merge, and then i decided fuck that i dont want it to fragment and wrote a buddy allocator)
when i was having memory corruption on my current kernel i swapped the functions causing issues over to use a debugallocator and it caught the problem (even if it took me like two days to understand what it was telling me because i had made a wrong assumption)
oh also because zig has no libc dependency (unless you want to link libc), it has full dwarf cfi unwinding in the std, so if you override like three files you get stack traces with source locations and symbol names on freestanding
ooo, so with say mlibc working well i could get zig running?
or yeah an os layer
yeah
i honestly should consider doing a kernel in zig. i want to make a buddy allocator and getting a free heap is nice
if you link libc then i think most io stuff would call into that but not 100% sure, but yeah even without that you can just write your own layer because if you dont call the std stuff it doesnt get compiled
yoooo
honestly zig looks pretty damn cool
ye its great
im gonna try and fix up my kernel still. if SMP ends up messing me up or other things i may switch

how does zig handle with smp btw? and other things like macros etc
(when i say override, zig has a thing where if you @import("root") that points to the main root file of the compilation, so a bunch of places in std do checks of if root has this thing as a declaration use that otherwise use the default std version)
smp is fine, its got atomics and stuff and you can always write your own mutexes etc and will need to anyway for osdev, as for macros zig doesnt have macros, instead it has comptime
comptime is basically certain things (default values of globals are the big one but you can mark a block as comptime to force it other places) are interpreted by the compiler as if its an interpreted language with a branch limit (to prevent infinite looping)
and then the result is used for the actual compiling the rest of it
so instead of macros you get shit that looks like normal code
https://git.evalyngoemer.com/evalynOS/evalynOS/src/commit/4280b6ec744697b5bb4e716a25d3e6b08a6a123b/src/kernel/drivers/dbgstub/dbgstub.c#L195
i mean for stuff like this? without macros it got pretty messy and edned up cuasing issues lol
but runs at compile time
so you could comptime precompute say a lookup table?
yup
for this id probably use an inline function instead of a macro, comptime-known values get preserved through inline calls so the compiler can do constexpr optimizations on it
one of the big uses of comptime though is to replace the #if on target stuff in std, which is part of why some of the os-independence of it works
hmm neat
i could also use an inline function but i went with macros there since im not using it anywehre else
and snprintf was a horrible monstreisty
so in that case in your dbgstub if you made it an inline function in zig, the width would get inlined and then the branch on it would get chosen ahead of time
this was crashing shit btw 💀
oooooo
OH PRAISE THE LORD 😭
or https://ziglang.org/documentation/master/std/#std.fmt.hex if you got ints
tho that one is little endian
is there a bultin hex to int?
gdbstub wants you to send things as little endian hex which means i had to byteswap it before sending lmfao
and to do the reverse on recv
parseInt or parseUnsigned (if you want to ignore the sign) in that namespace. for the little endian recv you probably want to do hexToBytes in that namespace and then call std.mem.readInt (or you can actually @bitCast the returned array from hexToBytes into an integer if youre on an LE system)
i mean i can just convert it and then use a byteswap intrin on the int no?
that too
how does zig handle compiler inteinics btw?
we got builtins, anything that starts with an @ is a builtin
do they have less stuff where i need to make manual things with outb/inb?
so for byteswap youd use @byteswap
there arent any builtins for asm stuff apart from atomics, the only builtins are the stuff thats any-architecture
the inline asm is just normal c inline asm, but the asterisk is that the string it accepts is a comptime known string rather than a literal string
so you can use comptime to generate the asm string
here lemme go find the example i got
the first bit is a block at comptime that iterates the fields of the interrupt frame GPRs sub-struct and generates two strings from it, one pushes the register and one pops it
is this like macros?
but in the right orders automatically for whatever gpr fields i put in the type
kinda yeah
but written like normal code
debug printing lmao
i dont need em for 99% of things but when something goes wrong i want to see the values in my unhandled interrupt panic
yeah i could do that tbh
and may someday
i was basing what i had on what qemu's -d int output prints lmao
my talk is cheap and il send patches 
this is what my panic screen looks like
i get alot of stuff dumped with a normal stack frame lol
even nornal panic() calls get some stuff dumped
my panic handler (theres a @panic builtin but it goes through a set panic handler that also has functions for a bunch of different kinds of safe-mode assertions like out of bounds etc, theres a premade default with messages that all get sent to a regular panic handler that you provide that i use) actually does a stack unwind and prints the panic stack too
as does yours
oh nice nice
@panic seems nice lol
i need to do DWARF at some point
or atleast generate my symboles better 💀
my make debug compiles the entire thing twice
once forn symbols
the second to cimpile them in
theres also std.debug.panic which is like @panic but it takes a format string and args instead of a comptime string so you can format your panics
provide extra info like the faulting address for example using your case there
for debug symbols in zig i just had to set strip=false in the build system
and then limine (or now my bootloader since i swapped) gives me the kernel file as a blob, and i use std's dwarf parsing to load it from there
the part i had to override for debug was the part that tries to load the bin file from the file system which would compile error on freestanding, but because i dont touch that filesystem stuff now it works
does allocate a fuckton of memory though, the std debug info is not memory efficient lmao
had to up the max block size in my page allocator to make it happy on full debug -O0 builds
and it was borderline on my normal releasesafe
in any case if you ever got more zig osdev questions feel free to ask lol
ill do my best to answer
i may have more later
possibly more general for zig lmfao
but thats if i start such a rewrite
I do wonder
i can also try to help answer those
maybe? id copy @last pebble's cfi unwinding if youre already in mostly C land though
from #1385970208631427173

true
but i could infect more of it with zig etc
and like ease it in etc
for some stuff i may not be compfy to make in zig etc etc
oh also im glad i shared this because i found a bug
💀
that CR8
it shows a bitfield
it should never have a total value of 1
@kindred isle on your question regarding printf:
zig has a really good print and logginh that doesn't need io at all
so i can just add a putc backend etc ala npf?
yep
Huh neat
Yeah maybe I should replace some of my kernel with zig
I quite hate making stdlib shit

Wow that looks pretty simple lol
my debugcon provides a writer impl https://codeberg.org/Khitiara/imaginarium/src/branch/rewrite/src/krnl/hal/debugcon.zig based on my arch puts/putc
Nah that’s normal though I may rename it to TPR and show it as decimal with string replacements later maybe
and the log fn just uses that
It’s that it got set to 1
Or 2
iirc how it works anyway i think its that second nibble that matters
TPR on x86 is in chunks of 16
An TPR of 2 means nothing from 0x20 to 0x2F
3 is 0x20 to 0x3f masked
Etc etc
yep
aarch64 is sorta the same except you can have anywhere from 4 to 7 bits of it
and its backwards
so 00 is all masked and FF is all unmasked
the shift is the same though, the extra bits is just which lower ones are allowed to be nonzero
(and technically if youre in secure mode instead of nonsecure mode its 5-8 bits, with the nonsecure version mapped to one bit lower, so secure mode interrupts get higher priority with their own half of the range)
@haughty cipher i wonder how convinced @kindred isle is when she sees the packed struct.
👀
so you know bitfields in c?
zig has those as a first-class language feature with packed structs
and theyre a lot better defined than c bitfields
Yes. I use them. I say fuck it we ball I don’t care if the compiler fucks it up lmao
yeah with zig they have very well-defined semantics so that isnt a worry generally
Oh I deal with it by ignoring it 
lmao
I use clangs over loadable functions anyways
So you kind of have to use clang to even build my kernel
So it works out in the end 
thing is c has those its just not well defined enough for the compiler to not fuck it up
...whats an over loadable function?
I do think I can use bitints
Functions with the same name but different arguments and impl
heres my idt packed struct for a decent example of em
and then selector itself is a packed struct too
const What = packed struct (u23) {
lsb: bool,
mode: enum(u2) {yes, no, cancel, retry },
payload: i19,
msb: u1,
};
bitint-backed enums in em is my favorite thing tbh
you get to pick what the backing integer is for an enum
and it can be a bitint
That could make certain semantics fucking clean
and then you can use em in packed structs like that
i love em for u1s even, when theres two options but neither one really fits onto true or false
stuff like gdt vs idt in a segment selector, or edge vs level in ioapic stuff
my memory cache typing is an enum backed by u3
that's the reason we have it. wait until you hear about packed union
:O
oh lemme go find my good packed unions
pakced union
heres one
small in there
but its either a u36 or that other packed struct with the pat flag for large pages
im currently rebuilding zig itself in debug mode to try and track down something i noticed when i did that on a different platform the other day that alex (of the zig compiler team) couldnt reproduce because my build system didnt work on linux at the time lmao so i got plenty of time to find neat codebase things lmao
how to shill zig to any embedded person.
ok this one doesnt fit onto a full shot becuase of all the functions but at the top it says packed union
for the PCI BARs
in this case
what the
heres how i define cr3
which is probably the best example for making it clear how packed unions work
packed in zig means bitfields/bitints
theres a proposal to rename it to bitpacked that got accepted but hasnt been implemented yet afaik
fwiw iirc you dont have to touch pwt/pcd etc on CR3 on moden days as its per page and uses PATs
so i dont think id have that under CR3
so a packed union(u12) is a union but 12 bits long, and you can use it like any other bit thing
how does loading the u51 work here?
yeah i just did it there for correctness™ and also because it was two years ago and i wrote that
ahnhh
ahh fair fair
it just works™ like a bitfield
this is why id just CR3 |= PCID
but when putting the physical address in
you shift it over by 12 to get the page number first
one of my most common uses for packed unions is actually to have one union field be the raw int and the other be a packed struct so i can use masking instead for efficiency™ though tbh the compiler might handle that case for me anyway
so cr3.base = phys >> 12
oh heres another packed union that i use for the abstracted version of PTEs
exactly
makes sense
validpte here is white because the lsp is stupid and cant figure out the layers of platform-abstraction ive got there 
validpte being an alias for the arch-specific pte type
the only union fields for this packed union i actually use so far are valid and list though
i think the compiler will optimize cr3.base = phys >> 12 into a mask off and or but im not 100% certain lmao; also just out of frame below that shot of the cr3 packed struct are these functions lmaoo
i dont think i actually use them anymore tho
check the decompile
i will someday™
i dont have any uses of that sorta thing in the hot path atm
oh heres a fun packed union from my bootloader i forgot about
Will not be compiling 
clang has better codegen anyways
thats llvm not clang but yeah
on x86*
sometimes*
clang is just the frontend
well compared to GCC you know what i mean
rust llvm is pretty crappy tbh
how is rust GCC 
zigs got ok llvm output but also zig does have a completely self-hosted x86 backend that does the codegen itself
oooooooo
The problem with llvm and rust is fucking stack usage
500 megabyte stacks
Rust overuses the stack
its just that the zig self-hosted x86 backend doesnt fully handle linker scripts yet and dies horribly if you try to make it use soft floats so its not suitable for osdev yet (it is in early beta)
sounds like a rust problem not an llvm problem to me
zig seems to be a very promissing language for osdev
but im also a known confirmed rust-hater
better than rust 
you should make a guide on a howto for zig osdev when things are more stable
not a high bar lmao
like a mini wiki / yrabslation guide for C kernels
as long as you use llvm backend its very stable rn, and theres even a limine template for zig iirc but idk how outdated it is
You joke about it but afaik some kernel here had to blow the stack into the megabytes to get rust working because like 128Kb wasn't enough
Like what the fuck
if i make zig sound unstable its because im tracking zig master instead of release tags
so things break
oh not like that
not that its unstable
that there is upcoming cool features
oh stable as in not getting breaking changes
gotcha
yeah zig is still fairly young as a language and getting a decent amount of breaking changes still as things get refined
Zig in like 5-10 years will be a decent language
For now they're in the feature craze phase
like if you pull a tagged zig version rn the packed struct(u36) is a compile error and if you get zig master rn the packed struct { is a compiler error in some cases
yeah zig shows a lotta promise for osdev
im just in this for the learning and dont mind chasing breaking changes to try it out
theyre going to remove an entire builtin from the language after the next proper version gets tagged apparently lmao
(the @cImport builtin is getting nuked in favor of using a build step to do that translation so you get more control over it)
the syntax for cimport was stupid anyway lmao
anyway today might be object manager day if i get enough energy to actually work on shit
esp with the C inteop
ok heres a question for how to do the object manager
should the object header be a field of the object
or should it be prepended in the allocation
former is way easier, latter lets me drop parts of the object header that arent needed
to save memory
im on 64 bit though
so do i need to save that much memory?
esp since the objects therell generally be the most of are the ones that need the extra header bits
(latter is what windows does)
(please someone give feedback im stumped here)
i think the intrusive object header approach is easier to implement as well
does the other one have any other advantages?
you can just not allocate the extra memory for e.g. the name if an object wont have one
or the memory for the pointer that makes up a handle table, if it isnt accessible in user mode
gotcha, i don't think it's that important to save those couple bytes per object
unless you really care about memory efficiency down to that level
yeah thats how ive been leaning too, just wasnt ever sure
tbh i think windows only does that because it has been since NT 3.51
from 1995
if you ever run out of things to do you can always revisit that area of the kernel and optimize it :p
true
ok intrusive object header it is
(oh yeah the other benefit to not using intrusive header is its slightly less convenient for other code to access things about the header it shouldnt. which sounds like a why dont you trust your devs issue to me)
true tbh
anyway instead of going too far with that now im currently doing something absolutely insane just to proactively turn a function pointer call into a switch and regular calls lmao
ok time to find out if my bullshit compiles
it compiles im scared
its probably ignoring all the bullshit that im not using yet
Also I should ask. How is the LSP support for zig in stuff like KATE?
havent tried it but https://github.com/zigtools/zls is pretty good as an lsp
i think its standard lsp protocol, thats how im using it just not with kate
Kate works with clangd so it should be fineee™
if theyd just add @unrollArgumentTuple like ive been wanting then i could get this nonsense to be even more cursed but also kinda cleaner lmao
what would that do?
it takes a comptime reference to a function whose last argument is a tuple. and returns a function body object that takes the elements of the tuple and wraps them up to call the function
so if i had fn foo(a: A, rest: .{ b: B, c: C, d: D }) R
then @unrollArgumentTuple(foo) would be
fn bar(a: A, b: B, c: C, d: D) R {
return foo(a, .{ b, c, d });
}
but without having to type all that out
the main use is as an inverse to the existing @call builtin
which takes a tuple of arguments and calls the function
so you can make a generic wrapper with a generic argument tuple type that calls your inner thing with some processing, and then convert it into a wrapper with a normal function type
zig hashmaps winning again
just make a context that uses the object names to hash them and make the object directory a hashset
and then i can make a key adapter context and use the xxxAdapted versions of all the functions and pass a fuckin string in
ah yes. another proposal of mine 😛
and it JUST WORKS
the absolute bullshit worked. my normal code around it, not so much lmao
Lmfao
index out of bounds errors all over in the entirely normal boring code lmao
alright its working now
which is like, invisible mostly
but hey
something
infrastructure moment
ill be honest, https://codeberg.org/Khitiara/imaginarium/src/branch/rewrite/src/krnl/ob/Directory.zig is probably the best propoganda for zig i can come up with rn
and its all because of how goated the hash_map impl is in the zig std
https://codeberg.org/Khitiara/imaginarium/src/branch/rewrite/src/krnl/ob.zig#L34-L80 and for something far more cursed which would benefit greatly from unrollArgumentTuple
ive been informed that theres a number of cases in the zig compiler of AutoArrayHashMap(void, void)
which is cursed af but actually pretty useful somehow
in that case you use a key adapter context and hold onto the index in the arrayhashmap that you get
without ever actually storing anything in the map
randomly decided to make setting BARs work
so thats done now
kinda boring code tbh
and doesnt do anything yet because i dont do proper resource reallocation lmao
so rn the resource "allocator" just sets everything to the initial value given and trusts the firmware
sad but unsurprised to find out that qemu apci doesnt use DDN
tho actually hang on
i mightve made an error here and forgot to do this code somewhere
ive gotta refactor this shit
nope still nothin
oh nvm on aarch64 this is now triggering a panic
huh
this is weird
oh lmao
ok thats dumb but funny
its a use-after free when a driver errors during init of a device, should be fixable but for now i just fixed the actual error that was happening instead
anyway now i get _DDN and _STR copied into device properties which is nice
even if across both of my qemu setups theres exactly one thing that has either (the pci root complex on aarch64 qemu virt-acpi has _STR set)
idk if ive shared this yet but the device categorization stuff i mentioned (also names but theres currently no drivers setting names so only the root dev has one. considered using acpi name but the pci stuff has duplicates there)
you could use the ACPI name and append a number
yeah that could work, might even do that lol
and if it ends with a number add a dash
and always add a zero even if no duplicated
might just always add the dash 
went one further and instead of deduplicating properly i just use a global monotonic value for it
and also probably didnt need to but decided to not bother with items that dont have a proper hid/cid anyway
ACPI also has _UID for things that may appear multiple times
ie will \_SB_.PCI0.S18_.S00_ have a UID if \_SB_.PCI0.S00_ also exists?
No its for multiple devices of the same type, not same nameseg
Right
how do you print pretty trees like this btw
this dash is already bothering me with the _s so im changing it to .
nah its manual
i mean zig does have a function for this but its for the specific case of the progress reporting api the build system uses
i copied the ideas
its actually fairly shrimple
well it would be if i didnt decide to manually unrecurse it
the idea is to build a prefix in a buffer so you dont need to keep track of all the parents' sibling statuses
anyway did a bunch of fiddling and also pushed up an update to the docs site
now i gotta go take my inhaler so i can breathe again and then gonna hang out with my brother since hes over today
Btw have you ever heard of 16 byte atomics?
yup
I've got a thing that even uses them though I'm not actually using that thing for anything atm
I’ve always wanted to do some lockless algorithms with them but never got around with them
IIRC you can do a buddy allocator with them
I've got a lockless singly linked list (prepends and pops only so basically a stack) that uses 128 bit cmpxchg
fun fact that exact lockless singly linked list is why windows 8 and newer hard requires 128 bit atomics to function
Oh dang lol
My plan was to use 16 byte atomic
And as a fallback use the extra space for a normal lock
mhm
the thing with the list is it doesn't actually need 16 byte nodes, just the list itself needs to be 16 byte (nodes do need to be 16 byte aligned though)
id share a link to my code but on mobile rn and can't be assed
it's called a sequencedlist or slist though if you wanna look it up
and if you figure out a lockless buddy allocator using 16 byte atomics I'd love to see that
It shouldn’t be too bad?
Esp with 16b CAs
I think somgody here has already implemented such
CC: @round robin
You could also get away with tagged pointers given it’s all 4kb aligned? Though I’m not sure how ABA resistant that is on the buddy allocator usage
mhm
I wouldn't know how to start actually figuring this out lmao
I look at atomic ordering and my brain short circuits
Just make it all strong

lmao
To be fair on x86 I don’t think it actualy hurts that much?
yeah there's very little difference on x86
I'm also targeting aarch64 though and there there is a decent difference
I'm doing both lmao
Oh lmfao
multiple arches forces me to keep the code cleaner and more organized
ABA shouldnt apply to a buddy as the memory location itself represents physical memory and not bound on pointer equality
afaik you can have a double linked list with just 64b atomics, but the algorithm is quite new
i designed one, versions for both 8B and 16B cas
got links (and licenses) for them? im def interested in seeing how that works
I remember talking about ABA stuff when we talked a bit ago
yea, ABA would be problematic if you do pointer comparisons to dynamically allocated data aka normal ll usage
Ahhh
my buddy isnt truly a PMM atm, though i plan to rework that soonish since ill need physically contiguous stuff for the GIC ITS on aarch64
like comparing heap pointers where equality doesnt mean its really the same object
yep
got any code and/or design info on these i could read?
currently not really
rip
i try to write it down in the next few days
👍 no rush or worries, was more curious than anything
im currently only startup on aps on one of the arches i support and dont really have the scheduling infrastructure yet to make full use of aps anyway so making my alloc lockless isnt a priority
now as often the case im running into the issue of idk what to work on next on this os
anyone got any suggestions?
(so far i got acpi tables, an acpi device enumeration driver, timer interrupts, DPCs, a basic-ass round robin scheduler with no preempting yet, a pci bus/bridge driver, an object manager system, and ap startup on x86_64 but not aarch64)
isnt ap startup on arm just unparking the cores?
https://www.eecs.yorku.ca/~eruppert/Mikhail.pdf
Lock Free Linked List
varies, acpi tells you what the method you should use is (as does devicetree)
thanks!
ah
theres the super-old no longer supported acpi unpark, a basical mailbox unpark ala how limine does it, and the PSCI SMC/HVC method thats the most common
that last one you get told whether to use hypercall or secure-monitor call and theres a predefined hyper/sm-call function that starts a given ap in a defined state at a specific address, with a given value in x0
no init/startup ipi shitty design 

