grub-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH] x86_64 again (related with my previous topics)


From: Ruslan Nikolaev
Subject: [PATCH] x86_64 again (related with my previous topics)
Date: Fri, 19 Aug 2005 15:18:35 -0700 (PDT)

Hi all!
First of all I want to say that all things I said are related with x86_64.
x86_64 implements 48-bit virtual address space. As AMD writes the bits from 64 to 48 (or implementation limit) should be all ones or all zeros.
In that case with have "sign-extended" address.
Also x86_64 uses 4 memory models. For example "kernel" model designed for kernel. "Kernel" model is also supported by GCC.
Moreover ABI allows running kernel in negative address space.
From x86_64 ABI:
---------------
"The kernel of an operating system is usually rather small but runs in the negative half of the address space. So we define all symbols to be
in the range from 2^64-2^31 to 2^64-2^24..."
From System.map of Linux x86_64:
-------------------------------
ffffffff80100000 A _text
ffffffff80100000 t startup_32
ffffffff80100081 t reach_compatibility_mode
ffffffff8010008e t second
ffffffff80100100 t reach_long64
ffffffff8010013d T initial_code
...
and so on
I think that using negative addresses is acceptable because the first thing that kernel do is creating early page table (otherwise we can't activate 64-bit mode).
I think that multiboot ELF64 for x86_64 must be compiled using negative address space (including all symbols). Using negative address space always can be accepted for x86_64 because paging is only one available memory model for 64-bit mode of x86_64.
That means the virtual address "0xffffffff80000000" should represents physical address 0x00000000
0xffffffff80100000 should represents 0x00100000 and so on.
In other words I want to say that all memory addresses must be masked with 0x7fffffff during loading ELF64.
SEE A VERY SIMPLE PATCH BELOW.
What do you think about it?
PATCH (it should affect ELF64 only):
diff -urN old/multiboot.c new/multiboot.c
--- old/multiboot.c 2005-08-19 21:44:34.000000000 +0000
+++ new/multiboot.c 2005-08-20 01:58:01.234065520 +0000
@@ -179,11 +179,7 @@
   if (ehdr->e_phoff + ehdr->e_phnum * ehdr->e_phentsize > GRUB_MB_SEARCH)
     return grub_error (GRUB_ERR_BAD_OS, "program header at a too high offset");
 
-  /* We still in 32-bit mode */
-  if (ehdr->e_entry > 0xffffffff)
-    return grub_error (GRUB_ERR_BAD_OS, "invalid entry point for ELF64");
-
-  entry = ehdr->e_entry;
+  entry = ehdr->e_entry & 0x7fffffff;
 
   /* Load every loadable segment in memory.  */
   for (i = 0; i < ehdr->e_phnum; i++)
@@ -192,6 +188,8 @@
         + i * ehdr->e_phentsize);
       if (phdr->p_type == PT_LOAD)
         {
+   grub_uint32_t paddr;
+
           /* The segment should fit in the area reserved for the OS.  */
           if ((phdr->p_paddr < (grub_uint64_t) grub_os_area_addr)
               || (phdr->p_paddr + phdr->p_memsz
@@ -204,14 +202,15 @@
      return grub_error (GRUB_ERR_BAD_OS,
           "invalid offset in program header");
 
-   if (grub_file_read (file, (void *) ((grub_uint32_t) phdr->p_paddr),
+          paddr = (grub_uint32_t) phdr->p_paddr & 0x7fffffff;
+   if (grub_file_read (file, (void *) paddr,
          phdr->p_filesz)
               != (grub_ssize_t) phdr->p_filesz)
      return grub_error (GRUB_ERR_BAD_OS,
           "couldn't read segment from file");
-  
+
           if (phdr->p_filesz < phdr->p_memsz)
-     grub_memset (((char *) ((grub_uint32_t) phdr->p_paddr)
+     grub_memset (((char *) paddr
      + phdr->p_filesz),
     0,
     phdr->p_memsz - phdr->p_filesz);


Start your day with Yahoo! - make it your home page
reply via email to

[Prev in Thread] Current Thread [Next in Thread]