#uACPI - a portable and easy-to-integrate ACPI implementation
1 messages · Page 42 of 1
the string and memory functions you are fine just taking for granted
string not so much imo
gprbuild
i said good
exactly :^)
any non-trivial kernel compiled with clang or gcc will have memcpy and friends
Can you elaborate lol
having an override might make sense but memcpy as a default seems reasonable
any non trivial kernel compiled with anything, rust requires it, zig requires it, ada requires it
everything does
its fine for some things, but its not good in general
well anything with an LLVM or GCC backend that is
Requires aka might call for certain code patterns
its required runtime
actually no, it might call for any code pattern
Oh you mean non c stuff
aiming for the smallest possible number of kernel-provided hooks doesn't make a lot of sense
yeah there is no guarantee on what can cause it to be called; anything can cause it to be called
in practice it isn't going to get randomly called tho
But language lawyers win
this isn't even language lawyerism
i'm the first person to dislike that
this is pretty sensible reasoning
Backend laweyring 
it's a common "you are required to provide this, any input may generate a dependency on it"
like
bruv
I truly do mean it with please, go and find a kernel that could run uacpi and doesnt have memcpy
I legitimately do not think it exists
uacpi depends already on memcpy/cmp/move/set if the compiler decides so
depending on version, type, compiler options, target, etc
this code emits a memcpy at the frontend in clang: c #include <stdatomic.h> #include <stdint.h> typedef struct { int p; } lol; lol heh(_Atomic(lol)* p) { return atomic_load(p); }
(which gets eliminated by isel but thats besides the point, it could easily not)
Sure ill make it auto depend on those by default
I love you
🎉
sanity restored
The rest will be built-in by default
by means of:
#ifndef uacpi_memcpy
#ifndef memcpy
extern void *memcpy (void *, const void *, uacpi_size);
#endif
#define uacpi_memcpy memcpy
#endif
?
idc if you need a 2.0 to do this
Yup
because this stays compatible with current kernel usage, I think
what the heck
this is breaking but who cares
whats wrong ukraine flag ukraine flag ukraine flag ukraine flag
Probably just call to built-in on GCC
yeah, sure, it can be a builtin
brian hurt
#ifdef __GNUC (or whatever the macro is) ofc
wish he gets better
You didnt like the macro hell?
yea no
Can probably be simplified
I'm running some reinforcement learning thingy on my computer that trains the stupidest possible PPO implementation (because it was done by me) on crappybird, and its brian must hurt much, because this shit is not learning
great uacpi discussion 
the reward function or observation space are probably broken
also, RL is notorious for needing a lot of samples
I will add that for me i could leave the libc file out probably but I have to provide my own implementation for stdint.h for it to work in a zig environment
i like to use https://github.com/osdev0/freestnd-c-hdrs/
just add b.fmt("{s}/include", .{@tagName(arch)}) to include directories
mind you that there is also https://github.com/osdev0/freestnd-c-hdrs-0bsd which is the same but much smaller and probably still has everything you want
... so I spent hours trying to rig up some possibly broken headers for types and it turns out I didn't even need to dammit
oops 
lol
and it has a way more permissive license (basically public domain)
I just need whichever things are imported by uacpi types.h iirc
latter works
both work
the non 0bsd one is the headers from gcc, which is much more complete, massive, but also GPLv3 w/ Compiler RT exception license
you likely don't need those unless you also need the freestanding C++ headers from gcc or the extra fancy freestanding headers like those for avx or whatever (which tbh are mostly useless decor)
cool
no (well maybe a little), most of the poor performance is probably to blame on my skill-issued PPO implementation
reason being, other algorithms such as a shitty DQN implementation actually kinda work
from my experience, improvements in the reward functions and/or action/observation space are way more impactful than tuning the training algo
ah
it's not exactly tuning. moreso not doing stupid shit that kills the training
no
ah okay
which OS?
a commercial one that is the basis for a hypervisor
esxi?
nope
i work at https://www.bluerock.io/
ah nvm
blackrock but poorer
It's a hypervisor that does VM introspection to protect against exploits
how well does that work?
on the scale between "not" and "vaporware"
for example by making kernel code pages non-writable even if the kernel tries to overwrite them etc
and stuff like that
lol
wait but kernel page writing is a userspace exposed API
via ftrace et al
and ebpf
we're also running a custom linux kernel in the guest which talks to the hypervisor
also
how many exploitable issues are kernel bugs?
compared to literally everything else
probably a tiny amount.
yeah lol
but some extra security is better than no extra secyrity
a decent amount but not the majority
and kernel exploits are usually very high-integrity high-confidentiality
how would the kernel be in your attack surface?
if someone has code exec inside of your cluster something has already gone very very wrong
real world exploits usually work in multiple stages (e.g., they exploit 5 CVEs, not one) and if you stop one of the exploits that targets the kernel, that's enough to stop the attack
ofc
but that assumes any of the 5 stages involves kernel pwn
that's not too uncommon
tell them to invest on Ironclad and its formal verification proven to help security
lmao
but performance! 
but thats worse verification
SPARK is the bleeding edge, and Ironclad uses it across the whole stack
idk it seems like a pretty weak security measure
when you could like
just put the workload on a different vm
wdym by "put the workload on a different vm"?
split every kind of task you have into its own vm
so that even if one task is compromised other kinds of tasks arent
or alternatively apply gvisor
people do that already for certain stuff
that's not incompatible with what we're doing though
which apparantly isnt even that big of a performance impact
- lots of ppl use containers not VMs
incompatible, no, gives as much security without expensive vendor solutions, yes
gvisor is drop in compatible with runc
so
me when uacpi talk happens in uacpi thread
i can only talk about publicly available information but there are lots of things that you fundamentally cannot do if you're operating at the same trust level as the thing that you're trying to protect
i see i see
uACPI in linux kernel when
gvisor is basically like linux except in userspace and written in go
bro just write bugless code
True
Just don’t make mistakes™️
my mom already did that for my conception
for example, for many existing commerical security solutions you can avoid detection by just triggering enough stupid events
I am just continuing the original sin
until the kernel <-> userland communication backlogs
this is true for lots of tech that tries to detect attacks e.g. by using ebpf
Exists already
whats the score
U just missed a memcpy debate
Was 3M but thats pre 1.0 so less optimized
What?
that makes sense
every argument Ironclad takes a side in, we win, side with us or lose
uacpi-linux repo in the uacpi org
watch it get like 20M when updated and optimized
I though linux uses ACPICA
Ok but that’s not mainstream
it's an experimental fork
iretq ported it
No one cares bout that
or not, linux is not necessarily that fast
Duh lol

ok i need to stop being lazy and 1. reinstall Artix on my ARL PC and 2. port uACPI to Vinix
its not like uacpi benchmarks really bechmark anything apart of allocator speed and uhh locks ig
which is not bad, but you cannot make a statement on OS speed with that
Yeah
well for locks, afaik there's low contention, so it doesn't even benchmark the whole lock
only the fastpath
Linux stuff just works but its not super fast
linux is a good general purpose kernel for other reasons
Its optimized for multicore
just use this as your uacpi allocator and you will be on top of the leaderboard trust
void *malloc(size_t size) {
uint8_t data[size];
return data;
}
ez allocator
True 
just put your computer in the oven? thats a non issue
movdir64b my beloved
actually that doesn't work
since it invalidates the cache line
The direct-store is implemented by using the write combining (WC) memory type protocol for writing data.
pat obsoleted just use movdir64b for all framebuffer writes
True
I learned a bit of machine learning some years ago, that's what I know how reinforcements learning works. I never did anything technical with LLMs though
BASED!
waiting for flanterm to use movdir64b instead of needing WC
True
Availability of the MOVDIR64B instruction is indicated by the presence of the CPUID feature flag MOVDIR64B (bit
28 of the ECX register in leaf 07H, see “CPUID—CPU Identification” in the Intel® 64 and IA-32 Architectures Soft-
ware Developer’s Manual, Volume 2A).
no idea but it's more-or-less necessary for intel's total memory encryption extensions which have been available since Sapphire Rapids
maybe its also available on older gens though
Damn that's more recent than I thought
that's because with TME-MK accessing memory with one encryption key that was previously accessed through another one is not cache coherent
Gcc support added in 2018 it seems
so you need to re-initialize the memory somehow after changing keys
so just run until it hits that and then if it isnt supported change all the calls to that function to one that doesnt use it in the #UD handler and retry 
ifunc or whatever
@flat badge asking you because of your job. I've never quite understood what the purpose of memory encryption is, both in userspace and in virtualization scenarios. Because someone has to enroll the keys, right? And is that the host (kernel if userspace) or guest? If the guest enrolls the key, the host can just intercept it, thus breaking confidentiality. (The host would probably be able to extract the key anyways.) And if the host enrolls the key, it sort-of loses its purpose because, well, the host enrolled the key. So how does memory encryption provide additional security?
the keys are generated in hardware, i think
memory encryption mostly protects against physical attacks
i.e., somebody freezing your dram, removing it from the machine and putting it somewhere else to read it
I read it
I guess that if the host is compromised after the guest has already enrolled the keys, confidentiality isn't as greatly impacted.
and yes, the keys can be generated in hardware such that neither the host nor the guest sees them
so that's another benefit
apple's secure enclave stuff makes use of that very often iirc
ok so I halved ACTOR_LR and CRITIC_LR, and now it seems to perform significantly better
lol
no idea why
Yes, that's another use case. If you can trust the host (e.g., because it has a TPM that attests that only your software runs) and Intel, you can be sure that not even your cloud hoster can read your data
even if they physically interact with your machine
so long as you trust the TPM manufacturer
in microsoft azure iirc beyond memory encryption, there is a guest generated keypair used for loading secrets from the host
yes, right
so i think the host never sees plaintext secrets
and ofc so long as your attacker doesn't have a FIB machine
except when they're stored for the first time possibly? cuz the host needs to encrypt them with the public key and securely erase the plaintext
because if they do no amount of TPMs and memory encryption can save you
true, but that makes the attack way harder to execute
what's FIB again?
getting access to a sensitive device, freezing the ram with liquid nitrogen or whatever and putting it into another machine is way easier to execute than looking at the inner workings of the CPU
focused ion beam
yeah true
basically you just need one or a few corrupt data center employees to pull it off vs. expensive and large hardware
yeah fair
yea but the latter sounds more fun and likely easier to execute without leaving traces
i don't think frozen and stolen ram is traceless
it's used for fault injection right?
no fault injection is where you dont disassemble the chip
and you dont pay millions to tens of millions of dollars
FIB lets you change the chip in-place
ah
it's funny how laptop manufacturers leave test pads for the LPC bus that can be used for sniffing on the TPM
TPM should be an integral part of an SoC
yea that attack against the TPM exists but current TPMs also support integrity validation + encryption that is sent over the lpc bus
iirc Linux doesn't implement that yet though
but maybe it does by now
all you need to do is get the exact model of laptop as your target, make a pogo pin sniffing tool for it and you can get keys and stuff in less than a minute of holding the victim's laptop
oh? tell me more
lmfao
tldr you can encrypt the traffic using AES-CFB it's just that linux doesn't do it by default 
doesnt matter
because you can downgrade windows
and then it will pull the out of date key
:^)
same with linux ig
no that doesn't work
you can attach a policy to the TPM session that only allows you to retrieve keys that were generated with the same OS
so basically it can use some shared secret as an encryption key?
and for setting up the shared secret it uses a trusted asymmetric key placed by the manufacturer?
yes
cool
How does it know its the same os
the TPM policy allows quite a bit of flexibility but one possibility is checking the PCRs
= platform configuration registers
which essentially store hashes of the stuff that is loaded by secure boot
Ah
(or measured boot, if you're using DRTM)
DRTM = you ask the CPU to validate the contents of RAM after taking control from the firmware
that has the advantage that you don't have to trust the firmware
I always trust my firmware 
last year I made a research project for TÜBİTAK's competition, where I "designed" a trusted boot mechanism where the user (possibly on setup when having received the device) can unlock their device and enroll their own signing/encryption keys at the cost of losing the previous keysrm -rf /
kinda like how unlocking your bootloader on an android device makes you lose all data
yeah
btw this can also happen involuntarily with bitlocker on win11
if you encrypt your hard drive using bitlocker, then upgrade the mainboard, you lose access to your drive
because it uses exactly the mechanism that i mentioned above
you can avoid this by storing recovery keys
but if you forget to store them somewhere / print them out etc you're out of luck
except your device is always in the "locked" state and simply the keys are swapped so you're saying "oh thanks manufacturer keys, I won't need you anymore I can deal with signing my own stuff." and still only signed stuff will be loaded
there is cloud storage too
had to use it as changing some unrelated stuff on the bios settings made bit locker not trust it
lol
one thing I don't like about my hypothesized mechanism is that the root of trust depends on a keypair where the manufacturer gets rid of the private key right after signing something so you're trusting the manufacturer properly destroying the private counterpart of the public key burned into the SoC OTP memory after signing something with the private key (so the private key is only used once EVER)
if the manufacturer didn't actually properly destroy it, then someone getting hold of that private key = everything is compromised
wait why would you do that
just use a hash?
i don't remember
lol
thank you (and thank @left orbit) for this suggestion, so much cleaner and just worked after some minor fiddling with my other things
if I don't forget I can try reading my paper again
i want to implement it lol
i did "implement" it
lol
btw why did u need a custom types header
zig doesnt have stdint.h or stdarg.h
when building without linking libc
and i didnt know about that easy freestanding header repo so i had to use the custom types header to wedge in an impl of those two headers
ah
how the fuck do all my pcs have somewhat broken aml
did you fix your io helpers
to be actually io
the warning there tells me u didnt
at which points it does random stuff
show cod
bruh like
ignore the asm_* name, i was renaming things
read the headers pls
offset is an offset within the mapped handle
it's not a global offset
can u look at existing impls
you return the port base from the io map function as the handle and then add the offset to the handle inside the io read/write
lol
letsgo
ah and suddenly i need to hold the power button to turn it off

before it just turned off
yeah, so it bypasses acpi mode
previosuly it would dispatch to SMM
now u have to handle it
or if u dont it times out and goes to SMM anyway
tldr add a power button handler
will do
is uacpi score generally lower on real hardware?
oh 11k ops
uacpi score depends on what the code actually does
In general: the more aml runs, the better the score should get
since the code will already be hot
But device access will eat into the score
calling into SMM too
Hardware is a wild west
"as long as Windows runs on it and doesn't crash we can sell it!" is probably the logic of hardware manufacturers
it's not 'probably' the logic of them, it is the logic of them
if they test Linux in the slightest (rare), all they do is test that it boots into the latest Ubuntu (and maybe Fedora)
entirely forget anything else
latest boards might have aml that even nt barely works on
e.g marvin's aml has completely bogus stuff im sure nt aborts too
which causes an irq storm
so u wait until they figure it out and ship a bios update
i wonder what's the reason they do this
like, not being untested on non-nt
but being shit
it's not apparent you caused an irq storm i guess
if your testing harness is shit
or your test suite is "it boots lol"
what's like the most complicated thing AML should do
powering on devices at init
well
speaking of terrible firmware, when I first built my current dev pc both windows and linux seemingly triple faulted about a minute after waking from suspend, a bios update a few months later fixed it but I really do wonder what caused that
they should've tested obos for suspend functionality
the complexity is not what causes problems tbh, it's that aml is like javascript, very easy to fuck up types, forget to declare something, cause an undefined reference, etc
ah
if u look at marvin's blob its just them forgetting to put stuff under an if check
that if check already exists in one place, but they forgot to put it in the other
when is uOF coming?
only fans?
open firmware
oh
sure
libfdt is pretty good i think lol
the forth one?
yep
yeah
full OF had a bytecode thing as well just like ACPI I believe
was it forth compiled to some bytecode or did the ROMs literally have forth in text
we have smoldtb
btw i can report that uacpi also works on my T14s
given that it was shipped on macs
im not sure if "ahead of its time" is accurate
whats so bad about macs
nothing

i need an EC driver
you cant say its ahead of the time when its a common thing

a trillion acpi tables
what i mean is we went back to a crappier version without bytecode
well not crappier just more barebones
yeah, because linux didnt really use the bytecode :^)
if someone made DTs with embedded eBPF
L
this is based
linux would use them i think
and eBPF can take over your system much more easierly than AML it thinks
i have a funny idea
not really
i'm going to name my driver files after their compat string 
theres a verifier
we only have BPF for packet filtering
if someone pushed this like, 5 years ago
also not ported, reimplemented from spec 
i think that might have ended up being a thing
what about today
doubtful
managarm W
i wonder how much work left to get nixos on mlibc
you know a, e, r, s and t as well
#define W assert
based
C tho
we actually now prefer error returns to asserts 
WHAAAAAAAAt
errors in managarm?
never
heresy
i bet the workers who wrote that AML are paid little
i would need gcc (I'm getting close! I need mpfr, libmpc and tzdata for that), busybox, GNU patch, curl, probably tar and cpio for making it bootstrappable
aka the same people we can blame acpi.sys on
lol
probably
(ms also gets part of the blame, for letting them do this)
we'll never know who made acpi.sys
darkfire said it was firmware devs, though
must've missed that
i may consider it some day
uPC when?
what would an "uOF" even be? something like seabios/ovmf? or am i misunderstanding something
the requirements for an OS are less than for ACPI since the fcode interpreter is part of openfirmware and accessible to the kernel
something like uACPI but for OpenFirmware
ah , i need to look that up
it's where device trees came from
but the fake device trees don't have methods like real ones do
ah i thought it was like an actual "firmware" thing, something like seabios lol
there are a few implementations of the openfirmware for various platforms
@fiery turtle any progress on the iterator api? (sorry for ping)
Nice
kinda hard to write good abstractions around callback driver api in a language like zig
Makes sense
of course
i am taking a little bit of a different approach now
instead of good old "everything is kernel"
i am dividing it up into things, so "ke" is a separate thing from the rest of the kernel
and i plan on logically separating things between these "components"
so ke will not do anything scheduling related, that's what "dispatch" is for
and there's also "ob" which is the object manager, "io" which will be the io manager
source is not yet available because i want to work on it for a while before deciding if i wanna stick with things i have so far
yes, i know i can just refactor it even after it's public but i want to have a design i'm happy with before showing it off
thanks!! 🙏
any update on table only compilation options? 
there's uacpi_setup_early_table_access
you can call that then use uacpi_table_find_by_signature and other functions related to the tables api
ik but i don't want to compile in the hooks not needed for table access
lto :^)
that's rather unreliable + i don't want to lose the ability to do non-LTO builds
that's fair, tbh at this point you could just enumerate tables yourself and use the uacpi headers for the table definitions
iirc those are public
but i guess it would be nice to have the option to strip down uacpi to just tables
Soon tm
lmao
how does the new iterator api work with ascending/descending?
i rely pretty heavily on that for my device tree
It doesnt basically, it relies on you recursing down for each child
uacpi_status uacpi_namespace_node_next(
uacpi_namespace_node *parent, uacpi_namespace_node *child,
uacpi_namespace_node **next_node
);
uacpi_status uacpi_namespace_node_next_typed(
uacpi_namespace_node *parent, uacpi_namespace_node *child,
uacpi_object_type_bits type_mask, uacpi_namespace_node **next_node
);
thats the entire API
the way you use it is just
void recurse(uacpi_namespace_node *parent) {
uacpi_namespace_node *iter = UACPI_NULL;
while (uacpi_namespace_node_next(parent, iter, &iter) == UACPI_STATUS_OK) {
recurse(iter);
}
}
one thing i was thinking is like
should table-only compilation require uacpi_kernel_alloc for dynamic array resizing, or should it only rely on the early access fixed buffer mechanism
probably the latter
also i have to go through every header and source file and wrap in #ifndef UACPI_TABLE_ONLY_MODE or wahtever
so ive been kinda slacking off
the idea was that for kernels that want to use full uacpi later can still use the table-only mode in the beginning and then seamlessly switch to full mode
so much for not being recursive :P
well I guess, if they really want to, kernels can implement that code with an explicit stack
this is not uacpi's code tho lol
it's up to you how you use it
haiku does recurse
you are free to make a stack data structure instead
if you don't want recursion use for_each_child
ACPICA has this API, but it's used in like one place in linux btw
and has a race condition bug which can crash the kernel
this got me thinking of this code that I wrote for iterating over ioresources in my kernel and dumping them (an "ioresource" is some area in SystemIO or SystemMemory that has been claimed by a driver)
heck, it even does locking
this is a depth first walk right
yeah, it is DFS
yeah uacpi does exactly this for for_each_child
lol
docs
should probably mention that if possible prefer for_each_child instead
Make it a compile time definition 
imma leave it at this i think
ehh idk
i want it to be simple
tbh i think it'd be nice if instead of taking child and next_node it would just take an iterator
kind of an in/out parameter
You can make an ascend type of thing
Like from child to parent
Then you can do DFS iteratively
im just copying ACPICA API, but yeah a stateful iterator API could be nice as well ig
(or however that's called, I always forget which graph walking name is which)
not even a "stateful iterator api", literally just read in the child node from the pointer you get from the user
so the user data IS the iterator :^)
and you just write the next node to it or something
wdym?
Yeah it's dfs
ah ok thatll work. my device enumeration already is a queue so it wont be too hard to make this work without recursion anyway
fn recurse(parent: *uacpi_node) {
var it: *uacpi_node = null;
while (uacpi_namespace_node_next(parent, &it) == UACPI_STATUS_OK) {
recurse(it);
}
}```
ohh, u mean just overwrite the child
on next iteration it would contain the node you got from the function, uacpi would read that in and then give you the next node
yeah exactly
hmm yeah thats nicer
less parameters and functionally the same api
idk why acpica didnt do it like that tbh
Oh, you already have uacpi_namespace_node_parent
what should the parameter be called in this case lol
literally iterator?
ofc!
tbh even recursing here is probably safe-ish because i doubt you'll have namespaces with more than like 5 levels
especially if you do a typed iteration
mhm
if you dont filter by e.g. DEVICE then could probably be in the 20s
yeah thats fair
processor is deprecated compared to giving it a device for that but qemu and firmware devs as a whole do not care lmao
yeah u should just treat processor as a device with processor hid
yeah thats what i do
nice
ive even got a "driver" for that (it just attaches a pointer to my io system device object to the appropriate prcb)
damn
i really want to start a kernel but i dont want it to be shit and for that i must read tons of these papers etc so im lazy af to do that
mood
tbh it would mostly be focused on drivers and real hardware etc
(in my kernel the PRCB will be at address 0xFFFF_FCFF_CXXX_0000 where XXX is the lapic id, and while in kernel mode at gs:0 if its the currently executing processor's PRCB)
nice
linux does similar stuff for __per_cpu
where it stores an offset from base of per-cpu data
i think windows does the same but idk for sure
i decided i wanted the PRCBs to be page-aligned so i do it like this, it doesnt really matter because its accessed through a global const prcbs: [*]PrcbWrapper = @ptrFromInt(0xFFFF_FCFF_C000_0000); where PrcbWrapper is just a Prcb and padding out to page_size
so it uses array access syntax to get them from the global array
btw what if u have more than 4096 cpus
idk yet lmao
(each one has a pointer to itself as one of its fields so you can escape the gs address space)
yeah i figure ill deal with that many cpus if i ever encounter an environment with that many lmao
fair fair
just write a shit kernel like us peasants smh
wdym astral is pretty good
hes not wrong tho
tbh you can start out with the scheduler and io/driver stack :^)
if you do these right you can build nice abstractions over memory management in the process
at least i think so
thats what im doing currently lmao
kinda same but without the scheduler so far
ig i kinda have one, ive got enough of one to do sync primitives
but i dont have any timer interrupts yet
by scheduler i mean being able to start threads and have some sort of blocking between threads and be able to switch between them
yeah keyword "if you do them right" which i wont 
and sync primitives
(or any timers other than a tsc that can only be calibrated by cpuid or hypervisor (also cpuid but different) for that matter)
i can start, block, and yield threads
and i can turn the routine the loader drops me into into a managed thread
mkdir ~/osdev-$RANDOM never failed me
and that last is the only tested part lmao
the only way to get them right is to try and try, over and over, until eventually you get it right
or, alternatively, accept that there is no "right" because everything has subtle little disadvantages
this took me some time to realise, and I haven't even fully realised it yet
same on both counts
true
one thing i kinda want to try once i get my resources stuff up and running btw is to see if the root bridge has a PCI header in its acpi-provided resources somewhere
which might give the bus number behind it
instead of assuming if the acpi method doesnt exist it must be 0
so i kinda want to dump it lol
if anything is even there anyway
I personally don't really care. It's probably easier to keep the same interface as the full uacpi implementation
it's not about the interface tho, it's about it's fundumental ability to allocate memory
if i keep it as a static buffer only, it will only depend on log, map & unmap
hmm wdym
im just kinda curious whats in the RCRB tbh
RCRB?
hmm is that somehow acpi related?
if it exists its location must be retrieved from whatever gave you the root port in theory
so im curious if acpi will have a 4096-byte memory resource in CRS for the root port
and if so i wanna dump it
maybe
the spec for it btw says that if it exists it must have a pcie extended capabilities header at offset 000h, the absence of any of which must be signaled by a capability with cap id FFFF and next cap 000
and theres a couple caps that are rcrb specific
can give a vendor id and device id and theres support/enable bits for request retry status on config requests for all devices under the root complex
anyway id just seen this in the spec and it made me curious lol
yeah i know nothing about this but seems interesting
Also, if I remove bultin memcpy etc by default I'm gonna have to bump uACPI's major version by 1 sooo
uacpi 2.0 coming lmfao
that's just how semantic versioning be
limine 9
I imagine that bumping the major version number from 1 to 2 would feel more significant than bumping it from 8 to 9 (because in the latter case, you've already bumped it so many times that it's habit).
don't do that for memcmp, it will break obos
(my memcmp is non-standard)
if the function is called memcmp this might invoke ub
because the compiler might emit a call to memcmp without you knowng
and by "might" we mean "will"
tbh thats just a you skill issue
i don't get why people even make changes to the standard string functions but keep the same name
what does your version even do differently
returns a bool
why
so it's just worse 
because I felt like it
or whatever
its UB though
does it at least return 1 when the two regions are inequal?
yeah I don't think I knew that 8 months ago
it returns false when they are unequal
fyi memcmp can be useful to check whether one chunk of memory is smaller than another, for example if you want to sort objects
yeah so its instant UB whenever you compare structs that are big enough
I also didn't know that 8 months ago either
I did figure that out when I started using openbsd's rn tree
*RB tree
F
Soo if i understand it correctly, clang has builtin memcpy/memmove but no memset nor memcmp
it has builtins for all 4
hmm docs are lying ig
no __builtin_memset here
Hm actually it does say It is identical to __builtin_memset but also guarantees not to call any external functions.
oh well okay then
#ifdef UACPI_USE_BUILTIN_STRING
#ifndef uacpi_memcpy
void *uacpi_memcpy(void *dest, const void *src, uacpi_size count);
#endif
#ifndef uacpi_memmove
void *uacpi_memmove(void *dest, const void *src, uacpi_size count);
#endif
#ifndef uacpi_memset
void *uacpi_memset(void *dest, uacpi_i32 ch, uacpi_size count);
#endif
#ifndef uacpi_memcmp
uacpi_i32 uacpi_memcmp(const void *lhs, const void *rhs, uacpi_size count);
#endif
#else
#ifndef uacpi_memcpy
#ifdef UACPI_COMPILER_HAS_BUILTIN_MEMCPY
#define uacpi_memcpy __builtin_memcpy
#else
extern void *memcpy(void *dest, const void *src, uacpi_size count);
#define uacpi_memcpy memcpy
#endif
#endif
#ifndef uacpi_memmove
#ifdef UACPI_COMPILER_HAS_BUILTIN_MEMMOVE
#define uacpi_memmove __builtin_memmove
#else
extern void *memmove(void *dest, const void *src, uacpi_size count);
#define uacpi_memmove memmove
#endif
#endif
#ifndef uacpi_memset
#ifdef UACPI_COMPILER_HAS_BUILTIN_MEMSET
#define uacpi_memset __builtin_memset
#else
extern void *memset(void *dest, int ch, uacpi_size count);
#define uacpi_memset memset
#endif
#endif
#ifndef uacpi_memcmp
#ifdef UACPI_COMPILER_HAS_BUILTIN_MEMCMP
#define uacpi_memcmp __builtin_memcmp
#else
extern int memcmp(const void *lhs, const void *rhs, uacpi_size count);
#define uacpi_memcmp memcmp
#endif
#endif
#endif
This is what im gonna do (this is uacpi's internal stdlib.h)
also added it to config
After I enumerate all ACPI devices (btw, how do I do that? Do I just uacpi_find_devices_at(uacpi_namespace_root(), ...)), can they disappear?
see osdev wiki on how to properly make an acpi bus
no they cannot disappear
namespace nodes (at least exposed via public api) are guaranteed to be permanent
But it passes PNP ids to functions
I just want all devices there are
(am I missing something?)
Does UACPI_NULL do what I want?

ok, wiki explains it I'm dumb
wiki shows a lazy and dumb way to do it, as well as a proper way to do it
the proper way doesnt involve find_devices
this is for __builtin_memset_inline, isn't it?
yeah but builtin memset is not mentioned at all other than implicitly
which is what confused me
Clang provides constant expression evaluation support for builtin forms of the following functions from the C standard library headers <string.h> and <wchar.h>:
memcpy memmove wmemcpy wmemmoveIn each case, the builtin form has the name of the C library function prefixed by _builtin.
do u see memset here
ah that's probably just a mistake in the docs
Why does it do ```C
if (info->flags & UACPI_NS_NODE_INFO_HAS_HID) {
// Match the HID against every existing acpi_driver pnp id list
}
if (drv == NULL && (info->flags & UACPI_NS_NODE_INFO_HAS_CID)) {
// Match the CID list against every existing acpi_driver pnp id list
}
Isn't _HID mandatory?
what makes you think that
thats gcc
clang does pretty much what gcc does
also u want to match both hid and cid anyway
- it's own bullshit on top
remember that mandatory is not a word that exists in the firmware world
a device can have just a _CID and be perfectly fine
This optional object is used to supply OSPM with a device’s Plug and Play-Compatible Device ID. Use _CID objects when a device has no other defined hardware standard method to report its compatible IDs. The _CID object is valid only within a Full Device Descriptor. An _HID object must also be present.
btw why does it matter for you anyway
I don't want to match anything, I just want to publish everything that's in a system to my fancy new discovery system, and let drivers match it that way
Like my init server would match ACPI devies and start servers that way
you match against a union of (_HID, *_CID)
so publish a device object with compatibile_ids: _HID, _CID[0], _CID[1], ...
local man thought it would be easy
how else would they advertise e.g. a ps2 touchpad
but order doesn't matter?
no, it's an arbitrary list
Ok
hid is prefered for best compat
cid order doesnt matter
it's like matching (vid, pid) vs matching (class id, subclass id, prog) from pci config header
hid vs cid respectively
maybe a stupid analogy lol, but prefer _HID over _CID
usually you have no choice anyway
So it's like a system where you just drop a driver with server.conf or whatever with compatible _HID = "IDEA0010" into a directory and init is just gonna fork() execlp() driver with no strings attached if/when the device appears
it may be problematic if u have e.g. a synaptics_touchpad.sys running alongside ps2mouse.sys
synaptics must take precedence
both will match at least one entry from cid
I can have priorities
then yeah if u configure correctly
something like "match_before: ps2mouse" would work i guess?
No, just making sure that if 2 devices match, only one gets to run
It's making sense in my head
well yeah
2 drivers*
i am just thinking how you'd express that in the server config file :^)
absolute priorities kinda suck imo, the moment you start adding more conflicting drivers you might need to adjust them everywhere
idk, I'm gonna think of something once this becomes a problem
relations like this might make more sense, so init knows synaptics_touchpad.sys must be asked before ps2mouse.sys
well i need to think about it too, it's gonna become a problem soon for me :^)
and drivers in python eventually I guess
If this works out...
ew
Why ew
it's python
Or JavaScript
Idk this sounds cursed so it must be fun if I get it to work
Like C++/Rust is more practical, but just the possibility
anyway, maybe not, this is like a thing that I will maybe do in a few more years
no no, do it, it will be a fun thing to se :^)
i can get behind the "it's so cursed i wanna do it" mindset
no 9999999999 points 
wow so fast 9999999999
wow this output looks so empty
i might actually store bad_timesource as a boolean in the global context
should probably disable while timeouts and stuff if its detected
removed time printing from namespace init as well if clocksource is bad
alright the iterator api seems to work as well
@ oberrow, @ iretq and @ khitiara if you could test if the PR works for you that would be great :^)
i have nothing to test it on yet 😭
lol fair enough
i did NOT expect it to come this quick tbh
but rest assured i am working my ass off to get to write the device/driver/io stack asap
:^)
as much as my adhd allows me to, at least lol
void recurse(uacpi_namespace_node *parent)
{
uacpi_namespace_node *iter = UACPI_NULL;
while (uacpi_namespace_node_next(parent, &iter) == UACPI_STATUS_OK) {
dump_one_node(iter, uacpi_namespace_node_depth(iter));
recurse(iter);
}
}
Well i did test it locally like this but

I should also write the acpi bus driver after I have finished this seh stuff lol
i wanna make an optional thing where it verifies all of kernel api for basic sanity at startup
could be useful perhaps
seh is really cool tbh
yeah, the only slightly annoying thing that I discovered is that clang doesn't like it being used in some places (I think its the functions where there are c++ destructors but I have no idea why, the destructors don't get run inside the try block or anything
it just sometimes randomly crashes when compiling (and it looks like this https://github.com/llvm/llvm-project/issues/82917 but there shouldn't be any destructors inside the except block + usually it works second try)
lol
compile your kernel with msvc like a 
as bonus points u get very little punishment for ub
the downside being, of course, that you get very little fast code as well
they call it "punishment for ub", i call it "clang realizing my code can be made much faster by removing all of it"
What changed?
smbus or osdev wiki stuff?
look at the pr
nothing out of the public api
but a lot of internal stuff
I don't think that's a good idea
there can be genuine reasons why the clock yields 0 elapsed seconds
for uacpi init
like what
for example if the AML is very small and the timer is not very accurate
elapsed time = 0 is not necessarily a bug
even very small aml runs an absolute ton of code
only disable timeouts if the clock is stubbed :^)
you do already distinguish between stub vs low resolution
but yeah
but iirc you coalesce them into a single "bad time source" variable
if u always return 0 effectively timeouts are already disabled
because it will never reach the expiration point
yeah true, right now it just prints a warning so
poor timer resolution can also happen on modern systems depending on the configuration
e.g. AML Timer expects 100ns ticks, so if your timekeeping is that bad even aml might trip
no, why?
aka it will see a huge jump in time at once
i don't think that's true
what is?
ACPI doesn't guarantee any minimum response time
if aml requires sub-microsecond timers
100ns is the maximum resolution that it can make use of
what the fuck are you doing
The timer operator returns 100ns ticks
yes
but it doesn't need to provide 100ns of accuracy
yes, I never said it did bruh
but if an interrupt happens and you switch to a task that runs at a higher prio than AML you may have a 10s of ms jump
im saying aml might rely on it being more precise than milliseconds as it was in case of ironclad
that sounds like very broken aml
idk about this kind of breakage though
probably not
what would you have to do to make that a problem?
what happens on NT if there is an interrupt during AML?
surely the machine doesn't just stop working
and NT has real time interrupts
no idea, aml probably runs as dpc
"probably"
DPCs can be interrupted
i seriously doubt its a DPC
yeah
that's the entire point of DPCs
you cant sleep in a dpc
interrupting it to ack an irq is a few microseconds
i doubt that AML in NT runs at > everything else prio
yes, but an irq can switch to a real time prio task
I seriously doubt that any AML relies on a minimum response time
that'd be insane
you also cant acquire mutexes in DPCs
anyway uh, i'll just keep it as a warning and will hide your uacpi points for now
which device driven by AML would even have a minimum response time
the only thing i can think of is bitbanged hardware drivers
not even realtime capable USB controllers demand that, they just drop frames if you don't respond
smbus? idk
like somoene trying to bitbang uart over a gpu from aml
which hw is bitbanged but not serial transmission?
no you have an IP block which handles it on its own
i2c
hardware designed by firmware devs?
you can literally slow down the pcie clock to 1mhz or so and most devices will still work
the devices driven by aml are limited only by the insanity of firmware devs
technically u can drive anything
practically i dont think youd see bitbanged i2c or uart tho
you have 3 tries for USB in device mode iirc
just but i doubt that any x86 has devices that hard fail on minimum response time violations
depends on how u define hard fail
cpu fans?
:^)
i also doubt that NT or Linux make any effort to guarantee a minimum response time for AML
yeah your cpu overheating and dying perhaps 
im sure some firmware dev will have the bright idea of implementing PWM in AML
hard fail = need reset to continue
ah
cpu fans have a hard fail condition
if you dont spin them the cpu dies
and you need to reset the cpu

the CPU doesn't die because it goes into thermal shutdown
i mean they have SCI that can run AML handlers exactly for this reason, although u shouldnt use them for that ofc
;D
aka enable fans as a response to a thermal event
thats what i meant
AFAIU both linux and NT run SCI handlers in softirq/DPC context
which is not real time priority
that'd make any ACPI system incapable of running an RTOS
which i'm pretty sure is not the case
i doubt some shitty chinese laptop manufacturers know anything about rtos, timing guaratees etc
they can roll anything as long as it boots
it is not because RTOS is loosely defined, not because ACPI allows you
the hardest of real time OSes cannot use ACPI bytecode

i mean running aml can (and will) call into SMM at which point your real time guarantees are gone
modern systems don't usually call into SMM at runtime
not true
how do RTOSes deal with NMIs
u can grep your latest laptop's aml for smi calls
wow ur real time guarantees are gone
No, they run the NMI work in a DPC
not many RTOSes of the ones that require sub ms accuracy running on ACPI enabled systems have as a task they have to do talk with AML to hotplug PCI devices
but you got interrupted, meaning you aren't real time anymore
it depends on what your RTOS has to do with what considerations
what does real time even entail?
actually I think that's not true. a lot of RTOS run on x86 system with PCIe
for the most part, kinda, they still need SMM to e.g. handle missing OS features like support for SMBus, EC etc
some just handroll an smbus driver in aml, some offload it to smm
for a hard real time system, you would use hardware that doesnt generate NMIs, or include the NMIs in your scheduling guarantees by bounding their execution time by, for example, having wiggle room on your scheduling by using slack time
that's not the point. you just factor the possibility that you can get interrupted into your time budget
real time systems usually do not exhaust 100% of CPU time, they need some slack to guarantee minimum response time
and to guarantee that tasks do not backlog
yeah that is what I am refering to
interesting
the most important point of a real time system though is that it guarantees that always the highest prio task will run
lol
which is one of the reasons why RTOSes suck, because a hard real time RTOS most of the time needs slack time, unless you use specific scheduling partitions
RTOS will not preempt tasks at the highest prio
basically the osdev wiki stuff but instead of immediately probing devices just create persistent device objects for them when the bus is enumerated by the kernel + combining the acpi hid/cid when the kernel requests the compatible ids for a device (+ other ioctls for getting the resources, executing aml method on the device etc)
Also, the ACPI spec agrees with me:
The period of this timer is 100 nanoseconds. While the underlying hardware may not support this granularity, the
interpreter will do the conversion from the actual timer hardware frequency into 100 nanosecond units.
Users of this opcode should realize that a value returned only represents the time at which the opcode itself executed.
There is no guarantee that the next opcode in the instruction stream will execute in any particular time bound
The OSPM can implement this using the ACPI Timer and keep track of overrun.
The specific partitions being harmonic periods or stuff like that which rarely adjust to tasks irl
There is no guarantee that the next opcode in the instruction stream will execute in any particular time bound
^ In particular: there is no guarantee
i mean, what u said is just common sense
but firmware devs wipe their ass with this spec
yes, but users will complain if they run windows, a sound driver at real time prio enqueues a buffer and the CPU goes into thermal shutdown because the fans stop working 
why would it switch to a real time task tho?
IOCTL_ACPI_EVAL_METHOD_EX can be used only at IRQL < DISPATCH_LEVEL.
so it follows that (unless AML is invoked by other means) AML is run at APC or passive IRQL
tru
what does this mean?
IRQL>=DISPATCH_LEVEL meaning no preemption is done
I might just make ironclad soft real time just because hard real time is not really what the stuff is about anymore, people have found other aspects of it of note
they run at low priority in thread context
And it's a very real PITA
and it seems forbidden from interrupt/dpc context to invoke AML
which, again, makes perfect sense 
ah
if AML is able to cause sleep then it must be so
I have a laptop which overheats during Windows updates because it needs a driver to set the fan speed
So like what you're saying is probably a thing
Does uACPI terminate strings?
Also, is this all (+ 2 entries) all there is in a device?
(Like what info should I be discovering/publishing?)
_CLS
Ofc
there's a get namespace node info function fwiw
gives a struct with the essentials
and yeah those are the important ones
I also get bbn and seg for pci root complexes
and a device might not have all things
if anyone wants a sample of code getting properties and all that from uacpi I can share my enumeration code
I want that