2
votes

I am developing an x86 bootloader and have come across this problem (which I guess should be pretty straightforward, but so far I haven't been able to solve): I want to detect the bitness of the CPU host (e.g. if it's 16bit-only, or supports 32bit or 64bit).

I have used the CPUID instruction, but it was introduced with 486 so doesn't help for detecting 16-bit-only vs. a 386-compatible CPU that supports 32-bit protected mode (or 32-bit operand-size in real mode with prefixes).

1
Just out of curiosity - what will you be booting, that supports all of 16, 32 and 64-bit processors?xs0
@davmac: A BIOS booting in legacy non-EFI mode loads the boot-sector and jumps to it in 16-bit real mode. It's up to that code to switch to protected or long mode (after loading more sectors or whatever). If you want to print a nice error message on (virtual) machines that don't support 32 or 64 bit modes, you need to check first. e.g. with wiki.osdev.org/…Peter Cordes
I recall this question being asked quite often. This has to be a duplicate. You can find out if your CPU is a 386 or better by checking some bits in FLAGS.fuz
@AntónSeoane: Detecting support for 64-bit mode is shown in detail on the OSdev wiki. wiki.osdev.org/…. The Protected Mode article (wiki.osdev.org/Protected_Mode) doesn't have a detection method shown. It has links to more stuff. I'm not going to post an answer; I'll leave that for one of the people that like to play with custom kernels.Peter Cordes
This page has code to detect pre CPUID CPUs. If you have the CPUID instruction, you can use it to detect 64-bit mode (32-bit is implied).Margaret Bloom

1 Answers

1
votes

Checking for 32-bits (see http://www.rcollins.org/ddj/Sep96/Sep96.html):

  • 16-bit CPUs without protected mode (8088/8086/80186) will always have the upper 4 bits (15-12) of the flags register set when doing pushf
  • 80286 will always have the upper 4 bits clear on pushf (when running in real mode)
  • CPUs supporting 32-bit allow modifying the upper 4 bits in real mode using popf (however all 4 bits should have the same value - all set or all clear)

By using pushf, popf and modifying the data on the stack you check if it is possible to modify the upper 4 bits; if yes, it must be a 32-bit CPU.

Checking for CPUID:

  • Ensure the CPU supports 32-bit (see above)
  • Switch to 32-bits mode
  • Check if bit 21 of EFLAGS can be modified (set and cleared); if the value of that bit is not fixed (it can be changed from 0 to 1 or vice versa) the cpuid instruction is supported.