LDLS: every MDIO read was RFLAGS; ACPI: an Embedded Controller
On the TUF A15 Linux's r8169 found its PHY and read its ID as 0x02460246. mdio-bus keeps the register it has just read in r11 across preempt_enable(), which on x86 is `decl %gs:__preempt_count; je` to a call that preserves every register. LDLS gave __preempt_count zeroes, so the count reached zero and the call was made -- to a logging stub, whose syscall left RFLAGS (0x246) in r11. __preempt_count now starts at PREEMPT_ENABLED (x86 keeps NEED_RESCHED inverted), and preempt_schedule and its notrace twin are a bare ret. The same laptop reported its battery full and on AC, unplugged. The EC owns both, and with no EmbeddedControl handler _REG never told the firmware the EC was usable, so _BST and _PSR answered their fallbacks. The EC is found by PNP0C09 or the ECDT and served by the ACPI 12.3 byte protocol, installed before _INI. SCI queries are not handled yet. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01S1giNvrHTrPMPw7V6x1kQ4
This commit is contained in:
parent
3676036762
commit
d437e42b49
3 changed files with 179 additions and 1 deletions
|
|
@ -264,7 +264,7 @@ resolve(void *ctx, const char *name, unsigned long long *out)
|
|||
// bargain as the logging stubs, and the same caveat -- see the memcpy note in
|
||||
// docs/architecture/ldls.md.
|
||||
|
||||
#define PERCPU_SLOTS 8
|
||||
#define PERCPU_SLOTS 16
|
||||
#define PERCPU_SIZE (16 * 1024)
|
||||
|
||||
static char percpu_mem[PERCPU_SLOTS][PERCPU_SIZE];
|
||||
|
|
@ -294,6 +294,14 @@ percpu_for(void *ctx, const char *name)
|
|||
*(unsigned long long *)percpu_mem[i] =
|
||||
(unsigned long long)(void *)(percpu_mem[i] + 64);
|
||||
puts_(" per-CPU "); puts_(name); puts_(" -- a task of zeroes\n");
|
||||
} else if (streq(name, "__preempt_count")) {
|
||||
// x86 keeps PREEMPT_NEED_RESCHED inverted in this word, so that
|
||||
// `decl %gs:__preempt_count; je resched` is one instruction. Zero
|
||||
// means "count zero *and* a reschedule wanted", and every
|
||||
// preempt_enable() then called preempt_schedule -- see the note on
|
||||
// __SCT__preempt_schedule in ldls/kpi/base.c for what that cost.
|
||||
*(unsigned int *)percpu_mem[i] = 0x80000000u;
|
||||
puts_(" per-CPU "); puts_(name); puts_(" -- PREEMPT_ENABLED\n");
|
||||
} else {
|
||||
puts_(" per-CPU "); puts_(name); puts_(" -- 16K of zeroes\n");
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue