かなり強引技だけど,仮想メモリのアドレスをそのまま物理メモリアドレス変換するページテーブルを作成してみた.
# もっとスマートなやりかたないですかねー...?
#include <linux/module.h>
#include <linux/init.h>
#include <asm/page.h>
#include <linux/pagemap.h>
// 物理メモリにアクセスするためのページテーブル
void *linear_pagedir = NULL;
/*
* 物理メモリにアクセスするためのページテーブルを作成
* (最初に1回これを呼ぶ)
*/
void
linear_pagedir_init(void) {
struct page *pagedir_page;
ulong pde_template, pde;
int i;
ulong *pd;
pagedir_page = alloc_page(GFP_ATOMIC | __GFP_ZERO);
linear_pagedir = page_address(pagedir_page);
pd = (ulong *) linear_pagedir;
pde_template = (1 << 7) + (1 << 1) + (1 << 0);
for (i = 0; i < 1024; i++) {
pde = pde_template | (i << 22);
pd[i] = pde;
}
}
/*
* 物理メモリを1ワード読む
* phys_addr: 読みたい物理アドレス
* val: 読み出す変数
*
* 事前にlinear_pagedir_init()を呼んでおく必要あり.
*/
asmlinkage void
read_phys_mem (ulong phys_addr, ulong *val) {
ulong tmpcr3 = (ulong) __pa(linear_pagedir);
asm volatile (
"mov %%cr3, %%eax\n\t"
"mov %1, %%cr3\n\t"
"mov (%2), %%ebx\n\t"
"mov %%eax, %%cr3\n\t"
"mov %%ebx, %0"
: "=r" (*val)
: "r" (tmpcr3), "r" (phys_addr)
: "%eax", "%ebx", "cc"
);
}
/**
* 物理メモリにアクセスするためのページテーブルを開放
* (最後に1回これを呼ぶ)
*/
void
linear_pagedir_free(void) {
if (linear_pagedir == NULL) {
// no need to free
} else {
free_page((ulong)linear_pagedir);
linear_pagedir = NULL;
}
}

