All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH RFC 0/2] s390x: Make the s390-ccw BIOS relocatable
@ 2015-03-05 11:02 Thomas Huth
  2015-03-05 11:02 ` [Qemu-devel] [PATCH RFC 1/2] elf-loader: Provide the possibility to relocate s390 ELF files Thomas Huth
                   ` (2 more replies)
  0 siblings, 3 replies; 6+ messages in thread
From: Thomas Huth @ 2015-03-05 11:02 UTC (permalink / raw)
  To: qemu-devel; +Cc: agraf, Thomas Huth

Currently, our s390-ccw.img sits at the fix address 126 MiB in memory.
This has two big disadvantages: 1) We can not start guests with less
than 128 MiB RAM and 2) if the guest uses a really huge ramdisk > 126 MiB,
the s390-ccw BIOS gets overwritten and the boot silently crashes.

These two patches now fix these problems by relocating the s390-ccw
BIOS to the end of the RAM. The basic idea here is to compile the
BIOS with the "-fpie" compiler option to create position independent
code. Sounds easy at a first glance - however, with -fpie, we only
get position independent _code_ - and a so called GOT (global offset
table) which contains absolute references to global variables again
(this is normally needed for supporting dynamic libraries - in our
s390-ccw BIOS, it's just bad luck that we get a GOT).

So to be able to really move around our s390-ccw.img in RAM, we've got
to relocate the entries in the GOT, too. This is what the first patch
is good for. I've changed the ELF loader there to parse the reloc section
of the ELF file. I only included the bare minimum of relocation types
(R_390_RELATIVE) in the patch so far, but this can easily be extended
in case we need more (with different compiler version etc.).

The second patch then adds the required changes to the s390-ccw BIOS
Makefile and our s390 ipl code in QEMU.

Now I'd like to get some feedback on this approach: Is it ok to extend
the ELF loader this way? Does anybody have better/nicer ideas to solve
the problem of a relocatable BIOS?

Thanks for any insights!

Thomas Huth (2):
  elf-loader: Provide the possibility to relocate s390 ELF files
  s390/bios: Make the s390-ccw.img relocatable

 hw/core/loader.c          |    2 +
 hw/s390x/ipl.c            |   23 +++++++++++++++-
 include/elf.h             |    2 +
 include/hw/elf_ops.h      |   60 +++++++++++++++++++++++++++++++++++++++++++++
 pc-bios/s390-ccw/Makefile |   11 ++++---
 5 files changed, 91 insertions(+), 7 deletions(-)

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

* [Qemu-devel] [PATCH RFC 1/2] elf-loader: Provide the possibility to relocate s390 ELF files
  2015-03-05 11:02 [Qemu-devel] [PATCH RFC 0/2] s390x: Make the s390-ccw BIOS relocatable Thomas Huth
@ 2015-03-05 11:02 ` Thomas Huth
  2015-03-05 11:02 ` [Qemu-devel] [PATCH RFC 2/2] s390/bios: Make the s390-ccw.img relocatable Thomas Huth
  2015-03-05 11:10 ` [Qemu-devel] [PATCH RFC 0/2] s390x: Make the s390-ccw BIOS relocatable Alexander Graf
  2 siblings, 0 replies; 6+ messages in thread
From: Thomas Huth @ 2015-03-05 11:02 UTC (permalink / raw)
  To: qemu-devel; +Cc: agraf, Thomas Huth

On s390, we would like to load our "BIOS" s390-ccw.img to the end of the
RAM. Therefor we need the possibility to relocate the ELF file so that
it can also run from different addresses. This patch adds the necessary
code to the QEMU ELF loader function.

Signed-off-by: Thomas Huth <thuth@linux.vnet.ibm.com>
---
 hw/core/loader.c     |    2 +
 include/elf.h        |    2 +
 include/hw/elf_ops.h |   60 ++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 64 insertions(+), 0 deletions(-)

diff --git a/hw/core/loader.c b/hw/core/loader.c
index e45dc0b..76d8aca 100644
--- a/hw/core/loader.c
+++ b/hw/core/loader.c
@@ -297,6 +297,7 @@ static void *load_at(int fd, int offset, int size)
 #undef elf_phdr
 #undef elf_shdr
 #undef elf_sym
+#undef elf_rela
 #undef elf_note
 #undef elf_word
 #undef elf_sword
@@ -307,6 +308,7 @@ static void *load_at(int fd, int offset, int size)
 #define elf_note	elf64_note
 #define elf_shdr	elf64_shdr
 #define elf_sym		elf64_sym
+#define elf_rela        elf64_rela
 #define elf_word        uint64_t
 #define elf_sword        int64_t
 #define bswapSZs	bswap64s
diff --git a/include/elf.h b/include/elf.h
index a516584..3e75f05 100644
--- a/include/elf.h
+++ b/include/elf.h
@@ -1508,6 +1508,7 @@ struct elf32_fdpic_loadmap {
 #define elf_shdr	elf32_shdr
 #define elf_sym		elf32_sym
 #define elf_addr_t	Elf32_Off
+#define elf_rela  elf32_rela
 
 #ifdef ELF_USES_RELOCA
 # define ELF_RELOC      Elf32_Rela
@@ -1523,6 +1524,7 @@ struct elf32_fdpic_loadmap {
 #define elf_shdr	elf64_shdr
 #define elf_sym		elf64_sym
 #define elf_addr_t	Elf64_Off
+#define elf_rela  elf64_rela
 
 #ifdef ELF_USES_RELOCA
 # define ELF_RELOC      Elf64_Rela
diff --git a/include/hw/elf_ops.h b/include/hw/elf_ops.h
index a517753..8bff1f7 100644
--- a/include/hw/elf_ops.h
+++ b/include/hw/elf_ops.h
@@ -182,6 +182,64 @@ static int glue(load_symbols, SZ)(struct elfhdr *ehdr, int fd, int must_swab,
     return -1;
 }
 
+static int glue(elf_reloc, SZ)(struct elfhdr *ehdr, int fd, int must_swab,
+                               uint64_t (*translate_fn)(void *, uint64_t),
+                               void *translate_opaque, uint8_t *data,
+                               struct elf_phdr *ph, int elf_machine)
+{
+    struct elf_shdr *reltab, *shdr_table = NULL;
+    struct elf_rela *rels = NULL;
+    int nrels, i, ret = -1;
+    void *addr;
+
+    shdr_table = load_at(fd, ehdr->e_shoff,
+                         sizeof(struct elf_shdr) * ehdr->e_shnum);
+    if (!shdr_table) {
+        return -1;
+    }
+    if (must_swab) {
+        for (i = 0; i < ehdr->e_shnum; i++) {
+            glue(bswap_shdr, SZ)(shdr_table + i);
+        }
+    }
+
+    reltab = glue(find_section, SZ)(shdr_table, ehdr->e_shnum, SHT_RELA);
+    if (!reltab) {
+        goto fail;
+    }
+    rels = load_at(fd, reltab->sh_offset, reltab->sh_size);
+    if (!rels) {
+        goto fail;
+    }
+    nrels = reltab->sh_size / sizeof(struct elf_rela);
+
+    for (i = 0; i < nrels; i++) {
+        if (rels[i].r_offset < ph->p_vaddr ||
+            rels[i].r_offset >= ph->p_vaddr + ph->p_filesz) {
+            continue;
+        }
+        addr = &data[rels[i].r_offset - ph->p_vaddr];
+        switch (elf_machine) {
+        case EM_S390:
+            switch (rels[i].r_info) {
+            case R_390_RELATIVE:
+                *(elf_word *)addr = translate_fn(translate_opaque,
+                                                 *(elf_word *)addr);
+                break;
+            default:
+                fprintf(stderr, "Unsupported relocation type %i!\n",
+                        (int)rels[i].r_info);
+            }
+        }
+    }
+
+    ret = 0;
+fail:
+    g_free(rels);
+    g_free(shdr_table);
+    return ret;
+}
+
 static int glue(load_elf, SZ)(const char *name, int fd,
                               uint64_t (*translate_fn)(void *, uint64_t),
                               void *translate_opaque,
@@ -271,6 +329,8 @@ static int glue(load_elf, SZ)(const char *name, int fd,
                linked at the wrong physical address.  */
             if (translate_fn) {
                 addr = translate_fn(translate_opaque, ph->p_paddr);
+                glue(elf_reloc, SZ)(&ehdr, fd, must_swab,  translate_fn,
+                                    translate_opaque, data, ph, elf_machine);
             } else {
                 addr = ph->p_paddr;
             }
-- 
1.7.1

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

* [Qemu-devel] [PATCH RFC 2/2] s390/bios: Make the s390-ccw.img relocatable
  2015-03-05 11:02 [Qemu-devel] [PATCH RFC 0/2] s390x: Make the s390-ccw BIOS relocatable Thomas Huth
  2015-03-05 11:02 ` [Qemu-devel] [PATCH RFC 1/2] elf-loader: Provide the possibility to relocate s390 ELF files Thomas Huth
@ 2015-03-05 11:02 ` Thomas Huth
  2015-03-05 11:10 ` [Qemu-devel] [PATCH RFC 0/2] s390x: Make the s390-ccw BIOS relocatable Alexander Graf
  2 siblings, 0 replies; 6+ messages in thread
From: Thomas Huth @ 2015-03-05 11:02 UTC (permalink / raw)
  To: qemu-devel; +Cc: agraf, Thomas Huth

The current bios sits at location 0x7e00000 in the guest RAM
and thus prevents loading of bigger ramdisks. By making the
image relocatable we can move it to the end of the RAM so that
it is getting out of the way.

Signed-off-by: Thomas Huth <thuth@linux.vnet.ibm.com>
---
 hw/s390x/ipl.c            |   23 +++++++++++++++++++++--
 pc-bios/s390-ccw/Makefile |   11 ++++++-----
 2 files changed, 27 insertions(+), 7 deletions(-)

diff --git a/hw/s390x/ipl.c b/hw/s390x/ipl.c
index b57adbd..ab7fd8a 100644
--- a/hw/s390x/ipl.c
+++ b/hw/s390x/ipl.c
@@ -14,6 +14,7 @@
 #include "sysemu/sysemu.h"
 #include "cpu.h"
 #include "elf.h"
+#include "exec/ram_addr.h"
 #include "hw/loader.h"
 #include "hw/sysbus.h"
 #include "hw/s390x/virtio-ccw.h"
@@ -95,6 +96,16 @@ static const VMStateDescription vmstate_ipl = {
      }
 };
 
+static uint64_t bios_translate_addr(void *opaque, uint64_t srcaddr)
+{
+    uint64_t dstaddr = (uint64_t)opaque;
+    /*
+     * Assuming that our s390-ccw.img was linked for starting at address 0,
+     * we can simply add the destination address for the final location
+     */
+    return srcaddr + dstaddr;
+}
+
 static int s390_ipl_init(SysBusDevice *dev)
 {
     S390IPLState *ipl = S390_IPL(dev);
@@ -109,6 +120,8 @@ static int s390_ipl_init(SysBusDevice *dev)
      * even if an external kernel has been defined.
      */
     if (!ipl->kernel || ipl->enforce_bios) {
+        uint64_t fwbase = (MIN(ram_size, 0x80000000U) - 0x200000) & ~0xffffUL;
+
         if (bios_name == NULL) {
             bios_name = ipl->firmware;
         }
@@ -118,9 +131,15 @@ static int s390_ipl_init(SysBusDevice *dev)
             hw_error("could not find stage1 bootloader\n");
         }
 
-        bios_size = load_elf(bios_filename, NULL, NULL, &ipl->bios_start_addr,
+        bios_size = load_elf(bios_filename, bios_translate_addr,
+                             (void *)fwbase, &ipl->bios_start_addr,
                              NULL, NULL, 1, ELF_MACHINE, 0);
-        if (bios_size < 0) {
+
+        if (bios_size > 0) {
+            /* Adjust ELF start address to final location */
+            ipl->bios_start_addr += fwbase;
+        } else {
+            /* Try to load non-ELF file (e.g. s390-zipl.rom) */
             bios_size = load_image_targphys(bios_filename, ZIPL_IMAGE_START,
                                             4096);
             ipl->bios_start_addr = ZIPL_IMAGE_START;
diff --git a/pc-bios/s390-ccw/Makefile b/pc-bios/s390-ccw/Makefile
index ad55a14..009bb8d 100644
--- a/pc-bios/s390-ccw/Makefile
+++ b/pc-bios/s390-ccw/Makefile
@@ -9,10 +9,9 @@ $(call set-vpath, $(SRC_PATH)/pc-bios/s390-ccw)
 
 .PHONY : all clean build-all
 
-OBJECTS=main.o bootmap.o sclp-ascii.o virtio.o start.o
-CFLAGS += -fno-stack-protector
-# XXX find a more clever to locate the bootloader
-LDFLAGS += -Wl,-Ttext,0x7e00000,-Tbss,0x7f00000 -nostdlib
+OBJECTS = start.o main.o bootmap.o sclp-ascii.o virtio.o
+CFLAGS += -fPIE -fno-stack-protector -ffreestanding
+LDFLAGS += -Wl,-pie -nostdlib
 
 build-all: s390-ccw.img
 
@@ -20,7 +19,9 @@ s390-ccw.elf: $(OBJECTS)
 	$(call quiet-command,$(CC) $(LDFLAGS) -o $@ $(OBJECTS),"  Building $(TARGET_DIR)$@")
 
 s390-ccw.img: s390-ccw.elf
-	$(call quiet-command,strip $< -o $@,"  Stripping $(TARGET_DIR)$@")
+	$(call quiet-command,strip --strip-unneeded $< -o $@,"  Stripping $(TARGET_DIR)$@")
+
+$(OBJECTS): Makefile
 
 clean:
 	rm -f *.o *.d *.img *.elf *~
-- 
1.7.1

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

* Re: [Qemu-devel] [PATCH RFC 0/2] s390x: Make the s390-ccw BIOS relocatable
  2015-03-05 11:02 [Qemu-devel] [PATCH RFC 0/2] s390x: Make the s390-ccw BIOS relocatable Thomas Huth
  2015-03-05 11:02 ` [Qemu-devel] [PATCH RFC 1/2] elf-loader: Provide the possibility to relocate s390 ELF files Thomas Huth
  2015-03-05 11:02 ` [Qemu-devel] [PATCH RFC 2/2] s390/bios: Make the s390-ccw.img relocatable Thomas Huth
@ 2015-03-05 11:10 ` Alexander Graf
  2015-03-05 12:43   ` Christian Borntraeger
  2 siblings, 1 reply; 6+ messages in thread
From: Alexander Graf @ 2015-03-05 11:10 UTC (permalink / raw)
  To: Thomas Huth, qemu-devel



On 05.03.15 12:02, Thomas Huth wrote:
> Currently, our s390-ccw.img sits at the fix address 126 MiB in memory.
> This has two big disadvantages: 1) We can not start guests with less
> than 128 MiB RAM and 2) if the guest uses a really huge ramdisk > 126 MiB,
> the s390-ccw BIOS gets overwritten and the boot silently crashes.
> 
> These two patches now fix these problems by relocating the s390-ccw
> BIOS to the end of the RAM. The basic idea here is to compile the
> BIOS with the "-fpie" compiler option to create position independent
> code. Sounds easy at a first glance - however, with -fpie, we only
> get position independent _code_ - and a so called GOT (global offset
> table) which contains absolute references to global variables again
> (this is normally needed for supporting dynamic libraries - in our
> s390-ccw BIOS, it's just bad luck that we get a GOT).
> 
> So to be able to really move around our s390-ccw.img in RAM, we've got
> to relocate the entries in the GOT, too. This is what the first patch
> is good for. I've changed the ELF loader there to parse the reloc section
> of the ELF file. I only included the bare minimum of relocation types
> (R_390_RELATIVE) in the patch so far, but this can easily be extended
> in case we need more (with different compiler version etc.).
> 
> The second patch then adds the required changes to the s390-ccw BIOS
> Makefile and our s390 ipl code in QEMU.
> 
> Now I'd like to get some feedback on this approach: Is it ok to extend
> the ELF loader this way? Does anybody have better/nicer ideas to solve
> the problem of a relocatable BIOS?
> 
> Thanks for any insights!

I think the approach is perfectly valid and good :)


Alex

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

* Re: [Qemu-devel] [PATCH RFC 0/2] s390x: Make the s390-ccw BIOS relocatable
  2015-03-05 11:10 ` [Qemu-devel] [PATCH RFC 0/2] s390x: Make the s390-ccw BIOS relocatable Alexander Graf
@ 2015-03-05 12:43   ` Christian Borntraeger
  2015-03-05 12:49     ` Alexander Graf
  0 siblings, 1 reply; 6+ messages in thread
From: Christian Borntraeger @ 2015-03-05 12:43 UTC (permalink / raw)
  To: Alexander Graf, Thomas Huth, qemu-devel, Paolo Bonzini

Am 05.03.2015 um 12:10 schrieb Alexander Graf:
> 
> 
> On 05.03.15 12:02, Thomas Huth wrote:
>> Currently, our s390-ccw.img sits at the fix address 126 MiB in memory.
>> This has two big disadvantages: 1) We can not start guests with less
>> than 128 MiB RAM and 2) if the guest uses a really huge ramdisk > 126 MiB,
>> the s390-ccw BIOS gets overwritten and the boot silently crashes.
>>
>> These two patches now fix these problems by relocating the s390-ccw
>> BIOS to the end of the RAM. The basic idea here is to compile the
>> BIOS with the "-fpie" compiler option to create position independent
>> code. Sounds easy at a first glance - however, with -fpie, we only
>> get position independent _code_ - and a so called GOT (global offset
>> table) which contains absolute references to global variables again
>> (this is normally needed for supporting dynamic libraries - in our
>> s390-ccw BIOS, it's just bad luck that we get a GOT).
>>
>> So to be able to really move around our s390-ccw.img in RAM, we've got
>> to relocate the entries in the GOT, too. This is what the first patch
>> is good for. I've changed the ELF loader there to parse the reloc section
>> of the ELF file. I only included the bare minimum of relocation types
>> (R_390_RELATIVE) in the patch so far, but this can easily be extended
>> in case we need more (with different compiler version etc.).
>>
>> The second patch then adds the required changes to the s390-ccw BIOS
>> Makefile and our s390 ipl code in QEMU.
>>
>> Now I'd like to get some feedback on this approach: Is it ok to extend
>> the ELF loader this way? Does anybody have better/nicer ideas to solve
>> the problem of a relocatable BIOS?
>>
>> Thanks for any insights!
> 
> I think the approach is perfectly valid and good :)

Yes, looks good. It relocated much higher, but not beyond 2GB, and it can
now handle guests < 128MB.

I can take these patches via the s390 tree. 

Would be good if somebody else (Paolo,Alex ??)
could Ack the change in include/hw/elf_ops.h.

Christian

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

* Re: [Qemu-devel] [PATCH RFC 0/2] s390x: Make the s390-ccw BIOS relocatable
  2015-03-05 12:43   ` Christian Borntraeger
@ 2015-03-05 12:49     ` Alexander Graf
  0 siblings, 0 replies; 6+ messages in thread
From: Alexander Graf @ 2015-03-05 12:49 UTC (permalink / raw)
  To: Christian Borntraeger, Thomas Huth, qemu-devel, Paolo Bonzini



On 05.03.15 13:43, Christian Borntraeger wrote:
> Am 05.03.2015 um 12:10 schrieb Alexander Graf:
>>
>>
>> On 05.03.15 12:02, Thomas Huth wrote:
>>> Currently, our s390-ccw.img sits at the fix address 126 MiB in memory.
>>> This has two big disadvantages: 1) We can not start guests with less
>>> than 128 MiB RAM and 2) if the guest uses a really huge ramdisk > 126 MiB,
>>> the s390-ccw BIOS gets overwritten and the boot silently crashes.
>>>
>>> These two patches now fix these problems by relocating the s390-ccw
>>> BIOS to the end of the RAM. The basic idea here is to compile the
>>> BIOS with the "-fpie" compiler option to create position independent
>>> code. Sounds easy at a first glance - however, with -fpie, we only
>>> get position independent _code_ - and a so called GOT (global offset
>>> table) which contains absolute references to global variables again
>>> (this is normally needed for supporting dynamic libraries - in our
>>> s390-ccw BIOS, it's just bad luck that we get a GOT).
>>>
>>> So to be able to really move around our s390-ccw.img in RAM, we've got
>>> to relocate the entries in the GOT, too. This is what the first patch
>>> is good for. I've changed the ELF loader there to parse the reloc section
>>> of the ELF file. I only included the bare minimum of relocation types
>>> (R_390_RELATIVE) in the patch so far, but this can easily be extended
>>> in case we need more (with different compiler version etc.).
>>>
>>> The second patch then adds the required changes to the s390-ccw BIOS
>>> Makefile and our s390 ipl code in QEMU.
>>>
>>> Now I'd like to get some feedback on this approach: Is it ok to extend
>>> the ELF loader this way? Does anybody have better/nicer ideas to solve
>>> the problem of a relocatable BIOS?
>>>
>>> Thanks for any insights!
>>
>> I think the approach is perfectly valid and good :)
> 
> Yes, looks good. It relocated much higher, but not beyond 2GB, and it can
> now handle guests < 128MB.
> 
> I can take these patches via the s390 tree. 
> 
> Would be good if somebody else (Paolo,Alex ??)
> could Ack the change in include/hw/elf_ops.h.

Acked-by: Alexander Graf <agraf@suse.de>


Alex

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

end of thread, other threads:[~2015-03-05 12:49 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-03-05 11:02 [Qemu-devel] [PATCH RFC 0/2] s390x: Make the s390-ccw BIOS relocatable Thomas Huth
2015-03-05 11:02 ` [Qemu-devel] [PATCH RFC 1/2] elf-loader: Provide the possibility to relocate s390 ELF files Thomas Huth
2015-03-05 11:02 ` [Qemu-devel] [PATCH RFC 2/2] s390/bios: Make the s390-ccw.img relocatable Thomas Huth
2015-03-05 11:10 ` [Qemu-devel] [PATCH RFC 0/2] s390x: Make the s390-ccw BIOS relocatable Alexander Graf
2015-03-05 12:43   ` Christian Borntraeger
2015-03-05 12:49     ` Alexander Graf

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.