[PATCH v7 5/8] s390x/pci: enable adapter event notification for interpreted devices

2022-06-06 Thread Matthew Rosato
Use the associated kvm ioctl operation to enable adapter event notification
and forwarding for devices when requested.  This feature will be set up
with or without firmware assist based upon the 'forwarding_assist' setting.

Signed-off-by: Matthew Rosato 
---
 hw/s390x/s390-pci-bus.c | 20 ++---
 hw/s390x/s390-pci-inst.c| 40 +++--
 hw/s390x/s390-pci-kvm.c | 30 +
 include/hw/s390x/s390-pci-bus.h |  1 +
 include/hw/s390x/s390-pci-kvm.h | 14 
 5 files changed, 100 insertions(+), 5 deletions(-)

diff --git a/hw/s390x/s390-pci-bus.c b/hw/s390x/s390-pci-bus.c
index 816d17af99..e66a0dfbef 100644
--- a/hw/s390x/s390-pci-bus.c
+++ b/hw/s390x/s390-pci-bus.c
@@ -190,7 +190,10 @@ void s390_pci_sclp_deconfigure(SCCB *sccb)
 rc = SCLP_RC_NO_ACTION_REQUIRED;
 break;
 default:
-if (pbdev->summary_ind) {
+if (pbdev->interp && (pbdev->fh & FH_MASK_ENABLE)) {
+/* Interpreted devices were using interrupt forwarding */
+s390_pci_kvm_aif_disable(pbdev);
+} else if (pbdev->summary_ind) {
 pci_dereg_irqs(pbdev);
 }
 if (pbdev->iommu->enabled) {
@@ -1082,6 +1085,7 @@ static void s390_pcihost_plug(HotplugHandler 
*hotplug_dev, DeviceState *dev,
 } else {
 DPRINTF("zPCI interpretation facilities missing.\n");
 pbdev->interp = false;
+pbdev->forwarding_assist = false;
 }
 }
 pbdev->iommu->dma_limit = s390_pci_start_dma_count(s, pbdev);
@@ -1090,11 +1094,13 @@ static void s390_pcihost_plug(HotplugHandler 
*hotplug_dev, DeviceState *dev,
 if (!pbdev->interp) {
 /* Do vfio passthrough but intercept for I/O */
 pbdev->fh |= FH_SHM_VFIO;
+pbdev->forwarding_assist = false;
 }
 } else {
 pbdev->fh |= FH_SHM_EMUL;
 /* Always intercept emulated devices */
 pbdev->interp = false;
+pbdev->forwarding_assist = false;
 }
 
 if (s390_pci_msix_init(pbdev) && !pbdev->interp) {
@@ -1244,7 +1250,10 @@ static void s390_pcihost_reset(DeviceState *dev)
 /* Process all pending unplug requests */
 QTAILQ_FOREACH_SAFE(pbdev, &s->zpci_devs, link, next) {
 if (pbdev->unplug_requested) {
-if (pbdev->summary_ind) {
+if (pbdev->interp && (pbdev->fh & FH_MASK_ENABLE)) {
+/* Interpreted devices were using interrupt forwarding */
+s390_pci_kvm_aif_disable(pbdev);
+} else if (pbdev->summary_ind) {
 pci_dereg_irqs(pbdev);
 }
 if (pbdev->iommu->enabled) {
@@ -1382,7 +1391,10 @@ static void s390_pci_device_reset(DeviceState *dev)
 break;
 }
 
-if (pbdev->summary_ind) {
+if (pbdev->interp && (pbdev->fh & FH_MASK_ENABLE)) {
+/* Interpreted devices were using interrupt forwarding */
+s390_pci_kvm_aif_disable(pbdev);
+} else if (pbdev->summary_ind) {
 pci_dereg_irqs(pbdev);
 }
 if (pbdev->iommu->enabled) {
@@ -1428,6 +1440,8 @@ static Property s390_pci_device_properties[] = {
 DEFINE_PROP_S390_PCI_FID("fid", S390PCIBusDevice, fid),
 DEFINE_PROP_STRING("target", S390PCIBusDevice, target),
 DEFINE_PROP_BOOL("interpret", S390PCIBusDevice, interp, true),
+DEFINE_PROP_BOOL("forwarding_assist", S390PCIBusDevice, forwarding_assist,
+ true),
 DEFINE_PROP_END_OF_LIST(),
 };
 
diff --git a/hw/s390x/s390-pci-inst.c b/hw/s390x/s390-pci-inst.c
index 651ec38635..20a9bcc7af 100644
--- a/hw/s390x/s390-pci-inst.c
+++ b/hw/s390x/s390-pci-inst.c
@@ -1066,6 +1066,32 @@ static void fmb_update(void *opaque)
 timer_mod(pbdev->fmb_timer, t + pbdev->pci_group->zpci_group.mui);
 }
 
+static int mpcifc_reg_int_interp(S390PCIBusDevice *pbdev, ZpciFib *fib)
+{
+int rc;
+
+rc = s390_pci_kvm_aif_enable(pbdev, fib, pbdev->forwarding_assist);
+if (rc) {
+DPRINTF("Failed to enable interrupt forwarding\n");
+return rc;
+}
+
+return 0;
+}
+
+static int mpcifc_dereg_int_interp(S390PCIBusDevice *pbdev, ZpciFib *fib)
+{
+int rc;
+
+rc = s390_pci_kvm_aif_disable(pbdev);
+if (rc) {
+DPRINTF("Failed to disable interrupt forwarding\n");
+return rc;
+}
+
+return 0;
+}
+
 int mpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba, uint8_t ar,
 uintptr_t ra)
 {
@@ -1120,7 +1146,12 @@ int mpcifc_service_call(S390CPU *cpu, uint8_t r1, 
uint64_t fiba, uint8_t ar,
 
 switch (oc) {
 case ZPCI_MOD_FC_REG_INT:
-if (pbdev->summary_ind) {
+if (pbdev->interp) {
+if (mpcifc_reg_int_interp(pbdev, &fib)) {
+cc = ZPCI_PCI_LS_ERR;
+s390_set_status_code(env, r1, ZPCI_MOD_ST_SEQUENCE);
+}
+  

[PATCH v7 6/8] s390x/pci: let intercept devices have separate PCI groups

2022-06-06 Thread Matthew Rosato
Let's use the reserved pool of simulated PCI groups to allow intercept
devices to have separate groups from interpreted devices as some group
values may be different. If we run out of simulated PCI groups, subsequent
intercept devices just get the default group.
Furthermore, if we encounter any PCI groups from hostdevs that are marked
as simulated, let's just assign them to the default group to avoid
conflicts between host simulated groups and our own simulated groups.

Reviewed-by: Pierre Morel 
Signed-off-by: Matthew Rosato 
---
 hw/s390x/s390-pci-bus.c | 19 ++--
 hw/s390x/s390-pci-vfio.c| 40 ++---
 include/hw/s390x/s390-pci-bus.h |  6 -
 3 files changed, 59 insertions(+), 6 deletions(-)

diff --git a/hw/s390x/s390-pci-bus.c b/hw/s390x/s390-pci-bus.c
index e66a0dfbef..5342f7899f 100644
--- a/hw/s390x/s390-pci-bus.c
+++ b/hw/s390x/s390-pci-bus.c
@@ -748,13 +748,14 @@ static void s390_pci_iommu_free(S390pciState *s, PCIBus 
*bus, int32_t devfn)
 object_unref(OBJECT(iommu));
 }
 
-S390PCIGroup *s390_group_create(int id)
+S390PCIGroup *s390_group_create(int id, int host_id)
 {
 S390PCIGroup *group;
 S390pciState *s = s390_get_phb();
 
 group = g_new0(S390PCIGroup, 1);
 group->id = id;
+group->host_id = host_id;
 QTAILQ_INSERT_TAIL(&s->zpci_groups, group, link);
 return group;
 }
@@ -772,12 +773,25 @@ S390PCIGroup *s390_group_find(int id)
 return NULL;
 }
 
+S390PCIGroup *s390_group_find_host_sim(int host_id)
+{
+S390PCIGroup *group;
+S390pciState *s = s390_get_phb();
+
+QTAILQ_FOREACH(group, &s->zpci_groups, link) {
+if (group->id >= ZPCI_SIM_GRP_START && group->host_id == host_id) {
+return group;
+}
+}
+return NULL;
+}
+
 static void s390_pci_init_default_group(void)
 {
 S390PCIGroup *group;
 ClpRspQueryPciGrp *resgrp;
 
-group = s390_group_create(ZPCI_DEFAULT_FN_GRP);
+group = s390_group_create(ZPCI_DEFAULT_FN_GRP, ZPCI_DEFAULT_FN_GRP);
 resgrp = &group->zpci_group;
 resgrp->fr = 1;
 resgrp->dasm = 0;
@@ -825,6 +839,7 @@ static void s390_pcihost_realize(DeviceState *dev, Error 
**errp)
NULL, g_free);
 s->zpci_table = g_hash_table_new_full(g_int_hash, g_int_equal, NULL, NULL);
 s->bus_no = 0;
+s->next_sim_grp = ZPCI_SIM_GRP_START;
 QTAILQ_INIT(&s->pending_sei);
 QTAILQ_INIT(&s->zpci_devs);
 QTAILQ_INIT(&s->zpci_dma_limit);
diff --git a/hw/s390x/s390-pci-vfio.c b/hw/s390x/s390-pci-vfio.c
index 4bf0a7e22d..985980f021 100644
--- a/hw/s390x/s390-pci-vfio.c
+++ b/hw/s390x/s390-pci-vfio.c
@@ -150,13 +150,18 @@ static void s390_pci_read_group(S390PCIBusDevice *pbdev,
 {
 struct vfio_info_cap_header *hdr;
 struct vfio_device_info_cap_zpci_group *cap;
+S390pciState *s = s390_get_phb();
 ClpRspQueryPciGrp *resgrp;
 VFIOPCIDevice *vpci =  container_of(pbdev->pdev, VFIOPCIDevice, pdev);
+uint8_t start_gid = pbdev->zpci_fn.pfgid;
 
 hdr = vfio_get_device_info_cap(info, VFIO_DEVICE_INFO_CAP_ZPCI_GROUP);
 
-/* If capability not provided, just use the default group */
-if (hdr == NULL) {
+/*
+ * If capability not provided or the underlying hostdev is simulated, just
+ * use the default group.
+ */
+if (hdr == NULL || pbdev->zpci_fn.pfgid >= ZPCI_SIM_GRP_START) {
 trace_s390_pci_clp_cap(vpci->vbasedev.name,
VFIO_DEVICE_INFO_CAP_ZPCI_GROUP);
 pbdev->zpci_fn.pfgid = ZPCI_DEFAULT_FN_GRP;
@@ -165,11 +170,40 @@ static void s390_pci_read_group(S390PCIBusDevice *pbdev,
 }
 cap = (void *) hdr;
 
+/*
+ * For an intercept device, let's use an existing simulated group if one
+ * one was already created for other intercept devices in this group.
+ * If not, create a new simulated group if any are still available.
+ * If all else fails, just fall back on the default group.
+ */
+if (!pbdev->interp) {
+pbdev->pci_group = s390_group_find_host_sim(pbdev->zpci_fn.pfgid);
+if (pbdev->pci_group) {
+/* Use existing simulated group */
+pbdev->zpci_fn.pfgid = pbdev->pci_group->id;
+return;
+} else {
+if (s->next_sim_grp == ZPCI_DEFAULT_FN_GRP) {
+/* All out of simulated groups, use default */
+trace_s390_pci_clp_cap(vpci->vbasedev.name,
+   VFIO_DEVICE_INFO_CAP_ZPCI_GROUP);
+pbdev->zpci_fn.pfgid = ZPCI_DEFAULT_FN_GRP;
+pbdev->pci_group = s390_group_find(ZPCI_DEFAULT_FN_GRP);
+return;
+} else {
+/* We can assign a new simulated group */
+pbdev->zpci_fn.pfgid = s->next_sim_grp;
+s->next_sim_grp++;
+/* Fall through to create the new sim group using CLP info */
+}
+}
+}
+
 /* See if the PC

[PATCH v7 2/8] s390x/pci: add routine to get host function handle from CLP info

2022-06-06 Thread Matthew Rosato
In order to interface with the underlying host zPCI device, we need
to know it's function handle.  Add a routine to grab this from the
vfio CLP capabilities chain.

Reviewed-by: Pierre Morel 
Signed-off-by: Matthew Rosato 
---
 hw/s390x/s390-pci-vfio.c | 83 ++--
 include/hw/s390x/s390-pci-vfio.h |  5 ++
 2 files changed, 72 insertions(+), 16 deletions(-)

diff --git a/hw/s390x/s390-pci-vfio.c b/hw/s390x/s390-pci-vfio.c
index 6f80a47e29..4bf0a7e22d 100644
--- a/hw/s390x/s390-pci-vfio.c
+++ b/hw/s390x/s390-pci-vfio.c
@@ -124,6 +124,27 @@ static void s390_pci_read_base(S390PCIBusDevice *pbdev,
 pbdev->zpci_fn.pft = 0;
 }
 
+static bool get_host_fh(S390PCIBusDevice *pbdev, struct vfio_device_info *info,
+uint32_t *fh)
+{
+struct vfio_info_cap_header *hdr;
+struct vfio_device_info_cap_zpci_base *cap;
+VFIOPCIDevice *vpci =  container_of(pbdev->pdev, VFIOPCIDevice, pdev);
+
+hdr = vfio_get_device_info_cap(info, VFIO_DEVICE_INFO_CAP_ZPCI_BASE);
+
+/* Can only get the host fh with version 2 or greater */
+if (hdr == NULL || hdr->version < 2) {
+trace_s390_pci_clp_cap(vpci->vbasedev.name,
+   VFIO_DEVICE_INFO_CAP_ZPCI_BASE);
+return false;
+}
+cap = (void *) hdr;
+
+*fh = cap->fh;
+return true;
+}
+
 static void s390_pci_read_group(S390PCIBusDevice *pbdev,
 struct vfio_device_info *info)
 {
@@ -217,25 +238,13 @@ static void s390_pci_read_pfip(S390PCIBusDevice *pbdev,
 memcpy(pbdev->zpci_fn.pfip, cap->pfip, CLP_PFIP_NR_SEGMENTS);
 }
 
-/*
- * This function will issue the VFIO_DEVICE_GET_INFO ioctl and look for
- * capabilities that contain information about CLP features provided by the
- * underlying host.
- * On entry, defaults have already been placed into the guest CLP response
- * buffers.  On exit, defaults will have been overwritten for any CLP features
- * found in the capability chain; defaults will remain for any CLP features not
- * found in the chain.
- */
-void s390_pci_get_clp_info(S390PCIBusDevice *pbdev)
+static struct vfio_device_info *get_device_info(S390PCIBusDevice *pbdev,
+uint32_t argsz)
 {
-g_autofree struct vfio_device_info *info = NULL;
+struct vfio_device_info *info = g_malloc0(argsz);
 VFIOPCIDevice *vfio_pci;
-uint32_t argsz;
 int fd;
 
-argsz = sizeof(*info);
-info = g_malloc0(argsz);
-
 vfio_pci = container_of(pbdev->pdev, VFIOPCIDevice, pdev);
 fd = vfio_pci->vbasedev.fd;
 
@@ -250,7 +259,8 @@ retry:
 
 if (ioctl(fd, VFIO_DEVICE_GET_INFO, info)) {
 trace_s390_pci_clp_dev_info(vfio_pci->vbasedev.name);
-return;
+free(info);
+return NULL;
 }
 
 if (info->argsz > argsz) {
@@ -259,6 +269,47 @@ retry:
 goto retry;
 }
 
+return info;
+}
+
+/*
+ * Get the host function handle from the vfio CLP capabilities chain.  Returns
+ * true if a fh value was placed into the provided buffer.  Returns false
+ * if a fh could not be obtained (ioctl failed or capabilitiy version does
+ * not include the fh)
+ */
+bool s390_pci_get_host_fh(S390PCIBusDevice *pbdev, uint32_t *fh)
+{
+g_autofree struct vfio_device_info *info = NULL;
+
+assert(fh);
+
+info = get_device_info(pbdev, sizeof(*info));
+if (!info) {
+return false;
+}
+
+return get_host_fh(pbdev, info, fh);
+}
+
+/*
+ * This function will issue the VFIO_DEVICE_GET_INFO ioctl and look for
+ * capabilities that contain information about CLP features provided by the
+ * underlying host.
+ * On entry, defaults have already been placed into the guest CLP response
+ * buffers.  On exit, defaults will have been overwritten for any CLP features
+ * found in the capability chain; defaults will remain for any CLP features not
+ * found in the chain.
+ */
+void s390_pci_get_clp_info(S390PCIBusDevice *pbdev)
+{
+g_autofree struct vfio_device_info *info = NULL;
+
+info = get_device_info(pbdev, sizeof(*info));
+if (!info) {
+return;
+}
+
 /*
  * Find the CLP features provided and fill in the guest CLP responses.
  * Always call s390_pci_read_base first as information from this could
diff --git a/include/hw/s390x/s390-pci-vfio.h b/include/hw/s390x/s390-pci-vfio.h
index ff708aef50..ae1b126ff7 100644
--- a/include/hw/s390x/s390-pci-vfio.h
+++ b/include/hw/s390x/s390-pci-vfio.h
@@ -20,6 +20,7 @@ bool s390_pci_update_dma_avail(int fd, unsigned int *avail);
 S390PCIDMACount *s390_pci_start_dma_count(S390pciState *s,
   S390PCIBusDevice *pbdev);
 void s390_pci_end_dma_count(S390pciState *s, S390PCIDMACount *cnt);
+bool s390_pci_get_host_fh(S390PCIBusDevice *pbdev, uint32_t *fh);
 void s390_pci_get_clp_info(S390PCIBusDevice *pbdev);
 #else
 static inline bool s390_pci_update_dma_avail(int fd, unsigned int *avail)
@@ -33,6 +34,10 @@ static inline 

[PATCH v7 3/8] s390x/pci: enable for load/store intepretation

2022-06-06 Thread Matthew Rosato
If the ZPCI_OP ioctl reports that is is available and usable, then the
underlying KVM host will enable load/store intepretation for any guest
device without a SHM bit in the guest function handle.  For a device that
will be using interpretation support, ensure the guest function handle
matches the host function handle; this value is re-checked every time the
guest issues a SET PCI FN to enable the guest device as it is the only
opportunity to reflect function handle changes.

By default, unless interpret=off is specified, interpretation support will
always be assumed and exploited if the necessary ioctl and features are
available on the host kernel.  When these are unavailable, we will silently
revert to the interception model; this allows existing guest configurations
to work unmodified on hosts with and without zPCI interpretation support,
allowing QEMU to choose the best support model available.

Signed-off-by: Matthew Rosato 
---
 hw/s390x/meson.build|  1 +
 hw/s390x/s390-pci-bus.c | 66 -
 hw/s390x/s390-pci-inst.c| 16 
 hw/s390x/s390-pci-kvm.c | 22 +++
 include/hw/s390x/s390-pci-bus.h |  1 +
 include/hw/s390x/s390-pci-kvm.h | 24 
 target/s390x/kvm/kvm.c  |  7 
 target/s390x/kvm/kvm_s390x.h|  1 +
 8 files changed, 137 insertions(+), 1 deletion(-)
 create mode 100644 hw/s390x/s390-pci-kvm.c
 create mode 100644 include/hw/s390x/s390-pci-kvm.h

diff --git a/hw/s390x/meson.build b/hw/s390x/meson.build
index feefe0717e..f291016fee 100644
--- a/hw/s390x/meson.build
+++ b/hw/s390x/meson.build
@@ -23,6 +23,7 @@ s390x_ss.add(when: 'CONFIG_KVM', if_true: files(
   's390-skeys-kvm.c',
   's390-stattrib-kvm.c',
   'pv.c',
+  's390-pci-kvm.c',
 ))
 s390x_ss.add(when: 'CONFIG_TCG', if_true: files(
   'tod-tcg.c',
diff --git a/hw/s390x/s390-pci-bus.c b/hw/s390x/s390-pci-bus.c
index 4b2bdd94b3..156051e6e9 100644
--- a/hw/s390x/s390-pci-bus.c
+++ b/hw/s390x/s390-pci-bus.c
@@ -16,6 +16,7 @@
 #include "qapi/visitor.h"
 #include "hw/s390x/s390-pci-bus.h"
 #include "hw/s390x/s390-pci-inst.h"
+#include "hw/s390x/s390-pci-kvm.h"
 #include "hw/s390x/s390-pci-vfio.h"
 #include "hw/pci/pci_bus.h"
 #include "hw/qdev-properties.h"
@@ -971,12 +972,51 @@ static void s390_pci_update_subordinate(PCIDevice *dev, 
uint32_t nr)
 }
 }
 
+static int s390_pci_interp_plug(S390pciState *s, S390PCIBusDevice *pbdev)
+{
+uint32_t idx, fh;
+
+if (!s390_pci_get_host_fh(pbdev, &fh)) {
+return -EPERM;
+}
+
+/*
+ * The host device is already in an enabled state, but we always present
+ * the initial device state to the guest as disabled (ZPCI_FS_DISABLED).
+ * Therefore, mask off the enable bit from the passthrough handle until
+ * the guest issues a CLP SET PCI FN later to enable the device.
+ */
+pbdev->fh = fh & ~FH_MASK_ENABLE;
+
+/* Next, see if the idx is already in-use */
+idx = pbdev->fh & FH_MASK_INDEX;
+if (pbdev->idx != idx) {
+if (s390_pci_find_dev_by_idx(s, idx)) {
+return -EINVAL;
+}
+/*
+ * Update the idx entry with the passed through idx
+ * If the relinquished idx is lower than next_idx, use it
+ * to replace next_idx
+ */
+g_hash_table_remove(s->zpci_table, &pbdev->idx);
+if (idx < s->next_idx) {
+s->next_idx = idx;
+}
+pbdev->idx = idx;
+g_hash_table_insert(s->zpci_table, &pbdev->idx, pbdev);
+}
+
+return 0;
+}
+
 static void s390_pcihost_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
   Error **errp)
 {
 S390pciState *s = S390_PCI_HOST_BRIDGE(hotplug_dev);
 PCIDevice *pdev = NULL;
 S390PCIBusDevice *pbdev = NULL;
+int rc;
 
 if (object_dynamic_cast(OBJECT(dev), TYPE_PCI_BRIDGE)) {
 PCIBridge *pb = PCI_BRIDGE(dev);
@@ -1022,12 +1062,35 @@ static void s390_pcihost_plug(HotplugHandler 
*hotplug_dev, DeviceState *dev,
 set_pbdev_info(pbdev);
 
 if (object_dynamic_cast(OBJECT(dev), "vfio-pci")) {
-pbdev->fh |= FH_SHM_VFIO;
+/*
+ * By default, interpretation is always requested; if the available
+ * facilities indicate it is not available, fallback to the
+ * interception model.
+ */
+if (pbdev->interp) {
+if (s390_pci_kvm_interp_allowed()) {
+rc = s390_pci_interp_plug(s, pbdev);
+if (rc) {
+error_setg(errp, "Plug failed for zPCI device in "
+   "interpretation mode: %d", rc);
+return;
+}
+} else {
+DPRINTF("zPCI interpretation facilities missing.\n");
+pbdev->interp = false;
+}
+}
 pbdev->iommu->dma_limit = s390_pci_start_dma_count(

[PATCH v7 7/8] s390x/pci: reflect proper maxstbl for groups of interpreted devices

2022-06-06 Thread Matthew Rosato
The maximum supported store block length might be different depending
on whether the instruction is interpretively executed (firmware-reported
maximum) or handled via userspace intercept (host kernel API maximum).
Choose the best available value during group creation.

Reviewed-by: Pierre Morel 
Signed-off-by: Matthew Rosato 
---
 hw/s390x/s390-pci-vfio.c | 6 +-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/hw/s390x/s390-pci-vfio.c b/hw/s390x/s390-pci-vfio.c
index 985980f021..212dd053f7 100644
--- a/hw/s390x/s390-pci-vfio.c
+++ b/hw/s390x/s390-pci-vfio.c
@@ -213,7 +213,11 @@ static void s390_pci_read_group(S390PCIBusDevice *pbdev,
 resgrp->msia = cap->msi_addr;
 resgrp->mui = cap->mui;
 resgrp->i = cap->noi;
-resgrp->maxstbl = cap->maxstbl;
+if (pbdev->interp && hdr->version >= 2) {
+resgrp->maxstbl = cap->imaxstbl;
+} else {
+resgrp->maxstbl = cap->maxstbl;
+}
 resgrp->version = cap->version;
 resgrp->dtsm = ZPCI_DTSM;
 }
-- 
2.27.0




[PATCH v7 8/8] s390x/s390-virtio-ccw: add zpcii-disable machine property

2022-06-06 Thread Matthew Rosato
The zpcii-disable machine property can be used to force-disable the use
of zPCI interpretation facilities for a VM.  By default, this setting
will be off for machine 7.1 and newer.

Signed-off-by: Matthew Rosato 
---
 hw/s390x/s390-pci-kvm.c|  4 +++-
 hw/s390x/s390-virtio-ccw.c | 24 
 include/hw/s390x/s390-virtio-ccw.h |  1 +
 qemu-options.hx|  8 +++-
 util/qemu-config.c |  4 
 5 files changed, 39 insertions(+), 2 deletions(-)

diff --git a/hw/s390x/s390-pci-kvm.c b/hw/s390x/s390-pci-kvm.c
index 9134fe185f..5eb7fd12e2 100644
--- a/hw/s390x/s390-pci-kvm.c
+++ b/hw/s390x/s390-pci-kvm.c
@@ -22,7 +22,9 @@
 
 bool s390_pci_kvm_interp_allowed(void)
 {
-return kvm_s390_get_zpci_op() && !s390_is_pv();
+return (kvm_s390_get_zpci_op() && !s390_is_pv() &&
+!object_property_get_bool(OBJECT(qdev_get_machine()),
+  "zpcii-disable", NULL));
 }
 
 int s390_pci_kvm_aif_enable(S390PCIBusDevice *pbdev, ZpciFib *fib, bool assist)
diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c
index cc3097bfee..70229b102b 100644
--- a/hw/s390x/s390-virtio-ccw.c
+++ b/hw/s390x/s390-virtio-ccw.c
@@ -645,6 +645,21 @@ static inline void machine_set_dea_key_wrap(Object *obj, 
bool value,
 ms->dea_key_wrap = value;
 }
 
+static inline bool machine_get_zpcii_disable(Object *obj, Error **errp)
+{
+S390CcwMachineState *ms = S390_CCW_MACHINE(obj);
+
+return ms->zpcii_disable;
+}
+
+static inline void machine_set_zpcii_disable(Object *obj, bool value,
+ Error **errp)
+{
+S390CcwMachineState *ms = S390_CCW_MACHINE(obj);
+
+ms->zpcii_disable = value;
+}
+
 static S390CcwMachineClass *current_mc;
 
 /*
@@ -740,6 +755,13 @@ static inline void s390_machine_initfn(Object *obj)
 "Up to 8 chars in set of [A-Za-z0-9. ] (lower case chars converted"
 " to upper case) to pass to machine loader, boot manager,"
 " and guest kernel");
+
+object_property_add_bool(obj, "zpcii-disable",
+ machine_get_zpcii_disable,
+ machine_set_zpcii_disable);
+object_property_set_description(obj, "zpcii-disable",
+"disable zPCI interpretation facilties");
+object_property_set_bool(obj, "zpcii-disable", false, NULL);
 }
 
 static const TypeInfo ccw_machine_info = {
@@ -804,9 +826,11 @@ DEFINE_CCW_MACHINE(7_1, "7.1", true);
 static void ccw_machine_7_0_instance_options(MachineState *machine)
 {
 static const S390FeatInit qemu_cpu_feat = { S390_FEAT_LIST_QEMU_V7_0 };
+S390CcwMachineState *ms = S390_CCW_MACHINE(machine);
 
 ccw_machine_7_1_instance_options(machine);
 s390_set_qemu_cpu_model(0x8561, 15, 1, qemu_cpu_feat);
+ms->zpcii_disable = true;
 }
 
 static void ccw_machine_7_0_class_options(MachineClass *mc)
diff --git a/include/hw/s390x/s390-virtio-ccw.h 
b/include/hw/s390x/s390-virtio-ccw.h
index 3331990e02..8a0090a071 100644
--- a/include/hw/s390x/s390-virtio-ccw.h
+++ b/include/hw/s390x/s390-virtio-ccw.h
@@ -27,6 +27,7 @@ struct S390CcwMachineState {
 bool aes_key_wrap;
 bool dea_key_wrap;
 bool pv;
+bool zpcii_disable;
 uint8_t loadparm[8];
 };
 
diff --git a/qemu-options.hx b/qemu-options.hx
index 60cf188da4..fafe335b4a 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -36,7 +36,8 @@ DEF("machine", HAS_ARG, QEMU_OPTION_machine, \
 "nvdimm=on|off controls NVDIMM support (default=off)\n"
 "memory-encryption=@var{} memory encryption object to use 
(default=none)\n"
 "hmat=on|off controls ACPI HMAT support (default=off)\n"
-"memory-backend='backend-id' specifies explicitly provided 
backend for main RAM (default=none)\n",
+"memory-backend='backend-id' specifies explicitly provided 
backend for main RAM (default=none)\n"
+"zpcii-disable=on|off disables zPCI interpretation 
facilities (default=off)\n",
 QEMU_ARCH_ALL)
 SRST
 ``-machine [type=]name[,prop=value[,...]]``
@@ -124,6 +125,11 @@ SRST
 -object 
memory-backend-ram,id=pc.ram,size=512M,x-use-canonical-path-for-ramblock-id=off
 -machine memory-backend=pc.ram
 -m 512M
+
+``zpcii-disable=on|off``
+Disables zPCI interpretation facilties on s390-ccw hosts.
+This feature can be used to disable hardware virtual assists
+related to zPCI devices. The default is off.
 ERST
 
 DEF("M", HAS_ARG, QEMU_OPTION_M,
diff --git a/util/qemu-config.c b/util/qemu-config.c
index 433488aa56..5325f6bf80 100644
--- a/util/qemu-config.c
+++ b/util/qemu-config.c
@@ -236,6 +236,10 @@ static QemuOptsList machine_opts = {
 .help = "Up to 8 chars in set of [A-Za-z0-9. ](lower case chars"
 " converted to upper case) to pass to machine"
 " loader

[PATCH v7 4/8] s390x/pci: don't fence interpreted devices without MSI-X

2022-06-06 Thread Matthew Rosato
Lack of MSI-X support is not an issue for interpreted passthrough
devices, so let's let these in.  This will allow, for example, ISM
devices to be passed through -- but only when interpretation is
available and being used.

Reviewed-by: Thomas Huth 
Reviewed-by: Pierre Morel 
Signed-off-by: Matthew Rosato 
---
 hw/s390x/s390-pci-bus.c | 6 +-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/hw/s390x/s390-pci-bus.c b/hw/s390x/s390-pci-bus.c
index 156051e6e9..816d17af99 100644
--- a/hw/s390x/s390-pci-bus.c
+++ b/hw/s390x/s390-pci-bus.c
@@ -881,6 +881,10 @@ static int s390_pci_msix_init(S390PCIBusDevice *pbdev)
 
 static void s390_pci_msix_free(S390PCIBusDevice *pbdev)
 {
+if (pbdev->msix.entries == 0) {
+return;
+}
+
 memory_region_del_subregion(&pbdev->iommu->mr, &pbdev->msix_notify_mr);
 object_unparent(OBJECT(&pbdev->msix_notify_mr));
 }
@@ -1093,7 +1097,7 @@ static void s390_pcihost_plug(HotplugHandler 
*hotplug_dev, DeviceState *dev,
 pbdev->interp = false;
 }
 
-if (s390_pci_msix_init(pbdev)) {
+if (s390_pci_msix_init(pbdev) && !pbdev->interp) {
 error_setg(errp, "MSI-X support is mandatory "
"in the S390 architecture");
 return;
-- 
2.27.0




Re: [PATCH v10 13/14] vfio-user: handle device interrupts

2022-06-06 Thread Alexander Duyck
On Mon, Jun 6, 2022 at 12:29 PM Jag Raman  wrote:
>
>
>
> > On Jun 6, 2022, at 2:32 PM, Alexander Duyck  
> > wrote:
> >
> > On Tue, May 24, 2022 at 9:11 AM Jagannathan Raman  
> > wrote:
> >>
> >> Forward remote device's interrupts to the guest
> >>
> >> Signed-off-by: Elena Ufimtseva 
> >> Signed-off-by: John G Johnson 
> >> Signed-off-by: Jagannathan Raman 
> >> ---
> >> include/hw/pci/pci.h  |  13 
> >> include/hw/remote/vfio-user-obj.h |   6 ++
> >> hw/pci/msi.c  |  16 ++--
> >> hw/pci/msix.c |  10 ++-
> >> hw/pci/pci.c  |  13 
> >> hw/remote/machine.c   |  14 +++-
> >> hw/remote/vfio-user-obj.c | 123 ++
> >> stubs/vfio-user-obj.c |   6 ++
> >> MAINTAINERS   |   1 +
> >> hw/remote/trace-events|   1 +
> >> stubs/meson.build |   1 +
> >> 11 files changed, 193 insertions(+), 11 deletions(-)
> >> create mode 100644 include/hw/remote/vfio-user-obj.h
> >> create mode 100644 stubs/vfio-user-obj.c
> >>
> >
> > So I had a question about a few bits below. Specifically I ran into
> > issues when I had setup two devices to be assigned to the same VM via
> > two vfio-user-pci/x-vfio-user-server interfaces.
>
> Thanks for the heads up, Alexander!
>
> >
> > What I am hitting is an assert(irq_num < bus->nirq) in
> > pci_bus_change_irq_level in the server.
>
> That is issue is because we are only initializing only one
> IRQ for the PCI bus - but it should be more. We will update
> it and when the bus initializes interrupts and get back to you.
>
> We only tested MSI/x devices for the multi-device config. We
> should also test INTx - could you please confirm which device
> you’re using so we could verify that it works before posting
> the next revision.
>
> Thank you!
> --
> Jag

I was testing an MSI-X capable NIC, so you can reproduce with e1000e.
During the device enumeration before the driver was even loaded it
threw the error:
qemu-system-x86_64: ../hw/pci/pci.c:276: pci_bus_change_irq_level:
Assertion `irq_num < bus->nirq' failed.

All it really takes is attaching to the second device, that is enough
to trigger the error since the irq_num will be non-zero.

If I recall, all the kernel is doing is unmasking the interrupt via
the config space and it is triggering the error which then shuts down
the server.



Re: [PATCH v3 2/4] docs: rSTify MailingLists wiki; move it to QEMU Git

2022-06-06 Thread Alistair Francis
On Tue, Jun 7, 2022 at 2:46 AM Kashyap Chamarthy  wrote:
>
> This document is referred to from the GettingStartedDevelopers wiki
> which will be rSTified in a follow-up commit.
>
> Converted from Mediawiki to rST using:
>
> $> pandoc -f Mediawiki -t rst MailingLists.wiki
> -o mailing-lists.rst
>
> The only change in this coversion is that I have removed the users
> mailing list, as it will be referred to from a different document from
> the docs/about/ directory.
>
> Besides that, this is almost a 1-1 conversion (I double-checked to the
> best I could).  I've also checked that the hyperlinks work correctly
> post-conversion.
>
> Signed-off-by: Kashyap Chamarthy 
> Reviewed-by: Thomas Huth 

Reviewed-by: Alistair Francis 

Alistair

> ---
>  docs/devel/index.rst |  1 +
>  docs/devel/mailing-lists.rst | 51 
>  2 files changed, 52 insertions(+)
>  create mode 100644 docs/devel/mailing-lists.rst
>
> diff --git a/docs/devel/index.rst b/docs/devel/index.rst
> index 424eff9294..fb9d9f3a80 100644
> --- a/docs/devel/index.rst
> +++ b/docs/devel/index.rst
> @@ -12,6 +12,7 @@ modifying QEMU's source code.
>
> code-of-conduct
> conflict-resolution
> +   mailing-lists
> build-system
> style
> kconfig
> diff --git a/docs/devel/mailing-lists.rst b/docs/devel/mailing-lists.rst
> new file mode 100644
> index 00..4533179f1f
> --- /dev/null
> +++ b/docs/devel/mailing-lists.rst
> @@ -0,0 +1,51 @@
> +.. _mailing-lists:
> +
> +Mailing lists
> +=
> +
> +-  `QEMU developers mailing
> +   list `__
> +-  `QEMU stable mailing
> +   list `__
> +-  `QEMU trivial patch mailing
> +   list `__
> +
> +.. _subsystem_specific_lists:
> +
> +Subsystem Specific Lists
> +
> +
> +These exist to make it a little easier to follow subsystem specific
> +patches. You should however continue to CC qemu-devel so your series
> +gets wide visibility.
> +
> +-  `QEMU ARM mailing
> +   list `__
> +-  `QEMU block devices mailing
> +   list `__
> +-  `QEMU PowerPC mailing
> +   list `__
> +-  `QEMU RISC-V mailing
> +   list `__
> +-  `QEMU s390x mailing
> +   list `__
> +
> +If a subsystem maintainer thinks that a new mailing list for their
> +subsystem would make life easier, we're happy to create one -- mail
> +qemu-devel to suggest it (ideally cc'ing the people listed as Savannah
> +project admins in our `AdminContacts `__ page, as they
> +are the ones with the ability to make the change).
> +
> +If you are a Savannah project admin, you may want the `technical notes
> +on how to create and configure a new
> +list `__.
> +
> +.. _access_via_lore.kernel.org:
> +
> +Access via lore.kernel.org
> +--
> +
> +The qemu-devel mailing list is also archived via
> +`public-inbox `__ on
> +https://lore.kernel.org/qemu-devel/ and accessible via NNTP at
> +nntp.lore.kernel.org (newsgroup org.nongnu.qemu-devel).
> --
> 2.36.1
>
>



[PATCH] Hexagon (target/hexagon) fix store w/mem_noshuf & predicated load

2022-06-06 Thread Taylor Simpson
Call the CHECK_NOSHUF macro multiple times: once in the
fGEN_TCG_PRED_LOAD() and again in fLOAD().

Before this commit, a packet with a store and a predicated
load with mem_noshuf that gets encoded like this:

{ P0 = cmp.eq(R17,#0x0)
  memw(R18+#0x0) = R2
  if (!P0.new) R3 = memw(R17+#0x4) }

... would end up generating a branch over both the load
and the store like so:

...
brcond_i32 loc17,$0x0,eq,$L1
mov_i32 loc18,store_addr_1
qemu_st_i32 store_val32_1,store_addr_1,leul,0
qemu_ld_i32 loc16,loc7,leul,0
set_label $L1
...

Test cases added to tests/tcg/hexagon/mem_noshuf.c

Co-authored-by: Taylor Simpson 
Signed-off-by: Brian Cain 
Signed-off-by: Taylor Simpson 
---
 target/hexagon/gen_tcg.h   |   2 +
 tests/tcg/hexagon/mem_noshuf.c | 122 +++--
 2 files changed, 119 insertions(+), 5 deletions(-)

diff --git a/target/hexagon/gen_tcg.h b/target/hexagon/gen_tcg.h
index c6f0879b6e..b0b6b3644e 100644
--- a/target/hexagon/gen_tcg.h
+++ b/target/hexagon/gen_tcg.h
@@ -343,6 +343,7 @@
 PRED;  \
 PRED_LOAD_CANCEL(LSB, EA); \
 tcg_gen_movi_tl(RdV, 0); \
+CHECK_NOSHUF; \
 tcg_gen_brcondi_tl(TCG_COND_EQ, LSB, 0, label); \
 fLOAD(1, SIZE, SIGN, EA, RdV); \
 gen_set_label(label); \
@@ -402,6 +403,7 @@
 PRED;  \
 PRED_LOAD_CANCEL(LSB, EA); \
 tcg_gen_movi_i64(RddV, 0); \
+CHECK_NOSHUF; \
 tcg_gen_brcondi_tl(TCG_COND_EQ, LSB, 0, label); \
 fLOAD(1, 8, u, EA, RddV); \
 gen_set_label(label); \
diff --git a/tests/tcg/hexagon/mem_noshuf.c b/tests/tcg/hexagon/mem_noshuf.c
index dd714d5e98..0f4064e700 100644
--- a/tests/tcg/hexagon/mem_noshuf.c
+++ b/tests/tcg/hexagon/mem_noshuf.c
@@ -1,5 +1,5 @@
 /*
- *  Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights 
Reserved.
+ *  Copyright(c) 2019-2022 Qualcomm Innovation Center, Inc. All Rights 
Reserved.
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -84,6 +84,70 @@ MEM_NOSHUF32(mem_noshuf_sd_luh, long long,unsigned 
short,   memd, memuh)
 MEM_NOSHUF32(mem_noshuf_sd_lw,  long long,signed int,   memd, memw)
 MEM_NOSHUF64(mem_noshuf_sd_ld,  long long,signed long long, memd, memd)
 
+static inline int pred_lw_sw(int pred, int *p, int *q, int x, int y)
+{
+int ret;
+asm volatile("p0 = cmp.eq(%5, #0)\n\t"
+ "%0 = %3\n\t"
+ "{\n\t"
+ "memw(%1) = %4\n\t"
+ "if (!p0) %0 = memw(%2)\n\t"
+ "}:mem_noshuf\n"
+ : "=&r"(ret)
+ : "r"(p), "r"(q), "r"(x), "r"(y), "r"(pred)
+ : "p0", "memory");
+return ret;
+}
+
+static inline int pred_lw_sw_pi(int pred, int *p, int *q, int x, int y)
+{
+int ret;
+asm volatile("p0 = cmp.eq(%5, #0)\n\t"
+ "%0 = %3\n\t"
+ "r7 = %2\n\t"
+ "{\n\t"
+ "memw(%1) = %4\n\t"
+ "if (!p0) %0 = memw(r7++#4)\n\t"
+ "}:mem_noshuf\n"
+ : "=&r"(ret)
+ : "r"(p), "r"(q), "r"(x), "r"(y), "r"(pred)
+ : "r7", "p0", "memory");
+return ret;
+}
+
+static inline long long pred_ld_sd(int pred, long long *p, long long *q,
+   long long x, long long y)
+{
+unsigned long long ret;
+asm volatile("p0 = cmp.eq(%5, #0)\n\t"
+ "%0 = %3\n\t"
+ "{\n\t"
+ "memd(%1) = %4\n\t"
+ "if (!p0) %0 = memd(%2)\n\t"
+ "}:mem_noshuf\n"
+ : "=&r"(ret)
+ : "r"(p), "r"(q), "r"(x), "r"(y), "r"(pred)
+ : "p0", "memory");
+return ret;
+}
+
+static inline long long pred_ld_sd_pi(int pred, long long *p, long long *q,
+  long long x, long long y)
+{
+long long ret;
+asm volatile("p0 = cmp.eq(%5, #0)\n\t"
+ "%0 = %3\n\t"
+ "r7 = %2\n\t"
+ "{\n\t"
+ "memd(%1) = %4\n\t"
+ "if (!p0) %0 = memd(r7++#8)\n\t"
+ "}:mem_noshuf\n"
+ : "=&r"(ret)
+ : "r"(p), "r"(q), "r"(x), "r"(y), "r"(pred)
+ : "p0", "memory");
+return ret;
+}
+
 static inline unsigned int cancel_sw_lb(int pred, int *p, signed char *q, int 
x)
 {
 unsigned int ret;
@@ -126,18 +190,22 @@ typedef union {
 
 int err;
 
-static void check32(int n, int expect)
+#define check32(n, expect) check32_(n, expect, __LINE__)
+
+static void check32_(int n, int expect, int line)
 {
 if (n != expect) {
-printf("ERROR: 0x%08x != 0x%08x\n", n, expect);
+printf("ERROR: 0x%08x != 0x%08x, line %d\n", n, expect, line);
 err++;
 }
 }
 
-static void check6

[PATCH] Hexagon (target/hexagon) make VyV operands use a unique temp

2022-06-06 Thread Taylor Simpson
VyV operand is only used in the vshuff and vdeal instructions.  These
instructions write to both VyV and VxV operands.  In the case where
both operands are the same register, we need a separate location for
VyV.  We use the existing vtmp field in CPUHexagonState.

Test case added in tests/tcg/hexagon/hvx_misc.c

Signed-off-by: Taylor Simpson 
---
 tests/tcg/hexagon/hvx_misc.c| 45 +
 target/hexagon/gen_tcg_funcs.py |  9 +++
 2 files changed, 49 insertions(+), 5 deletions(-)

diff --git a/tests/tcg/hexagon/hvx_misc.c b/tests/tcg/hexagon/hvx_misc.c
index b896f5897e..6e2c9ab3cd 100644
--- a/tests/tcg/hexagon/hvx_misc.c
+++ b/tests/tcg/hexagon/hvx_misc.c
@@ -498,6 +498,49 @@ static void test_vsubuwsat_dv(void)
 check_output_w(__LINE__, 2);
 }
 
+static void test_vshuff(void)
+{
+/* Test that vshuff works when the two operands are the same register */
+const uint32_t splat = 0x089be55c;
+const uint32_t shuff = 0x454fa926;
+MMVector v0, v1;
+
+memset(expect, 0x12, sizeof(MMVector));
+memset(output, 0x34, sizeof(MMVector));
+
+asm volatile("v25 = vsplat(%0)\n\t"
+ "vshuff(v25, v25, %1)\n\t"
+ "vmem(%2 + #0) = v25\n\t"
+ : /* no outputs */
+ : "r"(splat), "r"(shuff), "r"(output)
+ : "v25", "memory");
+
+/*
+ * The semantics of Hexagon are the operands are pass-by-value, so create
+ * two copies of the vsplat result.
+ */
+for (int i = 0; i < MAX_VEC_SIZE_BYTES / 4; i++) {
+v0.uw[i] = splat;
+v1.uw[i] = splat;
+}
+/* Do the vshuff operation */
+for (int offset = 1; offset < MAX_VEC_SIZE_BYTES; offset <<= 1) {
+if (shuff & offset) {
+for (int k = 0; k < MAX_VEC_SIZE_BYTES; k++) {
+if (!(k & offset)) {
+uint8_t tmp = v0.ub[k];
+v0.ub[k] = v1.ub[k + offset];
+v1.ub[k + offset] = tmp;
+}
+}
+}
+}
+/* Put the result in the expect buffer for verification */
+expect[0] = v1;
+
+check_output_b(__LINE__, 1);
+}
+
 int main()
 {
 init_buffers();
@@ -533,6 +576,8 @@ int main()
 test_vadduwsat();
 test_vsubuwsat_dv();
 
+test_vshuff();
+
 puts(err ? "FAIL" : "PASS");
 return err ? 1 : 0;
 }
diff --git a/target/hexagon/gen_tcg_funcs.py b/target/hexagon/gen_tcg_funcs.py
index 1fd9de95d5..d72c689ad7 100755
--- a/target/hexagon/gen_tcg_funcs.py
+++ b/target/hexagon/gen_tcg_funcs.py
@@ -1,7 +1,7 @@
 #!/usr/bin/env python3
 
 ##
-##  Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights 
Reserved.
+##  Copyright(c) 2019-2022 Qualcomm Innovation Center, Inc. All Rights 
Reserved.
 ##
 ##  This program is free software; you can redistribute it and/or modify
 ##  it under the terms of the GNU General Public License as published by
@@ -164,7 +164,9 @@ def genptr_decl(f, tag, regtype, regid, regno):
 (regtype, regid, regno))
 f.write("const intptr_t %s%sV_off =\n" % \
 (regtype, regid))
-if (hex_common.is_tmp_result(tag)):
+if (regid == "y"):
+f.write("offsetof(CPUHexagonState, vtmp);\n")
+elif (hex_common.is_tmp_result(tag)):
 f.write("ctx_tmp_vreg_off(ctx, %s%sN, 1, true);\n" % \
 (regtype, regid))
 else:
@@ -379,9 +381,6 @@ def genptr_src_read(f, tag, regtype, regid):
 f.write("vreg_src_off(ctx, %s%sN),\n" % \
  (regtype, regid))
 f.write("sizeof(MMVector), sizeof(MMVector));\n")
-if (not hex_common.skip_qemu_helper(tag)):
-f.write("tcg_gen_addi_ptr(%s%sV, cpu_env, %s%sV_off);\n" % 
\
- (regtype, regid, regtype, regid))
 else:
 print("Bad register parse: ", regtype, regid)
 elif (regtype == "Q"):
-- 
2.17.1



[PATCH] Hexagon (tests/tcg/hexagon) reference file for float_convd

2022-06-06 Thread Taylor Simpson
The test is in tests/tcg/multiarch/float_convd.c

Signed-off-by: Taylor Simpson 
---
 tests/tcg/hexagon/float_convd.ref | 988 ++
 1 file changed, 988 insertions(+)
 create mode 100644 tests/tcg/hexagon/float_convd.ref

diff --git a/tests/tcg/hexagon/float_convd.ref 
b/tests/tcg/hexagon/float_convd.ref
new file mode 100644
index 00..aba1e13e35
--- /dev/null
+++ b/tests/tcg/hexagon/float_convd.ref
@@ -0,0 +1,988 @@
+### Rounding to nearest
+from double: f64(nan:0x007ff4)
+  to single: f32(-nan:0x) (INVALID)
+   to int32: -1 (INVALID)
+   to int64: -1 (INVALID)
+  to uint32: -1 (INVALID)
+  to uint64: -1 (INVALID)
+from double: f64(-nan:0x00fff8)
+  to single: f32(-nan:0x) (OK)
+   to int32: -1 (INVALID)
+   to int64: -1 (INVALID)
+  to uint32: -1 (INVALID)
+  to uint64: -1 (INVALID)
+from double: f64(-inf:0x00fff0)
+  to single: f32(-inf:0xff80) (OK)
+   to int32: -2147483648 (INVALID)
+   to int64: -9223372036854775808 (INVALID)
+  to uint32: 0 (INVALID)
+  to uint64: 0 (INVALID)
+from double: f64(-0x1.f000p+1023:0x00ffef)
+  to single: f32(-inf:0xff80) (OVERFLOW INEXACT )
+   to int32: -2147483648 (INVALID)
+   to int64: -9223372036854775808 (INVALID)
+  to uint32: 0 (INVALID)
+  to uint64: 0 (INVALID)
+from double: f64(-0x1.fe00p+127:0x00c7efe000)
+  to single: f32(-0x1.fe00p+127:0xff7f) (OK)
+   to int32: -2147483648 (INVALID)
+   to int64: -9223372036854775808 (INVALID)
+  to uint32: 0 (INVALID)
+  to uint64: 0 (INVALID)
+from double: f64(-0x1.fe00p+127:0x00c7efe000)
+  to single: f32(-0x1.fe00p+127:0xff7f) (OK)
+   to int32: -2147483648 (INVALID)
+   to int64: -9223372036854775808 (INVALID)
+  to uint32: 0 (INVALID)
+  to uint64: 0 (INVALID)
+from double: f64(-0x1.1874b135ff654000p+103:0x00c661874b135ff654)
+  to single: f32(-0x1.1874b200p+103:0xf30c3a59) (INEXACT )
+   to int32: -2147483648 (INVALID)
+   to int64: -9223372036854775808 (INVALID)
+  to uint32: 0 (INVALID)
+  to uint64: 0 (INVALID)
+from double: f64(-0x1.c0bab523323b9000p+99:0x00c62c0bab523323b9)
+  to single: f32(-0x1.c0bab600p+99:0xf1605d5b) (INEXACT )
+   to int32: -2147483648 (INVALID)
+   to int64: -9223372036854775808 (INVALID)
+  to uint32: 0 (INVALID)
+  to uint64: 0 (INVALID)
+from double: f64(-0x1.p+1:0x00c000)
+  to single: f32(-0x1.p+1:0xc000) (OK)
+   to int32: -2 (OK)
+   to int64: -2 (OK)
+  to uint32: 0 (INVALID)
+  to uint64: 0 (INVALID)
+from double: f64(-0x1.p+0:0x00bff0)
+  to single: f32(-0x1.p+0:0xbf80) (OK)
+   to int32: -1 (OK)
+   to int64: -1 (OK)
+  to uint32: 0 (INVALID)
+  to uint64: 0 (INVALID)
+from double: f64(-0x1.p-1022:0x008010)
+  to single: f32(-0x0.p+0:0x8000) (UNDERFLOW INEXACT )
+   to int32: 0 (INEXACT )
+   to int64: 0 (INEXACT )
+  to uint32: 0 (INVALID)
+  to uint64: 0 (INVALID)
+from double: f64(-0x1.p-126:0x00b810)
+  to single: f32(-0x1.p-126:0x8080) (OK)
+   to int32: 0 (INEXACT )
+   to int64: 0 (INEXACT )
+  to uint32: 0 (INVALID)
+  to uint64: 0 (INVALID)
+from double: f64(0x0.p+0:)
+  to single: f32(0x0.p+0:00) (OK)
+   to int32: 0 (OK)
+   to int64: 0 (OK)
+  to uint32: 0 (OK)
+  to uint64: 0 (OK)
+from double: f64(0x1.p-126:0x003810)
+  to single: f32(0x1.p-126:0x0080) (OK)
+   to int32: 0 (INEXACT )
+   to int64: 0 (INEXACT )
+  to uint32: 0 (INEXACT )
+  to uint64: 0 (INEXACT )
+from double: f64(0x1.0001c5f68000p-25:0x003e60001c5f68)
+  to single: f32(0x1.p-25:0x3300) (INEXACT )
+   to int32: 0 (INEXACT )
+   to int64: 0 (INEXACT )
+  to uint32: 0 (INEXACT )
+  to uint64: 0 (INEXACT )
+from double: f64(0x1.e6cb2fa82000p-25:0x003e6e6cb2fa82)
+  to single: f32(0x1.e600p-25:0x3373) (INEXACT )
+   to int32: 0 (INEXACT )
+   to int64: 0 (INEXACT )
+  to uint32: 0 (INEXACT )
+  to uint64: 0 (INEXACT )
+from double: f64(0x1.ff801a9af58a1000p-15:0x003f0ff801a9af58a1)
+  to single: f32(0x1.ff801a00p-15:0x387fc00d) (INEXACT )
+   to int32: 0 (INEXACT )
+   to int64: 0 (INEXACT )
+  to uint32: 0 (INEXACT )
+  to uint64: 0 (INEXACT )
+from double: f64(0x1.0c06a1ef5000p-14:0x003f10c06a1ef5)
+  to single: f32(0x1.0c00p-14:0x3886) (INEXACT )
+   to int32: 0 (INEXACT )
+   to int64: 0 (INEXACT )
+  to uint32: 0 (INEXACT )
+  to uint64: 0 (INEXACT )
+from double: f64(0x1.p+0:0x003ff0)
+  to single: f32(0x1.p+0:0x3f80) (OK)
+   to int32: 1 (OK)
+   to

[PATCH] Hexagon (target/hexagon) remove unused encodings

2022-06-06 Thread Taylor Simpson
Remove encodings guarded by ifdef that is not defined

Signed-off-by: Taylor Simpson 
---
 target/hexagon/imported/encode_pp.def | 23 ---
 1 file changed, 23 deletions(-)

diff --git a/target/hexagon/imported/encode_pp.def 
b/target/hexagon/imported/encode_pp.def
index 939c6fc55f..d71c04cd30 100644
--- a/target/hexagon/imported/encode_pp.def
+++ b/target/hexagon/imported/encode_pp.def
@@ -944,13 +944,6 @@ MPY_ENC(F2_dfmpyfix, 
"1000","d","0","0","1","0","11")
 MPY_ENC(F2_dfmin,"1000","d","0","0","1","1","11")
 MPY_ENC(F2_dfmax,"1000","d","0","1","0","0","11")
 MPY_ENC(F2_dfmpyll,  "1000","d","0","1","0","1","11")
-#ifdef ADD_DP_OPS
-MPY_ENC(F2_dfdivcheat,   "1000","d","0","0","0","1","00")
-
-MPY_ENC(F2_dffixupn, "1000","d","0","1","0","1","11")
-MPY_ENC(F2_dffixupd, "1000","d","0","1","1","0","11")
-MPY_ENC(F2_dfrecipa, "1000","d","0","1","1","1","ee")
-#endif
 
 MPY_ENC(M7_dcmpyrw,  "1000","d","0","0","0","1","10")
 MPY_ENC(M7_dcmpyrwc, "1000","d","0","0","1","1","10")
@@ -1024,15 +1017,6 @@ MPY_ENC(M5_vdmacbsu, 
"1010","x","0","1","0","0","01")
 
 MPY_ENC(F2_dfmpylh,  "1010","x","0","0","0","0","11")
 MPY_ENC(F2_dfmpyhh,  "1010","x","0","0","0","1","11")
-#ifdef ADD_DP_OPS
-MPY_ENC(F2_dfmpyhh,  "1010","x","0","0","1","0","11")
-MPY_ENC(F2_dffma,"1010","x","0","0","0","0","11")
-MPY_ENC(F2_dffms,"1010","x","0","0","0","1","11")
-
-MPY_ENC(F2_dffma_lib,"1010","x","0","0","1","0","11")
-MPY_ENC(F2_dffms_lib,"1010","x","0","0","1","1","11")
-MPY_ENC(F2_dffma_sc, "1010","x","0","1","1","1","uu")
-#endif
 
 
 MPY_ENC(M7_dcmpyrw_acc,  "1010","x","0","0","0","1","10")
@@ -1547,15 +1531,8 @@ SH2_RR_ENC(F2_conv_df2d,  "","111","0","0 
00","d")
 SH2_RR_ENC(F2_conv_df2ud, "","111","0","0 01","d")
 SH2_RR_ENC(F2_conv_ud2df, "","111","0","0 10","d")
 SH2_RR_ENC(F2_conv_d2df,  "","111","0","0 11","d")
-#ifdef ADD_DP_OPS
-SH2_RR_ENC(F2_dffixupr,   "","111","0","1 00","d")
-SH2_RR_ENC(F2_dfsqrtcheat,"","111","0","1 01","d")
-#endif
 SH2_RR_ENC(F2_conv_df2d_chop, "","111","0","1 10","d")
 SH2_RR_ENC(F2_conv_df2ud_chop,"","111","0","1 11","d")
-#ifdef ADD_DP_OPS
-SH2_RR_ENC(F2_dfinvsqrta, "","111","1","0 ee","d")
-#endif
 
 
 
-- 
2.17.1



[PATCH] Hexagon (target/hexagon) add overrides for S2_asr_r_r_sat/S2_asl_r_r_sat

2022-06-06 Thread Taylor Simpson
These instructions will not be generated by idef-parser, so we override
them manually.

Test cases added to tests/tcg/hexagon/usr.c

Signed-off-by: Taylor Simpson 
---
 target/hexagon/gen_tcg.h |  10 ++-
 target/hexagon/genptr.c  | 147 +++
 tests/tcg/hexagon/usr.c  |  22 --
 3 files changed, 172 insertions(+), 7 deletions(-)

diff --git a/target/hexagon/gen_tcg.h b/target/hexagon/gen_tcg.h
index c6f0879b6e..9268f49acd 100644
--- a/target/hexagon/gen_tcg.h
+++ b/target/hexagon/gen_tcg.h
@@ -1,5 +1,5 @@
 /*
- *  Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights 
Reserved.
+ *  Copyright(c) 2019-2022 Qualcomm Innovation Center, Inc. All Rights 
Reserved.
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -610,6 +610,14 @@
 tcg_temp_free(tmp); \
 } while (0)
 
+/* r0 = asr(r1, r2):sat */
+#define fGEN_TCG_S2_asr_r_r_sat(SHORTCODE) \
+gen_asr_r_r_sat(RdV, RsV, RtV)
+
+/* r0 = asl(r1, r2):sat */
+#define fGEN_TCG_S2_asl_r_r_sat(SHORTCODE) \
+gen_asl_r_r_sat(RdV, RsV, RtV)
+
 /* Floating point */
 #define fGEN_TCG_F2_conv_sf2df(SHORTCODE) \
 gen_helper_conv_sf2df(RddV, cpu_env, RsV)
diff --git a/target/hexagon/genptr.c b/target/hexagon/genptr.c
index cd6af4bceb..36e6451859 100644
--- a/target/hexagon/genptr.c
+++ b/target/hexagon/genptr.c
@@ -468,6 +468,153 @@ static TCGv gen_8bitsof(TCGv result, TCGv value)
 return result;
 }
 
+static void gen_set_usr_field(int field, TCGv val)
+{
+tcg_gen_deposit_tl(hex_new_value[HEX_REG_USR], hex_new_value[HEX_REG_USR],
+   val,
+   reg_field_info[field].offset,
+   reg_field_info[field].width);
+}
+
+static void gen_set_usr_fieldi(int field, int x)
+{
+TCGv val = tcg_const_tl(x);
+gen_set_usr_field(field, val);
+tcg_temp_free(val);
+}
+
+static void gen_sat_i64(TCGv_i64 dst, TCGv_i64 src, uint32_t bits)
+{
+TCGLabel *label = gen_new_label();
+
+tcg_gen_sextract_i64(dst, src, 0, bits);
+tcg_gen_brcond_i64(TCG_COND_EQ, dst, src, label);
+{
+TCGv_i64 min = tcg_constant_i64(-(1LL << (bits - 1)));
+TCGv_i64 max = tcg_constant_i64((1LL << (bits - 1)) - 1);
+tcg_gen_movcond_i64(TCG_COND_LT, dst, src, tcg_constant_i64(0),
+min, max);
+gen_set_usr_fieldi(USR_OVF, 1);
+}
+gen_set_label(label);
+}
+
+static void gen_satval(TCGv_i64 dest, TCGv_i64 source, uint32_t bits)
+{
+TCGv_i64 min = tcg_constant_i64(-(1LL << (bits - 1)));
+TCGv_i64 max = tcg_constant_i64((1LL << (bits - 1)) - 1);
+
+gen_set_usr_fieldi(USR_OVF, 1);
+tcg_gen_movcond_i64(TCG_COND_LT, dest, source, tcg_constant_i64(0),
+min, max);
+}
+
+/* Shift left with saturation */
+static void gen_shl_sat(TCGv RdV, TCGv RsV, TCGv shift_amt)
+{
+/*
+ * int64_t A = (fCAST4_8s(RsV) << shift_amt;
+ * if (((int32_t)((fSAT(A)) ^ ((int32_t)(RsV < 0) {
+ * RdV = fSATVALN(32, ((int32_t)(RsV)))
+ * } else if (((RsV) > 0) && ((A) == 0)) {
+ * RdV = fSATVALN(32, (RsV));
+ * } else {
+ * RdV = fSAT(A);
+ * }
+ */
+TCGv_i64 RsV_i64 = tcg_temp_local_new_i64();
+TCGv_i64 shift_amt_i64 = tcg_temp_local_new_i64();
+TCGv_i64 A = tcg_temp_local_new_i64();
+TCGv_i64 A_sat_i64 = tcg_temp_local_new_i64();
+TCGv A_sat = tcg_temp_local_new();
+TCGv_i64 RdV_i64 = tcg_temp_local_new_i64();
+TCGv tmp = tcg_temp_new();
+TCGLabel *label1 = gen_new_label();
+TCGLabel *label2 = gen_new_label();
+TCGLabel *done = gen_new_label();
+
+tcg_gen_ext_i32_i64(RsV_i64, RsV);
+tcg_gen_ext_i32_i64(shift_amt_i64, shift_amt);
+tcg_gen_shl_i64(A, RsV_i64, shift_amt_i64);
+
+/* Check for saturation */
+gen_sat_i64(A_sat_i64, A, 32);
+tcg_gen_extrl_i64_i32(A_sat, A_sat_i64);
+tcg_gen_xor_tl(tmp, A_sat, RsV);
+tcg_gen_brcondi_tl(TCG_COND_GE, tmp, 0, label1);
+gen_satval(RdV_i64, RsV_i64, 32);
+tcg_gen_extrl_i64_i32(RdV, RdV_i64);
+tcg_gen_br(done);
+
+gen_set_label(label1);
+tcg_gen_brcondi_tl(TCG_COND_LE, RsV, 0, label2);
+tcg_gen_brcondi_i64(TCG_COND_NE, A, 0, label2);
+gen_satval(RdV_i64, RsV_i64, 32);
+tcg_gen_extrl_i64_i32(RdV, RdV_i64);
+tcg_gen_br(done);
+
+gen_set_label(label2);
+tcg_gen_mov_tl(RdV, A_sat);
+
+gen_set_label(done);
+
+tcg_temp_free_i64(RsV_i64);
+tcg_temp_free_i64(shift_amt_i64);
+tcg_temp_free_i64(A);
+tcg_temp_free_i64(A_sat_i64);
+tcg_temp_free(A_sat);
+tcg_temp_free_i64(RdV_i64);
+tcg_temp_free(tmp);
+}
+
+/* Bidirectional shift right with saturation */
+static void gen_asr_r_r_sat(TCGv RdV, TCGv RsV, TCGv RtV)
+{
+TCGv shift_amt = tcg_temp_local_new();
+TCGLabel *positive = gen_new_label();
+TCGLabel *done = gen_new_label();
+
+tcg_gen_sextract_i32(shi

[PATCH] Hexagon (tests/tcg/hexagon) Fix alignment in load_unpack.c

2022-06-06 Thread Taylor Simpson
The increment used in :brev tests was causing unaligned addresses
Change the increment and the relevant expected values

Signed-off-by: Taylor Simpson 
---
 tests/tcg/hexagon/load_unpack.c | 14 +++---
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/tests/tcg/hexagon/load_unpack.c b/tests/tcg/hexagon/load_unpack.c
index 3575a37a28..4aa26fc388 100644
--- a/tests/tcg/hexagon/load_unpack.c
+++ b/tests/tcg/hexagon/load_unpack.c
@@ -245,7 +245,7 @@ TEST_pr(loadbsw4_pr, long long, S, 4, 0xff00ff00LL,
  */
 #define BxW_LOAD_pbr(SZ, RES, PTR) \
 __asm__( \
-"r4 = #(1 << (16 - 3))\n\t" \
+"r4 = #(1 << (16 - 4))\n\t" \
 "m0 = r4\n\t" \
 "%0 = mem" #SZ "(%1++m0:brev)\n\t" \
 : "=r"(RES), "+r"(PTR) \
@@ -273,15 +273,15 @@ void test_##NAME(void) \
 }
 
 TEST_pbr(loadbzw2_pbr, int, Z, 0x,
-0x00020081, 0x00060085, 0x00040083, 0x00080087)
+0x00020081, 0x000a0089, 0x00060085, 0x000e008d)
 TEST_pbr(loadbsw2_pbr, int, S, 0xff00,
-0x00020081, 0x00060085, 0x00040083, 0x00080087)
+0x00020081, 0x000aff89, 0x0006ff85, 0x000eff8d)
 TEST_pbr(loadbzw4_pbr, long long, Z, 0xLL,
-0x0004008300020081LL, 0x0008008700060085LL,
-0x0006008500040083LL, 0x000a008900080087LL)
+0x0004008300020081LL, 0x000c008b000a0089LL,
+0x0008008700060085LL, 0x0010008f000e008dLL)
 TEST_pbr(loadbsw4_pbr, long long, S, 0xff00ff00LL,
-0x0004008300020081LL, 0x0008008700060085LL,
-0x0006008500040083LL, 0x000a008900080087LL)
+0x0004008300020081LL, 0x000cff8b000aff89LL,
+0x0008ff870006ff85LL, 0x0010ff8f000eff8dLL)
 
 /*
  
-- 
2.17.1



[PATCH] Hexagon (target/hexagon) move store size tracking to translation

2022-06-06 Thread Taylor Simpson
The store width is needed for packet commit, so it is stored in
ctx->store_width.  Currently, it is set when a store has a TCG
override instead of a QEMU helper.  In the QEMU helper case, the
ctx->store_width is not set, we invoke a helper during packet commit
that uses the runtime store width.

This patch ensures ctx->store_width is set for all store instructions,
so performance is improved because packet commit can generate the proper
TCG store rather than the generic helper.

We do this by
- Create new attributes to indicate the store size
- During gen_semantics, convert the fSTORE instances to fSTORE
- Assign the new attributes to the new macros
- Add definitions for the new macros
- Use the attributes from the instructions during translation to
  set ctx->store_width
- Remove setting of ctx->store_width from genptr.c

Signed-off-by: Taylor Simpson 
---
 target/hexagon/macros.h  | 16 ++
 target/hexagon/attribs_def.h.inc |  4 
 target/hexagon/gen_semantics.c   | 26 +++
 target/hexagon/genptr.c  | 36 +++-
 target/hexagon/translate.c   | 26 +++
 5 files changed, 80 insertions(+), 28 deletions(-)

diff --git a/target/hexagon/macros.h b/target/hexagon/macros.h
index a78e84faa4..1d26f59fea 100644
--- a/target/hexagon/macros.h
+++ b/target/hexagon/macros.h
@@ -139,7 +139,7 @@
 __builtin_choose_expr(TYPE_TCGV(X), \
 gen_store1, (void)0))
 #define MEM_STORE1(VA, DATA, SLOT) \
-MEM_STORE1_FUNC(DATA)(cpu_env, VA, DATA, ctx, SLOT)
+MEM_STORE1_FUNC(DATA)(cpu_env, VA, DATA, SLOT)
 
 #define MEM_STORE2_FUNC(X) \
 __builtin_choose_expr(TYPE_INT(X), \
@@ -147,7 +147,7 @@
 __builtin_choose_expr(TYPE_TCGV(X), \
 gen_store2, (void)0))
 #define MEM_STORE2(VA, DATA, SLOT) \
-MEM_STORE2_FUNC(DATA)(cpu_env, VA, DATA, ctx, SLOT)
+MEM_STORE2_FUNC(DATA)(cpu_env, VA, DATA, SLOT)
 
 #define MEM_STORE4_FUNC(X) \
 __builtin_choose_expr(TYPE_INT(X), \
@@ -155,7 +155,7 @@
 __builtin_choose_expr(TYPE_TCGV(X), \
 gen_store4, (void)0))
 #define MEM_STORE4(VA, DATA, SLOT) \
-MEM_STORE4_FUNC(DATA)(cpu_env, VA, DATA, ctx, SLOT)
+MEM_STORE4_FUNC(DATA)(cpu_env, VA, DATA, SLOT)
 
 #define MEM_STORE8_FUNC(X) \
 __builtin_choose_expr(TYPE_INT(X), \
@@ -163,7 +163,7 @@
 __builtin_choose_expr(TYPE_TCGV_I64(X), \
 gen_store8, (void)0))
 #define MEM_STORE8(VA, DATA, SLOT) \
-MEM_STORE8_FUNC(DATA)(cpu_env, VA, DATA, ctx, SLOT)
+MEM_STORE8_FUNC(DATA)(cpu_env, VA, DATA, SLOT)
 #else
 #define MEM_LOAD1s(VA) ((int8_t)mem_load1(env, slot, VA))
 #define MEM_LOAD1u(VA) ((uint8_t)mem_load1(env, slot, VA))
@@ -600,8 +600,16 @@ static inline TCGv gen_read_ireg(TCGv result, TCGv val, 
int shift)
 
 #ifdef QEMU_GENERATE
 #define fSTORE(NUM, SIZE, EA, SRC) MEM_STORE##SIZE(EA, SRC, insn->slot)
+#define fSTORE1(EA, SRC) MEM_STORE1(EA, SRC, insn->slot)
+#define fSTORE2(EA, SRC) MEM_STORE2(EA, SRC, insn->slot)
+#define fSTORE4(EA, SRC) MEM_STORE4(EA, SRC, insn->slot)
+#define fSTORE8(EA, SRC) MEM_STORE8(EA, SRC, insn->slot)
 #else
 #define fSTORE(NUM, SIZE, EA, SRC) MEM_STORE##SIZE(EA, SRC, slot)
+#define fSTORE1(EA, SRC) MEM_STORE1(EA, SRC, slot)
+#define fSTORE2(EA, SRC) MEM_STORE2(EA, SRC, slot)
+#define fSTORE4(EA, SRC) MEM_STORE4(EA, SRC, slot)
+#define fSTORE8(EA, SRC) MEM_STORE8(EA, SRC, slot)
 #endif
 
 #ifdef QEMU_GENERATE
diff --git a/target/hexagon/attribs_def.h.inc b/target/hexagon/attribs_def.h.inc
index dc890a557f..9c19e08dd7 100644
--- a/target/hexagon/attribs_def.h.inc
+++ b/target/hexagon/attribs_def.h.inc
@@ -38,6 +38,10 @@ DEF_ATTRIB(SUBINSN, "sub-instruction", "", "")
 /* Load and Store attributes */
 DEF_ATTRIB(LOAD, "Loads from memory", "", "")
 DEF_ATTRIB(STORE, "Stores to memory", "", "")
+DEF_ATTRIB(STORE_SIZE1, "Stores 1 byte to memory", "", "")
+DEF_ATTRIB(STORE_SIZE2, "Stores 2 bytes to memory", "", "")
+DEF_ATTRIB(STORE_SIZE4, "Stores 4 bytes to memory", "", "")
+DEF_ATTRIB(STORE_SIZE8, "Stores 8 bytes to memory", "", "")
 DEF_ATTRIB(MEMLIKE, "Memory-like instruction", "", "")
 DEF_ATTRIB(MEMLIKE_PACKET_RULES, "follows Memory-like packet rules", "", "")
 
diff --git a/target/hexagon/gen_semantics.c b/target/hexagon/gen_semantics.c
index 4a2bdd70e9..b4bbd66006 100644
--- a/target/hexagon/gen_semantics.c
+++ b/target/hexagon/gen_semantics.c
@@ -78,6 +78,10 @@ int main(int argc, char *argv[])
  ")\n", \
 #TAG, STRINGIZE(ATTRIBS)); \
 } while (0);
+
+/* Change the store macros so we can track the size during translation */
+#define fSTORE(NUM, SIZE, EA, SRC) fSTORE##SIZE(EA, SRC)
+
 #include "imported/allidefs.def"
 #undef Q6INSN
 #undef EXTINSN
@@ -101,6 +105,28 @@ int main(int argc, char *argv[])
  ")\n", \
 #MNAME, STRINGIZE(BEH), STRINGIZE(ATTRS));
 #include "imported/macros.def"
+
+/* These macros give the size of the store used during tra

[PULL 00/43] target/loongarch: Initial system support

2022-06-06 Thread Richard Henderson
Thanks for the patience, guys.


r~


The following changes since commit 57c9363c452af64fe058aa946cc923eae7f7ad33:

  Merge tag 'for-upstream' of https://gitlab.com/bonzini/qemu into staging 
(2022-06-06 07:57:14 -0700)

are available in the Git repository at:

  https://gitlab.com/rth7680/qemu.git tags/pull-la-20220606

for you to fetch changes up to 34bb43b074906a7cd642ccf03e2b7bea63b53d95:

  target/loongarch: 'make check-tcg' support (2022-06-06 18:14:13 +)


Initial LoongArch support.


Song Gao (18):
  target/loongarch: Add README
  target/loongarch: Add core definition
  target/loongarch: Add main translation routines
  target/loongarch: Add fixed point arithmetic instruction translation
  target/loongarch: Add fixed point shift instruction translation
  target/loongarch: Add fixed point bit instruction translation
  target/loongarch: Add fixed point load/store instruction translation
  target/loongarch: Add fixed point atomic instruction translation
  target/loongarch: Add fixed point extra instruction translation
  target/loongarch: Add floating point arithmetic instruction translation
  target/loongarch: Add floating point comparison instruction translation
  target/loongarch: Add floating point conversion instruction translation
  target/loongarch: Add floating point move instruction translation
  target/loongarch: Add floating point load/store instruction translation
  target/loongarch: Add branch instruction translation
  target/loongarch: Add disassembler
  target/loongarch: Add target build suport
  target/loongarch: 'make check-tcg' support

Xiaojuan Yang (25):
  target/loongarch: Add system emulation introduction
  target/loongarch: Add CSRs definition
  target/loongarch: Add basic vmstate description of CPU.
  target/loongarch: Implement qmp_query_cpu_definitions()
  target/loongarch: Add MMU support for LoongArch CPU.
  target/loongarch: Add LoongArch interrupt and exception handle
  target/loongarch: Add constant timer support
  target/loongarch: Add LoongArch CSR instruction
  target/loongarch: Add LoongArch IOCSR instruction
  target/loongarch: Add TLB instruction support
  target/loongarch: Add other core instructions support
  target/loongarch: Add timer related instructions support.
  hw/loongarch: Add support loongson3 virt machine type.
  hw/loongarch: Add LoongArch ipi interrupt support(IPI)
  hw/intc: Add LoongArch ls7a interrupt controller support(PCH-PIC)
  hw/intc: Add LoongArch ls7a msi interrupt controller support(PCH-MSI)
  hw/intc: Add LoongArch extioi interrupt controller(EIOINTC)
  hw/loongarch: Add irq hierarchy for the system
  Enable common virtio pci support for LoongArch
  hw/loongarch: Add some devices support for 3A5000.
  hw/loongarch: Add LoongArch ls7a rtc device support
  hw/loongarch: Add LoongArch load elf function.
  hw/loongarch: Add LoongArch virt power manager support.
  target/loongarch: Add gdb support.
  tests/tcg/loongarch64: Add hello/memory test in loongarch64 system

 docs/system/loongarch/loongson3.rst|  41 +
 configure  |   1 +
 configs/devices/loongarch64-softmmu/default.mak|   3 +
 configs/targets/loongarch64-softmmu.mak|   4 +
 meson.build|   1 +
 qapi/machine-target.json   |   6 +-
 qapi/machine.json  |   2 +-
 include/disas/dis-asm.h|   2 +
 include/exec/poison.h  |   2 +
 include/hw/intc/loongarch_extioi.h |  62 ++
 include/hw/intc/loongarch_ipi.h|  52 ++
 include/hw/intc/loongarch_pch_msi.h|  20 +
 include/hw/intc/loongarch_pch_pic.h|  69 ++
 include/hw/loongarch/virt.h|  33 +
 include/hw/pci-host/ls7a.h |  44 ++
 include/sysemu/arch_init.h |   1 +
 target/loongarch/cpu-csr.h | 208 +
 target/loongarch/cpu-param.h   |  18 +
 target/loongarch/cpu.h | 391 ++
 target/loongarch/helper.h  | 130 
 target/loongarch/internals.h   |  56 ++
 target/loongarch/translate.h   |  45 ++
 tests/tcg/loongarch64/system/regdef.h  |  86 ++
 target/loongarch/insns.decode  | 486 
 hw/intc/loongarch_extioi.c | 312 
 hw/intc/loongarch_ipi.c| 242 ++
 hw/intc/loongarch_pch_msi.c|  73 +

[PULL 01/43] target/loongarch: Add README

2022-06-06 Thread Richard Henderson
From: Song Gao 

This patch gives an introduction to the LoongArch target.

Signed-off-by: Song Gao 
Signed-off-by: Xiaojuan Yang 
Reviewed-by: Richard Henderson 
Message-Id: <20220606124333.2060567-2-yangxiaoj...@loongson.cn>
Signed-off-by: Richard Henderson 
---
 MAINTAINERS |  6 ++
 target/loongarch/README | 10 ++
 2 files changed, 16 insertions(+)
 create mode 100644 target/loongarch/README

diff --git a/MAINTAINERS b/MAINTAINERS
index 5fe8f7eca2..319a5d805a 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -212,6 +212,12 @@ S: Maintained
 F: target/hppa/
 F: disas/hppa.c
 
+LoongArch TCG CPUs
+M: Song Gao 
+M: Xiaojuan Yang 
+S: Maintained
+F: target/loongarch/
+
 M68K TCG CPUs
 M: Laurent Vivier 
 S: Maintained
diff --git a/target/loongarch/README b/target/loongarch/README
new file mode 100644
index 00..de141c1a58
--- /dev/null
+++ b/target/loongarch/README
@@ -0,0 +1,10 @@
+- Introduction
+
+  LoongArch is the general processor architecture of Loongson.
+
+  The following versions of the LoongArch core are supported
+core: 3A5000
+
https://github.com/loongson/LoongArch-Documentation/releases/download/2021.08.17/LoongArch-Vol1-v1.00-EN.pdf
+
+  We can get the latest loongarch documents at 
https://github.com/loongson/LoongArch-Documentation/tags.
+
-- 
2.34.1




[PULL 07/43] target/loongarch: Add fixed point load/store instruction translation

2022-06-06 Thread Richard Henderson
From: Song Gao 

This includes:
- LD.{B[U]/H[U]/W[U]/D}, ST.{B/H/W/D}
- LDX.{B[U]/H[U]/W[U]/D}, STX.{B/H/W/D}
- LDPTR.{W/D}, STPTR.{W/D}
- PRELD
- LD{GT/LE}.{B/H/W/D}, ST{GT/LE}.{B/H/W/D}
- DBAR, IBAR

Signed-off-by: Song Gao 
Signed-off-by: Xiaojuan Yang 
Reviewed-by: Richard Henderson 
Message-Id: <20220606124333.2060567-8-yangxiaoj...@loongson.cn>
Signed-off-by: Richard Henderson 
---
 target/loongarch/helper.h |   3 +
 target/loongarch/insns.decode |  55 +
 target/loongarch/op_helper.c  |  15 ++
 target/loongarch/translate.c  |   6 +
 .../loongarch/insn_trans/trans_memory.c.inc   | 229 ++
 5 files changed, 308 insertions(+)
 create mode 100644 target/loongarch/insn_trans/trans_memory.c.inc

diff --git a/target/loongarch/helper.h b/target/loongarch/helper.h
index 04e0245d5e..100622bfc2 100644
--- a/target/loongarch/helper.h
+++ b/target/loongarch/helper.h
@@ -8,3 +8,6 @@ DEF_HELPER_2(raise_exception, noreturn, env, i32)
 DEF_HELPER_FLAGS_1(bitrev_w, TCG_CALL_NO_RWG_SE, tl, tl)
 DEF_HELPER_FLAGS_1(bitrev_d, TCG_CALL_NO_RWG_SE, tl, tl)
 DEF_HELPER_FLAGS_1(bitswap, TCG_CALL_NO_RWG_SE, tl, tl)
+
+DEF_HELPER_FLAGS_3(asrtle_d, TCG_CALL_NO_WG, void, env, tl, tl)
+DEF_HELPER_FLAGS_3(asrtgt_d, TCG_CALL_NO_WG, void, env, tl, tl)
diff --git a/target/loongarch/insns.decode b/target/loongarch/insns.decode
index b0bed5531b..1156e6965c 100644
--- a/target/loongarch/insns.decode
+++ b/target/loongarch/insns.decode
@@ -8,21 +8,25 @@
 #
 # Fields
 #
+%i14s2 10:s14   !function=shl_2
 %sa2p1 15:2 !function=plus_1
 
 #
 # Argument sets
 #
+&iimm
 &r_i  rd imm
 &rr   rd rj
 &rrr  rd rj rk
 &rr_i rd rj imm
+&hint_r_i hint rj imm
 &rrr_sa   rd rj rk sa
 &rr_ms_ls rd rj ms ls
 
 #
 # Formats
 #
+@i15     . imm:15&i
 @rr     . . rj:5 rd:5&rr
 @rrr     . rk:5 rj:5 rd:5&rrr
 @r_i20   ... imm:s20 rd:5&r_i
@@ -30,7 +34,9 @@
 @rr_ui6   imm:6 rj:5 rd:5&rr_i
 @rr_i12  .. imm:s12 rj:5 rd:5&rr_i
 @rr_ui12  .. imm:12 rj:5 rd:5&rr_i
+@rr_i14s2    .. rj:5 rd:5&rr_i imm=%i14s2
 @rr_i16  .. imm:s16 rj:5 rd:5&rr_i
+@hint_r_i12    .. imm:s12 rj:5 hint:5&hint_r_i
 @rrr_sa2p1  ... .. rk:5 rj:5 rd:5&rrr_sa  sa=%sa2p1
 @rrr_sa2  ... sa:2 rk:5 rj:5 rd:5&rrr_sa
 @rrr_sa3   .. sa:3 rk:5 rj:5 rd:5&rrr_sa
@@ -138,3 +144,52 @@ bstrins_w    011 . 0 . . .   
@rr_2bw
 bstrpick_w   011 . 1 . . .   @rr_2bw
 bstrins_d    10 .. .. . .@rr_2bd
 bstrpick_d   11 .. .. . .@rr_2bd
+
+#
+# Fixed point load/store instruction
+#
+ld_b0010 10  . . @rr_i12
+ld_h0010 11  . . @rr_i12
+ld_w0010 100010  . . @rr_i12
+ld_d0010 100011  . . @rr_i12
+st_b0010 100100  . . @rr_i12
+st_h0010 100101  . . @rr_i12
+st_w0010 100110  . . @rr_i12
+st_d0010 100111  . . @rr_i12
+ld_bu   0010 101000  . . @rr_i12
+ld_hu   0010 101001  . . @rr_i12
+ld_wu   0010 101010  . . @rr_i12
+ldx_b   0011 1000 0 . . .@rrr
+ldx_h   0011 1000 01000 . . .@rrr
+ldx_w   0011 1000 1 . . .@rrr
+ldx_d   0011 1000 11000 . . .@rrr
+stx_b   0011 1001 0 . . .@rrr
+stx_h   0011 1001 01000 . . .@rrr
+stx_w   0011 1001 1 . . .@rrr
+stx_d   0011 1001 11000 . . .@rrr
+ldx_bu  0011 1010 0 . . .@rrr
+ldx_hu  0011 1010 01000 . . .@rrr
+ldx_wu  0011 1010 1 . . .@rrr
+preld   0010 101011  . . @hint_r_i12
+dbar0011 1111 00100 ...  @i15
+ibar0011 1111 00101 ...  @i15
+ldptr_w 0010 0100 .. . . @rr_i14s2
+stptr_w 0010 0101 .. . . @rr_i14s2
+ldptr_d 0010 0110 .. . . @rr_i14s2
+stptr_d 0010 0111 .. . . @rr_i14s2
+ldgt_b  0011 1111 1 ...

[PULL 03/43] target/loongarch: Add main translation routines

2022-06-06 Thread Richard Henderson
From: Song Gao 

This patch adds main translation routines and
basic functions for translation.

Signed-off-by: Song Gao 
Signed-off-by: Xiaojuan Yang 
Reviewed-by: Richard Henderson 
Message-Id: <20220606124333.2060567-4-yangxiaoj...@loongson.cn>
Signed-off-by: Richard Henderson 
---
 target/loongarch/helper.h|   6 ++
 target/loongarch/translate.h |  26 ++
 target/loongarch/op_helper.c |  21 +
 target/loongarch/translate.c | 161 +++
 4 files changed, 214 insertions(+)
 create mode 100644 target/loongarch/helper.h
 create mode 100644 target/loongarch/translate.h
 create mode 100644 target/loongarch/op_helper.c
 create mode 100644 target/loongarch/translate.c

diff --git a/target/loongarch/helper.h b/target/loongarch/helper.h
new file mode 100644
index 00..eb771c0628
--- /dev/null
+++ b/target/loongarch/helper.h
@@ -0,0 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ */
+
+DEF_HELPER_2(raise_exception, noreturn, env, i32)
diff --git a/target/loongarch/translate.h b/target/loongarch/translate.h
new file mode 100644
index 00..6cc7f1a7cd
--- /dev/null
+++ b/target/loongarch/translate.h
@@ -0,0 +1,26 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * LoongArch translation routines.
+ *
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ */
+
+#ifndef TARGET_LOONGARCH_TRANSLATE_H
+#define TARGET_LOONGARCH_TRANSLATE_H
+
+#include "exec/translator.h"
+
+typedef struct DisasContext {
+DisasContextBase base;
+target_ulong page_start;
+uint32_t opcode;
+int mem_idx;
+} DisasContext;
+
+void generate_exception(DisasContext *ctx, int excp);
+
+extern TCGv cpu_gpr[32], cpu_pc;
+extern TCGv_i32 cpu_fscr0;
+extern TCGv_i64 cpu_fpr[32];
+
+#endif
diff --git a/target/loongarch/op_helper.c b/target/loongarch/op_helper.c
new file mode 100644
index 00..903810951e
--- /dev/null
+++ b/target/loongarch/op_helper.c
@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * LoongArch emulation helpers for QEMU.
+ *
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/main-loop.h"
+#include "cpu.h"
+#include "qemu/host-utils.h"
+#include "exec/helper-proto.h"
+#include "exec/exec-all.h"
+#include "exec/cpu_ldst.h"
+#include "internals.h"
+
+/* Exceptions helpers */
+void helper_raise_exception(CPULoongArchState *env, uint32_t exception)
+{
+do_raise_exception(env, exception, GETPC());
+}
diff --git a/target/loongarch/translate.c b/target/loongarch/translate.c
new file mode 100644
index 00..332a6d2d58
--- /dev/null
+++ b/target/loongarch/translate.c
@@ -0,0 +1,161 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * LoongArch emulation for QEMU - main translation routines.
+ *
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ */
+
+#include "qemu/osdep.h"
+#include "cpu.h"
+#include "tcg/tcg-op.h"
+#include "exec/translator.h"
+#include "exec/helper-proto.h"
+#include "exec/helper-gen.h"
+
+#include "exec/translator.h"
+#include "exec/log.h"
+#include "qemu/qemu-print.h"
+#include "translate.h"
+#include "internals.h"
+
+/* Global register indices */
+TCGv cpu_gpr[32], cpu_pc;
+static TCGv cpu_lladdr, cpu_llval;
+TCGv_i32 cpu_fcsr0;
+TCGv_i64 cpu_fpr[32];
+
+#define DISAS_STOP   DISAS_TARGET_0
+
+void generate_exception(DisasContext *ctx, int excp)
+{
+tcg_gen_movi_tl(cpu_pc, ctx->base.pc_next);
+gen_helper_raise_exception(cpu_env, tcg_constant_i32(excp));
+ctx->base.is_jmp = DISAS_NORETURN;
+}
+
+static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
+{
+if (translator_use_goto_tb(&ctx->base, dest)) {
+tcg_gen_goto_tb(n);
+tcg_gen_movi_tl(cpu_pc, dest);
+tcg_gen_exit_tb(ctx->base.tb, n);
+} else {
+tcg_gen_movi_tl(cpu_pc, dest);
+tcg_gen_lookup_and_goto_ptr();
+}
+}
+
+static void loongarch_tr_init_disas_context(DisasContextBase *dcbase,
+CPUState *cs)
+{
+int64_t bound;
+DisasContext *ctx = container_of(dcbase, DisasContext, base);
+
+ctx->page_start = ctx->base.pc_first & TARGET_PAGE_MASK;
+ctx->mem_idx = ctx->base.tb->flags;
+
+/* Bound the number of insns to execute to those left on the page.  */
+bound = -(ctx->base.pc_first | TARGET_PAGE_MASK) / 4;
+ctx->base.max_insns = MIN(ctx->base.max_insns, bound);
+}
+
+static void loongarch_tr_tb_start(DisasContextBase *dcbase, CPUState *cs)
+{
+}
+
+static void loongarch_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
+{
+DisasContext *ctx = container_of(dcbase, DisasContext, base);
+
+tcg_gen_insn_start(ctx->base.pc_next);
+}
+
+static void loongarch_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
+{
+CPULoongArchState *env = cs->env_ptr;
+DisasContext *ctx = container_of(dcbase, DisasContext, base);
+
+ct

[PULL 02/43] target/loongarch: Add core definition

2022-06-06 Thread Richard Henderson
From: Song Gao 

This patch adds target state header, target definitions
and initialization routines.

Signed-off-by: Song Gao 
Signed-off-by: Xiaojuan Yang 
Reviewed-by: Richard Henderson 
Reviewed-by: Philippe Mathieu-Daudé 
Message-Id: <20220606124333.2060567-3-yangxiaoj...@loongson.cn>
Signed-off-by: Richard Henderson 
---
 target/loongarch/cpu-param.h |  18 ++
 target/loongarch/cpu.h   | 243 ++
 target/loongarch/internals.h |  21 +++
 target/loongarch/cpu.c   | 324 +++
 4 files changed, 606 insertions(+)
 create mode 100644 target/loongarch/cpu-param.h
 create mode 100644 target/loongarch/cpu.h
 create mode 100644 target/loongarch/internals.h
 create mode 100644 target/loongarch/cpu.c

diff --git a/target/loongarch/cpu-param.h b/target/loongarch/cpu-param.h
new file mode 100644
index 00..9a769b67e0
--- /dev/null
+++ b/target/loongarch/cpu-param.h
@@ -0,0 +1,18 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * LoongArch CPU parameters for QEMU.
+ *
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ */
+
+#ifndef LOONGARCH_CPU_PARAM_H
+#define LOONGARCH_CPU_PARAM_H
+
+#define TARGET_LONG_BITS 64
+#define TARGET_PHYS_ADDR_SPACE_BITS 48
+#define TARGET_VIRT_ADDR_SPACE_BITS 48
+
+#define TARGET_PAGE_BITS 14
+#define NB_MMU_MODES 4
+
+#endif
diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h
new file mode 100644
index 00..3e8ba46377
--- /dev/null
+++ b/target/loongarch/cpu.h
@@ -0,0 +1,243 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * QEMU LoongArch CPU
+ *
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ */
+
+#ifndef LOONGARCH_CPU_H
+#define LOONGARCH_CPU_H
+
+#include "exec/cpu-defs.h"
+#include "fpu/softfloat-types.h"
+#include "hw/registerfields.h"
+
+#define TCG_GUEST_DEFAULT_MO (0)
+
+#define FCSR0_M10x1f /* FCSR1 mask, Enables */
+#define FCSR0_M20x1f1f   /* FCSR2 mask, Cause and Flags */
+#define FCSR0_M30x300/* FCSR3 mask, Round Mode */
+#define FCSR0_RM8/* Round Mode bit num on fcsr0 */
+
+FIELD(FCSR0, ENABLES, 0, 5)
+FIELD(FCSR0, RM, 8, 2)
+FIELD(FCSR0, FLAGS, 16, 5)
+FIELD(FCSR0, CAUSE, 24, 5)
+
+#define GET_FP_CAUSE(REG)  FIELD_EX32(REG, FCSR0, CAUSE)
+#define SET_FP_CAUSE(REG, V)   FIELD_DP32(REG, FCSR0, CAUSE, V)
+#define GET_FP_ENABLES(REG)FIELD_EX32(REG, FCSR0, ENABLES)
+#define SET_FP_ENABLES(REG, V) FIELD_DP32(REG, FCSR0, ENABLES, V)
+#define GET_FP_FLAGS(REG)  FIELD_EX32(REG, FCSR0, FLAGS)
+#define SET_FP_FLAGS(REG, V)   FIELD_DP32(REG, FCSR0, FLAGS, V)
+#define UPDATE_FP_FLAGS(REG, V) \
+do { \
+(REG) |= FIELD_DP32(0, FCSR0, FLAGS, V); \
+} while (0)
+
+#define FP_INEXACT1
+#define FP_UNDERFLOW  2
+#define FP_OVERFLOW   4
+#define FP_DIV0   8
+#define FP_INVALID16
+
+#define  EXCCODE_EXTERNAL_INT   64   /* plus external interrupt number */
+#define  EXCCODE_INT 0
+#define  EXCCODE_PIL 1
+#define  EXCCODE_PIS 2
+#define  EXCCODE_PIF 3
+#define  EXCCODE_PME 4
+#define  EXCCODE_PNR 5
+#define  EXCCODE_PNX 6
+#define  EXCCODE_PPI 7
+#define  EXCCODE_ADEF8 /* Different exception subcode */
+#define  EXCCODE_ADEM8
+#define  EXCCODE_ALE 9
+#define  EXCCODE_BCE 10
+#define  EXCCODE_SYS 11
+#define  EXCCODE_BRK 12
+#define  EXCCODE_INE 13
+#define  EXCCODE_IPE 14
+#define  EXCCODE_FPD 15
+#define  EXCCODE_SXD 16
+#define  EXCCODE_ASXD17
+#define  EXCCODE_FPE 18 /* Different exception subcode */
+#define  EXCCODE_VFPE18
+#define  EXCCODE_WPEF19 /* Different exception subcode */
+#define  EXCCODE_WPEM19
+#define  EXCCODE_BTD 20
+#define  EXCCODE_BTE 21
+#define  EXCCODE_DBP 26 /* Reserved subcode used for debug */
+
+/* cpucfg[0] bits */
+FIELD(CPUCFG0, PRID, 0, 32)
+
+/* cpucfg[1] bits */
+FIELD(CPUCFG1, ARCH, 0, 2)
+FIELD(CPUCFG1, PGMMU, 2, 1)
+FIELD(CPUCFG1, IOCSR, 3, 1)
+FIELD(CPUCFG1, PALEN, 4, 8)
+FIELD(CPUCFG1, VALEN, 12, 8)
+FIELD(CPUCFG1, UAL, 20, 1)
+FIELD(CPUCFG1, RI, 21, 1)
+FIELD(CPUCFG1, EP, 22, 1)
+FIELD(CPUCFG1, RPLV, 23, 1)
+FIELD(CPUCFG1, HP, 24, 1)
+FIELD(CPUCFG1, IOCSR_BRD, 25, 1)
+FIELD(CPUCFG1, MSG_INT, 26, 1)
+
+/* cpucfg[2] bits */
+FIELD(CPUCFG2, FP, 0, 1)
+FIELD(CPUCFG2, FP_SP, 1, 1)
+FIELD(CPUCFG2, FP_DP, 2, 1)
+FIELD(CPUCFG2, FP_VER, 3, 3)
+FIELD(CPUCFG2, LSX, 6, 1)
+FIELD(CPUCFG2, LASX, 7, 1)
+FIELD(CPUCFG2, COMPLEX, 8, 1)
+FIELD(CPUCFG2, CRYPTO, 9, 1)
+FIELD(CPUCFG2, LVZ, 10, 1)
+FIELD(CPUCFG2, LVZ_VER, 11, 3)
+FIELD(CPUCFG2, LLFTP, 14, 1)
+FIELD(CPUCFG2, LLFTP_VER, 15, 3)
+FIELD(CPUCFG2, LBT_X86, 18, 1)
+FIELD(

[PULL 09/43] target/loongarch: Add fixed point extra instruction translation

2022-06-06 Thread Richard Henderson
From: Song Gao 

This includes:
- CRC[C].W.{B/H/W/D}.W
- SYSCALL
- BREAK
- ASRT{LE/GT}.D
- RDTIME{L/H}.W, RDTIME.D
- CPUCFG

Signed-off-by: Song Gao 
Signed-off-by: Xiaojuan Yang 
Reviewed-by: Richard Henderson 
Message-Id: <20220606124333.2060567-10-yangxiaoj...@loongson.cn>
Signed-off-by: Richard Henderson 
---
 target/loongarch/helper.h |  4 ++
 target/loongarch/insns.decode | 19 ++
 target/loongarch/op_helper.c  | 26 +++
 target/loongarch/translate.c  |  1 +
 target/loongarch/insn_trans/trans_extra.c.inc | 68 +++
 5 files changed, 118 insertions(+)
 create mode 100644 target/loongarch/insn_trans/trans_extra.c.inc

diff --git a/target/loongarch/helper.h b/target/loongarch/helper.h
index 100622bfc2..638c2efc51 100644
--- a/target/loongarch/helper.h
+++ b/target/loongarch/helper.h
@@ -11,3 +11,7 @@ DEF_HELPER_FLAGS_1(bitswap, TCG_CALL_NO_RWG_SE, tl, tl)
 
 DEF_HELPER_FLAGS_3(asrtle_d, TCG_CALL_NO_WG, void, env, tl, tl)
 DEF_HELPER_FLAGS_3(asrtgt_d, TCG_CALL_NO_WG, void, env, tl, tl)
+
+DEF_HELPER_FLAGS_3(crc32, TCG_CALL_NO_RWG_SE, tl, tl, tl, tl)
+DEF_HELPER_FLAGS_3(crc32c, TCG_CALL_NO_RWG_SE, tl, tl, tl, tl)
+DEF_HELPER_FLAGS_2(cpucfg, TCG_CALL_NO_RWG_SE, tl, env, tl)
diff --git a/target/loongarch/insns.decode b/target/loongarch/insns.decode
index 8d247aa68c..98774dbddb 100644
--- a/target/loongarch/insns.decode
+++ b/target/loongarch/insns.decode
@@ -17,6 +17,7 @@
 &iimm
 &r_i  rd imm
 &rr   rd rj
+&rr_jkrj rk
 &rrr  rd rj rk
 &rr_i rd rj imm
 &hint_r_i hint rj imm
@@ -28,6 +29,7 @@
 #
 @i15     . imm:15&i
 @rr     . . rj:5 rd:5&rr
+@rr_jk  . rk:5 rj:5 .&rr_jk
 @rrr     . rk:5 rj:5 rd:5&rrr
 @r_i20   ... imm:s20 rd:5&r_i
 @rr_ui5     . imm:5 rj:5 rd:5&rr_i
@@ -237,3 +239,20 @@ ammax_db_wu 0011 1111 0 . . .
@rrr
 ammax_db_du 0011 1111 1 . . .@rrr
 ammin_db_wu 0011 1111 00010 . . .@rrr
 ammin_db_du 0011 1111 00011 . . .@rrr
+
+#
+# Fixed point extra instruction
+#
+crc_w_b_w    0010 01000 . . .@rrr
+crc_w_h_w    0010 01001 . . .@rrr
+crc_w_w_w    0010 01010 . . .@rrr
+crc_w_d_w    0010 01011 . . .@rrr
+crcc_w_b_w   0010 01100 . . .@rrr
+crcc_w_h_w   0010 01101 . . .@rrr
+crcc_w_w_w   0010 01110 . . .@rrr
+crcc_w_d_w   0010 0 . . .@rrr
+break    0010 10100 ...  @i15
+syscall  0010 10110 ...  @i15
+asrtle_d  00010 . . 0@rr_jk
+asrtgt_d  00011 . . 0@rr_jk
+cpucfg    0 11011 . .@rr
diff --git a/target/loongarch/op_helper.c b/target/loongarch/op_helper.c
index bd2db783c9..18e565ce7f 100644
--- a/target/loongarch/op_helper.c
+++ b/target/loongarch/op_helper.c
@@ -13,6 +13,8 @@
 #include "exec/exec-all.h"
 #include "exec/cpu_ldst.h"
 #include "internals.h"
+#include "qemu/crc32c.h"
+#include 
 
 /* Exceptions helpers */
 void helper_raise_exception(CPULoongArchState *env, uint32_t exception)
@@ -55,3 +57,27 @@ void helper_asrtgt_d(CPULoongArchState *env, target_ulong 
rj, target_ulong rk)
 do_raise_exception(env, EXCCODE_ADEM, GETPC());
 }
 }
+
+target_ulong helper_crc32(target_ulong val, target_ulong m, uint64_t sz)
+{
+uint8_t buf[8];
+target_ulong mask = ((sz * 8) == 64) ? -1ULL : ((1ULL << (sz * 8)) - 1);
+
+m &= mask;
+stq_le_p(buf, m);
+return (int32_t) (crc32(val ^ 0x, buf, sz) ^ 0x);
+}
+
+target_ulong helper_crc32c(target_ulong val, target_ulong m, uint64_t sz)
+{
+uint8_t buf[8];
+target_ulong mask = ((sz * 8) == 64) ? -1ULL : ((1ULL << (sz * 8)) - 1);
+m &= mask;
+stq_le_p(buf, m);
+return (int32_t) (crc32c(val, buf, sz) ^ 0x);
+}
+
+target_ulong helper_cpucfg(CPULoongArchState *env, target_ulong rj)
+{
+return rj > 21 ? 0 : env->cpucfg[rj];
+}
diff --git a/target/loongarch/translate.c b/target/loongarch/translate.c
index 01791bf1a2..b946dc4d5f 100644
--- a/target/loongarch/translate.c
+++ b/target/loongarch/translate.c
@@ -155,6 +155,7 @@ static void gen_set_gpr(int reg_num, TCGv t, DisasExtend 
dst_ext)
 #include "insn_trans/trans_bit.c.inc"
 #include "insn_trans/trans_memory.c.inc"
 #include "insn_trans/trans_atomic.c.inc"
+#include "insn_trans/trans_extra.c.inc"
 
 static void loongarch_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
 {
diff --git a/target/loongarch/ins

[PULL 11/43] target/loongarch: Add floating point comparison instruction translation

2022-06-06 Thread Richard Henderson
From: Song Gao 

This includes:
- FCMP.cond.{S/D}

Signed-off-by: Song Gao 
Signed-off-by: Xiaojuan Yang 
Reviewed-by: Richard Henderson 
Message-Id: <20220606124333.2060567-12-yangxiaoj...@loongson.cn>
Signed-off-by: Richard Henderson 
---
 target/loongarch/helper.h|  9 +++
 target/loongarch/internals.h |  5 ++
 target/loongarch/insns.decode|  8 +++
 target/loongarch/fpu_helper.c| 60 
 target/loongarch/translate.c |  1 +
 target/loongarch/insn_trans/trans_fcmp.c.inc | 56 ++
 6 files changed, 139 insertions(+)
 create mode 100644 target/loongarch/insn_trans/trans_fcmp.c.inc

diff --git a/target/loongarch/helper.h b/target/loongarch/helper.h
index 840bad9b2f..25a891bf8b 100644
--- a/target/loongarch/helper.h
+++ b/target/loongarch/helper.h
@@ -52,3 +52,12 @@ DEF_HELPER_FLAGS_2(frecip_d, TCG_CALL_NO_WG, i64, env, i64)
 
 DEF_HELPER_FLAGS_2(fclass_s, TCG_CALL_NO_RWG_SE, i64, env, i64)
 DEF_HELPER_FLAGS_2(fclass_d, TCG_CALL_NO_RWG_SE, i64, env, i64)
+
+/* fcmp.cXXX.s */
+DEF_HELPER_4(fcmp_c_s, i64, env, i64, i64, i32)
+/* fcmp.sXXX.s */
+DEF_HELPER_4(fcmp_s_s, i64, env, i64, i64, i32)
+/* fcmp.cXXX.d */
+DEF_HELPER_4(fcmp_c_d, i64, env, i64, i64, i32)
+/* fcmp.sXXX.d */
+DEF_HELPER_4(fcmp_s_d, i64, env, i64, i64, i32)
diff --git a/target/loongarch/internals.h b/target/loongarch/internals.h
index 43b865ec21..1a3b39e0be 100644
--- a/target/loongarch/internals.h
+++ b/target/loongarch/internals.h
@@ -8,6 +8,11 @@
 #ifndef LOONGARCH_INTERNALS_H
 #define LOONGARCH_INTERNALS_H
 
+#define FCMP_LT   0b0001  /* fp0 < fp1 */
+#define FCMP_EQ   0b0010  /* fp0 = fp1 */
+#define FCMP_UN   0b0100  /* unordered */
+#define FCMP_GT   0b1000  /* fp0 > fp1 */
+
 void loongarch_translate_init(void);
 
 void loongarch_cpu_dump_state(CPUState *cpu, FILE *f, int flags);
diff --git a/target/loongarch/insns.decode b/target/loongarch/insns.decode
index 6455e09ebe..d7ed80b0b9 100644
--- a/target/loongarch/insns.decode
+++ b/target/loongarch/insns.decode
@@ -26,6 +26,7 @@
 &ff   fd fj
 &fff  fd fj fk
 & fd fj fk fa
+&cff_fcondcd fj fk fcond
 
 #
 # Formats
@@ -50,6 +51,7 @@
 @ff     . . fj:5 fd:5&ff
 @fff     . fk:5 fj:5 fd:5&fff
 @     fa:5 fk:5 fj:5 fd:5&
+@cff_fcond  fcond:5 fk:5 fj:5 .. cd:3&cff_fcond
 
 #
 # Fixed point arithmetic operation instruction
@@ -308,3 +310,9 @@ fcopysign_s  00010001 00101 . . .
@fff
 fcopysign_d  00010001 00110 . . .@fff
 fclass_s 00010001 01000 01101 . .@ff
 fclass_d 00010001 01000 01110 . .@ff
+
+#
+# Floating point compare instruction
+#
+fcmp_cond_s  1101 . . . 00 ...   @cff_fcond
+fcmp_cond_d  1110 . . . 00 ...   @cff_fcond
diff --git a/target/loongarch/fpu_helper.c b/target/loongarch/fpu_helper.c
index d7442cc188..1e514cce74 100644
--- a/target/loongarch/fpu_helper.c
+++ b/target/loongarch/fpu_helper.c
@@ -401,3 +401,63 @@ uint64_t helper_fmuladd_d(CPULoongArchState *env, uint64_t 
fj,
 update_fcsr0(env, GETPC());
 return fd;
 }
+
+static uint64_t fcmp_common(CPULoongArchState *env, FloatRelation cmp,
+uint32_t flags)
+{
+bool ret;
+
+switch (cmp) {
+case float_relation_less:
+ret = (flags & FCMP_LT);
+break;
+case float_relation_equal:
+ret = (flags & FCMP_EQ);
+break;
+case float_relation_greater:
+ret = (flags & FCMP_GT);
+break;
+case float_relation_unordered:
+ret = (flags & FCMP_UN);
+break;
+default:
+g_assert_not_reached();
+}
+update_fcsr0(env, GETPC());
+
+return ret;
+}
+
+/* fcmp_cXXX_s */
+uint64_t helper_fcmp_c_s(CPULoongArchState *env, uint64_t fj,
+ uint64_t fk, uint32_t flags)
+{
+FloatRelation cmp = float32_compare_quiet((uint32_t)fj,
+  (uint32_t)fk, &env->fp_status);
+return fcmp_common(env, cmp, flags);
+}
+
+/* fcmp_sXXX_s */
+uint64_t helper_fcmp_s_s(CPULoongArchState *env, uint64_t fj,
+ uint64_t fk, uint32_t flags)
+{
+FloatRelation cmp = float32_compare((uint32_t)fj,
+(uint32_t)fk, &env->fp_status);
+return fcmp_common(env, cmp, flags);
+}
+
+/* fcmp_cXXX_d */
+uint64_t helper_fcmp_c_d(CPULoongArchState *env, uint64_t fj,
+ uint64_t fk, uint32_t flags)
+{
+FloatRelation cmp = float64_compare_quiet(fj, fk, &env->fp_status);
+return fcmp_common(env, cmp, flags);
+}
+
+/* fcmp_sXXX_d */
+uint64_t helper_fcmp_s_d(CPULoongArchState *env, uint64_t fj,
+ uint64_t fk, uint32_t flags)
+{
+FloatRelation cmp = float64_comp

[PULL 06/43] target/loongarch: Add fixed point bit instruction translation

2022-06-06 Thread Richard Henderson
From: Song Gao 

This includes:
- EXT.W.{B/H}
- CL{O/Z}.{W/D}, CT{O/Z}.{W/D}
- BYTEPICK.{W/D}
- REVB.{2H/4H/2W/D}
- REVH.{2W/D}
- BITREV.{4B/8B}, BITREV.{W/D}
- BSTRINS.{W/D}, BSTRPICK.{W/D}
- MASKEQZ, MASKNEZ

Signed-off-by: Song Gao 
Signed-off-by: Xiaojuan Yang 
Reviewed-by: Richard Henderson 
Message-Id: <20220606124333.2060567-7-yangxiaoj...@loongson.cn>
Signed-off-by: Richard Henderson 
---
 target/loongarch/helper.h   |   4 +
 target/loongarch/insns.decode   |  39 
 target/loongarch/op_helper.c|  21 ++
 target/loongarch/translate.c|   1 +
 target/loongarch/insn_trans/trans_bit.c.inc | 212 
 5 files changed, 277 insertions(+)
 create mode 100644 target/loongarch/insn_trans/trans_bit.c.inc

diff --git a/target/loongarch/helper.h b/target/loongarch/helper.h
index eb771c0628..04e0245d5e 100644
--- a/target/loongarch/helper.h
+++ b/target/loongarch/helper.h
@@ -4,3 +4,7 @@
  */
 
 DEF_HELPER_2(raise_exception, noreturn, env, i32)
+
+DEF_HELPER_FLAGS_1(bitrev_w, TCG_CALL_NO_RWG_SE, tl, tl)
+DEF_HELPER_FLAGS_1(bitrev_d, TCG_CALL_NO_RWG_SE, tl, tl)
+DEF_HELPER_FLAGS_1(bitswap, TCG_CALL_NO_RWG_SE, tl, tl)
diff --git a/target/loongarch/insns.decode b/target/loongarch/insns.decode
index 673aee4be5..b0bed5531b 100644
--- a/target/loongarch/insns.decode
+++ b/target/loongarch/insns.decode
@@ -14,13 +14,16 @@
 # Argument sets
 #
 &r_i  rd imm
+&rr   rd rj
 &rrr  rd rj rk
 &rr_i rd rj imm
 &rrr_sa   rd rj rk sa
+&rr_ms_ls rd rj ms ls
 
 #
 # Formats
 #
+@rr     . . rj:5 rd:5&rr
 @rrr     . rk:5 rj:5 rd:5&rrr
 @r_i20   ... imm:s20 rd:5&r_i
 @rr_ui5     . imm:5 rj:5 rd:5&rr_i
@@ -29,6 +32,10 @@
 @rr_ui12  .. imm:12 rj:5 rd:5&rr_i
 @rr_i16  .. imm:s16 rj:5 rd:5&rr_i
 @rrr_sa2p1  ... .. rk:5 rj:5 rd:5&rrr_sa  sa=%sa2p1
+@rrr_sa2  ... sa:2 rk:5 rj:5 rd:5&rrr_sa
+@rrr_sa3   .. sa:3 rk:5 rj:5 rd:5&rrr_sa
+@rr_2bw ... ms:5 . ls:5 rj:5 rd:5&rr_ms_ls
+@rr_2bd    .. ms:6 ls:6 rj:5 rd:5&rr_ms_ls
 
 #
 # Fixed point arithmetic operation instruction
@@ -99,3 +106,35 @@ srai_w   0100 10001 . . .
@rr_ui5
 srai_d   0100 1001 .. . .@rr_ui6
 rotri_w  0100 11001 . . .@rr_ui5
 rotri_d  0100 1101 .. . .@rr_ui6
+
+#
+# Fixed point bit operation instruction
+#
+ext_w_h   0 10110 . .@rr
+ext_w_b   0 10111 . .@rr
+clo_w     0 00100 . .@rr
+clz_w     0 00101 . .@rr
+cto_w     0 00110 . .@rr
+ctz_w     0 00111 . .@rr
+clo_d     0 01000 . .@rr
+clz_d     0 01001 . .@rr
+cto_d     0 01010 . .@rr
+ctz_d     0 01011 . .@rr
+revb_2h   0 01100 . .@rr
+revb_4h   0 01101 . .@rr
+revb_2w   0 01110 . .@rr
+revb_d    0 0 . .@rr
+revh_2w   0 1 . .@rr
+revh_d    0 10001 . .@rr
+bitrev_4b     0 10010 . .@rr
+bitrev_8b     0 10011 . .@rr
+bitrev_w  0 10100 . .@rr
+bitrev_d  0 10101 . .@rr
+bytepick_w    100 .. . . .   @rrr_sa2
+bytepick_d    11 ... . . .   @rrr_sa3
+maskeqz  0001 00110 . . .@rrr
+masknez  0001 00111 . . .@rrr
+bstrins_w    011 . 0 . . .   @rr_2bw
+bstrpick_w   011 . 1 . . .   @rr_2bw
+bstrins_d    10 .. .. . .@rr_2bd
+bstrpick_d   11 .. .. . .@rr_2bd
diff --git a/target/loongarch/op_helper.c b/target/loongarch/op_helper.c
index 903810951e..f4b22c70a0 100644
--- a/target/loongarch/op_helper.c
+++ b/target/loongarch/op_helper.c
@@ -19,3 +19,24 @@ void helper_raise_exception(CPULoongArchState *env, uint32_t 
exception)
 {
 do_raise_exception(env, exception, GETPC());
 }
+
+target_ulong helper_bitrev_w(target_ulong rj)
+{
+return (int32_t)revbit32(rj);
+}
+
+target_ulong helper_bitrev_d(target_ulong rj)
+{
+return revbit64(rj);
+}
+
+target_ulon

[PULL 18/43] target/loongarch: Add system emulation introduction

2022-06-06 Thread Richard Henderson
From: Xiaojuan Yang 

Signed-off-by: Xiaojuan Yang 
Signed-off-by: Song Gao 
Reviewed-by: Richard Henderson 
Message-Id: <20220606124333.2060567-19-yangxiaoj...@loongson.cn>
Signed-off-by: Richard Henderson 
---
 docs/system/loongarch/loongson3.rst | 41 ++
 MAINTAINERS |  8 +
 target/loongarch/README | 54 +
 3 files changed, 103 insertions(+)
 create mode 100644 docs/system/loongarch/loongson3.rst

diff --git a/docs/system/loongarch/loongson3.rst 
b/docs/system/loongarch/loongson3.rst
new file mode 100644
index 00..fa3acd01c0
--- /dev/null
+++ b/docs/system/loongarch/loongson3.rst
@@ -0,0 +1,41 @@
+:orphan:
+
+==
+loongson3 virt generic platform (``virt``)
+==
+
+The ``virt`` machine use gpex host bridge, and there are some
+emulated devices on virt board, such as loongson7a RTC device,
+IOAPIC device, ACPI device and so on.
+
+Supported devices
+-
+
+The ``virt`` machine supports:
+- Gpex host bridge
+- Ls7a RTC device
+- Ls7a IOAPIC device
+- Ls7a ACPI device
+- Fw_cfg device
+- PCI/PCIe devices
+- Memory device
+- CPU device. Type: Loongson-3A5000.
+
+CPU and machine Type
+
+
+The ``qemu-system-loongarch64`` provides emulation for virt
+machine. You can specify the machine type ``virt`` and
+cpu type ``Loongson-3A5000``.
+
+Boot options
+
+
+Now the ``virt`` machine can run test program in ELF format and the
+method of compiling is in target/loongarch/README.
+
+.. code-block:: bash
+
+  $ qemu-system-loongarch64 -machine virt -m 4G -cpu Loongson-3A5000 \
+  -smp 1 -kernel hello -monitor none -display none \
+  -chardev file,path=hello.out,id=output -serial chardev:output
diff --git a/MAINTAINERS b/MAINTAINERS
index 319a5d805a..e3f875071a 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1122,6 +1122,14 @@ F: include/hw/net/lasi_82596.h
 F: include/hw/pci-host/dino.h
 F: pc-bios/hppa-firmware.img
 
+LoongArch Machines
+--
+Virt
+M: Xiaojuan Yang 
+M: Song Gao 
+S: Maintained
+F: docs/system/loongarch/loongson3.rst
+
 M68K Machines
 -
 an5206
diff --git a/target/loongarch/README b/target/loongarch/README
index de141c1a58..4dcd0f1682 100644
--- a/target/loongarch/README
+++ b/target/loongarch/README
@@ -8,3 +8,57 @@
 
   We can get the latest loongarch documents at 
https://github.com/loongson/LoongArch-Documentation/tags.
 
+
+- System emulation
+
+  Mainly emulate a virt 3A5000 board and ls7a bridge that is not exactly the 
same as the host.
+  3A5000 support multiple interrupt cascading while here we just emulate the 
extioi interrupt
+  cascading. LS7A1000 host bridge support multiple devices, such as sata, 
gmac, uart, rtc
+  and so on. But we just realize the rtc. Others use the qemu common devices. 
It does not affect
+  the general use. We also introduced the emulation of devices at 
docs/system/loongarch/loongson3.rst.
+
+  This version only supports running binary files in ELF format, and does not 
depend on BIOS and kernel file.
+  You can compile the test program with 'make & make check-tcg' and run the 
test case with the following command:
+
+  1. Install LoongArch cross-tools on X86 machines.
+
+Download cross-tools.
+
+  wget 
https://github.com/loongson/build-tools/releases/latest/download/loongarch64-clfs-20211202-cross-tools.tar.xz
+
+  tar -vxf loongarch64-clfs-20211202-cross-tools.tar.xz -C /opt
+
+Config cross-tools env.
+
+  . setenv.sh
+
+  setenv.sh:
+
+  #!/bin/sh
+  set -x
+  CC_PREFIX=/opt/cross-tools
+
+  export PATH=$CC_PREFIX/bin:$PATH
+  export LD_LIBRARY_PATH=$CC_PREFIX/lib:$LD_LIBRARY_PATH
+  export 
LD_LIBRARY_PATH=$CC_PREFIX/loongarch64-unknown-linux-gnu/lib/:$LD_LIBRARY_PATH
+  set +x
+
+  2. Test tests/tcg/multiarch.
+
+./configure --disable-rdma --disable-pvrdma --prefix=/usr  \
+--target-list="loongarch64-softmmu"  \
+--disable-libiscsi --disable-libnfs --disable-libpmem \
+--disable-glusterfs --enable-libusb --enable-usb-redir \
+--disable-opengl --disable-xen --enable-spice --disable-werror \
+--enable-debug --disable-capstone --disable-kvm --enable-profiler
+
+cd  build/
+
+make && make check-tcg
+
+or
+
+./build/qemu-system-loongarch64 -machine virt -m 4G -cpu Loongson-3A5000 
-smp 1 -kernel build/tests/tcg/loongarch64-softmmu/hello -monitor none -display 
none -chardev file,path=hello.out,id=output -serial chardev:output
+
+- Note.
+  We can get the latest LoongArch documents or LoongArch tools at 
https://github.com/loongson/
-- 
2.34.1




[PULL 05/43] target/loongarch: Add fixed point shift instruction translation

2022-06-06 Thread Richard Henderson
From: Song Gao 

This includes:
- SLL.W, SRL.W, SRA.W, ROTR.W
- SLLI.W, SRLI.W, SRAI.W, ROTRI.W
- SLL.D, SRL.D, SRA.D, ROTR.D
- SLLI.D, SRLI.D, SRAI.D, ROTRI.D

Signed-off-by: Song Gao 
Signed-off-by: Xiaojuan Yang 
Reviewed-by: Richard Henderson 
Message-Id: <20220606124333.2060567-6-yangxiaoj...@loongson.cn>
Signed-off-by: Richard Henderson 
---
 target/loongarch/insns.decode |  22 
 target/loongarch/translate.c  |   1 +
 target/loongarch/insn_trans/trans_shift.c.inc | 106 ++
 3 files changed, 129 insertions(+)
 create mode 100644 target/loongarch/insn_trans/trans_shift.c.inc

diff --git a/target/loongarch/insns.decode b/target/loongarch/insns.decode
index 8579c11984..673aee4be5 100644
--- a/target/loongarch/insns.decode
+++ b/target/loongarch/insns.decode
@@ -23,6 +23,8 @@
 #
 @rrr     . rk:5 rj:5 rd:5&rrr
 @r_i20   ... imm:s20 rd:5&r_i
+@rr_ui5     . imm:5 rj:5 rd:5&rr_i
+@rr_ui6   imm:6 rj:5 rd:5&rr_i
 @rr_i12  .. imm:s12 rj:5 rd:5&rr_i
 @rr_ui12  .. imm:12 rj:5 rd:5&rr_i
 @rr_i16  .. imm:s16 rj:5 rd:5&rr_i
@@ -77,3 +79,23 @@ addu16i_d   0001 00  . . 
@rr_i16
 andi 001101  . . @rr_ui12
 ori  001110  . . @rr_ui12
 xori 00  . . @rr_ui12
+
+#
+# Fixed point shift operation instruction
+#
+sll_w    0001 01110 . . .@rrr
+srl_w    0001 0 . . .@rrr
+sra_w    0001 1 . . .@rrr
+sll_d    0001 10001 . . .@rrr
+srl_d    0001 10010 . . .@rrr
+sra_d    0001 10011 . . .@rrr
+rotr_w   0001 10110 . . .@rrr
+rotr_d   0001 10111 . . .@rrr
+slli_w   0100 1 . . .@rr_ui5
+slli_d   0100 0001 .. . .@rr_ui6
+srli_w   0100 01001 . . .@rr_ui5
+srli_d   0100 0101 .. . .@rr_ui6
+srai_w   0100 10001 . . .@rr_ui5
+srai_d   0100 1001 .. . .@rr_ui6
+rotri_w  0100 11001 . . .@rr_ui5
+rotri_d  0100 1101 .. . .@rr_ui6
diff --git a/target/loongarch/translate.c b/target/loongarch/translate.c
index 65c7dfd3da..d5640d5d79 100644
--- a/target/loongarch/translate.c
+++ b/target/loongarch/translate.c
@@ -146,6 +146,7 @@ static void gen_set_gpr(int reg_num, TCGv t, DisasExtend 
dst_ext)
 
 #include "decode-insns.c.inc"
 #include "insn_trans/trans_arith.c.inc"
+#include "insn_trans/trans_shift.c.inc"
 
 static void loongarch_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
 {
diff --git a/target/loongarch/insn_trans/trans_shift.c.inc 
b/target/loongarch/insn_trans/trans_shift.c.inc
new file mode 100644
index 00..5260af2337
--- /dev/null
+++ b/target/loongarch/insn_trans/trans_shift.c.inc
@@ -0,0 +1,106 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ */
+
+static void gen_sll_w(TCGv dest, TCGv src1, TCGv src2)
+{
+TCGv t0 = tcg_temp_new();
+tcg_gen_andi_tl(t0, src2, 0x1f);
+tcg_gen_shl_tl(dest, src1, t0);
+tcg_temp_free(t0);
+}
+
+static void gen_srl_w(TCGv dest, TCGv src1, TCGv src2)
+{
+TCGv t0 = tcg_temp_new();
+tcg_gen_andi_tl(t0, src2, 0x1f);
+tcg_gen_shr_tl(dest, src1, t0);
+tcg_temp_free(t0);
+}
+
+static void gen_sra_w(TCGv dest, TCGv src1, TCGv src2)
+{
+TCGv t0 = tcg_temp_new();
+tcg_gen_andi_tl(t0, src2, 0x1f);
+tcg_gen_sar_tl(dest, src1, t0);
+tcg_temp_free(t0);
+}
+
+static void gen_sll_d(TCGv dest, TCGv src1, TCGv src2)
+{
+TCGv t0 = tcg_temp_new();
+tcg_gen_andi_tl(t0, src2, 0x3f);
+tcg_gen_shl_tl(dest, src1, t0);
+tcg_temp_free(t0);
+}
+
+static void gen_srl_d(TCGv dest, TCGv src1, TCGv src2)
+{
+TCGv t0 = tcg_temp_new();
+tcg_gen_andi_tl(t0, src2, 0x3f);
+tcg_gen_shr_tl(dest, src1, t0);
+tcg_temp_free(t0);
+}
+
+static void gen_sra_d(TCGv dest, TCGv src1, TCGv src2)
+{
+TCGv t0 = tcg_temp_new();
+tcg_gen_andi_tl(t0, src2, 0x3f);
+tcg_gen_sar_tl(dest, src1, t0);
+tcg_temp_free(t0);
+}
+
+static void gen_rotr_w(TCGv dest, TCGv src1, TCGv src2)
+{
+TCGv_i32 t1 = tcg_temp_new_i32();
+TCGv_i32 t2 = tcg_temp_new_i32();
+TCGv t0 = tcg_temp_new();
+
+tcg_gen_andi_tl(t0, src2, 0x1f);
+
+tcg_gen_trunc_tl_i32(t1, src1);
+tcg_gen_trunc_tl_i32(t2, t0);
+
+tcg_gen_rotr_i32(t1, t1, t2);
+tcg_gen_ext_i32_tl(de

[PULL 15/43] target/loongarch: Add branch instruction translation

2022-06-06 Thread Richard Henderson
From: Song Gao 

This includes:
- BEQ, BNE, BLT[U], BGE[U]
- BEQZ, BNEZ
- B
- BL
- JIRL
- BCEQZ, BCNEZ

Signed-off-by: Song Gao 
Signed-off-by: Xiaojuan Yang 
Reviewed-by: Richard Henderson 
Message-Id: <20220606124333.2060567-16-yangxiaoj...@loongson.cn>
Signed-off-by: Richard Henderson 
---
 target/loongarch/insns.decode | 28 +++
 target/loongarch/translate.c  |  1 +
 .../loongarch/insn_trans/trans_branch.c.inc   | 83 +++
 3 files changed, 112 insertions(+)
 create mode 100644 target/loongarch/insn_trans/trans_branch.c.inc

diff --git a/target/loongarch/insns.decode b/target/loongarch/insns.decode
index 8f286e7233..9b293dfdf9 100644
--- a/target/loongarch/insns.decode
+++ b/target/loongarch/insns.decode
@@ -10,6 +10,9 @@
 #
 %i14s2 10:s14   !function=shl_2
 %sa2p1 15:2 !function=plus_1
+%offs210:s5 10:16   !function=shl_2
+%offs1610:s16   !function=shl_2
+%offs260:s10 10:16  !function=shl_2
 
 #
 # Argument sets
@@ -38,6 +41,10 @@
 &rc   rd cj
 &frr  fd rj rk
 &fr_i fd rj imm
+&r_offs   rj offs
+&c_offs   cj offs
+&offs offs
+&rr_offs  rj rd offs
 
 #
 # Formats
@@ -74,6 +81,10 @@
 @rc  . . .. cj:3 rd:5&rc
 @frr     . rk:5 rj:5 fd:5&frr
 @fr_i12  .. imm:s12 rj:5 fd:5&fr_i
+@r_offs21  ..  rj:5 .&r_offs  
offs=%offs21
+@c_offs21   ..  .. cj:3 .&c_offs  
offs=%offs21
+@offs26 .. ..&offs
offs=%offs26
+@rr_offs16  ..  rj:5 rd:5&rr_offs 
offs=%offs16
 
 #
 # Fixed point arithmetic operation instruction
@@ -409,3 +420,20 @@ fstgt_s 0011 1111 01100 . . .
@frr
 fstgt_d 0011 1111 01101 . . .@frr
 fstle_s 0011 1111 01110 . . .@frr
 fstle_d 0011 1111 0 . . .@frr
+
+#
+# Branch instructions
+#
+beqz0100 00  . . @r_offs21
+bnez0100 01  . . @r_offs21
+bceqz   0100 10  00 ... .@c_offs21
+bcnez   0100 10  01 ... .@c_offs21
+jirl0100 11  . . @rr_offs16
+b   0101 00 ..   @offs26
+bl  0101 01 ..   @offs26
+beq 0101 10  . . @rr_offs16
+bne 0101 11  . . @rr_offs16
+blt 0110 00  . . @rr_offs16
+bge 0110 01  . . @rr_offs16
+bltu0110 10  . . @rr_offs16
+bgeu0110 11  . . @rr_offs16
diff --git a/target/loongarch/translate.c b/target/loongarch/translate.c
index daa77ade33..0ad6b7b2ee 100644
--- a/target/loongarch/translate.c
+++ b/target/loongarch/translate.c
@@ -171,6 +171,7 @@ static void gen_set_gpr(int reg_num, TCGv t, DisasExtend 
dst_ext)
 #include "insn_trans/trans_fcnv.c.inc"
 #include "insn_trans/trans_fmov.c.inc"
 #include "insn_trans/trans_fmemory.c.inc"
+#include "insn_trans/trans_branch.c.inc"
 
 static void loongarch_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
 {
diff --git a/target/loongarch/insn_trans/trans_branch.c.inc 
b/target/loongarch/insn_trans/trans_branch.c.inc
new file mode 100644
index 00..65dbdff41e
--- /dev/null
+++ b/target/loongarch/insn_trans/trans_branch.c.inc
@@ -0,0 +1,83 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ */
+
+static bool trans_b(DisasContext *ctx, arg_b *a)
+{
+gen_goto_tb(ctx, 0, ctx->base.pc_next + a->offs);
+ctx->base.is_jmp = DISAS_NORETURN;
+return true;
+}
+
+static bool trans_bl(DisasContext *ctx, arg_bl *a)
+{
+tcg_gen_movi_tl(cpu_gpr[1], ctx->base.pc_next + 4);
+gen_goto_tb(ctx, 0, ctx->base.pc_next + a->offs);
+ctx->base.is_jmp = DISAS_NORETURN;
+return true;
+}
+
+static bool trans_jirl(DisasContext *ctx, arg_jirl *a)
+{
+TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE);
+TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
+
+tcg_gen_addi_tl(cpu_pc, src1, a->offs);
+tcg_gen_movi_tl(dest, ctx->base.pc_next + 4);
+gen_set_gpr(a->rd, dest, EXT_NONE);
+tcg_gen_lookup_and_goto_ptr();
+ctx->base.is_jmp = DISAS_NORETURN;
+return true;
+}
+
+static void gen_bc(DisasContext *ctx, TCGv src1, TCGv src2,
+   target_long offs, TCGCond cond)
+{
+TCGLabel *l = gen_new_label();
+tcg_gen_brcond_tl(cond, src1, src2, l);
+gen_goto_tb(ctx, 1, ctx->base.pc_next + 4);
+gen_set_label(l);
+gen_goto_tb(ctx, 0, ctx->base.pc_next + of

[PULL 04/43] target/loongarch: Add fixed point arithmetic instruction translation

2022-06-06 Thread Richard Henderson
From: Song Gao 

This includes:
- ADD.{W/D}, SUB.{W/D}
- ADDI.{W/D}, ADDU16ID
- ALSL.{W[U]/D}
- LU12I.W, LU32I.D LU52I.D
- SLT[U], SLT[U]I
- PCADDI, PCADDU12I, PCADDU18I, PCALAU12I
- AND, OR, NOR, XOR, ANDN, ORN
- MUL.{W/D}, MULH.{W[U]/D[U]}
- MULW.D.W[U]
- DIV.{W[U]/D[U]}, MOD.{W[U]/D[U]}
- ANDI, ORI, XORI

Signed-off-by: Song Gao 
Signed-off-by: Xiaojuan Yang 
Reviewed-by: Richard Henderson 
Message-Id: <20220606124333.2060567-5-yangxiaoj...@loongson.cn>
Signed-off-by: Richard Henderson 
---
 target/loongarch/translate.h  |  19 ++
 target/loongarch/insns.decode |  79 +
 target/loongarch/translate.c  |  83 +
 target/loongarch/insn_trans/trans_arith.c.inc | 304 ++
 4 files changed, 485 insertions(+)
 create mode 100644 target/loongarch/insns.decode
 create mode 100644 target/loongarch/insn_trans/trans_arith.c.inc

diff --git a/target/loongarch/translate.h b/target/loongarch/translate.h
index 6cc7f1a7cd..9cc12512d1 100644
--- a/target/loongarch/translate.h
+++ b/target/loongarch/translate.h
@@ -10,11 +10,30 @@
 
 #include "exec/translator.h"
 
+#define TRANS(NAME, FUNC, ...) \
+static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \
+{ return FUNC(ctx, a, __VA_ARGS__); }
+
+/*
+ * If an operation is being performed on less than TARGET_LONG_BITS,
+ * it may require the inputs to be sign- or zero-extended; which will
+ * depend on the exact operation being performed.
+ */
+typedef enum {
+EXT_NONE,
+EXT_SIGN,
+EXT_ZERO,
+} DisasExtend;
+
 typedef struct DisasContext {
 DisasContextBase base;
 target_ulong page_start;
 uint32_t opcode;
 int mem_idx;
+TCGv zero;
+/* Space for 3 operands plus 1 extra for address computation. */
+TCGv temp[4];
+uint8_t ntemp;
 } DisasContext;
 
 void generate_exception(DisasContext *ctx, int excp);
diff --git a/target/loongarch/insns.decode b/target/loongarch/insns.decode
new file mode 100644
index 00..8579c11984
--- /dev/null
+++ b/target/loongarch/insns.decode
@@ -0,0 +1,79 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+#
+# LoongArch instruction decode definitions.
+#
+# Copyright (c) 2021 Loongson Technology Corporation Limited
+#
+
+#
+# Fields
+#
+%sa2p1 15:2 !function=plus_1
+
+#
+# Argument sets
+#
+&r_i  rd imm
+&rrr  rd rj rk
+&rr_i rd rj imm
+&rrr_sa   rd rj rk sa
+
+#
+# Formats
+#
+@rrr     . rk:5 rj:5 rd:5&rrr
+@r_i20   ... imm:s20 rd:5&r_i
+@rr_i12  .. imm:s12 rj:5 rd:5&rr_i
+@rr_ui12  .. imm:12 rj:5 rd:5&rr_i
+@rr_i16  .. imm:s16 rj:5 rd:5&rr_i
+@rrr_sa2p1  ... .. rk:5 rj:5 rd:5&rrr_sa  sa=%sa2p1
+
+#
+# Fixed point arithmetic operation instruction
+#
+add_w    0001 0 . . .@rrr
+add_d    0001 1 . . .@rrr
+sub_w    0001 00010 . . .@rrr
+sub_d    0001 00011 . . .@rrr
+slt  0001 00100 . . .@rrr
+sltu 0001 00101 . . .@rrr
+slti 001000  . . @rr_i12
+sltui    001001  . . @rr_i12
+nor  0001 01000 . . .@rrr
+and  0001 01001 . . .@rrr
+or   0001 01010 . . .@rrr
+xor  0001 01011 . . .@rrr
+orn  0001 01100 . . .@rrr
+andn 0001 01101 . . .@rrr
+mul_w    0001 11000 . . .@rrr
+mulh_w   0001 11001 . . .@rrr
+mulh_wu  0001 11010 . . .@rrr
+mul_d    0001 11011 . . .@rrr
+mulh_d   0001 11100 . . .@rrr
+mulh_du  0001 11101 . . .@rrr
+mulw_d_w 0001 0 . . .@rrr
+mulw_d_wu    0001 1 . . .@rrr
+div_w    0010 0 . . .@rrr
+mod_w    0010 1 . . .@rrr
+div_wu   0010 00010 . . .@rrr
+mod_wu   0010 00011 . . .@rrr
+div_d    0010 00100 . . .@rrr
+mod_d    0010 00101 . . .@rrr
+div_du   0010 00110 . . .@rrr
+mod_du   0010 00111 . . .@rrr
+alsl_w    010 .. . . .   @rrr_sa2p1
+alsl_wu   011 .. . . .   @rrr_sa2p1
+alsl_d   0010 110 .. . . .   @rrr_sa2p1
+lu12

[PULL 19/43] target/loongarch: Add CSRs definition

2022-06-06 Thread Richard Henderson
From: Xiaojuan Yang 

Signed-off-by: Xiaojuan Yang 
Signed-off-by: Song Gao 
Reviewed-by: Richard Henderson 
Message-Id: <20220606124333.2060567-20-yangxiaoj...@loongson.cn>
Signed-off-by: Richard Henderson 
---
 target/loongarch/cpu-csr.h | 208 +
 target/loongarch/cpu.h |  64 
 target/loongarch/cpu.c |  41 
 3 files changed, 313 insertions(+)
 create mode 100644 target/loongarch/cpu-csr.h

diff --git a/target/loongarch/cpu-csr.h b/target/loongarch/cpu-csr.h
new file mode 100644
index 00..4c8ce7fed5
--- /dev/null
+++ b/target/loongarch/cpu-csr.h
@@ -0,0 +1,208 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * QEMU LoongArch CSRs
+ *
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ */
+
+#ifndef LOONGARCH_CPU_CSR_H
+#define LOONGARCH_CPU_CSR_H
+
+#include "hw/registerfields.h"
+
+/* Base on kernal definitions: arch/loongarch/include/asm/loongarch.h */
+
+/* Basic CSRs */
+#define LOONGARCH_CSR_CRMD   0x0 /* Current mode info */
+
+#define LOONGARCH_CSR_PRMD   0x1 /* Prev-exception mode info */
+FIELD(CSR_PRMD, PPLV, 0, 2)
+FIELD(CSR_PRMD, PIE, 2, 1)
+FIELD(CSR_PRMD, PWE, 3, 1)
+
+#define LOONGARCH_CSR_EUEN   0x2 /* Extended unit enable */
+FIELD(CSR_EUEN, FPE, 0, 1)
+FIELD(CSR_EUEN, SXE, 1, 1)
+FIELD(CSR_EUEN, ASXE, 2, 1)
+FIELD(CSR_EUEN, BTE, 3, 1)
+
+#define LOONGARCH_CSR_MISC   0x3 /* Misc config */
+FIELD(CSR_MISC, VA32, 0, 4)
+FIELD(CSR_MISC, DRDTL, 4, 4)
+FIELD(CSR_MISC, RPCNTL, 8, 4)
+FIELD(CSR_MISC, ALCL, 12, 4)
+FIELD(CSR_MISC, DWPL, 16, 3)
+
+#define LOONGARCH_CSR_ECFG   0x4 /* Exception config */
+FIELD(CSR_ECFG, LIE, 0, 13)
+FIELD(CSR_ECFG, VS, 16, 3)
+
+#define LOONGARCH_CSR_ESTAT  0x5 /* Exception status */
+FIELD(CSR_ESTAT, IS, 0, 13)
+FIELD(CSR_ESTAT, ECODE, 16, 6)
+FIELD(CSR_ESTAT, ESUBCODE, 22, 9)
+
+#define LOONGARCH_CSR_ERA0x6 /* Exception return address */
+
+#define LOONGARCH_CSR_BADV   0x7 /* Bad virtual address */
+
+#define LOONGARCH_CSR_BADI   0x8 /* Bad instruction */
+
+#define LOONGARCH_CSR_EENTRY 0xc /* Exception entry address */
+
+/* TLB related CSRs */
+#define LOONGARCH_CSR_TLBIDX 0x10 /* TLB Index, EHINV, PageSize, NP */
+FIELD(CSR_TLBIDX, INDEX, 0, 12)
+FIELD(CSR_TLBIDX, PS, 24, 6)
+FIELD(CSR_TLBIDX, NE, 31, 1)
+
+#define LOONGARCH_CSR_TLBEHI 0x11 /* TLB EntryHi */
+FIELD(CSR_TLBEHI, VPPN, 13, 35)
+
+#define LOONGARCH_CSR_TLBELO00x12 /* TLB EntryLo0 */
+#define LOONGARCH_CSR_TLBELO10x13 /* TLB EntryLo1 */
+FIELD(TLBENTRY, V, 0, 1)
+FIELD(TLBENTRY, D, 1, 1)
+FIELD(TLBENTRY, PLV, 2, 2)
+FIELD(TLBENTRY, MAT, 4, 2)
+FIELD(TLBENTRY, G, 6, 1)
+FIELD(TLBENTRY, PPN, 12, 36)
+FIELD(TLBENTRY, NR, 61, 1)
+FIELD(TLBENTRY, NX, 62, 1)
+FIELD(TLBENTRY, RPLV, 63, 1)
+
+#define LOONGARCH_CSR_ASID   0x18 /* Address space identifier */
+FIELD(CSR_ASID, ASID, 0, 10)
+FIELD(CSR_ASID, ASIDBITS, 16, 8)
+
+/* Page table base address when badv[47] = 0 */
+#define LOONGARCH_CSR_PGDL   0x19
+/* Page table base address when badv[47] = 1 */
+#define LOONGARCH_CSR_PGDH   0x1a
+
+#define LOONGARCH_CSR_PGD0x1b /* Page table base address */
+
+/* Page walk controller's low addr */
+#define LOONGARCH_CSR_PWCL   0x1c
+FIELD(CSR_PWCL, PTBASE, 0, 5)
+FIELD(CSR_PWCL, PTWIDTH, 5, 5)
+FIELD(CSR_PWCL, DIR1_BASE, 10, 5)
+FIELD(CSR_PWCL, DIR1_WIDTH, 15, 5)
+FIELD(CSR_PWCL, DIR2_BASE, 20, 5)
+FIELD(CSR_PWCL, DIR2_WIDTH, 25, 5)
+FIELD(CSR_PWCL, PTEWIDTH, 30, 2)
+
+/* Page walk controller's high addr */
+#define LOONGARCH_CSR_PWCH   0x1d
+FIELD(CSR_PWCH, DIR3_BASE, 0, 6)
+FIELD(CSR_PWCH, DIR3_WIDTH, 6, 6)
+FIELD(CSR_PWCH, DIR4_BASE, 12, 6)
+FIELD(CSR_PWCH, DIR4_WIDTH, 18, 6)
+
+#define LOONGARCH_CSR_STLBPS 0x1e /* Stlb page size */
+FIELD(CSR_STLBPS, PS, 0, 5)
+
+#define LOONGARCH_CSR_RVACFG 0x1f /* Reduced virtual address config */
+FIELD(CSR_RVACFG, RBITS, 0, 4)
+
+/* Config CSRs */
+#define LOONGARCH_CSR_CPUID  0x20 /* CPU core id */
+
+#define LOONGARCH_CSR_PRCFG1 0x21 /* Config1 */
+FIELD(CSR_PRCFG1, SAVE_NUM, 0, 4)
+FIELD(CSR_PRCFG1, TIMER_BITS, 4, 8)
+FIELD(CSR_PRCFG1, VSMAX, 12, 3)
+
+#define LOONGARCH_CSR_PRCFG2 0x22 /* Config2 */
+
+#define LOONGARCH_CSR_PRCFG3 0x23 /* Config3 */
+FIELD(CSR_PRCFG3, TLB_TYPE, 0, 4)
+FIELD(CSR_PRCFG3, MTLB_ENTRY, 4, 8)
+FIELD(CSR_PRCFG3, STLB_WAYS, 12, 8)
+FIELD(CSR_PRCFG3, STLB_SETS, 20, 8)
+
+/*
+ * Save registers count can read from PRCFG1.SAVE_NUM
+ * The Min count is 1. Max count is 15.
+ */
+#define LOONGARCH_CSR_SAVE(N)(0x30 + N)
+
+/* Timer CSRs */
+#define LOONGARCH_CSR_TID0x40 /* Timer ID */
+
+#define LOONGARCH_CSR_TCFG   0x41 /* Timer config */
+FIELD(CSR_TCFG, EN, 0, 1)
+FIELD(CSR_TCFG, PERIODIC, 1, 1)
+FIELD(CSR_TCFG, INIT_VAL, 2, 46)
+
+#define LOONGARCH_CSR_TVAL   0x42 /* Timer ticks remain */
+
+#define LOONGARCH_CS

[PULL 12/43] target/loongarch: Add floating point conversion instruction translation

2022-06-06 Thread Richard Henderson
From: Song Gao 

This includes:
- FCVT.S.D, FCVT.D.S
- FFINT.{S/D}.{W/L}, FTINT.{W/L}.{S/D}
- FTINT{RM/RP/RZ/RNE}.{W/L}.{S/D}
- FRINT.{S/D}

Signed-off-by: Song Gao 
Signed-off-by: Xiaojuan Yang 
Reviewed-by: Richard Henderson 
Message-Id: <20220606124333.2060567-13-yangxiaoj...@loongson.cn>
Signed-off-by: Richard Henderson 
---
 target/loongarch/helper.h|  29 ++
 target/loongarch/insns.decode|  32 ++
 target/loongarch/fpu_helper.c| 393 +++
 target/loongarch/translate.c |   1 +
 target/loongarch/insn_trans/trans_fcnv.c.inc |  33 ++
 5 files changed, 488 insertions(+)
 create mode 100644 target/loongarch/insn_trans/trans_fcnv.c.inc

diff --git a/target/loongarch/helper.h b/target/loongarch/helper.h
index 25a891bf8b..1e8749433a 100644
--- a/target/loongarch/helper.h
+++ b/target/loongarch/helper.h
@@ -61,3 +61,32 @@ DEF_HELPER_4(fcmp_s_s, i64, env, i64, i64, i32)
 DEF_HELPER_4(fcmp_c_d, i64, env, i64, i64, i32)
 /* fcmp.sXXX.d */
 DEF_HELPER_4(fcmp_s_d, i64, env, i64, i64, i32)
+
+DEF_HELPER_2(fcvt_d_s, i64, env, i64)
+DEF_HELPER_2(fcvt_s_d, i64, env, i64)
+DEF_HELPER_2(ffint_d_w, i64, env, i64)
+DEF_HELPER_2(ffint_d_l, i64, env, i64)
+DEF_HELPER_2(ffint_s_w, i64, env, i64)
+DEF_HELPER_2(ffint_s_l, i64, env, i64)
+DEF_HELPER_2(ftintrm_l_s, i64, env, i64)
+DEF_HELPER_2(ftintrm_l_d, i64, env, i64)
+DEF_HELPER_2(ftintrm_w_s, i64, env, i64)
+DEF_HELPER_2(ftintrm_w_d, i64, env, i64)
+DEF_HELPER_2(ftintrp_l_s, i64, env, i64)
+DEF_HELPER_2(ftintrp_l_d, i64, env, i64)
+DEF_HELPER_2(ftintrp_w_s, i64, env, i64)
+DEF_HELPER_2(ftintrp_w_d, i64, env, i64)
+DEF_HELPER_2(ftintrz_l_s, i64, env, i64)
+DEF_HELPER_2(ftintrz_l_d, i64, env, i64)
+DEF_HELPER_2(ftintrz_w_s, i64, env, i64)
+DEF_HELPER_2(ftintrz_w_d, i64, env, i64)
+DEF_HELPER_2(ftintrne_l_s, i64, env, i64)
+DEF_HELPER_2(ftintrne_l_d, i64, env, i64)
+DEF_HELPER_2(ftintrne_w_s, i64, env, i64)
+DEF_HELPER_2(ftintrne_w_d, i64, env, i64)
+DEF_HELPER_2(ftint_l_s, i64, env, i64)
+DEF_HELPER_2(ftint_l_d, i64, env, i64)
+DEF_HELPER_2(ftint_w_s, i64, env, i64)
+DEF_HELPER_2(ftint_w_d, i64, env, i64)
+DEF_HELPER_2(frint_s, i64, env, i64)
+DEF_HELPER_2(frint_d, i64, env, i64)
diff --git a/target/loongarch/insns.decode b/target/loongarch/insns.decode
index d7ed80b0b9..b9f135d36f 100644
--- a/target/loongarch/insns.decode
+++ b/target/loongarch/insns.decode
@@ -316,3 +316,35 @@ fclass_d 00010001 01000 01110 . .
@ff
 #
 fcmp_cond_s  1101 . . . 00 ...   @cff_fcond
 fcmp_cond_d  1110 . . . 00 ...   @cff_fcond
+
+#
+# Floating point conversion instruction
+#
+fcvt_s_d 00010001 10010 00110 . .@ff
+fcvt_d_s 00010001 10010 01001 . .@ff
+ftintrm_w_s  00010001 10100 1 . .@ff
+ftintrm_w_d  00010001 10100 00010 . .@ff
+ftintrm_l_s  00010001 10100 01001 . .@ff
+ftintrm_l_d  00010001 10100 01010 . .@ff
+ftintrp_w_s  00010001 10100 10001 . .@ff
+ftintrp_w_d  00010001 10100 10010 . .@ff
+ftintrp_l_s  00010001 10100 11001 . .@ff
+ftintrp_l_d  00010001 10100 11010 . .@ff
+ftintrz_w_s  00010001 10101 1 . .@ff
+ftintrz_w_d  00010001 10101 00010 . .@ff
+ftintrz_l_s  00010001 10101 01001 . .@ff
+ftintrz_l_d  00010001 10101 01010 . .@ff
+ftintrne_w_s 00010001 10101 10001 . .@ff
+ftintrne_w_d 00010001 10101 10010 . .@ff
+ftintrne_l_s 00010001 10101 11001 . .@ff
+ftintrne_l_d 00010001 10101 11010 . .@ff
+ftint_w_s    00010001 10110 1 . .@ff
+ftint_w_d    00010001 10110 00010 . .@ff
+ftint_l_s    00010001 10110 01001 . .@ff
+ftint_l_d    00010001 10110 01010 . .@ff
+ffint_s_w    00010001 11010 00100 . .@ff
+ffint_s_l    00010001 11010 00110 . .@ff
+ffint_d_w    00010001 11010 01000 . .@ff
+ffint_d_l    00010001 11010 01010 . .@ff
+frint_s  00010001 11100 10001 . .@ff
+frint_d  00010001 11100 10010 . .@ff
diff --git a/target/loongarch/fpu_helper.c b/target/loongarch/fpu_helper.c
index 1e514cce74..81466678eb 100644
--- a/target/loongarch/fpu_helper.c
+++ b/target/loongarch/fpu_helper.c
@@ -461,3 +461,396 @@ uint64_t helper_fcmp_s_d(CPULoongArchState *env, uint64_t 
fj,
 FloatRelation cmp = float64_compare(fj, fk, &env->fp_status);
 return fcmp_common(env, cmp, flags);
 }
+
+/* floating point conversion */
+uint64_t helper_fcvt_s_d(CPULoongArchState *env, uint64_t fj)
+{
+uint64_t fd;
+
+fd = nanbox_s(float64_to_float32(fj, &env->fp_status));
+update_fcsr0(

[PULL 20/43] target/loongarch: Add basic vmstate description of CPU.

2022-06-06 Thread Richard Henderson
From: Xiaojuan Yang 

Signed-off-by: Xiaojuan Yang 
Signed-off-by: Song Gao 
Reviewed-by: Richard Henderson 
Message-Id: <20220606124333.2060567-21-yangxiaoj...@loongson.cn>
Signed-off-by: Richard Henderson 
---
 target/loongarch/internals.h |  2 +
 target/loongarch/cpu.c   |  1 +
 target/loongarch/machine.c   | 85 
 target/loongarch/meson.build |  6 +++
 4 files changed, 94 insertions(+)
 create mode 100644 target/loongarch/machine.c

diff --git a/target/loongarch/internals.h b/target/loongarch/internals.h
index 1a3b39e0be..39960dee27 100644
--- a/target/loongarch/internals.h
+++ b/target/loongarch/internals.h
@@ -25,4 +25,6 @@ const char *loongarch_exception_name(int32_t exception);
 
 void restore_fp_status(CPULoongArchState *env);
 
+extern const VMStateDescription vmstate_loongarch_cpu;
+
 #endif
diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
index 33d9a9450d..267d96c9a8 100644
--- a/target/loongarch/cpu.c
+++ b/target/loongarch/cpu.c
@@ -336,6 +336,7 @@ static void loongarch_cpu_class_init(ObjectClass *c, void 
*data)
 cc->class_by_name = loongarch_cpu_class_by_name;
 cc->dump_state = loongarch_cpu_dump_state;
 cc->set_pc = loongarch_cpu_set_pc;
+dc->vmsd = &vmstate_loongarch_cpu;
 cc->disas_set_info = loongarch_cpu_disas_set_info;
 #ifdef CONFIG_TCG
 cc->tcg_ops = &loongarch_tcg_ops;
diff --git a/target/loongarch/machine.c b/target/loongarch/machine.c
new file mode 100644
index 00..49a06fdf28
--- /dev/null
+++ b/target/loongarch/machine.c
@@ -0,0 +1,85 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * QEMU LoongArch Machine State
+ *
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ */
+
+#include "qemu/osdep.h"
+#include "cpu.h"
+#include "migration/cpu.h"
+
+/* LoongArch CPU state */
+
+const VMStateDescription vmstate_loongarch_cpu = {
+.name = "cpu",
+.version_id = 0,
+.minimum_version_id = 0,
+.fields = (VMStateField[]) {
+
+VMSTATE_UINTTL_ARRAY(env.gpr, LoongArchCPU, 32),
+VMSTATE_UINTTL(env.pc, LoongArchCPU),
+VMSTATE_UINT64_ARRAY(env.fpr, LoongArchCPU, 32),
+VMSTATE_UINT32(env.fcsr0, LoongArchCPU),
+VMSTATE_BOOL_ARRAY(env.cf, LoongArchCPU, 8),
+
+/* Remaining CSRs */
+VMSTATE_UINT64(env.CSR_CRMD, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_PRMD, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_EUEN, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_MISC, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_ECFG, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_ESTAT, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_ERA, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_BADV, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_BADI, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_EENTRY, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_TLBIDX, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_TLBEHI, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_TLBELO0, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_TLBELO1, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_ASID, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_PGDL, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_PGDH, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_PGD, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_PWCL, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_PWCH, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_STLBPS, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_RVACFG, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_PRCFG1, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_PRCFG2, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_PRCFG3, LoongArchCPU),
+VMSTATE_UINT64_ARRAY(env.CSR_SAVE, LoongArchCPU, 16),
+VMSTATE_UINT64(env.CSR_TID, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_TCFG, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_TVAL, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_CNTC, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_TICLR, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_LLBCTL, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_IMPCTL1, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_IMPCTL2, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_TLBRENTRY, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_TLBRBADV, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_TLBRERA, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_TLBRSAVE, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_TLBRELO0, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_TLBRELO1, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_TLBREHI, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_TLBRPRMD, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_MERRCTL, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_MERRINFO1, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_MERRINFO2, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_MERRENTRY, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_MERRERA, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_MERRSAVE, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_CTAG, LoongArchCPU),
+VMST

[PULL 08/43] target/loongarch: Add fixed point atomic instruction translation

2022-06-06 Thread Richard Henderson
From: Song Gao 

This includes:
- LL.{W/D}, SC.{W/D}
- AM{SWAP/ADD/AND/OR/XOR/MAX/MIN}[_DB].{W/D}
- AM{MAX/MIN}[_DB].{WU/DU}

Signed-off-by: Song Gao 
Signed-off-by: Xiaojuan Yang 
Reviewed-by: Richard Henderson 
Message-Id: <20220606124333.2060567-9-yangxiaoj...@loongson.cn>
Signed-off-by: Richard Henderson 
---
 target/loongarch/insns.decode |  44 +++
 target/loongarch/translate.c  |   1 +
 .../loongarch/insn_trans/trans_atomic.c.inc   | 113 ++
 .../loongarch/insn_trans/trans_memory.c.inc   |   2 +-
 4 files changed, 159 insertions(+), 1 deletion(-)
 create mode 100644 target/loongarch/insn_trans/trans_atomic.c.inc

diff --git a/target/loongarch/insns.decode b/target/loongarch/insns.decode
index 1156e6965c..8d247aa68c 100644
--- a/target/loongarch/insns.decode
+++ b/target/loongarch/insns.decode
@@ -193,3 +193,47 @@ stle_b  0011 1111 11100 . . .
@rrr
 stle_h  0011 1111 11101 . . .@rrr
 stle_w  0011 1111 0 . . .@rrr
 stle_d  0011 1111 1 . . .@rrr
+
+#
+# Fixed point atomic instruction
+#
+ll_w0010  .. . . @rr_i14s2
+sc_w0010 0001 .. . . @rr_i14s2
+ll_d0010 0010 .. . . @rr_i14s2
+sc_d0010 0011 .. . . @rr_i14s2
+amswap_w0011 1110 0 . . .@rrr
+amswap_d0011 1110 1 . . .@rrr
+amadd_w 0011 1110 00010 . . .@rrr
+amadd_d 0011 1110 00011 . . .@rrr
+amand_w 0011 1110 00100 . . .@rrr
+amand_d 0011 1110 00101 . . .@rrr
+amor_w  0011 1110 00110 . . .@rrr
+amor_d  0011 1110 00111 . . .@rrr
+amxor_w 0011 1110 01000 . . .@rrr
+amxor_d 0011 1110 01001 . . .@rrr
+ammax_w 0011 1110 01010 . . .@rrr
+ammax_d 0011 1110 01011 . . .@rrr
+ammin_w 0011 1110 01100 . . .@rrr
+ammin_d 0011 1110 01101 . . .@rrr
+ammax_wu0011 1110 01110 . . .@rrr
+ammax_du0011 1110 0 . . .@rrr
+ammin_wu0011 1110 1 . . .@rrr
+ammin_du0011 1110 10001 . . .@rrr
+amswap_db_w 0011 1110 10010 . . .@rrr
+amswap_db_d 0011 1110 10011 . . .@rrr
+amadd_db_w  0011 1110 10100 . . .@rrr
+amadd_db_d  0011 1110 10101 . . .@rrr
+amand_db_w  0011 1110 10110 . . .@rrr
+amand_db_d  0011 1110 10111 . . .@rrr
+amor_db_w   0011 1110 11000 . . .@rrr
+amor_db_d   0011 1110 11001 . . .@rrr
+amxor_db_w  0011 1110 11010 . . .@rrr
+amxor_db_d  0011 1110 11011 . . .@rrr
+ammax_db_w  0011 1110 11100 . . .@rrr
+ammax_db_d  0011 1110 11101 . . .@rrr
+ammin_db_w  0011 1110 0 . . .@rrr
+ammin_db_d  0011 1110 1 . . .@rrr
+ammax_db_wu 0011 1111 0 . . .@rrr
+ammax_db_du 0011 1111 1 . . .@rrr
+ammin_db_wu 0011 1111 00010 . . .@rrr
+ammin_db_du 0011 1111 00011 . . .@rrr
diff --git a/target/loongarch/translate.c b/target/loongarch/translate.c
index b8fed26699..01791bf1a2 100644
--- a/target/loongarch/translate.c
+++ b/target/loongarch/translate.c
@@ -154,6 +154,7 @@ static void gen_set_gpr(int reg_num, TCGv t, DisasExtend 
dst_ext)
 #include "insn_trans/trans_shift.c.inc"
 #include "insn_trans/trans_bit.c.inc"
 #include "insn_trans/trans_memory.c.inc"
+#include "insn_trans/trans_atomic.c.inc"
 
 static void loongarch_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
 {
diff --git a/target/loongarch/insn_trans/trans_atomic.c.inc 
b/target/loongarch/insn_trans/trans_atomic.c.inc
new file mode 100644
index 00..6763c1c301
--- /dev/null
+++ b/target/loongarch/insn_trans/trans_atomic.c.inc
@@ -0,0 +1,113 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ */
+
+static bool gen_ll(DisasContext *ctx, arg_rr_i *a, MemOp mop)
+{
+TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE);
+TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
+TCGv t0 = tcg_temp_new();
+
+tcg_gen_addi_tl(t0, src1, a->imm);
+tcg_gen_qemu_ld_i64(dest, t0, ctx->mem_idx, mop);
+tcg_gen_st_tl(t0, cpu_env, offsetof(CPULoongArchState, lladdr));
+tcg_gen_st_tl(dest, cpu_env, offse

[PULL 17/43] target/loongarch: Add target build suport

2022-06-06 Thread Richard Henderson
From: Song Gao 

Signed-off-by: Song Gao 
Signed-off-by: Xiaojuan Yang 
Reviewed-by: Richard Henderson 
Reviewed-by: Philippe Mathieu-Daudé 
Message-Id: <20220606124333.2060567-18-yangxiaoj...@loongson.cn>
Signed-off-by: Richard Henderson 
---
 target/loongarch/meson.build | 19 +++
 target/meson.build   |  1 +
 2 files changed, 20 insertions(+)
 create mode 100644 target/loongarch/meson.build

diff --git a/target/loongarch/meson.build b/target/loongarch/meson.build
new file mode 100644
index 00..bcb076e55f
--- /dev/null
+++ b/target/loongarch/meson.build
@@ -0,0 +1,19 @@
+gen = decodetree.process('insns.decode')
+
+loongarch_ss = ss.source_set()
+loongarch_ss.add(files(
+  'cpu.c',
+  'disas.c',
+))
+loongarch_tcg_ss = ss.source_set()
+loongarch_tcg_ss.add(gen)
+loongarch_tcg_ss.add(files(
+  'fpu_helper.c',
+  'op_helper.c',
+  'translate.c',
+))
+loongarch_tcg_ss.add(zlib)
+
+loongarch_ss.add_all(when: 'CONFIG_TCG', if_true: [loongarch_tcg_ss])
+
+target_arch += {'loongarch': loongarch_ss}
diff --git a/target/meson.build b/target/meson.build
index 2f6940255e..a53a60486f 100644
--- a/target/meson.build
+++ b/target/meson.build
@@ -5,6 +5,7 @@ subdir('cris')
 subdir('hexagon')
 subdir('hppa')
 subdir('i386')
+subdir('loongarch')
 subdir('m68k')
 subdir('microblaze')
 subdir('mips')
-- 
2.34.1




[PULL 14/43] target/loongarch: Add floating point load/store instruction translation

2022-06-06 Thread Richard Henderson
From: Song Gao 

This includes:
- FLD.{S/D}, FST.{S/D}
- FLDX.{S/D}, FSTX.{S/D}
- FLD{GT/LE}.{S/D}, FST{GT/LE}.{S/D}

Signed-off-by: Song Gao 
Signed-off-by: Xiaojuan Yang 
Reviewed-by: Richard Henderson 
Message-Id: <20220606124333.2060567-15-yangxiaoj...@loongson.cn>
Signed-off-by: Richard Henderson 
---
 target/loongarch/insns.decode |  24 +++
 target/loongarch/translate.c  |   1 +
 .../loongarch/insn_trans/trans_fmemory.c.inc  | 153 ++
 3 files changed, 178 insertions(+)
 create mode 100644 target/loongarch/insn_trans/trans_fmemory.c.inc

diff --git a/target/loongarch/insns.decode b/target/loongarch/insns.decode
index c62a4f6dcd..8f286e7233 100644
--- a/target/loongarch/insns.decode
+++ b/target/loongarch/insns.decode
@@ -36,6 +36,8 @@
 &fc   fd cj
 &cr   cd rj
 &rc   rd cj
+&frr  fd rj rk
+&fr_i fd rj imm
 
 #
 # Formats
@@ -70,6 +72,8 @@
 @fc  . . .. cj:3 fd:5&fc
 @cr  . . rj:5 .. cd:3&cr
 @rc  . . .. cj:3 rd:5&rc
+@frr     . rk:5 rj:5 fd:5&frr
+@fr_i12  .. imm:s12 rj:5 fd:5&fr_i
 
 #
 # Fixed point arithmetic operation instruction
@@ -385,3 +389,23 @@ movfr2cf 00010001 01001 10100 . 00 ...   
@cf
 movcf2fr 00010001 01001 10101 00 ... .   @fc
 movgr2cf 00010001 01001 10110 . 00 ...   @cr
 movcf2gr 00010001 01001 10111 00 ... .   @rc
+
+#
+# Floating point load/store instruction
+#
+fld_s   0010 101100  . . @fr_i12
+fst_s   0010 101101  . . @fr_i12
+fld_d   0010 101110  . . @fr_i12
+fst_d   0010 10  . . @fr_i12
+fldx_s  0011 1011 0 . . .@frr
+fldx_d  0011 1011 01000 . . .@frr
+fstx_s  0011 1011 1 . . .@frr
+fstx_d  0011 1011 11000 . . .@frr
+fldgt_s 0011 1111 01000 . . .@frr
+fldgt_d 0011 1111 01001 . . .@frr
+fldle_s 0011 1111 01010 . . .@frr
+fldle_d 0011 1111 01011 . . .@frr
+fstgt_s 0011 1111 01100 . . .@frr
+fstgt_d 0011 1111 01101 . . .@frr
+fstle_s 0011 1111 01110 . . .@frr
+fstle_d 0011 1111 0 . . .@frr
diff --git a/target/loongarch/translate.c b/target/loongarch/translate.c
index 26d60b50fd..daa77ade33 100644
--- a/target/loongarch/translate.c
+++ b/target/loongarch/translate.c
@@ -170,6 +170,7 @@ static void gen_set_gpr(int reg_num, TCGv t, DisasExtend 
dst_ext)
 #include "insn_trans/trans_fcmp.c.inc"
 #include "insn_trans/trans_fcnv.c.inc"
 #include "insn_trans/trans_fmov.c.inc"
+#include "insn_trans/trans_fmemory.c.inc"
 
 static void loongarch_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
 {
diff --git a/target/loongarch/insn_trans/trans_fmemory.c.inc 
b/target/loongarch/insn_trans/trans_fmemory.c.inc
new file mode 100644
index 00..74ee98f63a
--- /dev/null
+++ b/target/loongarch/insn_trans/trans_fmemory.c.inc
@@ -0,0 +1,153 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ */
+
+static void maybe_nanbox_load(TCGv freg, MemOp mop)
+{
+if ((mop & MO_SIZE) == MO_32) {
+gen_nanbox_s(freg, freg);
+}
+}
+
+static bool gen_fload_i(DisasContext *ctx, arg_fr_i *a, MemOp mop)
+{
+TCGv addr = gpr_src(ctx, a->rj, EXT_NONE);
+TCGv temp = NULL;
+
+if (a->imm) {
+temp = tcg_temp_new();
+tcg_gen_addi_tl(temp, addr, a->imm);
+addr = temp;
+}
+
+tcg_gen_qemu_ld_tl(cpu_fpr[a->fd], addr, ctx->mem_idx, mop);
+maybe_nanbox_load(cpu_fpr[a->fd], mop);
+
+if (temp) {
+tcg_temp_free(temp);
+}
+
+return true;
+}
+
+static bool gen_fstore_i(DisasContext *ctx, arg_fr_i *a, MemOp mop)
+{
+TCGv addr = gpr_src(ctx, a->rj, EXT_NONE);
+TCGv temp = NULL;
+
+if (a->imm) {
+temp = tcg_temp_new();
+tcg_gen_addi_tl(temp, addr, a->imm);
+addr = temp;
+}
+
+tcg_gen_qemu_st_tl(cpu_fpr[a->fd], addr, ctx->mem_idx, mop);
+
+if (temp) {
+tcg_temp_free(temp);
+}
+return true;
+}
+
+static bool gen_floadx(DisasContext *ctx, arg_frr *a, MemOp mop)
+{
+TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
+TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE);
+TCGv addr = tcg_temp_new();
+
+tcg_gen_add_tl(addr, src1, src2);
+tcg_gen_qemu_ld_tl(cpu_fpr[a->fd], addr, ctx->mem_idx, mop);
+maybe_nanbox_load(cpu_fpr[a->fd], mop);
+tcg_temp_free(addr);
+
+return true;
+}
+
+static bool gen_fstorex(DisasContext *ctx

[PULL 27/43] target/loongarch: Add TLB instruction support

2022-06-06 Thread Richard Henderson
From: Xiaojuan Yang 

This includes:
- TLBSRCH
- TLBRD
- TLBWR
- TLBFILL
- TLBCLR
- TLBFLUSH
- INVTLB

Signed-off-by: Xiaojuan Yang 
Signed-off-by: Song Gao 
Reviewed-by: Richard Henderson 
Message-Id: <20220606124333.2060567-28-yangxiaoj...@loongson.cn>
Signed-off-by: Richard Henderson 
---
 target/loongarch/helper.h |  13 +
 target/loongarch/insns.decode |  11 +
 target/loongarch/disas.c  |  18 +
 target/loongarch/tlb_helper.c | 355 ++
 .../insn_trans/trans_privileged.c.inc | 102 +
 5 files changed, 499 insertions(+)

diff --git a/target/loongarch/helper.h b/target/loongarch/helper.h
index 4664a02dcf..b092ca75fe 100644
--- a/target/loongarch/helper.h
+++ b/target/loongarch/helper.h
@@ -108,3 +108,16 @@ DEF_HELPER_3(iocsrwr_b, void, env, tl, tl)
 DEF_HELPER_3(iocsrwr_h, void, env, tl, tl)
 DEF_HELPER_3(iocsrwr_w, void, env, tl, tl)
 DEF_HELPER_3(iocsrwr_d, void, env, tl, tl)
+
+/* TLB helper */
+DEF_HELPER_1(tlbwr, void, env)
+DEF_HELPER_1(tlbfill, void, env)
+DEF_HELPER_1(tlbsrch, void, env)
+DEF_HELPER_1(tlbrd, void, env)
+DEF_HELPER_1(tlbclr, void, env)
+DEF_HELPER_1(tlbflush, void, env)
+DEF_HELPER_1(invtlb_all, void, env)
+DEF_HELPER_2(invtlb_all_g, void, env, i32)
+DEF_HELPER_2(invtlb_all_asid, void, env, tl)
+DEF_HELPER_3(invtlb_page_asid, void, env, tl, tl)
+DEF_HELPER_3(invtlb_page_asid_or_g, void, env, tl, tl)
diff --git a/target/loongarch/insns.decode b/target/loongarch/insns.decode
index 2b436d3cd6..f8ed11d83e 100644
--- a/target/loongarch/insns.decode
+++ b/target/loongarch/insns.decode
@@ -47,6 +47,8 @@
 &rr_offs  rj rd offs
 &r_csrrd csr
 &rr_csr   rd rj csr
+&empty
+&i_rr imm rj rk
 
 #
 # Formats
@@ -89,6 +91,8 @@
 @rr_offs16  ..  rj:5 rd:5&rr_offs 
offs=%offs16
 @r_csr  csr:14 . rd:5&r_csr
 @rr_csr  csr:14 rj:5 rd:5&rr_csr
+@empty    . . . .&empty
+@i_rr .. .. . rk:5 rj:5 imm:5&i_rr
 
 #
 # Fixed point arithmetic operation instruction
@@ -459,3 +463,10 @@ iocsrwr_b 01100100 1 00100 . .
@rr
 iocsrwr_h 01100100 1 00101 . .@rr
 iocsrwr_w 01100100 1 00110 . .@rr
 iocsrwr_d 01100100 1 00111 . .@rr
+tlbsrch   01100100 1 01010 0 0@empty
+tlbrd 01100100 1 01011 0 0@empty
+tlbwr 01100100 1 01100 0 0@empty
+tlbfill   01100100 1 01101 0 0@empty
+tlbclr    01100100 1 01000 0 0@empty
+tlbflush  01100100 1 01001 0 0@empty
+invtlb    01100100 10011 . . .@i_rr
diff --git a/target/loongarch/disas.c b/target/loongarch/disas.c
index ea26aea728..6a56607302 100644
--- a/target/loongarch/disas.c
+++ b/target/loongarch/disas.c
@@ -303,6 +303,17 @@ static void output_rr_csr(DisasContext *ctx, arg_rr_csr *a,
a->rd, a->rj, a->csr, get_csr_name(a->csr));
 }
 
+static void output_empty(DisasContext *ctx, arg_empty *a,
+ const char *mnemonic)
+{
+output(ctx, mnemonic, "");
+}
+
+static void output_i_rr(DisasContext *ctx, arg_i_rr *a, const char *mnemonic)
+{
+output(ctx, mnemonic, "%d, r%d, r%d", a->imm, a->rj, a->rk);
+}
+
 #define INSN(insn, type)\
 static bool trans_##insn(DisasContext *ctx, arg_##type * a) \
 {   \
@@ -623,6 +634,13 @@ INSN(iocsrwr_b,rr)
 INSN(iocsrwr_h,rr)
 INSN(iocsrwr_w,rr)
 INSN(iocsrwr_d,rr)
+INSN(tlbsrch,  empty)
+INSN(tlbrd,empty)
+INSN(tlbwr,empty)
+INSN(tlbfill,  empty)
+INSN(tlbclr,   empty)
+INSN(tlbflush, empty)
+INSN(invtlb,   i_rr)
 
 #define output_fcmp(C, PREFIX, SUFFIX) 
\
 {  
\
diff --git a/target/loongarch/tlb_helper.c b/target/loongarch/tlb_helper.c
index fad8bc7746..4f84ef3e4b 100644
--- a/target/loongarch/tlb_helper.c
+++ b/target/loongarch/tlb_helper.c
@@ -7,9 +7,11 @@
  */
 
 #include "qemu/osdep.h"
+#include "qemu/guest-random.h"
 
 #include "cpu.h"
 #include "internals.h"
+#include "exec/helper-proto.h"
 #include "exec/exec-all.h"
 #include "exec/cpu_ldst.h"
 #include "exec/log.h"
@@ -280,6 +282,359 @@ static void raise_mmu_exception(CPULoongArchState *env, 
target_ulong address,
}
 }
 
+static void invalidate_tlb_entry(CPULoongArchState *env, int index)
+{
+target_ulong addr, mask, pagesize;
+uint8_t tlb_ps;
+LoongArchTLB *tlb = &env->tlb[index];
+
+int mmu_idx = cpu_mmu_index(env, false);
+uint8_t tlb_v0 = FIELD_EX64(tlb->tlb_entry0, TLBENTRY, V

[PULL 10/43] target/loongarch: Add floating point arithmetic instruction translation

2022-06-06 Thread Richard Henderson
From: Song Gao 

This includes:
- F{ADD/SUB/MUL/DIV}.{S/D}
- F{MADD/MSUB/NMADD/NMSUB}.{S/D}
- F{MAX/MIN}.{S/D}
- F{MAXA/MINA}.{S/D}
- F{ABS/NEG}.{S/D}
- F{SQRT/RECIP/RSQRT}.{S/D}
- F{SCALEB/LOGB/COPYSIGN}.{S/D}
- FCLASS.{S/D}

Signed-off-by: Song Gao 
Signed-off-by: Xiaojuan Yang 
Reviewed-by: Richard Henderson 
Message-Id: <20220606124333.2060567-11-yangxiaoj...@loongson.cn>
Signed-off-by: Richard Henderson 
---
 target/loongarch/helper.h |  37 ++
 target/loongarch/internals.h  |   2 +
 target/loongarch/insns.decode |  52 +++
 target/loongarch/cpu.c|   1 +
 target/loongarch/fpu_helper.c | 403 ++
 target/loongarch/translate.c  |  11 +
 .../loongarch/insn_trans/trans_farith.c.inc   | 105 +
 7 files changed, 611 insertions(+)
 create mode 100644 target/loongarch/fpu_helper.c
 create mode 100644 target/loongarch/insn_trans/trans_farith.c.inc

diff --git a/target/loongarch/helper.h b/target/loongarch/helper.h
index 638c2efc51..840bad9b2f 100644
--- a/target/loongarch/helper.h
+++ b/target/loongarch/helper.h
@@ -15,3 +15,40 @@ DEF_HELPER_FLAGS_3(asrtgt_d, TCG_CALL_NO_WG, void, env, tl, 
tl)
 DEF_HELPER_FLAGS_3(crc32, TCG_CALL_NO_RWG_SE, tl, tl, tl, tl)
 DEF_HELPER_FLAGS_3(crc32c, TCG_CALL_NO_RWG_SE, tl, tl, tl, tl)
 DEF_HELPER_FLAGS_2(cpucfg, TCG_CALL_NO_RWG_SE, tl, env, tl)
+
+/* Floating-point helper */
+DEF_HELPER_FLAGS_3(fadd_s, TCG_CALL_NO_WG, i64, env, i64, i64)
+DEF_HELPER_FLAGS_3(fadd_d, TCG_CALL_NO_WG, i64, env, i64, i64)
+DEF_HELPER_FLAGS_3(fsub_s, TCG_CALL_NO_WG, i64, env, i64, i64)
+DEF_HELPER_FLAGS_3(fsub_d, TCG_CALL_NO_WG, i64, env, i64, i64)
+DEF_HELPER_FLAGS_3(fmul_s, TCG_CALL_NO_WG, i64, env, i64, i64)
+DEF_HELPER_FLAGS_3(fmul_d, TCG_CALL_NO_WG, i64, env, i64, i64)
+DEF_HELPER_FLAGS_3(fdiv_s, TCG_CALL_NO_WG, i64, env, i64, i64)
+DEF_HELPER_FLAGS_3(fdiv_d, TCG_CALL_NO_WG, i64, env, i64, i64)
+DEF_HELPER_FLAGS_3(fmax_s, TCG_CALL_NO_WG, i64, env, i64, i64)
+DEF_HELPER_FLAGS_3(fmax_d, TCG_CALL_NO_WG, i64, env, i64, i64)
+DEF_HELPER_FLAGS_3(fmin_s, TCG_CALL_NO_WG, i64, env, i64, i64)
+DEF_HELPER_FLAGS_3(fmin_d, TCG_CALL_NO_WG, i64, env, i64, i64)
+DEF_HELPER_FLAGS_3(fmaxa_s, TCG_CALL_NO_WG, i64, env, i64, i64)
+DEF_HELPER_FLAGS_3(fmaxa_d, TCG_CALL_NO_WG, i64, env, i64, i64)
+DEF_HELPER_FLAGS_3(fmina_s, TCG_CALL_NO_WG, i64, env, i64, i64)
+DEF_HELPER_FLAGS_3(fmina_d, TCG_CALL_NO_WG, i64, env, i64, i64)
+
+DEF_HELPER_FLAGS_5(fmuladd_s, TCG_CALL_NO_WG, i64, env, i64, i64, i64, i32)
+DEF_HELPER_FLAGS_5(fmuladd_d, TCG_CALL_NO_WG, i64, env, i64, i64, i64, i32)
+
+DEF_HELPER_FLAGS_3(fscaleb_s, TCG_CALL_NO_WG, i64, env, i64, i64)
+DEF_HELPER_FLAGS_3(fscaleb_d, TCG_CALL_NO_WG, i64, env, i64, i64)
+
+DEF_HELPER_FLAGS_2(flogb_s, TCG_CALL_NO_WG, i64, env, i64)
+DEF_HELPER_FLAGS_2(flogb_d, TCG_CALL_NO_WG, i64, env, i64)
+
+DEF_HELPER_FLAGS_2(fsqrt_s, TCG_CALL_NO_WG, i64, env, i64)
+DEF_HELPER_FLAGS_2(fsqrt_d, TCG_CALL_NO_WG, i64, env, i64)
+DEF_HELPER_FLAGS_2(frsqrt_s, TCG_CALL_NO_WG, i64, env, i64)
+DEF_HELPER_FLAGS_2(frsqrt_d, TCG_CALL_NO_WG, i64, env, i64)
+DEF_HELPER_FLAGS_2(frecip_s, TCG_CALL_NO_WG, i64, env, i64)
+DEF_HELPER_FLAGS_2(frecip_d, TCG_CALL_NO_WG, i64, env, i64)
+
+DEF_HELPER_FLAGS_2(fclass_s, TCG_CALL_NO_RWG_SE, i64, env, i64)
+DEF_HELPER_FLAGS_2(fclass_d, TCG_CALL_NO_RWG_SE, i64, env, i64)
diff --git a/target/loongarch/internals.h b/target/loongarch/internals.h
index 9f02287a90..43b865ec21 100644
--- a/target/loongarch/internals.h
+++ b/target/loongarch/internals.h
@@ -18,4 +18,6 @@ void G_NORETURN do_raise_exception(CPULoongArchState *env,
 
 const char *loongarch_exception_name(int32_t exception);
 
+void restore_fp_status(CPULoongArchState *env);
+
 #endif
diff --git a/target/loongarch/insns.decode b/target/loongarch/insns.decode
index 98774dbddb..6455e09ebe 100644
--- a/target/loongarch/insns.decode
+++ b/target/loongarch/insns.decode
@@ -23,6 +23,9 @@
 &hint_r_i hint rj imm
 &rrr_sa   rd rj rk sa
 &rr_ms_ls rd rj ms ls
+&ff   fd fj
+&fff  fd fj fk
+& fd fj fk fa
 
 #
 # Formats
@@ -44,6 +47,9 @@
 @rrr_sa3   .. sa:3 rk:5 rj:5 rd:5&rrr_sa
 @rr_2bw ... ms:5 . ls:5 rj:5 rd:5&rr_ms_ls
 @rr_2bd    .. ms:6 ls:6 rj:5 rd:5&rr_ms_ls
+@ff     . . fj:5 fd:5&ff
+@fff     . fk:5 fj:5 fd:5&fff
+@     fa:5 fk:5 fj:5 fd:5&
 
 #
 # Fixed point arithmetic operation instruction
@@ -256,3 +262,49 @@ syscall  0010 10110 ...  
@i15
 asrtle_d  00010 . . 0@rr_jk
 asrtgt_d  00011 . . 0@rr_jk
 cpucfg    0 11011 . .@rr
+
+#
+# Floating point arithmetic operation instruction
+#
+fadd_s   0001 1 . . .@fff
+f

[PULL 16/43] target/loongarch: Add disassembler

2022-06-06 Thread Richard Henderson
From: Song Gao 

This patch adds support for disassembling via option '-d in_asm'.

Signed-off-by: Song Gao 
Signed-off-by: Xiaojuan Yang 
Reviewed-by: Richard Henderson 
Message-Id: <20220606124333.2060567-17-yangxiaoj...@loongson.cn>
Signed-off-by: Richard Henderson 
---
 meson.build  |   1 +
 include/disas/dis-asm.h  |   2 +
 target/loongarch/disas.c | 610 +++
 3 files changed, 613 insertions(+)
 create mode 100644 target/loongarch/disas.c

diff --git a/meson.build b/meson.build
index d738391810..21cd949082 100644
--- a/meson.build
+++ b/meson.build
@@ -2349,6 +2349,7 @@ disassemblers = {
   'sh4' : ['CONFIG_SH4_DIS'],
   'sparc' : ['CONFIG_SPARC_DIS'],
   'xtensa' : ['CONFIG_XTENSA_DIS'],
+  'loongarch' : ['CONFIG_LOONGARCH_DIS'],
 }
 if link_language == 'cpp'
   disassemblers += {
diff --git a/include/disas/dis-asm.h b/include/disas/dis-asm.h
index fc7cb7af5a..64247ecb11 100644
--- a/include/disas/dis-asm.h
+++ b/include/disas/dis-asm.h
@@ -253,6 +253,7 @@ enum bfd_architecture
 #define bfd_mach_rx0x75
 #define bfd_mach_rx_v2 0x76
 #define bfd_mach_rx_v3 0x77
+  bfd_arch_loongarch,
   bfd_arch_last
   };
 #define bfd_mach_s390_31 31
@@ -458,6 +459,7 @@ int print_insn_riscv64  (bfd_vma, 
disassemble_info*);
 int print_insn_riscv128 (bfd_vma, disassemble_info*);
 int print_insn_rx(bfd_vma, disassemble_info *);
 int print_insn_hexagon(bfd_vma, disassemble_info *);
+int print_insn_loongarch(bfd_vma, disassemble_info *);
 
 #ifdef CONFIG_CAPSTONE
 bool cap_disas_target(disassemble_info *info, uint64_t pc, size_t size);
diff --git a/target/loongarch/disas.c b/target/loongarch/disas.c
new file mode 100644
index 00..9454ebb8e9
--- /dev/null
+++ b/target/loongarch/disas.c
@@ -0,0 +1,610 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * QEMU LoongArch Disassembler
+ *
+ * Copyright (c) 2021 Loongson Technology Corporation Limited.
+ */
+
+#include "qemu/osdep.h"
+#include "disas/dis-asm.h"
+#include "qemu/bitops.h"
+
+typedef struct {
+disassemble_info *info;
+uint64_t pc;
+uint32_t insn;
+} DisasContext;
+
+static inline int plus_1(DisasContext *ctx, int x)
+{
+return x + 1;
+}
+
+static inline int shl_2(DisasContext *ctx, int x)
+{
+return x << 2;
+}
+
+#define output(C, INSN, FMT, ...)   \
+{   \
+(C)->info->fprintf_func((C)->info->stream, "%08x   %-9s\t" FMT, \
+(C)->insn, INSN, ##__VA_ARGS__);\
+}
+
+#include "decode-insns.c.inc"
+
+int print_insn_loongarch(bfd_vma memaddr, struct disassemble_info *info)
+{
+bfd_byte buffer[4];
+uint32_t insn;
+int status;
+
+status = (*info->read_memory_func)(memaddr, buffer, 4, info);
+if (status != 0) {
+(*info->memory_error_func)(status, memaddr, info);
+return -1;
+}
+insn = bfd_getl32(buffer);
+DisasContext ctx = {
+.info = info,
+.pc = memaddr,
+.insn = insn
+};
+
+if (!decode(&ctx, insn)) {
+output(&ctx, "illegal", "");
+}
+return 4;
+}
+
+static void output_r_i(DisasContext *ctx, arg_r_i *a, const char *mnemonic)
+{
+output(ctx, mnemonic, "r%d, %d", a->rd, a->imm);
+}
+
+static void output_rrr(DisasContext *ctx, arg_rrr *a, const char *mnemonic)
+{
+output(ctx, mnemonic, "r%d, r%d, r%d", a->rd, a->rj, a->rk);
+}
+
+static void output_rr_i(DisasContext *ctx, arg_rr_i *a, const char *mnemonic)
+{
+output(ctx, mnemonic, "r%d, r%d, %d", a->rd, a->rj, a->imm);
+}
+
+static void output_rrr_sa(DisasContext *ctx, arg_rrr_sa *a,
+  const char *mnemonic)
+{
+output(ctx, mnemonic, "r%d, r%d, r%d, %d", a->rd, a->rj, a->rk, a->sa);
+}
+
+static void output_rr(DisasContext *ctx, arg_rr *a, const char *mnemonic)
+{
+output(ctx, mnemonic, "r%d, r%d", a->rd, a->rj);
+}
+
+static void output_rr_ms_ls(DisasContext *ctx, arg_rr_ms_ls *a,
+  const char *mnemonic)
+{
+output(ctx, mnemonic, "r%d, r%d, %d, %d", a->rd, a->rj, a->ms, a->ls);
+}
+
+static void output_hint_r_i(DisasContext *ctx, arg_hint_r_i *a,
+const char *mnemonic)
+{
+output(ctx, mnemonic, "%d, r%d, %d", a->hint, a->rj, a->imm);
+}
+
+static void output_i(DisasContext *ctx, arg_i *a, const char *mnemonic)
+{
+output(ctx, mnemonic, "%d", a->imm);
+}
+
+static void output_rr_jk(DisasContext *ctx, arg_rr_jk *a,
+ const char *mnemonic)
+{
+output(ctx, mnemonic, "r%d, r%d", a->rj, a->rk);
+}
+
+static void output_ff(DisasContext *ctx, arg_ff *a, const char *mnemonic)
+{
+output(ctx, mnemonic, "f%d, f%d", a->fd, a->fj);
+}
+
+static void output_fff(DisasContext *ctx, arg_fff *a, const char *mnemonic)
+{
+output(ctx, mnemonic, "f%d, f%d, f%d", a->fd, a->fj, a->fk);
+}
+
+static void output_(DisasContext *ctx, arg_ *a, const

[PULL 38/43] hw/loongarch: Add LoongArch ls7a rtc device support

2022-06-06 Thread Richard Henderson
From: Xiaojuan Yang 

This patch add ls7a rtc device support.

Signed-off-by: Xiaojuan Yang 
Signed-off-by: Song Gao 
Reviewed-by: Richard Henderson 
Message-Id: <20220606124333.2060567-39-yangxiaoj...@loongson.cn>
Signed-off-by: Richard Henderson 
---
 include/hw/pci-host/ls7a.h |   4 +
 hw/loongarch/loongson3.c   |   3 +
 hw/rtc/ls7a_rtc.c  | 528 +
 MAINTAINERS|   1 +
 hw/loongarch/Kconfig   |   1 +
 hw/rtc/Kconfig |   3 +
 hw/rtc/meson.build |   1 +
 7 files changed, 541 insertions(+)
 create mode 100644 hw/rtc/ls7a_rtc.c

diff --git a/include/hw/pci-host/ls7a.h b/include/hw/pci-host/ls7a.h
index 5c653527f0..08c5f78be2 100644
--- a/include/hw/pci-host/ls7a.h
+++ b/include/hw/pci-host/ls7a.h
@@ -37,4 +37,8 @@
 #define LS7A_PCI_IRQS   48
 #define LS7A_UART_IRQ   (PCH_PIC_IRQ_OFFSET + 2)
 #define LS7A_UART_BASE  0x1fe001e0
+#define LS7A_RTC_IRQ(PCH_PIC_IRQ_OFFSET + 3)
+#define LS7A_MISC_REG_BASE  (LS7A_PCH_REG_BASE + 0x0008)
+#define LS7A_RTC_REG_BASE   (LS7A_MISC_REG_BASE + 0x00050100)
+#define LS7A_RTC_LEN0x100
 #endif
diff --git a/hw/loongarch/loongson3.c b/hw/loongarch/loongson3.c
index 7bc17113dc..95984c9086 100644
--- a/hw/loongarch/loongson3.c
+++ b/hw/loongarch/loongson3.c
@@ -97,6 +97,9 @@ static void loongarch_devices_init(DeviceState *pch_pic)
  * Create some unimplemented devices to emulate this.
  */
 create_unimplemented_device("pci-dma-cfg", 0x1001041c, 0x4);
+sysbus_create_simple("ls7a_rtc", LS7A_RTC_REG_BASE,
+ qdev_get_gpio_in(pch_pic,
+ LS7A_RTC_IRQ - PCH_PIC_IRQ_OFFSET));
 }
 
 static void loongarch_irq_init(LoongArchMachineState *lams)
diff --git a/hw/rtc/ls7a_rtc.c b/hw/rtc/ls7a_rtc.c
new file mode 100644
index 00..fe6710310f
--- /dev/null
+++ b/hw/rtc/ls7a_rtc.c
@@ -0,0 +1,528 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Loongarch LS7A Real Time Clock emulation
+ *
+ * Copyright (C) 2021 Loongson Technology Corporation Limited
+ */
+
+#include "qemu/osdep.h"
+#include "hw/sysbus.h"
+#include "hw/irq.h"
+#include "include/hw/register.h"
+#include "qemu/timer.h"
+#include "sysemu/sysemu.h"
+#include "qemu/cutils.h"
+#include "qemu/log.h"
+#include "migration/vmstate.h"
+#include "hw/misc/unimp.h"
+#include "sysemu/rtc.h"
+#include "hw/registerfields.h"
+
+#define SYS_TOYTRIM0x20
+#define SYS_TOYWRITE0  0x24
+#define SYS_TOYWRITE1  0x28
+#define SYS_TOYREAD0   0x2C
+#define SYS_TOYREAD1   0x30
+#define SYS_TOYMATCH0  0x34
+#define SYS_TOYMATCH1  0x38
+#define SYS_TOYMATCH2  0x3C
+#define SYS_RTCCTRL0x40
+#define SYS_RTCTRIM0x60
+#define SYS_RTCWRTIE0  0x64
+#define SYS_RTCREAD0   0x68
+#define SYS_RTCMATCH0  0x6C
+#define SYS_RTCMATCH1  0x70
+#define SYS_RTCMATCH2  0x74
+
+#define LS7A_RTC_FREQ 32768
+#define TIMER_NUMS3
+/*
+ * Shift bits and filed mask
+ */
+
+FIELD(TOY, MON, 26, 6)
+FIELD(TOY, DAY, 21, 5)
+FIELD(TOY, HOUR, 16, 5)
+FIELD(TOY, MIN, 10, 6)
+FIELD(TOY, SEC, 4, 6)
+FIELD(TOY, MSEC, 0, 4)
+
+FIELD(TOY_MATCH, YEAR, 26, 6)
+FIELD(TOY_MATCH, MON, 22, 4)
+FIELD(TOY_MATCH, DAY, 17, 5)
+FIELD(TOY_MATCH, HOUR, 12, 5)
+FIELD(TOY_MATCH, MIN, 6, 6)
+FIELD(TOY_MATCH, SEC, 0, 6)
+
+FIELD(RTC_CTRL, RTCEN, 13, 1)
+FIELD(RTC_CTRL, TOYEN, 11, 1)
+FIELD(RTC_CTRL, EO, 8, 1)
+
+#define TYPE_LS7A_RTC "ls7a_rtc"
+OBJECT_DECLARE_SIMPLE_TYPE(LS7ARtcState, LS7A_RTC)
+
+struct LS7ARtcState {
+SysBusDevice parent_obj;
+
+MemoryRegion iomem;
+/*
+ * Needed to preserve the tick_count across migration, even if the
+ * absolute value of the rtc_clock is different on the source and
+ * destination.
+ */
+int64_t offset_toy;
+int64_t offset_rtc;
+uint64_t save_toy_mon;
+uint64_t save_toy_year;
+uint64_t save_rtc;
+int64_t data;
+int tidx;
+uint32_t toymatch[3];
+uint32_t toytrim;
+uint32_t cntrctl;
+uint32_t rtctrim;
+uint32_t rtccount;
+uint32_t rtcmatch[3];
+QEMUTimer *toy_timer[TIMER_NUMS];
+QEMUTimer *rtc_timer[TIMER_NUMS];
+qemu_irq irq;
+};
+
+/* switch nanoseconds time to rtc ticks */
+static inline uint64_t ls7a_rtc_ticks(void)
+{
+return qemu_clock_get_ns(rtc_clock) * LS7A_RTC_FREQ / 
NANOSECONDS_PER_SECOND;
+}
+
+/* switch rtc ticks to nanoseconds */
+static inline uint64_t ticks_to_ns(uint64_t ticks)
+{
+return ticks * NANOSECONDS_PER_SECOND / LS7A_RTC_FREQ;
+}
+
+static inline bool toy_enabled(LS7ARtcState *s)
+{
+return FIELD_EX32(s->cntrctl, RTC_CTRL, TOYEN) &&
+   FIELD_EX32(s->cntrctl, RTC_CTRL, EO);
+}
+
+static inline bool rtc_enabled(LS7ARtcState *s)
+{
+return FIELD_EX32(s->cntrctl, RTC_CTRL, RTCEN) &&
+   FIELD_EX32(s->cntrctl, RTC_CTRL, EO);
+}
+
+/* parse toy value to struct tm */
+static inline void toy_val_to_time_mon(uint64_t toy_val, struct tm *tm

[PULL 21/43] target/loongarch: Implement qmp_query_cpu_definitions()

2022-06-06 Thread Richard Henderson
From: Xiaojuan Yang 

Signed-off-by: Xiaojuan Yang 
Signed-off-by: Song Gao 
Reviewed-by: Richard Henderson 
Message-Id: <20220606124333.2060567-22-yangxiaoj...@loongson.cn>
Signed-off-by: Richard Henderson 
---
 qapi/machine-target.json |  6 --
 target/loongarch/cpu.c   | 26 ++
 2 files changed, 30 insertions(+), 2 deletions(-)

diff --git a/qapi/machine-target.json b/qapi/machine-target.json
index 06b0d2ca61..2e267fa458 100644
--- a/qapi/machine-target.json
+++ b/qapi/machine-target.json
@@ -323,7 +323,8 @@
'TARGET_ARM',
'TARGET_I386',
'TARGET_S390X',
-   'TARGET_MIPS' ] } }
+   'TARGET_MIPS',
+   'TARGET_LOONGARCH64' ] } }
 
 ##
 # @query-cpu-definitions:
@@ -339,4 +340,5 @@
'TARGET_ARM',
'TARGET_I386',
'TARGET_S390X',
-   'TARGET_MIPS' ] } }
+   'TARGET_MIPS',
+   'TARGET_LOONGARCH64' ] } }
diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
index 267d96c9a8..aa0e1f9167 100644
--- a/target/loongarch/cpu.c
+++ b/target/loongarch/cpu.c
@@ -365,3 +365,29 @@ static const TypeInfo loongarch_cpu_type_infos[] = {
 };
 
 DEFINE_TYPES(loongarch_cpu_type_infos)
+
+static void loongarch_cpu_add_definition(gpointer data, gpointer user_data)
+{
+ObjectClass *oc = data;
+CpuDefinitionInfoList **cpu_list = user_data;
+CpuDefinitionInfo *info = g_new0(CpuDefinitionInfo, 1);
+const char *typename = object_class_get_name(oc);
+
+info->name = g_strndup(typename,
+   strlen(typename) - strlen("-" TYPE_LOONGARCH_CPU));
+info->q_typename = g_strdup(typename);
+
+QAPI_LIST_PREPEND(*cpu_list, info);
+}
+
+CpuDefinitionInfoList *qmp_query_cpu_definitions(Error **errp)
+{
+CpuDefinitionInfoList *cpu_list = NULL;
+GSList *list;
+
+list = object_class_get_list(TYPE_LOONGARCH_CPU, false);
+g_slist_foreach(list, loongarch_cpu_add_definition, &cpu_list);
+g_slist_free(list);
+
+return cpu_list;
+}
-- 
2.34.1




[PULL 23/43] target/loongarch: Add LoongArch interrupt and exception handle

2022-06-06 Thread Richard Henderson
From: Xiaojuan Yang 

Signed-off-by: Xiaojuan Yang 
Signed-off-by: Song Gao 
Reviewed-by: Richard Henderson 
Message-Id: <20220606124333.2060567-24-yangxiaoj...@loongson.cn>
Signed-off-by: Richard Henderson 
---
 target/loongarch/cpu.h   |   2 +
 target/loongarch/internals.h |   2 +
 target/loongarch/cpu.c   | 230 +++
 3 files changed, 234 insertions(+)

diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h
index e0415d8929..b983ce241c 100644
--- a/target/loongarch/cpu.h
+++ b/target/loongarch/cpu.h
@@ -184,6 +184,8 @@ FIELD(CSR_CRMD, WE, 9, 1)
 extern const char * const regnames[32];
 extern const char * const fregnames[32];
 
+#define N_IRQS  13
+
 #define LOONGARCH_STLB 2048 /* 2048 STLB */
 #define LOONGARCH_MTLB 64   /* 64 MTLB */
 #define LOONGARCH_TLB_MAX  (LOONGARCH_STLB + LOONGARCH_MTLB)
diff --git a/target/loongarch/internals.h b/target/loongarch/internals.h
index 2fed768653..69183e8bb5 100644
--- a/target/loongarch/internals.h
+++ b/target/loongarch/internals.h
@@ -30,6 +30,8 @@ void restore_fp_status(CPULoongArchState *env);
 
 extern const VMStateDescription vmstate_loongarch_cpu;
 
+void loongarch_cpu_set_irq(void *opaque, int irq, int level);
+
 bool loongarch_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
 MMUAccessType access_type, int mmu_idx,
 bool probe, uintptr_t retaddr);
diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
index 9a5cabbf4c..01a0b4878a 100644
--- a/target/loongarch/cpu.c
+++ b/target/loongarch/cpu.c
@@ -80,6 +80,215 @@ static void loongarch_cpu_set_pc(CPUState *cs, vaddr value)
 env->pc = value;
 }
 
+void loongarch_cpu_set_irq(void *opaque, int irq, int level)
+{
+LoongArchCPU *cpu = opaque;
+CPULoongArchState *env = &cpu->env;
+CPUState *cs = CPU(cpu);
+
+if (irq < 0 || irq >= N_IRQS) {
+return;
+}
+
+env->CSR_ESTAT = deposit64(env->CSR_ESTAT, irq, 1, level != 0);
+
+if (FIELD_EX64(env->CSR_ESTAT, CSR_ESTAT, IS)) {
+cpu_interrupt(cs, CPU_INTERRUPT_HARD);
+} else {
+cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
+}
+}
+
+static inline bool cpu_loongarch_hw_interrupts_enabled(CPULoongArchState *env)
+{
+bool ret = 0;
+
+ret = (FIELD_EX64(env->CSR_CRMD, CSR_CRMD, IE) &&
+  !(FIELD_EX64(env->CSR_DBG, CSR_DBG, DST)));
+
+return ret;
+}
+
+/* Check if there is pending and not masked out interrupt */
+static inline bool cpu_loongarch_hw_interrupts_pending(CPULoongArchState *env)
+{
+uint32_t pending;
+uint32_t status;
+bool r;
+
+pending = FIELD_EX64(env->CSR_ESTAT, CSR_ESTAT, IS);
+status  = FIELD_EX64(env->CSR_ECFG, CSR_ECFG, LIE);
+
+r = (pending & status) != 0;
+return r;
+}
+
+static void loongarch_cpu_do_interrupt(CPUState *cs)
+{
+LoongArchCPU *cpu = LOONGARCH_CPU(cs);
+CPULoongArchState *env = &cpu->env;
+bool update_badinstr = 1;
+int cause = -1;
+const char *name;
+bool tlbfill = FIELD_EX64(env->CSR_TLBRERA, CSR_TLBRERA, ISTLBR);
+uint32_t vec_size = FIELD_EX64(env->CSR_ECFG, CSR_ECFG, VS);
+
+if (cs->exception_index != EXCCODE_INT) {
+if (cs->exception_index < 0 ||
+cs->exception_index > ARRAY_SIZE(excp_names)) {
+name = "unknown";
+} else {
+name = excp_names[cs->exception_index];
+}
+
+qemu_log_mask(CPU_LOG_INT,
+ "%s enter: pc " TARGET_FMT_lx " ERA " TARGET_FMT_lx
+ " TLBRERA " TARGET_FMT_lx " %s exception\n", __func__,
+ env->pc, env->CSR_ERA, env->CSR_TLBRERA, name);
+}
+
+switch (cs->exception_index) {
+case EXCCODE_DBP:
+env->CSR_DBG = FIELD_DP64(env->CSR_DBG, CSR_DBG, DCL, 1);
+env->CSR_DBG = FIELD_DP64(env->CSR_DBG, CSR_DBG, ECODE, 0xC);
+goto set_DERA;
+set_DERA:
+env->CSR_DERA = env->pc;
+env->CSR_DBG = FIELD_DP64(env->CSR_DBG, CSR_DBG, DST, 1);
+env->pc = env->CSR_EENTRY + 0x480;
+break;
+case EXCCODE_INT:
+if (FIELD_EX64(env->CSR_DBG, CSR_DBG, DST)) {
+env->CSR_DBG = FIELD_DP64(env->CSR_DBG, CSR_DBG, DEI, 1);
+goto set_DERA;
+}
+QEMU_FALLTHROUGH;
+case EXCCODE_PIF:
+cause = cs->exception_index;
+update_badinstr = 0;
+break;
+case EXCCODE_ADEM:
+case EXCCODE_SYS:
+case EXCCODE_BRK:
+case EXCCODE_PIL:
+case EXCCODE_PIS:
+case EXCCODE_PME:
+case EXCCODE_PNR:
+case EXCCODE_PNX:
+case EXCCODE_PPI:
+case EXCCODE_INE:
+case EXCCODE_IPE:
+case EXCCODE_FPE:
+cause = cs->exception_index;
+break;
+default:
+qemu_log("Error: exception(%d) '%s' has not been supported\n",
+ cs->exception_index, excp_names[cs->exception_index]);
+abort();
+}
+
+if (update_badinstr) {
+env->CSR_BADI = cpu_ldl_code(en

[PULL 13/43] target/loongarch: Add floating point move instruction translation

2022-06-06 Thread Richard Henderson
From: Song Gao 

This includes:
- FMOV.{S/D}
- FSEL
- MOVGR2FR.{W/D}, MOVGR2FRH.W
- MOVFR2GR.{S/D}, MOVFRH2GR.S
- MOVGR2FCSR, MOVFCSR2GR
- MOVFR2CF, MOVCF2FR
- MOVGR2CF, MOVCF2GR

Signed-off-by: Song Gao 
Signed-off-by: Xiaojuan Yang 
Reviewed-by: Richard Henderson 
Message-Id: <20220606124333.2060567-14-yangxiaoj...@loongson.cn>
Signed-off-by: Richard Henderson 
---
 target/loongarch/helper.h|   2 +
 target/loongarch/insns.decode|  37 +
 target/loongarch/fpu_helper.c|   6 +
 target/loongarch/translate.c |   1 +
 target/loongarch/insn_trans/trans_fmov.c.inc | 157 +++
 5 files changed, 203 insertions(+)
 create mode 100644 target/loongarch/insn_trans/trans_fmov.c.inc

diff --git a/target/loongarch/helper.h b/target/loongarch/helper.h
index 1e8749433a..da1a2bced7 100644
--- a/target/loongarch/helper.h
+++ b/target/loongarch/helper.h
@@ -90,3 +90,5 @@ DEF_HELPER_2(ftint_w_s, i64, env, i64)
 DEF_HELPER_2(ftint_w_d, i64, env, i64)
 DEF_HELPER_2(frint_s, i64, env, i64)
 DEF_HELPER_2(frint_d, i64, env, i64)
+
+DEF_HELPER_FLAGS_2(set_rounding_mode, TCG_CALL_NO_RWG, void, env, i32)
diff --git a/target/loongarch/insns.decode b/target/loongarch/insns.decode
index b9f135d36f..c62a4f6dcd 100644
--- a/target/loongarch/insns.decode
+++ b/target/loongarch/insns.decode
@@ -27,6 +27,15 @@
 &fff  fd fj fk
 & fd fj fk fa
 &cff_fcondcd fj fk fcond
+&fffc fd fj fk ca
+&fr   fd rj
+&rf   rd fj
+&fcsrd_r  fcsrd rj
+&r_fcsrs  rd fcsrs
+&cf   cd fj
+&fc   fd cj
+&cr   cd rj
+&rc   rd cj
 
 #
 # Formats
@@ -52,6 +61,15 @@
 @fff     . fk:5 fj:5 fd:5&fff
 @     fa:5 fk:5 fj:5 fd:5&
 @cff_fcond  fcond:5 fk:5 fj:5 .. cd:3&cff_fcond
+@fffc  .. ca:3 fk:5 fj:5 fd:5&fffc
+@fr     . . rj:5 fd:5&fr
+@rf     . . fj:5 rd:5&rf
+@fcsrd_r     . . rj:5 fcsrd:5&fcsrd_r
+@r_fcsrs     . . fcsrs:5 rd:5&r_fcsrs
+@cf  . . fj:5 .. cd:3&cf
+@fc  . . .. cj:3 fd:5&fc
+@cr  . . rj:5 .. cd:3&cr
+@rc  . . .. cj:3 rd:5&rc
 
 #
 # Fixed point arithmetic operation instruction
@@ -348,3 +366,22 @@ ffint_d_w    00010001 11010 01000 . .
@ff
 ffint_d_l    00010001 11010 01010 . .@ff
 frint_s  00010001 11100 10001 . .@ff
 frint_d  00010001 11100 10010 . .@ff
+
+#
+# Floating point move instruction
+#
+fmov_s   00010001 01001 00101 . .@ff
+fmov_d   00010001 01001 00110 . .@ff
+fsel 1101 00 ... . . .   @fffc
+movgr2fr_w   00010001 01001 01001 . .@fr
+movgr2fr_d   00010001 01001 01010 . .@fr
+movgr2frh_w  00010001 01001 01011 . .@fr
+movfr2gr_s   00010001 01001 01101 . .@rf
+movfr2gr_d   00010001 01001 01110 . .@rf
+movfrh2gr_s  00010001 01001 0 . .@rf
+movgr2fcsr   00010001 01001 1 . .@fcsrd_r
+movfcsr2gr   00010001 01001 10010 . .@r_fcsrs
+movfr2cf 00010001 01001 10100 . 00 ...   @cf
+movcf2fr 00010001 01001 10101 00 ... .   @fc
+movgr2cf 00010001 01001 10110 . 00 ...   @cr
+movcf2gr 00010001 01001 10111 00 ... .   @rc
diff --git a/target/loongarch/fpu_helper.c b/target/loongarch/fpu_helper.c
index 81466678eb..3d0cb8dd0d 100644
--- a/target/loongarch/fpu_helper.c
+++ b/target/loongarch/fpu_helper.c
@@ -854,3 +854,9 @@ uint64_t helper_ftint_w_d(CPULoongArchState *env, uint64_t 
fj)
 update_fcsr0(env, GETPC());
 return fd;
 }
+
+void helper_set_rounding_mode(CPULoongArchState *env, uint32_t fcsr0)
+{
+set_float_rounding_mode(ieee_rm[(fcsr0 >> FCSR0_RM) & 0x3],
+&env->fp_status);
+}
diff --git a/target/loongarch/translate.c b/target/loongarch/translate.c
index 26ef1e366c..26d60b50fd 100644
--- a/target/loongarch/translate.c
+++ b/target/loongarch/translate.c
@@ -169,6 +169,7 @@ static void gen_set_gpr(int reg_num, TCGv t, DisasExtend 
dst_ext)
 #include "insn_trans/trans_farith.c.inc"
 #include "insn_trans/trans_fcmp.c.inc"
 #include "insn_trans/trans_fcnv.c.inc"
+#include "insn_trans/trans_fmov.c.inc"
 
 static void loongarch_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
 {
diff --git a/target/loongarch/insn_trans/trans_fmov.c.inc 
b/target/loongarch/insn_trans/trans_fmov.c.inc
new file mode 100644
index 00..24753d4568
--- /dev/null
+++ b/target/loongarch/insn_trans/t

[PULL 40/43] hw/loongarch: Add LoongArch virt power manager support.

2022-06-06 Thread Richard Henderson
From: Xiaojuan Yang 

This is a placeholder for missing ACPI, and will eventually be replaced.

Signed-off-by: Xiaojuan Yang 
Signed-off-by: Song Gao 
Acked-by: Richard Henderson 
Message-Id: <20220606124333.2060567-41-yangxiaoj...@loongson.cn>
Signed-off-by: Richard Henderson 
---
 hw/loongarch/loongson3.c | 49 +++-
 1 file changed, 48 insertions(+), 1 deletion(-)

diff --git a/hw/loongarch/loongson3.c b/hw/loongarch/loongson3.c
index 3c8fcb828c..bd20ebbb78 100644
--- a/hw/loongarch/loongson3.c
+++ b/hw/loongarch/loongson3.c
@@ -31,6 +31,48 @@
 
 #include "target/loongarch/cpu.h"
 
+#define PM_BASE 0x1008
+#define PM_SIZE 0x100
+#define PM_CTRL 0x10
+
+/*
+ * This is a placeholder for missing ACPI,
+ * and will eventually be replaced.
+ */
+static uint64_t loongarch_virt_pm_read(void *opaque, hwaddr addr, unsigned 
size)
+{
+return 0;
+}
+
+static void loongarch_virt_pm_write(void *opaque, hwaddr addr,
+   uint64_t val, unsigned size)
+{
+if (addr != PM_CTRL) {
+return;
+}
+
+switch (val) {
+case 0x00:
+qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
+return;
+case 0xff:
+qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
+return;
+default:
+return;
+}
+}
+
+static const MemoryRegionOps loongarch_virt_pm_ops = {
+.read  = loongarch_virt_pm_read,
+.write = loongarch_virt_pm_write,
+.endianness = DEVICE_NATIVE_ENDIAN,
+.valid = {
+.min_access_size = 1,
+.max_access_size = 1
+}
+};
+
 static struct _loaderparams {
 uint64_t ram_size;
 const char *kernel_filename;
@@ -67,7 +109,7 @@ static void loongarch_devices_init(DeviceState *pch_pic)
 SysBusDevice *d;
 PCIBus *pci_bus;
 MemoryRegion *ecam_alias, *ecam_reg, *pio_alias, *pio_reg;
-MemoryRegion *mmio_alias, *mmio_reg;
+MemoryRegion *mmio_alias, *mmio_reg, *pm_mem;
 int i;
 
 gpex_dev = qdev_new(TYPE_GPEX_HOST);
@@ -132,6 +174,11 @@ static void loongarch_devices_init(DeviceState *pch_pic)
 sysbus_create_simple("ls7a_rtc", LS7A_RTC_REG_BASE,
  qdev_get_gpio_in(pch_pic,
  LS7A_RTC_IRQ - PCH_PIC_IRQ_OFFSET));
+
+pm_mem = g_new(MemoryRegion, 1);
+memory_region_init_io(pm_mem, NULL, &loongarch_virt_pm_ops,
+  NULL, "loongarch_virt_pm", PM_SIZE);
+memory_region_add_subregion(get_system_memory(), PM_BASE, pm_mem);
 }
 
 static void loongarch_irq_init(LoongArchMachineState *lams)
-- 
2.34.1




[PULL 22/43] target/loongarch: Add MMU support for LoongArch CPU.

2022-06-06 Thread Richard Henderson
From: Xiaojuan Yang 

Signed-off-by: Xiaojuan Yang 
Signed-off-by: Song Gao 
Reviewed-by: Richard Henderson 
Message-Id: <20220606124333.2060567-23-yangxiaoj...@loongson.cn>
Signed-off-by: Richard Henderson 
---
 target/loongarch/cpu-param.h  |   2 +-
 target/loongarch/cpu.h|  51 ++
 target/loongarch/internals.h  |   9 +
 target/loongarch/cpu.c|  24 +++
 target/loongarch/machine.c|  17 ++
 target/loongarch/tlb_helper.c | 315 ++
 target/loongarch/meson.build  |   1 +
 7 files changed, 418 insertions(+), 1 deletion(-)
 create mode 100644 target/loongarch/tlb_helper.c

diff --git a/target/loongarch/cpu-param.h b/target/loongarch/cpu-param.h
index 9a769b67e0..414d8fff46 100644
--- a/target/loongarch/cpu-param.h
+++ b/target/loongarch/cpu-param.h
@@ -13,6 +13,6 @@
 #define TARGET_VIRT_ADDR_SPACE_BITS 48
 
 #define TARGET_PAGE_BITS 14
-#define NB_MMU_MODES 4
+#define NB_MMU_MODES 5
 
 #endif
diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h
index 3ec978f47c..e0415d8929 100644
--- a/target/loongarch/cpu.h
+++ b/target/loongarch/cpu.h
@@ -184,6 +184,26 @@ FIELD(CSR_CRMD, WE, 9, 1)
 extern const char * const regnames[32];
 extern const char * const fregnames[32];
 
+#define LOONGARCH_STLB 2048 /* 2048 STLB */
+#define LOONGARCH_MTLB 64   /* 64 MTLB */
+#define LOONGARCH_TLB_MAX  (LOONGARCH_STLB + LOONGARCH_MTLB)
+
+/*
+ * define the ASID PS E VPPN field of TLB
+ */
+FIELD(TLB_MISC, E, 0, 1)
+FIELD(TLB_MISC, ASID, 1, 10)
+FIELD(TLB_MISC, VPPN, 13, 35)
+FIELD(TLB_MISC, PS, 48, 6)
+
+struct LoongArchTLB {
+uint64_t tlb_misc;
+/* Fields corresponding to CSR_TLBELO0/1 */
+uint64_t tlb_entry0;
+uint64_t tlb_entry1;
+};
+typedef struct LoongArchTLB LoongArchTLB;
+
 typedef struct CPUArchState {
 uint64_t gpr[32];
 uint64_t pc;
@@ -256,6 +276,8 @@ typedef struct CPUArchState {
 uint64_t CSR_DBG;
 uint64_t CSR_DERA;
 uint64_t CSR_DSAVE;
+
+LoongArchTLB  tlb[LOONGARCH_TLB_MAX];
 } CPULoongArchState;
 
 /**
@@ -294,6 +316,35 @@ struct LoongArchCPUClass {
 DeviceReset parent_reset;
 };
 
+/*
+ * LoongArch CPUs has 4 privilege levels.
+ * 0 for kernel mode, 3 for user mode.
+ * Define an extra index for DA(direct addressing) mode.
+ */
+#define MMU_KERNEL_IDX   0
+#define MMU_USER_IDX 3
+#define MMU_DA_IDX   4
+
+static inline int cpu_mmu_index(CPULoongArchState *env, bool ifetch)
+{
+uint8_t pg = FIELD_EX64(env->CSR_CRMD, CSR_CRMD, PG);
+
+if (!pg) {
+return MMU_DA_IDX;
+}
+return FIELD_EX64(env->CSR_CRMD, CSR_CRMD, PLV);
+}
+
+static inline void cpu_get_tb_cpu_state(CPULoongArchState *env,
+target_ulong *pc,
+target_ulong *cs_base,
+uint32_t *flags)
+{
+*pc = env->pc;
+*cs_base = 0;
+*flags = cpu_mmu_index(env, false);
+}
+
 void loongarch_cpu_list(void);
 
 #define cpu_list loongarch_cpu_list
diff --git a/target/loongarch/internals.h b/target/loongarch/internals.h
index 39960dee27..2fed768653 100644
--- a/target/loongarch/internals.h
+++ b/target/loongarch/internals.h
@@ -13,6 +13,9 @@
 #define FCMP_UN   0b0100  /* unordered */
 #define FCMP_GT   0b1000  /* fp0 > fp1 */
 
+#define TARGET_PHYS_MASK MAKE_64BIT_MASK(0, TARGET_PHYS_ADDR_SPACE_BITS)
+#define TARGET_VIRT_MASK MAKE_64BIT_MASK(0, TARGET_VIRT_ADDR_SPACE_BITS)
+
 void loongarch_translate_init(void);
 
 void loongarch_cpu_dump_state(CPUState *cpu, FILE *f, int flags);
@@ -27,4 +30,10 @@ void restore_fp_status(CPULoongArchState *env);
 
 extern const VMStateDescription vmstate_loongarch_cpu;
 
+bool loongarch_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
+MMUAccessType access_type, int mmu_idx,
+bool probe, uintptr_t retaddr);
+
+hwaddr loongarch_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
+
 #endif
diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
index aa0e1f9167..9a5cabbf4c 100644
--- a/target/loongarch/cpu.c
+++ b/target/loongarch/cpu.c
@@ -303,6 +303,21 @@ void loongarch_cpu_dump_state(CPUState *cs, FILE *f, int 
flags)
 }
 }
 
+qemu_fprintf(f, "CRMD=%016" PRIx64 "\n", env->CSR_CRMD);
+qemu_fprintf(f, "PRMD=%016" PRIx64 "\n", env->CSR_PRMD);
+qemu_fprintf(f, "EUEN=%016" PRIx64 "\n", env->CSR_EUEN);
+qemu_fprintf(f, "ESTAT=%016" PRIx64 "\n", env->CSR_ESTAT);
+qemu_fprintf(f, "ERA=%016" PRIx64 "\n", env->CSR_ERA);
+qemu_fprintf(f, "BADV=%016" PRIx64 "\n", env->CSR_BADV);
+qemu_fprintf(f, "BADI=%016" PRIx64 "\n", env->CSR_BADI);
+qemu_fprintf(f, "EENTRY=%016" PRIx64 "\n", env->CSR_EENTRY);
+qemu_fprintf(f, "PRCFG1=%016" PRIx64 ", PRCFG2=%016" PRIx64 ","
+ " PRCFG3=%016" PRIx64 "\n",
+ env->CSR_PRCFG1, env->CSR_PRCFG3, env->CSR_PRCFG3);
+qemu_fprintf(f, "TLBRENTRY=%016" PRIx64 "\n", env->CSR_TLBRENTRY);
+qemu_fpri

[PULL 28/43] target/loongarch: Add other core instructions support

2022-06-06 Thread Richard Henderson
From: Xiaojuan Yang 

This includes:
-CACOP
-LDDIR
-LDPTE
-ERTN
-DBCL
-IDLE

Signed-off-by: Xiaojuan Yang 
Signed-off-by: Song Gao 
Reviewed-by: Richard Henderson 
Message-Id: <20220606124333.2060567-29-yangxiaoj...@loongson.cn>
Signed-off-by: Richard Henderson 
---
 target/loongarch/helper.h |  5 +
 target/loongarch/internals.h  |  5 +
 target/loongarch/insns.decode | 11 +++
 target/loongarch/disas.c  | 17 
 target/loongarch/op_helper.c  | 37 
 target/loongarch/tlb_helper.c | 93 +++
 .../insn_trans/trans_privileged.c.inc | 65 +
 7 files changed, 233 insertions(+)

diff --git a/target/loongarch/helper.h b/target/loongarch/helper.h
index b092ca75fe..626fc32e1e 100644
--- a/target/loongarch/helper.h
+++ b/target/loongarch/helper.h
@@ -121,3 +121,8 @@ DEF_HELPER_2(invtlb_all_g, void, env, i32)
 DEF_HELPER_2(invtlb_all_asid, void, env, tl)
 DEF_HELPER_3(invtlb_page_asid, void, env, tl, tl)
 DEF_HELPER_3(invtlb_page_asid_or_g, void, env, tl, tl)
+
+DEF_HELPER_4(lddir, tl, env, tl, tl, i32)
+DEF_HELPER_4(ldpte, void, env, tl, tl, i32)
+DEF_HELPER_1(ertn, void, env)
+DEF_HELPER_1(idle, void, env)
diff --git a/target/loongarch/internals.h b/target/loongarch/internals.h
index 4b1bcd7c0f..a410c41c37 100644
--- a/target/loongarch/internals.h
+++ b/target/loongarch/internals.h
@@ -16,6 +16,11 @@
 #define TARGET_PHYS_MASK MAKE_64BIT_MASK(0, TARGET_PHYS_ADDR_SPACE_BITS)
 #define TARGET_VIRT_MASK MAKE_64BIT_MASK(0, TARGET_VIRT_ADDR_SPACE_BITS)
 
+/* Global bit used for lddir/ldpte */
+#define LOONGARCH_PAGE_HUGE_SHIFT   6
+/* Global bit for huge page */
+#define LOONGARCH_HGLOBAL_SHIFT 12
+
 void loongarch_translate_init(void);
 
 void loongarch_cpu_dump_state(CPUState *cpu, FILE *f, int flags);
diff --git a/target/loongarch/insns.decode b/target/loongarch/insns.decode
index f8ed11d83e..ebd3d505fb 100644
--- a/target/loongarch/insns.decode
+++ b/target/loongarch/insns.decode
@@ -49,6 +49,8 @@
 &rr_csr   rd rj csr
 &empty
 &i_rr imm rj rk
+&cop_r_i  cop rj imm
+&j_i  rj imm
 
 #
 # Formats
@@ -60,6 +62,7 @@
 @r_i20   ... imm:s20 rd:5&r_i
 @rr_ui5     . imm:5 rj:5 rd:5&rr_i
 @rr_ui6   imm:6 rj:5 rd:5&rr_i
+@rr_ui8  ..   imm:8 rj:5 rd:5&rr_i
 @rr_i12  .. imm:s12 rj:5 rd:5&rr_i
 @rr_ui12  .. imm:12 rj:5 rd:5&rr_i
 @rr_i14s2    .. rj:5 rd:5&rr_i imm=%i14s2
@@ -93,6 +96,8 @@
 @rr_csr  csr:14 rj:5 rd:5&rr_csr
 @empty    . . . .&empty
 @i_rr .. .. . rk:5 rj:5 imm:5&i_rr
+@cop_r_i   ..  imm:s12 rj:5 cop:5&cop_r_i
+@j_i     .. imm:8 rj:5 .&j_i
 
 #
 # Fixed point arithmetic operation instruction
@@ -470,3 +475,9 @@ tlbfill   01100100 1 01101 0 0
@empty
 tlbclr    01100100 1 01000 0 0@empty
 tlbflush  01100100 1 01001 0 0@empty
 invtlb    01100100 10011 . . .@i_rr
+cacop 011000  . . @cop_r_i
+lddir 01100100 00  . .@rr_ui8
+ldpte 01100100 01  . 0@j_i
+ertn  01100100 1 01110 0 0@empty
+idle  01100100 10001 ...  @i15
+dbcl  0010 10101 ...  @i15
diff --git a/target/loongarch/disas.c b/target/loongarch/disas.c
index 6a56607302..9d790b172c 100644
--- a/target/loongarch/disas.c
+++ b/target/loongarch/disas.c
@@ -314,6 +314,17 @@ static void output_i_rr(DisasContext *ctx, arg_i_rr *a, 
const char *mnemonic)
 output(ctx, mnemonic, "%d, r%d, r%d", a->imm, a->rj, a->rk);
 }
 
+static void output_cop_r_i(DisasContext *ctx, arg_cop_r_i *a,
+   const char *mnemonic)
+{
+output(ctx, mnemonic, "%d, r%d, %d", a->cop, a->rj, a->imm);
+}
+
+static void output_j_i(DisasContext *ctx, arg_j_i *a, const char *mnemonic)
+{
+output(ctx, mnemonic, "r%d, %d", a->rj, a->imm);
+}
+
 #define INSN(insn, type)\
 static bool trans_##insn(DisasContext *ctx, arg_##type * a) \
 {   \
@@ -641,6 +652,12 @@ INSN(tlbfill,  empty)
 INSN(tlbclr,   empty)
 INSN(tlbflush, empty)
 INSN(invtlb,   i_rr)
+INSN(cacop,cop_r_i)
+INSN(lddir,rr_i)
+INSN(ldpte,j_i)
+INSN(ertn, empty)
+INSN(idle, i)
+INSN(dbcl, i)
 
 #define output_fcmp(C, PREFIX, SUFFIX) 
\
 {   

[PULL 24/43] target/loongarch: Add constant timer support

2022-06-06 Thread Richard Henderson
From: Xiaojuan Yang 

Signed-off-by: Xiaojuan Yang 
Signed-off-by: Song Gao 
Reviewed-by: Richard Henderson 
Message-Id: <20220606124333.2060567-25-yangxiaoj...@loongson.cn>
Signed-off-by: Richard Henderson 
---
 target/loongarch/cpu.h|  4 ++
 target/loongarch/internals.h  |  6 +++
 target/loongarch/constant_timer.c | 64 +++
 target/loongarch/cpu.c|  2 +
 target/loongarch/meson.build  |  1 +
 5 files changed, 77 insertions(+)
 create mode 100644 target/loongarch/constant_timer.c

diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h
index b983ce241c..2081902f2e 100644
--- a/target/loongarch/cpu.h
+++ b/target/loongarch/cpu.h
@@ -11,6 +11,7 @@
 #include "exec/cpu-defs.h"
 #include "fpu/softfloat-types.h"
 #include "hw/registerfields.h"
+#include "qemu/timer.h"
 
 #define TCG_GUEST_DEFAULT_MO (0)
 
@@ -185,6 +186,8 @@ extern const char * const regnames[32];
 extern const char * const fregnames[32];
 
 #define N_IRQS  13
+#define IRQ_TIMER   11
+#define IRQ_IPI 12
 
 #define LOONGARCH_STLB 2048 /* 2048 STLB */
 #define LOONGARCH_MTLB 64   /* 64 MTLB */
@@ -295,6 +298,7 @@ struct ArchCPU {
 
 CPUNegativeOffsetState neg;
 CPULoongArchState env;
+QEMUTimer timer;
 };
 
 #define TYPE_LOONGARCH_CPU "loongarch-cpu"
diff --git a/target/loongarch/internals.h b/target/loongarch/internals.h
index 69183e8bb5..4b1bcd7c0f 100644
--- a/target/loongarch/internals.h
+++ b/target/loongarch/internals.h
@@ -32,6 +32,12 @@ extern const VMStateDescription vmstate_loongarch_cpu;
 
 void loongarch_cpu_set_irq(void *opaque, int irq, int level);
 
+void loongarch_constant_timer_cb(void *opaque);
+uint64_t cpu_loongarch_get_constant_timer_counter(LoongArchCPU *cpu);
+uint64_t cpu_loongarch_get_constant_timer_ticks(LoongArchCPU *cpu);
+void cpu_loongarch_store_constant_timer_config(LoongArchCPU *cpu,
+   uint64_t value);
+
 bool loongarch_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
 MMUAccessType access_type, int mmu_idx,
 bool probe, uintptr_t retaddr);
diff --git a/target/loongarch/constant_timer.c 
b/target/loongarch/constant_timer.c
new file mode 100644
index 00..1851f53fd6
--- /dev/null
+++ b/target/loongarch/constant_timer.c
@@ -0,0 +1,64 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * QEMU LoongArch constant timer support
+ *
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/timer.h"
+#include "cpu.h"
+#include "internals.h"
+#include "cpu-csr.h"
+
+#define TIMER_PERIOD10 /* 10 ns period for 100 MHz frequency */
+#define CONSTANT_TIMER_TICK_MASK0xfffcUL
+#define CONSTANT_TIMER_ENABLE   0x1UL
+
+uint64_t cpu_loongarch_get_constant_timer_counter(LoongArchCPU *cpu)
+{
+return qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) / TIMER_PERIOD;
+}
+
+uint64_t cpu_loongarch_get_constant_timer_ticks(LoongArchCPU *cpu)
+{
+uint64_t now, expire;
+
+now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
+expire = timer_expire_time_ns(&cpu->timer);
+
+return (expire - now) / TIMER_PERIOD;
+}
+
+void cpu_loongarch_store_constant_timer_config(LoongArchCPU *cpu,
+   uint64_t value)
+{
+CPULoongArchState *env = &cpu->env;
+uint64_t now, next;
+
+env->CSR_TCFG = value;
+if (value & CONSTANT_TIMER_ENABLE) {
+now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
+next = now + (value & CONSTANT_TIMER_TICK_MASK) * TIMER_PERIOD;
+timer_mod(&cpu->timer, next);
+} else {
+timer_del(&cpu->timer);
+}
+}
+
+void loongarch_constant_timer_cb(void *opaque)
+{
+LoongArchCPU *cpu  = opaque;
+CPULoongArchState *env = &cpu->env;
+uint64_t now, next;
+
+if (FIELD_EX64(env->CSR_TCFG, CSR_TCFG, PERIODIC)) {
+now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
+next = now + (env->CSR_TCFG & CONSTANT_TIMER_TICK_MASK) * TIMER_PERIOD;
+timer_mod(&cpu->timer, next);
+} else {
+env->CSR_TCFG = FIELD_DP64(env->CSR_TCFG, CSR_TCFG, EN, 0);
+}
+
+loongarch_cpu_set_irq(opaque, IRQ_TIMER, 1);
+}
diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
index 01a0b4878a..5ec0ba1cfa 100644
--- a/target/loongarch/cpu.c
+++ b/target/loongarch/cpu.c
@@ -495,6 +495,8 @@ static void loongarch_cpu_init(Object *obj)
 
 cpu_set_cpustate_pointers(cpu);
 qdev_init_gpio_in(DEVICE(cpu), loongarch_cpu_set_irq, N_IRQS);
+timer_init_ns(&cpu->timer, QEMU_CLOCK_VIRTUAL,
+  &loongarch_constant_timer_cb, cpu);
 }
 
 static ObjectClass *loongarch_cpu_class_by_name(const char *cpu_model)
diff --git a/target/loongarch/meson.build b/target/loongarch/meson.build
index 435cc75999..04e15ba1e3 100644
--- a/target/loongarch/meson.build
+++ b/target/loongarch/meson.build
@@ -18,6 +18,7 @@ loongarch_softmmu_ss = ss.source

[PULL 29/43] target/loongarch: Add timer related instructions support.

2022-06-06 Thread Richard Henderson
From: Xiaojuan Yang 

This includes:
-RDTIME{L/H}.W
-RDTIME.D

Signed-off-by: Xiaojuan Yang 
Signed-off-by: Song Gao 
Reviewed-by: Richard Henderson 
Message-Id: <20220606124333.2060567-30-yangxiaoj...@loongson.cn>
Signed-off-by: Richard Henderson 
---
 target/loongarch/helper.h |  2 ++
 target/loongarch/insns.decode |  3 ++
 target/loongarch/disas.c  |  3 ++
 target/loongarch/op_helper.c  | 13 
 target/loongarch/translate.c  |  2 ++
 target/loongarch/insn_trans/trans_extra.c.inc | 33 +++
 6 files changed, 56 insertions(+)

diff --git a/target/loongarch/helper.h b/target/loongarch/helper.h
index 626fc32e1e..85c11a60d4 100644
--- a/target/loongarch/helper.h
+++ b/target/loongarch/helper.h
@@ -93,6 +93,8 @@ DEF_HELPER_2(frint_d, i64, env, i64)
 
 DEF_HELPER_FLAGS_2(set_rounding_mode, TCG_CALL_NO_RWG, void, env, i32)
 
+DEF_HELPER_1(rdtime_d, i64, env)
+
 /* CSRs helper */
 DEF_HELPER_1(csrrd_pgd, i64, env)
 DEF_HELPER_1(csrrd_tval, i64, env)
diff --git a/target/loongarch/insns.decode b/target/loongarch/insns.decode
index ebd3d505fb..3fdc6e148c 100644
--- a/target/loongarch/insns.decode
+++ b/target/loongarch/insns.decode
@@ -309,6 +309,9 @@ break    0010 10100 ...  
@i15
 syscall  0010 10110 ...  @i15
 asrtle_d  00010 . . 0@rr_jk
 asrtgt_d  00011 . . 0@rr_jk
+rdtimel_w     0 11000 . .@rr
+rdtimeh_w     0 11001 . .@rr
+rdtime_d  0 11010 . .@rr
 cpucfg    0 11011 . .@rr
 
 #
diff --git a/target/loongarch/disas.c b/target/loongarch/disas.c
index 9d790b172c..858dfcc53a 100644
--- a/target/loongarch/disas.c
+++ b/target/loongarch/disas.c
@@ -352,6 +352,9 @@ INSN(bitrev_w, rr)
 INSN(bitrev_d, rr)
 INSN(ext_w_h,  rr)
 INSN(ext_w_b,  rr)
+INSN(rdtimel_w,rr)
+INSN(rdtimeh_w,rr)
+INSN(rdtime_d, rr)
 INSN(cpucfg,   rr)
 INSN(asrtle_d, rr_jk)
 INSN(asrtgt_d, rr_jk)
diff --git a/target/loongarch/op_helper.c b/target/loongarch/op_helper.c
index a9ba72d5b2..d87049851f 100644
--- a/target/loongarch/op_helper.c
+++ b/target/loongarch/op_helper.c
@@ -84,6 +84,19 @@ target_ulong helper_cpucfg(CPULoongArchState *env, 
target_ulong rj)
 return rj > 21 ? 0 : env->cpucfg[rj];
 }
 
+uint64_t helper_rdtime_d(CPULoongArchState *env)
+{
+uint64_t plv;
+LoongArchCPU *cpu = env_archcpu(env);
+
+plv = FIELD_EX64(env->CSR_CRMD, CSR_CRMD, PLV);
+if (extract64(env->CSR_MISC, R_CSR_MISC_DRDTL_SHIFT + plv, 1)) {
+do_raise_exception(env, EXCCODE_IPE, GETPC());
+}
+
+return cpu_loongarch_get_constant_timer_counter(cpu);
+}
+
 void helper_ertn(CPULoongArchState *env)
 {
 uint64_t csr_pplv, csr_pie;
diff --git a/target/loongarch/translate.c b/target/loongarch/translate.c
index 0f098924a3..c9afd11420 100644
--- a/target/loongarch/translate.c
+++ b/target/loongarch/translate.c
@@ -25,6 +25,8 @@ static TCGv cpu_lladdr, cpu_llval;
 TCGv_i32 cpu_fcsr0;
 TCGv_i64 cpu_fpr[32];
 
+#include "exec/gen-icount.h"
+
 #define DISAS_STOPDISAS_TARGET_0
 #define DISAS_EXITDISAS_TARGET_1
 #define DISAS_EXIT_UPDATE DISAS_TARGET_2
diff --git a/target/loongarch/insn_trans/trans_extra.c.inc 
b/target/loongarch/insn_trans/trans_extra.c.inc
index 549f75a867..ad713cd61e 100644
--- a/target/loongarch/insn_trans/trans_extra.c.inc
+++ b/target/loongarch/insn_trans/trans_extra.c.inc
@@ -33,6 +33,39 @@ static bool trans_asrtgt_d(DisasContext *ctx, arg_asrtgt_d * 
a)
 return true;
 }
 
+static bool gen_rdtime(DisasContext *ctx, arg_rr *a,
+   bool word, bool high)
+{
+TCGv dst1 = gpr_dst(ctx, a->rd, EXT_NONE);
+TCGv dst2 = gpr_dst(ctx, a->rj, EXT_NONE);
+
+if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
+gen_io_start();
+}
+gen_helper_rdtime_d(dst1, cpu_env);
+if (word) {
+tcg_gen_sextract_tl(dst1, dst1, high ? 32 : 0, 32);
+}
+tcg_gen_ld_i64(dst2, cpu_env, offsetof(CPULoongArchState, CSR_TID));
+
+return true;
+}
+
+static bool trans_rdtimel_w(DisasContext *ctx, arg_rdtimel_w *a)
+{
+return gen_rdtime(ctx, a, 1, 0);
+}
+
+static bool trans_rdtimeh_w(DisasContext *ctx, arg_rdtimeh_w *a)
+{
+return gen_rdtime(ctx, a, 1, 1);
+}
+
+static bool trans_rdtime_d(DisasContext *ctx, arg_rdtime_d *a)
+{
+return gen_rdtime(ctx, a, 0, 0);
+}
+
 static bool trans_cpucfg(DisasContext *ctx, arg_cpucfg *a)
 {
 TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE);
-- 
2.34.1




[PULL 26/43] target/loongarch: Add LoongArch IOCSR instruction

2022-06-06 Thread Richard Henderson
From: Xiaojuan Yang 

This includes:
- IOCSR{RD/WR}.{B/H/W/D}

Signed-off-by: Xiaojuan Yang 
Signed-off-by: Song Gao 
Reviewed-by: Richard Henderson 
Message-Id: <20220606124333.2060567-27-yangxiaoj...@loongson.cn>
Signed-off-by: Richard Henderson 
---
 target/loongarch/cpu.h| 25 +++
 target/loongarch/helper.h |  8 +++
 target/loongarch/insns.decode |  9 +++
 target/loongarch/cpu.c| 44 
 target/loongarch/disas.c  |  8 +++
 target/loongarch/iocsr_helper.c   | 67 +++
 .../insn_trans/trans_privileged.c.inc | 35 ++
 target/loongarch/meson.build  |  1 +
 8 files changed, 197 insertions(+)
 create mode 100644 target/loongarch/iocsr_helper.c

diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h
index 2081902f2e..03cc96ee9b 100644
--- a/target/loongarch/cpu.h
+++ b/target/loongarch/cpu.h
@@ -12,6 +12,27 @@
 #include "fpu/softfloat-types.h"
 #include "hw/registerfields.h"
 #include "qemu/timer.h"
+#include "exec/memory.h"
+#include "hw/sysbus.h"
+
+#define IOCSRF_TEMP 0
+#define IOCSRF_NODECNT  1
+#define IOCSRF_MSI  2
+#define IOCSRF_EXTIOI   3
+#define IOCSRF_CSRIPI   4
+#define IOCSRF_FREQCSR  5
+#define IOCSRF_FREQSCALE6
+#define IOCSRF_DVFSV1   7
+#define IOCSRF_GMOD 9
+#define IOCSRF_VM   11
+
+#define FEATURE_REG 0x8
+#define VENDOR_REG  0x10
+#define CPUNAME_REG 0x20
+#define MISC_FUNC_REG   0x420
+#define IOCSRM_EXTIOI_EN48
+
+#define IOCSR_MEM_SIZE  0x428
 
 #define TCG_GUEST_DEFAULT_MO (0)
 
@@ -283,6 +304,10 @@ typedef struct CPUArchState {
 uint64_t CSR_DSAVE;
 
 LoongArchTLB  tlb[LOONGARCH_TLB_MAX];
+
+AddressSpace address_space_iocsr;
+MemoryRegion system_iocsr;
+MemoryRegion iocsr_mem;
 } CPULoongArchState;
 
 /**
diff --git a/target/loongarch/helper.h b/target/loongarch/helper.h
index 5a6754eb65..4664a02dcf 100644
--- a/target/loongarch/helper.h
+++ b/target/loongarch/helper.h
@@ -100,3 +100,11 @@ DEF_HELPER_2(csrwr_estat, i64, env, tl)
 DEF_HELPER_2(csrwr_asid, i64, env, tl)
 DEF_HELPER_2(csrwr_tcfg, i64, env, tl)
 DEF_HELPER_2(csrwr_ticlr, i64, env, tl)
+DEF_HELPER_2(iocsrrd_b, i64, env, tl)
+DEF_HELPER_2(iocsrrd_h, i64, env, tl)
+DEF_HELPER_2(iocsrrd_w, i64, env, tl)
+DEF_HELPER_2(iocsrrd_d, i64, env, tl)
+DEF_HELPER_3(iocsrwr_b, void, env, tl, tl)
+DEF_HELPER_3(iocsrwr_h, void, env, tl, tl)
+DEF_HELPER_3(iocsrwr_w, void, env, tl, tl)
+DEF_HELPER_3(iocsrwr_d, void, env, tl, tl)
diff --git a/target/loongarch/insns.decode b/target/loongarch/insns.decode
index 43005ca283..2b436d3cd6 100644
--- a/target/loongarch/insns.decode
+++ b/target/loongarch/insns.decode
@@ -450,3 +450,12 @@ bgeu0110 11  . . 
@rr_offs16
   csrwr  0100 .. 1 . @r_csr
   csrxchg    0100 .. . . @rr_csr
 }
+
+iocsrrd_b 01100100 1 0 . .@rr
+iocsrrd_h 01100100 1 1 . .@rr
+iocsrrd_w 01100100 1 00010 . .@rr
+iocsrrd_d 01100100 1 00011 . .@rr
+iocsrwr_b 01100100 1 00100 . .@rr
+iocsrwr_h 01100100 1 00101 . .@rr
+iocsrwr_w 01100100 1 00110 . .@rr
+iocsrwr_d 01100100 1 00111 . .@rr
diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
index 5ec0ba1cfa..b846bd1a8b 100644
--- a/target/loongarch/cpu.c
+++ b/target/loongarch/cpu.c
@@ -17,6 +17,8 @@
 #include "internals.h"
 #include "fpu/softfloat-helpers.h"
 #include "cpu-csr.h"
+#include "sysemu/reset.h"
+#include "hw/loader.h"
 
 const char * const regnames[32] = {
 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
@@ -489,14 +491,56 @@ static void loongarch_cpu_realizefn(DeviceState *dev, 
Error **errp)
 lacc->parent_realize(dev, errp);
 }
 
+static void loongarch_qemu_write(void *opaque, hwaddr addr,
+ uint64_t val, unsigned size)
+{
+}
+
+static uint64_t loongarch_qemu_read(void *opaque, hwaddr addr, unsigned size)
+{
+switch (addr) {
+case FEATURE_REG:
+return 1ULL << IOCSRF_MSI | 1ULL << IOCSRF_EXTIOI |
+   1ULL << IOCSRF_CSRIPI;
+case VENDOR_REG:
+return 0x6e6f73676e6f6f4cULL; /* "Loongson" */
+case CPUNAME_REG:
+return 0x303030354133ULL; /* "3A5000" */
+case MISC_FUNC_REG:
+return 1ULL << IOCSRM_EXTIOI_EN;
+}
+return 0ULL;
+}
+
+static const MemoryRegionOps loongarch_qemu_ops = {
+.read = loongarch_qemu_read,
+.write = loongarch_qemu_write,
+.endianness = DEVICE_LITTLE_ENDIAN,
+.valid = {
+.min_access_size = 4,
+.max_access_size = 8,

[PULL 30/43] hw/loongarch: Add support loongson3 virt machine type.

2022-06-06 Thread Richard Henderson
From: Xiaojuan Yang 

Emulate a 3A5000 board use the new loongarch instruction.
3A5000 belongs to the Loongson3 series processors.
The board consists of a 3A5000 cpu model and the virt
bridge. The host 3A5000 board is really complicated and
contains many functions.Now for the tcg softmmu mode
only part functions are emulated.

More detailed info you can see
https://github.com/loongson/LoongArch-Documentation

Signed-off-by: Xiaojuan Yang 
Signed-off-by: Song Gao 
Reviewed-by: Richard Henderson 
Message-Id: <20220606124333.2060567-31-yangxiaoj...@loongson.cn>
Signed-off-by: Richard Henderson 
---
 .../devices/loongarch64-softmmu/default.mak   |  3 +
 configs/targets/loongarch64-softmmu.mak   |  3 +
 qapi/machine.json |  2 +-
 include/exec/poison.h |  2 +
 include/hw/loongarch/virt.h   | 31 ++
 include/sysemu/arch_init.h|  1 +
 hw/loongarch/loongson3.c  | 94 +++
 target/loongarch/cpu.c|  2 +
 MAINTAINERS   |  4 +
 hw/Kconfig|  1 +
 hw/loongarch/Kconfig  |  4 +
 hw/loongarch/meson.build  |  4 +
 hw/meson.build|  1 +
 target/Kconfig|  1 +
 target/loongarch/Kconfig  |  2 +
 15 files changed, 154 insertions(+), 1 deletion(-)
 create mode 100644 configs/devices/loongarch64-softmmu/default.mak
 create mode 100644 configs/targets/loongarch64-softmmu.mak
 create mode 100644 include/hw/loongarch/virt.h
 create mode 100644 hw/loongarch/loongson3.c
 create mode 100644 hw/loongarch/Kconfig
 create mode 100644 hw/loongarch/meson.build
 create mode 100644 target/loongarch/Kconfig

diff --git a/configs/devices/loongarch64-softmmu/default.mak 
b/configs/devices/loongarch64-softmmu/default.mak
new file mode 100644
index 00..928bc117ef
--- /dev/null
+++ b/configs/devices/loongarch64-softmmu/default.mak
@@ -0,0 +1,3 @@
+# Default configuration for loongarch64-softmmu
+
+CONFIG_LOONGARCH_VIRT=y
diff --git a/configs/targets/loongarch64-softmmu.mak 
b/configs/targets/loongarch64-softmmu.mak
new file mode 100644
index 00..666154022f
--- /dev/null
+++ b/configs/targets/loongarch64-softmmu.mak
@@ -0,0 +1,3 @@
+TARGET_ARCH=loongarch64
+TARGET_BASE_ARCH=loongarch
+TARGET_SUPPORTS_MTTCG=y
diff --git a/qapi/machine.json b/qapi/machine.json
index 883ce3f9ea..f750a16396 100644
--- a/qapi/machine.json
+++ b/qapi/machine.json
@@ -30,7 +30,7 @@
 ##
 { 'enum' : 'SysEmuTarget',
   'data' : [ 'aarch64', 'alpha', 'arm', 'avr', 'cris', 'hppa', 'i386',
- 'm68k', 'microblaze', 'microblazeel', 'mips', 'mips64',
+ 'loongarch64', 'm68k', 'microblaze', 'microblazeel', 'mips', 
'mips64',
  'mips64el', 'mipsel', 'nios2', 'or1k', 'ppc',
  'ppc64', 'riscv32', 'riscv64', 'rx', 's390x', 'sh4',
  'sh4eb', 'sparc', 'sparc64', 'tricore',
diff --git a/include/exec/poison.h b/include/exec/poison.h
index 9f1ca3409c..bbb82cf9ec 100644
--- a/include/exec/poison.h
+++ b/include/exec/poison.h
@@ -14,6 +14,7 @@
 #pragma GCC poison TARGET_CRIS
 #pragma GCC poison TARGET_HEXAGON
 #pragma GCC poison TARGET_HPPA
+#pragma GCC poison TARGET_LOONGARCH64
 #pragma GCC poison TARGET_M68K
 #pragma GCC poison TARGET_MICROBLAZE
 #pragma GCC poison TARGET_MIPS
@@ -71,6 +72,7 @@
 #pragma GCC poison CONFIG_HPPA_DIS
 #pragma GCC poison CONFIG_I386_DIS
 #pragma GCC poison CONFIG_HEXAGON_DIS
+#pragma GCC poison CONFIG_LOONGARCH_DIS
 #pragma GCC poison CONFIG_M68K_DIS
 #pragma GCC poison CONFIG_MICROBLAZE_DIS
 #pragma GCC poison CONFIG_MIPS_DIS
diff --git a/include/hw/loongarch/virt.h b/include/hw/loongarch/virt.h
new file mode 100644
index 00..4a4bb3f51f
--- /dev/null
+++ b/include/hw/loongarch/virt.h
@@ -0,0 +1,31 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Definitions for loongarch board emulation.
+ *
+ * Copyright (C) 2021 Loongson Technology Corporation Limited
+ */
+
+#ifndef HW_LOONGARCH_H
+#define HW_LOONGARCH_H
+
+#include "target/loongarch/cpu.h"
+#include "hw/boards.h"
+#include "qemu/queue.h"
+
+#define LOONGARCH_MAX_VCPUS 4
+
+#define LOONGARCH_ISA_IO_BASE   0x1800UL
+#define LOONGARCH_ISA_IO_SIZE   0x0004000
+
+struct LoongArchMachineState {
+/*< private >*/
+MachineState parent_obj;
+
+MemoryRegion lowmem;
+MemoryRegion highmem;
+MemoryRegion isa_io;
+};
+
+#define TYPE_LOONGARCH_MACHINE  MACHINE_TYPE_NAME("virt")
+OBJECT_DECLARE_SIMPLE_TYPE(LoongArchMachineState, LOONGARCH_MACHINE)
+#endif
diff --git a/include/sysemu/arch_init.h b/include/sysemu/arch_init.h
index 79c2591425..8850cb1a14 100644
--- a/include/sysemu/arch_init.h
+++ b/include/sysemu/arch_init.h
@@ -24,6 +24,7 @@ enum {
 QEMU_ARCH_RX = (1 << 20),
 QEMU_ARCH_AVR = (1 << 21),
 QEMU_ARCH_HEXAGON = (1 << 22),
+QEMU_ARCH_LOONGAR

[PULL 35/43] hw/loongarch: Add irq hierarchy for the system

2022-06-06 Thread Richard Henderson
From: Xiaojuan Yang 

This patch add the irq hierarchy for the virt board.

Signed-off-by: Xiaojuan Yang 
Signed-off-by: Song Gao 
Reviewed-by: Richard Henderson 
Message-Id: <20220606124333.2060567-36-yangxiaoj...@loongson.cn>
Signed-off-by: Richard Henderson 
---
 hw/loongarch/loongson3.c | 104 +++
 1 file changed, 104 insertions(+)

diff --git a/hw/loongarch/loongson3.c b/hw/loongarch/loongson3.c
index 7df32f777e..7a5c61e2df 100644
--- a/hw/loongarch/loongson3.c
+++ b/hw/loongarch/loongson3.c
@@ -16,8 +16,110 @@
 #include "sysemu/rtc.h"
 #include "hw/loongarch/virt.h"
 #include "exec/address-spaces.h"
+#include "hw/intc/loongarch_ipi.h"
+#include "hw/intc/loongarch_extioi.h"
+#include "hw/intc/loongarch_pch_pic.h"
+#include "hw/intc/loongarch_pch_msi.h"
+#include "hw/pci-host/ls7a.h"
+
 #include "target/loongarch/cpu.h"
 
+static void loongarch_irq_init(LoongArchMachineState *lams)
+{
+MachineState *ms = MACHINE(lams);
+DeviceState *pch_pic, *pch_msi, *cpudev;
+DeviceState *ipi, *extioi;
+SysBusDevice *d;
+LoongArchCPU *lacpu;
+CPULoongArchState *env;
+CPUState *cpu_state;
+int cpu, pin, i;
+
+ipi = qdev_new(TYPE_LOONGARCH_IPI);
+sysbus_realize_and_unref(SYS_BUS_DEVICE(ipi), &error_fatal);
+
+extioi = qdev_new(TYPE_LOONGARCH_EXTIOI);
+sysbus_realize_and_unref(SYS_BUS_DEVICE(extioi), &error_fatal);
+
+/*
+ * The connection of interrupts:
+ *   +-++-+ +---+
+ *   | IPI |--> | CPUINTC | <-- | Timer |
+ *   +-++-+ +---+
+ *  ^
+ *  |
+ *+-+
+ *| EIOINTC |
+ *+-+
+ * ^   ^
+ * |   |
+ *  +-+ +-+
+ *  | PCH-PIC | | PCH-MSI |
+ *  +-+ +-+
+ *^  ^  ^
+ *|  |  |
+ * ++ +-+ +-+
+ * | UARTs  | | Devices | | Devices |
+ * ++ +-+ +-+
+ */
+for (cpu = 0; cpu < ms->smp.cpus; cpu++) {
+cpu_state = qemu_get_cpu(cpu);
+cpudev = DEVICE(cpu_state);
+lacpu = LOONGARCH_CPU(cpu_state);
+env = &(lacpu->env);
+
+/* connect ipi irq to cpu irq */
+qdev_connect_gpio_out(ipi, cpu, qdev_get_gpio_in(cpudev, IRQ_IPI));
+/* IPI iocsr memory region */
+memory_region_add_subregion(&env->system_iocsr, SMP_IPI_MAILBOX,
+sysbus_mmio_get_region(SYS_BUS_DEVICE(ipi),
+cpu));
+/* extioi iocsr memory region */
+memory_region_add_subregion(&env->system_iocsr, APIC_BASE,
+sysbus_mmio_get_region(SYS_BUS_DEVICE(extioi),
+cpu));
+}
+
+/*
+ * connect ext irq to the cpu irq
+ * cpu_pin[9:2] <= intc_pin[7:0]
+ */
+for (cpu = 0; cpu < ms->smp.cpus; cpu++) {
+cpudev = DEVICE(qemu_get_cpu(cpu));
+for (pin = 0; pin < LS3A_INTC_IP; pin++) {
+qdev_connect_gpio_out(extioi, (cpu * 8 + pin),
+  qdev_get_gpio_in(cpudev, pin + 2));
+}
+}
+
+pch_pic = qdev_new(TYPE_LOONGARCH_PCH_PIC);
+d = SYS_BUS_DEVICE(pch_pic);
+sysbus_realize_and_unref(d, &error_fatal);
+memory_region_add_subregion(get_system_memory(), LS7A_IOAPIC_REG_BASE,
+sysbus_mmio_get_region(d, 0));
+memory_region_add_subregion(get_system_memory(),
+LS7A_IOAPIC_REG_BASE + PCH_PIC_ROUTE_ENTRY_OFFSET,
+sysbus_mmio_get_region(d, 1));
+memory_region_add_subregion(get_system_memory(),
+LS7A_IOAPIC_REG_BASE + PCH_PIC_INT_STATUS_LO,
+sysbus_mmio_get_region(d, 2));
+
+/* Connect 64 pch_pic irqs to extioi */
+for (int i = 0; i < PCH_PIC_IRQ_NUM; i++) {
+qdev_connect_gpio_out(DEVICE(d), i, qdev_get_gpio_in(extioi, i));
+}
+
+pch_msi = qdev_new(TYPE_LOONGARCH_PCH_MSI);
+d = SYS_BUS_DEVICE(pch_msi);
+sysbus_realize_and_unref(d, &error_fatal);
+sysbus_mmio_map(d, 0, LS7A_PCH_MSI_ADDR_LOW);
+for (i = 0; i < PCH_MSI_IRQ_NUM; i++) {
+/* Connect 192 pch_msi irqs to extioi */
+qdev_connect_gpio_out(DEVICE(d), i,
+  qdev_get_gpio_in(extioi, i + PCH_MSI_IRQ_START));
+}
+}
+
 static void loongarch_init(MachineState *machine)
 {
 const char *cpu_model = machine->cpu_type;
@@ -63,6 +165,8 @@ static void loongarch_init(MachineState *machine)
  get_system_io(), 0, LOONGARCH_ISA_IO_SIZE);
 memory_region_add_subregion(address_space_mem, LOONGARCH_ISA_IO_BASE,
 &lams->isa_io);
+/* Initialize the IO interrupt subsystem */
+loongarch_irq_init(lams)

[PULL 31/43] hw/loongarch: Add LoongArch ipi interrupt support(IPI)

2022-06-06 Thread Richard Henderson
From: Xiaojuan Yang 

This patch realize the IPI interrupt controller.

Signed-off-by: Xiaojuan Yang 
Signed-off-by: Song Gao 
Reviewed-by: Richard Henderson 
Message-Id: <20220606124333.2060567-32-yangxiaoj...@loongson.cn>
Signed-off-by: Richard Henderson 
---
 include/hw/intc/loongarch_ipi.h |  52 +++
 include/hw/loongarch/virt.h |   2 +
 hw/intc/loongarch_ipi.c | 242 
 MAINTAINERS |   2 +
 hw/intc/Kconfig |   3 +
 hw/intc/meson.build |   1 +
 hw/intc/trace-events|   4 +
 hw/loongarch/Kconfig|   1 +
 8 files changed, 307 insertions(+)
 create mode 100644 include/hw/intc/loongarch_ipi.h
 create mode 100644 hw/intc/loongarch_ipi.c

diff --git a/include/hw/intc/loongarch_ipi.h b/include/hw/intc/loongarch_ipi.h
new file mode 100644
index 00..996ed7ea93
--- /dev/null
+++ b/include/hw/intc/loongarch_ipi.h
@@ -0,0 +1,52 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * LoongArch ipi interrupt header files
+ *
+ * Copyright (C) 2021 Loongson Technology Corporation Limited
+ */
+
+#ifndef HW_LOONGARCH_IPI_H
+#define HW_LOONGARCH_IPI_H
+
+#include "hw/sysbus.h"
+
+/* Mainy used by iocsr read and write */
+#define SMP_IPI_MAILBOX  0x1000ULL
+#define CORE_STATUS_OFF   0x0
+#define CORE_EN_OFF   0x4
+#define CORE_SET_OFF  0x8
+#define CORE_CLEAR_OFF0xc
+#define CORE_BUF_20   0x20
+#define CORE_BUF_28   0x28
+#define CORE_BUF_30   0x30
+#define CORE_BUF_38   0x38
+#define IOCSR_IPI_SEND0x40
+#define IOCSR_MAIL_SEND   0x48
+#define IOCSR_ANY_SEND0x158
+
+/* IPI system memory address */
+#define IPI_SYSTEM_MEM0x1fe01000
+
+#define MAX_IPI_CORE_NUM  4
+#define MAX_IPI_MBX_NUM   4
+
+#define TYPE_LOONGARCH_IPI "loongarch_ipi"
+OBJECT_DECLARE_SIMPLE_TYPE(LoongArchIPI, LOONGARCH_IPI)
+
+typedef struct IPICore {
+uint32_t status;
+uint32_t en;
+uint32_t set;
+uint32_t clear;
+/* 64bit buf divide into 2 32bit buf */
+uint32_t buf[MAX_IPI_MBX_NUM * 2];
+qemu_irq irq;
+} IPICore;
+
+struct LoongArchIPI {
+SysBusDevice parent_obj;
+MemoryRegion ipi_iocsr_mem[MAX_IPI_CORE_NUM];
+MemoryRegion ipi_system_mem[MAX_IPI_CORE_NUM];
+};
+
+#endif
diff --git a/include/hw/loongarch/virt.h b/include/hw/loongarch/virt.h
index 4a4bb3f51f..09a816191c 100644
--- a/include/hw/loongarch/virt.h
+++ b/include/hw/loongarch/virt.h
@@ -11,6 +11,7 @@
 #include "target/loongarch/cpu.h"
 #include "hw/boards.h"
 #include "qemu/queue.h"
+#include "hw/intc/loongarch_ipi.h"
 
 #define LOONGARCH_MAX_VCPUS 4
 
@@ -21,6 +22,7 @@ struct LoongArchMachineState {
 /*< private >*/
 MachineState parent_obj;
 
+IPICore ipi_core[MAX_IPI_CORE_NUM];
 MemoryRegion lowmem;
 MemoryRegion highmem;
 MemoryRegion isa_io;
diff --git a/hw/intc/loongarch_ipi.c b/hw/intc/loongarch_ipi.c
new file mode 100644
index 00..66bee93675
--- /dev/null
+++ b/hw/intc/loongarch_ipi.c
@@ -0,0 +1,242 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * LoongArch ipi interrupt support
+ *
+ * Copyright (C) 2021 Loongson Technology Corporation Limited
+ */
+
+#include "qemu/osdep.h"
+#include "hw/sysbus.h"
+#include "hw/intc/loongarch_ipi.h"
+#include "hw/irq.h"
+#include "qapi/error.h"
+#include "qemu/log.h"
+#include "exec/address-spaces.h"
+#include "hw/loongarch/virt.h"
+#include "migration/vmstate.h"
+#include "target/loongarch/internals.h"
+#include "trace.h"
+
+static uint64_t loongarch_ipi_readl(void *opaque, hwaddr addr, unsigned size)
+{
+IPICore *s = opaque;
+uint64_t ret = 0;
+int index = 0;
+
+addr &= 0xff;
+switch (addr) {
+case CORE_STATUS_OFF:
+ret = s->status;
+break;
+case CORE_EN_OFF:
+ret = s->en;
+break;
+case CORE_SET_OFF:
+ret = 0;
+break;
+case CORE_CLEAR_OFF:
+ret = 0;
+break;
+case CORE_BUF_20 ... CORE_BUF_38 + 4:
+index = (addr - CORE_BUF_20) >> 2;
+ret = s->buf[index];
+break;
+default:
+qemu_log_mask(LOG_UNIMP, "invalid read: %x", (uint32_t)addr);
+break;
+}
+
+trace_loongarch_ipi_read(size, (uint64_t)addr, ret);
+return ret;
+}
+
+static int get_ipi_data(target_ulong val)
+{
+int i, mask, data;
+
+data = val >> 32;
+mask = (val >> 27) & 0xf;
+
+for (i = 0; i < 4; i++) {
+if ((mask >> i) & 1) {
+data &= ~(0xff << (i * 8));
+}
+}
+return data;
+}
+
+static void ipi_send(uint64_t val)
+{
+int cpuid, data;
+CPULoongArchState *env;
+
+cpuid = (val >> 16) & 0x3ff;
+/* IPI status vector */
+data = 1 << (val & 0x1f);
+qemu_mutex_lock_iothread();
+CPUState *cs = qemu_get_cpu(cpuid);
+LoongArchCPU *cpu = LOONGARCH_CPU(cs);
+env = &cpu->env;
+loongarch_cpu_set_irq(cpu, IRQ_IPI, 1);
+qemu_mutex_unlock_iothread();

[PULL 25/43] target/loongarch: Add LoongArch CSR instruction

2022-06-06 Thread Richard Henderson
From: Xiaojuan Yang 

This includes:
- CSRRD
- CSRWR
- CSRXCHG

Signed-off-by: Xiaojuan Yang 
Signed-off-by: Song Gao 
Reviewed-by: Richard Henderson 
Message-Id: <20220606124333.2060567-26-yangxiaoj...@loongson.cn>
Signed-off-by: Richard Henderson 
---
 target/loongarch/helper.h |   8 +
 target/loongarch/insns.decode |  13 +
 target/loongarch/csr_helper.c |  87 ++
 target/loongarch/disas.c  | 101 +++
 target/loongarch/translate.c  |  11 +-
 .../insn_trans/trans_privileged.c.inc | 264 ++
 target/loongarch/meson.build  |   1 +
 7 files changed, 484 insertions(+), 1 deletion(-)
 create mode 100644 target/loongarch/csr_helper.c
 create mode 100644 target/loongarch/insn_trans/trans_privileged.c.inc

diff --git a/target/loongarch/helper.h b/target/loongarch/helper.h
index da1a2bced7..5a6754eb65 100644
--- a/target/loongarch/helper.h
+++ b/target/loongarch/helper.h
@@ -92,3 +92,11 @@ DEF_HELPER_2(frint_s, i64, env, i64)
 DEF_HELPER_2(frint_d, i64, env, i64)
 
 DEF_HELPER_FLAGS_2(set_rounding_mode, TCG_CALL_NO_RWG, void, env, i32)
+
+/* CSRs helper */
+DEF_HELPER_1(csrrd_pgd, i64, env)
+DEF_HELPER_1(csrrd_tval, i64, env)
+DEF_HELPER_2(csrwr_estat, i64, env, tl)
+DEF_HELPER_2(csrwr_asid, i64, env, tl)
+DEF_HELPER_2(csrwr_tcfg, i64, env, tl)
+DEF_HELPER_2(csrwr_ticlr, i64, env, tl)
diff --git a/target/loongarch/insns.decode b/target/loongarch/insns.decode
index 9b293dfdf9..43005ca283 100644
--- a/target/loongarch/insns.decode
+++ b/target/loongarch/insns.decode
@@ -45,6 +45,8 @@
 &c_offs   cj offs
 &offs offs
 &rr_offs  rj rd offs
+&r_csrrd csr
+&rr_csr   rd rj csr
 
 #
 # Formats
@@ -85,6 +87,8 @@
 @c_offs21   ..  .. cj:3 .&c_offs  
offs=%offs21
 @offs26 .. ..&offs
offs=%offs26
 @rr_offs16  ..  rj:5 rd:5&rr_offs 
offs=%offs16
+@r_csr  csr:14 . rd:5&r_csr
+@rr_csr  csr:14 rj:5 rd:5&rr_csr
 
 #
 # Fixed point arithmetic operation instruction
@@ -437,3 +441,12 @@ blt 0110 00  . . 
@rr_offs16
 bge 0110 01  . . @rr_offs16
 bltu0110 10  . . @rr_offs16
 bgeu0110 11  . . @rr_offs16
+
+#
+# Core instructions
+#
+{
+  csrrd  0100 .. 0 . @r_csr
+  csrwr  0100 .. 1 . @r_csr
+  csrxchg    0100 .. . . @rr_csr
+}
diff --git a/target/loongarch/csr_helper.c b/target/loongarch/csr_helper.c
new file mode 100644
index 00..24a9389364
--- /dev/null
+++ b/target/loongarch/csr_helper.c
@@ -0,0 +1,87 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * LoongArch emulation helpers for CSRs
+ *
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/main-loop.h"
+#include "cpu.h"
+#include "internals.h"
+#include "qemu/host-utils.h"
+#include "exec/helper-proto.h"
+#include "exec/exec-all.h"
+#include "exec/cpu_ldst.h"
+#include "hw/irq.h"
+#include "cpu-csr.h"
+#include "tcg/tcg-ldst.h"
+
+target_ulong helper_csrrd_pgd(CPULoongArchState *env)
+{
+int64_t v;
+
+if (env->CSR_TLBRERA & 0x1) {
+v = env->CSR_TLBRBADV;
+} else {
+v = env->CSR_BADV;
+}
+
+if ((v >> 63) & 0x1) {
+v = env->CSR_PGDH;
+} else {
+v = env->CSR_PGDL;
+}
+
+return v;
+}
+
+target_ulong helper_csrrd_tval(CPULoongArchState *env)
+{
+LoongArchCPU *cpu = env_archcpu(env);
+
+return cpu_loongarch_get_constant_timer_ticks(cpu);
+}
+
+target_ulong helper_csrwr_estat(CPULoongArchState *env, target_ulong val)
+{
+int64_t old_v = env->CSR_ESTAT;
+
+/* Only IS[1:0] can be written */
+env->CSR_ESTAT = deposit64(env->CSR_ESTAT, 0, 2, val);
+
+return old_v;
+}
+
+target_ulong helper_csrwr_asid(CPULoongArchState *env, target_ulong val)
+{
+int64_t old_v = env->CSR_ASID;
+
+/* Only ASID filed of CSR_ASID can be written */
+env->CSR_ASID = deposit64(env->CSR_ASID, 0, 10, val);
+if (old_v != env->CSR_ASID) {
+tlb_flush(env_cpu(env));
+}
+return old_v;
+}
+
+target_ulong helper_csrwr_tcfg(CPULoongArchState *env, target_ulong val)
+{
+LoongArchCPU *cpu = env_archcpu(env);
+int64_t old_v = env->CSR_TCFG;
+
+cpu_loongarch_store_constant_timer_config(cpu, val);
+
+return old_v;
+}
+
+target_ulong helper_csrwr_ticlr(CPULoongArchState *env, target_ulong val)
+{
+LoongArchCPU *cpu = env_archcpu(env);
+int64_t old_v = 0;
+
+if (val & 0x1) {
+loongarch_cpu_set_irq(cpu, IRQ_TIMER, 0);
+}
+return old_v;
+}
diff --git a/target/loongarch/disas.c b/targe

[PULL 33/43] hw/intc: Add LoongArch ls7a msi interrupt controller support(PCH-MSI)

2022-06-06 Thread Richard Henderson
From: Xiaojuan Yang 

This patch realize PCH-MSI interrupt controller.

Signed-off-by: Xiaojuan Yang 
Signed-off-by: Song Gao 
Reviewed-by: Richard Henderson 
Message-Id: <20220606124333.2060567-34-yangxiaoj...@loongson.cn>
Signed-off-by: Richard Henderson 
---
 include/hw/intc/loongarch_pch_msi.h | 20 
 include/hw/pci-host/ls7a.h  |  3 ++
 hw/intc/loongarch_pch_msi.c | 73 +
 hw/intc/Kconfig |  5 ++
 hw/intc/meson.build |  1 +
 hw/intc/trace-events|  3 ++
 hw/loongarch/Kconfig|  1 +
 7 files changed, 106 insertions(+)
 create mode 100644 include/hw/intc/loongarch_pch_msi.h
 create mode 100644 hw/intc/loongarch_pch_msi.c

diff --git a/include/hw/intc/loongarch_pch_msi.h 
b/include/hw/intc/loongarch_pch_msi.h
new file mode 100644
index 00..f668bfca7a
--- /dev/null
+++ b/include/hw/intc/loongarch_pch_msi.h
@@ -0,0 +1,20 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * LoongArch 7A1000 I/O interrupt controller definitions
+ *
+ * Copyright (C) 2021 Loongson Technology Corporation Limited
+ */
+
+#define TYPE_LOONGARCH_PCH_MSI "loongarch_pch_msi"
+OBJECT_DECLARE_SIMPLE_TYPE(LoongArchPCHMSI, LOONGARCH_PCH_MSI)
+
+/* Msi irq start start from 64 to 255 */
+#define PCH_MSI_IRQ_START   64
+#define PCH_MSI_IRQ_END 255
+#define PCH_MSI_IRQ_NUM 192
+
+struct LoongArchPCHMSI {
+SysBusDevice parent_obj;
+qemu_irq pch_msi_irq[PCH_MSI_IRQ_NUM];
+MemoryRegion msi_mmio;
+};
diff --git a/include/hw/pci-host/ls7a.h b/include/hw/pci-host/ls7a.h
index bf80e99ce1..089d3e5438 100644
--- a/include/hw/pci-host/ls7a.h
+++ b/include/hw/pci-host/ls7a.h
@@ -15,6 +15,9 @@
 #include "qemu/range.h"
 #include "qom/object.h"
 
+#define LS7A_PCI_MEM_BASE0x4000UL
+#define LS7A_PCI_MEM_SIZE0x4000UL
+
 #define LS7A_PCH_REG_BASE   0x1000UL
 #define LS7A_IOAPIC_REG_BASE(LS7A_PCH_REG_BASE)
 #define LS7A_PCH_MSI_ADDR_LOW   0x2FF0UL
diff --git a/hw/intc/loongarch_pch_msi.c b/hw/intc/loongarch_pch_msi.c
new file mode 100644
index 00..74bcdbdb48
--- /dev/null
+++ b/hw/intc/loongarch_pch_msi.c
@@ -0,0 +1,73 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * QEMU Loongson 7A1000 msi interrupt controller.
+ *
+ * Copyright (C) 2021 Loongson Technology Corporation Limited
+ */
+
+#include "qemu/osdep.h"
+#include "hw/sysbus.h"
+#include "hw/irq.h"
+#include "hw/intc/loongarch_pch_msi.h"
+#include "hw/intc/loongarch_pch_pic.h"
+#include "hw/pci/msi.h"
+#include "hw/misc/unimp.h"
+#include "migration/vmstate.h"
+#include "trace.h"
+
+static uint64_t loongarch_msi_mem_read(void *opaque, hwaddr addr, unsigned 
size)
+{
+return 0;
+}
+
+static void loongarch_msi_mem_write(void *opaque, hwaddr addr,
+uint64_t val, unsigned size)
+{
+LoongArchPCHMSI *s = LOONGARCH_PCH_MSI(opaque);
+int irq_num = val & 0xff;
+
+trace_loongarch_msi_set_irq(irq_num);
+assert(irq_num < PCH_MSI_IRQ_NUM);
+qemu_set_irq(s->pch_msi_irq[irq_num], 1);
+}
+
+static const MemoryRegionOps loongarch_pch_msi_ops = {
+.read  = loongarch_msi_mem_read,
+.write = loongarch_msi_mem_write,
+.endianness = DEVICE_LITTLE_ENDIAN,
+};
+
+static void pch_msi_irq_handler(void *opaque, int irq, int level)
+{
+LoongArchPCHMSI *s = LOONGARCH_PCH_MSI(opaque);
+
+qemu_set_irq(s->pch_msi_irq[irq], level);
+}
+
+static void loongarch_pch_msi_init(Object *obj)
+{
+LoongArchPCHMSI *s = LOONGARCH_PCH_MSI(obj);
+SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+
+memory_region_init_io(&s->msi_mmio, obj, &loongarch_pch_msi_ops,
+  s, TYPE_LOONGARCH_PCH_MSI, 0x8);
+sysbus_init_mmio(sbd, &s->msi_mmio);
+msi_nonbroken = true;
+
+qdev_init_gpio_out(DEVICE(obj), s->pch_msi_irq, PCH_MSI_IRQ_NUM);
+qdev_init_gpio_in(DEVICE(obj), pch_msi_irq_handler, PCH_MSI_IRQ_NUM);
+}
+
+static const TypeInfo loongarch_pch_msi_info = {
+.name  = TYPE_LOONGARCH_PCH_MSI,
+.parent= TYPE_SYS_BUS_DEVICE,
+.instance_size = sizeof(LoongArchPCHMSI),
+.instance_init = loongarch_pch_msi_init,
+};
+
+static void loongarch_pch_msi_register_types(void)
+{
+type_register_static(&loongarch_pch_msi_info);
+}
+
+type_init(loongarch_pch_msi_register_types)
diff --git a/hw/intc/Kconfig b/hw/intc/Kconfig
index 362980ca8c..58f550b865 100644
--- a/hw/intc/Kconfig
+++ b/hw/intc/Kconfig
@@ -94,3 +94,8 @@ config LOONGARCH_IPI
 config LOONGARCH_PCH_PIC
 bool
 select UNIMP
+
+config LOONGARCH_PCH_MSI
+select MSI_NONBROKEN
+bool
+select UNIMP
diff --git a/hw/intc/meson.build b/hw/intc/meson.build
index 03f13f1c49..1d407c046d 100644
--- a/hw/intc/meson.build
+++ b/hw/intc/meson.build
@@ -65,3 +65,4 @@ specific_ss.add(when: 'CONFIG_M68K_IRQC', if_true: 
files('m68k_irqc.c'))
 specific_ss.add(when: 'CONFIG_NIOS2_VIC', if_true: files('nios2_vic.c'))
 specific_ss.add(when: 'CONFIG_LOO

[PULL 36/43] Enable common virtio pci support for LoongArch

2022-06-06 Thread Richard Henderson
From: Xiaojuan Yang 

Signed-off-by: Xiaojuan Yang 
Signed-off-by: Song Gao 
Reviewed-by: Richard Henderson 
Message-Id: <20220606124333.2060567-37-yangxiaoj...@loongson.cn>
Signed-off-by: Richard Henderson 
---
 softmmu/qdev-monitor.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/softmmu/qdev-monitor.c b/softmmu/qdev-monitor.c
index 12fe60c467..bb5897fc76 100644
--- a/softmmu/qdev-monitor.c
+++ b/softmmu/qdev-monitor.c
@@ -60,7 +60,8 @@ typedef struct QDevAlias
   QEMU_ARCH_HPPA | QEMU_ARCH_I386 | \
   QEMU_ARCH_MIPS | QEMU_ARCH_PPC |  \
   QEMU_ARCH_RISCV | QEMU_ARCH_SH4 | \
-  QEMU_ARCH_SPARC | QEMU_ARCH_XTENSA)
+  QEMU_ARCH_SPARC | QEMU_ARCH_XTENSA | \
+  QEMU_ARCH_LOONGARCH)
 #define QEMU_ARCH_VIRTIO_CCW (QEMU_ARCH_S390X)
 #define QEMU_ARCH_VIRTIO_MMIO (QEMU_ARCH_M68K)
 
-- 
2.34.1




[PULL 34/43] hw/intc: Add LoongArch extioi interrupt controller(EIOINTC)

2022-06-06 Thread Richard Henderson
From: Xiaojuan Yang 

This patch realize the EIOINTC interrupt controller.

Signed-off-by: Xiaojuan Yang 
Signed-off-by: Song Gao 
Reviewed-by: Richard Henderson 
Message-Id: <20220606124333.2060567-35-yangxiaoj...@loongson.cn>
Signed-off-by: Richard Henderson 
---
 include/hw/intc/loongarch_extioi.h |  62 ++
 hw/intc/loongarch_extioi.c | 312 +
 hw/intc/Kconfig|   3 +
 hw/intc/meson.build|   1 +
 hw/intc/trace-events   |   6 +
 hw/loongarch/Kconfig   |   1 +
 6 files changed, 385 insertions(+)
 create mode 100644 include/hw/intc/loongarch_extioi.h
 create mode 100644 hw/intc/loongarch_extioi.c

diff --git a/include/hw/intc/loongarch_extioi.h 
b/include/hw/intc/loongarch_extioi.h
new file mode 100644
index 00..15b8c999f6
--- /dev/null
+++ b/include/hw/intc/loongarch_extioi.h
@@ -0,0 +1,62 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * LoongArch 3A5000 ext interrupt controller definitions
+ *
+ * Copyright (C) 2021 Loongson Technology Corporation Limited
+ */
+
+#include "hw/sysbus.h"
+#include "hw/loongarch/virt.h"
+
+#ifndef LOONGARCH_EXTIOI_H
+#define LOONGARCH_EXTIOI_H
+
+#define LS3A_INTC_IP   8
+#define EXTIOI_IRQS(256)
+#define EXTIOI_IRQS_BITMAP_SIZE(256 / 8)
+/* map to ipnum per 32 irqs */
+#define EXTIOI_IRQS_IPMAP_SIZE (256 / 32)
+#define EXTIOI_IRQS_COREMAP_SIZE   256
+#define EXTIOI_IRQS_NODETYPE_COUNT  16
+#define EXTIOI_IRQS_GROUP_COUNT8
+
+#define APIC_OFFSET  0x400
+#define APIC_BASE(0x1000ULL + APIC_OFFSET)
+
+#define EXTIOI_NODETYPE_START(0x4a0 - APIC_OFFSET)
+#define EXTIOI_NODETYPE_END  (0x4c0 - APIC_OFFSET)
+#define EXTIOI_IPMAP_START   (0x4c0 - APIC_OFFSET)
+#define EXTIOI_IPMAP_END (0x4c8 - APIC_OFFSET)
+#define EXTIOI_ENABLE_START  (0x600 - APIC_OFFSET)
+#define EXTIOI_ENABLE_END(0x620 - APIC_OFFSET)
+#define EXTIOI_BOUNCE_START  (0x680 - APIC_OFFSET)
+#define EXTIOI_BOUNCE_END(0x6a0 - APIC_OFFSET)
+#define EXTIOI_ISR_START (0x700 - APIC_OFFSET)
+#define EXTIOI_ISR_END   (0x720 - APIC_OFFSET)
+#define EXTIOI_COREISR_START (0x800 - APIC_OFFSET)
+#define EXTIOI_COREISR_END   (0xB20 - APIC_OFFSET)
+#define EXTIOI_COREMAP_START (0xC00 - APIC_OFFSET)
+#define EXTIOI_COREMAP_END   (0xD00 - APIC_OFFSET)
+
+#define TYPE_LOONGARCH_EXTIOI "loongarch.extioi"
+OBJECT_DECLARE_SIMPLE_TYPE(LoongArchExtIOI, LOONGARCH_EXTIOI)
+struct LoongArchExtIOI {
+SysBusDevice parent_obj;
+/* hardware state */
+uint32_t nodetype[EXTIOI_IRQS_NODETYPE_COUNT / 2];
+uint32_t bounce[EXTIOI_IRQS_GROUP_COUNT];
+uint32_t isr[EXTIOI_IRQS / 32];
+uint32_t coreisr[LOONGARCH_MAX_VCPUS][EXTIOI_IRQS_GROUP_COUNT];
+uint32_t enable[EXTIOI_IRQS / 32];
+uint32_t ipmap[EXTIOI_IRQS_IPMAP_SIZE / 4];
+uint32_t coremap[EXTIOI_IRQS / 4];
+uint32_t sw_pending[EXTIOI_IRQS / 32];
+DECLARE_BITMAP(sw_isr[LOONGARCH_MAX_VCPUS][LS3A_INTC_IP], EXTIOI_IRQS);
+uint8_t  sw_ipmap[EXTIOI_IRQS_IPMAP_SIZE];
+uint8_t  sw_coremap[EXTIOI_IRQS];
+qemu_irq parent_irq[LOONGARCH_MAX_VCPUS][LS3A_INTC_IP];
+qemu_irq irq[EXTIOI_IRQS];
+MemoryRegion extioi_iocsr_mem[LOONGARCH_MAX_VCPUS];
+MemoryRegion extioi_system_mem;
+};
+#endif /* LOONGARCH_EXTIOI_H */
diff --git a/hw/intc/loongarch_extioi.c b/hw/intc/loongarch_extioi.c
new file mode 100644
index 00..22803969bc
--- /dev/null
+++ b/hw/intc/loongarch_extioi.c
@@ -0,0 +1,312 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Loongson 3A5000 ext interrupt controller emulation
+ *
+ * Copyright (C) 2021 Loongson Technology Corporation Limited
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/module.h"
+#include "qemu/log.h"
+#include "hw/irq.h"
+#include "hw/sysbus.h"
+#include "hw/loongarch/virt.h"
+#include "hw/qdev-properties.h"
+#include "exec/address-spaces.h"
+#include "hw/intc/loongarch_extioi.h"
+#include "migration/vmstate.h"
+#include "trace.h"
+
+
+static void extioi_update_irq(LoongArchExtIOI *s, int irq, int level)
+{
+int ipnum, cpu, found, irq_index, irq_mask;
+
+ipnum = s->sw_ipmap[irq / 32];
+cpu = s->sw_coremap[irq];
+irq_index = irq / 32;
+irq_mask = 1 << (irq & 0x1f);
+
+if (level) {
+/* if not enable return false */
+if (((s->enable[irq_index]) & irq_mask) == 0) {
+return;
+}
+s->coreisr[cpu][irq_index] |= irq_mask;
+found = find_first_bit(s->sw_isr[cpu][ipnum], EXTIOI_IRQS);
+set_bit(irq, s->sw_isr[cpu][ipnum]);
+if (found < EXTIOI_IRQS) {
+/* other irq is handling, need not update parent irq level */
+return;
+}
+} else {
+s->coreisr[cpu][irq_index] &= ~irq_mask;
+clear_bit(irq, s->sw_isr[cpu][ipnum]);
+found = find_first_bit(s->sw_isr[c

[PULL 37/43] hw/loongarch: Add some devices support for 3A5000.

2022-06-06 Thread Richard Henderson
From: Xiaojuan Yang 

1.Add uart,virtio-net,vga and usb for 3A5000.
2.Add irq set and map for the pci host. Non pci device
use irq 0-16, pci device use 16-64.
3.Add some unimplented device to emulate guest unused
memory space.

Signed-off-by: Xiaojuan Yang 
Signed-off-by: Song Gao 
Acked-by: Richard Henderson 
Message-Id: <20220606124333.2060567-38-yangxiaoj...@loongson.cn>
Signed-off-by: Richard Henderson 
---
 include/hw/pci-host/ls7a.h |  7 
 hw/loongarch/loongson3.c   | 77 ++
 hw/loongarch/Kconfig   |  7 
 3 files changed, 91 insertions(+)

diff --git a/include/hw/pci-host/ls7a.h b/include/hw/pci-host/ls7a.h
index 089d3e5438..5c653527f0 100644
--- a/include/hw/pci-host/ls7a.h
+++ b/include/hw/pci-host/ls7a.h
@@ -17,6 +17,11 @@
 
 #define LS7A_PCI_MEM_BASE0x4000UL
 #define LS7A_PCI_MEM_SIZE0x4000UL
+#define LS7A_PCI_IO_OFFSET  0x4000
+#define LS_PCIECFG_BASE 0x2000
+#define LS_PCIECFG_SIZE 0x0800
+#define LS7A_PCI_IO_BASE0x18004000UL
+#define LS7A_PCI_IO_SIZE0xC000
 
 #define LS7A_PCH_REG_BASE   0x1000UL
 #define LS7A_IOAPIC_REG_BASE(LS7A_PCH_REG_BASE)
@@ -30,4 +35,6 @@
 #define PCH_PIC_IRQ_OFFSET  64
 #define LS7A_DEVICE_IRQS16
 #define LS7A_PCI_IRQS   48
+#define LS7A_UART_IRQ   (PCH_PIC_IRQ_OFFSET + 2)
+#define LS7A_UART_BASE  0x1fe001e0
 #endif
diff --git a/hw/loongarch/loongson3.c b/hw/loongarch/loongson3.c
index 7a5c61e2df..7bc17113dc 100644
--- a/hw/loongarch/loongson3.c
+++ b/hw/loongarch/loongson3.c
@@ -9,6 +9,7 @@
 #include "qemu/datadir.h"
 #include "qapi/error.h"
 #include "hw/boards.h"
+#include "hw/char/serial.h"
 #include "sysemu/sysemu.h"
 #include "sysemu/qtest.h"
 #include "sysemu/runstate.h"
@@ -16,14 +17,88 @@
 #include "sysemu/rtc.h"
 #include "hw/loongarch/virt.h"
 #include "exec/address-spaces.h"
+#include "hw/irq.h"
+#include "net/net.h"
 #include "hw/intc/loongarch_ipi.h"
 #include "hw/intc/loongarch_extioi.h"
 #include "hw/intc/loongarch_pch_pic.h"
 #include "hw/intc/loongarch_pch_msi.h"
 #include "hw/pci-host/ls7a.h"
+#include "hw/pci-host/gpex.h"
+#include "hw/misc/unimp.h"
 
 #include "target/loongarch/cpu.h"
 
+static void loongarch_devices_init(DeviceState *pch_pic)
+{
+DeviceState *gpex_dev;
+SysBusDevice *d;
+PCIBus *pci_bus;
+MemoryRegion *ecam_alias, *ecam_reg, *pio_alias, *pio_reg;
+MemoryRegion *mmio_alias, *mmio_reg;
+int i;
+
+gpex_dev = qdev_new(TYPE_GPEX_HOST);
+d = SYS_BUS_DEVICE(gpex_dev);
+sysbus_realize_and_unref(d, &error_fatal);
+pci_bus = PCI_HOST_BRIDGE(gpex_dev)->bus;
+
+/* Map only part size_ecam bytes of ECAM space */
+ecam_alias = g_new0(MemoryRegion, 1);
+ecam_reg = sysbus_mmio_get_region(d, 0);
+memory_region_init_alias(ecam_alias, OBJECT(gpex_dev), "pcie-ecam",
+ ecam_reg, 0, LS_PCIECFG_SIZE);
+memory_region_add_subregion(get_system_memory(), LS_PCIECFG_BASE,
+ecam_alias);
+
+/* Map PCI mem space */
+mmio_alias = g_new0(MemoryRegion, 1);
+mmio_reg = sysbus_mmio_get_region(d, 1);
+memory_region_init_alias(mmio_alias, OBJECT(gpex_dev), "pcie-mmio",
+ mmio_reg, LS7A_PCI_MEM_BASE, LS7A_PCI_MEM_SIZE);
+memory_region_add_subregion(get_system_memory(), LS7A_PCI_MEM_BASE,
+mmio_alias);
+
+/* Map PCI IO port space. */
+pio_alias = g_new0(MemoryRegion, 1);
+pio_reg = sysbus_mmio_get_region(d, 2);
+memory_region_init_alias(pio_alias, OBJECT(gpex_dev), "pcie-io", pio_reg,
+ LS7A_PCI_IO_OFFSET, LS7A_PCI_IO_SIZE);
+memory_region_add_subregion(get_system_memory(), LS7A_PCI_IO_BASE,
+pio_alias);
+
+for (i = 0; i < GPEX_NUM_IRQS; i++) {
+sysbus_connect_irq(d, i,
+   qdev_get_gpio_in(pch_pic, 16 + i));
+gpex_set_irq_num(GPEX_HOST(gpex_dev), i, 16 + i);
+}
+
+serial_mm_init(get_system_memory(), LS7A_UART_BASE, 0,
+   qdev_get_gpio_in(pch_pic,
+LS7A_UART_IRQ - PCH_PIC_IRQ_OFFSET),
+   115200, serial_hd(0), DEVICE_LITTLE_ENDIAN);
+
+/* Network init */
+for (i = 0; i < nb_nics; i++) {
+NICInfo *nd = &nd_table[i];
+
+if (!nd->model) {
+nd->model = g_strdup("virtio");
+}
+
+pci_nic_init_nofail(nd, pci_bus, nd->model, NULL);
+}
+
+/* VGA setup */
+pci_vga_init(pci_bus);
+
+/*
+ * There are some invalid guest memory access.
+ * Create some unimplemented devices to emulate this.
+ */
+create_unimplemented_device("pci-dma-cfg", 0x1001041c, 0x4);
+}
+
 static void loongarch_irq_init(LoongArchMachineState *lams)
 {
 MachineState *ms = MACHINE(lams);
@@ -118,6 +193,8 @@ static void loongarch_irq_init(LoongArchMachineState *lams)
 q

[PULL 32/43] hw/intc: Add LoongArch ls7a interrupt controller support(PCH-PIC)

2022-06-06 Thread Richard Henderson
From: Xiaojuan Yang 

This patch realize the PCH-PIC interrupt controller.

Signed-off-by: Xiaojuan Yang 
Signed-off-by: Song Gao 
Reviewed-by: Richard Henderson 
Message-Id: <20220606124333.2060567-33-yangxiaoj...@loongson.cn>
Signed-off-by: Richard Henderson 
---
 include/hw/intc/loongarch_pch_pic.h |  69 +
 include/hw/pci-host/ls7a.h  |  30 ++
 hw/intc/loongarch_pch_pic.c | 431 
 MAINTAINERS |   1 +
 hw/intc/Kconfig |   4 +
 hw/intc/meson.build |   1 +
 hw/intc/trace-events|   9 +
 hw/loongarch/Kconfig|   1 +
 8 files changed, 546 insertions(+)
 create mode 100644 include/hw/intc/loongarch_pch_pic.h
 create mode 100644 include/hw/pci-host/ls7a.h
 create mode 100644 hw/intc/loongarch_pch_pic.c

diff --git a/include/hw/intc/loongarch_pch_pic.h 
b/include/hw/intc/loongarch_pch_pic.h
new file mode 100644
index 00..2d4aa9ed6f
--- /dev/null
+++ b/include/hw/intc/loongarch_pch_pic.h
@@ -0,0 +1,69 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * LoongArch 7A1000 I/O interrupt controller definitions
+ *
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ */
+
+#define TYPE_LOONGARCH_PCH_PIC "loongarch_pch_pic"
+#define PCH_PIC_NAME(name) TYPE_LOONGARCH_PCH_PIC#name
+OBJECT_DECLARE_SIMPLE_TYPE(LoongArchPCHPIC, LOONGARCH_PCH_PIC)
+
+#define PCH_PIC_IRQ_START   0
+#define PCH_PIC_IRQ_END 63
+#define PCH_PIC_IRQ_NUM 64
+#define PCH_PIC_INT_ID_VAL  0x700UL
+#define PCH_PIC_INT_ID_NUM  0x3f0001UL
+
+#define PCH_PIC_INT_ID_LO   0x00
+#define PCH_PIC_INT_ID_HI   0x04
+#define PCH_PIC_INT_MASK_LO 0x20
+#define PCH_PIC_INT_MASK_HI 0x24
+#define PCH_PIC_HTMSI_EN_LO 0x40
+#define PCH_PIC_HTMSI_EN_HI 0x44
+#define PCH_PIC_INT_EDGE_LO 0x60
+#define PCH_PIC_INT_EDGE_HI 0x64
+#define PCH_PIC_INT_CLEAR_LO0x80
+#define PCH_PIC_INT_CLEAR_HI0x84
+#define PCH_PIC_AUTO_CTRL0_LO   0xc0
+#define PCH_PIC_AUTO_CTRL0_HI   0xc4
+#define PCH_PIC_AUTO_CTRL1_LO   0xe0
+#define PCH_PIC_AUTO_CTRL1_HI   0xe4
+#define PCH_PIC_ROUTE_ENTRY_OFFSET  0x100
+#define PCH_PIC_ROUTE_ENTRY_END 0x13f
+#define PCH_PIC_HTMSI_VEC_OFFSET0x200
+#define PCH_PIC_HTMSI_VEC_END   0x23f
+#define PCH_PIC_INT_STATUS_LO   0x3a0
+#define PCH_PIC_INT_STATUS_HI   0x3a4
+#define PCH_PIC_INT_POL_LO  0x3e0
+#define PCH_PIC_INT_POL_HI  0x3e4
+
+#define STATUS_LO_START 0
+#define STATUS_HI_START 0x4
+#define POL_LO_START0x40
+#define POL_HI_START0x44
+struct LoongArchPCHPIC {
+SysBusDevice parent_obj;
+qemu_irq parent_irq[64];
+uint64_t int_mask; /*0x020 interrupt mask register*/
+uint64_t htmsi_en; /*0x040 1=msi*/
+uint64_t intedge; /*0x060 edge=1 level  =0*/
+uint64_t intclr; /*0x080 for clean edge int,set 1 clean,set 0 is noused*/
+uint64_t auto_crtl0; /*0x0c0*/
+uint64_t auto_crtl1; /*0x0e0*/
+uint64_t last_intirr;/* edge detection */
+uint64_t intirr; /* 0x380 interrupt request register */
+uint64_t intisr; /* 0x3a0 interrupt service register */
+/*
+ * 0x3e0 interrupt level polarity selection
+ * register 0 for high level trigger
+ */
+uint64_t int_polarity;
+
+uint8_t route_entry[64]; /*0x100 - 0x138*/
+uint8_t htmsi_vector[64]; /*0x200 - 0x238*/
+
+MemoryRegion iomem32_low;
+MemoryRegion iomem32_high;
+MemoryRegion iomem8;
+};
diff --git a/include/hw/pci-host/ls7a.h b/include/hw/pci-host/ls7a.h
new file mode 100644
index 00..bf80e99ce1
--- /dev/null
+++ b/include/hw/pci-host/ls7a.h
@@ -0,0 +1,30 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * QEMU LoongArch CPU
+ *
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ */
+
+#ifndef HW_LS7A_H
+#define HW_LS7A_H
+
+#include "hw/pci/pci.h"
+#include "hw/pci/pcie_host.h"
+#include "hw/pci-host/pam.h"
+#include "qemu/units.h"
+#include "qemu/range.h"
+#include "qom/object.h"
+
+#define LS7A_PCH_REG_BASE   0x1000UL
+#define LS7A_IOAPIC_REG_BASE(LS7A_PCH_REG_BASE)
+#define LS7A_PCH_MSI_ADDR_LOW   0x2FF0UL
+
+/*
+ * According to the kernel pch irq start from 64 offset
+ * 0 ~ 16 irqs used for non-pci device while 16 ~ 64 irqs
+ * used for pci device.
+ */
+#define PCH_PIC_IRQ_OFFSET  64
+#define LS7A_DEVICE_IRQS16
+#define LS7A_PCI_IRQS   48
+#endif
diff --git a/hw/intc/loongarch_pch_pic.c b/hw/intc/loongarch_pch_pic.c
new file mode 100644
index 00..3c9814a3b4
--- /dev/null
+++ b/hw/intc/loongarch_pch_pic.c
@@ -0,0 +1,431 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * QEMU Loongson 7A1000 I/O interrupt controller.
+ *
+ * Copyrig

[PULL 42/43] tests/tcg/loongarch64: Add hello/memory test in loongarch64 system

2022-06-06 Thread Richard Henderson
From: Xiaojuan Yang 

- We write a very minimal softmmu harness.
- This is a very simple smoke test with no need to run a full Linux/kernel.
- The Makefile.softmmu-target record the rule to run.

Signed-off-by: Xiaojuan Yang 
Signed-off-by: Song Gao 
Reviewed-by: Richard Henderson 
Message-Id: <20220606124333.2060567-43-yangxiaoj...@loongson.cn>
Signed-off-by: Richard Henderson 
---
 tests/tcg/loongarch64/system/regdef.h | 86 +++
 MAINTAINERS   |  1 +
 tests/tcg/loongarch64/Makefile.softmmu-target | 33 +++
 tests/tcg/loongarch64/system/boot.S   | 56 
 tests/tcg/loongarch64/system/kernel.ld| 30 +++
 5 files changed, 206 insertions(+)
 create mode 100644 tests/tcg/loongarch64/system/regdef.h
 create mode 100644 tests/tcg/loongarch64/Makefile.softmmu-target
 create mode 100644 tests/tcg/loongarch64/system/boot.S
 create mode 100644 tests/tcg/loongarch64/system/kernel.ld

diff --git a/tests/tcg/loongarch64/system/regdef.h 
b/tests/tcg/loongarch64/system/regdef.h
new file mode 100644
index 00..faa09b2377
--- /dev/null
+++ b/tests/tcg/loongarch64/system/regdef.h
@@ -0,0 +1,86 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ */
+#ifndef _ASM_REGDEF_H
+#define _ASM_REGDEF_H
+
+#define zero$r0 /* wired zero */
+#define ra  $r1 /* return address */
+#define tp  $r2
+#define sp  $r3 /* stack pointer */
+#define v0  $r4 /* return value - caller saved */
+#define v1  $r5
+#define a0  $r4 /* argument registers */
+#define a1  $r5
+#define a2  $r6
+#define a3  $r7
+#define a4  $r8
+#define a5  $r9
+#define a6  $r10
+#define a7  $r11
+#define t0  $r12/* caller saved */
+#define t1  $r13
+#define t2  $r14
+#define t3  $r15
+#define t4  $r16
+#define t5  $r17
+#define t6  $r18
+#define t7  $r19
+#define t8  $r20
+/* $r21: Temporarily reserved */
+#define fp  $r22/* frame pointer */
+#define s0  $r23/* callee saved */
+#define s1  $r24
+#define s2  $r25
+#define s3  $r26
+#define s4  $r27
+#define s5  $r28
+#define s6  $r29
+#define s7  $r30
+#define s8  $r31
+
+#define gr0 $r0
+#define gr1 $r1
+#define gr2 $r2
+#define gr3 $r3
+#define gr4 $r4
+#define gr5 $r5
+#define gr6 $r6
+#define gr7 $r7
+#define gr8 $r8
+#define gr9 $r9
+#define gr10$r10
+#define gr11$r11
+#define gr12$r12
+#define gr13$r13
+#define gr14$r14
+#define gr15$r15
+#define gr16$r16
+#define gr17$r17
+#define gr18$r18
+#define gr19$r19
+#define gr20$r20
+#define gr21$r21
+#define gr22$r22
+#define gr23$r23
+#define gr24$r24
+#define gr25$r25
+#define gr26$r26
+#define gr27$r27
+#define gr28$r28
+#define gr29$r29
+#define gr30$r30
+#define gr31$r31
+
+#define STT_NOTYPE  0
+#define STT_OBJECT  1
+#define STT_FUNC2
+#define STT_SECTION 3
+#define STT_FILE4
+#define STT_COMMON  5
+#define STT_TLS 6
+
+#define ASM_NL   ;
+
+#endif /* _ASM_REGDEF_H */
diff --git a/MAINTAINERS b/MAINTAINERS
index 954fb95218..5580a36b68 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -217,6 +217,7 @@ M: Song Gao 
 M: Xiaojuan Yang 
 S: Maintained
 F: target/loongarch/
+F: tests/tcg/loongarch64/
 
 M68K TCG CPUs
 M: Laurent Vivier 
diff --git a/tests/tcg/loongarch64/Makefile.softmmu-target 
b/tests/tcg/loongarch64/Makefile.softmmu-target
new file mode 100644
index 00..908f3a8c0f
--- /dev/null
+++ b/tests/tcg/loongarch64/Makefile.softmmu-target
@@ -0,0 +1,33 @@
+#
+# Loongarch64 system tests
+#
+
+LOONGARCH64_SYSTEM_SRC=$(SRC_PATH)/tests/tcg/loongarch64/system
+VPATH+=$(LOONGARCH64_SYSTEM_SRC)
+
+# These objects provide the basic boot code and helper functions for all tests
+CRT_OBJS=boot.o
+
+LOONGARCH64_TEST_SRCS=$(wildcard $(LOONGARCH64_SYSTEM_SRC)/*.c)
+LOONGARCH64_TESTS = $(patsubst $(LOONGARCH64_SYSTEM_SRC)/%.c, %, 
$(LOONGARCH64_TEST_SRCS))
+
+CRT_PATH=$(LOONGARCH64_SYSTEM_SRC)
+LINK_SCRIPT=$(LOONGARCH64_SYSTEM_SRC)/kernel.ld
+LDFLAGS=-Wl,-T$(LINK_SCRIPT)
+TESTS+=$(LOONGARCH64_TESTS) $(MULTIARCH_TESTS)
+CFLAGS+=-nostdlib -g -O1 -march=loongarch64 -mabi=lp64d $(MINILIB_INC)
+LDFLAGS+=-static -nostdlib $(CRT_OBJS) $(MINILIB_OBJS) -lgcc
+
+# building head blobs
+.PRECIOUS: $(CRT_OBJS)
+
+%.o: $(CRT_PATH)/%.S
+   $(CC) $(CFLAGS) $(EXTRA_CFLAGS) -x assembler-with-cpp -c $< -o $@
+
+# Build and link the tests
+%: %.c $(LINK_SCRIPT) $(CRT_OBJS) $(MINILIB_OBJS)
+   $(CC) $(CFLAGS) $(EXTRA_CFLAGS) $< -o $@ $(LDFLAGS)
+
+memory: CFLAGS+=-DCHECK_UNALIGNED=0
+# Running
+QEMU_OPTS+=-serial chardev:output -kernel
diff --git a/tests/tcg/loongarch64/system/boot.S 
b/tests/tcg/loongarch64/system/boot.S
new file mode 100644
index 00..67eb1c04ce
--- /dev/null
+++ b/tests/tcg/loongar

[PULL 41/43] target/loongarch: Add gdb support.

2022-06-06 Thread Richard Henderson
From: Xiaojuan Yang 

Signed-off-by: Xiaojuan Yang 
Signed-off-by: Song Gao 
Reviewed-by: Richard Henderson 
Message-Id: <20220606124333.2060567-42-yangxiaoj...@loongson.cn>
Signed-off-by: Richard Henderson 
---
 configs/targets/loongarch64-softmmu.mak |  1 +
 target/loongarch/internals.h|  4 ++
 target/loongarch/cpu.c  |  9 +++
 target/loongarch/gdbstub.c  | 81 +
 MAINTAINERS |  1 +
 gdb-xml/loongarch-base64.xml| 44 ++
 gdb-xml/loongarch-fpu64.xml | 57 +
 target/loongarch/meson.build|  1 +
 8 files changed, 198 insertions(+)
 create mode 100644 target/loongarch/gdbstub.c
 create mode 100644 gdb-xml/loongarch-base64.xml
 create mode 100644 gdb-xml/loongarch-fpu64.xml

diff --git a/configs/targets/loongarch64-softmmu.mak 
b/configs/targets/loongarch64-softmmu.mak
index 666154022f..7bc06c850c 100644
--- a/configs/targets/loongarch64-softmmu.mak
+++ b/configs/targets/loongarch64-softmmu.mak
@@ -1,3 +1,4 @@
 TARGET_ARCH=loongarch64
 TARGET_BASE_ARCH=loongarch
 TARGET_SUPPORTS_MTTCG=y
+TARGET_XML_FILES= gdb-xml/loongarch-base64.xml gdb-xml/loongarch-fpu64.xml
diff --git a/target/loongarch/internals.h b/target/loongarch/internals.h
index a410c41c37..9d50fbdd81 100644
--- a/target/loongarch/internals.h
+++ b/target/loongarch/internals.h
@@ -49,4 +49,8 @@ bool loongarch_cpu_tlb_fill(CPUState *cs, vaddr address, int 
size,
 
 hwaddr loongarch_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
 
+int loongarch_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n);
+int loongarch_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n);
+void loongarch_cpu_register_gdb_regs_for_features(CPUState *cs);
+
 #endif
diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
index 3b7d6289d2..4c8f96bc3a 100644
--- a/target/loongarch/cpu.c
+++ b/target/loongarch/cpu.c
@@ -487,6 +487,8 @@ static void loongarch_cpu_realizefn(DeviceState *dev, Error 
**errp)
 return;
 }
 
+loongarch_cpu_register_gdb_regs_for_features(cs);
+
 cpu_reset(cs);
 qemu_init_vcpu(cs);
 
@@ -640,6 +642,13 @@ static void loongarch_cpu_class_init(ObjectClass *c, void 
*data)
 dc->vmsd = &vmstate_loongarch_cpu;
 cc->sysemu_ops = &loongarch_sysemu_ops;
 cc->disas_set_info = loongarch_cpu_disas_set_info;
+cc->gdb_read_register = loongarch_cpu_gdb_read_register;
+cc->gdb_write_register = loongarch_cpu_gdb_write_register;
+cc->disas_set_info = loongarch_cpu_disas_set_info;
+cc->gdb_num_core_regs = 34;
+cc->gdb_core_xml_file = "loongarch-base64.xml";
+cc->gdb_stop_before_watchpoint = true;
+
 #ifdef CONFIG_TCG
 cc->tcg_ops = &loongarch_tcg_ops;
 #endif
diff --git a/target/loongarch/gdbstub.c b/target/loongarch/gdbstub.c
new file mode 100644
index 00..0c48834201
--- /dev/null
+++ b/target/loongarch/gdbstub.c
@@ -0,0 +1,81 @@
+/*
+ * LOONGARCH gdb server stub
+ *
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ *
+ * SPDX-License-Identifier: LGPL-2.1+
+ */
+
+#include "qemu/osdep.h"
+#include "cpu.h"
+#include "internals.h"
+#include "exec/gdbstub.h"
+
+int loongarch_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
+{
+LoongArchCPU *cpu = LOONGARCH_CPU(cs);
+CPULoongArchState *env = &cpu->env;
+
+if (0 <= n && n < 32) {
+return gdb_get_regl(mem_buf, env->gpr[n]);
+} else if (n == 32) {
+return gdb_get_regl(mem_buf, env->pc);
+} else if (n == 33) {
+return gdb_get_regl(mem_buf, env->badaddr);
+}
+return 0;
+}
+
+int loongarch_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
+{
+LoongArchCPU *cpu = LOONGARCH_CPU(cs);
+CPULoongArchState *env = &cpu->env;
+target_ulong tmp = ldtul_p(mem_buf);
+int length = 0;
+
+if (0 <= n && n < 32) {
+env->gpr[n] = tmp;
+length = sizeof(target_ulong);
+} else if (n == 32) {
+env->pc = tmp;
+length = sizeof(target_ulong);
+}
+return length;
+}
+
+static int loongarch_gdb_get_fpu(CPULoongArchState *env,
+ GByteArray *mem_buf, int n)
+{
+if (0 <= n && n < 32) {
+return gdb_get_reg64(mem_buf, env->fpr[n]);
+} else if (32 <= n && n < 40) {
+return gdb_get_reg8(mem_buf, env->cf[n - 32]);
+} else if (n == 40) {
+return gdb_get_reg32(mem_buf, env->fcsr0);
+}
+return 0;
+}
+
+static int loongarch_gdb_set_fpu(CPULoongArchState *env,
+ uint8_t *mem_buf, int n)
+{
+int length = 0;
+
+if (0 <= n && n < 32) {
+env->fpr[n] = ldq_p(mem_buf);
+length = 8;
+} else if (32 <= n && n < 40) {
+env->cf[n - 32] = ldub_p(mem_buf);
+length = 1;
+} else if (n == 40) {
+env->fcsr0 = ldl_p(mem_buf);
+length = 4;
+}
+return length;
+}
+
+void loongarch_cpu_register_gdb_regs_for_feature

[PULL 39/43] hw/loongarch: Add LoongArch load elf function.

2022-06-06 Thread Richard Henderson
From: Xiaojuan Yang 

Signed-off-by: Xiaojuan Yang 
Signed-off-by: Song Gao 
Reviewed-by: Richard Henderson 
Message-Id: <20220606124333.2060567-40-yangxiaoj...@loongson.cn>
Signed-off-by: Richard Henderson 
---
 target/loongarch/cpu.h   |  2 ++
 hw/loongarch/loongson3.c | 61 ++--
 2 files changed, 61 insertions(+), 2 deletions(-)

diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h
index 03cc96ee9b..71a5036c3c 100644
--- a/target/loongarch/cpu.h
+++ b/target/loongarch/cpu.h
@@ -308,6 +308,8 @@ typedef struct CPUArchState {
 AddressSpace address_space_iocsr;
 MemoryRegion system_iocsr;
 MemoryRegion iocsr_mem;
+bool load_elf;
+uint64_t elf_address;
 } CPULoongArchState;
 
 /**
diff --git a/hw/loongarch/loongson3.c b/hw/loongarch/loongson3.c
index 95984c9086..3c8fcb828c 100644
--- a/hw/loongarch/loongson3.c
+++ b/hw/loongarch/loongson3.c
@@ -19,6 +19,8 @@
 #include "exec/address-spaces.h"
 #include "hw/irq.h"
 #include "net/net.h"
+#include "hw/loader.h"
+#include "elf.h"
 #include "hw/intc/loongarch_ipi.h"
 #include "hw/intc/loongarch_extioi.h"
 #include "hw/intc/loongarch_pch_pic.h"
@@ -29,6 +31,36 @@
 
 #include "target/loongarch/cpu.h"
 
+static struct _loaderparams {
+uint64_t ram_size;
+const char *kernel_filename;
+} loaderparams;
+
+static uint64_t cpu_loongarch_virt_to_phys(void *opaque, uint64_t addr)
+{
+return addr & 0x1fffll;
+}
+
+static int64_t load_kernel_info(void)
+{
+uint64_t kernel_entry, kernel_low, kernel_high;
+ssize_t kernel_size;
+
+kernel_size = load_elf(loaderparams.kernel_filename, NULL,
+   cpu_loongarch_virt_to_phys, NULL,
+   &kernel_entry, &kernel_low,
+   &kernel_high, NULL, 0,
+   EM_LOONGARCH, 1, 0);
+
+if (kernel_size < 0) {
+error_report("could not load kernel '%s': %s",
+ loaderparams.kernel_filename,
+ load_elf_strerror(kernel_size));
+exit(1);
+}
+return kernel_entry;
+}
+
 static void loongarch_devices_init(DeviceState *pch_pic)
 {
 DeviceState *gpex_dev;
@@ -200,15 +232,29 @@ static void loongarch_irq_init(LoongArchMachineState 
*lams)
 loongarch_devices_init(pch_pic);
 }
 
+static void reset_load_elf(void *opaque)
+{
+LoongArchCPU *cpu = opaque;
+CPULoongArchState *env = &cpu->env;
+
+cpu_reset(CPU(cpu));
+if (env->load_elf) {
+cpu_set_pc(CPU(cpu), env->elf_address);
+}
+}
+
 static void loongarch_init(MachineState *machine)
 {
 const char *cpu_model = machine->cpu_type;
+const char *kernel_filename = machine->kernel_filename;
 ram_addr_t offset = 0;
 ram_addr_t ram_size = machine->ram_size;
 uint64_t highram_size = 0;
 MemoryRegion *address_space_mem = get_system_memory();
 LoongArchMachineState *lams = LOONGARCH_MACHINE(machine);
+LoongArchCPU *lacpu;
 int i;
+int64_t kernel_addr = 0;
 
 if (!cpu_model) {
 cpu_model = LOONGARCH_CPU_TYPE_NAME("la464");
@@ -234,17 +280,28 @@ static void loongarch_init(MachineState *machine)
  machine->ram, 0, 256 * MiB);
 memory_region_add_subregion(address_space_mem, offset, &lams->lowmem);
 offset += 256 * MiB;
-
 highram_size = ram_size - 256 * MiB;
 memory_region_init_alias(&lams->highmem, NULL, "loongarch.highmem",
  machine->ram, offset, highram_size);
 memory_region_add_subregion(address_space_mem, 0x9000, &lams->highmem);
-
 /* Add isa io region */
 memory_region_init_alias(&lams->isa_io, NULL, "isa-io",
  get_system_io(), 0, LOONGARCH_ISA_IO_SIZE);
 memory_region_add_subregion(address_space_mem, LOONGARCH_ISA_IO_BASE,
 &lams->isa_io);
+if (kernel_filename) {
+loaderparams.ram_size = ram_size;
+loaderparams.kernel_filename = kernel_filename;
+kernel_addr = load_kernel_info();
+if (!machine->firmware) {
+for (i = 0; i < machine->smp.cpus; i++) {
+lacpu = LOONGARCH_CPU(qemu_get_cpu(i));
+lacpu->env.load_elf = true;
+lacpu->env.elf_address = kernel_addr;
+qemu_register_reset(reset_load_elf, lacpu);
+}
+}
+}
 /* Initialize the IO interrupt subsystem */
 loongarch_irq_init(lams);
 }
-- 
2.34.1




Re: [PATCH 03/21] aspeed: i2c: Migrate to registerfields API

2022-06-06 Thread Joel Stanley
On Mon, 6 Jun 2022 at 15:08, Cédric Le Goater  wrote:
>
> From: Joe Komlodi 
>
> This cleans up some of the field accessing, setting, and clearing
> bitwise operations, and wraps them in macros instead.

I don't really like this change, as it adds more project-specific
"jargon" to the models.

It's clumsy in that we can no longer take a case from our switch
statements and grep for it:

 git grep A_I2CD_FUN_CTRL

Don't consider this a nak, but I felt it was worth explaining.

>
> Signed-off-by: Joe Komlodi 
> Change-Id: I33018d6325fa04376e7c29dc4a49ab389a8e333a
> Message-Id: <20220331043248.2237838-4-koml...@google.com>
> Signed-off-by: Cédric Le Goater 
> ---
>  hw/i2c/aspeed_i2c.c | 393 ++--
>  1 file changed, 196 insertions(+), 197 deletions(-)
>
> diff --git a/hw/i2c/aspeed_i2c.c b/hw/i2c/aspeed_i2c.c
> index 97eb9d57929c..be81a798cc35 100644
> --- a/hw/i2c/aspeed_i2c.c
> +++ b/hw/i2c/aspeed_i2c.c
> @@ -28,70 +28,61 @@
>  #include "hw/i2c/aspeed_i2c.h"
>  #include "hw/irq.h"
>  #include "hw/qdev-properties.h"
> +#include "hw/registerfields.h"
>  #include "trace.h"
>
>  /* I2C Global Register */
> -
> -#define I2C_CTRL_STATUS 0x00/* Device Interrupt Status */
> -#define I2C_CTRL_ASSIGN 0x08/* Device Interrupt Target
> -   Assignment */
> -#define I2C_CTRL_GLOBAL 0x0C/* Global Control Register */
> -#define   I2C_CTRL_SRAM_EN BIT(0)
> +REG32(I2C_CTRL_STATUS, 0x0) /* Device Interrupt Status */
> +REG32(I2C_CTRL_ASSIGN, 0x8) /* Device Interrupt Target Assignment */
> +REG32(I2C_CTRL_GLOBAL, 0xC) /* Global Control Register */
> +FIELD(I2C_CTRL_GLOBAL, SRAM_EN, 0, 1)
>
>  /* I2C Device (Bus) Register */
> -
> -#define I2CD_FUN_CTRL_REG   0x00   /* I2CD Function Control  */
> -#define   I2CD_POOL_PAGE_SEL(x)(((x) >> 20) & 0x7)  /* AST2400 */
> -#define   I2CD_M_SDA_LOCK_EN   (0x1 << 16)
> -#define   I2CD_MULTI_MASTER_DIS(0x1 << 15)
> -#define   I2CD_M_SCL_DRIVE_EN  (0x1 << 14)
> -#define   I2CD_MSB_STS (0x1 << 9)
> -#define   I2CD_SDA_DRIVE_1T_EN (0x1 << 8)
> -#define   I2CD_M_SDA_DRIVE_1T_EN   (0x1 << 7)
> -#define   I2CD_M_HIGH_SPEED_EN (0x1 << 6)
> -#define   I2CD_DEF_ADDR_EN (0x1 << 5)
> -#define   I2CD_DEF_ALERT_EN(0x1 << 4)
> -#define   I2CD_DEF_ARP_EN  (0x1 << 3)
> -#define   I2CD_DEF_GCALL_EN(0x1 << 2)
> -#define   I2CD_SLAVE_EN(0x1 << 1)
> -#define   I2CD_MASTER_EN   (0x1)
> -
> -#define I2CD_AC_TIMING_REG1 0x04   /* Clock and AC Timing Control #1 
> */
> -#define I2CD_AC_TIMING_REG2 0x08   /* Clock and AC Timing Control #1 
> */
> -#define I2CD_INTR_CTRL_REG  0x0c   /* I2CD Interrupt Control */
> -#define I2CD_INTR_STS_REG   0x10   /* I2CD Interrupt Status */
> -
> -#define   I2CD_INTR_SLAVE_ADDR_MATCH   (0x1 << 31) /* 0: addr1 1: addr2 
> */
> -#define   I2CD_INTR_SLAVE_ADDR_RX_PENDING  (0x1 << 30)
> -/* bits[19-16] Reserved */
> -
> -/* All bits below are cleared by writing 1 */
> -#define   I2CD_INTR_SLAVE_INACTIVE_TIMEOUT (0x1 << 15)
> -#define   I2CD_INTR_SDA_DL_TIMEOUT (0x1 << 14)
> -#define   I2CD_INTR_BUS_RECOVER_DONE   (0x1 << 13)
> -#define   I2CD_INTR_SMBUS_ALERT(0x1 << 12) /* Bus [0-3] only */
> -#define   I2CD_INTR_SMBUS_ARP_ADDR (0x1 << 11) /* Removed */
> -#define   I2CD_INTR_SMBUS_DEV_ALERT_ADDR   (0x1 << 10) /* Removed */
> -#define   I2CD_INTR_SMBUS_DEF_ADDR (0x1 << 9)  /* Removed */
> -#define   I2CD_INTR_GCALL_ADDR (0x1 << 8)  /* Removed */
> -#define   I2CD_INTR_SLAVE_ADDR_RX_MATCH(0x1 << 7)  /* use RX_DONE */
> -#define   I2CD_INTR_SCL_TIMEOUT(0x1 << 6)
> -#define   I2CD_INTR_ABNORMAL   (0x1 << 5)
> -#define   I2CD_INTR_NORMAL_STOP(0x1 << 4)
> -#define   I2CD_INTR_ARBIT_LOSS (0x1 << 3)
> -#define   I2CD_INTR_RX_DONE(0x1 << 2)
> -#define   I2CD_INTR_TX_NAK (0x1 << 1)
> -#define   I2CD_INTR_TX_ACK (0x1 << 0)
> -
> -#define I2CD_CMD_REG0x14   /* I2CD Command/Status */
> -#define   I2CD_SDA_OE  (0x1 << 28)
> -#define   I2CD_SDA_O   (0x1 << 27)
> -#define   I2CD_SCL_OE  (0x1 << 26)
> -#define   I2CD_SCL_O   (0x1 << 25)
> -#define   I2CD_TX_TIMING   (0x1 << 24)
> -#define   I2CD_TX_STATUS   (0x1 << 23)
> -
> -#define   I2CD_TX_STATE_SHIFT  19 /* Tx State Machine */
> +REG32(I2CD_FUN_CTRL, 0x0) /* I2CD Function Control  */
> +FIELD(I2CD_FUN_CTRL, POOL_PAGE_SEL, 20, 3) /* AST2400 */
> +FIELD(I2CD_FUN_CTRL, M_SDA_LOCK_EN, 16, 1)
> +FIELD(I2CD_FUN_CTRL, MULTI_MASTER_DIS, 15, 1)
> +FIELD(I2CD_FUN_CT

Re: [PATCH 11/21] test/avocado/machine_aspeed.py: Add an I2C RTC test

2022-06-06 Thread Joel Stanley
On Mon, 6 Jun 2022 at 15:08, Cédric Le Goater  wrote:
>
> Add a RTC device on bus 15 and check that the ouput of the hwclock

spelling: output

> command matches the current year.
>
> Signed-off-by: Cédric Le Goater 

Reviewed-by: Joel Stanley 

> ---
>  tests/avocado/machine_aspeed.py | 8 
>  1 file changed, 8 insertions(+)
>
> diff --git a/tests/avocado/machine_aspeed.py b/tests/avocado/machine_aspeed.py
> index a3b4b9e5093c..28b8a4c8124b 100644
> --- a/tests/avocado/machine_aspeed.py
> +++ b/tests/avocado/machine_aspeed.py
> @@ -136,10 +136,18 @@ def test_arm_ast2600_evb_builroot(self):
>
>  self.vm.add_args('-device',
>   'tmp423,bus=aspeed.i2c.bus.15,address=0x4c');
> +self.vm.add_args('-device',
> + 'ds1338,bus=aspeed.i2c.bus.15,address=0x32');

Is there any value running this on the 2400 and 2500 machine types
too? They all use the same model so perhaps not?

>  self.do_test_arm_aspeed_buidroot_start(image_path, '0xf00')
>  exec_command_and_wait_for_pattern(self,
>'i2cget -y 15 0x4c 0xff', '0x23');
>  exec_command_and_wait_for_pattern(self,
>'i2cget -y 15 0x4c 0xfe', '0x55');
>
> +exec_command_and_wait_for_pattern(self,
> + 'echo ds1307 0x32 > 
> /sys/class/i2c-dev/i2c-15/device/new_device',
> + 'i2c i2c-15: new_device: Instantiated device ds1307 at 0x32');
> +year = time.strftime("%Y")
> +exec_command_and_wait_for_pattern(self, 'hwclock -f /dev/rtc1', 
> year);
> +
>  self.do_test_arm_aspeed_buidroot_poweroff()
> --
> 2.35.3
>



Re: [PATCH 04/21] aspeed: i2c: Use reg array instead of individual vars

2022-06-06 Thread Joel Stanley
On Mon, 6 Jun 2022 at 15:08, Cédric Le Goater  wrote:
>
> From: Joe Komlodi 
>
> Using a register array will allow us to represent old-mode and new-mode
> I2C registers by using the same underlying register array, instead of
> adding an entire new set of variables to represent new mode.

The downside of this approach is you lose the safety of having
discrete types. A write to s->regs[R_FOO] can overwrite R_BAR.


>
> As part of this, we also do additional cleanup to use ARRAY_FIELD_
> macros instead of FIELD_ macros on registers.
>
> Signed-off-by: Joe Komlodi 
> Change-Id: Ib94996b17c361b8490c042b43c99d8abc69332e3
> Message-Id: <20220331043248.2237838-5-koml...@google.com>
> Signed-off-by: Cédric Le Goater 
> ---
>  include/hw/i2c/aspeed_i2c.h |  11 +-
>  hw/i2c/aspeed_i2c.c | 286 +---
>  2 files changed, 133 insertions(+), 164 deletions(-)

> @@ -858,12 +834,12 @@ static void aspeed_i2c_bus_reset(DeviceState *dev)
>  {
>  AspeedI2CBus *s = ASPEED_I2C_BUS(dev);
>
> -s->intr_ctrl = 0;
> -s->intr_status = 0;
> -s->cmd = 0;
> -s->buf = 0;
> -s->dma_addr = 0;
> -s->dma_len = 0;
> +s->regs[R_I2CD_INTR_CTRL] = 0;
> +s->regs[R_I2CD_INTR_STS] = 0;
> +s->regs[R_I2CD_CMD] = 0;
> +s->regs[R_I2CD_BYTE_BUF] = 0;
> +s->regs[R_I2CD_DMA_ADDR] = 0;
> +s->regs[R_I2CD_DMA_LEN] = 0;

Could this become a memset of s->regs?

>  i2c_end_transfer(s->bus);
>  }
>
> @@ -921,10 +897,10 @@ static qemu_irq 
> aspeed_2400_i2c_bus_get_irq(AspeedI2CBus *bus)
>  static uint8_t *aspeed_2400_i2c_bus_pool_base(AspeedI2CBus *bus)
>  {
>  uint8_t *pool_page =
> -&bus->controller->pool[FIELD_EX32(bus->ctrl, I2CD_FUN_CTRL,
> -  POOL_PAGE_SEL) * 0x100];
> +&bus->controller->pool[ARRAY_FIELD_EX32(bus->regs, I2CD_FUN_CTRL,
> +POOL_PAGE_SEL) * 0x100];
>
> -return &pool_page[FIELD_EX32(bus->pool_ctrl, I2CD_POOL_CTRL, OFFSET)];
> +return &pool_page[ARRAY_FIELD_EX32(bus->regs, I2CD_POOL_CTRL, OFFSET)];
>  }
>
>  static void aspeed_2400_i2c_class_init(ObjectClass *klass, void *data)
> --
> 2.35.3
>



Re: [PATCH 13/21] aspeed: Add I2C buses to AST1030 model

2022-06-06 Thread Joel Stanley
On Mon, 6 Jun 2022 at 15:09, Cédric Le Goater  wrote:
>
> From: Troy Lee 
>
> Instantiate the I2C buses in AST1030 model and create two slave device
> for ast1030-evb.
>
> Signed-off-by: Troy Lee 
> Signed-off-by: Jamin Lin 
> Signed-off-by: Steven Lee 
> [ clg : - adapted to current ast1030 upstream models
> - fixed typo in commit log ]
> Message-Id: <20220324100439.478317-3-troy_...@aspeedtech.com>
> Signed-off-by: Cédric Le Goater 

Reviewed-by: Joel Stanley 

one question about a comment below.

> ---
>  hw/arm/aspeed.c | 13 +
>  hw/arm/aspeed_ast10x0.c | 18 ++
>  2 files changed, 31 insertions(+)
>
> diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
> index 98dc185acd9a..5c3802308e80 100644
> --- a/hw/arm/aspeed.c
> +++ b/hw/arm/aspeed.c
> @@ -1401,6 +1401,18 @@ static void aspeed_minibmc_machine_init(MachineState 
> *machine)
> AST1030_INTERNAL_FLASH_SIZE);
>  }
>
> +static void ast1030_evb_i2c_init(AspeedMachineState *bmc)
> +{
> +AspeedSoCState *soc = &bmc->soc;
> +
> +/* U10 24C08 connects to SDA/SCL Groupt 1 by default */
> +uint8_t *eeprom_buf = g_malloc0(32 * 1024);
> +smbus_eeprom_init_one(aspeed_i2c_get_bus(&soc->i2c, 0), 0x50, 
> eeprom_buf);
> +
> +/* U11 LM75 connects to SDA/SCL Group 2 by default */
> +i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 1), "tmp105", 
> 0x4d);
> +}
> +
>  static void aspeed_minibmc_machine_ast1030_evb_class_init(ObjectClass *oc,
>void *data)
>  {
> @@ -1412,6 +1424,7 @@ static void 
> aspeed_minibmc_machine_ast1030_evb_class_init(ObjectClass *oc,
>  amc->hw_strap1 = 0;
>  amc->hw_strap2 = 0;
>  mc->init = aspeed_minibmc_machine_init;
> +amc->i2c_init = ast1030_evb_i2c_init;
>  mc->default_ram_size = 0;
>  mc->default_cpus = mc->min_cpus = mc->max_cpus = 1;
>  amc->fmc_model = "sst25vf032b";
> diff --git a/hw/arm/aspeed_ast10x0.c b/hw/arm/aspeed_ast10x0.c
> index d53454168403..a2ed275712fb 100644
> --- a/hw/arm/aspeed_ast10x0.c
> +++ b/hw/arm/aspeed_ast10x0.c
> @@ -114,6 +114,9 @@ static void aspeed_soc_ast1030_init(Object *obj)
>  object_property_add_alias(obj, "hw-strap1", OBJECT(&s->scu), 
> "hw-strap1");
>  object_property_add_alias(obj, "hw-strap2", OBJECT(&s->scu), 
> "hw-strap2");
>
> +snprintf(typename, sizeof(typename), "aspeed.i2c-%s", socname);
> +object_initialize_child(obj, "i2c", &s->i2c, typename);
> +
>  snprintf(typename, sizeof(typename), "aspeed.timer-%s", socname);
>  object_initialize_child(obj, "timerctrl", &s->timerctrl, typename);
>
> @@ -188,6 +191,21 @@ static void aspeed_soc_ast1030_realize(DeviceState 
> *dev_soc, Error **errp)
>  }
>  sysbus_mmio_map(SYS_BUS_DEVICE(&s->scu), 0, sc->memmap[ASPEED_DEV_SCU]);
>
> +/* I2C */
> +
> +object_property_set_link(OBJECT(&s->i2c), "dram", OBJECT(&s->sram),
> + &error_abort);
> +if (!sysbus_realize(SYS_BUS_DEVICE(&s->i2c), errp)) {
> +return;
> +}
> +sysbus_mmio_map(SYS_BUS_DEVICE(&s->i2c), 0, sc->memmap[ASPEED_DEV_I2C]);
> +for (i = 0; i < ASPEED_I2C_GET_CLASS(&s->i2c)->num_busses; i++) {
> +qemu_irq irq = qdev_get_gpio_in(DEVICE(&s->armv7m),
> +sc->irqmap[ASPEED_DEV_I2C] + i);
> +/* The AST2600 I2C controller has one IRQ per bus. */

I know it's the same hardware, but is the "AST2600" part of the comment correct?

> +sysbus_connect_irq(SYS_BUS_DEVICE(&s->i2c.busses[i]), 0, irq);
> +}
> +
>  /* LPC */
>  if (!sysbus_realize(SYS_BUS_DEVICE(&s->lpc), errp)) {
>  return;
> --
> 2.35.3
>



Re: [PATCH 02/21] aspeed: i2c: Add ctrl_global_rsvd property

2022-06-06 Thread Joel Stanley
On Mon, 6 Jun 2022 at 15:08, Cédric Le Goater  wrote:
>
> From: Joe Komlodi 
>
> The Aspeed I2C controller is used across other SKUs that have different
> reserved bits for the ctrl_global_rsvd register.

I think rsvd stands for reserved? Lets spell out the full name in the
variable to keep it clear.

You could also call global_control_mask (or ctrl_global_mask if you
prefer), as it's a mask of valid bits.

>
> Signed-off-by: Joe Komlodi 
> Change-Id: I606c5933c527274a9d2b0afe559b2e895767636c
> Message-Id: <20220331043248.2237838-3-koml...@google.com>
> Signed-off-by: Cédric Le Goater 
> ---
>  include/hw/i2c/aspeed_i2c.h | 2 ++
>  hw/arm/aspeed_ast2600.c | 2 ++
>  hw/i2c/aspeed_i2c.c | 4 
>  3 files changed, 8 insertions(+)
>
> diff --git a/include/hw/i2c/aspeed_i2c.h b/include/hw/i2c/aspeed_i2c.h
> index 4b9be09274c7..3912fcc3ff53 100644
> --- a/include/hw/i2c/aspeed_i2c.h
> +++ b/include/hw/i2c/aspeed_i2c.h
> @@ -71,6 +71,8 @@ struct AspeedI2CState {
>  MemoryRegion pool_iomem;
>  uint8_t pool[ASPEED_I2C_MAX_POOL_SIZE];
>
> +uint32_t ctrl_global_rsvd;
> +
>  AspeedI2CBus busses[ASPEED_I2C_NR_BUSSES];
>  MemoryRegion *dram_mr;
>  AddressSpace dram_as;
> diff --git a/hw/arm/aspeed_ast2600.c b/hw/arm/aspeed_ast2600.c
> index b0a4199b6960..cc57c8b437d8 100644
> --- a/hw/arm/aspeed_ast2600.c
> +++ b/hw/arm/aspeed_ast2600.c
> @@ -375,6 +375,8 @@ static void aspeed_soc_ast2600_realize(DeviceState *dev, 
> Error **errp)
>  aspeed_soc_uart_init(s);
>
>  /* I2C */
> +object_property_set_int(OBJECT(&s->i2c), "ctrl-global-rsvd", 0xfffc3e00,
> +&error_abort);
>  object_property_set_link(OBJECT(&s->i2c), "dram", OBJECT(s->dram_mr),
>   &error_abort);
>  if (!sysbus_realize(SYS_BUS_DEVICE(&s->i2c), errp)) {
> diff --git a/hw/i2c/aspeed_i2c.c b/hw/i2c/aspeed_i2c.c
> index 03a4f5a91010..97eb9d57929c 100644
> --- a/hw/i2c/aspeed_i2c.c
> +++ b/hw/i2c/aspeed_i2c.c
> @@ -648,6 +648,7 @@ static void aspeed_i2c_ctrl_write(void *opaque, hwaddr 
> offset,
>
>  switch (offset) {
>  case I2C_CTRL_GLOBAL:
> +value &= ~s->ctrl_global_rsvd;

Is there value in printing a guest error when the reserved bits are set?

If not, is it worth having this property at all? It doesn't affect the
ability to model it.

>  s->ctrl_global = value;
>  break;
>  case I2C_CTRL_STATUS:
> @@ -730,6 +731,7 @@ static const VMStateDescription aspeed_i2c_vmstate = {
>  .minimum_version_id = 2,
>  .fields = (VMStateField[]) {
>  VMSTATE_UINT32(intr_status, AspeedI2CState),
> +VMSTATE_UINT32(ctrl_global_rsvd, AspeedI2CState),
>  VMSTATE_STRUCT_ARRAY(busses, AspeedI2CState,
>   ASPEED_I2C_NR_BUSSES, 1, aspeed_i2c_bus_vmstate,
>   AspeedI2CBus),
> @@ -828,6 +830,8 @@ static void aspeed_i2c_realize(DeviceState *dev, Error 
> **errp)
>  static Property aspeed_i2c_properties[] = {
>  DEFINE_PROP_LINK("dram", AspeedI2CState, dram_mr,
>   TYPE_MEMORY_REGION, MemoryRegion *),
> +DEFINE_PROP_UINT32("ctrl-global-rsvd", AspeedI2CState, ctrl_global_rsvd,
> +   0xfffe),
>  DEFINE_PROP_END_OF_LIST(),
>  };
>
> --
> 2.35.3
>



[PULL 43/43] target/loongarch: 'make check-tcg' support

2022-06-06 Thread Richard Henderson
From: Song Gao 

Signed-off-by: Song Gao 
Signed-off-by: Xiaojuan Yang 
Reviewed-by: Richard Henderson 
Acked-by: Alex Bennée 
Reviewed-by: Philippe Mathieu-Daudé 
Message-Id: <20220606124333.2060567-44-yangxiaoj...@loongson.cn>
Signed-off-by: Richard Henderson 
---
 configure | 1 +
 1 file changed, 1 insertion(+)

diff --git a/configure b/configure
index ac18ed4f3a..e69537c756 100755
--- a/configure
+++ b/configure
@@ -1831,6 +1831,7 @@ fi
 : ${cross_prefix_arm="arm-linux-gnueabihf-"}
 : ${cross_prefix_armeb="$cross_prefix_arm"}
 : ${cross_prefix_hexagon="hexagon-unknown-linux-musl-"}
+: ${cross_prefix_loongarch64="loongarch64-unknown-linux-gnu-"}
 : ${cross_prefix_hppa="hppa-linux-gnu-"}
 : ${cross_prefix_i386="i686-linux-gnu-"}
 : ${cross_prefix_m68k="m68k-linux-gnu-"}
-- 
2.34.1




Re: [PATCH 12/21] aspeed/i2c: Add ast1030 controller models

2022-06-06 Thread Joel Stanley
On Mon, 6 Jun 2022 at 15:09, Cédric Le Goater  wrote:
>
> Based on :
>   https://lists.nongnu.org/archive/html/qemu-devel/2022-03/msg06017.html

Perhaps use the link to lore (which also includes the message id):

https://lore.kernel.org/qemu-devel/20220324100439.478317-2-troy_...@aspeedtech.com/

Reviewed-by: Joel Stanley 

>
> Cc: Troy Lee 
> Cc: Jamin Lin 
> Cc: Steven Lee 
> Signed-off-by: Cédric Le Goater 
> ---
>  include/hw/i2c/aspeed_i2c.h |  1 +
>  hw/i2c/aspeed_i2c.c | 24 
>  2 files changed, 25 insertions(+)
>
> diff --git a/include/hw/i2c/aspeed_i2c.h b/include/hw/i2c/aspeed_i2c.h
> index 506bcf1a9daf..79c6779c6c1e 100644
> --- a/include/hw/i2c/aspeed_i2c.h
> +++ b/include/hw/i2c/aspeed_i2c.h
> @@ -30,6 +30,7 @@
>  #define TYPE_ASPEED_2400_I2C TYPE_ASPEED_I2C "-ast2400"
>  #define TYPE_ASPEED_2500_I2C TYPE_ASPEED_I2C "-ast2500"
>  #define TYPE_ASPEED_2600_I2C TYPE_ASPEED_I2C "-ast2600"
> +#define TYPE_ASPEED_1030_I2C TYPE_ASPEED_I2C "-ast1030"
>  OBJECT_DECLARE_TYPE(AspeedI2CState, AspeedI2CClass, ASPEED_I2C)
>
>  #define ASPEED_I2C_NR_BUSSES 16
> diff --git a/hw/i2c/aspeed_i2c.c b/hw/i2c/aspeed_i2c.c
> index 8425e928890a..5fce516517a5 100644
> --- a/hw/i2c/aspeed_i2c.c
> +++ b/hw/i2c/aspeed_i2c.c
> @@ -1185,6 +1185,29 @@ static const TypeInfo aspeed_2600_i2c_info = {
>  .class_init = aspeed_2600_i2c_class_init,
>  };
>
> +static void aspeed_1030_i2c_class_init(ObjectClass *klass, void *data)
> +{
> +DeviceClass *dc = DEVICE_CLASS(klass);
> +AspeedI2CClass *aic = ASPEED_I2C_CLASS(klass);
> +
> +dc->desc = "ASPEED 1030 I2C Controller";
> +
> +aic->num_busses = 14;
> +aic->reg_size = 0x80;
> +aic->gap = -1; /* no gap */
> +aic->bus_get_irq = aspeed_2600_i2c_bus_get_irq;
> +aic->pool_size = 0x200;
> +aic->pool_base = 0xC00;
> +aic->bus_pool_base = aspeed_2600_i2c_bus_pool_base;
> +aic->has_dma = true;
> +}
> +
> +static const TypeInfo aspeed_1030_i2c_info = {
> +.name = TYPE_ASPEED_1030_I2C,
> +.parent = TYPE_ASPEED_I2C,
> +.class_init = aspeed_1030_i2c_class_init,
> +};
> +
>  static void aspeed_i2c_register_types(void)
>  {
>  type_register_static(&aspeed_i2c_bus_info);
> @@ -1192,6 +1215,7 @@ static void aspeed_i2c_register_types(void)
>  type_register_static(&aspeed_2400_i2c_info);
>  type_register_static(&aspeed_2500_i2c_info);
>  type_register_static(&aspeed_2600_i2c_info);
> +type_register_static(&aspeed_1030_i2c_info);
>  }
>
>  type_init(aspeed_i2c_register_types)
> --
> 2.35.3
>



[PATCH] avocado/boot_linux_console.py: Update ast2600 test

2022-06-06 Thread Joel Stanley
Update the test_arm_ast2600_debian test to

 - the latest Debian kernel
 - use the Rainier machine instead of Tacoma

Both of which contains support for more hardware and thus exercises more
of the hardware Qemu models.

Signed-off-by: Joel Stanley 
---
 tests/avocado/boot_linux_console.py | 12 ++--
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/tests/avocado/boot_linux_console.py 
b/tests/avocado/boot_linux_console.py
index 6b1533c17c8b..477b9b887754 100644
--- a/tests/avocado/boot_linux_console.py
+++ b/tests/avocado/boot_linux_console.py
@@ -1046,18 +1046,18 @@ def test_arm_vexpressa9(self):
 def test_arm_ast2600_debian(self):
 """
 :avocado: tags=arch:arm
-:avocado: tags=machine:tacoma-bmc
+:avocado: tags=machine:rainier-bmc
 """
 deb_url = ('http://snapshot.debian.org/archive/debian/'
-   '20210302T203551Z/'
+   '20220606T211338Z/'
'pool/main/l/linux/'
-   'linux-image-5.10.0-3-armmp_5.10.13-1_armhf.deb')
-deb_hash = 
'db40d32fe39255d05482bea48d72467b67d6225bb2a2a4d6f618cb8976f1e09e'
+   'linux-image-5.17.0-2-armmp_5.17.6-1%2Bb1_armhf.deb')
+deb_hash = 
'8acb2b4439faedc2f3ed4bdb2847ad4f6e0491f73debaeb7f660c8abe4dcdc0e'
 deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash,
 algorithm='sha256')
-kernel_path = self.extract_from_deb(deb_path, 
'/boot/vmlinuz-5.10.0-3-armmp')
+kernel_path = self.extract_from_deb(deb_path, 
'/boot/vmlinuz-5.17.0-2-armmp')
 dtb_path = self.extract_from_deb(deb_path,
-
'/usr/lib/linux-image-5.10.0-3-armmp/aspeed-bmc-opp-tacoma.dtb')
+
'/usr/lib/linux-image-5.17.0-2-armmp/aspeed-bmc-ibm-rainier.dtb')
 
 self.vm.set_console()
 self.vm.add_args('-kernel', kernel_path,
-- 
2.35.1




Re: [PULL 00/43] target/loongarch: Initial system support

2022-06-06 Thread Richard Henderson

On 6/6/22 16:14, Richard Henderson wrote:

Thanks for the patience, guys.


r~


The following changes since commit 57c9363c452af64fe058aa946cc923eae7f7ad33:

   Merge tag 'for-upstream' of https://gitlab.com/bonzini/qemu into staging 
(2022-06-06 07:57:14 -0700)

are available in the Git repository at:

   https://gitlab.com/rth7680/qemu.git tags/pull-la-20220606

for you to fetch changes up to 34bb43b074906a7cd642ccf03e2b7bea63b53d95:

   target/loongarch: 'make check-tcg' support (2022-06-06 18:14:13 +)


Initial LoongArch support.


Applied.


r~





Song Gao (18):
   target/loongarch: Add README
   target/loongarch: Add core definition
   target/loongarch: Add main translation routines
   target/loongarch: Add fixed point arithmetic instruction translation
   target/loongarch: Add fixed point shift instruction translation
   target/loongarch: Add fixed point bit instruction translation
   target/loongarch: Add fixed point load/store instruction translation
   target/loongarch: Add fixed point atomic instruction translation
   target/loongarch: Add fixed point extra instruction translation
   target/loongarch: Add floating point arithmetic instruction translation
   target/loongarch: Add floating point comparison instruction translation
   target/loongarch: Add floating point conversion instruction translation
   target/loongarch: Add floating point move instruction translation
   target/loongarch: Add floating point load/store instruction translation
   target/loongarch: Add branch instruction translation
   target/loongarch: Add disassembler
   target/loongarch: Add target build suport
   target/loongarch: 'make check-tcg' support

Xiaojuan Yang (25):
   target/loongarch: Add system emulation introduction
   target/loongarch: Add CSRs definition
   target/loongarch: Add basic vmstate description of CPU.
   target/loongarch: Implement qmp_query_cpu_definitions()
   target/loongarch: Add MMU support for LoongArch CPU.
   target/loongarch: Add LoongArch interrupt and exception handle
   target/loongarch: Add constant timer support
   target/loongarch: Add LoongArch CSR instruction
   target/loongarch: Add LoongArch IOCSR instruction
   target/loongarch: Add TLB instruction support
   target/loongarch: Add other core instructions support
   target/loongarch: Add timer related instructions support.
   hw/loongarch: Add support loongson3 virt machine type.
   hw/loongarch: Add LoongArch ipi interrupt support(IPI)
   hw/intc: Add LoongArch ls7a interrupt controller support(PCH-PIC)
   hw/intc: Add LoongArch ls7a msi interrupt controller support(PCH-MSI)
   hw/intc: Add LoongArch extioi interrupt controller(EIOINTC)
   hw/loongarch: Add irq hierarchy for the system
   Enable common virtio pci support for LoongArch
   hw/loongarch: Add some devices support for 3A5000.
   hw/loongarch: Add LoongArch ls7a rtc device support
   hw/loongarch: Add LoongArch load elf function.
   hw/loongarch: Add LoongArch virt power manager support.
   target/loongarch: Add gdb support.
   tests/tcg/loongarch64: Add hello/memory test in loongarch64 system

  docs/system/loongarch/loongson3.rst|  41 +
  configure  |   1 +
  configs/devices/loongarch64-softmmu/default.mak|   3 +
  configs/targets/loongarch64-softmmu.mak|   4 +
  meson.build|   1 +
  qapi/machine-target.json   |   6 +-
  qapi/machine.json  |   2 +-
  include/disas/dis-asm.h|   2 +
  include/exec/poison.h  |   2 +
  include/hw/intc/loongarch_extioi.h |  62 ++
  include/hw/intc/loongarch_ipi.h|  52 ++
  include/hw/intc/loongarch_pch_msi.h|  20 +
  include/hw/intc/loongarch_pch_pic.h|  69 ++
  include/hw/loongarch/virt.h|  33 +
  include/hw/pci-host/ls7a.h |  44 ++
  include/sysemu/arch_init.h |   1 +
  target/loongarch/cpu-csr.h | 208 +
  target/loongarch/cpu-param.h   |  18 +
  target/loongarch/cpu.h | 391 ++
  target/loongarch/helper.h  | 130 
  target/loongarch/internals.h   |  56 ++
  target/loongarch/translate.h   |  45 ++
  tests/tcg/loongarch64/system/regdef.h  |  86 ++
  target/loongarch/insns.decode  | 486 
  hw/intc/loongarch_extioi.c | 312 

[PATCH v2 07/25] target/arm: Use is_a64 in arm_generate_debug_exceptions

2022-06-06 Thread Richard Henderson
Use the accessor rather than the raw structure member.

Reviewed-by: Peter Maydell 
Signed-off-by: Richard Henderson 
---
 target/arm/debug_helper.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/target/arm/debug_helper.c b/target/arm/debug_helper.c
index 20a0e4261a..a18a09a0c3 100644
--- a/target/arm/debug_helper.c
+++ b/target/arm/debug_helper.c
@@ -99,7 +99,7 @@ static bool aa32_generate_debug_exceptions(CPUARMState *env)
  */
 bool arm_generate_debug_exceptions(CPUARMState *env)
 {
-if (env->aarch64) {
+if (is_a64(env)) {
 return aa64_generate_debug_exceptions(env);
 } else {
 return aa32_generate_debug_exceptions(env);
-- 
2.34.1




[PATCH v2 00/25] target/arm: tidy exception routing

2022-06-06 Thread Richard Henderson
This is mostly code movement at this point, out of headers
and into op_helper.c and debug_helper.c.  I have dropped all
the bits that change where route_to_el2 is computed -- it
remains in raise_exception alone.

The last patch has the tiniest of bug fixes, which probably
isn't even visible, because we don't ask for fp_exception_el
with el != current without SVE.


r~


Richard Henderson (25):
  target/arm: Mark exception helpers as noreturn
  target/arm: Add coproc parameter to syn_fp_access_trap
  target/arm: Move fp access syndrome adjust out of raise_exception
  target/arm: Move exception_target_el out of line
  target/arm: Move arm_singlestep_active out of line
  target/arm: Move arm_generate_debug_exceptions out of line
  target/arm: Use is_a64 in arm_generate_debug_exceptions
  target/arm: Move exception_bkpt_insn to debug_helper.c
  target/arm: Move arm_debug_exception_fsr to debug_helper.c
  target/arm: Rename helper_exception_with_syndrome
  target/arm: Introduce gen_exception_insn_el_v
  target/arm: Rename gen_exception_insn to gen_exception_insn_el
  target/arm: Introduce gen_exception_insn
  target/arm: Create helper_exception_swstep
  target/arm: Remove TBFLAG_ANY.DEBUG_TARGET_EL
  target/arm: Move gen_exception to translate.c
  target/arm: Rename gen_exception to gen_exception_el
  target/arm: Introduce gen_exception
  target/arm: Introduce gen_exception_el_v
  target/arm: Introduce helper_exception_with_syndrome
  target/arm: Remove default_exception_el
  target/arm: Create raise_exception_debug
  target/arm: Move arm_debug_target_el to debug_helper.c
  target/arm: Rearrange Secure PL1 test in arm_debug_target_el
  target/arm: Fix Secure PL1 tests in fp_exception_el

 target/arm/cpu.h  | 128 +---
 target/arm/helper.h   |   9 +-
 target/arm/internals.h|  43 +--
 target/arm/syndrome.h |   7 +-
 target/arm/translate.h|  46 ++-
 target/arm/debug_helper.c | 222 --
 target/arm/helper.c   |  35 ++
 target/arm/op_helper.c|  80 ++--
 target/arm/translate-a64.c|  33 ++---
 target/arm/translate-m-nocp.c |  15 ++-
 target/arm/translate-mve.c|   3 +-
 target/arm/translate-vfp.c|  20 ++-
 target/arm/translate.c| 106 
 13 files changed, 391 insertions(+), 356 deletions(-)

-- 
2.34.1




[PATCH v2 04/25] target/arm: Move exception_target_el out of line

2022-06-06 Thread Richard Henderson
Move the function to op_helper.c, near raise_exception.

Signed-off-by: Richard Henderson 
---
 target/arm/internals.h | 16 +---
 target/arm/op_helper.c | 15 +++
 2 files changed, 16 insertions(+), 15 deletions(-)

diff --git a/target/arm/internals.h b/target/arm/internals.h
index b654bee468..36c33a6ac5 100644
--- a/target/arm/internals.h
+++ b/target/arm/internals.h
@@ -1090,21 +1090,6 @@ typedef struct ARMVAParameters {
 ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va,
ARMMMUIdx mmu_idx, bool data);
 
-static inline int exception_target_el(CPUARMState *env)
-{
-int target_el = MAX(1, arm_current_el(env));
-
-/*
- * No such thing as secure EL1 if EL3 is aarch32,
- * so update the target EL to EL3 in this case.
- */
-if (arm_is_secure(env) && !arm_el_is_aa64(env, 3) && target_el == 1) {
-target_el = 3;
-}
-
-return target_el;
-}
-
 /* Determine if allocation tags are available.  */
 static inline bool allocation_tag_access_enabled(CPUARMState *env, int el,
  uint64_t sctlr)
@@ -1329,5 +1314,6 @@ void define_cortex_a72_a57_a53_cp_reginfo(ARMCPU *cpu);
 #endif
 
 void aa32_max_features(ARMCPU *cpu);
+int exception_target_el(CPUARMState *env);
 
 #endif
diff --git a/target/arm/op_helper.c b/target/arm/op_helper.c
index 67b7dbeaa9..00a082d1f7 100644
--- a/target/arm/op_helper.c
+++ b/target/arm/op_helper.c
@@ -28,6 +28,21 @@
 #define SIGNBIT (uint32_t)0x8000
 #define SIGNBIT64 ((uint64_t)1 << 63)
 
+int exception_target_el(CPUARMState *env)
+{
+int target_el = MAX(1, arm_current_el(env));
+
+/*
+ * No such thing as secure EL1 if EL3 is aarch32,
+ * so update the target EL to EL3 in this case.
+ */
+if (arm_is_secure(env) && !arm_el_is_aa64(env, 3) && target_el == 1) {
+target_el = 3;
+}
+
+return target_el;
+}
+
 void raise_exception(CPUARMState *env, uint32_t excp,
  uint32_t syndrome, uint32_t target_el)
 {
-- 
2.34.1




[PATCH v2 01/25] target/arm: Mark exception helpers as noreturn

2022-06-06 Thread Richard Henderson
Reviewed-by: Peter Maydell 
Signed-off-by: Richard Henderson 
---
 target/arm/helper.h | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/target/arm/helper.h b/target/arm/helper.h
index b1334e0c42..5161cdf73d 100644
--- a/target/arm/helper.h
+++ b/target/arm/helper.h
@@ -44,9 +44,9 @@ DEF_HELPER_FLAGS_2(usad8, TCG_CALL_NO_RWG_SE, i32, i32, i32)
 
 DEF_HELPER_FLAGS_3(sel_flags, TCG_CALL_NO_RWG_SE,
i32, i32, i32, i32)
-DEF_HELPER_2(exception_internal, void, env, i32)
-DEF_HELPER_4(exception_with_syndrome, void, env, i32, i32, i32)
-DEF_HELPER_2(exception_bkpt_insn, void, env, i32)
+DEF_HELPER_2(exception_internal, noreturn, env, i32)
+DEF_HELPER_4(exception_with_syndrome, noreturn, env, i32, i32, i32)
+DEF_HELPER_2(exception_bkpt_insn, noreturn, env, i32)
 DEF_HELPER_2(exception_pc_alignment, noreturn, env, tl)
 DEF_HELPER_1(setend, void, env)
 DEF_HELPER_2(wfi, void, env, i32)
-- 
2.34.1




[PATCH v2 03/25] target/arm: Move fp access syndrome adjust out of raise_exception

2022-06-06 Thread Richard Henderson
Create helper_exception_advsimdfp_access to handle both
the routing and the syndrome contents, depending on the
eventual target EL and mode.

Signed-off-by: Richard Henderson 
---
 target/arm/helper.h|  1 +
 target/arm/translate.h |  9 +
 target/arm/op_helper.c | 32 +++-
 target/arm/translate-a64.c |  5 ++---
 target/arm/translate-vfp.c |  4 +++-
 5 files changed, 38 insertions(+), 13 deletions(-)

diff --git a/target/arm/helper.h b/target/arm/helper.h
index 5161cdf73d..a13007699d 100644
--- a/target/arm/helper.h
+++ b/target/arm/helper.h
@@ -46,6 +46,7 @@ DEF_HELPER_FLAGS_3(sel_flags, TCG_CALL_NO_RWG_SE,
i32, i32, i32, i32)
 DEF_HELPER_2(exception_internal, noreturn, env, i32)
 DEF_HELPER_4(exception_with_syndrome, noreturn, env, i32, i32, i32)
+DEF_HELPER_3(exception_advsimdfp_access, noreturn, env, i32, i32)
 DEF_HELPER_2(exception_bkpt_insn, noreturn, env, i32)
 DEF_HELPER_2(exception_pc_alignment, noreturn, env, tl)
 DEF_HELPER_1(setend, void, env)
diff --git a/target/arm/translate.h b/target/arm/translate.h
index 9f0bb270c5..da5f89d49d 100644
--- a/target/arm/translate.h
+++ b/target/arm/translate.h
@@ -337,6 +337,15 @@ static inline void gen_exception(int excp, uint32_t 
syndrome,
tcg_constant_i32(target_el));
 }
 
+static inline void gen_exception_advsimdfp_access(DisasContext *s,
+  uint32_t syndrome)
+{
+gen_helper_exception_advsimdfp_access(cpu_env,
+  tcg_constant_i32(syndrome),
+  tcg_constant_i32(s->fp_excp_el));
+s->base.is_jmp = DISAS_NORETURN;
+}
+
 /* Generate an architectural singlestep exception */
 static inline void gen_swstep_exception(DisasContext *s, int isv, int ex)
 {
diff --git a/target/arm/op_helper.c b/target/arm/op_helper.c
index c4bd668870..67b7dbeaa9 100644
--- a/target/arm/op_helper.c
+++ b/target/arm/op_helper.c
@@ -34,16 +34,8 @@ void raise_exception(CPUARMState *env, uint32_t excp,
 CPUState *cs = env_cpu(env);
 
 if (target_el == 1 && (arm_hcr_el2_eff(env) & HCR_TGE)) {
-/*
- * Redirect NS EL1 exceptions to NS EL2. These are reported with
- * their original syndrome register value, with the exception of
- * SIMD/FP access traps, which are reported as uncategorized
- * (see DDI0478C.a D1.10.4)
- */
+/* Redirect NS EL1 exceptions to NS EL2. */
 target_el = 2;
-if (syn_get_ec(syndrome) == EC_ADVSIMDFPACCESSTRAP) {
-syndrome = syn_uncategorized();
-}
 }
 
 assert(!excp_is_internal(excp));
@@ -384,6 +376,28 @@ void HELPER(exception_with_syndrome)(CPUARMState *env, 
uint32_t excp,
 raise_exception(env, excp, syndrome, target_el);
 }
 
+/* Raise an exception with EC_ADVSIMDFPACCESS. */
+void HELPER(exception_advsimdfp_access)(CPUARMState *env,
+uint32_t syndrome, uint32_t target_el)
+{
+if (target_el == 1 && (arm_hcr_el2_eff(env) & HCR_TGE)) {
+/*
+ * SIMD/FP access traps, when re-routed to EL2, are reported with
+ * uncategorized syndrome.  See DDI0487H.a rule RJNBTN.
+ */
+target_el = 2;
+syndrome = syn_uncategorized();
+} else if (arm_el_is_aa64(env, target_el)) {
+/*
+ * From AArch32, we will have filled in TA and/or COPROC for use
+ * by aa32 HSR.  But in aa64 ESR_ELx, the low 20 bits are RES0.
+ */
+syndrome &= 0xfff0;
+}
+
+raise_exception(env, EXCP_UDEF, syndrome, target_el);
+}
+
 /* Raise an EXCP_BKPT with the specified syndrome register value,
  * targeting the correct exception level for debug exceptions.
  */
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
index 14b90a37ea..3251c69180 100644
--- a/target/arm/translate-a64.c
+++ b/target/arm/translate-a64.c
@@ -1161,9 +1161,8 @@ static bool fp_access_check(DisasContext *s)
 assert(!s->fp_access_checked);
 s->fp_access_checked = true;
 
-gen_exception_insn(s, s->pc_curr, EXCP_UDEF,
-   syn_fp_access_trap(1, 0xe, false, 0),
-   s->fp_excp_el);
+gen_a64_set_pc_im(s->pc_curr);
+gen_exception_advsimdfp_access(s, syn_fp_access_trap(1, 0xe, false, 
0));
 return false;
 }
 s->fp_access_checked = true;
diff --git a/target/arm/translate-vfp.c b/target/arm/translate-vfp.c
index 0f797c56fd..2a98387411 100644
--- a/target/arm/translate-vfp.c
+++ b/target/arm/translate-vfp.c
@@ -230,7 +230,9 @@ static bool vfp_access_check_a(DisasContext *s, bool 
ignore_vfp_enabled)
 int coproc = arm_dc_feature(s, ARM_FEATURE_V8) ? 0 : 0xa;
 uint32_t syn = syn_fp_access_trap(1, 0xe, false, coproc);
 
-gen_exception_insn(s, s->pc_curr, EXCP_UDEF, syn, s->fp_excp_el);
+gen_set_condexec(s);
+  

[PATCH v2 06/25] target/arm: Move arm_generate_debug_exceptions out of line

2022-06-06 Thread Richard Henderson
Move arm_generate_debug_exceptions and its two subroutines,
{aa32,aa64}_generate_debug_exceptions into debug_helper.c,
and the one interface declaration to internals.h.

Reviewed-by: Peter Maydell 
Signed-off-by: Richard Henderson 
---
 target/arm/cpu.h  | 91 -
 target/arm/internals.h|  1 +
 target/arm/debug_helper.c | 94 +++
 3 files changed, 95 insertions(+), 91 deletions(-)

diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 2e115a0281..92c9758e86 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -2996,97 +2996,6 @@ static inline bool arm_v7m_csselr_razwi(ARMCPU *cpu)
 return (cpu->clidr & R_V7M_CLIDR_CTYPE_ALL_MASK) != 0;
 }
 
-/* See AArch64.GenerateDebugExceptionsFrom() in ARM ARM pseudocode */
-static inline bool aa64_generate_debug_exceptions(CPUARMState *env)
-{
-int cur_el = arm_current_el(env);
-int debug_el;
-
-if (cur_el == 3) {
-return false;
-}
-
-/* MDCR_EL3.SDD disables debug events from Secure state */
-if (arm_is_secure_below_el3(env)
-&& extract32(env->cp15.mdcr_el3, 16, 1)) {
-return false;
-}
-
-/*
- * Same EL to same EL debug exceptions need MDSCR_KDE enabled
- * while not masking the (D)ebug bit in DAIF.
- */
-debug_el = arm_debug_target_el(env);
-
-if (cur_el == debug_el) {
-return extract32(env->cp15.mdscr_el1, 13, 1)
-&& !(env->daif & PSTATE_D);
-}
-
-/* Otherwise the debug target needs to be a higher EL */
-return debug_el > cur_el;
-}
-
-static inline bool aa32_generate_debug_exceptions(CPUARMState *env)
-{
-int el = arm_current_el(env);
-
-if (el == 0 && arm_el_is_aa64(env, 1)) {
-return aa64_generate_debug_exceptions(env);
-}
-
-if (arm_is_secure(env)) {
-int spd;
-
-if (el == 0 && (env->cp15.sder & 1)) {
-/* SDER.SUIDEN means debug exceptions from Secure EL0
- * are always enabled. Otherwise they are controlled by
- * SDCR.SPD like those from other Secure ELs.
- */
-return true;
-}
-
-spd = extract32(env->cp15.mdcr_el3, 14, 2);
-switch (spd) {
-case 1:
-/* SPD == 0b01 is reserved, but behaves as 0b00. */
-case 0:
-/* For 0b00 we return true if external secure invasive debug
- * is enabled. On real hardware this is controlled by external
- * signals to the core. QEMU always permits debug, and behaves
- * as if DBGEN, SPIDEN, NIDEN and SPNIDEN are all tied high.
- */
-return true;
-case 2:
-return false;
-case 3:
-return true;
-}
-}
-
-return el != 2;
-}
-
-/* Return true if debugging exceptions are currently enabled.
- * This corresponds to what in ARM ARM pseudocode would be
- *if UsingAArch32() then
- *return AArch32.GenerateDebugExceptions()
- *else
- *return AArch64.GenerateDebugExceptions()
- * We choose to push the if() down into this function for clarity,
- * since the pseudocode has it at all callsites except for the one in
- * CheckSoftwareStep(), where it is elided because both branches would
- * always return the same value.
- */
-static inline bool arm_generate_debug_exceptions(CPUARMState *env)
-{
-if (env->aarch64) {
-return aa64_generate_debug_exceptions(env);
-} else {
-return aa32_generate_debug_exceptions(env);
-}
-}
-
 static inline bool arm_sctlr_b(CPUARMState *env)
 {
 return
diff --git a/target/arm/internals.h b/target/arm/internals.h
index 148f2a9252..e9ac54f244 100644
--- a/target/arm/internals.h
+++ b/target/arm/internals.h
@@ -1316,5 +1316,6 @@ void define_cortex_a72_a57_a53_cp_reginfo(ARMCPU *cpu);
 void aa32_max_features(ARMCPU *cpu);
 int exception_target_el(CPUARMState *env);
 bool arm_singlestep_active(CPUARMState *env);
+bool arm_generate_debug_exceptions(CPUARMState *env);
 
 #endif
diff --git a/target/arm/debug_helper.c b/target/arm/debug_helper.c
index 1abf41c5f8..20a0e4261a 100644
--- a/target/arm/debug_helper.c
+++ b/target/arm/debug_helper.c
@@ -12,6 +12,100 @@
 #include "exec/helper-proto.h"
 
 
+/* See AArch64.GenerateDebugExceptionsFrom() in ARM ARM pseudocode */
+static bool aa64_generate_debug_exceptions(CPUARMState *env)
+{
+int cur_el = arm_current_el(env);
+int debug_el;
+
+if (cur_el == 3) {
+return false;
+}
+
+/* MDCR_EL3.SDD disables debug events from Secure state */
+if (arm_is_secure_below_el3(env)
+&& extract32(env->cp15.mdcr_el3, 16, 1)) {
+return false;
+}
+
+/*
+ * Same EL to same EL debug exceptions need MDSCR_KDE enabled
+ * while not masking the (D)ebug bit in DAIF.
+ */
+debug_el = arm_debug_target_el(env);
+
+if (cur_el == debug_el) {
+return extract32(env->cp15.mdscr_el1, 13, 1)
+&& !(env-

[PATCH v2 08/25] target/arm: Move exception_bkpt_insn to debug_helper.c

2022-06-06 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 target/arm/debug_helper.c | 31 +++
 target/arm/op_helper.c| 29 -
 2 files changed, 31 insertions(+), 29 deletions(-)

diff --git a/target/arm/debug_helper.c b/target/arm/debug_helper.c
index a18a09a0c3..80dff0788b 100644
--- a/target/arm/debug_helper.c
+++ b/target/arm/debug_helper.c
@@ -430,6 +430,37 @@ void arm_debug_excp_handler(CPUState *cs)
 }
 }
 
+/*
+ * Raise an EXCP_BKPT with the specified syndrome register value,
+ * targeting the correct exception level for debug exceptions.
+ */
+void HELPER(exception_bkpt_insn)(CPUARMState *env, uint32_t syndrome)
+{
+int debug_el = arm_debug_target_el(env);
+int cur_el = arm_current_el(env);
+
+/* FSR will only be used if the debug target EL is AArch32. */
+env->exception.fsr = arm_debug_exception_fsr(env);
+/*
+ * FAR is UNKNOWN: clear vaddress to avoid potentially exposing
+ * values to the guest that it shouldn't be able to see at its
+ * exception/security level.
+ */
+env->exception.vaddress = 0;
+/*
+ * Other kinds of architectural debug exception are ignored if
+ * they target an exception level below the current one (in QEMU
+ * this is checked by arm_generate_debug_exceptions()). Breakpoint
+ * instructions are special because they always generate an exception
+ * to somewhere: if they can't go to the configured debug exception
+ * level they are taken to the current exception level.
+ */
+if (debug_el < cur_el) {
+debug_el = cur_el;
+}
+raise_exception(env, EXCP_BKPT, syndrome, debug_el);
+}
+
 #if !defined(CONFIG_USER_ONLY)
 
 vaddr arm_adjust_watchpoint_address(CPUState *cs, vaddr addr, int len)
diff --git a/target/arm/op_helper.c b/target/arm/op_helper.c
index 00a082d1f7..ae0009d1a3 100644
--- a/target/arm/op_helper.c
+++ b/target/arm/op_helper.c
@@ -413,35 +413,6 @@ void HELPER(exception_advsimdfp_access)(CPUARMState *env,
 raise_exception(env, EXCP_UDEF, syndrome, target_el);
 }
 
-/* Raise an EXCP_BKPT with the specified syndrome register value,
- * targeting the correct exception level for debug exceptions.
- */
-void HELPER(exception_bkpt_insn)(CPUARMState *env, uint32_t syndrome)
-{
-int debug_el = arm_debug_target_el(env);
-int cur_el = arm_current_el(env);
-
-/* FSR will only be used if the debug target EL is AArch32. */
-env->exception.fsr = arm_debug_exception_fsr(env);
-/* FAR is UNKNOWN: clear vaddress to avoid potentially exposing
- * values to the guest that it shouldn't be able to see at its
- * exception/security level.
- */
-env->exception.vaddress = 0;
-/*
- * Other kinds of architectural debug exception are ignored if
- * they target an exception level below the current one (in QEMU
- * this is checked by arm_generate_debug_exceptions()). Breakpoint
- * instructions are special because they always generate an exception
- * to somewhere: if they can't go to the configured debug exception
- * level they are taken to the current exception level.
- */
-if (debug_el < cur_el) {
-debug_el = cur_el;
-}
-raise_exception(env, EXCP_BKPT, syndrome, debug_el);
-}
-
 uint32_t HELPER(cpsr_read)(CPUARMState *env)
 {
 return cpsr_read(env) & ~CPSR_EXEC;
-- 
2.34.1




[PATCH v2 15/25] target/arm: Remove TBFLAG_ANY.DEBUG_TARGET_EL

2022-06-06 Thread Richard Henderson
We no longer need this value during translation,
as it is now handled within the helpers.

Signed-off-by: Richard Henderson 
---
 target/arm/cpu.h   |  6 ++
 target/arm/translate.h |  2 --
 target/arm/helper.c| 12 ++--
 target/arm/translate-a64.c |  1 -
 target/arm/translate.c |  1 -
 5 files changed, 4 insertions(+), 18 deletions(-)

diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 92c9758e86..5224dc2c85 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -3085,11 +3085,9 @@ FIELD(TBFLAG_ANY, BE_DATA, 3, 1)
 FIELD(TBFLAG_ANY, MMUIDX, 4, 4)
 /* Target EL if we take a floating-point-disabled exception */
 FIELD(TBFLAG_ANY, FPEXC_EL, 8, 2)
-/* For A-profile only, target EL for debug exceptions.  */
-FIELD(TBFLAG_ANY, DEBUG_TARGET_EL, 10, 2)
 /* Memory operations require alignment: SCTLR_ELx.A or CCR.UNALIGN_TRP */
-FIELD(TBFLAG_ANY, ALIGN_MEM, 12, 1)
-FIELD(TBFLAG_ANY, PSTATE__IL, 13, 1)
+FIELD(TBFLAG_ANY, ALIGN_MEM, 10, 1)
+FIELD(TBFLAG_ANY, PSTATE__IL, 11, 1)
 
 /*
  * Bit usage when in AArch32 state, both A- and M-profile.
diff --git a/target/arm/translate.h b/target/arm/translate.h
index c720a7e26c..4a93cac65f 100644
--- a/target/arm/translate.h
+++ b/target/arm/translate.h
@@ -59,8 +59,6 @@ typedef struct DisasContext {
  */
 uint32_t svc_imm;
 int current_el;
-/* Debug target exception level for single-step exceptions */
-int debug_target_el;
 GHashTable *cp_regs;
 uint64_t features; /* CPU features bits */
 bool aarch64;
diff --git a/target/arm/helper.c b/target/arm/helper.c
index 40da63913c..eeca1a5dc8 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -13630,18 +13630,10 @@ static CPUARMTBFlags rebuild_hflags_m32(CPUARMState 
*env, int fp_el,
 return rebuild_hflags_common_32(env, fp_el, mmu_idx, flags);
 }
 
-static CPUARMTBFlags rebuild_hflags_aprofile(CPUARMState *env)
-{
-CPUARMTBFlags flags = {};
-
-DP_TBFLAG_ANY(flags, DEBUG_TARGET_EL, arm_debug_target_el(env));
-return flags;
-}
-
 static CPUARMTBFlags rebuild_hflags_a32(CPUARMState *env, int fp_el,
 ARMMMUIdx mmu_idx)
 {
-CPUARMTBFlags flags = rebuild_hflags_aprofile(env);
+CPUARMTBFlags flags = {};
 int el = arm_current_el(env);
 
 if (arm_sctlr(env, el) & SCTLR_A) {
@@ -13667,7 +13659,7 @@ static CPUARMTBFlags rebuild_hflags_a32(CPUARMState 
*env, int fp_el,
 static CPUARMTBFlags rebuild_hflags_a64(CPUARMState *env, int el, int fp_el,
 ARMMMUIdx mmu_idx)
 {
-CPUARMTBFlags flags = rebuild_hflags_aprofile(env);
+CPUARMTBFlags flags = {};
 ARMMMUIdx stage1 = stage_1_mmu_idx(mmu_idx);
 uint64_t tcr = regime_tcr(env, mmu_idx)->raw_tcr;
 uint64_t sctlr;
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
index a5c66ce085..b45039a124 100644
--- a/target/arm/translate-a64.c
+++ b/target/arm/translate-a64.c
@@ -14644,7 +14644,6 @@ static void 
aarch64_tr_init_disas_context(DisasContextBase *dcbase,
 dc->ss_active = EX_TBFLAG_ANY(tb_flags, SS_ACTIVE);
 dc->pstate_ss = EX_TBFLAG_ANY(tb_flags, PSTATE__SS);
 dc->is_ldex = false;
-dc->debug_target_el = EX_TBFLAG_ANY(tb_flags, DEBUG_TARGET_EL);
 
 /* Bound the number of insns to execute to those left on the page.  */
 bound = -(dc->base.pc_first | TARGET_PAGE_MASK) / 4;
diff --git a/target/arm/translate.c b/target/arm/translate.c
index c7d422b541..b8a8972bac 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -9350,7 +9350,6 @@ static void arm_tr_init_disas_context(DisasContextBase 
*dcbase, CPUState *cs)
 dc->v7m_lspact = EX_TBFLAG_M32(tb_flags, LSPACT);
 dc->mve_no_pred = EX_TBFLAG_M32(tb_flags, MVE_NO_PRED);
 } else {
-dc->debug_target_el = EX_TBFLAG_ANY(tb_flags, DEBUG_TARGET_EL);
 dc->sctlr_b = EX_TBFLAG_A32(tb_flags, SCTLR__B);
 dc->hstr_active = EX_TBFLAG_A32(tb_flags, HSTR_ACTIVE);
 dc->ns = EX_TBFLAG_A32(tb_flags, NS);
-- 
2.34.1




[PATCH v2 02/25] target/arm: Add coproc parameter to syn_fp_access_trap

2022-06-06 Thread Richard Henderson
With ARMv8, this field is always RES0.
With ARMv7, targeting EL2 and TA=0, it is always 0xA.

Signed-off-by: Richard Henderson 
---
 target/arm/syndrome.h  |  7 ---
 target/arm/translate-a64.c |  3 ++-
 target/arm/translate-vfp.c | 14 --
 3 files changed, 18 insertions(+), 6 deletions(-)

diff --git a/target/arm/syndrome.h b/target/arm/syndrome.h
index 0cb26dde7d..c105f9e6ba 100644
--- a/target/arm/syndrome.h
+++ b/target/arm/syndrome.h
@@ -185,12 +185,13 @@ static inline uint32_t syn_cp15_rrt_trap(int cv, int 
cond, int opc1, int crm,
 | (rt2 << 10) | (rt << 5) | (crm << 1) | isread;
 }
 
-static inline uint32_t syn_fp_access_trap(int cv, int cond, bool is_16bit)
+static inline uint32_t syn_fp_access_trap(int cv, int cond, bool is_16bit,
+  int coproc)
 {
-/* AArch32 FP trap or any AArch64 FP/SIMD trap: TA == 0 coproc == 0xa */
+/* AArch32 FP trap or any AArch64 FP/SIMD trap: TA == 0 */
 return (EC_ADVSIMDFPACCESSTRAP << ARM_EL_EC_SHIFT)
 | (is_16bit ? 0 : ARM_EL_IL)
-| (cv << 24) | (cond << 20) | 0xa;
+| (cv << 24) | (cond << 20) | coproc;
 }
 
 static inline uint32_t syn_simd_access_trap(int cv, int cond, bool is_16bit)
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
index 935e1929bb..14b90a37ea 100644
--- a/target/arm/translate-a64.c
+++ b/target/arm/translate-a64.c
@@ -1162,7 +1162,8 @@ static bool fp_access_check(DisasContext *s)
 s->fp_access_checked = true;
 
 gen_exception_insn(s, s->pc_curr, EXCP_UDEF,
-   syn_fp_access_trap(1, 0xe, false), s->fp_excp_el);
+   syn_fp_access_trap(1, 0xe, false, 0),
+   s->fp_excp_el);
 return false;
 }
 s->fp_access_checked = true;
diff --git a/target/arm/translate-vfp.c b/target/arm/translate-vfp.c
index 40a513b822..0f797c56fd 100644
--- a/target/arm/translate-vfp.c
+++ b/target/arm/translate-vfp.c
@@ -219,8 +219,18 @@ static void gen_update_fp_context(DisasContext *s)
 static bool vfp_access_check_a(DisasContext *s, bool ignore_vfp_enabled)
 {
 if (s->fp_excp_el) {
-gen_exception_insn(s, s->pc_curr, EXCP_UDEF,
-   syn_fp_access_trap(1, 0xe, false), s->fp_excp_el);
+/*
+ * The full syndrome is only used for HSR when HCPTR traps:
+ * For v8, when TA==0, coproc is RES0.
+ * For v7, any use of a Floating-point instruction or access
+ * to a Floating-point Extension register that is trapped to
+ * Hyp mode because of a trap configured in the HCPTR sets
+ * this field to 0xA.
+ */
+int coproc = arm_dc_feature(s, ARM_FEATURE_V8) ? 0 : 0xa;
+uint32_t syn = syn_fp_access_trap(1, 0xe, false, coproc);
+
+gen_exception_insn(s, s->pc_curr, EXCP_UDEF, syn, s->fp_excp_el);
 return false;
 }
 
-- 
2.34.1




[PATCH v2 14/25] target/arm: Create helper_exception_swstep

2022-06-06 Thread Richard Henderson
Move the computation from gen_swstep_exception into a helper.

Signed-off-by: Richard Henderson 
---
 target/arm/helper.h   |  1 +
 target/arm/translate.h| 12 +++-
 target/arm/debug_helper.c | 16 
 3 files changed, 20 insertions(+), 9 deletions(-)

diff --git a/target/arm/helper.h b/target/arm/helper.h
index aca86612b4..afc0f1a462 100644
--- a/target/arm/helper.h
+++ b/target/arm/helper.h
@@ -48,6 +48,7 @@ DEF_HELPER_2(exception_internal, noreturn, env, i32)
 DEF_HELPER_4(exception_with_syndrome_el, noreturn, env, i32, i32, i32)
 DEF_HELPER_3(exception_advsimdfp_access, noreturn, env, i32, i32)
 DEF_HELPER_2(exception_bkpt_insn, noreturn, env, i32)
+DEF_HELPER_2(exception_swstep, noreturn, env, i32)
 DEF_HELPER_2(exception_pc_alignment, noreturn, env, tl)
 DEF_HELPER_1(setend, void, env)
 DEF_HELPER_2(wfi, void, env, i32)
diff --git a/target/arm/translate.h b/target/arm/translate.h
index 04d45da54e..c720a7e26c 100644
--- a/target/arm/translate.h
+++ b/target/arm/translate.h
@@ -350,15 +350,9 @@ static inline void 
gen_exception_advsimdfp_access(DisasContext *s,
 /* Generate an architectural singlestep exception */
 static inline void gen_swstep_exception(DisasContext *s, int isv, int ex)
 {
-bool same_el = (s->debug_target_el == s->current_el);
-
-/*
- * If singlestep is targeting a lower EL than the current one,
- * then s->ss_active must be false and we can never get here.
- */
-assert(s->debug_target_el >= s->current_el);
-
-gen_exception(EXCP_UDEF, syn_swstep(same_el, isv, ex), s->debug_target_el);
+/* Fill in the same_el field of the syndrome in the helper. */
+uint32_t syn = syn_swstep(false, isv, ex);
+gen_helper_exception_swstep(cpu_env, tcg_constant_i32(syn));
 }
 
 /*
diff --git a/target/arm/debug_helper.c b/target/arm/debug_helper.c
index a743061e89..a3a1b98de2 100644
--- a/target/arm/debug_helper.c
+++ b/target/arm/debug_helper.c
@@ -487,6 +487,22 @@ void HELPER(exception_bkpt_insn)(CPUARMState *env, 
uint32_t syndrome)
 raise_exception(env, EXCP_BKPT, syndrome, debug_el);
 }
 
+void HELPER(exception_swstep)(CPUARMState *env, uint32_t syndrome)
+{
+int debug_el = arm_debug_target_el(env);
+int cur_el = arm_current_el(env);
+
+/*
+ * If singlestep is targeting a lower EL than the current one, then
+ * DisasContext.ss_active must be false and we can never get here.
+ */
+assert(debug_el >= cur_el);
+if (debug_el == cur_el) {
+syndrome |= 1 << ARM_EL_EC_SHIFT;
+}
+raise_exception(env, EXCP_UDEF, syndrome, debug_el);
+}
+
 #if !defined(CONFIG_USER_ONLY)
 
 vaddr arm_adjust_watchpoint_address(CPUState *cs, vaddr addr, int len)
-- 
2.34.1




[PATCH v2 09/25] target/arm: Move arm_debug_exception_fsr to debug_helper.c

2022-06-06 Thread Richard Henderson
This function now now only used in debug_helper.c, so there is
no reason to have a declaration in a header.

Signed-off-by: Richard Henderson 
---
 target/arm/internals.h| 25 -
 target/arm/debug_helper.c | 26 ++
 2 files changed, 26 insertions(+), 25 deletions(-)

diff --git a/target/arm/internals.h b/target/arm/internals.h
index e9ac54f244..c8410ee801 100644
--- a/target/arm/internals.h
+++ b/target/arm/internals.h
@@ -793,31 +793,6 @@ static inline TCR *regime_tcr(CPUARMState *env, ARMMMUIdx 
mmu_idx)
 return &env->cp15.tcr_el[regime_el(env, mmu_idx)];
 }
 
-/* Return the FSR value for a debug exception (watchpoint, hardware
- * breakpoint or BKPT insn) targeting the specified exception level.
- */
-static inline uint32_t arm_debug_exception_fsr(CPUARMState *env)
-{
-ARMMMUFaultInfo fi = { .type = ARMFault_Debug };
-int target_el = arm_debug_target_el(env);
-bool using_lpae = false;
-
-if (target_el == 2 || arm_el_is_aa64(env, target_el)) {
-using_lpae = true;
-} else {
-if (arm_feature(env, ARM_FEATURE_LPAE) &&
-(env->cp15.tcr_el[target_el].raw_tcr & TTBCR_EAE)) {
-using_lpae = true;
-}
-}
-
-if (using_lpae) {
-return arm_fi_to_lfsc(&fi);
-} else {
-return arm_fi_to_sfsc(&fi);
-}
-}
-
 /**
  * arm_num_brps: Return number of implemented breakpoints.
  * Note that the ID register BRPS field is "number of bps - 1",
diff --git a/target/arm/debug_helper.c b/target/arm/debug_helper.c
index 80dff0788b..a743061e89 100644
--- a/target/arm/debug_helper.c
+++ b/target/arm/debug_helper.c
@@ -379,6 +379,32 @@ bool arm_debug_check_watchpoint(CPUState *cs, 
CPUWatchpoint *wp)
 return check_watchpoints(cpu);
 }
 
+/*
+ * Return the FSR value for a debug exception (watchpoint, hardware
+ * breakpoint or BKPT insn) targeting the specified exception level.
+ */
+static uint32_t arm_debug_exception_fsr(CPUARMState *env)
+{
+ARMMMUFaultInfo fi = { .type = ARMFault_Debug };
+int target_el = arm_debug_target_el(env);
+bool using_lpae = false;
+
+if (target_el == 2 || arm_el_is_aa64(env, target_el)) {
+using_lpae = true;
+} else {
+if (arm_feature(env, ARM_FEATURE_LPAE) &&
+(env->cp15.tcr_el[target_el].raw_tcr & TTBCR_EAE)) {
+using_lpae = true;
+}
+}
+
+if (using_lpae) {
+return arm_fi_to_lfsc(&fi);
+} else {
+return arm_fi_to_sfsc(&fi);
+}
+}
+
 void arm_debug_excp_handler(CPUState *cs)
 {
 /*
-- 
2.34.1




[PATCH v2 05/25] target/arm: Move arm_singlestep_active out of line

2022-06-06 Thread Richard Henderson
Move the function to debug_helper.c, and the
declaration to internals.h.

Reviewed-by: Peter Maydell 
Signed-off-by: Richard Henderson 
---
 target/arm/cpu.h  | 10 --
 target/arm/internals.h|  1 +
 target/arm/debug_helper.c | 12 
 3 files changed, 13 insertions(+), 10 deletions(-)

diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index c1865ad5da..2e115a0281 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -3087,16 +3087,6 @@ static inline bool 
arm_generate_debug_exceptions(CPUARMState *env)
 }
 }
 
-/* Is single-stepping active? (Note that the "is EL_D AArch64?" check
- * implicitly means this always returns false in pre-v8 CPUs.)
- */
-static inline bool arm_singlestep_active(CPUARMState *env)
-{
-return extract32(env->cp15.mdscr_el1, 0, 1)
-&& arm_el_is_aa64(env, arm_debug_target_el(env))
-&& arm_generate_debug_exceptions(env);
-}
-
 static inline bool arm_sctlr_b(CPUARMState *env)
 {
 return
diff --git a/target/arm/internals.h b/target/arm/internals.h
index 36c33a6ac5..148f2a9252 100644
--- a/target/arm/internals.h
+++ b/target/arm/internals.h
@@ -1315,5 +1315,6 @@ void define_cortex_a72_a57_a53_cp_reginfo(ARMCPU *cpu);
 
 void aa32_max_features(ARMCPU *cpu);
 int exception_target_el(CPUARMState *env);
+bool arm_singlestep_active(CPUARMState *env);
 
 #endif
diff --git a/target/arm/debug_helper.c b/target/arm/debug_helper.c
index 46893697cc..1abf41c5f8 100644
--- a/target/arm/debug_helper.c
+++ b/target/arm/debug_helper.c
@@ -11,6 +11,18 @@
 #include "exec/exec-all.h"
 #include "exec/helper-proto.h"
 
+
+/*
+ * Is single-stepping active? (Note that the "is EL_D AArch64?" check
+ * implicitly means this always returns false in pre-v8 CPUs.)
+ */
+bool arm_singlestep_active(CPUARMState *env)
+{
+return extract32(env->cp15.mdscr_el1, 0, 1)
+&& arm_el_is_aa64(env, arm_debug_target_el(env))
+&& arm_generate_debug_exceptions(env);
+}
+
 /* Return true if the linked breakpoint entry lbn passes its checks */
 static bool linked_bp_matches(ARMCPU *cpu, int lbn)
 {
-- 
2.34.1




[PATCH v2 16/25] target/arm: Move gen_exception to translate.c

2022-06-06 Thread Richard Henderson
This function is not required by any other translation file.

Signed-off-by: Richard Henderson 
---
 target/arm/translate.h | 8 
 target/arm/translate.c | 7 +++
 2 files changed, 7 insertions(+), 8 deletions(-)

diff --git a/target/arm/translate.h b/target/arm/translate.h
index 4a93cac65f..d7a9acf5a9 100644
--- a/target/arm/translate.h
+++ b/target/arm/translate.h
@@ -328,14 +328,6 @@ static inline void gen_ss_advance(DisasContext *s)
 }
 }
 
-static inline void gen_exception(int excp, uint32_t syndrome,
- uint32_t target_el)
-{
-gen_helper_exception_with_syndrome_el(cpu_env, tcg_constant_i32(excp),
-  tcg_constant_i32(syndrome),
-  tcg_constant_i32(target_el));
-}
-
 static inline void gen_exception_advsimdfp_access(DisasContext *s,
   uint32_t syndrome)
 {
diff --git a/target/arm/translate.c b/target/arm/translate.c
index b8a8972bac..fc5eafaeeb 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -1086,6 +1086,13 @@ static void gen_exception_internal_insn(DisasContext *s, 
uint32_t pc, int excp)
 s->base.is_jmp = DISAS_NORETURN;
 }
 
+static void gen_exception(int excp, uint32_t syndrome, uint32_t target_el)
+{
+gen_helper_exception_with_syndrome_el(cpu_env, tcg_constant_i32(excp),
+  tcg_constant_i32(syndrome),
+  tcg_constant_i32(target_el));
+}
+
 static void gen_exception_insn_el_v(DisasContext *s, uint64_t pc, int excp,
 uint32_t syn, TCGv_i32 tcg_el)
 {
-- 
2.34.1




[PATCH v2 17/25] target/arm: Rename gen_exception to gen_exception_el

2022-06-06 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 target/arm/translate.c | 18 +-
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/target/arm/translate.c b/target/arm/translate.c
index fc5eafaeeb..edb7d3f394 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -1086,7 +1086,7 @@ static void gen_exception_internal_insn(DisasContext *s, 
uint32_t pc, int excp)
 s->base.is_jmp = DISAS_NORETURN;
 }
 
-static void gen_exception(int excp, uint32_t syndrome, uint32_t target_el)
+static void gen_exception_el(int excp, uint32_t syndrome, uint32_t target_el)
 {
 gen_helper_exception_with_syndrome_el(cpu_env, tcg_constant_i32(excp),
   tcg_constant_i32(syndrome),
@@ -9758,16 +9758,16 @@ static void arm_tr_tb_stop(DisasContextBase *dcbase, 
CPUState *cpu)
 switch (dc->base.is_jmp) {
 case DISAS_SWI:
 gen_ss_advance(dc);
-gen_exception(EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb),
-  default_exception_el(dc));
+gen_exception_el(EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb),
+ default_exception_el(dc));
 break;
 case DISAS_HVC:
 gen_ss_advance(dc);
-gen_exception(EXCP_HVC, syn_aa32_hvc(dc->svc_imm), 2);
+gen_exception_el(EXCP_HVC, syn_aa32_hvc(dc->svc_imm), 2);
 break;
 case DISAS_SMC:
 gen_ss_advance(dc);
-gen_exception(EXCP_SMC, syn_aa32_smc(), 3);
+gen_exception_el(EXCP_SMC, syn_aa32_smc(), 3);
 break;
 case DISAS_NEXT:
 case DISAS_TOO_MANY:
@@ -9828,14 +9828,14 @@ static void arm_tr_tb_stop(DisasContextBase *dcbase, 
CPUState *cpu)
 gen_helper_yield(cpu_env);
 break;
 case DISAS_SWI:
-gen_exception(EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb),
-  default_exception_el(dc));
+gen_exception_el(EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb),
+ default_exception_el(dc));
 break;
 case DISAS_HVC:
-gen_exception(EXCP_HVC, syn_aa32_hvc(dc->svc_imm), 2);
+gen_exception_el(EXCP_HVC, syn_aa32_hvc(dc->svc_imm), 2);
 break;
 case DISAS_SMC:
-gen_exception(EXCP_SMC, syn_aa32_smc(), 3);
+gen_exception_el(EXCP_SMC, syn_aa32_smc(), 3);
 break;
 }
 }
-- 
2.34.1




[PATCH v2 10/25] target/arm: Rename helper_exception_with_syndrome

2022-06-06 Thread Richard Henderson
Rename to helper_exception_with_syndrome_el, to emphasize
that the target el is a parameter.

Signed-off-by: Richard Henderson 
---
 target/arm/helper.h| 2 +-
 target/arm/translate.h | 6 +++---
 target/arm/op_helper.c | 6 +++---
 target/arm/translate.c | 6 +++---
 4 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/target/arm/helper.h b/target/arm/helper.h
index a13007699d..aca86612b4 100644
--- a/target/arm/helper.h
+++ b/target/arm/helper.h
@@ -45,7 +45,7 @@ DEF_HELPER_FLAGS_2(usad8, TCG_CALL_NO_RWG_SE, i32, i32, i32)
 DEF_HELPER_FLAGS_3(sel_flags, TCG_CALL_NO_RWG_SE,
i32, i32, i32, i32)
 DEF_HELPER_2(exception_internal, noreturn, env, i32)
-DEF_HELPER_4(exception_with_syndrome, noreturn, env, i32, i32, i32)
+DEF_HELPER_4(exception_with_syndrome_el, noreturn, env, i32, i32, i32)
 DEF_HELPER_3(exception_advsimdfp_access, noreturn, env, i32, i32)
 DEF_HELPER_2(exception_bkpt_insn, noreturn, env, i32)
 DEF_HELPER_2(exception_pc_alignment, noreturn, env, tl)
diff --git a/target/arm/translate.h b/target/arm/translate.h
index da5f89d49d..1d6a8c7dca 100644
--- a/target/arm/translate.h
+++ b/target/arm/translate.h
@@ -332,9 +332,9 @@ static inline void gen_ss_advance(DisasContext *s)
 static inline void gen_exception(int excp, uint32_t syndrome,
  uint32_t target_el)
 {
-gen_helper_exception_with_syndrome(cpu_env, tcg_constant_i32(excp),
-   tcg_constant_i32(syndrome),
-   tcg_constant_i32(target_el));
+gen_helper_exception_with_syndrome_el(cpu_env, tcg_constant_i32(excp),
+  tcg_constant_i32(syndrome),
+  tcg_constant_i32(target_el));
 }
 
 static inline void gen_exception_advsimdfp_access(DisasContext *s,
diff --git a/target/arm/op_helper.c b/target/arm/op_helper.c
index ae0009d1a3..1c4e6753f6 100644
--- a/target/arm/op_helper.c
+++ b/target/arm/op_helper.c
@@ -373,7 +373,7 @@ void HELPER(yield)(CPUARMState *env)
  * those EXCP values which are special cases for QEMU to interrupt
  * execution and not to be used for exceptions which are passed to
  * the guest (those must all have syndrome information and thus should
- * use exception_with_syndrome).
+ * use exception_with_syndrome*).
  */
 void HELPER(exception_internal)(CPUARMState *env, uint32_t excp)
 {
@@ -385,8 +385,8 @@ void HELPER(exception_internal)(CPUARMState *env, uint32_t 
excp)
 }
 
 /* Raise an exception with the specified syndrome register value */
-void HELPER(exception_with_syndrome)(CPUARMState *env, uint32_t excp,
- uint32_t syndrome, uint32_t target_el)
+void HELPER(exception_with_syndrome_el)(CPUARMState *env, uint32_t excp,
+uint32_t syndrome, uint32_t target_el)
 {
 raise_exception(env, excp, syndrome, target_el);
 }
diff --git a/target/arm/translate.c b/target/arm/translate.c
index 87a899d638..dc033600c0 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -1119,9 +1119,9 @@ static void gen_exception_el(DisasContext *s, int excp, 
uint32_t syn,
 {
 gen_set_condexec(s);
 gen_set_pc_im(s, s->pc_curr);
-gen_helper_exception_with_syndrome(cpu_env,
-   tcg_constant_i32(excp),
-   tcg_constant_i32(syn), tcg_el);
+gen_helper_exception_with_syndrome_el(cpu_env,
+  tcg_constant_i32(excp),
+  tcg_constant_i32(syn), tcg_el);
 s->base.is_jmp = DISAS_NORETURN;
 }
 
-- 
2.34.1




[PATCH v2 11/25] target/arm: Introduce gen_exception_insn_el_v

2022-06-06 Thread Richard Henderson
Create a function below gen_exception_insn that takes
the target_el as a TCGv_i32, replacing gen_exception_el.

Signed-off-by: Richard Henderson 
---
 target/arm/translate.c | 27 ---
 1 file changed, 12 insertions(+), 15 deletions(-)

diff --git a/target/arm/translate.c b/target/arm/translate.c
index dc033600c0..9cb31663dd 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -1086,8 +1086,8 @@ static void gen_exception_internal_insn(DisasContext *s, 
uint32_t pc, int excp)
 s->base.is_jmp = DISAS_NORETURN;
 }
 
-void gen_exception_insn(DisasContext *s, uint64_t pc, int excp,
-uint32_t syn, uint32_t target_el)
+static void gen_exception_insn_el_v(DisasContext *s, uint64_t pc, int excp,
+uint32_t syn, TCGv_i32 tcg_el)
 {
 if (s->aarch64) {
 gen_a64_set_pc_im(pc);
@@ -1095,10 +1095,17 @@ void gen_exception_insn(DisasContext *s, uint64_t pc, 
int excp,
 gen_set_condexec(s);
 gen_set_pc_im(s, pc);
 }
-gen_exception(excp, syn, target_el);
+gen_helper_exception_with_syndrome_el(cpu_env, tcg_constant_i32(excp),
+  tcg_constant_i32(syn), tcg_el);
 s->base.is_jmp = DISAS_NORETURN;
 }
 
+void gen_exception_insn(DisasContext *s, uint64_t pc, int excp,
+uint32_t syn, uint32_t target_el)
+{
+gen_exception_insn_el_v(s, pc, excp, syn, tcg_constant_i32(target_el));
+}
+
 static void gen_exception_bkpt_insn(DisasContext *s, uint32_t syn)
 {
 gen_set_condexec(s);
@@ -1114,17 +1121,6 @@ void unallocated_encoding(DisasContext *s)
default_exception_el(s));
 }
 
-static void gen_exception_el(DisasContext *s, int excp, uint32_t syn,
- TCGv_i32 tcg_el)
-{
-gen_set_condexec(s);
-gen_set_pc_im(s, s->pc_curr);
-gen_helper_exception_with_syndrome_el(cpu_env,
-  tcg_constant_i32(excp),
-  tcg_constant_i32(syn), tcg_el);
-s->base.is_jmp = DISAS_NORETURN;
-}
-
 /* Force a TB lookup after an instruction that changes the CPU state.  */
 void gen_lookup_tb(DisasContext *s)
 {
@@ -2847,7 +2843,8 @@ static bool msr_banked_access_decode(DisasContext *s, int 
r, int sysm, int rn,
 tcg_el = tcg_constant_i32(3);
 }
 
-gen_exception_el(s, EXCP_UDEF, syn_uncategorized(), tcg_el);
+gen_exception_insn_el_v(s, s->pc_curr, EXCP_UDEF,
+syn_uncategorized(), tcg_el);
 tcg_temp_free_i32(tcg_el);
 return false;
 }
-- 
2.34.1




[PATCH v2 12/25] target/arm: Rename gen_exception_insn to gen_exception_insn_el

2022-06-06 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 target/arm/translate.h|  4 ++--
 target/arm/translate-a64.c| 30 +--
 target/arm/translate-m-nocp.c | 16 +++---
 target/arm/translate-mve.c|  4 ++--
 target/arm/translate-vfp.c|  4 ++--
 target/arm/translate.c| 39 ++-
 6 files changed, 49 insertions(+), 48 deletions(-)

diff --git a/target/arm/translate.h b/target/arm/translate.h
index 1d6a8c7dca..c54db51d70 100644
--- a/target/arm/translate.h
+++ b/target/arm/translate.h
@@ -279,8 +279,8 @@ void arm_jump_cc(DisasCompare *cmp, TCGLabel *label);
 void arm_gen_test_cc(int cc, TCGLabel *label);
 MemOp pow2_align(unsigned i);
 void unallocated_encoding(DisasContext *s);
-void gen_exception_insn(DisasContext *s, uint64_t pc, int excp,
-uint32_t syn, uint32_t target_el);
+void gen_exception_insn_el(DisasContext *s, uint64_t pc, int excp,
+   uint32_t syn, uint32_t target_el);
 
 /* Return state of Alternate Half-precision flag, caller frees result */
 static inline TCGv_i32 get_ahp_flag(void)
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
index 3251c69180..cc96535fae 100644
--- a/target/arm/translate-a64.c
+++ b/target/arm/translate-a64.c
@@ -1178,8 +1178,8 @@ bool sve_access_check(DisasContext *s)
 assert(!s->sve_access_checked);
 s->sve_access_checked = true;
 
-gen_exception_insn(s, s->pc_curr, EXCP_UDEF,
-   syn_sve_access_trap(), s->sve_excp_el);
+gen_exception_insn_el(s, s->pc_curr, EXCP_UDEF,
+  syn_sve_access_trap(), s->sve_excp_el);
 return false;
 }
 s->sve_access_checked = true;
@@ -1815,8 +1815,8 @@ static void gen_sysreg_undef(DisasContext *s, bool isread,
 } else {
 syndrome = syn_uncategorized();
 }
-gen_exception_insn(s, s->pc_curr, EXCP_UDEF, syndrome,
-   default_exception_el(s));
+gen_exception_insn_el(s, s->pc_curr, EXCP_UDEF, syndrome,
+  default_exception_el(s));
 }
 
 /* MRS - move from system register
@@ -2068,8 +2068,8 @@ static void disas_exc(DisasContext *s, uint32_t insn)
 switch (op2_ll) {
 case 1: /* SVC */
 gen_ss_advance(s);
-gen_exception_insn(s, s->base.pc_next, EXCP_SWI,
-   syn_aa64_svc(imm16), default_exception_el(s));
+gen_exception_insn_el(s, s->base.pc_next, EXCP_SWI,
+  syn_aa64_svc(imm16), 
default_exception_el(s));
 break;
 case 2: /* HVC */
 if (s->current_el == 0) {
@@ -2082,8 +2082,8 @@ static void disas_exc(DisasContext *s, uint32_t insn)
 gen_a64_set_pc_im(s->pc_curr);
 gen_helper_pre_hvc(cpu_env);
 gen_ss_advance(s);
-gen_exception_insn(s, s->base.pc_next, EXCP_HVC,
-   syn_aa64_hvc(imm16), 2);
+gen_exception_insn_el(s, s->base.pc_next, EXCP_HVC,
+  syn_aa64_hvc(imm16), 2);
 break;
 case 3: /* SMC */
 if (s->current_el == 0) {
@@ -2093,8 +2093,8 @@ static void disas_exc(DisasContext *s, uint32_t insn)
 gen_a64_set_pc_im(s->pc_curr);
 gen_helper_pre_smc(cpu_env, tcg_constant_i32(syn_aa64_smc(imm16)));
 gen_ss_advance(s);
-gen_exception_insn(s, s->base.pc_next, EXCP_SMC,
-   syn_aa64_smc(imm16), 3);
+gen_exception_insn_el(s, s->base.pc_next, EXCP_SMC,
+  syn_aa64_smc(imm16), 3);
 break;
 default:
 unallocated_encoding(s);
@@ -14724,8 +14724,8 @@ static void aarch64_tr_translate_insn(DisasContextBase 
*dcbase, CPUState *cpu)
  * Illegal execution state. This has priority over BTI
  * exceptions, but comes after instruction abort exceptions.
  */
-gen_exception_insn(s, s->pc_curr, EXCP_UDEF,
-   syn_illegalstate(), default_exception_el(s));
+gen_exception_insn_el(s, s->pc_curr, EXCP_UDEF,
+  syn_illegalstate(), default_exception_el(s));
 return;
 }
 
@@ -14756,9 +14756,9 @@ static void aarch64_tr_translate_insn(DisasContextBase 
*dcbase, CPUState *cpu)
 if (s->btype != 0
 && s->guarded_page
 && !btype_destination_ok(insn, s->bt, s->btype)) {
-gen_exception_insn(s, s->pc_curr, EXCP_UDEF,
-   syn_btitrap(s->btype),
-   default_exception_el(s));
+gen_exception_insn_el(s, s->pc_curr, EXCP_UDEF,
+  

[PATCH v2 13/25] target/arm: Introduce gen_exception_insn

2022-06-06 Thread Richard Henderson
Create a new wrapper function that passes the default
exception target to gen_exception_insn_el.

Signed-off-by: Richard Henderson 
---
 target/arm/translate.h|  1 +
 target/arm/translate-a64.c| 15 ++-
 target/arm/translate-m-nocp.c |  3 +--
 target/arm/translate-mve.c|  3 +--
 target/arm/translate.c| 29 +
 5 files changed, 22 insertions(+), 29 deletions(-)

diff --git a/target/arm/translate.h b/target/arm/translate.h
index c54db51d70..04d45da54e 100644
--- a/target/arm/translate.h
+++ b/target/arm/translate.h
@@ -281,6 +281,7 @@ MemOp pow2_align(unsigned i);
 void unallocated_encoding(DisasContext *s);
 void gen_exception_insn_el(DisasContext *s, uint64_t pc, int excp,
uint32_t syn, uint32_t target_el);
+void gen_exception_insn(DisasContext *s, uint64_t pc, int excp, uint32_t syn);
 
 /* Return state of Alternate Half-precision flag, caller frees result */
 static inline TCGv_i32 get_ahp_flag(void)
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
index cc96535fae..a5c66ce085 100644
--- a/target/arm/translate-a64.c
+++ b/target/arm/translate-a64.c
@@ -1815,8 +1815,7 @@ static void gen_sysreg_undef(DisasContext *s, bool isread,
 } else {
 syndrome = syn_uncategorized();
 }
-gen_exception_insn_el(s, s->pc_curr, EXCP_UDEF, syndrome,
-  default_exception_el(s));
+gen_exception_insn(s, s->pc_curr, EXCP_UDEF, syndrome);
 }
 
 /* MRS - move from system register
@@ -2068,8 +2067,8 @@ static void disas_exc(DisasContext *s, uint32_t insn)
 switch (op2_ll) {
 case 1: /* SVC */
 gen_ss_advance(s);
-gen_exception_insn_el(s, s->base.pc_next, EXCP_SWI,
-  syn_aa64_svc(imm16), 
default_exception_el(s));
+gen_exception_insn(s, s->base.pc_next, EXCP_SWI,
+   syn_aa64_svc(imm16));
 break;
 case 2: /* HVC */
 if (s->current_el == 0) {
@@ -14724,8 +14723,7 @@ static void aarch64_tr_translate_insn(DisasContextBase 
*dcbase, CPUState *cpu)
  * Illegal execution state. This has priority over BTI
  * exceptions, but comes after instruction abort exceptions.
  */
-gen_exception_insn_el(s, s->pc_curr, EXCP_UDEF,
-  syn_illegalstate(), default_exception_el(s));
+gen_exception_insn(s, s->pc_curr, EXCP_UDEF, syn_illegalstate());
 return;
 }
 
@@ -14756,9 +14754,8 @@ static void aarch64_tr_translate_insn(DisasContextBase 
*dcbase, CPUState *cpu)
 if (s->btype != 0
 && s->guarded_page
 && !btype_destination_ok(insn, s->bt, s->btype)) {
-gen_exception_insn_el(s, s->pc_curr, EXCP_UDEF,
-  syn_btitrap(s->btype),
-  default_exception_el(s));
+gen_exception_insn(s, s->pc_curr, EXCP_UDEF,
+   syn_btitrap(s->btype));
 return;
 }
 } else {
diff --git a/target/arm/translate-m-nocp.c b/target/arm/translate-m-nocp.c
index 636bfb1788..4029d7fdd4 100644
--- a/target/arm/translate-m-nocp.c
+++ b/target/arm/translate-m-nocp.c
@@ -765,8 +765,7 @@ static bool trans_NOCP(DisasContext *s, arg_nocp *a)
 }
 
 if (a->cp != 10) {
-gen_exception_insn_el(s, s->pc_curr, EXCP_NOCP,
-  syn_uncategorized(), default_exception_el(s));
+gen_exception_insn(s, s->pc_curr, EXCP_NOCP, syn_uncategorized());
 return true;
 }
 
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
index 5aec2a1555..0cf1b5ea4f 100644
--- a/target/arm/translate-mve.c
+++ b/target/arm/translate-mve.c
@@ -100,8 +100,7 @@ bool mve_eci_check(DisasContext *s)
 return true;
 default:
 /* Reserved value: INVSTATE UsageFault */
-gen_exception_insn_el(s, s->pc_curr, EXCP_INVSTATE, 
syn_uncategorized(),
-  default_exception_el(s));
+gen_exception_insn(s, s->pc_curr, EXCP_INVSTATE, syn_uncategorized());
 return false;
 }
 }
diff --git a/target/arm/translate.c b/target/arm/translate.c
index 44f462a3a3..c7d422b541 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -1106,6 +1106,11 @@ void gen_exception_insn_el(DisasContext *s, uint64_t pc, 
int excp,
 gen_exception_insn_el_v(s, pc, excp, syn, tcg_constant_i32(target_el));
 }
 
+void gen_exception_insn(DisasContext *s, uint64_t pc, int excp, uint32_t syn)
+{
+gen_exception_insn_el(s, pc, excp, syn, default_exception_el(s));
+}
+
 static void gen_exception_bkpt_insn(DisasContext *s, uint32_t syn)
 {
 gen_set_condexec(s);
@@ -1117,8 +1122,7 @@ static void gen_exception_bkpt_insn(DisasConte

[PATCH v2 24/25] target/arm: Rearrange Secure PL1 test in arm_debug_target_el

2022-06-06 Thread Richard Henderson
Not a bug, because arm_is_el2_enabled tests for secure,
and SCR_EL3.EEL2 cannot be set for AArch32, however the
ordering of the tests looks odd.  Mirror the structure
over in exception_target_el().

Signed-off-by: Richard Henderson 
---
 target/arm/debug_helper.c | 30 --
 1 file changed, 16 insertions(+), 14 deletions(-)

diff --git a/target/arm/debug_helper.c b/target/arm/debug_helper.c
index b18a6bd3a2..59dfcb5d5c 100644
--- a/target/arm/debug_helper.c
+++ b/target/arm/debug_helper.c
@@ -15,22 +15,24 @@
 /* Return the Exception Level targeted by debug exceptions. */
 static int arm_debug_target_el(CPUARMState *env)
 {
-bool secure = arm_is_secure(env);
-bool route_to_el2 = false;
-
-if (arm_is_el2_enabled(env)) {
-route_to_el2 = env->cp15.hcr_el2 & HCR_TGE ||
-   env->cp15.mdcr_el2 & MDCR_TDE;
-}
-
-if (route_to_el2) {
-return 2;
-} else if (arm_feature(env, ARM_FEATURE_EL3) &&
-   !arm_el_is_aa64(env, 3) && secure) {
+/*
+ * No such thing as secure EL1 if EL3 is AArch32.
+ * Remap Secure PL1 to EL3.
+ */
+if (arm_is_secure(env) && !arm_el_is_aa64(env, 3)) {
 return 3;
-} else {
-return 1;
 }
+
+/*
+ * HCR.TGE redirects EL0 exceptions from EL1 to EL2.
+ * MDCR.TDE redirects both EL0 and EL1 debug exceptions to EL2.
+ */
+if (arm_is_el2_enabled(env) &&
+(env->cp15.hcr_el2 & HCR_TGE || env->cp15.mdcr_el2 & MDCR_TDE)) {
+return 2;
+}
+
+return 1;
 }
 
 /*
-- 
2.34.1




[PATCH v2 18/25] target/arm: Introduce gen_exception

2022-06-06 Thread Richard Henderson
Create a new wrapper function that passes the default
exception target to gen_exception_el.

Signed-off-by: Richard Henderson 
---
 target/arm/translate.c | 11 +++
 1 file changed, 7 insertions(+), 4 deletions(-)

diff --git a/target/arm/translate.c b/target/arm/translate.c
index edb7d3f394..5a48937ede 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -1093,6 +1093,11 @@ static void gen_exception_el(int excp, uint32_t 
syndrome, uint32_t target_el)
   tcg_constant_i32(target_el));
 }
 
+static void gen_exception(DisasContext *s, int excp, uint32_t syndrome)
+{
+gen_exception_el(excp, syndrome, default_exception_el(s));
+}
+
 static void gen_exception_insn_el_v(DisasContext *s, uint64_t pc, int excp,
 uint32_t syn, TCGv_i32 tcg_el)
 {
@@ -9758,8 +9763,7 @@ static void arm_tr_tb_stop(DisasContextBase *dcbase, 
CPUState *cpu)
 switch (dc->base.is_jmp) {
 case DISAS_SWI:
 gen_ss_advance(dc);
-gen_exception_el(EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb),
- default_exception_el(dc));
+gen_exception(dc, EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb));
 break;
 case DISAS_HVC:
 gen_ss_advance(dc);
@@ -9828,8 +9832,7 @@ static void arm_tr_tb_stop(DisasContextBase *dcbase, 
CPUState *cpu)
 gen_helper_yield(cpu_env);
 break;
 case DISAS_SWI:
-gen_exception_el(EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb),
- default_exception_el(dc));
+gen_exception(dc, EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb));
 break;
 case DISAS_HVC:
 gen_exception_el(EXCP_HVC, syn_aa32_hvc(dc->svc_imm), 2);
-- 
2.34.1




Re: [PATCH v3 3/4] target/riscv: Update [m|h]tinst CSR in riscv_cpu_do_interrupt()

2022-06-06 Thread Anup Patel
On Mon, Jun 6, 2022 at 7:23 AM Alistair Francis  wrote:
>
> On Mon, Jun 6, 2022 at 11:48 AM Alistair Francis  wrote:
> >
> > On Thu, May 26, 2022 at 8:12 PM Anup Patel  wrote:
> > >
> > > We should write transformed instruction encoding of the trapped
> > > instruction in [m|h]tinst CSR at time of taking trap as defined
> > > by the RISC-V privileged specification v1.12.
> > >
> > > Signed-off-by: Anup Patel 
> >
> > Reviewed-by: Alistair Francis 
>
> Whoops, I thought there was another patch. This doesn't seem to
> implemented the guest-page fault pseudoinstructions which can be
> generated while doing VS-stage translation

I did not understand. Which guest-page fault pseudo-instructions ?

Regards,
Anup

>
> Alistair
>
> >
> > Alistair
> >
> > > ---
> > >  target/riscv/cpu_helper.c | 210 +-
> > >  target/riscv/instmap.h|  43 
> > >  2 files changed, 249 insertions(+), 4 deletions(-)
> > >
> > > diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
> > > index d99fac9d2d..2a2b6776fb 100644
> > > --- a/target/riscv/cpu_helper.c
> > > +++ b/target/riscv/cpu_helper.c
> > > @@ -22,6 +22,7 @@
> > >  #include "qemu/main-loop.h"
> > >  #include "cpu.h"
> > >  #include "exec/exec-all.h"
> > > +#include "instmap.h"
> > >  #include "tcg/tcg-op.h"
> > >  #include "trace.h"
> > >  #include "semihosting/common-semi.h"
> > > @@ -1316,6 +1317,200 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr 
> > > address, int size,
> > >
> > >  return true;
> > >  }
> > > +
> > > +static target_ulong riscv_transformed_insn(CPURISCVState *env,
> > > +   target_ulong insn)
> > > +{
> > > +bool xinsn_has_addr_offset = false;
> > > +target_ulong xinsn = 0;
> > > +
> > > +/*
> > > + * Only Quadrant 0 and Quadrant 2 of RVC instruction space need to
> > > + * be uncompressed. The Quadrant 1 of RVC instruction space need
> > > + * not be transformed because these instructions won't generate
> > > + * any load/store trap.
> > > + */
> > > +
> > > +if ((insn & 0x3) != 0x3) {
> > > +/* Transform 16bit instruction into 32bit instruction */
> > > +switch (GET_C_OP(insn)) {
> > > +case OPC_RISC_C_OP_QUAD0: /* Quadrant 0 */
> > > +switch (GET_C_FUNC(insn)) {
> > > +case OPC_RISC_C_FUNC_FLD_LQ:
> > > +if (riscv_cpu_xlen(env) != 128) { /* C.FLD (RV32/64) */
> > > +xinsn = OPC_RISC_FLD;
> > > +xinsn = SET_RD(xinsn, GET_C_RS2S(insn));
> > > +xinsn = SET_RS1(xinsn, GET_C_RS1S(insn));
> > > +xinsn = SET_I_IMM(xinsn, GET_C_LD_IMM(insn));
> > > +xinsn_has_addr_offset = true;
> > > +}
> > > +break;
> > > +case OPC_RISC_C_FUNC_LW: /* C.LW */
> > > +xinsn = OPC_RISC_LW;
> > > +xinsn = SET_RD(xinsn, GET_C_RS2S(insn));
> > > +xinsn = SET_RS1(xinsn, GET_C_RS1S(insn));
> > > +xinsn = SET_I_IMM(xinsn, GET_C_LW_IMM(insn));
> > > +xinsn_has_addr_offset = true;
> > > +break;
> > > +case OPC_RISC_C_FUNC_FLW_LD:
> > > +if (riscv_cpu_xlen(env) == 32) { /* C.FLW (RV32) */
> > > +xinsn = OPC_RISC_FLW;
> > > +xinsn = SET_RD(xinsn, GET_C_RS2S(insn));
> > > +xinsn = SET_RS1(xinsn, GET_C_RS1S(insn));
> > > +xinsn = SET_I_IMM(xinsn, GET_C_LW_IMM(insn));
> > > +xinsn_has_addr_offset = true;
> > > +} else { /* C.LD (RV64/RV128) */
> > > +xinsn = OPC_RISC_LD;
> > > +xinsn = SET_RD(xinsn, GET_C_RS2S(insn));
> > > +xinsn = SET_RS1(xinsn, GET_C_RS1S(insn));
> > > +xinsn = SET_I_IMM(xinsn, GET_C_LD_IMM(insn));
> > > +xinsn_has_addr_offset = true;
> > > +}
> > > +break;
> > > +case OPC_RISC_C_FUNC_FSD_SQ:
> > > +if (riscv_cpu_xlen(env) != 128) { /* C.FSD (RV32/64) */
> > > +xinsn = OPC_RISC_FSD;
> > > +xinsn = SET_RS2(xinsn, GET_C_RS2S(insn));
> > > +xinsn = SET_RS1(xinsn, GET_C_RS1S(insn));
> > > +xinsn = SET_S_IMM(xinsn, GET_C_SD_IMM(insn));
> > > +xinsn_has_addr_offset = true;
> > > +}
> > > +break;
> > > +case OPC_RISC_C_FUNC_SW: /* C.SW */
> > > +xinsn = OPC_RISC_SW;
> > > +xinsn = SET_RS2(xinsn, GET_C_RS2S(insn));
> > > +xinsn = SET_RS1(xinsn, GET_C_RS1S(insn));
> > > +xinsn = SET_S_IMM(xinsn, GET_C_SW_IMM(insn));
> > > +xinsn_has_addr_offset = true;
> > > +break;
> > > +case OPC_RISC_C_FUNC_FSW_S

[PATCH v2 22/25] target/arm: Create raise_exception_debug

2022-06-06 Thread Richard Henderson
Handle the debug vs current el exception test in one place.
Leave EXCP_BKPT alone, since that treats debug < current differently.

Signed-off-by: Richard Henderson 
---
 target/arm/debug_helper.c | 44 +--
 1 file changed, 24 insertions(+), 20 deletions(-)

diff --git a/target/arm/debug_helper.c b/target/arm/debug_helper.c
index a3a1b98de2..26004df99b 100644
--- a/target/arm/debug_helper.c
+++ b/target/arm/debug_helper.c
@@ -12,6 +12,26 @@
 #include "exec/helper-proto.h"
 
 
+/*
+ * Raise an exception to the debug target el.
+ * Modify syndrome to indicate when origin and target EL are the same.
+ */
+G_NORETURN static void
+raise_exception_debug(CPUARMState *env, uint32_t excp, uint32_t syndrome)
+{
+int debug_el = arm_debug_target_el(env);
+int cur_el = arm_current_el(env);
+
+/*
+ * If singlestep is targeting a lower EL than the current one, then
+ * DisasContext.ss_active must be false and we can never get here.
+ * Similarly for watchpoint and breakpoint matches.
+ */
+assert(debug_el >= cur_el);
+syndrome |= (debug_el == cur_el) << ARM_EL_EC_SHIFT;
+raise_exception(env, excp, syndrome, debug_el);
+}
+
 /* See AArch64.GenerateDebugExceptionsFrom() in ARM ARM pseudocode */
 static bool aa64_generate_debug_exceptions(CPUARMState *env)
 {
@@ -418,19 +438,16 @@ void arm_debug_excp_handler(CPUState *cs)
 if (wp_hit) {
 if (wp_hit->flags & BP_CPU) {
 bool wnr = (wp_hit->flags & BP_WATCHPOINT_HIT_WRITE) != 0;
-bool same_el = arm_debug_target_el(env) == arm_current_el(env);
 
 cs->watchpoint_hit = NULL;
 
 env->exception.fsr = arm_debug_exception_fsr(env);
 env->exception.vaddress = wp_hit->hitaddr;
-raise_exception(env, EXCP_DATA_ABORT,
-syn_watchpoint(same_el, 0, wnr),
-arm_debug_target_el(env));
+raise_exception_debug(env, EXCP_DATA_ABORT,
+  syn_watchpoint(0, 0, wnr));
 }
 } else {
 uint64_t pc = is_a64(env) ? env->pc : env->regs[15];
-bool same_el = (arm_debug_target_el(env) == arm_current_el(env));
 
 /*
  * (1) GDB breakpoints should be handled first.
@@ -450,9 +467,7 @@ void arm_debug_excp_handler(CPUState *cs)
  * exception/security level.
  */
 env->exception.vaddress = 0;
-raise_exception(env, EXCP_PREFETCH_ABORT,
-syn_breakpoint(same_el),
-arm_debug_target_el(env));
+raise_exception_debug(env, EXCP_PREFETCH_ABORT, syn_breakpoint(0));
 }
 }
 
@@ -489,18 +504,7 @@ void HELPER(exception_bkpt_insn)(CPUARMState *env, 
uint32_t syndrome)
 
 void HELPER(exception_swstep)(CPUARMState *env, uint32_t syndrome)
 {
-int debug_el = arm_debug_target_el(env);
-int cur_el = arm_current_el(env);
-
-/*
- * If singlestep is targeting a lower EL than the current one, then
- * DisasContext.ss_active must be false and we can never get here.
- */
-assert(debug_el >= cur_el);
-if (debug_el == cur_el) {
-syndrome |= 1 << ARM_EL_EC_SHIFT;
-}
-raise_exception(env, EXCP_UDEF, syndrome, debug_el);
+raise_exception_debug(env, EXCP_UDEF, syndrome);
 }
 
 #if !defined(CONFIG_USER_ONLY)
-- 
2.34.1




[PATCH v2 19/25] target/arm: Introduce gen_exception_el_v

2022-06-06 Thread Richard Henderson
Split out a common helper function for gen_exception_el
and gen_exception_insn_el_v.

Signed-off-by: Richard Henderson 
---
 target/arm/translate.c | 13 -
 1 file changed, 8 insertions(+), 5 deletions(-)

diff --git a/target/arm/translate.c b/target/arm/translate.c
index 5a48937ede..fcb6ee648b 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -1086,11 +1086,15 @@ static void gen_exception_internal_insn(DisasContext 
*s, uint32_t pc, int excp)
 s->base.is_jmp = DISAS_NORETURN;
 }
 
-static void gen_exception_el(int excp, uint32_t syndrome, uint32_t target_el)
+static void gen_exception_el_v(int excp, uint32_t syndrome, TCGv_i32 tcg_el)
 {
 gen_helper_exception_with_syndrome_el(cpu_env, tcg_constant_i32(excp),
-  tcg_constant_i32(syndrome),
-  tcg_constant_i32(target_el));
+  tcg_constant_i32(syndrome), tcg_el);
+}
+
+static void gen_exception_el(int excp, uint32_t syndrome, uint32_t target_el)
+{
+gen_exception_el_v(excp, syndrome, tcg_constant_i32(target_el));
 }
 
 static void gen_exception(DisasContext *s, int excp, uint32_t syndrome)
@@ -1107,8 +,7 @@ static void gen_exception_insn_el_v(DisasContext *s, 
uint64_t pc, int excp,
 gen_set_condexec(s);
 gen_set_pc_im(s, pc);
 }
-gen_helper_exception_with_syndrome_el(cpu_env, tcg_constant_i32(excp),
-  tcg_constant_i32(syn), tcg_el);
+gen_exception_el_v(excp, syn, tcg_el);
 s->base.is_jmp = DISAS_NORETURN;
 }
 
-- 
2.34.1




[PATCH v2 23/25] target/arm: Move arm_debug_target_el to debug_helper.c

2022-06-06 Thread Richard Henderson
This function is no longer used outside debug_helper.c.

Signed-off-by: Richard Henderson 
---
 target/arm/cpu.h  | 21 -
 target/arm/debug_helper.c | 21 +
 2 files changed, 21 insertions(+), 21 deletions(-)

diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 5224dc2c85..5bc6382fce 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -2967,27 +2967,6 @@ typedef enum ARMASIdx {
 ARMASIdx_TagS = 3,
 } ARMASIdx;
 
-/* Return the Exception Level targeted by debug exceptions. */
-static inline int arm_debug_target_el(CPUARMState *env)
-{
-bool secure = arm_is_secure(env);
-bool route_to_el2 = false;
-
-if (arm_is_el2_enabled(env)) {
-route_to_el2 = env->cp15.hcr_el2 & HCR_TGE ||
-   env->cp15.mdcr_el2 & MDCR_TDE;
-}
-
-if (route_to_el2) {
-return 2;
-} else if (arm_feature(env, ARM_FEATURE_EL3) &&
-   !arm_el_is_aa64(env, 3) && secure) {
-return 3;
-} else {
-return 1;
-}
-}
-
 static inline bool arm_v7m_csselr_razwi(ARMCPU *cpu)
 {
 /* If all the CLIDR.Ctypem bits are 0 there are no caches, and
diff --git a/target/arm/debug_helper.c b/target/arm/debug_helper.c
index 26004df99b..b18a6bd3a2 100644
--- a/target/arm/debug_helper.c
+++ b/target/arm/debug_helper.c
@@ -12,6 +12,27 @@
 #include "exec/helper-proto.h"
 
 
+/* Return the Exception Level targeted by debug exceptions. */
+static int arm_debug_target_el(CPUARMState *env)
+{
+bool secure = arm_is_secure(env);
+bool route_to_el2 = false;
+
+if (arm_is_el2_enabled(env)) {
+route_to_el2 = env->cp15.hcr_el2 & HCR_TGE ||
+   env->cp15.mdcr_el2 & MDCR_TDE;
+}
+
+if (route_to_el2) {
+return 2;
+} else if (arm_feature(env, ARM_FEATURE_EL3) &&
+   !arm_el_is_aa64(env, 3) && secure) {
+return 3;
+} else {
+return 1;
+}
+}
+
 /*
  * Raise an exception to the debug target el.
  * Modify syndrome to indicate when origin and target EL are the same.
-- 
2.34.1




[PATCH v2 20/25] target/arm: Introduce helper_exception_with_syndrome

2022-06-06 Thread Richard Henderson
With the helper we can use exception_target_el at runtime,
instead of default_exception_el at translate time.
While we're at it, remove the DisasContext parameter from
gen_exception, as it is no longer used.

Signed-off-by: Richard Henderson 
---
 target/arm/helper.h|  1 +
 target/arm/op_helper.c | 10 ++
 target/arm/translate.c | 18 +-
 3 files changed, 24 insertions(+), 5 deletions(-)

diff --git a/target/arm/helper.h b/target/arm/helper.h
index afc0f1a462..7c8133f83a 100644
--- a/target/arm/helper.h
+++ b/target/arm/helper.h
@@ -45,6 +45,7 @@ DEF_HELPER_FLAGS_2(usad8, TCG_CALL_NO_RWG_SE, i32, i32, i32)
 DEF_HELPER_FLAGS_3(sel_flags, TCG_CALL_NO_RWG_SE,
i32, i32, i32, i32)
 DEF_HELPER_2(exception_internal, noreturn, env, i32)
+DEF_HELPER_3(exception_with_syndrome, noreturn, env, i32, i32)
 DEF_HELPER_4(exception_with_syndrome_el, noreturn, env, i32, i32, i32)
 DEF_HELPER_3(exception_advsimdfp_access, noreturn, env, i32, i32)
 DEF_HELPER_2(exception_bkpt_insn, noreturn, env, i32)
diff --git a/target/arm/op_helper.c b/target/arm/op_helper.c
index 1c4e6753f6..32e2a92ff4 100644
--- a/target/arm/op_helper.c
+++ b/target/arm/op_helper.c
@@ -391,6 +391,16 @@ void HELPER(exception_with_syndrome_el)(CPUARMState *env, 
uint32_t excp,
 raise_exception(env, excp, syndrome, target_el);
 }
 
+/*
+ * Raise an exception with the specified syndrome register value
+ * to the default target el.
+ */
+void HELPER(exception_with_syndrome)(CPUARMState *env, uint32_t excp,
+uint32_t syndrome)
+{
+raise_exception(env, excp, syndrome, exception_target_el(env));
+}
+
 /* Raise an exception with EC_ADVSIMDFPACCESS. */
 void HELPER(exception_advsimdfp_access)(CPUARMState *env,
 uint32_t syndrome, uint32_t target_el)
diff --git a/target/arm/translate.c b/target/arm/translate.c
index fcb6ee648b..81c27e7c70 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -1097,9 +1097,10 @@ static void gen_exception_el(int excp, uint32_t 
syndrome, uint32_t target_el)
 gen_exception_el_v(excp, syndrome, tcg_constant_i32(target_el));
 }
 
-static void gen_exception(DisasContext *s, int excp, uint32_t syndrome)
+static void gen_exception(int excp, uint32_t syndrome)
 {
-gen_exception_el(excp, syndrome, default_exception_el(s));
+gen_helper_exception_with_syndrome(cpu_env, tcg_constant_i32(excp),
+   tcg_constant_i32(syndrome));
 }
 
 static void gen_exception_insn_el_v(DisasContext *s, uint64_t pc, int excp,
@@ -1123,7 +1124,14 @@ void gen_exception_insn_el(DisasContext *s, uint64_t pc, 
int excp,
 
 void gen_exception_insn(DisasContext *s, uint64_t pc, int excp, uint32_t syn)
 {
-gen_exception_insn_el(s, pc, excp, syn, default_exception_el(s));
+if (s->aarch64) {
+gen_a64_set_pc_im(pc);
+} else {
+gen_set_condexec(s);
+gen_set_pc_im(s, pc);
+}
+gen_exception(excp, syn);
+s->base.is_jmp = DISAS_NORETURN;
 }
 
 static void gen_exception_bkpt_insn(DisasContext *s, uint32_t syn)
@@ -9766,7 +9774,7 @@ static void arm_tr_tb_stop(DisasContextBase *dcbase, 
CPUState *cpu)
 switch (dc->base.is_jmp) {
 case DISAS_SWI:
 gen_ss_advance(dc);
-gen_exception(dc, EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb));
+gen_exception(EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb));
 break;
 case DISAS_HVC:
 gen_ss_advance(dc);
@@ -9835,7 +9843,7 @@ static void arm_tr_tb_stop(DisasContextBase *dcbase, 
CPUState *cpu)
 gen_helper_yield(cpu_env);
 break;
 case DISAS_SWI:
-gen_exception(dc, EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb));
+gen_exception(EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb));
 break;
 case DISAS_HVC:
 gen_exception_el(EXCP_HVC, syn_aa32_hvc(dc->svc_imm), 2);
-- 
2.34.1




[PATCH v2 21/25] target/arm: Remove default_exception_el

2022-06-06 Thread Richard Henderson
This function is no longer used.  At the same time, remove
DisasContext.secure_routed_to_el3, as it in turn becomes unused.

Signed-off-by: Richard Henderson 
---
 target/arm/translate.h | 16 
 target/arm/translate-a64.c |  5 -
 target/arm/translate.c |  5 -
 3 files changed, 26 deletions(-)

diff --git a/target/arm/translate.h b/target/arm/translate.h
index d7a9acf5a9..b01a58653e 100644
--- a/target/arm/translate.h
+++ b/target/arm/translate.h
@@ -43,8 +43,6 @@ typedef struct DisasContext {
 int fp_excp_el; /* FP exception EL or 0 if enabled */
 int sve_excp_el; /* SVE exception EL or 0 if enabled */
 int sve_len; /* SVE vector length in bytes */
-/* Flag indicating that exceptions from secure mode are routed to EL3. */
-bool secure_routed_to_el3;
 bool vfp_enabled; /* FP enabled via FPSCR.EN */
 int vec_len;
 int vec_stride;
@@ -199,20 +197,6 @@ static inline int get_mem_index(DisasContext *s)
 return arm_to_core_mmu_idx(s->mmu_idx);
 }
 
-/* Function used to determine the target exception EL when otherwise not known
- * or default.
- */
-static inline int default_exception_el(DisasContext *s)
-{
-/* If we are coming from secure EL0 in a system with a 32-bit EL3, then
- * there is no secure EL1, so we route exceptions to EL3.  Otherwise,
- * exceptions can only be routed to ELs above 1, so we target the higher of
- * 1 or the current EL.
- */
-return (s->mmu_idx == ARMMMUIdx_SE10_0 && s->secure_routed_to_el3)
-? 3 : MAX(1, s->current_el);
-}
-
 static inline void disas_set_insn_syndrome(DisasContext *s, uint32_t syn)
 {
 /* We don't need to save all of the syndrome so we mask and shift
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
index b45039a124..8da2ca8324 100644
--- a/target/arm/translate-a64.c
+++ b/target/arm/translate-a64.c
@@ -14584,11 +14584,6 @@ static void 
aarch64_tr_init_disas_context(DisasContextBase *dcbase,
 dc->condjmp = 0;
 
 dc->aarch64 = true;
-/* If we are coming from secure EL0 in a system with a 32-bit EL3, then
- * there is no secure EL1, so we route exceptions to EL3.
- */
-dc->secure_routed_to_el3 = arm_feature(env, ARM_FEATURE_EL3) &&
-   !arm_el_is_aa64(env, 3);
 dc->thumb = false;
 dc->sctlr_b = 0;
 dc->be_data = EX_TBFLAG_ANY(tb_flags, BE_DATA) ? MO_BE : MO_LE;
diff --git a/target/arm/translate.c b/target/arm/translate.c
index 81c27e7c70..6617de775f 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -9319,11 +9319,6 @@ static void arm_tr_init_disas_context(DisasContextBase 
*dcbase, CPUState *cs)
 dc->condjmp = 0;
 
 dc->aarch64 = false;
-/* If we are coming from secure EL0 in a system with a 32-bit EL3, then
- * there is no secure EL1, so we route exceptions to EL3.
- */
-dc->secure_routed_to_el3 = arm_feature(env, ARM_FEATURE_EL3) &&
-   !arm_el_is_aa64(env, 3);
 dc->thumb = EX_TBFLAG_AM32(tb_flags, THUMB);
 dc->be_data = EX_TBFLAG_ANY(tb_flags, BE_DATA) ? MO_BE : MO_LE;
 condexec = EX_TBFLAG_AM32(tb_flags, CONDEXEC);
-- 
2.34.1




[PATCH v2 25/25] target/arm: Fix Secure PL1 tests in fp_exception_el

2022-06-06 Thread Richard Henderson
We were using arm_is_secure and is_a64, which are
tests against the current EL, as opposed to
arm_el_is_aa64 and arm_is_secure_below_el3, which
can be applied to a different EL than current.
Consolidate the two tests.

Signed-off-by: Richard Henderson 
---
 target/arm/helper.c | 23 +--
 1 file changed, 9 insertions(+), 14 deletions(-)

diff --git a/target/arm/helper.c b/target/arm/helper.c
index eeca1a5dc8..1d81a01c94 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -13400,27 +13400,22 @@ int fp_exception_el(CPUARMState *env, int cur_el)
 int fpen = FIELD_EX64(env->cp15.cpacr_el1, CPACR_EL1, FPEN);
 
 switch (fpen) {
+case 1:
+if (cur_el != 0) {
+break;
+}
+/* fall through */
 case 0:
 case 2:
-if (cur_el == 0 || cur_el == 1) {
-/* Trap to PL1, which might be EL1 or EL3 */
-if (arm_is_secure(env) && !arm_el_is_aa64(env, 3)) {
-return 3;
-}
-return 1;
-}
-if (cur_el == 3 && !is_a64(env)) {
-/* Secure PL1 running at EL3 */
+/* Trap from Secure PL0 or PL1 to Secure PL1. */
+if (!arm_el_is_aa64(env, 3)
+&& (cur_el == 3 || arm_is_secure_below_el3(env))) {
 return 3;
 }
-break;
-case 1:
-if (cur_el == 0) {
+if (cur_el <= 1) {
 return 1;
 }
 break;
-case 3:
-break;
 }
 }
 
-- 
2.34.1




Re: [PATCH v3 4/4] target/riscv: Force disable extensions if priv spec version does not match

2022-06-06 Thread Anup Patel
On Mon, Jun 6, 2022 at 7:25 AM Alistair Francis  wrote:
>
> On Thu, May 26, 2022 at 8:09 PM Anup Patel  wrote:
> >
> > We should disable extensions in riscv_cpu_realize() if minimum required
> > priv spec version is not satisfied. This also ensures that machines with
> > priv spec v1.11 (or lower) cannot enable H, V, and various multi-letter
> > extensions.
> >
> > Fixes: a775398be2e ("target/riscv: Add isa extenstion strings to the
> > device tree")
> > Signed-off-by: Anup Patel 
> > ---
> >  target/riscv/cpu.c | 56 +-
> >  1 file changed, 51 insertions(+), 5 deletions(-)
> >
> > diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> > index b086eb25da..e6e878ceb3 100644
> > --- a/target/riscv/cpu.c
> > +++ b/target/riscv/cpu.c
> > @@ -43,9 +43,13 @@ static const char riscv_single_letter_exts[] = 
> > "IEMAFDQCPVH";
> >
> >  struct isa_ext_data {
> >  const char *name;
> > -bool enabled;
> > +int min_version;
> > +bool *enabled;
> >  };
> >
> > +#define ISA_EDATA_ENTRY(name, prop) {#name, PRIV_VERSION_1_10_0, 
> > &cpu->cfg.prop}
> > +#define ISA_EDATA_ENTRY2(name, min_ver, prop) {#name, min_ver, 
> > &cpu->cfg.prop}
> > +
> >  const char * const riscv_int_regnames[] = {
> >"x0/zero", "x1/ra",  "x2/sp",  "x3/gp",  "x4/tp",  "x5/t0",   "x6/t1",
> >"x7/t2",   "x8/s0",  "x9/s1",  "x10/a0", "x11/a1", "x12/a2",  "x13/a3",
> > @@ -513,8 +517,42 @@ static void riscv_cpu_realize(DeviceState *dev, Error 
> > **errp)
> >  CPURISCVState *env = &cpu->env;
> >  RISCVCPUClass *mcc = RISCV_CPU_GET_CLASS(dev);
> >  CPUClass *cc = CPU_CLASS(mcc);
> > -int priv_version = -1;
> > +int i, priv_version = -1;
> >  Error *local_err = NULL;
> > +struct isa_ext_data isa_edata_arr[] = {
> > +ISA_EDATA_ENTRY2(h, PRIV_VERSION_1_12_0, ext_h),
> > +ISA_EDATA_ENTRY2(v, PRIV_VERSION_1_12_0, ext_v),
> > +ISA_EDATA_ENTRY2(zicsr, PRIV_VERSION_1_10_0, ext_icsr),
> > +ISA_EDATA_ENTRY2(zifencei, PRIV_VERSION_1_10_0, ext_ifencei),
> > +ISA_EDATA_ENTRY2(zfh, PRIV_VERSION_1_12_0, ext_zfh),
> > +ISA_EDATA_ENTRY2(zfhmin, PRIV_VERSION_1_12_0, ext_zfhmin),
> > +ISA_EDATA_ENTRY2(zfinx, PRIV_VERSION_1_12_0, ext_zfinx),
> > +ISA_EDATA_ENTRY2(zdinx, PRIV_VERSION_1_12_0, ext_zdinx),
> > +ISA_EDATA_ENTRY2(zba, PRIV_VERSION_1_12_0, ext_zba),
> > +ISA_EDATA_ENTRY2(zbb, PRIV_VERSION_1_12_0, ext_zbb),
> > +ISA_EDATA_ENTRY2(zbc, PRIV_VERSION_1_12_0, ext_zbc),
> > +ISA_EDATA_ENTRY2(zbkb, PRIV_VERSION_1_12_0, ext_zbkb),
> > +ISA_EDATA_ENTRY2(zbkc, PRIV_VERSION_1_12_0, ext_zbkc),
> > +ISA_EDATA_ENTRY2(zbkx, PRIV_VERSION_1_12_0, ext_zbkx),
> > +ISA_EDATA_ENTRY2(zbs, PRIV_VERSION_1_12_0, ext_zbs),
> > +ISA_EDATA_ENTRY2(zk, PRIV_VERSION_1_12_0, ext_zk),
> > +ISA_EDATA_ENTRY2(zkn, PRIV_VERSION_1_12_0, ext_zkn),
> > +ISA_EDATA_ENTRY2(zknd, PRIV_VERSION_1_12_0, ext_zknd),
> > +ISA_EDATA_ENTRY2(zkne, PRIV_VERSION_1_12_0, ext_zkne),
> > +ISA_EDATA_ENTRY2(zknh, PRIV_VERSION_1_12_0, ext_zknh),
> > +ISA_EDATA_ENTRY2(zkr, PRIV_VERSION_1_12_0, ext_zkr),
> > +ISA_EDATA_ENTRY2(zks, PRIV_VERSION_1_12_0, ext_zks),
> > +ISA_EDATA_ENTRY2(zksed, PRIV_VERSION_1_12_0, ext_zksed),
> > +ISA_EDATA_ENTRY2(zksh, PRIV_VERSION_1_12_0, ext_zksh),
> > +ISA_EDATA_ENTRY2(zkt, PRIV_VERSION_1_12_0, ext_zkt),
> > +ISA_EDATA_ENTRY2(zve32f, PRIV_VERSION_1_12_0, ext_zve32f),
> > +ISA_EDATA_ENTRY2(zve64f, PRIV_VERSION_1_12_0, ext_zve64f),
> > +ISA_EDATA_ENTRY2(zhinx, PRIV_VERSION_1_12_0, ext_zhinx),
> > +ISA_EDATA_ENTRY2(zhinxmin, PRIV_VERSION_1_12_0, ext_zhinxmin),
> > +ISA_EDATA_ENTRY2(svinval, PRIV_VERSION_1_12_0, ext_svinval),
> > +ISA_EDATA_ENTRY2(svnapot, PRIV_VERSION_1_12_0, ext_svnapot),
> > +ISA_EDATA_ENTRY2(svpbmt, PRIV_VERSION_1_12_0, ext_svpbmt),
> > +};
> >
> >  cpu_exec_realizefn(cs, &local_err);
> >  if (local_err != NULL) {
> > @@ -541,6 +579,16 @@ static void riscv_cpu_realize(DeviceState *dev, Error 
> > **errp)
> >  set_priv_version(env, priv_version);
> >  }
> >
> > +/* Force disable extensions if priv spec version does not match */
> > +for (i = 0; i < ARRAY_SIZE(isa_edata_arr); i++) {
> > +if (*isa_edata_arr[i].enabled &&
> > +(env->priv_ver < isa_edata_arr[i].min_version)) {
> > +*isa_edata_arr[i].enabled = false;
> > +warn_report("privilege spec version does not match for %s 
> > extension",
> > +isa_edata_arr[i].name);
>
> This should indicate to the user that we are disabling the extension
> because of this

Sure, I will update.

Regards,
Anup

>
> Alistair
>
> > +}
> > +}
> > +
> >  if (cpu->cfg.mmu) {
> >  riscv_set_feature(env, RISCV_FEATURE_MMU);
> >  }
> > @@ -1005,8 +1053,6 @@ static void riscv_cpu_c

Re: [PATCH v3 3/4] target/riscv: Update [m|h]tinst CSR in riscv_cpu_do_interrupt()

2022-06-06 Thread Anup Patel
On Tue, Jun 7, 2022 at 8:31 AM Anup Patel  wrote:
>
> On Mon, Jun 6, 2022 at 7:23 AM Alistair Francis  wrote:
> >
> > On Mon, Jun 6, 2022 at 11:48 AM Alistair Francis  
> > wrote:
> > >
> > > On Thu, May 26, 2022 at 8:12 PM Anup Patel  
> > > wrote:
> > > >
> > > > We should write transformed instruction encoding of the trapped
> > > > instruction in [m|h]tinst CSR at time of taking trap as defined
> > > > by the RISC-V privileged specification v1.12.
> > > >
> > > > Signed-off-by: Anup Patel 
> > >
> > > Reviewed-by: Alistair Francis 
> >
> > Whoops, I thought there was another patch. This doesn't seem to
> > implemented the guest-page fault pseudoinstructions which can be
> > generated while doing VS-stage translation
>
> I did not understand. Which guest-page fault pseudo-instructions ?

Nevermind, I see what you meant. Let me check.

Regards,
Anup

>
> Regards,
> Anup
>
> >
> > Alistair
> >
> > >
> > > Alistair
> > >
> > > > ---
> > > >  target/riscv/cpu_helper.c | 210 +-
> > > >  target/riscv/instmap.h|  43 
> > > >  2 files changed, 249 insertions(+), 4 deletions(-)
> > > >
> > > > diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
> > > > index d99fac9d2d..2a2b6776fb 100644
> > > > --- a/target/riscv/cpu_helper.c
> > > > +++ b/target/riscv/cpu_helper.c
> > > > @@ -22,6 +22,7 @@
> > > >  #include "qemu/main-loop.h"
> > > >  #include "cpu.h"
> > > >  #include "exec/exec-all.h"
> > > > +#include "instmap.h"
> > > >  #include "tcg/tcg-op.h"
> > > >  #include "trace.h"
> > > >  #include "semihosting/common-semi.h"
> > > > @@ -1316,6 +1317,200 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr 
> > > > address, int size,
> > > >
> > > >  return true;
> > > >  }
> > > > +
> > > > +static target_ulong riscv_transformed_insn(CPURISCVState *env,
> > > > +   target_ulong insn)
> > > > +{
> > > > +bool xinsn_has_addr_offset = false;
> > > > +target_ulong xinsn = 0;
> > > > +
> > > > +/*
> > > > + * Only Quadrant 0 and Quadrant 2 of RVC instruction space need to
> > > > + * be uncompressed. The Quadrant 1 of RVC instruction space need
> > > > + * not be transformed because these instructions won't generate
> > > > + * any load/store trap.
> > > > + */
> > > > +
> > > > +if ((insn & 0x3) != 0x3) {
> > > > +/* Transform 16bit instruction into 32bit instruction */
> > > > +switch (GET_C_OP(insn)) {
> > > > +case OPC_RISC_C_OP_QUAD0: /* Quadrant 0 */
> > > > +switch (GET_C_FUNC(insn)) {
> > > > +case OPC_RISC_C_FUNC_FLD_LQ:
> > > > +if (riscv_cpu_xlen(env) != 128) { /* C.FLD (RV32/64) */
> > > > +xinsn = OPC_RISC_FLD;
> > > > +xinsn = SET_RD(xinsn, GET_C_RS2S(insn));
> > > > +xinsn = SET_RS1(xinsn, GET_C_RS1S(insn));
> > > > +xinsn = SET_I_IMM(xinsn, GET_C_LD_IMM(insn));
> > > > +xinsn_has_addr_offset = true;
> > > > +}
> > > > +break;
> > > > +case OPC_RISC_C_FUNC_LW: /* C.LW */
> > > > +xinsn = OPC_RISC_LW;
> > > > +xinsn = SET_RD(xinsn, GET_C_RS2S(insn));
> > > > +xinsn = SET_RS1(xinsn, GET_C_RS1S(insn));
> > > > +xinsn = SET_I_IMM(xinsn, GET_C_LW_IMM(insn));
> > > > +xinsn_has_addr_offset = true;
> > > > +break;
> > > > +case OPC_RISC_C_FUNC_FLW_LD:
> > > > +if (riscv_cpu_xlen(env) == 32) { /* C.FLW (RV32) */
> > > > +xinsn = OPC_RISC_FLW;
> > > > +xinsn = SET_RD(xinsn, GET_C_RS2S(insn));
> > > > +xinsn = SET_RS1(xinsn, GET_C_RS1S(insn));
> > > > +xinsn = SET_I_IMM(xinsn, GET_C_LW_IMM(insn));
> > > > +xinsn_has_addr_offset = true;
> > > > +} else { /* C.LD (RV64/RV128) */
> > > > +xinsn = OPC_RISC_LD;
> > > > +xinsn = SET_RD(xinsn, GET_C_RS2S(insn));
> > > > +xinsn = SET_RS1(xinsn, GET_C_RS1S(insn));
> > > > +xinsn = SET_I_IMM(xinsn, GET_C_LD_IMM(insn));
> > > > +xinsn_has_addr_offset = true;
> > > > +}
> > > > +break;
> > > > +case OPC_RISC_C_FUNC_FSD_SQ:
> > > > +if (riscv_cpu_xlen(env) != 128) { /* C.FSD (RV32/64) */
> > > > +xinsn = OPC_RISC_FSD;
> > > > +xinsn = SET_RS2(xinsn, GET_C_RS2S(insn));
> > > > +xinsn = SET_RS1(xinsn, GET_C_RS1S(insn));
> > > > +xinsn = SET_S_IMM(xinsn, GET_C_SD_IMM(insn));
> > > > +xinsn_has_addr_offset = true;
> > > > +}
> > > > +break;
> > > > +case OPC_RISC_C_FUNC_SW: /* C.SW */
> > > > +   

Re: [RFC PATCH v8 03/21] vdpa: control virtqueue support on shadow virtqueue

2022-06-06 Thread Jason Wang



在 2022/5/20 03:12, Eugenio Pérez 写道:

Introduce the control virtqueue support for vDPA shadow virtqueue. This
is needed for advanced networking features like multiqueue.

To demonstrate command handling, VIRTIO_NET_F_CTRL_MACADDR and
VIRTIO_NET_CTRL_MQ are implemented. If vDPA device is started with SVQ
support and virtio-net driver changes MAC or the number of queues
virtio-net device model will be updated with the new one.

Others cvq commands could be added here straightforwardly but they have
been not tested.

Signed-off-by: Eugenio Pérez 
---
  net/vhost-vdpa.c | 44 
  1 file changed, 44 insertions(+)

diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c
index df1e69ee72..ef12fc284c 100644
--- a/net/vhost-vdpa.c
+++ b/net/vhost-vdpa.c
@@ -11,6 +11,7 @@
  
  #include "qemu/osdep.h"

  #include "clients.h"
+#include "hw/virtio/virtio-net.h"
  #include "net/vhost_net.h"
  #include "net/vhost-vdpa.h"
  #include "hw/virtio/vhost-vdpa.h"
@@ -187,6 +188,46 @@ static NetClientInfo net_vhost_vdpa_info = {
  .check_peer_type = vhost_vdpa_check_peer_type,
  };
  
+static void vhost_vdpa_net_handle_ctrl(VirtIODevice *vdev,

+   const VirtQueueElement *elem)
+{
+struct virtio_net_ctrl_hdr ctrl;
+virtio_net_ctrl_ack status = VIRTIO_NET_ERR;
+size_t s;
+struct iovec in = {
+.iov_base = &status,
+.iov_len = sizeof(status),
+};
+
+s = iov_to_buf(elem->out_sg, elem->out_num, 0, &ctrl, sizeof(ctrl.class));
+if (s != sizeof(ctrl.class)) {
+return;
+}
+
+switch (ctrl.class) {
+case VIRTIO_NET_CTRL_MAC_ADDR_SET:
+case VIRTIO_NET_CTRL_MQ:
+break;
+default:
+return;
+};



I think we can probably remove the whitelist here since it is expected 
to work for any kind of command?


Thanks



+
+s = iov_to_buf(elem->in_sg, elem->in_num, 0, &status, sizeof(status));
+if (s != sizeof(status) || status != VIRTIO_NET_OK) {
+return;
+}
+
+status = VIRTIO_NET_ERR;
+virtio_net_handle_ctrl_iov(vdev, &in, 1, elem->out_sg, elem->out_num);
+if (status != VIRTIO_NET_OK) {
+error_report("Bad CVQ processing in model");
+}
+}
+
+static const VhostShadowVirtqueueOps vhost_vdpa_net_svq_ops = {
+.used_elem_handler = vhost_vdpa_net_handle_ctrl,
+};
+
  static NetClientState *net_vhost_vdpa_init(NetClientState *peer,
 const char *device,
 const char *name,
@@ -211,6 +252,9 @@ static NetClientState *net_vhost_vdpa_init(NetClientState 
*peer,
  
  s->vhost_vdpa.device_fd = vdpa_device_fd;

  s->vhost_vdpa.index = queue_pair_index;
+if (!is_datapath) {
+s->vhost_vdpa.shadow_vq_ops = &vhost_vdpa_net_svq_ops;
+}
  ret = vhost_vdpa_add(nc, (void *)&s->vhost_vdpa, queue_pair_index, nvqs);
  if (ret) {
  qemu_del_net_client(nc);





Re: [RFC PATCH v8 02/21] vhost: Add custom used buffer callback

2022-06-06 Thread Jason Wang



在 2022/5/20 03:12, Eugenio Pérez 写道:

The callback allows SVQ users to know the VirtQueue requests and
responses. QEMU can use this to synchronize virtio device model state,
allowing to migrate it with minimum changes to the migration code.

In the case of networking, this will be used to inspect control
virtqueue messages.

Signed-off-by: Eugenio Pérez 
---
  hw/virtio/vhost-shadow-virtqueue.h | 16 +++-
  include/hw/virtio/vhost-vdpa.h |  2 ++
  hw/virtio/vhost-shadow-virtqueue.c |  9 -
  hw/virtio/vhost-vdpa.c |  3 ++-
  4 files changed, 27 insertions(+), 3 deletions(-)

diff --git a/hw/virtio/vhost-shadow-virtqueue.h 
b/hw/virtio/vhost-shadow-virtqueue.h
index c132c994e9..6593f07db3 100644
--- a/hw/virtio/vhost-shadow-virtqueue.h
+++ b/hw/virtio/vhost-shadow-virtqueue.h
@@ -15,6 +15,13 @@
  #include "standard-headers/linux/vhost_types.h"
  #include "hw/virtio/vhost-iova-tree.h"
  
+typedef void (*VirtQueueElementCallback)(VirtIODevice *vdev,

+ const VirtQueueElement *elem);



Nit: I wonder if something like "VirtQueueCallback" is sufficient (e.g 
kernel use "callback" directly)




+
+typedef struct VhostShadowVirtqueueOps {
+VirtQueueElementCallback used_elem_handler;
+} VhostShadowVirtqueueOps;
+
  /* Shadow virtqueue to relay notifications */
  typedef struct VhostShadowVirtqueue {
  /* Shadow vring */
@@ -59,6 +66,12 @@ typedef struct VhostShadowVirtqueue {
   */
  uint16_t *desc_next;
  
+/* Optional callbacks */

+const VhostShadowVirtqueueOps *ops;



Can we merge map_ops to ops?



+
+/* Optional custom used virtqueue element handler */
+VirtQueueElementCallback used_elem_cb;



This seems not used in this series.

Thanks



+
  /* Next head to expose to the device */
  uint16_t shadow_avail_idx;
  
@@ -85,7 +98,8 @@ void vhost_svq_start(VhostShadowVirtqueue *svq, VirtIODevice *vdev,

   VirtQueue *vq);
  void vhost_svq_stop(VhostShadowVirtqueue *svq);
  
-VhostShadowVirtqueue *vhost_svq_new(VhostIOVATree *iova_tree);

+VhostShadowVirtqueue *vhost_svq_new(VhostIOVATree *iova_tree,
+const VhostShadowVirtqueueOps *ops);
  
  void vhost_svq_free(gpointer vq);

  G_DEFINE_AUTOPTR_CLEANUP_FUNC(VhostShadowVirtqueue, vhost_svq_free);
diff --git a/include/hw/virtio/vhost-vdpa.h b/include/hw/virtio/vhost-vdpa.h
index a29dbb3f53..f1ba46a860 100644
--- a/include/hw/virtio/vhost-vdpa.h
+++ b/include/hw/virtio/vhost-vdpa.h
@@ -17,6 +17,7 @@
  #include "hw/virtio/vhost-iova-tree.h"
  #include "hw/virtio/virtio.h"
  #include "standard-headers/linux/vhost_types.h"
+#include "hw/virtio/vhost-shadow-virtqueue.h"
  
  typedef struct VhostVDPAHostNotifier {

  MemoryRegion mr;
@@ -35,6 +36,7 @@ typedef struct vhost_vdpa {
  /* IOVA mapping used by the Shadow Virtqueue */
  VhostIOVATree *iova_tree;
  GPtrArray *shadow_vqs;
+const VhostShadowVirtqueueOps *shadow_vq_ops;
  struct vhost_dev *dev;
  VhostVDPAHostNotifier notifier[VIRTIO_QUEUE_MAX];
  } VhostVDPA;
diff --git a/hw/virtio/vhost-shadow-virtqueue.c 
b/hw/virtio/vhost-shadow-virtqueue.c
index 56c96ebd13..167db8be45 100644
--- a/hw/virtio/vhost-shadow-virtqueue.c
+++ b/hw/virtio/vhost-shadow-virtqueue.c
@@ -410,6 +410,10 @@ static void vhost_svq_flush(VhostShadowVirtqueue *svq,
  break;
  }
  
+if (svq->ops && svq->ops->used_elem_handler) {

+svq->ops->used_elem_handler(svq->vdev, elem);
+}
+
  if (unlikely(i >= svq->vring.num)) {
  qemu_log_mask(LOG_GUEST_ERROR,
   "More than %u used buffers obtained in a %u size 
SVQ",
@@ -607,12 +611,14 @@ void vhost_svq_stop(VhostShadowVirtqueue *svq)
   * shadow methods and file descriptors.
   *
   * @iova_tree: Tree to perform descriptors translations
+ * @ops: SVQ operations hooks
   *
   * Returns the new virtqueue or NULL.
   *
   * In case of error, reason is reported through error_report.
   */
-VhostShadowVirtqueue *vhost_svq_new(VhostIOVATree *iova_tree)
+VhostShadowVirtqueue *vhost_svq_new(VhostIOVATree *iova_tree,
+const VhostShadowVirtqueueOps *ops)
  {
  g_autofree VhostShadowVirtqueue *svq = g_new0(VhostShadowVirtqueue, 1);
  int r;
@@ -634,6 +640,7 @@ VhostShadowVirtqueue *vhost_svq_new(VhostIOVATree 
*iova_tree)
  event_notifier_init_fd(&svq->svq_kick, VHOST_FILE_UNBIND);
  event_notifier_set_handler(&svq->hdev_call, vhost_svq_handle_call);
  svq->iova_tree = iova_tree;
+svq->ops = ops;
  return g_steal_pointer(&svq);
  
  err_init_hdev_call:

diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c
index 66f054a12c..7677b337e6 100644
--- a/hw/virtio/vhost-vdpa.c
+++ b/hw/virtio/vhost-vdpa.c
@@ -418,7 +418,8 @@ static int vhost_vdpa_init_svq(struct vhost_dev *hdev, 
struct vhost_vdpa *v,
  
  shadow_vqs = g_ptr_arra

Re: [RFC PATCH v8 01/21] virtio-net: Expose ctrl virtqueue logic

2022-06-06 Thread Jason Wang



在 2022/5/20 03:12, Eugenio Pérez 写道:

This allows external vhost-net devices to modify the state of the
VirtIO device model once vhost-vdpa device has acknowledge the control
commands.

Signed-off-by: Eugenio Pérez 
---
  include/hw/virtio/virtio-net.h |  4 ++
  hw/net/virtio-net.c| 84 --
  2 files changed, 53 insertions(+), 35 deletions(-)

diff --git a/include/hw/virtio/virtio-net.h b/include/hw/virtio/virtio-net.h
index eb87032627..cd31b7f67d 100644
--- a/include/hw/virtio/virtio-net.h
+++ b/include/hw/virtio/virtio-net.h
@@ -218,6 +218,10 @@ struct VirtIONet {
  struct EBPFRSSContext ebpf_rss;
  };
  
+unsigned virtio_net_handle_ctrl_iov(VirtIODevice *vdev,

+const struct iovec *in_sg, size_t in_num,
+const struct iovec *out_sg,
+unsigned out_num);
  void virtio_net_set_netclient_name(VirtIONet *n, const char *name,
 const char *type);
  
diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c

index 7ad948ee7c..0e350154ec 100644
--- a/hw/net/virtio-net.c
+++ b/hw/net/virtio-net.c
@@ -1434,57 +1434,71 @@ static int virtio_net_handle_mq(VirtIONet *n, uint8_t 
cmd,
  return VIRTIO_NET_OK;
  }
  
-static void virtio_net_handle_ctrl(VirtIODevice *vdev, VirtQueue *vq)

+unsigned virtio_net_handle_ctrl_iov(VirtIODevice *vdev,



Should we use size_t here?

Thanks



+const struct iovec *in_sg, size_t in_num,
+const struct iovec *out_sg,
+unsigned out_num)
  {
  VirtIONet *n = VIRTIO_NET(vdev);
  struct virtio_net_ctrl_hdr ctrl;
  virtio_net_ctrl_ack status = VIRTIO_NET_ERR;
-VirtQueueElement *elem;
  size_t s;
  struct iovec *iov, *iov2;
-unsigned int iov_cnt;
+
+if (iov_size(in_sg, in_num) < sizeof(status) ||
+iov_size(out_sg, out_num) < sizeof(ctrl)) {
+virtio_error(vdev, "virtio-net ctrl missing headers");
+return 0;
+}
+
+iov2 = iov = g_memdup2(out_sg, sizeof(struct iovec) * out_num);
+s = iov_to_buf(iov, out_num, 0, &ctrl, sizeof(ctrl));
+iov_discard_front(&iov, &out_num, sizeof(ctrl));
+if (s != sizeof(ctrl)) {
+status = VIRTIO_NET_ERR;
+} else if (ctrl.class == VIRTIO_NET_CTRL_RX) {
+status = virtio_net_handle_rx_mode(n, ctrl.cmd, iov, out_num);
+} else if (ctrl.class == VIRTIO_NET_CTRL_MAC) {
+status = virtio_net_handle_mac(n, ctrl.cmd, iov, out_num);
+} else if (ctrl.class == VIRTIO_NET_CTRL_VLAN) {
+status = virtio_net_handle_vlan_table(n, ctrl.cmd, iov, out_num);
+} else if (ctrl.class == VIRTIO_NET_CTRL_ANNOUNCE) {
+status = virtio_net_handle_announce(n, ctrl.cmd, iov, out_num);
+} else if (ctrl.class == VIRTIO_NET_CTRL_MQ) {
+status = virtio_net_handle_mq(n, ctrl.cmd, iov, out_num);
+} else if (ctrl.class == VIRTIO_NET_CTRL_GUEST_OFFLOADS) {
+status = virtio_net_handle_offloads(n, ctrl.cmd, iov, out_num);
+}
+
+s = iov_from_buf(in_sg, in_num, 0, &status, sizeof(status));
+assert(s == sizeof(status));
+
+g_free(iov2);
+return sizeof(status);
+}
+
+static void virtio_net_handle_ctrl(VirtIODevice *vdev, VirtQueue *vq)
+{
+VirtQueueElement *elem;
  
  for (;;) {

+unsigned written;
  elem = virtqueue_pop(vq, sizeof(VirtQueueElement));
  if (!elem) {
  break;
  }
-if (iov_size(elem->in_sg, elem->in_num) < sizeof(status) ||
-iov_size(elem->out_sg, elem->out_num) < sizeof(ctrl)) {
-virtio_error(vdev, "virtio-net ctrl missing headers");
+
+written = virtio_net_handle_ctrl_iov(vdev, elem->in_sg, elem->in_num,
+ elem->out_sg, elem->out_num);
+if (written > 0) {
+virtqueue_push(vq, elem, written);
+virtio_notify(vdev, vq);
+g_free(elem);
+} else {
  virtqueue_detach_element(vq, elem, 0);
  g_free(elem);
  break;
  }
-
-iov_cnt = elem->out_num;
-iov2 = iov = g_memdup2(elem->out_sg,
-   sizeof(struct iovec) * elem->out_num);
-s = iov_to_buf(iov, iov_cnt, 0, &ctrl, sizeof(ctrl));
-iov_discard_front(&iov, &iov_cnt, sizeof(ctrl));
-if (s != sizeof(ctrl)) {
-status = VIRTIO_NET_ERR;
-} else if (ctrl.class == VIRTIO_NET_CTRL_RX) {
-status = virtio_net_handle_rx_mode(n, ctrl.cmd, iov, iov_cnt);
-} else if (ctrl.class == VIRTIO_NET_CTRL_MAC) {
-status = virtio_net_handle_mac(n, ctrl.cmd, iov, iov_cnt);
-} else if (ctrl.class == VIRTIO_NET_CTRL_VLAN) {
-status = virtio_net_handle_vlan_table(n, ctrl.cmd, iov, iov_cnt);
-} else if (ctrl.class == VIRTIO_NET_CTRL_ANNOUNCE) {

  1   2   3   4   >