#uACPI - a portable and easy-to-integrate ACPI implementation

1 messages · Page 49 of 1

rustic compass
#

done

torpid root
#

I heard that thin lto is the recommended kind for incremental builds but it costs me like 700k points

rustic compass
#

who needs incremental builds?trl

frank canopy
#

i dont use incremental lol

#

its still in early experimental phase for zig

rustic compass
#

also for getter with unknown size like arrays try to use one interface without allocations (for example use a index approach), one with alloc and one with allocator_api

#

as an example look at the trait AcpiTable

rustic compass
#
fn get_ptr_to_table_payload(&self) -> *mut u8

points to the first byte after the table header

trim frost
torpid root
#

but takes more space and the performance is worse

rustic compass
#

its not ready to be published to cargo

trim frost
#

@rustic compass

rustic compass
#

branch "dev-1.0" btw

trim frost
#

ffs i didnt even look at it

#

main branch

rustic compass
#

also ignore the ton of errors

kind mantle
# trim frost

__popcountdi2 is a libgcc (and FWIW probably clang too) function that count how many bits are set in an integer

#

So if you don't compile that into your kernel you may need to define some of them yourself.

trim frost
rustic compass
#

you can mask most of them by removing the aml_interpreter feature and probably replace the two errors in tables.rs with todo

#

"full_acpi_hardware"

trim frost
#

still ton of errors

#

mostly types

#

error: could not compile uacpi (lib) due to 102 previous errors; 7 warnings emitted

rustic compass
#

with default = [] i only get 3 errors

#

one of them is stupid rustc

#

comment out line 393 in types.rs and replace both implementations in tables.rs with todo!()

trim frost
#

line 393 in types.rs is inactive since no default features (aml_interpreter)

#

why do i get 102 errors?

rustic compass
#

rustc still reports an error there

#

dunno

#

where do you get them?

trim frost
#

mostly u32s instead of i32s

#

these 2 in tables

#

yeah its those 2 in tables and rest are u32s instead of i32s errors

rustic compass
trim frost
rustic compass
#

on what system do you compile it?

trim frost
#

linux

#

arch

rustic compass
#

aparently on linux c_int is a u32 while on windows its a i32

trim frost
#

bruuuh

kind mantle
#

That doesn't make any sense

#

Why is c_int ever a u32?

#

It should be signed, like it implies with its name.

trim frost
#

its because its not c_int

#

its c_uint

rustic compass
#

looks like bindgen chooses a c_int for me

trim frost
#

yeah

#

thats weird

kind mantle
#

LLM answer: Enum sign is not specified so it can be either.

#

Maybe you can tell bindgen you want a specific sign for your enums?

trim frost
#

thats what im trying to figure out rn

rustic compass
#

i use clang

trim frost
#

found it

#

.default_enum_style

#

i think

#

hold on

#

.default_enum_style(bindgen::EnumVariation::Rust { non_exhaustive: false })
.rustified_enum_variant_type(Some(bindgen::EnumVariantCustomType::Int32))

#

gpt halucinating as always

trim frost
#

et voila

#

i fixed it

#

very horribly

#

@rustic compass is this it?

#

intellisense doesnt show core functionality

#

okay i will wait for uacpi-rs to be finished and meanwhile i will use the bindgen output

#

aww hell naw

rustic compass
#

kernel api isnt implemented yet

trim frost
#

how can i edit includepaths for the c files?

rustic compass
trim frost
#

going to the c files gives me errors like this

torpid root
rustic compass
#

And I forgot to check that and update the build script

rustic compass
trim frost
rustic compass
#

what compiler do you use?

#

based on github bindgen issues linux isnt spec compliant here, enum should always be i32 on x86_64

trim frost
#

oh i read as linker

#

latest nightly

rustic compass
#

i mean the c compiler that cc/bindgen use

left orbit
#

it'll be env!("CC")

#

so unless they explicitly provide that it should be gcc

thorny orbit
#

K so, this might be unrelated to uACPI but is it normal that there's no 'FACS' table in memory

#

because i made a QEMU memory dump, read all the RSDP,R/XSDT, found all addresses by myself, and in the FADT i can see there's a value in the FIRMWARE_CTRL field

#

even tho it brings nowhere

#

}

kindred beacon
#

when in doubt you can dump ACPI tables from the UEFI shell and inspect those

fiery turtle
#

and im pretty sure qemu does have FACS

torpid root
#

it does

frank canopy
#

and i dont know if the FACS region has a header since its not really a table

#

i could be wrong though

thorny orbit
#

I mean, I'm pretty much leaving everything to uACPI, which does check for x_firmware_ctrl

#

But the problem is that it finds an address where there's no FACS apparently

#

Even tho I might try NVME shill's hint and see where this goes

fiery turtle
#

can u explain the problem in more detail

#

what are you trying to do, what happens

#

if uacpi gets a bogus address that probably means you dont handle misaligned mappings correctly

#

read the comment above uacpi_kernel_map

thorny orbit
#

So, to start, i was trying to initialize uACPI in my kernel, almost all tables get initlialized but when checking for FACS signature it simply doesn't find a signature (and there isn't any since i checked the memory dump)

#

so the problem is not anything related to address aligment since all the other tables worked fine 🤷‍♂️

fiery turtle
#

Are you using early table access?

thorny orbit
#

nope

#

or, from what i saw, early_table_access is still set to false at init

fiery turtle
#

Set to false?

#

Wdym

thorny orbit
#

one sec

fiery turtle
#

Is this invalid table thing logged by you or uacpi?

thorny orbit
#

I meant this value btw

fiery turtle
#

Oh ok

#

Can you show where it does it

thorny orbit
#

OK

#

So, in the initialize_tables function, it tries to check for the table signature right here

fiery turtle
#

Any way you're just not mapping it correctly?

#

Or corrupting uacpis context

thorny orbit
#

i don't really think so

fiery turtle
#

Yeah looks like you do

torpid root
#

mapping it incorrectly could be the problem

fiery turtle
#

There's an extra bogus 16 on top of its address

torpid root
#

what's in your kernel api map function?

fiery turtle
#

If u look at uacpis output

thorny orbit
#

about that

#

it's because it's not actually written correctly in the log function

fiery turtle
#

Hm?

#

Its written correctly

thorny orbit
#

nope

gentle peak
#

there's a literal 0x016 in front

fiery turtle
#

Oh lol

#

Yeah

#

So that's not the issue then

thorny orbit
#

yeah

fiery turtle
#

Can u run something like Linux and see in dmesg what address it reports for facs

thorny orbit
#

ok

fiery turtle
#

And yeah show us your mapping function

#

Because that address looks somewhat correct

thorny orbit
#
void *uacpi_kernel_map(uacpi_phys_addr addr, uacpi_size len) {
    uint64_t aligned = ROUND_DOWN(addr, PFRAME_SIZE);
    size_t offset    = (size_t)(addr - aligned);

    size_t actual_len = len + offset; // this is BYTES!!!
    size_t pages      = ROUND_UP(actual_len, PFRAME_SIZE) / PFRAME_SIZE;

    void *virt = vma_alloc(get_current_ctx(), pages, (void *)aligned);

    // re-align the pointer to original addr offset

    virt += offset;

    return virt;
}
gentle peak
#

did you omit the actual mapping part or

thorny orbit
fiery turtle
#

Lol

thorny orbit
gentle peak
#

you're not passing it the physical address though

#

how does it know what to map

#

oh wait you are

#

nevermind

thorny orbit
#

yup

gentle peak
#

the void * cast tripped me up

thorny orbit
#

understandable

fiery turtle
#

Btw how does your round down behave if the address is already aligned

#

Can you show it as well

thorny orbit
#

oke

#
#define ROUND_DOWN(n, a) ((n) & ~((a) - 1))
#define ROUND_UP(n, a)   (((n) + (a) - 1) & ~((a) - 1))

they're just some macros

fiery turtle
#

Would be easier if you had an hhdm we could quickly replace this logic with but oh well

thorny orbit
#

you'd be right

#

🤔

#

now that you told me about it

gentle peak
#

is it possible you're corrupting the facs memory itself?

thorny orbit
#

ermmm...

#

bruh

fiery turtle
#

Ye

#

I guess your mapper is misbehaving

thorny orbit
#

mh

#

well uhmm thanks and sorry nooo

fiery turtle
#

Lol np

#

We found a print bug as well which is useful

thorny orbit
#

👍

kind mantle
#

}}}}}}}}}}

fiery turtle
#

technically an api break so uacpi 3.0 time? trl

#

(jk i wont do that)

#

also as per shinribo's request, clarified the table api usage a bit

frank canopy
#

nice

hollow elm
#

then when enough deprecated defines accumulate make 3.0 that removes them?

fiery turtle
#

i think i can go out on a limb and say that no one used this define

#

but a proper way would be that yeah

hollow crescent
fiery turtle
#

most of these are just copied code or autogenerated bindings

#

but threre are two uses i think still

#

damn

#

okay then

#

ill do what qookie said

#

also why is there jai bindings damn lmfao

fiery turtle
#

is there any way to make macros deprecated with a warning

hollow crescent
torpid root
hollow crescent
#

your fault for using -Werror

torpid root
#

I don't but I can't stand having warnings

#

build log needs to be clean

fiery turtle
#

or rather, the macro itself

torpid root
#

you could have a global function/object marked as deprecated and somehow reference it in the macro definition

#

#define UACPI_POISITIVE_DECODE (deprecated, 0)

fiery turtle
#

interesting

#

could i make it a static inline function instead?

#
__attribute__((deprecated)) static inline int uacpi_poisitive_decode_value() { return X; }

#define UACPI_POISITIVE_DECODE uacpi_poisitive_decode_value()
#

maybe like this

calm latch
#

the issue is that this is not a constant expression?

fiery turtle
#

you can't make a global static inline tho

#

so i'd have to add it as an extern

#

which is fine i guess idk

calm latch
#

yeah

fiery turtle
calm latch
#

but at that point maybe the function would be the best option

calm latch
#

like since everyone was using it so it became a language feature?

fiery turtle
#

i'll just do #if __has_attribute(deprecated) etc

#

otherwise u get no warning and its your fault

calm latch
kind mantle
#

I recommend what I did last time I had a similar problem: Keep the old one around but deprecate it. Since it's a macro you can't do much better than put a warning comment before it. Then next major version (3.x) you can remove the misspelled version.

fiery turtle
#

yeah see the discussion above

fiery turtle
#

Alright I think I'm back from my Minecraft/gtnh semi hiatus because I kind of hate how AE2 works, I might focus on my os ™️ project

jaunty fox
#

i can't wait to see ultraos form

fiery turtle
#

nahh its gonna be way worse than keyronex

kind mantle
#

cmon we're not here to make perfect things now are we?

#

Make UltraOS

fiery turtle
#

but i wanted it to be good nooo

kind mantle
#

Good need not be perfect

fiery turtle
#

fair

calm latch
#

how could a bad OS even come from you?

fiery turtle
#

watch me trl

calm latch
fiery turtle
#

well thanks

left orbit
#

yooooo

#

finally

#

after all these months it's finally true

frank canopy
#

👀

fiery turtle
#

lol

thorny orbit
#

uOS ultrameme

#

}

fiery turtle
#

i did a bit of ultra work, mostly remembering whatever i was doing there and changing some things around

#

but its a start ig

calm latch
#

you just need to rename this thread risc

fiery turtle
#

nah ill make a new one when im confident im actually gonna work on it

#

and it will generate less traffic since its not actually a useful project to anyone

calm latch
kind mantle
fiery turtle
#

speaking of that, ill need to integrate uacpi at least for early table access mode very soon which is nice

#

ill probably get rid of my printf and just steal uacpi's symbols

fiery turtle
kind mantle
calm latch
#

can I shill a microkernel design? /j

fiery turtle
#

nah im not doing that lol

#

basically my idea is very simple and not innovative, i want to get it running very quickly so that i can focus on stuff that i enjoy, which is drivers

#

and i want to get a basic drm up and running

calm latch
fiery turtle
#

if i were to make a microkernel id have to focus on the details which im not interested in

#

im considering dropping aarch64 and i686 atm as well

fiery turtle
fiery turtle
#

basically i want it to be old proxima like which was very simple and very fast

#

although i do want to support numa as well from the start

#

we'll see

calm latch
#

that's still a good goal

fiery turtle
#

my long term goal is to be able to run a simple opengl 3 or 4 game with native accel on my 2010 igpu

#

with that game being a binary built for linux userspace and just cp'ed to my image

#

i might just get some game from my steam library

#

maybe factorio, idk which opengl it uses

#

or balatro would be cool lol

#

but thats obviously a giant amount of work so yeah

#

hopefully i get there eventually and dont abandon it lol

vast kestrel
#

Run Minecraft Smuggy

#

Then while you are playing it instead of working you could at least do it as a stress test for your os

fiery turtle
#

lol

#

yeah i guess actually

vast kestrel
#

Today I did some vulkan thing and I got reminded about your (I think it was you) igpu triangle hello world and how much smaller it was compared to vulkan KurisuSip

fiery turtle
#

lol yeah

#

it was me

fiery turtle
#

Spent a few hours figuring out how linuxes log ring works, I think I have a pretty good idea of the algorithm

#

Its pretty neat

#

Since I'm doing Linux compat might as well have a syslog ring

left orbit
#

are you going linux binary compat?

#

that's pretty sick

#

definitely takes away a lot of the porting groundwork, you can just throw an alpine rootfs at it and work on the kernel instead :^)

fiery turtle
#

Ill probably have some of my own syscalls that live at some offset, sort of like xnu does

#

But Linux syscalls and vfs layout will be the native way to use it still

fiery turtle
#

Also this will allow me to really understand how Linux is built in depth

flat badge
fiery turtle
#

this stuff is also reused for printing out to consoles etc

#

basically the in-kernel, yes

flat badge
#

just copy managarm

#

Jokes aside you probably don't need a fancy strategy until you're using NMIs

fiery turtle
#

its nothing fancy tbf

#

they just have a ring of log entries basically that have a pointer to text and its length + log level/facility etc

#

each log entry has a 64 bit sequence number

#

that u can use to extract its position in the ring with a simple modulo etc

#

the text buffer is also just a fixed length dynamic array

flat badge
#

Well, at least in case of linux (and managarm) it needs to be NMI safe though

fiery turtle
#

it does have all sorts of complicated locking stuff so that u can use it in every possible context yeah

flat badge
#

which means it must be able to cope with the log function getting entered in an nmi while the context that was interrupted by the nmi is currently writing to the ringbuffer

fiery turtle
#

yeah

#

for that it has multiple states for the log entries

#

like available, commited etc

calm latch
#

What are you even supposed to do when you get an NMI and you're a microkernel?

#

Like your console driver would probably be running in userspace

flat badge
#

buffer the message and send it to userspace after the NMI is done

calm latch
#

But aren't you supposed to crash?

flat badge
#

no

#

not in general

#

NMI can be used to deliver critical failures but the more modern mechanism for that is MCE

#

NMI is also used for watchdogs / profiling / etc

#

and you don't want to crash in these situations

calm latch
#

But even in case of a critical failure, you should still somehow be able to get to userspace to show an error message, and I don't get what's the best way to do that

fiery turtle
#

if your kernel is fucked to an extent where it gets a watchdog NMI it's not really an option

#

aka you cant rely on userspace working at all in that case probably

calm latch
#

I was thinking about going to userspace and crossing fingers for it to work enough to print an error message to the screen

#

Since now when the kernel crashes, it only prints error to the debugcon

#

So like if you're running it on physical hardware without COM port and the kernel dies, it just freezes and you have no way of knowing what happened

mortal yoke
#

why couldn't you also print to the fb in the kernel in case of a panic?

left orbit
#

well, linux has drm_panic i guess

#

but idk how that works

#

but if your framebuffer has been taken over by a driver then i don't think you can simply just print to the framebuffer anymore

mortal yoke
#

well yeah if you have a proper gpu driver then you'd need to do it with it

calm latch
left orbit
#

idk how feasible that is if you're in the "we're fucked" state :^)

calm latch
#

Like it could be some cursed serial otput or something, and I want userspace drivers

#

Maybe I want too much though

left orbit
#

imo if you're a microkernel your kernel shouldn't crash no matter what

#

you could still enter a user thread context from an nmi handler context, it's just that your system might be in less than ideal state at that point so you should probably do as little as possible

#

it's not like the cpu is dysfunctional and switching to another thread will blow things up

hollow crescent
left orbit
#

the cpu? why lol

hollow crescent
#

i dont know why you would receive an NMI other than hardware failure

left orbit
#

hardware does not necessarily mean cpu

hollow crescent
#

it could also mean memory

#

which is similarly bad

mortal yoke
#

something like ram would be more likely yeah

left orbit
#

exactly, as i said - do as little as possible

#

hopefully it's not all gone to shit yet

#

maybe you can get your last words out before dying

hollow crescent
#

meanwhile windows

#

(it used to just clear the screen blue and say NMI - Hardware failure. Contact your hardware vendor)

calm latch
left orbit
#

ECC is a thing

calm latch
#

but some fuckery could still happen in hardware

hollow crescent
#

if you have some kind of special hardware that issues NMIs then maybe

left orbit
#

i think infy meant actual architectural profiling

fiery turtle
#

i think its the standard x86 way of doing profiling

#

yeah

flat badge
#

NMI is not used for error reporting on modern hardware

#

NMI is used for watch dogs and profiling

#

And yes, that is architectural

#

If you're talking about MCE: if you encounter a synchronous memory failure in the kernel, you're probably fucked

urban galleon
flat badge
#

if it's in userspace you can poison the page, maybe kill the process, continue

urban galleon
#

It might be a intel problem but I blame windows

fiery turtle
#

only if its nonmovable memory

flat badge
#

can't migrate the page if you can't read it anymore

fiery turtle
#

hm tru

flat badge
#

if it's a kernel page, the most reasonable thing you can do is probably log a kernel panic to whatever devices the kernel can talk to

#

realistically ppl will run memtest upon random crashes / detect faulting memory during POST so that should be good enough anyway

#

another option is to write error info to some nvram

#

or even normal RAM

#

and then doing a soft reboot

#

linux can also do that

mortal yoke
flat badge
#

essentially this does a kexec on panic

north hull
#

has anyone else ran into this

#

if I build with release meson doesnt like it

#

nothing else seems to really break

fiery turtle
#

bro the linux printk_ringbuffer design is genius

#

you can reserve entries completely lockless

#

and they made it completely NMI safe

dense steppe
#

A fully reentrant ringbuffer is a very good exercise in concurrency and reentrancy, as I believe @flat badge (sorry for ping) has pointed out.

fiery turtle
#

the log entries have 4 states: reusable, reserved, commited and finalized

Reusable just means free, reserved means someone allocated an entry, but is not yet done writing to it, so readers will be aborted when trying to continue reading the ring at this point, but writers can continue concurrently allocating more entries. Commited means someone has commited the data, but may want to append more later, this is only used during early boot for multiline logs. Then finalized is a read-to-read entry.

#

and this ring is actually 3 separate rings: descriptors, info, and actual text prepended by descriptor id

fiery turtle
#

but it can still be concurrent with a few atomic ops

dense steppe
fiery turtle
#

yeah the KERN_CONT flag makes printk code not finalize the record

#

but if a new record after is reserved the previous one is instantly finalized if its commited

#

so it cant really be used after early boot

dense steppe
#

note the lack of \n

fiery turtle
#

yeah

dense steppe
#

ah.

fiery turtle
#

what's cool is readers won't see the commited message unless a new one is added after or the commited message is finalized

#

so its very well thought out

fiery turtle
#

hmm do i wanna waste a week making this log ring completely lockless like linux, I think I understand how to make that work entirely...

left orbit
#

bro said he wants to focus on writing drivers and yet he's making one of the most sophisticated logging systems any hobby kernel has seen :^)

fiery turtle
#

lmfao thats kinda true, but i already dumped way too much time into studying how it handles every edge case trl

left orbit
#

lockless stuff is always fun as long as it works correctly

#

it can be extremely tricky to get right too

fiery turtle
#

the amount of barrier pairs and comments there do make me a bit scared tho

#

that maybe i wont make it in a week

left orbit
#

oh shit 💀

fiery turtle
#

like that log ring is truly cool, u can have an infinite number of cpus concurrently writing to it and then readers reading at the same time, and all u need for a reader's iterator is one u64 seqnum

#

i would probably care less about it if it wasnt exposed to userspace as /dev/kmesg etc

#

or maybe i should just say fuck it an do spin_lock() trl

left orbit
#

tbf that is probably good enough for any hobby os

#

and it will let you work on other important stuff

fiery turtle
#

most hobby osses probably dont even have a log ring, they just pipe the input string to sinks directly

#

but yeah idk, i kinda want it to be better than your avg os

left orbit
#

doesn't mean you can't have your kernel log ring be simple :^)

fiery turtle
#

this design is also nice because u can do the actual output work in a separate thread

fiery turtle
left orbit
#

so relatable

fiery turtle
#

to start the ultra kernel with a 3k loc log ring

#

that doesnt even have smp

#

or malloc

left orbit
#

if only i had the motivation to read about stuff like that

fiery turtle
#

well i just browsed the sources for like 10 hours total probably

#

until i got a literal headache

flat badge
#

ulog library when

fiery turtle
#

lol

#

i'd have to make tons of tests for it anyway

#

so maybe

#

if it's lockless that makes it nmi safe as well which is nice

flat badge
#

tbh the linux implementation looks way make complicated than the Managarm one

#

how does linux achieve NMI safety?

fiery turtle
#

everything is reentrant, there isnt a single critical section there

#

they have id consistency checks and are able to detect concurrent modifications of a descriptor

flat badge
fiery turtle
#

they store ID and STATE as a combined ORed value

#

that is atomically modified

flat badge
#

and how do they prevent the messages themselves from being overwritten?

#

writing descriptors in an NMI safe way is relatively easy

fiery turtle
#

they have 3 separate rings

#

the text ring is an array of [descriptor id, text data]

flat badge
#

an array?

#

so "text data" is fixed size?

fiery turtle
#

rings are all fixed size

#

text data is dynamic ofc

#

but it's reserved when allocating the descriptor

flat badge
#

so they have a sophisticated allocation algorithm for that?

fiery turtle
#

yeah

flat badge
#

sophisticated = not just circular reuse

fiery turtle
#

its very sophisticated

flat badge
#

ah

fiery turtle
#

well no

#

it is circular reuse

flat badge
#

but it jumps over stuff that is still in use by another context? or how does it work

fiery turtle
#

i can explain

#

so a new record is allocated via prb_reserve(), which accepts the needed text length.
The first thing it does is allocate a new descriptor by changing its state to reserved and advancing the descriptor ring tail pointer. It then allocates the text for this descriptor by advancing the tail text ring pointer, and then walking over it for the length of the needed text data and invalidating any descriptors currently referencing this text data (since text data has an inline header with descriptor ID that references this text, and text data is always aligned at 8 bytes to fit it)

#

so the older descriptors referencing text data in the new span are invalidated into reusable state

dense steppe
#

what if we prb_reserve a lot without ever finalizing, such that we wrap around?

fiery turtle
#

the reader does the following

desc = get_descriptor(seqnum)
memcpy(caller_buffer, desc->text, desc->size)
return desc_still_alive_and_has_the_same_id(desc);
#

so concurrent modifications of the descriptor are safe

fiery turtle
#

basically, it isnt allowed to recycle reserved descriptors

#

so if you reserve but never commit, the ring will stall

#

aka all new writers will be aborted

dense steppe
#

ah, ok.

fiery turtle
#

if it wraps around

dense steppe
#

and that voids messages?

fiery turtle
#

yup

#

but it's very hard to trigger, as you need a buggy writer or a writer that literally does a sleep between reserve and commit

#

and the default implementation of reserve() disables interrupts

#

so its expected that u do commit very quickly

dense steppe
#

so if I have one hundred thousand concurrent printk's some of them may be voided meme

fiery turtle
#

only if u have that many CPUs

#

because it disables irqs on reserve

dense steppe
#

yeah

fiery turtle
#

but the default implementation also scales the log ring according to max number of cpus

dense steppe
#

and AFAIK it has some memory per CPU for this too

#

yeah

fiery turtle
#

so you wont run into this

dense steppe
#

ingenious design

fiery turtle
#

yeah

left orbit
#

what happens on commit that makes the log descriptors not lost when it wraps around?

fiery turtle
#

wdym? thats the idea of the ring, if it wraps around the old entries are lost

#

there's klogd in userspace which journals kmsg entries

#

so they're always available

left orbit
#

ah that's the part i was missing

#

that's why dmesg goes back all the way to the first message

dense steppe
#

no

fiery turtle
#

nah dmesg reads kmgs directly

left orbit
#

oh?

fiery turtle
#

the ring is just pretty large

#

by default

left orbit
#

how large are we talking?

fiery turtle
#

so it fits everything just fine usually

dense steppe
#

if you can somehow perform lots of printk's (e.g. via a kernel module) and then do dmesg, you will see that it does not go back to the beginning

fiery turtle
#
  • max_number_of_cpus
dense steppe
fiery turtle
#

well 1 << 17 * AVG_MSG_SIZE (32)

left orbit
#

that would be 4M

#

it's not that bad

#

but yeah that makes sense

#

so it's just a set of really big ring buffers

fiery turtle
#

well it's 3 arrays

#

descriptors, log info, and text

left orbit
#

yup

#

they are still pretty big though

#

:^)

#

i wouldn't have thought to "waste" a few megabytes of memory for logging

fiery turtle
#

actually I lied, the default is 1 << 14

left orbit
#

so it can hold 16K "average sized messages"

dense steppe
fiery turtle
#
/*
 * Define the average message size. This only affects the number of
 * descriptors that will be available. Underestimating is better than
 * overestimating (too many available descriptors is better than not enough).
 */
#define PRB_AVGBITS 5    /* 32 character average length */

#if CONFIG_LOG_BUF_SHIFT <= PRB_AVGBITS
#error CONFIG_LOG_BUF_SHIFT value too small.
#endif
_DEFINE_PRINTKRB(printk_rb_static, CONFIG_LOG_BUF_SHIFT - PRB_AVGBITS,
         PRB_AVGBITS, &__log_buf[0]);
#

basically this is the default

fiery turtle
dense steppe
#

yeah

left orbit
#

interesting

fiery turtle
#
config LOG_BUF_SHIFT
    int "Kernel log buffer size (16 => 64KB, 17 => 128KB)"
    range 12 25
    default 17
    depends on PRINTK
    help
      Select the minimal kernel log buffer size as a power of 2.
      The final size is affected by LOG_CPU_MAX_BUF_SHIFT config
      parameter, see below. Any higher size also might be forced
      by "log_buf_len" boot parameter.

      Examples:
             17 => 128 KB
             16 => 64 KB
             15 => 32 KB
             14 => 16 KB
             13 =>  8 KB
             12 =>  4 KB
#

so 128KB, but - 5 bits because of text

#

so its actually under a meg

#

or even under 512KiB for all

#

and then it's 12 bits per cpu

left orbit
#

damn that's some crazy stuff lol

fiery turtle
#

or well, extra 4K of log ring per cpu

dense steppe
#

the kernel has a static char printk_ringbuffer[128 kilobytes]; or something, and then it reallocates using vmalloc at a later stage I think

fiery turtle
#

it reallocates using memblock

#

so the very early memory map allocator

#

before smp startup

dense steppe
#

ah

#

I had a similar thing

dense steppe
#

initmem, which was an initmeme in my old kernel

fiery turtle
#

i think x86 calls it here

dense steppe
#

however I did not have any printk ringbuffer

fiery turtle
#

it's definitely a huge overkill for my kernel lmfao

#

but i might give it a shot

#

i'll need all of the atomic helpers and barriers anyway

fiery turtle
dense steppe
fiery turtle
#

it was actually added only in 2020

#

its very new

#

and this commit description is already outdated

dense steppe
#

evolution

fiery turtle
#

stuff like this

flat badge
#

Managarm achives nmi safety by cancelling in progress memcpys to the log ring when an nmi happens

fiery turtle
#

in this case this isnt needed since a descriptor is either reserved or it isnt

#

and its guaranteed to be safe to memcpy if prb_reserve succeeded

flat badge
#

Yeah but the cost of that is that you need to handle the case that the ring wraps around while the nmi happens

fiery turtle
#

yeah they have two separate ID systems because of this

#

the seqnum, and the internal descriptor id which is limited to unsigned long bits - state bits

#

a lot of workarounds for 32 bit unsigned long

flat badge
#

Managarm's ring can't ever stall

#

since stuff is committed atomically with no pre-reservation

fiery turtle
#

well this one kinda cant as well unless every single CPU gets an NMI at the same time while its writing to the ring

#

and then writes in the NMI handler as well

#

then some entries might get dropped

#

since it scales for the maximum number of cpus at boot time

#

each cpu gets a 4K wiggle room by default

flat badge
#

Managarm's ring as a single ring buffer and it works like this on write:

  • it invalidates existing entries that'd overlap the new one
  • it copies the new entry to the ring
  • if the previous operation succeeded without being interrupted by reentrancy, it advances the head ptr
fiery turtle
#

so it's not lockless right

flat badge
#

It is

fiery turtle
#

oh also managarms ring doesnt support many readers as far as i can see

#

since dequeue is global

flat badge
#

Managarm is stateless at the reader side

fiery turtle
#

linuxes ring has no such thing as dequeue

flat badge
#

So it supports any number of readers

dense steppe
fiery turtle
#

any new reader will only read the new contents

#

that the previous reader hasnt seen

flat badge
#

A reader simply knows its position in the ring, checks if the entry at that position is still valid, copies out of the ring and checks that no invalidation happened in the meantime

#

No, readers are independent

fiery turtle
#

oh ok

#

yeah i guess its lockless but not concurrent

#

many writers will just keep spinning in retries

#

but its definitely a simpler design

flat badge
#

That's right, it's per cpu

#

And a kernel thread dumps it to sinks

fiery turtle
#

ohh wait

#

it has to collect records from every cpu's ring basically?

flat badge
#

yes

fiery turtle
#

i guess this is only bad because it it's hard to keep timestamp ordering

flat badge
#

Or rather, all cpus push to a centralized sink

#

But go to a per-cpu ring first

fiery turtle
#

cpus push themselves?

dense steppe
#

the strategy is to defer the work of pushing to the centralized sink/logbuffer/whatever to a context that can e.g. block on mutexes?

flat badge
#

The full story is this: logs go to per CPU ring buffer -> a per-CPU soft irq dumps them to a global sink -> a kernel thread serves the userspace visible /dev/kmsg

fiery turtle
#

how does this ensure timestamp ordering?

dense steppe
#

why would you need timestamp ordering?

#

Linux doesn't guarantee timestamp ordering.

flat badge
#

Essentially this separates the reentrancy from concurrency

fiery turtle
#

well because u want earlier logs to appear before later logs?

fiery turtle
flat badge
#

rdtsc?

fiery turtle
#

it does

#

u have no guarantees that a cpu pushes its earlier logs before some other cpus later logs

#

basically

flat badge
#

Linux messages are ordered by seqnum not by timestamp, aren't they?

fiery turtle
#

both

dense steppe
# fiery turtle wdym

alright.
thread level does sched_clock()
NMI
NMI handler does sched_clock(), prb_reserve() ..., returns
thread does prb_reserve

#

-> not ordered

flat badge
#

I don't think that's true, the /dev/kmsg docs specifically state that there is no guaranteed ordering

fiery turtle
#

dev kmsg docs generally kinda suck

fiery turtle
flat badge
fiery turtle
#

ok so prink grabs the timestamp on entry

#

so i guess its possible

#

but it would be an exceptional situation

#

more or less

flat badge
#

Well in general you can't guarantee both seqnum and timestamp order, right?

dense steppe
flat badge
#

Unless you do heavy synchronization around getting the timestamp

fiery turtle
#

if you really wanted to u could

#

yeah

#

i dont think its that useful

dense steppe
fiery turtle
#

but overall its nice if they come in order unless u get exceptional situation like NMIs

#

like managarm would just push in whichever order right

#

here its at least mostly in order i think

#

do u see any unordered ones in your /dev/kmsg?

dense steppe
#

I'm on my phone right now meme

fiery turtle
#

technically if two cpus log at the same time, but the other does it slightly later and then the first one gets preempted before prb_reserve this might happen

#

but strangely i dont see anything like that

dense steppe
#

but I've never seen unordered messages in dmesg. although dmesg might be doing some sorting of its own.

fiery turtle
#

actually i think the x86 kernel is usually non preemptible

#

so thats why

fiery turtle
#

well yours says preempt_dynamic

#

which means off by default

dense steppe
#

oh, really?

fiery turtle
#

yeah it can be overriden in the command line

#

but also it says CONFIG_PREEMPT=y, lemme check idk how these two cooperate

flat badge
fiery turtle
# dense steppe oh, really?

basically yeah, in dynamic mode preemption is off by default, unless the command line has preempt=none/voluntary/full/etc

#

so check you /proc/cmdline

dense steppe
#

ah

#

yeah it doesn't have preempt=

fiery turtle
#

if i understand correctly with your config it will enter the last else

dense steppe
#

yeah it goes into preempt_dynamic_full

fiery turtle
#

your /sys/kernel/debug/sched might contain the mode if u have that built

fiery turtle
dense steppe
#

or just dmesg shows it

fiery turtle
#

this is x86 right?

left orbit
#
[iretq@raptor linux-mlibc-jinx]$ sudo cat /sys/kernel/debug/sched/preempt
none voluntary (full) lazy```
#

arch linux does preempt=full apparently?

fiery turtle
#

they're always on the edge i guess

#

because it hasnt been stable on x86 iirc

dense steppe
#

yes this is x86

fiery turtle
#

lol

#

xr linux port when

left orbit
#

btw are you planning to open source your kernel from the start or will your work on it privately first?

#

i am kinda curious to see how it develops meme

fiery turtle
#

I mean its already open source, i'm just not upstreaming stuff yet because there isnt much to upstream

#

last commit 2 years ago trl

left orbit
#

well, yeah, i meant the new stuff you're working on :^)

#

(or will be working on, idk)

fiery turtle
#

yeah i will be upstreaming that stuff ofc

#

i need to decide if im dropping 32 bit support

#

i probably should because im never getting to driver dev then

hollow crescent
#

what purpose does it provide

left orbit
#

very robust logging

fiery turtle
#

That scales to any number of readers and writers

#

Also works under panic or any other condition

gentle peak
#

just spinlock and if an nmi happens during logging too bad

fiery turtle
#

True

frank canopy
#

dang now you're making me tempted to do the same

#

would take more stack space in my actual logging handler since I'll need to print out to a buffer though

#

rn my log handler just writes directly to the qemu debug port and I've been wanting to add other sink options for a hot minute now

fiery turtle
#

it takes 0 stack space

#

since you print out to a pre-reserved buffer

#

the buffer comes directly from the ring

frank canopy
#

id need to use a counting null-output writer and do the format in two passes then

jaunty fox
#

they went to a lot of effort around kprintf in linux

frank canopy
#

zig logging handler happens before the formatting so you can do a formatting write directly to output to save on format buffer if possible

jaunty fox
#

it was for decades the blocker to RTLinux™️ integration

fiery turtle
#

yeah they also did non-blocking consoles specifically for rt

#

a lot of work has been put into this

frank canopy
#

also im def not doing a full kprintf type thing that soon, i may consider myself ok at lockless using interlockedxxx but zig atomics take an ordering like cpp ones and i dont understand those at all on a good day let alone while having been sick for a week lmao

#

also i dont need realtime anything if thats why its so thoroughly nonblocking i just want nmi correctness in theory

fiery turtle
#

well linux atomics also take ordering

#

they just have simplified macros

jaunty fox
fiery turtle
#

nah macros dont, they abstract it away

#

and yeah they use barriers

#

they have e.g. atomic_read_acquire

#

which is an acquire barrier

frank canopy
#

the only atomics ive felt like i understood what i was doing using are the InterlockedXXX functions that microsoft has which iirc dont

fiery turtle
#

microsoft's ones have suffixes i think

frank canopy
#

well ive never used a suffixed version lol

fiery turtle
#

on x86 its not really that needed, only to protect from compile reorderings

#

because cpu stuff is mostly already serialized

frank canopy
#

yeah the docs for InterlockedCompareExchange say to use the aqcuire and release versions for itanium performance critical things

#

but thats it

vast kestrel
#

interlocked is x86 semantics :^)

#

C# to this day doesn't have atomicswith proper memory ordering

frank canopy
#

yeah and thats how i learned atomics and lockless

#

so i never learned proper ordering and now ive gotten too dumb to understand it lmao

fiery turtle
#

this is the perfect doc to understand it

frank canopy
#

ill give that a read

vast kestrel
#

do note, linux has a different memory model to the c memory model

#

because linux defined a memory model for themselves before the standard defined one

frank canopy
#

idk im using zig so i really dont know what would actually apply

fiery turtle
fiery turtle
frank canopy
#

people have sent me memory order stuff before but its always gone over my head lol

vast kestrel
frank canopy
#

it was one of my three things that i cant wrap my head around no matter how much i try but maybe this changes that (the other two things are the rust borrow checker and being able to read lisps)

vast kestrel
#

not like old gcc ports even listen to the standard memory model

fiery turtle
#

yeah

#

its also a very language lawyer-y thing

frank canopy
#

yeah my struggle isnt so much in understanding the basically-legalese spec terms its in translating that to practice

#

its like ok i can understand this combination of specification words but i have no clue what to plug in when actually writing code

fiery turtle
#

its probably the hardest part of concurrent programming

vast kestrel
#

I have a friend who did his thesis on memory orderings, and from him the only way to ensure that what you do is safe and to ensure all the barriers actually interact correctly with each other is to describe the memory in relations like happens-before

#

like, in practice things just "happen to work" because of how cpus handle things in the real world, but it quickly breaks down under the correct conditions of the cpu

frank canopy
#

the part that sucks for me rn is i know and get x86 semantics and am targeting x86 only but because of compiler reordering i have to learn the rest of this anyway

fiery turtle
#

The key idea is you make barrier pairs, so e.g. a release is paired with acquire somewhere

#

If you have multiple atomic accesses you don't want reordered you use a sequentially consistent ordering

vast kestrel
#

the pairs ensure the relationships between the memory accesses

frank canopy
#

ok cool

vast kestrel
#

the main goal is to not think about atomics on a timeline, but as a graph of accesses

frank canopy
#

oh its fuckin DAG ordering

vast kestrel
#

there is no timeline when dealing with memory, and the only way to ensure a happens-before is with the atomic barriers

frank canopy
#

ok that makes way more sense suddenly just saying it that way

slim panther
#

@fiery turtle do you already have a framework 13 dump or do you want it

#

i kinda wanna see what all the blobs are for

fiery turtle
#

i dont think i have seen any framework dumps

slim panther
#

insyde efi nooo

fiery turtle
#

thx

#

anything interesting there?

slim panther
#

dunno

#

a lot of ssdts

fiery turtle
#

Linux memory barriers and atomics have very stupid implied ordering and semantics, QEMUs seem a lot more sane so I'm stealing the idea

flat badge
#

Why don't you just use the c11 memory model?

fiery turtle
#

wdym

#

like _Atomic?

flat badge
#

yes

fiery turtle
#

qemu uses the c model, just with their own wrappers using gcc's builtins

flat badge
#

You can also just use stdatomic.h without weird wrappers

fiery turtle
#

i hate it because it requires _Atomic prefix which is a special type which doesnt work with anything and changes the default behavior for operators

#

is stdatomic even a freestanding header?

flat badge
#

yes

jaunty fox
flat badge
#

Just use the aliases like atomic_uint32_t etc

jaunty fox
#

the __builtin_atomic intrinsics are basically once removed from it

fiery turtle
#

ah

flat badge
#

I'd use stdatomic.h just because it's standard and well established

#

Writing correct concurrent code is hard enough

fiery turtle
#

i really dont understand how they help with anything

#

gcc builtins work well enough

flat badge
#

So if you want to talk to others about it / get code reviews etc it's just an extra burden if you're using your own barriers

jaunty fox
#

the main niggle people are having with the c11 atomics is that they want memory ordering parameters to the operations while most people think rather in terms of explicit barriers

fiery turtle
#

is smp_Xmb() harder to read than atomic_thread_fence(...)?

fiery turtle
#

how does it help?

slim panther
#

there it's called atomic

jaunty fox
flat badge
#

Gcc built-ins are fine as well

#

But smp_mb() etc is stupid

jaunty fox
#

and nice as the type safety may be i found some subtle differences between clang and gcc's take on them and that put me off that stuff altogether

fiery turtle
#

^

fiery turtle
flat badge
#

What exactly are the guarantees of smp_mb()?

#

No offense, but if you think that this question is easy to answer, you probably haven't done enough research yet

fiery turtle
flat badge
#

That fact alone is not obvious at all

fiery turtle
#

why is it not obvious?

#

you know there's a read-modify barrier, you know there's a write-modify barrier

flat badge
#

For example, why is it not a full memory barrier?

fiery turtle
#

because linuxes model was invented before this stuff was added into the standard

flat badge
#

Yeah but how many ppl know the intricacies of the linux model? Probably 20?

#

And how many ppl know the c11 model? Probably many thousands

fiery turtle
#

to be fair they have the new atomic header which is closer to that

flat badge
#

Yeah but my point is that for a greenfield project you shouldn't go with something like the linux model at all

fiery turtle
#

ofc

#

thats why im doing the gcc builtins

flat badge
#

Then we're not disagreeing at all

#

The gcc built-ins follow the c11 model

fiery turtle
#

you're probably gonna hate qemu tho trl

#
#define smp_mb()                     ({ barrier(); __atomic_thread_fence(__ATOMIC_SEQ_CST); })
#define smp_mb_release()             ({ barrier(); __atomic_thread_fence(__ATOMIC_RELEASE); })
#define smp_mb_acquire()             ({ barrier(); __atomic_thread_fence(__ATOMIC_ACQUIRE); })
dense steppe
dense steppe
fiery turtle
#

didnt know about the sync ones

#

whats the diff?

dense steppe
#

the __sync primitives are old and outdated

fiery turtle
dense steppe
#

all the cool kids use __atomics

dense steppe
fiery turtle
#
/* Manual memory barriers
 *
 *__atomic_thread_fence does not include a compiler barrier; instead,
 * the barrier is part of __atomic_load/__atomic_store's "volatile-like"
 * semantics. If smp_wmb() is a no-op, absence of the barrier means that
 * the compiler is free to reorder stores on each side of the barrier.
 * Add one here, and similarly in smp_rmb() and smp_read_barrier_depends().
 */
#

no compiler barrier there

dense steppe
#

-_-

fiery turtle
#

which is kind of crazy

dense steppe
#

why

#

just why

#

wtf

#

GNU, wtf?

fiery turtle
#

yeah idk

#

why the hell did qemu just slap a seq_cst everywhere

dense steppe
#

as opposed to dealing with the intricacies of acquire/release

#

not to speak of consume

fiery turtle
#

consume is only relevant for dead arches i think

dense steppe
fiery turtle
#

yeah i still dont understand entirely when u need seq_cst

fiery turtle
flat badge
#

For example this: #programming message

fiery turtle
#

This one makes sense

vast kestrel
vast kestrel
flat badge
#

Consume is not only relevant for alpha btw

#

Alpha is the only arch where consume needs an explicit fence

#

But you can exploit that dependencies imply ordering on other archs as well

#

It's generally not worth it over acq/rel though except in niche cases

calm latch
fiery turtle
calm latch
fiery turtle
#

Or you do multiple relaxed atomic stores followed by a stricter barrier

calm latch
#

you can just make the last store release?

fiery turtle
#

That works too

#

As far as I understand barriers and normal ordering flags for other operations are identical

calm latch
#

maybe only copies from userspace

#

(at which point you don't need hardware barriers?)

fiery turtle
#

memcpy(data)
atomic_fence(release)
data_is_set.store(true, relaxed)

calm latch
fiery turtle
#

Perhaps

#

this has some examples

fiery turtle
# flat badge Hm?

x.store(y, release) is the same as x.store(y, relaxed) fence(release)

flat badge
#

A release barrier is not the same as a store-release

fiery turtle
#

well the cppref says it is

flat badge
#

No that's wrong

fiery turtle
#

how?

flat badge
#

The latter is stronger

jaunty fox
flat badge
#

The barrier orders all proceeding stores vs all following stores

#

While the store release orders all proceeding stores vs. exactly the store done by the store-release

fiery turtle
#

how can the barrier order stores that come after the barrier

#

unless im misunderstanding your point

flat badge
#

That's the point of release semantics

flat badge
fiery turtle
#

release semantics means all stores before the barrier are not reordered with the following stores

#

im not sure what u mean

flat badge
#

With the barrier after the store, it does nothing

fiery turtle
#

true

flat badge
#

Acquire/release semantics mean that if an acquire operation reads the value written by a store-release, then all future reads will read newer (or just as new) values than the value that was read by the read acquire

fiery turtle
#

yeah but still what exactly is the difference between a release barrier and just a store release

flat badge
#

If i do

a.store_relaxed(1)
b.store_release(2)
c.store_relaxed(3)
#

And another thread read acquires c = 3 and then reads a, there is no guarantee that it'll read a=1

fiery turtle
#

I think this has some answers

flat badge
fiery turtle
#

So you're saying relaxed stores can still be reordered with respect to each other

flat badge
#

No I'm saying a release barrier acts on all following stores while a store release acts on one store

#

A release barrier is strictly stronger than a store release

fiery turtle
#

How can a happen after b

flat badge
#

Compare the snippet that i posted above to:

#
a.store_relaxed(1)
release_barrier()
b.store_relaxed(2)
c.store_relaxed(3)
#

Then the release barrier affects c as well

#

While the store release only ever affects b

#

If a read acquire now reads c=3, a following read is guaranteed to read a=1

#

Which is not true for the store-release

fiery turtle
#

So tldr barrier affects all atomic stores and a store ordering only affects this store

flat badge
#

yes

fiery turtle
#

How is this even possible at CPU level

fiery turtle
flat badge
#

Yes

fiery turtle
#

Oh ok makes sense I think

#

Thanks

flat badge
#

I have no idea how it works at the hw level but at least aarch64 and rv have explicit acq/rel load/store instructions, so it can apparently be optimized more aggressively in hw than barriers

fiery turtle
#

interesting

#

the acq rel stuff on x86 is just a no-op other than the compiler barrier i think

#

a seq cst barrier might emit mfence

frank canopy
#

realising i dont think zig even has an equivalent to barrier()

fiery turtle
#

Yeah i wouldn't be surprised

lilac knoll
fiery turtle
#

Yeah qemu seems to not trust its developers

lilac knoll
#

seems not worth using a wrapper

lilac knoll
fiery turtle
#

Well independent stores before release are sequenced before the atomic store, that's kind of the point, so you cant just wait for this specific store I think

lilac knoll
#

is the question 'what's the difference between release store and release barrier in hw'?

fiery turtle
#

Basically

kindred beacon
#

good shit

fiery turtle
lilac knoll
# fiery turtle Basically

I don't think there's a difference on modern hw because stores pretty much have to retire in-order anyway: reordering stores A and B is risky because there may be a branch mispredict or exception that occurs between A and B, so this is only possible when you know that both instructions are non-speculative

lilac knoll
#

(what I'm saying is that formally there is a difference in the ISA between store-release and fence-release, so you still need different instructions for those, but I don't think that a fence release would realistically be worse because store-store reordering is too difficult anyway)

#

nice, another couple hours of time wasted thinking about memory orderings

flat badge
#

that's assuming that the architecture has release fences and release stores though

#

for example on risc-v you get acq/rel with no extra instructions (since it's a bit in the load-reserve/store-conditional isns)

#

but a fence needs an explicit instruction

#

and a fence may also degrade to a stronger fence than necessary

lilac knoll
fiery turtle
#

Why?

lilac knoll
#

I just misremembered how store buffering works entirely

#

once a store retires, it's known to be non-speculative. at that point it gets entered into the store buffer

#

so entries in the store buffer can drain in whatever order the CPU likes. on x86, due to TSO, this must (at least appear to) be FIFO

#

but on aarch64 it's pretty plausible that a store could jump ahead of a prior entry in the store buffer if there's a cache miss or something

#

a store release effectively says 'this store cannot be moved ahead of an earlier store'

a fence-release says 'any later stores cannot be moved ahead of an earlier store'

so a cpu could in theory see the following sequence:

store 1
store-release
store 2

and reorder this to:
store 2
store 1
store-release

whereas a fence-release prohibits this

#

I do suspect this is a possible reordering that aarch64 stlr permits in practice but I'd need to cook up a litmus test to demonstrate that

fiery turtle
#

interesting

lilac knoll
#

I could be completely wrong again but who knows

dense steppe
#

hmmm, that's a very long RSDP

fiery turtle
#

the address is bogus as well

dense steppe
#

no. the address is the copy in the multiboot data

fiery turtle
#

are you giving it the v2 version of the tag?

#

otherwise it cuts off the extended part

#

and uacpi gets garbage

#

managarm ran into this as well

dense steppe
fiery turtle
#

do u handle misaligned mappings correctly

dense steppe
#

yeah, I'm very sure I do

fiery turtle
#

yeah idk but im pretty sure this has something to do with multiboot crap

dense steppe
#

also here's the code that "finds" the RSDP:

    multiboot_tag *rsdp1 = nullptr, *rsdp2 = nullptr;
    for (multiboot_tag *tag : mb2_tags) {
        switch (tag->type) {
        case MB2_TAG_RSDPv1:
            rsdp1 = tag;
            break;
        case MB2_TAG_RSDPv2:
            rsdp2 = tag;
            break;
        default:
            break;
        }
    }

    if (rsdp2)
        rsdp1 = rsdp2;
    if (!rsdp1)
        panic ("No ACPI RSD PTR was provided by the bootloader.");

    acpi_set_rsdp (virt_to_phys ((uintptr_t) rsdp1) + 8);
dense steppe
fiery turtle
#

00 is what qemu sets it to

fiery turtle
#

see if they make sense

#

also how does your virt_to_phys work

dense steppe
#
static inline uintptr_t
virt_to_phys (uintptr_t x)
{
    return x - HHDM_OFFSET;
}
#

kernel direct map

fiery turtle
#

are you sure you construct it correctly?

dense steppe
#

100%

fiery turtle
dense steppe
#

sure, I'll just have to grab the multiboot definitions for that

#

1sec

gentle peak
dense steppe
#

ah. that's it.

#

because everything seems to work, it loads all the other tables correctly etc.

dense steppe
#

it is ah the linked code

gentle peak
#

oh sorry yeah that's rsxdt

fiery turtle
#

thats {R,X}SDT

#

thats retrieved from RSDP

gentle peak
dense steppe
#

but the RSDP handling in dump_table_header is incorrect

#
    if (!uacpi_memcmp(hdr, ACPI_RSDP_SIGNATURE, sizeof(ACPI_RSDP_SIGNATURE) - 1)) {
        struct acpi_rsdp *rsdp = hdr;

        uacpi_info(
            "RSDP 0x%016"UACPI_PRIX64" %08X v%02X (%6.6s)\n",
            UACPI_FMT64(phys_addr), rsdp->length, rsdp->revision,
            rsdp->oemid
        );
        return;
    }
gentle peak
#

seems to be a purely cosmetic issue though

fiery turtle
#

ah, the dump function is wrong

#

yeah fair

dense steppe
#

just out of curiosity, apart from faking a RSDP yourself, is it possible to initialize uACPI from a RSDT or XSDT?

#

afaict no

fiery turtle
#

nope

dense steppe
#

anyway. daily atomic warcrime:

#

note the relaxed

fiery turtle
#

probably need an RCU here

#

or just a console_lock

dense steppe
fiery turtle
#

then relaxed should be fine no?

dense steppe
#

yup, it is fine.

gentle peak
#

you probably don't even need an atomic there except for the initial load of the head, if there's no console_unregister the next field of a console in the list will never be written to again

#

unless you insert at tail instead of at head

dense steppe
#

it is fine for two reasons:

  1. seq_cst load in printk_emit synchronizes with seq_cst store in console_register, which happens after past seq_cst stores. thus the seq_cst load happens after all seq_cst stores it can see, and the relaxed load(s) cannot be moved before.
  2. I wasn't planning on having more than one console for the time being meme
fiery turtle
#

why not just acquire here and release in register instead?

#

you have one writer and one reader

dense steppe
#

idk, because I felt like it

#

anyway I will replace this with a 3000 LoC message ringbuffer sooner or later anyway meme

fiery turtle
#

or well, if you have multiple registers, you probably want an ACQ_REL cmpxchg loop in register

#

and just acquire here

dense steppe
fiery turtle
#

L

dense steppe
# dense steppe

(printk does not take console_lock. printk takes another lock instead.)

fiery turtle
fiery turtle
#

should i get rid of 32-bit support in the ultra kernel think3d