Re: [Qemu-devel] [PATCH v2 00/21] RISC-V QEMU Port Submission v2

2018-01-10 Thread Christoph Hellwig
On Wed, Jan 10, 2018 at 03:46:19PM -0800, Michael Clark wrote:
> - RISC-V Instruction Set Manual Volume I: User-Level ISA Version 2.2
> - RISC-V Instruction Set Manual Volume II: Privileged ISA Version 1.9.1
> - RISC-V Instruction Set Manual Volume II: Privileged ISA Version 1.10

Same question as for V2:  Why do you want to add code for an obsolete
version of the privileged ISA spec? (which as far as I can tell
can't even be found online).



Re: [Qemu-devel] [PATCH qemu] target/ppc: Yet another fix for KVM-HV HPTE accessors

2018-01-10 Thread David Gibson
On Thu, Jan 11, 2018 at 03:08:32PM +1100, Alexey Kardashevskiy wrote:
> As stated in the 1ad9f0a464fe commit log, the returned entries are not
> a while PTEG. It was not a problem before 1ad9f0a464fe as it would read
> a single record assuming it contains a whole PTEG but now the code tries
> reading the entire PTEG and "if ((n - i) < invalid)" produces negative
> values which then are converted to size_t for memset() and that throws
> seg fault.
> 
> This fixes the math.
> 
> While here, fix the last @i increment as well.
> 
> Fixes: 1ad9f0a464fe "target/ppc: Fix KVM-HV HPTE accessors"
> Signed-off-by: Alexey Kardashevskiy 

Applied, thanks.

> ---
> 
> Record #0:
> (gdb) p *hdr
> $13 = {
>   index = ,
>   n_valid = 0x1,
>   n_invalid = 0x6
> }
> 
> Record #1:
> (gdb) p *hdr
> $18 = {
>   index = ,
>   n_valid = 0x2,
>   n_invalid = 0x6
> }
> 
> 
> i.e. in the second iteration of the loop right before
> "if ((n - i) < invalid)":
> (gdb) p n
> $16 = 0x8
> (gdb) p i
> $17 = 0x9
> 
> and @invalid becomes -1.
> 
> ---
>  target/ppc/kvm.c | 11 +++
>  1 file changed, 7 insertions(+), 4 deletions(-)
> 
> diff --git a/target/ppc/kvm.c b/target/ppc/kvm.c
> index 0566af7..c2dea81 100644
> --- a/target/ppc/kvm.c
> +++ b/target/ppc/kvm.c
> @@ -2657,21 +2657,24 @@ void kvmppc_read_hptes(ppc_hash_pte64_t *hptes, 
> hwaddr ptex, int n)
>  
>  hdr = (struct kvm_get_htab_header *)buf;
>  while ((i < n) && ((char *)hdr < (buf + rc))) {
> -int invalid = hdr->n_invalid;
> +int invalid = hdr->n_invalid, valid = hdr->n_valid;
>  
>  if (hdr->index != (ptex + i)) {
>  hw_error("kvmppc_read_hptes: Unexpected HPTE index %"PRIu32
>   " != (%"HWADDR_PRIu" + %d", hdr->index, ptex, i);
>  }
>  
> -memcpy(hptes + i, hdr + 1, HASH_PTE_SIZE_64 * hdr->n_valid);
> -i += hdr->n_valid;
> +if (n - i < valid) {
> +valid = n - i;
> +}
> +memcpy(hptes + i, hdr + 1, HASH_PTE_SIZE_64 * valid);
> +i += valid;
>  
>  if ((n - i) < invalid) {
>  invalid = n - i;
>  }
>  memset(hptes + i, 0, invalid * HASH_PTE_SIZE_64);
> -i += hdr->n_invalid;
> +i += invalid;
>  
>  hdr = (struct kvm_get_htab_header *)
>  ((char *)(hdr + 1) + HASH_PTE_SIZE_64 * hdr->n_valid);

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


signature.asc
Description: PGP signature


Re: [Qemu-devel] vhost-pci and virtio-vhost-user

2018-01-10 Thread Wei Wang

On 01/11/2018 12:14 AM, Stefan Hajnoczi wrote:

Hi Wei,
I wanted to summarize the differences between the vhost-pci and
virtio-vhost-user approaches because previous discussions may have been
confusing.

vhost-pci defines a new virtio device type for each vhost device type
(net, scsi, blk).  It therefore requires a virtio device driver for each
device type inside the slave VM.

Adding a new device type requires:
1. Defining a new virtio device type in the VIRTIO specification.
3. Implementing a new QEMU device model.
2. Implementing a new virtio driver.

virtio-vhost-user is a single virtio device that acts as a vhost-user
protocol transport for any vhost device type.  It requires one virtio
driver inside the slave VM and device types are implemented using
existing vhost-user slave libraries (librte_vhost in DPDK and
libvhost-user in QEMU).

Adding a new device type to virtio-vhost-user involves:
1. Adding any new vhost-user protocol messages to the QEMU
virtio-vhost-user device model.
2. Adding any new vhost-user protocol messages to the vhost-user slave
library.
3. Implementing the new device slave.

The simplest case is when no new vhost-user protocol messages are
required for the new device.  Then all that's needed for
virtio-vhost-user is a device slave implementation (#3).  That slave
implementation will also work with AF_UNIX because the vhost-user slave
library hides the transport (AF_UNIX vs virtio-vhost-user).  Even
better, if another person has already implemented that device slave to
use with AF_UNIX then no new code is needed for virtio-vhost-user
support at all!

If you compare this to vhost-pci, it would be necessary to design a new
virtio device, implement it in QEMU, and implement the virtio driver.
Much of virtio driver is more or less the same thing as the vhost-user
device slave but it cannot be reused because the vhost-user protocol
isn't being used by the virtio device.  The result is a lot of
duplication in DPDK and other codebases that implement vhost-user
slaves.

The way that vhost-pci is designed means that anyone wishing to support
a new device type has to become a virtio device designer.  They need to
map vhost-user protocol concepts to a new virtio device type.  This will
be time-consuming for everyone involved (e.g. the developer, the VIRTIO
community, etc).

The virtio-vhost-user approach stays at the vhost-user protocol level as
much as possible.  This way there are fewer concepts that need to be
mapped by people adding new device types.  As a result, it will allow
virtio-vhost-user to keep up with AF_UNIX vhost-user and grow because
it's easier to work with.

What do you think?



Thanks Stefan for the clarification.

I agree with idea of making one single device for all device types. 
Would you think it is also possible with vhost-pci? (Fundamentally, the 
duty of the device is to use a bar to expose the master guest memory, 
and passes the master vring address info and memory region info, which 
has no dependency on device types)


If you agree with the above, I think the main difference is what to pass 
to the driver. I think vhost-pci is simpler because it only passes the 
above mentioned info, which is sufficient.


Relaying needs to
1) pass all the vhost-user messages to the driver, and
2) requires the driver to join the vhost-user negotiation.
Without above two, the solution already works well, so I'm not sure why 
would we need the above two from functionality point of view.


Finally, either we choose vhost-pci or virtio-vhost-user, future 
developers will need to study vhost-user protocol and virtio spec (one 
device). This wouldn't make much difference, right?


Best,
Wei








Re: [Qemu-devel] [PATCH v14 5/9] target-arm: kvm64: inject synchronous External Abort

2018-01-10 Thread gengdongjiu
Hi Peter.

On 2018/1/10 1:30, Peter Maydell wrote:
> On 28 December 2017 at 05:54, Dongjiu Geng  wrote:
>> Add synchronous external abort injection logic, setup
>> exception type and syndrome value. When switch to guest,
>> guest will jump to the synchronous external abort vector
>> table entry.
>>
>> The ESR_ELx.DFSC is set to synchronous external abort(0x10),
>> and ESR_ELx.FnV is set to not valid(0x1), which will tell
>> guest that FAR is not valid and holds an UNKNOWN value.
>> These value will be set to KVM register structures through
>> KVM_SET_ONE_REG IOCTL.
>>
>> Signed-off-by: Dongjiu Geng 
>> ---
>> Marc is against that KVM inject the synchronous external abort(SEA) in [1],
>> so user space how to inject it. The test result that injection SEA to guest 
>> by Qemu
>> is shown in [2].
>>
>> [1]: https://lkml.org/lkml/2017/3/2/110
>> [2]:
>> Taking exception 4 [Data Abort]
>> ...from EL0 to EL1
>> ...with ESR 0x24/0x92000410
>> ...with FAR 0x0
>> ...with ELR 0x40cf04
>> ...to EL1 PC 0xffc84c00 PSTATE 0x3c5
>> after kvm_inject_arm_sea
>> Unhandled fault: synchronous external abort (0x92000410) at 
>> 0x007fa234c12c
>> CPU: 0 PID: 536 Comm: devmem Not tainted 4.1.0+ #20
>> Hardware name: linux,dummy-virt (DT)
>> task: ffc019ab2b00 ti: ffc008134000 task.ti: ffc008134000
>> PC is at 0x40cf04
>> LR is at 0x40cdec
>> pc : [<0040cf04>] lr : [<0040cdec>] pstate: 6000
>> sp : 007ff7b24130
>> x29: 007ff7b24260 x28: 
>> x27: 00ad x26: 0049c000
>> x25: 0048904b x24: 0049c000
>> x23: 4060 x22: 007ff7b243a0
>> x21: 0002 x20: 
>> x19: 0020 x18: 
>> x17: 0049c6d0 x16: 007fa22c85c0
>> x15: 5798 x14: 007fa2205f1c
>> x13: 007fa241ccb0 x12: 0137
>> x11:  x10: 
>> x9 :  x8 : 00de
>> x7 :  x6 : 2000
>> x5 : 4060 x4 : 0003
>> x3 : 0001 x2 : 
>> x1 :  x0 : 007fa2418000
>> ---
>>  target/arm/kvm64.c | 65 
>> ++
>>  1 file changed, 65 insertions(+)
>>
>> diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c
>> index a16abc8..c00450d 100644
>> --- a/target/arm/kvm64.c
>> +++ b/target/arm/kvm64.c
>> @@ -582,6 +582,71 @@ int kvm_arm_cpreg_level(uint64_t regidx)
>>  return KVM_PUT_RUNTIME_STATE;
>>  }
>>
>> +static int kvm_arm_cpreg_value(ARMCPU *cpu, ptrdiff_t fieldoffset)
>> +{
>> +int i;
>> +
>> +for (i = 0; i < cpu->cpreg_array_len; i++) {
> 
> This is still absolutely the wrong thing to do. Nothing should
> need to scan this array like this.
I will confirm that whether KVM mode will need this code, if not, I will remove 
this function.

> 
>> +uint32_t regidx = kvm_to_cpreg_id(cpu->cpreg_indexes[i]);
>> +const ARMCPRegInfo *ri;
>> +ri = get_arm_cp_reginfo(cpu->cp_regs, regidx);
>> +if (!ri) {
>> +continue;
>> +}
>> +
>> +if (ri->type & ARM_CP_NO_RAW) {
>> +continue;
>> +}
>> +
>> +if (ri->fieldoffset == fieldoffset) {
>> +cpu->cpreg_values[i] = read_raw_cp_reg(&cpu->env, ri);
>> +return 0;
>> +}
>> +}
>> +return -EINVAL;
>> +}
>> +
>> +/* Inject synchronous external abort */
>> +static void kvm_inject_arm_sea(CPUState *c)
>> +{
>> +ARMCPU *cpu = ARM_CPU(c);
>> +CPUARMState *env = &cpu->env;
>> +unsigned long cpsr = pstate_read(env);
>> +uint32_t esr, ret;
>> +
>> +/* This exception is synchronous data abort*/
> 
> Missing space before */
will fix it.

> 
>> +c->exception_index = EXCP_DATA_ABORT;
>> +/* Inject the exception to guest El1 */
> 
> "EL1", all caps.
will fix it.

> 
>> +env->exception.target_el = 1;
>> +CPUClass *cc = CPU_GET_CLASS(c);
> 
> Don't declare variables in the middle of the code -- check QEMU's
> CODING_STYLE doc for more info.
will fix it.

> 
>> +
>> +/* Set the DFSC to synchronous external abort and set FnV to not valid,
>> + * this will tell guest the FAR_ELx is UNKNOWN for this abort.
>> + */
>> +esr = (0x10 | (1 << 10));
>> +
>> +/* This exception comes from lower or current exception level. */
>> +if ((cpsr & 0xf) == PSTATE_MODE_EL0t) {
> 
> This looks like it'll be wrong for AArch32 guests (which you can
> still have with KVM with a 64-bit host), and even for AArch32
> userspace in a 64-bit guest. The correct way to find out what the
> current EL is is to use arm_current_el().
 sorry, in the OS(include guest OS), for software error recovery, we only 
support AArch64 kernel, not support AArch32
 kernel or AArch32 user space.

> 
>> +esr |= (EC_DATAABORT << ARM_EL_EC_SHIFT);
>> +} else {
>> +esr |= (EC_DATAABORT_SAME_EL << ARM_EL_EC_SHIFT);
>> +}
> 
> I'

[Qemu-devel] [PULL 04/11] ppc4xx_i2c: Implement basic I2C functions

2018-01-10 Thread David Gibson
From: BALATON Zoltan 

Enough to please U-Boot and make it able to detect SDRAM SPD EEPROMs

Signed-off-by: François Revol 
Signed-off-by: BALATON Zoltan 
Reviewed-by: David Gibson 
Signed-off-by: David Gibson 
---
 hw/i2c/ppc4xx_i2c.c | 198 +---
 include/hw/i2c/ppc4xx_i2c.h |   3 +
 2 files changed, 171 insertions(+), 30 deletions(-)

diff --git a/hw/i2c/ppc4xx_i2c.c b/hw/i2c/ppc4xx_i2c.c
index 5a6bde951e..e873a445da 100644
--- a/hw/i2c/ppc4xx_i2c.c
+++ b/hw/i2c/ppc4xx_i2c.c
@@ -2,6 +2,8 @@
  * PPC4xx I2C controller emulation
  *
  * Copyright (c) 2007 Jocelyn Mayer
+ * Copyright (c) 2012 François Revol
+ * Copyright (c) 2016 BALATON Zoltan
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to 
deal
@@ -25,26 +27,118 @@
 #include "qemu/osdep.h"
 #include "qapi/error.h"
 #include "qemu-common.h"
+#include "qemu/log.h"
 #include "cpu.h"
 #include "hw/hw.h"
 #include "hw/i2c/ppc4xx_i2c.h"
 
-/*#define DEBUG_I2C*/
+#define PPC4xx_I2C_MEM_SIZE 0x12
 
-#define PPC4xx_I2C_MEM_SIZE 0x11
+#define IIC_CNTL_PT (1 << 0)
+#define IIC_CNTL_READ   (1 << 1)
+#define IIC_CNTL_CHT(1 << 2)
+#define IIC_CNTL_RPST   (1 << 3)
+
+#define IIC_STS_PT  (1 << 0)
+#define IIC_STS_ERR (1 << 2)
+#define IIC_STS_MDBS(1 << 5)
+
+#define IIC_EXTSTS_XFRA (1 << 0)
+
+#define IIC_XTCNTLSS_SRST   (1 << 0)
+
+static void ppc4xx_i2c_reset(DeviceState *s)
+{
+PPC4xxI2CState *i2c = PPC4xx_I2C(s);
+
+/* FIXME: Should also reset bus?
+ *if (s->address != ADDR_RESET) {
+ *i2c_end_transfer(s->bus);
+ *}
+ */
+
+i2c->mdata = 0;
+i2c->lmadr = 0;
+i2c->hmadr = 0;
+i2c->cntl = 0;
+i2c->mdcntl = 0;
+i2c->sts = 0;
+i2c->extsts = 0x8f;
+i2c->sdata = 0;
+i2c->lsadr = 0;
+i2c->hsadr = 0;
+i2c->clkdiv = 0;
+i2c->intrmsk = 0;
+i2c->xfrcnt = 0;
+i2c->xtcntlss = 0;
+i2c->directcntl = 0x0f;
+i2c->intr = 0;
+}
+
+static inline bool ppc4xx_i2c_is_master(PPC4xxI2CState *i2c)
+{
+return true;
+}
 
 static uint64_t ppc4xx_i2c_readb(void *opaque, hwaddr addr, unsigned int size)
 {
 PPC4xxI2CState *i2c = PPC4xx_I2C(opaque);
 uint64_t ret;
 
-#ifdef DEBUG_I2C
-printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
-#endif
 switch (addr) {
 case 0x00:
-/*i2c_readbyte(&i2c->mdata);*/
 ret = i2c->mdata;
+if (ppc4xx_i2c_is_master(i2c)) {
+ret = 0xff;
+
+if (!(i2c->sts & IIC_STS_MDBS)) {
+qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Trying to read "
+  "without starting transfer\n",
+  TYPE_PPC4xx_I2C, __func__);
+} else {
+int pending = (i2c->cntl >> 4) & 3;
+
+/* get the next byte */
+int byte = i2c_recv(i2c->bus);
+
+if (byte < 0) {
+qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: read failed "
+  "for device 0x%02x\n", TYPE_PPC4xx_I2C,
+  __func__, i2c->lmadr);
+ret = 0xff;
+} else {
+ret = byte;
+/* Raise interrupt if enabled */
+/*ppc4xx_i2c_raise_interrupt(i2c)*/;
+}
+
+if (!pending) {
+i2c->sts &= ~IIC_STS_MDBS;
+/*i2c_end_transfer(i2c->bus);*/
+/*} else if (i2c->cntl & (IIC_CNTL_RPST | IIC_CNTL_CHT)) {*/
+} else if (pending) {
+/* current smbus implementation doesn't like
+   multibyte xfer repeated start */
+i2c_end_transfer(i2c->bus);
+if (i2c_start_transfer(i2c->bus, i2c->lmadr >> 1, 1)) {
+/* if non zero is returned, the adress is not valid */
+i2c->sts &= ~IIC_STS_PT;
+i2c->sts |= IIC_STS_ERR;
+i2c->extsts |= IIC_EXTSTS_XFRA;
+} else {
+/*i2c->sts |= IIC_STS_PT;*/
+i2c->sts |= IIC_STS_MDBS;
+i2c->sts &= ~IIC_STS_ERR;
+i2c->extsts = 0;
+}
+}
+pending--;
+i2c->cntl = (i2c->cntl & 0xcf) | (pending << 4);
+}
+} else {
+qemu_log_mask(LOG_UNIMP, "[%s]%s: slave mode not implemented\n",
+  TYPE_PPC4xx_I2C, __func__);
+}
 break;
 case 0x02:
 ret = i2c->sdata;
@@ -88,13 +182,15 @@ static uint64_t ppc4xx_i2c_readb(void *opaque, hwaddr 
addr, unsigned int size)
 case 0x10:
 ret = i2c->directcntl;
 break;
+case 0x11:
+ret = i2c->i

[Qemu-devel] [PULL 11/11] spapr: Correct compatibility mode setting for hotplugged CPUs

2018-01-10 Thread David Gibson
Currently the pseries machine sets the compatibility mode for the
guest's cpus in two places: 1) at machine reset and 2) after CAS
negotiation.

This means that if we set or negotiate a compatiblity mode, then
hotplug a cpu, the hotplugged cpu doesn't get the right mode set and
will incorrectly have the full native features.

To correct this, we set the compatibility mode on a cpu when it is
brought online with the 'start-cpu' RTAS call.  Given that we no
longer need to set the compatibility mode on all CPUs at machine
reset, so we change that to only set the mode for the boot cpu.

Signed-off-by: David Gibson 
Reported-by: Satheesh Rajendran 
Tested-by: Satheesh Rajendran 
Reviewed-by: Alexey Kardashevskiy 
---
 hw/ppc/spapr.c  | 2 +-
 hw/ppc/spapr_rtas.c | 9 +
 2 files changed, 10 insertions(+), 1 deletion(-)

diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index 6785a90c60..dfd352c473 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -1504,7 +1504,7 @@ static void spapr_machine_reset(void)
 spapr_ovec_cleanup(spapr->ov5_cas);
 spapr->ov5_cas = spapr_ovec_new();
 
-ppc_set_compat_all(spapr->max_compat_pvr, &error_fatal);
+ppc_set_compat(first_ppc_cpu, spapr->max_compat_pvr, &error_fatal);
 }
 
 fdt = spapr_build_fdt(spapr, rtas_addr, spapr->rtas_size);
diff --git a/hw/ppc/spapr_rtas.c b/hw/ppc/spapr_rtas.c
index 4bb939d3d1..2b89e1d448 100644
--- a/hw/ppc/spapr_rtas.c
+++ b/hw/ppc/spapr_rtas.c
@@ -163,6 +163,7 @@ static void rtas_start_cpu(PowerPCCPU *cpu_, 
sPAPRMachineState *spapr,
 CPUState *cs = CPU(cpu);
 CPUPPCState *env = &cpu->env;
 PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
+Error *local_err = NULL;
 
 if (!cs->halted) {
 rtas_st(rets, 0, RTAS_OUT_HW_ERROR);
@@ -174,6 +175,14 @@ static void rtas_start_cpu(PowerPCCPU *cpu_, 
sPAPRMachineState *spapr,
  * new cpu enters */
 kvm_cpu_synchronize_state(cs);
 
+/* Set compatibility mode to match existing cpus */
+ppc_set_compat(cpu, POWERPC_CPU(first_cpu)->compat_pvr, &local_err);
+if (local_err) {
+error_report_err(local_err);
+rtas_st(rets, 0, RTAS_OUT_HW_ERROR);
+return;
+}
+
 env->msr = (1ULL << MSR_SF) | (1ULL << MSR_ME);
 
 /* Enable Power-saving mode Exit Cause exceptions for the new CPU */
-- 
2.14.3




[Qemu-devel] [PULL 07/11] ppc/pnv: change powernv_ prefix to pnv_ for overall naming consistency

2018-01-10 Thread David Gibson
From: Cédric Le Goater 

The 'pnv' prefix is now used for all and the routines populating the
device tree start with 'pnv_dt'. The handler of the PnvXScomInterface
is also renamed to 'dt_xscom' which should reflect that it is
populating the device tree under the 'xscom@' node of the chip.

Signed-off-by: Cédric Le Goater 
Signed-off-by: David Gibson 
---
 hw/ppc/pnv.c   | 94 ++
 hw/ppc/pnv_bmc.c   |  2 +-
 hw/ppc/pnv_core.c  |  8 ++--
 hw/ppc/pnv_lpc.c   |  6 +--
 hw/ppc/pnv_psi.c   |  4 +-
 hw/ppc/pnv_xscom.c | 10 ++---
 include/hw/ppc/pnv.h   | 10 ++---
 include/hw/ppc/pnv_xscom.h |  4 +-
 8 files changed, 67 insertions(+), 71 deletions(-)

diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c
index 94ffc8e137..9475e8479c 100644
--- a/hw/ppc/pnv.c
+++ b/hw/ppc/pnv.c
@@ -77,8 +77,7 @@ static const char *pnv_chip_core_typename(const PnvChip *o)
  * that has a different "affinity". In practice, it means one range
  * per chip.
  */
-static void powernv_populate_memory_node(void *fdt, int chip_id, hwaddr start,
- hwaddr size)
+static void pnv_dt_memory(void *fdt, int chip_id, hwaddr start, hwaddr size)
 {
 char *mem_name;
 uint64_t mem_reg_property[2];
@@ -119,7 +118,7 @@ static int get_cpus_node(void *fdt)
  * device tree, used in XSCOM to address cores and in interrupt
  * servers.
  */
-static void powernv_create_core_node(PnvChip *chip, PnvCore *pc, void *fdt)
+static void pnv_dt_core(PnvChip *chip, PnvCore *pc, void *fdt)
 {
 CPUState *cs = CPU(DEVICE(pc->threads));
 DeviceClass *dc = DEVICE_GET_CLASS(cs);
@@ -228,8 +227,8 @@ static void powernv_create_core_node(PnvChip *chip, PnvCore 
*pc, void *fdt)
servers_prop, sizeof(servers_prop;
 }
 
-static void powernv_populate_icp(PnvChip *chip, void *fdt, uint32_t pir,
- uint32_t nr_threads)
+static void pnv_dt_icp(PnvChip *chip, void *fdt, uint32_t pir,
+   uint32_t nr_threads)
 {
 uint64_t addr = PNV_ICP_BASE(chip) | (pir << 12);
 char *name;
@@ -277,13 +276,13 @@ static int pnv_chip_lpc_offset(PnvChip *chip, void *fdt)
 return offset;
 }
 
-static void powernv_populate_chip(PnvChip *chip, void *fdt)
+static void pnv_dt_chip(PnvChip *chip, void *fdt)
 {
 const char *typename = pnv_chip_core_typename(chip);
 size_t typesize = object_type_get_instance_size(typename);
 int i;
 
-pnv_xscom_populate(chip, fdt, 0);
+pnv_dt_xscom(chip, fdt, 0);
 
 /* The default LPC bus of a multichip system is on chip 0. It's
  * recognized by the firmware (skiboot) using a "primary"
@@ -298,20 +297,18 @@ static void powernv_populate_chip(PnvChip *chip, void 
*fdt)
 for (i = 0; i < chip->nr_cores; i++) {
 PnvCore *pnv_core = PNV_CORE(chip->cores + i * typesize);
 
-powernv_create_core_node(chip, pnv_core, fdt);
+pnv_dt_core(chip, pnv_core, fdt);
 
 /* Interrupt Control Presenters (ICP). One per core. */
-powernv_populate_icp(chip, fdt, pnv_core->pir,
- CPU_CORE(pnv_core)->nr_threads);
+pnv_dt_icp(chip, fdt, pnv_core->pir, CPU_CORE(pnv_core)->nr_threads);
 }
 
 if (chip->ram_size) {
-powernv_populate_memory_node(fdt, chip->chip_id, chip->ram_start,
- chip->ram_size);
+pnv_dt_memory(fdt, chip->chip_id, chip->ram_start, chip->ram_size);
 }
 }
 
-static void powernv_populate_rtc(ISADevice *d, void *fdt, int lpc_off)
+static void pnv_dt_rtc(ISADevice *d, void *fdt, int lpc_off)
 {
 uint32_t io_base = d->ioport_id;
 uint32_t io_regs[] = {
@@ -331,7 +328,7 @@ static void powernv_populate_rtc(ISADevice *d, void *fdt, 
int lpc_off)
 _FDT((fdt_setprop_string(fdt, node, "compatible", "pnpPNP,b00")));
 }
 
-static void powernv_populate_serial(ISADevice *d, void *fdt, int lpc_off)
+static void pnv_dt_serial(ISADevice *d, void *fdt, int lpc_off)
 {
 const char compatible[] = "ns16550\0pnpPNP,501";
 uint32_t io_base = d->ioport_id;
@@ -362,7 +359,7 @@ static void powernv_populate_serial(ISADevice *d, void 
*fdt, int lpc_off)
 _FDT((fdt_setprop_string(fdt, node, "device_type", "serial")));
 }
 
-static void powernv_populate_ipmi_bt(ISADevice *d, void *fdt, int lpc_off)
+static void pnv_dt_ipmi_bt(ISADevice *d, void *fdt, int lpc_off)
 {
 const char compatible[] = "bt\0ipmi-bt";
 uint32_t io_base;
@@ -401,17 +398,17 @@ typedef struct ForeachPopulateArgs {
 int offset;
 } ForeachPopulateArgs;
 
-static int powernv_populate_isa_device(DeviceState *dev, void *opaque)
+static int pnv_dt_isa_device(DeviceState *dev, void *opaque)
 {
 ForeachPopulateArgs *args = opaque;
 ISADevice *d = ISA_DEVICE(dev);
 
 if (object_dynamic_cast(OBJECT(dev), TYPE_MC146818_RTC)) {
-powernv_populate_rtc(d, args->fdt, args->offset);
+pnv_dt_rtc(d, args->fdt, a

[Qemu-devel] [PULL 06/11] hw/ide: Emulate SiI3112 SATA controller

2018-01-10 Thread David Gibson
From: BALATON Zoltan 

This is a common generic PCI SATA controller that is also used in PCs
but more importantly guests running on the Sam460ex board prefer this
card and have a driver for it (unlike for other SATA controllers
already emulated).

Signed-off-by: BALATON Zoltan 
Acked-by: John Snow 
Signed-off-by: David Gibson 
---
 MAINTAINERS|   6 +
 default-configs/ppcemb-softmmu.mak |   1 +
 hw/ide/Makefile.objs   |   1 +
 hw/ide/sii3112.c   | 368 +
 hw/ide/trace-events|   5 +
 5 files changed, 381 insertions(+)
 create mode 100644 hw/ide/sii3112.c

diff --git a/MAINTAINERS b/MAINTAINERS
index bc2d3a4ef1..8ab86930e4 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -765,6 +765,12 @@ L: qemu-...@nongnu.org
 S: Odd Fixes
 F: hw/ppc/virtex_ml507.c
 
+sam460ex
+M: BALATON Zoltan 
+L: qemu-...@nongnu.org
+S: Maintained
+F: hw/ide/sii3112.c
+
 SH4 Machines
 
 R2D
diff --git a/default-configs/ppcemb-softmmu.mak 
b/default-configs/ppcemb-softmmu.mak
index 13917fb7a3..5db4618a5a 100644
--- a/default-configs/ppcemb-softmmu.mak
+++ b/default-configs/ppcemb-softmmu.mak
@@ -16,3 +16,4 @@ CONFIG_I8259=y
 CONFIG_XILINX=y
 CONFIG_XILINX_ETHLITE=y
 CONFIG_SM501=y
+CONFIG_IDE_SII3112=y
diff --git a/hw/ide/Makefile.objs b/hw/ide/Makefile.objs
index f0edca3300..fc328ffbe8 100644
--- a/hw/ide/Makefile.objs
+++ b/hw/ide/Makefile.objs
@@ -11,3 +11,4 @@ common-obj-$(CONFIG_MICRODRIVE) += microdrive.o
 common-obj-$(CONFIG_AHCI) += ahci.o
 common-obj-$(CONFIG_AHCI) += ich.o
 common-obj-$(CONFIG_ALLWINNER_A10) += ahci-allwinner.o
+common-obj-$(CONFIG_IDE_SII3112) += sii3112.o
diff --git a/hw/ide/sii3112.c b/hw/ide/sii3112.c
new file mode 100644
index 00..e2f5562bb7
--- /dev/null
+++ b/hw/ide/sii3112.c
@@ -0,0 +1,368 @@
+/*
+ * QEMU SiI3112A PCI to Serial ATA Controller Emulation
+ *
+ * Copyright (C) 2017 BALATON Zoltan 
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ */
+
+/* For documentation on this and similar cards see:
+ * http://wiki.osdev.org/User:Quok/Silicon_Image_Datasheets
+ */
+
+#include 
+#include 
+#include "trace.h"
+
+#define TYPE_SII3112_PCI "sii3112"
+#define SII3112_PCI(obj) OBJECT_CHECK(SiI3112PCIState, (obj), \
+ TYPE_SII3112_PCI)
+
+typedef struct SiI3112Regs {
+uint32_t confstat;
+uint32_t scontrol;
+uint16_t sien;
+uint8_t swdata;
+} SiI3112Regs;
+
+typedef struct SiI3112PCIState {
+PCIIDEState i;
+MemoryRegion mmio;
+SiI3112Regs regs[2];
+} SiI3112PCIState;
+
+/* The sii3112_reg_read and sii3112_reg_write functions implement the
+ * Internal Register Space - BAR5 (section 6.7 of the data sheet).
+ */
+
+static uint64_t sii3112_reg_read(void *opaque, hwaddr addr,
+unsigned int size)
+{
+SiI3112PCIState *d = opaque;
+uint64_t val = 0;
+
+switch (addr) {
+case 0x00:
+val = d->i.bmdma[0].cmd;
+break;
+case 0x01:
+val = d->regs[0].swdata;
+break;
+case 0x02:
+val = d->i.bmdma[0].status;
+break;
+case 0x03:
+val = 0;
+break;
+case 0x04 ... 0x07:
+val = bmdma_addr_ioport_ops.read(&d->i.bmdma[0], addr - 4, size);
+break;
+case 0x08:
+val = d->i.bmdma[1].cmd;
+break;
+case 0x09:
+val = d->regs[1].swdata;
+break;
+case 0x0a:
+val = d->i.bmdma[1].status;
+break;
+case 0x0b:
+val = 0;
+break;
+case 0x0c ... 0x0f:
+val = bmdma_addr_ioport_ops.read(&d->i.bmdma[1], addr - 12, size);
+break;
+case 0x10:
+val = d->i.bmdma[0].cmd;
+val |= (d->regs[0].confstat & (1UL << 11) ? (1 << 4) : 0); /*SATAINT0*/
+val |= (d->regs[1].confstat & (1UL << 11) ? (1 << 6) : 0); /*SATAINT1*/
+val |= (d->i.bmdma[1].status & BM_STATUS_INT ? (1 << 14) : 0);
+val |= d->i.bmdma[0].status << 16;
+val |= d->i.bmdma[1].status << 24;
+break;
+case 0x18:
+val = d->i.bmdma[1].cmd;
+val |= (d->regs[1].confstat & (1UL << 11) ? (1 << 4) : 0);
+val |= d->i.bmdma[1].status << 16;
+break;
+case 0x80 ... 0x87:
+if (size == 1) {
+val = ide_ioport_read(&d->i.bus[0], addr - 0x80);
+} else if (addr == 0x80) {
+val = (size == 2) ? ide_data_readw(&d->i.bus[0], 0) :
+ide_data_readl(&d->i.bus[0], 0);
+} else {
+val = (1ULL << (size * 8)) - 1;
+}
+break;
+case 0x8a:
+val = (size == 1) ? ide_status_read(&d->i.bus[0], 4) :
+(1ULL << (size * 8)) - 1;
+break;
+case 0xa0:
+val = d->regs[0].confstat;
+break;
+case 0xc0 ... 0xc7:
+if (size == 1) {
+val = ide_ioport_read(&d->i.bu

[Qemu-devel] [PULL 08/11] target/ppc: more use of the PPC_*() macros

2018-01-10 Thread David Gibson
From: Cédric Le Goater 

Also introduce utilities to manipulate bitmasks (originaly from OPAL)
which be will be used in the model of the XIVE interrupt controller.

Signed-off-by: Cédric Le Goater 
Signed-off-by: David Gibson 
---
 hw/ppc/pnv_lpc.c| 10 -
 target/ppc/cpu.h| 56 ++---
 target/ppc/int_helper.c |  2 +-
 3 files changed, 40 insertions(+), 28 deletions(-)

diff --git a/hw/ppc/pnv_lpc.c b/hw/ppc/pnv_lpc.c
index b777b78e18..c42b4a8f6c 100644
--- a/hw/ppc/pnv_lpc.c
+++ b/hw/ppc/pnv_lpc.c
@@ -146,13 +146,13 @@ static bool opb_write(PnvLpcController *lpc, uint32_t 
addr, uint8_t *data,
 return success;
 }
 
-#define ECCB_CTL_READ   (1ull << (63 - 15))
+#define ECCB_CTL_READ   PPC_BIT(15)
 #define ECCB_CTL_SZ_LSH (63 - 7)
-#define ECCB_CTL_SZ_MASK(0xfull << ECCB_CTL_SZ_LSH)
-#define ECCB_CTL_ADDR_MASK  0xu;
+#define ECCB_CTL_SZ_MASKPPC_BITMASK(4, 7)
+#define ECCB_CTL_ADDR_MASK  PPC_BITMASK(32, 63)
 
-#define ECCB_STAT_OP_DONE   (1ull << (63 - 52))
-#define ECCB_STAT_OP_ERR(1ull << (63 - 52))
+#define ECCB_STAT_OP_DONE   PPC_BIT(52)
+#define ECCB_STAT_OP_ERRPPC_BIT(52)
 #define ECCB_STAT_RD_DATA_LSH   (63 - 37)
 #define ECCB_STAT_RD_DATA_MASK  (0x << ECCB_STAT_RD_DATA_LSH)
 
diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
index 370b05e76e..a5e49f23e9 100644
--- a/target/ppc/cpu.h
+++ b/target/ppc/cpu.h
@@ -93,6 +93,19 @@
 #define PPC_BITMASK(bs, be) ((PPC_BIT(bs) - PPC_BIT(be)) | PPC_BIT(bs))
 #define PPC_BITMASK32(bs, be)   ((PPC_BIT32(bs) - PPC_BIT32(be)) | \
  PPC_BIT32(bs))
+#define PPC_BITMASK8(bs, be)((PPC_BIT8(bs) - PPC_BIT8(be)) | PPC_BIT8(bs))
+
+#if HOST_LONG_BITS == 32
+# define MASK_TO_LSH(m)  (__builtin_ffsll(m) - 1)
+#elif HOST_LONG_BITS == 64
+# define MASK_TO_LSH(m)  (__builtin_ffsl(m) - 1)
+#else
+# error Unknown sizeof long
+#endif
+
+#define GETFIELD(m, v)  (((v) & (m)) >> MASK_TO_LSH(m))
+#define SETFIELD(m, v, val) \
+(((v) & ~(m)) | typeof(v))(val)) << MASK_TO_LSH(m)) & (m)))
 
 /*/
 /* Exception vectors definitions */
@@ -2349,32 +2362,31 @@ enum {
 
 /* Processor Compatibility mask (PCR) */
 enum {
-PCR_COMPAT_2_05 = 1ull << (63-62),
-PCR_COMPAT_2_06 = 1ull << (63-61),
-PCR_COMPAT_2_07 = 1ull << (63-60),
-PCR_COMPAT_3_00 = 1ull << (63-59),
-PCR_VEC_DIS = 1ull << (63-0), /* Vec. disable (bit NA since 
POWER8) */
-PCR_VSX_DIS = 1ull << (63-1), /* VSX disable (bit NA since POWER8) 
*/
-PCR_TM_DIS  = 1ull << (63-2), /* Trans. memory disable (POWER8) */
+PCR_COMPAT_2_05 = PPC_BIT(62),
+PCR_COMPAT_2_06 = PPC_BIT(61),
+PCR_COMPAT_2_07 = PPC_BIT(60),
+PCR_COMPAT_3_00 = PPC_BIT(59),
+PCR_VEC_DIS = PPC_BIT(0), /* Vec. disable (bit NA since POWER8) */
+PCR_VSX_DIS = PPC_BIT(1), /* VSX disable (bit NA since POWER8) */
+PCR_TM_DIS  = PPC_BIT(2), /* Trans. memory disable (POWER8) */
 };
 
 /* HMER/HMEER */
 enum {
-HMER_MALFUNCTION_ALERT  = 1ull << (63 - 0),
-HMER_PROC_RECV_DONE = 1ull << (63 - 2),
-HMER_PROC_RECV_ERROR_MASKED = 1ull << (63 - 3),
-HMER_TFAC_ERROR = 1ull << (63 - 4),
-HMER_TFMR_PARITY_ERROR  = 1ull << (63 - 5),
-HMER_XSCOM_FAIL = 1ull << (63 - 8),
-HMER_XSCOM_DONE = 1ull << (63 - 9),
-HMER_PROC_RECV_AGAIN= 1ull << (63 - 11),
-HMER_WARN_RISE  = 1ull << (63 - 14),
-HMER_WARN_FALL  = 1ull << (63 - 15),
-HMER_SCOM_FIR_HMI   = 1ull << (63 - 16),
-HMER_TRIG_FIR_HMI   = 1ull << (63 - 17),
-HMER_HYP_RESOURCE_ERR   = 1ull << (63 - 20),
-HMER_XSCOM_STATUS_MASK  = 7ull << (63 - 23),
-HMER_XSCOM_STATUS_LSH   = (63 - 23),
+HMER_MALFUNCTION_ALERT  = PPC_BIT(0),
+HMER_PROC_RECV_DONE = PPC_BIT(2),
+HMER_PROC_RECV_ERROR_MASKED = PPC_BIT(3),
+HMER_TFAC_ERROR = PPC_BIT(4),
+HMER_TFMR_PARITY_ERROR  = PPC_BIT(5),
+HMER_XSCOM_FAIL = PPC_BIT(8),
+HMER_XSCOM_DONE = PPC_BIT(9),
+HMER_PROC_RECV_AGAIN= PPC_BIT(11),
+HMER_WARN_RISE  = PPC_BIT(14),
+HMER_WARN_FALL  = PPC_BIT(15),
+HMER_SCOM_FIR_HMI   = PPC_BIT(16),
+HMER_TRIG_FIR_HMI   = PPC_BIT(17),
+HMER_HYP_RESOURCE_ERR   = PPC_BIT(20),
+HMER_XSCOM_STATUS_MASK  = PPC_BITMASK(21, 23),
 };
 
 /* Alternate Interrupt Location (AIL) */
diff --git a/target/ppc/int_helper.c b/target/ppc/int_helper.c
index 1c013a0ee3..3a50f1e1b7 100644
--- a/target/ppc/int_helper.c
+++ b/target/ppc/int_helper.c
@@ -183,7 +183,7 @@ uint64

[Qemu-devel] [PULL 03/11] sm501: Add some more unimplemented registers

2018-01-10 Thread David Gibson
From: BALATON Zoltan 

These are not really implemented (just return zero or default values)
but add these so guests accessing them can run.

Signed-off-by: BALATON Zoltan 
Signed-off-by: David Gibson 
---
 hw/display/sm501.c | 17 +
 1 file changed, 17 insertions(+)

diff --git a/hw/display/sm501.c b/hw/display/sm501.c
index b9b611131e..4f7dc59b25 100644
--- a/hw/display/sm501.c
+++ b/hw/display/sm501.c
@@ -795,6 +795,8 @@ static uint64_t sm501_system_config_read(void *opaque, 
hwaddr addr,
 case SM501_ARBTRTN_CONTROL:
 ret = s->arbitration_control;
 break;
+case SM501_COMMAND_LIST_STATUS:
+ret = 0x00180002; /* FIFOs are empty, everything idle */
 case SM501_IRQ_MASK:
 ret = s->irq_mask;
 break;
@@ -812,6 +814,9 @@ static uint64_t sm501_system_config_read(void *opaque, 
hwaddr addr,
 case SM501_POWER_MODE_CONTROL:
 ret = s->power_mode_control;
 break;
+case SM501_ENDIAN_CONTROL:
+ret = 0; /* Only default little endian mode is supported */
+break;
 
 default:
 printf("sm501 system config : not implemented register read."
@@ -865,6 +870,12 @@ static void sm501_system_config_write(void *opaque, hwaddr 
addr,
 case SM501_POWER_MODE_CONTROL:
 s->power_mode_control = value & 0x0003;
 break;
+case SM501_ENDIAN_CONTROL:
+if (value & 0x0001) {
+printf("sm501 system config : big endian mode not implemented.\n");
+abort();
+}
+break;
 
 default:
 printf("sm501 system config : not implemented register write."
@@ -924,6 +935,9 @@ static uint64_t sm501_disp_ctrl_read(void *opaque, hwaddr 
addr,
 case SM501_DC_PANEL_PANNING_CONTROL:
 ret = s->dc_panel_panning_control;
 break;
+case SM501_DC_PANEL_COLOR_KEY:
+/* Not implemented yet */
+break;
 case SM501_DC_PANEL_FB_ADDR:
 ret = s->dc_panel_fb_addr;
 break;
@@ -1035,6 +1049,9 @@ static void sm501_disp_ctrl_write(void *opaque, hwaddr 
addr,
 case SM501_DC_PANEL_PANNING_CONTROL:
 s->dc_panel_panning_control = value & 0xFF3FFF3F;
 break;
+case SM501_DC_PANEL_COLOR_KEY:
+/* Not implemented yet */
+break;
 case SM501_DC_PANEL_FB_ADDR:
 s->dc_panel_fb_addr = value & 0x8FF0;
 break;
-- 
2.14.3




[Qemu-devel] [PULL 10/11] hw/ppc: Remove the deprecated spapr-pci-vfio-host-bridge device

2018-01-10 Thread David Gibson
From: Thomas Huth 

It's a deprecated dummy device since QEMU v2.6.0. That should have
been enough time to allow the users to update their scripts in case
they still use it, so let's remove this legacy code now.

Reviewed-by: Alexey Kardashevskiy 
Signed-off-by: Thomas Huth 
Signed-off-by: David Gibson 
---
 hw/ppc/spapr_pci_vfio.c   | 47 ---
 qemu-doc.texi |  5 -
 scripts/device-crash-test |  1 -
 3 files changed, 53 deletions(-)

diff --git a/hw/ppc/spapr_pci_vfio.c b/hw/ppc/spapr_pci_vfio.c
index 1f775ea93d..053efb03bd 100644
--- a/hw/ppc/spapr_pci_vfio.c
+++ b/hw/ppc/spapr_pci_vfio.c
@@ -29,31 +29,6 @@
 #include "qemu/error-report.h"
 #include "sysemu/qtest.h"
 
-#define TYPE_SPAPR_PCI_VFIO_HOST_BRIDGE "spapr-pci-vfio-host-bridge"
-
-#define SPAPR_PCI_VFIO_HOST_BRIDGE(obj) \
-OBJECT_CHECK(sPAPRPHBVFIOState, (obj), TYPE_SPAPR_PCI_VFIO_HOST_BRIDGE)
-
-typedef struct sPAPRPHBVFIOState sPAPRPHBVFIOState;
-
-struct sPAPRPHBVFIOState {
-sPAPRPHBState phb;
-
-int32_t iommugroupid;
-};
-
-static Property spapr_phb_vfio_properties[] = {
-DEFINE_PROP_INT32("iommu", sPAPRPHBVFIOState, iommugroupid, -1),
-DEFINE_PROP_END_OF_LIST(),
-};
-
-static void spapr_phb_vfio_instance_init(Object *obj)
-{
-if (!qtest_enabled()) {
-warn_report("spapr-pci-vfio-host-bridge is deprecated");
-}
-}
-
 bool spapr_phb_eeh_available(sPAPRPHBState *sphb)
 {
 return vfio_eeh_as_ok(&sphb->iommu_as);
@@ -218,25 +193,3 @@ int spapr_phb_vfio_eeh_configure(sPAPRPHBState *sphb)
 
 return RTAS_OUT_SUCCESS;
 }
-
-static void spapr_phb_vfio_class_init(ObjectClass *klass, void *data)
-{
-DeviceClass *dc = DEVICE_CLASS(klass);
-
-dc->props = spapr_phb_vfio_properties;
-}
-
-static const TypeInfo spapr_phb_vfio_info = {
-.name  = TYPE_SPAPR_PCI_VFIO_HOST_BRIDGE,
-.parent= TYPE_SPAPR_PCI_HOST_BRIDGE,
-.instance_size = sizeof(sPAPRPHBVFIOState),
-.instance_init = spapr_phb_vfio_instance_init,
-.class_init= spapr_phb_vfio_class_init,
-};
-
-static void spapr_pci_vfio_register_types(void)
-{
-type_register_static(&spapr_phb_vfio_info);
-}
-
-type_init(spapr_pci_vfio_register_types)
diff --git a/qemu-doc.texi b/qemu-doc.texi
index 9d0159832e..a3d2054c90 100644
--- a/qemu-doc.texi
+++ b/qemu-doc.texi
@@ -2757,11 +2757,6 @@ The ``host_net_remove'' command is replaced by the 
``netdev_del'' command.
 The ``ivshmem'' device type is replaced by either the ``ivshmem-plain''
 or ``ivshmem-doorbell`` device types.
 
-@subsection spapr-pci-vfio-host-bridge (since 2.6.0)
-
-The ``spapr-pci-vfio-host-bridge'' device type is replaced by
-the ``spapr-pci-host-bridge'' device type.
-
 @section System emulator machines
 
 @subsection Xilinx EP108 (since 2.11.0)
diff --git a/scripts/device-crash-test b/scripts/device-crash-test
index c11fd81c52..827d8ec2af 100755
--- a/scripts/device-crash-test
+++ b/scripts/device-crash-test
@@ -119,7 +119,6 @@ ERROR_WHITELIST = [
 {'device':'scsi-generic', 'expected':True},# drive property 
not set
 {'device':'scsi-hd', 'expected':True}, # drive property 
not set
 {'device':'spapr-pci-host-bridge', 'expected':True},   # BUID not 
specified for PHB
-{'device':'spapr-pci-vfio-host-bridge', 'expected':True}, # BUID not 
specified for PHB
 {'device':'spapr-rng', 'expected':True},   # spapr-rng needs 
an RNG backend!
 {'device':'spapr-vty', 'expected':True},   # chardev property 
not set
 {'device':'tpm-tis', 'expected':True}, # tpm_tis: backend 
driver with id (null) could not be found
-- 
2.14.3




[Qemu-devel] [PULL 05/11] spapr_pci: use warn_report()

2018-01-10 Thread David Gibson
From: Greg Kurz 

These two are definitely warnings. Let's use the appropriate API.

Signed-off-by: Greg Kurz 
Signed-off-by: David Gibson 
---
 hw/ppc/spapr_pci.c  | 6 +++---
 hw/ppc/spapr_pci_vfio.c | 2 +-
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c
index 88797b3d36..695c820911 100644
--- a/hw/ppc/spapr_pci.c
+++ b/hw/ppc/spapr_pci.c
@@ -1696,9 +1696,9 @@ static void spapr_phb_realize(DeviceState *dev, Error 
**errp)
 /* DMA setup */
 if (((sphb->page_size_mask & qemu_getrampagesize()) == 0)
 && kvm_enabled()) {
-error_report("System page size 0x%lx is not enabled in page_size_mask "
- "(0x%"PRIx64"). Performance may be slow",
- qemu_getrampagesize(), sphb->page_size_mask);
+warn_report("System page size 0x%lx is not enabled in page_size_mask "
+"(0x%"PRIx64"). Performance may be slow",
+qemu_getrampagesize(), sphb->page_size_mask);
 }
 
 for (i = 0; i < windows_supported; ++i) {
diff --git a/hw/ppc/spapr_pci_vfio.c b/hw/ppc/spapr_pci_vfio.c
index 8448e0b024..1f775ea93d 100644
--- a/hw/ppc/spapr_pci_vfio.c
+++ b/hw/ppc/spapr_pci_vfio.c
@@ -50,7 +50,7 @@ static Property spapr_phb_vfio_properties[] = {
 static void spapr_phb_vfio_instance_init(Object *obj)
 {
 if (!qtest_enabled()) {
-error_report("spapr-pci-vfio-host-bridge is deprecated");
+warn_report("spapr-pci-vfio-host-bridge is deprecated");
 }
 }
 
-- 
2.14.3




[Qemu-devel] [PULL 00/11] ppc-for-2.12 queue 20180111

2018-01-10 Thread David Gibson
The following changes since commit 3cee4db661ab9c0fce7937b3bbfa188a1845f31f:

  Merge remote-tracking branch 'remotes/ericb/tags/pull-nbd-2018-01-08' into 
staging (2018-01-09 15:22:47 +)

are available in the Git repository at:

  git://github.com/dgibson/qemu.git tags/ppc-for-2.12-20180111

for you to fetch changes up to 51f84465dd985fc21589b2eac1f18658fc9783e9:

  spapr: Correct compatibility mode setting for hotplugged CPUs (2018-01-10 
12:53:00 +1100)


ppc patch queue 2018-01-11

This pull request supersedes ppc-for-2.12-20180108 and several before
it.  The earlier pull request included a patch which exposed a bug in
the ARM TCG backend.  I've pulled that out and will repost once the
ARM bug is fixed (a patch has been posted by Richard Henderson).

Higlights from this series:
  * SLOF update
  * Several new devices for embedded platforms
  * Fix to correctly set compatiblity mode for hotplugged CPUs
  * dtc compile fix for older MacOS versions


Alexey Kardashevskiy (1):
  pseries: Update SLOF firmware image to qemu-slof-20171214

BALATON Zoltan (4):
  sm501: Add panel hardware cursor registers also to read function
  sm501: Add some more unimplemented registers
  ppc4xx_i2c: Implement basic I2C functions
  hw/ide: Emulate SiI3112 SATA controller

Cédric Le Goater (2):
  ppc/pnv: change powernv_ prefix to pnv_ for overall naming consistency
  target/ppc: more use of the PPC_*() macros

David Gibson (1):
  spapr: Correct compatibility mode setting for hotplugged CPUs

Greg Kurz (1):
  spapr_pci: use warn_report()

John Arbuckle (1):
  Update dtc to fix compilation problem on Mac OS 10.6

Thomas Huth (1):
  hw/ppc: Remove the deprecated spapr-pci-vfio-host-bridge device

 MAINTAINERS|   6 +
 default-configs/ppcemb-softmmu.mak |   1 +
 dtc|   2 +-
 hw/display/sm501.c |  30 +++
 hw/i2c/ppc4xx_i2c.c| 198 +---
 hw/ide/Makefile.objs   |   1 +
 hw/ide/sii3112.c   | 368 +
 hw/ide/trace-events|   5 +
 hw/ppc/pnv.c   |  94 +-
 hw/ppc/pnv_bmc.c   |   2 +-
 hw/ppc/pnv_core.c  |   8 +-
 hw/ppc/pnv_lpc.c   |  16 +-
 hw/ppc/pnv_psi.c   |   4 +-
 hw/ppc/pnv_xscom.c |  10 +-
 hw/ppc/spapr.c |   2 +-
 hw/ppc/spapr_pci.c |   6 +-
 hw/ppc/spapr_pci_vfio.c|  47 -
 hw/ppc/spapr_rtas.c|   9 +
 include/hw/i2c/ppc4xx_i2c.h|   3 +
 include/hw/ppc/pnv.h   |  10 +-
 include/hw/ppc/pnv_xscom.h |   4 +-
 pc-bios/README |   2 +-
 pc-bios/slof.bin   | Bin 905200 -> 913880 bytes
 qemu-doc.texi  |   5 -
 roms/SLOF  |   2 +-
 scripts/device-crash-test  |   1 -
 target/ppc/cpu.h   |  56 +++---
 target/ppc/int_helper.c|   2 +-
 28 files changed, 705 insertions(+), 189 deletions(-)
 create mode 100644 hw/ide/sii3112.c



[Qemu-devel] [PULL 02/11] sm501: Add panel hardware cursor registers also to read function

2018-01-10 Thread David Gibson
From: BALATON Zoltan 

These were forgotten when adding panel layer support in ffd39257018
"SM501 emulation for R2D-SH4".

Signed-off-by: BALATON Zoltan 
Reviewed-by: Philippe Mathieu-Daudé 
[dwg: Added reference to earlier commit in message]
Signed-off-by: David Gibson 
---
 hw/display/sm501.c | 13 +
 1 file changed, 13 insertions(+)

diff --git a/hw/display/sm501.c b/hw/display/sm501.c
index 7f1822421a..b9b611131e 100644
--- a/hw/display/sm501.c
+++ b/hw/display/sm501.c
@@ -956,6 +956,19 @@ static uint64_t sm501_disp_ctrl_read(void *opaque, hwaddr 
addr,
 ret = s->dc_panel_v_sync;
 break;
 
+case SM501_DC_PANEL_HWC_ADDR:
+ret = s->dc_panel_hwc_addr;
+break;
+case SM501_DC_PANEL_HWC_LOC:
+ret = s->dc_panel_hwc_location;
+break;
+case SM501_DC_PANEL_HWC_COLOR_1_2:
+ret = s->dc_panel_hwc_color_1_2;
+break;
+case SM501_DC_PANEL_HWC_COLOR_3:
+ret = s->dc_panel_hwc_color_3;
+break;
+
 case SM501_DC_VIDEO_CONTROL:
 ret = s->dc_video_control;
 break;
-- 
2.14.3




[Qemu-devel] [PULL 09/11] Update dtc to fix compilation problem on Mac OS 10.6

2018-01-10 Thread David Gibson
From: John Arbuckle 

Currently QEMU does not build on Mac OS 10.6
because of a missing patch in the dtc
subproject. Updating dtc to make the patch
available fixes this problem.

Signed-off-by: John Arbuckle 
Signed-off-by: David Gibson 
---
 dtc | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/dtc b/dtc
index 558cd81bdd..e54388015a 16
--- a/dtc
+++ b/dtc
@@ -1 +1 @@
-Subproject commit 558cd81bdd432769b59bff01240c44f82cfb1a9d
+Subproject commit e54388015af1fb4bf04d0bca99caba1074d9cc42
-- 
2.14.3




[Qemu-devel] [PATCH qemu] target/ppc: Yet another fix for KVM-HV HPTE accessors

2018-01-10 Thread Alexey Kardashevskiy
As stated in the 1ad9f0a464fe commit log, the returned entries are not
a while PTEG. It was not a problem before 1ad9f0a464fe as it would read
a single record assuming it contains a whole PTEG but now the code tries
reading the entire PTEG and "if ((n - i) < invalid)" produces negative
values which then are converted to size_t for memset() and that throws
seg fault.

This fixes the math.

While here, fix the last @i increment as well.

Fixes: 1ad9f0a464fe "target/ppc: Fix KVM-HV HPTE accessors"
Signed-off-by: Alexey Kardashevskiy 
---

Record #0:
(gdb) p *hdr
$13 = {
  index = ,
  n_valid = 0x1,
  n_invalid = 0x6
}

Record #1:
(gdb) p *hdr
$18 = {
  index = ,
  n_valid = 0x2,
  n_invalid = 0x6
}


i.e. in the second iteration of the loop right before
"if ((n - i) < invalid)":
(gdb) p n
$16 = 0x8
(gdb) p i
$17 = 0x9

and @invalid becomes -1.

---
 target/ppc/kvm.c | 11 +++
 1 file changed, 7 insertions(+), 4 deletions(-)

diff --git a/target/ppc/kvm.c b/target/ppc/kvm.c
index 0566af7..c2dea81 100644
--- a/target/ppc/kvm.c
+++ b/target/ppc/kvm.c
@@ -2657,21 +2657,24 @@ void kvmppc_read_hptes(ppc_hash_pte64_t *hptes, hwaddr 
ptex, int n)
 
 hdr = (struct kvm_get_htab_header *)buf;
 while ((i < n) && ((char *)hdr < (buf + rc))) {
-int invalid = hdr->n_invalid;
+int invalid = hdr->n_invalid, valid = hdr->n_valid;
 
 if (hdr->index != (ptex + i)) {
 hw_error("kvmppc_read_hptes: Unexpected HPTE index %"PRIu32
  " != (%"HWADDR_PRIu" + %d", hdr->index, ptex, i);
 }
 
-memcpy(hptes + i, hdr + 1, HASH_PTE_SIZE_64 * hdr->n_valid);
-i += hdr->n_valid;
+if (n - i < valid) {
+valid = n - i;
+}
+memcpy(hptes + i, hdr + 1, HASH_PTE_SIZE_64 * valid);
+i += valid;
 
 if ((n - i) < invalid) {
 invalid = n - i;
 }
 memset(hptes + i, 0, invalid * HASH_PTE_SIZE_64);
-i += hdr->n_invalid;
+i += invalid;
 
 hdr = (struct kvm_get_htab_header *)
 ((char *)(hdr + 1) + HASH_PTE_SIZE_64 * hdr->n_valid);
-- 
2.11.0




Re: [Qemu-devel] [PATCH v5 2/4][RFC] tap: do not close fd if only vhost failed to initialize

2018-01-10 Thread Zhoujian (jay)
Hi Jason,

> -Original Message-
> From: Jason Wang [mailto:jasow...@redhat.com]
> Sent: Thursday, January 11, 2018 11:35 AM
> To: Zhoujian (jay) ; qemu-devel@nongnu.org
> Cc: Huangweidong (C) ; m...@redhat.com; wangxin (U)
> ; Gonglei (Arei) ;
> imamm...@redhat.com; Liuzhe (Ahriy, Euler) 
> Subject: Re: [Qemu-devel] [PATCH v5 2/4][RFC] tap: do not close fd if only
> vhost failed to initialize
> 
> 
> 
> On 2018年01月10日 15:39, Zhoujian (jay) wrote:
>  +*vhost_init_failed = true;
> >> Why not simply check s->vhost_net after call net_init_tap_one()?
> > s->vhost_net is always NULL if net_init_tap_one() failed, it can't
> distinguish
> > failure reasons.
> 
> On which condition net_init_tap_one() fail but s->vhost_net is set?

No, it does not exist, so we could not use s->vhost_net to decide
whether close the fd of tap when error occurred.


Maybe the patch below will be much better to understand, please have a look.

diff --git a/net/tap.c b/net/tap.c
index 979e622..a5c5111 100644
--- a/net/tap.c
+++ b/net/tap.c
@@ -642,7 +642,8 @@ static void net_init_tap_one(const NetdevTapOptions *tap, 
NetClientState *peer,
  const char *model, const char *name,
  const char *ifname, const char *script,
  const char *downscript, const char *vhostfdname,
- int vnet_hdr, int fd, Error **errp)
+ int vnet_hdr, int fd, Error **errp,
+ bool *error_is_set_sndbuf)
 {
 Error *err = NULL;
 TAPState *s = net_tap_fd_init(peer, model, name, fd, vnet_hdr);
@@ -651,6 +652,9 @@ static void net_init_tap_one(const NetdevTapOptions *tap, 
NetClientState *peer,
 tap_set_sndbuf(s->fd, tap, &err);
 if (err) {
 error_propagate(errp, err);
+if (error_is_set_sndbuf) {
+*error_is_set_sndbuf = true;
+}
 return;
 }
 
@@ -748,6 +752,7 @@ int net_init_tap(const Netdev *netdev, const char *name,
 Error *err = NULL;
 const char *vhostfdname;
 char ifname[128];
+bool error_is_set_sndbuf = false;
 
 assert(netdev->type == NET_CLIENT_DRIVER_TAP);
 tap = &netdev->u.tap;
@@ -783,7 +788,7 @@ int net_init_tap(const Netdev *netdev, const char *name,
 
 net_init_tap_one(tap, peer, "tap", name, NULL,
  script, downscript,
- vhostfdname, vnet_hdr, fd, &err);
+ vhostfdname, vnet_hdr, fd, &err, NULL);
 if (err) {
 error_propagate(errp, err);
 return -1;
@@ -835,7 +840,7 @@ int net_init_tap(const Netdev *netdev, const char *name,
 net_init_tap_one(tap, peer, "tap", name, ifname,
  script, downscript,
  tap->has_vhostfds ? vhost_fds[i] : NULL,
- vnet_hdr, fd, &err);
+ vnet_hdr, fd, &err, NULL);
 if (err) {
 error_propagate(errp, err);
 goto free_fail;
@@ -874,10 +879,13 @@ free_fail:
 
 net_init_tap_one(tap, peer, "bridge", name, ifname,
  script, downscript, vhostfdname,
- vnet_hdr, fd, &err);
+ vnet_hdr, fd, &err, &error_is_set_sndbuf);
 if (err) {
 error_propagate(errp, err);
-close(fd);
+if (error_is_set_sndbuf || (tap->has_vhostforce &&
+tap->vhostforce)) {
+close(fd);
+}
 return -1;
 }
 } else {
@@ -913,10 +921,14 @@ free_fail:
 net_init_tap_one(tap, peer, "tap", name, ifname,
  i >= 1 ? "no" : script,
  i >= 1 ? "no" : downscript,
- vhostfdname, vnet_hdr, fd, &err);
+ vhostfdname, vnet_hdr, fd, &err,
+ &error_is_set_sndbuf);
 if (err) {
 error_propagate(errp, err);
-close(fd);
+if (error_is_set_sndbuf || (tap->has_vhostforce &&
+tap->vhostforce)) {
+close(fd);
+}
 return -1;
 }
 }



PS: I think I do not express the meaning clearly... I can express it in
Chinese in private if necessary

Regards,
Jay


Re: [Qemu-devel] [PATCH 0/7] CPU model updates for CVE-2017-5715 (Spectre variant #2)

2018-01-10 Thread no-reply
Hi,

This series failed automatic build test. Please find the testing commands and
their output below. If you have docker installed, you can probably reproduce it
locally.

Type: series
Message-id: 20180109154519.25634-1-ehabk...@redhat.com
Subject: [Qemu-devel] [PATCH 0/7] CPU model updates for CVE-2017-5715 (Spectre 
variant #2)

=== TEST SCRIPT BEGIN ===
#!/bin/bash
set -e
git submodule update --init dtc
# Let docker tests dump environment info
export SHOW_ENV=1
export J=8
time make docker-test-quick@centos6
time make docker-test-build@min-glib
time make docker-test-mingw@fedora
# iotests is broken now, skip
# time make docker-test-block@fedora
=== TEST SCRIPT END ===

Updating 3c8cf5a9c21ff8782164d1def7f44bd888713384
From https://github.com/patchew-project/qemu
 * [new tag]   patchew/20180109154519.25634-1-ehabk...@redhat.com 
-> patchew/20180109154519.25634-1-ehabk...@redhat.com
Switched to a new branch 'test'
8abab8209b i386: Add PCID to {Westmere, SandyBridge, IvyBridge}-IBRS
3c1571848a i386: Add EPYC-IBPB CPU model
193b8fb502 i386: Add new -IBRS versions of Intel CPU models
90ca85d76c i386: Add FEAT_8000_0008_EBX CPUID feature word
5ae7849afb i386: Add spec-ctrl CPUID bit
cf28b26d08 i386: Add support for SPEC_CTRL MSR
a2c77c75f7 i386: Change X86CPUDefinition::model_id to const char*

=== OUTPUT BEGIN ===
Submodule 'dtc' (git://git.qemu-project.org/dtc.git) registered for path 'dtc'
Cloning into '/var/tmp/patchew-tester-tmp-rw0u2ys3/src/dtc'...
Submodule path 'dtc': checked out '558cd81bdd432769b59bff01240c44f82cfb1a9d'
  BUILD   centos6
make[1]: Entering directory '/var/tmp/patchew-tester-tmp-rw0u2ys3/src'
  GEN 
/var/tmp/patchew-tester-tmp-rw0u2ys3/src/docker-src.2018-01-09-10.55.01.11221/qemu.tar
Cloning into 
'/var/tmp/patchew-tester-tmp-rw0u2ys3/src/docker-src.2018-01-09-10.55.01.11221/qemu.tar.vroot'...
done.
Checking out files:  40% (2303/5710)   
Checking out files:  41% (2342/5710)   
Checking out files:  42% (2399/5710)   
Checking out files:  43% (2456/5710)   
Checking out files:  44% (2513/5710)   
Checking out files:  45% (2570/5710)   
Checking out files:  46% (2627/5710)   
Checking out files:  47% (2684/5710)   
Checking out files:  48% (2741/5710)   
Checking out files:  49% (2798/5710)   
Checking out files:  50% (2855/5710)   
Checking out files:  51% (2913/5710)   
Checking out files:  52% (2970/5710)   
Checking out files:  53% (3027/5710)   
Checking out files:  54% (3084/5710)   
Checking out files:  55% (3141/5710)   
Checking out files:  56% (3198/5710)   
Checking out files:  57% (3255/5710)   
Checking out files:  58% (3312/5710)   
Checking out files:  59% (3369/5710)   
Checking out files:  60% (3426/5710)   
Checking out files:  61% (3484/5710)   
Checking out files:  62% (3541/5710)   
Checking out files:  63% (3598/5710)   
Checking out files:  64% (3655/5710)   
Checking out files:  65% (3712/5710)   
Checking out files:  66% (3769/5710)   
Checking out files:  67% (3826/5710)   
Checking out files:  68% (3883/5710)   
Checking out files:  69% (3940/5710)   
Checking out files:  70% (3997/5710)   
Checking out files:  71% (4055/5710)   
Checking out files:  72% (4112/5710)   
Checking out files:  73% (4169/5710)   
Checking out files:  74% (4226/5710)   
Checking out files:  75% (4283/5710)   
Checking out files:  76% (4340/5710)   
Checking out files:  77% (4397/5710)   
Checking out files:  78% (4454/5710)   
Checking out files:  79% (4511/5710)   
Checking out files:  80% (4568/5710)   
Checking out files:  81% (4626/5710)   
Checking out files:  82% (4683/5710)   
Checking out files:  83% (4740/5710)   
Checking out files:  84% (4797/5710)   
Checking out files:  85% (4854/5710)   
Checking out files:  86% (4911/5710)   
Checking out files:  87% (4968/5710)   
Checking out files:  88% (5025/5710)   
Checking out files:  89% (5082/5710)   
Checking out files:  90% (5139/5710)   
Checking out files:  91% (5197/5710)   
Checking out files:  92% (5254/5710)   
Checking out files:  93% (5311/5710)   
Checking out files:  94% (5368/5710)   
Checking out files:  95% (5425/5710)   
Checking out files:  96% (5482/5710)   
Checking out files:  97% (5539/5710)   
Checking out files:  98% (5596/5710)   
Checking out files:  99% (5653/5710)   
Checking out files: 100% (5710/5710)   
Checking out files: 100% (5710/5710), done.
Your branch is up-to-date with 'origin/test'.
Submodule 'dtc' (git://git.qemu-project.org/dtc.git) registered for path 'dtc'
Cloning into 
'/var/tmp/patchew-tester-tmp-rw0u2ys3/src/docker-src.2018-01-09-10.55.01.11221/qemu.tar.vroot/dtc'...
Submodule path 'dtc': checked out '558cd81bdd432769b59bff01240c44f82cfb1a9d'
Submodule 'ui/keycodemapdb' (git://git.qemu.org/keycodemapdb.git) registered 
for path 'ui/keycodemapdb'
Cloning into 
'/var/tmp/patchew-tester-tmp-rw0u2ys3/src/docker-src.2018-01-09-10.55.01.11221/qemu.tar.vroot/ui/keycodemapdb'...
Submodule path 'ui/keycodemapdb': checked out 
'10739aa26051a5d49d88132604539d3ed085e72e'
  CO

Re: [Qemu-devel] [PATCH v5 2/4][RFC] tap: do not close fd if only vhost failed to initialize

2018-01-10 Thread Jason Wang



On 2018年01月10日 15:39, Zhoujian (jay) wrote:

+*vhost_init_failed = true;

Why not simply check s->vhost_net after call net_init_tap_one()?

s->vhost_net is always NULL if net_init_tap_one() failed, it can't distinguish
failure reasons.


On which condition net_init_tap_one() fail but s->vhost_net is set?

Thanks



Re: [Qemu-devel] [PATCH v5 3/7] vhost: Simplify ring verification checks

2018-01-10 Thread Jason Wang



On 2018年01月10日 18:23, Igor Mammedov wrote:

On Mon, 8 Jan 2018 17:54:50 +
"Dr. David Alan Gilbert"  wrote:


* Igor Mammedov (imamm...@redhat.com) wrote:

On Mon, 18 Dec 2017 20:13:36 +
"Dr. David Alan Gilbert (git)"  wrote:
   

From: "Dr. David Alan Gilbert"

vhost_verify_ring_mappings() were used to verify that
rings are still accessible and related memory hasn't
been moved after flatview is updated.

It was doing checks by mapping ring's GPA+len and
checking that HVA hadn't changed with new memory map.
To avoid maybe expensive mapping call, we were
identifying address range that changed and were doing
mapping only if ring was in changed range.

However it's not neccessary to perform ring's GPA
mapping as we already have its current HVA and all
we need is to verify that ring's GPA translates to
the same HVA in updated flatview.

This will allow the following patches to simplify the range
comparison that was previously needed to avoid expensive
verify_ring_mapping calls.

Signed-off-by: Igor Mammedov
with modifications by:
Signed-off-by: Dr. David Alan Gilbert   

an additional question,

in iommu case ring_hva == ring_gpa if we look in to vhost_memory_map()
have you check if iommu case is working with new code?

No I've not; do you have a suggested way of testing it?

Not really,
CCing Jason and Peter who worked on IOMMU stuff there,
maybe the would suggest a test case.




Haven't read the thread but for IOMMU test you need:

1) enable iommu_platform for virtio device
2) enable ats for virtio device
3) boot with intel_iomu device
4) boot a guest with intel_iommu=strict (which makes the flush happens 
immediately)

5) do some network loads e.g netperf TCP_STREAM test

Thanks



[Qemu-devel] [RFC PATCH 5/5] vfio/ccw: build schib with real schib information

2018-01-10 Thread Dong Jia Shi
The current implementation grabs chpids and path masks from
sysfs to build the schib and chp for the virtual subchannels.

Since now vfio-ccw provides a schib region for store subchannel
information. Let's leverage it to get the chipids and the masks,
and serve the virtual subchannels.

While we are at it, touch one line of the comment around by
adding white space to make it aligned.

Signed-off-by: Dong Jia Shi 
---
 hw/s390x/css.c  | 83 -
 hw/s390x/s390-ccw.c | 20 +++
 hw/vfio/ccw.c   | 28 +--
 include/hw/s390x/s390-ccw.h |  3 +-
 4 files changed, 39 insertions(+), 95 deletions(-)

diff --git a/hw/s390x/css.c b/hw/s390x/css.c
index c1ec83f08f..b9bc489e55 100644
--- a/hw/s390x/css.c
+++ b/hw/s390x/css.c
@@ -2417,72 +2417,6 @@ SubchDev *css_create_sch(CssDevId bus_id, bool 
squash_mcss, Error **errp)
 return sch;
 }
 
-static int css_sch_get_chpids(SubchDev *sch, CssDevId *dev_id)
-{
-char *fid_path;
-FILE *fd;
-uint32_t chpid[8];
-int i;
-PMCW *p = &sch->curr_status.pmcw;
-
-fid_path = g_strdup_printf("/sys/bus/css/devices/%x.%x.%04x/chpids",
-   dev_id->cssid, dev_id->ssid, dev_id->devid);
-fd = fopen(fid_path, "r");
-if (fd == NULL) {
-error_report("%s: open %s failed", __func__, fid_path);
-g_free(fid_path);
-return -EINVAL;
-}
-
-if (fscanf(fd, "%x %x %x %x %x %x %x %x",
-&chpid[0], &chpid[1], &chpid[2], &chpid[3],
-&chpid[4], &chpid[5], &chpid[6], &chpid[7]) != 8) {
-fclose(fd);
-g_free(fid_path);
-return -EINVAL;
-}
-
-for (i = 0; i < ARRAY_SIZE(p->chpid); i++) {
-p->chpid[i] = chpid[i];
-}
-
-fclose(fd);
-g_free(fid_path);
-
-return 0;
-}
-
-static int css_sch_get_path_masks(SubchDev *sch, CssDevId *dev_id)
-{
-char *fid_path;
-FILE *fd;
-uint32_t pim, pam, pom;
-PMCW *p = &sch->curr_status.pmcw;
-
-fid_path = g_strdup_printf("/sys/bus/css/devices/%x.%x.%04x/pimpampom",
-   dev_id->cssid, dev_id->ssid, dev_id->devid);
-fd = fopen(fid_path, "r");
-if (fd == NULL) {
-error_report("%s: open %s failed", __func__, fid_path);
-g_free(fid_path);
-return -EINVAL;
-}
-
-if (fscanf(fd, "%x %x %x", &pim, &pam, &pom) != 3) {
-fclose(fd);
-g_free(fid_path);
-return -EINVAL;
-}
-
-p->pim = pim;
-p->pam = pam;
-p->pom = pom;
-fclose(fd);
-g_free(fid_path);
-
-return 0;
-}
-
 static int css_sch_get_chpid_type(uint8_t chpid, uint32_t *type,
   CssDevId *dev_id)
 {
@@ -2529,19 +2463,14 @@ int css_sch_build_schib(SubchDev *sch, CssDevId *dev_id)
 /* We are dealing with I/O subchannels only. */
 p->devno = sch->devno;
 
-/* Grab path mask from sysfs. */
-ret = css_sch_get_path_masks(sch, dev_id);
-if (ret) {
-return ret;
-}
-
-/* Grab chpids from sysfs. */
-ret = css_sch_get_chpids(sch, dev_id);
-if (ret) {
-return ret;
+/* Read schib from the physical device. */
+/* g_assert(sch->update_schib != NULL) ? */
+if (sch->update_schib &&
+(sch->update_schib(sch) != IOINST_CC_EXPECTED)) {
+return -ENODEV;
 }
 
-   /* Build chpid type. */
+/* Build chpid type. */
 for (i = 0; i < ARRAY_SIZE(p->chpid); i++) {
 if (p->chpid[i] && !css->chpids[p->chpid[i]].in_use) {
 ret = css_sch_get_chpid_type(p->chpid[i], &type, dev_id);
diff --git a/hw/s390x/s390-ccw.c b/hw/s390x/s390-ccw.c
index 491697137c..f658b87131 100644
--- a/hw/s390x/s390-ccw.c
+++ b/hw/s390x/s390-ccw.c
@@ -72,7 +72,18 @@ static void s390_ccw_get_dev_info(S390CCWDevice *cdev,
 cdev->hostid.valid = true;
 }
 
-static void s390_ccw_realize(S390CCWDevice *cdev, char *sysfsdev, Error **errp)
+static void s390_ccw_pre_realize(S390CCWDevice *cdev, char *sysfsdev,
+ Error **errp)
+{
+Error *err = NULL;
+
+s390_ccw_get_dev_info(cdev, sysfsdev, &err);
+if (err) {
+error_propagate(errp, err);
+}
+}
+
+static void s390_ccw_realize(S390CCWDevice *cdev, Error **errp)
 {
 CcwDevice *ccw_dev = CCW_DEVICE(cdev);
 CCWDeviceClass *ck = CCW_DEVICE_GET_CLASS(ccw_dev);
@@ -83,11 +94,6 @@ static void s390_ccw_realize(S390CCWDevice *cdev, char 
*sysfsdev, Error **errp)
 int ret;
 Error *err = NULL;
 
-s390_ccw_get_dev_info(cdev, sysfsdev, &err);
-if (err) {
-goto out_err_propagate;
-}
-
 sch = css_create_sch(ccw_dev->devno, cbus->squash_mcss, &err);
 if (!sch) {
 goto out_mdevid_free;
@@ -119,7 +125,6 @@ out_err:
 g_free(sch);
 out_mdevid_free:
 g_free(cdev->mdevid);
-out_err_propagate:
 error_propagate(errp, err);
 }
 
@@ -143,6 +148,7 @@ static void s390_ccw_class_init(ObjectClass *klass, void 
*data)
 S390CCWDeviceClass *cd

[Qemu-devel] [RFC PATCH 4/5] vfio/ccw: update subchanel information block lazily

2018-01-10 Thread Dong Jia Shi
We want to sync up channel path related information between the
physical device and the virtual device. Thus here we read out
subchannel information block from the schib region, and update
the virtual sbuchannel information block.

Since the kernel side will signal userland once it has channel
path information update, we only do update if we were signaled.

We sets scsw.pno and pmcw.pnom to indicate path related event
for a guest. This is a bit lazy, but it works.

Signed-off-by: Dong Jia Shi 
---
 hw/s390x/css.c  | 14 +--
 hw/s390x/s390-ccw.c | 12 +
 hw/vfio/ccw.c   | 59 -
 include/hw/s390x/css.h  |  3 ++-
 include/hw/s390x/s390-ccw.h |  1 +
 target/s390x/ioinst.c   |  3 +--
 6 files changed, 86 insertions(+), 6 deletions(-)

diff --git a/hw/s390x/css.c b/hw/s390x/css.c
index 1c526fd7e2..c1ec83f08f 100644
--- a/hw/s390x/css.c
+++ b/hw/s390x/css.c
@@ -1297,11 +1297,16 @@ static void copy_schib_to_guest(SCHIB *dest, const 
SCHIB *src)
 }
 }
 
-int css_do_stsch(SubchDev *sch, SCHIB *schib)
+IOInstEnding css_do_stsch(SubchDev *sch, SCHIB *schib)
 {
+if (sch->update_schib &&
+(sch->update_schib(sch) != IOINST_CC_EXPECTED)) {
+return IOINST_CC_NOT_OPERATIONAL;
+}
+
 /* Use current status. */
 copy_schib_to_guest(schib, &sch->curr_status);
-return 0;
+return IOINST_CC_EXPECTED;
 }
 
 static void copy_pmcw_from_guest(PMCW *dest, const PMCW *src)
@@ -1586,6 +1591,11 @@ int css_do_tsch_get_irb(SubchDev *sch, IRB *target_irb, 
int *irb_len)
 uint16_t stctl;
 IRB irb;
 
+if (sch->update_schib &&
+(sch->update_schib(sch) != IOINST_CC_EXPECTED)) {
+return IOINST_CC_NOT_OPERATIONAL;
+}
+
 if (~(p->flags) & (PMCW_FLAGS_MASK_DNV | PMCW_FLAGS_MASK_ENA)) {
 return 3;
 }
diff --git a/hw/s390x/s390-ccw.c b/hw/s390x/s390-ccw.c
index 4a9d4d2534..491697137c 100644
--- a/hw/s390x/s390-ccw.c
+++ b/hw/s390x/s390-ccw.c
@@ -28,6 +28,17 @@ IOInstEnding s390_ccw_cmd_request(SubchDev *sch)
 return cdc->handle_request(sch);
 }
 
+static IOInstEnding s390_ccw_update_schib(SubchDev *sch)
+{
+S390CCWDeviceClass *cdc = S390_CCW_DEVICE_GET_CLASS(sch->driver_data);
+
+if (!cdc->update_schib) {
+/* g_assert_not_reached()? */
+return IOINST_CC_NOT_OPERATIONAL;
+}
+return cdc->update_schib(sch);
+}
+
 static void s390_ccw_get_dev_info(S390CCWDevice *cdev,
   char *sysfsdev,
   Error **errp)
@@ -83,6 +94,7 @@ static void s390_ccw_realize(S390CCWDevice *cdev, char 
*sysfsdev, Error **errp)
 }
 sch->driver_data = cdev;
 sch->do_subchannel_work = do_subchannel_work_passthrough;
+sch->update_schib = s390_ccw_update_schib;
 
 ccw_dev->sch = sch;
 ret = css_sch_build_schib(sch, &cdev->hostid);
diff --git a/hw/vfio/ccw.c b/hw/vfio/ccw.c
index d812cecfe0..0eca3453af 100644
--- a/hw/vfio/ccw.c
+++ b/hw/vfio/ccw.c
@@ -33,6 +33,7 @@ typedef struct VFIOCCWDevice {
 struct ccw_io_region *io_region;
 EventNotifier io_notifier;
 
+bool schib_need_update;
 uint64_t schib_region_size;
 uint64_t schib_region_offset;
 struct ccw_schib_region *schib_region;
@@ -97,6 +98,57 @@ again:
 }
 }
 
+static IOInstEnding vfio_ccw_update_schib(SubchDev *sch)
+{
+
+S390CCWDevice *cdev = sch->driver_data;
+VFIOCCWDevice *vcdev = DO_UPCAST(VFIOCCWDevice, cdev, cdev);
+struct ccw_schib_region *region = vcdev->schib_region;
+PMCW *p = &sch->curr_status.pmcw;
+SCSW *s = &sch->curr_status.scsw;
+SCHIB *schib;
+int size;
+int i;
+
+/*
+ * If there is no update that interested us since last read,
+ * we do not read then.
+ */
+if (!vcdev->schib_need_update) {
+return IOINST_CC_EXPECTED;
+}
+vcdev->schib_need_update = false;
+
+/* Read schib region, and update schib for virtual subchannel. */
+size = pread(vcdev->vdev.fd, region, vcdev->schib_region_size,
+ vcdev->schib_region_offset);
+if (size != vcdev->schib_region_size) {
+return IOINST_CC_NOT_OPERATIONAL;
+}
+if (region->cc) {
+g_assert(region->cc == IOINST_CC_NOT_OPERATIONAL);
+return region->cc;
+}
+
+schib = (SCHIB *)region->schib_area;
+
+/* Path mask. */
+p->pim = schib->pmcw.pim;
+p->pam = schib->pmcw.pam;
+p->pom = schib->pmcw.pom;
+
+/* We use PNO and PNOM to indicate path related events. */
+p->pnom = ~schib->pmcw.pam;
+s->flags |= SCSW_FLAGS_MASK_PNO;
+
+/* Chp id. */
+for (i = 0; i < ARRAY_SIZE(p->chpid); i++) {
+p->chpid[i] = schib->pmcw.chpid[i];
+}
+
+return region->cc;
+}
+
 static void vfio_ccw_reset(DeviceState *dev)
 {
 CcwDevice *ccw_dev = DO_UPCAST(CcwDevice, parent_obj, dev);
@@ -182,7 +234,9 @@ static void vfio_ccw_chp_notifier_handler(void *opaque)
 return;
 }
 
-/* TO

[Qemu-devel] [RFC PATCH 2/5] vfio/ccw: get schib region info

2018-01-10 Thread Dong Jia Shi
vfio-ccw provides an MMIO region for store subchannel
information. We fetch this information via ioctls here,
then we can use it to update schib for virtual subchannels
later on.

While we are at it, also modify the comment and error
message for the config region a bit, to make these unified
with the schib likeness.

Signed-off-by: Dong Jia Shi 
---
 hw/vfio/ccw.c | 24 +++-
 1 file changed, 23 insertions(+), 1 deletion(-)

diff --git a/hw/vfio/ccw.c b/hw/vfio/ccw.c
index 16713f2c52..e673695509 100644
--- a/hw/vfio/ccw.c
+++ b/hw/vfio/ccw.c
@@ -32,6 +32,10 @@ typedef struct VFIOCCWDevice {
 uint64_t io_region_offset;
 struct ccw_io_region *io_region;
 EventNotifier io_notifier;
+
+uint64_t schib_region_size;
+uint64_t schib_region_offset;
+struct ccw_schib_region *schib_region;
 } VFIOCCWDevice;
 
 static void vfio_ccw_compute_needs_reset(VFIODevice *vdev)
@@ -268,9 +272,10 @@ static void vfio_ccw_get_region(VFIOCCWDevice *vcdev, 
Error **errp)
 return;
 }
 
+/* Get I/O region info. */
 ret = vfio_get_region_info(vdev, VFIO_CCW_CONFIG_REGION_INDEX, &info);
 if (ret) {
-error_setg_errno(errp, -ret, "vfio: Error getting config info");
+error_setg_errno(errp, -ret, "vfio: Error getting config region info");
 return;
 }
 
@@ -283,13 +288,30 @@ static void vfio_ccw_get_region(VFIOCCWDevice *vcdev, 
Error **errp)
 
 vcdev->io_region_offset = info->offset;
 vcdev->io_region = g_malloc0(info->size);
+g_free(info);
 
+/* Get SCHIB region info. */
+ret = vfio_get_region_info(vdev, VFIO_CCW_SCHIB_REGION_INDEX, &info);
+if (ret) {
+error_setg_errno(errp, -ret, "vfio: Error getting schib region info");
+return;
+}
+
+vcdev->schib_region_size = info->size;
+if (sizeof(*vcdev->schib_region) != vcdev->schib_region_size) {
+error_setg(errp, "vfio: Unexpected size of the schib region");
+g_free(info);
+return;
+}
+vcdev->schib_region_offset = info->offset;
+vcdev->schib_region = g_malloc0(info->size);
 g_free(info);
 }
 
 static void vfio_ccw_put_region(VFIOCCWDevice *vcdev)
 {
 g_free(vcdev->io_region);
+g_free(vcdev->schib_region);
 }
 
 static void vfio_put_device(VFIOCCWDevice *vcdev)
-- 
2.13.5




[Qemu-devel] [RFC PATCH 0/5] vfio/ccw: basic channel path event handling

2018-01-10 Thread Dong Jia Shi
Hi Folks,

This is the QEMU couterpart for the "basic channel path event handling" series.
For more information, please refer to the kernel counterpart.

Dong Jia Shi (5):
  vfio: linux-headers update for vfio-ccw
  vfio/ccw: get schib region info
  vfio/ccw: get irq info and set up handler for chp irq
  vfio/ccw: update subchanel information block lazily
  vfio/ccw: build schib with real schib information

 hw/s390x/css.c |  97 
 hw/s390x/s390-ccw.c|  32 +--
 hw/vfio/ccw.c  | 199 ++---
 include/hw/s390x/css.h |   3 +-
 include/hw/s390x/s390-ccw.h|   4 +-
 linux-headers/linux/vfio.h |   2 +
 linux-headers/linux/vfio_ccw.h |   6 ++
 target/s390x/ioinst.c  |   3 +-
 8 files changed, 224 insertions(+), 122 deletions(-)

-- 
2.13.5




[Qemu-devel] [RFC PATCH 3/3] vfio: ccw: handle chp event

2018-01-10 Thread Dong Jia Shi
This adds channel path related event handler for vfio-ccw.
This also signals userland when there is a chp event.

Signed-off-by: Dong Jia Shi 
---
 drivers/s390/cio/vfio_ccw_drv.c | 51 +
 drivers/s390/cio/vfio_ccw_fsm.c | 22 
 drivers/s390/cio/vfio_ccw_private.h |  3 +++
 3 files changed, 76 insertions(+)

diff --git a/drivers/s390/cio/vfio_ccw_drv.c b/drivers/s390/cio/vfio_ccw_drv.c
index ea6a2d0b2894..5f01f3e6742d 100644
--- a/drivers/s390/cio/vfio_ccw_drv.c
+++ b/drivers/s390/cio/vfio_ccw_drv.c
@@ -17,6 +17,7 @@
 
 #include 
 
+#include "chp.h"
 #include "ioasm.h"
 #include "css.h"
 #include "vfio_ccw_private.h"
@@ -88,6 +89,15 @@ static void vfio_ccw_sch_io_todo(struct work_struct *work)
private->state = VFIO_CCW_STATE_IDLE;
 }
 
+static void vfio_ccw_sch_chp_todo(struct work_struct *work)
+{
+   struct vfio_ccw_private *private =
+   container_of(work, struct vfio_ccw_private, chp_work);
+
+   if (private->chp_trigger)
+   eventfd_signal(private->chp_trigger, 1);
+}
+
 /*
  * Css driver callbacks
  */
@@ -130,6 +140,7 @@ static int vfio_ccw_sch_probe(struct subchannel *sch)
goto out_disable;
 
INIT_WORK(&private->io_work, vfio_ccw_sch_io_todo);
+   INIT_WORK(&private->chp_work, vfio_ccw_sch_chp_todo);
atomic_set(&private->avail, 1);
private->state = VFIO_CCW_STATE_STANDBY;
 
@@ -202,6 +213,45 @@ static int vfio_ccw_sch_event(struct subchannel *sch, int 
process)
return 0;
 }
 
+static int vfio_ccw_sch_chp_event(struct subchannel *sch,
+ struct chp_link *link, int event)
+{
+   struct vfio_ccw_private *private = dev_get_drvdata(&sch->dev);
+   int mask = chp_ssd_get_mask(&sch->ssd_info, link);
+
+   /* move these checks around? */
+   if (!private || !mask)
+   return 0;
+
+   if (cio_update_schib(sch))
+   return -ENODEV;
+
+   switch (event) {
+   case CHP_VARY_OFF:
+   sch->opm &= ~mask;
+   sch->lpm &= ~mask;
+   /* TODO: terminate current I/O on path. */
+   break;
+   case CHP_VARY_ON:
+   sch->opm |= mask;
+   sch->lpm |= mask;
+   break;
+   case CHP_OFFLINE:
+   /* TODO: terminate current I/O on path. */
+   break;
+   case CHP_ONLINE:
+   sch->lpm |= mask & sch->opm;
+   break;
+   default:
+   /* Not possible? */
+   return 0;
+   }
+
+   vfio_ccw_fsm_event(private, VFIO_CCW_EVENT_UPDATE_CHP);
+
+   return 0;
+}
+
 static struct css_device_id vfio_ccw_sch_ids[] = {
{ .match_flags = 0x1, .type = SUBCHANNEL_TYPE_IO, },
{ /* end of list */ },
@@ -219,6 +269,7 @@ static struct css_driver vfio_ccw_sch_driver = {
.remove = vfio_ccw_sch_remove,
.shutdown = vfio_ccw_sch_shutdown,
.sch_event = vfio_ccw_sch_event,
+   .chp_event = vfio_ccw_sch_chp_event,
 };
 
 static int __init vfio_ccw_sch_init(void)
diff --git a/drivers/s390/cio/vfio_ccw_fsm.c b/drivers/s390/cio/vfio_ccw_fsm.c
index be081ccabea3..c400021134cb 100644
--- a/drivers/s390/cio/vfio_ccw_fsm.c
+++ b/drivers/s390/cio/vfio_ccw_fsm.c
@@ -188,6 +188,23 @@ static void fsm_update_subch(struct vfio_ccw_private 
*private,
   sizeof(sch->schib));
 }
 
+static void fsm_update_chp(struct vfio_ccw_private *private,
+  enum vfio_ccw_event event)
+{
+   queue_work(vfio_ccw_work_q, &private->chp_work);
+
+}
+
+static void fsm_update_chp_busy(struct vfio_ccw_private *private,
+   enum vfio_ccw_event event)
+{
+   /*
+* TODO:
+* If we are having I/O on the current path, do
+* extra handling?
+*/
+}
+
 /*
  * Device statemachine
  */
@@ -197,29 +214,34 @@ fsm_func_t 
*vfio_ccw_jumptable[NR_VFIO_CCW_STATES][NR_VFIO_CCW_EVENTS] = {
[VFIO_CCW_EVENT_IO_REQ] = fsm_io_error,
[VFIO_CCW_EVENT_INTERRUPT]  = fsm_disabled_irq,
[VFIO_CCW_EVENT_UPDATE_SUBCH]   = fsm_update_subch,
+   [VFIO_CCW_EVENT_UPDATE_CHP] = fsm_nop,
},
[VFIO_CCW_STATE_STANDBY] = {
[VFIO_CCW_EVENT_NOT_OPER]   = fsm_notoper,
[VFIO_CCW_EVENT_IO_REQ] = fsm_io_error,
[VFIO_CCW_EVENT_INTERRUPT]  = fsm_irq,
[VFIO_CCW_EVENT_UPDATE_SUBCH]   = fsm_update_subch,
+   [VFIO_CCW_EVENT_UPDATE_CHP] = fsm_update_chp,
},
[VFIO_CCW_STATE_IDLE] = {
[VFIO_CCW_EVENT_NOT_OPER]   = fsm_notoper,
[VFIO_CCW_EVENT_IO_REQ] = fsm_io_request,
[VFIO_CCW_EVENT_INTERRUPT]  = fsm_irq,
[VFIO_CCW_EVENT_UPDATE_SUBCH]   = fsm_update_subch,
+   [VFIO_CCW_EVENT_UPDATE_CHP] = fs

[Qemu-devel] [RFC PATCH 3/5] vfio/ccw: get irq info and set up handler for chp irq

2018-01-10 Thread Dong Jia Shi
vfio-ccw now resorts to the eventfd mechanism to communicate
with userland for channel path related event. To get notification
of the channel path event, userland basically needs to:
1. check the chp irq capability via issuing VFIO_DEVICE_GET_IRQ_INFO
   ioctl with VFIO_CCW_CHP_IRQ_INDEX.
2. register an event notifier to get an eventfd fd.
3. register the eventfd for chp irq to kernel via
   VFIO_DEVICE_SET_IRQS ioctl.

This work introduces vfio_ccw_chp_notifier_handler(), and refactors
vfio_ccw_(un)register_event_notifier() to do the above.

Based on this, future work could read channel path information
out once got the eventfd signal, and do further process.

Signed-off-by: Dong Jia Shi 
---
 hw/vfio/ccw.c | 92 +--
 1 file changed, 70 insertions(+), 22 deletions(-)

diff --git a/hw/vfio/ccw.c b/hw/vfio/ccw.c
index e673695509..d812cecfe0 100644
--- a/hw/vfio/ccw.c
+++ b/hw/vfio/ccw.c
@@ -36,6 +36,8 @@ typedef struct VFIOCCWDevice {
 uint64_t schib_region_size;
 uint64_t schib_region_offset;
 struct ccw_schib_region *schib_region;
+
+EventNotifier chp_notifier;
 } VFIOCCWDevice;
 
 static void vfio_ccw_compute_needs_reset(VFIODevice *vdev)
@@ -172,33 +174,56 @@ read_err:
 css_inject_io_interrupt(sch);
 }
 
-static void vfio_ccw_register_io_notifier(VFIOCCWDevice *vcdev, Error **errp)
+static void vfio_ccw_chp_notifier_handler(void *opaque)
+{
+VFIOCCWDevice *vcdev = opaque;
+
+if (!event_notifier_test_and_clear(&vcdev->chp_notifier)) {
+return;
+}
+
+/* TODO: further process on path informaion. */
+}
+
+static void vfio_ccw_register_event_notifier(VFIOCCWDevice *vcdev, int irq,
+ Error **errp)
 {
 VFIODevice *vdev = &vcdev->vdev;
 struct vfio_irq_info *irq_info;
 struct vfio_irq_set *irq_set;
 size_t argsz;
 int32_t *pfd;
-
-if (vdev->num_irqs < VFIO_CCW_IO_IRQ_INDEX + 1) {
-error_setg(errp, "vfio: unexpected number of io irqs %u",
-   vdev->num_irqs);
+EventNotifier *notifier;
+IOHandler *fd_read;
+
+switch (irq) {
+case VFIO_CCW_IO_IRQ_INDEX:
+notifier = &vcdev->io_notifier;
+fd_read = vfio_ccw_io_notifier_handler;
+break;
+case VFIO_CCW_CHP_IRQ_INDEX:
+notifier = &vcdev->chp_notifier;
+fd_read = vfio_ccw_chp_notifier_handler;
+break;
+default:
+error_setg(errp, "vfio: Unsupported device irq(%d) fd: %m", irq);
 return;
 }
 
 argsz = sizeof(*irq_info);
 irq_info = g_malloc0(argsz);
-irq_info->index = VFIO_CCW_IO_IRQ_INDEX;
+irq_info->index = irq;
 irq_info->argsz = argsz;
 if (ioctl(vdev->fd, VFIO_DEVICE_GET_IRQ_INFO,
   irq_info) < 0 || irq_info->count < 1) {
-error_setg_errno(errp, errno, "vfio: Error getting irq info");
+error_setg_errno(errp, errno, "vfio: Error getting irq(%d) info", irq);
 goto out_free_info;
 }
 
-if (event_notifier_init(&vcdev->io_notifier, 0)) {
+if (event_notifier_init(notifier, 0)) {
 error_setg_errno(errp, errno,
- "vfio: Unable to init event notifier for IO");
+ "vfio: Unable to init event notifier for irq(%d)",
+ irq);
 goto out_free_info;
 }
 
@@ -207,17 +232,18 @@ static void vfio_ccw_register_io_notifier(VFIOCCWDevice 
*vcdev, Error **errp)
 irq_set->argsz = argsz;
 irq_set->flags = VFIO_IRQ_SET_DATA_EVENTFD |
  VFIO_IRQ_SET_ACTION_TRIGGER;
-irq_set->index = VFIO_CCW_IO_IRQ_INDEX;
+irq_set->index = irq;
 irq_set->start = 0;
 irq_set->count = 1;
 pfd = (int32_t *) &irq_set->data;
 
-*pfd = event_notifier_get_fd(&vcdev->io_notifier);
-qemu_set_fd_handler(*pfd, vfio_ccw_io_notifier_handler, NULL, vcdev);
+*pfd = event_notifier_get_fd(notifier);
+qemu_set_fd_handler(*pfd, fd_read, NULL, vcdev);
 if (ioctl(vdev->fd, VFIO_DEVICE_SET_IRQS, irq_set)) {
-error_setg(errp, "vfio: Failed to set up io notification");
+error_setg(errp, "vfio: Failed to set up notification for irq(%d)",
+   irq);
 qemu_set_fd_handler(*pfd, NULL, NULL, vcdev);
-event_notifier_cleanup(&vcdev->io_notifier);
+event_notifier_cleanup(notifier);
 }
 
 g_free(irq_set);
@@ -226,30 +252,42 @@ out_free_info:
 g_free(irq_info);
 }
 
-static void vfio_ccw_unregister_io_notifier(VFIOCCWDevice *vcdev)
+static void vfio_ccw_unregister_event_notifier(VFIOCCWDevice *vcdev, int irq)
 {
 struct vfio_irq_set *irq_set;
 size_t argsz;
 int32_t *pfd;
+EventNotifier *notifier;
+
+switch (irq) {
+case VFIO_CCW_IO_IRQ_INDEX:
+notifier = &vcdev->io_notifier;
+break;
+case VFIO_CCW_CHP_IRQ_INDEX:
+notifier = &vcdev->chp_notifier;
+break;
+default:
+error_report("vfio: Unsupported device i

[Qemu-devel] [RFC PATCH 1/5] vfio: linux-headers update for vfio-ccw

2018-01-10 Thread Dong Jia Shi
This is a placeholder for a linux-headers update.

Signed-off-by: Dong Jia Shi 
---
 linux-headers/linux/vfio.h | 2 ++
 linux-headers/linux/vfio_ccw.h | 6 ++
 2 files changed, 8 insertions(+)

diff --git a/linux-headers/linux/vfio.h b/linux-headers/linux/vfio.h
index 4312e961ff..24d85be022 100644
--- a/linux-headers/linux/vfio.h
+++ b/linux-headers/linux/vfio.h
@@ -457,11 +457,13 @@ enum {
 
 enum {
VFIO_CCW_CONFIG_REGION_INDEX,
+   VFIO_CCW_SCHIB_REGION_INDEX,
VFIO_CCW_NUM_REGIONS
 };
 
 enum {
VFIO_CCW_IO_IRQ_INDEX,
+   VFIO_CCW_CHP_IRQ_INDEX,
VFIO_CCW_NUM_IRQS
 };
 
diff --git a/linux-headers/linux/vfio_ccw.h b/linux-headers/linux/vfio_ccw.h
index 5bf96c3812..4944dd946e 100644
--- a/linux-headers/linux/vfio_ccw.h
+++ b/linux-headers/linux/vfio_ccw.h
@@ -22,4 +22,10 @@ struct ccw_io_region {
__u32   ret_code;
 } __attribute__((packed));
 
+struct ccw_schib_region {
+__u8   cc;
+#define SCHIB_AREA_SIZE 52
+__u8   schib_area[SCHIB_AREA_SIZE];
+} __attribute__((packed));
+
 #endif
-- 
2.13.5




[Qemu-devel] [RFC PATCH 2/3] vfio: ccw: introduce channel path irq

2018-01-10 Thread Dong Jia Shi
This introduces a new irq for vfio-ccw to provide channel path
related event for userland.

Signed-off-by: Dong Jia Shi 
---
 drivers/s390/cio/vfio_ccw_ops.c | 29 +
 drivers/s390/cio/vfio_ccw_private.h |  2 ++
 include/uapi/linux/vfio.h   |  1 +
 3 files changed, 24 insertions(+), 8 deletions(-)

diff --git a/drivers/s390/cio/vfio_ccw_ops.c b/drivers/s390/cio/vfio_ccw_ops.c
index 9528fce2e7d9..972cfc8834fc 100644
--- a/drivers/s390/cio/vfio_ccw_ops.c
+++ b/drivers/s390/cio/vfio_ccw_ops.c
@@ -275,17 +275,20 @@ static int vfio_ccw_mdev_get_region_info(struct 
vfio_region_info *info,
 
 static int vfio_ccw_mdev_get_irq_info(struct vfio_irq_info *info)
 {
-   if (info->index != VFIO_CCW_IO_IRQ_INDEX)
+   switch (info->index) {
+   case VFIO_CCW_IO_IRQ_INDEX:
+   case VFIO_CCW_CHP_IRQ_INDEX:
+   info->count = 1;
+   info->flags = VFIO_IRQ_INFO_EVENTFD;
+   return 0;
+   default:
return -EINVAL;
-
-   info->count = 1;
-   info->flags = VFIO_IRQ_INFO_EVENTFD;
-
-   return 0;
+   }
 }
 
 static int vfio_ccw_mdev_set_irqs(struct mdev_device *mdev,
  uint32_t flags,
+ unsigned index,
  void __user *data)
 {
struct vfio_ccw_private *private;
@@ -295,7 +298,17 @@ static int vfio_ccw_mdev_set_irqs(struct mdev_device *mdev,
return -EINVAL;
 
private = dev_get_drvdata(mdev_parent_dev(mdev));
-   ctx = &private->io_trigger;
+
+   switch (index) {
+   case VFIO_CCW_IO_IRQ_INDEX:
+   ctx = &private->io_trigger;
+   break;
+   case VFIO_CCW_CHP_IRQ_INDEX:
+   ctx = &private->chp_trigger;
+   break;
+   default:
+   return -EINVAL;
+   }
 
switch (flags & VFIO_IRQ_SET_DATA_TYPE_MASK) {
case VFIO_IRQ_SET_DATA_NONE:
@@ -433,7 +446,7 @@ static ssize_t vfio_ccw_mdev_ioctl(struct mdev_device *mdev,
return ret;
 
data = (void __user *)(arg + minsz);
-   return vfio_ccw_mdev_set_irqs(mdev, hdr.flags, data);
+   return vfio_ccw_mdev_set_irqs(mdev, hdr.flags, hdr.index, data);
}
case VFIO_DEVICE_RESET:
return vfio_ccw_mdev_reset(mdev);
diff --git a/drivers/s390/cio/vfio_ccw_private.h 
b/drivers/s390/cio/vfio_ccw_private.h
index 460c8b90d834..da86f82dd7b9 100644
--- a/drivers/s390/cio/vfio_ccw_private.h
+++ b/drivers/s390/cio/vfio_ccw_private.h
@@ -33,6 +33,7 @@
  * @irb: irb info received from interrupt
  * @scsw: scsw info
  * @io_trigger: eventfd ctx for signaling userspace I/O results
+ * @chp_trigger: eventfd ctx for signaling userspace chp event
  * @io_work: work for deferral process of I/O handling
  */
 struct vfio_ccw_private {
@@ -50,6 +51,7 @@ struct vfio_ccw_private {
union scsw  scsw;
 
struct eventfd_ctx  *io_trigger;
+   struct eventfd_ctx  *chp_trigger;
struct work_struct  io_work;
 } __aligned(8);
 
diff --git a/include/uapi/linux/vfio.h b/include/uapi/linux/vfio.h
index c60244debf71..179a7492d53a 100644
--- a/include/uapi/linux/vfio.h
+++ b/include/uapi/linux/vfio.h
@@ -463,6 +463,7 @@ enum {
 
 enum {
VFIO_CCW_IO_IRQ_INDEX,
+   VFIO_CCW_CHP_IRQ_INDEX,
VFIO_CCW_NUM_IRQS
 };
 
-- 
2.13.5




[Qemu-devel] [RFC PATCH 0/3] vfio: ccw: basic channel path event handling

2018-01-10 Thread Dong Jia Shi
Hi Folks,

Background
==

Some days ago, we had a discussion on the topic of channel path virtualization.
Ref:
Subject: [PATCH 0/3] Channel Path realted CRW generation
Message-Id: <20170727015418.85407-1-bjsdj...@linux.vnet.ibm.com>
URL: https://lists.nongnu.org/archive/html/qemu-devel/2017-07/msg08414.html

Indeed that thread is not short and discussed many aspects in a
non-concentrated manner. The parts those are most valuable to me are:
1. a re-modelling for channel path is surely the best offer, but is not
   possible to have in the near future.
2. to enhance the path related functionalities, using PNO and PNOM might
   be something we can do for now. This may be something that I could improve
   without model related arguments.

So here I have this series targeting to add basic channel path event handling
for vfio-ccw -- no touch of the channel path modelling in both the kernel and
the QEMU side, but find a way to sync path status change to guest lazily using
SCSW_FLAGS_MASK_PNO and pmcw->pnom.  In short, I want to enhance path related
stuff (to be more specific: sync up path status to the guest) on a best effort
basis, which means in a way that won't get us invloed to do channel path
re-modelling.

What benifit can we get from this? The administrator of a virtual machine can
get uptodate (in some extent) status of the current using channel paths, so
he/she can monitor paths status and get path problem noticed timely (see the
example below).

I think we can start a new round discussion based on this series. So reviewers
can give their comments based on some code, and then we can decide if this is
we want or not.

As flagged with RFC, the intention of this series is to show what I have for
now, and what could the code look like in general. Thus I can get some early
feedbacks. I would expect to see opinions on:
- is the target (mentioned above) of this series welcomed or not.
- is the approach of this series good or bad.
So I can either move on with this (or with other suggested approach) or leave
it alone.

Basic Introduction of The Patches
=

This is the kernel counterpart, which mainly does:
1. add a schib vfio region for userland to _store_ subchannel information.
2. add a channel path vfio irq to notify userland with chp status change event.
3. add .chp_event handler for vfio-ccw driver, so the driver handles chp event,
   and signals userland about the event.

With the above work, userland can be signaled with chp related event, and then
it can read out uptodate SCHIB from the new region, and sync up path related
information to the corresponding virtual subchannel. So a guest can sense the
path update in some extent.

For the QEMU counterpart, please ref:
[RFC PATCH 0/5] vfio/ccw: basic channel path event handling

The QEMU counterpart mainly does:
1. add handling of the schib region, so that it can read out the newest schib
   information.
2. add handling of the chp irq, so that it can get notification of channel path
   status change.
3. once there is a chp status event, synchronize related information from the
   newest schib information to guest lazily.

What are still missing, thus need to be offered in the next version are:
- I/O termination and FSM state handling if currently we have I/O on the status
  switched path.
- Vary on/off event is not sensible to a guest.

Example
===

With both the kernel and Qemu parts applied, we can notice some new behaviors
of a channel path when we have a guest with a passed through vfio-ccw device
using it. The guest can reflect the chp status change of the host side lazily,
and synchronize the updated information.

For example:
0. Prepare a vfio subchannel on the host:
[root@host ~]# lscss --vfio 013f
MDEV  Subchan.  PIM PAM POM  CHPIDs
--
6dfd3ec5-e8b3-4e18-a6fe-57bc9eceb920  0.0.013f  f0  f0  ff   42434445 

1. Pass-through subchannel 0.0.013f to a guest:
-device vfio-ccw,sysfsdev="$MDEV_FILE_PATH",devno=0.0.3f3f

2. Start the guest and check the device and path information:
[root@guest ~]# lscss 0002
Device   Subchan.  DevType CU Type Use  PIM PAM POM  CHPIDs
--
0.0.3f3f 0.0.0002  3390/0c 3990/e9  f0  f0  ff   42434445  
[root@guest ~]# lschp 
CHPID  Vary  Cfg.  Type  Cmg  Shared  PCHID

0.00   1 - 32--   -
0.42   1 3 1b--   -
0.43   1 3 1b--   -
0.44   1 3 1b--   -
0.45   1 3 1b--   -

3. On the host, configure off one path.
[root@host ~]# chchp -c 0 42

4. On the guest, check the status:
[root@guest ~]# lscss 0002
Device   Subchan.  DevType CU Type Use  PIM PAM POM  CHPIDs
--
0.0.3f3f 0.0.000

[Qemu-devel] [RFC PATCH 1/3] vfio: ccw: introduce schib region

2018-01-10 Thread Dong Jia Shi
This introduces a new region for vfio-ccw to provide subchannel
information for user space.

Signed-off-by: Dong Jia Shi 
---
 drivers/s390/cio/vfio_ccw_fsm.c | 21 ++
 drivers/s390/cio/vfio_ccw_ops.c | 79 +++--
 drivers/s390/cio/vfio_ccw_private.h |  3 ++
 include/uapi/linux/vfio.h   |  1 +
 include/uapi/linux/vfio_ccw.h   |  6 +++
 5 files changed, 90 insertions(+), 20 deletions(-)

diff --git a/drivers/s390/cio/vfio_ccw_fsm.c b/drivers/s390/cio/vfio_ccw_fsm.c
index c30420c517b1..be081ccabea3 100644
--- a/drivers/s390/cio/vfio_ccw_fsm.c
+++ b/drivers/s390/cio/vfio_ccw_fsm.c
@@ -172,6 +172,22 @@ static void fsm_irq(struct vfio_ccw_private *private,
complete(private->completion);
 }
 
+static void fsm_update_subch(struct vfio_ccw_private *private,
+enum vfio_ccw_event event)
+{
+   struct subchannel *sch;
+
+   sch = private->sch;
+   if (cio_update_schib(sch)) {
+   private->schib_region.cc = 3;
+   return;
+   }
+
+   private->schib_region.cc = 0;
+   memcpy(private->schib_region.schib_area, &sch->schib,
+  sizeof(sch->schib));
+}
+
 /*
  * Device statemachine
  */
@@ -180,25 +196,30 @@ fsm_func_t 
*vfio_ccw_jumptable[NR_VFIO_CCW_STATES][NR_VFIO_CCW_EVENTS] = {
[VFIO_CCW_EVENT_NOT_OPER]   = fsm_nop,
[VFIO_CCW_EVENT_IO_REQ] = fsm_io_error,
[VFIO_CCW_EVENT_INTERRUPT]  = fsm_disabled_irq,
+   [VFIO_CCW_EVENT_UPDATE_SUBCH]   = fsm_update_subch,
},
[VFIO_CCW_STATE_STANDBY] = {
[VFIO_CCW_EVENT_NOT_OPER]   = fsm_notoper,
[VFIO_CCW_EVENT_IO_REQ] = fsm_io_error,
[VFIO_CCW_EVENT_INTERRUPT]  = fsm_irq,
+   [VFIO_CCW_EVENT_UPDATE_SUBCH]   = fsm_update_subch,
},
[VFIO_CCW_STATE_IDLE] = {
[VFIO_CCW_EVENT_NOT_OPER]   = fsm_notoper,
[VFIO_CCW_EVENT_IO_REQ] = fsm_io_request,
[VFIO_CCW_EVENT_INTERRUPT]  = fsm_irq,
+   [VFIO_CCW_EVENT_UPDATE_SUBCH]   = fsm_update_subch,
},
[VFIO_CCW_STATE_BOXED] = {
[VFIO_CCW_EVENT_NOT_OPER]   = fsm_notoper,
[VFIO_CCW_EVENT_IO_REQ] = fsm_io_busy,
[VFIO_CCW_EVENT_INTERRUPT]  = fsm_irq,
+   [VFIO_CCW_EVENT_UPDATE_SUBCH]   = fsm_update_subch,
},
[VFIO_CCW_STATE_BUSY] = {
[VFIO_CCW_EVENT_NOT_OPER]   = fsm_notoper,
[VFIO_CCW_EVENT_IO_REQ] = fsm_io_busy,
[VFIO_CCW_EVENT_INTERRUPT]  = fsm_irq,
+   [VFIO_CCW_EVENT_UPDATE_SUBCH]   = fsm_update_subch,
},
 };
diff --git a/drivers/s390/cio/vfio_ccw_ops.c b/drivers/s390/cio/vfio_ccw_ops.c
index 41eeb57d68a3..9528fce2e7d9 100644
--- a/drivers/s390/cio/vfio_ccw_ops.c
+++ b/drivers/s390/cio/vfio_ccw_ops.c
@@ -13,6 +13,11 @@
 
 #include "vfio_ccw_private.h"
 
+#define VFIO_CCW_OFFSET_SHIFT   40
+#define VFIO_CCW_OFFSET_TO_INDEX(off)  (off >> VFIO_CCW_OFFSET_SHIFT)
+#define VFIO_CCW_INDEX_TO_OFFSET(index)((u64)(index) << 
VFIO_CCW_OFFSET_SHIFT)
+#define VFIO_CCW_OFFSET_MASK   (((u64)(1) << VFIO_CCW_OFFSET_SHIFT) - 1)
+
 static int vfio_ccw_mdev_reset(struct mdev_device *mdev)
 {
struct vfio_ccw_private *private;
@@ -168,14 +173,31 @@ static ssize_t vfio_ccw_mdev_read(struct mdev_device 
*mdev,
  loff_t *ppos)
 {
struct vfio_ccw_private *private;
-   struct ccw_io_region *region;
+   void *region;
+   u32 index;
+   loff_t pos;
+
+   index = VFIO_CCW_OFFSET_TO_INDEX(*ppos);
+   pos = (*ppos) & VFIO_CCW_OFFSET_MASK;
+   private = dev_get_drvdata(mdev_parent_dev(mdev));
 
-   if (*ppos + count > sizeof(*region))
+   switch (index) {
+   case VFIO_CCW_CONFIG_REGION_INDEX:
+   if (pos + count > sizeof(struct ccw_io_region))
+   return -EINVAL;
+   region = &private->io_region;
+   break;
+   case VFIO_CCW_SCHIB_REGION_INDEX:
+   if (pos + count > sizeof(struct ccw_schib_region))
+   return -EINVAL;
+   region = &private->schib_region;
+   vfio_ccw_fsm_event(private, VFIO_CCW_EVENT_UPDATE_SUBCH);
+   break;
+   default:
return -EINVAL;
+   }
 
-   private = dev_get_drvdata(mdev_parent_dev(mdev));
-   region = &private->io_region;
-   if (copy_to_user(buf, (void *)region + *ppos, count))
+   if (copy_to_user(buf, region + pos, count))
return -EFAULT;
 
return count;
@@ -187,23 +209,35 @@ static ssize_t vfio_ccw_mdev_write(struct mdev_device 
*mdev,
   loff_t *ppos)
 {
struct vfio_ccw_private *private;
-   struct ccw_io_region *region;

Re: [Qemu-devel] [PATCH v3 00/21] RISC-V QEMU Port Submission v3

2018-01-10 Thread no-reply
Hi,

This series seems to have some coding style problems. See output below for
more information:

Type: series
Message-id: 1515637324-96034-1-git-send-email-...@sifive.com
Subject: [Qemu-devel] [PATCH v3 00/21] RISC-V QEMU Port Submission v3

=== TEST SCRIPT BEGIN ===
#!/bin/bash

BASE=base
n=1
total=$(git log --oneline $BASE.. | wc -l)
failed=0

git config --local diff.renamelimit 0
git config --local diff.renames True

commits="$(git log --format=%H --reverse $BASE..)"
for c in $commits; do
echo "Checking PATCH $n/$total: $(git log -n 1 --format=%s $c)..."
if ! git show $c --format=email | ./scripts/checkpatch.pl --mailback -; then
failed=1
echo
fi
n=$((n+1))
done

exit $failed
=== TEST SCRIPT END ===

Updating 3c8cf5a9c21ff8782164d1def7f44bd888713384
Switched to a new branch 'test'
7f192f5ceb RISC-V Build Infrastructure
91f292f2cc SiFive Freedom U500 RISC-V Machine
a80f42638c SiFive Freedom E300 RISC-V Machine
c2519d2f95 SiFive RISC-V PRCI Block
d22164e263 SiFive RISC-V UART Device
319d67278f RISC-V VirtIO Machine
0d1f8ea1fd RISC-V Spike Machines
5d048d84c6 SiFive RISC-V PLIC Block
87dfc5ca6a SiFive RISC-V CLINT Block
ac1e42ddb2 RISC-V HART Array
63b446e985 RISC-V HTIF Console
1397d2776b RISC-V Linux User Emulation
d2512fa8ad RISC-V Physical Memory Protection
675d33bbe3 RISC-V TCG Code Generation
a5ea9ea97f RISC-V GDB Stub
a170177cab RISC-V FPU Support
61678e3f7e RISC-V CPU Helpers
64b8c82021 RISC-V Disassembler
3b561b5019 RISC-V CPU Core Definition
3cb33c620c RISC-V ELF Machine Definition
806fcf588f RISC-V Maintainers

=== OUTPUT BEGIN ===
Checking PATCH 1/21: RISC-V Maintainers...
Checking PATCH 2/21: RISC-V ELF Machine Definition...
Checking PATCH 3/21: RISC-V CPU Core Definition...
Checking PATCH 4/21: RISC-V Disassembler...
WARNING: line over 80 characters
#653: FILE: disas/riscv.c:603:
+static const rvc_constraint rvcc_jalr[] = { rvc_rd_eq_ra, rvc_imm_eq_zero, 
rvc_end };

ERROR: line over 90 characters
#654: FILE: disas/riscv.c:604:
+static const rvc_constraint rvcc_nop[] = { rvc_rd_eq_x0, rvc_rs1_eq_x0, 
rvc_imm_eq_zero, rvc_end };

WARNING: line over 80 characters
#684: FILE: disas/riscv.c:634:
+static const rvc_constraint rvcc_ret[] = { rvc_rd_eq_x0, rvc_rs1_eq_ra, 
rvc_end };

WARNING: line over 80 characters
#685: FILE: disas/riscv.c:635:
+static const rvc_constraint rvcc_jr[] = { rvc_rd_eq_x0, rvc_imm_eq_zero, 
rvc_end };

WARNING: line over 80 characters
#686: FILE: disas/riscv.c:636:
+static const rvc_constraint rvcc_rdcycle[] = { rvc_rs1_eq_x0, 
rvc_csr_eq_0xc00, rvc_end };

WARNING: line over 80 characters
#687: FILE: disas/riscv.c:637:
+static const rvc_constraint rvcc_rdtime[] = { rvc_rs1_eq_x0, rvc_csr_eq_0xc01, 
rvc_end };

ERROR: line over 90 characters
#688: FILE: disas/riscv.c:638:
+static const rvc_constraint rvcc_rdinstret[] = { rvc_rs1_eq_x0, 
rvc_csr_eq_0xc02, rvc_end };

ERROR: line over 90 characters
#689: FILE: disas/riscv.c:639:
+static const rvc_constraint rvcc_rdcycleh[] = { rvc_rs1_eq_x0, 
rvc_csr_eq_0xc80, rvc_end };

WARNING: line over 80 characters
#690: FILE: disas/riscv.c:640:
+static const rvc_constraint rvcc_rdtimeh[] = { rvc_rs1_eq_x0, 
rvc_csr_eq_0xc81, rvc_end };

ERROR: line over 90 characters
#691: FILE: disas/riscv.c:641:
+static const rvc_constraint rvcc_rdinstreth[] = { rvc_rs1_eq_x0, 
rvc_csr_eq_0xc80, rvc_end };

WARNING: line over 80 characters
#692: FILE: disas/riscv.c:642:
+static const rvc_constraint rvcc_frcsr[] = { rvc_rs1_eq_x0, rvc_csr_eq_0x003, 
rvc_end };

WARNING: line over 80 characters
#693: FILE: disas/riscv.c:643:
+static const rvc_constraint rvcc_frrm[] = { rvc_rs1_eq_x0, rvc_csr_eq_0x002, 
rvc_end };

WARNING: line over 80 characters
#694: FILE: disas/riscv.c:644:
+static const rvc_constraint rvcc_frflags[] = { rvc_rs1_eq_x0, 
rvc_csr_eq_0x001, rvc_end };

ERROR: line over 90 characters
#1093: FILE: disas/riscv.c:1043:
+{ "c.addi4spn", rv_codec_ciw_4spn, rv_fmt_rd_rs1_imm, NULL, rv_op_addi, 
rv_op_addi, rv_op_addi },

WARNING: line over 80 characters
#1094: FILE: disas/riscv.c:1044:
+{ "c.fld", rv_codec_cl_ld, rv_fmt_frd_offset_rs1, NULL, rv_op_fld, 
rv_op_fld, 0 },

WARNING: line over 80 characters
#1095: FILE: disas/riscv.c:1045:
+{ "c.lw", rv_codec_cl_lw, rv_fmt_rd_offset_rs1, NULL, rv_op_lw, rv_op_lw, 
rv_op_lw },

WARNING: line over 80 characters
#1097: FILE: disas/riscv.c:1047:
+{ "c.fsd", rv_codec_cs_sd, rv_fmt_frs2_offset_rs1, NULL, rv_op_fsd, 
rv_op_fsd, 0 },

WARNING: line over 80 characters
#1098: FILE: disas/riscv.c:1048:
+{ "c.sw", rv_codec_cs_sw, rv_fmt_rs2_offset_rs1, NULL, rv_op_sw, rv_op_sw, 
rv_op_sw },

WARNING: line over 80 characters
#1100: FILE: disas/riscv.c:1050:
+{ "c.nop", rv_codec_ci_none, rv_fmt_none, NULL, rv_op_addi, rv_op_addi, 
rv_op_addi },

ERROR: line over 90 characters
#1101: FILE: disas/riscv.c:1051:
+{ "c.addi", rv_codec_ci, rv_fmt_rd_rs1_imm, NULL, rv_op_addi, rv_op_addi, 
rv_op_addi },

ERROR: line over 90 characters
#1103: FILE: disas/

Re: [Qemu-devel] [Qemu-discuss] ppc and icount

2018-01-10 Thread David Gibson
On Wed, Jan 10, 2018 at 10:34:18AM +, Peter Maydell wrote:
> On 10 January 2018 at 08:57, Steven Seeger
>  wrote:
> > Sorry for another post. I did a bisect and found what is the bad commit for
> > me:
> >
> > 044897ef4a22af89aecb8df509477beba0a2e0ce is the first bad commit
> > commit 044897ef4a22af89aecb8df509477beba0a2e0ce
> > Author: Richard Purdie 
> > Date:   Mon Dec 4 22:25:43 2017 +
> >
> > target/ppc: Fix system lockups caused by interrupt_request state
> > corruption
> 
> Great -- thanks for the bisect. Let's take this to the -devel list;
> I've cc'd the PPC maintainers.
> 
> Context: Steven reports that we broke -icount for PPC guests with
> this commit:
> 
> $ ./build/all/ppc-softmmu/qemu-system-ppc  -icount auto
> qemu: fatal: Raised interrupt while not in I/O function
> NIP fff08978   LR fff08904 CTR  XER  CPU#0
> MSR  HID0   HF  iidx 3 didx 3
> Bad icount read
> 
> The backtrace from the assert is:
> 
> #0  tcg_handle_interrupt (cpu=0x77fc2010, mask=4) at qemu/accel/tcg/tcg-
> all.c:58
> #1  0x55962aa4 in cpu_interrupt (cpu=0x77fc2010, mask=4) at qemu/
> include/qom/cpu.h:859
> #2  0x55962e55 in cpu_interrupt_exittb (cs=0x77fc2010) at qemu/
> target/ppc/helper_regs.h:105
> #3  0x55964505 in do_rfi (env=0x77fca2b0, nip=197460, msr=4096)
> at qemu/target/ppc/excp_helper.c:998
> #4  0x55964555 in helper_rfi (env=0x77fca2b0) at qemu/target/ppc/
> excp_helper.c:1008
> #5  0x7fffe7c124b9 in code_gen_buffer ()
> 
> The problem is that icount was relying on the previous
> handling of do_rfi() as "just set state as we know we're
> going to be last insn in the TB".
> 
> Not sure how best to fix this (mark the insn as IO ok?)

Aw, man.  I've become target-ppc tcg maintainer by default, but tbh my
knowledge wasn't really deep enough to understand the problem that
044897ef was fixing in the first place.  And I barely know what icount
does at all.

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


signature.asc
Description: PGP signature


Re: [Qemu-devel] [PULL 00/12] ppc-for-2.12 queue 20180108

2018-01-10 Thread David Gibson
On Wed, Jan 10, 2018 at 02:33:41PM +0100, Paolo Bonzini wrote:
> On 10/01/2018 02:55, David Gibson wrote:
> > On Tue, Jan 09, 2018 at 03:15:25PM +, Peter Maydell wrote:
> >> On 9 January 2018 at 12:16, David Gibson  
> >> wrote:
> >>> Thanks.  Even if you can identify which patch it is and we can
> >>> postpone that one would be a bug help.
> >>
> >> Bisection blames this one:
> >>
> >> pbonz...@redhat.com (1):
> >>   target-ppc: optimize cmp translation
> > 
> > Aha!  Ok, I'll pull that one out until we find a fix.
> 
> Richard posted one, it's an ARM32 backend bug.
> 
> > [snip]
> >> (This is a build for arm32, running in a chroot on an aarch64
> >> box, non-debug build.)
> > 
> > Ah.. but since it's a chroot, still an aarch64 cpu behind it all.
> 
> No, it's running 32-bit ARM code.

Ah.  But maybe a different version to older ARM32s?

I'm trying to figure out why I entirely failed to reproduce this on a
Raspberry Pi 1 (and a couple of other arm32 machines, but I forget the
details of them).

>   I
> > think the machines I managed to borrow were all much older slower
> > really truly arm32 machines, which I guess didn't show the problem.
> > 
> > Oh.. and probably a debug (default) build as well.
> > 
> 

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


signature.asc
Description: PGP signature


Re: [Qemu-devel] [PATCH v1 2/2] intel-iommu: Extend address width to 48 bits

2018-01-10 Thread Liu, Yi L
> -Original Message-
> From: Qemu-devel [mailto:qemu-devel-bounces+yi.l.liu=intel@nongnu.org] On
> Behalf Of Prasad Singamsetty
> Sent: Thursday, January 11, 2018 8:06 AM
> To: Liu, Yi L 
> Cc: ehabk...@redhat.com; m...@redhat.com; konrad.w...@oracle.com; qemu-
> de...@nongnu.org; pet...@redhat.com; imamm...@redhat.com;
> pbonz...@redhat.com; r...@twiddle.net
> Subject: Re: [Qemu-devel] [PATCH v1 2/2] intel-iommu: Extend address width to 
> 48
> bits
> 
> 
> Hi Yi L,
> 
> On 12/1/2017 3:29 AM, Liu, Yi L wrote:
> > On Tue, Nov 14, 2017 at 06:13:50PM -0500, prasad.singamse...@oracle.com
> wrote:
> >> From: Prasad Singamsetty 
> >>
> >> The current implementation of Intel IOMMU code only supports 39 bits
> >> iova address width. This patch provides a new parameter (x-aw-bits)
> >> for intel-iommu to extend its address width to 48 bits but keeping
> >> the default the same (39 bits). The reason for not changing the
> >> default is to avoid potential compatibility problems with live
> >> migration of intel-iommu enabled QEMU guest. The only valid values for 
> >> 'x-aw-
> bits'
> >> parameter are 39 and 48.
> >>
> >> After enabling larger address width (48), we should be able to map
> >> larger iova addresses in the guest. For example, a QEMU guest that is
> >> configured with large memory ( >=1TB ). To check whether 48 bits aw
> >> is enabled, we can grep in the guest dmesg output with line:
> >> "DMAR: Host address width 48".
> >>
> >> Signed-off-by: Prasad Singamsetty 
> >
> > Prasad,
> >
> > Have you tested the scenario with physical device assigned to a guest?
> 
> Sorry for the long delay in following up on this.
> 
> I did some testing with vfio-pci devices assigned to the guest.
> This is done on the latest qemu code base (2.11.50).
> 
> Here are the test cases/results:
> 
> 1. Booting VM with one or two vfio-pci (network) devices
> and multiple memory size configs (up to 256G). Assigned pci
> devices (network interfaces) worked fine and no issues
> in using these devices. This test is run for both address
> widths (39 and 48).
> 2. If the guest VM is configured to use 512G and address
> width is the default 39 bits then guest OS fails to
> boot due to DMA failures. The same is observed without
> applying the patch set. The guest OS ends up booting into
> dracut shell. This problem is not seen if we set the address
> width to 48 bits. So, the patch set addresses a latent bug
> with large memory config.
> 
> ISSUE - VM could take long time to boot with vfio-pci devices
> 
> Qemu process could take a long time to initialize the VM when vfio-pci device 
> is
> configured depending on the memory size. For small memory sizes (less than 
> 32G) it
> is not noticeable (<30s). For larger memory sizes, the delay ranges from 
> several
> minutes and longer (2-40min). For more than 512G, qemu process appears to hang
> but can be interrupted. This behavior is observed without patch set applied 
> also. The
> slowness is due to VFIO_IOMMU_MAP_DMA ioctl taking long time to map the
> system ram assigned to the guest. This is when qemu process is initializing 
> the vfio
> device where it maps all the assigned ram memory regions. Here is the stack 
> trace
> from gdb:
> 
> #0  vfio_dma_map (container=0x582709d0, iova=4294967296,
>size=547608330240, vaddr=0x7f7fd3e0,
>readonly=false)
>  at /home/psingams/qemu-upstream-v2/hw/vfio/common.c:250
> #1  0x5584f471 in vfio_listener_region_add(
>listener=0x582709e0,
>section=0x7fffc7f0)
>  at /home/psingams/qemu-upstream-v2/hw/vfio/common.c:521
> #2  0x557f08fc in listener_add_address_space (
>listener=0x582709e0, as=0x5813b790)
>  at /home/psingams/qemu-upstream-v2/memory.c:2600
> #3  0x557f0bbe in memory_listener_register (
>listener=0x582709e0, as=0x5813b790)
>  at /home/psingams/qemu-upstream-v2/memory.c:2643
> #4  0x558511ef in vfio_connect_container (group=0x58270960,
>as=0x5813b790, errp=0x7fffdae8)
>  at /home/psingams/qemu-upstream-v2/hw/vfio/common.c:1130
> 
> (gdb) print/x size
> $2 = 0x7f8000
> 
> This is before guest OS gets to boot. The host is running 4.15.0-rc6 kernel 
> with qemu
> version 2.11.50.
> 
> I am not sure if this is a known issue and someone is already working on 
> fixing the
> implementation of VFIO_IOMMU_MAP_DMA ioctl.

It seems to be same issue with the one reported by Bob.
https://lists.gnu.org/archive/html/qemu-devel/2017-12/msg05098.html

Per chatted with them, the reason looks to be no enough memory in host. how 
about
the memory size in your host?

> This issue is not related to this patch set and need to be investigated 
> separately.
> 
> Please let me know if there are other comments on this patch set.
> 

Regards,
Yi L


Re: [Qemu-devel] virtio-9p: hot-plug/unplug about virtio-9p device

2018-01-10 Thread sochin . jiang


On 2018/1/8 18:10, Greg Kurz wrote:
> On Tue, 19 Dec 2017 13:41:12 +0800
> sochin.jiang  wrote:
>
>>  Hi, guys.
>>
>> I'm looking for the hot-plug/unplug features of virtio-9p device 
>> recently, and found there's a lack of support.
>>
>> I am wondering why ? Is there a reason. Actually, I write a qmp command 
>> to support fsdev_add, then a device_add qmp will
>>
>> successfully add a virtio-9p device(just like virtio-blk).
>>
>>Whether there is some concerns that we haven't support this ? hope for a 
>> reply, thanks.
>>
>>
>> sochin.
>>
> Hi Sochin,
>
> I've just discovered this mail by chance. Please note I'm the only active
> maintainer for virtio-9p. You really should check the content of MAINTAINERS
> and Cc the appropriate people. :)
>
> Now, back to your question. Yes, there's only some partial support for
> hot-plug/unplug. Mostly because nobody cared to work on it I guess.
>
> So, indeed, we don't have fsdev_add/fsdev_del, ie, we can only rely on
> shared directories specified on the QEMU command line.
>
> On the virtio-9p device side, hotplug is supported, ie, device_add virtio-9p
> works as expected.
>
> Hot-unplug is different as it requires some coordination with the guest. The
> current status is that it requires the 9p shared directory to be unmounted
> in the guest: if you do device_del while the directory is mounted in a linux
> guest, you'll get these messages in the guest syslog:
>
> kernel:9pnet_virtio virtio2: p9_virtio_remove: waiting for device in use.
>
> If the 9p directory is unmounted at some point, then the hot unplug
> sequence will eventually succeed.
>
> But this shouldn't be done like this: the guest should cancel inflight
> requests and cause any new I/O requests in the guest to fail right away.
> I have a tentative patch for the linux driver I can share if you want.
>
> Cheers,
>
> --
> Greg
>
> .
>


Thanks, Greg.

Indeed, I got those error messages while trying to do device_del with
shared directory mounted in the guest. I really would like to see you patch for 
linux driver.

About virtio-9p, we are actually considering to use it for hypervisor-based 
container, 
a support of hotplug/unplug will be better, also I believe there will be more 
people to work on it.


Sochin.






[Qemu-devel] [PATCH v3 08/21] RISC-V TCG Code Generation

2018-01-10 Thread Michael Clark
TCG code generation for the RV32IMAFDC and RV64IMAFDC. The QEMU
RISC-V code generator has complete coverage for the Base ISA v2.2,
Privileged ISA v1.9.1 and Privileged ISA v1.10:

- RISC-V Instruction Set Manual Volume I: User-Level ISA Version 2.2
- RISC-V Instruction Set Manual Volume II: Privileged ISA Version 1.9.1
- RISC-V Instruction Set Manual Volume II: Privileged ISA Version 1.10

Signed-off-by: Michael Clark 
---
 target/riscv/instmap.h   |  377 +
 target/riscv/translate.c | 1982 ++
 2 files changed, 2359 insertions(+)
 create mode 100644 target/riscv/instmap.h
 create mode 100644 target/riscv/translate.c

diff --git a/target/riscv/instmap.h b/target/riscv/instmap.h
new file mode 100644
index 000..5121f63
--- /dev/null
+++ b/target/riscv/instmap.h
@@ -0,0 +1,377 @@
+/*
+ * RISC-V emulation for qemu: Instruction decode helpers
+ *
+ * Author: Sagar Karandikar, sag...@eecs.berkeley.edu
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see .
+ */
+
+#define MASK_OP_MAJOR(op)  (op & 0x7F)
+enum {
+/* rv32i, rv64i, rv32m */
+OPC_RISC_LUI= (0x37),
+OPC_RISC_AUIPC  = (0x17),
+OPC_RISC_JAL= (0x6F),
+OPC_RISC_JALR   = (0x67),
+OPC_RISC_BRANCH = (0x63),
+OPC_RISC_LOAD   = (0x03),
+OPC_RISC_STORE  = (0x23),
+OPC_RISC_ARITH_IMM  = (0x13),
+OPC_RISC_ARITH  = (0x33),
+OPC_RISC_FENCE  = (0x0F),
+OPC_RISC_SYSTEM = (0x73),
+
+/* rv64i, rv64m */
+OPC_RISC_ARITH_IMM_W = (0x1B),
+OPC_RISC_ARITH_W = (0x3B),
+
+/* rv32a, rv64a */
+OPC_RISC_ATOMIC = (0x2F),
+
+/* floating point */
+OPC_RISC_FP_LOAD = (0x7),
+OPC_RISC_FP_STORE = (0x27),
+
+OPC_RISC_FMADD = (0x43),
+OPC_RISC_FMSUB = (0x47),
+OPC_RISC_FNMSUB = (0x4B),
+OPC_RISC_FNMADD = (0x4F),
+
+OPC_RISC_FP_ARITH = (0x53),
+};
+
+#define MASK_OP_ARITH(op)   (MASK_OP_MAJOR(op) | (op & ((0x7 << 12) | \
+(0x7F << 25
+enum {
+OPC_RISC_ADD   = OPC_RISC_ARITH | (0x0 << 12) | (0x00 << 25),
+OPC_RISC_SUB   = OPC_RISC_ARITH | (0x0 << 12) | (0x20 << 25),
+OPC_RISC_SLL   = OPC_RISC_ARITH | (0x1 << 12) | (0x00 << 25),
+OPC_RISC_SLT   = OPC_RISC_ARITH | (0x2 << 12) | (0x00 << 25),
+OPC_RISC_SLTU  = OPC_RISC_ARITH | (0x3 << 12) | (0x00 << 25),
+OPC_RISC_XOR   = OPC_RISC_ARITH | (0x4 << 12) | (0x00 << 25),
+OPC_RISC_SRL   = OPC_RISC_ARITH | (0x5 << 12) | (0x00 << 25),
+OPC_RISC_SRA   = OPC_RISC_ARITH | (0x5 << 12) | (0x20 << 25),
+OPC_RISC_OR= OPC_RISC_ARITH | (0x6 << 12) | (0x00 << 25),
+OPC_RISC_AND   = OPC_RISC_ARITH | (0x7 << 12) | (0x00 << 25),
+
+/* RV64M */
+OPC_RISC_MUL= OPC_RISC_ARITH | (0x0 << 12) | (0x01 << 25),
+OPC_RISC_MULH   = OPC_RISC_ARITH | (0x1 << 12) | (0x01 << 25),
+OPC_RISC_MULHSU = OPC_RISC_ARITH | (0x2 << 12) | (0x01 << 25),
+OPC_RISC_MULHU  = OPC_RISC_ARITH | (0x3 << 12) | (0x01 << 25),
+
+OPC_RISC_DIV= OPC_RISC_ARITH | (0x4 << 12) | (0x01 << 25),
+OPC_RISC_DIVU   = OPC_RISC_ARITH | (0x5 << 12) | (0x01 << 25),
+OPC_RISC_REM= OPC_RISC_ARITH | (0x6 << 12) | (0x01 << 25),
+OPC_RISC_REMU   = OPC_RISC_ARITH | (0x7 << 12) | (0x01 << 25),
+};
+
+
+#define MASK_OP_ARITH_IMM(op)   (MASK_OP_MAJOR(op) | (op & (0x7 << 12)))
+enum {
+OPC_RISC_ADDI   = OPC_RISC_ARITH_IMM | (0x0 << 12),
+OPC_RISC_SLTI   = OPC_RISC_ARITH_IMM | (0x2 << 12),
+OPC_RISC_SLTIU  = OPC_RISC_ARITH_IMM | (0x3 << 12),
+OPC_RISC_XORI   = OPC_RISC_ARITH_IMM | (0x4 << 12),
+OPC_RISC_ORI= OPC_RISC_ARITH_IMM | (0x6 << 12),
+OPC_RISC_ANDI   = OPC_RISC_ARITH_IMM | (0x7 << 12),
+OPC_RISC_SLLI   = OPC_RISC_ARITH_IMM | (0x1 << 12), /* additional part of
+   IMM */
+OPC_RISC_SHIFT_RIGHT_I = OPC_RISC_ARITH_IMM | (0x5 << 12) /* SRAI, SRLI */
+};
+
+#define MASK_OP_BRANCH(op) (MASK_OP_MAJOR(op) | (op & (0x7 << 12)))
+enum {
+OPC_RISC_BEQ  = OPC_RISC_BRANCH  | (0x0  << 12),
+OPC_RISC_BNE  = OPC_RISC_BRANCH  | (0x1  << 12),
+OPC_RISC_BLT  = OPC_RISC_BRANCH  | (0x4  << 12),
+OPC_RISC_BGE  = OPC_RISC_BRANCH  | (0x5  << 12),
+OPC_RISC_BLTU = OPC_RISC_BRANCH  | (0x6  << 12),
+OPC_RISC_BGEU = OPC_RISC_BRANCH  | (0x7  << 12)
+};
+
+enum {
+OPC_RISC_ADDIW   = OPC_RISC_ARITH_IMM_W | (0x0 << 1

[Qemu-devel] [PATCH v3 21/21] RISC-V Build Infrastructure

2018-01-10 Thread Michael Clark
This adds RISC-V into the build system enabling the following targets:

- riscv32-softmmu
- riscv64-softmmu
- riscv32-linux-user
- riscv64-linux-user

This adds defaults configs for RISC-V, enables the build for the RISC-V
CPU core, hardware, and Linux User Emulation. The 'qemu-binfmt-conf.sh'
script is updated to add the RISC-V ELF magic.

Expected checkpatch errors for consistency reasons:

ERROR: line over 90 characters
FILE: scripts/qemu-binfmt-conf.sh
Signed-off-by: Michael Clark 
---
 Makefile.objs  |  1 +
 arch_init.c|  2 ++
 configure  | 11 +++
 cpus.c |  6 ++
 default-configs/riscv32-linux-user.mak |  1 +
 default-configs/riscv32-softmmu.mak|  4 
 default-configs/riscv64-linux-user.mak |  1 +
 default-configs/riscv64-softmmu.mak|  4 
 hw/riscv/Makefile.objs | 12 
 include/sysemu/arch_init.h |  1 +
 qapi-schema.json   | 14 +-
 scripts/qemu-binfmt-conf.sh| 13 -
 target/riscv/Makefile.objs |  2 ++
 target/riscv/trace-events  |  1 +
 14 files changed, 71 insertions(+), 2 deletions(-)
 create mode 100644 default-configs/riscv32-linux-user.mak
 create mode 100644 default-configs/riscv32-softmmu.mak
 create mode 100644 default-configs/riscv64-linux-user.mak
 create mode 100644 default-configs/riscv64-softmmu.mak
 create mode 100644 hw/riscv/Makefile.objs
 create mode 100644 target/riscv/Makefile.objs
 create mode 100644 target/riscv/trace-events

diff --git a/Makefile.objs b/Makefile.objs
index 285c6f3..ae8658e 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -164,6 +164,7 @@ trace-events-subdirs += target/mips
 trace-events-subdirs += target/sparc
 trace-events-subdirs += target/s390x
 trace-events-subdirs += target/ppc
+trace-events-subdirs += target/riscv
 trace-events-subdirs += qom
 trace-events-subdirs += linux-user
 trace-events-subdirs += qapi
diff --git a/arch_init.c b/arch_init.c
index a0b8ed6..dcf356b 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -69,6 +69,8 @@ int graphic_depth = 32;
 #define QEMU_ARCH QEMU_ARCH_OPENRISC
 #elif defined(TARGET_PPC)
 #define QEMU_ARCH QEMU_ARCH_PPC
+#elif defined(TARGET_RISCV)
+#define QEMU_ARCH QEMU_ARCH_RISCV
 #elif defined(TARGET_S390X)
 #define QEMU_ARCH QEMU_ARCH_S390X
 #elif defined(TARGET_SH4)
diff --git a/configure b/configure
index 6a04082..a8151f9 100755
--- a/configure
+++ b/configure
@@ -6565,6 +6565,14 @@ case "$target_name" in
 echo "TARGET_ABI32=y" >> $config_target_mak
 gdb_xml_files="power64-core.xml power-fpu.xml power-altivec.xml 
power-spe.xml power-vsx.xml"
   ;;
+  riscv32)
+TARGET_BASE_ARCH=riscv
+TARGET_ABI_DIR=riscv
+  ;;
+  riscv64)
+TARGET_BASE_ARCH=riscv
+TARGET_ABI_DIR=riscv
+  ;;
   sh4|sh4eb)
 TARGET_ARCH=sh4
 bflt="yes"
@@ -6730,6 +6738,9 @@ for i in $ARCH $TARGET_BASE_ARCH ; do
   ppc*)
 disas_config "PPC"
   ;;
+  riscv)
+disas_config "RISCV"
+  ;;
   s390*)
 disas_config "S390"
   ;;
diff --git a/cpus.c b/cpus.c
index e8139de..499be10 100644
--- a/cpus.c
+++ b/cpus.c
@@ -1995,6 +1995,9 @@ CpuInfoList *qmp_query_cpus(Error **errp)
 #elif defined(TARGET_SPARC)
 SPARCCPU *sparc_cpu = SPARC_CPU(cpu);
 CPUSPARCState *env = &sparc_cpu->env;
+#elif defined(TARGET_RISCV)
+RISCVCPU *riscv_cpu = RISCV_CPU(cpu);
+CPURISCVState *env = &riscv_cpu->env;
 #elif defined(TARGET_MIPS)
 MIPSCPU *mips_cpu = MIPS_CPU(cpu);
 CPUMIPSState *env = &mips_cpu->env;
@@ -2028,6 +2031,9 @@ CpuInfoList *qmp_query_cpus(Error **errp)
 #elif defined(TARGET_TRICORE)
 info->value->arch = CPU_INFO_ARCH_TRICORE;
 info->value->u.tricore.PC = env->PC;
+#elif defined(TARGET_RISCV)
+info->value->arch = CPU_INFO_ARCH_RISCV;
+info->value->u.riscv.pc = env->pc;
 #else
 info->value->arch = CPU_INFO_ARCH_OTHER;
 #endif
diff --git a/default-configs/riscv32-linux-user.mak 
b/default-configs/riscv32-linux-user.mak
new file mode 100644
index 000..865b362
--- /dev/null
+++ b/default-configs/riscv32-linux-user.mak
@@ -0,0 +1 @@
+# Default configuration for riscv-linux-user
diff --git a/default-configs/riscv32-softmmu.mak 
b/default-configs/riscv32-softmmu.mak
new file mode 100644
index 000..f9e7421
--- /dev/null
+++ b/default-configs/riscv32-softmmu.mak
@@ -0,0 +1,4 @@
+# Default configuration for riscv-softmmu
+
+CONFIG_SERIAL=y
+CONFIG_VIRTIO=y
diff --git a/default-configs/riscv64-linux-user.mak 
b/default-configs/riscv64-linux-user.mak
new file mode 100644
index 000..865b362
--- /dev/null
+++ b/default-configs/riscv64-linux-user.mak
@@ -0,0 +1 @@
+# Default configuration for riscv-linux-user
diff --git a/default-configs/riscv64-softmmu.mak 
b/default-configs/riscv64-softmmu.mak
new file mode 100644
index 000..f9e7421
--- /dev/null
+++ b/default-configs/riscv64-softmmu.mak
@@

[Qemu-devel] [PATCH v3 19/21] SiFive Freedom E300 RISC-V Machine

2018-01-10 Thread Michael Clark
This provides a RISC-V Board compatible with the the SiFive E300 SDK.
The following machine is implemented:

- 'sifive_e300'; CLINT, PLIC, UART, AON, GPIO, QSPI, PWM

Signed-off-by: Michael Clark 
---
 hw/riscv/sifive_e300.c | 232 +
 include/hw/riscv/sifive_e300.h |  79 ++
 2 files changed, 311 insertions(+)
 create mode 100644 hw/riscv/sifive_e300.c
 create mode 100644 include/hw/riscv/sifive_e300.h

diff --git a/hw/riscv/sifive_e300.c b/hw/riscv/sifive_e300.c
new file mode 100644
index 000..bbea55a
--- /dev/null
+++ b/hw/riscv/sifive_e300.c
@@ -0,0 +1,232 @@
+/*
+ * QEMU RISC-V Board Compatible with SiFive E300 SDK
+ *
+ * Copyright (c) 2017 SiFive, Inc.
+ *
+ * Provides a board compatible with the bsp in the SiFive E300 SDK:
+ *
+ * 0) UART
+ * 1) CLINT (Core Level Interruptor)
+ * 2) PLIC (Platform Level Interrupt Controller)
+ * 3) PRCI (Power, Reset, Clock, Interrupt)
+ * 4) Registers emulated as RAM: AON, GPIO, QSPI, PWM
+ * 5) Flash memory emulated as RAM
+ *
+ * The Mask ROM reset vector jumps to the flash payload at 0x2040_.
+ * The OTP ROM and Flash boot code will be emulated in a future version.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to 
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+#include "qemu/error-report.h"
+#include "hw/hw.h"
+#include "hw/boards.h"
+#include "hw/loader.h"
+#include "hw/sysbus.h"
+#include "hw/char/serial.h"
+#include "target/riscv/cpu.h"
+#include "hw/riscv/riscv_hart.h"
+#include "hw/riscv/sifive_plic.h"
+#include "hw/riscv/sifive_clint.h"
+#include "hw/riscv/sifive_prci.h"
+#include "hw/riscv/sifive_uart.h"
+#include "hw/riscv/sifive_e300.h"
+#include "chardev/char.h"
+#include "sysemu/arch_init.h"
+#include "exec/address-spaces.h"
+#include "elf.h"
+
+static const struct MemmapEntry {
+hwaddr base;
+hwaddr size;
+} sifive_e300_memmap[] = {
+[SIFIVE_E300_DEBUG] ={0x0,  0x100 },
+[SIFIVE_E300_MROM] = { 0x1000, 0x2000 },
+[SIFIVE_E300_OTP] =  {0x2, 0x2000 },
+[SIFIVE_E300_CLINT] ={  0x200,0x1 },
+[SIFIVE_E300_PLIC] = {  0xc00,  0x400 },
+[SIFIVE_E300_AON] =  { 0x1000, 0x8000 },
+[SIFIVE_E300_PRCI] = { 0x10008000, 0x8000 },
+[SIFIVE_E300_OTP_CTRL] = { 0x1001, 0x1000 },
+[SIFIVE_E300_GPIO0] ={ 0x10012000, 0x1000 },
+[SIFIVE_E300_UART0] ={ 0x10013000, 0x1000 },
+[SIFIVE_E300_QSPI0] ={ 0x10014000, 0x1000 },
+[SIFIVE_E300_PWM0] = { 0x10015000, 0x1000 },
+[SIFIVE_E300_UART1] ={ 0x10023000, 0x1000 },
+[SIFIVE_E300_QSPI1] ={ 0x10024000, 0x1000 },
+[SIFIVE_E300_PWM1] = { 0x10025000, 0x1000 },
+[SIFIVE_E300_QSPI2] ={ 0x10034000, 0x1000 },
+[SIFIVE_E300_PWM2] = { 0x10035000, 0x1000 },
+[SIFIVE_E300_XIP] =  { 0x2000, 0x2000 },
+[SIFIVE_E300_DTIM] = { 0x8000, 0x4000 }
+};
+
+static uint64_t identity_translate(void *opaque, uint64_t addr)
+{
+return addr;
+}
+
+static uint64_t load_kernel(const char *kernel_filename)
+{
+uint64_t kernel_entry, kernel_high;
+
+if (load_elf(kernel_filename, identity_translate, NULL,
+ &kernel_entry, NULL, &kernel_high,
+ /* little_endian = */ 0, ELF_MACHINE, 1, 0) < 0) {
+error_report("qemu: could not load kernel '%s'", kernel_filename);
+exit(1);
+}
+return kernel_entry;
+}
+
+static void sifive_mmio_emulate(MemoryRegion *parent, const char *name,
+ uintptr_t offset, uintptr_t length)
+{
+MemoryRegion *mock_mmio = g_new(MemoryRegion, 1);
+memory_region_init_ram(mock_mmio, NULL, name, length, &error_fatal);
+memory_region_add_subregion(parent, offset, mock_mmio);
+}
+
+static void riscv_sifive_e300_init(MachineState *machine)
+{
+const struct MemmapEntry *memm

[Qemu-devel] [PATCH v3 15/21] RISC-V Spike Machines

2018-01-10 Thread Michael Clark
RISC-V machines compatble with Spike aka riscv-isa-sim, the RISC-V
Instruction Set Simulator. The following machines are implemented:

- 'spike_v1.9'; HTIF console, config-string, Privileged ISA Version 1.9.1
- 'spike_v1.10'; HTIF console, device-tree, Privileged ISA Version 1.10

Signed-off-by: Michael Clark 
---
 hw/riscv/spike_v1_09.c   | 207 ++
 hw/riscv/spike_v1_10.c   | 281 +++
 include/hw/riscv/spike.h |  51 +
 3 files changed, 539 insertions(+)
 create mode 100644 hw/riscv/spike_v1_09.c
 create mode 100644 hw/riscv/spike_v1_10.c
 create mode 100644 include/hw/riscv/spike.h

diff --git a/hw/riscv/spike_v1_09.c b/hw/riscv/spike_v1_09.c
new file mode 100644
index 000..9b32c6a
--- /dev/null
+++ b/hw/riscv/spike_v1_09.c
@@ -0,0 +1,207 @@
+/*
+ * QEMU RISC-V Spike Board
+ *
+ * Author: Sagar Karandikar, sag...@eecs.berkeley.edu
+ *
+ * This provides a RISC-V Board with the following devices:
+ *
+ * 0) HTIF Test Pass/Fail Reporting (no syscall proxy)
+ * 1) HTIF Console
+ *
+ * These are created by htif_mm_init below.
+ *
+ * This board currently uses a hardcoded devicetree that indicates one hart.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to 
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+#include "qemu/error-report.h"
+#include "hw/hw.h"
+#include "hw/boards.h"
+#include "hw/loader.h"
+#include "hw/sysbus.h"
+#include "target/riscv/cpu.h"
+#include "hw/riscv/riscv_htif.h"
+#include "hw/riscv/riscv_hart.h"
+#include "hw/riscv/sifive_clint.h"
+#include "hw/riscv/spike.h"
+#include "chardev/char.h"
+#include "sysemu/arch_init.h"
+#include "exec/address-spaces.h"
+#include "elf.h"
+
+static const struct MemmapEntry {
+hwaddr base;
+hwaddr size;
+} spike_memmap[] = {
+[SPIKE_MROM] = { 0x1000, 0x2000 },
+[SPIKE_CLINT] ={  0x200,0x1 },
+[SPIKE_DRAM] = { 0x8000,0x0 },
+};
+
+static uint64_t identity_translate(void *opaque, uint64_t addr)
+{
+return addr;
+}
+
+static uint64_t load_kernel(const char *kernel_filename)
+{
+uint64_t kernel_entry, kernel_high;
+
+if (load_elf(kernel_filename, identity_translate, NULL,
+ &kernel_entry, NULL, &kernel_high,
+ /* little_endian = */ 0, ELF_MACHINE, 1, 0) < 0) {
+error_report("qemu: could not load kernel '%s'", kernel_filename);
+exit(1);
+}
+return kernel_entry;
+}
+
+static void riscv_spike_board_init(MachineState *machine)
+{
+const struct MemmapEntry *memmap = spike_memmap;
+
+SpikeState *s = g_new0(SpikeState, 1);
+/* const char *cpu_model = machine->cpu_model; */
+/* const char *kernel_cmdline = machine->kernel_cmdline; */
+/* const char *initrd_filename = machine->initrd_filename; */
+MemoryRegion *system_memory = get_system_memory();
+MemoryRegion *main_mem = g_new(MemoryRegion, 1);
+MemoryRegion *boot_rom = g_new(MemoryRegion, 1);
+
+/* Initialize SOC */
+object_initialize(&s->soc, sizeof(s->soc), TYPE_RISCV_HART_ARRAY);
+object_property_add_child(OBJECT(machine), "soc", OBJECT(&s->soc),
+  &error_abort);
+object_property_set_str(OBJECT(&s->soc), TYPE_RISCV_CPU_IMAFDCSU_PRIV_1_09,
+"cpu-model", &error_abort);
+object_property_set_int(OBJECT(&s->soc), smp_cpus, "num-harts",
+&error_abort);
+object_property_set_bool(OBJECT(&s->soc), true, "realized",
+&error_abort);
+
+/* register system main memory (actual RAM) */
+memory_region_init_ram(main_mem, NULL, "riscv.spike.ram",
+   machine->ram_size, &error_fatal);
+memory_region_add_subregion(system_memory, DRAM_BASE, main_mem);
+
+/* boot rom */
+memory_region_init_ram(boot_rom, NULL, "riscv.spike.bootrom",
+   0x4, &error_fatal

[Qemu-devel] [PATCH v3 11/21] RISC-V HTIF Console

2018-01-10 Thread Michael Clark
HTIF (Host Target Interface) provides console emulation for QEMU. HTIF
allows identical copies of BBL (Berkeley Boot Loader) and linux to run
on both Spike and QEMU. BBL provides HTIF console access via the
SBI (Supervisor Binary Interface) and the linux kernel SBI console.

The HTIF interface reads the ELF kernel and locates the 'tohost' and
'fromhost' symbols which it uses for guest to host console MMIO.

The HTIT chardev implements the pre qom legacy interface consistent
with the 16550a UART in 'hw/char/serial.c'.

Signed-off-by: Michael Clark 
---
 hw/riscv/riscv_elf.c  | 244 +++
 hw/riscv/riscv_htif.c | 373 ++
 include/hw/riscv/riscv_elf.h  |  69 
 include/hw/riscv/riscv_htif.h |  62 +++
 4 files changed, 748 insertions(+)
 create mode 100644 hw/riscv/riscv_elf.c
 create mode 100644 hw/riscv/riscv_htif.c
 create mode 100644 include/hw/riscv/riscv_elf.h
 create mode 100644 include/hw/riscv/riscv_htif.h

diff --git a/hw/riscv/riscv_elf.c b/hw/riscv/riscv_elf.c
new file mode 100644
index 000..355a5a1
--- /dev/null
+++ b/hw/riscv/riscv_elf.c
@@ -0,0 +1,244 @@
+/*
+ * elf.c - A simple package for manipulating symbol tables in elf binaries.
+ *
+ * Taken from
+ * https://www.cs.cmu.edu/afs/cs.cmu.edu/academic/class/15213-f03/www/
+ * ftrace/elf.c
+ *
+ */
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "hw/riscv/riscv_elf.h"
+
+/*
+ * elf_open - Map a binary into the address space and extract the
+ * locations of the static and dynamic symbol tables and their string
+ * tables. Return this information in a Elf object file handle that will
+ * be passed to all of the other elf functions.
+ */
+Elf_obj64 *elf_open64(const char *filename)
+{
+int i, fd;
+struct stat sbuf;
+Elf_obj64 *ep;
+Elf64_Shdr *shdr;
+
+ep = g_new(Elf_obj64, 1);
+
+/* Do some consistency checks on the binary */
+fd = open(filename, O_RDONLY);
+if (fd == -1) {
+fprintf(stderr, "Can't open \"%s\": %s\n", filename, strerror(errno));
+exit(1);
+}
+if (fstat(fd, &sbuf) == -1) {
+fprintf(stderr, "Can't stat \"%s\": %s\n", filename, strerror(errno));
+exit(1);
+}
+if (sbuf.st_size < sizeof(Elf64_Ehdr)) {
+fprintf(stderr, "\"%s\" is not an ELF binary object\n", filename);
+exit(1);
+}
+
+/* It looks OK, so map the Elf binary into our address space */
+ep->mlen = sbuf.st_size;
+ep->maddr = mmap(NULL, ep->mlen, PROT_READ, MAP_SHARED, fd, 0);
+if (ep->maddr == (void *)-1) {
+fprintf(stderr, "Can't mmap \"%s\": %s\n", filename, strerror(errno));
+exit(1);
+}
+close(fd);
+
+/* The Elf binary begins with the Elf header */
+ep->ehdr = ep->maddr;
+
+/* check we have a 64-bit little-endian RISC-V ELF object */
+if (ep->ehdr->e_ident[EI_MAG0] != ELFMAG0 ||
+ep->ehdr->e_ident[EI_MAG1] != ELFMAG1 ||
+ep->ehdr->e_ident[EI_MAG2] != ELFMAG2 ||
+ep->ehdr->e_ident[EI_MAG3] != ELFMAG3 ||
+ep->ehdr->e_ident[EI_CLASS] != ELFCLASS64 ||
+ep->ehdr->e_ident[EI_DATA] != ELFDATA2LSB ||
+ep->ehdr->e_machine != EM_RISCV)
+{
+fprintf(stderr, "\"%s\" is not a 64-bit RISC-V ELF object\n", 
filename);
+exit(1);
+}
+
+/*
+ * Find the static and dynamic symbol tables and their string
+ * tables in the the mapped binary. The sh_link field in symbol
+ * table section headers gives the section index of the string
+ * table for that symbol table.
+ */
+shdr = (Elf64_Shdr *)(ep->maddr + ep->ehdr->e_shoff);
+for (i = 0; i < ep->ehdr->e_shnum; i++) {
+if (shdr[i].sh_type == SHT_SYMTAB) {   /* Static symbol table */
+ep->symtab = (Elf64_Sym *)(ep->maddr + shdr[i].sh_offset);
+ep->symtab_end = (Elf64_Sym *)((char *)ep->symtab +
+ shdr[i].sh_size);
+ep->strtab = (char *)(ep->maddr + shdr[shdr[i].sh_link].sh_offset);
+}
+if (shdr[i].sh_type == SHT_DYNSYM) {   /* Dynamic symbol table */
+ep->dsymtab = (Elf64_Sym *)(ep->maddr + shdr[i].sh_offset);
+ep->dsymtab_end = (Elf64_Sym *)((char *)ep->dsymtab +
+  shdr[i].sh_size);
+ep->dstrtab = (char *)(ep->maddr + 
shdr[shdr[i].sh_link].sh_offset);
+}
+}
+return ep;
+}
+
+Elf_obj32 *elf_open32(const char *filename)
+{
+int i, fd;
+struct stat sbuf;
+Elf_obj32 *ep;
+Elf32_Shdr *shdr;
+
+ep = g_new(Elf_obj32, 1);
+
+/* Do some consistency checks on the binary */
+fd = open(filename, O_RDONLY);
+if (fd == -1) {
+fprintf(stderr, "Can't open \"%s\": %s\n", filename, strerror(errno));
+exit(1);
+}
+if (fstat(fd, &sbuf) == -1) {
+fprintf(stderr, "Can't stat \"%s\": %s\n", filename, strerror(errno));
+ 

[Qemu-devel] [PATCH v3 13/21] SiFive RISC-V CLINT Block

2018-01-10 Thread Michael Clark
The CLINT (Core Local Interruptor) device provides real-time clock, timer
and interprocessor interrupts based on SiFive's CLINT specification.

Signed-off-by: Michael Clark 
---
 hw/riscv/sifive_clint.c | 312 
 include/hw/riscv/sifive_clint.h |  56 
 2 files changed, 368 insertions(+)
 create mode 100644 hw/riscv/sifive_clint.c
 create mode 100644 include/hw/riscv/sifive_clint.h

diff --git a/hw/riscv/sifive_clint.c b/hw/riscv/sifive_clint.c
new file mode 100644
index 000..50d2a09
--- /dev/null
+++ b/hw/riscv/sifive_clint.c
@@ -0,0 +1,312 @@
+/*
+ * SiFive CLINT (Core Local Interruptor)
+ *
+ * Copyright (c) 2016-2017 Sagar Karandikar, sag...@eecs.berkeley.edu
+ * Copyright (c) 2017 SiFive, Inc.
+ *
+ * This provides real-time clock, timer and interprocessor interrupts.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to 
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/error-report.h"
+#include "hw/sysbus.h"
+#include "target/riscv/cpu.h"
+#include "hw/riscv/sifive_clint.h"
+#include "qemu/timer.h"
+
+/* See: riscv-pk/machine/sbi_entry.S and arch/riscv/kernel/time.c */
+#define TIMER_FREQ (10 * 1000 * 1000)
+
+uint64_t cpu_riscv_read_instret(CPURISCVState *env)
+{
+return muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), TIMER_FREQ,
+NANOSECONDS_PER_SECOND);
+}
+
+uint64_t cpu_riscv_read_rtc(void)
+{
+return muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), TIMER_FREQ,
+NANOSECONDS_PER_SECOND);
+}
+
+static void sifive_clint_irq_request(void *opaque, int irq, int level)
+{
+/* These are not the same irq numbers visible to the emulated processor. */
+RISCVCPU *cpu = opaque;
+CPURISCVState *env = &cpu->env;
+CPUState *cs = CPU(cpu);
+
+/* The CLINT currently uses irq 0 */
+
+if (level) {
+cpu_interrupt(cs, CPU_INTERRUPT_HARD);
+} else {
+if (!env->mip && !env->mfromhost) {
+/* no interrupts pending, no host interrupt for HTIF, reset */
+cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
+}
+}
+}
+
+/*
+ * Called when timecmp is written to update the QEMU timer or immediately
+ * trigger timer interrupt if mtimecmp <= current timer value.
+ */
+static void sifive_clint_timer_update(CPURISCVState *env)
+{
+uint64_t next;
+uint64_t diff;
+
+uint64_t rtc_r = cpu_riscv_read_rtc();
+
+if (env->timecmp <= rtc_r) {
+/* if we're setting an MTIMECMP value in the "past",
+   immediately raise the timer interrupt */
+env->mip |= MIP_MTIP;
+qemu_irq_raise(env->irq[3]);
+return;
+}
+
+/* otherwise, set up the future timer interrupt */
+diff = env->timecmp - rtc_r;
+/* back to ns (note args switched in muldiv64) */
+next = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
+muldiv64(diff, NANOSECONDS_PER_SECOND, TIMER_FREQ);
+timer_mod(env->timer, next);
+}
+
+/*
+ * Called by the callback used when the timer set using timer_mod expires.
+ * Should raise the timer interrupt line
+ */
+static void sifive_clint_timer_expire(CPURISCVState *env)
+{
+/* do not call update here */
+env->mip |= MIP_MTIP;
+qemu_irq_raise(env->irq[3]);
+}
+
+static void sifive_clint_write_timecmp(CPURISCVState *env, uint64_t value)
+{
+env->timecmp = value;
+env->mip &= ~MIP_MTIP;
+sifive_clint_timer_update(env);
+}
+
+/*
+ * Callback used when the timer set using timer_mod expires.
+ */
+static void sifive_clint_timer_cb(void *opaque)
+{
+CPURISCVState *env;
+env = opaque;
+sifive_clint_timer_expire(env);
+}
+
+/* CPU wants to read rtc or timecmp register */
+static uint64_t sifive_clint_read(void *opaque, hwaddr addr, unsigned size)
+{
+SiFiveCLINTState *clint = opaque;
+if (addr >= clint->sip_base &&
+addr < clint->sip_base + (clint->num_harts << 2)) {
+size_t hartid = (addr - clint->sip_base) >> 2;
+CPUSta

[Qemu-devel] [PATCH v3 05/21] RISC-V CPU Helpers

2018-01-10 Thread Michael Clark
Privileged control and status register helpers and page fault handling.

Signed-off-by: Michael Clark 
---
 target/riscv/helper.c| 499 ++
 target/riscv/helper.h|  78 ++
 target/riscv/op_helper.c | 682 +++
 3 files changed, 1259 insertions(+)
 create mode 100644 target/riscv/helper.c
 create mode 100644 target/riscv/helper.h
 create mode 100644 target/riscv/op_helper.c

diff --git a/target/riscv/helper.c b/target/riscv/helper.c
new file mode 100644
index 000..ff3f19a
--- /dev/null
+++ b/target/riscv/helper.c
@@ -0,0 +1,499 @@
+/*
+ *  RISC-V emulation helpers for qemu.
+ *
+ *  Author: Sagar Karandikar, sag...@eecs.berkeley.edu
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see .
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+#include "cpu.h"
+#include "exec/exec-all.h"
+
+#define RISCV_DEBUG_INTERRUPT 0
+
+int riscv_cpu_mmu_index(CPURISCVState *env, bool ifetch)
+{
+#ifdef CONFIG_USER_ONLY
+return 0;
+#else
+target_ulong mode = env->priv;
+if (!ifetch) {
+if (get_field(env->mstatus, MSTATUS_MPRV)) {
+mode = get_field(env->mstatus, MSTATUS_MPP);
+}
+}
+if (env->priv_ver >= PRIV_VERSION_1_10_0) {
+if (get_field(env->satp, SATP_MODE) == VM_1_10_MBARE) {
+mode = PRV_M;
+}
+} else {
+if (get_field(env->mstatus, MSTATUS_VM) == VM_1_09_MBARE) {
+mode = PRV_M;
+}
+}
+return mode;
+#endif
+}
+
+#ifndef CONFIG_USER_ONLY
+/*
+ * Return RISC-V IRQ number if an interrupt should be taken, else -1.
+ * Used in cpu-exec.c
+ *
+ * Adapted from Spike's processor_t::take_interrupt()
+ */
+static int riscv_cpu_hw_interrupts_pending(CPURISCVState *env)
+{
+target_ulong pending_interrupts = env->mip & env->mie;
+
+target_ulong mie = get_field(env->mstatus, MSTATUS_MIE);
+target_ulong m_enabled = env->priv < PRV_M || (env->priv == PRV_M && mie);
+target_ulong enabled_interrupts = pending_interrupts &
+  ~env->mideleg & -m_enabled;
+
+target_ulong sie = get_field(env->mstatus, MSTATUS_SIE);
+target_ulong s_enabled = env->priv < PRV_S || (env->priv == PRV_S && sie);
+enabled_interrupts |= pending_interrupts & env->mideleg &
+  -s_enabled;
+
+if (enabled_interrupts) {
+target_ulong counted = ctz64(enabled_interrupts); /* since non-zero */
+if (counted == IRQ_X_HOST) {
+/* we're handing it to the cpu now, so get rid of the qemu irq */
+qemu_irq_lower(HTIF_IRQ);
+} else if (counted == IRQ_M_TIMER) {
+/* we're handing it to the cpu now, so get rid of the qemu irq */
+qemu_irq_lower(MTIP_IRQ);
+} else if (counted == IRQ_S_TIMER || counted == IRQ_H_TIMER) {
+/* don't lower irq here */
+}
+return counted;
+} else {
+return EXCP_NONE; /* indicates no pending interrupt */
+}
+}
+#endif
+
+bool riscv_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
+{
+#if !defined(CONFIG_USER_ONLY)
+if (interrupt_request & CPU_INTERRUPT_HARD) {
+RISCVCPU *cpu = RISCV_CPU(cs);
+CPURISCVState *env = &cpu->env;
+int interruptno = riscv_cpu_hw_interrupts_pending(env);
+if (interruptno + 1) {
+cs->exception_index = RISCV_EXCP_INT_FLAG | interruptno;
+riscv_cpu_do_interrupt(cs);
+return true;
+}
+}
+#endif
+return false;
+}
+
+#if !defined(CONFIG_USER_ONLY)
+
+/* get_physical_address - get the physical address for this virtual address
+ *
+ * Do a page table walk to obtain the physical address corresponding to a
+ * virtual address. Returns 0 if the translation was successful
+ *
+ * Adapted from Spike's mmu_t::translate and mmu_t::walk
+ *
+ */
+static int get_physical_address(CPURISCVState *env, hwaddr *physical,
+int *prot, target_ulong address,
+int access_type, int mmu_idx)
+{
+/* NOTE: the env->pc value visible here will not be
+ * correct, but the value visible to the exception handler
+ * (riscv_cpu_do_interrupt) is correct */
+
+const int mode = mmu_idx;
+
+*prot = 0;
+CPUState *cs = CPU(riscv_env_get_cpu(env));
+
+if (mode 

[Qemu-devel] [PATCH v3 20/21] SiFive Freedom U500 RISC-V Machine

2018-01-10 Thread Michael Clark
This provides a RISC-V Board compatible with the the SiFive U500 SDK.
The following machine is implemented:

- 'sifive_u500'; CLINT, PLIC, UART, device-tree

Signed-off-by: Michael Clark 
---
 hw/riscv/sifive_u500.c | 338 +
 include/hw/riscv/sifive_u500.h |  69 +
 2 files changed, 407 insertions(+)
 create mode 100644 hw/riscv/sifive_u500.c
 create mode 100644 include/hw/riscv/sifive_u500.h

diff --git a/hw/riscv/sifive_u500.c b/hw/riscv/sifive_u500.c
new file mode 100644
index 000..9cc411e
--- /dev/null
+++ b/hw/riscv/sifive_u500.c
@@ -0,0 +1,338 @@
+/*
+ * QEMU RISC-V Board Compatible with SiFive U500 SDK
+ *
+ * Copyright (c) 2016-2017 Sagar Karandikar, sag...@eecs.berkeley.edu
+ * Copyright (c) 2017 SiFive, Inc.
+ *
+ * This provides a RISC-V Board compatible with the the SiFive U500 SDK
+ *
+ * 0) UART
+ * 1) CLINT (Core Level Interruptor)
+ * 2) PLIC (Platform Level Interrupt Controller)
+ *
+ * This board currently uses a hardcoded devicetree that indicates one hart.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to 
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+#include "qemu/error-report.h"
+#include "hw/hw.h"
+#include "hw/boards.h"
+#include "hw/loader.h"
+#include "hw/sysbus.h"
+#include "hw/char/serial.h"
+#include "target/riscv/cpu.h"
+#include "hw/riscv/riscv_hart.h"
+#include "hw/riscv/sifive_plic.h"
+#include "hw/riscv/sifive_clint.h"
+#include "hw/riscv/sifive_uart.h"
+#include "hw/riscv/sifive_prci.h"
+#include "hw/riscv/sifive_u500.h"
+#include "chardev/char.h"
+#include "sysemu/arch_init.h"
+#include "sysemu/device_tree.h"
+#include "exec/address-spaces.h"
+#include "elf.h"
+
+static const struct MemmapEntry {
+hwaddr base;
+hwaddr size;
+} sifive_u500_memmap[] = {
+[SIFIVE_U500_DEBUG] ={0x0,  0x100 },
+[SIFIVE_U500_MROM] = { 0x1000, 0x2000 },
+[SIFIVE_U500_CLINT] ={  0x200,0x1 },
+[SIFIVE_U500_PLIC] = {  0xc00,  0x400 },
+[SIFIVE_U500_UART0] ={ 0x10013000, 0x1000 },
+[SIFIVE_U500_UART1] ={ 0x10023000, 0x1000 },
+[SIFIVE_U500_DRAM] = { 0x8000,0x0 },
+};
+
+static uint64_t identity_translate(void *opaque, uint64_t addr)
+{
+return addr;
+}
+
+static uint64_t load_kernel(const char *kernel_filename)
+{
+uint64_t kernel_entry, kernel_high;
+
+if (load_elf(kernel_filename, identity_translate, NULL,
+ &kernel_entry, NULL, &kernel_high,
+ /* little_endian = */ 0, ELF_MACHINE, 1, 0) < 0) {
+error_report("qemu: could not load kernel '%s'", kernel_filename);
+exit(1);
+}
+return kernel_entry;
+}
+
+static void create_fdt(SiFiveU500State *s, const struct MemmapEntry *memmap,
+uint64_t mem_size, const char *cmdline)
+{
+void *fdt;
+int cpu;
+uint32_t *cells;
+char *nodename;
+uint32_t plic_phandle;
+
+fdt = s->fdt = create_device_tree(&s->fdt_size);
+if (!fdt) {
+error_report("create_device_tree() failed");
+exit(1);
+}
+
+qemu_fdt_setprop_string(fdt, "/", "model", "ucbbar,spike-bare,qemu");
+qemu_fdt_setprop_string(fdt, "/", "compatible", "ucbbar,spike-bare-dev");
+qemu_fdt_setprop_cell(fdt, "/", "#size-cells", 0x2);
+qemu_fdt_setprop_cell(fdt, "/", "#address-cells", 0x2);
+
+qemu_fdt_add_subnode(fdt, "/soc");
+qemu_fdt_setprop(fdt, "/soc", "ranges", NULL, 0);
+qemu_fdt_setprop_string(fdt, "/soc", "compatible", 
"ucbbar,spike-bare-soc");
+qemu_fdt_setprop_cell(fdt, "/soc", "#size-cells", 0x2);
+qemu_fdt_setprop_cell(fdt, "/soc", "#address-cells", 0x2);
+
+nodename = g_strdup_printf("/memory@%lx",
+(long)memmap[SIFIVE_U500_DRAM].base);
+qemu_fdt_add_subnode(fdt, nodename);
+qemu_fdt_setprop_cells(fdt, nodename, "reg",
+memmap[SIFIVE_U500_DRAM].base >> 32, memmap[SIFIVE_U500_DRAM].base,
+mem_siz

[Qemu-devel] [PATCH v3 04/21] RISC-V Disassembler

2018-01-10 Thread Michael Clark
The RISC-V disassembler has no dependencies outside of the 'disas'
directory so it can be applied independently. The majority of the
disassembler is machine-generated from instruction set metadata:

- https://github.com/michaeljclark/riscv-meta

Expected checkpatch errors for consistency and brevity reasons:

ERROR: line over 90 characters
ERROR: trailing statements should be on next line
ERROR: space prohibited between function name and open parenthesis '('
Signed-off-by: Michael Clark 
---
 disas.c |2 +
 disas/Makefile.objs |1 +
 disas/riscv.c   | 3054 +++
 include/disas/bfd.h |2 +
 4 files changed, 3059 insertions(+)
 create mode 100644 disas/riscv.c

diff --git a/disas.c b/disas.c
index d4ad108..5325b7e 100644
--- a/disas.c
+++ b/disas.c
@@ -522,6 +522,8 @@ void disas(FILE *out, void *code, unsigned long size)
 # ifdef _ARCH_PPC64
 s.info.cap_mode = CS_MODE_64;
 # endif
+#elif defined(__riscv__)
+print_insn = print_insn_riscv;
 #elif defined(__aarch64__) && defined(CONFIG_ARM_A64_DIS)
 print_insn = print_insn_arm_a64;
 s.info.cap_arch = CS_ARCH_ARM64;
diff --git a/disas/Makefile.objs b/disas/Makefile.objs
index 194648f..95c64cf 100644
--- a/disas/Makefile.objs
+++ b/disas/Makefile.objs
@@ -17,6 +17,7 @@ common-obj-$(CONFIG_MIPS_DIS) += mips.o
 common-obj-$(CONFIG_NIOS2_DIS) += nios2.o
 common-obj-$(CONFIG_MOXIE_DIS) += moxie.o
 common-obj-$(CONFIG_PPC_DIS) += ppc.o
+common-obj-$(CONFIG_RISCV_DIS) += riscv.o
 common-obj-$(CONFIG_S390_DIS) += s390.o
 common-obj-$(CONFIG_SH4_DIS) += sh4.o
 common-obj-$(CONFIG_SPARC_DIS) += sparc.o
diff --git a/disas/riscv.c b/disas/riscv.c
new file mode 100644
index 000..d0f1d72
--- /dev/null
+++ b/disas/riscv.c
@@ -0,0 +1,3054 @@
+/*
+ * QEMU RISC-V Disassembler
+ *
+ * Copyright (c) 2016-2017 Michael Clark 
+ * Copyright (c) 2017-2018 SiFive, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to 
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "qemu/osdep.h"
+#include "disas/bfd.h"
+
+
+/* types */
+
+typedef uint64_t rv_inst;
+typedef uint16_t rv_opcode;
+
+/* enums */
+
+typedef enum {
+rv32,
+rv64,
+rv128
+} rv_isa;
+
+typedef enum {
+rv_rm_rne = 0,
+rv_rm_rtz = 1,
+rv_rm_rdn = 2,
+rv_rm_rup = 3,
+rv_rm_rmm = 4,
+rv_rm_dyn = 7,
+} rv_rm;
+
+typedef enum {
+rv_fence_i = 8,
+rv_fence_o = 4,
+rv_fence_r = 2,
+rv_fence_w = 1,
+} rv_fence;
+
+typedef enum {
+rv_ireg_zero,
+rv_ireg_ra,
+rv_ireg_sp,
+rv_ireg_gp,
+rv_ireg_tp,
+rv_ireg_t0,
+rv_ireg_t1,
+rv_ireg_t2,
+rv_ireg_s0,
+rv_ireg_s1,
+rv_ireg_a0,
+rv_ireg_a1,
+rv_ireg_a2,
+rv_ireg_a3,
+rv_ireg_a4,
+rv_ireg_a5,
+rv_ireg_a6,
+rv_ireg_a7,
+rv_ireg_s2,
+rv_ireg_s3,
+rv_ireg_s4,
+rv_ireg_s5,
+rv_ireg_s6,
+rv_ireg_s7,
+rv_ireg_s8,
+rv_ireg_s9,
+rv_ireg_s10,
+rv_ireg_s11,
+rv_ireg_t3,
+rv_ireg_t4,
+rv_ireg_t5,
+rv_ireg_t6,
+} rv_ireg;
+
+typedef enum {
+rvc_end,
+rvc_simm_6,
+rvc_imm_6,
+rvc_imm_7,
+rvc_imm_8,
+rvc_imm_9,
+rvc_imm_10,
+rvc_imm_12,
+rvc_imm_18,
+rvc_imm_nz,
+rvc_imm_x2,
+rvc_imm_x4,
+rvc_imm_x8,
+rvc_imm_x16,
+rvc_rd_b3,
+rvc_rs1_b3,
+rvc_rs2_b3,
+rvc_rd_eq_rs1,
+rvc_rd_eq_ra,
+rvc_rd_eq_sp,
+rvc_rd_eq_x0,
+rvc_rs1_eq_sp,
+rvc_rs1_eq_x0,
+rvc_rs2_eq_x0,
+rvc_rd_ne_x0_x2,
+rvc_rd_ne_x0,
+rvc_rs1_ne_x0,
+rvc_rs2_ne_x0,
+rvc_rs2_eq_rs1,
+rvc_rs1_eq_ra,
+rvc_imm_eq_zero,
+rvc_imm_eq_n1,
+rvc_imm_eq_p1,
+rvc_csr_eq_0x001,
+rvc_csr_eq_0x002,
+rvc_csr_eq_0x003,
+rvc_csr_eq_0xc00,
+rvc_csr_eq_0xc01,
+rvc_csr_eq_0xc02,
+rvc_csr_eq_0xc80,
+rvc_csr_eq_0xc81,
+rvc_csr_eq_0xc82,
+} rvc_constraint;
+
+typedef enum {
+rv_codec_illegal,
+rv_codec_none,
+rv_codec_u,
+rv_codec_uj,
+

[Qemu-devel] [PATCH v3 07/21] RISC-V GDB Stub

2018-01-10 Thread Michael Clark
GDB Register read and write routines.

Signed-off-by: Michael Clark 
---
 target/riscv/gdbstub.c | 59 ++
 1 file changed, 59 insertions(+)
 create mode 100644 target/riscv/gdbstub.c

diff --git a/target/riscv/gdbstub.c b/target/riscv/gdbstub.c
new file mode 100644
index 000..12d1d9f
--- /dev/null
+++ b/target/riscv/gdbstub.c
@@ -0,0 +1,59 @@
+/*
+ * RISC-V GDB Server Stub
+ *
+ * Author: Sagar Karandikar, sag...@eecs.berkeley.edu
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see .
+ */
+
+#include "qemu/osdep.h"
+#include "qemu-common.h"
+#include "exec/gdbstub.h"
+#include "cpu.h"
+
+int riscv_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
+{
+/* TODO proper x0 handling */
+RISCVCPU *cpu = RISCV_CPU(cs);
+CPURISCVState *env = &cpu->env;
+
+if (n < 32) {
+return gdb_get_regl(mem_buf, env->gpr[n]);
+} else if (n == 32) {
+return gdb_get_regl(mem_buf, env->pc);
+} else if (n < 65) {
+return gdb_get_reg64(mem_buf, env->fpr[n - 33]);
+}
+return 0;
+}
+
+int riscv_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
+{
+/* TODO proper x0 handling */
+RISCVCPU *cpu = RISCV_CPU(cs);
+CPURISCVState *env = &cpu->env;
+
+if (n < 32) {
+env->gpr[n] = ldtul_p(mem_buf);
+return sizeof(target_ulong);
+} else if (n == 32) {
+env->pc = ldtul_p(mem_buf);
+return sizeof(target_ulong);
+} else if (n < 65) {
+env->fpr[n - 33] = ldq_p(mem_buf); /* always 64-bit */
+return sizeof(uint64_t);
+}
+return 0;
+}
-- 
2.7.0




[Qemu-devel] [PATCH v3 14/21] SiFive RISC-V PLIC Block

2018-01-10 Thread Michael Clark
The PLIC (Platform Level Interrupt Controller) device provides a
parameterizable interrupt controller based on SiFive's PLIC specification.

Signed-off-by: Michael Clark 
---
 hw/riscv/sifive_plic.c | 554 +
 include/hw/riscv/sifive_plic.h |  91 +++
 2 files changed, 645 insertions(+)
 create mode 100644 hw/riscv/sifive_plic.c
 create mode 100644 include/hw/riscv/sifive_plic.h

diff --git a/hw/riscv/sifive_plic.c b/hw/riscv/sifive_plic.c
new file mode 100644
index 000..10942c2
--- /dev/null
+++ b/hw/riscv/sifive_plic.c
@@ -0,0 +1,554 @@
+/*
+ * SiFive PLIC (Platform Level Interrupt Controller)
+ *
+ * Copyright (c) 2017 SiFive, Inc.
+ *
+ * This provides a parameterizable interrupt controller based on SiFive's PLIC.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to 
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/error-report.h"
+#include "hw/sysbus.h"
+#include "target/riscv/cpu.h"
+#include "hw/riscv/sifive_plic.h"
+
+#define RISCV_DEBUG_PLIC 0
+
+static PLICMode char_to_mode(char c)
+{
+switch (c) {
+case 'U': return PLICMode_U;
+case 'S': return PLICMode_S;
+case 'H': return PLICMode_H;
+case 'M': return PLICMode_M;
+default:
+error_report("plic: invalid mode '%c'", c);
+exit(1);
+}
+}
+
+static char mode_to_char(PLICMode m)
+{
+switch (m) {
+case PLICMode_U: return 'U';
+case PLICMode_S: return 'S';
+case PLICMode_H: return 'H';
+case PLICMode_M: return 'M';
+default: return '?';
+}
+}
+
+static void sifive_plic_print_state(SiFivePLICState *plic)
+{
+int i;
+int addrid;
+
+/* pending */
+printf("pending   : ");
+for (i = plic->bitfield_words - 1; i >= 0; i--) {
+printf("%08x", plic->pending[i]);
+}
+printf("\n");
+
+/* pending */
+printf("claimed   : ");
+for (i = plic->bitfield_words - 1; i >= 0; i--) {
+printf("%08x", plic->claimed[i]);
+}
+printf("\n");
+
+for (addrid = 0; addrid < plic->num_addrs; addrid++) {
+printf("hart%d-%c enable: ",
+plic->addr_config[addrid].hartid,
+mode_to_char(plic->addr_config[addrid].mode));
+for (i = plic->bitfield_words - 1; i >= 0; i--) {
+printf("%08x", plic->enable[addrid * plic->bitfield_words + i]);
+}
+printf("\n");
+}
+}
+
+static
+void sifive_plic_set_pending(SiFivePLICState *plic, int irq, bool pending)
+{
+qemu_mutex_lock(&plic->lock);
+uint32_t word = irq >> 5;
+if (pending) {
+plic->pending[word] |= (1 << (irq & 31));
+} else {
+plic->pending[word] &= ~(1 << (irq & 31));
+}
+qemu_mutex_unlock(&plic->lock);
+}
+
+static
+void sifive_plic_set_claimed(SiFivePLICState *plic, int irq, bool claimed)
+{
+qemu_mutex_lock(&plic->lock);
+uint32_t word = irq >> 5;
+if (claimed) {
+plic->claimed[word] |= (1 << (irq & 31));
+} else {
+plic->claimed[word] &= ~(1 << (irq & 31));
+}
+qemu_mutex_unlock(&plic->lock);
+}
+
+static
+int sifive_plic_num_irqs_pending(SiFivePLICState *plic, uint32_t addrid)
+{
+int i, j, count = 0;
+for (i = 0; i < plic->bitfield_words; i++) {
+uint32_t pending_enabled_not_claimed =
+(plic->pending[i] & ~plic->claimed[i]) &
+plic->enable[addrid * plic->bitfield_words + i];
+if (!pending_enabled_not_claimed) {
+continue;
+}
+for (j = 0; j < 32; j++) {
+int irq = (i << 5) + j;
+uint32_t prio = plic->source_priority[irq];
+int enabled = pending_enabled_not_claimed & (1 << j);
+if (enabled && prio > plic->target_priority[addrid]) {
+count++;
+}
+}
+}
+return count;
+}
+
+static void sifive_plic_update(SiFivePLICState *plic)
+{
+int addrid;
+
+/* raise irq on harts where this irq is enabled */
+for (a

[Qemu-devel] [PATCH v3 16/21] RISC-V VirtIO Machine

2018-01-10 Thread Michael Clark
RISC-V machine with device-tree, 16550a UART and VirtIO MMIO.
The following machine is implemented:

- 'virt'; CLINT, PLIC, 16550A UART, VirtIO MMIO, device-tree

Signed-off-by: Michael Clark 
---
 hw/riscv/virt.c | 364 
 include/hw/riscv/virt.h |  73 ++
 2 files changed, 437 insertions(+)
 create mode 100644 hw/riscv/virt.c
 create mode 100644 include/hw/riscv/virt.h

diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
new file mode 100644
index 000..7c6fead
--- /dev/null
+++ b/hw/riscv/virt.c
@@ -0,0 +1,364 @@
+/*
+ * QEMU RISC-V VirtIO Board
+ *
+ * Copyright (c) 2017 SiFive, Inc.
+ *
+ * RISC-V machine with 16550a UART and VirtIO MMIO
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to 
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+#include "qemu/error-report.h"
+#include "hw/hw.h"
+#include "hw/boards.h"
+#include "hw/loader.h"
+#include "hw/sysbus.h"
+#include "hw/char/serial.h"
+#include "target/riscv/cpu.h"
+#include "hw/riscv/riscv_htif.h"
+#include "hw/riscv/riscv_hart.h"
+#include "hw/riscv/sifive_plic.h"
+#include "hw/riscv/sifive_clint.h"
+#include "hw/riscv/virt.h"
+#include "chardev/char.h"
+#include "sysemu/arch_init.h"
+#include "sysemu/device_tree.h"
+#include "exec/address-spaces.h"
+#include "elf.h"
+
+static const struct MemmapEntry {
+hwaddr base;
+hwaddr size;
+} virt_memmap[] = {
+[VIRT_DEBUG] ={0x0,  0x100 },
+[VIRT_MROM] = { 0x1000, 0x2000 },
+[VIRT_CLINT] ={  0x200,0x1 },
+[VIRT_PLIC] = {  0xc00,  0x400 },
+[VIRT_UART0] ={ 0x1000,  0x100 },
+[VIRT_VIRTIO] =   { 0x10001000, 0x1000 },
+[VIRT_DRAM] = { 0x8000,0x0 },
+};
+
+static uint64_t identity_translate(void *opaque, uint64_t addr)
+{
+return addr;
+}
+
+static uint64_t load_kernel(const char *kernel_filename)
+{
+uint64_t kernel_entry, kernel_high;
+
+if (load_elf(kernel_filename, identity_translate, NULL,
+ &kernel_entry, NULL, &kernel_high,
+ /* little_endian = */ 0, ELF_MACHINE, 1, 0) < 0) {
+error_report("qemu: could not load kernel '%s'", kernel_filename);
+exit(1);
+}
+return kernel_entry;
+}
+
+static void create_fdt(RISCVVirtState *s, const struct MemmapEntry *memmap,
+uint64_t mem_size, const char *cmdline)
+{
+void *fdt;
+int cpu;
+uint32_t *cells;
+char *nodename;
+uint32_t plic_phandle, phandle = 1;
+int i;
+
+fdt = s->fdt = create_device_tree(&s->fdt_size);
+if (!fdt) {
+error_report("create_device_tree() failed");
+exit(1);
+}
+
+qemu_fdt_setprop_string(fdt, "/", "model", "riscv-virtio,qemu");
+qemu_fdt_setprop_string(fdt, "/", "compatible", "riscv-virtio");
+qemu_fdt_setprop_cell(fdt, "/", "#size-cells", 0x2);
+qemu_fdt_setprop_cell(fdt, "/", "#address-cells", 0x2);
+
+qemu_fdt_add_subnode(fdt, "/soc");
+qemu_fdt_setprop(fdt, "/soc", "ranges", NULL, 0);
+qemu_fdt_setprop_string(fdt, "/soc", "compatible", "riscv-virtio-soc");
+qemu_fdt_setprop_cell(fdt, "/soc", "#size-cells", 0x2);
+qemu_fdt_setprop_cell(fdt, "/soc", "#address-cells", 0x2);
+
+nodename = g_strdup_printf("/memory@%lx",
+(long)memmap[VIRT_DRAM].base);
+qemu_fdt_add_subnode(fdt, nodename);
+qemu_fdt_setprop_cells(fdt, nodename, "reg",
+memmap[VIRT_DRAM].base >> 32, memmap[VIRT_DRAM].base,
+mem_size >> 32, mem_size);
+qemu_fdt_setprop_string(fdt, nodename, "device_type", "memory");
+g_free(nodename);
+
+qemu_fdt_add_subnode(fdt, "/cpus");
+qemu_fdt_setprop_cell(fdt, "/cpus", "timebase-frequency", 1000);
+qemu_fdt_setprop_cell(fdt, "/cpus", "#size-cells", 0x0);
+qemu_fdt_setprop_cell(fdt, "/cpus", "#address-cells", 0x1);
+
+for (cpu = s->soc.num_harts - 1; cpu >= 0; cpu--) {
+int cpu_phandle = phandle++;
+

[Qemu-devel] [PATCH v3 10/21] RISC-V Linux User Emulation

2018-01-10 Thread Michael Clark
Implementation of linux user emulation for RISC-V.

Signed-off-by: Michael Clark 
---
 linux-user/elfload.c  |  22 +++
 linux-user/main.c | 114 +++
 linux-user/riscv/syscall_nr.h | 275 +++
 linux-user/riscv/target_cpu.h |  18 +++
 linux-user/riscv/target_signal.h  |  23 +++
 linux-user/riscv/target_structs.h |  46 ++
 linux-user/riscv/target_syscall.h |  56 
 linux-user/riscv/termbits.h   | 220 
 linux-user/signal.c   | 203 +-
 linux-user/syscall.c  |   2 +
 linux-user/syscall_defs.h |  13 +-
 target/riscv/cpu_user.h   |  26 
 target/riscv/user_atomic.c| 291 ++
 13 files changed, 1303 insertions(+), 6 deletions(-)
 create mode 100644 linux-user/riscv/syscall_nr.h
 create mode 100644 linux-user/riscv/target_cpu.h
 create mode 100644 linux-user/riscv/target_signal.h
 create mode 100644 linux-user/riscv/target_structs.h
 create mode 100644 linux-user/riscv/target_syscall.h
 create mode 100644 linux-user/riscv/termbits.h
 create mode 100644 target/riscv/cpu_user.h
 create mode 100644 target/riscv/user_atomic.c

diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 20f3d8c..178af56 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -1272,6 +1272,28 @@ static inline void init_thread(struct target_pt_regs 
*regs,
 
 #endif /* TARGET_TILEGX */
 
+#ifdef TARGET_RISCV
+
+#define ELF_START_MMAP 0x8000
+#define ELF_ARCH  EM_RISCV
+
+#ifdef TARGET_RISCV32
+#define ELF_CLASS ELFCLASS32
+#else
+#define ELF_CLASS ELFCLASS64
+#endif
+
+static inline void init_thread(struct target_pt_regs *regs,
+   struct image_info *infop)
+{
+regs->sepc = infop->entry;
+regs->sp = infop->start_stack;
+}
+
+#define ELF_EXEC_PAGESIZE 4096
+
+#endif /* TARGET_RISCV */
+
 #ifdef TARGET_HPPA
 
 #define ELF_START_MMAP  0x8000
diff --git a/linux-user/main.c b/linux-user/main.c
index 99a551b..2b8fcc2 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -3647,6 +3647,115 @@ void cpu_loop(CPUTLGState *env)
 
 #endif
 
+#ifdef TARGET_RISCV
+
+void cpu_loop(CPURISCVState *env)
+{
+CPUState *cs = CPU(riscv_env_get_cpu(env));
+int trapnr, signum, sigcode;
+target_ulong sigaddr;
+target_ulong ret;
+
+for (;;) {
+cpu_exec_start(cs);
+trapnr = cpu_exec(cs);
+cpu_exec_end(cs);
+
+signum = 0;
+sigcode = 0;
+sigaddr = 0;
+
+switch (trapnr) {
+case EXCP_INTERRUPT:
+/* just indicate that signals should be handled asap */
+break;
+case RISCV_EXCP_U_ECALL:
+env->pc += 4;
+if (env->gpr[xA7] == TARGET_NR_arch_specific_syscall + 15) {
+/* riscv_flush_icache_syscall is a no-op in QEMU as
+   self-modifying code is automatically detected */
+ret = 0;
+} else {
+ret = do_syscall(env,
+ env->gpr[xA7],
+ env->gpr[xA0],
+ env->gpr[xA1],
+ env->gpr[xA2],
+ env->gpr[xA3],
+ env->gpr[xA4],
+ env->gpr[xA5],
+ 0, 0);
+}
+if (ret == -TARGET_ERESTARTSYS) {
+env->pc -= 4;
+} else if (ret != -TARGET_QEMU_ESIGRETURN) {
+env->gpr[xA0] = ret;
+}
+if (cs->singlestep_enabled) {
+goto gdbstep;
+}
+break;
+case QEMU_USER_EXCP_ATOMIC:
+start_exclusive();
+switch (riscv_cpu_do_usermode_amo(cs)) {
+case RISCV_AMO_OK:
+env->pc += 4;
+break;
+case RISCV_AMO_BADADDR:
+signum = TARGET_SIGSEGV;
+sigcode = TARGET_SEGV_MAPERR;
+sigaddr = env->badaddr;
+break;
+case RISCV_AMO_BADINSN:
+default:
+signum = TARGET_SIGILL;
+sigcode = TARGET_ILL_ILLOPC;
+}
+end_exclusive();
+if (cs->singlestep_enabled) {
+goto gdbstep;
+}
+break;
+case RISCV_EXCP_ILLEGAL_INST:
+signum = TARGET_SIGILL;
+sigcode = TARGET_ILL_ILLOPC;
+break;
+case RISCV_EXCP_BREAKPOINT:
+signum = TARGET_SIGTRAP;
+sigcode = TARGET_TRAP_BRKPT;
+sigaddr = env->pc;
+break;
+case QEMU_USER_EXCP_FAULT:
+signum = TARGET_SIGSEGV;
+sigcode = TARGET_SEGV_MAPERR;
+break;
+case EXCP_DEBUG:
+gdbstep:
+signum =

[Qemu-devel] [PATCH v3 03/21] RISC-V CPU Core Definition

2018-01-10 Thread Michael Clark
Add CPU state header, CPU definitions and initialization routines

Signed-off-by: Michael Clark 
---
 target/riscv/cpu.c  | 391 +
 target/riscv/cpu.h  | 271 +++
 target/riscv/cpu_bits.h | 417 
 3 files changed, 1079 insertions(+)
 create mode 100644 target/riscv/cpu.c
 create mode 100644 target/riscv/cpu.h
 create mode 100644 target/riscv/cpu_bits.h

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
new file mode 100644
index 000..035dd39
--- /dev/null
+++ b/target/riscv/cpu.c
@@ -0,0 +1,391 @@
+/*
+ * QEMU RISC-V CPU
+ *
+ * Author: Sagar Karandikar, sag...@eecs.berkeley.edu
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see
+ * 
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+#include "cpu.h"
+#include "exec/exec-all.h"
+#include "qapi/error.h"
+#include "migration/vmstate.h"
+
+/* RISC-V CPU definitions */
+
+const char * const riscv_int_regnames[] = {
+  "zero", "ra  ", "sp  ", "gp  ", "tp  ", "t0  ", "t1  ", "t2  ",
+  "s0  ", "s1  ", "a0  ", "a1  ", "a2  ", "a3  ", "a4  ", "a5  ",
+  "a6  ", "a7  ", "s2  ", "s3  ", "s4  ", "s5  ", "s6  ", "s7  ",
+  "s8  ", "s9  ", "s10 ", "s11 ", "t3  ", "t4  ", "t5  ", "t6  "
+};
+
+const char * const riscv_fpr_regnames[] = {
+  "ft0 ", "ft1 ", "ft2 ", "ft3 ", "ft4 ", "ft5 ", "ft6 ",  "ft7 ",
+  "fs0 ", "fs1 ", "fa0 ", "fa1 ", "fa2 ", "fa3 ", "fa4 ",  "fa5 ",
+  "fa6 ", "fa7 ", "fs2 ", "fs3 ", "fs4 ", "fs5 ", "fs6 ",  "fs7 ",
+  "fs8 ", "fs9 ", "fs10", "fs11", "ft8 ", "ft9 ", "ft10",  "ft11"
+};
+
+const char * const riscv_excp_names[] = {
+"misaligned_fetch",
+"fault_fetch",
+"illegal_instruction",
+"breakpoint",
+"misaligned_load",
+"fault_load",
+"misaligned_store",
+"fault_store",
+"user_ecall",
+"supervisor_ecall",
+"hypervisor_ecall",
+"machine_ecall",
+"exec_page_fault",
+"load_page_fault",
+"reserved",
+"store_page_fault"
+};
+
+const char * const riscv_intr_names[] = {
+"u_software",
+"s_software",
+"h_software",
+"m_software",
+"u_timer",
+"s_timer",
+"h_timer",
+"m_timer",
+"u_external",
+"s_external",
+"h_external",
+"m_external",
+"coprocessor",
+"host"
+};
+
+typedef struct RISCVCPUInfo {
+const char *name;
+void (*initfn)(Object *obj);
+} RISCVCPUInfo;
+
+#ifdef CONFIG_USER_ONLY
+static void riscv_any_cpu_init(Object *obj)
+{
+CPURISCVState *env = &RISCV_CPU(obj)->env;
+env->misa = RVXLEN | RVI | RVM | RVA | RVF | RVD | RVC | RVU;
+env->misa_mask = env->misa;
+env->user_ver = USER_VERSION_2_02_0;
+env->priv_ver = PRIV_VERSION_1_10_0;
+}
+#else
+static void riscv_imafdcsu_priv1_9_cpu_init(Object *obj)
+{
+CPURISCVState *env = &RISCV_CPU(obj)->env;
+env->misa = RVXLEN | RVI | RVM | RVA | RVF | RVD | RVC | RVS | RVU;
+env->misa_mask = env->misa;
+env->user_ver = USER_VERSION_2_02_0;
+env->priv_ver = PRIV_VERSION_1_09_1;
+}
+
+static void riscv_imafdcsu_priv1_10_cpu_init(Object *obj)
+{
+CPURISCVState *env = &RISCV_CPU(obj)->env;
+env->misa = RVXLEN | RVI | RVM | RVA | RVF | RVD | RVC | RVS | RVU;
+env->misa_mask = env->misa;
+env->user_ver = USER_VERSION_2_02_0;
+env->priv_ver = PRIV_VERSION_1_10_0;
+}
+
+static void riscv_imacu_priv1_10_cpu_init(Object *obj)
+{
+CPURISCVState *env = &RISCV_CPU(obj)->env;
+env->misa = RVXLEN | RVI | RVM | RVA | RVC | RVU;
+env->misa_mask = env->misa;
+env->user_ver = USER_VERSION_2_02_0;
+env->priv_ver = PRIV_VERSION_1_10_0;
+}
+
+static void riscv_imac_priv1_10_cpu_init(Object *obj)
+{
+CPURISCVState *env = &RISCV_CPU(obj)->env;
+env->misa = RVXLEN | RVI | RVM | RVA | RVC;
+env->misa_mask = env->misa;
+env->user_ver = USER_VERSION_2_02_0;
+env->priv_ver = PRIV_VERSION_1_10_0;
+}
+#endif
+
+static const RISCVCPUInfo riscv_cpus[] = {
+#ifdef CONFIG_USER_ONLY
+{ TYPE_RISCV_CPU_ANY,riscv_any_cpu_init },
+#else
+{ TYPE_RISCV_CPU_IMAFDCSU_PRIV_1_09, riscv_imafdcsu_priv1_9_cpu_init },
+{ TYPE_RISCV_CPU_IMAFDCSU_PRIV_1_10, riscv_imafdcsu_priv1_10_cpu_init },
+{ TYPE_RISCV_CPU_IMACU_PRIV_1_10,riscv_imacu_priv1_10_cpu_init },
+{ TYPE_RISCV_CPU_IMAC_PRIV_1_10, riscv_imac_priv1_10_cpu_init },

[Qemu-devel] [PATCH v3 18/21] SiFive RISC-V PRCI Block

2018-01-10 Thread Michael Clark
Simple model of the PRCI  (Power, Reset, Clock, Interrupt) to emulate
register reads made by the SDK BSP.

Signed-off-by: Michael Clark 
---
 hw/riscv/sifive_prci.c | 107 +
 include/hw/riscv/sifive_prci.h |  43 +
 2 files changed, 150 insertions(+)
 create mode 100644 hw/riscv/sifive_prci.c
 create mode 100644 include/hw/riscv/sifive_prci.h

diff --git a/hw/riscv/sifive_prci.c b/hw/riscv/sifive_prci.c
new file mode 100644
index 000..5c27696
--- /dev/null
+++ b/hw/riscv/sifive_prci.c
@@ -0,0 +1,107 @@
+/*
+ * QEMU SiFive PRCI (Power, Reset, Clock, Interrupt)
+ *
+ * Copyright (c) 2017 SiFive, Inc.
+ *
+ * Simple model of the PRCI to emulate register reads made by the SDK BSP
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to 
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "qemu/osdep.h"
+#include "hw/sysbus.h"
+#include "target/riscv/cpu.h"
+#include "hw/riscv/sifive_prci.h"
+
+/* currently implements enough to mock freedom-e-sdk BSP clock programming */
+
+static uint64_t sifive_prci_read(void *opaque, hwaddr addr, unsigned int size)
+{
+if (addr == 0 /* PRCI_HFROSCCFG */) {
+return 1 << 31; /* ROSC_RDY */
+}
+if (addr == 8 /* PRCI_PLLCFG*/) {
+return 1 << 31; /* PLL_LOCK */
+}
+hw_error("%s: read: addr=0x%x\n", __func__, (int)addr);
+return 0;
+}
+
+static void sifive_prci_write(void *opaque, hwaddr addr,
+   uint64_t val64, unsigned int size)
+{
+/* discard writes */
+}
+
+static const MemoryRegionOps sifive_prci_ops = {
+.read = sifive_prci_read,
+.write = sifive_prci_write,
+.endianness = DEVICE_NATIVE_ENDIAN,
+.valid = {
+.min_access_size = 4,
+.max_access_size = 4
+}
+};
+
+static Property sifive_prci_properties[] = {
+DEFINE_PROP_END_OF_LIST(),
+};
+
+static void sifive_prci_init(Object *obj)
+{
+SiFivePRCIState *s = SIFIVE_PRCI(obj);
+
+memory_region_init_io(&s->mmio, obj, &sifive_prci_ops, s,
+  TYPE_SIFIVE_PRCI, 0x8000);
+sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio);
+}
+
+static void sifive_prci_class_init(ObjectClass *klass, void *data)
+{
+DeviceClass *dc = DEVICE_CLASS(klass);
+
+dc->props = sifive_prci_properties;
+}
+
+static const TypeInfo sifive_prci_info = {
+.name  = TYPE_SIFIVE_PRCI,
+.parent= TYPE_SYS_BUS_DEVICE,
+.instance_size = sizeof(SiFivePRCIState),
+.instance_init = sifive_prci_init,
+.class_init= sifive_prci_class_init,
+};
+
+static void sifive_prci_register_types(void)
+{
+type_register_static(&sifive_prci_info);
+}
+
+type_init(sifive_prci_register_types)
+
+
+/*
+ * Create PRCI device.
+ */
+DeviceState *sifive_prci_create(hwaddr addr)
+{
+DeviceState *dev = qdev_create(NULL, TYPE_SIFIVE_PRCI);
+qdev_init_nofail(dev);
+sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, addr);
+return dev;
+}
diff --git a/include/hw/riscv/sifive_prci.h b/include/hw/riscv/sifive_prci.h
new file mode 100644
index 000..0e032e5
--- /dev/null
+++ b/include/hw/riscv/sifive_prci.h
@@ -0,0 +1,43 @@
+/*
+ * QEMU SiFive PRCI (Power, Reset, Clock, Interrupt) interface
+ *
+ * Copyright (c) 2017 SiFive, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to 
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL

[Qemu-devel] [PATCH v3 17/21] SiFive RISC-V UART Device

2018-01-10 Thread Michael Clark
QEMU model of the UART on the SiFive E300 and U500 series SOCs.
BBL supports the SiFive UART for early console access via the SBI
(Supervisor Binary Interface) and the linux kernel SBI console.

The SiFive UART implements the pre qom legacy interface consistent
with the 16550a UART in 'hw/char/serial.c'.

Signed-off-by: Michael Clark 
---
 hw/riscv/sifive_uart.c | 182 +
 include/hw/riscv/sifive_uart.h |  76 +
 2 files changed, 258 insertions(+)
 create mode 100644 hw/riscv/sifive_uart.c
 create mode 100644 include/hw/riscv/sifive_uart.h

diff --git a/hw/riscv/sifive_uart.c b/hw/riscv/sifive_uart.c
new file mode 100644
index 000..0e73df6
--- /dev/null
+++ b/hw/riscv/sifive_uart.c
@@ -0,0 +1,182 @@
+/*
+ * QEMU model of the UART on the SiFive E300 and U500 series SOCs.
+ *
+ * Copyright (c) 2016 Stefan O'Rear
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to 
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "hw/sysbus.h"
+#include "chardev/char.h"
+#include "chardev/char-fe.h"
+#include "target/riscv/cpu.h"
+#include "hw/riscv/sifive_uart.h"
+
+/*
+ * Not yet implemented:
+ *
+ * Transmit FIFO using "qemu/fifo8.h"
+ * SIFIVE_UART_IE_TXWM interrupts
+ * SIFIVE_UART_IE_RXWM interrupts must honor fifo watermark
+ * Rx FIFO watermark interrupt trigger threshold
+ * Tx FIFO watermark interrupt trigger threshold.
+ */
+
+static void update_irq(SiFiveUARTState *s)
+{
+int cond = 0;
+if ((s->ie & SIFIVE_UART_IE_RXWM) && s->rx_fifo_len) {
+cond = 1;
+}
+if (cond) {
+qemu_irq_raise(s->irq);
+} else {
+qemu_irq_lower(s->irq);
+}
+}
+
+static uint64_t
+uart_read(void *opaque, hwaddr addr, unsigned int size)
+{
+SiFiveUARTState *s = opaque;
+unsigned char r;
+switch (addr) {
+case SIFIVE_UART_RXFIFO:
+if (s->rx_fifo_len) {
+r = s->rx_fifo[0];
+memmove(s->rx_fifo, s->rx_fifo + 1, s->rx_fifo_len - 1);
+s->rx_fifo_len--;
+qemu_chr_fe_accept_input(&s->chr);
+update_irq(s);
+return r;
+}
+return 0x8000;
+
+case SIFIVE_UART_TXFIFO:
+return 0; /* Should check tx fifo */
+case SIFIVE_UART_IE:
+return s->ie;
+case SIFIVE_UART_IP:
+return s->rx_fifo_len ? SIFIVE_UART_IP_RXWM : 0;
+case SIFIVE_UART_TXCTRL:
+return s->txctrl;
+case SIFIVE_UART_RXCTRL:
+return s->rxctrl;
+case SIFIVE_UART_DIV:
+return s->div;
+}
+
+hw_error("%s: bad read: addr=0x%x\n",
+__func__, (int)addr);
+return 0;
+}
+
+static void
+uart_write(void *opaque, hwaddr addr,
+   uint64_t val64, unsigned int size)
+{
+SiFiveUARTState *s = opaque;
+uint32_t value = val64;
+unsigned char ch = value;
+
+switch (addr) {
+case SIFIVE_UART_TXFIFO:
+qemu_chr_fe_write(&s->chr, &ch, 1);
+return;
+case SIFIVE_UART_IE:
+s->ie = val64;
+update_irq(s);
+return;
+case SIFIVE_UART_TXCTRL:
+s->txctrl = val64;
+return;
+case SIFIVE_UART_RXCTRL:
+s->rxctrl = val64;
+return;
+case SIFIVE_UART_DIV:
+s->div = val64;
+return;
+}
+hw_error("%s: bad write: addr=0x%x v=0x%x\n",
+__func__, (int)addr, (int)value);
+}
+
+static const MemoryRegionOps uart_ops = {
+.read = uart_read,
+.write = uart_write,
+.endianness = DEVICE_NATIVE_ENDIAN,
+.valid = {
+.min_access_size = 4,
+.max_access_size = 4
+}
+};
+
+static void uart_rx(void *opaque, const uint8_t *buf, int size)
+{
+SiFiveUARTState *s = opaque;
+
+/* Got a byte.  */
+if (s->rx_fifo_len >= sizeof(s->rx_fifo)) {
+printf("WARNING: UART dropped char.\n");
+return;
+}
+s->rx_fifo[s->rx_fifo_len++] = *buf;
+
+update_irq(s);
+}
+
+static int uart_can_rx(void *opaque)

[Qemu-devel] [PATCH v3 09/21] RISC-V Physical Memory Protection

2018-01-10 Thread Michael Clark
Implements the physical memory protection extension as specified in
Privileged ISA Version 1.10.

PMP (Physical Memory Protection) is as-of-yet unused and needs testing.
The SiFive verification team have PMP test cases that will be run.

Nothing currently depends on PMP support. It would be preferable to keep
the code in-tree for folk that are interested in RISC-V PMP support.

Signed-off-by: Michael Clark 
---
 target/riscv/pmp.c | 386 +
 target/riscv/pmp.h |  70 ++
 2 files changed, 456 insertions(+)
 create mode 100644 target/riscv/pmp.c
 create mode 100644 target/riscv/pmp.h

diff --git a/target/riscv/pmp.c b/target/riscv/pmp.c
new file mode 100644
index 000..f57a420
--- /dev/null
+++ b/target/riscv/pmp.c
@@ -0,0 +1,386 @@
+/*
+ * QEMU RISC-V PMP (Physical Memory Protection)
+ *
+ * Author: Daire McNamara, daire.mcnam...@emdalo.com
+ * Ivan Griffin, ivan.grif...@emdalo.com
+ *
+ * This provides a RISC-V Physical Memory Protection implementation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to 
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+/*
+ * PMP (Physical Memory Protection) is as-of-yet unused and needs testing.
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+#include "qapi/error.h"
+#include "cpu.h"
+#include "qemu-common.h"
+
+#ifndef CONFIG_USER_ONLY
+
+#define RISCV_DEBUG_PMP 0
+#define PMP_DEBUG(fmt, ...)\
+do {   \
+if (RISCV_DEBUG_PMP) { \
+qemu_log_mask(LOG_TRACE, "%s: " fmt, __func__, ##__VA_ARGS__); \
+}  \
+} while (0)
+
+static void pmp_write_cfg(CPURISCVState *env, uint32_t addr_index,
+uint8_t val);
+static uint8_t pmp_read_cfg(CPURISCVState *env, uint32_t addr_index);
+static void pmp_update_rule(CPURISCVState *env, uint32_t pmp_index);
+
+/*
+ * Accessor method to extract address matching type 'a field' from cfg reg
+ */
+static inline uint8_t pmp_get_a_field(uint8_t cfg)
+{
+uint8_t a = cfg >> 3;
+return a & 0x3;
+}
+
+/*
+ * Check whether a PMP is locked or not.
+ */
+static inline int pmp_is_locked(CPURISCVState *env, uint32_t pmp_index)
+{
+
+if (env->pmp_state.pmp[pmp_index].cfg_reg & PMP_LOCK) {
+return 1;
+}
+
+/* Top PMP has no 'next' to check */
+if ((pmp_index + 1u) >= MAX_RISCV_PMPS) {
+return 0;
+}
+
+/* In TOR mode, need to check the lock bit of the next pmp
+ * (if there is a next)
+ */
+const uint8_t a_field =
+pmp_get_a_field(env->pmp_state.pmp[pmp_index + 1].cfg_reg);
+if ((env->pmp_state.pmp[pmp_index + 1u].cfg_reg & PMP_LOCK) &&
+ (PMP_AMATCH_TOR == a_field)) {
+return 1;
+}
+
+return 0;
+}
+
+/*
+ * Count the number of active rules.
+ */
+static inline uint32_t pmp_get_num_rules(CPURISCVState *env)
+{
+ return env->pmp_state.num_rules;
+}
+
+/*
+ * Accessor to get the cfg reg for a specific PMP/HART
+ */
+static inline uint8_t pmp_read_cfg(CPURISCVState *env, uint32_t pmp_index)
+{
+if (pmp_index < MAX_RISCV_PMPS) {
+return env->pmp_state.pmp[pmp_index].cfg_reg;
+}
+
+return 0;
+}
+
+
+/*
+ * Accessor to set the cfg reg for a specific PMP/HART
+ * Bounds checks and relevant lock bit.
+ */
+static void pmp_write_cfg(CPURISCVState *env, uint32_t pmp_index, uint8_t val)
+{
+if (pmp_index < MAX_RISCV_PMPS) {
+if (!pmp_is_locked(env, pmp_index)) {
+env->pmp_state.pmp[pmp_index].cfg_reg = val;
+pmp_update_rule(env, pmp_index);
+} else {
+PMP_DEBUG("ignoring write - locked");
+}
+} else {
+PMP_DEBUG("ignoring write - out of bounds");
+}
+}
+
+static void pmp_decode_napot(target_ulong a, target_ulong *sa, target_ulong 
*ea)
+{
+/*
+   ...aaa0

[Qemu-devel] [PATCH v3 00/21] RISC-V QEMU Port Submission v3

2018-01-10 Thread Michael Clark
QEMU RISC-V Emulation Support (RV64GC, RV32GC)

This patch series has major clean ups to target/riscv. There may be
some feedback that has been missed however the changelog is growing
quite large so we have decided to respin the patch series. No new
features have been added however a number of bugs have been fixed.

The git tree for this v3 patch series (squashed and rebased):

- https://github.com/riscv/riscv-qemu/tree/qemu-upstream-v3

The git tree for the v2 patch series with full review commit history:

- https://github.com/riscv/riscv-qemu/tree/qemu-upstream-v2

The git tree for the v1 patch series with full review commit history:

- https://github.com/riscv/riscv-qemu/tree/qemu-upstream-v1

We're adding Palmer Dabbelt as a maintainer so that we have at least
two full-time RISC-V developers available to work on the port.

*** Known Issues ***

- Disassembler has some checkpatch warnings for the sake of code brevity
- scripts/qemu-binfmt-conf.sh has checkpatch warnings due to line length
- PMP (Physical Memory Protection) is as-of-yet unused and needs testing

*** Changelog ***

v3

- Fix indentation in PMP and HTIF debug macros
- Fix disassembler checkpatch open brace '{' on next line errors
- NOTE: the other checkpatch issues have been reviewed previously

v2

- Remove redundant NULL terminators from disassembler register arrays
- Change disassembler register name arrays to const
- Refine disassembler internal function names
- Update dates in disassembler copyright message
- Remove #ifdef CONFIG_USER_ONLY version of cpu_has_work
- Use ULL suffix on 64-bit constants
- Move riscv_cpu_mmu_index from cpu.h to helper.c
- Move riscv_cpu_hw_interrupts_pending from cpu.h to helper.c
- Remove redundant TARGET_HAS_ICE from cpu.h
- Use qemu_irq instead of void* for irq definition in cpu.h
- Remove duplicate typedef from struct CPURISCVState
- Remove redundant g_strdup from cpu_register
- Remove redundant tlb_flush from riscv_cpu_reset
- Remove redundant mode calculation from get_physical_address
- Remove redundant debug mode printf and dcsr comment
- Remove redundant clearing of MSB for bare physical addresses
- Use g_assert_not_reached for invalid mode in get_physical_address
- Use g_assert_not_reached for unreachable checks in get_physical_address
- Use g_assert_not_reached for unreachable type in raise_mmu_exception
- Return exception instead of aborting for misaligned fetches
- Move exception defines from cpu.h to cpu_bits.h
- Remove redundant breakpoint control definitions from cpu_bits.h
- Implement riscv_cpu_unassigned_access exception handling
- Log and raise exceptions for unimplemented CSRs
- Match Spike HTIF exit behavior - don’t print TEST-PASSED
- Make frm,fflags,fcsr writes trap when mstatus.FS is clear
- Use g_assert_not_reached for unreachable invalid mode
- Make hret,uret,dret generate illegal instructions
- Move riscv_cpu_dump_state and int/fpr regnames to cpu.c
- Lift interrupt flag and mask into constants in cpu_bits.h
- Change trap debugging to use qemu_log_mask LOG_TRACE 
- Change CSR debugging to use qemu_log_mask LOG_TRACE
- Change PMP debugging to use qemu_log_mask LOG_TRACE
- Remove commented code from pmp.c
- Change CpuInfoRISCV qapi schema docs to Since 2.12
- Change RV feature macro to use target_ulong cast
- Remove riscv_feature and instead use misa extension flags
- Make riscv_flush_icache_syscall a no-op
- Undo checkpatch whitespace fixes in unrelated linux-user code
- Remove redudant constants and tidy up cpu_bits.h
- Make helper_fence_i a no-op
- Move include "exec/cpu-all" to end of cpu.h
- Rename set_privilege to riscv_set_mode
- Move redundant forward declaration for cpu_riscv_translate_address
- Remove TCGV_UNUSED from riscv_translate_init
- Add comment to pmp.c stating the code is untested and currently unused
- Use ctz to simplify decoding of PMP NAPOT address ranges
- Change pmp_is_in_range to use than equal for end addresses
- Fix off by one error in pmp_update_rule
- Rearrange PMP_DEBUG so that formatting is compile-time checked
- Rearrange trap debugging so that formatting is compile-time checked
- Rearrange PLIC debugging so that formatting is compile-time checked
- Use qemu_log/qemu_log_mask for HTIF logging and debugging
- Move exception and interrupt names into cpu.c
- Add Palmer Dabbelt as a RISC-V Maintainer
- Rebase against current qemu master branch

v1

- initial version based on forward port from riscv-qemu repository

*** Background ***

"RISC-V is an open, free ISA enabling a new era of processor innovation
through open standard collaboration. Born in academia and research,
RISC-V ISA delivers a new level of free, extensible software and
hardware freedom on architecture, paving the way for the next 50 years
of computing design and innovation."

The QEMU RISC-V port has been developed and maintained out-of-tree for
several years by Sagar Karandikar and Bastian Koppelmann. The RISC-V
Privileged specification has evolved substantially over this period but
has

[Qemu-devel] [PATCH v3 06/21] RISC-V FPU Support

2018-01-10 Thread Michael Clark
Helper routines for FPU instructions and NaN definitions.

Signed-off-by: Michael Clark 
---
 fpu/softfloat-specialize.h |   7 +-
 target/riscv/fpu_helper.c  | 591 +
 2 files changed, 595 insertions(+), 3 deletions(-)
 create mode 100644 target/riscv/fpu_helper.c

diff --git a/fpu/softfloat-specialize.h b/fpu/softfloat-specialize.h
index de2c5d5..49ee578 100644
--- a/fpu/softfloat-specialize.h
+++ b/fpu/softfloat-specialize.h
@@ -114,7 +114,8 @@ float32 float32_default_nan(float_status *status)
 #if defined(TARGET_SPARC) || defined(TARGET_M68K)
 return const_float32(0x7FFF);
 #elif defined(TARGET_PPC) || defined(TARGET_ARM) || defined(TARGET_ALPHA) || \
-  defined(TARGET_XTENSA) || defined(TARGET_S390X) || 
defined(TARGET_TRICORE)
+  defined(TARGET_XTENSA) || defined(TARGET_S390X) || \
+  defined(TARGET_TRICORE) || defined(TARGET_RISCV)
 return const_float32(0x7FC0);
 #elif defined(TARGET_HPPA)
 return const_float32(0x7FA0);
@@ -139,7 +140,7 @@ float64 float64_default_nan(float_status *status)
 #if defined(TARGET_SPARC) || defined(TARGET_M68K)
 return const_float64(LIT64(0x7FFF));
 #elif defined(TARGET_PPC) || defined(TARGET_ARM) || defined(TARGET_ALPHA) || \
-  defined(TARGET_S390X)
+  defined(TARGET_S390X) || defined(TARGET_RISCV)
 return const_float64(LIT64(0x7FF8));
 #elif defined(TARGET_HPPA)
 return const_float64(LIT64(0x7FF4));
@@ -189,7 +190,7 @@ float128 float128_default_nan(float_status *status)
 r.high = LIT64(0x7FFF7FFF);
 } else {
 r.low = LIT64(0x);
-#if defined(TARGET_S390X) || defined(TARGET_PPC)
+#if defined(TARGET_S390X) || defined(TARGET_PPC) || defined(TARGET_RISCV)
 r.high = LIT64(0x7FFF8000);
 #else
 r.high = LIT64(0x8000);
diff --git a/target/riscv/fpu_helper.c b/target/riscv/fpu_helper.c
new file mode 100644
index 000..ada985f
--- /dev/null
+++ b/target/riscv/fpu_helper.c
@@ -0,0 +1,591 @@
+/*
+ * RISC-V FPU Emulation Helpers for QEMU.
+ *
+ * Author: Sagar Karandikar, sag...@eecs.berkeley.edu
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see .
+ */
+
+#include "qemu/osdep.h"
+#include 
+#include "cpu.h"
+#include "qemu/host-utils.h"
+#include "exec/helper-proto.h"
+
+/* convert RISC-V rounding mode to IEEE library numbers */
+unsigned int ieee_rm[] = {
+float_round_nearest_even,
+float_round_to_zero,
+float_round_down,
+float_round_up,
+float_round_ties_away
+};
+
+/* obtain rm value to use in computation
+ * as the last step, convert rm codes to what the softfloat library expects
+ * Adapted from Spike's decode.h:RM
+ */
+#define RM ({ \
+if (rm == 7) {\
+rm = env->frm;   \
+} \
+if (rm > 4) { \
+helper_raise_exception(env, RISCV_EXCP_ILLEGAL_INST); \
+} \
+ieee_rm[rm]; })
+
+#ifndef CONFIG_USER_ONLY
+#define require_fp if (!(env->mstatus & MSTATUS_FS)) { \
+helper_raise_exception(env, RISCV_EXCP_ILLEGAL_INST); \
+}
+#else
+#define require_fp /* nop */
+#endif
+
+/* convert softfloat library flag numbers to RISC-V */
+unsigned int softfloat_flags_to_riscv(unsigned int flags)
+{
+int rv_flags = 0;
+rv_flags |= (flags & float_flag_inexact) ? 1 : 0;
+rv_flags |= (flags & float_flag_underflow) ? 2 : 0;
+rv_flags |= (flags & float_flag_overflow) ? 4 : 0;
+rv_flags |= (flags & float_flag_divbyzero) ? 8 : 0;
+rv_flags |= (flags & float_flag_invalid) ? 16 : 0;
+return rv_flags;
+}
+
+/* adapted from Spike's decode.h:set_fp_exceptions */
+#define set_fp_exceptions() do { \
+env->fflags |= softfloat_flags_to_riscv(get_float_exception_flags(\
+&env->fp_status)); \
+set_float_exception_flags(0, &env->fp_status); \
+} while (0)
+
+uint64_t helper_fmadd_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2,
+uint64_t frs3, uint64_t rm)
+{
+require_fp;
+set_float_rounding_mode(RM, &env->fp_status);
+frs1 = float32_muladd(frs1, frs2, frs3, 0, &env->fp_status);
+

[Qemu-devel] [PATCH v3 02/21] RISC-V ELF Machine Definition

2018-01-10 Thread Michael Clark
Define RISC-V ELF machine EM_RISCV 243

Reviewed-by: Richard Henderson 
Signed-off-by: Michael Clark 
---
 include/elf.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/include/elf.h b/include/elf.h
index e8a515c..8e457fc 100644
--- a/include/elf.h
+++ b/include/elf.h
@@ -112,6 +112,8 @@ typedef int64_t  Elf64_Sxword;
 
 #define EM_UNICORE32110 /* UniCore32 */
 
+#define EM_RISCV243 /* RISC-V */
+
 /*
  * This is an interim value that we will use until the committee comes
  * up with a final number.
-- 
2.7.0




[Qemu-devel] [PATCH v3 12/21] RISC-V HART Array

2018-01-10 Thread Michael Clark
Holds the state of a heterogenous array of RISC-V hardware threads.

Signed-off-by: Michael Clark 
---
 hw/riscv/riscv_hart.c | 95 +++
 include/hw/riscv/riscv_hart.h | 45 
 2 files changed, 140 insertions(+)
 create mode 100644 hw/riscv/riscv_hart.c
 create mode 100644 include/hw/riscv/riscv_hart.h

diff --git a/hw/riscv/riscv_hart.c b/hw/riscv/riscv_hart.c
new file mode 100644
index 000..a7e079e
--- /dev/null
+++ b/hw/riscv/riscv_hart.c
@@ -0,0 +1,95 @@
+/*
+ * QEMU RISCV Hart Array
+ *
+ * Copyright (c) 2017 SiFive, Inc.
+ *
+ * Holds the state of a heterogenous array of RISC-V harts
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to 
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "hw/sysbus.h"
+#include "target/riscv/cpu.h"
+#include "hw/riscv/riscv_hart.h"
+
+static Property riscv_harts_props[] = {
+DEFINE_PROP_UINT32("num-harts", RISCVHartArrayState, num_harts, 1),
+DEFINE_PROP_STRING("cpu-model", RISCVHartArrayState, cpu_model),
+DEFINE_PROP_END_OF_LIST(),
+};
+
+static void riscv_harts_cpu_reset(void *opaque)
+{
+RISCVCPU *cpu = opaque;
+cpu_reset(CPU(cpu));
+}
+
+static void riscv_harts_realize(DeviceState *dev, Error **errp)
+{
+RISCVHartArrayState *s = RISCV_HART_ARRAY(dev);
+Error *err = NULL;
+int n;
+
+s->harts = g_new0(RISCVCPU, s->num_harts);
+
+for (n = 0; n < s->num_harts; n++) {
+
+object_initialize(&s->harts[n], sizeof(RISCVCPU), s->cpu_model);
+s->harts[n].env.mhartid = n;
+object_property_add_child(OBJECT(s), "harts[*]", OBJECT(&s->harts[n]),
+  &error_abort);
+qemu_register_reset(riscv_harts_cpu_reset, &s->harts[n]);
+object_property_set_bool(OBJECT(&s->harts[n]), true,
+ "realized", &err);
+if (err) {
+error_propagate(errp, err);
+return;
+}
+}
+}
+
+static void riscv_harts_class_init(ObjectClass *klass, void *data)
+{
+DeviceClass *dc = DEVICE_CLASS(klass);
+
+dc->props = riscv_harts_props;
+dc->realize = riscv_harts_realize;
+}
+
+static void riscv_harts_init(Object *obj)
+{
+/* RISCVHartArrayState *s = SIFIVE_COREPLEX(obj); */
+}
+
+static const TypeInfo riscv_harts_info = {
+.name  = TYPE_RISCV_HART_ARRAY,
+.parent= TYPE_SYS_BUS_DEVICE,
+.instance_size = sizeof(RISCVHartArrayState),
+.instance_init = riscv_harts_init,
+.class_init= riscv_harts_class_init,
+};
+
+static void riscv_harts_register_types(void)
+{
+type_register_static(&riscv_harts_info);
+}
+
+type_init(riscv_harts_register_types)
diff --git a/include/hw/riscv/riscv_hart.h b/include/hw/riscv/riscv_hart.h
new file mode 100644
index 000..c45e987
--- /dev/null
+++ b/include/hw/riscv/riscv_hart.h
@@ -0,0 +1,45 @@
+/*
+ * QEMU RISC-V Hart Array interface
+ *
+ * Copyright (c) 2017 SiFive, Inc.
+ *
+ * Holds the state of a heterogenous array of RISC-V harts
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to 
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIA

[Qemu-devel] [PATCH v3 01/21] RISC-V Maintainers

2018-01-10 Thread Michael Clark
Add Michael Clark, Palmer Dabbelt, Sagar Karandikar and Bastian
Koppelmann as RISC-V Maintainers.

Signed-off-by: Michael Clark 
---
 MAINTAINERS | 11 +++
 1 file changed, 11 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index bc2d3a4..17af5b4 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -209,6 +209,17 @@ F: hw/ppc/
 F: include/hw/ppc/
 F: disas/ppc.c
 
+RISC-V
+M: Michael Clark 
+M: Palmer Dabbelt 
+M: Sagar Karandikar 
+M: Bastian Koppelmann 
+S: Maintained
+F: target/riscv/
+F: hw/riscv/
+F: include/hw/riscv/
+F: disas/riscv.c
+
 S390
 M: Richard Henderson 
 M: Alexander Graf 
-- 
2.7.0




Re: [Qemu-devel] [PATCH v5 1/4] vhost: remove assertion to prevent crash

2018-01-10 Thread Zhoujian (jay)
Hi Igor,

> -Original Message-
> From: Igor Mammedov [mailto:imamm...@redhat.com]
> Sent: Wednesday, January 10, 2018 9:31 PM
> To: Zhoujian (jay) 
> Cc: qemu-devel@nongnu.org; Huangweidong (C) ;
> m...@redhat.com; wangxin (U) ; qemu-
> sta...@nongnu.org; Gonglei (Arei) ; Liuzhe (Ahriy,
> Euler) 
> Subject: Re: [Qemu-devel] [PATCH v5 1/4] vhost: remove assertion to prevent
> crash
> 
> On Wed, 10 Jan 2018 00:39:35 +0800
> Jay Zhou  wrote:
> 
> > Start QEMU with more DIMM devices than limit but without any vhost
> > backends and then hotplug a vhost user backend, the VM will be
> > crashed.
> > Instead of asserting in vhost_user_set_mem_table(), error number is
> > used to gracefully prevent device to start. This fixes the crash
> > issue.
> 
> I'd rewrite commit message as following:
> --
> QEMU will assert on vhsot-user backed virtio device hotplug if QEMU is using
> more RAM regions than VHOST_MEMORY_MAX_NREGIONS (for example if it  were
> started with a lot of DIMM devices).
> 
> Fix it by returning error instead of asserting and let callers of
> vhost_set_mem_table() handle error condition gracefully.
> --

s/vhsot-user/vhost-user, otherwise much better than mine, will use it
in the next version, thanks!

Jay

> >
> > Cc: qemu-sta...@nongnu.org
> > Signed-off-by: Igor Mammedov 
> > Signed-off-by: Jay Zhou 
> > ---
> >  hw/virtio/vhost-user.c | 5 -
> >  1 file changed, 4 insertions(+), 1 deletion(-)
> >
> > diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c index
> > 093675e..8500562 100644
> > --- a/hw/virtio/vhost-user.c
> > +++ b/hw/virtio/vhost-user.c
> > @@ -317,11 +317,14 @@ static int vhost_user_set_mem_table(struct vhost_dev
> *dev,
> >   &offset);
> >  fd = memory_region_get_fd(mr);
> >  if (fd > 0) {
> > +if (fd_num == VHOST_MEMORY_MAX_NREGIONS) {
> > +error_report("Failed preparing vhost-user memory table
> msg");
> > +return -1;
> > +}
> >  msg.payload.memory.regions[fd_num].userspace_addr = reg-
> >userspace_addr;
> >  msg.payload.memory.regions[fd_num].memory_size  = reg-
> >memory_size;
> >  msg.payload.memory.regions[fd_num].guest_phys_addr = reg-
> >guest_phys_addr;
> >  msg.payload.memory.regions[fd_num].mmap_offset = offset;
> > -assert(fd_num < VHOST_MEMORY_MAX_NREGIONS);
> >  fds[fd_num++] = fd;
> >  }
> >  }




Re: [Qemu-devel] [PATCH v2 00/21] RISC-V QEMU Port Submission v2

2018-01-10 Thread no-reply
Hi,

This series seems to have some coding style problems. See output below for
more information:

Type: series
Message-id: 1515628000-93285-1-git-send-email-...@sifive.com
Subject: [Qemu-devel] [PATCH v2 00/21] RISC-V QEMU Port Submission v2

=== TEST SCRIPT BEGIN ===
#!/bin/bash

BASE=base
n=1
total=$(git log --oneline $BASE.. | wc -l)
failed=0

git config --local diff.renamelimit 0
git config --local diff.renames True

commits="$(git log --format=%H --reverse $BASE..)"
for c in $commits; do
echo "Checking PATCH $n/$total: $(git log -n 1 --format=%s $c)..."
if ! git show $c --format=email | ./scripts/checkpatch.pl --mailback -; then
failed=1
echo
fi
n=$((n+1))
done

exit $failed
=== TEST SCRIPT END ===

Updating 3c8cf5a9c21ff8782164d1def7f44bd888713384
Switched to a new branch 'test'
345ea778fb RISC-V Build Infrastructure
0c18e148fd SiFive Freedom U500 RISC-V Machine
6c968431a3 SiFive Freedom E300 RISC-V Machine
65883d2bdb SiFive RISC-V PRCI Block
0cddb7345d SiFive RISC-V UART Device
a34ff4ecaa RISC-V VirtIO Machine
7a6af3895f RISC-V Spike Machines
ce310d45b2 SiFive RISC-V PLIC Block
3a61a5af2c SiFive RISC-V CLINT Block
d11a2328f8 RISC-V HART Array
bf59500952 RISC-V HTIF Console
19ae592def RISC-V Linux User Emulation
fb8c6b2a22 RISC-V Physical Memory Protection
f887e7dcad RISC-V TCG Code Generation
5429573698 RISC-V GDB Stub
d67868d26c RISC-V FPU Support
36d3fd1ee3 RISC-V CPU Helpers
fb9a27692d RISC-V Disassembler
c502fae409 RISC-V CPU Core Definition
c9ab887ba9 RISC-V ELF Machine Definition
f0b0b8a3fa RISC-V Maintainers

=== OUTPUT BEGIN ===
Checking PATCH 1/21: RISC-V Maintainers...
Checking PATCH 2/21: RISC-V ELF Machine Definition...
Checking PATCH 3/21: RISC-V CPU Core Definition...
Checking PATCH 4/21: RISC-V Disassembler...
WARNING: line over 80 characters
#653: FILE: disas/riscv.c:603:
+static const rvc_constraint rvcc_jalr[] = { rvc_rd_eq_ra, rvc_imm_eq_zero, 
rvc_end };

ERROR: line over 90 characters
#654: FILE: disas/riscv.c:604:
+static const rvc_constraint rvcc_nop[] = { rvc_rd_eq_x0, rvc_rs1_eq_x0, 
rvc_imm_eq_zero, rvc_end };

WARNING: line over 80 characters
#684: FILE: disas/riscv.c:634:
+static const rvc_constraint rvcc_ret[] = { rvc_rd_eq_x0, rvc_rs1_eq_ra, 
rvc_end };

WARNING: line over 80 characters
#685: FILE: disas/riscv.c:635:
+static const rvc_constraint rvcc_jr[] = { rvc_rd_eq_x0, rvc_imm_eq_zero, 
rvc_end };

WARNING: line over 80 characters
#686: FILE: disas/riscv.c:636:
+static const rvc_constraint rvcc_rdcycle[] = { rvc_rs1_eq_x0, 
rvc_csr_eq_0xc00, rvc_end };

WARNING: line over 80 characters
#687: FILE: disas/riscv.c:637:
+static const rvc_constraint rvcc_rdtime[] = { rvc_rs1_eq_x0, rvc_csr_eq_0xc01, 
rvc_end };

ERROR: line over 90 characters
#688: FILE: disas/riscv.c:638:
+static const rvc_constraint rvcc_rdinstret[] = { rvc_rs1_eq_x0, 
rvc_csr_eq_0xc02, rvc_end };

ERROR: line over 90 characters
#689: FILE: disas/riscv.c:639:
+static const rvc_constraint rvcc_rdcycleh[] = { rvc_rs1_eq_x0, 
rvc_csr_eq_0xc80, rvc_end };

WARNING: line over 80 characters
#690: FILE: disas/riscv.c:640:
+static const rvc_constraint rvcc_rdtimeh[] = { rvc_rs1_eq_x0, 
rvc_csr_eq_0xc81, rvc_end };

ERROR: line over 90 characters
#691: FILE: disas/riscv.c:641:
+static const rvc_constraint rvcc_rdinstreth[] = { rvc_rs1_eq_x0, 
rvc_csr_eq_0xc80, rvc_end };

WARNING: line over 80 characters
#692: FILE: disas/riscv.c:642:
+static const rvc_constraint rvcc_frcsr[] = { rvc_rs1_eq_x0, rvc_csr_eq_0x003, 
rvc_end };

WARNING: line over 80 characters
#693: FILE: disas/riscv.c:643:
+static const rvc_constraint rvcc_frrm[] = { rvc_rs1_eq_x0, rvc_csr_eq_0x002, 
rvc_end };

WARNING: line over 80 characters
#694: FILE: disas/riscv.c:644:
+static const rvc_constraint rvcc_frflags[] = { rvc_rs1_eq_x0, 
rvc_csr_eq_0x001, rvc_end };

ERROR: line over 90 characters
#1093: FILE: disas/riscv.c:1043:
+{ "c.addi4spn", rv_codec_ciw_4spn, rv_fmt_rd_rs1_imm, NULL, rv_op_addi, 
rv_op_addi, rv_op_addi },

WARNING: line over 80 characters
#1094: FILE: disas/riscv.c:1044:
+{ "c.fld", rv_codec_cl_ld, rv_fmt_frd_offset_rs1, NULL, rv_op_fld, 
rv_op_fld, 0 },

WARNING: line over 80 characters
#1095: FILE: disas/riscv.c:1045:
+{ "c.lw", rv_codec_cl_lw, rv_fmt_rd_offset_rs1, NULL, rv_op_lw, rv_op_lw, 
rv_op_lw },

WARNING: line over 80 characters
#1097: FILE: disas/riscv.c:1047:
+{ "c.fsd", rv_codec_cs_sd, rv_fmt_frs2_offset_rs1, NULL, rv_op_fsd, 
rv_op_fsd, 0 },

WARNING: line over 80 characters
#1098: FILE: disas/riscv.c:1048:
+{ "c.sw", rv_codec_cs_sw, rv_fmt_rs2_offset_rs1, NULL, rv_op_sw, rv_op_sw, 
rv_op_sw },

WARNING: line over 80 characters
#1100: FILE: disas/riscv.c:1050:
+{ "c.nop", rv_codec_ci_none, rv_fmt_none, NULL, rv_op_addi, rv_op_addi, 
rv_op_addi },

ERROR: line over 90 characters
#1101: FILE: disas/riscv.c:1051:
+{ "c.addi", rv_codec_ci, rv_fmt_rd_rs1_imm, NULL, rv_op_addi, rv_op_addi, 
rv_op_addi },

ERROR: line over 90 characters
#1103: FILE: disas/

Re: [Qemu-devel] [PATCH] 9pfs: drop v9fs_register_transport()

2018-01-10 Thread Stefano Stabellini
On Mon, 8 Jan 2018, Greg Kurz wrote:
> Stefano, can you ack/nack this one ?
> 
> On Wed, 20 Dec 2017 20:42:54 +0100
> Greg Kurz  wrote:
> 
> > No good reasons to do this outside of v9fs_device_realize_common().
> > 
> > Signed-off-by: Greg Kurz 

Reviewed-by: Stefano Stabellini 


> > ---
> >  hw/9pfs/9p.c   |6 +-
> >  hw/9pfs/9p.h   |   10 ++
> >  hw/9pfs/virtio-9p-device.c |8 ++--
> >  hw/9pfs/xen-9p-backend.c   |3 +--
> >  4 files changed, 10 insertions(+), 17 deletions(-)
> > 
> > diff --git a/hw/9pfs/9p.c b/hw/9pfs/9p.c
> > index ccbc75265a52..2f836a59deac 100644
> > --- a/hw/9pfs/9p.c
> > +++ b/hw/9pfs/9p.c
> > @@ -3502,7 +3502,8 @@ void pdu_submit(V9fsPDU *pdu, P9MsgHeader *hdr)
> >  }
> >  
> >  /* Returns 0 on success, 1 on failure. */
> > -int v9fs_device_realize_common(V9fsState *s, Error **errp)
> > +int v9fs_device_realize_common(V9fsState *s, const V9fsTransport *t,
> > +   Error **errp)
> >  {
> >  int i, len;
> >  struct stat stat;
> > @@ -3510,6 +3511,9 @@ int v9fs_device_realize_common(V9fsState *s, Error 
> > **errp)
> >  V9fsPath path;
> >  int rc = 1;
> >  
> > +assert(!s->transport);
> > +s->transport = t;
> > +
> >  /* initialize pdu allocator */
> >  QLIST_INIT(&s->free_list);
> >  QLIST_INIT(&s->active_list);
> > diff --git a/hw/9pfs/9p.h b/hw/9pfs/9p.h
> > index ea7657837784..e2aa64577fe1 100644
> > --- a/hw/9pfs/9p.h
> > +++ b/hw/9pfs/9p.h
> > @@ -346,7 +346,8 @@ void v9fs_path_sprintf(V9fsPath *path, const char *fmt, 
> > ...);
> >  void v9fs_path_copy(V9fsPath *lhs, V9fsPath *rhs);
> >  int v9fs_name_to_path(V9fsState *s, V9fsPath *dirpath,
> >const char *name, V9fsPath *path);
> > -int v9fs_device_realize_common(V9fsState *s, Error **errp);
> > +int v9fs_device_realize_common(V9fsState *s, const V9fsTransport *t,
> > +   Error **errp);
> >  void v9fs_device_unrealize_common(V9fsState *s, Error **errp);
> >  
> >  V9fsPDU *pdu_alloc(V9fsState *s);
> > @@ -366,11 +367,4 @@ struct V9fsTransport {
> >  void(*pdu_complete)(V9fsPDU *pdu, bool discard);
> >  };
> >  
> > -static inline int v9fs_register_transport(V9fsState *s, const 
> > V9fsTransport *t)
> > -{
> > -assert(!s->transport);
> > -s->transport = t;
> > -return 0;
> > -}
> > -
> >  #endif
> > diff --git a/hw/9pfs/virtio-9p-device.c b/hw/9pfs/virtio-9p-device.c
> > index d874f48467ba..806e7573276c 100644
> > --- a/hw/9pfs/virtio-9p-device.c
> > +++ b/hw/9pfs/virtio-9p-device.c
> > @@ -201,17 +201,13 @@ static void virtio_9p_device_realize(DeviceState 
> > *dev, Error **errp)
> >  V9fsVirtioState *v = VIRTIO_9P(dev);
> >  V9fsState *s = &v->state;
> >  
> > -if (v9fs_device_realize_common(s, errp)) {
> > -goto out;
> > +if (v9fs_device_realize_common(s, &virtio_9p_transport, errp)) {
> > +return;
> >  }
> >  
> >  v->config_size = sizeof(struct virtio_9p_config) + 
> > strlen(s->fsconf.tag);
> >  virtio_init(vdev, "virtio-9p", VIRTIO_ID_9P, v->config_size);
> >  v->vq = virtio_add_queue(vdev, MAX_REQ, handle_9p_output);
> > -v9fs_register_transport(s, &virtio_9p_transport);
> > -
> > -out:
> > -return;
> >  }
> >  
> >  static void virtio_9p_device_unrealize(DeviceState *dev, Error **errp)
> > diff --git a/hw/9pfs/xen-9p-backend.c b/hw/9pfs/xen-9p-backend.c
> > index dc1e6c5d..e2ae1ac148eb 100644
> > --- a/hw/9pfs/xen-9p-backend.c
> > +++ b/hw/9pfs/xen-9p-backend.c
> > @@ -448,7 +448,6 @@ static int xen_9pfs_connect(struct XenDevice *xendev)
> >  xen_9pdev->id = s->fsconf.fsdev_id =
> >  g_strdup_printf("xen9p%d", xendev->dev);
> >  xen_9pdev->tag = s->fsconf.tag = xenstore_read_fe_str(xendev, "tag");
> > -v9fs_register_transport(s, &xen_9p_transport);
> >  fsdev = qemu_opts_create(qemu_find_opts("fsdev"),
> >  s->fsconf.tag,
> >  1, NULL);
> > @@ -457,7 +456,7 @@ static int xen_9pfs_connect(struct XenDevice *xendev)
> >  qemu_opt_set(fsdev, "security_model", xen_9pdev->security_model, NULL);
> >  qemu_opts_set_id(fsdev, s->fsconf.fsdev_id);
> >  qemu_fsdev_add(fsdev);
> > -v9fs_device_realize_common(s, NULL);
> > +v9fs_device_realize_common(s, &xen_9p_transport, NULL);
> >  
> >  return 0;
> >  
> > 
> 
> 



Re: [Qemu-devel] [PATCH v3 1/2] 9pfs: allow PDU to complete without sending a reply

2018-01-10 Thread Stefano Stabellini
On Mon, 18 Dec 2017, Greg Kurz wrote:
> The 9p protocol mostly relies on a request/reply dialog between the
> client and the server. A notable exception to this rule is request
> cancellation (ie, flush in 9p wording): the server shouldn't send a
> reply when the request was flushed.
> 
> This patch changes the transport API so that the core 9p code may
> choose to discard a reply instead of pushing it back to the client.
> As a consequence, the push_and_notify naming isn't quite appropriate
> anymore. And by the way, this operation also frees ring descriptors
> allocated by the transport, ie, finalizes the completion of the PDU
> in the transport layer. It is hence renamed to pdu_complete.
> 
> This will be used by a subsequent patch to fix request cancellation.
> 
> Signed-off-by: Greg Kurz 

Reviewed-by: Stefano Stabellini 


> ---
>  hw/9pfs/9p.c   |   10 +-
>  hw/9pfs/9p.h   |2 +-
>  hw/9pfs/virtio-9p-device.c |   11 +++
>  hw/9pfs/xen-9p-backend.c   |   14 --
>  4 files changed, 21 insertions(+), 16 deletions(-)
> 
> diff --git a/hw/9pfs/9p.c b/hw/9pfs/9p.c
> index 1e4ebbe57687..dd8b7c6d69c6 100644
> --- a/hw/9pfs/9p.c
> +++ b/hw/9pfs/9p.c
> @@ -642,7 +642,7 @@ static void coroutine_fn pdu_complete(V9fsPDU *pdu, 
> ssize_t len)
>  
>  ret = pdu_marshal(pdu, len, "s", &str);
>  if (ret < 0) {
> -goto out_notify;
> +goto out_complete;
>  }
>  len += ret;
>  id = P9_RERROR;
> @@ -650,7 +650,7 @@ static void coroutine_fn pdu_complete(V9fsPDU *pdu, 
> ssize_t len)
>  
>  ret = pdu_marshal(pdu, len, "d", err);
>  if (ret < 0) {
> -goto out_notify;
> +goto out_complete;
>  }
>  len += ret;
>  
> @@ -662,15 +662,15 @@ static void coroutine_fn pdu_complete(V9fsPDU *pdu, 
> ssize_t len)
>  
>  /* fill out the header */
>  if (pdu_marshal(pdu, 0, "dbw", (int32_t)len, id, pdu->tag) < 0) {
> -goto out_notify;
> +goto out_complete;
>  }
>  
>  /* keep these in sync */
>  pdu->size = len;
>  pdu->id = id;
>  
> -out_notify:
> -pdu->s->transport->push_and_notify(pdu);
> +out_complete:
> +pdu->s->transport->pdu_complete(pdu, false);
>  
>  /* Now wakeup anybody waiting in flush for this request */
>  if (!qemu_co_queue_next(&pdu->complete)) {
> diff --git a/hw/9pfs/9p.h b/hw/9pfs/9p.h
> index ffe658ab8975..ea7657837784 100644
> --- a/hw/9pfs/9p.h
> +++ b/hw/9pfs/9p.h
> @@ -363,7 +363,7 @@ struct V9fsTransport {
>  unsigned int *pniov, size_t size);
>  void(*init_out_iov_from_pdu)(V9fsPDU *pdu, struct iovec **piov,
>   unsigned int *pniov, size_t size);
> -void(*push_and_notify)(V9fsPDU *pdu);
> +void(*pdu_complete)(V9fsPDU *pdu, bool discard);
>  };
>  
>  static inline int v9fs_register_transport(V9fsState *s, const V9fsTransport 
> *t)
> diff --git a/hw/9pfs/virtio-9p-device.c b/hw/9pfs/virtio-9p-device.c
> index 43f4e53f336f..083df987fd93 100644
> --- a/hw/9pfs/virtio-9p-device.c
> +++ b/hw/9pfs/virtio-9p-device.c
> @@ -20,14 +20,17 @@
>  #include "hw/virtio/virtio-access.h"
>  #include "qemu/iov.h"
>  
> -static void virtio_9p_push_and_notify(V9fsPDU *pdu)
> +static void virtio_pdu_complete(V9fsPDU *pdu, bool discard)
>  {
>  V9fsState *s = pdu->s;
>  V9fsVirtioState *v = container_of(s, V9fsVirtioState, state);
>  VirtQueueElement *elem = v->elems[pdu->idx];
>  
> -/* push onto queue and notify */
> -virtqueue_push(v->vq, elem, pdu->size);
> +if (discard) {
> +virtqueue_detach_element(v->vq, elem, 0);
> +} else {
> +virtqueue_push(v->vq, elem, pdu->size);
> +}
>  g_free(elem);
>  v->elems[pdu->idx] = NULL;
>  
> @@ -189,7 +192,7 @@ static const V9fsTransport virtio_9p_transport = {
>  .pdu_vunmarshal = virtio_pdu_vunmarshal,
>  .init_in_iov_from_pdu = virtio_init_in_iov_from_pdu,
>  .init_out_iov_from_pdu = virtio_init_out_iov_from_pdu,
> -.push_and_notify = virtio_9p_push_and_notify,
> +.pdu_complete = virtio_pdu_complete,
>  };
>  
>  static void virtio_9p_device_realize(DeviceState *dev, Error **errp)
> diff --git a/hw/9pfs/xen-9p-backend.c b/hw/9pfs/xen-9p-backend.c
> index df2a4100bf55..dc1e6c5d 100644
> --- a/hw/9pfs/xen-9p-backend.c
> +++ b/hw/9pfs/xen-9p-backend.c
> @@ -210,7 +210,7 @@ static void xen_9pfs_init_in_iov_from_pdu(V9fsPDU *pdu,
>  *pniov = num;
>  }
>  
> -static void xen_9pfs_push_and_notify(V9fsPDU *pdu)
> +static void xen_9pfs_pdu_complete(V9fsPDU *pdu, bool discard)
>  {
>  RING_IDX prod;
>  Xen9pfsDev *priv = container_of(pdu->s, Xen9pfsDev, state);
> @@ -222,10 +222,12 @@ static void xen_9pfs_push_and_notify(V9fsPDU *pdu)
>  ring->intf->out_cons = ring->out_cons;
>  xen_wmb();
>  
> -prod = ring->intf->in_prod;
> -

[Qemu-devel] [PATCHv2] linux-user: Add getcpu() support

2018-01-10 Thread Samuel Thibault
Signed-off-by: Samuel Thibault 

---
Difference from v1: handle failure of put_user_u32 with goto efault;
---
 linux-user/syscall.c | 16 
 1 file changed, 16 insertions(+)

diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 11c9116c4a..89d78b7b48 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -296,6 +296,8 @@ _syscall3(int, sys_sched_getaffinity, pid_t, pid, unsigned 
int, len,
 #define __NR_sys_sched_setaffinity __NR_sched_setaffinity
 _syscall3(int, sys_sched_setaffinity, pid_t, pid, unsigned int, len,
   unsigned long *, user_mask_ptr);
+#define __NR_sys_getcpu __NR_getcpu
+_syscall3(int, sys_getcpu, unsigned *, cpu, unsigned *, node, void *, tcache);
 _syscall4(int, reboot, int, magic1, int, magic2, unsigned int, cmd,
   void *, arg);
 _syscall2(int, capget, struct __user_cap_header_struct *, header,
@@ -10403,6 +10405,20 @@ abi_long do_syscall(void *cpu_env, int num, abi_long 
arg1,
 ret = get_errno(sys_sched_setaffinity(arg1, mask_size, mask));
 }
 break;
+case TARGET_NR_getcpu:
+{
+unsigned cpu, node;
+ret = get_errno(sys_getcpu(arg1 ? &cpu : NULL,
+   arg2 ? &node : NULL,
+   NULL));
+if (arg1 && put_user_u32(cpu, arg1)) {
+goto efault;
+}
+if (arg2 && put_user_u32(node, arg2)) {
+goto efault;
+}
+}
+break;
 case TARGET_NR_sched_setparam:
 {
 struct sched_param *target_schp;
-- 
2.15.1




Re: [Qemu-devel] [PATCH v2] 9pfs: Correctly handle cancelled requests

2018-01-10 Thread Stefano Stabellini
On Wed, 20 Dec 2017, Greg Kurz wrote:
> On Tue, 12 Dec 2017 15:14:06 -0800 (PST)
> Stefano Stabellini  wrote:
> 
> > On Fri, 8 Dec 2017, Greg Kurz wrote:
> > > Cc'ing Stefano using a more appropriate address :)  
> > 
> > Thanks Greg for the ping, one comment inline below.
> > 
> > 
> > > On Thu, 7 Dec 2017 18:04:24 +0100
> > > Greg Kurz  wrote:
> > >   
> > > > On Mon, 4 Dec 2017 15:36:19 -0500
> > > > Keno Fischer  wrote:
> > > >   
> > > > >  # Background
> > > > > 
> > > > > I was investigating spurious non-deterministic EINTR returns from
> > > > > various 9p file system operations in a Linux guest served from the
> > > > > qemu 9p server.
> > > > > 
> > > > >  ## EINTR, ERESTARTSYS and the linux kernel
> > > > > 
> > > > > When a signal arrives that the Linux kernel needs to deliver to 
> > > > > user-space
> > > > > while a given thread is blocked (in the 9p case waiting for a reply 
> > > > > to its
> > > > > request in 9p_client_rpc -> wait_event_interruptible), it asks 
> > > > > whatever
> > > > > driver is currently running to abort its current operation (in the 9p 
> > > > > case
> > > > > causing the submission of a TFLUSH message) and return to user space.
> > > > > In these situations, the error message reported is generally 
> > > > > ERESTARTSYS.
> > > > > If the userspace processes specified SA_RESTART, this means that the
> > > > > system call will get restarted upon completion of the signal handler
> > > > > delivery (assuming the signal handler doesn't modify the process state
> > > > > in complicated ways not relevant here). If SA_RESTART is not 
> > > > > specified,
> > > > > ERESTARTSYS gets translated to EINTR and user space is expected to 
> > > > > handle
> > > > > the restart itself.
> > > > > 
> > > > >  ## The 9p TFLISH command
> > > >^^^
> > > > I'll fix this before pushing to my tree in case there's no v3.
> > > >   
> > > > > 
> > > > > The 9p TFLUSH commands requests that the server abort an ongoing 
> > > > > operation.
> > > > > The man page [1] specifies:
> > > > > 
> > > > > ```
> > > > > If it recognizes oldtag as the tag of a pending transaction, it 
> > > > > should abort any
> > > > > pending response and discard that tag.
> > > > > [...]
> > > > > When the client sends a Tflush, it must wait to receive the 
> > > > > corresponding Rflush
> > > > > before reusing oldtag for subsequent messages. If a response to the 
> > > > > flushed request
> > > > > is received before the Rflush, the client must honor the response as 
> > > > > if it had not
> > > > > been flushed, since the completed request may signify a state change 
> > > > > in the server
> > > > > ```
> > > > > 
> > > > > In particular, this means that the server must not send a reply with 
> > > > > the orignal
> > > > > tag in response to the cancellation request, because the client is 
> > > > > obligated
> > > > > to interpret such a reply as a coincidental reply to the original 
> > > > > request.
> > > > > 
> > > > >  # The bug
> > > > > 
> > > > > When qemu receives a TFlush request, it sets the `cancelled` flag on 
> > > > > the relevant
> > > > > pdu. This flag is periodically checked, e.g. in 
> > > > > `v9fs_co_name_to_path`, and if
> > > > > set, the operation is aborted and the error is set to EINTR. However, 
> > > > > the server
> > > > > then violates the spec, by returning to the client an Rerror 
> > > > > response, rather
> > > > > than discarding the message entirely. As a result, the client is 
> > > > > required
> > > > > to assume that said Rerror response is a result of the original 
> > > > > request, not
> > > > > a result of the cancellation and thus passes the EINTR error back to 
> > > > > user space.
> > > > > This is not the worst thing it could do, however as discussed above, 
> > > > > the correct
> > > > > error code would have been ERESTARTSYS, such that user space programs 
> > > > > with
> > > > > SA_RESTART set get correctly restarted upon completion of the signal 
> > > > > handler.
> > > > > Instead, such programs get spurious EINTR results that they were not 
> > > > > expecting
> > > > > to handle.
> > > > > 
> > > > > It should be noted that there are plenty of user space programs that 
> > > > > do not
> > > > > set SA_RESTART and do not correctly handle EINTR either. However, 
> > > > > that is then
> > > > > a userspace bug. It should also be noted that this bug has been 
> > > > > mitigated by
> > > > > a recent commit to the Linux kernel [2], which essentially prevents 
> > > > > the kernel
> > > > > from sending Tflush requests unless the process is about to die (in 
> > > > > which case
> > > > > the process likely doesn't care about the response). Nevertheless, 
> > > > > for older
> > > > > kernels and to comply with the spec, I believe this change is 
> > > > > beneficial.
> > > > > 
> > > > >  # Implementation
> > > > > 
> > > > > The fix is fairly simple, just skipping notification of a reply if
> > > > > the pdu was previously canc

Re: [Qemu-devel] [PATCH v1 2/2] intel-iommu: Extend address width to 48 bits

2018-01-10 Thread Prasad Singamsetty


Hi Yi L,

On 12/1/2017 3:29 AM, Liu, Yi L wrote:

On Tue, Nov 14, 2017 at 06:13:50PM -0500, prasad.singamse...@oracle.com wrote:

From: Prasad Singamsetty 

The current implementation of Intel IOMMU code only supports 39 bits
iova address width. This patch provides a new parameter (x-aw-bits)
for intel-iommu to extend its address width to 48 bits but keeping the
default the same (39 bits). The reason for not changing the default
is to avoid potential compatibility problems with live migration of
intel-iommu enabled QEMU guest. The only valid values for 'x-aw-bits'
parameter are 39 and 48.

After enabling larger address width (48), we should be able to map
larger iova addresses in the guest. For example, a QEMU guest that
is configured with large memory ( >=1TB ). To check whether 48 bits
aw is enabled, we can grep in the guest dmesg output with line:
"DMAR: Host address width 48".

Signed-off-by: Prasad Singamsetty 


Prasad,

Have you tested the scenario with physical device assigned to a guest?


Sorry for the long delay in following up on this.

I did some testing with vfio-pci devices assigned to the guest.
This is done on the latest qemu code base (2.11.50).

Here are the test cases/results:

1. Booting VM with one or two vfio-pci (network) devices
   and multiple memory size configs (up to 256G). Assigned pci
   devices (network interfaces) worked fine and no issues
   in using these devices. This test is run for both address
   widths (39 and 48).
2. If the guest VM is configured to use 512G and address
   width is the default 39 bits then guest OS fails to
   boot due to DMA failures. The same is observed without
   applying the patch set. The guest OS ends up booting into
   dracut shell. This problem is not seen if we set the address
   width to 48 bits. So, the patch set addresses a latent bug
   with large memory config.

ISSUE - VM could take long time to boot with vfio-pci devices

Qemu process could take a long time to initialize the VM
when vfio-pci device is configured depending on the
memory size. For small memory sizes (less than 32G) it is
not noticeable (<30s). For larger memory sizes, the delay ranges
from several minutes and longer (2-40min). For more than 512G, qemu
process appears to hang but can be interrupted. This behavior
is observed without patch set applied also. The slowness is due
to VFIO_IOMMU_MAP_DMA ioctl taking long time to map the
system ram assigned to the guest. This is when qemu process
is initializing the vfio device where it maps all the assigned
ram memory regions. Here is the stack trace from gdb:

#0  vfio_dma_map (container=0x582709d0, iova=4294967296,
  size=547608330240, vaddr=0x7f7fd3e0,
  readonly=false)
at /home/psingams/qemu-upstream-v2/hw/vfio/common.c:250
#1  0x5584f471 in vfio_listener_region_add(
  listener=0x582709e0,
  section=0x7fffc7f0)
at /home/psingams/qemu-upstream-v2/hw/vfio/common.c:521
#2  0x557f08fc in listener_add_address_space (
  listener=0x582709e0, as=0x5813b790)
at /home/psingams/qemu-upstream-v2/memory.c:2600
#3  0x557f0bbe in memory_listener_register (
  listener=0x582709e0, as=0x5813b790)
at /home/psingams/qemu-upstream-v2/memory.c:2643
#4  0x558511ef in vfio_connect_container (group=0x58270960,
  as=0x5813b790, errp=0x7fffdae8)
at /home/psingams/qemu-upstream-v2/hw/vfio/common.c:1130

(gdb) print/x size
$2 = 0x7f8000

This is before guest OS gets to boot. The host is running 4.15.0-rc6
kernel with qemu version 2.11.50.

I am not sure if this is a known issue and someone is already
working on fixing the implementation of VFIO_IOMMU_MAP_DMA ioctl.

This issue is not related to this patch set and need to be
investigated separately.

Please let me know if there are other comments on this patch set.

Regards,
--Prasad



Regards,
Yi L

---
  hw/i386/acpi-build.c   |   3 +-
  hw/i386/intel_iommu.c  | 101 -
  hw/i386/intel_iommu_internal.h |   9 ++--
  include/hw/i386/intel_iommu.h  |   1 +
  4 files changed, 65 insertions(+), 49 deletions(-)

diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index 73519ab3ac..537957c89a 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -2460,6 +2460,7 @@ build_dmar_q35(GArray *table_data, BIOSLinker *linker)
  AcpiDmarDeviceScope *scope = NULL;
  /* Root complex IOAPIC use one path[0] only */
  size_t ioapic_scope_size = sizeof(*scope) + sizeof(scope->path[0]);
+IntelIOMMUState *intel_iommu = INTEL_IOMMU_DEVICE(iommu);
  
  assert(iommu);

  if (iommu->intr_supported) {
@@ -2467,7 +2468,7 @@ build_dmar_q35(GArray *table_data, BIOSLinker *linker)
  }
  
  dmar = acpi_data_push(table_data, sizeof(*dmar));

-dmar->host_address_width = VTD_HOST_ADDRESS_WIDTH - 1;
+dmar->host_ad

Re: [Qemu-devel] [Qemu-ppc] [PATCH 1/1] spapr: Check SMT based on KVM_CAP_PPC_SMT_POSSIBLE

2018-01-10 Thread joserz
On Tue, Jan 09, 2018 at 01:48:13PM +0100, Greg Kurz wrote:
> On Fri,  5 Jan 2018 22:47:22 -0200
> Jose Ricardo Ziviani  wrote:
> 
> > Power9 supports 4 HW threads/core but it's possible to emulate
> > doorbells to implement virtual SMT. KVM has the KVM_CAP_PPC_SMT_POSSIBLE
> > which returns a bitmap with all SMT modes supported by the host.
> > 
> > Today, QEMU forces the SMT mode based on PVR compat table, this is
> > silently done in spapr_fixup_cpu_dt. Then, if user passes thread=8 the
> > guest will end up with 4 threads/core without any feedback to the user.
> > It is confusing and will crash QEMU if a cpu is hotplugged in that
> > guest.
> > 
> > This patch makes use of KVM_CAP_PPC_SMT_POSSIBLE to check if the host
> > supports the SMT mode so it allows Power9 guests to have 8 threads/core
> > if desired.
> > 
> > Reported-by: Satheesh Rajendran 
> > Signed-off-by: Jose Ricardo Ziviani 
> > ---
> 
> Hi,
> 
> I agree with the general idea but I have a few questions.

Hello Thank you for your detailed review. :)

I'm copying David too because I've seen other bugs related with (v)smt
topic (specially migration) that it could address.

> 
> The MIN(smp_threads, ppc_compat_max_threads(cpu)) computation is
> performed in spapr_fixup_cpu_dt() at CAS, but it is also performed
> in spapr_populate_cpu_dt() at machine reset or when a CPU is added.
> 
> Shouldn't your patch address the latter as well ?

As far as I investigated, I found out that ppc_compat_max_threads() is
called several times, but it always returns the number of threads from
the argument line. Only in spapr_fixup_cpu_dt(), that happens during
the guest kernel initialization when it's realizing the CPUS, is that
ppc_compat_max_threads() will return that MIN(n_threads, compat->max_threads).

Until them, if(cpu->compat_pvr) is zeroed and QEMU doesn't know the
max_threads yet.

That's the reason that I added the code only in spapr_fixup_cpu_dt()
because this is where the change really happens.

> 
> >  hw/ppc/spapr.c   | 14 +-
> >  hw/ppc/trace-events  |  1 +
> >  target/ppc/kvm.c |  5 +
> >  target/ppc/kvm_ppc.h |  6 ++
> >  4 files changed, 25 insertions(+), 1 deletion(-)
> > 
> > diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
> > index d1acfe8858..ea2503cd2f 100644
> > --- a/hw/ppc/spapr.c
> > +++ b/hw/ppc/spapr.c
> > @@ -345,7 +345,19 @@ static int spapr_fixup_cpu_dt(void *fdt, 
> > sPAPRMachineState *spapr)
> >  PowerPCCPU *cpu = POWERPC_CPU(cs);
> >  DeviceClass *dc = DEVICE_GET_CLASS(cs);
> >  int index = spapr_vcpu_id(cpu);
> > -int compat_smt = MIN(smp_threads, ppc_compat_max_threads(cpu));
> 
> Considering that we have:
> 
> int ppc_compat_max_threads(PowerPCCPU *cpu)
> {
> const CompatInfo *compat = compat_by_pvr(cpu->compat_pvr);
> int n_threads = CPU(cpu)->nr_threads;
> 
> if (cpu->compat_pvr) {
> g_assert(compat);
> n_threads = MIN(n_threads, compat->max_threads);
> }
> 
> return n_threads;
> }
> 
> and
> 
> void qemu_init_vcpu(CPUState *cpu)
> {
> cpu->nr_cores = smp_cores;
> cpu->nr_threads = smp_threads;
> ...
> }
> 
> ppc_compat_max_threads() already returns the smaller value of
> smp_threads and the maximum number of HW threads for the PVR.
> 
> I don't quite understand why we had this compat_smt calculation
> in the first place...

Mostly it only returns "n_threads = CPU(cpu)->nr_threads" because until
the guest kernel initialization cpu->compat_pvr is false so that
MIN() macro is not executed.

So, until late, QEMU thinks its guest will have 8 threads/core. During
the guest kernel init., that fixup code calls ppc_compat_max_threads
that will now have cpu->compat_pvr true and will change the number
of threads to 4. Example:

qemu-system-ppc64 -smp sockets=1,cores=1,threads=8
 +-> qemu_init_vcpu, spapr_populate_cpu_dt: 8 threads/core
 +-> guest kernel is running and asks about CPUs, spapr_fixup_cpu_dt()
 runs, sets threads to 4, set ibm,ppc-interrupt-server#s and done.
 +-> guest now believes it only has 4 threads.

> 
> > +
> > +/* set smt to maximum for this current pvr if the number
> > + * passed is higher than defined by PVR compat mode AND
> > + * if KVM cannot emulate it.*/
> > +int compat_smt = smp_threads;
> > +if ((kvmppc_cap_smt_possible() & smp_threads) != smp_threads &&
> > +smp_threads > ppc_compat_max_threads(cpu)) {
> > +compat_smt = ppc_compat_max_threads(cpu);
> > +
> > +trace_spapr_fixup_cpu_smt(index, smp_threads,
> > +kvmppc_cap_smt_possible(),
> > +ppc_compat_max_threads(cpu));
> > +}
> 
> ... so I'm wondering if the above shouldn't be performed in
> ppc_compat_max_threads() directly ? 

Hmm, now I'm believe that the whole code could rely on that
kvmppc_cap_smt_possible() since it will always return the number of
threads supported by the underlying HW. We could have a check 

Re: [Qemu-devel] [PATCH v2 00/21] RISC-V QEMU Port Submission v2

2018-01-10 Thread Michael Clark
FYI - I intended these emails to go to the RISC-V Patches but unfortunately
had the wrong address on the 'cc.

This time around, the patches are in the qemu-devel archives here:

- http://lists.nongnu.org/archive/html/qemu-devel/2018-01/threads.html

On Thu, Jan 11, 2018 at 12:46 PM, Michael Clark  wrote:

> QEMU RISC-V Emulation Support (RV64GC, RV32GC)
>
> This patch series has major clean ups to target/riscv. There may be
> some feedback that has been missed however the changelog is growing
> quite large so we have decided to respin the patch series. No new
> features have been added however a number of bugs have been fixed.
>
> The git tree for this v2 patch series (squashed and rebased):
>
> - https://github.com/riscv/riscv-qemu/tree/qemu-upstream-v2
>
> The git tree for the v1 patch series with full review commit history:
>
> - https://github.com/riscv/riscv-qemu/tree/qemu-upstream-v1
>
> We're adding Palmer Dabbelt as a maintainer so that we have at least
> two full-time RISC-V developers available to work on the port.
>
> *** Known Issues ***
>
> - Disassembler has some checkpatch warnings for the sake of code brevity
> - scripts/qemu-binfmt-conf.sh has checkpatch warnings due to line length
> - PMP (Physical Memory Protection) is as-of-yet unused and needs testing
>
> *** Changelog ***
>
> v2
>
> - Remove redundant NULL terminators from disassembler register arrays
> - Change disassembler register name arrays to const
> - Refine disassembler internal function names
> - Update dates in disassembler copyright message
> - Remove #ifdef CONFIG_USER_ONLY version of cpu_has_work
> - Use ULL suffix on 64-bit constants
> - Move riscv_cpu_mmu_index from cpu.h to helper.c
> - Move riscv_cpu_hw_interrupts_pending from cpu.h to helper.c
> - Remove redundant TARGET_HAS_ICE from cpu.h
> - Use qemu_irq instead of void* for irq definition in cpu.h
> - Remove duplicate typedef from struct CPURISCVState
> - Remove redundant g_strdup from cpu_register
> - Remove redundant tlb_flush from riscv_cpu_reset
> - Remove redundant mode calculation from get_physical_address
> - Remove redundant debug mode printf and dcsr comment
> - Remove redundant clearing of MSB for bare physical addresses
> - Use g_assert_not_reached for invalid mode in get_physical_address
> - Use g_assert_not_reached for unreachable checks in get_physical_address
> - Use g_assert_not_reached for unreachable type in raise_mmu_exception
> - Return exception instead of aborting for misaligned fetches
> - Move exception defines from cpu.h to cpu_bits.h
> - Remove redundant breakpoint control definitions from cpu_bits.h
> - Implement riscv_cpu_unassigned_access exception handling
> - Log and raise exceptions for unimplemented CSRs
> - Match Spike HTIF exit behavior - don’t print TEST-PASSED
> - Make frm,fflags,fcsr writes trap when mstatus.FS is clear
> - Use g_assert_not_reached for unreachable invalid mode
> - Make hret,uret,dret generate illegal instructions
> - Move riscv_cpu_dump_state and int/fpr regnames to cpu.c
> - Lift interrupt flag and mask into constants in cpu_bits.h
> - Change trap debugging to use qemu_log_mask LOG_TRACE
> - Change CSR debugging to use qemu_log_mask LOG_TRACE
> - Change PMP debugging to use qemu_log_mask LOG_TRACE
> - Remove commented code from pmp.c
> - Change CpuInfoRISCV qapi schema docs to Since 2.12
> - Change RV feature macro to use target_ulong cast
> - Remove riscv_feature and instead use misa extension flags
> - Make riscv_flush_icache_syscall a no-op
> - Undo checkpatch whitespace fixes in unrelated linux-user code
> - Remove redudant constants and tidy up cpu_bits.h
> - Make helper_fence_i a no-op
> - Move include "exec/cpu-all" to end of cpu.h
> - Rename set_privilege to riscv_set_mode
> - Move redundant forward declaration for cpu_riscv_translate_address
> - Remove TCGV_UNUSED from riscv_translate_init
> - Add comment to pmp.c stating the code is untested and currently unused
> - Use ctz to simplify decoding of PMP NAPOT address ranges
> - Change pmp_is_in_range to use than equal for end addresses
> - Fix off by one error in pmp_update_rule
> - Rearrange PMP_DEBUG so that formatting is compile-time checked
> - Rearrange trap debugging so that formatting is compile-time checked
> - Rearrange PLIC debugging so that formatting is compile-time checked
> - Use qemu_log/qemu_log_mask for HTIF logging and debugging
> - Move exception and interrupt names into cpu.c
> - Add Palmer Dabbelt as a RISC-V Maintainer
> - Rebase against current qemu master branch
>
> v1
>
> - initial version based on forward port from riscv-qemu repository
>
> *** Background ***
>
> "RISC-V is an open, free ISA enabling a new era of processor innovation
> through open standard collaboration. Born in academia and research,
> RISC-V ISA delivers a new level of free, extensible software and
> hardware freedom on architecture, paving the way for the next 50 years
> of computing design and innovation."
>
> The QEMU RISC-V port has been developed and

[Qemu-devel] [PATCH v2 04/21] RISC-V Disassembler

2018-01-10 Thread Michael Clark
The RISC-V disassembler has no dependencies outside of the 'disas'
directory so it can be applied independently. The majority of the
disassembler is machine-generated from instruction set metadata:

- https://github.com/michaeljclark/riscv-meta

Expected checkpatch errors for consistency and brevity reasons:

ERROR: line over 90 characters
ERROR: trailing statements should be on next line
ERROR: space prohibited between function name and open parenthesis '('
Signed-off-by: Michael Clark 
---
 disas.c |2 +
 disas/Makefile.objs |1 +
 disas/riscv.c   | 3005 +++
 include/disas/bfd.h |2 +
 4 files changed, 3010 insertions(+)
 create mode 100644 disas/riscv.c

diff --git a/disas.c b/disas.c
index d4ad108..5325b7e 100644
--- a/disas.c
+++ b/disas.c
@@ -522,6 +522,8 @@ void disas(FILE *out, void *code, unsigned long size)
 # ifdef _ARCH_PPC64
 s.info.cap_mode = CS_MODE_64;
 # endif
+#elif defined(__riscv__)
+print_insn = print_insn_riscv;
 #elif defined(__aarch64__) && defined(CONFIG_ARM_A64_DIS)
 print_insn = print_insn_arm_a64;
 s.info.cap_arch = CS_ARCH_ARM64;
diff --git a/disas/Makefile.objs b/disas/Makefile.objs
index 194648f..95c64cf 100644
--- a/disas/Makefile.objs
+++ b/disas/Makefile.objs
@@ -17,6 +17,7 @@ common-obj-$(CONFIG_MIPS_DIS) += mips.o
 common-obj-$(CONFIG_NIOS2_DIS) += nios2.o
 common-obj-$(CONFIG_MOXIE_DIS) += moxie.o
 common-obj-$(CONFIG_PPC_DIS) += ppc.o
+common-obj-$(CONFIG_RISCV_DIS) += riscv.o
 common-obj-$(CONFIG_S390_DIS) += s390.o
 common-obj-$(CONFIG_SH4_DIS) += sh4.o
 common-obj-$(CONFIG_SPARC_DIS) += sparc.o
diff --git a/disas/riscv.c b/disas/riscv.c
new file mode 100644
index 000..9e86476
--- /dev/null
+++ b/disas/riscv.c
@@ -0,0 +1,3005 @@
+/*
+ * QEMU RISC-V Disassembler
+ *
+ * Copyright (c) 2016-2017 Michael Clark 
+ * Copyright (c) 2017-2018 SiFive, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to 
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "qemu/osdep.h"
+#include "disas/bfd.h"
+
+
+/* types */
+
+typedef uint64_t rv_inst;
+typedef uint16_t rv_opcode;
+
+/* enums */
+
+typedef enum {
+rv32,
+rv64,
+rv128
+} rv_isa;
+
+typedef enum {
+rv_rm_rne = 0,
+rv_rm_rtz = 1,
+rv_rm_rdn = 2,
+rv_rm_rup = 3,
+rv_rm_rmm = 4,
+rv_rm_dyn = 7,
+} rv_rm;
+
+typedef enum {
+rv_fence_i = 8,
+rv_fence_o = 4,
+rv_fence_r = 2,
+rv_fence_w = 1,
+} rv_fence;
+
+typedef enum {
+rv_ireg_zero,
+rv_ireg_ra,
+rv_ireg_sp,
+rv_ireg_gp,
+rv_ireg_tp,
+rv_ireg_t0,
+rv_ireg_t1,
+rv_ireg_t2,
+rv_ireg_s0,
+rv_ireg_s1,
+rv_ireg_a0,
+rv_ireg_a1,
+rv_ireg_a2,
+rv_ireg_a3,
+rv_ireg_a4,
+rv_ireg_a5,
+rv_ireg_a6,
+rv_ireg_a7,
+rv_ireg_s2,
+rv_ireg_s3,
+rv_ireg_s4,
+rv_ireg_s5,
+rv_ireg_s6,
+rv_ireg_s7,
+rv_ireg_s8,
+rv_ireg_s9,
+rv_ireg_s10,
+rv_ireg_s11,
+rv_ireg_t3,
+rv_ireg_t4,
+rv_ireg_t5,
+rv_ireg_t6,
+} rv_ireg;
+
+typedef enum {
+rvc_end,
+rvc_simm_6,
+rvc_imm_6,
+rvc_imm_7,
+rvc_imm_8,
+rvc_imm_9,
+rvc_imm_10,
+rvc_imm_12,
+rvc_imm_18,
+rvc_imm_nz,
+rvc_imm_x2,
+rvc_imm_x4,
+rvc_imm_x8,
+rvc_imm_x16,
+rvc_rd_b3,
+rvc_rs1_b3,
+rvc_rs2_b3,
+rvc_rd_eq_rs1,
+rvc_rd_eq_ra,
+rvc_rd_eq_sp,
+rvc_rd_eq_x0,
+rvc_rs1_eq_sp,
+rvc_rs1_eq_x0,
+rvc_rs2_eq_x0,
+rvc_rd_ne_x0_x2,
+rvc_rd_ne_x0,
+rvc_rs1_ne_x0,
+rvc_rs2_ne_x0,
+rvc_rs2_eq_rs1,
+rvc_rs1_eq_ra,
+rvc_imm_eq_zero,
+rvc_imm_eq_n1,
+rvc_imm_eq_p1,
+rvc_csr_eq_0x001,
+rvc_csr_eq_0x002,
+rvc_csr_eq_0x003,
+rvc_csr_eq_0xc00,
+rvc_csr_eq_0xc01,
+rvc_csr_eq_0xc02,
+rvc_csr_eq_0xc80,
+rvc_csr_eq_0xc81,
+rvc_csr_eq_0xc82,
+} rvc_constraint;
+
+typedef enum {
+rv_codec_illegal,
+rv_codec_none,
+rv_codec_u,
+rv_codec_uj,
+

[Qemu-devel] [PATCH v2 19/21] SiFive Freedom E300 RISC-V Machine

2018-01-10 Thread Michael Clark
This provides a RISC-V Board compatible with the the SiFive E300 SDK.
The following machine is implemented:

- 'sifive_e300'; CLINT, PLIC, UART, AON, GPIO, QSPI, PWM

Signed-off-by: Michael Clark 
---
 hw/riscv/sifive_e300.c | 232 +
 include/hw/riscv/sifive_e300.h |  79 ++
 2 files changed, 311 insertions(+)
 create mode 100644 hw/riscv/sifive_e300.c
 create mode 100644 include/hw/riscv/sifive_e300.h

diff --git a/hw/riscv/sifive_e300.c b/hw/riscv/sifive_e300.c
new file mode 100644
index 000..bbea55a
--- /dev/null
+++ b/hw/riscv/sifive_e300.c
@@ -0,0 +1,232 @@
+/*
+ * QEMU RISC-V Board Compatible with SiFive E300 SDK
+ *
+ * Copyright (c) 2017 SiFive, Inc.
+ *
+ * Provides a board compatible with the bsp in the SiFive E300 SDK:
+ *
+ * 0) UART
+ * 1) CLINT (Core Level Interruptor)
+ * 2) PLIC (Platform Level Interrupt Controller)
+ * 3) PRCI (Power, Reset, Clock, Interrupt)
+ * 4) Registers emulated as RAM: AON, GPIO, QSPI, PWM
+ * 5) Flash memory emulated as RAM
+ *
+ * The Mask ROM reset vector jumps to the flash payload at 0x2040_.
+ * The OTP ROM and Flash boot code will be emulated in a future version.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to 
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+#include "qemu/error-report.h"
+#include "hw/hw.h"
+#include "hw/boards.h"
+#include "hw/loader.h"
+#include "hw/sysbus.h"
+#include "hw/char/serial.h"
+#include "target/riscv/cpu.h"
+#include "hw/riscv/riscv_hart.h"
+#include "hw/riscv/sifive_plic.h"
+#include "hw/riscv/sifive_clint.h"
+#include "hw/riscv/sifive_prci.h"
+#include "hw/riscv/sifive_uart.h"
+#include "hw/riscv/sifive_e300.h"
+#include "chardev/char.h"
+#include "sysemu/arch_init.h"
+#include "exec/address-spaces.h"
+#include "elf.h"
+
+static const struct MemmapEntry {
+hwaddr base;
+hwaddr size;
+} sifive_e300_memmap[] = {
+[SIFIVE_E300_DEBUG] ={0x0,  0x100 },
+[SIFIVE_E300_MROM] = { 0x1000, 0x2000 },
+[SIFIVE_E300_OTP] =  {0x2, 0x2000 },
+[SIFIVE_E300_CLINT] ={  0x200,0x1 },
+[SIFIVE_E300_PLIC] = {  0xc00,  0x400 },
+[SIFIVE_E300_AON] =  { 0x1000, 0x8000 },
+[SIFIVE_E300_PRCI] = { 0x10008000, 0x8000 },
+[SIFIVE_E300_OTP_CTRL] = { 0x1001, 0x1000 },
+[SIFIVE_E300_GPIO0] ={ 0x10012000, 0x1000 },
+[SIFIVE_E300_UART0] ={ 0x10013000, 0x1000 },
+[SIFIVE_E300_QSPI0] ={ 0x10014000, 0x1000 },
+[SIFIVE_E300_PWM0] = { 0x10015000, 0x1000 },
+[SIFIVE_E300_UART1] ={ 0x10023000, 0x1000 },
+[SIFIVE_E300_QSPI1] ={ 0x10024000, 0x1000 },
+[SIFIVE_E300_PWM1] = { 0x10025000, 0x1000 },
+[SIFIVE_E300_QSPI2] ={ 0x10034000, 0x1000 },
+[SIFIVE_E300_PWM2] = { 0x10035000, 0x1000 },
+[SIFIVE_E300_XIP] =  { 0x2000, 0x2000 },
+[SIFIVE_E300_DTIM] = { 0x8000, 0x4000 }
+};
+
+static uint64_t identity_translate(void *opaque, uint64_t addr)
+{
+return addr;
+}
+
+static uint64_t load_kernel(const char *kernel_filename)
+{
+uint64_t kernel_entry, kernel_high;
+
+if (load_elf(kernel_filename, identity_translate, NULL,
+ &kernel_entry, NULL, &kernel_high,
+ /* little_endian = */ 0, ELF_MACHINE, 1, 0) < 0) {
+error_report("qemu: could not load kernel '%s'", kernel_filename);
+exit(1);
+}
+return kernel_entry;
+}
+
+static void sifive_mmio_emulate(MemoryRegion *parent, const char *name,
+ uintptr_t offset, uintptr_t length)
+{
+MemoryRegion *mock_mmio = g_new(MemoryRegion, 1);
+memory_region_init_ram(mock_mmio, NULL, name, length, &error_fatal);
+memory_region_add_subregion(parent, offset, mock_mmio);
+}
+
+static void riscv_sifive_e300_init(MachineState *machine)
+{
+const struct MemmapEntry *memm

[Qemu-devel] [PATCH v2 20/21] SiFive Freedom U500 RISC-V Machine

2018-01-10 Thread Michael Clark
This provides a RISC-V Board compatible with the the SiFive U500 SDK.
The following machine is implemented:

- 'sifive_u500'; CLINT, PLIC, UART, device-tree

Signed-off-by: Michael Clark 
---
 hw/riscv/sifive_u500.c | 338 +
 include/hw/riscv/sifive_u500.h |  69 +
 2 files changed, 407 insertions(+)
 create mode 100644 hw/riscv/sifive_u500.c
 create mode 100644 include/hw/riscv/sifive_u500.h

diff --git a/hw/riscv/sifive_u500.c b/hw/riscv/sifive_u500.c
new file mode 100644
index 000..9cc411e
--- /dev/null
+++ b/hw/riscv/sifive_u500.c
@@ -0,0 +1,338 @@
+/*
+ * QEMU RISC-V Board Compatible with SiFive U500 SDK
+ *
+ * Copyright (c) 2016-2017 Sagar Karandikar, sag...@eecs.berkeley.edu
+ * Copyright (c) 2017 SiFive, Inc.
+ *
+ * This provides a RISC-V Board compatible with the the SiFive U500 SDK
+ *
+ * 0) UART
+ * 1) CLINT (Core Level Interruptor)
+ * 2) PLIC (Platform Level Interrupt Controller)
+ *
+ * This board currently uses a hardcoded devicetree that indicates one hart.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to 
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+#include "qemu/error-report.h"
+#include "hw/hw.h"
+#include "hw/boards.h"
+#include "hw/loader.h"
+#include "hw/sysbus.h"
+#include "hw/char/serial.h"
+#include "target/riscv/cpu.h"
+#include "hw/riscv/riscv_hart.h"
+#include "hw/riscv/sifive_plic.h"
+#include "hw/riscv/sifive_clint.h"
+#include "hw/riscv/sifive_uart.h"
+#include "hw/riscv/sifive_prci.h"
+#include "hw/riscv/sifive_u500.h"
+#include "chardev/char.h"
+#include "sysemu/arch_init.h"
+#include "sysemu/device_tree.h"
+#include "exec/address-spaces.h"
+#include "elf.h"
+
+static const struct MemmapEntry {
+hwaddr base;
+hwaddr size;
+} sifive_u500_memmap[] = {
+[SIFIVE_U500_DEBUG] ={0x0,  0x100 },
+[SIFIVE_U500_MROM] = { 0x1000, 0x2000 },
+[SIFIVE_U500_CLINT] ={  0x200,0x1 },
+[SIFIVE_U500_PLIC] = {  0xc00,  0x400 },
+[SIFIVE_U500_UART0] ={ 0x10013000, 0x1000 },
+[SIFIVE_U500_UART1] ={ 0x10023000, 0x1000 },
+[SIFIVE_U500_DRAM] = { 0x8000,0x0 },
+};
+
+static uint64_t identity_translate(void *opaque, uint64_t addr)
+{
+return addr;
+}
+
+static uint64_t load_kernel(const char *kernel_filename)
+{
+uint64_t kernel_entry, kernel_high;
+
+if (load_elf(kernel_filename, identity_translate, NULL,
+ &kernel_entry, NULL, &kernel_high,
+ /* little_endian = */ 0, ELF_MACHINE, 1, 0) < 0) {
+error_report("qemu: could not load kernel '%s'", kernel_filename);
+exit(1);
+}
+return kernel_entry;
+}
+
+static void create_fdt(SiFiveU500State *s, const struct MemmapEntry *memmap,
+uint64_t mem_size, const char *cmdline)
+{
+void *fdt;
+int cpu;
+uint32_t *cells;
+char *nodename;
+uint32_t plic_phandle;
+
+fdt = s->fdt = create_device_tree(&s->fdt_size);
+if (!fdt) {
+error_report("create_device_tree() failed");
+exit(1);
+}
+
+qemu_fdt_setprop_string(fdt, "/", "model", "ucbbar,spike-bare,qemu");
+qemu_fdt_setprop_string(fdt, "/", "compatible", "ucbbar,spike-bare-dev");
+qemu_fdt_setprop_cell(fdt, "/", "#size-cells", 0x2);
+qemu_fdt_setprop_cell(fdt, "/", "#address-cells", 0x2);
+
+qemu_fdt_add_subnode(fdt, "/soc");
+qemu_fdt_setprop(fdt, "/soc", "ranges", NULL, 0);
+qemu_fdt_setprop_string(fdt, "/soc", "compatible", 
"ucbbar,spike-bare-soc");
+qemu_fdt_setprop_cell(fdt, "/soc", "#size-cells", 0x2);
+qemu_fdt_setprop_cell(fdt, "/soc", "#address-cells", 0x2);
+
+nodename = g_strdup_printf("/memory@%lx",
+(long)memmap[SIFIVE_U500_DRAM].base);
+qemu_fdt_add_subnode(fdt, nodename);
+qemu_fdt_setprop_cells(fdt, nodename, "reg",
+memmap[SIFIVE_U500_DRAM].base >> 32, memmap[SIFIVE_U500_DRAM].base,
+mem_siz

[Qemu-devel] [PATCH v2 15/21] RISC-V Spike Machines

2018-01-10 Thread Michael Clark
RISC-V machines compatble with Spike aka riscv-isa-sim, the RISC-V
Instruction Set Simulator. The following machines are implemented:

- 'spike_v1.9'; HTIF console, config-string, Privileged ISA Version 1.9.1
- 'spike_v1.10'; HTIF console, device-tree, Privileged ISA Version 1.10

Signed-off-by: Michael Clark 
---
 hw/riscv/spike_v1_09.c   | 207 ++
 hw/riscv/spike_v1_10.c   | 281 +++
 include/hw/riscv/spike.h |  51 +
 3 files changed, 539 insertions(+)
 create mode 100644 hw/riscv/spike_v1_09.c
 create mode 100644 hw/riscv/spike_v1_10.c
 create mode 100644 include/hw/riscv/spike.h

diff --git a/hw/riscv/spike_v1_09.c b/hw/riscv/spike_v1_09.c
new file mode 100644
index 000..9b32c6a
--- /dev/null
+++ b/hw/riscv/spike_v1_09.c
@@ -0,0 +1,207 @@
+/*
+ * QEMU RISC-V Spike Board
+ *
+ * Author: Sagar Karandikar, sag...@eecs.berkeley.edu
+ *
+ * This provides a RISC-V Board with the following devices:
+ *
+ * 0) HTIF Test Pass/Fail Reporting (no syscall proxy)
+ * 1) HTIF Console
+ *
+ * These are created by htif_mm_init below.
+ *
+ * This board currently uses a hardcoded devicetree that indicates one hart.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to 
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+#include "qemu/error-report.h"
+#include "hw/hw.h"
+#include "hw/boards.h"
+#include "hw/loader.h"
+#include "hw/sysbus.h"
+#include "target/riscv/cpu.h"
+#include "hw/riscv/riscv_htif.h"
+#include "hw/riscv/riscv_hart.h"
+#include "hw/riscv/sifive_clint.h"
+#include "hw/riscv/spike.h"
+#include "chardev/char.h"
+#include "sysemu/arch_init.h"
+#include "exec/address-spaces.h"
+#include "elf.h"
+
+static const struct MemmapEntry {
+hwaddr base;
+hwaddr size;
+} spike_memmap[] = {
+[SPIKE_MROM] = { 0x1000, 0x2000 },
+[SPIKE_CLINT] ={  0x200,0x1 },
+[SPIKE_DRAM] = { 0x8000,0x0 },
+};
+
+static uint64_t identity_translate(void *opaque, uint64_t addr)
+{
+return addr;
+}
+
+static uint64_t load_kernel(const char *kernel_filename)
+{
+uint64_t kernel_entry, kernel_high;
+
+if (load_elf(kernel_filename, identity_translate, NULL,
+ &kernel_entry, NULL, &kernel_high,
+ /* little_endian = */ 0, ELF_MACHINE, 1, 0) < 0) {
+error_report("qemu: could not load kernel '%s'", kernel_filename);
+exit(1);
+}
+return kernel_entry;
+}
+
+static void riscv_spike_board_init(MachineState *machine)
+{
+const struct MemmapEntry *memmap = spike_memmap;
+
+SpikeState *s = g_new0(SpikeState, 1);
+/* const char *cpu_model = machine->cpu_model; */
+/* const char *kernel_cmdline = machine->kernel_cmdline; */
+/* const char *initrd_filename = machine->initrd_filename; */
+MemoryRegion *system_memory = get_system_memory();
+MemoryRegion *main_mem = g_new(MemoryRegion, 1);
+MemoryRegion *boot_rom = g_new(MemoryRegion, 1);
+
+/* Initialize SOC */
+object_initialize(&s->soc, sizeof(s->soc), TYPE_RISCV_HART_ARRAY);
+object_property_add_child(OBJECT(machine), "soc", OBJECT(&s->soc),
+  &error_abort);
+object_property_set_str(OBJECT(&s->soc), TYPE_RISCV_CPU_IMAFDCSU_PRIV_1_09,
+"cpu-model", &error_abort);
+object_property_set_int(OBJECT(&s->soc), smp_cpus, "num-harts",
+&error_abort);
+object_property_set_bool(OBJECT(&s->soc), true, "realized",
+&error_abort);
+
+/* register system main memory (actual RAM) */
+memory_region_init_ram(main_mem, NULL, "riscv.spike.ram",
+   machine->ram_size, &error_fatal);
+memory_region_add_subregion(system_memory, DRAM_BASE, main_mem);
+
+/* boot rom */
+memory_region_init_ram(boot_rom, NULL, "riscv.spike.bootrom",
+   0x4, &error_fatal

[Qemu-devel] [PATCH v2 08/21] RISC-V TCG Code Generation

2018-01-10 Thread Michael Clark
TCG code generation for the RV32IMAFDC and RV64IMAFDC. The QEMU
RISC-V code generator has complete coverage for the Base ISA v2.2,
Privileged ISA v1.9.1 and Privileged ISA v1.10:

- RISC-V Instruction Set Manual Volume I: User-Level ISA Version 2.2
- RISC-V Instruction Set Manual Volume II: Privileged ISA Version 1.9.1
- RISC-V Instruction Set Manual Volume II: Privileged ISA Version 1.10

Signed-off-by: Michael Clark 
---
 target/riscv/instmap.h   |  377 +
 target/riscv/translate.c | 1982 ++
 2 files changed, 2359 insertions(+)
 create mode 100644 target/riscv/instmap.h
 create mode 100644 target/riscv/translate.c

diff --git a/target/riscv/instmap.h b/target/riscv/instmap.h
new file mode 100644
index 000..5121f63
--- /dev/null
+++ b/target/riscv/instmap.h
@@ -0,0 +1,377 @@
+/*
+ * RISC-V emulation for qemu: Instruction decode helpers
+ *
+ * Author: Sagar Karandikar, sag...@eecs.berkeley.edu
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see .
+ */
+
+#define MASK_OP_MAJOR(op)  (op & 0x7F)
+enum {
+/* rv32i, rv64i, rv32m */
+OPC_RISC_LUI= (0x37),
+OPC_RISC_AUIPC  = (0x17),
+OPC_RISC_JAL= (0x6F),
+OPC_RISC_JALR   = (0x67),
+OPC_RISC_BRANCH = (0x63),
+OPC_RISC_LOAD   = (0x03),
+OPC_RISC_STORE  = (0x23),
+OPC_RISC_ARITH_IMM  = (0x13),
+OPC_RISC_ARITH  = (0x33),
+OPC_RISC_FENCE  = (0x0F),
+OPC_RISC_SYSTEM = (0x73),
+
+/* rv64i, rv64m */
+OPC_RISC_ARITH_IMM_W = (0x1B),
+OPC_RISC_ARITH_W = (0x3B),
+
+/* rv32a, rv64a */
+OPC_RISC_ATOMIC = (0x2F),
+
+/* floating point */
+OPC_RISC_FP_LOAD = (0x7),
+OPC_RISC_FP_STORE = (0x27),
+
+OPC_RISC_FMADD = (0x43),
+OPC_RISC_FMSUB = (0x47),
+OPC_RISC_FNMSUB = (0x4B),
+OPC_RISC_FNMADD = (0x4F),
+
+OPC_RISC_FP_ARITH = (0x53),
+};
+
+#define MASK_OP_ARITH(op)   (MASK_OP_MAJOR(op) | (op & ((0x7 << 12) | \
+(0x7F << 25
+enum {
+OPC_RISC_ADD   = OPC_RISC_ARITH | (0x0 << 12) | (0x00 << 25),
+OPC_RISC_SUB   = OPC_RISC_ARITH | (0x0 << 12) | (0x20 << 25),
+OPC_RISC_SLL   = OPC_RISC_ARITH | (0x1 << 12) | (0x00 << 25),
+OPC_RISC_SLT   = OPC_RISC_ARITH | (0x2 << 12) | (0x00 << 25),
+OPC_RISC_SLTU  = OPC_RISC_ARITH | (0x3 << 12) | (0x00 << 25),
+OPC_RISC_XOR   = OPC_RISC_ARITH | (0x4 << 12) | (0x00 << 25),
+OPC_RISC_SRL   = OPC_RISC_ARITH | (0x5 << 12) | (0x00 << 25),
+OPC_RISC_SRA   = OPC_RISC_ARITH | (0x5 << 12) | (0x20 << 25),
+OPC_RISC_OR= OPC_RISC_ARITH | (0x6 << 12) | (0x00 << 25),
+OPC_RISC_AND   = OPC_RISC_ARITH | (0x7 << 12) | (0x00 << 25),
+
+/* RV64M */
+OPC_RISC_MUL= OPC_RISC_ARITH | (0x0 << 12) | (0x01 << 25),
+OPC_RISC_MULH   = OPC_RISC_ARITH | (0x1 << 12) | (0x01 << 25),
+OPC_RISC_MULHSU = OPC_RISC_ARITH | (0x2 << 12) | (0x01 << 25),
+OPC_RISC_MULHU  = OPC_RISC_ARITH | (0x3 << 12) | (0x01 << 25),
+
+OPC_RISC_DIV= OPC_RISC_ARITH | (0x4 << 12) | (0x01 << 25),
+OPC_RISC_DIVU   = OPC_RISC_ARITH | (0x5 << 12) | (0x01 << 25),
+OPC_RISC_REM= OPC_RISC_ARITH | (0x6 << 12) | (0x01 << 25),
+OPC_RISC_REMU   = OPC_RISC_ARITH | (0x7 << 12) | (0x01 << 25),
+};
+
+
+#define MASK_OP_ARITH_IMM(op)   (MASK_OP_MAJOR(op) | (op & (0x7 << 12)))
+enum {
+OPC_RISC_ADDI   = OPC_RISC_ARITH_IMM | (0x0 << 12),
+OPC_RISC_SLTI   = OPC_RISC_ARITH_IMM | (0x2 << 12),
+OPC_RISC_SLTIU  = OPC_RISC_ARITH_IMM | (0x3 << 12),
+OPC_RISC_XORI   = OPC_RISC_ARITH_IMM | (0x4 << 12),
+OPC_RISC_ORI= OPC_RISC_ARITH_IMM | (0x6 << 12),
+OPC_RISC_ANDI   = OPC_RISC_ARITH_IMM | (0x7 << 12),
+OPC_RISC_SLLI   = OPC_RISC_ARITH_IMM | (0x1 << 12), /* additional part of
+   IMM */
+OPC_RISC_SHIFT_RIGHT_I = OPC_RISC_ARITH_IMM | (0x5 << 12) /* SRAI, SRLI */
+};
+
+#define MASK_OP_BRANCH(op) (MASK_OP_MAJOR(op) | (op & (0x7 << 12)))
+enum {
+OPC_RISC_BEQ  = OPC_RISC_BRANCH  | (0x0  << 12),
+OPC_RISC_BNE  = OPC_RISC_BRANCH  | (0x1  << 12),
+OPC_RISC_BLT  = OPC_RISC_BRANCH  | (0x4  << 12),
+OPC_RISC_BGE  = OPC_RISC_BRANCH  | (0x5  << 12),
+OPC_RISC_BLTU = OPC_RISC_BRANCH  | (0x6  << 12),
+OPC_RISC_BGEU = OPC_RISC_BRANCH  | (0x7  << 12)
+};
+
+enum {
+OPC_RISC_ADDIW   = OPC_RISC_ARITH_IMM_W | (0x0 << 1

[Qemu-devel] [PATCH v2 21/21] RISC-V Build Infrastructure

2018-01-10 Thread Michael Clark
This adds RISC-V into the build system enabling the following targets:

- riscv32-softmmu
- riscv64-softmmu
- riscv32-linux-user
- riscv64-linux-user

This adds defaults configs for RISC-V, enables the build for the RISC-V
CPU core, hardware, and Linux User Emulation. The 'qemu-binfmt-conf.sh'
script is updated to add the RISC-V ELF magic.

Expected checkpatch errors for consistency reasons:

ERROR: line over 90 characters
FILE: scripts/qemu-binfmt-conf.sh
Signed-off-by: Michael Clark 
---
 Makefile.objs  |  1 +
 arch_init.c|  2 ++
 configure  | 11 +++
 cpus.c |  6 ++
 default-configs/riscv32-linux-user.mak |  1 +
 default-configs/riscv32-softmmu.mak|  4 
 default-configs/riscv64-linux-user.mak |  1 +
 default-configs/riscv64-softmmu.mak|  4 
 hw/riscv/Makefile.objs | 12 
 include/sysemu/arch_init.h |  1 +
 qapi-schema.json   | 14 +-
 scripts/qemu-binfmt-conf.sh| 13 -
 target/riscv/Makefile.objs |  2 ++
 target/riscv/trace-events  |  1 +
 14 files changed, 71 insertions(+), 2 deletions(-)
 create mode 100644 default-configs/riscv32-linux-user.mak
 create mode 100644 default-configs/riscv32-softmmu.mak
 create mode 100644 default-configs/riscv64-linux-user.mak
 create mode 100644 default-configs/riscv64-softmmu.mak
 create mode 100644 hw/riscv/Makefile.objs
 create mode 100644 target/riscv/Makefile.objs
 create mode 100644 target/riscv/trace-events

diff --git a/Makefile.objs b/Makefile.objs
index 285c6f3..ae8658e 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -164,6 +164,7 @@ trace-events-subdirs += target/mips
 trace-events-subdirs += target/sparc
 trace-events-subdirs += target/s390x
 trace-events-subdirs += target/ppc
+trace-events-subdirs += target/riscv
 trace-events-subdirs += qom
 trace-events-subdirs += linux-user
 trace-events-subdirs += qapi
diff --git a/arch_init.c b/arch_init.c
index a0b8ed6..dcf356b 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -69,6 +69,8 @@ int graphic_depth = 32;
 #define QEMU_ARCH QEMU_ARCH_OPENRISC
 #elif defined(TARGET_PPC)
 #define QEMU_ARCH QEMU_ARCH_PPC
+#elif defined(TARGET_RISCV)
+#define QEMU_ARCH QEMU_ARCH_RISCV
 #elif defined(TARGET_S390X)
 #define QEMU_ARCH QEMU_ARCH_S390X
 #elif defined(TARGET_SH4)
diff --git a/configure b/configure
index 6a04082..a8151f9 100755
--- a/configure
+++ b/configure
@@ -6565,6 +6565,14 @@ case "$target_name" in
 echo "TARGET_ABI32=y" >> $config_target_mak
 gdb_xml_files="power64-core.xml power-fpu.xml power-altivec.xml 
power-spe.xml power-vsx.xml"
   ;;
+  riscv32)
+TARGET_BASE_ARCH=riscv
+TARGET_ABI_DIR=riscv
+  ;;
+  riscv64)
+TARGET_BASE_ARCH=riscv
+TARGET_ABI_DIR=riscv
+  ;;
   sh4|sh4eb)
 TARGET_ARCH=sh4
 bflt="yes"
@@ -6730,6 +6738,9 @@ for i in $ARCH $TARGET_BASE_ARCH ; do
   ppc*)
 disas_config "PPC"
   ;;
+  riscv)
+disas_config "RISCV"
+  ;;
   s390*)
 disas_config "S390"
   ;;
diff --git a/cpus.c b/cpus.c
index e8139de..499be10 100644
--- a/cpus.c
+++ b/cpus.c
@@ -1995,6 +1995,9 @@ CpuInfoList *qmp_query_cpus(Error **errp)
 #elif defined(TARGET_SPARC)
 SPARCCPU *sparc_cpu = SPARC_CPU(cpu);
 CPUSPARCState *env = &sparc_cpu->env;
+#elif defined(TARGET_RISCV)
+RISCVCPU *riscv_cpu = RISCV_CPU(cpu);
+CPURISCVState *env = &riscv_cpu->env;
 #elif defined(TARGET_MIPS)
 MIPSCPU *mips_cpu = MIPS_CPU(cpu);
 CPUMIPSState *env = &mips_cpu->env;
@@ -2028,6 +2031,9 @@ CpuInfoList *qmp_query_cpus(Error **errp)
 #elif defined(TARGET_TRICORE)
 info->value->arch = CPU_INFO_ARCH_TRICORE;
 info->value->u.tricore.PC = env->PC;
+#elif defined(TARGET_RISCV)
+info->value->arch = CPU_INFO_ARCH_RISCV;
+info->value->u.riscv.pc = env->pc;
 #else
 info->value->arch = CPU_INFO_ARCH_OTHER;
 #endif
diff --git a/default-configs/riscv32-linux-user.mak 
b/default-configs/riscv32-linux-user.mak
new file mode 100644
index 000..865b362
--- /dev/null
+++ b/default-configs/riscv32-linux-user.mak
@@ -0,0 +1 @@
+# Default configuration for riscv-linux-user
diff --git a/default-configs/riscv32-softmmu.mak 
b/default-configs/riscv32-softmmu.mak
new file mode 100644
index 000..f9e7421
--- /dev/null
+++ b/default-configs/riscv32-softmmu.mak
@@ -0,0 +1,4 @@
+# Default configuration for riscv-softmmu
+
+CONFIG_SERIAL=y
+CONFIG_VIRTIO=y
diff --git a/default-configs/riscv64-linux-user.mak 
b/default-configs/riscv64-linux-user.mak
new file mode 100644
index 000..865b362
--- /dev/null
+++ b/default-configs/riscv64-linux-user.mak
@@ -0,0 +1 @@
+# Default configuration for riscv-linux-user
diff --git a/default-configs/riscv64-softmmu.mak 
b/default-configs/riscv64-softmmu.mak
new file mode 100644
index 000..f9e7421
--- /dev/null
+++ b/default-configs/riscv64-softmmu.mak
@@

[Qemu-devel] [PATCH v2 14/21] SiFive RISC-V PLIC Block

2018-01-10 Thread Michael Clark
The PLIC (Platform Level Interrupt Controller) device provides a
parameterizable interrupt controller based on SiFive's PLIC specification.

Signed-off-by: Michael Clark 
---
 hw/riscv/sifive_plic.c | 554 +
 include/hw/riscv/sifive_plic.h |  91 +++
 2 files changed, 645 insertions(+)
 create mode 100644 hw/riscv/sifive_plic.c
 create mode 100644 include/hw/riscv/sifive_plic.h

diff --git a/hw/riscv/sifive_plic.c b/hw/riscv/sifive_plic.c
new file mode 100644
index 000..10942c2
--- /dev/null
+++ b/hw/riscv/sifive_plic.c
@@ -0,0 +1,554 @@
+/*
+ * SiFive PLIC (Platform Level Interrupt Controller)
+ *
+ * Copyright (c) 2017 SiFive, Inc.
+ *
+ * This provides a parameterizable interrupt controller based on SiFive's PLIC.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to 
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/error-report.h"
+#include "hw/sysbus.h"
+#include "target/riscv/cpu.h"
+#include "hw/riscv/sifive_plic.h"
+
+#define RISCV_DEBUG_PLIC 0
+
+static PLICMode char_to_mode(char c)
+{
+switch (c) {
+case 'U': return PLICMode_U;
+case 'S': return PLICMode_S;
+case 'H': return PLICMode_H;
+case 'M': return PLICMode_M;
+default:
+error_report("plic: invalid mode '%c'", c);
+exit(1);
+}
+}
+
+static char mode_to_char(PLICMode m)
+{
+switch (m) {
+case PLICMode_U: return 'U';
+case PLICMode_S: return 'S';
+case PLICMode_H: return 'H';
+case PLICMode_M: return 'M';
+default: return '?';
+}
+}
+
+static void sifive_plic_print_state(SiFivePLICState *plic)
+{
+int i;
+int addrid;
+
+/* pending */
+printf("pending   : ");
+for (i = plic->bitfield_words - 1; i >= 0; i--) {
+printf("%08x", plic->pending[i]);
+}
+printf("\n");
+
+/* pending */
+printf("claimed   : ");
+for (i = plic->bitfield_words - 1; i >= 0; i--) {
+printf("%08x", plic->claimed[i]);
+}
+printf("\n");
+
+for (addrid = 0; addrid < plic->num_addrs; addrid++) {
+printf("hart%d-%c enable: ",
+plic->addr_config[addrid].hartid,
+mode_to_char(plic->addr_config[addrid].mode));
+for (i = plic->bitfield_words - 1; i >= 0; i--) {
+printf("%08x", plic->enable[addrid * plic->bitfield_words + i]);
+}
+printf("\n");
+}
+}
+
+static
+void sifive_plic_set_pending(SiFivePLICState *plic, int irq, bool pending)
+{
+qemu_mutex_lock(&plic->lock);
+uint32_t word = irq >> 5;
+if (pending) {
+plic->pending[word] |= (1 << (irq & 31));
+} else {
+plic->pending[word] &= ~(1 << (irq & 31));
+}
+qemu_mutex_unlock(&plic->lock);
+}
+
+static
+void sifive_plic_set_claimed(SiFivePLICState *plic, int irq, bool claimed)
+{
+qemu_mutex_lock(&plic->lock);
+uint32_t word = irq >> 5;
+if (claimed) {
+plic->claimed[word] |= (1 << (irq & 31));
+} else {
+plic->claimed[word] &= ~(1 << (irq & 31));
+}
+qemu_mutex_unlock(&plic->lock);
+}
+
+static
+int sifive_plic_num_irqs_pending(SiFivePLICState *plic, uint32_t addrid)
+{
+int i, j, count = 0;
+for (i = 0; i < plic->bitfield_words; i++) {
+uint32_t pending_enabled_not_claimed =
+(plic->pending[i] & ~plic->claimed[i]) &
+plic->enable[addrid * plic->bitfield_words + i];
+if (!pending_enabled_not_claimed) {
+continue;
+}
+for (j = 0; j < 32; j++) {
+int irq = (i << 5) + j;
+uint32_t prio = plic->source_priority[irq];
+int enabled = pending_enabled_not_claimed & (1 << j);
+if (enabled && prio > plic->target_priority[addrid]) {
+count++;
+}
+}
+}
+return count;
+}
+
+static void sifive_plic_update(SiFivePLICState *plic)
+{
+int addrid;
+
+/* raise irq on harts where this irq is enabled */
+for (a

[Qemu-devel] [PATCH v2 18/21] SiFive RISC-V PRCI Block

2018-01-10 Thread Michael Clark
Simple model of the PRCI  (Power, Reset, Clock, Interrupt) to emulate
register reads made by the SDK BSP.

Signed-off-by: Michael Clark 
---
 hw/riscv/sifive_prci.c | 107 +
 include/hw/riscv/sifive_prci.h |  43 +
 2 files changed, 150 insertions(+)
 create mode 100644 hw/riscv/sifive_prci.c
 create mode 100644 include/hw/riscv/sifive_prci.h

diff --git a/hw/riscv/sifive_prci.c b/hw/riscv/sifive_prci.c
new file mode 100644
index 000..5c27696
--- /dev/null
+++ b/hw/riscv/sifive_prci.c
@@ -0,0 +1,107 @@
+/*
+ * QEMU SiFive PRCI (Power, Reset, Clock, Interrupt)
+ *
+ * Copyright (c) 2017 SiFive, Inc.
+ *
+ * Simple model of the PRCI to emulate register reads made by the SDK BSP
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to 
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "qemu/osdep.h"
+#include "hw/sysbus.h"
+#include "target/riscv/cpu.h"
+#include "hw/riscv/sifive_prci.h"
+
+/* currently implements enough to mock freedom-e-sdk BSP clock programming */
+
+static uint64_t sifive_prci_read(void *opaque, hwaddr addr, unsigned int size)
+{
+if (addr == 0 /* PRCI_HFROSCCFG */) {
+return 1 << 31; /* ROSC_RDY */
+}
+if (addr == 8 /* PRCI_PLLCFG*/) {
+return 1 << 31; /* PLL_LOCK */
+}
+hw_error("%s: read: addr=0x%x\n", __func__, (int)addr);
+return 0;
+}
+
+static void sifive_prci_write(void *opaque, hwaddr addr,
+   uint64_t val64, unsigned int size)
+{
+/* discard writes */
+}
+
+static const MemoryRegionOps sifive_prci_ops = {
+.read = sifive_prci_read,
+.write = sifive_prci_write,
+.endianness = DEVICE_NATIVE_ENDIAN,
+.valid = {
+.min_access_size = 4,
+.max_access_size = 4
+}
+};
+
+static Property sifive_prci_properties[] = {
+DEFINE_PROP_END_OF_LIST(),
+};
+
+static void sifive_prci_init(Object *obj)
+{
+SiFivePRCIState *s = SIFIVE_PRCI(obj);
+
+memory_region_init_io(&s->mmio, obj, &sifive_prci_ops, s,
+  TYPE_SIFIVE_PRCI, 0x8000);
+sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio);
+}
+
+static void sifive_prci_class_init(ObjectClass *klass, void *data)
+{
+DeviceClass *dc = DEVICE_CLASS(klass);
+
+dc->props = sifive_prci_properties;
+}
+
+static const TypeInfo sifive_prci_info = {
+.name  = TYPE_SIFIVE_PRCI,
+.parent= TYPE_SYS_BUS_DEVICE,
+.instance_size = sizeof(SiFivePRCIState),
+.instance_init = sifive_prci_init,
+.class_init= sifive_prci_class_init,
+};
+
+static void sifive_prci_register_types(void)
+{
+type_register_static(&sifive_prci_info);
+}
+
+type_init(sifive_prci_register_types)
+
+
+/*
+ * Create PRCI device.
+ */
+DeviceState *sifive_prci_create(hwaddr addr)
+{
+DeviceState *dev = qdev_create(NULL, TYPE_SIFIVE_PRCI);
+qdev_init_nofail(dev);
+sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, addr);
+return dev;
+}
diff --git a/include/hw/riscv/sifive_prci.h b/include/hw/riscv/sifive_prci.h
new file mode 100644
index 000..0e032e5
--- /dev/null
+++ b/include/hw/riscv/sifive_prci.h
@@ -0,0 +1,43 @@
+/*
+ * QEMU SiFive PRCI (Power, Reset, Clock, Interrupt) interface
+ *
+ * Copyright (c) 2017 SiFive, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to 
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL

[Qemu-devel] [PATCH v2 16/21] RISC-V VirtIO Machine

2018-01-10 Thread Michael Clark
RISC-V machine with device-tree, 16550a UART and VirtIO MMIO.
The following machine is implemented:

- 'virt'; CLINT, PLIC, 16550A UART, VirtIO MMIO, device-tree

Signed-off-by: Michael Clark 
---
 hw/riscv/virt.c | 364 
 include/hw/riscv/virt.h |  73 ++
 2 files changed, 437 insertions(+)
 create mode 100644 hw/riscv/virt.c
 create mode 100644 include/hw/riscv/virt.h

diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
new file mode 100644
index 000..7c6fead
--- /dev/null
+++ b/hw/riscv/virt.c
@@ -0,0 +1,364 @@
+/*
+ * QEMU RISC-V VirtIO Board
+ *
+ * Copyright (c) 2017 SiFive, Inc.
+ *
+ * RISC-V machine with 16550a UART and VirtIO MMIO
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to 
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+#include "qemu/error-report.h"
+#include "hw/hw.h"
+#include "hw/boards.h"
+#include "hw/loader.h"
+#include "hw/sysbus.h"
+#include "hw/char/serial.h"
+#include "target/riscv/cpu.h"
+#include "hw/riscv/riscv_htif.h"
+#include "hw/riscv/riscv_hart.h"
+#include "hw/riscv/sifive_plic.h"
+#include "hw/riscv/sifive_clint.h"
+#include "hw/riscv/virt.h"
+#include "chardev/char.h"
+#include "sysemu/arch_init.h"
+#include "sysemu/device_tree.h"
+#include "exec/address-spaces.h"
+#include "elf.h"
+
+static const struct MemmapEntry {
+hwaddr base;
+hwaddr size;
+} virt_memmap[] = {
+[VIRT_DEBUG] ={0x0,  0x100 },
+[VIRT_MROM] = { 0x1000, 0x2000 },
+[VIRT_CLINT] ={  0x200,0x1 },
+[VIRT_PLIC] = {  0xc00,  0x400 },
+[VIRT_UART0] ={ 0x1000,  0x100 },
+[VIRT_VIRTIO] =   { 0x10001000, 0x1000 },
+[VIRT_DRAM] = { 0x8000,0x0 },
+};
+
+static uint64_t identity_translate(void *opaque, uint64_t addr)
+{
+return addr;
+}
+
+static uint64_t load_kernel(const char *kernel_filename)
+{
+uint64_t kernel_entry, kernel_high;
+
+if (load_elf(kernel_filename, identity_translate, NULL,
+ &kernel_entry, NULL, &kernel_high,
+ /* little_endian = */ 0, ELF_MACHINE, 1, 0) < 0) {
+error_report("qemu: could not load kernel '%s'", kernel_filename);
+exit(1);
+}
+return kernel_entry;
+}
+
+static void create_fdt(RISCVVirtState *s, const struct MemmapEntry *memmap,
+uint64_t mem_size, const char *cmdline)
+{
+void *fdt;
+int cpu;
+uint32_t *cells;
+char *nodename;
+uint32_t plic_phandle, phandle = 1;
+int i;
+
+fdt = s->fdt = create_device_tree(&s->fdt_size);
+if (!fdt) {
+error_report("create_device_tree() failed");
+exit(1);
+}
+
+qemu_fdt_setprop_string(fdt, "/", "model", "riscv-virtio,qemu");
+qemu_fdt_setprop_string(fdt, "/", "compatible", "riscv-virtio");
+qemu_fdt_setprop_cell(fdt, "/", "#size-cells", 0x2);
+qemu_fdt_setprop_cell(fdt, "/", "#address-cells", 0x2);
+
+qemu_fdt_add_subnode(fdt, "/soc");
+qemu_fdt_setprop(fdt, "/soc", "ranges", NULL, 0);
+qemu_fdt_setprop_string(fdt, "/soc", "compatible", "riscv-virtio-soc");
+qemu_fdt_setprop_cell(fdt, "/soc", "#size-cells", 0x2);
+qemu_fdt_setprop_cell(fdt, "/soc", "#address-cells", 0x2);
+
+nodename = g_strdup_printf("/memory@%lx",
+(long)memmap[VIRT_DRAM].base);
+qemu_fdt_add_subnode(fdt, nodename);
+qemu_fdt_setprop_cells(fdt, nodename, "reg",
+memmap[VIRT_DRAM].base >> 32, memmap[VIRT_DRAM].base,
+mem_size >> 32, mem_size);
+qemu_fdt_setprop_string(fdt, nodename, "device_type", "memory");
+g_free(nodename);
+
+qemu_fdt_add_subnode(fdt, "/cpus");
+qemu_fdt_setprop_cell(fdt, "/cpus", "timebase-frequency", 1000);
+qemu_fdt_setprop_cell(fdt, "/cpus", "#size-cells", 0x0);
+qemu_fdt_setprop_cell(fdt, "/cpus", "#address-cells", 0x1);
+
+for (cpu = s->soc.num_harts - 1; cpu >= 0; cpu--) {
+int cpu_phandle = phandle++;
+

[Qemu-devel] [PATCH v2 17/21] SiFive RISC-V UART Device

2018-01-10 Thread Michael Clark
QEMU model of the UART on the SiFive E300 and U500 series SOCs.
BBL supports the SiFive UART for early console access via the SBI
(Supervisor Binary Interface) and the linux kernel SBI console.

The SiFive UART implements the pre qom legacy interface consistent
with the 16550a UART in 'hw/char/serial.c'.

Signed-off-by: Michael Clark 
---
 hw/riscv/sifive_uart.c | 182 +
 include/hw/riscv/sifive_uart.h |  76 +
 2 files changed, 258 insertions(+)
 create mode 100644 hw/riscv/sifive_uart.c
 create mode 100644 include/hw/riscv/sifive_uart.h

diff --git a/hw/riscv/sifive_uart.c b/hw/riscv/sifive_uart.c
new file mode 100644
index 000..0e73df6
--- /dev/null
+++ b/hw/riscv/sifive_uart.c
@@ -0,0 +1,182 @@
+/*
+ * QEMU model of the UART on the SiFive E300 and U500 series SOCs.
+ *
+ * Copyright (c) 2016 Stefan O'Rear
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to 
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "hw/sysbus.h"
+#include "chardev/char.h"
+#include "chardev/char-fe.h"
+#include "target/riscv/cpu.h"
+#include "hw/riscv/sifive_uart.h"
+
+/*
+ * Not yet implemented:
+ *
+ * Transmit FIFO using "qemu/fifo8.h"
+ * SIFIVE_UART_IE_TXWM interrupts
+ * SIFIVE_UART_IE_RXWM interrupts must honor fifo watermark
+ * Rx FIFO watermark interrupt trigger threshold
+ * Tx FIFO watermark interrupt trigger threshold.
+ */
+
+static void update_irq(SiFiveUARTState *s)
+{
+int cond = 0;
+if ((s->ie & SIFIVE_UART_IE_RXWM) && s->rx_fifo_len) {
+cond = 1;
+}
+if (cond) {
+qemu_irq_raise(s->irq);
+} else {
+qemu_irq_lower(s->irq);
+}
+}
+
+static uint64_t
+uart_read(void *opaque, hwaddr addr, unsigned int size)
+{
+SiFiveUARTState *s = opaque;
+unsigned char r;
+switch (addr) {
+case SIFIVE_UART_RXFIFO:
+if (s->rx_fifo_len) {
+r = s->rx_fifo[0];
+memmove(s->rx_fifo, s->rx_fifo + 1, s->rx_fifo_len - 1);
+s->rx_fifo_len--;
+qemu_chr_fe_accept_input(&s->chr);
+update_irq(s);
+return r;
+}
+return 0x8000;
+
+case SIFIVE_UART_TXFIFO:
+return 0; /* Should check tx fifo */
+case SIFIVE_UART_IE:
+return s->ie;
+case SIFIVE_UART_IP:
+return s->rx_fifo_len ? SIFIVE_UART_IP_RXWM : 0;
+case SIFIVE_UART_TXCTRL:
+return s->txctrl;
+case SIFIVE_UART_RXCTRL:
+return s->rxctrl;
+case SIFIVE_UART_DIV:
+return s->div;
+}
+
+hw_error("%s: bad read: addr=0x%x\n",
+__func__, (int)addr);
+return 0;
+}
+
+static void
+uart_write(void *opaque, hwaddr addr,
+   uint64_t val64, unsigned int size)
+{
+SiFiveUARTState *s = opaque;
+uint32_t value = val64;
+unsigned char ch = value;
+
+switch (addr) {
+case SIFIVE_UART_TXFIFO:
+qemu_chr_fe_write(&s->chr, &ch, 1);
+return;
+case SIFIVE_UART_IE:
+s->ie = val64;
+update_irq(s);
+return;
+case SIFIVE_UART_TXCTRL:
+s->txctrl = val64;
+return;
+case SIFIVE_UART_RXCTRL:
+s->rxctrl = val64;
+return;
+case SIFIVE_UART_DIV:
+s->div = val64;
+return;
+}
+hw_error("%s: bad write: addr=0x%x v=0x%x\n",
+__func__, (int)addr, (int)value);
+}
+
+static const MemoryRegionOps uart_ops = {
+.read = uart_read,
+.write = uart_write,
+.endianness = DEVICE_NATIVE_ENDIAN,
+.valid = {
+.min_access_size = 4,
+.max_access_size = 4
+}
+};
+
+static void uart_rx(void *opaque, const uint8_t *buf, int size)
+{
+SiFiveUARTState *s = opaque;
+
+/* Got a byte.  */
+if (s->rx_fifo_len >= sizeof(s->rx_fifo)) {
+printf("WARNING: UART dropped char.\n");
+return;
+}
+s->rx_fifo[s->rx_fifo_len++] = *buf;
+
+update_irq(s);
+}
+
+static int uart_can_rx(void *opaque)

[Qemu-devel] [PATCH v2 12/21] RISC-V HART Array

2018-01-10 Thread Michael Clark
Holds the state of a heterogenous array of RISC-V hardware threads.

Signed-off-by: Michael Clark 
---
 hw/riscv/riscv_hart.c | 95 +++
 include/hw/riscv/riscv_hart.h | 45 
 2 files changed, 140 insertions(+)
 create mode 100644 hw/riscv/riscv_hart.c
 create mode 100644 include/hw/riscv/riscv_hart.h

diff --git a/hw/riscv/riscv_hart.c b/hw/riscv/riscv_hart.c
new file mode 100644
index 000..a7e079e
--- /dev/null
+++ b/hw/riscv/riscv_hart.c
@@ -0,0 +1,95 @@
+/*
+ * QEMU RISCV Hart Array
+ *
+ * Copyright (c) 2017 SiFive, Inc.
+ *
+ * Holds the state of a heterogenous array of RISC-V harts
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to 
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "hw/sysbus.h"
+#include "target/riscv/cpu.h"
+#include "hw/riscv/riscv_hart.h"
+
+static Property riscv_harts_props[] = {
+DEFINE_PROP_UINT32("num-harts", RISCVHartArrayState, num_harts, 1),
+DEFINE_PROP_STRING("cpu-model", RISCVHartArrayState, cpu_model),
+DEFINE_PROP_END_OF_LIST(),
+};
+
+static void riscv_harts_cpu_reset(void *opaque)
+{
+RISCVCPU *cpu = opaque;
+cpu_reset(CPU(cpu));
+}
+
+static void riscv_harts_realize(DeviceState *dev, Error **errp)
+{
+RISCVHartArrayState *s = RISCV_HART_ARRAY(dev);
+Error *err = NULL;
+int n;
+
+s->harts = g_new0(RISCVCPU, s->num_harts);
+
+for (n = 0; n < s->num_harts; n++) {
+
+object_initialize(&s->harts[n], sizeof(RISCVCPU), s->cpu_model);
+s->harts[n].env.mhartid = n;
+object_property_add_child(OBJECT(s), "harts[*]", OBJECT(&s->harts[n]),
+  &error_abort);
+qemu_register_reset(riscv_harts_cpu_reset, &s->harts[n]);
+object_property_set_bool(OBJECT(&s->harts[n]), true,
+ "realized", &err);
+if (err) {
+error_propagate(errp, err);
+return;
+}
+}
+}
+
+static void riscv_harts_class_init(ObjectClass *klass, void *data)
+{
+DeviceClass *dc = DEVICE_CLASS(klass);
+
+dc->props = riscv_harts_props;
+dc->realize = riscv_harts_realize;
+}
+
+static void riscv_harts_init(Object *obj)
+{
+/* RISCVHartArrayState *s = SIFIVE_COREPLEX(obj); */
+}
+
+static const TypeInfo riscv_harts_info = {
+.name  = TYPE_RISCV_HART_ARRAY,
+.parent= TYPE_SYS_BUS_DEVICE,
+.instance_size = sizeof(RISCVHartArrayState),
+.instance_init = riscv_harts_init,
+.class_init= riscv_harts_class_init,
+};
+
+static void riscv_harts_register_types(void)
+{
+type_register_static(&riscv_harts_info);
+}
+
+type_init(riscv_harts_register_types)
diff --git a/include/hw/riscv/riscv_hart.h b/include/hw/riscv/riscv_hart.h
new file mode 100644
index 000..c45e987
--- /dev/null
+++ b/include/hw/riscv/riscv_hart.h
@@ -0,0 +1,45 @@
+/*
+ * QEMU RISC-V Hart Array interface
+ *
+ * Copyright (c) 2017 SiFive, Inc.
+ *
+ * Holds the state of a heterogenous array of RISC-V harts
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to 
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIA

[Qemu-devel] [PATCH v2 10/21] RISC-V Linux User Emulation

2018-01-10 Thread Michael Clark
Implementation of linux user emulation for RISC-V.

Signed-off-by: Michael Clark 
---
 linux-user/elfload.c  |  22 +++
 linux-user/main.c | 114 +++
 linux-user/riscv/syscall_nr.h | 275 +++
 linux-user/riscv/target_cpu.h |  18 +++
 linux-user/riscv/target_signal.h  |  23 +++
 linux-user/riscv/target_structs.h |  46 ++
 linux-user/riscv/target_syscall.h |  56 
 linux-user/riscv/termbits.h   | 220 
 linux-user/signal.c   | 203 +-
 linux-user/syscall.c  |   2 +
 linux-user/syscall_defs.h |  13 +-
 target/riscv/cpu_user.h   |  26 
 target/riscv/user_atomic.c| 291 ++
 13 files changed, 1303 insertions(+), 6 deletions(-)
 create mode 100644 linux-user/riscv/syscall_nr.h
 create mode 100644 linux-user/riscv/target_cpu.h
 create mode 100644 linux-user/riscv/target_signal.h
 create mode 100644 linux-user/riscv/target_structs.h
 create mode 100644 linux-user/riscv/target_syscall.h
 create mode 100644 linux-user/riscv/termbits.h
 create mode 100644 target/riscv/cpu_user.h
 create mode 100644 target/riscv/user_atomic.c

diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 20f3d8c..178af56 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -1272,6 +1272,28 @@ static inline void init_thread(struct target_pt_regs 
*regs,
 
 #endif /* TARGET_TILEGX */
 
+#ifdef TARGET_RISCV
+
+#define ELF_START_MMAP 0x8000
+#define ELF_ARCH  EM_RISCV
+
+#ifdef TARGET_RISCV32
+#define ELF_CLASS ELFCLASS32
+#else
+#define ELF_CLASS ELFCLASS64
+#endif
+
+static inline void init_thread(struct target_pt_regs *regs,
+   struct image_info *infop)
+{
+regs->sepc = infop->entry;
+regs->sp = infop->start_stack;
+}
+
+#define ELF_EXEC_PAGESIZE 4096
+
+#endif /* TARGET_RISCV */
+
 #ifdef TARGET_HPPA
 
 #define ELF_START_MMAP  0x8000
diff --git a/linux-user/main.c b/linux-user/main.c
index 99a551b..2b8fcc2 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -3647,6 +3647,115 @@ void cpu_loop(CPUTLGState *env)
 
 #endif
 
+#ifdef TARGET_RISCV
+
+void cpu_loop(CPURISCVState *env)
+{
+CPUState *cs = CPU(riscv_env_get_cpu(env));
+int trapnr, signum, sigcode;
+target_ulong sigaddr;
+target_ulong ret;
+
+for (;;) {
+cpu_exec_start(cs);
+trapnr = cpu_exec(cs);
+cpu_exec_end(cs);
+
+signum = 0;
+sigcode = 0;
+sigaddr = 0;
+
+switch (trapnr) {
+case EXCP_INTERRUPT:
+/* just indicate that signals should be handled asap */
+break;
+case RISCV_EXCP_U_ECALL:
+env->pc += 4;
+if (env->gpr[xA7] == TARGET_NR_arch_specific_syscall + 15) {
+/* riscv_flush_icache_syscall is a no-op in QEMU as
+   self-modifying code is automatically detected */
+ret = 0;
+} else {
+ret = do_syscall(env,
+ env->gpr[xA7],
+ env->gpr[xA0],
+ env->gpr[xA1],
+ env->gpr[xA2],
+ env->gpr[xA3],
+ env->gpr[xA4],
+ env->gpr[xA5],
+ 0, 0);
+}
+if (ret == -TARGET_ERESTARTSYS) {
+env->pc -= 4;
+} else if (ret != -TARGET_QEMU_ESIGRETURN) {
+env->gpr[xA0] = ret;
+}
+if (cs->singlestep_enabled) {
+goto gdbstep;
+}
+break;
+case QEMU_USER_EXCP_ATOMIC:
+start_exclusive();
+switch (riscv_cpu_do_usermode_amo(cs)) {
+case RISCV_AMO_OK:
+env->pc += 4;
+break;
+case RISCV_AMO_BADADDR:
+signum = TARGET_SIGSEGV;
+sigcode = TARGET_SEGV_MAPERR;
+sigaddr = env->badaddr;
+break;
+case RISCV_AMO_BADINSN:
+default:
+signum = TARGET_SIGILL;
+sigcode = TARGET_ILL_ILLOPC;
+}
+end_exclusive();
+if (cs->singlestep_enabled) {
+goto gdbstep;
+}
+break;
+case RISCV_EXCP_ILLEGAL_INST:
+signum = TARGET_SIGILL;
+sigcode = TARGET_ILL_ILLOPC;
+break;
+case RISCV_EXCP_BREAKPOINT:
+signum = TARGET_SIGTRAP;
+sigcode = TARGET_TRAP_BRKPT;
+sigaddr = env->pc;
+break;
+case QEMU_USER_EXCP_FAULT:
+signum = TARGET_SIGSEGV;
+sigcode = TARGET_SEGV_MAPERR;
+break;
+case EXCP_DEBUG:
+gdbstep:
+signum =

[Qemu-devel] [PATCH v2 11/21] RISC-V HTIF Console

2018-01-10 Thread Michael Clark
HTIF (Host Target Interface) provides console emulation for QEMU. HTIF
allows identical copies of BBL (Berkeley Boot Loader) and linux to run
on both Spike and QEMU. BBL provides HTIF console access via the
SBI (Supervisor Binary Interface) and the linux kernel SBI console.

The HTIF interface reads the ELF kernel and locates the 'tohost' and
'fromhost' symbols which it uses for guest to host console MMIO.

The HTIT chardev implements the pre qom legacy interface consistent
with the 16550a UART in 'hw/char/serial.c'.

Signed-off-by: Michael Clark 
---
 hw/riscv/riscv_elf.c  | 244 +++
 hw/riscv/riscv_htif.c | 373 ++
 include/hw/riscv/riscv_elf.h  |  69 
 include/hw/riscv/riscv_htif.h |  62 +++
 4 files changed, 748 insertions(+)
 create mode 100644 hw/riscv/riscv_elf.c
 create mode 100644 hw/riscv/riscv_htif.c
 create mode 100644 include/hw/riscv/riscv_elf.h
 create mode 100644 include/hw/riscv/riscv_htif.h

diff --git a/hw/riscv/riscv_elf.c b/hw/riscv/riscv_elf.c
new file mode 100644
index 000..355a5a1
--- /dev/null
+++ b/hw/riscv/riscv_elf.c
@@ -0,0 +1,244 @@
+/*
+ * elf.c - A simple package for manipulating symbol tables in elf binaries.
+ *
+ * Taken from
+ * https://www.cs.cmu.edu/afs/cs.cmu.edu/academic/class/15213-f03/www/
+ * ftrace/elf.c
+ *
+ */
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "hw/riscv/riscv_elf.h"
+
+/*
+ * elf_open - Map a binary into the address space and extract the
+ * locations of the static and dynamic symbol tables and their string
+ * tables. Return this information in a Elf object file handle that will
+ * be passed to all of the other elf functions.
+ */
+Elf_obj64 *elf_open64(const char *filename)
+{
+int i, fd;
+struct stat sbuf;
+Elf_obj64 *ep;
+Elf64_Shdr *shdr;
+
+ep = g_new(Elf_obj64, 1);
+
+/* Do some consistency checks on the binary */
+fd = open(filename, O_RDONLY);
+if (fd == -1) {
+fprintf(stderr, "Can't open \"%s\": %s\n", filename, strerror(errno));
+exit(1);
+}
+if (fstat(fd, &sbuf) == -1) {
+fprintf(stderr, "Can't stat \"%s\": %s\n", filename, strerror(errno));
+exit(1);
+}
+if (sbuf.st_size < sizeof(Elf64_Ehdr)) {
+fprintf(stderr, "\"%s\" is not an ELF binary object\n", filename);
+exit(1);
+}
+
+/* It looks OK, so map the Elf binary into our address space */
+ep->mlen = sbuf.st_size;
+ep->maddr = mmap(NULL, ep->mlen, PROT_READ, MAP_SHARED, fd, 0);
+if (ep->maddr == (void *)-1) {
+fprintf(stderr, "Can't mmap \"%s\": %s\n", filename, strerror(errno));
+exit(1);
+}
+close(fd);
+
+/* The Elf binary begins with the Elf header */
+ep->ehdr = ep->maddr;
+
+/* check we have a 64-bit little-endian RISC-V ELF object */
+if (ep->ehdr->e_ident[EI_MAG0] != ELFMAG0 ||
+ep->ehdr->e_ident[EI_MAG1] != ELFMAG1 ||
+ep->ehdr->e_ident[EI_MAG2] != ELFMAG2 ||
+ep->ehdr->e_ident[EI_MAG3] != ELFMAG3 ||
+ep->ehdr->e_ident[EI_CLASS] != ELFCLASS64 ||
+ep->ehdr->e_ident[EI_DATA] != ELFDATA2LSB ||
+ep->ehdr->e_machine != EM_RISCV)
+{
+fprintf(stderr, "\"%s\" is not a 64-bit RISC-V ELF object\n", 
filename);
+exit(1);
+}
+
+/*
+ * Find the static and dynamic symbol tables and their string
+ * tables in the the mapped binary. The sh_link field in symbol
+ * table section headers gives the section index of the string
+ * table for that symbol table.
+ */
+shdr = (Elf64_Shdr *)(ep->maddr + ep->ehdr->e_shoff);
+for (i = 0; i < ep->ehdr->e_shnum; i++) {
+if (shdr[i].sh_type == SHT_SYMTAB) {   /* Static symbol table */
+ep->symtab = (Elf64_Sym *)(ep->maddr + shdr[i].sh_offset);
+ep->symtab_end = (Elf64_Sym *)((char *)ep->symtab +
+ shdr[i].sh_size);
+ep->strtab = (char *)(ep->maddr + shdr[shdr[i].sh_link].sh_offset);
+}
+if (shdr[i].sh_type == SHT_DYNSYM) {   /* Dynamic symbol table */
+ep->dsymtab = (Elf64_Sym *)(ep->maddr + shdr[i].sh_offset);
+ep->dsymtab_end = (Elf64_Sym *)((char *)ep->dsymtab +
+  shdr[i].sh_size);
+ep->dstrtab = (char *)(ep->maddr + 
shdr[shdr[i].sh_link].sh_offset);
+}
+}
+return ep;
+}
+
+Elf_obj32 *elf_open32(const char *filename)
+{
+int i, fd;
+struct stat sbuf;
+Elf_obj32 *ep;
+Elf32_Shdr *shdr;
+
+ep = g_new(Elf_obj32, 1);
+
+/* Do some consistency checks on the binary */
+fd = open(filename, O_RDONLY);
+if (fd == -1) {
+fprintf(stderr, "Can't open \"%s\": %s\n", filename, strerror(errno));
+exit(1);
+}
+if (fstat(fd, &sbuf) == -1) {
+fprintf(stderr, "Can't stat \"%s\": %s\n", filename, strerror(errno));
+ 

[Qemu-devel] [PATCH v2 13/21] SiFive RISC-V CLINT Block

2018-01-10 Thread Michael Clark
The CLINT (Core Local Interruptor) device provides real-time clock, timer
and interprocessor interrupts based on SiFive's CLINT specification.

Signed-off-by: Michael Clark 
---
 hw/riscv/sifive_clint.c | 312 
 include/hw/riscv/sifive_clint.h |  56 
 2 files changed, 368 insertions(+)
 create mode 100644 hw/riscv/sifive_clint.c
 create mode 100644 include/hw/riscv/sifive_clint.h

diff --git a/hw/riscv/sifive_clint.c b/hw/riscv/sifive_clint.c
new file mode 100644
index 000..50d2a09
--- /dev/null
+++ b/hw/riscv/sifive_clint.c
@@ -0,0 +1,312 @@
+/*
+ * SiFive CLINT (Core Local Interruptor)
+ *
+ * Copyright (c) 2016-2017 Sagar Karandikar, sag...@eecs.berkeley.edu
+ * Copyright (c) 2017 SiFive, Inc.
+ *
+ * This provides real-time clock, timer and interprocessor interrupts.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to 
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/error-report.h"
+#include "hw/sysbus.h"
+#include "target/riscv/cpu.h"
+#include "hw/riscv/sifive_clint.h"
+#include "qemu/timer.h"
+
+/* See: riscv-pk/machine/sbi_entry.S and arch/riscv/kernel/time.c */
+#define TIMER_FREQ (10 * 1000 * 1000)
+
+uint64_t cpu_riscv_read_instret(CPURISCVState *env)
+{
+return muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), TIMER_FREQ,
+NANOSECONDS_PER_SECOND);
+}
+
+uint64_t cpu_riscv_read_rtc(void)
+{
+return muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), TIMER_FREQ,
+NANOSECONDS_PER_SECOND);
+}
+
+static void sifive_clint_irq_request(void *opaque, int irq, int level)
+{
+/* These are not the same irq numbers visible to the emulated processor. */
+RISCVCPU *cpu = opaque;
+CPURISCVState *env = &cpu->env;
+CPUState *cs = CPU(cpu);
+
+/* The CLINT currently uses irq 0 */
+
+if (level) {
+cpu_interrupt(cs, CPU_INTERRUPT_HARD);
+} else {
+if (!env->mip && !env->mfromhost) {
+/* no interrupts pending, no host interrupt for HTIF, reset */
+cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
+}
+}
+}
+
+/*
+ * Called when timecmp is written to update the QEMU timer or immediately
+ * trigger timer interrupt if mtimecmp <= current timer value.
+ */
+static void sifive_clint_timer_update(CPURISCVState *env)
+{
+uint64_t next;
+uint64_t diff;
+
+uint64_t rtc_r = cpu_riscv_read_rtc();
+
+if (env->timecmp <= rtc_r) {
+/* if we're setting an MTIMECMP value in the "past",
+   immediately raise the timer interrupt */
+env->mip |= MIP_MTIP;
+qemu_irq_raise(env->irq[3]);
+return;
+}
+
+/* otherwise, set up the future timer interrupt */
+diff = env->timecmp - rtc_r;
+/* back to ns (note args switched in muldiv64) */
+next = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
+muldiv64(diff, NANOSECONDS_PER_SECOND, TIMER_FREQ);
+timer_mod(env->timer, next);
+}
+
+/*
+ * Called by the callback used when the timer set using timer_mod expires.
+ * Should raise the timer interrupt line
+ */
+static void sifive_clint_timer_expire(CPURISCVState *env)
+{
+/* do not call update here */
+env->mip |= MIP_MTIP;
+qemu_irq_raise(env->irq[3]);
+}
+
+static void sifive_clint_write_timecmp(CPURISCVState *env, uint64_t value)
+{
+env->timecmp = value;
+env->mip &= ~MIP_MTIP;
+sifive_clint_timer_update(env);
+}
+
+/*
+ * Callback used when the timer set using timer_mod expires.
+ */
+static void sifive_clint_timer_cb(void *opaque)
+{
+CPURISCVState *env;
+env = opaque;
+sifive_clint_timer_expire(env);
+}
+
+/* CPU wants to read rtc or timecmp register */
+static uint64_t sifive_clint_read(void *opaque, hwaddr addr, unsigned size)
+{
+SiFiveCLINTState *clint = opaque;
+if (addr >= clint->sip_base &&
+addr < clint->sip_base + (clint->num_harts << 2)) {
+size_t hartid = (addr - clint->sip_base) >> 2;
+CPUSta

[Qemu-devel] [PATCH v2 09/21] RISC-V Physical Memory Protection

2018-01-10 Thread Michael Clark
Implements the physical memory protection extension as specified in
Privileged ISA Version 1.10.

PMP (Physical Memory Protection) is as-of-yet unused and needs testing.
The SiFive verification team have PMP test cases that will be run.

Nothing currently depends on PMP support. It would be preferable to keep
the code in-tree for folk that are interested in RISC-V PMP support.

Signed-off-by: Michael Clark 
---
 target/riscv/pmp.c | 386 +
 target/riscv/pmp.h |  70 ++
 2 files changed, 456 insertions(+)
 create mode 100644 target/riscv/pmp.c
 create mode 100644 target/riscv/pmp.h

diff --git a/target/riscv/pmp.c b/target/riscv/pmp.c
new file mode 100644
index 000..cdd6bf8
--- /dev/null
+++ b/target/riscv/pmp.c
@@ -0,0 +1,386 @@
+/*
+ * QEMU RISC-V PMP (Physical Memory Protection)
+ *
+ * Author: Daire McNamara, daire.mcnam...@emdalo.com
+ * Ivan Griffin, ivan.grif...@emdalo.com
+ *
+ * This provides a RISC-V Physical Memory Protection implementation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to 
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+/*
+ * PMP (Physical Memory Protection) is as-of-yet unused and needs testing.
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+#include "qapi/error.h"
+#include "cpu.h"
+#include "qemu-common.h"
+
+#ifndef CONFIG_USER_ONLY
+
+#define RISCV_DEBUG_PMP 0
+#define PMP_DEBUG(fmt, ...)  \
+  do {   \
+if (RISCV_DEBUG_PMP) {   \
+  qemu_log_mask(LOG_TRACE, "%s: " fmt, __func__, ##__VA_ARGS__); \
+}\
+  } while (0)
+
+static void pmp_write_cfg(CPURISCVState *env, uint32_t addr_index,
+uint8_t val);
+static uint8_t pmp_read_cfg(CPURISCVState *env, uint32_t addr_index);
+static void pmp_update_rule(CPURISCVState *env, uint32_t pmp_index);
+
+/*
+ * Accessor method to extract address matching type 'a field' from cfg reg
+ */
+static inline uint8_t pmp_get_a_field(uint8_t cfg)
+{
+uint8_t a = cfg >> 3;
+return a & 0x3;
+}
+
+/*
+ * Check whether a PMP is locked or not.
+ */
+static inline int pmp_is_locked(CPURISCVState *env, uint32_t pmp_index)
+{
+
+if (env->pmp_state.pmp[pmp_index].cfg_reg & PMP_LOCK) {
+return 1;
+}
+
+/* Top PMP has no 'next' to check */
+if ((pmp_index + 1u) >= MAX_RISCV_PMPS) {
+return 0;
+}
+
+/* In TOR mode, need to check the lock bit of the next pmp
+ * (if there is a next)
+ */
+const uint8_t a_field =
+pmp_get_a_field(env->pmp_state.pmp[pmp_index + 1].cfg_reg);
+if ((env->pmp_state.pmp[pmp_index + 1u].cfg_reg & PMP_LOCK) &&
+ (PMP_AMATCH_TOR == a_field)) {
+return 1;
+}
+
+return 0;
+}
+
+/*
+ * Count the number of active rules.
+ */
+static inline uint32_t pmp_get_num_rules(CPURISCVState *env)
+{
+ return env->pmp_state.num_rules;
+}
+
+/*
+ * Accessor to get the cfg reg for a specific PMP/HART
+ */
+static inline uint8_t pmp_read_cfg(CPURISCVState *env, uint32_t pmp_index)
+{
+if (pmp_index < MAX_RISCV_PMPS) {
+return env->pmp_state.pmp[pmp_index].cfg_reg;
+}
+
+return 0;
+}
+
+
+/*
+ * Accessor to set the cfg reg for a specific PMP/HART
+ * Bounds checks and relevant lock bit.
+ */
+static void pmp_write_cfg(CPURISCVState *env, uint32_t pmp_index, uint8_t val)
+{
+if (pmp_index < MAX_RISCV_PMPS) {
+if (!pmp_is_locked(env, pmp_index)) {
+env->pmp_state.pmp[pmp_index].cfg_reg = val;
+pmp_update_rule(env, pmp_index);
+} else {
+PMP_DEBUG("ignoring write - locked");
+}
+} else {
+PMP_DEBUG("ignoring write - out of bounds");
+}
+}
+
+static void pmp_decode_napot(target_ulong a, target_ulong *sa, target_ulong 
*ea)
+{
+/*
+   ...aaa0   8-byte NAPOT range
+   aa

[Qemu-devel] [PATCH v2 03/21] RISC-V CPU Core Definition

2018-01-10 Thread Michael Clark
Add CPU state header, CPU definitions and initialization routines

Signed-off-by: Michael Clark 
---
 target/riscv/cpu.c  | 391 +
 target/riscv/cpu.h  | 271 +++
 target/riscv/cpu_bits.h | 417 
 3 files changed, 1079 insertions(+)
 create mode 100644 target/riscv/cpu.c
 create mode 100644 target/riscv/cpu.h
 create mode 100644 target/riscv/cpu_bits.h

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
new file mode 100644
index 000..035dd39
--- /dev/null
+++ b/target/riscv/cpu.c
@@ -0,0 +1,391 @@
+/*
+ * QEMU RISC-V CPU
+ *
+ * Author: Sagar Karandikar, sag...@eecs.berkeley.edu
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see
+ * 
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+#include "cpu.h"
+#include "exec/exec-all.h"
+#include "qapi/error.h"
+#include "migration/vmstate.h"
+
+/* RISC-V CPU definitions */
+
+const char * const riscv_int_regnames[] = {
+  "zero", "ra  ", "sp  ", "gp  ", "tp  ", "t0  ", "t1  ", "t2  ",
+  "s0  ", "s1  ", "a0  ", "a1  ", "a2  ", "a3  ", "a4  ", "a5  ",
+  "a6  ", "a7  ", "s2  ", "s3  ", "s4  ", "s5  ", "s6  ", "s7  ",
+  "s8  ", "s9  ", "s10 ", "s11 ", "t3  ", "t4  ", "t5  ", "t6  "
+};
+
+const char * const riscv_fpr_regnames[] = {
+  "ft0 ", "ft1 ", "ft2 ", "ft3 ", "ft4 ", "ft5 ", "ft6 ",  "ft7 ",
+  "fs0 ", "fs1 ", "fa0 ", "fa1 ", "fa2 ", "fa3 ", "fa4 ",  "fa5 ",
+  "fa6 ", "fa7 ", "fs2 ", "fs3 ", "fs4 ", "fs5 ", "fs6 ",  "fs7 ",
+  "fs8 ", "fs9 ", "fs10", "fs11", "ft8 ", "ft9 ", "ft10",  "ft11"
+};
+
+const char * const riscv_excp_names[] = {
+"misaligned_fetch",
+"fault_fetch",
+"illegal_instruction",
+"breakpoint",
+"misaligned_load",
+"fault_load",
+"misaligned_store",
+"fault_store",
+"user_ecall",
+"supervisor_ecall",
+"hypervisor_ecall",
+"machine_ecall",
+"exec_page_fault",
+"load_page_fault",
+"reserved",
+"store_page_fault"
+};
+
+const char * const riscv_intr_names[] = {
+"u_software",
+"s_software",
+"h_software",
+"m_software",
+"u_timer",
+"s_timer",
+"h_timer",
+"m_timer",
+"u_external",
+"s_external",
+"h_external",
+"m_external",
+"coprocessor",
+"host"
+};
+
+typedef struct RISCVCPUInfo {
+const char *name;
+void (*initfn)(Object *obj);
+} RISCVCPUInfo;
+
+#ifdef CONFIG_USER_ONLY
+static void riscv_any_cpu_init(Object *obj)
+{
+CPURISCVState *env = &RISCV_CPU(obj)->env;
+env->misa = RVXLEN | RVI | RVM | RVA | RVF | RVD | RVC | RVU;
+env->misa_mask = env->misa;
+env->user_ver = USER_VERSION_2_02_0;
+env->priv_ver = PRIV_VERSION_1_10_0;
+}
+#else
+static void riscv_imafdcsu_priv1_9_cpu_init(Object *obj)
+{
+CPURISCVState *env = &RISCV_CPU(obj)->env;
+env->misa = RVXLEN | RVI | RVM | RVA | RVF | RVD | RVC | RVS | RVU;
+env->misa_mask = env->misa;
+env->user_ver = USER_VERSION_2_02_0;
+env->priv_ver = PRIV_VERSION_1_09_1;
+}
+
+static void riscv_imafdcsu_priv1_10_cpu_init(Object *obj)
+{
+CPURISCVState *env = &RISCV_CPU(obj)->env;
+env->misa = RVXLEN | RVI | RVM | RVA | RVF | RVD | RVC | RVS | RVU;
+env->misa_mask = env->misa;
+env->user_ver = USER_VERSION_2_02_0;
+env->priv_ver = PRIV_VERSION_1_10_0;
+}
+
+static void riscv_imacu_priv1_10_cpu_init(Object *obj)
+{
+CPURISCVState *env = &RISCV_CPU(obj)->env;
+env->misa = RVXLEN | RVI | RVM | RVA | RVC | RVU;
+env->misa_mask = env->misa;
+env->user_ver = USER_VERSION_2_02_0;
+env->priv_ver = PRIV_VERSION_1_10_0;
+}
+
+static void riscv_imac_priv1_10_cpu_init(Object *obj)
+{
+CPURISCVState *env = &RISCV_CPU(obj)->env;
+env->misa = RVXLEN | RVI | RVM | RVA | RVC;
+env->misa_mask = env->misa;
+env->user_ver = USER_VERSION_2_02_0;
+env->priv_ver = PRIV_VERSION_1_10_0;
+}
+#endif
+
+static const RISCVCPUInfo riscv_cpus[] = {
+#ifdef CONFIG_USER_ONLY
+{ TYPE_RISCV_CPU_ANY,riscv_any_cpu_init },
+#else
+{ TYPE_RISCV_CPU_IMAFDCSU_PRIV_1_09, riscv_imafdcsu_priv1_9_cpu_init },
+{ TYPE_RISCV_CPU_IMAFDCSU_PRIV_1_10, riscv_imafdcsu_priv1_10_cpu_init },
+{ TYPE_RISCV_CPU_IMACU_PRIV_1_10,riscv_imacu_priv1_10_cpu_init },
+{ TYPE_RISCV_CPU_IMAC_PRIV_1_10, riscv_imac_priv1_10_cpu_init },

[Qemu-devel] [PATCH v2 07/21] RISC-V GDB Stub

2018-01-10 Thread Michael Clark
GDB Register read and write routines.

Signed-off-by: Michael Clark 
---
 target/riscv/gdbstub.c | 59 ++
 1 file changed, 59 insertions(+)
 create mode 100644 target/riscv/gdbstub.c

diff --git a/target/riscv/gdbstub.c b/target/riscv/gdbstub.c
new file mode 100644
index 000..12d1d9f
--- /dev/null
+++ b/target/riscv/gdbstub.c
@@ -0,0 +1,59 @@
+/*
+ * RISC-V GDB Server Stub
+ *
+ * Author: Sagar Karandikar, sag...@eecs.berkeley.edu
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see .
+ */
+
+#include "qemu/osdep.h"
+#include "qemu-common.h"
+#include "exec/gdbstub.h"
+#include "cpu.h"
+
+int riscv_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
+{
+/* TODO proper x0 handling */
+RISCVCPU *cpu = RISCV_CPU(cs);
+CPURISCVState *env = &cpu->env;
+
+if (n < 32) {
+return gdb_get_regl(mem_buf, env->gpr[n]);
+} else if (n == 32) {
+return gdb_get_regl(mem_buf, env->pc);
+} else if (n < 65) {
+return gdb_get_reg64(mem_buf, env->fpr[n - 33]);
+}
+return 0;
+}
+
+int riscv_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
+{
+/* TODO proper x0 handling */
+RISCVCPU *cpu = RISCV_CPU(cs);
+CPURISCVState *env = &cpu->env;
+
+if (n < 32) {
+env->gpr[n] = ldtul_p(mem_buf);
+return sizeof(target_ulong);
+} else if (n == 32) {
+env->pc = ldtul_p(mem_buf);
+return sizeof(target_ulong);
+} else if (n < 65) {
+env->fpr[n - 33] = ldq_p(mem_buf); /* always 64-bit */
+return sizeof(uint64_t);
+}
+return 0;
+}
-- 
2.7.0




[Qemu-devel] [PATCH v2 00/21] RISC-V QEMU Port Submission v2

2018-01-10 Thread Michael Clark
QEMU RISC-V Emulation Support (RV64GC, RV32GC)

This patch series has major clean ups to target/riscv. There may be
some feedback that has been missed however the changelog is growing
quite large so we have decided to respin the patch series. No new
features have been added however a number of bugs have been fixed.

The git tree for this v2 patch series (squashed and rebased):

- https://github.com/riscv/riscv-qemu/tree/qemu-upstream-v2

The git tree for the v1 patch series with full review commit history:

- https://github.com/riscv/riscv-qemu/tree/qemu-upstream-v1

We're adding Palmer Dabbelt as a maintainer so that we have at least
two full-time RISC-V developers available to work on the port.

*** Known Issues ***

- Disassembler has some checkpatch warnings for the sake of code brevity
- scripts/qemu-binfmt-conf.sh has checkpatch warnings due to line length
- PMP (Physical Memory Protection) is as-of-yet unused and needs testing

*** Changelog ***

v2

- Remove redundant NULL terminators from disassembler register arrays
- Change disassembler register name arrays to const
- Refine disassembler internal function names
- Update dates in disassembler copyright message
- Remove #ifdef CONFIG_USER_ONLY version of cpu_has_work
- Use ULL suffix on 64-bit constants
- Move riscv_cpu_mmu_index from cpu.h to helper.c
- Move riscv_cpu_hw_interrupts_pending from cpu.h to helper.c
- Remove redundant TARGET_HAS_ICE from cpu.h
- Use qemu_irq instead of void* for irq definition in cpu.h
- Remove duplicate typedef from struct CPURISCVState
- Remove redundant g_strdup from cpu_register
- Remove redundant tlb_flush from riscv_cpu_reset
- Remove redundant mode calculation from get_physical_address
- Remove redundant debug mode printf and dcsr comment
- Remove redundant clearing of MSB for bare physical addresses
- Use g_assert_not_reached for invalid mode in get_physical_address
- Use g_assert_not_reached for unreachable checks in get_physical_address
- Use g_assert_not_reached for unreachable type in raise_mmu_exception
- Return exception instead of aborting for misaligned fetches
- Move exception defines from cpu.h to cpu_bits.h
- Remove redundant breakpoint control definitions from cpu_bits.h
- Implement riscv_cpu_unassigned_access exception handling
- Log and raise exceptions for unimplemented CSRs
- Match Spike HTIF exit behavior - don’t print TEST-PASSED
- Make frm,fflags,fcsr writes trap when mstatus.FS is clear
- Use g_assert_not_reached for unreachable invalid mode
- Make hret,uret,dret generate illegal instructions
- Move riscv_cpu_dump_state and int/fpr regnames to cpu.c
- Lift interrupt flag and mask into constants in cpu_bits.h
- Change trap debugging to use qemu_log_mask LOG_TRACE 
- Change CSR debugging to use qemu_log_mask LOG_TRACE
- Change PMP debugging to use qemu_log_mask LOG_TRACE
- Remove commented code from pmp.c
- Change CpuInfoRISCV qapi schema docs to Since 2.12
- Change RV feature macro to use target_ulong cast
- Remove riscv_feature and instead use misa extension flags
- Make riscv_flush_icache_syscall a no-op
- Undo checkpatch whitespace fixes in unrelated linux-user code
- Remove redudant constants and tidy up cpu_bits.h
- Make helper_fence_i a no-op
- Move include "exec/cpu-all" to end of cpu.h
- Rename set_privilege to riscv_set_mode
- Move redundant forward declaration for cpu_riscv_translate_address
- Remove TCGV_UNUSED from riscv_translate_init
- Add comment to pmp.c stating the code is untested and currently unused
- Use ctz to simplify decoding of PMP NAPOT address ranges
- Change pmp_is_in_range to use than equal for end addresses
- Fix off by one error in pmp_update_rule
- Rearrange PMP_DEBUG so that formatting is compile-time checked
- Rearrange trap debugging so that formatting is compile-time checked
- Rearrange PLIC debugging so that formatting is compile-time checked
- Use qemu_log/qemu_log_mask for HTIF logging and debugging
- Move exception and interrupt names into cpu.c
- Add Palmer Dabbelt as a RISC-V Maintainer
- Rebase against current qemu master branch

v1

- initial version based on forward port from riscv-qemu repository

*** Background ***

"RISC-V is an open, free ISA enabling a new era of processor innovation
through open standard collaboration. Born in academia and research,
RISC-V ISA delivers a new level of free, extensible software and
hardware freedom on architecture, paving the way for the next 50 years
of computing design and innovation."

The QEMU RISC-V port has been developed and maintained out-of-tree for
several years by Sagar Karandikar and Bastian Koppelmann. The RISC-V
Privileged specification has evolved substantially over this period but
has recently been solidifying. The RISC-V Base ISA has been frozon for
some time and the Privileged ISA, GCC toolchain and Linux ABI are now
quite stable. I have recently joined Sagar and Bastian as a RISC-V QEMU
Maintainer and hope to support upstreaming the port. 

There are multiple vendors taping out, preparing t

[Qemu-devel] [PATCH v2 05/21] RISC-V CPU Helpers

2018-01-10 Thread Michael Clark
Privileged control and status register helpers and page fault handling.

Signed-off-by: Michael Clark 
---
 target/riscv/helper.c| 499 ++
 target/riscv/helper.h|  78 ++
 target/riscv/op_helper.c | 682 +++
 3 files changed, 1259 insertions(+)
 create mode 100644 target/riscv/helper.c
 create mode 100644 target/riscv/helper.h
 create mode 100644 target/riscv/op_helper.c

diff --git a/target/riscv/helper.c b/target/riscv/helper.c
new file mode 100644
index 000..ff3f19a
--- /dev/null
+++ b/target/riscv/helper.c
@@ -0,0 +1,499 @@
+/*
+ *  RISC-V emulation helpers for qemu.
+ *
+ *  Author: Sagar Karandikar, sag...@eecs.berkeley.edu
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see .
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+#include "cpu.h"
+#include "exec/exec-all.h"
+
+#define RISCV_DEBUG_INTERRUPT 0
+
+int riscv_cpu_mmu_index(CPURISCVState *env, bool ifetch)
+{
+#ifdef CONFIG_USER_ONLY
+return 0;
+#else
+target_ulong mode = env->priv;
+if (!ifetch) {
+if (get_field(env->mstatus, MSTATUS_MPRV)) {
+mode = get_field(env->mstatus, MSTATUS_MPP);
+}
+}
+if (env->priv_ver >= PRIV_VERSION_1_10_0) {
+if (get_field(env->satp, SATP_MODE) == VM_1_10_MBARE) {
+mode = PRV_M;
+}
+} else {
+if (get_field(env->mstatus, MSTATUS_VM) == VM_1_09_MBARE) {
+mode = PRV_M;
+}
+}
+return mode;
+#endif
+}
+
+#ifndef CONFIG_USER_ONLY
+/*
+ * Return RISC-V IRQ number if an interrupt should be taken, else -1.
+ * Used in cpu-exec.c
+ *
+ * Adapted from Spike's processor_t::take_interrupt()
+ */
+static int riscv_cpu_hw_interrupts_pending(CPURISCVState *env)
+{
+target_ulong pending_interrupts = env->mip & env->mie;
+
+target_ulong mie = get_field(env->mstatus, MSTATUS_MIE);
+target_ulong m_enabled = env->priv < PRV_M || (env->priv == PRV_M && mie);
+target_ulong enabled_interrupts = pending_interrupts &
+  ~env->mideleg & -m_enabled;
+
+target_ulong sie = get_field(env->mstatus, MSTATUS_SIE);
+target_ulong s_enabled = env->priv < PRV_S || (env->priv == PRV_S && sie);
+enabled_interrupts |= pending_interrupts & env->mideleg &
+  -s_enabled;
+
+if (enabled_interrupts) {
+target_ulong counted = ctz64(enabled_interrupts); /* since non-zero */
+if (counted == IRQ_X_HOST) {
+/* we're handing it to the cpu now, so get rid of the qemu irq */
+qemu_irq_lower(HTIF_IRQ);
+} else if (counted == IRQ_M_TIMER) {
+/* we're handing it to the cpu now, so get rid of the qemu irq */
+qemu_irq_lower(MTIP_IRQ);
+} else if (counted == IRQ_S_TIMER || counted == IRQ_H_TIMER) {
+/* don't lower irq here */
+}
+return counted;
+} else {
+return EXCP_NONE; /* indicates no pending interrupt */
+}
+}
+#endif
+
+bool riscv_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
+{
+#if !defined(CONFIG_USER_ONLY)
+if (interrupt_request & CPU_INTERRUPT_HARD) {
+RISCVCPU *cpu = RISCV_CPU(cs);
+CPURISCVState *env = &cpu->env;
+int interruptno = riscv_cpu_hw_interrupts_pending(env);
+if (interruptno + 1) {
+cs->exception_index = RISCV_EXCP_INT_FLAG | interruptno;
+riscv_cpu_do_interrupt(cs);
+return true;
+}
+}
+#endif
+return false;
+}
+
+#if !defined(CONFIG_USER_ONLY)
+
+/* get_physical_address - get the physical address for this virtual address
+ *
+ * Do a page table walk to obtain the physical address corresponding to a
+ * virtual address. Returns 0 if the translation was successful
+ *
+ * Adapted from Spike's mmu_t::translate and mmu_t::walk
+ *
+ */
+static int get_physical_address(CPURISCVState *env, hwaddr *physical,
+int *prot, target_ulong address,
+int access_type, int mmu_idx)
+{
+/* NOTE: the env->pc value visible here will not be
+ * correct, but the value visible to the exception handler
+ * (riscv_cpu_do_interrupt) is correct */
+
+const int mode = mmu_idx;
+
+*prot = 0;
+CPUState *cs = CPU(riscv_env_get_cpu(env));
+
+if (mode 

[Qemu-devel] [PATCH v2 06/21] RISC-V FPU Support

2018-01-10 Thread Michael Clark
Helper routines for FPU instructions and NaN definitions.

Signed-off-by: Michael Clark 
---
 fpu/softfloat-specialize.h |   7 +-
 target/riscv/fpu_helper.c  | 591 +
 2 files changed, 595 insertions(+), 3 deletions(-)
 create mode 100644 target/riscv/fpu_helper.c

diff --git a/fpu/softfloat-specialize.h b/fpu/softfloat-specialize.h
index de2c5d5..49ee578 100644
--- a/fpu/softfloat-specialize.h
+++ b/fpu/softfloat-specialize.h
@@ -114,7 +114,8 @@ float32 float32_default_nan(float_status *status)
 #if defined(TARGET_SPARC) || defined(TARGET_M68K)
 return const_float32(0x7FFF);
 #elif defined(TARGET_PPC) || defined(TARGET_ARM) || defined(TARGET_ALPHA) || \
-  defined(TARGET_XTENSA) || defined(TARGET_S390X) || 
defined(TARGET_TRICORE)
+  defined(TARGET_XTENSA) || defined(TARGET_S390X) || \
+  defined(TARGET_TRICORE) || defined(TARGET_RISCV)
 return const_float32(0x7FC0);
 #elif defined(TARGET_HPPA)
 return const_float32(0x7FA0);
@@ -139,7 +140,7 @@ float64 float64_default_nan(float_status *status)
 #if defined(TARGET_SPARC) || defined(TARGET_M68K)
 return const_float64(LIT64(0x7FFF));
 #elif defined(TARGET_PPC) || defined(TARGET_ARM) || defined(TARGET_ALPHA) || \
-  defined(TARGET_S390X)
+  defined(TARGET_S390X) || defined(TARGET_RISCV)
 return const_float64(LIT64(0x7FF8));
 #elif defined(TARGET_HPPA)
 return const_float64(LIT64(0x7FF4));
@@ -189,7 +190,7 @@ float128 float128_default_nan(float_status *status)
 r.high = LIT64(0x7FFF7FFF);
 } else {
 r.low = LIT64(0x);
-#if defined(TARGET_S390X) || defined(TARGET_PPC)
+#if defined(TARGET_S390X) || defined(TARGET_PPC) || defined(TARGET_RISCV)
 r.high = LIT64(0x7FFF8000);
 #else
 r.high = LIT64(0x8000);
diff --git a/target/riscv/fpu_helper.c b/target/riscv/fpu_helper.c
new file mode 100644
index 000..ada985f
--- /dev/null
+++ b/target/riscv/fpu_helper.c
@@ -0,0 +1,591 @@
+/*
+ * RISC-V FPU Emulation Helpers for QEMU.
+ *
+ * Author: Sagar Karandikar, sag...@eecs.berkeley.edu
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see .
+ */
+
+#include "qemu/osdep.h"
+#include 
+#include "cpu.h"
+#include "qemu/host-utils.h"
+#include "exec/helper-proto.h"
+
+/* convert RISC-V rounding mode to IEEE library numbers */
+unsigned int ieee_rm[] = {
+float_round_nearest_even,
+float_round_to_zero,
+float_round_down,
+float_round_up,
+float_round_ties_away
+};
+
+/* obtain rm value to use in computation
+ * as the last step, convert rm codes to what the softfloat library expects
+ * Adapted from Spike's decode.h:RM
+ */
+#define RM ({ \
+if (rm == 7) {\
+rm = env->frm;   \
+} \
+if (rm > 4) { \
+helper_raise_exception(env, RISCV_EXCP_ILLEGAL_INST); \
+} \
+ieee_rm[rm]; })
+
+#ifndef CONFIG_USER_ONLY
+#define require_fp if (!(env->mstatus & MSTATUS_FS)) { \
+helper_raise_exception(env, RISCV_EXCP_ILLEGAL_INST); \
+}
+#else
+#define require_fp /* nop */
+#endif
+
+/* convert softfloat library flag numbers to RISC-V */
+unsigned int softfloat_flags_to_riscv(unsigned int flags)
+{
+int rv_flags = 0;
+rv_flags |= (flags & float_flag_inexact) ? 1 : 0;
+rv_flags |= (flags & float_flag_underflow) ? 2 : 0;
+rv_flags |= (flags & float_flag_overflow) ? 4 : 0;
+rv_flags |= (flags & float_flag_divbyzero) ? 8 : 0;
+rv_flags |= (flags & float_flag_invalid) ? 16 : 0;
+return rv_flags;
+}
+
+/* adapted from Spike's decode.h:set_fp_exceptions */
+#define set_fp_exceptions() do { \
+env->fflags |= softfloat_flags_to_riscv(get_float_exception_flags(\
+&env->fp_status)); \
+set_float_exception_flags(0, &env->fp_status); \
+} while (0)
+
+uint64_t helper_fmadd_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2,
+uint64_t frs3, uint64_t rm)
+{
+require_fp;
+set_float_rounding_mode(RM, &env->fp_status);
+frs1 = float32_muladd(frs1, frs2, frs3, 0, &env->fp_status);
+

[Qemu-devel] [PATCH v2 01/21] RISC-V Maintainers

2018-01-10 Thread Michael Clark
Add Michael Clark, Palmer Dabbelt, Sagar Karandikar and Bastian
Koppelmann as RISC-V Maintainers.

Signed-off-by: Michael Clark 
---
 MAINTAINERS | 11 +++
 1 file changed, 11 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index bc2d3a4..17af5b4 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -209,6 +209,17 @@ F: hw/ppc/
 F: include/hw/ppc/
 F: disas/ppc.c
 
+RISC-V
+M: Michael Clark 
+M: Palmer Dabbelt 
+M: Sagar Karandikar 
+M: Bastian Koppelmann 
+S: Maintained
+F: target/riscv/
+F: hw/riscv/
+F: include/hw/riscv/
+F: disas/riscv.c
+
 S390
 M: Richard Henderson 
 M: Alexander Graf 
-- 
2.7.0




[Qemu-devel] [PATCH v2 02/21] RISC-V ELF Machine Definition

2018-01-10 Thread Michael Clark
Define RISC-V ELF machine EM_RISCV 243

Reviewed-by: Richard Henderson 
Signed-off-by: Michael Clark 
---
 include/elf.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/include/elf.h b/include/elf.h
index e8a515c..8e457fc 100644
--- a/include/elf.h
+++ b/include/elf.h
@@ -112,6 +112,8 @@ typedef int64_t  Elf64_Sxword;
 
 #define EM_UNICORE32110 /* UniCore32 */
 
+#define EM_RISCV243 /* RISC-V */
+
 /*
  * This is an interim value that we will use until the committee comes
  * up with a final number.
-- 
2.7.0




[Qemu-devel] [PATCH v2 2/6] nbd/server: refactor negotiation functions parameters

2018-01-10 Thread Eric Blake
From: Vladimir Sementsov-Ogievskiy 

Instead of passing currently negotiating option and its length to
many of negotiation functions let's just store them on NBDClient
struct to be state-variables of negotiation phase.

This unifies semantics of negotiation functions and allows
tracking changes of remaining option length in future patches.

Signed-off-by: Vladimir Sementsov-Ogievskiy 
Reviewed-by: Eric Blake 
Message-Id: <20171122101958.17065-2-vsement...@virtuozzo.com>
[eblake: rebase, commit message tweak, assert !optlen after
negotiation completes]
Signed-off-by: Eric Blake 
---
 nbd/server.c | 168 +--
 1 file changed, 84 insertions(+), 84 deletions(-)

diff --git a/nbd/server.c b/nbd/server.c
index d3b457c337..08a24b56f4 100644
--- a/nbd/server.c
+++ b/nbd/server.c
@@ -102,9 +102,11 @@ struct NBDClient {
 bool closing;

 bool structured_reply;
-};

-/* That's all folks */
+uint32_t opt; /* Current option being negotiated */
+uint32_t optlen; /* remaining length of data in ioc for the option being
+negotiated now */
+};

 static void nbd_client_receive_next_request(NBDClient *client);

@@ -137,10 +139,12 @@ static void nbd_client_receive_next_request(NBDClient 
*client);

 /* Send a reply header, including length, but no payload.
  * Return -errno on error, 0 on success. */
-static int nbd_negotiate_send_rep_len(QIOChannel *ioc, uint32_t type,
-  uint32_t opt, uint32_t len, Error **errp)
+static int nbd_negotiate_send_rep_len(NBDClient *client, uint32_t type,
+  uint32_t len, Error **errp)
 {
 uint64_t magic;
+QIOChannel *ioc = client->ioc;
+uint32_t opt = client->opt;

 trace_nbd_negotiate_send_rep_len(opt, nbd_opt_lookup(opt),
  type, nbd_rep_lookup(type), len);
@@ -174,17 +178,17 @@ static int nbd_negotiate_send_rep_len(QIOChannel *ioc, 
uint32_t type,

 /* Send a reply header with default 0 length.
  * Return -errno on error, 0 on success. */
-static int nbd_negotiate_send_rep(QIOChannel *ioc, uint32_t type, uint32_t opt,
+static int nbd_negotiate_send_rep(NBDClient *client, uint32_t type,
   Error **errp)
 {
-return nbd_negotiate_send_rep_len(ioc, type, opt, 0, errp);
+return nbd_negotiate_send_rep_len(client, type, 0, errp);
 }

 /* Send an error reply.
  * Return -errno on error, 0 on success. */
-static int GCC_FMT_ATTR(5, 6)
-nbd_negotiate_send_rep_err(QIOChannel *ioc, uint32_t type,
-   uint32_t opt, Error **errp, const char *fmt, ...)
+static int GCC_FMT_ATTR(4, 5)
+nbd_negotiate_send_rep_err(NBDClient *client, uint32_t type,
+   Error **errp, const char *fmt, ...)
 {
 va_list va;
 char *msg;
@@ -197,11 +201,11 @@ nbd_negotiate_send_rep_err(QIOChannel *ioc, uint32_t type,
 len = strlen(msg);
 assert(len < 4096);
 trace_nbd_negotiate_send_rep_err(msg);
-ret = nbd_negotiate_send_rep_len(ioc, type, opt, len, errp);
+ret = nbd_negotiate_send_rep_len(client, type, len, errp);
 if (ret < 0) {
 goto out;
 }
-if (nbd_write(ioc, msg, len, errp) < 0) {
+if (nbd_write(client->ioc, msg, len, errp) < 0) {
 error_prepend(errp, "write failed (error message): ");
 ret = -EIO;
 } else {
@@ -215,21 +219,21 @@ out:

 /* Send a single NBD_REP_SERVER reply to NBD_OPT_LIST, including payload.
  * Return -errno on error, 0 on success. */
-static int nbd_negotiate_send_rep_list(QIOChannel *ioc, NBDExport *exp,
+static int nbd_negotiate_send_rep_list(NBDClient *client, NBDExport *exp,
Error **errp)
 {
 size_t name_len, desc_len;
 uint32_t len;
 const char *name = exp->name ? exp->name : "";
 const char *desc = exp->description ? exp->description : "";
+QIOChannel *ioc = client->ioc;
 int ret;

 trace_nbd_negotiate_send_rep_list(name, desc);
 name_len = strlen(name);
 desc_len = strlen(desc);
 len = name_len + desc_len + sizeof(len);
-ret = nbd_negotiate_send_rep_len(ioc, NBD_REP_SERVER, NBD_OPT_LIST, len,
- errp);
+ret = nbd_negotiate_send_rep_len(client, NBD_REP_SERVER, len, errp);
 if (ret < 0) {
 return ret;
 }
@@ -258,20 +262,21 @@ static int nbd_negotiate_send_rep_list(QIOChannel *ioc, 
NBDExport *exp,
 static int nbd_negotiate_handle_list(NBDClient *client, Error **errp)
 {
 NBDExport *exp;
+assert(client->opt == NBD_OPT_LIST);

 /* For each export, send a NBD_REP_SERVER reply. */
 QTAILQ_FOREACH(exp, &exports, next) {
-if (nbd_negotiate_send_rep_list(client->ioc, exp, errp)) {
+if (nbd_negotiate_send_rep_list(client, exp, errp)) {
 return -EINVAL;
 }
 }
 /* Finish with a NBD_REP_ACK. */
-return nbd_negotiate_send_rep(client->ioc, NBD_REP

[Qemu-devel] [PATCH v2 6/6] nbd/server: structurize option reply sending

2018-01-10 Thread Eric Blake
From: Vladimir Sementsov-Ogievskiy 

Signed-off-by: Vladimir Sementsov-Ogievskiy 
Reviewed-by: Eric Blake 
Message-Id: <20171122101958.17065-6-vsement...@virtuozzo.com>
Signed-off-by: Eric Blake 
---
 nbd/server.c | 40 +---
 1 file changed, 13 insertions(+), 27 deletions(-)

diff --git a/nbd/server.c b/nbd/server.c
index ec8c3be019..9019ad28f4 100644
--- a/nbd/server.c
+++ b/nbd/server.c
@@ -137,43 +137,29 @@ static void nbd_client_receive_next_request(NBDClient 
*client);

 */

+static inline void set_be_option_rep(NBDOptionReply *rep, uint32_t option,
+ uint32_t type, uint32_t length)
+{
+stq_be_p(&rep->magic, NBD_REP_MAGIC);
+stl_be_p(&rep->option, option);
+stl_be_p(&rep->type, type);
+stl_be_p(&rep->length, length);
+}
+
 /* Send a reply header, including length, but no payload.
  * Return -errno on error, 0 on success. */
 static int nbd_negotiate_send_rep_len(NBDClient *client, uint32_t type,
   uint32_t len, Error **errp)
 {
-uint64_t magic;
-QIOChannel *ioc = client->ioc;
-uint32_t opt = client->opt;
+NBDOptionReply rep;

-trace_nbd_negotiate_send_rep_len(opt, nbd_opt_lookup(opt),
+trace_nbd_negotiate_send_rep_len(client->opt, nbd_opt_lookup(client->opt),
  type, nbd_rep_lookup(type), len);

 assert(len < NBD_MAX_BUFFER_SIZE);
-magic = cpu_to_be64(NBD_REP_MAGIC);
-if (nbd_write(ioc, &magic, sizeof(magic), errp) < 0) {
-error_prepend(errp, "write failed (rep magic): ");
-return -EINVAL;
-}

-opt = cpu_to_be32(opt);
-if (nbd_write(ioc, &opt, sizeof(opt), errp) < 0) {
-error_prepend(errp, "write failed (rep opt): ");
-return -EINVAL;
-}
-
-type = cpu_to_be32(type);
-if (nbd_write(ioc, &type, sizeof(type), errp) < 0) {
-error_prepend(errp, "write failed (rep type): ");
-return -EINVAL;
-}
-
-len = cpu_to_be32(len);
-if (nbd_write(ioc, &len, sizeof(len), errp) < 0) {
-error_prepend(errp, "write failed (rep data length): ");
-return -EINVAL;
-}
-return 0;
+set_be_option_rep(&rep, client->opt, type, len);
+return nbd_write(client->ioc, &rep, sizeof(rep), errp);
 }

 /* Send a reply header with default 0 length.
-- 
2.14.3




[Qemu-devel] [PATCH v2 3/6] nbd/server: Better error for NBD_OPT_EXPORT_NAME failure

2018-01-10 Thread Eric Blake
When a client abruptly disconnects before we've finished reading
the name sent with NBD_OPT_EXPORT_NAME, we are better off logging
the failure as EIO (we can't communicate with the client), rather
than EINVAL (the client sent bogus data).

Signed-off-by: Eric Blake 
---
 nbd/server.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/nbd/server.c b/nbd/server.c
index 08a24b56f4..9943a911c3 100644
--- a/nbd/server.c
+++ b/nbd/server.c
@@ -299,7 +299,7 @@ static int nbd_negotiate_handle_export_name(NBDClient 
*client,
 }
 if (nbd_read(client->ioc, name, client->optlen, errp) < 0) {
 error_prepend(errp, "read failed: ");
-return -EINVAL;
+return -EIO;
 }
 name[client->optlen] = '\0';
 client->optlen = 0;
-- 
2.14.3




[Qemu-devel] [PATCH v2 5/6] nbd/server: Add helper functions for parsing option payload

2018-01-10 Thread Eric Blake
Rather than making every callsite perform length sanity checks
and error reporting, add the helper functions nbd_opt_read()
and nbd_opt_drop() that use the length stored in the client
struct; also add an assertion that optlen is reduced to zero
after each option is handled.

Note that the call in nbd_negotiate_handle_export_name() does
not use the new helper (in part because the server cannot
reply to NBD_OPT_EXPORT_NAME - it either succeeds or the
connection drops).

Based on patches by Vladimir Sementsov-Ogievskiy.

Signed-off-by: Eric Blake 
---
 nbd/server.c | 123 ++-
 1 file changed, 63 insertions(+), 60 deletions(-)

diff --git a/nbd/server.c b/nbd/server.c
index d23bc2918a..ec8c3be019 100644
--- a/nbd/server.c
+++ b/nbd/server.c
@@ -229,6 +229,41 @@ nbd_negotiate_send_rep_err(NBDClient *client, uint32_t 
type,
 return ret;
 }

+/* Drop remainder of the current option, after sending a reply with
+ * the given error type and message. Return -errno on read or write
+ * failure; or 0 if connection is still live. */
+static int GCC_FMT_ATTR(4, 5)
+nbd_opt_drop(NBDClient *client, uint32_t type, Error **errp,
+ const char *fmt, ...)
+{
+int ret = nbd_drop(client->ioc, client->optlen, errp);
+
+client->optlen = 0;
+if (!ret) {
+va_list va;
+
+va_start(va, fmt);
+ret = nbd_negotiate_send_rep_verr(client, type, errp, fmt, va);
+va_end(va);
+}
+return ret;
+}
+
+/* Read size bytes from the unparsed payload of the current option.
+ * Return -errno on I/O error, 0 if option was completely handled by
+ * sending a reply about inconsistent lengths, or 1 on success. */
+static int nbd_opt_read(NBDClient *client, void *buffer, size_t size,
+Error **errp)
+{
+if (size > client->optlen) {
+return nbd_opt_drop(client, NBD_REP_ERR_INVALID, errp,
+"Inconsistent lengths in option %s",
+nbd_opt_lookup(client->opt));
+}
+client->optlen -= size;
+return qio_channel_read_all(client->ioc, buffer, size, errp) < 0 ? -EIO : 
1;
+}
+
 /* Send a single NBD_REP_SERVER reply to NBD_OPT_LIST, including payload.
  * Return -errno on error, 0 on success. */
 static int nbd_negotiate_send_rep_list(NBDClient *client, NBDExport *exp,
@@ -378,14 +413,11 @@ static int nbd_reject_length(NBDClient *client, bool 
fatal, Error **errp)
 int ret;

 assert(client->optlen);
-if (nbd_drop(client->ioc, client->optlen, errp) < 0) {
-return -EIO;
-}
-ret = nbd_negotiate_send_rep_err(client, NBD_REP_ERR_INVALID, errp,
- "option '%s' should have zero length",
- nbd_opt_lookup(client->opt));
+ret = nbd_opt_drop(client, NBD_REP_ERR_INVALID, errp,
+   "option '%s' has unexpected length",
+   nbd_opt_lookup(client->opt));
 if (fatal && !ret) {
-error_setg(errp, "option '%s' should have zero length",
+error_setg(errp, "option '%s' has unexpected length",
nbd_opt_lookup(client->opt));
 return -EINVAL;
 }
@@ -408,7 +440,6 @@ static int nbd_negotiate_handle_info(NBDClient *client, 
uint16_t myflags,
 bool blocksize = false;
 uint32_t sizes[3];
 char buf[sizeof(uint64_t) + sizeof(uint16_t)];
-const char *msg;

 /* Client sends:
 4 bytes: L, name length (can be 0)
@@ -416,48 +447,34 @@ static int nbd_negotiate_handle_info(NBDClient *client, 
uint16_t myflags,
 2 bytes: N, number of requests (can be 0)
 N * 2 bytes: N requests
 */
-if (client->optlen < sizeof(namelen) + sizeof(requests)) {
-msg = "overall request too short";
-goto invalid;
-}
-if (nbd_read(client->ioc, &namelen, sizeof(namelen), errp) < 0) {
-return -EIO;
+rc = nbd_opt_read(client, &namelen, sizeof(namelen), errp);
+if (rc <= 0) {
+return rc;
 }
 be32_to_cpus(&namelen);
-client->optlen -= sizeof(namelen);
-if (namelen > client->optlen - sizeof(requests) ||
-(client->optlen - namelen) % 2)
-{
-msg = "name length is incorrect";
-goto invalid;
-}
 if (namelen >= sizeof(name)) {
-msg = "name too long for qemu";
-goto invalid;
+return nbd_opt_drop(client, NBD_REP_ERR_INVALID, errp,
+"name too long for qemu");
 }
-if (nbd_read(client->ioc, name, namelen, errp) < 0) {
-return -EIO;
+rc = nbd_opt_read(client, name, namelen, errp);
+if (rc <= 0) {
+return rc;
 }
 name[namelen] = '\0';
-client->optlen -= namelen;
 trace_nbd_negotiate_handle_export_name_request(name);

-if (nbd_read(client->ioc, &requests, sizeof(requests), errp) < 0) {
-return -EIO;
+rc = nbd_opt_read(client, &requests, sizeof(requests), errp);
+if (rc <= 0) {

[Qemu-devel] [PATCH v2 1/6] nbd/server: Hoist nbd_reject_length() earlier

2018-01-10 Thread Eric Blake
No semantic change, but will make it easier for an upcoming patch
to refactor code without having to add forward declarations.

Signed-off-by: Eric Blake 
---
 nbd/server.c | 56 
 1 file changed, 28 insertions(+), 28 deletions(-)

diff --git a/nbd/server.c b/nbd/server.c
index 6cf2eeb2c1..d3b457c337 100644
--- a/nbd/server.c
+++ b/nbd/server.c
@@ -348,6 +348,34 @@ static int nbd_negotiate_send_info(NBDClient *client, 
uint32_t opt,
 return 0;
 }

+/* nbd_reject_length: Handle any unexpected payload.
+ * @fatal requests that we quit talking to the client, even if we are able
+ * to successfully send an error to the guest.
+ * Return:
+ * -errno  transmission error occurred or @fatal was requested, errp is set
+ * 0   error message successfully sent to client, errp is not set
+ */
+static int nbd_reject_length(NBDClient *client, uint32_t length,
+ uint32_t option, bool fatal, Error **errp)
+{
+int ret;
+
+assert(length);
+if (nbd_drop(client->ioc, length, errp) < 0) {
+return -EIO;
+}
+ret = nbd_negotiate_send_rep_err(client->ioc, NBD_REP_ERR_INVALID,
+ option, errp,
+ "option '%s' should have zero length",
+ nbd_opt_lookup(option));
+if (fatal && !ret) {
+error_setg(errp, "option '%s' should have zero length",
+   nbd_opt_lookup(option));
+return -EINVAL;
+}
+return ret;
+}
+
 /* Handle NBD_OPT_INFO and NBD_OPT_GO.
  * Return -errno on error, 0 if ready for next option, and 1 to move
  * into transmission phase.  */
@@ -570,34 +598,6 @@ static QIOChannel *nbd_negotiate_handle_starttls(NBDClient 
*client,
 return QIO_CHANNEL(tioc);
 }

-/* nbd_reject_length: Handle any unexpected payload.
- * @fatal requests that we quit talking to the client, even if we are able
- * to successfully send an error to the guest.
- * Return:
- * -errno  transmission error occurred or @fatal was requested, errp is set
- * 0   error message successfully sent to client, errp is not set
- */
-static int nbd_reject_length(NBDClient *client, uint32_t length,
- uint32_t option, bool fatal, Error **errp)
-{
-int ret;
-
-assert(length);
-if (nbd_drop(client->ioc, length, errp) < 0) {
-return -EIO;
-}
-ret = nbd_negotiate_send_rep_err(client->ioc, NBD_REP_ERR_INVALID,
- option, errp,
- "option '%s' should have zero length",
- nbd_opt_lookup(option));
-if (fatal && !ret) {
-error_setg(errp, "option '%s' should have zero length",
-   nbd_opt_lookup(option));
-return -EINVAL;
-}
-return ret;
-}
-
 /* nbd_negotiate_options
  * Process all NBD_OPT_* client option commands, during fixed newstyle
  * negotiation.
-- 
2.14.3




[Qemu-devel] [PATCH v2 4/6] nbd/server: Add va_list form of nbd_negotiate_send_rep_err()

2018-01-10 Thread Eric Blake
This will be useful for the next patch.

Based on a patch by Vladimir Sementsov-Ogievskiy

Signed-off-by: Eric Blake 
---
 nbd/server.c | 24 ++--
 1 file changed, 18 insertions(+), 6 deletions(-)

diff --git a/nbd/server.c b/nbd/server.c
index 9943a911c3..d23bc2918a 100644
--- a/nbd/server.c
+++ b/nbd/server.c
@@ -186,18 +186,15 @@ static int nbd_negotiate_send_rep(NBDClient *client, 
uint32_t type,

 /* Send an error reply.
  * Return -errno on error, 0 on success. */
-static int GCC_FMT_ATTR(4, 5)
-nbd_negotiate_send_rep_err(NBDClient *client, uint32_t type,
-   Error **errp, const char *fmt, ...)
+static int GCC_FMT_ATTR(4, 0)
+nbd_negotiate_send_rep_verr(NBDClient *client, uint32_t type,
+Error **errp, const char *fmt, va_list va)
 {
-va_list va;
 char *msg;
 int ret;
 size_t len;

-va_start(va, fmt);
 msg = g_strdup_vprintf(fmt, va);
-va_end(va);
 len = strlen(msg);
 assert(len < 4096);
 trace_nbd_negotiate_send_rep_err(msg);
@@ -217,6 +214,21 @@ out:
 return ret;
 }

+/* Send an error reply.
+ * Return -errno on error, 0 on success. */
+static int GCC_FMT_ATTR(4, 5)
+nbd_negotiate_send_rep_err(NBDClient *client, uint32_t type,
+   Error **errp, const char *fmt, ...)
+{
+va_list va;
+int ret;
+
+va_start(va, fmt);
+ret = nbd_negotiate_send_rep_verr(client, type, errp, fmt, va);
+va_end(va);
+return ret;
+}
+
 /* Send a single NBD_REP_SERVER reply to NBD_OPT_LIST, including payload.
  * Return -errno on error, 0 on success. */
 static int nbd_negotiate_send_rep_list(NBDClient *client, NBDExport *exp,
-- 
2.14.3




[Qemu-devel] [PATCH v2 0/6] NBD server refactoring before BLOCK_STATUS

2018-01-10 Thread Eric Blake
This is my promised revision of Vladimir's v1 posted here:
https://lists.gnu.org/archive/html/qemu-devel/2017-11/msg04119.html

Sorry for my delay; it was due in part to an embargo while dealing
with 2 bounds-check CVEs in the NBD code that I discovered while
reviewing his v1 (fixed in time for 2.11), then waiting for the
2.12 tree to reopen, coupled with my holiday break.  I'm hoping
we can get actual BLOCK_STATUS code reviewed and applied much
faster than this preliminary series has gone.

Based-on: <20180110225944.17920-1-ebl...@redhat.com>

Since v1:
- original patch 4/5 now in a pull request
- replace original 2-3/5 with a single patch, giving more useful
semantics to nbd_opt_drop/nbd_opt_read
- add a couple of other easy fixes while touching the file

Eric Blake (4):
  nbd/server: Hoist nbd_reject_length() earlier
  nbd/server: Better error for NBD_OPT_EXPORT_NAME failure
  nbd/server: Add va_list form of nbd_negotiate_send_rep_err()
  nbd/server: Add helper functions for parsing option payload

Vladimir Sementsov-Ogievskiy (2):
  nbd/server: refactor negotiation functions parameters
  nbd/server: structurize option reply sending

 nbd/server.c | 341 ++-
 1 file changed, 171 insertions(+), 170 deletions(-)

-- 
2.14.3




[Qemu-devel] [PULL 2/2] nbd: rename nbd_option and nbd_opt_reply

2018-01-10 Thread Eric Blake
From: Vladimir Sementsov-Ogievskiy 

Rename nbd_option and nbd_opt_reply to NBDOption and NBDOptionReply
to correspond to Qemu coding style and other structures here.

Signed-off-by: Vladimir Sementsov-Ogievskiy 
Reviewed-by: Eric Blake 
Message-Id: <20171122101958.17065-5-vsement...@virtuozzo.com>
Signed-off-by: Eric Blake 
---
 include/block/nbd.h |  8 
 nbd/client.c| 12 ++--
 2 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/include/block/nbd.h b/include/block/nbd.h
index 113c707a5e..978e443366 100644
--- a/include/block/nbd.h
+++ b/include/block/nbd.h
@@ -28,20 +28,20 @@

 /* Handshake phase structs - this struct is passed on the wire */

-struct nbd_option {
+struct NBDOption {
 uint64_t magic; /* NBD_OPTS_MAGIC */
 uint32_t option; /* NBD_OPT_* */
 uint32_t length;
 } QEMU_PACKED;
-typedef struct nbd_option nbd_option;
+typedef struct NBDOption NBDOption;

-struct nbd_opt_reply {
+struct NBDOptionReply {
 uint64_t magic; /* NBD_REP_MAGIC */
 uint32_t option; /* NBD_OPT_* */
 uint32_t type; /* NBD_REP_* */
 uint32_t length;
 } QEMU_PACKED;
-typedef struct nbd_opt_reply nbd_opt_reply;
+typedef struct NBDOptionReply NBDOptionReply;

 /* Transmission phase structs
  *
diff --git a/nbd/client.c b/nbd/client.c
index eea236ca06..89f80f9590 100644
--- a/nbd/client.c
+++ b/nbd/client.c
@@ -66,7 +66,7 @@ static int nbd_send_option_request(QIOChannel *ioc, uint32_t 
opt,
uint32_t len, const char *data,
Error **errp)
 {
-nbd_option req;
+NBDOption req;
 QEMU_BUILD_BUG_ON(sizeof(req) != 16);

 if (len == -1) {
@@ -109,7 +109,7 @@ static void nbd_send_opt_abort(QIOChannel *ioc)
  * payload. Return 0 if successful, -1 with errp set if it is
  * impossible to continue. */
 static int nbd_receive_option_reply(QIOChannel *ioc, uint32_t opt,
-nbd_opt_reply *reply, Error **errp)
+NBDOptionReply *reply, Error **errp)
 {
 QEMU_BUILD_BUG_ON(sizeof(*reply) != 20);
 if (nbd_read(ioc, reply, sizeof(*reply), errp) < 0) {
@@ -146,7 +146,7 @@ static int nbd_receive_option_reply(QIOChannel *ioc, 
uint32_t opt,
  * can fall back to other approaches), or -1 with errp set for other
  * errors.
  */
-static int nbd_handle_reply_err(QIOChannel *ioc, nbd_opt_reply *reply,
+static int nbd_handle_reply_err(QIOChannel *ioc, NBDOptionReply *reply,
 Error **errp)
 {
 char *msg = NULL;
@@ -239,7 +239,7 @@ static int nbd_handle_reply_err(QIOChannel *ioc, 
nbd_opt_reply *reply,
 static int nbd_receive_list(QIOChannel *ioc, const char *want, bool *match,
 Error **errp)
 {
-nbd_opt_reply reply;
+NBDOptionReply reply;
 uint32_t len;
 uint32_t namelen;
 char name[NBD_MAX_NAME_SIZE + 1];
@@ -325,7 +325,7 @@ static int nbd_receive_list(QIOChannel *ioc, const char 
*want, bool *match,
 static int nbd_opt_go(QIOChannel *ioc, const char *wantname,
   NBDExportInfo *info, Error **errp)
 {
-nbd_opt_reply reply;
+NBDOptionReply reply;
 uint32_t len = strlen(wantname);
 uint16_t type;
 int error;
@@ -517,7 +517,7 @@ static int nbd_receive_query_exports(QIOChannel *ioc,
  */
 static int nbd_request_simple_option(QIOChannel *ioc, int opt, Error **errp)
 {
-nbd_opt_reply reply;
+NBDOptionReply reply;
 int error;

 if (nbd_send_option_request(ioc, opt, 0, NULL, errp) < 0) {
-- 
2.14.3




[Qemu-devel] [PULL 1/2] nbd/server: add additional assert to nbd_export_put

2018-01-10 Thread Eric Blake
From: Vladimir Sementsov-Ogievskiy 

This place is not obvious, nbd_export_close may theoretically reduce
refcount to 0. It may happen if someone calls nbd_export_put on named
export not through nbd_export_set_name when refcount is 1.

Signed-off-by: Vladimir Sementsov-Ogievskiy 
Reviewed-by: Eric Blake 
Reviewed-by: Max Reitz 
Message-Id: <20171207155102.66622-2-vsement...@virtuozzo.com>
Signed-off-by: Eric Blake 
---
 nbd/server.c | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/nbd/server.c b/nbd/server.c
index e443b3cf5c..6cf2eeb2c1 100644
--- a/nbd/server.c
+++ b/nbd/server.c
@@ -1190,6 +1190,12 @@ void nbd_export_put(NBDExport *exp)
 nbd_export_close(exp);
 }

+/* nbd_export_close() may theoretically reduce refcount to 0. It may happen
+ * if someone calls nbd_export_put() on named export not through
+ * nbd_export_set_name() when refcount is 1. So, let's assert that
+ * it is > 0.
+ */
+assert(exp->refcount > 0);
 if (--exp->refcount == 0) {
 assert(exp->name == NULL);
 assert(exp->description == NULL);
-- 
2.14.3




[Qemu-devel] [PULL 0/2] nbd patches for 10 Jan

2018-01-10 Thread Eric Blake
The following changes since commit 3cee4db661ab9c0fce7937b3bbfa188a1845f31f:

  Merge remote-tracking branch 'remotes/ericb/tags/pull-nbd-2018-01-08' into 
staging (2018-01-09 15:22:47 +)

are available in the Git repository at:

  git://repo.or.cz/qemu/ericb.git tags/pull-nbd-2018-01-10

for you to fetch changes up to 420a4e955909788263a33d11600839e93480dfd3:

  nbd: rename nbd_option and nbd_opt_reply (2018-01-10 12:11:23 -0600)

Not much time elapsed since my last pull request, but my last request
was delayed due the holiday break, and I've now got other patches that
will be easier to post if I can do a Based-on: against this pull request,
rather than the larger in-progress series they were extracted from.


nbd patches for 2018-01-10

- Vladimir Sementsov-Ogievskiy: nbd: rename nbd_option and nbd_opt_reply
- Vladimir Sementsov-Ogievskiy: nbd/server: add additional assert to 
nbd_export_put


Vladimir Sementsov-Ogievskiy (2):
  nbd/server: add additional assert to nbd_export_put
  nbd: rename nbd_option and nbd_opt_reply

 include/block/nbd.h |  8 
 nbd/client.c| 12 ++--
 nbd/server.c|  6 ++
 3 files changed, 16 insertions(+), 10 deletions(-)

-- 
2.14.3




[Qemu-devel] [Bug 1175089] Re: Crash why dragon fly 3.4.1

2018-01-10 Thread Thomas Huth
Triaging old bug tickets... can you still reproduce this issue with the
latest version of QEMU? Or could we close this ticket nowadays?

** Changed in: qemu
   Status: New => Incomplete

-- 
You received this bug notification because you are a member of qemu-
devel-ml, which is subscribed to QEMU.
https://bugs.launchpad.net/bugs/1175089

Title:
  Crash why dragon fly 3.4.1

Status in QEMU:
  Incomplete

Bug description:
  Hello, all is here (kernel 3.8, qemu 1.2.2-r3):
  /usr/bin/qemu-system-x86_64 -k fr -alt-grab -m 2048 -vga vmware -net 
nic,vlan=0,model=virtio -net user -rtc base=localtime -smp 4,cores=4,sockets=1 
-boot once=d -cdrom dfly-x86_64-gui-3.4.1_REL.iso 
  KVM internal error. Suberror: 1
  emulation failure
  EAX=0010 EBX=9338 ECX= EDX=
  ESI=17fc EDI=17c8 EBP=000364a0 ESP=17b8
  EIP=9318 EFL=3002 [---] CPL=0 II=0 A20=1 SMM=0 HLT=0
  ES =0010   00c09300
  CS =0018   9b00
  SS =0010   00c09300
  DS =0010   00c09300
  FS =0033 a000  00c0f300
  GS =0033 a000  00c0f300
  LDT=   8200
  TR =0038 5f98 2067 8b00
  GDT= 9590 003f
  IDT= 5e00 0197
  CR0=0010 CR2= CR3= CR4=
  DR0= DR1= DR2= 
DR3= 
  DR6=0ff0 DR7=0400
  EFER=
  Code=00 a3 ea 5d 00 00 66 ea 10 93 18 00 0f 20 c0 fe c8 0f 22 c0  1d 93 
00 00 31 c0 8e d8 8e d0 0f 01 1e dc 95 66 07 66 1f 66 0f a1 66 0f a9 66 61 bc ea

To manage notifications about this bug go to:
https://bugs.launchpad.net/qemu/+bug/1175089/+subscriptions



[Qemu-devel] [Bug 1163474] Re: qemu mount usb permission denied

2018-01-10 Thread Thomas Huth
Triaging old bug tickets ... Sounds like this was rather a problem with
your distro / udev than with qemu. In case you still have the problem,
please report it to the Debian bug tracker first.

** Changed in: qemu
   Status: New => Invalid

-- 
You received this bug notification because you are a member of qemu-
devel-ml, which is subscribed to QEMU.
https://bugs.launchpad.net/bugs/1163474

Title:
  qemu mount usb permission denied

Status in QEMU:
  Invalid

Bug description:
  I use debian with kde and the new Qemu 14.0 . I use this Qemu start
  arguments:

  /usr/bin/qemu-system-x86_64 -monitor stdio -smp 2 -soundhw es1370,ac97
  -k de -enable-kvm -m 4096 -localtime -cdrom /dev/sr0 -hda
  /home/../.aqemu/Windows_7_x64_HDA.img -boot once=d,menu=off -net
  nic,vlan=0 -net user,vlan=0 -usb -usbdevice tablet -device usb-
  host,hostbus=1,hostaddr=2 -device usb-host,hostbus=2,hostaddr=2 -name
  "Windows 7 x64"

  Then I get this error: /dev/bus/usb/000/001: Permission denied

  Some says I must change the permissions /dev/bus/usb to 777 but I
  think that can't be the solution and when I restart the changes are
  lost. I think there is also a problem with the automount in KDE.

  The user user who starts Qemu has also full access to usb device
  (member of the group plugdev)

To manage notifications about this bug go to:
https://bugs.launchpad.net/qemu/+bug/1163474/+subscriptions



  1   2   3   4   >