#OBOS (not vibecoded)
1 messages · Page 18 of 1
the solution was just to lower the irql after the thread is unblocked
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;
}```
Don't forget that the libc version should always fail :-)
yeah so I decided to just implement it in the kernel
No I mean the function is defined to always fail with EINTR
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).
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
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
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.
I have figured out that OBOS_SyncPendingSignals can be simplified to just call one signal
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
what's the null signal
probably means "nothing"
idk why I said output a context
anyway I think ucontext_t can just be typedef'd to thread_context_info
for those I'll need to implement some memcpy functions for kernel->usermode and usermode->kernel (I plan on implementing KPTI, so I can't directly do a memcpy)
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)
maybe that's not worth the effort
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
*4M
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
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)
I will 🙂
you'll report the bug, right
yes 
I'm sure it's stable enough
this check ```c
if (ctx.frame.rip >= OBOS_KERNEL_ADDRESS_SPACE_BASE || frame->rsp >= OBOS_KERNEL_ADDRESS_SPACE_BASE)
return;
also you want to clear iopl not set it?
shi I did
oh ye
I coulda sworn I had a good reason to put that there
also also you check it after you try to copy
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
this still lets the user set iopl=3 on their own?
oh yeah
I just need to add the xrstor to the function
or fxrstor
depends
but anyway
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;
imagine actually following posix O_O
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

Why not, it's such a simple thing to do
Yes for both
ok
eh, you don't really NEED to do that
also why are you OR-ing 3 on the segment values
thats not how you set CPL, what does it do
what's RPL?
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
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
nope
i wanna get a semi decent Mm and Ps first
makes sense how you'd make that mistake
(memory manager, process system)
true
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
thanks :)
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
with how it looks, I can probably start
researching them today
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
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;```
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
I might be able to start today (within the next 3-4 hours) if they're simple enough.
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
hope u actually rewrite the vmm instead of the entirety of the kernel
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
noooooo
instead of rewriting the VMM
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
any help on how to unfuck this is much appreciated
might go for a bit to read wininternals
and books about NT design
looks fun to read 
dam
why it so expensive O_O
would cost me $150 for part1+2
maybe I should find older things
sorry im not gonna pay 150$ for a pdf
fr
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?
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
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"
Yeah the only annoying thing is the watermark
But why pay when there's stuff like massgrave
Well you usually pay because that's the law, whether you agree with it or not
Microsoft doesn't really care if you pay or not
you can also just transfer the license from an old pc that you bought
My point wasn't about microsoft getting paid.
I've only seen one entity in my country pay for windows
which is schools
not a single individual that I've seen has paid for windows
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.
We had free web Office too while I was in high school
its just MS doing adobe moment
get your sw everywhere so it becomes the standard
and then people use it when they grow up
My school gave all the students free adobe licences last year.
what about the authors of the book
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

what happened
I'm getting pretty tired after school and simply cannot find the time
I probably will when I get time
I have some time rn
and I have found a solution for this
I'll explain it in a bit
nice
SO BASICALLY
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
then to swap in/out
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;
};```
to page out, I simply check if the page was modified since the last swap out
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
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
genius
obos will have the best kernel
please dont rewrite the kernel
i actually wanna see OBOS finished
😭
I won't
thank you
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```
yk you could just
return !in_range(whatever)
you cannot for rb trees
what
it needs the distinction between less and greater
you convert a bool to an int
in the ternary statement
you can literally just return the bool
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);
}```
I thought you meant I should do this
what for?
well I'm changing this giant struct to represent a range of pages
and I'm using an rb-tree to store the ranges
so ur making folios or is it still virtual memory related
what's folios
still vmem related
f
wait until u learn about vm_area
your struct page is basically this https://litux.nl/mirror/kerneldevelopment/0672327201/ch14lev1sec2.html
how many bytes is that, about 128?
yes
yeah, except it's for a single page
and this exists for every virtually mapped page
i have 64 (well, 56, but padded on 64-bit platforms; 32 on 32-bit platforms)
Lol
Me when my entire ram is consumed by vmm overhead
I feel like you could put a bunch of those fields inside unions
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
yeah that's essentially what I do too
so whats the approximate byte overhead for a single anon page mapping
worst case is 64 bytes on the page struct, 1 page on the working set list, 64? bytes on the map entry, well, i could go on for a while with the constant overheads
i see
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
whats a prototype page table
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
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
Do you know how other kernels solve this?
it is basically just a particular way of implementing something that first started in mach with its concept of memory objects
I see
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
Interesting
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
i think they're useful to have when testing on real hardware
so i wasted some time implementing polled send/receive for e1000 in case i need to debug my kernel on my laptop
until I find the time to fix it
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
it's not going to be used
you're giving me flashbacks
hahaha
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
i would be storing it in working set list entries
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
i know the feeling
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)
how many times by now?!
I am starting to think that you secretly are sadistic and enjoy giving yourself pain
this would be the third revision of the vmm
ahhh
(this is the fifth rewrite btw)
(fourth was a disaster)
(third was just not designed well)
(2nd/1st were shit)
I suggest to start an entire channel in here just for people to try out your curse, and maybe help you
hah
I have rewritten my bootloader like 20 times
lol
.!t limine
yessir
#bootloaders message
well gl with your btldr
after vmm rewrite is TTYs
so in a couple weeks bcuz school
I just skipped school because I liked it so much
modern problems require modern (bad) solutions
please kids don't try this at home
only reason so for me is that I miss being at school with all the people
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
you are quite wrong here
you see, everything is optional, except the last in the list
the loader will support x86-64 relocations for now
maybe m68k soon
and x86
since no one uses msvc I'll be forcing gcc
extensions
does msvc even support m68k?
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
and there will also be chown and chmod cbs which take in vnodes
what the fuck is a CB
ah
CBT without the T
I hate this 
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
lgtm
but how would I figure out the swap allocation id for a swapped out page
when it's being swapped in once again
(basically that thing just represents allocated space in the swapfile)
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
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);```
hi
hello
so this would become
what are you up to?
that
fixing my vmm
whats wrong with it?
currently there's a big design flaw
where each virtual page
is stored in a 128-byte struct
causing very large vmm overhead
how much overhead we talkin?
also do you dev on windows or linux?
yay a fellow linux freedom figher
8M overhead
for 1G allocated
8 megabytes, thats a LOT, so is this your malloc and free stuff?
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
OH so this is mapping psyical memory to virtual right?
and many other duties
as the very base level, yes
and it has a big overhead due to what?
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
so what part of the code do you suspect is causing issues?
but the thing is, the entire thing depends on that one struct
have you tried chatgpt /j
so I need to basically rewrite everything
oh, well at that porint just reimplement paging
chatgpt stoobid
that's many many work
to rewrite all
in the vmm
well not ALL but more like the struct, so something in it is causing an 8MB overhead, correct?
and a big misconception in beginners is that the VMM just deals with mapping pages
that's if you allocated 1G
for each mapped page, it's about a 128-byte overhead
and within that it grows I suppose?
wdym?
I mean the overhead grows
that 128 byte overhead (not much) grows into a WAY bigger 8MB overhead which would grow to become a bigger and bigger issue
is it not as big of an overhead or is it way bigger?
still thats WAY better than 8MB, I mean windows has some overhead too lemme check it
certainly not as much overhead as this
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
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
104 byte overhead with 1 TERABYTE of ram
104 bytes overhead
more like virtual address space
the kernel doesn't hand out ram like it's nothin'
okay that makes more sense lol
the program thinks it gets 1 TiB
but in reality
the kernel doesn't "commit" the memory until it's touched
so its not actually used until its asked for
indeed
you can also reserve virtual address space
if you do that
it's unmapped
but nothing can reallocate it
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?
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
for me I just pass free the pointer and it does its magic
yeah same
-# I probably forget to free a bunch of stuff
-# 20M of memory committed? more like 20M memory leaked
for me the kernel API is also the userspace API lol, since its all going to be in kernel mode because im dumb
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
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
true, on the other hand, who can hack an OS when they cannot even understand the API!
lmao
not even the dev understands the API, thats how bad my code is
only thing that runs in kernel mode in my kernel is the kernel ofc and the kernel modules (drivers)
so you have a driver system already?
yes
what about apps?
also planning on making a library for that
not there yet, or working on it?
are the kernel modules loaded from disk?
they can be
so it works?
yes
so how do kernel modules work?
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
so its a program more or less?
when it's loaded
you could say that
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
kinda like templeOS, loaded at run time, but in this case not compiled at run time
and what its name is (optional)
and also a table of functions for the kernel to call when it wants somethin from the driver
well idk why it'd be compiled at runtime
in temple OS the entire OS is just JIT

gn
marker
depending on your goals this could be all it does
welcome to linux land 😎
it's using bits 64 instead of 16
Ok
(i have an intel 4004 as a cpu)
Ok
Will work on this some more in a tiny bit
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
first thing it should do is page fault executing nullptr
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
obos without the oberrow curse is like an angel without its wings
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)))
hmm
I think I should just return a memcmp
or smth like that
hmm
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
the freeing function should be implemented for the most part

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
or CoW support
or file mapping
or rather I only have one half of them
when new obos features
nice
also brainfuck interpreter
bro is putting a brainfuck interpreter in obos
write kernel in bf

someone has to have written a gcc backend for bf
to output bf from C
or smth
someone did make a frontend
that's insanely hard to do tho
yea I thought about it a bit
so never? 
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
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
unless
wait nvm
I was in the dynamic symbol table of the driver
new stuff added to the panic screen
namely the driver bases
my kernel panic is better then ur kernel panic
and stack trace

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
lol
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
Where do you get symbol names from?
oh because you have modules
yea
While to write page
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
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
You cant dump much in it since qr can barely store anything
2953 bytes is the maximum size of a single QR code with a module size of 177×177 and low error correction.
for this I meant on panic
to output a qr code with the panic info
you can still fit like
maybe a stack dump
kernel version + traceback + format args for panic + panic id
yeah
as a link to a website which reports the crash :^)
I could probably just dump the info printfed on panic to the qr code
except for the ascii art ofc
No no it must be included as well
Dump the entire framebuffer as qr
Just tell the user to take a picture and upload it to some website 
made some small changes
waiiit
that crash could be because of an allocator bug
shit
TODO:
the oberrow curse strikes again
TODO: make it not
don't worry about it
I won't sue, promise
you dont really need an rbtree unless you load symbols from the kernel file
i use a separate symbol array ordered by address so i can simply do a binary search
Once I get modules working in astral the first module I should do is fireworks test
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
tbh there's a lot of noise there - how much of that is helpful in diagnosing why the system crashed?
Depends on where you are, on qemu most of it can be found out using gdb
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
eh i find the gpr state kind of useless
Fair
the ip, sp and cr2 sure but the other registers aren't terribly useful
The info about the build is there for bug reports
The gpr state isn't part of the panic function itself btw
I just dump it in the format string for cpu exceptions
though to be fair linux also does a gpr dump 
I guess thats why its called Linux and not Winux
i mean not really
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
I'm writing my own based off of boron fireworks
wasn't mintia2 in it's early development stage?
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
I now continue making fireworks
well if cr2 is like 0xfefefefefe and RAX is the same, you know the problem is on accessing rax
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
I mean you could use objdump to try and figure out how rax got that way
I've done that a couple times
rather
what rax is supposed to be
anyway another reason to print the gprs is to make panic scary
just found a really old screenshot
of obos
true
damn this test might kill the kernel
// Explode it!
// This spawns many, many threads! Cause why not, right?!
int PartCount = Rand() % 100 + 100```
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
thats a beautiful #when-your-os-goes-crazy moment