From: Mark Powell <medp@primagraphics.co.uk>
To: Neil Wilson <NWilson@Airspan.com>
Cc: linuxppc-embedded@ozlabs.org
Subject: Re: mmap64/open64/pread etc on 440GX
Date: Thu, 11 Nov 2004 10:57:35 +0000 [thread overview]
Message-ID: <4193459F.8010803@primagraphics.co.uk> (raw)
In-Reply-To: <3506EDCDEC47904CBE6FD2E1DEEA8984020CFB73@fs5.airspan.com>
[-- Attachment #1: Type: text/plain, Size: 988 bytes --]
FWIW, the attached might help.
This is something I added to our 2.4.25 (10-May-04) tree to allow me do
the same thing on our '440GP platform.
The patch adds a file to arch/ppc/mm that provides an
io_remap_page_range64() function, analogous to ioremap64().
drv_mmap.c is the body of the mmap() entry point in my driver for an
example.
Hope it is useful
--
Mark Powell, Senior Software Engineer
Primagraphics, Curtiss-Wright Controls Embedded Computing
Tel: +44 (0) 1763 852222
Email: medp@primagraphics.com
Neil Wilson wrote:
>
>
>
>>I'm working on some patches to fix 36-bit support for
>>io_remap_page_range() and to fix some problems with set_pte()
>>and friends on 36-bit platforms. This is the first bit
>>necessary to make this work at all in 2.6. I should be
>>posting something RSN. ;)
>>
>>-Matt
>>
>>
>
>Okay, thanks for the info.
>
>Guess I will have to put together a simple kernel driver so the hardware
>boys can get 36bit access for now.
>
>Neil
>
>
>
[-- Attachment #2: mm.patch --]
[-- Type: text/plain, Size: 3369 bytes --]
diff -urN --exclude=CVS ../10-May-04/arch/ppc/mm/44x_remap.c ./arch/ppc/mm/44x_remap.c
--- ../10-May-04/arch/ppc/mm/44x_remap.c Thu Jan 1 01:00:00 1970
+++ ./arch/ppc/mm/44x_remap.c Thu Jun 3 16:54:44 2004
@@ -0,0 +1,102 @@
+/*
+ * Implementation of remap_page_range() for IBM440GP where physical
+ * addresses are 36 bits.
+ *
+ * This differs form ioremap64() in that it manipulates the
+ * current process's page tables.
+ *
+ * $Id: 44x_remap.c,v 1.1 2004/06/03 15:54:44 medp Exp $
+ * $Log: 44x_remap.c,v $
+ * Revision 1.1 2004/06/03 15:54:44 medp
+ * Added io_remap_page_range64
+ *
+ */
+#include <linux/mm.h>
+
+
+static inline void forget_pte(pte_t page)
+{
+ if (!pte_none(page)) {
+ printk("forget_pte: old mapping existed!\n");
+ BUG();
+ }
+}
+
+/*
+ * 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")
+ */
+static inline void io_remap_pte_range64(pte_t * pte, unsigned long address, unsigned long size,
+ phys_addr_t phys_addr, pgprot_t prot)
+{
+ unsigned long end;
+
+ address &= ~PMD_MASK;
+ end = address + size;
+ if (end > PMD_SIZE)
+ end = PMD_SIZE;
+ do {
+ pte_t oldpage;
+ oldpage = ptep_get_and_clear(pte);
+
+ set_pte(pte, mk_pte_phys(phys_addr, prot));
+ forget_pte(oldpage);
+ address += PAGE_SIZE;
+ phys_addr += PAGE_SIZE;
+ pte++;
+ } while (address && (address < end));
+}
+
+static inline int io_remap_pmd_range64(struct mm_struct *mm, pmd_t * pmd, unsigned long address, unsigned long size,
+ phys_addr_t phys_addr, pgprot_t prot)
+{
+ unsigned long end;
+
+ address &= ~PGDIR_MASK;
+ end = address + size;
+ if (end > PGDIR_SIZE)
+ end = PGDIR_SIZE;
+ phys_addr -= address;
+ do {
+ pte_t * pte = pte_alloc(mm, pmd, address);
+ if (!pte)
+ return -ENOMEM;
+ io_remap_pte_range64(pte, address, end - address, address + phys_addr, prot);
+ address = (address + PMD_SIZE) & PMD_MASK;
+ pmd++;
+ } while (address && (address < end));
+ return 0;
+}
+
+/* Note: this is only safe if the mm semaphore is held when called. */
+int io_remap_page_range64(unsigned long from, phys_addr_t phys_addr, unsigned long size, pgprot_t prot)
+{
+ int error = 0;
+ pgd_t * dir;
+ unsigned long beg = from;
+ unsigned long end = from + size;
+ struct mm_struct *mm = current->mm;
+
+ phys_addr -= from;
+ dir = pgd_offset(mm, from);
+ flush_cache_range(mm, beg, end);
+ if (from >= end)
+ BUG();
+
+ spin_lock(&mm->page_table_lock);
+ do {
+ pmd_t *pmd = pmd_alloc(mm, dir, from);
+ error = -ENOMEM;
+ if (!pmd)
+ break;
+ error = io_remap_pmd_range64(mm, pmd, from, end - from, phys_addr + from, prot);
+ if (error)
+ break;
+ from = (from + PGDIR_SIZE) & PGDIR_MASK;
+ dir++;
+ } while (from && (from < end));
+ spin_unlock(&mm->page_table_lock);
+ flush_tlb_range(mm, beg, end);
+ return error;
+}
diff -urN --exclude=CVS ../10-May-04/arch/ppc/mm/Makefile ./arch/ppc/mm/Makefile
--- ../10-May-04/arch/ppc/mm/Makefile Tue Dec 16 20:12:55 2003
+++ ./arch/ppc/mm/Makefile Thu Jun 3 16:54:44 2004
@@ -19,7 +19,7 @@
obj-$(CONFIG_PPC_STD_MMU) += hashtable.o ppc_mmu.o tlb.o
obj-$(CONFIG_40x) += 4xx_mmu.o
-obj-$(CONFIG_44x) += 44x_mmu.o
+obj-$(CONFIG_44x) += 44x_mmu.o 44x_remap.o
obj-$(CONFIG_NOT_COHERENT_CACHE) += cachemap.o
include $(TOPDIR)/Rules.make
[-- Attachment #3: drv_mmap.c --]
[-- Type: text/plain, Size: 1637 bytes --]
/*
* - Function ----------------------------------------------------------------
*
* sentric_fpga_mmap
*
* This function maps the FPGA register block to user space.
*
* Parameters:
* filep Pointer to file struct for this device.
* vma Pointer to the virtual memory area struct to map to.
*
* Returns:
* 0 success, -ve number is an error code.
*
* Notes:
* None.
* ---------------------------------------------------------------------------
*/
int
sentric_fpga_mmap(struct file *filep, struct vm_area_struct *vma)
{
unsigned long off;
phys_addr_t phys;
unsigned long vsize, psize;
/* Convert requested offset in units of pages to bytes */
/* This is the offset from base of FPGA regs region, should always be 0 */
off = vma->vm_pgoff << PAGE_SHIFT;
/* physical address */
phys = SENTRIC_FPGA_ADDR;
/* Check that the user hasn't asked for more than is available */
vsize = vma->vm_end - vma->vm_start;
psize = PAGE_SIZE - off;
if (vsize > psize) {
printk("sentric_fpga:mmap: requested too much i/o space: %ld\n", vsize);
return -EINVAL;
}
/* Use non-cached accesses as this is shared-memory */
vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
/* Don't try to swap out physical pages.. */
vma->vm_flags |= VM_RESERVED;
/* Don't dump addresses that are not real memory to a core file. */
vma->vm_flags |= VM_IO;
if (io_remap_page_range64(vma->vm_start, phys, vsize, vma->vm_page_prot)) {
return -EAGAIN;
}
return 0;
} /* sentric_fpga_mmap() */
next prev parent reply other threads:[~2004-11-11 10:57 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2004-11-11 7:32 mmap64/open64/pread etc on 440GX Neil Wilson
2004-11-11 10:57 ` Mark Powell [this message]
-- strict thread matches above, loose matches on Subject: below --
2004-11-10 13:58 Neil Wilson
2004-11-10 15:13 ` Matt Porter
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4193459F.8010803@primagraphics.co.uk \
--to=medp@primagraphics.co.uk \
--cc=NWilson@Airspan.com \
--cc=linuxppc-embedded@ozlabs.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).