patch-2.2.6 linux/drivers/char/mem.c
Next file: linux/drivers/char/radio-aimslab.c
Previous file: linux/drivers/char/istallion.c
Back to the patch index
Back to the overall index
- Lines: 67
- Date:
Mon Apr 12 10:35:41 1999
- Orig file:
v2.2.5/linux/drivers/char/mem.c
- Orig date:
Wed Mar 10 15:29:46 1999
diff -u --recursive --new-file v2.2.5/linux/drivers/char/mem.c linux/drivers/char/mem.c
@@ -138,8 +138,11 @@
static inline unsigned long pgprot_noncached(unsigned long prot)
{
#if defined(__i386__)
+ /* On PPro and successors, PCD alone doesn't always mean
+ uncached because of interactions with the MTRRs. PCD | PWT
+ means definitely uncached. */
if (boot_cpu_data.x86 > 3)
- prot |= _PAGE_PCD;
+ prot |= _PAGE_PCD | _PAGE_PWT;
#elif defined(__powerpc__)
prot |= _PAGE_NO_CACHE | _PAGE_GUARDED;
#elif defined(__mc68000__)
@@ -155,6 +158,28 @@
return prot;
}
+/*
+ * Architectures vary in how they handle caching for addresses
+ * outside of main memory.
+ */
+static inline int noncached_address(unsigned long addr)
+{
+#if defined(__i386__)
+ /*
+ * On the PPro and successors, the MTRRs are used to set
+ * memory types for physical addresses outside main memory,
+ * so blindly setting PCD or PWT on those pages is wrong.
+ * For Pentiums and earlier, the surround logic should disable
+ * caching for the high addresses through the KEN pin, but
+ * we maintain the tradition of paranoia in this code.
+ */
+ return !(boot_cpu_data.x86_capability & X86_FEATURE_MTRR)
+ && addr >= __pa(high_memory);
+#else
+ return addr >= __pa(high_memory);
+#endif
+}
+
static int mmap_mem(struct file * file, struct vm_area_struct * vma)
{
unsigned long offset = vma->vm_offset;
@@ -166,15 +191,17 @@
* Accessing memory above the top the kernel knows about or
* through a file pointer that was marked O_SYNC will be
* done non-cached.
- *
- * Set VM_IO, as this is likely a non-cached access to an
- * I/O area, and we don't want to include that in a core
- * file.
*/
- if (offset >= __pa(high_memory) || (file->f_flags & O_SYNC)) {
- pgprot_val(vma->vm_page_prot) = pgprot_noncached(pgprot_val(vma->vm_page_prot));
+ if (noncached_address(offset) || (file->f_flags & O_SYNC))
+ pgprot_val(vma->vm_page_prot)
+ = pgprot_noncached(pgprot_val(vma->vm_page_prot));
+
+ /*
+ * Don't dump addresses that are not real memory to a core file.
+ */
+ if (offset >= __pa(high_memory) || (file->f_flags & O_SYNC))
vma->vm_flags |= VM_IO;
- }
+
if (remap_page_range(vma->vm_start, offset, vma->vm_end-vma->vm_start,
vma->vm_page_prot))
return -EAGAIN;
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)