* [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.