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;
}
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')
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!