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

📄 p4-clockmod.c

📁 这个linux源代码是很全面的~基本完整了~使用c编译的~由于时间问题我没有亲自测试~但就算用来做参考资料也是非常好的
💻 C
字号:
/* *	Pentium 4/Xeon CPU on demand clock modulation/speed scaling *	(C) 2002 Zwane Mwaikambo <zwane@commfireservices.com> *	(C) 2002 Arjan van de Ven <arjanv@redhat.com> *	(C) 2002 Tora T. Engstad *	All Rights Reserved * *	This program is free software; you can redistribute it and/or *      modify it under the terms of the GNU General Public License *      as published by the Free Software Foundation; either version *      2 of the License, or (at your option) any later version. * *      The author(s) of this software shall not be held liable for damages *      of any nature resulting due to the use of this software. This *      software is provided AS-IS with no warranties. *	 *	Date		Errata			Description *	20020525	N44, O17	12.5% or 25% DC causes lockup * */#include <linux/kernel.h>#include <linux/module.h> #include <linux/init.h>#include <linux/smp.h>#include <linux/cpufreq.h>#include <linux/slab.h>#include <linux/sched.h>#include <asm/processor.h> #include <asm/msr.h>#include <asm/timex.h>#define PFX	"cpufreq: "/* * Duty Cycle (3bits), note DC_DISABLE is not specified in * intel docs i just use it to mean disable */enum {	DC_RESV, DC_DFLT, DC_25PT, DC_38PT, DC_50PT,	DC_64PT, DC_75PT, DC_88PT, DC_DISABLE};#define DC_ENTRIES	8static int has_N44_O17_errata;static int stock_freq;MODULE_PARM(stock_freq, "i");static struct cpufreq_driver *cpufreq_p4_driver;static int cpufreq_p4_setdc(unsigned int cpu, unsigned int newstate){	u32 l, h;	unsigned long cpus_allowed;	struct cpufreq_freqs freqs;	int hyperthreading = 0;	int affected_cpu_map = 0;	int sibling = 0;	if (!cpu_online(cpu) || (newstate > DC_DISABLE) || 		(newstate == DC_RESV))		return -EINVAL;	/* switch to physical CPU where state is to be changed*/	cpus_allowed = current->cpus_allowed;	/* only run on CPU to be set, or on its sibling */	affected_cpu_map = 1 << cpu;#ifdef CONFIG_X86_HT	hyperthreading = ((cpu_has_ht) && (smp_num_siblings == 2));	if (hyperthreading) {		sibling = cpu_sibling_map[cpu];		affected_cpu_map |= (1 << sibling);	}#endif	set_cpus_allowed(current, affected_cpu_map);	BUG_ON(!(affected_cpu_map & (1 << smp_processor_id())));	/* get current state */	rdmsr(MSR_IA32_THERM_CONTROL, l, h);	if (l & 0x10) {		l = l >> 1;		l &= 0x7;	} else		l = DC_DISABLE;		if (l == newstate) {		set_cpus_allowed(current, cpus_allowed);		return 0;	} else if (l == DC_RESV) {		printk(KERN_ERR PFX "BIG FAT WARNING: currently in invalid setting\n");	}	/* notifiers */	freqs.old = stock_freq * l / 8;	freqs.new = stock_freq * newstate / 8;	freqs.cpu = cpu;	cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);	if (hyperthreading) {		freqs.cpu = sibling;		cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);	}	rdmsr(MSR_IA32_THERM_STATUS, l, h);	if (l & 0x01)		printk(KERN_DEBUG PFX "CPU#%d currently thermal throttled\n", cpu);	if (has_N44_O17_errata && (newstate == DC_25PT || newstate == DC_DFLT))		newstate = DC_38PT;	rdmsr(MSR_IA32_THERM_CONTROL, l, h);	if (newstate == DC_DISABLE) {		printk(KERN_INFO PFX "CPU#%d disabling modulation\n", cpu);		wrmsr(MSR_IA32_THERM_CONTROL, l & ~(1<<4), h);	} else {		printk(KERN_INFO PFX "CPU#%d setting duty cycle to %d%%\n", cpu, ((125 * newstate) / 10));		/* bits 63 - 5	: reserved 		 * bit  4	: enable/disable		 * bits 3-1	: duty cycle		 * bit  0	: reserved		 */		l = (l & ~14);		l = l | (1<<4) | ((newstate & 0x7)<<1);		wrmsr(MSR_IA32_THERM_CONTROL, l, h);	}	set_cpus_allowed(current, cpus_allowed);	/* notifiers */	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);	if (hyperthreading) {		freqs.cpu = cpu;		cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);	}	return 0;}static struct cpufreq_frequency_table p4clockmod_table[] = {	{DC_RESV, CPUFREQ_ENTRY_INVALID},	{DC_DFLT, 0},	{DC_25PT, 0},	{DC_38PT, 0},	{DC_50PT, 0},	{DC_64PT, 0},	{DC_75PT, 0},	{DC_88PT, 0},	{DC_DISABLE, 0},	{DC_RESV, CPUFREQ_TABLE_END},};static int cpufreq_p4_setpolicy(struct cpufreq_policy *policy){	unsigned int    newstate = DC_RESV;	if (cpufreq_frequency_table_setpolicy(policy, &p4clockmod_table[0], &newstate))		return -EINVAL;	cpufreq_p4_setdc(policy->cpu, newstate);	return 0;}static int cpufreq_p4_verify(struct cpufreq_policy *policy){	return cpufreq_frequency_table_verify(policy, &p4clockmod_table[0]);}static int __init cpufreq_p4_init(void){		struct cpuinfo_x86 *c = cpu_data;	int cpuid;	int ret;	struct cpufreq_driver *driver;	unsigned int i;	/*	 * THERM_CONTROL is architectural for IA32 now, so 	 * we can rely on the capability checks	 */	if (c->x86_vendor != X86_VENDOR_INTEL)		return -ENODEV;	if (!test_bit(X86_FEATURE_ACPI, c->x86_capability) ||		!test_bit(X86_FEATURE_ACC, c->x86_capability))		return -ENODEV;	/* Errata workarounds */	cpuid = (c->x86 << 8) | (c->x86_model << 4) | c->x86_mask;	switch (cpuid) {		case 0x0f07:		case 0x0f0a:		case 0x0f11:		case 0x0f12:			has_N44_O17_errata = 1;		default:			break;	}	printk(KERN_INFO PFX "P4/Xeon(TM) CPU On-Demand Clock Modulation available\n");	if (!stock_freq) {		if (cpu_khz)			stock_freq = cpu_khz;		else {			printk(KERN_INFO PFX "unknown core frequency - please use module parameter 'stock_freq'\n");			return -EINVAL;		}	}	driver = kmalloc(sizeof(struct cpufreq_driver) +			 NR_CPUS * sizeof(struct cpufreq_policy), GFP_KERNEL);	if (!driver)		return -ENOMEM;	driver->policy = (struct cpufreq_policy *) (driver + 1);	/* table init */	for (i=1; (p4clockmod_table[i].frequency != CPUFREQ_TABLE_END); i++) {		if ((i<2) && (has_N44_O17_errata))			p4clockmod_table[i].frequency = CPUFREQ_ENTRY_INVALID;		else			p4clockmod_table[i].frequency = (stock_freq * i)/8;	}	#ifdef CONFIG_CPU_FREQ_24_API	for (i=0;i<NR_CPUS;i++) {		driver->cpu_cur_freq[i] = stock_freq;	}#endif	driver->verify        = &cpufreq_p4_verify;	driver->setpolicy     = &cpufreq_p4_setpolicy;	for (i=0;i<NR_CPUS;i++) {		driver->policy[i].cpu    = i;		ret = cpufreq_frequency_table_cpuinfo(&driver->policy[i], &p4clockmod_table[0]);		if (ret) {			kfree(driver);			return ret;		}		driver->policy[i].policy = CPUFREQ_POLICY_PERFORMANCE;		driver->policy[i].cpuinfo.transition_latency = CPUFREQ_ETERNAL;	}	cpufreq_p4_driver = driver;		ret = cpufreq_register(driver);	if (ret) {		cpufreq_p4_driver = NULL;		kfree(driver);	}	return ret;}static void __exit cpufreq_p4_exit(void){	unsigned int i;	if (cpufreq_p4_driver) {		for (i=0; i<NR_CPUS; i++) {			if (cpu_online(i)) 				cpufreq_p4_setdc(i, DC_DISABLE);		}		cpufreq_unregister();		kfree(cpufreq_p4_driver);	}}MODULE_AUTHOR ("Zwane Mwaikambo <zwane@commfireservices.com>");MODULE_DESCRIPTION ("cpufreq driver for Pentium(TM) 4/Xeon(TM)");MODULE_LICENSE ("GPL");module_init(cpufreq_p4_init);module_exit(cpufreq_p4_exit);

⌨️ 快捷键说明

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