#Boron (not vibecoded)

1 messages · Page 4 of 1

glass heart
#

tomorrow i think i will re-factor how arguments are passed to a program (they'll be separated by null instead of spaces), add a blob (crt0.o) linked into every executable that parses all the arguments and passes them off to main() (right now everything starts from, well, _start), and write a small program that outputs something to the terminal, and then try and run it from FullScreenTerminal (i might also rename FST)

uncut cosmos
#

A Windows wrapper for this would be pretty cool, although I'm not sure if it'd make development faster

glass heart
#

The build and run cycle is already pretty fast

uncut cosmos
#

I figured

bronze egret
#

yooooo 🤩

scenic bronze
#

if u want I have code to make it look like windows

#

like this

glass heart
scenic bronze
#

tho I have to admit the nextstep look looks good

#

yea

glass heart
#

What font is that btw

scenic bronze
#

the sunOS font

glass heart
#

I see

scenic bronze
#

I think it's called Gallant

glass heart
#

I'm thinking of using a different font and that one looks really good

#

It'd look great imo

scenic bronze
#

yeah I like it a lot

#

tho it's huge

glass heart
#

fine w me

scenic bronze
#

I can send it to you, just a sec

glass heart
#

or maybe I can find a smaller similar font

glass heart
scenic bronze
#

yea i will

#

im just finding it

glass heart
#

also what's "the NYX Operating System"?

scenic bronze
#

my os

#

well

glass heart
#

and is the similarity to NixOS intended

scenic bronze
#

was

#

no it's not

glass heart
#

what happened to it

scenic bronze
#

i work on another project now

glass heart
#

i see

scenic bronze
#

nyx is a wordplay on the greek goddess and unix

#

and i had a bunch of greek names so like the support library is atlas

glass heart
#

i was thinking of a name for the operating system distribution because boron is kinda bad for an OS name

scenic bronze
#

just realized the TL in atlas could mean template library galaxybrain

scenic bronze
#

why the name boron actually?

glass heart
# scenic bronze why the name boron actually?

it's described in the readme, but basically in 2023 i needed a new name for the kernel and i wanted it to be some chemical element. so after some deliberation I landed on boron, and went with it because:

  • it's my 5th OS project (nanoshell I - private, nanoshell II - private, nanoshell III - the released one, nanoshell64 - the abandoned one, and finally boron). and boron has the atomic number of 5 (H, He, Li, Be, B, C, N, O, F, etc)
  • boron could also stand for "born outofthe remnants of nanoshell64"
#

as a fun fact i've been partaking in osdev in some capacity since 2019!

scenic bronze
#

kinda sounds like moron tho meme

glass heart
#

i've had this pointed out to me

#

even back in 2023

#

i've had a gnawing thought in my mind about borrowing a code name from iOS (namely, iPhone OS 1.1 which is codenamed Snowbird)

#

or iPhone OS 1.0 which is codenamed Alpine

#

AlpineOS sounds cool but I fear it's taken by Alpine Linux

#

CarpathianOS is kinda a weird name for an OS

scenic bronze
#

I try to follow a theme kinda, like atm my project with ethan was originally named dufay (after the composer), but I thought of a funny name instead, 'bach' (sounds like mach), so we pivoted to that and so the OS is named fuga and the kernel bach

glass heart
#

I also noticed that the kernel for nyx OS was called "gaia"

#

which is another greek mythology thing

scenic bronze
#

yeah

#

amazing names

#

right

#

🔥

glass heart
#

sure

scenic bronze
#

gaia is the earth, nyx is the moon, atlas is the one who is supporting the skies

#

kernel, OS, support library

scenic bronze
#

it doesnt look that good imo

#

only works for macOS

glass heart
#

indeed i could not use the OS suffix

#

i'm still thinking

#

if a name comes up i will announce it and rename the thread

scenic bronze
#

idk what kinda name it could be

#

are there mountains made of boron?

#

(what even is boron?)

glass heart
#

boron is a chemical element

scenic bronze
#

yeah I know

#

but like I've never seen boron

glass heart
#

specifically a metal

scenic bronze
#

name it borax

glass heart
scenic bronze
#

there's borate mining in the mojave desert, name it mojave galaxybrain

glass heart
#

so your CPU, GPU, RAM etc might have boron in them!

#

(if it's old enough)

#

nevermind looks like it was phased out in the 70s

scenic bronze
#

you could also name the OS boron and find something else for the kernel?

glass heart
#

i think the kernel could still be named boron

scenic bronze
#

chatgpt

#

boreal doesnt sound bad

#

(remove the OS)

#

everest is pretty cool as well

glass heart
#

yeah idk

#

I am still thinking about it

scenic bronze
#

yeah it's hard to find a name you like

glass heart
#

I'm terrible with names which is why all my projects' names I am not proud of

#

"one of the hardest problems in programming is naming things" and they're damn right

#

I'm sure that's not the original intent of the phrase but in this case it sure is true

scenic bronze
#

oh i completely forgot to send the font @glass heart

#

here it is

glass heart
#

why did this shit crash

#

stack overflow?? but why?

#

so hold on

#

WHY does it go into the other thing instead of the fucking pipe write function

#

I CREATED A PIPE OBJECT

#

why are these different, wtf

#

well i fixed it

#

now the userspace terminal works

#

(this is still not an external process but thats fine, i'll do it later.)

glass heart
#

banger commits today... and now i need to go to class

glass heart
#

i finished my homework like 2 hrs ago and now i shall continue for a bit

#

its 10:40pm rn so i won't be able to do much, but whatever

glass heart
#

now with an external process!

#

but letting it run amok (removing sleeps) causes it to break. oops.

#

in other news nanoshell (my previous OS) just reached 900 commits because i forgot to push a UTF-8 parsing fix

noble sphinx
#

Cool progress

glass heart
#

and he didnt want to do it for memory saving reasons

#

do you remember?

#

if i disable this assertion, it keeps going, but it randomly drops some data

#

and crashes again with a different assertion

#

so the error happens on both sides

noble sphinx
glass heart
#

well fk

#

i think i will need to rewrite or try and reanalyze and fix the pipe code

glass heart
#

looks like it wasnt that dramatic, i think i fixed it

glass heart
glass heart
#

crazy idea

#

enabling FPU/SSE/SSE2 extensions on demand per user process

#

or even per thread

noble sphinx
#

Not useful, all 64 bit apps use it unconditionally, even for simple stuff like zeroing large structs

#

Also if they detect them as disabled they won't use them so u slow everything down

glass heart
#

so if you enable them also enable AVX or whatever else

#

also isnt the increased cost of context switching for all programs worse than allowing some programs not to have it

glass heart
#

Try the instruction out and then see if you get a signal?

#

Because if so the problem gets remedied on the first invalid opcode and then that same opcode magically works and it's happy

#

It's like it was never disabled

primal gorge
#

cpuid is available in ring 3

glass heart
#

Even better

#

Because you can just query cpuid

#

Instead of "detecting" that the instructions are disabled

#

and no, I don't believe in the lie that the CPUID flags pertaining to ISA extensions are controlled by the CR bits that enable said ISA extnesions

#

because CPUID is constant in that regard

primal gorge
#

I dont have any proper numbers, before you ask

glass heart
#

i thought you got #UD for disabled ISA extensions

primal gorge
#

#NM is intended for lazy fpu/vector save/restore

glass heart
#

also the idea is that that one exception is enough to enable SSE for the entire duration of the program

#

including all new threads

#

so the cost is minimal and will only be paid once per process

primal gorge
glass heart
#

even better because I don't have to try and decode the opcode on a #UD

#

just wait for a #NM

#

anyway I guess this is more useful on 32-bit when it's not guaranteed that a program will use MMX/SSE instructions

primal gorge
#

yeah for 32 bit it makes sense

#

for 64 bit just do it up front, since SSE is assumed to exist. Maybe there's some benefit to doing it with ymm/zmm registers if you're really concerned with memory usage.

glass heart
#

I'm more concerned with context switching time than anything

primal gorge
#

if you dont do it when context switching, you might incur an interrupt and then still have to do it.

wild widget
#

the bits used to detect whether it's usable in userspace are a bitwise and of what's supported and what's enabled

glass heart
#

https://youtu.be/CTUMNtKQLl8?t=43m42s but in this video matt describes that the CPU tells .net runtime that sse2 exists but windows 95 doesn't support it

wild widget
#

userspace is capable of checking the bits intended for kernel use - that's probably what happened there - but they're not supposed to when determining what instructions are usable

glass heart
wild widget
#

don't think so

#

well idk how the CR0 bits interact with SSE

glass heart
#

beginning of the other end of the terminal process

#

i still need to add line discipline

#

then i should probably make a setup so that the fullscreen terminal and a future serial terminal can share most of the code (because they should be able to)

glass heart
#

I'll want to figure that out at some point

#

the highest latency I've seen was about 7.5M ticks and it hangs around 500-600K ticks on 1 core

glass heart
#

anyway im making real progress and soon i think i will start working on the mlibc port again

#

short summary of the recent changes

  • FullScreenTerminal renamed to VideoTerminal but actually I'm considering another rename to simply ScreenTerminal
  • init.exe now reads a configuration file and assembles some environment variables
  • initial terminal and interactive shell are configurable from said configuration file
  • VideoTerminal takes commandline parameters for specifying keyboard and frame buffer device names
  • commandline parameters used to be just one string but became a null-character-separated list
#

and more

#

oh and a kind of unusual thing, I pass arguments into the entry point of an ELF from libboron.so. this will be unexpected by applications linked against mlibc, so only libboron-interpreted programs will be subjected to such problems

noble sphinx
#

Would be nice if you report the bug on their github

glass heart
#

@noble sphinxso the problem is I don't know how to make up a minimal repro

#

it seems to work here

fast prism
glass heart
fast prism
glass heart
#

i should work on it again but i got kinda bored

fast prism
glass heart
#

having to implement terminal line discipline in the kernel to allow for posix compatibility seems like a pain

#

because iirc posix mandates that write()s to a cooked mode terminal go through line discipline

#

and things like xterm are literally simulating actual dumb terminals and shit like that

#

and dumb terminals can only show character and send character from keyboard

#

and sometimes format (vt100)

glass heart
#

im thinking of removing the FCB rwlock and letting filesystems handle their own locking in a possibly more versatile way

glass heart
#

well thats one edge case i didn't think of

#

so either I move file offset handling back in the kernel (and add a flag to ignore the file offset... and dont create separate file objects on handle inheritance) or somehow communicate file offsets between processes

#

although the problem was already solved when appending

#

also i figured out how i could implement arbitrary mountpoints

#

the way i could do it is that each FCB has a boolean variable called "IsMountPoint", and this FCB will probably be pinned (so it cannot be freed) (but i'd need to figure out when i should assign it to true in the first place)

#

if IsMountPoint is true, refer to the linked FCB which is the root of another filesystem

wild widget
glass heart
#

when they turn off the flag, set the current file offset to the size of the file

#

but cross process?

#

yeah, no. making the file object in the kernel contain the file offset would make that work

#

so the upcoming changes would be:

  • do not duplicate file offsets when their handles are inherited (only on dup())
  • move file offset handling back into the kernel, allow specification of the file offset only if a flag is (or is not) specified
  • handle append mode in the kernel too?
wild widget
#

specifically in posix these fd flags can be changed cross process

glass heart
wild widget
#

no just the file descriptor

#

new handle same object

glass heart
#

so they'll have two separate file offsets

#

oh wtf

#

so they won't have two separate file offsets

wild widget
#

the only ways to get a new file description in posix are open(), pipe(), socket(), etc

wild widget
glass heart
#

i see

#

so i guess if i want posix compatibility i'll have to compromise in some ways in the kernel

#

which i don't like, but i'd rather do that than write complex IPC based machinery which could fail for no reason

wild widget
#

yeah it's not ideal

glass heart
#

managarm does that because of their whole microkernel thing

#

but i wont

#

this wont stop me from achieving my other goals with this OS though, so i think it's okay

scenic bronze
#

deep = you copy the whole structure and shallow = you get a reference to it

glass heart
#

well the duplication function would normally duplicate the handle and not the object

#

but file objects were an exception for some reason

scenic bronze
#

ahh

glass heart
#

in the case of posix compatibility though this isn't going to be done

#

the file object will be able to have multiple references

#

so basically file objects in boron (and NT and mintia and stuff) are equivalent to file descriptions on linux/etc

#

and FCBs are equivalent to vnodes

#

and handles are somewhat equivalent to file descriptors. but in my design at least they don't have all the properties of file descriptors

#

for example standard I/O handles are not handles 0, 1, and 2

#

they might be handles 4, 8, and 12, or they might not

#

but the posix layer inside mlibc will handle that discrepancy because the values of the standard I/O handles are stored in the PEB (process environment block)

scenic bronze
#

i think what I'll do is have a separate posix fd to handle table

glass heart
#

that's what i was gonna do as well.

#

so my OS won't expose a POSIX API right off of the bat, but it'll have all the components to emulate POSIX compatibility, when I finish that part

glass heart
#

however this isn't necessary if the offset is pre-specified

glass heart
#

Another proposed redesign would be using sections for absolutely everything, anonymous memory or file backed memory

#

This would imitate NT a bit closer but I think it would simplify the code a lot

#

It'd allow CoW'd file pages to be paged out through the same codepath as anonymous pages

#

The system call interface would still support mapping file objects directly, and anonymous memory directly. No changes will happen there

#

But new APIs will be added to allocate named sections/section objects, which will be useful in the implementation of shmget()/shmat()/shmdt() APIs in boron

glass heart
#

wtf is this codegen 😭

#

(GCC this time)

#

but it generates properly in compiler explorer 😭

wild widget
#

aka the output with -S

glass heart
glass heart
#

and heck

#

the .o file itself has invalid asm too

wild widget
#

right well the assembly itself looks fine

#

what's the output of objdump -dr <.o file>

glass heart
#

shared above but fine

wild widget
#

ida formats it weirdly

glass heart
wild widget
#

objdump does a much better job for this kind of stuff

glass heart
#

and the full output file

wild widget
#

the assembler is just using a completely incorrect relocation type

#

it's using GOTOFF64 (64-bit offset between GOT start and GOT slot) instead of GOTPCRELX

#

so _GLOBAL_OFFSET_TABLE_@GOTPCREL(%rip) is broken with the gnu assembler, great!

#

sounds like you need to mark the GOT as hidden in C so that the compiler generates something like lea _GLOBAL_OFFSET_TABLE_(%rip), %... instead

glass heart
glass heart
#

although here it does seem to be using GOTPCREL

wild widget
#

for that one you seem to have marked _DYNAMIC as hidden but not _GLOBAL_OFFSET_TABLE_

glass heart
wild widget
#

oh?

#

that's weird because it's using the exact same input instruction

glass heart
#

let me see the whole binary

#

yeah looks like it works

#

then i'll also see if it works on 32-bit because i had issues in this very place on 32-bit too

wild widget
#

the not marking as global thing is was the workaround for the clang 32 bit issue right?

glass heart
#

and the error has returned

glass heart
wild widget
#

this is the reason why i just avoid referencing _GLOBAL_OFFSET_TABLE_ and _DYNAMIC from C at all

glass heart
#

but it's C++

#

so i guess it somehow makes a difference?

wild widget
#

i highly doubt that makes a difference considering the error is in llvm's integrated assembler which is below even llvm ir at which point input language is barely known

#

maybe nobody has tried compiling mlibc i686 with clang before?

glass heart
#

okay, i've fixed it

#

i've written angry-ish comments for each case

wild widget
#

btw as for what the bad instructions with the gnu assembler are, the erroneous relocation it's using is a 64 bit one, and it's a 32 bit field, so the upper 32 bits spill over and become the next instructions

glass heart
#

😭

glass heart
#

handling append mode wouldn't be hard either

#

(actually I kinda already do that :P)

glass heart
#

im getting line discipline working

#

no echo though

#

whys it going down

#

im pressing the left arrow

#

oh right

glass heart
#

wtf happened here

molten jay
crude arrow
#

Looks more like vikings did.

glass heart
#

okay

#

so I implemented a little more line discipline stuff

glass heart
#

because apparently cooked mode doesnt support in-line editing

scenic bronze
scenic bronze
#

INT_TO_FP is a shift

glass heart
#

it's a positive shift left

scenic bronze
#

SinTable[angle] may have a negative value

glass heart
#

and?

scenic bronze
glass heart
#

16 bits are dropped... so what

#

the sign bit should still be kept

scenic bronze
#

ubsan complains meme

glass heart
#

so...

#

what do you propose to fix this predicament

#

multiply by 65536 instead?

scenic bronze
#

well either you add a no_sanitize attribute or you find a way around using negative numbers, I'm probably gonna do the former meme

glass heart
#

i don't use ubsan so this isn't a problem for me

scenic bronze
#

bruh

scenic bronze
#

looks like this is a fix

#

i wouldnt ignore UB just because you dont use ubsan

glass heart
#

i guess my initrd is too big?

#

(its like 20mb now)

#

i guess i don't support symlinks

#

also it crashes in the slab allocator

#

thats not good news 💔

#

ok, fk it, i'll delay ncurses+bash for later

glass heart
#

okay

#

time to run a test executable with mlibc

#

hmm so it fails to load test

#

why

runic delta
#

@glass heart

#

this?

glass heart
#

thats one of them yeah

runic delta
#

damn

glass heart
#

so it expects this

#

but wtf why is it a page fault

#

so why the fuck didnt it get mapped

#

it said initialized data

runic delta
glass heart
#

wait holy smokes you're right

#

(not you)

runic delta
#

😂

glass heart
#

i'm in the address space of the SPAWNING process

#

not the SPAWNED process

#

duh

#

thats why it didn't work... and that's why it "worked" with normal applications

glass heart
#

broke 900 kernel builds!

glass heart
#

and this is the first time it tries to load ld.so!!

#

oh god

#

i gotta implement SSE/FPU support

molten jay
#

sse is not that hard

#

it's just a few instructions

glass heart
molten jay
molten jay
#

save the context of the old thread before switching

#

and load the new one

glass heart
#

just SSE state

molten jay
#

ye

glass heart
# molten jay

do I need to check for xsave and use that, or can I just use fxsave and fxrstor

molten jay
#

you have to check like i showd in the screen

molten jay
#

xsave will save both fpu and sse

#

you have to enable it like this thi

uncut cosmos
#

You're probably not gonna want AVX for a long time

molten jay
molten jay
uncut cosmos
#

He probably compiled stuff with AVX by accident since his cpu probably has it

molten jay
#

makes stuff faster

glass heart
#

isnt it

molten jay
#

still needs xsave

glass heart
#

oh no

#

i really did compile with avx

#

fuck

molten jay
#

lol

glass heart
#

i'll add support for it for now

molten jay
#

the code i showed you is all you need btw

uncut cosmos
glass heart
#

okay I'm going to continue work tomorrow

#

good night

molten jay
#

gn

glass heart
#

i just enabled fxsave and SSE and it works

#

now I get this

#

and here it is

#

well

#

why

molten jay
#

it's just an if

glass heart
#

i cbf to do it

#

because it's not entirely clear how much memory it takes up

#

(not specified like hey, this instruction saves X bytes)

#

(fxsave is a clear 512 bytes)

#

and i need to write some insns for xcr0

#

and im lazy

molten jay
#

the size depends on the cpu

#

and you can get it

glass heart
#

why isnt it just one size

#

even if its like 2kb

molten jay
#

it's normally 8kb+

#

and wants to be aligned to 64

glass heart
#

i could tell

glass heart
molten jay
#

idk

#

maybe check the flags

glass heart
#

looks like i had 4 symbols that had weak binding

#

or whatever

#

making them hidden fixed it

glass heart
#

what the fuck

#

why is this fucking parameter not 0

#

looks like i cant use init array either

molten jay
glass heart
#

idk what i even did but it was fixed

#

somehow

#

maybe i forgot to ninja install??

#

idk

molten jay
#

so making BaseAddressInOut the value of the pointer of BaseAddress

#

i think that's what''s happening

glass heart
#

we're really chipping at this

molten jay
#

yep

glass heart
#

apparently i will need to implement overlapping mmaps

#

which sucks but okay

#

i'll try to do it

#

later

slow fractal
#

Yeah, mlibc first mmaps memory to allocate the space for the dso and then maps/reads it

finite flint
slow fractal
#

I think so

glass heart
#

so i implemented a function called MmOverrideAddressRange, which will be used to support overlapping fixed mmaps, and it turns out i wrote it "perfectly" (i'll figure out later if there are any bugs, right now i just tested one specific case)

#

the first two bugs i found are unrelated to this function entirely

#

the first bug: not incrementing the exclusive owner lock count on recursive lock

#

(mintia1, whose implementation i "stole" with permission, does this)

#

and the second: i forgot to put an "else"

#

the first test, which looks like this, works

#

okay, i discovered a hang

#

new test. hanging here

#
OSAllocateVirtualMemory returned base address 0000000000021000.
MmOverrideAddressRange LOCKING SPACE EXCLUSIVE.
MmLockSpaceExclusive(0000000000000000)
MmOverrideAddressRange LOCKING SPACE EXCLUSIVE DONE.
MmLockSpaceExclusive(0000000000029000)
MmUnlockSpace(0000000000029000)
MmUnlockSpace(0000000000000000)
Split succeeded. BaseAddress2: 0000000000029000
MmOverrideAddressRange LOCKING SPACE EXCLUSIVE.
MmLockSpaceExclusive(0000000000000000)
#

?????

#

whys it failing the second time

#

okay

#

that was another rwlock bug, actually the same one, i just fixed it wrong

#

FINALLY we found a mm bug

#

uhhhh

#

so the resulting PTE at that address is 8

#

MM_DPTE_COMMITTED is 1 << 8

glass heart
#

going to sleep, will figure ts out tomorrow

#

but yeah. idk why that PTE value shows up

#

it DOESNT show up when i allocate that region and free it

#

only when i split and then deallocate

#

wait!

#

ahh its MM_DPTE_DECOMMITTED

#

well I'll fix it tomorrow

#

after this fix i think it'll likely just work

#

damn, a function that found like 2 or 3 bugs in other locations

#

that's one mighty function

glass heart
#

that seems to have been the issue

#

now the split actually seems to work

glass heart
#

okay i found another bug

#

this time it's actually in that function, and it happens when trying to shrink heap (read: free list) ranges

#

i fixed another bug that was actually tangentially related to said function which is that i was accidentally setting the decommitted PTE when i actually meant to set 0

glass heart
#

Support for overlapping mmaps has officially been added and I believe it is stable now

#

Next I will add support for partial overlapping unmapping

glass heart
#

Partial unmapping support has been added now, leveraging the same machinery as overlapping mappings

glass heart
#

now im struggling to figure out why libc isnt being mapped

glass heart
#

what the fuck is a 0x8 error code

molten jay
glass heart
#

the order is FaultPC, FaultAddress, FaultMode

#

thats not an address

#

uhhhhhhhhhh

#

what fucking kind of PTE is this

molten jay
glass heart
#

if only I knew

molten jay
glass heart
#

what are you asking

molten jay
#

where are you calling that function

#

and where it is from

glass heart
#

okay, so context

#

i am trying to port mlibc's rtld to boron

#

i have just finished implementing overlapping mmap and partial munmap

#

and i discovered a freeze

#

and i discovered that that freeze is located in OSReadFile

#

and i discovered that for some weird reason it keeps page faulting over and over on a specific address

#

AND THEN I FOUND

#

THAT THERE IS AN INVALID PTE

#

WHY

#

(i dont know)

molten jay
#

lol

glass heart
#

oh but i notice that there are TWO page faults

#

the first is the normal one

#

so likely that's at fault

#

WAIT

#

I THINK I FIGURED IT OUT

#

see this

#

thats an int

#

a SIGNED int

#

then i use it here

#

and GUESS WHAT FKING HAPPENS

molten jay
#

XDDD

glass heart
#

IT FUCKING SIGN EXTENDS

#

THANK GOD IT WASNT A MEMORY CORRUPTION!

#

were making great progress

glass heart
#

it printed now!

#

however I call DbgPrint and dont see anything... what gives?!

#

maybe i didnt install it properly

#

yeah no thats weird. it only calls puts() and not DbgPrint

#

oh its because DbgPrint isnt defined since this isnt debug mode.

#

duh

#

success though

glass heart
#

Features that will need to be implemented going forward:

  • Time/RTC related system calls
  • Anonymous sections, and shift all anonymous memory reservations to said sections
    • I don't know if I should use a sparsely allocated data structure or not. Will have to figure it out.
    • Technically this isn't required for forking support, but it will be when I add support for page out, so best to add it now
    • Possibly even move away from the separate reserve and commit model I borrowed from Win32/NT, which will allow me to start freeing paged out page tables without worrying about losing information
    • Maybe there is a way to do it by putting the decommitted/committed information inside the proto-PTEs inside the section object
      • Well that'd require duplicating the section objects...
      • Still need to hash out the design
  • Signals
  • Duplicating address spaces (and then the whole process)
  • Job Control
glass heart
#

shared memory can be implemented using sections as they are

#

private memory will have to have sections created at the time of the fork

#

containing the forked state of the mapping

#

also CoW'd pages are gonna have to be paged out separately

#

i'm struggling to come up with something

uncut cosmos
glass heart
#

its not even that much harder than static binaries

#

all you need to do is load a second elf file called ld.so (you'll find its path with the PT_INTERP entry) with any base address (preferably in the high addresses though)

#

and jump to its entrypoint instead of the program's

#

(and of course have POSIX compliant mmap support)

glass heart
#

tomorrow i'm going to mock up a scheme to implement forkable address spaces. since I plan on adding support for pageout I'm going to need to think this through a little bit more carefully.

uncut lance
#

when a forked page is evicted from the working set you create such a pte instead of an ordinary transitional pte

#

it has a pointer to a structure consisting of the actual pte + a refcount

glass heart
uncut lance
#

that structure, you can see as being like a tiny vm object all its own

glass heart
#

or actually that might not work

#

hmm

#

by section object i mean a container for all the pages

#

this WOULD work for shared memory

#

but maybe not for privately allocated memory

#

the big problem is that there may be privately mapped copied-on-write pages within the mapped region

#

and this applies to both private anon mappings and private file backed mappings

#

if I didn't have to worry about pageout I'd literally just make the PTEs say that the page is CoW-able

glass heart
#

which is copied-on-write pages within existing mappings

glass heart
# uncut lance that structure, you can see as being like a tiny vm object all its own

hmm. so I could implement an object called "CoW overlay" or something, which points to a mappable object (either a file or in-memory section). each entry inside this object would have a bit set:

  • if the bit is 0 (or actually it might just be if the whole entry is zero), then redirect to the backing object
  • if the bit is 1 (or actually it might just be if the whole entry is non-zero), then this is a CoW page and map and evict that one
#

if this were C++ I'd just make each part of a common interface

#

in C I could still do it using a vtable or manual if/switch based checks

#

so I'm thinking it could be something like this

#

(don't ask why it's vertical when i could've made it horizontal, thinking of it vertically made me think of it a little better)

#

and actually this CoW overlay object could redirect into another CoW overlay object, technically.

#

however I'd rather avoid that if possible?

#

but I don't know how, without actually duplicating those pages

#

Uses the property of recursiveness of BOTH mutexes AND rwlocks!

#

This sure does look like an afterthought

finite flint
#

Actually no, this is likely slightly trickier than that (at least the duplication part is a bit tricky)

glass heart
#

That's exactly what I said

#

Isn't that what you mean?

finite flint
#

no. if you see that you are doing this, instead create it on top of the backing directly.

#

except that of course doesn't work just as simple as that, because the CoW overlay that you are duplicating can itself have dirty pages.

glass heart
glass heart
#

Let's say that I map a file whose first byte is "1"

#

As private CoW

#

Then the program increments the first byte by 1, resulting in "2"

#

Then, it forks

#

The child process increments the data and puts "3"

#

The parent also increments the data and also puts "3" (because it saw "2" in that memory region)

#

Neither of them see the true backing memory of the file which still has "1" mapped to it

#

The main thing I'm worried about is, what if the parent forks a lot of times? For each fork there would be an additional layer of CoW overlay

#

You can evaluate the CoW overlay layerings in a non-recursive way, that's not a problem, but then you still run into the risk of running OOM (if the process forks too much, even if the processes all exit), and slowing down lookup for the particular VA a lot

#

Something like bash can fork thousands of times in just a few hours of regular use, and that's without shell scripts and the like

#

And I'm also not sure how you can "merge" two CoW overlays. I saw an edge case but I can't remember it

#

I am also thinking of giving these CoW overlays a silly name like "Memory Cel"

#

the "Cel" here from "animation cel"

#

anyway, the dumb design i was thinking of before would lead to something like this

#

if we're smart about it we might be able to merge these

#

but we'd kinda have to walk the tree of CoW overlays and it's a mess and surely there must be a simpler way

#

the CoW overlay concept seems simple, but if you aren't careful it can lead to weirdness

#

an alternative is to wait until a child process exits, then start merging

uncut lance
# glass heart

you've reinvented from first principles the concept of 'object chaining' in mach vm, and also started developing the techniques to collapse/garbage collect object chains

glass heart
#

oh so this concept is really used in a production kernel

#

that's really neat

#

that must mean i'm on the right track

glass heart
uncut lance
#

this is not the best illustration but you can see it at work in the top example ("BSD VM")

glass heart
#

i'm sorta proud of this because from the first commit i got most of it right (i just got the tree walk wrong)

glass heart
#

interesting

uncut lance
#

it is conceptually nice and it's used in most of the mach vm descendents today (freebsd, dragonfly bsd, xnu) but was ditched by chuck cranor in favour of solution from sunos called amaps and anons, which is based on reference counting pages instead

glass heart
#

the idea is that i want to be able to page these out relatively easily

#

idk how that's done with amaps and anons

uncut lance
#

it looks like it should work at least, definitely one of those apis where having a test suite is helpful to be certain about it

uncut lance
glass heart
#

nanoshell would have had a considerably simpler implementation probably

uncut lance
#

an amap is like a vm object/section, except instead of directly containing pointers to pages (or swap), it contains pointers to anons; and anons are reference-counted

uncut lance
#

to fork you clone the whole amap 1 and end up with amap 2, where amap 1 and amap 2 at this point are identical, pointing to the same anons; each anon's refcount was incremented in the process

glass heart
uncut lance
#

and you've made the actual process mappings all read only. then whenever you write-fault on a page within an amap, if the anon's refcount is > 1, you clone the anon and its backing page

uncut lance
glass heart
#

that seems kind of hard to scale because an anon is a slab/pool/whatever allocation

#

and for a lot of pages parallel memory usage would grow considerably

#

i think i will go with this object chaining mechanism. personally it looks simple to implement and i think i've figured out how to collect garbage too

uncut lance
#

the anon incurs a cost of no less than 16 bytes for each cloned page (unless you settle for a smaller refcnt and can tolerate, say, a 10 or 12-byte anon which, if you pack, you end up with your 8-byte page/swap pointer being misaligned) but in principle you only need the anon to exist for as long as there are >1 mappings of that anon

glass heart
#

i see

#

that sounds moderately better

#

i'd then ask "couldn't you just use the page frame's refcount instead?"

#

but maybe the anon's ref count is for a different purpose

uncut lance
#

the anon becomes like a sort of single-page anonymous vm object/section, in that it can point to either swap or to a physical page

glass heart
#

didnt see too many updates

uncut lance
#

i had forgotten i had a rewrite branch where i had started prototyping some new ideas (one or two of them made it to master) and rediscovered it

#

i've been working on that

#

i hadn't touched it in almost a year, 2 or 3 days ago i completed enough of the page fault on mapped object codepath to do this, which you will have to trust me is interesting because it's demonstrating pagefault clustering/readahead of a mapped file on an ext2 volume:

Did read in object page (520; tot. 8)
We read: < [what] understandest thou, which [is] not in us?
Job 15:10       With us [are] both the grayheaded and very aged men, much elder than thy father.
Job 15:11       [Are] the consolations of God small with thee? is there any secret thing with thee?
Job 15:12       Why doth thine heart carry thee away? and what do thy eyes wink at,
Job 15:13       That thou turnest thy spirit against God, and lettest [such] words go out of thy mouth?
Job 15:14       What [is] man, that he should be clean? and [he which is] born of a woman, that he should be righteous?
Job 15:15       Behold, he putteth no trust in his saints; yea, the heavens are not clean in his sight.
Job 15:16       How much more abominable and filthy [is] man, which drinketh iniquity like water?
Job 15:17       I will shew thee, hear me; and that [which] I have seen I will declare;
Job 15:18       Which wise men have told from their fathers, and have not hid [it]:
Job 15:19       Unto whom alone the earth was given, and no stranger passed among them.
Job 15:20       The wicked man travaileth with pain all [his] day>
#

(i always use the bible as my test file when working on filesystem/vm/where the two meet)

#

what is new in that rewrite branch: mostly rewritten dispatcher (hopefully with timers that won't have weird problems on aarch64!!) with some topology awareness; a nice mechanism for calling things on other CPUs; hopefully more hotplug-ready io system; new ext2 driver; proper riscv port; the start of fdt support; proper kernel modules support; and the latest exciting VM changes

glass heart
#

as an update i finally built mlibc

#

i got a basic "hello world" application working

glass heart
#

i am also planning to port my OS to different platforms in the future

#

i have some real hardware platforms which i can test on:

  • the iPhone 3G (probably booted with OpeniBoot)
  • the Nintendo Wii
near panther
glass heart
#

they ported android to it so why not

near panther
#

maybe

glass heart
#

taking a small break. i have homework to catch up to

minor plinth
#

@glass heart I have question, do you use serial or framebuffer to log? Both now and when you've just started. Thanks in advance, please answer TvT

molten jay
#

FB is too slow currently

#

also, why did you send the same msg on all threads?

glass heart
molten jay
#

what does e9 do btw

#

and what advantages does it have over serial?

noble sphinx
#

no configuration required, no waiting needed

#

u just spam it

glass heart
#

On real hardware it tends to do nothing

glass heart
molten jay
#

i'll re-route my debug log there then

glass heart
#

you should keep the serial output for non-qemu/bochs machines

molten jay
#

what is the qemu flag to get it out to stdio or a file?

molten jay
#

and spam debug on e9

molten jay
#

k

glass heart
#

itll significantly slow down the machine

molten jay
#

even if the messages are the same amount as serial?

glass heart
#

i mean dont spam everything you can possibly think of to e9

molten jay
#

yeah

glass heart
#

keep the log amount the same

molten jay
#

atp i think i can start using flanterm again to print just info logs

#

it was wayy too slow when i sent both debug and info log there

glass heart
#

no kidding

#

i have several debug switches so if i dont need debug output from something i can disable it

#

like PMMDEBUG and PAGE_FAULT_DEBUG

molten jay
#

i might do that

glass heart
#

for my usecase those options significantly slowdown because an e9 write is a call to the windows conhost and thats slow as fuck

molten jay
#

windows conhost?

glass heart
#

and i can't use qemu with accel on windows

glass heart
molten jay
#

ah

#

whpx isn't that good?

glass heart
#

like i develop on windows

#

sadly

glass heart
molten jay
#

lol

glass heart
#

linux running inside it hogs my memory

#

and it couldn't even boot nanoshell

molten jay
#

why not dual boot then

glass heart
#

and hyper-v sucks ass for legacy OSes in general

glass heart
glass heart
#

prior to april this year it also was that i didnt have enough storage either

#

just a 512gb ssd

#

now i have a 2tb ssd

molten jay
#

i have a 512gb ssd too

#

and i dual boot

glass heart
#

i didnt even partition it fully because i knew i would dualboot

#

but i just never did it

glass heart
#

4 yrs ago today i began the nanoshell project (which is the precursor to this one)

#

i was learning how paging worked and i felt that a fresh start was needed

primal gorge
#

Wow only 4 years? I thought it was older than that.

glass heart
#

Actually that reminds me

#

In October 2021 I implemented multitasking for the first time, but when I found out what I have to do, I decided that in December I'd start the project that would become nanoshell

minor plinth
minor plinth
glass heart
minor plinth
glass heart
#

i was considering moving the "sparse linear array" structure from MM (where the page cache is its only use) to Ex

#

so that I can use it in multiple places

#

(well also in MM but ykwim)

minor plinth
glass heart
near panther
#

also is it nextstep or windows nt i cant even figure out anymore

#

unix trl

near panther
minor plinth
#

Ahhh

#

Lmao

glass heart
#

i have once again rewritten my page cache

#

this time the data structured is a bit more generic

#

still a progressively more indirect data structure just like the previous 2 versions

#

i don't know if there are any bugs because it mostly just worked first try

#

well i need to check 32-bit too

glass heart
#

looks like i had a typo where the system call number for OSSetEvent was mistakenly set to OSResetEvent

#

and the 32-bit build is fixed!

glass heart
#

other than inodes, mappable objects are another place where i miss OOP languages like C++/Java. right now I could be specifying a MappableObject interface and having files/sections/cow-overlays implement said interface. instead I'm going to have to do it manually since, y'know, C

glass heart
#

in fact i have only written one os in c++ and its dead

#

that being nanoshell64

#

imagine if i had fixed that bug that caused me to drop nanoshell64 lmfao

minor plinth
glass heart
#

It runs on both 32 and 64

minor plinth
#

It's not Limine?

#

I'm surprised

#

x86 is a pain compared to x64

glass heart
glass heart
glass heart
#

what WAS bad was the transition from 64 to 32-bit

#

that one was hard

#

because i did rely on the HHDM in many places and had to compromise

minor plinth
#

My bad, that was what I'm talking about

glass heart
#

i also omitted certain features like SMP support from the 32-bit build

#

the reason is simple

minor plinth
#

And that is?

glass heart
#

because if you have an SMP system you're likely already on a 64-bit platform, so just use 64-bit

#

however this assumption wont hold up for comparatively very long

#

because there are 32-bit SMP platforms that are not x86

#

fortunately I don't intend to port to any of those for now

minor plinth
#

I heard that on x86, people usually did Higher-Half Mapping by placing the kernel at PDPT[3] which is the top 1GB of the VM

glass heart
#

for the other 4gb-256mb i use a switchable 64KB mapping (or whatever)

#

(my initial design had 4mb but i realized that was slow as fuck)

minor plinth
glass heart
#

guarded by a "spinlock"

minor plinth
#

Isn't that less query for the CPU

#

??

glass heart
#

AND invlpg them all

minor plinth
#

Ah

#

Hmm

#

Make sense I guess

glass heart
#

but in my case they're a BIT more involved

#

they still dont wait

#

just crash if the spinlock is already locked

minor plinth
#

Wait @glass heart

#

Your x86 don't use PAE?

#

Why?

glass heart
#

you'll notice that NO modern features are being used by the 32-bit port

#

that's why

minor plinth
#

AHh

vestal river
#

since mb1 with uefi is broken (no way to find acpi)

vestal river
#

but i guess mb1 lets you use grub legacy etc

glass heart
#

you can just pretend it says Copyright (C) 1997 iProgramInCpp instead of 2025

#

(ignore that i was born 8 years later)

minor plinth
#

LMAO >_<
That's funny (ik my humor is broken, kinda)

glass heart
#

first test with overlay objects instead of the old bad CoW mechanism

#

although that might be API misuse (not setting PAGE_WRITE) instead of anything else

#

oh yay

#

deadlock averted

#

thank you....

#

but maybe there is actually a deadlock because disabling the crash leads to one

#

shit doesnt seem to be working anymore

#

i broke it 🥺

#

oh this one's failing at execution

#

literally the first instruction

#

it couldnt read

glass heart
#

whys it trying to use NULL 😭

glass heart
#

and by legacy i mean really legacy

wild widget
#

I mean yeah but you still target i686 right

glass heart
#

386/486/pentium type shit

wild widget
#

ah ok

glass heart
#

no

wild widget
#

that makes more sense then

glass heart
#

in fact i dont support any modern x86 feature such as the APIC or ACPI on the x86 version

#

there is going to be an unsupported gap but I don't care about that one that much

#

where you have 32-bit PCs that have modern features unused by the 32-bit kernel

#

that could be used by the 64-bit kernel if the CPU was 64-bit

glass heart
#

why

#

cr2 really is 0

#

i bet it didnt even load the content of the file

wild widget
#

can't see how endbr64 would even cause a page fault so yeah the code is probably zeroed

glass heart
#

oh yep

#

💀

#

thats 0 alright

#

but that makes me think

#

how did mapping even succeed if it cant read files

#

wait i know why

#

its because i apply the section offset twice

#

i dont need to specify it when creating the CoW overlay

#

(it creates a sparse linear array so it wont use more memory than it has to)

#

okay, got a bit further by making sure OSGetMappedFileHandle actually returns the file handle and NOT the CoW overlay on top of it

#

oh no

#

its failing in the heap

glass heart
#

now that I AM though

#

i got an issue regarding IopPrepareWriteFile

#

after fixing that

#

i get a DEADLOCK!

#

YESSSSS

#

FINALLY

glass heart
#

@uncut lance i have implemented CoW overlays and anonymous sections

#

and also opted files in to the same system

#

now the page fault routine is considerably simpler because it doesn't have to treat two separate cases

#

i will remove the separate commit/reserve feature i borrowed from windows because i don't use it

#

and then i'll go on to implement fork

minor plinth
#

You're making CoW rn?

#

Cool

#

Btw what is rtld, runtime loader?

glass heart
glass heart
#

Loads executable and shared objects

glass heart
#

i have started work on the clone address space part of the fork process

#

the part where i inherit handles is already basically done however for fork i will have to do it a bit more aggressively as some things can opt in to a mechanism where child processes created through OSCreateProcess wont see some handles

#

I have already written most of it however I will need to write code that calls it and code to test it

#

eventually it will be implemented

#

i do still remember like 3 1/2 years ago where i said "fuck fork"

#

well while i do still think it's not a good API, i have decided that i should implement it

#

#progress-report message (from archived channels)

#

#progress-report message (also archive)
@uncut lance you say that your implementation of fork requires extra allocations to make anonymous private memory work with symmetric CoW. well guess what, mine will too. i haven't yet decided to make OSAllocateVirtualMemory calls allocate anon sections instead of just creating non-object VADs where the information is stored inside the page tables. so for fork I'm introducing a mechanism where these non-object VADs are automatically upgraded to section based VADs during fork, before creating the cow overlays on top of private mappings

#

due to laziness reasons I am not going to roll back the section VAD upgrade upon failure of the subsequent code path, since that'd involve tracking every modified VAD in a list and I don't feel like doing that, and for just a couple extra kilobytes per process on average?

#

i'll explain more tomorrow

glass heart
#

i have a plan

#

after my vacation starts im going to lock the fuck in

#

and port boron to powerpc

#

and then run it on the wii

#

so i can get ppc fireworks by new year's

uncut lance
#

or in other words everything would need the anon indirection

glass heart
barren ocean
# glass heart and then run it on the wii

Based chad
Let me know if you want some patches to help it work better in Dolphin (it's super inaccurate for low level stuff), or if you need testing on real hardware with a USB Gecko serial console, would be happy to provide either

#

I also have some original minimal bootstrap (enough to get everything mapped and a sane enough env to run C code) if you need some of that to get it off the ground; currently licensed under GPLv2 but since it's my own I'd be happy to relicense it under whatever if you want it

glass heart
glass heart
#

I'm going to commit a slight breach of boron's "only implement what you need in the kernel" principle: I'll be putting most of the fork implementation in the kernel

#

I will remain unbudged for execve type functions though. Those will still be implemented in mlibc or libboron.

#

In other news I have thought of a new codename for this OS: Flutter (or Flutter OS). But I'm not 100% sure about it

#

afaict, there is no OS named flutter on the internet currently. I originally considered butterfly but there is already a Butterfly OS.

random sleet
#

and flutter OS sounds like a shitty website os

#

like those fake ones that just run in the browser pretending to be one

glass heart
#

anyway yeah im still looking for potential names

glass heart
#

a rename is most likely going to happen sometime in 2026, because i don't think boron is that good of a name for a complete desktop OS distribution

scenic bronze
#

take shrooms and go out in the wilderness to find a name

scenic bronze
#

Zircon

#

Oh wait

near panther
glass heart
#

okay

#

first fork test

#

guaranteed to fail, but let's see ...

#

what did i say

glass heart
#

fix one bug and like 2 more appear

#

it thinks its the parent process twice?!

#

we're making progress

#

i screwed up by returning a status from OSDLLForkEntry instead of just returning the status value from the OSForkProcess system call

glass heart
#

boom

#

it fucking works

#

here is the code

#

even works on vbox

glass heart
#

32-bit: stack overflow?!

glass heart
#

in the parent, when entering OSForkProcessInternal

#

child process

#

of course it wouldnt fucking work the return SP is messed up

#

wtf now its the same

echo saffron
#

i'm pretty sure you can use print/x instead of typing it into the calculator to see the hex representation

#

or p/x for short

glass heart
#

thanks

#

if i did x [something] it'd dump the memory instead

echo saffron
#
(gdb) p 1337
$2 = 1337
(gdb) p/x 1337
$3 = 0x539```
#

x is examine memory

glass heart
#

okay NOW it entered the child process

echo saffron
#

different comand

glass heart
#

thats like

#

not the same esp

#

so of course its messing up

#

WTF am I doing??!

#

writing shit to userspace memory

vestal river
glass heart
#

this is extremely brittle

vestal river
#

as in examine/x $esp?

glass heart
#

doesnt matter

glass heart
# glass heart

what matters is what i was smoking when i wrote this function

#

because i want it again

#

(jk. i don't smoke)

glass heart
# glass heart

technically there is no need to worry since most of the time this deals with entirely new threads where we do indeed want to pass a parameter as context

glass heart
# glass heart

okay i removed that modifying the stack part out of the assembly and put it in an MmSafeCopy when entering the thread.

glass heart
#

ayy i fixed it

#

okay, there's one more thing i need to do before i can merge fork support into master

#

which is to make an entirely new event object for critical sections

glass heart
#

okay i have added support for OB_FLAG_DUPLICATE_ON_FORK

#

the object is duplicated if it can be duplicated, upon any fork operation

#

if you try to create or open an object with this flag and the duplicate method isnt implemented then opening will fail

uncut lance
glass heart
#

then i think ill be set for bash

#

actually i think i might need signal support as well

scenic bronze
#

Bash doesn't require signals

glass heart
#

yay

#

and bash also doesnt require job control

#

signals and job control are 2026 goals i guess

#

2026 is going to be a good year for boron. that's when most of the ports to other platforms will happen

#

2023-2025 were foundation setting

primal gorge
glass heart
#

okay

#

mlibc fork + waitpid is working

uncut lance
#

Bash is not too demanding

glass heart
#

for the past 2 days or so ive been working on an armv6 port

#

now i got a basic higherhalf kernel separate from the boron source tree

#

and also got boron to compile (but not link because of missing dependencies)

uncut cosmos
#

isn't armv6 ancient?

glass heart
#

That's... kind of the point though!

glass heart
#

armv6 showing some signs of life

#

i have my doubts im gonna be able to achieve a real hardware port in 1 day until new year's but at least it's running

#

idk why its accessing that address though

near panther
#

todo 😔

glass heart
glass heart
#

We making progress

#

got to the point where it asks for a HAL... good!

glass heart
glass heart
primal gorge
#

ooh exciting

glass heart
#

Happy new year!

glass heart
#

I have decided to take up implementing execve