реклама на сайте
подробности

 
 
> отмапить виртуальный адрес ядра в пространство пользователя
novartis
сообщение Jan 28 2016, 10:59
Сообщение #1


Местный
***

Группа: Свой
Сообщений: 375
Регистрация: 9-10-09
Из: Свердловский регион
Пользователь №: 52 845



В pcie драйвере вызвал функцию pci_alloc_consistent(). Благодаря этому получил два адреса - один виртуальный адрес ядра, другой - физический адрес. Физический адрес сообщил в плис. Плис пишет данные по этому адресу, выставляет прерывание. В обработчике прерывания печатаю содержимое буфера с виртуальным адресом. Вижу свои данные, все работает.

Вопрос 1. Функция pci_alloc_consistent завершается удачно, если размер запрашиваемого буфера не превышает 4 МБайт. С чем это связано, почему не удаётся получить 8 и больше МБайт?

Вопрос 2. Можно ли замапить виртуальный буфер ядра в пространство пользователя?
Это вообще возможно?
Как я понимаю, физическая память линейна и поделена на траницы. Эти страницы отображаются в виртуальную память в произвольном порядке.
Вызвав функцию pci_alloc_consistent, я зарезервировал большое количество подряд идущих страниц физической памяти и отобразил их в виртуальной памяти.
В виртуальной памяти пользователя свой порядок страниц, это меня и напрягает, получится ли просто замапить виртуальный буфер ядра в виртуальный буфер пользователя, у пользователя как то тоже нужно пересортировать страницы, чтобы они в линию выстроились в физической памяти.
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
novartis
сообщение Feb 1 2016, 17:41
Сообщение #2


Местный
***

Группа: Свой
Сообщений: 375
Регистрация: 9-10-09
Из: Свердловский регион
Пользователь №: 52 845



Удалось отмапить буфер ядра в user space, но данные в буфере юзера циклически повторяются каждые 4096 байт.

В ядре маплю как-то так:
Код
static u64* dma_buf_virt_core_addr_ptr;
static dma_addr_t  dma_bus_addr_for_fpga;

#ifndef VM_RESERVED
#define VM_RESERVED    (VM_DONTEXPAND | VM_DONTDUMP)
#endif

struct mmap_info
{
    uint64_t* data;
    int reference;
};

void mmap_open(struct vm_area_struct* vma)
{
    struct mmap_info* info = (struct mmap_info*)vma->vm_private_data;
    info->reference++;
}

void mmap_close(struct vm_area_struct* vma)
{
    struct mmap_info* info = (struct mmap_info*)vma->vm_private_data;
    info->reference--;
}

static int mmap_fault(struct vm_area_struct* vma, struct vm_fault* vmf)
{
    // если в user space был отмаплен буфер с помощью функции mmap, в которую передали размер буфера 65536,
    // то здесь (vma->vm_end - vma->vm_start) как раз будет равно 65536,
    // то есть делаю вывод, что vma соотносится с созданным буфером в user space.
    struct page* page;
    struct mmap_info* info;

    info = (struct mmap_info*)vma->vm_private_data;
    if (!info->data)
    {
        printk( KERN_INFO "[ag_pcie_driver]:[mmap_fault]: no data");
        return 0;
    }
    
    //get the page
    page = virt_to_page(info->data);
    // increment the reference count of this page
    get_page(page);
    
    vmf->page = page;
    return 0;
}

struct vm_operations_struct mmap_vm_ops =
{
    .open = mmap_open,
    .close = mmap_close,
    .fault = mmap_fault,
};

int mmapfop_mmap(struct file* filp, struct vm_area_struct* vma)
{
    vma->vm_ops = &mmap_vm_ops;
    vma->vm_flags |= VM_RESERVED;
    vma->vm_private_data = filp->private_data;
    mmap_open(vma);
    return 0;
}

int mmapfop_close(struct inode* inode, struct file* filp)
{
    filp->private_data = NULL;
    return 0;
}

int mmapfop_open(struct inode* inode, struct file* filp)
{
    struct mmap_info* info = kmalloc(sizeof(struct mmap_info),GFP_KERNEL);
    info->data = dma_buf_virt_core_addr_ptr;
    filp->private_data = info;
    return 0;
}

static const struct file_operations mmap_fops =
{
    .owner = THIS_MODULE,
    .open = mmapfop_open,
    .release = mmapfop_close,
    .mmap = mmapfop_mmap
};

static struct miscdevice ag_user_struct_miscdevice3 =
{
    MISC_DYNAMIC_MINOR,
    "ag_pcie_driver3",
    &mmap_fops
};

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
static int ag_pciedr_probe( struct pci_dev *dev, const struct pci_device_id *id )
{
   ....
   // выделяю буфер в пространстве ядра
   dma_buf_virt_core_addr_ptr = pci_alloc_consistent( dev, 4194304, &dma_bus_addr_for_fpga);
  
   // передаю в ПЛИС шинный адрес
   iowrite32( (u32)((dma_bus_addr_for_fpga))               ,  0x10);    //low
   iowrite32( (u32)((dma_bus_addr_for_fpga>>32)&0xffffffff), 0x14);    //high
   ....
}


........



В user space открываю устройство и маплю буфер:
Код
ssize_t g_file_fid3 = open ("/dev/ag_pcie_driver3", O_RDWR);

char* g_ptr_mmap3 = (char*)mmap( NULL, 65536, PROT_READ | PROT_WRITE, MAP_SHARED, g_file_fid3, 0);

uint32_t* ptr = (uint32_t*)g_ptr_mmap3;  // для удобства



Теперь засылаю данные из ПЛИС на комп.
Засылаю, например, 100 слов по 32 бит, начиная с 0 адреса.
В ядре вывожу на печать содержимое ядерного буфера dma_buf_virt_core_addr_ptr.
В нем все нормально - первые 100 слов из ПЛИС, дальше все нули.

Печатаю в user space буфер ptr с 0 по 4096 слова.
Вижу первые 100 слов из ПЛИС, дальше нули до 1024 слова.
С 1024 слова опять 100 слов из ПЛИС, дальше нули до 2048 слова.
И т.д.
Как будто первая страница в 4096 Байт (а это 1024 слова по 32 бит) циклически выделяется и повторяется для всего моего буфера g_ptr_mmap3.


Само отображение ядерного буфера в пользовательский буфер происходит в методе mmap_fault.
Если я обращаюсь к g_ptr_mmap3, то я попадаю в mmap_fault.

Мой ядерный адрес лежит в info->data.
Преобразование адреса в номер страницы происходит в строке
page = virt_to_page(info->data);

И получается, что я всегда нахожу первую страницу для моего ядерного адреса.
Как я думаю, нужно как то добавить нужное смещение в эту строчку и все заработает.
Даже нашел, что в переменной vmf->pgoff хранится номер страницы пользовательского буфера, к которой я и обращаюсь.
Но правильно реализовать мозгов не хватает...

Пробовал просто добавить смещение в строчку
page = virt_to_page(info->data+4096);
Но данные в пользовательском буфере все равно не корректны, к тому же это иногда приводит зависанию компа).

Подскажите, как правильно отмапить нужную страницу, осталось то вроде чуть чуть.




Go to the top of the page
 
+Quote Post



Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 25th August 2025 - 04:04
Рейтинг@Mail.ru


Страница сгенерированна за 0.01354 секунд с 7
ELECTRONIX ©2004-2016