#OBOS (not vibecoded)

1 messages · Page 24 of 1

flint idol
#

that's a big part of D state API implemented

real pecan
#

Nice

flint idol
#
// Enable all power resources set by _PRW.
uacpi_namespace_node* pwr_resource = nullptr;
for (size_t i = 2; i < (pkg.count - 2); i++)
{
    uacpi_data_view path = {};
    uacpi_object_get_string(pkg.objects[i], &path);
    pwr_resource = uacpi_namespace_node_resolve_from_aml_namepath(dev, path.const_text);
    uacpi_status ustatus = uacpi_eval(pwr_resource, "_ON", nullptr, nullptr);
    if (uacpi_unlikely_error(ustatus))
    {
        if (ustatus != UACPI_STATUS_NOT_FOUND)
            OBOS_Warning("%s: Could not enable power resource for wake. Status: %d\nNote: Skipping...\n");
        continue;
    }
    
}```
#

hopefully I used uacpi_eval right there

real pecan
flint idol
#

ty

#

I think scope should be the namespace root

#

or just nullptr

#

to assume root

#

OBOS_DeviceMakeWakeCapable is 153 lines

#

including some helpers to evaluate DSW/PSW

#

and to enable/disable power resources in _PRW

#

I still must implement OBOS_DeviceSetDState and OBOS_DeviceHasDState for this to be completed.

real pecan
flint idol
#

uacpi_object_resolve_as_aml_namepath takes scope

#

as the second argument

real pecan
#

yes

flint idol
#

I'm deleting it tho

real pecan
#

the scope is the parent device you're resolving against

#

this is so that if the resource is just 4 letters it recurses upwards correctly

#

and finds the node

#

otherwise it would fail

#

sometimes its an absolute path in which case it doesnt matter

#

but sometimes just 4 letters

flint idol
#
static void enable_pwr(uacpi_namespace_node* dev, uacpi_object_array *pkg, bool on)
{
    uacpi_namespace_node* pwr_resource = nullptr;
    for (size_t i = 2; i < pkg->count; i++)
    {
        uacpi_object_resolve_as_aml_namepath(pkg->objects[i], dev, &pwr_resource);
        uacpi_status ustatus = uacpi_eval(pwr_resource, on ? "_ON" : "_OFF", nullptr, nullptr);
        if (uacpi_unlikely_error(ustatus))
        {
            if (ustatus != UACPI_STATUS_NOT_FOUND)
                OBOS_Warning("%s: Could not %s power resource for wake. Status: %d\nNote: Skipping...\n", __func__, on ? "enable" : "disable", ustatus);
            continue;
        }
    }
}```
#

this is what it is now

real pecan
#

ye

flint idol
#
uacpi_object_array pkg2 = {};
uacpi_object_get_package(pkg->objects[0], &pkg2);
uacpi_object_resolve_as_aml_namepath(pkg2.objects[0], nullptr, &gpe_dev);
uacpi_object_get_integer(pkg2.objects[1], &gpe_idx);```
also this code
#

for the wake gpe stuff

real pecan
#

no error checking at all but ok

flint idol
#

who needed error checking

#

it probably™️ exists

#

and I don't wanna error check for stuff like fetching integers

#

or packages

white mulch
#

assert(... == UACPI_STATUS_OK)

flint idol
#

333 lines of pure power management

#

how fun

#

I think this file for D state management will probably end up being 500-600 lines

#

unconviniently

#

if a D state doesn't exist for a device as power resources (_PRn) or as _PSn, I should still disable the power resources for lower D states, right?

#

To put a device into the ACPI power state Dx (where x is a number between 0 and 3 inclusive) the kernel is supposed to (1) enable the power resources required by the device in this state using their _ON control methods and (2) execute the _PSx control method defined for the device. In addition to that, if the device is going to be put into a low-power state (D1-D3) and is supposed to generate wakeup signals from that state, the _DSW (or _PSW, replaced with _DSW by ACPI 3.0) control method defined for it has to be executed before _PSx. Power resources that are not required by the device in the target power state and are not required any more by any other device should be disabled (by executing their _OFF control methods). If the current power state of the device is D3, it can only be put into D0 this way.

white mulch
#

oh yeah the power resources can be shared

flint idol
#

fuck acpi

white mulch
#

maybe you could just not turn any power resources off

#

though ofc it would likely result in more power usage

real pecan
#

whats the point of suspend then LULW

flint idol
#
const char prn_path[] = { '_', 'P', 'R', '0' + state };
uacpi_namespace_node* prn = uacpi_namespace_node_find(dev, prn_path);```
fnuy variable names
#

(hint: o)

white mulch
#

would likely be what you get if you use the pcie mechanism to put the device to a sleep state too

flint idol
#

I hate acpi

#

I now go eat

#

and be back

real pecan
#

damn you eat a lot

flint idol
flint idol
#

ok

#

time to go suffer

#

and implement transitioning to D states

weak kestrel
#

you ate already?

flint idol
#

how would I even know

#

if a power resource is shared

real pecan
flint idol
#

and how do I find every device using the power resource

real pecan
#

u run the prw right

#

so u know the power resource

flint idol
#

yeah

real pecan
#

u accumulate them

#

then u just have power resources with arrays of devices

flint idol
#

sounds boring af

#

like

#

really boring

#

did I mention how that sounds boring

white mulch
flint idol
#

you can turn off all of them

real pecan
#

that i have no idea

flint idol
#

then reenable the ones wake use

white mulch
#

that sounds kinda sketchy, what if there are devices not in sleep state using them and then you just cut power to them KEKW

flint idol
#

refcount it

white mulch
#

well idk if it really matters, maybe it doesn't

flint idol
#

abstract power resources and ref it for each device using said resource

#

the unref it when u wanna turn it off

#

until ref becomes zero

#

where you actually turn it off

#

by evaluating _OFF

#

also keep a list of referencing devices

#

because why not

white mulch
#

I guess that works, and you probably want to discover all devices from the acpi namespace and get the power resources of them because if you only get them for the ones you have a driver for it might be bad

flint idol
#

or just never turn off power resources because you are lazy

#

although now I should theorerically be able to wake from sleep

#

because I set up stuff properly

#

except for D states

#

which I need to do

real pecan
#

do u restore bars now

flint idol
#

I just said wake from sleep

#

not wake from sleep and continue normal operation

white mulch
#

when you have implemented the bar restore then let me know if it actually properly worked KEKW

flint idol
#

kk

thick jolt
#

congrats on 34 stars

flint idol
#

ty

thick jolt
#

np !!!

flint idol
#

if you prefer sanity, do not

#

@real pecan apparently linux doesn't support PCI PM (the thing you do to put PCI devices into D states)

#

PCI bus power management, however, is not supported by the Linux kernel at the time of this writing and therefore it is not covered by this document.

thick jolt
flint idol
#

and if you do decide to despite my warning

#

you'll probably want to wait until I finish my implementation so you can have a reference that isn't linux

thick jolt
#

i see

flint idol
#

I am the first hobby kernel with suspend

thick jolt
#

!!

flint idol
#

fr

thick jolt
#

frfr

flint idol
#

In some platforms, certain power resources may be shared between devices and processors, requiring both to be in specific idle states before they can be turned off. Direct OSPM control of such resources is not possible while the OS is running because the processors depend on the resources being enabled whilst they are running. It is only when processors go idle that it may be possible to turn off these shared resources. For a given resource of this type this is only possible if, in addition to the processors being idle, any other devices that depend on the resource are in a state that allows powering it down. In these cases, the platform can manage the power resource as part of entry/exit from a Low Power Idle (LPI) state and OSPM can guide the decision on whether or not to turn off the resources with its LPI state request. In those cases the power resource _ON/_OFF/_STA methods are completely redundant.

Passive power resources, which are just like traditional power resources except they do not include _ON, _OFF, or _STA, are introduced to support this case. Omission of these methods reduces overhead by avoiding redundant evaluations and saves the platform from having to supply (working) methods which it does not need. Since OSPM cannot manage passive power resources directly via _ON/_OFF, passive power resources must be listed as a dependency of at least one LPI state where the platform will manipulate them. The dependencies between LPI states and power resources are described in the _RDI object. See _RDI (Resource Dependencies for Idle) for additional details.

#

just found this

#

if I understood right

#

it actually tells me the power resource dependencies

flint idol
#

marker

#

I'm going to redesign my entire PCI interface

#

luckily PCI is only used twice in all of OBOS

#

the AHCI driver

#

and PnP

#

so first I guess I'll have a struct pci_resource

#
enum pci_resource_type
{
    PCI_RESOURCE_BAR,
    PCI_RESOURCE_MSI_CAP,
    PCI_RESOURCE_MSIX_CAP,
    PCI_RESOURCE_CMD_REGISTER, // only ever one of these
};
struct pci_bar
{
    uint8_t idx;
    uintptr_t phys;
    size_t size;
    bool bar32; // true: 32-bit bar, false: 64-bit bar
    uint8_t flags;
};
struct pci_resource
{
    union {
        struct pci_bar *bar;
        uint16_t cmd_register;
        // msi(-x) stuff
    };
    pci_resource_type type;
    size_t refs;
};```
#

as well as a struct pci_device

#

which contains the HID of the pci device (class, subclass, and prog if in a more unified format)

#

vendor id

#

device id

#

the location

#

and all the pci resources

#

all PCI devices will be cached in memory

#

I will also be supporting PCIe

#

I will have some helpers to update resources

#

and stuff

flint idol
#

I can call something like Drv_UpdateResource(device, the_bar_we_just_updated);

#

to tell the PCI bus I modified the BAR

#

on top of that it can also restore PCI resources after wake

flint idol
#

which will also be a resource

#
union pci_hid
{
    struct
    {
        uint8_t classCode;
        uint8_t subClass;
        uint8_t progIf;
        uint8_t revId;
        uint16_t vendorId;
        uint16_t deviceId;
    } OBOS_PACK indiv;
    uint64_t id;
};
struct pci_device
{
   union pci_hid hid;
   struct pci_resource* resources;
   size_t nResources;
};
#

there will also be pci_node

#

which can be a pci_device

#

or a pci bus bridge (TODO: what is that?)

#

hold up

#

when am I supposed to be calling uacpi_finalize_gpe_initialization

#

omg

#

I never call uacpi_finalize_gpe_initialization

#

and apparently I need to

#

please don't let that be the problem on real hw

#

well please do let it be the problem

#

but if it is then that'd be embarrassing

#

Didn't fix anything

#

Yeah so I did look at some debug logs

#

That I added

#

It only confirmed that the D state needed doesn't exist on my pc

#

I'll set uacpi to trace

#

after spending way too much time looking for the function that sets the uacpi log level

#

I will now reboot and see what uacpi is actually doing

real pecan
flint idol
#

Got some logs on real hw

#

It still doesn't wake my kernel though

#

trace isn't enough logging

#

time to use DEBUG

real pecan
#

lol

#

maybe add your own logs to know where it hangs at least

flint idol
#

It doesn't hang

#

It never wakes up

#

Same bug I was debugging two or three days ago

flint idol
#

But smashing the keyboard to wake me does nothing

real pecan
#

ohh

flint idol
#

Clicking the power button makes it reboot

real pecan
#

lol

flint idol
#

Debug is too much logs

#

So I'm gonna make it only do debug logs

#

When evaluating PSW

#

inb4 it never evaluated PSW

real pecan
#

u do do setup_for_wake and stuff right?

flint idol
#

Yup

flint idol
#

if you were wondering how I actually setup a device for wake the code's in here

#

OBOS_DeviceMakeWakeCapable

#

at line 166

real pecan
#

gpe_dev is not the device

#

gpe dev is nullptr in your case

flint idol
#

yes

real pecan
#

yes what

#

just pass in nullptr

flint idol
#

if it exists

real pecan
#

no no

#

ur just doing it wrong

#

its always \_GPE

#

its not the power resource

flint idol
#

I think you may have misunderstood my code

real pecan
#

maybe

flint idol
#

if the first element of _PRW

#

is a package

real pecan
#

oh yeah nvm

#

probably

flint idol
#

the first element is a reference to the GPE device

#

and the 2nd element is the gpe index

real pecan
#

did u try printf'ing what it finds?

flint idol
#

nope

real pecan
#

should probably

flint idol
#

added some more logs

#

Other than the fact that the gpe index is 0xd each time.e

#

It looks fine

#

PSW is evaluated

real pecan
#

just shared gpe

#

what does psw say

flint idol
#

Well it is only enabling USB controller sleep capability

flint idol
#

It sets some field to Ones

#

And returns

real pecan
#

makes sense

#

maybe d2 is wrong

flint idol
#

according to the acpi spec it should be right...

real pecan
#

yea..

flint idol
#

well the deepest sleep state supported in S3

#

is D2

#

so apparently the D state I should enter is D2

real pecan
#

also like

#

does fb never shutdown when u suspend?

flint idol
#

it does

#

and the light on my power button indicating suspend

#

is on

real pecan
#

interesting

flint idol
#

one behaviour that might be wrong

#

is not enabling a device for wake

#

if _S3D and _S3W don't exist

real pecan
#

btw

#
    args.objects[0] = uacpi_object_create_integer(enableWake);
    args.objects[1] = uacpi_object_create_integer(target_slp);
    args.objects[2] = uacpi_object_create_integer(target_d_state == DSTATE_INVALID ? 0 : target_d_state);
    uacpi_object_ref(args.objects[0]);
    uacpi_object_ref(args.objects[1]);
    uacpi_object_ref(args.objects[2]);
flint idol
#

double reference I assume

real pecan
#

did u assume that initially created objects have a refcount of 0?

flint idol
#

yup

real pecan
#

lol

flint idol
#

I'll just fix that rn

real pecan
#

to see what it does

flint idol
#

I'll look in a bit

#

I changed that behaviour temporarily to see if it changes anything

#

I keep accidentally clicking sleep instead of restart

real pecan
#

lol

flint idol
#

when tryna reboot into obos

#

Weirdly when I unplug a usb

#

Then replug it in

#

It seems to initialize

real pecan
#

strange that its rebooting on power button press

flint idol
#

Yeah

real pecan
flint idol
#

Like it has a light

#

That flashes

#

When it's plugged in

#

To a computer

#

Which means that the ehci controller is alive

real pecan
#

ah and no wake?

flint idol
#

No wale

#

*wake

real pecan
#

interesting

flint idol
#

Hold on

#

When it's shutdown

#

The USB still flashes

#

So it might be that ehci really is dead?

real pecan
#

maybe its just continuous power delivery

flint idol
#

Maybe

#

The EHCI controller has no power resources

#

Both controllers

#

And the XHCI controller

real pecan
#

damn

flint idol
#

just found a mistake in the acpi spec

#

for _S1D

#

it says it returns

An Integer containing the shallowest D-state supported in state S2

real pecan
#

copy pasta

flint idol
#

what if instead of evaluating _SnD and _SnW

#

I use the things in the uacpi namespace node info

real pecan
#

whats the diff

flint idol
#

idk

#

I saw this

This value overrides an S-state to D-state mapping OSPM may ascertain from the device’s power resource declarations.

#

and thought that maybe uacpi would have known a bit more

#

and looked in other places for _SnD

real pecan
#

nah

flint idol
#

well it is an override

#

so that doesn't matter

#

time to look at linux src

#

y'know what

#

I'm gonna beat mc and be back

flint idol
#

just beat minecraft

#

@real pecan I just realized that linux passes nothing to DSW

#

with nothing meaning 0,0,0

#

and nothing to PSW

#

with nothing meaning it executes it without any arguments

flint idol
#

it passes zero to it too

#

which, according to the acpi spec, would disable the device's wake capabilities

#

and from what I could reverse engineer from my dsdt

real pecan
#

huh

flint idol
#

ok I think I was looking in the wrong place

real pecan
#

like if that method does a RefOf and then stores it somewhere this will be a UAF

#

thats why i dont even offer such api

flint idol
#

wait

#

I just realized I had a bug with GPEs previously

#

where I would get infinite GPEs

#

so I kept them masked

#

I wonder if that could have anything to do with this

real pecan
#

lol

flint idol
#

I still get infinite GPEs

#

But it doesn't hang the system anymore

#

Nvm

#

It hangs after a bit

real pecan
#

u can mask that particular GPE

#

uacpi_mask_gpe(nullptr, Idx)

flint idol
#

It gets an infinite stream of GOEs

#

*GPEs

#

or really

#

an infinite stream of GSI 9

#
/*
    oboskrnl/irq/irql.h

    Copyright (c) 2024 Omar Berrow
*/

#pragma once

// You mustn't include anything else, or everything will likely stop compiling.
#include <int.h>```
I love this comment in irql.h lol
real pecan
#

well

#

gsi 9 can mean literally anything

flint idol
#

in my case it's GPE

#

just noticed a bug

#
static void bootstrap_irq_handler(irq* i, interrupt_frame* frame, void* udata, irql oldIrql)
{
    OBOS_UNUSED(i);
    OBOS_UNUSED(frame);
    OBOS_UNUSED(oldIrql);
    uacpi_handle ctx = *((void**)udata);
    uacpi_interrupt_handler handler = (uacpi_interrupt_handler)((void**)udata)[1];
    handler(ctx);
}
#
uintptr_t *udata = OBOS_KernelAllocator->ZeroAllocate(OBOS_KernelAllocator, 1, sizeof(uintptr_t), nullptr);
    udata[0] = (uintptr_t)ctx;
    udata[1] = (uintptr_t)handler;
    irqHnd->handler = bootstrap_irq_handler;
    irqHnd->handlerUserdata = udata;```
#

nvm

#

I misread that

real pecan
#

a gpe spam can happen if it expects the system to do something in response and u dont do it

flint idol
#

mhm

#

and how do I know what that is?

real pecan
#

u generally dont

#

proprietary drivers

flint idol
#

bruh

real pecan
#

but like

flint idol
#

I suspect it might be a bug in my IOAPIC code

#

since it's TriggerModeLevelSensitive

#

and active low

#

iirc

real pecan
#

only GPEs with an AML handler are enabled by default

#

does it tell u how many it has enabled

#

and also u do do setup_for_wake before finalize_initialization right?

flint idol
#

yes

real pecan
#

if u add a printf to uacpi we can see which aml handler it runs

#

and what that handler does

flint idol
#

okie

#

where shall I put it?

#

just throw a function name at me

real pecan
#

it already exists

#

enable trace

flint idol
#

okie

real pecan
#

async_run_gpe_handler

flint idol
#

inb4 it never gets to uacpi

real pecan
#

wouldnt be surprised

flint idol
#

Ummm

#

It infinitely prints that it's in the bootstrap irq handler

#

But never prints any thing in uACPI

real pecan
#

lol

#

u could add printfs to handle_sci

flint idol
#

It initialized a gpe block

#

Then starts printing that forever

flint idol
real pecan
#
static uacpi_interrupt_ret handle_sci(uacpi_handle ctx)
{
    uacpi_interrupt_ret int_ret = UACPI_INTERRUPT_NOT_HANDLED;

    int_ret |= handle_fixed_events();
    int_ret |= handle_gpes(ctx);

    return int_ret;
}
#

this is the interrupt handler

flint idol
#

@real pecan am I supposed to call uacpi_initialize_events

#

or does uacpi do it for me

#
#define UACPI_INTERRUPT_NOT_HANDLED 0
#define UACPI_INTERRUPT_HANDLED 1```
real pecan
flint idol
#

ok

#

The GPE goes unhandled

#

It gets to handle_sci

real pecan
#

maybe one of the regs in detect_gpes has a non-zero status

flint idol
#

maybe I'm not even supposed to be getting an SCI in the first place

real pecan
#

well u do get it so

#

u probably are

#

unless you're fucking something up

flint idol
#

could be a bug with how I'm configuring the IOAPIC

#

I'm gonna take a look at the madt

real pecan
#

yeah its a possibility

flint idol
#

I found the interrupt source override for the SCI

real pecan
#

yeah i think ur fucking it up

#

because uacpi has a warning for this

        uacpi_warn("GPE(%02X) fired but no handler, keeping disabled\n",
                   event->idx);
#

maybe tahts why wake also doesnt work

flint idol
#

maybe

#

the SCI interrupt is overriden as active-high level-triggered

real pecan
#

maybe its a bogus override or maybe ur not handling it correctly

flint idol
#

found the bug

#

*a bug

real pecan
#

what is it

flint idol
#
bool res = false;
if (polarity == 0b1 || polarity == 0)
    res = true;
else if (polarity == 0b11)
    res = false;```
#
// polarity (0: active-high, 1: active-low)```
real pecan
#

maybe use fucking enums

#

uacpi lliterally has them defined

flint idol
#

I wrote this ages ago

#

this is likely copied from my third kernel

real pecan
#

F

flint idol
#

I fixed that

#

time to see if it fixes anything

#

It fixed the gpe bug

#

But not the wake bug

real pecan
#

well thats one bug out of the way

flint idol
#

Yea

#

Hold on

#

Nvm

#

ngl fuck acpi

#

I do all it tells me to make a device wake capable

#

and behold

#

it never wakes up

#

maybe I am triple faulting

#

not that I would know why, or how

#

It seems to triple fault in the smp trampoline

#

On wale

#

*wake

#

@real pecan this is big, wake works

#

But doesn't at the same time

white mulch
#

from keyboard?

flint idol
#

No from power buttom

#

*button

white mulch
#

for usb I am pretty sure that you need to first setup the usb controller as it has its own port suspend stuff and it generates wake events for enabled ports

flint idol
#

Idk what's happening though

#

Why it triple faults

#

Could be corrupted memory

#

It is confirmed to triple fault in the smp trampoline

#

And not somewhere else in the code

#

It triple faults after entering long mode

#

Which can mean two things:
Gdt is corrupted
Page table has the smp trampoline unmapped

#

but it probably is not the gdt

#

since otherwise the other smp trampoline code would be corrupted

#

but I explicitly map the smp trampoline

#

why can't I just have a real hw qemu log

#
    jmp 0x8:reload_cs_addr
.reload_cs:
reload_cs_addr: equ $-Arch_SMPTrampolineStart+trampoline_base
    mov ax, 0x10
    mov ss, ax
    mov ds, ax
    mov gs, ax
    mov fs, ax```
#

it triple faults somewhere here

real pecan
flint idol
#

If I knew I'd tell you

#

Maybe it always worked but triple faulted each time

#

As now I know it triples

flint idol
#

it'd be funny if I were in protected mode

#

on entry of the smp trampoline

#

Wtf

#

Wtf

#

Wtf

#

I decided to assert that

#

Just in case

#

The assertion failed

real pecan
#

how did u even asert it

flint idol
#

Looked at cr0

#

If bit 0 is set

#

Jump to the reset vector

real pecan
#

meh probably some skill issue

flint idol
#

Otherwise continue

#

ok it might not be the case

#

as I had my infinite loop right after the place where it triple faults

flint idol
#

Thank God it wasn't the case

#

Otherwise I would be sending an angry email to acer

white mulch
#

it is possible that you indeed boot in protected mode tho

flint idol
#

Bit 0 of cr0 is off

#

Making me in real mode

#

When I try looking at the gdt

#

Before reloading the segments

#

It triple faults

#

Rather that

#

Or the assertion fails

#
mov eax, [gdt_addr+0x8+4]
    test eax, 0x00af9b00
    jz .down1
    jmp 0xf000:0xfff0

.down1:

    mov eax, [gdt_addr+0x10+4]
    test eax, 0x00cf9300
    jz .down2
    jmp 0xf000:0xfff0

.down2:
       db 0xeb, 0xfe```
#

the joy of debugging smp trampolines

real pecan
#

well it works in qemu right?

flint idol
#

yea

real pecan
#

interesting

flint idol
#

if it didn't then why would I be debugging it on real hw

real pecan
#

mental insanity

flint idol
#

I fucking hate this shit

#

I am going insane

real pecan
#

just make obos 16 bit so u dont have to switch

flint idol
#

I make SURE that the gdt is intact RIGHT FUCKING BEFORE I reload the segment

#

and it still fucking triple faults

#

IS IT FDRESH SD
fds G

#

DSGURHEGURHED]

#

DFSGVHDFVGDHFKJGHDFS

#

e

#

e

#

e

#

e

quaint rivetBOT
#
Anti-spam Message

Possible spam detected for user: oberrow. Please contact a moderator to be unmuted.

real pecan
#

maybe the gdt is too high in memory

flint idol
#

it's at 0x1008

#

which is mapped

real pecan
#

u do respect real mode addressing and stuff right?

flint idol
#

I'm in 16-bit long mode

real pecan
#

maybe real hw puts u into non zero cs

flint idol
#

or smth like that

#

if my trampoline is at 0x1000

#

wouldn't that mean that cs is zero

real pecan
#

it can be represented as 0 cs yes

#

doesnt have to tho

flint idol
#

I'll make sure it is then

real pecan
#

reload cs to zero first thing yeah

flint idol
real pecan
#

lmao

#

so i guess your suspend now works on real hw

flint idol
#

Wait what the fuck lmao

#

mov cs, ax

#

Didn't crash

real pecan
#

wtf

flint idol
#

ok wtf

#

why

#

is it now

#

triple faulting

#

in QEMU

#

ashnjryr

#

AHHHHHHHHHH

#

BRO

#

WHY

#

IS THE TRAMPOLINE'S STACK MAPPED AS READ ONLY

#

ok fixed

#

@real pecan I might almost be able to wake on real hw

#

I mean it hangs somewhere

real pecan
#

is it in c code at least

flint idol
#

only god knows

#

78% chance that it is

#

anyway

#

time to push this code

#

then I will commence work on the new pci interface

real pecan
flint idol
#

nope

#

it could be anything

#

and I don't

#

have the willpower to debug that

#

without printf

real pecan
#

reinit fb bars

white mulch
#

I doubt it's that easy tbh

real pecan
#

wdym?

white mulch
#

as in you'd just get the framebuffer back after restoring the bars without doing anything else

real pecan
#

if u run _WAK and stuff u should

white mulch
#

also regarding the bar restore I am not sure how do you actually get it to properly work, I tried it on the legacy chipset in qemu that uses port io for pci space and there the values persist after you write them but if you use q35 and mmio pci space then they just read back as zeros after you write to them

real pecan
#

also might be because MTRRs also get reset

flint idol
#

forgot those existed

white mulch
#

that could be, though idk if qemu cares about that

real pecan
#

on qemu it should be as easy as just writing to bar regs, so that must be some sort of skill issue on your part

#

(probably)

flint idol
#

only 1k additions meme

#

nothing too big

real pecan
white mulch
#

the bars?

flint idol
#

-d trace:pci*

real pecan
#

yeah

flint idol
#

time to make the new pci interface

real pecan
white mulch
#

it only shows this (and no pci_cfg_write/pci_cfg_read that I get when initializing some devices) ```
bus reset
pci_update_mappings_del VGA 00:01.0 0,0xfd000000+0x1000000
pci_update_mappings_del VGA 00:01.0 2,0xfebd4000+0x1000
pci_update_mappings_del e1000e 00:02.0 0,0xfeb80000+0x20000
pci_update_mappings_del e1000e 00:02.0 1,0xfeba0000+0x20000
pci_update_mappings_del e1000e 00:02.0 2,0xc040+0x20
pci_update_mappings_del e1000e 00:02.0 3,0xfebd0000+0x4000
pci_update_mappings_del ich9-ahci 00:1f.2 4,0xc060+0x20
pci_update_mappings_del ich9-ahci 00:1f.2 5,0xfebd5000+0x1000
pci_update_mappings_del ICH9-SMB 00:1f.3 4,0x700+0x40
[kernel][smp]: resuming after wake from sleep
KERNEL PANIC: pci.cpp:49: (resume_from_suspend) assertion 'device->read(hdr0::BARS[i]) == device->raw_bars[i]' failed

flint idol
white mulch
#

how do you restore that lol

flint idol
#

I just want to make sure that my suspend properly works on real hw (and doesn't hang somewhere arbitrary) before writing the article

real pecan
white mulch
#

bruh

flint idol
#

bruh

real pecan
#

but idk if thats the way to do it

flint idol
#

anyway I'll be back in a bit

real pecan
#

in the MCH_HOST_BRIDGE_PCIEXBAR register

#

so basically u have to reinitialize the chipset yourself

real pecan
#

its one write

white mulch
#

that's kinda weird, there are like billion different chipsets

flint idol
#

I would expect that to be handled by _WAK

real pecan
#
static void mch_mmconfig_setup(u16 bdf)
{
    u64 addr = Q35_HOST_BRIDGE_PCIEXBAR_ADDR;
    u32 upper = addr >> 32;
    u32 lower = (addr & 0xffffffff) | Q35_HOST_BRIDGE_PCIEXBAREN;
    pci_config_writel(bdf, Q35_HOST_BRIDGE_PCIEXBAR, 0);
    pci_config_writel(bdf, Q35_HOST_BRIDGE_PCIEXBAR + 4, upper);
    pci_config_writel(bdf, Q35_HOST_BRIDGE_PCIEXBAR, lower);
    pci_enable_mmconfig(Q35_HOST_BRIDGE_PCIEXBAR_ADDR, "q35");
}
#

this is how SeaBIOS does it

#

basically just the address | 1

flint idol
real pecan
#

maybe on real hw its handled via _WAK idk

white mulch
#

it looks like linux only does it to a few host bridges so that might be the case

real pecan
flint idol
#

How does it know that it should? Does it probe it by writing an address and making sure the same value is read back

#

And how does it know what chipsey

real pecan
#

its literally a pci device at 00:00.0?

#

the host bridge is a pci device

#

the base

flint idol
#

Now I'm just confused

real pecan
#

type lspci

flint idol
#

We need to reinitialize the chipset

real pecan
#

your pci device 0 is the chipset

flint idol
#

So we can use PCI

#

And then we find the chipset with pci

real pecan
#

u can use the legacy io

#

ecam must be enabled separately

flint idol
#

oh

white mulch
real pecan
#

supposedly its this

white mulch
#

that's what I found yeah

real pecan
#

but that doesnt have q35

white mulch
#

I guess I can at least try if doing that to see if it changes anything regardless

real pecan
#

yeah i mean we know it will

#

i saw what it does in reset in qemu

#

it disables it

#

i just dont understand how linux restores it

flint idol
#

linux is just magic

#

it does some black magic to wake up from suspend

#

properly

#

it's the only way

white mulch
real pecan
#

ohh interesting

white mulch
#

looks like its still not properly enabled for some reason, the enable bit is not set and if I set it then it starts working

real pecan
#

is this resume code even called?

real pecan
#

so seabios did not in fact restore it

white mulch
#

I guess that branch where it does the enabling didn't get hit then, idk why tho

#

at least pci_resume is called in the only s3 resume path there is

real pecan
#

thats so weird

#

u are booting with seabios and not ovmf right?

white mulch
#

yes

real pecan
#

oh i think its a bug in SeaBIOS

white mulch
#

with ovmf it just works without doing anything

real pecan
#

nvm no doesnt look like a bug

#

this was added a very long time ago too

flint idol
#

or does seabios do it for me

white mulch
#

well its supposed to do it but idk why doesn't it actually happen in practice

#

would have to add debug prints to seabios ig, idk if I feel like doing that rn

flint idol
#

I can try

#

just tell me where

#

@white mulch SeaBios does indeed call mch_mmconfig_setup

white mulch
#

hmm

flint idol
#
PCIe: using q35 mmconfig at 0xb0000000```
#

and I also added a log before calling it

#

and it did indeed call that

white mulch
#

could you make sure that mmconfig in src/hw/pci.c is zero at the start of that fn? because if its saved across the suspend then it would try to use the memory space to enable the ecam (which doesn't work for obvious reasons)

#

its a static so you'd have to make it a global or make some sort of accessor fn or smth ig

real pecan
flint idol
#

it does

real pecan
#

maybe qwinci's seabios is just some bugged old version

real pecan
#

send qwinci your seabios

white mulch
real pecan
flint idol
#

idk ask qwinci

real pecan
#

no like

#

where did u get it

flint idol
#

I dprintf'ed it

white mulch
#

and that was after suspend?

real pecan
#

show the goddamn diff

flint idol
real pecan
#

show git diff

flint idol
#
diff --git a/src/fw/pciinit.c b/src/fw/pciinit.c
index b3e359d7..dd0e35bc 100644
--- a/src/fw/pciinit.c
+++ b/src/fw/pciinit.c
@@ -396,6 +396,8 @@ void pci_resume(void)
     }
 
     if(MCHMmcfgBDF >= 0) {
+        extern u32 mmconfig;
+        dprintf(1, "mmconfig=0x%08x\n", mmconfig);
         mch_mmconfig_setup(MCHMmcfgBDF);
     }
 }
diff --git a/src/hw/pci.c b/src/hw/pci.c
index 8eda84b2..e556b9ea 100644
--- a/src/hw/pci.c
+++ b/src/hw/pci.c
@@ -14,7 +14,7 @@
 #define PORT_PCI_CMD           0x0cf8
 #define PORT_PCI_DATA          0x0cfc
 
-static u32 mmconfig;
+u32 mmconfig;
 
 static void *mmconfig_addr(u16 bdf, u32 addr)
 {```
real pecan
#

nah thats fine

#

it doesnt explain anything

white mulch
#

I am pretty sure that my theory is correct in that as its non-zero at that point it uses ecam to write to the base addr register ```c
void pci_config_writel(u16 bdf, u32 addr, u32 val)
{
if (!MODESEGMENT && mmconfig) {
writel(mmconfig_addr(bdf, addr), val);
} else {
pci_ioconfig_writel(bdf, addr, val);
}
}

real pecan
#

ohh so it is a bug?

real pecan
flint idol
#

sure

flint idol
real pecan
#

jesus christ

#

RetardoBIOS

flint idol
#

theoretically the fix should just to reset mmconfig?

flint idol
real pecan
#

yeah reset mmconfig on reset

#

or rather

#

on suspend

flint idol
#

or rather

#

on wake from suspend

#

since the bios doesn't really know that we're suspending

real pecan
#

doesnt matter

flint idol
#

only the aml code

real pecan
#

wdym it doesnt know

flint idol
#

well

#

how would the bios c code know

#

if it's in C

#

and we use AML to suspend

real pecan
#

we use a write to an IO port

#

but yeah you're probably right, only qemu knows

flint idol
#

at the beginning of pci_reset

#

I will set mmconfig to zero

#

send qwinci the bios image

real pecan
#

u mean resume?

#

thats too early still

#

*too late

flint idol
#

and see if it works for him

real pecan
#

u should probably reset it here

flint idol
#

mkay

real pecan
#

fun fact

#

seabios knows its a resume from s3 by reading CMOS

flint idol
#

cool

#

try using this bios image

#

-bios /path/to/bios.bin

white mulch
#

doesn't seem to fix the issue unfortunately

flint idol
#

what else could it be thinkong

#

if you want seabios logs

#

add this

#
-chardev file,path=/dev/stdout,id=seabios -device isa-debugcon,iobase=0x402,chardev=seabios```
white mulch
#

looks like the write to mmconfig doesn't persist for some reason

flint idol
#

how?

white mulch
#

idk

#

but printing it inside writel reveals that its non-zero again at the point where it writes the base

flint idol
#

doing that somehow fixed my shutdown probably on seabios

white mulch
#

mmconfig

real pecan
#

like oberrow reset it incorrectly or something?

flint idol
#

I set it to zero

#
using legacy i/o
using legacy i/o
using legacy i/o
mmconfig=0x00000000
using legacy i/o
using legacy i/o
using legacy i/o```
#

and when I print it somewhere

#

it's zero

white mulch
#

does it work properly for you?

flint idol
#

well I don't use PCIe

#

so I wouldn't know

#

but what I do know is that

#

shutdown now works after wake-from-suspend on seabios

white mulch
#

it prints ```
using mmconfig
using mmconfig
using mmconfig
mmconfig=0xb0000000
using mmconfig
using mmconfig
using mmconfig
PCIe: using q35 mmconfig at 0xb0000000

flint idol
#

wtf

#

for me it prints

#
using legacy i/o
using legacy i/o
using legacy i/o
mmconfig=0x00000000
using legacy i/o
using legacy i/o
using legacy i/o
PCIe: using q35 mmconfig at 0xb0000000```
#

maybe I sent you the wrong image

white mulch
#

still same thing nooo

flint idol
#

wut

flint idol
#

before it resets mmconfig

white mulch
#
In 32bit resume
table(50434146)=0x7ffe20f4 (via rsdt)
resetting mmconfig
Found 1 cpu(s) max supported 1 cpu(s)
using mmconfig
using mmconfig
using mmconfig
mmconfig=0xb0000000
using mmconfig
using mmconfig
using mmconfig
PCIe: using q35 mmconfig at 0xb0000000
flint idol
#

wut

#

it sets mmconfig to zero

white mulch
#

yeah idk anymore

flint idol
#

your qemu is cursed

#

what else do you pass to qemu?

white mulch
#
qemu-system-x86_64 -boot d -cdrom /home/visa/Projects/crescent/cmake-build-debug-clang/image.iso -m 2G -M q35 -smp 1 -cpu qemu64,+umip,+smep,+smap -serial stdio -chardev file,path=/dev/stdout,id=seabios -device isa-debugcon,iobase=0x402,chardev=seabios -bios /home/visa/Downloads/bios.bin
real pecan
#

maybe print it right after reset?

white mulch
#

and qemu version is 9.1.0

flint idol
#

fail

real pecan
flint idol
real pecan
#

probably has something to do with this

#

the bios is readonly at this point maybe

flint idol
#

nope

#

make_bios_readonly is called

#

right before jumping to the wake vector

#

in FACS

real pecan
#

yeah but

#

make_bios_writable

#

try calling that

flint idol
#

I will once we confirm it's not just something else setting mmconfig

#

@white mulch

white mulch
#

there is only one place where its written and its static to pci.c file (in the unmodified seabios)

#

and when it writes to it it prints the "using q35 mmconfig at"

flint idol
#

can you try that image tho

real pecan
#

oberrow do u have SMM disabled?

flint idol
#

nope

white mulch
flint idol
real pecan
#

qwinci also doesnt have kvm

#

anyways looks like oberrows qemu doesnt enforce readonly bios

flint idol
#

each time I use tcg I'm reminded of why I don't use tcg

white mulch
#
table(50434146)=0x7ffe20f4 (via rsdt)
resetting mmconfig
mmconfig: 0x0
Found 1 cpu(s) max supported 1 cpu(s)
using mmconfig
using mmconfig
using mmconfig
mmconfig=0xb0000000
using mmconfig
using mmconfig
using mmconfig
PCIe: using q35 mmconfig at 0xb0000000
flint idol
#

wth

real pecan
#

lmao

flint idol
#

for me, on tcg+no smm

#

it triple faults

#

in the bios

#

or rather

#

triple faults somewhere

#

I was just able to reproduce what qwinci had

#

but it makes no sense

#

how does being on tcg

#

correlate to mmconfig not being set to zero at some random point

white mulch
#

maybe doing the make_bios_writable() like infy suggested before writing would fix it?

flint idol
white mulch
#

what if the compiler optimized the load out or smth

real pecan
#

^

flint idol
#

or maybe cpu cache

real pecan
#

its not a volatile variable

real pecan
flint idol
#

I fucking hate tcg

flint idol
white mulch
#

that works

real pecan
#

yay i was right

#

we really need to submit the fix to SeaBIOS

flint idol
#

yes

white mulch
#

yeah would be nice

real pecan
#

who's gonna do it?

flint idol
#

I will

#

since I have the code

real pecan
#

beware its a mailing list

#

but other than that its nice

flint idol
#

scary

real pecan
#

ive submitted a few fixes

flint idol
#

I'll remove my dprintfs

#

make a patch

#

should I sign off my commit

flint idol
real pecan
#

it was at least 2

flint idol
#

which also happened to be a PCI fix

real pecan
#

github is tripping

#

or maybe i am

flint idol
#

git log only found you once

real pecan
#

idk

flint idol
#

anything I'm missing

#

?

#

@real pecan

#

I think I explained what I did well enough

#

also when uLife

real pecan
# flint idol
On wake it would attempt use the ECAM space to restore access to ECAM, which wouldn't work because ECAM is disabled after reset.

Maybe something like that?

flint idol
#

that's better

#

(tbh I had no idea what I was doing in the first place)

#

((so I just tried saying what I think I did))

#

after subscribing to the seabios mailing list

#

to post on it

real pecan
#

good debugging today

#

and congrats on seabios contribution too

#

team work

flint idol
#

ye

#

this is my first time using a mailing list

#

do I just throw the patch file in there

#

or do I copy paste it into the body??

#

From 36720e74aac6822454262d019d3b2ba3f94248fa Mon Sep 17 00:00:00 2001
From: Omar Berrow [email protected]
Date: Sat, 2 Nov 2024 17:14:47 -0400
Subject: [PATCH] resume: reset mmconfig to zero

On wake it would attempt use the ECAM space to restore access to ECAM, which wouldn't work because ECAM is disabled after reset.

Signed-off-by: Omar Berrow [email protected]

src/hw/pci.c | 2 +-
src/resume.c | 9 +++++++++
2 files changed, 10 insertions(+), 1 deletion(-)

diff --git a/src/hw/pci.c b/src/hw/pci.c
index 8eda84b2..dfe4d92a 100644
--- a/src/hw/pci.c
+++ b/src/hw/pci.c
@@ -14,7 +14,7 @@
#define PORT_PCI_CMD 0x0cf8
#define PORT_PCI_DATA 0x0cfc

-static u32 mmconfig;
+volatile u32 mmconfig;

static void *mmconfig_addr(u16 bdf, u32 addr)
{
diff --git a/src/resume.c b/src/resume.c
index fb0b8a89..10b873c3 100644
--- a/src/resume.c
+++ b/src/resume.c
@@ -96,6 +96,15 @@ s3_resume(void)
return;
}

  • make_bios_writable();
  • // reset mmconfig to make sure that we don't use PCIe to
  • // resume PCIe
  • dprintf(1, "resetting mmconfig\n");
  • extern volatile u32 mmconfig;
  • mmconfig = 0;
  • dprintf(1, "mmconfig: 0x%x\n", mmconfig);
    +// make_bios_readonly();
  • pic_setup();
    smm_setup();
    smp_resume();
    --
    2.45.2
#

wait

#

it has my subject

#

but then

real pecan
#
git format-patch -1
git send-email 0001-<patch-name>.patch --to <[email protected]> --cc whatever
flint idol
#

do I need the cc

#

probs not right

real pecan
#

i dont remmeber what the seabios mailing list wants

#

usually there are maintainers u cc

flint idol
real pecan
#

apt install git-send-email

flint idol
#

ok I sent it using git send-email

#

but I don't see it on the mailing list

real pecan
#

it refreshes every x minutes

real pecan
#

well looks like it was abandoned so

white mulch
#

now I guess the only kinda important remaining problem is getting the framebuffer to work

white mulch
#

as at least on my kernel it doesn't work after _WAK + restoring the bars

#

yeah

flint idol
#

I'm going to implement that like

#

now

#

so I'll see what happens for me

white mulch
#

could also be some kind of skill issue on my part, would be nice to see what you get yeah

real pecan
#

could also be mtrr skill issue like i mentioned

white mulch
#

looks like the bars are still shown as F's in there, yeah ig I can try to save/restore the mtrrs

flint idol
#

wait

#

when I boot up the other CPUs

#

what are the MTTRs set to

real pecan
#

depends

#

probably same value if your bios is good

#

but yeah all cpus must have the same mtrrs otherwise its ub

#

its your job to configure them

flint idol
#

okay

real pecan
#

u can just save whatever bsp has initialy

flint idol
#

ye

#

that's what I was gonna do

white mulch
#

didn't change anything regarding info pci or the fb

#

info pci also shows the same thing when not using ecam

real pecan
#

wdym by not using ecam

white mulch
#

as in writing the bars using port io (or using the default qemu machine)

real pecan
#

not using ecam works, or the other way around?

white mulch
#

neither of them changes what info pci shows

#

the bars do read as the same value that I write to them on both of them

real pecan
#

do u write like the type info and stuff?

white mulch
#

yes, though I probably shouldn't

#

I'd think that it wouldn't really matter tho as its the same value that was there before

#

also trace shows no pci update mappings stuff, it only shows pci_cfg_write

real pecan
flint idol
#

MTRRs are dumb

white mulch
#

looks like it added the mappings after I enabled the mem + io spaces in the pci command

#

still no fb tho 💀

real pecan
white mulch
#

oh yeah maybe that stuff works now

real pecan
#

looks like here it just calls into standard DRM resume

flint idol
#

I now restore MTRRs

#

while initializing APs

#

and on S3 wakeup

#

branch is starting to get a bit too big

real pecan
#

how did u manage to make 8k changes lol

#

anyway we now know how to reinitialize everything on qemu

#

on real hw it might just work too

flint idol
#

and then I wouldn't even be done with that branch yet

#

I still have more syscalls

#

Because apparently, I was doing that before

#

then I'm also going to implement futexes (should be simple, right?)

white mulch
#

I figured out the fb problem (kinda), it looks like qemu doesn't refresh the window for some reason KEKW

#

when you resize the window a little then it refreshes

flint idol
#

Current roadmap:

  • Design new PCI interface
  • Make sure suspend works properly
  • Implement futexes
  • Implement sync primitive syscalls (Not needed, so nevermind)
  • Implement VFS syscalls
  • Implement partition syscalls (like partition probing n'stuff)
  • Implement driver interface syscalls
  • Implement TTYs
  • mlibc
real pecan
white mulch
#

I did that

real pecan
#

did u reconfigure the resolution regs?

white mulch
#

yes

real pecan
#

like same sequence as linux?

white mulch
#

I saved everything on suspend and then restored them

real pecan
#

disable, set res, enable

white mulch
#

basically yeah though the regs between disable + enable are in a different order

#

it shouldn't matter tho

real pecan
#

hm

flint idol
#

obos has 31 syscalls rn

white mulch
real pecan
#

do u do blank/unblank stuff too?

flint idol
#

I should be using all the handle types obos has

real pecan
#

handle types?

flint idol
#
typedef enum handle_type
{
    // vfs/fd.h
    HANDLE_TYPE_FD,
    // irq/timer.h
    HANDLE_TYPE_TIMER,
    // vfs/dirent.h
    HANDLE_TYPE_DIRENT,
    // scheduler/thread.h
    HANDLE_TYPE_THREAD,
    // scheduler/process.h
    HANDLE_TYPE_PROCESS,
    // mm/context.h
    HANDLE_TYPE_VMM_CONTEXT,
    // locks/mutex.h
    HANDLE_TYPE_MUTEX,
    // locks/semaphore.h
    HANDLE_TYPE_SEMAPHORE,
    // locks/pushlock.h
    HANDLE_TYPE_PUSHLOCK,
    // locks/event.h
    HANDLE_TYPE_EVENT,
    // driver_interface/driverId.h
    HANDLE_TYPE_DRIVER_ID,
    // scheduler/thread_context_info.h
    HANDLE_TYPE_THREAD_CTX,

    LAST_VALID_HANDLE_TYPE,

    HANDLE_TYPE_ANY = 0xfd,
    HANDLE_TYPE_CURRENT = 0xfe,
    HANDLE_TYPE_INVALID = 0xff,
} handle_type;```
#

basically what a handle actually is

real pecan
#

whats is the purpose of this

flint idol
#

verification stuff

real pecan
#

hm

flint idol
#

like

// vmm syscall
if (handle_type(vmm_ctx) != HANDLE_TYPE_VMM_CONTEXT)
    return OBOS_STATUS_INVALID_ARGUMENT```
real pecan
#

like if it gets corrupted or something?

flint idol
#

yeah\

#

or if a user program tries to do fnuy stuff with handles (e.g., passes in a dirent handle to a futex function)

#

the handle type can also indicate whether the user wants to use the current object (if such thing exists)

#

like if it wanted to it can pass a special HANDLE_CURRENT value, which simply has a handle with the type HANDLE_TYPE_CURRENT (that needn't be created)

#

to Sys_ThreadBlock for example

#

so it blocks the current thread

real pecan
#

really OBOS_ASSERT(thr);

#

just return error?

flint idol
#

thr can never be nullptr

white mulch
real pecan
#

oh i thought it was a syscall

flint idol
#

if the user passed an invalid handle

flint idol
#

it would return OBOS_STATUS_INVALID_ARGUMENT

flint idol
#

idr

#

it's OBOS_STATUS_INVALID_ARGUMENT

#

obos hit 36k loc recently

real pecan
#

nice

vale nymph
#

over 10k more than astral

flint idol
#

just figured out that git send-email it not actually sending emails

#

so I tried using the gmail smtp server

5.7.8 Username and Password not accepted. For more information, go to```
#

for that

#

(my username and password are both right)

flint idol
#

FUCK

#

I accidentally just sent a patch to seabios

#

that has no commit message

real pecan
#

Lol

#

I got it

flint idol
#

gmail is fucking stupid

#

idk why it won't just

#

let me use git send-email

#

like my brother

#

I put the correct password

#

and you say incorrect password

real pecan
#

Well u need to configure it idk

#

Works for me

flint idol
#

whatever

#

I'm just gonna use outlook or smth

real pecan
flint idol
#

or never touch mailing lists again

real pecan
#

U need to reboot the pc

#

It just stops working after N wrong attempts

devout niche
#

no one is using PINE to handle their (ascii, 80-char-wide) emails anymore so getting the right thing done is harder

flint idol
#

@white mulch so did writing to the BARs end up working with the patched seabios?

real pecan
#

yes

#

after enabling memory and io access he was able to get the fb to work

#

well and re-initializing the bochs fb

flint idol
#

oh ok

#

I'm going to do something and respond to the reply I got on the seabios mailing list

real pecan
#

yeah i saw it

flint idol
#

idk why, but compiling in release speeds my kernel up by like 2x

#

compared to no optimizations