Thread (12 messages) 12 messages, 5 authors, 2011-06-22

Re: Mapping an executable page

From: Thomas De Schampheleire <hidden>
Date: 2011-06-14 08:56:35

Hi,

On Sun, May 29, 2011 at 4:53 PM, Tabi Timur-B04825 [off-list ref] w=
rote:
On Fri, May 27, 2011 at 8:25 AM, Thomas De Schampheleire
[off-list ref] wrote:
quoted
Although I realize that what I need to achieve is unconventional, what
is the correct way of mapping a certain address range into memory, and
be able to execute from it?
Have you tried looking at the actual TLB entry for this page to see if
it's correct? =A0Also, you might need to do some kind of instruction
cache flushing before you jump to that page.
Sorry to have delayed this so long.
I had to do quite some experimentation to get it finally working. Here
are my findings:
* to map a page as executable, the following does indeed work:
void __iomem *vaddr =3D __ioremap(map_start, map_size, (_PAGE_BASE |
_PAGE_KERNEL_RWX));

* However, if you jump to an address in that page, you'll have to make
sure that the entire code that executes is mapped (make map_size large
enough).

* When that range spanned multiple pages, I faced the issue of only
one page being actually mapped in the TLBs. My assumption is that the
call to __ioremap not necessarily updates the TLBs, but mainly some
kernel-internal tables. The actual TLB mapping presumably happens when
a data exception occurs.
Unfortunately, since I left the Linux kernel and jumped to other
(boot) code that reassigns the exception vectors, the kernel-internal
tables are not used anymore, and the exception handler cannot update
the TLBs correctly.

* Therefore, to make sure that the mapping I intended with __ioremap()
is actually reflected in the TLB tables, I added dummy reads of each
page in the TLB, prior to jumping to the boot code, as follows:
                /* make sure memory is read, once every 4Kbyte is enough */
                for (p =3D vaddr; p < vaddr + map_size; p +=3D 0x1000) {
                        unsigned long dummy =3D *(volatile unsigned long *)=
p;
                        (void)dummy;
                }

* After these changes (make sure all code is mapped + make sure to
read all pages so that the TLBs are updated), my scenario works fine.

Best regards,
Thomas
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help