[Bug 46132] New: Multiple Windows 10 ARM64 apps crash with illegal instruction fault due to access of ARMv8 PMU cycle counter via 'PMCCNTR_EL0' register in EL0 (Linux kernel disallows access by default)
wine-bugs at winehq.org
wine-bugs at winehq.org
Mon Nov 12 08:40:47 CST 2018
https://bugs.winehq.org/show_bug.cgi?id=46132
Bug ID: 46132
Summary: Multiple Windows 10 ARM64 apps crash with illegal
instruction fault due to access of ARMv8 PMU cycle
counter via 'PMCCNTR_EL0' register in EL0 (Linux
kernel disallows access by default)
Product: Wine
Version: 3.20
Hardware: aarch64
OS: Linux
Status: NEW
Severity: normal
Priority: P2
Component: -unknown
Assignee: wine-bugs at winehq.org
Reporter: focht at gmx.net
Distribution: ---
Hello folks,
just for documentation ...
--- snip ---
$ WINEDEBUG=+seh,+loaddll,+process,+relay,+msvcrt wine64 ./gatherosstate.exe
>>log.txt 2>&1
...
0009:trace:msvcrt:DllMain finished process init
0009:Ret PE DLL (proc=0x7fae7e3b04,module=0x7fae730000
L"msvcrt.dll",reason=PROCESS_ATTACH,res=0x22fc48) retval=1
0009:Call PE DLL (proc=0x7fae5fd5d8,module=0x7fae580000
L"advapi32.dll",reason=PROCESS_ATTACH,res=0x22fc48)
0009:Ret PE DLL (proc=0x7fae5fd5d8,module=0x7fae580000
L"advapi32.dll",reason=PROCESS_ATTACH,res=0x22fc48) retval=1
0009:Starting process
L"Z:\\home\\focht\\Downloads\\ARM64-win10-apps\\gatherosstate.exe"
(entryproc=0x14002fd80)
0009:trace:process:NtQueryInformationProcess
(0xffffffffffffffff,0x00000007,0x22f988,0x00000008,(nil))
0009:trace:seh:call_stack_handlers calling handler at 0x7b4d6330 code=c000001d
flags=0
wine: Unhandled illegal instruction at address 0x14002fc0c (thread 0009),
starting debugger...
0009:trace:seh:start_debugger Starting debugger "winedbg --auto 8 32"
--- snip ---
strace:
--- snip ---
2752 [000000014002fc0c] --- SIGILL {si_signo=SIGILL, si_code=ILL_ILLOPC,
si_addr=0x14002fc0c} ---
--- snip ---
Disassembly around faulting instruction:
--- snip ---
start:
000000014002FD80 F3 53 BE A9 STP X19, X20, [SP,#-0x20+var_s0]!
000000014002FD84 F5 0B 00 F9 STR X21, [SP,#var_s10]
000000014002FD88 FD 7B BF A9 STP X29, X30, [SP,#var_10]!
000000014002FD8C FD 03 00 91 MOV X29, SP
000000014002FD90 13 00 80 52 MOV W19, #0
000000014002FD94 9B FF FF 97 BL sub_14002FC00
000000014002FD98 F5 03 00 2A MOV W21, W0
...
sub_14002FC00:
000000014002FC00 F3 0F 1F F8 STR X19, [SP,#-0x10+var_s0]!
000000014002FC04 FD 7B BF A9 STP X29, X30, [SP,#var_10]!
000000014002FC08 FD 03 00 91 MOV X29, SP
000000014002FC0C 08 9D 3B D5 MRS X8, #3, c9, c13, #0 ; *boom*
000000014002FC10 0A 03 00 B0 ADRP X10, #qword_140090670 at PAGE
000000014002FC14 53 C1 19 91 ADD X19, X10, #qword_140090670 at PAGEOFF
000000014002FC18 08 79 40 92 AND X8, X8, #0x7FFFFFFF
--- snip ---
Decoding the sysreg using ARM's ARMv8 Processor Technical Reference Manual:
MRS <Xt>, (<systemreg>|S<op0>_<op1>_<Cn>_<Cm>_<op2>)
08 9D 3B D5 -> D5 3B 9D 08
| D5 | 3B | 9D | 08 |
|11010101|00 1 11 011|1001 1101|000 01000|
| OPCode |L|o0|op1|CRn |CRm |op2| Rt |
op0 = 3
op1 = 3
op2 = 0
CRn = 9
CRm = 13
Rt = 8
0x08,0x9d,0x3b,0xd5 = 'MRS X8, PMCCNTR_EL0'
Microsoft docs:
https://docs.microsoft.com/en-us/cpp/build/arm64-windows-abi-conventions?view=vs-2017
--- quote ---
Cycle counter
All ARMv8 CPUs are required to support a cycle counter register. This is a
64-bit register that Windows configures
to be readable at any exception level (including user mode). It can be accessed
via the special PMCCNTR_EL0
register, using the MSR opcode in assembly code, or the _ReadStatusReg
intrinsic in C/C++ code.
Note that the cycle counter here is a true cycle counter, not a wall clock, and
thus the counting frequency
will vary with the processor frequency. If you feel you must know the frequency
of the cycle counter,
you should not be using the cycle counter. Instead, you want to measure wall
clock time, for which you
should use QueryPerformanceCounter.
--- quote ---
Defined as 'ReadTimeStampCounter()' in Windows 10 SDK header 'winnt.h'.
Current QEMU for ARM64 supports it (if not run under real hardware):
https://github.com/qemu/qemu/blob/master/target/arm/helper.c#L1410
--- snip ---
#ifndef CONFIG_USER_ONLY
...
{ .name = "PMCCNTR_EL0", .state = ARM_CP_STATE_AA64,
.opc0 = 3, .opc1 = 3, .crn = 9, .crm = 13, .opc2 = 0,
.access = PL0_RW, .accessfn = pmreg_access_ccntr,
.type = ARM_CP_IO,
.readfn = pmccntr_read, .writefn = pmccntr_write, },
#endif
--- snip ---
The relevant piece of Linux kernel code:
https://github.com/torvalds/linux/commit/60792ad349f3c6dc5735aafefe5dc9121c79e320
--- quote ---
arm64: kernel: enforce pmuserenr_el0 initialization and restore
The pmuserenr_el0 register value is architecturally UNKNOWN on reset.
Current kernel code resets that register value iff the core pmu device is
correctly probed in the kernel. On platforms with missing DT pmu nodes (or
disabled perf events in the kernel), the pmu is not probed, therefore the
pmuserenr_el0 register is not reset in the kernel, which means that its
value retains the reset value that is architecturally UNKNOWN (system
may run with eg pmuserenr_el0 == 0x1, which means that PMU counters access
is available at EL0, which must be disallowed).
This patch adds code that resets pmuserenr_el0 on cold boot and restores
it on core resume from shutdown, so that the pmuserenr_el0 setup is
always enforced in the kernel.
--- quote ---
Since the Linux kernel maintainers disallow PMU counter access in EL0 by
default, one has to patch the Linux kernel or use a helper kernel module.
Windows 10 ARM64 likely has PMU counter access in EL0 enabled by default.
There were some attempts in the past, but they never made it in.
https://patchwork.kernel.org/patch/5217341/
https://github.com/zhiyisun/enable_arm_pmu/tree/dev
Anyway, nothing to fix in Wine here. Upstream (if at all).
Regards
--
Do not reply to this email, post in Bugzilla using the
above URL to reply.
You are receiving this mail because:
You are watching all bug changes.
More information about the wine-bugs
mailing list