From patchwork Wed Sep 21 06:35:40 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Gibson X-Patchwork-Id: 115686 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [140.186.70.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 5A0DEB6F67 for ; Wed, 21 Sep 2011 16:36:00 +1000 (EST) Received: from localhost ([::1]:50985 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1R6GPU-0008BF-G9 for incoming@patchwork.ozlabs.org; Wed, 21 Sep 2011 02:35:56 -0400 Received: from eggs.gnu.org ([140.186.70.92]:34872) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1R6GPO-0008BA-Mz for qemu-devel@nongnu.org; Wed, 21 Sep 2011 02:35:51 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1R6GPN-0001SF-7p for qemu-devel@nongnu.org; Wed, 21 Sep 2011 02:35:50 -0400 Received: from ozlabs.org ([203.10.76.45]:56311) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1R6GPM-0001S4-Jx for qemu-devel@nongnu.org; Wed, 21 Sep 2011 02:35:49 -0400 Received: by ozlabs.org (Postfix, from userid 1007) id 21615B6F90; Wed, 21 Sep 2011 16:35:43 +1000 (EST) From: David Gibson To: agraf@suse.de Date: Wed, 21 Sep 2011 16:35:40 +1000 Message-Id: <1316586940-5692-1-git-send-email-david@gibson.dropbear.id.au> X-Mailer: git-send-email 1.7.5.4 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 203.10.76.45 Cc: qemu-devel@nongnu.org Subject: [Qemu-devel] [PATCH] pseries: Add device tree properties for VMX/VSX and DFP under kvm X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sufficiently recent PAPR specifications define properties "ibm,vmx" and "ibm,dfp" on the CPU node which advertise whether the VMX vector extensions (or the later VSX version) and/or the Decimal Floating Point operations from IBM's recent POWER CPUs are available. Currently we do not put these in the guest device tree and the guest kernel will consequently assume they are not available. This is good, because they are not supported under TCG. VMX is similar enough to Altivec that it might be trivial to support, but VSX and DFP would both require significant work to support in TCG. However, when running under kvm on a host which supports these instructions, there's no reason not to let the guest use them. This patch, therefore, checks for the relevant support on the host CPU and, if present, advertises them to the guest as well. Signed-off-by: David Gibson --- hw/spapr.c | 13 ++++++++++ target-ppc/kvm.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++ target-ppc/kvm_ppc.h | 12 ++++++++++ 3 files changed, 85 insertions(+), 0 deletions(-) diff --git a/hw/spapr.c b/hw/spapr.c index b118975..573392d 100644 --- a/hw/spapr.c +++ b/hw/spapr.c @@ -168,6 +168,9 @@ static void *spapr_create_fdt_skel(const char *cpu_model, 0xffffffff, 0xffffffff}; uint32_t tbfreq = kvm_enabled() ? kvmppc_get_tbfreq() : TIMEBASE_FREQ; uint32_t cpufreq = kvm_enabled() ? kvmppc_get_clockfreq() : 1000000000; + /* Currently TCG doesn't implement VMX or DFP instructions */ + uint32_t vmx = kvm_enabled() ? kvmppc_get_vmx() : 0; + uint32_t dfp = kvm_enabled() ? kvmppc_get_dfp() : 0; if (asprintf(&nodename, "%s@%x", modelname, index) < 0) { fprintf(stderr, "Allocation failure\n"); @@ -202,6 +205,16 @@ static void *spapr_create_fdt_skel(const char *cpu_model, segs, sizeof(segs)))); } + /* Advertise VMX/VSX (vector extensions) if available */ + if (vmx) { + _FDT((fdt_property_cell(fdt, "ibm,vmx", vmx))); + } + + /* Advertise DFP (Decimal Floating Point) if available */ + if (dfp) { + _FDT((fdt_property_cell(fdt, "ibm,dfp", dfp))); + } + _FDT((fdt_end_node(fdt))); } diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c index 35a6f10..397a803 100644 --- a/target-ppc/kvm.c +++ b/target-ppc/kvm.c @@ -673,6 +673,66 @@ uint64_t kvmppc_get_clockfreq(void) return 0; } +uint32_t kvmppc_get_vmx(void) +{ + char buf[512]; + uint32_t vmx; + FILE *f; + int len; + + if (kvmppc_find_cpu_dt(buf, sizeof(buf))) { + return 0; + } + + strncat(buf, "/ibm,vmx", sizeof(buf) - strlen(buf)); + + f = fopen(buf, "rb"); + if (!f) { + /* Assume -ENOENT, which indicates that VMX is not available */ + return 0; + } + + len = fread(&vmx, sizeof(vmx), 1, f); + fclose(f); + + if (len != 1) { + /* Malformed ibm,vmx property, assume no vmx or vsx */ + return 0; + } + + return be32_to_cpu(vmx); +} + +uint32_t kvmppc_get_dfp(void) +{ + char buf[512]; + uint32_t dfp; + FILE *f; + int len; + + if (kvmppc_find_cpu_dt(buf, sizeof(buf))) { + return 0; + } + + strncat(buf, "/ibm,dfp", sizeof(buf) - strlen(buf)); + + f = fopen(buf, "rb"); + if (!f) { + /* Assume -ENOENT, which indicates that DFP is not available */ + return 0; + } + + len = fread(&dfp, sizeof(dfp), 1, f); + fclose(f); + + if (len != 1) { + /* Malformed ibm,dfp property, assume no DFP */ + return 0; + } + + return be32_to_cpu(dfp); +} + int kvmppc_get_hypercall(CPUState *env, uint8_t *buf, int buf_len) { uint32_t *hc = (uint32_t*)buf; diff --git a/target-ppc/kvm_ppc.h b/target-ppc/kvm_ppc.h index c484e60..b125317 100644 --- a/target-ppc/kvm_ppc.h +++ b/target-ppc/kvm_ppc.h @@ -15,6 +15,8 @@ void kvmppc_init(void); uint32_t kvmppc_get_tbfreq(void); uint64_t kvmppc_get_clockfreq(void); +uint32_t kvmppc_get_vmx(void); +uint32_t kvmppc_get_dfp(void); int kvmppc_get_hypercall(CPUState *env, uint8_t *buf, int buf_len); int kvmppc_set_interrupt(CPUState *env, int irq, int level); void kvmppc_set_papr(CPUState *env); @@ -31,6 +33,16 @@ static inline uint64_t kvmppc_get_clockfreq(void) return 0; } +static inline uint32_t kvmppc_get_vmx(void) +{ + return 0; +} + +static inline uint32_t kvmppc_get_dfp(void) +{ + return 0; +} + static inline int kvmppc_get_hypercall(CPUState *env, uint8_t *buf, int buf_len) { return -1;