* [Qemu-devel] [PATCH 0/9] mips: implement Inter-Thread Communication Unit
@ 2016-02-03 16:56 Leon Alrae
2016-02-03 16:56 ` [Qemu-devel] [PATCH 1/9] hw/mips: implement ITC Configuration Tags Leon Alrae
` (8 more replies)
0 siblings, 9 replies; 10+ messages in thread
From: Leon Alrae @ 2016-02-03 16:56 UTC (permalink / raw)
To: qemu-devel; +Cc: aurelien
Inter-Thread Communication Unit (ITU) provides ITC storage which is a
gating storage mechanism for efficient communication and data transfer
between threads.
Each 64-bit location or "cell" within ITC space appears at multiple
consecutive addresses, or "views", distinguished by bits [6:3] of the
load/store target address. Each view can have distinct semantics. For
example in some views a load from a cell which is empty causes the
thread issuing the load to be blocked until the cell is written to
by a store from another thread.
In this implementation there are two kinds of storage cells (four-entry
FIFO queues and single-entry Semaphore cells) and six views (Bypass,
Control, E/F Synchronized, E/F Try, P/V Synchronized and P/V Try).
ITU object contains two memory regions: ITC Storage which is memory-mapped
and ITC Configuration Tags which are accessible directly from the CPU via
Cache instruction. Guest can remap the ITC storage by writing into ITC
Configuration Tags.
If thread is supposed to be blocked then it is marked as halted and it exits
the cpu loop. On the wake-up the thread will be restarted from the last
instruction.
This patchset does not implement Gating Storage exceptions. Also it does not
implement the behaviour of SC instruction which should indicate
success/failure of the access in E/F Try view.
In QEMU the ITU is available to any multi-threaded CPU, i.e. 34Kf and
MIPS64R6-generic. Therefore this patchset applies on to top of the other
patch introducing R6 multi-threading support.
This feature has been divided into the following patches:
* patches 1 and 2: define an ITU object and initial data structures
* patches 3-6: implement ITC Views
* patch 7: add ITC block to malta board
* patch 8: minor fix for Cache instruction in R6
* patch 9: make changes in the CPU to access ITC Tags
Feedback is welcome!
Thanks,
Leon
Leon Alrae (9):
hw/mips: implement ITC Configuration Tags
hw/mips: add ITC Storage Cells
hw/mips: implement ITC Storage - Control View
hw/mips: implement ITC Storage - Empty/Full Sync and Try Views
hw/mips: implement ITC Storage - P/V Sync and Try Views
hw/mips: implement ITC Storage - Bypass View
hw/mips_malta: make ITU available to multi-threading processors
target-mips: check CP0 enabled for CACHE instruction also in R6
target-mips: make ITC Configuration Tags accessible to the CPU
default-configs/mips-softmmu.mak | 1 +
default-configs/mips64-softmmu.mak | 1 +
default-configs/mips64el-softmmu.mak | 1 +
default-configs/mipsel-softmmu.mak | 1 +
hw/mips/mips_malta.c | 53 ++++
hw/misc/Makefile.objs | 1 +
hw/misc/mips_itu.c | 515 +++++++++++++++++++++++++++++++++++
include/hw/misc/mips_itu.h | 72 +++++
target-mips/cpu.h | 8 +-
target-mips/helper.h | 3 +
target-mips/op_helper.c | 40 ++-
target-mips/translate.c | 63 ++++-
12 files changed, 747 insertions(+), 12 deletions(-)
create mode 100644 hw/misc/mips_itu.c
create mode 100644 include/hw/misc/mips_itu.h
--
2.1.0
^ permalink raw reply [flat|nested] 10+ messages in thread
* [Qemu-devel] [PATCH 1/9] hw/mips: implement ITC Configuration Tags
2016-02-03 16:56 [Qemu-devel] [PATCH 0/9] mips: implement Inter-Thread Communication Unit Leon Alrae
@ 2016-02-03 16:56 ` Leon Alrae
2016-02-03 16:56 ` [Qemu-devel] [PATCH 2/9] hw/mips: add ITC Storage Cells Leon Alrae
` (7 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Leon Alrae @ 2016-02-03 16:56 UTC (permalink / raw)
To: qemu-devel; +Cc: aurelien
Implement ITC as a single object consisting of two memory regions:
* tag_io: ITC Configuration Tags (i.e. ITCAddressMap{0,1} registers) which
are accessible by the CPU via CACHE instruction. Also adding
MemoryRegion *itc_tag to the CPUMIPSState so that CACHE instruction will
dispatch reads/writes directly.
* storage_io: memory-mapped ITC Storage whose address space is
configurable (i.e. enabled/remapped/resized) by writing to
ITCAddressMap{0,1} registers.
Signed-off-by: Leon Alrae <leon.alrae@imgtec.com>
---
default-configs/mips-softmmu.mak | 1 +
default-configs/mips64-softmmu.mak | 1 +
default-configs/mips64el-softmmu.mak | 1 +
default-configs/mipsel-softmmu.mak | 1 +
hw/misc/Makefile.objs | 1 +
hw/misc/mips_itu.c | 186 +++++++++++++++++++++++++++++++++++
include/hw/misc/mips_itu.h | 47 +++++++++
target-mips/cpu.h | 1 +
8 files changed, 239 insertions(+)
create mode 100644 hw/misc/mips_itu.c
create mode 100644 include/hw/misc/mips_itu.h
diff --git a/default-configs/mips-softmmu.mak b/default-configs/mips-softmmu.mak
index 44467c3..9754371 100644
--- a/default-configs/mips-softmmu.mak
+++ b/default-configs/mips-softmmu.mak
@@ -30,3 +30,4 @@ CONFIG_I8259=y
CONFIG_MC146818RTC=y
CONFIG_ISA_TESTDEV=y
CONFIG_EMPTY_SLOT=y
+CONFIG_MIPS_ITU=y
diff --git a/default-configs/mips64-softmmu.mak b/default-configs/mips64-softmmu.mak
index 66ed5f9..598d6b7 100644
--- a/default-configs/mips64-softmmu.mak
+++ b/default-configs/mips64-softmmu.mak
@@ -36,3 +36,4 @@ CONFIG_JAZZ_LED=y
CONFIG_MC146818RTC=y
CONFIG_ISA_TESTDEV=y
CONFIG_EMPTY_SLOT=y
+CONFIG_MIPS_ITU=y
diff --git a/default-configs/mips64el-softmmu.mak b/default-configs/mips64el-softmmu.mak
index bfca2b2..3639f66 100644
--- a/default-configs/mips64el-softmmu.mak
+++ b/default-configs/mips64el-softmmu.mak
@@ -39,3 +39,4 @@ CONFIG_MC146818RTC=y
CONFIG_VT82C686=y
CONFIG_ISA_TESTDEV=y
CONFIG_EMPTY_SLOT=y
+CONFIG_MIPS_ITU=y
diff --git a/default-configs/mipsel-softmmu.mak b/default-configs/mipsel-softmmu.mak
index 0162ef0..371aea8 100644
--- a/default-configs/mipsel-softmmu.mak
+++ b/default-configs/mipsel-softmmu.mak
@@ -30,3 +30,4 @@ CONFIG_I8259=y
CONFIG_MC146818RTC=y
CONFIG_ISA_TESTDEV=y
CONFIG_EMPTY_SLOT=y
+CONFIG_MIPS_ITU=y
diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
index d4765c2..2d95404 100644
--- a/hw/misc/Makefile.objs
+++ b/hw/misc/Makefile.objs
@@ -40,6 +40,7 @@ obj-$(CONFIG_SLAVIO) += slavio_misc.o
obj-$(CONFIG_ZYNQ) += zynq_slcr.o
obj-$(CONFIG_ZYNQ) += zynq-xadc.o
obj-$(CONFIG_STM32F2XX_SYSCFG) += stm32f2xx_syscfg.o
+obj-$(CONFIG_MIPS_ITU) += mips_itu.o
obj-$(CONFIG_PVPANIC) += pvpanic.o
obj-$(CONFIG_EDU) += edu.o
diff --git a/hw/misc/mips_itu.c b/hw/misc/mips_itu.c
new file mode 100644
index 0000000..cf79bc6
--- /dev/null
+++ b/hw/misc/mips_itu.c
@@ -0,0 +1,186 @@
+/*
+ * Inter-Thread Communication Unit emulation.
+ *
+ * Copyright (c) 2016 Imagination Technologies
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "hw/hw.h"
+#include "hw/sysbus.h"
+#include "sysemu/sysemu.h"
+#include "hw/misc/mips_itu.h"
+
+#define ITC_TAG_ADDRSPACE_SZ (ITC_ADDRESSMAP_NUM * 8)
+/* Initialize as 4kB area to fit all 32 cells with default 128B grain.
+ Storage may be resized by the software. */
+#define ITC_STORAGE_ADDRSPACE_SZ 0x1000
+
+#define ITC_FIFO_NUM_MAX 16
+#define ITC_SEMAPH_NUM_MAX 16
+#define ITC_AM1_NUMENTRIES_OFS 20
+
+#define ITC_AM0_BASE_ADDRESS_MASK 0xFFFFFC00ULL
+#define ITC_AM0_EN_MASK 0x1
+
+#define ITC_AM1_ADDR_MASK_MASK 0x1FC00
+#define ITC_AM1_ENTRY_GRAIN_MASK 0x7
+
+MemoryRegion *mips_itu_get_tag_region(MIPSITUState *itu)
+{
+ return &itu->tag_io;
+}
+
+static uint64_t itc_tag_read(void *opaque, hwaddr addr, unsigned size)
+{
+ MIPSITUState *tag = (MIPSITUState *)opaque;
+ uint64_t index = addr >> 3;
+ uint64_t ret = 0;
+
+ switch (index) {
+ case 0 ... ITC_ADDRESSMAP_NUM:
+ ret = tag->ITCAddressMap[index];
+ break;
+ default:
+ qemu_log_mask(LOG_GUEST_ERROR, "Read 0x%" PRIx64 "\n", addr);
+ break;
+ }
+
+ return ret;
+}
+
+static void itc_tag_write(void *opaque, hwaddr addr,
+ uint64_t data, unsigned size)
+{
+ MIPSITUState *tag = (MIPSITUState *)opaque;
+ uint64_t *am = &tag->ITCAddressMap[0];
+ uint64_t am_old, mask;
+ uint64_t index = addr >> 3;
+
+ switch (index) {
+ case 0:
+ mask = ITC_AM0_BASE_ADDRESS_MASK | ITC_AM0_EN_MASK;
+ break;
+ case 1:
+ mask = ITC_AM1_ADDR_MASK_MASK | ITC_AM1_ENTRY_GRAIN_MASK;
+ break;
+ default:
+ qemu_log_mask(LOG_GUEST_ERROR, "Bad write 0x%" PRIx64 "\n", addr);
+ return;
+ }
+
+ am_old = am[index];
+ am[index] = (data & mask) | (am_old & ~mask);
+
+ /* Reconfigure ITC block */
+ if (am_old != am[index]) {
+ MemoryRegion *mr = &tag->storage_io;
+ hwaddr address = am[0] & ITC_AM0_BASE_ADDRESS_MASK;
+ uint64_t size = (1 << 10) + (am[1] & ITC_AM1_ADDR_MASK_MASK);
+ bool is_enabled = (am[0] & ITC_AM0_EN_MASK) != 0;
+
+ if (!(size & (size - 1))) {
+ memory_region_set_size(mr, size);
+ }
+ memory_region_set_address(mr, address);
+ memory_region_set_enabled(mr, is_enabled);
+ }
+}
+
+static const MemoryRegionOps itc_tag_ops = {
+ .read = itc_tag_read,
+ .write = itc_tag_write,
+ .impl = {
+ .max_access_size = 8,
+ },
+ .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static inline uint32_t get_num_cells(MIPSITUState *s)
+{
+ return s->num_fifo + s->num_semaphores;
+}
+
+static const MemoryRegionOps itc_storage_ops = {
+ .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void mips_itu_init(Object *obj)
+{
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+ MIPSITUState *s = MIPS_ITU(obj);
+
+ memory_region_init_io(&s->storage_io, OBJECT(s), &itc_storage_ops, s,
+ "mips-itc-storage", ITC_STORAGE_ADDRSPACE_SZ);
+ sysbus_init_mmio(sbd, &s->storage_io);
+
+ memory_region_init_io(&s->tag_io, OBJECT(s), &itc_tag_ops, s,
+ "mips-itc-tag", ITC_TAG_ADDRSPACE_SZ);
+
+}
+
+static void mips_itu_realize(DeviceState *dev, Error **errp)
+{
+ MIPSITUState *s = MIPS_ITU(dev);
+
+ if (s->num_fifo > ITC_FIFO_NUM_MAX) {
+ error_setg(errp, "Exceed maximum number of FIFO cells: %d",
+ s->num_fifo);
+ return;
+ }
+ if (s->num_semaphores > ITC_SEMAPH_NUM_MAX) {
+ error_setg(errp, "Exceed maximum number of Semaphore cells: %d",
+ s->num_semaphores);
+ return;
+ }
+
+ s->ITCAddressMap[0] = 0;
+
+ s->ITCAddressMap[1] =
+ ((ITC_STORAGE_ADDRSPACE_SZ - 1) & ITC_AM1_ADDR_MASK_MASK) |
+ (get_num_cells(s) << ITC_AM1_NUMENTRIES_OFS);
+
+ memory_region_set_enabled(&s->storage_io, false);
+}
+
+static Property mips_itu_properties[] = {
+ DEFINE_PROP_INT32("num-fifo", MIPSITUState, num_fifo,
+ ITC_FIFO_NUM_MAX),
+ DEFINE_PROP_INT32("num-semaphores", MIPSITUState, num_semaphores,
+ ITC_SEMAPH_NUM_MAX),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void mips_itu_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+
+ dc->props = mips_itu_properties;
+ dc->realize = mips_itu_realize;
+}
+
+static const TypeInfo mips_itu_info = {
+ .name = TYPE_MIPS_ITU,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(MIPSITUState),
+ .instance_init = mips_itu_init,
+ .class_init = mips_itu_class_init,
+};
+
+static void mips_itu_register_types(void)
+{
+ type_register_static(&mips_itu_info);
+}
+
+type_init(mips_itu_register_types)
diff --git a/include/hw/misc/mips_itu.h b/include/hw/misc/mips_itu.h
new file mode 100644
index 0000000..9ddd8b4
--- /dev/null
+++ b/include/hw/misc/mips_itu.h
@@ -0,0 +1,47 @@
+/*
+ * Inter-Thread Communication Unit emulation.
+ *
+ * Copyright (c) 2016 Imagination Technologies
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef MIPS_ITU_H
+#define MIPS_ITU_H
+
+#define TYPE_MIPS_ITU "mips-itu"
+#define MIPS_ITU(obj) OBJECT_CHECK(MIPSITUState, (obj), TYPE_MIPS_ITU)
+
+#define ITC_ADDRESSMAP_NUM 2
+
+typedef struct MIPSITUState {
+ /*< private >*/
+ SysBusDevice parent_obj;
+ /*< public >*/
+
+ int32_t num_fifo;
+ int32_t num_semaphores;
+
+ /* ITC Storage */
+ MemoryRegion storage_io;
+
+ /* ITC Configuration Tags */
+ uint64_t ITCAddressMap[ITC_ADDRESSMAP_NUM];
+ MemoryRegion tag_io;
+} MIPSITUState;
+
+/* Get ITC Configuration Tag memory region. */
+MemoryRegion *mips_itu_get_tag_region(MIPSITUState *itu);
+
+#endif /* MIPS_ITU_H */
diff --git a/target-mips/cpu.h b/target-mips/cpu.h
index ae8c575..d947eae 100644
--- a/target-mips/cpu.h
+++ b/target-mips/cpu.h
@@ -600,6 +600,7 @@ struct CPUMIPSState {
const mips_def_t *cpu_model;
void *irq[8];
QEMUTimer *timer; /* Internal timer */
+ MemoryRegion *itc_tag; /* ITC Configuration Tags */
};
#include "cpu-qom.h"
--
2.1.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [Qemu-devel] [PATCH 2/9] hw/mips: add ITC Storage Cells
2016-02-03 16:56 [Qemu-devel] [PATCH 0/9] mips: implement Inter-Thread Communication Unit Leon Alrae
2016-02-03 16:56 ` [Qemu-devel] [PATCH 1/9] hw/mips: implement ITC Configuration Tags Leon Alrae
@ 2016-02-03 16:56 ` Leon Alrae
2016-02-03 16:56 ` [Qemu-devel] [PATCH 3/9] hw/mips: implement ITC Storage - Control View Leon Alrae
` (6 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Leon Alrae @ 2016-02-03 16:56 UTC (permalink / raw)
To: qemu-devel; +Cc: aurelien
Define single structure for FIFO and Semaphore cells. Read-only FIFO bit
in the ITC cell tag indicates the type of the cell. If the ITC Storage
contains both types of cells then FIFOs are located before Semaphores.
Since issuing thread can get blocked on the access to a cell (in E/F
Synchronized and P/V Synchronized Views) each cell contains a bitmap
to track which threads are currently blocked.
Signed-off-by: Leon Alrae <leon.alrae@imgtec.com>
---
hw/misc/mips_itu.c | 17 +++++++++++++++++
include/hw/misc/mips_itu.h | 25 +++++++++++++++++++++++++
2 files changed, 42 insertions(+)
diff --git a/hw/misc/mips_itu.c b/hw/misc/mips_itu.c
index cf79bc6..d6f6905 100644
--- a/hw/misc/mips_itu.c
+++ b/hw/misc/mips_itu.c
@@ -116,6 +116,20 @@ static const MemoryRegionOps itc_storage_ops = {
.endianness = DEVICE_NATIVE_ENDIAN,
};
+static void itc_reset_cells(MIPSITUState *s)
+{
+ int i;
+ int num_cell = get_num_cells(s);
+
+ memset(s->cell, 0, num_cell * sizeof(s->cell[0]));
+
+ for (i = 0; i < s->num_fifo; i++) {
+ s->cell[i].tag.E = 1;
+ s->cell[i].tag.FIFO = 1;
+ s->cell[i].tag.FIFODepth = ITC_CELL_DEPTH_SHIFT;
+ }
+}
+
static void mips_itu_init(Object *obj)
{
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
@@ -151,6 +165,9 @@ static void mips_itu_realize(DeviceState *dev, Error **errp)
((ITC_STORAGE_ADDRSPACE_SZ - 1) & ITC_AM1_ADDR_MASK_MASK) |
(get_num_cells(s) << ITC_AM1_NUMENTRIES_OFS);
+ s->cell = g_new(ITCStorageCell, get_num_cells(s));
+ itc_reset_cells(s);
+
memory_region_set_enabled(&s->storage_io, false);
}
diff --git a/include/hw/misc/mips_itu.h b/include/hw/misc/mips_itu.h
index 9ddd8b4..b3a4532 100644
--- a/include/hw/misc/mips_itu.h
+++ b/include/hw/misc/mips_itu.h
@@ -23,6 +23,30 @@
#define TYPE_MIPS_ITU "mips-itu"
#define MIPS_ITU(obj) OBJECT_CHECK(MIPSITUState, (obj), TYPE_MIPS_ITU)
+#define ITC_CELL_DEPTH_SHIFT 2
+#define ITC_CELL_DEPTH (1u << ITC_CELL_DEPTH_SHIFT)
+
+typedef struct ITCStorageCell {
+ struct {
+ uint8_t FIFODepth; /* Log2 of the cell depth */
+ uint8_t FIFOPtr; /* Number of elements in a FIFO cell */
+ uint8_t FIFO; /* 1 - FIFO cell, 0 - Semaphore cell */
+ uint8_t T; /* Trap Bit */
+ uint8_t F; /* Full Bit */
+ uint8_t E; /* Empty Bit */
+ } tag;
+
+ /* Index of the oldest element in the queue */
+ uint8_t fifo_out;
+
+ /* Circular buffer for FIFO. Semaphore cells use index 0 only */
+ uint64_t data[ITC_CELL_DEPTH];
+
+ /* Bitmap tracking blocked threads on the cell.
+ TODO: support >64 threads ? */
+ uint64_t blocked_threads;
+} ITCStorageCell;
+
#define ITC_ADDRESSMAP_NUM 2
typedef struct MIPSITUState {
@@ -34,6 +58,7 @@ typedef struct MIPSITUState {
int32_t num_semaphores;
/* ITC Storage */
+ ITCStorageCell *cell;
MemoryRegion storage_io;
/* ITC Configuration Tags */
--
2.1.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [Qemu-devel] [PATCH 3/9] hw/mips: implement ITC Storage - Control View
2016-02-03 16:56 [Qemu-devel] [PATCH 0/9] mips: implement Inter-Thread Communication Unit Leon Alrae
2016-02-03 16:56 ` [Qemu-devel] [PATCH 1/9] hw/mips: implement ITC Configuration Tags Leon Alrae
2016-02-03 16:56 ` [Qemu-devel] [PATCH 2/9] hw/mips: add ITC Storage Cells Leon Alrae
@ 2016-02-03 16:56 ` Leon Alrae
2016-02-03 16:56 ` [Qemu-devel] [PATCH 4/9] hw/mips: implement ITC Storage - Empty/Full Sync and Try Views Leon Alrae
` (5 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Leon Alrae @ 2016-02-03 16:56 UTC (permalink / raw)
To: qemu-devel; +Cc: aurelien
Control view is used to access the ITC Storage Cell Tags. It never causes
the issuing thread to block.
Guest can empty the FIFO cell by setting Empty bit to 1.
Signed-off-by: Leon Alrae <leon.alrae@imgtec.com>
---
hw/misc/mips_itu.c | 104 +++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 104 insertions(+)
diff --git a/hw/misc/mips_itu.c b/hw/misc/mips_itu.c
index d6f6905..0864957 100644
--- a/hw/misc/mips_itu.c
+++ b/hw/misc/mips_itu.c
@@ -31,12 +31,28 @@
#define ITC_SEMAPH_NUM_MAX 16
#define ITC_AM1_NUMENTRIES_OFS 20
+#define ITC_CELL_TAG_FIFO_DEPTH 28
+#define ITC_CELL_TAG_FIFO_PTR 18
+#define ITC_CELL_TAG_FIFO 17
+#define ITC_CELL_TAG_T 16
+#define ITC_CELL_TAG_F 1
+#define ITC_CELL_TAG_E 0
+
#define ITC_AM0_BASE_ADDRESS_MASK 0xFFFFFC00ULL
#define ITC_AM0_EN_MASK 0x1
#define ITC_AM1_ADDR_MASK_MASK 0x1FC00
#define ITC_AM1_ENTRY_GRAIN_MASK 0x7
+typedef enum ITCView {
+ ITCVIEW_BYPASS = 0,
+ ITCVIEW_CONTROL = 1,
+ ITCVIEW_EF_SYNC = 2,
+ ITCVIEW_EF_TRY = 3,
+ ITCVIEW_PV_SYNC = 4,
+ ITCVIEW_PV_TRY = 5
+} ITCView;
+
MemoryRegion *mips_itu_get_tag_region(MIPSITUState *itu)
{
return &itu->tag_io;
@@ -112,7 +128,95 @@ static inline uint32_t get_num_cells(MIPSITUState *s)
return s->num_fifo + s->num_semaphores;
}
+static inline ITCView get_itc_view(hwaddr addr)
+{
+ return (addr >> 3) & 0xf;
+}
+
+static inline int get_cell_stride_shift(const MIPSITUState *s)
+{
+ /* Minimum interval (for EntryGain = 0) is 128 B */
+ return 7 + (s->ITCAddressMap[1] & ITC_AM1_ENTRY_GRAIN_MASK);
+}
+
+static inline ITCStorageCell *get_cell(MIPSITUState *s,
+ hwaddr addr)
+{
+ uint32_t cell_idx = addr >> get_cell_stride_shift(s);
+ uint32_t num_cells = get_num_cells(s);
+
+ if (cell_idx >= num_cells) {
+ cell_idx = num_cells - 1;
+ }
+
+ return &s->cell[cell_idx];
+}
+
+/* ITC Control View */
+
+static inline uint64_t view_control_read(ITCStorageCell *c)
+{
+ return ((uint64_t)c->tag.FIFODepth << ITC_CELL_TAG_FIFO_DEPTH) |
+ (c->tag.FIFOPtr << ITC_CELL_TAG_FIFO_PTR) |
+ (c->tag.FIFO << ITC_CELL_TAG_FIFO) |
+ (c->tag.T << ITC_CELL_TAG_T) |
+ (c->tag.E << ITC_CELL_TAG_E) |
+ (c->tag.F << ITC_CELL_TAG_F);
+}
+
+static inline void view_control_write(ITCStorageCell *c, uint64_t val)
+{
+ c->tag.T = (val >> ITC_CELL_TAG_T) & 1;
+ c->tag.E = (val >> ITC_CELL_TAG_E) & 1;
+ c->tag.F = (val >> ITC_CELL_TAG_F) & 1;
+
+ if (c->tag.E) {
+ c->tag.FIFOPtr = 0;
+ }
+}
+
+static uint64_t itc_storage_read(void *opaque, hwaddr addr, unsigned size)
+{
+ MIPSITUState *s = (MIPSITUState *)opaque;
+ ITCStorageCell *cell = get_cell(s, addr);
+ ITCView view = get_itc_view(addr);
+ uint64_t ret = -1;
+
+ switch (view) {
+ case ITCVIEW_CONTROL:
+ ret = view_control_read(cell);
+ break;
+ default:
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "itc_storage_read: Bad ITC View %d\n", (int)view);
+ break;
+ }
+
+ return ret;
+}
+
+static void itc_storage_write(void *opaque, hwaddr addr, uint64_t data,
+ unsigned size)
+{
+ MIPSITUState *s = (MIPSITUState *)opaque;
+ ITCStorageCell *cell = get_cell(s, addr);
+ ITCView view = get_itc_view(addr);
+
+ switch (view) {
+ case ITCVIEW_CONTROL:
+ view_control_write(cell, data);
+ break;
+ default:
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "itc_storage_write: Bad ITC View %d\n", (int)view);
+ break;
+ }
+
+}
+
static const MemoryRegionOps itc_storage_ops = {
+ .read = itc_storage_read,
+ .write = itc_storage_write,
.endianness = DEVICE_NATIVE_ENDIAN,
};
--
2.1.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [Qemu-devel] [PATCH 4/9] hw/mips: implement ITC Storage - Empty/Full Sync and Try Views
2016-02-03 16:56 [Qemu-devel] [PATCH 0/9] mips: implement Inter-Thread Communication Unit Leon Alrae
` (2 preceding siblings ...)
2016-02-03 16:56 ` [Qemu-devel] [PATCH 3/9] hw/mips: implement ITC Storage - Control View Leon Alrae
@ 2016-02-03 16:56 ` Leon Alrae
2016-02-03 16:56 ` [Qemu-devel] [PATCH 5/9] hw/mips: implement ITC Storage - P/V " Leon Alrae
` (4 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Leon Alrae @ 2016-02-03 16:56 UTC (permalink / raw)
To: qemu-devel; +Cc: aurelien
Empty/Full Synchronized and Try views can be used to access FIFO cells.
Store to the FIFO cell pushes the value into the queue, load pops the oldest
element from the queue. Cell's Full and Empty bits are automatically updated
to reflect new state of the cell.
Empty/Full Synchronized View causes the issuing thread to block when FIFO is
empty while thread is performing a read, or FIFO is full while thread is
performing a write.
Empty/Full Try View never blocks the thread. If cell is full then write is
ignored, if cell is empty then load returns 0.
Trap bit (i.e. Gating Storage exceptions) not implemented.
Store Conditional support for E/F Try View (i.e. indicate failure if FIFO
is full) not implemented.
Signed-off-by: Leon Alrae <leon.alrae@imgtec.com>
---
hw/misc/mips_itu.c | 113 +++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 113 insertions(+)
diff --git a/hw/misc/mips_itu.c b/hw/misc/mips_itu.c
index 0864957..9ef5619 100644
--- a/hw/misc/mips_itu.c
+++ b/hw/misc/mips_itu.c
@@ -152,6 +152,26 @@ static inline ITCStorageCell *get_cell(MIPSITUState *s,
return &s->cell[cell_idx];
}
+static void wake_blocked_threads(ITCStorageCell *c)
+{
+ CPUState *cs;
+ CPU_FOREACH(cs) {
+ if (cs->halted && (c->blocked_threads & (1ULL << cs->cpu_index))) {
+ cpu_interrupt(cs, CPU_INTERRUPT_WAKE);
+ }
+ }
+ c->blocked_threads = 0;
+}
+
+static void QEMU_NORETURN block_thread_and_exit(ITCStorageCell *c)
+{
+ c->blocked_threads |= 1ULL << current_cpu->cpu_index;
+ cpu_restore_state(current_cpu, current_cpu->mem_io_pc);
+ current_cpu->halted = 1;
+ current_cpu->exception_index = EXCP_HLT;
+ cpu_loop_exit(current_cpu);
+}
+
/* ITC Control View */
static inline uint64_t view_control_read(ITCStorageCell *c)
@@ -175,6 +195,87 @@ static inline void view_control_write(ITCStorageCell *c, uint64_t val)
}
}
+/* ITC Empty/Full View */
+
+static uint64_t view_ef_common_read(ITCStorageCell *c, bool blocking)
+{
+ uint64_t ret = 0;
+
+ if (!c->tag.FIFO) {
+ return 0;
+ }
+
+ c->tag.F = 0;
+
+ if (blocking && c->tag.E) {
+ block_thread_and_exit(c);
+ }
+
+ if (c->blocked_threads) {
+ wake_blocked_threads(c);
+ }
+
+ if (c->tag.FIFOPtr > 0) {
+ ret = c->data[c->fifo_out];
+ c->fifo_out = (c->fifo_out + 1) % ITC_CELL_DEPTH;
+ c->tag.FIFOPtr--;
+ }
+
+ if (c->tag.FIFOPtr == 0) {
+ c->tag.E = 1;
+ }
+
+ return ret;
+}
+
+static uint64_t view_ef_sync_read(ITCStorageCell *c)
+{
+ return view_ef_common_read(c, true);
+}
+
+static uint64_t view_ef_try_read(ITCStorageCell *c)
+{
+ return view_ef_common_read(c, false);
+}
+
+static inline void view_ef_common_write(ITCStorageCell *c, uint64_t val,
+ bool blocking)
+{
+ if (!c->tag.FIFO) {
+ return;
+ }
+
+ c->tag.E = 0;
+
+ if (blocking && c->tag.F) {
+ block_thread_and_exit(c);
+ }
+
+ if (c->blocked_threads) {
+ wake_blocked_threads(c);
+ }
+
+ if (c->tag.FIFOPtr < ITC_CELL_DEPTH) {
+ int idx = (c->fifo_out + c->tag.FIFOPtr) % ITC_CELL_DEPTH;
+ c->data[idx] = val;
+ c->tag.FIFOPtr++;
+ }
+
+ if (c->tag.FIFOPtr == ITC_CELL_DEPTH) {
+ c->tag.F = 1;
+ }
+}
+
+static void view_ef_sync_write(ITCStorageCell *c, uint64_t val)
+{
+ view_ef_common_write(c, val, true);
+}
+
+static void view_ef_try_write(ITCStorageCell *c, uint64_t val)
+{
+ view_ef_common_write(c, val, false);
+}
+
static uint64_t itc_storage_read(void *opaque, hwaddr addr, unsigned size)
{
MIPSITUState *s = (MIPSITUState *)opaque;
@@ -186,6 +287,12 @@ static uint64_t itc_storage_read(void *opaque, hwaddr addr, unsigned size)
case ITCVIEW_CONTROL:
ret = view_control_read(cell);
break;
+ case ITCVIEW_EF_SYNC:
+ ret = view_ef_sync_read(cell);
+ break;
+ case ITCVIEW_EF_TRY:
+ ret = view_ef_try_read(cell);
+ break;
default:
qemu_log_mask(LOG_GUEST_ERROR,
"itc_storage_read: Bad ITC View %d\n", (int)view);
@@ -206,6 +313,12 @@ static void itc_storage_write(void *opaque, hwaddr addr, uint64_t data,
case ITCVIEW_CONTROL:
view_control_write(cell, data);
break;
+ case ITCVIEW_EF_SYNC:
+ view_ef_sync_write(cell, data);
+ break;
+ case ITCVIEW_EF_TRY:
+ view_ef_try_write(cell, data);
+ break;
default:
qemu_log_mask(LOG_GUEST_ERROR,
"itc_storage_write: Bad ITC View %d\n", (int)view);
--
2.1.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [Qemu-devel] [PATCH 5/9] hw/mips: implement ITC Storage - P/V Sync and Try Views
2016-02-03 16:56 [Qemu-devel] [PATCH 0/9] mips: implement Inter-Thread Communication Unit Leon Alrae
` (3 preceding siblings ...)
2016-02-03 16:56 ` [Qemu-devel] [PATCH 4/9] hw/mips: implement ITC Storage - Empty/Full Sync and Try Views Leon Alrae
@ 2016-02-03 16:56 ` Leon Alrae
2016-02-03 16:56 ` [Qemu-devel] [PATCH 6/9] hw/mips: implement ITC Storage - Bypass View Leon Alrae
` (3 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Leon Alrae @ 2016-02-03 16:56 UTC (permalink / raw)
To: qemu-devel; +Cc: aurelien
P/V Synchronized and Try Views can be used to access Semaphore cells.
Load returns current value and post-decrements the value in the cell
(until it reaches zero). Stores increment the value (until it saturates
at 0xFFFF).
P/V Synchronized View causes the issuing thread to block on read if value
is 0. P/V Try View does not block the thread, it returns 0 in this case.
Cell's Empty and Full bits are not modified.
Trap bit (i.e. Gating Storage exceptions) not implemented.
Signed-off-by: Leon Alrae <leon.alrae@imgtec.com>
---
hw/misc/mips_itu.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 68 insertions(+)
diff --git a/hw/misc/mips_itu.c b/hw/misc/mips_itu.c
index 9ef5619..dd10b11 100644
--- a/hw/misc/mips_itu.c
+++ b/hw/misc/mips_itu.c
@@ -31,6 +31,8 @@
#define ITC_SEMAPH_NUM_MAX 16
#define ITC_AM1_NUMENTRIES_OFS 20
+#define ITC_CELL_PV_MAX_VAL 0xFFFF
+
#define ITC_CELL_TAG_FIFO_DEPTH 28
#define ITC_CELL_TAG_FIFO_PTR 18
#define ITC_CELL_TAG_FIFO 17
@@ -276,6 +278,60 @@ static void view_ef_try_write(ITCStorageCell *c, uint64_t val)
view_ef_common_write(c, val, false);
}
+/* ITC P/V View */
+
+static uint64_t view_pv_common_read(ITCStorageCell *c, bool blocking)
+{
+ uint64_t ret = c->data[0];
+
+ if (c->tag.FIFO) {
+ return 0;
+ }
+
+ if (c->data[0] > 0) {
+ c->data[0]--;
+ } else if (blocking) {
+ block_thread_and_exit(c);
+ }
+
+ return ret;
+}
+
+static uint64_t view_pv_sync_read(ITCStorageCell *c)
+{
+ return view_pv_common_read(c, true);
+}
+
+static uint64_t view_pv_try_read(ITCStorageCell *c)
+{
+ return view_pv_common_read(c, false);
+}
+
+static inline void view_pv_common_write(ITCStorageCell *c)
+{
+ if (c->tag.FIFO) {
+ return;
+ }
+
+ if (c->data[0] < ITC_CELL_PV_MAX_VAL) {
+ c->data[0]++;
+ }
+
+ if (c->blocked_threads) {
+ wake_blocked_threads(c);
+ }
+}
+
+static void view_pv_sync_write(ITCStorageCell *c)
+{
+ view_pv_common_write(c);
+}
+
+static void view_pv_try_write(ITCStorageCell *c)
+{
+ view_pv_common_write(c);
+}
+
static uint64_t itc_storage_read(void *opaque, hwaddr addr, unsigned size)
{
MIPSITUState *s = (MIPSITUState *)opaque;
@@ -293,6 +349,12 @@ static uint64_t itc_storage_read(void *opaque, hwaddr addr, unsigned size)
case ITCVIEW_EF_TRY:
ret = view_ef_try_read(cell);
break;
+ case ITCVIEW_PV_SYNC:
+ ret = view_pv_sync_read(cell);
+ break;
+ case ITCVIEW_PV_TRY:
+ ret = view_pv_try_read(cell);
+ break;
default:
qemu_log_mask(LOG_GUEST_ERROR,
"itc_storage_read: Bad ITC View %d\n", (int)view);
@@ -319,6 +381,12 @@ static void itc_storage_write(void *opaque, hwaddr addr, uint64_t data,
case ITCVIEW_EF_TRY:
view_ef_try_write(cell, data);
break;
+ case ITCVIEW_PV_SYNC:
+ view_pv_sync_write(cell);
+ break;
+ case ITCVIEW_PV_TRY:
+ view_pv_try_write(cell);
+ break;
default:
qemu_log_mask(LOG_GUEST_ERROR,
"itc_storage_write: Bad ITC View %d\n", (int)view);
--
2.1.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [Qemu-devel] [PATCH 6/9] hw/mips: implement ITC Storage - Bypass View
2016-02-03 16:56 [Qemu-devel] [PATCH 0/9] mips: implement Inter-Thread Communication Unit Leon Alrae
` (4 preceding siblings ...)
2016-02-03 16:56 ` [Qemu-devel] [PATCH 5/9] hw/mips: implement ITC Storage - P/V " Leon Alrae
@ 2016-02-03 16:56 ` Leon Alrae
2016-02-03 16:56 ` [Qemu-devel] [PATCH 7/9] hw/mips_malta: make ITU available to multi-threading processors Leon Alrae
` (2 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Leon Alrae @ 2016-02-03 16:56 UTC (permalink / raw)
To: qemu-devel; +Cc: aurelien
Bypass View does not cause issuing thread to block and does not affect
any of the cells state bit.
Read from a FIFO cell returns the value of the oldest entry.
Store to a FIFO cell changes the value of the newest entry.
Signed-off-by: Leon Alrae <leon.alrae@imgtec.com>
---
hw/misc/mips_itu.c | 27 +++++++++++++++++++++++++++
1 file changed, 27 insertions(+)
diff --git a/hw/misc/mips_itu.c b/hw/misc/mips_itu.c
index dd10b11..55241af 100644
--- a/hw/misc/mips_itu.c
+++ b/hw/misc/mips_itu.c
@@ -174,6 +174,27 @@ static void QEMU_NORETURN block_thread_and_exit(ITCStorageCell *c)
cpu_loop_exit(current_cpu);
}
+/* ITC Bypass View */
+
+static inline uint64_t view_bypass_read(ITCStorageCell *c)
+{
+ if (c->tag.FIFO) {
+ return c->data[c->fifo_out];
+ } else {
+ return c->data[0];
+ }
+}
+
+static inline void view_bypass_write(ITCStorageCell *c, uint64_t val)
+{
+ if (c->tag.FIFO && (c->tag.FIFOPtr > 0)) {
+ int idx = (c->fifo_out + c->tag.FIFOPtr - 1) % ITC_CELL_DEPTH;
+ c->data[idx] = val;
+ }
+
+ /* ignore a write to the semaphore cell */
+}
+
/* ITC Control View */
static inline uint64_t view_control_read(ITCStorageCell *c)
@@ -340,6 +361,9 @@ static uint64_t itc_storage_read(void *opaque, hwaddr addr, unsigned size)
uint64_t ret = -1;
switch (view) {
+ case ITCVIEW_BYPASS:
+ ret = view_bypass_read(cell);
+ break;
case ITCVIEW_CONTROL:
ret = view_control_read(cell);
break;
@@ -372,6 +396,9 @@ static void itc_storage_write(void *opaque, hwaddr addr, uint64_t data,
ITCView view = get_itc_view(addr);
switch (view) {
+ case ITCVIEW_BYPASS:
+ view_bypass_write(cell, data);
+ break;
case ITCVIEW_CONTROL:
view_control_write(cell, data);
break;
--
2.1.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [Qemu-devel] [PATCH 7/9] hw/mips_malta: make ITU available to multi-threading processors
2016-02-03 16:56 [Qemu-devel] [PATCH 0/9] mips: implement Inter-Thread Communication Unit Leon Alrae
` (5 preceding siblings ...)
2016-02-03 16:56 ` [Qemu-devel] [PATCH 6/9] hw/mips: implement ITC Storage - Bypass View Leon Alrae
@ 2016-02-03 16:56 ` Leon Alrae
2016-02-03 16:56 ` [Qemu-devel] [PATCH 8/9] target-mips: check CP0 enabled for CACHE instruction also in R6 Leon Alrae
2016-02-03 16:56 ` [Qemu-devel] [PATCH 9/9] target-mips: make ITC Configuration Tags accessible to the CPU Leon Alrae
8 siblings, 0 replies; 10+ messages in thread
From: Leon Alrae @ 2016-02-03 16:56 UTC (permalink / raw)
To: qemu-devel; +Cc: aurelien
Add ITU block to Malta board and make it available to multithreading
processors.
Signed-off-by: Leon Alrae <leon.alrae@imgtec.com>
---
hw/mips/mips_malta.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 53 insertions(+)
diff --git a/hw/mips/mips_malta.c b/hw/mips/mips_malta.c
index c5da83f..2c54a04 100644
--- a/hw/mips/mips_malta.c
+++ b/hw/mips/mips_malta.c
@@ -55,6 +55,7 @@
#include "hw/empty_slot.h"
#include "sysemu/kvm.h"
#include "exec/semihost.h"
+#include "hw/misc/mips_itu.h"
//#define DEBUG_BOARD_INIT
@@ -93,6 +94,7 @@ typedef struct {
typedef struct {
SysBusDevice parent_obj;
+ MIPSITUState itu;
qemu_irq *i8259;
} MaltaState;
@@ -567,6 +569,25 @@ static MaltaFPGAState *malta_fpga_init(MemoryRegion *address_space,
return s;
}
+static void itu_init(MaltaState *s, Error **err)
+{
+ SysBusDevice *itubusdev;
+
+ object_initialize(&s->itu, sizeof(s->itu), TYPE_MIPS_ITU);
+ qdev_set_parent_bus(DEVICE(&s->itu), sysbus_get_default());
+
+ object_property_set_int(OBJECT(&s->itu), 16, "num-fifo", err);
+ object_property_set_int(OBJECT(&s->itu), 16, "num-semaphores", err);
+ object_property_set_bool(OBJECT(&s->itu), true, "realized", err);
+
+ if (*err != NULL) {
+ return;
+ }
+
+ itubusdev = SYS_BUS_DEVICE(&s->itu);
+ sysbus_mmio_map_overlap(itubusdev, 0, 0, 1);
+}
+
/* Network support */
static void network_init(PCIBus *pci_bus)
{
@@ -882,6 +903,10 @@ static void malta_mips_config(MIPSCPU *cpu)
env->mvp->CP0_MVPConf0 |= ((smp_cpus - 1) << CP0MVPC0_PVPE) |
((smp_cpus * cs->nr_threads - 1) << CP0MVPC0_PTC);
+
+ if (env->itc_tag) {
+ env->mvp->CP0_MVPConf0 |= 1 << CP0MVPC0_GS;
+ }
}
static void main_cpu_reset(void *opaque)
@@ -906,6 +931,20 @@ static void main_cpu_reset(void *opaque)
}
}
+static bool cpu_mips_itu_supported(CPUMIPSState *env)
+{
+ bool is_mt = ((env->CP0_Config5 & (1 << CP0C5_VP)) != 0) ||
+ ((env->CP0_Config3 & (1 << CP0C3_MT)) != 0);
+
+ return is_mt && !kvm_enabled();
+
+}
+
+static void cpu_mips_attach_itc_tag(CPUMIPSState *env, MIPSITUState *itu)
+{
+ env->itc_tag = mips_itu_get_tag_region(itu);
+}
+
static
void mips_malta_init(MachineState *machine)
{
@@ -940,6 +979,7 @@ void mips_malta_init(MachineState *machine)
int fl_idx = 0;
int fl_sectors = bios_size >> 16;
int be;
+ bool itu_present = false;
DeviceState *dev = qdev_create(NULL, TYPE_MIPS_MALTA);
MaltaState *s = MIPS_MALTA(dev);
@@ -980,6 +1020,10 @@ void mips_malta_init(MachineState *machine)
/* Init internal devices */
cpu_mips_irq_init_cpu(env);
cpu_mips_clock_init(env);
+ if (cpu_mips_itu_supported(env)) {
+ itu_present = true;
+ cpu_mips_attach_itc_tag(env, &s->itu);
+ }
qemu_register_reset(main_cpu_reset, cpu);
}
cpu = MIPS_CPU(first_cpu);
@@ -1137,6 +1181,15 @@ void mips_malta_init(MachineState *machine)
cpu_mips_irq_init_cpu(env);
cpu_mips_clock_init(env);
+ if (itu_present) {
+ Error *err = NULL;
+ itu_init(s, &err);
+ if (err != NULL) {
+ error_report("%s", error_get_pretty(err));
+ exit(1);
+ }
+ }
+
/*
* We have a circular dependency problem: pci_bus depends on isa_irq,
* isa_irq is provided by i8259, i8259 depends on ISA, ISA depends
--
2.1.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [Qemu-devel] [PATCH 8/9] target-mips: check CP0 enabled for CACHE instruction also in R6
2016-02-03 16:56 [Qemu-devel] [PATCH 0/9] mips: implement Inter-Thread Communication Unit Leon Alrae
` (6 preceding siblings ...)
2016-02-03 16:56 ` [Qemu-devel] [PATCH 7/9] hw/mips_malta: make ITU available to multi-threading processors Leon Alrae
@ 2016-02-03 16:56 ` Leon Alrae
2016-02-03 16:56 ` [Qemu-devel] [PATCH 9/9] target-mips: make ITC Configuration Tags accessible to the CPU Leon Alrae
8 siblings, 0 replies; 10+ messages in thread
From: Leon Alrae @ 2016-02-03 16:56 UTC (permalink / raw)
To: qemu-devel; +Cc: aurelien
Signed-off-by: Leon Alrae <leon.alrae@imgtec.com>
---
target-mips/translate.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/target-mips/translate.c b/target-mips/translate.c
index c6e2951..3fb3744 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -17179,6 +17179,7 @@ static void decode_opc_special3_r6(CPUMIPSState *env, DisasContext *ctx)
/* Treat as NOP. */
break;
case R6_OPC_CACHE:
+ check_cp0_enabled(ctx);
/* Treat as NOP. */
break;
case R6_OPC_SC:
--
2.1.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [Qemu-devel] [PATCH 9/9] target-mips: make ITC Configuration Tags accessible to the CPU
2016-02-03 16:56 [Qemu-devel] [PATCH 0/9] mips: implement Inter-Thread Communication Unit Leon Alrae
` (7 preceding siblings ...)
2016-02-03 16:56 ` [Qemu-devel] [PATCH 8/9] target-mips: check CP0 enabled for CACHE instruction also in R6 Leon Alrae
@ 2016-02-03 16:56 ` Leon Alrae
8 siblings, 0 replies; 10+ messages in thread
From: Leon Alrae @ 2016-02-03 16:56 UTC (permalink / raw)
To: qemu-devel; +Cc: aurelien
Add CP0.ErrCtl register with WST, SPR and ITC bits. In 34K and interAptiv
processors these bits are used to enable CACHE instruction access to
different arrays. When WST=0, SPR=0 and ITC=1 the CACHE instruction will
access ITC tag values.
Generally we do not model caches and we have been treating the CACHE
instruction as NOP. But since CACHE can operate on ITC Tags new
MIPS_HFLAG_ITC_CACHE hflag is introduced to generate the helper only when
CACHE is in the ITC Access mode.
Signed-off-by: Leon Alrae <leon.alrae@imgtec.com>
---
target-mips/cpu.h | 7 +++++-
target-mips/helper.h | 3 +++
target-mips/op_helper.c | 40 ++++++++++++++++++++++++++++++-
target-mips/translate.c | 62 +++++++++++++++++++++++++++++++++++++++++--------
4 files changed, 100 insertions(+), 12 deletions(-)
diff --git a/target-mips/cpu.h b/target-mips/cpu.h
index d947eae..b4ca467 100644
--- a/target-mips/cpu.h
+++ b/target-mips/cpu.h
@@ -516,6 +516,10 @@ struct CPUMIPSState {
#define CP0DB_DSS 0
target_ulong CP0_DEPC;
int32_t CP0_Performance0;
+ int32_t CP0_ErrCtl;
+#define CP0EC_WST 29
+#define CP0EC_SPR 28
+#define CP0EC_ITC 26
uint64_t CP0_TagLo;
int32_t CP0_DataLo;
int32_t CP0_TagHi;
@@ -531,7 +535,7 @@ struct CPUMIPSState {
#define EXCP_INST_NOTAVAIL 0x2 /* No valid instruction word for BadInstr */
uint32_t hflags; /* CPU State */
/* TMASK defines different execution modes */
-#define MIPS_HFLAG_TMASK 0x75807FF
+#define MIPS_HFLAG_TMASK 0xF5807FF
#define MIPS_HFLAG_MODE 0x00007 /* execution modes */
/* The KSU flags must be the lowest bits in hflags. The flag order
must be the same as defined for CP0 Status. This allows to use
@@ -580,6 +584,7 @@ struct CPUMIPSState {
#define MIPS_HFLAG_MSA 0x1000000
#define MIPS_HFLAG_FRE 0x2000000 /* FRE enabled */
#define MIPS_HFLAG_ELPA 0x4000000
+#define MIPS_HFLAG_ITC_CACHE 0x8000000 /* CACHE instr. operates on ITC tag */
target_ulong btarget; /* Jump / branch target */
target_ulong bcond; /* Branch condition (if needed) */
diff --git a/target-mips/helper.h b/target-mips/helper.h
index 1bc8bb2..62fe20b 100644
--- a/target-mips/helper.h
+++ b/target-mips/helper.h
@@ -151,6 +151,7 @@ DEF_HELPER_2(mtc0_framemask, void, env, tl)
DEF_HELPER_2(mtc0_debug, void, env, tl)
DEF_HELPER_2(mttc0_debug, void, env, tl)
DEF_HELPER_2(mtc0_performance0, void, env, tl)
+DEF_HELPER_2(mtc0_errctl, void, env, tl)
DEF_HELPER_2(mtc0_taglo, void, env, tl)
DEF_HELPER_2(mtc0_datalo, void, env, tl)
DEF_HELPER_2(mtc0_taghi, void, env, tl)
@@ -949,3 +950,5 @@ MSALDST_PROTO(h)
MSALDST_PROTO(w)
MSALDST_PROTO(d)
#undef MSALDST_PROTO
+
+DEF_HELPER_3(cache, void, env, tl, i32)
diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c
index 7c5669c..dcd44c4 100644
--- a/target-mips/op_helper.c
+++ b/target-mips/op_helper.c
@@ -1632,9 +1632,31 @@ void helper_mtc0_performance0(CPUMIPSState *env, target_ulong arg1)
env->CP0_Performance0 = arg1 & 0x000007ff;
}
+void helper_mtc0_errctl(CPUMIPSState *env, target_ulong arg1)
+{
+ int32_t wst = arg1 & (1 << CP0EC_WST);
+ int32_t spr = arg1 & (1 << CP0EC_SPR);
+ int32_t itc = env->itc_tag ? (arg1 & (1 << CP0EC_ITC)) : 0;
+
+ env->CP0_ErrCtl = wst | spr | itc;
+
+ if (itc && !wst && !spr) {
+ env->hflags |= MIPS_HFLAG_ITC_CACHE;
+ } else {
+ env->hflags &= ~MIPS_HFLAG_ITC_CACHE;
+ }
+}
+
void helper_mtc0_taglo(CPUMIPSState *env, target_ulong arg1)
{
- env->CP0_TagLo = arg1 & 0xFFFFFCF6;
+ if (env->hflags & MIPS_HFLAG_ITC_CACHE) {
+ /* If CACHE instruction is configured for ITC tags then make all
+ CP0.TagLo bits writable. The actual write to ITC Configuration
+ Tag will take care of the read-only bits. */
+ env->CP0_TagLo = arg1;
+ } else {
+ env->CP0_TagLo = arg1 & 0xFFFFFCF6;
+ }
}
void helper_mtc0_datalo(CPUMIPSState *env, target_ulong arg1)
@@ -3781,3 +3803,19 @@ MSA_ST_DF(DF_HALF, h, cpu_stw_data)
MSA_ST_DF(DF_WORD, w, cpu_stl_data)
MSA_ST_DF(DF_DOUBLE, d, cpu_stq_data)
#endif
+
+void helper_cache(CPUMIPSState *env, target_ulong addr, uint32_t op)
+{
+#ifndef CONFIG_USER_ONLY
+ target_ulong index = addr & 0x1fffffff;
+ if (op == 9) {
+ /* Index Store Tag */
+ memory_region_dispatch_write(env->itc_tag, index, env->CP0_TagLo,
+ 8, MEMTXATTRS_UNSPECIFIED);
+ } else if (op == 5) {
+ /* Index Load Tag */
+ memory_region_dispatch_read(env->itc_tag, index, &env->CP0_TagLo,
+ 8, MEMTXATTRS_UNSPECIFIED);
+ }
+#endif
+}
diff --git a/target-mips/translate.c b/target-mips/translate.c
index 3fb3744..f7c8ef4 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -5477,8 +5477,14 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
}
break;
case 26:
- tcg_gen_movi_tl(arg, 0); /* unimplemented */
- rn = "ECC";
+ switch (sel) {
+ case 0:
+ gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl));
+ rn = "ErrCtl";
+ break;
+ default:
+ goto cp0_unimplemented;
+ }
break;
case 27:
switch (sel) {
@@ -6127,8 +6133,15 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
}
break;
case 26:
- /* ignored */
- rn = "ECC";
+ switch (sel) {
+ case 0:
+ gen_helper_mtc0_errctl(cpu_env, arg);
+ ctx->bstate = BS_STOP;
+ rn = "ErrCtl";
+ break;
+ default:
+ goto cp0_unimplemented;
+ }
break;
case 27:
switch (sel) {
@@ -6747,8 +6760,14 @@ static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
}
break;
case 26:
- tcg_gen_movi_tl(arg, 0); /* unimplemented */
- rn = "ECC";
+ switch (sel) {
+ case 0:
+ gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl));
+ rn = "ErrCtl";
+ break;
+ default:
+ goto cp0_unimplemented;
+ }
break;
case 27:
switch (sel) {
@@ -7389,8 +7408,15 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
}
break;
case 26:
- /* ignored */
- rn = "ECC";
+ switch (sel) {
+ case 0:
+ gen_helper_mtc0_errctl(cpu_env, arg);
+ ctx->bstate = BS_STOP;
+ rn = "ErrCtl";
+ break;
+ default:
+ goto cp0_unimplemented;
+ }
break;
case 27:
switch (sel) {
@@ -11175,6 +11201,15 @@ static void gen_addiupc (DisasContext *ctx, int rx, int imm,
tcg_temp_free(t0);
}
+static void gen_cache_operation(DisasContext *ctx, uint32_t op, int base,
+ int16_t offset)
+{
+ TCGv_i32 t0 = tcg_const_i32(op);
+ TCGv t1 = tcg_temp_new();
+ gen_base_offset_addr(ctx, t1, base, offset);
+ gen_helper_cache(cpu_env, t1, t0);
+}
+
#if defined(TARGET_MIPS64)
static void decode_i64_mips16 (DisasContext *ctx,
int ry, int funct, int16_t offset,
@@ -13726,7 +13761,9 @@ static void decode_micromips32_opc(CPUMIPSState *env, DisasContext *ctx)
switch (minor) {
case CACHE:
check_cp0_enabled(ctx);
- /* Treat as no-op. */
+ if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
+ gen_cache_operation(ctx, rt, rs, imm);
+ }
break;
case LWC2:
case SWC2:
@@ -17180,7 +17217,9 @@ static void decode_opc_special3_r6(CPUMIPSState *env, DisasContext *ctx)
break;
case R6_OPC_CACHE:
check_cp0_enabled(ctx);
- /* Treat as NOP. */
+ if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
+ gen_cache_operation(ctx, rt, rs, imm);
+ }
break;
case R6_OPC_SC:
gen_st_cond(ctx, op1, rt, rs, imm);
@@ -19289,6 +19328,9 @@ static void decode_opc(CPUMIPSState *env, DisasContext *ctx)
check_insn_opc_removed(ctx, ISA_MIPS32R6);
check_cp0_enabled(ctx);
check_insn(ctx, ISA_MIPS3 | ISA_MIPS32);
+ if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
+ gen_cache_operation(ctx, rt, rs, imm);
+ }
/* Treat as NOP. */
break;
case OPC_PREF:
--
2.1.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
end of thread, other threads:[~2016-02-03 16:57 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-02-03 16:56 [Qemu-devel] [PATCH 0/9] mips: implement Inter-Thread Communication Unit Leon Alrae
2016-02-03 16:56 ` [Qemu-devel] [PATCH 1/9] hw/mips: implement ITC Configuration Tags Leon Alrae
2016-02-03 16:56 ` [Qemu-devel] [PATCH 2/9] hw/mips: add ITC Storage Cells Leon Alrae
2016-02-03 16:56 ` [Qemu-devel] [PATCH 3/9] hw/mips: implement ITC Storage - Control View Leon Alrae
2016-02-03 16:56 ` [Qemu-devel] [PATCH 4/9] hw/mips: implement ITC Storage - Empty/Full Sync and Try Views Leon Alrae
2016-02-03 16:56 ` [Qemu-devel] [PATCH 5/9] hw/mips: implement ITC Storage - P/V " Leon Alrae
2016-02-03 16:56 ` [Qemu-devel] [PATCH 6/9] hw/mips: implement ITC Storage - Bypass View Leon Alrae
2016-02-03 16:56 ` [Qemu-devel] [PATCH 7/9] hw/mips_malta: make ITU available to multi-threading processors Leon Alrae
2016-02-03 16:56 ` [Qemu-devel] [PATCH 8/9] target-mips: check CP0 enabled for CACHE instruction also in R6 Leon Alrae
2016-02-03 16:56 ` [Qemu-devel] [PATCH 9/9] target-mips: make ITC Configuration Tags accessible to the CPU Leon Alrae
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).