[Qemu-devel] [QEMU-PPC] [PATCH V4] powerpc/spapr: Add host threads parameter to ibm, get_system_parameter

2019-08-26 Thread Suraj Jitindar Singh
The ibm,get_system_parameter rtas call is used by the guest to retrieve
data relating to certain parameters of the system. The SPLPAR
characteristics option (token 20) is used to determine characteristics of
the environment in which the lpar will run.

It may be useful for a guest to know the number of physical host threads
present on the underlying system where it is being run. Add the
characteristic "HostThrs" to the SPLPAR Characteristics
ibm,get_system_parameter rtas call to expose this information to a
guest. Add a n_host_threads property to the processor class which is
then used to retrieve this information and define it for POWER8 and
POWER9. Other processors will default to 0 and the charateristic won't
be added.

Signed-off-by: Suraj Jitindar Singh 

---

V1 -> V2:
- Take into account that the core may be operating in split core mode
  meaning a single core may be split into multiple subcores.
V2 -> V3:
- Add curly braces for single line if statements
V3 -> V4;
- Add a host threads property to the processor class and use this to
  derive the information rather than the device tree.
---
 hw/ppc/spapr_rtas.c | 15 +++
 target/ppc/cpu-qom.h|  1 +
 target/ppc/translate_init.inc.c |  2 ++
 3 files changed, 18 insertions(+)

diff --git a/hw/ppc/spapr_rtas.c b/hw/ppc/spapr_rtas.c
index 526b489297..bee3835214 100644
--- a/hw/ppc/spapr_rtas.c
+++ b/hw/ppc/spapr_rtas.c
@@ -266,6 +266,7 @@ static void rtas_ibm_get_system_parameter(PowerPCCPU *cpu,
   target_ulong args,
   uint32_t nret, target_ulong rets)
 {
+PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
 MachineState *ms = MACHINE(qdev_get_machine());
 unsigned int max_cpus = ms->smp.max_cpus;
 target_ulong parameter = rtas_ld(args, 0);
@@ -283,6 +284,20 @@ static void rtas_ibm_get_system_parameter(PowerPCCPU *cpu,
   current_machine->ram_size / MiB,
   ms->smp.cpus,
   max_cpus);
+if (pcc->n_host_threads > 0) {
+char *hostthr_val, *old = param_val;
+
+/*
+ * Add HostThrs property. This property is not present in PAPR but
+ * is expected by some guests to communicate the number of physical
+ * host threads per core on the system so that they can scale
+ * information which varies based on the thread configuration.
+ */
+hostthr_val = g_strdup_printf(",HostThrs=%d", pcc->n_host_threads);
+param_val = g_strconcat(param_val, hostthr_val, NULL);
+g_free(hostthr_val);
+g_free(old);
+}
 ret = sysparm_st(buffer, length, param_val, strlen(param_val) + 1);
 g_free(param_val);
 break;
diff --git a/target/ppc/cpu-qom.h b/target/ppc/cpu-qom.h
index 7ffdb0a706..e499575dc8 100644
--- a/target/ppc/cpu-qom.h
+++ b/target/ppc/cpu-qom.h
@@ -191,6 +191,7 @@ typedef struct PowerPCCPUClass {
 const PPCHash64Options *hash64_opts;
 struct ppc_radix_page_info *radix_page_info;
 uint32_t lrg_decr_bits;
+int n_host_threads;
 void (*init_proc)(CPUPPCState *env);
 int  (*check_pow)(CPUPPCState *env);
 int (*handle_mmu_fault)(PowerPCCPU *cpu, vaddr eaddr, int rwx, int 
mmu_idx);
diff --git a/target/ppc/translate_init.inc.c b/target/ppc/translate_init.inc.c
index 4a21ed7289..41f77b7ef8 100644
--- a/target/ppc/translate_init.inc.c
+++ b/target/ppc/translate_init.inc.c
@@ -8770,6 +8770,7 @@ POWERPC_FAMILY(POWER8)(ObjectClass *oc, void *data)
 pcc->handle_mmu_fault = ppc_hash64_handle_mmu_fault;
 pcc->hash64_opts = _hash64_opts_POWER7;
 pcc->lrg_decr_bits = 32;
+pcc->n_host_threads = 8;
 #endif
 pcc->excp_model = POWERPC_EXCP_POWER8;
 pcc->bus_model = PPC_FLAGS_INPUT_POWER7;
@@ -8981,6 +8982,7 @@ POWERPC_FAMILY(POWER9)(ObjectClass *oc, void *data)
 pcc->hash64_opts = _hash64_opts_POWER7;
 pcc->radix_page_info = _radix_page_info;
 pcc->lrg_decr_bits = 56;
+pcc->n_host_threads = 4;
 #endif
 pcc->excp_model = POWERPC_EXCP_POWER9;
 pcc->bus_model = PPC_FLAGS_INPUT_POWER9;
-- 
2.13.6




[Qemu-devel] [QEMU] crypto/random: Fall back to /dev/random when getrandom returns EAGAIN

2019-07-17 Thread Suraj Jitindar Singh
Hi,

I'm trying to use qemu inside a a guest, however since there isn't
enough entropy for the rng getrandom() blocks. This means I am unable
to even get output from 'qemu --help' for example. This is annoying at
best.

Thinking about ways to work around this obviously the major one is to
have an entropy source for the guest.

In cases where this isn't possible I think it would make sense to fall
back to the old /dev/random source when the getrandom() syscall returns
EAGAIN indicating that it would block.

Alternatively it would be nice to have a config option to disable the
new getrandom interface, along the lines of --disable-getrandom.

If you feel that either of the approaches would be statisfactory I'd be
happy to send a patch. Otherwise if we can have a discussion here with
regards to how to progress.

Kind Regards,
Suraj



Re: [Qemu-devel] [QEMU-PPC] [PATCH v3] powerpc/spapr: Add host threads parameter to ibm, get_system_parameter

2019-07-08 Thread Suraj Jitindar Singh
On Thu, 2019-07-04 at 14:59 +1000, David Gibson wrote:
> On Thu, Jul 04, 2019 at 01:41:59PM +1000, Suraj Jitindar Singh wrote:
> > On Wed, 2019-07-03 at 16:12 +1000, David Gibson wrote:
> > > On Mon, Jul 01, 2019 at 04:19:46PM +1000, Suraj Jitindar Singh
> > > wrote:
> > > > The ibm,get_system_parameter rtas call is used by the guest to
> > > > retrieve
> > > > data relating to certain parameters of the system. The SPLPAR
> > > > characteristics option (token 20) is used to determin
> > > > characteristics of
> > > > the environment in which the lpar will run.
> > > > 
> > > > It may be useful for a guest to know the number of physical
> > > > host
> > > > threads
> > > > present on the underlying system where it is being run. Add the
> > > > characteristic "HostThrs" to the SPLPAR Characteristics
> > > > ibm,get_system_parameter rtas call to expose this information
> > > > to a
> > > > guest and provide an implementation which determines this
> > > > information
> > > > based on the number of interrupt servers present in the device
> > > > tree.
> > > > 
> > > > Signed-off-by: Suraj Jitindar Singh 
> > > 
> > > Hrm, as I said on our call, I have some misgivings about this.
> > > 
> > > Starting with the most general: this again publishes host
> > > information
> > > to the guest without filtering, which has caused us problems
> > > before
> > > (e.g. security issues with publishing the host serial and model
> > > information).  Now, I can't immediately see what harm a guest
> > > could
> > > do
> > > with the host # threads (especially since it could in theory
> > > deduce
> > > it
> > > from the PVR, I think) but it still makes me uneasy.
> > 
> > Correct, a guest could pretty reliably determine this information
> > anyway based on the PVR. It can't account for a POWER8 operating in
> > split core mode, but I don't know any harm that could be done by
> > introducing this information.
> > 
> > Additionally it doesn't really tell you anything about how you're
> > going
> > to be scheduled (at least on POWER9) since vcpus are scheduled on a
> > per
> > thread, not per core basis.
> 
> Hmm.
> 
> > > Secondly, the "HostThrs" tag doesn't seem to be documented in
> > > PAPR as
> > > something that this system-parameter will include.  I don't much
> > > like
> > > the idea of adding ad-hoc bits of information here without some
> > > thought going into designing and specifying it first.
> > 
> > This isn't documented in papr, it has been decided that this is how
> > the
> > information will be communicated to a guest. This is the most
> > appropriate place to put this information and the HostThrs name is
> > consistent with the naming of other information in this property.
> 
> Grr.  If someone can decide this, they can bloody well document it
> somewhere.
> 
> > We have other non-papr information in qemu, for example hcall
> > numbers,
> > so this isn't exactly a precedent.
> 
> I suppose
> 
> > > > ---
> > > > 
> > > > V1 -> V2:
> > > > - Take into account that the core may be operating in split
> > > > core
> > > > mode
> > > >   meaning a single core may be split into multiple subcores.
> > > > V2 -> V3:
> > > > - Add curly braces for single line if statements
> > > > ---
> > > >  hw/ppc/spapr_rtas.c | 62
> > > > +
> > > >  1 file changed, 62 insertions(+)
> > > > 
> > > > diff --git a/hw/ppc/spapr_rtas.c b/hw/ppc/spapr_rtas.c
> > > > index 5bc1a93271..1bab71c90c 100644
> > > > --- a/hw/ppc/spapr_rtas.c
> > > > +++ b/hw/ppc/spapr_rtas.c
> > > > @@ -229,6 +229,58 @@ static inline int sysparm_st(target_ulong
> > > > addr, target_ulong len,
> > > >  return RTAS_OUT_SUCCESS;
> > > >  }
> > > >  
> > > > +#define CPUS_PATH   "/proc/device-tree/cpus/"
> > > > +#define
> > > > SUBCORE_PATH"/sys/devices/system/cpu/subcores_per_core"
> > > > +
> > > > +static int rtas_get_num_host_threads(void)
> > > > +{
> > > > +int num_threads = -1;
> > 

Re: [Qemu-devel] [QEMU-PPC] [PATCH v3] powerpc/spapr: Add host threads parameter to ibm, get_system_parameter

2019-07-03 Thread Suraj Jitindar Singh
On Wed, 2019-07-03 at 16:12 +1000, David Gibson wrote:
> On Mon, Jul 01, 2019 at 04:19:46PM +1000, Suraj Jitindar Singh wrote:
> > The ibm,get_system_parameter rtas call is used by the guest to
> > retrieve
> > data relating to certain parameters of the system. The SPLPAR
> > characteristics option (token 20) is used to determin
> > characteristics of
> > the environment in which the lpar will run.
> > 
> > It may be useful for a guest to know the number of physical host
> > threads
> > present on the underlying system where it is being run. Add the
> > characteristic "HostThrs" to the SPLPAR Characteristics
> > ibm,get_system_parameter rtas call to expose this information to a
> > guest and provide an implementation which determines this
> > information
> > based on the number of interrupt servers present in the device
> > tree.
> > 
> > Signed-off-by: Suraj Jitindar Singh 
> 
> Hrm, as I said on our call, I have some misgivings about this.
> 
> Starting with the most general: this again publishes host information
> to the guest without filtering, which has caused us problems before
> (e.g. security issues with publishing the host serial and model
> information).  Now, I can't immediately see what harm a guest could
> do
> with the host # threads (especially since it could in theory deduce
> it
> from the PVR, I think) but it still makes me uneasy.

Correct, a guest could pretty reliably determine this information
anyway based on the PVR. It can't account for a POWER8 operating in
split core mode, but I don't know any harm that could be done by
introducing this information.

Additionally it doesn't really tell you anything about how you're going
to be scheduled (at least on POWER9) since vcpus are scheduled on a per
thread, not per core basis.

> 
> Secondly, the "HostThrs" tag doesn't seem to be documented in PAPR as
> something that this system-parameter will include.  I don't much like
> the idea of adding ad-hoc bits of information here without some
> thought going into designing and specifying it first.

This isn't documented in papr, it has been decided that this is how the
information will be communicated to a guest. This is the most
appropriate place to put this information and the HostThrs name is
consistent with the naming of other information in this property.

We have other non-papr information in qemu, for example hcall numbers,
so this isn't exactly a precedent.

> 
> > 
> > ---
> > 
> > V1 -> V2:
> > - Take into account that the core may be operating in split core
> > mode
> >   meaning a single core may be split into multiple subcores.
> > V2 -> V3:
> > - Add curly braces for single line if statements
> > ---
> >  hw/ppc/spapr_rtas.c | 62
> > +
> >  1 file changed, 62 insertions(+)
> > 
> > diff --git a/hw/ppc/spapr_rtas.c b/hw/ppc/spapr_rtas.c
> > index 5bc1a93271..1bab71c90c 100644
> > --- a/hw/ppc/spapr_rtas.c
> > +++ b/hw/ppc/spapr_rtas.c
> > @@ -229,6 +229,58 @@ static inline int sysparm_st(target_ulong
> > addr, target_ulong len,
> >  return RTAS_OUT_SUCCESS;
> >  }
> >  
> > +#define CPUS_PATH   "/proc/device-tree/cpus/"
> > +#define
> > SUBCORE_PATH"/sys/devices/system/cpu/subcores_per_core"
> > +
> > +static int rtas_get_num_host_threads(void)
> > +{
> > +int num_threads = -1;
> > +unsigned long len;
> > +const char *entry;
> > +char *buf;
> > +GDir *dir;
> > +
> > +if (!kvm_enabled()) {
> > +return 1;
> > +}
> > +
> > +/* Read interrupt servers to determine number of threads per
> > core */
> > +dir = g_dir_open(CPUS_PATH, 0, NULL);
> > +if (!dir) {
> > +return -1;
> > +}
> > +
> > +while ((entry = g_dir_read_name(dir))) {
> > +if (!strncmp(entry, "PowerPC,POWER",
> > strlen("PowerPC,POWER"))) {
> > +char *path;
> > +
> > +path = g_strconcat(CPUS_PATH, entry, "/ibm,ppc-
> > interrupt-server#s",
> > +   NULL);
> > +if (g_file_get_contents(path, , , NULL)) {
> > +num_threads = len / sizeof(int);
> > +g_free(buf);
> > +}
> > +
> > +g_free(path);
> > +break;
> > +}
> > +}
> > +
> > +g_dir_close(dir);
> > +
> > +/* Check if split core mode in use */
>

[Qemu-devel] [QEMU-PPC] [PATCH v3] powerpc/spapr: Add host threads parameter to ibm, get_system_parameter

2019-07-01 Thread Suraj Jitindar Singh
The ibm,get_system_parameter rtas call is used by the guest to retrieve
data relating to certain parameters of the system. The SPLPAR
characteristics option (token 20) is used to determin characteristics of
the environment in which the lpar will run.

It may be useful for a guest to know the number of physical host threads
present on the underlying system where it is being run. Add the
characteristic "HostThrs" to the SPLPAR Characteristics
ibm,get_system_parameter rtas call to expose this information to a
guest and provide an implementation which determines this information
based on the number of interrupt servers present in the device tree.

Signed-off-by: Suraj Jitindar Singh 

---

V1 -> V2:
- Take into account that the core may be operating in split core mode
  meaning a single core may be split into multiple subcores.
V2 -> V3:
- Add curly braces for single line if statements
---
 hw/ppc/spapr_rtas.c | 62 +
 1 file changed, 62 insertions(+)

diff --git a/hw/ppc/spapr_rtas.c b/hw/ppc/spapr_rtas.c
index 5bc1a93271..1bab71c90c 100644
--- a/hw/ppc/spapr_rtas.c
+++ b/hw/ppc/spapr_rtas.c
@@ -229,6 +229,58 @@ static inline int sysparm_st(target_ulong addr, 
target_ulong len,
 return RTAS_OUT_SUCCESS;
 }
 
+#define CPUS_PATH   "/proc/device-tree/cpus/"
+#define SUBCORE_PATH"/sys/devices/system/cpu/subcores_per_core"
+
+static int rtas_get_num_host_threads(void)
+{
+int num_threads = -1;
+unsigned long len;
+const char *entry;
+char *buf;
+GDir *dir;
+
+if (!kvm_enabled()) {
+return 1;
+}
+
+/* Read interrupt servers to determine number of threads per core */
+dir = g_dir_open(CPUS_PATH, 0, NULL);
+if (!dir) {
+return -1;
+}
+
+while ((entry = g_dir_read_name(dir))) {
+if (!strncmp(entry, "PowerPC,POWER", strlen("PowerPC,POWER"))) {
+char *path;
+
+path = g_strconcat(CPUS_PATH, entry, "/ibm,ppc-interrupt-server#s",
+   NULL);
+if (g_file_get_contents(path, , , NULL)) {
+num_threads = len / sizeof(int);
+g_free(buf);
+}
+
+g_free(path);
+break;
+}
+}
+
+g_dir_close(dir);
+
+/* Check if split core mode in use */
+if (g_file_get_contents(SUBCORE_PATH, , , NULL)) {
+int subcores = g_ascii_strtoll(buf, NULL, 10);
+
+if (subcores) {
+num_threads /= subcores;
+}
+g_free(buf);
+}
+
+return num_threads;
+}
+
 static void rtas_ibm_get_system_parameter(PowerPCCPU *cpu,
   SpaprMachineState *spapr,
   uint32_t token, uint32_t nargs,
@@ -250,6 +302,16 @@ static void rtas_ibm_get_system_parameter(PowerPCCPU *cpu,
   current_machine->ram_size / MiB,
   smp_cpus,
   max_cpus);
+int num_host_threads = rtas_get_num_host_threads();
+
+if (num_host_threads > 0) {
+char *hostthr_val, *old = param_val;
+
+hostthr_val = g_strdup_printf(",HostThrs=%d", num_host_threads);
+param_val = g_strconcat(param_val, hostthr_val, NULL);
+g_free(hostthr_val);
+g_free(old);
+}
 ret = sysparm_st(buffer, length, param_val, strlen(param_val) + 1);
 g_free(param_val);
 break;
-- 
2.13.6




Re: [Qemu-devel] [QEMU-PPC] [PATCH 1/2] ppc/spapr: Add implementation of hcall H_PURR

2019-06-30 Thread Suraj Jitindar Singh
On Fri, 2019-06-28 at 19:29 +1000, David Gibson wrote:
> On Mon, Jun 24, 2019 at 03:58:11PM +1000, Suraj Jitindar Singh wrote:
> > The hcall H_PURR is used by a guest to read the PURR (processor
> > utilisation of resources register). A guest expects that this
> > register
> > will count at a rate of timebase scaled by the number of guest
> > vcpus
> > present in the vcore. That is the per vcpu purr will count at a
> > rate of
> > timebase / # vcpus per vcore.
> > 
> > Implement a handler for the H_PURR hcall and return the purr value
> > divided by smp_threads so that the sum of the purr deltas across
> > the
> > vcpus of a vcore equals the timebase delta
> > 
> > Signed-off-by: Suraj Jitindar Singh 
> 
> Does this need something new advertised in the hypertas DT entry?

Hi David,

There doesn't seem to be a concensus on what the return value from the
H_PURR hcall should be, whether it just returns the hardware value or
does some adjusting of the value based on guest smt mode as I've
implemented in the patch below.

As such please drop this patch series.

The guest can just read the purr register directly anyway and then
interpret the values as it pleases.

Kind Regards,
Suraj

> 
> > ---
> >  hw/ppc/spapr_hcall.c | 24 
> >  1 file changed, 24 insertions(+)
> > 
> > diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c
> > index aae9fd2b3e..88b3343f04 100644
> > --- a/hw/ppc/spapr_hcall.c
> > +++ b/hw/ppc/spapr_hcall.c
> > @@ -1819,6 +1819,27 @@ static target_ulong h_update_dt(PowerPCCPU
> > *cpu, SpaprMachineState *spapr,
> >  return H_SUCCESS;
> >  }
> >  
> > +static target_ulong h_purr(PowerPCCPU *cpu, SpaprMachineState
> > *spapr,
> > +   target_ulong opcode, target_ulong
> > *args)
> > +{
> > +CPUPPCState *env = >env;
> > +target_ulong purr;
> > +
> > +if (kvm_enabled()) {
> > +cpu_synchronize_state(CPU(cpu));
> > +/*
> > + * Divide by smp_threads so that the sum of the purr
> > deltas across the
> > + * vcpus of a vcore equal the timebase delta.
> > + */
> > +purr = env->spr[SPR_PURR] / smp_threads;
> > +} else {
> > +purr = cpu_ppc_load_purr(env);
> > +}
> > +args[0] = purr;
> > +
> > +return H_SUCCESS;
> > +}
> > +
> >  static spapr_hcall_fn papr_hypercall_table[(MAX_HCALL_OPCODE / 4)
> > + 1];
> >  static spapr_hcall_fn kvmppc_hypercall_table[KVMPPC_HCALL_MAX -
> > KVMPPC_HCALL_BASE + 1];
> >  
> > @@ -1915,6 +1936,9 @@ static void hypercall_register_types(void)
> >  spapr_register_hypercall(H_LOGICAL_DCBF, h_logical_dcbf);
> >  spapr_register_hypercall(KVMPPC_H_LOGICAL_MEMOP,
> > h_logical_memop);
> >  
> > +/* hcall-purr */
> > +spapr_register_hypercall(H_PURR, h_purr);
> > +
> >  /* qemu/KVM-PPC specific hcalls */
> >  spapr_register_hypercall(KVMPPC_H_RTAS, h_rtas);
> >  
> 
> 



[Qemu-devel] [QEMU-PPC] [PATCH v2] powerpc/spapr: Add host threads parameter to ibm, get_system_parameter

2019-06-25 Thread Suraj Jitindar Singh
The ibm,get_system_parameter rtas call is used by the guest to retrieve
data relating to certain parameters of the system. The SPLPAR
characteristics option (token 20) is used to determin characteristics of
the environment in which the lpar will run.

It may be useful for a guest to know the number of physical host threads
present on the underlying system where it is being run. Add the
characteristic "HostThrs" to the SPLPAR Characteristics
ibm,get_system_parameter rtas call to expose this information to a
guest and provide an implementation which determines this information
based on the number of interrupt servers present in the device tree.

Signed-off-by: Suraj Jitindar Singh 

---

V1 -> V2:
- Take into account that the core may be operating in split core mode
  meaning a single core may be split into multiple subcores.
---
 hw/ppc/spapr_rtas.c | 59 +
 1 file changed, 59 insertions(+)

diff --git a/hw/ppc/spapr_rtas.c b/hw/ppc/spapr_rtas.c
index 5bc1a93271..9b15e7606b 100644
--- a/hw/ppc/spapr_rtas.c
+++ b/hw/ppc/spapr_rtas.c
@@ -229,6 +229,55 @@ static inline int sysparm_st(target_ulong addr, 
target_ulong len,
 return RTAS_OUT_SUCCESS;
 }
 
+#define CPUS_PATH   "/proc/device-tree/cpus/"
+#define SUBCORE_PATH"/sys/devices/system/cpu/subcores_per_core"
+
+static int rtas_get_num_host_threads(void)
+{
+int num_threads = -1;
+unsigned long len;
+const char *entry;
+char *buf;
+GDir *dir;
+
+if (!kvm_enabled())
+return 1;
+
+/* Read interrupt servers to determine number of threads per core */
+dir = g_dir_open(CPUS_PATH, 0, NULL);
+if (!dir)
+return -1;
+
+while ((entry = g_dir_read_name(dir))) {
+if (!strncmp(entry, "PowerPC,POWER", strlen("PowerPC,POWER"))) {
+char *path;
+
+path = g_strconcat(CPUS_PATH, entry, "/ibm,ppc-interrupt-server#s",
+   NULL);
+if (g_file_get_contents(path, , , NULL)) {
+num_threads = len / sizeof(int);
+g_free(buf);
+}
+
+g_free(path);
+break;
+}
+}
+
+g_dir_close(dir);
+
+/* Check if split core mode in use */
+if (g_file_get_contents(SUBCORE_PATH, , , NULL)) {
+int subcores = g_ascii_strtoll(buf, NULL, 10);
+
+if (subcores)
+num_threads /= subcores;
+g_free(buf);
+}
+
+return num_threads;
+}
+
 static void rtas_ibm_get_system_parameter(PowerPCCPU *cpu,
   SpaprMachineState *spapr,
   uint32_t token, uint32_t nargs,
@@ -250,6 +299,16 @@ static void rtas_ibm_get_system_parameter(PowerPCCPU *cpu,
   current_machine->ram_size / MiB,
   smp_cpus,
   max_cpus);
+int num_host_threads = rtas_get_num_host_threads();
+
+if (num_host_threads > 0) {
+char *hostthr_val, *old = param_val;
+
+hostthr_val = g_strdup_printf(",HostThrs=%d", num_host_threads);
+param_val = g_strconcat(param_val, hostthr_val, NULL);
+g_free(hostthr_val);
+g_free(old);
+}
 ret = sysparm_st(buffer, length, param_val, strlen(param_val) + 1);
 g_free(param_val);
 break;
-- 
2.13.6




Re: [Qemu-devel] [Qemu-ppc] [QEMU-PPC] [PATCH] powerpc/spapr: Add host threads parameter to ibm, get_system_parameter

2019-06-25 Thread Suraj Jitindar Singh
On Mon, 2019-06-24 at 10:37 +0200, Greg Kurz wrote:
> On Mon, 24 Jun 2019 11:39:21 +1000
> Suraj Jitindar Singh  wrote:
> 
> > The ibm,get_system_parameter rtas call is used by the guest to
> > retrieve
> > data relating to certain parameters of the system. The SPLPAR
> > characteristics option (token 20) is used to determin
> > characteristics of
> > the environment in which the lpar will run.
> > 
> > It may be useful for a guest to know the number of physical host
> > threads
> > present on the underlying system where it is being run. Add the
> > characteristic "HostThrs" to the SPLPAR Characteristics
> > ibm,get_system_parameter rtas call to expose this information to a
> > guest and provide an implementation which determines this
> > information
> > based on the number of interrupt servers present in the device
> > tree.
> > 
> 
> Shouldn't this also take split core into account, ie. divide the
> result by "/sys/devices/system/cpu/subcores_per_core" like the 
> ppc64_cpu command from powerpc-utils does ?

That makes sense, I'll modify the code to account for that.

Thanks,
Suraj

> 
> > Signed-off-by: Suraj Jitindar Singh 
> > ---
> >  hw/ppc/spapr_rtas.c | 44
> > 
> >  1 file changed, 44 insertions(+)
> > 
> > diff --git a/hw/ppc/spapr_rtas.c b/hw/ppc/spapr_rtas.c
> > index 5bc1a93271..a33d87794c 100644
> > --- a/hw/ppc/spapr_rtas.c
> > +++ b/hw/ppc/spapr_rtas.c
> > @@ -229,6 +229,40 @@ static inline int sysparm_st(target_ulong
> > addr, target_ulong len,
> >  return RTAS_OUT_SUCCESS;
> >  }
> >  
> > +static int rtas_get_num_host_threads(void)
> > +{
> > +const char *entry, *name = "/proc/device-tree/cpus/";
> > +int num_threads = -1;
> > +GDir *dir;
> > +
> > +if (!kvm_enabled())
> > +return 1;
> > +
> > +dir = g_dir_open(name, 0, NULL);
> > +if (!dir)
> > +return -1;
> > +
> > +while ((entry = g_dir_read_name(dir))) {
> > +if (!strncmp(entry, "PowerPC,POWER",
> > strlen("PowerPC,POWER"))) {
> > +unsigned long len;
> > +char *path, *buf;
> > +
> > +path = g_strconcat(name, entry, "/ibm,ppc-interrupt-
> > server#s",
> > +   NULL);
> > +if (g_file_get_contents(path, , , NULL)) {
> > +num_threads = len / sizeof(int);
> > +g_free(buf);
> > +}
> > +
> > +g_free(path);
> > +break;
> > +}
> > +}
> > +
> > +g_dir_close(dir);
> > +return num_threads;
> > +}
> > +
> >  static void rtas_ibm_get_system_parameter(PowerPCCPU *cpu,
> >SpaprMachineState
> > *spapr,
> >uint32_t token, uint32_t
> > nargs,
> > @@ -250,6 +284,16 @@ static void
> > rtas_ibm_get_system_parameter(PowerPCCPU *cpu,
> >current_machine-
> > >ram_size / MiB,
> >smp_cpus,
> >max_cpus);
> > +int num_host_threads = rtas_get_num_host_threads();
> > +
> > +if (num_host_threads > 0) {
> > +char *hostthr_val, *old = param_val;
> > +
> > +hostthr_val = g_strdup_printf(",HostThrs=%d",
> > num_host_threads);
> > +param_val = g_strconcat(param_val, hostthr_val, NULL);
> > +g_free(hostthr_val);
> > +g_free(old);
> > +}
> >  ret = sysparm_st(buffer, length, param_val,
> > strlen(param_val) + 1);
> >  g_free(param_val);
> >  break;
> 
> 



[Qemu-devel] [QEMU-PPC] [PATCH 1/2] ppc/spapr: Add implementation of hcall H_PURR

2019-06-24 Thread Suraj Jitindar Singh
The hcall H_PURR is used by a guest to read the PURR (processor
utilisation of resources register). A guest expects that this register
will count at a rate of timebase scaled by the number of guest vcpus
present in the vcore. That is the per vcpu purr will count at a rate of
timebase / # vcpus per vcore.

Implement a handler for the H_PURR hcall and return the purr value
divided by smp_threads so that the sum of the purr deltas across the
vcpus of a vcore equals the timebase delta

Signed-off-by: Suraj Jitindar Singh 
---
 hw/ppc/spapr_hcall.c | 24 
 1 file changed, 24 insertions(+)

diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c
index aae9fd2b3e..88b3343f04 100644
--- a/hw/ppc/spapr_hcall.c
+++ b/hw/ppc/spapr_hcall.c
@@ -1819,6 +1819,27 @@ static target_ulong h_update_dt(PowerPCCPU *cpu, 
SpaprMachineState *spapr,
 return H_SUCCESS;
 }
 
+static target_ulong h_purr(PowerPCCPU *cpu, SpaprMachineState *spapr,
+   target_ulong opcode, target_ulong *args)
+{
+CPUPPCState *env = >env;
+target_ulong purr;
+
+if (kvm_enabled()) {
+cpu_synchronize_state(CPU(cpu));
+/*
+ * Divide by smp_threads so that the sum of the purr deltas across the
+ * vcpus of a vcore equal the timebase delta.
+ */
+purr = env->spr[SPR_PURR] / smp_threads;
+} else {
+purr = cpu_ppc_load_purr(env);
+}
+args[0] = purr;
+
+return H_SUCCESS;
+}
+
 static spapr_hcall_fn papr_hypercall_table[(MAX_HCALL_OPCODE / 4) + 1];
 static spapr_hcall_fn kvmppc_hypercall_table[KVMPPC_HCALL_MAX - 
KVMPPC_HCALL_BASE + 1];
 
@@ -1915,6 +1936,9 @@ static void hypercall_register_types(void)
 spapr_register_hypercall(H_LOGICAL_DCBF, h_logical_dcbf);
 spapr_register_hypercall(KVMPPC_H_LOGICAL_MEMOP, h_logical_memop);
 
+/* hcall-purr */
+spapr_register_hypercall(H_PURR, h_purr);
+
 /* qemu/KVM-PPC specific hcalls */
 spapr_register_hypercall(KVMPPC_H_RTAS, h_rtas);
 
-- 
2.13.6




[Qemu-devel] [QEMU-PPC] [PATCH 2/2] ppc/spapr: Enable H_PURR in-kernel handling

2019-06-24 Thread Suraj Jitindar Singh
Enable in-kernel handling of the hcall H_PURR. This means that if the
kernel implements an hcall handler for H_PURR, it will be used.

Signed-off-by: Suraj Jitindar Singh 
---
 hw/ppc/spapr.c   | 3 +++
 target/ppc/kvm.c | 5 +
 target/ppc/kvm_ppc.h | 5 +
 3 files changed, 13 insertions(+)

diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index 39e698e9b0..b62dce8876 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -2851,6 +2851,9 @@ static void spapr_machine_init(MachineState *machine)
 
 /* Enable H_PAGE_INIT */
 kvmppc_enable_h_page_init();
+
+/* Enable H_PURR */
+kvmppc_enable_h_purr();
 }
 
 /* allocate RAM */
diff --git a/target/ppc/kvm.c b/target/ppc/kvm.c
index 3bf0a46c33..0fd3ef4d48 100644
--- a/target/ppc/kvm.c
+++ b/target/ppc/kvm.c
@@ -2075,6 +2075,11 @@ void kvmppc_enable_h_page_init(void)
 kvmppc_enable_hcall(kvm_state, H_PAGE_INIT);
 }
 
+void kvmppc_enable_h_purr(void)
+{
+kvmppc_enable_hcall(kvm_state, H_PURR);
+}
+
 void kvmppc_set_papr(PowerPCCPU *cpu)
 {
 CPUState *cs = CPU(cpu);
diff --git a/target/ppc/kvm_ppc.h b/target/ppc/kvm_ppc.h
index 45776cad79..b5d2feab22 100644
--- a/target/ppc/kvm_ppc.h
+++ b/target/ppc/kvm_ppc.h
@@ -24,6 +24,7 @@ void kvmppc_enable_logical_ci_hcalls(void);
 void kvmppc_enable_set_mode_hcall(void);
 void kvmppc_enable_clear_ref_mod_hcalls(void);
 void kvmppc_enable_h_page_init(void);
+void kvmppc_enable_h_purr(void);
 void kvmppc_set_papr(PowerPCCPU *cpu);
 int kvmppc_set_compat(PowerPCCPU *cpu, uint32_t compat_pvr);
 void kvmppc_set_mpic_proxy(PowerPCCPU *cpu, int mpic_proxy);
@@ -145,6 +146,10 @@ static inline void kvmppc_enable_h_page_init(void)
 {
 }
 
+static inline void kvmppc_enable_h_purr(void)
+{
+}
+
 static inline void kvmppc_set_papr(PowerPCCPU *cpu)
 {
 }
-- 
2.13.6




[Qemu-devel] [QEMU-PPC] [PATCH] powerpc/spapr: Add host threads parameter to ibm, get_system_parameter

2019-06-23 Thread Suraj Jitindar Singh
The ibm,get_system_parameter rtas call is used by the guest to retrieve
data relating to certain parameters of the system. The SPLPAR
characteristics option (token 20) is used to determin characteristics of
the environment in which the lpar will run.

It may be useful for a guest to know the number of physical host threads
present on the underlying system where it is being run. Add the
characteristic "HostThrs" to the SPLPAR Characteristics
ibm,get_system_parameter rtas call to expose this information to a
guest and provide an implementation which determines this information
based on the number of interrupt servers present in the device tree.

Signed-off-by: Suraj Jitindar Singh 
---
 hw/ppc/spapr_rtas.c | 44 
 1 file changed, 44 insertions(+)

diff --git a/hw/ppc/spapr_rtas.c b/hw/ppc/spapr_rtas.c
index 5bc1a93271..a33d87794c 100644
--- a/hw/ppc/spapr_rtas.c
+++ b/hw/ppc/spapr_rtas.c
@@ -229,6 +229,40 @@ static inline int sysparm_st(target_ulong addr, 
target_ulong len,
 return RTAS_OUT_SUCCESS;
 }
 
+static int rtas_get_num_host_threads(void)
+{
+const char *entry, *name = "/proc/device-tree/cpus/";
+int num_threads = -1;
+GDir *dir;
+
+if (!kvm_enabled())
+return 1;
+
+dir = g_dir_open(name, 0, NULL);
+if (!dir)
+return -1;
+
+while ((entry = g_dir_read_name(dir))) {
+if (!strncmp(entry, "PowerPC,POWER", strlen("PowerPC,POWER"))) {
+unsigned long len;
+char *path, *buf;
+
+path = g_strconcat(name, entry, "/ibm,ppc-interrupt-server#s",
+   NULL);
+if (g_file_get_contents(path, , , NULL)) {
+num_threads = len / sizeof(int);
+g_free(buf);
+}
+
+g_free(path);
+break;
+}
+}
+
+g_dir_close(dir);
+return num_threads;
+}
+
 static void rtas_ibm_get_system_parameter(PowerPCCPU *cpu,
   SpaprMachineState *spapr,
   uint32_t token, uint32_t nargs,
@@ -250,6 +284,16 @@ static void rtas_ibm_get_system_parameter(PowerPCCPU *cpu,
   current_machine->ram_size / MiB,
   smp_cpus,
   max_cpus);
+int num_host_threads = rtas_get_num_host_threads();
+
+if (num_host_threads > 0) {
+char *hostthr_val, *old = param_val;
+
+hostthr_val = g_strdup_printf(",HostThrs=%d", num_host_threads);
+param_val = g_strconcat(param_val, hostthr_val, NULL);
+g_free(hostthr_val);
+g_free(old);
+}
 ret = sysparm_st(buffer, length, param_val, strlen(param_val) + 1);
 g_free(param_val);
 break;
-- 
2.13.6




Re: [Qemu-devel] [PATCH 1/2] monitor: Add dump-stack command

2019-06-20 Thread Suraj Jitindar Singh
On Wed, 2019-05-01 at 15:35 +1000, Suraj Jitindar Singh wrote:
> Add a monitor command "dump-stack" to be used to dump the stack for
> the
> current cpu.

To summarise the discussion which occured on this patch,

- It looks like it's ok to duplicate this functionality as it provides
an easier method to achieve this in the field and also for development.
- It's ok for this to remain as a separate command and to not place it
as a subcommand under info.

I'll rework based on the comments on 2/2 of the series and resend.

Thanks,
Suraj

> 
> Signed-off-by: Suraj Jitindar Singh 
> ---
>  hmp-commands.hx   | 13 +
>  hmp.h |  1 +
>  include/qom/cpu.h | 10 ++
>  monitor.c | 12 
>  qom/cpu.c | 10 ++
>  5 files changed, 46 insertions(+)
> 
> diff --git a/hmp-commands.hx b/hmp-commands.hx
> index 9b4035965c..965ccdea28 100644
> --- a/hmp-commands.hx
> +++ b/hmp-commands.hx
> @@ -862,6 +862,19 @@ ETEXI
>  },
>  
>  STEXI
> +@item dump-stack
> +@findex dump-stack
> +dump stack of the cpu
> +ETEXI
> +{
> +.name   = "dump-stack",
> +.args_type  = "",
> +.params = "",
> +.help   = "dump stack",
> +.cmd= hmp_dumpstack,
> +},
> +
> +STEXI
>  @item pmemsave @var{addr} @var{size} @var{file}
>  @findex pmemsave
>  save to disk physical memory dump starting at @var{addr} of size
> @var{size}.
> diff --git a/hmp.h b/hmp.h
> index 43617f2646..e6edf1215c 100644
> --- a/hmp.h
> +++ b/hmp.h
> @@ -51,6 +51,7 @@ void hmp_announce_self(Monitor *mon, const QDict
> *qdict);
>  void hmp_cpu(Monitor *mon, const QDict *qdict);
>  void hmp_memsave(Monitor *mon, const QDict *qdict);
>  void hmp_pmemsave(Monitor *mon, const QDict *qdict);
> +void hmp_dumpstack(Monitor *mon, const QDict *qdict);
>  void hmp_ringbuf_write(Monitor *mon, const QDict *qdict);
>  void hmp_ringbuf_read(Monitor *mon, const QDict *qdict);
>  void hmp_cont(Monitor *mon, const QDict *qdict);
> diff --git a/include/qom/cpu.h b/include/qom/cpu.h
> index 08abcbd3fe..f2e83e9918 100644
> --- a/include/qom/cpu.h
> +++ b/include/qom/cpu.h
> @@ -181,6 +181,7 @@ typedef struct CPUClass {
>  int (*memory_rw_debug)(CPUState *cpu, vaddr addr,
> uint8_t *buf, int len, bool is_write);
>  void (*dump_state)(CPUState *cpu, FILE *, int flags);
> +void (*dump_stack)(CPUState *cpu, FILE *f);
>  GuestPanicInformation* (*get_crash_info)(CPUState *cpu);
>  void (*dump_statistics)(CPUState *cpu, int flags);
>  int64_t (*get_arch_id)(CPUState *cpu);
> @@ -568,6 +569,15 @@ enum CPUDumpFlags {
>  void cpu_dump_state(CPUState *cpu, FILE *f, int flags);
>  
>  /**
> + * cpu_dump_stack:
> + * @cpu: The CPU whose stack is to be dumped.
> + * @f: If non-null, dump to this stream, else to current print sink.
> + *
> + * Dumps CPU stack.
> + */
> +void cpu_dump_stack(CPUState *cpu, FILE *f);
> +
> +/**
>   * cpu_dump_statistics:
>   * @cpu: The CPU whose state is to be dumped.
>   * @flags: Flags what to dump.
> diff --git a/monitor.c b/monitor.c
> index 9b5f10b475..dbec2e4376 100644
> --- a/monitor.c
> +++ b/monitor.c
> @@ -1299,6 +1299,18 @@ static void hmp_info_registers(Monitor *mon,
> const QDict *qdict)
>  }
>  }
>  
> +void hmp_dumpstack(Monitor *mon, const QDict *qdict)
> +{
> +CPUState *cs = mon_get_cpu();
> +
> +if (!cs) {
> +monitor_printf(mon, "No CPU available\n");
> +return;
> +}
> +
> +cpu_dump_stack(cs, NULL);
> +}
> +
>  #ifdef CONFIG_TCG
>  static void hmp_info_jit(Monitor *mon, const QDict *qdict)
>  {
> diff --git a/qom/cpu.c b/qom/cpu.c
> index 3c5493c96c..0dc10004f4 100644
> --- a/qom/cpu.c
> +++ b/qom/cpu.c
> @@ -230,6 +230,16 @@ void cpu_dump_state(CPUState *cpu, FILE *f, int
> flags)
>  }
>  }
>  
> +void cpu_dump_stack(CPUState *cpu, FILE *f)
> +{
> +CPUClass *cc = CPU_GET_CLASS(cpu);
> +
> +if (cc->dump_stack) {
> +cpu_synchronize_state(cpu);
> +cc->dump_stack(cpu, f);
> +}
> +}
> +
>  void cpu_dump_statistics(CPUState *cpu, int flags)
>  {
>  CPUClass *cc = CPU_GET_CLASS(cpu);



[Qemu-devel] [PATCH] target/ppc: Set PSSCR_EC on cpu halt to prevent spurious wakeup

2019-05-15 Thread Suraj Jitindar Singh
The processor stop status and control register (PSSCR) is used to
control the power saving facilities of the thread. The exit criterion
bit (EC) is used to specify whether the thread should be woken by any
interrupt (EC == 0) or only an interrupt enabled in the LPCR to wake the
thread (EC == 1).

The rtas facilities start-cpu and self-stop are used to transition a
vcpu between the stopped and running states. When a vcpu is stopped it
may only be started again by the start-cpu rtas call.

Currently a vcpu in the stopped state will start again whenever an
interrupt comes along due to PSSCR_EC being cleared, and while this is
architecturally correct for a hardware thread, a vcpu is expected to
only be woken by calling start-cpu. This means when performing a reboot
on a tcg machine that the secondary threads will restart while the
primary is still in slof, this is unsupported and causes call traces
like:

SLOF **
QEMU Starting
 Build Date = Jan 14 2019 18:00:39
 FW Version = git-a5b428e1c1eae703
 Press "s" to enter Open Firmware.

qemu: fatal: Trying to deliver HV exception (MSR) 70 with no HV support

NIP 6d61676963313230   LR 3dbe0308 CTR 6d61676963313233 XER 
 CPU#1
MSR  HID0   HF  iidx 3 didx 3
TB 0026 115746031956 DECR 18446744073326238463
GPR00 3dbe0308 3e669fe0 3dc10700 0003
GPR04 3dc62198 3dc62178 3dc0ea48 0030
GPR08 3dc621a8 0018 3e466008 3dc50700
GPR12 c093a4e0 c0003300 c0003e533f90 
GPR16   3e466010 3dc0b040
GPR20 8000 f003 0006 3e66a050
GPR24 3dc06400 3dc0ae70 0003 f001
GPR28 3e66a060  6d61676963313233 0028
CR 28000222  [ E  L  -  -  -  E  E  E  ] RES 
FPR00    
FPR04    
FPR08    311825e0
FPR12 311825e0   
FPR16    
FPR20    
FPR24    
FPR28    
FPSCR 
 SRR0 3dbe06b0  SRR1 0008PVR 004e1200 VRSAVE 

SPRG0 3dbe0308 SPRG1 3e669fe0  SPRG2 00d8  SPRG3 
3dbe0308
SPRG4  SPRG5   SPRG6   SPRG7 

HSRR0 6d61676963313230 HSRR1 
 CFAR 3dbe3e64
 LPCR 04020008
 PTCR    DAR   DSISR 
Aborted (core dumped)

To fix this, set the PSSCR_EC bit when a vcpu is stopped to disable it
from coming back online until the start-cpu rtas call is made.

Fixes: 21c0d66a9c99 ("target/ppc: Fix support for "STOP light" states on 
POWER9")

Signed-off-by: Suraj Jitindar Singh 
---
 hw/ppc/spapr_cpu_core.c | 2 ++
 hw/ppc/spapr_rtas.c | 6 +-
 2 files changed, 7 insertions(+), 1 deletion(-)

diff --git a/hw/ppc/spapr_cpu_core.c b/hw/ppc/spapr_cpu_core.c
index f04e06cdf6..5621fb9a3d 100644
--- a/hw/ppc/spapr_cpu_core.c
+++ b/hw/ppc/spapr_cpu_core.c
@@ -58,9 +58,11 @@ static void spapr_cpu_reset(void *opaque)
  *
  * Disable Power-saving mode Exit Cause exceptions for the CPU, so
  * we don't get spurious wakups before an RTAS start-cpu call.
+ * For the same reason, set PSSCR_EC.
  */
 lpcr &= ~(LPCR_VPM0 | LPCR_VPM1 | LPCR_ISL | LPCR_KBV | pcc->lpcr_pm);
 lpcr |= LPCR_LPES0 | LPCR_LPES1;
+env->spr[SPR_PSSCR] |= PSSCR_EC;
 
 /* Set RMLS to the max (ie, 16G) */
 lpcr &= ~LPCR_RMLS;
diff --git a/hw/ppc/spapr_rtas.c b/hw/ppc/spapr_rtas.c
index ee24212765..5bc1a93271 100644
--- a/hw/ppc/spapr_rtas.c
+++ b/hw/ppc/spapr_rtas.c
@@ -177,6 +177,7 @@ static void rtas_start_cpu(PowerPCCPU *callcpu, 
SpaprMachineState *spapr,
 } else {
 lpcr &= ~(LPCR_UPRT | LPCR_GTSE | LPCR_HR);
 }
+env->spr[SPR_PSSCR] &= ~PSSCR_EC;
 }
 ppc_store_lpcr(newcpu, lpcr);
 
@@ -205,8 +206,11 @@ static void rtas_stop_self(PowerPCCPU *cpu, 
SpaprMachineState *spapr,
 
 /* Disable Power-saving mode Exit Cause exceptions for the CPU.
  * This could deliver an interrupt on a dying CPU and crash the
- * guest */
+ * guest.
+ * For the same reason, set PSSCR_EC.
+ */
 ppc_store_lpcr(cpu, env-&

Re: [Qemu-devel] [QEMU-PPC] [PATCH 02/13] target/ppc: Work [S]PURR implementation and add HV support

2019-05-06 Thread Suraj Jitindar Singh
On Mon, 2019-05-06 at 16:15 +1000, David Gibson wrote:
> On Fri, May 03, 2019 at 03:53:05PM +1000, Suraj Jitindar Singh wrote:
> > The Processor Utilisation of Resources Register (PURR) and Scaled
> > Processor Utilisation of Resources Register (SPURR) provide an
> > estimate
> > of the resources used by the thread, present on POWER7 and later
> > processors.
> > 
> > Currently the [S]PURR registers simply count at the rate of the
> > timebase.
> > 
> > Preserve this behaviour but rework the implementation to store an
> > offset
> > like the timebase rather than doing the calculation manually. Also
> > allow
> > hypervisor write access to the register along with the currently
> > available read access.
> > 
> > Signed-off-by: Suraj Jitindar Singh 
> 
> Hm.  How will this affect migration of the PURR and SPURR?

So as it turns out, the PURR isn't acutually migrated. We rely on the
fact that the QEMU_CLOCK_VIRTUAL is migrated and that the PURR can
never change value. Since it just counts at the same rate as the time
base we get away with it.

For this to work we will need to add PURR, and VTB for the later patch
which adds it to the migration stream. I suggest me just migrate by
value meaning the internal representation can infact change in future
without breaking migration.

What this means is that this patch changing the internal representation
if fine given migration is broken anyway. When I resend this series
I'll add the purr and vtb to the migration stream.

> 
> > ---
> >  /ppc/ppc.c| 17 +++--
> >  include/hw/ppc/ppc.h|  3 +--
> >  target/ppc/cpu.h|  1 +
> >  target/ppc/helper.h |  1 +
> >  target/ppc/timebase_helper.c|  5 +
> >  target/ppc/translate_init.inc.c | 23 +++
> >  6 files changed, 30 insertions(+), 20 deletions(-)
> > 
> > diff --git a/hw/ppc/ppc.c b/hw/ppc/ppc.c
> > index a57ca64626..b567156f97 100644
> > --- a/hw/ppc/ppc.c
> > +++ b/hw/ppc/ppc.c
> > @@ -819,12 +819,9 @@ target_ulong cpu_ppc_load_hdecr (CPUPPCState
> > *env)
> >  uint64_t cpu_ppc_load_purr (CPUPPCState *env)
> >  {
> >  ppc_tb_t *tb_env = env->tb_env;
> > -uint64_t diff;
> >  
> > -diff = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) - tb_env-
> > >purr_start;
> > -
> > -return tb_env->purr_load +
> > -muldiv64(diff, tb_env->tb_freq, NANOSECONDS_PER_SECOND);
> > +return cpu_ppc_get_tb(tb_env,
> > qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL),
> > +  tb_env->purr_offset);
> >  }
> >  
> >  /* When decrementer expires,
> > @@ -980,12 +977,12 @@ static void cpu_ppc_hdecr_cb(void *opaque)
> >  cpu_ppc_hdecr_excp(cpu);
> >  }
> >  
> > -static void cpu_ppc_store_purr(PowerPCCPU *cpu, uint64_t value)
> > +void cpu_ppc_store_purr(CPUPPCState *env, uint64_t value)
> >  {
> > -ppc_tb_t *tb_env = cpu->env.tb_env;
> > +ppc_tb_t *tb_env = env->tb_env;
> >  
> > -tb_env->purr_load = value;
> > -tb_env->purr_start = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
> > +cpu_ppc_store_tb(tb_env,
> > qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL),
> > + _env->purr_offset, value);
> >  }
> >  
> >  static void cpu_ppc_set_tb_clk (void *opaque, uint32_t freq)
> > @@ -1002,7 +999,7 @@ static void cpu_ppc_set_tb_clk (void *opaque,
> > uint32_t freq)
> >   */
> >  _cpu_ppc_store_decr(cpu, 0x, 0x, 32);
> >  _cpu_ppc_store_hdecr(cpu, 0x, 0x, 32);
> > -cpu_ppc_store_purr(cpu, 0xULL);
> > +cpu_ppc_store_purr(env, 0xULL);
> >  }
> >  
> >  static void timebase_save(PPCTimebase *tb)
> > diff --git a/include/hw/ppc/ppc.h b/include/hw/ppc/ppc.h
> > index 205150e6b4..b09ffbf300 100644
> > --- a/include/hw/ppc/ppc.h
> > +++ b/include/hw/ppc/ppc.h
> > @@ -32,8 +32,7 @@ struct ppc_tb_t {
> >  /* Hypervisor decrementer management */
> >  uint64_t hdecr_next;/* Tick for next hdecr interrupt  */
> >  QEMUTimer *hdecr_timer;
> > -uint64_t purr_load;
> > -uint64_t purr_start;
> > +int64_t purr_offset;
> >  void *opaque;
> >  uint32_t flags;
> >  };
> > diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
> > index 70167bae22..19b3e1de0e 100644
> > --- a/target/ppc/cpu.h
> > +++ b/target/ppc/cpu.h
> > @@ -1335,6 +1335,7 @@ void cpu_ppc_store_decr (CPUPPCState *env,
> > target_

Re: [Qemu-devel] [QEMU-PPC] [PATCH 00/13] target/ppc: Implement KVM support under TCG

2019-05-06 Thread Suraj Jitindar Singh
On Mon, 2019-05-06 at 16:20 +1000, David Gibson wrote:
> On Fri, May 03, 2019 at 03:53:03PM +1000, Suraj Jitindar Singh wrote:
> > This patch series adds the necessary parts so that a tcg guest is
> > able to use
> > kvm facilities. That is a tcg guest can boot its own kvm guests.
> 
> The topic line is a bit hard to parse.  IIUC there are basically two
> things in this series:
> 
> 1) Implement / fix TCG emulation of TCG hypervisor facilities, so
> that
>a TCG powernv machine can use them to run KVM guests.
> 
> 2) Have the pseries machine under TCG implement the paravirtualized
>interfaces to allow nested virtualizationm therefore allowing TCG
>pseries machines to run KVM guests
> 
> Is that right?

That is correct.

Patches 1-7 achieve 1) TCG emulation of hypervisor facilities

Patches 8-13 achieve 2) emulation of paravirtualised KVM for pseries
guest

> 
> > The main requirements for this were a few registers and
> > instructions as well as
> > some hcalls and the addition of partition scoped translation in the
> > radix mmu
> > emulation.
> > 
> > This can be used to boot a kvm guest under a pseries tcg guest:
> > Use power9_v2.2 cpu and add -machine cap-nested-hv=on for the first
> > guest.
> > Then inside that guest boot a kvm guest as normal.
> > This takes advantage of the new hcalls with qemu emulating them as
> > a normal
> > hypervisor would on a real machine.
> > 
> > This can also be used to boot a kvm guest under a powernv tcg
> > guest:
> > Use any power9 cpu type.
> > This takes advantage of the new hv register access added.
> > Note that for powernv there is no xive interrupt excalation for KVM
> > which means
> > that while the guest will boot, it won't receive any interrupts.
> > 
> > Suraj Jitindar Singh (13):
> >   target/ppc: Implement the VTB for HV access
> >   target/ppc: Work [S]PURR implementation and add HV support
> >   target/ppc: Add SPR ASDR
> >   target/ppc: Add SPR TBU40
> >   target/ppc: Add privileged message send facilities
> >   target/ppc: Enforce that the root page directory size must be at
> > least
> > 5
> >   target/ppc: Handle partition scoped radix tree translation
> >   target/ppc: Implement hcall H_SET_PARTITION_TABLE
> >   target/ppc: Implement hcall H_ENTER_NESTED
> >   target/ppc: Implement hcall H_TLB_INVALIDATE
> >   target/ppc: Implement hcall H_COPY_TOFROM_GUEST
> >   target/ppc: Introduce POWER9 DD2.2 cpu type
> >   target/ppc: Enable SPAPR_CAP_NESTED_KVM_HV under tcg
> > 
> >  hw/ppc/ppc.c|  46 -
> >  hw/ppc/spapr_caps.c |  22 ++-
> >  hw/ppc/spapr_cpu_core.c |   1 +
> >  hw/ppc/spapr_hcall.c| 409
> > +++
> >  include/hw/ppc/ppc.h|   4 +-
> >  include/hw/ppc/spapr.h  |   7 +-
> >  linux-user/ppc/cpu_loop.c   |   5 +
> >  target/ppc/cpu-models.c |   2 +
> >  target/ppc/cpu-models.h |   1 +
> >  target/ppc/cpu.h|  70 +++
> >  target/ppc/excp_helper.c|  79 +++-
> >  target/ppc/helper.h |   9 +
> >  target/ppc/misc_helper.c|  46 +
> >  target/ppc/mmu-radix64.c| 412
> > 
> >  target/ppc/mmu-radix64.h|   4 +
> >  target/ppc/timebase_helper.c|  20 ++
> >  target/ppc/translate.c  |  28 +++
> >  target/ppc/translate_init.inc.c | 107 +--
> >  18 files changed, 1115 insertions(+), 157 deletions(-)
> > 
> 
> 



Re: [Qemu-devel] [QEMU-PPC] [PATCH] target/ppc: Add ibm, purr and ibm, spurr device-tree properties

2019-05-06 Thread Suraj Jitindar Singh
On Mon, 2019-05-06 at 13:23 +1000, David Gibson wrote:
> On Mon, May 06, 2019 at 11:48:03AM +1000, Suraj Jitindar Singh wrote:
> > The ibm,purr and ibm,spurr device tree properties are used to
> > indicate
> > that the processor implements the Processor Utilisation of
> > Resources
> > Register (PURR) and Scaled Processor Utilisation of Resources
> > Registers
> > (SPURR), respectively. Each property has a single value which
> > represents
> > the level of architecture supported. A value of 1 for ibm,purr
> > means
> > support for the version of the PURR defined in book 3 in version
> > 2.02 of
> > the architecture. A value of 1 for ibm,spurr means support for the
> > version of the SPURR defined in version 2.05 of the architecture.
> > 
> > Add these properties for all processors for which the PURR and
> > SPURR
> > registers are generated.
> 
> So.. what does the current empty property mean?  Is it just wrong by
> spec, or does it actually mean something incorrect?

Af far as I can tell, an empty property is invalid according to PAPR.
A level value is required to communicate the level of purr implemented.

Should probably have:

Fixes: 0da6f3fef9a "spapr: Reorganize CPU dt generation code"

> 
> > 
> > Signed-off-by: Suraj Jitindar Singh 
> > ---
> >  hw/ppc/spapr.c | 5 -
> >  1 file changed, 4 insertions(+), 1 deletion(-)
> > 
> > diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
> > index 2ef3ce4362..8580a8dc67 100644
> > --- a/hw/ppc/spapr.c
> > +++ b/hw/ppc/spapr.c
> > @@ -500,7 +500,10 @@ static void spapr_populate_cpu_dt(CPUState
> > *cs, void *fdt, int offset,
> >  _FDT((fdt_setprop(fdt, offset, "64-bit", NULL, 0)));
> >  
> >  if (env->spr_cb[SPR_PURR].oea_read) {
> > -_FDT((fdt_setprop(fdt, offset, "ibm,purr", NULL, 0)));
> > +_FDT((fdt_setprop_cell(fdt, offset, "ibm,purr", 1)));
> > +}
> > +if (env->spr_cb[SPR_SPURR].oea_read) {
> > +_FDT((fdt_setprop_cell(fdt, offset, "ibm,spurr", 1)));
> >  }
> >  
> >  if (ppc_hash64_has(cpu, PPC_HASH64_1TSEG)) {
> 
> 



[Qemu-devel] [QEMU-PPC] [PATCH] target/ppc: Add ibm, purr and ibm, spurr device-tree properties

2019-05-05 Thread Suraj Jitindar Singh
The ibm,purr and ibm,spurr device tree properties are used to indicate
that the processor implements the Processor Utilisation of Resources
Register (PURR) and Scaled Processor Utilisation of Resources Registers
(SPURR), respectively. Each property has a single value which represents
the level of architecture supported. A value of 1 for ibm,purr means
support for the version of the PURR defined in book 3 in version 2.02 of
the architecture. A value of 1 for ibm,spurr means support for the
version of the SPURR defined in version 2.05 of the architecture.

Add these properties for all processors for which the PURR and SPURR
registers are generated.

Signed-off-by: Suraj Jitindar Singh 
---
 hw/ppc/spapr.c | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index 2ef3ce4362..8580a8dc67 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -500,7 +500,10 @@ static void spapr_populate_cpu_dt(CPUState *cs, void *fdt, 
int offset,
 _FDT((fdt_setprop(fdt, offset, "64-bit", NULL, 0)));
 
 if (env->spr_cb[SPR_PURR].oea_read) {
-_FDT((fdt_setprop(fdt, offset, "ibm,purr", NULL, 0)));
+_FDT((fdt_setprop_cell(fdt, offset, "ibm,purr", 1)));
+}
+if (env->spr_cb[SPR_SPURR].oea_read) {
+_FDT((fdt_setprop_cell(fdt, offset, "ibm,spurr", 1)));
 }
 
 if (ppc_hash64_has(cpu, PPC_HASH64_1TSEG)) {
-- 
2.13.6




[Qemu-devel] [QEMU-PPC] [PATCH 06/13] target/ppc: Enforce that the root page directory size must be at least 5

2019-05-03 Thread Suraj Jitindar Singh
According to the ISA the root page directory size of a radix tree for
either process or partition scoped translation must be >= 5.

Thus add this to the list of conditions checked when validating the
partition table entry in validate_pate();

Signed-off-by: Suraj Jitindar Singh 
---
 target/ppc/mmu-radix64.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/target/ppc/mmu-radix64.c b/target/ppc/mmu-radix64.c
index a6ab290323..afa5ba506a 100644
--- a/target/ppc/mmu-radix64.c
+++ b/target/ppc/mmu-radix64.c
@@ -249,6 +249,8 @@ static bool validate_pate(PowerPCCPU *cpu, uint64_t lpid, 
ppc_v3_pate_t *pate)
 if (lpid == 0 && !msr_hv) {
 return false;
 }
+if ((pate->dw0 & PATE1_R_PRTS) < 5)
+return false;
 /* More checks ... */
 return true;
 }
-- 
2.13.6




[Qemu-devel] [QEMU-PPC] [PATCH 09/13] target/ppc: Implement hcall H_ENTER_NESTED

2019-05-03 Thread Suraj Jitindar Singh
The hcall H_ENTER_NESTED is used by a guest acting as a nested
hypervisor to provide the state of one of its guests which it would
like the real hypervisor to load onto the cpu and execute on its behalf.

The hcall takes as arguments 2 guest real addresses which provide the
location of a regs struct and a hypervisor regs struct which provide the
values to use to execute the guest. These are loaded into the cpu state
and then the function returns to continue tcg execution in the new
context. When an interrupt requires us to context switch back we restore
the old register values and save the cpu state back into the guest
memory.

Signed-off-by: Suraj Jitindar Singh 
---
 hw/ppc/spapr_hcall.c | 285 +++
 include/hw/ppc/spapr.h   |   3 +-
 target/ppc/cpu.h |  55 +
 target/ppc/excp_helper.c |  13 ++-
 4 files changed, 353 insertions(+), 3 deletions(-)

diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c
index 704ceff8e1..68f3282214 100644
--- a/hw/ppc/spapr_hcall.c
+++ b/hw/ppc/spapr_hcall.c
@@ -16,6 +16,7 @@
 #include "hw/ppc/spapr_ovec.h"
 #include "mmu-book3s-v3.h"
 #include "hw/mem/memory-device.h"
+#include "hw/ppc/ppc.h"
 
 static bool has_spr(PowerPCCPU *cpu, int spr)
 {
@@ -1847,6 +1848,289 @@ static target_ulong h_set_partition_table(PowerPCCPU 
*cpu,
 return H_SUCCESS;
 }
 
+static void byteswap_pt_regs(struct pt_regs *regs)
+{
+target_ulong *addr = (target_ulong *) regs;
+
+for (; addr < ((target_ulong *) (regs + 1)); addr++) {
+*addr = bswap64(*addr);
+}
+}
+
+static void byteswap_hv_regs(struct hv_guest_state *hr)
+{
+hr->version = bswap64(hr->version);
+hr->lpid = bswap32(hr->lpid);
+hr->vcpu_token = bswap32(hr->vcpu_token);
+hr->lpcr = bswap64(hr->lpcr);
+hr->pcr = bswap64(hr->pcr);
+hr->amor = bswap64(hr->amor);
+hr->dpdes = bswap64(hr->dpdes);
+hr->hfscr = bswap64(hr->hfscr);
+hr->tb_offset = bswap64(hr->tb_offset);
+hr->dawr0 = bswap64(hr->dawr0);
+hr->dawrx0 = bswap64(hr->dawrx0);
+hr->ciabr = bswap64(hr->ciabr);
+hr->hdec_expiry = bswap64(hr->hdec_expiry);
+hr->purr = bswap64(hr->purr);
+hr->spurr = bswap64(hr->spurr);
+hr->ic = bswap64(hr->ic);
+hr->vtb = bswap64(hr->vtb);
+hr->hdar = bswap64(hr->hdar);
+hr->hdsisr = bswap64(hr->hdsisr);
+hr->heir = bswap64(hr->heir);
+hr->asdr = bswap64(hr->asdr);
+hr->srr0 = bswap64(hr->srr0);
+hr->srr1 = bswap64(hr->srr1);
+hr->sprg[0] = bswap64(hr->sprg[0]);
+hr->sprg[1] = bswap64(hr->sprg[1]);
+hr->sprg[2] = bswap64(hr->sprg[2]);
+hr->sprg[3] = bswap64(hr->sprg[3]);
+hr->pidr = bswap64(hr->pidr);
+hr->cfar = bswap64(hr->cfar);
+hr->ppr = bswap64(hr->ppr);
+}
+
+static void save_regs(PowerPCCPU *cpu, struct pt_regs *regs)
+{
+CPUPPCState env = cpu->env;
+int i;
+
+for (i = 0; i < 32; i++)
+regs->gpr[i] = env.gpr[i];
+regs->nip = env.nip;
+regs->msr = env.msr;
+regs->ctr = env.ctr;
+regs->link = env.lr;
+regs->xer = env.xer;
+regs->ccr = 0UL;
+for (i = 0; i < 8; i++)
+regs->ccr |= ((env.crf[i] & 0xF) << ((7 - i) * 4));
+regs->dar = env.spr[SPR_DAR];
+regs->dsisr = env.spr[SPR_DSISR];
+}
+
+static void save_hv_regs(PowerPCCPU *cpu, struct hv_guest_state *hv_regs)
+{
+CPUPPCState env = cpu->env;
+
+hv_regs->lpid = env.spr[SPR_LPIDR];
+hv_regs->lpcr = env.spr[SPR_LPCR];
+hv_regs->pcr = env.spr[SPR_PCR];
+hv_regs->amor = env.spr[SPR_AMOR];
+hv_regs->dpdes = !!(env.pending_interrupts & (1 << 
PPC_INTERRUPT_DOORBELL));
+hv_regs->hfscr = env.spr[SPR_HFSCR];
+hv_regs->tb_offset = env.tb_env->tb_offset;
+hv_regs->dawr0 = env.spr[SPR_DAWR];
+hv_regs->dawrx0 = env.spr[SPR_DAWRX];
+hv_regs->ciabr = env.spr[SPR_CIABR];
+hv_regs->purr = cpu_ppc_load_purr();
+hv_regs->spurr = cpu_ppc_load_purr();
+hv_regs->ic = env.spr[SPR_IC];
+hv_regs->vtb = cpu_ppc_load_vtb();
+hv_regs->hdar = env.spr[SPR_HDAR];
+hv_regs->hdsisr = env.spr[SPR_HDSISR];
+hv_regs->asdr = env.spr[SPR_ASDR];
+hv_regs->srr0 = env.spr[SPR_SRR0];
+hv_regs->srr1 = env.spr[SPR_SRR1];
+hv_regs->sprg[0] = env.spr[SPR_SPRG0];
+hv_regs->sprg[1] = env.spr[SPR_SPRG1];
+hv_regs->sprg[2] = env.spr[SPR_SPRG2];
+hv_regs->sprg[3] = env.spr[SPR_SPRG3];
+hv_regs->pidr = env.spr[SPR_BOOKS_PID];
+hv_regs->cfar = env.cfar;
+hv_regs->ppr = env.spr[SPR_PPR];
+}
+
+static void restore_regs(PowerPCCPU *cpu, struct pt_regs regs)
+{
+CPUPPCState *env = >env;
+int i;
+
+for (i = 

[Qemu-devel] [QEMU-PPC] [PATCH 08/13] target/ppc: Implement hcall H_SET_PARTITION_TABLE

2019-05-03 Thread Suraj Jitindar Singh
The hcall H_SET_PARTITION_TABLE is used by a guest acting as a nested
hypervisor to register the partition table entry for one of its guests
with the real hypervisor.

Implement this hcall for a spapr guest.

Signed-off-by: Suraj Jitindar Singh 
---
 hw/ppc/spapr_hcall.c   | 22 ++
 include/hw/ppc/spapr.h |  4 +++-
 2 files changed, 25 insertions(+), 1 deletion(-)

diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c
index 4d7fe337a1..704ceff8e1 100644
--- a/hw/ppc/spapr_hcall.c
+++ b/hw/ppc/spapr_hcall.c
@@ -1828,6 +1828,25 @@ static target_ulong h_update_dt(PowerPCCPU *cpu, 
SpaprMachineState *spapr,
 return H_SUCCESS;
 }
 
+static target_ulong h_set_partition_table(PowerPCCPU *cpu,
+  SpaprMachineState *spapr,
+  target_ulong opcode,
+  target_ulong *args)
+{
+CPUPPCState *env = >env;
+target_ulong ptcr = args[0];
+
+if (spapr_get_cap(spapr, SPAPR_CAP_NESTED_KVM_HV) == 0) {
+return H_FUNCTION;
+}
+
+if ((ptcr & PTCR_PATS) > 24)
+return H_PARAMETER;
+
+env->spr[SPR_PTCR] = ptcr;
+return H_SUCCESS;
+}
+
 static spapr_hcall_fn papr_hypercall_table[(MAX_HCALL_OPCODE / 4) + 1];
 static spapr_hcall_fn kvmppc_hypercall_table[KVMPPC_HCALL_MAX - 
KVMPPC_HCALL_BASE + 1];
 
@@ -1934,6 +1953,9 @@ static void hypercall_register_types(void)
 
 spapr_register_hypercall(KVMPPC_H_UPDATE_DT, h_update_dt);
 
+/* Platform-specific hcalls used for nested HV KVM */
+spapr_register_hypercall(H_SET_PARTITION_TABLE, h_set_partition_table);
+
 /* Virtual Processor Home Node */
 spapr_register_hypercall(H_HOME_NODE_ASSOCIATIVITY,
  h_home_node_associativity);
diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
index 4251215908..e591ee0ba0 100644
--- a/include/hw/ppc/spapr.h
+++ b/include/hw/ppc/spapr.h
@@ -501,7 +501,9 @@ struct SpaprMachineState {
 /* Client Architecture support */
 #define KVMPPC_H_CAS(KVMPPC_HCALL_BASE + 0x2)
 #define KVMPPC_H_UPDATE_DT  (KVMPPC_HCALL_BASE + 0x3)
-#define KVMPPC_HCALL_MAXKVMPPC_H_UPDATE_DT
+/* Platform-specific hcalls used for nested HV KVM */
+#define H_SET_PARTITION_TABLE   0xF800
+#define KVMPPC_HCALL_MAXH_SET_PARTITION_TABLE
 
 typedef struct SpaprDeviceTreeUpdateHeader {
 uint32_t version_id;
-- 
2.13.6




[Qemu-devel] [QEMU-PPC] [PATCH 13/13] target/ppc: Enable SPAPR_CAP_NESTED_KVM_HV under tcg

2019-05-03 Thread Suraj Jitindar Singh
It is now possible to use nested kvm-hv under tcg, thus allow for it to
be enabled.

Note that nested kvm-hv requires that rc updates to ptes be done by
software, otherwise the page tables get out of sync. So disable hardware
rc updates when nested kvm-hv is enabled.

Signed-off-by: Suraj Jitindar Singh 
---
 hw/ppc/spapr_caps.c  | 22 ++
 target/ppc/cpu.h |  1 +
 target/ppc/mmu-radix64.c |  4 ++--
 3 files changed, 21 insertions(+), 6 deletions(-)

diff --git a/hw/ppc/spapr_caps.c b/hw/ppc/spapr_caps.c
index 3278c09b0f..7fe07d83dd 100644
--- a/hw/ppc/spapr_caps.c
+++ b/hw/ppc/spapr_caps.c
@@ -389,10 +389,7 @@ static void cap_nested_kvm_hv_apply(SpaprMachineState 
*spapr,
 return;
 }
 
-if (tcg_enabled()) {
-error_setg(errp,
-   "No Nested KVM-HV support in tcg, try cap-nested-hv=off");
-} else if (kvm_enabled()) {
+if (kvm_enabled()) {
 if (!kvmppc_has_cap_nested_kvm_hv()) {
 error_setg(errp,
 "KVM implementation does not support Nested KVM-HV, try cap-nested-hv=off");
@@ -400,6 +397,22 @@ static void cap_nested_kvm_hv_apply(SpaprMachineState 
*spapr,
 error_setg(errp,
 "Error enabling cap-nested-hv with KVM, try cap-nested-hv=off");
 }
+} /* else { nothing required for tcg } */
+}
+
+static void cap_nested_kvm_hv_cpu_apply(SpaprMachineState *spapr,
+PowerPCCPU *cpu,
+uint8_t val, Error **errp)
+{
+CPUPPCState *env = >env;
+
+if (tcg_enabled() && val) {
+if (env->spr[SPR_PVR] != 0x004E1202) {
+error_setg(errp, "Nested KVM-HV only supported on POWER9 DD2.2, "
+ "try cap-nested-hv=off or -cpu power9_v2.2");
+return;
+}
+env->disable_hw_rc_updates = true;
 }
 }
 
@@ -544,6 +557,7 @@ SpaprCapabilityInfo capability_table[SPAPR_CAP_NUM] = {
 .set = spapr_cap_set_bool,
 .type = "bool",
 .apply = cap_nested_kvm_hv_apply,
+.cpu_apply = cap_nested_kvm_hv_cpu_apply,
 },
 [SPAPR_CAP_LARGE_DECREMENTER] = {
 .name = "large-decr",
diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
index 426015c9cd..6502e0de82 100644
--- a/target/ppc/cpu.h
+++ b/target/ppc/cpu.h
@@ -1237,6 +1237,7 @@ struct CPUPPCState {
 target_ulong hv_ptr, regs_ptr;
 struct hv_guest_state l2_hv, l1_saved_hv;
 struct pt_regs l2_regs, l1_saved_regs;
+bool disable_hw_rc_updates;
 };
 
 #define SET_FIT_PERIOD(a_, b_, c_, d_)  \
diff --git a/target/ppc/mmu-radix64.c b/target/ppc/mmu-radix64.c
index 2a8147fc38..cc06967dbe 100644
--- a/target/ppc/mmu-radix64.c
+++ b/target/ppc/mmu-radix64.c
@@ -31,9 +31,9 @@
 static inline bool ppc_radix64_hw_rc_updates(CPUPPCState *env)
 {
 #ifdef CONFIG_ATOMIC64
-return true;
+return !env->disable_hw_rc_updates;
 #else
-return !qemu_tcg_mttcg_enabled();
+return !qemu_tcg_mttcg_enabled() && !env->disable_hw_rc_updates;
 #endif
 }
 
-- 
2.13.6




Re: [Qemu-devel] [QEMU-PPC] [PATCH 00/13] target/ppc: Implement KVM support under TCG

2019-05-03 Thread Suraj Jitindar Singh
On Fri, 2019-05-03 at 15:53 +1000, Suraj Jitindar Singh wrote:
> This patch series adds the necessary parts so that a tcg guest is
> able to use
> kvm facilities. That is a tcg guest can boot its own kvm guests.
> 
> The main requirements for this were a few registers and instructions
> as well as
> some hcalls and the addition of partition scoped translation in the
> radix mmu
> emulation.
> 
> This can be used to boot a kvm guest under a pseries tcg guest:
> Use power9_v2.2 cpu and add -machine cap-nested-hv=on for the first
> guest.
> Then inside that guest boot a kvm guest as normal.
> This takes advantage of the new hcalls with qemu emulating them as a
> normal
> hypervisor would on a real machine.
> 
> This can also be used to boot a kvm guest under a powernv tcg guest:
> Use any power9 cpu type.
> This takes advantage of the new hv register access added.
> Note that for powernv there is no xive interrupt excalation for KVM
> which means
> that while the guest will boot, it won't receive any interrupts.

Ah so I'm suddenly aware I based this on the wrong tree so it won't
apply to your dwg-ppc-for-4.1 David.

Consider this a RFC and I'll rebase and resend when required.

> 
> Suraj Jitindar Singh (13):
>   target/ppc: Implement the VTB for HV access
>   target/ppc: Work [S]PURR implementation and add HV support
>   target/ppc: Add SPR ASDR
>   target/ppc: Add SPR TBU40
>   target/ppc: Add privileged message send facilities
>   target/ppc: Enforce that the root page directory size must be at
> least
> 5
>   target/ppc: Handle partition scoped radix tree translation
>   target/ppc: Implement hcall H_SET_PARTITION_TABLE
>   target/ppc: Implement hcall H_ENTER_NESTED
>   target/ppc: Implement hcall H_TLB_INVALIDATE
>   target/ppc: Implement hcall H_COPY_TOFROM_GUEST
>   target/ppc: Introduce POWER9 DD2.2 cpu type
>   target/ppc: Enable SPAPR_CAP_NESTED_KVM_HV under tcg
> 
>  hw/ppc/ppc.c|  46 -
>  hw/ppc/spapr_caps.c |  22 ++-
>  hw/ppc/spapr_cpu_core.c |   1 +
>  hw/ppc/spapr_hcall.c| 409
> +++
>  include/hw/ppc/ppc.h|   4 +-
>  include/hw/ppc/spapr.h  |   7 +-
>  linux-user/ppc/cpu_loop.c   |   5 +
>  target/ppc/cpu-models.c |   2 +
>  target/ppc/cpu-models.h |   1 +
>  target/ppc/cpu.h|  70 +++
>  target/ppc/excp_helper.c|  79 +++-
>  target/ppc/helper.h |   9 +
>  target/ppc/misc_helper.c|  46 +
>  target/ppc/mmu-radix64.c| 412 
> 
>  target/ppc/mmu-radix64.h|   4 +
>  target/ppc/timebase_helper.c|  20 ++
>  target/ppc/translate.c  |  28 +++
>  target/ppc/translate_init.inc.c | 107 +--
>  18 files changed, 1115 insertions(+), 157 deletions(-)
> 



[Qemu-devel] [QEMU-PPC] [PATCH 10/13] target/ppc: Implement hcall H_TLB_INVALIDATE

2019-05-03 Thread Suraj Jitindar Singh
The hcall H_TLB_INVALIDATE is used by a guest acting as a nested
hypervisor to perform partition scoped tlb invalidation since these
instructions are hypervisor privileged.

Check the arguments are valid and then invalidate the entire tlb since
this is about all we can do in tcg.

Signed-off-by: Suraj Jitindar Singh 
---
 hw/ppc/spapr_hcall.c   | 28 
 include/hw/ppc/spapr.h |  3 ++-
 2 files changed, 30 insertions(+), 1 deletion(-)

diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c
index 68f3282214..a84d5e2163 100644
--- a/hw/ppc/spapr_hcall.c
+++ b/hw/ppc/spapr_hcall.c
@@ -2131,6 +2131,33 @@ void h_exit_nested(PowerPCCPU *cpu)
 env->gpr[3] = trap;
 }
 
+static target_ulong h_nested_tlb_invalidate(PowerPCCPU *cpu,
+SpaprMachineState *spapr,
+target_ulong opcode,
+target_ulong *args)
+{
+target_ulong instr = args[0];
+target_ulong rbval = args[2];
+int r, ric, prs, is;
+
+if (spapr_get_cap(spapr, SPAPR_CAP_NESTED_KVM_HV) == 0) {
+return H_FUNCTION;
+}
+
+ric = (instr >> 18) & 0x3;
+prs = (instr >> 17) & 0x1;
+r = (instr >> 16) & 0x1;
+is = (rbval >> 10) & 0x3;
+
+if ((!r) || (prs) || (ric == 3) || (is == 1) || ((!is) && (ric == 1 ||
+   ric == 2)))
+return H_PARAMETER;
+
+/* Invalidate everything, not much else we can do */
+cpu->env.tlb_need_flush = TLB_NEED_GLOBAL_FLUSH | TLB_NEED_LOCAL_FLUSH;
+return H_SUCCESS;
+}
+
 static spapr_hcall_fn papr_hypercall_table[(MAX_HCALL_OPCODE / 4) + 1];
 static spapr_hcall_fn kvmppc_hypercall_table[KVMPPC_HCALL_MAX - 
KVMPPC_HCALL_BASE + 1];
 
@@ -2240,6 +2267,7 @@ static void hypercall_register_types(void)
 /* Platform-specific hcalls used for nested HV KVM */
 spapr_register_hypercall(H_SET_PARTITION_TABLE, h_set_partition_table);
 spapr_register_hypercall(H_ENTER_NESTED, h_enter_nested);
+spapr_register_hypercall(H_TLB_INVALIDATE, h_nested_tlb_invalidate);
 
 /* Virtual Processor Home Node */
 spapr_register_hypercall(H_HOME_NODE_ASSOCIATIVITY,
diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
index 7083dea9ef..6a614c445f 100644
--- a/include/hw/ppc/spapr.h
+++ b/include/hw/ppc/spapr.h
@@ -504,7 +504,8 @@ struct SpaprMachineState {
 /* Platform-specific hcalls used for nested HV KVM */
 #define H_SET_PARTITION_TABLE   0xF800
 #define H_ENTER_NESTED  0xF804
-#define KVMPPC_HCALL_MAXH_ENTER_NESTED
+#define H_TLB_INVALIDATE0xF808
+#define KVMPPC_HCALL_MAXH_TLB_INVALIDATE
 
 typedef struct SpaprDeviceTreeUpdateHeader {
 uint32_t version_id;
-- 
2.13.6




[Qemu-devel] [QEMU-PPC] [PATCH 11/13] target/ppc: Implement hcall H_COPY_TOFROM_GUEST

2019-05-02 Thread Suraj Jitindar Singh
The hcall H_COPY_TOFROM_GUEST of used by a guest acting as a nested
hypervisor to access quadrants since quadrant access is hypervisor
privileged.

Translate the guest address to be accessed, map the memory and perform
the access on behalf of the guest. If the parameters are invalid, the
address can't be translated or the memory cannot be mapped then fail
the access.

Signed-off-by: Suraj Jitindar Singh 
---
 hw/ppc/spapr_hcall.c | 74 
 include/hw/ppc/spapr.h   |  3 +-
 target/ppc/mmu-radix64.c |  7 ++---
 target/ppc/mmu-radix64.h |  4 +++
 4 files changed, 83 insertions(+), 5 deletions(-)

diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c
index a84d5e2163..a370d70500 100644
--- a/hw/ppc/spapr_hcall.c
+++ b/hw/ppc/spapr_hcall.c
@@ -17,6 +17,7 @@
 #include "mmu-book3s-v3.h"
 #include "hw/mem/memory-device.h"
 #include "hw/ppc/ppc.h"
+#include "mmu-radix64.h"
 
 static bool has_spr(PowerPCCPU *cpu, int spr)
 {
@@ -2158,6 +2159,78 @@ static target_ulong h_nested_tlb_invalidate(PowerPCCPU 
*cpu,
 return H_SUCCESS;
 }
 
+static target_ulong h_copy_tofrom_guest(PowerPCCPU *cpu,
+SpaprMachineState *spapr,
+target_ulong opcode, target_ulong 
*args)
+{
+target_ulong lpid = args[0];
+target_ulong pid = args[1];
+vaddr eaddr = args[2];
+target_ulong gp_to = args[3];
+target_ulong gp_from = args[4];
+target_ulong n = args[5];
+int is_load = !!gp_to;
+void *from, *to;
+int prot, psize;
+hwaddr raddr, to_len, from_len;
+
+if (spapr_get_cap(spapr, SPAPR_CAP_NESTED_KVM_HV) == 0) {
+return H_FUNCTION;
+}
+
+if ((gp_to && gp_from) || (!gp_to && !gp_from)) {
+return H_PARAMETER;
+}
+
+if (eaddr & (0xFFFUL << 52)) {
+return H_PARAMETER;
+}
+
+if (!lpid) {
+return H_PARAMETER;
+}
+
+/* Translate eaddr to raddr */
+if (ppc_radix64_xlate(cpu, eaddr, is_load, lpid, pid, 1, , ,
+  , 0)) {
+return H_NOT_FOUND;
+}
+if (((raddr & ((1UL << psize) - 1)) + n) >= (1UL << psize)) {
+return H_PARAMETER;
+}
+
+if (is_load) {
+gp_from = raddr;
+} else {
+gp_to = raddr;
+}
+
+/* Map the memory regions and perform a memory copy */
+from = cpu_physical_memory_map(gp_from, _len, 0);
+if (!from) {
+return H_NOT_FOUND;
+}
+if (from_len < n) {
+cpu_physical_memory_unmap(from, from_len, 0, 0);
+return H_PARAMETER;
+}
+to = cpu_physical_memory_map(gp_to, _len, 1);
+if (!to) {
+cpu_physical_memory_unmap(from, from_len, 0, 0);
+return H_PARAMETER;
+}
+if (to_len < n) {
+cpu_physical_memory_unmap(from, from_len, 0, 0);
+cpu_physical_memory_unmap(to, to_len, 1, 0);
+return H_PARAMETER;
+}
+memcpy(to, from, n);
+cpu_physical_memory_unmap(from, from_len, 0, n);
+cpu_physical_memory_unmap(to, to_len, 1, n);
+
+return H_SUCCESS;
+}
+
 static spapr_hcall_fn papr_hypercall_table[(MAX_HCALL_OPCODE / 4) + 1];
 static spapr_hcall_fn kvmppc_hypercall_table[KVMPPC_HCALL_MAX - 
KVMPPC_HCALL_BASE + 1];
 
@@ -2268,6 +2341,7 @@ static void hypercall_register_types(void)
 spapr_register_hypercall(H_SET_PARTITION_TABLE, h_set_partition_table);
 spapr_register_hypercall(H_ENTER_NESTED, h_enter_nested);
 spapr_register_hypercall(H_TLB_INVALIDATE, h_nested_tlb_invalidate);
+spapr_register_hypercall(H_COPY_TOFROM_GUEST, h_copy_tofrom_guest);
 
 /* Virtual Processor Home Node */
 spapr_register_hypercall(H_HOME_NODE_ASSOCIATIVITY,
diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
index 6a614c445f..d62f4108d4 100644
--- a/include/hw/ppc/spapr.h
+++ b/include/hw/ppc/spapr.h
@@ -505,7 +505,8 @@ struct SpaprMachineState {
 #define H_SET_PARTITION_TABLE   0xF800
 #define H_ENTER_NESTED  0xF804
 #define H_TLB_INVALIDATE0xF808
-#define KVMPPC_HCALL_MAXH_TLB_INVALIDATE
+#define H_COPY_TOFROM_GUEST 0xF80C
+#define KVMPPC_HCALL_MAXH_COPY_TOFROM_GUEST
 
 typedef struct SpaprDeviceTreeUpdateHeader {
 uint32_t version_id;
diff --git a/target/ppc/mmu-radix64.c b/target/ppc/mmu-radix64.c
index 6118ad1b00..2a8147fc38 100644
--- a/target/ppc/mmu-radix64.c
+++ b/target/ppc/mmu-radix64.c
@@ -429,10 +429,9 @@ static bool validate_pate(PowerPCCPU *cpu, uint64_t lpid, 
ppc_v3_pate_t *pate)
 return true;
 }
 
-static int ppc_radix64_xlate(PowerPCCPU *cpu, vaddr eaddr, int rwx,
- uint64_t lpid, uint64_t pid, bool relocation,
- hwaddr *raddr, int *psizep, int *protp,
- bool cause_excp)
+int ppc_radix64_xlate(PowerPCCPU *cpu, vaddr eaddr, int rwx, uint64_t lpid,
+  uint64_t

[Qemu-devel] [QEMU-PPC] [PATCH 05/13] target/ppc: Add privileged message send facilities

2019-05-02 Thread Suraj Jitindar Singh
Privileged message send facilities exist on POWER8 processors and later
and include a register and instructions which can be used to generate,
observe/modify the state of and clear privileged doorbell exceptions as
described below.

The Directed Privileged Doorbell Exception State (DPDES) register
reflects the state of pending privileged doorbell exceptions and can
also be used to modify that state. The register can be used to read and
modify the state of privileged doorbell exceptions for all threads of a
subprocessor and thus is a shared facility for that subprocessor. The
register can be read/written by the hypervisor and read by the
supervisor if enabled in the HFSCR, otherwise a hypervisor facility
unavailable exception is generated.

The privileged message send and clear instructions (msgsndp & msgclrp)
are used to generate and clear the presence of a directed privileged
doorbell exception, respectively. The msgsndp instruction can be used to
target any thread of the current subprocessor, msgclrp acts on the
thread issuing the instruction. These instructions are privileged, but
will generate a hypervisor facility unavailable exception if not enabled
in the HFSCR and executed in privileged non-hypervisor state.

Add and implement this register and instructions by reading or modifying the
pending interrupt state of the cpu.

Note that TCG only supports one thread per core and so we only need to
worry about the cpu making the access.

Signed-off-by: Suraj Jitindar Singh 
---
 target/ppc/cpu.h|  7 +
 target/ppc/excp_helper.c| 63 +
 target/ppc/helper.h |  5 
 target/ppc/misc_helper.c| 46 ++
 target/ppc/translate.c  | 28 ++
 target/ppc/translate_init.inc.c | 40 ++
 6 files changed, 184 insertions(+), 5 deletions(-)

diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
index e324064111..1d2a088391 100644
--- a/target/ppc/cpu.h
+++ b/target/ppc/cpu.h
@@ -425,6 +425,10 @@ typedef struct ppc_v3_pate_t {
 #define PSSCR_ESL PPC_BIT(42) /* Enable State Loss */
 #define PSSCR_EC  PPC_BIT(43) /* Exit Criterion */
 
+/* HFSCR bits */
+#define HFSCR_MSGSNDP PPC_BIT(53) /* Privileged Message Send Facilities */
+#define HFSCR_IC_MSGSNDP  0xA
+
 #define msr_sf   ((env->msr >> MSR_SF)   & 1)
 #define msr_isf  ((env->msr >> MSR_ISF)  & 1)
 #define msr_shv  ((env->msr >> MSR_SHV)  & 1)
@@ -1355,6 +1359,8 @@ void cpu_ppc_set_vhyp(PowerPCCPU *cpu, 
PPCVirtualHypervisor *vhyp);
 #endif
 
 void store_fpscr(CPUPPCState *env, uint64_t arg, uint32_t mask);
+void gen_hfscr_facility_check(DisasContext *ctx, int facility_sprn, int bit,
+  int sprn, int cause);
 
 static inline uint64_t ppc_dump_gpr(CPUPPCState *env, int gprn)
 {
@@ -1501,6 +1507,7 @@ void ppc_compat_add_property(Object *obj, const char 
*name,
 #define SPR_MPC_ICTRL (0x09E)
 #define SPR_MPC_BAR   (0x09F)
 #define SPR_PSPB  (0x09F)
+#define SPR_DPDES (0x0B0)
 #define SPR_DAWR  (0x0B4)
 #define SPR_RPR   (0x0BA)
 #define SPR_CIABR (0x0BB)
diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c
index beafcf1ebd..7a4da7bdba 100644
--- a/target/ppc/excp_helper.c
+++ b/target/ppc/excp_helper.c
@@ -461,6 +461,13 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int 
excp_model, int excp)
 env->spr[SPR_FSCR] |= ((target_ulong)env->error_code << 56);
 #endif
 break;
+case POWERPC_EXCP_HV_FU: /* Hypervisor Facility Unavailable Exception 
*/
+env->spr[SPR_HFSCR] |= ((target_ulong)env->error_code << FSCR_IC_POS);
+srr0 = SPR_HSRR0;
+srr1 = SPR_HSRR1;
+new_msr |= (target_ulong)MSR_HVB;
+new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
+break;
 case POWERPC_EXCP_PIT:   /* Programmable interval timer interrupt*/
 LOG_EXCP("PIT exception\n");
 break;
@@ -884,7 +891,11 @@ static void ppc_hw_interrupt(CPUPPCState *env)
 }
 if (env->pending_interrupts & (1 << PPC_INTERRUPT_DOORBELL)) {
 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DOORBELL);
-powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_DOORI);
+if (env->insns_flags & PPC_SEGMENT_64B) {
+powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_SDOOR);
+} else {
+powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_DOORI);
+}
 return;
 }
 if (env->pending_interrupts & (1 << PPC_INTERRUPT_HDOORBELL)) {
@@ -1202,19 +1213,26 @@ void helper_msgsnd(target_ulong rb)
 }
 
 /* Server Processor Control */
-static int book3s_dbell2irq(target_ulong rb)
+static int book3

[Qemu-devel] [QEMU-PPC] [PATCH 12/13] target/ppc: Introduce POWER9 DD2.2 cpu type

2019-05-02 Thread Suraj Jitindar Singh
Introduce a POWER9 DD2.2 cpu type with pvr 0x004E1202.

A DD2.2 POWER9 cpu type is needed to enable kvm for pseries tcg guests
since it means they will use the H_ENTER_NESTED hcall to run a guest
rather than trying the generic entry path which will fail.

Signed-off-by: Suraj Jitindar Singh 
---
 hw/ppc/spapr_cpu_core.c | 1 +
 target/ppc/cpu-models.c | 2 ++
 target/ppc/cpu-models.h | 1 +
 3 files changed, 4 insertions(+)

diff --git a/hw/ppc/spapr_cpu_core.c b/hw/ppc/spapr_cpu_core.c
index 40e7010cf0..98d46c6edb 100644
--- a/hw/ppc/spapr_cpu_core.c
+++ b/hw/ppc/spapr_cpu_core.c
@@ -399,6 +399,7 @@ static const TypeInfo spapr_cpu_core_type_infos[] = {
 DEFINE_SPAPR_CPU_CORE_TYPE("power8nvl_v1.0"),
 DEFINE_SPAPR_CPU_CORE_TYPE("power9_v1.0"),
 DEFINE_SPAPR_CPU_CORE_TYPE("power9_v2.0"),
+DEFINE_SPAPR_CPU_CORE_TYPE("power9_v2.2"),
 #ifdef CONFIG_KVM
 DEFINE_SPAPR_CPU_CORE_TYPE("host"),
 #endif
diff --git a/target/ppc/cpu-models.c b/target/ppc/cpu-models.c
index 7c75963e3c..603ae7f5b4 100644
--- a/target/ppc/cpu-models.c
+++ b/target/ppc/cpu-models.c
@@ -773,6 +773,8 @@
 "POWER9 v1.0")
 POWERPC_DEF("power9_v2.0",   CPU_POWERPC_POWER9_DD20,POWER9,
 "POWER9 v2.0")
+POWERPC_DEF("power9_v2.2",   CPU_POWERPC_POWER9_DD22,POWER9,
+"POWER9 v2.2")
 #endif /* defined (TARGET_PPC64) */
 
 /***/
diff --git a/target/ppc/cpu-models.h b/target/ppc/cpu-models.h
index efdb2fa53c..820e94b0c8 100644
--- a/target/ppc/cpu-models.h
+++ b/target/ppc/cpu-models.h
@@ -373,6 +373,7 @@ enum {
 CPU_POWERPC_POWER9_BASE= 0x004E,
 CPU_POWERPC_POWER9_DD1 = 0x004E0100,
 CPU_POWERPC_POWER9_DD20= 0x004E1200,
+CPU_POWERPC_POWER9_DD22= 0x004E1202,
 CPU_POWERPC_970_v22= 0x00390202,
 CPU_POWERPC_970FX_v10  = 0x00391100,
 CPU_POWERPC_970FX_v20  = 0x003C0200,
-- 
2.13.6




[Qemu-devel] [QEMU-PPC] [PATCH 04/13] target/ppc: Add SPR TBU40

2019-05-02 Thread Suraj Jitindar Singh
The spr TBU40 is used to set the upper 40 bits of the timebase
register, present on POWER5+ and later processors.

This register can only be written by the hypervisor, and cannot be read.

Signed-off-by: Suraj Jitindar Singh 
---
 hw/ppc/ppc.c| 13 +
 target/ppc/cpu.h|  1 +
 target/ppc/helper.h |  1 +
 target/ppc/timebase_helper.c|  5 +
 target/ppc/translate_init.inc.c | 19 +++
 5 files changed, 39 insertions(+)

diff --git a/hw/ppc/ppc.c b/hw/ppc/ppc.c
index b567156f97..b618c6f615 100644
--- a/hw/ppc/ppc.c
+++ b/hw/ppc/ppc.c
@@ -710,6 +710,19 @@ void cpu_ppc_store_vtb(CPUPPCState *env, uint64_t value)
  _env->vtb_offset, value);
 }
 
+void cpu_ppc_store_tbu40(CPUPPCState *env, uint64_t value)
+{
+ppc_tb_t *tb_env = env->tb_env;
+uint64_t tb;
+
+tb = cpu_ppc_get_tb(tb_env, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL),
+tb_env->tb_offset);
+tb &= 0xFFUL;
+tb |= (value & ~0xFFUL);
+cpu_ppc_store_tb(tb_env, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL),
+ _env->tb_offset, tb);
+}
+
 static void cpu_ppc_tb_stop (CPUPPCState *env)
 {
 ppc_tb_t *tb_env = env->tb_env;
diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
index 8d66265e5a..e324064111 100644
--- a/target/ppc/cpu.h
+++ b/target/ppc/cpu.h
@@ -1334,6 +1334,7 @@ target_ulong cpu_ppc_load_decr (CPUPPCState *env);
 void cpu_ppc_store_decr (CPUPPCState *env, target_ulong value);
 target_ulong cpu_ppc_load_hdecr (CPUPPCState *env);
 void cpu_ppc_store_hdecr (CPUPPCState *env, target_ulong value);
+void cpu_ppc_store_tbu40(CPUPPCState *env, uint64_t value);
 uint64_t cpu_ppc_load_purr (CPUPPCState *env);
 void cpu_ppc_store_purr(CPUPPCState *env, uint64_t value);
 uint32_t cpu_ppc601_load_rtcl (CPUPPCState *env);
diff --git a/target/ppc/helper.h b/target/ppc/helper.h
index 336e7802fb..6aee195528 100644
--- a/target/ppc/helper.h
+++ b/target/ppc/helper.h
@@ -703,6 +703,7 @@ DEF_HELPER_FLAGS_2(store_decr, TCG_CALL_NO_RWG, void, env, 
tl)
 DEF_HELPER_FLAGS_1(load_hdecr, TCG_CALL_NO_RWG, tl, env)
 DEF_HELPER_FLAGS_2(store_hdecr, TCG_CALL_NO_RWG, void, env, tl)
 DEF_HELPER_FLAGS_2(store_vtb, TCG_CALL_NO_RWG, void, env, tl)
+DEF_HELPER_FLAGS_2(store_tbu40, TCG_CALL_NO_RWG, void, env, tl)
 DEF_HELPER_2(store_hid0_601, void, env, tl)
 DEF_HELPER_3(store_403_pbr, void, env, i32, tl)
 DEF_HELPER_FLAGS_1(load_40x_pit, TCG_CALL_NO_RWG, tl, env)
diff --git a/target/ppc/timebase_helper.c b/target/ppc/timebase_helper.c
index 2395295b77..703bd9ed18 100644
--- a/target/ppc/timebase_helper.c
+++ b/target/ppc/timebase_helper.c
@@ -128,6 +128,11 @@ void helper_store_vtb(CPUPPCState *env, target_ulong val)
 cpu_ppc_store_vtb(env, val);
 }
 
+void helper_store_tbu40(CPUPPCState *env, target_ulong val)
+{
+cpu_ppc_store_tbu40(env, val);
+}
+
 target_ulong helper_load_40x_pit(CPUPPCState *env)
 {
 return load_40x_pit(env);
diff --git a/target/ppc/translate_init.inc.c b/target/ppc/translate_init.inc.c
index a0cae58e19..8e287066e5 100644
--- a/target/ppc/translate_init.inc.c
+++ b/target/ppc/translate_init.inc.c
@@ -325,6 +325,11 @@ static void spr_write_vtb(DisasContext *ctx, int sprn, int 
gprn)
 gen_helper_store_vtb(cpu_env, cpu_gpr[gprn]);
 }
 
+static void spr_write_tbu40(DisasContext *ctx, int sprn, int gprn)
+{
+gen_helper_store_tbu40(cpu_env, cpu_gpr[gprn]);
+}
+
 #endif
 #endif
 
@@ -7812,6 +7817,16 @@ static void gen_spr_power5p_ear(CPUPPCState *env)
  0x);
 }
 
+static void gen_spr_power5p_tb(CPUPPCState *env)
+{
+/* TBU40 (High 40 bits of the Timebase register */
+spr_register_hv(env, SPR_TBU40, "TBU40",
+SPR_NOACCESS, SPR_NOACCESS,
+SPR_NOACCESS, SPR_NOACCESS,
+SPR_NOACCESS, _write_tbu40,
+0x);
+}
+
 #if !defined(CONFIG_USER_ONLY)
 static void spr_write_hmer(DisasContext *ctx, int sprn, int gprn)
 {
@@ -8352,6 +8367,7 @@ static void init_proc_power5plus(CPUPPCState *env)
 gen_spr_power5p_common(env);
 gen_spr_power5p_lpar(env);
 gen_spr_power5p_ear(env);
+gen_spr_power5p_tb(env);
 
 /* env variables */
 env->dcache_line_size = 128;
@@ -8464,6 +8480,7 @@ static void init_proc_POWER7(CPUPPCState *env)
 gen_spr_power5p_common(env);
 gen_spr_power5p_lpar(env);
 gen_spr_power5p_ear(env);
+gen_spr_power5p_tb(env);
 gen_spr_power6_common(env);
 gen_spr_power6_dbg(env);
 gen_spr_power7_book4(env);
@@ -8605,6 +8622,7 @@ static void init_proc_POWER8(CPUPPCState *env)
 gen_spr_power5p_common(env);
 gen_spr_power5p_lpar(env);
 gen_spr_power5p_ear(env);
+gen_spr_power5p_tb(env);
 gen_spr_power6_common(env);
 gen_spr_power6_dbg(env);
 gen_spr_power8_tce_address_control(env);
@@ -8793,6 +8811,7 @@ static void init_proc_POWER9(CPUPPCState *env)
 gen_spr_power5p_common

[Qemu-devel] [QEMU-PPC] [PATCH 02/13] target/ppc: Work [S]PURR implementation and add HV support

2019-05-02 Thread Suraj Jitindar Singh
The Processor Utilisation of Resources Register (PURR) and Scaled
Processor Utilisation of Resources Register (SPURR) provide an estimate
of the resources used by the thread, present on POWER7 and later
processors.

Currently the [S]PURR registers simply count at the rate of the
timebase.

Preserve this behaviour but rework the implementation to store an offset
like the timebase rather than doing the calculation manually. Also allow
hypervisor write access to the register along with the currently
available read access.

Signed-off-by: Suraj Jitindar Singh 
---
 hw/ppc/ppc.c| 17 +++--
 include/hw/ppc/ppc.h|  3 +--
 target/ppc/cpu.h|  1 +
 target/ppc/helper.h |  1 +
 target/ppc/timebase_helper.c|  5 +
 target/ppc/translate_init.inc.c | 23 +++
 6 files changed, 30 insertions(+), 20 deletions(-)

diff --git a/hw/ppc/ppc.c b/hw/ppc/ppc.c
index a57ca64626..b567156f97 100644
--- a/hw/ppc/ppc.c
+++ b/hw/ppc/ppc.c
@@ -819,12 +819,9 @@ target_ulong cpu_ppc_load_hdecr (CPUPPCState *env)
 uint64_t cpu_ppc_load_purr (CPUPPCState *env)
 {
 ppc_tb_t *tb_env = env->tb_env;
-uint64_t diff;
 
-diff = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) - tb_env->purr_start;
-
-return tb_env->purr_load +
-muldiv64(diff, tb_env->tb_freq, NANOSECONDS_PER_SECOND);
+return cpu_ppc_get_tb(tb_env, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL),
+  tb_env->purr_offset);
 }
 
 /* When decrementer expires,
@@ -980,12 +977,12 @@ static void cpu_ppc_hdecr_cb(void *opaque)
 cpu_ppc_hdecr_excp(cpu);
 }
 
-static void cpu_ppc_store_purr(PowerPCCPU *cpu, uint64_t value)
+void cpu_ppc_store_purr(CPUPPCState *env, uint64_t value)
 {
-ppc_tb_t *tb_env = cpu->env.tb_env;
+ppc_tb_t *tb_env = env->tb_env;
 
-tb_env->purr_load = value;
-tb_env->purr_start = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
+cpu_ppc_store_tb(tb_env, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL),
+ _env->purr_offset, value);
 }
 
 static void cpu_ppc_set_tb_clk (void *opaque, uint32_t freq)
@@ -1002,7 +999,7 @@ static void cpu_ppc_set_tb_clk (void *opaque, uint32_t 
freq)
  */
 _cpu_ppc_store_decr(cpu, 0x, 0x, 32);
 _cpu_ppc_store_hdecr(cpu, 0x, 0x, 32);
-cpu_ppc_store_purr(cpu, 0xULL);
+cpu_ppc_store_purr(env, 0xULL);
 }
 
 static void timebase_save(PPCTimebase *tb)
diff --git a/include/hw/ppc/ppc.h b/include/hw/ppc/ppc.h
index 205150e6b4..b09ffbf300 100644
--- a/include/hw/ppc/ppc.h
+++ b/include/hw/ppc/ppc.h
@@ -32,8 +32,7 @@ struct ppc_tb_t {
 /* Hypervisor decrementer management */
 uint64_t hdecr_next;/* Tick for next hdecr interrupt  */
 QEMUTimer *hdecr_timer;
-uint64_t purr_load;
-uint64_t purr_start;
+int64_t purr_offset;
 void *opaque;
 uint32_t flags;
 };
diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
index 70167bae22..19b3e1de0e 100644
--- a/target/ppc/cpu.h
+++ b/target/ppc/cpu.h
@@ -1335,6 +1335,7 @@ void cpu_ppc_store_decr (CPUPPCState *env, target_ulong 
value);
 target_ulong cpu_ppc_load_hdecr (CPUPPCState *env);
 void cpu_ppc_store_hdecr (CPUPPCState *env, target_ulong value);
 uint64_t cpu_ppc_load_purr (CPUPPCState *env);
+void cpu_ppc_store_purr(CPUPPCState *env, uint64_t value);
 uint32_t cpu_ppc601_load_rtcl (CPUPPCState *env);
 uint32_t cpu_ppc601_load_rtcu (CPUPPCState *env);
 #if !defined(CONFIG_USER_ONLY)
diff --git a/target/ppc/helper.h b/target/ppc/helper.h
index 3701bcbf1b..336e7802fb 100644
--- a/target/ppc/helper.h
+++ b/target/ppc/helper.h
@@ -686,6 +686,7 @@ DEF_HELPER_FLAGS_1(load_601_rtcu, TCG_CALL_NO_RWG, tl, env)
 #if !defined(CONFIG_USER_ONLY)
 #if defined(TARGET_PPC64)
 DEF_HELPER_FLAGS_1(load_purr, TCG_CALL_NO_RWG, tl, env)
+DEF_HELPER_FLAGS_2(store_purr, TCG_CALL_NO_RWG, void, env, tl)
 DEF_HELPER_2(store_ptcr, void, env, tl)
 #endif
 DEF_HELPER_2(store_sdr1, void, env, tl)
diff --git a/target/ppc/timebase_helper.c b/target/ppc/timebase_helper.c
index 8c3c2fe67c..2395295b77 100644
--- a/target/ppc/timebase_helper.c
+++ b/target/ppc/timebase_helper.c
@@ -55,6 +55,11 @@ target_ulong helper_load_purr(CPUPPCState *env)
 {
 return (target_ulong)cpu_ppc_load_purr(env);
 }
+
+void helper_store_purr(CPUPPCState *env, target_ulong val)
+{
+cpu_ppc_store_purr(env, val);
+}
 #endif
 
 target_ulong helper_load_601_rtcl(CPUPPCState *env)
diff --git a/target/ppc/translate_init.inc.c b/target/ppc/translate_init.inc.c
index e3f941800b..9cd33e79ef 100644
--- a/target/ppc/translate_init.inc.c
+++ b/target/ppc/translate_init.inc.c
@@ -285,6 +285,11 @@ static void spr_read_purr(DisasContext *ctx, int gprn, int 
sprn)
 gen_helper_load_purr(cpu_gpr[gprn], cpu_env);
 }
 
+static void spr_write_purr(DisasContext *ctx, int sprn, int gprn)
+{
+gen_helper_store_purr(cpu_env, cpu_gpr[gprn]);
+}
+
 /* HDECR */
 static void spr_read_hde

[Qemu-devel] [QEMU-PPC] [PATCH 07/13] target/ppc: Handle partition scoped radix tree translation

2019-05-02 Thread Suraj Jitindar Singh
Radix tree translation is a 2 step process:

Process Scoped Translation:
Effective Address (EA) -> Virtual Address (VA)

Paritition Scoped Translation:
Virtual Address (VA) -> Real Address (RA)

Performed based on:
  MSR[HV]
   ---
   | | HV = 0| HV = 1|
   ---
   | Relocation  |   Partition   |  No   |
   | = Off   |Scoped |  Translation  |
Relocation ---
   | Relocation  |  Partition &  |Process|
   | = On|Process Scoped |Scoped |
   ---

Currently only process scoped translation is handled.
Implement partitition scoped translation.

The process of using the radix trees to perform partition scoped
translation is identical to process scoped translation, however
hypervisor exceptions are generated, and thus we can reuse the radix
tree traversing code.

Signed-off-by: Suraj Jitindar Singh 
---
 target/ppc/cpu.h |   2 +
 target/ppc/excp_helper.c |   3 +-
 target/ppc/mmu-radix64.c | 407 +--
 3 files changed, 293 insertions(+), 119 deletions(-)

diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
index 1d2a088391..3acc248f40 100644
--- a/target/ppc/cpu.h
+++ b/target/ppc/cpu.h
@@ -501,6 +501,8 @@ typedef struct ppc_v3_pate_t {
 /* Unsupported Radix Tree Configuration */
 #define DSISR_R_BADCONFIG0x0008
 #define DSISR_ATOMIC_RC  0x0004
+/* Unable to translate address of (guest) pde or process/page table entry */
+#define DSISR_PRTABLE_FAULT  0x0002
 
 /* SRR1 error code fields */
 
diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c
index 7a4da7bdba..10091d4624 100644
--- a/target/ppc/excp_helper.c
+++ b/target/ppc/excp_helper.c
@@ -441,9 +441,10 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int 
excp_model, int excp)
 case POWERPC_EXCP_ISEG:  /* Instruction segment exception*/
 case POWERPC_EXCP_TRACE: /* Trace exception  */
 break;
+case POWERPC_EXCP_HISI:  /* Hypervisor instruction storage exception */
+msr |= env->error_code;
 case POWERPC_EXCP_HDECR: /* Hypervisor decrementer exception */
 case POWERPC_EXCP_HDSI:  /* Hypervisor data storage exception*/
-case POWERPC_EXCP_HISI:  /* Hypervisor instruction storage exception */
 case POWERPC_EXCP_HDSEG: /* Hypervisor data segment exception*/
 case POWERPC_EXCP_HISEG: /* Hypervisor instruction segment exception */
 case POWERPC_EXCP_SDOOR_HV:  /* Hypervisor Doorbell interrupt*/
diff --git a/target/ppc/mmu-radix64.c b/target/ppc/mmu-radix64.c
index afa5ba506a..6118ad1b00 100644
--- a/target/ppc/mmu-radix64.c
+++ b/target/ppc/mmu-radix64.c
@@ -112,9 +112,31 @@ static void ppc_radix64_raise_si(PowerPCCPU *cpu, int rwx, 
vaddr eaddr,
 }
 }
 
+static void ppc_radix64_raise_hsi(PowerPCCPU *cpu, int rwx, vaddr eaddr,
+  hwaddr g_raddr, uint32_t cause)
+{
+CPUState *cs = CPU(cpu);
+CPUPPCState *env = >env;
+
+if (rwx == 2) { /* H Instruction Storage Interrupt */
+cs->exception_index = POWERPC_EXCP_HISI;
+env->spr[SPR_ASDR] = g_raddr;
+env->error_code = cause;
+} else { /* H Data Storage Interrupt */
+cs->exception_index = POWERPC_EXCP_HDSI;
+if (rwx == 1) { /* Write -> Store */
+cause |= DSISR_ISSTORE;
+}
+env->spr[SPR_HDSISR] = cause;
+env->spr[SPR_HDAR] = eaddr;
+env->spr[SPR_ASDR] = g_raddr;
+env->error_code = 0;
+}
+}
 
 static bool ppc_radix64_check_prot(PowerPCCPU *cpu, int rwx, uint64_t pte,
-   int *fault_cause, int *prot)
+   int *fault_cause, int *prot,
+   bool partition_scoped)
 {
 CPUPPCState *env = >env;
 const int need_prot[] = { PAGE_READ, PAGE_WRITE, PAGE_EXEC };
@@ -130,11 +152,11 @@ static bool ppc_radix64_check_prot(PowerPCCPU *cpu, int 
rwx, uint64_t pte,
 }
 
 /* Determine permissions allowed by Encoded Access Authority */
-if ((pte & R_PTE_EAA_PRIV) && msr_pr) { /* Insufficient Privilege */
+if (!partition_scoped && (pte & R_PTE_EAA_PRIV) && msr_pr) {
 *prot = 0;
-} else if (msr_pr || (pte & R_PTE_EAA_PRIV)) {
+} else if (msr_pr || (pte & R_PTE_EAA_PRIV) || partition_scoped) {
 *prot = ppc_radix64_get_prot_eaa(pte);
-} else { /* !msr_pr && !(pte & R_PTE_EAA_PRIV) */
+} else { /* !msr_pr && !(pte & R_PTE_EAA_PRIV) && !partition_scoped

[Qemu-devel] [QEMU-PPC] [PATCH 00/13] target/ppc: Implement KVM support under TCG

2019-05-02 Thread Suraj Jitindar Singh
This patch series adds the necessary parts so that a tcg guest is able to use
kvm facilities. That is a tcg guest can boot its own kvm guests.

The main requirements for this were a few registers and instructions as well as
some hcalls and the addition of partition scoped translation in the radix mmu
emulation.

This can be used to boot a kvm guest under a pseries tcg guest:
Use power9_v2.2 cpu and add -machine cap-nested-hv=on for the first guest.
Then inside that guest boot a kvm guest as normal.
This takes advantage of the new hcalls with qemu emulating them as a normal
hypervisor would on a real machine.

This can also be used to boot a kvm guest under a powernv tcg guest:
Use any power9 cpu type.
This takes advantage of the new hv register access added.
Note that for powernv there is no xive interrupt excalation for KVM which means
that while the guest will boot, it won't receive any interrupts.

Suraj Jitindar Singh (13):
  target/ppc: Implement the VTB for HV access
  target/ppc: Work [S]PURR implementation and add HV support
  target/ppc: Add SPR ASDR
  target/ppc: Add SPR TBU40
  target/ppc: Add privileged message send facilities
  target/ppc: Enforce that the root page directory size must be at least
5
  target/ppc: Handle partition scoped radix tree translation
  target/ppc: Implement hcall H_SET_PARTITION_TABLE
  target/ppc: Implement hcall H_ENTER_NESTED
  target/ppc: Implement hcall H_TLB_INVALIDATE
  target/ppc: Implement hcall H_COPY_TOFROM_GUEST
  target/ppc: Introduce POWER9 DD2.2 cpu type
  target/ppc: Enable SPAPR_CAP_NESTED_KVM_HV under tcg

 hw/ppc/ppc.c|  46 -
 hw/ppc/spapr_caps.c |  22 ++-
 hw/ppc/spapr_cpu_core.c |   1 +
 hw/ppc/spapr_hcall.c| 409 +++
 include/hw/ppc/ppc.h|   4 +-
 include/hw/ppc/spapr.h  |   7 +-
 linux-user/ppc/cpu_loop.c   |   5 +
 target/ppc/cpu-models.c |   2 +
 target/ppc/cpu-models.h |   1 +
 target/ppc/cpu.h|  70 +++
 target/ppc/excp_helper.c|  79 +++-
 target/ppc/helper.h |   9 +
 target/ppc/misc_helper.c|  46 +
 target/ppc/mmu-radix64.c| 412 
 target/ppc/mmu-radix64.h|   4 +
 target/ppc/timebase_helper.c|  20 ++
 target/ppc/translate.c  |  28 +++
 target/ppc/translate_init.inc.c | 107 +--
 18 files changed, 1115 insertions(+), 157 deletions(-)

-- 
2.13.6




[Qemu-devel] [QEMU-PPC] [PATCH 01/13] target/ppc: Implement the VTB for HV access

2019-05-02 Thread Suraj Jitindar Singh
The virtual timebase register (VTB) is a 64-bit register which
increments at the same rate as the timebase register, present on POWER8
and later processors.

The register is able to be read/written by the hypervisor and read by
the supervisor. All other accesses are illegal.

Currently the VTB is just an alias for the timebase (TB) register.

Implement the VTB so that is can be read/written independent of the TB.
Make use of the existing method for accessing timebase facilities where
by the compensation is stored and used to compute the value on reads/is
updated on writes.

Signed-off-by: Suraj Jitindar Singh 
---
 hw/ppc/ppc.c| 16 
 include/hw/ppc/ppc.h|  1 +
 linux-user/ppc/cpu_loop.c   |  5 +
 target/ppc/cpu.h|  2 ++
 target/ppc/helper.h |  2 ++
 target/ppc/timebase_helper.c| 10 ++
 target/ppc/translate_init.inc.c | 19 +++
 7 files changed, 51 insertions(+), 4 deletions(-)

diff --git a/hw/ppc/ppc.c b/hw/ppc/ppc.c
index b2ff99ec66..a57ca64626 100644
--- a/hw/ppc/ppc.c
+++ b/hw/ppc/ppc.c
@@ -694,6 +694,22 @@ void cpu_ppc_store_atbu (CPUPPCState *env, uint32_t value)
  _env->atb_offset, ((uint64_t)value << 32) | tb);
 }
 
+uint64_t cpu_ppc_load_vtb(CPUPPCState *env)
+{
+ppc_tb_t *tb_env = env->tb_env;
+
+return cpu_ppc_get_tb(tb_env, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL),
+  tb_env->vtb_offset);
+}
+
+void cpu_ppc_store_vtb(CPUPPCState *env, uint64_t value)
+{
+ppc_tb_t *tb_env = env->tb_env;
+
+cpu_ppc_store_tb(tb_env, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL),
+ _env->vtb_offset, value);
+}
+
 static void cpu_ppc_tb_stop (CPUPPCState *env)
 {
 ppc_tb_t *tb_env = env->tb_env;
diff --git a/include/hw/ppc/ppc.h b/include/hw/ppc/ppc.h
index 4bdcb8bacd..205150e6b4 100644
--- a/include/hw/ppc/ppc.h
+++ b/include/hw/ppc/ppc.h
@@ -23,6 +23,7 @@ struct ppc_tb_t {
 /* Time base management */
 int64_t  tb_offset;/* Compensation*/
 int64_t  atb_offset;   /* Compensation*/
+int64_t  vtb_offset;
 uint32_t tb_freq;  /* TB frequency*/
 /* Decrementer management */
 uint64_t decr_next;/* Tick for next decr interrupt*/
diff --git a/linux-user/ppc/cpu_loop.c b/linux-user/ppc/cpu_loop.c
index 801f5ace29..c715861804 100644
--- a/linux-user/ppc/cpu_loop.c
+++ b/linux-user/ppc/cpu_loop.c
@@ -46,6 +46,11 @@ uint32_t cpu_ppc_load_atbu(CPUPPCState *env)
 return cpu_ppc_get_tb(env) >> 32;
 }
 
+uint64_t cpu_ppc_load_vtb(CPUPPCState *env)
+{
+return cpu_ppc_get_tb(env);
+}
+
 uint32_t cpu_ppc601_load_rtcu(CPUPPCState *env)
 __attribute__ (( alias ("cpu_ppc_load_tbu") ));
 
diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
index fe93cf0555..70167bae22 100644
--- a/target/ppc/cpu.h
+++ b/target/ppc/cpu.h
@@ -1327,6 +1327,8 @@ uint64_t cpu_ppc_load_atbl (CPUPPCState *env);
 uint32_t cpu_ppc_load_atbu (CPUPPCState *env);
 void cpu_ppc_store_atbl (CPUPPCState *env, uint32_t value);
 void cpu_ppc_store_atbu (CPUPPCState *env, uint32_t value);
+uint64_t cpu_ppc_load_vtb(CPUPPCState *env);
+void cpu_ppc_store_vtb(CPUPPCState *env, uint64_t value);
 bool ppc_decr_clear_on_delivery(CPUPPCState *env);
 target_ulong cpu_ppc_load_decr (CPUPPCState *env);
 void cpu_ppc_store_decr (CPUPPCState *env, target_ulong value);
diff --git a/target/ppc/helper.h b/target/ppc/helper.h
index 69cbf7922f..3701bcbf1b 100644
--- a/target/ppc/helper.h
+++ b/target/ppc/helper.h
@@ -680,6 +680,7 @@ DEF_HELPER_FLAGS_1(load_tbl, TCG_CALL_NO_RWG, tl, env)
 DEF_HELPER_FLAGS_1(load_tbu, TCG_CALL_NO_RWG, tl, env)
 DEF_HELPER_FLAGS_1(load_atbl, TCG_CALL_NO_RWG, tl, env)
 DEF_HELPER_FLAGS_1(load_atbu, TCG_CALL_NO_RWG, tl, env)
+DEF_HELPER_FLAGS_1(load_vtb, TCG_CALL_NO_RWG, tl, env)
 DEF_HELPER_FLAGS_1(load_601_rtcl, TCG_CALL_NO_RWG, tl, env)
 DEF_HELPER_FLAGS_1(load_601_rtcu, TCG_CALL_NO_RWG, tl, env)
 #if !defined(CONFIG_USER_ONLY)
@@ -700,6 +701,7 @@ DEF_HELPER_FLAGS_1(load_decr, TCG_CALL_NO_RWG, tl, env)
 DEF_HELPER_FLAGS_2(store_decr, TCG_CALL_NO_RWG, void, env, tl)
 DEF_HELPER_FLAGS_1(load_hdecr, TCG_CALL_NO_RWG, tl, env)
 DEF_HELPER_FLAGS_2(store_hdecr, TCG_CALL_NO_RWG, void, env, tl)
+DEF_HELPER_FLAGS_2(store_vtb, TCG_CALL_NO_RWG, void, env, tl)
 DEF_HELPER_2(store_hid0_601, void, env, tl)
 DEF_HELPER_3(store_403_pbr, void, env, i32, tl)
 DEF_HELPER_FLAGS_1(load_40x_pit, TCG_CALL_NO_RWG, tl, env)
diff --git a/target/ppc/timebase_helper.c b/target/ppc/timebase_helper.c
index 73363e08ae..8c3c2fe67c 100644
--- a/target/ppc/timebase_helper.c
+++ b/target/ppc/timebase_helper.c
@@ -45,6 +45,11 @@ target_ulong helper_load_atbu(CPUPPCState *env)
 return cpu_ppc_load_atbu(env);
 }
 
+target_ulong helper_load_vtb(CPUPPCState *env)
+{
+return cpu_ppc_load_vtb(env);
+}
+
 #if defined(TARGET_PPC64) && !defined(CONFIG_USER_

[Qemu-devel] [QEMU-PPC] [PATCH 03/13] target/ppc: Add SPR ASDR

2019-05-02 Thread Suraj Jitindar Singh
The Access Segment Descriptor Register (ASDR) provides information about
the storage element when taking a hypervisor storage interrupt. When
performing nested radix address translation, this is normally the guest
real address. This register is present on POWER9 processors and later.

Implement the ADSR, note read and write access is limited to the
hypervisor.

Signed-off-by: Suraj Jitindar Singh 
---
 target/ppc/cpu.h| 1 +
 target/ppc/translate_init.inc.c | 6 ++
 2 files changed, 7 insertions(+)

diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
index 19b3e1de0e..8d66265e5a 100644
--- a/target/ppc/cpu.h
+++ b/target/ppc/cpu.h
@@ -1797,6 +1797,7 @@ void ppc_compat_add_property(Object *obj, const char 
*name,
 #define SPR_MPC_MD_DBRAM1 (0x32A)
 #define SPR_RCPU_L2U_RA3  (0x32B)
 #define SPR_TAR   (0x32F)
+#define SPR_ASDR  (0x330)
 #define SPR_IC(0x350)
 #define SPR_VTB   (0x351)
 #define SPR_MMCRC (0x353)
diff --git a/target/ppc/translate_init.inc.c b/target/ppc/translate_init.inc.c
index 9cd33e79ef..a0cae58e19 100644
--- a/target/ppc/translate_init.inc.c
+++ b/target/ppc/translate_init.inc.c
@@ -8243,6 +8243,12 @@ static void gen_spr_power9_mmu(CPUPPCState *env)
 SPR_NOACCESS, SPR_NOACCESS,
 _read_generic, _write_ptcr,
 KVM_REG_PPC_PTCR, 0x);
+/* Address Segment Descriptor Register */
+spr_register_hv(env, SPR_ASDR, "ASDR",
+SPR_NOACCESS, SPR_NOACCESS,
+SPR_NOACCESS, SPR_NOACCESS,
+_read_generic, _write_generic,
+0x);
 #endif
 }
 
-- 
2.13.6




[Qemu-devel] [PATCH 2/2] ppc: Add dump-stack implementation

2019-04-30 Thread Suraj Jitindar Singh
The monitor function dump-stack is used to dump the stack for a cpu.
This can be useful for debugging purposes when the stack cannot be
dumped by another means.

Add a ppc implementation ppc_cpu_dump_stack().
The stack pointer is stored in R1 with the back pointer at offset 0 and
the link register at offset 2.
Also dump the registers from the stack frame if the marker "regshere" is
found.
This only dumps the kernel stack, stopping if a non-kernel address is
found in the stack.

Sample output:
(qemu) dump-stack
sp: 0xc0007bfc5690 lr: 0xc00974b8
sp: 0xc0007bfc56f0 lr: 0xc065aab4
sp: 0xc0007bfc5720 lr: 0xc065ab04
sp: 0xc0007bfc5740 lr: 0xc00c29b8
sp: 0xc0007bfc57b0 lr: 0xc00bc9e8
sp: 0xc0007bfc57e0 lr: 0xc00bd584
sp: 0xc0007bfc5800 lr: 0xc00bee14
sp: 0xc0007bfc5ac0 lr: 0xc00c2100
sp: 0xc0007bfc5c60 lr: 0xc0029460
sp: 0xc0007bfc5ca0 lr: 0xc010b5e8
sp: 0xc0007bfc5d00 lr: 0xc0105f34
trap : 0x0700
pc   : 0xc0104490
msr  : 0x92843003
lr   : 0xc0103ffc
gpr 0: 0x0001
gpr 1: 0xc0005051f530
gpr 2: 0xc1088200
gpr 3: 0x0001
gpr 4: 0xc00032d6
gpr 5: 0xc14b8f00
gpr 6: 0x00c835e0
gpr 7: 0x
gpr 8: 0x
gpr 9: 0xc00032f0
gpr10: 0x92803033
gpr11: 0xc0b60f00
gpr12: 0x2000
gpr13: 0xc125
gpr14: 0x
gpr15: 0x0008
gpr16: 0x
gpr17: 0xc114f790
gpr18: 0x
gpr19: 0xc0005051f8e8
gpr20: 0x0001
gpr21: 0x
gpr22: 0x0001
gpr23: 0x0001
gpr24: 0x0001
gpr25: 0xc14b8f70
gpr26: 0x
gpr27: 0x0001
gpr28: 0x0001
gpr29: 0x
gpr30: 0xc14b8f00
gpr31: 0xc14b8f00
sp: 0xc0005051f530 lr: 0x
sp: 0xc0005051f600 lr: 0xc0103ffc
sp: 0xc0005051f670 lr: 0xc00f60a8
sp: 0xc0005051f850 lr: 0xc00f18c0
sp: 0xc0005051fa10 lr: 0xc00f5184
sp: 0xc0005051fae0 lr: 0xc00ddf54
sp: 0xc0005051fb00 lr: 0xc00dab9c
sp: 0xc0005051fb90 lr: 0xc00cbf88
sp: 0xc0005051fd00 lr: 0xc03e7480
sp: 0xc0005051fdb0 lr: 0xc03e7ce4
sp: 0xc0005051fe00 lr: 0xc03e7d88
sp: 0xc0005051fe20 lr: 0xc000b3a4
trap : 0x0c01
pc   : 0x7fffa6c9d8d0
msr  : 0x9280f033
lr   : 0x10090f40
gpr 0: 0x0036
gpr 1: 0x7fffa62fdd70
gpr 2: 0x7fffa6d57300
gpr 3: 0x000d
gpr 4: 0x2000ae80
gpr 5: 0x
gpr 6: 0x0537
gpr 7: 0x
gpr 8: 0x000d
gpr 9: 0x
gpr10: 0x
gpr11: 0x
gpr12: 0x
gpr13: 0x7fffa6306380
gpr14: 0x
gpr15: 0x0001
gpr16: 0x39ba6928
gpr17: 0x
gpr18: 0x
gpr19: 0x7fffa6d702f0
gpr20: 0x7fffa62fddf0
gpr21: 0x0080
gpr22: 0x0004
gpr23: 0x
gpr24: 0x10ac85c0
gpr25: 0x0008
gpr26: 0x7fffa62fde10
gpr27: 0x
gpr28: 0x0002
gpr29: 0x
gpr30: 0x39ba6900
gpr31: 0x10ac85c0
sp: 0x7fffa62fdd70

Signed-off-by: Suraj Jitindar Singh 
---
 target/ppc/cpu.h|  1 +
 target/ppc/translate.c  | 60 +
 target/ppc/translate_init.inc.c |  1 +
 3 files changed, 62 insertions(+)

diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
index 5e7cf54b2f..28c4dffca1 100644
--- a/target/ppc/cpu.h
+++ b/target/ppc/cpu.h
@@ -1284,6 +1284,7 @@ struct PPCVirtualHypervisorClass {
 void ppc_cpu_do_interrupt(CPUState *cpu);
 bool ppc_cpu_exec_interrupt(CPUState *cpu, int int_req);
 void ppc_cpu_dump_state(CPUState *cpu, FILE *f, int flags);
+void ppc_cpu_dump_stack(CPUState *cpu, FILE *f);
 void ppc_cpu_dump_statistics(CPUState *cpu, int flags);
 hwaddr ppc_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
 int ppc_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
diff --git a/target/ppc/translate.c b/target/ppc/translate.c
index 8d08625c33..b162998ce7 100644
--- a/

[Qemu-devel] [PATCH 1/2] monitor: Add dump-stack command

2019-04-30 Thread Suraj Jitindar Singh
Add a monitor command "dump-stack" to be used to dump the stack for the
current cpu.

Signed-off-by: Suraj Jitindar Singh 
---
 hmp-commands.hx   | 13 +
 hmp.h |  1 +
 include/qom/cpu.h | 10 ++
 monitor.c | 12 
 qom/cpu.c | 10 ++
 5 files changed, 46 insertions(+)

diff --git a/hmp-commands.hx b/hmp-commands.hx
index 9b4035965c..965ccdea28 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -862,6 +862,19 @@ ETEXI
 },
 
 STEXI
+@item dump-stack
+@findex dump-stack
+dump stack of the cpu
+ETEXI
+{
+.name   = "dump-stack",
+.args_type  = "",
+.params = "",
+.help   = "dump stack",
+.cmd= hmp_dumpstack,
+},
+
+STEXI
 @item pmemsave @var{addr} @var{size} @var{file}
 @findex pmemsave
 save to disk physical memory dump starting at @var{addr} of size @var{size}.
diff --git a/hmp.h b/hmp.h
index 43617f2646..e6edf1215c 100644
--- a/hmp.h
+++ b/hmp.h
@@ -51,6 +51,7 @@ void hmp_announce_self(Monitor *mon, const QDict *qdict);
 void hmp_cpu(Monitor *mon, const QDict *qdict);
 void hmp_memsave(Monitor *mon, const QDict *qdict);
 void hmp_pmemsave(Monitor *mon, const QDict *qdict);
+void hmp_dumpstack(Monitor *mon, const QDict *qdict);
 void hmp_ringbuf_write(Monitor *mon, const QDict *qdict);
 void hmp_ringbuf_read(Monitor *mon, const QDict *qdict);
 void hmp_cont(Monitor *mon, const QDict *qdict);
diff --git a/include/qom/cpu.h b/include/qom/cpu.h
index 08abcbd3fe..f2e83e9918 100644
--- a/include/qom/cpu.h
+++ b/include/qom/cpu.h
@@ -181,6 +181,7 @@ typedef struct CPUClass {
 int (*memory_rw_debug)(CPUState *cpu, vaddr addr,
uint8_t *buf, int len, bool is_write);
 void (*dump_state)(CPUState *cpu, FILE *, int flags);
+void (*dump_stack)(CPUState *cpu, FILE *f);
 GuestPanicInformation* (*get_crash_info)(CPUState *cpu);
 void (*dump_statistics)(CPUState *cpu, int flags);
 int64_t (*get_arch_id)(CPUState *cpu);
@@ -568,6 +569,15 @@ enum CPUDumpFlags {
 void cpu_dump_state(CPUState *cpu, FILE *f, int flags);
 
 /**
+ * cpu_dump_stack:
+ * @cpu: The CPU whose stack is to be dumped.
+ * @f: If non-null, dump to this stream, else to current print sink.
+ *
+ * Dumps CPU stack.
+ */
+void cpu_dump_stack(CPUState *cpu, FILE *f);
+
+/**
  * cpu_dump_statistics:
  * @cpu: The CPU whose state is to be dumped.
  * @flags: Flags what to dump.
diff --git a/monitor.c b/monitor.c
index 9b5f10b475..dbec2e4376 100644
--- a/monitor.c
+++ b/monitor.c
@@ -1299,6 +1299,18 @@ static void hmp_info_registers(Monitor *mon, const QDict 
*qdict)
 }
 }
 
+void hmp_dumpstack(Monitor *mon, const QDict *qdict)
+{
+CPUState *cs = mon_get_cpu();
+
+if (!cs) {
+monitor_printf(mon, "No CPU available\n");
+return;
+}
+
+cpu_dump_stack(cs, NULL);
+}
+
 #ifdef CONFIG_TCG
 static void hmp_info_jit(Monitor *mon, const QDict *qdict)
 {
diff --git a/qom/cpu.c b/qom/cpu.c
index 3c5493c96c..0dc10004f4 100644
--- a/qom/cpu.c
+++ b/qom/cpu.c
@@ -230,6 +230,16 @@ void cpu_dump_state(CPUState *cpu, FILE *f, int flags)
 }
 }
 
+void cpu_dump_stack(CPUState *cpu, FILE *f)
+{
+CPUClass *cc = CPU_GET_CLASS(cpu);
+
+if (cc->dump_stack) {
+cpu_synchronize_state(cpu);
+cc->dump_stack(cpu, f);
+}
+}
+
 void cpu_dump_statistics(CPUState *cpu, int flags)
 {
 CPUClass *cc = CPU_GET_CLASS(cpu);
-- 
2.13.6




Re: [Qemu-devel] [Qemu-ppc] [PATCH for-4.0 3/3] target/ppc: Consolidate 64-bit server processor detection in a helper

2019-03-24 Thread Suraj Jitindar Singh
On Fri, 2019-03-22 at 19:03 +0100, Greg Kurz wrote:
> We use PPC_SEGMENT_64B in various places to guard code that is
> specific
> to 64-bit server processors compliant with arch 2.x. Consolidate the
> logic in a helper macro with an explicit name.

Tested-by: Suraj Jitindar Singh 

> 
> Signed-off-by: Greg Kurz 
> ---
>  hw/ppc/ppc.c |2 +-
>  target/ppc/cpu.h |6 ++
>  target/ppc/helper_regs.h |2 +-
>  target/ppc/translate.c   |   10 --
>  4 files changed, 12 insertions(+), 8 deletions(-)
> 
> diff --git a/hw/ppc/ppc.c b/hw/ppc/ppc.c
> index 49d57469fb34..ad20584f268d 100644
> --- a/hw/ppc/ppc.c
> +++ b/hw/ppc/ppc.c
> @@ -1101,7 +1101,7 @@ clk_setup_cb cpu_ppc_tb_init (CPUPPCState *env,
> uint32_t freq)
>  tb_env = g_malloc0(sizeof(ppc_tb_t));
>  env->tb_env = tb_env;
>  tb_env->flags = PPC_DECR_UNDERFLOW_TRIGGERED;
> -if (env->insns_flags & PPC_SEGMENT_64B) {
> +if (is_book3s_arch2x(env)) {
>  /* All Book3S 64bit CPUs implement level based DEC logic */
>  tb_env->flags |= PPC_DECR_UNDERFLOW_LEVEL;
>  }
> diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
> index fc12b4688e8c..070717758452 100644
> --- a/target/ppc/cpu.h
> +++ b/target/ppc/cpu.h
> @@ -2409,6 +2409,12 @@ enum {
>  target_ulong cpu_read_xer(CPUPPCState *env);
>  void cpu_write_xer(CPUPPCState *env, target_ulong xer);
>  
> +/*
> + * All 64-bit server processors compliant with arch 2.x, ie. 970 and
> newer,
> + * have PPC_SEGMENT_64B.
> + */
> +#define is_book3s_arch2x(ctx) (!!((ctx)->insns_flags &
> PPC_SEGMENT_64B))
> +
>  static inline void cpu_get_tb_cpu_state(CPUPPCState *env,
> target_ulong *pc,
>  target_ulong *cs_base,
> uint32_t *flags)
>  {
> diff --git a/target/ppc/helper_regs.h b/target/ppc/helper_regs.h
> index a2205e1044c9..c863abc0bfc3 100644
> --- a/target/ppc/helper_regs.h
> +++ b/target/ppc/helper_regs.h
> @@ -152,7 +152,7 @@ static inline int hreg_store_msr(CPUPPCState
> *env, target_ulong value,
>   * - 64-bit embedded implementations do not need any operation
> to be
>   *   performed when PR is set.
>   */
> -if ((env->insns_flags & PPC_SEGMENT_64B) && ((value >> MSR_PR) &
> 1)) {
> +if (is_book3s_arch2x(env) && ((value >> MSR_PR) & 1)) {
>  value |= (1 << MSR_EE) | (1 << MSR_DR) | (1 << MSR_IR);
>  }
>  #endif
> diff --git a/target/ppc/translate.c b/target/ppc/translate.c
> index d3aaa6482c6a..576210d901ad 100644
> --- a/target/ppc/translate.c
> +++ b/target/ppc/translate.c
> @@ -3755,7 +3755,7 @@ static void gen_bcond(DisasContext *ctx, int
> type)
>   * arch 2.x, do implement a "test and decrement" logic
> instead,
>   * as described in their respective UMs.
>   */
> -if (unlikely(!(ctx->insns_flags & PPC_SEGMENT_64B))) {
> +if (unlikely(!is_book3s_arch2x(ctx))) {
>  gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
>  tcg_temp_free(temp);
>  tcg_temp_free(target);
> @@ -3913,7 +3913,7 @@ static void gen_rfi(DisasContext *ctx)
>  /* This instruction doesn't exist anymore on 64-bit server
>   * processors compliant with arch 2.x
>   */
> -if (ctx->insns_flags & PPC_SEGMENT_64B) {
> +if (is_book3s_arch2x(ctx)) {
>  gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
>  return;
>  }
> @@ -6535,8 +6535,7 @@ static void gen_msgclr(DisasContext *ctx)
>  GEN_PRIV;
>  #else
>  CHK_HV;
> -/* 64-bit server processors compliant with arch 2.x */
> -if (ctx->insns_flags & PPC_SEGMENT_64B) {
> +if (is_book3s_arch2x(ctx)) {
>  gen_helper_book3s_msgclr(cpu_env, cpu_gpr[rB(ctx->opcode)]);
>  } else {
>  gen_helper_msgclr(cpu_env, cpu_gpr[rB(ctx->opcode)]);
> @@ -6550,8 +6549,7 @@ static void gen_msgsnd(DisasContext *ctx)
>  GEN_PRIV;
>  #else
>  CHK_HV;
> -/* 64-bit server processors compliant with arch 2.x */
> -if (ctx->insns_flags & PPC_SEGMENT_64B) {
> +if (is_book3s_arch2x(ctx)) {
>  gen_helper_book3s_msgsnd(cpu_gpr[rB(ctx->opcode)]);
>  } else {
>  gen_helper_msgsnd(cpu_gpr[rB(ctx->opcode)]);
> 
> 



Re: [Qemu-devel] [Qemu-ppc] [PATCH for-4.0 1/3] target/ppc: Fix TCG temporary leaks in gen_bcond()

2019-03-24 Thread Suraj Jitindar Singh
On Fri, 2019-03-22 at 19:03 +0100, Greg Kurz wrote:
> Signed-off-by: Greg Kurz 

Tested-by: Suraj Jitindar Singh 

> ---
>  target/ppc/translate.c |2 ++
>  1 file changed, 2 insertions(+)
> 
> diff --git a/target/ppc/translate.c b/target/ppc/translate.c
> index 98b37cebc2f5..aaafa3a715d8 100644
> --- a/target/ppc/translate.c
> +++ b/target/ppc/translate.c
> @@ -3749,6 +3749,8 @@ static void gen_bcond(DisasContext *ctx, int
> type)
>  TCGv temp = tcg_temp_new();
>  if (unlikely(type == BCOND_CTR)) {
>  gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
> +tcg_temp_free(temp);
> +tcg_temp_free(target);
>  return;
>  }
>  tcg_gen_subi_tl(cpu_ctr, cpu_ctr, 1);
> 
> 



Re: [Qemu-devel] [Qemu-ppc] [PATCH for-4.0 2/3] target/ppc: Enable "decrement and test CTR" version of bcctr

2019-03-24 Thread Suraj Jitindar Singh
On Fri, 2019-03-22 at 19:03 +0100, Greg Kurz wrote:
> Even if all ISAs up to v3 indeed mention:
> 
> If the "decrement and test CTR" option is specified (BO2=0), the
> instruction form is invalid.
> 
> The UMs of all existing 64-bit server class processors say:
> 
> If BO[2] = 0, the contents of CTR (before any update) are used as
> the
> target address and for the test of the contents of CTR to resolve
> the
> branch. The contents of the CTR are then decremented and written
> back
> to the CTR.
> 
> The linux kernel has spectre v2 mitigation code that relies on a
> BO[2] = 0 variant of bcctr, which is now activated by default on
> spapr, even with TCG. This causes linux guests to panic with
> the default machine type under TCG.
> 
> Since any CPU model can provide its own behaviour for invalid forms,
> we could possibly introduce a new instruction flag to handle this.
> In practice, since the behaviour is shared by all 64-bit server
> processors starting with 970 up to POWER9, let's reuse the
> PPC_SEGMENT_64B flag. Caveat: this may have to be fixed later if
> POWER10 introduces a different behaviour.
> 
> The existing behaviour of throwing a program interrupt is kept for
> all other CPU models.
> 
> Signed-off-by: Greg Kurz 

Tested-by: Suraj Jitindar Singh 

> ---
>  target/ppc/translate.c |   52 ++--
> 
>  1 file changed, 37 insertions(+), 15 deletions(-)
> 
> diff --git a/target/ppc/translate.c b/target/ppc/translate.c
> index aaafa3a715d8..d3aaa6482c6a 100644
> --- a/target/ppc/translate.c
> +++ b/target/ppc/translate.c
> @@ -3747,22 +3747,44 @@ static void gen_bcond(DisasContext *ctx, int
> type)
>  if ((bo & 0x4) == 0) {
>  /* Decrement and test CTR */
>  TCGv temp = tcg_temp_new();
> -if (unlikely(type == BCOND_CTR)) {
> -gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
> -tcg_temp_free(temp);
> -tcg_temp_free(target);
> -return;
> -}
> -tcg_gen_subi_tl(cpu_ctr, cpu_ctr, 1);
> -if (NARROW_MODE(ctx)) {
> -tcg_gen_ext32u_tl(temp, cpu_ctr);
> -} else {
> -tcg_gen_mov_tl(temp, cpu_ctr);
> -}
> -if (bo & 0x2) {
> -tcg_gen_brcondi_tl(TCG_COND_NE, temp, 0, l1);
> +
> +if (type == BCOND_CTR) {
> +/*
> + * All ISAs up to v3 describe this form of bcctr as
> invalid but
> + * some processors, ie. 64-bit server processors
> compliant with
> + * arch 2.x, do implement a "test and decrement" logic
> instead,
> + * as described in their respective UMs.
> + */
> +if (unlikely(!(ctx->insns_flags & PPC_SEGMENT_64B))) {
> +gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
> +tcg_temp_free(temp);
> +tcg_temp_free(target);
> +return;
> +}
> +
> +if (NARROW_MODE(ctx)) {
> +tcg_gen_ext32u_tl(temp, cpu_ctr);
> +} else {
> +tcg_gen_mov_tl(temp, cpu_ctr);
> +}
> +if (bo & 0x2) {
> +tcg_gen_brcondi_tl(TCG_COND_NE, temp, 0, l1);
> +} else {
> +tcg_gen_brcondi_tl(TCG_COND_EQ, temp, 0, l1);
> +}
> +tcg_gen_subi_tl(cpu_ctr, cpu_ctr, 1);
>  } else {
> -tcg_gen_brcondi_tl(TCG_COND_EQ, temp, 0, l1);
> +tcg_gen_subi_tl(cpu_ctr, cpu_ctr, 1);
> +if (NARROW_MODE(ctx)) {
> +tcg_gen_ext32u_tl(temp, cpu_ctr);
> +} else {
> +tcg_gen_mov_tl(temp, cpu_ctr);
> +}
> +if (bo & 0x2) {
> +tcg_gen_brcondi_tl(TCG_COND_NE, temp, 0, l1);
> +} else {
> +tcg_gen_brcondi_tl(TCG_COND_EQ, temp, 0, l1);
> +}
>  }
>  tcg_temp_free(temp);
>  }
> 
> 



Re: [Qemu-devel] [Qemu-ppc] [PATCH for-4.0 0/3] target/ppc: Fix pseries.cap-ibs=workaround with TCG

2019-03-24 Thread Suraj Jitindar Singh
On Fri, 2019-03-22 at 19:03 +0100, Greg Kurz wrote:
> Since recent commit 2782ad4c4102 "target/ppc/spapr: Enable
> mitigations by
> default for pseries-4.0 machine type", some recent distros, eg.
> fedora29,
> fail to boot under TCG because of a kernel panic:

Good catch! I noticed this as well but didn't get around to fixing it
so thanks for doing it for me :D

> 
> [0.614425] Oops: Exception in kernel mode, sig: 4 [#1]
> [0.618832] LE SMP NR_CPUS=1024 NUMA pSeries
> [0.621868] Modules linked in:
> [0.624958] CPU: 0 PID: 0 Comm: swapper/0 Not tainted 4.20.16-
> 200.fc29.ppc64le #1
> [0.625978] NIP:  c000bf00 LR: c000e268 CTR:
> 7fff
> [0.626572] REGS: c15a3750 TRAP: 0700   Not
> tainted  (4.20.16-200.fc29.ppc64le)
> [0.626835] MSR:  82089033   CR:
> 44828222  XER: 
> [0.628497] CFAR: c000bee4 IRQMASK: 1 
> [0.628497] GPR00: c001fbc8 c15a39e0
> c15a6200 c1533450 
> [0.628497] GPR04: c0003e5819d0 c0003ff15f68
>  22f63728 
> [0.628497] GPR08:  7fff
>   
> [0.628497] GPR12: 8000 c18b
> 3dc5fd20 02e75e90 
> [0.628497] GPR16: 02e75d40 c0003e594d00
> 3dc5fd20 02e90b50 
> [0.628497] GPR20: 3e45e800 c1531a80
> c1532100 44828222 
> [0.628497] GPR24: c1533450 c1533450
> c0003e5819d0 c10e51e0 
> [0.628497] GPR28: c15d5c18 c1531a80
> c0003e58 c1531a80 
> [0.631710] NIP [c000bf00] flush_count_cache+0x120/0x2420
> [0.631905] LR [c000e268] _switch+0x68/0x180
> [0.632585] Call Trace:
> [0.633490] [c15a39e0] [c15dbd58]
> __cpu_online_mask+0x0/0x80 (unreliable)
> [0.634383] [c15a3bc0] [c001fbc8]
> __switch_to+0x348/0x500
> [0.634614] [c15a3c20] [c0c509dc]
> __schedule+0x2bc/0xac0
> [0.634731] [c15a3cf0] [c0c51648]
> preempt_schedule_common+0x38/0x60
> [0.634852] [c15a3d10] [c0c516d4]
> _cond_resched+0x64/0x80
> [0.635527] [c15a3d40] [c011a190]
> copy_process.isra.4.part.5+0xc90/0x1d20
> [0.635656] [c15a3e40] [c011b414]
> _do_fork+0xd4/0x470
> [0.635772] [c15a3eb0] [c011b88c]
> kernel_thread+0x3c/0x50
> [0.635891] [c15a3ed0] [c0010b08]
> rest_init+0x98/0xf8
> [0.636025] [c15a3f00] [c0fe4084]
> start_kernel+0x658/0x67c
> [0.636163] [c15a3f90] [c000b37c]
> start_here_common+0x1c/0x520
> [0.636763] Instruction dump:
> [0.640925] 4805 4805 4805 4805 4805 481c
> 6000 6000 
> [0.641448] 6000 6000 6000 6000 <7d2803a6>
> 39207fff 7d2903a6 4c400420 
> [0.648580] ---[ end trace 1dcd9494acdef8df ]---
> [0.649361] 
> [1.657870] Kernel panic - not syncing: Attempted to kill the idle
> task!
> 
> The following error is also printed by QEMU:
> 
> Opcode 13 10 10 00 (4c400420) leaked temporaries
> 
> The root cause behind the panic is that the linux kernel uses for
> spectre v2
> mitigation a form of the bcctr instruction that we don't support.
> This gets
> triggered when passing cap-ibs=workaround machine option, which is
> the default
> since 2782ad4c4102.
> 
> The TCG temp leak comes from some missing tcg_temp_free()s on the
> exception path.
> 
> This series fixes the leak and adds support for the invalid form of
> bcctr.
> Since this adds yet another user of PPC_SEGMENT_64B to discriminate
> CPU
> models that should expose the _new_ behaviour, the final patch
> introduces
> a helper for that purpose.
> 
> --
> Greg
> 
> ---
> 
> Greg Kurz (3):
>   target/ppc: Fix TCG temporary leaks in gen_bcond()
>   target/ppc: Enable "decrement and test CTR" version of bcctr
>   target/ppc: Consolidate 64-bit server processor detection in a
> helper
> 
> 
>  hw/ppc/ppc.c |2 +-
>  target/ppc/cpu.h |6 +
>  target/ppc/helper_regs.h |2 +-
>  target/ppc/translate.c   |   58 --
> 
>  4 files changed, 48 insertions(+), 20 deletions(-)
> 
> 



[Qemu-devel] [QEMU-PPC] [PATCH] target/ppc/spapr: Enable H_PAGE_INIT in-kernel handling

2019-03-05 Thread Suraj Jitindar Singh
The H_CALL H_PAGE_INIT can be used to zero or copy a page of guest
memory. Enable the in-kernel H_PAGE_INIT handler.

The in-kernel handler takes half the time to complete compared to
handling the H_CALL in userspace.

Signed-off-by: Suraj Jitindar Singh 
---
 hw/ppc/spapr.c   | 3 +++
 target/ppc/kvm.c | 5 +
 target/ppc/kvm_ppc.h | 5 +
 3 files changed, 13 insertions(+)

diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index cf1ef9ebd4..8ce97ff1e7 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -2822,6 +2822,9 @@ static void spapr_machine_init(MachineState *machine)
 
 /* H_CLEAR_MOD/_REF are mandatory in PAPR, but off by default */
 kvmppc_enable_clear_ref_mod_hcalls();
+
+/* Enable H_PAGE_INIT */
+kvmppc_enable_h_page_init();
 }
 
 /* allocate RAM */
diff --git a/target/ppc/kvm.c b/target/ppc/kvm.c
index 4e3f1e4b78..d0bfb076df 100644
--- a/target/ppc/kvm.c
+++ b/target/ppc/kvm.c
@@ -2043,6 +2043,11 @@ void kvmppc_enable_clear_ref_mod_hcalls(void)
 kvmppc_enable_hcall(kvm_state, H_CLEAR_MOD);
 }
 
+void kvmppc_enable_h_page_init(void)
+{
+kvmppc_enable_hcall(kvm_state, H_PAGE_INIT);
+}
+
 void kvmppc_set_papr(PowerPCCPU *cpu)
 {
 CPUState *cs = CPU(cpu);
diff --git a/target/ppc/kvm_ppc.h b/target/ppc/kvm_ppc.h
index 2937b36cae..2c2ea30e87 100644
--- a/target/ppc/kvm_ppc.h
+++ b/target/ppc/kvm_ppc.h
@@ -23,6 +23,7 @@ int kvmppc_set_interrupt(PowerPCCPU *cpu, int irq, int level);
 void kvmppc_enable_logical_ci_hcalls(void);
 void kvmppc_enable_set_mode_hcall(void);
 void kvmppc_enable_clear_ref_mod_hcalls(void);
+void kvmppc_enable_h_page_init(void);
 void kvmppc_set_papr(PowerPCCPU *cpu);
 int kvmppc_set_compat(PowerPCCPU *cpu, uint32_t compat_pvr);
 void kvmppc_set_mpic_proxy(PowerPCCPU *cpu, int mpic_proxy);
@@ -138,6 +139,10 @@ static inline void kvmppc_enable_clear_ref_mod_hcalls(void)
 {
 }
 
+static inline void kvmppc_enable_h_page_init(void)
+{
+}
+
 static inline void kvmppc_set_papr(PowerPCCPU *cpu)
 {
 }
-- 
2.13.6




[Qemu-devel] [QEMU-PPC] [PATCH] target/ppc/spapr: Clear partition table entry when allocating hash table

2019-03-04 Thread Suraj Jitindar Singh
If we allocate a hash page table then we know that the guest won't be
using process tables, so set the partition table entry maintained for
the guest to zero. If this isn't done, then the guest radix bit will
remain set in the entry. This means that when the guest calls
H_REGISTER_PROCESS_TABLE there will be a mismatch between then flags
and the value in spapr->patb_entry, and the call will fail. The guest
will then panic:

Failed to register process table (rc=-4)
kernel BUG at arch/powerpc/platforms/pseries/lpar.c:959

The result being that it isn't possible to boot a hash guest on a P9
system.

Also fix a bug in the flags parsing in h_register_process_table() which
was introduced by the same patch, and simplify the handling to make it
less likely that errors will be introduced in the future. The effect
would have been setting the host radix bit LPCR_HR for a hash guest
using process tables, which currently isn't supported and so couldn't
have been triggered.

Fixes: 00fd075e18 "target/ppc/spapr: Set LPCR:HR when using Radix mode"

Signed-off-by: Suraj Jitindar Singh 
---
 hw/ppc/spapr.c   |  1 +
 hw/ppc/spapr_hcall.c | 12 
 2 files changed, 9 insertions(+), 4 deletions(-)

diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index e39068578e..cf1ef9ebd4 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -1632,6 +1632,7 @@ void spapr_reallocate_hpt(sPAPRMachineState *spapr, int 
shift,
 }
 }
 /* We're setting up a hash table, so that means we're not radix */
+spapr->patb_entry = 0;
 spapr_set_all_lpcrs(0, LPCR_HR | LPCR_UPRT);
 }
 
diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c
index 8bfdddc964..7016a09386 100644
--- a/hw/ppc/spapr_hcall.c
+++ b/hw/ppc/spapr_hcall.c
@@ -1339,6 +1339,7 @@ static target_ulong h_register_process_table(PowerPCCPU 
*cpu,
 target_ulong proc_tbl = args[1];
 target_ulong page_size = args[2];
 target_ulong table_size = args[3];
+target_ulong update_lpcr = 0;
 uint64_t cproc;
 
 if (flags & ~FLAGS_MASK) { /* Check no reserved bits are set */
@@ -1394,10 +1395,13 @@ static target_ulong h_register_process_table(PowerPCCPU 
*cpu,
 spapr->patb_entry = cproc; /* Save new process table */
 
 /* Update the UPRT, HR and GTSE bits in the LPCR for all cpus */
-spapr_set_all_lpcrs(((flags & (FLAG_RADIX | FLAG_HASH_PROC_TBL)) ?
- (LPCR_UPRT | LPCR_HR) : 0) |
-((flags & FLAG_GTSE) ? LPCR_GTSE : 0),
-LPCR_UPRT | LPCR_HR | LPCR_GTSE);
+if (flags & FLAG_RADIX) /* Radix must use process tables, also set HR 
*/
+update_lpcr |= (LPCR_UPRT | LPCR_HR);
+else if (flags & FLAG_HASH_PROC_TBL) /* Hash with process tables */
+update_lpcr |= LPCR_UPRT;
+if (flags & FLAG_GTSE)  /* Guest translation shootdown enable */
+update_lpcr |= FLAG_GTSE;
+spapr_set_all_lpcrs(update_lpcr, LPCR_UPRT | LPCR_HR | LPCR_GTSE);
 
 if (kvm_enabled()) {
 return kvmppc_configure_v3_mmu(cpu, flags & FLAG_RADIX,
-- 
2.13.6




[Qemu-devel] [QEMU-PPC] [PATCH 2/2] target/ppc/spapr: Enable mitigations by default for pseries-4.0 machine type

2019-02-28 Thread Suraj Jitindar Singh
There are currently 3 mitigations the availability of which is controlled
by the spapr-caps mechanism, cap-cfpc, cap-sbbc, and cap-ibs. Enable these
mitigations by default for the pseries-4.0 machine type.

By now machine firmware should have been upgraded to allow these
settings.

Signed-off-by: Suraj Jitindar Singh 
---
 hw/ppc/spapr.c | 9 ++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index 708e18dcdf..b103d2677e 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -4314,9 +4314,9 @@ static void spapr_machine_class_init(ObjectClass *oc, 
void *data)
 smc->default_caps.caps[SPAPR_CAP_HTM] = SPAPR_CAP_OFF;
 smc->default_caps.caps[SPAPR_CAP_VSX] = SPAPR_CAP_ON;
 smc->default_caps.caps[SPAPR_CAP_DFP] = SPAPR_CAP_ON;
-smc->default_caps.caps[SPAPR_CAP_CFPC] = SPAPR_CAP_BROKEN;
-smc->default_caps.caps[SPAPR_CAP_SBBC] = SPAPR_CAP_BROKEN;
-smc->default_caps.caps[SPAPR_CAP_IBS] = SPAPR_CAP_BROKEN;
+smc->default_caps.caps[SPAPR_CAP_CFPC] = SPAPR_CAP_WORKAROUND;
+smc->default_caps.caps[SPAPR_CAP_SBBC] = SPAPR_CAP_WORKAROUND;
+smc->default_caps.caps[SPAPR_CAP_IBS] = SPAPR_CAP_WORKAROUND;
 smc->default_caps.caps[SPAPR_CAP_HPT_MAXPAGESIZE] = 16; /* 64kiB */
 smc->default_caps.caps[SPAPR_CAP_NESTED_KVM_HV] = SPAPR_CAP_OFF;
 smc->default_caps.caps[SPAPR_CAP_LARGE_DECREMENTER] = SPAPR_CAP_ON;
@@ -4396,6 +4396,9 @@ static void spapr_machine_3_1_class_options(MachineClass 
*mc)
 mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power8_v2.0");
 smc->update_dt_enabled = false;
 smc->dr_phb_enabled = false;
+smc->default_caps.caps[SPAPR_CAP_CFPC] = SPAPR_CAP_BROKEN;
+smc->default_caps.caps[SPAPR_CAP_SBBC] = SPAPR_CAP_BROKEN;
+smc->default_caps.caps[SPAPR_CAP_IBS] = SPAPR_CAP_BROKEN;
 smc->default_caps.caps[SPAPR_CAP_LARGE_DECREMENTER] = SPAPR_CAP_OFF;
 }
 
-- 
2.13.6




[Qemu-devel] [QEMU-PPC] [PATCH 0/2] Enable mitigations by default for pseries-4.0 machine type

2019-02-28 Thread Suraj Jitindar Singh
This series is based on the ppc-for-4.0 branch with my large-decrementer
and count-cache-flush series applied.

Suraj Jitindar Singh (2):
  target/ppc/tcg: make spapr_caps apply cap-[cfpc/sbbc/ibs] non-fatal
for tcg
  target/ppc/spapr: Enable mitigations by default for pseries-4.0
machine type

 hw/ppc/spapr.c  |  9 ++---
 hw/ppc/spapr_caps.c | 33 -
 2 files changed, 30 insertions(+), 12 deletions(-)

-- 
2.13.6




[Qemu-devel] [QEMU-PPC] [PATCH 1/2] target/ppc/tcg: make spapr_caps apply cap-[cfpc/sbbc/ibs] non-fatal for tcg

2019-02-28 Thread Suraj Jitindar Singh
The spapr_caps cap-cfpc, cap-sbbc and cap-ibs are used to control the
availability of certain mitigations to the guest. These haven't been
implemented under TCG, it is unlikely they ever will be, and it is unclear
as to whether they even need to be.

As such, make failure to apply these capabilities under TCG non-fatal.
Instead we print a warning message to the user but still allow the guest
to continue.

Signed-off-by: Suraj Jitindar Singh 
---
 hw/ppc/spapr_caps.c | 33 -
 1 file changed, 24 insertions(+), 9 deletions(-)

diff --git a/hw/ppc/spapr_caps.c b/hw/ppc/spapr_caps.c
index f03f2f64e7..b68d767d63 100644
--- a/hw/ppc/spapr_caps.c
+++ b/hw/ppc/spapr_caps.c
@@ -239,17 +239,22 @@ sPAPRCapPossible cap_cfpc_possible = {
 static void cap_safe_cache_apply(sPAPRMachineState *spapr, uint8_t val,
  Error **errp)
 {
+Error *local_err = NULL;
 uint8_t kvm_val =  kvmppc_get_cap_safe_cache();
 
 if (tcg_enabled() && val) {
-/* TODO - for now only allow broken for TCG */
-error_setg(errp,
-"Requested safe cache capability level not supported by tcg, try a different 
value for cap-cfpc");
+/* TCG only supports broken, allow other values and print a warning */
+error_setg(_err,
+   "TCG doesn't support requested feature, cap-cfpc=%s",
+   cap_cfpc_possible.vals[val]);
 } else if (kvm_enabled() && (val > kvm_val)) {
 error_setg(errp,
 "Requested safe cache capability level not supported by kvm, try cap-cfpc=%s",
cap_cfpc_possible.vals[kvm_val]);
 }
+
+if (local_err != NULL)
+warn_report_err(local_err);
 }
 
 sPAPRCapPossible cap_sbbc_possible = {
@@ -262,17 +267,22 @@ sPAPRCapPossible cap_sbbc_possible = {
 static void cap_safe_bounds_check_apply(sPAPRMachineState *spapr, uint8_t val,
 Error **errp)
 {
+Error *local_err = NULL;
 uint8_t kvm_val =  kvmppc_get_cap_safe_bounds_check();
 
 if (tcg_enabled() && val) {
-/* TODO - for now only allow broken for TCG */
-error_setg(errp,
-"Requested safe bounds check capability level not supported by tcg, try a 
different value for cap-sbbc");
+/* TCG only supports broken, allow other values and print a warning */
+error_setg(_err,
+   "TCG doesn't support requested feature, cap-sbbc=%s",
+   cap_sbbc_possible.vals[val]);
 } else if (kvm_enabled() && (val > kvm_val)) {
 error_setg(errp,
 "Requested safe bounds check capability level not supported by kvm, try 
cap-sbbc=%s",
cap_sbbc_possible.vals[kvm_val]);
 }
+
+if (local_err != NULL)
+warn_report_err(local_err);
 }
 
 sPAPRCapPossible cap_ibs_possible = {
@@ -288,17 +298,22 @@ sPAPRCapPossible cap_ibs_possible = {
 static void cap_safe_indirect_branch_apply(sPAPRMachineState *spapr,
uint8_t val, Error **errp)
 {
+Error *local_err = NULL;
 uint8_t kvm_val = kvmppc_get_cap_safe_indirect_branch();
 
 if (tcg_enabled() && val) {
-/* TODO - for now only allow broken for TCG */
-error_setg(errp,
-"Requested safe indirect branch capability level not supported by tcg, try a 
different value for cap-ibs");
+/* TCG only supports broken, allow other values and print a warning */
+error_setg(_err,
+   "TCG doesn't support requested feature, cap-ibs=%s",
+   cap_ibs_possible.vals[val]);
 } else if (kvm_enabled() && (val > kvm_val)) {
 error_setg(errp,
 "Requested safe indirect branch capability level not supported by kvm, try 
cap-ibs=%s",
cap_ibs_possible.vals[kvm_val]);
 }
+
+if (local_err != NULL)
+warn_report_err(local_err);
 }
 
 #define VALUE_DESC_TRISTATE " (broken, workaround, fixed)"
-- 
2.13.6




Re: [Qemu-devel] [QEMU-PPC] [PATCH 2/2] target/ppc/spapr: Add SPAPR_CAP_CCF_ASSIST

2019-02-28 Thread Suraj Jitindar Singh
On Fri, 2019-03-01 at 14:19 +1100, Suraj Jitindar Singh wrote:
> Introduce a new spapr_cap SPAPR_CAP_CCF_ASSIST to be used to indicate
> the requirement for a hw-assisted version of the count cache flush
> workaround.
> 
> The count cache flush workaround is a software workaround which can
> be
> used to flush the count cache on context switch. Some revisions of
> hardware may have a hardware accelerated flush, in which case the
> software flush can be shortened. This cap is used to set the
> availability of such hardware acceleration for the count cache flush
> routine.
> 
> The availability of such hardware acceleration is indicated by the
> H_CPU_CHAR_BCCTR_FLUSH_ASSIST flag being set in the characteristics
> returned from the KVM_PPC_GET_CPU_CHAR ioctl.
> 
> Signed-off-by: Suraj Jitindar Singh 
> ---
>  hw/ppc/spapr.c |  2 ++
>  hw/ppc/spapr_caps.c| 25 +
>  hw/ppc/spapr_hcall.c   |  3 +++
>  include/hw/ppc/spapr.h |  5 -
>  target/ppc/kvm.c   | 14 ++
>  target/ppc/kvm_ppc.h   |  6 ++
>  6 files changed, 54 insertions(+), 1 deletion(-)
> 
> diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
> index 1df324379f..708e18dcdf 100644
> --- a/hw/ppc/spapr.c
> +++ b/hw/ppc/spapr.c
> @@ -2086,6 +2086,7 @@ static const VMStateDescription vmstate_spapr =
> {
>  _spapr_cap_nested_kvm_hv,
>  _spapr_dtb,
>  _spapr_cap_large_decr,
> +_spapr_cap_ccf_assist,
>  NULL
>  }
>  };
> @@ -4319,6 +4320,7 @@ static void
> spapr_machine_class_init(ObjectClass *oc, void *data)
>  smc->default_caps.caps[SPAPR_CAP_HPT_MAXPAGESIZE] = 16; /* 64kiB
> */
>  smc->default_caps.caps[SPAPR_CAP_NESTED_KVM_HV] = SPAPR_CAP_OFF;
>  smc->default_caps.caps[SPAPR_CAP_LARGE_DECREMENTER] =
> SPAPR_CAP_ON;
> +smc->default_caps.caps[SPAPR_CAP_CCF_ASSIST] = SPAPR_CAP_OFF;
>  spapr_caps_add_properties(smc, _abort);
>  smc->irq = _irq_xics;
>  smc->dr_phb_enabled = true;
> diff --git a/hw/ppc/spapr_caps.c b/hw/ppc/spapr_caps.c
> index 74a48a423a..f03f2f64e7 100644
> --- a/hw/ppc/spapr_caps.c
> +++ b/hw/ppc/spapr_caps.c
> @@ -436,6 +436,21 @@ static void
> cap_large_decr_cpu_apply(sPAPRMachineState *spapr,
>  ppc_store_lpcr(cpu, lpcr);
>  }
>  
> +static void cap_ccf_assist_apply(sPAPRMachineState *spapr, uint8_t
> val,
> + Error **errp)
> +{
> +uint8_t kvm_val = kvmppc_get_cap_count_cache_flush_assist();
> +
> +if (tcg_enabled() && val) {
> +/* TODO - for now only allow broken for TCG */
> +error_setg(errp,
> +"Requested count cache flush assist capability level not supported
> by tcg, try cap-ccf-assist=off");
> +} else if (kvm_enabled() && (val > kvm_val)) {
> +error_setg(errp,
> +"Requested count cache flush assist capability level not supported
> by kvm, try cap-ccf-assist=off");
> +}

Actually, this should probably be non-fatal if the count cache flush
routine isn't enabled

> +}
> +
>  sPAPRCapabilityInfo capability_table[SPAPR_CAP_NUM] = {
>  [SPAPR_CAP_HTM] = {
>  .name = "htm",
> @@ -525,6 +540,15 @@ sPAPRCapabilityInfo
> capability_table[SPAPR_CAP_NUM] = {
>  .apply = cap_large_decr_apply,
>  .cpu_apply = cap_large_decr_cpu_apply,
>  },
> +[SPAPR_CAP_CCF_ASSIST] = {
> +.name = "ccf-assist",
> +.description = "Count Cache Flush Assist via HW
> Instruction",
> +.index = SPAPR_CAP_CCF_ASSIST,
> +.get = spapr_cap_get_bool,
> +.set = spapr_cap_set_bool,
> +.type = "bool",
> +.apply = cap_ccf_assist_apply,
> +},
>  };
>  
>  static sPAPRCapabilities default_caps_with_cpu(sPAPRMachineState
> *spapr,
> @@ -659,6 +683,7 @@ SPAPR_CAP_MIG_STATE(sbbc, SPAPR_CAP_SBBC);
>  SPAPR_CAP_MIG_STATE(ibs, SPAPR_CAP_IBS);
>  SPAPR_CAP_MIG_STATE(nested_kvm_hv, SPAPR_CAP_NESTED_KVM_HV);
>  SPAPR_CAP_MIG_STATE(large_decr, SPAPR_CAP_LARGE_DECREMENTER);
> +SPAPR_CAP_MIG_STATE(ccf_assist, SPAPR_CAP_CCF_ASSIST);
>  
>  void spapr_caps_init(sPAPRMachineState *spapr)
>  {
> diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c
> index 4aa8036fc0..8bfdddc964 100644
> --- a/hw/ppc/spapr_hcall.c
> +++ b/hw/ppc/spapr_hcall.c
> @@ -1693,6 +1693,7 @@ static target_ulong
> h_get_cpu_characteristics(PowerPCCPU *cpu,
>  uint8_t safe_cache = spapr_get_cap(spapr, SPAPR_CAP_CFPC);
>  uint8_t safe_bounds_check = spapr_get_cap(spapr,
> SPAPR_CAP_SBBC);
>  uint8_t safe_indirect_branch = spapr_get_cap(spapr,
> SPAPR_CAP_IBS);
>

[Qemu-devel] [QEMU-PPC] [PATCH 2/2] target/ppc/spapr: Add SPAPR_CAP_CCF_ASSIST

2019-02-28 Thread Suraj Jitindar Singh
Introduce a new spapr_cap SPAPR_CAP_CCF_ASSIST to be used to indicate
the requirement for a hw-assisted version of the count cache flush
workaround.

The count cache flush workaround is a software workaround which can be
used to flush the count cache on context switch. Some revisions of
hardware may have a hardware accelerated flush, in which case the
software flush can be shortened. This cap is used to set the
availability of such hardware acceleration for the count cache flush
routine.

The availability of such hardware acceleration is indicated by the
H_CPU_CHAR_BCCTR_FLUSH_ASSIST flag being set in the characteristics
returned from the KVM_PPC_GET_CPU_CHAR ioctl.

Signed-off-by: Suraj Jitindar Singh 
---
 hw/ppc/spapr.c |  2 ++
 hw/ppc/spapr_caps.c| 25 +
 hw/ppc/spapr_hcall.c   |  3 +++
 include/hw/ppc/spapr.h |  5 -
 target/ppc/kvm.c   | 14 ++
 target/ppc/kvm_ppc.h   |  6 ++
 6 files changed, 54 insertions(+), 1 deletion(-)

diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index 1df324379f..708e18dcdf 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -2086,6 +2086,7 @@ static const VMStateDescription vmstate_spapr = {
 _spapr_cap_nested_kvm_hv,
 _spapr_dtb,
 _spapr_cap_large_decr,
+_spapr_cap_ccf_assist,
 NULL
 }
 };
@@ -4319,6 +4320,7 @@ static void spapr_machine_class_init(ObjectClass *oc, 
void *data)
 smc->default_caps.caps[SPAPR_CAP_HPT_MAXPAGESIZE] = 16; /* 64kiB */
 smc->default_caps.caps[SPAPR_CAP_NESTED_KVM_HV] = SPAPR_CAP_OFF;
 smc->default_caps.caps[SPAPR_CAP_LARGE_DECREMENTER] = SPAPR_CAP_ON;
+smc->default_caps.caps[SPAPR_CAP_CCF_ASSIST] = SPAPR_CAP_OFF;
 spapr_caps_add_properties(smc, _abort);
 smc->irq = _irq_xics;
 smc->dr_phb_enabled = true;
diff --git a/hw/ppc/spapr_caps.c b/hw/ppc/spapr_caps.c
index 74a48a423a..f03f2f64e7 100644
--- a/hw/ppc/spapr_caps.c
+++ b/hw/ppc/spapr_caps.c
@@ -436,6 +436,21 @@ static void cap_large_decr_cpu_apply(sPAPRMachineState 
*spapr,
 ppc_store_lpcr(cpu, lpcr);
 }
 
+static void cap_ccf_assist_apply(sPAPRMachineState *spapr, uint8_t val,
+ Error **errp)
+{
+uint8_t kvm_val = kvmppc_get_cap_count_cache_flush_assist();
+
+if (tcg_enabled() && val) {
+/* TODO - for now only allow broken for TCG */
+error_setg(errp,
+"Requested count cache flush assist capability level not supported by tcg, try 
cap-ccf-assist=off");
+} else if (kvm_enabled() && (val > kvm_val)) {
+error_setg(errp,
+"Requested count cache flush assist capability level not supported by kvm, try 
cap-ccf-assist=off");
+}
+}
+
 sPAPRCapabilityInfo capability_table[SPAPR_CAP_NUM] = {
 [SPAPR_CAP_HTM] = {
 .name = "htm",
@@ -525,6 +540,15 @@ sPAPRCapabilityInfo capability_table[SPAPR_CAP_NUM] = {
 .apply = cap_large_decr_apply,
 .cpu_apply = cap_large_decr_cpu_apply,
 },
+[SPAPR_CAP_CCF_ASSIST] = {
+.name = "ccf-assist",
+.description = "Count Cache Flush Assist via HW Instruction",
+.index = SPAPR_CAP_CCF_ASSIST,
+.get = spapr_cap_get_bool,
+.set = spapr_cap_set_bool,
+.type = "bool",
+.apply = cap_ccf_assist_apply,
+},
 };
 
 static sPAPRCapabilities default_caps_with_cpu(sPAPRMachineState *spapr,
@@ -659,6 +683,7 @@ SPAPR_CAP_MIG_STATE(sbbc, SPAPR_CAP_SBBC);
 SPAPR_CAP_MIG_STATE(ibs, SPAPR_CAP_IBS);
 SPAPR_CAP_MIG_STATE(nested_kvm_hv, SPAPR_CAP_NESTED_KVM_HV);
 SPAPR_CAP_MIG_STATE(large_decr, SPAPR_CAP_LARGE_DECREMENTER);
+SPAPR_CAP_MIG_STATE(ccf_assist, SPAPR_CAP_CCF_ASSIST);
 
 void spapr_caps_init(sPAPRMachineState *spapr)
 {
diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c
index 4aa8036fc0..8bfdddc964 100644
--- a/hw/ppc/spapr_hcall.c
+++ b/hw/ppc/spapr_hcall.c
@@ -1693,6 +1693,7 @@ static target_ulong h_get_cpu_characteristics(PowerPCCPU 
*cpu,
 uint8_t safe_cache = spapr_get_cap(spapr, SPAPR_CAP_CFPC);
 uint8_t safe_bounds_check = spapr_get_cap(spapr, SPAPR_CAP_SBBC);
 uint8_t safe_indirect_branch = spapr_get_cap(spapr, SPAPR_CAP_IBS);
+uint8_t count_cache_flush_assist = spapr_get_cap(spapr, 
SPAPR_CAP_CCF_ASSIST);
 
 switch (safe_cache) {
 case SPAPR_CAP_WORKAROUND:
@@ -1733,6 +1734,8 @@ static target_ulong h_get_cpu_characteristics(PowerPCCPU 
*cpu,
 break;
 case SPAPR_CAP_WORKAROUND:
 behaviour |= H_CPU_BEHAV_FLUSH_COUNT_CACHE;
+if (count_cache_flush_assist)
+characteristics |= H_CPU_CHAR_BCCTR_FLUSH_ASSIST;
 break;
 default: /* broken */
 assert(safe_indirect_branch == SPAPR_CAP_BROKEN);
diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
index 80d33ea284..493a44700d 100644
--- a/include/hw/ppc/spapr.h
+++ b/include/hw/ppc/spapr.h
@@ -76,8 +76,10 @@ typedef enum {
 #define SPAPR_CAP_NESTED_KVM

[Qemu-devel] [QEMU-PPC] [PATCH 1/2] target/ppc/spapr: Add workaround option to SPAPR_CAP_IBS

2019-02-28 Thread Suraj Jitindar Singh
The spapr_cap SPAPR_CAP_IBS is used to indicate the level of capability
for mitigations for indirect branch speculation. Currently the available
values are broken (default), fixed-ibs (fixed by serialising indirect
branches) and fixed-ccd (fixed by diabling the count cache).

Introduce a new value for this capability denoted workaround, meaning that
software can work around the issue by flushing the count cache on
context switch. This option is available if the hypervisor sets the
H_CPU_BEHAV_FLUSH_COUNT_CACHE flag in the cpu behaviours returned from
the KVM_PPC_GET_CPU_CHAR ioctl.

Signed-off-by: Suraj Jitindar Singh 
---
 hw/ppc/spapr_caps.c| 21 ++---
 hw/ppc/spapr_hcall.c   |  5 +
 include/hw/ppc/spapr.h |  7 +++
 target/ppc/kvm.c   |  8 +++-
 4 files changed, 29 insertions(+), 12 deletions(-)

diff --git a/hw/ppc/spapr_caps.c b/hw/ppc/spapr_caps.c
index 920224d0c2..74a48a423a 100644
--- a/hw/ppc/spapr_caps.c
+++ b/hw/ppc/spapr_caps.c
@@ -276,11 +276,13 @@ static void cap_safe_bounds_check_apply(sPAPRMachineState 
*spapr, uint8_t val,
 }
 
 sPAPRCapPossible cap_ibs_possible = {
-.num = 4,
+.num = 5,
 /* Note workaround only maintained for compatibility */
-.vals = {"broken", "workaround", "fixed-ibs", "fixed-ccd"},
-.help = "broken - no protection, fixed-ibs - indirect branch 
serialisation,"
-" fixed-ccd - cache count disabled",
+.vals = {"broken", "workaround", "fixed-ibs", "fixed-ccd", "fixed-na"},
+.help = "broken - no protection, workaround - count cache flush"
+", fixed-ibs - indirect branch serialisation,"
+" fixed-ccd - cache count disabled,"
+" fixed-na - fixed in hardware (no longer applicable)",
 };
 
 static void cap_safe_indirect_branch_apply(sPAPRMachineState *spapr,
@@ -288,15 +290,11 @@ static void 
cap_safe_indirect_branch_apply(sPAPRMachineState *spapr,
 {
 uint8_t kvm_val = kvmppc_get_cap_safe_indirect_branch();
 
-if (val == SPAPR_CAP_WORKAROUND) { /* Can only be Broken or Fixed */
-error_setg(errp,
-"Requested safe indirect branch capability level \"workaround\" not valid, try 
cap-ibs=%s",
-   cap_ibs_possible.vals[kvm_val]);
-} else if (tcg_enabled() && val) {
+if (tcg_enabled() && val) {
 /* TODO - for now only allow broken for TCG */
 error_setg(errp,
 "Requested safe indirect branch capability level not supported by tcg, try a 
different value for cap-ibs");
-} else if (kvm_enabled() && val && (val != kvm_val)) {
+} else if (kvm_enabled() && (val > kvm_val)) {
 error_setg(errp,
 "Requested safe indirect branch capability level not supported by kvm, try 
cap-ibs=%s",
cap_ibs_possible.vals[kvm_val]);
@@ -489,7 +487,8 @@ sPAPRCapabilityInfo capability_table[SPAPR_CAP_NUM] = {
 [SPAPR_CAP_IBS] = {
 .name = "ibs",
 .description =
-"Indirect Branch Speculation (broken, fixed-ibs, fixed-ccd)",
+"Indirect Branch Speculation (broken, workaround, fixed-ibs,"
+"fixed-ccd, fixed-na)",
 .index = SPAPR_CAP_IBS,
 .get = spapr_cap_get_string,
 .set = spapr_cap_set_string,
diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c
index 476bad6271..4aa8036fc0 100644
--- a/hw/ppc/spapr_hcall.c
+++ b/hw/ppc/spapr_hcall.c
@@ -1723,12 +1723,17 @@ static target_ulong 
h_get_cpu_characteristics(PowerPCCPU *cpu,
 }
 
 switch (safe_indirect_branch) {
+case SPAPR_CAP_FIXED_NA:
+break;
 case SPAPR_CAP_FIXED_CCD:
 characteristics |= H_CPU_CHAR_CACHE_COUNT_DIS;
 break;
 case SPAPR_CAP_FIXED_IBS:
 characteristics |= H_CPU_CHAR_BCCTRL_SERIALISED;
 break;
+case SPAPR_CAP_WORKAROUND:
+behaviour |= H_CPU_BEHAV_FLUSH_COUNT_CACHE;
+break;
 default: /* broken */
 assert(safe_indirect_branch == SPAPR_CAP_BROKEN);
 break;
diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
index 3cd47fb6e8..80d33ea284 100644
--- a/include/hw/ppc/spapr.h
+++ b/include/hw/ppc/spapr.h
@@ -85,12 +85,17 @@ typedef enum {
 /* Bool Caps */
 #define SPAPR_CAP_OFF   0x00
 #define SPAPR_CAP_ON0x01
+
 /* Custom Caps */
+
+/* Generic */
 #define SPAPR_CAP_BROKEN0x00
 #define SPAPR_CAP_WORKAROUND0x01
 #define SPAPR_CAP_FIXED 0x02
+/* SPAPR_CAP_IBS (cap-ibs) */
 #define SPAPR_CAP_FIXED_IBS 0x02
 #define SPAPR_CAP_FIXED_CCD 0x03
+#define SPAPR_CAP_FIXED_NA  0x10 /* Lets leave a bit of a gap... */
 
 typedef struct sPAPRCapabilities sPAPRCapabilities;
 struct sPAPRCapabili

[Qemu-devel] [QEMU-PPC] [PATCH v3 3/4] target/ppc: Implement large decrementer support for KVM

2019-02-28 Thread Suraj Jitindar Singh
Implement support to allow KVM guests to take advantage of the large
decrementer introduced on POWER9 cpus.

To determine if the host can support the requested large decrementer
size, we check it matches that specified in the ibm,dec-bits device-tree
property. We also need to enable it in KVM by setting the LPCR_LD bit in
the LPCR. Note that to do this we need to try and set the bit, then read
it back to check the host allowed us to set it, if so we can use it but
if we were unable to set it the host cannot support it and we must not
use the large decrementer.

Signed-off-by: Suraj Jitindar Singh 
Signed-off-by: Cédric Le Goater 
---
 hw/ppc/spapr_caps.c  | 17 +++--
 target/ppc/kvm.c | 39 +++
 target/ppc/kvm_ppc.h | 12 
 3 files changed, 66 insertions(+), 2 deletions(-)

diff --git a/hw/ppc/spapr_caps.c b/hw/ppc/spapr_caps.c
index 32f68cbd9e..1e76685199 100644
--- a/hw/ppc/spapr_caps.c
+++ b/hw/ppc/spapr_caps.c
@@ -406,8 +406,16 @@ static void cap_large_decr_apply(sPAPRMachineState *spapr,
 "Large decrementer only supported on POWER9, try -cpu POWER9");
 return;
 }
-} else {
-error_setg(errp, "No large decrementer support, try 
cap-large-decr=off");
+} else if (kvm_enabled()) {
+int kvm_nr_bits = kvmppc_get_cap_large_decr();
+
+if (!kvm_nr_bits) {
+error_setg(errp, "No large decrementer support, try 
cap-large-decr=off");
+} else if (pcc->lrg_decr_bits != kvm_nr_bits) {
+error_setg(errp,
+"KVM large decrementer size (%d) differs to model (%d), try 
-cap-large-decr=off",
+kvm_nr_bits, pcc->lrg_decr_bits);
+}
 }
 }
 
@@ -418,6 +426,11 @@ static void cap_large_decr_cpu_apply(sPAPRMachineState 
*spapr,
 CPUPPCState *env = >env;
 target_ulong lpcr = env->spr[SPR_LPCR];
 
+if (kvm_enabled()) {
+if (kvmppc_enable_cap_large_decr(cpu, val))
+error_setg(errp, "No large decrementer support, try 
cap-large-decr=off");
+}
+
 if (val)
 lpcr |= LPCR_LD;
 else
diff --git a/target/ppc/kvm.c b/target/ppc/kvm.c
index d01852fe31..3f650c8fc4 100644
--- a/target/ppc/kvm.c
+++ b/target/ppc/kvm.c
@@ -91,6 +91,7 @@ static int cap_ppc_safe_cache;
 static int cap_ppc_safe_bounds_check;
 static int cap_ppc_safe_indirect_branch;
 static int cap_ppc_nested_kvm_hv;
+static int cap_large_decr;
 
 static uint32_t debug_inst_opcode;
 
@@ -124,6 +125,7 @@ static bool kvmppc_is_pr(KVMState *ks)
 
 static int kvm_ppc_register_host_cpu_type(MachineState *ms);
 static void kvmppc_get_cpu_characteristics(KVMState *s);
+static int kvmppc_get_dec_bits(void);
 
 int kvm_arch_init(MachineState *ms, KVMState *s)
 {
@@ -151,6 +153,7 @@ int kvm_arch_init(MachineState *ms, KVMState *s)
 cap_resize_hpt = kvm_vm_check_extension(s, KVM_CAP_SPAPR_RESIZE_HPT);
 kvmppc_get_cpu_characteristics(s);
 cap_ppc_nested_kvm_hv = kvm_vm_check_extension(s, KVM_CAP_PPC_NESTED_HV);
+cap_large_decr = kvmppc_get_dec_bits();
 /*
  * Note: setting it to false because there is not such capability
  * in KVM at this moment.
@@ -1927,6 +1930,15 @@ uint64_t kvmppc_get_clockfreq(void)
 return kvmppc_read_int_cpu_dt("clock-frequency");
 }
 
+static int kvmppc_get_dec_bits(void)
+{
+int nr_bits = kvmppc_read_int_cpu_dt("ibm,dec-bits");
+
+if (nr_bits > 0)
+return nr_bits;
+return 0;
+}
+
 static int kvmppc_get_pvinfo(CPUPPCState *env, struct kvm_ppc_pvinfo *pvinfo)
  {
  PowerPCCPU *cpu = ppc_env_get_cpu(env);
@@ -2442,6 +2454,33 @@ bool kvmppc_has_cap_spapr_vfio(void)
 return cap_spapr_vfio;
 }
 
+int kvmppc_get_cap_large_decr(void)
+{
+return cap_large_decr;
+}
+
+int kvmppc_enable_cap_large_decr(PowerPCCPU *cpu, int enable)
+{
+CPUState *cs = CPU(cpu);
+uint64_t lpcr;
+
+kvm_get_one_reg(cs, KVM_REG_PPC_LPCR_64, );
+/* Do we need to modify the LPCR? */
+if (!!(lpcr & LPCR_LD) != !!enable) {
+if (enable)
+lpcr |= LPCR_LD;
+else
+lpcr &= ~LPCR_LD;
+kvm_set_one_reg(cs, KVM_REG_PPC_LPCR_64, );
+kvm_get_one_reg(cs, KVM_REG_PPC_LPCR_64, );
+
+if (!!(lpcr & LPCR_LD) != !!enable)
+return -1;
+}
+
+return 0;
+}
+
 PowerPCCPUClass *kvm_ppc_get_host_cpu_class(void)
 {
 uint32_t host_pvr = mfpvr();
diff --git a/target/ppc/kvm_ppc.h b/target/ppc/kvm_ppc.h
index bdfaa4e70a..a79835bd14 100644
--- a/target/ppc/kvm_ppc.h
+++ b/target/ppc/kvm_ppc.h
@@ -64,6 +64,8 @@ int kvmppc_get_cap_safe_bounds_check(void);
 int kvmppc_get_cap_safe_indirect_branch(void);
 bool kvmppc_has_cap_nested_kvm_hv(void);
 int kvmppc_set_cap_nested_kvm_hv(int enable);
+int kvmppc_get_cap_large_decr(void);
+int kvmppc_enable_cap_large_decr(PowerPCCPU *cpu, int enable);
 int kvmppc_enable_hwrng(void);
 int kvmppc_put_bo

[Qemu-devel] [QEMU-PPC] [PATCH v3 2/4] target/ppc: Implement large decrementer support for TCG

2019-02-28 Thread Suraj Jitindar Singh
Prior to POWER9 the decrementer was a 32-bit register which decremented
with each tick of the timebase. From POWER9 onwards the decrementer can
be set to operate in a mode called large decrementer where it acts as a
n-bit decrementing register which is visible as a 64-bit register, that
is the value of the decrementer is sign extended to 64 bits (where n is
implementation dependant).

The mode in which the decrementer operates is controlled by the LPCR_LD
bit in the logical paritition control register (LPCR).

>From POWER9 onwards the HDEC (hypervisor decrementer) was enlarged to
h-bits, also sign extended to 64 bits (where h is implementation
dependant). Note this isn't configurable and is always enabled.

On POWER9 the large decrementer and hdec are both 56 bits, as
represented by the lrg_decr_bits cpu class property. Since they are the
same size we only add one property for now, which could be extended in
the case they ever differ in the future.

We also add the lrg_decr_bits property for POWER5+/7/8 since it is used
to determine the size of the hdec, which is only generated on the
POWER5+ processor and later. On these processors it is 32 bits.

Signed-off-by: Suraj Jitindar Singh 
Signed-off-by: Cédric Le Goater 
---
 hw/ppc/ppc.c| 85 -
 hw/ppc/spapr.c  |  8 
 hw/ppc/spapr_caps.c | 31 ++-
 target/ppc/cpu-qom.h|  1 +
 target/ppc/cpu.h|  8 ++--
 target/ppc/mmu-hash64.c |  2 +-
 target/ppc/translate.c  |  2 +-
 target/ppc/translate_init.inc.c |  4 ++
 8 files changed, 108 insertions(+), 33 deletions(-)

diff --git a/hw/ppc/ppc.c b/hw/ppc/ppc.c
index d1e3d4cd20..9145aeddcb 100644
--- a/hw/ppc/ppc.c
+++ b/hw/ppc/ppc.c
@@ -744,11 +744,10 @@ bool ppc_decr_clear_on_delivery(CPUPPCState *env)
 return ((tb_env->flags & flags) == PPC_DECR_UNDERFLOW_TRIGGERED);
 }
 
-static inline uint32_t _cpu_ppc_load_decr(CPUPPCState *env, uint64_t next)
+static inline int64_t _cpu_ppc_load_decr(CPUPPCState *env, uint64_t next)
 {
 ppc_tb_t *tb_env = env->tb_env;
-uint32_t decr;
-int64_t diff;
+int64_t decr, diff;
 
 diff = next - qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
 if (diff >= 0) {
@@ -758,27 +757,47 @@ static inline uint32_t _cpu_ppc_load_decr(CPUPPCState 
*env, uint64_t next)
 }  else {
 decr = -muldiv64(-diff, tb_env->decr_freq, NANOSECONDS_PER_SECOND);
 }
-LOG_TB("%s: %08" PRIx32 "\n", __func__, decr);
+LOG_TB("%s: %016" PRIx64 "\n", __func__, decr);
 
 return decr;
 }
 
-uint32_t cpu_ppc_load_decr (CPUPPCState *env)
+target_ulong cpu_ppc_load_decr (CPUPPCState *env)
 {
 ppc_tb_t *tb_env = env->tb_env;
+uint64_t decr;
 
 if (kvm_enabled()) {
 return env->spr[SPR_DECR];
 }
 
-return _cpu_ppc_load_decr(env, tb_env->decr_next);
+decr = _cpu_ppc_load_decr(env, tb_env->decr_next);
+
+/*
+ * If large decrementer is enabled then the decrementer is signed extened
+ * to 64 bits, otherwise it is a 32 bit value.
+ */
+if (env->spr[SPR_LPCR] & LPCR_LD)
+return decr;
+return (uint32_t) decr;
 }
 
-uint32_t cpu_ppc_load_hdecr (CPUPPCState *env)
+target_ulong cpu_ppc_load_hdecr (CPUPPCState *env)
 {
+PowerPCCPU *cpu = ppc_env_get_cpu(env);
+PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
 ppc_tb_t *tb_env = env->tb_env;
+uint64_t hdecr;
 
-return _cpu_ppc_load_decr(env, tb_env->hdecr_next);
+hdecr =  _cpu_ppc_load_decr(env, tb_env->hdecr_next);
+
+/*
+ * If we have a large decrementer (POWER9 or later) then hdecr is sign
+ * extended to 64 bits, otherwise it is 32 bits.
+ */
+if (pcc->lrg_decr_bits > 32)
+return hdecr;
+return (uint32_t) hdecr;
 }
 
 uint64_t cpu_ppc_load_purr (CPUPPCState *env)
@@ -832,13 +851,21 @@ static void __cpu_ppc_store_decr(PowerPCCPU *cpu, 
uint64_t *nextp,
  QEMUTimer *timer,
  void (*raise_excp)(void *),
  void (*lower_excp)(PowerPCCPU *),
- uint32_t decr, uint32_t value)
+ target_ulong decr, target_ulong value,
+ int nr_bits)
 {
 CPUPPCState *env = >env;
 ppc_tb_t *tb_env = env->tb_env;
 uint64_t now, next;
+bool negative;
+
+/* Truncate value to decr_width and sign extend for simplicity */
+value &= ((1ULL << nr_bits) - 1);
+negative = !!(value & (1ULL << (nr_bits - 1)));
+if (negative)
+value |= (0xULL << nr_bits);
 
-LOG_TB("%s: %08" PRIx32 " => %08" PRIx32 "\n", __func__,
+LOG_TB("%s: " TARGET_FMT_lx " => " TARGET_FMT_lx "\n", __func__,
 

[Qemu-devel] [QEMU-PPC] [PATCH v3 4/4] target/ppc/spapr: Enable the large decrementer for pseries-4.0

2019-02-28 Thread Suraj Jitindar Singh
Enable the large decrementer by default for the pseries-4.0 machine type.
It is disabled again by default_caps_with_cpu() for pre-POWER9 cpus
since they don't support the large decrementer.

Signed-off-by: Suraj Jitindar Singh 
---
 hw/ppc/spapr.c  | 3 ++-
 hw/ppc/spapr_caps.c | 5 +
 2 files changed, 7 insertions(+), 1 deletion(-)

diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index 9942b270df..1df324379f 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -4318,7 +4318,7 @@ static void spapr_machine_class_init(ObjectClass *oc, 
void *data)
 smc->default_caps.caps[SPAPR_CAP_IBS] = SPAPR_CAP_BROKEN;
 smc->default_caps.caps[SPAPR_CAP_HPT_MAXPAGESIZE] = 16; /* 64kiB */
 smc->default_caps.caps[SPAPR_CAP_NESTED_KVM_HV] = SPAPR_CAP_OFF;
-smc->default_caps.caps[SPAPR_CAP_LARGE_DECREMENTER] = SPAPR_CAP_OFF;
+smc->default_caps.caps[SPAPR_CAP_LARGE_DECREMENTER] = SPAPR_CAP_ON;
 spapr_caps_add_properties(smc, _abort);
 smc->irq = _irq_xics;
 smc->dr_phb_enabled = true;
@@ -4394,6 +4394,7 @@ static void spapr_machine_3_1_class_options(MachineClass 
*mc)
 mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power8_v2.0");
 smc->update_dt_enabled = false;
 smc->dr_phb_enabled = false;
+smc->default_caps.caps[SPAPR_CAP_LARGE_DECREMENTER] = SPAPR_CAP_OFF;
 }
 
 DEFINE_SPAPR_MACHINE(3_1, "3.1", false);
diff --git a/hw/ppc/spapr_caps.c b/hw/ppc/spapr_caps.c
index 1e76685199..920224d0c2 100644
--- a/hw/ppc/spapr_caps.c
+++ b/hw/ppc/spapr_caps.c
@@ -536,6 +536,11 @@ static sPAPRCapabilities 
default_caps_with_cpu(sPAPRMachineState *spapr,
 
 caps = smc->default_caps;
 
+if (!ppc_type_check_compat(cputype, CPU_POWERPC_LOGICAL_3_00,
+   0, spapr->max_compat_pvr)) {
+caps.caps[SPAPR_CAP_LARGE_DECREMENTER] = SPAPR_CAP_OFF;
+}
+
 if (!ppc_type_check_compat(cputype, CPU_POWERPC_LOGICAL_2_07,
0, spapr->max_compat_pvr)) {
 caps.caps[SPAPR_CAP_HTM] = SPAPR_CAP_OFF;
-- 
2.13.6




[Qemu-devel] [QEMU-PPC] [PATCH v3 1/4] target/ppc/spapr: Add SPAPR_CAP_LARGE_DECREMENTER

2019-02-28 Thread Suraj Jitindar Singh
Add spapr_cap SPAPR_CAP_LARGE_DECREMENTER to be used to control the
availability of the large decrementer for a guest.

Signed-off-by: Suraj Jitindar Singh 
---
 hw/ppc/spapr.c |  2 ++
 hw/ppc/spapr_caps.c| 17 +
 include/hw/ppc/spapr.h |  5 -
 3 files changed, 23 insertions(+), 1 deletion(-)

diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index 6f9208476a..d068982a5e 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -2077,6 +2077,7 @@ static const VMStateDescription vmstate_spapr = {
 _spapr_irq_map,
 _spapr_cap_nested_kvm_hv,
 _spapr_dtb,
+_spapr_cap_large_decr,
 NULL
 }
 };
@@ -4309,6 +4310,7 @@ static void spapr_machine_class_init(ObjectClass *oc, 
void *data)
 smc->default_caps.caps[SPAPR_CAP_IBS] = SPAPR_CAP_BROKEN;
 smc->default_caps.caps[SPAPR_CAP_HPT_MAXPAGESIZE] = 16; /* 64kiB */
 smc->default_caps.caps[SPAPR_CAP_NESTED_KVM_HV] = SPAPR_CAP_OFF;
+smc->default_caps.caps[SPAPR_CAP_LARGE_DECREMENTER] = SPAPR_CAP_OFF;
 spapr_caps_add_properties(smc, _abort);
 smc->irq = _irq_xics;
 smc->dr_phb_enabled = true;
diff --git a/hw/ppc/spapr_caps.c b/hw/ppc/spapr_caps.c
index 64f98ae68d..3f90f5823e 100644
--- a/hw/ppc/spapr_caps.c
+++ b/hw/ppc/spapr_caps.c
@@ -390,6 +390,13 @@ static void cap_nested_kvm_hv_apply(sPAPRMachineState 
*spapr,
 }
 }
 
+static void cap_large_decr_apply(sPAPRMachineState *spapr,
+ uint8_t val, Error **errp)
+{
+if (val)
+error_setg(errp, "No large decrementer support, try 
cap-large-decr=off");
+}
+
 sPAPRCapabilityInfo capability_table[SPAPR_CAP_NUM] = {
 [SPAPR_CAP_HTM] = {
 .name = "htm",
@@ -468,6 +475,15 @@ sPAPRCapabilityInfo capability_table[SPAPR_CAP_NUM] = {
 .type = "bool",
 .apply = cap_nested_kvm_hv_apply,
 },
+[SPAPR_CAP_LARGE_DECREMENTER] = {
+.name = "large-decr",
+.description = "Allow Large Decrementer",
+.index = SPAPR_CAP_LARGE_DECREMENTER,
+.get = spapr_cap_get_bool,
+.set = spapr_cap_set_bool,
+.type = "bool",
+.apply = cap_large_decr_apply,
+},
 };
 
 static sPAPRCapabilities default_caps_with_cpu(sPAPRMachineState *spapr,
@@ -596,6 +612,7 @@ SPAPR_CAP_MIG_STATE(cfpc, SPAPR_CAP_CFPC);
 SPAPR_CAP_MIG_STATE(sbbc, SPAPR_CAP_SBBC);
 SPAPR_CAP_MIG_STATE(ibs, SPAPR_CAP_IBS);
 SPAPR_CAP_MIG_STATE(nested_kvm_hv, SPAPR_CAP_NESTED_KVM_HV);
+SPAPR_CAP_MIG_STATE(large_decr, SPAPR_CAP_LARGE_DECREMENTER);
 
 void spapr_caps_init(sPAPRMachineState *spapr)
 {
diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
index 86b0488d29..3cd47fb6e8 100644
--- a/include/hw/ppc/spapr.h
+++ b/include/hw/ppc/spapr.h
@@ -74,8 +74,10 @@ typedef enum {
 #define SPAPR_CAP_HPT_MAXPAGESIZE   0x06
 /* Nested KVM-HV */
 #define SPAPR_CAP_NESTED_KVM_HV 0x07
+/* Large Decrementer */
+#define SPAPR_CAP_LARGE_DECREMENTER 0x08
 /* Num Caps */
-#define SPAPR_CAP_NUM   (SPAPR_CAP_NESTED_KVM_HV + 1)
+#define SPAPR_CAP_NUM   (SPAPR_CAP_LARGE_DECREMENTER + 1)
 
 /*
  * Capability Values
@@ -843,6 +845,7 @@ extern const VMStateDescription vmstate_spapr_cap_cfpc;
 extern const VMStateDescription vmstate_spapr_cap_sbbc;
 extern const VMStateDescription vmstate_spapr_cap_ibs;
 extern const VMStateDescription vmstate_spapr_cap_nested_kvm_hv;
+extern const VMStateDescription vmstate_spapr_cap_large_decr;
 
 static inline uint8_t spapr_get_cap(sPAPRMachineState *spapr, int cap)
 {
-- 
2.13.6




Re: [Qemu-devel] [QEMU-PPC] [PATCH v2 1/4] target/ppc/spapr: Add SPAPR_CAP_LARGE_DECREMENTER

2019-02-27 Thread Suraj Jitindar Singh
On Wed, 2019-02-27 at 17:16 +1100, David Gibson wrote:
> On Wed, Feb 27, 2019 at 03:30:05PM +1100, Suraj Jitindar Singh wrote:
> > Add spapr_cap SPAPR_CAP_LARGE_DECREMENTER to be used to control the
> > availability of the large decrementer for a guest.
> > 
> > Signed-off-by: Suraj Jitindar Singh 
> 
> This series looks good now, except for one nit...
> 
> > ---
> >  hw/ppc/spapr.c |  2 ++
> >  hw/ppc/spapr_caps.c| 17 +
> >  include/hw/ppc/spapr.h |  5 -
> >  3 files changed, 23 insertions(+), 1 deletion(-)
> > 
> > diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
> > index b6a571b6f1..acf62a2b9f 100644
> > --- a/hw/ppc/spapr.c
> > +++ b/hw/ppc/spapr.c
> > @@ -2077,6 +2077,7 @@ static const VMStateDescription vmstate_spapr
> > = {
> >  _spapr_irq_map,
> >  _spapr_cap_nested_kvm_hv,
> >  _spapr_dtb,
> > +_spapr_cap_large_decr,
> >  NULL
> >  }
> >  };
> > @@ -4288,6 +4289,7 @@ static void
> > spapr_machine_class_init(ObjectClass *oc, void *data)
> >  smc->default_caps.caps[SPAPR_CAP_IBS] = SPAPR_CAP_BROKEN;
> >  smc->default_caps.caps[SPAPR_CAP_HPT_MAXPAGESIZE] = 16; /*
> > 64kiB */
> >  smc->default_caps.caps[SPAPR_CAP_NESTED_KVM_HV] =
> > SPAPR_CAP_OFF;
> > +smc->default_caps.caps[SPAPR_CAP_LARGE_DECREMENTER] = 0;
> 
> ... since this is now a boolean, it should use SPAPR_CAP_OFF /
> SPAPR_CAP_ON instead of bare 0 and 1.

True, do you want me to fix-up and resend? Or can you fix it when you
apply?

> 



[Qemu-devel] [QEMU-PPC] [PATCH] target/ppc/spapr: Enable mitigations by default for pseries-4.0 machine type

2019-02-26 Thread Suraj Jitindar Singh
There are currently 3 vulnerability mitigations controlled by the
spapr-caps mechanism, cap-cfpc, cap-sbbc, and cap-ibs. Enable these
mitigations by default for the pseries-4.0 machine type.

By now machine firmware should have been upgraded to allow these
settings.
Note: This means these caps will have to be set to broken for tcg

Signed-off-by: Suraj Jitindar Singh 
---
 hw/ppc/spapr.c | 9 ++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index 73aba70aa9..1ef8865dc5 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -4313,9 +4313,9 @@ static void spapr_machine_class_init(ObjectClass *oc, 
void *data)
 smc->default_caps.caps[SPAPR_CAP_HTM] = SPAPR_CAP_OFF;
 smc->default_caps.caps[SPAPR_CAP_VSX] = SPAPR_CAP_ON;
 smc->default_caps.caps[SPAPR_CAP_DFP] = SPAPR_CAP_ON;
-smc->default_caps.caps[SPAPR_CAP_CFPC] = SPAPR_CAP_BROKEN;
-smc->default_caps.caps[SPAPR_CAP_SBBC] = SPAPR_CAP_BROKEN;
-smc->default_caps.caps[SPAPR_CAP_IBS] = SPAPR_CAP_BROKEN;
+smc->default_caps.caps[SPAPR_CAP_CFPC] = SPAPR_CAP_WORKAROUND;
+smc->default_caps.caps[SPAPR_CAP_SBBC] = SPAPR_CAP_WORKAROUND;
+smc->default_caps.caps[SPAPR_CAP_IBS] = SPAPR_CAP_FIXED_CCD;
 smc->default_caps.caps[SPAPR_CAP_HPT_MAXPAGESIZE] = 16; /* 64kiB */
 smc->default_caps.caps[SPAPR_CAP_NESTED_KVM_HV] = SPAPR_CAP_OFF;
 smc->default_caps.caps[SPAPR_CAP_LARGE_DECREMENTER] = 1;
@@ -4394,6 +4394,9 @@ static void spapr_machine_3_1_class_options(MachineClass 
*mc)
 mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power8_v2.0");
 smc->update_dt_enabled = false;
 smc->dr_phb_enabled = false;
+smc->default_caps.caps[SPAPR_CAP_CFPC] = SPAPR_CAP_BROKEN;
+smc->default_caps.caps[SPAPR_CAP_SBBC] = SPAPR_CAP_BROKEN;
+smc->default_caps.caps[SPAPR_CAP_IBS] = SPAPR_CAP_BROKEN;
 smc->default_caps.caps[SPAPR_CAP_LARGE_DECREMENTER] = 0;
 }
 
-- 
2.13.6




[Qemu-devel] [QEMU-PPC] [PATCH v2 3/4] target/ppc: Implement large decrementer support for KVM

2019-02-26 Thread Suraj Jitindar Singh
Implement support to allow KVM guests to take advantage of the large
decrementer introduced on POWER9 cpus.

To determine if the host can support the requested large decrementer
size, we check it matches that specified in the ibm,dec-bits device-tree
property. We also need to enable it in KVM by setting the LPCR_LD bit in
the LPCR. Note that to do this we need to try and set the bit, then read
it back to check the host allowed us to set it, if so we can use it but
if we were unable to set it the host cannot support it and we must not
use the large decrementer.

Signed-off-by: Suraj Jitindar Singh 
Signed-off-by: Cédric Le Goater 
---
 hw/ppc/spapr_caps.c  | 17 +++--
 target/ppc/kvm.c | 39 +++
 target/ppc/kvm_ppc.h | 12 
 3 files changed, 66 insertions(+), 2 deletions(-)

diff --git a/hw/ppc/spapr_caps.c b/hw/ppc/spapr_caps.c
index 32f68cbd9e..1e76685199 100644
--- a/hw/ppc/spapr_caps.c
+++ b/hw/ppc/spapr_caps.c
@@ -406,8 +406,16 @@ static void cap_large_decr_apply(sPAPRMachineState *spapr,
 "Large decrementer only supported on POWER9, try -cpu POWER9");
 return;
 }
-} else {
-error_setg(errp, "No large decrementer support, try 
cap-large-decr=off");
+} else if (kvm_enabled()) {
+int kvm_nr_bits = kvmppc_get_cap_large_decr();
+
+if (!kvm_nr_bits) {
+error_setg(errp, "No large decrementer support, try 
cap-large-decr=off");
+} else if (pcc->lrg_decr_bits != kvm_nr_bits) {
+error_setg(errp,
+"KVM large decrementer size (%d) differs to model (%d), try 
-cap-large-decr=off",
+kvm_nr_bits, pcc->lrg_decr_bits);
+}
 }
 }
 
@@ -418,6 +426,11 @@ static void cap_large_decr_cpu_apply(sPAPRMachineState 
*spapr,
 CPUPPCState *env = >env;
 target_ulong lpcr = env->spr[SPR_LPCR];
 
+if (kvm_enabled()) {
+if (kvmppc_enable_cap_large_decr(cpu, val))
+error_setg(errp, "No large decrementer support, try 
cap-large-decr=off");
+}
+
 if (val)
 lpcr |= LPCR_LD;
 else
diff --git a/target/ppc/kvm.c b/target/ppc/kvm.c
index d01852fe31..3f650c8fc4 100644
--- a/target/ppc/kvm.c
+++ b/target/ppc/kvm.c
@@ -91,6 +91,7 @@ static int cap_ppc_safe_cache;
 static int cap_ppc_safe_bounds_check;
 static int cap_ppc_safe_indirect_branch;
 static int cap_ppc_nested_kvm_hv;
+static int cap_large_decr;
 
 static uint32_t debug_inst_opcode;
 
@@ -124,6 +125,7 @@ static bool kvmppc_is_pr(KVMState *ks)
 
 static int kvm_ppc_register_host_cpu_type(MachineState *ms);
 static void kvmppc_get_cpu_characteristics(KVMState *s);
+static int kvmppc_get_dec_bits(void);
 
 int kvm_arch_init(MachineState *ms, KVMState *s)
 {
@@ -151,6 +153,7 @@ int kvm_arch_init(MachineState *ms, KVMState *s)
 cap_resize_hpt = kvm_vm_check_extension(s, KVM_CAP_SPAPR_RESIZE_HPT);
 kvmppc_get_cpu_characteristics(s);
 cap_ppc_nested_kvm_hv = kvm_vm_check_extension(s, KVM_CAP_PPC_NESTED_HV);
+cap_large_decr = kvmppc_get_dec_bits();
 /*
  * Note: setting it to false because there is not such capability
  * in KVM at this moment.
@@ -1927,6 +1930,15 @@ uint64_t kvmppc_get_clockfreq(void)
 return kvmppc_read_int_cpu_dt("clock-frequency");
 }
 
+static int kvmppc_get_dec_bits(void)
+{
+int nr_bits = kvmppc_read_int_cpu_dt("ibm,dec-bits");
+
+if (nr_bits > 0)
+return nr_bits;
+return 0;
+}
+
 static int kvmppc_get_pvinfo(CPUPPCState *env, struct kvm_ppc_pvinfo *pvinfo)
  {
  PowerPCCPU *cpu = ppc_env_get_cpu(env);
@@ -2442,6 +2454,33 @@ bool kvmppc_has_cap_spapr_vfio(void)
 return cap_spapr_vfio;
 }
 
+int kvmppc_get_cap_large_decr(void)
+{
+return cap_large_decr;
+}
+
+int kvmppc_enable_cap_large_decr(PowerPCCPU *cpu, int enable)
+{
+CPUState *cs = CPU(cpu);
+uint64_t lpcr;
+
+kvm_get_one_reg(cs, KVM_REG_PPC_LPCR_64, );
+/* Do we need to modify the LPCR? */
+if (!!(lpcr & LPCR_LD) != !!enable) {
+if (enable)
+lpcr |= LPCR_LD;
+else
+lpcr &= ~LPCR_LD;
+kvm_set_one_reg(cs, KVM_REG_PPC_LPCR_64, );
+kvm_get_one_reg(cs, KVM_REG_PPC_LPCR_64, );
+
+if (!!(lpcr & LPCR_LD) != !!enable)
+return -1;
+}
+
+return 0;
+}
+
 PowerPCCPUClass *kvm_ppc_get_host_cpu_class(void)
 {
 uint32_t host_pvr = mfpvr();
diff --git a/target/ppc/kvm_ppc.h b/target/ppc/kvm_ppc.h
index bdfaa4e70a..a79835bd14 100644
--- a/target/ppc/kvm_ppc.h
+++ b/target/ppc/kvm_ppc.h
@@ -64,6 +64,8 @@ int kvmppc_get_cap_safe_bounds_check(void);
 int kvmppc_get_cap_safe_indirect_branch(void);
 bool kvmppc_has_cap_nested_kvm_hv(void);
 int kvmppc_set_cap_nested_kvm_hv(int enable);
+int kvmppc_get_cap_large_decr(void);
+int kvmppc_enable_cap_large_decr(PowerPCCPU *cpu, int enable);
 int kvmppc_enable_hwrng(void);
 int kvmppc_put_bo

[Qemu-devel] [QEMU-PPC] [PATCH v2 2/4] target/ppc: Implement large decrementer support for TCG

2019-02-26 Thread Suraj Jitindar Singh
Prior to POWER9 the decrementer was a 32-bit register which decremented
with each tick of the timebase. From POWER9 onwards the decrementer can
be set to operate in a mode called large decrementer where it acts as a
n-bit decrementing register which is visible as a 64-bit register, that
is the value of the decrementer is sign extended to 64 bits (where n is
implementation dependant).

The mode in which the decrementer operates is controlled by the LPCR_LD
bit in the logical paritition control register (LPCR).

>From POWER9 onwards the HDEC (hypervisor decrementer) was enlarged to
h-bits, also sign extended to 64 bits (where h is implementation
dependant). Note this isn't configurable and is always enabled.

On POWER9 the large decrementer and hdec are both 56 bits, as
represented by the lrg_decr_bits cpu class property. Since they are the
same size we only add one property for now, which could be extended in
the case they ever differ in the future.

We also add the lrg_decr_bits property for POWER5+/7/8 since it is used
to determine the size of the hdec, which is only generated on the
POWER5+ processor and later. On these processors it is 32 bits.

Signed-off-by: Suraj Jitindar Singh 
Signed-off-by: Cédric Le Goater 
---
 hw/ppc/ppc.c| 85 -
 hw/ppc/spapr.c  |  8 
 hw/ppc/spapr_caps.c | 31 ++-
 target/ppc/cpu-qom.h|  1 +
 target/ppc/cpu.h|  8 ++--
 target/ppc/mmu-hash64.c |  2 +-
 target/ppc/translate.c  |  2 +-
 target/ppc/translate_init.inc.c |  4 ++
 8 files changed, 108 insertions(+), 33 deletions(-)

diff --git a/hw/ppc/ppc.c b/hw/ppc/ppc.c
index d1e3d4cd20..9145aeddcb 100644
--- a/hw/ppc/ppc.c
+++ b/hw/ppc/ppc.c
@@ -744,11 +744,10 @@ bool ppc_decr_clear_on_delivery(CPUPPCState *env)
 return ((tb_env->flags & flags) == PPC_DECR_UNDERFLOW_TRIGGERED);
 }
 
-static inline uint32_t _cpu_ppc_load_decr(CPUPPCState *env, uint64_t next)
+static inline int64_t _cpu_ppc_load_decr(CPUPPCState *env, uint64_t next)
 {
 ppc_tb_t *tb_env = env->tb_env;
-uint32_t decr;
-int64_t diff;
+int64_t decr, diff;
 
 diff = next - qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
 if (diff >= 0) {
@@ -758,27 +757,47 @@ static inline uint32_t _cpu_ppc_load_decr(CPUPPCState 
*env, uint64_t next)
 }  else {
 decr = -muldiv64(-diff, tb_env->decr_freq, NANOSECONDS_PER_SECOND);
 }
-LOG_TB("%s: %08" PRIx32 "\n", __func__, decr);
+LOG_TB("%s: %016" PRIx64 "\n", __func__, decr);
 
 return decr;
 }
 
-uint32_t cpu_ppc_load_decr (CPUPPCState *env)
+target_ulong cpu_ppc_load_decr (CPUPPCState *env)
 {
 ppc_tb_t *tb_env = env->tb_env;
+uint64_t decr;
 
 if (kvm_enabled()) {
 return env->spr[SPR_DECR];
 }
 
-return _cpu_ppc_load_decr(env, tb_env->decr_next);
+decr = _cpu_ppc_load_decr(env, tb_env->decr_next);
+
+/*
+ * If large decrementer is enabled then the decrementer is signed extened
+ * to 64 bits, otherwise it is a 32 bit value.
+ */
+if (env->spr[SPR_LPCR] & LPCR_LD)
+return decr;
+return (uint32_t) decr;
 }
 
-uint32_t cpu_ppc_load_hdecr (CPUPPCState *env)
+target_ulong cpu_ppc_load_hdecr (CPUPPCState *env)
 {
+PowerPCCPU *cpu = ppc_env_get_cpu(env);
+PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
 ppc_tb_t *tb_env = env->tb_env;
+uint64_t hdecr;
 
-return _cpu_ppc_load_decr(env, tb_env->hdecr_next);
+hdecr =  _cpu_ppc_load_decr(env, tb_env->hdecr_next);
+
+/*
+ * If we have a large decrementer (POWER9 or later) then hdecr is sign
+ * extended to 64 bits, otherwise it is 32 bits.
+ */
+if (pcc->lrg_decr_bits > 32)
+return hdecr;
+return (uint32_t) hdecr;
 }
 
 uint64_t cpu_ppc_load_purr (CPUPPCState *env)
@@ -832,13 +851,21 @@ static void __cpu_ppc_store_decr(PowerPCCPU *cpu, 
uint64_t *nextp,
  QEMUTimer *timer,
  void (*raise_excp)(void *),
  void (*lower_excp)(PowerPCCPU *),
- uint32_t decr, uint32_t value)
+ target_ulong decr, target_ulong value,
+ int nr_bits)
 {
 CPUPPCState *env = >env;
 ppc_tb_t *tb_env = env->tb_env;
 uint64_t now, next;
+bool negative;
+
+/* Truncate value to decr_width and sign extend for simplicity */
+value &= ((1ULL << nr_bits) - 1);
+negative = !!(value & (1ULL << (nr_bits - 1)));
+if (negative)
+value |= (0xULL << nr_bits);
 
-LOG_TB("%s: %08" PRIx32 " => %08" PRIx32 "\n", __func__,
+LOG_TB("%s: " TARGET_FMT_lx " => " TARGET_FMT_lx "\n", __func__,
 

[Qemu-devel] [QEMU-PPC] [PATCH v2 4/4] target/ppc/spapr: Enable the large decrementer for pseries-4.0

2019-02-26 Thread Suraj Jitindar Singh
Enable the large decrementer by default for the pseries-4.0 machine type.
It is disabled again by default_caps_with_cpu() for pre-POWER9 cpus
since they don't support the large decrementer.

Signed-off-by: Suraj Jitindar Singh 
---
 hw/ppc/spapr.c  | 3 ++-
 hw/ppc/spapr_caps.c | 5 +
 2 files changed, 7 insertions(+), 1 deletion(-)

diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index ff5ba59cc0..bbfaca3b05 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -4297,7 +4297,7 @@ static void spapr_machine_class_init(ObjectClass *oc, 
void *data)
 smc->default_caps.caps[SPAPR_CAP_IBS] = SPAPR_CAP_BROKEN;
 smc->default_caps.caps[SPAPR_CAP_HPT_MAXPAGESIZE] = 16; /* 64kiB */
 smc->default_caps.caps[SPAPR_CAP_NESTED_KVM_HV] = SPAPR_CAP_OFF;
-smc->default_caps.caps[SPAPR_CAP_LARGE_DECREMENTER] = 0;
+smc->default_caps.caps[SPAPR_CAP_LARGE_DECREMENTER] = 1;
 spapr_caps_add_properties(smc, _abort);
 smc->irq = _irq_xics;
 smc->dr_phb_enabled = true;
@@ -4373,6 +4373,7 @@ static void spapr_machine_3_1_class_options(MachineClass 
*mc)
 mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power8_v2.0");
 smc->update_dt_enabled = false;
 smc->dr_phb_enabled = false;
+smc->default_caps.caps[SPAPR_CAP_LARGE_DECREMENTER] = 0;
 }
 
 DEFINE_SPAPR_MACHINE(3_1, "3.1", false);
diff --git a/hw/ppc/spapr_caps.c b/hw/ppc/spapr_caps.c
index 1e76685199..fbd5d35cd0 100644
--- a/hw/ppc/spapr_caps.c
+++ b/hw/ppc/spapr_caps.c
@@ -536,6 +536,11 @@ static sPAPRCapabilities 
default_caps_with_cpu(sPAPRMachineState *spapr,
 
 caps = smc->default_caps;
 
+if (!ppc_type_check_compat(cputype, CPU_POWERPC_LOGICAL_3_00,
+   0, spapr->max_compat_pvr)) {
+caps.caps[SPAPR_CAP_LARGE_DECREMENTER] = 0;
+}
+
 if (!ppc_type_check_compat(cputype, CPU_POWERPC_LOGICAL_2_07,
0, spapr->max_compat_pvr)) {
 caps.caps[SPAPR_CAP_HTM] = SPAPR_CAP_OFF;
-- 
2.13.6




[Qemu-devel] [QEMU-PPC] [PATCH v2 1/4] target/ppc/spapr: Add SPAPR_CAP_LARGE_DECREMENTER

2019-02-26 Thread Suraj Jitindar Singh
Add spapr_cap SPAPR_CAP_LARGE_DECREMENTER to be used to control the
availability of the large decrementer for a guest.

Signed-off-by: Suraj Jitindar Singh 
---
 hw/ppc/spapr.c |  2 ++
 hw/ppc/spapr_caps.c| 17 +
 include/hw/ppc/spapr.h |  5 -
 3 files changed, 23 insertions(+), 1 deletion(-)

diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index b6a571b6f1..acf62a2b9f 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -2077,6 +2077,7 @@ static const VMStateDescription vmstate_spapr = {
 _spapr_irq_map,
 _spapr_cap_nested_kvm_hv,
 _spapr_dtb,
+_spapr_cap_large_decr,
 NULL
 }
 };
@@ -4288,6 +4289,7 @@ static void spapr_machine_class_init(ObjectClass *oc, 
void *data)
 smc->default_caps.caps[SPAPR_CAP_IBS] = SPAPR_CAP_BROKEN;
 smc->default_caps.caps[SPAPR_CAP_HPT_MAXPAGESIZE] = 16; /* 64kiB */
 smc->default_caps.caps[SPAPR_CAP_NESTED_KVM_HV] = SPAPR_CAP_OFF;
+smc->default_caps.caps[SPAPR_CAP_LARGE_DECREMENTER] = 0;
 spapr_caps_add_properties(smc, _abort);
 smc->irq = _irq_xics;
 smc->dr_phb_enabled = true;
diff --git a/hw/ppc/spapr_caps.c b/hw/ppc/spapr_caps.c
index 64f98ae68d..3f90f5823e 100644
--- a/hw/ppc/spapr_caps.c
+++ b/hw/ppc/spapr_caps.c
@@ -390,6 +390,13 @@ static void cap_nested_kvm_hv_apply(sPAPRMachineState 
*spapr,
 }
 }
 
+static void cap_large_decr_apply(sPAPRMachineState *spapr,
+ uint8_t val, Error **errp)
+{
+if (val)
+error_setg(errp, "No large decrementer support, try 
cap-large-decr=off");
+}
+
 sPAPRCapabilityInfo capability_table[SPAPR_CAP_NUM] = {
 [SPAPR_CAP_HTM] = {
 .name = "htm",
@@ -468,6 +475,15 @@ sPAPRCapabilityInfo capability_table[SPAPR_CAP_NUM] = {
 .type = "bool",
 .apply = cap_nested_kvm_hv_apply,
 },
+[SPAPR_CAP_LARGE_DECREMENTER] = {
+.name = "large-decr",
+.description = "Allow Large Decrementer",
+.index = SPAPR_CAP_LARGE_DECREMENTER,
+.get = spapr_cap_get_bool,
+.set = spapr_cap_set_bool,
+.type = "bool",
+.apply = cap_large_decr_apply,
+},
 };
 
 static sPAPRCapabilities default_caps_with_cpu(sPAPRMachineState *spapr,
@@ -596,6 +612,7 @@ SPAPR_CAP_MIG_STATE(cfpc, SPAPR_CAP_CFPC);
 SPAPR_CAP_MIG_STATE(sbbc, SPAPR_CAP_SBBC);
 SPAPR_CAP_MIG_STATE(ibs, SPAPR_CAP_IBS);
 SPAPR_CAP_MIG_STATE(nested_kvm_hv, SPAPR_CAP_NESTED_KVM_HV);
+SPAPR_CAP_MIG_STATE(large_decr, SPAPR_CAP_LARGE_DECREMENTER);
 
 void spapr_caps_init(sPAPRMachineState *spapr)
 {
diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
index 59073a7579..8efc5e0779 100644
--- a/include/hw/ppc/spapr.h
+++ b/include/hw/ppc/spapr.h
@@ -74,8 +74,10 @@ typedef enum {
 #define SPAPR_CAP_HPT_MAXPAGESIZE   0x06
 /* Nested KVM-HV */
 #define SPAPR_CAP_NESTED_KVM_HV 0x07
+/* Large Decrementer */
+#define SPAPR_CAP_LARGE_DECREMENTER 0x08
 /* Num Caps */
-#define SPAPR_CAP_NUM   (SPAPR_CAP_NESTED_KVM_HV + 1)
+#define SPAPR_CAP_NUM   (SPAPR_CAP_LARGE_DECREMENTER + 1)
 
 /*
  * Capability Values
@@ -828,6 +830,7 @@ extern const VMStateDescription vmstate_spapr_cap_cfpc;
 extern const VMStateDescription vmstate_spapr_cap_sbbc;
 extern const VMStateDescription vmstate_spapr_cap_ibs;
 extern const VMStateDescription vmstate_spapr_cap_nested_kvm_hv;
+extern const VMStateDescription vmstate_spapr_cap_large_decr;
 
 static inline uint8_t spapr_get_cap(sPAPRMachineState *spapr, int cap)
 {
-- 
2.13.6




Re: [Qemu-devel] [QEMU-PPC] [PATCH 4/4] target/ppc/spapr: Enable the large decrementer by default on POWER9

2019-02-26 Thread Suraj Jitindar Singh
On Tue, 2019-02-26 at 14:59 +1100, David Gibson wrote:
> On Tue, Feb 26, 2019 at 02:05:31PM +1100, Suraj Jitindar Singh wrote:
> > Enable the large decrementer by default on POWER9 cpu models. The
> > default value applied is that provided in the cpu class.
> > 
> > Signed-off-by: Suraj Jitindar Singh 
> > ---
> >  hw/ppc/spapr_caps.c | 7 +++
> >  1 file changed, 7 insertions(+)
> > 
> > diff --git a/hw/ppc/spapr_caps.c b/hw/ppc/spapr_caps.c
> > index e07568fb94..f48aa367e3 100644
> > --- a/hw/ppc/spapr_caps.c
> > +++ b/hw/ppc/spapr_caps.c
> > @@ -566,11 +566,18 @@ sPAPRCapabilityInfo
> > capability_table[SPAPR_CAP_NUM] = {
> >  static sPAPRCapabilities default_caps_with_cpu(sPAPRMachineState
> > *spapr,
> > const char
> > *cputype)
> >  {
> > +PowerPCCPUClass *pcc =
> > POWERPC_CPU_CLASS(object_class_by_name(cputype));
> >  sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
> >  sPAPRCapabilities caps;
> >  
> >  caps = smc->default_caps;
> >  
> > +caps.caps[SPAPR_CAP_LARGE_DECREMENTER] = pcc->hdecr_bits;
> 
> So, the rule with default_caps_with_cpu() is that it can reduce the
> value from the machine-global default, but never increase it (because
> that could change guest visible behaviour for existing machine
> versions).
> 
> I think the line above will do that.

Yep

> 
> > +if (!ppc_type_check_compat(cputype, CPU_POWERPC_LOGICAL_3_00,
> > +   0, spapr->max_compat_pvr)) {
> > +caps.caps[SPAPR_CAP_LARGE_DECREMENTER] = 0;
> 
> And this part I think is redundant, because hdecr_bits won't be large
> for anything pre-POWER9.
> 
> > +}
> > +
> >  if (!ppc_type_check_compat(cputype, CPU_POWERPC_LOGICAL_2_07,
> > 0, spapr->max_compat_pvr)) {
> >  caps.caps[SPAPR_CAP_HTM] = SPAPR_CAP_OFF;
> 
> 



Re: [Qemu-devel] [QEMU-PPC] [PATCH 3/4] target/ppc: Implement large decrementer support for KVM

2019-02-26 Thread Suraj Jitindar Singh
On Tue, 2019-02-26 at 14:55 +1100, David Gibson wrote:
> On Tue, Feb 26, 2019 at 02:05:30PM +1100, Suraj Jitindar Singh wrote:
> > Implement support to allow KVM guests to take advantage of the
> > large
> > decrementer introduced on POWER9 cpus.
> > 
> > To determine if the host can support the requested large
> > decrementer
> > size, we check it matches that specified in the ibm,dec-bits
> > device-tree
> > property. We also need to enable it in KVM by setting the LPCR_LD
> > bit in
> > the LPCR. Note that to do this we need to try and set the bit, then
> > read
> > it back to check the host allowed us to set it, if so we can use it
> > but
> > if we were unable to set it the host cannot support it and we must
> > not
> > use the large decrementer.
> > 
> > Signed-off-by: Suraj Jitindar Singh 
> > Signed-off-by: Cédric Le Goater 
> 
> Reviewed-by: David Gibson 
> 
> Although changes might be necessary to match it to things I've
> suggested in the earlier patches in the series.
> 
> Is the KVM side support for this already merged?  If so, as of when?

Yes, as of v4.13

> 
> > ---
> >  hw/ppc/spapr_caps.c  | 17 +++--
> >  target/ppc/kvm.c | 39 +++
> >  target/ppc/kvm_ppc.h | 12 
> >  3 files changed, 66 insertions(+), 2 deletions(-)
> > 
> > diff --git a/hw/ppc/spapr_caps.c b/hw/ppc/spapr_caps.c
> > index 44542fdbb2..e07568fb94 100644
> > --- a/hw/ppc/spapr_caps.c
> > +++ b/hw/ppc/spapr_caps.c
> > @@ -440,8 +440,16 @@ static void
> > cap_large_decr_apply(sPAPRMachineState *spapr,
> >  pcc->hdecr_bits);
> >  return;
> >  }
> > -} else {
> > -error_setg(errp, "No large decrementer support, try cap-
> > large-decr=0");
> > +} else if (kvm_enabled()) {
> > +int kvm_nr_bits = kvmppc_get_cap_large_decr();
> > +
> > +if (!kvm_nr_bits) {
> > +error_setg(errp, "No large decrementer support, try
> > cap-large-decr=0");
> > +} else if (val != kvm_nr_bits) {
> > +error_setg(errp,
> > +"Large decrementer size unsupported, try -cap-
> > large-decr=%d",
> > +kvm_nr_bits);
> > +}
> >  }
> >  }
> >  
> > @@ -452,6 +460,11 @@ static void
> > cap_large_decr_cpu_apply(sPAPRMachineState *spapr,
> >  CPUPPCState *env = >env;
> >  target_ulong lpcr = env->spr[SPR_LPCR];
> >  
> > +if (kvm_enabled()) {
> > +if (kvmppc_enable_cap_large_decr(cpu, !!val))
> > +error_setg(errp, "No large decrementer support, try
> > cap-large-decr=0");
> > +}
> > +
> >  if (val)
> >  lpcr |= LPCR_LD;
> >  else
> > diff --git a/target/ppc/kvm.c b/target/ppc/kvm.c
> > index d01852fe31..3f650c8fc4 100644
> > --- a/target/ppc/kvm.c
> > +++ b/target/ppc/kvm.c
> > @@ -91,6 +91,7 @@ static int cap_ppc_safe_cache;
> >  static int cap_ppc_safe_bounds_check;
> >  static int cap_ppc_safe_indirect_branch;
> >  static int cap_ppc_nested_kvm_hv;
> > +static int cap_large_decr;
> >  
> >  static uint32_t debug_inst_opcode;
> >  
> > @@ -124,6 +125,7 @@ static bool kvmppc_is_pr(KVMState *ks)
> >  
> >  static int kvm_ppc_register_host_cpu_type(MachineState *ms);
> >  static void kvmppc_get_cpu_characteristics(KVMState *s);
> > +static int kvmppc_get_dec_bits(void);
> >  
> >  int kvm_arch_init(MachineState *ms, KVMState *s)
> >  {
> > @@ -151,6 +153,7 @@ int kvm_arch_init(MachineState *ms, KVMState
> > *s)
> >  cap_resize_hpt = kvm_vm_check_extension(s,
> > KVM_CAP_SPAPR_RESIZE_HPT);
> >  kvmppc_get_cpu_characteristics(s);
> >  cap_ppc_nested_kvm_hv = kvm_vm_check_extension(s,
> > KVM_CAP_PPC_NESTED_HV);
> > +cap_large_decr = kvmppc_get_dec_bits();
> >  /*
> >   * Note: setting it to false because there is not such
> > capability
> >   * in KVM at this moment.
> > @@ -1927,6 +1930,15 @@ uint64_t kvmppc_get_clockfreq(void)
> >  return kvmppc_read_int_cpu_dt("clock-frequency");
> >  }
> >  
> > +static int kvmppc_get_dec_bits(void)
> > +{
> > +int nr_bits = kvmppc_read_int_cpu_dt("ibm,dec-bits");
> > +
> > +if (nr_bits > 0)
> > +return nr_bits;
> > +return 0;
> > +}
> > +
> >  static int kv

Re: [Qemu-devel] [QEMU-PPC] [PATCH 2/4] target/ppc: Implement large decrementer support for TCG

2019-02-26 Thread Suraj Jitindar Singh
On Tue, 2019-02-26 at 14:53 +1100, David Gibson wrote:
> On Tue, Feb 26, 2019 at 02:05:29PM +1100, Suraj Jitindar Singh wrote:
> > Prior to POWER9 the decrementer was a 32-bit register which
> > decremented
> > with each tick of the timebase. From POWER9 onwards the decrementer
> > can
> > be set to operate in a mode called large decrementer where it acts
> > as a
> > n-bit decrementing register which is visible as a 64-bit register,
> > that
> > is the value of the decrementer is sign extended to 64 bits (where
> > n is
> > implementation dependant).
> > 
> > The mode in which the decrementer operates is controlled by the
> > LPCR_LD
> > bit in the logical paritition control register (LPCR).
> > 
> > > From POWER9 onwards the HDEC (hypervisor decrementer) was
> > > enlarged to
> > 
> > h-bits, also sign extended to 64 bits (where h is implementation
> > dependant). Note this isn't configurable and is always enabled.
> > 
> > For TCG we allow the user to configure a custom large decrementer
> > size,
> > so long as it's at least 32 and less than the size of the HDEC (the
> > restrictions imposed by the ISA).
> > 
> > Signed-off-by: Suraj Jitindar Singh 
> > Signed-off-by: Cédric Le Goater 
> > ---
> >  hw/ppc/ppc.c| 78 -
> > 
> >  hw/ppc/spapr.c  |  8 +
> >  hw/ppc/spapr_caps.c | 38 +++-
> >  target/ppc/cpu-qom.h|  1 +
> >  target/ppc/cpu.h| 11 +++---
> >  target/ppc/mmu-hash64.c |  2 +-
> >  target/ppc/translate.c  |  2 +-
> >  target/ppc/translate_init.inc.c |  1 +
> >  8 files changed, 109 insertions(+), 32 deletions(-)
> > 
> > diff --git a/hw/ppc/ppc.c b/hw/ppc/ppc.c
> > index d1e3d4cd20..853afeed6a 100644
> > --- a/hw/ppc/ppc.c
> > +++ b/hw/ppc/ppc.c
> > @@ -744,10 +744,10 @@ bool ppc_decr_clear_on_delivery(CPUPPCState
> > *env)
> >  return ((tb_env->flags & flags) ==
> > PPC_DECR_UNDERFLOW_TRIGGERED);
> >  }
> >  
> > -static inline uint32_t _cpu_ppc_load_decr(CPUPPCState *env,
> > uint64_t next)
> > +static inline uint64_t _cpu_ppc_load_decr(CPUPPCState *env,
> > uint64_t next)
> 
> Hrm.  Given how we use this - and how muldiv64 works, wouldn't it
> make
> more sense to have it return int64_t (i.e. signed).

I mean, functionally it's the same. So sure

> 
> >  {
> >  ppc_tb_t *tb_env = env->tb_env;
> > -uint32_t decr;
> > +uint64_t decr;
> >  int64_t diff;
> >  
> >  diff = next - qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
> > @@ -758,27 +758,42 @@ static inline uint32_t
> > _cpu_ppc_load_decr(CPUPPCState *env, uint64_t next)
> >  }  else {
> >  decr = -muldiv64(-diff, tb_env->decr_freq,
> > NANOSECONDS_PER_SECOND);
> >  }
> > -LOG_TB("%s: %08" PRIx32 "\n", __func__, decr);
> > +LOG_TB("%s: %016" PRIx64 "\n", __func__, decr);
> >  
> >  return decr;
> >  }
> >  
> > -uint32_t cpu_ppc_load_decr (CPUPPCState *env)
> > +target_ulong cpu_ppc_load_decr (CPUPPCState *env)
> >  {
> >  ppc_tb_t *tb_env = env->tb_env;
> > +uint64_t decr;
> >  
> >  if (kvm_enabled()) {
> >  return env->spr[SPR_DECR];
> >  }
> >  
> > -return _cpu_ppc_load_decr(env, tb_env->decr_next);
> > +decr = _cpu_ppc_load_decr(env, tb_env->decr_next);
> > +
> > +/*
> > + * If large decrementer is enabled then the decrementer is
> > signed extened
> > + * to 64 bits, otherwise it is a 32 bit value.
> > + */
> > +if (env->spr[SPR_LPCR] & LPCR_LD)
> > +return decr;
> > +return (uint32_t) decr;
> >  }
> >  
> > -uint32_t cpu_ppc_load_hdecr (CPUPPCState *env)
> > +target_ulong cpu_ppc_load_hdecr (CPUPPCState *env)
> >  {
> >  ppc_tb_t *tb_env = env->tb_env;
> > +uint64_t decr;
> >  
> > -return _cpu_ppc_load_decr(env, tb_env->hdecr_next);
> > +decr =  _cpu_ppc_load_decr(env, tb_env->hdecr_next);
> > +
> > +/* If POWER9 or later then hdecr is sign extended to 64 bits
> > otherwise 32 */
> > +if (env->mmu_model & POWERPC_MMU_3_00)
> 
> You already have a pcc->hdecr_bits.  Wouldn't it make more sense to
> check against that than the cpu model directly?

The end result is the same sinc

Re: [Qemu-devel] [QEMU-PPC] [PATCH 1/4] target/ppc/spapr: Add SPAPR_CAP_LARGE_DECREMENTER

2019-02-25 Thread Suraj Jitindar Singh
On Tue, 2019-02-26 at 14:39 +1100, David Gibson wrote:
> On Tue, Feb 26, 2019 at 02:05:28PM +1100, Suraj Jitindar Singh wrote:
> > Add spapr_cap SPAPR_CAP_LARGE_DECREMENTER to be used to control the
> > availability and size of the large decrementer made available to
> > the
> > guest.
> > 
> > Signed-off-by: Suraj Jitindar Singh 
> > ---
> >  hw/ppc/spapr.c |  2 ++
> >  hw/ppc/spapr_caps.c| 45
> > +
> >  include/hw/ppc/spapr.h |  5 -
> >  3 files changed, 51 insertions(+), 1 deletion(-)
> > 
> > diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
> > index b6a571b6f1..acf62a2b9f 100644
> > --- a/hw/ppc/spapr.c
> > +++ b/hw/ppc/spapr.c
> > @@ -2077,6 +2077,7 @@ static const VMStateDescription vmstate_spapr
> > = {
> >  _spapr_irq_map,
> >  _spapr_cap_nested_kvm_hv,
> >  _spapr_dtb,
> > +_spapr_cap_large_decr,
> >  NULL
> >  }
> >  };
> > @@ -4288,6 +4289,7 @@ static void
> > spapr_machine_class_init(ObjectClass *oc, void *data)
> >  smc->default_caps.caps[SPAPR_CAP_IBS] = SPAPR_CAP_BROKEN;
> >  smc->default_caps.caps[SPAPR_CAP_HPT_MAXPAGESIZE] = 16; /*
> > 64kiB */
> >  smc->default_caps.caps[SPAPR_CAP_NESTED_KVM_HV] =
> > SPAPR_CAP_OFF;
> > +smc->default_caps.caps[SPAPR_CAP_LARGE_DECREMENTER] = 0;
> 
> This looks basically fine, but the name kind of suggests it's a
> boolean, whereas it's actually a number of bits.  I wonder if just
> calling it "decrementer bits" would be clearer, with it defaulting to
> 32.

Yes, except there's a difference between a decrementer with 32 bits and
a large decrementer with 32 bits...

SPAPR_CAP_LARGE_DECR_NR_BITS?

> 
> >  spapr_caps_add_properties(smc, _abort);
> >  smc->irq = _irq_xics;
> >  smc->dr_phb_enabled = true;
> > diff --git a/hw/ppc/spapr_caps.c b/hw/ppc/spapr_caps.c
> > index 64f98ae68d..1545a02729 100644
> > --- a/hw/ppc/spapr_caps.c
> > +++ b/hw/ppc/spapr_caps.c
> > @@ -182,6 +182,34 @@ static void spapr_cap_set_pagesize(Object
> > *obj, Visitor *v, const char *name,
> >  spapr->eff.caps[cap->index] = val;
> >  }
> >  
> > +static void spapr_cap_get_uint8(Object *obj, Visitor *v, const
> > char *name,
> > +void *opaque, Error **errp)
> > +{
> > +sPAPRCapabilityInfo *cap = opaque;
> > +sPAPRMachineState *spapr = SPAPR_MACHINE(obj);
> > +uint8_t val = spapr_get_cap(spapr, cap->index);
> > +
> > +visit_type_uint8(v, name, , errp);
> > +}
> > +
> > +static void spapr_cap_set_uint8(Object *obj, Visitor *v, const
> > char *name,
> > +void *opaque, Error **errp)
> > +{
> > +sPAPRCapabilityInfo *cap = opaque;
> > +sPAPRMachineState *spapr = SPAPR_MACHINE(obj);
> > +Error *local_err = NULL;
> > +uint8_t val;
> > +
> > +visit_type_uint8(v, name, , _err);
> > +if (local_err) {
> > +error_propagate(errp, local_err);
> > +return;
> > +}
> > +
> > +spapr->cmd_line_caps[cap->index] = true;
> > +spapr->eff.caps[cap->index] = val;
> > +}
> > +
> >  static void cap_htm_apply(sPAPRMachineState *spapr, uint8_t val,
> > Error **errp)
> >  {
> >  if (!val) {
> > @@ -390,6 +418,13 @@ static void
> > cap_nested_kvm_hv_apply(sPAPRMachineState *spapr,
> >  }
> >  }
> >  
> > +static void cap_large_decr_apply(sPAPRMachineState *spapr,
> > + uint8_t val, Error **errp)
> > +{
> > +if (val)
> > +error_setg(errp, "No large decrementer support, try cap-
> > large-decr=0");
> > +}
> > +
> >  sPAPRCapabilityInfo capability_table[SPAPR_CAP_NUM] = {
> >  [SPAPR_CAP_HTM] = {
> >  .name = "htm",
> > @@ -468,6 +503,15 @@ sPAPRCapabilityInfo
> > capability_table[SPAPR_CAP_NUM] = {
> >  .type = "bool",
> >  .apply = cap_nested_kvm_hv_apply,
> >  },
> > +[SPAPR_CAP_LARGE_DECREMENTER] = {
> > +.name = "large-decr",
> > +.description = "Size of Large Decrementer for the Guest
> > (bits) 0=disabled",
> > +.index = SPAPR_CAP_LARGE_DECREMENTER,
> > +.get = spapr_cap_get_uint8,
> > +.set = spapr_cap_set_uint8,
> > +.type = "int",
> &g

[Qemu-devel] [QEMU-PPC] [PATCH 2/4] target/ppc: Implement large decrementer support for TCG

2019-02-25 Thread Suraj Jitindar Singh
Prior to POWER9 the decrementer was a 32-bit register which decremented
with each tick of the timebase. From POWER9 onwards the decrementer can
be set to operate in a mode called large decrementer where it acts as a
n-bit decrementing register which is visible as a 64-bit register, that
is the value of the decrementer is sign extended to 64 bits (where n is
implementation dependant).

The mode in which the decrementer operates is controlled by the LPCR_LD
bit in the logical paritition control register (LPCR).

>From POWER9 onwards the HDEC (hypervisor decrementer) was enlarged to
h-bits, also sign extended to 64 bits (where h is implementation
dependant). Note this isn't configurable and is always enabled.

For TCG we allow the user to configure a custom large decrementer size,
so long as it's at least 32 and less than the size of the HDEC (the
restrictions imposed by the ISA).

Signed-off-by: Suraj Jitindar Singh 
Signed-off-by: Cédric Le Goater 
---
 hw/ppc/ppc.c| 78 -
 hw/ppc/spapr.c  |  8 +
 hw/ppc/spapr_caps.c | 38 +++-
 target/ppc/cpu-qom.h|  1 +
 target/ppc/cpu.h| 11 +++---
 target/ppc/mmu-hash64.c |  2 +-
 target/ppc/translate.c  |  2 +-
 target/ppc/translate_init.inc.c |  1 +
 8 files changed, 109 insertions(+), 32 deletions(-)

diff --git a/hw/ppc/ppc.c b/hw/ppc/ppc.c
index d1e3d4cd20..853afeed6a 100644
--- a/hw/ppc/ppc.c
+++ b/hw/ppc/ppc.c
@@ -744,10 +744,10 @@ bool ppc_decr_clear_on_delivery(CPUPPCState *env)
 return ((tb_env->flags & flags) == PPC_DECR_UNDERFLOW_TRIGGERED);
 }
 
-static inline uint32_t _cpu_ppc_load_decr(CPUPPCState *env, uint64_t next)
+static inline uint64_t _cpu_ppc_load_decr(CPUPPCState *env, uint64_t next)
 {
 ppc_tb_t *tb_env = env->tb_env;
-uint32_t decr;
+uint64_t decr;
 int64_t diff;
 
 diff = next - qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
@@ -758,27 +758,42 @@ static inline uint32_t _cpu_ppc_load_decr(CPUPPCState 
*env, uint64_t next)
 }  else {
 decr = -muldiv64(-diff, tb_env->decr_freq, NANOSECONDS_PER_SECOND);
 }
-LOG_TB("%s: %08" PRIx32 "\n", __func__, decr);
+LOG_TB("%s: %016" PRIx64 "\n", __func__, decr);
 
 return decr;
 }
 
-uint32_t cpu_ppc_load_decr (CPUPPCState *env)
+target_ulong cpu_ppc_load_decr (CPUPPCState *env)
 {
 ppc_tb_t *tb_env = env->tb_env;
+uint64_t decr;
 
 if (kvm_enabled()) {
 return env->spr[SPR_DECR];
 }
 
-return _cpu_ppc_load_decr(env, tb_env->decr_next);
+decr = _cpu_ppc_load_decr(env, tb_env->decr_next);
+
+/*
+ * If large decrementer is enabled then the decrementer is signed extened
+ * to 64 bits, otherwise it is a 32 bit value.
+ */
+if (env->spr[SPR_LPCR] & LPCR_LD)
+return decr;
+return (uint32_t) decr;
 }
 
-uint32_t cpu_ppc_load_hdecr (CPUPPCState *env)
+target_ulong cpu_ppc_load_hdecr (CPUPPCState *env)
 {
 ppc_tb_t *tb_env = env->tb_env;
+uint64_t decr;
 
-return _cpu_ppc_load_decr(env, tb_env->hdecr_next);
+decr =  _cpu_ppc_load_decr(env, tb_env->hdecr_next);
+
+/* If POWER9 or later then hdecr is sign extended to 64 bits otherwise 32 
*/
+if (env->mmu_model & POWERPC_MMU_3_00)
+return decr;
+return (uint32_t) decr;
 }
 
 uint64_t cpu_ppc_load_purr (CPUPPCState *env)
@@ -832,13 +847,21 @@ static void __cpu_ppc_store_decr(PowerPCCPU *cpu, 
uint64_t *nextp,
  QEMUTimer *timer,
  void (*raise_excp)(void *),
  void (*lower_excp)(PowerPCCPU *),
- uint32_t decr, uint32_t value)
+ target_ulong decr, target_ulong value,
+ int nr_bits)
 {
 CPUPPCState *env = >env;
 ppc_tb_t *tb_env = env->tb_env;
 uint64_t now, next;
+bool negative;
+
+/* Truncate value to decr_width and sign extend for simplicity */
+value &= ((1ULL << nr_bits) - 1);
+negative = !!(value & (1ULL << (nr_bits - 1)));
+if (negative)
+value |= (0xULL << nr_bits);
 
-LOG_TB("%s: %08" PRIx32 " => %08" PRIx32 "\n", __func__,
+LOG_TB("%s: " TARGET_FMT_lx " => " TARGET_FMT_lx "\n", __func__,
 decr, value);
 
 if (kvm_enabled()) {
@@ -860,15 +883,15 @@ static void __cpu_ppc_store_decr(PowerPCCPU *cpu, 
uint64_t *nextp,
  * an edge interrupt, so raise it here too.
  */
 if ((value < 3) ||
-((tb_env->flags & PPC_DECR_UNDERFLOW_LEVEL) && (value & 0x8000)) ||
-((tb_env->flags & PPC_DECR_UNDERFLOW_TRIGGERED) && (value & 0x8000)
-  && !(d

[Qemu-devel] [QEMU-PPC] [PATCH 3/4] target/ppc: Implement large decrementer support for KVM

2019-02-25 Thread Suraj Jitindar Singh
Implement support to allow KVM guests to take advantage of the large
decrementer introduced on POWER9 cpus.

To determine if the host can support the requested large decrementer
size, we check it matches that specified in the ibm,dec-bits device-tree
property. We also need to enable it in KVM by setting the LPCR_LD bit in
the LPCR. Note that to do this we need to try and set the bit, then read
it back to check the host allowed us to set it, if so we can use it but
if we were unable to set it the host cannot support it and we must not
use the large decrementer.

Signed-off-by: Suraj Jitindar Singh 
Signed-off-by: Cédric Le Goater 
---
 hw/ppc/spapr_caps.c  | 17 +++--
 target/ppc/kvm.c | 39 +++
 target/ppc/kvm_ppc.h | 12 
 3 files changed, 66 insertions(+), 2 deletions(-)

diff --git a/hw/ppc/spapr_caps.c b/hw/ppc/spapr_caps.c
index 44542fdbb2..e07568fb94 100644
--- a/hw/ppc/spapr_caps.c
+++ b/hw/ppc/spapr_caps.c
@@ -440,8 +440,16 @@ static void cap_large_decr_apply(sPAPRMachineState *spapr,
 pcc->hdecr_bits);
 return;
 }
-} else {
-error_setg(errp, "No large decrementer support, try cap-large-decr=0");
+} else if (kvm_enabled()) {
+int kvm_nr_bits = kvmppc_get_cap_large_decr();
+
+if (!kvm_nr_bits) {
+error_setg(errp, "No large decrementer support, try 
cap-large-decr=0");
+} else if (val != kvm_nr_bits) {
+error_setg(errp,
+"Large decrementer size unsupported, try -cap-large-decr=%d",
+kvm_nr_bits);
+}
 }
 }
 
@@ -452,6 +460,11 @@ static void cap_large_decr_cpu_apply(sPAPRMachineState 
*spapr,
 CPUPPCState *env = >env;
 target_ulong lpcr = env->spr[SPR_LPCR];
 
+if (kvm_enabled()) {
+if (kvmppc_enable_cap_large_decr(cpu, !!val))
+error_setg(errp, "No large decrementer support, try 
cap-large-decr=0");
+}
+
 if (val)
 lpcr |= LPCR_LD;
 else
diff --git a/target/ppc/kvm.c b/target/ppc/kvm.c
index d01852fe31..3f650c8fc4 100644
--- a/target/ppc/kvm.c
+++ b/target/ppc/kvm.c
@@ -91,6 +91,7 @@ static int cap_ppc_safe_cache;
 static int cap_ppc_safe_bounds_check;
 static int cap_ppc_safe_indirect_branch;
 static int cap_ppc_nested_kvm_hv;
+static int cap_large_decr;
 
 static uint32_t debug_inst_opcode;
 
@@ -124,6 +125,7 @@ static bool kvmppc_is_pr(KVMState *ks)
 
 static int kvm_ppc_register_host_cpu_type(MachineState *ms);
 static void kvmppc_get_cpu_characteristics(KVMState *s);
+static int kvmppc_get_dec_bits(void);
 
 int kvm_arch_init(MachineState *ms, KVMState *s)
 {
@@ -151,6 +153,7 @@ int kvm_arch_init(MachineState *ms, KVMState *s)
 cap_resize_hpt = kvm_vm_check_extension(s, KVM_CAP_SPAPR_RESIZE_HPT);
 kvmppc_get_cpu_characteristics(s);
 cap_ppc_nested_kvm_hv = kvm_vm_check_extension(s, KVM_CAP_PPC_NESTED_HV);
+cap_large_decr = kvmppc_get_dec_bits();
 /*
  * Note: setting it to false because there is not such capability
  * in KVM at this moment.
@@ -1927,6 +1930,15 @@ uint64_t kvmppc_get_clockfreq(void)
 return kvmppc_read_int_cpu_dt("clock-frequency");
 }
 
+static int kvmppc_get_dec_bits(void)
+{
+int nr_bits = kvmppc_read_int_cpu_dt("ibm,dec-bits");
+
+if (nr_bits > 0)
+return nr_bits;
+return 0;
+}
+
 static int kvmppc_get_pvinfo(CPUPPCState *env, struct kvm_ppc_pvinfo *pvinfo)
  {
  PowerPCCPU *cpu = ppc_env_get_cpu(env);
@@ -2442,6 +2454,33 @@ bool kvmppc_has_cap_spapr_vfio(void)
 return cap_spapr_vfio;
 }
 
+int kvmppc_get_cap_large_decr(void)
+{
+return cap_large_decr;
+}
+
+int kvmppc_enable_cap_large_decr(PowerPCCPU *cpu, int enable)
+{
+CPUState *cs = CPU(cpu);
+uint64_t lpcr;
+
+kvm_get_one_reg(cs, KVM_REG_PPC_LPCR_64, );
+/* Do we need to modify the LPCR? */
+if (!!(lpcr & LPCR_LD) != !!enable) {
+if (enable)
+lpcr |= LPCR_LD;
+else
+lpcr &= ~LPCR_LD;
+kvm_set_one_reg(cs, KVM_REG_PPC_LPCR_64, );
+kvm_get_one_reg(cs, KVM_REG_PPC_LPCR_64, );
+
+if (!!(lpcr & LPCR_LD) != !!enable)
+return -1;
+}
+
+return 0;
+}
+
 PowerPCCPUClass *kvm_ppc_get_host_cpu_class(void)
 {
 uint32_t host_pvr = mfpvr();
diff --git a/target/ppc/kvm_ppc.h b/target/ppc/kvm_ppc.h
index bdfaa4e70a..a79835bd14 100644
--- a/target/ppc/kvm_ppc.h
+++ b/target/ppc/kvm_ppc.h
@@ -64,6 +64,8 @@ int kvmppc_get_cap_safe_bounds_check(void);
 int kvmppc_get_cap_safe_indirect_branch(void);
 bool kvmppc_has_cap_nested_kvm_hv(void);
 int kvmppc_set_cap_nested_kvm_hv(int enable);
+int kvmppc_get_cap_large_decr(void);
+int kvmppc_enable_cap_large_decr(PowerPCCPU *cpu, int enable);
 int kvmppc_enable_hwrng(void);
 int kvmppc_put_books_sregs(PowerPCCPU *cpu);
 PowerPCCPUClass *kvm_ppc_get_host_cpu_class(void);
@@ -332,6 +334,16 @@ sta

[Qemu-devel] [QEMU-PPC] [PATCH 1/4] target/ppc/spapr: Add SPAPR_CAP_LARGE_DECREMENTER

2019-02-25 Thread Suraj Jitindar Singh
Add spapr_cap SPAPR_CAP_LARGE_DECREMENTER to be used to control the
availability and size of the large decrementer made available to the
guest.

Signed-off-by: Suraj Jitindar Singh 
---
 hw/ppc/spapr.c |  2 ++
 hw/ppc/spapr_caps.c| 45 +
 include/hw/ppc/spapr.h |  5 -
 3 files changed, 51 insertions(+), 1 deletion(-)

diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index b6a571b6f1..acf62a2b9f 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -2077,6 +2077,7 @@ static const VMStateDescription vmstate_spapr = {
 _spapr_irq_map,
 _spapr_cap_nested_kvm_hv,
 _spapr_dtb,
+_spapr_cap_large_decr,
 NULL
 }
 };
@@ -4288,6 +4289,7 @@ static void spapr_machine_class_init(ObjectClass *oc, 
void *data)
 smc->default_caps.caps[SPAPR_CAP_IBS] = SPAPR_CAP_BROKEN;
 smc->default_caps.caps[SPAPR_CAP_HPT_MAXPAGESIZE] = 16; /* 64kiB */
 smc->default_caps.caps[SPAPR_CAP_NESTED_KVM_HV] = SPAPR_CAP_OFF;
+smc->default_caps.caps[SPAPR_CAP_LARGE_DECREMENTER] = 0;
 spapr_caps_add_properties(smc, _abort);
 smc->irq = _irq_xics;
 smc->dr_phb_enabled = true;
diff --git a/hw/ppc/spapr_caps.c b/hw/ppc/spapr_caps.c
index 64f98ae68d..1545a02729 100644
--- a/hw/ppc/spapr_caps.c
+++ b/hw/ppc/spapr_caps.c
@@ -182,6 +182,34 @@ static void spapr_cap_set_pagesize(Object *obj, Visitor 
*v, const char *name,
 spapr->eff.caps[cap->index] = val;
 }
 
+static void spapr_cap_get_uint8(Object *obj, Visitor *v, const char *name,
+void *opaque, Error **errp)
+{
+sPAPRCapabilityInfo *cap = opaque;
+sPAPRMachineState *spapr = SPAPR_MACHINE(obj);
+uint8_t val = spapr_get_cap(spapr, cap->index);
+
+visit_type_uint8(v, name, , errp);
+}
+
+static void spapr_cap_set_uint8(Object *obj, Visitor *v, const char *name,
+void *opaque, Error **errp)
+{
+sPAPRCapabilityInfo *cap = opaque;
+sPAPRMachineState *spapr = SPAPR_MACHINE(obj);
+Error *local_err = NULL;
+uint8_t val;
+
+visit_type_uint8(v, name, , _err);
+if (local_err) {
+error_propagate(errp, local_err);
+return;
+}
+
+spapr->cmd_line_caps[cap->index] = true;
+spapr->eff.caps[cap->index] = val;
+}
+
 static void cap_htm_apply(sPAPRMachineState *spapr, uint8_t val, Error **errp)
 {
 if (!val) {
@@ -390,6 +418,13 @@ static void cap_nested_kvm_hv_apply(sPAPRMachineState 
*spapr,
 }
 }
 
+static void cap_large_decr_apply(sPAPRMachineState *spapr,
+ uint8_t val, Error **errp)
+{
+if (val)
+error_setg(errp, "No large decrementer support, try cap-large-decr=0");
+}
+
 sPAPRCapabilityInfo capability_table[SPAPR_CAP_NUM] = {
 [SPAPR_CAP_HTM] = {
 .name = "htm",
@@ -468,6 +503,15 @@ sPAPRCapabilityInfo capability_table[SPAPR_CAP_NUM] = {
 .type = "bool",
 .apply = cap_nested_kvm_hv_apply,
 },
+[SPAPR_CAP_LARGE_DECREMENTER] = {
+.name = "large-decr",
+.description = "Size of Large Decrementer for the Guest (bits) 
0=disabled",
+.index = SPAPR_CAP_LARGE_DECREMENTER,
+.get = spapr_cap_get_uint8,
+.set = spapr_cap_set_uint8,
+.type = "int",
+.apply = cap_large_decr_apply,
+},
 };
 
 static sPAPRCapabilities default_caps_with_cpu(sPAPRMachineState *spapr,
@@ -596,6 +640,7 @@ SPAPR_CAP_MIG_STATE(cfpc, SPAPR_CAP_CFPC);
 SPAPR_CAP_MIG_STATE(sbbc, SPAPR_CAP_SBBC);
 SPAPR_CAP_MIG_STATE(ibs, SPAPR_CAP_IBS);
 SPAPR_CAP_MIG_STATE(nested_kvm_hv, SPAPR_CAP_NESTED_KVM_HV);
+SPAPR_CAP_MIG_STATE(large_decr, SPAPR_CAP_LARGE_DECREMENTER);
 
 void spapr_caps_init(sPAPRMachineState *spapr)
 {
diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
index 59073a7579..8efc5e0779 100644
--- a/include/hw/ppc/spapr.h
+++ b/include/hw/ppc/spapr.h
@@ -74,8 +74,10 @@ typedef enum {
 #define SPAPR_CAP_HPT_MAXPAGESIZE   0x06
 /* Nested KVM-HV */
 #define SPAPR_CAP_NESTED_KVM_HV 0x07
+/* Large Decrementer */
+#define SPAPR_CAP_LARGE_DECREMENTER 0x08
 /* Num Caps */
-#define SPAPR_CAP_NUM   (SPAPR_CAP_NESTED_KVM_HV + 1)
+#define SPAPR_CAP_NUM   (SPAPR_CAP_LARGE_DECREMENTER + 1)
 
 /*
  * Capability Values
@@ -828,6 +830,7 @@ extern const VMStateDescription vmstate_spapr_cap_cfpc;
 extern const VMStateDescription vmstate_spapr_cap_sbbc;
 extern const VMStateDescription vmstate_spapr_cap_ibs;
 extern const VMStateDescription vmstate_spapr_cap_nested_kvm_hv;
+extern const VMStateDescription vmstate_spapr_cap_large_decr;
 
 static inline uint8_t spapr_get_cap(sPAPRMachineState *spapr, int cap)
 {
-- 
2.13.6




[Qemu-devel] [QEMU-PPC] [PATCH 4/4] target/ppc/spapr: Enable the large decrementer by default on POWER9

2019-02-25 Thread Suraj Jitindar Singh
Enable the large decrementer by default on POWER9 cpu models. The
default value applied is that provided in the cpu class.

Signed-off-by: Suraj Jitindar Singh 
---
 hw/ppc/spapr_caps.c | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/hw/ppc/spapr_caps.c b/hw/ppc/spapr_caps.c
index e07568fb94..f48aa367e3 100644
--- a/hw/ppc/spapr_caps.c
+++ b/hw/ppc/spapr_caps.c
@@ -566,11 +566,18 @@ sPAPRCapabilityInfo capability_table[SPAPR_CAP_NUM] = {
 static sPAPRCapabilities default_caps_with_cpu(sPAPRMachineState *spapr,
const char *cputype)
 {
+PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(object_class_by_name(cputype));
 sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
 sPAPRCapabilities caps;
 
 caps = smc->default_caps;
 
+caps.caps[SPAPR_CAP_LARGE_DECREMENTER] = pcc->hdecr_bits;
+if (!ppc_type_check_compat(cputype, CPU_POWERPC_LOGICAL_3_00,
+   0, spapr->max_compat_pvr)) {
+caps.caps[SPAPR_CAP_LARGE_DECREMENTER] = 0;
+}
+
 if (!ppc_type_check_compat(cputype, CPU_POWERPC_LOGICAL_2_07,
0, spapr->max_compat_pvr)) {
 caps.caps[SPAPR_CAP_HTM] = SPAPR_CAP_OFF;
-- 
2.13.6




[Qemu-devel] [QEMU-PPC] [PATCH] target/ppc: tcg: Implement addex instruction

2018-11-14 Thread Suraj Jitindar Singh
Implement the addex instruction introduced in ISA V3.00 in qemu tcg.

The add extended using alternate carry bit (addex) instruction performs
the same operation as the add extended (adde) instruction, but using the
overflow (ov) field in the fixed point exception register (xer) as the
carry in and out instead of the carry (ca) field.

The instruction has a Z23-form, not an XO form, as follows:

--
|   31   |   RT   |   RA   |   RB   |   CY   | 170 |  0  |
--
0611   16   21   233132

However since the only valid form of the instruction defined so far is
CY = 0, we can treat this like an XO form instruction.

There is no dot form (addex.) of the instruction and the summary overflow
(so) bit in the xer is not modified by this instruction.

For simplicity we reuse the gen_op_arith_add function and add a function
argument to specify where the carry in input should come from and the
carry out output be stored (note must be the same location).

Signed-off-by: Suraj Jitindar Singh 
---
 disas/ppc.c|  2 ++
 target/ppc/translate.c | 60 +++---
 2 files changed, 35 insertions(+), 27 deletions(-)

diff --git a/disas/ppc.c b/disas/ppc.c
index 5ab9c35a84..da1140ba2b 100644
--- a/disas/ppc.c
+++ b/disas/ppc.c
@@ -3734,6 +3734,8 @@ const struct powerpc_opcode powerpc_opcodes[] = {
 { "addmeo.", XO(31,234,1,1), XORB_MASK, PPCCOM,{ RT, RA } },
 { "ameo.",   XO(31,234,1,1), XORB_MASK, PWRCOM,{ RT, RA } },
 
+{ "addex",   XO(31,170,0,0), XO_MASK,   POWER9, { RT, RA, RB } },
+
 { "mullw",   XO(31,235,0,0), XO_MASK,  PPCCOM, { RT, RA, RB } },
 { "muls",XO(31,235,0,0), XO_MASK,  PWRCOM, { RT, RA, RB } },
 { "mullw.",  XO(31,235,0,1), XO_MASK,  PPCCOM, { RT, RA, RB } },
diff --git a/target/ppc/translate.c b/target/ppc/translate.c
index 2b37910248..96894ab9a8 100644
--- a/target/ppc/translate.c
+++ b/target/ppc/translate.c
@@ -849,7 +849,7 @@ static inline void gen_op_arith_compute_ov(DisasContext 
*ctx, TCGv arg0,
 
 static inline void gen_op_arith_compute_ca32(DisasContext *ctx,
  TCGv res, TCGv arg0, TCGv arg1,
- int sub)
+ TCGv ca32, int sub)
 {
 TCGv t0;
 
@@ -864,13 +864,14 @@ static inline void gen_op_arith_compute_ca32(DisasContext 
*ctx,
 tcg_gen_xor_tl(t0, arg0, arg1);
 }
 tcg_gen_xor_tl(t0, t0, res);
-tcg_gen_extract_tl(cpu_ca32, t0, 32, 1);
+tcg_gen_extract_tl(ca32, t0, 32, 1);
 tcg_temp_free(t0);
 }
 
 /* Common add function */
 static inline void gen_op_arith_add(DisasContext *ctx, TCGv ret, TCGv arg1,
-TCGv arg2, bool add_ca, bool compute_ca,
+TCGv arg2, TCGv ca, TCGv ca32,
+bool add_ca, bool compute_ca,
 bool compute_ov, bool compute_rc0)
 {
 TCGv t0 = ret;
@@ -888,29 +889,29 @@ static inline void gen_op_arith_add(DisasContext *ctx, 
TCGv ret, TCGv arg1,
 tcg_gen_xor_tl(t1, arg1, arg2);/* add without carry */
 tcg_gen_add_tl(t0, arg1, arg2);
 if (add_ca) {
-tcg_gen_add_tl(t0, t0, cpu_ca);
+tcg_gen_add_tl(t0, t0, ca);
 }
-tcg_gen_xor_tl(cpu_ca, t0, t1);/* bits changed w/ carry */
+tcg_gen_xor_tl(ca, t0, t1);/* bits changed w/ carry */
 tcg_temp_free(t1);
-tcg_gen_extract_tl(cpu_ca, cpu_ca, 32, 1);
+tcg_gen_extract_tl(ca, ca, 32, 1);
 if (is_isa300(ctx)) {
-tcg_gen_mov_tl(cpu_ca32, cpu_ca);
+tcg_gen_mov_tl(ca32, ca);
 }
 } else {
 TCGv zero = tcg_const_tl(0);
 if (add_ca) {
-tcg_gen_add2_tl(t0, cpu_ca, arg1, zero, cpu_ca, zero);
-tcg_gen_add2_tl(t0, cpu_ca, t0, cpu_ca, arg2, zero);
+tcg_gen_add2_tl(t0, ca, arg1, zero, ca, zero);
+tcg_gen_add2_tl(t0, ca, t0, ca, arg2, zero);
 } else {
-tcg_gen_add2_tl(t0, cpu_ca, arg1, zero, arg2, zero);
+tcg_gen_add2_tl(t0, ca, arg1, zero, arg2, zero);
 }
-gen_op_arith_compute_ca32(ctx, t0, arg1, arg2, 0);
+gen_op_arith_compute_ca32(ctx, t0, arg1, arg2, ca32, 0);
 tcg_temp_free(zero);
 }
 } else {
 tcg_gen_add_tl(t0, arg1, arg2);
 if (add_ca) {
-tcg_gen_add_tl(t0, t0, cpu_ca);
+tcg_gen_add_tl(t0, t0, ca);
 }
 }
 
@@ -927,40 +928,44 @@ stat

[Qemu-devel] [QEMU-PPC] [PATCH V3 1/3] target/ppc: Update linux-headers for v4.19-rc7

2018-10-11 Thread Suraj Jitindar Singh
Signed-off-by: Suraj Jitindar Singh 
---
 linux-headers/asm-powerpc/kvm.h | 1 +
 linux-headers/linux/kvm.h   | 1 +
 2 files changed, 2 insertions(+)

diff --git a/linux-headers/asm-powerpc/kvm.h b/linux-headers/asm-powerpc/kvm.h
index 1b32b56a03..8c876c166e 100644
--- a/linux-headers/asm-powerpc/kvm.h
+++ b/linux-headers/asm-powerpc/kvm.h
@@ -634,6 +634,7 @@ struct kvm_ppc_cpu_char {
 
 #define KVM_REG_PPC_DEC_EXPIRY (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xbe)
 #define KVM_REG_PPC_ONLINE (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xbf)
+#define KVM_REG_PPC_PTCR   (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xc0)
 
 /* Transactional Memory checkpointed state:
  * This is all GPRs, all VSX regs and a subset of SPRs
diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h
index 66790724f1..d49767ad25 100644
--- a/linux-headers/linux/kvm.h
+++ b/linux-headers/linux/kvm.h
@@ -951,6 +951,7 @@ struct kvm_ppc_resize_hpt {
 #define KVM_CAP_HYPERV_TLBFLUSH 155
 #define KVM_CAP_S390_HPAGE_1M 156
 #define KVM_CAP_NESTED_STATE 157
+#define KVM_CAP_PPC_NESTED_HV 160
 
 #ifdef KVM_CAP_IRQ_ROUTING
 
-- 
2.13.6




[Qemu-devel] [QEMU-PPC] [PATCH V3 2/3] target/ppc: Add one reg id for ptcr

2018-10-11 Thread Suraj Jitindar Singh
The ptcr (partition table control register) is used to store the address
and size of the partition table. For nested kvm-hv we have a level 1
guest register the location of it's partition table with the hypervisor.
Thus to support migration we need to be able to read this out of kvm
and restore it post migration.

Add the one reg id for the ptcr.

Signed-off-by: Suraj Jitindar Singh 
Reviewed-by: David Gibson 
---
 target/ppc/translate_init.inc.c | 10 +-
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/target/ppc/translate_init.inc.c b/target/ppc/translate_init.inc.c
index 263e63cb03..487196800b 100644
--- a/target/ppc/translate_init.inc.c
+++ b/target/ppc/translate_init.inc.c
@@ -8197,11 +8197,11 @@ static void gen_spr_power9_mmu(CPUPPCState *env)
 {
 #if !defined(CONFIG_USER_ONLY)
 /* Partition Table Control */
-spr_register_hv(env, SPR_PTCR, "PTCR",
-SPR_NOACCESS, SPR_NOACCESS,
-SPR_NOACCESS, SPR_NOACCESS,
-_read_generic, _write_ptcr,
-0x);
+spr_register_kvm_hv(env, SPR_PTCR, "PTCR",
+SPR_NOACCESS, SPR_NOACCESS,
+SPR_NOACCESS, SPR_NOACCESS,
+_read_generic, _write_ptcr,
+KVM_REG_PPC_PTCR, 0x);
 #endif
 }
 
-- 
2.13.6




[Qemu-devel] [QEMU-PPC] [PATCH V3 0/3] ppc/spapr: Add support for nested kvm-hv

2018-10-11 Thread Suraj Jitindar Singh
This patch series adds the qemu support for running nested kvm-hv on a
POWER9 platform with appropriate hypervisor support and migration of
these guests.
That is, the ability to run kvm-hv guests as guests of an operating system
which is itself a kvm-hv guest.

The host (L0 hypervisor) and level 1 guest (L1 guest hypervisor) require
the following patch series:
KVM: PPC: Book3S HV: Nested HV virtualization

And this patch series in the qemu instance running on the L0 hypervisor.

Patch series based on: ppc-for-3.1

The cap number is now in Paolo's tree so hopefully we can rely on it not
changing.

V2 -> V3:
- The enable cap ioctl no longer takes an enable field to indicate
  disable/enable, but just enables the cap. So update to match this
  kernel change. (The cap starts out disable by default)

Suraj Jitindar Singh (3):
  target/ppc: Update linux-headers for v4.19-rc7
  target/ppc: Add one reg id for ptcr
  ppc/spapr_caps: Add SPAPR_CAP_NESTED_KVM_HV

 hw/ppc/spapr.c  |  2 ++
 hw/ppc/spapr_caps.c | 32 
 include/hw/ppc/spapr.h  |  5 -
 linux-headers/asm-powerpc/kvm.h |  1 +
 linux-headers/linux/kvm.h   |  1 +
 target/ppc/kvm.c| 12 
 target/ppc/kvm_ppc.h| 12 
 target/ppc/translate_init.inc.c | 10 +-
 8 files changed, 69 insertions(+), 6 deletions(-)

-- 
2.13.6




[Qemu-devel] [QEMU-PPC] [PATCH V3 3/3] ppc/spapr_caps: Add SPAPR_CAP_NESTED_KVM_HV

2018-10-11 Thread Suraj Jitindar Singh
Add the spapr cap SPAPR_CAP_NESTED_KVM_HV to be used to control the
availability of nested kvm-hv to the level 1 (L1) guest.

Assuming a hypervisor with support enabled an L1 guest can be allowed to
use the kvm-hv module (and thus run it's own kvm-hv guests) by setting:
-machine pseries,cap-nested-hv=true
or disabled with:
-machine pseries,cap-nested-hv=false

Signed-off-by: Suraj Jitindar Singh 
---
 hw/ppc/spapr.c |  2 ++
 hw/ppc/spapr_caps.c| 32 
 include/hw/ppc/spapr.h |  5 -
 target/ppc/kvm.c   | 12 
 target/ppc/kvm_ppc.h   | 12 
 5 files changed, 62 insertions(+), 1 deletion(-)

diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index 98868d893a..8ce97900e9 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -1915,6 +1915,7 @@ static const VMStateDescription vmstate_spapr = {
 _spapr_cap_sbbc,
 _spapr_cap_ibs,
 _spapr_irq_map,
+_spapr_cap_nested_kvm_hv,
 NULL
 }
 };
@@ -3886,6 +3887,7 @@ static void spapr_machine_class_init(ObjectClass *oc, 
void *data)
 smc->default_caps.caps[SPAPR_CAP_SBBC] = SPAPR_CAP_BROKEN;
 smc->default_caps.caps[SPAPR_CAP_IBS] = SPAPR_CAP_BROKEN;
 smc->default_caps.caps[SPAPR_CAP_HPT_MAXPAGESIZE] = 16; /* 64kiB */
+smc->default_caps.caps[SPAPR_CAP_NESTED_KVM_HV] = SPAPR_CAP_OFF;
 spapr_caps_add_properties(smc, _abort);
 smc->irq = _irq_xics;
 }
diff --git a/hw/ppc/spapr_caps.c b/hw/ppc/spapr_caps.c
index aa605cea91..8e1d791c63 100644
--- a/hw/ppc/spapr_caps.c
+++ b/hw/ppc/spapr_caps.c
@@ -368,6 +368,28 @@ static void 
cap_hpt_maxpagesize_cpu_apply(sPAPRMachineState *spapr,
 ppc_hash64_filter_pagesizes(cpu, spapr_pagesize_cb, );
 }
 
+static void cap_nested_kvm_hv_apply(sPAPRMachineState *spapr,
+uint8_t val, Error **errp)
+{
+if (!val) {
+/* capability disabled by default */
+return;
+}
+
+if (tcg_enabled()) {
+error_setg(errp,
+   "No Nested KVM-HV support in tcg, try cap-nested-hv=off");
+} else if (kvm_enabled()) {
+if (!kvmppc_has_cap_nested_kvm_hv()) {
+error_setg(errp,
+"KVM implementation does not support Nested KVM-HV, try cap-nested-hv=off");
+} else if (kvmppc_enable_nested_kvm_hv() < 0) {
+error_setg(errp,
+"Error enabling cap-nested-hv with KVM, try cap-nested-hv=off");
+}
+}
+}
+
 sPAPRCapabilityInfo capability_table[SPAPR_CAP_NUM] = {
 [SPAPR_CAP_HTM] = {
 .name = "htm",
@@ -437,6 +459,15 @@ sPAPRCapabilityInfo capability_table[SPAPR_CAP_NUM] = {
 .apply = cap_hpt_maxpagesize_apply,
 .cpu_apply = cap_hpt_maxpagesize_cpu_apply,
 },
+[SPAPR_CAP_NESTED_KVM_HV] = {
+.name = "nested-hv",
+.description = "Allow Nested KVM-HV",
+.index = SPAPR_CAP_NESTED_KVM_HV,
+.get = spapr_cap_get_bool,
+.set = spapr_cap_set_bool,
+.type = "bool",
+.apply = cap_nested_kvm_hv_apply,
+},
 };
 
 static sPAPRCapabilities default_caps_with_cpu(sPAPRMachineState *spapr,
@@ -564,6 +595,7 @@ SPAPR_CAP_MIG_STATE(dfp, SPAPR_CAP_DFP);
 SPAPR_CAP_MIG_STATE(cfpc, SPAPR_CAP_CFPC);
 SPAPR_CAP_MIG_STATE(sbbc, SPAPR_CAP_SBBC);
 SPAPR_CAP_MIG_STATE(ibs, SPAPR_CAP_IBS);
+SPAPR_CAP_MIG_STATE(nested_kvm_hv, SPAPR_CAP_NESTED_KVM_HV);
 
 void spapr_caps_init(sPAPRMachineState *spapr)
 {
diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
index ad4d7cfd97..bced85dd92 100644
--- a/include/hw/ppc/spapr.h
+++ b/include/hw/ppc/spapr.h
@@ -70,8 +70,10 @@ typedef enum {
 #define SPAPR_CAP_IBS   0x05
 /* HPT Maximum Page Size (encoded as a shift) */
 #define SPAPR_CAP_HPT_MAXPAGESIZE   0x06
+/* Nested KVM-HV */
+#define SPAPR_CAP_NESTED_KVM_HV 0x07
 /* Num Caps */
-#define SPAPR_CAP_NUM   (SPAPR_CAP_HPT_MAXPAGESIZE + 1)
+#define SPAPR_CAP_NUM   (SPAPR_CAP_NESTED_KVM_HV + 1)
 
 /*
  * Capability Values
@@ -793,6 +795,7 @@ extern const VMStateDescription vmstate_spapr_cap_dfp;
 extern const VMStateDescription vmstate_spapr_cap_cfpc;
 extern const VMStateDescription vmstate_spapr_cap_sbbc;
 extern const VMStateDescription vmstate_spapr_cap_ibs;
+extern const VMStateDescription vmstate_spapr_cap_nested_kvm_hv;
 
 static inline uint8_t spapr_get_cap(sPAPRMachineState *spapr, int cap)
 {
diff --git a/target/ppc/kvm.c b/target/ppc/kvm.c
index 30aeafa7de..8849180548 100644
--- a/target/ppc/kvm.c
+++ b/target/ppc/kvm.c
@@ -91,6 +91,7 @@ static int cap_ppc_pvr_compat;
 static int cap_ppc_safe_cache;
 static int cap_ppc_safe_bounds_check;
 static int cap_ppc_safe_indirect_branch;
+static int cap_ppc_nested_kvm_hv;
 
 static uint32_t debug_inst_opcode;
 
@@ -150,6 +151,7 @@ int kvm_arch_init(MachineState *ms, KVMState *s)
 cap_mmu_hash_v3 = kvm_vm_check_extension(s, KVM_CAP_PP

[Qemu-devel] [QEMU-PPC] [PATCH V2 1/3] target/ppc: Update linux-headers for v4.19-rc7

2018-10-07 Thread Suraj Jitindar Singh
Signed-off-by: Suraj Jitindar Singh 
---
 linux-headers/asm-powerpc/kvm.h | 1 +
 linux-headers/linux/kvm.h   | 1 +
 2 files changed, 2 insertions(+)

diff --git a/linux-headers/asm-powerpc/kvm.h b/linux-headers/asm-powerpc/kvm.h
index 1b32b56a03..8c876c166e 100644
--- a/linux-headers/asm-powerpc/kvm.h
+++ b/linux-headers/asm-powerpc/kvm.h
@@ -634,6 +634,7 @@ struct kvm_ppc_cpu_char {
 
 #define KVM_REG_PPC_DEC_EXPIRY (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xbe)
 #define KVM_REG_PPC_ONLINE (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xbf)
+#define KVM_REG_PPC_PTCR   (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xc0)
 
 /* Transactional Memory checkpointed state:
  * This is all GPRs, all VSX regs and a subset of SPRs
diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h
index 66790724f1..d49767ad25 100644
--- a/linux-headers/linux/kvm.h
+++ b/linux-headers/linux/kvm.h
@@ -951,6 +951,7 @@ struct kvm_ppc_resize_hpt {
 #define KVM_CAP_HYPERV_TLBFLUSH 155
 #define KVM_CAP_S390_HPAGE_1M 156
 #define KVM_CAP_NESTED_STATE 157
+#define KVM_CAP_PPC_NESTED_HV 160
 
 #ifdef KVM_CAP_IRQ_ROUTING
 
-- 
2.13.6




[Qemu-devel] [QEMU-PPC] [PATCH V2 0/3] ppc/spapr: Add support for nested kvm-hv

2018-10-07 Thread Suraj Jitindar Singh
This patch series adds the qemu support for running nested kvm-hv on a
POWER9 platform with appropriate hypervisor support and migration of
these guests.
That is, the ability to run kvm-hv guests as guests of an operating system
which is itself a kvm-hv guest.

The host (L0 hypervisor) and level 1 guest (L1 guest hypervisor) require
the following patch series:
KVM: PPC: Book3S HV: Nested HV virtualization

And this patch series in the qemu instance running on the L0 hypervisor.

Patch series based on: ppc-for-3.1

Still waiting for the cap number and one reg id to be confirmed in linux.

Changes RFC -> V2:
- Split header changes into separate patch
- Reword error messages when enabling nested-hv with kvm

Suraj Jitindar Singh (3):
  target/ppc: Update linux-headers for v4.19-rc7
  target/ppc: Add one reg id for ptcr
  ppc/spapr_caps: Add SPAPR_CAP_NESTED_KVM_HV

 hw/ppc/spapr.c  |  2 ++
 hw/ppc/spapr_caps.c | 32 
 include/hw/ppc/spapr.h  |  5 -
 linux-headers/asm-powerpc/kvm.h |  1 +
 linux-headers/linux/kvm.h   |  1 +
 target/ppc/kvm.c| 12 
 target/ppc/kvm_ppc.h| 12 
 target/ppc/translate_init.inc.c | 10 +-
 8 files changed, 69 insertions(+), 6 deletions(-)

-- 
2.13.6




[Qemu-devel] [QEMU-PPC] [PATCH V2 2/3] target/ppc: Add one reg id for ptcr

2018-10-07 Thread Suraj Jitindar Singh
The ptcr (partition table control register) is used to store the address
and size of the partition table. For nested kvm-hv we have a level 1
guest register the location of it's partition table with the hypervisor.
Thus to support migration we need to be able to read this out of kvm
and restore it post migration.

Add the one reg id for the ptcr.

Signed-off-by: Suraj Jitindar Singh 
---
 target/ppc/translate_init.inc.c | 10 +-
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/target/ppc/translate_init.inc.c b/target/ppc/translate_init.inc.c
index 263e63cb03..487196800b 100644
--- a/target/ppc/translate_init.inc.c
+++ b/target/ppc/translate_init.inc.c
@@ -8197,11 +8197,11 @@ static void gen_spr_power9_mmu(CPUPPCState *env)
 {
 #if !defined(CONFIG_USER_ONLY)
 /* Partition Table Control */
-spr_register_hv(env, SPR_PTCR, "PTCR",
-SPR_NOACCESS, SPR_NOACCESS,
-SPR_NOACCESS, SPR_NOACCESS,
-_read_generic, _write_ptcr,
-0x);
+spr_register_kvm_hv(env, SPR_PTCR, "PTCR",
+SPR_NOACCESS, SPR_NOACCESS,
+SPR_NOACCESS, SPR_NOACCESS,
+_read_generic, _write_ptcr,
+KVM_REG_PPC_PTCR, 0x);
 #endif
 }
 
-- 
2.13.6




[Qemu-devel] [QEMU-PPC] [PATCH V2 3/3] ppc/spapr_caps: Add SPAPR_CAP_NESTED_KVM_HV

2018-10-07 Thread Suraj Jitindar Singh
Add the spapr cap SPAPR_CAP_NESTED_KVM_HV to be used to control the
availability of nested kvm-hv to the level 1 (L1) guest.

Assuming a hypervisor with support enabled an L1 guest can be allowed to
use the kvm-hv module (and thus run it's own kvm-hv guests) by setting:
-machine pseries,cap-nested-hv=true
or disabled with:
-machine pseries,cap-nested-hv=false

Signed-off-by: Suraj Jitindar Singh 
---
 hw/ppc/spapr.c |  2 ++
 hw/ppc/spapr_caps.c| 32 
 include/hw/ppc/spapr.h |  5 -
 target/ppc/kvm.c   | 12 
 target/ppc/kvm_ppc.h   | 12 
 5 files changed, 62 insertions(+), 1 deletion(-)

diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index 98868d893a..8ce97900e9 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -1915,6 +1915,7 @@ static const VMStateDescription vmstate_spapr = {
 _spapr_cap_sbbc,
 _spapr_cap_ibs,
 _spapr_irq_map,
+_spapr_cap_nested_kvm_hv,
 NULL
 }
 };
@@ -3886,6 +3887,7 @@ static void spapr_machine_class_init(ObjectClass *oc, 
void *data)
 smc->default_caps.caps[SPAPR_CAP_SBBC] = SPAPR_CAP_BROKEN;
 smc->default_caps.caps[SPAPR_CAP_IBS] = SPAPR_CAP_BROKEN;
 smc->default_caps.caps[SPAPR_CAP_HPT_MAXPAGESIZE] = 16; /* 64kiB */
+smc->default_caps.caps[SPAPR_CAP_NESTED_KVM_HV] = SPAPR_CAP_OFF;
 spapr_caps_add_properties(smc, _abort);
 smc->irq = _irq_xics;
 }
diff --git a/hw/ppc/spapr_caps.c b/hw/ppc/spapr_caps.c
index aa605cea91..64f98ae68d 100644
--- a/hw/ppc/spapr_caps.c
+++ b/hw/ppc/spapr_caps.c
@@ -368,6 +368,28 @@ static void 
cap_hpt_maxpagesize_cpu_apply(sPAPRMachineState *spapr,
 ppc_hash64_filter_pagesizes(cpu, spapr_pagesize_cb, );
 }
 
+static void cap_nested_kvm_hv_apply(sPAPRMachineState *spapr,
+uint8_t val, Error **errp)
+{
+if (!val) {
+/* capability disabled by default */
+return;
+}
+
+if (tcg_enabled()) {
+error_setg(errp,
+   "No Nested KVM-HV support in tcg, try cap-nested-hv=off");
+} else if (kvm_enabled()) {
+if (!kvmppc_has_cap_nested_kvm_hv()) {
+error_setg(errp,
+"KVM implementation does not support Nested KVM-HV, try cap-nested-hv=off");
+} else if (kvmppc_set_cap_nested_kvm_hv(val) < 0) {
+error_setg(errp,
+"Error enabling cap-nested-hv with KVM, try cap-nested-hv=off");
+}
+}
+}
+
 sPAPRCapabilityInfo capability_table[SPAPR_CAP_NUM] = {
 [SPAPR_CAP_HTM] = {
 .name = "htm",
@@ -437,6 +459,15 @@ sPAPRCapabilityInfo capability_table[SPAPR_CAP_NUM] = {
 .apply = cap_hpt_maxpagesize_apply,
 .cpu_apply = cap_hpt_maxpagesize_cpu_apply,
 },
+[SPAPR_CAP_NESTED_KVM_HV] = {
+.name = "nested-hv",
+.description = "Allow Nested KVM-HV",
+.index = SPAPR_CAP_NESTED_KVM_HV,
+.get = spapr_cap_get_bool,
+.set = spapr_cap_set_bool,
+.type = "bool",
+.apply = cap_nested_kvm_hv_apply,
+},
 };
 
 static sPAPRCapabilities default_caps_with_cpu(sPAPRMachineState *spapr,
@@ -564,6 +595,7 @@ SPAPR_CAP_MIG_STATE(dfp, SPAPR_CAP_DFP);
 SPAPR_CAP_MIG_STATE(cfpc, SPAPR_CAP_CFPC);
 SPAPR_CAP_MIG_STATE(sbbc, SPAPR_CAP_SBBC);
 SPAPR_CAP_MIG_STATE(ibs, SPAPR_CAP_IBS);
+SPAPR_CAP_MIG_STATE(nested_kvm_hv, SPAPR_CAP_NESTED_KVM_HV);
 
 void spapr_caps_init(sPAPRMachineState *spapr)
 {
diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
index ad4d7cfd97..bced85dd92 100644
--- a/include/hw/ppc/spapr.h
+++ b/include/hw/ppc/spapr.h
@@ -70,8 +70,10 @@ typedef enum {
 #define SPAPR_CAP_IBS   0x05
 /* HPT Maximum Page Size (encoded as a shift) */
 #define SPAPR_CAP_HPT_MAXPAGESIZE   0x06
+/* Nested KVM-HV */
+#define SPAPR_CAP_NESTED_KVM_HV 0x07
 /* Num Caps */
-#define SPAPR_CAP_NUM   (SPAPR_CAP_HPT_MAXPAGESIZE + 1)
+#define SPAPR_CAP_NUM   (SPAPR_CAP_NESTED_KVM_HV + 1)
 
 /*
  * Capability Values
@@ -793,6 +795,7 @@ extern const VMStateDescription vmstate_spapr_cap_dfp;
 extern const VMStateDescription vmstate_spapr_cap_cfpc;
 extern const VMStateDescription vmstate_spapr_cap_sbbc;
 extern const VMStateDescription vmstate_spapr_cap_ibs;
+extern const VMStateDescription vmstate_spapr_cap_nested_kvm_hv;
 
 static inline uint8_t spapr_get_cap(sPAPRMachineState *spapr, int cap)
 {
diff --git a/target/ppc/kvm.c b/target/ppc/kvm.c
index 30aeafa7de..f81327d6cd 100644
--- a/target/ppc/kvm.c
+++ b/target/ppc/kvm.c
@@ -91,6 +91,7 @@ static int cap_ppc_pvr_compat;
 static int cap_ppc_safe_cache;
 static int cap_ppc_safe_bounds_check;
 static int cap_ppc_safe_indirect_branch;
+static int cap_ppc_nested_kvm_hv;
 
 static uint32_t debug_inst_opcode;
 
@@ -150,6 +151,7 @@ int kvm_arch_init(MachineState *ms, KVMState *s)
 cap_mmu_hash_v3 = kvm_vm_check_extension(s, KVM_CAP_PP

[Qemu-devel] [QEMU-PPC] [RFC 2/2] ppc/spapr_caps: Add SPAPR_CAP_NESTED_KVM_HV

2018-09-27 Thread Suraj Jitindar Singh
Add the spapr cap SPAPR_CAP_NESTED_KVM_HV to be used to control the
availability of nested kvm-hv to the level 1 (L1) guest.

Assuming a hypervisor with support enabled an L1 guest can be allowed to
use the kvm-hv module (and thus run it's own kvm-hv guests) by setting:
-machine pseries,cap-nested-hv=true
or disabled with:
-machine pseries,cap-netsed-hv=false

Signed-off-by: Suraj Jitindar Singh 
---
 hw/ppc/spapr.c|  2 ++
 hw/ppc/spapr_caps.c   | 29 +
 include/hw/ppc/spapr.h|  5 -
 linux-headers/linux/kvm.h |  1 +
 target/ppc/kvm.c  | 12 
 target/ppc/kvm_ppc.h  | 12 
 6 files changed, 60 insertions(+), 1 deletion(-)

diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index 98868d893a..8ce97900e9 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -1915,6 +1915,7 @@ static const VMStateDescription vmstate_spapr = {
 _spapr_cap_sbbc,
 _spapr_cap_ibs,
 _spapr_irq_map,
+_spapr_cap_nested_kvm_hv,
 NULL
 }
 };
@@ -3886,6 +3887,7 @@ static void spapr_machine_class_init(ObjectClass *oc, 
void *data)
 smc->default_caps.caps[SPAPR_CAP_SBBC] = SPAPR_CAP_BROKEN;
 smc->default_caps.caps[SPAPR_CAP_IBS] = SPAPR_CAP_BROKEN;
 smc->default_caps.caps[SPAPR_CAP_HPT_MAXPAGESIZE] = 16; /* 64kiB */
+smc->default_caps.caps[SPAPR_CAP_NESTED_KVM_HV] = SPAPR_CAP_OFF;
 spapr_caps_add_properties(smc, _abort);
 smc->irq = _irq_xics;
 }
diff --git a/hw/ppc/spapr_caps.c b/hw/ppc/spapr_caps.c
index aa605cea91..e0bdec76be 100644
--- a/hw/ppc/spapr_caps.c
+++ b/hw/ppc/spapr_caps.c
@@ -368,6 +368,25 @@ static void 
cap_hpt_maxpagesize_cpu_apply(sPAPRMachineState *spapr,
 ppc_hash64_filter_pagesizes(cpu, spapr_pagesize_cb, );
 }
 
+static void cap_nested_kvm_hv_apply(sPAPRMachineState *spapr,
+uint8_t val, Error **errp)
+{
+if (val && tcg_enabled()) {
+error_setg(errp,
+"No Nested KVM-HV support in tcg, try cap-nested-hv=off");
+} else if (kvm_enabled()) {
+if (kvmppc_has_cap_nested_kvm_hv()) {
+if (kvmppc_set_cap_nested_kvm_hv(val) < 0) {
+error_setg(errp,
+"KVM implementation does not support selected cap-nested-hv value");
+}
+} else if (val) {
+error_setg(errp,
+"KVM implementation does not support Nested KVM-HV, try cap-nested-hv=off");
+}
+}
+}
+
 sPAPRCapabilityInfo capability_table[SPAPR_CAP_NUM] = {
 [SPAPR_CAP_HTM] = {
 .name = "htm",
@@ -437,6 +456,15 @@ sPAPRCapabilityInfo capability_table[SPAPR_CAP_NUM] = {
 .apply = cap_hpt_maxpagesize_apply,
 .cpu_apply = cap_hpt_maxpagesize_cpu_apply,
 },
+[SPAPR_CAP_NESTED_KVM_HV] = {
+.name = "nested-hv",
+.description = "Allow Nested KVM-HV",
+.index = SPAPR_CAP_NESTED_KVM_HV,
+.get = spapr_cap_get_bool,
+.set = spapr_cap_set_bool,
+.type = "bool",
+.apply = cap_nested_kvm_hv_apply,
+},
 };
 
 static sPAPRCapabilities default_caps_with_cpu(sPAPRMachineState *spapr,
@@ -564,6 +592,7 @@ SPAPR_CAP_MIG_STATE(dfp, SPAPR_CAP_DFP);
 SPAPR_CAP_MIG_STATE(cfpc, SPAPR_CAP_CFPC);
 SPAPR_CAP_MIG_STATE(sbbc, SPAPR_CAP_SBBC);
 SPAPR_CAP_MIG_STATE(ibs, SPAPR_CAP_IBS);
+SPAPR_CAP_MIG_STATE(nested_kvm_hv, SPAPR_CAP_NESTED_KVM_HV);
 
 void spapr_caps_init(sPAPRMachineState *spapr)
 {
diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
index ad4d7cfd97..bced85dd92 100644
--- a/include/hw/ppc/spapr.h
+++ b/include/hw/ppc/spapr.h
@@ -70,8 +70,10 @@ typedef enum {
 #define SPAPR_CAP_IBS   0x05
 /* HPT Maximum Page Size (encoded as a shift) */
 #define SPAPR_CAP_HPT_MAXPAGESIZE   0x06
+/* Nested KVM-HV */
+#define SPAPR_CAP_NESTED_KVM_HV 0x07
 /* Num Caps */
-#define SPAPR_CAP_NUM   (SPAPR_CAP_HPT_MAXPAGESIZE + 1)
+#define SPAPR_CAP_NUM   (SPAPR_CAP_NESTED_KVM_HV + 1)
 
 /*
  * Capability Values
@@ -793,6 +795,7 @@ extern const VMStateDescription vmstate_spapr_cap_dfp;
 extern const VMStateDescription vmstate_spapr_cap_cfpc;
 extern const VMStateDescription vmstate_spapr_cap_sbbc;
 extern const VMStateDescription vmstate_spapr_cap_ibs;
+extern const VMStateDescription vmstate_spapr_cap_nested_kvm_hv;
 
 static inline uint8_t spapr_get_cap(sPAPRMachineState *spapr, int cap)
 {
diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h
index 66790724f1..d49767ad25 100644
--- a/linux-headers/linux/kvm.h
+++ b/linux-headers/linux/kvm.h
@@ -951,6 +951,7 @@ struct kvm_ppc_resize_hpt {
 #define KVM_CAP_HYPERV_TLBFLUSH 155
 #define KVM_CAP_S390_HPAGE_1M 156
 #define KVM_CAP_NESTED_STATE 157
+#define KVM_CAP_PPC_NESTED_HV 160
 
 #ifdef KVM_CAP_IRQ_ROUTING
 
diff --git a/target/ppc/kvm.c b/target/ppc/kvm.c
index 30aeafa7de..f81327d6cd 100644
--- a/target/ppc/kvm.c
+++ b/

[Qemu-devel] [QEMU-PPC] [RFC 0/2] ppc/spapr: Add support for nested kvm-hv

2018-09-27 Thread Suraj Jitindar Singh
This patch series adds the qemu support for running nested kvm-hv on a
POWER9 platform with appropriate hypervisor support and migration of
these guests.
That is, the ability to run kvm-hv guests as guests of an operating system
which is itself a kvm-hv guest.

The host (L0 hypervisor) and level 1 guest (L1 guest hypervisor) require
the following patch series:
[RFC PATCH 00/32] KVM: PPC: Book3S HV: Nested HV virtualization

And this patch series in the qemu instance running on the L0 hypervisor.

Patch series based on: ppc-for-3.1

RFC because waiting for the CAP number to be in upstream linux

Suraj Jitindar Singh (2):
  target/ppc: Add one reg id for ptcr
  ppc/spapr_caps: Add SPAPR_CAP_NESTED_KVM_HV

 hw/ppc/spapr.c  |  2 ++
 hw/ppc/spapr_caps.c | 29 +
 include/hw/ppc/spapr.h  |  5 -
 linux-headers/asm-powerpc/kvm.h |  1 +
 linux-headers/linux/kvm.h   |  1 +
 target/ppc/kvm.c| 12 
 target/ppc/kvm_ppc.h| 12 
 target/ppc/translate_init.inc.c | 10 +-
 8 files changed, 66 insertions(+), 6 deletions(-)

-- 
2.13.6




[Qemu-devel] [QEMU-PPC] [RFC 1/2] target/ppc: Add one reg id for ptcr

2018-09-27 Thread Suraj Jitindar Singh
The ptcr (partition table control register) is used to store the address
and size of the partition table. For nested kvm-hv we have a level 1
guest register the location of it's partition table with the hypervisor.
Thus to support migration we need to be able to read this out of kvm
and restore it post migration.

Add the one reg id for the ptcr.

Signed-off-by: Suraj Jitindar Singh 
---
 linux-headers/asm-powerpc/kvm.h |  1 +
 target/ppc/translate_init.inc.c | 10 +-
 2 files changed, 6 insertions(+), 5 deletions(-)

diff --git a/linux-headers/asm-powerpc/kvm.h b/linux-headers/asm-powerpc/kvm.h
index 1b32b56a03..8c876c166e 100644
--- a/linux-headers/asm-powerpc/kvm.h
+++ b/linux-headers/asm-powerpc/kvm.h
@@ -634,6 +634,7 @@ struct kvm_ppc_cpu_char {
 
 #define KVM_REG_PPC_DEC_EXPIRY (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xbe)
 #define KVM_REG_PPC_ONLINE (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xbf)
+#define KVM_REG_PPC_PTCR   (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xc0)
 
 /* Transactional Memory checkpointed state:
  * This is all GPRs, all VSX regs and a subset of SPRs
diff --git a/target/ppc/translate_init.inc.c b/target/ppc/translate_init.inc.c
index 263e63cb03..487196800b 100644
--- a/target/ppc/translate_init.inc.c
+++ b/target/ppc/translate_init.inc.c
@@ -8197,11 +8197,11 @@ static void gen_spr_power9_mmu(CPUPPCState *env)
 {
 #if !defined(CONFIG_USER_ONLY)
 /* Partition Table Control */
-spr_register_hv(env, SPR_PTCR, "PTCR",
-SPR_NOACCESS, SPR_NOACCESS,
-SPR_NOACCESS, SPR_NOACCESS,
-_read_generic, _write_ptcr,
-0x);
+spr_register_kvm_hv(env, SPR_PTCR, "PTCR",
+SPR_NOACCESS, SPR_NOACCESS,
+SPR_NOACCESS, SPR_NOACCESS,
+_read_generic, _write_ptcr,
+KVM_REG_PPC_PTCR, 0x);
 #endif
 }
 
-- 
2.13.6




Re: [Qemu-devel] [QEMU-PPC] [PATCH] ppc/tcg: Ignore bit 6 in the eieio instruction

2018-07-01 Thread Suraj Jitindar Singh
On Fri, 2018-06-29 at 16:29 +1000, David Gibson wrote:
> On Fri, Jun 29, 2018 at 04:20:24PM +1000, Suraj Jitindar Singh wrote:
> > The kernel patch
> > "powerpc/64s: Add support for a store forwarding barrier at kernel
> > entry/exit"
> > adds an eieio barrier instruction to kernel entry and exit points
> > on
> > the POWER9 platform. The eieio instruction form used has bit 6 set.
> > This bit is ignored by hardware however under tcg it causes an
> > illegal
> > instruction.
> > 
> > To allow these kernels to run under tcg, modify the eieio
> > instruction
> > to ignore bit 6.
> > 
> > Signed-off-by: Suraj Jitindar Singh 
> 
> Already done by commit c8fd8373 "target/ppc: extend eieio for
> POWER9".

I obviously missed that :)

> 
> > ---
> >  target/ppc/translate.c | 2 +-
> >  1 file changed, 1 insertion(+), 1 deletion(-)
> > 
> > diff --git a/target/ppc/translate.c b/target/ppc/translate.c
> > index 3457d29f8e..b1ad1e2a22 100644
> > --- a/target/ppc/translate.c
> > +++ b/target/ppc/translate.c
> > @@ -6496,7 +6496,7 @@ GEN_HANDLER(lswi, 0x1F, 0x15, 0x12,
> > 0x0001, PPC_STRING),
> >  GEN_HANDLER(lswx, 0x1F, 0x15, 0x10, 0x0001, PPC_STRING),
> >  GEN_HANDLER(stswi, 0x1F, 0x15, 0x16, 0x0001, PPC_STRING),
> >  GEN_HANDLER(stswx, 0x1F, 0x15, 0x14, 0x0001, PPC_STRING),
> > -GEN_HANDLER(eieio, 0x1F, 0x16, 0x1A, 0x03FFF801, PPC_MEM_EIEIO),
> > +GEN_HANDLER(eieio, 0x1F, 0x16, 0x1A, 0x01FFF801, PPC_MEM_EIEIO),
> >  GEN_HANDLER(isync, 0x13, 0x16, 0x04, 0x03FFF801, PPC_MEM),
> >  GEN_HANDLER_E(lbarx, 0x1F, 0x14, 0x01, 0, PPC_NONE,
> > PPC2_ATOMIC_ISA206),
> >  GEN_HANDLER_E(lharx, 0x1F, 0x14, 0x03, 0, PPC_NONE,
> > PPC2_ATOMIC_ISA206),
> 
> 



[Qemu-devel] [QEMU-PPC] [PATCH] ppc/tcg: Ignore bit 6 in the eieio instruction

2018-06-29 Thread Suraj Jitindar Singh
The kernel patch
"powerpc/64s: Add support for a store forwarding barrier at kernel entry/exit"
adds an eieio barrier instruction to kernel entry and exit points on
the POWER9 platform. The eieio instruction form used has bit 6 set.
This bit is ignored by hardware however under tcg it causes an illegal
instruction.

To allow these kernels to run under tcg, modify the eieio instruction
to ignore bit 6.

Signed-off-by: Suraj Jitindar Singh 
---
 target/ppc/translate.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/target/ppc/translate.c b/target/ppc/translate.c
index 3457d29f8e..b1ad1e2a22 100644
--- a/target/ppc/translate.c
+++ b/target/ppc/translate.c
@@ -6496,7 +6496,7 @@ GEN_HANDLER(lswi, 0x1F, 0x15, 0x12, 0x0001, 
PPC_STRING),
 GEN_HANDLER(lswx, 0x1F, 0x15, 0x10, 0x0001, PPC_STRING),
 GEN_HANDLER(stswi, 0x1F, 0x15, 0x16, 0x0001, PPC_STRING),
 GEN_HANDLER(stswx, 0x1F, 0x15, 0x14, 0x0001, PPC_STRING),
-GEN_HANDLER(eieio, 0x1F, 0x16, 0x1A, 0x03FFF801, PPC_MEM_EIEIO),
+GEN_HANDLER(eieio, 0x1F, 0x16, 0x1A, 0x01FFF801, PPC_MEM_EIEIO),
 GEN_HANDLER(isync, 0x13, 0x16, 0x04, 0x03FFF801, PPC_MEM),
 GEN_HANDLER_E(lbarx, 0x1F, 0x14, 0x01, 0, PPC_NONE, PPC2_ATOMIC_ISA206),
 GEN_HANDLER_E(lharx, 0x1F, 0x14, 0x03, 0, PPC_NONE, PPC2_ATOMIC_ISA206),
-- 
2.13.6




Re: [Qemu-devel] [PATCH] hmp-commands: use long for begin and length in dump-guest-memory

2018-06-19 Thread Suraj Jitindar Singh
On Tue, 2018-06-19 at 11:25 +0100, Dr. David Alan Gilbert wrote:
> * Suraj Jitindar Singh (sjitindarsi...@gmail.com) wrote:
> > The dump-guest-memory command is used to dump an area of guest
> > memory
> > to a file, the piece of memory is specified by a begin address and
> > a length. These parameters are specified as ints and thus have a
> > maximum
> > value of 4GB. This means you can't dump the guest memory past the
> > first
> > 4GB and instead get:
> > (qemu) dump-guest-memory tmp 0x1 0x1
> > 'dump-guest-memory' has failed: integer is for 32-bit values
> > Try "help dump-guest-memory" for more information
> > 
> > This limitation is imposed in monitor_parse_arguments() since they
> > are
> > both ints. hmp_dump_guest_memory() uses 64 bit quantities to store
> > both
> > the begin and length values. Thus specify begin and length as long
> > so
> > that the entire guest memory space can be dumped.
> > 
> > Signed-off-by: Suraj Jitindar Singh 
> > ---
> >  hmp-commands.hx | 2 +-
> >  1 file changed, 1 insertion(+), 1 deletion(-)
> > 
> > diff --git a/hmp-commands.hx b/hmp-commands.hx
> > index 0734fea931..3b5c1f65db 100644
> > --- a/hmp-commands.hx
> > +++ b/hmp-commands.hx
> > @@ -1116,7 +1116,7 @@ ETEXI
> >  
> >  {
> >  .name   = "dump-guest-memory",
> > -.args_type  = "paging:-p,detach:-d,zlib:-z,lzo:-l,snappy:-
> > s,filename:F,begin:i?,length:i?",
> > +.args_type  = "paging:-p,detach:-d,zlib:-z,lzo:-l,snappy:-
> > s,filename:F,begin:l?,length:l?",
> >  .params = "[-p] [-d] [-z|-l|-s] filename [begin
> > length]",
> >  .help   = "dump guest memory into file
> > 'filename'.\n\t\t\t"
> >"-p: do paging to get guest's memory
> > mapping.\n\t\t\t"
> 
> OK, so hmp_dump_guest_memory in hmp.c already uses int64_t for both,
> as does the qmp_dump_guest_memory it calls; so this looks OK.
> 
> Can you repost this please with the correct sign off that I see you
> tried to fix in the following mail; best if we get it in the one
> mail.

Of course. Done :)

> 
> Dave
> 
> > -- 
> > 2.13.6
> > 
> 
> --
> Dr. David Alan Gilbert / dgilb...@redhat.com / Manchester, UK



[Qemu-devel] [PATCH] [RESEND] hmp-commands: use long for begin and length in dump-guest-memory

2018-06-19 Thread Suraj Jitindar Singh
The dump-guest-memory command is used to dump an area of guest memory
to a file, the piece of memory is specified by a begin address and
a length. These parameters are specified as ints and thus have a maximum
value of 4GB. This means you can't dump the guest memory past the first
4GB and instead get:
(qemu) dump-guest-memory tmp 0x1 0x1
'dump-guest-memory' has failed: integer is for 32-bit values
Try "help dump-guest-memory" for more information

This limitation is imposed in monitor_parse_arguments() since they are
both ints. hmp_dump_guest_memory() uses 64 bit quantities to store both
the begin and length values. Thus specify begin and length as long so
that the entire guest memory space can be dumped.

Signed-off-by: Suraj Jitindar Singh 
---
 hmp-commands.hx | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hmp-commands.hx b/hmp-commands.hx
index 0734fea931..3b5c1f65db 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -1116,7 +1116,7 @@ ETEXI
 
 {
 .name   = "dump-guest-memory",
-.args_type  = 
"paging:-p,detach:-d,zlib:-z,lzo:-l,snappy:-s,filename:F,begin:i?,length:i?",
+.args_type  = 
"paging:-p,detach:-d,zlib:-z,lzo:-l,snappy:-s,filename:F,begin:l?,length:l?",
 .params = "[-p] [-d] [-z|-l|-s] filename [begin length]",
 .help   = "dump guest memory into file 'filename'.\n\t\t\t"
   "-p: do paging to get guest's memory mapping.\n\t\t\t"
-- 
2.13.6




Re: [Qemu-devel] [PATCH] hmp-commands: use long for begin and length in dump-guest-memory

2018-06-18 Thread Suraj Jitindar Singh
On Tue, 2018-06-19 at 14:48 +1000, Suraj Jitindar Singh wrote:
> The dump-guest-memory command is used to dump an area of guest memory
> to a file, the piece of memory is specified by a begin address and
> a length. These parameters are specified as ints and thus have a
> maximum
> value of 4GB. This means you can't dump the guest memory past the
> first
> 4GB and instead get:
> (qemu) dump-guest-memory tmp 0x1 0x1
> 'dump-guest-memory' has failed: integer is for 32-bit values
> Try "help dump-guest-memory" for more information
> 
> This limitation is imposed in monitor_parse_arguments() since they
> are
> both ints. hmp_dump_guest_memory() uses 64 bit quantities to store
> both
> the begin and length values. Thus specify begin and length as long so
> that the entire guest memory space can be dumped.
> 
> Signed-off-by: Suraj Jitindar Singh 
s/sjtindarsi...@gmail.com/sjitindarsi...@gmail.com

woops...
> ---
>  hmp-commands.hx | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/hmp-commands.hx b/hmp-commands.hx
> index 0734fea931..3b5c1f65db 100644
> --- a/hmp-commands.hx
> +++ b/hmp-commands.hx
> @@ -1116,7 +1116,7 @@ ETEXI
>  
>  {
>  .name   = "dump-guest-memory",
> -.args_type  = "paging:-p,detach:-d,zlib:-z,lzo:-l,snappy:-
> s,filename:F,begin:i?,length:i?",
> +.args_type  = "paging:-p,detach:-d,zlib:-z,lzo:-l,snappy:-
> s,filename:F,begin:l?,length:l?",
>  .params = "[-p] [-d] [-z|-l|-s] filename [begin
> length]",
>  .help   = "dump guest memory into file
> 'filename'.\n\t\t\t"
>"-p: do paging to get guest's memory
> mapping.\n\t\t\t"



[Qemu-devel] [PATCH] hmp-commands: use long for begin and length in dump-guest-memory

2018-06-18 Thread Suraj Jitindar Singh
The dump-guest-memory command is used to dump an area of guest memory
to a file, the piece of memory is specified by a begin address and
a length. These parameters are specified as ints and thus have a maximum
value of 4GB. This means you can't dump the guest memory past the first
4GB and instead get:
(qemu) dump-guest-memory tmp 0x1 0x1
'dump-guest-memory' has failed: integer is for 32-bit values
Try "help dump-guest-memory" for more information

This limitation is imposed in monitor_parse_arguments() since they are
both ints. hmp_dump_guest_memory() uses 64 bit quantities to store both
the begin and length values. Thus specify begin and length as long so
that the entire guest memory space can be dumped.

Signed-off-by: Suraj Jitindar Singh 
---
 hmp-commands.hx | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hmp-commands.hx b/hmp-commands.hx
index 0734fea931..3b5c1f65db 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -1116,7 +1116,7 @@ ETEXI
 
 {
 .name   = "dump-guest-memory",
-.args_type  = 
"paging:-p,detach:-d,zlib:-z,lzo:-l,snappy:-s,filename:F,begin:i?,length:i?",
+.args_type  = 
"paging:-p,detach:-d,zlib:-z,lzo:-l,snappy:-s,filename:F,begin:l?,length:l?",
 .params = "[-p] [-d] [-z|-l|-s] filename [begin length]",
 .help   = "dump guest memory into file 'filename'.\n\t\t\t"
   "-p: do paging to get guest's memory mapping.\n\t\t\t"
-- 
2.13.6




[Qemu-devel] [QEMU-PPC] [PATCH V2 2/2] ppc/spapr_caps: Don't disable cap_cfpc on POWER8 by default

2018-06-11 Thread Suraj Jitindar Singh
In default_caps_with_cpu() we set spapr_cap_cfpc to broken for POWER8
processors and before.

Since we no longer require private l1d cache on POWER8 for this cap to
be set to workaround change this to default to broken for POWER7
processors and before.

Signed-off-by: Suraj Jitindar Singh 
Reviewed-by: David Gibson 

---

V1 -> V2:
- No Change

---
 hw/ppc/spapr_caps.c | 6 +-
 1 file changed, 1 insertion(+), 5 deletions(-)

diff --git a/hw/ppc/spapr_caps.c b/hw/ppc/spapr_caps.c
index 531e145114..00e43a9ba7 100644
--- a/hw/ppc/spapr_caps.c
+++ b/hw/ppc/spapr_caps.c
@@ -335,14 +335,10 @@ static sPAPRCapabilities 
default_caps_with_cpu(sPAPRMachineState *spapr,
 
 caps = smc->default_caps;
 
-if (!ppc_check_compat(cpu, CPU_POWERPC_LOGICAL_3_00,
-  0, spapr->max_compat_pvr)) {
-caps.caps[SPAPR_CAP_CFPC] = SPAPR_CAP_BROKEN;
-}
-
 if (!ppc_check_compat(cpu, CPU_POWERPC_LOGICAL_2_07,
   0, spapr->max_compat_pvr)) {
 caps.caps[SPAPR_CAP_HTM] = SPAPR_CAP_OFF;
+caps.caps[SPAPR_CAP_CFPC] = SPAPR_CAP_BROKEN;
 }
 
 if (!ppc_check_compat(cpu, CPU_POWERPC_LOGICAL_2_06_PLUS,
-- 
2.13.6




[Qemu-devel] [QEMU-PPC] [PATCH V2 1/2] target/ppc: Don't require private l1d cache on POWER8 for cap_ppc_safe_cache

2018-06-11 Thread Suraj Jitindar Singh
For cap_ppc_safe_cache to be set to workaround, we require both a l1d
cache flush instruction and private l1d cache.

On POWER8 don't require private l1d cache. This means a guest on a
POWER8 machine can make use of the cache flush workarounds.

Signed-off-by: Suraj Jitindar Singh 

---

V1 -> V2:
- Use mfpvr() to detect host type

---
 target/ppc/kvm.c | 19 ++-
 1 file changed, 18 insertions(+), 1 deletion(-)

diff --git a/target/ppc/kvm.c b/target/ppc/kvm.c
index 2c0c34e125..7fe9d0126b 100644
--- a/target/ppc/kvm.c
+++ b/target/ppc/kvm.c
@@ -2412,11 +2412,28 @@ bool kvmppc_has_cap_mmu_hash_v3(void)
 return cap_mmu_hash_v3;
 }
 
+static bool kvmppc_power8_host(void)
+{
+bool ret = false;
+#ifdef TARGET_PPC64
+{
+uint32_t base_pvr = CPU_POWERPC_POWER_SERVER_MASK & mfpvr();
+ret = (base_pvr == CPU_POWERPC_POWER8E_BASE) ||
+  (base_pvr == CPU_POWERPC_POWER8NVL_BASE) ||
+  (base_pvr == CPU_POWERPC_POWER8_BASE);
+}
+#endif /* TARGET_PPC64 */
+return ret;
+}
+
 static int parse_cap_ppc_safe_cache(struct kvm_ppc_cpu_char c)
 {
+bool l1d_thread_priv_req = !kvmppc_power8_host();
+
 if (~c.behaviour & c.behaviour_mask & H_CPU_BEHAV_L1D_FLUSH_PR) {
 return 2;
-} else if ((c.character & c.character_mask & H_CPU_CHAR_L1D_THREAD_PRIV) &&
+} else if ((!l1d_thread_priv_req ||
+c.character & c.character_mask & H_CPU_CHAR_L1D_THREAD_PRIV) &&
(c.character & c.character_mask
 & (H_CPU_CHAR_L1D_FLUSH_ORI30 | H_CPU_CHAR_L1D_FLUSH_TRIG2))) {
 return 1;
-- 
2.13.6




Re: [Qemu-devel] [Qemu-ppc] [PATCH] target/ppc: fix tlbsync to check privilege level depending on GTSE

2018-03-14 Thread Suraj Jitindar Singh
On Wed, 2018-03-14 at 18:33 +0100, Cédric Le Goater wrote:
> tlbsync also needs to check the Guest Translation Shootdown Enable
> (GTSE) bit in the Logical Partition Control Register (LPCR) to
> determine at which privilege level it is running.
> 
> See commit c6fd28fd573d ("target/ppc: Update tlbie to check privilege
> level based on GTSE")
> 
> Signed-off-by: Cédric Le Goater <c...@kaod.org>

Reviewed-by: Suraj Jitindar Singh <sjitindarsi...@gmail.com>

> ---
> 
>  This will have its importance when we activate the HV bit on the
>  POWER9 CPU for the PowerNV machine.
> 
>  target/ppc/translate.c | 9 +++--
>  1 file changed, 7 insertions(+), 2 deletions(-)
> 
> diff --git a/target/ppc/translate.c b/target/ppc/translate.c
> index 0a0c090c9978..218665b4080b 100644
> --- a/target/ppc/translate.c
> +++ b/target/ppc/translate.c
> @@ -4526,7 +4526,7 @@ static void gen_tlbie(DisasContext *ctx)
>  TCGv_i32 t1;
>  
>  if (ctx->gtse) {
> -CHK_SV; /* If gtse is set then tblie is supervisor
> privileged */
> +CHK_SV; /* If gtse is set then tlbie is supervisor
> privileged */

^^^ Did that line actually change? :)

>  } else {
>  CHK_HV; /* Else hypervisor privileged */
>  }
> @@ -4553,7 +4553,12 @@ static void gen_tlbsync(DisasContext *ctx)
>  #if defined(CONFIG_USER_ONLY)
>  GEN_PRIV;
>  #else
> -CHK_HV;
> +
> +if (ctx->gtse) {
> +CHK_SV; /* If gtse is set then tlbsync is supervisor
> privileged */
> +} else {
> +CHK_HV; /* Else hypervisor privileged */
> +}
>  
>  /* BookS does both ptesync and tlbsync make tlbsync a nop for
> server */
>  if (ctx->insns_flags & PPC_BOOKE) {



[Qemu-devel] [QEMU-PPC] [PATCH V4 2/2] ppc/spapr-caps: For pseries-2.12 change spapr-cap defaults

2018-02-15 Thread Suraj Jitindar Singh
For the pseries-2.12 machine type, make the spapr-caps SPAPR_CAP_CFPC
and SPAPR_CAP_SBBC default to workaround. Thus if the host is capable
the guest will be able to take advantage of these workarounds by default.
Otherwise if the host doesn't have these capabilities qemu will fail to
start and they will have to be explicitly disabled on the command line
with:
-machine pseries,cap-cfpc=broken,cap-sbbc=broken

Signed-off-by: Suraj Jitindar Singh <sjitindarsi...@gmail.com>

---

V2 -> V3:
 - Set caps to workaround in the class default rather than the
   pseries-2.12 initialiser.
---
 hw/ppc/spapr.c  |  6 --
 hw/ppc/spapr_caps.c | 10 ++
 2 files changed, 14 insertions(+), 2 deletions(-)

diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index 83c9d66dd5..69f59aabf1 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -3915,8 +3915,8 @@ static void spapr_machine_class_init(ObjectClass *oc, 
void *data)
 smc->default_caps.caps[SPAPR_CAP_HTM] = SPAPR_CAP_OFF;
 smc->default_caps.caps[SPAPR_CAP_VSX] = SPAPR_CAP_ON;
 smc->default_caps.caps[SPAPR_CAP_DFP] = SPAPR_CAP_ON;
-smc->default_caps.caps[SPAPR_CAP_CFPC] = SPAPR_CAP_BROKEN;
-smc->default_caps.caps[SPAPR_CAP_SBBC] = SPAPR_CAP_BROKEN;
+smc->default_caps.caps[SPAPR_CAP_CFPC] = SPAPR_CAP_WORKAROUND;
+smc->default_caps.caps[SPAPR_CAP_SBBC] = SPAPR_CAP_WORKAROUND;
 smc->default_caps.caps[SPAPR_CAP_IBS] = SPAPR_CAP_BROKEN;
 spapr_caps_add_properties(smc, _abort);
 }
@@ -4000,6 +4000,8 @@ static void spapr_machine_2_11_class_options(MachineClass 
*mc)
 
 spapr_machine_2_12_class_options(mc);
 smc->default_caps.caps[SPAPR_CAP_HTM] = SPAPR_CAP_ON;
+smc->default_caps.caps[SPAPR_CAP_CFPC] = SPAPR_CAP_BROKEN;
+smc->default_caps.caps[SPAPR_CAP_SBBC] = SPAPR_CAP_BROKEN;
 SET_MACHINE_COMPAT(mc, SPAPR_COMPAT_2_11);
 }
 
diff --git a/hw/ppc/spapr_caps.c b/hw/ppc/spapr_caps.c
index 99a4b71d19..7b0ecb3eca 100644
--- a/hw/ppc/spapr_caps.c
+++ b/hw/ppc/spapr_caps.c
@@ -283,11 +283,21 @@ static sPAPRCapabilities 
default_caps_with_cpu(sPAPRMachineState *spapr,
 
 caps = smc->default_caps;
 
+if (!ppc_check_compat(cpu, CPU_POWERPC_LOGICAL_3_00,
+  0, spapr->max_compat_pvr)) {
+caps.caps[SPAPR_CAP_CFPC] = SPAPR_CAP_BROKEN;
+}
+
 if (!ppc_check_compat(cpu, CPU_POWERPC_LOGICAL_2_07,
   0, spapr->max_compat_pvr)) {
 caps.caps[SPAPR_CAP_HTM] = SPAPR_CAP_OFF;
 }
 
+if (!ppc_check_compat(cpu, CPU_POWERPC_LOGICAL_2_06_PLUS,
+  0, spapr->max_compat_pvr)) {
+caps.caps[SPAPR_CAP_SBBC] = SPAPR_CAP_BROKEN;
+}
+
 if (!ppc_check_compat(cpu, CPU_POWERPC_LOGICAL_2_06,
   0, spapr->max_compat_pvr)) {
 caps.caps[SPAPR_CAP_VSX] = SPAPR_CAP_OFF;
-- 
2.13.6




[Qemu-devel] [QEMU-PPC] [PATCH V4 1/2] ppc/spapr-caps: Disallow setting workaround for spapr-cap-ibs

2018-02-15 Thread Suraj Jitindar Singh
The spapr-cap cap-ibs can only have values broken or fixed as there is
no explicit workaround required. Currently setting the value workaround
for this cap will hit an assert if the guest makes the hcall
h_get_cpu_characteristics.

Report an error when attempting to apply the setting with a more helpful
error message.

Reported-by: Satheesh Rajendran <sathn...@linux.vnet.ibm.com>
Signed-off-by: Suraj Jitindar Singh <sjitindarsi...@gmail.com>

---

V3 -> V4:
 - Add this patch back from V1 to replace
   "ppc/spapr-caps: Convert spapr-cap-ibs to be a boolean"
   as this was deemed to be a better solution
---
 hw/ppc/spapr_caps.c | 6 --
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/hw/ppc/spapr_caps.c b/hw/ppc/spapr_caps.c
index e69d308560..99a4b71d19 100644
--- a/hw/ppc/spapr_caps.c
+++ b/hw/ppc/spapr_caps.c
@@ -205,7 +205,9 @@ static void cap_safe_bounds_check_apply(sPAPRMachineState 
*spapr, uint8_t val,
 static void cap_safe_indirect_branch_apply(sPAPRMachineState *spapr,
uint8_t val, Error **errp)
 {
-if (tcg_enabled() && val) {
+if (val == SPAPR_CAP_WORKAROUND) { /* Can only be Broken or Fixed */
+error_setg(errp, "Requested safe indirect branch capability level 
\"workaround\" not valid, try cap-ibs=fixed");
+} else if (tcg_enabled() && val) {
 /* TODO - for now only allow broken for TCG */
 error_setg(errp, "Requested safe indirect branch capability level not 
supported by tcg, try a different value for cap-ibs");
 } else if (kvm_enabled() && (val > kvmppc_get_cap_safe_indirect_branch())) 
{
@@ -263,7 +265,7 @@ sPAPRCapabilityInfo capability_table[SPAPR_CAP_NUM] = {
 },
 [SPAPR_CAP_IBS] = {
 .name = "ibs",
-.description = "Indirect Branch Serialisation" VALUE_DESC_TRISTATE,
+.description = "Indirect Branch Serialisation (broken, fixed)",
 .index = SPAPR_CAP_IBS,
 .get = spapr_cap_get_tristate,
 .set = spapr_cap_set_tristate,
-- 
2.13.6




[Qemu-devel] [QEMU-PPC] [PATCH V3 3/3] ppc/spapr-caps: For pseries-2.12 change spapr-cap defaults

2018-02-14 Thread Suraj Jitindar Singh
For the pseries-2.12 machine type, make the spapr-caps SPAPR_CAP_CFPC
and SPAPR_CAP_SBBC default to workaround. Thus if the host is capable
the guest will be able to take advantage of these workarounds by default.
Otherwise if the host doesn't have these capabilities qemu will fail to
start and they will have to be explicitly disabled on the command line
with:
-machine pseries,cap-cfpc=broken,cap-sbbc=broken

Signed-off-by: Suraj Jitindar Singh <sjitindarsi...@gmail.com>

---

V2 -> V3:
 - Set caps to workaround in the class default rather than the
   pseries-2.12 initialiser.
---
 hw/ppc/spapr.c  |  6 --
 hw/ppc/spapr_caps.c | 10 ++
 2 files changed, 14 insertions(+), 2 deletions(-)

diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index 969db6cde2..4fe2c3b90c 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -3884,8 +3884,8 @@ static void spapr_machine_class_init(ObjectClass *oc, 
void *data)
 smc->default_caps.caps[SPAPR_CAP_HTM] = SPAPR_CAP_OFF;
 smc->default_caps.caps[SPAPR_CAP_VSX] = SPAPR_CAP_ON;
 smc->default_caps.caps[SPAPR_CAP_DFP] = SPAPR_CAP_ON;
-smc->default_caps.caps[SPAPR_CAP_CFPC] = SPAPR_CAP_BROKEN;
-smc->default_caps.caps[SPAPR_CAP_SBBC] = SPAPR_CAP_BROKEN;
+smc->default_caps.caps[SPAPR_CAP_CFPC] = SPAPR_CAP_WORKAROUND;
+smc->default_caps.caps[SPAPR_CAP_SBBC] = SPAPR_CAP_WORKAROUND;
 smc->default_caps.caps[SPAPR_CAP_IBS] = SPAPR_CAP_OFF;
 spapr_caps_add_properties(smc, _abort);
 }
@@ -3969,6 +3969,8 @@ static void spapr_machine_2_11_class_options(MachineClass 
*mc)
 
 spapr_machine_2_12_class_options(mc);
 smc->default_caps.caps[SPAPR_CAP_HTM] = SPAPR_CAP_ON;
+smc->default_caps.caps[SPAPR_CAP_CFPC] = SPAPR_CAP_BROKEN;
+smc->default_caps.caps[SPAPR_CAP_SBBC] = SPAPR_CAP_BROKEN;
 SET_MACHINE_COMPAT(mc, SPAPR_COMPAT_2_11);
 }
 
diff --git a/hw/ppc/spapr_caps.c b/hw/ppc/spapr_caps.c
index 05997b0842..c25c2bca52 100644
--- a/hw/ppc/spapr_caps.c
+++ b/hw/ppc/spapr_caps.c
@@ -281,11 +281,21 @@ static sPAPRCapabilities 
default_caps_with_cpu(sPAPRMachineState *spapr,
 
 caps = smc->default_caps;
 
+if (!ppc_check_compat(cpu, CPU_POWERPC_LOGICAL_3_00,
+  0, spapr->max_compat_pvr)) {
+caps.caps[SPAPR_CAP_CFPC] = SPAPR_CAP_BROKEN;
+}
+
 if (!ppc_check_compat(cpu, CPU_POWERPC_LOGICAL_2_07,
   0, spapr->max_compat_pvr)) {
 caps.caps[SPAPR_CAP_HTM] = SPAPR_CAP_OFF;
 }
 
+if (!ppc_check_compat(cpu, CPU_POWERPC_LOGICAL_2_06_PLUS,
+  0, spapr->max_compat_pvr)) {
+caps.caps[SPAPR_CAP_SBBC] = SPAPR_CAP_BROKEN;
+}
+
 if (!ppc_check_compat(cpu, CPU_POWERPC_LOGICAL_2_06,
   0, spapr->max_compat_pvr)) {
 caps.caps[SPAPR_CAP_VSX] = SPAPR_CAP_OFF;
-- 
2.13.6




[Qemu-devel] [QEMU-PPC] [PATCH V3 1/3] ppc/spapr-caps: Change migration macro to take full spapr-cap name

2018-02-14 Thread Suraj Jitindar Singh
Change the macro that generates the vmstate migration field and the needed
function for the spapr-caps to take the full spapr-cap name. This has
the benefit of meaning this instance will be picked up when greping
for the spapr-caps and making it more obvious what this macro is doing.

Signed-off-by: Suraj Jitindar Singh <sjitindarsi...@gmail.com>
---
 hw/ppc/spapr_caps.c | 30 +++---
 1 file changed, 15 insertions(+), 15 deletions(-)

diff --git a/hw/ppc/spapr_caps.c b/hw/ppc/spapr_caps.c
index 62efdaee38..e69d308560 100644
--- a/hw/ppc/spapr_caps.c
+++ b/hw/ppc/spapr_caps.c
@@ -350,34 +350,34 @@ int spapr_caps_post_migration(sPAPRMachineState *spapr)
 }
 
 /* Used to generate the migration field and needed function for a spapr cap */
-#define SPAPR_CAP_MIG_STATE(cap, ccap)  \
-static bool spapr_cap_##cap##_needed(void *opaque)  \
+#define SPAPR_CAP_MIG_STATE(sname, cap) \
+static bool spapr_cap_##sname##_needed(void *opaque)\
 {   \
 sPAPRMachineState *spapr = opaque;  \
 \
-return spapr->cmd_line_caps[SPAPR_CAP_##ccap] &&\
-   (spapr->eff.caps[SPAPR_CAP_##ccap] !=\
-spapr->def.caps[SPAPR_CAP_##ccap]); \
+return spapr->cmd_line_caps[cap] && \
+   (spapr->eff.caps[cap] != \
+spapr->def.caps[cap]);  \
 }   \
 \
-const VMStateDescription vmstate_spapr_cap_##cap = {\
-.name = "spapr/cap/" #cap,  \
+const VMStateDescription vmstate_spapr_cap_##sname = {  \
+.name = "spapr/cap/" #sname,\
 .version_id = 1,\
 .minimum_version_id = 1,\
-.needed = spapr_cap_##cap##_needed, \
+.needed = spapr_cap_##sname##_needed,   \
 .fields = (VMStateField[]) {\
-VMSTATE_UINT8(mig.caps[SPAPR_CAP_##ccap],   \
+VMSTATE_UINT8(mig.caps[cap],\
   sPAPRMachineState),   \
 VMSTATE_END_OF_LIST()   \
 },  \
 }
 
-SPAPR_CAP_MIG_STATE(htm, HTM);
-SPAPR_CAP_MIG_STATE(vsx, VSX);
-SPAPR_CAP_MIG_STATE(dfp, DFP);
-SPAPR_CAP_MIG_STATE(cfpc, CFPC);
-SPAPR_CAP_MIG_STATE(sbbc, SBBC);
-SPAPR_CAP_MIG_STATE(ibs, IBS);
+SPAPR_CAP_MIG_STATE(htm, SPAPR_CAP_HTM);
+SPAPR_CAP_MIG_STATE(vsx, SPAPR_CAP_VSX);
+SPAPR_CAP_MIG_STATE(dfp, SPAPR_CAP_DFP);
+SPAPR_CAP_MIG_STATE(cfpc, SPAPR_CAP_CFPC);
+SPAPR_CAP_MIG_STATE(sbbc, SPAPR_CAP_SBBC);
+SPAPR_CAP_MIG_STATE(ibs, SPAPR_CAP_IBS);
 
 void spapr_caps_reset(sPAPRMachineState *spapr)
 {
-- 
2.13.6




[Qemu-devel] [QEMU-PPC] [PATCH V3 2/3] ppc/spapr-caps: Convert spapr-cap-ibs to be a boolean

2018-02-14 Thread Suraj Jitindar Singh
The spapr-cap cap-ibs can only have values broken or fixed as there is
no workaround. Currently setting the value workaround will hit an assert
if the guest makes the hcall h_get_cpu_characteristics.

Thus this capability is better suited to being represented as a boolean.
Setting this to OFF corresponds to the old BROKEN, that is no indirect
branch serialisation. Setting this to ON corresponds to the old FIXED,
that is indirect branches are serialised.

Reported-by: Satheesh Rajendran <sathn...@linux.vnet.ibm.com>
Signed-off-by: Suraj Jitindar Singh <sjitindarsi...@gmail.com>
---
 hw/ppc/spapr.c  |  2 +-
 hw/ppc/spapr_caps.c | 12 ++--
 target/ppc/kvm.c|  2 +-
 3 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index 32a876be56..969db6cde2 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -3886,7 +3886,7 @@ static void spapr_machine_class_init(ObjectClass *oc, 
void *data)
 smc->default_caps.caps[SPAPR_CAP_DFP] = SPAPR_CAP_ON;
 smc->default_caps.caps[SPAPR_CAP_CFPC] = SPAPR_CAP_BROKEN;
 smc->default_caps.caps[SPAPR_CAP_SBBC] = SPAPR_CAP_BROKEN;
-smc->default_caps.caps[SPAPR_CAP_IBS] = SPAPR_CAP_BROKEN;
+smc->default_caps.caps[SPAPR_CAP_IBS] = SPAPR_CAP_OFF;
 spapr_caps_add_properties(smc, _abort);
 }
 
diff --git a/hw/ppc/spapr_caps.c b/hw/ppc/spapr_caps.c
index e69d308560..05997b0842 100644
--- a/hw/ppc/spapr_caps.c
+++ b/hw/ppc/spapr_caps.c
@@ -207,9 +207,9 @@ static void 
cap_safe_indirect_branch_apply(sPAPRMachineState *spapr,
 {
 if (tcg_enabled() && val) {
 /* TODO - for now only allow broken for TCG */
-error_setg(errp, "Requested safe indirect branch capability level not 
supported by tcg, try a different value for cap-ibs");
+error_setg(errp, "Indirect Branch Serialisation support not available, 
try cap-ibs=off");
 } else if (kvm_enabled() && (val > kvmppc_get_cap_safe_indirect_branch())) 
{
-error_setg(errp, "Requested safe indirect branch capability level not 
supported by kvm, try a different value for cap-ibs");
+error_setg(errp, "Indirect Branch Serialisation support not available, 
try cap-ibs=off");
 }
 }
 
@@ -263,11 +263,11 @@ sPAPRCapabilityInfo capability_table[SPAPR_CAP_NUM] = {
 },
 [SPAPR_CAP_IBS] = {
 .name = "ibs",
-.description = "Indirect Branch Serialisation" VALUE_DESC_TRISTATE,
+.description = "Indirect Branch Serialisation",
 .index = SPAPR_CAP_IBS,
-.get = spapr_cap_get_tristate,
-.set = spapr_cap_set_tristate,
-.type = "string",
+.get = spapr_cap_get_bool,
+.set = spapr_cap_set_bool,
+.type = "bool",
 .apply = cap_safe_indirect_branch_apply,
 },
 };
diff --git a/target/ppc/kvm.c b/target/ppc/kvm.c
index 9842b3bb12..3e3e5f9c1f 100644
--- a/target/ppc/kvm.c
+++ b/target/ppc/kvm.c
@@ -2495,7 +2495,7 @@ static void kvmppc_get_cpu_characteristics(KVMState *s)
 }
 /* Parse and set cap_ppc_safe_indirect_branch */
 if (c.character & H_CPU_CHAR_BCCTRL_SERIALISED) {
-cap_ppc_safe_indirect_branch = 2;
+cap_ppc_safe_indirect_branch = 1;
 }
 }
 
-- 
2.13.6




Re: [Qemu-devel] [Qemu-ppc] [QEMU-PPC] [PATCH V2 3/3] ppc/spapr-caps: For pseries-2.12 change spapr-cap defaults

2018-02-14 Thread Suraj Jitindar Singh
On Wed, 2018-02-14 at 15:20 +0100, Greg Kurz wrote:
> On Wed, 14 Feb 2018 17:51:35 +1100
> Suraj Jitindar Singh <sjitindarsi...@gmail.com> wrote:
> 
> > For the pseries-2.12 machine type, make the spapr-caps
> > SPAPR_CAP_CFPC
> > and SPAPR_CAP_SBBC default to workaround. Thus if the host is
> > capable
> > the guest will be able to take advantage of these workarounds by
> > default.
> > Otherwise if the host doesn't have these capabilities qemu will
> > fail to
> > start and they will have to be explicitly disabled on the command
> > line
> > with:
> > -machine pseries,cap-cfpc=broken,cap-sbbc=broken
> > 
> > Signed-off-by: Suraj Jitindar Singh <sjitindarsi...@gmail.com>
> > ---
> >  hw/ppc/spapr.c  | 11 ++-
> >  hw/ppc/spapr_caps.c | 10 ++
> >  include/hw/compat.h |  2 ++
> >  3 files changed, 22 insertions(+), 1 deletion(-)
> > 
> > diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
> > index 969db6cde2..e2ebb76242 100644
> > --- a/hw/ppc/spapr.c
> > +++ b/hw/ppc/spapr.c
> > @@ -3941,13 +3941,20 @@ static const TypeInfo spapr_machine_info =
> > {
> >  /*
> >   * pseries-2.12
> >   */
> > +#define
> > SPAPR_COMPAT_2_12  \
> > +HW_COMPAT_2_12
> > +
> >  static void spapr_machine_2_12_instance_options(MachineState
> > *machine)
> >  {
> >  }
> >  
> >  static void spapr_machine_2_12_class_options(MachineClass *mc)
> >  {
> > -/* Defaults for the latest behaviour inherited from the base
> > class */
> > +sPAPRMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
> > +
> > +smc->default_caps.caps[SPAPR_CAP_CFPC] = SPAPR_CAP_WORKAROUND;
> > +smc->default_caps.caps[SPAPR_CAP_SBBC] = SPAPR_CAP_WORKAROUND;
> 
> As written in the comment, the default for the latest machine type
> should
> be set at the base class level, in spapr_machine_class_init()... not
> sure
> to understand why you set it here...

Ah yes, my bad.

> 
> > +SET_MACHINE_COMPAT(mc, SPAPR_COMPAT_2_12);
> 
> And so, you shouldn't need to setup 2.12 compat mode before 2.12 was
> even
> released :)

Fair enough :)

> 
> >  }
> >  
> >  DEFINE_SPAPR_MACHINE(2_12, "2.12", true);
> > @@ -3969,6 +3976,8 @@ static void
> > spapr_machine_2_11_class_options(MachineClass *mc)
> >  
> >  spapr_machine_2_12_class_options(mc);
> >  smc->default_caps.caps[SPAPR_CAP_HTM] = SPAPR_CAP_ON;
> > +smc->default_caps.caps[SPAPR_CAP_CFPC] = SPAPR_CAP_BROKEN;
> > +smc->default_caps.caps[SPAPR_CAP_SBBC] = SPAPR_CAP_BROKEN;
> >  SET_MACHINE_COMPAT(mc, SPAPR_COMPAT_2_11);
> >  }
> >  
> > diff --git a/hw/ppc/spapr_caps.c b/hw/ppc/spapr_caps.c
> > index 05997b0842..c25c2bca52 100644
> > --- a/hw/ppc/spapr_caps.c
> > +++ b/hw/ppc/spapr_caps.c
> > @@ -281,11 +281,21 @@ static sPAPRCapabilities
> > default_caps_with_cpu(sPAPRMachineState *spapr,
> >  
> >  caps = smc->default_caps;
> >  
> > +if (!ppc_check_compat(cpu, CPU_POWERPC_LOGICAL_3_00,
> > +  0, spapr->max_compat_pvr)) {
> > +caps.caps[SPAPR_CAP_CFPC] = SPAPR_CAP_BROKEN;
> > +}
> > +
> >  if (!ppc_check_compat(cpu, CPU_POWERPC_LOGICAL_2_07,
> >0, spapr->max_compat_pvr)) {
> >  caps.caps[SPAPR_CAP_HTM] = SPAPR_CAP_OFF;
> >  }
> >  
> > +if (!ppc_check_compat(cpu, CPU_POWERPC_LOGICAL_2_06_PLUS,
> > +  0, spapr->max_compat_pvr)) {
> > +caps.caps[SPAPR_CAP_SBBC] = SPAPR_CAP_BROKEN;
> > +}
> > +
> >  if (!ppc_check_compat(cpu, CPU_POWERPC_LOGICAL_2_06,
> >0, spapr->max_compat_pvr)) {
> >  caps.caps[SPAPR_CAP_VSX] = SPAPR_CAP_OFF;
> > diff --git a/include/hw/compat.h b/include/hw/compat.h
> > index 7f31850dfa..13238239da 100644
> > --- a/include/hw/compat.h
> > +++ b/include/hw/compat.h
> > @@ -1,6 +1,8 @@
> >  #ifndef HW_COMPAT_H
> >  #define HW_COMPAT_H
> >  
> > +#define HW_COMPAT_2_12
> > +
> >  #define HW_COMPAT_2_11 \
> >  {\
> >  .driver   = "hpet",\
> 
> 



[Qemu-devel] [QEMU-PPC] [PATCH V2 3/3] ppc/spapr-caps: For pseries-2.12 change spapr-cap defaults

2018-02-13 Thread Suraj Jitindar Singh
For the pseries-2.12 machine type, make the spapr-caps SPAPR_CAP_CFPC
and SPAPR_CAP_SBBC default to workaround. Thus if the host is capable
the guest will be able to take advantage of these workarounds by default.
Otherwise if the host doesn't have these capabilities qemu will fail to
start and they will have to be explicitly disabled on the command line
with:
-machine pseries,cap-cfpc=broken,cap-sbbc=broken

Signed-off-by: Suraj Jitindar Singh <sjitindarsi...@gmail.com>
---
 hw/ppc/spapr.c  | 11 ++-
 hw/ppc/spapr_caps.c | 10 ++
 include/hw/compat.h |  2 ++
 3 files changed, 22 insertions(+), 1 deletion(-)

diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index 969db6cde2..e2ebb76242 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -3941,13 +3941,20 @@ static const TypeInfo spapr_machine_info = {
 /*
  * pseries-2.12
  */
+#define SPAPR_COMPAT_2_12  \
+HW_COMPAT_2_12
+
 static void spapr_machine_2_12_instance_options(MachineState *machine)
 {
 }
 
 static void spapr_machine_2_12_class_options(MachineClass *mc)
 {
-/* Defaults for the latest behaviour inherited from the base class */
+sPAPRMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
+
+smc->default_caps.caps[SPAPR_CAP_CFPC] = SPAPR_CAP_WORKAROUND;
+smc->default_caps.caps[SPAPR_CAP_SBBC] = SPAPR_CAP_WORKAROUND;
+SET_MACHINE_COMPAT(mc, SPAPR_COMPAT_2_12);
 }
 
 DEFINE_SPAPR_MACHINE(2_12, "2.12", true);
@@ -3969,6 +3976,8 @@ static void spapr_machine_2_11_class_options(MachineClass 
*mc)
 
 spapr_machine_2_12_class_options(mc);
 smc->default_caps.caps[SPAPR_CAP_HTM] = SPAPR_CAP_ON;
+smc->default_caps.caps[SPAPR_CAP_CFPC] = SPAPR_CAP_BROKEN;
+smc->default_caps.caps[SPAPR_CAP_SBBC] = SPAPR_CAP_BROKEN;
 SET_MACHINE_COMPAT(mc, SPAPR_COMPAT_2_11);
 }
 
diff --git a/hw/ppc/spapr_caps.c b/hw/ppc/spapr_caps.c
index 05997b0842..c25c2bca52 100644
--- a/hw/ppc/spapr_caps.c
+++ b/hw/ppc/spapr_caps.c
@@ -281,11 +281,21 @@ static sPAPRCapabilities 
default_caps_with_cpu(sPAPRMachineState *spapr,
 
 caps = smc->default_caps;
 
+if (!ppc_check_compat(cpu, CPU_POWERPC_LOGICAL_3_00,
+  0, spapr->max_compat_pvr)) {
+caps.caps[SPAPR_CAP_CFPC] = SPAPR_CAP_BROKEN;
+}
+
 if (!ppc_check_compat(cpu, CPU_POWERPC_LOGICAL_2_07,
   0, spapr->max_compat_pvr)) {
 caps.caps[SPAPR_CAP_HTM] = SPAPR_CAP_OFF;
 }
 
+if (!ppc_check_compat(cpu, CPU_POWERPC_LOGICAL_2_06_PLUS,
+  0, spapr->max_compat_pvr)) {
+caps.caps[SPAPR_CAP_SBBC] = SPAPR_CAP_BROKEN;
+}
+
 if (!ppc_check_compat(cpu, CPU_POWERPC_LOGICAL_2_06,
   0, spapr->max_compat_pvr)) {
 caps.caps[SPAPR_CAP_VSX] = SPAPR_CAP_OFF;
diff --git a/include/hw/compat.h b/include/hw/compat.h
index 7f31850dfa..13238239da 100644
--- a/include/hw/compat.h
+++ b/include/hw/compat.h
@@ -1,6 +1,8 @@
 #ifndef HW_COMPAT_H
 #define HW_COMPAT_H
 
+#define HW_COMPAT_2_12
+
 #define HW_COMPAT_2_11 \
 {\
 .driver   = "hpet",\
-- 
2.13.6




[Qemu-devel] [QEMU-PPC] [PATCH V2 1/3] ppc/spapr-caps: Change migration macro to take full spapr-cap name

2018-02-13 Thread Suraj Jitindar Singh
Change the macro that generates the vmstate migration field and the needed
function for the spapr-caps to take the full spapr-cap name. This has
the benefit of meaning this instance will be picked up when greping
for the spapr-caps and making it more obvious what this macro is doing.

Signed-off-by: Suraj Jitindar Singh <sjitindarsi...@gmail.com>
---
 hw/ppc/spapr_caps.c | 30 +++---
 1 file changed, 15 insertions(+), 15 deletions(-)

diff --git a/hw/ppc/spapr_caps.c b/hw/ppc/spapr_caps.c
index 62efdaee38..e69d308560 100644
--- a/hw/ppc/spapr_caps.c
+++ b/hw/ppc/spapr_caps.c
@@ -350,34 +350,34 @@ int spapr_caps_post_migration(sPAPRMachineState *spapr)
 }
 
 /* Used to generate the migration field and needed function for a spapr cap */
-#define SPAPR_CAP_MIG_STATE(cap, ccap)  \
-static bool spapr_cap_##cap##_needed(void *opaque)  \
+#define SPAPR_CAP_MIG_STATE(sname, cap) \
+static bool spapr_cap_##sname##_needed(void *opaque)\
 {   \
 sPAPRMachineState *spapr = opaque;  \
 \
-return spapr->cmd_line_caps[SPAPR_CAP_##ccap] &&\
-   (spapr->eff.caps[SPAPR_CAP_##ccap] !=\
-spapr->def.caps[SPAPR_CAP_##ccap]); \
+return spapr->cmd_line_caps[cap] && \
+   (spapr->eff.caps[cap] != \
+spapr->def.caps[cap]);  \
 }   \
 \
-const VMStateDescription vmstate_spapr_cap_##cap = {\
-.name = "spapr/cap/" #cap,  \
+const VMStateDescription vmstate_spapr_cap_##sname = {  \
+.name = "spapr/cap/" #sname,\
 .version_id = 1,\
 .minimum_version_id = 1,\
-.needed = spapr_cap_##cap##_needed, \
+.needed = spapr_cap_##sname##_needed,   \
 .fields = (VMStateField[]) {\
-VMSTATE_UINT8(mig.caps[SPAPR_CAP_##ccap],   \
+VMSTATE_UINT8(mig.caps[cap],\
   sPAPRMachineState),   \
 VMSTATE_END_OF_LIST()   \
 },  \
 }
 
-SPAPR_CAP_MIG_STATE(htm, HTM);
-SPAPR_CAP_MIG_STATE(vsx, VSX);
-SPAPR_CAP_MIG_STATE(dfp, DFP);
-SPAPR_CAP_MIG_STATE(cfpc, CFPC);
-SPAPR_CAP_MIG_STATE(sbbc, SBBC);
-SPAPR_CAP_MIG_STATE(ibs, IBS);
+SPAPR_CAP_MIG_STATE(htm, SPAPR_CAP_HTM);
+SPAPR_CAP_MIG_STATE(vsx, SPAPR_CAP_VSX);
+SPAPR_CAP_MIG_STATE(dfp, SPAPR_CAP_DFP);
+SPAPR_CAP_MIG_STATE(cfpc, SPAPR_CAP_CFPC);
+SPAPR_CAP_MIG_STATE(sbbc, SPAPR_CAP_SBBC);
+SPAPR_CAP_MIG_STATE(ibs, SPAPR_CAP_IBS);
 
 void spapr_caps_reset(sPAPRMachineState *spapr)
 {
-- 
2.13.6




[Qemu-devel] [QEMU-PPC] [PATCH V2 2/3] ppc/spapr-caps: Convert spapr-cap-ibs to be a boolean

2018-02-13 Thread Suraj Jitindar Singh
The spapr-cap cap-ibs can only have values broken or fixed as there is
no workaround. Currently setting the value workaround will hit an assert
if the guest makes the hcall h_get_cpu_characteristics.

Thus this capability is better suited to being represented as a boolean.
Setting this to OFF corresponds to the old BROKEN, that is no indirect
branch serialisation. Setting this to ON corresponds to the old FIXED,
that is indirect branches are serialised.

Reported-by: Satheesh Rajendran <sathn...@linux.vnet.ibm.com>
Signed-off-by: Suraj Jitindar Singh <sjitindarsi...@gmail.com>
---
 hw/ppc/spapr.c  |  2 +-
 hw/ppc/spapr_caps.c | 12 ++--
 target/ppc/kvm.c|  2 +-
 3 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index 32a876be56..969db6cde2 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -3886,7 +3886,7 @@ static void spapr_machine_class_init(ObjectClass *oc, 
void *data)
 smc->default_caps.caps[SPAPR_CAP_DFP] = SPAPR_CAP_ON;
 smc->default_caps.caps[SPAPR_CAP_CFPC] = SPAPR_CAP_BROKEN;
 smc->default_caps.caps[SPAPR_CAP_SBBC] = SPAPR_CAP_BROKEN;
-smc->default_caps.caps[SPAPR_CAP_IBS] = SPAPR_CAP_BROKEN;
+smc->default_caps.caps[SPAPR_CAP_IBS] = SPAPR_CAP_OFF;
 spapr_caps_add_properties(smc, _abort);
 }
 
diff --git a/hw/ppc/spapr_caps.c b/hw/ppc/spapr_caps.c
index e69d308560..05997b0842 100644
--- a/hw/ppc/spapr_caps.c
+++ b/hw/ppc/spapr_caps.c
@@ -207,9 +207,9 @@ static void 
cap_safe_indirect_branch_apply(sPAPRMachineState *spapr,
 {
 if (tcg_enabled() && val) {
 /* TODO - for now only allow broken for TCG */
-error_setg(errp, "Requested safe indirect branch capability level not 
supported by tcg, try a different value for cap-ibs");
+error_setg(errp, "Indirect Branch Serialisation support not available, 
try cap-ibs=off");
 } else if (kvm_enabled() && (val > kvmppc_get_cap_safe_indirect_branch())) 
{
-error_setg(errp, "Requested safe indirect branch capability level not 
supported by kvm, try a different value for cap-ibs");
+error_setg(errp, "Indirect Branch Serialisation support not available, 
try cap-ibs=off");
 }
 }
 
@@ -263,11 +263,11 @@ sPAPRCapabilityInfo capability_table[SPAPR_CAP_NUM] = {
 },
 [SPAPR_CAP_IBS] = {
 .name = "ibs",
-.description = "Indirect Branch Serialisation" VALUE_DESC_TRISTATE,
+.description = "Indirect Branch Serialisation",
 .index = SPAPR_CAP_IBS,
-.get = spapr_cap_get_tristate,
-.set = spapr_cap_set_tristate,
-.type = "string",
+.get = spapr_cap_get_bool,
+.set = spapr_cap_set_bool,
+.type = "bool",
 .apply = cap_safe_indirect_branch_apply,
 },
 };
diff --git a/target/ppc/kvm.c b/target/ppc/kvm.c
index 9842b3bb12..3e3e5f9c1f 100644
--- a/target/ppc/kvm.c
+++ b/target/ppc/kvm.c
@@ -2495,7 +2495,7 @@ static void kvmppc_get_cpu_characteristics(KVMState *s)
 }
 /* Parse and set cap_ppc_safe_indirect_branch */
 if (c.character & H_CPU_CHAR_BCCTRL_SERIALISED) {
-cap_ppc_safe_indirect_branch = 2;
+cap_ppc_safe_indirect_branch = 1;
 }
 }
 
-- 
2.13.6




[Qemu-devel] [QEMU-PPC PATCH 3/3] ppc/spapr-caps: For pseries-2.12 change spapr-cap defaults

2018-02-13 Thread Suraj Jitindar Singh
For the pseries-2.12 machine type, make the spapr-caps SPAPR_CAP_CFPC
and SPAPR_CAP_SBBC default to workaround. This means the guest will
be able to take advantage of these workarounds by default, so long
as the host is capable.

Signed-off-by: Suraj Jitindar Singh <sjitindarsi...@gmail.com>
---
 hw/ppc/spapr.c  | 11 ++-
 hw/ppc/spapr_caps.c | 10 ++
 include/hw/compat.h |  2 ++
 3 files changed, 22 insertions(+), 1 deletion(-)

diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index 32a876be56..cd4a024660 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -3941,13 +3941,20 @@ static const TypeInfo spapr_machine_info = {
 /*
  * pseries-2.12
  */
+#define SPAPR_COMPAT_2_12  \
+HW_COMPAT_2_12
+
 static void spapr_machine_2_12_instance_options(MachineState *machine)
 {
 }
 
 static void spapr_machine_2_12_class_options(MachineClass *mc)
 {
-/* Defaults for the latest behaviour inherited from the base class */
+sPAPRMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
+
+smc->default_caps.caps[SPAPR_CAP_CFPC] = SPAPR_CAP_WORKAROUND;
+smc->default_caps.caps[SPAPR_CAP_SBBC] = SPAPR_CAP_WORKAROUND;
+SET_MACHINE_COMPAT(mc, SPAPR_COMPAT_2_12);
 }
 
 DEFINE_SPAPR_MACHINE(2_12, "2.12", true);
@@ -3969,6 +3976,8 @@ static void spapr_machine_2_11_class_options(MachineClass 
*mc)
 
 spapr_machine_2_12_class_options(mc);
 smc->default_caps.caps[SPAPR_CAP_HTM] = SPAPR_CAP_ON;
+smc->default_caps.caps[SPAPR_CAP_CFPC] = SPAPR_CAP_BROKEN;
+smc->default_caps.caps[SPAPR_CAP_SBBC] = SPAPR_CAP_BROKEN;
 SET_MACHINE_COMPAT(mc, SPAPR_COMPAT_2_11);
 }
 
diff --git a/hw/ppc/spapr_caps.c b/hw/ppc/spapr_caps.c
index 1cd73b617f..3dda1db812 100644
--- a/hw/ppc/spapr_caps.c
+++ b/hw/ppc/spapr_caps.c
@@ -283,11 +283,21 @@ static sPAPRCapabilities 
default_caps_with_cpu(sPAPRMachineState *spapr,
 
 caps = smc->default_caps;
 
+if (!ppc_check_compat(cpu, CPU_POWERPC_LOGICAL_3_00,
+  0, spapr->max_compat_pvr)) {
+caps.caps[SPAPR_CAP_CFPC] = SPAPR_CAP_BROKEN;
+}
+
 if (!ppc_check_compat(cpu, CPU_POWERPC_LOGICAL_2_07,
   0, spapr->max_compat_pvr)) {
 caps.caps[SPAPR_CAP_HTM] = SPAPR_CAP_OFF;
 }
 
+if (!ppc_check_compat(cpu, CPU_POWERPC_LOGICAL_2_06_PLUS,
+  0, spapr->max_compat_pvr)) {
+caps.caps[SPAPR_CAP_SBBC] = SPAPR_CAP_BROKEN;
+}
+
 if (!ppc_check_compat(cpu, CPU_POWERPC_LOGICAL_2_06,
   0, spapr->max_compat_pvr)) {
 caps.caps[SPAPR_CAP_VSX] = SPAPR_CAP_OFF;
diff --git a/include/hw/compat.h b/include/hw/compat.h
index 7f31850dfa..13238239da 100644
--- a/include/hw/compat.h
+++ b/include/hw/compat.h
@@ -1,6 +1,8 @@
 #ifndef HW_COMPAT_H
 #define HW_COMPAT_H
 
+#define HW_COMPAT_2_12
+
 #define HW_COMPAT_2_11 \
 {\
 .driver   = "hpet",\
-- 
2.13.6




[Qemu-devel] [QEMU-PPC PATCH 2/3] ppc/spapr-caps: Disallow setting workaround for spapr-cap-ibs

2018-02-13 Thread Suraj Jitindar Singh
The spapr-cap cap-ibs can only have values broken or fixed as there is
no workaround. Currently setting the value workaround will hit an assert
if the guest makes the hcall h_get_cpu_characteristics.

Report an error when attempting to apply the setting with a more helpful
error message.

Reported-by: Satheesh Rajendran <sathn...@linux.vnet.ibm.com>
Signed-off-by: Suraj Jitindar Singh <sjitindarsi...@gmail.com>
---
 hw/ppc/spapr_caps.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/hw/ppc/spapr_caps.c b/hw/ppc/spapr_caps.c
index e69d308560..1cd73b617f 100644
--- a/hw/ppc/spapr_caps.c
+++ b/hw/ppc/spapr_caps.c
@@ -205,7 +205,9 @@ static void cap_safe_bounds_check_apply(sPAPRMachineState 
*spapr, uint8_t val,
 static void cap_safe_indirect_branch_apply(sPAPRMachineState *spapr,
uint8_t val, Error **errp)
 {
-if (tcg_enabled() && val) {
+if (val == SPAPR_CAP_WORKAROUND) { /* Can only be Broken or Fixed */
+error_setg(errp, "Requested safe indirect branch capability level 
\"workaround\" not valid, try cap-ibs=fixed");
+} else if (tcg_enabled() && val) {
 /* TODO - for now only allow broken for TCG */
 error_setg(errp, "Requested safe indirect branch capability level not 
supported by tcg, try a different value for cap-ibs");
 } else if (kvm_enabled() && (val > kvmppc_get_cap_safe_indirect_branch())) 
{
-- 
2.13.6




[Qemu-devel] [QEMU-PPC PATCH 1/3] ppc/spapr-caps: Change migration macro to take full spapr-cap name

2018-02-13 Thread Suraj Jitindar Singh
Change the macro that generates the vmstate migration field and the needed
function for the spapr-caps to take the full spapr-cap name. This has
the benefit of meaning this instance will be picked up when greping
for the spapr-caps and making it more obvious what this macro is doing.

Signed-off-by: Suraj Jitindar Singh <sjitindarsi...@gmail.com>
---
 hw/ppc/spapr_caps.c | 30 +++---
 1 file changed, 15 insertions(+), 15 deletions(-)

diff --git a/hw/ppc/spapr_caps.c b/hw/ppc/spapr_caps.c
index 62efdaee38..e69d308560 100644
--- a/hw/ppc/spapr_caps.c
+++ b/hw/ppc/spapr_caps.c
@@ -350,34 +350,34 @@ int spapr_caps_post_migration(sPAPRMachineState *spapr)
 }
 
 /* Used to generate the migration field and needed function for a spapr cap */
-#define SPAPR_CAP_MIG_STATE(cap, ccap)  \
-static bool spapr_cap_##cap##_needed(void *opaque)  \
+#define SPAPR_CAP_MIG_STATE(sname, cap) \
+static bool spapr_cap_##sname##_needed(void *opaque)\
 {   \
 sPAPRMachineState *spapr = opaque;  \
 \
-return spapr->cmd_line_caps[SPAPR_CAP_##ccap] &&\
-   (spapr->eff.caps[SPAPR_CAP_##ccap] !=\
-spapr->def.caps[SPAPR_CAP_##ccap]); \
+return spapr->cmd_line_caps[cap] && \
+   (spapr->eff.caps[cap] != \
+spapr->def.caps[cap]);  \
 }   \
 \
-const VMStateDescription vmstate_spapr_cap_##cap = {\
-.name = "spapr/cap/" #cap,  \
+const VMStateDescription vmstate_spapr_cap_##sname = {  \
+.name = "spapr/cap/" #sname,\
 .version_id = 1,\
 .minimum_version_id = 1,\
-.needed = spapr_cap_##cap##_needed, \
+.needed = spapr_cap_##sname##_needed,   \
 .fields = (VMStateField[]) {\
-VMSTATE_UINT8(mig.caps[SPAPR_CAP_##ccap],   \
+VMSTATE_UINT8(mig.caps[cap],\
   sPAPRMachineState),   \
 VMSTATE_END_OF_LIST()   \
 },  \
 }
 
-SPAPR_CAP_MIG_STATE(htm, HTM);
-SPAPR_CAP_MIG_STATE(vsx, VSX);
-SPAPR_CAP_MIG_STATE(dfp, DFP);
-SPAPR_CAP_MIG_STATE(cfpc, CFPC);
-SPAPR_CAP_MIG_STATE(sbbc, SBBC);
-SPAPR_CAP_MIG_STATE(ibs, IBS);
+SPAPR_CAP_MIG_STATE(htm, SPAPR_CAP_HTM);
+SPAPR_CAP_MIG_STATE(vsx, SPAPR_CAP_VSX);
+SPAPR_CAP_MIG_STATE(dfp, SPAPR_CAP_DFP);
+SPAPR_CAP_MIG_STATE(cfpc, SPAPR_CAP_CFPC);
+SPAPR_CAP_MIG_STATE(sbbc, SPAPR_CAP_SBBC);
+SPAPR_CAP_MIG_STATE(ibs, SPAPR_CAP_IBS);
 
 void spapr_caps_reset(sPAPRMachineState *spapr)
 {
-- 
2.13.6




Re: [Qemu-devel] [PATCH] spapr: add missing break in h_get_cpu_characteristics()

2018-02-01 Thread Suraj Jitindar Singh
On Thu, 2018-02-01 at 20:47 +0100, Greg Kurz wrote:
> Detected by Coverity (CID 1385702). This fixes the recently added
> hypercall
> to let guests properly apply Spectre and Meltdown workarounds.
> 
> Fixes: c59704b25473 "target/ppc/spapr: Add H-Call
> H_GET_CPU_CHARACTERISTICS"
> Signed-off-by: Greg Kurz <gr...@kaod.org>

Reviewed-by: Suraj Jitindar Singh <sjitindarsi...@gmail.com>

> ---
>  hw/ppc/spapr_hcall.c |1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c
> index 4d0e6eb0cf1d..596f58378a40 100644
> --- a/hw/ppc/spapr_hcall.c
> +++ b/hw/ppc/spapr_hcall.c
> @@ -1697,6 +1697,7 @@ static target_ulong
> h_get_cpu_characteristics(PowerPCCPU *cpu,
>  switch (safe_indirect_branch) {
>  case SPAPR_CAP_FIXED:
>  characteristics |= H_CPU_CHAR_BCCTRL_SERIALISED;
> +break;
>  default: /* broken */
>  assert(safe_indirect_branch == SPAPR_CAP_BROKEN);
>  break;
> 



Re: [Qemu-devel] [PATCH 3/3] target/ppc: generalize check on radix when in HV mode

2018-02-01 Thread Suraj Jitindar Singh
On Wed, 2018-01-31 at 09:27 +0100, Cédric Le Goater wrote:
> On a POWER9 processor, the first doubleword of the PTCR indicates
> whether the partition uses HPT or Radix Trees translation. Use that
> bit to check for radix mode on powernv QEMU machines.

The above isn't quite right.

On a POWER9 processor, the first doubleword of the partition table
entry (as pointed to by the PTCR) indicates whether the host uses HPT
or Radix Tree translation for that partition.

> 
> Signed-off-by: Cédric Le Goater 
> ---
>  target/ppc/mmu-book3s-v3.c  | 17 -
>  target/ppc/mmu-book3s-v3.h  |  8 +---
>  target/ppc/mmu-hash64.h |  1 +
>  target/ppc/mmu_helper.c |  4 ++--
>  target/ppc/translate_init.c |  2 +-
>  5 files changed, 21 insertions(+), 11 deletions(-)
> 
> diff --git a/target/ppc/mmu-book3s-v3.c b/target/ppc/mmu-book3s-v3.c
> index e7798b3582b0..50b60fca3445 100644
> --- a/target/ppc/mmu-book3s-v3.c
> +++ b/target/ppc/mmu-book3s-v3.c
> @@ -24,10 +24,25 @@
>  #include "mmu-book3s-v3.h"
>  #include "mmu-radix64.h"
>  
> +bool ppc64_radix(PowerPCCPU *cpu)
> +{
> +CPUPPCState *env = >env;
> +
> +if (msr_hv) {

I would prefer something like:

uint64_t prtbe0 = ldq_phys(...);
return prtbe0 & HR;

> +return ldq_phys(CPU(cpu)->as, cpu->env.spr[SPR_PTCR] &
> +PTCR_PTAB) & PTCR_PTAB_HR;
> +} else  {
> +PPCVirtualHypervisorClass *vhc =
> +PPC_VIRTUAL_HYPERVISOR_GET_CLASS(cpu->vhyp);
> +
> +return !!(vhc->get_patbe(cpu->vhyp) & PATBE1_GR);
> +}
> +}
> +
>  int ppc64_v3_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr, int rwx,
>int mmu_idx)
>  {
> -if (ppc64_radix_guest(cpu)) { /* Guest uses radix */
> +if (ppc64_radix(cpu)) { /* radix mode */
>  return ppc_radix64_handle_mmu_fault(cpu, eaddr, rwx,
> mmu_idx);
>  } else { /* Guest uses hash */
>  return ppc_hash64_handle_mmu_fault(cpu, eaddr, rwx,
> mmu_idx);
> diff --git a/target/ppc/mmu-book3s-v3.h b/target/ppc/mmu-book3s-v3.h
> index 56095dab522c..3876cb51b35c 100644
> --- a/target/ppc/mmu-book3s-v3.h
> +++ b/target/ppc/mmu-book3s-v3.h
> @@ -37,13 +37,7 @@ static inline bool ppc64_use_proc_tbl(PowerPCCPU
> *cpu)
>  return !!(cpu->env.spr[SPR_LPCR] & LPCR_UPRT);
>  }
>  
> -static inline bool ppc64_radix_guest(PowerPCCPU *cpu)
> -{
> -PPCVirtualHypervisorClass *vhc =
> -PPC_VIRTUAL_HYPERVISOR_GET_CLASS(cpu->vhyp);
> -
> -return !!(vhc->get_patbe(cpu->vhyp) & PATBE1_GR);
> -}
> +bool ppc64_radix(PowerPCCPU *cpu);
>  
>  int ppc64_v3_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr, int rwx,
>int mmu_idx);
> diff --git a/target/ppc/mmu-hash64.h b/target/ppc/mmu-hash64.h
> index 4dc6b3968ec0..7e2ac64b6eeb 100644
> --- a/target/ppc/mmu-hash64.h
> +++ b/target/ppc/mmu-hash64.h
> @@ -106,6 +106,7 @@ void ppc_hash64_update_rmls(CPUPPCState *env);
>  /*
>   * Partition table definitions
>   */
> +#define PTCR_PTAB_HRPPC_BIT(0)/* 1:Host 

This isn't a bit in the partition table register, it is a bit in the
partition table entry. It should be defined in target/ppc/mmu-book3s-
v3.h as part of "/* Partition Table Entry Fields */"

Also to follow the naming, please call it:
#define PATBE0_HR   PPC_BIT(0)

:)

> Radix 0:HPT   */
>  #define PTCR_PTAB   0x0000ULL /* Partition
> Table Base */
>  #define PTCR_PTAS   0x001FULL /* Partition
> Table Size */
>  
> diff --git a/target/ppc/mmu_helper.c b/target/ppc/mmu_helper.c
> index b1e660a4d16a..059863b99b2e 100644
> --- a/target/ppc/mmu_helper.c
> +++ b/target/ppc/mmu_helper.c
> @@ -1286,7 +1286,7 @@ void dump_mmu(FILE *f, fprintf_function
> cpu_fprintf, CPUPPCState *env)
>  dump_slb(f, cpu_fprintf, ppc_env_get_cpu(env));
>  break;
>  case POWERPC_MMU_VER_3_00:
> -if (ppc64_radix_guest(ppc_env_get_cpu(env))) {
> +if (ppc64_radix(ppc_env_get_cpu(env))) {
>  /* TODO - Unsupported */
>  } else {
>  dump_slb(f, cpu_fprintf, ppc_env_get_cpu(env));
> @@ -1432,7 +1432,7 @@ hwaddr ppc_cpu_get_phys_page_debug(CPUState
> *cs, vaddr addr)
>  case POWERPC_MMU_VER_2_07:
>  return ppc_hash64_get_phys_page_debug(cpu, addr);
>  case POWERPC_MMU_VER_3_00:
> -if (ppc64_radix_guest(ppc_env_get_cpu(env))) {
> +if (ppc64_radix(ppc_env_get_cpu(env))) {
>  return ppc_radix64_get_phys_page_debug(cpu, addr);
>  } else {
>  return ppc_hash64_get_phys_page_debug(cpu, addr);
> diff --git a/target/ppc/translate_init.c
> b/target/ppc/translate_init.c
> index a6eaa74244ca..07012ee75e81 100644
> --- a/target/ppc/translate_init.c
> +++ b/target/ppc/translate_init.c
> @@ -8965,7 +8965,7 @@ void cpu_ppc_set_papr(PowerPCCPU *cpu,
> PPCVirtualHypervisor *vhyp)
>   * KVM but not under TCG. Update the default LPCR to keep
> new
>   * CPUs 

Re: [Qemu-devel] [PATCH 1/3] target/ppc: add basic support for PTCR on POWER9

2018-02-01 Thread Suraj Jitindar Singh
On Fri, 2018-02-02 at 13:34 +1100, Suraj Jitindar Singh wrote:
> On Wed, 2018-01-31 at 09:27 +0100, Cédric Le Goater wrote:
> > The Partition Table Control Register (PTCR) is a hypervisor
> > privileged
> > SPR. It contains the host real address of the Partition Table and
> > its
> > size.
> > 
> > Signed-off-by: Cédric Le Goater <c...@kaod.org>
> > ---
> >  target/ppc/cpu.h|  2 ++
> >  target/ppc/helper.h |  1 +
> >  target/ppc/misc_helper.c| 12 
> >  target/ppc/mmu-hash64.h |  6 ++
> >  target/ppc/mmu_helper.c | 28 
> >  target/ppc/translate.c  |  3 +++
> >  target/ppc/translate_init.c | 18 ++
> >  7 files changed, 70 insertions(+)
> > 
> > diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
> > index 9f8cbbe7aa4d..53061229a0a8 100644
> > --- a/target/ppc/cpu.h
> > +++ b/target/ppc/cpu.h
> > @@ -1314,6 +1314,7 @@ int ppc_cpu_handle_mmu_fault(CPUState *cpu,
> > vaddr address, int size, int rw,
> >  
> >  #if !defined(CONFIG_USER_ONLY)
> >  void ppc_store_sdr1 (CPUPPCState *env, target_ulong value);
> > +void ppc_store_ptcr(CPUPPCState *env, target_ulong value);
> >  #endif /* !defined(CONFIG_USER_ONLY) */
> >  void ppc_store_msr (CPUPPCState *env, target_ulong value);
> >  
> > @@ -1605,6 +1606,7 @@ void ppc_compat_add_property(Object *obj,
> > const
> > char *name,
> >  #define SPR_BOOKE_GIVOR13 (0x1BC)
> >  #define SPR_BOOKE_GIVOR14 (0x1BD)
> >  #define SPR_TIR   (0x1BE)
> > +#define SPR_PTCR  (0x1D0)
> >  #define SPR_BOOKE_SPEFSCR (0x200)
> >  #define SPR_Exxx_BBEAR(0x201)
> >  #define SPR_Exxx_BBTAR(0x202)
> > diff --git a/target/ppc/helper.h b/target/ppc/helper.h
> > index 5b739179b8b5..19453c68138a 100644
> > --- a/target/ppc/helper.h
> > +++ b/target/ppc/helper.h
> > @@ -709,6 +709,7 @@ DEF_HELPER_FLAGS_1(load_601_rtcu,
> > TCG_CALL_NO_RWG, tl, env)
> >  #if !defined(CONFIG_USER_ONLY)
> >  #if defined(TARGET_PPC64)
> >  DEF_HELPER_FLAGS_1(load_purr, TCG_CALL_NO_RWG, tl, env)
> > +DEF_HELPER_2(store_ptcr, void, env, tl)
> >  #endif
> >  DEF_HELPER_2(store_sdr1, void, env, tl)
> >  DEF_HELPER_2(store_pidr, void, env, tl)
> > diff --git a/target/ppc/misc_helper.c b/target/ppc/misc_helper.c
> > index 0e4217821b8e..8c8cba5cc6f1 100644
> > --- a/target/ppc/misc_helper.c
> > +++ b/target/ppc/misc_helper.c
> > @@ -88,6 +88,18 @@ void helper_store_sdr1(CPUPPCState *env,
> > target_ulong val)
> >  }
> >  }
> >  
> > +#if defined(TARGET_PPC64)
> > +void helper_store_ptcr(CPUPPCState *env, target_ulong val)
> > +{
> > +PowerPCCPU *cpu = ppc_env_get_cpu(env);
> > +
> > +if (env->spr[SPR_PTCR] != val) {
> > +ppc_store_ptcr(env, val);
> > +tlb_flush(CPU(cpu));
> > +}
> > +}
> > +#endif /* defined(TARGET_PPC64) */
> > +
> >  void helper_store_pidr(CPUPPCState *env, target_ulong val)
> >  {
> >  PowerPCCPU *cpu = ppc_env_get_cpu(env);
> > diff --git a/target/ppc/mmu-hash64.h b/target/ppc/mmu-hash64.h
> > index d297b97d3773..4fb00ac17abb 100644
> > --- a/target/ppc/mmu-hash64.h
> > +++ b/target/ppc/mmu-hash64.h
> > @@ -98,6 +98,12 @@ void ppc_hash64_update_rmls(CPUPPCState *env);
> >  #define HPTE64_V_1TB_SEG0x4000ULL
> >  #define HPTE64_V_VRMA_MASK  0x4001ff00ULL
> >  
> > +/*
> > + * Partition table definitions
> > + */
> > +#define PTCR_PTAB   0x0000ULL /* Partition
> > Table Base */
> > +#define PTCR_PTAS   0x001FULL /* Partition
> > Table Size */
> > +
> 
> s/PTCR_PTAB/PTCR_PATB
> s/PTCR_PTAS/PTCR_PATS
> To match the ISA?

Also these should be in target/ppc/mmu-book3s-v3.h, they're not hash
specific

> 
> >  static inline hwaddr ppc_hash64_hpt_base(PowerPCCPU *cpu)
> >  {
> >  return cpu->env.spr[SPR_SDR1] & SDR_64_HTABORG;
> > diff --git a/target/ppc/mmu_helper.c b/target/ppc/mmu_helper.c
> > index 16ef5acaa28f..b1e660a4d16a 100644
> > --- a/target/ppc/mmu_helper.c
> > +++ b/target/ppc/mmu_helper.c
> > @@ -2029,6 +2029,34 @@ void ppc_store_sdr1(CPUPPCState *env,
> > target_ulong value)
> >  env->spr[SPR_SDR1] = value;
> >  }
> >  
> > +#if defined(TARGET_PPC64)
> > +void ppc_store_ptcr(CPUPPCState *env, target_ulong value)
> > +{
> > +PowerPCCPU *cpu = pp

  1   2   3   >