From patchwork Fri Jan 8 17:43:12 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexander Graf X-Patchwork-Id: 42525 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [199.232.76.165]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 3A1661007D1 for ; Sat, 9 Jan 2010 04:48:21 +1100 (EST) Received: from localhost ([127.0.0.1]:49733 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1NTItR-0002ON-MP for incoming@patchwork.ozlabs.org; Fri, 08 Jan 2010 12:45:01 -0500 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1NTIs5-0002MZ-Bi for qemu-devel@nongnu.org; Fri, 08 Jan 2010 12:43:37 -0500 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1NTIs0-0002EV-83 for qemu-devel@nongnu.org; Fri, 08 Jan 2010 12:43:36 -0500 Received: from [199.232.76.173] (port=44180 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1NTIrz-0002EH-Vz for qemu-devel@nongnu.org; Fri, 08 Jan 2010 12:43:32 -0500 Received: from mx20.gnu.org ([199.232.41.8]:14339) by monty-python.gnu.org with esmtps (TLS-1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.60) (envelope-from ) id 1NTIry-0000Ah-0T for qemu-devel@nongnu.org; Fri, 08 Jan 2010 12:43:30 -0500 Received: from cantor2.suse.de ([195.135.220.15] helo=mx2.suse.de) by mx20.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1NTIrr-0004ao-1Z for qemu-devel@nongnu.org; Fri, 08 Jan 2010 12:43:23 -0500 Received: from relay2.suse.de (charybdis-ext.suse.de [195.135.221.2]) by mx2.suse.de (Postfix) with ESMTP id 0857789783; Fri, 8 Jan 2010 18:43:13 +0100 (CET) From: Alexander Graf To: QEMU Developers Date: Fri, 8 Jan 2010 18:43:12 +0100 Message-Id: <1262972592-7317-1-git-send-email-agraf@suse.de> X-Mailer: git-send-email 1.6.0.2 X-detected-operating-system: by mx20.gnu.org: GNU/Linux 2.4-2.6 X-detected-operating-system: by monty-python.gnu.org: GNU/Linux 2.6, seldom 2.4 (older, 4) Cc: Blue Swirl , Aurelien Jarno Subject: [Qemu-devel] [PATCH] PPC: tell the guest about the time base frequency X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Our guest systems need to know by how much the timebase increases every second, so there usually is a "timebase-frequency" property in the cpu leaf of the device tree. This property is missing in OpenBIOS, as is the "clock-frequency" property that tells the guest how fast the CPU is. FWIW that one is only used for /proc/cpuinfo though. With qemu, Linux's fallback timebase speed and qemu's internal timebase speed match up. With KVM, that is no longer true. The guest is running at the same timebase speed as the host. This leads to massive timing problems. On my test machine, a "sleep 2" takes about 14 seconds with KVM enabled. This patch exports the timebase and clock frequencies to OpenBIOS, so it can then put them into the device tree. I'll push the OpenBIOS change with the NewWorld patch set, once that's either been reviewed or applied. Signed-off-by: Alexander Graf --- hw/ppc.h | 2 + hw/ppc_newworld.c | 11 ++++++++ hw/ppc_oldworld.c | 11 ++++++++ target-ppc/kvm.c | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++ target-ppc/kvm_ppc.h | 3 ++ 5 files changed, 97 insertions(+), 0 deletions(-) diff --git a/hw/ppc.h b/hw/ppc.h index b9a12a1..864516f 100644 --- a/hw/ppc.h +++ b/hw/ppc.h @@ -46,5 +46,7 @@ enum { #define FW_CFG_PPC_WIDTH (FW_CFG_ARCH_LOCAL + 0x00) #define FW_CFG_PPC_HEIGHT (FW_CFG_ARCH_LOCAL + 0x01) #define FW_CFG_PPC_DEPTH (FW_CFG_ARCH_LOCAL + 0x02) +#define FW_CFG_PPC_TBFREQ (FW_CFG_ARCH_LOCAL + 0x03) +#define FW_CFG_PPC_CPUFREQ (FW_CFG_ARCH_LOCAL + 0x04) #define PPC_SERIAL_MM_BAUDBASE 399193 diff --git a/hw/ppc_newworld.c b/hw/ppc_newworld.c index d66860b..0ed7a39 100644 --- a/hw/ppc_newworld.c +++ b/hw/ppc_newworld.c @@ -40,6 +40,7 @@ #include "loader.h" #include "elf.h" #include "kvm.h" +#include "kvm_ppc.h" #define MAX_IDE_BUS 2 #define VGA_BIOS_SIZE 65536 @@ -389,6 +390,16 @@ static void ppc_core99_init (ram_addr_t ram_size, fw_cfg_add_i16(fw_cfg, FW_CFG_PPC_HEIGHT, graphic_height); fw_cfg_add_i16(fw_cfg, FW_CFG_PPC_DEPTH, graphic_depth); + if (kvm_enabled()) { +#ifdef CONFIG_KVM + fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_TBFREQ, kvmppc_get_tbfreq()); + fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_CPUFREQ, kvmppc_get_cpufreq()); +#endif + } else { + fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_TBFREQ, get_ticks_per_sec()); + fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_CPUFREQ, 1500 * 1000 * 1000); + } + qemu_register_boot_set(fw_cfg_boot_set, fw_cfg); } diff --git a/hw/ppc_oldworld.c b/hw/ppc_oldworld.c index 7ccc6a1..feb8b6a 100644 --- a/hw/ppc_oldworld.c +++ b/hw/ppc_oldworld.c @@ -40,6 +40,7 @@ #include "loader.h" #include "elf.h" #include "kvm.h" +#include "kvm_ppc.h" #define MAX_IDE_BUS 2 #define VGA_BIOS_SIZE 65536 @@ -401,6 +402,16 @@ static void ppc_heathrow_init (ram_addr_t ram_size, fw_cfg_add_i16(fw_cfg, FW_CFG_PPC_HEIGHT, graphic_height); fw_cfg_add_i16(fw_cfg, FW_CFG_PPC_DEPTH, graphic_depth); + if (kvm_enabled()) { +#ifdef CONFIG_KVM + fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_TBFREQ, kvmppc_get_tbfreq()); + fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_CPUFREQ, kvmppc_get_cpufreq()); +#endif + } else { + fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_TBFREQ, get_ticks_per_sec()); + fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_CPUFREQ, 500 * 1000 * 1000); + } + qemu_register_boot_set(fw_cfg_boot_set, fw_cfg); } diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c index 0424a78..2e1c897 100644 --- a/target-ppc/kvm.c +++ b/target-ppc/kvm.c @@ -252,3 +252,73 @@ int kvm_arch_handle_exit(CPUState *env, struct kvm_run *run) return ret; } +static int read_cpuinfo(const char *field, char *value, int len) +{ + FILE *f; + int ret = -1; + int field_len = strlen(field); + char line[512]; + + f = fopen("/proc/cpuinfo", "r"); + if (!f) { + return -1; + } + + do { + fgets(line, sizeof(line), f); + if (!strncmp(line, field, field_len)) { + strncpy(value, line, len); + ret = 0; + break; + } + } while(*line); + + fclose(f); + + return ret; +} + +uint32_t kvmppc_get_cpufreq(void) +{ + char line[512]; + char *ns, *ns2; + uint32_t retval = 1500 * 1000 * 1000; + + if (read_cpuinfo("clock", line, sizeof(line))) { + return retval; + } + + if (!(ns = strchr(line, ':'))) { + return retval; + } + + ns++; + + if (!(ns2 = strchr(ns, '.'))) { + return retval; + } + + retval = atoi(ns) * 1000 * 1000; + return retval; +} + +uint32_t kvmppc_get_tbfreq(void) +{ + char line[512]; + char *ns; + uint32_t retval = get_ticks_per_sec(); + + if (read_cpuinfo("timebase", line, sizeof(line))) { + return retval; + } + + if (!(ns = strchr(line, ':'))) { + return retval; + } + + ns++; + + retval = atoi(ns); + return retval; +} + diff --git a/target-ppc/kvm_ppc.h b/target-ppc/kvm_ppc.h index 3792ef7..7f504df 100644 --- a/target-ppc/kvm_ppc.h +++ b/target-ppc/kvm_ppc.h @@ -14,4 +14,7 @@ void kvmppc_fdt_update(void *fdt); int kvmppc_read_host_property(const char *node_path, const char *prop, void *val, size_t len); +uint32_t kvmppc_get_cpufreq(void); +uint32_t kvmppc_get_tbfreq(void); + #endif /* __KVM_PPC_H__ */