内核dma保护怎么开启
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了内核dma保护怎么开启相关的知识,希望对你有一定的参考价值。
参考技术A如果内核 DMA 保护 的当前状态为 OFF,Hyper-V - 固件中 启用 虚拟化的状态为 NO:
- 重新启动到 Bios 设置打开 Intel 虚拟化技术。打开适用于 I/O 和 VT-d (Intel 虚拟化) 。 在 Windows 10 版本 1803 中,仅支持 Intel VT-d。 将系统重新启动到 Windows 10。
DMA驱动框架
框架入口源文件:dma.c
(可根据入口源文件,再按着框架到内核走一遍)
内核版本:linux_2.6.22.6 硬件平台:JZ2440
以下是驱动框架:
以下是驱动代码 dma.c :
#include <linux/module.h> #include <linux/kernel.h> #include <linux/fs.h> #include <linux/init.h> #include <linux/delay.h> #include <linux/irq.h> #include <asm/uaccess.h> #include <asm/irq.h> #include <asm/io.h> #include <asm/arch/regs-gpio.h> #include <asm/hardware.h> #include <linux/poll.h> #include <linux/dma-mapping.h> //源地址 static unsigned char *src; static unsigned int src_phy; //目的地址 static unsigned char* dest; static unsigned int dest_phy; //空间大小 #define DMA_SIZE (1204*512) //驱动类 static struct class *dma_class; //主设备号 static int major ; #define USE_DMA 1 #define NO_DMA 0 //DMA寄存器 static struct s3c_dma_reg { unsigned long disrc; unsigned long disrcc; unsigned long didst; unsigned long didstc; unsigned long dcon; unsigned long dstat; unsigned long dcsrc; unsigned long dcdst; unsigned long dmaskting; }*s3c_dma_regs; //DMA地址 static unsigned long dma_addr0 = 0x4b000000; static unsigned long dma_addr1 = 0x4b000040; static unsigned long dma_addr2 = 0x4b000080; static unsigned long dma_addr3 = 0x4b0000c0; //为这个进程创建等待队列 static DECLARE_WAIT_QUEUE_HEAD(dma_wait_queue); //进程队列标志位 static volatile int dma_wait_queue_condition=0; static int s3c_dma_iotcl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long args) { int i=0; memset(src, 0xAA, DMA_SIZE); memset(dest, 0x55, DMA_SIZE); switch(cmd) { case NO_DMA : { for(i=0;i<DMA_SIZE;i++) dest[i] = src[i]; if(memcmp(src,dest,DMA_SIZE) == 0) printk("copy without DMA successfuly ! "); else printk("copy without DMA fialed ! "); break; } case USE_DMA : { // 设置DMA寄存器 s3c_dma_regs->disrc = src_phy; s3c_dma_regs->disrcc = (0<<0)|(0<<0); s3c_dma_regs->didst = dest_phy; s3c_dma_regs->didstc =(0<<3)|(0<<1)|(0<<0); s3c_dma_regs->dcon = (1<<30)|(1<<29)|(0<<28)|(1<<27)|(0<<23)|(0<<20)|(DMA_SIZE<<0); s3c_dma_regs->dmaskting = (1<<1)|(1<<0); //休眠进程 dma_wait_queue_condition = 0; //状态标志位为假 休眠dma.c进程 。 进程可被信号中断休眠,返回非0值表示休眠被信号中断 wait_event_interruptible(dma_wait_queue, dma_wait_queue_condition); if(memcmp(src,dest,DMA_SIZE) == 0) printk(" copy with DMA successfuly ! "); else printk("copy with DMA failed ! "); break; } } return 0; } //字符设备操作函数 static struct file_operations dma_fops = { .owner = THIS_MODULE, .ioctl = s3c_dma_iotcl, }; //中断处理函数 static int s3c_dma_irq(int irq, void *devid) { dma_wait_queue_condition = 1; //状态为真 唤醒dma.c进程 wake_up_interruptible(&dma_wait_queue); return IRQ_HANDLED; } static int dma_init(void) { //申请中断 request_irq(IRQ_DMA3, s3c_dma_irq,0, "s3c_dma", 1); //申请源地址空间 src = dma_alloc_writecombine(NULL,DMA_SIZE, &src_phy,GFP_KERNEL); //申请目的地址空间 dest= dma_alloc_writecombine(NULL,DMA_SIZE, &dest_phy,GFP_KERNEL); //dma_reg映射 s3c_dma_regs = ioremap(dma_addr3,sizeof(struct s3c_dma_reg)); //注册字符设备 major = register_chrdev(0, "s3c_dma",&dma_fops); //注册类 设备节点 dma_class = class_create(THIS_MODULE,"s3c_dma_class"); // /sys/class/s3c_dma_class class_device_create(dma_class,NULL,MKDEV(major,0),NULL, "s3c_dma"); // /dev/s3c_dma return 0; } static void dma_exit(void) { free_irq(IRQ_DMA3,1); dma_free_writecombine(NULL,DMA_SIZE, src,GFP_KERNEL); dma_free_writecombine(NULL,DMA_SIZE, dest,GFP_KERNEL); iounmap(s3c_dma_regs); unregister_chrdev(major, "s3c_dma"); class_destroy(dma_class); class_device_destroy( dma_class,MKDEV(major,0)); } module_init(dma_init); module_exit(dma_exit); MODULE_LICENSE("GPL");
以下是驱动测试文件:
#include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <sys/ioctl.h> #include <string.h> #define USE_DMA 1 #define NO_DMA 0 int main(int argc ,char **argv) { int fd=0; fd = open("/dev/s3c_dma", O_RDWR); if(fd<0) printf("can‘t open "); if(argc !=2) printf("please using like this : ./dma_test <dma|no_dma> "); if(argc ==2) { if(strcmp(argv[1],"dma")==0) while(1) ioctl(fd,USE_DMA); if(strcmp(argv[1],"no_dma")==0)while(1) ioctl(fd,NO_DMA); } return 0; }
以下是编译驱动的Makefile:
KERN_DIR = /work/systems/kernel/linux-2/linux-2.6.22.6 all: make -C $(KERN_DIR) M=`pwd` modules clean: make -C $(KERN_DIR) M=`pwd` modules clean rm -rf modules.order obj-m +=dma.o
以上是关于内核dma保护怎么开启的主要内容,如果未能解决你的问题,请参考以下文章
Linux 内核 内存管理优化内存屏障 ③ ( 编译器屏障 | 禁止 / 开启内核抢占 与 方法保护临界区 | preempt_disable 禁止内核抢占源码 | 开启内核抢占源码 )