Page 1 of 3

Unreal mode

Posted: Fri Nov 13, 2009 1:56 pm
by Karlosoft
Hi! I'm trying to support the unreal mode in my bootloader. Is there a way to use the old segment:offest notation up to the first megabyte and the physical for the upper addresses?

Re: Unreal mode

Posted: Fri Nov 13, 2009 5:39 pm
by Combuster
trying to support the unreal mode
That sounded rather clueless. What do you want with *supporting* unreal mode? Is your OS based on Unreal Mode?

That aside, please search the wiki first: Descriptor Cache & Unreal Mode

Re: Unreal mode

Posted: Fri Nov 13, 2009 6:04 pm
by Love4Boobies
Karlosoft wrote:Hi! I'm trying to support the unreal mode in my bootloader. Is there a way to use the old segment:offest notation up to the first megabyte and the physical for the upper addresses?
Do you know exactly what unreal mode is? Why do you want these "notations"? :| :|

Re: Unreal mode

Posted: Fri Nov 13, 2009 6:11 pm
by neon
Hello,

You do not "support" unreal mode because there is no such mode. Unreal mode is not a processor mode but rather a "trick" (One I personally dont recommend, but its there.) Also, a bootloader should not "support" a mode, its only job, by its definition, is to get the system running. The system software can then provide support for the real processor modes: its primary mode (probably protected mode), real and/or v86 tasks, etc.

Re: Unreal mode

Posted: Sat Nov 14, 2009 6:44 am
by Karlosoft
My bootloader loads files in the first mega and I want to copy them above it.
I've read that with the unreal mode I can use up to 4 gb so I need to switch the processor in this real mode to copy them. :)

Re: Unreal mode

Posted: Sat Nov 14, 2009 7:27 am
by kmtdk
well
i have done exactly that. it is quite simple.
load a new GDT, and only change es.
for example:

lgdt [temp_gdt]
mov axs,0x08
mov es,ax

and then you can acess all 4 GB of the memory. example :
mov edi,0xff000000
mov eax,0x12345678

mov [es:edi],eax
.
if you dont "change" the limit for the segment ( es) then you will get a protection fault ( if i remember correct). However you may not change ds, as that causes a lot of trouble.

the reason why this works is that the cpu keeps a copy of the old GDT ( for ds and the rest), so changing ds will affect that "copy" and thereby causing unknown errors( i do not remember the error at this time)
.
so to sum this up:

create a temperory new GDT for, with the limit as 4 GB, and full access. then load that new GDT, and change the the wanted segment ( however not DS, Nor a "jmp 0x08:where" because we do not want to enter 32 bit mode, only change the limit for the specific segment)
and that is all the "magic"

KMt dk

Re: Unreal mode

Posted: Sat Nov 14, 2009 8:31 am
by neon
Karlosoft wrote:My bootloader loads files in the first mega and I want to copy them above it.
I've read that with the unreal mode I can use up to 4 gb so I need to switch the processor in this real mode to copy them. :)
Not entirely true. There are other methods. Unreal mode is one of the easier methods though.

Re: Unreal mode

Posted: Sat Nov 14, 2009 9:48 am
by Karlosoft
Thank you kmtdk :)
However what are these other ways Neon?

Re: Unreal mode

Posted: Sat Nov 14, 2009 11:54 am
by Combuster
Just plain protected mode? I do that as well...

Re: Unreal mode

Posted: Sat Nov 14, 2009 11:55 am
by XanClic
When I wrote my own bootloader, I used the unreal mode first. But it didn't work on my computer, so I implemented reading from floppy in real mode, switching to protected mode, copying to high memory, switching back to real mode, reading again and so on. That has worked, so I don't suggest using unreal mode at all, because I'm pretty sure it doesn't work on my computer (and hence maybe on other CPUs, too).

Re: Unreal mode

Posted: Sat Nov 14, 2009 11:58 am
by neon
You can just load the sector via the BIOS in real mode and copy the sector to its protected mode address in protected mode. Tis what I do anyways in mine except it switches between modes for each sector. A little slow but works well for my design.

You can also just stick with protected mode as Combuster said.

Re: Unreal mode

Posted: Sat Nov 14, 2009 12:30 pm
by qqq
lots of needless attacks going on in the beginning part of this thread...
Combuster wrote: That sounded rather clueless.
He knows what real and unreal modes are, and listed a specific way he wants to use them. Apart from not knowing how to do this (which was his entire question and the purpose for this thread), what exactly was "clueless" about it?
Combuster wrote: What do you want with *supporting* unreal mode?
The benefits of unreal mode are quite well known; access to the 32-bit address space while simultaneously being able to call bios and real mode programs.
Combuster wrote: Is your OS based on Unreal Mode?
Irrelevant; all we need to know is that he plans on using it at some point.
Combuster wrote: That aside, please search the wiki first: Descriptor Cache
I'll see your wiki-based page, and raise you this one:
http://files.osdev.org/mirrors/geezer/j ... gments.htm
(hint: that was a poker reference; I'm suggesting that this page is vastly superior to the one he mentioned.)
Combuster wrote: Unreal Mode
The code on that page is rather crippled; it only sets one of the segment registers, and it is integrated into/mixed in with the test code (rather than being a separate function which can be copied standalone into a real mode program).
Neon wrote: You do not "support" unreal mode because there is no such mode. Unreal mode is not a processor mode but rather a "trick"
Ok? Its purpose/advantage is [I stated this above in response to Combuster.] As long as it fulfills these goals, what does it matter whether it is technically a "mode" or not?

Also, unreal mode is quite standard (if not officially documented), present on all 32-bit cpu's.
Neon wrote: (One I personally dont recommend, but its there.)
Any particular reason you're against it?
Neon wrote: Also, a bootloader should not "support" a mode, its only job, by its definition, is to get the system running.
I mentioned the abilities of unreal mode above; all of them can be used (and are even necessary!) by the bootloader to do its job. Again, I don't see why you're against unreal mode being used by bootloaders.
Neon wrote: The system software can then provide support for the real processor modes: its primary mode (probably protected mode), real and/or v86 tasks, etc.
System software can do whatever it wants, and so can the bootloader (while it's still running).
kmtdk wrote: However you may not change ds, as that causes a lot of trouble.

[...]

so changing ds will affect that "copy" and thereby causing unknown errors( i do not remember the error at this time)
Huh??

The cpu keeps its copy of the values in its internal registers; not in memory (aka not anywhere that would depend on ds or that would be messed up by changing it).

(now to actually ANSWER the op's question!)
Short version of unreal mode:

The cpu stores internally for each segment a base, limit, and security bits and uses this stored copy (not the gdt) for all memory accesses. This copy is updated only when writing to the segment registers, never in-between. The only difference between real and protected mode is what happens when a seg.reg. is written to:

In real mode: set the base to (value<<4), and leave the limit/others unchanged.

In protected mode: load/change all of them from the gdt in memory.

Also note that switching on/off protected mode in CR0 leaves these values completely unaltered.

The limit is set to ffff by default; but according to the above, you can set PE, load all regs w/a segment whose limit is ffffffff and whose base is anything (specified in the gdt), unset PE, restore the old value of the segment register (which changes only the base, not the newly set limit), and use the segment (including reading/writing to the seg.regs. and using segment:offset) exactly like real mode segments, but with the ability to access all memory.

Some sample code (untested) for switching to unreal mode, using the method in the above paragraph:

Code: Select all


; call this function from real mode to
enter_unreal_mode:

; save the interrupt flag state
  pushfd 

; save the segment bases, since
; they get overwritten by the 
; switch to unreal mode
  push ds
  push es
  push fs
  push gs
  
; interrupts can save/restore segment
; registers. The PE bit changes the 
; meaning of writing to a segment register,
; i.e. allowing this to happen would result
; in the restored data meaning something
; different than the saved data.

  cli

; set PE bit

  mov eax,cr0
  or al,1
  mov cr0,eax

; change the segment limit, while
; keeping all other atrributes the same.
; Note: this overwrites the base address.

  lgdt[cs:.gdt]

  mov ax,8
  mov ds,ax
  mov es,ax
  mov fs,ax
  mov gs,ax
  
; don't bother with cs or ss, since
; push/pop/call/jmp in real mode is
; limited to a 16-bit sp/ip

; done here, back to (altered) real mode
  mov eax,cr0
  and al,0xfe
  mov cr0,eax

; restore the stuff that was saved
  pop gs
  pop fs
  pop es
  pop ds

  popfd
  ret
  
.gdt:
dw .end-.gdt-1
dd gdt
dw 0

dq 0x008f92000000ffff ;unreal mode data

.end:
For example, in unreal mode, the following are both valid and produce identical results in edx:

Code: Select all

;one way:

mov ax,0
mov ds,ax
mov eax,0x200000
mov edx,[eax]

;another way to get the same address:

mov ax,0x1000
mov ds,ax
mov eax,0x1f0000
mov edx,[eax]
So to answer your question,
Karlosoft wrote:Is there a way to use the old segment:offest notation up to the first megabyte and the physical for the upper addresses?
In unreal mode, both segment:offset and physical can be used for any address (not just the 1st meg), since the offset can now be 32 bits.

Accessing memory by physical address just means doing a segment:offset after setting the segment register to 0.

Note that in unreal mode, you need the "a32" prefix with any [segment:offset] access where offset is bigger than ffff. The assembler might insert this automatically (in the case of using a 32-bit register in the address like "mov reg,[eax]") or it might insist on making you do it manually (like nasm, in the case of "mov reg,[32-bit number]" or the "rep movsd"-type instructions). This is fairly annoying, but can be worked around (use "a32 mov reg,[32-bit number]" or "a32 rep movsd").

Programs originally compiled/intended for real mode (including bios) will still continue to function in unreal mode by the old segment:offset of offset less than ffff, they just won't know they can use a32/access higher memory.
Karlosoft wrote:what are these other ways
You could run your code in 32-bit pmode, and then switch back to unreal mode to call the bios. (disabling interrupts in pmode would probably be the easiest way to get this to work.) It is more complicated to set up, but it means you don't have to deal with the 16-bit stack/ip limitation.

If you know that the bios is the only 16-bit code you will ever want to call, another way would be to make a "call bios interrupt" function that switches back to 16-bit mode for you, and just call that from 32-bit mode (rather than trying to make a separate 16-bit function for every bios function you want to use.)
XanClic wrote:I don't suggest using unreal mode at all, because I'm pretty sure it doesn't work on my computer (and hence maybe on other CPUs, too).
Would like to see your code; unreal mode not working on some cpu's would be a pretty big deal...

Re: Unreal mode

Posted: Sat Nov 14, 2009 2:00 pm
by XanClic
OK, I take everything back. #-o

I still found that old piece of code but it was only the "switch" version (switching from real to protected mode and back). That worked as expected. Then I changed that code to do everything in unreal mode and... It still worked. So it was the usual stuff, just a bug made by me and not an unusual CPU behaviour. Though I don't have the original code to locate that bug.

Luckily I did not write "I know it won't work" but "I'm pretty sure". :mrgreen:


I'm really sorry. :oops:

Re: Unreal mode

Posted: Sat Nov 14, 2009 2:29 pm
by neon
Hello,
qqq wrote:Any particular reason you're against it?
Yes - its a hack; nonstandard. I dont care how supported it is - it can break at any time. Just because there is an easy way to do something, doesnt make it a good way.
qqq wrote:I mentioned the abilities of unreal mode above; all of them can be used (and are even necessary!) by the bootloader to do its job. Again, I don't see why you're against unreal mode being used by bootloaders.
As posted earlier, there are ways that you can load files in a bootloader > 1 MB. ie, mine loads files > 3GB without unreal mode using the BIOS and protected mode. You can even stick with protected mode all together.

Re: Unreal mode

Posted: Sat Nov 14, 2009 4:52 pm
by tom9876543
neon wrote:Hello,
qqq wrote:Any particular reason you're against it?
Yes - its a hack; nonstandard. I dont care how supported it is - it can break at any time. Just because there is an easy way to do something, doesnt make it a good way.
qqq wrote:I mentioned the abilities of unreal mode above; all of them can be used (and are even necessary!) by the bootloader to do its job. Again, I don't see why you're against unreal mode being used by bootloaders.
As posted earlier, there are ways that you can load files in a bootloader > 1 MB. ie, mine loads files > 3GB without unreal mode using the BIOS and protected mode. You can even stick with protected mode all together.
Unreal mode IS documented by Intel and AMD. They just call it SMM mode. BIOSes rely on it to operate. SMM was officially implemented with the 386. Unreal mode is simply the OS taking advantage of the 4gb limit in the same way the BIOS does under SMM mode.

There is no reason for Intel or AMD to remove unreal mode as it costs them nothing.

If you want a "perfect" processor that is clearly documented with no quirks then don't work with x86.

Using unreal mode is perfectly acceptable.