qemu-devel
[Top][All Lists]
Advanced

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

[Qemu-devel] [PATCH 53/88] hw/core/loader: implement address translation


From: Michael Roth
Subject: [Qemu-devel] [PATCH 53/88] hw/core/loader: implement address translation in uimage loader
Date: Thu, 8 Jan 2015 11:33:57 -0600

From: Max Filippov <address@hidden>

Such address translation is needed when load address recorded in uImage
is a virtual address. When the actual load address is requested, return
untranslated address: user that needs the translated address can always
apply translation function to it and those that need it untranslated
don't need to do the inverse translation.

Add translation function pointer and its parameter to uimage_load
prototype. Update all existing users.

No user-visible functional changes.

Cc: address@hidden
Signed-off-by: Max Filippov <address@hidden>
Reviewed-by: Alexander Graf <address@hidden>
(cherry picked from commit 25bda50a0c7241dcb247483af2b7f961632020cc)
Signed-off-by: Michael Roth <address@hidden>
---
 hw/arm/boot.c              |  2 +-
 hw/core/loader.c           | 17 +++++++++++++----
 hw/m68k/an5206.c           |  3 ++-
 hw/m68k/dummy_m68k.c       |  3 ++-
 hw/m68k/mcf5208.c          |  3 ++-
 hw/microblaze/boot.c       |  3 ++-
 hw/openrisc/openrisc_sim.c |  2 +-
 hw/ppc/e500.c              |  3 ++-
 hw/ppc/ppc440_bamboo.c     |  3 ++-
 hw/xtensa/xtfpga.c         |  3 ++-
 include/hw/loader.h        |  4 +++-
 11 files changed, 32 insertions(+), 14 deletions(-)

diff --git a/hw/arm/boot.c b/hw/arm/boot.c
index 3d1f4a2..50b6c5c 100644
--- a/hw/arm/boot.c
+++ b/hw/arm/boot.c
@@ -508,7 +508,7 @@ void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info 
*info)
     entry = elf_entry;
     if (kernel_size < 0) {
         kernel_size = load_uimage(info->kernel_filename, &entry, NULL,
-                                  &is_linux);
+                                  &is_linux, NULL, NULL);
     }
     if (kernel_size < 0) {
         entry = info->loader_start + kernel_load_offset;
diff --git a/hw/core/loader.c b/hw/core/loader.c
index 2bf6b8f..8b84c12 100644
--- a/hw/core/loader.c
+++ b/hw/core/loader.c
@@ -456,7 +456,9 @@ static ssize_t gunzip(void *dst, size_t dstlen, uint8_t 
*src,
 
 /* Load a U-Boot image.  */
 static int load_uboot_image(const char *filename, hwaddr *ep, hwaddr *loadaddr,
-                            int *is_linux, uint8_t image_type)
+                            int *is_linux, uint8_t image_type,
+                            uint64_t (*translate_fn)(void *, uint64_t),
+                            void *translate_opaque)
 {
     int fd;
     int size;
@@ -490,6 +492,9 @@ static int load_uboot_image(const char *filename, hwaddr 
*ep, hwaddr *loadaddr,
     switch (hdr->ih_type) {
     case IH_TYPE_KERNEL:
         address = hdr->ih_load;
+        if (translate_fn) {
+            address = translate_fn(translate_opaque, address);
+        }
         if (loadaddr) {
             *loadaddr = hdr->ih_load;
         }
@@ -566,15 +571,19 @@ out:
 }
 
 int load_uimage(const char *filename, hwaddr *ep, hwaddr *loadaddr,
-                int *is_linux)
+                int *is_linux,
+                uint64_t (*translate_fn)(void *, uint64_t),
+                void *translate_opaque)
 {
-    return load_uboot_image(filename, ep, loadaddr, is_linux, IH_TYPE_KERNEL);
+    return load_uboot_image(filename, ep, loadaddr, is_linux, IH_TYPE_KERNEL,
+                            translate_fn, translate_opaque);
 }
 
 /* Load a ramdisk.  */
 int load_ramdisk(const char *filename, hwaddr addr, uint64_t max_sz)
 {
-    return load_uboot_image(filename, NULL, &addr, NULL, IH_TYPE_RAMDISK);
+    return load_uboot_image(filename, NULL, &addr, NULL, IH_TYPE_RAMDISK,
+                            NULL, NULL);
 }
 
 /*
diff --git a/hw/m68k/an5206.c b/hw/m68k/an5206.c
index 684496a..388420e 100644
--- a/hw/m68k/an5206.c
+++ b/hw/m68k/an5206.c
@@ -74,7 +74,8 @@ static void an5206_init(MachineState *machine)
                            NULL, NULL, 1, ELF_MACHINE, 0);
     entry = elf_entry;
     if (kernel_size < 0) {
-        kernel_size = load_uimage(kernel_filename, &entry, NULL, NULL);
+        kernel_size = load_uimage(kernel_filename, &entry, NULL, NULL,
+                                  NULL, NULL);
     }
     if (kernel_size < 0) {
         kernel_size = load_image_targphys(kernel_filename, KERNEL_LOAD_ADDR,
diff --git a/hw/m68k/dummy_m68k.c b/hw/m68k/dummy_m68k.c
index 6db1b71..fb9ca0e 100644
--- a/hw/m68k/dummy_m68k.c
+++ b/hw/m68k/dummy_m68k.c
@@ -50,7 +50,8 @@ static void dummy_m68k_init(MachineState *machine)
                                NULL, NULL, 1, ELF_MACHINE, 0);
         entry = elf_entry;
         if (kernel_size < 0) {
-            kernel_size = load_uimage(kernel_filename, &entry, NULL, NULL);
+            kernel_size = load_uimage(kernel_filename, &entry, NULL, NULL,
+                                      NULL, NULL);
         }
         if (kernel_size < 0) {
             kernel_size = load_image_targphys(kernel_filename,
diff --git a/hw/m68k/mcf5208.c b/hw/m68k/mcf5208.c
index 2ef617f..07683db 100644
--- a/hw/m68k/mcf5208.c
+++ b/hw/m68k/mcf5208.c
@@ -279,7 +279,8 @@ static void mcf5208evb_init(MachineState *machine)
                            NULL, NULL, 1, ELF_MACHINE, 0);
     entry = elf_entry;
     if (kernel_size < 0) {
-        kernel_size = load_uimage(kernel_filename, &entry, NULL, NULL);
+        kernel_size = load_uimage(kernel_filename, &entry, NULL, NULL,
+                                  NULL, NULL);
     }
     if (kernel_size < 0) {
         kernel_size = load_image_targphys(kernel_filename, 0x40000000,
diff --git a/hw/microblaze/boot.c b/hw/microblaze/boot.c
index 6bf36d0..a2843cd 100644
--- a/hw/microblaze/boot.c
+++ b/hw/microblaze/boot.c
@@ -154,7 +154,8 @@ void microblaze_load_kernel(MicroBlazeCPU *cpu, hwaddr 
ddr_base,
         if (kernel_size < 0) {
             hwaddr uentry, loadaddr;
 
-            kernel_size = load_uimage(kernel_filename, &uentry, &loadaddr, 0);
+            kernel_size = load_uimage(kernel_filename, &uentry, &loadaddr, 0,
+                                      NULL, NULL);
             boot_info.bootstrap_pc = uentry;
             high = (loadaddr + kernel_size + 3) & ~3;
         }
diff --git a/hw/openrisc/openrisc_sim.c b/hw/openrisc/openrisc_sim.c
index b2b4f9b..123cf4d 100644
--- a/hw/openrisc/openrisc_sim.c
+++ b/hw/openrisc/openrisc_sim.c
@@ -72,7 +72,7 @@ static void cpu_openrisc_load_kernel(ram_addr_t ram_size,
         entry = elf_entry;
         if (kernel_size < 0) {
             kernel_size = load_uimage(kernel_filename,
-                                      &entry, NULL, NULL);
+                                      &entry, NULL, NULL, NULL, NULL);
         }
         if (kernel_size < 0) {
             kernel_size = load_image_targphys(kernel_filename,
diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c
index 1a5b30d..c268b91 100644
--- a/hw/ppc/e500.c
+++ b/hw/ppc/e500.c
@@ -830,7 +830,8 @@ void ppce500_init(MachineState *machine, PPCE500Params 
*params)
          * Hrm. No ELF image? Try a uImage, maybe someone is giving us an
          * ePAPR compliant kernel
          */
-        kernel_size = load_uimage(filename, &bios_entry, &loadaddr, NULL);
+        kernel_size = load_uimage(filename, &bios_entry, &loadaddr, NULL,
+                                  NULL, NULL);
         if (kernel_size < 0) {
             fprintf(stderr, "qemu: could not load firmware '%s'\n", filename);
             exit(1);
diff --git a/hw/ppc/ppc440_bamboo.c b/hw/ppc/ppc440_bamboo.c
index 81a06d3..778970a 100644
--- a/hw/ppc/ppc440_bamboo.c
+++ b/hw/ppc/ppc440_bamboo.c
@@ -253,7 +253,8 @@ static void bamboo_init(MachineState *machine)
 
     /* Load kernel. */
     if (kernel_filename) {
-        success = load_uimage(kernel_filename, &entry, &loadaddr, NULL);
+        success = load_uimage(kernel_filename, &entry, &loadaddr, NULL,
+                              NULL, NULL);
         if (success < 0) {
             success = load_elf(kernel_filename, NULL, NULL, &elf_entry,
                                &elf_lowaddr, NULL, 1, ELF_MACHINE, 0);
diff --git a/hw/xtensa/xtfpga.c b/hw/xtensa/xtfpga.c
index a2dff5a..937d01e 100644
--- a/hw/xtensa/xtfpga.c
+++ b/hw/xtensa/xtfpga.c
@@ -325,7 +325,8 @@ static void lx_init(const LxBoardDesc *board, MachineState 
*machine)
         } else {
             hwaddr ep;
             int is_linux;
-            success = load_uimage(kernel_filename, &ep, NULL, &is_linux);
+            success = load_uimage(kernel_filename, &ep, NULL, &is_linux,
+                                  NULL, NULL);
             if (success > 0 && is_linux) {
                 entry_point = ep;
             } else {
diff --git a/include/hw/loader.h b/include/hw/loader.h
index 796cbf9..11b6b5a 100644
--- a/include/hw/loader.h
+++ b/include/hw/loader.h
@@ -28,7 +28,9 @@ int load_elf(const char *filename, uint64_t 
(*translate_fn)(void *, uint64_t),
 int load_aout(const char *filename, hwaddr addr, int max_sz,
               int bswap_needed, hwaddr target_page_size);
 int load_uimage(const char *filename, hwaddr *ep,
-                hwaddr *loadaddr, int *is_linux);
+                hwaddr *loadaddr, int *is_linux,
+                uint64_t (*translate_fn)(void *, uint64_t),
+                void *translate_opaque);
 
 /**
  * load_ramdisk:
-- 
1.9.1




reply via email to

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