#uACPI - a portable and easy-to-integrate ACPI implementation
1 messages · Page 18 of 1
I am at home now
try it anyway
Where I have 4 more AMD machines

From different gens
do you have intel
yes
Though I can't find the charger for one of the lapptops 
but only intel
oh funny thing
obos stopped booting on my pc without an EC
it hangs after trying to init an EC
ah no thats unrelated
Are you sure it doesn't have EC if it tries to init it? 
there's an EC object actually
Try pmOS 
but it's bogus
actually nvm it was fine lol
Least batshit insane firmeare
when EC driver in astral
When I do my devices
it's not really a loadable driver
or one that I would make loadable
or discoverable through conventional methods
yes i remember your pc
could be in other SSDTs under the scope
just filled by the bios dynamically
Y not
well, it intertwines with uacpi init quite a bit
afaik you rather initialize it before namespace load or after namespace init, depending on how you discover the EC
before namespace load is when you have an ECDT
and after namespace init is when you don't have an ECDT
yeah
if you truly wanted to, you could add a config option to your kernel
to compile it out
how has my track record been
1 for 1 I think?
i think i've only reported one or two problems with u.ACPI and both genuine
yeah
it sounds like a lot of kernels' allocators are stretched to breaking point by uACPI and that provokes false reports
and locking primitives lately 
Sounds stupid
Astral survived both teste
Tests
tell that to linux
not me
if you had a penny for each time obos crashed because of uacpi in my 4th rewrite, you would be a billionaire
I hate rust
why
hahahaha 🤣😂 - i am a rust user
it smells stinky
i disagree
wow :(
i use rust because i like how it smells
it's just a tool
not because it's safe
i use rust because i don't have to think about the code i write
I use C because I like how it smells
the compiler is my slave
tbh everyone should learn rust just to understand how to write safe code
then just use whatever smells the best
everyone should be open to learn new things
i tried zig and hated it
i tried rust and love it
D
:D
the language?
the question is what you mean by "how to write safe code"
Yeah
you could do the same in Java or Haskell or ML
just use kasan and ubsan smh
i mean the borrowck mindset
smh just use runtime checks to fix compile time issues
whenever i write other languages i still think in rust
yes
idk how corrupting memory in my kernel is the compiler's problem tho
which is why my C++ kernel was pretty much rust-with-templates cuz the stdlib i wrote was very rusty
i don't intend to come across arrogant in the slightest with this statement, but i have found obsessing over scalability and good locking in keyronex a tonic that has quite changed how i see memory and safety
sure experience in that will affect how you see this
that's not arrogant
it's not arrogant to be more experienced
the problems of memory reclamation in single-threaded or crudely multithreaded code now seem completely trifling
acutally, having RCU at your disposal sometimes makes lifetimes easier, not harder IMHO
you can say that again
because a lot of times you can just say "i know that objects of this type are never going away while I work with them"
the first taste of it was the vm_page struct
since those always exist that makes life so much easier
and now just being able to make anything that exists not go away over some period of time - or even to make anything that exists, if the memory backing it ends up reused, be reused as the same type - that is powerful too (and that way is less overhead since it fits so naturally with a slab allocator anyway - just make the slab be deferred free)
@fiery turtle what is that? what type does it have exactly?
typedef struct uacpi_namespace_node uacpi_namespace_node;
i dont know what rust equivalent i should choose
opaque
i mean is it mutated?
is uacpi_namespace_node itself mutated or only to what it points?
forgive me rustc
The latter
so its safe to copy around?
is the same true for uacpi_object?
Yes
i see that it exposes reference counting, does that mean its allowed to be copied?
what do u mean by copied
again its a pointer
u can copy the pointer yes
stuff like uacpi_eval returns a uacpi_object* that is owned by the caller
the caller can unref it to delete or ref if it wants to share it
same goes for uacpi_object_create_*
i mean that i would allow the opaque type wrapper of uacpi_object to be cloneable which would increase the ref count
basicly Object.clone() would increase the ref count
this is a struct which contains a uacpi_object pointer which is invisible for the user
the user would get object and is free to clone/copy it, the Object implementation would update the refcount acordingly
pub struct Object(pub(crate) *mut uacpi_sys::uacpi_object);
i pressed enter before i was finished writing
as namespace_node doesnt expose refcounting there would only be one instance per pointer
its probably a good idea that i explain the wrapper to you once im finished so that you can catch stuff that i implemented wrong
yeah
is it correct that these two are identical?
UACPI_OBJECT_BUFFER_INDEX = 21,
UACPI_OBJECT_MAX_TYPE_VALUE = UACPI_OBJECT_BUFFER_INDEX
yea rust also doesnt like it if two fields in an enum have the same value
if its not needed i will ignore it else i would give it a different value and translate it
ye
so needed or not?
i bet 10 second after uacpi-rs is published someone will complain 
about what?
its a common C construct needed only for C
idk how you structured uacpi-rs but usually the normal thing to do is expose everything the headers expose with a machine generated -sys crate
if you do that there's no way anyone would complain but i don't know what that is used for
i would expose that as a constant
because that's what it really is
like const UACPI_OBJECT_MAX_TYPE_VALUE: Foo = Foo::ObjectBufferIndex or something like that
if it's needed that is, if it's not needed just expose it in the -sys crate as a constant which is what stuff like bindgen should do automatically
the bindgen exposes it as a const
using a enum in rust groups the values nicely together
uacpi on linux when 
i can't wait to see how linux scores
@fiery turtle would you be able to send a patch or your linux work?
unless you actually plan on finishing it
otherwise i wanted to look at it myself, but it looks painful to say the least
idk, maybe i'm just unfamiliar with how it's supposed to actually work
but the acpi_* functions are ujsed in a lot of places
i wasnt planning on actually integrating uacpi
that would take years
of literal time
oh lol
just implement kernel api and initialize it
alongside acpica
just to see the numbers
but yeah there's like a thousand different files using acpica API if u want to fully replace it with uacpi
yeah, i do wonder how painful would it be 
it would be kinda based tho
mainline running with uacpi instead of acpica
yeah... more than i am willing to put in lol
maybe less if u can make a smart script or something
by about a year
because a lot of apis are translatable 1 for 1
some are more complex but not all
but for getting the score i was going to just implement kernel api then call uacpi_initialize; uacpi_namespace_load
that would be enough
if i had to guess the "easiest" way to replace acpica would be to remove all the implementation and basically implement it with uacpi instead
u can mostly blindly copy acpica acpi_os_* implementation for that
but yeah just running using linux kernmel as testbench is good too!
i think i can do without patches in that case, unless you think that will greatly reduce the amount of work i have to do
maybe once its integrated into reactos and is successful + stable for a while that could be an idea to entertain
but it's not like i know linux at all so i'll be staring at the code for a while anyway
i mean full replacement
i wonder if that would actually be upstreamable
just imagine
booting your favorite linux distro™️
dmesg | grep -i uacpi
is uacpi compatible with acpica in terms of aml behavior?
i wonder if linux relies on the way acpica works, that sounds silly
--- a/Makefile
+++ b/Makefile
@@ -570,6 +570,7 @@ LINUXINCLUDE := \
-I$(objtree)/arch/$(SRCARCH)/include/generated \
-I$(srctree)/include \
-I$(objtree)/include \
+ -I$(srctree)/drivers/acpi/uACPI/include \
$(USERINCLUDE)
KBUILD_AFLAGS := -D__ASSEMBLY__ -fno-PIE
diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
index 40208a0f5dfb..379f6131bd41 100644
--- a/drivers/acpi/Makefile
+++ b/drivers/acpi/Makefile
@@ -31,6 +31,8 @@ acpi-$(CONFIG_ACPI_SYSTEM_POWER_STATES_SUPPORT) += sleep.o
acpi-y += device_sysfs.o device_pm.o
acpi-$(CONFIG_ACPI_SLEEP) += proc.o
+obj-y += uACPI/
+
Makefile in uACPI/
ccflags-y += -DUACPI_OVERRIDE_LIBC
ccflags-y += -DUACPI_OVERRIDE_TYPES
obj-y += glue.o source/
Makefile in uACPI/source/
ccflags-y += -DUACPI_OVERRIDE_LIBC
ccflags-y += -DUACPI_OVERRIDE_TYPES
obj-y += \
default_handlers.o \
event.o \
interpreter.o \
io.o \
mutex.o \
namespace.o \
notify.o \
opcodes.o \
opregion.o \
osi.o \
registers.o \
resources.o \
shareable.o \
sleep.o \
stdlib.o \
tables.o \
types.o \
uacpi.o \
utilities.o
nah it doesnt
uacpi would work just fine
that would be really cool ofc
if we can clearly explain the benefit of that and prove that it's better then definitely
include/uacpi_types.h:
#pragma once
#include <linux/kernel.h>
#include <uacpi/helpers.h>
typedef uint8_t uacpi_u8;
typedef uint16_t uacpi_u16;
typedef uint32_t uacpi_u32;
typedef uint64_t uacpi_u64;
typedef int8_t uacpi_i8;
typedef int16_t uacpi_i16;
typedef int32_t uacpi_i32;
typedef int64_t uacpi_i64;
#define UACPI_TRUE true
#define UACPI_FALSE false
typedef bool uacpi_bool;
#define UACPI_NULL NULL
typedef uintptr_t uacpi_uintptr;
typedef uacpi_uintptr uacpi_virt_addr;
typedef size_t uacpi_size;
typedef va_list uacpi_va_list;
#define uacpi_va_start va_start
#define uacpi_va_end va_end
#define uacpi_va_arg va_arg
typedef char uacpi_char;
#define uacpi_offsetof offsetof
/*
* We use unsignd long long for 64-bit number formatting because 64-bit types
* don't have a standard way to format them. The inttypes.h header is not
* freestanding therefore it's not practical to force the user to define the
* corresponding PRI macros. Moreover, unsignd long long is required to be
* at least 64-bits as per C99.
*/
UACPI_BUILD_BUG_ON_WITH_MSG(
sizeof(unsigned long long) < 8,
"unsigned long long must be at least 64 bits large as per C99"
);
#define UACPI_PRIu64 "llu"
#define UACPI_PRIx64 "llx"
#define UACPI_PRIX64 "llX"
#define UACPI_FMT64(val) ((unsigned long long)(val))
this is basically all I have
for uacpi_libc.h you'll wnat to just make sure everything is using the linux's super fast versions
i'll see how far i can get
for now i'm just compiling it with those changes and see where it errors out
drivers/acpi/osl.c has basically everything in terms of kernel_api.h
you just have to copy paste carefully
everything that starts with acpi_os_* is uacpi_kernel_ basically
well they have custom ones that arent actually referenced by acpica but whatever
also one quick question
why did you add the -D flags in both makefiles?
is there any reason behind this or just copy paste mistake?
maybe it was a skill issue but i had to add to both
yeah it is
binary semaphore == mutex, semaphore == event
spinlock -> mutex -> semaphore
no like in linux
acpi_os implements lock in terms of semaphore
and a mutex can be imlemented using a semaphore too
linux has a mutex primitive lol just use that
static DEFINE_MUTEX(acpi_ioremap_lock);
yeah i have no idea what im doing, ill take a look
example
same, i just know it has every locking primitive on the planet
so like i actually dont know what im doing
Elixir Cross Referencer - source code of Linux v6.12.6: include/linux/mutex.h
but i hope i can make it through
i didnt find a mutex acquire with timeout api
there was a patch series in 2020
maybe u should use semaphores instead then lmao
Elixir Cross Referencer - source code of Linux v6.12.6: drivers/acpi/osl.c
this basically already is a mutex
because they have ifs everywhere checking that unit count is always 1
if (!sem || (units < 1))
return AE_BAD_PARAMETER;
if (units > 1)
return AE_SUPPORT;
as long as initial_units is 1 this is a mutex
can i use pthread apis in the kernel ☠️
uacpi_thread_id uacpi_kernel_get_thread_id(void)
{
return (uacpi_thread_id)pthread_self();
}```
i was planning for that to be my get_thread_id
but i am afraid that might not work ugh
That's what I do
yeah but ur not linux
return current?
damn lol thats crazy
acpica has that kernel api as well
static inline acpi_thread_id acpi_os_get_thread_id(void)
{
return (acpi_thread_id) (unsigned long)current;
}
☠️
yup
even copilot knows
those who know
does timeout = 0 work the same for events as it does for mutexes?
cursed
the kernel api docs dont explain that
cool ty
0 => try_acquire
they already do
well i was asking because uacpi kernel api returns the flags
and there's raw_spin_lock and raw_spin_lock_irqsave
i was wondering which ones i should use ;D
makes sense
now the "worst" kernel apis are left uacpi_kernel_handle_firmware_request uacpi_kernel_install_interrupt_handler uacpi_kernel_uninstall_interrupt_handler uacpi_kernel_schedule_work uacpi_kernel_wait_for_work_completion
i wonder if i should try running without those
i mean i don't think they are needed during namespace load
i think of those only install_interrupt_handler is ran by uacpi_namespace_load on qemu/kvm
and i think it'll still work without it
very interesting
i'd do so wherever acpi_subsystem_initialize is currently being called
yeah
acpica has exact same api, u could just steal osl.c for it
with workqueues and stuff
effort
meanwhile i'm just trying to figure out how to get linux to compile with -march=x86-64-v2 to get rid of the popcount libgcc reference
and probably not needed 
wait u doing uacpi/linux as well?
trying to yeah
sorry i might sound dense, but where? lol
like before bus_register would be good?
like literally anywhere in that function at the bottom
this is right after acpica init
ok ill do it after the bus_register then
hopefully it wont breka nything
this is what i'm doing for init (bus.c)
figured i'd make acpica init fail since idk if they'd try to double init hardware
on qemu shouldnt matter
(probably)
i dont think QEMU's aml has global state that would interfere, but im not 100% confident
probably not but better safe than sorry
yeah
wonder how long linux compile would take with LTO
depends how many modules u have as -y
defconfig
idk if linux parallelizes init but if it does hydrogen will probably outperform it since on there uacpi has the whole vcpu to itself
during init at least
nah, this is fairly early init as part of subsystem initcalls
i think its single threaded
ld: vmlinux.o: in function uacpi_popcount': (.text+0x5de955): undefined reference to __popcountdi2'

yeah i just edited one of the makefiles to pass -march=x86-64-v2
i should really get rid of that __builtin_popcount
yeahh
its needed only for the aml countbits i think
proxima isn't affected by it since it uses clang for compilation but still
clang ships its own implementation for it?
lol thanks works :D
i think clang just doesn't use a builtin
it linked! 🎉
if popcount isn't available for the target it does it inline
qemu-system-x86_64 -kernel vmlinuz should work i think?
the command i'm using for testing is make -j12 && qemu-system-x86_64 -accel kvm -cpu host -kernel arch/x86/boot/bzImage -serial stdio -append "earlyprintk=ttyS0 console=ttyS0" -display none
nice
@left orbit u did the libc overrides and stuff right?
to make sure it uses the linux stuff
that would probably really bump the perf
lol
u mean bug_on(true)?
where is it getting this oom from, i'm logging all uacpi_kernel_alloc calls
mutex or spinlock
ohh
or event
right
yeah
because false means not a bug
ill call uacpi_init at the start of acpi_bus_init
or just do WARN_ON(1)
it didnt get called
how did u even manage to fuck that part up 💀
[ 0.426670] RSDP 0x00000000000F52B0 00000000 v00 (BOCHS )
[ 0.428618] ioremap error for 0x7fe2000-0x7fe3000, requested 0x2, got 0x0
[ 0.429566] ACPI: Unable to initialize uACPI
yoooo
oh i am retarded
result = bus_register(&acpi_bus_type);
if (!result)
return 0;```
i put it
after the return 0
lmao
maybe we should fork linux and make a branch with uacpi integration since thats pretty interesting
could start slowly carving away at acpica calls
that would be cool as fuck
yes 
thats with my shitty libc right?
i'd assume so, yes
nice
oddly precise 1705000/s
i copied that from acpica
uacpi_u64 uacpi_kernel_get_nanoseconds_since_boot(void)
{
return (get_jiffies_64() - INITIAL_JIFFIES) * (ACPI_NSEC_PER_SEC / HZ);
}```
i just realized the fn is called "since boot"
because my BUG_ON was inverted lmao
is it fine to just pass any timer
i did BUG_ON(!locked) in spinlock_free
no, uacpi will find out it's actually not since boot but since earlier boot and come to your house
[ 0.436317] RSDP 0x00000000000F52C0 00000000 v00 (BOCHS )
[ 0.438221] RSDT 0x0000000007FE22FC 00000038 v01 (BOCHS BXPC )
[ 0.440229] DSDT 0x0000000007FE0040 000020B4 v01 (BOCHS BXPC )
[ 0.441216] FACP 0x0000000007FE20F4 000000F4 v03 (BOCHS BXPC )
[ 0.444218] APIC 0x0000000007FE21E8 00000078 v03 (BOCHS BXPC )
[ 0.446232] HPET 0x0000000007FE2260 00000038 v01 (BOCHS BXPC )
[ 0.448240] MCFG 0x0000000007FE2298 0000003C v01 (BOCHS BXPC )
[ 0.450249] WAET 0x0000000007FE22D4 00000028 v01 (BOCHS BXPC )
[ 0.452570] FACS 0x0000000007FE0000 00000040
[ 0.455686] successfully loaded 1 AML blob, 1705 ops in 2ms (avg 852500/s)
[ 0.456373] unable to install SCI interrupt handler: unimplemented
[ 0.457216] event initialization failed: unimplemented
[ 0.461014] ACPI: Unable to load uACPI namespace```
damn, it's slower with linux ones
huh what lol
#pragma once
#include <asm/string.h>
#define uacpi_memcpy memcpy
#define uacpi_memset memset
#define uacpi_memcmp memcmp
#define uacpi_strcmp strcmp
#define uacpi_memmove memmove
#define uacpi_strlen strlen
#define uacpi_snprintf snprintf
#define uacpi_vsnprintf vsnprintf
i did that
basically
great question
ok yeah that timer is shit
[ 0.454548] successfully loaded 1 AML blob, 1705 ops in 0ms (avg 1705000000000/s)

fastest uacpi implementation
what did u change?
lies
¯_(ツ)_/¯
[ 0.458990] successfully loaded 1 AML blob, 1705 ops in 2ms (avg 852500/s)
[ 0.450287] successfully loaded 1 AML blob, 1705 ops in 3ms (avg 568333/s)
[ 0.452721] successfully loaded 1 AML blob, 1705 ops in 1ms (avg 1705000/s)
three consecutive runs
makes no sense for there to be so much variation
yeah not to mention its slow as shit
uACPI the new reference ACPI implementation
i kinda did because their mem* stuff is very fast
i dont think the speed of linux comes from it being really well optimized and shit
maybe it matters more in a hobby os? idk
damn linux slower than menix
if u look at the leaderboard thats like menix speed lol
Can I claim I have better timers than Linux? 
aboslutely not slower
maybe monkuous will have better results
linux is the fastest out there
with that magic touch
maybe menix slab is the same as the linux impl
this just means get_nanoseconds_since_boot returned the exact same value twice
lmao
i'm trying to fix get_nanoseconds_since_boot since for whatever reason ktime_get_ns is returning 0
and so is get_jiffies_64
i know the kernel has a time reference at time of init already because printk is printing time
yeah
yknow what i'm just gonna return __builtin_ia32_rdtsc()
lool
same shit
are u sure 1 tick == 1 ns?
as inaccurate as get_jiffies_64
i can tell qemu to make it so
that might be it
hmm
although i wonder what magical time api printk is using then
anyway: [ 0.070157] uacpi: 3: successfully loaded 1 AML blob, 1705 ops in 1ms (avg 1512953/s)
thats with libc overrides right
yeah
L
#pragma once
#define memcmp __builtin_memcmp
#define memcpy __builtin_memcpy
#define memmove __builtin_memmove
#define memset __builtin_memset
#define strcmp __builtin_strcmp
#define strlen __builtin_strlen
#define strnlen __builtin_strnlen
menix > linux
kvm clock is initialized at that point
[ 0.000000] kvm-clock: Using msrs 4b564d01 and 4b564d00
[ 0.000002] kvm-clock: using sched offset of 435683178 cycles
[ 0.001871] clocksource: kvm-clock: mask: 0xffffffffffffffff max_cycles: 0x1cd42e4dffb, max_idle_ns: 881590591483 ns
could also do vsnprintf etc
wasn't sure whether the linux versions were fully conforming
they are i think
with some extensions
is it possible that override libc is not propagated everywhere?
it is
adding the c flag in the makefile should be enough
should be
and if u dont do that?
oh wait i didn't prefix the things with uacpi_
lol
brain not working full speed today
1.5 with naive memcpy is fair
[ 0.067545] uacpi: 3: successfully loaded 1 AML blob, 1705 ops in 0ms (avg 3104283/s)
that seems more reasonable
indeed
i also wonder whether telling qemu to override the tsc frequency degrades speed
right behind managarm
probably
so i am going to get the real tsc freq from proxima and hardcode that instead
damn that rdtsc is nice
3792.961870 MHz
do u also build with LTO?
probably but i figured i wouldn't wait >1h for it to compile before making sure the kernel api works
fair fair
actually i might try and figure out how much i need to enable starting from tinyconfig to get the output
what is that?
tinyconfig is a preset that's just the minimum to get a working kernel
ohh
i wonder if a lot of other allocations including acpica are fragmenting the heap causing degraded perf
pretty sure linux does lto with default config
when i did BUG_ON in print i got a lot of noreturn warnings
i commented out acpica init
so i doubt it
maybe other subsystems as well ig
with hardcoded tsc frequency so that qemu can just pass through rdtsc to the host cpu:
[ 0.065107] uacpi: 3: successfully loaded 1 AML blob, 1705 ops in 0ms (avg 3120527/s)
didn't make a huge difference
yeah i guess its cheap then
makes sense considering there were a grand total of 2 calls
lol
tinyconfig time
dont break my hopes 
i really doubt it considering LTO is horribly slow with gcc
and linking didn't take >1h
...huh
with tinyconfig there's a significant performance regression
uacpi: 3: successfully loaded 1 AML blob, 1705 ops in 0ms (avg 2374152/s)
wonder what that's caused by
btw you might also be building with unconditional memory zeroing and stuff
or sanitizers
maybe
a lot of stuff that could be on by default
i know ubsan and unconditional zeroing is enabled for ubuntus
i really have no idea where to look in menuconfig for those things
ah this is enabled by default with tinyconfig
just use the arch config
its pretty good minus the terrible amount of drivers you have to build
didn't have a significant impact
yeah that's the problem, i'm trying to minimize the amount of stuff to build so that i can try LTO
uacpi is not allocator bound proved 
ok so that's not it
stack vars were zero-inited by default i imagine that had an impact
but none of the other zero-init stuff was enabled
config INIT_ON_ALLOC_DEFAULT_ON
bool "Enable heap memory zeroing on allocation by default"
depends on !KMSAN
help
This has the effect of setting "init_on_alloc=1" on the kernel
command line. This can be disabled with "init_on_alloc=0".
When "init_on_alloc" is enabled, all page allocator and slab
allocator memory will be zeroed when allocated, eliminating
many kinds of "uninitialized heap memory" flaws, especially
heap content exposures. The performance impact varies by
workload, but most cases see <1% impact. Some synthetic
workloads have measured as high as 7%.
this one maybe
yeah that one's disabled
disabling this got it to 2.7M
makes sense
im compiling with -O3 -march=native -pipe with clang thinlto
i really have no idea what the rest could be since the only kernel api functions i had to implement are incredibly basic
lets see how bad it is
oh god does linux even work with -O3?
@gentle peak can i have the command line you're using to do rdtsc?
we're about to fdind out 
-cpu host,tsc-frequency=1000000000
god my pc is dying
linux doesnt work with anything other than O2
thanks'
Astral better than linux astral number one best os
yknow what i'm just gonna remove stuff from defconfig instead of adding to tinyconfig
fair
lmao
Soon
any bets on how long it'll take to link with lld? :^)
thinlto
idk waht that means but
it definitely is doing something
judging by it hogging up an entire code for whatever it's doing
mining crypto or whatever
oh god the final stage of lto is single threaded?
i think so lmao
i believe 🙏
it went full blast for like 20 seconds and now its stuck on a single thread
IT DID IT
oh btw proxima was up to a consistent 5.0-5.2M/s at some point but it's now around 4.8-4.9M/s
link takes about 2 mintues 
[ 0.360596] RSDP 0x00000000000F52C0 00000000 v00 (BOCHS )
[ 0.362528] RSDT 0x0000000007FE22FC 00000038 v01 (BOCHS BXPC )
[ 0.364499] DSDT 0x0000000007FE0040 000020B4 v01 (BOCHS BXPC )
[ 0.365495] FACP 0x0000000007FE20F4 000000F4 v03 (BOCHS BXPC )
[ 0.369574] APIC 0x0000000007FE21E8 00000078 v03 (BOCHS BXPC )
[ 0.370500] HPET 0x0000000007FE2260 00000038 v01 (BOCHS BXPC )
[ 0.372585] MCFG 0x0000000007FE2298 0000003C v01 (BOCHS BXPC )
[ 0.374644] WAET 0x0000000007FE22D4 00000028 v01 (BOCHS BXPC )
[ 0.375497] FACS 0x0000000007FE0000 00000040
[ 0.378258] successfully loaded 1 AML blob, 1705 ops in 0ms (avg 2857324/s)
[ 0.380480] unable to install SCI interrupt handler: unimplemented
[ 0.380496] event initialization failed: unimplemented
[ 0.383523] ACPI: Unable to load uACPI namespace```
meh that's shit
daamn, what happened tho?
really not sure
well u were at 1.5 before right
also , it works with -O3? :^)
i didn't pay attention to perf for a while because i use tcg while developing
and like 20 commits and a few uacpi updates later i checked again
don't know what exactly caused the regression
if anybody wants to give the image a go
qemu-system-x86_64 -M q35 -kernel arch/x86/boot/bzImage -enable-kvm -serial stdio -append "earlyprintk=ttyS0 console=ttyS0" -cpu host,tsc-frequency=1000000000
perhaps just me adding missing locking? 
big
i'll test later but how do you get the kernel to compile with lto and -o3?
wanna test with my kernel api impl
make LLVM=1 KCFLAGS="-O3 -march=native -pipe" -j26
qemu-system-x86_64: warning: TSC frequency mismatch between VM (1000000 kHz) and host (3600010 kHz), and TSC scaling unavailable
qemu-system-x86_64: kvm_init_vcpu: kvm_arch_init_vcpu failed (0): Operation not supported
also make LLVM=1 menuconfig
then go into general architectue blah blah blah
and enable lto
i dont think it can do lto with gcc, there were no options in menuconfig without LLVM=1
so you'll have to recompile with llvm
WSL2 loses again i guess
oh, im on wsl2
hmm then idk lol
Its some cpu specific bullshit
i'm gonna use -j20 even though i only have 16 lcpus wish me luck
im on i9 9900K
Hyperv likes some cpus and dislikes others
oh great this isn't valid on clang
-fno-builtin?
-fno-builtin just means that it doesn't translate x() to __builtin_x()
oh i see
that linked really quickly wtf is it even using lto
it's now 3.5M/s vs 3.2M/s so maybe?
well whatever
i'll test your image
this image is only 600k-800k on my machine somehow
if it does it's negligible
-smp 4 is still in the 3.4-3.6M/s range
i guess doesnt matter
I need proof
would be fun to do isolcpus=1,2,3,4 and then pin qemu vcpus there
see how perf changes with exclusive vcpu pinning
i wonder...
tf
oh god turning lto off is a full rebuild?
wtf
but then again you didnt measure proxima that way and got 5m anyway
because object files are llvm bytecode for LTO
[ 0.114300] successfully loaded 1 AML blob, 1705 ops in 2ms (avg 783966/s)
lol
actually, smp on my end is super influential
pmos speeds
oh no i wasn't wondering about that, what i was wondering about is that proxima's perf actually slightly degrades when i'm using -accel kvm -cpu host,migratable=off because it can then get the tsc frequency from cpuid, skip calibration and get to uacpi init so quickly that linux hasn't increased the cpu freq of whatever it's running on or whatever
-smp 1 yields 1.8mil on menix, but -smp 2 yields 700k
whereas if i just use normal -accel kvm -cpu host it calibrates for 500ms during which, from linux's perspective, qemu's utilizing 100% cpu
better than obos speeds
which tbf without smp enabled are a lot faster than what they were before
i was wondering whether something similar could be applied to linux here
ohhh
yeah
okay this is weird
[ 0.116306] successfully loaded 1 AML blob, 1705 ops in 0ms (avg 2601524/s)
rerun
are u on a laptop?
nah, ryzen 5800x
i mean marvin
oh
7700X desktop
it's only on the first ever boot up
let's see
[ 0.115882] successfully loaded 1 AML blob, 1705 ops in 0ms (avg 2621600/s)
yea seems stable
2.6m
what is blessing my eyes rn
cpu warming up before the benchmark
okay i'm pretty sure this is getting optimized away even though the asm is volatile
either that or my threshold is wrong
::: "memory"?
multiplying the threshold by 10 first because there's no way i'm missing a 5s delay
yeah ok i just wasn't noticing it
didn't have a noticeable effect on uacpi perf though, damn
damn
for reference: proxima when doing tsc calibration (aka 500ms of 100% cpu usage) gets 4.8-4.9M/s. when not doing tsc calibration, it gets 3.7-3.8M/s
@gentle peak do you do irq handlers?
in the linux kernel api? no, but i print whenever the function gets called, and it isn't called until after the benchmark
in proxima yeah
i was curious about your linux api
the key to improving performance is to just do less
it's simple, and it's enough for my purposes
yeah
i wonder how it scales tho
im definitely stealing this when i get back to actual osdev
like, smp scaling? probably similar to any other allocator that doesn't have magazines
or even threads, since it doesnt have lockless fast paths etc
true but it doesn't do much work while holding a lock
yeah
iirc lockless stuff tends to be slower on single-cpu machines
why does it need a mutex there, wouldnt a spinlock be enough?
astral uses kvm clock by default sooo 
mutexes are faster than spinlocks
so if it doesn't need a spinlock it gets a mutex
same speed actually
or are we talking uncontended cases
spinlock without disabling irqs is 1 CAS, mutex is 1 CAS
if it's contended any kind of spinlock is usually slower especially on single cpu machines
yeah
whereas for mutexes it would just block the thread
a spinlock that does sched_yield instead of cpu_relax would be somewhere in the middle i believe
but still worse than a normal mutex
no problem, that's why it's MIT licensed
which is why my mutex sucks, its based out of the semaphore 💀
and why I am gonna use something else soon enough
any plans to make it numa aware?
not really
[ 0.926961] RSDP 0x00000000000F52C0 00000000 v00 (BOCHS )
[ 0.927269] RSDT 0x0000000007FE22FC 00000038 v01 (BOCHS BXPC )
[ 0.928269] DSDT 0x0000000007FE0040 000020B4 v01 (BOCHS BXPC )
[ 0.929272] FACP 0x0000000007FE20F4 000000F4 v03 (BOCHS BXPC )
[ 0.930273] APIC 0x0000000007FE21E8 00000078 v03 (BOCHS BXPC )
[ 0.931267] HPET 0x0000000007FE2260 00000038 v01 (BOCHS BXPC )
[ 0.932269] MCFG 0x0000000007FE2298 0000003C v01 (BOCHS BXPC )
[ 0.933266] WAET 0x0000000007FE22D4 00000028 v01 (BOCHS BXPC )
[ 0.934288] FACS 0x0000000007FE0000 00000040
[ 0.936003] successfully loaded 1 AML blob, 1705 ops in 0ms (avg 2834533/s)```
at least not in this rewrite
final score, i am not going to try anymore
me?
yeah
this rewrite is basically meant to just be "get me a simple kernel that lets me develop userspace, won't even support smp, i'll switch it out for a proper one later"
it does the funny rdtsc warmup
maybe it would be faster on monkuous' cpu
idk if it actually makes any difference
seems like it doesn't because linux apparently does enough work pre-acpi init that it effectively does the same thing as warmup
https://gist.github.com/48cf/32736b0a6e01ec7510454c39acf3e711 my kernel api for anyone curious
what are your plans as far as userspace?
nothing concrete, probably just "indistinguishable from standard linux except NIH"
you also do malloc for io_map
which probably takes a bit of your points
like even abi stuff?
oh no not abi
ah
yeah true, i was thinking about properly implementing a bounds check but i gave up because i was like "meh"
ill change that real quick and see if it makes a difference
the kernel won't even have a true stable abi
my plan is to make a vdso-like thing be the only stable way to do syscalls
wait unmap is a no-op 💀
nice
a jit-like vdso
that's what windows does right
ntdll.dll
yeah
memory unmap? yeah
ntdll is not exactly a vdso
1.7M/s
oh
meh
it does this weird thing where its either hhdm or actual mapping
and i didnt know how to properly do unmap for that lol
its probably easy but yeah idk
nope it does get to the ioremap
@gentle peak can you dump your api impl as well?
oh its because of your is_ram check probably
3271792/s with proper iomap :D
yeah, acpica does that too
ah
nice
static void acpi_unmap(acpi_physical_address pg_off, void __iomem *vaddr)
{
unsigned long pfn;
pfn = pg_off >> PAGE_SHIFT;
if (should_use_kmap(pfn))
kunmap(pfn_to_page(pfn));
else
iounmap(vaddr);
}```
their unmap can do that
because it takes a pg_off
whatever that means
i think i indirectly use that exact method
since my uacpi_kernel_{map,unmap} just call acpi_os_*
loool
not the most familiar with linux's kernel internals and i figured that that'd be the easiest way to make sure it worked
what the hell did u pass to unmap as the physical address
u dont even get one from uacpi
the function you sent is an internal one for the osl layer

and i assume it eventually calls acpi_unmap
ah they just keep a list of mappings
they have a cache yeah
tracked down part of the cause: if i comment out the part of my allocator code that gives free pages back to the pmm it gets back up to 4.9-5.1M/s
I can update the score later if you'd like
it’s still at 4.6
too small of a difference to make me really care about it, and the giving empty pages back to pmm thing is desirable behavior, so i won't be permanently removing it, but nice to know where it came from
Do you think it’s possible to squeeze out more?
if there are more scores to be updated or something feel free to update mine as well but i don't really care about whether such a small difference is recorded
infy can you update my score:
[uACPI][INFO]: successfully loaded 1 AML blob, 1705 ops in 1ms (avg 1371085/s)
Im recording them for later to update in batches
ah ok
Sure
2s let me get a real sample
The rules are all API must be implemented fairly, q35 + kvm
Everything else is up to u
after i get this bug fixed i might make uacpi run in a thread 
kentry thread anyway
i have no way of communicating with other threads atm
morse code

block threads for specific periods of time
Kid named Morse
the cpu is Intel i5-4590T
btw
Noted
although I still don't beat anyone yet
I will at least be far from being beaten by nyaux
(the total disgrace in osdev)
Inb4 nyaux fixes skill issues and gets 10M
this would be me if nyaux passes me /j
But im curious about this
updated my kernel api gist, no unimplemented stuff
but im not too sure about how correct it is
Nice, we should really make a fork
but not like it matters
To at least store it for testing
that would definitely be cool
is it finally happening
Ill make one
is linux getting uacpi support
Kinda
Can you upload everything you have to a branch in your local fork perhaps?
i can make a patch one sec
with the iso image from https://github.com/proxima-os/proxima/actions/runs/12537199433
uacpi: info: successfully loaded 1 AML blob, 1705 ops in 0ms (avg 6406643/s)
Or I guess u have makefiles in a submodule dir hmm
oh i don't have a submodule 
Crazy numbers
i just downloaded a tarball of uacpi and extracted it
with my current unpushed code i get 5,063,043/s but i feel like that's a bit cheating since the heap shrinking is commented out
(aka stuff <PAGE_SIZE doesn't get returned to pmm)
Sort of I guess, since u dont wanna be leaking pages
U mean >?
no, <
Oh
PAGE_SIZE gets handled by a different allocator, that one still gives back memory
@fiery turtle is a patch okay?
I see
Sure
Lol
then again i don't think that allocator gets used by uacpi at all since my PAGE_SIZE is 16k
Waaait
Why 16k
wanted to make sure everything could handle PAGE_SHIFT not matching what the architecture expects so i just picked something at random
for "our" usecase it's probably okay to add a submodule in the root of the repo and symlink source + include into drivers/acpi/uacpi
Ah good idea
Lol
Perhaps
that gets rid of the "makefile in submodule" problem
Yea
at the expense of "fuck windows users" but not like ur compiling linux on windows anyway
U cant even clone it on windows
good

anyway if you do fork linux i can do the dirty work of submodule + adapting this patch for that i guess
Where shall I put it
Sure ill do that first thing tomorrow
U can make a local fork right now with those changes then pr into my fork if you wish
figured it out:
KERNEL_STACK_SIZEis still 16k, so the kernel stack of the init task was allocated withvmalloc_largeinstead ofkallocas it was whenPAGE_SIZEwas 16k- the size given to
vmfreewhen freeing said stack was the size of mytask_tstruct instead of that of the stack itself, so it was freed withkfreeinstead ofvmfree_large
i will do that yes

this worked before because kfree unlike vmfree doesn't take size as param
anyway has no bearing on uacpi benchmark thankfully
Oh nice
So you've uncovered a bug?
I should adapt a dumb page size idea as well
For my stuff
Like Linux does with jiffies
Setting initial to random values
uacpi benchmarks
- PAGE_SIZE 4k:
4 560 359 - PAGE_SIZE 16k:
4 794 861
not too significant of an impact
Probably because u get buckets for smaller allocations instead of going into the pmm?
going into the pmm is pretty fast actually, but for >PAGE_SIZE i don't just go into the pmm, i go off of the hhdm entirely so i need to allocate a virtual address and map it
demand paging isn't used for kernel memory so doesn't really apply
but yeah it's the equivalent of prefaulting
ok epic back to where we were but now with a submodule
[ 0.376604] successfully loaded 1 AML blob, 1705 ops in 0ms (avg 2818167/s)
Very nice
Wellll nt does that a lot right
nt yeah but hydrogen doesn't and won't
Fair lol
the idea is that if you're calling into vmalloc_large a lot you're probably doing something wrong anyway
Why _large?
it's only used for >PAGE_SIZE
Is there a small equivalent
there's normal vmalloc which decides whether to use kalloc or vmalloc_large based on the size given
basically:
- you use
kallocwhen you need power-of-two alignment or easy mapping to paddr - you use
vmallocanywhere else
How does vfree know where to go
it's a sized free
Or well struct page I guess
Ah
nah struct page is only used for kfree since with vmfree the pointer might not be in hhdm
U can vfree less than u malloced?
no the size still has to match
hacker@raptor:~/sources/linux$ git pull origin master --depth=1
remote: Enumerating objects: 39, done.
remote: Counting objects: 100% (39/39), done.
remote: Compressing objects: 100% (14/14), done.
remote: Total 20 (delta 19), reused 6 (delta 6), pack-reused 0
Unpacking objects: 100% (20/20), 2.76 KiB | 201.00 KiB/s, done.
From https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux
* branch master -> FETCH_HEAD
fatal: mmap failed, check sys.vm.max_map_count and/or RLIMIT_DATA: Cannot allocate memory```
holy 🔥
i just figured that for a lot of purposes the size is known at compile time even for free
Why require that?
so making it a sized free allows for LTO to optimize vmfree into a direct call to kfree
Lmao
Ohh
i haven't actually measured what impact uacpi's sized frees option has on perf
since my uacpi glue code emulates a non-sized free
Its probably worse because uacpi has to calculate it in some cases
Even strlen sometimes
oh wow
i might add another allocator that delegates to vmalloc/vmfree but doesn't have a sized free in case things like that pop up elsewhere in the kernel
won't do it until i need it but still
Fair
hm so sized frees+LTO would speed up most cases a tiny bit and slow down rare cases a lot
probably not worth it
