PB173 - Ovladače jádra - Linux IX. mmap Jiri Slabý Fakulta informatiky Masarykova univerzita 26. 11. 2015 Jiri Slabý (Fakulta informatiky, MU) PB173/04 26. 11. 2015 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 26.11.2015 2/ 11 Sekce 1 Mapování paměti jádra (mmap) Jiri Slabý (Fakulta informatiky, MU) PB173/04 26. 11. 2015 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 26. 11. 2015 4/11 Úkol Alokace pomocí mmap (uživatelský prostor) 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.WRITE • flags ... MAP.PRIVATE | MAP.ANONYMOUS • fd ... -1 Q Mapování/dev/zero • len a prot stejné • flags ... MAP.PRIVATE • f d ... deskriptor otevřeného /dev/zero Jiri Slabý (Fakulta informatiky, MU) PB173/04 26. 11. 2015 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 V struct file.operations • int mmap(struct file *filp, struct vm_area_struct *vma) • Parametry jsou předány přes struct vm_area_struct :uct vm area struct unsigned long vm_start; /* addr or random when addr is NULL */ unsigned long vm_end; /* vm_end = vm_start+len */ unsigned long vm_pgoff; /* vm_pgoff = off/PAGE_SIZE */ unsigned long vm_flags; /* vm_flags = encoded(flags|prot), see VM_READ etc. */ pgproM vm_page_prot; /* only for remap_* functions */ const struct vm_operations_struct *vm_ops; /* later ... */ void *vm_private_data; Ovladač musí mapovat stránky mezi vm.start a vm_end. Ale POZOR, také ověřit privilegia (čtení, zápis, spuštění). Jiri Slabý (Fakulta informatiky, MU) PB173/04 26. 11. 2015 6/11 Základní mmap funkce API • linux/mm.h, struct vm_area_struct •__get_f ree_page/pages =4> remap_pf n_range • vmalloc_user =4> 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 * PAGE_SIZE, vma->vm_page_prot); /* return remap_vmalloc_range(vma, mem, 0); */ Jiri Slabý (Fakulta informatiky, MU) PB173/04 26. 11. 2015 7/11 Úkol Přemapování 2 prostorů O Alokovat 2+2 stránky • DvoUStránku pomocí vmalloc.user • Dvoustránku pomocí stránkového alokátoru O Zapsat na všechny 4 stránky libovolný, ale různý řetězec O Vystavit (mapovat) stránky v mmap • První dvojice RO, druhá R/W (ověřte prot, tj. vma->vm_f lags) • 0 < vma->vm_pgof f < 2 jedno mapování • 3 < vma->vm_pgof f < 4 druhé mapování O Z userspace 2x mmap s off 0 a 2*4096 • Již hotOVO V pbl73/09/pt>173 . 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 26. 11. 2015 8/11 mmap po stránkách 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ě • 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 • 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) • vma->vm_private_data • Pro naše potřeby o K předání informací Z f ile_operations->mmap do vm_ops->* Jiri Slabý (Fakulta informatiky, MU) PB173/04 26. 11. 2015 9/11 mmap po strankach - priklad int my_fault(struct vm_area_struct *vma, struct vm_fault *vmf) { /* my_data == vma->vm_private_data; */ unsigned long offset = vmf->pgoff« PAGE_SHIFT; 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 26.11.2015 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řemapovat 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 26. 11. 2015 11/11