File s390-tools-sles15sp2-43-genprotimg-boot-initial-bootloader-support.patch of Package s390-tools.18705

Subject: [PATCH] [FEAT VS1804] genprotimg: boot: initial bootloader support
From: Marc Hartmayer <mhartmay@linux.ibm.com>

Summary:     genprotimg: Introduce new tool for the creation of PV images
Description: genprotimg takes a kernel, host-key documents, optionally an
             initrd, optionally a file with the kernel command line, and it
             generates a single, loadable image file. The image consists of a
             concatenation of a plain text boot loader, the encrypted
             components for kernel, initrd, and cmdline, and the
             integrity-protected PV header, containing metadata necessary for
             running the guest in PV mode. It's possible to use this image file
             as a kernel for zIPL or for a direct kernel boot using QEMU.
Upstream-ID: 3356d6f4facd748f8f5cf24ffc5056db3e915f2c
Problem-ID:  VS1804

Upstream-Description:

             genprotimg: boot: initial bootloader support

             Add a boot loader for protected virtualization (PV) that can be
             combined with a kernel/initrd/parmfile to form a single bootable file.
             This file must be constructed in a way that it can be used (1) for a
             QEMU direct kernel boot and (2) it can be zipl'ed by the normal,
             unmodified zipl program.

             This new boot loader consists of two parts:

             1. stage3a boot loader (cleartext), this loader is responsible for
                the transition into the protected mode by doing diag308 subcode 8
                and 10 calls.

             2. stage3b boot loader (encrypted), this loader is very similar to the
                normal zipl stage3 boot loader. It will be loaded by the Ultravisor
                after the successful transition into protected mode. Like the zipl
                stage3 boot loader it moves the kernel and patches in the values
                for initrd and parmline.

             The requirements for (1) and (2) result in the following constraints:

             1. It must be possible to place stage3a and stage3b at a location >=
                0x10000 because the zipl stage3 loader zeroes out everything at
                addresses lower than 0x10000 of the image.

             2. As the stage3 loader of zipl assumes that the passed kernel image
                looks like a normal kernel image, the zipl stage3 loader modifies the
                content at the memory area 0x10400 - 0x10800, therefore we leave this
                area unused in our stage3a loader.

             3. The default entry address used by the zipl stage3 loader is 0x10000
                so we add a simple branch to 0x11000 at 0x10000 so the zipl stage3
                loader can modify the area 0x10400 - 0x10800 without affecting the
                stage3a loader.

             The stage3b loader is linked at address 0x9000, therefore it will not
             work at another address. The relocation support for the stage3b
             loader, so that it can be placed at addresses != 0x9000, is added in
             the next patch. This loader with relocation support has the name
             'stage3b_reloc'.

             The memory layout of the single bootable file looks like:

             +-----------------------+-----------+------------------------+
             |Start                  |End        |Use                     |
             +=======================+===========+========================+
             |0                      |0x7        |Short PSW, starting     |
             |                       |           |instruction at 0x11000  |
             +-----------------------+-----------+------------------------+
             |0x10000                |0x10012    |Branch to 0x11000       |
             +-----------------------+-----------+------------------------+
             |0x10013                |0x10fff    |Left intentionally      |
             |                       |           |unused                  |
             +-----------------------+-----------+------------------------+
             |0x11000                |0x12fff    |Stage3a                 |
             +-----------------------+-----------+------------------------+
             |0x13000                |0x13fff    |IPIB used as argument   |
             |                       |           |for the diag308 call    |
             +-----------------------+-----------+------------------------+
             |0x14000                |0x1[45]fff |UV header used for the  |
             |                       |           |diag308 call (size can  |
             |                       |           |be either 1 or 2 pages) |
             +-----------------------+-----------+------------------------+
             |NEXT_PAGE_ALIGNED_ADDR |           |Encrypted Kernel        |
             +-----------------------+-----------+------------------------+
             |NEXT_PAGE_ALIGNED_ADDR |           |Encrypted Cmdline       |
             +-----------------------+-----------+------------------------+
             |NEXT_PAGE_ALIGNED_ADDR |           |Encrypted Initrd        |
             +-----------------------+-----------+------------------------+
             |NEXT_PAGE_ALIGNED_ADDR |           |Encrypted Stage3b_reloc |
             +-----------------------+-----------+------------------------+

             Reviewed-by: Philipp Rudo <prudo@linux.ibm.com>
             Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
             Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>


Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
---
 genprotimg/boot/.gitignore             |    3 
 genprotimg/boot/Makefile               |   83 +++++++++++++++++++++++++++
 genprotimg/boot/common_memory_layout.h |   25 ++++++++
 genprotimg/boot/head.S                 |   29 +++++++++
 genprotimg/boot/stage3a.c              |   62 ++++++++++++++++++++
 genprotimg/boot/stage3a.h              |   34 +++++++++++
 genprotimg/boot/stage3a.lds            |  101 +++++++++++++++++++++++++++++++++
 genprotimg/boot/stage3a_init.S         |   26 ++++++++
 genprotimg/boot/stage3b.c              |   77 +++++++++++++++++++++++++
 genprotimg/boot/stage3b.h              |   38 ++++++++++++
 genprotimg/boot/stage3b.lds            |   87 ++++++++++++++++++++++++++++
 include/boot/ipl.h                     |   25 ++++++++
 include/boot/s390.h                    |   22 +++++--
 zipl/boot/error.h                      |    6 +
 14 files changed, 613 insertions(+), 5 deletions(-)

--- /dev/null
+++ b/genprotimg/boot/.gitignore
@@ -0,0 +1,3 @@
+*.elf
+*.bin
+*.d
--- /dev/null
+++ b/genprotimg/boot/Makefile
@@ -0,0 +1,83 @@
+# Common definitions
+include ../../common.mak
+
+ZIPL_DIR := $(rootdir)/zipl
+ZIPL_BOOT_DIR := $(ZIPL_DIR)/boot
+
+INCLUDE_PATHS := $(ZIPL_BOOT_DIR) $(ZIPL_DIR)/include $(rootdir)/include
+INCLUDE_PARMS := $(addprefix -I,$(INCLUDE_PATHS))
+
+ALL_CFLAGS := $(NO_PIE_CFLAGS) -Os -g \
+	$(INCLUDE_PARMS) \
+	-DENABLE_SCLP_ASCII=1 \
+	-DS390_TOOLS_RELEASE=$(S390_TOOLS_RELEASE) \
+	-fno-builtin -ffreestanding -fno-asynchronous-unwind-tables \
+	-fno-delete-null-pointer-checks \
+	-fexec-charset=IBM1047 -m64 -mpacked-stack \
+	-mstack-size=4096 -mstack-guard=128 -msoft-float \
+	-Wall -Wformat-security -Wextra -Werror
+
+FILES := stage3a.bin stage3b.bin
+
+ZIPL_SRCS_C := libc.c ebcdic.c ebcdic_conv.c sclp.c
+ZIPL_SRCS_ASM := entry.S
+
+ZIPL_OBJS_C := $(ZIPL_SRCS_C:%.c=%.o)
+ZIPL_OBJS_ASM := $(ZIPL_SRCS_ASM:%.S=%.o)
+ZIPL_OBJS := $(ZIPL_OBJS_C) $(ZIPL_OBJS_ASM)
+
+
+all: $(FILES)
+
+# Prevent make from using some default rules...
+%:	%.S
+
+%.o:	%.S Makefile
+	$(CC) $(ALL_CFLAGS) -c -o $@ $<
+
+%.o:	%.c Makefile
+	$(CC) $(ALL_CFLAGS) -c -o $@ $<
+
+
+# Special rules for zipl object files
+$(ZIPL_OBJS_C): %.o : $(ZIPL_BOOT_DIR)/%.c
+	$(CC) $(ALL_CFLAGS) -c -o $@ $<
+
+$(ZIPL_OBJS_ASM): %.o : $(ZIPL_BOOT_DIR)/%.S
+	$(CC) $(ALL_CFLAGS) -c -o $@ $<
+
+dependencies_zipl_c := $(ZIPL_SRCS_C:%.c=.%.o.d)
+
+$(dependencies_zipl_c): .%.o.d : $(ZIPL_BOOT_DIR)/%.c
+	$(CC_SILENT) -MM $(ALL_CPPFLAGS) $(ALL_CFLAGS) $< > $@
+
+ifneq ($(MAKECMDGOALS),clean)
+-include $(dependencies_zipl_c)
+endif
+
+
+stage3a.elf: head.o stage3a_init.o stage3a.o stage3a.lds $(ZIPL_OBJS)
+stage3b.elf: head.o stage3b.o stage3b.lds $(ZIPL_OBJS)
+
+%.elf:	%.o
+	case $* in \
+		stage3a) SFLAGS="$(NO_PIE_LINKFLAGS) -nostdlib -Wl,-T,stage3a.lds";; \
+		stage3b) SFLAGS="$(NO_PIE_LINKFLAGS) -nostdlib -Wl,-T,stage3b.lds";; \
+	esac; \
+	$(LINK) $$SFLAGS -m64 $(filter %.o, $^) -o $@
+	@chmod a-x $@
+
+%.bin:	%.elf
+	$(OBJCOPY) -O binary \
+		--only-section=.text* \
+		--only-section=.ex_table* \
+		--only-section=.fixup* \
+		--only-section=.data*  \
+		--only-section=.rodata* \
+		$< $@
+	@chmod a-x $@
+
+clean:
+	rm -f *.o *.elf *.bin *.map .*.d
+
+.PHONY: all clean
--- /dev/null
+++ b/genprotimg/boot/common_memory_layout.h
@@ -0,0 +1,25 @@
+/*
+ * Common memory layout for stage3a and stage3b bootloader.
+ *
+ * Copyright IBM Corp. 2020
+ *
+ * s390-tools is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See LICENSE for details.
+ */
+
+#ifndef COMMON_MEMORY_LAYOUT_H
+#define COMMON_MEMORY_LAYOUT_H
+
+#include "boot/loaders_layout.h"
+
+#define STACK_ADDRESS		STAGE3_STACK_ADDRESS
+#define STACK_SIZE		STAGE3_STACK_SIZE
+
+#define HEAP_ADDRESS		STAGE3_HEAP_ADDRESS
+#define HEAP_SIZE		STAGE3_HEAP_SIZE
+
+
+#ifndef __ASSEMBLER__
+
+#endif /* __ASSEMBLER__ */
+#endif /* COMMON_MEMORY_LAYOUT_H */
--- /dev/null
+++ b/genprotimg/boot/head.S
@@ -0,0 +1,29 @@
+/*
+ * Entry code for stage 3a boot loader
+ *
+ * Copyright IBM Corp. 2020
+ *
+ * s390-tools is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See LICENSE for details.
+ */
+
+
+#include "common_memory_layout.h"
+
+#include "boot/s390.h"
+#include "boot/sigp.h"
+
+.section .text.start
+.globl _start
+_start:
+	/* Might be called after a diag308 so better set
+	 * architecture and addressing mode
+	 */
+	lhi	%r1, 1
+	sigp	%r1, %r0, SIGP_SET_ARCHITECTURE
+	sam64
+
+	/* Initialize stack */
+	lgfi	%r15, STACK_ADDRESS + STACK_SIZE - STACK_FRAME_OVERHEAD
+	brasl	%r14, initialize
+.previous
--- /dev/null
+++ b/genprotimg/boot/stage3a.c
@@ -0,0 +1,62 @@
+/*
+ * Main program for stage3a bootloader
+ *
+ * Copyright IBM Corp. 2020
+ *
+ * s390-tools is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See LICENSE for details.
+ */
+
+#include "libc.h"
+#include "stage3a.h"
+
+#include "lib/zt_common.h"
+#include "boot/s390.h"
+#include "boot/ipl.h"
+#include "sclp.h"
+#include "error.h"
+
+
+static volatile struct stage3a_args __section(".loader_parms") loader_parms;
+
+void __noreturn start(void)
+{
+	int rc;
+	volatile struct stage3a_args *args = &loader_parms;
+	/* calculate the IPIB memory address */
+	struct ipl_parameter_block *ipib = (void *)((uint64_t)args + args->ipib_offs);
+
+	/* Calculate the PV header memory address and set it and its
+	 * size in the IPIB. This allows the PV header to be position
+	 * independent.
+	 */
+	ipib->pv.pv_hdr_addr = (uint64_t)args + args->hdr_offs;
+	ipib->pv.pv_hdr_size = args->hdr_size;
+
+	/* set up ASCII and line-mode */
+	sclp_setup(SCLP_LINE_ASCII_INIT);
+
+	/* test if Secure Execution Unpack facility is available */
+	stfle(S390_lowcore.stfle_fac_list,
+	      ARRAY_SIZE(S390_lowcore.stfle_fac_list));
+	rc = test_facility(UNPACK_FACILITY);
+	if (rc == 0)
+		panic(ENOPV, "Secure unpack facility is not available\n");
+
+	rc = diag308(DIAG308_SET_PV, ipib);
+	if (rc != DIAG308_RC_OK)
+		panic(EPV, "Protected boot setup has failed: 0x%x\n", rc);
+
+	rc = diag308(DIAG308_UNPACK_PV, 0x0);
+	if (rc != DIAG308_RC_OK) {
+		sclp_setup(SCLP_LINE_ASCII_INIT);
+		panic(EPV, "Protected boot has failed: 0x%x\n", rc);
+	}
+
+	while (1)
+		;
+}
+
+void panic_notify(unsigned long UNUSED(rc))
+{
+}
--- /dev/null
+++ b/genprotimg/boot/stage3a.h
@@ -0,0 +1,34 @@
+/*
+ * Main program for stage3a bootloader.
+ *
+ * Copyright IBM Corp. 2020
+ *
+ * s390-tools is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See LICENSE for details.
+ */
+
+#ifndef STAGE3A_H
+#define STAGE3A_H
+
+#include "lib/zt_common.h"
+#include "boot/loaders_layout.h"
+
+#define STAGE3A_INIT_ENTRY		IMAGE_ENTRY
+#define STAGE3A_ENTRY			(STAGE3A_INIT_ENTRY + _AC(0x1000, UL))
+#define STAGE3A_LOAD_ADDRESS		IMAGE_LOAD_ADDRESS
+
+
+#ifndef __ASSEMBLER__
+
+#include <stdint.h>
+
+/* Must not have any padding */
+struct stage3a_args {
+	uint64_t hdr_offs;
+	uint64_t hdr_size;
+	uint64_t ipib_offs;
+};
+STATIC_ASSERT(sizeof(struct stage3a_args) == 3 * 8)
+
+#endif /* __ASSEMBLER__ */
+#endif /* STAGE3A_H */
--- /dev/null
+++ b/genprotimg/boot/stage3a.lds
@@ -0,0 +1,101 @@
+/*
+ * Memory layout for stage 3a
+ * ==========================
+ *
+ * General memory layout
+ * ---------------------
+ *
+ * 0x00000 - 0x01fff	Lowcore
+ * 0x02000 - 0x05fff	Memory allocation (heap)
+ * 0x0f000 - 0x0ffff	Stack
+ * 0x10000 - 0x10012	Jump to the "actual" stage3a code
+ * 0x11000 - 0x12fff	Stage3a code + arguments (offsets and lengths to the
+ * 			actual data: IPIB and UV header)
+ */
+
+OUTPUT_FORMAT("elf64-s390", "elf64-s390", "elf64-s390")
+OUTPUT_ARCH(s390:64-bit)
+
+ENTRY(_init)
+
+__heap_size__ = 0x4000;
+__stack_size__ = 0x1000;
+
+SECTIONS
+{
+	. = 0x0;
+
+	. = 0x2000;
+	__heap_start = .;
+	.heap : {
+		. = . + __heap_size__;
+		ASSERT(__heap_stop - __heap_start == __heap_size__,
+		       "Heap section doesn't conform to the described memory layout");
+	}
+	__heap_stop = .;
+
+	. = 0xf000;
+	__stack_start = .;
+	.stack : {
+		. = . + __stack_size__;
+		ASSERT(__stack_end - __stack_start == __stack_size__,
+		       "Stack section doesn't conform to the described memory layout");
+	}
+	__stack_end = .;
+
+	. = 0x10000;
+	__text_init_start = .;
+	.text : {
+		stage3a_init.o(.text.init)
+		__text_init_stop = ABSOLUTE(.);
+		/* Text size of text_init must be smaller than 'PARMAREA - IMAGE_ENTRY',
+		 * otherwise the text data could be overwritten by the original zipl stage3
+		 * boot loader */
+		ASSERT(__text_init_stop - __text_init_start < 0x400,
+		       "Text size must be smaller than 'PARMAREA - IMAGE_ENTRY'");
+		. = 0x1000;
+		head.o(.text.start)
+		*(.text)
+	}
+
+	.ex_table ALIGN(16) : {
+		__ex_table_start = .;
+		*(.ex_table)
+		__ex_table_stop = .;
+	}
+
+	.bss ALIGN(16) : {
+		__bss_start = .;
+		*(.bss)
+		__bss_stop = .;
+	}
+
+	.rodata ALIGN(16) : {
+		*(.rodata)
+		*(.rodata.*)
+	}
+
+	.data ALIGN(16) : {
+		*(.data)
+		. = ALIGN(16);
+		/* The IPIB offset and the UV header offset and size will be
+		 * saved in 'loader_parms' */
+		__loader_parms_start = .;
+		KEEP(*(.loader_parms));
+		__loader_parms_stop = .;
+		ASSERT(__loader_parms_stop - __loader_parms_start == 3 * 8,
+		       "Data size must be equal to 'sizeof(struct stage3a_args)'");
+		ASSERT(ABSOLUTE(.) < 0x13000, "Data section doesn't conform to the described memory layout");
+	}
+
+	/* List this explicitly as otherwise .note.gnu.build-id will be
+	 * put at 0x0 */
+	.notes : {
+		*(.note.*)
+	}
+
+	/* Sections to be discarded */
+	/DISCARD/ : {
+		*(.eh_frame)
+	}
+}
--- /dev/null
+++ b/genprotimg/boot/stage3a_init.S
@@ -0,0 +1,26 @@
+/*
+ * Entry code for stage 3a boot loader
+ *
+ * Copyright IBM Corp. 2020
+ *
+ * s390-tools is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See LICENSE for details.
+ */
+
+#include "stage3a.h"
+#include "boot/sigp.h"
+
+.section .text.init
+.globl _init
+_init:
+	/* set architecture and switch to 64bit  */
+	lhi	%r1, 1
+	sigp	%r1, %r0, SIGP_SET_ARCHITECTURE
+	sam64
+	/* The original stage3 boot loader will try to store the
+	 * kernel command line and the address and size of the
+	 * ramdisk. Simply ignore this by starting at 0x11000.
+	 */
+	lgfi	%r1, STAGE3A_ENTRY
+	br	%r1
+.previous
--- /dev/null
+++ b/genprotimg/boot/stage3b.c
@@ -0,0 +1,77 @@
+/*
+ * Main program for stage3b bootloader
+ *
+ * Copyright IBM Corp. 2020
+ *
+ * s390-tools is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See LICENSE for details.
+ */
+
+#include "libc.h"
+#include "stage3b.h"
+
+#include "lib/zt_common.h"
+#include "boot/s390.h"
+#include "boot/linux_layout.h"
+#include "boot/loaders_layout.h"
+#include "sclp.h"
+#include "error.h"
+
+
+static volatile struct stage3b_args __section(".loader_parms") loader_parms;
+
+static inline void __noreturn load_psw(struct psw_t psw)
+{
+	asm volatile("lpswe %0" : : "Q"(psw) : "cc");
+
+	while (1)
+		;
+}
+
+void __noreturn start(void)
+{
+	volatile struct stage3b_args *args = &loader_parms;
+	volatile struct memblob *kernel = &args->kernel;
+	volatile struct memblob *cmdline = &args->cmdline;
+	volatile struct memblob *initrd = &args->initrd;
+	volatile struct psw_t psw = args->psw;
+
+	/* set up ASCII and line-mode */
+	sclp_setup(SCLP_LINE_ASCII_INIT);
+
+	if (kernel->size < IMAGE_LOAD_ADDRESS)
+		panic(EINTERNAL, "Invalid kernel\n");
+
+	if (cmdline->size > COMMAND_LINE_SIZE)
+		panic(EINTERNAL, "Command line is too large\n");
+
+	/* move the kernel and cut the kernel header */
+	memmove((void *)IMAGE_LOAD_ADDRESS,
+		(void *)(kernel->src + IMAGE_LOAD_ADDRESS),
+		kernel->size - IMAGE_LOAD_ADDRESS);
+
+	/* move the kernel cmdline */
+	memmove((void *)COMMAND_LINE,
+		(void *)cmdline->src,
+		cmdline->size);
+	/* the initrd does not need to be moved */
+
+	if (initrd->size != 0) {
+		/* copy initrd start address and size into new kernel space */
+		*(unsigned long long *)INITRD_START = initrd->src;
+		*(unsigned long long *)INITRD_SIZE = initrd->size;
+	}
+
+	/* disable ASCII and line-mode */
+	sclp_setup(SCLP_DISABLE);
+
+	/* use lpswe instead of diag308 as a I/O subsystem reset is not
+	 * needed as this was already done by the diag308 subcode 10 call
+	 * in stage3a
+	 */
+	load_psw(psw);
+}
+
+void panic_notify(unsigned long UNUSED(rc))
+{
+}
--- /dev/null
+++ b/genprotimg/boot/stage3b.h
@@ -0,0 +1,38 @@
+/*
+ * Main program for stage3b bootloader
+ *
+ * Copyright IBM Corp. 2020
+ *
+ * s390-tools is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See LICENSE for details.
+ */
+
+#ifndef STAGE3B_H
+#define STAGE3B_H
+
+#include "lib/zt_common.h"
+
+
+#ifndef __ASSEMBLER__
+
+#include <stdint.h>
+
+#include "boot/s390.h"
+
+/* Must not have any padding included */
+struct memblob {
+	uint64_t src;
+	uint64_t size;
+};
+STATIC_ASSERT(sizeof(struct memblob) == 2 * 8)
+
+/* Must not have any padding included */
+struct stage3b_args {
+	struct memblob kernel;
+	struct memblob cmdline;
+	struct memblob initrd;
+	struct psw_t psw;
+};
+STATIC_ASSERT(sizeof(struct stage3b_args) == 3 * sizeof(struct memblob) + 16)
+#endif /* __ASSEMBLER__ */
+#endif /* STAGE3B_H */
--- /dev/null
+++ b/genprotimg/boot/stage3b.lds
@@ -0,0 +1,87 @@
+/*
+ * Memory layout for stage 3b
+ * ==========================
+ *
+ * General memory layout
+ * ---------------------
+ *
+ * 0x00000 - 0x01fff	Lowcore
+ * 0x02000 - 0x05fff	Memory allocation (heap)
+ * 0x0a000 - 0x0efff	Stage3b code
+ * 0x0f000 - 0x0ffff	Stack
+ */
+
+OUTPUT_FORMAT("elf64-s390", "elf64-s390", "elf64-s390")
+OUTPUT_ARCH(s390:64-bit)
+
+ENTRY(_start)
+
+__heap_size__ = 0x4000;
+__stack_size__ = 0x1000;
+
+SECTIONS
+{
+	. = 0x0;
+
+	. = 0x2000;
+	__heap_start = .;
+	.heap : {
+		. = . + __heap_size__;
+		ASSERT(__heap_stop - __heap_start == __heap_size__,
+		       "Heap section doesn't conform to the described memory layout");
+	}
+	__heap_stop = .;
+
+	. = 0xa000;
+	.text : {
+		head.o(.text.start)
+		*(.text)
+	}
+
+	.ex_table ALIGN(16) : {
+		__ex_table_start = .;
+		*(.ex_table)
+		__ex_table_stop = .;
+	}
+
+	.bss ALIGN(16) : {
+		__bss_start = .;
+		*(.bss)
+		__bss_stop = .;
+	}
+
+	.rodata ALIGN(16) : {
+		*(.rodata)
+		*(.rodata.*)
+	}
+
+	.data ALIGN(16) : {
+		*(.data)
+		. = ALIGN(16);
+		__loader_parms_start = .;
+		KEEP(*(.loader_parms));
+		__loader_parms_end = .;
+		ASSERT(__loader_parms_end - __loader_parms_start == 3 * 16 + 16,
+		       "Data size must be equal to 'sizeof(struct stage3b_args)'");
+	}
+
+	. = 0xf000;
+	__stack_start = .;
+	.stack : {
+		. = . + __stack_size__;
+		ASSERT(__stack_end - __stack_start == __stack_size__,
+		       "Stack section doesn't conform to the described memory layout");
+	}
+	__stack_end = .;
+
+	/* List this explicitly as otherwise .note.gnu.build-id will be
+	 * put at 0x0 */
+	.notes : {
+		*(.note.*)
+	}
+
+	/* Sections to be discarded */
+	/DISCARD/ : {
+		*(.eh_frame)
+	}
+}
--- a/include/boot/ipl.h
+++ b/include/boot/ipl.h
@@ -89,6 +89,30 @@ struct ipl_pb0_ccw {
 	uint8_t  reserved5[8];
 } __packed;
 
+/* Structure must not have any padding */
+struct ipl_pb0_pv_comp {
+	uint64_t tweak_pref;
+	uint64_t addr;
+	uint64_t len;
+};
+STATIC_ASSERT(sizeof(struct ipl_pb0_pv_comp) == 3 * 8)
+
+/* IPL Parameter Block 0 for PV */
+struct ipl_pb0_pv {
+	uint32_t len;
+	uint8_t  pbt;
+	uint8_t  reserved1[3];
+	uint8_t  loadparm[8];
+	uint8_t  reserved2[84];
+	uint8_t  reserved3[3];
+	uint8_t  version;
+	uint8_t  reserved4[4];
+	uint32_t num_comp;
+	uint64_t pv_hdr_addr;
+	uint64_t pv_hdr_size;
+	struct ipl_pb0_pv_comp components[];
+} __packed;
+
 struct ipl_parameter_block {
 	struct ipl_pl_hdr hdr;
 	union {
@@ -96,6 +120,7 @@ struct ipl_parameter_block {
 		struct ipl_pb0_common common;
 		struct ipl_pb0_fcp fcp;
 		struct ipl_pb0_ccw ccw;
+		struct ipl_pb0_pv pv;
 		char raw[PAGE_SIZE - sizeof(struct ipl_pl_hdr)];
 	};
 } __packed __aligned(PAGE_SIZE);
--- a/include/boot/s390.h
+++ b/include/boot/s390.h
@@ -18,6 +18,12 @@
 
 #define PAGE_SIZE		_AC(4096, UL)
 
+/* Minimum size of a stack frame in bytes */
+#define STACK_FRAME_OVERHEAD	_AC(160, U)
+
+/* Facilities */
+#define UNPACK_FACILITY		_AC(161, U)
+
 
 #ifndef __ASSEMBLER__
 
@@ -262,11 +268,17 @@ static __always_inline void __ctl_set_bi
  * DIAG 308 support
  */
 enum diag308_subcode {
-	DIAG308_REL_HSA = 2,
-	DIAG308_IPL	= 3,
-	DIAG308_DUMP	= 4,
-	DIAG308_SET	= 5,
-	DIAG308_STORE	= 6,
+	DIAG308_REL_HSA	  = 2,
+	DIAG308_IPL	  = 3,
+	DIAG308_DUMP	  = 4,
+	DIAG308_SET	  = 5,
+	DIAG308_STORE	  = 6,
+	DIAG308_SET_PV	  = 8,
+	DIAG308_UNPACK_PV = 10,
+};
+
+enum diag308_rc {
+	DIAG308_RC_OK	      = 0x0001,
 };
 
 static __always_inline unsigned long diag308(unsigned long subcode, void *addr)
--- a/zipl/boot/error.h
+++ b/zipl/boot/error.h
@@ -71,4 +71,10 @@
 #define ENOTIME		0x00004605  /* The zipl time stamps do not match */
 #define ENOMSS		0x00004606  /* Could not enable MSS */
 
+/*
+ * PV error codes
+ */
+#define ENOPV		0x00004607 /* No support for PV */
+#define EPV		0x00004608 /* PV error */
+
 #endif /* ERROR_H */
openSUSE Build Service is sponsored by