xref: /kvm-unit-tests/lib/s390x/sclp.c (revision 92bbd3220c117d75b53c706a03bcfd87cf38b2f2)
13db880b6SDavid Hildenbrand /*
23db880b6SDavid Hildenbrand  * s390x SCLP driver
33db880b6SDavid Hildenbrand  *
43db880b6SDavid Hildenbrand  * Copyright (c) 2017 Red Hat Inc
53db880b6SDavid Hildenbrand  *
63db880b6SDavid Hildenbrand  * Authors:
73db880b6SDavid Hildenbrand  *  David Hildenbrand <david@redhat.com>
83db880b6SDavid Hildenbrand  *
93db880b6SDavid Hildenbrand  * This code is free software; you can redistribute it and/or modify it
103db880b6SDavid Hildenbrand  * under the terms of the GNU Library General Public License version 2.
113db880b6SDavid Hildenbrand  */
123db880b6SDavid Hildenbrand 
133db880b6SDavid Hildenbrand #include <libcflat.h>
143db880b6SDavid Hildenbrand #include <asm/page.h>
153db880b6SDavid Hildenbrand #include <asm/arch_def.h>
163db880b6SDavid Hildenbrand #include <asm/interrupt.h>
173db880b6SDavid Hildenbrand #include "sclp.h"
18*92bbd322SDavid Hildenbrand #include <alloc_phys.h>
19*92bbd322SDavid Hildenbrand 
20*92bbd322SDavid Hildenbrand extern unsigned long stacktop;
213db880b6SDavid Hildenbrand 
223db880b6SDavid Hildenbrand static uint64_t storage_increment_size;
233db880b6SDavid Hildenbrand static uint64_t max_ram_size;
243db880b6SDavid Hildenbrand static uint64_t ram_size;
253db880b6SDavid Hildenbrand 
26*92bbd322SDavid Hildenbrand static void mem_init(phys_addr_t mem_end)
27*92bbd322SDavid Hildenbrand {
28*92bbd322SDavid Hildenbrand 	phys_addr_t freemem_start = (phys_addr_t)&stacktop;
29*92bbd322SDavid Hildenbrand 
30*92bbd322SDavid Hildenbrand 	phys_alloc_init(freemem_start, mem_end - freemem_start);
31*92bbd322SDavid Hildenbrand }
32*92bbd322SDavid Hildenbrand 
333db880b6SDavid Hildenbrand void sclp_memory_setup(void)
343db880b6SDavid Hildenbrand {
353db880b6SDavid Hildenbrand 	ReadInfo *ri = (void *)_sccb;
363db880b6SDavid Hildenbrand 	uint64_t rnmax, rnsize;
373db880b6SDavid Hildenbrand 	int cc;
383db880b6SDavid Hildenbrand 
393db880b6SDavid Hildenbrand 	ri->h.length = SCCB_SIZE;
403db880b6SDavid Hildenbrand 	sclp_service_call(SCLP_CMDW_READ_SCP_INFO_FORCED, ri);
413db880b6SDavid Hildenbrand 
423db880b6SDavid Hildenbrand 	/* calculate the storage increment size */
433db880b6SDavid Hildenbrand 	rnsize = ri->rnsize;
443db880b6SDavid Hildenbrand 	if (!rnsize) {
453db880b6SDavid Hildenbrand 		rnsize = ri->rnsize2;
463db880b6SDavid Hildenbrand 	}
473db880b6SDavid Hildenbrand 	storage_increment_size = rnsize << 20;
483db880b6SDavid Hildenbrand 
493db880b6SDavid Hildenbrand 	/* calculate the maximum memory size */
503db880b6SDavid Hildenbrand 	rnmax = ri->rnmax;
513db880b6SDavid Hildenbrand 	if (!rnmax) {
523db880b6SDavid Hildenbrand 		rnmax = ri->rnmax2;
533db880b6SDavid Hildenbrand 	}
543db880b6SDavid Hildenbrand 	max_ram_size = rnmax * storage_increment_size;
553db880b6SDavid Hildenbrand 
563db880b6SDavid Hildenbrand 	/* lowcore is always accessible, so the first increment is accessible */
573db880b6SDavid Hildenbrand 	ram_size = storage_increment_size;
583db880b6SDavid Hildenbrand 
593db880b6SDavid Hildenbrand 	/* probe for r/w memory up to max memory size */
603db880b6SDavid Hildenbrand 	while (ram_size < max_ram_size) {
613db880b6SDavid Hildenbrand 		expect_pgm_int();
623db880b6SDavid Hildenbrand 		cc = tprot(ram_size + storage_increment_size - 1);
633db880b6SDavid Hildenbrand 		/* stop once we receive an exception or have protected memory */
643db880b6SDavid Hildenbrand 		if (clear_pgm_int() || cc != 0)
653db880b6SDavid Hildenbrand 			break;
663db880b6SDavid Hildenbrand 		ram_size += storage_increment_size;
673db880b6SDavid Hildenbrand 	}
68*92bbd322SDavid Hildenbrand 
69*92bbd322SDavid Hildenbrand 	mem_init(ram_size);
703db880b6SDavid Hildenbrand }
71