Page 2 of 3
Re: unreal mode
Posted: Mon Apr 02, 2012 8:21 am
by bluemoon
It's perfectly OK without a GPF handler, as long as you do not generate such fault.
However, when such fault triggered and you do not have a valid handler, the CPU generate double fault; if that is also invalid the CPU tripple fault and reset.
Re: unreal mode
Posted: Mon Apr 02, 2012 9:47 pm
by dileep
In some system i am able to access 32 bit offset and not in other systems.
So i have to use GPF handler to handle the fault by switching into the unreal mode.
Is there anyway to check whether the system is in unreal mode or not?
Re: unreal mode
Posted: Mon Apr 02, 2012 9:55 pm
by bluemoon
dileep wrote:In some system i am able to access 32 bit offset and not in other systems.
So i have to use GPF handler to handle the fault by switching into the unreal mode.
Why do you access to some offset you don't know what's there?
If you're working on pre-boot environment, use the memory map, or firmware function, etc...to allocate runtime memory.
Especially for mmio you need to know what is (or is not) there.
dileep wrote:Is there anyway to check whether the system is in unreal mode or not?
No official way. In fact unreal mode is not official thought every 386+ supported it.
Re: unreal mode
Posted: Mon Apr 02, 2012 11:25 pm
by dileep
bluemoon wrote:
Why do you access to some offset you don't know what's there?
I trying to access known offset from PCI BAR2 address. some machines are left in unreal mode , so i can access this 32 bit offset without changing the mode. Some other machines (Dell R710, etc) are in Real mode, so i have to change to unreal mode.
So i am trying to fix this issue for my driver to work in all servers.
Re: unreal mode
Posted: Tue Apr 03, 2012 1:03 am
by bluemoon
I recommend to have your code run inside a barebone protected mode environment. So, instead of:
Code: Select all
// unreal mode
pushf
cli
switch_to_pmode();
set_flat_selectors();
switch_to_rmode();
access_to_BAR();
more_work();
popf
You should do:
Code: Select all
pushf
cli
switch_to_pmode();
set_flat_selectors();
access_to_BAR();
switch_to_rmode();
more_work();
popf
This way you do not need to assume a unreal mode environment, just require a real mode environment for caller.
Re: unreal mode
Posted: Tue Apr 03, 2012 5:29 am
by dileep
this doesn't make sense to me .
What is in the case of systems which are left in unreal mode by the bios.?
Re: unreal mode
Posted: Wed Apr 04, 2012 2:59 am
by Solar
Is there even such a thing?
bluemoon wrote:dileep wrote:dileep wrote:Is there anyway to check whether the system is in unreal mode or not?
No official way.
In fact unreal mode is not official thought every 386+ supported it.
Re: unreal mode
Posted: Wed Apr 04, 2012 9:22 am
by turdus
bluemoon wrote:dileep wrote:Is there anyway to check whether the system is in unreal mode or not?
No official way. In fact unreal mode is not official thought every 386+ supported it.
As a matter of fact, there are more ways. Here's two:
1. examine data segment in gdt (use sgdt to get base address)
2. set ds to an unused 64k+1 memory. Put a non-zero byte at offset [ds:0], and a zero at [ds+4096:0]. Read from offset [ds:65536]. If you got non-zero byte, you are in real mode, if not, you are in unreal.
Re: unreal mode
Posted: Wed Apr 04, 2012 12:00 pm
by Combuster
Read from offset [ds:65536]. If you got non-zero byte, you are in real mode, if not, you are in unreal.
Nonsense. It means continue if ds.limit >= 65536 and lock up otherwise (caused by an infinite #GPF/IRET loop).
examine data segment in gdt
Which might be changed or otherwise overwritten since, making it another bad idea.
The only way to check is to install a #GP handler in real mode and testing 4G-1 addresses for each desired selector. if the handler is called, the segment register has a smaller register size. Note that unreal simply means changing the limit to something over 64K for at least one segment register. Typical setups might only set ES, DS+ES, or one of FS/GS. Some typical beginner errors set the limit to 1M instead of 4G.
Which brings us to the bottom line: don't test for unreal mode, just set it if needed.
As far as unreal mode being unofficial - it's essentially nothing but a name coined by its inventor for a programmer construction using a now documented feature:
AMD64 manual wrote:On FAR transfers, CS (code segment) selector is updated to the new value, and the CS segment base is
set to selector * 16. The CS segment limit and attributes are unchanged, but are usually 64K and
read/write, respectively.
Re: unreal mode
Posted: Wed Apr 04, 2012 12:07 pm
by bluemoon
examine data segment in gdt (use sgdt to get base address)
Using sgdt in real mode probably give you random byte or zero on fresh boot,
or leftover from previous unreal mode switch, which the memory pointed by it probably got trashed.
Re: unreal mode
Posted: Wed Apr 04, 2012 1:04 pm
by turdus
@bluemoon: that's the point. If it's valid, you're in unreal mode. You're right the shadow registers may contain different value, so you can tell only being in unreal for sure, if it fails, it does mean anything.
@Combuster: if GPF happens, it's even easier to detect:
Code: Select all
gpfhandler:
inc ah
iret
xor ax, ax
mov ds, ax
mov word [13*4], gpfhandler
mov word [13*4+2], cs
mov ebx, 10000h
mov al, byte [ebx]
or ah, ah
jnz .realmode
;unreal mode
Now this is a 100% accurate method.
Re: unreal mode
Posted: Wed Apr 04, 2012 2:24 pm
by Combuster
turdus wrote:Now this is a 100% accurate method.
Again wrong because:
Combuster wrote:It means continue if ds.limit >= 65536 and lock up otherwise (caused by an infinite #GPF/IRET loop).
You definitely did not fix that.
Re: unreal mode
Posted: Wed Apr 04, 2012 2:48 pm
by bluemoon
turdus wrote:@bluemoon: that's the point. If it's valid, you're in unreal mode. You're right the shadow registers may contain different value, so you can tell only being in unreal for sure, if it fails, it does mean anything.
Case study One.
A firmware switched to protected, loaded GDT at slightly higher than 1MiB, finished it job and return to real mode. SGDT will give you a pointer to ~1MiB. In the Unreal Detection function it cannot access that location without itself switched to unreal mode. Detection Failed.
Case study Two.
A firmware switched to protected, loaded GDT at
any location, finished it job and return to real mode. SGDT will give you a pointer to some high address. In the Unreal Detection function it cannot tell if that address is just garbage. Detection Failed.
Case study Three.
The system previously goes into unreal mode, SGDT give you a proper pointer, you walk into the descriptor structure and they look valid. The function report unreal mode environment is found. However, the segment registers has already been reloaded by interrupt services. False detection.
Re: unreal mode
Posted: Wed Apr 04, 2012 3:01 pm
by turdus
@bluemoon: why are you struggling after I stated my 1st solution is not good, and moved on with 2nd?
Combuster wrote:You definitely did not fix that.
You are so narrow-minded. That's the homework part for you. Hint: place "dec ebx" where appropriate. I was programming in head in ancient assembly dialect, no wonder it's not 100%. Not the small details, but the big picture what's important.
The point is, IT IS POSSIBLE to detect unreal mode. Period.
(Before you began to jiggle on post only good code, that's me. I can solve very complex equation systems with several variables mostly in head, and at the end reckon x=5*5=10 without hesitation (that actually happened with me once). I'm afraid you have to deal with it. I'm too old to change.)
Re: unreal mode
Posted: Wed Apr 04, 2012 4:17 pm
by bluemoon
turdus wrote:@bluemoon: why are you struggling after I stated my 1st solution is not good, and moved on with 2nd?
Sorry but I did not see you abandon the 1st solution. I was about to say objection to the claim
"so you can tell only being in unreal for sure" by putting up a false detection scenario.
The point is, IT IS POSSIBLE to detect unreal mode. Period.
Seems plausible but not practical. In fact that is the official way to detect
CPU fault. However, I consider unreal mode itself, and the way to detect it, is still unofficial.
Intel Manual wrote:
In section 9.9.2 Switching Back to Real-Address Mode
A procedure that re- enters real-address mode should perform the following steps:
3. Transfer program control to a readable segment that has a limit of 64 KBytes (FFFFH)
4. Load segment registers SS, DS, ES, FS, and GS with a selector for a descriptor containing the following values, which are appropriate for real-address mode:
— Limit = 64 KBytes (0FFFFH)
Unreal mode is activated by not following the manual(at least for IA processors), thus unofficial.
By the way the counter method has overflow bug in some situation but it can be changed to alter the return address to skip the fault instruction. But instead of doing all the troubles, I prefer:
Combuster wrote:Which brings us to the bottom line: don't test for unreal mode, just set it if needed.