Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 087c4d74 authored by Gerald Schaefer's avatar Gerald Schaefer Committed by Martin Schwidefsky
Browse files

s390/sclp: do not use static sccbs



The sccbs for init/read/sdias/early have to be located below 2 GB, and
they are currently defined as a static buffer.

With a relocatable kernel that could reside at any place in memory, this
will no longer guarantee the location below 2 GB, so use a dynamic
GFP_DMA allocation instead.

The sclp_early_sccb buffer needs special handling, as it can be used
very early, and by both the decompressor and also the decompressed
kernel. Therefore, a fixed 4 KB buffer is introduced at 0x11000, the
former PARMAREA_END. The new PARMAREA_END is now 0x12000, and it is
renamed to HEAD_END, as it is rather the end of head.S and not the end
of the parmarea.

Signed-off-by: default avatarGerald Schaefer <gerald.schaefer@de.ibm.com>
Reviewed-by: default avatarPhilipp Rudo <prudo@linux.ibm.com>
Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
parent fd3d2742
Loading
Loading
Loading
Loading
+4 −1
Original line number Diff line number Diff line
@@ -336,4 +336,7 @@ ENTRY(startup_kdump)
	.byte	"root=/dev/ram0 ro"
	.byte	0

	.org	0x11000
	.org	EARLY_SCCB_OFFSET
	.fill	4096

	.org	HEAD_END
+4 −1
Original line number Diff line number Diff line
@@ -12,7 +12,10 @@
#define EP_OFFSET		0x10008
#define EP_STRING		"S390EP"
#define PARMAREA		0x10400
#define PARMAREA_END		0x11000
#define EARLY_SCCB_OFFSET	0x11000
#define HEAD_END		0x12000

#define EARLY_SCCB_SIZE		PAGE_SIZE

/*
 * Machine features detected in early.c
+1 −3
Original line number Diff line number Diff line
@@ -337,10 +337,8 @@ int arch_kexec_kernel_image_probe(struct kimage *image, void *buf,
	 * load memory in head.S will be accessed, e.g. to register the next
	 * command line. If the next kernel were smaller the current kernel
	 * will panic at load.
	 *
	 * 0x11000 = sizeof(head.S)
	 */
	if (buf_len < 0x11000)
	if (buf_len < HEAD_END)
		return -ENOEXEC;

	return kexec_image_probe_default(image, buf, buf_len);
+1 −1
Original line number Diff line number Diff line
@@ -829,7 +829,7 @@ static void __init reserve_kernel(void)
{
	unsigned long start_pfn = PFN_UP(__pa(_end));

	memblock_reserve(0, PARMAREA_END);
	memblock_reserve(0, HEAD_END);
	memblock_reserve((unsigned long)_stext, PFN_PHYS(start_pfn)
			 - (unsigned long)_stext);
}
+9 −5
Original line number Diff line number Diff line
@@ -45,8 +45,8 @@ static struct list_head sclp_req_queue;
/* Data for read and and init requests. */
static struct sclp_req sclp_read_req;
static struct sclp_req sclp_init_req;
static char sclp_read_sccb[PAGE_SIZE] __attribute__((__aligned__(PAGE_SIZE)));
static char sclp_init_sccb[PAGE_SIZE] __attribute__((__aligned__(PAGE_SIZE)));
static void *sclp_read_sccb;
static struct init_sccb *sclp_init_sccb;

/* Suspend request */
static DECLARE_COMPLETION(sclp_request_queue_flushed);
@@ -753,9 +753,8 @@ EXPORT_SYMBOL(sclp_remove_processed);
static inline void
__sclp_make_init_req(sccb_mask_t receive_mask, sccb_mask_t send_mask)
{
	struct init_sccb *sccb;
	struct init_sccb *sccb = sclp_init_sccb;

	sccb = (struct init_sccb *) sclp_init_sccb;
	clear_page(sccb);
	memset(&sclp_init_req, 0, sizeof(struct sclp_req));
	sclp_init_req.command = SCLP_CMDW_WRITE_EVENT_MASK;
@@ -782,7 +781,7 @@ static int
sclp_init_mask(int calculate)
{
	unsigned long flags;
	struct init_sccb *sccb = (struct init_sccb *) sclp_init_sccb;
	struct init_sccb *sccb = sclp_init_sccb;
	sccb_mask_t receive_mask;
	sccb_mask_t send_mask;
	int retry;
@@ -1175,6 +1174,9 @@ sclp_init(void)
	if (sclp_init_state != sclp_init_state_uninitialized)
		goto fail_unlock;
	sclp_init_state = sclp_init_state_initializing;
	sclp_read_sccb = (void *) __get_free_page(GFP_ATOMIC | GFP_DMA);
	sclp_init_sccb = (void *) __get_free_page(GFP_ATOMIC | GFP_DMA);
	BUG_ON(!sclp_read_sccb || !sclp_init_sccb);
	/* Set up variables */
	INIT_LIST_HEAD(&sclp_req_queue);
	INIT_LIST_HEAD(&sclp_reg_list);
@@ -1207,6 +1209,8 @@ sclp_init(void)
	unregister_reboot_notifier(&sclp_reboot_notifier);
fail_init_state_uninitialized:
	sclp_init_state = sclp_init_state_uninitialized;
	free_page((unsigned long) sclp_read_sccb);
	free_page((unsigned long) sclp_init_sccb);
fail_unlock:
	spin_unlock_irqrestore(&sclp_lock, flags);
	return rc;
Loading