Page 1 of 1

VMWare VBE Problem.

Posted: Sat Nov 14, 2015 8:20 am
by CrafterMan24
Hello, osdev forum!

I was developing my VBE driver and i have a problem now...

My VESA driver works great in VirtualBox, QEMU and Real hardware.

But in Bochs and VMWare i have strange problems...

I tried mode switching and etc with my both int32 (turns the real mode back does the interrupt and reenters the protected mode again, then loads the system state) and v8086 monitor, but same results in int32 and v8086, no difference...

I'm sure both v8086 and int32 working, i tested different interrupts and different video modes (0x12h, 0x13h, and etc) and it worked in all virtual machines and real hardware.

The problem is:

If i try setting the mode with an old legacy standardized video mode number (Like 0x117) in get controller info and get mode info, bochs and vmware returns success (0x004F), too like other virtual machines and real hardware. But when setting the mode, in VMWare and Bochs, system crashes (accidentally freezes, no turn back or error [error and exception handling works great in my system, tested too much times], system magically freezes, display stays same, i can't get the value in ax, because system crashes like i said) but in other virtual machines and real hardware, it works great again.

If i use http://wiki.osdev.org/Getting_VBE_Mode_Info 's get best display mode function, in bochs and vmware can't get any video mode from Video Mode Pointer, the Modes list i get from Video Mode Pointer is empty. But if i try in real hardware or other virtual machines it gets the modes, also sets the mode without problem again...

The debug output from both VMWare and other working virtual machines:

VMWare (When i try first way) (Mode is 0x114) (With LFB):

Get Controller Info:

Video Mode Pointer = 0xC00063BE
AX = 0x4F
Version = 2.0
Signature = VESA

Get 0x114 (With LFB) Mode Info:

Width = 800
Height = 600
Depth = 16

AX = 0x4F

Base pointer = (A correct value but i forgot it now)

Set Mode:

Nothing, system crashes, display looks same and interrupts being disabled.

--------------------------------------------------------------------------------------------------------------------------

VMWare (When i try first way) (Mode is 0x114) (Without LFB):

Get Controller Info:

Video Mode Pointer = 0xC00063BE
AX = 0x4F
Version = 2.0
Signature = VESA

Get 0x114 (Without LFB) Mode Info:

Width = 65535
Height = 512
Depth = 4

AX = 0x14F

Base pointer = (An incorrect value but i forgot it, too)

-------------------------------------------------------------------------------------------------------

VMWare, Using http://wiki.osdev.org/Getting_VBE_Mode_Info 's get best VBE mode function: (I wanted 800x600x16)

Get Controller Info:

Video Mode Pointer = 0xC00063BE
AX = 0x4F
Version = 2.0
Signature = VESA

Get Mode List:

List is empty, but it must be full of video modes.

---------------------------------------------------------------------------------------------------------------------------------





---------------------------------------------------------------------------------------------------------------------------------

In both other VMs And Real hardware: ( Excluding Bochs, Bochs has same result with VMWare [Results in top] )

Get Controller Info:

Video Mode Pointer = 0x202200
AX = 0x4F
Version = 3.0
Signature = VESA

-----------------------------------------------------------------------------------------

If using legacy standardized mode numbers ( Mode is 0x114 )

Get Mode Info:

(Correct values with / without LFB. Correct pointer, too)

AX = 0x4F

----------------------------------------------------------------------------------------------------

If using the http://wiki.osdev.org/Getting_VBE_Mode_Info 's get best VBE mode function:

List is full of video modes, also function gets the needed mode correctly.

AX = 0x4F

--------------------------------------------------------------------------------------------------------

Set Mode:

Screen resizes, sets the mode correct, and i can draw pixel.
AX = 0x4F

----------------------------------------------------------------------------------------------------------------------

The code i'm using:

Code: Select all

uint16_t findMode(int x, int y, int d)
{ 
  struct VESA_INFO *ctrl = (VESA_INFO *)0x2000;
  struct MODE_INFO *inf = (MODE_INFO *)0x3000;
  uint16_t *modes;
  int i;
  uint16_t best = 0x13;
  int pixdiff, bestpixdiff = DIFF(320 * 200, x * y);
  int depthdiff, bestdepthdiff = 8 >= d ? 8 - d : (d - 8) * 2;
 
  regs16_t regs;
  
  memcpy(ctrl->VESASignature, "VBE2", 4);
  regs.ax = 0x4F00;
  regs.es = 0;
  regs.di = ctrl;
  int32(0x10, &regs); // Get Controller Info
  if ( (uint16_t)regs.ax != 0x004F )
  {
    putstring("ERROR!");
  }
 
  modes = (uint16_t*)(ctrl->VideoModePtr);
  
  putstring_hex(ctrl->VideoModePtr);
      
  for ( i = 0 ; modes[i] != 0xFFFF ; ++i ) {
	  
	  regs.ax = 0x4F01;
	  regs.cx = modes[i];
	  regs.es = 0;
	  regs.di = inf;
	  
      int32(0x10, &regs); // Get Mode Info
 
      if ( (uint16_t)regs.ax != 0x004F ) continue;
 
      // Check if this is a graphics mode with linear frame buffer support
      if ( (inf->ModeAttributes & 0x90) != 0x90 ) continue;
 
      // Check if this is a packed pixel or direct color mode
      if ( inf->MemoryModel != 4 && inf->MemoryModel != 6 ) continue;
 
      // Check if this is exactly the mode we're looking for
      if ( x == inf->XResolution && y == inf->YResolution &&
          d == inf->BitsPerPixel ) return modes[i];
 
      // Otherwise, compare to the closest match so far, remember if best
      pixdiff = DIFF(inf->XResolution * inf->YResolution, x * y);
      depthdiff = (inf->BitsPerPixel >= d)? inf->BitsPerPixel - d : (d - inf->BitsPerPixel) * 2;
      if ( bestpixdiff > pixdiff ||
          (bestpixdiff == pixdiff && bestdepthdiff > depthdiff) ) {
        best = modes[i];
        bestpixdiff = pixdiff;
        bestdepthdiff = depthdiff;
      }
  }
  if ( x == 640 && y == 480 && d == 1 ) return 0x11;
  return best;
}

void setVesa(unsigned int X, unsigned int Y, unsigned int BitsPerPixel)
{
   regs16_t regs;
   regs.ax = 0x4f02; //mode the sets up VESA graphics
   regs.bx = (findMode(X, Y, BitsPerPixel));

   int32(0x10, &regs);

}
Tried with / without LFB, still same, not sure what is the bug...
Tried with much different mode numbers and resolutions, same, nothing changes...

#Edit:

Code: Select all

void setVesa(uint32_t mode)
{
  regs16_t regs;
  memset(&regs, 0, sizeof(regs));
  regs.ax = 0x4F02;
  regs.bx = (mode | 0x4000);
  int32(0x10, &regs);
}
I simplified code to this and started to working, i started to think vbe get mode info is broken on VMWare...
Anyone knows a fix, or what can be the problem?

Thanks for helping :(

Re: VMWare and Bochs VBE Problem.

Posted: Sat Nov 14, 2015 12:23 pm
by BASICFreak
I'm unsure about VMWare, but for Bochs you must change the standard vga rom and extension to something like:

Code: Select all

vgaromimage: file="/usr/share/bochs/VGABIOS-stdvga"
vga: extension=vbe, update_freq=60
The standard VGA setup does not allow SVGA nor does it have a VBE (Video BIOS Extension), it has a "special" interface called BGA (Bochs Graphics Adapter).

This Bochs config is what I use for my SVGA, and it hasn't failed me yet...

Re: VMWare and Bochs VBE Problem.

Posted: Sat Nov 14, 2015 12:48 pm
by CrafterMan24
BASICFreak wrote:I'm unsure about VMWare, but for Bochs you must change the standard vga rom and extension to something like:

Code: Select all

vgaromimage: file="/usr/share/bochs/VGABIOS-stdvga"
vga: extension=vbe, update_freq=60
The standard VGA setup does not allow SVGA nor does it have a VBE (Video BIOS Extension), it has a "special" interface called BGA (Bochs Graphics Adapter).

This Bochs config is what I use for my SVGA, and it hasn't failed me yet...
In Bochs it looks OK, but i'm still not sure what is the problem in VMWare...

Re: VMWare and Bochs VBE Problem.

Posted: Sat Nov 14, 2015 1:11 pm
by BASICFreak
A quick search came up with this thread, http://forum.osdev.org/viewtopic.php?f=1&t=18122, Within this thread it is stated the VMWare uses VBE3 - your code searches only for VBE2 signature?




NOTE: I have never used VMWare for my OS, therefore any information I provide about it is purely assumption!

If that doesn't help I highly expect someone here has the answer.




Also posting on a 9-month old thread is highly discouraged http://forum.osdev.org/viewtopic.php?f=1&t=29037

Re: VMWare and Bochs VBE Problem.

Posted: Sat Nov 14, 2015 4:19 pm
by Brendan
Hi,
CrafterMan24 wrote:The problem is:

If i try setting the mode with an old legacy standardized video mode number (Like 0x117) in get controller info and get mode info, bochs and vmware returns success (0x004F), too like other virtual machines and real hardware. But when setting the mode, in VMWare and Bochs, system crashes (accidentally freezes, no turn back or error [error and exception handling works great in my system, tested too much times], system magically freezes, display stays same, i can't get the value in ax, because system crashes like i said) but in other virtual machines and real hardware, it works great again.
This normally means that it crashed in real mode. The most common scenario is an exception, where the BIOS interrupt handler assumes its an IRQ or software interrupt and does nothing useful (or worse), then returns to the instruction that caused the exception (which causes the same exception again, and ...). Of course this has nothing to do with your exception handlers for protected mode.

Note that for Bochs you can configure/compile it and enable a built in debugger that will let you step through one instruction at a time, examine memory, etc (and find out exactly what is going on when the guest magically freezes). Sadly a lot of Linux distributions don't enable the built in debugger for their standard Bochs package so you probably will need to download the source code and configure and compile yourself.
BASICFreak wrote:A quick search came up with this thread, http://forum.osdev.org/viewtopic.php?f=1&t=18122, Within this thread it is stated the VMWare uses VBE3 - your code searches only for VBE2 signature?
That "VBE2" signature only tells VBE that your buffer is large enough for the larger structure introduced with VBE 2.0. It's fine for VBE3 (where the size of the structure remained the same).


Cheers,

Brendan

Re: VMWare and Bochs VBE Problem.

Posted: Sat Nov 14, 2015 9:55 pm
by CrafterMan24
Brendan wrote:Hi,
CrafterMan24 wrote:The problem is:

If i try setting the mode with an old legacy standardized video mode number (Like 0x117) in get controller info and get mode info, bochs and vmware returns success (0x004F), too like other virtual machines and real hardware. But when setting the mode, in VMWare and Bochs, system crashes (accidentally freezes, no turn back or error [error and exception handling works great in my system, tested too much times], system magically freezes, display stays same, i can't get the value in ax, because system crashes like i said) but in other virtual machines and real hardware, it works great again.
This normally means that it crashed in real mode. The most common scenario is an exception, where the BIOS interrupt handler assumes its an IRQ or software interrupt and does nothing useful (or worse), then returns to the instruction that caused the exception (which causes the same exception again, and ...). Of course this has nothing to do with your exception handlers for protected mode.

Note that for Bochs you can configure/compile it and enable a built in debugger that will let you step through one instruction at a time, examine memory, etc (and find out exactly what is going on when the guest magically freezes). Sadly a lot of Linux distributions don't enable the built in debugger for their standard Bochs package so you probably will need to download the source code and configure and compile yourself.
BASICFreak wrote:A quick search came up with this thread, http://forum.osdev.org/viewtopic.php?f=1&t=18122, Within this thread it is stated the VMWare uses VBE3 - your code searches only for VBE2 signature?
That "VBE2" signature only tells VBE that your buffer is large enough for the larger structure introduced with VBE 2.0. It's fine for VBE3 (where the size of the structure remained the same).


Cheers,

Brendan
Oh i guessed this, can i install a bochs debug environment in Windows? Normally i'm developing my os in Windows (Using cygwin and my cross compiler that targets i686-elf)

Edit: I installed the bochs with debugger. Incredibly Bochs is not crashing, too after vbe setting. There is no error message and everything works great. I don't know whats the problem with VMWare..

Re: VMWare and Bochs VBE Problem.

Posted: Sat Nov 14, 2015 10:57 pm
by CrafterMan24
YAY! Looks i found the problem:

2015-11-15T06:53:43.918+02:00| vcpu-0| I120: Unknown int 10h func 0x0000

It is from VMWare logs.

Then some CPU error messages, then a crash.

So my ax register looks not sending to vmware.

Yes, but why? Why function gets 0x0000 in vmware?

I started to think it is a stack corruption.

Code: Select all

; 
; Protected Mode BIOS Call Functionailty v2.0 - by Napalm
; -------------------------------------------------------
; 
; This is code shows how its POSSIBLE to execute BIOS interrupts
; by switch out to real-mode and then back into protected mode.
; 
; If you wish to use all or part of this code you must agree
; to the license at the following URL.
; 
; License: http://creativecommons.org/licenses/by-sa/2.0/uk/
;         
; Notes: This file is in NASM syntax.
;        Turn off paging before calling these functions.
;        int32() resets all selectors.
;
; C Prototype:
;	void _cdelc int32(unsigned char intnum, regs16_t *regs);
; 
; Example of usage:
;   regs.ax = 0x0013;
;   int32(0x10, &regs);
;   memset((char *)0xA0000, 1, (320*200));
;   memset((char *)0xA0000 + (100*320+80), 14, 80);
;   regs.ax = 0x0000;
;   int32(0x16, &regs);
;   regs.ax = 0x0003;
;   int32(0x10, &regs);
; 
; 
[bits 32]

global int32, _int32

struc regs16_t
	.di	resw 1
	.si	resw 1
	.bp	resw 1
	.sp resw 1
	.bx	resw 1
	.dx	resw 1
	.cx	resw 1
	.ax	resw 1
	.gs	resw 1
	.fs	resw 1
	.es	resw 1
	.ds	resw 1
	.ef resw 1
endstruc

%define INT32_BASE                             0x7C00
%define REBASE(x)                              (((x) - reloc) + INT32_BASE)
%define GDTENTRY(x)                            ((x) << 3)
%define CODE32                                 GDTENTRY(1)	; 0x08
%define DATA32                                 GDTENTRY(2)	; 0x10
%define CODE16                                 GDTENTRY(3)	; 0x18
%define DATA16                                 GDTENTRY(4)	; 0x20
%define STACK16                                (INT32_BASE - regs16_t_size)


section .text
	int32: use32                               ; by Napalm
	_int32:
		cli                                    ; disable interrupts
		pusha                                  ; save register state to 32bit stack
		mov  esi, reloc                        ; set source to code below
		mov  edi, INT32_BASE                   ; set destination to new base address
		mov  ecx, (int32_end - reloc)          ; set copy size to our codes size
		cld                                    ; clear direction flag (so we copy forward)
		rep  movsb                             ; do the actual copy (relocate code to low 16bit space)
		jmp INT32_BASE                         ; jump to new code location
	reloc: use32                               ; by Napalm
		mov  [REBASE(stack32_ptr)], esp        ; save 32bit stack pointer
		sidt [REBASE(idt32_ptr)]               ; save 32bit idt pointer
		sgdt [REBASE(gdt32_ptr)]               ; save 32bit gdt pointer
		lgdt [REBASE(gdt16_ptr)]               ; load 16bit gdt pointer
		lea  esi, [esp+0x24]                   ; set position of intnum on 32bit stack
		lodsd                                  ; read intnum into eax
		mov  [REBASE(ib)], al                  ; set intrrupt immediate byte from our arguments 
		mov  esi, [esi]                        ; read regs pointer in esi as source
		mov  edi, STACK16                      ; set destination to 16bit stack
		mov  ecx, regs16_t_size                ; set copy size to our struct size
		mov  esp, edi                          ; save destination to as 16bit stack offset
		rep  movsb                             ; do the actual copy (32bit stack to 16bit stack)
		jmp  word CODE16:REBASE(p_mode16)      ; switch to 16bit selector (16bit protected mode)
	p_mode16: use16
		mov  ax, DATA16                        ; get our 16bit data selector
		mov  ds, ax                            ; set ds to 16bit selector
		mov  es, ax                            ; set es to 16bit selector
		mov  fs, ax                            ; set fs to 16bit selector
		mov  gs, ax                            ; set gs to 16bit selector
		mov  ss, ax                            ; set ss to 16bit selector
		mov  eax, cr0                          ; get cr0 so we can modify it
		and  al,  ~0x01                        ; mask off PE bit to turn off protected mode
		mov  cr0, eax                          ; set cr0 to result
		jmp  word 0x0000:REBASE(r_mode16)      ; finally set cs:ip to enter real-mode
	r_mode16: use16
		xor  ax, ax                            ; set ax to zero
		mov  ds, ax                            ; set ds so we can access idt16
		mov  ss, ax                            ; set ss so they the stack is valid
		lidt [REBASE(idt16_ptr)]               ; load 16bit idt
		mov  bx, 0x0870                        ; master 8 and slave 112
		call resetpic                          ; set pic's the to real-mode settings
		popa                                   ; load general purpose registers from 16bit stack
		pop  gs                                ; load gs from 16bit stack
		pop  fs                                ; load fs from 16bit stack
		pop  es                                ; load es from 16bit stack
		pop  ds                                ; load ds from 16bit stack
		sti                                    ; enable interrupts
		db 0xCD                                ; opcode of INT instruction with immediate byte
	ib: db 0x00
		cli                                    ; disable interrupts
		xor  sp, sp                            ; zero sp so we can reuse it
		mov  ss, sp                            ; set ss so the stack is valid
		mov  sp, INT32_BASE                    ; set correct stack position so we can copy back
		pushf                                  ; save eflags to 16bit stack
		push ds                                ; save ds to 16bit stack
		push es                                ; save es to 16bit stack
		push fs                                ; save fs to 16bit stack
		push gs                                ; save gs to 16bit stack
		pusha                                  ; save general purpose registers to 16bit stack
		mov  bx, 0x2028                        ; master 32 and slave 40
		call resetpic                          ; restore the pic's to protected mode settings
		mov  eax, cr0                          ; get cr0 so we can modify it
		inc  eax                               ; set PE bit to turn on protected mode
		mov  cr0, eax                          ; set cr0 to result
		jmp  dword CODE32:REBASE(p_mode32)     ; switch to 32bit selector (32bit protected mode)
	p_mode32: use32
		mov  ax, DATA32                        ; get our 32bit data selector
		mov  ds, ax                            ; reset ds selector
		mov  es, ax                            ; reset es selector
		mov  fs, ax                            ; reset fs selector
		mov  gs, ax                            ; reset gs selector
		mov  ss, ax                            ; reset ss selector
		lgdt [REBASE(gdt32_ptr)]               ; restore 32bit gdt pointer
		lidt [REBASE(idt32_ptr)]               ; restore 32bit idt pointer
		mov  esp, [REBASE(stack32_ptr)]        ; restore 32bit stack pointer
		mov  esi, STACK16                      ; set copy source to 16bit stack
		lea  edi, [esp+0x28]                   ; set position of regs pointer on 32bit stack
		mov  edi, [edi]                        ; use regs pointer in edi as copy destination
		mov  ecx, regs16_t_size                ; set copy size to our struct size
		cld                                    ; clear direction flag (so we copy forward)
		rep  movsb                             ; do the actual copy (16bit stack to 32bit stack)
		popa                                   ; restore registers
		sti                                    ; enable interrupts
		ret                                    ; return to caller
		
	resetpic:                                  ; reset's 8259 master and slave pic vectors
		push ax                                ; expects bh = master vector, bl = slave vector
		mov  al, 0x11                          ; 0x11 = ICW1_INIT | ICW1_ICW4
		out  0x20, al                          ; send ICW1 to master pic
		out  0xA0, al                          ; send ICW1 to slave pic
		mov  al, bh                            ; get master pic vector param
		out  0x21, al                          ; send ICW2 aka vector to master pic
		mov  al, bl                            ; get slave pic vector param
		out  0xA1, al                          ; send ICW2 aka vector to slave pic
		mov  al, 0x04                          ; 0x04 = set slave to IRQ2
		out  0x21, al                          ; send ICW3 to master pic
		shr  al, 1                             ; 0x02 = tell slave its on IRQ2 of master
		out  0xA1, al                          ; send ICW3 to slave pic
		shr  al, 1                             ; 0x01 = ICW4_8086
		out  0x21, al                          ; send ICW4 to master pic
		out  0xA1, al                          ; send ICW4 to slave pic
		pop  ax                                ; restore ax from stack
		ret                                    ; return to caller
		
	stack32_ptr:                               ; address in 32bit stack after we
		dd 0x00000000                          ;   save all general purpose registers
		
	idt32_ptr:                                 ; IDT table pointer for 32bit access
		dw 0x0000                              ; table limit (size)
		dd 0x00000000                          ; table base address
		
	gdt32_ptr:                                 ; GDT table pointer for 32bit access
		dw 0x0000                              ; table limit (size)
		dd 0x00000000                          ; table base address
		
	idt16_ptr:                                 ; IDT table pointer for 16bit access
		dw 0x03FF                              ; table limit (size)
		dd 0x00000000                          ; table base address
		
	gdt16_base:                                ; GDT descriptor table
		.null:                                 ; 0x00 - null segment descriptor
			dd 0x00000000                      ; must be left zero'd
			dd 0x00000000                      ; must be left zero'd
			
		.code32:                               ; 0x01 - 32bit code segment descriptor 0xFFFFFFFF
			dw 0xFFFF                          ; limit  0:15
			dw 0x0000                          ; base   0:15
			db 0x00                            ; base  16:23
			db 0x9A                            ; present, iopl/0, code, execute/read
			db 0xCF                            ; 4Kbyte granularity, 32bit selector; limit 16:19
			db 0x00                            ; base  24:31
			
		.data32:                               ; 0x02 - 32bit data segment descriptor 0xFFFFFFFF
			dw 0xFFFF                          ; limit  0:15
			dw 0x0000                          ; base   0:15
			db 0x00                            ; base  16:23
			db 0x92                            ; present, iopl/0, data, read/write
			db 0xCF                            ; 4Kbyte granularity, 32bit selector; limit 16:19
			db 0x00                            ; base  24:31
			
		.code16:                               ; 0x03 - 16bit code segment descriptor 0x000FFFFF
			dw 0xFFFF                          ; limit  0:15
			dw 0x0000                          ; base   0:15
			db 0x00                            ; base  16:23
			db 0x9A                            ; present, iopl/0, code, execute/read
			db 0x0F                            ; 1Byte granularity, 16bit selector; limit 16:19
			db 0x00                            ; base  24:31
			
		.data16:                               ; 0x04 - 16bit data segment descriptor 0x000FFFFF
			dw 0xFFFF                          ; limit  0:15
			dw 0x0000                          ; base   0:15
			db 0x00                            ; base  16:23
			db 0x92                            ; present, iopl/0, data, read/write
			db 0x0F                            ; 1Byte granularity, 16bit selector; limit 16:19
			db 0x00                            ; base  24:31
			
	gdt16_ptr:                                 ; GDT table pointer for 16bit access
		dw gdt16_ptr - gdt16_base - 1          ; table limit (size)
		dd gdt16_base                          ; table base address
		
	int32_end:                                 ; end marker (so we can copy the code)
I'm using napalm's real mode interrupt functionality.

Then i modified this part of code

Code: Select all

r_mode16: use16
		xor  ax, ax                            ; set ax to zero
		mov  ds, ax                            ; set ds so we can access idt16
		mov  ss, ax                            ; set ss so they the stack is valid
		lidt [REBASE(idt16_ptr)]               ; load 16bit idt
		mov  bx, 0x0870                        ; master 8 and slave 112
		call resetpic                          ; set pic's the to real-mode settings
		popa                                   ; load general purpose registers from 16bit stack
		pop  gs                                ; load gs from 16bit stack
		pop  fs                                ; load fs from 16bit stack
		pop  es                                ; load es from 16bit stack
		pop  ds                                ; load ds from 16bit stack
		sti                                    ; enable interrupts
		db 0xCD                                ; opcode of INT instruction with immediate byte
with:

Code: Select all

r_mode16: use16
		xor  ax, ax                            ; set ax to zero
		mov  ds, ax                            ; set ds so we can access idt16
		mov  ss, ax                            ; set ss so they the stack is valid
		lidt [REBASE(idt16_ptr)]               ; load 16bit idt
		mov  bx, 0x0870                        ; master 8 and slave 112
		call resetpic                          ; set pic's the to real-mode settings
		popa                                   ; load general purpose registers from 16bit stack
		pop  gs                                ; load gs from 16bit stack
		pop  fs                                ; load fs from 16bit stack
		pop  es                                ; load es from 16bit stack
		pop  ds                                ; load ds from 16bit stack
		sti 
                mov ax, 4F02h
                mov bx, 117h                  ; enable interrupts
		db 0xCD                                ; opcode of INT instruction with immediate byte
Then it selected the mode.

I still don't know a fix or what causes to the problem, hope i will fix... I'm still unsure what causing to the problem.

What can i do?

Re: VMWare and Bochs VBE Problem.

Posted: Sun Nov 15, 2015 11:37 am
by Brendan
Hi,
CrafterMan24 wrote:I still don't know a fix or what causes to the problem, hope i will fix... I'm still unsure what causing to the problem.
I don't know either - there's too many possibilities in what I can see, and there's parts I can't see (like what the "REBASE" macro actually does or why its needed, where things are in memory, etc).

The only problem I've noticed is that it reprograms the PIC chips. This is impossible to do without the risk of losing interrupts and without the risk of various race conditions.

For a specific example; it's possible for an IRQ to be received by the PIC and delivered to the CPU (before the PIC is reprogrammed) while the CPU is in protected mode with interrupts disabled, where the IRQ isn't handled by the CPU until you enable IRQs in real mode. If the PICs were configured so that "IRQ0 = interrupt vector 0x20" in protected mode, then this can cause an "interrupt 0x20" in real mode, and if the BIOS's interrupt handler thinks its a software interrupt it could cause unexpected behaviour (like the BIOS using AX to return something from "BIOS software interrupt 0x20").

To reprogram the PIC chips without race conditions you have to mask all IRQs in both PIC chips (but not the "cascade") and do a few NOPs with interrupts enabled (to ensure any pending IRQs get a chance to be handled); then reprogram the PIC chips, and then unmask IRQs after. Of course this makes it more likely that IRQs will be lost (and that devices will stop working because their IRQs were losts).

The best (more reliable and faster) alternative is to not reprogram the PIC chips. It's entirely possible (and easy) for a protected mode interrupt handler to detect if an interrupt is an exception or an IRQ by asking the PIC chip if it sent an IRQ. Note that this approach doesn't/can't tell if an interrupt was a spurious IRQs from a PIC chip and an exception or software interrupt; but fortunately "interrupt 0x0F" is reserved and isn't a valid exception, so it's safe to assume than any "interrupt 0x0F" is either a spurious IRQ from the PIC or an actual IRQ7 from the PIC.

Also note that while in protected mode you have to reflect IRQs back to the BIOS (e.g. where your protected mode IRQ handlers switch back to real mode and pass control the the BIOS IRQ handler, then switch to protected mode after the BIOS has done its thing). If you don't do this then the BIOS's drivers can get out of sync with the hardware they're driving (simple example would be BIOS receiving the first byte of a 3 byte scan code from the keyboard and ending up in a bizarre state because it didn't get the second IRQ).


Cheers,

Brendan

Re: VMWare and Bochs VBE Problem.

Posted: Sun Nov 15, 2015 11:43 am
by CrafterMan24
Brendan wrote:Hi,
CrafterMan24 wrote:I still don't know a fix or what causes to the problem, hope i will fix... I'm still unsure what causing to the problem.
I don't know either - there's too many possibilities in what I can see, and there's parts I can't see (like what the "REBASE" macro actually does or why its needed, where things are in memory, etc).

The only problem I've noticed is that it reprograms the PIC chips. This is impossible to do without the risk of losing interrupts and without the risk of various race conditions.

For a specific example; it's possible for an IRQ to be received by the PIC and delivered to the CPU (before the PIC is reprogrammed) while the CPU is in protected mode with interrupts disabled, where the IRQ isn't handled by the CPU until you enable IRQs in real mode. If the PICs were configured so that "IRQ0 = interrupt vector 0x20" in protected mode, then this can cause an "interrupt 0x20" in real mode, and if the BIOS's interrupt handler thinks its a software interrupt it could cause unexpected behaviour (like the BIOS using AX to return something from "BIOS software interrupt 0x20").

To reprogram the PIC chips without race conditions you have to mask all IRQs in both PIC chips (but not the "cascade") and do a few NOPs with interrupts enabled (to ensure any pending IRQs get a chance to be handled); then reprogram the PIC chips, and then unmask IRQs after. Of course this makes it more likely that IRQs will be lost (and that devices will stop working because their IRQs were losts).

The best (more reliable and faster) alternative is to not reprogram the PIC chips. It's entirely possible (and easy) for a protected mode interrupt handler to detect if an interrupt is an exception or an IRQ by asking the PIC chip if it sent an IRQ. Note that this approach doesn't/can't tell if an interrupt was a spurious IRQs from a PIC chip and an exception or software interrupt; but fortunately "interrupt 0x0F" is reserved and isn't a valid exception, so it's safe to assume than any "interrupt 0x0F" is either a spurious IRQ from the PIC or an actual IRQ7 from the PIC.

Also note that while in protected mode you have to reflect IRQs back to the BIOS (e.g. where your protected mode IRQ handlers switch back to real mode and pass control the the BIOS IRQ handler, then switch to protected mode after the BIOS has done its thing). If you don't do this then the BIOS's drivers can get out of sync with the hardware they're driving (simple example would be BIOS receiving the first byte of a 3 byte scan code from the keyboard and ending up in a bizarre state because it didn't get the second IRQ).


Cheers,

Brendan
Wow, looks working now. I implemented my double buffer. And my new problem, mouse driver :D
It just throws random locations, not stable.