PB173 - Ovladače jádra - Linux X. mmap Jiri Slabý Fakulta informatiky Masarykova univerzita 22. 11. 2016 Jiri Slabý (Fakulta informatiky, MU) PB173/04 22. 11. 2016 1 /11 Paměť jinak I. LDD3 kap. 15 (zastaralá) Q Mapování paměti jádra (mmap) • mmap v uživatelském prostoru • mmap v jádře • mmap po stránkách Příště • Přímý přístup do paměti (DMA) Jiri Slabý (Fakulta informatiky, MU) PB173/04 22. 11. 2016 2/11 Sekce 1 Mapování paměti jádra (mmap) Jiri Slabý (Fakulta informatiky, MU) PB173/04 22. 11. 2016 3/11 Mapování paměti jádra Předání dat do/z procesu • Známe: read, write, ioctl, ... • U všeho nutné kopírování dat • copy_{f rom,to}_user apod. Mapování paměti • Namapování stránek do procesu • Proces používá kus stejné paměti jako jádro Systémové volání mmap (uživatelský prostor) void *mmap(void *addr, size_t len, int prot, int flags, int fd, off_t off); Jiri Slabý (Fakulta informatiky MU) PB173/04 22. 11. 2016 4/11 Úkol Alokace pomocí mmap (uživatelský prostor) O Upravujte nějaký main, c v uživatelském prostoru O Anonymní paměť • void *mmap(void *addr, size_t len, int prot, int flags, int fd, off_t off) • len: 20M • prot: PROT.READ | PROT.WRJTE • flags: MAP.PRIVATE | MAP.ANONYMOUS • fd: -1 O Mapování/dev/zero • len a prot stejné • flags: MAP_PRIVATE 9 f d: deskriptor otevřeného /dev/zero Jiri Slabý (Fakulta informatiky, MU) PB173/04 22. 11. 2016 5/11 Parametry mmap v jádře • V uživatelském prostoru • void *mmap(void *addr, size_t len, int prot, int flags, int fd, off_t off) • V jádře (opět) jedna položka ve struct f ile.operations • int mmap(struct file *filp, struct vm_area_struct *vma) o Parametry jsou předány přes struct vm_area_struct • Ovladač musí mapovat stránky mezi vm.start a vm.end o Ale POZOR, také ověřit privilegia (čtení, zápis, spuštění). vm area struct unsigned long vmstart; /* addr or random when addr is NULL */ unsigned long vm_end; /* vm_end = vm_start+len */ unsigned long vmpgoff; /* vmpgoff = off/PAGESIZE */ unsigned long vmflags; /* vmflags = encoded(flags|prot), see VMREAD etc. */ pgprot_t vm_page_prot; /* only for remap_* functions */ const struct vm_operations_struct *vm_ops; /* later ... */ void *vm_private_data; Jiri Slabý (Fakulta informatiky, MU) PB173/04 22. 11. 2016 6/11 Základní mmap funkce • linux/mm.h, struct vm_area_struct •__get_free_page/pages remap_pfn_range • vmalloc_user remap_vmalloc_range Příklad int my_init(void) { mem =_get_free_pages(GFP_KERNEL, 2); /* mem = vmalloc_user(PAGE_SIZE); */ } int my_mmap(struct file *filp, struct vm_area_struct *vma) { if ((vma->vm_flags & (VM_WRITE | VM_READ)) != VM_READ) return -EINVAL; return remap_pfn_range(vma, vma->vm_start, page_to_pfn(virt_to_page(mem)), 4 * PAGESIZE, vma->vm_page_prot); /* return remap_vmalloc_range(vma, mem, 0); */ } J Jiri Slabý (Fakulta informatiky, MU) PB173/04 22. 11. 2016 7/11 Ukol Přemapování 2 prostorů O V module.init alokujte 2+2 stránky DvojStránku pomocí vmalloc_user • Dvojstránku pomocí stránkového alokátoru Q Zapište na všechny 4 stránky libovolný, ale různý řetězec O Vystavte (mapujte) stránky v mmap • První dvojice RO, druhá R/W (ověřte prot, tj. vma->vm_f lags) o 0 < vma->vm_pgof f < 2 jedno mapování • 2 < vma->vm_pgof f < 4 druhé mapování O Z userspace vyzkoušejte • Prostudujte a spusťte pbi73/io/pbi73. c API (opakování) • linux/mm.h, struct vm_area_struct • int mmap(struct file *filp} struct vm_area_struct *vma) •__get_free_page* remap_pfn_range • vmalloc_user remap_vmalloc_range Jiri Slabý (Fakulta informatiky, MU) PB173/04 22. 11. 2016 8/11 mmap po stránkách rstruct vm_operations_struct ] void (*open)(struct vm_area_struct *vma); void (*close) (struct vm_area_struct *vma); int (* fault) (struct vm_area_struct *vma, struct vm_fault *vmf); Přemapování roztroušených stránek • Přes remap_pf n_range obtížně o Při výpadcích stránek se mapují takové stránky jednotlivě • Každý ovladač má „page fault handier" • Háčky struct vm_operations_struct a v ní fault a V mmap/f ault je třeba zkontrolovat rozsahy a velikosti • Předtím to dělaly remap_*_range funkce • vma->vm_ops se nastaví V mmap Na strukturu s háčky (zejm. fault) o vma->vm_private_data • Pro naše potřeby • K předání informací Z f ile_operations->mmap do vm_ops->* Jiri Slabý (Fakulta informatiky, MU) PB173/04 22. 11. 2016 9/11 mmap po strankach - priklad int my_fauInstruct vm_area_struct *vma, struct vm_fault *vmf) { /* my_data == vma->vm_private_data; */ unsigned long offset = vmf->pgoff « PAGESHIFT; struct page *page; page = my_find_page (offset); if (!page) return VM_FAULT_SIGBUS; get_page(page); vmf->page = page; return 0; } struct vm_operations_struct my_vm_ops = {.fault = my_fault,}; int my_mmap(struct file *filp, struct vm_area_struct *vma) { /* don't forget to check ranges */ vma->vm_ops = &my_vm_ops; vma->vm_private_data = my_data; return 0; } Jiri Slaby (Fakulta informatiky, MU) PB173/04 22.11.2016 10/11 Úkol Mapování roztroušených stránek (součást domácího) O Předchozí příklad rozšiřte O Místo alokací dvoustránek alokujte 4 samostatné stránky • 2x vmalloc_user(PAGE_SIZE) a2x__get_free_page O Přemapujte stránky v mmap • Změna remap_pf n_range na vma->vm_ops->f ault O Userspace program stejný • Funkčnost navenek musí být zachovaná Potřebné podkroky • Definice int fault(struct vm_area_struct *vma, struct vm_fault *vmf); • Kontrola rozsahů V mmap (end-start < 2*PAGE_SIZE apod.) • Definice vm_ops a přiřazení do vma->vm_ops Jiri Slabý (Fakulta informatiky, MU) PB173/04 22. 11. 2016 11/11