Page 1 of 1

Detecting under Bochs Emulation

Posted: Fri Jul 01, 2005 1:28 pm
by smiddy
Hi All,

I am looking for a way to determine if my OS is running under Bochs or not. Can someone point me in the right direction for determing if Bochs is running or not?

Re:Detecting under Bochs Emulation

Posted: Fri Jul 01, 2005 2:50 pm
by Kemp
Under perfect emulation there should be no way to tell at all. Of course, Bochs is nowhere near perfect and nor is any other emulation program. You could try reading from the floppy drive, if it succeeds in one try then it could possibly be an emulator, if it takes more than one try then chances are it's a real system. Dunno other than that, I'm sure guys with more experience know of a lot of differences to the real thing.

Re:Detecting under Bochs Emulation

Posted: Fri Jul 01, 2005 3:32 pm
by oswizard
Depending on how Bochs is compiled:

Code: Select all

if (inb(0xE9) == 0xE9)
   bochs = true;
Anything you write to port 0xE9 will be displayed on the console, if ENABLE_PORT_E9_HACK or similar is defined in the configure script.

Re:Detecting under Bochs Emulation

Posted: Fri Jul 01, 2005 4:21 pm
by smiddy
@Kemp,

I agree, in a perfect world, we'd have perfect emulation, but alas we do not.

@Mike,

Thanks! I needed the clarification that you gave. I read that portion of the code for Bochs but wasn't too sure what the heck they were saying about port 0E9h. Anyhow, this works:

Code: Select all

BochsDetectedMessage    db 'Bochs detected',13,10,0
BochsNotDetectedMessage db 'Bochs not detected',13,10,0
BochsOn                 dd 0

DetectBochs:

    mov dx,0E9h
    in al,dx
    
    cmp al,0E9h
    je .InBochs
    mov eax,0
    mov esi,BochsNotDetectedMessage
    jmp .Done
    
.InBochs:

    mov eax,1
    mov esi,BochsDetectedMessage
    
.Done:

    mov [BochsOn],eax
    call PrintString
    
    ret
Here's the screen dump:

Code: Select all


smiddy's OS (C) 2004, 2005. All Rights Reserved.
Version 1.00.00.000000AF
CPU: CPUID Instruction: GenuineIntel Pentium III (Coppermine)
A20 Gate: Init KBC: 1st Test: A20 memory address line enabled...
E820: 1,073,741,824 bytes.
E801: 1,073,741,824 bytes.
88xx: 16,777,216 bytes.
CMOS: 67,108,864 bytes.
Entering UnReal Mode...
Probe: 1,073,741,824 bytes.
Mapping Memory 1: 1,073,741,824 installed: E820:
Mapping Memory 2: Bitmap Initialized at 14MB: 1,056,964,608 bytes free for use.
Looking for VENDORS.TXT in root...Found! Loading VENDORS.TXT 198,196 bytes.
ERROR: No Plug and Play BIOS
BIOS32 Entry Found at: 000F9D90h Revision: 0
PCI32 BIOS Found at: 000F9DD0h
PCIIRQ Table found: 000FA030h  Slots: 6 Bus: 0 Device: 1 Function: 0
PCI IRQ Slot: 0 Bus: 0 Device: 1 INT A#: 60h
PCI IRQ Slot: 1 Bus: 0 Device: 2 INT A#: 61h
PCI IRQ Slot: 2 Bus: 0 Device: 3 INT A#: 62h
PCI IRQ Slot: 3 Bus: 0 Device: 4 INT A#: 63h
PCI IRQ Slot: 4 Bus: 0 Device: 5 INT A#: 60h
PCI IRQ Slot: 5 Bus: 0 Device: 6 INT A#: 61h
About to cook VENDORS.TXT file for use in enumeration.
The first pass completed:
This file was created on: Sat Jun 25 13:04:43 PDT 2005
Creating database of 891,224 bytes: VendorID, DeviceID, VendorString, DeviceString.
Reducing required information size to items only currently installed.
8086 1237 Intel Corporation - 82440LX/EX PCI & Memory
8086 7000 Intel Corporation - 82371SB PIIX3 PCI-to-ISA Bridge (Triton II)
8086 7010 Intel Corporation - 82371SB PIIX3 IDE Interface (Triton II)
smiddyOS Clock Initializing...Done!
smiddyOS Keyboard Initializing...Done!
Bochs detected
Virtual PC Not Detected
VM Ware Not Detected
Start     End       Size (bytes)  Type Owner/Description
--------- --------- ------------- ---  -----------------
00000000h 000003FFh         1,024 02h  Interrupt Vector Table (IVT)
00000400h 000004FFh           256 02h  BIOS Data Area (BDA)
00000500h 000005FFh           256 02h  smiddyOS Data Area (OSDA)
00000600h 0009FBFFh       652,800 02h  smiddyOS code
0009FC00h 0009FFFFh         1,024 02h  Extended BIOS Data Area (EBDA)
000A0000h 000BFFFFh       131,072 02h  VGA Buffer Area
000C0000h 000FFFFFh       262,144 02h  ROM/BIOS Area
00100000h 00FFFFFFh    15,728,640 02h  smiddyOS code
01000000h 010000BFh           192 02h  PCI Vendors and Devices Information (Reduced)
010000C0h 010307FFh       198,464 01h  <Free Useable Memory>
01030800h 0110A157h       891,224 02h  PCI Vendors and Devices Information (Cooking)
0110A158h 0120A157h     1,048,576 02h  Text Windowing Heap
0120A158h 3FFFFFFFh 1,054,826,152 01h  <Free Useable Memory>
40000000h FFFFFFFFh 3,221,225,472 02h  Unuseable addressable memory area
Press any key to continue...

Re:Detecting under Bochs Emulation

Posted: Sat Jul 02, 2005 2:43 am
by Brendan
HI,

A possibly more robust method of detecting Bochs is to examine the results returned by "Int 0x15, function 0xE820". For real computers the BIOS is mapped into the highest addresses of physical memory (below 4 GB) and this area is returned by the memory map function as unusable/reserved, while on Bochs it isn't as this high mapping doesn't exist.


Cheers,

Brendan

Re:Detecting under Bochs Emulation

Posted: Sat Jul 02, 2005 4:12 am
by smiddy
Hey Brendan,

Humm, my current E820 routine doesn't do a mapping that way within my OS. I'll have to include that code from my E820 application that does the entire mapping and make the comparison. Thanks! Though, I suspect, that if someone reports that as a bug to Bochs they'll fix it to be more like a real PC.

Re:Detecting under Bochs Emulation

Posted: Sat Jul 02, 2005 7:07 am
by Brendan
Hi,
smiddy wrote:Humm, my current E820 routine doesn't do a mapping that way within my OS. I'll have to include that code from my E820 application that does the entire mapping and make the comparison. Thanks! Though, I suspect, that if someone reports that as a bug to Bochs they'll fix it to be more like a real PC.
Hehee - I've already mentioned on the Bochs bug list that the 64 KB BIOS limit is a problem that will need to be rectified eventually, as 64 KB isn't enough space to support things like ACPI, however I assume such a change would only be done in conjuction with other larger changes that would take considerable time to complete.

For the time being there's no real reason for the Bochs project to change - as long as the environment that the guest OS runs in is correct it doesn't matter if the early BIOS initialization isn't 100% accurate (anything before the BIOS jumps to 0x07C00 isn't too important as long as it works).

In the meantime, a version of Bochs that doesn't have the 0xE9 hack enabled is much more likely...

Another way to detect Bochs is using the RDTSC instruction - Bochs increments the time stamp counter by one for every instruction (regardless of how many cycles it should take). Something like this should work:

Code: Select all

    mov ebx,0
    mov ecx,0x55555555

    rdtsc
    lea ebx,[ebx*8 + eax]
    mul ecx
    mul ecx
    mul ecx
    mul ecx
    mul ecx
    mul ecx
    mul ecx
    mul ecx
    mul ecx
    mul ecx
    mul ecx
    or eax,1
    and eax,1
    cpuid                 ;Serializing instruction!
    rdtsc

    sub eax,ebx      ;ebx = cycles used between RDTSC instructions
    cmp eax,16       ;Is it Bochs (16 cycles only)?
    je .isBochs        ; yes
Of course this relies on the RDTSC instruction being available - if your OS requires a Pentium or later CPU it always will be. Notice the care taken to prevent out of order execution on a real CPU from causing a "false positive" - the continued EAX register dependancies and the serializing instruction. Initializing ECX to 0x55555555 just makes the MUL's take longer, and the "lea ebx,[ebx*8 + eax]" is the slowest way of doing "mov ebx,eax" that I could think of :). On a real CPU this sequence should always cost more than 16 cycles...


Cheers,

Brendan

Re:Detecting under Bochs Emulation

Posted: Sat Jul 02, 2005 12:25 pm
by smiddy
Nice peice of code, thanks.

Here's a screen shot of my getmem app, and you're correct it only says what is available. Man I should have checked that out previously.

Code: Select all


A:\>getmem
GETMEM.COM - 0.14.0212 Attempt to see what memory is installed... -smiddy

BIOS:
   15h:
     E820:   Base Address   -  Memory Length    - Type
         : 0000000000000000 - 000000000009FC00h -  01 <<   Available to OS   >>
         : 0000000000100000 - 000000003FF00000h -  01 <<   Available to OS   >>
         ----------------------------------------------------------------
         : Total Memory (Free)         : 3FF9FC00h - 1,073,347,584 bytes.
     E801:
         : Extended memory (1M - 16M)  :     3C00h -    15,728,640 bytes.
         : Extended memory > 16M       :     3F00h - 1,056,964,608 bytes.
         : Configured memory (1M - 16M):     000Ah -        10,240 bytes.
         : Configured memory > 16M     :     3F00h - 1,056,964,608 bytes.
         ----------------------------------------------------------------
         : Total Memory (Free)         : 3FF00000h - 1,072,693,248 bytes.
   12h:
         : Conventional Memory (640K)  :     027Fh -       654,336 bytes.
   15h:
     88  :
         : Extended Memory (To 64M)    :     3C00h -    15,728,640 bytes.
         ----------------------------------------------------------------
         : Total Memory (Free)         : 00F9FC00h -    16,382,976 bytes.
CMOS:
         : Conventional Memory (640K)  :     0280h -       655,360 bytes.
         : Extended Memory (To 64M)    :     FC00h -    66,060,288 bytes.
         ----------------------------------------------------------------
         : Total Memory (Free)         : 03FA0000h -    66,715,648 bytes.

A:\>
That is on PC-DOS 3.3. Here's what I would have expected:

Code: Select all

A:\>GETMEM
GETMEM.COM - 0.14.020B Attempt to see what memory is installed... -smiddy

BIOS:
   15h:
     E820:   Base Address   -  Memory Length    - Type
         : 0000000000000000 - 000000000009FC00h -  01 <<   Available to OS   >>
         : 000000000009FC00 - 0000000000000400h -  02 <<   Reserved Memory   >>
         : 00000000000F0000 - 0000000000010000h -  02 <<   Reserved Memory   >>
         : 0000000000100000 - 0000000027EF0000h -  01 <<   Available to OS   >>
         : 0000000027FF0000 - 0000000000008000h -  03 << ACPI Reclaim Memory >>
         : 0000000027FF8000 - 0000000000008000h -  04 <<   ACPI NVS Memory   >>
         : 00000000FEC00000 - 0000000000001000h -  02 <<   Reserved Memory   >>
         : 00000000FEE00000 - 0000000000001000h -  02 <<   Reserved Memory   >>
         : 00000000FFF80000 - 0000000000080000h -  02 <<   Reserved Memory   >>
         ----------------------------------------------------------------
         : Total Memory                : 27F8FC00h -   670,628,864 bytes.
Something along those lines.

You seem very knowledgeable on Bochs' internals. Thanks, you have saved me the time in investigating this myself. A hefty pint of your favorite beverage (a nice Sam Adams sounds good right now) for you from me!