PB173 - Ovladače jádra - Linux IX. mmap Jiri Slabý Fakulta informatiky Masarykova univerzita 18. 11. 2014 Jiri Slabý (Fakulta informatiky, MU) PB173/02 18. 11. 2014 1/11 Paměť jinak I. LDD3 kap. 15 (zastaralá) O 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ě a Přímý přístup do paměti (DMA) Jiri Slabý (Fakulta informatiky, MU) PB173/02 18.11.2014 2/ 11 Sekce 1 Mapování paměti jádra (mmap) Jiri Slabý (Fakulta informatiky, MU) PB173/02 18. 11. 2014 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 • Syscall: mmap Prototyp systémového volání mmap void *mmap(void *addr, size_t len, int prot, int flags, int fd, off_t off); Jiri Slabý (Fakulta informatiky, MU) PB173/02 18. 11. 2014 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 . .. PR0T_READ | PROT_WRITE • flags .. . MAP_PRIVATE | MAP_AN0NYM0US • fd .. . -1 Q Mapování /dev/zero • flags .. . MAP_PRIVATE • f d ... deskriptor otevřeného /dev/zero Jiri Slabý (Fakulta informatiky, MU) PB173/02 18. 11. 2014 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 jedna položka V struct f ile_operations • int mmap(struct file *filp, struct vm_area_struct *vma) • Parametry JSOU V struct vm_area_struct ; 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) */ pgprot_t 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/02 18. 11. 2014 6/11 Základní mmap funkce API • linux/mm.h, struct vm_area_struct •__get_f ree_page/pages =4> remap_pfn_range • vmalloc_user =4> remap_vmalloc_range Příklad použití int myjnit(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/02 18. 11. 2014 7/11 Úkol Přemapování 2 prostorů O Alokovat 2+2 stránky • Dvoustránku pomocí vmalloc • 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ěření prot) • 0 < pgof f <2=> jedno mapování • 2 < pgof f druhé mapování O Z userspace 2x mmap s off o a 2*4096 • Již hotOVO V pbl73/09/pbl73. c API (opakovánQ • linux/mm.h, struct vm_area_struct • int mmap(striict file *filp, struct vm_area_striict *vma) •__get_free_page* => remap_pfn_range • vmalloc_user => remap_vmalloc_range Jiri Slabý (Fakulta informatiky, MU) PB173/02 18.11.2014 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 a 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í f ault • 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 o Pro naše potřeby • K předání informací Z f ile_operations->mmap do vm_ops->* Jiri Slabý (Fakulta informatiky, MU) PB173/02 18. 11. 2014 9/11 mmap po stránkách - příklad int my_fauInstruct 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); (!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 Slabý (Fakulta informatiky, MU) PB173/02 18. 11. 2014 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(PAGE_SIZE) a2x __get_free_page 0 Přemapovat stránky v mmap • Změna remap_pfn_range na vma->vm_ops->f ault O Userspace program stejný • Funkčnost navenek musí být zachovaná Potřebné podkroky • Definice int f ault (stmct vm_area_struct *vma, stmct vm_faiilt *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/02 18. 11. 2014 11/11