qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH] pseries: Add device tree properties for VMX/VSX and DFP under kvm
@ 2011-09-21  6:35 David Gibson
  2011-09-21  7:53 ` Alexander Graf
  0 siblings, 1 reply; 3+ messages in thread
From: David Gibson @ 2011-09-21  6:35 UTC (permalink / raw)
  To: agraf; +Cc: qemu-devel

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 <david@gibson.dropbear.id.au>
---
 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;
-- 
1.7.5.4

^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [Qemu-devel] [PATCH] pseries: Add device tree properties for VMX/VSX and DFP under kvm
  2011-09-21  6:35 [Qemu-devel] [PATCH] pseries: Add device tree properties for VMX/VSX and DFP under kvm David Gibson
@ 2011-09-21  7:53 ` Alexander Graf
  2011-09-22  3:16   ` David Gibson
  0 siblings, 1 reply; 3+ messages in thread
From: Alexander Graf @ 2011-09-21  7:53 UTC (permalink / raw)
  To: David Gibson; +Cc: qemu-devel


On 21.09.2011, at 08:35, David Gibson wrote:

> 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 <david@gibson.dropbear.id.au>
> ---
> 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;

This should also take the target CPU into account. If the target CPU can't do VMX/DFP, it shouldn' be announced. Imagine running a guest with the compatibility mode bit set, so we're virtualization the previous generation.

When did dfp get introduced? Was that POWER6 or POWER7? Also, isn't there this twice-as-wide VMX extension too?

> 
>         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);
> +}

Could you please fold those two into a single helper function to read out a 32-bit dt property and then just use that? :)

Please also document somewhere in the code what the return value means (0 = unavailable, 1 = available).


Apart from that, nice patch!

Alex

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [Qemu-devel] [PATCH] pseries: Add device tree properties for VMX/VSX and DFP under kvm
  2011-09-21  7:53 ` Alexander Graf
@ 2011-09-22  3:16   ` David Gibson
  0 siblings, 0 replies; 3+ messages in thread
From: David Gibson @ 2011-09-22  3:16 UTC (permalink / raw)
  To: Alexander Graf; +Cc: qemu-devel

On Wed, Sep 21, 2011 at 09:53:22AM +0200, Alexander Graf wrote:
> 
> On 21.09.2011, at 08:35, David Gibson wrote:
> 
> > 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 <david@gibson.dropbear.id.au>
> > ---
> > 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;
> 
> This should also take the target CPU into account. If the target CPU
> can't do VMX/DFP, it shouldn' be announced. Imagine running a guest
> with the compatibility mode bit set, so we're virtualization the
> previous generation.

Hrm, ok.

> When did dfp get introduced? Was that POWER6 or POWER7?

POWER7, I think, but I'm not certain.

> Also, isn't
> there this twice-as-wide VMX extension too?

Yeah, that's VSX.  It's represented by a 2 instead of a 1 in the
"ibm,vmx" property.

> >         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);
> > +}
> 
> Could you please fold those two into a single helper function to
> read out a 32-bit dt property and then just use that? :)
> 
> Please also document somewhere in the code what the return value
> means (0 = unavailable, 1 = available).

Ok.

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2011-09-22  3:16 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-09-21  6:35 [Qemu-devel] [PATCH] pseries: Add device tree properties for VMX/VSX and DFP under kvm David Gibson
2011-09-21  7:53 ` Alexander Graf
2011-09-22  3:16   ` David Gibson

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).