| @@ -1664,6 +1664,9 @@ out_unlock: · 1663 unmodified lines |
| 1664 | 1664 | * vmf_insert_pfn_prot should only be used if using multiple VMAs is |
| 1665 | 1665 | * impractical. |
| 1666 | 1666 | * |
| 1667 | + * See vmf_insert_mixed_prot() for a discussion of the implication of using |
| 1668 | + * a value of @pgprot different from that of @vma->vm_page_prot. |
| 1669 | + * |
| 1667 | 1670 | * Context: Process context. May allocate using %GFP_KERNEL. |
| 1668 | 1671 | * Return: vm_fault_t value. |
| 1669 | 1672 | */ |
| @@ -1737,9 +1740,9 @@ static bool vm_mixed_ok(struct vm_area_struct *vma, pfn_t pfn) · 67 unmodified lines |
| 1737 | 1740 | } |
| 1738 | 1741 | |
| 1739 | 1742 | static vm_fault_t __vm_insert_mixed(struct vm_area_struct *vma, |
| 1740 | | − unsigned long addr, pfn_t pfn, bool mkwrite) |
| 1743 | + unsigned long addr, pfn_t pfn, pgprot_t pgprot, |
| 1744 | + bool mkwrite) |
| 1741 | 1745 | { |
| 1742 | | − pgprot_t pgprot = vma->vm_page_prot; |
| 1743 | 1746 | int err; |
| 1744 | 1747 | |
| 1745 | 1748 | BUG_ON(!vm_mixed_ok(vma, pfn)); |
| @@ -1782,10 +1785,42 @@ static vm_fault_t __vm_insert_mixed(struct vm_area_struct *vma, · 36 unmodified lines |
| 1782 | 1785 | return VM_FAULT_NOPAGE; |
| 1783 | 1786 | } |
| 1784 | 1787 | |
| 1788 | +/** |
| 1789 | + * vmf_insert_mixed_prot - insert single pfn into user vma with specified pgprot |
| 1790 | + * @vma: user vma to map to |
| 1791 | + * @addr: target user address of this page |
| 1792 | + * @pfn: source kernel pfn |
| 1793 | + * @pgprot: pgprot flags for the inserted page |
| 1794 | + * |
| 1795 | + * This is exactly like vmf_insert_mixed(), except that it allows drivers to |
| 1796 | + * to override pgprot on a per-page basis. |
| 1797 | + * |
| 1798 | + * Typically this function should be used by drivers to set caching- and |
| 1799 | + * encryption bits different than those of @vma->vm_page_prot, because |
| 1800 | + * the caching- or encryption mode may not be known at mmap() time. |
| 1801 | + * This is ok as long as @vma->vm_page_prot is not used by the core vm |
| 1802 | + * to set caching and encryption bits for those vmas (except for COW pages). |
| 1803 | + * This is ensured by core vm only modifying these page table entries using |
| 1804 | + * functions that don't touch caching- or encryption bits, using pte_modify() |
| 1805 | + * if needed. (See for example mprotect()). |
| 1806 | + * Also when new page-table entries are created, this is only done using the |
| 1807 | + * fault() callback, and never using the value of vma->vm_page_prot, |
| 1808 | + * except for page-table entries that point to anonymous pages as the result |
| 1809 | + * of COW. |
| 1810 | + * |
| 1811 | + * Context: Process context. May allocate using %GFP_KERNEL. |
| 1812 | + * Return: vm_fault_t value. |
| 1813 | + */ |
| 1814 | +vm_fault_t vmf_insert_mixed_prot(struct vm_area_struct *vma, unsigned long addr, |
| 1815 | + pfn_t pfn, pgprot_t pgprot) |
| 1816 | +{ |
| 1817 | + return __vm_insert_mixed(vma, addr, pfn, pgprot, false); |
| 1818 | +} |
| 1819 | + |
| 1785 | 1820 | vm_fault_t vmf_insert_mixed(struct vm_area_struct *vma, unsigned long addr, |
| 1786 | 1821 | pfn_t pfn) |
| 1787 | 1822 | { |
| 1788 | | − return __vm_insert_mixed(vma, addr, pfn, false); |
| 1823 | + return __vm_insert_mixed(vma, addr, pfn, vma->vm_page_prot, false); |
| 1789 | 1824 | } |
| 1790 | 1825 | EXPORT_SYMBOL(vmf_insert_mixed); |
| 1791 | 1826 | |
| @@ -1797,7 +1832,7 @@ EXPORT_SYMBOL(vmf_insert_mixed); · 5 unmodified lines |
| 1797 | 1832 | vm_fault_t vmf_insert_mixed_mkwrite(struct vm_area_struct *vma, |
| 1798 | 1833 | unsigned long addr, pfn_t pfn) |
| 1799 | 1834 | { |
| 1800 | | − return __vm_insert_mixed(vma, addr, pfn, true); |
| 1835 | + return __vm_insert_mixed(vma, addr, pfn, vma->vm_page_prot, true); |
| 1801 | 1836 | } |
| 1802 | 1837 | EXPORT_SYMBOL(vmf_insert_mixed_mkwrite); |
| 1803 | 1838 | |