32 bit OS support on x86-64 architecture
32 bit OS support on x86-64 architecture
Hi,
reading x86-64 processor specs I've learned about supported modes: Long mode and Legacy mode
Now I suppose pure 32 bit OS (e.g. Linux/Windows 32 bit) use Legacy mode (i.e. starting from real mode and then switching to protected mode)
How can I check this from a processor point of view when 32 bit OS is running ?
Thanks.
reading x86-64 processor specs I've learned about supported modes: Long mode and Legacy mode
Now I suppose pure 32 bit OS (e.g. Linux/Windows 32 bit) use Legacy mode (i.e. starting from real mode and then switching to protected mode)
How can I check this from a processor point of view when 32 bit OS is running ?
Thanks.
Re: 32 bit OS support on x86-64 architecture
Checking CPUID for long mode support, then read the related MSR for LME(long mode enabled)
Re: 32 bit OS support on x86-64 architecture
Section 2.2 of Volume 3 of the Intel manual describes the different operating modes, how they are entered, and how you can use various registers to determine the current operating mode of the processor.
Re: 32 bit OS support on x86-64 architecture
A call to CPUID returns longmode-capable-bit turned on in the EDX extended feature flags (bit 29) (http://wiki.osdev.org/X86-64):bluemoon wrote:Checking CPUID for long mode support, then read the related MSR for LME(long mode enabled)
Code: Select all
0:000> r edx
edx=28100000
0:000> .formats 28100000
Evaluate expression:
Hex: 28100000
Decimal: 672137216
Octal: 05004000000
Binary: 00101000 00010000 00000000 00000000 <-------------
now trying to assemble & execute
Code: Select all
mov $0xC0000080, %ecx
rdmsr
Can you confirm that ?
Re: 32 bit OS support on x86-64 architecture
Yes, according the the manual:cianfa72 wrote: I get an error...it seems the last instruction (rdmsr) has to be executed only at ring 0 privilege...Can you confirm that ?
#GP(0)
- If the current privilege level is not 0.
- If the value in ECX specifies a reserved or unimplemented MSR address.
No, not necessary strictly "run in kernel" if I understand what you meant correctly, most general purpose OS provide some sort of mechanism to gain ring0 access (drivers, kernel extensions, special administrative APIs, etc).cianfa72 wrote:in other words the only way is run the code in kernel mode
Last edited by bluemoon on Mon Jan 21, 2013 8:13 am, edited 1 time in total.
Re: 32 bit OS support on x86-64 architecture
Yes, RDMSR works only in kernel mode. On Windows, you can determine if you're running in long mode by calling GetNativeSystemInfo. If this function exists, and wProcessorArchitecture equals 9, then yes, otherwise no. On Linux I have no idea except perhaps calling the uname function and searching for "x64" in the returned string.
Re: 32 bit OS support on x86-64 architecture
Perhaps it could be tested by executing some normal instruction that behaves differently? Long mode is easy (e.g. push/pop) but what about Legacy Mode... Is it possible? Maybe not...
Re: 32 bit OS support on x86-64 architecture
I think you've got your terms mixed up, because that sentence doesn't make sense.
Re: 32 bit OS support on x86-64 architecture
Hi,
For 16-bit and 32-bit code; to determine if you're running in protected mode or long mode there's no difference in the behaviour of different instructions (that I know of). However, I can't imagine an OS that doesn't use a 256-entry IDT, and IDT entries are larger in long mode (16 bytes instead of 8 bytes). This means that an application could do "SIDT" (which is allowed at CPL=3) and check the OS's IDT limit (e.g. "if(IDT_limit < 2048) { assume protected mode } else { assume long mode }"). Even though this isn't guaranteed to be foolproof, it's extremely likely that it'd work correctly on all OSs.
For real mode code, to determine if you're running in real mode or virtual8086 mode you can "pushf" and examine the VM flag.
Cheers,
Brendan
For 64-bit code it's a compile-time problem rather than a run-time problem (if your 64-bit code is executing then you're in long mode).Antti wrote:Perhaps it could be tested by executing some normal instruction that behaves differently? Long mode is easy (e.g. push/pop) but what about Legacy Mode... Is it possible? Maybe not...
For 16-bit and 32-bit code; to determine if you're running in protected mode or long mode there's no difference in the behaviour of different instructions (that I know of). However, I can't imagine an OS that doesn't use a 256-entry IDT, and IDT entries are larger in long mode (16 bytes instead of 8 bytes). This means that an application could do "SIDT" (which is allowed at CPL=3) and check the OS's IDT limit (e.g. "if(IDT_limit < 2048) { assume protected mode } else { assume long mode }"). Even though this isn't guaranteed to be foolproof, it's extremely likely that it'd work correctly on all OSs.
For real mode code, to determine if you're running in real mode or virtual8086 mode you can "pushf" and examine the VM flag.
Cheers,
Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
Re: 32 bit OS support on x86-64 architecture
Yes, my post did not help to solve the original problem. What I meant was something like this (ring-3 code):Gigasoft wrote:I think you've got your terms mixed up, because that sentence doesn't make sense.
Code: Select all
Carefully written x86 and x86-64 compatible code
Check (r/e)sp value and store it
Do push
Check (r/e)sp value and and compare
If difference is 4 jump to ProtectedModeCode:
If difference is 8 jump to LongModeCode:
ProtectedModeCode:
do something
LongModeCode:
do something
Re: 32 bit OS support on x86-64 architecture
If you want to detect the current bit mode, you can do the following:
Code: Select all
foo:
db 0x48
db 0xB8
dd 0xdeadbeef
db 0xEB
db 123
dw 0
This, when operate in 32-bit mode refer to:
0: 48 dec %eax
1: b8 ef be ad de mov $0xdeadbeef,%eax
6: eb 7b jmp 83 <foo+0x83>
8: 00 00 add %al,(%eax)
However, when operate in 64-bit mode it become:
0: 48 b8 ef be ad de eb movabs $0x7bebdeadbeef,%rax
7: 7b 00 00
*Note that you need to change the jump offset for practical uses.
Re: 32 bit OS support on x86-64 architecture
I think Brendans idea might work, but it cannot determine if long mode applications can execute, or the bitness of the kernel. All it does is to detect the current mode. For example in RDOS, it will always indicate "protected mode", because 32-bit applications always run in protected mode (at least until a processor without protected mode support exist).
Re: 32 bit OS support on x86-64 architecture
As far as I understand, when most modern 64 bit operating systems are running on a 64 bit processor then the actual CPU mode used depends on the bitness of the executable file: for ELF64/PE64 long mode is used, else compatibility mode is used. This generally means you can't have one binary which works in both 32 or 64 bit mode depending on the bitness of the underlying OS, but instead need to compile the executable separately for both. In this sense, testing for long mode vs compatibility mode in code may be as simple as doing something like #ifdef _LP64 (for gcc). Obviously protected mode instead of compatibility mode would be used when a 32 bit OS is used.
Regards,
John.
Regards,
John.
Re: 32 bit OS support on x86-64 architecture
AFAIK the "main" CPU mode for a modern 64 bit OS running on a 64 bit processor is "long mode". This CPU mode supports 2 sub-modes: 64 bit mode and compatibility mode.
Here do you refer actually to the two possible long mode "sub-modes" ?jnc100 wrote:As far as I understand, when most modern 64 bit operating systems are running on a 64 bit processor then the actual CPU mode used depends on the bitness of the executable file: for ELF64/PE64 long mode is used, else compatibility mode is used.
Re: 32 bit OS support on x86-64 architecture
Actually, from the point of view of the processor, the switch to long mode basically does nothing. It switches from protected mode to compability mode, but the instructions are executed the same way. The actual switch to 64-bit mode is done by a far control transfer to a 64-bit code segment. The main difference between the protected mode and long mode environment is in interrupt and exception handlers, and the content (and size) of IDT.cianfa72 wrote:AFAIK the "main" CPU mode for a modern 64 bit OS running on a 64 bit processor is "long mode". This CPU mode supports 2 sub-modes: 64 bit mode and compatibility mode.
It's also easy and relatively quick to switch between compability-mode and protected mode. The main time in this transition is the TLB flush.