#uACPI - a portable and easy-to-integrate ACPI implementation
1 messages Β· Page 15 of 1
lol
what do i pass to table_find
"HPET"?
doesn't work
show code
i should maybe just return rdtsc
@slim panther
kvm_clock to convert tsc to ns
_by_signature
uacpi_table_find_by_signature
ah
https://github.com/rayanmargham/NyauxKC/blob/master/kernel/src/timers/hpet.c some reference code from nyaux if u need it
wait and how do i convert this to the actual table
panic("The Nyaux Kernel does not support Devices without a HPET\nThe "
"Reason for this is becausei hate tsc with a burning desire. pr in a "
"different calibration timer if u want one so bad lol");```lol
i have the best spelling
is there a hpet_table struct?
π‘
acpi.h
acpi_hpet
wait why did i say devices
was i on a sleep tablet when i wrote that
π
were you high when writing that
no
but the sleep med i take before i go to sleep
gives me a eurphoic response as a side effect
before it makes me sleepy
hpet works but tsc + kvm_clock is lightning fast and accurate
im cold
im hot
i am actually hot tho
yeah
i started wearing a heavier tshirt than usual
and it doesn't take much for me to start feeling hot
i think so
play co-op with me
no i need to wire this hpet thing in
Look at obos code, if you dare https://github.com/OBOS-dev/obos/blob/userspace-work/src%2Foboskrnl%2Farch%2Fx86_64%2Ftimer.c
does uacpi have a stripped down version that only contains the table api? i want to put uacpi in userspace but need some tables at boot and dont want to have uacpi two times
well early_table_access mode exists, which only needs map and unmap, but there isn't a mode which removes references to other apis
i had that feature idea for later
its still a bit until i need uacpi, maybe by the time thats supported
right now u can stub out all other api to just be unimplemented and it will work fine technically
if you use LTO it will probably remove all other code
does uacpi move the tables or just copies them to an internal buffer?
neither
the internal buffer stores state needed to access those tables
like the virtual address where they're mapped, reference count etc
so it preserves the tables in memory?
yeah
so that two instances could access it
yeah ofc
is 100MHz the right hpet freq for qemu?
idk about mhz but for nanoseconds for me its 1 hpet tick per 10ns
@fiery turtle success! need to impl the rest
nice nice
yes
ty
bro good thing i decided to integrate uacpi into linux
it found actually important warnings
like functions that should be static not being static
but you do have spinlocks right?
yeah
lmao how
wdym how?
what if you take a spinlock instead of a real mutex acquire
Mint secretelt has a phd
whats your allocator
as i mentioned above, my kernel panics if you try to take a spinlock with ints enabled
it's a really simple bitmap allocator, actually
it's the most simple C memcpy ever lol
something seems not quite right
^
i am returning time like this, idk, maybe it's an issue? c uacpi_u64 uacpi_kernel_get_nanoseconds_since_boot(void) { return hpet_read_counter() / (1000000000 / hpet_frequency); }
hpet_frequency is in Hz
read_counter() reads the main hpet counter straight from mmio
...
it is
i think
what's the issue?
your calculation seems to be a little bit off
yuh
yeah
your clock runs 100 times fast
how come
uint64_t counter_clk_period = tmp >> 32;
hpet_frequency = 1000000000000000 / counter_clk_period;```
i use this division
thats wrong
yea
then it's right?
huh
i think this timekeeping logic is off
it's volatile
okay
yeah but how?
the correct way to calculate it is hpet_ticks() * ticks_per_ns
^
ticks_per_ns = 1e9 / freq_in_hz
this is what i also do
so the correct value is hpet_ticks() * 1e9 / freq_in_hz
ld: (.text+0x6331f3): undefined reference to `uacpi_kernel_free'
ld: (.text+0x633205): undefined reference to `uacpi_kernel_free'
ld: (.text+0x633216): undefined reference to `uacpi_kernel_free'
ld: (.text+0x633223): undefined reference to `uacpi_kernel_free'
ld: (.text+0x63337a): undefined reference to `uacpi_kernel_alloc'
ld: vmlinux.o: in function `uacpi_free_namespace_node_info':
(.text+0x6334aa): undefined reference to `uacpi_kernel_free'
ld: vmlinux.o: in function `uacpi_device_matches_pnp_id':
(.text+0x633550): undefined reference to `uacpi_kernel_free'
ld: (.text+0x633578): undefined reference to `uacpi_kernel_free'
ld: (.text+0x633585): undefined reference to `uacpi_kernel_free'
ld: vmlinux.o: in function `uacpi_get_pci_routing_table':
(.text+0x633a75): undefined reference to `uacpi_kernel_alloc'
ld: (.text+0x633bd1): undefined reference to `uacpi_kernel_free'
ld: vmlinux.o: in function `uacpi_free_pci_routing_table':
(.text+0x633dea): undefined reference to `uacpi_kernel_free'
ld: vmlinux.o: in function `uacpi_free_dynamic_string':
(.text+0x633e1a): undefined reference to `uacpi_kernel_free'
oh my god
now to implement these
this is just kernel api not implemented
i know
uACPICA when
i have this lol
return hpet.regs->main_counter * (hpet.period / 1000000);
im not saying oh my god to that
yeah that also works
though i'd calculate hpet.period / 1... statically
the best way to do it is to do what i do iirc
drivers/acpi/uACPI/source/utilities.c:931:26: error: no previous prototype for βfind_one_deviceβ [-Werror=missing-prototypes]
931 | uacpi_iteration_decision find_one_device(
| ^~~~~~~~~~~~~~~
This warning should really be enabled everywhere
or actually idk if i do it
Just use kvmclock and get a free nanosecond clock 
FINALLY BACK TO EARTH
that seems a lot more accurate

NYAUX IS CLOSE TO YOU
not sure
do a 1 second wait and printf in an infinite loop
HEAR ME ROAR MINT NYAUX WILL DESTROY CYNIX INTO THE GROUND
seems a bit low
i will submit a benchmark later
theres no way you are doing 5 million though
^
i mean i am also surprised if i do 5 mil
but 50k seems a bit low too lol
both values seem off
no u deserve that spot
with a bitmap allocator its imaginable
yeah i'd assume thats why its slow
menix has phd memcpy
show
its also likely not optimized for small copies
will when I'm home
dw im gonna steal memix's

its a phd memcpy so it must be good
also lets go pitust shitos 10000 uacpi race edition
how do i make an iso again
just add an if and do a simple byte loop for small ones
bye
Cya
no its completely accurate this is cope 
if statement adds more cycles π‘
it doesn't really matter
what if statement should i check for how big of a count
though tbf the rep overhead for small copies doesn't likely matter that much anyway
no i want phd memcpy in nyaux
so
anwer
anwer
bro i cannot spell
help
Just rely on memory being already initalized with the values you want and panic otherwise
idk I don't remember, you could test it yourself with gbenchmark
probably something around 128 or whatever
ill js wait for mr marvin to come home and to steal bros memcpy 
easy
rep movsb and a faster allocator fixes that
hes saying ur coping

basically
i know your step 1.5 of adding 10 memory corruption bugs

well i was gonna say step 0.5 is to make a 16 bit bootloader and calling it your operating system then ask in #osdev-misc-0 how to make windows
everyone had that phase ngl
or ask chatgpt to generate ur entire kernel

fair
Obos does though?
π‘
Stable
Stable enough
Rather
Doesn't crash when you blow on it once
Only when you mess with code that you shouldn't mess with
Or mess with code with // Abandon all hope, ye who enter here
π‘
i think most submissions are now done so I'll probably close the initial list in like 3-4 hours
lmfao rust's shitty compiler-builtins doesnt support __popcountdi2 because its not called by llvm apparantly?
lmao
seems to line up with my findings on clang, it generates inline code for the popcnt builtin
(when its not supported natively, if there is the popcnt instruction then it will use that)
oh huh
interesting
i just called rust count_ones
which doesnt generate the call
i think
hopefully lol
okay
i now have uacpistub os
that could actually be very useful
lol torture test
why rust @loud ice
he wants his os optimized out
when the compiler inlines everything into a single function
because
i mean that is the definition of performance :^)
least schizo rust code
but mah new allocator that I'm definitely not procrastinating writing!
It will make my score surpass managarm!
i can wait for a bit if you're actually serious
u can always add in the updated score later
but if u actually finish it today ill add it
If I switch to a bump allocator for uacpi and I get better perf can I use that as my score /hj
I wonder if its possible to somehow hack it so uacpi will have an arena
i mean if u make a private heap for uacpi probably
well, some things change global context
Wassan arena
I guess not really, since anything changing the namespace will have to be kept
yea
lmao
osdev teams up to get obos to be faster than managarm
microsoft with 1B dollar sponsorship to get obos to 5M/s
just run it on a good enough computer 
I think most people have a stroke reading obos code, unfortunately
And so do I
I avoid reading most obos code
lol
Big
I think my "worst" code is my page allocator mostly because originally it had fine-grained locking but then I just slapped a giant lock over the whole thing after I realized there were issues with the locking
but otherwise its fine I think
My worst looking code is probably everything
My biggest issue is vmm and mutex probably
If I had to choose one thing I'd look into the pf handler, which works, but the code is messy
Actually, it's the x86_64 entry code
In the part that loads kernel symbols into a tree
I like this part of my kernel 
Uh oh
jump to higher half + stack pointer adjust for hhdm
lmfao
wait
what
oh
ohhhh
but why
this is maximum ub
unless arch_start is an assembly self-relocator
I'm pretty sure there's a double-release bug here
don't see how it could be an issue in my kernel, but can anyone confirm? seems like it happens if uacpi_kernel_install_interrupt_handler unconditionally returns an error
the way it works is that I rely on the compiler generating relocation-less pie code with -fno-PIE for the entry code (before that asm) and the base of the kernel is set to higher half in the linker script so the functions/globals after that are at the correct addresses
If this is the qemu blob, then I am pretty sure I assert stuff like that in my mutez
*mutex
Wait I don't
uuuuuuu
thats
bad
whatever i'm back
I just return success if the lock is already released
No the blob loads fine, the timing info is printed earlier, this seems to happen because my uacpi_kernel_install_interrupt_handler returns UACPI_STATUS_UNIMPLEMENTED
Can u get a backtrace of where its called from?
it works tho, idk if there would have been any other way to do it without needing a prekernel
The panicking release?
This one has all the line numbers
the hpet counter increments by 1 billion a second, so it's not 100MHz so it's off by 10
anyway this is unrelated to uacpi, maybe go to #1097930216032178276 for the reply if you want lol
so it's not cope
i wouldn't say that yet
but i believe so
i need to make sure i am doing time properly
anyway, i'm pretty satisfied with this performance considering i started this kernel rewrite literally today
500k sounds fine i think
That's quite decent
Wanna get added to notable projects?
@fiery turtle am i allowed to call the handler immediatly in uacpi_kernel_schedule_work?
poweron and poweroff state are the same so optimize everything out
Ofc
assuming im not in an irq context
ok i don't think it's off, i think i got it wrong, it's actually 50k/s lol
did you do the "spin in a loop for 1 second worth of hpet ticks" thing
i am just printing it over and over and it does 1 billion ticks per second
I think I designed it specifically so lazy impl like that should work
Nah, the source isn't public yet and won't be for a while
Ah ok
it actually makes me wonder if @median crest could do the same and verify if it's the case for him as well
that it does 1 billion ticks a second
So yeah its probably the bitmap holding you back
Nope the other way around
so how do i make it use my memcpy
Take a look at libc.h
tedium
why not ship a hyper optimized memcpy 
Indeed
do i really have to do -Duacpi_memcpy=memcpy???
you add -DUACPI_OVERRIDE_LIBC and create an uacpi_libc.h somewhere in include path where you do (for an example) ```c
#define uacpi_memcpy __builtin_memcpy
#define uacpi_memset __builtin_memset
^
π
What lol
Taking suggestions
like i wouldn't provide the impls at all
everyone should realistically have those functions anyways
yeah
its also forbidden to not have those functions afaik
because gcc/clang will call them anyway
the mem* ones yes
Maybe but whenever I want to port uacpi its annoying af to implement all missing ones
for memcpy on gcc i believe theres some funny meme you can do
then at least do that for the mem* ones
Id rather have my own trusted ones by default than have some beginner complain about uacpi bugs
aren't you forced to have memcpy for struct derefs?
because
my_struct = *struct_ptr;
invokes memcpy
imo you should default to calling memcpy anyway
Yup
you know what may slow down my impl
a lot
the fact that i memset allocations to 0 always
and that i poison frees
Definitely
probably lol
and that the memset is naive
do you have profiles?
no
i mean i can use the qemu profiler actually
i have it here in the repo handy
let's see
True
I wanted to use that shell script profiler but uacpi was too fast
do it in a loop 
tbh yeah
i think llenotre's qemu instrumentation thing might work?
idk
or alternatively you could try copious amounts of dtrace?
or try without kvm actually lol
Yeah actually
it seems like a lot of time is spent in vmm.c
now that i think about it, can u give me the name of the node that is being uninstalled here?
some of it in spinlocks
i dont understand why it enters this branch
that means u cause a lot of vmexits probably
Check for lots of cr8 writes or something
@fiery turtle why is thread_id a void*?
recursive mutexes
why do u ask btw, are your thread-ids non representable as void*?
this one? or am i looking in the wrong func/var?
no they are, they're just usizes and i thought maybe you want a thread pointer
correct yeah
replacing the mem functions with rep movsb and friends barely made any difference
thanks
which unimplemented caused this?

the only unimplemented thing that's being called is uacpi_kernel_install_interrupt_handler, but i haven't checked whether that's the actual cause of the issue, it could be unrelated
install_interrupt_handler is called way before namespace_load
i'm logging all calls to unimplemented functions, and that's the only one that gets logged, and it gets logged right before the panic
set a breakpoint, this is the very first call to the function
nvm i dont know how uacpi works apparently lmao
fair enough i must've moved it at some point
will fix it shortly
ok i made it not poison on frees and not zero on allocs when not needed, and now it's 64k
idk, i have a feeling the allocator is not the issue
Stub out some uneeded you figure out whats the issue functions one by one until
@fiery turtle how can i wire up an interrupt handler? the function signature doesn't match the one from uacpi
realistically, how allocation heavy is this?
Wrap in one that does?
but that only works for one handler?
Very
is this allocation heavy to the point where things like cache locality and whatnot start to matter?
holy shit my kernel is so fast!1!!!!11
Dont u have a way to provide a context pointer to an interrupt
Based
(i always return 0 in my timer shit)
not sure
lol
probably not
ok whats the default tsc rate
whatever your host is
U definitely should have a priv field
i do i think
i had a slab allocator but i removed it because i figured i did not need it
Whats data?
priv basically
Thats fine
okay
Maybe
doesnt help
Good starting point
Like at all?
I had seen no diff between O2 and O3 in astral too
nope
i was at -Copt-level=1 before tbh
so its not super shocking
also i have stubbed mutexes still
Ah
and i think i have some UB somewhere
okay i turned off spammy e9 logging and now its at 83
this is all tcg btw
Try kvm?
gotta move it to my other laptop first
Should be about 800k
Not bad for a 3 hour old kernel
lmfao
its full of stubs
i backported the Lyre slab allocator
im on 909
Nice
i wonder how much of that is just my shit ass malloc
which isnt optimized for performance by far
run-to-run variance
holy shit the variance of this is bad yeah
okay then lets kill factorio
i think this is the most i see
probably just the fact that my cpu is worse than mint's at least somewhat
and my probably worse allocator
the slab allocator i backported still zeroes out on all allocs so
oh and i fill allocations
ah yeah same
actually i double clear on zeroed allocs
but yeah this is kinda a bad test just because its way too fast
do they have more?
ugh i dont want to deal with ovmf
and i dont want to deal with graphics rendering either
Mint's cpu and qwinci's cpu are 3x faster than mine on the benchmark lol
how much do i get? qemu-system-x86_64 -hda bs/reblast.iso -M q35,smm=off -cpu host,tsc-frequency=1000000000 -d int -accel kvm -debugcon stdio
on mine?
yeah
aight one sec
thanks
uacpi: successfully loaded 1 AML blob, 1702 ops in 0ms (avg 1854648/s)
Btw, linux (https://www.kernel.org/doc/Documentation/virt/kvm/timekeeping.txt) says this
The TSC is a CPU-local clock in most implementations. This means, on SMP
platforms, the TSCs of different CPUs may start at different times depending
on when the CPUs are powered on. Generally, CPUs on the same die will share
the same clock, however, this is not always the case.
okay so now question
how do people make their shit faster
i guess faster malloc?
hmm lets try that
i actually don't even remember why i removed the slab allocator
damn i get 1.6 mil consistently now
all i did compared to before is allow 2048 byte allocs to also go via slabs
qemu kvm: 1705 ops, 1088140 ops/s
real hw (haswell mobile cpu): 4962 ops, 122947 ops/s
i wonder why the difference is so big?
real hw is like 10x slower though
does uACPI map and unmap the same regions often?
does that really just come down to how much better my host system's cpu is?
idk i just return hhdm
Maybe aml does a sleep() inside for example
any reason you cant do that?
A lot of factors
Probably not
oh i guess you need to actually make sure its mapped
sleep and stall are both stubs rn
just map all of physmem
but yeah probably just firmware devs being as good at writing AML as they are at writing firmware (not very)
well, as per base revision 3 of the Limine protocol, and because of the fact that you should always map stuff that isn't usable memory and friends, i do map it, in hhdm, but i do map it
Yeah thats why we test on qemu so we have the same aml for all
yeah true
@fiery turtle in kernel_install_interrupt_handler, is ctx optional?
so yeah i was wondering that because checking if it was already mapped and not mapping it in that case may speed things up
if the same regions are mapped over and over
Wdym optional
Its uacpics context for that irq
i probably have to modify my irq implementation, right? i can only pass one thing as a context
i'm confused
That it wants to be passed to its handler
U can make a global variable if u want
tested it on my actual host without QEMU in the way: 10097 ops, 976768 ops/s
What did u do
slab allocator + allow 2k slabs + don't zero out unless calloc
So real hw close to qemu then?
Nice
yeah pretty close
Depends on the blob I guess
3M+ is PhD territory
I do think QEMU uses faster ops because it's faster even though anything that would be a vmexit on there is much cheaper on actual hw
Yeah thats not very fair
idk what my mutexes would even be, other than spinlocks without cli/sti
Once you implement them
Yeah
slab allocators are pretty cool
Indeed
what exactly does the interrupt handler return
Handled/not handled
damn thats significantly faster than mine
how do you select the slab bucket?
im gonna assume its something smarter than just a loop?
ah huh
i didn't want to make one π’
tbh i could also do a [static 2]
wtf why is my slab so much worse then
or what else is the problem?
maybe my malloc is crap?
Pog
it's not much but it's honest work
Mathwend recently implemented it you might want to ask him
womp womp
Its just one msr and a struct in memory so pretty simple stuff
Nice!
Theres a linux doc page talking about it
[ 0.080972] [ 0] acpi: successfully loaded 1 AML blob, 1816 ops in 50ms (avg 36304/s)
woe
Niice
no license, all rights reserved :^)
I like how it just has uacpi libc in root
yeah
https://docs.kernel.org/virt/kvm/x86/cpuid.html shows how to detect it
https://docs.kernel.org/virt/kvm/x86/msr.html shows how to use it
aren't the uacpi_kernel_io_{read,write} supposed to be PIO on x86, not MMIO? or am i implementing them wrong?
i thought it was mmio
pio ofc
damn
so like
how
then what the hell is it the same for kernel_io_map?
that makes no sense
this is how i implement them https://hst.sh/utixukoket.csharp
kernel_io_map is for probably for platforms where "PIO" is just MMIO with an offset
This or microkernels
so is io_map supposed to be a no-op in my case?
For kernel level x86 drivers yeah
the thing is that io is quite confusing, if it was pio i would've understood it better, but io could be mmio
Well there's already a memory read
what does uacpi use the pci_{read,write} fns for?
can i guarantee that these functions will be called after e.g. mcfg enumeration
They won't be called before namespace_load
okay good
get owned
that shrimply doesn't work on my kernel
some addresses are not mapped, or I forgot to map them somewhere
I play safe and barely rely on the hhdm outside of physical memory
i forgot to have a mapping api for the kernel
Btw, does uACPI only call this only during the initialization?
from the docs it seems like it's something that can be triggered by AML
(the raw_io family explicitly says it can't be triggered by AML, and the normal io family does not)
I don't use hhdm at all and don't even map it when stiching to my own page tables from limine 
alright I'm too tired for this allocator thingie
maybe in a few days
@fiery turtle what page protection does kernel_map need? RW?
RO crashes it
Rw ye
!!
94k
tcg?
what's that
are you using qemu with TCG on
i'm getting a pretty consistent average of 90k
or KVM
kvm
holy fuck what are you doing
im getting 90k on TCG
admittedly i cant call my thing a kernel
how do i do tcg
phd memcpy
lol
that should mean its not 90k lol
more like 900k
are you sure your timer logic is correct?
does it match rdtsc with -cpu host,tsc-frequency=1000000000 (which makes it a nanosecond-precision timer)
uACPI: cutting edge timer stress test
actually, maybe the timer is a bit slow
it's like 80% real time
it's not very precise lol
i told it to wait 1 second
maybe it's the printing
this looks like expected drift
your drift is 1ms per second?
so margin of error
hpet 
ah
my timer is accurate so far though
idk why it's so slow :(
@loud ice what's your qemu command
qemu-system-x86_64 -hda bs/reblast.iso -M q35,smm=off -cpu host,tsc-frequency=1000000000 -d int -accel kvm -debugcon stdio
nope, still 90k
funnily enough with fb enabled it's faster somehow
over serial it's only 36k
yea no, i can't get past 90k
without kvm i get 30k
is the irq passed to uacpi_kernel_install_interrupt_handler a GSI or an ISA IRQ? if it's GSI, how do you determine whether it's active low/high and level/edge triggered?
Gso
*gsi
And the ioapic redirection table entry things tell you
The trigger mode and polarity
like, the ones already in the ioapic registers, which were written by firmware?
i'd prefer not to rely on those if possible
Acpi ones
From the madt
interrupt source overrides? those are only for isa irqs
usually the irq passed to that function is an isa irq
I think its also allowed to be a gsi tho (likely only on platforms where there is no legacy pic at all)
Whatever type two
Eas
*was
System vector the SCI interrupt is wired to in 8259 mode. On systems that do not contain the 8259, this field contains the Global System interrupt number of the SCI interrupt. OSPM is required to treat the ACPI SCI interrupt as a sharable, level, active low interrupt.
ISA
Its usually overridden in madt so be careful
alright thanks
yeah that's why i asked, i wanted to know if i needed to check the isos
sounds correct
@calm latch pmOS powerbutton works just fine
--- a/source/namespace.c
+++ b/source/namespace.c
@@ -194,11 +194,14 @@ uacpi_status uacpi_initialize_namespace(void)
void uacpi_deinitialize_namespace(void)
{
+ uacpi_status ret;
uacpi_namespace_node *current, *next = UACPI_NULL;
uacpi_u32 depth = 1;
current = uacpi_namespace_root();
+ ret = uacpi_namespace_write_lock();
+
while (depth) {
next = next == UACPI_NULL ? current->child : next->next;
@@ -233,6 +236,9 @@ void uacpi_deinitialize_namespace(void)
// This node has no children, move on to its peer
}
+ if (ret == UACPI_STATUS_OK)
+ uacpi_namespace_write_unlock();
+
uacpi_object_unref(g_uacpi_rt_ctx.root_object);
can you please test if this fix works
yep, that fixed it
nice
one interesting thing i noticed: when booting with ovmf instead of seabios, uacpi is consistently faster by ~100k-200k ops/s (consistently 1.2-1.3M/s on ovmf, 900k-1.1M/s on seabios)
different aml perhaps?
doubt it, they both have exactly the same number of ops (1705)
This is the final call for anyone who wants to make it to the initial uacpi notable project & leaderboard list
ill be finalizing that pr shortly
@jaunty fox would you like to be mentioned? you have a pretty good score 
i have no objection to being mentioned
though i am wondering what the test methodology is
who carries them out?
what's considered decent/good
1M+ i guess
what are the bottlenecks again
also ubsan
wait memset too?

omw to phd memset
but tbh my allocator might be my bottleneck
shitty little slab
Is mimalloc any good
u mean namespace_load?
during the benchmark test or w/e
like every
because if so i know what's bottlenecking it lmao
im printing a todo message on every call
rofl
that costs a lot yeah
let me remove it
mimalloc is really good
could that because i have some qemu devices?
if they interface with acpi then probably yes
qemu-system-x86_64 -bios /usr/share/ovmf/x64/OVMF.4m.fd -machine q35 -cpu max -name "menix x86_64" -serial stdio -no-reboot -no-shutdown -m 2G -smp 16 -drive format=raw,file=fat:rw:build/install,if=none,id=fatfs -device virtio-gpu -netdev user,id=net0 -device virtio-net,disable-modern=on,netdev=net0 -device nvme,serial=deadbeef,drive=fatfs -enable-kvm
nice, but u have quite a lot of stubbed out right
1708 with only an nvme
yea, is there anything that's considered "cheating"?
kinda, yeah
not actually implementing an api is sort of cheating
because u avoid quite a lot of work
even io read and stuff?
is it cheating if I do something like not zero out allocated memory when trying to get the highest score possible?
but keep that memset in the kernel afterwards
like, not zero out memory allocated by calloc?
i have allocations, raw mem rw, raw io rw, pci rw, io map, timer, spin, interrupts
malloc, beacause I zero that too
i don't think that'd be cheating, normal malloc isn't required to be zeroed
my mutex is basically a spinlock for now
lol
idk how to design a nice mutex interface
though a mutex makes little sense at the time where i'm calling uacpi_init
it's the only process that's running then
1.9 mil 
damn me
no, ofc not
how
idk
maybe the timer is being bad again
oh yea no it tried to configure lapic without hpet 
okay 1.9 might have been bogus, but i can reliably get 1.1-1.4M
Why CPU do you have?
if you have a rep movsb/stosb for them then doing anything else is unlikely to make them a lot faster
i dont
i had a for loop
i set bytes so the address is qword aligned, then i do qword copies for memcpy
does that work on arm
yea
with mmu + cache enabled yes
if you have the mmu or caches off what the fuck are you doing
i believe windows does this btw
linux boot protocol 
the first thing you do when you take over is you turn on caches and mmu
yes but if you want to do that in eg. c/c++ or whatever
you cant
you can
cringe
and a perf penalty for the whole kernel
for the 1 line you save for caches
i believe its only caches too
okay the new memset got me +100k
for anyone trying to maximize their score, here's some very rudimentary profiling data
howd you do that
neat
so alloc, calloc, free
plus memcpy and memset
recorded starting time at the start of each function, end time at the end, and some glue code to list it all
now record the call stack and see what allocates the most 
worth doing tbh but i feel like at that point it'd be easier to hook up a proper profiler
maybe I should move the cache code to the startup asm in my kernel
I could also implement the entire thing in asm (so I wouldn't have to rely on the compiler generating relocation-less pie code) but I don't like writing paging code in asm
aren't there profiling solutions that instrument the code to automatically do what i've done here but for every function?
you really should do that
-minstrument-mcount kinda?
but its entry only i believe
i use it btw
damn
you need to remove -
the quotes take care of that
they don't
ah it's -finstrument-functions
ah
okay i believe now it's just my allocator slowing things down :(
yeah I found that
and I don't really know how to get it to work
in a kernel
properly
oh nice
log callers are killers under kvm what with the slow portio
if i log in uacpi_kernel_map it cuts me from
[uacpi]: successfully loaded 1 AML blob, 2356 ops in 1ms (avg 1857465/s)
immediately to
[uacpi]: successfully loaded 1 AML blob, 2356 ops in 2ms (avg 836618/s)
yea i had the same issue
i was dangling around 60k because i logged "todo" on every unimplemented fn
without i'm at 1.3mil
in that profiling data the only function that calls another profiled function is uacpi_kernel_calloc (which calls uacpi_kernel_alloc), and none of the calls log anything (except uacpi_kernel_log of course)
so i believe i avoided that in the data
but yeah it's a huge perf drain if you're logging a lot
for anyone that wants to make their own profiling data, here's the code i used: https://hst.sh/uqegidozov.cpp
it's not particularly optimized because i just wanted to get it implemented quickly, but none of the expensive parts are measured in the actual data (unless your profiled functions call other profiled functions)
fixed a bug that caused the heap to expand on each allocation, and uh...
uacpi: info: successfully loaded 1 AML blob, 1705 ops in 0ms (avg 4841920 ops/s)
that's a bigger improvement than i thought it'd be
wtf
this is with 0 stubs btw, each kernel api func is fully implemented
what allocator do you use?
u sure your time keeping is accurate?
yes, sleeping in a loop for 1s/iter and printing the current time works correctly
how are you so fast
@kindred beacon im afraid managarm has been demolished

whats your cpu?
pmm: simple free list, not even buddy (all physical allocations that are more than 1 page use a separate api that only works during early boot)
heap (objects <=PAGE_SIZE): allocations are rounded to the next highest power of two (using __builtin_clzl). a separate free list is maintained for each power of two, which is expanded directly from the pmm
heap (objects >PAGE_SIZE): allocations are rounded to a multiple of PAGE_SIZE, vmm does the rest (irrelevant for this benchmark since there's only 1 "large" allocation that uses this)
oh okay
AMD Ryzen 7 5800X 8-Core Processor
i'm using a (less opimal) slab allocator
i think the speed is a combination of four factors:
- good cpu
- my allocators are designed to only do the bare minimum required to be usable and reliable, which makes them simple and fast
- memcpy/memmove/memset are rep movsb and rep stosb
- my kernel does a lot of allocating and freeing before uacpi init, so my small object allocator's free lists are already populated. i suspect it can always or almost always go through its fast path
how come map is only called once
that's weird
"modern" cpus (this was introduced over a decade ago) have a feature that optimizes rep stosb and rep movsb
they're pretty much the fastest memcpy/memset you can get (excluding SIMD which isn't usable in kernels)
this data is only for uacpi_namespace_load, not any of the other calls. i suspect most of the mapping is done by uacpi_initialize
ah
i moved uacpi init earlier into the boot sequence to see if the last factor made any significant difference:
uacpi: info: successfully loaded 1 AML blob, 1705 ops in 0ms (avg 4605780/s)
so it does have an impact, but not super significant
so which cpu
.
bro beats phd code
i just make use of phd microcode (my string functions are https://hst.sh/afelovokab.pl)
incredible
still, managarm is a microkernel, isn't it? if that 3.2M figure is uacpi running in userspace, that's more impressive than my monolithic stuff imo
i don't think it's in userspace
remarkable
not sure, but i clearly remember lai being in thor
its in kernel space
@gentle peak would you post your iso so people can test on different cpus?
my best result yet is [uacpi]: successfully loaded 1 AML blob, 2356 ops in 0ms (avg 2586007/s) but usually it's more 1.8 to 1.9mil
i'm getting a very reliable 1.3mil
some real hw benchmarks:
- Haswell laptop (Intel i5-4200M): 579037/s
- Same system as before but on bare metal (Ryzen 5800X): 3880858/s (I suspect the lower result is because linux puts the CPU onto a higher frequency)
sure, give me a minute
i think we need someone to be a clearinghouse for benchmarking
yea
nah it's very likely not the frequency thing
it's what was mentioned before
like different firmware AML doing different things (and definitely more than QEMU's AML)
he should be someone that runs probably gnu/linux so KVM can be used and he should have an invariant TSC
he?
he should be lukflug
astral?
was it not astral?
leo is also acceptable
leo had worse perf
oh damn
did you mean qwinci
qwinci had the highest?
qwinci and mint left me at 2.4mil
i mean the leaderboard specifies which cpu was used so its not like super unfair
yes, the other criterion should be some statistical knowledge (both lukflug and leo will fit that bill)
The command line I used for measuring was qemu-system-x86_64 -accel kvm -cpu host,migratable=off -M q35,smm=off -cdrom proxima.iso
but if qwinci or mint are down to measure everyone's iso i dont mind it
i can
with keyronex tests i see a lot of intertest variability (probably the same will be true of other kernels, i will check this proxima one next) so whoever is testing should be mindful of it
i don't have an iso 
oh btw this is built with -O3 and LTO enabled
in case it makes a difference for comparison
this is probably important as well
i observe consistent 3.6mil, congratulations
now im sad its proprietary
its like, extremely simple
but i guess can still be on the leaderboard
