PB173 - Ovladače jádra - Linux IX. Jiří Slabý ITI, Fakulta Informatiky 23. 11. 2010 J. Slabý (ITI) PB173/01 23. 11. 2010 1 / 1 Paměť jinak I. LDD3 kap. 15 (zastaralá) • I. (dnes): Mapování paměti jádra (mmap) « II. (příště): Přímý přístup do paměti (DMA) J. Slabý (ITI) PB173/01 23.11.2010 2/1 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 23. 11. 2010 3/1 mmap • Jeden Člen V struct f ile_operations • int mmap(struct file *filp, struct vm_area_struct *vma) • V userspace odpovídá volání mmap • void *mmap(void *addr, size.t len, int prot, int flags, int fd, off.t off) 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í). J. Slabý (ITI) PB173/01 23. 11. 2010 4/1 Základní mmap funkce API • linux/mm.h, struct vm_area_struct • __get_f ree_page* =4> remap_pfn.range • vmalloc.user =4> remap.vmalloc.range 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 , virt.to.priys (mem) » PAGE.SHIFT, 4 * PAGE.SIZE, vma->vm_page.prot) ; /* return remap.vmalloc.range (vma, mem, 0); */ } J. Slabý (ITI) PB173/01 23. 11. 2010 5/1 Úkol Přemapování prostorů O Alokovat souvislé 2 a 2 stránky (vmalloc a page alokátory) O Zapsat na každou stránku libovolný různý řetězec 0 Přemapovat stránky v mmap Jedna dvojice R/W, druhá RO • 0 < pgof f <2=> jedno mapování • 2 < pgof f druhé mapování 0 Z userspace 2 x mmap s off 0 a 2*4096 • V pb173/09 API znovu • linux/mm.h, struct vm_area_struct • int mmap(struct file *filp, struct vm_area_struct *vma) • __get_f ree_page* =4> remap_pfn.range • vmalloc_user =4> remap_vmalloc_range J. Slabý (ITI) PB173/01 23. 11. 2010 6/1 mmap po stránkách 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í tyto stránky jednotlivě • Každý ovladač má „page fault handier" • Stará jádra: nopage • Nová jádra: fault • V mmap/nopage/f ault je třeba zkontrolovat rozsahy a velikosti • Před tí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 mmap do vm_ops J. Slabý (ITI) PB173/01 23. 11. 2010 7/1 mmap po stránkách (ponovu) Nové API struct vm.operations.struct { void (*open) (struct vm.area-Struct *vma) ; void (* close )( struct vm.area.struct *vma) ; int (* fau It)(struct vm.area.struct *vma, struct vm.fault *vmf) ; } 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 ( off set) ; if (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. Slabý (ITI) PB173/01 23. 11. 2010 8/1 mmap po stránkách (postaru) Stare API struct vm.operations.struct { struct page (*nopage) (struct vm.area.struct *vma, unsigned long address , int *type) } struct page *my_nopage( struct vm.area.struct *vma, unsigned long address, int *type) { /* my.data = vma->vm_private.data ; */ unsigned long offset = vma->pgoff « PAGE.SHIFT; struct page *page; offset += address - vma->vm_start; page = my.find.page ( offset) ; if (Ipage) return NOPAGE.SIGBUS; get.page(page) ; if (type) *type = VM_FAULT_MINOR; return page; } J. Slabý (ITI) PB173/01 23. 11. 2010 9/1 Úkol Mapování roztroušených stránek (domácí) O Předchozí příklad rozšiřte O Místo alokací dvojstránky alokovat 2 samostatné stránky • __get_f ree_pages (1) —>• 2x __get_f ree_page O Přemapovat stránky v mmap • remap_pfn.range —> vma->vm_ops->nopage O Userspace program stejný Potřebné podkroky • Definice struct page *nopage (struct vm_area_struct *vma, unsigned long address, int *type) • Kontrola rozsahů v mmap (end-start < 2*page_size apod.) « Definice vm_ops a přiřazení do vma->vm_ops J. Slabý (ITI) PB173/01 23. 11. 2010 10/1