#uACPI - a portable and easy-to-integrate ACPI implementation
1 messages · Page 63 of 1
NTs handling is probably saner here but otoh maybe this should have been a first class concept instead of being an artifact of how parsing works 
yeah its insane how willy nilly it is
The problem is that they always just added the bare minimum AML opcodes to make their next bios gens work without designing a proper bytecode
They also didnt bother with a first class timeout system for hardware state
so they rely on interpreters timing out the running aml
most aml just retries stuff infinitely
yeah
Hell they didnt even specify the expected output of ToHexString
which some firmware relied on the nt format for parsing
Its the most insane unfinished spec in existance probably
Considering how much of the pc world relies on it
and the implementations do not actually follow the spec for type conversions
acpica tried
Tbh Microsoft should do what Intel did with their memory model and just define the NT behavior as the standard behavior

its hilariously broken honestly
a lot of firmware relies on the memcpy behavior for implicit casts these days
well relies is a big word
it does work in acpica so i guess not realy
they found the middle ground
they do stuff like Name (_HID, "XXXX")
_HID = DEADBEEF
Tbh an opcode statistics could be fun
yeah that would be interesting
I wonder if there are opcodes that were never actually used
UnloadOp has only been used by a few surface laptops
and then removed in the subsequent spec
And in general their idea of DDB handles has been a complete failure
But in general i think literally every opcode is used
some way less than others
e.g. Signal() is almost unused
yeah, most opcodes are probably used
Makes sense tbh
i know cuz i've grepped for them when implementing
Lmao
there are a lot of opregions types that are never used literally
Like PCIBarTarget
or most i2c ones
Tbf most arm boards just offload alot of it to native drivers and the aml is mostly static
yep
i was surprised about the BAR one
it seems like it could be useful
but linux doesnt even implement it
probably because they figured everything out via pci config space which is at a fixed location
yeah
the rest they can just do via smm
which is still funny like u have aml but u still call into smm
The funnier thing is that there is no standard way to call the monitor
Like, on x86 you have an IO port, is there a way on arm/riscv to call into el3?
Without an opcode that is
interrupts
Well, I guess MSI can do it at the very least
well the SMM io port is basically universal
its like B5 or something
B2
both arm and rv can delegate irqs to all privilege levels (except for user mode)
yeah
And B3 for data
Yeah then that handles it assuming you can raise it via an mmio access
RISC-V actually has an extension draft for that last one
Not that I think it's a particularly great idea
No i think that was part of rv pre 1.0 and it got removed
It was never ratified IIRC
well, it was part of the 0.8 spec or whatever and then removed for 1.0
all firmware devs should add a prologue that has a 3000 statement deep opcode to filter out all hobby interpreters
with optional chained table loads to crash linux with a stack overflow as well
Make aml so cursed that you create a windows only computer
thats not particularly hard, i have quite a few tests that crash acpica but work on nt 
they should ngl
who is getting a job at a firmware manufacturer to add a CTS to the firmware?
CTS?
conformance test suite ig
I love reading about how cursed aml is, like watching a far-away shitshow for entertainment

Until you buy hardware with said cursed aml
dont give them ideas
they'd just put one of their many "quirks" hacks there
wasn't this the intent, it seems, of ACPI lol
atp just make AML that enforces a uacpi monopoly
the managarm PC
yeah just make some aml that makes all non-uacpi interpreters crash
qwinci's interpreter is pretty robust as well soo 
You must merge a subtle bug then
is uacpi not a hobby interpreter? how do you define hobby?

it's a vague word ofc
uacpi is hobby in the sense that i dont get paid for it
but i consider it production grade
ah speaking of robust
when I was enabling clang-tidy lints for managarm I got a few for uACPI as well
I should probably update managarm's uACPI + fix them upstream ig
iirc most of them were narrowing conversion warnings
based
one thing that I also wanted to do for managarm is to make it not use uACPI as a meson subproject, but to install it somewhere so that it's discoverable with pkgconfig
but that required more than 10 sec of work so I haven't done it yet
lol yeah
I think the solution to that in the case of Managarm is to split the kernel package into managarm-kernel-legacy-boot
then we can compile uacpi once for 32 bit and once for 64 bit
and add all required compilation flags to the cross file
the problem for separating out uACPI is that the compilation flags would need to be known ahead of time, or alternatively exclude it from sanitizers of something
it's a bit unfortunate
the alternative would be to install sources to /usr/share or something ig?
Hmm but then we can also just keep it as a subproject, can't we?
If we have to compile it alongside the kernel anyway
Or do we gain anything by having a package?
yeah but subprojects are really annoying to deal with if we were to compile it on managarm itself
you either need to replicate bootstrap's steps (and versions) to set it up
or you need to keep wrap files in sync with bootstrap
neither of which we currently do
I don't even think we have a uacpi wrap file tbh
That sounds easy to do with a script in bootstrap-managarm though
wdym by script in bootstrap
Maybe something like a CI stage that complains if wrap file and bootstrap.d version are out of sync
how often are you going to be updating uacpi in managarm though
I go with "if it ain't broke..."
if you're not updating it often and updates require manual review what's wrong with dropping the source into a folder in the tree?
although tbh all that stops me updating is laziness
vendoring is a horrible idea
if anything we git clone + checkout a specific revision
that is not the debate tho, as the only uACPI code in managarm are the bindings, uACPI is pulled from upstream
the question is about build system integration ig
I kinda dislike our current approach of meson subproject for pulling the source variable out of uACPI's meson.build
it's ugly and fragile
@fiery turtle
I think that is an access to unused local
it probably initializes it in some if that you don't trigger
I remember seeing it with other people
Do you have EC support?
nope
Yeah, the AML is stupid and does a check if the EC was initialized but doesnt handle the path it wasn't properly

common firmware developer L
hardware designers and firmware developers teaming up to mess with the software developers
real
could the lack of ec support be the reason why power button doesn't work :P
No idea tbh, is there maybe a power button device in aml?
(even if there is it doesn't necessarily means that it requires EC, just that you need to listen on a notification on it)
Yeah tomato is right
Yup
Check fadt to know
The power button can be routed in 4 ways
Is this a laptop and which CPU
Nvm I guess since it says BAT0 it is a laptop
Your power button is most likely EC, or worst case AMD GPIO device
But both still work as an aml notification
it's a laptop and I believe the cpu is ryzen 3 4350u
Yeah inspect your aml to know
Wdym check fadt?
theres a power button control method bit
Ohhhh
I'm guessing this
yea
is there any kind of documentation for https://github.com/uACPI/uacpi-rs ?
cargo doc
I've discovered NT-incompatible behavior in uACPI today thanks to marvin
I've already fixed it locally and will upstream the fix shortly but FYI i guess
The bug:
Method (ECRD, 1)
{
Local1 = DerefOf (Arg0)
Return (Local1)
}
OperationRegion (VARM, SystemMemory, 0xE9, 0x01)
Field (VARM, AnyAcc, NoLock, Preserve) {
FIL0, 8,
}
FIL0 = 0x65
Debug = ECRD(RefOf(FIL0))
The DerefOf here is expected to read the field automatically, whereas in uACPI it would just yield a field object
and there is literally thinkpad firmware abusing this trick so it must be fixed
[uACPI][DEBUG] BEGIN OP 'DerefOfOp' (0x0083)
[uACPI][DEBUG] pOP: TERM_ARG_UNWRAP_INTERNAL (0x07)
[uACPI][DEBUG] BEGIN OP 'Arg0Op' (0x0068)
[uACPI][DEBUG] pOP: EMPTY_OBJECT_ALLOC (0x17)
[uACPI][DEBUG] pOP: INVOKE_HANDLER (0x15)
[uACPI][DEBUG] pOP: OBJECT_TRANSFER_TO_PREV (0x27)
[uACPI][DEBUG] pOP: <END-OF-OP> (0x00)
[uACPI][DEBUG] END OP 'Arg0Op' (0x0068)
[uACPI][DEBUG] RESUME OP 'DerefOfOp' (0x0083)
[uACPI][DEBUG] pOP: TYPECHECK_ONE_OF (0x25)
[uACPI][DEBUG] pOP: OBJECT_ALLOC (0x16)
[uACPI][DEBUG] pOP: INVOKE_HANDLER (0x15)
[uACPI][DEBUG] pOP: OBJECT_ALLOC_TYPED (0x1A)
[uACPI][DEBUG] pOP: INVOKE_HANDLER (0x15)
[uACPI][TRACE] read from [\VARM] (1 bytes) SystemMemory[0x00000000000000E9] = 0x65
[uACPI][DEBUG] pOP: OBJECT_TRANSFER_TO_PREV (0x27)
[uACPI][DEBUG] pOP: <END-OF-OP> (0x00)
[uACPI][DEBUG] END OP 'InternalOpReadFieldAsInteger' (0x00F5)
Anyway now DerefOf automatically turns into a field read if the object referenced is a field
What's funny is ACPICA is technically compatible here, but it still manages to corrupt itself on real hardware so that code breaks anyway
@mortal yoke funny stuff
So Linux doesn't manage to run the aml properly?
yeah the object state gets corrupted
althought i wasnt able to repro the bug locally in ACPICA
which part 
all of it
yeah i was surprised there is firmware abusing reference semantics
they usually tread lightly there
and well as u can see didnt work out here
Yeah
interesting, Ill have to test this too
it prints 0x65
qacpi is one step ahead 
and is behind in some aspects, I should work on it again at some point 
Iirc the interpreter was basically done?
I mean basically yeah, I think it lacks table data stuff + ToString + Mid + global lock stuff
@fiery turtle

bro how do they even come up with that shit
Lmao
otoh it's insane otoh i'm surprised sel4 didn't pass DMI info before since quriks are quite common :kekw:
Yeah true
Hardware people are cooked
Always have been
Software people are just as cooked
All people are cooked
opened a PR to support the thinkpad field reference abuse
also added a test for it ofc
probably gonna make a release today
@mortal yoke give the test case a try, although I expect it should work for you no problem
and ofc acpica doesnt pass it as usual
ACPI Debug: "Invalid value read: 0000006F6C6C6548, expected Hello"
ACPI Error: Cannot assign type [Reference] to [String] (must be type Int/Str/Buf) (20230628/exstoren-131)
ACPI Debug: "Invalid value read: XXXXX, expected World
because it treats stores to Name as a CopyObject for whatever reason
interestingly enough it doesn't seem to work
both parts
aml debug: Invalid value read: 48 65, expected Hello
aml debug: Invalid value read: 57 6F, expected World
Interesting that it outputs 2 bytes even though the field is 40 bits long
@fiery turtle please also make a new release
yeah

apparently the reason was that I did an unconditional conversion of field -> string as the bytes of the field converted to two hex chars + a space instead of using the int/buffer conversion that just does a memcpy if its ascii
easy to fix though, literally just one bounded recursion of the same function (or it could be a loop but this works fine) ```c
if (auto status = read_field(field, res); status != Status::Success) {
return status;
}
return try_convert(res, res, {ObjectType::String});
yes
nice
we love thinkpads
it was also another thinkpad that used dynamic expressions inside a package initializer
it seems they use most aml features
I have two thinkpads, if you ever need to test anything
Release 3.2.0 is live!
if you could test managarm thatd be cool
I can, it boots off usb without changing any fixed storage yes?
Yeah
I have one older ThinkPad, about 8 years old and one that's about 3 years old
the newer one is more fussy and has weird AF UEFI firmware
Managarm triple faults on my 2010 laptop so it might be interesting
That has a very early UEFI impl that barely works
My code runs well on old UEFIs. But it barely does much on the kernel side yet. However, antload does quite a lot on the firmware side. But, I added an exit on NX absence, so one needs to enable it in the UEFI as I did for my i3 2330M laptop.
I should also try managarm on an old samsung laptop that I have, I think its from around 2010 too (its one of the red ones, though I dismantled the case and mounted the mobo between two wood panels + screen on top, the original screen actually got destroyed because I walked over it accidentally when it was off the laptop so I switched it from an another similar laptop)
managarm worked-ish on my samsung laptop
it's from like 2012/13, with an i5-3210m
iirc i got it to boot into kmscon off of an usb stick, but i couldn't get the ps/2 keyboard working
and i recall also having issues with an usb kbd
but i haven't tried it in a bit so i ought to try it again, the xhci driver got some fixes that might affect it
Thought this might be the first infy test my aml parser could pass... but no. Seems I don't support refs of refs. Not really surprised.
whats your parser btw
it's the zaos one. The one in a custom lang that everyone confuses for zig.
also, looks like I sort of support refs-to-refs, but if you refof something 3-times you need to derefof it 3 times too.
ah
you implemented pointers instead of references :^)
Maybe one day the spec will clear things up (no, I'm not holding my breath)
well even if it does it wont have any choice but to just spell out what NT does
because nt sure is aint breaking backward compat
That's not true. New spec could target new api. Time to ditch this mess is my opinion.
You mean redo aml?
Not much motivation for them there, what currently exists seems to work
I'd like to see a new spec that just deprecated a whole heap of aml behaviour. Reduce what is allowed down to a well defined set.
if it does crash do you have any way for me to get diagnostics to you?
and do you have a prebuilt usb image or something
yeah managarm ships nightlies
but other than logs i dont think theres any way to get diagnostics
doesn't managarm use uacpi? does it have the same fix otherwise that you applied for my messy ACPI tables on my old desktop? could try it there, that might break it
we have uACPI but we don't follow master
we bump the pinned version/commit every now and then
uacpi_status uacpi_kernel_install_interrupt_handler(uacpi_u32 irq, uacpi_interrupt_handler handler, uacpi_handle ctx, uacpi_handle *out_irq_handle)
^ why is the irq number 32 bits here?
what platforms you support have 32 bit wide isr numbers
(thats my kernel shim to the uacpi interrupt install function)
and is this an actual irq or an isr?
GSIs are 32 bit numbers I think?
no?
This is an ISA irq number
the ioapic cant support isr numbers > 254
with 255 being reserved for lapic spurious isnt it?
GSI is not the same as idt index
in my case isr = irq + 32, and 64 upwards reserved for msi(x)
but youre not asking for a gsi num there
youre asking for an irq number
that's GSI
im confused...
Fwiw the SCI IRQ field in FADT is 16 bits
my OS only supports x86_64 and only ever will, any weird portability isnt in my wheelhouse
irq controllers often have thousands of interrupts you can route to them
ioapic spec says 256
then assert(irq < whatever);
pretty sure
where problem
yes, what im asking is, can i actually expect uacpi to go "give me irq 6048105"?
not on x86
On x86 SCI GSI is always hardcoded to 9
because i cant cope with that logically
So you won't get any number but 9
ok, interesting, i can deal with that
thank god
Lol
so long as im not going to get any number > 255 as my internals use uint8_t for isr ids
Probably not a good idea to have such tight coupling with external irq numbers and literal isr index
ive had to make a quite fugly wrapper actually to make that function work, it never worked before (i dont use it)... but my interrupt system takes a fair few more parameters than just an integer context
typedef struct uacpi_irq {
uint8_t isr;
uacpi_interrupt_handler handler;
uacpi_handle ctx;
} uacpi_irq;
void uacpi_irq_handler(uint8_t isr, uint64_t error, uint64_t irq, void *opaque) {
uacpi_irq* irq_info = opaque;
irq_info->handler(irq_info->ctx);
}
uacpi_status uacpi_kernel_install_interrupt_handler(uacpi_u32 irq, uacpi_interrupt_handler handler, uacpi_handle ctx, uacpi_handle *out_irq_handle) {
uacpi_irq* irq_info = buddy_malloc(&acpi_pool, sizeof(uacpi_irq));
if (!irq_info) {
return UACPI_STATUS_INTERNAL_ERROR;
}
irq_info->isr = irq + IRQ_START;
irq_info->handler = handler;
irq_info->ctx = ctx;
bool success = register_interrupt_handler(irq_info->isr, uacpi_irq_handler, (pci_dev_t){0}, irq_info);
if (!success) {
buddy_free(&acpi_pool, irq_info);
return UACPI_STATUS_INTERNAL_ERROR;
}
*out_irq_handle = (uacpi_handle)(uintptr_t)irq_info;
dprintf("[uACPI] Installed interrupt handler on ISR %d\n", irq + IRQ_START);
return UACPI_STATUS_OK;
}
basically had to do this
Because you may have thousands of irq sources which you route to different CPUs
The CPU id is up to you
route wherever you want
yeah, by default all my interrupts are on the bsp unless i say otherwise, but i cant do that by the basic register_interrupt_handler function, i have a more advanced one that attempts msi for that
Sure
im guessing uacpi internally stashes complex structs and other non-POD data in the uacpi_handle?
the ctx it passes in to register interrupt handler i mean
If you mean the context pointer yes
makes sense, exactly what everyone else is doing
i assume by default just when initialising it isnt going to call uacpi_kernel_install_interrupt_handler, its used if you e.g. install a handler for the power button or something?
i dont think anything i do will call it right now, wanted to implement it at last for completeness
No its called unconditionally because enabling ACPI mode causes firmware to assume you can handle general purpose events which have nothing to do with handlers you have installed
Basically firmware can ask you to run any aml methods at any point in time
Via an interrupt
hmmmm wait no it always tries to grab irq 9.
this means im going to have to keep uacpi alive during the execution of the entire OS now.... no biggie
You probably should yes
hrm...... i have a catch 22 here. i cant implement this function.
i didnt realise it tries to snipe that irq immediately
and because of what i use uacpi for, i dont have an IDT up when i call it
uacpi is intialised in really early boot, and i use data i get from it to set up the correct trigger mode and polarity and gsi info etc for all my interrupts before i install the idt and unmask interrupts
can i tell it to not snipe that irq right away?
you're probably looking for setup_early_table_access
are there docs on that function?
hmmmmm, i dont think that gives me enough
Im really curious what you do if thats not enough lol
i walk the entire pci device list, fetching a bunch of info
it says in the docs the only thing it will call is map and unmap
Yeah that should be done way down the line
that being the case, how can it do anything pci
it cant, obviously
setup_early_table_access isnt made for this
Initializing PCI before basic interrupt bring up is impossible
Well in aml model it is impossible
doesnt seem so
its been working fine for me on emulator and real hardware
perhaps what im doing isnt as in depth as what you think im doing
Because to enumerate you must consult aml and to consult aml you must handle SCIs which you can only handle after initializing interrupts
You should really parse madt, set up basic isa routing based on that, then set up everything else, then do proper ACPI init and only the PCI init
it would be impractical for feeding back all requests asynchronously right?
i dont do full acpi
During the initial namespace load on a lot of hardware
that isnt my use case for uacpi
You cant not do full ACPI
Thats just not a thing
You either dont touch aml or you do full ACPI
from what ive seen, youre expected to do some weird thing with building an entire device tree via acpi, and all your devices are addressed by it? i dont do all that.
Hmm me? I dont support anything like that
basically like windows has those strange paths to devices in device manager... im struggling to explain what i mean here, its 1:30am
dude both of you should sleep
basically, all i use uacpi for is to determine the correct gsi, pin, etc, and the proper ports for timers
then i rug pull it
i never implemented the thing that lets you claim irq 9, and nothing broke
Yeah but that doesn't mean you can just violate the ACPI framework model while you do that
I mean sure its not like your computer will instantly combust if you dont
i think in this case, its being installed, but what im using doesnt need it
Im trying to tell you its not for you, its for your firmware
It being useful for you is secondary
silly question from someone who doesnt know the guts of acpi: why cant your firmware register an irq?
without the aml in the way
wdym?
it has direct access to the ioapic, the cpu, and the bus
why cant it just intercept it, why didnt they approach it like that?
By default it does do that, but when you enable ACPI mode it tries not to do that
And relies on aml
You should really just pass NO_ACPI_MODE
And then ignore the irq thing
to what?
Uacpi_initialize
Your grep is broken 
hmmmmm
that still unmasks irq 9
entering acpi mode seems to have no bearing on wether or not it grabs that irq
so i cant implement this completely 🙁
uacpi is too specific about boot order in a way that isnt how i want to work
Yes, the intended use for this flag is to defer ACPI mode, not ignore its existence lmao
but you cant claim that irq yet, it shoudnt claim it till i call enter_acpi_mode()
Well in my opinion the order you do things in is just objectively incorrect
it doesnt need it till then
Maybe
Just not a feature anyone needed
im still running a forkish version that hotpatched that broken acpi table in my desktop
i should update at some point
i have a better solution
but it can wait till the AM
if you say the isr it requests is always 9, i can defer it, the function will always return ok, but it wont immediately install the handler
it will flag it to be installed later once the IDT is up and sti is executed on the bsp
You can defer it quite easily even if the irq number is dynamic
Also uacpi has callbacks that are called when the init level changes, maybe that could be useful for you
I wish there was better docs that aren't "read the header", because docs that are rtfs rely on me knowing what im looking for
same for doxygen really, got to know a function exists and what it does, to go looking
be the change you want to see!
I agree, but its certainly better than no docs at all.
and with LSPs in modern editors its quite nice when you get fuzzy find a symbol and the documentation comes up next to it.
even on x86, GSIs are not restricted to 255
there can be multiple I/O apics
some(/most?) servers have more than 255 GSIs
Marvin's dual socket server for example has more IRQs than a single CPU can accept
but each ioapic is 0-255 yes?
so its a pair - ioapic id, gsi?
to be honest, pretty sure i dont own any hardware with multiple ioapics, and i have proper server hardware... not that i'd ever run my OS on it. thats not its target hardware type
i wonder if i can check something.... one sec
i have multiple
the firmware exposes the IOAPICs are both a device that can be enumerated and on the MADT iirc
windows even has a "Intel IOAPIC Device"
device inf
iirc AMD (?) commonly has multiple I/O apics on their mbs?
at least i have a consumer level machine with multiple I/O apics (but more than 255 GSIs though, for that you need to go to larger machines)
GSI is a global interrupt number, that's literally what the name says. If you don't know what it is, you should probably read it up in the ACPI spec
hmm, seems my server has 3. but there is no way i'd reboot it to run my os on it. it likely wouldnt even boot
root@neuron:/home/brain/retrorocket/cmake-build-debug# grep -i ioapic /proc/iomem
fec00000-fec003ff : IOAPIC 0
fec10000-fec103ff : IOAPIC 1
fec40000-fec403ff : IOAPIC 2
3 is a weird number, not very "round", not power of two
if anything had more than 255 gsi's this would be it
hmmmm
according to the docs/header of uacpi:
/*
* Install an interrupt handler at 'irq', 'ctx' is passed to the provided
* handler for every invocation.
*
* 'out_irq_handle' is set to a kernel-implemented value that can be used to
* refer to this handler from other API.
*/
uacpi_status uacpi_kernel_install_interrupt_handler(
uacpi_u32 irq, uacpi_interrupt_handler, uacpi_handle ctx,
uacpi_handle *out_irq_handle
);
if this really is a gsi, not an irq number, the docs are wrong
what even is an IRQ number
because the parameter is called irq, and the header refers to it as irq
exactly, be specific
it's obviously not an IDT vector since (1) IDT vectors are an x86 concept with no equivalent elsewhere and (2) there's no way for uACPI to know how you mapped GSIs to IDT vectors
because. if its always gsi.... right now ive been told its essentially hardcoded to gsi 9 on x86, that makes things easy, but if it cant rely on that, i need to know that and so do other devs because looking up a gsi is very different to looking up an isr
not obviously
when i read docs, i take them at face value
thats the point of docs
thats like saying "obviously, you must read between the lines and know what the author meant"
and what im saying is, perhaps someone (me?) should raise a simple pr correcting the parameter name and comment
reading uACPI comments is not enough to understand ACPI
you also need to read the ACPI spec
question; does uacpi acknowledge its own isr's with an EOI?
because my global handlers for irqs do that as a matter of routine, if it does, right now it would acknowledge twice
rather not
this is why i choose to use third party libraries, so they can know the spec
knowing acpi is something i want to avoid, with all certainty
no, for the same reason: uacpi cannot know if (and what kind) of eoi is needed
That's not how it works. uACPI implements the AML execution but there is plenty of functionality that needs to sit inside the OS itself
i think you and i have different ideas of fundamentals here. for example i develop and maintain a discord library. we dont expect users of the discord lib to know discord api. just the the library.
so really, i need to know uacpi, not the acpi spec.
this is my opinionated opinion on what a lib is for, a black box so we dont need to know it ourselves
yes, and that is not how it works for ACPI
or rather, there is no library with the scope that you're looking for
but i dont use all the other features of uacpi... if i dont use them, i shouldnt need to know them.
(i.e., so broad that you don't need to read the acpi spec)
if uacpi says to me "give me a hook so i can claim gsr 9"... thats fine, but i shouldnt need to know why it needs it and what for
if you compare uACPI and a web stack for an analogy, uACPI is more like an I/O framework that knows how to do tcp sockets
but not HTTP
in the case of the discord lib, its in C++ and does everything from the ground up with raw sockets, so your analogy is half way there in my terms
i get what you mean
but in this case i dont need "http" (the equivalent of)
i only use uacpi to enumerate what gsi's belong on which irqs etc, and to get the ports for timers
in fact, until last night, i would rugpull it when done, but if im going to let it have an irq, i cant do that. because i have no way of deregistering an irq right now. thats on my todo but hasnt been important
Yeah look while comments could be better uACPI is a low level library and not an ACPI handbook nor tutorial, it expects you to know what acpi is and how it works
i worked around the issue we were having last night
gsi vs irq is a non-issue, the only thing i needed to work around was uacpi's early claim
im only debating docs here
all im saying is, if the lib expects gsi, the param should be gsi_id or such, i would never have thought to question it if i hadnt noticed the value was 32 bits wide
would you accept a pr changing the name of the param in the forward definition and the docblock?
its definitely not always GSI
ACPI can work in PIC mode
the spec calls it a system vector
also, uacpi has this:
/*
* Install/uninstall a new GPE block, usually defined by a device in the
* namespace with a _HID of ACPI0006.
*/
UACPI_ALWAYS_ERROR_FOR_REDUCED_HARDWARE(
uacpi_status uacpi_install_gpe_block(
uacpi_namespace_node *gpe_device, uacpi_u64 address,
uacpi_address_space address_space, uacpi_u16 num_registers,
uacpi_u32 irq
))
In which case the irq number could be anything, including an os-specific id to identify it
for example linux uses a combination of masks to specify an MSI id
i think similar for windows
well, that is not an option here, i dont support PIC. but i guess that means the docs arent as generic as i thought
i think there are definitely some osses here using it in PIC mode btw
like even ironclad used it in pic mode i think
so the correct term is vector number?
i feel like we're splitting hairs, let me know if this is just annoying and i'll shush
well imo if it said system_vector instead of irq itd be even more confusing cuz then it sounds like we're talking about and idt index
because this all comes off the back of my os being "weird" to begin with 
im all for making it more intuitive if theres sometthing definitively bettter
yeah because nobody would point iat at isr 9, thats an exception handler
im guessing 99% of people do what i do, and remap the irq's starting at some constant, usually 32?
yeah
perhaps the docblock just needs to say, in pic mode its a straight irq number, otherwise its a gsi
and the parametrer name remain unchanged
thats the best i can come up with
ig it doesn't depend on pic mode but on whether the system has a pic or not
yeah
fair
although i wonder how reliable that info from the acpi spec is
are there any x86 machines without pic but with acpi?
maybe like amazon firecracker stuff
are there hw reduced chomebooks or something like that?
yeah
even surface laptops
those are always acpi mode iirc
im not sure they have a pic
would be interesting whether they advertise the existence of a pic in fadt (was it fadt?) and whether they have ISA redirect entries in the MADT
yeah no idea
the only thing i do to the pic is immediately disable it
i mean i assume there is one
its 2025 not 1985, no need to use it
the best way I've found to think about uacpi is as a DSL interpreter
like embedding a lua engine in a game
if you mentally replace every instance of AML with lua it starts making slightly more sense lmao
at least at first
the way i think about this: the pci root complex youre looking to get from acpi/aml isnt just some struct somewhere. the info about it is the return values of methods on a class. if you want to get the info, you have to be ready for the methods to call other things
one stupid but entirely legal option is to wait on a semaphore in the method that returns your pci root bus number and wait for an interrupt to send data over and signal it
maybe because theres some coprossecor that mediates the connections and can swap them out or something
itd be a dumb architecture but possible
therefore, in order to call that case of method impl, if you dont support the SCI interrupt (which goes at ISA 9 on x86 but thats arch specific stuff), which is how the aml dsl (read: script) gets given data asynchronously, then the signal function will never get called and the get bus number method will never return
sorry for restarting a talk from 5 hours ago lol
arch specific -> "a you thing" 😄
my OS supports only x86_64, and will only ever support that, portability is not a goal
it does make things simpler
i did work around all these problems though
uacpi can request irq 9, but it wont 'go live' until the IDT is set and the GSI's mapped
this lets me use things like acpi power button
Yeah this is possible and can be done on x86 given insane enough firmware
which i also dont request until i know uacpi has int 9
and when has the phrase "insane enough firmware" stopped any firmware dev lol
https://github.com/brainboxdotcc/retro-rocket/blob/master/src/acpi.c#L753-L800
its 90% the osdev wiki example tbh, but that example lacks some stuff, like halting APs
then theres this for handling "deferred" irq requests from early boot uACPI https://github.com/brainboxdotcc/retro-rocket/blob/master/src/acpi.c#L567-L663
mhm
mostly i saw that deferral idea and was like i can immediately think of a way for insane enough firmware to break with this lmao
i doubt any firmware exists that breaks with this (though id be excited and terrified to be proven wrong somehow) but it IS possible
this is specifically why acpi spec says "firmware is not allowed to access any PCI bus but 0 during the initial namespace loading phase"
only after the os has called the _REG of PCI opregions is it allowed to
this is specifically because PCI enumeration depends on loading the namespace first
oh neat
so this imaginary firmware would definitely work just fine with linux/windows
anything that interacts with firmware is by far where i spend the most time thinking about what bs could someone do to break this lmao
part of why im so glad uacpi exists, takes off a ton of the places id need to do that and makes infy do it there instead
it might give you the wrong mental model though
for example, IDT vectors (or equivalents) are not a thing on !x86
yeah
thats part of why im increasingly leaning towards rewriting my kernel. thought i could refactor out the arch-specific stuff but my kernel relies too much on the existence of an arch-given interrupt numbering system atm
among other issues
mental model of what though, platforms i dont ever want to support? im not trying to make a widely portable unix-like
its enough trying to recall all the knowledge of x86 ive forgotten over the years, wihout having to worry about if i'll one day make it work on risc v or arm
So it looks like all the existing Rust wrappers of uACPI are dead at this point. I kind of need it for my kernel so I'm going to see if I can revive that effort.
Does anyone want to help with it at all?
Maybe CC @rustic compass
Just reached out.
It looks like the acpi crate is still very much a work in progress, and ACPICA hasn't really incorporated the needed changes yet either so the only production level path forward is to wrap uACPI.
Unlike past attempts I wonder if I cant just make a very thin wrapper over the C interface with bindgen, compile the code into a static library and just use FFI to integrate it with my kernel.
i did this
Can I see yours as an example?
I'm setting mine up as a library crate that just uses cc and bindgen.
ah well cc too
you can check my sources, it's just a sys crate basically
I'm doing mine right now. Just need to get the clang flags right since my rust side uses relocatable code and LTO
It builds with the uACPI bindings added through cargo!!!
Excellent
Now to see if it actually works...
ah we could use it for managarm then 
we're upstream on cc and rustc (beta)
(I'm only semi-joking, iretq might be interested)
uacpi-rs isnt dead, just very slowly 
lmk if and how I can help make it go faster.
Using the raw C interface via FFI is a bit unwieldy.
What I'm seeing right now:
maybe use a bigger screen?
lol
I'm on my laptop right now. My desktop has a 45" OLED. But I meant to show how my kernel hooks in the required functionality.
Also Barbenheimer Nuclear Sunrise slaps as an editor theme.
dont give them ideas 😅
I mean that's one case where hardware designers would hate it much more than we do because PCIe has all the complexity on their side unlike USB where it's all on ours.
That said I'd like to see the two get merged into one universal everything bus with fully standardized device classes.
Universal Bus, UB
so both hardware and software can have ub
@fiery turtle prob a brain fart on my side but how exactly does this work again?
uacpi_status uacpi_table_find_by_signature(
const uacpi_char *signature, uacpi_table *out_table
);
uacpi_status uacpi_table_find_next_with_same_signature(
uacpi_table *in_out_table
);
uacpi_status uacpi_table_find(
const uacpi_table_identifiers *id, uacpi_table *out_table
);
with *out_table i pass a ptr to my uacpi_table somewhere in memory and uacpi fills it but i can still move it in memory between api calls?
basicly for refcounting i need to bypass rusts type system and to not go into ub territory i planed to create a copy of the uacpi_table by hand and then pass that to the ref/unref functions
i cant pass the original type/instance as i only get a shared borrow and the ffi wants mutable access
and afaik if i transmute it to a mut ptr is could be immediate ub
wait until you see hw that can: assertion failed
Update: can i rely on that table_ref/unref dont write to the ptr?
idk how it's supposed to work in rust, but the struct just contains a "handle" inside that can be copied by value and that uacpi can use to identify this table and unref it
only find writes into the ptr
good
@fiery turtle how am i supposed to iterate over multiple instances of a table?
just calling uacpi_table_find_next_with_same_signature in a loop?
yes
hw returning an ERRNO
Does uACPI actually help with parsing the static ACPI tables at all or do client kernels need to do that themselves? I'm looking through the headers and from what I can tell there isn't anything there that lets you get information from static tables unless you manually parse them but I might be missing something so I figured I'd ask.
yes
Yes it does or yes kernels have to do it themselves?
it helps you to find tables and provides to you headers
tables.h?
It even has helpers for walking madt etc
Or mcfg I think
Sorry I didn't see that because I'm using it through Rust bindgen which just mashes everything together.
reviving ded thread
for real tho, I wondered how we could package uACPI better than "just" a meson subproject
esp now that we use some of it in eir on managarm
also I was thinking of enabling clang-tidy, possibly even as a GHA job
thoughts?
you mean in uacpi github actions?
yes
i mean its going to blow up if u enable it
it's not that bad
any useful stuff there?
I run clang-tidy over managarm and that automatically includes uACPI
just some minor stuff
ig it depends on what lints you enable though
do u want to enable the same ones as managarm?
as a baseline, probably
do u have a paste of what warnings it currently produces
anyway im not opposed if its useful and we fix whats currently making it mad
for instance
any thoughts on the installing source and a .pc file thing btw?
../../../src/managarm/subprojects/uacpi/source/interpreter.c:775:63: warning: incrementing and referencing a variable in a complex condition can cause unintended side-effects due to C++'s order of evaluation, consider moving the modification outside of the condition to avoid misunderstandings [bugprone-inc-dec-in-conditions]
775 | if (uacpi_unlikely((length == max_bytes) || (string[length++] != 0x00)))
| ^
C++'s order of evaluation
this is not even c++
it probably means u can have operator|| and then it becomes dangerous
but this is C so like
yeah a custom operator|| is not subject to short circuiting
what is that?
pkg-config file
the idea would be to provide uACPI as a source somewhere in the file system
so that other build systems (like meson) can discover that via pkg-config and pull in the sources that way
can pkg-config do that? bring in source files i mean
this could be done so the current way of meson subproject can remain
or do you mean via a custom var
well you can just do a custom var with a path
that's how I would expect header-only libraries would work
although I guess the case where you install them system-wide and not into /usr/include is a bit rare
if you put them in extra_cflags it should work
(btw IMO simply installing into /usr/include is a bad idea and needs to die)
actually no nevermind then you get duplicate definitions
where else would it go?
some other directory to avoid conflicts
so that you can pull it in via cflags from pkg-config
something local or specifically-named
is where headers should go imo
and i just noticed its been 90 mins since that convo lmao
we sometimes install stuff to /usr/lib/<package>/{include,lib} and then symlink the pc file from there to /usr/lib/pkg-config
on Managarm
that allows us to selectively add packages to the kernel's include path (which does not include /usr/include)
getting the just port it already itch again for uacpi and zig
even though the C linking support is great
still gettin the urge
not sure where one would start in uacpi's source when looking to port is all tbh
wdym by port?
as in fully port uacpi to zig instead of just having bindings to it
rewrite it in zig
isnt that what port means?
in the sense of porting a thing to a language
semantics
why would you do an entire rewrite
i get the itch to have everything in the same language lol
then rewrite limine too
and i was in the middle of starting a zig acpi lib when i found uacpi
literally considered starting that but i dont link to limine
idk i think its stupid to rewrite 30k lines into zig just because
i never claimed to not be stupid tbh
and tbh i dont think ill ever actually do it i just feel a temptation every so often
rewriting stuff is a waste of time
I am thinking doing the same for the C# thing 
Mostly because creating bindings is pain
trying to bind to c# definitely has more legs than a zig rewrite lmao
the c# binding is pain
And tbf alot can be simplified because of things like GC and boxing
the only benefits id have are increased understanding of the code and error return traces that dont really matter, youd get to simplify and also not have to deal with c# function pointer casting and similar nonsense
tbh uacpi would be by far the least awful library to make c# bindings for compared to some of the other crap ive worked on\
since you arent dealing with getProcAddress or c++ class stuff
still a good amount of work tho
ever since we got the function to get the next namespace node instead of doing a callback the zig integration lost the only big issue it had lmao
the only "problem" now for zuacpi is you cant easily get a backtrace out from returning an error code from the kernel_api things
and thats doable too if you like suffering and are willing to reserve a few extra usizes somewhere for it
Thats true
I wonder how much slower it would be
well, the current jit is pretty naive :^)
but in theory it shouldn't have much overhead with my impl
interfaces and delegates are just fat pointers, and virtual dispatch is done using normal vtables
I mean GC and stuff, in general uacpi really benefits from hot allocations reusuing the same memory
it's funny that if someone says rewrite it in zig that's weird but "rewrite it in rust" is so common it's a meme now
rewriting in rust is as stupid
agreed, rewriting any established stable program in anything new is always bad
you're just asking for regression
did you see the uutils on ubuntu thing
ubuntu replaced coreutils with rust coreutils and turns out they arent even compatible
Raymond chen wrote a blog about this decades ago and still people don't learn
ah they didn't implement natural sort or did it different?
one of many things that can go wrong
it basically can't change, it's ossified
they dont implement locales
oops and oof
ah it was Joel on Software not Raymond chen
im not sure whats wrong here, iirc uACPI is supposed to print the aml stuff
and not print FACS this way, its missing the rest of it
The facs is printed correctly, it doesn't have those fields.
What is the return code of initialize()?
Also, enable debug logs in uacpi (uacpi_context_set_log_level)
status_ok
because if it wasnt ok it would've printed it
Probably hangs in your code somewhere later on so enable debug logs
does uACPI have debug logs using #define SOMETHING to enable it?
ok
literally the same thing
it doesnt print extra stuff
can u at least add printfs around the calls to see where it hangs? Or use gdb
it hangs in uacpi_initialize
i changed the init logger function to use the debug lvl
and it still prints nothing extra, time to gdb
what does that mean?
i changed it here
u can just call this function before uacpi_initialzie()
it didnt do a difference
i called it after
it didnt do a difference
i changed it inside
and still the same result
yeah im just saying what u did is pointless
not many logs in uacpi_initialize since it doesnt do much
well im sure it has to be in kapi.c
i will check it real quick
then if i dont find something i will use gdb
probably
see if your IO helpers are correct
maybe it hangs trying to enter ACPI mode
yeah it might be that, give me a sec i will check them
looks normal to me
yeah i will
(gdb) s
27 void uacpi_logger_initialize(void)
(gdb) s
uacpi_logger_initialize ()
at arch/x86_64/acpi/uacpi/uacpi.c:36
36 uacpi_info(
(gdb) s
uacpi_log (lvl=UACPI_LOG_INFO,
str=0xffffffff80021d88 "starting uACPI, version %d.%d.%d\n") at arch/x86_64/acpi/uacpi/stdlib.c:701
701 {
(gdb) s
706 uacpi_va_start(vlist, str);
(gdb) s
708 ret = uacpi_vsnprintf(buf, sizeof(buf), str, vlist);
(gdb) finish
Run till exit from #0 uacpi_log (lvl=UACPI_LOG_INFO,
str=0xffffffff80021d88 "starting uACPI, version %d.%d.%d\n") at arch/x86_64/acpi/uacpi/stdlib.c:708
^[[A^[[B^C
Program received signal SIGINT, Interrupt.
0xffffffff8000179c in uacpi_kernel_acquire_mutex (
handle=<optimized out>, timeout=65535)
at arch/x86_64/acpi/kapi/kapi.c:320
320 while (m->locked);
(gdb)
might be that, right?
maybe at least build without optimizations?
ok
but yeah looks like your mutex is broken
i figured so lol
okay i will fix it
do u zero allocate them?
wdym?
and btw the OS is single tasking rn
so mutexes should not work if they have infinte timeout
Why would they ever be non free then
do u know what a zeroed allocation is?
allocate and empty the allocated data?
like zero it
if you allocate your mutexes and forget to initialize them they might contain locked = 1 from the start
calloc
yes
i will just use a constructor and make it zero-ify everything
sure
wait wtf
ik ik i forgot the decl tihng
do u have like a hardcoded array of mutexes
i added it
uh yes
why??
am i supposed to dynamically allocate mutexes?
why not
just like any other object
can u show the other functions as well
im still fixing them to use the new kmalloc-d handles
okay i've got something different now
and the div error happens in namespace_initialize function
u should really invest in backtraces
or at least add cfi annotations to your idt stuff
im not the best at debugging i barely know how to use gdb
uacpi_u64 uacpi_kernel_get_nanoseconds_since_boot(void) {
static uint64_t tsc_base = 0;
static uint32_t cpu_mhz = 0;
if (cpu_mhz == 0)
cpu_mhz = cpuid_get_base_mhz();
if (tsc_base == 0)
tsc_base = rdtsc();
uint64_t tsc_now = rdtsc();
uint64_t delta = tsc_now - tsc_base;
/* ns = (cycles * 1000) / MHz */
return (delta * 1000ULL) / cpu_mhz;
}
found it, when dividing by /cpu_mhz
i know c, s, break, and yeah thats it, i will just use man or the osdev wiki to learn it all
its not that big of a deal i mean im not learning how to hack a nasa computer its just gdb
sure ok
i wont progress much without pit, AHHHHHHHHHHHHH, i will just do HPET since i have tables loaded using uacpi
if you're on intel u can get the TSC frequency like this https://elixir.bootlin.com/linux/v6.17.7/source/arch/x86/kernel/tsc.c#L663
specifically the crystal freq can be extracted from a diff leaf
yeah im actually scraping the entire tsc thing because i can just use HPET
having uacpi initialize different parts in independant functions is smart, then i can do in-between stuff like init HPET
i sould suggest to use tsc
instead of hpet
i use hpet just for sleep
the hardly precise event timer
a timer is a timer
if it can do timer stuff and has the word timer in its name then its good
no, it's not
then what is it if its not a timer
a thing that you should try to not use
FINE i will use PIT
what do i use then
bruh
HPET is not present on legacy devices, PIT is present on all, TSC counts cycles not time
it should be cyclestamp counter not timestamp
where is timekeeping her
here*
the tsc can count time, its actually what it evolved into
anyway I was just memeing, all of those timers can be fine
btw lets move to anyother channel because this is the uACPI progress report post
PIT is the worst timer possible
HPET is the somewhat better one
what do i use then
ACPIPM is in the middle of the 2
apic timer for scheduling and maybe hpet for sleep
apic timer is the most accurate one
and uses the tsc
tsc + cpu speed calculation = timer without interrupts
apic has interrupts tho...
RTC has to be worst
and in terms of not having less than a second of time keeping?
tho it rivals PIT anyway
i think RTC precision is ms
what precision does APIC timer do? and how do i get it without ACPI? because i need all this stuff specifically for ACPI
look there's already been quite a bit of good advice on which timers to use and in what priority, particularly in #x86.
you can do an early init of uAcpi to get the hpet timer
didnt you just tell me to avoid hpet
as a very precise time keeping thing
i want one or two timers at max, one for scheduler and one for sleeping
does APIC timer use PIO like PIT?
wdym PIO?
no
it's a bit more complicated
also we are well and truly off topic, please take this elsewhere so infy doesnt have to read this later.
i just said that a moment ago and yall continued, #drivers
nice attitude lol.
they are drivers tho
PIT is not present on a bunch of stuff, and is difficult to detect
o really
I thought its pretty much a standard PC thing
well ig im only using it to calibrate tsc when hpet isnt there
but other than that I dont think ill make any use for it
Rely on the acpi timer instead
fair
"bunch of stuff" -> mainly non-x86 machines
I'm talking about PCs
yet to see one that has no PIT
I've seen several
because its required to properly emulate an 80386 and real mode
Relatively old and new ones
without a PIT dos aint gonna work
because it used the pit on irq 0 for an ...what was it, 18hz interrupt?
There's no emulation of them
intel did talk about doing away with real mode entirely, x86-S or something. i dont think it got off the ground, too much stuff still relies on real mode that cant just be replaced
You're probably referring to running old operating systems that expect it
Like if you have UEFI class 3 machine, then why do you care about that?
yes and they have to provide it
plenty of new intel motherboards dont have a working PIT
or its not a compatible cpu
It's not about a CPU
by "it" i mean real mode, 32 bit protected mode
@lofty dragon's motherboard for example
And from 2010s as well
You don't need PIT for real mode
so what happens on a machine without a PIT if you try and program the PIT, isnt it intrinsictly linked into the way the dual PIC behaves?
You need PIT for operating systems that expect it
dos expects it
those PCs dont have a bios as well, no CSM
No
it, and many of its 'drivers' use its 18hz PIT driven interrupt
Arrow Lake motherboards are all in in dropping legacy compatibility
DOS and real mode is like comparing apples and cars
then its a non-issue on anywhere that may try to use the PIT, because its majority 16 bit OSes
they are class 3 UEFI
novell netware 3? and DOS
So 30+ years old operating systems
what's worse about that motherboard is that it does have a PIT, and it's even in the ACPI structures, but it's clock gated and therefore does not tick on its own unless accessed
Arrow Lake is a half assed piece of shit platform, Intel should've failed
Tbh it's probably also a firmware bug/responsibility, if it's broken, then ACPI shouldn't have it
it's a broken platform
The issue is that you shouldn't be using it unless you're targeting very old PCs
that's not true either
Linux uses the PIT on my Zen 5 system for some calibration related stuff
yeah
for tsc early calibration
Also, Linux is a good example of bad engineering 
yeah their calibration code is a fucking mess
random global function pointers overwritten in random places in code
what do BSDs do?
no idea
Like the thing that saves them is that everyone uses it and they can add workarounds
But Linux's sleep is broken on my laptop for example
(probably because of the ACPI mess)
I remember there was a brochure "book" like those "X for dummies", something 15 years ago, about linux, how to use it and, of course, depicting it as something superior, god chosen. I was skimming over it, it was in a store and I stumbled upon the "turning off and sleeping" part. They wrote there something like: "because linux is a real OS,
it doesn't really need to be turned off..." 😁 I was "oh, makes sense now of why it can't do that half of the times". Masters of representing crap as virtue.
i don't think this statement was ever true
that linux doesn't really need to be turned off
at least you need to unmount and sync every FS
Yeah, android on my phone annoys me every 3, 4 days with notifications that "I need to restart my phone 'for bettah perfomance'". 😁 you are way too serious.)))
never had my android phone ask me to reboot lol
Out of a sudden the uACPI post became chatting about timers lol
@fiery turtle can you add some documentation like limine has PROTOCOL.md or something like that, its pretty unclear to me how to use uACPI in most cases
look at other os sources
how many OSs do battery stuff using uACPI
if you know one that'd be pretty good
maybe managarm ?
okay thanks
You're new on this server
There is osdev wiki, for other more complex stuff I really don't have time
Replying to this
ig so
Also, getting battery stats is outside the scope of uacpi documentation
Read the ACPI specification, its 1000 pages long
U just need to call like two methods so its pretty easy, see other os sources
ok
but still you kinda need some basic docs at least
uACPI is major in a lot of OSs so having basic docs is pretty important
Managarm 
C++
What language are you using?
Osdev wiki and headers
Sounds basic enough to me
But idk no one really had much issue with it?
C
Osdev wiki doesnt show how to deal with batteries
my ACPI/devices server is in C
I would say that battery is somewhat far down the rabbit hole
can't say its compelte or well tested, but it worked on my laptop :^)
90% of acpi drivers is just installing a notify handler and calling random methods whenever the notification happens
^
lol maybe we should put this under the uacpi org
its pretty cool to have some examples
just add threads to ultra already and we can transfer the drivers smh
nah like it will never be as educational since all this info will be passed to userspace services etc
hmmmm true ig
yeah I guess its nice that its kernel only without much abstractions or anything
yeah i think its valuable to have
tbh I did start to get the urge to work on it again

the first thing might be to rework some of the core cause I don't like that it uses thread_local anymore
ever since we talked about it in ultra lol
its probably using some super old version as well lol