#Ultra
1 messages · Page 12 of 1
smbios here is just to detect certain hypervisors, yeah?
and maybe qemu config reading ig
smbios support is for very specific quirk handling or hardware detection
ill also use it for stuff like that
detecting broken hardware and working around it
ah
but like you have 3 different possible reference timers + several ways to get the frequency, if those are not available
its not that difficult to add support if u want
just an array of stupidly formatted structs
also 3 stupidly formatted structs
I forgor
efi has a configuration table that just tells u where to find them in memory
like efi runtime things, where you need to be mapping memory in specific locations, etc.
same as it does for acpi, theres just a "table" but its literally a pointer to the rsdp
i got an impl of that if youre looking to do it, its only for runtime services though
like the osdev wiki is like "just parse madt and you're set" and I wasn't even understanding how important it (acpi) actually was
and you only need runtime services for real when the uefi firmware takes ownership of the RTC on non-x86 platforms (like arm i know it happens)
uSMBIOS when?
but it's just going on and on and on, you have no clean implementation, you have to support a lot of permutations, and random standards, and don't get me started on quirks
come on its 1k line tops for everything 
welcome to osdev its all like this tbh, but also thats the fun part imo
like different gpio and ec controllers in acpi
and then I thought it would be nice to support i2c or whatever, but I haven't even started
like it's just random drivers after random drivers
hence why like a solid third of my time so far has been trying to make the best io abstraction layer i can
maybe embedded stuff isn't even just bad, since you're targeting just one machine. like you're doing the same amount of work to support all of its possible permutations
you can abstract anything you want via aml, for example
well aml can talk over i2c
and it does often times
thats why u dont need a driver
but you need a driver for i2c
no apple has some proprietary thing as always i think
but yeah its just hid over i2c
I'll just make everything a capability (a.k.a. clone mach)
anyway
I think part of why I feel this way is also because I'm doing my userspace in 3 languages for no reason
keyboard is ps/2 because lol
Because then I'm writing separate abstractions/interfaces for C, C++ and Rust
And as much as I like C++, there's kinda no point in writing it with C and Rust
loooks like even for i2c u will need smbios 
a lot of quirk stuff there
wait did i read that right
x86 android tablets??

designware... 🤪
Every time I look in this channel infy is in some random sidequest inside the linux source
lmao
breaking news: ultra gets its nth useless x86 quirk added instead of anything useful
yes they werent bad either
there even are x86 phones
In 2005, Steve Jobs offered Intel the chance to power the iPhone. Intel's CEO said no. This is the story of the worst business decision in modern history—and how ARM conquered the world while the king of chips got left behind.
Get ready for Snazzy Labs merch! - https://copland.supply
Follow Snazzy Labs on Twitter - https://snazzy.fm/fT
Follow...
Imagine using this title but putting an ASUS phone in the thumbnail
well asus made the intel phones. apple did not

I have one
Intel Atom x86 Android tablet
with PowerVR iGPU

wait why the hell does vmware provide an incorrect ioapic id
How are you getting it?
Potentially a stupid question, but you're treating it as 8 bits wide right? (I wasn't and got the same issue on my laptop)
i mean i think so:
struct ioapic_reg_id {
u32 rsvd : 24;
u32 id: 8;
};
UB?
wrong bits
aren't bits 0..7 the version?
this code uses bits 24..31 for version
although i can't say for sure because i can't find a spec that isnt older than me 
oh wait sorry im dumb
idk why i thought you were trying to rect the version instead of the id
wiki says this is the proper bitfield 💀
why do all the apic things have strange registers like this
with the bits crammed into the middle
ioapic ids used to be limited by 4 bits
they're 8 now though
nope, i checked the raw u32 that i get back from the io access
its just all zeroes
vmware just provides an incorrect id
does bit 7 have some other meaning according to some obscure spec?
0 vs 128 is quite sus
Are you accessing io with asm? 
ahh damn
thats what i thought but cant find anything relevant
num_entries that i get is correct so
i guess ill have to figure out how to put my bzimage into an iso and check via a linux
But like if it's just volatile uint32_t, maybe it's the same thing that happened to monkous
if you get me an ISO i can boot up QEMU rn for ya
or maybe qemu can boot the image?
i dont get the warning on qemu so
qemu reports acpi id 0 and actual is 0 also
the problem is this proprietary vmware thing
i wonder if you could use WSL and run QEMU under that instead of vmware?
i havent used vmware and years though
and i can confirm it does work
quite well tbh
ill just ask a clanker how to put my custom linux build into an iso
then boot that in vmware
and make sure it also gets the bogus 0x80 ioapic id and 0x00 actual
uhhh i hope whatever clanker produced will work
I have an Asus PDA that has an Intel XScale x)
Asus makes alot of weird and cool stuff ngl
Or at least made, idk what they do today
crazy but yeah it works great
okay this is QEMU, now lets try vmware
yess i was right
vmware skill issue for reporting bogus ids
[ 0.467238] IOAPIC[0]: apic_id 128, version 32, address 0xfec00000, GSI 0-23
And linux does continue to treat it as id 128
maybe the acpi reported id doesnt have to match physical?
nah it does
well at least according to the linux code that hands out unique io apic ids
it wont work correctly if reported != actual
@inland ridge sorry to bother you, do you maybe happen to know if its some sort of a special vmware quirk that in ACPI tables it reports an IOAPIC id that doesn't match the actual IOAPIC id stored in the id reg?
i've verified via printfs in linux code above
actually it seems to be a common theme since vbox does it as well
vbox code
now i see
MP tables guarantee that every apic id is unique even between IOAPIC and LAPICs
so its MP tables compat
So which one is the real ID
the one stored in the ioapic ofc
that is also required by the SDM
since in early versions, there was really a bus between the APICs
u sure? on all of these setups bsp apic id is 0 and ioapic id is also 0
does mangarm check ioapic and lapic id collisions then?
i definitely didnt see such code in linux
hm?
what does it achieve?
ioapic ids are writable, you can fix any collisions
i guess
and mp spec tells u that u should do that too
But either: the system is so old that it still uses the apic bus in which case the system would just be broken
or it is newer than that and then it doesn't matter
so on modern systems ioapic and lapic ids dont collide with each other so it just happens to work willy nilly?
on modern systems, I/O APICs just send an MSI to the CPU
how did it work on old systems?
there was a separate bus with the apic IDs (or rather, their ArbIds == initial APIC ids) as addresses
and that bus was shared between lapics and ioapics?
yes
ah ok
^ the bus message format is described in that section
for interrupts and eois etc
ill check it out
but it's not used on P6
ah actually it's not used by > Pentium 4, not P6
nvm just took 10 years
so what do i do if ioapic is is larger than 4 bits
it's not on these old systems
but newer ones also need eoi or no?
in any case, ioapic ID is completely irrelevant on anything remotely modern
the ArbId is the originator here
EOI is a broadcast
originator == lapic id?
yes
technically the lapic has a separate register for arb ID but it matches lapic ID on initialization
yeah ioapic does also
but this eoi message is not software generated correct?
it is generated when you write the lapic's eoi register
ah
and eoi broadcast is on
you need to use that (only) if you disable eoi broadcast
it was also not in the original ioapic
there are cases where you need to disable eoi broadcast
since eoi broadcast matches based on vector and lapic id alone
and not on ioapic
IIRC on modern systems, it also doesn't match based on lapic id
which means that if you use the same vector on different CPUs and some of the uses are level triggered you need to disable broadcast
hmm
/*
* IO-APIC versions below 0x20 don't support EOI register.
* For the record, here is the information about various versions:
* 0Xh 82489DX
* 1Xh I/OAPIC or I/O(x)APIC which are not PCI 2.2 Compliant
* 2Xh I/O(x)APIC which is PCI 2.2 Compliant
* 30h-FFh Reserved
*
* Some of the Intel ICH Specs (ICH2 to ICH5) documents the io-apic
* version as 0x2. This is an error with documentation and these ICH chips
* use io-apic's of version 0x20.
*
* For IO-APIC's with EOI register, we use that to do an explicit EOI.
* Otherwise, we simulate the EOI message manually by changing the trigger
* mode to edge and then back to level, with RTE being masked during this.
*/
static void __eoi_ioapic_pin(int apic, int pin, int vector)
{
if (mpc_ioapic_ver(apic) >= 0x20) {
io_apic_eoi(apic, vector);
} else {
struct IO_APIC_route_entry entry, entry1;
entry = entry1 = __ioapic_read_entry(apic, pin);
/* Mask the entry and change the trigger mode to edge. */
entry1.masked = true;
entry1.is_level = false;
__ioapic_write_entry(apic, pin, entry1);
/* Restore the previous level triggered entry. */
__ioapic_write_entry(apic, pin, entry);
}
}
some cursed stuff going on here
thats a bit in some lapic register?
yes
i wanna check if linux messes with it
eoi broadcast?
no i mean where it disables the lapic eoi broadcast to switch to this ioapic reg
(you cannot use both at the same time)
probably unconditionally, if it is supported
as i said, eoi broadcast has issues with multiple uses of the same vector for different purposes
you're probably looking in the wrong place
probably
yeah as far as i can see it always does both EOIs
idk where it disables broadcast tbh
the apic code in linux is a fucking mess but
or maybe its just always disabled and it always does this weird eoi with completely disabling an ioapic redirection
@carmine token do u just completely skip the lapic eoi if this broadcast thing is disabled?
No you need the lapic eoi anyway
oh ok then maybe it starts to make more sense
So in the end you do want to program it per spec, no?
if u want to be more spec compliant than linux u can
I think you just don't need to care about ioapic id
but linux literaly doesnt even check whats set in the id reg so
i dont think u should either
The lapic eoi is needed to clear the ISR register
even for edge
The ioapic handling only matters for level
which reg disables broadcast?
yeah i think it doesnt
maybe it just EOIs the IOAPIC twice then
@carmine token i think i get it, the ioapic EOI callback is only called on level interrupts
and broadcast is only for edge triggered
or actually no, the broadcast is also for level(?)
yeah this is confusing af
ig unnecessary eoi on level doesn't hurt but this seems like an inefficiency in linux code
the tmr check just checks if it's level triggered
It's not a magic number it just gets the TMR bit corresponding to the irq
wait so
ioapic eoi is only used if there's a level triggered interrupt configued as edge??
Ah wait, it checks if it's NOT level triggered
So this just works around a quirk
And it doesn't use explicit ioapic eoi in the normal case
but why would a level triggered interrupt be configured as edge on the cpu?
Ig buggy hw? The cpu/lapic doesn't know if an irq is level triggered, it just does what the ioapic tells it
It sets TMR if the ioapic says that the irq is level
so e.g. fw tells it to expect edge but we find out via TMR that its actually level?
TMR is set on each irq raise
So ig there are ioapics that send a wrong level/edge bit when raising the irq
ah so actually the other way around
ioapic reports an incorrect triggering to the cpu
right so now it makes sense, by default it only does an EOI via LAPIC, which EOIs IOAPIC automatically, but that only works for level triggered interrupts that are detected as such via TMR
if we find out that the ioapic was programmed as level but it reported edge we must ack it manually
is there any comment that states when this TMR vs. ioapic state desync happens?
Ah, so it's probably only very old hw
some crazy shit
but still annoying
its funny that its supposedly like very old ioapics only, yet they have a code path that uses the new directed eoi feature
see the last paragraph of that comment
ohhh lmao
ok i support neither cpu offlining nor old crappy io apics
so im good for now 
so like do edge irqs not require EOI at all or?
it does apic_eoi() unconditionally no?
well the function is called ioapic_ack_level
not at the IOAPIC level
ah i think i get it
theres .irq_ack and .irq_eoi
the former is set by lapic and is responsible for edge
it doesnt have an eoi callback tho
and eoi callback is only set by ioapic
so it might just be different entries in the hierarchy responsible for different irq types
its x86 specific weirdness i think
doesn't the lapic eoi lower the tpr too?
sorry, the ppr i mean
which is basically the "real tpr"
and lapic eoi clears the ISR bit
yep
so if you never send the lapic eoi then youre effectively never lowering the TPR from the interrupt even though you never use the tpr manually
(arm gic works the same way but with slightly different names)
i mean you will also never get that interrupt again because of ISR
but also nothing with a lower vector number
the TPR also prevents other interrupts from the same prio level
aka the same first four bits of the vector number
the ioapic literally just holds the interrupt on if its a level interrupt until it gets an eoi. this can be done by the broadcast when you do lapic eoi if the tmr is level or manually by the os at any condition, but the lapic eoi is still always required to stop its ISR bit being held on (which masks a bunch of other interrupts)
yeah i've already figured it out
the thing is in linux differnet irq chips are responsible for different triggering which is a bit annoying
or in x86 specifically for ioapic<->lapic interaction
ah
so it took a while to work out wtf is happening there
yeah that sounds messy
its surprising vbox is such a bad hypervisor
it has 0 pv support
and doesnt even set the hypervisor bit
i once ran into a bug on vbox where it ignored the ioapic mask bit in some situations
which made Managarm unusable
i think this is fixed now though
didnt they also have a bug where they messed up the signature and it was reversed or smth
idk
well vmware is closed source and commercial only
yeah but the free one is severly restricted in what it can do
or at least it was when i tried it last
oh ok
closed source is a serious issue tho i agree
they dont have to make like an open source license but could at least publish the code
realistically KVM is the best VM anyway unless you need vmware enterprise features
and the enterprise features are more around management and orchestration than they are about feature support
yep
doesn't AWS also run on KVM now? (they used xen in the past but iirc they switched)
good q
nah, full vmware workstation is available for free now (for consumers, not businesses)
you're thinking of the former vmware player
though, I think the macos version (fusion?) is still restricted compared to workstation, but it's possible the featureset has improved
I wish they would open source it
Like wtf its not the 90s
Even oracle did it with vbox
Or do they have such crazy revolutionary code there they're afraid people will steal or something
vbox was OSS very early though
no, it's just that they're targetting a market segment that doesn't care about open source
I mean free contributions and fixes are always nice since they now ship a free version no?
What's the downside
ig the most obvious downside is that it makes it easier to steal your product
i.e., run the code without paying for it
But why steal a free product?
it's not free, right? it's non-commercial
free for non-commercial is not the same as overall free yeah
and there are lots of companies in non-western countries who won't care about the license even if it bans commercial usage
Well you can still just use it commercially if you wanted to
Same way u can just compile the code and also use it commercially
Or u mean in that case it would be illegal?
Tbh they could just pick a license type like that also
it is a license violation in any case but some ppl will not care
and opening the source makes it significantly easier to circumvent protections
Wasn't Broadcom extorting money from a lot of people lately?
the other part is that they probably don't expect contributions that are impactful enough to justify the costs
of open sourcing
Probably
i remember vbox in the past had a proprietary extension pack that added support for things like xhci
Lmfao
that was free for personal use but not business use iirc
Bro seriously
at least xhci is, i dont even remember what else the pack included
but i dont recall seeing any mentions to it in vbox 7
Still does
damn
looking at the features they are pretty boring/useless
The Oracle VirtualBox Extension Pack is an optional, separately licensed, installation package that includes these additional features:
VirtualBox Remote Desktop Protocol (VRDP) server. [...] This allows remote clients to connect to a VM using RDP. [...]
Host webcam passthrough. [...]
Intel PXE boot ROM.
Disk image encryption with AES algorithm. [...]
Cloud integration features. [...]
``` only the last point seems like something one could forseeably need
Lmfao
i assume webcam passthrough does it in a way where the host can still use it
since you can passthrough whole usb devices already
Linux LARP mode activated
(with hw name also dumped in stacks)
ill also add other info a bit later (like cpu, comm, kernel version etc)
well i dont even have an idea of comm atm so thats gonna take some time
it's funny that the idle thread on linux is called swapper
when line numbers in call stack
linux has weird naming all over the place
probably because historically it did swapping or something?
static void smbios_setup_hardware_identity_string(void)
{
char ident_str[256];
char *cursor;
int this_write, bytes_left = sizeof(ident_str);
struct smbios_id id;
bool non_empty = false;
cursor = ident_str;
if (smbios_get_id(SMBIOS_ID_SYSTEM_MANUFACTURER, &id))
SMBIOS_ID_PRINT_ONE("%s", id.str);
if (smbios_get_id(SMBIOS_ID_SYSTEM_NAME, &id)) {
if (non_empty)
SMBIOS_ID_PRINT_ONE(" ");
SMBIOS_ID_PRINT_ONE("%s", id.str);
}
if (smbios_get_id(SMBIOS_ID_BOARD_PRODUCT, &id)) {
if (non_empty)
SMBIOS_ID_PRINT_ONE("/");
SMBIOS_ID_PRINT_ONE("%s", id.str);
}
if (!smbios_has_id(SMBIOS_ID_BIOS_VENDOR) &&
!smbios_has_id(SMBIOS_ID_BIOS_VERSION) &&
!smbios_has_id(SMBIOS_ID_BIOS_RELEASE_DATE))
// No BIOS information available :(
goto done;
if (!non_empty)
/*
* We don't know what hardware we're on, but at least we know the BIOS
* version. Let's do what we can.
*/
SMBIOS_ID_PRINT_ONE("Unknown Hardware");
SMBIOS_ID_PRINT_ONE(", ");
if (smbios_get_id(SMBIOS_ID_BIOS_VENDOR, &id)) {
bool contains_bios;
contains_bios = str_contains(STR(id.str), STR_CONSTEXPR("BIOS"));
SMBIOS_ID_PRINT_ONE("%s", id.str);
if (!contains_bios)
SMBIOS_ID_PRINT_ONE(" BIOS");
} else {
SMBIOS_ID_PRINT_ONE("Unknown BIOS");
}
if (smbios_get_id(SMBIOS_ID_BIOS_VERSION, &id)) {
SMBIOS_ID_PRINT_ONE(" ");
SMBIOS_ID_PRINT_ONE("%s", id.str);
}
if (smbios_get_id(SMBIOS_ID_BIOS_RELEASE_DATE, &id)) {
SMBIOS_ID_PRINT_ONE(" ");
SMBIOS_ID_PRINT_ONE("(%s)", id.str);
}
done:
if (!non_empty)
// Not enough data to make a meaningful identity string
return;
log_set_hardware_identity_string(ident_str);
pr_info("%s", ident_str);
}
Least overcomplicated code for no reason
but IMO the end result looks decent
VMware
VMware, Inc. VMware20,1/440BX Desktop Reference Platform, VMware, Inc. BIOS VMW201.00V.24866131.B64.2507211911 (07/21/2025)
VBox
innotek GmbH VirtualBox/VirtualBox, innotek GmbH BIOS VirtualBox (12/01/2006)
QEMU
QEMU Standard PC (Q35 + ICH9, 2009), SeaBIOS 1.16.3-debian-1.16.3-2 (04/01/2014)
QEMU+EDK2
QEMU Standard PC (Q35 + ICH9, 2009), Ubuntu distribution of EDK II BIOS 2024.02-2ubuntu0.7 (11/27/2025)
Maybe it shouldn't try to append BIOS if it was booted via UEFI lmfao
QEMU Standard PC (Q35 + ICH9, 2009), Ubuntu distribution of EDK II UEFI 2024.02-2ubuntu0.7 (11/27/2025)
Ok that looks better 
Do you have this code somewhere, for me to steal look at? (I couldn't find it in your Ultra repo...)
Not upstreamed yet, soon
nice
didnt know my unknown hardware fallback will ever be used
what the hell is my linux doing
are you reading linux logs and larping as it
nah i just wanted to check how it handles absten hardware info in smbios
way worse than me 
lol
but yeah it seems linux hangs on bochs
also my smbios handling is not as bad so officially better kernel 
also linux tainted bochs because cpu-out-of-spec apparently lol
What are all of those msrs
E8 is IA32_APERF apparently
Interesting, why would it spam it forever?
maybe thats why it hung
but it should've caught the gpf and stopped there
or maybe bochs doesnt gpf in this case
ignore_bad_msrs=1
thats probably why
oh ok linux triple faults
looks like it really wants that msr
Let the ultimate larping begin
struct smbios_match vmware_detect[2] = {
{
.name = "VMware System",
.matches = {
SMBIOS_FUZZY_MATCH(SMBIOS_ID_SYSTEM_SERIAL_NUMBER, "VMware")
},
},
{},
};
bro
also thats like the only way to detect bochs
it doesnt even set the hypervisor bit
same for vbox actually but that has no paravirt for the kernel
just had a clanker roll a strstr for me 😭
dawg
i know
before i forget i need to finally invent free_after_init annotations for code and data and slap it onto most init functions
i have [[__init]]
for both code and data?
no only code
oh ok
i dont think i have init only data
hm i already have a ton of early data
Why do you need to detect them?
e.g. acpi buffer, early per-cpu etc
i don't differentiate between early and normal percpu
i just reuse it
the only thing that comes to mind is limine requests, but those are in the text section anyways
because they come at the start
what do u mean by them
in the text segment
hm
hypervisors
for most hypervisors just using cpuid and signature, for some u need smbios matching (like vmware sometimes)
how are u gonna free that stuff if u dont even page align it
ah
Limine mentioned
peakl
how can it cost more memory if u literally free it 
aligning it
wastes more memory than just not doing anything
the code to free it also takes space 
u can just put it at the beginning of the section
which u align to 2m for some reason
btw
u override max page size also?
hm
no, what is the purpose of detecting hypervisors?
paravirt support
for most u can just use one hypercall or msr read or whatever to get the tsc frequency for example
and many other features
tsc and apic frequencies are the best part of paravirt
just being able to do one msr read or cpuid call or hypercall and get told yeah heres all your frequencies and never having to calibrate slaps
also theres often things that can be done faster via a hypercall instead of using the normal method because you can dodge or group vmexits
does bochs give you tsc frequency and stuff?
bochs has 0 paravirt
other than e9 and breakpoints
also wtf bochs doesnt support smp out of the box??
vmware and i think kvm in general (kvm for sure under qemu but unsure if thats a qemu added feature or native to kvm) reports tsc freq in a cpuid leaf, whpx reports it with an msr, dunno about other hypervisors
the latest
bochs 3.0
why the hell are pre-built bochs binaries compiled without smp support 
lmao
like im not tripping i think
Bochs is a portable x86 PC emulation software package that emulates enough of the x86 CPU, related AT hardware, and BIOS to run Windows, Linux,…
anyone can try
thats probably the right move
bochs on linux is kind of a shit experience
why
gui works really poorly
linux is kind of a shit experience in general
lol
systemd age verification merged
into freebsd??
idk why, but every major os feels like a shitshow right now
systemd haters rise up
Bochs fucking sucks imo
it does
does freebsd use systemd?
there are linked prs also
:^) so we just need to update and we get age verification on Managarm for free :^)
oh yeah bochs cant really emulate x86-64 worth a damn. crashes my kernel and it crashes astral lmfao
they even added FRED support..... which is worthless when it cannot even emulate the base x86-64v1 ISA
when tcg fred
patches are cheap
no idea and im not smart enough to add it to tcg
id presume its soon
i wonder if @versed obsidian's emulator can beat them to the punch 
iirc its already working more than bochs
oh btw @prime wraith you make any progress figuring out what youre going to do about irq abstraction? im curious to see what you come up with
not yet, still have more basics to flesh out before then
wait wtf is fred
the new guy at intel
idt for rich people
Ngl, I just copy these stuff from musl
naaaaah
$ ./bin/run_tests -s smbios
===== Tests for 'smbios' =====
Running test smbios_match_exact_and_first...OK
Running test smbios_match_fuzzy_and_exact...OK
Running test smbios_match_byte_and_mixed_entries...OK
Running test smbios_match_requires_all_entries...OK
Running test smbios_match_type_mismatch_fails...OK
Running test smbios_match_all_four_entries...OK
Running test smbios_match_smbios_unavailable...OK
Running test smbios_get_and_has_id...OK
==============================
Summary: all PASS! (8 total)
cool
clanker rolled relatively decent tests
uSMBIOS when
😭
do uSMBIOS
trying to add basic flanterm support 
flanterm bug!!!
ah lol nvm its because i told the bootloader to not set a videomode
cool
is there any way to make it to auto-\r on newline?
nope
you can use a few months old version :P
damn
i understand that its like emulating a terminal correctly and stuff
how is \r auto appended if u write something to stdout in general?
cant u set those in flanterm?
nope
why not?
it's termios oflags
is line discipline handled a layer above?
yeah i know nothing about that
what layers it has and how they inetract
ill have to read
i have this saved
interesting
i think part of the logic is like, a physical terminal or teletypewriter wont be adding the \r for you, so why would flanterm or the like
yep
I did it slightly different. I just check if it’s a \n and then insert a \r and let the normal control path send the \n
hm?
if char == \n
Send(\r)
Send(Char)
yeah thats smart actually
is that for flanterm or tty line discipline?
Flanterm, but you could apply it to both
not really
oh u literally patched flanterm
If the flag is set && char == \n
Nah that’s a seperate patch
My kernel still uses the older version
then you push both characters because it needs to be read by userspace
But my other projects have that method
Yes?
then what part is slightly different?
Wouldn’t this not be sending two charters
i think what shes saying is
u do:
if (flag && char == \n)
write(\r\n);
return
And she does
if (flag)
write(\r)
write(char)
probably
I also check for \n
But I don’t have the flag implemented so it’s just always if \n
anyway I also have if \n then \r in the logger as well
u mean kernel logger?
yes
where is your flanterm related code?
the previous link I sent is generic, it doesn't depend on flanterm
yeah i get that its just tty
currently only ttyS0 driver is hooked up to it
wait wheres the check
void write(flanterm_context *ctx, std::string_view str)
{
flanterm_write(ctx, str.data(), str.length());
}
c++ views 🤢
reminds me maybe i should rip up something to normalize line endings in my logs
why is it in unsafe namespace?
idk I think I named it that way when I still used headers and I couldn't control what was exported
oops wrong reply
similarly to managarm
I have a section that contains cpu local objects that are then copied over for each cpu
their base addresses are written to gs

ah i see
I do
cpu_local<type> var;
and optionally
cpu_local_init(var, args);
yeah i saw that so i was curious how u do it
so u store the base at gs:0 and then do loads relative to that value
yep
fair enough
decided to push all wip stuff to pr because its 4k lines now im afraid to just delete all of it
35 commits holy
a lot of them are fixup! stuff
per_cpu: THIS OCMMIT MUST BE AFTER ACPI PARSING!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

beautiful
lol
i also see you yoinked the linux style GENMASK
yeah well that's easy
its annoying af because u have to add a ton of validation macros for bounds checking of bit shifts
if u want an unsafe version its easy ig
also compile-time vs runtime fields etc
and that has to be done for every type like u8/16/32/64
but yeah before this shit can be merged:
- add proper bit fields helpers
- replace ioapic structs with bit fields
- clean up naming for some smbios fields
- add free_after_init and slap everywhere where needed
- clean up commit history
also i should consider switching smbios strings to string views
but idk if its worth
oh yeah also i should review the clanker written smbios tests closer before comitting them
but they looked fine at first glance
damn your code quality is so good
I look like a 12 year old in osdev-misc-0 compared to it lol
yeah infy is the goat
Lol dunno about that
ultra might take a while to get something cool going on but when it does at least i'll know it's rock solid
well thanks
except for all the unknown unknowns that'll be encountered on the way 
I think he meant that you might encounter something you don't know and will have to fix it
nothing in particular
🤷♂️
apparently this is something you can do ((int)sizeof(struct {_Static_assert(!(e), msg);}))
for verifying macros input
crazy tech
what the actual fuck am i looking at
basically its an expression that just produces 0
so u can do expr + normal logic
and expr does some sort of input verification u want
via the static assert
#define EMBED_STATIC_ASSERT(expr, msg) \
sizeof(struct {STATIC_ASSERT(!(expr), msg);})
#define MAKE_THING(x) (EMBED_STATIC_ASSERT((x) == 0, "x is 0") + 1 << x)
void foo(void)
{
int bar = MAKE_THING(1);
}
@proper tulip
u can do stuff like that
that's kinda wild
yeah in c++ u would have to do sizeof() - 1
yeah, i don't think any kind of planning will save you from re-architecturing later on
in c++ you can probably avoid macro hacks like that anyway :^)
yeah that would work, but i think in c++ there is generally better ways to accomplish that anyway
and also, the environment is changing over time as well, so no amount of planning will save you from adapting
i hope to reduce the amount of tech debt or stuff ill have to rearchitect by looking at more advanced things that have solved said problems already
but yeah its inevitable
i cut corners on features i dont want to support right now
if i want to support those laters ill have to redo stuff
btw infy have you studied CS? in a university I mean
yeah but over 5-10 years, some of the "advanced things" will become outdated anyway
i have a two year cs diploma yes, aka what would be an associate degree in the us
true
when Managarm was started, there were no PCIDs on x86, no SMAP, no hardware controlled power management, no nested VT-x
so no amount of planning would have enabled us to take advantage of these
how do cpu masks work on ultra? normally id guess just a straight bitmap but given the variable and possibly very large number of cpus I'm interested in how that's solved
Ill just steal linuxes cpu_mask
The mask is on the heap
But currently they dont exist
ah mhm
is it just a straight up mask on bitmask on linux or is it something more hierarchical?
Just a mask
what the fuck is going on
i may be retarded but i dont se how this thing is different from __builtin_constant_p
Maybe it's the same thing but "portable"
Bro has education
dam right
lol
When will you get a phd so u can say ultra is phd code
never
i kinda dropped out because formal education is just not for me
i like real work more
finally someone who gets me
i too dropped out after two years ish
academia was killing me
maybe i should try and find out if i managed to swing enough for an associates while i was there but it was 7 years ago now so idk what data is still there
seems to work
but the macro itself is relatively clean
#define MAKE_BIT_MASK_OF_TYPE(end_bit, start_bit, type) ((type) \
STATIC_ASSERT_IF_CONSTEXPR((end_bit) > (start_bit), "incorrect bit order") \
+ ((UNSIGNED_MAX(type) << (start_bit)) & \
((UNSIGNED_MAX(type) >> (BITS_PER_TYPE(type) - (end_bit) - 1)))) \
)
true
Son 😭
bru wtf
i've seen worse
tested this hello world on real hardware for fun
worked fine so im happy
ioapic id was reported as 1 (which at least matched the actual id stored in the ioapic unlike dumb vms)
or dumb macbooks 
Finally added bit fields macros (or just one for now)
#define IOAPIC_ID MAKE_BIT_MASK(31, 24)
stored_id = BIT_FIELD_READ(
ioapic_read(new_ioapic, IOAPIC_REG_ID),
IOAPIC_ID
);
u really dont wanna see what it expands to
The macro itself is simple
#define BIT_FIELD_READ(data, mask) \
BIT_FIELD_VALIDATE_INPUT(mask, 0u) + \
((typeof(mask))((data) & (mask)) >> BIT_FIELD_SHIFT(mask))
and then there's a ton of validation
#define BIT_FIELD_VALIDATE_INPUT(mask, value) \
EMBED_STATIC_ASSERT(IS_UNSIGNED_TYPE(mask), "field mask must be unsigned") + \
EMBED_STATIC_ASSERT(IS_CONSTEXPR(mask), "field mask must be a constant") + \
EMBED_STATIC_ASSERT(mask != 0, "field mask must be a non-zero value") + \
EMBED_STATIC_ASSERT(IS_POWER_OF_TWO(mask + BIT(BIT_FIELD_SHIFT(mask))), \
"field mask must be contiguous") + \
EMBED_STATIC_ASSERT(IS_UNSIGNED_TYPE(value), "value must be unsigned") + \
STATIC_ASSERT_IF_CONSTEXPR((~(mask >> BIT_FIELD_SHIFT(mask)) & (value)) == 0, \
"value is larger than the field mask accepts")
technically i can just do ({ }) instead of these embeds, idk whats better tbh
i think that would be less confusing
yeah i guess
there might be some catch like gcc/clang being unable to see that ({}) expands to a compile time constant
which kills a lot of extra checks
ill have to experiment with it
don’t think so, but fair concern ig
Never attribute to malicereason that which is adequately explained by stupiditybeing written by a Linux developer.
hmm yeah at least for field masks if i wrap them in a ({}) it stops thinking it's a constant
the fields themselves can be ({}) i guess, but MAKE_BIT_MASK will have to be that weird embed system
how could u say that linux devs are living gods
they dont make mistakes
or write mess
ever
anyway my brain is exploding from bit stuff ill go play bf6
I added BIT_FIELD_MAKE also, the last one ill have to do is probably BIT_FIELD_WRITE for modifying existing data

i mean yeah, in reality i don't think that linux devs are bad, it's just that there is a lot of tech debt in linux due to the development model
yeah
some code has been written 20 years ago and then only been fixed to such an extent that it keeps compiling 
x86 init code for example hasnt been touched or reworked in many many years, only new stuff has been awkwardly slapped on top in the least possible amount of loc
so its a fucking mess
yep
when i looked at the FRED patches it literally has to reclaim the IDT memory and other stuff because it looks fully bolted on with duct tape
In case you were curious to what
stored_id = BIT_FIELD_READ(
ioapic_read(new_ioapic, IOAPIC_REG_ID),
IOAPIC_ID
);
expands:
https://pastebin.com/4Wa0V6F2
Pastebin.com is the number one paste tool since 2002. Pastebin is a website where you can store text online for a set period of time.
(yes its this one single read)
and this produces a compile time constant too, i've verified with a global array size like int data[BIT_FIELD_READ(...)]
all this garbage is mostly to catch all possible invalid input
its crazy macro fuckery but honestly the end result is worth it
i love static assert abuse
Lol I kinda wanna add ratelimited print helpers and print_once
Now imagine the compiler didn't evaluate this and cosntant fold it 💀
Runtime static asserts would be funny
ts is horrifying
wtf
My unit test collection is growing
cooking some stuff
what is this cursed thing
Is it some clang sanitizer?
nah lol its a python script
Oh god
lol
Never let infy cook again regarding macros
all the macros i've used are just simple stuff that places code/data in a specific section
is it a python script that writes macros?
what no
it just takes an object file of the kernel and scans all section references to .free_after_init
then makes sure those references only come from special sections that allow those
ah that's awesome
idea stolen as always
I have done the same tbh
I have init code/data
And I have late ro data
So anything initialized during init is mapped as ro later
ah cool
Which special sections? Init code?
even worse than macro fuckery tbh
I just don't have skill issues so I don't access init data after init

And reclaim init code
init code is probably more worth it than data anyway
init code is implicitly allowed to access any init data yes, but non-init is only allowed if marked so explicitly
i have 3 init data categories: code/data/rodata
my point is there's gonna be more code than data likely
yeah
did u figure out the log ring?
Well been at school all day but I've been thinking about it and I understand the mechanisms of it
I really just need to look at the code and understand the orderings
But like it's not that complex really, it's just a fancier lockfree ringbuffer
And a lockfree ringbuffer is pretty simple
.free_after_init sounds pretty useless
Why not reclaim as much memory as possible?
I do it for code at least and can save a page or two
yeah even the wsl linux frees 5 megs worth of init data
so 0.000023842% of memory on a 16GiB system 
you'll oom 5ms later than w/o it 
What about on constrained platforms
i wonder how linux gets to 5M
it's probably all pt storage in BSS
yet another prekernel win 
Why do you need pt storage in bss
Ah they probably need it to remap themselves
bootloader win more like
linux has a complicated scheme where it links the kernel twice while guessing at the first stage how much memory it'll need to map itself in the worst case
it's quite stupid
what
yeah and then it allocates enough memory for these pts in its BSS
That is so cursed
why is Linux putting page tables in bss
It has no other options since its basically a built-in bootloader for itself
well is it 5m of data bytes
or 5m of total image size
ah ahhh
yeah that makes some sense
although
why wouldnt you just preallocate the area outside of the image
thats pretty much what i do (except i have an actual prekernel lol)
@prime wraith why does the log ring need so much code, is it not enough just just have a ring buffer of log metadata + log message? you can implement that in like 30 loc, what am i missing? lol
lmao
sorry for pinging but you're the first person that comes to mind when it comes to overengineered log rings
He got carried away let's say

would those 30 locs be lockless?
well, no, but you can have a loop that will make it lockless, no?
what sort of loop
sure
static uint8_t log_ring_buffer[16 * 1024 * 1024]; // 16M
static size_t log_ring_head;
size_t log_reserve(size_t size)
{
size_t needed = align_up(
sizeof(struct log_metadata) + size,
alignof(struct log_metadata));
do
{
size_t x = atomic_load(&log_ring_head, ...);
size_t next = x + needed;
if (atomic_compare_and_swap(&log_ring_head, &next, ...) == x)
return x;
} while (true);
}
like i dont know how to write code so bear with me
idk how to write code using atomics*
but i hope u can kind of see the idea with the pseudocode or whatever
and of course you need to make sure that if you wrap around you handle that
okay do u see some issues with that?
well, no, but that's why i asked why so much code is needed 
okay let me try to list some
god damn is it really that bad
you've been typing for a while
- your code doesn't handle toctou
- no way to tell whether you still own the part of the ring or not if it wraps around while you're still writing
- no way for the reader to know where to start reading
- no way for the reader to know whether whatever they read is consistend data or if it got overwritten in the process
- no way for the reader to check how many messages got dropped
i see, i don't exactly know what point 1 is about honestly but everything else seems like it could be handled with a big enough buffer and a "but that'll basically never happen" mindset
i dont think so because u basically dont have message states
there is no way for the reader to know whether data is finalized or not
well that's where the metadata comes in
but i agree, it's suboptimal
ideally the metadata header shoudl store the level and size
basically with what you've presented you're suggesting a bump allocator log buffer
and that's it
its definitely not a ring since it doesnt work as one
but yeah as a bump allocator, if u add message states it will work fine
okay i can see how it can become kind of a complicated piece of code
when iretq log ring 
if you only saw me work you'd realize i really mean what i say about myself, the moment i hit a corner case and have to actually think and refactor half of my code i kind of just give up because i can't
this seems harder than it should be
like what?
i can't really give you a specific thing but it's a pattern and it's very apparent if you ever join vcs in servers i hang out in :^)
i just end up playing games or watching reels because i get discouraged from working on a project
well i don't think it matters if you actually look at the technical aspect of what you're working on
yeah it looks like you are doing nothing
but then you look at the code and it's no longer nothing
fwiw from what ive seen your projects or stuff you contribute is usually pretty decent stuff, maybe its just a mental block u have that has nothing to do with your abilities
yeah maybe, my recent mental block was astral xhci
it seemed to work fine, then i smashed the keyboard and it corrupted the memory and then i could not reproduce it
lmfao
that shit really made me want to just never work on it again
yeah that can be discouraging lmao
like even that uacpi test runner rework u did was huge it saved countless hours at this point
or the windows apple nvme driver thing, the borderline unusable windows debugger just made the whole thing so much more fun (not)
it still doesn't fucking work and i don't know why 
oh yeah windows debugger
yeah that was nice but nothing crazy, at least i contributed something useful
ive had enough with that shit from aml reverse engineering days
If you can’t reproduce somthing it’s not a problem 
trust
it could very well be a preexisting astral bug
do u still have it on a branch somewhere?
finish it 
i think it actually works but it just needs an hid parser to be actually useful
and i haven't really tested on real hardware
due to astral not really working on my pc
what can be more fun than a byte code parser 
hid parsing is actually pretty nice
also mathew has fixed a lot of stuff since then maybe it boots now
yeah unironically
im kinda too lazy to try it out rn, i reinstalled windows and arch since then so i'd need to build so much stuff
it only takes 5 llvm recompiles 
that reminds me. maybe i should run another fuzzing campaign
poor uacpi
i wish there was an actually good roadmap for a kernel
not a 1. gdt 2. idt 3. pmm 4. scheduler
u mean for your kernel?
cant u design one?
and then start implementing it
and get stuck because i didn't take something into account
and then it turns out my design is shit

lol
It’s been fixed enough to boot on a good few of my PCs
A lot of the later stages of monolithic kernels have interdependencies, for example between disk I/O and VMM if you do swapping
yea
So one roadmap of strictly in-order writing entire subsystems isn't a thing
yeah but the few initial things really don't have that many dependencies
i usually tried to do per-cpu -> scheduling -> memory management
but i could never actually finish anything
You can't get sched up without at least PMM
you can
Because stacks
I ended up just plopping a bunch of half asses crap down to do cool stuff so I can go back and do more proper implementations once I have learnt enough
tell that to liam 
you don't need separate stacks in kernel space
Is my kernel a mess rn? Yes. Can I still fix it? Sure. Will I? Yes
u can definitely make a scheduler without any memory management
Where are you getting your stacks from
nowhere
char stack[8192]
you just run on a kernel stack from the bootloader
or that
you don't need separate stacks for each thread
The real VFS should be on the way. And I know a ton of other crap is gonna be need to be re done for mutexes condition variables and proper blocking on page caches maybe but
It’s a journey
and you can switch to a separately allocated userspace stack when you enter userspace with an iret
Just have fun with crap and redo things if you need
FYM you don't need separate stacks per thread, are you only having one kernel thread at all?
I ported bash without a real VFS 
beast? 
that would require effort 

