#Boron (not vibecoded)

1 messages · Page 2 of 1

mossy thicket
#

i860 had the same issue

#

caches were VIVT so page table lookup was uncached

uncut lance
#

this is one for the rest of us targeting the 68ks to keep in mind, since we all test almost all the time in qemu which is 68040

#

well, not that qemu would emulate this either way

glass heart
#

what does XIXT stand for? (like PIPT, VIVT etc)

mossy thicket
#

x-indexed x-tagged

uncut lance
glass heart
#

ah

mossy thicket
#

theres also VIPT

glass heart
#

but what is tagging in this case?

mossy thicket
#

and PIVT

mossy thicket
#

so like

uncut lance
#

aarch64 i wondered initially if my big problems trere could be a result of aliased cache lines as i think both the d and i cache can be virtually indexed

mossy thicket
#

say you have virtual address 0x1234 and its mapped to physical address 0x3242, and its a VIPT cache with 16 cache lines that are each a byte, youd index it with like 0x1234 & 0xF = 4 and then when youve looked up cache line 4 you compare the tag with physical address 0x3242 to make sure it has the data youre looking for

uncut lance
#

but they don't permit aliases

mossy thicket
#

if it does you got it, otherwise its a miss and you replace cache line 4 with the data you want

#

in a VIPT cache the tag is just the physical address of the cache line basically

#

the reason youd do this is so that you can look up the cache and TLB in parallel

#

by the time the cache lookup is done, the TLB lookup has also completed and the physical address is available for you to compare with the cache line tag

#

in PIPT caches you have to wait fo rthe TLB lookup to complete before you can look up the cache

#

VIPT caches have "aliasing" issues if they are larger than a page size

#

because imagine you have two neighboring virtual pages

#

which are both mapped to the same page frame

#

and you access cache line 0 in each

#

you now have two cache lines which are for the same physical data

#

which is bad!

#

you will write to one and then be really confused why the other didnt update

#

this isnt possible if the VIPT cache is a page size or smaller

#

but theres another way to get them larger which is to increase the number of "ways" for each set

#

basically you have the virtual index select a "set" of cache lines

#

and any line from that set can match with the physical tag

#

so if you have a 2-way VIPT cache and 4k page size you can get a 8k VIPT cache without aliasing issues

#

at the expense of extra circuitry

#

thats why modern processor L1 caches are all like 32-way

#

because they are VIPT and want to avoid aliasing

#

so they only have like a page worth of cache sets and each set has 32 lines so the cache can be like 32x a page size or whatever

#

that was a tangent but hopefully informative.

#

PIPT is nice because you can arbitrarily specify cache parameters and never worry about aliasing or anything, at the expense of serializing it with the TLB lookup; VIVT is nice because you dont have to look up the TLB at all on a cache hit! but at the expense of nearly unresolvable problems with aliasing that are so evil its considered the province of shitty little microcontrollers with special purpose operating systems

#

dont ask what PIVT is for apparently it exists but i cant imagine why

#

Wikipedia says that MIPS r6000 is the only known implementation, and gives the extremely esoteric reason: Even a TLB would be too large to implement in Emitter-Coupled Logic, so they implement a TLB slice to just translate enough bits for a physical index. Given that limitation, PIPT and VIPT were not options, and they decided to go PIVT instead of VIVT.

#

dont know what that means

glass heart
#

I dont know what I should work on

#

There's a lot to work on

#

Maybe I should start on some kind of tmpfs system?

glass heart
#

damn. I really don't know what to work on

#

maybe tomorrow I'll figure it out

#

im not sure if this is the right time to start on this

#

but i think it might be time to write a page cache data structure (cache control block) for FCBs

glass heart
#

im trying to implement the cache control block and im giving it a very hard think

#

but im not sure how it will integrate with the IO system

#

other than, like, each FCB having a cache block if caching is enabled, and IoRead/IoWriteFile using it preferentially

glass heart
#

i think i will take a break

#

hopefully in the meantime i can figure out what i should do and how i should do it

glass heart
#
0xffff800000000000 --- HHDM Area
0xffffa00000000000 --- Page Frame Database
0xffffa08000000000 --- Pool Space
0xffffa10000000000 --- Recursive Paging Space
0xfffff00000000000 --- Kernel Module Loader Base Address
0xffffffff80000000 --- -2 GiB. Kernel loaded around here
#

these are the currently used memory regions

#

for my reference

glass heart
glass heart
cedar mulch
#

you were time travelling

glass heart
#

nanoshell64 was around at the time but it didn't have file headers like this

glass heart
#

i was thinking of partition objects and i thought that maybe they can be generalized

#

partition objects as in, partition of a disk volume

#

they wouldn't have a cache of their own, instead passing all IO (cached or not) through to the disk, with the specified offset

echo saffron
#

that’s exactly how everyone (or at least me) does it ;p

glass heart
glass heart
#

ok i implemented at least a little bit of the cache control block

#

that being the entry retrieval function

#

tomorrow i'd like to add a function called BSTATUS ObDuplicateHandle(PHANDLE OutHandle, HANDLE Handle);

#

which duplicates a handle

#

and continue work on the MM

glass heart
#

bruh why the fuck is the IPL randomly >=IPL_DPC at page fault time???

#

I thought it might have something to do with the race condition I recently found with the KeGetCurrentThread func

#

i also found a deadlock

#

yeah deadlock

#

one of them was interrupted while trying to do a tlb shootdown

#

this is a classic deadlock

#

thread a locks a then b

#

thread b locks b then a

glass heart
#

sigh

#

why the fuck is PRCB 1's Ipl being set to IPL_DPC

#

i bet theres a bug in my raiseipl

#

ok there is

#

hows it possible???!

#

the TOCTTOU that i discovered yesterday is materializing in more places than one now!

#

are you fucking kidding me

#

oh i was freeing the stack with dispatcher lock held

#

L

#

so basically i need to rearchitect a lot of things

#

frankly before continuing with the MM i should flesh out PS

#

and its management of threads

#

have a thread be the reaper of threads & shit

#

well those are fixed now..

#

tomorrow methinks I will start working on Ps

#

and yank out all the Mm references from Ke

glass heart
#

In my ps/2 driver, in my init function, I have a hack

#

specifically this one

#

it might be superfluous now as that test rig doesnt seem to do that

#

this is what it looks like in nanoshell

#

and this is what it looked like in nanoshell's predecessor, confusingly also named nanoshell

primal gorge
#

interesting - btw I like the style of boron's codebase.

noble sphinx
#

Same

glass heart
#

thanks

glass heart
#

Ok I've done a bunch of cleanup work

#

Now instead of IA32_KERNEL_GS_BASE which I was actually using erroneously, I'm using IA32_GS_BASE

#

I removed the segment reloading from the interrupt exit/enter and context switch in/out code

#

and I've inlined the current thread and current IPL operations into single GS relative accesses

#

also inlined 3 intrinsics which for some reason were regular functions and have thrown me off before: KeWaitForNextInterrupt, KeSpinningHint and KeInvalidatePage

#

I should consider working on Ps now

glass heart
#

please excuse my apparent disappearance

#

on another note,

#

bug!

#

how is 0x1 getting in the handle table?

#

its supposed to be overwritten

#

oh I was writing the wrong index

glass heart
#

sorted by length

slow fractal
#

KiTestTrap

glass heart
#
#1
DbgLookUpRoutineNameByAddressExact
ObpRemoveObjectFromDirectoryLocked
ObpNormalizeParentDirectoryAndName
#2
MmGetSmallestSlabSizeThatFitsSize
#3
ExiDisposeCopiedObjectAttributes
MiGetUserDataFromPoolSpaceHandle (used to be the longest last time I checked)
#

pretty cool

glass heart
#

they're called "test" because they WERE tests when I refactored my interrupt handling system

glass heart
#

some more changes to boron

#

i've removed the old thread detachment system (you could detach a thread and it'd be automatically cleaned up by the system) in favor of the process manager

#

you can call PsCreateSystemThread and it features automatic cleanup of the thread if you simply close the handle

#

aint that cool?

#

this is once again lifted from NT

#

with that, very little of the kernel core actually "calls up" into the memory manager anymore

#

just the init stuff basically

glass heart
#

successfully ported boron's fireworks test to m*ntia2

warm imp
#

@glass heart can I ask what is your relation with Mintia? Not only because I recall you mentioning it a few times, like above, but also because to me it seems that you are trying to also use NT concepts, and not only Unix

glass heart
#

yes I do regularly talk in hyenasky's server

#

and I have read mintia a little bit

#

does this answer your question?

warm imp
#

Mintia has a server right? Or rather it is a xr station server

cedar mulch
#

it does

glass heart
warm imp
#

is it possible for you to send it to me in here or private?

#

the link

glass heart
#

yea sure

warm imp
#

thx!

noble sphinx
glass heart
#

yeah

noble sphinx
#

Nice

glass heart
#

decently fast I think

#

this is 7 or 8 processors running at like 25 mhz doing this stuff

#

more impressive than my own

noble sphinx
#

If only it was available on a real architecture

glass heart
#

fixed a bug today

#

a really nasty bug

#

it turns out that the expirytick key might collide when setting a timer

#

so the later timer is just dropped

#

the firework test once again revealed this

#

i didnt think much of it but this bug is insidious as fuck

#

my current fix is to just add 1 until the function can add it, but i'm thinking of a more proper fix

keen breach
#

looks cool

glass heart
#

apologies for my lack of progress

#

xd

#

i've been busy at uni + working on something different

glass heart
glass heart
#

the biggest roadblock that I have, i feel, is the memory manager. specifically i'd like to have some relatively advanced features such as file mapping, symmetric/asymmetric CoW and paging

cedar mulch
#

I mean that's not too hard

#

My vmm supports those

#

And is only ~3k loc

#

Also never forget dirty and standby lists

slow fractal
#

My vmm supports those and its like 1k loc

#

Theyre pretty simple

cedar mulch
#

*tho

#

Which is one of the features he wanted

slow fractal
#

I probably could implement it if I wanted (lie)

#

I didnt see the paging 💀

cedar mulch
#

Tbh

glass heart
#

part of the reason I'm still not working on it is that I've been making an NES game but there's that reason too

glass heart
#

eh maybe I don't need swapping initially but I should design with it in mind

scenic bronze
echo saffron
#

daily reminder that loc isn't a good measure of anything

noble sphinx
#

empty lines are the way to measure code quality meme

fast prism
#

just found out about this, good luck on it :3

glass heart
#

‼️

glass heart
#

i mentioned this and ill mention it again. when i decide i dont want to work on my NES game anymore i will start working on this again

#

but yeah

#

uni, and my nes game, have been draining most of my time

glass heart
fast prism
glass heart
#

lmfao

noble sphinx
cedar mulch
#

Boron is dead nooo

#

@glass heart nooo

glass heart
#

I'll come back to it someday

#

When I'm motivated to learn how to write a proper VMM

glass heart
#

does anyone have any references for NT like vmms that I can bunch up so I can read them in the future

#

I still haven't decided to come back to this project, but I'll give continuing it a shot someday this year

fringe cedar
#

so I'm passing this recommendation along to you

glass heart
#

so i got a copy of what makes it page

#

at least, so it seems

#

i hope that that book will help out

glass heart
#

oh damn

#

i saw like 2 typos so far

#

20.1: "VAD affress"

fringe cedar
#

The man didn't have an editor

#

he just REd the Windows 7 memory manager and wrote a book about it in ms word with the default formatting

glass heart
#

ah so this is reverse engineering work

#

well hes probably smarter, and definitely more experienced, than I am

glass heart
#

I actually did some work on boron again today! (only a small amount)

#

Right now I'm working on the memory manager

#

Planning how the main system calls (system services) are going to be implemented

primal gorge
#

nice to see boron continuing

glass heart
#

mm progress is actually kind of going now

#

i got anonymous commit memory working (so basically demand paging)

#

next is decommitting and then integrating them into some simple APIs

#

and then eventually memory mapped file I/O

#

i'll have a basic vm system working in no time okay no it's going to take a while still

#

but its going so far

glass heart
#

people might lynch me for this but i kinda wanted to see how Windows would handle the case where you reserve memory with VirtualAlloc MEM_RESERVE | MEM_COMMIT and then decommit the middle of that range

#

checking the PTE for this process at those addresses reveals that there is actually no PDE allocated for the middle of that range

#

however, once I run VirtualFree, that's when the PTE appears

#

so they literally allocate memory when you decommit a region

#

how nonsensical is that?

#

does this make more sense than allocating all of the page mapping levels (PDs on x86 32) when passing MEM_RESERVE | MEM_COMMIT

#

(note for the naysayers: VirtualAlloc is basically just a Win32ified NtAllocateVirtualMemory, likewise with VirtualFree)

#

@mossy thicket i don't know if you handle memory reservation in a similar enough fashion in mintia1/2 but i would like your input for this

glass heart
#

tbh looking at your plans you might thing that this whole entire thing sucks because your new plan is to have fully disposable page tables

#

also i bet they improved on this substantially until windows 11

mossy thicket
mossy thicket
#

And this isn't enough info to tell me what's really going on here tbh

glass heart
#

Then I decommit half of it in the middle

#

Notice that I don't actually access any of it so nothing is allocated

#

Before I do the VirtualFree though I run the command !pte on the start of the allocated region and the start of the region to deallocate

#

The latter PTE doesn't even have a PDE associated with it.

#

However, after running VirtualFree, suddenly that latter address' PTE exists (because its PDE was created) and it's marked decommitted

#

What virtualalloc with MEM_RESERVE | MEM_COMMIT does is it creates the VAD but doesn't actually mark any of the PTEs as "committed"; they're left at 0 and the flag within the VAD called "MemCommit" is set to 1

#

So the TL;DR of it all is that VirtualFree, when called inside a VAD that was completely reserved at creation (which doesn't initialize any PTEs at all), actually allocates PTs to place the "decommitted" flag in the PTEs corresponding to that region of memory that got freed

glass heart
#

Here's the relevant VAD

#

The start VA of the VAD has a PDE associated with it (because other things are mapped within the range vovered by the PDE)

#

the VAD doesn't change at all after VirtualFree however

#

but it does allocate the PDEs

glass heart
glass heart
#

well in any case if Windows XP behaves like that it makes me less ashamed to do something similar

glass heart
#

work on boron is slowly progressing

#

some simple tests work

#

i should do more complicated tests

#

maybe i'll keep working on it for a while instead of chiming in now and giving up on it in 5 days. but so far i think i have anonymous private memory working (ranges of memory can be reserved, and things can be committed into those ranges, and it works with demand paging too)

glass heart
#

dont you just love the win32 API sometimes

#
  • MapViewOfFile
  • MapViewOfFile2
  • MapViewOfFile3
  • MapViewOfFileNuma
  • MapViewOfFileNuma2
  • MapViewOfFileEx
  • MapViewOfFileExNuma
  • MapViewOfFileFromApp
  • MapViewOfFile3FromApp
#
  • UnmapViewOfFile
  • UnmapViewOfFile2
  • UnmapViewOfFileEx
#
  • VirtualAlloc
  • VirtualAlloc2
  • VirtualAllocEx
  • VirtualAllocExNuma
wide depot
#

oof, file, file_2, file_2_new, etc

noble sphinx
undone sky
#

lol

#

yes

glass heart
#

the anonymous memory APIs are almost complete

#

soon i should begin working on file backed memory mapping support

glass heart
#

for boron i kinda wanna expose some files already but i dont wanna build a file system driver so im going to add support for the boot files (ones you add to limine's cmd line) to be exposed

#

now the vm APIs I plan on exposing to userspace dont really map well to mmap

#

which sucks 😦

#

i might add some mmap support functions though because with only those APIs it seems like a pain to implement

placid sail
#

aside from the windows store ones, those are strange

placid sail
glass heart
#

tarfs not yet

placid sail
#

parsing tar files even with error handling is like 100 lines

#

its worth it to make getting test data into your os easier imo

glass heart
#

i know lol

#

i have such a thing in nanoshell

#

it's funny

#

nanoshell vs boron will be a lot like windows 9x vs windows nt

#

except my OSes will be both somewhat worse than their respective windows

glass heart
#

from a glance, and by glance I mean a small test, the APIs OSAllocateVirtualMemory and OSFreeVirtualMemory seem to work

#

the page fault performance is... not great, it seems. but i'll work on that at some point

#

(it takes about half a second to fault in 40 MB of pages or 9766 pages)

#

(which is kinda trash)

#

tomorrow or saturday i will start working on file backed memory aka memory mapped files

glass heart
#

also im thinking about the best time to deallocate empty PTEs and I think it's when a VAD is being freed

glass heart
#

note: between the time when the VAD is removed from the VAD list and when it's added to the free list

#

there are three locks that operate in total, im not sure if its good design

#

theres the address space lock which guards, you guessed it, the address space (page tables). then theres the VAD list which guards the VADs. and then theres the free list lock which guards the free lists

#

so freeing a VAD would behave something like this. first erase the VAD from the VAD list (holding only the VAD list lock). then start erasing the PTEs covered by this VAD, guarded using the address space lock. also clear unused PTs. then issue a TLB shootdown request. and finally add the free range into the free list.

#

each segment of memory is under custody of either a VAD or a free list segment so if it's part of neither, nobody can touch it (currently)

#

except for threads that fault on that memory. they'll end up in the page fault handler and lock the address space lock before doing anything

#

when they finally reach the guarded region they'll see only empty/nonexistent PTEs as far as the eye can see

#

and subsequently raise an access violation status

#

also im thinking to have a mutex or something for each VAD so I don't have to hold the VAD list mutex while modifying the VAD

#

although this could cause issues if the VAD's place in the tree needs to be modified by a rebalance

#

maybe not

glass heart
#

the amount of physical pages available before and after my test is the same

#

okay i said it too soon

#

what is this 😭

#

i know its a failure in the access of a goddamn recursive paging area

#

okay its fixed

glass heart
#

^ yay

#

now im thinking

#

where should i put the page cache

#

should i associate it with the fcb

#

i think so

#

should it be like an ext2 "direct and indirect" type structure? as in, the first N pages are directly indexed and then no longer?

#

if the pages arent mapped in but someone calls ReadFile how should i handle caching

#

should i map small views of the file to make caching fast or

#

theres a lot of design actually

noble sphinx
#

btw any plans for an aml interpreter in boron

glass heart
#

in the far future i would like to import uacpi

noble sphinx
#

cool

glass heart
#

I might already be able to but I'd rather wait a bit

noble sphinx
#

i was curious if u would roll your own since u have tons of acpi code for table parsing

glass heart
#

nah

#

that code is mainly there to detect the HPET, if I remember correctly

#

it may be replaced with uACPI code if it simplifies the code

noble sphinx
#

yeah it can be replaced with a one liner if u use uacpi

#

uacpi also has a header with all those tables

#

also your pm timer code can be replaced with uacpi_map_gas + uacpi_gas_read_mapped etc

glass heart
#

i had an idea that i'd be placing it in a different uacpi.sys module tbh, so integration with the hal would be unlikely unless i design around it

#

maybe i can make uacpi.sys load right after hal.sys instead of anytime later

noble sphinx
#

you can depend on acpi.sys for pm timer and stuff

glass heart
#

Currently drivers can't link with each other

noble sphinx
#

i mean nt drivers dont link to each other usually right

mossy thicket
#

they do regularly

noble sphinx
#

they have callbacks or whatever

mossy thicket
#

many of the NT .sys files are just dynamic libraries in kernel space

#

linked to by other modules

noble sphinx
#

well acpi in particular

#

i think it exposes 99999 different ioctls

mossy thicket
#

i will probably just embed uacpi in my kernel binary

#

when i get there

#

it will go in the "integral system driver" for amd64 pc platform

noble sphinx
#

acpi is usually like a very core driver so it makes sense

#

and u need it at early boot to do numa prep

mossy thicket
#

i stopped having the HAL be a separate binary so it didnt make sense for those to be either (since kernel binaries are already platform-dependent) so it all just goes in the kernel now

noble sphinx
#

how far away from the amd64 port are we

mossy thicket
#

a year

#

idk

noble sphinx
#

damn

glass heart
#

my plan for the hal was that I'd use it for different raspberry pi models or something

mossy thicket
#

mintia2 is still pretty early

glass heart
#

like i could port to the pi 3 in 2026 and then to the pi 4 in 2027

#

idk

#

otherwise i would probably have built it into the kernel

glass heart
#

i guess i gotta implement that in my OS

#

or maybe not

uncut lance
#

mintia2 is doing this already

glass heart
#

it optimizes small files while also allowing for larger files

glass heart
mossy thicket
glass heart
#

cause i didnt know will reached that part of his design

mossy thicket
#

i havent really

#

i just decided on that a long time ago

glass heart
#

i think that might be where i got it from actually

uncut lance
glass heart
#

tbh i took a long break since september 2024 and everything is exactly as i left it

#

so theres little bits of a premature design that i have to look at and decide what to keep

#

i think that part is fine

#

but anyway i had some questions about file caching earlier

glass heart
mossy thicket
#

to be exact i put it in a "cache info block" which only gets allocated when you actually read/write a file

#

which saves a ton of space in FCBs that were only created to like query a file

#

but its logically just part of the FCB

#

i think it does have a lifetime independent of the FCB in one weird instance involving the lazy writer

#

but i forget details

glass heart
#

i see

#

so it makes sense to associate it with the fcb

uncut lance
#

i have discrete vm objects but they have an unpleasant relationship with vnodes where their lifetime is basically tied to their vnode and they make refcount adjustments to ensure this (++refcmt on furst dirt page, -- on last dirty page written)

glass heart
#

i struggled to remember what file objects were used for but i remember now

glass heart
mossy thicket
#

yeah idk why it does that i just map the file object directly

glass heart
#

like you cant map views of files, you have to create a section of that file first

#

is that somewhat analogous to your "vm objects"?

mossy thicket
#

so if you just flush whats there then you can purge and delete safely

uncut lance
mossy thicket
#

if youre worried about IO failures and you want dirty data to stay in memory if you fail to write it out at deletion time, you could enqueue this to a worker thread and each time the flush fails, it just logs this and delays trying again for like 5 seconds, and it only purges and deletes once it succeeds

uncut lance
#

they are some kind of innovation particular to NT or maybe to VMS or some other predecessor, but not really present in mach tradition which influenced my model

mossy thicket
#

honestly it seems mostly like a weird mica-ism that was meant to support mica virtual memory features that NT didnt even end up having or ended up doing differently

uncut lance
#

they have some use in executable mapping but that's all i know

mossy thicket
#

so i consider all that stuff to be probably just redundant and strange

#

bc i never encountered even a hint of a need for it despite doing most stuff in an NTy way

glass heart
#

let me guess, they didn't want to define two other syscalls

#

/j

mossy thicket
#

one of the mica workbook drafts the chm digitized for me goes into extreme detail in the virtual memory workings

#

and i think it elucidated the original intent of some of these things

#

but i dont remember

#

maybe here

glass heart
#

what do i do

#

do i just keep the pages in standby in the page cache and copy from the page cache directly

mossy thicket
#

i have a component called the viewcache

#

which caches mapped views of files

glass heart
#

(this would allow them to get purged if necessary but it seems inefficient)

mossy thicket
#

pages stay faulted into the system working set until trimmed

#

so repeated cached file IO just becomes a straight memcpy

glass heart
#

how does it operate though, how big are the mapped views of files? when are they mapped? what if you fill the space theyre designed to take?

mossy thicket
#

u can read the code

glass heart
#

if i wanted to read the code i would probably have already read the code

mossy thicket
#

i guess youll never know then

glass heart
#

bu sure

#

i guess ill take a look

glass heart
#

what the fuck

#

so i found a heisenbug

#

it doesnt trigger when the debug is attached but it consistently triggers without it?!

#

and this dumb fucking stack trace

#

this all started because i was running out of memory for some reason even though this test shouldnt cause any memory to be allocated without freeing it

#

okay so i managed to coerce it to proceed with gdb (it was getting stuck in two spin loops)

#

oh thats in the kernel

#

maybe it's a function within an init page

#

yeah

#

why the fuck is this in init

#

okay finally

#

see i love this stack trace format ❤️

#

but fuck

#

maybe i have a memory leak in the MDL stuff

#

now it looks like ive hit yet another stupid bug

#

whys it failing to acquire the tlbs lock

#

the other threads arent in a fucking tlb shootdown

mossy thicket
#

be calm. all will be revealed.

glass heart
#

im going to solve it eventually

#

all i wanted to debug was a memory leak though why did it have to throw this conundrum...

#

okay tomorrow time

glass heart
#

now that my journey of porting a program across 32 years of 32-bit Windows is complete, I have no excuse

#

I will get memory mapped files working

#

I already got started in some unpushed commits

glass heart
#

this only happens when the system is given critically low memory (like 4.2 megabytes)

glass heart
#

it's not. I mentioned another project I was working on that involved being ported to old Windows versions

#

Not this one

#

Although you could say its code style is inspired from Windows..

mossy thicket
#

relatively famous (among a small group of weird nerds) string that seems to have been a debug print during initial bringup of the NT kernel back in 1989

#

nah theyre like 19 or something i think

mossy thicket
#

also im not the author by the way im just answering questions ik the answer to, since he's offline

#

its just cool because it may be one of the earliest things the windows kernel ever spaketh

glass heart
#

a friend asked me to print this out and only told me "I found this in an early beta of Windows NT"

#

at the time I wasn't exactly aware of the fact it's part of leaked code

#

but i guess that's where he got it from

#

I'm not

fast prism
glass heart
#

progress update: I can now read from an NVMe drive using cached memory!

glass heart
#

here is a dump of the first 1kb of the nvme file

#

and now here is the read operation

#

note: the offset is 20

#

and only one actual NVMe operation! (even though the exact same test is performed 3 times! the rest of the times the data is mapped in from the page cache)

#

now writes don't work right now and it'll be a lot of effort to get them working as well

#

with the modified page writer and things like that

#

one thing i will provide for mapped files/devices is the ability to have them directly backed by physical memory

#

(this is pretty much only useful for framebuffer type devices or an in memory file system)

#

the MM will recognize that this is possible and just bypass the whole cache machinery

#

this commit implements everything

#

technically this and CoW is all I need to start implementing userspace

#

(and of course some code to setup an in memory fs, probably from a tar)

glass heart
#

similar idea yeah

finite flint
#

though using it for a framebuffer device or similar differs quite a bit from how Linux does it (Linux has VM_PFNMAP for that type of mapping)

#

Now what I don't understand is why this would be needed for tmpfs-like filesystems, as those can simply have their backing storage be the page cache itself, no?

glass heart
#

instead of having the tmpfs files be backed by memory and bypassing the cache machinery, let's use the cache machinery to keep track of the pages and just keep those pages permanently mapped

finite flint
#

yup, exactly

#

that's kind of what Linux does

glass heart
#

it's just a matter of which kind of machinery i use, either the direct map one or the page cache one

finite flint
#

or you make them the same meme

#

e.g. Linux can have struct pages for direct access memory

glass heart
#

non RAM pages aren't opted in into the page frame database in boron currently

#

this might change but that's how it is right now

glass heart
#

Boron

#

(old title: "Work on The Boron Operating System")

glass heart
#

@uncut lance @primal gorge @fast prism @mossy thicket

terse mantleBOT
#
Anti-spam Message

(ping spam) Possible spam detected for user: iProgramInCpp. Please contact a moderator to be unmuted.

glass heart
#

i should probably not do that again sorry

#

thanks fadanoid

fast prism
glass heart
uncut lance
#

i'm also happy to be

primal gorge
#

Lol, yeah me too

#

Congrats on the progress

glass heart
#

thank you!

glass heart
#

it turns out i am dealing with a page frame reference leak

#

leading to pages not being purged from the standby list when they should under (simulated) memory pressure

glass heart
#

one of the reasons is that i was using __atomic_clear which for some weird ass reason only operates on bools and chars but i was trying to use it on a uint64_t

#

the other is that i was using a stale pointer to a pte and writing to it, when mapping newly loaded pages, inadvertently writing to something completely unrelated

#

it works great now

#

these are only the first steps but boy is it satisfying for everything to tie together

mossy thicket
glass heart
#

kk, so I will not ping you when anything major happens

glass heart
#

a big problem: I want borondll to map things into the processes it creates. However, my system calls aren't designed with an additional Process parameter and they use recursive PTEs heavily

#

So I was thinking that the system calls would temporarily switch into a process' address space and detach afterwards

#

I already have functions to pull this off however I'm not sure how code decayed they are

#

Some more things I might need for user space in Boron include a file system that includes the boron layer DLL, an exposure of the screen and debug consoles as a file, and a way to create a shared library that is actually fixed at an address

#

(Although thinking about it, the lattermost item might not be necessary)

#

(I'd be avoiding performing relocations in the kernel though)

#

What I'm thinking for the OS startup: first, the kernel starts up, then a new process is created and borondll (actually will be called libboron.so) is mapped into it. Then, that new process is given a thread which jumps to user mode at the boron DLL's entry point

#

This ephemeral process' only job is to start up init.exe or whatever I'll call it

#

BoronDLL will include the "advanced" ELF loader, the kernel will only include a stub which is enough to map borondll

mossy thicket
#

thats what i was doing but i realized for the new kernel ill need more robust loading & linking capabilities inside the kernel itself, bc of loadable drivers

glass heart
#

Finally, init.exe initializes the rest of the system, launches a console login prompt, etc.

#

boron will end up with two ELF loaders which share the same struct definitions and some utils

#

the first will deal with driver loading and doesn't deal with any user adjacent APIs

#

and the second will deal with mapping borondll into every new process

#

something that im looking to try, but i might realize later on that this is a futile goal, is that user processes are completely in control of their own address space

#

meaning they'll be able to unmap everything, including the PEB/TEBs and borondll

glass heart
#

this took like 3 minutes to post because the OSdev forums are probably getting abused by ChatGPT/other AI bots

#

chase should really start fighting off these stupid bots

glass heart
#

this deep ass stack trace

#

20 items deep it seems

#

mate that page is present what the fuck

#

oh wait what the hell

#

its not marked writable

#

so THATS what the NVMe assertion MDL_IS_WRITE was for

#

and yep that seems to be the test.sys driver mapped into the user half of memory and working like it should! 😄

glass heart
#

im thinking of how the POSIX/UNIX style file system will be exposed

#

i think this could be done in osdll/borondll

#

it would append \PsxRoot to the path name if absolute

#

also about / or \

#

I could do a last min change and switch to /

#

or I could make borondll translate the path replacing all / with \

glass heart
#

will be a symbolic link to either the init-root (exposes all the kernel modules) or to the boot volume selected by command line

#

heck maybe mlibc can handle that

glass heart
#

maybe i should use tar or something

#

instead of loading every module separately

#

the problem with that is that data isn't aligned to 4 kbyte boundaries

#

but to 512 bytes afair

placid sail
glass heart
#

wdym

placid sail
#

a path is a list of names right, not a single string

glass heart
#

uh

#

i don't think i've seen this specific type of design before

placid sail
#

a path is as much [ 'home', 'elliot', 'documents' ] as it is /home/elliot/documents conceptually

glass heart
#

afaik linux just passes paths directly as slash separated names

placid sail
#

linux does it wrong meme

glass heart
#

i'm not sure what windows does but i think it does something similar

placid sail
#

windows also does it wrong ngl

#

really the path seperator shouldnt even be in memory

#

you can support one when like formatting for an error message or parsing in userland, but a path should be agnostic to whatever seperator is used

glass heart
#

i'd do something like that if i didn't already invest loads of time into creating path lookup machinery and i hadn't started the project so long ago

placid sail
#

i bet alot of that path lookup machinery boils down to some form of for name in path: folder = parent.lookup(name)

glass heart
placid sail
#

its one less thing to go wrong if you expect an actual data structure of a list of names rather than an unstructured string

glass heart
#

hmm that's true

#

one thing i do plan on doing is to make userspace give strings and their length so the kernel doesn't have to go scrubbing for the zero terminator

#

but currently the kernel does use zero terminated strings quite a bit

placid sail
#

i make the userspace provide a begin and end pointer for a null terminated list of names

glass heart
#

though... most of the strings are debug

#

the ones that aren't are like

placid sail
#

so the kernel gets Users\0Guest\0Documents and a pointer to the front and back

glass heart
#

the greeting text at startup, the object manager directories' names etc

placid sail
#

the \0 are nuls rather than the text \0

glass heart
placid sail
#

fair enough

glass heart
#

it sounds like a very good idea though

placid sail
#

i do it mostly for the principle of it rather than it being significantly easier

placid sail
glass heart
#

in this case you just need to check if begin < end and if end < userspacelimit

placid sail
#

yeah, but you'd need to do the second check anyway

#

although it might partially be because i use c++ in the kernel which all works on begin end pointers meme

glass heart
#

for one simple reason

#

because it makes parameter validation faster

#

and also I didn't do almost anything regarding syscall specification

wild widget
#

Which is exactly the same check you do for overflow

#

So it really just saves a single add

placid sail
#

overflow checking in C is kinda painful which doesnt help

wild widget
#

not really?

#

if they're unsigned you just add them together and check if the result is greater than or equal to either of the inputs

#

if so, there's no overflow

placid sail
#

oh, yeah i suppose

glass heart
#

like both quantities (begin and size) are unsigned

#

just check if begin + size > end

glass heart
#

so i am running into a bug

#

where for some reason, sometimes, page references are being leaked

#

idk why

#

the last time this happened was because of a stale PTE pointer

#

you may be wondering "okay but how can a pointer to a PTE be stale?"

#

it's because I was using the old interface which fetches the physical page with the HHDM offset, where the PTE resides

#

but the pointer can go stale if you unlock the address space lock and then relock it

glass heart
#

modifying the code that modifies the PTEs to use the recursive paging thing does nothing

#

well it does something

#

instead of leaking everything it keeps faulting over and over again

#

ffffa150a8542000: 00000000001b6000 which matches cr3

#

also it has worked 2x so why isnt it working the third time?!

glass heart
#

ok so i fixed that bug

#

why did it happen

#

it happened because i wasnt invalidating the TLB regions within the recursive page map which caused the pf handler to use stale TLB entries and write to the wrong pages

#

now i am invalidating them. in the wrong place probably (because i think i am supposed to do it in MiFreeUnusedMappingLevelsInCurrentMap but i really do it every time someone wants the PTE pointer in MmGetPteLocation) but still

#

@uncut lance how does keyronex handle freeing upper page map levels? (like, PTs, PDs, PDPTs etc)

#

or does it not?

uncut lance
#

it does get rid of them

glass heart
#

like yeah does it get rid of them

uncut lance
#

oh, it does, there is a non-zero PTE count in the page struct

#

and when that reaches 0 the table is thrown out

glass heart
#

or maybe was

#

which is that i'm not invalidating the recursive page maps corresponding to the upper page table levels

#

so i added a hack to invalidate them whenever someone calls MmGetPteLocation

glass heart
#

currently i just scan all of the entries

#

i don't think this is a totally insane approach because i don't want to have to do accounting when writing *PtePtr = MM_DPTE_DECOMMITTED; or *PtePtr = 0;

glass heart
#

there are so many things i would like to work on now

#

and i will get to work on them someday

#

i think tomorrow or so i will continue the road to userspace

#

i won't implement any write support anywhere just yet but that will be implemented soon

#

actually i could do this first

#

and then userspace

#

my plan is to indeed just do my userspace with the ELF format

#

the init process will literally be run from the system DLL so it wont even need to dynamically link against anything

#

the kernel's elf loader can be as simple as possible

#

now, i will need to introduce something else, which is a way to create a process, and then pass it into OSAllocateVirtualMemory/OSFreeVirtualMemory/etc

#

since these functions are written to use the Fast PTE tech I will need to do something a bit hacky, which is to literally switch process

#

these functions will be modified to call a new function, something like PsGetAttachedProcess()

#

which will return either the current process, if you aren't modifying another's address space, or the modified process' address space

glass heart
#

progress "seems" glacial right now but i am working on it!!

#

i made OSAllocateVirtualMemory/OSFreeVirtualMemory take in a process handle

#

you can also pass special hardcoded magic numbers (using a define) that lead to referencing the current process (-1) and the current thread (-2)

noble sphinx
#

What's the diff for -1 and -2 in this case?

glass heart
#

you cannot use -2 to refer to the current process and you cannot refer to -1 to refer to the current thread

#

this is mostly for system calls where a handle can refer to either

#

i cant think of any rn though

noble sphinx
#

i mean for OSAllocateVirtualMemory

glass heart
#

you have to use -1

#

actually theyre given proper names like CURRENT_PROCESS_HANDLE and CURRENT_THREAD_HANDLE so

noble sphinx
#

Hmm id expect them to work the same in this case

glass heart
glass heart
#

hmm yes

glass heart
#

a backup of the original PMM in boron, from 19 August 2023

#

before I decided to not just rewrite NanoShell64 but just do it as a new thing entirely

#
ffffffff800102e2 T MiGetUserDataFromPoolSpaceHandle
ffffffff8000cda4 t MmpHandleFaultCommittedMappedPage
ffffffff800105ca T MmGetSmallestSlabSizeThatFitsSize
ffffffff80008e21 t KepGetNextProcessorToStealWorkFrom
ffffffff800096f3 T DbgLookUpRoutineNameByAddressExact
ffffffff80012574 T ObpRemoveObjectFromDirectoryLocked
ffffffff80012cba T ObpNormalizeParentDirectoryAndName
ffffffff8000912f t KepGetProcessToSwitchAddressSpaceTo
ffffffff8000bd57 T MiFreeUnusedMappingLevelsInCurrentMap
ffffffff8000be99 t MmpFreeUnusedMappingLevelsInCurrentMapPML```
#

as a fun fact here are the top 10 longest symbol names in boron

#
c0172ac4 r CplColorsWndProc.s_ColorComboItems
c012a2d0 T KeUnsuspendTasksWaitingForPipeWrite
c0144650 T UpdateControlsBasedOnAnchoringModes
c0149a20 T WidgetColorPicker_SubDrawHueValRect
c0149c20 T WidgetColorPicker_DrawSatPickerRect
c014a370 T WidgetColorPicker_DrawPropertyField
c013aa50 T TaskbarRecalculateGraphRectsIfNeeded
c01331c0 T CabinetDetermineResourceLaunchFailure
c0158460 T WindowBlitTakingIntoAccountOcclusions

for posterity here is the same top for nanoshell

hidden bloom
glass heart
hidden bloom
#

Though at ring 3 with actual memory protection, right?

crude arrow
#

Private Mm functions should kind off be prefixed with Mi not Mmp. You use both.

glass heart
glass heart
#

In Boron there is Mi and Mmp. Mi is for memory internals that are shared and Mmp is for memory internals that aren't shared, and are static to one compile unit

#

MiFreeUnusedMappingLevelsInCurrentMap is usable within the context of the MM but MmpFreeUnusedMappingLevelsInCurrentMapPML is only used by the former

#

Compare to Ki and Kep

glass heart
#

so close

#

oh

#

i forgot to attach to the process

#

L

glass heart
#

oh

#

i think it did the syscall instruction

glass heart
#

fyi this isnt running in user mode YET

glass heart
#

still have some hellish issues regarding improper mapping of segments

#

but im out so ill fix them later

glass heart
#

status update

#

its calling my syscall handler

#

but then triple fault

#

oh

#

lol

#

it was forcing a sysret to user mode with cs=0 ss=8

#

duh

#

maybe i should switch to user mode first

glass heart
#

reeeeeeeeeee

#

this infinite page fault loop is killing me

#

WHY are you page faulting when trying to fetch the instruction within user mode

#

you at least seem to be smoothly returning to kernel mode :3

glass heart
#

am debugging YET ANOTHER issue

#

WHY in the mother of ass is CS being set to 0x2B

#

after what seems like an innocent page fault

glass heart
#

we in user mode 🎉

noble sphinx
#

Nice

hidden bloom
#

Are you trying to make this compatible with Windows NT drivers, or is it just heavily inspired by Windows NT?

glass heart
#

great minds think alike because i also wanted to keep the first 6 args in the same registers as the sysv abi except for RCX

glass heart
#

ok so i have bugs in my process teardown procedure

glass heart
#

now the process is torn down if all threads exit

#

I suppose I should work on some kind of pseudo terminal next

#

why did it work with rax==0 but not now

#

oh

#

me dumb

#

now with the actual dummy system calls working

#

cause it was resetting rax to zero and hiding some problems

glass heart
#

so over the coming days i will figure out how i should do certain things

#

im thinking i could have a common include and rtl source folder

#

this common include would be includable by both boron-kernel and libboron

#

and it'd have definitions for structs used in syscalls as well as prototypes for those syscalls

#

as for rtl well i wonder if i could make it work so that the kernel rtl is symlinked to the libboron rtl

#

will windows explode if i add a symlink to a directory? (because I do all my work on an NTFS drive within WSL1)

#

hopefully not

#

then i should also get started with an actual userspace starting with init.exe

#

there's a lot of other things i need to do though. first of all, a lot of writing behavior has not been implemented, so no modified page writer, not even any way to write to pages aside from CoW

#

and there is nothing you can write to

#

so perhaps i should work on a file system implementation, maybe ext2 again, porting a lot of code from nanoshell but with way less constricted locking (nanoshell has a Giant File System Lock which Sucks)

#

the thing i wanna finish before any of that though is the system call exposure

#

in the future i would also like to start working on a security subsystem

uncut lance
#

leaning on 9p and virtio-fuse meant i didn't have to address the problems of disk filesystems which have interesting requirements

#

incredible progress btw

glass heart
placid sail
#

also implement zfs devilish

glass heart
glass heart
placid sail
#

rcu is a way to reduce locking on a filesystem

#

it deffers reclaimation of nodes so you dont need to guard as much stuff with global locks

#

zfs is a good filesystem

#

durable, journaling, multi-disk volumes, resilient to power outages, all the things really

uncut lance
#

porting it seems hardish but feasible though

placid sail
#

yeah thats fair, ext2 is probably alot easier lol

#

although the zfs spec is pretty comprehensive, and theres good tooling for verifying that you've done stuff right

#

although since this is NT inspired fat32 or exfat would stick to the theme better meme

uncut lance
#

sun were on fire at the time it was implemented

#

getting jeff bonwick (inventor of the slab allocator) to work on a filesystem was a masterstroke

#

he brought fresh thinking

glass heart
#

If anything implementing NTFS would stick to the theme better

#

admirably enough I remember banging out nanoshell's ext2 driver within two weeks with a few hours of school every day

#

two weeks of pain because the OS was pretty much broken most of the time and wouldn't really get a GUI or anything

#

or no wait it did

#

im misremembering

#

the MM overhaul I did in mid 2022 in nanoshell was so comprehensive it took me several days to write in a wholly new project and a few more days to port it to nanoshell proper

#

(that's how trash the old old MM was)

#

anyway. I predict that in 3 months, if I keep up consistent work, I might be able to get nanoshell applications and the environment running on boron

#

for that I'd need to create like a special edition of libboron just for nanoshell to call into

placid sail
#

even if they're kinda poor quality being able to test a single bit of code without starting up the full os is useful

glass heart
#

did i say two months

#

i meant two weeks

#

two weeks it took me, start to finish, to get the ext2 driver working

#

two months i would have died of boredom lol

placid sail
#

tests are nice either way, especially for stuff like filesystems that should be deterministic

glass heart
#

sure

#

i do have some tests, they're not really "unit" tests because they require the full OS to boot which takes like 4 seconds (since its just the kernel)

#

of which 2 are the qemu seabios and 1 is pressing enter in limine

#

more like integration tests

#

the closest thing to a unit test is probably boron/source/ke/tests.c which i should actually remove because its a giant anachronism

#

it survived many battles

placid sail
#

you're running qemu inside wsl2 right? i've found enabling kvm if you can really speeds up boot times

#

and you can set the limine boot timeout to 0 to instantly boot

placid sail
#

hm nvm then

glass heart
#

it's a batch script run from wsl(1) that runs qemu-system-x86_64.exe

#

Honestly probably the oldest script in boron

placid sail
#

idk what the state of qemu on windows is like, is haxm or hyperv an option?

glass heart
#

nanoshells run script is a direct ancestor to borons

glass heart
#

idk why

placid sail
#

probably worth fixing lol

glass heart
#

and it messes up the perf of my vbox & vmware vms so

#

i just left it to use tcg

placid sail
#

for reasons unknown to me, hyperv actually validates alot of stuff that other vms dont

glass heart
#

and from time to time also other vms and real hw

placid sail
#

hell its closer to the x86 spec in some ways than my actual cpu is lol

glass heart
#

i tried installing XP on it

#

horribly slow

#

does it do a vmexit for each pixel that XP writes or what

#

nanoshell isnt much better on HV either

placid sail
#

i personally havent had issues, but that might be because i use server hardware

#

actually its not bad on my laptop either so idk

glass heart
#

yknow i have a friend and i was using a linux vm in vbox and he said

#

and im not joking

#

"how is it so snappy"

#

"i have tons of lag in vbox"

placid sail
#

what version of windows are you using? i know its performance has improved alot in recent versions of 11

#

ouch

placid sail
#

what cpu do you have?

glass heart
#

though i got a new ssd and im planning to move to a new install of 11 24h2 ltsc

glass heart
placid sail
#

older amd chips struggled with virtualization

#

well nevermind then

#

im stumped lol

glass heart
placid sail
#

cursed windows install

glass heart
#

my entire old youtube channel was made with it

#

it was about screwing windows xp up

#

perf was very acceptable

hidden bloom
#

Virtualbox and qemu on my Linux machine is really fucking fast, and I'm using a Core i5-7500, nothing special at all.

glass heart
#

i should look into a bug where for some reason, if i make it spawn like max 60 explodeable threads in the firework test instead of max 2, then the firework spawner thread stops

#

which is annoying

#

i think it might just be having trouble spawning anything

#

several seconds in between each spawning message

#

what the hell is it waiting for

#

perhaps it's contending against the handle table lock?!

#

wow

#

it's contending against the handle table lock

#

"but iprogram! why is it contending against the handle lock!"

#

well it's because i am using the object manager backed PsCreateSystemThread to create threads instead of allocating them from pool and stuff

#

for their ref counting capabilities

glass heart
#

i have an idea for handle table optimization

#

to use a rwlock

#

to create a handle, first, acquire the rwlock shared, and perform an atomic compare exchange over every slot. if there are no free slots, then unlock shared and lock exclusive, scan again, and if there are really no slots, expand and create a slot.

#

to delete, simply lock shared and atomically clear the handle spot

#

the handle table currently doesnt employ any fancy tricks to optimize handle creation so in effect its O(n)

#

so i could either do this locking optimization or perhaps try something new

finite flint
finite flint
glass heart
#

it doesn't, ive only seen it grow up to 48

#

because the firework test creates a thread, the function that creates the thread returns a handle which is derefed

#

and then the handle is closed

#

and only the object remains

#

a big roundabout

#

i should just create the object and thats it

finite flint
# glass heart it's contending against the handle table lock

I suspect that writer starvation is happening. If you have a rwlock where there are lots of readers such that, with high probability, at any point in time at least one reader is holding the lock, then (depending on implementation) the writer side will be completely starved from execution.

glass heart
#

creating an object with ObCreateObject does not require any locks except for the pool allocator lock

glass heart
#

im literally CRYING

#

bawling my eyes out

#

WHO THE FUCK is corrupting my threads' stacks

#
31186248059        30979535763 4 2: Thread ffffa080000bc8a0 -> StackPointer ffffa080000c9b18 | R15=0000000000000000 R14=0000000000000000 R13=ffffa080000fdc28 R12=0000000000000004 RBX=000000072b926f3e RBP=ffffa080000c9bf8 RFLAGS=0000000000000083 RIP=ffffffff80009b7b
31286475908        31245270129 4 2: Thread ffffa080000bc8a0 -> StackPointer ffffa080000c9b18 | R15=ffffa080000c9b28 R14=00000000004c4b40 R13=ffffa080000c9b48 R12=fffff0000000d3a5 RBX=ffffa08000108ed0 RBP=00000000004c4b40 RFLAGS=ffffa080000c9b68 RIP=ffffffff80002c27```
#

two different instances that have the same sp

#

not out of the ordinary

#

what is out of the ordinary though is the fucking SP

glass heart
#

what the absolute FUCK

#

the bug will not trigger with gdb hooked in

#

just never

#

it will never trigger

#

maybe if i hook gdb later?

hidden bloom
#

Red zone, maybe?

glass heart
glass heart
#

i have an idea

#

i wonder if the crash is caused by a thread being transitioned to a different CPU

#

and it's using stale TLB entries

#

the answer is probably not

#

also i dont think the PTE backing the SP is changing

glass heart
#

i spotted something weird

#

it seems to be scheduling the thread in without having a previous switch?!

#
       12794793622        12791571375 0 2: Thread ffffa080000be0a0 -> StackPointer ffffa080000c5c48 | R15=ffffa080000c5c58 R14=ffffffff800047c9 R13=ffffa080000c5c68 R12=ffffffff80009e49 RBX=ffffa080000c5c98 RBP=ffffffff80005a4a RFLAGS=fffff00000004555 RIP=0000000480009a1d PTE=000000000040a363 OTH=ffffa080000be8a0
#

omg

#

i found the bug

#

fuck

#

this is what happens when you dont extensively test everything

#

i think

#

what if OldThread and NewThread are the same

glass heart
#

it could use a stale sp here

#

is my point

glass heart
#

no, i think this bug is fixed actually

glass heart
#

all of these were uncommitted yesterday

#

like

#

i manually git staged everything

#

if this were 2022 i probably would've just made it one commit

#

nanoshell had many a huge commit

glass heart
#

i quashed a few more bugs

#

made borondll relocate itself instead of the kernel relocating it

#

fixed the bad IA32_STAR value that was used

#

good night

#

I probably broke some records on my profile with this amount of commits

glass heart
#

btw this is still not totally stable. I have some freezes in qemu sometimes

#

also im starting to think of future ports again

#

x86_64 SMP (now), then i386 UP (later), and ARM/AArch64 (later) are the planned ports

glass heart
#

cool

#

i fixed another bug

#

this time in the rwlock implementation

#
        if (!Exclusive)
        {
            // We were holding onto it shared, so try to grant exclusive access.
            Access = true;
        }
        else if (Lock->SharedWaiterCount)
        {
            // We were holding it exclusive, and there are no shared waiters.
            // Have to grant exclusive access.
            Access = true;
        }
#

this

#

was supposed to be this

        if (!Exclusive)
        {
            // We were holding onto it shared, so try to grant exclusive access.
            Access = true;
        }
        else if (!Lock->SharedWaiterCount)
        {
            // We were holding it exclusive, and there are no shared waiters.
            // Have to grant exclusive access.
            Access = true;
        }
#

with that we should have pretty much stable userspace ™️

#

on 1 core this wasnt a problem because.. uh, reasons

#

idk why actually

glass heart
#

ironically this isnt even supposed to have the VAD mutex or something locked

#

ah no thats not the VAD mutex

#

what the fuck is this mutex

#

oh

#

handle table lock

#

okay... i think the VAD and heap locks should be a bigger level then

#

works

#

but now i have another problem

#

sometimes one of these addresses is corrupted

glass heart
#

Nope

#

I was using a kernel address legitimately

#

There were a class of other issues tho

glass heart
#

i wonder how i should organize everything now that i want to start creating userspace applications potentially

echo saffron
#

apps/* maybe?

glass heart
#

Nanoshell did it like that

echo saffron
#

i think it makes perfect sense with the current structure

glass heart
#

But there'd probably be quite a few in there

echo saffron
#

that's fine

glass heart
echo saffron
#

as long as they are separated properly

#

oh, but do you want to restructure it?

glass heart
#

Also I'm not sure with the "common" include idea. I mean it seems nice

glass heart
glass heart
#

For structure definitions that they share

#

maybe i can create a github organization

#

instead of it all being one monorepo

#

however i will want a different name for this OS

glass heart
glass heart
#

yuh so as it turns out

#

my kernel ELF loader was actually Broken

#

I was not supposed to just blindly add the image base to every GOT entry. As it turns out the RELA and PLTREL tables took care of that for me!

#

And I finally fixed the long standing bug where if you did something like

PIO_DISPATCH_TABLE Dispatch = {
.Mount = MyMount
};```
#

then the table's entries wouldn't be relocated

glass heart
#

no updates in a while

#

probably because of finals season

#

but i am thinking of the next thing which is to introduce a way to map files into system space (the upper half of va space)

#

this is so that a view caching mechanism can be used

#

i think the view cache views should be tied to the FCB or something but the page cache is already tied to it

#

the plan is merely to use the view cache as a way to speed up regular IO operations (read(), write() etc) by performing them on cached versions instead

#

even if a user process didnt mmap the file in its own va space the system will do that in its own half

#

yes this is very similar to how mintia does this, this isnt very original at all

#

but im wondering like

#

how should i make the fileobject or fcb to viewcache address ranges linkage

#

should i give the fcb a tree? indirection pointers ext2 style?

crude arrow
#

Have you read Russinovich's Windows Internals? He describes the Cache Manager (this is what you are talking about).

wild widget
# glass heart the plan is merely to use the view cache as a way to speed up regular IO operati...

would this really make those ops faster compared to just going through the page cache? afaict it'd need to do the exact same things plus some more
going through page cache:

  1. look up the backing page
  2. copy data into it
  3. advance position
  4. if you have more data to copy, goto 1
    view caching:
  5. find an address to map it to and create the mapping
  6. [in the page fault handler] look up the backing page
  7. [in memcpy] copy data into it
  8. [in memcpy] advance position
  9. [in memcpy] if you have more data to copy, goto 2
  10. unmap range
#

i suppose if you'd keep the mapping around between calls it might be faster depending on how you find existing mappings

glass heart
#

First of all it would make it significantly easier because all I would have to do is a memcpy from the views (which can be substantially bigger than one page)

#

And it would be significantly faster because the pages would be already mapped in

glass heart
glass heart
#

But on 32-bit these views could be a bit more restrained like 128K or something

wild widget
#

that's just intuition though, might be completely wrong

glass heart
#

Looking up the backing page is pretty fast because I use indirection pointers ext2 style for that

#

However having to do this every time for frequently accessed data, even if it's already been accessed before, sounds like a giant pain (mapping views of the file into memory solves this problem by virtue of the sections of the file already being mapped)

wild widget
#

I use a radix tree for it in such a way that if the page is already cached the only "lock" that needs to be taken is an rcu critical section

wild widget
#

to account for the fact that part of the range might not have a view yet

glass heart
#

This larger granularity should help, I think

#

Maybe I can benchmark this but that would require me to implement it both ways

wild widget
#

using a very simple benchmark (pwrite(fd, buffer, 8MiB, 0) in a loop to write 1 TiB) and a very simple (and faster than realistic) view cache implementation (map the range if it doesn't match the last mapped range) i get 14.1 GiB/s with direct-through-page-cache and 26.2 GiB/s with view caching

#

that's much better than i expected tbh

#

the difference would no doubt be less with a better direct-through-page-cache implementation (i have to copy the data twice because copying into the page cache has to be in an rcu critical section where i can't page fault) and a realistic view cache implementation (which would have more overhead for looking up the views and such), but still

wild widget
#

unfortunately I will not be able to benchmark scalability with this setup because anything but the original direct-through-page-cache implementation has incorrect locking and a bunch of race conditions

glass heart
#

what exactly are you testing in btw

wild widget
#

in qemu+kvm

glass heart
#

i see

wild widget
#

the file is on tmpfs (I haven't implemented any other filesystems yet) and there is no memory pressure or lock contention

#

oh and the test view cache implementation maps into userspace instead of kernel space because my kernel space isn't demand paged

glass heart
wild widget
glass heart
#

this file forgotten by time

#
// Boron64 - Exception handling
#ifndef NS64_EXCEPT_H
#define NS64_EXCEPT_H

#include <main.h>

void KeOnUnknownInterrupt(PKREGISTERS);
void KeOnDoubleFault(PKREGISTERS);
void KeOnProtectionFault(PKREGISTERS);
void KeOnPageFault(PKREGISTERS);

#endif//NS64_EXCEPT_H
#

it even lacks a proper header and makes references to nanoshell64

glass heart
#

so anyway i was also thinking if it's worth using the same "pool space" as the rest of the kernel or if i should make a totally separate thing with fixed size entries and a bitmap allocator

#

(because i dont think i will need to allocate views of different sizes for the cache manager)

#

the trouble with the pool space allocator is that if i use too much pool space for views (which are disposable) i might run out of it for other purposes

crude arrow
#

VA range for the Cache is separate from pools in NT. I'm going to do it the same. But it's up to the author how to do it in their design. You use bitmaps for physical allocation, not working set lists. Also why fixed size chunks for views? Shouldn't they be subject to demand paging? Committed as much as requested but wired (to ram) on demand basis.

glass heart
#

But for each however many kb/mb in the file there is a separate view

#

The goal of the cache manager is to allow standard non-mmap read/write operations to be implemented in terms of mmap-like calls, as far as I understand it

crude arrow