#Keyronex
1 messages · Page 7 of 1
i will look at it when i get tired of inserting printfs
figuring out a real program will distract me too much right now
dnsmasq.conf: dhcp-range=192.168.0.1,proxy enable-tftp tftp-root=/home/qookie/rpi-netboot pxe-service=0,"Raspberry Pi Boot" pxe-service=ARM64_EFI,"Limine",BOOTAA64.EFI and ```
$ sudo dnsmasq -d -C /.../dnsmasq.conf
:^)
192.168.0.1,proxy means it just sends the bootp response and doesn't provide a full blown dhcp server
thanks that's actually very helpful
but i'll deal with this stupid thing just once or twice more
i think i've localised bug to ioapic class instantiatioon
if you use boot:/// in your limine config you don't even need to change it
This is pretty useful actually
BTW do you have the power button hooked up for testing? @hexed solstice
oh, it's not where i expected it to fail surprisingly
no dice with dnsmasq i'll have to go back to iventoy
oddly it does report dnsmasq-dhcp: PXE(eth0) 8c:16:45:fe:c7:2c proxy and then does nothing
dhcp-range=192.168.178.1,proxy
enable-tftp
tftp-root=/ws/Projects/Keylite/build/amd64/isoroot
pxe-service=0,"Raspberry Pi Boot"
pxe-service=ARM64_EFI,"Limine",BOOTX64.EFI
hm well change ARM64_EFI to X86-64_EFI
and you can drop the Raspberry Pi Boot entry, it's for having the rpi firmware load stuff over the network (i was netbooting uefi, then netbooting limine over uefi, then netbooting a kernel)
wtf it worked
thanks
that saves time on iteration
Where does it die?
now i see it
it died in a kassert but my kassert previously dumpde only to serial port
_n_redirs = ((ioapic_read(_vaddr, kRegisterVersion) >> 16) & 0xff) + 1;
kprintf("done read it. how many redirs? %d\n", _n_redirs);
kassert(_n_redirs <= 24);
_n_redirs = 120 (why am i using this hideous identifier naming convention here? this is old stuff)
Lol
i haven't touch ioapic since 2022, let me have a quick review of the spec to see if this assertion is sensible
Maximum Redirection Entry—RO. This field contains the entry number (0 being the lowest
entry) of the highest entry in the I/O Redirection Table. The value is equal to the number of
interrupt input pins for the IOAPIC minus one. The range of values is 0 through 239. For this
IOAPIC, the value is 17h.
alright then, it's a fine reading, and in any case i obviously didn't pay attention the first time
uacpi laying it on thick with traces
bloody hell
and at last we got a page fault in an unacceptable area
following OBJECT_ALLOC_TYPED(0x19)
within the kernel wired heap area
Is that an allocator corruption 
it's not impossible but it's not likely
this allocator has dealt with far worse challenges than this and came home to tell the tale happily
Interesting
let me shut up the traces and see what i can find out
but now i really am getting tempted to bring in a kernel debugger
i'm not writing an xhci driver just so i can attach a gdb stub
to some usb serial adapter
kmem (slab allocator) appears to be served up with a block of memory which, well, is not mapped. going to try to identify why
no obvious problems
i have no answer to this yet
is it trying to map it?
@earnest salmon
the offending address appears to be mapped by a valid/writable PTE (0x7b1fa007) and 0x7b1fa000 appears to be a legitimate page
no i really don't have any idea of what's gone wrong yet
i need a usable environment for exploring what's going wrong in not worthless printfs
Are you going to make a kernel debugger now?
maybe at some point
i really need something
i have very little to go off here
You need even more printfs
i need something dynamic so that the extremely stupid mistake that i've probably made becomes obvious when i start probing
that's usually how it worsk
Lol
the whole thing is quite embarassing really, i have no idea why something so apparently trivial is defeating me
i know what you need
you need ebpf
or dtrace, which is the same thing (in-kernel vm that you can use to attach code to whatever code path you want)
i have a working hypothesis now
yes
i think it's this
well what else could it be. i don't immediately understand how but this makes the most sense
What's the bug?
probably the new kvm reallocation routine (which is being used in my local repo) not doing what it ought to do for tlb invalidation
great
it fails where it ought to now
13 aml blobs holy
thinkpad t480s for reference
No ec handler causes aborts in some places, expected
You can work around that by pretending to be windows xp if you want
It will use SMM instead
But doesn't really matter
https://github.com/managarm/managarm/blob/master/kernel/thor/system/acpi/ec.cpp mangarm's stuff for it looks quite compact
Yeah its pretty simple
Technically it should be asynchronous and use interrupts but whatever
i will have a look at it at some point
for now the important thing will be supporting a tmpfs
i don't understand why it does yet
i deliberately don't reuse kernel wired address space yet because it's supposed to be enqueued for later reuse after every processor has shot down the relevant TLBs when quiet
(because the only 32-bit plaforms, where i may really need to reclaim the address space rapidly, that i support, are ones that aren't multiprocessors; while for 64-bit machines it's not a problem to defer reclamation in this fashion)
so i don't understand yet why it mattered that i invalidated the old addresses
they a) shouldn't be used anymore, but b) if they were, then that should've turned into a fault when i started invalidating them anyway, and c) they shouldn't be used again, because that region won't be given out again by the allocator (not until i have the lazy kvm space invalidation implemented)
Bruh oberrow curse is spreading even to fadanoid
what happened with you?
Allocator and vmm bugs
i've reconfirmed it
everything goes to shit if i don't immediately invalidate the freed area
despite that the area shouldn't be reaccessed and it's in a different, newly allocated, validly-mapped area that the offending fault happens...
- 0xffff820007106000-0xffff820007107ffff allocated
- 0xffff820007106000-0xffff820007107ffff freed
- 0xffff820007108000-0xffff820007109ffff allocated
- non present pf 0xffff820007108000, despite that a valid PTE exists
now the relevant part is that immediately after 2 and prior to 3, the pml1 page that mapped that area is freed
and if it's not freed, then no tlb flush is necessary and everything works
i can deal with that
i wonder what ethernet adapter this has
intel i219 apparently
the datasheet is lite on information
this looks like it's supposed to complement some other resource
What do you need the driver for?
my laptop has one of these
this is by far the easiest way i'd be able to get a gdb stub
yes, the data sheet is lite on details and it seems that you have to refer to your hopefully-existing body of knowledge on e1000e (i have none), there are a lot of differences
so many variants
this is ridiculous
and the i219 documentation even with respect to other stuff i've found on e1000e dosen't seem adequate
i'm going to refer to the netbsd driver
i have mae a small start on this thing
seems you can just follow any e1000 documentation and it's all mostly the same apart from subtle quirks detailed in the bsd drivers (the freebsd one being from intel itself)
much is said about an e1000 vs e1000e distinction but i think it doesn't exist
they are the same thing
it's just that linux has two drivers for whatever reason, but freebsd's e1000 driver (directly from Intel themselves) draws no distinction and drives alike what linux calls e1000 and e1000e
the osdev wiki article on e217 was a nice read courtesy of infy but it's an absolute mess
just look at this outrageous function
eerprom indeed
the trick seems to be consulting one of the older e1000 models' specs, as the i219 spec is extremely lite on details, but what's said of the older ones applies just as well
Can confirm this is correct
An e1000 driver should work on almost every derivative since
The lyre (rip) driver was nice and simple, I started with that before adding quirks around it
The newer drivers (e1000e, igx or whatever its called) include more features and behaviours but the core is mostly the same, just messier lol.
i have the driver happily notifying me of packets received on my laptop but on qemu it's hellish
interrupts and won't stop interrupting
So when he does it it's cool but when I do it, "make a gdb stub!!!@!Q@#W!#!@!@!"? smh
anyway sorry about that I'm a bit tired
He's making a gdb stub tho
qemu is bullshit
when you read ICR it's supposed to clear it, it says so in the spec
but qemu doesn't, like a riotous rebel
It's not clowning. You can define an ABI for it, just like any other ABI, which could yield binary compatibility should this be required.
it would be a massive performance hit
and lots of work
for no gain
or minimal gain anyway
No performance hit, can do AOT compilation as part of the driver installation process.
The gain is probably minimal, yes.
that is a massive amount of work
you'd basically be bringing in an ebpf jit
There are frameworks like LLVM that would make this not a massive amount of work.
you can't shove that into kernelmode
and "driver installation process" is not a thing on most platforms
and going through bytecode is a performance hit anyway
it's entirely an an academic point because no one is doing anything meaningful to revive UDI, and if they were, this would turn their task from "revive an actually-existing framework" into "figure out what on earth this bytecode will look like, build lots of tooling around it, pray God you don't make mistakes because you're going to kill debuggability with this, and then somehow revive UDI"
IIRC UDI defines some tools, including for installing drivers? I don't really remember. The functionality would be put there and then as far as the kernel knows, there's nothing special going on.
you don't have to define a bytecode
you can just use ebpf
lmao
use aml 
i mean
ebpf is not Turing complete
or at least use one vm instead of 10
Could probably steal the Singularity OS code from Microsoft, doubt they'd care about a hobby OS.
that is highly illegal
It is but I dobut they give a crap.
i can't remember if singularity is even garbage-collected
id assume so
It would have to be.
this is just stupid
there was one of these C# kernels that wasn't
i dont think there's any other way to put it
in any case founding a new universal driver initiative on stolen code is obviously counterproductive
and a massive amount of code
awful license
that everyone has to pull in
it was microsoft's attempt at a fully C#(++) kernel
source: we tried :^)
nah bro its fine you can just ignore the license
cosmos
Well, if someone were to do it as a hobby project, they could. All of these projects are hobbies so it's not like there's any decision that has any impact. "Oh no, better not do that becase..."
thye have one now
really?
idk maybe it doesn't have much impact on YOUR decision-making process
but i would not want to pull in nt code
so it wouldn't be UDI
You don't have to. They're hobby projects and anyone can muck around with their own toy designs, none matter.
you don't know that
it would be DI for people happy to swipe random microsoft code
yeah that too
even if you could get away it, its unethical - surely not a label you want to attach to your project.
I don't think CIL is an appropriate bytecode for UDI specifically anyway.
we all know no one but hobby kernels would likely ever implement a revived UDI anyway but it's a bit short sighted to cut off the possibility of it ever getting used by anyone else
Just answering since someone mentioned it.
i mean id use ebpf
if i had to choose something
it's... reasonably fast
has verifiers
i think no bytecode is appropriate for it. UDI is already mind bending and i'm not sure it can meet modern requirements
and you could probably shoehorn it into a kernel
Isn't that a realtime thing? Because that would have a performance hit associated with it.
no its not
it's used for literally every bit of userspace-posts-code-into-the-kernel in all of linux
and windows too now i guess
UDI isn't mind-bending, it's a pretty simple interface. The manuals are large cause they are super repetitive with two sides describing everything.
its actually pretty similar to dtrace
fafnir 
you don't want to maintain 30 different vms, you want to maintain one really fast one
for example, how do you do this pattern with UDI?
- you use NVMe and you create NCORES queues and direct an MSI for each queue to one core only, so there's a 1:1 core-to-queue correspondence
- you only submit work to your core's associated queue
- you are now liberated from locking around each queue, because you only ever deal with a queue on the core it's associated with
Anyway, if I were to implement UDI, I probably would not define a portable ABI for a hobby OS. Just saying there is non-zero merit to the proposal.
i don't say that it's impossible to do with UDI, because i am not smart enough to understand UDI without spending probably a long time experimenting with it
but i did not get the impression that it could express such patterns as these
i don't think such a generic interface makes as much sense for fast devices
but for slow devices it's perfectly acceptable to do them in python in userspace imo
(except that it's python, ofc)
storport can do it but in full fairness storport is not meant to be generic
it's specifically for modern style host controllers which have queuing and specifically for windows
Also note that having a UDI environment does not stop and OS from having its own native interface if it wants to do anything "special"
but surprisingly not so difficult to implement on another host
honestly just do all the slow shit in like
idk go or something
in userspace
with a gc
so you can't fuck up as hard
and put it behind a giant lock because for userspace nobody cares
There's probably no reason to since not enough drivers exist for it. It would be of value if enough of the community started implementing in and then people would get free drivers but there's no way to control that and so it is almost certainly never going to happen.
yes, that was offputting when i looked at it
implementing a big and complex framework is one thing, but implementing it solely so that i could then trouble myself to write drivers for it, and not have any clearly visible way to write the drivers to use modern techniques like queues with cpu affinity, was not overly appealing
there's only one way to make it work
and that is to write all the drivers in your os for something portable
and then shill it until other people port it to their os
the Keyronex® DeviceKit™ framework
if you have DPCs and such, sort of
but they are quite bound up with the IOP system
speaking of drivers
the basics of the e1000 driver are now in
including zero-copy tx with scatter/gather and not-too-many-copy rx
I'd be interested to see your approach, what branch is it all under?
It doesn't really work like that, you will find.
which part?
the make your drivers portable part?
or the shilling your library to other people part?
because given the success of limine, flanterm and uacpi, the shilling your library to everyone part does seem to work rather well
and mlibc too
First because device driver interfaces tend to be tied to kernel designs so you can't really write portable drivers---which is what led to the design of something like UDI, otherwise it would not have been considered necessary. Something like C standard library is a lot simpler to port. That said, I would argue that none of those projects are a "success" but the standard by which one defines what is to be considered a success can obviously vary.
i mean
fadanoid above ported some windows drivers to their os
also, a lot of things aren't really OS-specific?
like
"i need some way of getting IRQs delivered" is pretty much everywhere
Good for him, that doesn't mean that the drivers are cross-platform by my definition.
interfaces for exposing other things are of course more complicated
but also, lots of hardware doesn't have a lot of design freedom in terms of how you expose it
i would love to see how you expose a block device other than as "read/write/discard block X and signal a completion in some way"
You can write a C program that conforms to the ISO standard and make sure it works on any C implementation just like you should be able to write a UDI driver that runs on any system with a complying UDI environment. If you want to take blocks of code from here and there and change them to no end, then I suppose you can call anything portable, even the Windows UI, whatever it's called.
you can write a limine-protocol-compatible kernel and use it with any limine-protocol-compatible loader (of which there is exactly one because why would you make your own one)
thats a success by your measure
You can although a boot loader is less tied to an OS' design because it just sets up the environment and passes along some data structures.
Not that limine is a boot loader in wide use or anything.
yeah... i'm not sure how such a driver interface would work without inherently restricting how you can design your kernel
Although you can implement UDI natively, if you like, it was designed in mind with implementing it on top of existing driver interfaces too. The reference implementation has some environments for various OSes.
IIRC Solaris, Linux, FreeBSD, UnixWare, OpenServer, Darwin were all supported and there's also some bare bones POSIX stuff in there.
Think of it as an API as you do OpenGL or sockets.
They try to put minimal constraints on the hardware or OS or drivers but naturally if someone came up with something super exotic, those might not be the best fit either. It's interoperability that is the goal there.
depends on your definition of wide use; definitely in wider use than UDI
I did not venture to call UDI a success as far as adoption goes.
in that both are quite a bit less efficient than driving hardware directly?
DPDK is a massive step up in terms of perf afaik
i mean massive enough that it's a thing
Historically speaking, a lot of shit happened at that time. For example, the tinfoil hat Richard Stallman wrote a piece about how UDI is bad because they are agnostic to free software vs proprietary and did not mandate a free software license so maybe people would start using proprietary software on free OSes (which happens with other types of software anyway) or vice versa (which I do not see why that should be an issue).
It's pretty transparent. But generally speaking, yes, you can probably get some positives from not adhering to the standard. But this applies to anything: POSIX, TCP/IP, the various types of file systems, ELF, you name it. That does not mean the penalty is so big that they are unusable.
Or that they cannot be scaled or whatever.
so as i see it there are two types of drivers
those where perf matters, and those where it does not
If you've ever had to deal with the video driver stack it sucks even in Windows that probably does the best job.
for the first kind, fuck standards write your own one
that does as much perf as you can get
for the second one, sure, i can see sharing drivers being nice
but i think python is a far better platform for that than some sort of in-kernel interface
You have to decide on your own requirements and constraints based on the problem that you are trying to solve, I would say, rather than to adhere to arbitrary standards. Maybe even TCP/IP is not what you want - or maybe you do.
tcpip is a very different class of standard
in that you can't not do tcp
at least in a fallback path
(in most cases anyway)
because somehow i doubt my router (or isp, too) will let me shove out sctp to the internet
Perhaps your use case is not to interact with the Internet.
But networking is still relevant in some form for your project.
but either way, that is still a very different class of problem
It isn't though, it's just way more widely adopted.
There are systems that use OSI rather than TCP/IP.
"use OSI rather than TCP/IP" how many drugs are you on
it very much is, because it is something where you NEED concensus
As I have said previously, you need to clearly state your problem and then decide on the requirements and constraints.
and udi (like elf, posix, bsd sockets at one point) is fundamentally something where you do not need any
If you need interoperability with TCP/IP, then you should go for it. If not, it's probably the wrong solution.
no i don't think so
designs don't exist in a vacuum, and tooling/experience around ip and friends makes anything nonstandard a very, uh, "interesting" idea
But there are systems that do not use TCP/IP. OSI is used in some military/defense applications, in industrial control systems, etc. If your system does TCP/IP instead in that context, then it is solving the wrong problem.
not uploaded yet, i'll up it soon
"using OSI" is a nonsensical statement
and that is also completly unrelated to UDI and how it isn't solving any problem, not well anyway
It's not a nonsensical statement. It's a set of protocols that inspired TCP/IP yet is incompatible with it.
no, it's not
it's a hypothetical idea that has not all that much overlap with reality
and that gets incredibly iffy
because you can't always separate layers cleanly (see NAT)
TCP/IP predated them
i thought the OSI is a model?
of how they should maybe be designed?
it's a model designed for its own protocols
that's why it doesn't match TCP/IP's layering
i didn't know the OSI protocols were ever actually used though
oh wow nevermind i have not heard of any of this
Yes, I did not mean to make a historical statement, although I phrased it awkwardly. Just meant to reference the whole "OSI model" thing.
i always supposed they were just designed and then literally never used because TCP/IP was established and called a success
They are used though not nearly as popular as the TCP/IP stack.
Getting back to UDI and standards not existing in a vacuum, perhaps you have a server running OSR (which to my knowledge still supports UDI even though most drivers it runs are non-UDI) and a hobby OS and you want to use the same SCSI driver on both or something. Obviously, the use cases where UDI makes sense are more limited than with networking - I only said that you should consider your requirements and constraints, which pretty much always applies to any engineering project.
I essentially had to make up a use case right now but perhaps a valid one exists... for someone.
Just implement Windows’ driver interface(s) tbh
updating to new uACPI
let's see if anything goes wrong
seemingly not
just a few more stubs to implement + don't need to use that funny struct for the table lookup fun anymore
overall i have to say i don't mind the e1000
it's slightly more dated than i expected but not by any means a bad experience
i have tried the various e1000 variants provided by qemu and all seem to work + my laptop with a real i219, all without any bother
Thats nice
i haven't tried transmit yet but surely it can't be that easy to fuck it up
my top objection to the e1000 as a family is that many of its members are nigh undocumented
i don't know what kind of atrocious quirks i might encounter
what documentation did you use to write the e1000 driver? I've been meaning to write one for it so I don't have to be stuck with virtio-net
what did you think of the latest api changes?
https://www.intel.com/content/dam/doc/manual/pci-pci-x-family-gbe-controllers-software-dev-manual.pdf this is for, i believe, the first of the family, but it's largely still true
i havne't used any new stuff yet, what exciting things await?
oh, i only had to change the find table thing to use a string again instead of an inline uacpi string struct thing
much less bother than the last time around
yeah I also made the init params structure a lot simpler
ty
@hexed solstice any chance you'll look into containerizing keyronex builds? for some reason i am getting a bunch of internal compiler errors when building host-gcc and i'm not sure what's at fault here
wtf
xbstrap lets you do that by using cbuildrt
for amd64?!
yeah
g++ -fno-PIE -c -O1 -pipe -DIN_GCC -DCROSS_DIRECTORY_STRUCTURE -fno-exceptions -fno-rtti -fasynchronous-unwind-tables -W -Wall -Wno-narrowing -Wwrite-strings -Wcast-qual -Wmissing-format-attribute -Wconditionally-supported -Woverloaded-virtual -pedantic -Wno-long-long -Wno-variadic-macros -Wno-overlength-strings -DHAVE_CONFIG_H -I. -I. -I/home/czapek/source/Keyronex/sources/gcc/gcc -I/home/czapek/source/Keyronex/sources/gcc/gcc/. -I/home/czapek/source/Keyronex/sources/gcc/gcc/../include -I/home/czapek/source/Keyronex/sources/gcc/gcc/../libcpp/include -I/home/czapek/source/Keyronex/sources/gcc/gcc/../libcody -I/home/czapek/source/Keyronex/sources/gcc/gcc/../libdecnumber -I/home/czapek/source/Keyronex/sources/gcc/gcc/../libdecnumber/dpd -I../libdecnumber -I/home/czapek/source/Keyronex/sources/gcc/gcc/../libbacktrace -o lists.o -MT lists.o -MMD -MP -MF ./.deps/lists.TPo /home/czapek/source/Keyronex/sources/gcc/gcc/lists.cc
during RTL pass: into_cfglayout
/home/czapek/source/Keyronex/sources/gcc/gcc/ipa-pure-const.cc: In function ‘funct_state_d* analyze_function(cgraph_node*, bool)’:
/home/czapek/source/Keyronex/sources/gcc/gcc/ipa-pure-const.cc:1171:1: internal compiler error: in try_forward_edges, at cfgcleanup.cc:580
1171 | }
| ^
0x7fd5c3391c89 __libc_start_call_main
../sysdeps/nptl/libc_start_call_main.h:58
0x7fd5c3391d44 __libc_start_main_impl
../csu/libc-start.c:360
Please submit a full bug report, with preprocessed source (by using -freport-bug).
Please include the complete backtrace with any bug report.
See <file:///usr/share/doc/gcc-13/README.Bugs> for instructions.```
one of many
czapek@raptor-wsl:~/source/Keyronex$ g++ --version
g++ (Debian 13.2.0-25) 13.2.0
Copyright (C) 2023 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.```
thats my gcc version
but never in my life could i have imagined it happening for amd64
looks like a destructor exploded if it's at a line consisting solely of }
i'll try with gcc 14 but i don't expect it to go any different
i am really surprised by it
at first i thought you meant ICEs in the cross-compiler
but in the host compiler, that's evil
very strangee
yeah that is very weird
might want to report it to debian?
i reckon that may be appropriate
meh, i cba
i also dont know how
im on debian unstable after all so
gcc-14 seems to progress a bit further
looks scary
gcc-14 also dies with an ICE, interesting
maybe i should go back down to like gcc-11 or something lol
sorry for littering your thread btw
well i can at least build the kernel with gcc-11 so that's progress, but im still getting that configure error from above, unfortunate
oh you fucking little cunt
it took me an undue amount of time before i spotted that bloody bastard
lol
that bloody thing again
i completely forgot how you fix that
honestly i would fain toss GCC into the bin at this point
someone here does know how to fix that stupid error though, and hopefully they'll turn up and reveal it all
transmit works under qemu but i've not got it working right on my laptop yet
TXDW (i.e. tx writeback) never read on my laptop
working hypothesis right now is that my laptop initialises the nic funnily as part of PXE and that perhaps leaves me in afunny state? but you would think that PXE would initialise it in a quite compatible and unremarkable way
the status is never updated on the submitted descriptors either
making some progress
// you should set the TCTRL register as follows. For detailed description of each bit, please refer to the Intel Manual.
// In the case of I217 and 82577LM packets will not be sent if the TCTRL is not configured using the following bits.
writeCommand(REG_TCTRL, 0b0110000000000111111000011111010);
thanks osdev wiki article, i wonder where you pulled that out of
For detailed description of each bit, please refer to the Intel Manual
this means you don't know what they mean, but that's fine, maybe somewhere there's a manual that describes this bloody model in sufficient detail to figure that out
i have gone sour on e1000, it was nice when i was using qemu and it wasn't full of whatever weird quirks the real deal has
the high 1s (in what in the original e1000 was a reserved area, the manual explicitly saying to write 0s there for foward compatibility...) make it so that at least it appears as if the packet was transmitted
this is basically the struggle for all crappy non standardized legacy hardware
wonderful
do not let intel touch your standard
lmao
i'm on the verge of importing the bloody freebsd driver, like leo did
nvme is good tho
it's apparently quite portable
and intel did it i think
broken clock something something
i give up
on litearlly one occasion about an hour ago i managed to transmit a few packets
it worked randomly after the loop-and-sleep failed several times
just fuzz the hardware
i have not been able to replicate this since
i take back everything nice i said about the e1000 before
it's a piece of shit
don't use it
don't buy any
it's fine if you want to write a driver for qemu
but god help you if you have the nerve to try the real thing
At that point use virtio
huh, that's nowhere near what I have for TCTRL
e1000_outl(e, REG_TCTRL, (1 << 1) | (1 << 3));
without those magic numbers i never even get the interrupt indicating the packet was transmitted
it just sits there in the tx ring
it's the highest pair of 1 bits that does it
i would love to find out what they are, but the documentation doesn't say a word about it!
and now i managed to transmit some packets
i have no idea how
i'm not counting on it happening again
it worked once earlier too
no obvious reason why
Makes me wonder if my code would work when booted normally or via built-in PXE. I was using iPXE on a floppy (via a USB floppy drive) for some reason that I can't recall (that was almost 12 years ago now lol). But it did work with the e1000 that was in the Thinkpad I was using as a testing mule at the time.
not in this iteration of the codebase but they can be put back quite easily
i have no idea what's going on
some restarts of the laptop it works
others it doesn't
according to the original e1000 spec and also the newer one i should be fine
but as we have seen those aer worthless for this new mfer
wish i could find out where that magic number fmo the osdev wiki came from
having a good run at the moment, it's worked consistently every time I've tried
i have no idea why
all i've done is fiddle with magic numbers and configuration that shouldn't have a bearing on operation. it's no way to write a driver but it seems that it's made the i219 happy for now. but i am expecting it to stop working spontaneously again before long
and in the meantime i have absolutely butchered the code. it's a mess
that's a run about 15 succsesses now
... mulr = 1 and rrthresh = 01?
The software device driver must not modify this register
when the Tx head register is not equal to the tail register.
this is what immediately stands out to me, but i don't do this in any case
i have managed to get this to consistently work by having RRTHRESH = 3
lots of potential for RCU in networking
exploring what i can do
i might need to implement RCU BH Edition, because i expect to run network input processing in DPCs, and Linux did similarly - they call their DPCs as Bottom Halves, or BH for short - and found that RCU Classic Edition was DoS prone under the circumstances
where is it applicable?
i guess like, connection tracking or something?
the reason being that if you have a heavy load of packets coming in, they could find a core spends all of its time handling NIC interrupts and running the net stack input bottom-half. it never ever has the chance to enter a quiescent state
arp tables for example
anything that you can afford to not be necessarily current when you consult it
or well, per queue
dragonfly bsd takes the approach of replicating as much as they can
it's completely fair
this is why they are a tiny project but still competitive with freebsd (masters of the fine-grained mutex, though now they have EPOCH which is an alternative form of RCU) and linux (masters of RCU)
for arp tables at least, replicating is probably good enough (and somewhat faster)
https://leaf.dragonflybsd.org/~sephe/AsiaBSDCon - Dfly.pdf nice paper on what dfbsd is doing
i like how they collect data that belongs to different cores by literally migrating the requesting thread between cores
That's worth a pin in #networking
good idea
@hexed solstice You have a working i219/8257x driver?
general e1000 driver, it works on my laptop which has an i219-lm
I've done i8254x (e1000) and didn't have issues between virtual/physical systems using it. What did you run into?
Ok good to know. I'm doing i8257x (e1000e) and i8259x (10-gigabit) at the moment.
packets never transmitted on the real i219-lm until i set RRTHRESH bits in TCTL to 11
Ok I'll keep that in mind. Thanks!
without setting RRTHRESH thus they just sat there, status unchanged, no TXDW interrupt of course. nightmare
no worries, hope it goes well
I do have transmit working on i8259x.. no interrupts yet. Annoyed that my i8254x driver works on e1000 and e1000e in QEMU but not a physical i8257x device
what goes wrong with it?
Nothing is sent or received on actual i8257x hardware. Still going over the docs.
I'll look into what you noted
no received, that one never snared me
only the transmit
i have a goal for the near term
for keyronex on my laptop to mount a 9p filesystem hosted by my desktop
this i believe could be a first for a hobby kernel
serenity os
not a hobby
worse
Do you have your driver somewhere public?
i had no idea they had a 9p driver though
it might've been removed
yes it's in the keyronex repository
because no one used it
kernel/dev/E1000.m
https://github.com/SerenityOS/serenity/tree/master/Kernel/FileSystem/Plan9FS seems they still have it
sergey wrote it for serenity, a very smart guy
Thanks. I’ll look it up
but then it was abandoned
is it good?
i am looking now
looks tiny
i don't like it
with 9p you know in advance how big your message is going to be but they just use some builder object that repeatedly reallocates the message as it grows
imagine supporting oom conditions
for write of file data they also assemble the whole message in memory in that bfufer including the data to be written
That is significantly less code than I expected
by contrast i expect to be able to write file data back from cache without a single copy of that file data: the principle is that you pass a handle to the data down the stack and finally it gets to the NIC driver, which i have designed to be able to do scatter-gather
i dont think serenity even has scatter gather
it memcopies stuff into kernel buffer then writes from that
for read of file data i can do that one-copy (zero-copy receive is hard): the principle is that the 9p driver will read the message header of a message, and then issue a read to the socket for the message contents, and that read would directly go into the page cache
one good thing about the 9p wire protocol it is painless to have this kind of efficient, zero-copy tx/one-copy rx approach (as long as the rest of the system is able to do it)
Thats nice
it is very nice
i would explode if i had to allocate big buffers, even variably sized ones, instead of this fun trick
😱
so easy DDOS attack on serenityos without a fire wall?
not that I would but the possibility could be there
What does scatter gather mean?
lol, they have ub there
m_builder.~KBufferBuilder(); isn't allowed unless you reallocate afterwards
because you cant call the destructor twice
instead of using a contiguous chunk of physical memory, you can use a list of pages and the driver/device treats it as if it were a single buffer.
but even if your device doesnt support SGLs you can break it up into multiple operations (one per contiguous chunk) in the driver.
I see
NVMe is where I first saw it (and it has a nice interface for them)
I guess MDLs are kind of a wrapper around the concept
its necessary to do any sort of bulk io
its basically a list of { phys_addr, num_pages } that you feed to the device, most disk controllers support such interface for example
AHCI, NVMe etc
virtio is based around that as well
that list is constructed from some virtual_address, num_pages pair
windows mdls are slightly more flexible as you can have unaligned start and length
that would probably require some awkward workarounds for devices that cant deal with misaligned io
or e.g. reading less than a block size
but i guess u can just point it to some placeholder page
or to the zero page for writes
yeah
a lot do tolerate non-page-aligned I/O
i would be unimpressed with a NIC that didn't
NVMe didn't originally support arbitrary scatter-gather lists, only "PRP" lists which had some constraints so you couldn't arbitrarily read/write here and there and everywhere at non page-aligned positions
but even there i think it did support the case of read into pages 5, 6 and 7, but start at + 512 bytes into page 5 and write only a total of 10,240 bytes
yeah it has always allowed for the first page to some some offset
and nowadays NVMe has fully-blown SGLs, not just PRPs
new keyronex kernel + drivers is now larger than old keyronex kernel + drivers, and still so much left to do...
right now i am sketching out code for the high-level interfaces to sockets. new keyronex is supposed to be async native api first (and sync posix api implemented in terms of these wherever viable), so they're asynchronous APIs. i like them a great deal
the unavoidable copy involved previously (where 1. incoming data copied to receive buffer 2. readers and epoll'ers woken 3. reader copies data out of receive buffer) is no longer needed because now asynchronous readers include a scatter-gather list for the data to be written to!
so the data can be copied directly and the reader can be woken - either immediately when any data arrives, or (very useful) only when as many bytes as they've asked for has arrived
that means that for 9p, for example, the client issues as async read sized for the common part of a 9p response header, and then they're woken when that many bytes arrives - which includes the length of the response in total - and they can submit another async read for the remainder of the data - and have the file contents directly emplaced into the file cache through an appropriate scatter-gather list
whats the cloc counter?
on the new one ```
Language files blank comment code
C 54 1941 859 8769
Objective-C 26 1305 238 5982
C/C++ Header 73 902 920 3217
Assembly 5 60 17 414
Meson 17 8 2 106
SUM: 175 4216 2036 18488
c is the kernel proper and in new one most of it is the C code
by contrast in the previous one the c code amounted to 11,000 lines so it looks like much of the difference is currently explained by there being more drivers in the new one
nice
-------------------------------------------------------------------------------
Language files blank comment code
-------------------------------------------------------------------------------
C 19 3247 808 14954
C/C++ Header 44 842 1109 4588
C++ 4 379 493 2421
Python 3 207 30 561
Markdown 1 59 0 184
CMake 3 23 14 109
YAML 1 10 5 56
Meson 1 2 0 23
-------------------------------------------------------------------------------
SUM: 76 4769 2459 22896
-------------------------------------------------------------------------------
uACPI is a bit bigger
how big is acpica?
last time i checked about 200k, but it has a compiler, a disassembler, a debugger, etc
i should be in trouble if my kernel were not merely exceeded by but by an order of magnitude by the acpi stuff
looks like LAI was 8664 code
well if u integrate acpica the actual loc count you're compiling is probably in that neighborhood
yeah pretty tiny
i mean it didnt support a ton of stuff, and it was very very limited in terms of api
in a way it's a bit sad that it's fallen from grace
it was the last legacy of a famous former osdever
thomtl?
no, one omar, an egyptian
he wrote an OS called LUX (i assume named after the egyptian city of Luxor)
oh dont even know who that is
that's why LAI is the LUX ACPI Implementation
makes sense
He's not even on the contributor list here https://github.com/managarm/lai/graphs/contributors
he reportedly abandoned osdev forever when he got into the best university in cairo
I see
i think the repository was started with a source import
ah
he seems to have deleted the original repo along with his account
but someone forked it at https://github.com/lkundrak/lai
interesting
why did i put these into IOP stack frames instead of into the IOP itself?
even 2 years ago i didn't know why
in this case i think the reason was me being stupid
oh god
i love this quote
i need this whenever someone takes like the limine-c-template and just starts removing flags and shit
without knowing why they are there
why ARE most of them there
you guys got camera on me or smth? i just removed a reference flag that i think i didnt need and then bam everything broke (47 errors)
lol
always good to keep it in mind
i used to always be in a hurry to get rid of what i didn't understand but i've realised by experience that doing this is a first class ticket to making a mess or breaking something
some progress towards network 9p in addition to virtio-9p
diod: P9_TVERSION tag 65535 msize 8288 version '9P2000.L'
diod: P9_RVERSION tag 65535 msize 8288 version '9P2000.L'
diod: P9_TATTACH tag 0 fid 1 afid 0 uname 'root' aname 'root' n_uname 0
diod: attach([email protected]:root): invalid afid (0): Operation not permitted
diod: P9_RLERROR tag 0 ecode 1
looks like the DIOD 9p server doesn't like me not even paying lip service to authenticating
qemu however doesn't care
it won't find pagefile because i haven't made it possible for it to do so yet
i can do scatter-gather I/O to/from kernel buffers within one page but not yet to MDLs through this code path
i wasn't particularly expecting success immediaetly
good progress
diod: P9_TREAD tag 58 fid 15 offset 208896 count 4096
diod: P9_RREAD tag 58 count 4096
74785f75 6e6c6f63 6b00636e 645f696e 69740063 6e645f64 65737472 6f790063
6e645f62 726f6164 63617374 00636e64 5f776169 74005f5a 4e313166 696c655f
Segmentation fault
nice
i crashed diod
holy based
that's as far as i can go though
looks like we never recover from the very first page fault?
no, not the very first i don't think
let's try turning off working set trimming
writeback turned off + smp off
let's try writeback + working set trimming on but no SMP
i have a vague hypothesis
aha
who said printf debugging is useless?
looks like tlb shootdown is began but never completed
wtf inserting printfs around the IPI sending seems to make it work
missing volatiles maybe?
no
done
fixed
i think i am the first hobby kernel to netboot from 9p
granted it's not as though i'm doing anything even remotely interesting with it
i'm really happy with this
thanks @sinful jetty for asking me about running on real hardware
what was the issue?
no but i really ought to add at least a dirty reset in ersponse to hitting the power button, if only to make testing more pleasant
not awaiting delivery status bit of icr to become 0
give that a try, its like 5 lines of code with uacpi
ah
in due time, i'm resting now
yeah, i mean when u get around ofc
Yup, that is the very definition of Chesterton’s Fence
i hope i'm not too much of a bother but i'd like to ask how did you come up with keyronex design? how did you come up with all the concepts that your kernel is comprised of? currently i am really struggling with my kernel design and i wanted to know if you had any tricks up your sleeve 😅
i have stolen designs from these sources:
- the mach vmm
- the sunos vfs
- solaris
- netbsd uvm
- other stuff from netbsd and solaris i can't immedaitely bring to mind
- windows kernel objects and vmm
- dragonfly bsd namecache
Like the papers or did you read the code
books or papers mostly, the code is often bound up in complexities that only make sense with a very good understanding of the rest of the kernel, and the source code to some useful references is unavailable
Do you still have links to those?
also patents
vmm stuff: see pins in #virtual-memory
sunos vfs and dragonfly bsd namecache: see pins in #filesystems
solaris: see solaris internals book
windows: see windows internals books
Thanks
there are more sources but i can't immediately bring them all to mind, they've shaped how i see and approach kernel design though
i had one in mind a moment ago but it's left my awareness now
can't remember for the life of me what it was
oh, nextstep driverkit
oh, and vmem and slab, those go without saying
did you design keyronex as you wrote it or did you already have something in mind shaped around those concepts before writing the code?
i was inspired by mach a great deal
and filled in the gaps with the vague understanding i had of netbsd structure from contributing to it
well that was true of SCAL/UX
by the time of keyronex there was an injection of other sources of inspiration
interesting, is there anything you recommend that i do? i have no idea where to start and just writing code with no clear path ahead doesn't seem like a good idea, it has worked once but my first real attempt (zigux) is terrible lol
im thinking i could write down how everything comes together and then once i have all the pieces maybe then write the code but i feel like i cant know how it all will work until i actually write the code
like im bound to forget about something and adding that will break my entire design 😄
i did just this and i made mistakes and painted myself into corners but, by god, i did something, and it doesn't seem to have stopped me from improving later
everytime i trashed everything and started afresh, i had a few more components that worked well and had proven to be good, so i had to trash much less each time, and using ported apps running as a metric, things improved massively
well i had bash and gcc running... but 1.5 years later i discover terrible bugs hiding in all parts of the kernel and i just dont feel like i want to touch any of it anymore, also i want to rewrite it in c++ (because of zigbugs... sigh)
i think first scal/ux barely ran BASH, second scal/ux almost ran GCC, third scal/ux didn't go anywhere, first keyronex didn't go anywhere, 2nd keyronex got to gcc, xorg, all that stuff
(when they didn't go anywhere it just meant simply that i got pulled aside by other things and then ended up rebuilding a lot of it when i went back to it with fresh eyes)
i have coded myself into corners in this project before but somehow i made it work most of the time, and i was really proud of that because i usually don't... i just abandon the project, but for some reason this one kept me going, but i dont like coding myself into a corner because it shows that i lack understanding of my own code, idk if its the right way to think about this though
being able to run GCC is no mean feat
and especially if it reliably runs then that's something
yeah well, userspace was pretty realiable, but then 1.5 years later when i come back to the project and write an xhci driver + usb stack i discover all kinds of bugs, the scheduler is trash, the time keeping is not very good either
and my kernel was smashing almost every stack that it got its hands on 😅
i would continue working on this, but as i said the zig compiler hates me, and i don't feel like going through all the code and auditing it is time well spent, im sure there is more nasty oopsies in there hiding and waiting for me to find them miraculously
if you had to rewrite from scratch, it's not really from scratch, it's informed by the experience you've had writing before
yeah exactly, i think ill just try and code my way through it all again with all the knowledge i gained from my zig kernel 😄
i think having a solid memory manager is a good start so ill start with that, along with some abstraction over the mmu and maybe a slab allocator
i like memory management, that was what i worked on almost immediately
yeah well my "memory management" will only involve a physical memory manager :p
i have NO idea what im doing when it comes to virtual memory
in my zig kernel the "vmm" was basically a fancy page table manager
with a half assed mmap for userspace, which was a bump allocator
couldnt do file mappings nor shared mappings, only private anon, so it was bad
i plan on changing that in this iteration, i want to be able to let mlibc map shared libraries instead of reading them in, that is my dream... sort of lol (i dont actually dream about it, but i really want to achieve that)
do you have any recommendation on where to start with memory management past the pmm? i dont actually know what a vmm should do honestly
This reminds me that I really need to digitize the two giant binders of NeXT documentation that I bought on eBay
the papers pinned in #virtual-memory wouldn't go amiss
thanks for that, i like the "SunOS Virtual Memory Implementation" one but it seems to be tied to the tasking and vnode management part of the kernel (i assume every one of them is, so i'll have to look into that first probably), giving it a read also made me pretty confused about vnode mappings - i didn't know you could get a shared read-write mapping of /dev/zero, i didn't do any further testing myself but i wonder how that is reflected when you fork and write to that memory, does it act like regular anonymous memory? anyway, enough hijacking your thread, sorry about that :p
the mapping of /dev/zero is just a fun way to say MAP_ANONYMOUS
ah that makes sense, i expected something like this
so in all other respects than that it behaves exactly like mmap with no FD and MAP_ANONYMOUS set
that is fun, ill look into that, hopefully soon enough
i was being lazy all day and i havent looked into tasking yet, i also need to take a look at sunso vfs paper 
actually i was wrong, for some reason i thought that the sunos vmm interacted with the scheduler, seems like i misinterpreted some part of the paper but ill have to come up with something there too
maybe you have some good resources on schedulers?
yeaaah that would be greatly appreciated 😄
@prime coyote @stone orbit OSTEP actually has a nice overview of scheduling algorithms
"Unix Internals" by Vahalia is also worth a look
Holy christ
jesus why is it so expensive
Used copies on eBay are cheap af though
great book
i can't remember how much i paid for it but it was more like yours than that
this book i got for £6 or something like that and now look at it
I wonder if that’s the original MSRP
Book prices are really strange, and there are, or at least were, a couple of bad actors that would list books on multiple platforms, and then jack the price up on all if the listing was visited on one.
Sometimes to absolutely bonkers amounts
LMAO
I had to wait a year due to it being pretty damn uncommon, but:
I wanted this because it’s written by one of the main 68000 engineers. And there’s a lot of info about a joint Motorola-IBM project to replace the 68000’s microcode so that the otherwise exact same silicon could execute System 370 instructions instead.
thinking of doing a GDB stub next
the principle of it will be that on making debugging available the NIC driver is placed into a special state where it deals solely in polled receives and transmits. GDB has a UDP option for communicating with a gdbstub so that makes things much simpler, the gdb stub will only need to deal with UDP (and a little ARP) to communicate with the remote GDB
you dont need arp if you use a broadcast mac 
ostep is good. i'd like to read about more advanced things and innovations in this area
lmao what is this
gdb protocol is crazy text nonsense apparently
they added XML too
jfc
https://github.com/bminor/binutils-gdb/blob/master/gdb/features/m68k-core.xml dear GDB people: this shit doesn't need to be XML
I think @rain flame explained why earlier
Something to do with serial
the XML will be because open source projects starting with the letter "G" went absolutely wild with obsession for XML around 2003
It's because in the old days 7bit serial was a thing that people used, so it only uses 7bit ASCII for it's base
Some extensions can pass binary
like gnome?
gimp?
or just GNU stuff
gnu stuff and mostly gnome
i cannot fucking stand this protocol
it's ugly and documented in an annoying way
and then XML thrown in because that was the obsession of 2002 - granted i don't think i need to parse XML - it's still stupid though
it's repulsive
I managed to craash gdb with my stub
this is something only the free software community could've cooked up
I <3 overengineered solutions
I think I want to make a gdb stub soon
but the problem is
well for one it'd be practically useless, as my hardware doesn't have a serial port
and I got a cast
you need an ethernet driver
which I don't plan on making any time soon
I want to make the VMM and VFS before a driver interface
a small subset of an ethernet driver is more than sufficient for this
since the debugger wants to operate it polled (you might want to retain rx interrupting so that you can detect GDB trying to connect and go into the debugger in response. alternatively you could e.g. have some keystroke invoke the debugger)
i've stubbed enough of the gdb protocol that it stops and tells it all registers read 0x0 and so does all memory
i'll deal with this further later
I've owned an Amiga for the past 30 years but in all that time the one thing I have never done is put an Amiga online, I have never networked an Amiga. I found this Zorro 2 ethernet / clock port / ide card on gitlab so lets put it together and see if I can network an Amiga.
Zorro Lan IDE Gitlab - https://gitlab.com/MHeinrichs/Zorro-LAN-IDE
...
Though I wonder if just going with a PiStorm would be the better debugging solution
implement kdp
it's the apple meme for this
i believe it does not involve xml
i did consider it
it's a nice and clean protocol not this ridiculous text based monstrosity
as far as i can see no, which is why i rejected it
https://opensource.apple.com/source/gdb/gdb-2831/src/gdb/macosx/ it appears apple was patching GDB to include all sorts of macos stuff
you could implement a kdp-to-gdb translation layer in python
so at least the os side is clean enough
i didn't want to implement GDB protocol at all!
however
it's a protocol more suited to implementing in python than in C
Remote debugging using udp:10.0.2.15:2159
kdbudp_check_packet () at ../../../../kernel/kdb/kdb_udp.m:423
423 splx(ipl);
that's the basics in now, minus memory reads
and minus all thread stuff (the 'threads' can better just be each cpu, initially anyway)
@hexed solstice the interrupted sys futex wait fix has been upstreamed to mlibc if you wanna make your FUTEX_WAIT interruptible again
thanks, it will come in handy when i have signals in the future
wrapped to gdbstub? or did you give in to lldb
it's a gdb stub implementation, i swallowed my pride and went with it
i see
its not too late to implement gdbstub in python
i think thats a pretty classic approach actually
implement whatever in-kernel, and wrap ot to gdbstub (openocd, m1n1, idk what else)
i am strongly considering it
the string manipulation is already irritating me
dont even have to use kdp internally, you can invent a custom protocol and adapt it
i don't mind in principle the debugger interfacing code being lazy and unable to deal with malformed requests and such, but it feels wrong to do, and i don't want to waste time on parsing in freestanding C, which is not a fun language to do it in
yes i am fairly sure this is what i will do now
i asked gdb to connect to keyronex, despite implementing nothing at that point, and looked at what it was sending
and so i repeated until i had the bare minimum
it sounds very simple in retrospect
i should drop my attitude of needing to know how something works before implementing it
right now i am doing some conveniences like having the bootloader communicate a string which should tell how to mount the root FS, and i am seriously considering implementing a feature no hobby kernel has ever implemented before next
that's right
shutting down
it's a tricky thing
i don't know how good it is to run in all guns blazing and implement something you barely understand
but sometimes i do it depending on the stakes
i would say i am not afraid to make a mess and try again but i usually don't have such self awareness as to know from the getgo that what i'm doing isn't right
my problem is actually that i am afraid to make a mess lol
i hate going in and cleaning up my old code
refactoring all the call sites etc, it gets tedious
but its probably a me issue, i just need to keep programming and maybe one day ill learn how to deal with it
Managarm has it (we don’t do shit with your file systems but we’ll shutdown with uACPI if you ask)
And if I finally fix my PR it should be wired to userspace too
Yeah I tried to type shutdown in the terminal to be cool but it didn't work 
There isn’t a shutdown command (outside of my testing locally with InitWare (if it provides one) and my test binary (which works, but the PR got comments which I need to address))
Which package is the shutdown command from?
czapek@raptor-wsl:~/source/kernel$ dpkg -S /usr/sbin/shutdown
systemd-sysv: /usr/sbin/shutdown```
usually your init system
Oh interesting
i hate waiting 5s or whatever for hard poweroff on my laptop when testing so it'll be a big help there
i do want to implementing unmounting and all that along the awy
Yeah its considered an emergency shutdown
Not exactly good as it bypasses everything
tbh all the hardware I tested nanoshell on just shut off when I pressed the power button
or are you already using ACPI?
That's if you dont have acpi enabled
managarm should do that too but it's not wired yet
(also idk if unmount is a thing, I'd need to check)
unmount is tricky
i will need quite a bit of code added to support it
actually maybe not that much
i'll need to keep track of how many files are opened/mapped and refuse before that reaches 0
then i need to purge and dissociate the namecache, purge the buffer cache, and finally write back every dirty page
If you refuse before it reaches 0 then what do you do if I force unplug the disk
I suppose the vnodes will stay in memory until everyone closes them but any access to them will return an i/o error
i guess
likely what mathewnd proposes
most OSes simply do not recover from this situation
if it's a read-only FS it might be possible
but if it's read-write? good luck
what about MNT_LAZY though
you mean the lazy unmounts?
i can do that later
unmounting hard
good thing i am addressing it now, not who-knows-how-long into the future
Not looking forward to that then
How does it play with your retain-release api for your namecache (assuming it’s still what I know it as from when Ihad a talk with you about the namecache)?
i don't know
it's an open question which i am trying to figure out
i think i need a counter of open files on an FS
then if that's 0 then i can begin destroying the namecache hierarchy - leaves first, being that they are retaining their parents
but i have to watch out because people could open a file in the meantime
maybe i need an "unmounting in progress" flag in the vfs structure that every attempt to open a file will consult first
Yeah that‘d be reasonable to do
Could you refcount on your mountpoints for unmounting?
and as you already said, you‘ll have to „figure out mount locking“ as your code comments read, so you can safely destroy file systems…
and i set that flag when i begin unmounting - atomically - then i move on from there
Discord being discord as always made your messages show up after I had sent mine - turns out you were a step ahead already
it's complicated because if i set that flag i'd surely begin to fail opens, but if an open got in in the meantime, then the unmount should be aborted - hmm
but by that point i may be failing opens which should be valid
so maybe i need to speculatively increment the open files count during opening? and then consult that flag - and if unmount in progress is set, then lock the vfs, and check what's going on - hmm
Yeah just fail the open call and unmount in peace
the unmount might've been aborted by this point
How would unmounts be aborted
and i don't want to lock the VFS every time i try to open a file
because the number of open files on the vfs increased between someone asking to unmount it and me setting the unnmount-in-progress flag
someone opened a file before the unmount formally began
You shouldn’t even set the flag before having that checked
if i check it before setting the flag then the value is stale after i set it
it can be changed in the meantime
lock everything for a second 
then i would have to lock around all opens
which is not necessarily unacceptable
could have an rwlock and readlock around all opens
is there no way to do this atomically without locking
i only need to acquire the readlock to increment the open files count in this, and then i can release it, and the idea is that would synchronise against unmounts
the open files count woudls till be manipulated atomically
i cannot immediately think of a way to completely avoid using an rwlock here yet
realistically it can just be a spinlock it's only for synchronising n open files count and the unmount in progress flag
however i would rather not have to lock around it at all, but in this case i do not consider it to be intolerable
actually
correct me if I’m wrong here but why not, on open, check the flag and only increment your filesystems refcount atomically
And when unmounting, atomically set the flag
Isnt this just a CAS
now you're cooking
i could fold the n open files and umount in progress flag into one atomic variable and try to CAS it in open procedure
^
because what i effectively need is to be able to manipulate these two things atomically
so previously i thought, no, that's not really doable, i would need CAS2 because they're separate
but realistically they can be one field
low bit = unmount in progress, remaining bits = n open files
2 billion files open on a mountpoint ought to be enough for anyone so it can be a uint32_t, which all decent architectures can CAS
thank you for popping up in the chat here right as i was getting flustered with this
i think you've pushed me to consider what might be a good solution
what's CAS
compare-and-set, atomically
ah
Totally not gonna steal that whole idea for myself now : )
it changes a field to a new value if and only if the value at the time of being changed is equal to a value you have specified it should be
cmpxchg?
very useful primitive and available everywhere (some arches use a different primitive called ll/sc but they're equivalent)
yes lock cmpxchg is this
it kinda also broke my spinlocks for a couple rewrites
because I was using it wrong
what did you do?
I don't even remember
all I remember is spinlocks did not work
only fixed it in this rewrite
and i am just writing this for reference:
unmount operation = cas n open files from 0 to 1 (set unmount in progress bit, inhibits openers)
any operation that increases open file count (this needs to be done speculatively sometimes) = cas n open files from whatever even number you read to that + 2; if the value changed to 1 (it cannot be any other odd number), you're being unmounted
and i think this might also be the recipe for making the mount list RCU'able
i like this a lot
brutal situation to be in
I mainly ran one thread so I never really noticed
Was just about to ask if it has stayed cursed
ye
since you being here and talking caused me to think of this, i think you should also know that i believe this enables RCU'ing the mount point table
you defer the mount point struct being deleted with RCU, and whenever you try to walk a mountpoint into the new root, you try to do the "any operation that increases open file count" above, speculatively. and if you succeed, the mountpoint is now protected from being unmounted, so you should be safe to proceed
Holy sht thats a good idea
cheers, i really like it
and of course the actual removal of a mount point entry frmo the mount point table is not done till after unmount in progress is set
so you shouldn't get a spurious walk at any point
you're young, you'll recover quickly
fair enough
anyway since it's a cast and not a sling I can type relatively quickly
so I'll hopefully get back tomorrow
but now I must work
and finish this school thing
in 5 and a half hour
s
or my mark on this class
is
fucked
You just gotta make sure you don’t allow any references to the filesystem you’re unmounting / or you invalidate all of them
*the mountpoint
does that even matter actually
the open files counter i think can be used for all purposes
so it's a bit of a misnomer
because it would also be incremented for stuff like mounting something else under the parent mountpoint
it's like the gate you have to go through before you can do anything with anything under that mountpoint
there might be some flaw in this approach which i haven't realised yet but i am feeling quiet confident about it
that can probably be left to userland i think
check mounts list, if there's something mounted under the mountpoint you want to unmount, unmount that first
Yeah leave the effort to someone else
i suppose some people might want the recursive unmount to be atomic and that's harder to do with this
but these people want something that ruins this neat little solution so they can go find another kernel
really, what kind of man needs an atomic recursive unmount anyway
I‘m hearing bindage in the corner arguing how some exotic system configuration may want that
Don’t know why
Anyways, good luck implementing it
cheers, and many thanks for prompting me on this
please do copy it
I definitely will
oh and @zenith karma does a lazy unmount prevent further opening of files, or does it just wait until whenever the current open count finally hits 0 before it starts unmountint?
because if the former then this can do that semantic (odd number of open files = unmount in progress = further opens inhibited, when closing a file and count reaches 1, tell the lazy unmount to get on with its job)
spoiler: you should probably listen to pitust, not me
but
google says that the lazy unmount hides the mountpoint but waits for all files to be closed (before actually unmounting it in the background)
So it effectively prevents further opening of files
i wonder if that extends to oepning a file within a directory you already have open
iirc in linux a lazy unmount makes the mount invisible in the vfs
I‘d assume it does
And it somehow
Makes the directory appear empty
Or something
the trivial implementation i was thinking of, i would just remove the mount from the mount table
that would prevent walking into it from outside of it, but not walking inside it when you're already inside
i'd imagine that's what linux does
test it maybe
On linux
Also check how it reacts if you do ../mountpoint from inside the mountpoint
Because in theory it shouldn’t be able to find it anymore assuming going backwards is legal
oh that's an interesting one
in my trivial implementation idea, it would still be possible
because the removal from the mount table doesn't do anything to this field:
/*! namecache handle over which the mount was made, if not root */
namecache_handle_t nchcovered;
I mean
You could just do it however you like
I don’t think you have to comply strictly to linux design choices
(Except if there’s a reason for why they‘ve been made ofc)
quite, i don't think i even really need a lazy unmount
i am sceptical about it being any good
forced unnmount i am not certain about either
It may be sensible for network based file systems from what i‘ve gathered from my quick reading
Wait
force unmounting
may hang
right
So if you have a non responsive mountpoint because network down or disk dies
You can make it look like it‘s been completely unmounted by lazily unmounting it, therefore not risking a hangup
i suppose it depends on how you handle certain situations
but some of them are really quite difficutl to handle if say your disk controller has decided to hang
From what i‘ve read it’s a thing with NFS‘s
Server goes down, doesn’t respond anymore -> lazily unmount to clean up the mount point
it's probably the most reasonable approach i suppose
actually i think it really is the only reasonable option
since it's hard to tear down everything and make it so that you can guarantee in reasonable time that everything referencing the FS will be gone
I‘m sure you can implement the lazy thing on top of the non lazy version, so i‘d just do the normal unmount for now
the latter, i think
