Line 1... |
Line 1... |
|
|
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
#define __NO_VERSION__
|
#include <linux/version.h>
|
#include <linux/module.h>
|
#include <linux/module.h>
|
#include <linux/types.h>
|
#include <linux/types.h>
|
#include <linux/ioport.h>
|
#include <linux/ioport.h>
|
#include <linux/pci.h>
|
#include <linux/pci.h>
|
#include <linux/pagemap.h>
|
#include <linux/pagemap.h>
|
#include <linux/interrupt.h>
|
#include <linux/interrupt.h>
|
#include <linux/proc_fs.h>
|
#include <linux/proc_fs.h>
|
|
#include <linux/sched.h>
|
|
|
#include <asm/io.h>
|
#include <asm/io.h>
|
|
|
#include "memory.h"
|
|
#include "pexmodule.h"
|
#include "pexmodule.h"
|
|
#include "memory.h"
|
|
|
//--------------------------------------------------------------------
|
//--------------------------------------------------------------------
|
|
|
int lock_pages( void *va, u32 size )
|
int lock_pages( void *va, u32 size )
|
{
|
{
|
struct page *start_page_addr = virt_to_page(va);
|
struct page *start_page_addr = virt_to_page(va);
|
int i = 0;
|
int i = 0;
|
|
|
for (i=0; i < (size >> PAGE_CACHE_SHIFT); i++) {
|
for (i=0; i < (size >> PAGE_SHIFT); i++) {
|
SetPageReserved(start_page_addr+i);
|
SetPageReserved(start_page_addr+i);
|
//dbg_msg(dbg_trace, "%s(): page_addr[%d] = 0x%x\n", __FUNCTION__, i, (int)(start_page_addr+i));
|
//dbg_msg(dbg_trace, "%s(): page_addr[%d] = 0x%x\n", __FUNCTION__, i, (int)(start_page_addr+i));
|
}
|
}
|
|
|
return i;
|
return i;
|
Line 33... |
Line 36... |
int unlock_pages( void *va, u32 size )
|
int unlock_pages( void *va, u32 size )
|
{
|
{
|
struct page *start_page_addr = virt_to_page(va);
|
struct page *start_page_addr = virt_to_page(va);
|
int i = 0;
|
int i = 0;
|
|
|
for (i=0; i < (size >> PAGE_CACHE_SHIFT); i++) {
|
for (i=0; i < (size >> PAGE_SHIFT); i++) {
|
ClearPageReserved(start_page_addr+i);
|
ClearPageReserved(start_page_addr+i);
|
//dbg_msg(dbg_trace, "%s(): page_addr[%d] = 0x%x\n", __FUNCTION__, i, (int)(start_page_addr+i));
|
//dbg_msg(dbg_trace, "%s(): page_addr[%d] = 0x%x\n", __FUNCTION__, i, (int)(start_page_addr+i));
|
}
|
}
|
|
|
return i;
|
return i;
|
}
|
}
|
|
|
//--------------------------------------------------------------------
|
//--------------------------------------------------------------------
|
|
|
|
int check_address( void *pMemUserAddr )
|
|
{
|
|
size_t addr = (size_t)pMemUserAddr;
|
|
size_t mask = (size_t)~PAGE_MASK;
|
|
|
|
printk("%s()\n", __FUNCTION__);
|
|
|
|
// адрес пользовательского буфера должен быть выровнен на страницу
|
|
if(addr & mask) {
|
|
printk("%s(): %p - Error! Address must be aling at PAGE_SIZE border\n", __FUNCTION__, pMemUserAddr );
|
|
return 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
|
|
int check_size( size_t userSize )
|
|
{
|
|
printk("%s()\n", __FUNCTION__);
|
|
|
|
// размер пользовательского буфера должен быть кратен размеру страницы
|
|
if((userSize % PAGE_SIZE) != 0) {
|
|
printk("%s(): Invalid user memory block size - 0x%lX.\n", __FUNCTION__, userSize);
|
|
return 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
|
|
int lock_user_memory( SHARED_MEMORY_DESCRIPTION *MemDscr, void* userSpaceAddress, size_t userSpaceSize )
|
|
{
|
|
int i = 0;
|
|
int requested_page_count = 0;
|
|
int allocated_page_count = 0;
|
|
|
|
printk("%s()\n", __FUNCTION__);
|
|
|
|
if(!MemDscr) {
|
|
printk("%s(): Invalid memory descriptor.\n", __FUNCTION__);
|
|
return -EINVAL;
|
|
}
|
|
|
|
requested_page_count = (userSpaceSize >> PAGE_SHIFT);
|
|
|
|
MemDscr->LockedPages = (struct page**)kmalloc(requested_page_count*sizeof(struct page*), GFP_KERNEL);
|
|
if(!MemDscr->LockedPages) {
|
|
printk("%s(): Cant allocate memory for locked pages pointers.\n", __FUNCTION__);
|
|
return -ENOMEM;
|
|
}
|
|
|
|
memset(MemDscr->LockedPages,0,requested_page_count*sizeof(struct page*));
|
|
|
|
down_read(¤t->mm->mmap_sem);
|
|
#if LINUX_VERSION_CODE < KERNEL_VERSION(4,5,0)
|
|
allocated_page_count = get_user_pages(current,
|
|
current->mm,
|
|
(size_t)userSpaceAddress,
|
|
requested_page_count,
|
|
1,
|
|
0,
|
|
MemDscr->LockedPages,
|
|
0);
|
|
#endif
|
|
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4,5,0)) && (LINUX_VERSION_CODE < KERNEL_VERSION(4,9,0))
|
|
allocated_page_count = get_user_pages((size_t)userSpaceAddress,
|
|
requested_page_count,
|
|
1,
|
|
0,
|
|
MemDscr->LockedPages,
|
|
0);
|
|
#endif
|
|
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4,9,0))
|
|
allocated_page_count = get_user_pages((size_t)userSpaceAddress,
|
|
requested_page_count,
|
|
1,
|
|
MemDscr->LockedPages,
|
|
0);
|
|
#endif
|
|
|
|
up_read(¤t->mm->mmap_sem);
|
|
|
|
// если все ok то result содержит число страниц в массиве struct page *pages
|
|
if(MemDscr->PageCount <= 0) {
|
|
printk("%s(): Error to lock memory pages.\n", __FUNCTION__);
|
|
kfree(MemDscr->LockedPages);
|
|
MemDscr->LockedPages = NULL;
|
|
MemDscr->PageCount = 0;
|
|
return -ENOMEM;
|
|
}
|
|
|
|
printk("%s(): MemDscr->PageCount = %ld\n", __FUNCTION__, MemDscr->PageCount);
|
|
printk("%s(): MemDscr->LockedPages = %p\n", __FUNCTION__, MemDscr->LockedPages);
|
|
|
|
for(i=0; i<MemDscr->PageCount; i++) {
|
|
|
|
printk("%s(): LockedPages[%d] = %p\n", __FUNCTION__, i, MemDscr->LockedPages[i]);
|
|
printk("%s(): PhysicalAddress = %p\n", __FUNCTION__, (void*)page_to_phys(MemDscr->LockedPages[i]));
|
|
|
|
if(!PageReserved(MemDscr->LockedPages[i])) {
|
|
SetPageReserved(MemDscr->LockedPages[i]);
|
|
}
|
|
}
|
|
|
|
printk("%s(): Lock %ld memory pages\n", __FUNCTION__, MemDscr->PageCount);
|
|
|
|
return 0;
|
|
}
|
|
|
//--------------------------------------------------------------------
|
//--------------------------------------------------------------------
|
/*
|
|
static int copy_memory_descriptors(unsigned long arg, struct memory_descriptor *md, struct memory_block **mb)
|
int unlock_user_memory( SHARED_MEMORY_DESCRIPTION *MemDscr )
|
{
|
{
|
struct memory_block *mblocks = NULL;
|
int i = 0;
|
int error = 0;
|
|
//int i = 0;
|
printk("%s()\n", __FUNCTION__);
|
|
|
if(copy_from_user((void*)md, (void*)arg, sizeof(struct memory_descriptor))) {
|
if(!MemDscr) {
|
err_msg(err_trace, "%s(): Error copy memory descriptor from user space\n", __FUNCTION__);
|
printk("%s(): Invalid parameter MemDscr = %p\n", __FUNCTION__, MemDscr);
|
error = -EINVAL;
|
return -EINVAL;
|
goto do_exit;
|
}
|
}
|
|
|
printk("%s(): MemDscr = %p\n", __FUNCTION__, MemDscr);
|
dbg_msg(dbg_trace, "%s(): md.total_blocks = %zd\n", __FUNCTION__, md->total_blocks );
|
|
dbg_msg(dbg_trace, "%s(): md.blocks = %p\n", __FUNCTION__, md->blocks );
|
if(MemDscr->LockedPages)
|
|
printk("%s(): MemDscr->LockedPages = %p\n", __FUNCTION__, MemDscr->LockedPages);
|
mblocks = kzalloc(md->total_blocks*sizeof(struct memory_block), GFP_KERNEL);
|
|
if(!mblocks) {
|
for(i=0; i<MemDscr->PageCount; i++) {
|
err_msg(err_trace, "%s(): Error allocate memory for memory descriptors\n", __FUNCTION__);
|
if(MemDscr->LockedPages[i]) {
|
error = -ENOMEM;
|
ClearPageReserved(MemDscr->LockedPages[i]);
|
goto do_exit;
|
//page_cache_release(MemDscr->LockedPages[i]);
|
}
|
printk("%s(): Unlock page %p\n", __FUNCTION__, MemDscr->LockedPages[i]);
|
|
|
if(copy_from_user((void*)mblocks, (void*)md->blocks, md->total_blocks*sizeof(struct memory_block))) {
|
|
err_msg(err_trace, "%s(): Error copy memory blocks from user space\n", __FUNCTION__);
|
|
error = -EINVAL;
|
|
goto do_free_mem;
|
|
}
|
|
|
|
//for(i=0; i<md->total_blocks; i++) {
|
|
// dbg_msg(dbg_trace, "%s(): mb[%d].size = 0x%x\n", __FUNCTION__, i, mblocks[i].size );
|
|
//}
|
|
|
|
*mb = mblocks;
|
|
|
|
return 0;
|
|
|
|
do_free_mem:
|
|
kfree(mb);
|
|
|
|
do_exit:
|
|
return error;
|
|
}
|
|
*/
|
|
//-----------------------------------------------------------------------------
|
|
|
|
int lock_user_pages(unsigned long addr, int size)
|
|
{
|
|
//int res = 0;
|
|
//res = get_user_pages(current, current->mm, unsigned long start, int nr_pages, int write, int force,
|
|
// struct page **pages, struct vm_area_struct **vmas);
|
|
return -1;
|
|
}
|
}
|
|
}
|
|
|
|
if(MemDscr->LockedPages)
|
|
kfree(MemDscr->LockedPages);
|
|
|
//-----------------------------------------------------------------------------
|
return 0;
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
|
void* allocate_memory_block(struct pex_device *brd, size_t block_size, dma_addr_t *dma_addr)
|
void* allocate_memory_block(struct pex_device *brd, size_t block_size, dma_addr_t *dma_addr)
|
{
|
{
|
struct mem_t *m = NULL;
|
struct mem_t *m = NULL;
|
void *cpu_addr = NULL;
|
void *cpu_addr = NULL;
|