/****************************************************************************************** ** Project : Atlantis for Linux ** Filename : MsrAccDrv.c ** Creator : ** Date : Apr 22, 2014 ** ** Copyright 2011 NetApp Corporation. All Rights Reserved ** ** Description: ** Provide a driver interface for msr operations ** **********************************************************************************************/ #ifndef MSRACC_MODULE_C #define MSRACC_MODULE_C #include #include #include #include #include #include #include #include #include "MsrAccDrv.h" static int msracc_major; static struct class *msracc_module_class; int msr_access_open (struct inode *inod, struct file *filp) { int major, minor; major = imajor(inod); minor = iminor(inod); try_module_get(THIS_MODULE); return 0; } int msr_access_release(struct inode *inod, struct file *filp) { module_put(THIS_MODULE); return 0; } int read_msr(void *arg) { int ret = -EINVAL; struct msracc_drv_cmd *msracc_drvcmd; struct msracc_drv_cmd kerdrvcmd; msracc_drvcmd = (struct msracc_drv_cmd *)arg; ret = copy_from_user(&kerdrvcmd, msracc_drvcmd, sizeof(struct msracc_drv_cmd)); if(ret) { printk("read_msr: Copy from user space error!\n"); return ret; } rdmsr_safe_on_cpu(kerdrvcmd.cpu_id, kerdrvcmd.msr_offset, &kerdrvcmd.val_low, &kerdrvcmd.val_high); ret = copy_to_user(msracc_drvcmd, &kerdrvcmd, sizeof(struct msracc_drv_cmd)); if(ret) { printk("read_msr: Copy to user space error!\n"); } return ret; } int write_msr(void *arg) { int ret = -EINVAL; struct msracc_drv_cmd *msracc_drvcmd; struct msracc_drv_cmd kerdrvcmd; msracc_drvcmd = (struct msracc_drv_cmd *)arg; ret = copy_from_user(&kerdrvcmd, msracc_drvcmd, sizeof(struct msracc_drv_cmd)); if(ret) { printk("write_msr: Copy from user space error!\n"); return ret; } wrmsr_safe_on_cpu(kerdrvcmd.cpu_id, kerdrvcmd.msr_offset, (u32)kerdrvcmd.val_low, (u32)kerdrvcmd.val_high); return 0; } /** Function Name : msr_access_ioctl() ** Parameter : cmd: ioctl command; ** arg: user space parameter pointer; ** Return : ** Function : the ioctl() syscall implementation **/ //int pci_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) long msr_access_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { long ret = 0; if ((_IOC_TYPE(cmd) & MSRACC_MAGIC_NUMBER) != MSRACC_MAGIC_NUMBER) { return -EINVAL; } switch (_IOC_NR(cmd)) { case READ_MSR_IOCTL: ret = read_msr((void *)arg); break; case WRITE_MSR_IOCTL: ret = write_msr((void *)arg); break; default: return -ENOTTY; } return ret; } struct file_operations msr_access_fops = { owner: THIS_MODULE, unlocked_ioctl: msr_access_ioctl, open : msr_access_open, release : msr_access_release, }; int msr_access_init_module(void) { int ret_num = 0; msracc_major = 0; ret_num = register_chrdev(MSRACC_DYNAMIC_MAJOR, MSRACC_DEVICE_NAME, &msr_access_fops); msracc_major = ret_num; if (ret_num < 0) { printk(KERN_ERR "MSRACCESS MODULE: Can not get major device Number !\n"); return ret_num; } if (ret_num >= 0) { msracc_module_class = class_create(THIS_MODULE, MSRACC_DEVICE_NAME); device_create(msracc_module_class, NULL, MKDEV(msracc_major, 0), NULL, "%s", MSRACC_DEVICE_NAME); printk(KERN_INFO "MSRACCESS module have been loaded successfully (MAJOR_NUM=%d)!\n", ret_num); } return 0; } void msr_access_cleanup_module(void) { unregister_chrdev(msracc_major, MSRACC_DEVICE_NAME); device_destroy(msracc_module_class, MKDEV(msracc_major, 0)); class_destroy(msracc_module_class); } module_init(msr_access_init_module); module_exit(msr_access_cleanup_module); /* MODULE LICENSE DEFINE */ MODULE_LICENSE("GPL"); #endif /* MSRACC_MODULE_C */