Commit 1995a536 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull more s390 updates from Vasily Gorbik:

 - Get rid of s390 specific use of two PTEs per 4KB page with complex
   half-used pages tracking. Using full 4KB pages for 2KB PTEs increases
   the memory footprint of page tables but drastically simplify mm code,
   removing a common blocker for common code changes and adaptations

 - Simplify and rework "cmma no-dat" handling. This is a follow up for
   recent fixes which prevent potential incorrect guest TLB flushes

 - Add perf user stack unwinding as well as USER_STACKTRACE support for
   user space built with -mbackchain compile option

 - Add few missing conversion from tlb_remove_table to tlb_remove_ptdesc

 - Fix crypto cards vanishing in a secure execution environment due to
   asynchronous errors

 - Avoid reporting crypto cards or queues in check-stop state as online

 - Fix null-ptr deference in AP bus code triggered by early config
   change via SCLP

 - Couple of stability improvements in AP queue interrupt handling

* tag 's390-6.7-2' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux:
  s390/mm: make pte_free_tlb() similar to pXd_free_tlb()
  s390/mm: use compound page order to distinguish page tables
  s390/mm: use full 4KB page for 2KB PTE
  s390/cmma: rework no-dat handling
  s390/cmma: move arch_set_page_dat() to header file
  s390/cmma: move set_page_stable() and friends to header file
  s390/cmma: move parsing of cmma kernel parameter to early boot code
  s390/cmma: cleanup inline assemblies
  s390/ap: fix vanishing crypto cards in SE environment
  s390/zcrypt: don't report online if card or queue is in check-stop state
  s390: add USER_STACKTRACE support
  s390/perf: implement perf_callchain_user()
  s390/ap: fix AP bus crash on early config change callback invocation
  s390/ap: re-enable interrupt for AP queues
  s390/ap: rework to use irq info from ap queue status
  s390/mm: add missing conversion to use ptdescs
parents 90450a06 02e790ee
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -236,6 +236,7 @@ config S390
	select THREAD_INFO_IN_TASK
	select TRACE_IRQFLAGS_SUPPORT
	select TTY
	select USER_STACKTRACE_SUPPORT
	select VIRT_CPU_ACCOUNTING
	select ZONE_DMA
	# Note: keep the above list sorted alphabetically
+8 −0
Original line number Diff line number Diff line
@@ -3,6 +3,7 @@
#include <linux/init.h>
#include <linux/ctype.h>
#include <linux/pgtable.h>
#include <asm/page-states.h>
#include <asm/ebcdic.h>
#include <asm/sclp.h>
#include <asm/sections.h>
@@ -24,6 +25,7 @@ unsigned int __bootdata_preserved(zlib_dfltcc_support) = ZLIB_DFLTCC_FULL;
struct ipl_parameter_block __bootdata_preserved(ipl_block);
int __bootdata_preserved(ipl_block_valid);
int __bootdata_preserved(__kaslr_enabled);
int __bootdata_preserved(cmma_flag) = 1;

unsigned long vmalloc_size = VMALLOC_DEFAULT_SIZE;
unsigned long memory_limit;
@@ -295,6 +297,12 @@ void parse_boot_command_line(void)
		if (!strcmp(param, "nokaslr"))
			__kaslr_enabled = 0;

		if (!strcmp(param, "cmma")) {
			rc = kstrtobool(val, &enabled);
			if (!rc && !enabled)
				cmma_flag = 0;
		}

#if IS_ENABLED(CONFIG_KVM)
		if (!strcmp(param, "prot_virt")) {
			rc = kstrtobool(val, &enabled);
+44 −0
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0
#include <linux/string.h>
#include <linux/elf.h>
#include <asm/page-states.h>
#include <asm/boot_data.h>
#include <asm/sections.h>
#include <asm/maccess.h>
@@ -57,6 +58,48 @@ static void detect_facilities(void)
		machine.has_nx = 1;
}

static int cmma_test_essa(void)
{
	unsigned long reg1, reg2, tmp = 0;
	int rc = 1;
	psw_t old;

	/* Test ESSA_GET_STATE */
	asm volatile(
		"	mvc	0(16,%[psw_old]),0(%[psw_pgm])\n"
		"	epsw	%[reg1],%[reg2]\n"
		"	st	%[reg1],0(%[psw_pgm])\n"
		"	st	%[reg2],4(%[psw_pgm])\n"
		"	larl	%[reg1],1f\n"
		"	stg	%[reg1],8(%[psw_pgm])\n"
		"	.insn	rrf,0xb9ab0000,%[tmp],%[tmp],%[cmd],0\n"
		"	la	%[rc],0\n"
		"1:	mvc	0(16,%[psw_pgm]),0(%[psw_old])\n"
		: [reg1] "=&d" (reg1),
		  [reg2] "=&a" (reg2),
		  [rc] "+&d" (rc),
		  [tmp] "=&d" (tmp),
		  "+Q" (S390_lowcore.program_new_psw),
		  "=Q" (old)
		: [psw_old] "a" (&old),
		  [psw_pgm] "a" (&S390_lowcore.program_new_psw),
		  [cmd] "i" (ESSA_GET_STATE)
		: "cc", "memory");
	return rc;
}

static void cmma_init(void)
{
	if (!cmma_flag)
		return;
	if (cmma_test_essa()) {
		cmma_flag = 0;
		return;
	}
	if (test_facility(147))
		cmma_flag = 2;
}

static void setup_lpp(void)
{
	S390_lowcore.current_pid = 0;
@@ -306,6 +349,7 @@ void startup_kernel(void)
	setup_boot_command_line();
	parse_boot_command_line();
	detect_facilities();
	cmma_init();
	sanitize_prot_virt_host();
	max_physmem_end = detect_max_physmem_end();
	setup_ident_map_size(max_physmem_end);
+17 −0
Original line number Diff line number Diff line
@@ -2,6 +2,7 @@
#include <linux/sched/task.h>
#include <linux/pgtable.h>
#include <linux/kasan.h>
#include <asm/page-states.h>
#include <asm/pgalloc.h>
#include <asm/facility.h>
#include <asm/sections.h>
@@ -70,6 +71,10 @@ static void kasan_populate_shadow(void)
	crst_table_init((unsigned long *)kasan_early_shadow_pud, pud_val(pud_z));
	crst_table_init((unsigned long *)kasan_early_shadow_pmd, pmd_val(pmd_z));
	memset64((u64 *)kasan_early_shadow_pte, pte_val(pte_z), PTRS_PER_PTE);
	__arch_set_page_dat(kasan_early_shadow_p4d, 1UL << CRST_ALLOC_ORDER);
	__arch_set_page_dat(kasan_early_shadow_pud, 1UL << CRST_ALLOC_ORDER);
	__arch_set_page_dat(kasan_early_shadow_pmd, 1UL << CRST_ALLOC_ORDER);
	__arch_set_page_dat(kasan_early_shadow_pte, 1);

	/*
	 * Current memory layout:
@@ -223,6 +228,7 @@ static void *boot_crst_alloc(unsigned long val)

	table = (unsigned long *)physmem_alloc_top_down(RR_VMEM, size, size);
	crst_table_init(table, val);
	__arch_set_page_dat(table, 1UL << CRST_ALLOC_ORDER);
	return table;
}

@@ -238,6 +244,7 @@ static pte_t *boot_pte_alloc(void)
	if (!pte_leftover) {
		pte_leftover = (void *)physmem_alloc_top_down(RR_VMEM, PAGE_SIZE, PAGE_SIZE);
		pte = pte_leftover + _PAGE_TABLE_SIZE;
		__arch_set_page_dat(pte, 1);
	} else {
		pte = pte_leftover;
		pte_leftover = NULL;
@@ -418,6 +425,14 @@ void setup_vmem(unsigned long asce_limit)
	unsigned long asce_bits;
	int i;

	/*
	 * Mark whole memory as no-dat. This must be done before any
	 * page tables are allocated, or kernel image builtin pages
	 * are marked as dat tables.
	 */
	for_each_physmem_online_range(i, &start, &end)
		__arch_set_page_nodat((void *)start, (end - start) >> PAGE_SHIFT);

	if (asce_limit == _REGION1_SIZE) {
		asce_type = _REGION2_ENTRY_EMPTY;
		asce_bits = _ASCE_TYPE_REGION2 | _ASCE_TABLE_LENGTH;
@@ -429,6 +444,8 @@ void setup_vmem(unsigned long asce_limit)

	crst_table_init((unsigned long *)swapper_pg_dir, asce_type);
	crst_table_init((unsigned long *)invalid_pg_dir, _REGION3_ENTRY_EMPTY);
	__arch_set_page_dat((void *)swapper_pg_dir, 1UL << CRST_ALLOC_ORDER);
	__arch_set_page_dat((void *)invalid_pg_dir, 1UL << CRST_ALLOC_ORDER);

	/*
	 * To allow prefixing the lowcore must be mapped with 4KB pages.
+0 −2
Original line number Diff line number Diff line
@@ -11,7 +11,6 @@ typedef struct {
	cpumask_t cpu_attach_mask;
	atomic_t flush_count;
	unsigned int flush_mm;
	struct list_head pgtable_list;
	struct list_head gmap_list;
	unsigned long gmap_asce;
	unsigned long asce;
@@ -39,7 +38,6 @@ typedef struct {

#define INIT_MM_CONTEXT(name)						   \
	.context.lock =	__SPIN_LOCK_UNLOCKED(name.context.lock),	   \
	.context.pgtable_list = LIST_HEAD_INIT(name.context.pgtable_list), \
	.context.gmap_list = LIST_HEAD_INIT(name.context.gmap_list),

#endif
Loading