Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CPUID: Why must MISC_ENABLE.LCMV be set to 0 for some functions? Can I temporarily overwrite it?

I'm trying to use CPUID, but there are some strings attached. According to sandpile.org's CPUID page, CPUID standard functions 0000_0004h and up will only work if the MISC_ENABLE.LCMV flag is set to 0. This flag is bit 22 of model-specific register (MSR) 1A0. Apparently, this limitation is due to a bug in Windows NT (thanks for making things easier on me, Microsoft ;)).

I can test for the presence of the LCMV flag with CPUID 0000_0001h (ecx flags, bit 3). Assuming it is present though, what exactly is it for, and why does it have such an effect on CPUID? Is MSR 1A0 a read/write register or read-only? How is such a special-purpose register even read from/written to using assembly code?

If the register is technically read/write, is it safe to reset bit 22 to 0 for the duration of the CPUID instruction, before restoring it to its original setting? Or am I pretty much screwed if it's set incorrectly (i.e. enabled)?

Finally, sandpile uses the wording,"This level is only enabled if MISC_ENABLE.LCMV is set to 0. This is due to a Windows NT bug." If a bunch of standard levels are specifically disabled for this reason, will that be reflected in the output of CPUID level 0000_000h's eax register (maximum supported standard level)?

Phew...I think that's about it.

like image 346
Mike S Avatar asked Feb 24 '23 03:02

Mike S


1 Answers

You will want to download Intel® 64 and IA-32 Architectures Software Developer’s Manuals as it contains all the requested information.

I can test for the presence of the LCMV flag with CPUID 0000_0001h (ecx flags, bit 3). Assuming it is present though, what exactly is it for, and why does it have such an effect on CPUID?

The full name of the flag (see Vol. 3B B-17) is " Limit CPUID MaxVal" and states its effect as "When this bit is set to 1, CPUID.00H returns a maximum value in EAX[7:0] of 3".

Is MSR 1A0 a read/write register or read-only?

Read/Write according to the Intel manual (with one caveat, read on).

How is such a special-purpose register even read from/written to using assembly code?

You read using RDMSR (Vol. 2B 4-301) and write using WRMSR (Vol. 2B 4-505), but note that they require you to run in either real mode or privilege level 0 (a.k.a. kernel mode).

If the register is technically read/write, is it safe to reset bit 22 to 0 for the duration of the CPUID instruction, before restoring it to its original setting? Or am I pretty much screwed if it's set incorrectly (i.e. enabled)?

It should really only be set on buggy operating systems and there you shouldn't clear it. If you're writing your own kernel by all means go ahead and clear it as you yourself state it's only for buggy versions of NT and similar circumstances.

Finally, sandpile uses the wording,"This level is only enabled if MISC_ENABLE.LCMV is set to 0. This is due to a Windows NT bug." If a bunch of standard levels are specifically disabled for this reason, will that be reflected in the output of CPUID level 0000_000h's eax register (maximum supported standard level)?

Yes, it is specifically designed to force it to return 3 in this case (see the above description).

like image 180
user786653 Avatar answered Apr 28 '23 22:04

user786653