#OBOS (not vibecoded)
1 messages · Page 10 of 1
Yes
I assumed you wanted both of us to answer
I was asking about both you and Infy
The latter responded to a different question I believe
Ty
Ye
I implemented the part of the vmm that ages pages (assuming I understood the algorithm properly)
I need to implement a virutal allocator 
Even thinking about this function slightly makes me realize it's doo doo
the performance will be shit
naturally
currently the kernel takes up 224 pages of virtual memory'
and this function is O(n) time complexity
if I'm lucky
I haven't gotten into the other functions it depends on
suggestions on literally any optimization for this
are welcome
@main girder dont shit too hard tho
bah
I'm ready this time
as in I am not rewriting again
but this is still early code for the vmm, so I'm not too worried
I feel like you haven't even read it yet
Lol
look at line 18
Yes
I think best while sleeping
I'll go to sleep and wake up with some ways to optimize that code
I'm starting to realize that the aging algorithm is a lot easier said than done (or well, done efficiently)
my left arm was destroyed by my cast, it's so stiff
you know how when you relax your arm it rests on your side
my left arm is bent like it was when I had the cast
and to bend my elbow isn't fun
but, after a few weeks it should be fine
Yeah
but since I can't do anything about it until then, I'm just venting it off here
if that happens, ignore it
anyway infy isn't it 6 am for you
rather you woke up early
or haven't went to sleep
(I assume the latter)
Im going to the airport
oh
So woke up early it is
Damn you program whilst sleeping? 
no I think whilst trying to go to sleep
oof
Don't
When you go to sleep, make yourself half brainded, you'll fall asleep much faster
I've found where I jinxed my os
is that message it?
in the replied message
ah lol
I changed my panic screen
It's on fire
that's the gif I was looking for
meanwhile mine
🥱
wow your hal is a separate binary? thats soooo 2021
i realized its pointless larp to do that
You guys have HALs?
what is HAL?
Hardware Abstraction Layer
I just have a separate arch directory for each platform
that does some stuff
ohh
It is pointless on x86 cause there's just one platform
you are conflating architecture and platform
but it probably won't be pointless on ARM platforms
the HAL does not abstract the architecture
it abstracts the platform
in NT the architecture specific code is just in arch-specific subdirectories of the components
like mm/mips and ke/mips so on
I am probably gonna end up using a different HAL for each ARM device I port to because they might have certain necessary I/O at different addresses etc
would an ioapic "driver" be in the HAL?
like device trees might be in different places and so on
i guess so
or lapic code
the pointer to the device tree is given to you
anything you consider like an integral platform feature would be
not so sure of the IOAPIC
well technically there's one LAPIC for each core!
and they're mapped to the same address IIRC
of 0xFEE00000
still some terms that I don't understand well, but that's okay, I don't need them
lol
now it might be pointless LARP to separate out the HAL and the kernel, but it actually helped get rid of some layering violations previously
so I'd say the action that I performed wasn't pointless
hey, it dumps the stack trace as well as the dllbase of every loaded driver
more info than just Test panic.
Yeah, the ASCII art is cool but not yours
anyway, I do need a stack trace soon
not @ornate ginkgo's either
he found it on some website
idk how to crash obos to make it provide a useful panic
oh ok
because it's just so stable /j
hint: the @silent feature just doesn't send r4 a notification, but it still is a ping and it will show up as a marker in the channel
I know
he'll see the ping eventually
just I don't wanna give him a push notification
mine darkens the screen.
after commenting out random lines, I get a meaningful panic
oh thats cool you got ubsan working
I also got kasan (well my own algorithm, but anyway)
which of course stops working as soon as I try to trigger it
nvm
I allocated one byte, which is rounded up to 0x10 bytes
and I accessed the 2nd byte
ptr[1]
there
the panic for a kasan violation
Pretty cool
I just need a stack trace
which I will do in a couple hours or tomorrow
I decided to run the scheduler test that was choking before
It started 16 threads which simultaneously use the allocator
so far 8 threads have exited
after 11 threads exit, the allocator deadlocks on all cores
i think that's a bug
There's no such thing as a bug, it's just an unexpected feature 🙂
nvm that seemed to be a quantum bug
as in a bug that, when observed, can rather continue to exist, or never happen again
I implemented a swap interface
I just need to test it
(and also put in a pf handler)
Right now, it just swaps stuff into some memory buffer
my current test code is simple, I still need to test it more thorughly
OBOS_ALIGN(0x1000) static char buf[0x1000];
buf[3] = 0xde;
buf[2] = 0xad;
buf[1] = 0xbe;
buf[0] = 0xef;
page_node what = {.addr = (uintptr_t)&buf};
page_node* page = RB_FIND(page_node_tree, &Mm_KernelContext->pageNodeTree, &what);
Mm_PageOutPage(Mm_SwapProvider, page);
// 'buf' will pf on any accesses between these two calls
Mm_PageInPage(Mm_SwapProvider, page);```
After adding some code for handling page faults for swapped-pages, I can page out pages, then on access, I can page them in
I just thought of an optimization for this function

for each page-fault that swapped a page in, that address will be added to some linked list
because it was accessed
then instead of looping over every single page of a context
I only have to loop over those pages in the list, and the pages in the working-set
the core of the vmm is almost done
All I'd need after this is a virtual memory allocator
and maybe some optimizations here and there
then I'm working on the driver interface I think
I mean you could also sort that linked list then based on access time. So the ones that haven't been accessed yet are all the way at the start of the list
pages are stored in an rb-tree
not a linked list
I mean this
oh
but all those pages will be accessed
because the page-fault for swapping a page in only happens when that page is accessed
Yes, but you can just make it so you move an accessed page to the end
Which would sort based on access time
There's probably a smarter solution tho xD
I mean that could be a good idea
or even better, just age the page right there
and have no list
actually nvm
wait actually
hmm
I'll think about it
I mean yeah, you could do the simplest thing and just store into a vector, with a simple push_back...
altho you'd probably want a paged vector, so you don't need to reallocate the entire memory for it 
I figured out what I'll do
ditch the timer that will call the function that puts pages into the working-set
and instead, call the function on page fault (for swapping pages in)
That's probably simpler, if it's more efficient tho 
it is probably more efficient
Just underthink everything 
How so?
because the (default) size of the working-set isn't necessarily small, so once a process' working set reaches max size, the vmm will be searching through the entire working-set on each page fault
the working-set max size by default is 4 mib
except, once I make the vma, the working-set max size will depend on be based on the size of allocated memory blocks
Hmm
to decrease the overhead, I could just not check the working-set if pages were accessed
and instead, queue up a couple pages in the list, then after the amount of pages in that list hits a certain amount, the vmm checks for pages to put into the working-set
and if the working-set is full then I just page-out rarely accessed pages from it
but then to do that (in a way that doesn't cause more page faults), I'd need to age the pages in the working-set
beating the entire purpose of this
note: this wouldn't happen if the program doesn't use much memory
anyone have any ideas
I'm kind of stuck
for this
yesterday I learnt that page replacement algorithms are hard to get right
I could just do it the lazy way and slow down the system a lot
but I don't want to slow down the system a lot
so I need to overthink a solution
a timer to carry out paging bookkeeping is quiet normal
I think I'm going to add a stack trace to my panic after school
Nvm that's too boring
I'll do it later
I feel like making a gdb stub though
I might do it after VMM
So I can like connect to the kernel and view kernel objects better
monitor page_node 0x0
could be a monitor command
for dumping the page node for address zero
or
monitor dump_thread 1
for viewing the TIB for the thread with the id 1
But, if I do the working-set right, pages won't be swapped often
I could also do this
and check the working-set with it
I think that's what I'll do
The question is, what is this amount?
I could just make it some small number
like 5
or 30
or I could try to figure out a good number based off the count of pages not in the working-set, but in the context
like some formula
I'll put that as a TODO
Also do note that the kernel will likely triple fault as soon as I get this code running
because crucial kernel memory, such as ISR stubs and the PF handler will be paged out
I remember some kernels do linker tricks to throw up a bunch of addresses that should never be paged out
or I could just use a section
So today I got basically nothing done because I got distracted talking to my friends
but tomorrow I'll get something done
Getting the kernel paged (properly) is proving to be a boring task of adding macros that put a function/variable into some special linker section that the MM checks during init, and doesn't add to the context
As for any dynamically allocated variables
I need to deal with those properly
Anyway, I'll continue work on this later
This is so annoying
I need to find every single memory access
and tell the vmm to ignore it
by adding it to some section
except a lot of variables are dynamically allocated
like context objects
so I need to somehow keep the vmm from knowing about those on allocation
@main girder You made MINTIA's kernel pageable, how did you deal with this problem
I am confused by what you're talking about
I hope that the fire is out
You know how mintia could page out the kernel pages
how would it deal with dynamically allocated vmm structs in the kernel
oh wait
nvm
u could read the code yk
doesnt have this part yet
ok
ok I thought of a solution that should be trivial
after some reading
I'll just say all allocations made by the "vmm allocator" are in the "non-paged pool"
well let's just say my allocators are objects for reasons I don't remember
so I can just make it not tell the vmm about any memory allocations there
thus essentially making it the non-paged pool
might be a bit hacky
// Swap out the entire kernel lol.
page_node *i = nullptr;
RB_FOREACH(i, page_node_tree, &Mm_KernelContext->pageNodeTree)
Mm_PageOutPage(Mm_SwapProvider, i);```
feel like that's a bad idea
but I'll compile and watch as the kernel burns
wtf
it doesn't crash
at the same time it doesn't run
but it doesn't crash either
well that's because it constantly page faults
because nothing is mapped
nvm
why is every page mapped
but the one that needs to exist for the page fault handler to work
wtf
That sounds like fun
Now that I'm done doing nothing for no apparent reason (adhd moment I guess)
I can continue debugging this god-foresaken bug
last day of school for me before summer break
so I got like 2 months to work on OBOS
You're lucky. I don't get my 2 month break from school until the end of November.
Where I live, we don't really get a winter, so there is just a really hot and wet time of year, and a slightly cooler dry time of year.
Also, have you ever thought that you're the one that is upside down
so wait does that mean you've never built a snowman
no
you are
Ive never seen snow in person
*this is a joke btw, I'm not actually serious
oof
just go a bit south to antartica
can't possibly take that long
after fixing this
I now crash on a page fault on an address that seems like it should've been paged in
For unknown reasons as of now, it's paged out, but it says it's paged in
despite being unpresent
The problem was another CPU tried to access the page while it's being paged out.
@real pecan The Hyper bootloader is too fast
(for my own good)
the kernel triple faults, and I don't even know that it did until I realize a second later that's what happened
Lol
I can now successfully* page out the kernel
*it triple faults right after all that can be paged out is paged out
I could've sworn I'd made the idt invisible to the MM
guess I didn't
After fixing a couple bugs
I think it works
and by that I mean it doesn't crash
for some reason the counter for physical pages used is negative
The kernel is so good, it's adding memory to the system instead of taking it
After fixing another bug
It boots
[ LOG ] Arch_KernelMainBootstrap: Done early boot. Boot required -188 KiB of memory to finish.

Anyway, I couldn't be bothered to fix this bug
OBOS hangs on vmm init on real hw
Nvm it also happens on qemu
Ok I fixed it on qemu
After testing on real hw
It panics recursively
And on qemu with more than one core, it does the same
Except it never says the panic reason
Do you have zram or is it to disk
well it just has some memory buffer for now
that acts as swap
until I get a disk driver
My kernel seems to be cursed again
It only breaks in mysterious ways when unmasking IRQs after paging out everything
I suspect it has something to do with the scheduler not liking being unmapped
actually no
there's probably some sort of race condition
in the VMM
causing all to shit it self
Same here
Ever thought of memory compression? :>
I think someone should make some qubit compression algorithm for regular bits :>
Like encode 2 bits in a single bit
(only with SMP though)
I'll continue debugging tomorrow
Without SMP, the kernel works just fine
no crashes
no nothing
probably some sort of sync bug
except there are like three locks protecting the VMM from paging a page in after a page fault
the context lock
the per-page lock
the swap lock
I just thought of a maybe good idea to do TLB shootdowns
If I do them lazily
i.e., on page fault, it does a bunch of checks
and if it deduces the page mapping was changed on a different processor (with the same cr3), it will invlpg that page
and return as if nothing happened
which basically does a tlb shootdown, without a single IPI sent
if you think about it you will realize why some IPIs are still necessary
and also
if a page fault happens on an unmapped page, it might (will?) accidentally deduce that the page as one to invalidate in the TLB, when actually it should: a) be swapped in b) crash c) signal whatever thread faulted (TODO)
I guess a workaround for that is to check the page in the context before assuming to invaliate the page in the TLB
but except, pages invisible to the VMM won't be counted
I could just add them back into the context, but give them some special flag that makes them invisible to the page replacement algorithm/the swap out page function
so then I could do that
but then, is it really worth it for a TLB shootdown
I'll think more about this when I wake up
I'm going to sleep rn
but anyway, without SMP, the kernel can be paged out without issues
no crashes
If for some reason someone wanted to try OBOS on qemu (idk why)
I got a uniprocessor (aka doesn't crash with the VMM) build here
and for good mesure, I'll throw in a release build as well
Why is it 37MB?
Because I'm bad at making some disk image containing the btldr for uefi
do like me and generate a 2 GiB file O_O
OBOS uses ✨ state of the art technology ✨ to do ✨ absolutely nothing ✨
So like
uint32_t StateOfTheArtPRNG() {
static uint32_t val = 0;
return val++;
}
Nono, more like
i think being humble is a good thing
some people claim in their readmes that their kernel is a great and modern advanced kernel and should be used by everyone
so a humble opener like this is always a welcome change and makes me feel more confident that the kernel will be interesting
I have tracked down the stack corruption to a recursive page fault handler
I use ISTs for the pf interrupt
so they can't really nest
(workarounds are welcome)
and a page fault handler page faulted
(that, and also there's the chance that it just hangs locking the context)
I did also just end up implementing TLB shootdown with an IPI
Basically it used the wrong variant of a function
you really shouldn't
if you're running into stack overflows it's going to devolve into a GPF or DF, I think
but you really shouldn't need to
I think I'll need to because if a (kernel) stack is swapped out, then when it page faults, it'll just triple fault because there is no mapped stack to go to
I could just not page out kernel stacks...
I'll just not put an IST and see what happens
Nothing happened
ok wtf
rsp is set to some mmio address, causing a gpf because the cpu is kinda confused
probably underflowed
Yeah do that
That is indeed the case
maybe I shouldn't be putting my MMIO right below the zero page
I've almost fixed my triple faults
nvm
ok I think I did now
40 pages in the working-set at the end of boot
and if all goes well, as the kernel idles, it should go down
nope
oh wait that's because nothing ever faults when the kernel idles
and this only does its stuff when a new page is referenced
The majority of the VMM is complete
What's left is:
- Virtual memory allocator
- Optimizations?
I've pushed the changes
It can be done
Just not while the thread is running
which is where I messed up
Nice work
because these always only happen on SMP, I might as well slap a giant kernel lock on everything
As soon as I make the idle task sleep and do nothing (with irqs disabled)
nothing crashes
nvm
the kernel is forever cursed
"When I wrote this code, God and I knew what it did"
"Now, only God knows"
0$ to anyone who can fix the kernel as a whole
inb4 a pr comes that deletes the entire code base
Will there be a new rewrite 
(probably) no
when I say "the kernel"
I mean any kernel I ever make
ok this is just a stack corruption bug probably
hopefully
what if I just port the kernel to linux x86-64
so I can debug the kernel in user space
no way it's that hard
there are barely even any functions that are arch-specific
probably < 100
maybe even < 50 arch-specific functions
and by that I mean functions that act as an abstraction between some thing and arch-agnostic code
like a function to map a function for example
hardest port would be the irq interface
https://github.com/OBOS-dev/obos/blob/7fde10cbce0ba0cc89ee49d9c9d96715c5925d69/src/oboskrnl/irq/irq.c#L28-L29 why is the condition in the message different than the actual if condition
probably changed the if statement
and didn't bother to change the comment
oh wait no
nvm
probably had a brain fart
and accidentally put in the wrong thing for some reason
also if you want newer code go in the vmm branch
ok I fixed the typo
So I'm porting obos to linux
so how that works is it just makes "linux-amd64" a separate arch
then I'll implement a bunch of shit for that to work
and by that I mean abstract away linux syscalls
#include <int.h>
#include <klog.h>
#include <arch/linux-amd64/syscall.h>
OBOS_NORETURN void Arch_KernelEntryBootstrap()
{
int tid = 0;
tid = syscall(186);
// Exit.
syscall(60, 65);
}```
Sneak peak
sneak peak of the linker errors
After defining one function, it's already looking a lot better
Good luck
It shouldn't be too hard to get it to link (I hope)
all I need to do is define a couple abstraction functions
the irq interface is a whole different beast though
I'm interested to see how you get an IRQ interface on linux userland
so am I (it will be an abomination of signals probably)
I believe linux itself has a userland port, which could contain some useful information
don't feel like reading linux code
Linux code is mostly readable
I think I'll make other "CPUs" just other threads in the process
and the cpu IDs will just be the TID of the thread
so to halt all other CPUs, I can just send SIGKILL to each of them
Best part about this is I can mostly copy+paste code from the x86-64 implementation (for the thread context switching, at least)
I just did a very cursed way to mimic an iretq in the context switch code
add rsp, 0x10 ; Skip the saved DS and CR3
mov rax, [rsp+0x98] ; RIP
mov rdx, [rsp+0xB0] ; RSP
mov [rdx-8], rax
popaq
add rsp, 0x18
add rsp, 0x10
popfq
mov [rsp], rsp
sub rsp, 8
ret```
It first pushes the return address on the thread's stack
then it continues to restore gprs
then it skips over rip and cs
it pops eflags
pops rsp
then does a return
to return into the thread's rip
it definitely will break eventually
but this is meant as a way to procrastinate debugging the kernel last ditch effort to debug the kernel if I can't tell what went wrong through qemu
I think I'm going to treat physical pages as such:
they're the fd of some tmp file the size of the allocation
Then virtual pages are just that FD mmap'ed
actually
maybe that's a bad idea
popaq 
%macro popaq 0
pop rbp
add rsp, 8
pop r15
pop r14
pop r13
pop r12
pop r11
pop r10
pop r9
pop r8
pop rdi
pop rsi
add rsp, 8
pop rbx
pop rdx
pop rcx
pop rax
%endmacro```
meh it'll be fine
freeing a physical page will be closing that fd
i hate assembler macros so much
that's tough
yeah i know
sorry i forgot to elaborate
basically in my head i like to write assembly because i gives me control over the code size etc
but i feel like macros obscure that somewhat
especially with macros like popaq which makes it sound like a mnemonic, but actually expands to like 50 bytes of code lmao
Well that's fair
Oh god O_O
That's a lot of pops O_O
Ok how do I implement OBOSS_GetPagePhysicalAddress
I couldn't find a syscall which queries page info
so I'll rather have to:
- cache this info
- search /proc/self/maps
- give up because this is pointless
third option is quite viable
well how do you represent physical pages
file descriptors
(this is a linux port)
I think I'll do this some other day week month year
Huh
it was a port of OBOS to linux
and I was going to treat physical pages as a file descriptor
now that I got rid of that cursed mess, I can continue debugging the other cursed mess
something tells me that I forget to zero memory
wut
upon randomizing some memory backing file and throwing it at qemu
it doesn't crash at all
Uninitialized memory usage?
which is what I thought
so I randomized a file
told qemu to use it as a backing
then it just stopped crashing entirely
Yeah maybe its the other way around tho
You're trying to use bogus memory as initialized struct
well the bug is something going to the most randomest parts of memory
I'm going to map out what it cannot be here so I don't forget:
- Bug with the swap thing, as kernel stacks are not swapped out as of now
something tells me a bug with the context switch functions
nope
oh wait I tested that wrong
shit
uintptr_t rbp, ignored1, r8, r9, r10, r11, r12, r13, r14, r15,
rdi, rsi, ignored2, rbx, rdx, rcx, rax;```
is the interrupt frame
pop rbp
add rsp, 8
pop r15
pop r14
pop r13
pop r12
pop r11
pop r10
pop r9
pop r8```
is the first part of the code to restore those registers
ok I think I fixed that bug
but anyway, I now get this panic:
Kernel Panic on CPU 2 in thread 6, owned by process 1. Reason: OBOS_PANIC_FATAL_ERROR. Information on the crash is below:
Page in working-set is swapped out.```
I think that might've just been uninitialized memory
I think I fixed the bugs
after a bunch of resetting qemu to test the kernel stress testing, there is one occasion that causes a KASAN violation

I got a UBSan type mismatch
ok it's not an allocator bug
it's instead the scheduler going crazy
I just pushed some fixes and some of the virtual memory allocator
I now need to think of a way to allocate virtual pages through the rb-tree
I could just use the way I've used for the previous 3 kernels
and improve it later*
*that means never
@white mulch You have been summoned
so what was the problem or whatever
page faults on invalid return addresses (not on every boot)
and also a corrupted interrupt frame after the pf
actually not this
actually no
the interrupt frame is pretty fucked
I sense concurrency issues with the tlb shootdown IPI (which is an NMI because I was too lazy to allocate an IRQ object for it)
It's guarded by a single lock
and only used in one place, the unmap function
wait those two bugs are probably related
the stack pointers for all 4 CPUs are different
(at least, in the interrupt handler)
ok now the qemu log is trolling me
the kernel sends an NMI to each CPU on panic telling the CPU to just stop
and the last recorded interrupt is the page fault
This page fault is not supposed to be panicking
it's supposed to be paging a page in
but for some reason it doesn't
weirdly, two other cores fault at the same time as that core
so it races to crash first
the other two page faults are weird as their interrupt frame struct is corrupted
in fact, I don't even think they're supposed to be in the page fault handler in the first place
the interrupt frame suspiciously looks like some function's stack frame
Looking at gdb's stack trace, the function that called the pf handler is "unknown"
then looking at the stack frame of these pf handlers
it's corrupted
so now I gotta debug stack corruption
oh no it seems even worse than that
nvm
I have SSP on
nothing reported
UBSan
nothing reported
KASAN
nothing reported
why must this be so cursed 
disabling KASAN causes the ssp to report something
weirdly, even the stack of the stack check fail function is getting corrupted
it must be spooky actions from a distance
(another CPU corrupting the stack)
but what might cause such a thing
The swap
is the only thing that could cause such a bug
because nothing is peeking at other CPUs' stacks
but stacks cannot be swapped out
which can only mean two things:
the swap is writing the wrong physical page
the pmm gave the same address twice
the stack corruption happens while another CPU is paging a page out
Looks like your curse continues
it never dies out...
You rewrite constantly to avoid it, maybe if you just deal with the problem and it might finally stop
that's what I'll do this rewrite
I feel like one day I'll start a rewrite
then rewrite the next day
I'm happy I rewrote this time though
because the other kernel was kinda shite
it became what it was meaning to replace
anyway, tomorrow I should be able to debug further
I currently suspect the swap does something stupid
and changes the mapping for the wrong page
wait
I rebooted OBOS
right
it crashed
and some other core happened to be in the page out function
Now that it's tomorrow
I can continue debugging this shit
oh shit
I found the bug
*a bug
uintptr_t Arch_GetCPUTempStack()
{
return (uintptr_t)CoreS_GetCPULocalPtr()->arch_specific.ist_stack;
}```
call Arch_GetCPUTempStack
pop rsi
pop rdi
lea rsp, [rax+0x10000]```
ist_stack is already offset by 0x10000 bytes, the stack's size, to be put at the top of the stack
but then, when switching to it, it adds another 0x10000 bytes, going to random shit
That's iirc
I'll check the part where that member is initialized
ok that wasn't a bug
maybe some stack overflows?
and since the stacks are allocated contiguously, some CPU wreaks havoc on some other CPU's stack
ok I think I finally found the culprit
The stacks are being paged out
nvm

I thought that because there was a page fault on rsp
but then the error code indicated that it was on execution of a present page
I think I should rewrite the VMM
These bugs did not exist before the VMM
Something is fucked up in the VMM, and it's not showing itself
but before I do that, I'm going to quadruple the size of the kernel main thread's stack
and double the size of temporary stacks
and make the size of idle thread stacks a lot bigger
Maybe the threads just have a stack overflow
because the size of the idle thread stack is only 0x4000 bytes
and the temp stack is 0x10000 bytes
fuck thids
fuck this
I hate this
Instead of rewriting, I might as well go to the only kernel I made that wasn't that shit
actually no
The vmm is going to cease to exist
and I'm going to rewrite it completely
Which
Wasn't it also unstable that you had to rewrite it
no, it was only because I didn't like how I wrote some stuff
Ah
like the vmm was doo doo
in terms of design
and the vfs
Amazing
The kernel can now boot without it shitting itself

Did you just comment out the vmm
does this explain anything
Now, I rewrite the VMM
The kernel is only down 1k loc from that
gasp
It's been more than a month since I made the vmm branch and I still don't have a vmm smh
also i was trying for like 4 months to learn how to implement an async IO system before i decided to just implement a regular sync one
I've made the page and context structures
the context struct is like the exact same
but the page struct is different
I think I'll now define some functions to get info about a page from a page table
Ok now that I've done that
I guess I'll define a function to change page mappings within a page table
I did that
so now I can go on to initializing the kernel's context
Before I get on with that, I'm going to define the pages that the VMM is not allowed to page out, so I don't mess that up:
- Pages in the
.no.mm.*sections - Pages that correspond to a kernel stack, so idle thread stacks and cpu temporary stacks
- Pages representing cpu-local structures.
- Maybe the framebuffer so that it is possible to log stuff within the vmm.
If anyone thinks I might be missing something important
tell me
After having to reinstall debian after accidentally deleting my system through sudo apt remove libssl3
I can finally make the function to initialize the kernel's context
couldnt you like download the deb/get it from cache and dpkg -i it
It removed all packages depending on it
oh lol
after many procrastination and a doctor's appointement
I am half-done that
What's next is probably emulation of a swap
and for that I will just use a memory buffer
on a side note, kde plasma is quite nice after switching from gnome
only thing I'd want is making the taskbar be mirrored on both monitors
I can have one per monitor
but I need to manually sync them
but anyway...
I think this time, I'll make my swap backend thingy easier to recover from in case of an error
Before, the swap in/out function had to undo any changes if the swap backend failed
which was quite inconvinient, and prone to memory leaks
if theres an error the only result should be that the pages stay in memory
yeah yeah I know
but if the backend thing failed, it would need to undo stuff
which meant undoing the
I'm blanking
which meant remapping the page
why on earth
would it mean that
you seem to have a bad separation of responsibilities!
I'm having trouble explaining this lol
if you care enough there's the old function
it first unmapped the page
then it asked the thing that throws pages into the swap to throw that physical page into swap
and if that failed, it would have to map the page again
dumb
I know
re map it at fault time
keep it on a list of dirty pages pending page-out
until then
same place you should always get pages from to write out to swap
filling the list of dirty pages is done by someone else who unmaps pages and places them on that list
"working set trimmer" in NT parlance
so I basically just queue pages for swap out if it failed
or do I just always queue the swap out
sorry me is a bit dumb in vmm stuff
in NT (and VMS) the working set trimmer removes pages from processes
in rough FIFO order of when they were faulted in
by iterating over the working set list
this unmaps the page and decrements the refcount in its pfn element
when its refcount hits zero, and it was modified since last time it was written out (or has never been written out), it goes on the modified page list
when the modified page list's length goes above a certain threshold, the event waited on by the modified page writer thread is signaled
he builds clusters of pages from the modified page list and writes them to the pagefile
but this doesnt remove the page frame from memory
it just sets it un-modified
so it goes on the standby list instead
which is where 0 refcount pages go when they were non-modified when their refcount hit 0
standby list pages can be immediately reclaimed upon page frame allocation after the free page list runs dry
in any period between the page being trimmed and being reclaimed from the standby list, the process can fault it back into its working set
which increments its refcount and takes it off the list
after being reclaimed from the standby list the process must read it back from the pagefile at that point
if it faults on the page again
if it faults the page back in and writes to it, then next time its trimmed, it goes on the modified list again
since its pagefile backing is no longer valid as the copy in RAM has been changed by the process writing to it
the page in the pagefile is also freed by clearing a bit in a bitmap (since that page on disk no longer contains meaningful data)
nvm
To prevent dumb bugs from having I need to do something like this
like the disk driver yielding while it swaps a page in
but then the scheduler isn't paged in
so it page faults
then it just deadlocks
or if it's interrupt-based, that might cause the same effect
Is there a specific reason for why allow the scheduler to be paged out?
Now i‘m curious 
Because of the page replacement algorithm, this basically won't matter
because the scheduler code is always being referenced
It's quite nice
No
It's broken
To do that
Memory manager depends on the scheduler
That‘s nothing unusual in this thread 
i did too until half an hour ago
I've slautered more sheep in this world than in any other world I've had
well idk actually
but it feels like it
oh and I'm playing 1.12.2
Why
there are sheep everywhere
because it's objectively better
vanilla?
I think I've made it so the scheduler cannot get paged out
idk if I got every single function/object, but I did
Why not make it opt in instead
No
It's broken
To do that
Memory manager depends on the scheduler
Or what do you mean
Nvm
I guess you mean make it that the functions can opt in to get paged out?
Yeah that sounds right
They opt-out
not opt-in
Basically anything can get paged out unless the mm is explicitly told not to
My suggestion is that it should be the complete opposite
Wish there was a way to set an entire compiler unit's text section
You can with a global asm(section X) statement I think?
no the generated assembly switches sections if you mix variables and functions at global scope
why
if most of the kernel can be paged out
then why would I want to opt-in
I mean tbf that would workaround a lot of bugs related to strings being in .rodata
specifically format strings for a panic within a pf handler
I have implemented the swap in/out functions
Just pushed that code along with the VMM initialization functions
Time to implement:
- The page replacement algorithm.
- The page fault handler.
should we get hyena involved to do a code review?
no(t yet)
lol
yes
Isn't my test code for swapping in/out pages so good (/s):
OBOS_ALIGNAS(0x1000) static uint8_t buf[0x1000];
page what = {.addr=(uintptr_t)buf};
page* page = RB_FIND(page_tree, &Mm_KernelContext.pages, &what);
buf[1] = 0xad;
Mm_SwapOut(page);
Mm_SwapIn(page);
buf[0] = 0xde;
OBOS_ASSERT(buf[1] == 0xad);```
OBOS_ALIGNAS(0x1000) static uint8_t buf[0x2000];
page what = {.addr=(uintptr_t)buf};
page* p = RB_FIND(page_tree, &Mm_KernelContext.pages, &what);
what.addr += 0x1000;
page* p2 = RB_FIND(page_tree, &Mm_KernelContext.pages, &what);;
buf[1] = 0xad;
Mm_SwapOut(p);
buf[0x1001] = 0xef;
Mm_SwapOut(p2);
Mm_SwapIn(p);
buf[0] = 0xde;
Mm_SwapIn(p2);
OBOS_ASSERT(buf[1] == 0xad);
buf[0x1000] = 0xbe;```
now it tests two simple cases
doesn't crash (yet)
which is why I will throw this code into multiple threads
and try swapping a lot of pages
I'll just make the buffer 0x10000 bytes, and have 4 threads which all page in/out a 0x4000-sized portion of the buffer
then of course there will be random (enough) data written to the buffer
no way obos is stable now
no it's because this is a rewrite of the vmm
once I swap out the kernel
it will probably crash
so you have yet to plant a subtle bug in it?
do u have it disabled now?
no
nice
I am currently writing the test case for swapping in/out pages multithreaded
I've written it
Now time to run it
UBSan Violation invalid value load in file /home/oberrow/Code/obos/src/oboskrnl/irq/timer.c at line 92:16

lol
line in question:
for(timer* t = timer_list.head; t; )```
(timer_list is a global)
oh wait I can't read
while (!can_run_dispatcher);
now it accesses nullptr
After "fixing" that
it gets stuck in an infinite panic loop
Now Mm_SwapProvider gets corrupted to 0xdededededededede
Heap bug?
It's a pointer
and this allocator has been extensively (uACPI) tested in the previous kernel
The bug is caused by the vmm test
Lol
Certified allocator
lol
for (uintptr_t addr = what.addr; addr < ((uintptr_t)buf + 0x4000); addr += 0x1000)
if the range of the buffer is 0x4000 bytes
then this should only go from buf to buf+0x4000
right?
if addr is 0x1000 aligned then the last iteration that is entered would be buf + 0x3000 yeah
well it is
memset((void*)addr, 0xea, 0x1000);
that sets every byte within that page to 0xea
oops
found the bug
buf was offset by 0x4000 on entry to the thread
OBOS might be a bit dead over the next couple days as I'm trying to port some xbox 360 emulator to linux
so far it's not going well
it doesn't even compile
it uses c extensions like the _s versions of functions
gcc is also being a bit dumb
isnan is undefined
despite cmath being included
nvm there seems to already be a port that compiles on linux
I'll check though
Why are you doing that
I want to play minecraft xbox 360 edition
but I don't have neither an xbox 360 nor an mc xbox 360 edition disk
seems rather illegal
ah okay cool
Why
nostalgia and stuff
Also steamdeck can certainly run an xbox360 emulator so one probably exists already for Linux
I can run one
but I get 💩 performance
like it's bad
even on the most optimized wine executable I could find
(wine-ge-8-26-default)
although luckily for me there is already a port (albeit it's very incomplete according to the devs)
I just need to build it
qemu? :^)
I don't think the xbox 360 OS exists anywhere
on the web
If it did I'd know what to do (not?)
I would just need to run qemu-system-ppc with the os somehow
and the cdrom would be the iso that I extracted from my CD
also it might be illegal to use the OS on anything but an xbox 360
also qemu probably doesn't have support for whatever devices the kernel expects
apparently the xbox 360 os is a modified version of NT for powerpc
Oh my
while linking
the linker crashed because of OOM
For my own sanity, I am going to take a break from OSDev for a week
or two
So uhh see y'all in a week
So I'm back to OSDev
welcome back
Now time to go back to debugging my thingy
My timer interface seems to be fucking stuff up
without it enabled all works fine
however, with it enabled, stuff start crashing
I currently suspect that the timer is simply going too fast at 1khz
hmm the timer IRQ has the same IRQL as dispatch
maybe that's a problem
that's a major problem
the timer should
- have a higher IRQL than the dispatcher's
- not interfere in any way with the dispatcher's operations
well my timer irq now has an irql of 2, whilst IRQL_DISPATCH is now 4
of course the problem still exists
I'll debug it later
I gotta do something now
it should be higher not lower
ideally one of the highest
thats what NT does
Not that i know anything about this but shouldn’t generally there be no interference in form of locks etc between irqls