Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 272058
b: refs/heads/master
c: 7f0bf65
h: refs/heads/master
v: v3
  • Loading branch information
Michael Holzheu authored and Martin Schwidefsky committed Oct 30, 2011
1 parent fd1b90d commit 3ff6fef
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 19 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 1943f53c9ca182fa233e5a17e89ef8e421d7819e
refs/heads/master: 7f0bf656c66e4292e965c95fd9de55c72b6578bb
2 changes: 2 additions & 0 deletions trunk/arch/s390/include/asm/system.h
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,8 @@ extern void pfault_fini(void);
extern void cmma_init(void);
extern int memcpy_real(void *, void *, size_t);
extern void copy_to_absolute_zero(void *dest, void *src, size_t count);
extern int copy_to_user_real(void __user *dest, void *src, size_t count);
extern int copy_from_user_real(void *dest, void __user *src, size_t count);

#define finish_arch_switch(prev) do { \
set_fs(current->thread.mm_segment); \
Expand Down
56 changes: 56 additions & 0 deletions trunk/arch/s390/mm/maccess.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/gfp.h>
#include <asm/system.h>

/*
Expand Down Expand Up @@ -60,6 +61,9 @@ long probe_kernel_write(void *dst, const void *src, size_t size)
return copied < 0 ? -EFAULT : 0;
}

/*
* Copy memory in real mode (kernel to kernel)
*/
int memcpy_real(void *dest, void *src, size_t count)
{
register unsigned long _dest asm("2") = (unsigned long) dest;
Expand Down Expand Up @@ -101,3 +105,55 @@ void copy_to_absolute_zero(void *dest, void *src, size_t count)
__ctl_load(cr0, 0, 0);
preempt_enable();
}

/*
* Copy memory from kernel (real) to user (virtual)
*/
int copy_to_user_real(void __user *dest, void *src, size_t count)
{
int offs = 0, size, rc;
char *buf;

buf = (char *) __get_free_page(GFP_KERNEL);
if (!buf)
return -ENOMEM;
rc = -EFAULT;
while (offs < count) {
size = min(PAGE_SIZE, count - offs);
if (memcpy_real(buf, src + offs, size))
goto out;
if (copy_to_user(dest + offs, buf, size))
goto out;
offs += size;
}
rc = 0;
out:
free_page((unsigned long) buf);
return rc;
}

/*
* Copy memory from user (virtual) to kernel (real)
*/
int copy_from_user_real(void *dest, void __user *src, size_t count)
{
int offs = 0, size, rc;
char *buf;

buf = (char *) __get_free_page(GFP_KERNEL);
if (!buf)
return -ENOMEM;
rc = -EFAULT;
while (offs < count) {
size = min(PAGE_SIZE, count - offs);
if (copy_from_user(buf, src + offs, size))
goto out;
if (memcpy_real(dest + offs, buf, size))
goto out;
offs += size;
}
rc = 0;
out:
free_page((unsigned long) buf);
return rc;
}
20 changes: 2 additions & 18 deletions trunk/drivers/s390/char/zcore.c
Original file line number Diff line number Diff line change
Expand Up @@ -142,22 +142,6 @@ static int memcpy_hsa_kernel(void *dest, unsigned long src, size_t count)
return memcpy_hsa(dest, src, count, TO_KERNEL);
}

static int memcpy_real_user(void __user *dest, unsigned long src, size_t count)
{
static char buf[4096];
int offs = 0, size;

while (offs < count) {
size = min(sizeof(buf), count - offs);
if (memcpy_real(buf, (void *) src + offs, size))
return -EFAULT;
if (copy_to_user(dest + offs, buf, size))
return -EFAULT;
offs += size;
}
return 0;
}

static int __init init_cpu_info(enum arch_id arch)
{
struct save_area *sa;
Expand Down Expand Up @@ -346,8 +330,8 @@ static ssize_t zcore_read(struct file *file, char __user *buf, size_t count,

/* Copy from real mem */
size = count - mem_offs - hdr_count;
rc = memcpy_real_user(buf + hdr_count + mem_offs, mem_start + mem_offs,
size);
rc = copy_to_user_real(buf + hdr_count + mem_offs,
(void *) mem_start + mem_offs, size);
if (rc)
goto fail;

Expand Down

0 comments on commit 3ff6fef

Please sign in to comment.