Page 1 of 2

Switching to virtual memory management

Posted: Sat Nov 08, 2014 5:52 am
by psychobeagle12
Hello all! I have been working on a small system for a few weeks now (I have worked on a few little hobby systems and I am pretty good with C and x86 assembly.) I am loosely following Brokenthorn's OS Development Series and most of the OSDev Wiki pages when needed. Anyway, here is the issue. I am starting to migrate from pure physical memory management to virtual memory management. I am using GRUB to load the system, GCC and NASM to build. I built a small assembler stub that sets up basic paging tables and then jumps to my higher half kernel. For some reason, when I jump to the higher half (which is still in the stub part) I am getting a page fault, gp fault, then finally triple fault (obviously caused by the invalid idt.) Here is the assembler stub and the linker script:

Code: Select all

;-----------------------------------------------------------------------------------------;
;	kboot.asm: Version two of the kernel bootstrap (forms jump point for GRUB)        ;
;	Written by Ben Melikant 11/2014                                                   ;
;	This bootstrap sets up a basic paging directory table for the kernel so that our  ;
;	jump to the kernel does not result in triple-fault.                               ;
;-----------------------------------------------------------------------------------------;

bits 32

; paging identification info

%define PAGE_DIRECTORY_ADDR 0x9C000
%define PAGE_TABLE_0_ADDR   0x9D000
%define PAGE_TABLE_768_ADDR 0x9E000

%define PAGE_TABLE_ENTRIES 1024
%define FIRST_MEG_ENTRIES  256
%define PAGE_PRIVILEGE     3

; multiboot information definitions

MULTIBOOT_PAGE_ALIGN   equ 1<<0
MULTIBOOT_MEMORY_INFO  equ 1<<1
MULTIBOOT_HEADER_MAGIC equ 0x1BADB002
MULTIBOOT_HEADER_FLAGS equ MULTIBOOT_PAGE_ALIGN | MULTIBOOT_MEMORY_INFO
MULTIBOOT_CHECKSUM     equ -(MULTIBOOT_HEADER_MAGIC+MULTIBOOT_HEADER_FLAGS)

; place the multiboot header in it's own section

[section .multiboot]
align 4

multiboot_hdr:

	dd MULTIBOOT_HEADER_MAGIC
	dd MULTIBOOT_HEADER_FLAGS
	dd MULTIBOOT_CHECKSUM

; switch to the .startup section

[section .startup]
[global start]

; memory location to preserve the multiboot pointer

multiboot_ptr dd 0x00000000

; global descriptor table (to override GRUB's table)

gdt_start:

	dd 0,0
	db 0xff,0xff,0x00,0x00,0x00,10011010b,11001111b,0x00
	db 0xff,0xff,0x00,0x00,0x00,10010010b,11001111b,0x00

gdt_table:

	dw gdt_table-gdt_start-1
	dd gdt_start

;------------------------------------------------------------------------------------------;
;	start: Load into the operating system proper by setting up a page directory table  ;
;	and enabling paging. The OS is loaded at 0x10000 physical, 0xC0000000 virtual.     ;
;	If the OS ever returns, we have an issue.                                          ;
;------------------------------------------------------------------------------------------;

start:

	; load a new global descriptor table (override GRUB's table)

	lgdt [gdt_table]
	jmp 0x08:next

next:

	; fix our segments

	mov ax,0x10
	mov ds,ax
	mov es,ax
	mov fs,ax
	mov gs,ax
	mov ss,ax

	; jump to the actual start code, below the paging install routine

	mov dword [multiboot_ptr],ebx
	jmp start_system

;---------------------------------------------------------;
;	setup_paging: Enable paging before executing OS   ;
;	Inputs: None, Returns: None                       ;
;---------------------------------------------------------;

setup_paging:

	; save the registers

	pusha

	; identity-map addresses 0x00000000 - 0x00400000

	mov eax,PAGE_TABLE_0_ADDR
	mov ebx,0 | PAGE_PRIVILEGE
	mov ecx,PAGE_TABLE_ENTRIES

.identity_loop:

	mov dword [eax],ebx		; put the address entry into the table
	add eax,4			; queue next page entry
	add ebx,4096			; each entry is 4Kb

	loop .identity_loop		; set up next entry

	; next set up the address for the kernel page table

	mov eax,PAGE_TABLE_768_ADDR
	mov ebx,0x10000 | PAGE_PRIVILEGE
	mov ecx,PAGE_TABLE_ENTRIES

.kernel_loop:

	mov dword [eax],ebx		; same as above
	add eax,4			; same as above
	add ebx,4096			; same as above

	loop .kernel_loop		; same as above

.already_mapped:

	; install the tables into the directory

	mov eax,PAGE_TABLE_0_ADDR | PAGE_PRIVILEGE
	mov dword [PAGE_DIRECTORY_ADDR],eax

	mov eax,PAGE_TABLE_768_ADDR | PAGE_PRIVILEGE
	mov dword [PAGE_DIRECTORY_ADDR+(768*4)],eax

	; install the page directory into cr3 (pdbr)

	mov eax,PAGE_DIRECTORY_ADDR
	mov cr3,eax

	popa
	ret

start_system:

	; first set up the page directory table and page tables

	call setup_paging
	push dword [multiboot_ptr]

	mov ebx,0xb8000
	mov byte [ebx],'H'

	; now enable the paging mechanism

	mov eax,cr0
	or eax,0x80000000
	mov cr0,eax

	mov byte [0xc0000000],'i'		; this memory access works...
	jmp 0x08:paging_code

; paging is enabled. All addresses must now be translated as virtual
; switch to the .text section (regular system code, 0xC0000000 virtual)

[section .text]
[extern kmain]

paging_code:

	; mov ebx,0xb8002
	; mov byte [ebx],'i'

	; restore the multiboot ptr

	; pop ebx

	; now all we need to do is call the kernel loadpoint

	; mov esp,system_stack
	; push ebx
	; call kmain

	; a safeguard. The code should never reach this point

	jmp $

[section .bss]

resb 0x1000
system_stack:

	; our kernel stack begins here
and the link script:

Code: Select all

OUTPUT_FORMAT("elf32-i386")
ENTRY(start)

SECTIONS {

	. = 0x10000;

	.startup : 
	{
		*(.multiboot)
		*(.startup)
	}

	. += 0xC0000000;

	.text : AT(ADDR(.text) - 0xC0000000)
	{
		*(.text)
	}

	.data ALIGN(4096) : AT(ADDR(.data) - 0xC0000000)
	{
		*(.data)
		*(.rodata*)
	}

	.bss ALIGN(4096) : AT(ADDR(.bss) - 0xC0000000)
	{
		*(COMMON*)
		*(.bss*)
	}

	kernel_end=.;
}
Do I have a logical approach to getting into paging mode, or am I completely on the wrong track here? I appreciate any help, and again I apologize if this is a duplicate question at all. Thanks everyone!

Re: Switching to virtual memory management

Posted: Sat Nov 08, 2014 8:02 am
by Combuster
Without actually reading the question:

Code: Select all

%define PAGE_DIRECTORY_ADDR 0x9C000
%define PAGE_TABLE_0_ADDR   0x9D000
%define PAGE_TABLE_768_ADDR 0x9E000
That's likely to be reserved addresses.

Code: Select all

mov ebx,0x10000 | PAGE_PRIVILEGE
That maps to the addresses 64K up to 4M+64K, which is probably not what you want.

Code: Select all

call
Stackpointer undefined.

Re: Switching to virtual memory management

Posted: Sat Nov 08, 2014 8:32 am
by psychobeagle12

Code: Select all

mov ebx,0x10000 | PAGE_PRIVILEGE
That maps to the addresses 64K up to 4M+64K, which is probably not what you want.
Yes, that code is a mistake that I never changed back after trying a few experimental changes. I had forgotten about that. I want to map 0x00100000 - 0x00400000 for my OS code. As for the stack pointer, I believe I am setting it up in the startup code here:

Code: Select all

;------------------------------------------------------------------------------------------;
;   start: Load into the operating system proper by setting up a page directory table  ;
;   and enabling paging. The OS is loaded at 0x10000 physical, 0xC0000000 virtual.     ;
;   If the OS ever returns, we have an issue.                                          ;
;------------------------------------------------------------------------------------------;

start:

   ; load a new global descriptor table (override GRUB's table)

   lgdt [gdt_table]
   jmp 0x08:next

next:

   ; fix our segments

   mov ax,0x10
   mov ds,ax
   mov es,ax
   mov fs,ax
   mov gs,ax
   mov ss,ax

   ; jump to the actual start code, below the paging install routine

   mov dword [multiboot_ptr],ebx
   jmp start_system                                       ; this just skips the following enable_paging routine

As for the other addresses, to be honest I took most of the basic page mapping code from Brokenthorn's virtual memory management tutorial, so I used the same memory values found on that tutorial for my code. I can move them around if necessary no problem. I will try to change the addresses around and also make sure I change my linker script and mapping routine for 0x100000 instead of 0x10000. Anything else that jumps out to anybody? I'm very open to suggestions :)

Re: Switching to virtual memory management

Posted: Sat Nov 08, 2014 10:00 am
by eryjus
Check for setting esp again. I see you cleaning up ss after jumping to next to set your cs register. After setting the ss, you should be executing mov esp,<you-stack-pointer>.

Re: Switching to virtual memory management

Posted: Sat Nov 08, 2014 10:23 am
by psychobeagle12
Yes, I see the mistake with the stack now. Sorry, I'm not too crazy... I seem to have mixed up the words "pointer" and "segment." My mistake.

Re: Switching to virtual memory management

Posted: Sat Nov 08, 2014 10:44 am
by psychobeagle12
Well, I made the following changes:

Code: Select all


   mov ax,0x10
   mov ds,ax
   mov es,ax
   mov fs,ax
   mov gs,ax

   mov ss,ax
   mov esp,0x90000        ; fixed stack pointer, again location taken from Brokenthorn

   ; jump to the actual start code, below the paging install routine

   mov dword [multiboot_ptr],ebx
   jmp start_system       
and also:

Code: Select all


    mov eax,PAGE_TABLE_768_ADDR
    mov ebx,0x100000 | PAGE_PRIVILEGE
    mov ecx,PAGE_TABLE_ENTRIES

and lastly:

Code: Select all


%define PAGE_DIRECTORY_ADDR 0x7E00
%define PAGE_TABLE_0_ADDR     0x7F00
%define PAGE_TABLE_768_ADDR  0x8000

I also changed the start address in my linker script to 0x100000. None of these seemed to fix my issue. The bochs log shows exactly the same pattern with the revised code. Page fault (no vector available), GP Fault (no vector available), triple fault - reset.

Re: Switching to virtual memory management

Posted: Sat Nov 08, 2014 11:17 am
by Combuster
You forgot a zero (page structures must be page aligned)

Re: Switching to virtual memory management

Posted: Sat Nov 08, 2014 11:57 am
by psychobeagle12
Oops, another typo. I'm writing the code on my laptop, posting from my desktop. I in fact used

Code: Select all

%define PAGE_DIRECTORY_ADDR 0x7E000
%define PAGE_TABLE_0_ADDR     0x7F000
%define PAGE_TABLE_768_ADDR  0x80000

Re: Switching to virtual memory management

Posted: Sat Nov 08, 2014 12:10 pm
by eryjus
psychobeagle12 wrote:

Code: Select all

	; next set up the address for the kernel page table

	mov eax,PAGE_TABLE_768_ADDR
	mov ebx,0x10000 | PAGE_PRIVILEGE
	mov ecx,PAGE_TABLE_ENTRIES

.kernel_loop:

	mov dword [eax],ebx		; same as above
	add eax,4			; same as above
	add ebx,4096			; same as above

	loop .kernel_loop		; same as above
Correct me if I am wrong, but you really want virtual address 0xc0000000 to map to physical address 0x00000000 (and more to the point, virtual address 0xc0100000 to map to physical address 0x00100000)?

Re: Switching to virtual memory management

Posted: Sat Nov 08, 2014 12:19 pm
by psychobeagle12
eryjus wrote:
psychobeagle12 wrote:

Code: Select all

; next set up the address for the kernel page table

mov eax,PAGE_TABLE_768_ADDR
mov ebx,0x10000 | PAGE_PRIVILEGE
mov ecx,PAGE_TABLE_ENTRIES

.kernel_loop:

mov dword [eax],ebx ; same as above
add eax,4 ; same as above
add ebx,4096 ; same as above

loop .kernel_loop ; same as above
Correct me if I am wrong, but you really want virtual address 0xc0000000 to map to physical address 0x00000000 (and more to the point, virtual address 0xc0100000 to map to physical address 0x00100000)?
As far as I know, given the knowledge base I have on paging (I am honestly still very new to paging) the code I have written (or rather followed) will map the first page table to 0x00000000 (identity-mapping the first 4mb), and then will map address 0x100000 to 0xC0000000. Perhaps I am wrong in my understanding of the code I followed. And that raises a question for me as well. To my knowledge, bits 11 - 31 in a page table entry point to the physical address of the mapping, correct? So why, in the example read from Brokenthorn, would we not shift the entry left (0x100000 << 11) to set the entry correctly? I think I am still confused on this. Rather than ask anybody to fix this for me, I think I will reread the paging tutorial, unless I am on the right track? I appreciate the responses though, know that you guys are helping me very much!

Re: Switching to virtual memory management

Posted: Sat Nov 08, 2014 6:55 pm
by eryjus
OK, I am by no means an expert in paging and virtual memory. However, I have just completed a similar fight myself so the topic is still fresh in my mind. I'm sure if I get some of the details wrong, there are many people willing to set both of us straight. :)

First a few tool I use:

readelf will show you the sections of your file and where they will be loaded. In particular, the Program Headers ans Section to Segment mapping will show you where your binary is expected to live. In the Program Headers, look for "VirtAddr" and "PhysAddr" for each section. Take note that your .startup section is expected to load at physical address 0x00100000 and at virtual address 0x00100000. Thus, you need the identity map once you enable paging to get to the next instruction to execute.

Now, your .text section will likely be at a physical address (for the sake of argument since I cannot see your file) 0x00100e00. This will correspond to a virtual address of 0xc0100e00 based on your linker script. Notice you stated in your script:

Code: Select all

. += 0xc0000000
This line changes your virtual offset for the program you are linking, but does not impact where your elf binary will really be loaded in physical memory. You want this offset because you want to be able to have your low memory stub and high memory kernel to coexist nicely, which they cannot do if they are in the same physical memory. By the way, you might want to page-align the .text segment so you have the option to reclaim that stub code memory space at a later time.

This all really means you want virtual address 0xc0000000 to map to physical address 0x00000000 and virtual address 0xc0100000 to map to 0x00100000. This is not how your paging tables are setup.

Now for the paging tables. I highly recommend taking a look at the Intel software development manuals. In short, the physical address is "assembled" from the different entries in the paging tables. The Intel System Programming Guide, Part 1, Chapter 4 contains a good discussion on paging, and a number of tables that lay out the page table entries. In particular, section 4.3 is specific to 32-bit paging. Find the manuals here.
psychobeagle12 wrote:To my knowledge, bits 11 - 31 in a page table entry point to the physical address of the mapping
Bits 31:12 of the physical address are assembled from the virtual address and the entries found in the tables at each level. That is: bits 31:22 of the virtual address identify a page directory entry, where bits 31:12 of the resulting PDE identify a (4K aligned) page Table. Bits 21:12 of the virtual address identify a page table entry, where bits 31:12 of the resulting PTE identify a 4k page of physical memory. Bits 11:0 of your virtual address indicate the offset (bits 11:0) into your 4K aligned page of physical memory.


I hope this helps. Good luck!

EDIT: fixed URL link

Re: Switching to virtual memory management

Posted: Sat Nov 08, 2014 7:28 pm
by psychobeagle12
I poured over the tutorials some more (and believe it or not the Intel 80386 developer's manual) and my understanding is now much more complete. For the life of me though I cannot understand how my page tables are set up incorrectly. Yes, I realize that the address of my start code will not be 0xc0100000, but some offset into that area. However, from what I can tell my page tables still should be mapping the address of my paging_code symbol (which, according to bochs, is 0xc0101c00). My page tables are mapping this area to the correct non-virtual address, are they not? My table sets up mapping from 0xC0000000 to 0x100000 which should work correctly from what I can tell. Gives me more to think about though, I'll keep digging until I hit the nail...

Re: Switching to virtual memory management

Posted: Sat Nov 08, 2014 7:49 pm
by psychobeagle12
The more I work the more frustrated I become, and the more convinced I am that this should be working! I changed my linker script:

Code: Select all


OUTPUT_FORMAT("elf32-i386")
ENTRY(start)

SECTIONS {

	. = 0x7E000;

	.startup : 
	{
		*(.multiboot)
		*(.startup)
	}

	. = 0xC0100000;

	.text : AT(ADDR(.text) - 0xC0000000)
	{
		*(.text)
	}

	.data ALIGN(4096) : AT(ADDR(.data) - 0xC0000000)
	{
		*(.data)
		*(.rodata*)
	}

	.bss ALIGN(4096) : AT(ADDR(.bss) - 0xC0000000)
	{
		*(COMMON*)
		*(.bss*)
	}

	kernel_end=.;
}

So now I am loading the stub code to the memory at 0x7e000, and the kernel gets loaded to physical 0x100000, virtual 0xc0100000. My page should be mapped (unless my mapping routine is really messed up, which I nearly refuse to believe barring more evidence) and I changed my directory pointers to:

Code: Select all

%define PAGE_DIRECTORY_ADDR 0x7F000
%define PAGE_TABLE_0_ADDR   0x80000
%define PAGE_TABLE_768_ADDR 0x81000
so that I wouldn't overwrite my stub with page data (my stub is smaller than 4Kb). I am quickly running out of ideas. Is it possible that I am going about this whole thing the wrong way? I feel like this is a fairly basic task of most systems and that I shouldn't bother continuing if I can't figure this part out!

Re: Switching to virtual memory management

Posted: Sat Nov 08, 2014 7:55 pm
by eryjus
please post the results of readelf.

Re: Switching to virtual memory management

Posted: Sat Nov 08, 2014 8:02 pm
by psychobeagle12
readelf missy.elf -l -s:

Code: Select all

Elf file type is EXEC (Executable file)
Entry point 0x7e02e
There are 3 program headers, starting at offset 52

Program Headers:
  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
  LOAD           0x001000 0x0007e000 0x0007e000 0x006f4 0x006f4 R   0x1000
  LOAD           0x002000 0xc0100000 0x00100000 0x01cce 0x01cce R E 0x1000
  LOAD           0x004000 0xc0102000 0x00102000 0x002a9 0x028a0 RW  0x1000

 Section to Segment mapping:
  Segment Sections...
   00     .startup .eh_frame 
   01     .text 
   02     .data .bss 

Symbol table '.symtab' contains 189 entries:
   Num:    Value  Size Type    Bind   Vis      Ndx Name
     0: 00000000     0 NOTYPE  LOCAL  DEFAULT  UND 
     1: 0007e000     0 SECTION LOCAL  DEFAULT    1 
     2: 0007e0d4     0 SECTION LOCAL  DEFAULT    2 
     3: c0100000     0 SECTION LOCAL  DEFAULT    3 
     4: c0102000     0 SECTION LOCAL  DEFAULT    4 
     5: c0103000     0 SECTION LOCAL  DEFAULT    5 
     6: 00000000     0 SECTION LOCAL  DEFAULT    6 
     7: 00000000     0 FILE    LOCAL  DEFAULT  ABS src/asm/kboot.asm
     8: 00000001     0 NOTYPE  LOCAL  DEFAULT  ABS MULTIBOOT_PAGE_ALIGN
     9: 00000002     0 NOTYPE  LOCAL  DEFAULT  ABS MULTIBOOT_MEMORY_INFO
    10: 1badb002     0 NOTYPE  LOCAL  DEFAULT  ABS MULTIBOOT_HEADER_MAGIC
    11: 00000003     0 NOTYPE  LOCAL  DEFAULT  ABS MULTIBOOT_HEADER_FLAGS
    12: e4524ffb     0 NOTYPE  LOCAL  DEFAULT  ABS MULTIBOOT_CHECKSUM
    13: 0007e000     0 NOTYPE  LOCAL  DEFAULT    1 multiboot_hdr
    14: 0007e00c     0 NOTYPE  LOCAL  DEFAULT    1 multiboot_ptr
    15: 0007e010     0 NOTYPE  LOCAL  DEFAULT    1 gdt_start
    16: 0007e028     0 NOTYPE  LOCAL  DEFAULT    1 gdt_table
    17: 0007e03c     0 NOTYPE  LOCAL  DEFAULT    1 next
    18: 0007e057     0 NOTYPE  LOCAL  DEFAULT    1 setup_paging
    19: 0007e067     0 NOTYPE  LOCAL  DEFAULT    1 setup_paging.identity_loo
    20: 0007e083     0 NOTYPE  LOCAL  DEFAULT    1 setup_paging.kernel_loop
    21: 0007e090     0 NOTYPE  LOCAL  DEFAULT    1 setup_paging.already_mapp
    22: 0007e0ae     0 NOTYPE  LOCAL  DEFAULT    1 start_system
    23: c0101500     0 NOTYPE  LOCAL  DEFAULT    3 paging_code
    24: c01048a0     0 NOTYPE  LOCAL  DEFAULT    5 system_stack
    25: 00000000     0 FILE    LOCAL  DEFAULT  ABS x86_display.c
    26: 00000000     0 FILE    LOCAL  DEFAULT  ABS x86_idt.c
    27: 00000000     0 FILE    LOCAL  DEFAULT  ABS x86_pic.c
    28: c0100302    29 FUNC    LOCAL  DEFAULT    3 x86_inportb
    29: c010031f    30 FUNC    LOCAL  DEFAULT    3 x86_outportb
    30: 00000000     0 FILE    LOCAL  DEFAULT  ABS x86_gdt.c
    31: c0100625    51 FUNC    LOCAL  DEFAULT    3 x86_gdt_install
    32: 00000000     0 FILE    LOCAL  DEFAULT  ABS x86_pit.c
    33: c01008fc    29 FUNC    LOCAL  DEFAULT    3 x86_inportb
    34: c0100919    30 FUNC    LOCAL  DEFAULT    3 x86_outportb
    35: 00000000     0 FILE    LOCAL  DEFAULT  ABS hal.c
    36: 00000000     0 FILE    LOCAL  DEFAULT  ABS kernel.c
    37: 00000000     0 FILE    LOCAL  DEFAULT  ABS mmngr_physical.c
    38: c0103888     4 OBJECT  LOCAL  DEFAULT    5 _memory_bmp
    39: c010388c     2 OBJECT  LOCAL  DEFAULT    5 _bmp_sz
    40: c0103890     4 OBJECT  LOCAL  DEFAULT    5 _memory_size
    41: c0103894     4 OBJECT  LOCAL  DEFAULT    5 _free_blocks
    42: c0103898     4 OBJECT  LOCAL  DEFAULT    5 _used_blocks
    43: c010389c     4 OBJECT  LOCAL  DEFAULT    5 _total_blocks
    44: c0101108   136 FUNC    LOCAL  DEFAULT    3 _pmmngr_init_region
    45: c0101082   134 FUNC    LOCAL  DEFAULT    3 _pmmngr_find_first_free
    46: c0101190   138 FUNC    LOCAL  DEFAULT    3 _pmmngr_deinit_region
    47: 00000000     0 FILE    LOCAL  DEFAULT  ABS stdio.c
    48: 00000000     0 FILE    LOCAL  DEFAULT  ABS string.c
    49: 00000000     0 FILE    LOCAL  DEFAULT  ABS stdlib.c
    50: 00000000     0 FILE    LOCAL  DEFAULT  ABS x86_cpu.c
    51: 00000000     0 FILE    LOCAL  DEFAULT  ABS x86_keyboard.c
    52: 00000000     0 FILE    LOCAL  DEFAULT  ABS x86_apic.c
    53: 00000000     0 FILE    LOCAL  DEFAULT  ABS mmngr_virtual.c
    54: 00000000     0 FILE    LOCAL  DEFAULT  ABS src/asm/x86_handler_irq0.
    55: c0101522     0 NOTYPE  LOCAL  DEFAULT    3 x86_int20_handler_pit.ela
    56: c010152f     0 NOTYPE  LOCAL  DEFAULT    3 x86_int20_handler_pit.don
    57: c0101535     0 NOTYPE  LOCAL  DEFAULT    3 internal_counter
    58: 00000000     0 FILE    LOCAL  DEFAULT  ABS src/asm/exceptions.asm
    59: c0101558     0 NOTYPE  LOCAL  DEFAULT    3 msgDefaultHandler
    60: c01015ae     0 NOTYPE  LOCAL  DEFAULT    3 msgDivideByZero
    61: c01015f0     0 NOTYPE  LOCAL  DEFAULT    3 msgDebugTrap
    62: c0101627     0 NOTYPE  LOCAL  DEFAULT    3 msgNonMaskable
    63: c010165f     0 NOTYPE  LOCAL  DEFAULT    3 msgBreakPoint
    64: c0101695     0 NOTYPE  LOCAL  DEFAULT    3 msgOverflow
    65: c01016cb     0 NOTYPE  LOCAL  DEFAULT    3 msgBoundFault
    66: c0101703     0 NOTYPE  LOCAL  DEFAULT    3 msgInvalidOpcode
    67: c010173a     0 NOTYPE  LOCAL  DEFAULT    3 msgDeviceError
    68: c0101773     0 NOTYPE  LOCAL  DEFAULT    3 msgDoubleFault
    69: c01017ac     0 NOTYPE  LOCAL  DEFAULT    3 msgInvalidTss
    70: c01017e4     0 NOTYPE  LOCAL  DEFAULT    3 msgSegmentNotPresent
    71: c010181f     0 NOTYPE  LOCAL  DEFAULT    3 msgStackSegmentFault
    72: c010186a     0 NOTYPE  LOCAL  DEFAULT    3 x86_genprotectfault.gdt_d
    73: c0101879     0 NOTYPE  LOCAL  DEFAULT    3 x86_genprotectfault.idt_d
    74: c0101886     0 NOTYPE  LOCAL  DEFAULT    3 x86_genprotectfault.print
    75: c0101888     0 NOTYPE  LOCAL  DEFAULT    3 _gpf_error
    76: c010188c     0 NOTYPE  LOCAL  DEFAULT    3 msgGeneralProtectionFault
    77: c01018c8     0 NOTYPE  LOCAL  DEFAULT    3 msgGdtDescriptor
    78: c01018f1     0 NOTYPE  LOCAL  DEFAULT    3 msgIdtDescriptor
    79: c010192c     0 NOTYPE  LOCAL  DEFAULT    3 x86_pagefault.pf_notprese
    80: c0101945     0 NOTYPE  LOCAL  DEFAULT    3 x86_pagefault.pf_protecti
    81: c010196b     0 NOTYPE  LOCAL  DEFAULT    3 x86_pagefault.from_user_m
    82: c0101978     0 NOTYPE  LOCAL  DEFAULT    3 x86_pagefault.check_readw
    83: c0101991     0 NOTYPE  LOCAL  DEFAULT    3 x86_pagefault.on_write
    84: c010199e     0 NOTYPE  LOCAL  DEFAULT    3 x86_pagefault.stop
    85: c01019a1     0 NOTYPE  LOCAL  DEFAULT    3 x86_pagefault.page_nonexi
    86: c01019b1     0 NOTYPE  LOCAL  DEFAULT    3 x86_pagefault.fault_done
    87: c01019b3     0 NOTYPE  LOCAL  DEFAULT    3 msgPageFault
    88: c01019e9     0 NOTYPE  LOCAL  DEFAULT    3 msgPageProtectError
    89: c0101a13     0 NOTYPE  LOCAL  DEFAULT    3 msgPageNonexistant
    90: c0101a37     0 NOTYPE  LOCAL  DEFAULT    3 msgPageAccessRead
    91: c0101a68     0 NOTYPE  LOCAL  DEFAULT    3 msgPageAccessWrite
    92: c0101a9a     0 NOTYPE  LOCAL  DEFAULT    3 msgPagePrivilegeUser
    93: c0101ac0     0 NOTYPE  LOCAL  DEFAULT    3 msgPagePrivilegeKernel
    94: c0101ae8     0 NOTYPE  LOCAL  DEFAULT    3 _pf_err_code
    95: c0101afa     0 NOTYPE  LOCAL  DEFAULT    3 msgFPUException
    96: c0101b34     0 NOTYPE  LOCAL  DEFAULT    3 msgAlignmentCheck
    97: c0101b6c     0 NOTYPE  LOCAL  DEFAULT    3 msgMachineCheck
    98: c0101ba6     0 NOTYPE  LOCAL  DEFAULT    3 msgSimdException
    99: c0101be1     0 NOTYPE  LOCAL  DEFAULT    3 msgVirtualizeException
   100: c0101c22     0 NOTYPE  LOCAL  DEFAULT    3 msgSecurityException
   101: c0101c61     0 NOTYPE  LOCAL  DEFAULT    3 msgTestCode
   102: 00000000     0 FILE    LOCAL  DEFAULT  ABS src/asm/x86_handler_irq7.
   103: c0101ca0     0 NOTYPE  LOCAL  DEFAULT    3 x86_handler_irq7.spurious
   104: c0101ca6     0 NOTYPE  LOCAL  DEFAULT    3 x86_handler_irq7.interrup
   105: 00000000     0 FILE    LOCAL  DEFAULT  ABS src/asm/x86_handler_irq15
   106: c0101cc2     0 NOTYPE  LOCAL  DEFAULT    3 x86_handler_irq15.spuriou
   107: c0101ccc     0 NOTYPE  LOCAL  DEFAULT    3 x86_handler_irq15.interru
   108: 00000000     0 FILE    LOCAL  DEFAULT  ABS 
   109: c01002f6    12 FUNC    GLOBAL DEFAULT    3 x86_idt_install
   110: c0101aec     0 NOTYPE  GLOBAL DEFAULT    3 x86_fpuexception
   111: c0101c14     0 NOTYPE  GLOBAL DEFAULT    3 x86_securityexception
   112: c0100000   101 FUNC    GLOBAL DEFAULT    3 x86_clearscreen
   113: c0100fce    94 FUNC    GLOBAL DEFAULT    3 pmmngr_alloc_block
   114: c0103000  2040 OBJECT  GLOBAL DEFAULT    5 _idt
   115: c0103800    80 OBJECT  GLOBAL DEFAULT    5 _gdt
   116: c0101619     0 NOTYPE  GLOBAL DEFAULT    3 x86_nonmaskable
   117: 00000000     0 NOTYPE  GLOBAL DEFAULT  UND x86_pit_update_count
   118: c0100a71    15 FUNC    GLOBAL DEFAULT    3 x86_pit_resetticks
   119: c0101652     0 NOTYPE  GLOBAL DEFAULT    3 x86_breakpoint
   120: c010102c    86 FUNC    GLOBAL DEFAULT    3 pmmngr_free_block
   121: c010191b     0 NOTYPE  GLOBAL DEFAULT    3 x86_pagefault
   122: c0101811     0 NOTYPE  GLOBAL DEFAULT    3 x86_stacksegfault
   123: c01006c3   569 FUNC    GLOBAL DEFAULT    3 x86_gdt_add_descriptor
   124: c0101b5e     0 NOTYPE  GLOBAL DEFAULT    3 x86_machinecheck
   125: c0100ac7    13 FUNC    GLOBAL DEFAULT    3 tickcount
   126: c0101b26     0 NOTYPE  GLOBAL DEFAULT    3 x86_aligncheck
   127: c0102298    17 OBJECT  GLOBAL DEFAULT    4 lettermap
   128: c01005ce    87 FUNC    GLOBAL DEFAULT    3 x86_pic_get_irqreg
   129: c01016f5     0 NOTYPE  GLOBAL DEFAULT    3 x86_badopcode
   130: c0103850     6 OBJECT  GLOBAL DEFAULT    5 _gdt_table
   131: c0103881     1 OBJECT  GLOBAL DEFAULT    5 _curY
   132: c0100af9    70 FUNC    GLOBAL DEFAULT    3 sound
   133: c01015e2     0 NOTYPE  GLOBAL DEFAULT    3 x86_debugtrap
   134: c01009bc   132 FUNC    GLOBAL DEFAULT    3 x86_pit_makesound
   135: c0102004     4 OBJECT  GLOBAL DEFAULT    4 video_memory
   136: c0101bd3     0 NOTYPE  GLOBAL DEFAULT    3 x86_virtualizeexception
   137: c0101765     0 NOTYPE  GLOBAL DEFAULT    3 x86_doublefault
   138: c0101536     0 NOTYPE  GLOBAL DEFAULT    3 x86_int20_pit_counter
   139: c01013fc   191 FUNC    GLOBAL DEFAULT    3 itoa_s
   140: c0101c90     0 NOTYPE  GLOBAL DEFAULT    3 x86_handler_irq7
   141: c010172c     0 NOTYPE  GLOBAL DEFAULT    3 x86_deviceerror
   142: c010184c     0 NOTYPE  GLOBAL DEFAULT    3 x86_genprotectfault
   143: c01001e4    38 FUNC    GLOBAL DEFAULT    3 x86_setpos
   144: c0100513    38 FUNC    GLOBAL DEFAULT    3 x86_pic_disable
   145: c01048a0     0 NOTYPE  GLOBAL DEFAULT    5 kernel_end
   146: c0100273   131 FUNC    GLOBAL DEFAULT    3 x86_idt_setvector
   147: c0103860    32 OBJECT  GLOBAL DEFAULT    5 buffer
   148: c0100a40    39 FUNC    GLOBAL DEFAULT    3 x86_pit_killsound
   149: c0101238    47 FUNC    GLOBAL DEFAULT    3 debug_puts
   150: c0100a67    10 FUNC    GLOBAL DEFAULT    3 x86_pit_getticks
   151: c0101687     0 NOTYPE  GLOBAL DEFAULT    3 x86_overflow
   152: c0100a80    61 FUNC    GLOBAL DEFAULT    3 hal_initialize
   153: c0101cb0     0 NOTYPE  GLOBAL DEFAULT    3 x86_handler_irq15
   154: c010020a   105 FUNC    GLOBAL DEFAULT    3 x86_idt_initialize
   155: c0103880     1 OBJECT  GLOBAL DEFAULT    5 _curX
   156: c010033d   247 FUNC    GLOBAL DEFAULT    3 x86_pic_initialize
   157: c0100ad4    37 FUNC    GLOBAL DEFAULT    3 setvector
   158: c0100492    97 FUNC    GLOBAL DEFAULT    3 x86_pic_unmask_irq
   159: c01014bb    56 FUNC    GLOBAL DEFAULT    3 memset
   160: c0100539   139 FUNC    GLOBAL DEFAULT    3 x86_pic_send_eoi
   161: c01037f8     6 OBJECT  GLOBAL DEFAULT    5 _idtr
   162: c0100e57   375 FUNC    GLOBAL DEFAULT    3 pmmngr_initialize
   163: c0100abd    10 FUNC    GLOBAL DEFAULT    3 hal_shutdown
   164: c01016bd     0 NOTYPE  GLOBAL DEFAULT    3 x86_bounderror
   165: c010179e     0 NOTYPE  GLOBAL DEFAULT    3 x86_invalidtss
   166: c0102000     1 OBJECT  GLOBAL DEFAULT    4 color_attrib
   167: c010008a   116 FUNC    GLOBAL DEFAULT    3 x86_scroll
   168: c01004f3    32 FUNC    GLOBAL DEFAULT    3 x86_pic_enable
   169: c010159e     0 NOTYPE  GLOBAL DEFAULT    3 x86_dividebyzero
   170: c01000fe   230 FUNC    GLOBAL DEFAULT    3 x86_putchar
   171: c0100937    40 FUNC    GLOBAL DEFAULT    3 x86_pit_initialize
   172: c01017d6     0 NOTYPE  GLOBAL DEFAULT    3 x86_segnotpresent
   173: c0100065    37 FUNC    GLOBAL DEFAULT    3 x86_color
   174: c0101540     0 NOTYPE  GLOBAL DEFAULT    3 x86_default_interrupt
   175: c0100658   107 FUNC    GLOBAL DEFAULT    3 x86_gdt_initialize
   176: 0007e02e     0 NOTYPE  GLOBAL DEFAULT    1 start
   177: c010121a    30 FUNC    GLOBAL DEFAULT    3 debug_putc
   178: c0100ba7   688 FUNC    GLOBAL DEFAULT    3 kmain
   179: 00000000     0 NOTYPE  GLOBAL DEFAULT  UND _x86_swap_page
   180: c0101267   405 FUNC    GLOBAL DEFAULT    3 debug_printf
   181: c0101510     0 NOTYPE  GLOBAL DEFAULT    3 x86_int20_handler_pit
   182: c0100b3f   104 FUNC    GLOBAL DEFAULT    3 print_splash
   183: c010095f    93 FUNC    GLOBAL DEFAULT    3 x86_pit_startcount
   184: c0101b98     0 NOTYPE  GLOBAL DEFAULT    3 x86_simdexception
   185: c0103884     4 OBJECT  GLOBAL DEFAULT    5 spurious
   186: c0101c53     0 NOTYPE  GLOBAL DEFAULT    3 x86_testcode
   187: c01005c4    10 FUNC    GLOBAL DEFAULT    3 x86_pic_spurious_count
   188: c0100434    94 FUNC    GLOBAL DEFAULT    3 x86_pic_mask_irq
None of the C stuff is involved. It is only there because it is linked into the final executable so (I think) it can be safely ignored. Also, the relevant part of the bochs log:

Code: Select all

00017844368i[BIOS  ] Booting from 0000:7c00
00060242922e[CPU0  ] interrupt(): vector must be within IDT table limits, IDT.limit = 0x0
00060242922e[CPU0  ] interrupt(): vector must be within IDT table limits, IDT.limit = 0x0
00060242922i[CPU0  ] CPU is in protected mode (active)
00060242922i[CPU0  ] CS.mode = 32 bit
00060242922i[CPU0  ] SS.mode = 32 bit
00060242922i[CPU0  ] EFER   = 0x00000000
00060242922i[CPU0  ] | EAX=e0000011  EBX=000b8000  ECX=00000000  EDX=00000000
00060242922i[CPU0  ] | ESP=0008fffc  EBP=00000000  ESI=00000000  EDI=00000000
00060242922i[CPU0  ] | IOPL=0 ID vip vif ac vm RF nt of df if tf SF zf af PF cf
00060242922i[CPU0  ] | SEG sltr(index|ti|rpl)     base    limit G D
00060242922i[CPU0  ] |  CS:0008( 0001| 0|  0) 00000000 ffffffff 1 1
00060242922i[CPU0  ] |  DS:0010( 0002| 0|  0) 00000000 ffffffff 1 1
00060242922i[CPU0  ] |  SS:0010( 0002| 0|  0) 00000000 ffffffff 1 1
00060242922i[CPU0  ] |  ES:0010( 0002| 0|  0) 00000000 ffffffff 1 1
00060242922i[CPU0  ] |  FS:0010( 0002| 0|  0) 00000000 ffffffff 1 1
00060242922i[CPU0  ] |  GS:0010( 0002| 0|  0) 00000000 ffffffff 1 1
00060242922i[CPU0  ] | EIP=c0101500 (c0101500)
00060242922i[CPU0  ] | CR0=0xe0000011 CR2=0xe0000011
00060242922i[CPU0  ] | CR3=0x0007f000 CR4=0x00000000
00060242922e[CPU0  ] exception(): 3rd (13) exception with no resolution, shutdown status is 00h, resetting
00060242922i[SYS   ] bx_pc_system_c::Reset(HARDWARE) called
00060242922i[CPU0  ] cpu hardware reset
Any help to anybody? :/

Edit: I should have mentioned from the beginning that this code triple-faults on real hardware as well, just to throw that into the mix...