#OBOS (not vibecoded)

1 messages · Page 10 of 1

flint idol
#

You guys

inland radish
#

Yes

flint idol
#

I assumed you wanted both of us to answer

inland radish
#

I was asking about both you and Infy

#

The latter responded to a different question I believe

real pecan
#

Fell off a merry go round type of thing at a high speed

#

I was 11

inland radish
#

I see

#

Wish you a speedy recovery @flint idol

flint idol
#

Ty

real pecan
#

Ye

flint idol
#

I misinterpreted this as "and are you infy"

#

Instead of "and you, infy?"

vernal chasm
#

Ah yes

#

I removed cast from static_cast, so now it's just static_

#

:>

flint idol
#

I implemented the part of the vmm that ages pages (assuming I understood the algorithm properly)

flint idol
#

I need to implement a virutal allocator nooo

flint idol
#

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

real pecan
flint idol
#

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

flint idol
real pecan
#

Lol

flint idol
#

look at line 18

real pecan
#

Yes

flint idol
#

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

real pecan
flint idol
#

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)

real pecan
#

Im going to the airport

flint idol
#

oh

real pecan
#

So woke up early it is

vernal chasm
flint idol
vernal chasm
#

oof

#

Don't

#

When you go to sleep, make yourself half brainded, you'll fall asleep much faster

flint idol
#

I've found where I jinxed my os

inland radish
flint idol
#

in the replied message

inland radish
#

ah lol

flint idol
#

from that day on, there were allocator bugs

#

and stuff

#

weird pf bugs

flint idol
#

I changed my panic screen

vernal chasm
flint idol
#

yes

#

this is definitely NOT @ornate ginkgo's panic ascii art

vernal chasm
flint idol
#

that's the gif I was looking for

inland radish
#

meanwhile mine

flint idol
#

🥱

main girder
#

wow your hal is a separate binary? thats soooo 2021

#

i realized its pointless larp to do that

flint idol
#

You guys have HALs?

fluid crown
#

what is HAL?

flint idol
#

Hardware Abstraction Layer

#

I just have a separate arch directory for each platform

#

that does some stuff

main girder
#

ohh

inland radish
main girder
#

you are conflating architecture and platform

inland radish
#

but it probably won't be pointless on ARM platforms

main girder
#

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

inland radish
flint idol
#

would an ioapic "driver" be in the HAL?

inland radish
#

like device trees might be in different places and so on

inland radish
flint idol
#

or lapic code

inland radish
#

actually no maybe not

#

the LAPIC is part of the CPU

weary hound
main girder
inland radish
#

not so sure of the IOAPIC

main girder
#

this is physically the case

inland radish
#

well technically there's one LAPIC for each core!

#

and they're mapped to the same address IIRC

#

of 0xFEE00000

fluid crown
#

still some terms that I don't understand well, but that's okay, I don't need them

flint idol
#

lol

inland radish
#

so I'd say the action that I performed wasn't pointless

inland radish
#

more info than just Test panic.

flint idol
#

well it was a test panic

#

to show off the ascii art

inland radish
#

Yeah, the ASCII art is cool but not yours

flint idol
#

anyway, I do need a stack trace soon

flint idol
#

he found it on some website

#

idk how to crash obos to make it provide a useful panic

inland radish
#

oh ok

flint idol
#

because it's just so stable /j

inland radish
flint idol
#

I know

#

he'll see the ping eventually

#

just I don't wanna give him a push notification

main girder
#

mine darkens the screen.

flint idol
#

after commenting out random lines, I get a meaningful panic

inland radish
flint idol
#

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

inland radish
#

Pretty cool

flint idol
#

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

ashen goblet
#

i think that's a bug

vernal chasm
flint idol
#

nvm that seemed to be a quantum bug

#

as in a bug that, when observed, can rather continue to exist, or never happen again

ornate ginkgo
#

🫨

#

I will now verify you are licensing the ascii art properly meme

flint idol
#

I implemented a swap interface

#

I just need to test it

#

(and also put in a pf handler)

flint idol
#

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);```
flint idol
#

After adding some code for handling page faults for swapped-pages, I can page out pages, then on access, I can page them in

flint idol
flint idol
#

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

vernal chasm
#

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

flint idol
#

not a linked list

flint idol
#

oh

flint idol
#

because the page-fault for swapping a page in only happens when that page is accessed

vernal chasm
#

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

flint idol
flint idol
#

and have no list

#

actually nvm

#

wait actually

#

hmm

#

I'll think about it

vernal chasm
#

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 kekw

flint idol
#

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)

vernal chasm
#

That's probably simpler, if it's more efficient tho kekw

flint idol
#

it is probably more efficient

vernal chasm
#

I'd say that would depend...

#

But as some people say, simpler is sometimes better

flint idol
#

my brain isn't braining anymore

#

I'm overthinking this

vernal chasm
#

Just underthink everything smart

flint idol
#

there is more overhead in the page fault handler later in the program

#

that's a con

flint idol
#

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

vernal chasm
#

Hmm

flint idol
#

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

flint idol
flint idol
#

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

devout niche
#

a timer to carry out paging bookkeeping is quiet normal

flint idol
#

I know

#

But I want to optimize it

#

Anyway I got school so I'll be back

flint idol
#

I think I'm going to add a stack trace to my panic after school

flint idol
#

I'll do it later

#

I feel like making a gdb stub though

#

I might do it after VMM

flint idol
#

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

flint idol
flint idol
#

and check the working-set with it

#

I think that's what I'll do

flint idol
#

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

flint idol
#

So today I got basically nothing done because I got distracted talking to my friends

#

but tomorrow I'll get something done

flint idol
#

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

flint idol
#

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

main girder
flint idol
#

I'll explain on a bit

#

*in

#

Currently exploring a fire

empty kernel
flint idol
#

It's out

#

One injured

flint idol
#

how would it deal with dynamically allocated vmm structs in the kernel

#

oh wait

#

nvm

main girder
#

u could read the code yk

flint idol
#

does new mintia exist

#

yet

main girder
#

doesnt have this part yet

flint idol
#

ok

main girder
#

but basically theres a paged pool and a nonpaged pool

#

thats it

flint idol
#

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"

main girder
#

i just give a flag

#

to the heap allocator

#

about which it should go in

#

.

flint idol
#

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

empty kernel
#

That sounds like fun

flint idol
#

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

empty kernel
#

You're lucky. I don't get my 2 month break from school until the end of November.

flint idol
#

not my fault you're upside down

#

and summer is in the wrong months

empty kernel
#

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.

flint idol
#

oof

#

just move to antartica

empty kernel
#

Also, have you ever thought that you're the one that is upside down

flint idol
#

so wait does that mean you've never built a snowman

empty kernel
#

Ive never seen snow in person

flint idol
#

*this is a joke btw, I'm not actually serious

flint idol
#

just go a bit south to antartica

#

can't possibly take that long

flint idol
#

I now crash on a page fault on an address that seems like it should've been paged in

flint idol
#

despite being unpresent

flint idol
flint idol
#

@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

real pecan
#

Lol

flint idol
#

Just noticed that the kernel accidentally tries to page out MMIO pages

#

oops

flint idol
#

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

flint idol
#

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

flint idol
#

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

flint idol
lean glen
#

Do you have zram or is it to disk

flint idol
#

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

ashen goblet
vernal chasm
vernal chasm
#

I think someone should make some qubit compression algorithm for regular bits :>

#

Like encode 2 bits in a single bit

flint idol
#

It seems as if I am back in my curse

flint idol
#

I'll continue debugging tomorrow

flint idol
#

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

flint idol
#

My bugs seem to be as a result of me having no TLB shootdowns

flint idol
#

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

main girder
#

if you think about it you will realize why some IPIs are still necessary

flint idol
#

oh wait

#

if a caching bit is changed, that won't ever fault really

main girder
#

and also

flint idol
#

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

flint idol
#

I got a uniprocessor (aka doesn't crash with the VMM) build here

empty kernel
#

Why is it 37MB?

ornate ginkgo
#

Lol

#

Good question

flint idol
vernal chasm
flint idol
#

OBOS uses ✨ state of the art technology ✨ to do ✨ absolutely nothing ✨

vernal chasm
flint idol
#

More like

vernal chasm
flint idol
#

Should I make the readme say this:

#

there's the diff

devout niche
#

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

flint idol
#

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

flint idol
inland radish
#

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

flint idol
#

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

flint idol
#

ok wtf

#

rsp is set to some mmio address, causing a gpf because the cpu is kinda confused

#

probably underflowed

lean glen
flint idol
#

maybe I shouldn't be putting my MMIO right below the zero page

flint idol
#

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

main girder
#

Just not while the thread is running

flint idol
#

which is where I messed up

lean glen
#

Nice work

flint idol
#

Just as I thought I got all the bugs

#

others pop up

flint idol
#

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

real pecan
flint idol
#

(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

steep ravine
flint idol
#

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

flint idol
#

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

flint idol
#
#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

#

After defining one function, it's already looking a lot better

empty kernel
flint idol
#

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

empty kernel
#

I'm interested to see how you get an IRQ interface on linux userland

flint idol
#

so am I (it will be an abomination of signals probably)

empty kernel
#

I believe linux itself has a userland port, which could contain some useful information

flint idol
#

don't feel like reading linux code

empty kernel
#

Linux code is mostly readable

empty kernel
#

Ok, some of it is very old style

#

And takes ages to understand what it is doing

flint idol
#

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

steep ravine
#

popaq nah

flint idol
#
%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```
flint idol
#

freeing a physical page will be closing that fd

steep ravine
#

i hate assembler macros so much

flint idol
#

that's tough

steep ravine
#

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

flint idol
#

Ok how do I implement OBOSS_GetPagePhysicalAddress

#

I couldn't find a syscall which queries page info

#

so I'll rather have to:

  1. cache this info
  2. search /proc/self/maps
  3. give up because this is pointless
#

third option is quite viable

lean glen
#

well how do you represent physical pages

flint idol
#

file descriptors

#

(this is a linux port)

#

I think I'll do this some other day week month year

lean glen
#

keep track of them in some sort of table

#

idk

flint idol
#

too late troll

#

I just reverted all the changes

main girder
flint idol
#

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

real pecan
#

Uninitialized memory usage?

flint idol
#

which is what I thought

#

so I randomized a file

#

told qemu to use it as a backing

#

then it just stopped crashing entirely

real pecan
#

Yeah maybe its the other way around tho

#

You're trying to use bogus memory as initialized struct

flint idol
#

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

flint idol
#

I just pushed some fixes and some of the virtual memory allocator

flint idol
#

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

flint idol
#

@white mulch You have been summoned

white mulch
#

so what was the problem or whatever

flint idol
#

page faults on invalid return addresses (not on every boot)

#

and also a corrupted interrupt frame after the pf

flint idol
#

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

flint idol
#

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

flint idol
#

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

flint idol
#

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

flint idol
#

I tried setting the SSP to all to no avail

#

the stack is extremely fucked

flint idol
#

I have SSP on

#

nothing reported

#

UBSan

#

nothing reported

#

KASAN

#

nothing reported

#

why must this be so cursed nooo

#

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

empty kernel
#

Looks like your curse continues

flint idol
#

it never dies out...

empty kernel
#

You rewrite constantly to avoid it, maybe if you just deal with the problem and it might finally stop

flint idol
#

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

flint idol
#

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

flint idol
#

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

flint idol
#

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

flint idol
#

third could boot

#

without shitting itself

real pecan
#

Wasn't it also unstable that you had to rewrite it

flint idol
#

no, it was only because I didn't like how I wrote some stuff

real pecan
#

Ah

flint idol
#

like the vmm was doo doo

#

in terms of design

#

and the vfs

#

Amazing

#

The kernel can now boot without it shitting itself

real pecan
#

Did you just comment out the vmm

flint idol
#

does this explain anything

#

Now, I rewrite the VMM

#

The kernel is only down 1k loc from that

inland radish
#

gasp

flint idol
#

It's been more than a month since I made the vmm branch and I still don't have a vmm smh

inland radish
#

but you had swapping

#

wth happened to that

flint idol
#

swapping.... through some memory buffer

#

so it's fine

inland radish
#

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

flint idol
#

the vmm was very broken

#

and I couldn't be bothered anymore to find out why and where

flint idol
#

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

flint idol
#

I guess I'll define a function to change page mappings within a page table

flint idol
#

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

flint idol
#

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

near linden
flint idol
#

It removed all packages depending on it

near linden
#

oh lol

flint idol
#

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...

flint idol
#

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

main girder
#

if theres an error the only result should be that the pages stay in memory

flint idol
#

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

main girder
#

why on earth

#

would it mean that

#

you seem to have a bad separation of responsibilities!

flint idol
#

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

flint idol
#

I know

main girder
#

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

flint idol
#

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

main girder
#

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)

flint idol
flint idol
#

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

flint idol
ashen goblet
#

Is there a specific reason for why allow the scheduler to be paged out?

flint idol
#

well

#

now that I thought of my reasons

#

they're quite stupid

ashen goblet
#

Now i‘m curious KEKW

flint idol
#

I didn't want to keep thread objects swapped in

#

The scheduler is a hot code path

ashen goblet
#

Yeah that’s what i was thinking

#

Thanks for changing your pfp btw

flint idol
#

because the scheduler code is always being referenced

flint idol
ashen goblet
#

It‘s not very sharp

#

But cute cow

flint idol
#

dat a goat\

#

lol

ashen goblet
#

Oh sht

#

I was 99% sure it‘s a cöw

main girder
#

It's broken

#

To do that

#

Memory manager depends on the scheduler

ashen goblet
flint idol
#

trust me all will work out eventually

#

not rn though I'm playing mc

ashen goblet
#

i did too until half an hour ago

flint idol
#

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

ashen goblet
#

Why

flint idol
#

there are sheep everywhere

flint idol
ashen goblet
#

vanilla?

flint idol
#

yes

#

well I have optifine but whatever

ashen goblet
#

Played the old versions too much

#

Became boring

flint idol
#

I have killed 50 sheep

#

and no other mob so far in this world

flint idol
#

I think I've made it so the scheduler cannot get paged out

#

idk if I got every single function/object, but I did

real pecan
#

Why not make it opt in instead

inland radish
#

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

flint idol
#

not opt-in

#

Basically anything can get paged out unless the mm is explicitly told not to

inland radish
#

Wish there was a way to set an entire compiler unit's text section

real pecan
weary hound
#

no the generated assembly switches sections if you mix variables and functions at global scope

flint idol
#

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

flint idol
#

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.
real pecan
#

should we get hyena involved to do a code review?

flint idol
#

no(t yet)

real pecan
#

lol

flint idol
#

you wouldn't want someone reviewing your half-done untested code

#

would you

real pecan
#

yes

flint idol
#

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);```
real pecan
#

well

#

it tests one specfic simple case

flint idol
#
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

real pecan
#

and try swapping a lot of pages

flint idol
#

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

real pecan
flint idol
#

no it's because this is a rewrite of the vmm

#

once I swap out the kernel

#

it will probably crash

real pecan
#

so you have yet to plant a subtle bug in it?

flint idol
#

no known subtle bugs

#

I also don't think the old vmm crashed with smp disabled

real pecan
#

do u have it disabled now?

flint idol
#

no

real pecan
#

nice

flint idol
#

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

real pecan
#

lol

flint idol
#

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

flint idol
#

it gets stuck in an infinite panic loop

#

Now Mm_SwapProvider gets corrupted to 0xdededededededede

real pecan
#

Heap bug?

flint idol
#

It's a pointer

#

and this allocator has been extensively (uACPI) tested in the previous kernel

#

The bug is caused by the vmm test

flint idol
#

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?

white mulch
#

if addr is 0x1000 aligned then the last iteration that is entered would be buf + 0x3000 yeah

flint idol
#

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

flint idol
#

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

flint idol
#

I want to play minecraft xbox 360 edition

#

but I don't have neither an xbox 360 nor an mc xbox 360 edition disk

haughty abyss
#

seems rather illegal

flint idol
#

well the emulator is

#

legal

haughty abyss
#

you arent supposed to admit to crimes like downloading the rom

#

:^)

flint idol
#

no I would never download a rom

#

it turned out I did have a mc xbox 360 disk

haughty abyss
#

ah okay cool

real pecan
flint idol
#

nostalgia and stuff

real pecan
#

Also steamdeck can certainly run an xbox360 emulator so one probably exists already for Linux

flint idol
#

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

haughty abyss
flint idol
#

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

flint idol
#

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

flint idol
#

So I'm back to OSDev

inland radish
#

welcome back

flint idol
#

Now time to go back to debugging my thingy

flint idol
#

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

inland radish
#

the timer should

  • have a higher IRQL than the dispatcher's
  • not interfere in any way with the dispatcher's operations
flint idol
#

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

inland radish
#

ideally one of the highest

#

thats what NT does

ashen goblet