GPF while switching video modes

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
User avatar
0fb1d8
Member
Member
Posts: 27
Joined: Mon Nov 03, 2014 2:20 pm
Location: Seoul, South Korea
Contact:

GPF while switching video modes

Post by 0fb1d8 »

Hello,
I have recently implemented Napalm's VM86 monitor in my operating system, and have coded up a small driver for switching video modes in VGA and VESA VBE. The functions vga_set_mode() and vbe_set_mode() both seem to be able to switch video modes, as the QEMU's window size changes based on the given parameter when I run them. However, I was surprised to find in my kernel log that my system had been throwing a General Protection Fault (#GP) every time I ran one of those mode-switching functions.

Below is the code to the two mode-switching functions and a utility to collect basic information from the VGA:

Code: Select all

int vga_mode_set(uint16_t mode) {
	if (gregs == NULL) {
		dprintf("%s(): error: graphics driver not ready.\n",
		        __FUNCTION__);
		return -1;
	}
	
	clear_gregs();
	gregs->ax = mode;
	int32(0x10, gregs);
	
	return 0;
}

int get_vga_mode_info(vga_info_t* vga_info) {
	if (gregs == NULL) {
		dprintf("%s(): error: graphics driver not ready.\n",
		        __FUNCTION__);
		return -1;
	}
	
	if (vga_info == NULL) {
		dprintf("%s(): error: vga_info struct NULL; unable to"
		        " write information.\n", __FUNCTION__);
		return -1;
	}
	
	clear_gregs();
	gregs->ax = 0x0F;
	int32(0x10, gregs);
	
	vga_info->col = reg16_get_high(gregs->ax);
	vga_info->dpg = reg16_get_low(gregs->ax);
	vga_info->apg = reg16_get_high(gregs->bx);
	
	kprintf("%s(): \n"
	        "vga_info->col = %d\n"
	        "vga_info->dpg = %d\n"
	        "vga_info->apg = %d\n",
	        vga_info->col,
	        vga_info->dpg,
	        vga_info->apg);
	
	return 0;
}

int vbe_mode_set(uint16_t mode) {
	if (gregs == NULL) {
		dprintf("%s(): error: graphics driver not ready.\n",
		        __FUNCTION__);
		return -1;
	}
	
	clear_gregs();
	gregs->ax = 0x4F02;
	gregs->bx = mode;
	int32(0x10, gregs);
	
	return 0;
}
gregs is initialized outside of the scope of this code snippet by main.c.

This is the error message I found in my kernel log:

Code: Select all

****STOP: General Protection Fault
vec=0x0d err=0x00006710
eax=0x000000ec ebx=0x0000000b ecx=0x0000ffff edx=0xd0a4eca8
esi=0x00000023 edi=0x00000015
cs:eip=0x0008:0x00001fd3 eflags=0x00000282
ebp=0xd000d013 ss:esp=0x0:0xd000cf67
Process ID: 2 ('init')
Can anyone figure out why my kernel is faulting in the background? Is it possible that I am skipping certain procedures while handling VM86 instructions?

P.S. I've actually tried silencing the GPF handler, but then I get a Breakpoint Trap even before the interrupt handler finishes clearing the GPF.

Thank you!
Joonyoung Lee
Student at 한성과학고등학교(Hansung Science High School) & Ambitious OSDever
Arcrascent OS | Source <-- My OSDev Project
“One of my most productive days was throwing away 1000 lines of code.” - Ken Thompson
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re: GPF while switching video modes

Post by Brendan »

Hi,
0fb1d8 wrote:I have recently implemented Napalm's VM86 monitor in my operating system, and have coded up a small driver for switching video modes in VGA and VESA VBE.
Note: Virtual 8086 mode (or "VM86 mode") is a specific CPU mode (a sub-mode of protected mode); where the CPU handles most things but you need a monitor to handle things that the CPU doesn't (e.g. IOPL sensitive instructions). This code has nothing at all to do with virtual 8086 mode and has no "monitor". It's switching between real mode and protected mode instead.
0fb1d8 wrote:The functions vga_set_mode() and vbe_set_mode() both seem to be able to switch video modes, as the QEMU's window size changes based on the given parameter when I run them. However, I was surprised to find in my kernel log that my system had been throwing a General Protection Fault (#GP) every time I ran one of those mode-switching functions.
First step would be to figure out why your kernel is ignoring critical failures and not doing some kind of "halt the world" diagnostic (e.g. kernel panic, blue screen of death, etc).

Seconds step would be to use the information you get from the first step to determine the cause of the problem (e.g. using the exception's error code and "return CS:EIP", in conjunction with a disassembly or something, to determine the exact instruction causing the problem and why).


Cheers,

Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
User avatar
0fb1d8
Member
Member
Posts: 27
Joined: Mon Nov 03, 2014 2:20 pm
Location: Seoul, South Korea
Contact:

Re: GPF while switching video modes

Post by 0fb1d8 »

Could this be due to me ignoring the "disable paging before using" instruction? If so, how would one accomplish such task?

Thank you!
Joonyoung Lee
Student at 한성과학고등학교(Hansung Science High School) & Ambitious OSDever
Arcrascent OS | Source <-- My OSDev Project
“One of my most productive days was throwing away 1000 lines of code.” - Ken Thompson
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re: GPF while switching video modes

Post by Brendan »

Hi,
0fb1d8 wrote:Could this be due to me ignoring the "disable paging before using" instruction? If so, how would one accomplish such task?
It could be due to anything.

To disable paging, you mostly make sure you're only using identity mapped pages (e.g. for EIP and ESP) and clear the "paging enabled" flag in CR0.

What is the instruction causing the fault (the instruction at "cs:eip=0x0008:0x00001fd3")?


Cheers,

Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
Post Reply