forked from torvalds/linux
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
s390/kernel: add system calls for PCI memory access
Add the new __NR_s390_pci_mmio_write and __NR_s390_pci_mmio_read system calls to allow user space applications to access device PCI I/O memory pages on s390x platform. [ Martin Schwidefsky: some code beautification ] Signed-off-by: Alexey Ishchuk <[email protected]> Signed-off-by: Martin Schwidefsky <[email protected]>
- Loading branch information
Alexey Ishchuk
authored and
Martin Schwidefsky
committed
Nov 19, 2014
1 parent
86c558e
commit 4eafad7
Showing
7 changed files
with
127 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
/* | ||
* Access to PCI I/O memory from user space programs. | ||
* | ||
* Copyright IBM Corp. 2014 | ||
* Author(s): Alexey Ishchuk <[email protected]> | ||
*/ | ||
#include <linux/kernel.h> | ||
#include <linux/syscalls.h> | ||
#include <linux/init.h> | ||
#include <linux/mm.h> | ||
#include <linux/errno.h> | ||
#include <linux/pci.h> | ||
|
||
static long get_pfn(unsigned long user_addr, unsigned long access, | ||
unsigned long *pfn) | ||
{ | ||
struct vm_area_struct *vma; | ||
long ret; | ||
|
||
down_read(¤t->mm->mmap_sem); | ||
ret = -EINVAL; | ||
vma = find_vma(current->mm, user_addr); | ||
if (!vma) | ||
goto out; | ||
ret = -EACCES; | ||
if (!(vma->vm_flags & access)) | ||
goto out; | ||
ret = follow_pfn(vma, user_addr, pfn); | ||
out: | ||
up_read(¤t->mm->mmap_sem); | ||
return ret; | ||
} | ||
|
||
SYSCALL_DEFINE3(s390_pci_mmio_write, unsigned long, mmio_addr, | ||
const void __user *, user_buffer, size_t, length) | ||
{ | ||
u8 local_buf[64]; | ||
void __iomem *io_addr; | ||
void *buf; | ||
unsigned long pfn; | ||
long ret; | ||
|
||
if (!zpci_is_enabled()) | ||
return -ENODEV; | ||
|
||
if (length <= 0 || PAGE_SIZE - (mmio_addr & ~PAGE_MASK) < length) | ||
return -EINVAL; | ||
if (length > 64) { | ||
buf = kmalloc(length, GFP_KERNEL); | ||
if (!buf) | ||
return -ENOMEM; | ||
} else | ||
buf = local_buf; | ||
|
||
ret = get_pfn(mmio_addr, VM_WRITE, &pfn); | ||
if (ret) | ||
goto out; | ||
io_addr = (void *)((pfn << PAGE_SHIFT) | (mmio_addr & ~PAGE_MASK)); | ||
|
||
ret = -EFAULT; | ||
if ((unsigned long) io_addr < ZPCI_IOMAP_ADDR_BASE) | ||
goto out; | ||
|
||
if (copy_from_user(buf, user_buffer, length)) | ||
goto out; | ||
|
||
memcpy_toio(io_addr, buf, length); | ||
ret = 0; | ||
out: | ||
if (buf != local_buf) | ||
kfree(buf); | ||
return ret; | ||
} | ||
|
||
SYSCALL_DEFINE3(s390_pci_mmio_read, unsigned long, mmio_addr, | ||
void __user *, user_buffer, size_t, length) | ||
{ | ||
u8 local_buf[64]; | ||
void __iomem *io_addr; | ||
void *buf; | ||
unsigned long pfn; | ||
long ret; | ||
|
||
if (!zpci_is_enabled()) | ||
return -ENODEV; | ||
|
||
if (length <= 0 || PAGE_SIZE - (mmio_addr & ~PAGE_MASK) < length) | ||
return -EINVAL; | ||
if (length > 64) { | ||
buf = kmalloc(length, GFP_KERNEL); | ||
if (!buf) | ||
return -ENOMEM; | ||
} else | ||
buf = local_buf; | ||
|
||
ret = get_pfn(mmio_addr, VM_READ, &pfn); | ||
if (ret) | ||
goto out; | ||
io_addr = (void *)((pfn << PAGE_SHIFT) | (mmio_addr & ~PAGE_MASK)); | ||
|
||
ret = -EFAULT; | ||
if ((unsigned long) io_addr < ZPCI_IOMAP_ADDR_BASE) | ||
goto out; | ||
|
||
memcpy_fromio(buf, io_addr, length); | ||
|
||
if (copy_to_user(user_buffer, buf, length)) | ||
goto out; | ||
|
||
ret = 0; | ||
out: | ||
if (buf != local_buf) | ||
kfree(buf); | ||
return ret; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters