OSDev.org

The Place to Start for Operating System Developers
It is currently Tue Apr 23, 2024 3:41 pm

All times are UTC - 6 hours




Post new topic Reply to topic  [ 1 post ] 
Author Message
 Post subject: Calling 32-bit C from lower- of higher half 64-bit kernel
PostPosted: Thu May 04, 2017 3:25 am 
Offline
User avatar

Joined: Thu May 04, 2017 2:03 am
Posts: 13
My x86_64 kernel is loaded into the higher half, at 0xFFFFFFFF80000000. Before paging is set up and the jump to the higher half and long mode is made, I'm subtracting 0xFFFFFFFF80000000 from my addresses to get the lower half physical address. So far so good.

I would, however, like to call some 32-bit C code from assembly while we're still in the lower half (kernel starts at 1MB) to initialize paging, load the gdt. This is presents a problem because said code is linked into the higher half of the kernel which results in an error. I tried to solve this by using GCC's section attribute to relocate the static variables and functions to a section in the lower half (1). Linking now succeeds, but the machine just triple faults and Bochs reports this error:

Code:
bx_dbg_read_linear: physical memory read error (phy=0x000080101170, lin=0x0000000080101170)

This happens if I just:
Code:
call paging_init

Which makes sense. So I tried this:
Code:
lea paging_init, %eax
call *%eax

Check the contents of eax again and now they correspond to the address of the function and the machine doesn't triple fault... But the function is simply not called! What?

My ld script looks like this:
Code:
VM_ADDR = 0xFFFFFFFF80000000;

SECTIONS
{
   . = 0x100000;

   .mboot ALIGN(4096) : {
      *(.mboot)
      . = ALIGN(4096);
   }

   .init ALIGN(4096) : {
      *(.init)
      *(.gdt)
   }

   . += VM_ADDR;

   .text ALIGN(4096) : AT(ADDR(.text) - VM_ADDR) {
      *(.text)
   }

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

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

   /DISCARD/ : {
      *(.eh_frame)
      *(.comment)
   }
}


The .init section contains .text compiled for i386 and .gdt is for 32-bit .bss data.

Moving the section is done by prefixing this to functions:
Code:
__attribute__ ((section(".init")))


Maybe what I'm trying to do is just impossible (it shouldn't be) and I should just separate the binaries into a 32-bit loader and the 64-bit kernel. I would love to hear your thoughts on this and perhaps even a solution.

(1) I can move the functions and variables to another section but I haven't found a way to give debugging information a new section, for now I'm just omitting 32-bit debug info using -g0. If you have a solution for this issue as well, that'd be awesome!

P.S. I don't like how my tabs (and tabs are 8 columns, mind you) are displayed as a mere 3 spaces on this forum.

EDIT: I've decided to get rid of the C code and just implement it in assembly. This works for me, though it'd still be nice to know how to tackle this problem in the future if (read when) it comes up again...

_________________
"Writing a portable OS is not much harder than a nonportable one, and all systems should be written with portability in mind these days." — Andrew S. Tanenbaum

Elarix
Source: https://github.com/teeuwen/elarix


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 1 post ] 

All times are UTC - 6 hours


Who is online

Users browsing this forum: AlmaX3 and 120 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group