⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 microcode.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 2 页
字号:
				mark_microcode_update(cpu_num, &mc_header, mc_header.sig, mc_header.pf, mc_header.cksum);		}		ext_table_size = total_size - (MC_HEADER_SIZE + data_size);		if (ext_table_size) {			struct extended_sigtable ext_header;			struct extended_signature ext_sig;			int ext_sigcount;			if ((ext_table_size < EXT_HEADER_SIZE) 					|| ((ext_table_size - EXT_HEADER_SIZE) % EXT_SIGNATURE_SIZE)) {				printk(KERN_ERR "microcode: error! Bad data in microcode data file\n");				error = -EINVAL;				goto out;			}			if (copy_from_user(&ext_header, user_buffer + cursor 					+ MC_HEADER_SIZE + data_size, EXT_HEADER_SIZE)) {				printk(KERN_ERR "microcode: error! Can not read user data\n");				error = -EFAULT;				goto out;			}			if (ext_table_size != exttable_size(&ext_header)) {				printk(KERN_ERR "microcode: error! Bad data in microcode data file\n");				error = -EFAULT;				goto out;			}			ext_sigcount = ext_header.count;						for (i = 0; i < ext_sigcount; i++) {				if (copy_from_user(&ext_sig, user_buffer + cursor + MC_HEADER_SIZE + data_size + EXT_HEADER_SIZE 						+ EXT_SIGNATURE_SIZE * i, EXT_SIGNATURE_SIZE)) {					printk(KERN_ERR "microcode: error! Can not read user data\n");					error = -EFAULT;					goto out;				}				for (cpu_num = 0; cpu_num < num_online_cpus(); cpu_num++) {					struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num;					if (uci->err != MC_NOTFOUND) /* already found a match or not an online cpu*/						continue;					if (sigmatch(ext_sig.sig, uci->sig, ext_sig.pf, uci->pf)) {						mark_microcode_update(cpu_num, &mc_header, ext_sig.sig, ext_sig.pf, ext_sig.cksum);					}				}			}		}		/* now check if any cpu has matched */		for (cpu_num = 0, allocated_flag = 0, sum = 0; cpu_num < num_online_cpus(); cpu_num++) {			if (ucode_cpu_info[cpu_num].err == MC_MARKED) { 				struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num;				if (!allocated_flag) {					allocated_flag = 1;					newmc = vmalloc(total_size);					if (!newmc) {						printk(KERN_ERR "microcode: error! Can not allocate memory\n");						error = -ENOMEM;						goto out;					}					if (copy_from_user(newmc + MC_HEADER_SIZE, 								user_buffer + cursor + MC_HEADER_SIZE, 								total_size - MC_HEADER_SIZE)) {						printk(KERN_ERR "microcode: error! Can not read user data\n");						vfree(newmc);						error = -EFAULT;						goto out;					}					memcpy(newmc, &mc_header, MC_HEADER_SIZE);					/* check extended table checksum */					if (ext_table_size) {						int ext_table_sum = 0;						int * ext_tablep = (((void *) newmc) + MC_HEADER_SIZE + data_size);						i = ext_table_size / DWSIZE;						while (i--) ext_table_sum += ext_tablep[i];						if (ext_table_sum) {							printk(KERN_WARNING "microcode: aborting, bad extended signature table checksum\n");							vfree(newmc);							error = -EINVAL;							goto out;						}					}					/* calculate the checksum */					i = (MC_HEADER_SIZE + data_size) / DWSIZE;					while (i--) sum += ((int *)newmc)[i];					sum -= (mc_header.sig + mc_header.pf + mc_header.cksum);				}				ucode_cpu_info[cpu_num].mc = newmc;				ucode_cpu_info[cpu_num].err = MC_ALLOCATED; /* mc updated */				if (sum + uci->sig + uci->pf + uci->cksum != 0) {					printk(KERN_ERR "microcode: CPU%d aborting, bad checksum\n", cpu_num);					error = -EINVAL;					goto out;				}			}		}		cursor += total_size; /* goto the next update patch */	} /* end of while */out:	return error;}static void do_update_one (void * unused){	unsigned long flags;	unsigned int val[2];	int cpu_num = smp_processor_id();	struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num;	if (uci->mc == NULL) {		printk(KERN_INFO "microcode: No new microcode data for CPU%d\n", cpu_num);		return;	}	/* serialize access to the physical write to MSR 0x79 */	spin_lock_irqsave(&microcode_update_lock, flags);          	/* write microcode via MSR 0x79 */	wrmsr(MSR_IA32_UCODE_WRITE,		(unsigned long) uci->mc->bits, 		(unsigned long) uci->mc->bits >> 16 >> 16);	wrmsr(MSR_IA32_UCODE_REV, 0, 0);	/* see notes above for revision 1.07.  Apparent chip bug */	serialize_cpu();	/* get the current revision from MSR 0x8B */	rdmsr(MSR_IA32_UCODE_REV, val[0], val[1]);	/* notify the caller of success on this cpu */	uci->err = MC_SUCCESS;	spin_unlock_irqrestore(&microcode_update_lock, flags);	printk(KERN_INFO "microcode: CPU%d updated from revision "	       "0x%x to 0x%x, date = %08x \n", 	       cpu_num, uci->rev, val[1], uci->mc->hdr.date);	return;}static int do_microcode_update (void){	int i, error;	if (on_each_cpu(collect_cpu_info, NULL, 1, 1) != 0) {		printk(KERN_ERR "microcode: Error! Could not run on all processors\n");		error = -EIO;		goto out;	}	if ((error = find_matching_ucodes())) {		printk(KERN_ERR "microcode: Error in the microcode data\n");		goto out_free;	}	if (on_each_cpu(do_update_one, NULL, 1, 1) != 0) {		printk(KERN_ERR "microcode: Error! Could not run on all processors\n");		error = -EIO;	}out_free:	for (i = 0; i < num_online_cpus(); i++) {		if (ucode_cpu_info[i].mc) {			int j;			void *tmp = ucode_cpu_info[i].mc;			vfree(tmp);			for (j = i; j < num_online_cpus(); j++) {				if (ucode_cpu_info[j].mc == tmp)					ucode_cpu_info[j].mc = NULL;			}		}	}out:	return error;}static ssize_t microcode_write (struct file *file, const char __user *buf, size_t len, loff_t *ppos){	ssize_t ret;	if (len < DEFAULT_UCODE_TOTALSIZE) {		printk(KERN_ERR "microcode: not enough data\n"); 		return -EINVAL;	}	if ((len >> PAGE_SHIFT) > num_physpages) {		printk(KERN_ERR "microcode: too much data (max %ld pages)\n", num_physpages);		return -EINVAL;	}	down(&microcode_sem);	user_buffer = (void __user *) buf;	user_buffer_size = (int) len;	ret = do_microcode_update();	if (!ret)		ret = (ssize_t)len;	up(&microcode_sem);	return ret;}static int microcode_ioctl (struct inode *inode, struct file *file, 		unsigned int cmd, unsigned long arg){	switch (cmd) {		/* 		 *  XXX: will be removed after microcode_ctl 		 *  is updated to ignore failure of this ioctl()		 */		case MICROCODE_IOCFREE:			return 0;		default:			return -EINVAL;	}	return -EINVAL;}static struct file_operations microcode_fops = {	.owner		= THIS_MODULE,	.write		= microcode_write,	.ioctl		= microcode_ioctl,	.open		= microcode_open,};static struct miscdevice microcode_dev = {	.minor		= MICROCODE_MINOR,	.name		= "microcode",	.devfs_name	= "cpu/microcode",	.fops		= &microcode_fops,};static int __init microcode_init (void){	int error;	error = misc_register(&microcode_dev);	if (error) {		printk(KERN_ERR			"microcode: can't misc_register on minor=%d\n",			MICROCODE_MINOR);		return error;	}	printk(KERN_INFO 		"IA-32 Microcode Update Driver: v" MICROCODE_VERSION " <tigran@veritas.com>\n");	return 0;}static void __exit microcode_exit (void){	misc_deregister(&microcode_dev);	printk(KERN_INFO "IA-32 Microcode Update Driver v" MICROCODE_VERSION " unregistered\n");}module_init(microcode_init)module_exit(microcode_exit)MODULE_ALIAS_MISCDEV(MICROCODE_MINOR);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -