* [Linux-ia64] Re: Status on ioremap patch
@ 2001-09-14 23:14 David Mosberger
2001-09-15 12:36 ` Steffen Persvold
` (8 more replies)
0 siblings, 9 replies; 12+ messages in thread
From: David Mosberger @ 2001-09-14 23:14 UTC (permalink / raw)
To: linux-ia64
>>>>> On Fri, 14 Sep 2001 23:57:03 +0200, Steffen Persvold <sp@scali.no> said:
Steffen> So, how about that patch guys ? Any chance you'll put it
Steffen> into the mainstream IA64 kernel ???
I haven't looked at it yet, but am planning to do so as part of the
2.4.10 patch.
--david
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [Linux-ia64] Re: Status on ioremap patch
2001-09-14 23:14 [Linux-ia64] Re: Status on ioremap patch David Mosberger
@ 2001-09-15 12:36 ` Steffen Persvold
2001-09-28 12:39 ` Jes Sorensen
` (7 subsequent siblings)
8 siblings, 0 replies; 12+ messages in thread
From: Steffen Persvold @ 2001-09-15 12:36 UTC (permalink / raw)
To: linux-ia64
[-- Attachment #1: Type: text/plain, Size: 1390 bytes --]
David Mosberger wrote:
>
> >>>>> On Fri, 14 Sep 2001 23:57:03 +0200, Steffen Persvold <sp@scali.no> said:
>
> Steffen> So, how about that patch guys ? Any chance you'll put it
> Steffen> into the mainstream IA64 kernel ???
>
> I haven't looked at it yet, but am planning to do so as part of the
> 2.4.10 patch.
>
I just discovered that several files in arch/ia64/kernel (more specifically acpi.c, efi.c and iosapic.c) calls ioremap with 0 as
size argument. This is ok with the current ioremap implementation which always uses region 6 and therefore in theory doesn't need a
size since it's mapped all the time. However with my patch you will get a NULL pointer in return if you specify size as 0. Because
of this I've modified my original patch to accept 0 as size argument and return the region 6 address when this is the case. This
means that we cannot get rid of region 6 yet since some of the source files seem to depend on it.
Attached is my new version of the patch. (Please note that the old ioremap() methods in asm/io.h is just disabled with '#if 0')
Regards,
--
Steffen Persvold | Scali Computer AS | Try out the world's best
mailto:sp@scali.no | http://www.scali.com | performing MPI implementation:
Tel: (+47) 2262 8950 | Olaf Helsets vei 6 | - ScaMPI 1.12.2 -
Fax: (+47) 2262 8951 | N0621 Oslo, NORWAY | >300MBytes/s and <4uS latency
[-- Attachment #2: ia64-ioremap3.patch --]
[-- Type: text/plain, Size: 7149 bytes --]
--- linux-2.4.4/arch/ia64/mm/Makefile.~1~ Thu Jan 4 21:50:17 2001
+++ linux-2.4.4/arch/ia64/mm/Makefile Sat Aug 11 21:20:03 2001
@@ -9,6 +9,6 @@
O_TARGET := mm.o
-obj-y := init.o fault.o tlb.o extable.o
+obj-y := init.o fault.o ioremap.o tlb.o extable.o
include $(TOPDIR)/Rules.make
--- linux-2.4.4/arch/ia64/mm/ioremap.c.~1~ Tue May 5 22:32:27 1998
+++ linux-2.4.4/arch/ia64/mm/ioremap.c Sat Sep 15 13:20:25 2001
@@ -0,0 +1,162 @@
+/*
+ * arch/ia64/mm/ioremap.c
+ *
+ * IA64 version
+ * Copyright (C) 2001 Scali AS
+ * Author(s): Steffen Persvold (sp@scali.com)
+ *
+ * Derived from "arch/i386/mm/ioremap.c"
+ * (C) Copyright 1995 1996 Linus Torvalds
+ *
+ * Re-map IO memory to kernel address space so that we can access it.
+ */
+
+#include <linux/vmalloc.h>
+#include <asm/io.h>
+#include <asm/pgalloc.h>
+
+static inline void remap_area_pte(pte_t * pte, unsigned long address, unsigned long size,
+ unsigned long phys_addr, unsigned long flags)
+{
+ unsigned long end;
+
+ address &= ~PMD_MASK;
+ end = address + size;
+ if (end > PMD_SIZE)
+ end = PMD_SIZE;
+ if (address >= end)
+ BUG();
+ do {
+ if (!pte_none(*pte)) {
+ printk("remap_area_pte: page already exists\n");
+ BUG();
+ }
+ set_pte(pte, mk_pte_phys(phys_addr, __pgprot(__DIRTY_BITS | _PAGE_PL_0 |
+ _PAGE_AR_RWX | (flags & _PAGE_MA_MASK))));
+ address += PAGE_SIZE;
+ phys_addr += PAGE_SIZE;
+ pte++;
+ } while (address && (address < end));
+}
+
+static inline int remap_area_pmd(pmd_t * pmd, unsigned long address, unsigned long size,
+ unsigned long phys_addr, unsigned long flags)
+{
+ unsigned long end;
+
+ address &= ~PGDIR_MASK;
+ end = address + size;
+ if (end > PGDIR_SIZE)
+ end = PGDIR_SIZE;
+ phys_addr -= address;
+ if (address >= end)
+ BUG();
+ do {
+ pte_t * pte = pte_alloc(&init_mm, pmd, address);
+ if (!pte)
+ return -ENOMEM;
+ remap_area_pte(pte, address, end - address, address + phys_addr, flags);
+ address = (address + PMD_SIZE) & PMD_MASK;
+ pmd++;
+ } while (address && (address < end));
+ return 0;
+}
+
+static int remap_area_pages(unsigned long address, unsigned long phys_addr,
+ unsigned long size, unsigned long flags)
+{
+ int error;
+ pgd_t * dir;
+ unsigned long end = address + size;
+
+ phys_addr -= address;
+ dir = pgd_offset_k(address);
+ flush_cache_all();
+ if (address >= end)
+ BUG();
+ spin_lock(&init_mm.page_table_lock);
+ do {
+ pmd_t *pmd;
+ pmd = pmd_alloc(&init_mm, dir, address);
+ error = -ENOMEM;
+ if (!pmd)
+ break;
+ if (remap_area_pmd(pmd, address, end - address,
+ phys_addr + address, flags))
+ break;
+ error = 0;
+ address = (address + PGDIR_SIZE) & PGDIR_MASK;
+ dir++;
+ } while (address && (address < end));
+ spin_unlock(&init_mm.page_table_lock);
+ flush_tlb_all();
+ return error;
+}
+
+/*
+ * Generic mapping function (not visible outside):
+ */
+
+/*
+ * Remap an arbitrary physical address space into the kernel virtual
+ * address space. Needed when the kernel wants to access high addresses
+ * directly.
+ *
+ * NOTE! We need to allow non-page-aligned mappings too: we will obviously
+ * have to convert them into an offset in a page-aligned mapping, but the
+ * caller shouldn't need to know that small detail.
+ */
+void * __ia64_ioremap(unsigned long phys_addr, unsigned long size, unsigned long flags)
+{
+ void * addr;
+ struct vm_struct * area;
+ unsigned long offset, last_addr;
+
+ /* If size is zero we can't set up a dynamic map,
+ * use the uncached region.
+ */
+ if (!size)
+ return (void *) (__IA64_UNCACHED_OFFSET | (phys_addr));
+
+ /* Don't allow wraparound */
+ last_addr = phys_addr + size - 1;
+ if (last_addr < phys_addr)
+ return NULL;
+
+ /*
+ * Don't allow anybody to remap normal RAM that we're using..
+ */
+ if (phys_addr < virt_to_phys(high_memory))
+ return NULL;
+
+ /*
+ * Mappings have to be page-aligned
+ */
+ offset = phys_addr & ~PAGE_MASK;
+ phys_addr &= PAGE_MASK;
+ size = PAGE_ALIGN(last_addr) - phys_addr;
+
+ /*
+ * Ok, go for it..
+ */
+ area = get_vm_area(size, VM_IOREMAP);
+ if (!area)
+ return NULL;
+ addr = area->addr;
+
+ if ((flags & _PAGE_MA_MASK) == 0)
+ flags = _PAGE_MA_UC;
+
+ if (remap_area_pages(VMALLOC_VMADDR(addr), phys_addr, size, flags)) {
+ vfree(addr);
+ return NULL;
+ }
+ return (void *) (offset + (char *)addr);
+}
+
+void __ia64_iounmap(void *addr)
+{
+ /* We can't do vfree() on addresses in the uncached region */
+ if ((unsigned long)addr < __IA64_UNCACHED_OFFSET)
+ return vfree(addr);
+}
--- linux-2.4.4/arch/ia64/kernel/ia64_ksyms.c.~1~ Thu Apr 5 21:51:47 2001
+++ linux-2.4.4/arch/ia64/kernel/ia64_ksyms.c Sat Aug 11 23:57:12 2001
@@ -39,6 +39,8 @@
EXPORT_SYMBOL(ip_fast_csum);
#include <asm/io.h>
+EXPORT_SYMBOL(__ia64_ioremap);
+EXPORT_SYMBOL(__ia64_iounmap);
EXPORT_SYMBOL(__ia64_memcpy_fromio);
EXPORT_SYMBOL(__ia64_memcpy_toio);
EXPORT_SYMBOL(__ia64_memset_c_io);
--- linux-2.4.4/include/asm-ia64/io.h.~1~ Thu Apr 5 21:51:47 2001
+++ linux-2.4.4/include/asm-ia64/io.h Sat Sep 15 13:25:50 2001
@@ -32,6 +32,7 @@
#include <asm/machvec.h>
#include <asm/page.h>
#include <asm/system.h>
+#include <asm/pgtable.h>
/*
* Change virtual addresses to physical addresses and vv.
@@ -372,7 +373,15 @@
* accept both, thus the casts.
*
* On ia-64, we access the physical I/O memory space through the uncached kernel region.
+ *
+ * Which is not a good idea if we want speed on large PIO operations. This is now changed
+ * to map dynamically so that we can use the page table attributes to decide the caching.
*/
+
+extern void * __ia64_ioremap(unsigned long offset, unsigned long size, unsigned long flags);
+extern void __ia64_iounmap(void *addr);
+
+#if 0
static inline void *
ioremap (unsigned long offset, unsigned long size)
{
@@ -385,6 +394,25 @@
}
#define ioremap_nocache(o,s) ioremap(o,s)
+#else
+static inline void *
+ioremap (unsigned long offset, unsigned long size)
+{
+ return __ia64_ioremap(offset, size, _PAGE_MA_WC);
+}
+
+static inline void *
+ioremap_nocache (unsigned long offset, unsigned long size)
+{
+ return __ia64_ioremap(offset, size, _PAGE_MA_UC);
+}
+
+static inline void
+iounmap (void *addr)
+{
+ __ia64_iounmap(addr);
+}
+#endif
# ifdef __KERNEL__
--- linux-2.4.4/include/asm-ia64/pgtable.h.~1~ Thu Apr 5 21:51:47 2001
+++ linux-2.4.4/include/asm-ia64/pgtable.h Sat Aug 11 23:59:36 2001
@@ -125,7 +125,6 @@
# ifndef __ASSEMBLY__
#include <asm/bitops.h>
-#include <asm/mmu_context.h>
#include <asm/processor.h>
/*
@@ -329,11 +328,7 @@
/* The offset in the 1-level directory is given by the 3 region bits
(61..63) and the seven level-1 bits (33-39). */
-static inline pgd_t*
-pgd_offset (struct mm_struct *mm, unsigned long address)
-{
- return mm->pgd + pgd_index(address);
-}
+#define pgd_offset(mm, address) ((mm)->pgd+pgd_index(address))
/* In the kernel's mapped region we have a full 43 bit space available and completely
ignore the region number (since we know its in region number 5). */
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [Linux-ia64] Re: Status on ioremap patch
2001-09-14 23:14 [Linux-ia64] Re: Status on ioremap patch David Mosberger
2001-09-15 12:36 ` Steffen Persvold
@ 2001-09-28 12:39 ` Jes Sorensen
2002-01-05 15:01 ` Steffen Persvold
` (6 subsequent siblings)
8 siblings, 0 replies; 12+ messages in thread
From: Jes Sorensen @ 2001-09-28 12:39 UTC (permalink / raw)
To: linux-ia64
>>>>> "Steffen" = Steffen Persvold <sp@scali.no> writes:
Steffen> David Mosberger wrote:
>> I haven't looked at it yet, but am planning to do so as part of
>> the 2.4.10 patch.
Steffen> I just discovered that several files in arch/ia64/kernel
Steffen> (more specifically acpi.c, efi.c and iosapic.c) calls ioremap
Steffen> with 0 as size argument. This is ok with the current ioremap
Steffen> implementation which always uses region 6 and therefore in
Steffen> theory doesn't need a size since it's mapped all the
Steffen> time.
This is really borked, it should be changed whether we change the
ioremap() implementation or not. ioremap() really should be treated
identically on all architectures from the users perspective.
Cheers
Jes
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [Linux-ia64] Re: Status on ioremap patch
2001-09-14 23:14 [Linux-ia64] Re: Status on ioremap patch David Mosberger
2001-09-15 12:36 ` Steffen Persvold
2001-09-28 12:39 ` Jes Sorensen
@ 2002-01-05 15:01 ` Steffen Persvold
2002-01-05 23:30 ` Keith Owens
` (5 subsequent siblings)
8 siblings, 0 replies; 12+ messages in thread
From: Steffen Persvold @ 2002-01-05 15:01 UTC (permalink / raw)
To: linux-ia64
[-- Attachment #1: Type: text/plain, Size: 1579 bytes --]
David Mosberger wrote:
>
> Steffen,
>
> I looked at your patch and have a comment and a suggestion. First, I
> do not think it's safe to define ioremap() as a way to install
> write-cached mappings. There are plenty of drivers left that use
> ioremap() instead of ioremap_nocache() and we can't change the
> semantics of ioremap() underneath them.
>
> Second, it seems to me it would be cleaner to extend
> remap_page_range() to allow remapping into the kernel mapped segment
> (region 5 in the case of ia64 linux). This should work as is, except
> that in the kernel case, you need to use pgd_offset_k(). I think you
> could hack mm/memory.c to check whether "from" is in the range from
> VMALLOC_START to VMALLOC_END and, if so, use pgd_offset_k() instead of
> pgd_offset(). Can you try this and let me know if it works for your
> needs?
>
I've had some time to look at it, and I decided to do what you said. I also changed ioremap on all
platforms that implements it so that they use remap_page_range()). I've tested the patch on IA64 and
i386.
I've attached the patch (I didn't post it on the lkml even though it affects more that the IA64
platform), it's against a vanilla 2.4.17 tree.
Please take a look and tell me what you think.
Regards,
--
Steffen Persvold | Scalable Linux Systems | Try out the world's best
mailto:sp@scali.no | http://www.scali.com | performing MPI implementation:
Tel: (+47) 2262 8950 | Olaf Helsets vei 6 | - ScaMPI 1.12.2 -
Fax: (+47) 2262 8951 | N0621 Oslo, NORWAY | >300MBytes/s and <4uS latencyy
[-- Attachment #2: linux-2.4.17-ioremap.patch --]
[-- Type: text/plain, Size: 26595 bytes --]
--- linux-2.4.17/mm/memory.c.orig Fri Dec 21 18:42:05 2001
+++ linux-2.4.17/mm/memory.c Sat Jan 5 13:13:26 2002
@@ -791,6 +791,9 @@
* maps a range of physical memory into the requested pages. the old
* mappings are removed. any references to nonexistent pages results
* in null mappings (currently treated as "copy-on-access")
+ *
+ * For physical (or I/O) memory mapped into the kernel virtual space,
+ * the old mappings will not be removed.
*/
static inline void remap_pte_range(pte_t * pte, unsigned long address, unsigned long size,
unsigned long phys_addr, pgprot_t prot)
@@ -802,14 +805,22 @@
if (end > PMD_SIZE)
end = PMD_SIZE;
do {
- struct page *page;
- pte_t oldpage;
- oldpage = ptep_get_and_clear(pte);
-
- page = virt_to_page(__va(phys_addr));
- if ((!VALID_PAGE(page)) || PageReserved(page))
- set_pte(pte, mk_pte_phys(phys_addr, prot));
- forget_pte(oldpage);
+ if (address > VMALLOC_START && address < VMALLOC_END) {
+ if (!pte_none(*pte)) {
+ printk("remap_area_pte: page already exists\n");
+ BUG();
+ }
+ set_pte(pte, mk_pte_phys(phys_addr, prot));
+ } else {
+ struct page *page;
+ pte_t oldpage;
+ oldpage = ptep_get_and_clear(pte);
+
+ page = virt_to_page(__va(phys_addr));
+ if ((!VALID_PAGE(page)) || PageReserved(page))
+ set_pte(pte, mk_pte_phys(phys_addr, prot));
+ forget_pte(oldpage);
+ }
address += PAGE_SIZE;
phys_addr += PAGE_SIZE;
pte++;
@@ -844,10 +855,17 @@
pgd_t * dir;
unsigned long beg = from;
unsigned long end = from + size;
- struct mm_struct *mm = current->mm;
+ struct mm_struct *mm;
phys_addr -= from;
- dir = pgd_offset(mm, from);
+ /* Check if we're going to map into the kernel virtual addresses (ioremap) */
+ if (from > VMALLOC_START && end < VMALLOC_END) {
+ mm = &init_mm;
+ dir = pgd_offset_k(from);
+ } else {
+ mm = current->mm;
+ dir = pgd_offset(mm, from);
+ }
flush_cache_range(mm, beg, end);
if (from >= end)
BUG();
--- linux-2.4.17/arch/i386/mm/ioremap.c.orig Tue Mar 20 17:13:33 2001
+++ linux-2.4.17/arch/i386/mm/ioremap.c Sat Jan 5 14:02:31 2002
@@ -12,84 +12,6 @@
#include <asm/io.h>
#include <asm/pgalloc.h>
-static inline void remap_area_pte(pte_t * pte, unsigned long address, unsigned long size,
- unsigned long phys_addr, unsigned long flags)
-{
- unsigned long end;
-
- address &= ~PMD_MASK;
- end = address + size;
- if (end > PMD_SIZE)
- end = PMD_SIZE;
- if (address >= end)
- BUG();
- do {
- if (!pte_none(*pte)) {
- printk("remap_area_pte: page already exists\n");
- BUG();
- }
- set_pte(pte, mk_pte_phys(phys_addr, __pgprot(_PAGE_PRESENT | _PAGE_RW |
- _PAGE_DIRTY | _PAGE_ACCESSED | flags)));
- address += PAGE_SIZE;
- phys_addr += PAGE_SIZE;
- pte++;
- } while (address && (address < end));
-}
-
-static inline int remap_area_pmd(pmd_t * pmd, unsigned long address, unsigned long size,
- unsigned long phys_addr, unsigned long flags)
-{
- unsigned long end;
-
- address &= ~PGDIR_MASK;
- end = address + size;
- if (end > PGDIR_SIZE)
- end = PGDIR_SIZE;
- phys_addr -= address;
- if (address >= end)
- BUG();
- do {
- pte_t * pte = pte_alloc(&init_mm, pmd, address);
- if (!pte)
- return -ENOMEM;
- remap_area_pte(pte, address, end - address, address + phys_addr, flags);
- address = (address + PMD_SIZE) & PMD_MASK;
- pmd++;
- } while (address && (address < end));
- return 0;
-}
-
-static int remap_area_pages(unsigned long address, unsigned long phys_addr,
- unsigned long size, unsigned long flags)
-{
- int error;
- pgd_t * dir;
- unsigned long end = address + size;
-
- phys_addr -= address;
- dir = pgd_offset(&init_mm, address);
- flush_cache_all();
- if (address >= end)
- BUG();
- spin_lock(&init_mm.page_table_lock);
- do {
- pmd_t *pmd;
- pmd = pmd_alloc(&init_mm, dir, address);
- error = -ENOMEM;
- if (!pmd)
- break;
- if (remap_area_pmd(pmd, address, end - address,
- phys_addr + address, flags))
- break;
- error = 0;
- address = (address + PGDIR_SIZE) & PGDIR_MASK;
- dir++;
- } while (address && (address < end));
- spin_unlock(&init_mm.page_table_lock);
- flush_tlb_all();
- return error;
-}
-
/*
* Generic mapping function (not visible outside):
*/
@@ -108,6 +30,8 @@
void * addr;
struct vm_struct * area;
unsigned long offset, last_addr;
+ pgprot_t pgprot = __pgprot(_PAGE_PRESENT | _PAGE_RW
+ | _PAGE_DIRTY | _PAGE_ACCESSED | flags);
/* Don't allow wraparound or zero size */
last_addr = phys_addr + size - 1;
@@ -149,7 +73,7 @@
if (!area)
return NULL;
addr = area->addr;
- if (remap_area_pages(VMALLOC_VMADDR(addr), phys_addr, size, flags)) {
+ if (remap_page_range(VMALLOC_VMADDR(addr), phys_addr, size, pgprot)) {
vfree(addr);
return NULL;
}
--- linux-2.4.17/arch/mips/mm/ioremap.c.orig Wed Jul 4 20:50:39 2001
+++ linux-2.4.17/arch/mips/mm/ioremap.c Sat Jan 5 14:07:02 2002
@@ -14,85 +14,6 @@
#include <asm/io.h>
#include <asm/pgalloc.h>
-static inline void remap_area_pte(pte_t * pte, unsigned long address, unsigned long size,
- unsigned long phys_addr, unsigned long flags)
-{
- unsigned long end;
- pgprot_t pgprot = __pgprot(_PAGE_GLOBAL | _PAGE_PRESENT | __READABLE
- | __WRITEABLE | flags);
-
- address &= ~PMD_MASK;
- end = address + size;
- if (end > PMD_SIZE)
- end = PMD_SIZE;
- if (address >= end)
- BUG();
- do {
- if (!pte_none(*pte)) {
- printk("remap_area_pte: page already exists\n");
- BUG();
- }
- set_pte(pte, mk_pte_phys(phys_addr, pgprot));
- address += PAGE_SIZE;
- phys_addr += PAGE_SIZE;
- pte++;
- } while (address && (address < end));
-}
-
-static inline int remap_area_pmd(pmd_t * pmd, unsigned long address, unsigned long size,
- unsigned long phys_addr, unsigned long flags)
-{
- unsigned long end;
-
- address &= ~PGDIR_MASK;
- end = address + size;
- if (end > PGDIR_SIZE)
- end = PGDIR_SIZE;
- phys_addr -= address;
- if (address >= end)
- BUG();
- do {
- pte_t * pte = pte_alloc(&init_mm, pmd, address);
- if (!pte)
- return -ENOMEM;
- remap_area_pte(pte, address, end - address, address + phys_addr, flags);
- address = (address + PMD_SIZE) & PMD_MASK;
- pmd++;
- } while (address && (address < end));
- return 0;
-}
-
-static int remap_area_pages(unsigned long address, unsigned long phys_addr,
- unsigned long size, unsigned long flags)
-{
- int error;
- pgd_t * dir;
- unsigned long end = address + size;
-
- phys_addr -= address;
- dir = pgd_offset(&init_mm, address);
- flush_cache_all();
- if (address >= end)
- BUG();
- spin_lock(&init_mm.page_table_lock);
- do {
- pmd_t *pmd;
- pmd = pmd_alloc(&init_mm, dir, address);
- error = -ENOMEM;
- if (!pmd)
- break;
- if (remap_area_pmd(pmd, address, end - address,
- phys_addr + address, flags))
- break;
- error = 0;
- address = (address + PGDIR_SIZE) & PGDIR_MASK;
- dir++;
- } while (address && (address < end));
- spin_unlock(&init_mm.page_table_lock);
- flush_tlb_all();
- return error;
-}
-
/*
* Generic mapping function (not visible outside):
*/
@@ -114,6 +35,8 @@
void * addr;
struct vm_struct * area;
unsigned long offset, last_addr;
+ pgprot_t pgprot = __pgprot(_PAGE_GLOBAL | _PAGE_PRESENT | __READABLE
+ | __WRITEABLE | flags);
/* Don't allow wraparound or zero size */
last_addr = phys_addr + size - 1;
@@ -156,7 +79,7 @@
if (!area)
return NULL;
addr = area->addr;
- if (remap_area_pages(VMALLOC_VMADDR(addr), phys_addr, size, flags)) {
+ if (remap_page_range(VMALLOC_VMADDR(addr), phys_addr, size, pgprot)) {
vfree(addr);
return NULL;
}
@@ -171,6 +94,3 @@
if (!IS_KSEG1(addr))
return vfree((void *) (PAGE_MASK & (unsigned long) addr));
}
-
-EXPORT_SYMBOL(__ioremap);
-EXPORT_SYMBOL(iounmap);
--- linux-2.4.17/arch/mips/kernel/mips_ksyms.c.orig Sun Sep 9 19:43:01 2001
+++ linux-2.4.17/arch/mips/kernel/mips_ksyms.c Sat Jan 5 14:07:57 2002
@@ -106,6 +106,9 @@
*/
EXPORT_SYMBOL(mips_io_port_base);
+EXPORT_SYMBOL(__ioremap);
+EXPORT_SYMBOL(iounmap);
+
/*
* Architecture specific stuff.
*/
--- linux-2.4.17/arch/arm/mm/ioremap.c.orig Thu Apr 12 21:20:31 2001
+++ linux-2.4.17/arch/arm/mm/ioremap.c Sat Jan 5 13:36:38 2002
@@ -35,88 +35,6 @@
#include <asm/pgalloc.h>
#include <asm/io.h>
-static inline void remap_area_pte(pte_t * pte, unsigned long address, unsigned long size,
- unsigned long phys_addr, pgprot_t pgprot)
-{
- unsigned long end;
-
- address &= ~PMD_MASK;
- end = address + size;
- if (end > PMD_SIZE)
- end = PMD_SIZE;
- if (address >= end)
- BUG();
- do {
- if (!pte_none(*pte)) {
- printk("remap_area_pte: page already exists\n");
- BUG();
- }
- set_pte(pte, mk_pte_phys(phys_addr, pgprot));
- address += PAGE_SIZE;
- phys_addr += PAGE_SIZE;
- pte++;
- } while (address && (address < end));
-}
-
-static inline int remap_area_pmd(pmd_t * pmd, unsigned long address, unsigned long size,
- unsigned long phys_addr, unsigned long flags)
-{
- unsigned long end;
- pgprot_t pgprot;
-
- address &= ~PGDIR_MASK;
- end = address + size;
-
- if (end > PGDIR_SIZE)
- end = PGDIR_SIZE;
-
- phys_addr -= address;
- if (address >= end)
- BUG();
-
- pgprot = __pgprot(L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY | L_PTE_WRITE | flags);
- do {
- pte_t * pte = pte_alloc(&init_mm, pmd, address);
- if (!pte)
- return -ENOMEM;
- remap_area_pte(pte, address, end - address, address + phys_addr, pgprot);
- address = (address + PMD_SIZE) & PMD_MASK;
- pmd++;
- } while (address && (address < end));
- return 0;
-}
-
-static int remap_area_pages(unsigned long address, unsigned long phys_addr,
- unsigned long size, unsigned long flags)
-{
- int error;
- pgd_t * dir;
- unsigned long end = address + size;
-
- phys_addr -= address;
- dir = pgd_offset(&init_mm, address);
- flush_cache_all();
- if (address >= end)
- BUG();
- spin_lock(&init_mm.page_table_lock);
- do {
- pmd_t *pmd;
- pmd = pmd_alloc(&init_mm, dir, address);
- error = -ENOMEM;
- if (!pmd)
- break;
- if (remap_area_pmd(pmd, address, end - address,
- phys_addr + address, flags))
- break;
- error = 0;
- address = (address + PGDIR_SIZE) & PGDIR_MASK;
- dir++;
- } while (address && (address < end));
- spin_unlock(&init_mm.page_table_lock);
- flush_tlb_all();
- return error;
-}
-
/*
* Remap an arbitrary physical address space into the kernel virtual
* address space. Needed when the kernel wants to access high addresses
@@ -134,6 +52,8 @@
void * addr;
struct vm_struct * area;
unsigned long offset, last_addr;
+ pgprot_t pgprot = __pgprot(L_PTE_PRESENT | L_PTE_YOUNG
+ | L_PTE_DIRTY | L_PTE_WRITE | flags);
/* Don't allow wraparound or zero size */
last_addr = phys_addr + size - 1;
@@ -154,7 +74,7 @@
if (!area)
return NULL;
addr = area->addr;
- if (remap_area_pages(VMALLOC_VMADDR(addr), phys_addr, size, flags)) {
+ if (remap_page_range(VMALLOC_VMADDR(addr), phys_addr, size, pgprot)) {
vfree(addr);
return NULL;
}
--- linux-2.4.17/arch/sh/mm/ioremap.c.orig Sat Sep 8 21:29:09 2001
+++ linux-2.4.17/arch/sh/mm/ioremap.c Sat Jan 5 13:35:40 2002
@@ -13,86 +13,6 @@
#include <asm/io.h>
#include <asm/pgalloc.h>
-static inline void remap_area_pte(pte_t * pte, unsigned long address,
- unsigned long size, unsigned long phys_addr, unsigned long flags)
-{
- unsigned long end;
- pgprot_t pgprot = __pgprot(_PAGE_PRESENT | _PAGE_RW |
- _PAGE_DIRTY | _PAGE_ACCESSED |
- _PAGE_HW_SHARED | _PAGE_FLAGS_HARD | flags);
-
- address &= ~PMD_MASK;
- end = address + size;
- if (end > PMD_SIZE)
- end = PMD_SIZE;
- if (address >= end)
- BUG();
- do {
- if (!pte_none(*pte)) {
- printk("remap_area_pte: page already exists\n");
- BUG();
- }
- set_pte(pte, mk_pte_phys(phys_addr, pgprot));
- address += PAGE_SIZE;
- phys_addr += PAGE_SIZE;
- pte++;
- } while (address && (address < end));
-}
-
-static inline int remap_area_pmd(pmd_t * pmd, unsigned long address,
- unsigned long size, unsigned long phys_addr, unsigned long flags)
-{
- unsigned long end;
-
- address &= ~PGDIR_MASK;
- end = address + size;
- if (end > PGDIR_SIZE)
- end = PGDIR_SIZE;
- phys_addr -= address;
- if (address >= end)
- BUG();
- do {
- pte_t * pte = pte_alloc(&init_mm, pmd, address);
- if (!pte)
- return -ENOMEM;
- remap_area_pte(pte, address, end - address, address + phys_addr, flags);
- address = (address + PMD_SIZE) & PMD_MASK;
- pmd++;
- } while (address && (address < end));
- return 0;
-}
-
-int remap_area_pages(unsigned long address, unsigned long phys_addr,
- unsigned long size, unsigned long flags)
-{
- int error;
- pgd_t * dir;
- unsigned long end = address + size;
-
- phys_addr -= address;
- dir = pgd_offset_k(address);
- flush_cache_all();
- if (address >= end)
- BUG();
- spin_lock(&init_mm.page_table_lock);
- do {
- pmd_t *pmd;
- pmd = pmd_alloc(&init_mm, dir, address);
- error = -ENOMEM;
- if (!pmd)
- break;
- if (remap_area_pmd(pmd, address, end - address,
- phys_addr + address, flags))
- break;
- error = 0;
- address = (address + PGDIR_SIZE) & PGDIR_MASK;
- dir++;
- } while (address && (address < end));
- spin_unlock(&init_mm.page_table_lock);
- flush_tlb_all();
- return error;
-}
-
/*
* Generic mapping function (not visible outside):
*/
@@ -111,6 +31,9 @@
void * addr;
struct vm_struct * area;
unsigned long offset, last_addr;
+ pgprot_t pgprot = __pgprot(_PAGE_PRESENT | _PAGE_RW |
+ _PAGE_DIRTY | _PAGE_ACCESSED |
+ _PAGE_HW_SHARED | _PAGE_FLAGS_HARD | flags);
/* Don't allow wraparound or zero size */
last_addr = phys_addr + size - 1;
@@ -143,7 +66,7 @@
if (!area)
return NULL;
addr = area->addr;
- if (remap_area_pages(VMALLOC_VMADDR(addr), phys_addr, size, flags)) {
+ if (remap_page_range(VMALLOC_VMADDR(addr), phys_addr, size, pgprot)) {
vfree(addr);
return NULL;
}
--- linux-2.4.17/arch/ia64/kernel/ia64_ksyms.c.orig Fri Nov 9 23:26:17 2001
+++ linux-2.4.17/arch/ia64/kernel/ia64_ksyms.c Sat Jan 5 14:06:11 2002
@@ -43,6 +43,8 @@
EXPORT_SYMBOL(ip_fast_csum);
#include <asm/io.h>
+EXPORT_SYMBOL(__ioremap);
+EXPORT_SYMBOL(iounmap);
EXPORT_SYMBOL(__ia64_memcpy_fromio);
EXPORT_SYMBOL(__ia64_memcpy_toio);
EXPORT_SYMBOL(__ia64_memset_c_io);
--- linux-2.4.17/arch/ia64/mm/ioremap.c.orig Sat Jan 5 13:59:40 2002
+++ linux-2.4.17/arch/ia64/mm/ioremap.c Sat Jan 5 13:43:41 2002
@@ -0,0 +1,70 @@
+/*
+ * arch/ia64/mm/ioremap.c
+ *
+ * IA64 version
+ * Copyright (C) 2001 Scali AS
+ * Author(s): Steffen Persvold (sp@scali.com)
+ *
+ * Derived from "arch/i386/mm/ioremap.c"
+ * (C) Copyright 1995 1996 Linus Torvalds
+ *
+ * Re-map IO memory to kernel address space so that we can access it.
+ */
+
+#include <linux/vmalloc.h>
+#include <asm/io.h>
+#include <asm/pgalloc.h>
+
+/*
+ * Generic mapping function (not visible outside):
+ */
+
+/*
+ * Remap an arbitrary physical address space into the kernel virtual
+ * address space. Needed when the kernel wants to access high addresses
+ * directly.
+ *
+ * NOTE! We need to allow non-page-aligned mappings too: we will obviously
+ * have to convert them into an offset in a page-aligned mapping, but the
+ * caller shouldn't need to know that small detail.
+ */
+void * __ioremap(unsigned long phys_addr, unsigned long size, unsigned long flags)
+{
+ void * addr;
+ struct vm_struct * area;
+ unsigned long offset, last_addr;
+ pgprot_t pgprot = __pgprot(__DIRTY_BITS | _PAGE_PL_0
+ | _PAGE_AR_RWX | flags);
+
+ /* Don't allow wraparound */
+ last_addr = phys_addr + size - 1;
+ if (!size || last_addr < phys_addr)
+ return NULL;
+
+ /*
+ * Mappings have to be page-aligned
+ */
+ offset = phys_addr & ~PAGE_MASK;
+ phys_addr &= PAGE_MASK;
+ size = PAGE_ALIGN(last_addr) - phys_addr;
+
+ /*
+ * Ok, go for it..
+ */
+ area = get_vm_area(size, VM_IOREMAP);
+ if (!area)
+ return NULL;
+ addr = area->addr;
+
+ if (remap_page_range(VMALLOC_VMADDR(addr), phys_addr, size, pgprot)) {
+ vfree(addr);
+ return NULL;
+ }
+ return (void *) (offset + (char *)addr);
+}
+
+void iounmap(void *addr)
+{
+ if ((unsigned long)addr > VMALLOC_START && (unsigned long)addr < VMALLOC_END)
+ vfree((void *) (PAGE_MASK & (unsigned long) addr));
+}
--- linux-2.4.17/arch/s390/mm/ioremap.c.orig Thu Apr 12 04:02:27 2001
+++ linux-2.4.17/arch/s390/mm/ioremap.c Sat Jan 5 13:41:05 2002
@@ -17,84 +17,6 @@
#include <asm/io.h>
#include <asm/pgalloc.h>
-static inline void remap_area_pte(pte_t * pte, unsigned long address, unsigned long size,
- unsigned long phys_addr, unsigned long flags)
-{
- unsigned long end;
-
- address &= ~PMD_MASK;
- end = address + size;
- if (end > PMD_SIZE)
- end = PMD_SIZE;
- if (address >= end)
- BUG();
- do {
- if (!pte_none(*pte)) {
- printk("remap_area_pte: page already exists\n");
- BUG();
- }
- set_pte(pte, mk_pte_phys(phys_addr,
- __pgprot(_PAGE_PRESENT | flags)));
- address += PAGE_SIZE;
- phys_addr += PAGE_SIZE;
- pte++;
- } while (address && (address < end));
-}
-
-static inline int remap_area_pmd(pmd_t * pmd, unsigned long address, unsigned long size,
- unsigned long phys_addr, unsigned long flags)
-{
- unsigned long end;
-
- address &= ~PGDIR_MASK;
- end = address + size;
- if (end > PGDIR_SIZE)
- end = PGDIR_SIZE;
- phys_addr -= address;
- if (address >= end)
- BUG();
- do {
- pte_t * pte = pte_alloc(&init_mm, pmd, address);
- if (!pte)
- return -ENOMEM;
- remap_area_pte(pte, address, end - address, address + phys_addr, flags);
- address = (address + PMD_SIZE) & PMD_MASK;
- pmd++;
- } while (address && (address < end));
- return 0;
-}
-
-static int remap_area_pages(unsigned long address, unsigned long phys_addr,
- unsigned long size, unsigned long flags)
-{
- int error;
- pgd_t * dir;
- unsigned long end = address + size;
-
- phys_addr -= address;
- dir = pgd_offset(&init_mm, address);
- flush_cache_all();
- if (address >= end)
- BUG();
- spin_lock(&init_mm.page_table_lock);
- do {
- pmd_t *pmd;
- pmd = pmd_alloc(&init_mm, dir, address);
- error = -ENOMEM;
- if (!pmd)
- break;
- if (remap_area_pmd(pmd, address, end - address,
- phys_addr + address, flags))
- break;
- error = 0;
- address = (address + PGDIR_SIZE) & PGDIR_MASK;
- dir++;
- } while (address && (address < end));
- spin_unlock(&init_mm.page_table_lock);
- flush_tlb_all();
- return 0;
-}
-
/*
* Generic mapping function (not visible outside):
*/
@@ -108,7 +30,8 @@
{
void * addr;
struct vm_struct * area;
-
+ pgprot_t pgprot = __pgprot(_PAGE_PRESENT | flags);
+
if (phys_addr < virt_to_phys(high_memory))
return phys_to_virt(phys_addr);
if (phys_addr & ~PAGE_MASK)
@@ -120,7 +43,7 @@
if (!area)
return NULL;
addr = area->addr;
- if (remap_area_pages(VMALLOC_VMADDR(addr), phys_addr, size, flags)) {
+ if (remap_page_range(VMALLOC_VMADDR(addr), phys_addr, size, pgprot)) {
vfree(addr);
return NULL;
}
--- linux-2.4.17/arch/cris/mm/ioremap.c.orig Wed May 2 01:04:56 2001
+++ linux-2.4.17/arch/cris/mm/ioremap.c Sat Jan 5 13:40:24 2002
@@ -13,85 +13,6 @@
#include <asm/io.h>
#include <asm/pgalloc.h>
-static inline void remap_area_pte(pte_t * pte, unsigned long address, unsigned long size,
- unsigned long phys_addr, unsigned long flags)
-{
- unsigned long end;
-
- address &= ~PMD_MASK;
- end = address + size;
- if (end > PMD_SIZE)
- end = PMD_SIZE;
- if (address >= end)
- BUG();
- do {
- if (!pte_none(*pte)) {
- printk("remap_area_pte: page already exists\n");
- BUG();
- }
- set_pte(pte, mk_pte_phys(phys_addr, __pgprot(_PAGE_PRESENT | __READABLE |
- __WRITEABLE | _PAGE_GLOBAL |
- _PAGE_KERNEL | flags)));
- address += PAGE_SIZE;
- phys_addr += PAGE_SIZE;
- pte++;
- } while (address && (address < end));
-}
-
-static inline int remap_area_pmd(pmd_t * pmd, unsigned long address, unsigned long size,
- unsigned long phys_addr, unsigned long flags)
-{
- unsigned long end;
-
- address &= ~PGDIR_MASK;
- end = address + size;
- if (end > PGDIR_SIZE)
- end = PGDIR_SIZE;
- phys_addr -= address;
- if (address >= end)
- BUG();
- do {
- pte_t * pte = pte_alloc(&init_mm, pmd, address);
- if (!pte)
- return -ENOMEM;
- remap_area_pte(pte, address, end - address, address + phys_addr, flags);
- address = (address + PMD_SIZE) & PMD_MASK;
- pmd++;
- } while (address && (address < end));
- return 0;
-}
-
-static int remap_area_pages(unsigned long address, unsigned long phys_addr,
- unsigned long size, unsigned long flags)
-{
- int error;
- pgd_t * dir;
- unsigned long end = address + size;
-
- phys_addr -= address;
- dir = pgd_offset(&init_mm, address);
- flush_cache_all();
- if (address >= end)
- BUG();
- spin_lock(&init_mm.page_table_lock);
- do {
- pmd_t *pmd;
- pmd = pmd_alloc(&init_mm, dir, address);
- error = -ENOMEM;
- if (!pmd)
- break;
- if (remap_area_pmd(pmd, address, end - address,
- phys_addr + address, flags))
- break;
- error = 0;
- address = (address + PGDIR_SIZE) & PGDIR_MASK;
- dir++;
- } while (address && (address < end));
- spin_unlock(&init_mm.page_table_lock);
- flush_tlb_all();
- return error;
-}
-
/*
* Generic mapping function (not visible outside):
*/
@@ -110,7 +31,9 @@
void * addr;
struct vm_struct * area;
unsigned long offset, last_addr;
-
+ pgprot_t pgprot = __pgprot(_PAGE_PRESENT | __READABLE | __WRITEABLE
+ | _PAGE_GLOBAL | _PAGE_KERNEL | flags);
+
/* Don't allow wraparound or zero size */
last_addr = phys_addr + size - 1;
if (!size || last_addr < phys_addr)
@@ -155,7 +78,7 @@
if (!area)
return NULL;
addr = area->addr;
- if (remap_area_pages(VMALLOC_VMADDR(addr), phys_addr, size, flags)) {
+ if (remap_page_range(VMALLOC_VMADDR(addr), phys_addr, size, pgprot)) {
vfree(addr);
return NULL;
}
--- linux-2.4.17/arch/s390x/mm/ioremap.c.orig Thu Apr 12 04:02:30 2001
+++ linux-2.4.17/arch/s390x/mm/ioremap.c Sat Jan 5 13:42:15 2002
@@ -17,84 +17,6 @@
#include <asm/io.h>
#include <asm/pgalloc.h>
-static inline void remap_area_pte(pte_t * pte, unsigned long address, unsigned long size,
- unsigned long phys_addr, unsigned long flags)
-{
- unsigned long end;
-
- address &= ~PMD_MASK;
- end = address + size;
- if (end > PMD_SIZE)
- end = PMD_SIZE;
- if (address >= end)
- BUG();
- do {
- if (!pte_none(*pte)) {
- printk("remap_area_pte: page already exists\n");
- BUG();
- }
- set_pte(pte, mk_pte_phys(phys_addr,
- __pgprot(_PAGE_PRESENT | flags)));
- address += PAGE_SIZE;
- phys_addr += PAGE_SIZE;
- pte++;
- } while (address && (address < end));
-}
-
-static inline int remap_area_pmd(pmd_t * pmd, unsigned long address, unsigned long size,
- unsigned long phys_addr, unsigned long flags)
-{
- unsigned long end;
-
- address &= ~PGDIR_MASK;
- end = address + size;
- if (end > PGDIR_SIZE)
- end = PGDIR_SIZE;
- phys_addr -= address;
- if (address >= end)
- BUG();
- do {
- pte_t * pte = pte_alloc(&init_mm, pmd, address);
- if (!pte)
- return -ENOMEM;
- remap_area_pte(pte, address, end - address, address + phys_addr, flags);
- address = (address + PMD_SIZE) & PMD_MASK;
- pmd++;
- } while (address && (address < end));
- return 0;
-}
-
-static int remap_area_pages(unsigned long address, unsigned long phys_addr,
- unsigned long size, unsigned long flags)
-{
- int error;
- pgd_t * dir;
- unsigned long end = address + size;
-
- phys_addr -= address;
- dir = pgd_offset(&init_mm, address);
- flush_cache_all();
- if (address >= end)
- BUG();
- spin_lock(&init_mm.page_table_lock);
- do {
- pmd_t *pmd;
- pmd = pmd_alloc(&init_mm, dir, address);
- error = -ENOMEM;
- if (!pmd)
- break;
- if (remap_area_pmd(pmd, address, end - address,
- phys_addr + address, flags))
- break;
- error = 0;
- address = (address + PGDIR_SIZE) & PGDIR_MASK;
- dir++;
- } while (address && (address < end));
- spin_unlock(&init_mm.page_table_lock);
- flush_tlb_all();
- return 0;
-}
-
/*
* Generic mapping function (not visible outside):
*/
@@ -108,6 +30,7 @@
{
void * addr;
struct vm_struct * area;
+ pgprot_t pgprot = __pgprot(_PAGE_PRESENT | flags);
if (phys_addr < virt_to_phys(high_memory))
return phys_to_virt(phys_addr);
@@ -120,7 +43,7 @@
if (!area)
return NULL;
addr = area->addr;
- if (remap_area_pages(VMALLOC_VMADDR(addr), phys_addr, size, flags)) {
+ if (remap_page_range(VMALLOC_VMADDR(addr), phys_addr, size, pgprot)) {
vfree(addr);
return NULL;
}
--- linux-2.4.17/include/asm-ia64/io.h.orig Fri Nov 9 23:26:17 2001
+++ linux-2.4.17/include/asm-ia64/io.h Sat Jan 5 13:46:26 2002
@@ -37,6 +37,7 @@
#include <asm/machvec.h>
#include <asm/page.h>
#include <asm/system.h>
+#include <asm/pgtable.h>
/*
* Change virtual addresses to physical addresses and vv.
@@ -378,19 +379,23 @@
* accept both, thus the casts.
*
* On ia-64, we access the physical I/O memory space through the uncached kernel region.
+ *
+ * Which is not a good idea if we want speed on large PIO operations. It is now possible
+ * to map dynamically so that we can use the page table attributes to decide the caching.
+ * ioremap_wrcomb() does this and uses Write Coalescing attribute.
*/
+
+extern void * __ioremap(unsigned long offset, unsigned long size, unsigned long flags);
+extern void iounmap(void *addr);
+
static inline void *
ioremap (unsigned long offset, unsigned long size)
{
return (void *) (__IA64_UNCACHED_OFFSET | (offset));
}
-static inline void
-iounmap (void *addr)
-{
-}
-
#define ioremap_nocache(o,s) ioremap(o,s)
+#define ioremap_wrcomb(o,s) __ioremap(o,s,_PAGE_MA_WC)
# ifdef __KERNEL__
--- linux-2.4.17/include/asm-ia64/pgtable.h.orig Sat Jan 5 13:55:06 2002
+++ linux-2.4.17/include/asm-ia64/pgtable.h Sat Jan 5 14:20:13 2002
@@ -125,7 +125,6 @@
# ifndef __ASSEMBLY__
#include <asm/bitops.h>
-#include <asm/mmu_context.h>
#include <asm/processor.h>
/*
@@ -329,11 +328,7 @@
/* The offset in the 1-level directory is given by the 3 region bits
(61..63) and the seven level-1 bits (33-39). */
-static inline pgd_t*
-pgd_offset (struct mm_struct *mm, unsigned long address)
-{
- return mm->pgd + pgd_index(address);
-}
+#define pgd_offset(mm, address) ((mm)->pgd+pgd_index(address))
/* In the kernel's mapped region we have a full 43 bit space available and completely
ignore the region number (since we know its in region number 5). */
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [Linux-ia64] Re: Status on ioremap patch
2001-09-14 23:14 [Linux-ia64] Re: Status on ioremap patch David Mosberger
` (2 preceding siblings ...)
2002-01-05 15:01 ` Steffen Persvold
@ 2002-01-05 23:30 ` Keith Owens
2002-01-06 11:02 ` Steffen Persvold
` (4 subsequent siblings)
8 siblings, 0 replies; 12+ messages in thread
From: Keith Owens @ 2002-01-05 23:30 UTC (permalink / raw)
To: linux-ia64
On Sat, 05 Jan 2002 16:01:29 +0100,
Steffen Persvold <sp@scali.no> wrote:
>--- linux-2.4.17/mm/memory.c.orig Fri Dec 21 18:42:05 2001
>+++ linux-2.4.17/mm/memory.c Sat Jan 5 13:13:26 2002
>@@ -791,6 +791,9 @@
> * maps a range of physical memory into the requested pages. the old
> * mappings are removed. any references to nonexistent pages results
> * in null mappings (currently treated as "copy-on-access")
>+ *
>+ * For physical (or I/O) memory mapped into the kernel virtual space,
>+ * the old mappings will not be removed.
That comment worries me. If you have multiple mappings for the same
page then you may have problems on hardware that uses virtually indexed
caches. Two virtual addresses could map to the same physical page but
index to different cache lines, destroying cache coherency. How do you
prevent that?
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [Linux-ia64] Re: Status on ioremap patch
2001-09-14 23:14 [Linux-ia64] Re: Status on ioremap patch David Mosberger
` (3 preceding siblings ...)
2002-01-05 23:30 ` Keith Owens
@ 2002-01-06 11:02 ` Steffen Persvold
2002-01-06 11:55 ` Keith Owens
` (3 subsequent siblings)
8 siblings, 0 replies; 12+ messages in thread
From: Steffen Persvold @ 2002-01-06 11:02 UTC (permalink / raw)
To: linux-ia64
Keith Owens wrote:
>
> On Sat, 05 Jan 2002 16:01:29 +0100,
> Steffen Persvold <sp@scali.no> wrote:
> >--- linux-2.4.17/mm/memory.c.orig Fri Dec 21 18:42:05 2001
> >+++ linux-2.4.17/mm/memory.c Sat Jan 5 13:13:26 2002
> >@@ -791,6 +791,9 @@
> > * maps a range of physical memory into the requested pages. the old
> > * mappings are removed. any references to nonexistent pages results
> > * in null mappings (currently treated as "copy-on-access")
> >+ *
> >+ * For physical (or I/O) memory mapped into the kernel virtual space,
> >+ * the old mappings will not be removed.
>
> That comment worries me. If you have multiple mappings for the same
> page then you may have problems on hardware that uses virtually indexed
> caches. Two virtual addresses could map to the same physical page but
> index to different cache lines, destroying cache coherency. How do you
> prevent that?
>
Well, actually multiple mappings in kernel space is denied :
+ if (address > VMALLOC_START && address < VMALLOC_END) {
+ if (!pte_none(*pte)) {
+ printk("remap_area_pte: page already exists\n");
+ BUG();
+ }
+ set_pte(pte, mk_pte_phys(phys_addr, prot));
+ } else {
+ struct page *page;
+ pte_t oldpage;
+ oldpage = ptep_get_and_clear(pte);
+
+ page = virt_to_page(__va(phys_addr));
+ if ((!VALID_PAGE(page)) || PageReserved(page))
+ set_pte(pte, mk_pte_phys(phys_addr, prot));
+ forget_pte(oldpage);
+ }
Regards,
--
Steffen Persvold | Scalable Linux Systems | Try out the world's best
mailto:sp@scali.no | http://www.scali.com | performing MPI implementation:
Tel: (+47) 2262 8950 | Olaf Helsets vei 6 | - ScaMPI 1.12.2 -
Fax: (+47) 2262 8951 | N0621 Oslo, NORWAY | >300MBytes/s and <4uS latency
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [Linux-ia64] Re: Status on ioremap patch
2001-09-14 23:14 [Linux-ia64] Re: Status on ioremap patch David Mosberger
` (4 preceding siblings ...)
2002-01-06 11:02 ` Steffen Persvold
@ 2002-01-06 11:55 ` Keith Owens
2002-01-06 14:27 ` Steffen Persvold
` (2 subsequent siblings)
8 siblings, 0 replies; 12+ messages in thread
From: Keith Owens @ 2002-01-06 11:55 UTC (permalink / raw)
To: linux-ia64
On Sun, 06 Jan 2002 12:02:01 +0100,
Steffen Persvold <sp@scali.no> wrote:
>Keith Owens wrote:
>>
>> On Sat, 05 Jan 2002 16:01:29 +0100,
>> Steffen Persvold <sp@scali.no> wrote:
>> >--- linux-2.4.17/mm/memory.c.orig Fri Dec 21 18:42:05 2001
>> >+++ linux-2.4.17/mm/memory.c Sat Jan 5 13:13:26 2002
>> >@@ -791,6 +791,9 @@
>> > * maps a range of physical memory into the requested pages. the old
>> > * mappings are removed. any references to nonexistent pages results
>> > * in null mappings (currently treated as "copy-on-access")
>> >+ *
>> >+ * For physical (or I/O) memory mapped into the kernel virtual space,
>> >+ * the old mappings will not be removed.
>>
>> That comment worries me. If you have multiple mappings for the same
>> page then you may have problems on hardware that uses virtually indexed
>> caches. Two virtual addresses could map to the same physical page but
>> index to different cache lines, destroying cache coherency. How do you
>> prevent that?
>>
>
>Well, actually multiple mappings in kernel space is denied :
>
>+ if (address > VMALLOC_START && address < VMALLOC_END) {
>+ if (!pte_none(*pte)) {
>+ printk("remap_area_pte: page already exists\n");
>+ BUG();
>+ }
>+ set_pte(pte, mk_pte_phys(phys_addr, prot));
>+ } else {
>+ struct page *page;
>+ pte_t oldpage;
>+ oldpage = ptep_get_and_clear(pte);
>+
>+ page = virt_to_page(__va(phys_addr));
>+ if ((!VALID_PAGE(page)) || PageReserved(page))
>+ set_pte(pte, mk_pte_phys(phys_addr, prot));
>+ forget_pte(oldpage);
>+ }
What about one mapping in kernel space and one in user space, or two
mappings in user space? As long as you have more than one mapping to
the same physical page you must handle virtual cache aliasing.
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [Linux-ia64] Re: Status on ioremap patch
2001-09-14 23:14 [Linux-ia64] Re: Status on ioremap patch David Mosberger
` (5 preceding siblings ...)
2002-01-06 11:55 ` Keith Owens
@ 2002-01-06 14:27 ` Steffen Persvold
2002-01-09 20:01 ` Steffen Persvold
2002-01-10 3:01 ` David Mosberger
8 siblings, 0 replies; 12+ messages in thread
From: Steffen Persvold @ 2002-01-06 14:27 UTC (permalink / raw)
To: linux-ia64
Keith Owens wrote:
>
> On Sun, 06 Jan 2002 12:02:01 +0100,
> Steffen Persvold <sp@scali.no> wrote:
> >Keith Owens wrote:
> >>
> >> On Sat, 05 Jan 2002 16:01:29 +0100,
> >> Steffen Persvold <sp@scali.no> wrote:
> >> >--- linux-2.4.17/mm/memory.c.orig Fri Dec 21 18:42:05 2001
> >> >+++ linux-2.4.17/mm/memory.c Sat Jan 5 13:13:26 2002
> >> >@@ -791,6 +791,9 @@
> >> > * maps a range of physical memory into the requested pages. the old
> >> > * mappings are removed. any references to nonexistent pages results
> >> > * in null mappings (currently treated as "copy-on-access")
> >> >+ *
> >> >+ * For physical (or I/O) memory mapped into the kernel virtual space,
> >> >+ * the old mappings will not be removed.
> >>
> >> That comment worries me. If you have multiple mappings for the same
> >> page then you may have problems on hardware that uses virtually indexed
> >> caches. Two virtual addresses could map to the same physical page but
> >> index to different cache lines, destroying cache coherency. How do you
> >> prevent that?
> >>
> >
> >Well, actually multiple mappings in kernel space is denied :
> >
> >+ if (address > VMALLOC_START && address < VMALLOC_END) {
> >+ if (!pte_none(*pte)) {
> >+ printk("remap_area_pte: page already exists\n");
> >+ BUG();
> >+ }
> >+ set_pte(pte, mk_pte_phys(phys_addr, prot));
> >+ } else {
> >+ struct page *page;
> >+ pte_t oldpage;
> >+ oldpage = ptep_get_and_clear(pte);
> >+
> >+ page = virt_to_page(__va(phys_addr));
> >+ if ((!VALID_PAGE(page)) || PageReserved(page))
> >+ set_pte(pte, mk_pte_phys(phys_addr, prot));
> >+ forget_pte(oldpage);
> >+ }
>
> What about one mapping in kernel space and one in user space, or two
> mappings in user space? As long as you have more than one mapping to
> the same physical page you must handle virtual cache aliasing.
>
If you do two mappings from userspace (via mmap() and from there remap_page_range()), the "else"
case would be true because then the addess isn't a kernel virtual address and the old mapping would
be forgotten. The case where ioremap() is called first and then remap_page_range() is called later
(via mmap() function) will also work fine. The two cases I can think of where the BUG() case wold
trigger, are when remap_page_range() is called first and then ioremap() is called, or when ioremap()
is called twice. None of these two cases is something that I would consider "legal" and this would
also happen with the old (similar) ioremap() implementation.
Do you think I should drop the if/else statements and just always treat it as it was two mappings
from userspace (currently the "else" case) ?
Regards,
--
Steffen Persvold | Scalable Linux Systems | Try out the world's best
mailto:sp@scali.no | http://www.scali.com | performing MPI implementation:
Tel: (+47) 2262 8950 | Olaf Helsets vei 6 | - ScaMPI 1.12.2 -
Fax: (+47) 2262 8951 | N0621 Oslo, NORWAY | >300MBytes/s and <4uS latency
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [Linux-ia64] Re: Status on ioremap patch
2001-09-14 23:14 [Linux-ia64] Re: Status on ioremap patch David Mosberger
` (6 preceding siblings ...)
2002-01-06 14:27 ` Steffen Persvold
@ 2002-01-09 20:01 ` Steffen Persvold
2002-01-10 3:01 ` David Mosberger
8 siblings, 0 replies; 12+ messages in thread
From: Steffen Persvold @ 2002-01-09 20:01 UTC (permalink / raw)
To: linux-ia64
Steffen Persvold wrote:
>
> David Mosberger wrote:
> >
> > Steffen,
> >
> > I looked at your patch and have a comment and a suggestion. First, I
> > do not think it's safe to define ioremap() as a way to install
> > write-cached mappings. There are plenty of drivers left that use
> > ioremap() instead of ioremap_nocache() and we can't change the
> > semantics of ioremap() underneath them.
> >
> > Second, it seems to me it would be cleaner to extend
> > remap_page_range() to allow remapping into the kernel mapped segment
> > (region 5 in the case of ia64 linux). This should work as is, except
> > that in the kernel case, you need to use pgd_offset_k(). I think you
> > could hack mm/memory.c to check whether "from" is in the range from
> > VMALLOC_START to VMALLOC_END and, if so, use pgd_offset_k() instead of
> > pgd_offset(). Can you try this and let me know if it works for your
> > needs?
> >
>
> I've had some time to look at it, and I decided to do what you said. I also changed ioremap on all
> platforms that implements it so that they use remap_page_range()). I've tested the patch on IA64 and
> i386.
>
> I've attached the patch (I didn't post it on the lkml even though it affects more that the IA64
> platform), it's against a vanilla 2.4.17 tree.
>
> Please take a look and tell me what you think.
>
So, what about this patch (posted earlier) David ? Have you seen the comments from Keith ?
Regards,
--
Steffen Persvold | Scalable Linux Systems | Try out the world's best
mailto:sp@scali.no | http://www.scali.com | performing MPI implementation:
Tel: (+47) 2262 8950 | Olaf Helsets vei 6 | - ScaMPI 1.12.2 -
Fax: (+47) 2262 8951 | N0621 Oslo, NORWAY | >300MBytes/s and <4uS latency
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [Linux-ia64] Re: Status on ioremap patch
2001-09-14 23:14 [Linux-ia64] Re: Status on ioremap patch David Mosberger
` (7 preceding siblings ...)
2002-01-09 20:01 ` Steffen Persvold
@ 2002-01-10 3:01 ` David Mosberger
8 siblings, 0 replies; 12+ messages in thread
From: David Mosberger @ 2002-01-10 3:01 UTC (permalink / raw)
To: linux-ia64
>>>>> On Wed, 09 Jan 2002 21:01:13 +0100, Steffen Persvold <sp@scali.no> said:
Steffen> So, what about this patch (posted earlier) David ? Have you
Steffen> seen the comments from Keith ?
Keith's concerns are legitimate and to some degree apply even for
ia64. On ia64, we need to be careful to avoid mapping the same
physical page with different memory attributes. If more and more
drivers are starting to use write-combine mappings, we need to solve
this problem properly. I don't have a solution off hand (I suspect
we'll have to keep track of which i/o regions are mapped how) and
don't have time to work on it now. I'd recommend to maintain a
separate patch for now, until a proper solution is ready (which will
have to take non-ia64 platforms into consideration, of course).
--david
PS: I apologize for not being as responsive yet as I'd like to be.
I'm done with the book (well, 99.999% as my wife put it...) and
ready to attack my backlog of kernel work (and other things, such
as user-level unwind support). I just had a spell of bad luck
this week, which didn't help. Hopefully, over the next one or two
weeks, things will start to go back to normal.
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [Linux-ia64] Re: Status on ioremap patch
@ 2004-03-03 15:12 Hugo Kohmann
2004-03-03 22:58 ` David Mosberger
0 siblings, 1 reply; 12+ messages in thread
From: Hugo Kohmann @ 2004-03-03 15:12 UTC (permalink / raw)
To: linux-ia64
Hi,
Is there any news or progress for official support for setting up kernel
space write-combine mappings for Itanium systems. ?? Steffens patch is a
good start, but we would like to avoid patching the kernel.
We are currently implementing a kernel space socket module for SCI
(bypassing the TCP/IP protocols). Typical latency for send/receive
between two systems is down to 2.7us for small messages ( Benchmarks
running on Opterons ). Without kernel write-combine we would need to use
regular DMA to move data, and we would no longer get the 2.7us latency.
Linux running on both IA32 and X86_64 systems supports some kind of kernel
write-combine, why not IA64 ??
Best regards
Hugo
>>>>>> On Wed, 09 Jan 2002 21:01:13 +0100, Steffen Persvold <sp@scali.no>
>said:
>
> Steffen> So, what about this patch (posted earlier) David ? Have you
> Steffen> seen the comments from Keith ?
>
>Keith's concerns are legitimate and to some degree apply even for
>ia64. On ia64, we need to be careful to avoid mapping the same
>physical page with different memory attributes. If more and more
>drivers are starting to use write-combine mappings, we need to solve
>this problem properly. I don't have a solution off hand (I suspect
>we'll have to keep track of which i/o regions are mapped how) and
>don't have time to work on it now. I'd recommend to maintain a
>separate patch for now, until a proper solution is ready (which will
>have to take non-ia64 platforms into consideration, of course).
>
> --david
>
>PS: I apologize for not being as responsive yet as I'd like to be.
> I'm done with the book (well, 99.999% as my wife put it...) and
> ready to attack my backlog of kernel work (and other things, such
> as user-level unwind support). I just had a spell of bad luck
> this week, which didn't help. Hopefully, over the next one or two
> weeks, things will start to go back to normal.
--
============================================Hugo Kohmann |
Dolphin Interconnect Solutions AS | E-mail:
P.O. Box 150 Oppsal | hugo@dolphinics.com
N-0619 Oslo, Norway | Web:
Tel:+47 23 16 71 73 | http://www.dolphinics.com
Fax:+47 23 16 71 80 | Home Office:
Visiting Address: Olaf Helsets vei 6 | Tel: +47 22 23 25 35
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [Linux-ia64] Re: Status on ioremap patch
2004-03-03 15:12 Hugo Kohmann
@ 2004-03-03 22:58 ` David Mosberger
0 siblings, 0 replies; 12+ messages in thread
From: David Mosberger @ 2004-03-03 22:58 UTC (permalink / raw)
To: linux-ia64
>>>>> On Wed, 3 Mar 2004 16:12:33 +0100 (CET), Hugo Kohmann <hugo@dolphinics.no> said:
Hugo> supports some kind of kernel write-combine, why not IA64 ??
I don't think anybody has anything _against_ adding such a feature, if
done properly ("properly" ~= the resulting interface must be safe and
prevent memory-attribute conflicts). AFAIR, the last patch didn't
address the memory-attribute issue at all, so it wasn't fit for
general use.
--david
^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2004-03-03 22:58 UTC | newest]
Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2001-09-14 23:14 [Linux-ia64] Re: Status on ioremap patch David Mosberger
2001-09-15 12:36 ` Steffen Persvold
2001-09-28 12:39 ` Jes Sorensen
2002-01-05 15:01 ` Steffen Persvold
2002-01-05 23:30 ` Keith Owens
2002-01-06 11:02 ` Steffen Persvold
2002-01-06 11:55 ` Keith Owens
2002-01-06 14:27 ` Steffen Persvold
2002-01-09 20:01 ` Steffen Persvold
2002-01-10 3:01 ` David Mosberger
-- strict thread matches above, loose matches on Subject: below --
2004-03-03 15:12 Hugo Kohmann
2004-03-03 22:58 ` David Mosberger
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox