Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Kernel: Implement ACPI-based shutdown (revival attempt) #25653

Open
wants to merge 7 commits into
base: master
Choose a base branch
from

Conversation

RatcheT2497
Copy link
Contributor

This is an attempt at reviving IdanHo's PR #19556 , which has gone stale.

Original description:
This includes a couple of bug-fixes, and the pretty big pre-requisite of an AML parser, but we can finally shutdown some* baremetal PCs :^)

* Those that don't require AML execution, which is not part of this PR.

Memory::map_typed maps the physical address as readable, not writable,
so we would get a kernel page fault and panic when trying to access
SystemMemory backed generic addresses. This patch switches to using a
writable mapping instead.
It is not strictly specified if SystemMemory addreses should use the
access_size or bit_width field of the generic address structure, and in
practice both are used in the wild. Support the bit width case as well.
This patch adds a minimal implementation of an AML parser - minimal in
the sense that it only supports the subset of AML encodings required to
parse QEMU's AML blob. Adding the rest of the encodings that might be
used on other systems is left as a TODO for the future.
This should allow us to parse the AML blobs that are part of the ACPI
DSDT and SSDT tables, which will let us implement proper ACPI shutdown
on bare-metal systems.
Note that this is only a parser, not an interpreter. Executing AML
methods is another issue we will have to tackle in the future, once
we start looking into more fine-grained power management.
Now that we have a bare-bones AML parser we can use it to actually
parse the AML blobs that are contained in the ACPI DSDT and SSDT
tables. These AML blobs should contain the values we will need to
implement ACPI shutdown.
Now that we have the contents of the ACPI AML blobs parsed, all we need
to do is to write them to the right place.
Note that another step we are missing is calling the '_PTS' AML method
before actually initiating the shutdown. (This is supposed to let the
platform controller know our intent and give it time to do any
preparations it needs to before-hands)
The specification does still allow doing the shutdown without calling
it, but it's still strongly encouraged. (as some platforms might not be
fully compatible and require it to properly shutdown)
Since QEMU does not actually have a _PTS method, I've left it as a TODO
for the future.
This makes sure we actually try shutting down via ACPI if it's
available when shutdown is initiated by the user.
Now that we support ACPI/AML based shutdown, enable it by default.
@github-actions github-actions bot added the 👀 pr-needs-review PR needs review from a maintainer or community member label Jan 16, 2025
Copy link
Contributor

@Hendiadyoin1 Hendiadyoin1 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All the stuff I found quickly going over this, all nits, I guess

Comment on lines +13 to +15
for (auto i = 0u; i < indent; ++i) {
dbg(" ");
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IIRC we can use dbg("{:>{}}","",indent)
not sure if thats better

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also see the device tree printer, that uses a similar pattern (IIRC)

Comment on lines +13 to +15
// 20.3 AML Byte Stream Byte Values

static constexpr u8 AliasOp = 0x06;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NIT: I prefer enum class OpCode : u8 for this

Comment on lines +29 to +35
[[nodiscard]] u8 consume()
{
auto byte = current();
m_offset++;
return byte;
}
void skip() { m_offset++; }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To this pattern:
a memory stream would be nicer, and would make some helpers redundant
If you want to change it, feel free to do that in a separate commit to make ease the commit management

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if we should expose this whole thing as a userspace library, like the fdt stuff
That would make testing simpler, like through lagom

Comment on lines +396 to +397
SLP_TYPa = static_cast<AML::IntegerData&>(*elements[0]).value();
SLP_TYPb = static_cast<AML::IntegerData&>(*elements[1]).value();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bit_cast<...>(...) is preferable

auto s5_object = MUST(m_root_namespace->get_node({ "_S5"sv }));
if (!s5_object->is_define_package())
return false;
auto elements = static_cast<AML::DefinePackage&>(*s5_object).element_list();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same

Comment on lines +16 to +19
enum class IntegerBitness {
IntegersAre32Bit,
IntegersAre64Bit
};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do not like this name, but do not have a better one
(FDT was nice enough to always count in cells, so it was cell_size there, but it does not make sense in AML i guess)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well that's an ACPI limitation, ACPI 2.0 added support for 64-bit addresses. Before that only 16-bit and 32-bit systems were supported.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Quick Idea

enum class IntSize {
    I32, I64
};

?
(Late night phone review)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bitness is a real word or what do you not like about the name?
I think this name is fine.

Comment on lines +344 to +348
static constexpr size_t PM1_CNT_SLP_TYP_offset = 10;
static constexpr u16 PM1_CNT_SLP_EN = 1u << 13;

static constexpr size_t SLEEP_CONTROL_SLP_TYP_offset = 2;
static constexpr u8 SLEEP_CONTROL_SLP_EN = 1u << 5;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you find spec links for these?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Side note: IIRC the spec links in here might be out of date/dead

@d-tatianin
Copy link

I think this part is fundamentally flawed and should not be merged as is:

Note that this is only a parser, not an interpreter. Executing AML
methods is another issue we will have to tackle in the future, once
we start looking into more fine-grained power management.

Top level code found in DSDT/SSDT/PSDT is exactly the same as "executing AML methods", because it is a method, just one with an extra rule: named objects created inside are not destroyed upon exit. Other than that it is a method, that can use Locals, branches, Whiles, call into other methods etc.

How is this "parser" going to handle conditionally declared objects? (even QEMU AML does this for some Sx objects iirc)

If (S5EN) {
    Name (_S5, ...)
}

You cannot just parse this, same as you cannot just parse python bytecode, because you're supposed to execute it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
👀 pr-needs-review PR needs review from a maintainer or community member
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants