#pmOS - microkernel OS for RISC-V, x86, and LoongArch
1 messages · Page 3 of 1
The driver should program the DebounceTmrOut/DebounceTmrOutUnit/DebounceCntrl bits according to
the data passed by BIOS through ASL code
![]()
![]()
![]()
![]()
Is it me or is Linux's driver a bit fucked?
(AMD spec)

This stuff is reserved...
Oh nevermind
I can't read
@twilit talon the driver is cooking 🧑🍳
Btw, linux does this
if (pin <= 255) {
char ev_name[8];
sprintf(ev_name, "_%c%02X",
agpio->triggering == ACPI_EDGE_SENSITIVE ? 'E' : 'L',
pin);
if (ACPI_SUCCESS(acpi_get_handle(handle, ev_name, &evt_handle)))
handler = acpi_gpio_irq_handler;
}
if (!handler) {
if (ACPI_SUCCESS(acpi_get_handle(handle, "_EVT", &evt_handle)))
handler = acpi_gpio_irq_handler_evt;
}
(the only part that's left is to call uacpi)
Although ACPI says
Interrupt based event signaling follows a similar methodology, a generic event device (GED) is declared which in turn
describes all interrupts associated with event generation. The interrupts are listed in a _CRS object. When an interrupt
is asserted the OSPM will execute the event method (_EVT) declared in the GED object specifying the interrupt
identifier as a parameter. In this way the interrupt can be associated with specific platform events
A GPIO controller is modeled as a device in the namespace, with _HID or _ADR and _CRS objects, at a minimum. Op-
tionally, the GPIO controller device scope may include GeneralPurposeIO OpRegion declarations ( Section 5.5.2.4.5)
and GPIO interrupt-to-ACPI Event mappings (Section 5.6.5.2). Note that for GPIO-signaled ACPI Events, the corre-
sponding event method (e.g. _Exx, _Lxx, or _EVT) must also appear in the target GPIO controller’s scope. For GPIO
event numbers larger than 255 (0xFF), the _EVT method is used.
Each pin on a GPIO Controller has a configuration (e.g. level-sensitive interrupt, de-bounced input, high-drive output,
etc.), which is described to OSPM in the GPIO Interrupt or GPIO IO Connection resources claimed by peripheral
devices or used in operation region accesses
Damn
Looks correct
Did you figure it out?
pin 0 looks correct according to your aml as well
I went to eat
I think they've connected it to gpio so it can have debounce
Because my laptop has its power button on its side for no reason
And it's acutally handled by the GPIO controller lol
Do I just call uacpi_eval with "_EVT(0)" ?
uacpi_execute
which has no ret value
And _EXX and _LXX as well?
Yes
But do I also call execute with no arguments?
Like what's the difference between eval and execute
just simpler signature
uacpi_status uacpi_eval_simple(
uacpi_namespace_node *parent, const uacpi_char *path, uacpi_object **ret
)
{
return uacpi_eval(parent, path, UACPI_NULL, ret);
}
uacpi_status uacpi_execute(
uacpi_namespace_node *parent, const uacpi_char *path,
const uacpi_object_array *args
)
{
return uacpi_eval(parent, path, args, UACPI_NULL);
}
uacpi_status uacpi_execute_simple(
uacpi_namespace_node *parent, const uacpi_char *path
)
{
return uacpi_eval(parent, path, UACPI_NULL, UACPI_NULL);
}
does this help? 
Bruh
Ok
So eval _EXX and if that fails execute _EVT
(since it's the same thing)
is it edge triggered?
agpio->triggering
Lol, this means that the power button is literally almost wired to the interrupt line
yes
Linux does sprintf
do u understand the logic now?
Yes
nice
I just didn't know which functions to call
_EVT is generic, aka a fallback
_LXX or _EXX are specialized
btw one extra difference
_L/EXX doesnt take any args
_EVT takes in an integer
so u want to pass it uacpi_object_create_integer(pin_idx)
lmao
Can I do some sort of get_handle/eval serapately, so I distinguish between non-existing nodes and errors?
uacpi_namespace_node_find
(though I guess I can do that by the return value)
or that
why would it be no handler lol
Idk because there's no handler found...................
which handler
its edge triggered in your case
Am I supposed to be calling uacpi_object_unref?
on your created integer? yeah ofc
I'm doing sprintf
(after the call right)
(I think so)
(I'll push the code once I confirm it works)
bruh it's returning 6
(I know there is a to text function but I would be debugging things too quickly in that case)
NOT_FOUND
holy shit
yes its working
Switch (ToInteger (Arg0))
{
Case (0x00)
{
M000 (0x3900)
M460 (" Notify (\\_SB.PWRB, 0x80)\n", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00)
Local0 = \_SB.PCI0.LPC0.EC0.HWAK /* External reference */
If (((Local0 & 0x04) == 0x04))
{
Local0 &= 0xFFFB
\_SB.PCI0.LPC0.EC0.HWAK = Local0
Notify (\_SB.LID0, 0x80) // Status Change
Sleep (0x01F4)
}
ElseIf (((Local0 & 0x20) == 0x20))
{
Local0 &= 0xFFDF
\_SB.PCI0.LPC0.EC0.HWAK = Local0
Notify (\_SB.LID0, 0x80) // Status Change
Sleep (0x01F4)
}
ElseIf (((Local0 & 0x50) == 0x50))
{
Local0 &= 0xFFAF
\_SB.PCI0.LPC0.EC0.HWAK = Local0
Sleep (0xC8)
If ((\_SB.PCI0.LPC0.EC0.ADPT == 0x01))
{
Notify (\_SB.ADP0, 0x80) // Status Change
Notify (\_SB.PCI0.LPC0.EC0.BAT0, 0x80) // Status Change
}
Else
{
Notify (\_SB.ADP0, 0x80) // Status Change
Notify (\_SB.PCI0.LPC0.EC0.BAT0, 0x80) // Status Change
}
}
ElseIf (((Local0 & 0x80) == 0x80))
{
Local0 &= 0xFF7F
\_SB.PCI0.LPC0.EC0.HWAK = Local0
Notify (\_SB.PCI0.LPC0.EC0.BAT0, 0x80) // Status Change
}
Else
{
Local0 &= 0xFFEF
\_SB.PCI0.LPC0.EC0.HWAK = Local0
Notify (\_SB.PWRB, 0x80) // Status Change
}
Event this huge if is handled correctly
u get into the last branch
Why wouldn't it be
uacpi bugs potentially
this means all init up until this point was correct
pretty fucking cool
this is like cutting edge hw too
/*
* Modern hardware uses power button devices instead of the fixed event.
* Search for them here and hook AML notifications.
*/
uacpi_find_devices(ACPI_HID_POWER_BUTTON, [](void*, uacpi_namespace_node *node, uint32_t) {
uacpi_install_notify_handler(node, handlePowerButtonNotify, nullptr);
return UACPI_ITERATION_DECISION_CONTINUE;
}, nullptr);
This is what's left for you
@hexed acorn he actually got it
try on your laptop ^^
nope
gitlab L
Where
reg &= ~PIN_INTERRUPT_MASK;
I'm not
ah nvm
It's only when !is_interrupt_pin(device, offset + j)
(influenced by linux)
Anyway
What did I want to do
Right
Oof C++
My ACPI server is written in C
(my OS is weird)
(because why not have C++ kernel and C userspace)
Ok I'm adding it
i can try it in a moment
- uacpi_resources *resources;
- uacpi_status result = uacpi_get_current_resources(node, &resources);
+ result = uacpi_for_each_device_resource(node, "_CRS", find_amd_gpio_resources, device);
if (result != UACPI_STATUS_OK) {
printf("Failed to get resources for AMD GPIO device\n");
goto fail;
}
- uacpi_for_each_resource(resources, find_amd_gpio_resources, device);
- uacpi_free_resources(resources);
Ok
very based work btw, first hobby AMD gpio driver lol
now i gotta one-up that and make the first hobby amd i2c driver 
which actually is not amd-specific and is just some designware ip iirc
true
very very cool
it shut down the laptop
Can you update the wiki and add the third way lmao
congrats, very good work
fun
wtf
This needs fixing, but otherwise it works
what is that interrupt?
why is there no handler?
Because of how my interrupts work
Because it configures lapic from userspace, and then installs the handle
hm
And in between that, it's getting interrupts
I need to find the interrupt disable bit I'd suppose
btw while you're here can u test the wip uacpi PR real quick?
Ok
im about to merge it soon
if your test is succesful
git fetch && git checkout thread-safety-p3 in submodule
One sec
amazing, thanks
thats fine
i mostly wanted to make sure i didnt mess up by introducing deadlocks or anything like that
And my scheduler quantum is 100ms (I think)
first fully thread safe uacpi test 
But I create a pthread per event
u get quite a delay between plugging the charger and actually receiving a notify
i wonder why that is
Yeah idk
scheduling memes probably
That might be because the kernel is so slow
or debounce on hw side
My copy to/from user functions need fixing
And they're called all the time for IPC
Did obos get fixed?
fixed?
oh this reminds me, now that i've replaced the battery in my laptop i can actually test the charger plugged in/out events
It wasn't booting on my laptop
ah no i dont think so
pmOS on hyper?
thats nice because im still working on event stuff (finishing up rn so ill appreciate more testing)
i mean if u want lol
they're ec queries on mishakov's laptop as well
I want to try the old MacBook tomorrow
this should boot if i write it to an usb stick right?
asking since astral's iso didn't last time i tried it
hey u wanna try something

daily nyaux shilling
need ventoy 💀
Yes
I'm using ventoy though
I think I had some bad luck booting it on either bios or EFI machines directly from USB drive
Btw is there managram iso?
I've only found a weird format image
yeah we have raw hard disk images only
it should in theory work if you just write it to a usb stick or a hard disk
assuming that xhci/sata/nvme drivers cooperate
$(ISO): ../kernel/build/kernel ../bootstrapd/bootstrapd.elf ../devicesd/devicesd.elf ../logd/logd.elf ../ns16550/ns16550.elf ../piped/piped.elf ../processd/processd.elf ../terminald/terminald.elf ../vfsd/vfsd.elf ../vfatfsd/vfatfsd.elf ../ahcid/ahcid.elf limine.conf limine
mkdir -p isodir/boot/limine
mkdir -p isodir/EFI/BOOT
cp limine.conf isodir/boot/limine/
cp -v limine/limine-uefi-cd.bin isodir/boot/limine/
cp -v limine/limine-bios-cd.bin isodir/boot/limine/
cp -v limine/limine-bios.sys isodir/boot/limine/
cp -v limine/BOOTRISCV64.EFI isodir/EFI/BOOT/
cp -v limine/BOOTX64.EFI isodir/EFI/BOOT/
cp -v ../kernel/build/kernel isodir/kernel
cp -v ../bootstrapd/bootstrapd.elf isodir/
cp -v ../devicesd/devicesd.elf isodir/
cp -v ../logd/logd.elf isodir/
cp -v ../ns16550/ns16550.elf isodir/
cp -v ../piped/piped.elf isodir/
cp -v ../processd/processd.elf isodir/
cp -v ../terminald/terminald.elf isodir/
cp -v ../vfsd/vfsd.elf isodir/
cp -v ../vfatfsd/vfatfsd.elf isodir/
cp -v ../ahcid/ahcid.elf isodir/
# cp -v ../test/test.elf isodir
xorriso -as mkisofs -b boot/limine/limine-bios-cd.bin -no-emul-boot -boot-load-size 4 -boot-info-table --efi-boot boot/limine/limine-uefi-cd.bin -efi-boot-part --efi-boot-image --protective-msdos-label isodir -o $(ISO)
This is what I do
we don't have iso images mainly since we don't have an iso9660 driver so we couldn't mount the image (and we don't have overlayfs or anything so you'd be stuck with a read-only root)
lol (reasonable)
@carmine nacelle hey uh sorry for bothering u, I realized I had some possible races in the latest version and so I made some fixes, any way u can re-test with the same test?
Ok
nice
make sure u pull in the latest version since it was force-pushed
fetch && checkout should work
Is this alr?
yup
I can test it too if you want
i dont think u use GPEs for anything?
Wake from suspend
Sure
Impossible
It crashes before a new gdt is loaded
It also takes half a second, but it's hard to know for sure with windows 11
yeah
Maybe it's instant and gui is slow
we can check with managarm
it should be more or less instant there
i mean the irq to work
nice nice
although maybe it's better to test on real hw
does wake work on real hw?
probably
u never tested?
I will make it reboot after wake-from-suspend
i think the charger notifications also take like 1 or 2 seconds on my laptop as well
with managram?
although that's from plugging/unplugging it to seeing the status change in the taskbar in kde
did u test pmos?
i am currently glued to factorio i will test both pmos and managarm in a moment
I think it was not recieving events
yeah thats basically what i said
ah
It worked
What windows version makes it not assume that
what specifically
It'll be known for sure once uDRM becomes usable 🙂
Which Windows even added suspend?
suspend has existed since the inception of acpi
So like 98?
somewhere in the 90s
ACPI was first published in 96 according to wikipedia
Wake from suspend
on real hw?
Yes
damn obos cooking
On my old motherboard, Windows could not be able to wake sometimes
And it would clear bios
lmao
b450
Yes
Find the paper
I've read it
Then you have list
Of pages you need to have swapped in to run a program efficiently
Search pager replacement algorithm for info on how to do that
*page
I want to use it for disk caching
Uh ok
But idk if the same principle would apply
And just have all disks be virtually mapped into the kernel
Doesn't sound like an amazing idea
And then the algorithm could efficiently page everything in and out
yeah
I also don't think you page out page cache
me omw to get a fuckton of disks and make it run out of virtual memory
But like not mapped mapped
Idk
Be represented by memory objects
For which I use hash tables
of struct page
So like I could avoid IPC costs
By having all the cache be managed by the kernel
power button works in pmos on my laptop
Did it turn off?
yes
@twilit talon
said itll turn off in 3 seconds, and then it did
bro thats a huge win
so many things have to go right for that power press to reach the handler
And we have different platforms I think
what about EC events btw
for AC and stuff like that
i fucking hate the discord mobile app
how can you make something that sucks so bad
anyway, ec events work as well, tried brightness up/down and ac plugging in and unplugging (and yeah there is like a 1s delay there)
brightness up/down only works once though, then no more notifies happen
very cool
thats normal because it expects u to do stuff in response
same for sleep button
there's a timeout there after which it should start working again
probably
also there is an invalid arg error while running some aml method
my laptop spams it
ig it's trying to read from the ec opregion before it's been set up?
or the ec io rather
@carmine nacelle your ec_read returns UACPI_INVALID_ARGUMENT?
It could be
I copied it from managram
And it was checking read and write and returning invalid if none match
I need to add printfs I'd suppose
welp now to write managarm to the usb stick instead
also your iso does work if i just write it to the usb stick
nah when _REG is invoked its already set up
Found EC device at and before discovering GPIO is during its initialization
I have ```C
if (!device->initialized) {
return UACPI_STATUS_INVALID_ARGUMENT;
}

lol
no that aint gonna work
uacpi_status result = uacpi_install_address_space_handler(
address_space_node, UACPI_ADDRESS_SPACE_EMBEDDED_CONTROLLER,
handle_ec_region, device);
initialized must be set to true here
before this call
as u can see qookies laptop accesses it right there during _REG
so u must be ready at this point
I think I can just remove that check
no no
u should just move that installation down probably
no reason to do it before _GLK and _GPE check
but yeah i dont think its needed
@hexed acorn btw your laptop doesnt have an ECDT right?
if someone wants to test it
qookie@selenium ~ λ ls /sys/firmware/acpi/tables/E*
ls: cannot access '/sys/firmware/acpi/tables/E*': No such file or directory
yeah
i have like 5 laptops i can test a bit later
they're all intel tho
Mine are all AMD
Same
Steam deck is a PC 
Good idea
Does it suspend to s3?
Yes
I've commented out pthread stuff here
Since uACPI is already a good pthread test 
I think I know why battery events could be so slow
definitely should
(daily obos shilling complete)

Is i2c hard to implement?
My laptop has everything connected over it, by the looks of things
it has opregions of this type but they arent used very much
for very specific hw maybe
So they are separate things
Smbus and i2c
But AMDI0010 for example
amd-specific i2c controller probably
drivers/acpi/acpi_apd.c: { "AMDI0010", APD_ADDR(wt_i2c_desc) },
drivers/i2c/busses/i2c-designware-platdrv.c: { "AMDI0010", ACCESS_INTR_MASK },
one of these
looks like a tiny driver as well
And yeah your touchpad is under one of these:
Scope (_SB.I2CB)
{
Device (TPNL)
{
Name (_HID, "GXTP7936") // _HID: Hardware ID
Name (_CID, "PNP0C50" /* HID Protocol Device (I2C bus) */) // _CID: Compatible ID
Scope (_SB.I2CA)
{
Device (TPD0)
{
Name (_HID, "XXXX0000") // _HID: Hardware ID
Name (_CID, "PNP0C50" /* HID Protocol Device (I2C bus) */) // _CID: Compatible ID
or i guess touch panel and touch pad
is it a touch screen laptop?
anyway yeah a lot of HID devices via i2c
Yes
I have another one
Which also has an accelerometer and a bunch of stuff
And a pen support
Anyways, I think I'm motivated enough to work on page cache
So I can finally have a disk driver
Or maybe I can implement kernel threads 
(for the disk stuff)
why does that need kernel threads?
They would already go through a server
But, the kernel has memory objects and is in charge of virtual memory management
Partially I guess
your server can give back the shared mapping to the process that it owns
So it would be quick to just add a few queues and keep track of cache there
every page fault would be handled by it by paging stuff from disk
i just think its strange to have it in kernel if your disk drivers are in userspace
And I don't see yet how it can be done cleanly
Why
userfaultfd + shared mappings
very easy to do cleanly
use SCM_RIGHTS to give it the shared mapping of the file, then the faults would be handled by either reusing an existing page from cache, or COWing it, or paging from disk into cache etc
u have userfaultfd right?
or similar
page faulting thread freezes until user decides what to do
because you're gonna have to be talking to disk drivers in userspace, which kinda breaks the idea of a microkernel
its supposed to be abstracted away

I'm not really talking to drivers
It's page in and page out requests
But yeah, with write-protect flag I can make userspace track their page stuff
how do u know who to send them to
My memory objects (memory regions) have an IPC port (handle) link in them
Which stop the kernel from zero allocating memory, and pauses the thread and sends a message to the userspace handler untill the page fault is resolved
I had that since the beginning
That is easy
Now, how do I track dirty pages?
And like since the kernel does memory management, how does it flush caches when it runs out of memory and stuff
what does tihs mean
does every process handle their own page faults
but u said this
It's optional
oh
Like you can have kernel give zeroed pages
Or you can have it ask userspace for pages
yeah idk still feels a bit backwards to make the kernel responsible for it
maybe, not sure
But then you have minix which manages page tables in userspace
lol
So like kernel has no say at all
Idk
I need to think about it
I can put it in userspace
yeah
I think I'm basically doing the same as this https://www.gnu.org/software/hurd/microkernel/mach/external_pager_mechanism.html
Minus the
capability designating the task
Change manager Pager m_o_return store_write\ _________ (B) (A) (C) ________ (D) _______
S | / Default \ / \ / \ / \
W |<=>| Pager |<=>| Mach |==>| server |<=>| storeio |<=>
A | ___/ _/ _/ _/
P |
/(A) The ?paging policy is implemented by Mach: servers just implement the mechanism.
(B) Once the kernel has selected a page that it would like to evict, it changes the manager from the server to the default pager. This way, if the server does not deallocate the page quickly enough, it cannot cause a denial of service: the kernel will just later double page it to swap (the default pager is part of the tcb).
(C) Mach then invokes memory_object_return method on the control object. The server is expected to save the page free it in a timely fashion. The server is not required to send a response to the kernel.
(D) The manager then transfers the data to the storeio server which eventually sends it to disk. The device driver consumes the memory doing the equivalent of a vm_deallocate.
But mach is a fat microkernel
im a bit skeptical about these complex designs now because ive seen the proxima os just come in and demolish the uacpi benchnmark without any of these things
but its single threaded ofc so perhaps doesnt mean anything
was it the fastest microkernel?
It was the slowest microkernel 
lol
L4 was the fastest
But they have a very small kernel and just focus on doing IPC as fast as possible I think
just steal l4 designs then
But it doesn't matter
All microkernels are scheduling, IPC and memory management
Mach is 100k LoC (I think)
L4 is 10k LoC
It's just overly complicated
wtf
how is it so tiny
hyper is bigger than that lmao
uACPI is 26k 💀
misha@Yoga:~/pmos/kernel$ cloc .
183 text files.
183 unique files.
6 files ignored.
github.com/AlDanial/cloc v 1.90 T=0.45 s (393.7 files/s, 79707.7 lines/s)
-------------------------------------------------------------------------------
Language files blank comment code
-------------------------------------------------------------------------------
C++ 61 2702 2172 10193
C/C++ Header 95 2064 4444 6079
C 1 700 1938 3672
Assembly 15 341 523 1101
CMake 4 20 1 55
JSON 1 0 0 18
make 1 5 0 10
-------------------------------------------------------------------------------
SUM: 178 5832 9078 21128
-------------------------------------------------------------------------------
do --vcs=git
(dlmalloc is 4k LoC)
?
cloc . --vcs=git
With one dash only
works with two here
I've rm'd smoldtb
And I think my userspace is 30-40k LoC, excluding external libraries
So I'm doing ok
misha@Yoga:~/pmos$ cloc . --vcs=git
738 text files.
732 unique files.
65 files ignored.
github.com/AlDanial/cloc v 1.90 T=1.17 s (587.6 files/s, 102243.9 lines/s)
-------------------------------------------------------------------------------
Language files blank comment code
-------------------------------------------------------------------------------
C 233 5923 9078 28607
C/C++ Header 287 5116 12463 17302
diff 3 103 417 14857
C++ 75 3321 2393 13312
Assembly 45 703 1396 2206
make 23 306 91 766
JSON 3 0 0 241
Markdown 4 80 0 227
CMake 10 68 14 150
YAML 1 1 0 43
Go 1 2 0 12
-------------------------------------------------------------------------------
SUM: 685 15623 25852 77723
-------------------------------------------------------------------------------
Fun
Somehow I have more C than C++ 
I think it's pulling something in which should be a submodule
13k LoC of assembly is very sus
Oh and diff
Yeah it should be around 50k LoC
Anyway, what this says is that
Process wants memory
It requests it from server, which tell the kernel "I'm gonna be managing addresses 0xAAAAAAA - 0xBBBBBBB of process X"
When the process (thread) page faults, the kernel stops it and asks the server to read the stuff from disk
When the kernel decides to evict the memory it gives the page back to disk driver, to write it onto disk...
It should be simple
Assuming you know when to evict a page
And avoids gazillion task switches every time someone wants to read something from disk
Yes, that's the most difficult part
I think I'll have two queues
Yes, and that's what I want to implement
But for page cache
In the end, it's almost the same thing
Here code example
But like then I can just say "move anonymous memory to this disk to swap out"
And I have swap
But your working set size if fixed
Note that you also have dirty and standby lists for swapping, and if you use the discord search feature you can find hyenasky explaining it
Yeah I want to implement that
But I don't knwo if I understand it correctly
Hyenasky explains it decently I think
If not you can look into code, or ask people
Yeah I think the explanation is quite clear
What I want though, apart from that, is to have the kernel flush pages periodically, even when there's no memory pressure
Like what linux does
For mmaping files
I abstract that all in src/oboskrnl/mm/swap.c
I mean no one is stopping you
I case someone yoinks the power cord
Sounds like an idea you can do
You could probably even implement that easily by keeping the modified page writer always running
Or occasionally waking it
Like have a timer going for x seconds that wakes it
And hopefully that won't cause too much of a performance loss
I can run it in background as a kernel thread
But what infy was saying
Why am I putting it in kernel if I'm a microkernel
My argument is that it should be kept close to the paging stuff
l4 is a thin layer over kernel mode
lol
how so slow
(and my anonymous memory mappings are temporarely bad)
ah
dont fuck this up because I use pmos as an example when someone says "uacpi no workie"

Not for no reason
Why is it so complex yet so slow
mach consistently recorded favourable results performancewise (by 1986 already it outperformed 4.3BSD and that's why 4.4BSD imported the mach vmm)
I'm trying to remove the state from page tables and move that to memory objects
And I currently just store pages in a linked list, which is very slow to traverse on page faults (I'll replace it with hash map once everything else works)
speaking of VMM mach invented the TLB shootdown and the VM object, two concepts which are everywhere now
I've implemented tlb shootdowns by/after reading the mach paper
the entirety of the "slow mach" claim is some guy, a german guy i should point out, take of that what you will, trashtalked its IPC for being asynchronous and semantically rich while his own was not, so he compared the time it takes for a roundtrip on mach v.s. his own kernel, l3, and found mach wanting
and nowadays that claim is more based on transmission of trivia than anything else
So microkernels not (necessarely) slow?
there's no reason why they should be
at least it depends on how "slow" is meant
if you compared a perfectly optimal microkernel to a perfectly optimal monolithic kernel then probably you will observe a small performance differential in the monolithic's favour
since even in optimal form of each, IPC will never be so fast as simple syscalls
thats not even necessarily why
tight coupling in monolithic kernels allows for more reactive stuff, like nvme switching to poll mode dynamically depending on scheduler load etc
this is not practical in a microkernel
since all components are abstracted away from each other
there are a lot of "hacks" you can do in a monolithic kernel that are relatively simple to reduce latency and stuff
in a microkernel this would require a lot of work and thought
hardware drivers in userland are more of an orthogonal axis, traditionally microkernels don't do that, untraditionally monolithic kernels do
even so i think that there is a lack of imagination here
actually i thought from the start of this conversation about there being certain difficulties (but not insurmountable obstacles) in providing the kind of responsiveness in microkernels that is more obvious in monolithic kernels
like your page cache server idea, it drives a hard bargain, how would it participate in the page replacement policy? the easier and more traditional approach is that the microkernel does that policy and delegates to pagers the mechanism of reading or writing back pages on demand
even so i don't think the ability of a microkernel system to have these sorts of things should be written off
with respect to synchronisation it really is a bit of a challenge i think
file truncation on keyronex for example i am thinking about a lot lately, it is a bit of a hassle because i want to replicate the behaviour on a lot of unixes where (shared mapped) pages beyond the truncation point are thrown out of processes that mapped it (so if they try to access them, they get SIGBUS)
and that sounds deceptively easy but is more challenging to synchronise
first you need some kind of barrier after which you won't get A) any new read/write requests beyond the new limit, and B) any new mmap'ings of the file beyond the new limit, for instance, then you need to deal with all of the existing mappings
you need to keep a mind as well to the theoretically possible situation where you're short of memory but the only place you can reclaim it from is the very file you've locked so you can truncate it
and i did think about how much harder this stuff would be if i had a microkernel (or maybe it would be easier, maybe i am halfway along a needlessly complicated path and i can't see the straight path)
yeah sounds like a very fun puzzle to solve
I've also been thinking about that, but in terms of locks ordering
lol
i find locking one of the hardest things
i spend probably 80% of my time thinking about keyronex thinking about that
its also the least rewarding
I slapped locks on memory objects. It's kinda probably slow with a lot of cores, but solves all the problems
because your reward is: it works (sometimes when it wouldnt?)
Now, with memory object inheritance, the child object (chain) might want to request pages from the parent objects, and parent objects want to unmap the pages from child objects, what do I do with locks
if you do it really well you get faster/more scalable
that's why it bothers me so often
the easy thing is you just have a big kernel lock and a few condition variables for the long waits
do you permit arbitrarily long chains of memory objects?
Slapping locks is easy. When you start locking several of them at the time is when it becomes really fun
I want to do that
what for?
So it can work as CoW for fork

And stuff like that
Forking? Just create two new objects that inherit from each other
that's one thing i dislike about mach, they had these memory object chains, and there is some use to them and they are probably more general
but i find it obtuse and problematic to deal with (freebsd needs something like a "garbage collector" to clear out no-longer needed objects within a chain)
I haven't implemented it yet, but it seems like a simple and effective idea
i found the sunos solution of individually refcounted anon structures nicer
I've thought of that
Is there a paper?
so that's what the new right arrow does
I'm also adding "anonymous" flag to objects
So that they can only be mapped once
And they can easily decay once the parent object only has one anonymous child object
netbsd's uvm replicated this while still being a machish vmm in other respects, it's discussed in https://www.usenix.org/legacy/publications/library/proceedings/usenix99/full_papers/cranor/cranor.pdf
https://keyronex.readthedocs.io/en/latest/vmm.html#anonymous-mappings i also discuss it here
I think that's what I have at the moment but I'm removing it and going to object chains 
there might be some merit to object chains but i can't identify any personally
fuchsia ended up with them as well, but a big fuchsia guy complained it's problematic for them
(another "coincidental" resemblance of fuchsia to mach)
the refcount of the anons are incremented by 1

But I can still do that with memory objects
Just having them be created horizontally
but the chain structure doesn't really match
Yeah
the individually-refcounted page is a more fit match
really what i would say is that fork is just a bit of a nightmare in general and while i like unix i don't much like fork
Oh, the problem is storage
Although maybe not really
It's implementation details (?)
At the moment my page struct can only pertain to one memory object, and has an intrusive list pointer, which allows it to be stored in objects
But I guess I can replace that with some other data structure, which would not be intrusive
the trick is the singular anon struct is the "object" it'd belong to
Hmm
So like pages are still part of that object, but are referenced by many structs?
there's one vm_anon for every virtual page, no matter how many times it's shared
and there's a vm_amap which is comprised of a table of pointers to vm_anons (the vm_amap is a member of an anonymous vm object)
the definition of a vm_anon from old keyronex (the one that could actually run xorg etc) might illustrate:
struct vm_anon {
kmutex_t mutex;
uintptr_t pfn_or_drumslot: 63, resident: 1;
uint32_t refcnt;
};
drumsalot???
who drums a lot/
im so confused
you must imagine an anon as having some of the responsibilities of a VM object (here viz. storing either a physical page pointer or a swap location)
drumslot
whats that
the traditional term for a swapfile location
it's because historically drum meory was used to swap to
(physical) page frame number
oh okay
and i see vm anon is reference counted, why so?
is there like a particular reason for it or
for fork purposes, if it's referenced by > 1 process, then it should be CoW'd
oh okayy
Ok, I don't quite understand all of the aspects of it, but I need to think about it
I still want object chains for filesystems though, but I think that can be combined
Hmm, I think I can just put that in my struct page
no you can't
you need somewhere to store the refcnt when it's swapped out
in principle maybe you could have your swap allocator store this instead, i think it might work
Yeah, just store page struct like stuff there
possible lock ordering oddities because vm_anons are their own thing and can be referenced by multiple vm objects
And replace the pointer to page with that
Yeah that's gonna make swap very slow
Since I guess I will have to be iterating through all anon regions when swapping pages in and out
I wanted to say that I don't like extra memory allocations involved with this
But I think this is actually fine...
My Page is roughly ```C++
struct Page {
Page *next;
u64 offset;
size_t refcount;
PageType type = PageType::Free;
int flags = 0;
};
I think I won't even have to inflate it for this stuff
Ok I have to study so I'm gonna be quick and try to implement all of this till the end of today 
study now
pmos later
:)
No
I started making changes to memory management yesterday after thinking about it for 3 monts
I want closure
No, I do
if you use global rather than local page replacement, you'd keeping some kind of physical-to-virtual mapping for each page
else you'd have to do linux style scanning page tables for references to the page you want to outswap
There's something I don't get
And that's anonymous mappings
That would create a memory object
It would have amap attached to it
How do I avoid deduplication of zero pages?
Well, not the zero, but on the first page fault, it would allocate a page in the memory object, and then it would be copied to the amap
Now I have zero page inside the memory object, and another page inside the amap
Hmm
A special case of mapping is used for MAP_PRIVATE mmap()’s of a vnode
So if a mapping is anonymous, pages are moved instead of being copied?
the amap is of the VM object
Yes, but if I understand it correctly, you would have pages "stored" in memory objects, and then amap to hold the privately mapped modified pages
well if you've modified it you've modified it
i don't understand your question
as best i can understand you're asking what happens if someone creates an anonymous VM object
and then maps it MAP_PRIVATE
and then they write to a page and it induces the creation first of a pageful of zeroes in the VM object that was mapped, then a second page privately
that's a very bizarre thing for someone to do
you can optimise that case explicitly if you want
That's how I wanted to implement anonymous mappings
you'd be mapping the object shared
not private
But then there's fork stuff, which has to clone it somehow
that's what the anons are for
you make a new object
and increment the reference of every anon that the parent's object had
the object does not matter one bit in this, the anon alone matters
I don't get it then
it's very simple
you have an anonymous VM object with an amap
you create it when you're asked to allocate some anonymous memory in a process
you map it shared
So amaps are unconditional?
I though that they were only needed for private mappings
when you fork, you create a new anonymous object for the child, and foreach parent object->amap entry, you ++ amap[i]->refcnt and you store parent amap[i] into child amap[i]
they are unnecessary for really shared anonymous VM objects, i.e. ones that are not created to back private memory
because really shared anonymous VM objects (tmpfs files for instance) never need to be subject to symmetric cow
What I wanted to do is to not clone memory objects at all when forking
only to asymmetric cow
If the mapping is shared, there is no amap
then you can embed amaps in VM map_entry's instead
When the mapping is private, the same object is mapped again, creating new amap
So them the anonymous memory would have to be private object + private mapping
if you want to have VM objects for everything then you will have to map VM objects for mmap MAP_PRIVATE as, paradoxically you might think, shared mappings
Yes
but note i say "shared" not "MAP_SHARED"
if you do so then VM objects are entirely unnecessary for private anonymous memory
That's what I had at the moment
But I want to unify it into one mechanism
Kind off and without CoW
Hmm that's also certain, I can still have amaps, just no objects
Then I don't even need anonymous objects (I think)
Why would I
they might be useful for tmpfs files and also for mmap() MAP_SHARED anonymous mappings
some people really like them
I'm not really getting it
On shared mapping, I skip amaps and get pages from the objects directly
if you used VM objects for every mapping, you'd have a kind of anonymous VM object that contained an amap
On private mappings of shared objects, I get pages from objects on reads, and copy them to amap on writes
at first i assumed (wrongly) that you really wanted to have everything be a VM object
(I've meant this as something to do in futue)
That is my idea
Or was
So then I could have object chains for CoW
But yeah I think I can try to do this amap thing instead
you were the world's first man to want to replace clean simple amaps and anons with object chains
The're not clean and simple as I have them implemented at the moment
So I guess I should just refactor what I have so that the private copies could be shared
Although I can maybe just change my Page struct to count references for private mappings
No, there's swap problem again
Or maybe there isn't if I walk page tables...
Ok, I think I'll keep the system that I have at the moment
Which is similar in spirit to amaps
But I'll also keep what I did yesterday, which is having anonymous mappings have memory objects
Since that could provide fast physical -> virtual lookups
(I don't have a separate amap table, so the info will be stored in page tables directly)
the traditional way is to do a pv map
that's a list head in the page struct which points to a pv_entry struct stating in which vm map + which offset every page is mapped
however you can make an economy instead
by instead allocating, for every time you allocate a new region of private mmap'd anonymous memory, some struct describing what the offset is and a list of every process that pages belonging to this region could be in
and have your page structs point to that thing
This kinda feels like a big waste of memory
it's perhaps another 24 bytes for every mapping of a page
however this alternative solution i propose above should work as well
Or have that struct be the memory object
With no edge cases
since while vm_anons are self-contained, they won't be found at arbitrary offsets - they don't move around
mremap?
Idk if I even want to support it though since that seems to be a Linux thing
I just remember I wanted to test uACPI

Fun, MacBook is refusing to boot limine with ventoy
(though I think the framebuffer was also broken without it)
Wtf macs don't have delete button??
sony's ec works, but i think it got the power button event twice
I can't find the charger for the Asus netbook 
And spectre x360 is refusing to charge
@twilit talon is that normal?
why does it take so long to print
Because
a. My IPC is slow (because of really bad implementation)
b. I think I'm mapping framebuffer as non-cacheable
so map the framebuffer as WC
easy
even i do that in nyaux
!!!
Macbooks hace ECDT
My new b550 motherboard doesn't have EC

Need to check with windows
Also I need to investigate what took it so long
But meh
I'm really hoping spectre x360 comes back to life
Do I need this?
what is ECDT
fn+delete
Oh no, it's fully dead
Even disconnecting the battery doesn't make it turn on
Very sad
It was a cool laptop
Nice
Acpi table
and what it contain
What device is this?
I mean pnp0200
"DMA controller" according to Windows
I think its the legacy isa one
Could be
which resources does it use
some hp meme
A bunch of IO ranges
nice, your os works on quite a lot of hw
and ec seems to work too
It works on everything I've tried so far
https://wiki.osdev.org/ISA_DMA yeah its this, scroll down to registers
No obos curse
do you have a ps2 driver
indeed
thats where your stability will end 
Why
astral curse
My PS/2 controller was working
astral curse is ps2 driver breaks on every existing hw but your own
I had been polling it so it would work even with some lost interrupts 
I have no idea why they were lost though
Still, is it normal that it got 2 power button events?
could be physical damage or bugged firmware
usually firmware masks this event so u cant retrigger it
its a fixed event in this case not an EC one right?
I think it's ec
then we can take a look at aml
So it've gotten the event, then the fixed one
makes sense
Why
u enable both, u receive both
At the same time?
why wouldnt it be at the same time
Idk firmware should do something
u should disable the fixed one if ec is supported probably
or idk, see how linux decides
does your FADT even report fixed pwrb event support?
HP laptop has EC, but uses fixed interrupt
Idk
there's a fadt bit for that
i think u can decide based on that
Control Method Power Button (V1) : 1
this one
either way it shouldnt matter because u should have protection from that
i can also just spam this button as a user
Btw have you been able to try it on your PCs? 
#1236769772805554206 message
thanks
@carmine nacelle any way u can check kapi-improvements for regressions on some of your hw? I have removed all uacpi_kernel_raw_*
I can check that later
nice
no rush
I can test it if you want
np
I really need to find all the chargers from my laptops so i can test pmos on them (and obos as well ig)
shutdown and reboot is what mightve regressed so make sure that still works

I can explain how to compile pmOS 
we have a slight problem
it doesn't shutdown
checking that rn
i have your iso
But like to test uACPI
luckily for you infy, it hangs in obos' code
lol
now it's my problem to find out why
does it hang in qemu as well?
F
it hangs halting the other CPUs
except it broadcasts an NMI
so I suspect it's a bug in the handler
How did I come to have the (seemingly) most stable OS here?
-# I should probably find all times I said "Microkernel L" to you and replace them with "microkernel W"
skill unissue
when your os is so stable it crashes gdb

raw read stuff is basically this now:
uacpi_status uacpi_system_io_read(
uacpi_io_addr address, uacpi_u8 width, uacpi_u64 *out
)
{
uacpi_status ret;
uacpi_handle handle;
ret = uacpi_kernel_io_map(address, width, &handle);
if (uacpi_unlikely_error(ret))
return ret;
ret = uacpi_kernel_io_read(handle, 0, width, out);
uacpi_kernel_io_unmap(handle);
return ret;
}
similar for memory
I just use iopl so my io_map does nothing
So I don't think there would be a difference...
but u still have to ask the kernel to modify iopl no?
Yes, but it's a flag in rflags
ah lol
maybe the bug was a deadlock since I would halt other CPUs with a lock held
Which I just set unconditionally
anyway the idea is there shouldn't be any difference besides less API to implement
There's other mechanism which does allow you to allow individual ports
Which I might implement in the future
But what I have atm works so it's not a priority
@twilit talon it now hangs in uacpi
just implement this
rather that or it hangs in my kernel api
i can tell u which one it is 
can you test shutdown on pmos
to make sure I didn't mess up
does it only hang on real hw or qemu as well
technically stuff changed in the PR should work the same way on QEMU and real hw
its a 1-byte write to one io port
what if u revert uacpi tho
obos daily regression debugging
New branch
Haven't tested it myself
@carmine nacelle your stuff hangs on my laptop

