2008年12月27日

[Linux] Process ID (PID) から CR3 値を得る自作システムコール

カーネル空間内で,プロセスIDからそのプロセスのページディレクトリの物理アドレスを得るシステムコールを作った.

arch/x86/kernel/pid2cr3.c (システムコール本体)

#include <linux/pid2cr3.h>
#include <linux/sched.h>
#include <linux/pid.h>

asmlinkage unsigned long sys_pid2cr3(int pid) {
  struct task_struct *p;
  p = pid_task(find_vpid(pid), PIDTYPE_PID);
  if (p && (p->active_mm != NULL))
    return __pa((unsigned long) (p->active_mm->pgd));
  else
    return 1;
}

/usr/include/linux/pid2cr3.h

#ifndef NR_PID2CR3_H
#define NR_PID2CR3_H

#include <linux/unistd.h>
#include <sys/syscall.h>

#define pid2cr3(pid) syscall(__NR_pid2cr3, pid)

#endif

include/linux/pid2cr3.h

#ifndef NR_PID2CR3_H
#define NR_PID2CR3_H

#include <linux/unistd.h>
#include <linux/linkage.h>

#define pid2cr3(pid) syscall(__NR_pid2cr3, pid)

#endif

あとは適当に.

おまけ Pythonから上記システムコールを使うためのモジュール

#include <Python.h>
#include <linux/pid2cr3.h>

static PyObject * get_cr3(PyObject *self, PyObject *args) {
	int ok, pid;
	ok = PyArg_ParseTuple(args, "i", &pid);
	return PyLong_FromUnsignedLong(pid2cr3(pid));
}

// module method tbl init
static PyMethodDef SpamMethods[] = {
  { "pid2cr3", get_cr3, METH_VARARGS, "get CR3 value from PID" },
  {NULL, NULL, 0, NULL},
};

PyMODINIT_FUNC initpid2cr3(void) {
  PyObject *m;
  m = Py_InitModule("pid2cr3", SpamMethods);
}
posted by dev-man at 19:51| Comment(0) | TrackBack(0) | Linux | このブログの読者になる | 更新情報をチェックする

2008年12月16日

[Linux] メモリに物理アドレスでアクセスする

カーネルをいじっていて,物理アドレスでメモリにアクセスする必要がでた.

かなり強引技だけど,仮想メモリのアドレスをそのまま物理メモリアドレス変換するページテーブルを作成してみた.
# もっとスマートなやりかたないですかねー...?
#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;
	}
}

posted by dev-man at 15:36| Comment(0) | TrackBack(0) | Linux | このブログの読者になる | 更新情報をチェックする

2008年05月18日

[Linux] CtrlキーとCapsLockキーを入れ替える

~/.xmodmaprc を以下のように作成

remove Lock = Caps_Lock
keysym Caps_Lock = Control_L
add Control = Control_L

~/.xinitrc に以下の行を追加

xmodmap ~/.xmodmaprc &
posted by dev-man at 01:05| Comment(0) | TrackBack(0) | Linux | このブログの読者になる | 更新情報をチェックする