From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from [140.186.70.92] (port=56748 helo=eggs.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1PztO0-00021I-Hp for qemu-devel@nongnu.org; Wed, 16 Mar 2011 12:15:50 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1PztNy-0000VR-T8 for qemu-devel@nongnu.org; Wed, 16 Mar 2011 12:15:48 -0400 Received: from cantor2.suse.de ([195.135.220.15]:53070 helo=mx2.suse.de) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1PztNy-0000VI-F8 for qemu-devel@nongnu.org; Wed, 16 Mar 2011 12:15:46 -0400 Message-ID: <4D80E231.6040400@suse.de> Date: Wed, 16 Mar 2011 17:15:45 +0100 From: Alexander Graf MIME-Version: 1.0 References: <1300251423-6715-1-git-send-email-david@gibson.dropbear.id.au> <1300251423-6715-24-git-send-email-david@gibson.dropbear.id.au> In-Reply-To: <1300251423-6715-24-git-send-email-david@gibson.dropbear.id.au> Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit Subject: [Qemu-devel] Re: [PATCH 23/26] Implement PAPR CRQ hypercalls List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: David Gibson Cc: paulus@samba.org, qemu-devel@nongnu.org, anton@samba.org On 03/16/2011 05:57 AM, David Gibson wrote: > From: Ben Herrenschmidt > > This patch implements the infrastructure and hypercalls necessary for the > PAPR specified CRQ (Command Request Queue) mechanism. This general > request queueing system is used by many of the PAPR virtual IO devices, > including the virtual scsi adapter. > > Signed-off-by: Ben Herrenschmidt > Signed-off-by: David Gibson > --- > hw/spapr.c | 2 +- > hw/spapr_vio.c | 159 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > hw/spapr_vio.h | 12 ++++ > 3 files changed, 172 insertions(+), 1 deletions(-) > > diff --git a/hw/spapr.c b/hw/spapr.c > index 44cf3cc..cb97a16 100644 > --- a/hw/spapr.c > +++ b/hw/spapr.c > @@ -64,7 +64,7 @@ static void *spapr_create_fdt(int *fdt_size, ram_addr_t ramsize, > uint32_t end_prop = cpu_to_be32(initrd_base + initrd_size); > uint32_t pft_size_prop[] = {0, cpu_to_be32(hash_shift)}; > char hypertas_prop[] = "hcall-pft\0hcall-term\0hcall-dabr\0hcall-interrupt" > - "\0hcall-tce"; > + "\0hcall-tce\0hcall-vio"; > uint32_t interrupt_server_ranges_prop[] = {0, cpu_to_be32(smp_cpus)}; > int i; > char *modelname; > diff --git a/hw/spapr_vio.c b/hw/spapr_vio.c > index 37cf51e..96668f3 100644 > --- a/hw/spapr_vio.c > +++ b/hw/spapr_vio.c > @@ -352,6 +352,159 @@ uint64_t ldq_tce(VIOsPAPRDevice *dev, uint64_t taddr) > return tswap64(val); > } > > +/* > + * CRQ handling > + */ > +static target_ulong h_reg_crq(CPUState *env, sPAPREnvironment *spapr, > + target_ulong opcode, target_ulong *args) > +{ > + target_ulong reg = args[0]; > + target_ulong queue_addr = args[1]; > + target_ulong queue_len = args[2]; > + VIOsPAPRDevice *dev = spapr_vio_find_by_reg(spapr->vio_bus, reg); > + > + if (!dev) { > + fprintf(stderr, "h_reg_crq on non-existent unit 0x" > + TARGET_FMT_lx "\n", reg); > + return H_PARAMETER; > + } > + > + /* We can't grok a queue size bigger than 256M for now */ > + if (queue_len< 0x1000 || queue_len> 0x10000000) { > + fprintf(stderr, "h_reg_crq, queue size too small or too big (0x%llx)\n", > + (unsigned long long)queue_len); > + return H_PARAMETER; > + } > + > + /* Check queue alignment */ > + if (queue_addr& 0xfff) { > + fprintf(stderr, "h_reg_crq, queue not aligned (0x%llx)\n", > + (unsigned long long)queue_addr); > + return H_PARAMETER; > + } > + > + /* Check if device supports CRQs */ > + if (!dev->crq.SendFunc) { > + return H_NOT_FOUND; > + } > + > + > + /* Already a queue ? */ > + if (dev->crq.qsize) { > + return H_RESOURCE; > + } > + dev->crq.qladdr = queue_addr; > + dev->crq.qsize = queue_len; > + dev->crq.qnext = 0; > + > + dprintf("CRQ for dev 0x" TARGET_FMT_lx " registered at 0x" > + TARGET_FMT_lx "/0x" TARGET_FMT_lx "\n", > + reg, queue_addr, queue_len); > + return H_SUCCESS; > +} > + > +static target_ulong h_free_crq(CPUState *env, sPAPREnvironment *spapr, > + target_ulong opcode, target_ulong *args) > +{ > + target_ulong reg = args[0]; > + VIOsPAPRDevice *dev = spapr_vio_find_by_reg(spapr->vio_bus, reg); > + > + if (!dev) { > + fprintf(stderr, "h_free_crq on non-existent unit 0x" > + TARGET_FMT_lx "\n", reg); > + return H_PARAMETER; > + } > + > + dev->crq.qladdr = 0; > + dev->crq.qsize = 0; > + dev->crq.qnext = 0; > + > + dprintf("CRQ for dev 0x" TARGET_FMT_lx " freed\n", reg); > + > + return H_SUCCESS; > +} > + > +static target_ulong h_send_crq(CPUState *env, sPAPREnvironment *spapr, > + target_ulong opcode, target_ulong *args) > +{ > + target_ulong reg = args[0]; > + target_ulong msg_hi = args[1]; > + target_ulong msg_lo = args[2]; > + VIOsPAPRDevice *dev = spapr_vio_find_by_reg(spapr->vio_bus, reg); > + uint64_t crq_mangle[2]; > + > + if (!dev) { > + fprintf(stderr, "h_send_crq on non-existent unit 0x" > + TARGET_FMT_lx "\n", reg); > + return H_PARAMETER; > + } > + crq_mangle[0] = cpu_to_be64(msg_hi); > + crq_mangle[1] = cpu_to_be64(msg_lo); > + > + if (dev->crq.SendFunc) { > + return dev->crq.SendFunc(dev, (uint8_t *)crq_mangle); > + } > + > + return H_HARDWARE; > +} > + > +static target_ulong h_enable_crq(CPUState *env, sPAPREnvironment *spapr, > + target_ulong opcode, target_ulong *args) > +{ > + target_ulong reg = args[0]; > + VIOsPAPRDevice *dev = spapr_vio_find_by_reg(spapr->vio_bus, reg); > + > + if (!dev) { > + fprintf(stderr, "h_enable_crq on non-existent unit 0x" > + TARGET_FMT_lx "\n", reg); > + return H_PARAMETER; > + } > + > + return 0; > +} > + > +/* Returns negative error, 0 success, or positive: queue full */ > +int spapr_vio_send_crq(VIOsPAPRDevice *dev, uint8_t *crq) > +{ > + int rc; > + uint8_t byte; > + > + if (!dev->crq.qsize) { > + fprintf(stderr, "spapr_vio_send_creq on uninitialized queue\n"); > + return -1; > + } > + > + /* Maybe do a fast path for KVM just writing to the pages */ > + rc = spapr_tce_dma_read(dev, dev->crq.qladdr + dev->crq.qnext,&byte, 1); > + if (rc) { > + return rc; > + } > + if (byte != 0) { > + return 1; > + } > + > + rc = spapr_tce_dma_write(dev, dev->crq.qladdr + dev->crq.qnext + 8,&crq[8], 8); > + if (rc) { > + return rc; > + } > +#ifdef __powerpc__ > + /* Really only needed for kvm... */ Create a kvm helper function for this in target-ppc/kvm.c please that is just a nop when !kvm. > + asm volatile("eieio" : : : "memory"); > +#endif Alex