Can't build simple program!!
I'm at my wits end. I can't figure this thing out - it makes no sense to me.
System: Sony Vaio w/ugraded CPU (Athlon 2600+) Topologilinux 5.0.0 (slackware 10 base) kernels 2.4.26 and 2.6.9 I'm trying to modify the cpufreq driver powernow-k7.c to simply set the CPU core voltage to 1.225V (by BIOS doesn't have a PST for my CPU). I have simple program for WinXP that works flawlesly doing this. I simply removed everything except the FID and VID table (for reference) and the functions to set the VID and the FID. The program compiles, but then returns: In function: 'Change_FID': :undefined reference to 'rdmsrl' In function: 'Change_FID': :undefined reference to 'wrmsrl' In function: 'Change_VID': :undefined reference to 'rdmsrl' In function: 'Change_VID': :undefined reference to 'wrmsrl' which I dorn't understand since rdmsrl and wrmdrl are defined explicitly in msr.h: #ifndef __ASM_MSR_H #define __ASM_MSR_H /* * Access to machine-specific registers (available on 586 and better only) * Note: the rd* operations modify the parameters directly (without using * pointer indirection), this allows gcc to optimize better */ #define rdmsr(msr,val1,val2) \ __asm__ __volatile__("rdmsr" \ : "=a" (val1), "=d" (val2) \ : "c" (msr)) #define wrmsr(msr,val1,val2) \ __asm__ __volatile__("wrmsr" \ : /* no outputs */ \ : "c" (msr), "a" (val1), "d" (val2)) #define rdmsrl(msr,val) do { \ unsigned long l__,h__; \ rdmsr (msr, l__, h__); \ val = l__; \ val |= ((u64)h__<<32); \ } while(0) static inline void wrmsrl (unsigned long msr, unsigned long long val) { unsigned long lo, hi; lo = (unsigned long) val; hi = val >> 32; wrmsr (msr, lo, hi); } Here is the listing of the program: /* * Sets Athlon K7 Core Voltage to 1.225 V Using AMD K7 Powernow driver. * (C) 2003 Dave Jones <davej@codemonkey.org.uk> on behalf of SuSE Labs. * (C) 2003-2004 Dave Jones <davej@redhat.com> * * Licensed under the terms of the GNU GPL License version 2. * Based upon datasheets & sample CPUs kindly provided by AMD. * * Errata 5: Processor may fail to execute a FID/VID change in presence of interrupt. * - We cli/sti on stepping A0 CPUs around the FID/VID transition. * Errata 15: Processors with half frequency multipliers may hang upon wakeup from disconnect. * - We disable half multipliers if ACPI is used on A0 stepping CPUs. */ #include <stdio.h> #include <linux/config.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/moduleparam.h> #include <linux/init.h> //#include <linux/cpufreq.h> #include <linux/slab.h> #include <linux/string.h> //#include <linux/dmi.h> //#include <asm/msr.h> #include <asm/timex.h> #include <asm/io.h> #include <asm/system.h> #include "powernow-k7.h" #include "/usr/src/linux/include/asm-i386/msr.h" #define PFX "powernow: " // Back to main program /* divide by 1000 to get VID. */ static int mobile_vid_table[32] = { 2000, 1950, 1900, 1850, 1800, 1750, 1700, 1650, 1600, 1550, 1500, 1450, 1400, 1350, 1300, 0, 1275, 1250, 1225, 1200, 1175, 1150, 1125, 1100, 1075, 1050, 1024, 1000, 975, 950, 925, 0, }; /* divide by 10 to get FID. */ static int fid_codes[32] = { 110, 115, 120, 125, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95, 100, 105, 30, 190, 40, 200, 130, 135, 140, 210, 150, 225, 160, 165, 170, 180, -1, -1, }; /* This parameter is used in order to force ACPI instead of legacy method for * configuration purpose. */ static int acpi_force; static int debug; //static struct cpufreq_frequency_table *powernow_table; /*static unsigned int can_scale_bus; static unsigned int can_scale_vid; static unsigned int minimum_speed=-1; static unsigned int maximum_speed; static unsigned int number_scales; static unsigned int fsb; static unsigned int latency; static char have_a0; */ static unsigned int latency=100; static void change_FID(int fid) { union msr_fidvidctl fidvidctl; rdmsrl (MSR_K7_FID_VID_CTL, fidvidctl.val); if (fidvidctl.bits.FID != fid) { fidvidctl.bits.SGTC = latency; fidvidctl.bits.FID = fid; fidvidctl.bits.VIDC = 0; fidvidctl.bits.FIDC = 1; wrmsrl (MSR_K7_FID_VID_CTL, fidvidctl.val); } } static void change_VID(int vid) { union msr_fidvidctl fidvidctl; rdmsrl (MSR_K7_FID_VID_CTL, fidvidctl.val); if (fidvidctl.bits.VID != vid) { fidvidctl.bits.SGTC = latency; fidvidctl.bits.VID = vid; fidvidctl.bits.FIDC = 0; fidvidctl.bits.VIDC = 1; wrmsrl (MSR_K7_FID_VID_CTL, fidvidctl.val); } } int main (void) { printf("Changing VID to index 18 =1.225 V"); change_VID(18); return 0; } |
Header files don't contain the functions, just the function prototypes. The functions themselves are probably contained in a library that you need to link into your program.
|
I have no idea what library they are in.
But it looks like rdmsrl and wrmsrl are defined in msr.h, not just listed as prototypes. I have googled "wrmsrl" and "rdmsrl" in an attempt to find the libraries, but I only get links to these functions in code, no libraries. |
Did you read Documentation/cpu-freq/amd-powernow.txt from your kernel tree ?
Also for my part I enable powersaving with setpci at boot in a init script folowing this link : http://ldp.kernelnotes.de/HOWTO/Athl...pproaches.html |
All times are GMT -5. The time now is 05:00 PM. |