site_archiver@lists.apple.com Delivered-To: darwin-kernel@lists.apple.com What's the equivalent of Linux's kmap to map a user virtual address into the kernel memory space so that it is accessible "magically" (i.e. without any additional mapping/unmapping required) to all other tasks and kernel threads? What do you mean by 'accessible "magically"'? static inline struct page *ntfs_map_page(struct address_space *mapping, pgoff_t index) { struct page *page; page = read_mapping_page(mapping, index, NULL); if (!IS_ERR(page)) { wait_on_page_locked(page); kmap(page); if (PageUptodate(page) && !PageError(page)) return page; ntfs_unmap_page(page); return ERR_PTR(-EIO); } return page; } errno_t ntfs_page_map_ext(ntfs_inode *ni, s64 ofs, upl_t *upl, upl_page_info_array_t *pl, u8 **kaddr, const BOOL rw) { s64 size; kern_return_t kerr; int abort_flags; errno_t err; Best regards, Anton -- Anton Altaparmakov <aia21 at cam.ac.uk> (replace at with @) Unix Support, Computing Service, University of Cambridge, CB2 3QH, UK Linux NTFS maintainer, http://www.linux-ntfs.org/ _______________________________________________ Do not post admin requests to the list. They will be ignored. Darwin-kernel mailing list (Darwin-kernel@lists.apple.com) Help/Unsubscribe/Update your Subscription: http://lists.apple.com/mailman/options/darwin-kernel/site_archiver%40lists.a... On 7 Mar 2007, at 11:32, Michael Smith wrote: On Mar 6, 2007, at 4:35 PM, Bhavesh Davda wrote: Are you just trying to make a portion of a user map visible in the kernel map, or are you trying to project that space into other maps as well? From what I can tell, the Linux 'kmap' call just maps a single user page somewhere into the kernel address space, so I'm assuming that you mean "so that other processes can call code in the kernel and see this page from there". No that is not kmap does. kmap is used to map the data content of a "struct page" (i.e. a page in the VM) into the kernel address space for access. I will give a concrete example from the Linux NTFS file system driver and show you the equivalent code from the OSX NTFS driver. If Bhavesh is asking about a file system then this is the answer he is looking for... Ok, on Linux in NTFS we map the content of a page at offset OFS of a file using (note index = OFS >> PAGE_CACHE_SHIFT): The important point of note is that once we have the struct page we run "kmap(page);" after which we can call "page_address(page)" to obtain the virtual memory pointer at which we can read/write the data content of the page. And now on OSX we do the same but it is a bit more involved (I have oversimplified the code for simplicity - we only really care about mapping the page anyway): if (ofs & PAGE_MASK) panic("%s() called with non page aligned offset (0x% llx).", __FUNCTION__, (unsigned long long)ofs); size = ubc_getsize(ni->vn); if (ofs > size) { ntfs_error(ni->vol->mp, "Offset 0x%llx is outside the end of " "the attribute (0x%llx).", (unsigned long long)ofs, (unsigned long long)size); return EINVAL; } /* Create a page list for the wanted page. */ kerr = ubc_create_upl(ni->vn, ofs, PAGE_SIZE, upl, pl, UPL_SET_LITE | (rw ? UPL_WILL_MODIFY : 0)); if (kerr != KERN_SUCCESS) panic("%s(): Failed to get page (error %d).\n", __FUNCTION__, (int)kerr); /* * If the page is not valid, need to read it in from the vnode now thus * making it valid. */ if (!upl_valid_page(*pl, 0)) { ntfs_debug("Reading page as it was not valid."); err = ntfs_pagein(ni, ofs, PAGE_SIZE, *upl, 0, UPL_IOSYNC | UPL_NOCOMMIT); if (err) { ntfs_error(ni->vol->mp, "Failed to read page (error " "%d).", err); goto pagein_err; } } /* Map the page into the kernel's address space. */ kerr = ubc_upl_map(*upl, (vm_offset_t*)kaddr); if (kerr == KERN_SUCCESS) { ntfs_debug("Done."); return 0; } ntfs_error(ni->vol->mp, "Failed to map page (error %d).", (int)kerr); err = EIO; pagein_err: abort_flags = UPL_ABORT_FREE_ON_EMPTY; if (!upl_valid_page(*pl, 0) || (vnode_isnocache(ni->vn) && !upl_dirty_page (*pl, 0))) abort_flags |= UPL_ABORT_DUMP_PAGES; ubc_upl_abort_range(*upl, 0, PAGE_SIZE, abort_flags); return err; } The important bit is ubc_upl_map() which maps all the pages in the UPL *upl into a linear virtual memory region which the start address of which will be returned in *kaddr. (i.e. *kaddr == page_address (page) on Linux). If you are not working with a file system then I would suggest checking out what ubc_upl_map() does and following it up that way to figure out what to do analogously. Typically, you don't want to map user data into the kernel in the first place; it's expensive and kernel VM is a scarce resource - typically you will find it's faster just to copy the page in/out. If you are trying to establish a shared page for the purposes of communication, I'd be inclined to encourage you to consider the system's native communication primitives instead. There are lots of ways of moving map entries around depending on what you're trying to achieve. I've already looked at vm_map and AFAICT, that ain't it. If you're doing this in an I/O Kit kext, the canonical tool for handling memory in another address space is the IOMemoryDescriptor. You can use this to map said memory, if you really need it. = Mike This email sent to site_archiver@lists.apple.com