[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