arch/s390/boot/startup.c

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

File Facts

System
Linux kernel
Corpus path
arch/s390/boot/startup.c
Extension
.c
Size
22062 bytes
Lines
650
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 (!sclp_early_get_hsa_size(&hsa_size) && hsa_size) {
			ident_map_size = min(ident_map_size, hsa_size);
			boot_debug("Stand-alone dump limit: 0x%016lx\n", hsa_size);
		}
	}
#endif
	boot_debug("Identity map size:   0x%016lx\n", ident_map_size);
}

#define FIXMAP_SIZE	round_up(MEMCPY_REAL_SIZE + ABS_LOWCORE_MAP_SIZE, sizeof(struct lowcore))

static unsigned long get_vmem_size(unsigned long identity_size,
				   unsigned long vmemmap_size,
				   unsigned long vmalloc_size,
				   unsigned long rte_size)
{
	unsigned long max_mappable, vsize;

	max_mappable = max(identity_size, MAX_DCSS_ADDR);
	vsize = round_up(SZ_2G + max_mappable, rte_size) +
		round_up(vmemmap_size, rte_size) +
		FIXMAP_SIZE + MODULES_LEN + KASLR_LEN;
	if (IS_ENABLED(CONFIG_KMSAN))
		vsize += MODULES_LEN * 2;
	return size_add(vsize, vmalloc_size);
}

static unsigned long setup_kernel_memory_layout(unsigned long kernel_size)
{
	unsigned long vmemmap_start;
	unsigned long kernel_start;
	unsigned long asce_limit;
	unsigned long rte_size;
	unsigned long pages;
	unsigned long vsize;
	unsigned long vmax;

	pages = ident_map_size / PAGE_SIZE;
	/* vmemmap contains a multiple of PAGES_PER_SECTION struct pages */
	vmemmap_size = SECTION_ALIGN_UP(pages) * sizeof(struct page);

	/* choose kernel address space layout: 4 or 3 levels. */
	BUILD_BUG_ON(!IS_ALIGNED(TEXT_OFFSET, THREAD_SIZE));
	BUILD_BUG_ON(!IS_ALIGNED(__NO_KASLR_START_KERNEL, THREAD_SIZE));
	BUILD_BUG_ON(__NO_KASLR_END_KERNEL > _REGION1_SIZE);
	BUILD_BUG_ON(CONFIG_ILLEGAL_POINTER_VALUE < _REGION1_SIZE);
	vsize = get_vmem_size(ident_map_size, vmemmap_size, vmalloc_size, _REGION3_SIZE);
	boot_debug("vmem size estimated: 0x%016lx\n", vsize);
	if (IS_ENABLED(CONFIG_KASAN) || __NO_KASLR_END_KERNEL > _REGION2_SIZE ||
	    (vsize > _REGION2_SIZE && kaslr_enabled())) {
		asce_limit = _REGION1_SIZE;
		if (__NO_KASLR_END_KERNEL > _REGION2_SIZE) {
			rte_size = _REGION2_SIZE;
			vsize = get_vmem_size(ident_map_size, vmemmap_size, vmalloc_size, _REGION2_SIZE);
		} else {
			rte_size = _REGION3_SIZE;
		}
	} else {
		asce_limit = _REGION2_SIZE;
		rte_size = _REGION3_SIZE;
	}

	/*
	 * Forcing modules and vmalloc area under the ultravisor
	 * secure storage limit, so that any vmalloc allocation
	 * we do could be used to back secure guest storage.
	 *
	 * Assume the secure storage limit always exceeds _REGION2_SIZE,
	 * otherwise asce_limit and rte_size would have been adjusted.
	 */
	vmax = adjust_to_uv_max(asce_limit);
	boot_debug("%d level paging       0x%016lx vmax\n", vmax == _REGION1_SIZE ? 4 : 3, vmax);
#ifdef CONFIG_KASAN
	BUILD_BUG_ON(__NO_KASLR_END_KERNEL > KASAN_SHADOW_START);
	boot_debug("KASAN shadow area:   0x%016lx-0x%016lx\n", KASAN_SHADOW_START, KASAN_SHADOW_END);
	/* force vmalloc and modules below kasan shadow */
	vmax = min(vmax, KASAN_SHADOW_START);
#endif
	vsize = min(vsize, vmax);
	if (kaslr_enabled()) {
		unsigned long kernel_end, kaslr_len, slots, pos;

		kaslr_len = max(KASLR_LEN, vmax - vsize);
		slots = DIV_ROUND_UP(kaslr_len - kernel_size, THREAD_SIZE);
		if (get_random(slots, &pos))
			pos = 0;
		kernel_end = vmax - pos * THREAD_SIZE;
		kernel_start = round_down(kernel_end - kernel_size, THREAD_SIZE);
		boot_debug("Randomization range: 0x%016lx-0x%016lx\n", vmax - kaslr_len, vmax);
		boot_debug("kernel image:        0x%016lx-0x%016lx (kaslr)\n", kernel_start,

Annotation

Implementation Notes