#OBOS (not vibecoded)
1 messages · Page 24 of 1
Nice
// 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
- 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_object_resolve_as_aml_namepath(pkg.objects[i], &pwr_resource);
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.
wdym
yes
https://pastebin.com/25PPSFPz
marker in case I need to refer back to this code
I'm deleting it tho
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
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
ye
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
no error checking at all but ok
same here btw
who needed error checking
it probably™️ exists
and I don't wanna error check for stuff like fetching integers
or packages
assert(... == UACPI_STATUS_OK)
here I already know that pkg->objects[0] is a package
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.
oh yeah the power resources can be shared
fuck acpi
maybe you could just not turn any power resources off
though ofc it would likely result in more power usage
whats the point of suspend then 
const char prn_path[] = { '_', 'P', 'R', '0' + state };
uacpi_namespace_node* prn = uacpi_namespace_node_find(dev, prn_path);```
fnuy variable names
(hint: o)
I wouldn't think that the devices use that much power even if the power source is powered if they are in a sleep state
would likely be what you get if you use the pcie mechanism to put the device to a sleep state too
damn you eat a lot
no I went to do other stuff after eating
you ate already?
with proper power resource shit
how would I even know
if a power resource is shared
make a struct and link every device using the power resource?
and how do I find every device using the power resource
yeah
how do you know which ones to turn off tho, do you look at all device's power resources for D0 and then turn off the ones that the wake devices don't use?
you can turn off all of them
that i have no idea
then reenable the ones wake use
that sounds kinda sketchy, what if there are devices not in sleep state using them and then you just cut power to them 
refcount it
well idk if it really matters, maybe it doesn't
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
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
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
do u restore bars now
when you have implemented the bar restore then let me know if it actually properly worked 
kk
congrats on 34 stars
ty
np !!!
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.
fair
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
i see
I am the first hobby kernel with suspend
!!
fr
frfr
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
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
e.g., I change a BAR resource
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
also the command register
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
lol
i doubt this tbh, might be outdated information
Got some logs on real hw
It still doesn't wake my kernel though
trace isn't enough logging
time to use DEBUG
Right after this it appears to have suspended
But smashing the keyboard to wake me does nothing
ohh
Clicking the power button makes it reboot
lol
Debug is too much logs
So I'm gonna make it only do debug logs
When evaluating PSW
inb4 it never evaluated PSW
u do do setup_for_wake and stuff right?
Yup
Pastebin.com is the number one paste tool since 2002. Pastebin is a website where you can store text online for a set period of time.
if you were wondering how I actually setup a device for wake the code's in here
OBOS_DeviceMakeWakeCapable
at line 166
yes
if it exists
I think you may have misunderstood my code
maybe
the first element is a reference to the GPE device
and the 2nd element is the gpe index
did u try printf'ing what it finds?
nope
should probably
added some more logs
Other than the fact that the gpe index is 0xd each time.e
It looks fine
PSW is evaluated
thats probably fine
just shared gpe
what does psw say
Well it is only enabling USB controller sleep capability
according to the acpi spec it should be right...
yea..
well the deepest sleep state supported in S3
is D2
so apparently the D state I should enter is D2
interesting
one behaviour that might be wrong
is not enabling a device for wake
if _S3D and _S3W don't exist
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]);
double reference I assume
did u assume that initially created objects have a refcount of 0?
yup
lol
I'll just fix that rn
maybe, id lean heavily for linux code or like bsd code
to see what it does
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
lol
when tryna reboot into obos
Weirdly when I unplug a usb
Then replug it in
It seems to initialize
strange that its rebooting on power button press
Yeah
wdym
Like it has a light
That flashes
When it's plugged in
To a computer
Which means that the ehci controller is alive
ah and no wake?
interesting
Hold on
When it's shutdown
The USB still flashes
So it might be that ehci really is dead?
maybe its just continuous power delivery
Maybe
The EHCI controller has no power resources
Both controllers
And the XHCI controller
damn
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
copy pasta
what if instead of evaluating _SnD and _SnW
I use the things in the uacpi namespace node info
whats the diff
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
nah
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
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
Elixir Cross Referencer - source file of Linux (version v6.11.5). Browsed file: /drivers/acpi/scan.c
nvm
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
huh
ok I think I was looking in the wrong place
Elixir Cross Referencer - source file of Linux (version v6.11.5). Browsed file: /drivers/acpi/power.c
unrelated, but i like how they just create objects on the stack as method arguments
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
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
lol
I still get infinite GPEs
But it doesn't hang the system anymore
Nvm
It hangs after a bit
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
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
a gpe spam can happen if it expects the system to do something in response and u dont do it
bruh
but like
I suspect it might be a bug in my IOAPIC code
since it's TriggerModeLevelSensitive
and active low
iirc
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?
yes
if u add a printf to uacpi we can see which aml handler it runs
and what that handler does
okie
async_run_gpe_handler
inb4 it never gets to uacpi
wouldnt be surprised
Ummm
It infinitely prints that it's in the bootstrap irq handler
But never prints any thing in uACPI
Gtg for a bit
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
@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```
its an internal function
maybe one of the regs in detect_gpes has a non-zero status
maybe I'm not even supposed to be getting an SCI in the first place
yeah its a possibility
I found the interrupt source override for the SCI
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
maybe its a bogus override or maybe ur not handling it correctly
what is it
bool res = false;
if (polarity == 0b1 || polarity == 0)
res = true;
else if (polarity == 0b11)
res = false;```
// polarity (0: active-high, 1: active-low)```
F
I fixed that
time to see if it fixes anything
It fixed the gpe bug
But not the wake bug
well thats one bug out of the way
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
from keyboard?
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
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
wait what did u change
If I knew I'd tell you
Maybe it always worked but triple faulted each time
As now I know it triples
It triple faults changing the code segment
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
how did u even asert it
meh probably some skill issue
Otherwise continue
ok it might not be the case
as I had my infinite loop right after the place where it triple faults
mov eax, cr0
test eax, 0x1
jz .down
jmp 0xf000:0xfff0
.down:```
Thank God it wasn't the case
Otherwise I would be sending an angry email to acer
it is possible that you indeed boot in protected mode tho
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
well it works in qemu right?
yea
interesting
if it didn't then why would I be debugging it on real hw
mental insanity
just make obos 16 bit so u dont have to switch
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
Possible spam detected for user: oberrow. Please contact a moderator to be unmuted.
maybe the gdt is too high in memory
u do respect real mode addressing and stuff right?
I'm in 16-bit long mode
maybe real hw puts u into non zero cs
I'll make sure it is then
reload cs to zero first thing yeah
Infy you genius
wtf
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
is it in c code at least
only god knows
78% chance that it is
anyway
time to push this code
then I will commence work on the new pci interface
did u figure it out
nope
it could be anything
and I don't
have the willpower to debug that
without printf
reinit fb bars
I doubt it's that easy tbh
wdym?
as in you'd just get the framebuffer back after restoring the bars without doing anything else
if u run _WAK and stuff u should
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
also might be because MTRRs also get reset
forgot those existed
that could be, though idk if qemu cares about that
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)
only 1k additions 
nothing too big
but cant u just add printfs or enable traces and see why they wont get enabled?
the bars?
-d trace:pci*
yeah
time to make the new pci interface
nice, u should really make a wiki article after
marker
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
yeah I will be doing that
ecam addres gets reset probably
how do you restore that lol
I just want to make sure that my suspend properly works on real hw (and doesn't hang somewhere arbitrary) before writing the article
its a register in the chipset i think
bruh
bruh
but idk if thats the way to do it
anyway I'll be back in a bit
found it
Elixir Cross Referencer - source file of Qemu (version v9.1.1). Browsed file: /hw/pci-host/q35.c
Elixir Cross Referencer - source file of Qemu (version v9.1.1). Browsed file: /include/hw/pci-host/q35.h
in the MCH_HOST_BRIDGE_PCIEXBAR register
so basically u have to reinitialize the chipset yourself
its one write
that's kinda weird, there are like billion different chipsets
I would expect that to be handled by _WAK
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
* 100000 different chipsets
maybe on real hw its handled via _WAK idk
it looks like linux only does it to a few host bridges so that might be the case
did u find the q35 init code in linux?
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
Now I'm just confused
type lspci
We need to reinitialize the chipset
your pci device 0 is the chipset
oh
or actually nvm I didn't it just reads the base from that kind of register
supposedly its this
that's what I found yeah
but that doesnt have q35
I guess I can at least try if doing that to see if it changes anything regardless
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
linux is just magic
it does some black magic to wake up from suspend
properly
it's the only way
it looks like seabios should restore it tho https://github.com/coreboot/seabios/blob/master/src/fw/pciinit.c#L399
ohh interesting
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
is this resume code even called?
this is just the reset value btw, its just 0xB00000...
so seabios did not in fact restore it
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
yes
oh i think its a bug in SeaBIOS
with ovmf it just works without doing anything
nvm no doesnt look like a bug
Following the i440fx example, save the LPC, SMBUS and PCIEXBAR bdfs
between OS sleeps and use them to re-configure the
corresponding registers.
Tested-by: Gal Hammer <[email protected]&...
this was added a very long time ago too
so do I need to restore it myself
or does seabios do it for me
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
I can try
just tell me where
@white mulch SeaBios does indeed call mch_mmconfig_setup
hmm
PCIe: using q35 mmconfig at 0xb0000000```
and I also added a log before calling it
and it did indeed call that
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
well see if it gets there when restoring from suspend
it does
maybe qwinci's seabios is just some bugged old version
mmconfig=0xb0000000
send qwinci your seabios
that probably explains it lol
what is this
idk ask qwinci
I dprintf'ed it
and that was after suspend?
show the goddamn diff
after wake from suspend, yes
show git diff
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)
{```
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);
}
}
ohh so it is a bug?
@flint idol add printf to see which path it takes here
sure
it used the first path
theoretically the fix should just to reset mmconfig?
fr
or rather
on wake from suspend
since the bios doesn't really know that we're suspending
doesnt matter
only the aml code
wdym it doesnt know
at the beginning of pci_reset
I will set mmconfig to zero
send qwinci the bios image
and see if it works for him
u should probably reset it here
mkay
doesn't seem to fix the issue unfortunately
what else could it be 
if you want seabios logs
add this
-chardev file,path=/dev/stdout,id=seabios -device isa-debugcon,iobase=0x402,chardev=seabios```
looks like the write to mmconfig doesn't persist for some reason
how?
idk
but printing it inside writel reveals that its non-zero again at the point where it writes the base
doing that somehow fixed my shutdown probably on seabios
ur qemu is haunted
printing what
mmconfig
like oberrow reset it incorrectly or something?
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
does it work properly for you?
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
can you add this to qemu?
it prints ```
using mmconfig
using mmconfig
using mmconfig
mmconfig=0xb0000000
using mmconfig
using mmconfig
using mmconfig
PCIe: using q35 mmconfig at 0xb0000000
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
still same thing 
wut
I added a log
before it resets mmconfig
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
yeah idk anymore
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
maybe print it right after reset?
and qemu version is 9.1.0
nope
make_bios_readonly is called
right before jumping to the wake vector
in FACS
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"
can you try that image tho
oberrow do u have SMM disabled?
nope
what image?
qwinci also doesnt have kvm
anyways looks like oberrows qemu doesnt enforce readonly bios
each time I use tcg I'm reminded of why I don't use tcg
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
wth
lmao
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
maybe doing the make_bios_writable() like infy suggested before writing would fix it?
well it does say mmconfig is zero
what if the compiler optimized the load out or smth
^
or maybe cpu cache
its not a volatile variable
yup
I fucking hate tcg
it did this
@white mulch try this
that works
yes
yeah would be nice
who's gonna do it?
scary
ive submitted a few fixes
it was at least 2
which also happened to be a PCI fix
idk
anything I'm missing
?
@real pecan
I think I explained what I did well enough
also when uLife
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?
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
I apparently need to send an email to [email protected]
to post on it
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
no
git format-patch -1
git send-email 0001-<patch-name>.patch --to <[email protected]> --cc whatever
i dont remmeber what the seabios mailing list wants
usually there are maintainers u cc
git: 'send-email' is not a git command. See 'git --help'.
apt install git-send-email
it refreshes every x minutes
okie
@real pecan it seems like someone already submitted a patch for that
two years ago
hold on
that's the full thread
well looks like it was abandoned so
now I guess the only kinda important remaining problem is getting the framebuffer to work
have you reset the BARs
could also be some kind of skill issue on my part, would be nice to see what you get yeah
what does info pci say
could also be mtrr skill issue like i mentioned
looks like the bars are still shown as F's in there, yeah ig I can try to save/restore the mtrrs
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
okay
u can just save whatever bsp has initialy
didn't change anything regarding info pci or the fb
info pci also shows the same thing when not using ecam
wdym by not using ecam
as in writing the bars using port io (or using the default qemu machine)
not using ecam works, or the other way around?
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
do u write like the type info and stuff?
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
i dont think u should
MTRRs are dumb
looks like it added the mappings after I enabled the mem + io spaces in the pci command
still no fb tho 💀
ohhh
try writing 1 to the enable bit of bochsfb?
oh yeah maybe that stuff works now
Elixir Cross Referencer - source file of Linux (version v6.11.6). Browsed file: /drivers/gpu/drm/tiny/bochs.c
looks like here it just calls into standard DRM resume
but it probably results in just calling this https://elixir.bootlin.com/linux/v6.11.6/source/drivers/gpu/drm/tiny/bochs.c#L320
Elixir Cross Referencer - source file of Linux (version v6.11.6). Browsed file: /drivers/gpu/drm/tiny/bochs.c
I now restore MTRRs
while initializing APs
and on S3 wakeup
branch is starting to get a bit too big
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
by the end of that that would be like another 1k changes
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?)
I figured out the fb problem (kinda), it looks like qemu doesn't refresh the window for some reason 
when you resize the window a little then it refreshes
Current roadmap:
Design new PCI interfaceMake sure suspend works properlyImplement futexesImplement sync primitive syscalls (Not needed, so nevermind)Implement VFS syscallsImplement partition syscalls (like partition probing n'stuff)Implement driver interface syscalls- Implement TTYs
- mlibc
lol
it probably would if u re-enable bochs properly
I did that
did u reconfigure the resolution regs?
yes
like same sequence as linux?
I saved everything on suspend and then restored them
disable, set res, enable
basically yeah though the regs between disable + enable are in a different order
it shouldn't matter tho
hm
obos has 31 syscalls rn
ig I can try the exact same order to make sure
do u do blank/unblank stuff too?
and by the end of that
I should be using all the handle types obos has
handle types?
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
whats is the purpose of this
verification stuff
hm
like
// vmm syscall
if (handle_type(vmm_ctx) != HANDLE_TYPE_VMM_CONTEXT)
return OBOS_STATUS_INVALID_ARGUMENT```
like if it gets corrupted or something?
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
thr can never be nullptr
that was it, I had to add the blank at the start before doing the bochs stuff and then unblank after
oh i thought it was a syscall
if the user passed an invalid handle
nice
it would return OBOS_STATUS_INVALID_ARGUMENT
or NOT_FOUND
idr
it's OBOS_STATUS_INVALID_ARGUMENT
obos hit 36k loc recently
nice
over 10k more than astral
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)
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
I had that happen
or never touch mailing lists again
my logo omg!!!
they are a pain in the neck
no one is using PINE to handle their (ascii, 80-char-wide) emails anymore so getting the right thing done is harder
@white mulch so did writing to the BARs end up working with the patched seabios?
yes
after enabling memory and io access he was able to get the fb to work
well and re-initializing the bochs fb
oh ok
I'm going to do something and respond to the reply I got on the seabios mailing list
yeah i saw it
