* @brief Map a file page into virtual address space * * This function maps a file page into the specified virtual address space, handling * memory allocation, page lookup, and cache synchronization. It ensures proper * memory visibility across different CPU architectures with cache operations. * * @param[in] file Pointer to the file structure * @param[in] varea Pointer to the virtual a
| 1816 | * manages the mapping structure lifecycle through proper allocation/free. |
| 1817 | */ |
| 1818 | void *dfs_aspace_mmap(struct dfs_file *file, struct rt_varea *varea, void *vaddr) |
| 1819 | { |
| 1820 | void *ret = RT_NULL; |
| 1821 | struct dfs_page *page; |
| 1822 | struct dfs_aspace *aspace = file->vnode->aspace; |
| 1823 | rt_aspace_t target_aspace = varea->aspace; |
| 1824 | |
| 1825 | page = dfs_page_lookup(file, dfs_aspace_fpos(varea, vaddr)); |
| 1826 | if (page) |
| 1827 | { |
| 1828 | struct dfs_mmap *map = (struct dfs_mmap *)rt_calloc(1, sizeof(struct dfs_mmap)); |
| 1829 | if (map) |
| 1830 | { |
| 1831 | void *pg_vaddr = page->page; |
| 1832 | void *pg_paddr = rt_kmem_v2p(pg_vaddr); |
| 1833 | int err = rt_varea_map_range(varea, vaddr, pg_paddr, page->size); |
| 1834 | if (err == RT_EOK) |
| 1835 | { |
| 1836 | /** |
| 1837 | * Note: While the page is mapped into user area, the data writing into the page |
| 1838 | * is not guaranteed to be visible for machines with the *weak* memory model and |
| 1839 | * those Harvard architecture (especially for those ARM64) cores for their |
| 1840 | * out-of-order pipelines of data buffer. Besides if the instruction cache in the |
| 1841 | * L1 memory system is a VIPT cache, there are chances to have the alias matching |
| 1842 | * entry if we reuse the same page frame and map it into the same virtual address |
| 1843 | * of the previous one. |
| 1844 | * |
| 1845 | * That's why we have to do synchronization and cleanup manually to ensure that |
| 1846 | * fetching of the next instruction can see the coherent data with the data cache, |
| 1847 | * TLB, MMU, main memory, and all the other observers in the computer system. |
| 1848 | */ |
| 1849 | rt_hw_cpu_dcache_ops(RT_HW_CACHE_FLUSH, vaddr, ARCH_PAGE_SIZE); |
| 1850 | rt_hw_cpu_icache_ops(RT_HW_CACHE_INVALIDATE, vaddr, ARCH_PAGE_SIZE); |
| 1851 | |
| 1852 | ret = pg_vaddr; |
| 1853 | map->aspace = target_aspace; |
| 1854 | map->vaddr = vaddr; |
| 1855 | dfs_aspace_lock(aspace); |
| 1856 | rt_list_insert_after(&page->mmap_head, &map->mmap_node); |
| 1857 | dfs_page_release(page); |
| 1858 | dfs_aspace_unlock(aspace); |
| 1859 | } |
| 1860 | else |
| 1861 | { |
| 1862 | dfs_page_release(page); |
| 1863 | rt_free(map); |
| 1864 | } |
| 1865 | } |
| 1866 | else |
| 1867 | { |
| 1868 | dfs_page_release(page); |
| 1869 | } |
| 1870 | } |
| 1871 | |
| 1872 | return ret; |
| 1873 | } |
| 1874 | |
| 1875 | /** |
no test coverage detected