Re: [Qemu-devel] [PATCH v2 00/16] Virtio devices split from virtio-pci
"Michael S. Tsirkin" wrote: > On Mon, Nov 26, 2018 at 08:59:53PM +0100, Juan Quintela wrote: >> Hi >> >> V2: >> >> - Rebase on top of master >> >> Please review. >> >> Later, Juan. > > And just making sure the point is so that one > can disable virtio-pci and still build virtio? > > And the point of that is mostly as a cleanup on > generic principles, right? Or is there a project that > actually wants to do it? This allows "make check" to work with them disabled. Without this changes, introspection fails, because we have the "name" (kind of) "virtio-pci-blk", but not the real virtio device, so it tries to use it while it is not there. See the equivalent change for virtio-ccw-*. Thanks, Juan. PD. Without this change, you can build a qemu with virtio devices disabled (i.e. not compiled in), but it fails "make check". With the changes, it also works for "make check". > >> >> [v1] >> >From previous verision (in the middle of make check tests): >> - split also the bits of virtio-pci.h (mst suggestion) >> - add gpu, crypt and gpg bits >> - more cleanups >> - fix all the copyrights (the ones not changed have been there >> foverever) >> - be consistent with naming, vhost-* or virtio-* >> >> Please review, Juan. >> >> Juan Quintela (16): >> virtio: split vhost vsock bits from virtio-pci >> virtio: split virtio input host bits from virtio-pci >> virtio: split virtio input bits from virtio-pci >> virtio: split virtio rng bits from virtio-pci >> virtio: split virtio balloon bits from virtio-pci >> virtio: split virtio 9p bits from virtio-pci >> virtio: split vhost user blk bits from virtio-pci >> virtio: split vhost user scsi bits from virtio-pci >> virtio: split vhost scsi bits from virtio-pci >> virtio: split virtio scsi bits from virtio-pci >> virtio: split virtio blk bits rom virtio-pci >> virtio: split virtio net bits rom virtio-pci >> virtio: split virtio serial bits rom virtio-pci >> virtio: split virtio gpu bits rom virtio-pci.h >> virtio: split virtio crypto bits rom virtio-pci.h >> virtio: virtio 9p really requires CONFIG_VIRTFS to work >> >> default-configs/virtio.mak| 3 +- >> hw/display/virtio-gpu-pci.c | 14 + >> hw/display/virtio-vga.c | 1 + >> hw/virtio/Makefile.objs | 14 +- >> hw/virtio/vhost-scsi-pci.c| 95 >> hw/virtio/vhost-user-blk-pci.c| 101 >> hw/virtio/vhost-user-scsi-pci.c | 101 >> hw/virtio/vhost-vsock-pci.c | 82 >> hw/virtio/virtio-9p-pci.c | 86 >> hw/virtio/virtio-balloon-pci.c| 94 >> hw/virtio/virtio-blk-pci.c| 97 >> hw/virtio/virtio-crypto-pci.c | 14 + >> hw/virtio/virtio-input-host-pci.c | 45 ++ >> hw/virtio/virtio-input-pci.c | 154 ++ >> hw/virtio/virtio-net-pci.c| 96 >> hw/virtio/virtio-pci.c| 783 -- >> hw/virtio/virtio-pci.h| 234 - >> hw/virtio/virtio-rng-pci.c| 86 >> hw/virtio/virtio-scsi-pci.c | 106 >> hw/virtio/virtio-serial-pci.c | 112 + >> tests/Makefile.include| 18 +- >> 21 files changed, 1308 insertions(+), 1028 deletions(-) >> create mode 100644 hw/virtio/vhost-scsi-pci.c >> create mode 100644 hw/virtio/vhost-user-blk-pci.c >> create mode 100644 hw/virtio/vhost-user-scsi-pci.c >> create mode 100644 hw/virtio/vhost-vsock-pci.c >> create mode 100644 hw/virtio/virtio-9p-pci.c >> create mode 100644 hw/virtio/virtio-balloon-pci.c >> create mode 100644 hw/virtio/virtio-blk-pci.c >> create mode 100644 hw/virtio/virtio-input-host-pci.c >> create mode 100644 hw/virtio/virtio-input-pci.c >> create mode 100644 hw/virtio/virtio-net-pci.c >> create mode 100644 hw/virtio/virtio-rng-pci.c >> create mode 100644 hw/virtio/virtio-scsi-pci.c >> create mode 100644 hw/virtio/virtio-serial-pci.c >> >> -- >> 2.19.1 >>
Re: [Qemu-devel] [PATCH v2] bt: use size_t type for length parameters instead of int
+-- On Mon, 19 Nov 2018, P J P wrote --+ | From: Prasad J Pandit | | The length parameter values are not negative, thus use an unsigned | type 'size_t' for them. Many routines pass 'len' values to memcpy(3) | calls. If it was negative, it could lead to memory corruption issues. | Add check to avoid it. | | Reported-by: Arash TC | Signed-off-by: Prasad J Pandit | --- | bt-host.c | 8 +++--- | bt-vhci.c | 7 +++--- | hw/bt/core.c | 2 +- | hw/bt/hci-csr.c| 32 | hw/bt/hci.c| 38 ++-- | hw/bt/hid.c| 10 | hw/bt/l2cap.c | 56 ++ | hw/bt/sdp.c| 6 ++--- | hw/usb/dev-bluetooth.c | 12 - | include/hw/bt.h| 8 +++--- | include/sysemu/bt.h| 10 | 11 files changed, 96 insertions(+), 93 deletions(-) | | Update v2: modify assert calls | -> https://lists.gnu.org/archive/html/qemu-devel/2018-11/msg01036.html | Ping...! -- Prasad J Pandit / Red Hat Product Security Team 47AF CE69 3A90 54AA 9045 1053 DD13 3D32 FE5B 041F
Re: [Qemu-devel] [PATCH for-3.1 0/2] Fix disas/nanomips
Stefan Weil wrote: > These two patches fix wrong format strings used in disas/nanomips. Stefan, I truly appreciate your interest in nanoMIPS dissasembler. In my opinion, this series comes too late in 3.1 development cycle to be accepted. The described severity of undesired behavior is just way too low for rc3 phase. Also, as a general remark, in this series, there is no example of wrong output for big endian host, only some belief or opinion - referent test example would be helpful, and much better justification for the series. Some build errors are mentioned, but they are not a part for official builds. Related to these errors, certain additional build options are said to cause build warnings, but such build options were not identified. All in all, my judgement is that we should deal with these issues after 3.1 release. However, I am still grateful to you for bringing these issues up, and you are welcome to participate in any way in future development of this and other segments of QEMU for MIPS. Yours, Aleksandar On Nov 27, 2018 1:19 PM, "Stefan Weil" wrote: > These two patches fix wrong format strings used in disas/nanomips. > > The first patch replaces proprietary data types by POSIX data types, > because otherwise the PRI... macros cannot be used in the second patch. > > Those patches are only relevant for 3.1 if full nanomips support is > considered > important enought and if QEMU is used on big endian machines (I think > the old code will work on little endian hosts even with wrong format > strings). > > I use those patches for QEMU for Windows because that is compiled with > more compiler warnings, so compilation would fail without the fix. > > Regards > Stefan > > >
Re: [Qemu-devel] [PATCH] spice: Use new SpiceImageCompression definition
Hi, This series seems to have some coding style problems. See output below for more information: Message-id: 20181126153036.22414-1-fzig...@redhat.com Subject: [Qemu-devel] [PATCH] spice: Use new SpiceImageCompression definition Type: series === 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 git config --local diff.algorithm histogram 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' 0db479d spice: Use new SpiceImageCompression definition === OUTPUT BEGIN === Checking PATCH 1/1: spice: Use new SpiceImageCompression definition... ERROR: space prohibited after that open square bracket '[' #26: FILE: ui/spice-core.c:334: +[ SPICE_IMAGE_COMPRESSION_OFF ] = "off", ERROR: space prohibited before that close square bracket ']' #26: FILE: ui/spice-core.c:334: +[ SPICE_IMAGE_COMPRESSION_OFF ] = "off", ERROR: space prohibited after that open square bracket '[' #27: FILE: ui/spice-core.c:335: +[ SPICE_IMAGE_COMPRESSION_AUTO_GLZ ] = "auto_glz", ERROR: space prohibited before that close square bracket ']' #27: FILE: ui/spice-core.c:335: +[ SPICE_IMAGE_COMPRESSION_AUTO_GLZ ] = "auto_glz", ERROR: space prohibited after that open square bracket '[' #28: FILE: ui/spice-core.c:336: +[ SPICE_IMAGE_COMPRESSION_AUTO_LZ ] = "auto_lz", ERROR: space prohibited before that close square bracket ']' #28: FILE: ui/spice-core.c:336: +[ SPICE_IMAGE_COMPRESSION_AUTO_LZ ] = "auto_lz", ERROR: space prohibited after that open square bracket '[' #29: FILE: ui/spice-core.c:337: +[ SPICE_IMAGE_COMPRESSION_QUIC ] = "quic", ERROR: space prohibited before that close square bracket ']' #29: FILE: ui/spice-core.c:337: +[ SPICE_IMAGE_COMPRESSION_QUIC ] = "quic", ERROR: space prohibited after that open square bracket '[' #30: FILE: ui/spice-core.c:338: +[ SPICE_IMAGE_COMPRESSION_GLZ ] = "glz", ERROR: space prohibited before that close square bracket ']' #30: FILE: ui/spice-core.c:338: +[ SPICE_IMAGE_COMPRESSION_GLZ ] = "glz", ERROR: space prohibited after that open square bracket '[' #31: FILE: ui/spice-core.c:339: +[ SPICE_IMAGE_COMPRESSION_LZ ] = "lz", ERROR: space prohibited before that close square bracket ']' #31: FILE: ui/spice-core.c:339: +[ SPICE_IMAGE_COMPRESSION_LZ ] = "lz", total: 12 errors, 0 warnings, 34 lines checked Your patch has style problems, please review. If any of these errors are false positives report them to the maintainer, see CHECKPATCH in MAINTAINERS. === OUTPUT END === Test command exited with code: 1 --- Email generated automatically by Patchew [http://patchew.org/]. Please send your feedback to patchew-de...@redhat.com
Re: [Qemu-devel] [PATCH v5 22/36] spapr/xive: add models for KVM support
On Fri, Nov 16, 2018 at 11:57:15AM +0100, Cédric Le Goater wrote: > This introduces a set of XIVE models specific to KVM which derive from > the XIVE base models. The interfaces with KVM are a new capability and > a new KVM device for the XIVE native exploitation interrupt mode. > > They handle the initialization of the TIMA and the source ESB memory > regions which have a different type under KVM. These are 'ram device' > memory mappings, similarly to VFIO, exposed to the guest and the > associated VMAs on the host are populated dynamically with the > appropriate pages using a fault handler. > > Signed-off-by: Cédric Le Goater The logic here looks fine, but I think it would be better to activate it with explicit if (kvm) type logic rather than using a subclass. > --- > default-configs/ppc64-softmmu.mak | 1 + > include/hw/ppc/spapr_xive.h | 18 ++ > include/hw/ppc/xive.h | 3 + > linux-headers/asm-powerpc/kvm.h | 12 + > linux-headers/linux/kvm.h | 4 + > target/ppc/kvm_ppc.h | 6 + > hw/intc/spapr_xive_kvm.c | 430 ++ > hw/ppc/spapr.c| 7 +- > hw/ppc/spapr_irq.c| 19 +- > target/ppc/kvm.c | 7 + > hw/intc/Makefile.objs | 1 + > 11 files changed, 503 insertions(+), 5 deletions(-) > create mode 100644 hw/intc/spapr_xive_kvm.c > > diff --git a/default-configs/ppc64-softmmu.mak > b/default-configs/ppc64-softmmu.mak > index 7f34ad0528ed..c1bf5cd951f5 100644 > --- a/default-configs/ppc64-softmmu.mak > +++ b/default-configs/ppc64-softmmu.mak > @@ -18,6 +18,7 @@ CONFIG_XICS_SPAPR=$(CONFIG_PSERIES) > CONFIG_XICS_KVM=$(call land,$(CONFIG_PSERIES),$(CONFIG_KVM)) > CONFIG_XIVE=$(CONFIG_PSERIES) > CONFIG_XIVE_SPAPR=$(CONFIG_PSERIES) > +CONFIG_XIVE_KVM=$(call land,$(CONFIG_PSERIES),$(CONFIG_KVM)) > CONFIG_MEM_DEVICE=y > CONFIG_DIMM=y > CONFIG_SPAPR_RNG=y > diff --git a/include/hw/ppc/spapr_xive.h b/include/hw/ppc/spapr_xive.h > index aca2969a09ab..9c817bb7ae74 100644 > --- a/include/hw/ppc/spapr_xive.h > +++ b/include/hw/ppc/spapr_xive.h > @@ -40,6 +40,10 @@ typedef struct sPAPRXive { > /* TIMA mapping address */ > hwaddrtm_base; > MemoryRegion tm_mmio; > + > +/* KVM support */ > +int fd; > +void *tm_mmap; > } sPAPRXive; > > #define SPAPR_XIVE_BASE_CLASS(klass) \ > @@ -83,4 +87,18 @@ void spapr_xive_hcall_init(sPAPRMachineState *spapr); > void spapr_dt_xive(sPAPRXive *xive, int nr_servers, void *fdt, > uint32_t phandle); > > +/* > + * XIVE KVM models > + */ > + > +#define TYPE_SPAPR_XIVE_KVM "spapr-xive-kvm" > +#define SPAPR_XIVE_KVM(obj) OBJECT_CHECK(sPAPRXive, (obj), > TYPE_SPAPR_XIVE_KVM) > + > +#define TYPE_XIVE_SOURCE_KVM "xive-source-kvm" > +#define XIVE_SOURCE_KVM(obj) \ > +OBJECT_CHECK(XiveSource, (obj), TYPE_XIVE_SOURCE_KVM) > + > +#define TYPE_XIVE_TCTX_KVM "xive-tctx-kvm" > +#define XIVE_TCTX_KVM(obj) OBJECT_CHECK(XiveTCTX, (obj), > TYPE_XIVE_TCTX_KVM) > + > #endif /* PPC_SPAPR_XIVE_H */ > diff --git a/include/hw/ppc/xive.h b/include/hw/ppc/xive.h > index 281ed370121c..7aaf5a182cb3 100644 > --- a/include/hw/ppc/xive.h > +++ b/include/hw/ppc/xive.h > @@ -69,6 +69,9 @@ typedef struct XiveSource { > uint32_tesb_shift; > MemoryRegionesb_mmio; > > +/* KVM support */ > +void*esb_mmap; > + > XiveFabric *xive; > } XiveSource; > > diff --git a/linux-headers/asm-powerpc/kvm.h b/linux-headers/asm-powerpc/kvm.h > index 8c876c166ef2..f34c971491dd 100644 > --- a/linux-headers/asm-powerpc/kvm.h > +++ b/linux-headers/asm-powerpc/kvm.h Updates to linux-headers need to be split out into a separate patch. Eventually (i.e. by the time we merge) they should be just "update headers to SHA XXX" not picking and choosing pieces. > @@ -675,4 +675,16 @@ struct kvm_ppc_cpu_char { > #define KVM_XICS_PRESENTED (1ULL << 43) > #define KVM_XICS_QUEUED (1ULL << 44) > > +/* POWER9 XIVE Native Interrupt Controller */ > +#define KVM_DEV_XIVE_GRP_CTRL1 > +#define KVM_DEV_XIVE_GET_ESB_FD1 > +#define KVM_DEV_XIVE_GET_TIMA_FD 2 > +#define KVM_DEV_XIVE_VC_BASE 3 > +#define KVM_DEV_XIVE_GRP_SOURCES 2 /* 64-bit source attributes */ > + > +/* Layout of 64-bit XIVE source attribute values */ > +#define KVM_XIVE_LEVEL_SENSITIVE (1ULL << 0) > +#define KVM_XIVE_LEVEL_ASSERTED (1ULL << 1) > + > + > #endif /* __LINUX_KVM_POWERPC_H */ > diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h > index f11a7eb49cfa..59fa8d8d7f39 100644 > --- a/linux-headers/linux/kvm.h > +++ b/linux-headers/linux/kvm.h > @@ -965,6 +965,8 @@ struct kvm_ppc_resize_hpt { > #define KVM_CAP_COALESCED_PIO 162 > #define KVM_CAP_HYPERV_ENLIGHTENED_VMCS 163 > #define KVM_CAP_EXCEPTION_PAYLOAD 164 > +#define KVM_CAP_ARM_VM_IPA_SIZE 165 > +#define KVM_CAP_P
Re: [Qemu-devel] [PATCH v5 21/36] spapr: extend the sPAPR IRQ backend for XICS migration
On Fri, Nov 16, 2018 at 11:57:14AM +0100, Cédric Le Goater wrote: > Introduce a new sPAPR IRQ handler to handle resend after migration > when the machine is using a KVM XICS interrupt controller model. > > Signed-off-by: Cédric Le Goater Reviewed-by: David Gibson > --- > include/hw/ppc/spapr_irq.h | 2 ++ > hw/ppc/spapr.c | 13 + > hw/ppc/spapr_irq.c | 27 +++ > 3 files changed, 34 insertions(+), 8 deletions(-) > > diff --git a/include/hw/ppc/spapr_irq.h b/include/hw/ppc/spapr_irq.h > index b299dd794bff..4e36c0984e1a 100644 > --- a/include/hw/ppc/spapr_irq.h > +++ b/include/hw/ppc/spapr_irq.h > @@ -45,6 +45,7 @@ typedef struct sPAPRIrq { > void *fdt, uint32_t phandle); > Object *(*cpu_intc_create)(sPAPRMachineState *spapr, Object *cpu, > Error **errp); > +int (*post_load)(sPAPRMachineState *spapr, int version_id); > } sPAPRIrq; > > extern sPAPRIrq spapr_irq_xics; > @@ -55,6 +56,7 @@ void spapr_irq_init(sPAPRMachineState *spapr, int > nr_servers, Error **errp); > int spapr_irq_claim(sPAPRMachineState *spapr, int irq, bool lsi, Error > **errp); > void spapr_irq_free(sPAPRMachineState *spapr, int irq, int num); > qemu_irq spapr_qirq(sPAPRMachineState *spapr, int irq); > +int spapr_irq_post_load(sPAPRMachineState *spapr, int version_id); > > /* > * XICS legacy routines > diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c > index 8fbb743769db..f9cf2debff5a 100644 > --- a/hw/ppc/spapr.c > +++ b/hw/ppc/spapr.c > @@ -1738,14 +1738,6 @@ static int spapr_post_load(void *opaque, int > version_id) > return err; > } > > -if (!object_dynamic_cast(OBJECT(spapr->ics), TYPE_ICS_KVM)) { > -CPUState *cs; > -CPU_FOREACH(cs) { > -PowerPCCPU *cpu = POWERPC_CPU(cs); > -icp_resend(ICP(cpu->intc)); > -} > -} > - > /* In earlier versions, there was no separate qdev for the PAPR > * RTC, so the RTC offset was stored directly in sPAPREnvironment. > * So when migrating from those versions, poke the incoming offset > @@ -1766,6 +1758,11 @@ static int spapr_post_load(void *opaque, int > version_id) > } > } > > +err = spapr_irq_post_load(spapr, version_id); > +if (err) { > +return err; > +} > + > return err; > } > > diff --git a/hw/ppc/spapr_irq.c b/hw/ppc/spapr_irq.c > index f6e9e44d4cf9..33dd5da7d255 100644 > --- a/hw/ppc/spapr_irq.c > +++ b/hw/ppc/spapr_irq.c > @@ -203,6 +203,18 @@ static Object > *spapr_irq_cpu_intc_create_xics(sPAPRMachineState *spapr, > return icp_create(cpu, spapr->icp_type, XICS_FABRIC(spapr), errp); > } > > +static int spapr_irq_post_load_xics(sPAPRMachineState *spapr, int version_id) > +{ > +if (!object_dynamic_cast(OBJECT(spapr->ics), TYPE_ICS_KVM)) { > +CPUState *cs; > +CPU_FOREACH(cs) { > +PowerPCCPU *cpu = POWERPC_CPU(cs); > +icp_resend(ICP(cpu->intc)); > +} > +} > +return 0; > +} > + > #define SPAPR_IRQ_XICS_NR_IRQS 0x1000 > #define SPAPR_IRQ_XICS_NR_MSIS \ > (XICS_IRQ_BASE + SPAPR_IRQ_XICS_NR_IRQS - SPAPR_IRQ_MSI) > @@ -219,6 +231,7 @@ sPAPRIrq spapr_irq_xics = { > .print_info = spapr_irq_print_info_xics, > .dt_populate = spapr_irq_dt_populate_xics, > .cpu_intc_create = spapr_irq_cpu_intc_create_xics, > +.post_load = spapr_irq_post_load_xics, > }; > > /* > @@ -331,6 +344,11 @@ static Object > *spapr_irq_cpu_intc_create_xive(sPAPRMachineState *spapr, > XIVE_ROUTER(spapr->xive), errp); > } > > +static int spapr_irq_post_load_xive(sPAPRMachineState *spapr, int version_id) > +{ > +return 0; > +} > + > /* > * XIVE uses the full IRQ number space. Set it to 8K to be compatible > * with XICS. > @@ -351,6 +369,7 @@ sPAPRIrq spapr_irq_xive = { > .print_info = spapr_irq_print_info_xive, > .dt_populate = spapr_irq_dt_populate_xive, > .cpu_intc_create = spapr_irq_cpu_intc_create_xive, > +.post_load = spapr_irq_post_load_xive, > }; > > /* > @@ -389,6 +408,13 @@ qemu_irq spapr_qirq(sPAPRMachineState *spapr, int irq) > return smc->irq->qirq(spapr, irq); > } > > +int spapr_irq_post_load(sPAPRMachineState *spapr, int version_id) > +{ > +sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr); > + > +return smc->irq->post_load(spapr, version_id); > +} > + > /* > * XICS legacy routines - to deprecate one day > */ > @@ -458,4 +484,5 @@ sPAPRIrq spapr_irq_xics_legacy = { > .print_info = spapr_irq_print_info_xics, > .dt_populate = spapr_irq_dt_populate_xics, > .cpu_intc_create = spapr_irq_cpu_intc_create_xics, > +.post_load = spapr_irq_post_load_xics, > }; -- David Gibson| I'll have my music baroque, and my code david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_ |
Re: [Qemu-devel] [PATCH for-3.1] vfio-helpers: Fix qemu_vfio_open_pci() crash
- Original Message - > From: "Markus Armbruster" > To: qemu-devel@nongnu.org > Cc: c...@redhat.com, f...@euphon.net, stefa...@redhat.com, pbonz...@redhat.com > Sent: Tuesday, November 27, 2018 4:41:43 PM > Subject: [PATCH for-3.1] vfio-helpers: Fix qemu_vfio_open_pci() crash > > qemu_vfio_open_common() initializes s->lock only after passing s to > qemu_vfio_dma_map() via qemu_vfio_init_ramblock(). > qemu_vfio_dma_map() tries to lock the uninitialized lock and crashes. > > Fix by initializing s->lock first. > > RHBZ: https://bugzilla.redhat.com/show_bug.cgi?id=1645840 > Fixes: 418026ca43bc2626db092d7558258f9594366f28 > Cc: qemu-sta...@nongnu.org > Signed-off-by: Markus Armbruster > --- > Compile-tested only, as I lack suitable hardware. Cong Li (cc'ed) is > going to test it for real. It looks obvious enough to me to put it > into -rc3 without waiting for the test results. We can also wait and > put it into -rc4. Smoke test of nvme:// pass with this patch. Ack. > > util/vfio-helpers.c | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > > diff --git a/util/vfio-helpers.c b/util/vfio-helpers.c > index 1d9272efa4..9cd42e 100644 > --- a/util/vfio-helpers.c > +++ b/util/vfio-helpers.c > @@ -411,13 +411,13 @@ static int qemu_vfio_init_ramblock(const char > *block_name, void *host_addr, > > static void qemu_vfio_open_common(QEMUVFIOState *s) > { > +qemu_mutex_init(&s->lock); > s->ram_notifier.ram_block_added = qemu_vfio_ram_block_added; > s->ram_notifier.ram_block_removed = qemu_vfio_ram_block_removed; > ram_block_notifier_add(&s->ram_notifier); > s->low_water_mark = QEMU_VFIO_IOVA_MIN; > s->high_water_mark = QEMU_VFIO_IOVA_MAX; > qemu_ram_foreach_block(qemu_vfio_init_ramblock, s); > -qemu_mutex_init(&s->lock); > } > > /** > -- > 2.17.2 > >
[Qemu-devel] [PATCH 07/12] tcg: Dump register preference info with liveness
Signed-off-by: Richard Henderson --- tcg/tcg.h | 3 --- tcg/tcg.c | 44 +--- 2 files changed, 37 insertions(+), 10 deletions(-) diff --git a/tcg/tcg.h b/tcg/tcg.h index b2e274b7af..ac5d01c223 100644 --- a/tcg/tcg.h +++ b/tcg/tcg.h @@ -1089,9 +1089,6 @@ TCGOp *tcg_op_insert_after(TCGContext *s, TCGOp *op, TCGOpcode opc, int narg); void tcg_optimize(TCGContext *s); -/* only used for debugging purposes */ -void tcg_dump_ops(TCGContext *s); - TCGv_i32 tcg_const_i32(int32_t val); TCGv_i64 tcg_const_i64(int64_t val); TCGv_i32 tcg_const_local_i32(int32_t val); diff --git a/tcg/tcg.c b/tcg/tcg.c index adf6570c36..27d081e11a 100644 --- a/tcg/tcg.c +++ b/tcg/tcg.c @@ -1921,7 +1921,7 @@ static inline TCGReg tcg_regset_first(TCGRegSet d) } } -void tcg_dump_ops(TCGContext *s) +static void tcg_dump_ops(TCGContext *s, bool have_prefs) { char buf[128]; TCGOp *op; @@ -2056,12 +2056,15 @@ void tcg_dump_ops(TCGContext *s) col += qemu_log("%s$0x%" TCG_PRIlx, k ? "," : "", op->args[k]); } } -if (op->life) { -unsigned life = op->life; -for (; col < 48; ++col) { +if (have_prefs || op->life) { +for (; col < 40; ++col) { putc(' ', qemu_logfile); } +} + +if (op->life) { +unsigned life = op->life; if (life & (SYNC_ARG * 3)) { qemu_log(" sync:"); @@ -2081,6 +2084,33 @@ void tcg_dump_ops(TCGContext *s) } } } + +if (have_prefs) { +for (i = 0; i < nb_oargs; ++i) { +TCGRegSet set = op->output_pref[i]; + +if (i == 0) { +qemu_log(" pref="); +} else { +qemu_log(","); +} +if (set == 0) { +qemu_log("none"); +} else if (set == MAKE_64BIT_MASK(0, TCG_TARGET_NB_REGS)) { +qemu_log("all"); +#ifdef CONFIG_DEBUG_TCG +} else if (tcg_regset_single(set)) { +TCGReg reg = tcg_regset_first(set); +qemu_log("%s", tcg_target_reg_names[reg]); +#endif +} else if (TCG_TARGET_NB_REGS <= 32) { +qemu_log("%#x", (uint32_t)set); +} else { +qemu_log("%#" PRIx64, (uint64_t)set); +} +} +} + qemu_log("\n"); } } @@ -3669,7 +3699,7 @@ int tcg_gen_code(TCGContext *s, TranslationBlock *tb) && qemu_log_in_addr_range(tb->pc))) { qemu_log_lock(); qemu_log("OP:\n"); -tcg_dump_ops(s); +tcg_dump_ops(s, false); qemu_log("\n"); qemu_log_unlock(); } @@ -3697,7 +3727,7 @@ int tcg_gen_code(TCGContext *s, TranslationBlock *tb) && qemu_log_in_addr_range(tb->pc))) { qemu_log_lock(); qemu_log("OP before indirect lowering:\n"); -tcg_dump_ops(s); +tcg_dump_ops(s, false); qemu_log("\n"); qemu_log_unlock(); } @@ -3718,7 +3748,7 @@ int tcg_gen_code(TCGContext *s, TranslationBlock *tb) && qemu_log_in_addr_range(tb->pc))) { qemu_log_lock(); qemu_log("OP after optimization and liveness analysis:\n"); -tcg_dump_ops(s); +tcg_dump_ops(s, true); qemu_log("\n"); qemu_log_unlock(); } -- 2.17.2
Re: [Qemu-devel] [Spice-devel] [PATCH] spice: Use new SpiceImageCompression definition
On Tue, Nov 27, 2018 at 01:35:02PM +0100, Christophe Fergeau wrote: > hey, > > On Mon, Nov 26, 2018 at 03:30:36PM +, Frediano Ziglio wrote: > > Definitions were updated by spice-server in patch de66161 included > > in 0.12.6 released on 12th June 2015. > > QEMU's configure only checks for spice-server 0.12.0: > I don't know how far back QEMU wants to support spice-server. > Apart from this, the patch looks good to me. 0.12.6 is more than three years old, so this or something newer should be available in most distros meanwhile. Raising the bar to that version looks ok to me (separate patch please, and please also drop #ifdefs we don't need any more then). thanks, Gerd
[Qemu-devel] [PATCH 10/12] tcg: Split out more subroutines from liveness_pass_1
Signed-off-by: Richard Henderson --- tcg/tcg.c | 35 +++ 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/tcg/tcg.c b/tcg/tcg.c index 27814df882..21668831a1 100644 --- a/tcg/tcg.c +++ b/tcg/tcg.c @@ -2417,6 +2417,26 @@ static void la_bb_end(TCGContext *s, int ng, int nt) } } +/* liveness analysis: sync globals back to memory. */ +static void la_global_sync(TCGContext *s, int ng) +{ +int i; + +for (i = 0; i < ng; ++i) { +s->temps[i].state |= TS_MEM; +} +} + +/* liveness analysis: sync globals back to memory and kill. */ +static void la_global_kill(TCGContext *s, int ng) +{ +int i; + +for (i = 0; i < ng; i++) { +s->temps[i].state = TS_DEAD | TS_MEM; +} +} + /* Liveness analysis : update the opc_arg_life array to tell if a given input arguments is dead. Instructions updating dead temporaries are removed. */ @@ -2472,15 +2492,9 @@ static void liveness_pass_1(TCGContext *s) if (!(call_flags & (TCG_CALL_NO_WRITE_GLOBALS | TCG_CALL_NO_READ_GLOBALS))) { -/* globals should go back to memory */ -for (i = 0; i < nb_globals; i++) { -s->temps[i].state = TS_DEAD | TS_MEM; -} +la_global_kill(s, nb_globals); } else if (!(call_flags & TCG_CALL_NO_READ_GLOBALS)) { -/* globals should be synced to memory */ -for (i = 0; i < nb_globals; i++) { -s->temps[i].state |= TS_MEM; -} +la_global_sync(s, nb_globals); } /* record arguments that die in this helper */ @@ -2623,10 +2637,7 @@ static void liveness_pass_1(TCGContext *s) if (def->flags & TCG_OPF_BB_END) { la_bb_end(s, nb_globals, nb_temps); } else if (def->flags & TCG_OPF_SIDE_EFFECTS) { -/* globals should be synced to memory */ -for (i = 0; i < nb_globals; i++) { -s->temps[i].state |= TS_MEM; -} +la_global_sync(s, nb_globals); } /* record arguments that die in this opcode */ -- 2.17.2
[Qemu-devel] [PATCH 09/12] tcg: Rename and adjust liveness_pass_1 helpers
No need for a "tcg_" prefix for a static function; we already have another "la_" prefix for indicating liveness analysis. Pass in nb_globals and nb_temps, as we will already have them in registers for other loops within the parent function. Signed-off-by: Richard Henderson --- tcg/tcg.c | 13 + 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/tcg/tcg.c b/tcg/tcg.c index 82f9a66d31..27814df882 100644 --- a/tcg/tcg.c +++ b/tcg/tcg.c @@ -2389,10 +2389,8 @@ static void reachable_code_pass(TCGContext *s) /* liveness analysis: end of function: all temps are dead, and globals should be in memory. */ -static void tcg_la_func_end(TCGContext *s) +static void la_func_end(TCGContext *s, int ng, int nt) { -int ng = s->nb_globals; -int nt = s->nb_temps; int i; for (i = 0; i < ng; ++i) { @@ -2405,10 +2403,8 @@ static void tcg_la_func_end(TCGContext *s) /* liveness analysis: end of basic block: all temps are dead, globals and local temps should be in memory. */ -static void tcg_la_bb_end(TCGContext *s) +static void la_bb_end(TCGContext *s, int ng, int nt) { -int ng = s->nb_globals; -int nt = s->nb_temps; int i; for (i = 0; i < ng; ++i) { @@ -2427,9 +2423,10 @@ static void tcg_la_bb_end(TCGContext *s) static void liveness_pass_1(TCGContext *s) { int nb_globals = s->nb_globals; +int nb_temps = s->nb_temps; TCGOp *op, *op_prev; -tcg_la_func_end(s); +la_func_end(s, nb_globals, nb_temps); QTAILQ_FOREACH_REVERSE_SAFE(op, &s->ops, TCGOpHead, link, op_prev) { int i, nb_iargs, nb_oargs; @@ -2624,7 +2621,7 @@ static void liveness_pass_1(TCGContext *s) /* if end of basic block, update */ if (def->flags & TCG_OPF_BB_END) { -tcg_la_bb_end(s); +la_bb_end(s, nb_globals, nb_temps); } else if (def->flags & TCG_OPF_SIDE_EFFECTS) { /* globals should be synced to memory */ for (i = 0; i < nb_globals; i++) { -- 2.17.2
[Qemu-devel] [PATCH 08/12] tcg: Reindent parts of liveness_pass_1
There are two blocks of the form if (foo) { stuff1; goto bar; } else { baz: stuff2; } which have unnecessary and confusing indentation. Remove the else and unindent stuff2. Signed-off-by: Richard Henderson --- tcg/tcg.c | 139 -- 1 file changed, 71 insertions(+), 68 deletions(-) diff --git a/tcg/tcg.c b/tcg/tcg.c index 27d081e11a..82f9a66d31 100644 --- a/tcg/tcg.c +++ b/tcg/tcg.c @@ -2458,47 +2458,46 @@ static void liveness_pass_1(TCGContext *s) } } goto do_remove; -} else { -do_not_remove_call: +} +do_not_remove_call: -/* output args are dead */ -for (i = 0; i < nb_oargs; i++) { -arg_ts = arg_temp(op->args[i]); -if (arg_ts->state & TS_DEAD) { -arg_life |= DEAD_ARG << i; -} -if (arg_ts->state & TS_MEM) { -arg_life |= SYNC_ARG << i; -} -arg_ts->state = TS_DEAD; +/* output args are dead */ +for (i = 0; i < nb_oargs; i++) { +arg_ts = arg_temp(op->args[i]); +if (arg_ts->state & TS_DEAD) { +arg_life |= DEAD_ARG << i; } +if (arg_ts->state & TS_MEM) { +arg_life |= SYNC_ARG << i; +} +arg_ts->state = TS_DEAD; +} -if (!(call_flags & (TCG_CALL_NO_WRITE_GLOBALS | -TCG_CALL_NO_READ_GLOBALS))) { -/* globals should go back to memory */ -for (i = 0; i < nb_globals; i++) { -s->temps[i].state = TS_DEAD | TS_MEM; -} -} else if (!(call_flags & TCG_CALL_NO_READ_GLOBALS)) { -/* globals should be synced to memory */ -for (i = 0; i < nb_globals; i++) { -s->temps[i].state |= TS_MEM; -} +if (!(call_flags & (TCG_CALL_NO_WRITE_GLOBALS | +TCG_CALL_NO_READ_GLOBALS))) { +/* globals should go back to memory */ +for (i = 0; i < nb_globals; i++) { +s->temps[i].state = TS_DEAD | TS_MEM; } +} else if (!(call_flags & TCG_CALL_NO_READ_GLOBALS)) { +/* globals should be synced to memory */ +for (i = 0; i < nb_globals; i++) { +s->temps[i].state |= TS_MEM; +} +} -/* record arguments that die in this helper */ -for (i = nb_oargs; i < nb_iargs + nb_oargs; i++) { -arg_ts = arg_temp(op->args[i]); -if (arg_ts && arg_ts->state & TS_DEAD) { -arg_life |= DEAD_ARG << i; -} +/* record arguments that die in this helper */ +for (i = nb_oargs; i < nb_iargs + nb_oargs; i++) { +arg_ts = arg_temp(op->args[i]); +if (arg_ts && arg_ts->state & TS_DEAD) { +arg_life |= DEAD_ARG << i; } -/* input arguments are live for preceding opcodes */ -for (i = nb_oargs; i < nb_iargs + nb_oargs; i++) { -arg_ts = arg_temp(op->args[i]); -if (arg_ts) { -arg_ts->state &= ~TS_DEAD; -} +} +/* input arguments are live for preceding opcodes */ +for (i = nb_oargs; i < nb_iargs + nb_oargs; i++) { +arg_ts = arg_temp(op->args[i]); +if (arg_ts) { +arg_ts->state &= ~TS_DEAD; } } } @@ -2602,43 +2601,47 @@ static void liveness_pass_1(TCGContext *s) goto do_not_remove; } } -do_remove: -tcg_op_remove(s, op); -} else { -do_not_remove: -/* output args are dead */ -for (i = 0; i < nb_oargs; i++) { -arg_ts = arg_temp(op->args[i]); -if (arg_ts->state & TS_DEAD) { -arg_life |= DEAD_ARG << i; -} -if (arg_ts->state & TS_MEM) { -arg_life |= SYNC_ARG << i; -} -
[Qemu-devel] [PATCH 12/12] tcg: Record register preferences during liveness
With these preferences, we can arrange for function call arguments to be computed into the proper registers instead of requiring extra moves. Signed-off-by: Richard Henderson --- tcg/tcg.c | 197 +- 1 file changed, 165 insertions(+), 32 deletions(-) diff --git a/tcg/tcg.c b/tcg/tcg.c index 673aaf52a1..734a453fc8 100644 --- a/tcg/tcg.c +++ b/tcg/tcg.c @@ -2387,6 +2387,21 @@ static void reachable_code_pass(TCGContext *s) #define IS_DEAD_ARG(n) (arg_life & (DEAD_ARG << (n))) #define NEED_SYNC_ARG(n) (arg_life & (SYNC_ARG << (n))) +/* For liveness_pass_1, the register preferences for a given temp. */ +static inline TCGRegSet *la_temp_pref(TCGTemp *ts) +{ +return ts->state_ptr; +} + +/* For liveness_pass_1, reset the preferences for a given temp to the + * maximal regset for its type. + */ +static inline void la_reset_pref(TCGTemp *ts) +{ +*la_temp_pref(ts) += (ts->state == TS_DEAD ? 0 : tcg_target_available_regs[ts->type]); +} + /* liveness analysis: end of function: all temps are dead, and globals should be in memory. */ static void la_func_end(TCGContext *s, int ng, int nt) @@ -2395,9 +2410,11 @@ static void la_func_end(TCGContext *s, int ng, int nt) for (i = 0; i < ng; ++i) { s->temps[i].state = TS_DEAD | TS_MEM; +la_reset_pref(&s->temps[i]); } for (i = ng; i < nt; ++i) { s->temps[i].state = TS_DEAD; +la_reset_pref(&s->temps[i]); } } @@ -2409,11 +2426,13 @@ static void la_bb_end(TCGContext *s, int ng, int nt) for (i = 0; i < ng; ++i) { s->temps[i].state = TS_DEAD | TS_MEM; +la_reset_pref(&s->temps[i]); } for (i = ng; i < nt; ++i) { s->temps[i].state = (s->temps[i].temp_local ? TS_DEAD | TS_MEM : TS_DEAD); +la_reset_pref(&s->temps[i]); } } @@ -2423,7 +2442,12 @@ static void la_global_sync(TCGContext *s, int ng) int i; for (i = 0; i < ng; ++i) { -s->temps[i].state |= TS_MEM; +int state = s->temps[i].state; +s->temps[i].state = state | TS_MEM; +if (state == TS_DEAD) { +/* If the global was previously dead, reset prefs. */ +la_reset_pref(&s->temps[i]); +} } } @@ -2434,6 +2458,29 @@ static void la_global_kill(TCGContext *s, int ng) for (i = 0; i < ng; i++) { s->temps[i].state = TS_DEAD | TS_MEM; +la_reset_pref(&s->temps[i]); +} +} + +/* liveness analysis: note live globals crossing calls. */ +static void la_cross_call(TCGContext *s, int nt) +{ +TCGRegSet mask = ~tcg_target_call_clobber_regs; +int i; + +for (i = 0; i < nt; i++) { +TCGTemp *ts = &s->temps[i]; +if (!(ts->state & TS_DEAD)) { +TCGRegSet *pset = la_temp_pref(ts); +TCGRegSet set = *pset; + +set &= mask; +/* If the combination is not possible, restart. */ +if (set == 0) { +set = tcg_target_available_regs[ts->type] & mask; +} +*pset = set; +} } } @@ -2445,16 +2492,23 @@ static void liveness_pass_1(TCGContext *s) int nb_globals = s->nb_globals; int nb_temps = s->nb_temps; TCGOp *op, *op_prev; +TCGRegSet *prefs; +int i; + +prefs = tcg_malloc(sizeof(TCGRegSet) * nb_temps); +for (i = 0; i < nb_temps; ++i) { +s->temps[i].state_ptr = prefs + i; +} /* ??? Should be redundant with the exit_tb that ends the TB. */ la_func_end(s, nb_globals, nb_temps); QTAILQ_FOREACH_REVERSE_SAFE(op, &s->ops, TCGOpHead, link, op_prev) { -int i, nb_iargs, nb_oargs; +int nb_iargs, nb_oargs; TCGOpcode opc_new, opc_new2; bool have_opc_new2; TCGLifeData arg_life = 0; -TCGTemp *arg_ts; +TCGTemp *ts; TCGOpcode opc = op->opc; const TCGOpDef *def = &tcg_op_defs[opc]; @@ -2462,6 +2516,7 @@ static void liveness_pass_1(TCGContext *s) case INDEX_op_call: { int call_flags; +int nb_call_regs; nb_oargs = TCGOP_CALLO(op); nb_iargs = TCGOP_CALLI(op); @@ -2470,8 +2525,8 @@ static void liveness_pass_1(TCGContext *s) /* pure functions can be removed if their result is unused */ if (call_flags & TCG_CALL_NO_SIDE_EFFECTS) { for (i = 0; i < nb_oargs; i++) { -arg_ts = arg_temp(op->args[i]); -if (arg_ts->state != TS_DEAD) { +ts = arg_temp(op->args[i]); +if (ts->state != TS_DEAD) { goto do_not_remove_call; } } @@ -2479,16 +2534,20 @@ static void liveness_pass_1(TCGContext *s) } do_not_remove_call: -
[Qemu-devel] [PATCH 02/12] tcg: Add preferred_reg argument to temp_load
Pass this through to tcg_reg_alloc. Signed-off-by: Richard Henderson --- tcg/tcg.c | 18 +- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/tcg/tcg.c b/tcg/tcg.c index c596277fd0..7f29a2045a 100644 --- a/tcg/tcg.c +++ b/tcg/tcg.c @@ -2859,7 +2859,7 @@ static void temp_allocate_frame(TCGContext *s, TCGTemp *ts) s->current_frame_offset += sizeof(tcg_target_long); } -static void temp_load(TCGContext *, TCGTemp *, TCGRegSet, TCGRegSet); +static void temp_load(TCGContext *, TCGTemp *, TCGRegSet, TCGRegSet, TCGRegSet); /* Mark a temporary as free or dead. If 'free_or_dead' is negative, mark it free; otherwise mark it dead. */ @@ -2908,7 +2908,7 @@ static void temp_sync(TCGContext *s, TCGTemp *ts, break; } temp_load(s, ts, tcg_target_available_regs[ts->type], - allocated_regs); + allocated_regs, 0); /* fallthrough */ case TEMP_VAL_REG: @@ -3014,7 +3014,7 @@ static TCGReg tcg_reg_alloc(TCGContext *s, TCGRegSet required_regs, /* Make sure the temporary is in a register. If needed, allocate the register from DESIRED while avoiding ALLOCATED. */ static void temp_load(TCGContext *s, TCGTemp *ts, TCGRegSet desired_regs, - TCGRegSet allocated_regs) + TCGRegSet allocated_regs, TCGRegSet preferred_regs) { TCGReg reg; @@ -3023,13 +3023,13 @@ static void temp_load(TCGContext *s, TCGTemp *ts, TCGRegSet desired_regs, return; case TEMP_VAL_CONST: reg = tcg_reg_alloc(s, desired_regs, allocated_regs, -0, ts->indirect_base); +preferred_regs, ts->indirect_base); tcg_out_movi(s, ts->type, reg, ts->val); ts->mem_coherent = 0; break; case TEMP_VAL_MEM: reg = tcg_reg_alloc(s, desired_regs, allocated_regs, -0, ts->indirect_base); +preferred_regs, ts->indirect_base); tcg_out_ld(s, ts->type, reg, ts->mem_base->reg, ts->mem_offset); ts->mem_coherent = 1; break; @@ -3159,7 +3159,7 @@ static void tcg_reg_alloc_mov(TCGContext *s, const TCGOp *op) the SOURCE value into its own register first, that way we don't have to reload SOURCE the next time it is used. */ if (ts->val_type == TEMP_VAL_MEM) { -temp_load(s, ts, tcg_target_available_regs[itype], allocated_regs); +temp_load(s, ts, tcg_target_available_regs[itype], allocated_regs, 0); } tcg_debug_assert(ts->val_type == TEMP_VAL_REG); @@ -3243,7 +3243,7 @@ static void tcg_reg_alloc_op(TCGContext *s, const TCGOp *op) goto iarg_end; } -temp_load(s, ts, arg_ct->u.regs, i_allocated_regs); +temp_load(s, ts, arg_ct->u.regs, i_allocated_regs, 0); if (arg_ct->ct & TCG_CT_IALIAS) { if (ts->fixed_reg) { @@ -3424,7 +3424,7 @@ static void tcg_reg_alloc_call(TCGContext *s, TCGOp *op) if (arg != TCG_CALL_DUMMY_ARG) { ts = arg_temp(arg); temp_load(s, ts, tcg_target_available_regs[ts->type], - s->reserved_regs); + s->reserved_regs, 0); tcg_out_st(s, ts->type, ts->reg, TCG_REG_CALL_STACK, stack_offset); } #ifndef TCG_TARGET_STACK_GROWSUP @@ -3449,7 +3449,7 @@ static void tcg_reg_alloc_call(TCGContext *s, TCGOp *op) TCGRegSet arg_set = 0; tcg_regset_set_reg(arg_set, reg); -temp_load(s, ts, arg_set, allocated_regs); +temp_load(s, ts, arg_set, allocated_regs, 0); } tcg_regset_set_reg(allocated_regs, reg); -- 2.17.2
[Qemu-devel] [PATCH 05/12] tcg: Add output_pref to TCGOp
Allocate storage for, but do not yet fill in, per-opcode preferences for the output operands. Pass it in to the register allocation routines for output operands. Signed-off-by: Richard Henderson --- tcg/tcg.h | 3 +++ tcg/tcg.c | 18 +++--- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/tcg/tcg.h b/tcg/tcg.h index c6caeeb42b..b2e274b7af 100644 --- a/tcg/tcg.h +++ b/tcg/tcg.h @@ -621,6 +621,9 @@ typedef struct TCGOp { /* Arguments for the opcode. */ TCGArg args[MAX_OPC_PARAM]; + +/* Register preferences for the output(s). */ +TCGRegSet output_pref[2]; } TCGOp; #define TCGOP_CALLI(X)(X)->param1 diff --git a/tcg/tcg.c b/tcg/tcg.c index c83ca238aa..f86415ce29 100644 --- a/tcg/tcg.c +++ b/tcg/tcg.c @@ -2613,6 +2613,8 @@ static void liveness_pass_1(TCGContext *s) break; } op->life = arg_life; +op->output_pref[0] = 0; +op->output_pref[1] = 0; } } @@ -3127,17 +3129,18 @@ static void tcg_reg_alloc_movi(TCGContext *s, const TCGOp *op) TCGTemp *ots = arg_temp(op->args[0]); tcg_target_ulong val = op->args[1]; -tcg_reg_alloc_do_movi(s, ots, val, op->life, 0); +tcg_reg_alloc_do_movi(s, ots, val, op->life, op->output_pref[0]); } static void tcg_reg_alloc_mov(TCGContext *s, const TCGOp *op) { const TCGLifeData arg_life = op->life; -TCGRegSet allocated_regs; +TCGRegSet allocated_regs, preferred_regs; TCGTemp *ts, *ots; TCGType otype, itype; allocated_regs = s->reserved_regs; +preferred_regs = op->output_pref[0]; ots = arg_temp(op->args[0]); ts = arg_temp(op->args[1]); @@ -3151,7 +3154,7 @@ static void tcg_reg_alloc_mov(TCGContext *s, const TCGOp *op) if (IS_DEAD_ARG(1)) { temp_dead(s, ts); } -tcg_reg_alloc_do_movi(s, ots, val, arg_life, 0); +tcg_reg_alloc_do_movi(s, ots, val, arg_life, preferred_regs); return; } @@ -3160,7 +3163,8 @@ static void tcg_reg_alloc_mov(TCGContext *s, const TCGOp *op) the SOURCE value into its own register first, that way we don't have to reload SOURCE the next time it is used. */ if (ts->val_type == TEMP_VAL_MEM) { -temp_load(s, ts, tcg_target_available_regs[itype], allocated_regs, 0); +temp_load(s, ts, tcg_target_available_regs[itype], + allocated_regs, preferred_regs); } tcg_debug_assert(ts->val_type == TEMP_VAL_REG); @@ -3190,7 +3194,7 @@ static void tcg_reg_alloc_mov(TCGContext *s, const TCGOp *op) input one. */ tcg_regset_set_reg(allocated_regs, ts->reg); ots->reg = tcg_reg_alloc(s, tcg_target_available_regs[otype], - allocated_regs, 0, + allocated_regs, preferred_regs, ots->indirect_base); } tcg_out_mov(s, otype, ots->reg, ts->reg); @@ -3324,7 +3328,7 @@ static void tcg_reg_alloc_op(TCGContext *s, const TCGOp *op) } else if (arg_ct->ct & TCG_CT_NEWREG) { reg = tcg_reg_alloc(s, arg_ct->u.regs, i_allocated_regs | o_allocated_regs, -0, ts->indirect_base); +op->output_pref[k], ts->indirect_base); } else { /* if fixed register, we try to use it */ reg = ts->reg; @@ -,7 +3337,7 @@ static void tcg_reg_alloc_op(TCGContext *s, const TCGOp *op) goto oarg_end; } reg = tcg_reg_alloc(s, arg_ct->u.regs, o_allocated_regs, -0, ts->indirect_base); +op->output_pref[k], ts->indirect_base); } tcg_regset_set_reg(o_allocated_regs, reg); /* if a fixed register is used, then a move will be done afterwards */ -- 2.17.2
[Qemu-devel] [PATCH 04/12] tcg: Add preferred_reg argument to tcg_reg_alloc_do_movi
Pass this through to temp_sync. Signed-off-by: Richard Henderson --- tcg/tcg.c | 9 + 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/tcg/tcg.c b/tcg/tcg.c index 509e5974bd..c83ca238aa 100644 --- a/tcg/tcg.c +++ b/tcg/tcg.c @@ -3099,7 +3099,8 @@ static void tcg_reg_alloc_bb_end(TCGContext *s, TCGRegSet allocated_regs) } static void tcg_reg_alloc_do_movi(TCGContext *s, TCGTemp *ots, - tcg_target_ulong val, TCGLifeData arg_life) + tcg_target_ulong val, TCGLifeData arg_life, + TCGRegSet preferred_regs) { if (ots->fixed_reg) { /* For fixed registers, we do not do any constant propagation. */ @@ -3115,7 +3116,7 @@ static void tcg_reg_alloc_do_movi(TCGContext *s, TCGTemp *ots, ots->val = val; ots->mem_coherent = 0; if (NEED_SYNC_ARG(0)) { -temp_sync(s, ots, s->reserved_regs, 0, IS_DEAD_ARG(0)); +temp_sync(s, ots, s->reserved_regs, preferred_regs, IS_DEAD_ARG(0)); } else if (IS_DEAD_ARG(0)) { temp_dead(s, ots); } @@ -3126,7 +3127,7 @@ static void tcg_reg_alloc_movi(TCGContext *s, const TCGOp *op) TCGTemp *ots = arg_temp(op->args[0]); tcg_target_ulong val = op->args[1]; -tcg_reg_alloc_do_movi(s, ots, val, op->life); +tcg_reg_alloc_do_movi(s, ots, val, op->life, 0); } static void tcg_reg_alloc_mov(TCGContext *s, const TCGOp *op) @@ -3150,7 +3151,7 @@ static void tcg_reg_alloc_mov(TCGContext *s, const TCGOp *op) if (IS_DEAD_ARG(1)) { temp_dead(s, ts); } -tcg_reg_alloc_do_movi(s, ots, val, arg_life); +tcg_reg_alloc_do_movi(s, ots, val, arg_life, 0); return; } -- 2.17.2
[Qemu-devel] [PATCH 06/12] tcg: Improve register allocation for matching constraints
Try harder to honor the output_pref. When we're forced to allocate a second register for the input, it does not need to use the input constraint; that will be honored by the register we allocate for the output and a move is already required. Signed-off-by: Richard Henderson --- tcg/tcg.c | 36 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/tcg/tcg.c b/tcg/tcg.c index f86415ce29..adf6570c36 100644 --- a/tcg/tcg.c +++ b/tcg/tcg.c @@ -3235,6 +3235,8 @@ static void tcg_reg_alloc_op(TCGContext *s, const TCGOp *op) /* satisfy input constraints */ for (k = 0; k < nb_iargs; k++) { +TCGRegSet i_preferred_regs, o_preferred_regs; + i = def->sorted_args[nb_oargs + k]; arg = op->args[i]; arg_ct = &def->args_ct[i]; @@ -3245,17 +3247,18 @@ static void tcg_reg_alloc_op(TCGContext *s, const TCGOp *op) /* constant is OK for instruction */ const_args[i] = 1; new_args[i] = ts->val; -goto iarg_end; +continue; } -temp_load(s, ts, arg_ct->u.regs, i_allocated_regs, 0); - +i_preferred_regs = o_preferred_regs = 0; if (arg_ct->ct & TCG_CT_IALIAS) { +o_preferred_regs = op->output_pref[arg_ct->alias_index]; if (ts->fixed_reg) { /* if fixed register, we must allocate a new register if the alias is not the same register */ -if (arg != op->args[arg_ct->alias_index]) +if (arg != op->args[arg_ct->alias_index]) { goto allocate_in_reg; +} } else { /* if the input is aliased to an output and if it is not dead after the instruction, we must allocate @@ -3263,33 +3266,42 @@ static void tcg_reg_alloc_op(TCGContext *s, const TCGOp *op) if (!IS_DEAD_ARG(i)) { goto allocate_in_reg; } + /* check if the current register has already been allocated for another input aliased to an output */ -int k2, i2; -for (k2 = 0 ; k2 < k ; k2++) { -i2 = def->sorted_args[nb_oargs + k2]; -if ((def->args_ct[i2].ct & TCG_CT_IALIAS) && -(new_args[i2] == ts->reg)) { -goto allocate_in_reg; +if (ts->val_type == TEMP_VAL_REG) { +int k2, i2; +reg = ts->reg; +for (k2 = 0 ; k2 < k ; k2++) { +i2 = def->sorted_args[nb_oargs + k2]; +if ((def->args_ct[i2].ct & TCG_CT_IALIAS) && +reg == new_args[i2]) { +goto allocate_in_reg; +} } } +i_preferred_regs = o_preferred_regs; } } + +temp_load(s, ts, arg_ct->u.regs, i_allocated_regs, i_preferred_regs); reg = ts->reg; + if (tcg_regset_test_reg(arg_ct->u.regs, reg)) { /* nothing to do : the constraint is satisfied */ } else { allocate_in_reg: /* allocate a new register matching the constraint and move the temporary register into it */ +temp_load(s, ts, tcg_target_available_regs[ts->type], + i_allocated_regs, 0); reg = tcg_reg_alloc(s, arg_ct->u.regs, i_allocated_regs, -0, ts->indirect_base); +o_preferred_regs, ts->indirect_base); tcg_out_mov(s, ts->type, reg, ts->reg); } new_args[i] = reg; const_args[i] = 0; tcg_regset_set_reg(i_allocated_regs, reg); -iarg_end: ; } /* mark dead temporaries and free the associated registers */ -- 2.17.2
[Qemu-devel] [PATCH 03/12] tcg: Add preferred_reg argument to temp_sync
Pass this through to tcg_reg_alloc. Signed-off-by: Richard Henderson --- tcg/tcg.c | 16 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/tcg/tcg.c b/tcg/tcg.c index 7f29a2045a..509e5974bd 100644 --- a/tcg/tcg.c +++ b/tcg/tcg.c @@ -2887,8 +2887,8 @@ static inline void temp_dead(TCGContext *s, TCGTemp *ts) registers needs to be allocated to store a constant. If 'free_or_dead' is non-zero, subsequently release the temporary; if it is positive, the temp is dead; if it is negative, the temp is free. */ -static void temp_sync(TCGContext *s, TCGTemp *ts, - TCGRegSet allocated_regs, int free_or_dead) +static void temp_sync(TCGContext *s, TCGTemp *ts, TCGRegSet allocated_regs, + TCGRegSet preferred_regs, int free_or_dead) { if (ts->fixed_reg) { return; @@ -2908,7 +2908,7 @@ static void temp_sync(TCGContext *s, TCGTemp *ts, break; } temp_load(s, ts, tcg_target_available_regs[ts->type], - allocated_regs, 0); + allocated_regs, preferred_regs); /* fallthrough */ case TEMP_VAL_REG: @@ -2935,7 +2935,7 @@ static void tcg_reg_free(TCGContext *s, TCGReg reg, TCGRegSet allocated_regs) { TCGTemp *ts = s->reg_to_temp[reg]; if (ts != NULL) { -temp_sync(s, ts, allocated_regs, -1); +temp_sync(s, ts, allocated_regs, 0, -1); } } @@ -3115,7 +3115,7 @@ static void tcg_reg_alloc_do_movi(TCGContext *s, TCGTemp *ots, ots->val = val; ots->mem_coherent = 0; if (NEED_SYNC_ARG(0)) { -temp_sync(s, ots, s->reserved_regs, IS_DEAD_ARG(0)); +temp_sync(s, ots, s->reserved_regs, 0, IS_DEAD_ARG(0)); } else if (IS_DEAD_ARG(0)) { temp_dead(s, ots); } @@ -3198,7 +3198,7 @@ static void tcg_reg_alloc_mov(TCGContext *s, const TCGOp *op) ots->mem_coherent = 0; s->reg_to_temp[ots->reg] = ots; if (NEED_SYNC_ARG(0)) { -temp_sync(s, ots, allocated_regs, 0); +temp_sync(s, ots, allocated_regs, 0, 0); } } } @@ -3368,7 +3368,7 @@ static void tcg_reg_alloc_op(TCGContext *s, const TCGOp *op) tcg_out_mov(s, ts->type, ts->reg, reg); } if (NEED_SYNC_ARG(i)) { -temp_sync(s, ts, o_allocated_regs, IS_DEAD_ARG(i)); +temp_sync(s, ts, o_allocated_regs, 0, IS_DEAD_ARG(i)); } else if (IS_DEAD_ARG(i)) { temp_dead(s, ts); } @@ -3502,7 +3502,7 @@ static void tcg_reg_alloc_call(TCGContext *s, TCGOp *op) ts->mem_coherent = 0; s->reg_to_temp[reg] = ts; if (NEED_SYNC_ARG(i)) { -temp_sync(s, ts, allocated_regs, IS_DEAD_ARG(i)); +temp_sync(s, ts, allocated_regs, 0, IS_DEAD_ARG(i)); } else if (IS_DEAD_ARG(i)) { temp_dead(s, ts); } -- 2.17.2
[Qemu-devel] [PATCH 00/12] tcg: Improve register allocation for calls
The intent here is to remove several move insns putting the function arguments into the proper place. I'm hoping that this will solve the skylake regression with spec2006, as seen with the ool softmmu patch set. Emilio, all of this is present on my tcg-next-for-4.0 branch. r~ Richard Henderson (12): tcg: Add preferred_reg argument to tcg_reg_alloc tcg: Add preferred_reg argument to temp_load tcg: Add preferred_reg argument to temp_sync tcg: Add preferred_reg argument to tcg_reg_alloc_do_movi tcg: Add output_pref to TCGOp tcg: Improve register allocation for matching constraints tcg: Dump register preference info with liveness tcg: Reindent parts of liveness_pass_1 tcg: Rename and adjust liveness_pass_1 helpers tcg: Split out more subroutines from liveness_pass_1 tcg: Add TCG_OPF_BB_EXIT tcg: Record register preferences during liveness tcg/tcg-opc.h | 7 +- tcg/tcg.h | 20 +- tcg/tcg.c | 527 +- 3 files changed, 405 insertions(+), 149 deletions(-) -- 2.17.2
[Qemu-devel] [PATCH 01/12] tcg: Add preferred_reg argument to tcg_reg_alloc
This new argument will aid register allocation by indicating how the temporary will be used in future. If the preference cannot be satisfied, fall back to the constraints of the current insn. Short circuit the preference when it cannot be satisfied or if it does not further constrain the operation. With an eye toward optimizing function call sequences, optimize for the preferred_reg set containing a single register. For the moment, all users pass 0 for preference. Signed-off-by: Richard Henderson --- tcg/tcg.c | 103 ++ 1 file changed, 81 insertions(+), 22 deletions(-) diff --git a/tcg/tcg.c b/tcg/tcg.c index 8734389ba9..c596277fd0 100644 --- a/tcg/tcg.c +++ b/tcg/tcg.c @@ -1907,6 +1907,20 @@ static const char * const alignment_name[(MO_AMASK >> MO_ASHIFT) + 1] = { [MO_ALIGN_64 >> MO_ASHIFT] = "al64+", }; +static inline bool tcg_regset_single(TCGRegSet d) +{ +return (d & (d - 1)) == 0; +} + +static inline TCGReg tcg_regset_first(TCGRegSet d) +{ +if (TCG_TARGET_NB_REGS <= 32) { +return ctz32(d); +} else { +return ctz64(d); +} +} + void tcg_dump_ops(TCGContext *s) { char buf[128]; @@ -1922,6 +1936,7 @@ void tcg_dump_ops(TCGContext *s) def = &tcg_op_defs[c]; if (c == INDEX_op_insn_start) { +nb_oargs = 0; col += qemu_log("\n "); for (i = 0; i < TARGET_INSN_START_WORDS; ++i) { @@ -2924,31 +2939,72 @@ static void tcg_reg_free(TCGContext *s, TCGReg reg, TCGRegSet allocated_regs) } } -/* Allocate a register belonging to reg1 & ~reg2 */ -static TCGReg tcg_reg_alloc(TCGContext *s, TCGRegSet desired_regs, -TCGRegSet allocated_regs, bool rev) +/** + * tcg_reg_alloc: + * @required_regs: Set of registers in which we must allocate. + * @allocated_regs: Set of registers which must be avoided. + * @preferred_regs: Set of registers we should prefer. + * @rev: True if we search the registers in "indirect" order. + * + * The allocated register must be in @required_regs & ~@allocated_regs, + * but if we can put it in @preferred_regs we may save a move later. + */ +static TCGReg tcg_reg_alloc(TCGContext *s, TCGRegSet required_regs, +TCGRegSet allocated_regs, +TCGRegSet preferred_regs, bool rev) { -int i, n = ARRAY_SIZE(tcg_target_reg_alloc_order); +int i, j, f, n = ARRAY_SIZE(tcg_target_reg_alloc_order); +TCGRegSet reg_ct[2]; const int *order; -TCGReg reg; -TCGRegSet reg_ct; -reg_ct = desired_regs & ~allocated_regs; +reg_ct[1] = required_regs & ~allocated_regs; +tcg_debug_assert(reg_ct[1] != 0); +reg_ct[0] = reg_ct[1] & preferred_regs; + +/* Skip the preferred_regs option if it cannot be satisfied, + or if the preference made no difference. */ +f = reg_ct[0] == 0 || reg_ct[0] == reg_ct[1]; + order = rev ? indirect_reg_alloc_order : tcg_target_reg_alloc_order; -/* first try free registers */ -for(i = 0; i < n; i++) { -reg = order[i]; -if (tcg_regset_test_reg(reg_ct, reg) && s->reg_to_temp[reg] == NULL) -return reg; +/* Try free registers, preferences first. */ +for (j = f; j < 2; j++) { +TCGRegSet set = reg_ct[j]; + +if (tcg_regset_single(set)) { +/* One register in the set. */ +TCGReg reg = tcg_regset_first(set); +if (s->reg_to_temp[reg] == NULL) { +return reg; +} +} else { +for (i = 0; i < n; i++) { +TCGReg reg = order[i]; +if (s->reg_to_temp[reg] == NULL && +tcg_regset_test_reg(set, reg)) { +return reg; +} +} +} } -/* XXX: do better spill choice */ -for(i = 0; i < n; i++) { -reg = order[i]; -if (tcg_regset_test_reg(reg_ct, reg)) { +/* We must spill something. */ +for (j = f; j < 2; j++) { +TCGRegSet set = reg_ct[j]; + +if (tcg_regset_single(set)) { +/* One register in the set. */ +TCGReg reg = tcg_regset_first(set); tcg_reg_free(s, reg, allocated_regs); return reg; +} else { +for (i = 0; i < n; i++) { +TCGReg reg = order[i]; +if (tcg_regset_test_reg(set, reg)) { +tcg_reg_free(s, reg, allocated_regs); +return reg; +} +} } } @@ -2966,12 +3022,14 @@ static void temp_load(TCGContext *s, TCGTemp *ts, TCGRegSet desired_regs, case TEMP_VAL_REG: return; case TEMP_VAL_CONST: -reg = tcg_reg_alloc(s, desired_regs, allocated_regs, ts->indirect_base); +reg = tcg_reg_alloc(s, desired_regs, allocated_regs, +0, ts->indirect_base); tcg_out_movi(s, ts->type,
[Qemu-devel] [PATCH 11/12] tcg: Add TCG_OPF_BB_EXIT
Use this to notice the opcodes that exit the TB, which implies that local temps are really dead and need not be synced. Previously we so marked the true end of the TB, but that was immediately overwritten by the la_bb_end invoked by any TCG_OPF_BB_END opcode, like exit_tb. Signed-off-by: Richard Henderson --- tcg/tcg-opc.h | 7 --- tcg/tcg.h | 14 -- tcg/tcg.c | 5 - 3 files changed, 16 insertions(+), 10 deletions(-) diff --git a/tcg/tcg-opc.h b/tcg/tcg-opc.h index e3a43aabb6..7a8a3edb5b 100644 --- a/tcg/tcg-opc.h +++ b/tcg/tcg-opc.h @@ -191,9 +191,10 @@ DEF(mulsh_i64, 1, 2, 0, IMPL64 | IMPL(TCG_TARGET_HAS_mulsh_i64)) /* QEMU specific */ DEF(insn_start, 0, 0, TLADDR_ARGS * TARGET_INSN_START_WORDS, TCG_OPF_NOT_PRESENT) -DEF(exit_tb, 0, 0, 1, TCG_OPF_BB_END) -DEF(goto_tb, 0, 0, 1, TCG_OPF_BB_END) -DEF(goto_ptr, 0, 1, 0, TCG_OPF_BB_END | IMPL(TCG_TARGET_HAS_goto_ptr)) +DEF(exit_tb, 0, 0, 1, TCG_OPF_BB_EXIT | TCG_OPF_BB_END) +DEF(goto_tb, 0, 0, 1, TCG_OPF_BB_EXIT | TCG_OPF_BB_END) +DEF(goto_ptr, 0, 1, 0, +TCG_OPF_BB_EXIT | TCG_OPF_BB_END | IMPL(TCG_TARGET_HAS_goto_ptr)) DEF(qemu_ld_i32, 1, TLADDR_ARGS, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS) diff --git a/tcg/tcg.h b/tcg/tcg.h index ac5d01c223..abbf9c836a 100644 --- a/tcg/tcg.h +++ b/tcg/tcg.h @@ -1037,20 +1037,22 @@ typedef struct TCGArgConstraint { /* Bits for TCGOpDef->flags, 8 bits available. */ enum { +/* Instruction exits the translation block. */ +TCG_OPF_BB_EXIT = 0x01, /* Instruction defines the end of a basic block. */ -TCG_OPF_BB_END = 0x01, +TCG_OPF_BB_END = 0x02, /* Instruction clobbers call registers and potentially update globals. */ -TCG_OPF_CALL_CLOBBER = 0x02, +TCG_OPF_CALL_CLOBBER = 0x04, /* Instruction has side effects: it cannot be removed if its outputs are not used, and might trigger exceptions. */ -TCG_OPF_SIDE_EFFECTS = 0x04, +TCG_OPF_SIDE_EFFECTS = 0x08, /* Instruction operands are 64-bits (otherwise 32-bits). */ -TCG_OPF_64BIT= 0x08, +TCG_OPF_64BIT= 0x10, /* Instruction is optional and not implemented by the host, or insn is generic and should not be implemened by the host. */ -TCG_OPF_NOT_PRESENT = 0x10, +TCG_OPF_NOT_PRESENT = 0x20, /* Instruction operands are vectors. */ -TCG_OPF_VECTOR = 0x20, +TCG_OPF_VECTOR = 0x40, }; typedef struct TCGOpDef { diff --git a/tcg/tcg.c b/tcg/tcg.c index 21668831a1..673aaf52a1 100644 --- a/tcg/tcg.c +++ b/tcg/tcg.c @@ -2446,6 +2446,7 @@ static void liveness_pass_1(TCGContext *s) int nb_temps = s->nb_temps; TCGOp *op, *op_prev; +/* ??? Should be redundant with the exit_tb that ends the TB. */ la_func_end(s, nb_globals, nb_temps); QTAILQ_FOREACH_REVERSE_SAFE(op, &s->ops, TCGOpHead, link, op_prev) { @@ -2634,7 +2635,9 @@ static void liveness_pass_1(TCGContext *s) } /* if end of basic block, update */ -if (def->flags & TCG_OPF_BB_END) { +if (def->flags & TCG_OPF_BB_EXIT) { +la_func_end(s, nb_globals, nb_temps); +} else if (def->flags & TCG_OPF_BB_END) { la_bb_end(s, nb_globals, nb_temps); } else if (def->flags & TCG_OPF_SIDE_EFFECTS) { la_global_sync(s, nb_globals); -- 2.17.2
Re: [Qemu-devel] [PATCH v9 5/8] migration/ram.c: add a notifier chain for precopy
On Tue, Nov 27, 2018 at 06:25:40PM +0800, Wei Wang wrote: > On 11/27/2018 03:38 PM, Peter Xu wrote: > > On Thu, Nov 15, 2018 at 06:08:01PM +0800, Wei Wang wrote: > > > +typedef enum PrecopyNotifyReason { > > > +PRECOPY_NOTIFY_ERR = 0, > > > +PRECOPY_NOTIFY_START_ITERATION = 1, > > > +PRECOPY_NOTIFY_BEFORE_SYNC_BITMAP = 2, > > > +PRECOPY_NOTIFY_AFTER_SYNC_BITMAP = 3, > > > +PRECOPY_NOTIFY_MAX = 4, > > It would be nice to add some comments for each of the notify reason. > > E.g., from the name PRECOPY_NOTIFY_START_ITERATION seems more like a > > hook at the start of each iteration but according to [1] it should be > > at the start of migration rather than each iteration (or when > > migration restarts, though I'm not sure whether we really have this > > yet). > > OK. I think It would be better if the name itself could be straightforward. > Probably we could change PRECOPY_NOTIFY_START_ITERATION to > PRECOPY_NOTIFY_START_MIGRATION. Sounds good. > > > > > +} PrecopyNotifyReason; > > > + > > > +void precopy_infrastructure_init(void); > > > +void precopy_add_notifier(Notifier *n); > > > +void precopy_remove_notifier(Notifier *n); > > > + > > > void ram_mig_init(void); > > > void qemu_guest_free_page_hint(void *addr, size_t len); > > > diff --git a/migration/ram.c b/migration/ram.c > > > index 229b791..65b1223 100644 > > > --- a/migration/ram.c > > > +++ b/migration/ram.c > > > @@ -292,6 +292,8 @@ struct RAMState { > > > bool ram_bulk_stage; > > > /* How many times we have dirty too many pages */ > > > int dirty_rate_high_cnt; > > > +/* ram save states used for notifiers */ > > > +int ram_save_state; > > This can be removed? > > Yes, thanks. > > > > > > /* these variables are used for bitmap sync */ > > > /* last time we did a full bitmap_sync */ > > > int64_t time_last_bitmap_sync; > > > @@ -328,6 +330,28 @@ typedef struct RAMState RAMState; > > > static RAMState *ram_state; > > > +static NotifierList precopy_notifier_list; > > > + > > > +void precopy_infrastructure_init(void) > > > +{ > > > +notifier_list_init(&precopy_notifier_list); > > > +} > > > + > > > +void precopy_add_notifier(Notifier *n) > > > +{ > > > +notifier_list_add(&precopy_notifier_list, n); > > > +} > > > + > > > +void precopy_remove_notifier(Notifier *n) > > > +{ > > > +notifier_remove(n); > > > +} > > > + > > > +static void precopy_notify(PrecopyNotifyReason reason) > > > +{ > > > +notifier_list_notify(&precopy_notifier_list, &reason); > > > +} > > > + > > > uint64_t ram_bytes_remaining(void) > > > { > > > return ram_state ? (ram_state->migration_dirty_pages * > > > TARGET_PAGE_SIZE) : > > > @@ -1642,6 +1666,8 @@ static void migration_bitmap_sync(RAMState *rs) > > > int64_t end_time; > > > uint64_t bytes_xfer_now; > > > +precopy_notify(PRECOPY_NOTIFY_BEFORE_SYNC_BITMAP); > > > + > > > ram_counters.dirty_sync_count++; > > > if (!rs->time_last_bitmap_sync) { > > > @@ -1699,6 +1725,8 @@ static void migration_bitmap_sync(RAMState *rs) > > > if (migrate_use_events()) { > > > qapi_event_send_migration_pass(ram_counters.dirty_sync_count); > > > } > > > + > > > +precopy_notify(PRECOPY_NOTIFY_AFTER_SYNC_BITMAP); > > > } > > > /** > > > @@ -2555,6 +2583,8 @@ static void ram_state_reset(RAMState *rs) > > > rs->last_page = 0; > > > rs->last_version = ram_list.version; > > > rs->ram_bulk_stage = true; > > > + > > > +precopy_notify(PRECOPY_NOTIFY_START_ITERATION); > > [1] > > > > > } > > > #define MAX_WAIT 50 /* ms, half buffered_file limit */ > > > @@ -3324,6 +3354,7 @@ out: > > > ret = qemu_file_get_error(f); > > > if (ret < 0) { > > > +precopy_notify(PRECOPY_NOTIFY_ERR); > > Could you show me which function is this line in? > > > > Line 3324 here is ram_save_complete(), but I cannot find this exact > > place. > > Sure, it's in ram_save_iterate(): > ... > out: > qemu_put_be64(f, RAM_SAVE_FLAG_EOS); > qemu_fflush(f); > ram_counters.transferred += 8; > > ret = qemu_file_get_error(f); > if (ret < 0) { > +precopy_notify(PRECOPY_NOTIFY_ERR); > return ret; > } > > return done; > } Ok thanks. Please just make sure you will capture all the error cases, e.g., I also see path like this (a few lines below): if (pages < 0) { qemu_file_set_error(f, pages); break; } It seems that you missed that one. I would even suggest that you capture the error with higher level. E.g., in migration_iteration_run() after qemu_savevm_state_iterate(). Or we can just check the return value of qemu_savevm_state_iterate(), which we have had ignored so far. [1] > > > > > > Another thing to mention about the "reasons" (though I see it more > > like "events"): have you thought about adding a PRECOPY_NOTIFY_END? > > It might help in some cases: > > > >- then you don't need to trickily
Re: [Qemu-devel] [PATCH v5 20/36] spapr: add classes for the XIVE models
On Fri, Nov 16, 2018 at 11:57:13AM +0100, Cédric Le Goater wrote: > The XIVE models for the QEMU and KVM accelerators will have a lot in > common. Introduce an abstract class for the source, the thread context > and the interrupt controller object to handle the differences in the > object initialization. These classes will also be used to define state > synchronization handlers for the monitor and migration usage. > > This is very much like the XICS models. Yeah.. so I know it's my code, but in hindsight I think making separate subclasses for TCG and KVM was a mistake. The distinction between emulated and KVM version is supposed to be invisible to both guest and (almost) to user, whereas a subclass usually indicates a visibly different device. > Signed-off-by: Cédric Le Goater > --- > include/hw/ppc/spapr_xive.h | 15 + > include/hw/ppc/xive.h | 30 ++ > hw/intc/spapr_xive.c| 86 +++- > hw/intc/xive.c | 109 +--- > hw/ppc/spapr_irq.c | 4 +- > 5 files changed, 182 insertions(+), 62 deletions(-) > > diff --git a/include/hw/ppc/spapr_xive.h b/include/hw/ppc/spapr_xive.h > index 5b3fab192d41..aca2969a09ab 100644 > --- a/include/hw/ppc/spapr_xive.h > +++ b/include/hw/ppc/spapr_xive.h > @@ -13,6 +13,10 @@ > #include "hw/sysbus.h" > #include "hw/ppc/xive.h" > > +#define TYPE_SPAPR_XIVE_BASE "spapr-xive-base" > +#define SPAPR_XIVE_BASE(obj) \ > +OBJECT_CHECK(sPAPRXive, (obj), TYPE_SPAPR_XIVE_BASE) > + > #define TYPE_SPAPR_XIVE "spapr-xive" > #define SPAPR_XIVE(obj) OBJECT_CHECK(sPAPRXive, (obj), TYPE_SPAPR_XIVE) > > @@ -38,6 +42,17 @@ typedef struct sPAPRXive { > MemoryRegion tm_mmio; > } sPAPRXive; > > +#define SPAPR_XIVE_BASE_CLASS(klass) \ > + OBJECT_CLASS_CHECK(sPAPRXiveClass, (klass), TYPE_SPAPR_XIVE_BASE) > +#define SPAPR_XIVE_BASE_GET_CLASS(obj) \ > + OBJECT_GET_CLASS(sPAPRXiveClass, (obj), TYPE_SPAPR_XIVE_BASE) > + > +typedef struct sPAPRXiveClass { > +XiveRouterClass parent_class; > + > +DeviceRealize parent_realize; > +} sPAPRXiveClass; > + > bool spapr_xive_irq_enable(sPAPRXive *xive, uint32_t lisn, bool lsi); > bool spapr_xive_irq_disable(sPAPRXive *xive, uint32_t lisn); > void spapr_xive_pic_print_info(sPAPRXive *xive, Monitor *mon); > diff --git a/include/hw/ppc/xive.h b/include/hw/ppc/xive.h > index b74eb326dcd1..281ed370121c 100644 > --- a/include/hw/ppc/xive.h > +++ b/include/hw/ppc/xive.h > @@ -38,6 +38,10 @@ typedef struct XiveFabricClass { > * XIVE Interrupt Source > */ > > +#define TYPE_XIVE_SOURCE_BASE "xive-source-base" > +#define XIVE_SOURCE_BASE(obj) \ > +OBJECT_CHECK(XiveSource, (obj), TYPE_XIVE_SOURCE_BASE) > + > #define TYPE_XIVE_SOURCE "xive-source" > #define XIVE_SOURCE(obj) OBJECT_CHECK(XiveSource, (obj), TYPE_XIVE_SOURCE) > > @@ -68,6 +72,18 @@ typedef struct XiveSource { > XiveFabric *xive; > } XiveSource; > > +#define XIVE_SOURCE_BASE_CLASS(klass) \ > + OBJECT_CLASS_CHECK(XiveSourceClass, (klass), TYPE_XIVE_SOURCE_BASE) > +#define XIVE_SOURCE_BASE_GET_CLASS(obj) \ > + OBJECT_GET_CLASS(XiveSourceClass, (obj), TYPE_XIVE_SOURCE_BASE) > + > +typedef struct XiveSourceClass { > +SysBusDeviceClass parent_class; > + > +DeviceRealize parent_realize; > +DeviceReset parent_reset; > +} XiveSourceClass; > + > /* > * ESB MMIO setting. Can be one page, for both source triggering and > * source management, or two different pages. See below for magic > @@ -253,6 +269,9 @@ void xive_end_pic_print_info(XiveEND *end, uint32_t > end_idx, Monitor *mon); > * XIVE Thread interrupt Management (TM) context > */ > > +#define TYPE_XIVE_TCTX_BASE "xive-tctx-base" > +#define XIVE_TCTX_BASE(obj) OBJECT_CHECK(XiveTCTX, (obj), > TYPE_XIVE_TCTX_BASE) > + > #define TYPE_XIVE_TCTX "xive-tctx" > #define XIVE_TCTX(obj) OBJECT_CHECK(XiveTCTX, (obj), TYPE_XIVE_TCTX) > > @@ -278,6 +297,17 @@ typedef struct XiveTCTX { > XiveRouter *xrtr; > } XiveTCTX; > > +#define XIVE_TCTX_BASE_CLASS(klass) \ > + OBJECT_CLASS_CHECK(XiveTCTXClass, (klass), TYPE_XIVE_TCTX_BASE) > +#define XIVE_TCTX_BASE_GET_CLASS(obj) \ > + OBJECT_GET_CLASS(XiveTCTXClass, (obj), TYPE_XIVE_TCTX_BASE) > + > +typedef struct XiveTCTXClass { > +DeviceClass parent_class; > + > +DeviceRealize parent_realize; > +} XiveTCTXClass; > + > /* > * XIVE Thread Interrupt Management Aera (TIMA) > */ > diff --git a/hw/intc/spapr_xive.c b/hw/intc/spapr_xive.c > index 3bf77ace11a2..ec85f7e4f88d 100644 > --- a/hw/intc/spapr_xive.c > +++ b/hw/intc/spapr_xive.c > @@ -53,9 +53,9 @@ static void spapr_xive_mmio_map(sPAPRXive *xive) > sysbus_mmio_map(SYS_BUS_DEVICE(xive), 0, xive->tm_base); > } > > -static void spapr_xive_reset(DeviceState *dev) > +static void spapr_xive_base_reset(DeviceState *dev) > { > -sPAPRXive *xive = SPAPR_XIVE(dev); > +sPAPRXive *xive = SPAPR_XIVE_BASE(dev); > int i; >
Re: [Qemu-devel] [PATCH v5 18/36] spapr: allocate the interrupt thread context under the CPU core
On Fri, Nov 16, 2018 at 11:57:11AM +0100, Cédric Le Goater wrote: > Each interrupt mode has its own specific interrupt presenter object, > that we store under the CPU object, one for XICS and one for XIVE. > > Extend the sPAPR IRQ backend with a new handler to support them both. > > Signed-off-by: Cédric Le Goater Reviewed-by: David Gibson > --- > include/hw/ppc/spapr.h | 1 + > include/hw/ppc/spapr_irq.h | 2 ++ > include/hw/ppc/xive.h | 2 ++ > hw/intc/xive.c | 21 + > hw/ppc/spapr_cpu_core.c| 5 ++--- > hw/ppc/spapr_irq.c | 17 + > 6 files changed, 45 insertions(+), 3 deletions(-) > > diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h > index 8415faea7b82..f43ef69d61bc 100644 > --- a/include/hw/ppc/spapr.h > +++ b/include/hw/ppc/spapr.h > @@ -177,6 +177,7 @@ struct sPAPRMachineState { > int32_t irq_map_nr; > unsigned long *irq_map; > sPAPRXive *xive; > +const char *xive_tctx_type; > > bool cmd_line_caps[SPAPR_CAP_NUM]; > sPAPRCapabilities def, eff, mig; > diff --git a/include/hw/ppc/spapr_irq.h b/include/hw/ppc/spapr_irq.h > index cfdc1f86e713..c3b4c38145eb 100644 > --- a/include/hw/ppc/spapr_irq.h > +++ b/include/hw/ppc/spapr_irq.h > @@ -42,6 +42,8 @@ typedef struct sPAPRIrq { > void (*print_info)(sPAPRMachineState *spapr, Monitor *mon); > void (*dt_populate)(sPAPRMachineState *spapr, uint32_t nr_servers, > void *fdt, uint32_t phandle); > +Object *(*cpu_intc_create)(sPAPRMachineState *spapr, Object *cpu, > + Error **errp); > } sPAPRIrq; > > extern sPAPRIrq spapr_irq_xics; > diff --git a/include/hw/ppc/xive.h b/include/hw/ppc/xive.h > index e6931ddaa83f..b74eb326dcd1 100644 > --- a/include/hw/ppc/xive.h > +++ b/include/hw/ppc/xive.h > @@ -284,6 +284,8 @@ typedef struct XiveTCTX { > extern const MemoryRegionOps xive_tm_ops; > > void xive_tctx_pic_print_info(XiveTCTX *tctx, Monitor *mon); > +Object *xive_tctx_create(Object *cpu, const char *type, XiveRouter *xrtr, > + Error **errp); > > static inline uint32_t xive_tctx_cam_line(uint8_t nvt_blk, uint32_t nvt_idx) > { > diff --git a/hw/intc/xive.c b/hw/intc/xive.c > index fc6ef5895e6d..7d921023e2ee 100644 > --- a/hw/intc/xive.c > +++ b/hw/intc/xive.c > @@ -579,6 +579,27 @@ static const TypeInfo xive_tctx_info = { > .class_init= xive_tctx_class_init, > }; > > +Object *xive_tctx_create(Object *cpu, const char *type, XiveRouter *xrtr, > + Error **errp) > +{ > +Error *local_err = NULL; > +Object *obj; > + > +obj = object_new(type); > +object_property_add_child(cpu, type, obj, &error_abort); > +object_unref(obj); > +object_property_add_const_link(obj, "cpu", cpu, &error_abort); > +object_property_add_const_link(obj, "xive", OBJECT(xrtr), &error_abort); > +object_property_set_bool(obj, true, "realized", &local_err); > +if (local_err) { > +object_unparent(obj); > +error_propagate(errp, local_err); > +return NULL; > +} > + > +return obj; > +} > + > /* > * XIVE ESB helpers > */ > diff --git a/hw/ppc/spapr_cpu_core.c b/hw/ppc/spapr_cpu_core.c > index 2398ce62c0e7..1811cd48db90 100644 > --- a/hw/ppc/spapr_cpu_core.c > +++ b/hw/ppc/spapr_cpu_core.c > @@ -11,7 +11,6 @@ > #include "hw/ppc/spapr_cpu_core.h" > #include "target/ppc/cpu.h" > #include "hw/ppc/spapr.h" > -#include "hw/ppc/xics.h" /* for icp_create() - to be removed */ > #include "hw/boards.h" > #include "qapi/error.h" > #include "sysemu/cpus.h" > @@ -215,6 +214,7 @@ static void spapr_cpu_core_unrealize(DeviceState *dev, > Error **errp) > static void spapr_realize_vcpu(PowerPCCPU *cpu, sPAPRMachineState *spapr, > sPAPRCPUCore *sc, Error **errp) > { > +sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr); > CPUPPCState *env = &cpu->env; > CPUState *cs = CPU(cpu); > Error *local_err = NULL; > @@ -233,8 +233,7 @@ static void spapr_realize_vcpu(PowerPCCPU *cpu, > sPAPRMachineState *spapr, > qemu_register_reset(spapr_cpu_reset, cpu); > spapr_cpu_reset(cpu); > > -cpu->intc = icp_create(OBJECT(cpu), spapr->icp_type, XICS_FABRIC(spapr), > - &local_err); > +cpu->intc = smc->irq->cpu_intc_create(spapr, OBJECT(cpu), &local_err); > if (local_err) { > goto error_unregister; > } > diff --git a/hw/ppc/spapr_irq.c b/hw/ppc/spapr_irq.c > index d88a029d8c5c..253abc10e780 100644 > --- a/hw/ppc/spapr_irq.c > +++ b/hw/ppc/spapr_irq.c > @@ -197,6 +197,12 @@ static void spapr_irq_dt_populate_xics(sPAPRMachineState > *spapr, > spapr_dt_xics(nr_servers, fdt, phandle); > } > > +static Object *spapr_irq_cpu_intc_create_xics(sPAPRMachineState *spapr, > + Object *cpu, Error **errp) > +{ > +return icp_create(cpu, spapr->icp_ty
Re: [Qemu-devel] [PATCH v5 19/36] spapr: add a 'pseries-3.1-xive' machine type
On Fri, Nov 16, 2018 at 11:57:12AM +0100, Cédric Le Goater wrote: > The interrupt mode is statically defined to XIVE only for this machine. > The guest OS is required to have support for the XIVE exploitation > mode of the POWER9 interrupt controller. > > Signed-off-by: Cédric Le Goater > --- > include/hw/ppc/spapr_irq.h | 1 + > hw/ppc/spapr.c | 36 +++- > hw/ppc/spapr_irq.c | 3 +++ > 3 files changed, 35 insertions(+), 5 deletions(-) > > diff --git a/include/hw/ppc/spapr_irq.h b/include/hw/ppc/spapr_irq.h > index c3b4c38145eb..b299dd794bff 100644 > --- a/include/hw/ppc/spapr_irq.h > +++ b/include/hw/ppc/spapr_irq.h > @@ -33,6 +33,7 @@ void spapr_irq_msi_reset(sPAPRMachineState *spapr); > typedef struct sPAPRIrq { > uint32_tnr_irqs; > uint32_tnr_msis; > +uint8_t ov5; I'm a bit confused as to what exactly this represents.. > void (*init)(sPAPRMachineState *spapr, int nr_irqs, int nr_servers, > Error **errp); > diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c > index ad1692cdcd0f..8fbb743769db 100644 > --- a/hw/ppc/spapr.c > +++ b/hw/ppc/spapr.c > @@ -1097,12 +1097,14 @@ static void spapr_dt_rtas(sPAPRMachineState *spapr, > void *fdt) > spapr_dt_rtas_tokens(fdt, rtas); > } > > -/* Prepare ibm,arch-vec-5-platform-support, which indicates the MMU features > - * that the guest may request and thus the valid values for bytes 24..26 of > - * option vector 5: */ > -static void spapr_dt_ov5_platform_support(void *fdt, int chosen) > +/* Prepare ibm,arch-vec-5-platform-support, which indicates the MMU > + * and the XIVE features that the guest may request and thus the valid > + * values for bytes 23..26 of option vector 5: */ > +static void spapr_dt_ov5_platform_support(sPAPRMachineState *spapr, void > *fdt, > + int chosen) > { > PowerPCCPU *first_ppc_cpu = POWERPC_CPU(first_cpu); > +sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr); > > char val[2 * 4] = { > 23, 0x00, /* Xive mode, filled in below. */ > @@ -1123,7 +1125,11 @@ static void spapr_dt_ov5_platform_support(void *fdt, > int chosen) > } else { > val[3] = 0x00; /* Hash */ > } > +/* TODO: test KVM support */ > +val[1] = smc->irq->ov5; > } else { > +val[1] = smc->irq->ov5; ..here it seems to be a specific value for this OV5 byte, indicating the supported intc... > + > /* V3 MMU supports both hash and radix in tcg (with dynamic > switching) */ > val[3] = 0xC0; > } > @@ -1191,7 +1197,7 @@ static void spapr_dt_chosen(sPAPRMachineState *spapr, > void *fdt) > _FDT(fdt_setprop_string(fdt, chosen, "stdout-path", stdout_path)); > } > > -spapr_dt_ov5_platform_support(fdt, chosen); > +spapr_dt_ov5_platform_support(spapr, fdt, chosen); > > g_free(stdout_path); > g_free(bootlist); > @@ -2622,6 +2628,11 @@ static void spapr_machine_init(MachineState *machine) > /* advertise support for ibm,dyamic-memory-v2 */ > spapr_ovec_set(spapr->ov5, OV5_DRMEM_V2); > > +/* advertise XIVE */ > +if (smc->irq->ov5) { ..but here it seems to be a bool indicating XIVE support specifically. > +spapr_ovec_set(spapr->ov5, OV5_XIVE_EXPLOIT); > +} > + > /* init CPUs */ > spapr_init_cpus(spapr); > > @@ -3971,6 +3982,21 @@ static void > spapr_machine_3_1_class_options(MachineClass *mc) > > DEFINE_SPAPR_MACHINE(3_1, "3.1", true); > > +static void spapr_machine_3_1_xive_instance_options(MachineState *machine) > +{ > +spapr_machine_3_1_instance_options(machine); > +} > + > +static void spapr_machine_3_1_xive_class_options(MachineClass *mc) > +{ > +sPAPRMachineClass *smc = SPAPR_MACHINE_CLASS(mc); > + > +spapr_machine_3_1_class_options(mc); > +smc->irq = &spapr_irq_xive; > +} > + > +DEFINE_SPAPR_MACHINE(3_1_xive, "3.1-xive", false); > + > /* > * pseries-3.0 > */ > diff --git a/hw/ppc/spapr_irq.c b/hw/ppc/spapr_irq.c > index 253abc10e780..42e73851b174 100644 > --- a/hw/ppc/spapr_irq.c > +++ b/hw/ppc/spapr_irq.c > @@ -210,6 +210,7 @@ static Object > *spapr_irq_cpu_intc_create_xics(sPAPRMachineState *spapr, > sPAPRIrq spapr_irq_xics = { > .nr_irqs = SPAPR_IRQ_XICS_NR_IRQS, > .nr_msis = SPAPR_IRQ_XICS_NR_MSIS, > +.ov5 = 0x0, /* XICS only */ > > .init= spapr_irq_init_xics, > .claim = spapr_irq_claim_xics, > @@ -341,6 +342,7 @@ static Object > *spapr_irq_cpu_intc_create_xive(sPAPRMachineState *spapr, > sPAPRIrq spapr_irq_xive = { > .nr_irqs = SPAPR_IRQ_XIVE_NR_IRQS, > .nr_msis = SPAPR_IRQ_XIVE_NR_MSIS, > +.ov5 = 0x40, /* XIVE exploitation mode only */ > > .init= spapr_irq_init_xive, > .claim = spapr_irq_claim_xive, > @@ -447,6 +449,7 @@ int spapr_irq_find(sPAPRMachineState *spapr, int num, > bool align, Error **er
Re: [Qemu-devel] [PATCH v5 17/36] spapr: add device tree support for the XIVE exploitation mode
On Fri, Nov 16, 2018 at 11:57:10AM +0100, Cédric Le Goater wrote: > The XIVE interface for the guest is described in the device tree under > the "interrupt-controller" node. A couple of new properties are > specific to XIVE : > > - "reg" > >contains the base address and size of the thread interrupt >managnement areas (TIMA), for the User level and for the Guest OS >level. Only the Guest OS level is taken into account today. > > - "ibm,xive-eq-sizes" > >the size of the event queues. One cell per size supported, contains >log2 of size, in ascending order. > > - "ibm,xive-lisn-ranges" > >the IRQ interrupt number ranges assigned to the guest for the IPIs. > > and also under the root node : > > - "ibm,plat-res-int-priorities" > >contains a list of priorities that the hypervisor has reserved for >its own use. OPAL uses the priority 7 queue to automatically >escalate interrupts for all other queues (DD2.X POWER9). So only >priorities [0..6] are allowed for the guest. > > Extend the sPAPR IRQ backend with a new handler to populate the DT > with the appropriate "interrupt-controller" node. > > Signed-off-by: Cédric Le Goater > --- > include/hw/ppc/spapr_irq.h | 2 ++ > include/hw/ppc/spapr_xive.h | 2 ++ > hw/intc/spapr_xive_hcall.c | 62 + > hw/ppc/spapr.c | 3 +- > hw/ppc/spapr_irq.c | 17 ++ > 5 files changed, 85 insertions(+), 1 deletion(-) > > diff --git a/include/hw/ppc/spapr_irq.h b/include/hw/ppc/spapr_irq.h > index c854ae527808..cfdc1f86e713 100644 > --- a/include/hw/ppc/spapr_irq.h > +++ b/include/hw/ppc/spapr_irq.h > @@ -40,6 +40,8 @@ typedef struct sPAPRIrq { > void (*free)(sPAPRMachineState *spapr, int irq, int num); > qemu_irq (*qirq)(sPAPRMachineState *spapr, int irq); > void (*print_info)(sPAPRMachineState *spapr, Monitor *mon); > +void (*dt_populate)(sPAPRMachineState *spapr, uint32_t nr_servers, > +void *fdt, uint32_t phandle); > } sPAPRIrq; > > extern sPAPRIrq spapr_irq_xics; > diff --git a/include/hw/ppc/spapr_xive.h b/include/hw/ppc/spapr_xive.h > index 418511f3dc10..5b3fab192d41 100644 > --- a/include/hw/ppc/spapr_xive.h > +++ b/include/hw/ppc/spapr_xive.h > @@ -65,5 +65,7 @@ bool spapr_xive_priority_is_valid(uint8_t priority); > typedef struct sPAPRMachineState sPAPRMachineState; > > void spapr_xive_hcall_init(sPAPRMachineState *spapr); > +void spapr_dt_xive(sPAPRXive *xive, int nr_servers, void *fdt, > + uint32_t phandle); > > #endif /* PPC_SPAPR_XIVE_H */ > diff --git a/hw/intc/spapr_xive_hcall.c b/hw/intc/spapr_xive_hcall.c > index 52e4e23995f5..66c78aa88500 100644 > --- a/hw/intc/spapr_xive_hcall.c > +++ b/hw/intc/spapr_xive_hcall.c > @@ -890,3 +890,65 @@ void spapr_xive_hcall_init(sPAPRMachineState *spapr) > spapr_register_hypercall(H_INT_SYNC, h_int_sync); > spapr_register_hypercall(H_INT_RESET, h_int_reset); > } > + > +void spapr_dt_xive(sPAPRXive *xive, int nr_servers, void *fdt, uint32_t > phandle) > +{ > +int node; > +uint64_t timas[2 * 2]; > +/* Interrupt number ranges for the IPIs */ > +uint32_t lisn_ranges[] = { > +cpu_to_be32(0), > +cpu_to_be32(nr_servers), > +}; > +uint32_t eq_sizes[] = { > +cpu_to_be32(12), /* 4K */ > +cpu_to_be32(16), /* 64K */ > +cpu_to_be32(21), /* 2M */ > +cpu_to_be32(24), /* 16M */ > +}; > +/* The following array is in sync with the 'spapr_xive_priority_is_valid' > + * routine above. The O/S is expected to choose priority 6. > + */ > +uint32_t plat_res_int_priorities[] = { > +cpu_to_be32(7),/* start */ > +cpu_to_be32(0xf8), /* count */ > +}; > +gchar *nodename; > + > +/* Thread Interrupt Management Area : User (ring 3) and OS (ring 2) */ > +timas[0] = cpu_to_be64(xive->tm_base + 3 * (1ull << TM_SHIFT)); > +timas[1] = cpu_to_be64(1ull << TM_SHIFT); > +timas[2] = cpu_to_be64(xive->tm_base + 2 * (1ull << TM_SHIFT)); Don't you have symbolic constants for the ring numbers, instead of '2' and '3' above? > +timas[3] = cpu_to_be64(1ull << TM_SHIFT); > + > +nodename = g_strdup_printf("interrupt-controller@%" PRIx64, > + xive->tm_base + 3 * (1 << TM_SHIFT)); > +_FDT(node = fdt_add_subnode(fdt, 0, nodename)); > +g_free(nodename); > + > +_FDT(fdt_setprop_string(fdt, node, "device_type", "power-ivpe")); > +_FDT(fdt_setprop(fdt, node, "reg", timas, sizeof(timas))); > + > +_FDT(fdt_setprop_string(fdt, node, "compatible", "ibm,power-ivpe")); > +_FDT(fdt_setprop(fdt, node, "ibm,xive-eq-sizes", eq_sizes, > + sizeof(eq_sizes))); > +_FDT(fdt_setprop(fdt, node, "ibm,xive-lisn-ranges", lisn_ranges, > + sizeof(lisn_ranges))); > + > +/* For Linux to link the LSIs to the main interrupt controller. What's the "main interrupt co
Re: [Qemu-devel] [PATCH v5 16/36] spapr: add hcalls support for the XIVE exploitation interrupt mode
On Fri, Nov 16, 2018 at 11:57:09AM +0100, Cédric Le Goater wrote: > The different XIVE virtualization structures (sources and event queues) > are configured with a set of Hypervisor calls : > > - H_INT_GET_SOURCE_INFO > >used to obtain the address of the MMIO page of the Event State >Buffer (ESB) entry associated with the source. > > - H_INT_SET_SOURCE_CONFIG > >assigns a source to a "target". > > - H_INT_GET_SOURCE_CONFIG > >determines which "target" and "priority" is assigned to a source > > - H_INT_GET_QUEUE_INFO > >returns the address of the notification management page associated >with the specified "target" and "priority". > > - H_INT_SET_QUEUE_CONFIG > >sets or resets the event queue for a given "target" and "priority". >It is also used to set the notification configuration associated >with the queue, only unconditional notification is supported for >the moment. Reset is performed with a queue size of 0 and queueing >is disabled in that case. > > - H_INT_GET_QUEUE_CONFIG > >returns the queue settings for a given "target" and "priority". > > - H_INT_RESET > >resets all of the guest's internal interrupt structures to their >initial state, losing all configuration set via the hcalls >H_INT_SET_SOURCE_CONFIG and H_INT_SET_QUEUE_CONFIG. > > - H_INT_SYNC > >issue a synchronisation on a source to make sure all notifications >have reached their queue. > > Calls that still need to be addressed : > >H_INT_SET_OS_REPORTING_LINE >H_INT_GET_OS_REPORTING_LINE > > See the code for more documentation on each hcall. > > Signed-off-by: Cédric Le Goater > --- > include/hw/ppc/spapr.h | 15 +- > include/hw/ppc/spapr_xive.h | 6 + > hw/intc/spapr_xive_hcall.c | 892 > hw/ppc/spapr_irq.c | 2 + > hw/intc/Makefile.objs | 2 +- > 5 files changed, 915 insertions(+), 2 deletions(-) > create mode 100644 hw/intc/spapr_xive_hcall.c > > diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h > index 1fbc2663e06c..8415faea7b82 100644 > --- a/include/hw/ppc/spapr.h > +++ b/include/hw/ppc/spapr.h > @@ -452,7 +452,20 @@ struct sPAPRMachineState { > #define H_INVALIDATE_PID0x378 > #define H_REGISTER_PROC_TBL 0x37C > #define H_SIGNAL_SYS_RESET 0x380 > -#define MAX_HCALL_OPCODEH_SIGNAL_SYS_RESET > + > +#define H_INT_GET_SOURCE_INFO 0x3A8 > +#define H_INT_SET_SOURCE_CONFIG 0x3AC > +#define H_INT_GET_SOURCE_CONFIG 0x3B0 > +#define H_INT_GET_QUEUE_INFO0x3B4 > +#define H_INT_SET_QUEUE_CONFIG 0x3B8 > +#define H_INT_GET_QUEUE_CONFIG 0x3BC > +#define H_INT_SET_OS_REPORTING_LINE 0x3C0 > +#define H_INT_GET_OS_REPORTING_LINE 0x3C4 > +#define H_INT_ESB 0x3C8 > +#define H_INT_SYNC 0x3CC > +#define H_INT_RESET 0x3D0 > + > +#define MAX_HCALL_OPCODEH_INT_RESET > > /* The hcalls above are standardized in PAPR and implemented by pHyp > * as well. > diff --git a/include/hw/ppc/spapr_xive.h b/include/hw/ppc/spapr_xive.h > index 3f65b8f485fd..418511f3dc10 100644 > --- a/include/hw/ppc/spapr_xive.h > +++ b/include/hw/ppc/spapr_xive.h > @@ -60,4 +60,10 @@ int spapr_xive_target_to_end(sPAPRXive *xive, uint32_t > target, uint8_t prio, > int spapr_xive_cpu_to_end(sPAPRXive *xive, PowerPCCPU *cpu, uint8_t prio, >uint8_t *out_end_blk, uint32_t *out_end_idx); > > +bool spapr_xive_priority_is_valid(uint8_t priority); AFAICT this could be a local function. > + > +typedef struct sPAPRMachineState sPAPRMachineState; > + > +void spapr_xive_hcall_init(sPAPRMachineState *spapr); > + > #endif /* PPC_SPAPR_XIVE_H */ > diff --git a/hw/intc/spapr_xive_hcall.c b/hw/intc/spapr_xive_hcall.c > new file mode 100644 > index ..52e4e23995f5 > --- /dev/null > +++ b/hw/intc/spapr_xive_hcall.c > @@ -0,0 +1,892 @@ > +/* > + * QEMU PowerPC sPAPR XIVE interrupt controller model > + * > + * Copyright (c) 2017-2018, IBM Corporation. > + * > + * This code is licensed under the GPL version 2 or later. See the > + * COPYING file in the top-level directory. > + */ > + > +#include "qemu/osdep.h" > +#include "qemu/log.h" > +#include "qapi/error.h" > +#include "cpu.h" > +#include "hw/ppc/fdt.h" > +#include "hw/ppc/spapr.h" > +#include "hw/ppc/spapr_xive.h" > +#include "hw/ppc/xive_regs.h" > +#include "monitor/monitor.h" Fwiw, I don't think it's particularly necessary to split the hcall handling out into a separate .c file. > +/* > + * OPAL uses the priority 7 EQ to automatically escalate interrupts > + * for all other queues (DD2.X POWER9). So only priorities [0..6] are > + * available for the guest. Referencing OPAL behaviour doesn't really make sense in the context of PAPR. What I think you're getting at is that the PAPR spec only allows a PAPR guest to use priorities 0..6 (or at least it will if the XIVE updated spec ever gets published). The fact that this allows the host use 7 fo
[Qemu-devel] [PATCH V10 7/9] hw/misc/pvpanic: preparing for adding configure interface
Prepare for pvpanic-mmio configure interface. Signed-off-by: Peng Hao --- hw/arm/sysbus-fdt.c | 2 ++ hw/arm/virt.c | 2 ++ hw/misc/pvpanic.c | 11 +-- 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/hw/arm/sysbus-fdt.c b/hw/arm/sysbus-fdt.c index ad698d4..34577f3 100644 --- a/hw/arm/sysbus-fdt.c +++ b/hw/arm/sysbus-fdt.c @@ -38,6 +38,7 @@ #include "hw/vfio/vfio-amd-xgbe.h" #include "hw/display/ramfb.h" #include "hw/arm/fdt.h" +#include "hw/misc/pvpanic.h" /* * internal struct that contains the information to create dynamic @@ -459,6 +460,7 @@ static const BindingEntry bindings[] = { VFIO_PLATFORM_BINDING("amd,xgbe-seattle-v1a", add_amd_xgbe_fdt_node), #endif TYPE_BINDING(TYPE_RAMFB_DEVICE, no_fdt_node), +TYPE_BINDING(TYPE_PVPANIC_MMIO, no_fdt_node), TYPE_BINDING("", NULL), /* last element */ }; diff --git a/hw/arm/virt.c b/hw/arm/virt.c index f2cb5de..1fd5941 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -59,6 +59,7 @@ #include "qapi/visitor.h" #include "standard-headers/linux/input.h" #include "hw/arm/smmuv3.h" +#include "hw/misc/pvpanic.h" #define DEFINE_VIRT_MACHINE_LATEST(major, minor, latest) \ static void virt_##major##_##minor##_class_init(ObjectClass *oc, \ @@ -1783,6 +1784,7 @@ static void virt_machine_class_init(ObjectClass *oc, void *data) machine_class_allow_dynamic_sysbus_dev(mc, TYPE_VFIO_CALXEDA_XGMAC); machine_class_allow_dynamic_sysbus_dev(mc, TYPE_VFIO_AMD_XGBE); machine_class_allow_dynamic_sysbus_dev(mc, TYPE_RAMFB_DEVICE); +machine_class_allow_dynamic_sysbus_dev(mc, TYPE_PVPANIC_MMIO); machine_class_allow_dynamic_sysbus_dev(mc, TYPE_VFIO_PLATFORM); mc->block_default_type = IF_VIRTIO; mc->no_cdrom = 1; diff --git a/hw/misc/pvpanic.c b/hw/misc/pvpanic.c index c9382a8..b6b5c89 100644 --- a/hw/misc/pvpanic.c +++ b/hw/misc/pvpanic.c @@ -67,7 +67,7 @@ typedef struct PVPanicISAState { typedef struct PVPanicMMIOState { SysBusDevice parent_obj; /**/ - +uint32_t base; /* public */ MemoryRegion mr; } PVPanicMMIOState; @@ -151,10 +151,17 @@ static void pvpanic_mmio_initfn(Object *obj) sysbus_init_mmio(sbd, &s->mr); } +static Property pvpanic_mmio_properties[] = { +DEFINE_PROP_UINT32("mmio", PVPanicMMIOState, base, 0x0907), +DEFINE_PROP_END_OF_LIST(), +}; + static void pvpanic_mmio_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); - + +dc->user_creatable = true; +dc->props = pvpanic_mmio_properties; set_bit(DEVICE_CATEGORY_MISC, dc->categories); } -- 1.8.3.1
[Qemu-devel] [PATCH V10 8/9] hw/misc/pvpanic: realize the configure interface
Add configure interface for pvpanic-mmio. In qemu command line use -device pvpanic-mmio to enable the device. Signed-off-by: Peng Hao --- hw/arm/virt-acpi-build.c | 5 - hw/arm/virt.c| 7 +++ hw/misc/pvpanic.c| 1 + 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c index 2adba60..d29d229 100644 --- a/hw/arm/virt-acpi-build.c +++ b/hw/arm/virt-acpi-build.c @@ -45,6 +45,7 @@ #include "hw/arm/virt.h" #include "sysemu/numa.h" #include "kvm_arm.h" +#include "hw/misc/pvpanic.h" #define ARM_SPI_BASE 32 #define ACPI_POWER_BUTTON_DEVICE "PWRB" @@ -785,7 +786,9 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) acpi_dsdt_add_uart(scope, &memmap[VIRT_UART], (irqmap[VIRT_UART] + ARM_SPI_BASE)); acpi_dsdt_add_flash(scope, &memmap[VIRT_FLASH]); -acpi_dsdt_add_pvpanic(scope, &memmap[VIRT_PVPANIC]); +if (pvpanic_mmio()) { +acpi_dsdt_add_pvpanic(scope, &memmap[VIRT_PVPANIC]); +} acpi_dsdt_add_fw_cfg(scope, &memmap[VIRT_FW_CFG]); acpi_dsdt_add_virtio(scope, &memmap[VIRT_MMIO], (irqmap[VIRT_MMIO] + ARM_SPI_BASE), NUM_VIRTIO_TRANSPORTS); diff --git a/hw/arm/virt.c b/hw/arm/virt.c index 1fd5941..9cddf36 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -198,8 +198,6 @@ static void create_pvpanic_device(const VirtMachineState *vms) hwaddr base = vms->memmap[VIRT_PVPANIC].base; hwaddr size = vms->memmap[VIRT_PVPANIC].size; - sysbus_create_simple(TYPE_PVPANIC_MMIO, base, NULL); - nodename = g_strdup_printf("/pvpanic-mmio@%" PRIx64, base); qemu_fdt_add_subnode(vms->fdt, nodename); qemu_fdt_setprop_string(vms->fdt, nodename, @@ -1330,6 +1328,9 @@ void virt_machine_done(Notifier *notifier, void *data) struct arm_boot_info *info = &vms->bootinfo; AddressSpace *as = arm_boot_address_space(cpu, info); +if (pvpanic_mmio()) { +create_pvpanic_device(vms); +} /* * If the user provided a dtb, we assume the dynamic sysbus nodes * already are integrated there. This corresponds to a use case where @@ -1551,8 +1552,6 @@ static void machvirt_init(MachineState *machine) create_flash(vms, sysmem, secure_sysmem ? secure_sysmem : sysmem); -create_pvpanic_device(vms); - create_gic(vms, pic); fdt_add_pmu_nodes(vms); diff --git a/hw/misc/pvpanic.c b/hw/misc/pvpanic.c index b6b5c89..6c4a79f 100644 --- a/hw/misc/pvpanic.c +++ b/hw/misc/pvpanic.c @@ -149,6 +149,7 @@ static void pvpanic_mmio_initfn(Object *obj) memory_region_init_io(&s->mr, OBJECT(s), &pvpanic_ops, s, TYPE_PVPANIC_MMIO, 2); sysbus_init_mmio(sbd, &s->mr); +sysbus_mmio_map(sbd, 0, s->base); } static Property pvpanic_mmio_properties[] = { -- 1.8.3.1
[Qemu-devel] [PATCH V10 0/9] add pvpanic mmio support
The first patches are simple cleanups: - patch 1 move the pvpanic device with the 'ocmmon objects' so we compile it once for the x86/arm/aarch64 archs, - patch 2 simply renames ISA fields/definitions to generic ones. Then instead of add/use the MMIO pvpanic device in the virt machine in an unique patch, I split it in two distinct patches: - patch 3 uses Peng Hao's work, but add the MMIO interface to the existing device (no logical change). - patch 4 is Peng Hao's work in the virt machine (no logical change). - patch 5 add pvpanic device in acpi table in virt machine v2 from Peng Hao is: https://lists.gnu.org/archive/html/qemu-devel/2018-10/msg03433.html v3 --> v4 patch 1,2 no modification. patch 3, add TYPE_PANIC_MMIO for distinguishing different bus device, virt + isa_pvpanic will abnormally terminate virtual machine. patch 4, "pvpanic,mmio" --> "qemu,pvpanic-mmio". patch 5, newly added. v4 --> v5 patch 1,2 no modification. patch 3 delete PvpanicCommonState structure. patch 4 VIRT_PVPANIC_MMIO --> VIRT_PVPANIC correct VIRT_PVPANIC's overlap start address patch 5 no modification. v5 --> v6 add document. v6 --> v7 patch 5 modify device name from "PANC" to "PEVT". patch 6 modify document description. v7 --> v8 add configure interface for pvpanic-mmio v8 --> v9 revert "moving structure definition to header file" because of compile error in x86. v9 --> v10 Modify document. Repair missing header files. the kernel part of the series: https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc.git/log/?h=char-misc-testing misc/pvpanic: remove a redundant comma misc/pvpanic: convert to SPDX license tags misc/pvpanic: change header file sort style misc/pvpanic: remove unnecessary header file misc/pvpanic : break dependency on ACPI misc/pvpanic : grouping ACPI related stuff misc/pvpanic: add support to get pvpanic device info FDT dt-bindings: misc/pvpanic: add document for pvpanic-mmio misc/pvpanic: add MMIO support misc/pvpanic: simplify the code using acpi_dev_resource_io pvpanic: move pvpanic to misc as common driver Philippe Mathieu-Daudé (2): hw/misc/pvpanic: Build the pvpanic device in $(common-obj) hw/misc/pvpanic: Cosmetic renaming Peng Hao (7): hw/misc/pvpanic: Add the MMIO interface hw/arm/virt: Use the pvpanic device hw/arm/virt: add pvpanic device in virt acpi table hw/misc/pvpanic: add configure query interface hw/misc/pvpanic: preparing for adding configure interface hw/misc/pvpanic: realize the configure interface pvpanic : update pvpanic document default-configs/arm-softmmu.mak | 1 + docs/specs/pvpanic.txt | 15 ++- hw/arm/sysbus-fdt.c | 2 + hw/arm/virt-acpi-build.c| 17 hw/arm/virt.c | 23 ++- hw/misc/Makefile.objs | 2 +- hw/misc/pvpanic.c | 87 + include/hw/arm/virt.h | 1 + include/hw/misc/pvpanic.h | 6 +++ 9 files changed, 134 insertions(+), 20 deletions(-) -- 1.8.3.1
[Qemu-devel] [PATCH V10 6/9] hw/misc/pvpanic: add configure query interface
Add configure query interface for pvpanic-mmio. Signed-off-by: Peng Hao --- include/hw/misc/pvpanic.h | 7 +++ 1 file changed, 7 insertions(+) diff --git a/include/hw/misc/pvpanic.h b/include/hw/misc/pvpanic.h index f1a05b2..dc042cf 100644 --- a/include/hw/misc/pvpanic.h +++ b/include/hw/misc/pvpanic.h @@ -2,10 +2,12 @@ * QEMU simulated pvpanic device. * * Copyright Fujitsu, Corp. 2013 + * Copyright ZTE Ltd. 2018 * * Authors: * Wen Congyang * Hu Tao + * Peng Hao * * This work is licensed under the terms of the GNU GPL, version 2 or later. * See the COPYING file in the top-level directory. @@ -28,4 +30,9 @@ static inline uint16_t pvpanic_port(void) return object_property_get_uint(o, PVPANIC_IOPORT_PROP, NULL); } +static inline Object *pvpanic_mmio(void) +{ +return object_resolve_path_type("", TYPE_PVPANIC_MMIO, NULL); +} + #endif -- 1.8.3.1
[Qemu-devel] [PATCH V10 4/9] hw/arm/virt: Use the pvpanic device
Add pvpanic device in arm virt machine. Signed-off-by: Peng Hao --- default-configs/arm-softmmu.mak | 1 + hw/arm/virt.c | 21 + include/hw/arm/virt.h | 1 + 3 files changed, 23 insertions(+) diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak index 2420491..50345df 100644 --- a/default-configs/arm-softmmu.mak +++ b/default-configs/arm-softmmu.mak @@ -159,3 +159,4 @@ CONFIG_PCI_DESIGNWARE=y CONFIG_STRONGARM=y CONFIG_HIGHBANK=y CONFIG_MUSICPAL=y +CONFIG_PVPANIC=y diff --git a/hw/arm/virt.c b/hw/arm/virt.c index a2b8d8f..f2cb5de 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -143,6 +143,7 @@ static const MemMapEntry a15memmap[] = { [VIRT_GPIO] = { 0x0903, 0x1000 }, [VIRT_SECURE_UART] ={ 0x0904, 0x1000 }, [VIRT_SMMU] = { 0x0905, 0x0002 }, +[VIRT_PVPANIC] ={ 0x0907, 0x0002 }, [VIRT_MMIO] = { 0x0a00, 0x0200 }, /* ...repeating for a total of NUM_VIRTIO_TRANSPORTS, each of that size */ [VIRT_PLATFORM_BUS] = { 0x0c00, 0x0200 }, @@ -190,6 +191,24 @@ static bool cpu_type_valid(const char *cpu) return false; } +static void create_pvpanic_device(const VirtMachineState *vms) +{ + char *nodename; + hwaddr base = vms->memmap[VIRT_PVPANIC].base; + hwaddr size = vms->memmap[VIRT_PVPANIC].size; + + sysbus_create_simple(TYPE_PVPANIC_MMIO, base, NULL); + + nodename = g_strdup_printf("/pvpanic-mmio@%" PRIx64, base); + qemu_fdt_add_subnode(vms->fdt, nodename); + qemu_fdt_setprop_string(vms->fdt, nodename, + "compatible", "qemu,pvpanic-mmio"); + qemu_fdt_setprop_sized_cells(vms->fdt, nodename, "reg", + 2, base, 2, size); + + g_free(nodename); +} + static void create_fdt(VirtMachineState *vms) { void *fdt = create_device_tree(&vms->fdt_size); @@ -1531,6 +1550,8 @@ static void machvirt_init(MachineState *machine) create_flash(vms, sysmem, secure_sysmem ? secure_sysmem : sysmem); +create_pvpanic_device(vms); + create_gic(vms, pic); fdt_add_pmu_nodes(vms); diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h index 4cc57a7..937c124 100644 --- a/include/hw/arm/virt.h +++ b/include/hw/arm/virt.h @@ -66,6 +66,7 @@ enum { VIRT_GIC_REDIST, VIRT_GIC_REDIST2, VIRT_SMMU, +VIRT_PVPANIC, VIRT_UART, VIRT_MMIO, VIRT_RTC, -- 1.8.3.1
[Qemu-devel] [PATCH V10 9/9] pvpanic : update pvpanic document
Add mmio support info in docs/specs/pvpanic.txt. Signed-off-by: Peng Hao --- docs/specs/pvpanic.txt | 14 -- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/docs/specs/pvpanic.txt b/docs/specs/pvpanic.txt index c7bbacc..b1beea3 100644 --- a/docs/specs/pvpanic.txt +++ b/docs/specs/pvpanic.txt @@ -1,14 +1,17 @@ PVPANIC DEVICE == -pvpanic device is a simulated ISA device, through which a guest panic -event is sent to qemu, and a QMP event is generated. This allows +pvpanic device is a simulated ISA/SYSBUS device, through which a guest +panic event is sent to qemu, and a QMP event is generated. This allows management apps (e.g. libvirt) to be notified and respond to the event. The management app has the option of waiting for GUEST_PANICKED events, and/or polling for guest-panicked RunState, to learn when the pvpanic device has fired a panic event. +The pvpanic device can be implemented as an ISA device (using IOPORT), +or, since qemu 4.0, as a SYSBUS device (using MMIO). + ISA Interface - @@ -19,6 +22,13 @@ Software should set only bits both itself and the device recognize. Currently, only bit 0 is recognized, setting it indicates a guest panic has happened. +SYSBUS Interface + + +The SYSBUS interface is similar to the ISA interface except that it uses +MMIO. For example, the arm virt machine could put the pvpanic device at +[0x907, 0x9070001] and currently only the first byte is used. + ACPI Interface -- -- 1.8.3.1
[Qemu-devel] [PATCH V10 5/9] hw/arm/virt: add pvpanic device in virt acpi table
Add pvpanic device in virt acpi table, so when kenrel command line uses acpi=force, kernel can get info from acpi table. Signed-off-by: Peng Hao --- hw/arm/virt-acpi-build.c | 15 +++ 1 file changed, 15 insertions(+) diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c index 5785fb6..2adba60 100644 --- a/hw/arm/virt-acpi-build.c +++ b/hw/arm/virt-acpi-build.c @@ -84,6 +84,20 @@ static void acpi_dsdt_add_uart(Aml *scope, const MemMapEntry *uart_memmap, aml_append(scope, dev); } +static void acpi_dsdt_add_pvpanic(Aml *scope, const MemMapEntry *pvpanic_memmap) +{ +Aml *dev = aml_device("PEVT"); +aml_append(dev, aml_name_decl("_HID", aml_string("QEMU0001"))); +aml_append(dev, aml_name_decl("_UID", aml_int(0))); + +Aml *crs = aml_resource_template(); +aml_append(crs, aml_memory32_fixed(pvpanic_memmap->base, + pvpanic_memmap->size, AML_READ_WRITE)); + +aml_append(dev, aml_name_decl("_CRS", crs)); +aml_append(scope, dev); +} + static void acpi_dsdt_add_fw_cfg(Aml *scope, const MemMapEntry *fw_cfg_memmap) { Aml *dev = aml_device("FWCF"); @@ -771,6 +785,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) acpi_dsdt_add_uart(scope, &memmap[VIRT_UART], (irqmap[VIRT_UART] + ARM_SPI_BASE)); acpi_dsdt_add_flash(scope, &memmap[VIRT_FLASH]); +acpi_dsdt_add_pvpanic(scope, &memmap[VIRT_PVPANIC]); acpi_dsdt_add_fw_cfg(scope, &memmap[VIRT_FW_CFG]); acpi_dsdt_add_virtio(scope, &memmap[VIRT_MMIO], (irqmap[VIRT_MMIO] + ARM_SPI_BASE), NUM_VIRTIO_TRANSPORTS); -- 1.8.3.1
[Qemu-devel] [PATCH V10 3/9] hw/misc/pvpanic: Add the MMIO interface
Add pvpanic new type "TYPE_PVPANIC_MMIO" Signed-off-by: Peng Hao --- hw/misc/pvpanic.c | 50 +++ include/hw/misc/pvpanic.h | 1 + 2 files changed, 47 insertions(+), 4 deletions(-) diff --git a/hw/misc/pvpanic.c b/hw/misc/pvpanic.c index 0f23a67..c9382a8 100644 --- a/hw/misc/pvpanic.c +++ b/hw/misc/pvpanic.c @@ -2,10 +2,12 @@ * QEMU simulated pvpanic device. * * Copyright Fujitsu, Corp. 2013 + * Copyright (c) 2018 ZTE Ltd. * * Authors: * Wen Congyang * Hu Tao + * Peng Hao * * This work is licensed under the terms of the GNU GPL, version 2 or later. * See the COPYING file in the top-level directory. @@ -28,6 +30,9 @@ #define PVPANIC_ISA_DEVICE(obj)\ OBJECT_CHECK(PVPanicISAState, (obj), TYPE_PVPANIC) +#define PVPANIC_MMIO_DEVICE(obj)\ +OBJECT_CHECK(PVPanicMMIOState, (obj), TYPE_PVPANIC_MMIO) + static void handle_event(int event) { static bool logged; @@ -56,21 +61,32 @@ typedef struct PVPanicISAState { MemoryRegion mr; } PVPanicISAState; +/* PVPanicMMIOState for sysbus device and + * use mmio. + */ +typedef struct PVPanicMMIOState { +SysBusDevice parent_obj; +/**/ + +/* public */ +MemoryRegion mr; +} PVPanicMMIOState; + /* return supported events on read */ -static uint64_t pvpanic_ioport_read(void *opaque, hwaddr addr, unsigned size) +static uint64_t pvpanic_read(void *opaque, hwaddr addr, unsigned size) { return PVPANIC_PANICKED; } -static void pvpanic_ioport_write(void *opaque, hwaddr addr, uint64_t val, +static void pvpanic_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) { handle_event(val); } static const MemoryRegionOps pvpanic_ops = { -.read = pvpanic_ioport_read, -.write = pvpanic_ioport_write, +.read = pvpanic_read, +.write = pvpanic_write, .impl = { .min_access_size = 1, .max_access_size = 1, @@ -125,9 +141,35 @@ static TypeInfo pvpanic_isa_info = { .class_init= pvpanic_isa_class_init, }; +static void pvpanic_mmio_initfn(Object *obj) +{ +PVPanicMMIOState *s = PVPANIC_MMIO_DEVICE(obj); +SysBusDevice *sbd = SYS_BUS_DEVICE(obj); + +memory_region_init_io(&s->mr, OBJECT(s), &pvpanic_ops, s, + TYPE_PVPANIC_MMIO, 2); +sysbus_init_mmio(sbd, &s->mr); +} + +static void pvpanic_mmio_class_init(ObjectClass *klass, void *data) +{ +DeviceClass *dc = DEVICE_CLASS(klass); + +set_bit(DEVICE_CATEGORY_MISC, dc->categories); +} + +static TypeInfo pvpanic_mmio_info = { +.name = TYPE_PVPANIC_MMIO, +.parent= TYPE_SYS_BUS_DEVICE, +.instance_size = sizeof(PVPanicMMIOState), +.instance_init = pvpanic_mmio_initfn, +.class_init= pvpanic_mmio_class_init, +}; + static void pvpanic_register_types(void) { type_register_static(&pvpanic_isa_info); +type_register_static(&pvpanic_mmio_info); } type_init(pvpanic_register_types) diff --git a/include/hw/misc/pvpanic.h b/include/hw/misc/pvpanic.h index 1ee071a..f1a05b2 100644 --- a/include/hw/misc/pvpanic.h +++ b/include/hw/misc/pvpanic.h @@ -15,6 +15,7 @@ #define HW_MISC_PVPANIC_H #define TYPE_PVPANIC "pvpanic" +#define TYPE_PVPANIC_MMIO "pvpanic-mmio" #define PVPANIC_IOPORT_PROP "ioport" -- 1.8.3.1
[Qemu-devel] [PATCH V10 2/9] hw/misc/pvpanic: Cosmetic renaming
From: Philippe Mathieu-Daudé To ease the MMIO device addition in the next patch, rename: - ISA_PVPANIC_DEVICE -> PVPANIC_ISA_DEVICE. - MemoryRegion io -> mr. Signed-off-by: Philippe Mathieu-Daudé Signed-off-by: Peng Hao --- hw/misc/pvpanic.c | 28 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/hw/misc/pvpanic.c b/hw/misc/pvpanic.c index 9d8961b..0f23a67 100644 --- a/hw/misc/pvpanic.c +++ b/hw/misc/pvpanic.c @@ -25,8 +25,8 @@ /* The pv event value */ #define PVPANIC_PANICKED(1 << PVPANIC_F_PANICKED) -#define ISA_PVPANIC_DEVICE(obj)\ -OBJECT_CHECK(PVPanicState, (obj), TYPE_PVPANIC) +#define PVPANIC_ISA_DEVICE(obj)\ +OBJECT_CHECK(PVPanicISAState, (obj), TYPE_PVPANIC) static void handle_event(int event) { @@ -45,12 +45,16 @@ static void handle_event(int event) #include "hw/isa/isa.h" -typedef struct PVPanicState { +/* PVPanicISAState for ISA device and + * use ioport. + */ +typedef struct PVPanicISAState { ISADevice parent_obj; - -MemoryRegion io; +/*< private>*/ uint16_t ioport; -} PVPanicState; +/**/ +MemoryRegion mr; +} PVPanicISAState; /* return supported events on read */ static uint64_t pvpanic_ioport_read(void *opaque, hwaddr addr, unsigned size) @@ -75,15 +79,15 @@ static const MemoryRegionOps pvpanic_ops = { static void pvpanic_isa_initfn(Object *obj) { -PVPanicState *s = ISA_PVPANIC_DEVICE(obj); +PVPanicISAState *s = PVPANIC_ISA_DEVICE(obj); -memory_region_init_io(&s->io, OBJECT(s), &pvpanic_ops, s, "pvpanic", 1); +memory_region_init_io(&s->mr, OBJECT(s), &pvpanic_ops, s, "pvpanic", 1); } static void pvpanic_isa_realizefn(DeviceState *dev, Error **errp) { ISADevice *d = ISA_DEVICE(dev); -PVPanicState *s = ISA_PVPANIC_DEVICE(dev); +PVPanicISAState *s = PVPANIC_ISA_DEVICE(dev); FWCfgState *fw_cfg = fw_cfg_find(); uint16_t *pvpanic_port; @@ -96,11 +100,11 @@ static void pvpanic_isa_realizefn(DeviceState *dev, Error **errp) fw_cfg_add_file(fw_cfg, "etc/pvpanic-port", pvpanic_port, sizeof(*pvpanic_port)); -isa_register_ioport(d, &s->io, s->ioport); +isa_register_ioport(d, &s->mr, s->ioport); } static Property pvpanic_isa_properties[] = { -DEFINE_PROP_UINT16(PVPANIC_IOPORT_PROP, PVPanicState, ioport, 0x505), +DEFINE_PROP_UINT16(PVPANIC_IOPORT_PROP, PVPanicISAState, ioport, 0x505), DEFINE_PROP_END_OF_LIST(), }; @@ -116,7 +120,7 @@ static void pvpanic_isa_class_init(ObjectClass *klass, void *data) static TypeInfo pvpanic_isa_info = { .name = TYPE_PVPANIC, .parent= TYPE_ISA_DEVICE, -.instance_size = sizeof(PVPanicState), +.instance_size = sizeof(PVPanicISAState), .instance_init = pvpanic_isa_initfn, .class_init= pvpanic_isa_class_init, }; -- 1.8.3.1
[Qemu-devel] [PATCH V10 1/9] hw/misc/pvpanic: Build the pvpanic device in $(common-obj)
From: Philippe Mathieu-Daudé The 'pvpanic' ISA device can be use by any machine with an ISA bus. Reviewed-by: Peter Maydell Signed-off-by: Philippe Mathieu-Daudé Signed-off-by: Peng Hao --- hw/misc/Makefile.objs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs index 680350b..c387ce4 100644 --- a/hw/misc/Makefile.objs +++ b/hw/misc/Makefile.objs @@ -8,6 +8,7 @@ common-obj-$(CONFIG_ISA_TESTDEV) += pc-testdev.o common-obj-$(CONFIG_PCI_TESTDEV) += pci-testdev.o common-obj-$(CONFIG_EDU) += edu.o common-obj-$(CONFIG_PCA9552) += pca9552.o +common-obj-$(CONFIG_PVPANIC) += pvpanic.o common-obj-y += unimp.o common-obj-$(CONFIG_FW_CFG_DMA) += vmcoreinfo.o @@ -70,7 +71,6 @@ obj-$(CONFIG_IOTKIT_SECCTL) += iotkit-secctl.o obj-$(CONFIG_IOTKIT_SYSCTL) += iotkit-sysctl.o obj-$(CONFIG_IOTKIT_SYSINFO) += iotkit-sysinfo.o -obj-$(CONFIG_PVPANIC) += pvpanic.o obj-$(CONFIG_AUX) += auxbus.o obj-$(CONFIG_ASPEED_SOC) += aspeed_scu.o aspeed_sdmc.o obj-$(CONFIG_MSF2) += msf2-sysreg.o -- 1.8.3.1
Re: [Qemu-devel] [PATCH v5 12/36] spapr: initialize VSMT before initializing the IRQ backend
On Fri, Nov 16, 2018 at 11:57:05AM +0100, Cédric Le Goater wrote: > We will need to use xics_max_server_number() to create the sPAPRXive > object modeling the interrupt controller of the machine which is > created before the CPUs. > > Signed-off-by: Cédric Le Goater My only concern here is that this moves the spapr_set_vsmt_mode() before some of the sanity checks in spapr_init_cpus(). Are we certain there are no edge cases that could cause badness? > --- > hw/ppc/spapr.c | 10 +- > 1 file changed, 5 insertions(+), 5 deletions(-) > > diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c > index 7afd1a175bf2..50cb9f9f4a02 100644 > --- a/hw/ppc/spapr.c > +++ b/hw/ppc/spapr.c > @@ -2466,11 +2466,6 @@ static void spapr_init_cpus(sPAPRMachineState *spapr) > boot_cores_nr = possible_cpus->len; > } > > -/* VSMT must be set in order to be able to compute VCPU ids, ie to > - * call xics_max_server_number() or spapr_vcpu_id(). > - */ > -spapr_set_vsmt_mode(spapr, &error_fatal); > - > if (smc->pre_2_10_has_unused_icps) { > int i; > > @@ -2593,6 +2588,11 @@ static void spapr_machine_init(MachineState *machine) > /* Setup a load limit for the ramdisk leaving room for SLOF and FDT */ > load_limit = MIN(spapr->rma_size, RTAS_MAX_ADDR) - FW_OVERHEAD; > > +/* VSMT must be set in order to be able to compute VCPU ids, ie to > + * call xics_max_server_number() or spapr_vcpu_id(). > + */ > +spapr_set_vsmt_mode(spapr, &error_fatal); > + > /* Set up Interrupt Controller before we create the VCPUs */ > smc->irq->init(spapr, &error_fatal); > -- 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 v5 13/36] spapr: introduce a spapr_irq_init() routine
On Fri, Nov 16, 2018 at 11:57:06AM +0100, Cédric Le Goater wrote: > Initialize the MSI bitmap from it as this will be necessary for the > sPAPR IRQ backend for XIVE. > > Signed-off-by: Cédric Le Goater Reviewed-by: David Gibson > --- > include/hw/ppc/spapr_irq.h | 1 + > hw/ppc/spapr.c | 2 +- > hw/ppc/spapr_irq.c | 16 +++- > 3 files changed, 13 insertions(+), 6 deletions(-) > > diff --git a/include/hw/ppc/spapr_irq.h b/include/hw/ppc/spapr_irq.h > index a467ce696ee4..bd7301e6d9c6 100644 > --- a/include/hw/ppc/spapr_irq.h > +++ b/include/hw/ppc/spapr_irq.h > @@ -43,6 +43,7 @@ typedef struct sPAPRIrq { > extern sPAPRIrq spapr_irq_xics; > extern sPAPRIrq spapr_irq_xics_legacy; > > +void spapr_irq_init(sPAPRMachineState *spapr, Error **errp); > int spapr_irq_claim(sPAPRMachineState *spapr, int irq, bool lsi, Error > **errp); > void spapr_irq_free(sPAPRMachineState *spapr, int irq, int num); > qemu_irq spapr_qirq(sPAPRMachineState *spapr, int irq); > diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c > index 50cb9f9f4a02..e470efe7993c 100644 > --- a/hw/ppc/spapr.c > +++ b/hw/ppc/spapr.c > @@ -2594,7 +2594,7 @@ static void spapr_machine_init(MachineState *machine) > spapr_set_vsmt_mode(spapr, &error_fatal); > > /* Set up Interrupt Controller before we create the VCPUs */ > -smc->irq->init(spapr, &error_fatal); > +spapr_irq_init(spapr, &error_fatal); > > /* Set up containers for ibm,client-architecture-support negotiated > options > */ > diff --git a/hw/ppc/spapr_irq.c b/hw/ppc/spapr_irq.c > index e77b94cc685e..f8b651de0ec9 100644 > --- a/hw/ppc/spapr_irq.c > +++ b/hw/ppc/spapr_irq.c > @@ -97,11 +97,6 @@ static void spapr_irq_init_xics(sPAPRMachineState *spapr, > Error **errp) > int nr_irqs = smc->irq->nr_irqs; > Error *local_err = NULL; > > -/* Initialize the MSI IRQ allocator. */ > -if (!SPAPR_MACHINE_GET_CLASS(spapr)->legacy_irq_allocation) { > -spapr_irq_msi_init(spapr, smc->irq->nr_msis); > -} > - > if (kvm_enabled()) { > if (machine_kernel_irqchip_allowed(machine) && > !xics_kvm_init(spapr, &local_err)) { > @@ -213,6 +208,17 @@ sPAPRIrq spapr_irq_xics = { > /* > * sPAPR IRQ frontend routines for devices > */ > +void spapr_irq_init(sPAPRMachineState *spapr, Error **errp) > +{ > +sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr); > + > +/* Initialize the MSI IRQ allocator. */ > +if (!SPAPR_MACHINE_GET_CLASS(spapr)->legacy_irq_allocation) { > +spapr_irq_msi_init(spapr, smc->irq->nr_msis); > +} > + > +smc->irq->init(spapr, errp); > +} > > int spapr_irq_claim(sPAPRMachineState *spapr, int irq, bool lsi, Error > **errp) > { -- 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 v5 15/36] spapr: introdude a new machine IRQ backend for XIVE
On Fri, Nov 16, 2018 at 11:57:08AM +0100, Cédric Le Goater wrote: > The XIVE IRQ backend uses the same layout as the new XICS backend but > covers the full range of the IRQ number space. The IRQ numbers for the > CPU IPIs are allocated at the bottom of this space, below 4K, to > preserve compatibility with XICS which does not use that range. > > This should be enough given that the maximum number of CPUs is 1024 > for the sPAPR machine under QEMU. For the record, the biggest POWER8 > or POWER9 system has a maximum of 1536 HW threads (16 sockets, 192 > cores, SMT8). > > Signed-off-by: Cédric Le Goater > --- > include/hw/ppc/spapr.h | 2 + > include/hw/ppc/spapr_irq.h | 7 ++- > hw/ppc/spapr.c | 2 +- > hw/ppc/spapr_irq.c | 119 - > 4 files changed, 124 insertions(+), 6 deletions(-) > > diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h > index 6279711fe8f7..1fbc2663e06c 100644 > --- a/include/hw/ppc/spapr.h > +++ b/include/hw/ppc/spapr.h > @@ -16,6 +16,7 @@ typedef struct sPAPREventLogEntry sPAPREventLogEntry; > typedef struct sPAPREventSource sPAPREventSource; > typedef struct sPAPRPendingHPT sPAPRPendingHPT; > typedef struct ICSState ICSState; > +typedef struct sPAPRXive sPAPRXive; > > #define HPTE64_V_HPTE_DIRTY 0x0040ULL > #define SPAPR_ENTRY_POINT 0x100 > @@ -175,6 +176,7 @@ struct sPAPRMachineState { > const char *icp_type; > int32_t irq_map_nr; > unsigned long *irq_map; > +sPAPRXive *xive; > > bool cmd_line_caps[SPAPR_CAP_NUM]; > sPAPRCapabilities def, eff, mig; > diff --git a/include/hw/ppc/spapr_irq.h b/include/hw/ppc/spapr_irq.h > index 0e9229bf219e..c854ae527808 100644 > --- a/include/hw/ppc/spapr_irq.h > +++ b/include/hw/ppc/spapr_irq.h > @@ -13,6 +13,7 @@ > /* > * IRQ range offsets per device type > */ > +#define SPAPR_IRQ_IPI0x0 > #define SPAPR_IRQ_EPOW 0x1000 /* XICS_IRQ_BASE offset */ > #define SPAPR_IRQ_HOTPLUG0x1001 > #define SPAPR_IRQ_VIO0x1100 /* 256 VIO devices */ > @@ -33,7 +34,8 @@ typedef struct sPAPRIrq { > uint32_tnr_irqs; > uint32_tnr_msis; > > -void (*init)(sPAPRMachineState *spapr, int nr_irqs, Error **errp); > +void (*init)(sPAPRMachineState *spapr, int nr_irqs, int nr_servers, > + Error **errp); > int (*claim)(sPAPRMachineState *spapr, int irq, bool lsi, Error **errp); > void (*free)(sPAPRMachineState *spapr, int irq, int num); > qemu_irq (*qirq)(sPAPRMachineState *spapr, int irq); > @@ -42,8 +44,9 @@ typedef struct sPAPRIrq { > > extern sPAPRIrq spapr_irq_xics; > extern sPAPRIrq spapr_irq_xics_legacy; > +extern sPAPRIrq spapr_irq_xive; > > -void spapr_irq_init(sPAPRMachineState *spapr, Error **errp); > +void spapr_irq_init(sPAPRMachineState *spapr, int nr_servers, Error **errp); I don't see why nr_servers needs to become a parameter, since it can be derived from spapr within this routine. > int spapr_irq_claim(sPAPRMachineState *spapr, int irq, bool lsi, Error > **errp); > void spapr_irq_free(sPAPRMachineState *spapr, int irq, int num); > qemu_irq spapr_qirq(sPAPRMachineState *spapr, int irq); > diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c > index e470efe7993c..9f8c19e56e7a 100644 > --- a/hw/ppc/spapr.c > +++ b/hw/ppc/spapr.c > @@ -2594,7 +2594,7 @@ static void spapr_machine_init(MachineState *machine) > spapr_set_vsmt_mode(spapr, &error_fatal); > > /* Set up Interrupt Controller before we create the VCPUs */ > -spapr_irq_init(spapr, &error_fatal); > +spapr_irq_init(spapr, xics_max_server_number(spapr), &error_fatal); We should rename xics_max_server_number() since it's no longer xics specific. > /* Set up containers for ibm,client-architecture-support negotiated > options > */ > diff --git a/hw/ppc/spapr_irq.c b/hw/ppc/spapr_irq.c > index bac45023..2569ae1bc7f8 100644 > --- a/hw/ppc/spapr_irq.c > +++ b/hw/ppc/spapr_irq.c > @@ -12,6 +12,7 @@ > #include "qemu/error-report.h" > #include "qapi/error.h" > #include "hw/ppc/spapr.h" > +#include "hw/ppc/spapr_xive.h" > #include "hw/ppc/xics.h" > #include "sysemu/kvm.h" > > @@ -91,7 +92,7 @@ error: > } > > static void spapr_irq_init_xics(sPAPRMachineState *spapr, int nr_irqs, > -Error **errp) > +int nr_servers, Error **errp) > { > MachineState *machine = MACHINE(spapr); > Error *local_err = NULL; > @@ -204,10 +205,122 @@ sPAPRIrq spapr_irq_xics = { > .print_info = spapr_irq_print_info_xics, > }; > > + /* > + * XIVE IRQ backend. > + */ > +static sPAPRXive *spapr_xive_create(sPAPRMachineState *spapr, > +const char *type_xive, int nr_irqs, > +int nr_servers, Error **errp) > +{ > +sPAPRXive *xive; > +Error *local_err = NULL; > +Object *obj; > +uint32_t nr_ends = nr_servers <<
Re: [Qemu-devel] [PATCH 4/8] hw: arm: Carry RSDP specific data through AcpiRsdpData
On Tue, Nov 27, 2018 at 05:27:49PM +0100, Igor Mammedov wrote: > On Tue, 27 Nov 2018 16:42:18 +0100 > Samuel Ortiz wrote: > > > Hi Igor, > > > > On Tue, Nov 27, 2018 at 04:25:51PM +0100, Igor Mammedov wrote: > > > On Mon, 26 Nov 2018 17:29:37 +0100 > > > Samuel Ortiz wrote: > > > > > > > That will allow us to generalize the ARM build_rsdp() routine to support > > > > both legacy RSDP (The current i386 implementation) and extended RSDP > > > > (The ARM implementation). > > > > > > > > Signed-off-by: Samuel Ortiz > > > > --- > > > > include/hw/acpi/acpi-defs.h | 11 +++ > > > > hw/arm/virt-acpi-build.c| 27 ++- > > > > 2 files changed, 33 insertions(+), 5 deletions(-) > > > > > > > > diff --git a/include/hw/acpi/acpi-defs.h b/include/hw/acpi/acpi-defs.h > > > > index af8e023968..e7fd24c6c5 100644 > > > > --- a/include/hw/acpi/acpi-defs.h > > > > +++ b/include/hw/acpi/acpi-defs.h > > > > @@ -53,6 +53,17 @@ struct AcpiRsdpDescriptor {/* Root System > > > > Descriptor Pointer */ > > > > } QEMU_PACKED; > > > > typedef struct AcpiRsdpDescriptor AcpiRsdpDescriptor; > > > > > > > > +typedef struct AcpiRsdpData { > > > > +uint8_t oem_id[6]; /* OEM identification */ > > > > +uint8_t revision; /* Must be 0 for 1.0, 2 for 2.0 */ > > > > + > > > > +unsigned *rsdt_tbl_offset; > > > > +unsigned *xsdt_tbl_offset; > > > > +} AcpiRsdpData; > > > > + > > > > > > > +#define ACPI_RSDP_REV_1 0 > > > > +#define ACPI_RSDP_REV_2 2 > > > it's one time used spec defined values so just use values directly > > > in place with a comment, so reader won't have to jump around code > > > when comparing to spec. > > It's also used in the ACPI tests fix patch. > it's better to use in test it's own version (we just opencode them there) > see fadt_fetch_facs_and_dsdt_ptrs()/sanitize_fadt_ptrs() > same applies for length. > that way if we break it in qemu's code test would catch the thing > > > Also the 0 for revision 1 is a little confusing, I feel the above > > definition is clearer. > that's confusion is in the spec, so we just mimic it, no need to add more on > top To be more precise, there is a huge number of constants in ACPI such that adding defines for them all would be a huge burden, and will not make it easy to check values against the spec at all (case in point ACPI_RSDP_REV_2 is actually wrong, 2 is version 3 and up). Thus the preferred style is to add a comment near the value matching spec name verbatim, so one can copy it and look it up in the spec. Sometimes one needs to reference specific spec version. 0 /* Revision: ACPI version 1.0 */ and 1 /* Revision: ACPI 2.0 */ and 2 /* Revision: ACPI 3.0a */ For style consistency, if the value is used multiple times, we avoid duplication by using an inline function and not a macro. > > > > > > > > + > > > > /* Table structure from Linux kernel (the ACPI tables are under the > > > > BSD license) */ > > > > > > > > diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c > > > > index 0835900052..2dad465ecf 100644 > > > > --- a/hw/arm/virt-acpi-build.c > > > > +++ b/hw/arm/virt-acpi-build.c > > > > @@ -368,7 +368,7 @@ static void acpi_dsdt_add_power_button(Aml *scope) > > > > > > > > /* RSDP */ > > > > static void > > > > -build_rsdp(GArray *rsdp_table, BIOSLinker *linker, unsigned > > > > xsdt_tbl_offset) > > > > +build_rsdp(GArray *rsdp_table, BIOSLinker *linker, AcpiRsdpData > > > > *rsdp_data) > > > > { > > > > AcpiRsdpDescriptor *rsdp = acpi_data_push(rsdp_table, sizeof > > > > *rsdp); > > > > unsigned xsdt_pa_size = sizeof(rsdp->xsdt_physical_address); > > > > @@ -379,14 +379,14 @@ build_rsdp(GArray *rsdp_table, BIOSLinker > > > > *linker, unsigned xsdt_tbl_offset) > > > > true /* fseg memory */); > > > > > > > > memcpy(&rsdp->signature, "RSD PTR ", sizeof(rsdp->signature)); > > > > -memcpy(rsdp->oem_id, ACPI_BUILD_APPNAME6, sizeof(rsdp->oem_id)); > > > > +memcpy(rsdp->oem_id, rsdp_data->oem_id, sizeof(rsdp->oem_id)); > > > > rsdp->length = cpu_to_le32(sizeof(*rsdp)); > > > > -rsdp->revision = 0x02; > > > > +rsdp->revision = rsdp_data->revision; > > > > > > > > /* Address to be filled by Guest linker */ > > > > bios_linker_loader_add_pointer(linker, > > > > ACPI_BUILD_RSDP_FILE, xsdt_pa_offset, xsdt_pa_size, > > > > -ACPI_BUILD_TABLE_FILE, xsdt_tbl_offset); > > > > +ACPI_BUILD_TABLE_FILE, *rsdp_data->xsdt_tbl_offset); > > > > > > > > /* Checksum to be filled by Guest linker */ > > > > bios_linker_loader_add_checksum(linker, ACPI_BUILD_RSDP_FILE, > > > > @@ -399,6 +399,20 @@ build_rsdp(GArray *rsdp_table, BIOSLinker *linker, > > > > unsigned xsdt_tbl_offset) > > > > (char *)&rsdp->extended_checksum - rsdp_table->data); > > > > } > > > > > > > > +static void > > > > +init_rsdp_data(AcpiRsdpData *data, const char *oem_id, uint8_t > > > > r
Re: [Qemu-devel] [PATCH v2 00/16] Virtio devices split from virtio-pci
On Mon, Nov 26, 2018 at 08:59:53PM +0100, Juan Quintela wrote: > Hi > > V2: > > - Rebase on top of master > > Please review. > > Later, Juan. And just making sure the point is so that one can disable virtio-pci and still build virtio? And the point of that is mostly as a cleanup on generic principles, right? Or is there a project that actually wants to do it? > > [v1] > >From previous verision (in the middle of make check tests): > - split also the bits of virtio-pci.h (mst suggestion) > - add gpu, crypt and gpg bits > - more cleanups > - fix all the copyrights (the ones not changed have been there > foverever) > - be consistent with naming, vhost-* or virtio-* > > Please review, Juan. > > Juan Quintela (16): > virtio: split vhost vsock bits from virtio-pci > virtio: split virtio input host bits from virtio-pci > virtio: split virtio input bits from virtio-pci > virtio: split virtio rng bits from virtio-pci > virtio: split virtio balloon bits from virtio-pci > virtio: split virtio 9p bits from virtio-pci > virtio: split vhost user blk bits from virtio-pci > virtio: split vhost user scsi bits from virtio-pci > virtio: split vhost scsi bits from virtio-pci > virtio: split virtio scsi bits from virtio-pci > virtio: split virtio blk bits rom virtio-pci > virtio: split virtio net bits rom virtio-pci > virtio: split virtio serial bits rom virtio-pci > virtio: split virtio gpu bits rom virtio-pci.h > virtio: split virtio crypto bits rom virtio-pci.h > virtio: virtio 9p really requires CONFIG_VIRTFS to work > > default-configs/virtio.mak| 3 +- > hw/display/virtio-gpu-pci.c | 14 + > hw/display/virtio-vga.c | 1 + > hw/virtio/Makefile.objs | 14 +- > hw/virtio/vhost-scsi-pci.c| 95 > hw/virtio/vhost-user-blk-pci.c| 101 > hw/virtio/vhost-user-scsi-pci.c | 101 > hw/virtio/vhost-vsock-pci.c | 82 > hw/virtio/virtio-9p-pci.c | 86 > hw/virtio/virtio-balloon-pci.c| 94 > hw/virtio/virtio-blk-pci.c| 97 > hw/virtio/virtio-crypto-pci.c | 14 + > hw/virtio/virtio-input-host-pci.c | 45 ++ > hw/virtio/virtio-input-pci.c | 154 ++ > hw/virtio/virtio-net-pci.c| 96 > hw/virtio/virtio-pci.c| 783 -- > hw/virtio/virtio-pci.h| 234 - > hw/virtio/virtio-rng-pci.c| 86 > hw/virtio/virtio-scsi-pci.c | 106 > hw/virtio/virtio-serial-pci.c | 112 + > tests/Makefile.include| 18 +- > 21 files changed, 1308 insertions(+), 1028 deletions(-) > create mode 100644 hw/virtio/vhost-scsi-pci.c > create mode 100644 hw/virtio/vhost-user-blk-pci.c > create mode 100644 hw/virtio/vhost-user-scsi-pci.c > create mode 100644 hw/virtio/vhost-vsock-pci.c > create mode 100644 hw/virtio/virtio-9p-pci.c > create mode 100644 hw/virtio/virtio-balloon-pci.c > create mode 100644 hw/virtio/virtio-blk-pci.c > create mode 100644 hw/virtio/virtio-input-host-pci.c > create mode 100644 hw/virtio/virtio-input-pci.c > create mode 100644 hw/virtio/virtio-net-pci.c > create mode 100644 hw/virtio/virtio-rng-pci.c > create mode 100644 hw/virtio/virtio-scsi-pci.c > create mode 100644 hw/virtio/virtio-serial-pci.c > > -- > 2.19.1 >
Re: [Qemu-devel] [PATCH v5 09/36] ppc/xive: notify the CPU when the interrupt priority is more privileged
On 11/27/18 8:41 PM, David Gibson wrote: On Wed, Nov 28, 2018 at 01:32:21PM +1100, Benjamin Herrenschmidt wrote: On Wed, 2018-11-28 at 11:13 +1100, David Gibson wrote: Don't you need a cast to avoid (nsr << 8) being a shift-wider-than-size? Shouldn't be a problem as long as it fits in an int, no ? I dunno, I can never remember the rules about when C extends and when it doesn't. I'm not sure anybody does, which is kind of the point. As soon as you perform arithmetic on a type narrower than int, it is first promoted to at least int (possibly wider, depending on the type of the other operand to the binary operator). And, since C guarantees that int is larger than 8 bits, 'uint8_t << 8' and 'int8_t << 8' are both well-defined, without needing a cast of nsr. -- Eric Blake, Principal Software Engineer Red Hat, Inc. +1-919-301-3266 Virtualization: qemu.org | libvirt.org
Re: [Qemu-devel] [PATCH V9 0/9] add pvpanic mmio support
Hi, This series failed docker-quick@centos7 build test. Please find the testing commands and their output below. If you have Docker installed, you can probably reproduce it locally. Message-id: 1543262162-6351-1-git-send-email-peng.h...@zte.com.cn Subject: [Qemu-devel] [PATCH V9 0/9] add pvpanic mmio support Type: series === TEST SCRIPT BEGIN === #!/bin/bash time make docker-test-quick@centos7 SHOW_ENV=1 J=8 === TEST SCRIPT END === Updating 3c8cf5a9c21ff8782164d1def7f44bd888713384 Switched to a new branch 'test' 3159b16 pvpanic : update pvpanic document 043c070 hw/misc/pvpanic: realize the configure interface 86ea086 hw/misc/pvpanic: preparing for adding configure interface af8de03 hw/misc/pvpanic: add configure query interface 63deb69 hw/arm/virt: add pvpanic device in virt acpi table 272983e hw/arm/virt: Use the pvpanic device a0bdaee hw/misc/pvpanic: Add the MMIO interface fe0cdc7e hw/misc/pvpanic: Cosmetic renaming 65de96a hw/misc/pvpanic: Build the pvpanic device in $(common-obj) === OUTPUT BEGIN === BUILD centos7 make[1]: Entering directory `/var/tmp/patchew-tester-tmp-q3noxx78/src' GEN /var/tmp/patchew-tester-tmp-q3noxx78/src/docker-src.2018-11-27-21.45.24.27232/qemu.tar Cloning into '/var/tmp/patchew-tester-tmp-q3noxx78/src/docker-src.2018-11-27-21.45.24.27232/qemu.tar.vroot'... done. Checking out files: 46% (3031/6463) Checking out files: 47% (3038/6463) Checking out files: 48% (3103/6463) Checking out files: 49% (3167/6463) Checking out files: 50% (3232/6463) Checking out files: 51% (3297/6463) Checking out files: 52% (3361/6463) Checking out files: 53% (3426/6463) Checking out files: 54% (3491/6463) Checking out files: 55% (3555/6463) Checking out files: 56% (3620/6463) Checking out files: 57% (3684/6463) Checking out files: 58% (3749/6463) Checking out files: 59% (3814/6463) Checking out files: 60% (3878/6463) Checking out files: 61% (3943/6463) Checking out files: 62% (4008/6463) Checking out files: 63% (4072/6463) Checking out files: 64% (4137/6463) Checking out files: 65% (4201/6463) Checking out files: 66% (4266/6463) Checking out files: 67% (4331/6463) Checking out files: 68% (4395/6463) Checking out files: 69% (4460/6463) Checking out files: 70% (4525/6463) Checking out files: 71% (4589/6463) Checking out files: 72% (4654/6463) Checking out files: 73% (4718/6463) Checking out files: 74% (4783/6463) Checking out files: 75% (4848/6463) Checking out files: 76% (4912/6463) Checking out files: 77% (4977/6463) Checking out files: 78% (5042/6463) Checking out files: 79% (5106/6463) Checking out files: 80% (5171/6463) Checking out files: 81% (5236/6463) Checking out files: 82% (5300/6463) Checking out files: 83% (5365/6463) Checking out files: 84% (5429/6463) Checking out files: 85% (5494/6463) Checking out files: 86% (5559/6463) Checking out files: 87% (5623/6463) Checking out files: 88% (5688/6463) Checking out files: 89% (5753/6463) Checking out files: 90% (5817/6463) Checking out files: 91% (5882/6463) Checking out files: 92% (5946/6463) Checking out files: 93% (6011/6463) Checking out files: 94% (6076/6463) Checking out files: 95% (6140/6463) Checking out files: 96% (6205/6463) Checking out files: 97% (6270/6463) Checking out files: 98% (6334/6463) Checking out files: 99% (6399/6463) Checking out files: 100% (6463/6463) Checking out files: 100% (6463/6463), done. Submodule 'dtc' (https://git.qemu.org/git/dtc.git) registered for path 'dtc' Cloning into 'dtc'... Submodule path 'dtc': checked out '88f18909db731a627456f26d779445f84e449536' Submodule 'ui/keycodemapdb' (https://git.qemu.org/git/keycodemapdb.git) registered for path 'ui/keycodemapdb' Cloning into 'ui/keycodemapdb'... Submodule path 'ui/keycodemapdb': checked out '6b3d716e2b6472eb7189d3220552280ef3d832ce' COPYRUNNER RUN test-quick in qemu:centos7 Packages installed: SDL-devel-1.2.15-14.el7.x86_64 bison-3.0.4-1.el7.x86_64 bzip2-1.0.6-13.el7.x86_64 bzip2-devel-1.0.6-13.el7.x86_64 ccache-3.3.4-1.el7.x86_64 csnappy-devel-0-6.20150729gitd7bc683.el7.x86_64 flex-2.5.37-3.el7.x86_64 gcc-4.8.5-28.el7_5.1.x86_64 gettext-0.19.8.1-2.el7.x86_64 git-1.8.3.1-14.el7_5.x86_64 glib2-devel-2.54.2-2.el7.x86_64 libaio-devel-0.3.109-13.el7.x86_64 libepoxy-devel-1.3.1-2.el7_5.x86_64 libfdt-devel-1.4.6-1.el7.x86_64 lzo-devel-2.06-8.el7.x86_64 make-3.82-23.el7.x86_64 mesa-libEGL-devel-17.2.3-8.20171019.el7.x86_64 mesa-libgbm-devel-17.2.3-8.20171019.el7.x86_64 nettle-devel-2.7.1-8.el7.x86_64 package g++ is not installed package librdmacm-devel is not installed pixman-devel-0.34.0-1.el7.x86_64 spice-glib-devel-0.34-3.el7_5.2.x86_64 spice-server-devel-0.14.0-2.el7_5.5.x86_64 tar-1.26-34.el7.x86_64 vte-devel-0.28.2-10.el7.x86_64 xen-devel-4.8.4.43.ge52ec4b787-1.el7.x86_64 zlib-devel-1.2.7-17.el7.x86_64 Environment
Re: [Qemu-devel] [PATCH V9 0/9] add pvpanic mmio support
Hi, This series failed docker-mingw@fedora build test. Please find the testing commands and their output below. If you have Docker installed, you can probably reproduce it locally. Message-id: 1543262162-6351-1-git-send-email-peng.h...@zte.com.cn Subject: [Qemu-devel] [PATCH V9 0/9] add pvpanic mmio support Type: series === TEST SCRIPT BEGIN === #!/bin/bash time make docker-test-mingw@fedora SHOW_ENV=1 J=8 === TEST SCRIPT END === Updating 3c8cf5a9c21ff8782164d1def7f44bd888713384 Switched to a new branch 'test' 3159b16 pvpanic : update pvpanic document 043c070 hw/misc/pvpanic: realize the configure interface 86ea086 hw/misc/pvpanic: preparing for adding configure interface af8de03 hw/misc/pvpanic: add configure query interface 63deb69 hw/arm/virt: add pvpanic device in virt acpi table 272983e hw/arm/virt: Use the pvpanic device a0bdaee hw/misc/pvpanic: Add the MMIO interface fe0cdc7e hw/misc/pvpanic: Cosmetic renaming 65de96a hw/misc/pvpanic: Build the pvpanic device in $(common-obj) === OUTPUT BEGIN === BUILD fedora make[1]: Entering directory `/var/tmp/patchew-tester-tmp-txwecgp8/src' GEN /var/tmp/patchew-tester-tmp-txwecgp8/src/docker-src.2018-11-27-21.43.06.22116/qemu.tar Cloning into '/var/tmp/patchew-tester-tmp-txwecgp8/src/docker-src.2018-11-27-21.43.06.22116/qemu.tar.vroot'... done. Checking out files: 46% (3012/6463) Checking out files: 47% (3038/6463) Checking out files: 48% (3103/6463) Checking out files: 49% (3167/6463) Checking out files: 50% (3232/6463) Checking out files: 51% (3297/6463) Checking out files: 52% (3361/6463) Checking out files: 53% (3426/6463) Checking out files: 54% (3491/6463) Checking out files: 55% (3555/6463) Checking out files: 56% (3620/6463) Checking out files: 57% (3684/6463) Checking out files: 58% (3749/6463) Checking out files: 59% (3814/6463) Checking out files: 60% (3878/6463) Checking out files: 61% (3943/6463) Checking out files: 62% (4008/6463) Checking out files: 63% (4072/6463) Checking out files: 64% (4137/6463) Checking out files: 65% (4201/6463) Checking out files: 66% (4266/6463) Checking out files: 67% (4331/6463) Checking out files: 68% (4395/6463) Checking out files: 69% (4460/6463) Checking out files: 70% (4525/6463) Checking out files: 71% (4589/6463) Checking out files: 72% (4654/6463) Checking out files: 73% (4718/6463) Checking out files: 74% (4783/6463) Checking out files: 75% (4848/6463) Checking out files: 76% (4912/6463) Checking out files: 77% (4977/6463) Checking out files: 78% (5042/6463) Checking out files: 79% (5106/6463) Checking out files: 80% (5171/6463) Checking out files: 81% (5236/6463) Checking out files: 82% (5300/6463) Checking out files: 83% (5365/6463) Checking out files: 84% (5429/6463) Checking out files: 85% (5494/6463) Checking out files: 86% (5559/6463) Checking out files: 87% (5623/6463) Checking out files: 88% (5688/6463) Checking out files: 89% (5753/6463) Checking out files: 90% (5817/6463) Checking out files: 91% (5882/6463) Checking out files: 92% (5946/6463) Checking out files: 93% (6011/6463) Checking out files: 94% (6076/6463) Checking out files: 95% (6140/6463) Checking out files: 96% (6205/6463) Checking out files: 97% (6270/6463) Checking out files: 98% (6334/6463) Checking out files: 99% (6399/6463) Checking out files: 100% (6463/6463) Checking out files: 100% (6463/6463), done. Submodule 'dtc' (https://git.qemu.org/git/dtc.git) registered for path 'dtc' Cloning into 'dtc'... Submodule path 'dtc': checked out '88f18909db731a627456f26d779445f84e449536' Submodule 'ui/keycodemapdb' (https://git.qemu.org/git/keycodemapdb.git) registered for path 'ui/keycodemapdb' Cloning into 'ui/keycodemapdb'... Submodule path 'ui/keycodemapdb': checked out '6b3d716e2b6472eb7189d3220552280ef3d832ce' COPYRUNNER RUN test-mingw in qemu:fedora Packages installed: SDL2-devel-2.0.9-1.fc28.x86_64 bc-1.07.1-5.fc28.x86_64 bison-3.0.4-9.fc28.x86_64 bluez-libs-devel-5.50-1.fc28.x86_64 brlapi-devel-0.6.7-19.fc28.x86_64 bzip2-1.0.6-26.fc28.x86_64 bzip2-devel-1.0.6-26.fc28.x86_64 ccache-3.4.2-2.fc28.x86_64 clang-6.0.1-2.fc28.x86_64 device-mapper-multipath-devel-0.7.4-3.git07e7bd5.fc28.x86_64 findutils-4.6.0-19.fc28.x86_64 flex-2.6.1-7.fc28.x86_64 gcc-8.2.1-5.fc28.x86_64 gcc-c++-8.2.1-5.fc28.x86_64 gettext-0.19.8.1-14.fc28.x86_64 git-2.17.2-1.fc28.x86_64 glib2-devel-2.56.3-2.fc28.x86_64 glusterfs-api-devel-4.1.5-1.fc28.x86_64 gnutls-devel-3.6.4-1.fc28.x86_64 gtk3-devel-3.22.30-1.fc28.x86_64 hostname-3.20-3.fc28.x86_64 libaio-devel-0.3.110-11.fc28.x86_64 libasan-8.2.1-5.fc28.x86_64 libattr-devel-2.4.48-3.fc28.x86_64 libcap-devel-2.25-9.fc28.x86_64 libcap-ng-devel-0.7.9-4.fc28.x86_64 libcurl-devel-7.59.0-8.fc28.x86_64 libfdt-devel-1.4.7-1.fc28.x86_64 libpng-devel-1.6.34-6.fc28.x86_64 librbd-devel-12.2
Re: [Qemu-devel] [PATCH v5 09/36] ppc/xive: notify the CPU when the interrupt priority is more privileged
On Wed, Nov 28, 2018 at 01:32:21PM +1100, Benjamin Herrenschmidt wrote: > On Wed, 2018-11-28 at 11:13 +1100, David Gibson wrote: > > Don't you need a cast to avoid (nsr << 8) being a shift-wider-than-size? > > Shouldn't be a problem as long as it fits in an int, no ? I dunno, I can never remember the rules about when C extends and when it doesn't. I'm not sure anybody does, which is kind of the point. -- 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 v5 11/36] spapr/xive: use the VCPU id as a NVT identifier
On Fri, Nov 16, 2018 at 11:57:04AM +0100, Cédric Le Goater wrote: > The IVPE scans the O/S CAM line of the XIVE thread interrupt contexts > to find a matching Notification Virtual Target (NVT) among the NVTs > dispatched on the HW processor threads. > > On a real system, the thread interrupt contexts are updated by the > hypervisor when a Virtual Processor is scheduled to run on a HW > thread. Under QEMU, the model emulates the same behavior by hardwiring > the NVT identifier in the thread context registers at reset. > > The NVT identifier used by the sPAPRXive model is the VCPU id. The END > identifier is also derived from the VCPU id. A set of helpers doing > the conversion between identifiers are provided for the hcalls > configuring the sources and the ENDs. > > The model does not need a NVT table but The XiveRouter NVT operations > are provided to perform some extra checks in the routing algorithm. > > Signed-off-by: Cédric Le Goater > --- > include/hw/ppc/spapr_xive.h | 17 + > include/hw/ppc/xive.h | 3 + > hw/intc/spapr_xive.c| 136 > hw/intc/xive.c | 9 +++ > 4 files changed, 165 insertions(+) > > diff --git a/include/hw/ppc/spapr_xive.h b/include/hw/ppc/spapr_xive.h > index 06727bd86aa9..3f65b8f485fd 100644 > --- a/include/hw/ppc/spapr_xive.h > +++ b/include/hw/ppc/spapr_xive.h > @@ -43,4 +43,21 @@ bool spapr_xive_irq_disable(sPAPRXive *xive, uint32_t > lisn); > void spapr_xive_pic_print_info(sPAPRXive *xive, Monitor *mon); > qemu_irq spapr_xive_qirq(sPAPRXive *xive, uint32_t lisn); > > +/* > + * sPAPR NVT and END indexing helpers > + */ > +uint32_t spapr_xive_nvt_to_target(sPAPRXive *xive, uint8_t nvt_blk, > + uint32_t nvt_idx); > +int spapr_xive_target_to_nvt(sPAPRXive *xive, uint32_t target, > +uint8_t *out_nvt_blk, uint32_t *out_nvt_idx); > +int spapr_xive_cpu_to_nvt(sPAPRXive *xive, PowerPCCPU *cpu, > + uint8_t *out_nvt_blk, uint32_t *out_nvt_idx); > + > +int spapr_xive_end_to_target(sPAPRXive *xive, uint8_t end_blk, uint32_t > end_idx, > + uint32_t *out_server, uint8_t *out_prio); > +int spapr_xive_target_to_end(sPAPRXive *xive, uint32_t target, uint8_t prio, > + uint8_t *out_end_blk, uint32_t *out_end_idx); > +int spapr_xive_cpu_to_end(sPAPRXive *xive, PowerPCCPU *cpu, uint8_t prio, > + uint8_t *out_end_blk, uint32_t *out_end_idx); > + > #endif /* PPC_SPAPR_XIVE_H */ > diff --git a/include/hw/ppc/xive.h b/include/hw/ppc/xive.h > index e715a6c6923d..e6931ddaa83f 100644 > --- a/include/hw/ppc/xive.h > +++ b/include/hw/ppc/xive.h > @@ -187,6 +187,8 @@ typedef struct XiveRouter { > #define XIVE_ROUTER_GET_CLASS(obj) \ > OBJECT_GET_CLASS(XiveRouterClass, (obj), TYPE_XIVE_ROUTER) > > +typedef struct XiveTCTX XiveTCTX; > + > typedef struct XiveRouterClass { > SysBusDeviceClass parent; > > @@ -201,6 +203,7 @@ typedef struct XiveRouterClass { > XiveNVT *nvt); > int (*set_nvt)(XiveRouter *xrtr, uint8_t nvt_blk, uint32_t nvt_idx, > XiveNVT *nvt); > +void (*reset_tctx)(XiveRouter *xrtr, XiveTCTX *tctx); > } XiveRouterClass; > > void xive_eas_pic_print_info(XiveEAS *eas, uint32_t lisn, Monitor *mon); > diff --git a/hw/intc/spapr_xive.c b/hw/intc/spapr_xive.c > index 5d038146c08e..3bf77ace11a2 100644 > --- a/hw/intc/spapr_xive.c > +++ b/hw/intc/spapr_xive.c > @@ -199,6 +199,139 @@ static int spapr_xive_set_end(XiveRouter *xrtr, > return 0; > } > > +static int spapr_xive_get_nvt(XiveRouter *xrtr, > + uint8_t nvt_blk, uint32_t nvt_idx, XiveNVT > *nvt) > +{ > +sPAPRXive *xive = SPAPR_XIVE(xrtr); > +uint32_t vcpu_id = spapr_xive_nvt_to_target(xive, nvt_blk, nvt_idx); > +PowerPCCPU *cpu = spapr_find_cpu(vcpu_id); > + > +if (!cpu) { > +return -1; > +} > + > +/* > + * sPAPR does not maintain a NVT table. Return that the NVT is > + * valid if we have found a matching CPU > + */ > +nvt->w0 = NVT_W0_VALID; > +return 0; > +} > + > +static int spapr_xive_set_nvt(XiveRouter *xrtr, > + uint8_t nvt_blk, uint32_t nvt_idx, XiveNVT > *nvt) > +{ > +/* no NVT table */ > +return 0; > +} > + > +/* > + * When a Virtual Processor is scheduled to run on a HW thread, the > + * hypervisor pushes its identifier in the OS CAM line. Under QEMU, we > + * need to emulate the same behavior. > + */ > +static void spapr_xive_reset_tctx(XiveRouter *xrtr, XiveTCTX *tctx) > +{ > +uint8_t nvt_blk; > +uint32_t nvt_idx; > +uint32_t nvt_cam; > + > +spapr_xive_cpu_to_nvt(SPAPR_XIVE(xrtr), POWERPC_CPU(tctx->cs), > + &nvt_blk, &nvt_idx); > + > +nvt_cam = cpu_to_be32(TM_QW1W2_VO | xive_tctx_cam_line(nvt_blk, > nvt_idx)); > +mem
Re: [Qemu-devel] [PATCH v5 08/36] ppc/xive: introduce a simplified XIVE presenter
On Wed, 2018-11-28 at 10:49 +1100, David Gibson wrote: > On Fri, Nov 16, 2018 at 11:57:01AM +0100, Cédric Le Goater wrote: > > The last sub-engine of the XIVE architecture is the Interrupt > > Virtualization Presentation Engine (IVPE). On HW, they share elements, > > the Power Bus interface (CQ), the routing table descriptors, and they > > can be combined in the same HW logic. We do the same in QEMU and > > combine both engines in the XiveRouter for simplicity. > > Ok, I'm not entirely convinced combining the IVPE and IVRE into a > single object is a good idea, but we can probably discuss that once > I've read further. Keep in mind that the communication between the two is a bit more hairy than simple notifications, though. Especially once we start implementing escalation interrupts or worse, groups... > > When the IVRE has completed its job of matching an event source with a > > Notification Virtual Target (NVT) to notify, it forwards the event > > notification to the IVPE sub-engine. The IVPE scans the thread > > interrupt contexts of the Notification Virtual Targets (NVT) > > dispatched on the HW processor threads and if a match is found, it > > signals the thread. If not, the IVPE escalates the notification to > > some other targets and records the notification in a backlog queue. > > > > The IVPE maintains the thread interrupt context state for each of its > > NVTs not dispatched on HW processor threads in the Notification > > Virtual Target table (NVTT). > > > > The model currently only supports single NVT notifications. > > > > Signed-off-by: Cédric Le Goater > > --- > > include/hw/ppc/xive.h | 13 +++ > > include/hw/ppc/xive_regs.h | 22 > > hw/intc/xive.c | 223 + > > 3 files changed, 258 insertions(+) > > > > diff --git a/include/hw/ppc/xive.h b/include/hw/ppc/xive.h > > index 5987f26ddb98..e715a6c6923d 100644 > > --- a/include/hw/ppc/xive.h > > +++ b/include/hw/ppc/xive.h > > @@ -197,6 +197,10 @@ typedef struct XiveRouterClass { > > XiveEND *end); > > int (*set_end)(XiveRouter *xrtr, uint8_t end_blk, uint32_t end_idx, > > XiveEND *end); > > +int (*get_nvt)(XiveRouter *xrtr, uint8_t nvt_blk, uint32_t nvt_idx, > > + XiveNVT *nvt); > > +int (*set_nvt)(XiveRouter *xrtr, uint8_t nvt_blk, uint32_t nvt_idx, > > + XiveNVT *nvt); > > As with the ENDs, I don't think get/set is a good interface for a > bigger-than-word-size object. > > > } XiveRouterClass; > > > > void xive_eas_pic_print_info(XiveEAS *eas, uint32_t lisn, Monitor *mon); > > @@ -207,6 +211,10 @@ int xive_router_get_end(XiveRouter *xrtr, uint8_t > > end_blk, uint32_t end_idx, > > XiveEND *end); > > int xive_router_set_end(XiveRouter *xrtr, uint8_t end_blk, uint32_t > > end_idx, > > XiveEND *end); > > +int xive_router_get_nvt(XiveRouter *xrtr, uint8_t nvt_blk, uint32_t > > nvt_idx, > > +XiveNVT *nvt); > > +int xive_router_set_nvt(XiveRouter *xrtr, uint8_t nvt_blk, uint32_t > > nvt_idx, > > +XiveNVT *nvt); > > > > /* > > * XIVE END ESBs > > @@ -274,4 +282,9 @@ extern const MemoryRegionOps xive_tm_ops; > > > > void xive_tctx_pic_print_info(XiveTCTX *tctx, Monitor *mon); > > > > +static inline uint32_t xive_tctx_cam_line(uint8_t nvt_blk, uint32_t > > nvt_idx) > > +{ > > +return (nvt_blk << 19) | nvt_idx; > > I'm guessing this formula is the standard way of combining the NVT > block and index into a single word? If so, I think we should > standardize on passing a single word "nvt_id" around and only > splitting it when we need to use the block separately. Same goes for > the end_id, assuming there's a standard way of putting that into a > single word. That will address the point I raised earlier about lisn > being passed around as a single word, but these later stage ids being > split. > > We'll probably want some inlines or macros to build an > nvt/end/lisn/whatever id from block and index as well. > > > +} > > + > > #endif /* PPC_XIVE_H */ > > diff --git a/include/hw/ppc/xive_regs.h b/include/hw/ppc/xive_regs.h > > index 2e3d6cb507da..05cb992d2815 100644 > > --- a/include/hw/ppc/xive_regs.h > > +++ b/include/hw/ppc/xive_regs.h > > @@ -158,4 +158,26 @@ typedef struct XiveEND { > > #define END_W7_F1_LOG_SERVER_ID PPC_BITMASK32(1, 31) > > } XiveEND; > > > > +/* Notification Virtual Target (NVT) */ > > +typedef struct XiveNVT { > > +uint32_tw0; > > +#define NVT_W0_VALID PPC_BIT32(0) > > +uint32_tw1; > > +uint32_tw2; > > +uint32_tw3; > > +uint32_tw4; > > +uint32_tw5; > > +uint32_tw6; > > +uint32_tw7; > > +uint32_tw8; > > +#define NVT_W8_GRP_VALID PPC_BIT32(0) > > +uint32_tw9; > > +
Re: [Qemu-devel] [PATCH v5 09/36] ppc/xive: notify the CPU when the interrupt priority is more privileged
On Wed, 2018-11-28 at 11:13 +1100, David Gibson wrote: > Don't you need a cast to avoid (nsr << 8) being a shift-wider-than-size? Shouldn't be a problem as long as it fits in an int, no ? Cheers, Ben.
Re: [Qemu-devel] [RFC 38/48] translator: implement 2-pass translation
On Tue, Nov 27, 2018 at 14:06:57 -0500, Emilio G. Cota wrote: > On Tue, Nov 27, 2018 at 14:48:11 +, Alex Bennée wrote: > > With a little tweaking to the TCG we could then insert > > our instrumentation at the end of the pass with all the knowledge we > > want to export to the plugin. > > After .translate_insn has returned for the last instruction, how > do we insert the instrumentation that the plugin wants--say, a TB > callback at the beginning of the TB, memory callbacks for the > 2nd instruction, and an insn callback before the 3rd instruction > executes? > > I don't see how we could achieve that with "a little tweaking" > instead of a 2nd pass, but I'd love to be wrong =) (snip) > > I don't quite follow. When we've done all our translation into TCG ops > > haven't we by definition defined the TB? > > Yes, that's precisely my point. > > The part that's missing is that once the TB is defined, we want to > insert instrumentation. Unfortunately, the "TCG ops" we get after > the 1st pass (no instrumentation), are very different from the list > of "TCG ops" that we get after the 2nd pass (after having injected > instrumentation). Could we get the same output of the 2nd pass, > just by using the output of the 1st and the list of injection points? > It's probably possible, but it seems very hard to do. (Think for > instance of memory callbacks, and further the complication of when > they use helpers). > > The only reasonable way to do this I think would be to leave behind > "placeholder" TCG ops, that then we could scan to add further TCG ops. > But you'll agree with me that the 2nd pass is simpler :P It might not be that much simpler after all! I am exploring the approach you suggested, that is IIUC to do a single pass and then walk the list of Ops, adding (and reordering) Ops based on what the plugins have requested. Contrary to what I wrote earlier today (quoted above), this approach seems quite promising, and certainly less ugly than doing the 2 passes. I just wrote some code to go over the list and add TB callbacks, which go right before the first insn_start Op. The code is hack-ish in that we first generate the TCG ops we need, which get added to the end of the ops list, and then we go over those and move them to where we want them to be (before insn_start, in this case). But it works and it's less of a hack than doing the whole 2nd pass. Insn callbacks will be trivial to implement this way; memory callbacks should be harder because there are several qemu_ld/st opcodes, but it should be doable; last, memory instrumentation of helpers might actually be easier than with the 2 passes, because here we just have to look for a Call TCG op to know whether a guest instruction uses helpers, and if it does we can wrap the call with the helpers to generate the setting/resetting of CPUState.plugin_mem_cbs. I'll try to do what's in the previous paragraph tomorrow -- I'm appending what I did so far. Thanks, Emilio --- diff --git a/accel/tcg/translator.c b/accel/tcg/translator.c index ee9e179e14..232f645cd4 100644 --- a/accel/tcg/translator.c +++ b/accel/tcg/translator.c @@ -18,6 +18,7 @@ #include "exec/gen-icount.h" #include "exec/log.h" #include "exec/translator.h" +#include "exec/plugin-gen.h" /* Pairs with tcg_clear_temp_count. To be called by #TranslatorOps.{translate_insn,tb_stop} if @@ -142,6 +143,11 @@ void translator_loop(const TranslatorOps *ops, DisasContextBase *db, gen_tb_end(db->tb, db->num_insns - bp_insn); if (plugin_enabled) { +/* collect the plugins' instrumentation */ +qemu_plugin_tb_trans_cb(cpu, &tcg_ctx->plugin_tb); +/* inject instrumentation */ +qemu_plugin_gen_inject(); +/* done */ tcg_ctx->plugin_insn = NULL; } diff --git a/accel/tcg/plugin-gen.c b/accel/tcg/plugin-gen.c index 75f182be37..cb5dbadc3c 100644 --- a/accel/tcg/plugin-gen.c +++ b/accel/tcg/plugin-gen.c @@ -1,4 +1,5 @@ #include "qemu/osdep.h" +#include "qemu/queue.h" #include "cpu.h" #include "tcg/tcg.h" #include "tcg/tcg-op.h" @@ -169,8 +170,61 @@ static void gen_vcpu_udata_cb(struct qemu_plugin_dyn_cb *cb) tcg_temp_free_i32(cpu_index); } -void qemu_plugin_gen_vcpu_udata_callbacks(struct qemu_plugin_dyn_cb_arr *arr) +/* check that @a comes before @b */ +static inline void ops_check(const TCGOp *a, const TCGOp *b) { +const TCGOp *op; +bool seen_a = false; +bool seen_b = false; + +tcg_debug_assert(a != b); +QTAILQ_FOREACH(op, &tcg_ctx->ops, link) { +if (op == a) { +tcg_debug_assert(!seen_b); +seen_a = true; +} else if (op == b) { +tcg_debug_assert(seen_a); +seen_b = true; +break; +} +} +} + +/* + * Move ops from @from to @dest. + * @from must come after @dest in the list. + */ +static void ops_move(TCGOp *dest, TCGOp *from) +{ +TCGOp *curr; + +#ifdef CONFIG_DEBUG_TCG +ops_check(dest, from); +#endi
Re: [Qemu-devel] [SeaBIOS] SeaBIOS booting time optimization
On Wed, Nov 21, 2018 at 12:43:34AM -0500, Stefan Berger wrote: > On 11/20/18 11:51 AM, Stefano Garzarella wrote: > > On Tue, Nov 20, 2018 at 5:13 PM Steve Douthit > > wrote: > > > On 11/20/18 10:55 AM, Kevin O'Connor wrote: > > > > FYI, this was raised a few months ago - see: > > > > > > > > https://mail.coreboot.org/pipermail/seabios/2018-March/012186.html > > > > > > > > IIRC, it should be possible to verify the TPM device is present before > > > > trying to wait for it. > > > We could skip probing entirely if there's no TCPA or TPM2 ACPI tables. > > > There'd need to be some option to force probing in the case of > > > missing/broken ACPI configurations. > > I've just tried the > > 0001-tpm-Check-for-TPM-related-ACPI-tables-before-attempt.patch > > (https://mail.coreboot.org/pipermail/seabios/2018-March/012188.html) > > and it solves my issue with the TPM. > > I have tried it with the attached patch of that mail. We have to apply it, > also for QEMU. It is this patch here: Okay, thanks. I applied Steve's patch. -Kevin
Re: [Qemu-devel] [PATCH] riscv/cpu: use device_class_set_parent_realize
Hi, Palmer On 11/28/18 8:34 AM, Palmer Dabbelt wrote: On Mon, 26 Nov 2018 01:06:33 PST (-0800), Bastian Koppelmann wrote: On 11/26/18 4:20 AM, Mao Zhongyi wrote: Signed-off-by: Mao Zhongyi --- target/riscv/cpu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) Reviewed-by: Bastian Koppelmann Shouldn't we also use device_class_set_parent_reset right below this? device_class_set_parent_reset only used for DeviceClass *dc->reset, here is CPUClass *cc->reset. Thanks, Mao Either way, I'll queue this one for 3.2. Thanks!
Re: [Qemu-devel] [RFC 23/48] translator: add plugin_insn argument to translate_insn
On Tue, Nov 27, 2018 at 19:54:02 -0500, Emilio G. Cota wrote: > To avoid altering the signature of .translate_insn, I've modified > arm_ldl_code directly, as follows: > > uint32_t insn = cpu_ldl_code(env, addr); > + > if (bswap_code(sctlr_b)) { > -return bswap32(insn); > +insn = bswap32(insn); > +} > +if (tcg_ctx->plugin_insn) { > +qemu_plugin_insn_append(tcg_ctx->plugin_insn, &insn, sizeof(insn)); > } > return insn; > } Turns out it got even more complicated with thumb, since instructions can be 16 or 32 bits. I ended up with the appended (qemu_plugin_insn_append() returns when the first argument is NULL). Emilio diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c index 88195ab949..e6caaff976 100644 --- a/target/arm/translate-a64.c +++ b/target/arm/translate-a64.c @@ -38,6 +38,7 @@ #include "trace-tcg.h" #include "translate-a64.h" #include "qemu/atomic128.h" +#include "qemu/plugin.h" static TCGv_i64 cpu_X[32]; static TCGv_i64 cpu_pc; @@ -13321,6 +13322,7 @@ static void disas_a64_insn(CPUARMState *env, DisasContext *s) uint32_t insn; insn = arm_ldl_code(env, s->pc, s->sctlr_b); +qemu_plugin_insn_append(tcg_ctx->plugin_insn, &insn, sizeof(insn)); s->insn = insn; s->pc += 4; diff --git a/target/arm/translate.c b/target/arm/translate.c index 7c4675ffd8..7523257b85 100644 --- a/target/arm/translate.c +++ b/target/arm/translate.c @@ -36,6 +36,7 @@ #include "trace-tcg.h" #include "exec/log.h" +#include "qemu/plugin.h" #define ENABLE_ARCH_4Tarm_dc_feature(s, ARM_FEATURE_V4T) @@ -13234,6 +13235,7 @@ static void arm_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu) } insn = arm_ldl_code(env, dc->pc, dc->sctlr_b); +qemu_plugin_insn_append(tcg_ctx->plugin_insn, &insn, sizeof(insn)); dc->insn = insn; dc->pc += 4; disas_arm_insn(dc, insn); @@ -13304,11 +13306,16 @@ static void thumb_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu) insn = arm_lduw_code(env, dc->pc, dc->sctlr_b); is_16bit = thumb_insn_is_16bit(dc, insn); dc->pc += 2; -if (!is_16bit) { +if (is_16bit) { +uint16_t insn16 = insn; + +qemu_plugin_insn_append(tcg_ctx->plugin_insn, &insn16, sizeof(insn16)); +} else { uint32_t insn2 = arm_lduw_code(env, dc->pc, dc->sctlr_b); insn = insn << 16 | insn2; dc->pc += 2; +qemu_plugin_insn_append(tcg_ctx->plugin_insn, &insn, sizeof(insn)); } dc->insn = insn;
[Qemu-devel] (no subject)
>From af4497f2b161bb4165acb8eee5cae3f2a7ea2227 Mon Sep 17 00:00:00 2001 From: John Arbuckle Date: Tue, 27 Nov 2018 20:01:20 -0500 Subject: [PATCH] ui/cocoa.m: fix crash due to cocoa_refresh() on Mac OS 10.14 Mac OS 10.14 only wants UI code to be called from the main thread. The cocoa_refresh() function is called on another thread and this causes a crash to take place. To fix this problem the cocoa_refresh() code is called from the main thread only. Signed-off-by: John Arbuckle --- ui/cocoa.m | 59 ++- 1 file changed, 34 insertions(+), 25 deletions(-) diff --git a/ui/cocoa.m b/ui/cocoa.m index ecf12bfc2e..17c168d08f 100644 --- a/ui/cocoa.m +++ b/ui/cocoa.m @@ -972,6 +972,8 @@ - (void)openDocumentation:(NSString *)filename; - (IBAction) do_about_menu_item: (id) sender; - (void)make_about_window; - (void)adjustSpeed:(id)sender; +- (void) cocoa_refresh; +- (void) cocoa_refresh_internal: (id) dummy; @end @implementation QemuCocoaAppController @@ -1406,6 +1408,37 @@ - (void)adjustSpeed:(id)sender COCOA_DEBUG("cpu throttling at %d%c\n", cpu_throttle_get_percentage(), '%'); } +- (void) cocoa_refresh +{ +[self performSelectorOnMainThread: @selector(cocoa_refresh_internal:) withObject: nil waitUntilDone: YES]; +} + +- (void) cocoa_refresh_internal: (id) dummy +{ +COCOA_DEBUG("qemu_cocoa: cocoa_refresh\n"); +graphic_hw_update(NULL); + +if (qemu_input_is_absolute()) { +if (![cocoaView isAbsoluteEnabled]) { +if ([cocoaView isMouseGrabbed]) { +[cocoaView ungrabMouse]; +} +} +[cocoaView setAbsoluteEnabled:YES]; +} + +NSDate *distantPast; +NSEvent *event; +distantPast = [NSDate distantPast]; +do { +event = [NSApp nextEventMatchingMask:NSEventMaskAny untilDate:distantPast + inMode: NSDefaultRunLoopMode dequeue:YES]; +if (event != nil) { +[cocoaView handleEvent:event]; +} +} while(event != nil); +} + @end @@ -1579,31 +1612,7 @@ static void cocoa_switch(DisplayChangeListener *dcl, static void cocoa_refresh(DisplayChangeListener *dcl) { -NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; - -COCOA_DEBUG("qemu_cocoa: cocoa_refresh\n"); -graphic_hw_update(NULL); - -if (qemu_input_is_absolute()) { -if (![cocoaView isAbsoluteEnabled]) { -if ([cocoaView isMouseGrabbed]) { -[cocoaView ungrabMouse]; -} -} -[cocoaView setAbsoluteEnabled:YES]; -} - -NSDate *distantPast; -NSEvent *event; -distantPast = [NSDate distantPast]; -do { -event = [NSApp nextEventMatchingMask:NSEventMaskAny untilDate:distantPast -inMode: NSDefaultRunLoopMode dequeue:YES]; -if (event != nil) { -[cocoaView handleEvent:event]; -} -} while(event != nil); -[pool release]; +[[NSApp delegate] cocoa_refresh]; } static void cocoa_cleanup(void) -- 2.14.3 (Apple Git-98)
Re: [Qemu-devel] [PATCH v5 10/36] spapr/xive: introduce a XIVE interrupt controller
On Fri, Nov 16, 2018 at 11:57:03AM +0100, Cédric Le Goater wrote: > sPAPRXive models the XIVE interrupt controller of the sPAPR machine. > It inherits from the XiveRouter and provisions storage for the routing > tables : > > - Event Assignment Structure (EAS) > - Event Notification Descriptor (END) > > The sPAPRXive model incorporates an internal XiveSource for the IPIs > and for the interrupts of the virtual devices of the guest. This model > is consistent with XIVE architecture which also incorporates an > internal IVSE for IPIs and accelerator interrupts in the IVRE > sub-engine. > > The sPAPRXive model exports two memory regions, one for the ESB > trigger and management pages used to control the sources and one for > the TIMA pages. They are mapped by default at the addresses found on > chip 0 of a baremetal system. This is also consistent with the XIVE > architecture which defines a Virtualization Controller BAR for the > internal IVSE ESB pages and a Thread Managment BAR for the TIMA. > > Signed-off-by: Cédric Le Goater > --- > default-configs/ppc64-softmmu.mak | 1 + > include/hw/ppc/spapr_xive.h | 46 + > hw/intc/spapr_xive.c | 323 ++ > hw/intc/Makefile.objs | 1 + > 4 files changed, 371 insertions(+) > create mode 100644 include/hw/ppc/spapr_xive.h > create mode 100644 hw/intc/spapr_xive.c > > diff --git a/default-configs/ppc64-softmmu.mak > b/default-configs/ppc64-softmmu.mak > index 2d1e7c5c4668..7f34ad0528ed 100644 > --- a/default-configs/ppc64-softmmu.mak > +++ b/default-configs/ppc64-softmmu.mak > @@ -17,6 +17,7 @@ CONFIG_XICS=$(CONFIG_PSERIES) > CONFIG_XICS_SPAPR=$(CONFIG_PSERIES) > CONFIG_XICS_KVM=$(call land,$(CONFIG_PSERIES),$(CONFIG_KVM)) > CONFIG_XIVE=$(CONFIG_PSERIES) > +CONFIG_XIVE_SPAPR=$(CONFIG_PSERIES) > CONFIG_MEM_DEVICE=y > CONFIG_DIMM=y > CONFIG_SPAPR_RNG=y > diff --git a/include/hw/ppc/spapr_xive.h b/include/hw/ppc/spapr_xive.h > new file mode 100644 > index ..06727bd86aa9 > --- /dev/null > +++ b/include/hw/ppc/spapr_xive.h > @@ -0,0 +1,46 @@ > +/* > + * QEMU PowerPC sPAPR XIVE interrupt controller model > + * > + * Copyright (c) 2017-2018, IBM Corporation. > + * > + * This code is licensed under the GPL version 2 or later. See the > + * COPYING file in the top-level directory. > + */ > + > +#ifndef PPC_SPAPR_XIVE_H > +#define PPC_SPAPR_XIVE_H > + > +#include "hw/sysbus.h" > +#include "hw/ppc/xive.h" > + > +#define TYPE_SPAPR_XIVE "spapr-xive" > +#define SPAPR_XIVE(obj) OBJECT_CHECK(sPAPRXive, (obj), TYPE_SPAPR_XIVE) > + > +typedef struct sPAPRXive { > +XiveRouterparent; > + > +/* Internal interrupt source for IPIs and virtual devices */ > +XiveSourcesource; > +hwaddrvc_base; > + > +/* END ESB MMIOs */ > +XiveENDSource end_source; > +hwaddrend_base; > + > +/* Routing table */ > +XiveEAS *eat; > +uint32_t nr_irqs; > +XiveEND *endt; > +uint32_t nr_ends; > + > +/* TIMA mapping address */ > +hwaddrtm_base; > +MemoryRegion tm_mmio; > +} sPAPRXive; > + > +bool spapr_xive_irq_enable(sPAPRXive *xive, uint32_t lisn, bool lsi); > +bool spapr_xive_irq_disable(sPAPRXive *xive, uint32_t lisn); > +void spapr_xive_pic_print_info(sPAPRXive *xive, Monitor *mon); > +qemu_irq spapr_xive_qirq(sPAPRXive *xive, uint32_t lisn); > + > +#endif /* PPC_SPAPR_XIVE_H */ > diff --git a/hw/intc/spapr_xive.c b/hw/intc/spapr_xive.c > new file mode 100644 > index ..5d038146c08e > --- /dev/null > +++ b/hw/intc/spapr_xive.c > @@ -0,0 +1,323 @@ > +/* > + * QEMU PowerPC sPAPR XIVE interrupt controller model > + * > + * Copyright (c) 2017-2018, IBM Corporation. > + * > + * This code is licensed under the GPL version 2 or later. See the > + * COPYING file in the top-level directory. > + */ > + > +#include "qemu/osdep.h" > +#include "qemu/log.h" > +#include "qapi/error.h" > +#include "target/ppc/cpu.h" > +#include "sysemu/cpus.h" > +#include "monitor/monitor.h" > +#include "hw/ppc/spapr.h" > +#include "hw/ppc/spapr_xive.h" > +#include "hw/ppc/xive.h" > +#include "hw/ppc/xive_regs.h" > + > +/* > + * XIVE Virtualization Controller BAR and Thread Managment BAR that we > + * use for the ESB pages and the TIMA pages > + */ > +#define SPAPR_XIVE_VC_BASE 0x00060100ull > +#define SPAPR_XIVE_TM_BASE 0x000603020318ull > + > +void spapr_xive_pic_print_info(sPAPRXive *xive, Monitor *mon) > +{ > +int i; > +uint32_t offset = 0; > + > +monitor_printf(mon, "XIVE Source %08x .. %08x\n", offset, > + offset + xive->source.nr_irqs - 1); > +xive_source_pic_print_info(&xive->source, offset, mon); > + > +monitor_printf(mon, "XIVE EAT %08x .. %08x\n", 0, xive->nr_irqs - 1); > +for (i = 0; i < xive->nr_irqs; i++) { > +xive_eas_pic_print_info(&xive->eat[i], i, mon); > +} > + > +monitor_printf(mon, "XIVE ENDT %08x .. %08x\n", 0, xive->nr_ends - 1);
Re: [Qemu-devel] [RFC 23/48] translator: add plugin_insn argument to translate_insn
On Mon, Nov 26, 2018 at 20:38:25 -0500, Emilio G. Cota wrote: > On Mon, Nov 26, 2018 at 11:30:25 -0800, Richard Henderson wrote: > > On 11/26/18 11:07 AM, Emilio G. Cota wrote: > > > The main reason why I added the qemu_plugin_insn_append calls > > > was to avoid reading the instructions twice from guest memory, > > > because I was worried that doing so might somehow alter the > > > guest's execution, e.g. what if we read a cross-page instruction, > > > and both pages mapped to the same TLB entry? We'd end up having > > > more TLB misses because instrumentation was enabled. > > > > A better solution for this, I think is to change direct calls from > > > > cpu_ldl_code(env, pc); > > to > > translator_ldl_code(dc_base, env, pc); > > > > instead of passing around a new argument separate from DisasContextBase? > > I think this + diff'ing pc_next should work to figure out the > contents and size of each instruction. I just tried doing things this way. For some targets like i386, the translator_ld* helpers work great; the instruction contents are copied, and through the helpers we get the sizes of the instructions as well. For ARM though (and maybe others, I haven't gone through all of them yet), arm_ldl_code does the following: /* Load an instruction and return it in the standard little-endian order */ static inline uint32_t arm_ldl_code(CPUARMState *env, target_ulong addr, bool sctlr_b) { uint32_t insn = cpu_ldl_code(env, addr); if (bswap_code(sctlr_b)) { return bswap32(insn); } return insn; } To avoid altering the signature of .translate_insn, I've modified arm_ldl_code directly, as follows: uint32_t insn = cpu_ldl_code(env, addr); + if (bswap_code(sctlr_b)) { -return bswap32(insn); +insn = bswap32(insn); +} +if (tcg_ctx->plugin_insn) { +qemu_plugin_insn_append(tcg_ctx->plugin_insn, &insn, sizeof(insn)); } return insn; } (NB. tcg_ctx->plugin_insn is updated by translator_loop on every iteration.) Let me know if you think I should do this differently. Thanks, Emilio
[Qemu-devel] What will happen if guest write to a memory address which not exists in any kvm memory slot?
For a multiple cpu guest, during cpu 0 delete a memory sot then add it, if cpu 1 write the memory address which belong to the deleted memory slot and not exist in PTE, kvm_mmu_page_fault fail, then return the QEMU with the reason KVM_EXIT_MMIO, QEMU will also fail, What will happen in Guest? This is the trace of kvm_set_memory_region, slot 0 is often deleted then added, Maybe there is a memory write in guest after delete and before add. # trace-bpfcc -I /usr/src/linux-headers-4.18.0-10-generic/include/uapi/linux/kvm.h \ 'p::kvm_set_memory_region(struct kvm *kvm, struct kvm_userspace_memory_region *mem), \ "slot %d addr %x size %x", mem->slot,mem->guest_phys_addr,mem->memory_size' PID TID COMMFUNC - 80198019qemu-system-x86 kvm_set_memory_region slot 0 addr 0 size 4000 80198019qemu-system-x86 kvm_set_memory_region slot 1 addr fffe size 0 80198019qemu-system-x86 kvm_set_memory_region slot 1 addr fffe size 2 80198019qemu-system-x86 kvm_set_memory_region slot 0 addr 0 size 0 80198019qemu-system-x86 kvm_set_memory_region slot 0 addr 0 size c 80198019qemu-system-x86 kvm_set_memory_region slot 2 addr c size 0 80198019qemu-system-x86 kvm_set_memory_region slot 2 addr c size 2 80198019qemu-system-x86 kvm_set_memory_region slot 3 addr e size 0 80198019qemu-system-x86 kvm_set_memory_region slot 3 addr e size 2 80198019qemu-system-x86 kvm_set_memory_region slot 4 addr 10 size 3ff0 80198019qemu-system-x86 kvm_set_memory_region slot 0 addr 0 size 0 80198019qemu-system-x86 kvm_set_memory_region slot 0 addr 0 size a
Re: [Qemu-devel] [PATCH] scsi: Address spurious clang warning
On Tue, 27 Nov 2018 at 18:49, John Snow wrote: > > Some versions of Clang prior to 6.0 (and some builds of clang after, > such as 6.0.1-2.fc28) fail to recognize { 0 } as a valid initializer > for a struct with subobjects when -Wmissing-braces is enabled. > > https://bugs.llvm.org/show_bug.cgi?id=21689 and > https://reviews.llvm.org/rL314499 suggests this should be fixed in 6.0, > but it might not be the case for older versions or downstream versions. > > For now, follow the precedent of ebf2a499 and replace the standard { 0 } > with the accepted { } to silence this warning and allow the build to > work under clang 6.0.1-2.fc28, and builds prior to 6.0. > > Signed-off-by: John Snow Applied to master as a build fix for rc3, thanks. -- PMM
Re: [Qemu-devel] [PATCH] riscv/cpu: use device_class_set_parent_realize
On Mon, 26 Nov 2018 01:06:33 PST (-0800), Bastian Koppelmann wrote: On 11/26/18 4:20 AM, Mao Zhongyi wrote: Signed-off-by: Mao Zhongyi --- target/riscv/cpu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) Reviewed-by: Bastian Koppelmann Shouldn't we also use device_class_set_parent_reset right below this? Either way, I'll queue this one for 3.2. Thanks!
Re: [Qemu-devel] [PATCH v5 08/36] ppc/xive: introduce a simplified XIVE presenter
On Fri, Nov 16, 2018 at 11:57:01AM +0100, Cédric Le Goater wrote: > The last sub-engine of the XIVE architecture is the Interrupt > Virtualization Presentation Engine (IVPE). On HW, they share elements, > the Power Bus interface (CQ), the routing table descriptors, and they > can be combined in the same HW logic. We do the same in QEMU and > combine both engines in the XiveRouter for simplicity. Ok, I'm not entirely convinced combining the IVPE and IVRE into a single object is a good idea, but we can probably discuss that once I've read further. > When the IVRE has completed its job of matching an event source with a > Notification Virtual Target (NVT) to notify, it forwards the event > notification to the IVPE sub-engine. The IVPE scans the thread > interrupt contexts of the Notification Virtual Targets (NVT) > dispatched on the HW processor threads and if a match is found, it > signals the thread. If not, the IVPE escalates the notification to > some other targets and records the notification in a backlog queue. > > The IVPE maintains the thread interrupt context state for each of its > NVTs not dispatched on HW processor threads in the Notification > Virtual Target table (NVTT). > > The model currently only supports single NVT notifications. > > Signed-off-by: Cédric Le Goater > --- > include/hw/ppc/xive.h | 13 +++ > include/hw/ppc/xive_regs.h | 22 > hw/intc/xive.c | 223 + > 3 files changed, 258 insertions(+) > > diff --git a/include/hw/ppc/xive.h b/include/hw/ppc/xive.h > index 5987f26ddb98..e715a6c6923d 100644 > --- a/include/hw/ppc/xive.h > +++ b/include/hw/ppc/xive.h > @@ -197,6 +197,10 @@ typedef struct XiveRouterClass { > XiveEND *end); > int (*set_end)(XiveRouter *xrtr, uint8_t end_blk, uint32_t end_idx, > XiveEND *end); > +int (*get_nvt)(XiveRouter *xrtr, uint8_t nvt_blk, uint32_t nvt_idx, > + XiveNVT *nvt); > +int (*set_nvt)(XiveRouter *xrtr, uint8_t nvt_blk, uint32_t nvt_idx, > + XiveNVT *nvt); As with the ENDs, I don't think get/set is a good interface for a bigger-than-word-size object. > } XiveRouterClass; > > void xive_eas_pic_print_info(XiveEAS *eas, uint32_t lisn, Monitor *mon); > @@ -207,6 +211,10 @@ int xive_router_get_end(XiveRouter *xrtr, uint8_t > end_blk, uint32_t end_idx, > XiveEND *end); > int xive_router_set_end(XiveRouter *xrtr, uint8_t end_blk, uint32_t end_idx, > XiveEND *end); > +int xive_router_get_nvt(XiveRouter *xrtr, uint8_t nvt_blk, uint32_t nvt_idx, > +XiveNVT *nvt); > +int xive_router_set_nvt(XiveRouter *xrtr, uint8_t nvt_blk, uint32_t nvt_idx, > +XiveNVT *nvt); > > /* > * XIVE END ESBs > @@ -274,4 +282,9 @@ extern const MemoryRegionOps xive_tm_ops; > > void xive_tctx_pic_print_info(XiveTCTX *tctx, Monitor *mon); > > +static inline uint32_t xive_tctx_cam_line(uint8_t nvt_blk, uint32_t nvt_idx) > +{ > +return (nvt_blk << 19) | nvt_idx; I'm guessing this formula is the standard way of combining the NVT block and index into a single word? If so, I think we should standardize on passing a single word "nvt_id" around and only splitting it when we need to use the block separately. Same goes for the end_id, assuming there's a standard way of putting that into a single word. That will address the point I raised earlier about lisn being passed around as a single word, but these later stage ids being split. We'll probably want some inlines or macros to build an nvt/end/lisn/whatever id from block and index as well. > +} > + > #endif /* PPC_XIVE_H */ > diff --git a/include/hw/ppc/xive_regs.h b/include/hw/ppc/xive_regs.h > index 2e3d6cb507da..05cb992d2815 100644 > --- a/include/hw/ppc/xive_regs.h > +++ b/include/hw/ppc/xive_regs.h > @@ -158,4 +158,26 @@ typedef struct XiveEND { > #define END_W7_F1_LOG_SERVER_ID PPC_BITMASK32(1, 31) > } XiveEND; > > +/* Notification Virtual Target (NVT) */ > +typedef struct XiveNVT { > +uint32_tw0; > +#define NVT_W0_VALID PPC_BIT32(0) > +uint32_tw1; > +uint32_tw2; > +uint32_tw3; > +uint32_tw4; > +uint32_tw5; > +uint32_tw6; > +uint32_tw7; > +uint32_tw8; > +#define NVT_W8_GRP_VALID PPC_BIT32(0) > +uint32_tw9; > +uint32_twa; > +uint32_twb; > +uint32_twc; > +uint32_twd; > +uint32_twe; > +uint32_twf; > +} XiveNVT; > + > #endif /* PPC_XIVE_REGS_H */ > diff --git a/hw/intc/xive.c b/hw/intc/xive.c > index 4c6cb5d52975..5ba3b06e6e25 100644 > --- a/hw/intc/xive.c > +++ b/hw/intc/xive.c > @@ -373,6 +373,32 @@ void xive_tctx_pic_print_info(XiveTCTX *tctx, Monitor > *mon) > } > } > > +/* The H
[Qemu-devel] [PATCH v1 1/1] riscv: Ensure the kernel start address is correctly cast
Cast the kernel start address to the target bit length. This ensures that we calculate the initrd offset to a valid address for the architecture. Signed-off-by: Alistair Francis Suggested-by: Alexander Graf Reported-by: Alexander Graf --- hw/riscv/sifive_e.c | 2 +- hw/riscv/sifive_u.c | 2 +- hw/riscv/spike.c| 2 +- hw/riscv/virt.c | 3 ++- 4 files changed, 5 insertions(+), 4 deletions(-) diff --git a/hw/riscv/sifive_e.c b/hw/riscv/sifive_e.c index cb513cc3bb..3427b840cb 100644 --- a/hw/riscv/sifive_e.c +++ b/hw/riscv/sifive_e.c @@ -74,7 +74,7 @@ static const struct MemmapEntry { [SIFIVE_E_DTIM] = { 0x8000, 0x4000 } }; -static uint64_t load_kernel(const char *kernel_filename) +static target_ulong load_kernel(const char *kernel_filename) { uint64_t kernel_entry, kernel_high; diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c index ef07df2442..5d03a76a28 100644 --- a/hw/riscv/sifive_u.c +++ b/hw/riscv/sifive_u.c @@ -65,7 +65,7 @@ static const struct MemmapEntry { #define GEM_REVISION0x10070109 -static uint64_t load_kernel(const char *kernel_filename) +static target_ulong load_kernel(const char *kernel_filename) { uint64_t kernel_entry, kernel_high; diff --git a/hw/riscv/spike.c b/hw/riscv/spike.c index 268df04c3c..79cb4c1282 100644 --- a/hw/riscv/spike.c +++ b/hw/riscv/spike.c @@ -53,7 +53,7 @@ static const struct MemmapEntry { [SPIKE_DRAM] = { 0x8000,0x0 }, }; -static uint64_t load_kernel(const char *kernel_filename) +static target_ulong load_kernel(const char *kernel_filename) { uint64_t kernel_entry, kernel_high; diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c index 2b38f89070..f4cbf6aa21 100644 --- a/hw/riscv/virt.c +++ b/hw/riscv/virt.c @@ -57,7 +57,7 @@ static const struct MemmapEntry { [VIRT_DRAM] = { 0x8000,0x0 }, }; -static uint64_t load_kernel(const char *kernel_filename) +static target_ulong load_kernel(const char *kernel_filename) { uint64_t kernel_entry, kernel_high; @@ -85,6 +85,7 @@ static hwaddr load_initrd(const char *filename, uint64_t mem_size, * halfway into RAM, and for boards with 256MB of RAM or more we put * the initrd at 128MB. */ +/* As hwaddr is a 64-bit number we need to cast it for 32-bit */ *start = kernel_entry + MIN(mem_size / 2, 128 * MiB); size = load_ramdisk(filename, *start, mem_size - *start); -- 2.19.1
Re: [Qemu-devel] [PATCH v5 09/36] ppc/xive: notify the CPU when the interrupt priority is more privileged
On Fri, Nov 16, 2018 at 11:57:02AM +0100, Cédric Le Goater wrote: > After the event data was pushed in the O/S Event Queue, the IVPE > raises the bit corresponding to the priority of the pending interrupt > in the register IBP (Interrupt Pending Buffer) to indicate there is an > event pending in one of the 8 priority queues. The Pending Interrupt > Priority Register (PIPR) is also updated using the IPB. This register > represent the priority of the most favored pending notification. > > The PIPR is then compared to the the Current Processor Priority > Register (CPPR). If it is more favored (numerically less than), the > CPU interrupt line is raised and the EO bit of the Notification Source > Register (NSR) is updated to notify the presence of an exception for > the O/S. The check needs to be done whenever the PIPR or the CPPR are > changed. > > The O/S acknowledges the interrupt with a special load in the Thread > Interrupt Management Area. If the EO bit of the NSR is set, the CPPR > takes the value of PIPR. The bit number in the IBP corresponding to > the priority of the pending interrupt is reseted and so is the EO bit > of the NSR. > > Signed-off-by: Cédric Le Goater > --- > hw/intc/xive.c | 94 +- > 1 file changed, 93 insertions(+), 1 deletion(-) > > diff --git a/hw/intc/xive.c b/hw/intc/xive.c > index 5ba3b06e6e25..c49932d2b799 100644 > --- a/hw/intc/xive.c > +++ b/hw/intc/xive.c > @@ -21,9 +21,73 @@ > * XIVE Thread Interrupt Management context > */ > > +/* Convert a priority number to an Interrupt Pending Buffer (IPB) > + * register, which indicates a pending interrupt at the priority > + * corresponding to the bit number > + */ > +static uint8_t priority_to_ipb(uint8_t priority) > +{ > +return priority > XIVE_PRIORITY_MAX ? > +0 : 1 << (XIVE_PRIORITY_MAX - priority); > +} > + > +/* Convert an Interrupt Pending Buffer (IPB) register to a Pending > + * Interrupt Priority Register (PIPR), which contains the priority of > + * the most favored pending notification. > + */ > +static uint8_t ipb_to_pipr(uint8_t ibp) > +{ > +return ibp ? clz32((uint32_t)ibp << 24) : 0xff; > +} > + > +static void ipb_update(uint8_t *regs, uint8_t priority) > +{ > +regs[TM_IPB] |= priority_to_ipb(priority); > +regs[TM_PIPR] = ipb_to_pipr(regs[TM_IPB]); > +} > + > +static uint8_t exception_mask(uint8_t ring) > +{ > +switch (ring) { > +case TM_QW1_OS: > +return TM_QW1_NSR_EO; > +default: > +g_assert_not_reached(); > +} > +} > + > static uint64_t xive_tctx_accept(XiveTCTX *tctx, uint8_t ring) > { > -return 0; > +uint8_t *regs = &tctx->regs[ring]; > +uint8_t nsr = regs[TM_NSR]; > +uint8_t mask = exception_mask(ring); > + > +qemu_irq_lower(tctx->output); > + > +if (regs[TM_NSR] & mask) { > +uint8_t cppr = regs[TM_PIPR]; > + > +regs[TM_CPPR] = cppr; > + > +/* Reset the pending buffer bit */ > +regs[TM_IPB] &= ~priority_to_ipb(cppr); > +regs[TM_PIPR] = ipb_to_pipr(regs[TM_IPB]); > + > +/* Drop Exception bit */ > +regs[TM_NSR] &= ~mask; > +} > + > +return (nsr << 8) | regs[TM_CPPR]; Don't you need a cast to avoid (nsr << 8) being a shift-wider-than-size? > +} > + > +static void xive_tctx_notify(XiveTCTX *tctx, uint8_t ring) > +{ > +uint8_t *regs = &tctx->regs[ring]; > + > +if (regs[TM_PIPR] < regs[TM_CPPR]) { > +regs[TM_NSR] |= exception_mask(ring); > +qemu_irq_raise(tctx->output); > +} > } > > static void xive_tctx_set_cppr(XiveTCTX *tctx, uint8_t ring, uint8_t cppr) > @@ -33,6 +97,9 @@ static void xive_tctx_set_cppr(XiveTCTX *tctx, uint8_t > ring, uint8_t cppr) > } > > tctx->regs[ring + TM_CPPR] = cppr; > + > +/* CPPR has changed, check if we need to raise a pending exception */ > +xive_tctx_notify(tctx, ring); > } > > /* > @@ -198,6 +265,17 @@ static void xive_tm_set_os_cppr(XiveTCTX *tctx, hwaddr > offset, > xive_tctx_set_cppr(tctx, TM_QW1_OS, value & 0xff); > } > > +/* > + * Adjust the IPB to allow a CPU to process event queues of other > + * priorities during one physical interrupt cycle. > + */ > +static void xive_tm_set_os_pending(XiveTCTX *tctx, hwaddr offset, > + uint64_t value, unsigned size) > +{ > +ipb_update(&tctx->regs[TM_QW1_OS], value & 0xff); > +xive_tctx_notify(tctx, TM_QW1_OS); > +} > + > /* > * Define a mapping of "special" operations depending on the TIMA page > * offset and the size of the operation. > @@ -220,6 +298,7 @@ static const XiveTmOp xive_tm_operations[] = { > > /* MMIOs above 2K : special operations with side effects */ > { XIVE_TM_OS_PAGE, TM_SPC_ACK_OS_REG, 2, NULL, xive_tm_ack_os_reg }, > +{ XIVE_TM_OS_PAGE, TM_SPC_SET_OS_PENDING, 1, xive_tm_set_os_pending, > NULL }, > }; > > static const XiveTmOp *xive_tm_find_op(hwaddr offset, unsigned size, bool > write)
Re: [Qemu-devel] [PATCH v5 04/36] ppc/xive: introduce the XiveRouter model
On Tue, Nov 27, 2018 at 08:30:15AM +0100, Cédric Le Goater wrote: > On 11/27/18 1:11 AM, David Gibson wrote: > > On Mon, Nov 26, 2018 at 10:39:44AM +0100, Cédric Le Goater wrote: > >> On 11/26/18 6:44 AM, David Gibson wrote: > >>> On Fri, Nov 23, 2018 at 11:28:24AM +0100, Cédric Le Goater wrote: > On 11/23/18 2:10 AM, David Gibson wrote: > > On Thu, Nov 22, 2018 at 05:50:07PM +1100, Benjamin Herrenschmidt wrote: > >> On Thu, 2018-11-22 at 15:44 +1100, David Gibson wrote: > >>> > >>> Sorry, didn't think of this in my first reply. > >>> > >>> 1) Does the hardware ever actually write back to the EAS? I know it > >>> does for the END, but it's not clear why it would need to for the > >>> EAS. If not, we don't need the setter. > >> > >> Nope, though the PAPR model will via hcalls > > > > Right, bit AIUI the set_eas hook is about abstracting PAPR vs bare > > metal details. Since the hcall knows it's PAPR it can just update the > > backing information for the EAS directly, and no need for an > > abstracted hook. > > Indeed, the first versions of the XIVE patchset did not use such hooks, > but when discussed we said we wanted abstract methods for the router > to validate the overall XIVE model, which is useful for PowerNV. > > We can change again and have the hcalls get/set directly in the EAT > and ENDT. It would certainly simplify the sPAPR model. > >>> > >>> I think that's the better approach. > >> > >> ok. let's keep that in mind for : > >> > >> [PATCH v5 11/36] spapr/xive: use the VCPU id as a NVT identifier > >> [PATCH v5 16/36] spapr: add hcalls support for the XIVE exploitation > >> > >> which are using the XiveRouter methods to access the controller EAT > >> and ENDT. I thought that was good practice to validate the model but > >> we can use direct sPAPR table accessors or none at all. > > > > Ok. Consistency is good as a general rule, but I don't think it makes > > sense to force the EAT and the ENDT into the same model. > > What do you mean by model ? the QEMU machine IC model ? Oh, sorry, nothing that formal. By "model" I just meant the same pattern of accessor hooks. They certainly do belong in the same qemu object. > > The EAT is > > pure configuration, whereas the the ENDT has both configuration and > > status. Or to look at it another way, the EAT is purely software > > controlled, whereas the ENDT is at least partially hardware > > controlled. > > yes but the EAT and the ENDT are XIVE internal tables of the same XIVE > sub-engine, the IVRE, Interrupt Virtualization Routing Engine, formely > known as VC, for Virtualization Controller. the EAS is just an entry > point to the ENDT. I don't see why we would use different models for > them. > > > (I realize that gets a bit fuzzy when considering PAPR, but I think > > from the point of view of the XIVE model it makes sense to treat the > > PAPR hypervisor logic as "software", even though it's "hardware" from the > > guest point of view). > > That I agree but the resulting code is too ugly in the hcalls. Tell me > when you reach patch 11, which links the machine IC model sPAPRXive to > the generic XiveRouter and also check patch 16 introducing the hcalls, > which update the XIVE internal tables. > > Thanks, > > C. > > > >> > >> > >> I think these prereq patches could be merged now : > >> > >> [PATCH v5 12/36] spapr: initialize VSMT before initializing the IRQ > >> [PATCH v5 13/36] spapr: introduce a spapr_irq_init() routine > >> [PATCH v5 14/36] spapr: modify the irq backend 'init' method > >> > >> This one also : > >> > >> [PATCH v5 21/36] spapr: extend the sPAPR IRQ backend for XICS > >> > >> Thanks, > >> > >> C. > >> > > > -- 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 for-4.0 0/9] ppc: get rid of g_malloc(sizeof(T) * n)
On Tue, Nov 27, 2018 at 02:04:53PM +0100, Greg Kurz wrote: > As explained in HACKING, the g_malloc(sizeof(T) * n) construct is unsafe > because it can't detect multiplication overflowing size_t and doesn't > allow type checking. > > It appears to be used in a bunch of places though: > > $ git grep -E 'malloc.*sizeof' | grep ' \* ' | wc -l > 101 > > This series fixes the ppc target and ppc machine code. The changes are > mostly trivial. Only the mac99 and e500 machines required some more work > that should be reviewed carefully, as it was only compile-tested. Series applied, thanks. -- 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
[Qemu-devel] [Bug 1805445] Re: QEMU arm virt machine was stopped by STMFD command while debug process
No, that is not something that QEMU supports. There is no such thing as a "generic arm board". All arm boards are different hardware, and we model only a few boards. We don't provide "put together your own model from building blocks" functionality, I'm afraid, and it's unlikely we ever will in future. -- You received this bug notification because you are a member of qemu- devel-ml, which is subscribed to QEMU. https://bugs.launchpad.net/bugs/1805445 Title: QEMU arm virt machine was stopped by STMFD command while debug process Status in QEMU: New Bug description: Hello, i have a big problem with QEMU arm virtual machine. So... I run QEMU machine with bare-metal ThreadX fullflash from Texet TM-333 phone (Spreadtrum platform) [CODE]qemu-system-arm -S -gdb tcp::1234,ipv4 -drive file=C:\cygwin64\home\flash.bin,if=mtd,format=raw -M palmetto-bmc -cpu arm926 -m 64M[/CODE] I use palmetto-bmc platform because it have ARM926EJ-S core and support SPI Flash. Then, i attach to gdb qemu process from IDA and run code step-by-step. When the IDA run 00032534 STR R11, [R10] command instead of store R11 on R10 adress, it jump 000328DC STMFD SP!, {R0-R12,LR} instruction... and virt machine not execute new instruction... [IMG]https://pp.userapi.com/c850624/v850624111/528f3/N7FTpgloWVU.jpg[/IMG] and why i did not change flash from n25q256a to n25q032a11 in aspeed.c without rebuild qemu? To manage notifications about this bug go to: https://bugs.launchpad.net/qemu/+bug/1805445/+subscriptions
Re: [Qemu-devel] [PULL v3 00/14] Misc patches for QEMU 3.1.0-rc3
On Tue, 27 Nov 2018 at 19:00, Paolo Bonzini wrote: > > The following changes since commit 4822f1ee9efa8df56e29db0a68323b484bdb0335: > > Merge remote-tracking branch > 'remotes/kraxel/tags/fixes-31-20181127-pull-request' into staging (2018-11-27 > 11:21:38 +) > > are available in the git repository at: > > > git://github.com/bonzini/qemu.git tags/for-upstream > > for you to fetch changes up to 3fe2199833c47652a7e5dbf8b347d873820104b8: > > hostmem: no need to check for host_memory_backend_mr_inited() in alloc() > (2018-11-27 19:36:22 +0100) > > > * lsi HBA reselection fix (George) > * Small cleanups (Li Qiang) > * bugfixes for vhost-user-bridge and hostmem (Marc-André) > * single-thread TCG fix (me) > * VMX migration blocker (me) > * target/i386 fix for LOCK (Richard) > * MAINTAINERS update (Philippe, Thomas) > > --- This still has the problem with backends/hostmem-file.c that means it doesn't build on the BSDs... backends/hostmem-file.c: In function 'file_backend_memory_alloc': backends/hostmem-file.c:61:5: error: 'path' undeclared (first use in this function) path = object_get_canonical_path(OBJECT(backend)); ^ backends/hostmem-file.c:61:5: note: each undeclared identifier is reported only once for each function it appears in (mismatch in #ifdef choice between declaration and use of variable) thanks -- PMM
Re: [Qemu-devel] [RFC 41/48] configure: add --enable-plugins
On Tue, Nov 27, 2018 at 15:43:52 +0300, Roman Bolshakov wrote: > ld64 on macOS has similar -exported_symbols_list option. Here's the reference: > > -exported_symbols_list filename > The specified filename contains a list of global symbol names > that will remain as global symbols in the output file. All other > global symbols will be treated as if they were marked as > __private_extern__ (aka visibility=hidden) and will not be global in > the output file. The symbol names listed in filename must be one per > line. Leading and trailing white space are not part of the symbol > name. Lines starting with # are ignored, as are lines with only white > space. Some wildcards (similar to shell file matching) are supported. > The * matches zero or more characters. The ? matches one character. > [abc] matches one character which must be an 'a', 'b', or 'c'. > [a-z] matches any single lower case letter from 'a' to 'z'. > > > I can try your branch if you add support of the linker flag or send required > changes via GitHub. Can you please try this branch? I added a commit with the appended. https://github.com/cota/qemu/tree/plugin-v2 You can inspect the symbols in the final binary with `readelf --dyn-syms' or `nm -D'. Thanks, Emilio --- diff --git a/configure b/configure index fe9707d951..3dc9c9697b 100755 --- a/configure +++ b/configure @@ -5176,15 +5176,31 @@ int main(void) } EOF +ld_dynamic_list="no" if compile_prog "" "-Wl,--dynamic-list=$TMPTXT" ; then ld_dynamic_list="yes" -else - if test "$plugins" = "yes" ; then -error_exit \ -"Plugin support requires specifying a set of symbols that " \ -"are exported to plugins. Unfortunately your linker doesn't " \ -"support the flag (--dynamic-list) used for this purpose." - fi +fi + +# +# See if -exported_symbols_list is supported by the linker + +cat > $TMPTXT <> $config_host_mak LIBS="-ldl $LIBS" -LDFLAGS="-Wl,--dynamic-list=\$(SRC_PATH)/qemu-plugins.symbols $LDFLAGS" +if test "$ld_dynamic_list" = "yes" ; then + LDFLAGS="-Wl,--dynamic-list=\$(SRC_PATH)/qemu-plugins.symbols $LDFLAGS" +elif test "$ld_exported_symbols_list" = "yes" ; then + ld64_symbols=qemu-plugins-ld64.symbols + echo "# Automatically generated by configure - do not modify" > $ld64_symbols + cat "$source_path/qemu-plugins.symbols" | grep qemu_ | sed 's/;//g' >> $ld64_symbols + LDFLAGS="-Wl,-exported_symbols_list,\$(BUILD_DIR)/$ld64_symbols $LDFLAGS" +else + error_exit \ + "If \$plugins=yes, either \$ld_dynamic_list or " \ + "\$ld_exported_symbols_list should have been set to 'yes'." +fi fi if test "$tcg_interpreter" = "yes"; then
Re: [Qemu-devel] [PATCH] qemu-img info lists bitmap directory entries
On 11/27/18 6:41 AM, Andrey Shinkevich wrote: The 'Format specific information' of qemu-img info command will show the name, flags and granularity for every QCOW2 bitmap. Signed-off-by: Andrey Shinkevich --- Dear colleagues, With this patch, qemu-img info will display a name, flags and granularity information for every bitmap in the directory section of a QCOW2 image. That information appears in the 'Format specific information' section as it's shown in the following example: image: /vz/vmprivate/VM1/harddisk.hdd file format: qcow2 virtual size: 64G (68719476736 bytes) disk size: 3.0M cluster_size: 1048576 Format specific information: compat: 1.1 lazy refcounts: true refcount bits: 16 dirty bitmaps: [0]: flags: [0]: in-use [1]: auto name: {257b5ea5-38c5-410e-a457-71c76f763c60} granularity: 65536 [1]: flags: [0]: in-use [1]: auto name: back-up granularity: 65536 corrupt: false This example is worth including in the commit message proper (by putting it above the Signed-off-by and --- lines). In addition to Vladimir's review (he's correct about using 4.0), +++ b/block/qcow2-bitmap.c @@ -1008,6 +1008,56 @@ fail: return false; } +static Qcow2BitmapInfoFlagsList *get_bitmap_info_flags(uint32_t flags) +{ +Qcow2BitmapInfoFlagsList *list = NULL; +Qcow2BitmapInfoFlagsList **plist = &list; + +if (flags & BME_FLAG_IN_USE) { +Qcow2BitmapInfoFlagsList *entry = g_new0(Qcow2BitmapInfoFlagsList, 1); +entry->value = QCOW2_BITMAP_INFO_FLAGS_IN_USE; +*plist = entry; +plist = &entry->next; +} +if (flags & BME_FLAG_AUTO) { +Qcow2BitmapInfoFlagsList *entry = g_new0(Qcow2BitmapInfoFlagsList, 1); +entry->value = QCOW2_BITMAP_INFO_FLAGS_AUTO; +*plist = entry; +} +return list; +} This implementation means that qemu won't report bits that are set but which qemu doesn't recognize. Is that a problem? I wouldn't over-engineer it unless we have a use case, but maybe one way would be to have an optional integer field alongside the array of known flags, where the integer is present only if there are unrecognized flags present. But by the time we encounter an image with more than the two flags we currently recognize, we may have also patched this code to recognize a new flag. @@ -4279,6 +4287,8 @@ static ImageInfoSpecific *qcow2_get_specific_info(BlockDriverState *bs) QCOW2_INCOMPAT_CORRUPT, .has_corrupt= true, .refcount_bits = s->refcount_bits, +.has_bitmaps= bitmaps ? true : false, This looks awkward; I'd write it ' = !!bitmaps'. +++ b/qapi/block-core.json @@ -77,7 +77,8 @@ '*lazy-refcounts': 'bool', '*corrupt': 'bool', 'refcount-bits': 'int', - '*encrypt': 'ImageInfoSpecificQCow2Encryption' + '*encrypt': 'ImageInfoSpecificQCow2Encryption', + '*bitmaps': ['Qcow2BitmapInfo'] Missing documentation on the new member, including a '(since 4.0)' tag. -- Eric Blake, Principal Software Engineer Red Hat, Inc. +1-919-301-3266 Virtualization: qemu.org | libvirt.org
Re: [Qemu-devel] [PATCH v1 1/1] riscv: virt: Cast the initrd start address to target bit length
On 27.11.18 23:28, Alistair Francis wrote: > On Tue, Nov 27, 2018 at 2:24 PM Alistair Francis wrote: >> >> On Tue, Nov 27, 2018 at 2:12 PM Alexander Graf wrote: >>> >>> >>> >>> On 27.11.18 23:05, Alistair Francis wrote: On Mon, Nov 26, 2018 at 11:02 AM Palmer Dabbelt wrote: > > On Wed, 21 Nov 2018 18:09:27 PST (-0800), alistai...@gmail.com wrote: >> On Wed, Nov 21, 2018 at 5:58 PM Palmer Dabbelt wrote: >>> >>> On Wed, 21 Nov 2018 14:34:44 PST (-0800), Alistair Francis wrote: Ensure that the calculate initrd offset points to a valid address for the architecture. Signed-off-by: Alistair Francis Suggested-by: Alexander Graf Reported-by: Alexander Graf --- hw/riscv/virt.c | 7 ++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c index 2b38f89070..4467195fac 100644 --- a/hw/riscv/virt.c +++ b/hw/riscv/virt.c @@ -85,7 +85,12 @@ static hwaddr load_initrd(const char *filename, uint64_t mem_size, * halfway into RAM, and for boards with 256MB of RAM or more we put * the initrd at 128MB. */ -*start = kernel_entry + MIN(mem_size / 2, 128 * MiB); +/* As hwaddr is a 64-bit number we need to cast it for 32-bit */ +#if defined(TARGET_RISCV32) +*start = (uint32_t) (kernel_entry + MIN(mem_size / 2, 128ULL * MiB)); +#elif defined(TARGET_RISCV64) +*start = (uint64_t) (kernel_entry + MIN(mem_size / 2, 128 * MiB)); +#endif size = load_ramdisk(filename, *start, mem_size - *start); if (size == -1) { -- 2.19.1 >>> >>> Maybe I'm missing something, but wouldn't something like >>> >>> uint64_t start_unclobbered = kernel_entry + MIN(mem_size / 2, >>> 128ULL * MiB); >>> assert(start_unclobbered == (hwaddr)start_unclobbered); >>> *start = (hwaddr)start_unclobbered; >>> >>> work better? That should actually check this all lines up, as opposed >>> to just >>> silently truncating a bad address. >> >> The problem is that hwaddr is always 64-bit. >> >> Stupidly I forgot about target_ulong, which should work basically the >> same as above. An assert() seems a little harsh though, Alex reported >> problem was fixed with just a cast. > > OK, I must be misunderstanding the problem, then. With the current code, > isn't > it possible to end up causing start to overflow a 32-bit address? This > would > happen if kernel_entry is high, with IIUC is coming from the ELF to load > and is > therefor user input. I think that's worth some sort of assertion, as > it'll > definitely blow up trying to enter the kernel (and possible before that, > assuming there's no target memory where it overflows into). I don't have a setup to reproduce this unfortunately, but Alex reported that he saw start being excessively high (0x8800) when loading an initrd. >>> >>> Sorry for only jumping in so late. >>> >>> I didn't actually propose the cast as a solution. The problem must be >>> sign extension of some variable in the mix. I didn't find out quickly >>> which one it was, so I figured I'd leave it for someone else to debug :). >>> >>> The issue is very easy to reproduce: Build U-Boot for the virt machine >>> for riscv32. Then run it with >>> >>> $ qemu-system-riscv32 -M virt -kernel u-boot -nographic -initrd >> >> Ah, cool I can reproduce it now. >> >> It happens in load_elf32() (which is actually glue(load_elf, SZ)). >> >> This line ends up sign extending the value: >> *pentry = (uint64_t)(elf_sword)ehdr.e_entry; >> >> and we just continue it from there. >> >> So I think this diff is a much better solution: >> >> diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c >> index e7f0716fb6..348ecc39d5 100644 >> --- a/hw/riscv/virt.c >> +++ b/hw/riscv/virt.c >> @@ -62,7 +62,7 @@ static const struct MemmapEntry { >> [VIRT_PCIE_ECAM] = { 0x3000,0x1000 }, >> }; >> >> -static uint64_t load_kernel(const char *kernel_filename) >> +static target_ulong load_kernel(const char *kernel_filename) >> { >> uint64_t kernel_entry, kernel_high; >> >> >> >> Alistair >> >>> >>> You can find the initrd address with >>> >>> U-Boot# fdt addr $fdtcontroladdr >>> U-Boot# fdt ls /chosen >>> >>> Then take a peek at that address: >>> >>> U-Boot# md.b >>> >>> and you will see that there is nothing there without this patch. The >>> reason is that the binary was loaded to a negative address. Again, >>> probably some misguided sign extension. >>> It looks like the kernel entry address ends up being converted to 0x8000 incorrectly instead of being a real overflow. >>>
[Qemu-devel] [Bug 1805445] Re: QEMU arm virt machine was stopped by STMFD command while debug process
** Description changed: Hello, i have a big problem with QEMU arm virtual machine. So... I run QEMU machine with bare-metal ThreadX fullflash from Texet TM-333 phone (Spreadtrum platform) [CODE]qemu-system-arm -S -gdb tcp::1234,ipv4 -drive file=C:\cygwin64\home\flash.bin,if=mtd,format=raw -M palmetto-bmc -cpu arm926 -m 64M[/CODE] I use palmetto-bmc platform because it have ARM926EJ-S core and support SPI Flash. Then, i attach to gdb qemu process from IDA and run code step-by-step. - [IMG]https://pp.userapi.com/c847218/v847218546/13ec1c/iSIcre5-js4.jpg[/IMG] + When the IDA run 00032534 STR R11, [R10] command - [IMG]https://pp.userapi.com/c846416/v846416708/133f60/GQzxORvf4Tg.jpg[/IMG] + instead of store R11 on R10 adress, it jump 000328DC STMFD SP!, {R0-R12,LR} instruction... - [IMG]https://pp.userapi.com/c847218/v847218546/13ec26/32A0VcaJywg.jpg[/IMG] - and virt machine not execute new instruction... + + and virt machine not execute new instruction... [IMG]https://pp.userapi.com/c850624/v850624111/528f3/N7FTpgloWVU.jpg[/IMG] and why i did not change flash from n25q256a to n25q032a11 in aspeed.c without rebuild qemu? -- You received this bug notification because you are a member of qemu- devel-ml, which is subscribed to QEMU. https://bugs.launchpad.net/bugs/1805445 Title: QEMU arm virt machine was stopped by STMFD command while debug process Status in QEMU: New Bug description: Hello, i have a big problem with QEMU arm virtual machine. So... I run QEMU machine with bare-metal ThreadX fullflash from Texet TM-333 phone (Spreadtrum platform) [CODE]qemu-system-arm -S -gdb tcp::1234,ipv4 -drive file=C:\cygwin64\home\flash.bin,if=mtd,format=raw -M palmetto-bmc -cpu arm926 -m 64M[/CODE] I use palmetto-bmc platform because it have ARM926EJ-S core and support SPI Flash. Then, i attach to gdb qemu process from IDA and run code step-by-step. When the IDA run 00032534 STR R11, [R10] command instead of store R11 on R10 adress, it jump 000328DC STMFD SP!, {R0-R12,LR} instruction... and virt machine not execute new instruction... [IMG]https://pp.userapi.com/c850624/v850624111/528f3/N7FTpgloWVU.jpg[/IMG] and why i did not change flash from n25q256a to n25q032a11 in aspeed.c without rebuild qemu? To manage notifications about this bug go to: https://bugs.launchpad.net/qemu/+bug/1805445/+subscriptions
Re: [Qemu-devel] [PATCH v1 1/1] riscv: virt: Cast the initrd start address to target bit length
On Tue, Nov 27, 2018 at 2:24 PM Alistair Francis wrote: > > On Tue, Nov 27, 2018 at 2:12 PM Alexander Graf wrote: > > > > > > > > On 27.11.18 23:05, Alistair Francis wrote: > > > On Mon, Nov 26, 2018 at 11:02 AM Palmer Dabbelt wrote: > > >> > > >> On Wed, 21 Nov 2018 18:09:27 PST (-0800), alistai...@gmail.com wrote: > > >>> On Wed, Nov 21, 2018 at 5:58 PM Palmer Dabbelt > > >>> wrote: > > > > On Wed, 21 Nov 2018 14:34:44 PST (-0800), Alistair Francis wrote: > > > Ensure that the calculate initrd offset points to a valid address for > > > the architecture. > > > > > > Signed-off-by: Alistair Francis > > > Suggested-by: Alexander Graf > > > Reported-by: Alexander Graf > > > --- > > > hw/riscv/virt.c | 7 ++- > > > 1 file changed, 6 insertions(+), 1 deletion(-) > > > > > > diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c > > > index 2b38f89070..4467195fac 100644 > > > --- a/hw/riscv/virt.c > > > +++ b/hw/riscv/virt.c > > > @@ -85,7 +85,12 @@ static hwaddr load_initrd(const char *filename, > > > uint64_t mem_size, > > > * halfway into RAM, and for boards with 256MB of RAM or more we > > > put > > > * the initrd at 128MB. > > > */ > > > -*start = kernel_entry + MIN(mem_size / 2, 128 * MiB); > > > +/* As hwaddr is a 64-bit number we need to cast it for 32-bit */ > > > +#if defined(TARGET_RISCV32) > > > +*start = (uint32_t) (kernel_entry + MIN(mem_size / 2, 128ULL * > > > MiB)); > > > +#elif defined(TARGET_RISCV64) > > > +*start = (uint64_t) (kernel_entry + MIN(mem_size / 2, 128 * > > > MiB)); > > > +#endif > > > > > > size = load_ramdisk(filename, *start, mem_size - *start); > > > if (size == -1) { > > > -- > > > 2.19.1 > > > > Maybe I'm missing something, but wouldn't something like > > > > uint64_t start_unclobbered = kernel_entry + MIN(mem_size / 2, > > 128ULL * MiB); > > assert(start_unclobbered == (hwaddr)start_unclobbered); > > *start = (hwaddr)start_unclobbered; > > > > work better? That should actually check this all lines up, as opposed > > to just > > silently truncating a bad address. > > >>> > > >>> The problem is that hwaddr is always 64-bit. > > >>> > > >>> Stupidly I forgot about target_ulong, which should work basically the > > >>> same as above. An assert() seems a little harsh though, Alex reported > > >>> problem was fixed with just a cast. > > >> > > >> OK, I must be misunderstanding the problem, then. With the current > > >> code, isn't > > >> it possible to end up causing start to overflow a 32-bit address? This > > >> would > > >> happen if kernel_entry is high, with IIUC is coming from the ELF to load > > >> and is > > >> therefor user input. I think that's worth some sort of assertion, as > > >> it'll > > >> definitely blow up trying to enter the kernel (and possible before that, > > >> assuming there's no target memory where it overflows into). > > > > > > I don't have a setup to reproduce this unfortunately, but Alex > > > reported that he saw start being excessively high (0x8800) > > > when loading an initrd. > > > > Sorry for only jumping in so late. > > > > I didn't actually propose the cast as a solution. The problem must be > > sign extension of some variable in the mix. I didn't find out quickly > > which one it was, so I figured I'd leave it for someone else to debug :). > > > > The issue is very easy to reproduce: Build U-Boot for the virt machine > > for riscv32. Then run it with > > > > $ qemu-system-riscv32 -M virt -kernel u-boot -nographic -initrd > > Ah, cool I can reproduce it now. > > It happens in load_elf32() (which is actually glue(load_elf, SZ)). > > This line ends up sign extending the value: > *pentry = (uint64_t)(elf_sword)ehdr.e_entry; > > and we just continue it from there. > > So I think this diff is a much better solution: > > diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c > index e7f0716fb6..348ecc39d5 100644 > --- a/hw/riscv/virt.c > +++ b/hw/riscv/virt.c > @@ -62,7 +62,7 @@ static const struct MemmapEntry { > [VIRT_PCIE_ECAM] = { 0x3000,0x1000 }, > }; > > -static uint64_t load_kernel(const char *kernel_filename) > +static target_ulong load_kernel(const char *kernel_filename) > { > uint64_t kernel_entry, kernel_high; > > > > Alistair > > > > > You can find the initrd address with > > > > U-Boot# fdt addr $fdtcontroladdr > > U-Boot# fdt ls /chosen > > > > Then take a peek at that address: > > > > U-Boot# md.b > > > > and you will see that there is nothing there without this patch. The > > reason is that the binary was loaded to a negative address. Again, > > probably some misguided sign extension. > > > > > It looks like the kernel entry address ends up being converted to > > > 0x8000 incorrectly instead of being a real
Re: [Qemu-devel] [PATCH v1 1/1] riscv: virt: Cast the initrd start address to target bit length
On Tue, Nov 27, 2018 at 2:12 PM Alexander Graf wrote: > > > > On 27.11.18 23:05, Alistair Francis wrote: > > On Mon, Nov 26, 2018 at 11:02 AM Palmer Dabbelt wrote: > >> > >> On Wed, 21 Nov 2018 18:09:27 PST (-0800), alistai...@gmail.com wrote: > >>> On Wed, Nov 21, 2018 at 5:58 PM Palmer Dabbelt wrote: > > On Wed, 21 Nov 2018 14:34:44 PST (-0800), Alistair Francis wrote: > > Ensure that the calculate initrd offset points to a valid address for > > the architecture. > > > > Signed-off-by: Alistair Francis > > Suggested-by: Alexander Graf > > Reported-by: Alexander Graf > > --- > > hw/riscv/virt.c | 7 ++- > > 1 file changed, 6 insertions(+), 1 deletion(-) > > > > diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c > > index 2b38f89070..4467195fac 100644 > > --- a/hw/riscv/virt.c > > +++ b/hw/riscv/virt.c > > @@ -85,7 +85,12 @@ static hwaddr load_initrd(const char *filename, > > uint64_t mem_size, > > * halfway into RAM, and for boards with 256MB of RAM or more we > > put > > * the initrd at 128MB. > > */ > > -*start = kernel_entry + MIN(mem_size / 2, 128 * MiB); > > +/* As hwaddr is a 64-bit number we need to cast it for 32-bit */ > > +#if defined(TARGET_RISCV32) > > +*start = (uint32_t) (kernel_entry + MIN(mem_size / 2, 128ULL * > > MiB)); > > +#elif defined(TARGET_RISCV64) > > +*start = (uint64_t) (kernel_entry + MIN(mem_size / 2, 128 * MiB)); > > +#endif > > > > size = load_ramdisk(filename, *start, mem_size - *start); > > if (size == -1) { > > -- > > 2.19.1 > > Maybe I'm missing something, but wouldn't something like > > uint64_t start_unclobbered = kernel_entry + MIN(mem_size / 2, 128ULL > * MiB); > assert(start_unclobbered == (hwaddr)start_unclobbered); > *start = (hwaddr)start_unclobbered; > > work better? That should actually check this all lines up, as opposed > to just > silently truncating a bad address. > >>> > >>> The problem is that hwaddr is always 64-bit. > >>> > >>> Stupidly I forgot about target_ulong, which should work basically the > >>> same as above. An assert() seems a little harsh though, Alex reported > >>> problem was fixed with just a cast. > >> > >> OK, I must be misunderstanding the problem, then. With the current code, > >> isn't > >> it possible to end up causing start to overflow a 32-bit address? This > >> would > >> happen if kernel_entry is high, with IIUC is coming from the ELF to load > >> and is > >> therefor user input. I think that's worth some sort of assertion, as it'll > >> definitely blow up trying to enter the kernel (and possible before that, > >> assuming there's no target memory where it overflows into). > > > > I don't have a setup to reproduce this unfortunately, but Alex > > reported that he saw start being excessively high (0x8800) > > when loading an initrd. > > Sorry for only jumping in so late. > > I didn't actually propose the cast as a solution. The problem must be > sign extension of some variable in the mix. I didn't find out quickly > which one it was, so I figured I'd leave it for someone else to debug :). > > The issue is very easy to reproduce: Build U-Boot for the virt machine > for riscv32. Then run it with > > $ qemu-system-riscv32 -M virt -kernel u-boot -nographic -initrd Ah, cool I can reproduce it now. It happens in load_elf32() (which is actually glue(load_elf, SZ)). This line ends up sign extending the value: *pentry = (uint64_t)(elf_sword)ehdr.e_entry; and we just continue it from there. So I think this diff is a much better solution: diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c index e7f0716fb6..348ecc39d5 100644 --- a/hw/riscv/virt.c +++ b/hw/riscv/virt.c @@ -62,7 +62,7 @@ static const struct MemmapEntry { [VIRT_PCIE_ECAM] = { 0x3000,0x1000 }, }; -static uint64_t load_kernel(const char *kernel_filename) +static target_ulong load_kernel(const char *kernel_filename) { uint64_t kernel_entry, kernel_high; Alistair > > You can find the initrd address with > > U-Boot# fdt addr $fdtcontroladdr > U-Boot# fdt ls /chosen > > Then take a peek at that address: > > U-Boot# md.b > > and you will see that there is nothing there without this patch. The > reason is that the binary was loaded to a negative address. Again, > probably some misguided sign extension. > > > It looks like the kernel entry address ends up being converted to > > 0x8000 incorrectly instead of being a real overflow. > > Yeah, so we seem to cast from int32_t to int64_t somewhere. Can you spot > where exactly? That's where the bug is :). > > > Alex
Re: [Qemu-devel] [PATCH v1 1/1] riscv: virt: Cast the initrd start address to target bit length
On 27.11.18 23:05, Alistair Francis wrote: > On Mon, Nov 26, 2018 at 11:02 AM Palmer Dabbelt wrote: >> >> On Wed, 21 Nov 2018 18:09:27 PST (-0800), alistai...@gmail.com wrote: >>> On Wed, Nov 21, 2018 at 5:58 PM Palmer Dabbelt wrote: On Wed, 21 Nov 2018 14:34:44 PST (-0800), Alistair Francis wrote: > Ensure that the calculate initrd offset points to a valid address for > the architecture. > > Signed-off-by: Alistair Francis > Suggested-by: Alexander Graf > Reported-by: Alexander Graf > --- > hw/riscv/virt.c | 7 ++- > 1 file changed, 6 insertions(+), 1 deletion(-) > > diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c > index 2b38f89070..4467195fac 100644 > --- a/hw/riscv/virt.c > +++ b/hw/riscv/virt.c > @@ -85,7 +85,12 @@ static hwaddr load_initrd(const char *filename, > uint64_t mem_size, > * halfway into RAM, and for boards with 256MB of RAM or more we put > * the initrd at 128MB. > */ > -*start = kernel_entry + MIN(mem_size / 2, 128 * MiB); > +/* As hwaddr is a 64-bit number we need to cast it for 32-bit */ > +#if defined(TARGET_RISCV32) > +*start = (uint32_t) (kernel_entry + MIN(mem_size / 2, 128ULL * MiB)); > +#elif defined(TARGET_RISCV64) > +*start = (uint64_t) (kernel_entry + MIN(mem_size / 2, 128 * MiB)); > +#endif > > size = load_ramdisk(filename, *start, mem_size - *start); > if (size == -1) { > -- > 2.19.1 Maybe I'm missing something, but wouldn't something like uint64_t start_unclobbered = kernel_entry + MIN(mem_size / 2, 128ULL * MiB); assert(start_unclobbered == (hwaddr)start_unclobbered); *start = (hwaddr)start_unclobbered; work better? That should actually check this all lines up, as opposed to just silently truncating a bad address. >>> >>> The problem is that hwaddr is always 64-bit. >>> >>> Stupidly I forgot about target_ulong, which should work basically the >>> same as above. An assert() seems a little harsh though, Alex reported >>> problem was fixed with just a cast. >> >> OK, I must be misunderstanding the problem, then. With the current code, >> isn't >> it possible to end up causing start to overflow a 32-bit address? This would >> happen if kernel_entry is high, with IIUC is coming from the ELF to load and >> is >> therefor user input. I think that's worth some sort of assertion, as it'll >> definitely blow up trying to enter the kernel (and possible before that, >> assuming there's no target memory where it overflows into). > > I don't have a setup to reproduce this unfortunately, but Alex > reported that he saw start being excessively high (0x8800) > when loading an initrd. Sorry for only jumping in so late. I didn't actually propose the cast as a solution. The problem must be sign extension of some variable in the mix. I didn't find out quickly which one it was, so I figured I'd leave it for someone else to debug :). The issue is very easy to reproduce: Build U-Boot for the virt machine for riscv32. Then run it with $ qemu-system-riscv32 -M virt -kernel u-boot -nographic -initrd You can find the initrd address with U-Boot# fdt addr $fdtcontroladdr U-Boot# fdt ls /chosen Then take a peek at that address: U-Boot# md.b and you will see that there is nothing there without this patch. The reason is that the binary was loaded to a negative address. Again, probably some misguided sign extension. > It looks like the kernel entry address ends up being converted to > 0x8000 incorrectly instead of being a real overflow. Yeah, so we seem to cast from int32_t to int64_t somewhere. Can you spot where exactly? That's where the bug is :). Alex
Re: [Qemu-devel] [PATCH v1 1/1] riscv: virt: Cast the initrd start address to target bit length
On Mon, Nov 26, 2018 at 11:02 AM Palmer Dabbelt wrote: > > On Wed, 21 Nov 2018 18:09:27 PST (-0800), alistai...@gmail.com wrote: > > On Wed, Nov 21, 2018 at 5:58 PM Palmer Dabbelt wrote: > >> > >> On Wed, 21 Nov 2018 14:34:44 PST (-0800), Alistair Francis wrote: > >> > Ensure that the calculate initrd offset points to a valid address for > >> > the architecture. > >> > > >> > Signed-off-by: Alistair Francis > >> > Suggested-by: Alexander Graf > >> > Reported-by: Alexander Graf > >> > --- > >> > hw/riscv/virt.c | 7 ++- > >> > 1 file changed, 6 insertions(+), 1 deletion(-) > >> > > >> > diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c > >> > index 2b38f89070..4467195fac 100644 > >> > --- a/hw/riscv/virt.c > >> > +++ b/hw/riscv/virt.c > >> > @@ -85,7 +85,12 @@ static hwaddr load_initrd(const char *filename, > >> > uint64_t mem_size, > >> > * halfway into RAM, and for boards with 256MB of RAM or more we put > >> > * the initrd at 128MB. > >> > */ > >> > -*start = kernel_entry + MIN(mem_size / 2, 128 * MiB); > >> > +/* As hwaddr is a 64-bit number we need to cast it for 32-bit */ > >> > +#if defined(TARGET_RISCV32) > >> > +*start = (uint32_t) (kernel_entry + MIN(mem_size / 2, 128ULL * > >> > MiB)); > >> > +#elif defined(TARGET_RISCV64) > >> > +*start = (uint64_t) (kernel_entry + MIN(mem_size / 2, 128 * MiB)); > >> > +#endif > >> > > >> > size = load_ramdisk(filename, *start, mem_size - *start); > >> > if (size == -1) { > >> > -- > >> > 2.19.1 > >> > >> Maybe I'm missing something, but wouldn't something like > >> > >> uint64_t start_unclobbered = kernel_entry + MIN(mem_size / 2, 128ULL * > >> MiB); > >> assert(start_unclobbered == (hwaddr)start_unclobbered); > >> *start = (hwaddr)start_unclobbered; > >> > >> work better? That should actually check this all lines up, as opposed to > >> just > >> silently truncating a bad address. > > > > The problem is that hwaddr is always 64-bit. > > > > Stupidly I forgot about target_ulong, which should work basically the > > same as above. An assert() seems a little harsh though, Alex reported > > problem was fixed with just a cast. > > OK, I must be misunderstanding the problem, then. With the current code, > isn't > it possible to end up causing start to overflow a 32-bit address? This would > happen if kernel_entry is high, with IIUC is coming from the ELF to load and > is > therefor user input. I think that's worth some sort of assertion, as it'll > definitely blow up trying to enter the kernel (and possible before that, > assuming there's no target memory where it overflows into). I don't have a setup to reproduce this unfortunately, but Alex reported that he saw start being excessively high (0x8800) when loading an initrd. It looks like the kernel entry address ends up being converted to 0x8000 incorrectly instead of being a real overflow. Alistair > > This won't happen with the default Linux setup, but could happen if users are > trying to do something weird.
[Qemu-devel] [Bug 1805445] Re: QEMU arm virt machine was stopped by STMFD command while debug process
Maybe this is correct for palmetto-board, but qemu user should be able to debug any basic arm instructions for generic arm board with general purpose SPI, I2C etc... My SPI Flash has 4 Mb, and RAM adress may start from 0x40, This is impossible for 256 Mb Flash. It would be great, if qemu can build general arm device with var ram adr, cpu core and block dev. -- You received this bug notification because you are a member of qemu- devel-ml, which is subscribed to QEMU. https://bugs.launchpad.net/bugs/1805445 Title: QEMU arm virt machine was stopped by STMFD command while debug process Status in QEMU: New Bug description: Hello, i have a big problem with QEMU arm virtual machine. So... I run QEMU machine with bare-metal ThreadX fullflash from Texet TM-333 phone (Spreadtrum platform) [CODE]qemu-system-arm -S -gdb tcp::1234,ipv4 -drive file=C:\cygwin64\home\flash.bin,if=mtd,format=raw -M palmetto-bmc -cpu arm926 -m 64M[/CODE] I use palmetto-bmc platform because it have ARM926EJ-S core and support SPI Flash. Then, i attach to gdb qemu process from IDA and run code step-by-step. [IMG]https://pp.userapi.com/c847218/v847218546/13ec1c/iSIcre5-js4.jpg[/IMG] When the IDA run 00032534 STR R11, [R10] command [IMG]https://pp.userapi.com/c846416/v846416708/133f60/GQzxORvf4Tg.jpg[/IMG] instead of store R11 on R10 adress, it jump 000328DC STMFD SP!, {R0-R12,LR} instruction... [IMG]https://pp.userapi.com/c847218/v847218546/13ec26/32A0VcaJywg.jpg[/IMG] and virt machine not execute new instruction... [IMG]https://pp.userapi.com/c850624/v850624111/528f3/N7FTpgloWVU.jpg[/IMG] and why i did not change flash from n25q256a to n25q032a11 in aspeed.c without rebuild qemu? To manage notifications about this bug go to: https://bugs.launchpad.net/qemu/+bug/1805445/+subscriptions
Re: [Qemu-devel] [RFC v2 00/24] Add RISC-V TCG backend support
On Tue, Nov 27, 2018 at 1:06 PM Alistair Francis wrote: It looks like the cover was lost, here it is: This patch set adds RISC-V backend support to QEMU. This is based on Michael Clark's original work with some patches ontop. This has been slightly tested and can run other architecture softmmu code for a number of instructions but eventually QEMU will do something it shouldn't. I haven't tested linux user support at all yet. I think Michael had that working reliably though and hopefully my changes haven't broken it. I'll test both a lot more before I send a full patchset. There are still some todos in the code (there is missing instructions and byte swapping) and I'll have to rebase this ontop of Richard's TCG work. In the meantime I wanted to try and keep the ball rolling though. There are two WIP patches at the end of the series that I am not sure about, so they have been kept seperate from the series for the time being. This branch can be found here: https://github.com/alistair23/qemu/tree/mainline/alistair/tcg-backend-upstream.next The working version with Michael's orignal patch and work ontop can be found here: https://github.com/alistair23/qemu/tree/mainline/alistair/tcg-backend.next RFC v2: - A large number of changes based on Richard's feedback > > > Alistair Francis (24): > elf.h: Add the RISCV ELF magic numbers > linux-user: Add host dependency for RISC-V 32-bit > linux-user: Add host dependency for RISC-V 64-bit > exec: Add RISC-V GCC poison macro > riscv: Add the tcg-target header file > riscv: Add the tcg target registers > riscv: tcg-target: Add support for the constraints > riscv: tcg-target: Add the immediate encoders > riscv: tcg-target: Add the instruction emitters > riscv: tcg-target: Add the relocation functions > riscv: tcg-target: Add the mov and movi instruction > riscv: tcg-target: Add the extract instructions > riscv: tcg-target: Add the out load and store instructions > riscv: tcg-target: Add branch and jump instructions > riscv: tcg-target: Add slowpath load and store instructions > riscv: tcg-target: Add direct load and store instructions > riscv: tcg-target: Add the out op decoder > riscv: tcg-target: Add the prologue generation and register the JIT > riscv: tcg-target: Add the target init code > tcg: Add RISC-V cpu signal handler > dias: Add RISC-V support > configure: Add support for building RISC-V host > WIP: Add missing instructions > WIP: Try to patch longer branches > > accel/tcg/user-exec.c | 75 ++ > configure | 12 +- > disas.c | 10 +- > include/elf.h | 55 + > include/exec/poison.h |1 + > linux-user/host/riscv32/hostdep.h | 11 + > linux-user/host/riscv64/hostdep.h | 11 + > tcg/riscv/tcg-target.h| 173 +++ > tcg/riscv/tcg-target.inc.c| 1890 + > 9 files changed, 2234 insertions(+), 4 deletions(-) > create mode 100644 linux-user/host/riscv32/hostdep.h > create mode 100644 linux-user/host/riscv64/hostdep.h > create mode 100644 tcg/riscv/tcg-target.h > create mode 100644 tcg/riscv/tcg-target.inc.c > > -- > 2.19.1 >
[Qemu-devel] [RFC v2 19/24] riscv: tcg-target: Add the target init code
Signed-off-by: Alistair Francis Signed-off-by: Michael Clark --- tcg/riscv/tcg-target.inc.c | 31 +++ 1 file changed, 31 insertions(+) diff --git a/tcg/riscv/tcg-target.inc.c b/tcg/riscv/tcg-target.inc.c index 51961ade81..13756f6d0d 100644 --- a/tcg/riscv/tcg-target.inc.c +++ b/tcg/riscv/tcg-target.inc.c @@ -1683,6 +1683,37 @@ static void tcg_target_qemu_prologue(TCGContext *s) tcg_out_opc_imm(s, OPC_JALR, TCG_REG_ZERO, TCG_REG_RA, 0); } +static void tcg_target_init(TCGContext *s) +{ +tcg_target_available_regs[TCG_TYPE_I32] = 0x; +if (TCG_TARGET_REG_BITS == 64) { +tcg_target_available_regs[TCG_TYPE_I64] = 0x; +} + +tcg_target_call_clobber_regs = -1u; +tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S0); +tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S1); +tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S2); +tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S3); +tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S4); +tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S5); +tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S6); +tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S7); +tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S8); +tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S9); +tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S10); +tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S11); + +s->reserved_regs = 0; +tcg_regset_set_reg(s->reserved_regs, TCG_REG_ZERO); +tcg_regset_set_reg(s->reserved_regs, TCG_REG_TMP0); +tcg_regset_set_reg(s->reserved_regs, TCG_REG_TMP1); +tcg_regset_set_reg(s->reserved_regs, TCG_REG_TMP2); +tcg_regset_set_reg(s->reserved_regs, TCG_REG_SP); +tcg_regset_set_reg(s->reserved_regs, TCG_REG_GP); +tcg_regset_set_reg(s->reserved_regs, TCG_REG_TP); +} + void tb_target_set_jmp_target(uintptr_t tc_ptr, uintptr_t jmp_addr, uintptr_t addr) { -- 2.19.1
[Qemu-devel] [RFC v2 16/24] riscv: tcg-target: Add direct load and store instructions
Signed-off-by: Alistair Francis Signed-off-by: Michael Clark --- tcg/riscv/tcg-target.inc.c | 162 - 1 file changed, 158 insertions(+), 4 deletions(-) diff --git a/tcg/riscv/tcg-target.inc.c b/tcg/riscv/tcg-target.inc.c index 4f3a6de52c..e3b5f48848 100644 --- a/tcg/riscv/tcg-target.inc.c +++ b/tcg/riscv/tcg-target.inc.c @@ -816,14 +816,10 @@ static void tcg_out_tlb_load(TCGContext *s, TCGReg addrl, ? offsetof(CPUArchState, tlb_table[mem_index][0].addr_read) : offsetof(CPUArchState, tlb_table[mem_index][0].addr_write)); int add_off = offsetof(CPUArchState, tlb_table[mem_index][0].addend); -int addend_offset = (offsetof(CPUTLBEntry, addend)) - -(is_load ? offsetof(CPUTLBEntry, addr_read) - : offsetof(CPUTLBEntry, addr_write)); RISCVInsn load_cmp_op = (TARGET_LONG_BITS == 64 ? OPC_LD : TCG_TARGET_REG_BITS == 64 ? OPC_LWU : OPC_LW); RISCVInsn load_add_op = TCG_TARGET_REG_BITS == 64 ? OPC_LD : OPC_LW; TCGReg base = TCG_AREG0; -TCGReg cmpr; /* We don't support oversize guests */ if (TCG_TARGET_REG_BITS < TARGET_LONG_BITS) { @@ -991,6 +987,164 @@ static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *l) } #endif /* CONFIG_SOFTMMU */ +static void tcg_out_qemu_ld_direct(TCGContext *s, TCGReg lo, TCGReg hi, + TCGReg base, TCGMemOp opc, bool is_64) +{ +const TCGMemOp bswap = opc & MO_BSWAP; + +/* We don't yet handle byteswapping, assert */ +g_assert(!bswap); + +switch (opc & (MO_SSIZE)) { +case MO_UB: +tcg_out_opc_imm(s, OPC_LBU, lo, base, 0); +break; +case MO_SB: +tcg_out_opc_imm(s, OPC_LB, lo, base, 0); +break; +case MO_UW: +tcg_out_opc_imm(s, OPC_LHU, lo, base, 0); +break; +case MO_SW: +tcg_out_opc_imm(s, OPC_LH, lo, base, 0); +break; +case MO_UL: +if (TCG_TARGET_REG_BITS == 64 && is_64) { +tcg_out_opc_imm(s, OPC_LWU, lo, base, 0); +break; +} +/* FALLTHRU */ +case MO_SL: +tcg_out_opc_imm(s, OPC_LW, lo, base, 0); +break; +case MO_Q: +/* Prefer to load from offset 0 first, but allow for overlap. */ +if (TCG_TARGET_REG_BITS == 64) { +tcg_out_opc_imm(s, OPC_LD, lo, base, 0); +} else if (lo != base) { +tcg_out_opc_imm(s, OPC_LW, lo, base, 0); +tcg_out_opc_imm(s, OPC_LW, hi, base, 4); +} else { +tcg_out_opc_imm(s, OPC_LW, hi, base, 4); +tcg_out_opc_imm(s, OPC_LW, lo, base, 0); +} +break; +default: +g_assert_not_reached(); +} +} + +static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, bool is_64) +{ +TCGReg addr_regl, addr_regh __attribute__((unused)); +TCGReg data_regl, data_regh; +TCGMemOpIdx oi; +TCGMemOp opc; +#if defined(CONFIG_SOFTMMU) +tcg_insn_unit *label_ptr[1]; +#endif +TCGReg base = TCG_REG_TMP0; + +data_regl = *args++; +data_regh = (TCG_TARGET_REG_BITS == 32 && is_64 ? *args++ : 0); +addr_regl = *args++; +addr_regh = (TCG_TARGET_REG_BITS < TARGET_LONG_BITS ? *args++ : 0); +oi = *args++; +opc = get_memop(oi); + +#if defined(CONFIG_SOFTMMU) +tcg_out_tlb_load(s, addr_regl, addr_regh, oi, label_ptr, 1); +tcg_out_qemu_ld_direct(s, data_regl, data_regh, base, opc, is_64); +add_qemu_ldst_label(s, 1, oi, +(is_64 ? TCG_TYPE_I64 : TCG_TYPE_I32), +data_regl, data_regh, addr_regl, addr_regh, +s->code_ptr, label_ptr); +#else +if (TCG_TARGET_REG_BITS > TARGET_LONG_BITS) { +tcg_out_ext32u(s, base, addr_regl); +addr_regl = base; +} + +if (guest_base == 0) { +tcg_out_opc_reg(s, OPC_ADD, base, addr_regl, TCG_REG_ZERO); +} else { +tcg_out_opc_reg(s, OPC_ADD, base, TCG_GUEST_BASE_REG, addr_regl); +} +tcg_out_qemu_ld_direct(s, data_regl, data_regh, base, opc, is_64); +#endif +} + +static void tcg_out_qemu_st_direct(TCGContext *s, TCGReg lo, TCGReg hi, + TCGReg base, TCGMemOp opc) +{ +const TCGMemOp bswap = opc & MO_BSWAP; + +/* We don't yet handle byteswapping, assert */ +g_assert(!bswap); + +switch (opc & (MO_SSIZE)) { +case MO_8: +tcg_out_opc_store(s, OPC_SB, base, lo, 0); +break; +case MO_16: +tcg_out_opc_store(s, OPC_SH, base, lo, 0); +break; +case MO_32: +tcg_out_opc_store(s, OPC_SW, base, lo, 0); +break; +case MO_64: +if (TCG_TARGET_REG_BITS == 64) { +tcg_out_opc_store(s, OPC_SD, base, lo, 0); +} else { +tcg_out_opc_store(s, OPC_SW, base, lo, 0); +tcg_out_opc_store(s, OPC_SW, base, hi, 4); +} +break; +default
[Qemu-devel] [RFC v2 24/24] WIP: Try to patch longer branches
Signed-off-by: Alistair Francis --- tcg/riscv/tcg-target.inc.c | 44 +++--- 1 file changed, 41 insertions(+), 3 deletions(-) diff --git a/tcg/riscv/tcg-target.inc.c b/tcg/riscv/tcg-target.inc.c index b8e9c0e126..cf1680935a 100644 --- a/tcg/riscv/tcg-target.inc.c +++ b/tcg/riscv/tcg-target.inc.c @@ -418,10 +418,37 @@ static void reloc_call(tcg_insn_unit *code_ptr, tcg_insn_unit *target) static void patch_reloc(tcg_insn_unit *code_ptr, int type, intptr_t value, intptr_t addend) { +uint32_t insn = *code_ptr; +intptr_t diff; +bool short_jmp; + tcg_debug_assert(addend == 0); + switch (type) { case R_RISCV_BRANCH: -reloc_sbimm12(code_ptr, (tcg_insn_unit *)value); +diff = value - (uintptr_t)code_ptr; +#if TCG_TARGET_REG_BITS == 64 +short_jmp = diff == sextract64(diff, 0, 12); +#else +short_jmp = diff == sextract32(diff, 0, 12); +#endif +if (short_jmp) { +reloc_sbimm12(code_ptr, (tcg_insn_unit *)value); +} else { +/* Invert the condition */ +insn = insn ^ (1 << 12); +/* Clear the offset */ +insn &= 0xFFF; +/* Set the offset to the PC + 8 */ +insn |= ((unsigned int)(code_ptr + 8)) << 12; + +/* Move forward */ +code_ptr++; +insn = *code_ptr; + +/* Overwrite the NOP with jal x0,value */ +insn = encode_uj(OPC_JAL, TCG_REG_ZERO, value); +} break; case R_RISCV_JAL: reloc_jimm20(code_ptr, (tcg_insn_unit *)value); @@ -677,16 +704,27 @@ static void tcg_out_brcond(TCGContext *s, TCGCond cond, TCGReg arg1, TCGReg arg2, TCGLabel *l) { RISCVInsn op = tcg_brcond_to_riscv[cond].op; +intptr_t diff; bool swap = tcg_brcond_to_riscv[cond].swap; +bool short_jmp; + +tcg_debug_assert(op != 0); tcg_out_opc_branch(s, op, swap ? arg2 : arg1, swap ? arg1 : arg2, 0); -tcg_debug_assert(op != 0); +diff = l->u.value_ptr - (uintptr_t)s->code_gen_ptr; +#if TCG_TARGET_REG_BITS == 64 +short_jmp = diff == sextract64(diff, 0, 12); +#else +short_jmp = diff == sextract32(diff, 0, 12); +#endif -if (l->has_value) { +if (l->has_value && short_jmp) { reloc_sbimm12(s->code_ptr - 1, l->u.value_ptr); } else { tcg_out_reloc(s, s->code_ptr - 1, R_RISCV_BRANCH, l, 0); +/* NOP to allow patching later */ +tcg_out_opc_imm(s, OPC_ADDI, TCG_REG_ZERO, TCG_REG_ZERO, 0); } } -- 2.19.1
[Qemu-devel] [RFC v2 22/24] configure: Add support for building RISC-V host
Signed-off-by: Alistair Francis Signed-off-by: Michael Clark Reviewed-by: Richard Henderson --- configure | 12 ++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/configure b/configure index 0a3c6a72c3..fb52954368 100755 --- a/configure +++ b/configure @@ -709,6 +709,12 @@ elif check_define __s390__ ; then else cpu="s390" fi +elif check_define __riscv ; then + if check_define _LP64 ; then +cpu="riscv64" + elif check_define _ILP32 ; then +cpu="riscv32" + fi elif check_define __arm__ ; then cpu="arm" elif check_define __aarch64__ ; then @@ -721,7 +727,7 @@ ARCH= # Normalise host CPU name and set ARCH. # Note that this case should only have supported host CPUs, not guests. case "$cpu" in - ppc|ppc64|s390|s390x|sparc64|x32) + ppc|ppc64|s390|s390x|sparc64|x32|riscv32|riscv64) cpu="$cpu" supported_cpu="yes" eval "cross_cc_${cpu}=\$host_cc" @@ -6900,6 +6906,8 @@ elif test "$ARCH" = "x86_64" -o "$ARCH" = "x32" ; then QEMU_INCLUDES="-iquote \$(SRC_PATH)/tcg/i386 $QEMU_INCLUDES" elif test "$ARCH" = "ppc64" ; then QEMU_INCLUDES="-iquote \$(SRC_PATH)/tcg/ppc $QEMU_INCLUDES" +elif test "$ARCH" = "riscv32" -o "$ARCH" = "riscv64" ; then + QEMU_INCLUDES="-I\$(SRC_PATH)/tcg/riscv $QEMU_INCLUDES" else QEMU_INCLUDES="-iquote \$(SRC_PATH)/tcg/\$(ARCH) $QEMU_INCLUDES" fi @@ -7397,7 +7405,7 @@ for i in $ARCH $TARGET_BASE_ARCH ; do ppc*) disas_config "PPC" ;; - riscv) + riscv*) disas_config "RISCV" ;; s390*) -- 2.19.1
[Qemu-devel] [RFC v2 15/24] riscv: tcg-target: Add slowpath load and store instructions
Signed-off-by: Alistair Francis Signed-off-by: Michael Clark --- tcg/riscv/tcg-target.inc.c | 244 + 1 file changed, 244 insertions(+) diff --git a/tcg/riscv/tcg-target.inc.c b/tcg/riscv/tcg-target.inc.c index 97831bfb9d..4f3a6de52c 100644 --- a/tcg/riscv/tcg-target.inc.c +++ b/tcg/riscv/tcg-target.inc.c @@ -747,6 +747,250 @@ static void tcg_out_call(TCGContext *s, tcg_insn_unit *arg) tcg_out_call_int(s, arg, false); } +static void tcg_out_mb(TCGContext *s, TCGArg a0) +{ +static const RISCVInsn fence[] = { +[0 ... TCG_MO_ALL] = OPC_FENCE_RW_RW, +[TCG_MO_LD_LD] = OPC_FENCE_R_R, +[TCG_MO_ST_LD] = OPC_FENCE_W_R, +[TCG_MO_LD_ST] = OPC_FENCE_R_W, +[TCG_MO_ST_ST] = OPC_FENCE_W_W, +}; +tcg_out32(s, fence[a0 & TCG_MO_ALL]); +} + +/* + * Load/store and TLB + */ + +#if defined(CONFIG_SOFTMMU) +#include "tcg-ldst.inc.c" + +/* helper signature: helper_ret_ld_mmu(CPUState *env, target_ulong addr, + * TCGMemOpIdx oi, uintptr_t ra) + */ +static void * const qemu_ld_helpers[16] = { +[MO_UB] = helper_ret_ldub_mmu, +[MO_SB] = helper_ret_ldsb_mmu, +[MO_LEUW] = helper_le_lduw_mmu, +[MO_LESW] = helper_le_ldsw_mmu, +[MO_LEUL] = helper_le_ldul_mmu, +#if TCG_TARGET_REG_BITS == 64 +[MO_LESL] = helper_le_ldsl_mmu, +#endif +[MO_LEQ] = helper_le_ldq_mmu, +[MO_BEUW] = helper_be_lduw_mmu, +[MO_BESW] = helper_be_ldsw_mmu, +[MO_BEUL] = helper_be_ldul_mmu, +#if TCG_TARGET_REG_BITS == 64 +[MO_BESL] = helper_be_ldsl_mmu, +#endif +[MO_BEQ] = helper_be_ldq_mmu, +}; + +/* helper signature: helper_ret_st_mmu(CPUState *env, target_ulong addr, + * uintxx_t val, TCGMemOpIdx oi, + * uintptr_t ra) + */ +static void * const qemu_st_helpers[16] = { +[MO_UB] = helper_ret_stb_mmu, +[MO_LEUW] = helper_le_stw_mmu, +[MO_LEUL] = helper_le_stl_mmu, +[MO_LEQ] = helper_le_stq_mmu, +[MO_BEUW] = helper_be_stw_mmu, +[MO_BEUL] = helper_be_stl_mmu, +[MO_BEQ] = helper_be_stq_mmu, +}; + +static void tcg_out_tlb_load(TCGContext *s, TCGReg addrl, + TCGReg addrh, TCGMemOpIdx oi, + tcg_insn_unit **label_ptr, bool is_load) +{ +TCGMemOp opc = get_memop(oi); +unsigned s_bits = opc & MO_SIZE; +unsigned a_bits = get_alignment_bits(opc); +target_ulong mask; +int mem_index = get_mmuidx(oi); +int cmp_off += (is_load + ? offsetof(CPUArchState, tlb_table[mem_index][0].addr_read) + : offsetof(CPUArchState, tlb_table[mem_index][0].addr_write)); +int add_off = offsetof(CPUArchState, tlb_table[mem_index][0].addend); +int addend_offset = (offsetof(CPUTLBEntry, addend)) - +(is_load ? offsetof(CPUTLBEntry, addr_read) + : offsetof(CPUTLBEntry, addr_write)); +RISCVInsn load_cmp_op = (TARGET_LONG_BITS == 64 ? OPC_LD : + TCG_TARGET_REG_BITS == 64 ? OPC_LWU : OPC_LW); +RISCVInsn load_add_op = TCG_TARGET_REG_BITS == 64 ? OPC_LD : OPC_LW; +TCGReg base = TCG_AREG0; +TCGReg cmpr; + +/* We don't support oversize guests */ +if (TCG_TARGET_REG_BITS < TARGET_LONG_BITS) { +g_assert_not_reached(); +} + +/* We don't support unaligned accesses. */ +if (a_bits < s_bits) { +a_bits = s_bits; +} +mask = (target_ulong)TARGET_PAGE_MASK | ((1 << a_bits) - 1); + + +/* Compensate for very large offsets. */ +if (add_off >= 0x1000) { +int adj; +base = TCG_REG_TMP2; +if (cmp_off <= 2 * 0xfff) { +adj = 0xfff; +tcg_out_opc_imm(s, OPC_ADDI, base, TCG_AREG0, adj); +} else { +adj = cmp_off - sextract32(cmp_off, 0, 12); +tcg_debug_assert(add_off - adj >= -0x1000 + && add_off - adj < 0x1000); + +tcg_out_opc_upper(s, OPC_LUI, base, adj); +tcg_out_opc_reg(s, OPC_ADD, base, base, TCG_AREG0); +} +add_off -= adj; +cmp_off -= adj; +} + +/* Extract the page index. */ +if (CPU_TLB_BITS + CPU_TLB_ENTRY_BITS < 12) { +tcg_out_opc_imm(s, OPC_SRLI, TCG_REG_TMP0, addrl, +TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS); +tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_TMP0, TCG_REG_TMP0, +MAKE_64BIT_MASK(CPU_TLB_ENTRY_BITS, CPU_TLB_BITS)); +} else { +tcg_out_opc_imm(s, OPC_SRLI, TCG_REG_TMP0, addrl, TARGET_PAGE_BITS); +tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_TMP0, TCG_REG_TMP0, +MAKE_64BIT_MASK(0, CPU_TLB_BITS)); +tcg_out_opc_imm(s, OPC_SLLI, TCG_REG_TMP0, TCG_REG_TMP0, +CPU_TLB_ENTRY_BITS); +} + +/* Add that to the base address to index the tlb. */ +tcg_out_opc_reg(s
[Qemu-devel] [RFC v2 11/24] riscv: tcg-target: Add the mov and movi instruction
Signed-off-by: Alistair Francis Signed-off-by: Michael Clark --- tcg/riscv/tcg-target.inc.c | 78 ++ 1 file changed, 78 insertions(+) diff --git a/tcg/riscv/tcg-target.inc.c b/tcg/riscv/tcg-target.inc.c index 9c48679f11..e5a07b146f 100644 --- a/tcg/riscv/tcg-target.inc.c +++ b/tcg/riscv/tcg-target.inc.c @@ -434,6 +434,84 @@ static void patch_reloc(tcg_insn_unit *code_ptr, int type, } } +/* + * TCG intrinsics + */ + +static void tcg_out_mov(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg) +{ +if (ret == arg) { +return; +} +switch (type) { +case TCG_TYPE_I32: +case TCG_TYPE_I64: +tcg_out_opc_imm(s, OPC_ADDI, ret, arg, 0); +break; +default: +g_assert_not_reached(); +} +} + +static void tcg_out_movi(TCGContext *s, TCGType type, TCGReg rd, + tcg_target_long val) +{ +#if TCG_TARGET_REG_BITS == 64 +tcg_target_long lo = sextract64(val, 0, 12); +#else +tcg_target_long lo = sextract32(val, 0, 12); +#endif +tcg_target_long hi = val - lo; +int shift; +tcg_target_long tmp; + +RISCVInsn add32_op = TCG_TARGET_REG_BITS == 64 ? OPC_ADDIW : OPC_ADDI; + +#if TCG_TARGET_REG_BITS == 64 +ptrdiff_t offset = tcg_pcrel_diff(s, (void *)val); +#endif + +if (TCG_TARGET_REG_BITS == 32 || val == (int32_t)val) { +tcg_out_opc_upper(s, OPC_LUI, rd, hi); +if (lo != 0) { +tcg_out_opc_imm(s, add32_op, rd, rd, lo); +} + +return; +} + +/* We can only be here if TCG_TARGET_REG_BITS != 32 */ +if (offset == sextract64(offset, 1, 31) << 1) { +tcg_out_opc_upper(s, OPC_AUIPC, rd, 0); +tcg_out_opc_imm(s, OPC_ADDI, rd, rd, 0); +reloc_call(s->code_ptr - 2, (tcg_insn_unit *)val); +return; +} + +shift = ctz64(val); +tmp = val >> shift; + +if (tmp == sextract64(tmp, 0, 12)) { +tcg_out_opc_imm(s, OPC_ADDI, rd, TCG_REG_ZERO, 1); +tcg_out_opc_imm(s, OPC_SLLI, rd, rd, ctz64(val)); +} else if (!(val >> 31 == 0 || val >> 31 == -1)) { +shift = ctz64(hi); +hi >>= shift; +tcg_out_movi(s, type, rd, hi); +tcg_out_opc_imm(s, OPC_SLLI, rd, rd, shift); +if (lo != 0) { +tcg_out_opc_imm(s, OPC_ADDI, rd, rd, lo); +} +} else { +if (hi != 0) { +tcg_out_opc_upper(s, OPC_LUI, rd, hi); +} +if (lo != 0) { +tcg_out_opc_imm(s, add32_op, rd, hi == 0 ? TCG_REG_ZERO : rd, lo); +} +} +} + void tb_target_set_jmp_target(uintptr_t tc_ptr, uintptr_t jmp_addr, uintptr_t addr) { -- 2.19.1
[Qemu-devel] [RFC v2 18/24] riscv: tcg-target: Add the prologue generation and register the JIT
Signed-off-by: Alistair Francis Signed-off-by: Michael Clark --- tcg/riscv/tcg-target.inc.c | 111 + 1 file changed, 111 insertions(+) diff --git a/tcg/riscv/tcg-target.inc.c b/tcg/riscv/tcg-target.inc.c index d5fd7ca854..51961ade81 100644 --- a/tcg/riscv/tcg-target.inc.c +++ b/tcg/riscv/tcg-target.inc.c @@ -1617,6 +1617,72 @@ static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op) } } +static const int tcg_target_callee_save_regs[] = { +TCG_REG_S0, /* used for the global env (TCG_AREG0) */ +TCG_REG_S1, +TCG_REG_S2, +TCG_REG_S3, +TCG_REG_S4, +TCG_REG_S5, +TCG_REG_S6, +TCG_REG_S7, +TCG_REG_S8, +TCG_REG_S9, +TCG_REG_S10, +TCG_REG_S11, +TCG_REG_RA, /* should be last for ABI compliance */ +}; + +/* Stack frame parameters. */ +#define REG_SIZE (TCG_TARGET_REG_BITS / 8) +#define SAVE_SIZE ((int)ARRAY_SIZE(tcg_target_callee_save_regs) * REG_SIZE) +#define TEMP_SIZE (CPU_TEMP_BUF_NLONGS * (int)sizeof(long)) +#define FRAME_SIZE ((TCG_STATIC_CALL_ARGS_SIZE + TEMP_SIZE + SAVE_SIZE \ + + TCG_TARGET_STACK_ALIGN - 1) \ +& -TCG_TARGET_STACK_ALIGN) +#define SAVE_OFS (TCG_STATIC_CALL_ARGS_SIZE + TEMP_SIZE) + +/* We're expecting to be able to use an immediate for frame allocation. */ +QEMU_BUILD_BUG_ON(FRAME_SIZE > 0x7ff); + +/* Generate global QEMU prologue and epilogue code */ +static void tcg_target_qemu_prologue(TCGContext *s) +{ +int i; + +tcg_set_frame(s, TCG_REG_SP, TCG_STATIC_CALL_ARGS_SIZE, TEMP_SIZE); + +/* TB prologue */ +tcg_out_opc_imm(s, OPC_ADDI, TCG_REG_SP, TCG_REG_SP, -FRAME_SIZE); +for (i = 0; i < ARRAY_SIZE(tcg_target_callee_save_regs); i++) { +tcg_out_st(s, TCG_TYPE_REG, tcg_target_callee_save_regs[i], + TCG_REG_SP, SAVE_OFS + i * REG_SIZE); +} + +#if !defined(CONFIG_SOFTMMU) +tcg_out_movi(s, TCG_TYPE_PTR, TCG_GUEST_BASE_REG, guest_base); +tcg_regset_set_reg(s->reserved_regs, TCG_GUEST_BASE_REG); +#endif + +/* Call generated code */ +tcg_out_mov(s, TCG_TYPE_PTR, TCG_AREG0, tcg_target_call_iarg_regs[0]); +tcg_out_opc_imm(s, OPC_JALR, TCG_REG_ZERO, tcg_target_call_iarg_regs[1], 0); + +/* Return path for goto_ptr. Set return value to 0 */ +s->code_gen_epilogue = s->code_ptr; +tcg_out_mov(s, TCG_TYPE_REG, TCG_REG_A0, TCG_REG_ZERO); + +/* TB epilogue */ +tb_ret_addr = s->code_ptr; +for (i = 0; i < ARRAY_SIZE(tcg_target_callee_save_regs); i++) { +tcg_out_ld(s, TCG_TYPE_REG, tcg_target_callee_save_regs[i], + TCG_REG_SP, SAVE_OFS + i * REG_SIZE); +} + +tcg_out_opc_imm(s, OPC_ADDI, TCG_REG_SP, TCG_REG_SP, FRAME_SIZE); +tcg_out_opc_imm(s, OPC_JALR, TCG_REG_ZERO, TCG_REG_RA, 0); +} + void tb_target_set_jmp_target(uintptr_t tc_ptr, uintptr_t jmp_addr, uintptr_t addr) { @@ -1631,3 +1697,48 @@ void tb_target_set_jmp_target(uintptr_t tc_ptr, uintptr_t jmp_addr, flush_icache_range(jmp_addr, jmp_addr + 8); } + +typedef struct { +DebugFrameHeader h; +uint8_t fde_def_cfa[4]; +uint8_t fde_reg_ofs[ARRAY_SIZE(tcg_target_callee_save_regs) * 2]; +} DebugFrame; + +#define ELF_HOST_MACHINE EM_RISCV + +static const DebugFrame debug_frame = { +.h.cie.len = sizeof(DebugFrameCIE) - 4, /* length after .len member */ +.h.cie.id = -1, +.h.cie.version = 1, +.h.cie.code_align = 1, +.h.cie.data_align = -(TCG_TARGET_REG_BITS / 8) & 0x7f, /* sleb128 */ +.h.cie.return_column = TCG_REG_RA, + +/* Total FDE size does not include the "len" member. */ +.h.fde.len = sizeof(DebugFrame) - offsetof(DebugFrame, h.fde.cie_offset), + +.fde_def_cfa = { +12, TCG_REG_SP, /* DW_CFA_def_cfa sp, ... */ +(FRAME_SIZE & 0x7f) | 0x80, /* ... uleb128 FRAME_SIZE */ +(FRAME_SIZE >> 7) +}, +.fde_reg_ofs = { +0x80 + 9, 12, /* DW_CFA_offset, s1, -96 */ +0x80 + 18, 11, /* DW_CFA_offset, s2, -88 */ +0x80 + 19, 10, /* DW_CFA_offset, s3, -80 */ +0x80 + 20, 9, /* DW_CFA_offset, s4, -72 */ +0x80 + 21, 8, /* DW_CFA_offset, s5, -64 */ +0x80 + 22, 7, /* DW_CFA_offset, s6, -56 */ +0x80 + 23, 6, /* DW_CFA_offset, s7, -48 */ +0x80 + 24, 5, /* DW_CFA_offset, s8, -40 */ +0x80 + 25, 4, /* DW_CFA_offset, s9, -32 */ +0x80 + 26, 3, /* DW_CFA_offset, s10, -24 */ +0x80 + 27, 2, /* DW_CFA_offset, s11, -16 */ +0x80 + 1 , 1, /* DW_CFA_offset, ra, -8 */ +} +}; + +void tcg_register_jit(void *buf, size_t buf_size) +{ +tcg_register_jit_int(buf, buf_size, &debug_frame, sizeof(debug_frame)); +} -- 2.19.1
[Qemu-devel] [RFC v2 23/24] WIP: Add missing instructions
Signed-off-by: Alistair Francis --- tcg/riscv/tcg-target.inc.c | 77 ++ 1 file changed, 77 insertions(+) diff --git a/tcg/riscv/tcg-target.inc.c b/tcg/riscv/tcg-target.inc.c index 13756f6d0d..b8e9c0e126 100644 --- a/tcg/riscv/tcg-target.inc.c +++ b/tcg/riscv/tcg-target.inc.c @@ -606,6 +606,57 @@ static bool tcg_out_sti(TCGContext *s, TCGType type, TCGArg val, return false; } +static void tcg_out_addsub2(TCGContext *s, +TCGReg rl, TCGReg rh, +TCGReg al, TCGReg ah, +TCGReg bl, TCGReg bh, +bool cbl, bool cbh, bool is_sub) +{ +/* FIXME: This is just copied from MIPS */ +TCGReg th = TCG_REG_TMP1; + +/* If we have a negative constant such that negating it would + make the high part zero, we can (usually) eliminate one insn. */ +if (cbl && cbh && bh == -1 && bl != 0) { +bl = -bl; +bh = 0; +is_sub = !is_sub; +} + +/* By operating on the high part first, we get to use the final + carry operation to move back from the temporary. */ +if (!cbh) { +tcg_out_opc_reg(s, (is_sub ? OPC_SUB : OPC_ADDI), th, ah, bh); +} else if (bh != 0 || ah == rl) { +tcg_out_opc_imm(s, OPC_ADDI, th, ah, (is_sub ? -bh : bh)); +} else { +th = ah; +} + +if (is_sub) { +if (cbl) { +tcg_out_opc_imm(s, OPC_SLLI, TCG_REG_TMP0, al, bl); +tcg_out_opc_imm(s, OPC_ADDI, rl, al, -bl); +} else { +tcg_out_opc_reg(s, OPC_SLLI, TCG_REG_TMP0, al, bl); +tcg_out_opc_reg(s, OPC_SUB, rl, al, bl); +} +tcg_out_opc_reg(s, OPC_SUB, rh, th, TCG_REG_TMP0); +} else { +if (cbl) { +tcg_out_opc_imm(s, OPC_ADDI, rl, al, bl); +tcg_out_opc_imm(s, OPC_SLLI, TCG_REG_TMP0, rl, bl); +} else if (rl == al && rl == bl) { +tcg_out_opc_imm(s, OPC_SRLI, TCG_REG_TMP0, al, 31); +tcg_out_opc_reg(s, OPC_ADDI, rl, al, bl); +} else { +tcg_out_opc_reg(s, OPC_ADDI, rl, al, bl); +tcg_out_opc_reg(s, OPC_SLLI, TCG_REG_TMP0, rl, (rl == bl ? al : bl)); +} +tcg_out_opc_reg(s, OPC_ADDI, rh, th, TCG_REG_TMP0); +} +} + static const struct { RISCVInsn op; bool swap; @@ -1384,6 +1435,18 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, } break; +case INDEX_op_add2_i32: +case INDEX_op_add2_i64: +tcg_out_addsub2(s, a0, a1, a2, args[3], args[4], args[5], +const_args[4], const_args[5], false); +break; + +case INDEX_op_sub2_i32: +case INDEX_op_sub2_i64: +tcg_out_addsub2(s, a0, a1, a2, args[3], args[4], args[5], +const_args[4], const_args[5], true); +break; + case INDEX_op_brcond_i32: case INDEX_op_brcond_i64: tcg_out_brcond(s, a2, a0, a1, arg_label(args[3])); @@ -1439,6 +1502,8 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, break; case INDEX_op_ext32s_i64: +case INDEX_op_extrl_i64_i32: +case INDEX_op_extrh_i64_i32: case INDEX_op_ext_i32_i64: tcg_out_ext32s(s, a0, a1); break; @@ -1505,6 +1570,8 @@ static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op) = { .args_ct_str = { "LZ", "LZ", "L" } }; static const TCGTargetOpDef LZ_LZ_L_L = { .args_ct_str = { "LZ", "LZ", "L", "L" } }; +static const TCGTargetOpDef rZ_rZ_rZ_rZ_rZ_rZ += { .args_ct_str = { "rZ", "rZ", "rZ", "rZ", "rZ", "rZ" } }; switch (op) { case INDEX_op_goto_ptr: @@ -1537,6 +1604,8 @@ static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op) case INDEX_op_ext16s_i32: case INDEX_op_ext16s_i64: case INDEX_op_ext32s_i64: +case INDEX_op_extrl_i64_i32: +case INDEX_op_extrh_i64_i32: case INDEX_op_ext_i32_i64: return &r_r; @@ -1593,6 +1662,14 @@ static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op) case INDEX_op_brcond_i64: return &rZ_rZ; +case INDEX_op_add2_i32: +case INDEX_op_add2_i64: +return &rZ_rZ_rZ_rZ_rZ_rZ; + +case INDEX_op_sub2_i32: +case INDEX_op_sub2_i64: +return &rZ_rZ_rZ_rZ_rZ_rZ; + case INDEX_op_brcond2_i32: return &rZ_rZ_rZ_rZ; -- 2.19.1
[Qemu-devel] [RFC v2 20/24] tcg: Add RISC-V cpu signal handler
Signed-off-by: Alistair Francis Signed-off-by: Michael Clark --- accel/tcg/user-exec.c | 75 +++ 1 file changed, 75 insertions(+) diff --git a/accel/tcg/user-exec.c b/accel/tcg/user-exec.c index cd75829cf2..941295ea49 100644 --- a/accel/tcg/user-exec.c +++ b/accel/tcg/user-exec.c @@ -571,6 +571,81 @@ int cpu_signal_handler(int host_signum, void *pinfo, return handle_cpu_signal(pc, info, is_write, &uc->uc_sigmask); } +#elif defined(__riscv) + +int cpu_signal_handler(int host_signum, void *pinfo, + void *puc) +{ +siginfo_t *info = pinfo; +ucontext_t *uc = puc; +greg_t pc = uc->uc_mcontext.__gregs[REG_PC]; +uint32_t insn = *(uint32_t *)pc; +int is_write = 0; + +/* Detect store by reading the instruction at the program + counter. Note: we currently only generate 32-bit + instructions so we thus only detect 32-bit stores */ +switch (((insn >> 0) & 0b11)) { +case 3: +switch (((insn >> 2) & 0b1)) { +case 8: +switch (((insn >> 12) & 0b111)) { +case 0: /* sb */ +case 1: /* sh */ +case 2: /* sw */ +case 3: /* sd */ +case 4: /* sq */ +is_write = 1; +break; +default: +break; +} +break; +case 9: +switch (((insn >> 12) & 0b111)) { +case 2: /* fsw */ +case 3: /* fsd */ +case 4: /* fsq */ +is_write = 1; +break; +default: +break; +} +break; +default: +break; +} +} + +/* Check for compressed instructions */ +switch (((insn >> 13) & 0b111)) { +case 7: +switch (insn & 0b11) { +case 0: /*c.sd */ +case 2: /* c.sdsp */ +is_write = 1; +break; +default: +break; +} +break; +case 6: +switch (insn & 0b11) { +case 0: /* c.sw */ +case 3: /* c.swsp */ +is_write = 1; +break; +default: +break; +} +break; +default: +break; +} + +return handle_cpu_signal(pc, info, is_write, &uc->uc_sigmask); +} + #else #error host CPU specific signal handler needed -- 2.19.1
[Qemu-devel] [RFC v2 09/24] riscv: tcg-target: Add the instruction emitters
Signed-off-by: Alistair Francis Signed-off-by: Michael Clark Reviewed-by: Richard Henderson --- tcg/riscv/tcg-target.inc.c | 40 ++ 1 file changed, 40 insertions(+) diff --git a/tcg/riscv/tcg-target.inc.c b/tcg/riscv/tcg-target.inc.c index c659c4de39..ca7ae8939a 100644 --- a/tcg/riscv/tcg-target.inc.c +++ b/tcg/riscv/tcg-target.inc.c @@ -343,6 +343,46 @@ static int32_t encode_uj(RISCVInsn opc, TCGReg rd, uint32_t imm) return opc | (rd & 0x1f) << 7 | encode_ujimm12(imm); } +/* + * RISC-V instruction emitters + */ + +static void tcg_out_opc_reg(TCGContext *s, RISCVInsn opc, +TCGReg rd, TCGReg rs1, TCGReg rs2) +{ +tcg_out32(s, encode_r(opc, rd, rs1, rs2)); +} + +static void tcg_out_opc_imm(TCGContext *s, RISCVInsn opc, +TCGReg rd, TCGReg rs1, TCGArg imm) +{ +tcg_out32(s, encode_i(opc, rd, rs1, imm)); +} + +static void tcg_out_opc_store(TCGContext *s, RISCVInsn opc, + TCGReg rs1, TCGReg rs2, uint32_t imm) +{ +tcg_out32(s, encode_s(opc, rs1, rs2, imm)); +} + +static void tcg_out_opc_branch(TCGContext *s, RISCVInsn opc, + TCGReg rs1, TCGReg rs2, uint32_t imm) +{ +tcg_out32(s, encode_sb(opc, rs1, rs2, imm)); +} + +static void tcg_out_opc_upper(TCGContext *s, RISCVInsn opc, + TCGReg rd, uint32_t imm) +{ +tcg_out32(s, encode_u(opc, rd, imm)); +} + +static void tcg_out_opc_jump(TCGContext *s, RISCVInsn opc, + TCGReg rd, uint32_t imm) +{ +tcg_out32(s, encode_uj(opc, rd, imm)); +} + void tb_target_set_jmp_target(uintptr_t tc_ptr, uintptr_t jmp_addr, uintptr_t addr) { -- 2.19.1
[Qemu-devel] [RFC v2 21/24] dias: Add RISC-V support
Signed-off-by: Alistair Francis Signed-off-by: Michael Clark Reviewed-by: Richard Henderson --- disas.c | 10 -- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/disas.c b/disas.c index 5325b7e6be..82a408f272 100644 --- a/disas.c +++ b/disas.c @@ -522,8 +522,14 @@ 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(__riscv) && defined(CONFIG_RISCV_DIS) +#if defined(_ILP32) +print_insn = print_insn_riscv32; +#elif defined(_LP64) +print_insn = print_insn_riscv64; +#else +#error unsupported RISC-V ABI +#endif #elif defined(__aarch64__) && defined(CONFIG_ARM_A64_DIS) print_insn = print_insn_arm_a64; s.info.cap_arch = CS_ARCH_ARM64; -- 2.19.1
[Qemu-devel] [RFC QEMU v2 1/2] arm/virt: Initialize generic timer scale factor dynamically
Initialize the generic timer scale factor based on the counter frequency register cntfrq_el0, and default to the current static value if necessary. Always use the default value for TCG. Signed-off-by: Bijan Mottahedeh --- hw/arm/virt.c | 17 + target/arm/helper.c| 19 --- target/arm/internals.h | 8 ++-- target/arm/kvm64.c | 1 + 4 files changed, 40 insertions(+), 5 deletions(-) diff --git a/hw/arm/virt.c b/hw/arm/virt.c index 281ddcd..792d223 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -59,6 +59,7 @@ #include "qapi/visitor.h" #include "standard-headers/linux/input.h" #include "hw/arm/smmuv3.h" +#include "target/arm/internals.h" #define DEFINE_VIRT_MACHINE_LATEST(major, minor, latest) \ static void virt_##major##_##minor##_class_init(ObjectClass *oc, \ @@ -1710,6 +1711,21 @@ static HotplugHandler *virt_machine_get_hotplug_handler(MachineState *machine, return NULL; } +static void set_system_clock_scale(void) +{ +unsigned long cntfrq_el0 = 0; + +#ifdef CONFIG_KVM +asm volatile("mrs %0, cntfrq_el0" : "=r"(cntfrq_el0)); +#endif + +if (cntfrq_el0 == 0) { +cntfrq_el0 = GTIMER_SCALE_DEF; +} + +system_clock_scale = NANOSECONDS_PER_SECOND / (int)cntfrq_el0; +} + static void virt_machine_class_init(ObjectClass *oc, void *data) { MachineClass *mc = MACHINE_CLASS(oc); @@ -1736,6 +1752,7 @@ static void virt_machine_class_init(ObjectClass *oc, void *data) assert(!mc->get_hotplug_handler); mc->get_hotplug_handler = virt_machine_get_hotplug_handler; hc->plug = virt_machine_device_plug_cb; +set_system_clock_scale(); } static const TypeInfo virt_machine_info = { diff --git a/target/arm/helper.c b/target/arm/helper.c index 66afb08..6330586 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -18,6 +18,7 @@ #include "sysemu/kvm.h" #include "fpu/softfloat.h" #include "qemu/range.h" +#include "hw/arm/arm.h" #define ARM_CPU_FREQ 10 /* FIXME: 1 GHz, should be configurable */ @@ -1614,6 +1615,18 @@ static CPAccessResult gt_cntfrq_access(CPUARMState *env, const ARMCPRegInfo *ri, return CP_ACCESS_OK; } +static void gt_cntfrq_reset(CPUARMState *env, const ARMCPRegInfo *ri) +{ +assert(GTIMER_SCALE); +assert(ri->fieldoffset); + +if (cpreg_field_is_64bit(ri)) { +CPREG_FIELD64(env, ri) = NANOSECONDS_PER_SECOND / GTIMER_SCALE; +} else { +CPREG_FIELD32(env, ri) = NANOSECONDS_PER_SECOND / GTIMER_SCALE; +} +} + static CPAccessResult gt_counter_access(CPUARMState *env, int timeridx, bool isread) { @@ -1709,7 +1722,7 @@ static CPAccessResult gt_stimer_access(CPUARMState *env, } } -static uint64_t gt_get_countervalue(CPUARMState *env) +uint64_t gt_get_countervalue(CPUARMState *env) { return qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) / GTIMER_SCALE; } @@ -1996,7 +2009,7 @@ static const ARMCPRegInfo generic_timer_cp_reginfo[] = { .opc0 = 3, .opc1 = 3, .crn = 14, .crm = 0, .opc2 = 0, .access = PL1_RW | PL0_R, .accessfn = gt_cntfrq_access, .fieldoffset = offsetof(CPUARMState, cp15.c14_cntfrq), - .resetvalue = (1000 * 1000 * 1000) / GTIMER_SCALE, + .resetfn = gt_cntfrq_reset, }, /* overall control: mostly access permissions */ { .name = "CNTKCTL", .state = ARM_CP_STATE_BOTH, @@ -2187,7 +2200,7 @@ static const ARMCPRegInfo generic_timer_cp_reginfo[] = { .opc0 = 3, .opc1 = 3, .crn = 14, .crm = 0, .opc2 = 0, .type = ARM_CP_CONST, .access = PL0_R /* no PL1_RW in linux-user */, .fieldoffset = offsetof(CPUARMState, cp15.c14_cntfrq), - .resetvalue = NANOSECONDS_PER_SECOND / GTIMER_SCALE, + .resetfn = gt_cntfrq_reset, }, { .name = "CNTVCT_EL0", .state = ARM_CP_STATE_AA64, .opc0 = 3, .opc1 = 3, .crn = 14, .crm = 0, .opc2 = 2, diff --git a/target/arm/internals.h b/target/arm/internals.h index dc93577..b66a1fa 100644 --- a/target/arm/internals.h +++ b/target/arm/internals.h @@ -52,9 +52,13 @@ static inline bool excp_is_internal(int excp) } /* Scale factor for generic timers, ie number of ns per tick. - * This gives a 62.5MHz timer. + * Calculated dynamically based on CNTFRQ with a default value + * that gives a 62.5MHZ timer. */ -#define GTIMER_SCALE 16 +#define GTIMER_SCALEsystem_clock_scale +#define GTIMER_SCALE_DEF16 + +uint64_t gt_get_countervalue(CPUARMState *); /* Bit definitions for the v7M CONTROL register */ FIELD(V7M_CONTROL, NPRIV, 0, 1) diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c index e0b8246..5d1c394 100644 --- a/target/arm/kvm64.c +++ b/target/arm/kvm64.c @@ -485,6 +485,7 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) set_feature(&features, ARM_FEATURE_NEON); set_feature(&features, ARM_FEATURE_AARCH64); set_feature(&features, ARM_FEATURE_PMU); +set_feature(&features, ARM_FEATURE_GENERIC_TIMER); ahcf->features = featu
[Qemu-devel] [RFC v2 13/24] riscv: tcg-target: Add the out load and store instructions
Signed-off-by: Alistair Francis Signed-off-by: Michael Clark Reviewed-by: Richard Henderson --- tcg/riscv/tcg-target.inc.c | 60 ++ 1 file changed, 60 insertions(+) diff --git a/tcg/riscv/tcg-target.inc.c b/tcg/riscv/tcg-target.inc.c index 4291a00962..cac4a4b615 100644 --- a/tcg/riscv/tcg-target.inc.c +++ b/tcg/riscv/tcg-target.inc.c @@ -546,6 +546,66 @@ static void tcg_out_ext32s(TCGContext *s, TCGReg ret, TCGReg arg) tcg_out_opc_imm(s, OPC_ADDIW, ret, arg, 0); } +static void tcg_out_ldst(TCGContext *s, RISCVInsn opc, TCGReg data, + TCGReg addr, intptr_t offset) +{ +#if TCG_TARGET_REG_BITS == 64 +int32_t imm12 = sextract64(offset, 0, 12); +#else +int32_t imm12 = sextract32(offset, 0, 12); +#endif +if (offset != imm12) { +tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_TMP2, offset - imm12); +if (addr != TCG_REG_ZERO) { +tcg_out_opc_reg(s, OPC_ADD, TCG_REG_TMP2, TCG_REG_TMP2, addr); +} +addr = TCG_REG_TMP2; +} +switch (opc) { +case OPC_SB: +case OPC_SH: +case OPC_SW: +case OPC_SD: +tcg_out_opc_store(s, opc, addr, data, imm12); +break; +case OPC_LB: +case OPC_LBU: +case OPC_LH: +case OPC_LHU: +case OPC_LW: +case OPC_LWU: +case OPC_LD: +tcg_out_opc_imm(s, opc, data, addr, imm12); +break; +default: +g_assert_not_reached(); +} +} + +static void tcg_out_ld(TCGContext *s, TCGType type, TCGReg arg, + TCGReg arg1, intptr_t arg2) +{ +bool is32bit = (TCG_TARGET_REG_BITS == 32 || type == TCG_TYPE_I32); +tcg_out_ldst(s, is32bit ? OPC_LW : OPC_LD, arg, arg1, arg2); +} + +static void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg, + TCGReg arg1, intptr_t arg2) +{ +bool is32bit = (TCG_TARGET_REG_BITS == 32 || type == TCG_TYPE_I32); +tcg_out_ldst(s, is32bit ? OPC_SW : OPC_SD, arg, arg1, arg2); +} + +static bool tcg_out_sti(TCGContext *s, TCGType type, TCGArg val, +TCGReg base, intptr_t ofs) +{ +if (val == 0) { +tcg_out_st(s, type, TCG_REG_ZERO, base, ofs); +return true; +} +return false; +} + void tb_target_set_jmp_target(uintptr_t tc_ptr, uintptr_t jmp_addr, uintptr_t addr) { -- 2.19.1
[Qemu-devel] [RFC v2 17/24] riscv: tcg-target: Add the out op decoder
Signed-off-by: Alistair Francis Signed-off-by: Michael Clark Reviewed-by: Richard Henderson --- tcg/riscv/tcg-target.inc.c | 472 + 1 file changed, 472 insertions(+) diff --git a/tcg/riscv/tcg-target.inc.c b/tcg/riscv/tcg-target.inc.c index e3b5f48848..d5fd7ca854 100644 --- a/tcg/riscv/tcg-target.inc.c +++ b/tcg/riscv/tcg-target.inc.c @@ -1145,6 +1145,478 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, bool is_64) #endif } +static tcg_insn_unit *tb_ret_addr; + +static void tcg_out_op(TCGContext *s, TCGOpcode opc, + const TCGArg *args, const int *const_args) +{ +TCGArg a0 = args[0]; +TCGArg a1 = args[1]; +TCGArg a2 = args[2]; +int c2 = const_args[2]; +const bool is32bit = TCG_TARGET_REG_BITS == 32; + +switch (opc) { +case INDEX_op_exit_tb: +/* Reuse the zeroing that exists for goto_ptr. */ +if (a0 == 0) { +tcg_out_goto_long(s, s->code_gen_epilogue); +} else { +tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_A0, a0); +tcg_out_goto_long(s, tb_ret_addr); +} +break; + +case INDEX_op_goto_tb: +if (s->tb_jmp_insn_offset) { +/* direct jump method */ +s->tb_jmp_insn_offset[a0] = tcg_current_code_size(s); +/* should align on 64-bit boundary for atomic patching */ +tcg_out_opc_upper(s, OPC_AUIPC, TCG_REG_TMP0, 0); +tcg_out_opc_imm(s, OPC_JALR, TCG_REG_ZERO, TCG_REG_TMP0, 0); +} else { +/* indirect jump method */ +tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP0, TCG_REG_ZERO, + (uintptr_t)(s->tb_jmp_target_addr + a0)); +tcg_out_opc_imm(s, OPC_JALR, TCG_REG_ZERO, TCG_REG_TMP0, 0); +} +s->tb_jmp_reset_offset[a0] = tcg_current_code_size(s); +break; + +case INDEX_op_goto_ptr: +tcg_out_opc_imm(s, OPC_JALR, TCG_REG_ZERO, a0, 0); +break; + +case INDEX_op_br: +tcg_out_reloc(s, s->code_ptr, R_RISCV_JAL, arg_label(a0), 0); +tcg_out_opc_jump(s, OPC_JAL, TCG_REG_ZERO, 0); +break; + +case INDEX_op_ld8u_i32: +case INDEX_op_ld8u_i64: +tcg_out_ldst(s, OPC_LBU, a0, a1, a2); +break; +case INDEX_op_ld8s_i32: +case INDEX_op_ld8s_i64: +tcg_out_ldst(s, OPC_LB, a0, a1, a2); +break; +case INDEX_op_ld16u_i32: +case INDEX_op_ld16u_i64: +tcg_out_ldst(s, OPC_LHU, a0, a1, a2); +break; +case INDEX_op_ld16s_i32: +case INDEX_op_ld16s_i64: +tcg_out_ldst(s, OPC_LH, a0, a1, a2); +break; +case INDEX_op_ld32u_i64: +tcg_out_ldst(s, OPC_LWU, a0, a1, a2); +break; +case INDEX_op_ld_i32: +case INDEX_op_ld32s_i64: +tcg_out_ldst(s, OPC_LW, a0, a1, a2); +break; +case INDEX_op_ld_i64: +tcg_out_ldst(s, OPC_LD, a0, a1, a2); +break; + +case INDEX_op_st8_i32: +case INDEX_op_st8_i64: +tcg_out_ldst(s, OPC_SB, a0, a1, a2); +break; +case INDEX_op_st16_i32: +case INDEX_op_st16_i64: +tcg_out_ldst(s, OPC_SH, a0, a1, a2); +break; +case INDEX_op_st_i32: +case INDEX_op_st32_i64: +tcg_out_ldst(s, OPC_SW, a0, a1, a2); +break; +case INDEX_op_st_i64: +tcg_out_ldst(s, OPC_SD, a0, a1, a2); +break; + +case INDEX_op_add_i32: +if (c2) { +tcg_out_opc_imm(s, is32bit ? OPC_ADDI : OPC_ADDIW, a0, a1, a2); +} else { +tcg_out_opc_reg(s, is32bit ? OPC_ADD : OPC_ADDW, a0, a1, a2); +} +break; +case INDEX_op_add_i64: +if (c2) { +tcg_out_opc_imm(s, OPC_ADDI, a0, a1, a2); +} else { +tcg_out_opc_reg(s, OPC_ADD, a0, a1, a2); +} +break; + +case INDEX_op_sub_i32: +if (c2) { +tcg_out_opc_imm(s, is32bit ? OPC_ADDI : OPC_ADDIW, a0, a1, -a2); +} else { +tcg_out_opc_reg(s, is32bit ? OPC_SUB : OPC_SUBW, a0, a1, a2); +} +break; +case INDEX_op_sub_i64: +if (c2) { +tcg_out_opc_imm(s, OPC_ADDI, a0, a1, -a2); +} else { +tcg_out_opc_reg(s, OPC_SUB, a0, a1, a2); +} +break; + +case INDEX_op_and_i32: +case INDEX_op_and_i64: +if (c2) { +tcg_out_opc_imm(s, OPC_ANDI, a0, a1, a2); +} else { +tcg_out_opc_reg(s, OPC_AND, a0, a1, a2); +} +break; + +case INDEX_op_or_i32: +case INDEX_op_or_i64: +if (c2) { +tcg_out_opc_imm(s, OPC_ORI, a0, a1, a2); +} else { +tcg_out_opc_reg(s, OPC_OR, a0, a1, a2); +} +break; + +case INDEX_op_xor_i32: +case INDEX_op_xor_i64: +if (c2) { +tcg_out_opc_imm(s, OPC_XORI, a0, a1, a2); +} else { +tcg_out_opc_reg(s, OPC_XOR, a0, a1, a2); +} +break; + +
[Qemu-devel] [RFC v2 14/24] riscv: tcg-target: Add branch and jump instructions
Signed-off-by: Alistair Francis Signed-off-by: Michael Clark --- tcg/riscv/tcg-target.inc.c | 141 + 1 file changed, 141 insertions(+) diff --git a/tcg/riscv/tcg-target.inc.c b/tcg/riscv/tcg-target.inc.c index cac4a4b615..97831bfb9d 100644 --- a/tcg/riscv/tcg-target.inc.c +++ b/tcg/riscv/tcg-target.inc.c @@ -606,6 +606,147 @@ static bool tcg_out_sti(TCGContext *s, TCGType type, TCGArg val, return false; } +static const struct { +RISCVInsn op; +bool swap; +} tcg_brcond_to_riscv[] = { +[TCG_COND_EQ] = { OPC_BEQ, false }, +[TCG_COND_NE] = { OPC_BNE, false }, +[TCG_COND_LT] = { OPC_BLT, false }, +[TCG_COND_GE] = { OPC_BGE, false }, +[TCG_COND_LE] = { OPC_BGE, true }, +[TCG_COND_GT] = { OPC_BLT, true }, +[TCG_COND_LTU] = { OPC_BLTU, false }, +[TCG_COND_GEU] = { OPC_BGEU, false }, +[TCG_COND_LEU] = { OPC_BGEU, true }, +[TCG_COND_GTU] = { OPC_BLTU, true } +}; + +static void tcg_out_brcond(TCGContext *s, TCGCond cond, TCGReg arg1, + TCGReg arg2, TCGLabel *l) +{ +RISCVInsn op = tcg_brcond_to_riscv[cond].op; +bool swap = tcg_brcond_to_riscv[cond].swap; + +tcg_out_opc_branch(s, op, swap ? arg2 : arg1, swap ? arg1 : arg2, 0); + +tcg_debug_assert(op != 0); + +if (l->has_value) { +reloc_sbimm12(s->code_ptr - 1, l->u.value_ptr); +} else { +tcg_out_reloc(s, s->code_ptr - 1, R_RISCV_BRANCH, l, 0); +} +} + +static void tcg_out_setcond(TCGContext *s, TCGCond cond, TCGReg ret, +TCGReg arg1, TCGReg arg2) +{ +switch (cond) { +case TCG_COND_EQ: +tcg_out_opc_reg(s, OPC_SUB, ret, arg1, arg2); +tcg_out_opc_imm(s, OPC_SLTIU, ret, ret, 1); +break; +case TCG_COND_NE: +tcg_out_opc_reg(s, OPC_SUB, ret, arg1, arg2); +tcg_out_opc_reg(s, OPC_SLTU, ret, TCG_REG_ZERO, ret); +break; +case TCG_COND_LT: +tcg_out_opc_reg(s, OPC_SLT, ret, arg1, arg2); +break; +case TCG_COND_GE: +tcg_out_opc_reg(s, OPC_SLT, ret, arg1, arg2); +tcg_out_opc_imm(s, OPC_XORI, ret, ret, 1); +break; +case TCG_COND_LE: +tcg_out_opc_reg(s, OPC_SLT, ret, arg2, arg1); +tcg_out_opc_imm(s, OPC_XORI, ret, ret, 1); +break; +case TCG_COND_GT: +tcg_out_opc_reg(s, OPC_SLT, ret, arg2, arg1); +break; +case TCG_COND_LTU: +tcg_out_opc_reg(s, OPC_SLTU, ret, arg1, arg2); +break; +case TCG_COND_GEU: +tcg_out_opc_reg(s, OPC_SLTU, ret, arg1, arg2); +tcg_out_opc_imm(s, OPC_XORI, ret, ret, 1); +break; +case TCG_COND_LEU: +tcg_out_opc_reg(s, OPC_SLTU, ret, arg2, arg1); +tcg_out_opc_imm(s, OPC_XORI, ret, ret, 1); +break; +case TCG_COND_GTU: +tcg_out_opc_reg(s, OPC_SLTU, ret, arg2, arg1); +break; +default: + g_assert_not_reached(); + break; + } +} + +static void tcg_out_brcond2(TCGContext *s, TCGCond cond, TCGReg al, TCGReg ah, +TCGReg bl, TCGReg bh, TCGLabel *l) +{ +/* todo */ +g_assert_not_reached(); +} + +static void tcg_out_setcond2(TCGContext *s, TCGCond cond, TCGReg ret, + TCGReg al, TCGReg ah, TCGReg bl, TCGReg bh) +{ +/* todo */ +g_assert_not_reached(); +} + +static inline void tcg_out_goto(TCGContext *s, tcg_insn_unit *target) +{ +ptrdiff_t offset = tcg_pcrel_diff(s, target); +tcg_debug_assert(offset == sextract64(offset, 0, 26)); +tcg_out_opc_jump(s, OPC_JAL, TCG_REG_ZERO, offset); +} + +static inline void tcg_out_goto_long(TCGContext *s, tcg_insn_unit *target) +{ +ptrdiff_t offset = tcg_pcrel_diff(s, target); + +if (offset == sextract64(offset, 0, 26)) { +tcg_out_opc_jump(s, OPC_JAL, TCG_REG_ZERO, offset); +} else { +tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_TMP0, (intptr_t)target); +tcg_out_opc_jump(s, OPC_JAL, TCG_REG_TMP0, 0); +} +} + +static void tcg_out_call_int(TCGContext *s, tcg_insn_unit *arg, bool tail) +{ +TCGReg link = tail ? TCG_REG_ZERO : TCG_REG_RA; +ptrdiff_t offset = tcg_pcrel_diff(s, arg); +if (offset == sextract64(offset, 1, 20) << 1) { +/* short jump: -2097150 to 2097152 */ +tcg_out_opc_jump(s, OPC_JAL, link, offset); +} else if (TCG_TARGET_REG_BITS == 32 || +offset == sextract64(offset, 1, 31) << 1) { +/* long jump: -2147483646 to 2147483648 */ +tcg_out_opc_upper(s, OPC_AUIPC, TCG_REG_TMP0, 0); +tcg_out_opc_imm(s, OPC_JALR, link, TCG_REG_TMP0, 0); +reloc_call(s->code_ptr - 2, arg); +} else if (TCG_TARGET_REG_BITS == 64) { +/* far jump: 64-bit */ +tcg_target_long imm = sextract64((tcg_target_long)arg, 0, 12); +tcg_target_long base = (tcg_target_long)arg - imm; +tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_TMP0, base); +tcg_out_opc_imm(s, OPC_JALR, link, TCG_REG_TM
[Qemu-devel] [RFC v2 10/24] riscv: tcg-target: Add the relocation functions
Signed-off-by: Alistair Francis Signed-off-by: Michael Clark --- tcg/riscv/tcg-target.inc.c | 51 ++ 1 file changed, 51 insertions(+) diff --git a/tcg/riscv/tcg-target.inc.c b/tcg/riscv/tcg-target.inc.c index ca7ae8939a..9c48679f11 100644 --- a/tcg/riscv/tcg-target.inc.c +++ b/tcg/riscv/tcg-target.inc.c @@ -383,6 +383,57 @@ static void tcg_out_opc_jump(TCGContext *s, RISCVInsn opc, tcg_out32(s, encode_uj(opc, rd, imm)); } +/* + * Relocations + */ + +static void reloc_sbimm12(tcg_insn_unit *code_ptr, tcg_insn_unit *target) +{ +intptr_t offset = (intptr_t)target - (intptr_t)code_ptr; +tcg_debug_assert(offset == sextract32(offset, 1, 12) << 1); + +code_ptr[0] |= encode_sbimm12(offset); +} + +static void reloc_jimm20(tcg_insn_unit *code_ptr, tcg_insn_unit *target) +{ +intptr_t offset = (intptr_t)target - (intptr_t)code_ptr; +tcg_debug_assert(offset == sextract32(offset, 1, 20) << 1); + +code_ptr[0] |= encode_ujimm12(offset); +} + +static void reloc_call(tcg_insn_unit *code_ptr, tcg_insn_unit *target) +{ +intptr_t offset = (intptr_t)target - (intptr_t)code_ptr; +tcg_debug_assert(offset == (int32_t)offset); + +int32_t hi20 = ((offset + 0x800) >> 12) << 12; +int32_t lo12 = offset - hi20; + +code_ptr[0] |= encode_uimm20(hi20); +code_ptr[1] |= encode_imm12(lo12); +} + +static void patch_reloc(tcg_insn_unit *code_ptr, int type, +intptr_t value, intptr_t addend) +{ +tcg_debug_assert(addend == 0); +switch (type) { +case R_RISCV_BRANCH: +reloc_sbimm12(code_ptr, (tcg_insn_unit *)value); +break; +case R_RISCV_JAL: +reloc_jimm20(code_ptr, (tcg_insn_unit *)value); +break; +case R_RISCV_CALL: +reloc_call(code_ptr, (tcg_insn_unit *)value); +break; +default: +tcg_abort(); +} +} + void tb_target_set_jmp_target(uintptr_t tc_ptr, uintptr_t jmp_addr, uintptr_t addr) { -- 2.19.1
[Qemu-devel] [RFC QEMU v2 0/2] arm/virt: Account for guest pause time
v1 -> v2: - Call the asm code only for kvm and always use the default value for TCG. This patch series address two Qemu issues: - improper system clock frequency initialization - lack of pause (virtsh suspend) time accounting A simple test to reproduce the problem executes one or more instances of the following command in the guest: dd if=/dev/zero of=/dev/null & and then pauses and resumes the guest after a certain delay: virsh suspend # pauses the guest sleep 120 virsh resume After the guest is resumed, there are soft lockup warning messages displayed on the console. A comparison with x86 shows that hwclock and date values diverge after the above pause and resume sequence for x86 but remain the same for Arm. Patch 1 intializes the system clock frequency in Qemu similar to the kernel. Patch 2 accumulates the total guest pause time in QEMU and adjusts the virtual offset counter accordingly before the guest is resumed. The patches have been tested on an Ampere system. With the patches the time behavior is the same as x86 and the soft lockup messages go away. Clock Frequency Initialization == Arm v8 provides the virtual counter (cntvct), virtual counter offset (cntvoff), and counter frequency (cntfrq) registers for guest time management. Linux Arm platform code initializes the system clock frequency from cntrfq_el0 register and sets the value into a statically created device tree (DT) node. It is not clear why the timer device node is created with TIMER_OF_DECLARE(). The DT passed from Qemu to the kernel does not contain a timer node. drivers/clocksource/arm_arch_timer.c: static inline u32 arch_timer_get_cntfrq(void) { return read_sysreg(cntfrq_el0); } rate = arch_timer_get_cntfrq(); arch_timer_of_configure_rate(rate, np); /* * For historical reasons, when probing with DT we use whichever (non-zero) * rate was probed first, and don't verify that others match. If the first node * probed has a clock-frequency property, this overrides the HW register. */ static void arch_timer_of_configure_rate(u32 rate, struct device_node *np) { ... if (of_property_read_u32(np, "clock-frequency", &arch_timer_rate)) { arch_timer_rate = rate; ... } TIMER_OF_DECLARE(armv7_arch_timer, "arm,armv7-timer", arch_timer_of_init); TIMER_OF_DECLARE(armv8_arch_timer, "arm,armv8-timer", arch_timer_of_init); Linux then initializes the clock frequency to 50MHZ. Qemu however hard codes the clock frequency to 62.5MHZ. target/arm/cpu.h: /* Scale factor for generic timers, ie number of ns per tick. * This gives a 62.5MHz timer. */ #define GTIMER_SCALE 16 The suggested fix is to follow the kernel's arch_timer_get_cntfrq() approach in order to set system_clock_scale to match the kernel's idea of clock-frequency, rather than using a hard-coded value. Ultimately, it seems that Qemu should construct the timer DT node and pass the actual clock frequency value to the kernel that way but that brings up an interface and backward compatibility considerations. Furthermore, the implications for ACPI method of probing is not clear. Pause Time Accounting = Linux registers two clock sources, a platform-independent jiffies clocksource and a Arm-specific arch_sys_counter; the read interface for the latter reads the virtual counter register: static struct clocksource clocksource_jiffies = { .name = "jiffies", .rating = 1, /* lowest valid rating*/ .read = jiffies_read, .mask = CLOCKSOURCE_MASK(32), .mult = TICK_NSEC << JIFFIES_SHIFT, /* details above */ .shift = JIFFIES_SHIFT, .max_cycles = 10, }; static struct clocksource clocksource_counter = { .name = "arch_sys_counter", .rating = 400, .read = arch_counter_read, .mask = CLOCKSOURCE_MASK(56), .flags = CLOCK_SOURCE_IS_CONTINUOUS, }; arch_counter_read() -> arch_timer_read_counter() -> arch_counter_get_cntvct() -> arch_timer_reg_read_stable(cntvct_el0) The virtual counter offset register is set from: kvm_timer_vcpu_load() -> set_cntvoff() The counter is zeroed from: kvm_timer_vcpu_put() -> set_cntvoff() /* * The kernel may decide to run userspace after calling vcpu_put, so * we reset cntvoff to 0 to ensure a consistent read between user * accesses to the virtual counter and kernel access to the physical * counter of non-VHE case. For VHE, the virtual counter uses a fixed * virtual offset of zero, so no need to zero CNTVOFF_EL2 register. */ if (!has_vhe()) set_cntvoff(0); The virtual counter offset is not modified anywhere however to account for pause time. The suggested fix is to add pause time accounting to Qemu. One potential issue is whether modifying the virtual counter offset breaks any assumptions, e.g., see the kvm_timer_vcp
[Qemu-devel] [RFC v2 12/24] riscv: tcg-target: Add the extract instructions
Signed-off-by: Alistair Francis Signed-off-by: Michael Clark Reviewed-by: Richard Henderson --- tcg/riscv/tcg-target.inc.c | 34 ++ 1 file changed, 34 insertions(+) diff --git a/tcg/riscv/tcg-target.inc.c b/tcg/riscv/tcg-target.inc.c index e5a07b146f..4291a00962 100644 --- a/tcg/riscv/tcg-target.inc.c +++ b/tcg/riscv/tcg-target.inc.c @@ -512,6 +512,40 @@ static void tcg_out_movi(TCGContext *s, TCGType type, TCGReg rd, } } +static void tcg_out_ext8u(TCGContext *s, TCGReg ret, TCGReg arg) +{ +tcg_out_opc_imm(s, OPC_ANDI, ret, arg, 0xff); +} + +static void tcg_out_ext16u(TCGContext *s, TCGReg ret, TCGReg arg) +{ +tcg_out_opc_imm(s, OPC_SLLI, ret, arg, TCG_TARGET_REG_BITS - 16); +tcg_out_opc_imm(s, OPC_SRLI, ret, ret, TCG_TARGET_REG_BITS - 16); +} + +static void tcg_out_ext32u(TCGContext *s, TCGReg ret, TCGReg arg) +{ +tcg_out_opc_imm(s, OPC_SLLI, ret, arg, 32); +tcg_out_opc_imm(s, OPC_SRLI, ret, ret, 32); +} + +static void tcg_out_ext8s(TCGContext *s, TCGReg ret, TCGReg arg) +{ +tcg_out_opc_imm(s, OPC_SLLI, ret, arg, TCG_TARGET_REG_BITS - 8); +tcg_out_opc_imm(s, OPC_SRAI, ret, ret, TCG_TARGET_REG_BITS - 8); +} + +static void tcg_out_ext16s(TCGContext *s, TCGReg ret, TCGReg arg) +{ +tcg_out_opc_imm(s, OPC_SLLI, ret, arg, TCG_TARGET_REG_BITS - 16); +tcg_out_opc_imm(s, OPC_SRAI, ret, ret, TCG_TARGET_REG_BITS - 16); +} + +static void tcg_out_ext32s(TCGContext *s, TCGReg ret, TCGReg arg) +{ +tcg_out_opc_imm(s, OPC_ADDIW, ret, arg, 0); +} + void tb_target_set_jmp_target(uintptr_t tc_ptr, uintptr_t jmp_addr, uintptr_t addr) { -- 2.19.1
Re: [Qemu-devel] [PATCH] scsi: Address spurious clang warning
On 11/27/18 2:02 PM, Eric Blake wrote: > On 11/27/18 12:49 PM, John Snow wrote: >> Some versions of Clang prior to 6.0 (and some builds of clang after, >> such as 6.0.1-2.fc28) fail to recognize { 0 } as a valid initializer >> for a struct with subobjects when -Wmissing-braces is enabled. >> >> https://bugs.llvm.org/show_bug.cgi?id=21689 and >> https://reviews.llvm.org/rL314499 suggests this should be fixed in 6.0, >> but it might not be the case for older versions or downstream versions. >> >> For now, follow the precedent of ebf2a499 and replace the standard { 0 } >> with the accepted { } to silence this warning and allow the build to >> work under clang 6.0.1-2.fc28, and builds prior to 6.0. >> >> Signed-off-by: John Snow >> > > Reviewed-by: Eric Blake > > I'm okay if this goes into -rc3 as a build-fix; I'm also okay if it > slips to 4.0. > >> --- >> >> What I am actually less clear on is why this appears to be a problem >> only now; since the introduction of { 0 } was in 2.11. It might be >> a regression only in the fedora distribution of Clang 6.0. > > Or even a redefinition of struct dm_ioctl in some header where you are > just now picking up a new struct layout that tickles the Clang issue in > relation to the previous layout (since it is possible to have two > structs that are ABI-compatible but where only one of the two has a > nested substruct). > >> +++ b/scsi/qemu-pr-helper.c >> @@ -236,7 +236,7 @@ static void dm_init(void) >> perror("Cannot open " CONTROL_PATH); >> exit(1); >> } >> - struct dm_ioctl dm = { 0 }; >> + struct dm_ioctl dm = { }; > > Random thought: would it be worth having "qemu/compiler.h" define a macro: > > #if ...broken clang > #define ZERO_INIT {} > #else > #define ZERO_INIT {0} > #endif > > and then rewrite all our '= { 0? }' initializers into '= ZERO_INIT'? Or > is that aesthetically too ugly? > Obscures perfectly legitimate C code without solving anything, IMO. As much code as can reflect "naked" C89/C99/GNU99, the better. --js
[Qemu-devel] [RFC v2 05/24] riscv: Add the tcg-target header file
Signed-off-by: Alistair Francis Signed-off-by: Michael Clark --- tcg/riscv/tcg-target.h | 173 + 1 file changed, 173 insertions(+) create mode 100644 tcg/riscv/tcg-target.h diff --git a/tcg/riscv/tcg-target.h b/tcg/riscv/tcg-target.h new file mode 100644 index 00..76ce2acfb5 --- /dev/null +++ b/tcg/riscv/tcg-target.h @@ -0,0 +1,173 @@ +/* + * Tiny Code Generator for QEMU + * + * Copyright (c) 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. + */ + +#ifndef RISCV_TCG_TARGET_H +#define RISCV_TCG_TARGET_H + +#if __riscv_xlen == 32 +# define TCG_TARGET_REG_BITS 32 +#elif __riscv_xlen == 64 +# define TCG_TARGET_REG_BITS 64 +#endif + +#define TCG_TARGET_INSN_UNIT_SIZE 4 +#define TCG_TARGET_TLB_DISPLACEMENT_BITS 20 +#define TCG_TARGET_NB_REGS 32 + +typedef enum { +TCG_REG_ZERO, +TCG_REG_RA, +TCG_REG_SP, +TCG_REG_GP, +TCG_REG_TP, +TCG_REG_T0, +TCG_REG_T1, +TCG_REG_T2, +TCG_REG_S0, +TCG_REG_S1, +TCG_REG_A0, +TCG_REG_A1, +TCG_REG_A2, +TCG_REG_A3, +TCG_REG_A4, +TCG_REG_A5, +TCG_REG_A6, +TCG_REG_A7, +TCG_REG_S2, +TCG_REG_S3, +TCG_REG_S4, +TCG_REG_S5, +TCG_REG_S6, +TCG_REG_S7, +TCG_REG_S8, +TCG_REG_S9, +TCG_REG_S10, +TCG_REG_S11, +TCG_REG_T3, +TCG_REG_T4, +TCG_REG_T5, +TCG_REG_T6, + +/* aliases */ +TCG_AREG0 = TCG_REG_S0, +TCG_GUEST_BASE_REG = TCG_REG_S1, +TCG_REG_TMP0 = TCG_REG_T6, +TCG_REG_TMP1 = TCG_REG_T5, +TCG_REG_TMP2 = TCG_REG_T4, +} TCGReg; + +/* used for function call generation */ +#define TCG_REG_CALL_STACK TCG_REG_SP +#define TCG_TARGET_STACK_ALIGN 16 +#define TCG_TARGET_CALL_ALIGN_ARGS 1 +#define TCG_TARGET_CALL_STACK_OFFSET0 + +/* optional instructions */ +#define TCG_TARGET_HAS_goto_ptr 1 +#define TCG_TARGET_HAS_movcond_i32 0 +#define TCG_TARGET_HAS_div_i32 1 +#define TCG_TARGET_HAS_rem_i32 1 +#define TCG_TARGET_HAS_div2_i32 0 +#define TCG_TARGET_HAS_rot_i32 0 +#define TCG_TARGET_HAS_deposit_i32 0 +#define TCG_TARGET_HAS_extract_i32 0 +#define TCG_TARGET_HAS_sextract_i32 0 +#define TCG_TARGET_HAS_add2_i32 1 +#define TCG_TARGET_HAS_sub2_i32 1 +#define TCG_TARGET_HAS_mulu2_i320 +#define TCG_TARGET_HAS_muls2_i320 +#define TCG_TARGET_HAS_muluh_i32(TCG_TARGET_REG_BITS == 32) +#define TCG_TARGET_HAS_mulsh_i32(TCG_TARGET_REG_BITS == 32) +#define TCG_TARGET_HAS_ext8s_i321 +#define TCG_TARGET_HAS_ext16s_i32 1 +#define TCG_TARGET_HAS_ext8u_i321 +#define TCG_TARGET_HAS_ext16u_i32 1 +#define TCG_TARGET_HAS_bswap16_i32 0 +#define TCG_TARGET_HAS_bswap32_i32 0 +#define TCG_TARGET_HAS_not_i32 1 +#define TCG_TARGET_HAS_neg_i32 1 +#define TCG_TARGET_HAS_andc_i32 0 +#define TCG_TARGET_HAS_orc_i32 0 +#define TCG_TARGET_HAS_eqv_i32 0 +#define TCG_TARGET_HAS_nand_i32 0 +#define TCG_TARGET_HAS_nor_i32 0 +#define TCG_TARGET_HAS_clz_i32 0 +#define TCG_TARGET_HAS_ctz_i32 0 +#define TCG_TARGET_HAS_ctpop_i320 +#define TCG_TARGET_HAS_direct_jump 0 +#define TCG_TARGET_HAS_brcond2 1 +#define TCG_TARGET_HAS_setcond2 1 + +#if TCG_TARGET_REG_BITS == 64 +#define TCG_TARGET_HAS_movcond_i64 0 +#define TCG_TARGET_HAS_div_i64 1 +#define TCG_TARGET_HAS_rem_i64 1 +#define TCG_TARGET_HAS_div2_i64 0 +#define TCG_TARGET_HAS_rot_i64 0 +#define TCG_TARGET_HAS_deposit_i64 0 +#define TCG_TARGET_HAS_extract_i64 0 +#define TCG_TARGET_HAS_sextract_i64 0 +#define TCG_TARGET_HAS_extrl_i64_i321 +#define TCG_TARGET_HAS_extrh_i64_i321 +#define TCG_TARGET_HAS_ext8s_i641 +#define TCG_TARGET_HAS_ext16s_i64 1 +#define TCG_TARGET_HAS_ext
[Qemu-devel] [RFC v2 08/24] riscv: tcg-target: Add the immediate encoders
Signed-off-by: Alistair Francis Signed-off-by: Michael Clark --- tcg/riscv/tcg-target.inc.c | 105 + 1 file changed, 105 insertions(+) diff --git a/tcg/riscv/tcg-target.inc.c b/tcg/riscv/tcg-target.inc.c index 5719af3c08..c659c4de39 100644 --- a/tcg/riscv/tcg-target.inc.c +++ b/tcg/riscv/tcg-target.inc.c @@ -252,3 +252,108 @@ typedef enum { OPC_FENCE_R_RW = 0x023f, OPC_FENCE_RW_W = 0x031f, } RISCVInsn; + +/* + * RISC-V immediate and instruction encoders (excludes 16-bit RVC) + */ + +/* Type-R */ + +static int32_t encode_r(RISCVInsn opc, TCGReg rd, TCGReg rs1, TCGReg rs2) +{ +return opc | (rd & 0x1f) << 7 | (rs1 & 0x1f) << 15 | (rs2 & 0x1f) << 20; +} + +/* Type-I */ + +static int32_t encode_imm12(uint32_t imm) +{ +return (imm & 0xfff) << 20; +} + +static int32_t encode_i(RISCVInsn opc, TCGReg rd, TCGReg rs1, uint32_t imm) +{ +return opc | (rd & 0x1f) << 7 | (rs1 & 0x1f) << 15 | encode_imm12(imm); +} + +/* Type-S */ + +static int32_t encode_simm12(uint32_t imm) +{ +int32_t ret = 0; + +ret |= (imm & 0xFE0) << 20; +ret |= (imm & 0x1F) << 7; + +return ret; +} + +static int32_t encode_s(RISCVInsn opc, TCGReg rs1, TCGReg rs2, uint32_t imm) +{ +return opc | (rs1 & 0x1f) << 15 | (rs2 & 0x1f) << 20 | encode_simm12(imm); +} + +/* Type-SB */ + +static int32_t encode_sbimm12(uint32_t imm) +{ +int32_t ret = 0; + +ret |= (imm & 0x1000) << 19; +ret |= (imm & 0x7e0) << 20; +ret |= (imm & 0x1e) << 7; +ret |= (imm & 0x800) >> 4; + +return ret; +} + +static int32_t encode_sb(RISCVInsn opc, TCGReg rs1, TCGReg rs2, uint32_t imm) +{ +return opc | (rs1 & 0x1f) << 15 | (rs2 & 0x1f) << 20 | encode_sbimm12(imm); +} + +/* Type-U */ + +static int32_t encode_uimm20(uint32_t imm) +{ +return imm & 0xf000; +} + +static int32_t encode_u(RISCVInsn opc, TCGReg rd, uint32_t imm) +{ +return opc | (rd & 0x1f) << 7 | encode_uimm20(imm); +} + +/* Type-UJ */ + +static int32_t encode_ujimm12(uint32_t imm) +{ +int32_t ret = 0; + +ret |= (imm & 0x10) << 11; +ret |= (imm & 0xffe) << 20; +ret |= (imm & 0x800) << 9; +ret |= imm & 0xff000; + +return ret; +} + +static int32_t encode_uj(RISCVInsn opc, TCGReg rd, uint32_t imm) +{ +return opc | (rd & 0x1f) << 7 | encode_ujimm12(imm); +} + +void tb_target_set_jmp_target(uintptr_t tc_ptr, uintptr_t jmp_addr, + uintptr_t addr) +{ +intptr_t offset = (intptr_t)addr - (intptr_t)jmp_addr; +tcg_debug_assert(offset == (int32_t)offset); + +int32_t hi20 = ((offset + 0x800) >> 12) << 12; +int32_t lo12 = offset - hi20; + +atomic_set((uint32_t *)jmp_addr, encode_uimm20(hi20)); +atomic_set((uint32_t *)jmp_addr + 4, encode_imm12(lo12)); + +flush_icache_range(jmp_addr, jmp_addr + 8); +} -- 2.19.1
[Qemu-devel] [RFC v2 06/24] riscv: Add the tcg target registers
Signed-off-by: Alistair Francis Signed-off-by: Michael Clark Reviewed-by: Richard Henderson --- tcg/riscv/tcg-target.inc.c | 116 + 1 file changed, 116 insertions(+) create mode 100644 tcg/riscv/tcg-target.inc.c diff --git a/tcg/riscv/tcg-target.inc.c b/tcg/riscv/tcg-target.inc.c new file mode 100644 index 00..a4a1579440 --- /dev/null +++ b/tcg/riscv/tcg-target.inc.c @@ -0,0 +1,116 @@ +/* + * Tiny Code Generator for QEMU + * + * Copyright (c) 2018 SiFive, Inc + * Copyright (c) 2008-2009 Arnaud Patard + * Copyright (c) 2009 Aurelien Jarno + * Copyright (c) 2008 Fabrice Bellard + * + * Based on i386/tcg-target.c and mips/tcg-target.c + * + * 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. + */ + +#ifdef CONFIG_DEBUG_TCG +static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = { +"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" +}; +#endif + +static const int tcg_target_reg_alloc_order[] = { +/* Call saved registers */ +/* TCG_REG_S0 reservered for TCG_AREG0 */ +TCG_REG_S1, +TCG_REG_S2, +TCG_REG_S3, +TCG_REG_S4, +TCG_REG_S5, +TCG_REG_S6, +TCG_REG_S7, +TCG_REG_S8, +TCG_REG_S9, +TCG_REG_S10, +TCG_REG_S11, + +/* Call clobbered registers */ +TCG_REG_T0, +TCG_REG_T1, +TCG_REG_T2, +TCG_REG_T3, +TCG_REG_T4, +TCG_REG_T5, +TCG_REG_T6, + +/* Argument registers */ +TCG_REG_A0, +TCG_REG_A1, +TCG_REG_A2, +TCG_REG_A3, +TCG_REG_A4, +TCG_REG_A5, +TCG_REG_A6, +TCG_REG_A7, +}; + +static const int tcg_target_call_iarg_regs[] = { +TCG_REG_A0, +TCG_REG_A1, +TCG_REG_A2, +TCG_REG_A3, +TCG_REG_A4, +TCG_REG_A5, +TCG_REG_A6, +TCG_REG_A7, +}; + +static const int tcg_target_call_oarg_regs[] = { +TCG_REG_A0, +TCG_REG_A1, +}; -- 2.19.1
[Qemu-devel] [RFC v2 07/24] riscv: tcg-target: Add support for the constraints
Signed-off-by: Alistair Francis Signed-off-by: Michael Clark --- tcg/riscv/tcg-target.inc.c | 138 + 1 file changed, 138 insertions(+) diff --git a/tcg/riscv/tcg-target.inc.c b/tcg/riscv/tcg-target.inc.c index a4a1579440..5719af3c08 100644 --- a/tcg/riscv/tcg-target.inc.c +++ b/tcg/riscv/tcg-target.inc.c @@ -114,3 +114,141 @@ static const int tcg_target_call_oarg_regs[] = { TCG_REG_A0, TCG_REG_A1, }; + +#define TCG_CT_CONST_ZERO 0x100 +#define TCG_CT_CONST_S12 0x200 +#define TCG_CT_CONST_N12 0x400 + +/* parse target specific constraints */ +static const char *target_parse_constraint(TCGArgConstraint *ct, + const char *ct_str, TCGType type) +{ +switch (*ct_str++) { +case 'r': +ct->ct |= TCG_CT_REG; +ct->u.regs = 0x; +break; +case 'L': +/* qemu_ld/qemu_st constraint */ +ct->ct |= TCG_CT_REG; +ct->u.regs = 0x; +/* qemu_ld/qemu_st uses TCG_REG_TMP0 */ +#if defined(CONFIG_SOFTMMU) +tcg_regset_reset_reg(ct->u.regs, tcg_target_call_iarg_regs[0]); +tcg_regset_reset_reg(ct->u.regs, tcg_target_call_iarg_regs[1]); +tcg_regset_reset_reg(ct->u.regs, tcg_target_call_iarg_regs[2]); +tcg_regset_reset_reg(ct->u.regs, tcg_target_call_iarg_regs[3]); +tcg_regset_reset_reg(ct->u.regs, tcg_target_call_iarg_regs[4]); +#endif +break; +case 'I': +ct->ct |= TCG_CT_CONST_S12; +break; +case 'N': +ct->ct |= TCG_CT_CONST_N12; +break; +case 'Z': +/* we can use a zero immediate as a zero register argument. */ +ct->ct |= TCG_CT_CONST_ZERO; +break; +default: +return NULL; +} +return ct_str; +} + +/* test if a constant matches the constraint */ +static int tcg_target_const_match(tcg_target_long val, TCGType type, + const TCGArgConstraint *arg_ct) +{ +int ct = arg_ct->ct; +if (ct & TCG_CT_CONST) { +return 1; +} +if ((ct & TCG_CT_CONST_ZERO) && val == 0) { +return 1; +} +if ((ct & TCG_CT_CONST_S12) && val == sextract32(val, 0, 12)) { +return 1; +} +if ((ct & TCG_CT_CONST_N12) && val == sextract32(-val, 0, 12)) { +return 1; +} +return 0; +} + +/* + * RISC-V Base ISA opcodes (IM) + */ + +typedef enum { +OPC_ADD = 0x33, +OPC_ADDI = 0x13, +OPC_ADDIW = 0x1b, +OPC_ADDW = 0x3b, +OPC_AND = 0x7033, +OPC_ANDI = 0x7013, +OPC_AUIPC = 0x17, +OPC_BEQ = 0x63, +OPC_BGE = 0x5063, +OPC_BGEU = 0x7063, +OPC_BLT = 0x4063, +OPC_BLTU = 0x6063, +OPC_BNE = 0x1063, +OPC_DIV = 0x2004033, +OPC_DIVU = 0x2005033, +OPC_DIVUW = 0x200503b, +OPC_DIVW = 0x200403b, +OPC_JAL = 0x6f, +OPC_JALR = 0x67, +OPC_LB = 0x3, +OPC_LBU = 0x4003, +OPC_LD = 0x3003, +OPC_LH = 0x1003, +OPC_LHU = 0x5003, +OPC_LUI = 0x37, +OPC_LW = 0x2003, +OPC_LWU = 0x6003, +OPC_MUL = 0x233, +OPC_MULH = 0x2001033, +OPC_MULHSU = 0x2002033, +OPC_MULHU = 0x2003033, +OPC_MULW = 0x23b, +OPC_OR = 0x6033, +OPC_ORI = 0x6013, +OPC_REM = 0x2006033, +OPC_REMU = 0x2007033, +OPC_REMUW = 0x200703b, +OPC_REMW = 0x200603b, +OPC_SB = 0x23, +OPC_SD = 0x3023, +OPC_SH = 0x1023, +OPC_SLL = 0x1033, +OPC_SLLI = 0x1013, +OPC_SLLIW = 0x101b, +OPC_SLLW = 0x103b, +OPC_SLT = 0x2033, +OPC_SLTI = 0x2013, +OPC_SLTIU = 0x3013, +OPC_SLTU = 0x3033, +OPC_SRA = 0x40005033, +OPC_SRAI = 0x40005013, +OPC_SRAIW = 0x4000501b, +OPC_SRAW = 0x4000503b, +OPC_SRL = 0x5033, +OPC_SRLI = 0x5013, +OPC_SRLIW = 0x501b, +OPC_SRLW = 0x503b, +OPC_SUB = 0x4033, +OPC_SUBW = 0x403b, +OPC_SW = 0x2023, +OPC_XOR = 0x4033, +OPC_XORI = 0x4013, +OPC_FENCE_RW_RW = 0x033f, +OPC_FENCE_R_R = 0x022f, +OPC_FENCE_W_R = 0x012f, +OPC_FENCE_R_W = 0x021f, +OPC_FENCE_W_W = 0x011f, +OPC_FENCE_R_RW = 0x023f, +OPC_FENCE_RW_W = 0x031f, +} RISCVInsn; -- 2.19.1
[Qemu-devel] [RFC v2 04/24] exec: Add RISC-V GCC poison macro
Signed-off-by: Alistair Francis Signed-off-by: Michael Clark Reviewed-by: Richard Henderson --- include/exec/poison.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/exec/poison.h b/include/exec/poison.h index 32d53789f8..ecdc83c147 100644 --- a/include/exec/poison.h +++ b/include/exec/poison.h @@ -79,6 +79,7 @@ #pragma GCC poison CONFIG_MOXIE_DIS #pragma GCC poison CONFIG_NIOS2_DIS #pragma GCC poison CONFIG_PPC_DIS +#pragma GCC poison CONFIG_RISCV_DIS #pragma GCC poison CONFIG_S390_DIS #pragma GCC poison CONFIG_SH4_DIS #pragma GCC poison CONFIG_SPARC_DIS -- 2.19.1