From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1Ka47F-0008GU-Ja for qemu-devel@nongnu.org; Mon, 01 Sep 2008 03:46:25 -0400 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1Ka47E-0008FI-4d for qemu-devel@nongnu.org; Mon, 01 Sep 2008 03:46:25 -0400 Received: from [199.232.76.173] (port=44308 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1Ka47D-0008F2-R7 for qemu-devel@nongnu.org; Mon, 01 Sep 2008 03:46:23 -0400 Received: from mx20.gnu.org ([199.232.41.8]:11071) by monty-python.gnu.org with esmtps (TLS-1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.60) (envelope-from ) id 1Ka47D-0005zh-3W for qemu-devel@nongnu.org; Mon, 01 Sep 2008 03:46:23 -0400 Received: from il.qumranet.com ([212.179.150.194]) by mx20.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1Ka47B-0000m9-EQ for qemu-devel@nongnu.org; Mon, 01 Sep 2008 03:46:21 -0400 Received: from gleb-debian.qumranet.com (gleb-debian.qumranet.com.qumranet.com [172.16.15.143]) by il.qumranet.com (Postfix) with ESMTP id 6D8CE250EDA for ; Mon, 1 Sep 2008 10:46:20 +0300 (IDT) Date: Mon, 1 Sep 2008 10:46:20 +0300 From: Gleb Natapov Subject: Re: [Qemu-devel] [PATCH v4 6/8] Pass cpu speed into SM BIOS. Message-ID: <20080901074620.GK6192@minantech.com> References: <20080901072531.17854.37681.stgit@gleb-debian.qumranet.com.qumranet.com> <20080901072601.17854.43871.stgit@gleb-debian.qumranet.com.qumranet.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20080901072601.17854.43871.stgit@gleb-debian.qumranet.com.qumranet.com> Reply-To: qemu-devel@nongnu.org List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Sorry, use this one instead. --- Signed-off-by: Gleb Natapov diff --git a/hw/pc.c b/hw/pc.c index 933e936..aae9fc6 100644 --- a/hw/pc.c +++ b/hw/pc.c @@ -49,6 +49,8 @@ #define MAX_IDE_BUS 2 +#define FW_CFG_PC_CPUSPEED (FW_CFG_ARCH_LOCAL + 0x00) + static fdctrl_t *floppy_controller; static RTCState *rtc_state; static PITState *pit; @@ -369,6 +371,89 @@ static uint32_t ioport92_read(void *opaque, uint32_t addr) return ioport_get_a20() << 1; } +#ifdef __linux__ +/* get_freq () function is taken from conky source code */ +#define CPUFREQ_PREFIX "/sys/devices/system/cpu" +#define CPUFREQ_POSTFIX "cpufreq/scaling_cur_freq" + +/* return system frequency in MHz (use divisor=1) or GHz (use divisor=1000) */ +static double get_freq(int divisor, unsigned int cpu) +{ + FILE *f; + char frequency[32]; + char s[256]; + double freq = 0; + + if (divisor <= 0) + return 0; + + snprintf(s, 256, "%s/cpu%d/%s", CPUFREQ_PREFIX, cpu - 1, CPUFREQ_POSTFIX); + f = fopen(s, "r"); + if (f) { + /* if there's a cpufreq /sys node, read the current frequency from + * this node and divide by 1000 to get Mhz. */ + if (fgets(s, sizeof(s), f)) { + s[strlen(s) - 1] = '\0'; + freq = strtod(s, NULL); + } + fclose(f); + return (freq / 1000) / divisor; + } + + // open the CPU information file + f = fopen("/proc/cpuinfo", "r"); + if (!f) { + perror("Failed to access '/proc/cpuinfo' at get_freq()"); + return 0; + } + + // read the file + while (fgets(s, sizeof(s), f) != NULL) { + +#if defined(__i386) || defined(__x86_64) + // and search for the cpu mhz + if (strncmp(s, "cpu MHz", 7) == 0 && cpu == 0) { +#else +#if defined(__alpha) + // different on alpha + if (strncmp(s, "cycle frequency [Hz]", 20) == 0 && cpu == 0) { +#else + // this is different on ppc for some reason + if (strncmp(s, "clock", 5) == 0 && cpu == 0) { +#endif // defined(__alpha) +#endif // defined(__i386) || defined(__x86_64) + + // copy just the number + strcpy(frequency, strchr(s, ':') + 2); +#if defined(__alpha) + // strip " est.\n" + frequency[strlen(frequency) - 6] = '\0'; + // kernel reports in Hz + freq = strtod(frequency, NULL) / 1000000; +#else + // strip \n + frequency[strlen(frequency) - 1] = '\0'; + freq = strtod(frequency, NULL); +#endif + break; + } + if (strncmp(s, "processor", 9) == 0) { + cpu--; + continue; + } + } + + fclose(f); + return freq / divisor; +} +#else +static double get_freq(int divisor, unsigned int cpu) +{ + return 0; +} +#endif + + /***********************************************************/ /* Bochs BIOS debug ports */ @@ -418,6 +503,7 @@ static void bochs_bios_write(void *opaque, uint32_t addr, uint32_t val) static void bochs_bios_init(void) { + uint16_t cpu_speed; void *fw_cfg; register_ioport_write(0x400, 1, 2, bochs_bios_write, NULL); @@ -433,6 +519,8 @@ static void bochs_bios_init(void) fw_cfg = fw_cfg_init(BIOS_CFG_IOPORT, 0); fw_cfg_add_i32(fw_cfg, FW_CFG_ID, 1); + cpu_speed = (uint16_t)get_freq(1, 1); + fw_cfg_add_i16(fw_cfg, FW_CFG_PC_CPUSPEED, cpu_speed); } /* Generate an initial boot sector which sets state and jump to -- Gleb.