Discussion:
Physical memory mapping with nopage handler
Clive Levinson
2004-08-30 16:36:33 UTC
Permalink
Hi,
I have been stuck for a few days trying to map physical memory
in my framebuffer driver using the nopage handler on a strongArm
running V2.4.18.

The hardware is physically at address 0x2C000000, iotable_init()
maps it to 0XF1000000.

Within my driver, writing directly to 0XF1000000 will set pixels
on the screen. However for, a user application that calls mmap
to map the framebuffer, I use the following in my mmap handler::
io_remap_page_range(vma->vm_start, 0x2c000000,
vma->vm_end - vma->vm_start,
vma->vm_page_prot)
This is remapping to the actual physical address, and seems
to work correctly. The user level application then is able to write
to the framebuffer return by mmap and have it appear on screen.

My first point of confusion, is what is the relationship between
the physical address at 0x2C000000, and the 0XF1000000 ?

However, the real problem is that my hardware has banked memory,
mapping in the mmap, I can only write to the first 64K of the
framebuffer. I decided to get around this by using a nopage handler,
so that I can handle the bank switching.

This is basically what I have:

static struct vm_operations_struct myfb_vm_ops = {
nopage: myfb_nopage,
};

static int myfb_mmap(struct fb_info *info,
struct file *file,
struct vm_area_struct *vma)
{
vma->vm_flags = vma->vm_flags|VM_IO|VM_RESERVED;
vma->vm_ops = &myfb_vm_ops;
return 0;
}

static struct page * myfb_nopage(struct vm_area_struct * vma,
unsigned long address,
int unused)
{

pte_t pte;

//ignore the address offset at this point, assume it is the
//same as vma->vm_start

//pte=mk_pte_phys( 0x2c000000, PAGE_SHARED); //Generates an error
pte=mk_pte_phys( 0xf1000000, PAGE_SHARED); //No error
pageptr=pte_page( pte );
get_page( pageptr );
return pageptr;
}

If I use mk_pte_phys( 0x2c000000, PAGE_SHARED), I get an internal
error. If use pte=mk_pte_phys( 0xf1000000, PAGE_SHARED), it
satisfies the page request, however, the write is not happening to the
actual framebuffer, I am not sure where it is going.
Any suggestions or tips please?

Thanks,
Clive


-------------------------------------------------------------------
Subscription options: http://lists.arm.linux.org.uk/mailman/listinfo/linux-arm-kernel
FAQ: http://www.arm.linux.org.uk/armlinux/mlfaq.php
Etiquette: http://www.arm.linux.org.uk/armlinux/mletiquette.php
Russell King - ARM Linux
2004-08-30 16:56:43 UTC
Permalink
Post by Clive Levinson
static struct page * myfb_nopage(struct vm_area_struct * vma,
unsigned long address,
int unused)
{
pte_t pte;
//ignore the address offset at this point, assume it is the
//same as vma->vm_start
//pte=mk_pte_phys( 0x2c000000, PAGE_SHARED); //Generates an error
pte=mk_pte_phys( 0xf1000000, PAGE_SHARED); //No error
pageptr=pte_page( pte );
get_page( pageptr );
return pageptr;
}
If I use mk_pte_phys( 0x2c000000, PAGE_SHARED), I get an internal
error. If use pte=mk_pte_phys( 0xf1000000, PAGE_SHARED), it
satisfies the page request, however, the write is not happening to the
actual framebuffer, I am not sure where it is going.
Any suggestions or tips please?
I have a suggestion for a question to ask yourself about the above
code: "Is there a system RAM page (ie SDRAM page) associated with
the address you're mapping?" If the answer to that is no, you may
not convert a PTE to a struct page pointer. struct page's only
exist for system RAM.

That also rules out using nopage here, sorry.

-------------------------------------------------------------------
Subscription options: http://lists.arm.linux.org.uk/mailman/listinfo/linux-arm-kernel
FAQ: http://www.arm.linux.org.uk/armlinux/mlfaq.php
Etiquette: http://www.arm.linux.org.uk/armlinux/mletiquette.php
Clive Levinson
2004-08-31 07:06:45 UTC
Permalink
Post by Russell King - ARM Linux
Post by Clive Levinson
static struct page * myfb_nopage(struct vm_area_struct * vma,
unsigned long address,
int unused)
{
pte_t pte;
//ignore the address offset at this point, assume it is the
//same as vma->vm_start
//pte=mk_pte_phys( 0x2c000000, PAGE_SHARED); //Generates an error
pte=mk_pte_phys( 0xf1000000, PAGE_SHARED); //No error
pageptr=pte_page( pte );
get_page( pageptr );
return pageptr;
}
If I use mk_pte_phys( 0x2c000000, PAGE_SHARED), I get an internal
error. If use pte=mk_pte_phys( 0xf1000000, PAGE_SHARED), it
satisfies the page request, however, the write is not happening to the
actual framebuffer, I am not sure where it is going.
Any suggestions or tips please?
I have a suggestion for a question to ask yourself about the above
code: "Is there a system RAM page (ie SDRAM page) associated with
the address you're mapping?" If the answer to that is no, you may
not convert a PTE to a struct page pointer. struct page's only
exist for system RAM.
That also rules out using nopage here, sorry.
Hi Russell,
Thanks for the reply, forgive me for being a bit stupid, but this is my first
foray into the Linux kernel. My background is embedded development
generally on smaller processors with no OS.
I am not sure what you mean by a "system RAM page", I have real
physical RAM (albeit on the video controller), at address 0x2C000000,
this is mapped by iotable_init() to 0xF1000000.
Thanks,
Clive




-------------------------------------------------------------------
Subscription options: http://lists.arm.linux.org.uk/mailman/listinfo/linux-arm-kernel
FAQ: http://www.arm.linux.org.uk/armlinux/mlfaq.php
Etiquette: http://www.arm.linux.org.uk/armlinux/mletiquette.php
Russell King - ARM Linux
2004-09-03 18:45:38 UTC
Permalink
Post by Clive Levinson
Thanks for the reply, forgive me for being a bit stupid, but this is my first
foray into the Linux kernel. My background is embedded development
generally on smaller processors with no OS.
I am not sure what you mean by a "system RAM page", I have real
physical RAM (albeit on the video controller), at address 0x2C000000,
this is mapped by iotable_init() to 0xF1000000.
I meant the RAM which the kernel has been told to use, iow, the SDRAM.

-------------------------------------------------------------------
Subscription options: http://lists.arm.linux.org.uk/mailman/listinfo/linux-arm-kernel
FAQ: http://www.arm.linux.org.uk/armlinux/mlfaq.php
Etiquette: http://www.arm.linux.org.uk/armlinux/mletiquette.php

Loading...