Commit 2f089a38 authored by Alexander Gordeev's avatar Alexander Gordeev
Browse files

Merge branch 'vmcore-iov_iter' into features

Pull changes that finalize switching of copy_oldmem_page() callback
to iov_iter interface. These changes were pulled in work.iov_iter of
git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs.git



Signed-off-by: default avatarAlexander Gordeev <agordeev@linux.ibm.com>
parents 9aa938dd ebbc9570
Loading
Loading
Loading
Loading
+0 −14
Original line number Diff line number Diff line
@@ -42,18 +42,4 @@ typedef struct {
	.context.pgtable_list = LIST_HEAD_INIT(name.context.pgtable_list), \
	.context.gmap_list = LIST_HEAD_INIT(name.context.gmap_list),

static inline int tprot(unsigned long addr)
{
	int rc = -EFAULT;

	asm volatile(
		"	tprot	0(%1),0\n"
		"0:	ipm	%0\n"
		"	srl	%0,28\n"
		"1:\n"
		EX_TABLE(0b,1b)
		: "+d" (rc) : "a" (addr) : "cc");
	return rc;
}

#endif
+16 −1
Original line number Diff line number Diff line
@@ -8,6 +8,8 @@
#ifndef _ASM_S390_OS_INFO_H
#define _ASM_S390_OS_INFO_H

#include <linux/uio.h>

#define OS_INFO_VERSION_MAJOR	1
#define OS_INFO_VERSION_MINOR	1
#define OS_INFO_MAGIC		0x4f53494e464f535aULL /* OSINFOSZ */
@@ -39,7 +41,20 @@ u32 os_info_csum(struct os_info *os_info);

#ifdef CONFIG_CRASH_DUMP
void *os_info_old_entry(int nr, unsigned long *size);
int copy_oldmem_kernel(void *dst, unsigned long src, size_t count);
size_t copy_oldmem_iter(struct iov_iter *iter, unsigned long src, size_t count);

static inline int copy_oldmem_kernel(void *dst, unsigned long src, size_t count)
{
	struct iov_iter iter;
	struct kvec kvec;

	kvec.iov_base = dst;
	kvec.iov_len = count;
	iov_iter_kvec(&iter, WRITE, &kvec, 1, count);
	if (copy_oldmem_iter(&iter, src, count) < count)
		return -EFAULT;
	return 0;
}
#else
static inline void *os_info_old_entry(int nr, unsigned long *size)
{
+2 −2
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
#define EXT_SCCB_READ_CPU	(3 * PAGE_SIZE)

#ifndef __ASSEMBLY__
#include <linux/uio.h>
#include <asm/chpid.h>
#include <asm/cpu.h>

@@ -142,8 +143,7 @@ int sclp_pci_deconfigure(u32 fid);
int sclp_ap_configure(u32 apid);
int sclp_ap_deconfigure(u32 apid);
int sclp_pci_report(struct zpci_report_error_header *report, u32 fh, u32 fid);
int memcpy_hsa_kernel(void *dest, unsigned long src, size_t count);
int memcpy_hsa_user(void __user *dest, unsigned long src, size_t count);
size_t memcpy_hsa_iter(struct iov_iter *iter, unsigned long src, size_t count);
void sclp_ocf_cpc_name_copy(char *dst);

static inline int sclp_get_core_info(struct sclp_core_info *info, int early)
+0 −1
Original line number Diff line number Diff line
@@ -285,7 +285,6 @@ static inline unsigned long __must_check clear_user(void __user *to, unsigned lo
	return __clear_user(to, n);
}

int copy_to_user_real(void __user *dest, unsigned long src, unsigned long count);
void *s390_kernel_write(void *dst, const void *src, size_t size);

int __noreturn __put_kernel_bad(void);
+28 −80
Original line number Diff line number Diff line
@@ -53,6 +53,8 @@ struct save_area {
};

static LIST_HEAD(dump_save_areas);
static DEFINE_MUTEX(memcpy_real_mutex);
static char memcpy_real_buf[PAGE_SIZE];

/*
 * Allocate a save area
@@ -63,7 +65,7 @@ struct save_area * __init save_area_alloc(bool is_boot_cpu)

	sa = memblock_alloc(sizeof(*sa), 8);
	if (!sa)
		panic("Failed to allocate save area\n");
		return NULL;

	if (is_boot_cpu)
		list_add(&sa->list, &dump_save_areas);
@@ -114,80 +116,35 @@ void __init save_area_add_vxrs(struct save_area *sa, __vector128 *vxrs)
	memcpy(sa->vxrs_high, vxrs + 16, 16 * sizeof(__vector128));
}

/*
 * Return physical address for virtual address
 */
static inline void *load_real_addr(void *addr)
{
	unsigned long real_addr;

	asm volatile(
		   "	lra     %0,0(%1)\n"
		   "	jz	0f\n"
		   "	la	%0,0\n"
		   "0:"
		   : "=a" (real_addr) : "a" (addr) : "cc");
	return (void *)real_addr;
}

/*
 * Copy memory of the old, dumped system to a kernel space virtual address
 */
int copy_oldmem_kernel(void *dst, unsigned long src, size_t count)
static size_t copy_to_iter_real(struct iov_iter *iter, unsigned long src, size_t count)
{
	unsigned long len;
	void *ra;
	int rc;
	size_t len, copied, res = 0;

	mutex_lock(&memcpy_real_mutex);
	while (count) {
		if (!oldmem_data.start && src < sclp.hsa_size) {
			/* Copy from zfcp/nvme dump HSA area */
			len = min(count, sclp.hsa_size - src);
			rc = memcpy_hsa_kernel(dst, src, len);
			if (rc)
				return rc;
		} else {
			/* Check for swapped kdump oldmem areas */
			if (oldmem_data.start && src - oldmem_data.start < oldmem_data.size) {
				src -= oldmem_data.start;
				len = min(count, oldmem_data.size - src);
			} else if (oldmem_data.start && src < oldmem_data.size) {
				len = min(count, oldmem_data.size - src);
				src += oldmem_data.start;
			} else {
				len = count;
			}
			if (is_vmalloc_or_module_addr(dst)) {
				ra = load_real_addr(dst);
				len = min(PAGE_SIZE - offset_in_page(ra), len);
			} else {
				ra = dst;
			}
			if (memcpy_real(ra, src, len))
				return -EFAULT;
		len = min(PAGE_SIZE, count);
		if (memcpy_real(memcpy_real_buf, src, len))
			break;
		copied = copy_to_iter(memcpy_real_buf, len, iter);
		count -= copied;
		src += copied;
		res += copied;
		if (copied < len)
			break;
	}
		dst += len;
		src += len;
		count -= len;
	}
	return 0;
	mutex_unlock(&memcpy_real_mutex);
	return res;
}

/*
 * Copy memory of the old, dumped system to a user space virtual address
 */
static int copy_oldmem_user(void __user *dst, unsigned long src, size_t count)
size_t copy_oldmem_iter(struct iov_iter *iter, unsigned long src, size_t count)
{
	unsigned long len;
	int rc;
	size_t len, copied, res = 0;

	while (count) {
		if (!oldmem_data.start && src < sclp.hsa_size) {
			/* Copy from zfcp/nvme dump HSA area */
			len = min(count, sclp.hsa_size - src);
			rc = memcpy_hsa_user(dst, src, len);
			if (rc)
				return rc;
			copied = memcpy_hsa_iter(iter, src, len);
		} else {
			/* Check for swapped kdump oldmem areas */
			if (oldmem_data.start && src - oldmem_data.start < oldmem_data.size) {
@@ -199,15 +156,15 @@ static int copy_oldmem_user(void __user *dst, unsigned long src, size_t count)
			} else {
				len = count;
			}
			rc = copy_to_user_real(dst, src, count);
			if (rc)
				return rc;
			copied = copy_to_iter_real(iter, src, len);
		}
		dst += len;
		src += len;
		count -= len;
		count -= copied;
		src += copied;
		res += copied;
		if (copied < len)
			break;
	}
	return 0;
	return res;
}

/*
@@ -217,18 +174,9 @@ ssize_t copy_oldmem_page(struct iov_iter *iter, unsigned long pfn, size_t csize,
			 unsigned long offset)
{
	unsigned long src;
	int rc;

	if (!csize)
		return 0;
	src = pfn_to_phys(pfn) + offset;

	/* XXX: pass the iov_iter down to a common function */
	if (iter_is_iovec(iter))
		rc = copy_oldmem_user(iter->iov->iov_base, src, csize);
	else
		rc = copy_oldmem_kernel(iter->kvec->iov_base, src, csize);
	return rc;
	return copy_oldmem_iter(iter, src, csize);
}

/*
Loading