On Thu, 20 Oct 2022 09:00:05 +0000 Janosch Frank <frankja@xxxxxxxxxxxxx> wrote: > A linker script has a few benefits: > - We can easily define a lowcore and load the snippet from 0x0 instead > of 0x4000 which makes asm snippets behave like c snippets > - We can easily define an invalid PGM new PSW to ensure an exit on a > guest PGM > - We can remove a lot of the offset variables from lib/s390x/snippet.h > > As we gain another step and file extension by linking, a comment > explains which file extensions are generated and why. > > Signed-off-by: Janosch Frank <frankja@xxxxxxxxxxxxx> > --- > lib/s390x/snippet.h | 14 +++++--------- > s390x/Makefile | 18 ++++++++++++++---- > s390x/mvpg-sie.c | 2 +- > s390x/pv-diags.c | 6 +++--- > s390x/snippets/asm/flat.lds | 35 +++++++++++++++++++++++++++++++++++ > 5 files changed, 58 insertions(+), 17 deletions(-) > create mode 100644 s390x/snippets/asm/flat.lds > > diff --git a/lib/s390x/snippet.h b/lib/s390x/snippet.h > index b17b2a4c..fcd04081 100644 > --- a/lib/s390x/snippet.h > +++ b/lib/s390x/snippet.h > @@ -32,8 +32,6 @@ > > #define SNIPPET_PV_TWEAK0 0x42UL > #define SNIPPET_PV_TWEAK1 0UL > -#define SNIPPET_OFF_C 0 > -#define SNIPPET_OFF_ASM 0x4000 > > > /* > @@ -57,15 +55,14 @@ static const struct psw snippet_psw = { > * @vm: VM that this function will populated, has to be initialized already > * @gbin: Snippet gbin data pointer > * @gbin_len: Length of the gbin data > - * @off: Offset from guest absolute 0x0 where snippet is copied to > */ > static inline void snippet_init(struct vm *vm, const char *gbin, > - uint64_t gbin_len, uint64_t off) > + uint64_t gbin_len) > { > uint64_t mso = vm->sblk->mso; > > /* Copy test image to guest memory */ > - memcpy((void *)mso + off, gbin, gbin_len); > + memcpy((void *)mso, gbin, gbin_len); > > /* Setup guest PSW */ > vm->sblk->gpsw = snippet_psw; > @@ -87,23 +84,22 @@ static inline void snippet_init(struct vm *vm, const char *gbin, > * @hdr: Snippet SE header data pointer > * @gbin_len: Length of the gbin data > * @hdr_len: Length of the hdr data > - * @off: Offset from guest absolute 0x0 where snippet is copied to > */ > static inline void snippet_pv_init(struct vm *vm, const char *gbin, > const char *hdr, uint64_t gbin_len, > - uint64_t hdr_len, uint64_t off) > + uint64_t hdr_len) > { > uint64_t tweak[2] = {SNIPPET_PV_TWEAK0, SNIPPET_PV_TWEAK1}; > uint64_t mso = vm->sblk->mso; > int i; > > - snippet_init(vm, gbin, gbin_len, off); > + snippet_init(vm, gbin, gbin_len); > > uv_create_guest(vm); > uv_set_se_hdr(vm->uv.vm_handle, (void *)hdr, hdr_len); > > /* Unpack works on guest addresses so we only need off */ > - uv_unpack(vm, off, gbin_len, tweak[0]); > + uv_unpack(vm, 0, gbin_len, tweak[0]); > uv_verify_load(vm); > > /* > diff --git a/s390x/Makefile b/s390x/Makefile > index 3b175015..0eaa72f4 100644 > --- a/s390x/Makefile > +++ b/s390x/Makefile > @@ -124,6 +124,13 @@ else > snippet-hdr-obj = > endif > > +# Each snippet will generate the following files (in order): \ > + *.o is a snippet that has been compiled \ > + *.ol is a snippet that has been linked \ > + *.gbin is a snippet that has been converted to binary \ > + *.gobj is the final format after converting the binary into a elf file again, \ > + it will be linked into the tests > + > # the asm/c snippets %.o have additional generated files as dependencies > $(SNIPPET_DIR)/asm/%.o: $(SNIPPET_DIR)/asm/%.S $(asm-offsets) > $(CC) $(CFLAGS) -c -nostdlib -o $@ $< > @@ -131,17 +138,20 @@ $(SNIPPET_DIR)/asm/%.o: $(SNIPPET_DIR)/asm/%.S $(asm-offsets) > $(SNIPPET_DIR)/c/%.o: $(SNIPPET_DIR)/c/%.c $(asm-offsets) > $(CC) $(CFLAGS) -c -nostdlib -o $@ $< > > -$(SNIPPET_DIR)/asm/%.gbin: $(SNIPPET_DIR)/asm/%.o > - $(OBJCOPY) -O binary -j ".rodata" -j ".text" -j ".data" -j ".bss" --set-section-flags .bss=alloc,load,contents $(patsubst %.gbin,%.o,$@) $@ > +$(SNIPPET_DIR)/asm/%.ol: $(SNIPPET_DIR)/asm/%.o > + $(CC) $(LDFLAGS) -o $@ -T $(SNIPPET_DIR)/asm/flat.lds $< > + > +$(SNIPPET_DIR)/asm/%.gbin: $(SNIPPET_DIR)/asm/%.ol > + $(OBJCOPY) -O binary -j ".rodata" -j ".lowcore" -j ".text" -j ".data" -j ".bss" --set-section-flags .bss=alloc,load,contents $< $@ > truncate -s '%4096' $@ can't you do $(CC) and $(OBJCOPY) in one step like you do for C snippets? then you don't need the .ol intermediate > > $(SNIPPET_DIR)/c/%.gbin: $(SNIPPET_DIR)/c/%.o $(snippet_lib) $(FLATLIBS) > - $(CC) $(LDFLAGS) -o $@ -T $(SRCDIR)/s390x/snippets/c/flat.lds $< $(snippet_lib) $(FLATLIBS) > + $(CC) $(LDFLAGS) -o $@ -T $(SNIPPET_DIR)/c/flat.lds $< $(snippet_lib) $(FLATLIBS) > $(OBJCOPY) -O binary -j ".rodata" -j ".lowcore" -j ".text" -j ".data" -j ".bss" --set-section-flags .bss=alloc,load,contents $@ $@ > truncate -s '%4096' $@ > > $(SNIPPET_DIR)/asm/%.hdr: $(SNIPPET_DIR)/asm/%.gbin $(HOST_KEY_DOCUMENT) > - $(GEN_SE_HEADER) -k $(HOST_KEY_DOCUMENT) -c $<,0x4000,0x00000000000000420000000000000000 --psw-addr 0x4000 -o $@ > + $(GEN_SE_HEADER) -k $(HOST_KEY_DOCUMENT) -c $<,0x0,0x00000000000000420000000000000000 --psw-addr 0x4000 -o $@ > > $(SNIPPET_DIR)/c/%.hdr: $(SNIPPET_DIR)/c/%.gbin $(HOST_KEY_DOCUMENT) > $(GEN_SE_HEADER) -k $(HOST_KEY_DOCUMENT) -c $<,0x0,0x00000000000000420000000000000000 --psw-addr 0x4000 -o $@ > diff --git a/s390x/mvpg-sie.c b/s390x/mvpg-sie.c > index 46a2edb6..17e209ad 100644 > --- a/s390x/mvpg-sie.c > +++ b/s390x/mvpg-sie.c > @@ -87,7 +87,7 @@ static void setup_guest(void) > > snippet_setup_guest(&vm, false); > snippet_init(&vm, SNIPPET_NAME_START(c, mvpg_snippet), > - SNIPPET_LEN(c, mvpg_snippet), SNIPPET_OFF_C); > + SNIPPET_LEN(c, mvpg_snippet)); > > /* Enable MVPG interpretation as we want to test KVM and not ourselves */ > vm.sblk->eca = ECA_MVPGI; > diff --git a/s390x/pv-diags.c b/s390x/pv-diags.c > index 9ced68c7..d472c994 100644 > --- a/s390x/pv-diags.c > +++ b/s390x/pv-diags.c > @@ -28,7 +28,7 @@ static void test_diag_500(void) > > snippet_pv_init(&vm, SNIPPET_NAME_START(asm, snippet_pv_diag_500), > SNIPPET_HDR_START(asm, snippet_pv_diag_500), > - size_gbin, size_hdr, SNIPPET_OFF_ASM); > + size_gbin, size_hdr); > > sie(&vm); > report(vm.sblk->icptcode == ICPT_PV_INSTR && vm.sblk->ipa == 0x8302 && > @@ -83,7 +83,7 @@ static void test_diag_288(void) > > snippet_pv_init(&vm, SNIPPET_NAME_START(asm, snippet_pv_diag_288), > SNIPPET_HDR_START(asm, snippet_pv_diag_288), > - size_gbin, size_hdr, SNIPPET_OFF_ASM); > + size_gbin, size_hdr); > > sie(&vm); > report(vm.sblk->icptcode == ICPT_PV_INSTR && vm.sblk->ipa == 0x8302 && > @@ -124,7 +124,7 @@ static void test_diag_yield(void) > > snippet_pv_init(&vm, SNIPPET_NAME_START(asm, snippet_pv_diag_yield), > SNIPPET_HDR_START(asm, snippet_pv_diag_yield), > - size_gbin, size_hdr, SNIPPET_OFF_ASM); > + size_gbin, size_hdr); > > /* 0x44 */ > report_prefix_push("0x44"); > diff --git a/s390x/snippets/asm/flat.lds b/s390x/snippets/asm/flat.lds > new file mode 100644 > index 00000000..388d7d5d > --- /dev/null > +++ b/s390x/snippets/asm/flat.lds > @@ -0,0 +1,35 @@ > +SECTIONS > +{ > + .lowcore : { > + /* Restart new PSW for booting via PSW restart. */ > + . = 0x1a0; > + QUAD(0x0000000180000000) > + QUAD(0x0000000000004000) > + /* > + * Invalid PGM new PSW so we hopefully get a code 8 > + * intercept on a PGM for PV snippets. > + */ > + . = 0x1d0; > + QUAD(0x0008000000000000) > + QUAD(0x0000000000000001) > + } > + . = 0x4000; > + .text : { > + *(.text) > + *(.text.*) > + } > + . = ALIGN(64K); > + etext = .; > + . = ALIGN(16); > + .data : { > + *(.data) > + *(.data.rel*) > + } > + . = ALIGN(16); > + .rodata : { *(.rodata) *(.rodata.*) } > + . = ALIGN(16); do you really need to ALIGN(16) right after ALIGN(64K) ? > + __bss_start = .; > + .bss : { *(.bss) } > + __bss_end = .; > + . = ALIGN(64K); why align the end? and why 64K instead of e.g. 4K? > +}