Re: [long] MINIX 3.1.6 works in QEMU-0.12.3 only with KVM disabled

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Avi Kivity wrote on 2010-03-10 13:03:25 +0200:
> On 03/10/2010 12:26 PM, Erik van der Kouwe wrote:
>> I've submitted this bug report a week ago:
>> http://sourceforge.net/tracker/?func=detail&aid=2962575&group_id=180599&atid=893831 
> 
> MINIX is using big real mode which is currently not well supported by kvm on Intel hardware: 
> 
>> (qemu) info registers
>> EAX=00000010 EBX=00000009 ECX=49200000 EDX=0000a796
>> ESI=00000200 EDI=49200200 EBP=00000009 ESP=0000a762
>> EIP=0000f4a7 EFL=00023002 [-------] CPL=3 II=0 A20=1 SMM=0 HLT=0
>> ES =0000 00000000 0000ffff 0000f300
>> CS =f000 000f0000 0000ffff 0000f300
>> SS =9492 00094920 0000ffff 0000f300
>> DS =97ce 00097cec 0000ffff 0000f300
> 
> A ds.base of 0x97cec cannot be translated to a real mode segment.
> 
> There is some work to get this to work, but it is proceeding really slowly.
> It should work on AMD hardware though.

Hi guys,

I searched the issue, and Erik was kind enough to point me to this list
where there are knowledgeable people.


Erik van der Kouwe wrote in
http://groups.google.com/group/minix3/msg/40f44df0c434cfa6:
> The situation is as follows:
>
> The boot monitor runs in real-address mode, but has to copy parts of
> the boot image into high memory (>= 1 MB) which is not accessible from
> that mode as only 20 bits are available. It calls the BIOS (int 0x15)
> to perform the copy. This is done under the ext_copy label in boot/
> boothead.s.

Okay. It is my understanding this is where Minix' involvement stops.


> The BIOS switches to protected mode, loading a GDT which it receives
> from the caller. Before returning to the caller, it copies data using
> the segment descriptors in the GDT and switches back to real-address
> mode.

This is the description of BIOS service 15/87, which have to be
implemented (using whatever solution it pleases) by the BIOS.


> When doing switch, the cached segment selectors are preserved,
> which allows one to use protected mode segments in real-address mode
> (this is called unreal mode).

Now this is a by-product of the implementation inside the BIOS.
In fact, even if the BIOS enters unreal mode (or the similar big real,
more useful with segmentation-less architectures), before turning back
to the client it (should) reset things to normal real mode, as service
15/87 is not an usual way to enter unreal mode (for example, this effect
is not even mentionned in Ralf Brown's list).

As a result (and also and foremost because of 80286 compatibility),
instead of directly using unreal or big real mode if possible (as done
eg. in himem.sys), Minix monitor goes to the great pain to going back to
square #1, and since blocks are at most 64 KB in size and several
iterations are needed, on the next block Minix sets up the (very
similar) GDT then does another call to the same BIOS service 15/87.


> I knew these parts before, but this is where Avi's answer came in: KVM
> on Intel does not yet support unreal mode and requires the cached
> segment descriptors to be valid in real-address mode.

I do not know which virtual BIOS is using KVM, but I notice while
reading http://bochs.sourceforge.net/cgi-bin/lxr/source/bios/rombios.c:
[ Slightly edited to fit the width of my post. AL. ]
3555     case 0x87:
3556 #if BX_CPU < 3
3557 #  error "Int15 function 87h not supported on < 80386"
3558 #endif
3559       // +++ should probably have descriptor checks
3560       // +++ should have exception handlers
...
3640       mov  eax, cr0
3641       or   al, #0x01
3642       mov  cr0, eax
3643       ;; far jump to flush CPU queue after transition to prot. mode
3644       JMP_AP(0x0020, protected_mode)
3645
3646 protected_mode:
3647       ;; GDT points to valid descriptor table, now load SS, DS, ES
3648       mov  ax, #0x28 ;; 101 000 = 5th desc.in table, TI=GDT,RPL=00
3649       mov  ss, ax
3650       mov  ax, #0x10 ;; 010 000 = 2nd desc.in table, TI=GDT,RPL=00
3651       mov  ds, ax
3652       mov  ax, #0x18 ;; 011 000 = 3rd desc.in table, TI=GDT,RPL=00
3653       mov  es, ax
3654       xor  si, si
3655       xor  di, di
3656       cld
3657       rep
3658         movsw  ;; move CX words from DS:SI to ES:DI
3659
3660       ;; make sure DS and ES limits are 64KB
3661       mov ax, #0x28
3662       mov ds, ax
3663       mov es, ax
3664
3665       ;; reset PG bit in CR0 ???
3666       mov  eax, cr0
3667       and  al, #0xFE
3668       mov  cr0, eax

I should be loosing something here... There is no unreal mode at any
moment, is it?

[ ... some web browsing occuring meanwhile ... Later: ]

Okay, now I got another picture. 8-|
Until recently, KVM (and qemu) used Bochs BIOS, showed above; but they
switched recently to SeaBIOS... where the applicable code is in
src/system.c, and looks like (now this is AT&T assembly):
  83 static void
  84 handle_1587(struct bregs *regs)
  85 {
  86     // +++ should probably have descriptor checks
  87     // +++ should have exception handlers
....
 127         // Enable protected mode
 128         "  movl %%cr0, %%eax\n"
 129         "  orl $" __stringify(CR0_PE) ", %%eax\n"
 130         "  movl %%eax, %%cr0\n"
 131
 132      // far jump to flush CPU queue after transition to prot. mode
 133         "  ljmpw $(4<<3), $1f\n"
 134
 135         // GDT points to valid descriptor table, now load DS, ES
 136         "1:movw $(2<<3), %%ax\n"
			 // 2nd descriptor in table, TI=GDT, RPL=00
 137         "  movw %%ax, %%ds\n"
 138         "  movw $(3<<3), %%ax\n"
			 // 3rd descriptor in table, TI=GDT, RPL=00
 139         "  movw %%ax, %%es\n"
 140
 141         // move CX words from DS:SI to ES:DI
 142         "  xorw %%si, %%si\n"
 143         "  xorw %%di, %%di\n"
 144         "  rep movsw\n"
 145
 146         // Disable protected mode
 147         "  movl %%cr0, %%eax\n"
 148         "  andl $~" __stringify(CR0_PE) ", %%eax\n"
 149         "  movl %%eax, %%cr0\n"

Note that while the basic scheme is the same, the "cleaning up" of lines
3660-3663 "make sure DS and ES limits are 64KB" is not present.
IIUC, the virtualized CPU goes back to real mode with those segments
sets as they are in protected mode, and yes with Minix boot monitor they
happenned to NOT be paragraph-aligned.


Is it possible to add back this "cleaning up" to the BIOS used in KVM?



Antoine
--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]
  Powered by Linux