#uACPI - a portable and easy-to-integrate ACPI implementation
1 messages · Page 29 of 1
they definitely have the same issue proxima did, regardless of how it's actually implemented
Can you maybe try to replicate that in usermode
And try using Intel vtune or something alike
To check the diffs
i found it
right
pain because of templates but shouldn't be too hard to port to c
actually i have no idea how to map the may_alias
yup
oh i can just do __attribute__((may_alias))
what the hell is gnu::artificial
seems like a debugging thing
What if you mark your memcpy as noinline and use __builtin
like by default it already has inlined stuff as part of the backtrace
Maybe it inlines the rep mosvb where the builtin memcpy didn't think it should
Like I am almost certain extern function has a stronger barrier than memory clobber
by default the backtrace shows the line of the inlined code instead of the site where it got inlined
I should mark my intrusive linked list functions as artificial tbh
"extern function" doesn't exist in this case because i'm using LTO
I mean against the asm code
Didn't you say the inline asm was worse than no inline asm
And using an extern
ah
inline asm is worse than normal asm using __builtin yeah
Try marking the memcpy as noinline and use builtin
i'm porting the phd memcpy rn i'll test that afterwards
Nice
nevermind i tried that first
it's now about on part with normal asm
but still not better than just the naive impls
Hmmmmm
wait isn't this technically UB? it violates strict aliasing as far as i can tell
eh i'll try it anyway
inb4 recurses because logging memcpies
@fiery turtle it's official: uacpi memcpy is better than phd memcpy
phd memcpy gave 6.7M
it's as straight of a translation to c as possible https://hst.sh/nazavuyaxa.cpp
bruh
Sus
Ok Linux just has an extern asm function on 64bit that either does memcpy if fsrm or a loop that copies 4x8 bytes at a time
Which it patches at load time obviously
that's what gnu::may_alias is for
What does the compiler do with the naive impl that's so special
what does the generated code look like?
Btw what about using O2 vs O3
It's hard to figure out even from diffs
Hmmm
With __builtin for the PhD right?
yeah
I feel like the problem is inline
with -O2 + LTO:
- phd memcpy: 7.4M
- naive memcpy: 7.3M
I feel like the copies are never large enough to make movsb be worth it, and that over inlining from it being small hurts it even more
It doesn't explain the variants with extern tho
And the naive is probably simple enough that it gets unrolled to something like the builtin
When it does get inlined
isn't it just loop unrolling by hand, which the compiler probably does for you anyway?
(i'm too dumb for it)
no i dont think they do it for free
phd memcpy is good for a reason or something
most same compilers wont unroll this because of code size
also here's a shit ass python script which takes a bunch of single results and calculates the mean and stddev and a 95% confidence interval https://paste.sr.ht/~pitust/43498d8ccca174530b6a1c52607e15fe3ae6e841
also a "score" which is the low 95% confidence interval value
uacpi memmove: mean 159819.90625 +- 929.433544647053
compiler_builtins (rust) memmove: mean 159334.46875 +- 1066.4083397122151 (std 3077.8145654056934)
This is what a dumb memcpy compiles to with clang
so within margin of error
I see it using SSE and copy in 16 byte chunks
about the same margin, and its a bit higher
@dire owl you are the maths expert, how do you calculate a % chance that this is actually an improvement
I think it's not
is it not?
rust strlen has mean 155660.875
holy fuck
void *memcpy(void *dest, const void *src, size_t n)
{
void *k = dest;
while (n--) {
*((char *)dest++) = *((char *)src++);
}
return k;
}
also, i benchmarked my sso patches properly now
No SSO: mean 143967.75 +- 1759.780639039281
SSO: mean 147692.625 +- 1063.661225436405
so its a definite improvement
4k points for free
sse?
oh
i have some shitty custom out-of-tree uacpi patches
which help a bit with allocation pressure
dont think i got them all in the sso changes though lol
okay lets do more perf improvement attempts
oh hmm i think i might not have been benchmarking correctly
oh no my changes are way more scuffed
Without general regs only 
i bet (
) but im just giving you my branch if you wanna test it too
ok its probably similar then
what's phd about it?
korona has a phd
and its his code
so
its phd code
thus its a phd memcpy
it's just an inside joke (sort of)
all slightly overengineered code written by korona is referred to as "phd code"
why
thesis about maximizing uacpi score
for one because it's not universal, i guess
different cpus do different things fast
oh no thats not that bad
the cursed thing is like
idk
well its way too practical for a phd
and like what happens if you give it misaligned pointers
this will explode
that's what -fno-builtin/-ffreestanding is for
Like I'm still convinced that what compiles give you is already good enough
It shaved a lot of instructions lol
baseline | mean 115812.91666666667 +- 1033.0985163355087
good memcpy | mean 157890.83333333334 +- 1977.378657942172
+rust memset | mean 147968.41666666666 +- 1287.0687489231607
good memcpy/memcmp | mean 161383.16666666666 +- 2146.584592338015
+rust memmove | mean 159985.08333333334 +- 1673.8996305597188
+rust strlen | mean 160433.58333333334 +- 1264.8421854959556
i should add a system to proxima that detects at runtime if there's only one cpu and if so switches out some functions for cheaper versions
for example turning spin_lock_noirq into ret or lock cmpxchg into cmpxchg
well yeah but then to be fair to all the smp kernels i'd have to test with the smp version
true but that's ugly
What happens if I add AVX to pmOS...
here are the results
baseline is already with sso fwiw
rust memset, memmove and strlen shit
and memcpy and memcmp good
without sso its mean 158841.0 +- 1305.8822066072166
so its a slight hit
my dedicated 32 byte slab fastpath was also a big improvement, without it i get mean 158387.5 +- 1826.162830652172
In the ACPI specification, there's this field called the "hardware signature". Is it possible to cheat the uACPI benchmark by somehow loading a pre-populated namespace if this value matches that of the pre-populated namespace's FADT->Hardware Signature?
this signature is for resume from S4
so that the os can distinguish between S4 resume and clean start up
it doesnt help with namespace preservation
The only thing that determines the hardware signature is the ACPI tables.
this is useless for any uACPI benchmark cheating purposes
disabled in ucode on most gens, and unsupported on like 10th gen and above iirc
I think HLE is different to TSX
the ram is reset during s4 sleep soo
HLE is part of TSX i think
Quick question, if I have SSE and just do inline void save_sse() { asm volatile(" fxsave %0 " ::"m"(data)); } what do I do to support AVX?
you have to use xsave i think?
avx needs xsave yeah
But like is it always available?
Not on CPUs without it
avx is usable if:
- xsave is supported and enabled
- avx is supported
- xsave is configured to save/restore avx registers
So like I do CPUID memes, and use XSAVE if it's supported and FXSAVE if not?
yeah
using clz in alloc is mean 157427.58333333334 +- 2856.8090871983513
so i dont know what magic rust is doing
but evidently its rather fast magic
wtf memset on free worsened my perf
these error bars are way too big
maybe 32 samples would get me close enough
Are there x86-64 CPUs which don't support GSBASE?
but that makes testing too annoying
yes i think so
but you dont really have to care
bruh
its hobby osdev
that's no swapgs
oh hmm
what do you do in those situations
according to some manual (idr if it's intel or amd) from my memory it's view into segment cache
thats not how it works
and you can't load segments of 64 bits
Isn't swapgs architectural to x86-64?
Yeah those are different
oh, the instructions
yes
fsgsbase != swapgs
ok
swapgs is part of the base x86_64 isa
i don't use it
The msrs and swapgs are architectural
fsgsbase is the faster way to read/write the GS_BASE and FS_BASE msrs
how much faster? 
don't know
like is it even worth extra if statement faster?
probably considering they exist
yeah if you could only enable them for kernelmode id use them
but i just use MSRs since i dont want to allow userspace messing with fsgsbase
yeah same
why not?
makes the paranoid irq entry points a pain
if you don't enable fsgsbase you can just read the msr and swap if it's a kernel mode address
because fs and gs base is how threadlocals and stuff work in userspace
if you enable fsgsbase userspace can set it to any canonical address they want
including kernel ones

so now whether a paranoid irq entrypoint uses valid gs is controllable by userspace
just don't be paranoid 
bit hard for NMIs and MCEs
also as someone suggested just store it on top of the NMI's stack
like one above what gets loaded from tss
ists*
as in, the IST? that'd work yeah
yeah
the cpu tells you the features you can enable
conveniently guaranteed to be in the same format as the register for the features you want to enable
then once you've set up that register it tells you the size of the context for the features you've enabled
no but like it's future compatibility (?)
yes
So I just add a few LoC and have AVX
if you unconditionally enable all features with xsave you'll be able to support all future extensions (as long as they don't supersede xsave)
xsavec/xsaves?
I sure do love the offtopic convos that always appear in here
uACPI thread > any other channel
i think it's just a lot of smart people hanging out in progress-report channels
also AVX is totally related to uACPI
depends on the distribution
but since the numbers are big, it's probably close to a normal distribution
but already just looking at the numbers I can see it's not statistically significant
wonderful
a relevant measure would be the difference dvidied by the root mean squared of the errors
if it is bigger than 3, one typically considers that significant
this is like
definitely smaller than 1
so consistent with the hypothesis that it makes no difference
makes sense
oh also * 1.96
Shouldn't like 41 be ECX?
EBX = everything that's enabled
ECX = everything that the cpu supports
When I initialize my kernel, ebx is 576 and ecx is 2432
in this case they should be the same
maybe I do it in a different order
ecx should always be big enough yeah but it might be too big if you choose to disable certain features
so you might have some wasted space if you use ecx
shouldn't matter that much though
@gentle peak btw why do u manually add uacpi's sources if it exposes them via a meson.build?
you can't have recursive subprojects in meson
u can have a wrap no?
and i didn't want uacpi to be a sibling of hydrogen because it's not really a separate thing
uhh
i've never used wraps
I almost have AVX but it pagefaults doing xrstor (%rcx) 
anyway im not good at meson so idk what that means
hi
basically if you have meson.build subprojects/ a/ meson.build subprojects/ b/ and subprojects/a/meson.build does subproject('b') it'll try to look at subprojects/b instead of subprojects/a/subprojects/b
this is an intentional design choice
i don't like it personally but whatever
oh wait nevermind i lied apparently the meson documentation is just wrong
struct SSE_Data {
klib::unique_ptr<u8[]> data = nullptr;
...
};
void SSE_Data::restore_sse()
{
switch (sse_ctx_style) {
case SSECtxStyle::FXSAVE:
asm volatile("fxrstorq (%0)" : : "r"(data.get()));
break;
case SSECtxStyle::XSAVE:
case SSECtxStyle::XSAVEOPT:
asm volatile("xrstor (%0)" : : "r"(data.get()), "a"(0xFFFFFFFF), "d"(0xFFFFFFFF));
break;
default:
assert(false);
}
}
Does this look ok?
you want to use xrstorq too
It's passing rcx
in assembly
; switch (sse_ctx_style) {
ffffffff8000672c: 74 0f je 0xffffffff8000673d <sse_exception_manager+0x3d>
; asm("xrstorq (%0)" : : "r"(data.get()), "a"(0xFFFFFFFF), "d"(0xFFFFFFFF));
ffffffff8000672e: b8 ff ff ff ff movl $0xffffffff, %eax # imm = 0xFFFFFFFF
ffffffff80006733: ba ff ff ff ff movl $0xffffffff, %edx # imm = 0xFFFFFFFF
ffffffff80006738: 0f ae 29 xrstor (%rcx)
I think I'm going to finally make kernel print %cr2 on pagefaults 
(to keep the legacy state in the same format)
xrstor uses a different format for the x87 state than xrstorq
the same way as fxrstor and fxrstorq are different
Wait a second
It's not a pagefault
It's #GP
This means that my cr4 is garbage
or misaligned pointer
nope
rcx: 0xFFFF80000001B020
cr4: 40620
yeah you didn't set osxsave
Isn't 1 << 18 == 0x40000?
I memset it to 0
oh wait
it's an alignment issue
xsave requires 64-byte alignment
yours is 32-byte aligned
I do indeed have it 
(I use dlmalloc as kernel heap
)
(it's like 1/3 of my kernel in terms of LoC)
Ok I think I have AVX
one way to check is qemu's info registers, if AVX is usable the output will be formatted like this
I'm compiling for -march=znver3
I think it's faster on my laptop...

; *((char *)dest++) = *((char *)src++);
24acd0: c5 fc 10 04 3e vmovups(%rsi,%rdi), %ymm0
24acd5: c5 fc 10 4c 3e 20 vmovups0x20(%rsi,%rdi), %ymm1
24acdb: c5 fc 10 54 3e 40 vmovups0x40(%rsi,%rdi), %ymm2
24ace1: c5 fc 10 5c 3e 60 vmovups0x60(%rsi,%rdi), %ymm3
24ace7: c5 fc 11 04 38 vmovups%ymm0, (%rax,%rdi)
24acec: c5 fc 11 4c 38 20 vmovups%ymm1, 0x20(%rax,%rdi)
24acf2: c5 fc 11 54 38 40 vmovups%ymm2, 0x40(%rax,%rdi)
24acf8: c5 fc 11 5c 38 60 vmovups%ymm3, 0x60(%rax,%rdi)
Same as phd memcpy
I think zen 3 is weaker than latest intel so...
can someone with fast intel test it? 🙏
i'm also on zen 3 so shouldn't be too different from what you got but on my pc it's 1.2M/s
I get this on 5900X
what is the avg lol
that's what you get when it's zero nanoseconds
Can you give it deadline tsc?
qemu-system-x86_64 -serial stdio -m 512M -cpu max,+hypervisor,+invtsc,+tsc-deadline -M q35 -accel kvm -cdrom limine/pmOS.iso -smp 1
invariant*
ah now it looks realistic
I don't have kvm clock 
Which CPU is that?
i5 13600k
its piss easy to implement
Not if your clocks stuff is a mess
proxima's clocks stuff needs to be reworked too because right now it cannot cope with a time source that changes frequency
or with any non-tsc time source for that matter
which time sources are those?
kvmclock
I mean those that change frequency
yeah, kvmclock
let me rephrase that a bit
proxima currently uses TSC ticks as its internal time unit in a bunch of places, and it cannot cope if the TSC changes frequency
My kernel can only calibrate with PIC and only uses LAPIC for scheduling and if there's not invariant TSC, it's also using lapic for monotonic time
With 20Hz interrupts or so
kvmclock gives you a mapping from tsc->ns that automatically changes if tsc freq changes
why would it change tho
vm migration to another cpu that has a different tsc frequency
vm migration
proxima just assumes that tsc is invariant, if the bit isn't set it prints a warning but it'll still act as if it is
I think AVX didn't change anything
I'm suspecting it's issue with locks 
How do you even detect that it happens?
basically how kvmclock works is you give it a physical address to a structure that holds the conversion info
You write to msr and it updates that
nope it auto updates
before the vm gets migrated a flag in that conversion info gets set that basically says 'hey this conversion info is invalid'
when the vm has been migrated it changes the conversion info and clears the flag
but it also gives you time in nanoseconds
looks like average C to me
are we looking at the same docs?
this is the one i'm looking at
when it starts updating flags is changed to indicate that
I'm telling from memory
it changes tsc_to_system_mul and tsc_shift and then clears the bit in flags
The MSR doc said that this structure gets updates when you write it
it gets updated on the initial write and every time it needs to be changed afterwards
oh it changes version actually
yeah that's a different msr
different msr yeah
i'm not sure what the purpose is of that one
I mean this makes sense
I think its for getting the time of day from the host
But it's unrealistic to be updating this all the time
yeah that one doesnt auto update
or well it can if the hypervisor impl feels like it
but its not guaranteed to
does the acpidumps repo have the qemu tables by any chance?
i am in ur walls by chance
I sure do not hope so given they are made of reinforced concrete
most same compilers wont unroll this because of code size
@left orbit
well this is vectorized
I think I've used the wrong term
i'd say that's a slightly different case
btw do you know if the tsc deadline register gets auto corrected when the tsc frequency changes?
you probably wouldn't get an unrolled loop with -mgeneral-regs-only
You do
; ((char *)to)[i] = ((const char *)from)[i];
ffffffff8003d3e0: 44 0f b6 0c 3e movzbl (%rsi,%rdi), %r9d
ffffffff8003d3e5: 44 88 0c 38 movb %r9b, (%rax,%rdi)
ffffffff8003d3e9: 44 0f b6 4c 3e 01 movzbl 0x1(%rsi,%rdi), %r9d
ffffffff8003d3ef: 44 88 4c 38 01 movb %r9b, 0x1(%rax,%rdi)
ffffffff8003d3f4: 44 0f b6 4c 3e 02 movzbl 0x2(%rsi,%rdi), %r9d
ffffffff8003d3fa: 44 88 4c 38 02 movb %r9b, 0x2(%rax,%rdi)
ffffffff8003d3ff: 44 0f b6 4c 3e 03 movzbl 0x3(%rsi,%rdi), %r9d
ffffffff8003d405: 44 88 4c 38 03 movb %r9b, 0x3(%rax,%rdi)
ffffffff8003d40a: 44 0f b6 4c 3e 04 movzbl 0x4(%rsi,%rdi), %r9d
ffffffff8003d410: 44 88 4c 38 04 movb %r9b, 0x4(%rax,%rdi)
ffffffff8003d415: 44 0f b6 4c 3e 05 movzbl 0x5(%rsi,%rdi), %r9d
ffffffff8003d41b: 44 88 4c 38 05 movb %r9b, 0x5(%rax,%rdi)
ffffffff8003d420: 44 0f b6 4c 3e 06 movzbl 0x6(%rsi,%rdi), %r9d
ffffffff8003d426: 44 88 4c 38 06 movb %r9b, 0x6(%rax,%rdi)
ffffffff8003d42b: 44 0f b6 4c 3e 07 movzbl 0x7(%rsi,%rdi), %r9d
ffffffff8003d431: 44 88 4c 38 07 movb %r9b, 0x7(%rax,%rdi)
ffffffff8003d436: 44 0f b6 4c 3e 08 movzbl 0x8(%rsi,%rdi), %r9d
ffffffff8003d43c: 44 88 4c 38 08 movb %r9b, 0x8(%rax,%rdi)
ffffffff8003d441: 44 0f b6 4c 3e 09 movzbl 0x9(%rsi,%rdi), %r9d
ffffffff8003d447: 44 88 4c 38 09 movb %r9b, 0x9(%rax,%rdi)
ffffffff8003d44c: 44 0f b6 4c 3e 0a movzbl 0xa(%rsi,%rdi), %r9d
ffffffff8003d452: 44 88 4c 38 0a movb %r9b, 0xa(%rax,%rdi)
ffffffff8003d457: 44 0f b6 4c 3e 0b movzbl 0xb(%rsi,%rdi), %r9d
ffffffff8003d45d: 44 88 4c 38 0b movb %r9b, 0xb(%rax,%rdi)
ffffffff8003d462: 44 0f b6 4c 3e 0c movzbl 0xc(%rsi,%rdi), %r9d
ffffffff8003d468: 44 88 4c 38 0c movb %r9b, 0xc(%rax,%rdi)
ffffffff8003d46d: 44 0f b6 4c 3e 0d movzbl 0xd(%rsi,%rdi), %r9d
ffffffff8003d473: 44 88 4c 38 0d movb %r9b, 0xd(%rax,%rdi)
ffffffff8003d478: 44 0f b6 4c 3e 0e movzbl 0xe(%rsi,%rdi), %r9d
ffffffff8003d47e: 44 88 4c 38 0e movb %r9b, 0xe(%rax,%rdi)
ffffffff8003d483: 44 0f b6 4c 3e 0f movzbl 0xf(%rsi,%rdi), %r9d
ffffffff8003d489: 44 88 4c 38 0f movb %r9b, 0xf(%rax,%rdi)
oh god what in the fuck is that
clang
probably not, since the kvmclock part acts on top of the tsc
I'm gonna add restrict
what compiler flags did you use?
fuck
well its not too bad actually my code can handle a 'spurious' tsc deadline trigger
im mostly worried about events being late if the tsc frequency decreases
But it's copying 1 byte at a time
I.e. doing what it was told
And not using misaligned movq
what's the problem with that?
Unless you're realtime
In which case why are you running in a VM
i don't think it'll have too many bad consequences but i don't like the concept
I would be more worried about events arriving early
oh no that's not a problem since i decided the best way to handle cancelling events on another cpu was to just let the interrupt fire and trigger none of the remaining events
No but like let's say you're waiting on hardware to time out
And suddenly your clock runs 10x faster
idk if that's possible but still
yeah
the interrupt will arrive early, the timing code will notice that the earliest event has its threshold after the current time, so none of the events get triggered and the deadline gets reprogrammed
You'd ask kvmclock for time
When an interrupt happens, you just look at kvmclock and ask "has this changed?"
if you're in a polling loop with timeout, the api you're using returns nanoseconds so there's no issue
if you're using the timing events subsystem, it'll notice that the interrupt arrived early and return without triggering any events
When you get an interrupt, you look at the front of priority queue, however it's implemented, and if its time is smaller than system clock, you fire the event
its time wouldnt be smaller than the system clock though
because both times would be stored in nanoseconds
Yeah that's what I'm saying, things arriving early is not a problem
oh i thought you were trying to say it is a problem
I didn't think about that
I was initially
Anyways a changing TSC frequency is not something that should normally happen. If one wants a migratable kernel, it is probably possible to get some sort of interrupt/event delivered before and after migration. It isn't worth it for me to worry about VM migration
It's not up to the kernel to decide if it want's to be moved (?)
If you're asking these questions it's probably not
No. But there will always be weird things that the user can do, and we can decide what weird usecases to support or not. Do you have any use case right now for migration of your kernel?
What
User can throw their PC out the window
And the kernel would also not be able to stop that
yeah the kernel certainly cannot do anything about that lol
It's the hypervisor that does the migration
yeah
but AFAIK that requires either of:
- user interaction. you tell QEMU to migrate the kernel (or suspend execution I guess)
- someone runs your kernel in a datacenter or something which auto-migrates.
until either of these happen, we don't have to care about migration
yeah
when they do happen, support for it can be fixed
but at that point the os would have enough functionality for user to be interested in running it in a datacenter
it's a valid argument that it is often hard to retro-fit new functionality into something that was designed without it in mind.
[ 0.005160] [ 0] acpi: successfully loaded 1 AML blob, 1711 ops in 0ms (avg 4032334/s) 4M cracked without SIMD

slowly adding support for write-then-read fields to uACPI (IPMI, SMBus, GeneralPurposeIO, GenericSerialBus, etc)
i have to propagate this response all the way from field dispatch code, kinda annoying
@mortal yoke qacpi support for this crap when
yeah its annoying af
does it always return a buffer or can it also return an integer?
also all fields work with u64 accesses atm, and this requires a buffer
only buffers
ah
technically u cant even store an int
well ACPICA errors out
i will support that because my code is generic enough
this is ACPICA
do you also pass the source as-is to the handler?
nah you will have to allocate a separate buffer and memcpy
and then that buffer is returned to the caller
so the source stays unmodified
so basically:
- take src
- allocate a buffer with the size required by protocol + field attribute specifier
- memcpy src to buffer
- pass buffer to address space handler
- address space handler reads the buffer then memcpies the response into it
- the buffer is returned back to AML from the store op
uacpi_status uacpi_dispatch_opregion_io(
uacpi_namespace_node *region_node, uacpi_field_unit *field,
uacpi_u32 offset, uacpi_region_op op, uacpi_u64 *in_out
)
My current field dispatch thing looks like this, i guess ill have to make this u64 a union of either u64 or buffer depending on field type
yeah idk if there are any other good options
ig Ill implement this in qacpi too, maybe also some kind of table api finally so I can implement most of the remaining ops lol
its really annoying how they shoved completely different functionality into the classic field op
just make a separate op or something
because this breaks like all abstractions
u cant even have generic trace_field_io
because the write is actually both a write and a read and its actually done on a buffer and not a u64
lol yeah
also other thing that I should do is breaking the huge 1k line switch to separate functions but that's a huge pain
Load will be useful as soon as u start using capability detection
because it loads extra aml code when u do that
iirc the only bad thing about it is it uses a lot of stack in debug mode?
Well as far as Load/LoadTable i have so many tests for that with probably 100% coverage of those ops so u cant screw it up
pretty much yeah, its not really that urgent but its slightly annoying that you have to basically compile the interpreter file with O2 even in debug mode unless you have a huge stack
Btw if u want NT compat u pretty much must implement Load/LoadTable as fake function calls
because mutex state and stuff is preserved across the load boundaries
not that its hard tbh
idk why acpica didnt do it
acpica full on allocates an entirely new interpreter state from scratch and goes into recursion
what about stuff like Local0, are they also separate for the load or are they the global ones (or local to the method where the load is called?)
its an entirely fresh method, so locals are fresh as well
table loads are like anonymous methods with a scope of \ by default
and well the fact that named objects are preserved
ah that's actually nice, so basically the only thing you have to make sure is that the nodes created inside that method don't get destroyed at the end
yeah
and one more catch
u gotta make sure to discard anything that it may try to Return
so that its not magically returned by Load etc
should be easy enough, I just mark the method's op frame as not needing a result and the return value is not pushed
ah
that's what I already do if you call a method that returns something and discard its result
really the only recursion is with the refcounted things, ig I could convert that to queue-based unref
ah lol
// Name: Infinite recursion eventually ends
// Expect: int => 0
DefinitionBlock ("", "DSDT", 2, "uTEST", "TESTTABL", 0xF0F0F0F0)
{
Name (MAIN, 0xDEADBEEF)
Name (ITER, 0)
Method (HANG) {
ITER++
HANG()
}
HANG()
Printf("Recursed %o times before stopping", ToDecimalString(ITER))
If (ITER > 64) {
MAIN = 0
} Else {
Debug = "Recursion depth was too small"
}
}
i want u to pass this test
well it wouldn't be hard, I'd just have to check the amount of method frames in call
this also tests the fact that method aborts dont abort the entire table load
is that a new test?
its pretty old
maybe I added like 7 month old tests when I added them 2 months ago lol
bruh
I’ll repost this here now since I’m working on making it presentable now, I’m like 40% done
holy shit
There’s some weirdness here since windows just takes in the raw ACPI tables and redoes some stuff in Po for some reason
But I’ll explain it later it’ll (probably) make sense

now what score does it get 
holy shit what?
yeah I think that’s my fault though
So I’ll get a final score when I finish rewrite
how did u get windows to do that with uacpi
is my question
doesn't windows have it's own aml interpreter and all
Windows reimplements a lot of its sleep logic in Po
po, one of the great rivers of europe
po, the dragon warrior
yeah
now when make fast 
does that mean you won't be able to shutdown/S3 suspend?
was react os previously using the ACPICA?
Correct
Correct for now
We have a PR to fix this
infy says they refuse to be windows compatible in acpica, so this should be more fitting
This is far more fitting
I tried to do this with ACPICA too at least to show some behavior comarisions
Nothing
It can’t even get close
hey if reactos needs a reference for S3 suspend
obos has done it

(obos shilling complete)
I’ve already looked at obos
@winter orbit kind of an off topic question, but do you know
a) can windows run on platforms without acpi
b) can you patch hal.sys to add support for different interrupt controllers
it was on my to-do list for a long time but i wanted to look at how to get windows up an running on apple sillicon without doing some weird gic emulation but instead just replace hal with one that supports apple's interrupt controller (which is the big issue with windows iirc)
and by windows i mean modern windows, like latest windows 11 or something
A) no
ah
B) Hal is gone in win10 22+
you need to implement some real ACPI tables
And also
Making a interrupt controller for windows is now almost impossible
Allegedly there’s some new way but we haven’t started learning yet
is it gone altogether? i heard it was merely compiled into one binary with the kenrel
Gic Supoort is now injected into NTOSKRNL as a lib
it’s just libraries now
All inside ntoskrnl
good for optimisation this way
would patching ntoskrnl technically work?
Not going to lie to you, no
There might be some new kmdf thing windows allows
hypervisor + gic emulation is the only reasonable way then
To our knowledge yes
i don't think loading drivers that early would be allowed
there used to be a system for using other controllers
Oh it is
like before any interrupt controller is set up?
yup
damn okay
But figuring it what secret system windows made isn’t optimal yet
we don’t know of anything that replaced 3rd party Hal extensions
Which is how you’d do this before windows 10 23+
so yes there’s some old version of windows 10 you could port
But for win11 you’d need to reverse the early boot stuff
And see if there’s a way
what's kinda confusing is that hal.dll still has a bunch of exports related to interrupts on my windows 11 system (24h2, 26100.2605)
are they just not used anymore or
file up some decompilafion and look at what those functions do :3
They’re there for driver compatibility
oh they are all forwarded to ntoskrnl
im dumb
i was wondering why the file was so small
drivers imported from Hal for a decade
now that explains it
yeah sorry they very much screwed over people when removing Hal extensions
i'll get an aarch64 ntoskrnl later and take a look, maybe i can figure out some hacky way to get that thing in there
holy shit 
i dont even want a proper way, anything would work at this point
yeah because GIC emulation makes me angry
Infy first person to make better ACPI than windows confirmed
yeah i don't like the idea of virtualizing windows because ntoskrnl is stupid
wdym, like actually 3 separate interpreters?
Only ACPI.sys is a full on interpreter
But there’s two other spots that do stuff with raw ACPI tables.
Sleep is implemented in windows by checking stuff in Po, Hal, and ACPI.sys
I’ll try to document what does what but uACPI does massive amount of work here
And it booting at all is wild
Since win10 only uses modern APIC etc etc
how many ops/s does it get
40% done with rewrite/clean up so I’ll post it after
currently
Uhh let me grab
nice, im also nearing 1.0
will 2.0 be entire ABI break with uAPI?
but grass touching is taking my time
uacpi+windows before uacpi+linux is crazy
uapi will always be optional
OBOS faster than NT confirmed
yeah
obos faster than NT 
Confirmed
surely 
does nt suspend work with uacpi or is that a stub still
stub
ok new server nickname
ah
see, obos even has better suspend support than NT with uACPI 
obos superiority confirmed.
Do you want me to spend today fixing that 
suspend is pain
Then there’s modern standby
yet™️
waiting for uDRM
@slim panther
where's uWu
😡
when uNT

someone make uNT
reactos
same
Thanks to uACPI I’ve been able to process my WDDM reimplementation
port to nyaux
That’s funny

do u like pain
Actually my WDDM implementation will be MIT
are u a masochist
yes
Anyone here will be free to steal it
and I'll make sure to only use obos apis
to make it as hard as possible to port
u can steal the wddm impl and throw it in nyaux and u do all of the porting work

but I'll also make it public domain 
but no one will be able to understand the code

@jaunty fox iirc had a storport port
or implementation
whatever it's called
He’s getting WDDM
the drivers are funny tho, like you need the shared info page so unless you are actually trying to be windows compatible it might be a little weird
shared info page mentioned
well ig its its not that bad as long as you just don't have anything else at that address like I think linux has something in there
going back to sleep now
now I really gotta go fix fork

no you won't
the way to fix it is to not sleep in the middle of a day

ugh fine ill stay awake
can't wait until nyaux gets fork and he spends 7 weeks debugging it
did u override the naive uacpi mem* functions to use nt's ones tho?

no
damn it

I tried to start to implement frk yesterday too but then I just stopped after I realized I need to clone handles 💀
this women needs to give me nt memcpy 😡
who will win
Hobbies OSes or the trillion dollar cooperation who hasn’t given a crap about its os in a decade
who will when
luckily using uacpi's builtin ones is a free performance boost 
gl
gl
also I implemented timeouts + callstack depth checks in qacpi, changed op regions to actually map memory/io instead of implicitly needing the os to do it and now I am trying to debug Load lol
nice!
do tests pass?
the timeout/recursion related yes
nice
the loads don't because idk, there are some weird things with it including leaks
what's linux got there?
it may well do have something
F
kasan shadow memory, ig that doesn't really matter if kasan is disabled
Even my fork is half-broken on RISC-V
One one of two cloned threads works 
bill gay will lose
to what extent could that just be replaced by doing uacpi_table_find_by_signature etc? now im curious
yes
but that requires me patching a binary
since ACPI tables are linked in loaderblock
ah ok yeah
its unrelated to uacpi, depends on your firmware
if a table is not present on the system uacpi will return STATUS_NOT_FOUND
yes i mean this
uacpi_status ret = uacpi_table_find_by_signature("BGRT",&bgrt_pointer);
why it returns status not found on uefi systems ? (6)
maybe there is just no BGRT on that system?
show logs
in initialization it shows bgrt table
only list of tables from initialisation
in this list bgrt is exists
any other logs?
❌
gonna go out on a limb and say its a skill issue on your part
barely any information besides "it no work"
show code or logs
show code
wait
also any chance your memcmp is fucked?
i have disabled scheduling
earlyAcpiInit(); // uacpi_initialize(0);
printf("Early ACPI Initializied\n");
uacpi_table bgrt_pointer;
uacpi_status ret = uacpi_table_find_by_signature("BGRT",&bgrt_pointer);
if(ret != UACPI_STATUS_OK) {
printf("BGRT Table doenst present by your firmware (%d)\n",ret);
} else {
bgrt_table* bgrt = (bgrt_table*)bgrt_pointer.virt_addr;
printf("0x%p\n",bgrt->image_address);
}
so i dont think what memcmp can be pooped
how is memcmp related to scheduling ☠️
my scheduling is pooped and have incorrect context switching
also isnt uacpi have own memcmp
if u didnt override it, yes
what i need to send to you
why not
git submodule
i am know only git add git commit git push and git init
void earlyAcpiInit() {
early = 1;
uacpi_initialize(0);
}
U dont check for errors here
okay i think i need to check
void *uacpi_kernel_map(uacpi_phys_addr addr, uacpi_size len) {
uint64_t aligned_phys = ALIGNPAGEDOWN(addr);
uint64_t aligned_virt = (uint64_t)phys2Virt(addr);
for(uint64_t i = aligned_phys;i < aligned_phys + len;i+= PAGE_SIZE) {
pagingMap(phys2Virt(pagingGetKernel()),i,(uint64_t)phys2Virt(i),PTE_PRESENT | PTE_WRITABLE);
}
return (void*)aligned_virt;
}
this is wrong
i changed it
in code
i know
i dont know why git dont overwrited it
what did u change it to
void *uacpi_kernel_map(uacpi_phys_addr addr, uacpi_size len) {
uint64_t aligned_phys = ALIGNPAGEDOWN(addr);
for(uint64_t i = aligned_phys;i < aligned_phys + len;i+= PAGE_SIZE) {
pagingMap(phys2Virt(pagingGetKernel()),i,(uint64_t)phys2Virt(i),PTE_PRESENT | PTE_WRITABLE);
}
return (void*)phys2Virt(addr);
}
what does phys2virt do
did u forget to ctrl+s?
alt+f4
uacpi initializition doesnt return errors
im afraid its your allocator bug
// its most lazy alloc in the world
void* easy_uacpi_alloc(uint64_t size) {
if(!ptr) {
ptr = (uint64_t)pmmVBigAlloc(2048 * 2);
}
ptr += size;
return (void*)ptr;
}
also wtf
4096 bytes is not enough
its pages
this returns misaligned addresses
you dont saw upper message ???
wdym
ok
anyway as a quick fix for u
u can change this to like 128
then it wont use your buggy allocator for table storage
// its most lazy alloc in the world
void* easy_uacpi_alloc(uint64_t size) {
if(!ptr) {
ptr = (uint64_t)pmmVBigAlloc(2048 * 2);
}
uint64_t align_size;
align_size = (size + 7) / 8 * 8;
ptr += align_size;
return (void*)ptr - align_size;
}
now it aligned
uhmm maybe i need to find where it cant find table
and MAYBE i am shit itself
i literally told u how to fix it
ok
avoid goose allocator at all costs
my allocator is best in the world
also for just tables u can use uacpi_setup_early_table_access
i'll go to slep because it 11 pm for me
gn
I am starting to hate Load 💀 like I don't understand how some namespace nodes sometimes randomly get removed from the root node's children when I don't ever remove anything from there and in some of the other tests I get use after free because some frame after the load frame somehow uses a buffer allocated specifically for the load frame where the table is copied to (that gets freed when the load frame is destroyed)
I swear every time someone fixes their obos curse
it pops up somewhere else
3:08 PM
9 minutes later: memory corruption somewhere else
It's not fixed, it's sent to obos
oh right I can't just free the aml like that when the load exits 💀 then all the methods that it added are full of garbage
u should append the tables to the table list yeah
and also give the os the ability to override or deny this Load
what is ACPICA maintainer cooking 
he was going for a nice walk along the road to damascus
then all of a sudden, he found himself in love with the device tree instead
he has repented of acpi
lmao
was he released from the corvette thing?
or does ACPICA have different maintainer now?
The what
he smashed up a corvette and was arrested for it lol
lmao
yeah there was a reddit article about it
at first i didnt even believe it was him when fadanoid posted it
like what are the odds
infy when are you gonna smash a corvette?
when I buy one
I would imagine those are close to non-existent outside of US
then never ig 
also smashing your own car is probably boring
worked for mr beast views farming
where's the fun in not being chased by the law enforcement
RISC-V and/or ARM
Going from the virgin x86_64
to the chad RISC-V 
noob
you sure that ain't just padding to exactly fit ROM size?
idk but the table length is 0x00113489
fun fact, this is the hardest (in terms of mental capacity needed to understand whats going on) function in the entire uACPI code base:
static void bit_copy(struct bit_span *dst, struct bit_span *src)
{
uacpi_u8 src_shift, dst_shift, bits = 0;
uacpi_u16 dst_mask;
uacpi_u8 *dst_ptr, *src_ptr;
uacpi_u64 dst_count, src_count;
dst_ptr = dst->data + (dst->index / 8);
src_ptr = src->data + (src->index / 8);
dst_count = dst->length;
dst_shift = dst->index & 7;
src_count = src->length;
src_shift = src->index & 7;
while (dst_count)
{
bits = 0;
if (src_count) {
bits = *src_ptr >> src_shift;
if (src_shift && src_count > (uacpi_u32)(8 - src_shift))
bits |= *(src_ptr + 1) << (8 - src_shift);
if (src_count < 8) {
bits &= (1 << src_count) - 1;
src_count = 0;
} else {
src_count -= 8;
src_ptr++;
}
}
dst_mask = (dst_count < 8 ? (1 << dst_count) - 1 : 0xFF) << dst_shift;
*dst_ptr = (*dst_ptr & ~dst_mask) | ((bits << dst_shift) & dst_mask);
if (dst_shift && dst_count > (uacpi_u32)(8 - dst_shift)) {
dst_mask >>= 8;
*(dst_ptr + 1) &= ~dst_mask;
*(dst_ptr + 1) |= (bits >> (8 - dst_shift)) & dst_mask;
}
dst_count = dst_count > 8 ? dst_count - 8 : 0;
++dst_ptr;
}
}
And I didn't write it either, it was contributed by a member from the cherno server
It's used for accessing misaligned fields
that's indeed interesting lol
Isn't that the shit you did in GAS reads
And writes
Because I almost had a stroke reading that
its not used for GAS but for actual AML fields
do u have something similar in qacpi?
Who was it
well there is this for buffer fields but the normal field reading code is mostly just some aligning and memcpys https://github.com/Qwinci/qacpi/blob/main/src/interpreter.cpp#L4445
Ah so the tdb guy
tdb yeah
yeah i guess this is basically that probably
do u pass the ACPICA buffer field tests?
I don't think I have tried, unless they are the generated buffer tests that you also have?
are you supposed to invoke some specific method in that too?
MAIN
ah so its the same
yeah
i even submitted a patch to fix NT compatibility in these tests
so they work perfectly in uacpi
❯ /mnt/d/uacpi/tests/runner/build-linux-64bits/test-runner bfield.aml --expect int 0
[uACPI][INFO] RSDP 0x00007FFDD7ACF830 00000024 v02 (uOEMID)
[uACPI][INFO] XSDT 0x0000604000001090 0000002C v02 (Intel uTESTTBL)
[uACPI][INFO] DSDT 0x000062B000000200 000068A8 v02 (Intel Many )
[uACPI][INFO] FACP 0x00006120000004C0 00000114 v06 (uOEMID uTESTTBL)
[uACPI][INFO] FACS 0x0000606000000320 00000040
[uACPI][INFO] SSDT 0x0000000000000000 00000055 v01 (uTEST RUNRIDTB)
[uACPI][TRACE] load of 'DSDT' (OEM ID 'Intel ' OEM Table ID 'Many ')
[uACPI][TRACE] load of 'SSDT' (OEM ID 'uTEST ' OEM Table ID 'RUNRIDTB')
[uACPI][TRACE] [AML DEBUG] String => "TestRunner ID SSDT loaded!"
[uACPI][INFO] successfully loaded 2 AML blobs, 1395 ops in 12ms (avg 108953/s)
[uACPI][TRACE] initialized GPE block _GPE[0->128], 0 AML handlers (IRQ 0)
[uACPI][TRACE] initialized GPE block _GPE[128->256], 0 AML handlers (IRQ 0)
[uACPI][TRACE] fixed event 0 enabled successfully
[uACPI][TRACE] activated all 'EmbeddedControl' opregions controlled by '\ ', 0 _REG() calls (0 errors)
got a GPE
[uACPI][TRACE] activated all 'PCI_Config' opregions controlled by '\ ', 0 _REG() calls (0 errors)
[uACPI][INFO] namespace initialization done in 0ms: 0 devices, 0 thermal zones
[uACPI][TRACE] _STA calls: 0 (0 errors), _INI calls: 0 (0 errors)
[uACPI][TRACE] read from [\STRT.HDR_] (1 bytes) TableData[0x000062B000000208] = 0x2
[uACPI][TRACE] [AML DEBUG] String => "64-bit mode"
[uACPI][TRACE] [AML DEBUG] String => "Release of parent ACPICA code 0x1"
[uACPI][TRACE] [AML DEBUG] String => "Release of ASLTS test suite 0x16"
[uACPI][TRACE] [AML DEBUG] String => "Settings of ASLTS test suite 0x5"
[uACPI][TRACE] [AML DEBUG] String => "TEST (functional), Buffer Field"
[uACPI][TRACE] [AML DEBUG] String => "m211 test started"
[uACPI][TRACE] [AML DEBUG] String => "TEST: m211, Create 1-Bit Buffer Field:"
[uACPI][TRACE] [AML DEBUG] String => ":CTST:functional:bfield:m211:PASS:"
[uACPI][TRACE] [AML DEBUG] String => "m213 test started"
[uACPI][TRACE] [AML DEBUG] String => "TEST: m213, Create 8-Bit Buffer Field:"
[uACPI][TRACE] [AML DEBUG] String => ":CTST:functional:bfield:m213:PASS:"
[uACPI][TRACE] [AML DEBUG] String => "m215 test started"
[uACPI][TRACE] [AML DEBUG] String => "TEST: m215, Create 16-Bit Buffer Field:"
[uACPI][TRACE] [AML DEBUG] String => ":CTST:functional:bfield:m215:PASS:"
[uACPI][TRACE] [AML DEBUG] String => "m217 test started"
[uACPI][TRACE] [AML DEBUG] String => "TEST: m217, Create 32-Bit Buffer Field:"
[uACPI][TRACE] [AML DEBUG] String => ":CTST:functional:bfield:m217:PASS:"
[uACPI][TRACE] [AML DEBUG] String => "m219 test started"
[uACPI][TRACE] [AML DEBUG] String => "TEST: m219, Create 64-Bit Buffer Field:"
[uACPI][TRACE] [AML DEBUG] String => ":CTST:functional:bfield:m219:PASS:"
[uACPI][TRACE] [AML DEBUG] String => "m21d test started"
[uACPI][TRACE] [AML DEBUG] String => "TEST: m21d, Create Arbitrary Length Buffer Field:"
[uACPI][TRACE] [AML DEBUG] String => ":CTST:functional:bfield:m21d:PASS:"
[uACPI][TRACE] [AML DEBUG] String => "Run time (in seconds): 0x1"
[uACPI][TRACE] [AML DEBUG] String => "The total number of exceptions handled: 0x0"
[uACPI][TRACE] [AML DEBUG] String => "========= ROOT METHODS SUMMARY (max 600):"
[uACPI][TRACE] [AML DEBUG] String => ":STST:functional:bfield:m211:PASS:"
[uACPI][TRACE] [AML DEBUG] String => ":STST:functional:bfield:m213:PASS:"
[uACPI][TRACE] [AML DEBUG] String => ":STST:functional:bfield:m215:PASS:"
[uACPI][TRACE] [AML DEBUG] String => ":STST:functional:bfield:m217:PASS:"
[uACPI][TRACE] [AML DEBUG] String => ":STST:functional:bfield:m219:PASS:"
[uACPI][TRACE] [AML DEBUG] String => ":STST:functional:bfield:m21d:PASS:"
[uACPI][TRACE] [AML DEBUG] String => "========= END."
[uACPI][TRACE] [AML DEBUG] String => "TEST ACPICA: 64-bit : PASS"
[uACPI][TRACE] fixed event 0 disabled successfully
This is what I get
For a second I thought you said you sent a patch to NT
Lol
nah it was this lol: https://github.com/acpica/acpica/pull/923
and a similar function for writes just below
LAI doesn't exist anymore
qacpi warning: Ignoring DataRegion
qacpi error: Operation Region HDR_ doesn't exist
aml debug: TEST (functional), Buffer Field
aml debug: m211 test started
aml debug: TEST: m211, Create 1-Bit Buffer Field:
aml debug: :CTST:functional:bfield:m211:PASS:
aml debug: m213 test started
aml debug: TEST: m213, Create 8-Bit Buffer Field:
aml debug: :CTST:functional:bfield:m213:PASS:
aml debug: m215 test started
aml debug: TEST: m215, Create 16-Bit Buffer Field:
aml debug: :CTST:functional:bfield:m215:PASS:
aml debug: Run time (in seconds): 0x677afd72
aml debug: The total number of exceptions handled: 0x
aml debug: ========= ROOT METHODS SUMMARY (max 600):
aml debug: :STST:functional:bfield:m211:PASS:
aml debug: :STST:functional:bfield:m213:PASS:
aml debug: :STST:functional:bfield:m215:PASS:
aml debug: ========= END.
aml debug: TEST ACPICA: 32-bit : PASS
```  I should implement dataregion

wait why do u only get 3 tests
iirc LAI doesnt support e.g. 512 bit fields
right?
that u must read in multiple accesses
fields that require multiple mmio/pio/pci config space reads should work
i have lai built actually i can try running it against this test
there was an issue with Preserve writes where it would perform extra reads but other than that i think this works
and for that i have a pr open and i asked a person who reported an issue to test it and i got ghosted 
❯ ~/lai_tools/build/laiexec bfield.aml
unexpected opcode in lai_exec_run(), sequence 5B 88 48 44
[1] 19578 IOT instruction (core dumped) ~/lai_tools/build/laiexec bfield.aml
idk
wait u did? was that me?
no some other person reported a hang on real hw iirc
wtf is an iot instruction
maybe the data region being unimplemented somehow causes that? also the run time isn't correct
hmm lemme comment that out
abort()
ah that

