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

Commit 53492b1d authored by Gerald Schaefer's avatar Gerald Schaefer Committed by Martin Schwidefsky
Browse files

[S390] System z large page support.



This adds hugetlbfs support on System z, using both hardware large page
support if available and software large page emulation on older hardware.
Shared (large) page tables are implemented in software emulation mode,
by using page->index of the first tail page from a compound large page
to store page table information.

Signed-off-by: default avatarGerald Schaefer <geraldsc@de.ibm.com>
Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
parent 2e5061e4
Loading
Loading
Loading
Loading
+16 −0
Original line number Original line Diff line number Diff line
@@ -268,6 +268,19 @@ static noinline __init void setup_lowcore_early(void)
	s390_base_pgm_handler_fn = early_pgm_check_handler;
	s390_base_pgm_handler_fn = early_pgm_check_handler;
}
}


static noinline __init void setup_hpage(void)
{
#ifndef CONFIG_DEBUG_PAGEALLOC
	unsigned int facilities;

	facilities = stfl();
	if (!(facilities & (1UL << 23)) || !(facilities & (1UL << 29)))
		return;
	machine_flags |= MACHINE_FLAG_HPAGE;
	__ctl_set_bit(0, 23);
#endif
}

static __init void detect_mvpg(void)
static __init void detect_mvpg(void)
{
{
#ifndef CONFIG_64BIT
#ifndef CONFIG_64BIT
@@ -360,6 +373,8 @@ static __init void detect_machine_facilities(void)
	facilities = stfl();
	facilities = stfl();
	if (facilities & (1 << 28))
	if (facilities & (1 << 28))
		machine_flags |= MACHINE_FLAG_IDTE;
		machine_flags |= MACHINE_FLAG_IDTE;
	if (facilities & (1 << 23))
		machine_flags |= MACHINE_FLAG_PFMF;
	if (facilities & (1 << 4))
	if (facilities & (1 << 4))
		machine_flags |= MACHINE_FLAG_MVCOS;
		machine_flags |= MACHINE_FLAG_MVCOS;
#endif
#endif
@@ -388,6 +403,7 @@ void __init startup_init(void)
	detect_diag9c();
	detect_diag9c();
	detect_diag44();
	detect_diag44();
	detect_machine_facilities();
	detect_machine_facilities();
	setup_hpage();
	sclp_read_info_early();
	sclp_read_info_early();
	sclp_facilities_detect();
	sclp_facilities_detect();
	memsize = sclp_memory_detect();
	memsize = sclp_memory_detect();
+1 −1
Original line number Original line Diff line number Diff line
@@ -129,7 +129,7 @@ startup_continue:
					# virtual and never return ...
					# virtual and never return ...
	.align	16
	.align	16
.Lentry:.quad	0x0000000180000000,_stext
.Lentry:.quad	0x0000000180000000,_stext
.Lctl:	.quad	0x04b50002		# cr0: various things
.Lctl:	.quad	0x04350002		# cr0: various things
	.quad	0			# cr1: primary space segment table
	.quad	0			# cr1: primary space segment table
	.quad	.Lduct			# cr2: dispatchable unit control table
	.quad	.Lduct			# cr2: dispatchable unit control table
	.quad	0			# cr3: instruction authorization
	.quad	0			# cr3: instruction authorization
+7 −3
Original line number Original line Diff line number Diff line
@@ -749,6 +749,9 @@ static void __init setup_hwcaps(void)
			elf_hwcap |= 1UL << 6;
			elf_hwcap |= 1UL << 6;
	}
	}


	if (MACHINE_HAS_HPAGE)
		elf_hwcap |= 1UL << 7;

	switch (cpuinfo->cpu_id.machine) {
	switch (cpuinfo->cpu_id.machine) {
	case 0x9672:
	case 0x9672:
#if !defined(CONFIG_64BIT)
#if !defined(CONFIG_64BIT)
@@ -872,8 +875,9 @@ void __cpuinit print_cpu_info(struct cpuinfo_S390 *cpuinfo)


static int show_cpuinfo(struct seq_file *m, void *v)
static int show_cpuinfo(struct seq_file *m, void *v)
{
{
	static const char *hwcap_str[7] = {
	static const char *hwcap_str[8] = {
		"esan3", "zarch", "stfle", "msa", "ldisp", "eimm", "dfp"
		"esan3", "zarch", "stfle", "msa", "ldisp", "eimm", "dfp",
		"edat"
	};
	};
        struct cpuinfo_S390 *cpuinfo;
        struct cpuinfo_S390 *cpuinfo;
	unsigned long n = (unsigned long) v - 1;
	unsigned long n = (unsigned long) v - 1;
@@ -888,7 +892,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
			       num_online_cpus(), loops_per_jiffy/(500000/HZ),
			       num_online_cpus(), loops_per_jiffy/(500000/HZ),
			       (loops_per_jiffy/(5000/HZ))%100);
			       (loops_per_jiffy/(5000/HZ))%100);
		seq_puts(m, "features\t: ");
		seq_puts(m, "features\t: ");
		for (i = 0; i < 7; i++)
		for (i = 0; i < 8; i++)
			if (hwcap_str[i] && (elf_hwcap & (1UL << i)))
			if (hwcap_str[i] && (elf_hwcap & (1UL << i)))
				seq_printf(m, "%s ", hwcap_str[i]);
				seq_printf(m, "%s ", hwcap_str[i]);
		seq_puts(m, "\n");
		seq_puts(m, "\n");
+1 −1
Original line number Original line Diff line number Diff line
@@ -4,4 +4,4 @@


obj-y	 := init.o fault.o extmem.o mmap.o vmem.o pgtable.o
obj-y	 := init.o fault.o extmem.o mmap.o vmem.o pgtable.o
obj-$(CONFIG_CMM) += cmm.o
obj-$(CONFIG_CMM) += cmm.o
obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o
+3 −0
Original line number Original line Diff line number Diff line
@@ -28,6 +28,7 @@
#include <linux/hardirq.h>
#include <linux/hardirq.h>
#include <linux/kprobes.h>
#include <linux/kprobes.h>
#include <linux/uaccess.h>
#include <linux/uaccess.h>
#include <linux/hugetlb.h>
#include <asm/system.h>
#include <asm/system.h>
#include <asm/pgtable.h>
#include <asm/pgtable.h>
#include <asm/s390_ext.h>
#include <asm/s390_ext.h>
@@ -367,6 +368,8 @@ do_exception(struct pt_regs *regs, unsigned long error_code, int write)
	}
	}


survive:
survive:
	if (is_vm_hugetlb_page(vma))
		address &= HPAGE_MASK;
	/*
	/*
	 * If for any reason at all we couldn't handle the fault,
	 * If for any reason at all we couldn't handle the fault,
	 * make sure we exit gracefully rather than endlessly redo
	 * make sure we exit gracefully rather than endlessly redo
Loading