* [Qemu-devel] [PATCH v2 0/2] s390x: Make the s390-ccw BIOS relocatable @ 2015-03-09 10:12 Thomas Huth 2015-03-09 10:12 ` [Qemu-devel] [PATCH v2 1/2] elf-loader: Provide the possibility to relocate s390 ELF files Thomas Huth ` (2 more replies) 0 siblings, 3 replies; 7+ messages in thread From: Thomas Huth @ 2015-03-09 10:12 UTC (permalink / raw) To: qemu-devel; +Cc: cornelia.huck, borntraeger, 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. v2: - Fixed endianess issues in the ELF relocation function 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 | 78 +++++++++++++++++++++++++++++++++++++++++++++ pc-bios/s390-ccw/Makefile | 11 +++--- 5 files changed, 109 insertions(+), 7 deletions(-) ^ permalink raw reply [flat|nested] 7+ messages in thread
* [Qemu-devel] [PATCH v2 1/2] elf-loader: Provide the possibility to relocate s390 ELF files 2015-03-09 10:12 [Qemu-devel] [PATCH v2 0/2] s390x: Make the s390-ccw BIOS relocatable Thomas Huth @ 2015-03-09 10:12 ` Thomas Huth 2015-03-09 11:11 ` Christian Borntraeger 2015-03-09 10:12 ` [Qemu-devel] [PATCH v2 2/2] s390/bios: Make the s390-ccw.img relocatable Thomas Huth 2015-03-09 15:21 ` [Qemu-devel] [PATCH v2 0/2] s390x: Make the s390-ccw BIOS relocatable Christian Borntraeger 2 siblings, 1 reply; 7+ messages in thread From: Thomas Huth @ 2015-03-09 10:12 UTC (permalink / raw) To: qemu-devel; +Cc: cornelia.huck, borntraeger, 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 | 78 ++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 82 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..16a627b 100644 --- a/include/hw/elf_ops.h +++ b/include/hw/elf_ops.h @@ -49,6 +49,13 @@ static void glue(bswap_sym, SZ)(struct elf_sym *sym) bswap16s(&sym->st_shndx); } +static void glue(bswap_rela, SZ)(struct elf_rela *rela) +{ + bswapSZs(&rela->r_offset); + bswapSZs(&rela->r_info); + bswapSZs((elf_word *)&rela->r_addend); +} + static struct elf_shdr *glue(find_section, SZ)(struct elf_shdr *shdr_table, int n, int type) { @@ -182,6 +189,75 @@ 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; + elf_word wordval; + 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 (must_swab) { + glue(bswap_rela, SZ)(&rels[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: + wordval = *(elf_word *)addr; + if (must_swab) { + bswapSZs(&wordval); + } + wordval = translate_fn(translate_opaque, wordval); + if (must_swab) { + bswapSZs(&wordval); + } + *(elf_word *)addr = wordval; + 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 +347,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] 7+ messages in thread
* Re: [Qemu-devel] [PATCH v2 1/2] elf-loader: Provide the possibility to relocate s390 ELF files 2015-03-09 10:12 ` [Qemu-devel] [PATCH v2 1/2] elf-loader: Provide the possibility to relocate s390 ELF files Thomas Huth @ 2015-03-09 11:11 ` Christian Borntraeger 2015-03-09 13:30 ` Thomas Huth 0 siblings, 1 reply; 7+ messages in thread From: Christian Borntraeger @ 2015-03-09 11:11 UTC (permalink / raw) To: Thomas Huth, qemu-devel; +Cc: cornelia.huck, agraf Am 09.03.2015 um 11:12 schrieb 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> I think this was Acked by Alex? > --- > hw/core/loader.c | 2 + > include/elf.h | 2 + > include/hw/elf_ops.h | 78 ++++++++++++++++++++++++++++++++++++++++++++++++++ > 3 files changed, 82 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..16a627b 100644 > --- a/include/hw/elf_ops.h > +++ b/include/hw/elf_ops.h > @@ -49,6 +49,13 @@ static void glue(bswap_sym, SZ)(struct elf_sym *sym) > bswap16s(&sym->st_shndx); > } > > +static void glue(bswap_rela, SZ)(struct elf_rela *rela) > +{ > + bswapSZs(&rela->r_offset); > + bswapSZs(&rela->r_info); > + bswapSZs((elf_word *)&rela->r_addend); > +} > + > static struct elf_shdr *glue(find_section, SZ)(struct elf_shdr *shdr_table, > int n, int type) > { > @@ -182,6 +189,75 @@ 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; > + elf_word wordval; > + 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 (must_swab) { > + glue(bswap_rela, SZ)(&rels[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: > + wordval = *(elf_word *)addr; > + if (must_swab) { > + bswapSZs(&wordval); > + } > + wordval = translate_fn(translate_opaque, wordval); > + if (must_swab) { > + bswapSZs(&wordval); > + } > + *(elf_word *)addr = wordval; > + 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 +347,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; > } > ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [Qemu-devel] [PATCH v2 1/2] elf-loader: Provide the possibility to relocate s390 ELF files 2015-03-09 11:11 ` Christian Borntraeger @ 2015-03-09 13:30 ` Thomas Huth 2015-03-09 13:42 ` Alexander Graf 0 siblings, 1 reply; 7+ messages in thread From: Thomas Huth @ 2015-03-09 13:30 UTC (permalink / raw) To: Christian Borntraeger; +Cc: cornelia.huck, qemu-devel, agraf On Mon, 09 Mar 2015 12:11:49 +0100 Christian Borntraeger <borntraeger@de.ibm.com> wrote: > Am 09.03.2015 um 11:12 schrieb 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> > > I think this was Acked by Alex? Well, that was on the first version which still had endianess bugs ... Alex, does your Ack still stand for v2, too? Thomas > > --- > > hw/core/loader.c | 2 + > > include/elf.h | 2 + > > include/hw/elf_ops.h | 78 ++++++++++++++++++++++++++++++++++++++++++++++++++ > > 3 files changed, 82 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..16a627b 100644 > > --- a/include/hw/elf_ops.h > > +++ b/include/hw/elf_ops.h > > @@ -49,6 +49,13 @@ static void glue(bswap_sym, SZ)(struct elf_sym *sym) > > bswap16s(&sym->st_shndx); > > } > > > > +static void glue(bswap_rela, SZ)(struct elf_rela *rela) > > +{ > > + bswapSZs(&rela->r_offset); > > + bswapSZs(&rela->r_info); > > + bswapSZs((elf_word *)&rela->r_addend); > > +} > > + > > static struct elf_shdr *glue(find_section, SZ)(struct elf_shdr *shdr_table, > > int n, int type) > > { > > @@ -182,6 +189,75 @@ 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; > > + elf_word wordval; > > + 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 (must_swab) { > > + glue(bswap_rela, SZ)(&rels[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: > > + wordval = *(elf_word *)addr; > > + if (must_swab) { > > + bswapSZs(&wordval); > > + } > > + wordval = translate_fn(translate_opaque, wordval); > > + if (must_swab) { > > + bswapSZs(&wordval); > > + } > > + *(elf_word *)addr = wordval; > > + 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 +347,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; > > } > > > ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [Qemu-devel] [PATCH v2 1/2] elf-loader: Provide the possibility to relocate s390 ELF files 2015-03-09 13:30 ` Thomas Huth @ 2015-03-09 13:42 ` Alexander Graf 0 siblings, 0 replies; 7+ messages in thread From: Alexander Graf @ 2015-03-09 13:42 UTC (permalink / raw) To: Thomas Huth, Christian Borntraeger; +Cc: cornelia.huck, qemu-devel On 09.03.15 08:30, Thomas Huth wrote: > On Mon, 09 Mar 2015 12:11:49 +0100 > Christian Borntraeger <borntraeger@de.ibm.com> wrote: > >> Am 09.03.2015 um 11:12 schrieb 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> >> >> I think this was Acked by Alex? > > Well, that was on the first version which still had endianess bugs ... > Alex, does your Ack still stand for v2, too? > Acked-by: Alexander Graf <agraf@suse.de> Alex ^ permalink raw reply [flat|nested] 7+ messages in thread
* [Qemu-devel] [PATCH v2 2/2] s390/bios: Make the s390-ccw.img relocatable 2015-03-09 10:12 [Qemu-devel] [PATCH v2 0/2] s390x: Make the s390-ccw BIOS relocatable Thomas Huth 2015-03-09 10:12 ` [Qemu-devel] [PATCH v2 1/2] elf-loader: Provide the possibility to relocate s390 ELF files Thomas Huth @ 2015-03-09 10:12 ` Thomas Huth 2015-03-09 15:21 ` [Qemu-devel] [PATCH v2 0/2] s390x: Make the s390-ccw BIOS relocatable Christian Borntraeger 2 siblings, 0 replies; 7+ messages in thread From: Thomas Huth @ 2015-03-09 10:12 UTC (permalink / raw) To: qemu-devel; +Cc: cornelia.huck, borntraeger, 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] 7+ messages in thread
* Re: [Qemu-devel] [PATCH v2 0/2] s390x: Make the s390-ccw BIOS relocatable 2015-03-09 10:12 [Qemu-devel] [PATCH v2 0/2] s390x: Make the s390-ccw BIOS relocatable Thomas Huth 2015-03-09 10:12 ` [Qemu-devel] [PATCH v2 1/2] elf-loader: Provide the possibility to relocate s390 ELF files Thomas Huth 2015-03-09 10:12 ` [Qemu-devel] [PATCH v2 2/2] s390/bios: Make the s390-ccw.img relocatable Thomas Huth @ 2015-03-09 15:21 ` Christian Borntraeger 2 siblings, 0 replies; 7+ messages in thread From: Christian Borntraeger @ 2015-03-09 15:21 UTC (permalink / raw) To: Thomas Huth, qemu-devel; +Cc: cornelia.huck, agraf Am 09.03.2015 um 11:12 schrieb 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. > > v2: > - Fixed endianess issues in the ELF relocation function > > 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 | 78 +++++++++++++++++++++++++++++++++++++++++++++ > pc-bios/s390-ccw/Makefile | 11 +++--- > 5 files changed, 109 insertions(+), 7 deletions(-) > Applied to s390-next. Thanks ^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2015-03-09 15:21 UTC | newest] Thread overview: 7+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2015-03-09 10:12 [Qemu-devel] [PATCH v2 0/2] s390x: Make the s390-ccw BIOS relocatable Thomas Huth 2015-03-09 10:12 ` [Qemu-devel] [PATCH v2 1/2] elf-loader: Provide the possibility to relocate s390 ELF files Thomas Huth 2015-03-09 11:11 ` Christian Borntraeger 2015-03-09 13:30 ` Thomas Huth 2015-03-09 13:42 ` Alexander Graf 2015-03-09 10:12 ` [Qemu-devel] [PATCH v2 2/2] s390/bios: Make the s390-ccw.img relocatable Thomas Huth 2015-03-09 15:21 ` [Qemu-devel] [PATCH v2 0/2] s390x: Make the s390-ccw BIOS relocatable Christian Borntraeger
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).