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

Instructions missing in Zydis: 64-bit RDSSPD, VMGEXIT, AltMovCr8 #183

Open
tremalrik opened this issue Apr 27, 2021 · 3 comments
Open

Instructions missing in Zydis: 64-bit RDSSPD, VMGEXIT, AltMovCr8 #183

tremalrik opened this issue Apr 27, 2021 · 3 comments
Assignees
Labels
A-decoder Area: Decoder C-enhancement Category: Enhancement of existing features P-medium Priority: Medium

Comments

@tremalrik
Copy link

Doing a bunch of tests with Zydis, I've identified instructions that it doesn't decode properly:

  • RDSSPD in 64-bit mode. "ZydisInfo -64 f3 0f 1e c8" returns "nop eax,ecx" and not the expected "rdsspd eax". This is surprising, since the closely related instruction RDSSPQ works fine ("ZydisInfo -64 f3 48 0f 1e c8" returns the expected "rdsspq rax")
  • VMGEXIT (AMD system instruction). "ZydisInfo -64 f3 0f 01 d9" returns "vmmcall" rather than the expected "vmgexit". Given that older AMD processors will, according to the AMD APM, treat the instruction as vmmcall, it might be a suitable candidate for a ZydisDecoderMode flag, similar to how wbinvd/wbnoinvd is handled.
  • On AMD processors with the "AltMovCr8" feature, it is possible to prefix a MOV to/from CR0 with a LOCK prefix; this will modify the instruction into a MOV to/from CR8. As such, e.g. F0 0F 20 00 should probably be decoded as "mov eax,cr8"/"mov rax,cr8" rather than the ILLEGAL_LOCK error that Zydis is currently returning.
@flobernd flobernd self-assigned this Apr 28, 2021
@flobernd flobernd added A-decoder Area: Decoder C-enhancement Category: Enhancement of existing features P-medium Priority: Medium labels Apr 28, 2021
@flobernd
Copy link
Member

flobernd commented Apr 28, 2021

RDSSPD

Fixed with 25193db

In the 64-bit mode branch the definition for REX.w == 0 was missing.

VMGEXIT

Will add a decoder mode for this one :-)

AltMovCr8

Oh, this one I was not aware of. I will leave this issue open and follow your suggestion to add a new decoder-mode. It requires some further adjustments to the code that validates the LOCK prefix and the register constraints as well as a new filter, so might take a while.

@tremalrik
Copy link
Author

For AltMovCr8, I decided to do a few tests on an AMD EPYC instance. Given how this feature works - using the LOCK prefix to get access to a register that one would normally use the 64-bit-only REX.R bit to access - it seemed to me natural to ask whether the processor just treated LOCK as an alias for REX.R for the MOV CRx opcodes. This doesn't turn out to be the case - placing both LOCK and REX.R on a MOV CRx opcode results in an #UD on the EPYC. A few tests and their results (from user-mode, where valid variants produce #GP and invalid variants produce #UD):

  • mov rax, cr0 : #GP
  • mov rax, cr1 : #UD
  • mov rax, cr2 : #GP
  • mov rax, cr8 : #GP
  • mov r8, cr8 : #GP : no surprises so far
  • lock mov rax, cr0 : #GP : AltMovCr8 shows up
  • lock mov r8, cr0 : #GP : For AltMovCr8, LOCK + a REX prefix without REX.R is valid
  • lock mov rax, cr2 : #UD : (LOCK is not simply ignored for these opcodes)
  • lock mov rax, cr8 : #UD : For AltMovCr8, LOCK + REX.R is not valid
  • lock mov rax, cr10 : #UD

@jfhs
Copy link

jfhs commented Feb 5, 2022

I have been testing this on baremetal Ryzen 9 5900HS, and can confirm @tremalrik's data: #UD's as described and no exceptions where he had #GP (since it was running in ring 0).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-decoder Area: Decoder C-enhancement Category: Enhancement of existing features P-medium Priority: Medium
Projects
None yet
Development

No branches or pull requests

3 participants