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

Commit 6b70a920 authored by Heiko Carstens's avatar Heiko Carstens Committed by Martin Schwidefsky
Browse files

s390/memory hotplug: use pfmf instruction to initialize storage keys



Move and rename init_storage_keys() to pageattr.c, so it can also be
used from the sclp memory hotplug code in order to initialize
storage keys.

Signed-off-by: default avatarHeiko Carstens <heiko.carstens@de.ibm.com>
Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
parent 1e466fcf
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -30,6 +30,8 @@
#include <asm/setup.h>
#ifndef __ASSEMBLY__

void storage_key_init_range(unsigned long start, unsigned long end);

static unsigned long pfmf(unsigned long function, unsigned long address)
{
	asm volatile(
+1 −35
Original line number Diff line number Diff line
@@ -777,40 +777,6 @@ static void __init reserve_crashkernel(void)
#endif
}

static void __init init_storage_keys(unsigned long start, unsigned long end)
{
	unsigned long boundary, function, size;

	while (start < end) {
		if (MACHINE_HAS_EDAT2) {
			/* set storage keys for a 2GB frame */
			function = 0x22000 | PAGE_DEFAULT_KEY;
			size = 1UL << 31;
			boundary = (start + size) & ~(size - 1);
			if (boundary <= end) {
				do {
					start = pfmf(function, start);
				} while (start < boundary);
				continue;
			}
		}
		if (MACHINE_HAS_EDAT1) {
			/* set storage keys for a 1MB frame */
			function = 0x21000 | PAGE_DEFAULT_KEY;
			size = 1UL << 20;
			boundary = (start + size) & ~(size - 1);
			if (boundary <= end) {
				do {
					start = pfmf(function, start);
				} while (start < boundary);
				continue;
			}
		}
		page_set_storage_key(start, PAGE_DEFAULT_KEY, 0);
		start += PAGE_SIZE;
	}
}

static void __init setup_memory(void)
{
        unsigned long bootmap_size;
@@ -889,7 +855,7 @@ static void __init setup_memory(void)
		memblock_add_node(PFN_PHYS(start_chunk),
				  PFN_PHYS(end_chunk - start_chunk), 0);
		pfn = max(start_chunk, start_pfn);
		init_storage_keys(PFN_PHYS(pfn), PFN_PHYS(end_chunk));
		storage_key_init_range(PFN_PHYS(pfn), PFN_PHYS(end_chunk));
	}

	psw_set_key(PAGE_DEFAULT_KEY);
+6 −6
Original line number Diff line number Diff line
@@ -2,9 +2,9 @@
# Makefile for the linux s390-specific parts of the memory manager.
#

obj-y	 := init.o fault.o extmem.o mmap.o vmem.o pgtable.o maccess.o \
	    page-states.o gup.o extable.o
obj-y		:= init.o fault.o extmem.o mmap.o vmem.o pgtable.o maccess.o
obj-y		+= page-states.o gup.o extable.o pageattr.o

obj-$(CONFIG_CMM)		+= cmm.o
obj-$(CONFIG_HUGETLB_PAGE)	+= hugetlbpage.o
obj-$(CONFIG_DEBUG_SET_MODULE_RONX) += pageattr.o
obj-$(CONFIG_S390_PTDUMP)	+= dump_pagetables.o
+36 −1
Original line number Diff line number Diff line
@@ -2,11 +2,46 @@
 * Copyright IBM Corp. 2011
 * Author(s): Jan Glauber <jang@linux.vnet.ibm.com>
 */
#include <linux/hugetlb.h>
#include <linux/module.h>
#include <linux/mm.h>
#include <linux/hugetlb.h>
#include <asm/cacheflush.h>
#include <asm/pgtable.h>
#include <asm/page.h>

void storage_key_init_range(unsigned long start, unsigned long end)
{
	unsigned long boundary, function, size;

	while (start < end) {
		if (MACHINE_HAS_EDAT2) {
			/* set storage keys for a 2GB frame */
			function = 0x22000 | PAGE_DEFAULT_KEY;
			size = 1UL << 31;
			boundary = (start + size) & ~(size - 1);
			if (boundary <= end) {
				do {
					start = pfmf(function, start);
				} while (start < boundary);
				continue;
			}
		}
		if (MACHINE_HAS_EDAT1) {
			/* set storage keys for a 1MB frame */
			function = 0x21000 | PAGE_DEFAULT_KEY;
			size = 1UL << 20;
			boundary = (start + size) & ~(size - 1);
			if (boundary <= end) {
				do {
					start = pfmf(function, start);
				} while (start < boundary);
				continue;
			}
		}
		page_set_storage_key(start, PAGE_DEFAULT_KEY, 0);
		start += PAGE_SIZE;
	}
}

static pte_t *walk_page_table(unsigned long addr)
{
+8 −9
Original line number Diff line number Diff line
@@ -19,10 +19,11 @@
#include <linux/memory.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <asm/ctl_reg.h>
#include <asm/chpid.h>
#include <asm/sclp.h>
#include <asm/setup.h>
#include <asm/ctl_reg.h>
#include <asm/page.h>
#include <asm/sclp.h>

#include "sclp.h"

@@ -400,17 +401,15 @@ static int do_assign_storage(sclp_cmdw_t cmd, u16 rn)

static int sclp_assign_storage(u16 rn)
{
	unsigned long long start, address;
	unsigned long long start;
	int rc;

	rc = do_assign_storage(0x000d0001, rn);
	if (rc)
		goto out;
	start = address = rn2addr(rn);
	for (; address < start + rzm; address += PAGE_SIZE)
		page_set_storage_key(address, PAGE_DEFAULT_KEY, 0);
out:
		return rc;
	start = rn2addr(rn);
	storage_key_init_range(start, start + rzm);
	return 0;
}

static int sclp_unassign_storage(u16 rn)