* What else need to be done if we allocate phys page manually?
@ 2012-09-11 11:09 陳韋任 (Wei-Ren Chen)
0 siblings, 0 replies; only message in thread
From: 陳韋任 (Wei-Ren Chen) @ 2012-09-11 11:09 UTC (permalink / raw)
To: linux-mm
[-- Attachment #1: Type: text/plain, Size: 2261 bytes --]
Hi all,
Please let me explain what I am trying to do first. First, I compile
a 64 bit binary so that it'll be loaded above 4G virtual space, so the
virtual space below 4G is empty. I want to make a virtual address below
4G share the same phys page with another virtual address above 4G, so
that read/write vadd1 just like vaddr2.
PGD/PUD/PMD Page Table
---------- Phys Page 2
| | --------
|----------| | |
vaddr2 | pte 2 | ---------> | |
|----------| | |
| | --------
| | ^
4G above | | |
--------------------------------------------- |
| | |
| | |
|----------| |
vaddr1 | pte 1 | ---------------
|----------|
| |
|__________|
Currently, I choose to manually create PUD/PMD/PT associated with vaddr1
, and set pte1 to point to phys page 2 (you can see the attach example
syscall, vadd1 is fixed to 0x10000000 for simplicity). However, the page
I create for PMD in the example will cause memory leak (see below). What
is the proper way to do so that kernel can free the page I allocated
automatically when the application calling the syscall is terminated?
pmd = pmd_offset(pud, vaddr);
if(pmd_none(*pmd)) {
page = pte_alloc_one(current->mm, vaddr);
pmd_n = mk_pmd(page, pgprot);
set_pmd(pmd, pmd_n);
}
Thanks!
Regards,
chenwj
--
Wei-Ren Chen (陳韋任)
Computer Systems Lab, Institute of Information Science,
Academia Sinica, Taiwan (R.O.C.)
Tel:886-2-2788-3799 #1667
Homepage: http://people.cs.nctu.edu.tw/~chenwj
[-- Attachment #2: syscall.c --]
[-- Type: text/x-csrc, Size: 1865 bytes --]
#include <linux/mm.h>
#include <linux/mm_types.h>
#include <linux/sched.h>
#include <asm/pgalloc.h>
#include <asm/tlbflush.h>
// vaddr_h: vaddr above 4G
long sys_set_pte(unsigned long vaddr_h)
{
unsigned long vaddr = 0x10000000 | (vaddr_h & 0xfff); // make vaddr's pte point to vaddr_h's phys page
// vaddr and vaddr_h shares the same pgd and pud, need to creat pmd and page table
pgd_t *pgd;
pud_t *pud;
pmd_t *pmd, pmd_n; // pmd_n is for vaddr
pte_t *pte, *pte_h;
struct page *page;
pgprot_t pgprot;
// get vaddr_h's physical page
pgd = pgd_offset(current->mm, vaddr_h);
pud = pud_offset(pgd, vaddr_h);
pmd = pmd_offset(pud, vaddr_h);
pgprot = __pgprot(pmd_val(*pmd) & 0xfff); // we copy vaddr_h's pmd permission to vaddr's pmd
pte_h = pte_offset_map(pmd, vaddr_h);
// mapping vaddr_h above 4G to vaddr below 4G alloc page entry
pgd = pgd_offset(current->mm, vaddr);
if (pgd_none(*pgd)) {
printk("pgd entry not found, alloc new pud and set pgd entry\n");
pgd = pgd_alloc(current->mm);
}
pud = pud_offset(pgd, vaddr);
if(pud_none(*pud)) {
printk("pud entry not found, alloc new pmd and set pud entry\n");
pud = pud_alloc(current->mm, pgd, vaddr);
}
pmd = pmd_offset(pud, vaddr);
if(pmd_none(*pmd)) {
printk("pmd entry not found, alloc new pte and set pmd entry\n");
page = pte_alloc_one(current->mm, vaddr); // allocate pte, i.e., page table
pmd_n = mk_pmd(page, pgprot); // make a new pmd entry which ponits to page with pgprot permission
set_pmd(pmd, pmd_n); // replace old pmd entry (pmd) with a new one (pmd_n)
}
// pte = page table entry
pte = pte_offset_map(pmd, vaddr);
// replace vaddr page table entry (pte) with vaddr_h's one (*pte_h)
set_pte(pte, *pte_h);
}
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2012-09-11 11:10 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-09-11 11:09 What else need to be done if we allocate phys page manually? 陳韋任 (Wei-Ren Chen)
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox