#OBOS (not vibecoded)

1 messages · Page 18 of 1

flint idol
#

the thread would be indefinitely blocked waiting for the event to be set

#

was quite fun to track that one down...

flint idol
#
obos_status OBOS_Kill(struct thread* as, struct thread* thr, int sigval);
obos_status OBOS_SigAction(int signum, const sigaction* act, sigaction* oldact);
obos_status OBOS_SigSuspend(sigset_t mask);
obos_status OBOS_SigPending(sigset_t* mask);
obos_status OBOS_SigProcMask(int how, const sigset_t* mask, sigset_t* oldset);
obos_status OBOS_SigAltStack(const uintptr_t* sp, uintptr_t* oldsp);

void OBOS_SyncPendingSignals(size_t maxCount);

void OBOSS_RunSignal(int sigval, sigaction* what);```
#

I have all my signal api done

#

bottom two functions are internal

#

2nd-last simply runs all signals in the current thread

#

last should be trivial to understand

#

although the last function will probably change a bit

#

the last function will take in a siginfo_t

#

time to start with the most trivial function to implement

#

kill

#

thr->signals.pending |= BIT(sigval);

#

bam

#

done

#

well

#

there is also setting some metadata

#
obos_status OBOS_Kill(struct thread* as, struct thread* thr, int sigval)
{
    if (!as || !thr || !(sigval >= 0 && sigval <= SIGRTMAX))
        return OBOS_STATUS_INVALID_ARGUMENT;
    if (thr->signal_info->pending & BIT(sigval))
        return OBOS_STATUS_SUCCESS;
    thr->signal_info->pending |= BIT(sigval);
    thr->signal_info->signals[sigval].addr = nullptr;
    thr->signal_info->signals[sigval].status = 0;
    thr->signal_info->signals[sigval].udata = 0;
    thr->signal_info->signals[sigval].sigcode = 0;
    thr->signal_info->signals[sigval].sender = as;
    return OBOS_STATUS_SUCCESS;
}```
#

easy

#

the fields set to zero should be setup if needed after Kill is called

#
obos_status OBOS_SigSuspend(sigset_t mask)
{
    Core_MutexAcquire(&Core_GetCurrentThread()->signal_info->lock);
    sigset_t old = Core_GetCurrentThread()->signal_info->mask;
    Core_GetCurrentThread()->signal_info->mask = mask;
    Core_WaitOnObjectsPtr(
        64, 
        sizeof(Core_GetCurrentThread()->signal_info->signals[0]), 
        (struct waitable_header*)&Core_GetCurrentThread()->signal_info->signals
    );
    Core_GetCurrentThread()->signal_info->mask = old;
    Core_MutexRelease(&Core_GetCurrentThread()->signal_info->lock);
    return OBOS_STATUS_SUCCESS;
}```
#

hopefully this is signal-safe

#

well since signal_info->lock is always taken when manipulating signals

#

I should be fine

#

wait...

#

I can't use wait on objects ptr

#

I'll just change this up a bit

#

this is better:

obos_status OBOS_SigSuspend(sigset_t mask)
{
    Core_MutexAcquire(&Core_GetCurrentThread()->signal_info->lock);
    sigset_t old = Core_GetCurrentThread()->signal_info->mask;
    Core_GetCurrentThread()->signal_info->mask = mask;
    Core_WaitOnObject(WAITABLE_OBJECT(Core_GetCurrentThread()->signal_info->event));
    Core_GetCurrentThread()->signal_info->mask = old;
    Core_MutexRelease(&Core_GetCurrentThread()->signal_info->lock);
    return OBOS_STATUS_SUCCESS;
}```
rapid pulsar
#

Don't forget that the libc version should always fail :-)

flint idol
#

yeah so I decided to just implement it in the kernel

rapid pulsar
#

No I mean the function is defined to always fail with EINTR

flint idol
#

ah

#

yeah I forgor

#

yeah I'll do that when I port mlibc

rapid pulsar
#

Unless you gave it a bad sigset, then it can fail with a fault, but the "success" case is that it gives EINTR because that's literally what the caller is asking it to do (wait until it gets interrupted).

flint idol
#

yup

#

your help is much appreciated, ty

rapid pulsar
#

Just gotta follow up myself ;) even my current signal implementation was written largely to 'practice what i preach' helping someone else with it a while back

flint idol
#
obos_status OBOS_Kill(struct thread* as, struct thread* thr, int sigval);
obos_status OBOS_SigAction(int signum, const sigaction* act, sigaction* oldact);
obos_status OBOS_SigSuspend(sigset_t mask);
obos_status OBOS_SigPending(sigset_t* mask);
enum {
    SIG_BLOCK,
    SIG_SETMASK,
    SIG_UNBLOCK,
};
obos_status OBOS_SigProcMask(int how, const sigset_t* mask, sigset_t* oldset);
obos_status OBOS_SigAltStack(const uintptr_t* sp, uintptr_t* oldsp);```
#

these are all implemented

#

all that's left is:

void OBOS_SyncPendingSignals(size_t maxCount);

void OBOSS_RunSignal(int sigval, sigaction* what);```
#

with run signal being arch-specific

inland radish
#

why not?

rapid pulsar
# inland radish why not?

The macros shall expand to positive integer constant expressions with type int and distinct values. The value 0 is reserved for use as the null signal

For one, because POSIX says so. But also this just holds in general and you’re bound to run into issues.

flint idol
#

and return

#

and run signal should take in an interrupt frame+thread+sigval and output a context

#

and after signals I will be optimizing swap

#

well more like my vmm

#

but anyway

flint idol
#

probably means "nothing"

flint idol
#

anyway I think ucontext_t can just be typedef'd to thread_context_info

flint idol
#

so if it's user to kernel, I can do CoW on the memory regions after the first page

#

up to the second last or last page depending on if the last byte is page aligned or not

#

for kernel->user I could do the same, but for security reasons I won't

#

(don't want to accidentally leak kernel memory to user mode)

flint idol
flint idol
#

my kasan is so slow and so memory inefficient

#

that when I remove it

#

the kernel uses 7M less memory

#

and boots a LOT faster

flint idol
#

or maybe it's a lot faster because a symbol is undefined in a driver

#

causing it to not do anything

#

turns out the ahci driver was using ~3M

#

but it's still a lot faster without kasan

#

but anyway I should be able to copy to and from user pages

flint idol
#

dam the log is so much more cluttered now

#

which is a good thing

#

because that means I didn't have ~25K changes in the summer for nothing

#

23K in august

#

and 5K in july

#

anyway, now that all public api for signals is done

#

I will start on the implementation

#
void OBOSS_SigReturn(interrupt_frame* frame);
void OBOSS_RunSignal(int sigval, thread* on, interrupt_frame* frame);```
#

I haven't written arch-specific code for quite a bit

#

almost just put a privellage escalation bug in my signal code

#

silly me!

#

basically I was doing:

memcpy(frame, &ctx.frame, sizeof(*frame));

with ctx.frame coming from usermode

#

so a user mode program could abuse that to set cs&ss to kernel code+data segments

#

which is why we must enable SMAP+SMEP

#

but then they could also abuse rip and set it to a kernel symbol address

#

and if I had some sort of internal set process uid function

#

they could use that to escalate a process to root

#
void OBOSS_SigReturn(interrupt_frame* frame)
{
    // Use frame->rsp to restore the previous thread context.
    thread_ctx ctx = {};
    memcpy_usr_to_k(&ctx, (void*)frame->rsp, sizeof(ctx));
    if (ctx.frame.rip >= OBOS_KERNEL_ADDRESS_SPACE_BASE || frame->rsp >= OBOS_KERNEL_ADDRESS_SPACE_BASE)
        return;
    wrmsr(KERNEL_GS_BASE, ctx.gs_base);
    wrmsr(FS_BASE, ctx.fs_base);
    memcpy(frame, &ctx.frame, sizeof(*frame));
    frame->cs = 0x18|3;
    frame->ss = 0x20|3;
    frame->ds = 0x20|3;
    frame->rflags |= RFLAGS_INTERRUPT_ENABLE;
    frame->rflags |= RFLAGS_IOPL_3;
    frame->cr3 = CoreS_GetCPULocalPtr()->currentContext->pt;
}```
#

hopefully no one tries to exploit this...

#

worst this can cause is the process getting SIGSEGV because the return address is invalid (hopefully)

real pecan
flint idol
#

you'll report the bug, right

real pecan
#

yes Kapp

flint idol
#

I'm sure it's stable enough

weary hound
#

also you want to clear iopl not set it?

flint idol
#

shi I did

flint idol
#

I coulda sworn I had a good reason to put that there

weary hound
#

also also you check it after you try to copy

flint idol
#
void OBOSS_SigReturn(interrupt_frame* frame)
{
    // Use frame->rsp to restore the previous thread context.
    thread_ctx ctx = {};
    if (obos_is_error(memcpy_usr_to_k(&ctx, (void*)frame->rsp, sizeof(ctx))))
        return;
    Core_EventClear(&Core_GetCurrentThread()->signal_info->event);
    wrmsr(KERNEL_GS_BASE, ctx.gs_base);
    wrmsr(FS_BASE, ctx.fs_base);
    memcpy(frame, &ctx.frame, sizeof(*frame));
    frame->cs = 0x18|3;
    frame->ss = 0x20|3;
    frame->ds = 0x20|3;
    frame->rflags |= RFLAGS_INTERRUPT_ENABLE;
    frame->cr3 = CoreS_GetCPULocalPtr()->currentContext->pt;
}```
#

this is what it is now btw

weary hound
#

this still lets the user set iopl=3 on their own?

flint idol
#

oh yeah

#

I just need to add the xrstor to the function

#

or fxrstor

#

depends

#

but anyway

weary hound
# weary hound this still lets the user set iopl=3 on their own?

managarm does ```cpp
// Allow modifying the normal non-privileged flags.
constexpr uintptr_t allowedFlagsMask = 0b1000011000110111111111;
thread->_executor.general()->rflags &= ~allowedFlagsMask;
thread->_executor.general()->rflags |= regs[17] & allowedFlagsMask;

flint idol
#

I see

#

you guys won't mind if I just... take that, right

flint idol
#

I'll implement m68k signals later™️

#

but I should have the basis for signals done

vernal chasm
flint idol
#

only reason my signals are going to be posix compliant is because I don't want to spend a lot of time on designing them

#

just for them to be shit anyway

#

and hard to port in mlibc

#

and no I'm not going to make my own libc

vernal chasm
#

Why not, it's such a simple thing to do

flint idol
#

SIGILL is illegal instruction right

#

and do I use SIGSEGV for #GP

vale nymph
#

Yes for both

flint idol
#

ok

inland radish
inland radish
#

thats not how you set CPL, what does it do

flint idol
#

I am 50% sure I'm supposed to

#

to set CPL

#

*RPL

inland radish
#

what's RPL?

flint idol
#

I think it's just the ring level of the selector

inland radish
#

i see

#

so the fact that a segment selector is oddly similar to the offset of the specific segment in the GDT is only coincidence

flint idol
#

indeed

#

out of curiosity, has boron gotten to ring 3 yet, or have you entirely been doing kernel mode dev

#

that's from the sdm

vernal chasm
inland radish
#

i wanna get a semi decent Mm and Ps first

flint idol
#

makes sense how you'd make that mistake

inland radish
#

(memory manager, process system)

flint idol
#

yup

#

gl

inland radish
flint idol
#

I like boron's codebase style

#

quite clean

#

so I've made all cpu exception handlers signal the thread

#

it happened on

#

so I guess that's posix signals done

#

except for SIGKILL

#

since I have no way to terminate processes

#

or even threads

#

I can terminate the current thread

#

but not remote threads

#

yet

inland radish
flint idol
#

marker

#

dam he explained it twice

#

so yeah to optimize my vmm I'll just do that

#

how hard could it possibly be

#

so yeah I basically have a dirty list

#

I throw dirty pages that are trimmed from the working set on there

#

or if no more references

#

then eventually

#

the kernel writes back the pages to the swap

#

and frees the physical pages

flint idol
#

if I lock in I can start ttys today

#

but I first need to do this thing with the vmm

flint idol
#

researching them today

flint idol
#

it almost™️ works

#
Assertion failed in function Mm_RunPRA. File: /home/oberrow/Code/obos/src/oboskrnl/mm/handler.c, line 374. !ctx->referenced.nNodes```
#

except for that

#

idk what's up with that

#

ctx->referenced.nNodes = -2

#
if (curr->workingSets > 0)
            {
                REMOVE_PAGE_NODE(ctx->workingSet.pages, &curr->ln_node);
                ctx->workingSet.size -= curr->prot.huge_page ? OBOS_HUGE_PAGE_SIZE : OBOS_PAGE_SIZE;
            }
            else 
                REMOVE_PAGE_NODE(ctx->referenced, &curr->ln_node); // it's in the referenced list```
#

that was it

#

omg this is so faster

#

rather I'm hallucinating

#

or this is genuinely faster

#

well that's probably because I don't actually ever wake the dirty page writer

#

and now it recursively locks

#

fixed that

#

to get the occasional deadlock

#

obos moment

#

fixed

#

I think

#

other than the fact that the ahci driver is suddenly broken

#

well it's more like the partition thingy

#

but it's more likely to be the ahci driver

#

fixed

#

it was Mm_VirtualMemoryProtect

#

fuck

#

this is 100 ms slower

#

50ms to 100 ms slower

flint idol
#
ASAN Violation at ffffffff8005e44f while trying to read 1 bytes from 0xffff80003a1b84f9 (Hint: Use of memory block after free).```
#

wtf

#

how was this bug never caught before

#
if (curr->allocated)
    Mm_Allocator->Free(Mm_Allocator, curr, sizeof(*curr));
offset = curr->prot.huge_page ? OBOS_HUGE_PAGE_SIZE : OBOS_PAGE_SIZE;```
flint idol
#

the difference between the new swap impl. and the old one is .032 ms, with the old one being faster

#

but the difference is probably a lot bigger if paging to disk instead of ram

#

it was a lot faster using the other swap thing

#

hmm it deadlocks later on though

#

not an artifact of the disk swap

#

nvm

#

it's probably an artifiact of switching to a new swap

#

but the problem is it doesn't always deadlock

#

even more weirdly, the page writer thread has the lock acquired

#

but it's blocked

#

but it never blocks itself before releasing the spinlock

#

I really gotta stop forgetting to init my event objects

#

so it was both that and a bug with event pulse

#

(or so it seems)

#

it was that

#

tomorrow after school I will probably start implementation of ttys

#

I now need to understand them

flint idol
flint idol
#

so I'm rewriting the vmm now

#

some parts won't be

#

expect this to take weeks because school

#

so how will I get this shit to not be shit

#

well it's not shit

#

it's just this that's causing trouble

#

but the problem is

#

that's used everywhere in the vmm

#

and even in some places outside the vmm

real pecan
#

hope u actually rewrite the vmm instead of the entirety of the kernel

flint idol
#

I want to refrain from the latter

#

yeah no it's really only ever used in the vmm

#

rarely outside

#

I'll keep the external vmm api

#

Mm_VirtualMemoryAlloc/Free/Protect

#

and just rewrite it

#

but now I'm kinda confused though

#

because I was told by fadanoid (I think) to use a rb tree for vmm page keeping

#

or smth like that

#

but idk how to do that with page regions

#

actually nvm I'm just not braining correctly

#

why couldn't anyone

#

have warned me

#

back then

#

my brain isn'tbraining pcorfeswfesw

#

scorecly

#

correctly

#

which is why I'll look at keyronex

#

I just need to summon fadanoid first

#

"m68k"

#

typo

#

is this for one page

#

or for a range

#

I think the former?

#

nvm

#

it's the latter

#

uhh so change of plans

#

obos rewrite 6

#

not rly

#

uhh

#

fuck

#

forgor

#

ah yes

#

shit

#

I'm typing faster than I can think atm

real pecan
#

noooooo

flint idol
#

I am NOT doing that again

flint idol
#

I am going to leave a TODO for the next person to come across this

#

and put a readme in src/oboskrnl/mm

#

saying

Abandon all hope, ye who enter here

#

I should optimize the struct's memory usage at the least

#
uintptr_t swapId : PTR_BITS;            // The page's swap allocation id. Only valid if pagedOut == true.
    size_t swap_off : PTR_BITS;             // The offset in the swap buffer. Only valid if pagedOut == true.```
#

that's a full 4ewrwrwrw

#

34r234

#

16 bytes

#

which I might be able to cut down to 8

#

if I slightly change swap

#

there's a 24-byte struct in there

#

which can be changed

#

probably

#

so I have no idea how to fix this

#

everything here is used

#

and I have no fucking idea what to remove

#

and what to move

flint idol
flint idol
#

might go for a bit to read wininternals

#

and books about NT design

#

looks fun to read lapfedmoment

#

dam

#

why it so expensive O_O

#

would cost me $150 for part1+2

#

maybe I should find older things

lean glen
#

lol

flint idol
#

piracy, fun

#

microsoft has enough money anyway

lean glen
#

sorry im not gonna pay 150$ for a pdf

flint idol
#

fr

lean glen
#

Even worse

#

You're paying 150$ for a book describing the 200$ software you bought

flint idol
#

who even buys windows

#

if it don't come with your computer

#

just don't activate it

#

what're they gonna do about it

#

make me not be able to set a wallpaper?

lean glen
#

Nah you can set a wallpaper just not through settings

#

Found this out when I was 12 at my friend's house

#

He didn't activate windows so I tried right clicking an image and click on set as wallpaper and voila

flint idol
#

lol

#

so like basically nothing happens

#

except for ms meatriders attacking you when you send a screenshot of your desktop

#

and it says "Active windows"

lean glen
#

Yeah the only annoying thing is the watermark

#

But why pay when there's stuff like massgrave

ornate ginkgo
#

Well you usually pay because that's the law, whether you agree with it or not

vernal chasm
white mulch
#

you can also just transfer the license from an old pc that you bought

vernal chasm
#

Or that

#

You can also get a key for like 5 bucks...

ornate ginkgo
inland radish
#

which is schools

#

not a single individual that I've seen has paid for windows

empty kernel
#

In my state within my country, the education department has some kind of arrangement with Microsoft so all students and teachers in public schools get free office 365, minecraft education and windows 10 education on school devices.

inland radish
#

We had free web Office too while I was in high school

haughty abyss
#

its just MS doing adobe moment

#

get your sw everywhere so it becomes the standard

#

and then people use it when they grow up

empty kernel
lunar narwhal
flint idol
#

might be stopping osdev for quite a bit

#

(this can range from a day to months)

#

but until then....

#

I will be playing mc or doing homework

#

(or maybe doing dev for the 6502)

#

might still be active here

#

my thread won't be tho

real pecan
flint idol
real pecan
#

i see

#

well i hope u come back and dont end up like marca

flint idol
flint idol
#

I have some time rn

flint idol
#

I'll explain it in a bit

real pecan
#

nice

flint idol
#

I replace this with a range of pages

#

idk what kinda data structure I'll use to store the page ranges tho

#

theoretically as long as the regions do not overlap, I can use an rb-tree

flint idol
#

I take in a region pointer and a offset

#

the standby and dirty list will be lists of:

struct page /* TODO: name */
{
    uintptr_t virt;
    uintptr_t phys;
    bool huge_page;
};```
flint idol
#

if so I setup a struct page

#

and slap it onto the dirty list

#

otherwise I also setup a struct page

#

but instead slap it onto the standby list

#

to swap in

#

I check if the page is on standby or is dirty

#

if so I can remove it from said list

#

and remap it with the same phys. address

#

otherwise I gotta go through the entire dance of reading it from the swap medium

#

I'll also have some sort of virtual page info struct

#

which contains prot bits

#

and redesign the arch-specific api to query/set page stuff

flint idol
#

guess we're doin chatgpt now /j

vale nymph
# flint idol

add chatgpt system calls, say obos has deep llm integration in the kernel, print vc money, get rich, retire, work full time on obos, profit

flint idol
#

obos will have the best kernel

thick jolt
#

i actually wanna see OBOS finished

#

😭

flint idol
thick jolt
flint idol
#

may god have mercy on my soul

flint idol
#

I need to implement pg_cmp_pages to compare two page ranges

#
inline static int pg_cmp_pages(const page_range* left, const page_range* right)
{
}```
#

well if left->virt < right->virt

#

then it returns -1

#

if it's greater it returns 1 IF !in_range(left->virt, left->virt+left->size, right->virt)

#

otherwise zero

#
#define in_range(ra,rb,x) (((x) >= (ra)) && ((x) < (rb)))
inline static int pg_cmp_pages(const page_range* left, const page_range* right)
{
    if (left->virt < right->virt)
        return -1;
    if (left->virt > right->virt)
        return (!in_range(left->virt, left->virt+left->size, right->virt)) ? 1 : 0;
    return 0;
}
#undef in_range```
lean glen
#

return !in_range(whatever)

flint idol
#

you cannot for rb trees

lean glen
#

what

flint idol
#

it needs the distinction between less and greater

lean glen
#

you convert a bool to an int

#

in the ternary statement

#

you can literally just return the bool

flint idol
#

wait I thought you meant

#

for the entire function

#
inline static int pg_cmp_pages(const page_range* left, const page_range* right)
{
    return in_range(left->virt, left->virt+left->size, right->virt);
}```
flint idol
flint idol
#

and I'm using an rb-tree to store the ranges

real pecan
#

so ur making folios or is it still virtual memory related

flint idol
flint idol
real pecan
#

f

#

wait until u learn about vm_area

devout niche
flint idol
#

yes

flint idol
real pecan
devout niche
#

i have 64 (well, 56, but padded on 64-bit platforms; 32 on 32-bit platforms)

real pecan
#

nah your struct page is for physical pages

#

this is a virtual page descriptor

devout niche
#

oh, i see it now

#

the pagedOut bit is a giveaway

flint idol
#

and pageable

#

and isPrivateMapping

real pecan
#

Lol

flint idol
#

I think this entire thing screams "virtual page"

#

except for the name

real pecan
#

Me when my entire ram is consumed by vmm overhead

lean glen
devout niche
#

in my case the division of labour for that virtual page struct is between the physical page frame struct, the working set list entry, and the vm map entry

lean glen
#

yeah that's essentially what I do too

flint idol
#

anyway

#

I must go back to de-shittifying this

lean glen
#

I think it'd be on a per-page-in-anon basis maybe?

#

idk

real pecan
devout niche
real pecan
#

i see

devout niche
#

but if you exclude the overheads that are dominated down to being fairly negligible when there's lots of pages mapped, it's a word (a single working set entry)

#

i am excluding the cost of page tables, prototype page tables, map entry struct, the physical vm_page struct, etc, those can dominate if you, say, make a hundred thousand memory objects and map a single page of each, each 1gib apart in the address space

real pecan
#

whats a prototype page table

devout niche
#

an abstract page table like data structure that keeps track of pages for files, anonymous shared vm objects, those are organised as a 4-level table, and (in the form of a single pointer coupled with a refcount) forked pages

real pecan
#

tahts interesting

#

is that some common concept or did you invent that yourself

devout niche
#

the 4-level tables are excessive and i have a plan to make it so that you don't have to pay 4 pages if you just want to e.g. mmap the very first page of a file

#

my plan is probably to make it so that the 4 levels can be collapsed to however many are actually needed to map the pages that are actually mapped of a file

real pecan
#

Do you know how other kernels solve this?

devout niche
real pecan
#

I see

flint idol
#

I think I'm ditching the kernel gdbstub

#

it's pretty slow and useless

devout niche
#

other popular data structures have been a hash table of {vnode, page} (e.g. sunos vmm), linux also uses radix trees for this, netbsd uses a wAVL tree for file pages and a 2-level table with variably-sized root-level for files, windows uses linear tables allocated from the paged pool

real pecan
#

Interesting

devout niche
#

well nowadays i think they might allocate linear spans on windows and link them into an avl tree because the linear tables are no good if you want to map only a few pages but they're 64gb into the file

devout niche
#

so i wasted some time implementing polled send/receive for e1000 in case i need to debug my kernel on my laptop

flint idol
#

until I find the time to fix it

devout niche
#

if any documentation exists for whatever tf the raspi4 has (let's be honest, there won't be any documentation, documentation is for computers with real cpus, i.e. amd64 cpus) then that's another one i should write

flint idol
thick jolt
#

page.

#

PAGE FAULT!

#

that gives you nightmares!

#

ksan violation!

flint idol
#

you're giving me flashbacks

thick jolt
#

hahaha

flint idol
#

wait

#

if I have a range of pages

#

struct page_range

#

how the fuck

#

do I figure out

#

how many working sets each page is in

#

or the pages' ages

#

without splitting the regions and updating the appropriate fields

#

whenever a page gets paged out

#

or is put in a working set

#

one thing I could do is.........

#

no idea

#

I can't do it with arch-specific hooks

#

like I can't have something like void Mm_PageAge(uintptr_t addr, uint8_t* age, bool rw);

#

at least not efficiently on archs that can't don't have 8 os-reserved bits in a PTE needed to store that kinda stuff

devout niche
flint idol
#

ok

#

gave me an idea

#

each working set list entry for a page is the same thing

#

and they will be stored in a non-intrusive linked list

#

oh god

#

the error log is ~2k lines

#

yeah this might call for a vmm rewrite

#

no public api of the vmm will be changed

devout niche
#

i am deep into 9000 lines of (very dense) code in the keyronex vmm and worry how will i ever make big changes to it (like the fine locking plan i have eventually)

limber wave
#

I am starting to think that you secretly are sadistic and enjoy giving yourself pain

flint idol
limber wave
#

yeah

#

and the pmm?

flint idol
#

has stayed the same since forever

#

since my 2nd rewrite of the kernel

#

or 3rd

limber wave
#

ahhh

flint idol
#

(this is the fifth rewrite btw)

#

(fourth was a disaster)

#

(third was just not designed well)

#

(2nd/1st were shit)

limber wave
#

I suggest to start an entire channel in here just for people to try out your curse, and maybe help you

limber wave
#

I have rewritten my bootloader like 20 times

flint idol
#

lol

limber wave
#

and never went further than that

#

because I enjoy bootloaders

flint idol
#

.!t limine

umbral iceBOT
flint idol
#

oh nvm

#

you chose this pain

limber wave
#

yessir

flint idol
#

#bootloaders message

#

well gl with your btldr

#

after vmm rewrite is TTYs

#

so in a couple weeks bcuz school

limber wave
#

modern problems require modern (bad) solutions

#

please kids don't try this at home

flint idol
#

wouldn't recommend

#

(my parents would kill me)

limber wave
flint idol
#

so I might actaully make a driver interface in the form of a library, sounds fun

#

oDriverinterface

#

comes with:

  • a dynamic loader
  • a lot of interface functions
  • maybe even pnp
  • the oberrow curse
limber wave
#

you are quite wrong here

#

you see, everything is optional, except the last in the list

flint idol
#

maybe m68k soon

#

and x86

#

since no one uses msvc I'll be forcing gcc

#

extensions

limber wave
flint idol
#

doubt

#

each driver will have a rw callback

#

along with ioctl

#

as well as a cleanup cb

#

for unload

#

and idk how fs drivers will work

#

for making, moving, and removing files

#

I guess I can just

#

have cbs for those

#

they'll take in a dirent

#

and then I'll also have a probe cb

#

which probes a partition to see if there is an fs there

flint idol
lean glen
#

what the fuck is a CB

flint idol
#

callback

#

or centerback in soccer

lean glen
#

ah

real pecan
flint idol
#

I hate this nooo

#

a full rewrite of the vmm

#

is going to be pain

#

commit msg will be:
Mm: Small changes

#

then continue to have 2k+ deletions

#

and 2k+ additions

vale nymph
#

lgtm

flint idol
#

I hate this

#

I hate this

#

I hate this

#

I no longer hate this as much

flint idol
#

when it's being swapped in once again

flint idol
#

uhhhhhh

#

maybe

#

in the page region thingy

#

I have a list of paged out pages

#

something like this:

typedef struct swap_range
{
    uintptr_t id;
    uintptr_t virt_base;
    size_t    size;
} swap_range;```
#

but since most pages are going to be paged out

#

that defeats the entire purpose of my vmm rewrite

#

yeah I haven't a clue

flint idol
#

I got an idea

#

to do that

#

I just need to completely re-design how my swap works

#
obos_status(* swap_resv)(struct swap_device* dev, uintptr_t *id, size_t nPages);
obos_status(* swap_free)(struct swap_device* dev, uintptr_t  id, size_t nPages, size_t offsetBytes);
obos_status(*swap_write)(struct swap_device* dev, uintptr_t  id, uintptr_t phys, size_t nPages, size_t offsetBytes);
obos_status(* swap_read)(struct swap_device* dev, uintptr_t  id, uintptr_t phys, size_t nPages, size_t offsetBytes);```
#

for example here

#

instead of swap_resv giving me an id

#

it just takes in a virtual address as the handle

#

and the swap device somehow (hashmap, fancy tree?) stores a virtual memory -> place in swap file

#

prob. hashmap on disk

#

and a tree for the in-ram swap

#
obos_status(* swap_resv)(struct swap_device* dev, uintptr_t virt, bool huge_page);
obos_status(* swap_free)(struct swap_device* dev, uintptr_t virt, bool huge_page);
obos_status(*swap_write)(struct swap_device* dev, uintptr_t virt /* must be mapped */, size_t nPages);
obos_status(* swap_read)(struct swap_device* dev, uintptr_t virt /* must be mapped */, size_t nPages);```
rapid cairn
#

hi

flint idol
#

hello

flint idol
rapid cairn
#

what are you up to?

flint idol
rapid cairn
#

whats wrong with it?

flint idol
#

currently there's a big design flaw

#

where each virtual page

#

is stored in a 128-byte struct

#

causing very large vmm overhead

rapid cairn
#

how much overhead we talkin?

flint idol
#

let's see

#

I'll do some math to see how much 1G of memory allocated would be

rapid cairn
#

also do you dev on windows or linux?

flint idol
#

used to dev on windows

#

then switched to linux mid-june

rapid cairn
#

yay a fellow linux freedom figher

flint idol
#

for 1G allocated

rapid cairn
#

8 megabytes, thats a LOT, so is this your malloc and free stuff?

flint idol
#

you could say that I guess

#

basically it's the thing that deals with allocating and managing virtual memory "pages"

#

e.g., mapping files, swapping out stuff, mapping anon memory

rapid cairn
#

OH so this is mapping psyical memory to virtual right?

flint idol
flint idol
rapid cairn
#

and it has a big overhead due to what?

flint idol
#

it must store info about a page

#

for example the offset in the swap file

#

that it lies in

#

or the file it's mapped to

rapid cairn
#

so what part of the code do you suspect is causing issues?

flint idol
#

but the thing is, the entire thing depends on that one struct

rapid cairn
#

have you tried chatgpt /j

flint idol
rapid cairn
#

oh, well at that porint just reimplement paging

flint idol
#

that's many many work

#

to rewrite all

#

in the vmm

rapid cairn
#

well not ALL but more like the struct, so something in it is causing an 8MB overhead, correct?

flint idol
#

and a big misconception in beginners is that the VMM just deals with mapping pages

flint idol
#

for each mapped page, it's about a 128-byte overhead

rapid cairn
#

and within that it grows I suppose?

flint idol
#

wdym?

rapid cairn
#

I mean the overhead grows

flint idol
#

yes

#

1 mapped page would be 128-bytes

#

2 would be 256 bytes

#

so on and so forth

rapid cairn
#

that 128 byte overhead (not much) grows into a WAY bigger 8MB overhead which would grow to become a bigger and bigger issue

flint idol
#

indeed

#

just figured out I did my math wrong

rapid cairn
#

is it not as big of an overhead or is it way bigger?

flint idol
#

a lot smaller

#

2048-bytes

#

but still unwanted

#

as it grows and grows

rapid cairn
#

still thats WAY better than 8MB, I mean windows has some overhead too lemme check it

flint idol
#

certainly not as much overhead as this

rapid cairn
#

true, but this is FAR better than 8MB, I mean at least this is ACCEPTABLE I mean its still a good chunck of overhead but still

flint idol
#

but with the solution of simply having a range of pages

#

that gets cut down to a static

#

lemme see how much

#

104 bytes overhead

#

for each range of pages allocated

#

say you allocated 1 TiB

#

that would be 104 bytes overhead

#

say you allocated a page

rapid cairn
#

104 byte overhead with 1 TERABYTE of ram

flint idol
#

104 bytes overhead

flint idol
#

the kernel doesn't hand out ram like it's nothin'

rapid cairn
flint idol
#

the program thinks it gets 1 TiB

#

but in reality

#

the kernel doesn't "commit" the memory until it's touched

rapid cairn
#

so its not actually used until its asked for

flint idol
#

indeed

#

you can also reserve virtual address space

#

if you do that

#

it's unmapped

#

but nothing can reallocate it

rapid cairn
#

what about stuff like malloc? how would it work then, for me it just makes a 1MB single page, then splits it to store data as requested then free marks it as free and merges it, so how does it work for you?

flint idol
#

my kernel's allocator (for general structs, not pages/physical pages) simply has a free list and allocated list

#

when you allocate something

#

it finds a "region" with sufficient memory

#

if no such thing exists it makes a new one with sufficient size

#

then it takes some memory from a node in the free list

#

then it throws at you that ptr

#

on free what it does is it takes your ptr

#

if it's the only allocated region it gets purged (freed)

#

otherwise it gets added to the free list

#

wrote this code months ago

rapid cairn
#

for me I just pass free the pointer and it does its magic

flint idol
#

yeah same

#

-# I probably forget to free a bunch of stuff

#

-# 20M of memory committed? more like 20M memory leaked

rapid cairn
#

for me the kernel API is also the userspace API lol, since its all going to be in kernel mode because im dumb

flint idol
#

won't go well

#

but you do you

rapid cairn
#

well its more ring 0 lol, the Kernel API will be private then it will have public stuff for the userspace to use

#

it will kinda be like templeOS, just no religion

flint idol
#

not quite a userspace if it's in ring 0 lol

#

since a program (with or without malicious intent) can call a kernel mode function without you knowing it

rapid cairn
#

true, on the other hand, who can hack an OS when they cannot even understand the API!

flint idol
#

lmao

rapid cairn
#

not even the dev understands the API, thats how bad my code is

flint idol
#

only thing that runs in kernel mode in my kernel is the kernel ofc and the kernel modules (drivers)

rapid cairn
#

so you have a driver system already?

flint idol
#

yes

rapid cairn
#

what about apps?

flint idol
#

also planning on making a library for that

flint idol
#

you're funny

rapid cairn
#

not there yet, or working on it?

flint idol
#

not there yet

#

(need to rewrite that vmm)

rapid cairn
#

are the kernel modules loaded from disk?

flint idol
#

they can be

rapid cairn
#

so it works?

flint idol
#

yes

rapid cairn
#

so how do kernel modules work?

flint idol
#

so basically

#

a kernel module is a dynamically loaded elf file

#

kinda like a dynamic library

#

that's linked to the kernel at run-time

rapid cairn
#

so its a program more or less?

flint idol
#

when it's loaded

flint idol
#

it has its own header alongside the elf header which can be anywhere in the header, or optionally in a section to speed up search

#

said header has info on the kernel module

#

like how pnp should find it

rapid cairn
flint idol
#

and what its name is (optional)

#

and also a table of functions for the kernel to call when it wants somethin from the driver

flint idol
rapid cairn
flint idol
rapid cairn
#

other than the bootloader and the compiler lol

#

welp, gn

flint idol
#

gn

flint idol
#

damn obos has been cursed since the start

flint idol
thick jolt
limber wave
flint idol
#

I made this a year ago

hollow geyser
#

make it 4 bit

#

so i can run it on my pc

flint idol
#

Ok

hollow geyser
#

(i have an intel 4004 as a cpu)

thick jolt
flint idol
#

Will work on this some more in a tiny bit

flint idol
#

the pf handler code is gonna be pain to change 😭

#

😭

#

I may as well rewrite that file

#

if I'm being completely honest

#

the kernel will not work when I get it to finally compile

flint idol
#

it's gottne to compiling drivers

#

*gotten

#

it's linking

#

ok it linked

#

and as intended

#

it crashes

#

or maybe not as intended

#

the curse is techincally back

#

but not really

#

since nothing is supposed to work

#

intentionally

vale nymph
#

obos without the oberrow curse is like an angel without its wings

flint idol
#

now that's a bug unfortunately

#

and not a result of unimplemented stuff

#

since freeing doesn't exist

#

I can do some stuff

#

bug in MmH_FindAvailableAddress

#

something tells me

#

that I don't register the regions

#

I don't

#
inline static int pg_cmp_pages(const page_range* left, const page_range* right)
{
    if (left->virt < right->virt)
        return -1;
    if (left->virt > right->virt)
        return in_range(left->virt, left->virt+left->size, right->virt);
    return 0;
}```
#

that's buggy

#

idk how

#

as in

#

idk how I shoulda made it in the first place

#

I feel like fadanoid would know

#

"m68k"

#

it'll work eventually

#

(as in saying m68k to summon fadanoid)

#

((not the code))

#

(((that ain't workin for a while)))

flint idol
#

I think I should just return a memcmp

#

or smth like that

limber wave
flint idol
#

it's gotten past uACPI init

#

and it crashes

#

at VFS init

#

because it tries to politely ask the initrd driver

#

for some files

#

but it pfs because the memory protection thing is unimplemented

flint idol
#

the freeing function should be implemented for the most part

flint idol
#

Curse is bacl

#

*back'

#

ok

#

it only exists on reboot

#

other than the fact that I temporarily don't have swap support

#

and that the kernel crashes on reboot

#

this is probably nearly dobe

#

*done

flint idol
#

or file mapping

#

or rather I only have one half of them

real pecan
#

when new obos features

flint idol
#

When I get the vmm outta the wat

#

*way

real pecan
#

nice

flint idol
thick jolt
#

bro is putting a brainfuck interpreter in obos

flint idol
#

no

#

(maybe)

#

((probably not))

thick jolt
#

(u should) ((best))

#

(write memory manager in brainfuck) :)

flint idol
#

write kernel in bf

thick jolt
flint idol
#

someone has to have written a gcc backend for bf

#

to output bf from C

#

or smth

#

someone did make a frontend

lean glen
flint idol
#

yea I thought about it a bit

limber wave
flint idol
#

no

#

soon enough

flint idol
#

fuck

#

curse back

flint idol
#

kinda wanna try boron's firework test

#

on obos

#

I've found it here

#

now I will do some magic stuff to get it to work on obos

#

(there is no way this goes well)

#

I'm thinking on putting this in my test_driver

#

it was originally there just to test the elf loader for the driver interface

#

but I guess I could make it better by adding that

#

actaully

#

idk if I wanna use boron's code

#

bcuz license

#

I mean if I just never commit it

limber wave
#

if I had to put license everytime I tested some code from other sources... well I would have more license files than source files

#

but then again, I never commit anything since I do not use github for personal projects

flint idol
#

bruh

#

wtf is this

#

my gdb don't wanna work

#

oops

flint idol
#

bruh

#

I hate dynamic linking

thick jolt
#

i love dynamic linking

#

enjo

#

y

#

:)

flint idol
#

unless

#

wait nvm

#

I was in the dynamic symbol table of the driver

#

new stuff added to the panic screen

#

namely the driver bases

thick jolt
#

my kernel panic is better then ur kernel panic

flint idol
#

and stack trace

thick jolt
#

it calls u an idiot

#

:)

flint idol
#

inspiration taken from boron's panic screen

#

there is the panic on the framebuffer

#

and not from the debugcon output

#

bruh the stack trace is garbage

thick jolt
#

lol

flint idol
#

bro why is the test driver causing the entire kernel to crash

#

it's 5 lines

#

of code run

#
OBOS_PAGEABLE_FUNCTION void OBOS_DriverEntry(driver_id* this)
{
    this_driver = this;
    OBOS_Log("%s: Hello from test driver #1. Driver base: %p. Driver id: %d.\n", __func__, this->base, this->id);
    TestDriver_Test(this);
    OBOS_Log("Exiting from main thread.\n");
    Core_ExitCurrentThread();
}```
#
Page fault at 0xffffff0000199310 in kernel-mode while to write page at 0x0000000000000000, which is unpresent. Error code: 2```
#

that address

#

is in the test driver

#

but it isn't at the same time

short mortar
#

Where do you get symbol names from?

flint idol
#

the kernel has all of its symbols cached in a tree

#

rb-tree

#

so does each driver

short mortar
#

oh because you have modules

flint idol
#

yea

real pecan
flint idol
#

wait

#

for how long has that been there for

#

no wonder those pf messages always sounded kinda weird

#

I think the test driver might be cursed

#

and the stack trace

#

why are some kernel symbols resolved

#

and others aren't

flint idol
#

old msg but good idea

#

I'll just put a kernel memory dump in a qr code

#

(not actually)

#

but maybe on panic that could be a good idea

real pecan
#

You cant dump much in it since qr can barely store anything

rapid pulsar
#

2953 bytes is the maximum size of a single QR code with a module size of 177×177 and low error correction.

flint idol
#

to output a qr code with the panic info

haughty abyss
#

you can still fit like

flint idol
#

maybe a stack dump

haughty abyss
#

kernel version + traceback + format args for panic + panic id

flint idol
#

yeah

haughty abyss
#

as a link to a website which reports the crash :^)

flint idol
#

I could probably just dump the info printfed on panic to the qr code

flint idol
real pecan
flint idol
#

that would take 16% of the qr code's space

#

so no

real pecan
#

Dump the entire framebuffer as qr

flint idol
#

that'd take 1420% of the qr code

#

*142035%

vale nymph
#

Just tell the user to take a picture and upload it to some website troll

lean glen
#

You can use qrloops

#

Which is a bunch of QR codes that are looped

flint idol
#

I added some more info to the kernel panic

flint idol
#

made some small changes

#

waiiit

#

that crash could be because of an allocator bug

#

shit

#

TODO:

vale nymph
#

the oberrow curse strikes again
TODO: make it not

inland radish
#

I won't sue, promise

inland radish
#

i use a separate symbol array ordered by address so i can simply do a binary search

vale nymph
#

Once I get modules working in astral the first module I should do is fireworks test

ornate ginkgo
#

lol everyone is porting nanoshell fireworks

#

I was also thinking about porting it (or a version of it) at one point for a scheduler test

ornate ginkgo
flint idol
#

However on real hw it's useful to have the stack trace and driver bases

#

And register dumps in the case of a cpu exception

ornate ginkgo
#

eh i find the gpr state kind of useless

flint idol
#

Fair

white mulch
#

the ip, sp and cr2 sure but the other registers aren't terribly useful

ornate ginkgo
#

yeah, thats why I specified gprs

#

maybe the stack pointer in some cases

flint idol
#

The info about the build is there for bug reports

flint idol
#

I just dump it in the format string for cpu exceptions

white mulch
#

though to be fair linux also does a gpr dump KEKW

ornate ginkgo
#

I guess thats why its called Linux and not Winux

inland radish
#

nanoshell fireworks is singlethreaded

#

boron fireworks isnt

#

also fun fact, I ported the fireworks test to jackal, and by extension mintia2, as well

#

and it managed to catch a bug in the xr/emulator

flint idol
limber wave
inland radish
#

it is

#

technically it supports modules (you can load a system debugger) but I didn't know that at the time so I ended up making it part of the kernel

flint idol
#

I now continue making fireworks

lean glen
ornate ginkgo
#

Still not helpful, what is rax in that case?

#

It doesn't tell you anything "page fault at <pc> with flags xyz" doesn't tell you

flint idol
#

I mean you could use objdump to try and figure out how rax got that way

#

I've done that a couple times

flint idol
#

damn this test might kill the kernel

#
// Explode it!
// This spawns many, many threads! Cause why not, right?!
int PartCount = Rand() % 100 + 100```
flint idol
#

aaand my timer interface has decided to die

#

so uhh

#

the timer irq

#

has decided to randomly to get masked

#

how?

#

idk

#

why?

#

idk

#

because of my damn irq interface

#

fixed

#

I guess

vale nymph
#

thats a beautiful #when-your-os-goes-crazy moment