Closed fpelliccioni closed 1 year ago
@fpelliccioni I am not expert on this, but I expect it is set via MSR (by OS) and cpuid reads back this value, similar to OSXSAVE.
@klauspost do you have a pointer to a document that says SCE have to be taken from EDX[11] ?
Maybe I am confused but the document you mentioned says
SysEnterSysExit: SYSENTER and SYSEXIT instructions. See “SYSENTER”, “SYSEXIT“ in APM3.
... and according to the Micro-Architecture Levels "spec" the example instruction of SCE is syscall
.
syscall
is described in page 21 in the doc. you sent.
This other document also agrees:
https://docs.microsoft.com/es-es/cpp/intrinsics/cpuid-cpuidex?view=msvc-170
(look for syscall
)
Ah, ok, so you are saying a different flag needs to be checked.
@fpelliccioni Are you able to find anything to confirm if "SCE" is referring to
A) SYSCALL and SYSRET
B) SYSENTER and SYSEXIT
C) both?
ok, even more digging. This seems to imply A)
Though little to no information.
@klauspost
As per my understanding it is related to A) SYSCALL and SYSRET
. Here is what I have found:
CPUID Fn8000_0001_EDX[11]
SysCallSysRet: SYSCALL and SYSRET instructions. See “SYSCALL” and “SYSRET” in APM3.
System-Call Extension (SCE) Bit. Bit 0, read/write. Setting this bit to 1 enables the SYSCALL and SYSRET instructions. Application software can use these instructions for low-latency system calls and returns in a non-segmented (flat) address space. See Section 6.1 “Fast System Call and Return,” on page 170 for additional information.
@klauspost
So on the one hand I think this code ...
_, _, c, d := cpuid(1)
fs.setIf((d&(1<<11)) != 0, SCE)
should actually be
_, _, c, d := cpuid(0x80000001)
fs.setIf((d&(1<<11)) != 0, SCE)
On the other hand, I am confused about the behavior of the EFER register
See #115 - I replaced it by two other flags. For microarch I test with SYSCALL
.
I doubt anyone is using it, but if they are they need to review their code.
I usually check GCC x86 march flags and... it is nothing related to it:
https://gcc.gnu.org/onlinedocs/gcc-12.1.0/gcc/x86-Options.html#x86-Options
The last possibility, the syscall instruction, pretty much allows for the same functionality as the sysenter instruction. The existence of both is due to the fact that one (systenter) was introduced by Intel while the other (syscall) was introduced by AMD.
FWIW. Since AMD design AMD64, it seems like syscall
became the "winner", and why there is two.
Reference code:
https://github.com/klauspost/cpuid/blob/master/cpuid.go#L996
According to the System V Application Binary Interface - AMD64 Architecture Processor Supplement, section 3.1.1:
I understand that the presence of SCE must be checked using the MSR register
(You can generate the PDF mentioned above from https://gitlab.com/x86-psABIs/x86-64-ABI)