PB173 - Ovladače jádra - Linux IX. mmap Jiri Slabý ITI, Fakulta informatiky 19. 11. 2013 J. Slabý (ITI, Fl) PB173/02 19. 11. 2013 1 /10 Paměť jinak I. LDD3 kap. 15 (zastaralá) • I. (dnes): Mapování paměti jádra (mmap) a II. (příště): Přímý přístup do paměti (DMA) J. Slabý (ITI, Fl) PB173/02 19.11.2013 2/ 10 Mapování paměti jádra Předání dat do/z procesu a Známe: read, write, ioctl, . .. • U všeho nutné kopírování dat 9 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 • void *mmap(void *addr, size_t len, int prot, int flags, int fd, off_t off) J. Slabý (ITI, Fl) PB173/02 19. 11. 2013 3/ 10 Ú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 a PROT_WRITE 0 flags . . . MAP_PRIVATE a HAP_AN0NYH0US • fd . . . -1 O Mapování /dev/zero • flags . . . MAP_PRIVATE • f d ... deskriptor otevřeného /dev/zero J. Slabý (ITI, Fl) PB173/02 19. 11. 2013 4/ 10 Parametry mmap v jádře • V uživatelském prostoru volání mmap • 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 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; } Je třeba namapovat stránky mezi vm_start a vm_end. Ale také ověřit privilegia (čtení, zápis, spuštění). POZOR J. Slabý (ITI, Fl) PB173/02 19. 11. 2013 5/ 10 Základní mmap funkce API • linux/mm.h, struct vm_area_struct •__get_free_page/pages =4> remap_pfn_range • vmalloc_user =4> remap_vmalloc_range 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->vmJlags & (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); */ } J. Slaby (ITI, Fl) PB173/02 19. 11. 2013 6/ 10 Úkol Přemapování prostorů O Alokovat 2+2 stránky • Dvoustránku pomocí vmalloc • Dvoustránku pomocí stránkového alokátoru Q 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 API (zopakováno) • 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 J. Slabý (ITI, Fl) PB173/02 19.11.2013 7/ 10 mmap po stránkách 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" o Stará jádra: nopage • Nová jádra: fault • V mmap/nopage/f ault je třeba zkontrolovat rozsahy a velikosti • Předtím to dělaly remap_*_range funkce • vma->vm_ops • Struktura ukazující na háčky (včetně nopage/f ault) • vma->vm_private_data • Pro naše potřeby • K předání informací Z f ile_operations->mmap do vm_ops->* J. Slabý (ITI, Fl) PB173/02 19. 11. 2013 8/ 10 mmap po strankach struct 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); } int my.fau It (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); (Ipage) return VM.FAULT.SIGBUS; get.page(page); vmf->page = page; return 0; } 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; } J. Slaby (ITI, Fl) PB173/02 19.11.2013 9/ 10 Úkol Mapování roztroušených stránek (součást domácího) O Předchozí příklad rozšiřte Q Místo alokací dvoustránek alokujte 4 samostatné stránky • 2x vmalloc a 2x __get_free_pages O Přemapovat stránky v mmap ■ Změna remap_pfn_range na vma->vm_ops->f ault O Userspace program stejný (funkčnost navenek stejná) 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 J. Slabý (ITI, Fl) PB173/02 19. 11. 2013 10/10