|
@@ -60,6 +60,10 @@ static inline int valid_mmap_phys_addr_range(unsigned long pfn, size_t size)
|
|
|
#endif
|
|
|
|
|
|
#ifdef CONFIG_STRICT_DEVMEM
|
|
|
+static inline int page_is_allowed(unsigned long pfn)
|
|
|
+{
|
|
|
+ return devmem_is_allowed(pfn);
|
|
|
+}
|
|
|
static inline int range_is_allowed(unsigned long pfn, unsigned long size)
|
|
|
{
|
|
|
u64 from = ((u64)pfn) << PAGE_SHIFT;
|
|
@@ -75,6 +79,10 @@ static inline int range_is_allowed(unsigned long pfn, unsigned long size)
|
|
|
return 1;
|
|
|
}
|
|
|
#else
|
|
|
+static inline int page_is_allowed(unsigned long pfn)
|
|
|
+{
|
|
|
+ return 1;
|
|
|
+}
|
|
|
static inline int range_is_allowed(unsigned long pfn, unsigned long size)
|
|
|
{
|
|
|
return 1;
|
|
@@ -122,23 +130,31 @@ static ssize_t read_mem(struct file *file, char __user *buf,
|
|
|
|
|
|
while (count > 0) {
|
|
|
unsigned long remaining;
|
|
|
+ int allowed;
|
|
|
|
|
|
sz = size_inside_page(p, count);
|
|
|
|
|
|
- if (!range_is_allowed(p >> PAGE_SHIFT, count))
|
|
|
+ allowed = page_is_allowed(p >> PAGE_SHIFT);
|
|
|
+ if (!allowed)
|
|
|
return -EPERM;
|
|
|
+ if (allowed == 2) {
|
|
|
+ /* Show zeros for restricted memory. */
|
|
|
+ remaining = clear_user(buf, sz);
|
|
|
+ } else {
|
|
|
+ /*
|
|
|
+ * On ia64 if a page has been mapped somewhere as
|
|
|
+ * uncached, then it must also be accessed uncached
|
|
|
+ * by the kernel or data corruption may occur.
|
|
|
+ */
|
|
|
+ ptr = xlate_dev_mem_ptr(p);
|
|
|
+ if (!ptr)
|
|
|
+ return -EFAULT;
|
|
|
|
|
|
- /*
|
|
|
- * On ia64 if a page has been mapped somewhere as uncached, then
|
|
|
- * it must also be accessed uncached by the kernel or data
|
|
|
- * corruption may occur.
|
|
|
- */
|
|
|
- ptr = xlate_dev_mem_ptr(p);
|
|
|
- if (!ptr)
|
|
|
- return -EFAULT;
|
|
|
+ remaining = copy_to_user(buf, ptr, sz);
|
|
|
+
|
|
|
+ unxlate_dev_mem_ptr(p, ptr);
|
|
|
+ }
|
|
|
|
|
|
- remaining = copy_to_user(buf, ptr, sz);
|
|
|
- unxlate_dev_mem_ptr(p, ptr);
|
|
|
if (remaining)
|
|
|
return -EFAULT;
|
|
|
|
|
@@ -181,30 +197,36 @@ static ssize_t write_mem(struct file *file, const char __user *buf,
|
|
|
#endif
|
|
|
|
|
|
while (count > 0) {
|
|
|
+ int allowed;
|
|
|
+
|
|
|
sz = size_inside_page(p, count);
|
|
|
|
|
|
- if (!range_is_allowed(p >> PAGE_SHIFT, sz))
|
|
|
+ allowed = page_is_allowed(p >> PAGE_SHIFT);
|
|
|
+ if (!allowed)
|
|
|
return -EPERM;
|
|
|
|
|
|
- /*
|
|
|
- * On ia64 if a page has been mapped somewhere as uncached, then
|
|
|
- * it must also be accessed uncached by the kernel or data
|
|
|
- * corruption may occur.
|
|
|
- */
|
|
|
- ptr = xlate_dev_mem_ptr(p);
|
|
|
- if (!ptr) {
|
|
|
- if (written)
|
|
|
- break;
|
|
|
- return -EFAULT;
|
|
|
- }
|
|
|
+ /* Skip actual writing when a page is marked as restricted. */
|
|
|
+ if (allowed == 1) {
|
|
|
+ /*
|
|
|
+ * On ia64 if a page has been mapped somewhere as
|
|
|
+ * uncached, then it must also be accessed uncached
|
|
|
+ * by the kernel or data corruption may occur.
|
|
|
+ */
|
|
|
+ ptr = xlate_dev_mem_ptr(p);
|
|
|
+ if (!ptr) {
|
|
|
+ if (written)
|
|
|
+ break;
|
|
|
+ return -EFAULT;
|
|
|
+ }
|
|
|
|
|
|
- copied = copy_from_user(ptr, buf, sz);
|
|
|
- unxlate_dev_mem_ptr(p, ptr);
|
|
|
- if (copied) {
|
|
|
- written += sz - copied;
|
|
|
- if (written)
|
|
|
- break;
|
|
|
- return -EFAULT;
|
|
|
+ copied = copy_from_user(ptr, buf, sz);
|
|
|
+ unxlate_dev_mem_ptr(p, ptr);
|
|
|
+ if (copied) {
|
|
|
+ written += sz - copied;
|
|
|
+ if (written)
|
|
|
+ break;
|
|
|
+ return -EFAULT;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
buf += sz;
|