您的位置:首页 > 其它

进程地址空间地址转换为物理地址

2011-08-08 20:31 225 查看
kernel代码

/*
* To test kernel's scheduler
* Date:2011/8/8 13:04
* ### wait queue ###
*/
#include <linux/init.h>
#include <linux/list.h>
#include <linux/module.h>
#include <linux/kmod.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/kthread.h>
#include <linux/sched.h>
#include <linux/wait.h>
#include <linux/kallsyms.h>
#include <linux/uaccess.h>
#include <linux/miscdevice.h>
#include <linux/fs.h>
#include <mach/hardware.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/page.h>
#include <asm/mman.h>
#include <asm/pgtable.h>
#include <asm/uaccess.h>
#include <asm/cacheflush.h>
#include <mach/bitfield.h>

//#define SYNC_DEBUG
/*
<1> no define SYNC_DEBUG
[ 2160.339202] [bloop, 68]i = 0
[ 2160.445648] [bloop, 68]i = 0
[ 2160.554992] [bloop, 68]i = 0
[ 2160.664337] [bloop, 68]i = 0
[ 2160.773712] [bloop, 68]i = 0
[ 2160.883087] [bloop, 68]i = 0
[ 2160.992462] [bloop, 68]i = 0
[ 2161.100952] [bloop, 68]i = 0
[ 2161.210357] [bloop, 68]i = 0
[ 2161.319702] [bloop, 68]i = 0
[ 2161.429962] [bloop, 68]i = 1
[ 2161.539337] [bloop, 68]i = 1
[ 2161.648773] [bloop, 68]i = 1

<2> define SYNC_DEBUG
[ 2160.339202] [bloop, 68]i = 0
[ 2161.648773] [bloop, 68]i = 1
[ 2161.648773] [bloop, 68]i = 2
*/

/*
### Get data from user space(not copy_from_user api) ###

# insmod /data/thread_test.ko
[ 7366.976959] [thread_init, 201]
#
#
#
#
# /data/vm_test[ 7385.550354] VM test open
[ 7385.553436] VM_TEST_GET_VADDR:  0x0007eb78

vaddress: 0x0007eb78 str: yugui.hu@gmail.com
[ 7385.557708] str:yugui.hu@gmail.com
[ 7385.565307] paddr: 0xc5f62b78
[ 7385.568267]
[ 7385.568267] =======Data========
[ 7385.572998] yugui.hu@gmail.com
[ 7385.576049] =======Data=======
q
Byte!!
*/
struct task_struct *kthreadA;
struct task_struct *kthreadB;
static int i = 0;

#ifdef SYNC_DEBUG
static wait_queue_head_t wait;
#endif

// IOCTL
#define VM_TEST_GET_VADDR 0
#define KSYM_NAME_LEN 128
#define KSYM_SYMBOL_LEN (sizeof("%s+%#lx/%#lx [%s]") + (KSYM_NAME_LEN - 1) + \
2*(BITS_PER_LONG*3/10) + (MODULE_NAME_LEN - 1) + 1)

/*
#define SCHED_NORMAL	0
#define SCHED_FIFO		1
#define SCHED_RR		2
#define SCHED_BATCH		3
#define SCHED_IDLE		5
*/

static int aloop(void *x)
{
struct sched_param param = { .sched_priority = 0 };
sched_setscheduler(current, SCHED_NORMAL, ¶m);

while (!kthread_should_stop()) {

msleep(1000);
i++;
#ifdef SYNC_DEBUG
wake_up_interruptible(&wait);
#endif
}
return 0;
}

static int bloop(void *x)
{
struct sched_param param = { .sched_priority = 2 };
sched_setscheduler(current, SCHED_FIFO, ¶m);

while (!kthread_should_stop()) {

#ifdef SYNC_DEBUG
interruptible_sleep_on(&wait);
#endif
printk("[%s, %d]i = %d\n", __func__, __LINE__, i);
msleep(100);
}
return 0;
}

static unsigned long uva_to_pa(struct mm_struct *mm, unsigned long addr)
{
unsigned long ret = 0UL;
pgd_t *pgd;
pud_t *pud;
pmd_t *pmd;
pte_t *pte;

pgd = pgd_offset(mm, addr);
if (!pgd_none(*pgd)) {
pud = pud_offset(pgd, addr);
if (!pud_none(*pud)) {
pmd = pmd_offset(pud, addr);
if (!pmd_none(*pmd)) {
pte = pte_offset_map(pmd, addr);
if (!pte_none(*pte) && pte_present(*pte)) {

/* Use hard PTE */
pte = (pte_t *)((u32)pte - 2048);
if(pte)
ret = (*pte & 0xfffff000) | (addr & 0xfff);
}
}
}
}
return ret;
}

static int
vm_test_open( struct inode * inode, struct file * file )
{
printk("VM test open\n");
return 0;
}

static int
vm_test_ioctl( struct inode * inode, struct file * file,
unsigned int cmd, unsigned long arg )
{
void __user *argp = (void __user *)arg;
unsigned long vaddr;
unsigned long paddr;
unsigned char str[20] = {0};
switch (cmd)
{
case VM_TEST_GET_VADDR:
printk("VM_TEST_GET_VADDR:  0x%08x\n", (unsigned long)argp);

/* output data from user space */
copy_from_user(str, argp, 18);   /* !!!删除这个函数后,uva_to_pa不能得到物理地址,还在研究中(缺页异常) */
printk("str:%s\n", str);

/* Get physical address */
struct mm_struct *mm = current->mm;
paddr = uva_to_pa(mm, vaddr);
if (paddr == 0)
printk("Can't find physical address!\n");
else
printk("paddr: 0x%08x\n", paddr);

printk("\n=======Data========\n");
unsigned long vpp = ioremap_nocache(paddr, 18);
int i = 0;
for (i = 0; i < 18; i++) {
printk("%c", *(volatile unsigned char *)(vpp + i));
}
printk("\n=======Data=======\n");

return 0;
default:
return -EINVAL;
}
}

static struct file_operations vm_test_fops = {
.owner    = THIS_MODULE,
.open	  = vm_test_open,
.ioctl	  = vm_test_ioctl,
};

static struct miscdevice vm_test_misc_device = {
.minor    = MISC_DYNAMIC_MINOR,
.name     = "VM-TEST",
.fops     = &vm_test_fops,
};

static int thread_init(void)
{
int err = 0;
printk("[%s, %d]\n", __func__, __LINE__);
#ifdef SYNC_DEBUG
init_waitqueue_head(&wait);
#endif
//kthreadA = kthread_run(aloop, NULL, "thread-A");
//kthreadB = kthread_run(bloop, NULL, "thread-B");

err = misc_register(&vm_test_misc_device);
if (err != 0)
printk("misc register device failed!\n");

return 0;
}

static void thread_exit(void)
{
#ifdef SYNC_DEBUG
wait_queue_t *curr, *next;
char str[KSYM_SYMBOL_LEN] = {0};
#endif
misc_deregister(&vm_test_misc_device);

printk("[%s, %d]\n", __func__, __LINE__);
//kthread_stop(kthreadA);
mdelay(200);

#ifdef SYNC_DEBUG
list_for_each_entry_safe(curr, next, &(wait.task_list), task_list) {
memset(str, 0 , KSYM_SYMBOL_LEN);
kallsyms_lookup((unsigned long)curr->private, NULL, NULL, NULL, str);
printk("waiting thread name: %s\n", str);
}
wake_up_interruptible(&wait);
#endif

//kthread_stop(kthreadB);
}

module_init(thread_init);
module_exit(thread_exit);
MODULE_LICENSE("GPL");


Makefile

# Makefile example
ARCH ?= arm
CROSS_COMPILE ?= arm-none-linux-gnueabi-
KERNELDIR ?= /KERNEL_OUT

ifneq ($(KERNELRELEASE),)

obj-m := thread_test.o

# Otherwise we were called directly from the command line; invoke the kernel build system.
else

default:
$(MAKE) -C $(KERNELDIR) M=$(PWD) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) modules
endif


user space代码

/*
* file  : vm_test.c
*
* How to use it:
* ./vm_test
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/fcntl.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/time.h>
#include <string.h>

#define DEVICE "/dev/VM-TEST"
#define VM_TEST_GET_VADDR 0
char str[20]= "yugui.hu@gmail.com";
int main(int argc, char *argv[])
{
int fd = 0;
char chr = 0;
fd = open(DEVICE, O_RDWR);
if (fd < 0) {
printf("Can't open the %s\n", DEVICE);
return -1;
}

printf("vaddress: 0x%08x str: %s\n", (unsigned long)str, str);
ioctl(fd, VM_TEST_GET_VADDR, str);
while (1) {
chr = getchar();
if (chr == 'q') {
printf("Byte!!\n");
return 0;
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: