#uACPI - a portable and easy-to-integrate ACPI implementation
1 messages ยท Page 13 of 1
i actually found two bugs because of your blobs, and one random one by browsing code while looking for your bug
all fixes pushed
the rest were minor but still
have u tried on there?
that would be interesting
but its old so probably not that big
but quirky af most likely
so good test
can u get a quick dump from it?
unlucky
get managarm gods or mathewnd to help u
steal it again until it works
I have frequency in nHz
And period in nHz^-1 (aka ns)
Why multiplying tsc * period gives me garbage
nanohenry :^)
recommend doing it as a fraction, if youre using an int for the period thatll be losing precision
I'm using fractions
3600042kHz is my emu's tsc freq
or maybe thats lapic
So 32949014999 should be close
Relatively
kvm timer is 1 ns ticks
about 10 times faster than what qemu is giving me if im counting digits right
ah
can u help pmos get a working timer mathewnd
I mean my timers arent that good either 
last time i checked astral time keeping is super accurate
Is there something obviously wrong here?https://gitlab.com/mishakov/pmos/-/blob/ia32/kernel/arch/x86_64/interrupts/apic.cc?ref_type=heads#L95
(I kinda don't want to deal with timers right now)
This is 9.15 times faster than the theoretical value
So 5,644,145/9.15 = 616'846 ops/s
what you cooking
#1316457641353936956
damn
yeah we're thinking of a common kernel api structure
not sure yet how its going to look
I mean, the uacpi kernel api is pretty good
problem is, some drivers need more, some need less
and it provides most things that a driver would need (ignoring actual subsystem abstractions)
e.g. udrm will need a ton more stuff
phys page allocation, bar mapping, msi, cpu affinity, threads, work queues etc
isn't work queues already abstracted?
sorta
you have the schedule work or something alike
bar mapping is basically the normal map function
not for arm stuff
true, the arm pcie controllers are garbage
yea
ecam was created for a freaking reason
but nooooo
you need to be special and have cfg0/cfg1 memes
and the weird offsets
thing is that defining too much and you might as well define how the kernel should behave
I think that's one of the things RISC-V did right
alright im on vacation so time to hardcore push uACPI release 1.0
first things is ironing out final thread safety stuff
So far fixed this one
the unfortunate news is some problems are unsolvable without a recursive mutex
ew
can't you just internally keep the recursion count?
because there's handler install code that needs the ns write lock, then releases it for the duration of calling a user's handler because that might also call into the interpreter, but the problem is when it does it the installation is in half-finished state
yeah ofc and i already do for aml mutexes
its just unfortunate overall
i have all the kernel api to implement one
normal mutex + thread_id getter
uacpi_status uacpi_acquire_aml_mutex(uacpi_mutex *mutex, uacpi_u16 timeout)
{
uacpi_thread_id this_id;
uacpi_status ret = UACPI_STATUS_OK;
this_id = uacpi_kernel_get_thread_id();
if (UACPI_ATOMIC_LOAD_THREAD_ID(&mutex->owner) == this_id) {
if (uacpi_unlikely(mutex->depth == 0xFFFF)) {
uacpi_warn(
"failing an attempt to acquire mutex @%p, too many recursive "
"acquires\n", mutex
);
return UACPI_STATUS_DENIED;
}
mutex->depth++;
return ret;
}
uacpi_namespace_write_unlock();
ret = uacpi_acquire_native_mutex_with_timeout(mutex->handle, timeout);
if (ret != UACPI_STATUS_OK)
goto out;
if (mutex->handle == g_uacpi_rt_ctx.global_lock_mutex->handle) {
ret = uacpi_acquire_global_lock_from_firmware();
if (uacpi_unlikely_error(ret)) {
uacpi_release_native_mutex(mutex->handle);
goto out;
}
}
UACPI_ATOMIC_STORE_THREAD_ID(&mutex->owner, this_id);
mutex->depth = 1;
out:
uacpi_namespace_write_lock();
return ret;
}
this is already existing code, but looks like ill have to add similar code for native mutexes
void u()
{
while (1) {
uacpi_install_address_space_handler(
uacpi_namespace_root(), UACPI_ADDRESS_SPACE_PCC,
handle_ec, nullptr
);
}
}
void uu()
{
while (1) {
uacpi_uninstall_address_space_handler(
uacpi_namespace_root(), UACPI_ADDRESS_SPACE_PCC
);
}
}
std::thread t0(u);
std::thread t1(uu);
t0.join();
least insane test
/mnt/d/uACPI/source/io.c:231:35: runtime error: member access within null pointer of type 'struct uacpi_address_space_handler'
AddressSanitizer:DEADLYSIGNAL
=================================================================
==2566==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000010 (pc 0x564416b1ad16 bp 0x7f5918afe310 sp 0x7f5918afe1e0 T1)
==2566==The signal is caused by a READ memory access.
==2566==Hint: address points to the zero page.
#0 0x564416b1ad16 in dispatch_field_io /mnt/d/uACPI/source/io.c:231
#1 0x564416b1bb92 in access_field_unit /mnt/d/uACPI/source/io.c:312
#2 0x564416b1d35b in uacpi_write_field_unit /mnt/d/uACPI/source/io.c:461
#3 0x564416acf837 in object_assign_with_implicit_cast /mnt/d/uACPI/source/interpreter.c:978
#4 0x564416adde91 in store_to_reference /mnt/d/uACPI/source/interpreter.c:2332
#5 0x564416af65ee in store_to_target /mnt/d/uACPI/source/interpreter.c:4194
#6 0x564416af6acf in handle_copy_object_or_store /mnt/d/uACPI/source/interpreter.c:4227
#7 0x564416affa20 in exec_op /mnt/d/uACPI/source/interpreter.c:5403
#8 0x564416b02b7d in uacpi_execute_control_method /mnt/d/uACPI/source/interpreter.c:5755
#9 0x564416b0ffa9 in region_run_reg /mnt/d/uACPI/source/opregion.c:143
#10 0x564416b12b51 in do_run_reg /mnt/d/uACPI/source/opregion.c:451
#11 0x564416b0897a in uacpi_namespace_do_for_each_child /mnt/d/uACPI/source/namespace.c:876
#12 0x564416b13249 in reg_or_unreg_all_opregions /mnt/d/uACPI/source/opregion.c:506
#13 0x564416b13ef3 in uacpi_install_address_space_handler /mnt/d/uACPI/source/opregion.c:642
this is what im trying to protect against
this is my AML blob:
Device (X) {
OperationRegion (Y, PCC, 0, 100)
Device (X) { OperationRegion (Y, PCC, 0, 100)
Device (Z) { OperationRegion (Y, PCC, 0, 100) Method (_REG, 2) { Field (Y, AnyAcc, NoLock, WriteAsZeros) { Z, 1 } Z = 1 }}
Device (A) { OperationRegion (Y, PCC, 0, 100) Method (_REG, 2) { Field (Y, AnyAcc, NoLock, WriteAsZeros) { Z, 1 } Z = 1 }}
Device (C) { OperationRegion (Y, PCC, 0, 100) Method (_REG, 2) { Field (Y, AnyAcc, NoLock, WriteAsZeros) { Z, 1 } Z = 1 }}
Device (D) { OperationRegion (Y, PCC, 0, 100) Method (_REG, 2) { Field (Y, AnyAcc, NoLock, WriteAsZeros) { Z, 1 } Z = 1 }}
Device (B) { OperationRegion (Y, PCC, 0, 100) Method (_REG, 2) { Field (Y, AnyAcc, NoLock, WriteAsZeros) { Z, 1 } Z = 1 }}
Device (F) { OperationRegion (Y, PCC, 0, 100) Method (_REG, 2) { Field (Y, AnyAcc, NoLock, WriteAsZeros) { Z, 1 } Z = 1 }}
Device (G) { OperationRegion (Y, PCC, 0, 100) Method (_REG, 2) { Field (Y, AnyAcc, NoLock, WriteAsZeros) { Z, 1 } Z = 1 }}
Device (H) { OperationRegion (Y, PCC, 0, 100) Method (_REG, 2) { Field (Y, AnyAcc, NoLock, WriteAsZeros) { Z, 1 } Z = 1 }}
Device (L) { OperationRegion (Y, PCC, 0, 100) Method (_REG, 2) { Field (Y, AnyAcc, NoLock, WriteAsZeros) { Z, 1 } Z = 1 }}
}
Device (Z) { OperationRegion (Y, PCC, 0, 100) }
Device (A) { OperationRegion (Y, PCC, 0, 100) }
Device (C) { OperationRegion (Y, PCC, 0, 100) }
Device (D) { OperationRegion (Y, PCC, 0, 100) }
Device (B) { OperationRegion (Y, PCC, 0, 100) }
Device (F) { OperationRegion (Y, PCC, 0, 100)
Device (Z) { OperationRegion (Y, PCC, 0, 100) Method (_REG, 2) { Field (Y, AnyAcc, NoLock, WriteAsZeros) { Z, 1 } Z = 1 }}
Device (A) { OperationRegion (Y, PCC, 0, 100) Method (_REG, 2) { Field (Y, AnyAcc, NoLock, WriteAsZeros) { Z, 1 } Z = 1 }}
Device (C) { OperationRegion (Y, PCC, 0, 100) Method (_REG, 2) { Field (Y, AnyAcc, NoLock, WriteAsZeros) { Z, 1 } Z = 1 }}
Device (D) { OperationRegion (Y, PCC, 0, 100) Method (_REG, 2) { Field (Y, AnyAcc, NoLock, WriteAsZeros) { Z, 1 } Z = 1 }}
Device (B) { OperationRegion (Y, PCC, 0, 100) Method (_REG, 2) { Field (Y, AnyAcc, NoLock, WriteAsZeros) { Z, 1 } Z = 1 }}
Device (F) { OperationRegion (Y, PCC, 0, 100) Method (_REG, 2) { Field (Y, AnyAcc, NoLock, WriteAsZeros) { Z, 1 } Z = 1 }}
Device (G) { OperationRegion (Y, PCC, 0, 100) Method (_REG, 2) { Field (Y, AnyAcc, NoLock, WriteAsZeros) { Z, 1 } Z = 1 }}
Device (H) { OperationRegion (Y, PCC, 0, 100) Method (_REG, 2) { Field (Y, AnyAcc, NoLock, WriteAsZeros) { Z, 1 } Z = 1 }}
Device (L) { OperationRegion (Y, PCC, 0, 100) Method (_REG, 2) { Field (Y, AnyAcc, NoLock, WriteAsZeros) { Z, 1 } Z = 1 }}
}
Device (G) { OperationRegion (Y, PCC, 0, 100) }
Device (H) { OperationRegion (Y, PCC, 0, 100) }
Device (L) { OperationRegion (Y, PCC, 0, 100) }
}
uacpi_namespace_write_unlock();
ret = handler->callback(UACPI_REGION_OP_ATTACH, &attach_data);
uacpi_namespace_write_lock();
if (region->handler == UACPI_NULL) {
uacpi_error("Lol handler is gone while we were attaching it\n");
}
this is what im talking about
why i need recursive mutexes
[uACPI][ERROR] Lol handler is gone while we were attaching it
at least some mutex must be held while we're calling into a user-provided handler
uacpi_object_ref(obj);
uacpi_namespace_write_unlock();
ret = handler->callback(UACPI_REGION_OP_ATTACH, &attach_data);
uacpi_namespace_write_lock();
// Handler might've disappeared while we were attaching it
if (uacpi_unlikely(region->handler == UACPI_NULL))
return UACPI_STATUS_NO_HANDLER;
Hmm this check technically fixes the segfault and i can cleanly abort in this case
i wonder if this could be the way out
you are removing the only excuse i had to procrastinate and not work on the uacpi rust bindings

[uACPI][TRACE] deactivated all 'PCC' opregions controlled by '\ ', 29 _REG() calls (18 errors)
now thats what i call a nice race condition
18 races out of 29 calls
but seems to not crash at least
my _REG serialization solution was bogus and causes deadlock tho so thats nice
whatever time to go workout and get some food
U can do it infy, i believe in u
thanks
this is an unsolved problem in acpica so i get brag rights
if i do it that is
You've already got quite a few bragging rights over ACPICA
lol
if you do need reentrant kernel mutexes, can you provide an option to use ones the kernel already has instead of forcing uacpi to implement them?
my imaginarium ones already have that option (though I think it's actually bugged right now lmao)
possibly, but I'm not sure that's useful given i have all the primitives needed for them?
if you want to do it yourself then sure lol
i already had to implement a special-cased version for AML mutex objects so kinda
nice, my acpica fix for linux was added to a bunch of linux stable branches
big W
thanks
this was a type of bug that would make keyronex panic, but I guess linux had a workaround for it
so it never manifested itself in prod
okay i think i got it finally
std::thread t0([] {
while (1) {
uacpi_install_address_space_handler(
uacpi_namespace_root(), UACPI_ADDRESS_SPACE_PCC,
handle_ec, nullptr
);
}
});
std::thread t1([] {
while (1) {
uacpi_uninstall_address_space_handler(
uacpi_namespace_root(), UACPI_ADDRESS_SPACE_PCC
);
}
});
t0.join();
this is now fully thread safe and serialized in uacpi
just so u know the amount of work this does on install:
- attach a new address space handler to the device object
- scan every opregion node under this device and attach the handler to it
- run _REG for every new opregion found
- if this opregion is accessed, dispatch to user handler first with OP_ATTACH, then with OP_READ/WRITE, both release the interpreter lock for the duration
and uninstall does the same, but in reverse, while also calling into the user handler with OP_DETACH
so its insane to serialize properly
static uacpi_status upgrade_to_opregion_lock(void)
{
uacpi_status ret;
/*
* Drop the namespace lock, and reacquire it after the opregion lock
* so we keep the ordering with user API.
*/
uacpi_namespace_write_unlock();
ret = uacpi_recursive_lock_acquire(&g_opregion_lock);
uacpi_namespace_write_lock();
return ret;
}
I have this atrocity where the interpreter might call into the opregion subsystem tho
attaching EC 17028
[uACPI][TRACE] write to [\X___.X___.Z___.Y___] (1 bytes) PCC[0x0000000000000000] = 0x1
attaching EC 17029
[uACPI][TRACE] write to [\X___.X___.A___.Y___] (1 bytes) PCC[0x0000000000000000] = 0x1
attaching EC 17030
[uACPI][TRACE] write to [\X___.X___.C___.Y___] (1 bytes) PCC[0x0000000000000000] = 0x1
attaching EC 17031
[uACPI][TRACE] write to [\X___.X___.D___.Y___] (1 bytes) PCC[0x0000000000000000] = 0x1
attaching EC 17032
[uACPI][TRACE] write to [\X___.X___.B___.Y___] (1 bytes) PCC[0x0000000000000000] = 0x1
attaching EC 17033
[uACPI][TRACE] write to [\X___.X___.F___.Y___] (1 bytes) PCC[0x0000000000000000] = 0x1
attaching EC 17034
[uACPI][TRACE] write to [\X___.X___.G___.Y___] (1 bytes) PCC[0x0000000000000000] = 0x1
attaching EC 17035
[uACPI][TRACE] write to [\X___.X___.H___.Y___] (1 bytes) PCC[0x0000000000000000] = 0x1
attaching EC 17036
[uACPI][TRACE] write to [\X___.X___.L___.Y___] (1 bytes) PCC[0x0000000000000000] = 0x1
attaching EC 17037
[uACPI][TRACE] write to [\X___.F___.Z___.Y___] (1 bytes) PCC[0x0000000000000000] = 0x1
attaching EC 17038
[uACPI][TRACE] write to [\X___.F___.A___.Y___] (1 bytes) PCC[0x0000000000000000] = 0x1
attaching EC 17039
[uACPI][TRACE] write to [\X___.F___.C___.Y___] (1 bytes) PCC[0x0000000000000000] = 0x1
attaching EC 17040
[uACPI][TRACE] write to [\X___.F___.D___.Y___] (1 bytes) PCC[0x0000000000000000] = 0x1
attaching EC 17041
[uACPI][TRACE] write to [\X___.F___.B___.Y___] (1 bytes) PCC[0x0000000000000000] = 0x1
attaching EC 17042
[uACPI][TRACE] write to [\X___.F___.F___.Y___] (1 bytes) PCC[0x0000000000000000] = 0x1
attaching EC 17043
[uACPI][TRACE] write to [\X___.F___.G___.Y___] (1 bytes) PCC[0x0000000000000000] = 0x1
attaching EC 17044
[uACPI][TRACE] write to [\X___.F___.H___.Y___] (1 bytes) PCC[0x0000000000000000] = 0x1
attaching EC 17045
[uACPI][TRACE] write to [\X___.F___.L___.Y___] (1 bytes) PCC[0x0000000000000000] = 0x1
[uACPI][TRACE] activated all 'PCC' opregions controlled by '\ ', 29 _REG() calls (0 errors)
detaching EC 17046
detaching EC 17047
detaching EC 17048
detaching EC 17049
detaching EC 17050
detaching EC 17051
detaching EC 17052
detaching EC 17053
detaching EC 17054
detaching EC 17055
detaching EC 17056
detaching EC 17057
detaching EC 17058
detaching EC 17059
detaching EC 17060
detaching EC 17061
detaching EC 17062
detaching EC 17063
At least all logs are like this now, no races
how is this safe?
this looks like a weird mechanism
you drop the namespace_write lock, so other threads can take it now
but if it's fine for other threads to take it, why do you have it in the first place?
lock not held means the namespace state is unknown, temporary nodes referenced might've been destroyed, objects held might've been deleted since the owner node got copyobject'ed into
it's safe to drop the lock as long as any objects needed for the duration of the operation have an extra reference keeping them alive and when we don't intend to modify the namespace
in this case i dont do either of those, and i verify that the object that i have with namespace locked is still what i want, e.g. that it didnt get overwritten by other aml during lock upgrade
so basically without the ns lock held its unsafe to:
- scan the namespace
- access objects at permanent namespace nodes
- access temporary namespace nodes
i see
the problem is there's user api to manipulate opregion handlers, and it calls into the interpreter, which may call back into opregion code, which may in turn need to run the user IO handler (for the duration of which i have to release the namespace lock so user can run aml inside handlers), during this window anyone can call uninstall_handler, which will uninstall the handler that is currently being used for AML IO
so there has to be some mutex ensuring serialized access to opregion handlers
which the ns lock is not good enough for because user handlers require releasing it
this is further made more difficult by the fact that a device might have any number of opregions underneath, and all must be regged and unregged in a seralized manner as well
idk if what im saying makes sense, its kinda hard to understand without the full context
ACPICA also drops the ns lock for user handler IO, but it doesn't care to protect against anyone calling handler_uninstall() from a different thread during this window, so u can blow it up quite easily, nor does it serialize reg/unreg
obligatory astral test
while i wait for CI
@north holly does obos currently boot on real hw
do u want to test new thread safety stuff 
Sure
Mhm
no api changes
K
It worked on real hw
nice
nooo my com collection
Anyways thanks for testing
All tests passed as well
Alright thats one huge roadblock before 1.0 solved
The last non-thread-safe thing in uACPI is events
I will fix that tomorrow
Only took like 6 hours today
Figuring out what code paths are possible
Im not a giant fan of the solution but i cant currently even theoretically think of a different one
nice
I really need to figure out whats making it so slow
Ok so
Event thread safety
I will have to change the meaning of uacpi_kernel_wait_for_work_completion
It will have to be also wait for in-flight ACPI irqs to finish
basically similar to synchronize_hardirq(); in linux
otherwise i cant guarantee that the interrupt handler won't touch event handlers that are being deleted
/*
* Waits for two types of work to finish:
* - All work scheduled via uacpi_kernel_schedule_work
* - All in-flight interrupts installed via uacpi_kernel_install_interrupt_handler
*/
uacpi_status uacpi_kernel_wait_for_work_completion(void);
basically like this
so event handler deinstallation will do:
- mask the event in the GPE register block
- wait for in-flight interrupts to complete
- unregister the handler
- restore the old native handler if one existed
- unmask
Is EC driver basically just functions to read and write to/from its registers, passed by uACPI?
yup
Can there be more than one controller??
technically nothing prevents it
but almost impossible
managarm supports only one i think
The ACPI standard supports multiple embedded controllers in a system, each with its own resources
sure why wouldnt the standard support it
I guess I'll support multiple because why not
It doesn't look difficult to do
Does it not pass ECDT?
your laptop doesnt have ECDT
What does global lock refer to in https://github.com/managarm/managarm/blob/275c0704a05cb904ae10d8964c6a300ac30d2dc7/kernel/thor/system/acpi/ec.cpp#L297 ?
global ACPI firmware lock
uacpi_acquire_global_lock
What do I need it for?
(where am I supposed to acquire it)
Did anyone notice that managram doesn't initialize gpeNode?
Is that intended?
You dont
The firmware might ask you to lock it
When u access EC
Yes, the null node is allowed, take a look at uacpi event header
Its resolved into _GPE automatically
I've already looked at it
I guess they have clearing allocator
Can EC be in memory? 
The what
Who knows
calloc
Since managram only takes UACPI_RESOURCE_TYPE_IO and UACPI_RESOURCE_TYPE_FIXED_IO

Yeah I doubt other exist but u can take a look at which ones Linux expects
Elixir Cross Referencer - source code of Linux v6.12.5: drivers/acpi/ec.c
Btw why doesn't the aml just implement the EC driver? Is there an actual reason or just yet another acpi weirdness?
it could I guess, fundamentally it's an asynchronous device, which might take an unpredicatble amount of time to respond so I guess they decided to offload that to the kernel
But acpi has everything it needs to handle async code
It has the event mechanism and the gpe mechanism
yeah
it would require non-trivial aml with events and stuff, I guess firmware devs are not at that level yet
The only actual reason I can think of is if maybe the OEM wants its own driver to do some EC stuff, but they could have just used the aml driver for both

one other reason i can think of is EC is used directly by the host to request hw specific information about thermals and firmware settings etc
maybe they did it to avoid races with host
i think the real reason is because aml is a shitty programming language
Is there a reason uacpi doesn't provide it's own EC driver?
and vendors dont want to write even more aml
already answered before
Lemme search then
#1217009725711847465 message
lmao
It doesn't work in threada
like in general
Tbh I can't really agree with the quirk thing because if you won't handle it no one would, but the coupling with the kernel I can understand
handling it requires uacpi to have SMBIOS hooks in kernel api
so basically just too many extra kernel api functions needed for that
uapi will definitely need platform info yeah
Its funny because I am not sure if I will even use any of these stuff in my C# kernel giving the whole goal is to have managed drivers 
C# bindings for uAPI 
I am actually kinda waiting to see the API to see if I can take inspiration from it lol
Like I need "safe" abstractions over interrupts and hardware resources
And I wasn't that impressed with the rust Linux bindings for inspiration
The closest to a nice api inspiration is WDK from all things
Ah yes I too like a switch case over every kernel function because ?????
Where would it be asking?
_GLK evaluating to 1
Elixir Cross Referencer - source code of Linux v6.12.5: drivers/acpi/ec.c
Oh so basically when doing reads and writes?
ye
But not in GPE handler
uACPI will be fully thread safe after I merge this PR!
it's basically done, just need to test it now
to test this properly ill need managarm because no one else uses events properly
Are they difficult to implement?
I should implement ec driver
I've started writing it
ok nice
yes
But I have an exam now...
Like maybe before adding the new syscalls
i can test obos on like 5 laptops if u do it
ill have to pull them out and find chargers tho
damn
I think
does your os boot on all?
Yes
Oh cool
Will be doing that soon
nice, if u add an ec driver that should be a very large coverage
if u do fn+various keys it should spam EC events
How would I see them?
same for AC charger/lid and stuff like that if u have laptops
One of them broke limine lmao
Pragmatic microkernel-based OS with fully asynchronous I/O - managarm/managarm
the EC makes u run AML
that it wants
Although I'll only be able to test it on the weekend
And potentially not all of them are working
Like my old laptop died a month ago 
But it's a battery problem so I can disassemble it and disconnect it I'd suppose
And it's a weird HP 2 in 1, which struggles with sound in Linux
Anyway, I think I'll try to finish it today's evening, and at least try it on my Lenovo laptop
okay astral revealed a slight skill issue but seems to be fixed now
seems to work
that would be nice
Event stuff was much easier to make thread safe and ended up cleaner and safer than ACPICA
ACPICA has a complex mutex + spinlock design
And still subject to race windows
Whereas i just use a mutex for public API + mask the corresponding event when modifying its handlers so it can't even occur and thus race against handler modification
What was it
I moved some logic into a separate helper and it was page faulting
static uacpi_status for_all_gpes_locked(struct do_for_all_gpes_ctx *ctx)
{
uacpi_status ret;
UACPI_ENSURE_INIT_LEVEL_AT_LEAST(UACPI_INIT_LEVEL_SUBSYSTEM_INITIALIZED);
ret = uacpi_recursive_lock_acquire(&g_event_lock);
if (uacpi_unlikely_error(ret))
return ret;
for_each_gpe_block(do_for_all_gpes, &ctx);
uacpi_recursive_lock_release(&g_event_lock);
return ctx->ret;
}
can u spot the bug?
ctx?
&ctx
yup
also I noticed astral doesnt even initialize events lol
i forgor to add it ๐
--- a/kernel-src/io/acpi/acpi.c
+++ b/kernel-src/io/acpi/acpi.c
@@ -35,6 +35,8 @@ void acpi_init(void) {
__assert(ret == UACPI_STATUS_OK);
uacpi_install_fixed_event_handler(UACPI_FIXED_EVENT_POWER_BUTTON, handle_pwrbtn, UACPI_NULL);
+
+ uacpi_finalize_gpe_initialization();
}
I decided to use recursive locks but it's mostly to prevent the user from deadlocking themselves if they want to do something about the event from an event handler
which technically u shouldn't be doing but whatever
no such kernel api
So it's spinlocks

uacpi_status uacpi_recursive_lock_acquire(struct uacpi_recursive_lock *lock)
{
uacpi_thread_id this_id;
uacpi_status ret = UACPI_STATUS_OK;
this_id = uacpi_kernel_get_thread_id();
if (UACPI_ATOMIC_LOAD_THREAD_ID(&lock->owner) == this_id) {
lock->depth++;
return ret;
}
ret = uacpi_acquire_native_mutex(lock->mutex);
if (uacpi_unlikely_error(ret))
return ret;
UACPI_ATOMIC_STORE_THREAD_ID(&lock->owner, this_id);
lock->depth = 1;
return ret;
}
Does recursive lock include recursive unlock?
yes
Like if I lock twice, the first time I unlock doesn't release it, but the 2nd time it does
uacpi_status uacpi_recursive_lock_release(struct uacpi_recursive_lock *lock)
{
if (lock->depth-- > 1)
return UACPI_STATUS_OK;
UACPI_ATOMIC_STORE_THREAD_ID(&lock->owner, UACPI_THREAD_ID_NONE);
return uacpi_release_native_mutex(lock->mutex);
}
maybe check that the owner is the current thread before decrementing the recursion depth?
maybe, but then again its kinda internal api so something has gone horribly wrong if that check fails
i could add that to just log BUG: ...
i was thinking just assert that thats the case
Uacpi has no assert
^
uACPI's ideology is that it has no right to decide what is worthy of panic
so all errros are propagated back to the host
it does reset its own state if some critical init fails tho
uAssert when
uKernel
wouldnt it be better if all manageable error are handled and the rest is an Abort?
whats an example of an unmanagable error?
.
thats just an internal error IMO
like it could signify a memory corruption for example ofc
but idk if its worth to abort just because it might be one
guys just do it like managarm
lol
add asserts everywhere
yeah as an optional "fortified" uacpi build i could definitely add that tbh
DEBUG build lol
assert(if cpu exists)
for debugging shitty kernel api
yeah
which is based
have u asserted if the cpu actually exists
and possibly internal errors
#ifdef UACPI_MAYBE_BROKEN_KERNEL_API
void uacpi_kernel_abort(const uacpi_char *why);
#endif
(100% of operating systems that use uACPI)
nah i think ```c
#ifdef UACPI_DEBUG_ASSERTIONS
#define UACPI_CHECK(cond) do { if (cond) { while (1) {} } } while (0)
#else
#define UACPI_CHECK(cond) do { } while(0)
#endif
// please add this to uacpi
void uacpi_init() {
uacpi_allocator_init();
uacpi_arch_init();
uacpi_scheduler_init();
uacpi_vfs_init();
uacpi_own_entry_init();
}
and ud2 in there or something maybe
true
but if internal consistency checks are failing, the kernel hooks are more than a bit suspect
infy add this 
Have you considered adding heap to uACPI?
something like this except it's wrapped in #ifndef UACPI_CHECK so the kernel can provide an assert that's a bit more visible
or it would be a UACPI_ARCH_UD2 but at that point might as well have a hook instead
yes
So it just calls mmap
if its gcc or clang you use __builtin_trap()
else just hang
who compiles a kernel with msvc
__debugbreak or something
I think llvm already does that too well
I do for testing
nullptr and its value is an index into a error table
insane
and in optimized builds you can __builtin_assume that it doesnt happen too
would be nice to have such option
Does msvc output to elf?
no
uHeap 
lol
I could add PE linker 
I already had to sacrafice a lot of make uacpi compilable under msvc so at this point its sunk cost fallacy
what about uACPITableBuilder
like an asl compiler?
why
why support a compiler
no one is gonna use
i work on windows
i havent seen one osdev compile their kernel with msvc
plus its an extra platform for testing
plus kernels that go for nt compat
since uacpi is nt compatible
NT compat doesnt mean you have to use the cringe compiler
uacpi.sys when
^
yeah still tho
already exists
oh
wip in reactos
there's wsl
this
could u somehow replace the aml interrepter with uacpi
good question
would be based for testing
insane
yeah
apparently uacpi fixed touchscreen detection in reactos on that tablet
idk how exactly but thats cool
they were previously using acpica
Did reactos switch to uacpi?
That's cool
yeah that would be a huge milestone for uacpi as well
Imagine Linux switching one day
yeah its doable, just a lot of files to go 1 by 1
but uacpi is very close to feature parity with acpica
there's like a few thousand acpica api calls
each one has to be carefully changed
although a lot of them are almost identical
also uACPI's repo is a bit over 2 years old now
which is crazy
i finished the interpreter last december
and its been all the rest of the features since then
and fixes etc
yeah it couldnt do shit back then
yeah lol
I can link his kernel wait
Daily obos shilling complete
never seen it before
Yeah it is a pretty cool kernel
Although since it first ported uacpi, it has had some rewrites
lol
i think we can talk about the second kernel that ported uacpi
its pretty cool
it was made by a guy i can link his kernel wait
its had some rewrites tho
idk

Daily nyaux shilling complete
guys what about kernel rewrite by some guy named ilobilo
I hear it throws a coprocessor segment overrun exception if you press a key in vmware
that dumass probably messed up the pic again
Lmao
Actually I dont know which kernel was second
I wanna say managarm
I guess I should only enable interrupts when the pic is remapped lol
mine was definitely after managarm
But it kinda wasn't
Managarm was 2nd
I believe
Was I third?
Perhaps
Astral was first because all others arent real operating systems
Astral <------- real operating system
Linux windows etc etc <------- delusional cosplayers
I am also the first one using uacpi to implement suspend functionality
And the first one to implement device detection via uacpi (sometime in February)
I'm racing you to be the second OS to have EC
Well I can't work on obos for another couple hours
Lol
True true
I can't either
time to speedrun a cros_ec driver
Also true
Managarm ec driver port speedrun
ctrl+c ctrl+v speed contest
found ec spec
what kind of stuff does an EC do anyway?
magical stuff
Its two registers
Was I the second to do PCI interrupts routing with uACPI?
Abstraction over proprietary firmware state basically
what aml wants it to do
"need"
i can get an m1
On broken modern devices
Basically all firmware stuff
and then i get the power button from something else
yeah aka laptops
i think chromebooks have their own linux driver
Basically all x86 hw after circa 2010 has one
Yeah some have a fucked up quirky ec
So they get a special driver or quirk
i wouldnt call it fucked up and quirky
they have their own entire driver lol
called cros_ec
its also in frameworks btw
The thing is ec is abstract away it shouldn't need special drivers lol
But how does Windows deal with it
why would they support this?
it would imply writing aml
and they are vendoring their own kernels anyway so might as well
Special chipset driver
I've had someone boot uacpi on a Chromebook so yeah
oh cool
It does have aml albeit tiny
i think i sent you my aml dump
Compared to other hw
from my chromebook?
which is dead now, rip charging controller
Oof
maybe i should add uacpi support to my bootloader/firmware thing
you def need userspace /s
userspace?
because it's cursed
Absolutely (not biased opinion in any way
)
uacpi cant make new acpi tables though
so idk maybe not
Aml ones u just propagate as is, the rest is just hardcoded struct + data so
well no i cant
i need to build them dynamically
thats like the point
Like from fdt?
I thought u dropped that idea
But yeah if thats your only goal for acpi then yes, unless u want to use aml to discover available non pci devices in the bootloader directly
i still kinda want to
its on the list of things i may want to do at some point
That would be a truly unique thing
yes but it would involve dealing with aml shit
id probably have to write an aml compiler
DSL?
I can show u an example of how qemu does it if u want
Yeah
Official QEMU mirror. Please see https://www.qemu.org/contribute/ for how to submit changes to QEMU. Pull Requests are ignored. Please only use release tarballs from the QEMU website. - qemu/qemu
example for a TPM device
ah
ifctx = aml_if(aml_lgreater_equal(op, aml_int(0x100)));
ugly
you would produce ascii text then compile it?
actually ig i could abuse rust
of course not lol
rust macros could be abused to make a very powerful dsl here
true
@fiery turtle this u?
Wut
the osdev irc channel thinks this is your username
on the irc channel
Never used irc before
Is it active?
yea
How would it even know
i dont even know they kept hinting at that ๐ญ
they are weird
but its an active irc channel so
๐คทโโ๏ธ
Didnt understand any of that but w/e
w/e?
wwe?
john cena? did u say john cina infy
"whatever"
Well hopefully this will allow some pretty useful stuff to be sent back to uACPI
Thatโs the goal
This is the plan
Im not sure if Infy wants a vs solution sent back into a PR or something that remains to be figured out
Btw, what should interrupt handlers return on failure?
But uACPI will be able to be plugged into vista from reactos
Wait really? You can just port the reactos driver and it will work?
How do you have the school that late?
It's 2 pm
Yeah I mean if there's a way to build a driver somehow for regression testing id be interested to hear
I only have a small base for an EC driver
Basically nothing
I could ssh into my 0x
Pc
From school

If only I had that port forwarded
this is why you should use tailscale
Wait
I will compile a cross compiler
For x86 64 elf
Then compile obos with it
Termux can't run static executables, unfortunately
So that won't work
I'm eating, so you have time bruh
Do I have to use burst?
Managram does it, but since I'm running in userspace, I'm afraid this stuff could be preempted
(though I have priorities in scheduler, I don't want to use that)
hmm? sorry i didn't see this till now.
yes that's what im working on
And it would disengage
bruh
Does QEMU support EC?
I'm gonna try it on my laptop...
Looks like QEMU doesn't have it..?
@fiery turtle it's failing what am I doing wrong
But I did get an even pressing f keys...
Nice
Do u initialize EC before namespace_initialize?
omega bruh
What did you do ๐
Idk it doesn't boot
Hard power off
Ok it booted
Least broken ec driver
But it booted to Windows, turned off and then I had this
Basically installing ec handler must happen before namespace initialize
Basically you should early reg for your laptop
This error doesnt happen on Linux right? Idk what logic it uses to decide if you should or not
Your laptop is strange in that it doesnt give an ECDT but expects _REG to be called before _STA
I have a laptop which wants the opposite
I've never tried Linux on it
Which part of spec should I look at?
Look at how Linux decides when to install the handler I guess, but for your hw the managarm logic is wrong
None, its not specified there
I find linux source to be intimidating
#ifdef CONFIG_ACPI_EC
/*
* ACPI 2.0 requires the EC driver to be loaded and work before
* the EC device is found in the namespace (i.e. before acpi_initialize_objects()
* is called).
*
* This is accomplished by looking for the ECDT table, and getting
* the EC parameters out of that.
*/
status = acpi_ec_ecdt_probe();
/* Ignore result. Not having an ECDT is not fatal. */
#endif
```?
What's the website with linux source
drivers/acpi/bus.c:689
Bootlin
ret = acpi_ec_get_real_ecdt();
/* Try to make a fake ECDT */
if (ret && acpi_fake_ecdt_enabled) {
ret = acpi_ec_fake_ecdt();
}
```
I'm gonna try Linux
Yeah try it
I think it's a kernel option
But I would imagine someone using Linux on it
It's 1 year old laptop
Yeah
Yeah try and we'll try to decide from there
Its not a critical error or anything but still
But still I've gotten en event here
But power button didn't work
Dont see u running the query
Which query
Yup
I was kinda hoping it would work first try
I had to debug hangs as well, but it was a skill issue
When making the managarm ec driver
What's event 1 btw
Wth
I've basically copied managram and so it should be firing uacpi_kernel_schedule_work, which should be printing stuff without taking locks
Maybe I do have a deadlock in kernel after all..
I'm feeling dumb
There's nowhere to lock up between 2 printfs
Ok, something fishy is going on
(maybe I do need kernel panic to framebuffer after all)
serial 
No that's the only output I have from kernel
The issue is that I only have it in VMs and on couple of my PCs
And not on laptops
So sometimes I don't know if the kernel has panicked
Ok anyways I've been looking at the wrong part of code again 
Somehow the kernel never crashes
dang updating to the new recursive-locks version broke my kernel
Btw can EC be tested in VMs?
I still have time to make a more stable ec driver than you
say hello from me too to the pthreads
Pastebin.com is the number one paste tool since 2002. Pastebin is a website where you can store text online for a set period of time.
Phoenix bios?????
I thought they were out of business
What is [ 1.057783] Unstable clock detected, switching default tracing clock to "global"?
So TSC is broken on this laptop?
Lol
And it's using PIT for calibration
What snd_hda_intel 0000:c3:00.1: enabling device (0000 -> 0002)
This is AMD only laptop
Will uhda work on it?
[ 12.512529] snd_hda_intel 0000:c3:00.1: enabling device (0000 -> 0002)
[ 12.512944] snd_hda_intel 0000:c3:00.1: Handle vga_switcheroo audio client
[ 12.513058] snd_hda_intel 0000:c3:00.6: enabling device (0000 -> 0002)
[ 12.531287] amd_atl: AMD Address Translation Library initialized
[ 12.531624] intel_rapl_common: Found RAPL domain package
[ 12.531627] intel_rapl_common: Found RAPL domain core
[ 12.532028] snd_hda_intel 0000:c3:00.1: bound 0000:c3:00.0 (ops amdgpu_dm_audio_component_bind_ops [amdgpu])
[ 12.534327] input: HD-Audio Generic HDMI/DP,pcm=3 as /devices/pci0000:00/0000:00:08.1/0000:c3:00.1/sound/card0/input16
[ 12.534388] input: HD-Audio Generic HDMI/DP,pcm=7 as /devices/pci0000:00/0000:00:08.1/0000:c3:00.1/sound/card0/input17
[ 12.534454] input: HD-Audio Generic HDMI/DP,pcm=8 as /devices/pci0000:00/0000:00:08.1/0000:c3:00.1/sound/card0/input18
unfortunately no
under the LPC0 device
oh thats why the new recursive mutex thing broke my kernel, my get thread id crashes before my processor-local control blocks get initialized which i dont do until after i init uacpi so i can have the MADT
does early table access use mutexes?
(by crashes i mean that before processor-local control blocks are initialized the gs-base is 0 and so the gs-relative pointer page faults accessing virt address 0 when i try to check the current thread id)
definitely not the recursive ones
or actually no it doesnt use any
it doesnt use heap whatsoever
cool, then i can use early table access to ensure i dont need thread ids until after i get processor local stuff figured out
will need to figure out memory management for the early table access buffer (which i assume can be freed after the normal initialize) but ill need memory management anyway by that point for the map/unmap so thats fine
yeah
linux just puts it in an __init section
which is automatically freed after init
ill have full kernel-mode alloc ready to use well before that point most likely anyway
ah ok then u can just kmalloc(4096)
then free after uacpi_initialize
there are kernel initialization hooks u may reuse for this
also a question for those who know windows synchronization stuff, is the uacpi_kernel_xxx_event stuff expected to be closer to a KSEMAPHORE or to a SynchronizationEvent?
cool
@fiery turtle could TSC be broken?
only one way to find out :p
maybe
I think Linux has gotten the same frequency
I should make a test image but I still haven't figured out the issue with astral and on my own kernel switching the output would be painful because the xhci is broken (though ig I could add a kernel param but that's not ideal)
i remember getting the same message on my laptop and it went away after a bios update
I think I have the latest bios though
I don't have a shell, but I guess I could try and port it...
shouldn't be that hard
@fiery turtle does ec init have to happen before namespace load or init?
it cant happen before load
either before init or after
depending on something
idk what specifically
does the spec know?
no
only linux knows
managarm does if ECDT exists then after load, otherwise after init
linux knows all
who is this linux person
linux torvald
Wait can I unconditionally call it after init?
that will break some init code like your battery
Like I'm iterating through it, where in it does it request early init?
linux sebastian
where is linux' ec driver
found it
Elixir Cross Referencer - source code of Linux v6.12.5: drivers/acpi/ec.c
Elixir Cross Referencer - source code of Linux v6.12.5: drivers/acpi/ec.c
(for some reason, pinning threads to other CPUs seems to be broken...)
Wait, no
Do GPE handlers want CPU 0?
bootstrap CPU that is
I believe so
what linux does:
- before namespace load, it probes the ecdt table, if it exists
- if that exists, all is fine
- otherwise, sometime after namespace init, it probes the acpi namespace for an EC
I did that and somehow it doesn't work on my laptop
well does linux work?
It looks like it
Elixir Cross Referencer - source code of Linux v6.12.5: drivers/acpi/bus.c
linux init sequence there
check journalctl or smth
or dmesh
*dmesg
to make sure nothing errored out
.
yup
it installs it to root if there's an ECDT
Elixir Cross Referencer - source code of Linux v6.12.5: drivers/acpi/ec.c
ACPI BIOS Error (bug): Failure creating named object [\_SB.MHSP], AE_ALREADY_EXISTS (20240322/dswload2-326)
What is this ACPI: [Firmware Bug]: BIOS _OSI(Linux) query ignored?
Could I need to be calling initialization code before finalize_gpe_initialization?
This also doesn't seem to be mentioning it anywhere
This is full dmesg
If I'm not missing anything
the person porting uacpi to reactos literally works there lol
[ 0.249958] ACPI: EC: EC started
[ 0.249959] ACPI: EC: interrupt blocked
[ 0.587395] ACPI: EC: EC_CMD/EC_SC=0x66, EC_DATA=0x62
[ 0.587399] ACPI: \_SB_.PCI0.LPC0.EC0_: Boot DSDT EC used to handle transactions
Elixir Cross Referencer - source code of Linux v6.12.5: drivers/acpi/bus.c
this call here
just means it was found in the AML namespace
so yeah in your case linux also calls _STA and _INI before
but i guess maybe they initialize locals to 0 by default and no Uninitialized
anyway that shouldnt matter for now
its not that big of an issue
thats your driver's skill issue
(maybe that is the reason)
its unrelated to this
That's my kernel's skill issue because why doesn't it work
I run uacpi_kernel_schedule_work
And it creates a thread, which pins itself to bootstrap CPU
And after that syscall, it disappears
Looking at printfs
Method (_Q32, 0, NotSerialized) // _Qxx: EC Query, xx=0x00-0xFF
{
P80H = 0x32
Notify (PWRB, 0x80) // Status Change
}
Or the kernel hangs
From EC?
yes
Bruh
Anyway
I'll fix bogus reading
I need to know what's going on with that thread
Maybe the kernel is panicking
How do you know what it does?
I think I'll add IPI panick so all the cores stop and at least I see that it's stuck 
Or I could test it in VM
Anyway, I think this is irrelevant to uACPI
one sec
(I urgently need a keyboard driver)
#1217009725711847465 message
lol
Please give me your submissions so I can record them, like project link: x ops/s
@fiery turtle I think I found a bug in managarm's ec code
https://github.com/managarm/managarm/blob/cdc7ca0c631b222502a44ac151f43cfe66178bcd/kernel/thor/system/acpi/ec.cpp#L302
_GPE can resolve to a package
but you only evaluate it as an integer
or they do
idk who wrote that driver
can it?
in practice it doesn't
better safe than sorry
Ok I'm able to trigger it in a vm
ah, GPE block devices were never added
they dont exist and arent supported
ye
my ec driver is nearly complete
I just need
to implement initializing it from the acpi namespace
my pc does indeed have an ec
wut
why is there no _GPE
only two mentions of _GPE in the entire dsdt
so I doubt it
both of which in the namespace root
first is a Scope(_GPE) in the root
and the 2nd is Scope(\_GPE)
or smth
the other way around
do u have any _QXX methods?
nope
so what's really the point of it now then?
guess so
I wonder what would happen if I wrote random shit to it
what could possibly go wrong
https://github.com/ilobilo/ilobilix 
it's still very wip though, not even on the master branch
well pmos tried and it couldnt boot after a reboot soo
thanks, recorded
yeah just a stub ig
man now I'm half tempted to revive techflash-os just so that I can compete on the leaderboard 
any EmbeddedControl opregions?
This code is two years old
nope