#uACPI - a portable and easy-to-integrate ACPI implementation
1 messages ยท Page 34 of 1
What
why would you do that when you need events anyway
fair
yes, until the firmware signals an interrupt
when you undeadlock yourself
is it?
Deadlocking as a feature is very cursed
its not deadlocking, though
you are just (mis)using the mutex as a different kind of concurrency primitive
Yes but as far as the kernel can see, its the same thread doing two acquires of a non recursive mutex
yeah because you transferred the first acquisition to a different thread
Anyway yeah that could work (although I kinda hate it), but aml needs event objects anyway so I just conveniently reused the api
fair enough
Such big brain idea I didnt get it at first
yeah you are not embodying the firmware dev energy infy
Some kernels rely on mutexes being released in the same thread as they were acquired too
uacpi's api contract doesn't mandate that though
although it very much should tbh
Yeah
is there anything that needs to be done to "enter ACPI mode"
or is initialize/load_namespace enough?
and then you just call the API on demand?
uacpi already does that in uacpi_initialize
does it do it even if your things to install irq handlers are stubs? :^)
it doesn't require irqs
How would it know 
If they do then it just aborts init entirely
Because its kinda unsafe to use acpi mode and not handle scis
Just lie to it and say OK
Then yeah everything will work
Ironclad doesn't have a way to install irqs or just to-do for now?
can i use uacpi only to access the tables? or do i have to implement all helpers just for this purpose?
i guess it's a to-do
Yeah ofc
Early table access mode only needs map and unmap
there's early table access which only uses map and log, and iirc there's a table only #define, though idk if that's a wip or not
The bare bones only mode is a planned feature yeah
I want to access tables from eir (Managarm's prekernel) to know the number of CPUs before the kernel starts
for now I guess just use early table access without doing the full init and --gc-sections will take care of dce
and in the future switch to bare bones mode
but honestly if you're just accessing tables without doing anything else I'd just use a custom ACPI impl, table access is like 150 loc
Yeah early table access will work just fine in that case
If you do what monkuous told you that will strip all unused code too
is there some #define or similar to compile out the other OS APIs or do I have to rely on --gc-sections?

yeah it turns out to be a relatively demanded feature, for e.g. microkernels with acpi in userspace, but still tables in kernel, or reactos where they need multiple acpi implementations, one core and one in acpi.sys etc
so its definitely higher prio
although after 1.0
yea understandable ๐ --gc-sections is probably fine for now
yeah it should be able to strip out most code i think
just build with lto and -fvisibility=hidden 
When do you plan on releasing 1.0?
this week
Neat
Neato
why am i looking at this and just thinking ok i think i can automatically generate these with zig comptime lmao
im pretty sure thats possible but i cant be bothered to try it until the PR is merged
damn
correction, its not a think i know i can
idk if its cleaner or messier than what ive got now on the old bit_width api but it will work
oh i almost forgot, hows your zig journey infy? 
down the procrastination pipeline next to my future kernel 
damn that uacpi 1.0 thing really set things back
lol
nah i think its cs2 and minecraft that did 
and work
ive been looking at some zig streams tho
hmm i should write some of my userland in zig (when i have a userland
but I'm happy with rust in my kernel
yeah thats what i wanted to do as well
try doing some zig programming in userland
i want to have my native and flagship os APIs in rust first and then maybe C++, go, zig idk whatever i touch
go is pretty nice also
i wouldn't use it in a kernel :3
but it was fun when I used it for like a 2k LOC project
but I already forgot how to write go
I just use pthread_cond and pthread_mutex...
im not sure how that would work, since its garbage collected
reminds me that i want to restructure how my wait code works since its a bit of a mess rn and i dont entirely trust it
GC in kernel?
letsgo
Isn't the whole point of a microkernel is that you can use it in userspace and not give a shit about GC/runtime?
like for device drivers
I think its concurrency model should be really nice for a lot of things
well, C++ and Rust now also have async
but it requires explicit scheduling activations
C++ async requires tons of allocations
or whatever its called
not like Go doesn't
a rust-style system requires function coloring
huh
since each function doesnt cause a gc alloc
the stack is just reallocated when it gets filled up
please do not think about how that works

rust async doesnt require as many sometimes usually but it has horrible degenerate cases
i.e. any recursion
that's a problem of all stackless systems
but C++ supposedly also optimizes a lot of allocations away
C++ and rust require the same number of allocations, more or less
C++ requires strictly more
because rust can coalesce them in many cases
also its explicit in rust which is cool
you can also overload operator new in C++
rust requires the absolute minimum allocations required for a stackless system
maybe some future C++ will add non-erased coroutine types
that would be cool but im not holding my breath
stackful systems are better anyway imo
but anyway, this is a non-issue. in practice both C++ and Rust use roughly the same number of allocations
anyway, C coroutines are the most fun 
it is true that Rust doesn't do type erasure
does C++ coalesce them?
*implicit type erasure
the C++ compiler is allowed to coalesce them, yes
ah cool
in C++ it's an optimization while in Rust it's a language feature
but in reality, the case that C++ cannot optimize is exactly the case where Rust's model doesn't help, namely when you do a virtual call
but yeah C++ requires at least one allocation more in every case
C++ cannot optimize cross-TU too?
LTO :)
since the scheduler allocation must be separate from the coroutine state
apart from being a layering violation
for example when you put a callback into a "wake me up when X happens" data structure
true
this requires an allocation both in Rust and in C++
yeye
it does
this is why stackful systems are better
they have one critical advantage though
why
they are way way way easier to implement
or rather, they require some a priori knowledge about how often an operation will be called etc
in rust, it's required due to aliasing rules
and way way easier to work with
so yeah
but in c++ you can also put that in coroutine state
they also avoid function coloring
i think that the way forward is very much stackful coros fwiw
not really, you still need to know whether a function blocks a green thread or an OS level thread
no go function can block an os thread
only c functions can
and those are run on a threadpool

and yeah its a bad solution for performance
but if you are writing pure go, it is acceptable
how portable is go to new OSes? 
I've ported libgo
depthos has it?
i think
Kinda
i think its pretty good
It works half the time
you have the bad go compiler tho
not the good one
(the good one == the maximally nih one)
I haven't found how to port the good one
they have windows, a bunch of unixes, plan 9
you add your os to the list
you compile a hello world for it
then you fix every error that comes up until its working

but there are no instricions (or I didn't search well enough)
to know which list to put it in
but I didn't know about that
Like I'm considering using Go for drivers, but I wasn't certain how that would work with blocking C syscalls
the answer is that it would work poorly, and you should write nonblocking go assembly wrappers for them anyway
the solution to function coloring is to color them all the same colour
in a stackless system, that is another way of saying is "kill performance"
i was trying to make a joke dw
how would that work considering that go has no inline asm (?)
im pretty sure you can link against manually built objects
so just use nasm/gcc to build separate assembly source files
not inline asm
eeeh i dont think that works, or works well at least
they have external out-of-line asm support
it works as well as their shitty assembly thing
largest uACPI AML test case with 400 loc of ASL lol
it tests basically every single esoteric opregion type
38 commits
With this, I think the 1.0 PR is done, now it's review and testing time


does this change any of the kernel API beyond the portio stuff?
compared to like, anytime recently i guess
Time for win11 + clang to break any new internal macro 
I'll be away from osdev during the weekend. Will the 1.0PR be done before I'm back?
its basically done so yes
will do


















lessgo

you gotta do like a countdown before you merge it into main
like a specific time
2025-01-25T20:00:00
or something
(completely random example time here, nothing to think about)

@fiery turtle
/home/oberrow/Code/obos-uacpi/dependencies/uACPI/source/registers.c:156:13: error: implicit declaration of function 'uacpi_atomic_load8' [-Wimplicit-function-declaration]
156 | state = uacpi_atomic_load8(&mapping->states[0]);
my builds are also werror
I'm on gcc 14.2.0
do u have a custom arch header?
does it have atomic load 8?
uh no
ok I think I need to:
#include <uacpi/platform/atomic.h>
i think we hit this same issue before
it was due to some header that leaks into other but not in your build
(laptops' chargers have been found)
time to painfully separate the PCI and port io kernel api
into the per-byte functions
lol
damn
i've just pushed an update, pls pull
I should take the time to learn some other language like zig tbh
it seems pretty cool
ikr
โฏ cloc --vcs=git .
145 text files.
145 unique files.
69 files ignored.
github.com/AlDanial/cloc v 1.90 T=2.69 s (29.0 files/s, 13559.0 lines/s)
-------------------------------------------------------------------------------
Language files blank comment code
-------------------------------------------------------------------------------
C 19 3898 928 17830
C/C++ Header 46 1111 1566 5656
C++ 4 502 516 2972
Python 3 228 40 629
Markdown 1 74 0 233
CMake 3 28 14 132
YAML 1 10 5 57
Meson 1 2 0 23
-------------------------------------------------------------------------------
SUM: 78 5853 3069 27532
-------------------------------------------------------------------------------
bruh almost 30k ๐
bruh
wdym bruh, its literally a fix for your compile error lmfao
did u think i was gonna put a commit on top
i can fixup changes into existing commits
Signed-off-by: Daniil Tatianin [email protected]
63ab369748db5764b59a728f54da0d7e5390f407 is the latest
oberrow
u know how u can rewrite git history?
i can go back to the exact commit that broke the compilation and make a fix in it
without introducing an extra commit
o
this is what i did
that is evil 
if this was master, yes
still evil, just less so.
its literally
git add -p
git commit -m "fixup! <commit-that-broke-shit>"
git rebase -i HEAD~N --autosquash
git push -f
Rebase'd
I couldn't be bothered to actually split the functions
amateur git history rewriting tbh. i once rewrote all of history to change one committer's name in every commit of every branch going back to the beginning retroactively
which is why I will just make it call into the function
that has the byte width passed
just make it a macro
macro function template
bah
zig is nice, lets me not rewrite the functions and just use a comptime loop to do generic instantiation of all them and export them
kinda like the macro idea tbh
haven't looked in nyaux code
so I'm fine
this is what i did in my test-runner.cpp
#define UACPI_IO_READ(bits) \
uacpi_status uacpi_kernel_io_read##bits( \
uacpi_handle handle, uacpi_size offset, uacpi_u##bits *out_value \
) \
{ \
auto addr = (uacpi_io_addr)handle + offset; \
\
if (io_space && addr <= UINT16_MAX) { \
memcpy(out_value, &io_space[addr], bits / 8); \
} else { \
*out_value = (uacpi_u##bits)0xFFFFFFFFFFFFFFFF; \
} \
\
return UACPI_STATUS_OK; \
}
#define UACPI_IO_WRITE(bits) \
uacpi_status uacpi_kernel_io_write##bits( \
uacpi_handle handle, uacpi_size offset, uacpi_u##bits in_value \
) \
{ \
auto addr = (uacpi_io_addr)handle + offset; \
\
if (io_space && addr <= UINT16_MAX) \
memcpy(&io_space[addr], &in_value, bits / 8); \
\
return UACPI_STATUS_OK; \
}
nyaux code jumpscare
nyaux code jumpscare
xdnbvdsjkfW
the code it generates is way bigger than i expected for the io ones but turns out thats because im building releasesafe so theres a bunch of safety checks branching to panic still in there
what sort of checks are there to do?
who wants my 3.1 volt circle battery that i stole from my old remote
integer overflow turning base + offset into a u16 port
just use an overflowing add or something
go update uacpi in nyaux NOW ๐ก
oh ok 
yea
finally built!
@north holly btw your gas stuff for EC can now be premapped
i could use truncate instead to avoid the checks but that generates extra code on no-safety-checks modes whereas the intcast just gets elided
makes sense
shutdown/reset/suspend etc
yeye
and EC stuff
i cant actually test this still since i havent finished my new page allocator yet and therefore have no allocaor lmao
obos and pmos are probably the largest uacpi api users so its fine if they both test
wtf even is this?? store immediate 176 into rdx and jump (??) to memcpy.
like that would give me enough confidence
im pretty sure this new per-size functions thing actually reduces line count for me btw, since i dont need to repeat the switch on each function and can just generic instantiate them instead
testing suspend
[ LOG ] oboskrnl: Suspend requested
[ WARN ] Note: Framebuffer might die
[ LOG ] oboskrnl: Woke up from suspend.```
wooo
lesgo



shutdown works
try reset too
based
blows up on the real hw
Epic
Who needs testing anyway 
- famous last words of @kind mantle
OBOS_Suspend();
OBOS_Shutdown();```
my real hardware test case will be this
just waiting for the 'success' message. I'm ready with lots of 

in the clipboard
News headline next day: @kind mantle found assasinated
looks like this shit is finally going to be removed soon
bruh
*r8169 driver
what happens?
Invalid value load
r8168 is a variant of the r8169 so not too far off 
At line 277 of device.c
Ye
btw did u figure out why 8169 was breaking on wake
I'm sure that bug is fixed in the network stack
It wasn't
It was a bug with the transmit code
what was it?
I forgor
yea, there are lots of realtek cards that use an r8169-like interface. iirc I have RTL8125A or smth on my desktop. (@north holly maybe I can setup some cursed passthrough stuff to help you debug your r8169.)
I have r8169 in my laptop
but it would be interesting to see if it even works on other laptops
are there any quirks for specific r8169 cards that one needs to be aware of when writing an r8169 driver?
/cards
idk I'm not linux
it's not a laptop.
yeah
yea lol
I meant NIC
btw never be brain damaged and forget to set the END_OF_RING bit on the last descriptor
of your Rx/Tx rings
otherwise the r8169 kind of just dies
I will study the available documentation very carefully (and maybe first do virtio) before trying to implement a r8169 driver.
anyways that is far into the future
r8169 is actually real easy*
*my driver only works on one piece of hardware that I know of
... still waiting for this
rebooting now
are u going to test multiple pcs?
I'll test as much as possible
nice
this reminds me i should update managarm's and proxima's score on the lb before merge
there's a whole bunch of different mac versions that require different behavior in places afaik
and the "documentation" for that is Linux?
Uh pretty much
most of the driver is the same, afaics it's just around init mostly
is that the same driver that needs an array of proprietary random register -> value pairs that u must write for the nic to work
No
no that was some wifi nic
also a realtek one i think
iirc rtl has that
God damn it
maybe
Nullptr access
i think it was in the driver for the wifi nic in my laptop?
Brb
In obos code
nah some serenity os driver has it
they definitely dont have wifi
It's serenity
not another obos regression โ ๏ธ
For all we know the registers are well defined
I swear this booted 1 hour ago
When I merged the RTC code
Magically elves in my laptop
yeah I'm thinking it is probably possible to keep a table associating vendor/device pairs with a 'quirk flags'/bitmask
like R8169_QUIRK_DO_X_THING_DURING_INIT
well for the mac revision you need to figure that out based on device regs, not pci vid:pid
sure
what the actual
they do also have arrays of reg -> value in the driver
wtf is the serenity code style btw
one line: ```c
auto region = MM.allocate_contiguous_kernel_region(Memory::page_round_up(RX_BUFFER_SIZE).release_value_but_fixme_should_propagate_errors(), "RTL8168 RX buffer"sv, Memory::Region::Access::ReadWrite).release_value();
Wtf
probably awesomekling taking inspiration from the coding style of some GUI toolkit or browser

btw hasn't ak been in this discord?
dont think so and hes not doing serenity anymore
i mean please put in a line break this single line is 215 characters long
yeah
yeah afaik he's only doing ladybird now
he resigned so ye
personally I steal a page from Linux's book and have 80 char width lines as a guideline, with exceptions for printk and where else reasonable.
same
not documented anywhere. it's just something I do automatically nowadays lol. like a sense for when a line of code is more than 80 characters
I should get uACPI ported to my kernel.
then I can finally call myself a 'real' kernel 
if u do it fast enough i can put u on the leaderboard before 1.0 merge
sorry, no can do. (unless you delay 1.0 by like four days)
I will be busy with a local competitive programming competition this weekend (lots of fun activities + competition sunday morning), so not much time for osdev
good luck!
actually maybe tomorrow after school, I might be able to speedrun a uACPI port by stubbing IRQ handling etc
yeah u can port it in like a few hours
i speedran astral port in 2 hours knowing nothing about the code base
dw i wont lol
only wait for @north holly to confirm that it works on real hardware
by just stubbing the IRQ stuff (I don't do IOAPIC yet lol, as there are no device drivers that use it) and replacing my own early ACPI table code with uACPI's early table support, I can probably get it done in like 15min lol (but it won't work, other than initializing the namespace lol)
He joined once for likeโฆa few days. I think it was 4-5 years ago.
Thats enough to get a score tbh
Lesgo
still waiting for this btw
I think this was paused because of obos segfault
Lol
that's why you gotta do a countdown
(except there's a risk I'm at this)
now I'm scared I'll get like 10k ops/s and be sad lol
Nah even nyaux gets a million
but Linux mmap(MAP_POPULATE) for like one gigabyte is like 20ms and my kernel is very close to that
so it should be good
How fast is your slab allocator
Monkuous gets 150ns/allocation
True
damn good luck
are you like high school level
like IOI quals
The main overhead to my generic kmalloc which takes in a size (slab_alloc takes in a preinitialized struct slab) is probably finding the correct struct slab to call slab_alloc with
or rather the qualifier to the qualifier to the qualifier
nah this is PO (progolymp.se), Swedish thing
Just Bret Hart doing some code review.
well yea but does it lead to IOI eventually
every country has some kind of organization
here you do CCC (canadian computing contest) -> CCO (... olympiad) -> IOI
but I don't belong in IOI lol. so many cursed things like segtrees I don't know about
yea most are math cracks that do this kind of stuff 24/7
I doubt there's that much usefulness to it though
I mean it's good problem solving
although I am kind of a math crack (except I only do math 23/7)
but yeah about this, this isnt just about allocation speed too, there's cache to account for and all that kinda stuff
It suspended...
Yeah
Letsgo
As the test does

Iโm just eager to have a good solution for ACPI now
I will be testing EC events
@north holly other subjects too?
Now
I will test my main pc
discord skill issue lol. cannot paste that many 
Oh yeah
my allocator is op
you are not ready.
(I'm totally overhyping it)
I gotta solve this tbh
(but its better than 99% of allocators here im 60% sure)
Is it really that good
Probably true
What algo does it utilize
I will probably implement some kind of per-CPU object caching in kmalloc()
it's roughly roughly similar to solaris's modern slab allocator
it's like 75% of it
won't do it in slab for the time being, as it would require dynamic cpulocal variable allocation, which is annoyingโข๏ธ
(dynamic cpulocal allocation can be solved by just reserving some amount of memory lol. but I'm lazy)
the per-cpu caches are stored in the kmem_cache structs
the way I plan on doing it does
in the slab "zones" (they're called caches because object caching)
and that I just use a switch statement
I have a few power-of-two slabs preallocated
and I just switch on the size in kmalloc
or rather an if statement
it's literally just a struct pcpu_slab_list_whatever [NUM_CPUS]; indexed by this_cpu_id()?
tbh I should do some cursed __builtin_constant_p stuff to optimise slab selection
:P
and that's per cache
cache as in slab zone again
yeah
(I know it's confusing)
not really tbh. it's just that I use slightly different terminology
Could have sworn I changed that
what solaris does and what I dont do is dynamic magazine sizes (per-cpu caches are refilled on a magazine-basis, like a gun)
so the allocator self-adapts itself during runtime to have optimal magazine size
by mesuring lock contention and stuff
meanwhile i just have fixed values but that's still better than most hobby OSs
on terminology: for me, a struct slab * is an opaque handle passed to the slab allocator to allocate memory of some fixed size
basically it is used instead of size in kmalloc
similar to linux kmem_cache I guess
the real terminology is:
- a cache works in slabs and has also a freelist for cached constructed objects
- slabs are allocated when a cache needs refilling, they contain memory for the objects
it's not linux stuff, it's solaris stuff
linux stole it from there
Do u have struct page?
I might 'dial a friend' -- get some help by my constand factor optimisation enjoyer friends from the competitive programming circle with optimising my kernel lol
yes. but I call it struct pfn_entry for some reason lol
windows naming conventions moment
anything for that #1 spot
pfn is what windows calls it
I don't currently, but yea I will call it pfn too or something
nah... that would be PPFNENTRY (not a typo)
Slab lookup might be slower without one
i call mine pfm because page frame number is a bad name for a struct lol
@fiery turtle EC worked
how lol
PMMPFN is the type
*works

the P might be for private?

no, pointer
Or maybe not idk
the first P is for pointer
as in PCSTR and friends
im sleepyyy
Sleep
everything is defined as ```
typedef struct _THING {
...
} THING, *PTHING
so get some sleep.
in windows
nah the slab is on another layer from raw pages
but yeah struct page = MMPFN basically
im so happy cause nyaux works now
i should sleep
but before i sleep
i jsut wanna say
Yes sleep
yeah. well I've heard nowadays this is only the user-visible API. internally it is saner
wux is the goat
that i wouldnt know
the reason why I dont have a pfndb yet is because I was too lazy to figure out how to make it contiguous
bro found out the bug i was trying to debug for weeks in a few hours
anyways
sleepy time nightnight
i think funny hyena man or the other will wrote about it sometime quite recently
wdym contiguous? what reactos (and i in imaginarium) use is to have a bitmap where if the bit is set the PFN is valid and you just map whichever PFNdb regions have normally-usable pages in them
so it can be accessed as an array
yeah what i do works for that
a virtually-contiguous pfndb is quite nice
you have kind of a chicken-egg problem where you need pages to map memory but to get the pages you need the pfndb
so you need to setup a bump allocator in the memory map
that's what initmem is for 
yeah
(initmem is an overcomplicated initmeme in my kernel)
the bump-allocator-in-memory-map is what i do with limine hhdm keeping it mapped
and then once page tables are up i swap to that from the hhdm
rebooting into obos on the other test subject rn
what is that
wdym?
where im at rn is i have it all initialized, both pfmdb (i use m for metadata instead of n for number) and tables, and then just dont have any way to allocate virtual memory
oberrow@AcerAIO:~/Code/obos/scripts$ uptime
19:15:01 up 9 days, 1:02, 2 users, load average: 6.25, 6.12, 5.99
wdym bitmap? so code can test has_pfndb_entry(physical address)? isn't that implied by how it got physical address?
uptime before reboot 
i pick the memory map entry with the most usable mem and just increment the base and decrement size when i need a new phys page
mmio wouldnt have an entry but might be mapped
yea but what's the hhdm thing
would mmio even have a pfn entry
why would you search for it
for refcounting reasons when temp-mapping normal pages is what i use it for
hhdm is each usable phys addr is accessible at phys addr + constant offset
After telling me I have no EC
yeah I know that
shameless self plug: https://github.com/dbstream/davix/blob/main/mm/initmem.c iirc (pls no advertising ban. he clearly asked for it)
(I may have gotten the link wrong as I typed it manually on my phone)
" what i do with limine hhdm keeping it mapped.

so if i have the page number i allocated from the memmap i can just access it from that
I have shilled obos way too many times
until i get my own page tables created
yes... but why are you using a bump allocator for that
And haven't gotten an advertisement ban
I think you may have worded it weirdly and that confuses me
idk if bump is the right word tbh, but its just a quick and easy way to get a known-free physical page before i have the pfmdb set up
yeah I think I get what you're saying now
the pfmdb is the last part of my mm bootstrapping
that was also what I was going to do
it's gonna be my first
I did get the link incorrect lol. https://github.com/dbstream/davix/blob/master/mm/initmem.c
probably
so you free it all back on exit?
to the normal page allocator, yes.
initmem doesn't use the pfndb
initmem additionally doesn't use any memory it hasn't been told by arch is mapped
yea but the pfndb uses initmem to allocate the page tables
so freeing those pages would overwrite the pagetables
it iterates over the free regions
basically there are two arrays:
- memory ranges.
- reserved ranges.
OBOS_InitWakeGPEs();
OBOS_ECSetGPEs();
uacpi_install_notify_handler(uacpi_namespace_root(), default_notify, nullptr);
uacpi_finalize_gpe_initialization();```
hmm so it hangs somewhere here
it iterates over memory ranges and reserved ranges simultaneously (that was hard to implement lol) and only frees that which is not reserved
initmem_alloc_* functions mark the allocated memory range as reserved
- Iterate over memory regions which are free (i.e. regions in initmem_usable
- that are not INITMEM_DONT_ALLOCATE_MASK and which don't overlap with
- initmem_reserved). Returns true for each new entry, false when finished.
ah nvm
so you only free the free pages
that makes sense lol
that is, the memory that wasnt used to allocate the db and stuff
anyway I'm quite happy with initmem. It basically multiplexes as my kernel's early internal representation of the physical memory map and a very flexible early memory allocator.
if you have other inquiries about the davix (trademark pending) kernel, please lift them in the #1326937732122935379 thread so it doesn't appear dead

Lol
Uacpi debug logs enabled
Ye
it's in OBOS_InitWakeGPEs
as this machine has no EC
so OBOS_ECSetGPEs can't really hang if it does nothing
the next two calls are from uacpi
What does it do
and uacpi is infalliable
finds GPEs that are wake-capable
then registers them for wake
Not another regression 
but only calls uacpi_setup_gpe_for_wake
Can u add prints there too
This code wasn't touched at all by this pr btw
yeah
Is that the one that's fixed by a reboot
never don't avoid not testing your code on twenty different machines after every single nontrivial commit (or series of commits)
never don't avoid
Ig you could add more prints to see where it hangs exactly
yeah doing that rn
Nice
it probably hangs in OBOS_DeviceGetDStateForWake
which is called by OBOS_DeviceMakeWakeCapable
which is called by OBOS_InitWakeGPEs
eventually
most of this is simple code
the only problem is, what is trivial and what is non-trivial?
which only calls into uacpi stuff
this sentence is making me have a brain fart
oh I can give you some long complicated sentences
maybe an English equivalent of the most vexxing parse
although it is hard to type on a phone without making lots of spelling mistakes lol
mmm the last line the kernel is seen at is line 301 of power/device.c
after evaluating an integer in _PRW
char path_d[5] = { '_', 'S', '0' + state, 'D', '\0' };
char path_w[5] = { '_', 'S', '0' + state, 'W', '\0' };
uint64_t snd = eval_integer_node(dev, path_d);
uint64_t snw = eval_integer_node(dev, path_w);
d_state val = DSTATE_INVALID;
if (snd == UINT64_MAX && snw == UINT64_MAX)
{
if (status)
*status = OBOS_STATUS_SUCCESS;
return DSTATE_INVALID;
}
if ((snd != UINT64_MAX && snw != UINT64_MAX) && snw >= snd)
{
if (status)
*status = OBOS_STATUS_MISMATCH;
return DSTATE_INVALID;
}```
which means it either hangs here, or returns here
and hangs in the caller
static uint64_t eval_integer_node(uacpi_namespace_node* dev, const char* path)
{
if (!path)
return UINT64_MAX;
uint64_t integer = 0;
uacpi_status status = uacpi_eval_simple_integer(dev, path, &integer);
return status == UACPI_STATUS_NOT_FOUND ? UINT64_MAX : integer;
}```
that probably isn't it
which means it hangs in the caller 
What would that mean?
idk, that's the problem
when the caller encounters an error in OBOS_DeviceGetDStateForWake
it errors out
static uacpi_iteration_decision acpi_enumerate_callback(void *ctx, uacpi_namespace_node *node, uint32_t max_depth)
{
OBOS_UNUSED(max_depth);
obos_status status = OBOS_DeviceMakeWakeCapable(node, UACPI_SLEEP_STATE_S3, !!ctx);
if (obos_is_error(status))
{
if (status != OBOS_STATUS_WAKE_INCAPABLE)
OBOS_Warning("Could not make device wake capable. Status: %d. Continuing...\n", status);
return UACPI_ITERATION_DECISION_CONTINUE;
}
return UACPI_ITERATION_DECISION_CONTINUE;
}```
which means it hung somewhere after the call to OBOS_DeviceMakeWakeCapable
But it just continues
unless the function doesn't fail
Then it also continues
if the first if statement gets reached
if (snd == UINT64_MAX && snw == UINT64_MAX)
{
if (status)
*status = OBOS_STATUS_SUCCESS;
return DSTATE_INVALID;
}```
so here

uacpi_object* buf = {};
if (uacpi_unlikely_error(uacpi_eval_simple_package(dev, "_PRW", &buf)))
return OBOS_STATUS_INTERNAL_ERROR;
uacpi_object_array pkg = {};
uacpi_object_get_package(buf, &pkg);```
in which case
status = enable_wake_gpe(dev, &pkg);
if (obos_is_error(status))
{
// Back out of the unfinished operation.
//enable_pwr(dev, &pkg, false);
if (useDSW)
dsw(dev, false, state, DSTATE_0);
else
psw(dev, false);
OBOS_DeviceSetDState(dev, DSTATE_0, false);
return status;
}```
it does that
enable_wake_gpe just evaluates _PRW and enables that gpe
basically
Anyways would be nice if you figured it out whether its obos or uacpi bug doesnt matter
Im off to bed for now tho
it's probably obos bug if I've had it for so long
gn
yes.
ye
ok so enable_wake_gpe returns success
which means OBOS_DeviceMakeWakeCapable returns
static uacpi_iteration_decision acpi_enumerate_callback(void *ctx, uacpi_namespace_node *node, uint32_t max_depth)
{
OBOS_UNUSED(max_depth);
obos_status status = OBOS_DeviceMakeWakeCapable(node, UACPI_SLEEP_STATE_S3, !!ctx);
if (obos_is_error(status))
{
if (status != OBOS_STATUS_WAKE_INCAPABLE)
OBOS_Warning("Could not make device wake capable. Status: %d. Continuing...\n", status);
return UACPI_ITERATION_DECISION_CONTINUE;
}
return UACPI_ITERATION_DECISION_CONTINUE;
}```
into there
where it return UACPI_ITERATION_DECISION_CONTINUE;
this callback is for uacpi_namespace_for_each_child_simple
infy, I am afraid this might be a deadlock
added logs to my kernel api's mutexes
wait nvm
the function returns
where it mysteriously hangs in OBOS_ECSetGPEs
it is probably possible to instrument (parts of) your code with some gcc flag
void OBOS_ECSetGPEs()
{
if (ec_initialized)
uacpi_enable_gpe(ec_gpe_node, ec_gpe_idx);
}```
ec_initialized is false on this machine
uacpi_install_notify_handler(uacpi_namespace_root(), default_notify, nullptr);
uacpi_finalize_gpe_initialization();```
it then probably goes onto here
by this I mean inserting calls to some __instrument_enter (CALLER_IP); and __instrument_leave (CALLER_IP)'; to everything in specific source files
it might help finding the bug
or it might not
idk
it hangs in uacpi_finalize_gpe_initialization
it says it's acquiring a mutex
whether that ever succeeds... idk
printf before and after?
maybe it is something silly, like running out of stack space
obos' kernel stacks have a guard page
nice
now... do you handle the double-fault from not being able to call the page-fault handler??
yes
nice
F
unless I forgot to actually add the log
ah whoops
forgor to run dd
before ejecting the usb
would it be the easy 'bah! I forgot to release here!' kind of bug or the annoying 'wtf is happening' kind of bug?
probably, and hopefully the former
dude setup PXEBOOT
I haven't done it myself but supposedly it is very good
basically 'just compile and run!' but for real hardware
dude. instrument with GCC. then it is impossible to forget some printf statements
too much work
will pay off in the long run
bah
(except you gotta make sure you avoid infinite recursion in the instrument handlers)
The best time investment ever and it pretty simple to setup
But it can be a bit annoying if your router doesn't support it
was there any router level stuff that you had to do to get your "victim" machines to boot from your dev machine?
The one who tells the machine what it should boot is the dhcp server
Typically located in your router
sadge :-(
If you have a extra machine laying around you can make it the dhcp server
well that'd be the dev machine :p
As long as it's always on
but there is a way to tell the victim machines "hey! pxeboot from 192.168.1.xyz instead!", no?
The dhcp server does that
(by storing stuff eg. grub config on the victim machine, i.e. no dhcp server)
probably
well
it's not relevant until I want to test on real hardware anyways
and... I think I'd need another ethernet cable for that lol
since afaik PXE over wifi is not common
Iirc you can also connect them directly
like an ethernet cable directly between the two machines?
yeah.
but then I lose internet connectivity on my dev machine
thus higher latency between a successful test and flexing in this discord
the worst type of latency
eh, I could probably use wifi to the router to get internet access lol
I just haven't bothered
@fiery turtle I've gotten too caught up with AHCI and I'll test patches tomorrow...
btw there's plenty of precedents where people link their own code as an example of something they're talking about, imo its fine.
i'm just trolling lol. it's part of a deliberate strategy to get more eyes on the #1326937732122935379 thread 
Oh lol, I totally missed that one ๐ฌ
similarily misspelling it is a deliberate strategy so I get to post the link twice 
lol
Pls do!
@north holly did you figure it out?
Was able to track it down to finalize gpe
Before going to sleep
are u gonna continue now?
if you want i have a old dell machine where i can test uacpi on if you want, id just need an iso
how old are we talking
thats pretty new but u could test obos, im sure oberrow would appreciate it

also
lfg
i still want oberrow to figure out that obos bug
if its a uacpi bug we should fix it before 1.0
and also for mishakov to test pmos on his pcs
damn am i finally going to be able to work on other projects soon
cant believe it
yay
Does this have an EC?
idk
dmesg | grep EC
btw does your pci code check/handle looped cap lists?
๐
uh I don't think it does
I think i have a couple machines with some pentiums
does this pc have that?
yeah
goddamnit
that would be cool
(if u could run obos)
We'll see
not another obos hang
is pentium even x86-64?
yeah I didn't know cap lists could be looped
depends which pentium
I think this is a 64 bit pentium
if I compile obos as x86_64-v1
But id have to check when i get home
I could send that iso
Just DM a link to me or smth and ill try to remember
kk
uint64_t tmp = 0;
DrvS_ReadPCIRegister(dev->location, 0x34, 4, &tmp);
pci_capability* tail = nullptr;
+ uint8_t first_offset = tmp & 0xff;
- for (uint8_t offset = tmp & 0xff; offset; )
+ for (uint8_t offset = tmp & 0xff; offset && first_offset != offset; )
{
uint8_t next = 0;
uint8_t cap_id = 0;
this should be the solution
are you checking if it reaches the first one again?
iirc it only loops on a subset
best bet is using a bitmap
that's what I'm tryna do
of visited offsets
that would be too simple
damn you retarted bios devs
it goes like cap a, cap b, cap c, back to cap b
so are u supposed to just terminate if it goes back to b?
just break out of the for loop if you reach a cap that you already visited
theoretically that fixes the problem
uint8_t visited_offsets[256/8];
#define set_visited_offset(off) (visited_offsets[(off)/8] |= BIT((off)%8))
#define visited_offset(off) !!(visited_offsets[(off)/8] & BIT((off)%8))
for (uint8_t offset = tmp & 0xff; offset; )
{
uint8_t next = 0;
uint8_t cap_id = 0;
// works around certain PCs that have something like:
// a->b->c->b
if (visited_offset(offset))
break;
set_visited_offset(offset);```
ok ill try
static u8 __pci_find_next_cap_ttl(struct pci_bus *bus, unsigned int devfn,
u8 pos, int cap, int *ttl)
{
u8 id;
u16 ent;
pci_bus_read_config_byte(bus, devfn, pos, &pos);
while ((*ttl)--) {
if (pos < 0x40)
break;
pos &= ~3;
pci_bus_read_config_word(bus, devfn, pos, &ent);
id = ent & 0xff;
if (id == 0xff)
break;
if (id == cap)
return pos;
pos = (ent >> 8);
}
return 0;
}
static u8 __pci_find_next_cap(struct pci_bus *bus, unsigned int devfn,
u8 pos, int cap)
{
int ttl = PCI_FIND_CAP_TTL;
return __pci_find_next_cap_ttl(bus, devfn, pos, cap, &ttl);
}
u8 pci_find_next_capability(struct pci_dev *dev, u8 pos, int cap)
{
return __pci_find_next_cap(dev->bus, dev->devfn,
pos + PCI_CAP_LIST_NEXT, cap);
}
EXPORT_SYMBOL_GPL(pci_find_next_capability);
looks like linux just has a TTL
aka max number of loops
mb i need the elf file. Im pxe booting (and limine cfg if you have anything special in there)
obos uses hyper 
ok ill get a usb
so this is basically harder than it should be
wdym
add pxe support to it 
hyper has PXE support iirc
aka max iterations
nope
guess I didn't recall correctly
other than the memory overhead being bigger, this isn't too complicated
LErtheriogres
FINALLY
obos booted on osmeone ellse's hardware
that panic I expected
now test suspend and stuff 
this is 1.0 uacpi right?
then you wake it and it shuts down
Signed-off-by: Daniil Tatianin [email protected]
shutdown debugging
yeye
actually I think the iso I sent was using another copy of obos I had
using old uacpi
either way it should boot
When it starts a '_' appears in the middle of the screen if I then press any key I get
Is 765059be191db the right commit?
@fiery turtle we might have a uacpi regression here
using the old obos iso
with old uacpi
it doesn't hang
not even an old iso
which branch do I checkout?
only behind on the RTC code
address spaces support
but with the new uacpi code it does hang in uacpi_finalize_gpe_initialization
on both my pc and his PC
and it doesn't on my laptop
with the same uacpi version

