|
@@ -664,13 +664,13 @@ static void free_pfn_range(u64 paddr, unsigned long size)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
/*
|
|
|
- * track_pfn_vma_copy is called when vma that is covering the pfnmap gets
|
|
|
|
|
|
|
+ * track_pfn_copy is called when vma that is covering the pfnmap gets
|
|
|
* copied through copy_page_range().
|
|
* copied through copy_page_range().
|
|
|
*
|
|
*
|
|
|
* If the vma has a linear pfn mapping for the entire range, we get the prot
|
|
* If the vma has a linear pfn mapping for the entire range, we get the prot
|
|
|
* from pte and reserve the entire vma range with single reserve_pfn_range call.
|
|
* from pte and reserve the entire vma range with single reserve_pfn_range call.
|
|
|
*/
|
|
*/
|
|
|
-int track_pfn_vma_copy(struct vm_area_struct *vma)
|
|
|
|
|
|
|
+int track_pfn_copy(struct vm_area_struct *vma)
|
|
|
{
|
|
{
|
|
|
resource_size_t paddr;
|
|
resource_size_t paddr;
|
|
|
unsigned long prot;
|
|
unsigned long prot;
|
|
@@ -694,15 +694,12 @@ int track_pfn_vma_copy(struct vm_area_struct *vma)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
/*
|
|
|
- * track_pfn_vma_new is called when a _new_ pfn mapping is being established
|
|
|
|
|
- * for physical range indicated by pfn and size.
|
|
|
|
|
- *
|
|
|
|
|
* prot is passed in as a parameter for the new mapping. If the vma has a
|
|
* prot is passed in as a parameter for the new mapping. If the vma has a
|
|
|
* linear pfn mapping for the entire range reserve the entire vma range with
|
|
* linear pfn mapping for the entire range reserve the entire vma range with
|
|
|
* single reserve_pfn_range call.
|
|
* single reserve_pfn_range call.
|
|
|
*/
|
|
*/
|
|
|
-int track_pfn_vma_new(struct vm_area_struct *vma, pgprot_t *prot,
|
|
|
|
|
- unsigned long pfn, unsigned long size)
|
|
|
|
|
|
|
+int track_pfn_remap(struct vm_area_struct *vma, pgprot_t *prot,
|
|
|
|
|
+ unsigned long pfn, unsigned long size)
|
|
|
{
|
|
{
|
|
|
resource_size_t paddr = (resource_size_t)pfn << PAGE_SHIFT;
|
|
resource_size_t paddr = (resource_size_t)pfn << PAGE_SHIFT;
|
|
|
unsigned long flags;
|
|
unsigned long flags;
|
|
@@ -714,8 +711,36 @@ int track_pfn_vma_new(struct vm_area_struct *vma, pgprot_t *prot,
|
|
|
if (!pat_enabled)
|
|
if (!pat_enabled)
|
|
|
return 0;
|
|
return 0;
|
|
|
|
|
|
|
|
- /* for vm_insert_pfn and friends, we set prot based on lookup */
|
|
|
|
|
|
|
+ /*
|
|
|
|
|
+ * For anything smaller than the vma size we set prot based on the
|
|
|
|
|
+ * lookup.
|
|
|
|
|
+ */
|
|
|
flags = lookup_memtype(paddr);
|
|
flags = lookup_memtype(paddr);
|
|
|
|
|
+
|
|
|
|
|
+ /* Check memtype for the remaining pages */
|
|
|
|
|
+ while (size > PAGE_SIZE) {
|
|
|
|
|
+ size -= PAGE_SIZE;
|
|
|
|
|
+ paddr += PAGE_SIZE;
|
|
|
|
|
+ if (flags != lookup_memtype(paddr))
|
|
|
|
|
+ return -EINVAL;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ *prot = __pgprot((pgprot_val(vma->vm_page_prot) & (~_PAGE_CACHE_MASK)) |
|
|
|
|
|
+ flags);
|
|
|
|
|
+
|
|
|
|
|
+ return 0;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+int track_pfn_insert(struct vm_area_struct *vma, pgprot_t *prot,
|
|
|
|
|
+ unsigned long pfn)
|
|
|
|
|
+{
|
|
|
|
|
+ unsigned long flags;
|
|
|
|
|
+
|
|
|
|
|
+ if (!pat_enabled)
|
|
|
|
|
+ return 0;
|
|
|
|
|
+
|
|
|
|
|
+ /* Set prot based on lookup */
|
|
|
|
|
+ flags = lookup_memtype((resource_size_t)pfn << PAGE_SHIFT);
|
|
|
*prot = __pgprot((pgprot_val(vma->vm_page_prot) & (~_PAGE_CACHE_MASK)) |
|
|
*prot = __pgprot((pgprot_val(vma->vm_page_prot) & (~_PAGE_CACHE_MASK)) |
|
|
|
flags);
|
|
flags);
|
|
|
|
|
|
|
@@ -723,12 +748,12 @@ int track_pfn_vma_new(struct vm_area_struct *vma, pgprot_t *prot,
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
/*
|
|
|
- * untrack_pfn_vma is called while unmapping a pfnmap for a region.
|
|
|
|
|
|
|
+ * untrack_pfn is called while unmapping a pfnmap for a region.
|
|
|
* untrack can be called for a specific region indicated by pfn and size or
|
|
* untrack can be called for a specific region indicated by pfn and size or
|
|
|
* can be for the entire vma (in which case pfn, size are zero).
|
|
* can be for the entire vma (in which case pfn, size are zero).
|
|
|
*/
|
|
*/
|
|
|
-void untrack_pfn_vma(struct vm_area_struct *vma, unsigned long pfn,
|
|
|
|
|
- unsigned long size)
|
|
|
|
|
|
|
+void untrack_pfn(struct vm_area_struct *vma, unsigned long pfn,
|
|
|
|
|
+ unsigned long size)
|
|
|
{
|
|
{
|
|
|
resource_size_t paddr;
|
|
resource_size_t paddr;
|
|
|
unsigned long prot;
|
|
unsigned long prot;
|