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

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;	
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值