arch/s390/boot/physmem_info.c

Source file repositories/reference/linux-study-clean/arch/s390/boot/physmem_info.c

File Facts

System
Linux kernel
Corpus path
arch/s390/boot/physmem_info.c
Extension
.c
Size
11015 bytes
Lines
387
Domain
Architecture Layer
Bucket
arch/s390
Inferred role
Architecture Layer: implementation source
Status
source implementation candidate

Why This File Exists

CPU and platform-specific kernel glue: boot entry, traps, syscall entry, interrupts, page tables, context switch, and low-level barriers.

Dependency Surface

Detected Declarations

Annotated Snippet

if (range->end == start) {
			range->end = end;
			return;
		}
	}

	range = __get_physmem_range_ptr(physmem_info.range_count);
	range->start = start;
	range->end = end;
	physmem_info.range_count++;
}

static int __diag260(unsigned long rx1, unsigned long rx2)
{
	union register_pair rx;
	int cc, exception;
	unsigned long ry;

	rx.even = rx1;
	rx.odd	= rx2;
	ry = 0x10; /* storage configuration */
	exception = 1;
	asm_inline volatile(
		"	diag	%[rx],%[ry],0x260\n"
		"0:	lhi	%[exc],0\n"
		"1:\n"
		CC_IPM(cc)
		EX_TABLE(0b, 1b)
		: CC_OUT(cc, cc), [exc] "+d" (exception), [ry] "+d" (ry)
		: [rx] "d" (rx.pair)
		: CC_CLOBBER_LIST("memory"));
	cc = exception ? -1 : CC_TRANSFORM(cc);
	return cc == 0 ? ry : -1;
}

static int diag260(void)
{
	int rc, i;

	struct {
		unsigned long start;
		unsigned long end;
	} storage_extents[8] __aligned(16); /* VM supports up to 8 extends */

	memset(storage_extents, 0, sizeof(storage_extents));
	rc = __diag260((unsigned long)storage_extents, sizeof(storage_extents));
	if (rc == -1)
		return -1;

	for (i = 0; i < min_t(int, rc, ARRAY_SIZE(storage_extents)); i++)
		add_physmem_online_range(storage_extents[i].start, storage_extents[i].end + 1);
	return 0;
}

#define DIAG500_SC_STOR_LIMIT 4

static int diag500_storage_limit(unsigned long *max_physmem_end)
{
	unsigned long storage_limit;

	asm_inline volatile(
		"	lghi	%%r1,%[subcode]\n"
		"	lghi	%%r2,0\n"
		"	diag	%%r2,%%r4,0x500\n"
		"0:	lgr	%[slimit],%%r2\n"
		EX_TABLE(0b, 0b)
		: [slimit] "=d" (storage_limit)
		: [subcode] "i" (DIAG500_SC_STOR_LIMIT)
		: "memory", "1", "2");
	if (!storage_limit)
		return -EINVAL;
	/* Convert inclusive end to exclusive end */
	*max_physmem_end = storage_limit + 1;
	return 0;
}

static int tprot(unsigned long addr)
{
	int cc, exception;

	exception = 1;
	asm_inline volatile(
		"	tprot	0(%[addr]),0\n"
		"0:	lhi	%[exc],0\n"
		"1:\n"
		CC_IPM(cc)
		EX_TABLE(0b, 1b)
		: CC_OUT(cc, cc), [exc] "+d" (exception)
		: [addr] "a" (addr)
		: CC_CLOBBER_LIST("memory"));

Annotation

Implementation Notes