#pmOS - microkernel OS for RISC-V, x86, and LoongArch
1 messages · Page 11 of 1
The IPC is very simple
Their discovery is not (at least to me)
What do I do once I remount root, discover new drivers, and have to probe filesystems with new drivers, etc.
Like what I'm stuck on is how do I probe for partuuid/label for my root partition
(since I'm using MBR since limine doesn't support GPT+BIOS)
Though I think I can do it the other way around, and probe all partitions with the filesystems that are in my fstab/whatever
Not query all filesystems to probe all partitions, and then do with that
Maybe I'm overthinking it
yes it does, you can specify a gpt partition index to bios-install and have it install limine there
I think I'll know what I'll do
- I'll publish all bootstrapd services on pmbus (
) - Those services will have capabilities, as strings (e.g. filesystem: [ext2, ext3, ext4], filesystem_actions: "probe", "mount")
- Each partition will store a set of filesystems that have probed it, and also, on success, the service and the data associated with it, as probing information
- The blockd (the point 3 is also inside of blockd) will wait for new filesystems on pmbus
- That will also somehow work with /etc/fstab or whatever (I need to think about how I want to do it)
- I need to decide who launches the servers, tbh I think I'll just IPC my init server for that
I think I've kinda implemented 1
I'm feeling like I'm going insane
This feels overengineered
Cool
Do I give up and use Boost for my C++ stuff?
how is boost useful for the problems that you're facing?
It has a UUID class
a uuid is just a char[16] with some bits fixed
I know
Cool, my broken Rust code broke C++...
what is Boost?
Libraries
thx
I don't know if they work in freestanding environment though
i'll be using them in my services anyway
its probably the most bloated library in existance
written by language lawyers
i wouldnt touch it with a 10 foot pole
i think you can choose the one you want
I guess I'll just use std::vector 
XD
frigg 
Does mlibc use it?
Because I've been thinking about it recently, you wouldn't be using stl in there, for example
Cool
I think I'll port mlibc after I finish the ext4 thing, and add futex, and fix my IPC (which includes using rights for interrupts, fixing timers, getting rid of send_message_port and adding bounds so Rust doesn't deadlock)
So it sounds like never 
Anyway, I've gotten to 4 out of there?
ultrabased
what libc are u using now
my own
but it's kinda bad and incomplete
And libm is stolen from musl I think
Idr
What if I change my C++ async stuff into the same thing as what Rust does now?
(I think I kinda grew to like it)
(sorry for ping, I meant to disable it)
How did I not know about std::as_bytes???
This is fun
Cool, my C code is elaborately trolling me
Oh my god, why do I dislike writing C so much
why are you doing it if you dislike it?
It's a bootstrapd server, which was like the first thing that I wrote, and it's too large to rewrite in C++, and besides, C is kinda fitting there
Since I'm using a limited set of libc

imagine disliking the best language
idk could not be me
i mean i like rust so
Idk, I like to think that I'm good with it, but I just get fatigue from thinking about manual memory management and writing all of the boilerplate
I mean the fact that my lsp is broken is also not helping
bro is a js programmer at heart
And python
I mean Rust feels weird, it feels bad writing it, but good after you've done it
real
Bruh, I've asked chatgpt to write me args parser, because I can't be bothered with it, and it wrote code with a bunch of double frees...
why do I even bother using ai
chatgpt is not a proper coding tool
I know that people use GPT models for coding? It wasn't a complicated problem
yes but (1) they don't use the free version which is severly restricted and (2) they don't use the web interface which is not made for coding (and has different tool access/system prompts/etc compared to the actual coding tools)
I tried codex and it's like super cool? But it burned through free tokens very quickly
It had managed to change stuff and run it in qemu by itself...
Before it could find the issue
dw, you are not the only one having problems with syscalls, lol
It's not a syscalls problem
My bootstrapd dies because of heap corruption
XD
ah
And I've no idea where to look
pain
ask claude, lol
And when it dies everything kinda dies
I don't have subscription
are you in school?
I've installed Codex but it burned through tokens and didn't find it
I'm doing masters 
then get github for students
I have it
They didn't give it to me
Oh, I didn't redeem it
XD
Does it have agentic ai stuff?
yes
not all the claude models tho
they got rid of them from the student plan
bc they were too expensive
you only get haiku from anthropic
it doesn't matter I guess
gpt 5.4 is good
bruh
?
it's scanning my repo
thats how agents work
mine had a lot of problems doing that, lmao
My ns16550 driver is working overtime
like I already did that
ah
like I think it's fully working?
and right after I said it, it's having a skill issue
On a separate note, I've been thinking about notifications (about rights, tasks/groups deletion, and interrupts), and I think I have a strategy for implementing them in a way that does not allocate memory on sent messages through them
So it can work when the kernel is short on memory (which would be when things start dying and these notifications start to be sent)
Since at the moment it's either not implemented or doesn't use rights (sends to ports directly bypassing my capabilities system) and allocates every time
I feel like I have to work on kernel allocations in general though

What if it's single threaded
(my code is single threaded, this is a filesystem)
rust doesnt buy it
I'll ask clanker 
Also, crate's skill issue
I think the ideal solution would be to implement single_threaded or something
@torn arrow
Clanker did this
lol
Wtf is ?Send
?Send = not send I think
Clanker said it makes it optional
wouldn't just removing the trait bound make it optional?
I have no idea, I'm new to Rust
I think I need a single threaded feature
basically what's going on is we have Arc<Inner { reader, writer } > so there is concurrent access
This is how I'm trying to use it https://gitlab.com/mishakov/pmos/-/blob/dev/userspace/ext4/src/main.rs?ref_type=heads
do you have mutexes? I think Arc<Mutex<T>> would fix it
I think there isn't much contention usually?
oh my bad then
mfw
yeah
no as in that wouldn't make it Send + Sync?
I mean I can make rights Send + Sync
Idk how
But I think they're thread safe
My runtime isn't though
sorry I'm a little disoriented rn for some reason
Don't the futures need to be Send + Sync, above all?
is your OS async? you could try enabling the sync feature
Yes, I have async IPC
if your executor is singled threaded (something I haven't considered until now), they don't need to be, since nothing is moving between threads
ok then async it is
Somehow in my setup I just implement directly onto this:
pub struct BlockBuffer {
dev: Box<dyn BlockDevice>,
block_size: usize,
}
impl Ext4Read for BlockBuffer...
impl Ext4Write for BlockBuffer...
I suppose the difference is block device does async fn write(&self, block_id: u64, buf: &[u8]) -> Result<()>; so I don't worry about mutability
not my kernel entirely, so I didn't design that, but it's custom
also I use a monolithic design
I just got off a conversation that really confused me about async which makes this even more confusing somehow
Also, this is talking to a C++ AHCI driver on the other end 💀
I wonder if you can just remove the Rc<RefCell<
no like just no refcell or rc at all
(or like I can make them, but it will syscall the kernel all the time, which is bad)
is there something that needs to be mutable
what is a "right" in this context?
No, right does need to be mutable, I think
ah ok
Yeah, I do &mut self.reader.borrow_mut().disk_right
I think the issue is a mutability one more than anything
The mutability should be fine
Like with a single threaded runtime it won't be mutating it from different places at the same time
true, there could be panics with the refcell
no
as long as you don't await during a borrow you should be fine no?
yea
yeah ok I'll reduce the requirement then
I mean you might want to keep Sync + Send for a multithreaded async kernel
yeah I'll feature gate it
I mean I am planning to make my runtime multithreaded eventually, but it will need a bunch of other things to work
So eventually is like in a year
I'm cooked if two crate in a dependency tree ever depend on different features sets of ext4plus
Huh?
feature sets are additive, but I'm using them as on off toggles. Essentially cargo sometimes merges feature sets for efficiency. This is bad if someone depends on the multi-threaded feature, then you'll get redundant warnings about stuff
I'll push up a fix at somepoint. Turns out async_trait requires you to be Send + Sync by default. I can bypass this, but it's not cooperating with me at the moment
?
I do that, but somehow it doesn't help
also rip my ability to ensure no breakage across feature flags
try https://github.com/arihant2math/ext4plus/tree/multi-threading when you get a chance?
one sec
It's 1 am where I live, so I think I'll just ask a clanker to do it
It looks like it has compiled
Give me a sec, imma implement the missing stuff
What a nice responses... https://users.rust-lang.org/t/get-page-size-of-target-platform/10243
Is it possible to get the page size for the target platform programmatically? Ideally this would be as a compile-time constant, but a runtime variable would be good too.
"Linux is the only OS" strikes again
I think I'll finish it tomorrow, it's doing something, and then explodes in mmap()
This is fun
I think I'll finish it tomorrow...
yeah I think that means it's not a valid ext4 disk
One is not a valid partition, the second one is my ahci driver issue
-4 is e2big
I'll publish a new ext4plus version tomorrow or the day after that with the fix probably
thx, this is awesome
btw, is there a way to get fs type? (ext2/3/4)
though maybe it doesn't make sense
look at the magic 🔥
ext3 and ext4 are just extensions to ext2, so you'd look at the feature fields in the superblock
(I had it, but it was vibecoded in like 2023, when I was experimenting with chatgpt, so I've decided to throw it away)
Lol, I've ran my code through an AI detector, and it (the detector) is so bad 
Though idk this whole no AI thing makes me feel so bad
That website was a code humanizer. How sad
Am I OOPing too hard?
The right deletion notification shouldn't be too bad, I think
also wtf, do I leak task groups????
I don't nevermind
nice function
If u can call it why cant u just delete ptr instead
it's a virtual function, and I wanted the other struct to push itself into RCU queue
yes
this cannot be deleted within the scope of the function because i love llvm
I had googled it in the past
i can try coming up with an example
struct Foo {
int field;
int bar(bool p, bool q);
};
int Foo::bar(bool p, bool q) {
int v = field;
if (__builtin_expect(p, false)) {
delete this;
}
if (q) {
v = field;
}
return v;
}``` consider a definition like this
and assume that it's allowed to delete this in this context
furthermore, assume that delete unmaps memory immediately (which it may do)
then, when Foo::bar(true, false) is invoked, the program crashes on a field read because llvm decided to llvm more harder
But I'm not accessing any fields
you can easily end up with code that accesses them (behind conditions, even with weird patterns like this) if you get weird inlining and devirtualization
But it's not always ub 
which part of "undefined" do i have to explain to you
delete this is defined
idk man
even if its defined it generates broken code in clang
so its as good as useless
How else are you supposed to do rcu or shit like that
yeah committing suicide is not UB in c++ provided that you never access this again ofc
Then it's a clang skill issue
again see my point above
if it generates wrong code in clang then its as good as useless anyway
does it though
that'd be surprising since it's indirectly used in a lot of patterns
and in general llvm applies dereferenceable to this
hmm is this unsound
can i turn it into a rust bug
would be epic
Hm?
how is this llvm ir problematic?
it has a load from the this after loading from the now-deleted object
define dso_local noundef i32 @Foo::bar(bool, bool)(ptr noundef nonnull align 4 dereferenceable(4) %this, i1 noundef %p, i1 noundef %q) local_unnamed_addr {
entry:
%0 = load i32, ptr %this, align 4, !tbaa !33
br i1 %p, label %delete.notnull, label %if.end, !prof !37
delete.notnull:
tail call void @operator delete(void*, unsigned long)(ptr noundef nonnull %this, i64 noundef 4) #2
%.pre = load i32, ptr %this, align 4 ; yeah thats gonna work great
br label %if.end
if.end:
%1 = phi i32 [ %.pre, %delete.notnull ], [ %0, %entry ]
%spec.select = select i1 %q, i32 %1, i32 %0
ret i32 %spec.select
}
what does tail call do?
its a normal call
with some weirdness im not sure about
you can forget the tail qualifier pretty much
Hmm
Yeah im pretty sure its not ub in c++, so this is a clang bug
yeah this may be a clang bug
you basically need delete this in one way or the other to implement a shared_ptr
do you?
No
no you dont
no for two reasons
firstly, you can obviously hack around it with e.g. unions
secondly, the C++ STL can just cheat harder
and they can do whatever with a special promise that its actually okay when they do ub
I don't think there is anything in the standard that disallows delete this either
the rust stdlib does quite a bibt of this
where are you looking
i couldnt even find anything about this
yeah there is nothing because the this pointer is just treated as any other pointer
i guess in practice this does not break because code will always do delete this last
uhh thats not really true
the this pointer must be valid at function entry because the call is considered an access
but there's nothing that mentions that it must remain valid throughout the function
well, it doesn't say that this has special semantics in this regard, so it doesn't have any
the isocpp faq agrees
the faq is not normative
yeah that's clear
have you read all of the standard though
like i cant find anything saying anything about this except its a pointer which duh
i've obviously not memorized the entire standard 
so like, with a reference, having an invalid reference is UB right?
which i think would justify this transform if you wrote the method with deducing this
also libc++ literally does delete this in shared_ptr
libc++ also abuses inactive union members for SSO 
lmao
its not a pointer
For implicit object member functions, the type of the implicit object parameter is
(4.1) “lvalue reference to cv X” for functions declared without a ref-qualifier or with the & ref-qualifier
so its passed as a reference to the object
idk if that affects anything tho
The object designated by such a glvalue can be outside its lifetime (6.7.3 [basic.life]).
seems like yes you can have an invalid ref
and i guess llvm is just doing a little ub trolling
when would it even be legal for llvm to apply dereferenceable then lmao
if clang cannot optimize the case where the "delete this" is last because it'd break its own shared_ptr impl, it's good enough for me
rules for thee but not for me 
I've finally implemented no-reply notifications from SendOnce rights with this cursed contraption (I need to do SendMany thing as well, but I need to decide how to track multiple rights without it being too slow)
But after I moved some stuff around, this was relatively straightforward to do
(I just send the right as if it was a message at the end of its life instead of deleting it immediately)
Omg, I didn't even think about it, but I can trivially implement blocking send_message_right(), and async unblocking notifications (so I can do clean async send with my Rust/C++ runtimes as well), using the same notifications mechanism
You just try non-blocking send, if it fails, you wait for a message that it's sendable again, and try again
So you just send_message_right().await everywhere, and it won't even allocate any memory
I mean at this point, what's stopping me from making memory allocation async as well 
And then I can just make processes page themselves in in userspace 
I think I need to do something about the locks situation in my kernel...
Fuck, I've just noticed a use after free in there 
actually, no
this looks like it would be super deadlock-prone
One of them was not necessary, so only 4 nested locks 
I think lock depth in Managarm never exceeds two
It should be fine as long as you run kernel with 1 CPU only
But yeah, I think this is the longest depth, and it's during a creation of a new right, so nothing should have access to new_right there, and then the other stuff should follow this lock order for the other objects
Though I have a different function which locks 7 locks at once
when you map memory, you acquire the vmstate lock, which allocates from a zone, which in the slowpath acquires the zone lock to allocate more memory, which in the slowpath acquires the pmm lock
so thats 3 locks
and you can also take the kernel page table lock which is also 3
I have this fun contraption for that 
and then it takes 2 more nested locks
IPC 
what ipc tho
idk i dont have ipc
message queues
ok but why 5 locks lmao
so that you can send capabilities
surely you dont need to acquire every capability lock to do that
you can send up to 4 extra
But how do you atomically check that all of them are alive
lock the handle table
problem solved

i need to optimize my syscall code so that i dont lock the handle table once for each handle the user includes in direct syscall args
No, I'm not sure this would be enough
idk what your design is like
maybe its not possible within it
in my design its def possible (maybe because i have refcounted handles?)
async send sync recieve, multiple sender, both sides can revoke rights
and I'm trying to implement revocation notifications
no, it makes the userspace api 1000x cleaner and more convenient
you say 1000x cleaner
but then your ipc takes 7 locks
atp just take a global lock lmao
there is a good chance a global lock would be faster tbh
how do you map a buffer if the capability can be revoked?
do you just leave it mapped?
i.e. you cant revoke mappable objects properly
or do you unmap it
i.e. you cant safely copy from an mmaped object because you could get rugpulled
My mappable objects are refcounted
You get a capability to map
And I haven't implemented revoking memory objects yet
But I think I can just leave them mapped, and the userspace would get EFAULT because the pager has disappeared
I need to reimplement pagers first though
I had them 3 or so years ago, but basically everything memory and IPC related had changed in the kernel since then
efault on what? on access?
So basically this just becomes an anonymous memory
Yeah
so you can get rugpulled, awesome
Idk, I don't really have a proper filesystem yet
What else can you do?
You can catch those and try remapping that memory with a new object
In userspace
thats what wayland does
its so awful tho
you could require a capability to make pagers
E.g. if half of the system dies, including all disks, you can just rediscover everything
Yeah, you can make everything a capability
Then the stuff like whatever docker is using in Linux is using becomes trivial
well, the solution is probably just to do not rely on memory mappings if you cannot trust the remote that handed you the mapping
yeah
You just give capabilities with less permissions
But like everything can happen, even if you're a privileged server
with most programs there is a clear trust relation anyway, for example: application trusts fs server
The user can pull the system disk out
Linux userspace dies, Windows somehow survives
No, but with Windows to Go, if you accidentally yank the drive out, and quickly plug it back in, it continues as if nothing had happened
I guess it just resumes them
yeah
But is it better actually?
Sure, you're only holding 1 lock, but for much longer, and this is shared by much more stuff
its shared only by other threads
(Also, I only have spinlocks in kernel)
if you are nopreempt thats fine
sleeping locks are slower if you dont have preemption to worry about
Yeah, but the rights would (usually) only be held by 1 thread
sleeping locks are faster on the fast path than spinlocks
since spinlocks need to disable irqs
are they?
oh right
well not if your kernel is nopreempt
and you dont take locks from the irq handler
Yeah, I'm nopreempt and never enable interrupts*
Or like if you get interrupted, you just don't take locks, problem solved
Or don't reschedule
well if you just disable preempt but not irqs, you're potentially extending the duration of a spinlock by hundreds of cycles if an irq happens
I mean paravirt probably complicates everything...
i dont think this is a huge concern
irqs are generally rare
my drivers for everything except timers are in userspace
and still, there's stuff like lazy irql
it's definitely a trade-off between worst case latency and throughput
where you'd just bounce back, and do the stuff after the locks are released
I think my kernel is very far from being realtime anyway
Idk, maybe I can play with atomics instead of locks
But this will make it even more complicated
I don't know how your locking strategy works but 7 locks sounds excessive
I take things in particular order
you can probably improve this by reworking your strategy
what is a right in pmos and why does it needs to be locked for IPC?
Why do you need to lock it?
so it can't be revoked before the message is sent
I'm writing the notification code right now
But it's so that you can recieve a bunch of messages, and then a notification that the right has been revoked (so there can't be any more messages)
And that notification has to arrive after everything else
There are probably better ways to solve this
yeah
but there are probably better ways to solve everything I have right now
So this works and I'll change it when it becomes a serious performance concern
FWIW Managarm's IPC also support capability transfer but it never takes more than one lock for the IPC itself
but managarm's IPC is quite different to mine?
Idk, I haven't really looked at it in too depth
The IPC that's sent from kernel won't need to take any locks at all, I think
(after I redo it)
well, except for the message queue
I'm just saying that if you need 7 locks, you should probably rethink it
but that can be made lockfree, it's just a list
When I was writing it initially, I thought that I could get away without having to lock that many at the same time, but then there were some problems with it
One thing that Managarm does "better" (at least with regards to the locking strategy) here is that inflight capability transfer does not have ownership of the capabilities
It's just a deque, so just needs a push_back() and pop_front()
The user is responsible for keeping the cap alive until the transfer completes
if the cap is concurrently unmapped, the transfer fails
I transfer ownership to the message
So that userspace can reject them if it's not expecting them
So the question "how do I keep the cap alive during the transfer" does not come up in the kernel
yeah
but how do you transfer capabilities?
I mean I have a different mechanism for it
as well
Where you can just transfer capabilities between task groups (which serve as namespaces)
But this has the issue with the fact that someone can just litter your capability namespace and not tell you about it
well, userspace says "i want to sent capability at handle X" and if it unmaps the cap before the transfer is complete, it just gets an error from the transfer
what does unmapping do in managarm specifically?
by unmapping i mean closing the handle
Are your IDs global?
Mine are not
Or I mean they are -ish
I know why I did what I did
When you transfer capabilities, you know the source and destination namespaces right away, no?
yes
well, right away = when the actual transfer happens
you don't know the destination at the time of posting the send
Ok
I need to take a look at your IPC I guess
Because my threads can choose where to accept the capabilities
When receiving
But it's the same issue I guess
And this transfer is synchronous then?
i don't have time to explain the full IPC model, you could look at the Managarm paper if you want to understand the details
Ok, sorry
but both send and receive post lightweight message structs to queues without doing any copying of data etc
the actual transfer happens when both send and receive are posted
Where's the paper
On a separate note, how are you supposed to be doing objdump/addr2line with Jinx?
This is fun...
(I really need to steal Infy's unwinder
)
Oh no, it's memory corruption
I'll ask clanker to fix it 
It kinda found it but it was a very simple thing that I could have found myself, and there is a different issue now
behind every assert there is a bug
are u planning to make any new talks on it
Based on this paper? Probably not but we'll surely have more Managarm talks in the future about upcoming topics
Last talk was the one by Geert on syscall cancellation
My kernel does it like this
https://gitlab.com/mishakov/pmos/-/blob/dev/kernel/generic/processes/tasks.cc?ref_type=heads#L914
what topics do u have in mind?
why is it commented out lol
Idk, very old x86-specific code
It's defined in the header, which then calls arch-specific code
So I probably commented it out when porting to RISC-V and forgot to remove it
On amd64 it calls this https://gitlab.com/mishakov/pmos/-/blob/dev/kernel/arch/x86_64/registers.hh?ref_type=heads#L159
(don't look at my context switching code
)
(I just switch the current task pointer, like in bad tutorials)
Cool, I have notifications about deleted rights working, I think
Time to add Rust abstractions 
And I've finally implemented delete port syscall
They vere easy to do
I think I'll do futex next...
Ok, it looks like it's too complicated 
its not that bad
first simplification
you can do futexes 100% in userspace
I mean it in itself is easy
futexes that synchronize between different processes have been deemed by fuchsia to be lame and so you are allowed to not support them
I do have them in userspace at the moment
But I want to move it to kernel
It relies on my IPC
IPC in process???
and it's problematic because of priorities
wdym
my recieve is blocking, so it blocks that way
how do you implement futexes lol
i mean it's not quite a futex
I did mutex and conditionals with IPC for blocking
but I want to have a proper futex
so that it doesn't have to allocate (which my IPC always does at the moment)
i think you just have a bad impl ngl
I have plans to get rid of it, but I can't completely get rid of allocations
So my mutex works by trying to lock it in userspace, and then when the thread sees that it has been locked by someone else, it blocks on a port
the core scheduler API i implement for this is basically ```rs
fn park_prepare() -> ThreadHandle;
fn park_commit();
fn park_wake(handle: ThreadHandle);
with semantics of "if a `park_wake` arrives after `park_prepare`, then the `park_commit` will not block/will stop blocking if it has been entered"
you can expose basically this to userspace by making a threadhandle just a tid or something
and then the wake() sends message to that queue
and then its a binary semaphore which is trivial
and you also need some form of inline lock for synchronizing on the userspace state
i have a ttas spinlock because its a kernel mechanism but thats not great for userspace
but the issue there is that the threads push themselves into a non-blocking list, which is probably a bad implementation, because it requires the waiter to wait for it to become consistent, and there is a deadlocking priority inversion in there
just spinlock on a list lol
if its good enough for webkit (and i think it is) its good enough for you
or use an rseq
it doesn't solve the priority inversion
my scheduler has priorities, but I can't use them
(tbh, my scheduler also needs work)
I have global run queues, and I want to eventually make them cpu-local
(except for the threads that are pinned to a given cpu, they have their own cpu-local queues)
But I haven't really looked into how to do work balancing and stuff like that yet, and global queues kinda just don't need that
so why not just do it in futex
Because it is a successful project right 
lol true
i mean sure
i mean true
if you are in kernel
or just use the virtual address and dont futex cross process
i think cross process futexes are kinda bad in general
idk, posix has an api for it, and some ancient program might decide to use it
futexes are not posix
also the solution is to not cave in to every demand of every broken program but to fix the program
it could also be nice for stuff like pci, where you need to lock it across drivers
if all your drivers trust each other just make them one driver tbh
yeah, but it's a simple api that can be used to build everything in posix
almost all sync primitives are complete
a pthread mutex is also complete iirc
yeah, the other (better) solution is to just ipc the central server which holds pci stuff
(or put pci in kernel, like managarm did)
idk, i feel like mmu will destroy my kernel
I need to rework interrupts...
there's so much stuff to do 
by construction: a pthread mutex+condvar is enough to implement parking_lot_core which is a superset of futexes so its trivially complete
go channels are complete too iirc
what does it mean?
you can build basically all of them from any of them individually
but go uses futex internally...
I mean everyone supports it
kinda
i mean yes but thats not the point
I can (and probably should) do priority inheritance based on ipc as well
but the issue with my mutexes is that I have to spin in userspace before I get to know where to send message
So iiuic, with futex I can just add an intrusive list entry to my threads, and then have a hash map of futexes, and push them onto there, which will also work with scheduling and stuff
i dont think this is even true necessarily
not on all platforms anyway
so it's gonna be lightweight and won't ever allocate memory and thus won't have an opportunity to fail
actually no
the difficulty is with my scheduler
for example on macos, they hang in a pthread condvar wait
on netbsd, its in lwp_park
on windows, its WaitForSingleObject
but this is basically futex?
no
no its what you do with ipc except with a kernel semaphore object
sorry an event object
which is just a binary semaphore afaict
what should I do instead of futex then?
another issue with my IPC is that it can't timeout
(though I think I can implement it with my new rights changes now)
Only 3 levels of inheritance 
https://gitlab.com/mishakov/pmos/-/blob/dev/kernel/generic/messaging/rights.hh?ref_type=heads
This looks similar to futex
yeah, but it still hides vtables and stuff under the hood
wdym
and you have traits and weirdness
a trait is just a class with only pure virtual methods
like the inheritance is bad because of the virtual functions?
but rust still has that
and i dont even have a lot of dynamic dispatch lol
i have one case of dynamic dispatch in my rbtree code because of a type system hack
a few in my ISA code where its a type system hack and a manual vtable
idk, I feel like it was warranted there
one in my object abstraction where its a compile time assertion
and thats it
and i have dynamic dispatch in my object abstraction but also through a custom vtable
so basically the same thing as my rights
the three levels are there because my rights inherit from messages
jank
so that the kernel can send a right directly, and userspace can read it as a message
e.g. I'm planning to rework my timers and interrupts, so that the userspace still recieves the notifications as messages, but internally the kernel just pushes those things onto the message queues
according to a clanker, lwps are basically threads??
thats the idea
linux calls (or used to at least) call them that
just processes that share the same address space so they're "lightweight"
I already have something similar to park/unpark then
Then what is a normal process?
So, NetBSD seems to just build a list of waiters, like I do, and then does priority inheritance protections in userspace as well?
Ok, I think the _lwp_park/unpark and "proper" mutex is more than 1 evening project
So what I'm going to do instead is to improve the kernel initialization, and hopefully unify limine and hyper code, and allow to be booted with hyper on x86_64 as well, and maybe I could also port to aarch64 
And I'm also planning to introduce interrupts rights/redo the interrupt handling in general, so it doesn't allocate memory and hopefully make it faster in general
and then I also wanted to do the same with timers (which shouldn't be too difficult (famous last words))
and it would also be nice to implement the vfs stuff, but I'm kinda waiting for ext4plus crate to be fixed so it compiles properly with my async runtime, so I'll probably just do it once that's sorted out
Why do u even need kaslr
Makes debugging harder, adds relocations
I can disable it, but idr how 
idk lol
My i386 build works
this is x86_64
is this hyper
Yes
bru
Wdym
I'm making my kernel truly dual protocol
linux protocol 🗣️
my kernel is protocol independent
Dual protocol means u can boot the same binary
yeah
this
How did you make it independent exactly
I was thinking about adding multiboot2 
it's not working right now, but i made an efi stub that seconds as a limine executable
Oh
Did u enable higher half exclusive and allocate anywhere?
no
Do it
can I keep this option for ia32 kernel?
Docs
It says "64 bit kernels" so it's confusing if it ignores it or rejects it
Wdym
I guess I just won't
Like if I boot a ia32 kernel with allocate anywhere option, will it boot and just ignore it?
It cant allocate anywhere since for ia32 its direct mapped to phys 0
Iirc it will error out
Ok, now it boots and tripple faults 
Lol
I don't have disk space to check if ia32 still works...
Believe it
fun
Gpf?
time to cry in x86
Yeah, it can be anything tbh
I just rewrote my ultra protocol init code to not assume anything about ia32
I don't have it 
How
Actually, nevermind
this tripple faults for no reason
I feel like half of the kernel doesn't get initialized or something dumb like that
also, what's weird is that it doesn't print anything to serial
wtf I forgot to call main function from assembly 


Btw why is it trying to allocate from a reserved region lol
It's the largest memory region available 
That fixed a bunch of stuff...
Oh no
Time to add more printfs

oh no
it works but then it breaks
yeah, booting with limine fully works
Whats the diff
I've no idea
I'm missing something that I do with limine during the kernel initialization
But this is deep into userspace
Time to fix linking with no lto 
I think this will be an ultimate reddit ragebait
"My 32 bit multiboot kernel finally has a shell!"
This is a pagefault during a pagefault?
which breaks because I don't use hhdm
Let's see if clanker can fix this 
The boot process basically the same though
Does ultra do elf relocations?
Though i686 build worked with no issues in the past...
Why is it so painful to watch it do stuff?
Ok, it's a skill issue with both protocols....

but couldn't there be relocations even without kaslr?
not in an EXEC elf
but why?
it's only relevant if u wanna do kaslr
it's a niche (and not super useful) kernel isolation technique
certainly has 0 relevance for any hobby os
idk why mint implemented it
can you do kasl without it?
wdym
kasl + exec
can u lie in the elf header?
sure its possible
should u? probably not unless u can do self relocation
or what is 0x03?
like ld.so
every userspace executable is ET_DYN
check any elf u have lol
but its not linux doing those relocations, but ld.so
another file it loads alongside and hands over control to
$ readelf --header /usr/bin/cat
ELF Header:
Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
Class: ELF64
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: DYN (Position-Independent Executable file)
but that would also be ET_DYN, wouldn't it?
yeah but linux doesnt check those types at all nor does it perform any relocations
ld.so relocates itself
this sounds fun
they have some cursed code in there for it
i thought u had a dynamically linked userspace??
same as the kernel elf self relocation code that i posted a while ago
I don't yet
I wanted to port mlibc so it could be done for me 
Anyway, this is x86_64 + hyper build (fully working)
Ultra + Limine dual protocol with the same kernel binary
Clanker found a very dumb bug, which was unrelated to boot protocols...
Which I had since forever, and it only surfaced now (and was hitting limine as well)
always blame a bootloader if u have an early crash and uacpi if u have a late crash 
I mean both stress memory allocation in their own ways 
but the issue was that I though it was early init code, but it's basically the same between limine and hyper protocols
I mean I don't reclaim bootloader memory with hyper yet...
It should be trivial to implement though
i dont reclaim it yet because i rely on its page tables 
I don't use direct map 
gg
but since u support crappy arches its easier not to use it
since its the same code for all arches
Though I think I'll introduce it as an optimization on 64 bit arches
Since I use it on loongarch
Where you can place it in the canonical gap
it's a good optimization since u can map hhdm with gigabyte pages
so it's very light on tlb
It should be trivial to implement
All of my code explicitly calls map/unmap already to access physical memory, and I can just short circuit it to return hhdm + addr
(like I do on loongarch for no reason)
But I have no direct map windows at all
besides the initialization, where I have to use it
Ok, I really want to add multiboot2 and then MIPS
Since I assume it should be really easy considering I already support risc-v and loongarch
Do big endian power pc
but booting there is cursed
idk, like what bootloader do I use?
I have a Wii to test it on though
I do now 
Probably the firmware
I'd need a prekernel 
Yes
I think I'll do this next...
It didn't really find anything
Just some locking issues, and an issue with tlb invalidation
and some path where I didn't propagate errors correctly...
Ok, it also found deadlocks in my (pinned) memory objects and page tables, but I think I'll just nuke that, and fully switch to memory object rights, since that subsystem is cancerous anyway
I've talked to a clanker and it pointed me to this, in relation with the interrupt capabilities...
https://docs.sel4.systems/Tutorials/interrupts.html
https://docs.sel4.systems/projects/sel4/api-doc.html?utm_source=chatgpt.com
I think I'll do something similar
(I mean I kinda had something like that already in mind)
What I'll have is
- Root/interrupt management capability (I probably won't bother with it for now though
) - Interrupt handler capability
- Interrupt notification capability
Hm?
hehe
h
Cool, my risc-v port had somehow survived all of my changes

cool, my i686 port tripple faults on boot 
In this rdmsr...
(which I think might be a skill issue with x2apic and smp?)
I wonder if that's the same issue as what's been stopping this from booting on that macbook...
Yeah, it almost fully works if I disable SMP 
And of course it works on risc-v, because every time I look at its code, I'm amazed how good it is
Yeah, no, it's still broken on that macbook
i686 dies on macbook?
no, smp
lol
I haven't tried i686 because I can't get EFI to work in Hyper
(probably because I'm compiling it wrong)
i686 was dying in qemu
and I would assume x86_64 would be as well
(My apic/interrupts code is shared between the two)
theres only so many ways to compile it lol
refusing how
(It compiles llvm and rustc in the process, which takes several hours on my laptop)
Idk, just doesn't boot
what does that mean
says "failed to boot" and tries to boot from pxe
huh
I have't gotten into edk2's menu though
screenshot?
definitely works fine for me & ci
probably means theres no BOOTX64.EFI on there
there should be
u can wait for it to drop you into edk2 cmd and type dir to see
how long do I need to wait for?
And I compile it like this https://gitlab.com/mishakov/pmos/-/blob/main/host-recipes/hyper?ref_type=heads
what does it need to be?
AA64

definitely not 3 A
It doesn't matter, I don't have an arm port anyway
do it 
huh
Too much work 
I wanted to unfuck my interrupt management first
Nothing in boot/efi
gg
I mean I can just use limine 
though having both would be better
how does it help your interrupt management
it doesn't

the conversation had started with this
i was replying to the thing directly above my message lmfao
lol
Ok, I've managed to get it to work
I seriously need to stop using copilot
Because I make a lot of mistakes myself already, which I can't see
And the fact that it autocompletes my shitcode with even more plausible-looking weirdness, but absolutely wrong stuff is bad...
what was the problem?
wrong extension
ah
and also mcopy didn't like that I've given it multiple arguments?
idk
but hyper with uefi boots instantly
anyway, what were you replying to? I'm confused
What I meant by this is that I want my interrupts to be done with capabilities
And I guess I can then handle that stuff transparently in kernel
All userspace would get is an interrupt source, and a right to recieve interrupts from it
But yeah, I'm having trouble with it even on x86...
