#Keyronex

1 messages ยท Page 4 of 1

hexed solstice
#

this is the challenging bit

#

for a regular file the semantics of 9p2000.L and FUSE alike is that having it open = it persists on the server side

paper fox
#

but directories, they're weird?

hexed solstice
#

yeah, those i need to handle more carefully

#

the vnode ops i use are a close match to those described in the paper on SunOS' VFS, and those were specifically designed for NFS

#

so there shouldn't be any fundamental incompatibilities

brazen smelt
hexed solstice
stone orbit
#

hmm where the hell is the iso??

#

Pattern 'keyronex-weekly-2023-05-10.iso' does not match any files. wow thanks actions

#

ugh i messed up

#

of course i did

hexed solstice
#

we should do a tarball of system-root as well for convenience

stone orbit
#
diff --git a/.github/workflows/weekly.yml b/.github/workflows/weekly.yml
index d622670..3bba39b 100644
--- a/.github/workflows/weekly.yml
+++ b/.github/workflows/weekly.yml
@@ -41,13 +41,13 @@ jobs:
       - name: Build everything
         run: make all

+      - name: Set TAG_DATE environment variable
+        run: echo "TAG_DATE=$(date +'%Y-%m-%d')" >> $GITHUB_ENV
+
       - name: Build and rename ISO
         run: |
           make iso
-          mv build/barebones.iso keyronex-weekly-$(date +'%Y%m%d').iso
-
-      - name: Set TAG_DATE environment variable
-        run: echo "TAG_DATE=$(date +'%Y-%m-%d')" >> $GITHUB_ENV
+          mv build/barebones.iso keyronex-weekly-$TAG_DATE.iso

       - name: Tag and push new release tag
         run: |
#

oh do the iso's not bundle the initrd?

#

thats right

hexed solstice
stone orbit
#

we just built everything for nothing then ๐Ÿ˜…

hexed solstice
stone orbit
#

ahh that makes sense

hexed solstice
#

i wonder how small a minimal bash, coreutils, mlibc combination would be though

#

could be worth doing such an iso that extracts a tar into a tmpfs

stone orbit
#

it would still take 30-40 ish minutes

#

most of it is taken up by gcc

#

compiling the cross compiler

#

it takes around 30 minutes sadly

hexed solstice
#

in that case we may as well build everything and dispense the complete system root as a tarball

stone orbit
#

alright, ill prepare a pr that hopefully isnt broken this time

#

sorry for the oversight

hexed solstice
#

no worries, we now have an actual weekly build going on, which is a big improvement over the previous state of affairs where only i could build this thing

stone orbit
#

the sysroot seems to be quite big on my end

#

i wonder how big the archive ends up being

#

148M gzip compressed

#

xz was taking forever

hexed solstice
#

it's inconsistently stripped because i like a lot of things to be unstripped for debuggability, but that drastically increaes the size

#

148m seems reasonable

#

and i can see uncompressed it's 674m

stone orbit
#

oh its running inside keyronex, that's neat

hexed solstice
#

i had a sudden desire to run df -h and stat -f so threw it together over the weekend

stone orbit
#

do you prefer tag names with hyphens or without?

#

weekly-yyyy-mm-dd or weekly-yyyymmdd

hexed solstice
#

funny you ask that

#

i was experimenting with how i label my files at placement

#

and i struggled with yymmdd or yyyymmdd but yy-mm-dd was much easier for me to parse

vale pelican
stone orbit
#

not a bad idea

#

what is the flag i have to pass to tar for it to use zstd?

#

--zstd, ugh

#

damn zstd is 3 times as fast and produces an even smaller archive

#

ill take that!

hexed solstice
#

that's remarkable

#

how small does it get?

stone orbit
#

around 15M less

#

129M

#

thats 19M less compared to 148M compressed by gzip

hexed solstice
#

i'm happy with that

stone orbit
#

and do you want to use yy-mm-dd for the date?

#

or do you want to stick with full 4 digit year?

hexed solstice
#

might as well use the 4-digit year, i think that's more standard

stone orbit
#

alright, yyyy-mm-dd it is

hexed solstice
#

it will also clear up confusion for people trying to download keyronex in 2123

stone orbit
#

keyronex-yyyy-mm-dd.iso
keyronex-sysroot-yyyy-mm-dd.tar.zst

#

lets hope everything goes as planned

#

hmm let me modify the workflow to place an empty file into the system root and see if everything works as planned

#

well except for that little detail it all seems to be working

#

alright testing it for the last time, if it works ill cook up a pr

brazen smelt
vale pelican
#

repost

brazen smelt
#

best compression algo imo

brazen smelt
vale pelican
#

lol

stone orbit
#

before running another "weekly" run make sure to get rid of the existing tag and release

#

im not entirely sure how to do that though

#

apparently git push --delete origin weekly-2023-05-10 should work just fine, but i havent tested it

#

actually let me lol

#

oh that's neat

czapek@~/sources/Keyronex-fork$ git push --delete origin weekly-2023-05-10
To github.com:czapek1337/Keyronex.git
 - [deleted]         weekly-2023-05-10
#

yeah that totally works

clever grotto
hexed solstice
#

'delete tag' was greyed out again

#

github loves greying things out, not explaining any further, and leaving

#

anyway, merged and started

stone orbit
#

yaaay it worked!

#

i didnt mess up this time :D

paper fox
#

Great minds let themselves be inspiered by other Great minds.

paper fox
hexed solstice
#

at last keyronex is runnable by others

#

tricky business, i was just thinking of this again

#

what do i even do when a namecache entry times out - look it up again?

#

i.e. get its parent, lookup(thisnc->name), check if we get the same result?

#

i am just designing the new namecache now and there are quite a few interesting design questions

#

for example, whether it should be legal to transfer a namecache from one parent to another (to handle the case of renaming, for example), or whether the old namecache should be orphaned; i think the latter is better in terms of locking constraints

paper fox
#

at the same time, the vnode that is being replaced (moved into) should stay

#

I've tested that by chdir()-ing into a directory on Linux, then removing it and moving a new directory into its place- getcwd() still returns the same path

#

this suggests that the vnode being moved into (aka replaced) is orphaned

#

although I think we mean different things when we say orphaned

hexed solstice
#

to avoid moving i had been thinking of invalidating the old namecache

#

orphaning it even

paper fox
paper fox
#

you'd have to invalidate a hell lot of namecaches for that

hexed solstice
paper fox
#

but all the children?

hexed solstice
#

they retain a reference to it

#

so it would persist

#

but i suspect there is another problem with doing this which i haven't thought of yet

paper fox
#

I guess a potential solution to the child problem would be to have orphaned namecaches have a pointer to the "real" namecache, and any time a child needs to get the parent (for lookups on '..', for example), if the parent is an orphaned namecache, it replaces its parent pointer

#

jesus fkn christ, I'm gonna get banned from discord because of the words I use

#

moving children?

hexed solstice
#

moved namecaches acquire a "replacement" pointer to a new namecache

paper fox
#

how would the new namecache handle lookups on children?

hexed solstice
#

i suppose it would have to check what it replaced, but then we run into a reference cycle

paper fox
#

I think for a proper rename(2), stuff is going to get moved regardless of what you do

#

I made the mistake in an earlier iteration of osdev (before I even had a clue what good design was) of designing the vnode layer to be immutable, no vnodes could be moved whatsoever, in any way ever

hexed solstice
#

i suppose what i worried about is that mutability of namecaches would be a cause for confusion

paper fox
#

well, everything is mutable unless it is locked

#

not really

#

but with the VFS, that's how you should think

#

(at least I think so)

hexed solstice
#

what i hoped to do was to avoid locking a namecache on every e.g. read/write/ioctl

#

otherwise namecache->inode can't be safely gotten

hexed solstice
#

even if i atomically load namecache->inode i am not safe yet because i need to reference it

#

without the reference it can and will go away

paper fox
#

well I propose a solution to you:
on unlink(), you don't actually remove the reference to the inode from the namecache, you instead orphan the namecache

#

I myself have been thinking of that

#

that way, namecache->inode can only change if it is NULL

#

meaning that whenever you know that namecache->inode is non-null, it can be considered const

hexed solstice
#

i don't think there can ever be a transition from one inode to another

#

but aye, with unlink i think orphaning is the appropriate choice

#

after all i envisage the namecache handle becoming the thing that a kernel file description refers to, so it's important to preserve the inode for continued operations on it

paper fox
paper fox
#

it wouldn't hurt

hexed solstice
paper fox
#

except for in the future when you'll maybe want to have a file descriptor that refers to a path (O_PATH) or a file descriptor that opens an inode but with a fake path in /proc/abc/fd/x

hexed solstice
#

now i need to think about how pid-specific namecaching is done

paper fox
#

how would pid-specific namecaching differ from any other namecaching?

#

surely the filesystem driver would be the only thing that differs

#

readlink("/proc/<pid>/fd/<x>") would be implemented by taking a look at file_t->namecache and prepending to a string

hexed solstice
paper fox
#

assuming that readlink() isn't cached

#

which, if it is, could be changed with a simple vnode/namecache flag

hexed solstice
#

i'm not sure why i had it in my head that /proc/self has to be/appear to be a true directory

paper fox
#

do this on your system right now:

cd /proc
ls -l self
#

typoed ls -l

hexed solstice
#

lr-xr-xr-x 1 root wheel 3 May 11 20:22 self -> curproc

#

and for curproc:
lr-xr-xr-x 1 root wheel 2 May 11 20:22 curproc -> 40
genius, a simple solution

paper fox
#

curproc -> 40

#

that's a bit unrealistic

#

for me, ls -l /proc/self usually returns something above 3000

#

I guess PID allocation differs between netbsd and linux

hexed solstice
#

in this case i quite literally just went over and booted my desktop

paper fox
#

that makes sense, I guess

hexed solstice
#

i am typing from my laptop's (boo, hiss) windows partition

paper fox
#

my linux machine might actually be quite bloated for a linux machine

hexed solstice
#

the result will be influenced by netbsd kernel threads not enjoying a PID number

paper fox
hexed solstice
#

incidentally i think a readlink cache is worth implementing but will certainly need to be possible to switch it off for the procfs

paper fox
#

afaik, on Linux, TIDs are unique across the entire system, so I'm a bit unsure

deft elm
#

lots of activity in here

hexed solstice
#

they are non-unique on netbsd, e.g.:

root      1   1  0.0  0.1 19848  1620 ?     Is    8:20PM 0:00.10 init 
root    166   1  0.0  0.1 32516  2284 ?     Ss    8:21PM 0:00.06 /usr/sbin/syslogd -s ```
#

username, pid, lwp id (tid equivalent)

paper fox
deft elm
#

just wing it /j

hexed solstice
#

everything seems to get horribly complex when you want to give even the slightest consideration to edge cases

paper fox
#

rename(2) - the bane of any VFS designer

hexed solstice
#

and with even only fairly-granular locking it gets worse

paper fox
#

actually, add mount -B to the list of things that are the bane of any VFS designer

hexed solstice
#

dragonfly bsd cleverly replicates parts of its namecache on a per-cpu basis and they have sophisticated cache-coherence mechanisms matt dillon developed with a view to clusters

paper fox
#

rename is hard

hexed solstice
#

currently experimenting with whether i can keep a struct namecache under 128 bytes

hexed solstice
#

i've barely squeezed it into 120 bytes

hexed solstice
#

@paper fox i think you might like this

#

vnodes might be kept, 'weakly referenced', in an inode number to vnode cache of the FS (or similar)

[18:27]Yehuda: so vnodes' destructor (they are managed by the object manager), it calls the 'inactive' vnode method, in a typical FS that locks the FS' node cache, it then checks if the vnode is still refcnt = 0, if so there's no way for a reference to be retained anymore and it makes away with the vnode. but if refcnt > 0, then it abandons the destruction and returns

[18:30]Yehuda: but this isn't enough. consider this: vnode destructor is entered (as --refcnt == 0). it locks the node cache mutex and discovers that the vnode refcnt is still 0. it removes it from the node cache and frees it. but before it got around to acquiring the node cache mutex, another thread already has gotten the vnode from the node cache and then released it again, bringing its refcnt to 0. the other thread now also wants to enter the destructor. but the first destructor has now acquired the node cache mutex and it's DELETED the vnode!

[18:32]Yehuda: i think i can solve it by, instead of the destructor being called after the object manager reduced vnode's refcnt to 0, instead calling the destructor when the refcnt is found to be 1 by the object manager's release-an-object function

[18:33]Yehuda: the destructor must lock the node cache, check if the vnode refcnt is still 1, if so it does the deletion, else it must now do the deferred reference count reduction and return

paper fox
#

Currently I just do the trivial thing, lock the vnode->parent so that no new refs to the vnode can be acquired, decrement the refcount, if it isn't zero, return, remove and destroy the vnode.

#

Suboptimal, puts some constraints on vput(), but it works

#

In the future I might have some generation counter or use some "deferred vnode freeing" scheme, where I offload the work of vput() to a separate kernel thread.

hexed solstice
#

so it decrements refcount before doing object-specific logic

#

that will have to change now

paper fox
#

This is my "object refcounting framework"

#

:^)

hexed solstice
# paper fox

and each drop() is wrapped in an if (drop() == 1) free the thing?

paper fox
#

same idea

#

obviously, certain things need to be more complicated than that

hexed solstice
#

i think my c style guide forbids ! for non-booleans

paper fox
#

atm vput() looks like this:

void vput(struct vnode *vnode)
{
begin:
    spin_acquire(&vnode->rename_lock);
    struct vnode *parent = vnode->parent;
    if(parent != vnode)
        spin_acquire(&parent->lock);

    if(!drop(&vnode->refcnt)) {
        if(parent != vnode)
            spin_release(&parent->lock);
        spin_release(&vnode->rename_lock);
        return;
    }

    if(vnode->inode)
        iput(vnode->inode);

    if(parent != vnode) {
        __avl_delete(&vnode->entry, &parent->children, NULL);
        spin_release(&parent->lock);
    }

    if(vnode->name != vnode->__inline_name)
        kfree((void *) vnode->name);

    free_vnode(vnode);

    if(parent != vnode) {
        vnode = parent;
        goto begin;
    }
}
#

horrendous

#

needs a rework

hexed solstice
#

how big are your vnodes out of interest?

paper fox
#

I have no idea, but I'll count it now

hexed solstice
#

this is what my namecaches look like (128 bytes):

struct namecache {
    kmutex_t mutex;              /*!< longer-term lock */
    uint32_t refcnt;          /*!< count of retaining references */
    uint8_t name_len;          /*!< length of name, max 255 */
    uint32_t unused : 24;          /*!< can become flags in the future */
    TAILQ_ENTRY(namecache) lru_entry; /*!< linkage in LRU list*/
    RB_ENTRY(namecache) rb_entry;      /*!< linkage in parent->entries */
    RB_HEAD(namecache_rb, namecache) entries; /*!< (m) names in directory */
    struct namecache *parent; /*!< (l to read) parent directory namecache */
    struct vnode *vp;      /*!< underlying vnode or NULL if a negative */
    char *name;          /*!< filename */
    uint64_t key;          /*!< rb key: len << 32 | hash(name) */
    uint64_t unused2; /*!< could use this space to store an inline name? */
};
paper fox
#

apparently my struct vnode is 120 bytes

#
struct vnode {
    /*
     * This is the link followed for 'chdir("..")'-type lookups. For root
     * vnodes, this is a pointer to self.
     */
    struct vnode *parent;

    struct avlnode entry;

    /*
     * For short vnode names (<20), we store the name embedded in the vnode.
     * This also aligns the struct fields a bit nicer when on a 64-bit
     * system.
     */
    char __inline_name[VNODE_NAME_INLINE_LEN + 1];
    const char *name;

    /*
     * Protects the above fields against renames.
     */
    spinlock_t rename_lock;

    /*
     * A lock for the 'inode' field, mount list, and child tree.
     */
    spinlock_t lock;

    /*
     * List of mounts that shadow this vnode.
     * Protected by the above lock.
     */
    struct list mount_list;

    /*
     * Contained inode, or NULL.
     */
    struct inode *inode;

    struct avltree children;

    /*
     * Don't use this direcly, use vget() and vput() instead.
     */
    refcnt_t refcnt;
};
#

I could (and probably should) increase VNODE_NAME_INLINE_LEN from 19 to 27

hexed solstice
#

mine are made large by needing a kmutex_t which is 32 bytes as i can't use a spinlock if namecache entries are to be locked during operations in the filesystem (IPL is elevated during spinlock holding => yielding operations forbidden => a non-spin snychronisation object can never be inferior in lock ordering to a spin lock => filesystem ops are toast because they want to do yielding operations and work with non-spin synch objects)

paper fox
#

I have a 24-byte struct mutex

#

well

#

it's more of a struct semaphore

hexed solstice
#

do you have any recursive mutexes?

paper fox
#

no

hexed solstice
#

i have left the door open to support them but have dodged the need so far

#

but that's probably why my mutex has another 8 bytes (owner pointer)

paper fox
#

For recursive mutexes, I'd have to separate the mutex implementation from the semaphore implementation (which wouldn't be too hard actually)

#

I want to have a singly-linked list in the mutex/semaphore struct, but I also want to be able to have waiters on timeouts or otherwise interruptible

#

actually

#

a singly-linked list would be very possible, I just realised.

#

nvm, it wouldn't, because I still need a tail pointer

#

so it'd still take up two machine-words

hexed solstice
#

that's where 16 of my bytes go

#

all syncronisation objects can be waited on with timeouts and can be interrupted by ASTs (used for the generation of signals among other things)

#

there is a bottleneck which will become significant when there are around 64 cores, which is that all synchronisation objects are subject to a big spinlock. i'll relieve it in the future with something like an in-kernel futex

paper fox
#

I guess one possible recursive mutex implementation that would work but not very well is to just have a pointer in a per-task variable ->owns_mutex, that points to a currently-owned recursive mutex, and then a per-task counter, thereby removing the need for any changes to the mutex implementation.

#

so for mutex_acquire_recursive():

void mutex_acquire_recursive(struct mutex *mtx)
{
        struct task *me = current_task();
        if(me->owns_mutex == mtx) {
                me->recursive_mutex_cnt++;
                return;
        }

        if(me->owns_mutex)
                panic("This design makes it impossible to own more than one recursive mutex at once. :^(");

        mutex_acquire(mtx);  /* normal acquire */
        me->owns_mutex = mtx;
        me->recursive_mutex_cnt = 1;
}
#

and mutex_release_recursive() wouldn't even need a pointer to the mutex as an argument, but it'd look like this:

void mutex_release_recursive(void)
{
        struct task *me = current_task();
        if(!me->owns_mutex)
                panic("Trying to release a recursive mutex, but not holding any!");

        if(--me->recursive_mutex_cnt)
                return;

        mutex_release(me->owns_mutex);  /* normal release */
        me->owns_mutex = NULL;
}
#

This way it'd be possible to use the current mutex/semaphore impl as a recursive mutex/semaphore without any modifications to the data structures, but it'd not be possible to hold more than one at once.

hexed solstice
#

what i had been thinking of for recursive mutexes was: i already have a counter in the common synch object header, that's used for semaphores. for mutexes, if you try to acquire it and owner == curthread(), then adjust the counter. when you release it, test if owner == curthread(), adjust counter, if counter goes back to the acquirable state, release and wake next waiter

hexed solstice
#

i feel like taking a detour before i continue with namecache work

hexed solstice
#

getting tempted by the prospect of enhancing & exposing tcp/udp sockets to userland

hexed solstice
#

yes, thats exactly what I'll do

hexed solstice
#

this looks like a promising start

#

too bad receiving isn't yet possible, but that can be dealt with

tiny sapphire
#

using slurp? @hexed solstice

hexed solstice
#

i remember slirp as being a hassle, can't remember exactly what was a hassle about it thugh

tiny sapphire
#

cool

hexed solstice
#

now we are getting somewhere

#

tcp will need more effort

final hatch
#

nice

hexed solstice
#

less effort than i expected (since the fundamentals were done, just not exposed to userspace

sullen fern
#

oh wow nice

hexed solstice
#

unfortunately i can do it only once

#

not sure why yet

hexed solstice
#

interesting, my virtio-nic driver seems to permit to send 63 requests and then it can't do any more

#

so that's what the problem seems to be. i never thought the virtio-nic driver would turn out to be faulty

#

so i've been searching everywhere else for clues. i rewrote the virtio-nic driver some time ago to be purely asynchronous. but, lo and behold, it seems i never wrote the new code to deal with used elements on the TX virtqueue

hexed solstice
#

reading about keyronex on keyronex w/ links

brazen smelt
#

wow congrats ๐Ÿฅณ

hexed solstice
quick saddle
#

can't wait for me keyronex inception

final hatch
#

very nice

sinful agate
#

Nice work

hexed solstice
#

cheers

#

bloody hell, my virtio-net driver is trying to DDOS people

#

it's repeatedly re-enqueuing a packet for transmission. transmitted it some 100,000 times in a second

hexed solstice
#

dreadful oversight i just discovered in keyronex: for all this time, vmem has not been actually making segments free under certain conditions (when it coudn't coalesce the segment with immediately prior or further segments)

hexed solstice
#

it's time to port a dhcp client

#

or write one. (i have no rust so andy's is not an option)

hollow hull
#

if you write one make it portable in C

hexed solstice
#

i've found udhcp which seems alright

#

just working on its prerequisites

#

it needs linux's PF_PACKET sockets

hexed solstice
#

udhcp is now ported

#

i can recommend it to anyone who needs a DHCP client but, having no rust, can't use andy's one

#

it does need PF_PACKET sockets, which are linux's badly named link-level sockets (and therefore very easy to implement, just duplicate incoming packets before delivery to the networking stack and deliver them to the PF_PACKET sockets if the specified protocol of that socket matches the ethertype of that packet; and in turn, send data sent on the socket directly to the ethernet driver)

hexed solstice
#

identified the ppoll issue i had previously been having: poll should ignore (not set POLLNVAL) negative FDs

final hatch
hexed solstice
#

fixed the issues preventing me using esc to access links' menu: a combination of the earlier poll() problem and a particularly stupid one i just spotted in the tty driver (reading zeroes into the supplied buffer of read() up to the max size of the buffer)

hexed solstice
#

and then poll() itself i do as nothing but a shim over epoll(), so i hadn't even considered the differing semantics

hexed solstice
#

some day i will be brave enough to try to build it with graphics enabled

tiny sapphire
hexed solstice
#

let's see if anyone steals it from me for a third time lucky

tiny sapphire
#

๐Ÿ‘€

hexed solstice
#

the time has come to implement ifconfig and route

#

(udhcp doesn't actually set anything, it launches an external script to do it for you)

hollow hull
hexed solstice
#

i might try something really outrageous like TVision and see how it reacts to that

#

in the meantime i think it's time to add a proper kernel-userspace communications method so that i can do ifconfig and route without ioctl hell

#

i could do a routing socket, NetLink, or some kind of distributed objects styled thing with objc

brazen smelt
hexed solstice
brazen smelt
hexed solstice
brazen smelt
#

ahh okay

quick saddle
tiny gale
#

are there images for keyronex?

tiny gale
#

thank you!

hexed solstice
#

there is not much exciting you can do with it and it needs to be launched with a particular command line to qemu (to provide a 9p fs)

#

one of these days i will arrange the weekly build to supply that script

tiny sapphire
#

@hexed solstice does your weekly build ever make the ci run out of the max hours?

#

and how much time does it take to build it

hexed solstice
#

and if i added llvm probably even longer. i noticed that github limits one job to 6 hours but a workflow can last 35 days (!) so it might be possible to optimise things - i know the xbstrap command says it has functionality like "download-archive" and "download-tool-archive", i've not seen documentation for these but i'm sure it should be possible to have one job build half of the tools and archive and upload those, another job build the next half by using "download-tool-archive", etc

hollow hull
#

i wanted to devise a way to distribute the build over multiple jobs

#

distribute is the wrong word

#

what i mean is basically: wrap up the build, transfer it to another job somehow, then continue the build

#

35 days is more than enough to build a full distribution

#

the other issue is that Lyre additionally simply runs out of available disk space lol

#

i should just use a build server/VPS and that's it

#

as is i just build a subset of Lyre packages, roughly equivalent to Arch's base-devel

frozen tendon
hollow hull
#

fair

sullen fern
#

Like jinx --build-only or something

hollow hull
#

wdym exactly

#

oh

#

ok i get what you mean

sullen fern
#

idk I think it would save space

hollow hull
#

though that isn't really the bulk of the issue, it's more about build artifacts

#

but i could do a build only option that does that, and on top of that, it thoroughly cleans any build artifact that isn't the final package

#

that should save a lot of space

sullen fern
#

Yeah that could work

hexed solstice
#

i've been thinking a bit on how i can design the native APIs to keyronex

#

quite fond of the idea of exposing them with a portable distributed objects type system (in which objc messages are directly serialised and sent to the kernel)

#

this is not terribly fast because it involves message dispatch initially failing locally, a special object being assembled from the stack frame, and then serialising that object (containing the message target, selector, and all arguments) and sending it to the kernel

#

where the data must be deserialised into an invocation object and then the stack frame reconstructed programmatically and invoked

#

i fear ObjFW supports neither the automatic creation of that object nor the corresponding dispatch of the invocation object. neither of which are trivial to do

hexed solstice
#

this is actually quite a fun little project in two halves: 1. write a function which doesn't know how it's been called; it must ask the runtime to provide it with a string representation of the return and argument types that it was probably called with, and it must use that information to create a structure containing each of these; 2. write a function that is called with such a structure + a function pointer and which calls the function pointed to, unpacking the arguments structure and packing the return value into that structure

hexed solstice
#

i have an initial working prototype for up to 6 integral arguments and an integral or void return. trying to get it to work with struct returns - failing - i need to take a closer look at the system v abi spec

hexed solstice
#

struct return ruins this whole thing

#

gcc isn't designed for objfw's runtime and doesn't call a special objc_msg_lookup_stret() function objfw provides. so the forwarding handler function, which is returned from objc_msg_lookup{_stret}(), is the handler for non-struct returns. and there's no way to proceed that i can think of from here

#

because now, thank you very much to the amd64 sys v abi, the argument order is all fucked up

#

since a pointer to the struct (to be returned into) is passed as a pseudo argument in %rdi

hexed solstice
#

i'm just going to limit it to the simple case for now: integral/object arguments and return types only. it's now time to pick or create an encoding format

hexed solstice
#

currently working out exactly what functionality will be available for kernel endpoints of this new IPC mechanism. i am probably going to rule out some fancy things like this:

- (void) iterateSomethingWithCallback:(function/block pointer or delegate)delegate;

such things would need to either run in a separate thread, or they would need a lot of new kernel infrastructure to do (either support for a 'syscall -> kernel code -> upcall user code' path, or some sort of coroutine facility to eliminate that)

tiny gale
hexed solstice
tiny gale
#

and clang as explicit lit ๐Ÿ”ฅ๐Ÿ”ฅ๐Ÿ”ฅ objfw support

hexed solstice
#

i have been informed of this directly by a gcc developer, arsen

tiny gale
#

Thatโ€™s based af ngl

#

What else is missing from GCC?

hexed solstice
#

lightweight generics, @() autoboxing support for numbers etc, probably quite a bit more

tiny gale
tiny gale
hexed solstice
#

objfw falls back to id in this case

vale pelican
#

iain is doing a lot of gcc stuff at once huh meme

tiny gale
#

Aye OF_GENERIC right?

vale pelican
#

he's also working on statement expr support for coroutines in c++

#

currently ({ if (...) co_return ...; }) causes an ICE :^)

hexed solstice
#

so useful

vale pelican
#

yeah we use them for FRG_TRY and FRG_CO_TRY in frigg for frg::expected

#

so you can do FRG_TRY(thing_that_may_fail()) to just bubble the error up

#

but unfortunately, FRG_CO_TRY doesn't work on gcc so we can't compile managarm-{kernel,system} with gcc

tiny gale
hexed solstice
#

do i have any use for BPF? i'm thinking of implementing a BPF JIT for the fun of it

hexed solstice
#

in the meantime i've made good progress on the new high-level IPC mechanism:

#

the principle of it is that special proxy objects have a special handler for messages not understood, such that they retrieve the type encoding of the invoked selector from the objc runtime, which is sufficient information to identify which registers and positions in the stack frame contain arguments of which type, and what type of thing should be returned, and the arguments are all then serialised and sent to the server, which can then deserialise the same to manually construct the stack frame to invoke the method, and the same principle is used for the return value to be serialised and sent back to the client

tiny sapphire
#

wait nvm

hexed solstice
#

i have really gotten into the mood to implement (e)BPF soon

#

i have no use for it yet other than (and this is a stretch and really quite unnecessary) filtering udhcp's AF_PACKET socket so that non-DHCP packets are discarded

#

but i like implementing interpreters and JITs and this is a perfect excuse for that

hexed solstice
#

there is a leak of between 4-10 pages on process exit

#

i need to find out where, really irritating

hexed solstice
#

i have had no luck identifying the leaks yet. i am half-tempted to implement a mechanism whereby i can log every single allocation and free and perhaps send that data through virtio-vsock to some script on the host that can identify what was freed and what wasn't

vale pelican
#

frigg's slab allocator has the logging part and in managarm we do hook it up to a ring buffer that ends up getting dumped to a file over virtio-console halfmemeright

#

including a tool that processes the output and does things like piping the stack traces through addr2line

#

the tool could probably be useful regardless, the format it takes in is a simple binary containing a bunch of records that look like this: ```
'a' for allocation / 'f' for free
64-bit pointer (result of allocation, memory being freed on free)
64-bit size (only on allocation)
up to 12 stack trace entries (as 64-bit pointers)
the 0xA5A5A5A5A5A5A5A5 64-bit constant

hexed solstice
#

i think it could actually be very useful

final hatch
hexed solstice
#

i've not confirmed this but i've just remembered

#

as part of testing the VFS i wasn't freeing unreferenced vnodes

#

probably at least a part of the leaking is the fact that vnodes are not currently freed, simply invalidated so i can detect errors

hexed solstice
#

some of the likely culprits to the memory leak

#

now i'll need to add stack traces to the debug output and parse those to figure out what these are

#

excluding bufctls a typical invocation and exit of bash --version, after it's already been started once to fill the page cache, causes the leak of 95 allocations

tiny sapphire
hexed solstice
#

now i can find the leaks

#

among the leaked: a file, strings, epoll results structure (created by poll()-to-epoll() translator), but most interesting of all, vm_anon_t's

hexed solstice
#

vm_anon_ts weren't being leaked, i can confirm after adding a pid field to the debug log, they were just getting dirtied first in the parent bash, after fork cow, before the child dirtied them. (i think)

#

following a round of fixes i now leak only about 1 page per process invocation

twin haven
#

nice investigation, it's always interesting to read these things ๐Ÿ™‚

#

do have any idea where that one page is being leaked?

final hatch
#

"about" 1 page?

hexed solstice
hexed solstice
#

so probably slabs getting filled or emptied

zenith karma
#

could you write every single kalloc to a file

#

with a backtrace

#

then simply find who allocated that page

#

to a file is in e9 or serial

#

or a buffer you can read with lldb whatever

hexed solstice
hexed solstice
#

i think i've identified the last two leaks

#
  1. large slab bufctls not freed when a slab becomes empty and will be freed 2. refcounting around exited posix processes broken (the posix process appears to never be freed)
hexed solstice
#

with these fixed, it's now time to consider other leaks and omitted features

#

signal handling is very incomplete (only a few syscalls are prepared to handle premature wakeup by signals.) tcp sockets leak memory because the socket transmit buffer implementation is not complete. unix domain sockets are only available for stream and not datagram sockets. there is a great deal to do

#

and i want to implement (e)BPF for the banter

hexed solstice
#

having a look at some of the outstanding problems of keyronex. i built udhcpc without modification and it works, but there are some issues and resource/memory leaks - the first stinker is that there's no PF_UNIX socketpair so the udhcpc's mechanism for dealing with signals is broken (it uses the self-pipe trick but with a unix socket for whatever reason); unix sockets are leaked (there is confusion around reference counting of them, and though it's not applicable in this instance, i want to clean up the treatment of bind); and SIGPIPE isn't operational for them

hexed solstice
#
__ensure(dir->__ent_next <= dir->__ent_limit) failed```
this is new - let's see what happened
#

i see what it is now: difference in alignment provided in 9p2000.L replies; the 9p2000.L readdir replies actually match the format of linux abi dirents, so i had once simply had them directly copied into the buffer, but later i instead explicitly copied them out one-at-a-time, only i align more aggressively, and hence overshot the buffer

#

stupid twat

hexed solstice
#

this is impossible, and also surprising to see in what i assume to be the most robust part of the kernel

sullen fern
#

luckily you had an assertion

hexed solstice
#

setting and reading these variables is protected under the big dispatcher lock so i don't know how on earth this could happen

hexed solstice
#

i really wish there were a "who wrote to this address" function in the debugger so that i would have the necessary ingredients to solve problems like this

#

(this is the first i've seen this; i've been trying to solve bugs which Links browser is revealing)

zenith karma
#

it doesnt work well at all

sullen fern
#

I've used it before when something was writing to an address and I didn't know what

sullen fern
zenith karma
#

it seems to be ultra slow for me

#

and also half broken

zenith karma
sullen fern
#

watch (char[100]) *addr will watch the range [addr, addr+100)

vale pelican
#

qemu record & replay in reverse

hexed solstice
hexed solstice
#

i just arrange for its hooks to log the accesses instead of testing them

hexed solstice
#

i spent 2 days trying to figure out how to do it

#

it didn't make a lick of sense - you need to have some disk device passed to qemu for reasons completely beyond my understanding

sullen fern
#

try watch

vale pelican
hexed solstice
#

-trace-to file.trace

hexed solstice
zenith karma
#

so a race condition of some sort?

hexed solstice
#

seems likely, i am just trying to determine how it could be raced to

#

i just had a look and all the sites that modify it + this site that reads it are under the big dispatcher lock

#

so i can't rule out the possibility of something trampling on it which shouldn't have

zenith karma
#

a qemu write trace would be very useful

sullen fern
#

qemu should add more debugging features outside of gdb

zenith karma
#

yessss

#

really they should add support for building a trace for reverse debugging

hexed solstice
#

this still remains my favourite debug feature of keyronex

#

i don't know how people live without describing what their threads are waiting on so they can swiftly identify deadlocks

twin haven
#

Mm that is a nice feature

sullen fern
#

omw to add that

zenith karma
#

(steal that)

hexed solstice
#

i have a rough idea about what might be going on with both the earlier bug and a new bug

#

the new bug is an amap (anonymous map, the structure describing anonymous memory; it contains a 3-level table of anonymous memory descriptors) becoming zeroed out randomly

#

i have had a look and found some instances of the slab allocator returning an already-allocated pointer and i think i must be double-freeing somewhere

zenith karma
#

exciting

sullen fern
#

frigg's slab allocator debug trace has been quite useful to me, you could probably add some sort of trace to detect leaks and double frees to yours

hexed solstice
#

i need a fast and special-purpose driver for virtio-console for it

hexed solstice
#

68k ports are back on the agenda

#

initially qemu's 'virt68k' machine then Amigas with 040s/060s

hexed solstice
#

progress

vale pelican
#

nice

hexed solstice
#

i have done away with the dependence on page table size = page size. instead they are allocated in groups of page-size (this was @neat steppe's simple suggestion. it allows for page table page-out to remain viable; if i allocated them from slabs instead, for example, i would have a single page be made up of potentially 16 page tables from different processes; much less likely that this would ever then be a candidate for pageout, since in each process the number of live PTEs in the pagetable forming a part of that page would have to reach 0)

#

this solution will work great unless and until someone shows me an architecture with page tables not of a power-of-2 size

vale pelican
#

very nice, almost makes me want to start a new project :^)

hexed solstice
vale pelican
#

some new os project, mainly so i can get to write the kernel from ground up with all the knowledge i gained between now and when i last worked on my own os project :^)

hexed solstice
stone orbit
#

i would love to start a project like this as well, but i have no idea how to plan the project properly so i don't code myself into a corner and have to rewrite a substantial part of it... i also don't know how to design a good interrupt and io subsystems so i might want to hold off until i'm more knowledgable in these areas ๐Ÿ˜„ in the mean time, any tips on the first part?

hexed solstice
#

when i am lite on those i end up making a mess

#

it's much harder when you are on your own and don't have a team to discuss things with and get code review

final hatch
hexed solstice
#

anyone tackled virtio-gpu yet for the simple case (framebuffer)? i'm sure i read before it's fairly straightforward. (i am using the goldfish serial port for now for output)

hexed solstice
#

the root level and middle level are 512 bytes long (128 entries each), the bottom level either 256 bytes (for 4kib pages) or 128 bytes (for 8kib pages)

zenith karma
hexed solstice
final hatch
twin haven
hexed solstice
#

i do need to adapt them to virtio-mmio first and sort out endianness

twin haven
#

yeah non little endian machines are something i'm dreading one day

twin haven
#

I was only able to get qemu to provide legacy interface devices rather than revision one devices though

#

but it only really means your 3 buffer areas must be physicall contiguous

#

and I didnt really spend much time figuring out if it was a config error on my end

hexed solstice
#

i saw a commit in 2019 introducing modern interface to qemu's virtio-mmio

twin haven
#

possible skill issue then

hexed solstice
#

it's nondefault in any case

hexed solstice
#
    for (i = 0; i < 128; i++) {
        dev = qdev_new(TYPE_VIRTIO_MMIO);
        qdev_prop_set_bit(dev, "force-legacy", false);

code from the m68k "virt" platform

twin haven
#

right, well thats frustrating

#

PR time ultrameme

hexed solstice
#

you could try this argument i saw: -global virtio-mmio.force-legacy=false

twin haven
#

ooh I'll make a note to try that

sinful agate
tiny sapphire
hexed solstice
#

getting virtio-mmio up and running on 68k is proving more obnoxious than expected

#

qemu-system-m68k for some reason appears to expect that when you write to VIRTIO_MMIO_QUEUE_etc registers that you write a guest-endian value (big in this case) rather than a little-endian one

#

i tried otherwise but it didn't work; i am going to have to be dead careful when i code anything here to make sure that i pay mind to what qemu expects. hopefully the queue address stuff is the only exception to the principle of little-endian everywhere in virtio

vale pelican
hexed solstice
#

finally managed - i think, i don't want to tempt fate - to untangle what qemu wants to be in guest-endian and what in little-endian. so now i can actually submit commands

#

it looks like getting to the actually framebuffer from here should be straightforward but it's time for a tea break anyway

hexed solstice
vale pelican
#

nice

hexed solstice
#

cheers. now that i know it works, it's time to iop-ify the driver

hexed solstice
#

i always enjoy bringing back the terminal

#

no VM statistics as there's only a minimal VMM up and running in this port so far

stone orbit
#

i remember it being blue

#

dark blue rather

hexed solstice
#

i must've made an endianness mistake

#

it is dark blue on amd64

stone orbit
#

i thought my eyes were playing tricks on me ๐Ÿ˜‚

#

also, are you planning on upstreaming this port?

#

i'd love to see how people approach multi-arch kernels

hexed solstice
neat steppe
#

There are other portable kernels u can also take a peek at in the meantime

neat steppe
stone orbit
#

i see, i started writing my new kernel yesterday and im having a little trouble planning out the arch specific things, not that it has to be right the first time but id like to have some level of organization from the start

hexed solstice
#

i am planning to add a third arch as well, which might be aarch64 or even riscv64

stone orbit
hexed solstice
hexed solstice
stone orbit
#

thanks ๐Ÿ˜„ in the meantime ill do what will said and look at how other people deal with it :^)

sullen fern
#

My kernel is multi arch if you consider printing hello world on riscv and arm multi arch meme

hexed solstice
#

one thing that is quite worth thinking about is interrupts, i previously assumed there was a concept of IRQ number or rather GSI number but on virt68k it's different, i have instead seven hardware interrupt levels and 6 PICs. so i am moving to having an object which designates an interrupt source and with which you can do things like mask or unmask it, and associate it with a handler

sullen fern
#

I have a HAL layer which manages things like architecture initialization, timers, interrupts and modifying pagetables

neat steppe
#

it abstracts the platform, not the architecture

#

the architecture specific code is in the kernel (and is simply separated out into arch specific subdirectories in each kernel component) since a particular kernel build is arch specific by nature anyway

#

what the HAL contains is platform specific stuff that varies across different platforms of same architecture

hexed solstice
#

i make some assumptions which i may need to change in the future, e.g. that a platform has a facility for providing a timer for each core and that i can get that up and running trivially (because DeviceKit initialisation has to happen in true, non-idle-thread context now since it involves sleeping)

neat steppe
neat steppe
#

by sending an IPI from the one core that gets the timer interrupt

#

to the other ones

#

(& if it doesn't have an IPI mechanism it's shit)

hexed solstice
neat steppe
#

Yeah I don't know how you could implement a general purpose OS without one

hexed solstice
#

even if it has something cool like a broadcast-tlb-flush instruction i still give up on such a platform because i like to do things like send an ipi to a core to preempt it when a thread suited to run on that core becomes ready

sullen fern
#

I just call it a HAL

#

It's a generic name not tied to NT

neat steppe
#

Think it is tied to NT

#

Never seen it used in any prior situation

#

All you really need though is per subcomponent arch specific directories

#

That's what I've been doing and it's been pretty clean so far

#

You could also put it all together in one directory per architecture but that's a bit too far removed from the context of where it's used for my taste

stone orbit
#

i dont remember if i ever asked this, or if i did whether i got an answer or not, but does anybody have any resources about interrupt management? id love to design everything in my kernel properly from the ground up and i feel like interrupt management wont be very complicated but it will let me implement core parts of the kernel along it

hexed solstice
#

there are two major items of interest i think

#

the first is the approach to prioritisation and suchlike and how scheduling fits in with interrupts

#

the second is the abstraction of interrupt sources so that drivers can be written generically

stone orbit
#

i guess interrupt management will be more complicated than i expected

hexed solstice
#

i had a brief chat with #osdev irc about this at one point and they didn't care for interrupt prioritisation and instead they advocated for making every interrupt threaded, and certainly i can see that such an approach isn't totally without merit, but i have committed to the IPL concept and make extensive use of DPCs so it isn't for me

stone orbit
#

i wanted to go the dpc route because it seems fancy lol, and mainly because i dont really know any other approaches

hexed solstice
stone orbit
hexed solstice
stone orbit
#

so its more of a โ€œno need to trouble yourself with that for a hobby kernelโ€ argument

hexed solstice
#

well, they actually argued against them entirely for any kernel

#

out of date concept, they said

stone orbit
#

dumb

#

irc guys cant make ip their mind

hexed solstice
#

fortunately i am also out of date now (you go out of date after the age of 25) so it's no problem for me

#

i hate clang-formatfformatting

stone orbit
#

// clang-format off to the rescue!

#

also before that i like to try and tame it with //

#

is your column limit like 70?

hexed solstice
stone orbit
#

damn that is still pretty low

#

i find 120 to be a lot, but i dont hit it often

#

im often below 100, which is pretty good for me

#

but it may be because i have a high resolution screen + i use a small font size ๐Ÿ˜…

sinful agate
twin haven
# stone orbit i'd love to see how people approach multi-arch kernels

fwiw I've taken a similar approach to what abbix describes: there's a collection of functions that abstract away platform specific stuff, and the rest of the kernel is built on top of those. I found the tricky part to be deciding exactly what I wanted those abstractions to be, but once in place its been pretty easy to maintain support for 2 archs. The real test will be adding a third ๐Ÿ˜† .
It's basically just a set of common headers, and then each architecture can add its own implementation files to build with the rest of the kernel, depending on the target arch for that compilation.
So far I'm finding it better to abstract at a slightly higher level than I initially though, and then emulate any missing features for that arch in software where necessary. Not sure how that will work out long term though.

#

(sorry for ping, forgot to disable it)

stone orbit
#

nah its alright, thanks for your input!

#

and as you said i find the "what should go where" part the hardest so far

hexed solstice
twin haven
#

I found it way easier starting with 2 at the same time, then adding support for a second one later (my original approach)

hexed solstice
#

i am thinking of throwing aarch64 into the equation here as well so that i am sure i design the right abstractions

twin haven
#

haha same ๐Ÿ˜†

hexed solstice
#

in fact i'll do it just as soon as i figure out how one pairs limine with, i suppose i'll go for qemu's aarch64 virt

stone orbit
#

i think tackling both the kernel design and learning a new architecture at the same time might be too much for me, idk what to do

stone orbit
#

yeah unfortunately!

twin haven
#

for all its jank, riscv is similar in a lot of ways to x86 (in the context of learning a new arch)

stone orbit
#

from what ive heard it has a lot of weird quirks

twin haven
#

a lot

#

but the core of it isnt too bad

hexed solstice
#

man the arm architecture reference manual is positively mastodontic

#

13 thousand pages

#

meanwhile i am happily perusing the nxp 68040 user's manual at 450 pages

stone orbit
sullen fern
vale pelican
#

prior to armv9 it was only 9k pages

#

or at least i think it's because of armv9

#

because i do have older copies somewhere

vale pelican
# hexed solstice i am thinking of throwing aarch64 into the equation here as well so that i am su...

well virtual memory doesn't differ that much from x86_64 in my experience, except that the virtual addresses are 1 bit larger (49 vs 48), with separate registers for page tables for the lower and higher halves, and that there are no mtrr equivalent to automagically set correct caching modes for mmio, and that at the bare minimum, the cpu does not do dirty bit or accessed bit tracking so you need to emulate it

hexed solstice
vale pelican
#

true, it's more flexible, but you can also just configure it to be very similar to x86_64 (4k pages, 4 levels)

hexed solstice
#

68040 also has separate registers for the higher and lower halves' page tables (and then it multiplies the number by two again, having separate tables for data v.s. instruction accesses - i don't know why this feature is present)

vale pelican
#

only reason i can think of is execute-only pages

hexed solstice
#

i now have an aarch64 toolchain together and i figured out the magic incantations to launch qemu-system-aarch64 with the uefi firmware, and limine just worked (very nice)

#

now to familiarise myself with an architecture about which i know next-to-nothing

sullen fern
#

Compared to x86

vale pelican
#

well it is very flexible, but after that the actual page tables are quite similar if you configure it to use 4k pages with 48 va bits

slender flame
#

It's not super complex at all

#

It's conceptually exactly the same

vale pelican
#

well theres a bunch of bits that if you get wrong doesn't work on real hw while working in qemu :^)

#

kvm helps a bit with finding those bugs but it doesn't catch all real hw problems still

neat steppe
#

and so it gets emulated so that it can be set with a spinlock held

vale pelican
#

ah huh

neat steppe
#

like they map the page read only initially and then use that to detect the first write rather than use the hw dirty bit

vale pelican
#

yeah that's what you're supposed to do on aarch64 as well afaik

#

for accessed bit emulation there is an access flag, that causes an access fault if unset in an entry (different fault compared to a non-present page)

neat steppe
#

iirc the race condition has to do with something like, you might check if the PTE has the dirty bit set, it's clear, then by the time the other core receives the IPI to flush the TLB entry for the page, it has dirtied the page

#

so you just miss the page being dirtied

hexed solstice
#

built on aarch64. my first priority will be to implement the IPL mechanism, context switching, and the basic setting of page tables for mapping devices

#

this will be fun as i continue to know virtually nothing about aarch64

vale pelican
#

nice, are you using limine?

hexed solstice
#

actually it traps from time to time in limine

#

i will collect some info about that next time i see it

vale pelican
#

i'd appreciate that

#

i don't think the aarch64 port has gotten any serious use so there may be some bugs lurking

hollow hull
#

i've never seen it trap in Limine myself

#

but it trapping from time to time makes me think it may have to do with KASLR?

vale pelican
#

yeah it being random makes me suspect it's something to do with kaslr

#

i've never had it happen to me personally, although i've had more runs where it fails because i'm working on it

#

so not a lot of chances for it to break where it should've worked

hollow hull
#

ig you can try running it over and over

#

ask yehuda for his kernel maybe, to better reproduce

#

in case it won't trigger otherwise

hexed solstice
#

doing some investigations atm

#

i actually can't reproduce it without timeout=0

#

and even then quite rarely

hexed solstice
#

epic, i made qemu segfault

hexed solstice
vale pelican
#

without uefi yeah, with uefi im afraid you only get acpi

hexed solstice
#

i can live with that

clever grotto
#

oh I guess fw_cfg isn't available through uefi

vale pelican
#

i mean its not reported via the standard mechanism (dtb guid in the system table or whatever it was)

clever grotto
#

yeah

#

oh fuck!

#

you find fw_cfg through the dtb

#

yeah no that's painful

#

so there's no way to do based fw_cfg shit if you use uefi

vale pelican
#

cant you find it via acpi?

clever grotto
#

maybe

#

I don't know

vale pelican
#

also i wonder if theres a uefi setup option to enable the dtb in the tianocore for virt, since there is one in the uefi fw for the rpi4

hexed solstice
clever grotto
#

nice

hexed solstice
#

why is every manual to do with aarch64 so big and sparse

#

constantly directing me to another section or to another manual for details

vale pelican
#

i recommend getting a pdf viewer with fast search functionality :^)

hexed solstice
#

and so many names and terms

hollow hull
#

any progress wrt this supposed Limine bug?

hexed solstice
tiny sapphire
#

whaat bug

slender flame
#

limine explodes and kills your whole computer and your family and then the CPU gains sentience and it stands up with lasers and KABOOM hole in the wall, uh oh, super CPU just escaped the socket, and it goes around the city blowing stuff up until superman stops it

frozen tendon
#

thatโ€™s not a bug thatโ€™s a feature

hexed solstice
#

i will try to induce it again some day

#

in the meantime i am trying a radical new approach to solving some very tricky bugs in the vmm

#

namely i am implementing it hosted, in a simulated form, with full access to all the tools that this places at my disposal

vale pelican
#

would be nice to have a proper way to do this so we could write tests for various operations

hexed solstice
#

i haven't decided yet how thorough i want to be with this

#

i can certainly spawn a few pthreads to do 'reads' and 'writes' and add functionality to inspect the state of all the data structures to make sure they appear sound

hexed solstice
#

i've got the code adapted to run hosted now

#

hooked up to mock platform ""mmu"" code

#

i can mock the keyronex async i/o mechanism as well with an elaborate system of threads and signals and then i can really put this thing to the test

#

should be able to try out all sorts of things, including out-of-pages conditions

twin haven
#

That's quite useful. Is the code available anywhere? This is similar to something I'd been thinking about trying (one day), I wouldn't mind the reference.

hexed solstice
#

the principle of it is quite simple

twin haven
#

No rush, I am neck deep in vmm + page cache shenanigans right now. ๐Ÿ™ƒ

hexed solstice
#

i shim the keyronex kernel functions that the vmm requires (spinlocks, mutexes, later i'll need to also shim the async i/o code which is required for file mmap and swap stuff)

#

thread-local variables provide an ipl, current pagetable, and current process pointer. as to the pages, right now they are an array of byte arrays. it works because the arch-specific MMU code provides functions like "get a virtual address at which i can read a given physical page" and how that's implemented is meant to be agnostic (so it could be done by a direct map, or by some kind of temporary mappings if i didn't want a direct map, or in this case the simulated arch mmu code just gives you the address of that page's data in the array)

twin haven
#

mm ok this all sounds very similar to how I was going to approach it

#

were there any particular pain points you encountered?

#

I hope you doint mind a brief interview ๐Ÿ˜†

hexed solstice
#

as for most of the metadata i just allocate that with system malloc so that valgrind/asan/whatever can deal with it (kernel wired heap has its own treatment anyway so i am not overly concerned about that, but i am more woried about making refcounting errors, inter-thread races, etc)

hexed solstice
#

and the idea will be that i'll create threads that will call access() with various random addresses for either read/write at random times

#

that should impose some nice stress on the eviction functionality

twin haven
#

interesting, so access() simulates a memory access and then you can wire that to your vmm's page fault handler?

#

well after checking the access is valid I guess

hexed solstice
twin haven
#

gotcha, thanks ๐Ÿ™‚

#

have you tested your scheduler/timers in userspace yet?

hexed solstice
#

i haven't, i think they are robust and reliable

#

except for one in twenty times running links and browsing the web there is an apparent race which i still haven't figured out

#

it probably helps that there is a global spinlock protecting the underlying primitives of scheduling, synchronisation, etc

#

so there is less scope there for problems

hexed solstice
#

in the future i will loosen the locking on it with fun new things like per-core ready queue locks, since that's the easy case. then the actual reschedule code will no longer contend on the global lock. i reckon that alone should be sufficient to get reasonable scalability

twin haven
#

I moved to that in the early days, but I remember it being a huge change for boot times

#

and a huge week of debugging

#

well worth it though imo

hexed solstice
#

the futex is the main thing exposed to userland for synchronisation, and that only relies on the global scheduling lock in the contended case

#

in any case i think being able to test components in userland is a huge boon

#

it's how i made my allocators robust

twin haven
#

likewise (re: testing allocators in userspace)

#

I've had this pipedream of slowly moving parts of my kernel into standalone userspace programs

#

starting with the vmm and scheduler (and I guess the device tree parser already exists standalone meme)

#

thanks for the insight

hexed solstice
#

no worries, and best of luck with your endeavours

#

i like northport, it's clean and well-architected based on what i've read of its code

twin haven
#

nice namedrop ๐Ÿ˜‰ I appreciate that

#

I'm well into "head down and research" territory right now, so my regular updates to it have suffered a bit, but I do plan on a third iteration.

neat steppe
#

I've been stuck ankle deep in a swamp for months straight half due to low motivation and half due to compiler design being evil

twin haven
#

hardly, my vmm/kernel is still relatively juvinile.

neat steppe
#

All of our kernels are juvenile

hexed solstice
#

trying to completely tease out all potential problems

#

make changes that will allow me to do all the fun things

#

and adopting the working set model

hexed solstice
#

there is no gain from paging the metadata of a memory object associated with a regular file vnode, there is obvious gain from paging the metadata of shared anonymous memory objects though

#

i use a three-level table for those

#

in servicing a page fault i think i'd really want to pin each level of these as i retrieve it, but that has locking implications

#

it would be foul to keep the map mutex (which protects the address space layout of a process) locked during the process, which would be the only way to ensure that the pages i pin into memory for that anonymous object as i potentially page them back in remain meaningful

#

i could, instead of pinning them immediately, instead just place them into the process' working set list, and hope that i don't end up in a cycle of chaos with them getting paged out before the page fault handler gets resumed after i/o

hexed solstice
#

vms/nt using linear tables here makes much sense

hexed solstice
#

suppose i could just keep a big "ongoing fault state" structure, including space for storing what anonymous memory object we faulted on + wired references to the needful pages making up its tables, and store the needful in there, and then test my assumptions when it's time

neat steppe
#

However that was prior to me having paged kernel memory

#

And I realized none of my shared memory sections were anywhere near big enough to warrant anything special

#

So I ended up just making it be a linear table appended directly to the end of the section object in memory

#

(Will obv have to change if they become extendable)

#

But basically I don't have to deal with that issue since I just have a small nonpaged linear array

#

If I did then I'd probably just do it the same way I do page table pinning

#

I might even have a special paged pool just for allocating chunks of prototype page tables

#

It'd be separated so that the pinning doesn't overlap with the other allocations on the same page too badly

hexed solstice
neat steppe
hexed solstice
#

i call it the refault state struct

#

and it can hold a reference to each level of the process' page tables for a given virtual address. and until dealing with huge pages, or even large pages, this can be done without any harm. so as we descend the tree, if we need to swap in a page, we can store a reference to it in the refault state for safe keeping before we begin a refault

#

doing this for shared anonymous memory objects, now that i think of it, should only be a little more effort

#

it should be sufficient to verify at each stage whether the value in the refault state struct is the expected value

#

is it the same anonymous object (top-level page same?) is the 2nd level the same? and so on

#

that's poorly explained but i am tired and unwell

hexed solstice
#

mock pmap for hosted development of the vmm is now operating

#

now i can experiment with all kinds of fun things

hexed solstice
#

@neat steppe unmapping (or protecting) regions really becomes a nasty business with pageable page tables

stone orbit
#

why not just page them in?

hexed solstice
#

unmapping becomes something that can block, and that means it has to release spinlocks when it blocks, but we have to make sure we keep everything sound

#

in principle we could hold the address space map mutex across the pagein, but then if we needed to evict pages from that map, we are in a bit of trouble as we can't

#

anyway i am not planning to support that just yet anyway, important thing for now is to fix up refcounting, accounting, and locking, and to move to process-local page replacement

hexed solstice
#

i think i'd like to implement a generic framework for resource accounting

#

should be hierarchically organisable and flexibly implemented, so that it might also be applied to e.g. cpu time, disk time, etc

prime coyote
#

or should do

hexed solstice
prime coyote
#

ah, so in this case resources != objects

hexed solstice
#

in keyronex it played a minimal role so far as mostly a place for reference counting logic to be shared in, in the keyronex branch i have been working on with m68k and aarch64 ports, which is not nearly up to feature parity with the main branch, it replaces the posix fds

#

actually in NT object manager probably does have generic code to charge processes for the objects they use

#

i'm not overly familiar with NT but this would make good sense

fierce blaze
#

do a risc-v port

hexed solstice
#

i'm sure i would get further faster with risc-v than with aarch64 as there can't possibly be as many manual pages to wade through

fierce blaze
#

risc-v should be a bit easier

hexed solstice
hexed solstice
prime coyote
#

hm, says page not found

hexed solstice
#

link fixed

hexed solstice
#

these were going to just be rough notes, but i think they might actually end up being what i work to when i implement this

#

i am crap at writing presentable rough notes, i feel the need t get in depth and at that point it's better to just do it thoroughly

hexed solstice
#

i should really figure out what's going on here

fierce blaze
#

No \r?
[Insert Megamind pic here]

wispy oasis
vale pelican
#

i think he:s talking about figuring out the fault itself

vale pelican
hexed solstice
vale pelican
#

ty

hexed solstice
#

keyronex/amiga68k loader is working again

#

unfortunately keyronex/amiga68k doesn't do anything interesting yet, but it does submit some copper lists and draws a cursor

vale pelican
#

nice

hexed solstice
#

that's more like it

#

font is NetBSD bold for anyone who cares

hollow hull
#

bitmap?

hexed solstice
hollow hull
#

ty

scenic plover
hexed solstice
scenic plover
hexed solstice
#

glad to hear it's so well regarded

hexed solstice
#

this has been a pleasant surprise

#

i will not tempt fate by speaking too certainly but it looks like i succesfully divided the virt68k specific code from the generically m68k when i wrote it

slender flame
#

if you wanna test irl tell me

#

I got an amiga for porting ironclad, that I can use for testing your stuff

hexed solstice
#

keep me up to date on ironclad porting to amiga for that matter

#

right now i'm trying to determine whether FS-UAE is being a prick or whether i've messed up my copper lists or something:

#

it only happens with one build of fs-uae so i've no idea

fierce blaze
#

i want to try on my amiga 4000 winuae config

#

which has amigaos 3.9 installed

#

and a cybervision 3d gpu

#

which looks much better than stock aga

hexed solstice
#

but it's very finicky

fierce blaze
#

cool

hexed solstice
#

the loader is a mess, i'll need to implement a serial driver as i can't provide any output for most of the load process because i need to turn off interrupts, enter supervisor state etc which is incompatible with further printing before keyronex takes over

slender flame
fierce blaze
#

what the fuck

ironclad java

hexed solstice
#

you have a stock A1000 right?

hexed solstice
#

just spent 2 hours getting agitated about keyronex not working on an (emulated) 68060

#

turns out that it's helpful to check whether amigaos exec is describing a memory region as being ram (and not rom) before you try to use it

hexed solstice
#

basic functionality of the amiga 68k port is now seemingly working

#

threads are scheduled, timers are managed, all the stuff i did for virt68k has largely carried over, and if anything it's been simpler for the amiga

#

there is still work to do, 68040 requires your bus fault handler to manually complete write-backs (it pushes a 30-word stack frame with state to help you figure that out) , there must be drivers, the loader is messy and falls apart with slightly unusual memory maps (which is common on amigas), and bringing up userland etc

#

but overall i am happy with how things have progressed so far on this port

hexed solstice
#

first attempt to run keyronex/amiga on actual hardware

#

it goes as far as printing this bracket

neat steppe
#

Exhilarating

hexed solstice
#

it looks like i can print constant strings but it dies on trying to print at least string and integral (?any printf specifier) parameters

neat steppe
#

maybe you ran into a 68k varargs regression

#

with your compiler

#

im sure someone would have found and fixed that by now

#

but then again its 68k

#

wait

#

it works on an emulator so thats not the problem

hexed solstice
#

i could use some debugging facilities

#

let's see if i can install a fresh IVT nice and early, and manually print out the faulting PC

#

assuming an exception is generated somewhere and i am not having to chase some unfunny kind of problem where the PC goes walkabouts

#

thank you

#

i can work with that

#

that's an illegal instruction exception

#

fd000322: 000c .short 0x000c

hexed solstice
#

this thing is very troubling

#

it fails in a seemingly nondeterministic way

#

and sometimes it even succeeds in the printfs but leaves the specifiers unexpanded

hexed solstice
#

presumably the emulators just implement those

hexed solstice
#

i seem to be consistently ending up at strange PCs

#

but just to be as annoying as possible, it actually worked exactly once

neat steppe
#

probably something to do with an interrupt then

#

timer interrupt or something

hexed solstice
neat steppe
#

then what could it bee

hexed solstice
#

that's what is torturing me

#

i'm collating the location of all the exceptions

hexed solstice
#
--- out2        2023-08-26 20:02:08.741696209 +0100
+++ out 2023-08-26 20:08:45.571670175 +0100
@@ -440,6 +440,7 @@
 fd0003ec:      2140 0006       movel %d0,%a0@(6)
     while ((*cur >= '0') && (*cur <= '9')) {
 fd0003f0:      206e fffc       moveal %fp@(-4),%a0
+BAD! 3f2
 fd0003f4:      1010            moveb %a0@,%d0
 fd0003f6:      0c00 002f       cmpib #47,%d0
 fd0003fa:      6f0c            bles fd000408 <npf_parse_format_spec+0x166>
@@ -472,10 +473,12 @@
 fd000434:      6610            bnes fd000446 <npf_parse_format_spec+0x1a4>
       out_spec->prec_opt = NPF_FMT_SPEC_OPT_STAR;
 fd000436:      206e 000c       moveal %fp@(12),%a0
+BAD! 438
 fd00043a:      7002            moveq #2,%d0
 fd00043c:      2140 000c       movel %d0,%a0@(12)
       ++cur;
 fd000440:      52ae fffc       addql #1,%fp@(-4)
+BAD! 442
 fd000444:      6070            bras fd0004b6 <npf_parse_format_spec+0x214>
     } else {
       if (*cur == '-') {
@@ -533,10 +536,12 @@
 fd0004b6:      70ff            moveq #-1,%d0
 fd0004b8:      2d40 fff8       movel %d0,%fp@(-8)
   out_spec->length_modifier = NPF_FMT_SPEC_LEN_MOD_NONE;
+BAD! 4ba
 fd0004bc:      206e 000c       moveal %fp@(12),%a0
 fd0004c0:      42a8 0014       clrl %a0@(20)
   switch (*cur++) { // Length modifier
 fd0004c4:      202e fffc       movel %fp@(-4),%d0
+BAD! 4c6
 fd0004c8:      2200            movel %d0,%d1
 fd0004ca:      5281            addql #1,%d1
 fd0004cc:      2d41 fffc       movel %d1,%fp@(-4)
@@ -548,6 +553,7 @@
 fd0004da:      7412            moveq #18,%d2
 fd0004dc:      b480            cmpl %d0,%d2
 fd0004de:      6500 00a8       bcsw fd000588 <npf_parse_format_spec+0x2e6>
+BAD! 4e0
 fd0004e2:      d080            addl %d0,%d0
 fd0004e4:      2040            moveal %d0,%a0
 fd0004e6:      d1fc fd00 04f2  addal #-50330382,%a0
@@ -567,6 +573,7 @@
 fd00051e:      2140 0014       movel %d0,%a0@(20)
       if (*cur == 'h') {
 fd000522:      206e fffc       moveal %fp@(-4),%a0
+BAD! 524
#

some of the sites i have observed bad PCs at

#

(if i say bad! + fragment of an address, thats the pc i observed a fault at)

#

now the interesting part is that they almost all involve %fp-indirect addressing with displacement

hexed solstice
#

i hit it with a big hammer

#

it still doesn't work 100% of the time

#

sometimes a bus error happens trying to access an address which should have been mapped by the loader

#

anyway

neat steppe
#

bus error dont necessarily mean not mapped

#

just that theres nothing on the bus for the corresponding physical address

#

or that you used it wrong

hexed solstice
#

i need to check the exception frame for it

#

i think at least kprintf works now which makes this much less hassle to deal with

#

i had been mapping pages in which page tables lived with copy-back cache mode for some reason

#

and the 68060 doesn't enjoy that

#

then I had to install the M68060 Software Package into my kernel

#

it's a set of wrappers for your exception handlers to do things which ought be done on 68060s

hexed solstice
#

i'm happy with this for now, it's been a good day's work

neat steppe
#

yeah that is really good progress

hexed solstice
#

i studied the 68040 manual in depth but only skimmed the 68060 manual but i did vaguely remember reading that unlike the 040 it doesn't consult the data cache when walking page tables

hexed solstice
#

CRTs look so good. retvrn

clever grotto
hexed solstice
# clever grotto I miss them

they were working on nicer display tech to try and preserve some of their nice properties up until the great recession

hexed solstice
#

something i've touched while working on the amiga port has broken virtio-gpu on virt-m68k apparently

#

ugh

#

repeated notification of the same completion

#

turned out to be as simple as forgetting to initialise allocated kernel wired heap; previously that would zero, now it doesn't

echo whale
#

amazing work, does this require a MMU?

hexed solstice
#

i will do the 030 mmu at some point when i can be bothered with the complexity + lack of a good debugger (qemu doesn't emulate it)

#

for now i am considering doing a driver for the scsi controller in my a2000 (ncr 53c710 based) but i can't figure out how to configure FS-UAE for it. options have inconsistent naming conventions, it's a mess

hexed solstice
#

no, i think i'll adapt the virtio-disk driver to the changes in devicekit, and then do an ext2 driver. keyronex has been in the odd position of having 9p and fuse but no disk FS driver yet, and this will be worth doing to reset some compasses that might have lost their bearings

hexed solstice
#

i've implemented a monstrosity, the Grand Unified Buffer Cache (GRUBC for short)

hollow hull
#

lol

hexed solstice
#

this provides a buffer cache interface and buffer cache level of control over when individual blocks get written back while participating in the system page replacement policy

#

using the partition device's page cache is unacceptable because FS block size < page size leads to problems like the partition device's page cache caching pages which contain metadata (desired in this case) and file data (undesired, produces incoherence with respect to the page cache of those block's owning files), and there is no sensible way to represent the ext2 metadata blocks in the form of a contiguous address space composed only of metadata blocks (as you can do for files)

hexed solstice
#

i am thinking of implementing the StorPort API for storage drivers. it might be a fun lark

#

i had a look at some typical storport drivers and they tend to only use these 20 or so functions

glad sentinel
#

huh

#

are the vast majority of windows storage drivers written against that API?

hexed solstice
#

all the high speed modern ones at least, it seems

glad sentinel
#

The MS page that was the top Google result made it sound like it was for things like fibrechannel

hexed solstice
#

and some of the older ones against a previous, similar API called scsiport

glad sentinel
hexed solstice
#

now some of these functions are really multipurpose ones so there's a larger API surface than appears at first glance, but i'm sure this wouldn't be a huge amount of work to implement the basics of

glad sentinel
#

oh man

#

This repository holds the source code to NetAdpaterCx.sys.
NetAdapterCx.sys ships with Windows, so you don't need to compile it yourself. However, you can use this reference source code to debug your own NIC driver, and to learn how NetAdapter works.

While we're proud of our API documentation, we know that even the best docs can't always answer every question you might have. Sometimes, you just have to refer to the source code. We've published this code so you can be more productive while developing your own NIC driver. Our aim is to make the inner workings of NetAdapterCx as transparent as possible.

#

After you get done with storport ๐Ÿ˜›

hexed solstice
glad sentinel
hexed solstice
#

that ahci driver will be a nice test

#

meanwhile i've discovered gcc lets you annotate a function with an ms_abi or sysv_abi attribute which will save me having to write asm shims

hexed solstice
#

i've thrown together a coff/pe loader and successfully loaded viostor; now i'm going to try to figure out how one makes a debug build of it so i can start exploring further

glad sentinel
#

nice

hexed solstice
#

making progress with this storport shim

#

this is atop a testbed kernel i threw together, i need to bring it over to keyronex now before i can get much further

glad sentinel
hexed solstice
#

allegedly the viostor driver for windows is set up and ready to go

#

i expected it to ask more of me. i suppose it will when i ask it to start doing i/o

glad sentinel
#

hell yeah

#

also that banner is dope

hexed solstice
#

maybe an endian mixup since i reprogrammed the console for m68k

#

turns out viostor.sys doesn't actually do much if you don't path a registry path argument to its DriverEntry routine, so I have done the needful there and now it's calling that mastodontic StorPortNotification function with all sorts of requests

hexed solstice
#

first Srb submitted and apparently worked - it just read the device ID

hexed solstice
#

it's notifying the the virtqueue and getting no further, let's see if i can figure out what's going on

hexed solstice
#

first i/o scsi request block submitted and the expected result appeared

glad sentinel
#

that was fast

hexed solstice
#

but i am happily surprised to see this so soon

glad sentinel
#

roughly how many lines of code did you have to write to make it this far?

hexed solstice
#

about 700 on shims, 200 on a PE loader

glad sentinel
#

notbad.jpeg

hexed solstice
#

it's the bare minimum to get any I/O done but i'm keen to expand this now

#

keyronex will become the no. #1 hobby OS for disk drivers

glad sentinel
#

I'm honestly surprised more people don't take this route

hexed solstice
#

if someone suggested it to me before i would've thought it was an outlandish idea which is impractical, after all, even reactos struggle with windows drivers

hexed solstice
#

first read using windows storahci.sys driver on keyronex

glad sentinel
#

hell yeah

sullen fern
#

Holy shit, nice

hexed solstice
#

currently in the midst of refactoring this storport driver layer, which has been until now an experimental toy, into a proper component of keyronex

#

and indeed i think i will actually use this as the standard way to implement SCSI hba, and even other disk HBA, drivers for keyronex

hexed solstice
#

windows virtio-scsi driver is now working

zenith karma
#

windows supports virtio-scsi?

hexed solstice
zenith karma
#

ah

hexed solstice
#

i'm going to try to get the refactoring branch organised and ready to put on github over the next few days

#

i know at least 2 people are interested in the storport shim so i owe them to do it

glad sentinel
#

I'm eager to take a look

#

I want to investigate how feasible it would be to do other Windows driver interfaces, mostly for WiFi tbh

ember geyser
#

oh, so something similiar to what wine does, very cool

hexed solstice
#

i've been trying to do a little work on making the aarch64 port do anything interesting but jeeze is aarch64 one of the most motivation-wrecking platforms i have ever worked with

#

i can't put my finger on what it is

#

maybe their sparse and insipid manuals

vale pelican
#

don't worry, it's been like 2 years and managarm still does not boot into weston on the pi4 :^)

#

although it does boot into weston in qemu at least

hexed solstice
#

it might be all the new acronyms

vale pelican
#

well it was a bit overwhelming initially, considering that when i started working on the port i had no prior experience with aarch64

#

on real hw the main problem currently is usb stuff and sdhci, apart from that the road to weston should be simple

hexed solstice
#

while me and the 68k and x86 go way back

vale pelican
#

it took me quite a while to figure out the page tables too

#

including caching modes

#

i remember having a lot of trouble getting mmio (to talk to the uart) working on a real pi4 initially

hexed solstice
#

the documentation is spread out all over the place, i found in one document the format of non-terminal page tables and another hadthe format of terminal page tables' PTEs!

vale pelican
#

and way later i had a weird bug due to a one character typo that caused smp to be borked in a really weird way (reads to a per-cpu register seemed to arrive from a random cpu and not the one that actually issued the read, because i accidentally mapped it in with nGRE and not nGnRE)

#

if you have hardware where you can run your aarch64 code in kvm i recommend doing so

#

it can help catch some things that qemu doesn't care about (like forgetting to enable caches, which breaks atomics)

glad sentinel
#

I've been working on aarch64 page mapping code for the past two days lol

glad sentinel
vale pelican
#

unfortunately it won't reveal caching issues per se (picking the wrong memory type)

glad sentinel
#

worst comes to worst I break out the JTAG ๐Ÿ˜›

vale pelican
#

i remember trying to get it working on my pi4 but couldn't