All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC][PATCH] Supporting MSB-domU on ia64 Xen
@ 2006-11-22 12:32 Dietmar Hahn
  2006-11-28  6:25 ` Dietmar Hahn
  0 siblings, 1 reply; 5+ messages in thread
From: Dietmar Hahn @ 2006-11-22 12:32 UTC (permalink / raw)
  To: xen-devel, xen-ia64-devel

[-- Attachment #1: Type: text/plain, Size: 595 bytes --]

Hi,

at present Xen supports only domU's with the same endianess.
The ia64 cpu is able to run in little or big endianess. Currently ia64-Xen 
runs little endian (dom0 linux too) and supports little endian domU's. I want 
to add support for big endian domU's on ia64-Xen.
My first step is changing the loader stuff to get big endian elf images loaded 
into the memory. Only tools/libxc/xc_load_elf.c is concerned.
Therefore I added some swap inline functions and macros.
Please have a look and send your comments!
Thanks.

Dietmar.

Signed-off-by: Dietmar Hahn <dietmar.hahn@fujitsu-siemens.com>

[-- Attachment #2: xc_load_elf.patch --]
[-- Type: text/x-diff, Size: 13648 bytes --]

diff -r bcd2960d6dfd tools/libxc/xc_load_elf.c
--- a/tools/libxc/xc_load_elf.c	Mon Nov 20 21:10:59 2006 -0700
+++ b/tools/libxc/xc_load_elf.c	Wed Nov 22 13:05:27 2006 +0100
@@ -6,6 +6,66 @@
 #include "xc_elf.h"
 #include <stdlib.h>
 #include <inttypes.h>
+
+#if defined(__ia64__)
+
+static int do_swap = 0;
+
+static __inline uint64_t
+bswap64(uint64_t x)
+{
+    uint64_t r;
+    asm __volatile("mux1 %0=%1,@rev" : "=r" (r) : "r"(x));
+    return r;
+}
+
+static __inline uint64_t
+xen_swap64(uint64_t x)
+{
+    if(do_swap)
+        return (bswap64(x));
+    else return x;
+}
+
+static __inline uint32_t
+xen_swap32(uint32_t x)
+{
+    if(do_swap)
+        return (bswap64(x) >> 32);
+    else return x;
+}
+
+static __inline uint16_t
+xen_swap16(uint16_t x)
+{
+
+    if(do_swap)
+        return (bswap64(x) >> 48);
+    else return x;
+}
+
+
+#define xenswap(x,sz)  ( \
+	((sz)==1)? (uint8_t)(x): \
+	((sz)==2)? xen_swap16(x): \
+	((sz)==4)? xen_swap32(x): \
+	((sz)==8)? xen_swap64(x): \
+	~0l )
+
+#define SWAP(x)	xenswap((x), sizeof((x)))
+
+
+#define SET_SWAP do_swap = 1;
+#define SET_NOSWAP do_swap = 0;
+
+#else /* defined(__ia64__) */
+
+#define SWAP(x) x
+#define SET_SWAP
+#define SET_NOSWAP
+
+#endif /* defined(__ia64__) */
+
 
 #define round_pgup(_p)    (((_p)+(PAGE_SIZE-1))&PAGE_MASK)
 #define round_pgdown(_p)  ((_p)&PAGE_MASK)
@@ -62,8 +122,8 @@ int probe_elf(const char *image,
 
 static inline int is_loadable_phdr(Elf_Phdr *phdr)
 {
-    return ((phdr->p_type == PT_LOAD) &&
-            ((phdr->p_flags & (PF_W|PF_X)) != 0));
+    return ((SWAP(phdr->p_type) == PT_LOAD) &&
+            ((SWAP(phdr->p_flags) & (PF_W|PF_X)) != 0));
 }
 
 /*
@@ -72,7 +132,7 @@ static inline int is_loadable_phdr(Elf_P
  */
 static int is_xen_guest_section(Elf_Shdr *shdr, const char *shstrtab)
 {
-    return strcmp(&shstrtab[shdr->sh_name], "__xen_guest") == 0;
+    return strcmp(&shstrtab[SWAP(shdr->sh_name)], "__xen_guest") == 0;
 }
 
 static const char *xen_guest_lookup(struct domain_setup_info *dsi, int type)
@@ -157,11 +217,11 @@ static int is_xen_elfnote_section(const 
 {
     Elf_Note *note;
 
-    if ( shdr->sh_type != SHT_NOTE )
-        return 0;
-
-    for ( note = (Elf_Note *)(image + shdr->sh_offset);
-          note < (Elf_Note *)(image + shdr->sh_offset + shdr->sh_size);
+    if ( SWAP(shdr->sh_type) != SHT_NOTE )
+        return 0;
+
+    for ( note = (Elf_Note *)(image + SWAP(shdr->sh_offset));
+          note < (Elf_Note *)(image + SWAP(shdr->sh_offset) + SWAP(shdr->sh_size));
           note = ELFNOTE_NEXT(note) )
     {
         if ( !strncmp(ELFNOTE_NAME(note), "Xen", 4) )
@@ -254,61 +314,75 @@ static int parseelfimage(const char *ima
         return -EINVAL;
     }
 
+    SET_NOSWAP  /* Default is no byte swapping. */
+    if(ehdr->e_ident[EI_DATA] != ELFDATA)
+    {
+#if defined(__ia64__)
+        if(ehdr->e_ident[EI_DATA] != ELFDATA2MSB)
+        {
+            ERROR("Kernel not a Xen-compatible Elf image.");
+            return -EINVAL;
+        }
+        SET_SWAP  /* Switch on byte swapping. */
+#else /* defined(__ia64__) */
+        ERROR("Kernel not a Xen-compatible Elf image.");
+        return -EINVAL;
+#endif /* defined(__ia64__) */
+    }
     if ( (ehdr->e_ident[EI_CLASS] != ELFCLASS) ||
-         (ehdr->e_machine != ELFMACHINE) ||
-         (ehdr->e_ident[EI_DATA] != ELFDATA) ||
-         (ehdr->e_type != ET_EXEC) )
+         (SWAP(ehdr->e_machine) != ELFMACHINE) ||
+         (SWAP(ehdr->e_type) != ET_EXEC) )
     {
         ERROR("Kernel not a Xen-compatible Elf image.");
         return -EINVAL;
     }
 
-    if ( (ehdr->e_phoff + (ehdr->e_phnum*ehdr->e_phentsize)) > image_len )
+    if ( (SWAP(ehdr->e_phoff) + (SWAP(ehdr->e_phnum)*SWAP(ehdr->e_phentsize))) > image_len )
     {
         ERROR("ELF program headers extend beyond end of image.");
         return -EINVAL;
     }
 
-    if ( (ehdr->e_shoff + (ehdr->e_shnum*ehdr->e_shentsize)) > image_len )
+    if ( (SWAP(ehdr->e_shoff) + (SWAP(ehdr->e_shnum)*SWAP(ehdr->e_shentsize))) > image_len )
     {
         ERROR("ELF section headers extend beyond end of image.");
         return -EINVAL;
     }
 
+
     /* Find the section-header strings table. */
-    if ( ehdr->e_shstrndx == SHN_UNDEF )
+    if ( SWAP(ehdr->e_shstrndx) == SHN_UNDEF )
     {
         ERROR("ELF image has no section-header strings table (shstrtab).");
         return -EINVAL;
     }
-    shdr = (Elf_Shdr *)(image + ehdr->e_shoff +
-                        (ehdr->e_shstrndx*ehdr->e_shentsize));
-    shstrtab = image + shdr->sh_offset;
+    shdr = (Elf_Shdr *)(image + SWAP(ehdr->e_shoff) +
+                        (SWAP(ehdr->e_shstrndx)*SWAP(ehdr->e_shentsize)));
+    shstrtab = image + SWAP(shdr->sh_offset);
 
     dsi->__elfnote_section = NULL;
     dsi->__xen_guest_string = NULL;
 
     /* Look for .notes segment containing at least one Xen note */
-    for ( h = 0; h < ehdr->e_shnum; h++ )
-    {
-        shdr = (Elf_Shdr *)(image + ehdr->e_shoff + (h*ehdr->e_shentsize));
+    for ( h = 0; h < SWAP(ehdr->e_shnum); h++ )
+    {
+        shdr = (Elf_Shdr *)(image + SWAP(ehdr->e_shoff) + (h*SWAP(ehdr->e_shentsize)));
         if ( !is_xen_elfnote_section(image, shdr) )
             continue;
-        dsi->__elfnote_section = (void *)image + shdr->sh_offset;
+        dsi->__elfnote_section = (void *)image + SWAP(shdr->sh_offset);
         dsi->__elfnote_section_end =
-            (void *)image + shdr->sh_offset + shdr->sh_size;
+            (void *)image + SWAP(shdr->sh_offset) + SWAP(shdr->sh_size);
         break;
     }
-
     /* Fall back to looking for the special '__xen_guest' section. */
     if ( dsi->__elfnote_section == NULL )
     {
-        for ( h = 0; h < ehdr->e_shnum; h++ )
-        {
-            shdr = (Elf_Shdr *)(image + ehdr->e_shoff + (h*ehdr->e_shentsize));
+        for ( h = 0; h < SWAP(ehdr->e_shnum); h++ )
+        {
+            shdr = (Elf_Shdr *)(image + SWAP(ehdr->e_shoff) + (h*SWAP(ehdr->e_shentsize)));
             if ( is_xen_guest_section(shdr, shstrtab) )
             {
-                dsi->__xen_guest_string = (char *)image + shdr->sh_offset;
+                dsi->__xen_guest_string = (char *)image + SWAP(shdr->sh_offset);
                 break;
             }
         }
@@ -368,7 +442,6 @@ static int parseelfimage(const char *ima
                 dsi->pae_kernel = PAEKERN_extended_cr3;
         }
     }
-
     /* Initial guess for v_start is 0 if it is not explicitly defined. */
     dsi->v_start =
         xen_elfnote_numeric(dsi, XEN_ELFNOTE_VIRT_BASE, &virt_base_defined);
@@ -393,34 +466,29 @@ static int parseelfimage(const char *ima
         else
             dsi->elf_paddr_offset = dsi->v_start;
     }
-
     if ( elf_pa_off_defined && !virt_base_defined )
     {
         ERROR("Neither ELF_PADDR_OFFSET nor VIRT_BASE found in ELF "
               " notes or __xen_guest section.");
         return -EINVAL;
     }
-
-    for ( h = 0; h < ehdr->e_phnum; h++ )
-    {
-        phdr = (Elf_Phdr *)(image + ehdr->e_phoff + (h*ehdr->e_phentsize));
+    for ( h = 0; h < SWAP(ehdr->e_phnum); h++ )
+    {
+        phdr = (Elf_Phdr *)(image + SWAP(ehdr->e_phoff) + (h*SWAP(ehdr->e_phentsize)));
         if ( !is_loadable_phdr(phdr) )
             continue;
-        vaddr = phdr->p_paddr - dsi->elf_paddr_offset + dsi->v_start;
-        if ( (vaddr + phdr->p_memsz) < vaddr )
+        vaddr = SWAP(phdr->p_paddr) - dsi->elf_paddr_offset + dsi->v_start;
+        if ( (vaddr + SWAP(phdr->p_memsz)) < vaddr )
         {
             ERROR("ELF program header %d is too large.", h);
             return -EINVAL;
         }
-
         if ( vaddr < kernstart )
             kernstart = vaddr;
-        if ( (vaddr + phdr->p_memsz) > kernend )
-            kernend = vaddr + phdr->p_memsz;
-    }
-
-    dsi->v_kernentry = ehdr->e_entry;
-
+        if ( (vaddr + SWAP(phdr->p_memsz)) > kernend )
+            kernend = vaddr + SWAP(phdr->p_memsz);
+    }
+    dsi->v_kernentry = SWAP(ehdr->e_entry);
     virt_entry =
         xen_elfnote_numeric(dsi, XEN_ELFNOTE_ENTRY, &virt_entry_defined);
     if ( virt_entry_defined )
@@ -434,7 +502,6 @@ static int parseelfimage(const char *ima
         ERROR("ELF start or entries are out of bounds.");
         return -EINVAL;
     }
-
     p = xen_elfnote_string(dsi, XEN_ELFNOTE_BSD_SYMTAB);
     if ( p != NULL && strncmp(p, "yes", 3) == 0 )
         dsi->load_symtab = 1;
@@ -460,42 +527,39 @@ loadelfimage(
     char         *va;
     unsigned long pa, done, chunksz;
 
-    for ( h = 0; h < ehdr->e_phnum; h++ )
-    {
-        phdr = (Elf_Phdr *)(image + ehdr->e_phoff + (h*ehdr->e_phentsize));
+    for ( h = 0; h < SWAP(ehdr->e_phnum); h++ )
+    {
+        phdr = (Elf_Phdr *)(image + SWAP(ehdr->e_phoff) + (h*SWAP(ehdr->e_phentsize)));
         if ( !is_loadable_phdr(phdr) )
             continue;
-
-        for ( done = 0; done < phdr->p_filesz; done += chunksz )
-        {
-            pa = (phdr->p_paddr + done) - dsi->elf_paddr_offset;
+        for ( done = 0; done < SWAP(phdr->p_filesz); done += chunksz )
+        {
+            pa = (SWAP(phdr->p_paddr) + done) - dsi->elf_paddr_offset;
             va = xc_map_foreign_range(
                 xch, dom, PAGE_SIZE, PROT_WRITE, parray[pa>>PAGE_SHIFT]);
             if ( va == NULL )
                 return -1;
-            chunksz = phdr->p_filesz - done;
+            chunksz = SWAP(phdr->p_filesz) - done;
             if ( chunksz > (PAGE_SIZE - (pa & (PAGE_SIZE-1))) )
                 chunksz = PAGE_SIZE - (pa & (PAGE_SIZE-1));
             memcpy(va + (pa & (PAGE_SIZE-1)),
-                   image + phdr->p_offset + done, chunksz);
+                   image + SWAP(phdr->p_offset) + done, chunksz);
             munmap(va, PAGE_SIZE);
         }
-
-        for ( ; done < phdr->p_memsz; done += chunksz )
-        {
-            pa = (phdr->p_paddr + done) - dsi->elf_paddr_offset;
+        for ( ; done < SWAP(phdr->p_memsz); done += chunksz )
+        {
+            pa = (SWAP(phdr->p_paddr) + done) - dsi->elf_paddr_offset;
             va = xc_map_foreign_range(
                 xch, dom, PAGE_SIZE, PROT_WRITE, parray[pa>>PAGE_SHIFT]);
             if ( va == NULL )
                 return -1;
-            chunksz = phdr->p_memsz - done;
+            chunksz = SWAP(phdr->p_memsz) - done;
             if ( chunksz > (PAGE_SIZE - (pa & (PAGE_SIZE-1))) )
                 chunksz = PAGE_SIZE - (pa & (PAGE_SIZE-1));
             memset(va + (pa & (PAGE_SIZE-1)), 0, chunksz);
             munmap(va, PAGE_SIZE);
         }
     }
-
     loadelfsymtab(image, xch, dom, parray, dsi);
 
     return 0;
@@ -518,7 +582,7 @@ loadelfsymtab(
         return 0;
 
     p = malloc(sizeof(int) + sizeof(Elf_Ehdr) +
-               ehdr->e_shnum * sizeof(Elf_Shdr));
+               SWAP(ehdr->e_shnum) * sizeof(Elf_Shdr));
     if (p == NULL)
         return 0;
 
@@ -527,42 +591,42 @@ loadelfsymtab(
     maxva += sizeof(int);
     dsi->symtab_addr = maxva;
     dsi->symtab_len = 0;
-    maxva += sizeof(Elf_Ehdr) + ehdr->e_shnum * sizeof(Elf_Shdr);
+    maxva += sizeof(Elf_Ehdr) + SWAP(ehdr->e_shnum) * sizeof(Elf_Shdr);
     maxva = (maxva + ELFROUND - 1) & ~(ELFROUND - 1);
 
     shdr = (Elf_Shdr *)(p + sizeof(int) + sizeof(Elf_Ehdr));
-    memcpy(shdr, image + ehdr->e_shoff, ehdr->e_shnum * sizeof(Elf_Shdr));
-
-    for ( h = 0; h < ehdr->e_shnum; h++ )
-    {
-        if ( shdr[h].sh_type == SHT_STRTAB )
+    memcpy(shdr, image + SWAP(ehdr->e_shoff), SWAP(ehdr->e_shnum) * sizeof(Elf_Shdr));
+
+    for ( h = 0; h < SWAP(ehdr->e_shnum); h++ )
+    {
+        if ( SWAP(shdr[h].sh_type) == SHT_STRTAB )
         {
             /* Look for a strtab @i linked to symtab @h. */
-            for ( i = 0; i < ehdr->e_shnum; i++ )
-                if ( (shdr[i].sh_type == SHT_SYMTAB) &&
-                     (shdr[i].sh_link == h) )
+            for ( i = 0; i < SWAP(ehdr->e_shnum); i++ )
+                if ( (SWAP(shdr[i].sh_type) == SHT_SYMTAB) &&
+                     (SWAP(shdr[i].sh_link) == h) )
                     break;
             /* Skip symtab @h if we found no corresponding strtab @i. */
-            if ( i == ehdr->e_shnum )
+            if ( i == SWAP(ehdr->e_shnum) )
             {
                 shdr[h].sh_offset = 0;
                 continue;
             }
         }
 
-        if ( (shdr[h].sh_type == SHT_STRTAB) ||
-             (shdr[h].sh_type == SHT_SYMTAB) )
+        if ( (SWAP(shdr[h].sh_type) == SHT_STRTAB) ||
+             (SWAP(shdr[h].sh_type) == SHT_SYMTAB) )
         {
             if ( parray != NULL )
-                xc_map_memcpy(maxva, image + shdr[h].sh_offset,
-                              shdr[h].sh_size,
+                xc_map_memcpy(maxva, image + SWAP(shdr[h].sh_offset),
+                              SWAP(shdr[h].sh_size),
                               xch, dom, parray, dsi->v_start);
 
             /* Mangled to be based on ELF header location. */
             shdr[h].sh_offset = maxva - dsi->symtab_addr;
 
-            dsi->symtab_len += shdr[h].sh_size;
-            maxva += shdr[h].sh_size;
+            dsi->symtab_len += SWAP(shdr[h].sh_size);
+            maxva += SWAP(shdr[h].sh_size);
             maxva = (maxva + ELFROUND - 1) & ~(ELFROUND - 1);
         }
 
@@ -588,7 +652,7 @@ loadelfsymtab(
 
         /* Copy total length, crafted ELF header and section header table */
         xc_map_memcpy(symva, p, sizeof(int) + sizeof(Elf_Ehdr) +
-                   ehdr->e_shnum * sizeof(Elf_Shdr), xch, dom, parray,
+                   SWAP(ehdr->e_shnum) * sizeof(Elf_Shdr), xch, dom, parray,
                    dsi->v_start);
     }
 

[-- Attachment #3: Type: text/plain, Size: 152 bytes --]

_______________________________________________
Xen-ia64-devel mailing list
Xen-ia64-devel@lists.xensource.com
http://lists.xensource.com/xen-ia64-devel

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2006-11-28 11:01 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-11-22 12:32 [RFC][PATCH] Supporting MSB-domU on ia64 Xen Dietmar Hahn
2006-11-28  6:25 ` Dietmar Hahn
2006-11-28  8:34   ` Gerd Hoffmann
2006-11-28 11:01     ` Dietmar Hahn
2006-11-28  9:20   ` Keir Fraser

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.