commit-hurd
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[gnumach] 01/01: fix access to physical pages beyond last_phys_addr


From: Samuel Thibault
Subject: [gnumach] 01/01: fix access to physical pages beyond last_phys_addr
Date: Mon, 03 Mar 2014 00:00:36 +0000

This is an automated email from the git hooks/post-receive script.

sthibault pushed a commit to branch master
in repository gnumach.

commit f26b25ef7cb1efbdef0a673686bde08fd792adef
Author: Samuel Thibault <address@hidden>
Date:   Mon Mar 3 01:00:08 2014 +0100

    fix access to physical pages beyond last_phys_addr
    
    patches/git-physical-access.patch: New patch
---
 debian/changelog                         |   7 +
 debian/patches/git-physical-access.patch | 241 +++++++++++++++++++++++++++++++
 debian/patches/series                    |   1 +
 3 files changed, 249 insertions(+)

diff --git a/debian/changelog b/debian/changelog
index 3a57f7c..99ff152 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,10 @@
+gnumach (2:1.4-7) UNRELEASED; urgency=medium
+
+  * patches/git-physical-access.patch: New patch, fixes access to physical
+    pages beyond last_phys_addr.
+
+ -- Samuel Thibault <address@hidden>  Mon, 03 Mar 2014 00:59:30 +0100
+
 gnumach (2:1.4-6) unstable; urgency=medium
 
   * Re-enable patches/git-kentry_data_size.patch, but with an additional
diff --git a/debian/patches/git-physical-access.patch 
b/debian/patches/git-physical-access.patch
new file mode 100644
index 0000000..64652e7
--- /dev/null
+++ b/debian/patches/git-physical-access.patch
@@ -0,0 +1,241 @@
+commit b9a59e483225093dec4e28ee5841b5b7f5e73562
+Author: Samuel Thibault <address@hidden>
+Date:   Mon Mar 3 00:50:33 2014 +0100
+
+    Keep two virtual pages as mapping windows to access physical memory
+    
+    PCI devices expose their memory etc. way beyond last_phys_addr. Userland
+    drivers opening /dev/mem need to open those too, even if phystokv() will
+    not work for them.
+    
+    * i386/intel/pmap.h (pmap_mapwindow_t): New type.
+    (pmap_get_mapwindow, pmap_put_mapwindow): New prototypes.
+    (PMAP_NMAPWINDOWS): New macro.
+    * i386/intel/pmap.c (mapwindows): New array.
+    (pmap_get_mapwindow, pmap_put_mapwindow): New functions.
+    (pmap_bootstrap, pmap_virtual_space): Reserve virtual pages for the mapping
+    windows.
+    * i386/i386/phys.c: Include <i386/model_dep.h>
+    (INTEL_PTE_W, INTEL_PTE_R): New macros
+    (pmap_zero_page, pmap_copy_page, copy_to_phys, copy_from_phys): Use
+    `pmap_get_mapwindow' to temporarily map physical pages beyond 
last_phys_addr.
+
+diff --git a/i386/i386/phys.c b/i386/i386/phys.c
+index ed4a309..d4bd6c3 100644
+--- a/i386/i386/phys.c
++++ b/i386/i386/phys.c
+@@ -37,8 +37,12 @@
+ #include <vm/vm_page.h>
+ 
+ #include <i386/pmap.h>
++#include <i386/model_dep.h>
+ #include <mach/machine/vm_param.h>
+ 
++#define INTEL_PTE_W(p) (INTEL_PTE_VALID | INTEL_PTE_WRITE | INTEL_PTE_REF | 
INTEL_PTE_MOD | pa_to_pte(p))
++#define INTEL_PTE_R(p) (INTEL_PTE_VALID | INTEL_PTE_REF | pa_to_pte(p))
++
+ /*
+  *    pmap_zero_page zeros the specified (machine independent) page.
+  */
+@@ -47,7 +51,21 @@ pmap_zero_page(p)
+       vm_offset_t p;
+ {
+       assert(p != vm_page_fictitious_addr);
+-      memset((void *)phystokv(p), 0, PAGE_SIZE);
++      vm_offset_t v;
++      pmap_mapwindow_t *map;
++
++      if (p >= phys_last_addr)
++      {
++              map = pmap_get_mapwindow(INTEL_PTE_W(p));
++              v = map->vaddr;
++      }
++      else
++              v = phystokv(p);
++
++      memset((void*) v, 0, PAGE_SIZE);
++
++      if (p >= phys_last_addr)
++              pmap_put_mapwindow(map);
+ }
+ 
+ /*
+@@ -57,10 +75,33 @@ void
+ pmap_copy_page(src, dst)
+       vm_offset_t src, dst;
+ {
++      vm_offset_t src_addr_v, dst_addr_v;
++      pmap_mapwindow_t *src_map, *dst_map;
+       assert(src != vm_page_fictitious_addr);
+       assert(dst != vm_page_fictitious_addr);
+ 
+-      memcpy((void *)phystokv(dst), (void *)phystokv(src), PAGE_SIZE);
++      if (src >= phys_last_addr)
++      {
++              src_map = pmap_get_mapwindow(INTEL_PTE_R(src));
++              src_addr_v = src_map->vaddr;
++      }
++      else
++              src_addr_v = phystokv(src);
++
++      if (dst >= phys_last_addr)
++      {
++              dst_map = pmap_get_mapwindow(INTEL_PTE_W(dst));
++              dst_addr_v = dst_map->vaddr;
++      }
++      else
++              dst_addr_v = phystokv(dst);
++
++      memcpy((void *) dst_addr_v, (void *) src_addr_v, PAGE_SIZE);
++
++      if (src >= phys_last_addr)
++              pmap_put_mapwindow(src_map);
++      if (dst >= phys_last_addr)
++              pmap_put_mapwindow(dst_map);
+ }
+ 
+ /*
+@@ -73,8 +114,23 @@ copy_to_phys(src_addr_v, dst_addr_p, count)
+       vm_offset_t src_addr_v, dst_addr_p;
+       int count;
+ {
++      vm_offset_t dst_addr_v;
++      pmap_mapwindow_t *dst_map;
+       assert(dst_addr_p != vm_page_fictitious_addr);
+-      memcpy((void *)phystokv(dst_addr_p), (void *)src_addr_v, count);
++      assert(pa_to_pte(dst_addr_p + count-1) == pa_to_pte(dst_addr_p));
++
++      if (dst_addr_p >= phys_last_addr)
++      {
++              dst_map = pmap_get_mapwindow(INTEL_PTE_W(dst_addr_p));
++              dst_addr_v = dst_map->vaddr;
++      }
++      else
++              dst_addr_v = phystokv(dst_addr_p);
++
++      memcpy((void *)dst_addr_v, (void *)src_addr_v, count);
++
++      if (dst_addr_p >= phys_last_addr)
++              pmap_put_mapwindow(dst_map);
+ }
+ 
+ /*
+@@ -88,8 +144,23 @@ copy_from_phys(src_addr_p, dst_addr_v, count)
+       vm_offset_t src_addr_p, dst_addr_v;
+       int count;
+ {
++      vm_offset_t src_addr_v;
++      pmap_mapwindow_t *src_map;
+       assert(src_addr_p != vm_page_fictitious_addr);
+-      memcpy((void *)dst_addr_v, (void *)phystokv(src_addr_p), count);
++      assert(pa_to_pte(src_addr_p + count-1) == pa_to_pte(src_addr_p));
++
++      if (src_addr_p >= phys_last_addr)
++      {
++              src_map = pmap_get_mapwindow(INTEL_PTE_R(src_addr_p));
++              src_addr_v = src_map->vaddr;
++      }
++      else
++              src_addr_v = phystokv(src_addr_p);
++
++      memcpy((void *)dst_addr_v, (void *)src_addr_v, count);
++
++      if (src_addr_p >= phys_last_addr)
++              pmap_put_mapwindow(src_map);
+ }
+ 
+ /*
+diff --git a/i386/intel/pmap.c b/i386/intel/pmap.c
+index 2943d26..a3d9630 100644
+--- a/i386/intel/pmap.c
++++ b/i386/intel/pmap.c
+@@ -419,6 +419,12 @@ unsigned int      inuse_ptepages_count = 0;       /* 
debugging */
+  */
+ pt_entry_t *kernel_page_dir;
+ 
++/*
++ * Two slots for temporary physical page mapping, to allow for
++ * physical-to-physical transfers.
++ */
++static pmap_mapwindow_t mapwindows[PMAP_NMAPWINDOWS];
++
+ static inline pt_entry_t *
+ pmap_pde(const pmap_t pmap, vm_offset_t addr)
+ {
+@@ -774,6 +780,12 @@ void pmap_bootstrap(void)
+                       }
+                       for (; pte < ptable+NPTES; pte++)
+                       {
++                              if (va >= kernel_virtual_end - PMAP_NMAPWINDOWS 
* PAGE_SIZE);
++                              {
++                                      pmap_mapwindow_t *win = 
&mapwindows[atop(va - (kernel_virtual_end - PMAP_NMAPWINDOWS * PAGE_SIZE))];
++                                      win->entry = pte;
++                                      win->vaddr = va;
++                              }
+                               WRITE_PTE(pte, 0);
+                               va += INTEL_PGBYTES;
+                       }
+@@ -884,12 +896,41 @@ void pmap_clear_bootstrap_pagetable(pt_entry_t *base) {
+ }
+ #endif        /* MACH_PV_PAGETABLES */
+ 
++/*
++ * Create a temporary mapping for a given physical entry
++ *
++ * This can be used to access physical pages which are not mapped 1:1 by
++ * phystokv().
++ */
++pmap_mapwindow_t *pmap_get_mapwindow(pt_entry_t entry)
++{
++      pmap_mapwindow_t *map;
++
++      /* Find an empty one.  */
++      for (map = &mapwindows[0]; map < &mapwindows[sizeof (mapwindows) / 
sizeof (*mapwindows)]; map++)
++              if (!(*map->entry))
++                      break;
++      assert(map < &mapwindows[sizeof (mapwindows) / sizeof (*mapwindows)]);
++
++      WRITE_PTE(map->entry, entry);
++      return map;
++}
++
++/*
++ * Destroy a temporary mapping for a physical entry
++ */
++void pmap_put_mapwindow(pmap_mapwindow_t *map)
++{
++      WRITE_PTE(map->entry, 0);
++      PMAP_UPDATE_TLBS(kernel_pmap, map->vaddr, map->vaddr + PAGE_SIZE);
++}
++
+ void pmap_virtual_space(startp, endp)
+       vm_offset_t *startp;
+       vm_offset_t *endp;
+ {
+       *startp = kernel_virtual_start;
+-      *endp = kernel_virtual_end;
++      *endp = kernel_virtual_end - PMAP_NMAPWINDOWS * PAGE_SIZE;
+ }
+ 
+ /*
+diff --git a/i386/intel/pmap.h b/i386/intel/pmap.h
+index 047a384..382cd5f 100644
+--- a/i386/intel/pmap.h
++++ b/i386/intel/pmap.h
+@@ -192,6 +192,16 @@ extern void pmap_clear_bootstrap_pagetable(pt_entry_t 
*addr);
+ #define       set_pmap(pmap)  set_cr3(kvtophys((vm_offset_t)(pmap)->dirbase))
+ #endif        /* PAE */
+ 
++typedef struct {
++      pt_entry_t      *entry;
++      vm_offset_t     vaddr;
++} pmap_mapwindow_t;
++
++extern pmap_mapwindow_t *pmap_get_mapwindow(pt_entry_t entry);
++extern void pmap_put_mapwindow(pmap_mapwindow_t *map);
++
++#define PMAP_NMAPWINDOWS 2
++
+ #if   NCPUS > 1
+ /*
+  *    List of cpus that are actively using mapped memory.  Any
diff --git a/debian/patches/series b/debian/patches/series
index 81e99a2..bcb1755 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -11,3 +11,4 @@ git-cursor_init.patch
 git-coverity-fixes.patch
 git-mig-inlines.patch
 git-quiet-cd-floppy.patch
+git-physical-access.patch

-- 
Alioth's /usr/local/bin/git-commit-notice on 
/srv/git.debian.org/git/pkg-hurd/gnumach.git



reply via email to

[Prev in Thread] Current Thread [Next in Thread]