#pmOS - microkernel OS for RISC-V, x86, and LoongArch
1 messages ยท Page 9 of 1
Fuck it, I'm pushing it to main
I'm tired of it
Cool
Time to port to ARM 
lol
Why did no one tell me that cmake can fetch git repos?
i'm more suprised you didn't know that
if it exists, cmake can do it
I don't like requiring network to build
Yeah, but there's Rust anyway
I've also found it annoying when programming on trains
my build system is a dumpster fire
(I'm planning to make it interract with the pmbus stuff)
(bidirectionally)
So the drivers could publish handles to devices, and the init server could match those based on the user provided rules, and start more stuff
Cool, now my PS/2 server is trolling me
Nevermind
It's the kernel 
I think I'll just pretend that it's working as intended 
The timers are completely broken 
Dead 
Maybe I need to find some contributors or whatever 
I have a lot of stuff to do though
I've gotten stuck on yaml parsing in my init server to have a proper ... init system that's integrated with pmbus and stuff
Yaml is way more complex than json
I've found a library for it
Ah
just emulate systemd units
Too much work
damn..
I want the system to publish stuff on pmbus (which is mbus close)
And that to be able to launch drivers
Through the init server
So e.g. devices server could publish PCI devices, which would launch XHCI driver, which would publish USB devices and so on and that could launch USB drivers
Or whatever
only Mintia, Ironclad, and Managarm will be left standing
I mean it's not completely dead I hope
No ultra 
๐
Like it has only been 2 months I think?
where idt
Merged
doit

I have decided that I will not merge bootstrap and process servers
But now I don't know what to do with filesystems/logs
curious why not
They're 2 separate servers now
And I can just make them talk over IPC and it should work as well
And once is in C and the other one is in C++, so I would have to rewrite it basically
:( dead chat
Day 1 of waiting for pmos comeback 
Oh no, I forgot how to build it
I think I've basically done no programming (in general) since August
(except a fling with Zigbee switches)
Cool, it's working, and the timers are still casually broken
I need to fix/reimplement environment variables and aux vector stuff
pmos is back 
Idk if I'll stick to it
This looks too complicated now
Nice return type
(Anyway, I'm finally implementing a way to pass the data from process to process when it's started, so I can pass capability, args and environmental variables. And maybe I'll do posix_spawn eventually)
use a struct, perhaps?
probably easier to manage if you ever need to add another item to the tuple lol
mm, tuple
my favorite compile time killer
also shared_ptr<page table> is kinda lame, tbh
Yeah, I've used shared pointers everywhere in the beginning and can't get rid of them now (or rather, it's not a priority)
I have RCU for some stuff
Why
Shared pointers are obnoxious
depending on how your shared_ptr is implemented, it can be quite wasteful
and depending on what a paging::Arch_Page_Table is
It is a bad pointer, with external structure for weak_ptr
I don't hate pair for a return value where the parts are not really connected
yes the only issue is that pair and tuple are really not good for compile times
I'm writing a microkernel, it's not (supposed to be) that much code anyway for it to matter...
lol
write a macro kernel
Hybrid kernelโข
(linux)
it's sometimes a necessary evil though
Ok, so moving the memory between the address spaces seems to work (again), but my process initialization logic is broken now for some reason...
(which is annoying to debug since my screen driver is in userspace)
don't you have a small uart driver in the kernel?
I do, bit it's only for kernel messages
Actually, the issue is not where I was expecting it and I've no idea why it pagefaults
Bruh, it's a weird UB in C with pointer arithmetic which removed the null check?
(I've managed to get it to work...)
Now I need to decide how to hook into pmbus to match the devices for drivers
(namely, how do I make it match PCI and ACPI devices)
Why did I use libyaml, this is pain
Oh no, Rust is pagefaulting (
)
But my PCI routing is also broken for some reason
Ok, the rust situation has been rectified
I feel like just copying mbus's conjunction/disjunction thing 
(the only problem is that I'm doing it in 3 programming languages, and I'm afraid it's gonna be a bit obnixious in C...)
(and I forgot how to write Rust)
A small progress update: I'm currently trying to make the filter thing to work in init server, which should make it able to start i8042 driver (and later after this, I wanted it for disks...) by matching its PNP ID from ACPI
(but my yaml parsing is broken for some reason, and it's too late for me to be fixing it today)
Least cursed way to load drivers
https://gitlab.com/mishakov/pmos/-/blob/dev/limine/limine.conf?ref_type=heads#L57
The kernel has chosen to troll me
wtf ๐ญ
This looks promissing
I mean limine doesn't complain about it, and it seems to work 
(I'll move it to the proper config files on the disk (or/and initramfs), once I have necessary drivers)
obv but just have like an mbus filter shit or something
idk how I'm going to do it yet
It is an mbus filter
yeah but just put that in the drivers lol
The difference with managarm is that it launches drivers, and those then talk to mbus
I launch drivers once it finds a device in mbus
(Or plan to do it, I need to implement some more stuff...)
it seems like a nicer system
Idk, I haven't looked into it, but this is an example with their i8042 https://github.com/managarm/managarm/blob/master/drivers/kbd/src/main.cpp#L1180
for some of the devices (e.g. graphics cards) udev is used to bind the mbus node to a driver
But you still need to have some external structure which lets you match the driver (?)
(or you can spawn the driver, and make it tell you)
for early drivers (e.g. usb controllers, nvme etc, needed to mount the rootfs) they currently enumerate mbus themselves (but we could also just put udev in the initrd)
for late drivers that use udev the flow is: posix-subsystem scans mbus and fills out sysfs, udev scans sysfs and processes rules, the rules tell it to bind a device to a driver (potentially launching the driver if it wasn't running before)
Unfortunate (I need to replace my libc)
But ignoring broken puts, this is very promissing...
how did it fail to print to stdout with error 0 ๐
the returned written number of bytes is messed up when the text is too long
(and I don't know where the bug is)
oh right i forgot how write() worked for a sec
It has to do with the fact that if it gets too long, I send several IPC messages
Now, this looks extremely promissing
(Now I just need to rewrite everything in that chain to use capabilities (a.k.a. rights), instead of juggling the ports directly)
(And then implement dependencies in my init thing)
(and then to decide how I'm gonna pass that to the drivers (it's probably gonna be cmdline args (so that needs implementing as well)))
I think this is going smoother than expected (I just need to implement right copying error handling when requesting objects, but it's too late and I'm too sleepy to do It now; and of course the C (devicesd) side needs changes as well, but I don't think it'll be too complicated)...
what is a disjunction
Ok, I changed the devicesd, but now Rust can't deserialize it for some reason
Cool, it seems to be fully working, but using capabilities
(but I still need to implement notifications about closed rights...)
(which isn't really a priority though)
Ok, I need to do something with auxiliary vector, but I've no idea how I should do it
Maybe I should implement futex first instead? 
I think I'll add rights to threads and page tables as well...
(though the page tables would be complicated)
Ok, fuck it, I'm changing everything to proper aux vector stuff instead of my thing that I have now, and moving elf loading back to userspace
I think I'm coming back full circle to using u64 for pointers (even on 32 bit platforms...)
uintptr_t:
But it's 32 bit
32 bit userspace with 64 bit kernel
ew
wdym ew lol
Why
its much better than a 32 bit kernel
So that you can load 64 bit processes from 32 bit bootstrap server or whatever
Like yeah it's pointless, but kinda cool, and not that difficult to implement
It's only for memory management syscalls
btw do you mean actual 32-bit or just x32
i686 userspace mixed with amd64 userspace and kernel
compat mode
I haven't bothered looking into x32
what is x32
Though that can be implemented as well, I guess?
amd64 with 32 bit pointers cursed calling convention
wtf
saves memory trust me
linux supports it
or at least did, I think there were talks about removing it?
or something like that
i refuse to mix different address sizes
why
this could also be useful for emulation and stuff
where?
I wanted to do m68k eventually
and ppc
So porting to i686 was a logical first step
and I started that with porting userspace by adding compat mode to kernel
ppc64le 
noooooo
Small progress update: the elf loader in userspace is almost working. But I think I have a new fun issue, the scheduling seems to die after anything pagefaults in userspace?
The loader is working, but it seems that I have a deadlock somewhere...
Actually, my splay bst is broken again, and I don't want to deal with it right now 
or not?
And the userspace loader seems to be working as expected...
I've changed the TLS logic to use data from ELF pheaders directly...
And now I'm trying to build loongarch64 version, but Rust is refusing to cooperate
(Since riscv64 is also broken, but I couldn't event compile rust toolchain for it in the first place)
(why am I suddenly getting this? https://pastebin.com/ALhwkfvD)
you need to enable pthreads in your gcc config
It's clang
I think I forgot to rebuild the compiler, and I've been using an old version which didn't define _pmos_ for loongarch
For my future reference:
cmake -S ../llvm-pmos/runtimes -DLLVM_ENABLE_RUNTIMES="libcxx;libcxxabi;libunwind;compiler-rt" -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=$HOME/pmos/sysroot/usr/ -DLLVM_TARGET_TRIPLE=loongarch64-pmos -DCMAKE_CXX_COMPILER_TARGET="loongarch64-pmos" -DCMAKE_C_COMPILER="clang" -DCMAKE_CXX_COMPILER="clang++" -DCMAKE_C_COMPILER_TARGET="loongarch64-pmos" -DCMAKE_ASM_COMPILER_TARGET="loongarch64-pmos" -DCOMPILER_RT_BUILD_BUILTINS=ON -DCMAKE_C_FLAGS="--sysroot=$HOME/pmos/sysroot -nostartfiles" -DCMAKE_CXX_FLAGS="--sysroot=$HOME/pmos/sysroot -nostdlib" -DLIBCXXABI_USE_LLVM_UNWINDER=true -DLIBCXX_ENABLE_SHARED=OFF -DLIBUNWIND_ENABLE_SHARED=OFF -DLIBCXXABI_ENABLE_SHARED=OFF -DCOMPILER_RT_BUILD_BUILTINS=ON -DCOMPILER_RT_BUILD_ORC=OFF -DCOMPILER_RT_BUILD_SANITIZERS=OFF -DCOMPILER_RT_BUILD_MEMPROF=OFF -DCOMPILER_RT_BUILD_XRAY=OFF -DCOMPILER_RT_BUILD_LIBFUZZER=OFF -DCOMPILER_RT_BUILD_PROFILE=OFF -DCOMPILER_RT_INSTALL_LIBRARY_DIR="$HOME/pmos/sysroot/usr/lib" -DCAN_TARGET_loongarch64=1 -DCOMPILER_RT_BUILD_CTX_PROFILE=OFF
cool, rust is still broken on my other pc on loongarch64
So my rust version is just broken?
fuck me I don't have energy to rebase it
is your compiler 2 years out of date?
1 year out of date
Rebasing wasn't too bad... But I now need to figure out libc and cc-rs crates, which I remember being a huge pita
Ok, it is bad, I can't compile rustc for some reason
(I'm trying to get cc-rs generate new targets from my rustc, but it's refusing to do it)
ok, it cooperated
cooperate daemon
I think I'm rebuilding rustc like 7th time today?
(the only saving thing is that I'm using my desktop, where unlike my laptop wsl2 doesn't crash every time I compile anything, because it (laptop) "only" has 32GB of RAM...)
Why this now
Oh no, I need to define my libc in libc crate
What am I doing wrong 
I think I now understand the hate of the compilers by the os developers
I want to kms (figuratively)
Cool, it's still broken with the latest Rust 
But at least x86 still works
Nice
Nevermind, I think it compiled on my laptop?
Cool
My loongarch64 port is fully alive???
(I assume RISC-V would be as well then)
I think I'll finally do auxvec thing now
loongarch seems to be in fashion nowadays
I mean I haven't touched it for a year
I love C++
(Removed lto and recompiled the kernel)
Guess I'm just stuck with O3 and LTO 
Also, something in here wants std::__1::__libcpp_verbose_abort(char const*, ...) for some reason?
bruh
I think at least the kernel's aux vector stuff is working...
I think userspace auxvec stuff is also working correctly?
Which means I can finally pass arguments when starting processes
Though finally having a disk sounds more fun (I already had an AHCI driver, I just need to redo VFS...)
x2apic has chosen violence
nice
smp breaks with x2apic now?
or maybe it's working but interrupts don't seem to work for some reason...
fuck it, I'm doing iommu
Didn't pmos have a lot more than bash already?
I don't have a shell
๐ i thought you had that already
I also wanted to figure out evdev or whatever before that
why
Because I have no idea how io devices should be managed
Like I have a keyboard input and flanterm output. But what needs to happen so that you get a shell with pipes to those?
Hence 60k (or maybe 70k) LoC with no shell
Ppl with kernels that consist of 90% log ring code are not allowed to argue about priorities 
mint said everyone had to urgently implement x2apic 
holy owned
x2apic doesn't necessarily need iommu, you can just make it so cpus with lapic id >= 256 aren't considered eligible irq destinations
but then it's not a proper implementation 
Also, intel docs don't seem to be making too big of a deal of vt-d?
also, this doesn't work for some reason?
wdym
I've tried it and it doesn't work with x2apic
Idk maybe something else is busted
Like 1 << 24 for lapic 1
Do u treat icr as one register?
(u should)
Literally
you use id << 56 for ioapic entries and msis, and id << 32 for ipis?
Ok, I'm dumb, I removed id << 32 and added 1d << 24 instead
it works
Does managarm support the amd vt-d clone thing?
My intel laptop died
idk but if you need the spec here it is
Cool, less pages than intel
Vibe code it without a spec 
Not yet
How difficult is it
Interrupt remapping is just a giant table
Is the initial idea that u give it virtual apic ids or something?
Idk how apic virt works
isn't it kinda like IOAPIC but on steroids
No I get that, im just curious what was the initial purpose of remapping interrupts
It takes a (cpu, vector) pair and remaps it to an (actual cpu, actual vector)
but just because im dumb
How does this help virtualization?
it has a posted mode
There is one such table per BDF
Maybe im dumb I dont understand why that's needed
Because you don't want a PT device to interrupt storm an arbitrary host vector
So every time u move a vcpu thread u edit the table?
No, you just allocate some vectors for the VM and only let the VM use those vectors
In a way that's transparent to the VM
But that can be done even without a remapper no?
sure, but i assume it's not as straightforward as with the iommu approach
idk what im talking about tho
How?
pretty sure that's up to the cpu
vt-x has apic virtualization support
Remember that the device can write to arbitrary MSI addresses
but you can also make apic accesses trap(vmexit)
Hm ig
So where do u redirect to? Just arbitrary kvm handler that then injects the irq into the guest?
yeah
At least that's the simplest case
As mishakov said, there also a posted interrupt mode but that's relatively new
Iirc gen 12+ or something like that?
What's a posted interrupt?
Basically a table in RAM that vt-x can read to inject the interrupt into the guest
Without a kvmexit
Damn
do I finally switch my kernel to uACPI (table only thing)?
Oh no
Or maybe it's not that bad actually
Ah yeah don't forget to map the RMRRs or some hw will fail catastrophically :^)
Uacpi might have some of those tables but probably not all
Then I can look into adding them?
That would be cool since ill also need them
If u do pls take a look at the other tables in the file so u can match the naming style etc
Barebones mode should be pretty lightweight
like what?
Smp probably
timers, ioapic, a bunch of stuff in risc-v and loongarch
and this on i686
(or if I decide to add ultra protocol to amd64 port as well)
probably more stuff
idr, I haven't thouched it in a long time
Do they want me to move PCI enumeration to kernel??
I guess that's why managarm does it in the kernel
you can just report iommus to userspace and let userspace match them with devices
Why?
no? just interrupt handling
But like you need AML to discover root bridges, etc.
yeah but not to discover ioapics
Some platforms may also expose I/OxAPICs as PCI-discoverable devices
oh
you can just tell userspace "hey here's a handle to the iommu described by acpi table X" and let userspace do the matching
But I still don't get this
bus = read_secondary_bus_reg(bus, dev, func);// secondary bus# from config reg.
if the device is behind a (tree of) bridges the device id is the one of the first bridge
afaict
Yeah, I was thinking about exposing it to my devices server, and it then being the thing that manages handles is stuff
But do I really need to care about it now?
but that can work with barebones mode
yeah
you need to care about it when matching devices to iommus
and when setting up the device-specific iommu configuration
I need to think about it
Because I wanted to do iommu management in kernel, together with ioapic
But things are connecting in my mind yet
how this whole thing works
If u want iommu management in kernel u need acpi there as well
Like the full thing I guess
no you don't?
Because it's tied to PCI
only the matching
Not really
If u blindly trust to userspace I guess not
But that's what I'm trying to understand
you have to blindly trust at least some of userspace if you want to put acpi there
You'll get a handle to device as a driver
since acpi needs to be able to access arbitrary physical addresses
and then the devices server will have to give a handle to iommu or something?
Anyway
320 pages document
the way i'd do it is devices server gives driver a handle to an iommu domain
yeah
but then I wanted to (eventually) tie it to memory allocation
or not?
it has to be tied to vmm
that'd be a good idea yes since the iommu is involved in allocating dma buffers
then driver uses that handle to create a (kernel-managed) 'dma space' (this has to be done by driver since only that is aware of the device's addressing limitations)
Like I have memory objects, so there will be a syscall to give some device access to that
and that 'dma space' can then finally be used to allocate and/or map dma buffers
Yeah
I think I'd need to read amd's thing as well before I implement all of this
(and I want to do interrupts first anyway)
i think amd vi is very similar to vt-d
and I don't have MSI
Yeah, but I need to know how to abstract it
Because [this](#x86 message) says you can have both in the same system
also i'd design the api in such a way that it can support a bounce-buffer-based 'software iommu', so that the drivers can be written in a way that assumes an iommu is present
how would it work?
allocate would just allocate in a certain physical range, as indicated by the dma space setup parameters
(I mean I would need to modify it)
map would map in a preallocated bounce buffer instead of the given address, and then upon unmap copy the contents of that buffer
Ok, yeah
but then again i don't think iommu mapping (as opposed to allocation) is an operation that needs to be exposed to userspace
I would need an explicit unmap
it's only necessary for io into the page cache, which is initiated by the kernel vmm
I wanted to make it transparent to userspace
you could have the kernel, upon pagein/out, set up the dma mappings, give userspace a dma address to perform io with, and upon transaction end tear down the dma mappings again
you need that for pagein/out anyway
since the kernel needs to unblock the thread(s) that caused the event
It's semi-abandoned because it causes issues with the kernel not being preemptible
(But I had that working in the beginning)
Which are solvable
What I don't understand is this
(Also, I have a thunderbolt 3 egpu, I wonder if I could support it eventually...)
the iommu can verify whether interrupt requests are coming from the ioapic they were allocated for
it does this by having an 'interrupt source id' in the interrupt table entry
this section documents how to get the source id for a given ioapic
you don't have to worry about it though since this source verification is optional and can be disabled
look at section 9.9 fields SVT, SQ, and SID
That's not true
For example, Bluerock's stack has iommu in kernel, acpi in userspace
another possibility is to just have matching VA and DMA addresses
for the IOMMU case
true but not every dma transaction requires the buffer to also be mapped in the virtual address space, so for those transactions you'd have a pretty large overhead due to the cpu side of mapping/unmapping the buffer
tlb shootdowns for example
not all DMA is disk IO though
true. although you could reserve the VA space w/o actually using it
re exposing mapping vs allocation: On Managarm you can "just" map a memory object into multiple spaces
so you can take your CoW or page cache object and map it into a VM, for example
@kindred venture how's your os going btw
still waiting on motivation
Lol
Wait, how does this happen?
new sysdep dropped
But why unknown type in uacpi's headers?
do you override arch_helpers.h?
This is weird
because that's what defines uacpi_interrupt_state
Yeah, I have it
then it's just that your version doesn't define that
I don't think so
well yeah you have the file and the override
but your override doesn't define one of the things that it has to
but it's not the override, I think?
yeah the latest major version update of uacpi added another thing to arch_helpers.h that you'll have to override
uacpi_interrupt_state

just make the gp handler check if the faulting insn is cli or sti and clear/set if in saved rflags on the stack :^)
I probably need to be changing TPR
Wait
Can I use uacpi_setup_early_table_access with dynamic size?
I dreamt that I should just malloc a large buffer and that's it 
I posted an example before, but you can just call it in a loop
where?
If it fails with some size, just 2x the size and call it again
Ugh
I must have accidentally erased it???
This is fun 
This pointer looks off...
(this happens when rsdp is bogus)
Did anyone test it?
(cc @twilit talon)
It works otherwise
yes
i mean, it will map it, then it's up to you what virtual address you return as a result
but why did it crash
if u catch a part where it's missing OOB checks that can be fixed
like trupple fault
I think I'll look into it
Because my kernel doesn't use hhdm
i mean if it triple faults that means u didnt catch the GPF/page fault
So because everyone else probably does, there might be a bug somewhere?
yeah, because it's an early init, before I have interrupts
do u have idt setup at this point?
u should really have exception vectors setup at this point
its like the first thing u should do
gdt+idt init
no
I set it up after this (but also because afaik it's using tls? though if I get interrupt in ring 0, it should just use kernel's stack
Cool, loongarch is just trolling me
Everything is broken, unless I enable a framebuffer in kernel
but it was working before
mine needs O3 and lto, otherwise it crashes the linker
I'm blaming uACPI 
(or maybe it's the same bug as on that cursed laptop where there was no framebuffer output for no reason)
This patch is sus
(Which got pulled in after rebasing the kernel framebuffer branch)
I sense some serious trolling
queue in discovering something basic being extremely broken in a year
(like my set implementation, which was just randomly and casually locking up the kernel on deletion)
No, this is serious trolling
I think I'll just assume I haven't seen anything and carry on as if it was working perfectly 
It's probably some UB, which I'll probably catch on risc-v
Wtf, why is there RCHT and RHCT?
Wait, it's just my headers
Huh, risc-v rustc had suddenly decided to compile???
Cool, RISC-V also just works
So loongarch64 is the only one broken?
(I haven't fixed i686 yet though...)
Oh no
(though this is weird)
how did this stuff even work in the first place?
I haven't touched this in a long time
I give up, I think I'll just wrap it with mutex
This is so obnoxious, how do I just force it?
CXX_COMPILER_WORKS 1 or whatever
Did you prefix it with cmake
And it must be at the very top
set(CMAKE_TRY_COMPILE_TARGET_TYPE "STATIC_LIBRARY") worked...
But I need to figure out how to disable libyaml
(tbh the best solution would be figuring out why clang doesn't append it automatically)
What's a module command line
I mean if its just a string I could add that if you want
Why is your module metadata in the limine cfg
Instead of having a metadata struct inside the module
Fair question
I was doing this in hyper. but the issue is with quotation marks
because then I'd have to use some custom format for it or something?
or package it into an archive
the modules can't just be elf files
What
Those are not kernel modules
Who parses them then?
userspace
Hyper allows same quotation mark syntax as python
Well the elf interpreter that parses them can still look for a metadata struct?
U can use '"data"'
I don't know python 
then just have userspace look for a custom ELF note?
This too
I mean I can do that as well I guess
Although I have no idea how those work so I just use a struct
But I also wanted to pass initramfs that way
eventually
when I fix my vfs
then this would not be an issue, since I can just pass it separately
Actually, I will probably do that eventually, thx for the idea
.section ".note.your-note-type", "", %note
.balign 4
.4byte 2f - 1f
.4byte 4f - 3f
.4byte YOUR_NOTE_TYPE_ID
1: .asciz "Your Organization Name"
2: .balign 4
3: <your note data>
4: .balign 4```
the linker will recognize the SHT_NOTE and put it into a PT_NOTE
So I just need to throw this in a random C/asm file?
yeah
cool
if you do it in C i'd use a global asm statement with .pushsection/.popsection
we use elf notes in managarm for passing a bunch of info between eir and thor
Pushsection is overpowered
I'll look into this for my os too
and have a helper class + macro for defining them https://github.com/managarm/managarm/blob/master/kernel/thor/generic/thor-internal/elf-notes.hpp
i really like elf notes because it's a standardized format for passing arbitrary non-runtime data in an elf file
what I don't like about it is that the file itself encodes the capabilities
but since everything kinda has access to everything anyway it's not an issue
Well because it knows its capabilities?
(for now)
I think it makes sense
if the capabilities are inherent to the file, for example if it describes what the code supports, that's a good thing
Like a service should be responsible for listing the capabilities it supports I think
is the .note. prefix enough for the linker to recognize it as a note and put it into PT_NOTE?
yeah, that's an (eventual) idea
(I mean it's easy to implement, just not the priority)
Yesterday I decided I wanted to do iommu first 
yes that's how eir finds them
huh i thought it'd need SHT_NOTE
and we don't do anything special aside from that, just mention them in the linker script so they end up in a segment
unless the assembler automatically uses that type for the .note prefix
might be
for .note.GNU-stack you also only need ```
.section .note.GNU-stack,"",%progbits
I'll check later
in an assembly file
yeah but .note.GNU-stack is handled specially
it's not a "real" note
Also, what do you need to do for it?
since it ends up in PT_GNU_STACK
true
this seems to be the case
Ok, I've changed my mind
This is really cool
hm? the gnu stack note is just to make the linker shut up
Just drop a random elf file, you have a driver
well technically it's to say what stack permissions the assembly code needs
but in reality yeah it's just to make the linker shut up
i mean yeah but in the kernel you allocate stacks at runtime anyway (although ig you could go and look at gnu-stack and respect it)
Jit in kernel with executable stacks
hmm today i will define a function in a statement expression and return a pointer to it and call it
(it'll put exec code on the stack)
Yeah thats a funny gnu extension
also officially a note type id is only valid for a given namespace (which is specified by name and namesz) but in reality a bunch of tools assume some type ids have the same meaning regardless of namespace
just something to be aware of
512 chars is not enough 
It's 850 chars long
Technically its not limited by anything, its just the loader currently stores that on the stack iirc
Ok, I'll move it to elf notes
Basically I need to get rid of that limit, especially since the protocol specifies that its limited by u32 size
Also, I think the PR is for cmdline?
Ah right
Ok, I don't know what I want to do now
(I'm adding this to uACPI)
though if x2apic is supported, but iommu isn't, then it implies it shouldn't be used?
does limine look into this?
That only matters for large apic ids
but what about this
queue in "linux doesn't boot on my random server" lkml thread
x2apic is newer
anyway
it weird, like as an operating system you're expected to set up iommu before apic?
(maybe what's weird is doing smp in bootloader)
yes
actually i was wrong
it just duplicates acpi bits for some reason so i didnt find it initially
whats the issue btw
None
just dont use x2apic if u use iommu and see opt-out
what about them
since it doesn't check this
u dont have to use the smp feature (and u shouldnt)
yeah
I mean I have init code from Ultra
(on i686 though)
Though it should be easily adaptable I guess
The issue with this is that limine passes hart id on risc-v through this
So you are forced to use it there
well risc-v doesnt have this problem
yeah
btw
if im reading linux code correctly
x2 opt out doesnt disable x2
it just limits apic ids to 255
huh
it has a separate risc-v bsp hart id feature
actually
oh, this is nice
It wasn't there when I ported to risc-v
it does try to disable x2 apic, but that checks if x2 apic is locked, and if it is it just doesnt disable it
But I think the bios might lock you from disabling apic (which prevents you from groing x2 -> x), but still allows xapic?
how can it lock disabling apic?
dont think so, at least i didnt see such a bit
I just read SDM on it
or checks for it in linux
This is how x2apic lock works afaic?
u sure ur not mixing it up with apic enable/disable in apic base?
yes but thats x2 lock, not x1 lock
XAPIC_DISABLE_STATUS is separate from IA32_XAPIC_DISABLE_STATUS[0] ?
I mean idk how this works
Oh no
Lol
tbh, it looks similar to pci hotplug?
yes? what does this have to do with that
Is it not optional then?
it is
Or am I confusing it with something else?
i think you are yes
ATC stands for address translation cache
it has nothing to do with interrupt source verification
oh
nevermind then
atc didn't look too difficult
Anyway, I've done this https://github.com/uACPI/uACPI/compare/master...ThatMishakov:uACPI:master
I'll check it tomorrow
I forgot the comment anyway
THe tables are not too bad
(and the whole thing in general)
AMD is also just one table
I think I forgot to mention, I've completely switched my kernel to uACPI (barebones mode) for table parsing
Cool cool

Damn
Yeah, there are several places where it's reserved
yes
it's 2 uint16_ts
I think I saw some table in acpi.h where it was {u16; u8;} as well?
or something like that
(but I think it's because these entries might be larger than 256 bytes)
because most of them have paths and stuff
Thats really annoying
If thats the only place ill change it in the next major release
yeah, but not too insane
there are 3 places I think
just grep over it?
Not at my PC but yeah
I mean I'm also in bed with my laptop
Lol
oh yeah? source?
it wasn't really hard to find
That's not true
Managarm runs on Limine on rv without SMP request just fine
I kinda read the entire AMD spec, and it doesn't look too complicated
Yeah, sorry, it was late yesterday
So iiuic both VT-d and AMD's iommu are just page tables (similar to x86), and ioapic-like tables for interrupt redirecting, and then some ring buffers for submitting commands, and receiving messages
I don't think I need to add defines for this (?)
Meanwhile, AMD:
type flags length

what disk
ahci
I had a working driver
But I wanted to do all of the stuff around it
Since it would just start, discover the ahci controllers, and fork() itself for each controller, and I don't like fork
So I wanted to finish the pmbus pci discovery thing, then the disk discovery, then finally do the ext4 driver, and then rewrite the VFS mess, after which I could do futex, and switch to mlibc, and hopefully have bash
etc., etc.
I think I'll just get rid of SMP request from limine first 
Since I have code for i686 already, I just need to adapt the trampoline to AMD64??
Wtf is this comment
The misteries of programming
I remember writing it, but don't remember why
What if I randomly add multiboot2 back?

(I want to unify amd64 and i686 initialization code anyway)
This is concerning...
I think I have memory corruption??
I'm blaming the new limine revision 
Like it didn't find madt when initializing lapics, but did find it for ioapic??
Wtf
I think the issue is with the idle_cr3 variable...
What the fuck
I changed SMP initialization, and my whole mm just decided to die
I need a second opinion from a different bootloader 
No, my vmem is returning weird addresses
Another stupid vmem bug rectified 
Idk how, but the code is not too difficult, and it's used all over the kernel, but every so often some bug comes up in there, for some stupidest reason
Now the kernel just happily tripple faults 
(I'm going insane)
(I think this will fix loongarch64 port as well, since uACPI triggered it
)
Epic commit though
Cool, limine is refusing to boot in bochs
Nevermind
Paging's broken (how did it even work before???)
How do you even get your kernel to triple fault
smp init code's busted
this basically means that you double fault handler isn't working
It was working like a year ago
his idt is loaded after acpi init
Now it's tripple faulting on APs
(Because I've ditched limine's MP request, and doing SMP by muself)
For some reason the kernel isn't mapped
(But like I've merged x86_64 and i686 code together without looking, so there's probably a dumb error somewhere in there)
I've looked at it in bochs
It gets to the -2GB code (with the correct address) and tripple faults
I forgot a memcpy
Now it just crashes 
But at least it's after the full userspace init and stuff??
It's probably the race condition
I think it's working? (though CPU id 5 is fishy...)
But x2APIC is broken for no reason?
(Omg, -O3 lto is just one big function, this is insane)
mfw no abortable instructions 
theres no apic icr high
Why is it writing to that in x2apic mode
theres one icr register
I know

But like the thing is
And looking at assembly it's just one giant initialization function
And my kernel doesn't compile without -O3 -flto
how the hell โ ๏ธ
do u build with -ggdb3?
no i mean
addr2line should work
for gdb backtrace to work u need proper cfi annotations in your isr code
I have -g
at least do -g3
it does usually work
dodn't make addr2line work
if u want wrmsr to not kill your kernel u should make them abortable
how?
i implement it same way you would implement copy_to_user
I mean it doesn't matter probably
catch the exception and move rip
whats the error with o0
But linker crashes without -flto
which error?
Also, this is broken
(because I don't wait for anything, etc.)
Wait a sec, I'm recompiling it
All excluding self wakeup is completely wrong as well
you wake them up in the order specified in madt
some cpus might be marked as disabled also
can you wake them up in paralel?
if you ipi them you might die etc
yes as long as u send INIT in the right order
linux sends the entire init-sipi sequence in the order
then waits
This is with -O0
huh
(Not too bad tbh)
It's some std::optional::get or something
I should've just used *
It gets optimized away with -O3
(the checks)
Btw, if I'm using X2APIC, are the X2APIC entries guaranteed to be present?
nope ofc not
its more complicated then that
Check if lapic entries exist at all, if they do, you must use them for apic_id < 0xFF
lapic entries take precedense, otherwise use x2
they may be located in madt after x2, so u have to iterate it multiple times
I'm just using a set so I don't go over them twice
u must go over twice to know what to ignore
first iteration is just a check whether lapic entries exist at all
So this is also how I can detect that I'm not booted on BSP?
the flag in the msr?
yes
no ofc not
though I'm restoring it
Do you have examples of this?
(Or I guess I should just look at limine...)
Do I also fix my lapic/tsc calibration?
linux code, my code
static uacpi_iteration_decision detect_lapics(
uacpi_handle user, struct acpi_entry_hdr *hdr
)
{
struct madt_iter_ctx *ctx = user;
u32 apic_id;
u32 flags;
switch (hdr->type) {
case ACPI_MADT_ENTRY_TYPE_LAPIC: {
struct acpi_madt_lapic *lapic = (struct acpi_madt_lapic*)hdr;
if (lapic->id == LAPIC_ID_NONE)
return UACPI_ITERATION_DECISION_CONTINUE;
flags = lapic->flags;
apic_id = lapic->id;
break;
}
case ACPI_MADT_ENTRY_TYPE_LOCAL_X2APIC: {
struct acpi_madt_x2apic *x2apic = (struct acpi_madt_x2apic*)hdr;
if (ctx->has_valid_lapic_entries && x2apic->id < 0xFF)
return UACPI_ITERATION_DECISION_CONTINUE;
if (x2apic->id == X2APIC_ID_NONE)
return UACPI_ITERATION_DECISION_CONTINUE;
flags = x2apic->flags;
apic_id = x2apic->id;
break;
}
case ACPI_MADT_ENTRY_TYPE_LSAPIC:
/*
* Apparently these might exist even on x86, but there's no confirmation
* of that ever happening, so guard against that explicitly.
*/
panic("Local SAPIC entries are not supported\n");
default:
return UACPI_ITERATION_DECISION_CONTINUE;
}
if (cpu_usable(flags)) {
error_t ret;
ret = register_cpu(apic_id);
if (is_error(ret))
return UACPI_ITERATION_DECISION_BREAK;
}
return UACPI_ITERATION_DECISION_CONTINUE;
}
This is what I do
This is what I get without lto btw
your build flags are very fucked
It's PIE
So does this mean that the x2apic entries that come before xapic have to be initialized first?
you're linking as pie but not compiling as pie
It should be compiling as PIE
are you doing that before or after creating the kernel target
if you're doing it after it has no effect
you should replace both of those with target_compile_options and target_link_options
no
i have one extra iteration before that that sets has_valid_lapic_entries = true
static uacpi_iteration_decision check_if_madt_has_lapic(
uacpi_handle user, struct acpi_entry_hdr *hdr
)
{
struct madt_iter_ctx *ctx = user;
if (hdr->type == ACPI_MADT_ENTRY_TYPE_LAPIC) {
struct acpi_madt_lapic *lapic = (struct acpi_madt_lapic*)hdr;
if (!cpu_usable(lapic->flags))
return UACPI_ITERATION_DECISION_CONTINUE;
if (lapic->id == LAPIC_ID_NONE)
return UACPI_ITERATION_DECISION_CONTINUE;
ctx->has_valid_lapic_entries = true;
return UACPI_ITERATION_DECISION_BREAK;
}
return UACPI_ITERATION_DECISION_CONTINUE;
}
but in here, if x2apic with id > 0xff comes before lapic, it gets initialized first
why do you do < 0xFF instead of <=
yeah but this is x2
yeah good catch that has to be <=
wait no
it is correct
<= 0xFF means it would skip an apic id of 0xFF
why does INIT order matter?
It shouldn't
To ensure that the boot processor is supported post initialization, two guidelines should be followed. The first is that OSPM should initialize processors in the
order that they appear in the MADT. The second is that platform firmware should list the boot processor as the first
processor entry in the MADT.
this is acpi spec
as for why idk, probably doesnt matter on most hw
you didn't answer my question 
? i did
so if x2apic entry comes before xapic, you initialize it in that order?
only if it has id < 0xFF
or rather
if madt HAD any lapic entries that are valid: discard x2apic entries with apic id less than 0xFF
yeah, just make sure u iterate it before u record any lapics
so u check if lapics exist
I guess I should also check the mailbox wakeup thing
not sure if anything ever implemented that
I mean it would have been needed for x86s
if only it hadnt been discarded
Anyway, this works now 
any% smp
I mean it worked on my physical hardware as well
I think it will be easy to fix later
also i seem to remember someone saying a broadcast like that is a bad idea?
something along the lines of firmware-disabled CPUs responding to it
yep


)