* [Qemu-devel] [PATCH v5 00/15] demacro softmmu (plus tests/coverage)
@ 2019-04-30 16:52 ` Alex Bennée
0 siblings, 0 replies; 53+ messages in thread
From: Alex Bennée @ 2019-04-30 16:52 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm, mark.cave-ayland, cota, Alex Bennée
Hi,
This is the latest iteration of the softmmu demacro series. The main
changes from the last submission are some updates from Richard. Some
are merged into the main demacro patch (mostly casting cleanups) and
then a series of 3 patches to out of line some of the less hot code to
keep the main access functions a reasonable size. For example:
readelf -s aarch64-softmmu/accel/tcg/cputlb.o | ag helper |\
ag -v atomic | ag mmu | tr -s ' ' | cut -d ' ' -f 4,9 | sort -n
Before:
16 helper_be_ldsl_mmu
16 helper_le_ldsl_mmu
18 helper_be_ldsw_mmu
18 helper_le_ldsw_mmu
18 helper_ret_ldsb_mmu
535 helper_ret_ldub_mmu
556 helper_ret_ldb_cmmu
586 helper_ret_stb_mmu
679 helper_le_ldul_mmu
681 helper_be_ldul_mmu
685 helper_le_ldq_mmu
688 helper_be_ldq_mmu
688 helper_le_lduw_mmu
693 helper_le_ldl_cmmu
701 helper_le_ldq_cmmu
701 helper_le_ldw_cmmu
703 helper_be_ldl_cmmu
704 helper_be_ldq_cmmu
708 helper_be_lduw_mmu
713 helper_be_ldw_cmmu
943 helper_le_stw_mmu
944 helper_le_stl_mmu
952 helper_be_stl_mmu
952 helper_le_stq_mmu
959 helper_be_stw_mmu
960 helper_be_stq_mmu
After:
5 helper_be_ldul_mmu
5 helper_be_lduw_mmu
5 helper_le_ldul_mmu
5 helper_le_lduw_mmu
5 helper_ret_ldub_mmu
14 helper_be_ldl_cmmu
14 helper_be_ldw_cmmu
14 helper_le_ldl_cmmu
14 helper_le_ldw_cmmu
16 helper_be_ldsl_mmu
16 helper_le_ldsl_mmu
18 helper_be_ldsw_mmu
18 helper_le_ldsw_mmu
18 helper_ret_ldsb_mmu
783 helper_ret_stb_mmu
785 helper_ret_ldb_cmmu
881 helper_be_ldq_mmu
881 helper_le_ldq_mmu
889 helper_le_ldq_cmmu
897 helper_be_ldq_cmmu
1150 helper_be_stw_mmu
1150 helper_le_stw_mmu
1151 helper_be_stq_mmu
1151 helper_le_stl_mmu
1151 helper_le_stq_mmu
1159 helper_be_stl_mmu
I've also moved the existing system memory test and made it multiarch
and added the bootstrapping for aarch64 system tests. I would like to
add support for Big Endian as well but I didn't want to delay the
posting of the series. It would also be nice to exercise the
ioread/write paths and other handling but I leave this as an exercise
for later.
There are also some minor tweaks for the code coverage reports now I'm
running with out-of-tree builds.
Alex Bennée (11):
tests/tcg/multiarch: add support for multiarch system tests
tests/tcg/multiarch: add hello world system test
tests/tcg/aarch64: add system boot.S
tests/tcg/multiarch: move the system memory test
tests/tcg/minilib: support %c format char
tests/tcg/multiarch: expand system memory test to cover more
accel/tcg: demacro cputlb
accel/tcg: remove softmmu_template.h
Makefile: fix coverage-report reference to BUILD_DIR
Makefile: include per-target build directories in coverage report
Makefile.target: support per-target coverage reports
Richard Henderson (4):
cputlb: Move TLB_RECHECK handling into load/store_helper
cputlb: Drop attribute flatten
cputlb: Do unaligned load recursion to outermost function
cputlb: Do unaligned store recursion to outermost function
Makefile | 4 +-
Makefile.target | 16 +
accel/tcg/cputlb.c | 626 +++++++++++++++---
accel/tcg/softmmu_template.h | 454 -------------
tests/tcg/Makefile | 1 +
tests/tcg/aarch64/Makefile.softmmu-target | 32 +
tests/tcg/aarch64/system/boot.S | 200 ++++++
tests/tcg/aarch64/system/kernel.ld | 22 +
tests/tcg/i386/Makefile.softmmu-target | 2 +-
tests/tcg/i386/system/memory.c | 243 -------
tests/tcg/minilib/printf.c | 6 +-
.../multiarch/system/Makefile.softmmu-target | 14 +
tests/tcg/{i386 => multiarch}/system/hello.c | 0
tests/tcg/multiarch/system/memory.c | 427 ++++++++++++
14 files changed, 1267 insertions(+), 780 deletions(-)
delete mode 100644 accel/tcg/softmmu_template.h
create mode 100644 tests/tcg/aarch64/Makefile.softmmu-target
create mode 100644 tests/tcg/aarch64/system/boot.S
create mode 100644 tests/tcg/aarch64/system/kernel.ld
delete mode 100644 tests/tcg/i386/system/memory.c
create mode 100644 tests/tcg/multiarch/system/Makefile.softmmu-target
rename tests/tcg/{i386 => multiarch}/system/hello.c (100%)
create mode 100644 tests/tcg/multiarch/system/memory.c
--
2.20.1
^ permalink raw reply [flat|nested] 53+ messages in thread
* [Qemu-devel] [PATCH v5 00/15] demacro softmmu (plus tests/coverage)
@ 2019-04-30 16:52 ` Alex Bennée
0 siblings, 0 replies; 53+ messages in thread
From: Alex Bennée @ 2019-04-30 16:52 UTC (permalink / raw)
To: qemu-devel; +Cc: Alex Bennée, qemu-arm, mark.cave-ayland, cota
Hi,
This is the latest iteration of the softmmu demacro series. The main
changes from the last submission are some updates from Richard. Some
are merged into the main demacro patch (mostly casting cleanups) and
then a series of 3 patches to out of line some of the less hot code to
keep the main access functions a reasonable size. For example:
readelf -s aarch64-softmmu/accel/tcg/cputlb.o | ag helper |\
ag -v atomic | ag mmu | tr -s ' ' | cut -d ' ' -f 4,9 | sort -n
Before:
16 helper_be_ldsl_mmu
16 helper_le_ldsl_mmu
18 helper_be_ldsw_mmu
18 helper_le_ldsw_mmu
18 helper_ret_ldsb_mmu
535 helper_ret_ldub_mmu
556 helper_ret_ldb_cmmu
586 helper_ret_stb_mmu
679 helper_le_ldul_mmu
681 helper_be_ldul_mmu
685 helper_le_ldq_mmu
688 helper_be_ldq_mmu
688 helper_le_lduw_mmu
693 helper_le_ldl_cmmu
701 helper_le_ldq_cmmu
701 helper_le_ldw_cmmu
703 helper_be_ldl_cmmu
704 helper_be_ldq_cmmu
708 helper_be_lduw_mmu
713 helper_be_ldw_cmmu
943 helper_le_stw_mmu
944 helper_le_stl_mmu
952 helper_be_stl_mmu
952 helper_le_stq_mmu
959 helper_be_stw_mmu
960 helper_be_stq_mmu
After:
5 helper_be_ldul_mmu
5 helper_be_lduw_mmu
5 helper_le_ldul_mmu
5 helper_le_lduw_mmu
5 helper_ret_ldub_mmu
14 helper_be_ldl_cmmu
14 helper_be_ldw_cmmu
14 helper_le_ldl_cmmu
14 helper_le_ldw_cmmu
16 helper_be_ldsl_mmu
16 helper_le_ldsl_mmu
18 helper_be_ldsw_mmu
18 helper_le_ldsw_mmu
18 helper_ret_ldsb_mmu
783 helper_ret_stb_mmu
785 helper_ret_ldb_cmmu
881 helper_be_ldq_mmu
881 helper_le_ldq_mmu
889 helper_le_ldq_cmmu
897 helper_be_ldq_cmmu
1150 helper_be_stw_mmu
1150 helper_le_stw_mmu
1151 helper_be_stq_mmu
1151 helper_le_stl_mmu
1151 helper_le_stq_mmu
1159 helper_be_stl_mmu
I've also moved the existing system memory test and made it multiarch
and added the bootstrapping for aarch64 system tests. I would like to
add support for Big Endian as well but I didn't want to delay the
posting of the series. It would also be nice to exercise the
ioread/write paths and other handling but I leave this as an exercise
for later.
There are also some minor tweaks for the code coverage reports now I'm
running with out-of-tree builds.
Alex Bennée (11):
tests/tcg/multiarch: add support for multiarch system tests
tests/tcg/multiarch: add hello world system test
tests/tcg/aarch64: add system boot.S
tests/tcg/multiarch: move the system memory test
tests/tcg/minilib: support %c format char
tests/tcg/multiarch: expand system memory test to cover more
accel/tcg: demacro cputlb
accel/tcg: remove softmmu_template.h
Makefile: fix coverage-report reference to BUILD_DIR
Makefile: include per-target build directories in coverage report
Makefile.target: support per-target coverage reports
Richard Henderson (4):
cputlb: Move TLB_RECHECK handling into load/store_helper
cputlb: Drop attribute flatten
cputlb: Do unaligned load recursion to outermost function
cputlb: Do unaligned store recursion to outermost function
Makefile | 4 +-
Makefile.target | 16 +
accel/tcg/cputlb.c | 626 +++++++++++++++---
accel/tcg/softmmu_template.h | 454 -------------
tests/tcg/Makefile | 1 +
tests/tcg/aarch64/Makefile.softmmu-target | 32 +
tests/tcg/aarch64/system/boot.S | 200 ++++++
tests/tcg/aarch64/system/kernel.ld | 22 +
tests/tcg/i386/Makefile.softmmu-target | 2 +-
tests/tcg/i386/system/memory.c | 243 -------
tests/tcg/minilib/printf.c | 6 +-
.../multiarch/system/Makefile.softmmu-target | 14 +
tests/tcg/{i386 => multiarch}/system/hello.c | 0
tests/tcg/multiarch/system/memory.c | 427 ++++++++++++
14 files changed, 1267 insertions(+), 780 deletions(-)
delete mode 100644 accel/tcg/softmmu_template.h
create mode 100644 tests/tcg/aarch64/Makefile.softmmu-target
create mode 100644 tests/tcg/aarch64/system/boot.S
create mode 100644 tests/tcg/aarch64/system/kernel.ld
delete mode 100644 tests/tcg/i386/system/memory.c
create mode 100644 tests/tcg/multiarch/system/Makefile.softmmu-target
rename tests/tcg/{i386 => multiarch}/system/hello.c (100%)
create mode 100644 tests/tcg/multiarch/system/memory.c
--
2.20.1
^ permalink raw reply [flat|nested] 53+ messages in thread
* [Qemu-devel] [PATCH v5 01/15] tests/tcg/multiarch: add support for multiarch system tests
@ 2019-04-30 16:52 ` Alex Bennée
0 siblings, 0 replies; 53+ messages in thread
From: Alex Bennée @ 2019-04-30 16:52 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm, mark.cave-ayland, cota, Alex Bennée
We can certainly support some common tests for system emulation that
make use of our minimal defined boot.S support. It will still be up to
individual architectures to ensure they build so we provide a
MULTIARCH_TESTS variable that they can tack onto TESTS themselves.
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
---
tests/tcg/Makefile | 1 +
tests/tcg/multiarch/system/Makefile.softmmu-target | 14 ++++++++++++++
2 files changed, 15 insertions(+)
create mode 100644 tests/tcg/multiarch/system/Makefile.softmmu-target
diff --git a/tests/tcg/Makefile b/tests/tcg/Makefile
index 1cdd628e96..6fa63cc8d5 100644
--- a/tests/tcg/Makefile
+++ b/tests/tcg/Makefile
@@ -96,6 +96,7 @@ else
# build options for bare programs are usually pretty different. They
# are expected to provide their own build recipes.
-include $(SRC_PATH)/tests/tcg/minilib/Makefile.target
+-include $(SRC_PATH)/tests/tcg/multiarch/system/Makefile.softmmu-target
-include $(SRC_PATH)/tests/tcg/$(TARGET_BASE_ARCH)/Makefile.softmmu-target
ifneq ($(TARGET_BASE_ARCH),$(TARGET_NAME))
-include $(SRC_PATH)/tests/tcg/$(TARGET_NAME)/Makefile.softmmu-target
diff --git a/tests/tcg/multiarch/system/Makefile.softmmu-target b/tests/tcg/multiarch/system/Makefile.softmmu-target
new file mode 100644
index 0000000000..db4bbeda44
--- /dev/null
+++ b/tests/tcg/multiarch/system/Makefile.softmmu-target
@@ -0,0 +1,14 @@
+# -*- Mode: makefile -*-
+#
+# Multiarch system tests
+#
+# We just collect the tests together here and rely on the actual guest
+# architecture to add to the test dependancies and deal with the
+# complications of building.
+#
+
+MULTIARCH_SYSTEM_SRC=$(SRC_PATH)/tests/tcg/multiarch/system
+VPATH+=$(MULTIARCH_SYSTEM_SRC)
+
+MULTIARCH_TEST_SRCS=$(wildcard $(MULTIARCH_SYSTEM_SRC)/*.c)
+MULTIARCH_TESTS = $(patsubst $(MULTIARCH_SYSTEM_SRC)/%.c, %, $(MULTIARCH_TEST_SRCS))
--
2.20.1
^ permalink raw reply related [flat|nested] 53+ messages in thread
* [Qemu-devel] [PATCH v5 01/15] tests/tcg/multiarch: add support for multiarch system tests
@ 2019-04-30 16:52 ` Alex Bennée
0 siblings, 0 replies; 53+ messages in thread
From: Alex Bennée @ 2019-04-30 16:52 UTC (permalink / raw)
To: qemu-devel; +Cc: Alex Bennée, qemu-arm, mark.cave-ayland, cota
We can certainly support some common tests for system emulation that
make use of our minimal defined boot.S support. It will still be up to
individual architectures to ensure they build so we provide a
MULTIARCH_TESTS variable that they can tack onto TESTS themselves.
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
---
tests/tcg/Makefile | 1 +
tests/tcg/multiarch/system/Makefile.softmmu-target | 14 ++++++++++++++
2 files changed, 15 insertions(+)
create mode 100644 tests/tcg/multiarch/system/Makefile.softmmu-target
diff --git a/tests/tcg/Makefile b/tests/tcg/Makefile
index 1cdd628e96..6fa63cc8d5 100644
--- a/tests/tcg/Makefile
+++ b/tests/tcg/Makefile
@@ -96,6 +96,7 @@ else
# build options for bare programs are usually pretty different. They
# are expected to provide their own build recipes.
-include $(SRC_PATH)/tests/tcg/minilib/Makefile.target
+-include $(SRC_PATH)/tests/tcg/multiarch/system/Makefile.softmmu-target
-include $(SRC_PATH)/tests/tcg/$(TARGET_BASE_ARCH)/Makefile.softmmu-target
ifneq ($(TARGET_BASE_ARCH),$(TARGET_NAME))
-include $(SRC_PATH)/tests/tcg/$(TARGET_NAME)/Makefile.softmmu-target
diff --git a/tests/tcg/multiarch/system/Makefile.softmmu-target b/tests/tcg/multiarch/system/Makefile.softmmu-target
new file mode 100644
index 0000000000..db4bbeda44
--- /dev/null
+++ b/tests/tcg/multiarch/system/Makefile.softmmu-target
@@ -0,0 +1,14 @@
+# -*- Mode: makefile -*-
+#
+# Multiarch system tests
+#
+# We just collect the tests together here and rely on the actual guest
+# architecture to add to the test dependancies and deal with the
+# complications of building.
+#
+
+MULTIARCH_SYSTEM_SRC=$(SRC_PATH)/tests/tcg/multiarch/system
+VPATH+=$(MULTIARCH_SYSTEM_SRC)
+
+MULTIARCH_TEST_SRCS=$(wildcard $(MULTIARCH_SYSTEM_SRC)/*.c)
+MULTIARCH_TESTS = $(patsubst $(MULTIARCH_SYSTEM_SRC)/%.c, %, $(MULTIARCH_TEST_SRCS))
--
2.20.1
^ permalink raw reply related [flat|nested] 53+ messages in thread
* [Qemu-devel] [PATCH v5 02/15] tests/tcg/multiarch: add hello world system test
@ 2019-04-30 16:52 ` Alex Bennée
0 siblings, 0 replies; 53+ messages in thread
From: Alex Bennée @ 2019-04-30 16:52 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm, mark.cave-ayland, cota, Alex Bennée
This is not really i386 only, we can have the same test for all
architectures supporting system tests.
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
---
tests/tcg/i386/Makefile.softmmu-target | 2 +-
tests/tcg/{i386 => multiarch}/system/hello.c | 0
2 files changed, 1 insertion(+), 1 deletion(-)
rename tests/tcg/{i386 => multiarch}/system/hello.c (100%)
diff --git a/tests/tcg/i386/Makefile.softmmu-target b/tests/tcg/i386/Makefile.softmmu-target
index 53c9c5ece0..c31bbbf39a 100644
--- a/tests/tcg/i386/Makefile.softmmu-target
+++ b/tests/tcg/i386/Makefile.softmmu-target
@@ -27,7 +27,7 @@ CFLAGS+=-m32
LINK_SCRIPT=$(I386_SYSTEM_SRC)/kernel.ld
LDFLAGS=-Wl,-T$(LINK_SCRIPT) -Wl,-melf_i386
# FIXME: move to common once x86_64 is bootstrapped
-TESTS+=$(X86_TESTS)
+TESTS+=$(X86_TESTS) $(MULTIARCH_TESTS)
endif
CFLAGS+=-nostdlib -ggdb -O0 $(MINILIB_INC)
LDFLAGS+=-static -nostdlib $(CRT_OBJS) $(MINILIB_OBJS) -lgcc
diff --git a/tests/tcg/i386/system/hello.c b/tests/tcg/multiarch/system/hello.c
similarity index 100%
rename from tests/tcg/i386/system/hello.c
rename to tests/tcg/multiarch/system/hello.c
--
2.20.1
^ permalink raw reply related [flat|nested] 53+ messages in thread
* [Qemu-devel] [PATCH v5 02/15] tests/tcg/multiarch: add hello world system test
@ 2019-04-30 16:52 ` Alex Bennée
0 siblings, 0 replies; 53+ messages in thread
From: Alex Bennée @ 2019-04-30 16:52 UTC (permalink / raw)
To: qemu-devel; +Cc: Alex Bennée, qemu-arm, mark.cave-ayland, cota
This is not really i386 only, we can have the same test for all
architectures supporting system tests.
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
---
tests/tcg/i386/Makefile.softmmu-target | 2 +-
tests/tcg/{i386 => multiarch}/system/hello.c | 0
2 files changed, 1 insertion(+), 1 deletion(-)
rename tests/tcg/{i386 => multiarch}/system/hello.c (100%)
diff --git a/tests/tcg/i386/Makefile.softmmu-target b/tests/tcg/i386/Makefile.softmmu-target
index 53c9c5ece0..c31bbbf39a 100644
--- a/tests/tcg/i386/Makefile.softmmu-target
+++ b/tests/tcg/i386/Makefile.softmmu-target
@@ -27,7 +27,7 @@ CFLAGS+=-m32
LINK_SCRIPT=$(I386_SYSTEM_SRC)/kernel.ld
LDFLAGS=-Wl,-T$(LINK_SCRIPT) -Wl,-melf_i386
# FIXME: move to common once x86_64 is bootstrapped
-TESTS+=$(X86_TESTS)
+TESTS+=$(X86_TESTS) $(MULTIARCH_TESTS)
endif
CFLAGS+=-nostdlib -ggdb -O0 $(MINILIB_INC)
LDFLAGS+=-static -nostdlib $(CRT_OBJS) $(MINILIB_OBJS) -lgcc
diff --git a/tests/tcg/i386/system/hello.c b/tests/tcg/multiarch/system/hello.c
similarity index 100%
rename from tests/tcg/i386/system/hello.c
rename to tests/tcg/multiarch/system/hello.c
--
2.20.1
^ permalink raw reply related [flat|nested] 53+ messages in thread
* [Qemu-devel] [PATCH v5 03/15] tests/tcg/aarch64: add system boot.S
@ 2019-04-30 16:52 ` Alex Bennée
0 siblings, 0 replies; 53+ messages in thread
From: Alex Bennée @ 2019-04-30 16:52 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm, mark.cave-ayland, cota, Alex Bennée
This provides the bootstrap and low level helper functions for an
aarch64 kernel. We use semihosting to handle test output and exiting
the emulation. semihosting's parameter passing is a little funky so we
end up using the stack and pointing to that as the parameter block.
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
---
tests/tcg/aarch64/Makefile.softmmu-target | 32 ++++
tests/tcg/aarch64/system/boot.S | 200 ++++++++++++++++++++++
tests/tcg/aarch64/system/kernel.ld | 22 +++
3 files changed, 254 insertions(+)
create mode 100644 tests/tcg/aarch64/Makefile.softmmu-target
create mode 100644 tests/tcg/aarch64/system/boot.S
create mode 100644 tests/tcg/aarch64/system/kernel.ld
diff --git a/tests/tcg/aarch64/Makefile.softmmu-target b/tests/tcg/aarch64/Makefile.softmmu-target
new file mode 100644
index 0000000000..e6aee856c8
--- /dev/null
+++ b/tests/tcg/aarch64/Makefile.softmmu-target
@@ -0,0 +1,32 @@
+#
+# Aarch64 system tests
+#
+
+AARCH64_SYSTEM_SRC=$(SRC_PATH)/tests/tcg/aarch64/system
+VPATH+=$(AARCH64_SYSTEM_SRC)
+
+# These objects provide the basic boot code and helper functions for all tests
+CRT_OBJS=boot.o
+
+AARCH64_TEST_SRCS=$(wildcard $(AARCH64_SYSTEM_SRC)/*.c)
+AARCH64_TESTS = $(patsubst $(AARCH64_SYSTEM_SRC)/%.c, %, $(AARCH64_TEST_SRCS))
+
+CRT_PATH=$(AARCH64_SYSTEM_SRC)
+LINK_SCRIPT=$(AARCH64_SYSTEM_SRC)/kernel.ld
+LDFLAGS=-Wl,-T$(LINK_SCRIPT)
+TESTS+=$(AARCH64_TESTS) $(MULTIARCH_TESTS)
+CFLAGS+=-nostdlib -ggdb -O0 $(MINILIB_INC)
+LDFLAGS+=-static -nostdlib $(CRT_OBJS) $(MINILIB_OBJS) -lgcc
+
+# building head blobs
+.PRECIOUS: $(CRT_OBJS)
+
+%.o: $(CRT_PATH)/%.S
+ $(CC) $(CFLAGS) -x assembler-with-cpp -c $< -o $@
+
+# Build and link the tests
+%: %.c $(LINK_SCRIPT) $(CRT_OBJS) $(MINILIB_OBJS)
+ $(CC) $(CFLAGS) $< -o $@ $(LDFLAGS)
+
+# Running
+QEMU_OPTS+=-M virt -cpu max -display none -semihosting -kernel
diff --git a/tests/tcg/aarch64/system/boot.S b/tests/tcg/aarch64/system/boot.S
new file mode 100644
index 0000000000..03d319e07f
--- /dev/null
+++ b/tests/tcg/aarch64/system/boot.S
@@ -0,0 +1,200 @@
+/*
+ * Minimal AArch64 system boot code.
+ *
+ * Copyright Linaro Ltd 2019
+ *
+ * Loosely based on the newlib/libgloss setup stubs. Using semihosting
+ * for serial output and exit functions.
+ */
+
+/*
+ * Semihosting interface on ARM AArch64
+ * See "Semihosting for AArch32 and AArch64 Relase 2.0" by ARM
+ * w0 - semihosting call number
+ * x1 - semihosting parameter
+ */
+#define semihosting_call hlt 0xf000
+#define SYS_WRITEC 0x03 /* character to debug channel */
+#define SYS_WRITE0 0x04 /* string to debug channel */
+#define SYS_EXIT 0x18
+
+ .align 12
+
+ .macro ventry label
+ .align 7
+ b \label
+ .endm
+
+vector_table:
+ /* Current EL with SP0. */
+ ventry curr_sp0_sync /* Synchronous */
+ ventry curr_sp0_irq /* Irq/vIRQ */
+ ventry curr_sp0_fiq /* Fiq/vFIQ */
+ ventry curr_sp0_serror /* SError/VSError */
+
+ /* Current EL with SPx. */
+ ventry curr_spx_sync /* Synchronous */
+ ventry curr_spx_irq /* IRQ/vIRQ */
+ ventry curr_spx_fiq /* FIQ/vFIQ */
+ ventry curr_spx_serror /* SError/VSError */
+
+ /* Lower EL using AArch64. */
+ ventry lower_a64_sync /* Synchronous */
+ ventry lower_a64_irq /* IRQ/vIRQ */
+ ventry lower_a64_fiq /* FIQ/vFIQ */
+ ventry lower_a64_serror /* SError/VSError */
+
+ /* Lower EL using AArch32. */
+ ventry lower_a32_sync /* Synchronous */
+ ventry lower_a32_irq /* IRQ/vIRQ */
+ ventry lower_a32_fiq /* FIQ/vFIQ */
+ ventry lower_a32_serror /* SError/VSError */
+
+ .text
+ .align 4
+
+ /* Common vector handling for now */
+curr_sp0_sync:
+curr_sp0_irq:
+curr_sp0_fiq:
+curr_sp0_serror:
+curr_spx_sync:
+curr_spx_irq:
+curr_spx_fiq:
+curr_spx_serror:
+lower_a64_sync:
+lower_a64_irq:
+lower_a64_fiq:
+lower_a64_serror:
+lower_a32_sync:
+lower_a32_irq:
+lower_a32_fiq:
+lower_a32_serror:
+ mov x0, SYS_WRITE0
+ adr x1, .error
+ semihosting_call
+ mov x0, SYS_EXIT
+ mov x1, 1
+ semihosting_call
+ /* never returns */
+
+.error:
+ .string "Terminated by exception.\n"
+
+ .align 4
+ .global __start
+__start:
+ /* Installs a table of exception vectors to catch and handle all
+ exceptions by terminating the process with a diagnostic. */
+ adr x0, vector_table
+ msr vbar_el1, x0
+
+ /* Page table setup (identity mapping). */
+ adrp x0, ttb
+ add x0, x0, :lo12:ttb
+ msr ttbr0_el1, x0
+
+ /* Create some (big) pages */
+ adr x1, . /* phys address */
+ bic x1, x1, #(1 << 30) - 1 /* 1GB block alignment */
+
+ add x2, x0, x1, lsr #(30 - 3) /* page offset in l1 page table */
+
+ mov x3, #0x401 /* page table attributes (AF, block) */
+ orr x1, x1, x3
+
+ str x1, [x2], #8 /* 1st GB */
+
+ mov x3, #(1 << 30) /* 1GB block */
+ add x1, x1, x3
+
+ str x1, [x2] /* 2nd GB */
+
+ /* Setup/enable the MMU. */
+
+ /*
+ * TCR_EL1 - Translation Control Registers
+ *
+ * IPS[34:32] = 40-bit PA, 1TB
+ * ORGN0[11:10] = Outer: Normal, Outer Write-Back Read-Allocate No Write-Allocate Cacheable
+ * IRGN0[9:8] = Inner: Normal, Inner Write-Back Read-Allocate No Write-Allocate Cacheable.
+ * T0SZ[5:0] = 2^(64 - 25)
+ */
+ ldr x0, = (2 << 32) | 25 | (3 << 10) | (3 << 8)
+ msr tcr_el1, x0
+
+ mov x0, #0xee /* Inner/outer cacheable WB */
+ msr mair_el1, x0
+ isb
+
+ /*
+ * SCTLR_EL1 - System Control Register
+ *
+ * WXN[19] = 0 = no effect, Write does not imply XN (execute never)
+ * I[12] = Instruction cachability control
+ * SA[3] = SP alignment check
+ * C[2] = Data cachability control
+ * M[0] = 1, enable stage 1 address translation for EL0/1
+ */
+ mrs x0, sctlr_el1
+ ldr x1, =0x100d /* bits I(12) SA(3) C(2) M(0) */
+ bic x0, x0, #(1 << 1) /* clear bit A(1) */
+ bic x0, x0, #(1 << 19) /* clear WXN */
+ orr x0, x0, x1 /* set bits */
+
+ dsb sy
+ msr sctlr_el1, x0
+ isb
+
+ /*
+ * Enable FP registers. The standard C pre-amble will be
+ * saving these and A-profile compilers will use AdvSIMD
+ * registers unless we tell it not to.
+ */
+ mrs x0, cpacr_el1
+ orr x0, x0, #(3 << 20)
+ msr cpacr_el1, x0
+
+ /* Setup some stack space and enter the test code.
+ * Assume everthing except the return value is garbage when we
+ * return, we won't need it.
+ */
+ adrp x0, stack
+ add x0, x0, :lo12:stack
+
+ mov sp, x0
+ bl main
+
+ /* pass return value to sys exit */
+ mov x1, x0
+ ldr x0, =0x20026 /* ADP_Stopped_ApplicationExit */
+ stp x0, x1, [sp, #-16]!
+ mov x1, sp
+ mov x0, SYS_EXIT
+ semihosting_call
+ /* never returns */
+
+ /*
+ * Helper Functions
+ */
+
+ /* Output a single character to serial port */
+ .global __sys_outc
+__sys_outc:
+ stp x0, x1, [sp, #-16]!
+ /* pass address of c on stack */
+ mov x1, sp
+ mov x0, SYS_WRITEC
+ semihosting_call
+ ldp x0, x1, [sp], #16
+ ret
+
+ .data
+ .align 12
+ttb:
+ .space 4096, 0
+
+ .align 12
+stack:
+ .space 65536, 0
+stack_end:
diff --git a/tests/tcg/aarch64/system/kernel.ld b/tests/tcg/aarch64/system/kernel.ld
new file mode 100644
index 0000000000..73d75cae64
--- /dev/null
+++ b/tests/tcg/aarch64/system/kernel.ld
@@ -0,0 +1,22 @@
+ENTRY(__start)
+
+SECTIONS
+{
+ /* virt machine, RAM starts at 1gb */
+ . = (1 << 30);
+ .text : {
+ *(.text)
+ }
+ .data : {
+ *(.data)
+ }
+ .rodata : {
+ *(.rodata)
+ }
+ .bss : {
+ *(.bss)
+ }
+ /DISCARD/ : {
+ *(.ARM.attributes)
+ }
+}
--
2.20.1
^ permalink raw reply related [flat|nested] 53+ messages in thread
* [Qemu-devel] [PATCH v5 03/15] tests/tcg/aarch64: add system boot.S
@ 2019-04-30 16:52 ` Alex Bennée
0 siblings, 0 replies; 53+ messages in thread
From: Alex Bennée @ 2019-04-30 16:52 UTC (permalink / raw)
To: qemu-devel; +Cc: Alex Bennée, qemu-arm, mark.cave-ayland, cota
This provides the bootstrap and low level helper functions for an
aarch64 kernel. We use semihosting to handle test output and exiting
the emulation. semihosting's parameter passing is a little funky so we
end up using the stack and pointing to that as the parameter block.
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
---
tests/tcg/aarch64/Makefile.softmmu-target | 32 ++++
tests/tcg/aarch64/system/boot.S | 200 ++++++++++++++++++++++
tests/tcg/aarch64/system/kernel.ld | 22 +++
3 files changed, 254 insertions(+)
create mode 100644 tests/tcg/aarch64/Makefile.softmmu-target
create mode 100644 tests/tcg/aarch64/system/boot.S
create mode 100644 tests/tcg/aarch64/system/kernel.ld
diff --git a/tests/tcg/aarch64/Makefile.softmmu-target b/tests/tcg/aarch64/Makefile.softmmu-target
new file mode 100644
index 0000000000..e6aee856c8
--- /dev/null
+++ b/tests/tcg/aarch64/Makefile.softmmu-target
@@ -0,0 +1,32 @@
+#
+# Aarch64 system tests
+#
+
+AARCH64_SYSTEM_SRC=$(SRC_PATH)/tests/tcg/aarch64/system
+VPATH+=$(AARCH64_SYSTEM_SRC)
+
+# These objects provide the basic boot code and helper functions for all tests
+CRT_OBJS=boot.o
+
+AARCH64_TEST_SRCS=$(wildcard $(AARCH64_SYSTEM_SRC)/*.c)
+AARCH64_TESTS = $(patsubst $(AARCH64_SYSTEM_SRC)/%.c, %, $(AARCH64_TEST_SRCS))
+
+CRT_PATH=$(AARCH64_SYSTEM_SRC)
+LINK_SCRIPT=$(AARCH64_SYSTEM_SRC)/kernel.ld
+LDFLAGS=-Wl,-T$(LINK_SCRIPT)
+TESTS+=$(AARCH64_TESTS) $(MULTIARCH_TESTS)
+CFLAGS+=-nostdlib -ggdb -O0 $(MINILIB_INC)
+LDFLAGS+=-static -nostdlib $(CRT_OBJS) $(MINILIB_OBJS) -lgcc
+
+# building head blobs
+.PRECIOUS: $(CRT_OBJS)
+
+%.o: $(CRT_PATH)/%.S
+ $(CC) $(CFLAGS) -x assembler-with-cpp -c $< -o $@
+
+# Build and link the tests
+%: %.c $(LINK_SCRIPT) $(CRT_OBJS) $(MINILIB_OBJS)
+ $(CC) $(CFLAGS) $< -o $@ $(LDFLAGS)
+
+# Running
+QEMU_OPTS+=-M virt -cpu max -display none -semihosting -kernel
diff --git a/tests/tcg/aarch64/system/boot.S b/tests/tcg/aarch64/system/boot.S
new file mode 100644
index 0000000000..03d319e07f
--- /dev/null
+++ b/tests/tcg/aarch64/system/boot.S
@@ -0,0 +1,200 @@
+/*
+ * Minimal AArch64 system boot code.
+ *
+ * Copyright Linaro Ltd 2019
+ *
+ * Loosely based on the newlib/libgloss setup stubs. Using semihosting
+ * for serial output and exit functions.
+ */
+
+/*
+ * Semihosting interface on ARM AArch64
+ * See "Semihosting for AArch32 and AArch64 Relase 2.0" by ARM
+ * w0 - semihosting call number
+ * x1 - semihosting parameter
+ */
+#define semihosting_call hlt 0xf000
+#define SYS_WRITEC 0x03 /* character to debug channel */
+#define SYS_WRITE0 0x04 /* string to debug channel */
+#define SYS_EXIT 0x18
+
+ .align 12
+
+ .macro ventry label
+ .align 7
+ b \label
+ .endm
+
+vector_table:
+ /* Current EL with SP0. */
+ ventry curr_sp0_sync /* Synchronous */
+ ventry curr_sp0_irq /* Irq/vIRQ */
+ ventry curr_sp0_fiq /* Fiq/vFIQ */
+ ventry curr_sp0_serror /* SError/VSError */
+
+ /* Current EL with SPx. */
+ ventry curr_spx_sync /* Synchronous */
+ ventry curr_spx_irq /* IRQ/vIRQ */
+ ventry curr_spx_fiq /* FIQ/vFIQ */
+ ventry curr_spx_serror /* SError/VSError */
+
+ /* Lower EL using AArch64. */
+ ventry lower_a64_sync /* Synchronous */
+ ventry lower_a64_irq /* IRQ/vIRQ */
+ ventry lower_a64_fiq /* FIQ/vFIQ */
+ ventry lower_a64_serror /* SError/VSError */
+
+ /* Lower EL using AArch32. */
+ ventry lower_a32_sync /* Synchronous */
+ ventry lower_a32_irq /* IRQ/vIRQ */
+ ventry lower_a32_fiq /* FIQ/vFIQ */
+ ventry lower_a32_serror /* SError/VSError */
+
+ .text
+ .align 4
+
+ /* Common vector handling for now */
+curr_sp0_sync:
+curr_sp0_irq:
+curr_sp0_fiq:
+curr_sp0_serror:
+curr_spx_sync:
+curr_spx_irq:
+curr_spx_fiq:
+curr_spx_serror:
+lower_a64_sync:
+lower_a64_irq:
+lower_a64_fiq:
+lower_a64_serror:
+lower_a32_sync:
+lower_a32_irq:
+lower_a32_fiq:
+lower_a32_serror:
+ mov x0, SYS_WRITE0
+ adr x1, .error
+ semihosting_call
+ mov x0, SYS_EXIT
+ mov x1, 1
+ semihosting_call
+ /* never returns */
+
+.error:
+ .string "Terminated by exception.\n"
+
+ .align 4
+ .global __start
+__start:
+ /* Installs a table of exception vectors to catch and handle all
+ exceptions by terminating the process with a diagnostic. */
+ adr x0, vector_table
+ msr vbar_el1, x0
+
+ /* Page table setup (identity mapping). */
+ adrp x0, ttb
+ add x0, x0, :lo12:ttb
+ msr ttbr0_el1, x0
+
+ /* Create some (big) pages */
+ adr x1, . /* phys address */
+ bic x1, x1, #(1 << 30) - 1 /* 1GB block alignment */
+
+ add x2, x0, x1, lsr #(30 - 3) /* page offset in l1 page table */
+
+ mov x3, #0x401 /* page table attributes (AF, block) */
+ orr x1, x1, x3
+
+ str x1, [x2], #8 /* 1st GB */
+
+ mov x3, #(1 << 30) /* 1GB block */
+ add x1, x1, x3
+
+ str x1, [x2] /* 2nd GB */
+
+ /* Setup/enable the MMU. */
+
+ /*
+ * TCR_EL1 - Translation Control Registers
+ *
+ * IPS[34:32] = 40-bit PA, 1TB
+ * ORGN0[11:10] = Outer: Normal, Outer Write-Back Read-Allocate No Write-Allocate Cacheable
+ * IRGN0[9:8] = Inner: Normal, Inner Write-Back Read-Allocate No Write-Allocate Cacheable.
+ * T0SZ[5:0] = 2^(64 - 25)
+ */
+ ldr x0, = (2 << 32) | 25 | (3 << 10) | (3 << 8)
+ msr tcr_el1, x0
+
+ mov x0, #0xee /* Inner/outer cacheable WB */
+ msr mair_el1, x0
+ isb
+
+ /*
+ * SCTLR_EL1 - System Control Register
+ *
+ * WXN[19] = 0 = no effect, Write does not imply XN (execute never)
+ * I[12] = Instruction cachability control
+ * SA[3] = SP alignment check
+ * C[2] = Data cachability control
+ * M[0] = 1, enable stage 1 address translation for EL0/1
+ */
+ mrs x0, sctlr_el1
+ ldr x1, =0x100d /* bits I(12) SA(3) C(2) M(0) */
+ bic x0, x0, #(1 << 1) /* clear bit A(1) */
+ bic x0, x0, #(1 << 19) /* clear WXN */
+ orr x0, x0, x1 /* set bits */
+
+ dsb sy
+ msr sctlr_el1, x0
+ isb
+
+ /*
+ * Enable FP registers. The standard C pre-amble will be
+ * saving these and A-profile compilers will use AdvSIMD
+ * registers unless we tell it not to.
+ */
+ mrs x0, cpacr_el1
+ orr x0, x0, #(3 << 20)
+ msr cpacr_el1, x0
+
+ /* Setup some stack space and enter the test code.
+ * Assume everthing except the return value is garbage when we
+ * return, we won't need it.
+ */
+ adrp x0, stack
+ add x0, x0, :lo12:stack
+
+ mov sp, x0
+ bl main
+
+ /* pass return value to sys exit */
+ mov x1, x0
+ ldr x0, =0x20026 /* ADP_Stopped_ApplicationExit */
+ stp x0, x1, [sp, #-16]!
+ mov x1, sp
+ mov x0, SYS_EXIT
+ semihosting_call
+ /* never returns */
+
+ /*
+ * Helper Functions
+ */
+
+ /* Output a single character to serial port */
+ .global __sys_outc
+__sys_outc:
+ stp x0, x1, [sp, #-16]!
+ /* pass address of c on stack */
+ mov x1, sp
+ mov x0, SYS_WRITEC
+ semihosting_call
+ ldp x0, x1, [sp], #16
+ ret
+
+ .data
+ .align 12
+ttb:
+ .space 4096, 0
+
+ .align 12
+stack:
+ .space 65536, 0
+stack_end:
diff --git a/tests/tcg/aarch64/system/kernel.ld b/tests/tcg/aarch64/system/kernel.ld
new file mode 100644
index 0000000000..73d75cae64
--- /dev/null
+++ b/tests/tcg/aarch64/system/kernel.ld
@@ -0,0 +1,22 @@
+ENTRY(__start)
+
+SECTIONS
+{
+ /* virt machine, RAM starts at 1gb */
+ . = (1 << 30);
+ .text : {
+ *(.text)
+ }
+ .data : {
+ *(.data)
+ }
+ .rodata : {
+ *(.rodata)
+ }
+ .bss : {
+ *(.bss)
+ }
+ /DISCARD/ : {
+ *(.ARM.attributes)
+ }
+}
--
2.20.1
^ permalink raw reply related [flat|nested] 53+ messages in thread
* [Qemu-devel] [PATCH v5 04/15] tests/tcg/multiarch: move the system memory test
@ 2019-04-30 16:52 ` Alex Bennée
0 siblings, 0 replies; 53+ messages in thread
From: Alex Bennée @ 2019-04-30 16:52 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm, mark.cave-ayland, cota, Alex Bennée
There is nothing inherently architecture specific about the memory
test although we may have to manage different restrictions of
unaligned access across architectures.
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
---
tests/tcg/{i386 => multiarch}/system/memory.c | 0
1 file changed, 0 insertions(+), 0 deletions(-)
rename tests/tcg/{i386 => multiarch}/system/memory.c (100%)
diff --git a/tests/tcg/i386/system/memory.c b/tests/tcg/multiarch/system/memory.c
similarity index 100%
rename from tests/tcg/i386/system/memory.c
rename to tests/tcg/multiarch/system/memory.c
--
2.20.1
^ permalink raw reply [flat|nested] 53+ messages in thread
* [Qemu-devel] [PATCH v5 04/15] tests/tcg/multiarch: move the system memory test
@ 2019-04-30 16:52 ` Alex Bennée
0 siblings, 0 replies; 53+ messages in thread
From: Alex Bennée @ 2019-04-30 16:52 UTC (permalink / raw)
To: qemu-devel; +Cc: Alex Bennée, qemu-arm, mark.cave-ayland, cota
There is nothing inherently architecture specific about the memory
test although we may have to manage different restrictions of
unaligned access across architectures.
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
---
tests/tcg/{i386 => multiarch}/system/memory.c | 0
1 file changed, 0 insertions(+), 0 deletions(-)
rename tests/tcg/{i386 => multiarch}/system/memory.c (100%)
diff --git a/tests/tcg/i386/system/memory.c b/tests/tcg/multiarch/system/memory.c
similarity index 100%
rename from tests/tcg/i386/system/memory.c
rename to tests/tcg/multiarch/system/memory.c
--
2.20.1
^ permalink raw reply [flat|nested] 53+ messages in thread
* [Qemu-devel] [PATCH v5 05/15] tests/tcg/minilib: support %c format char
@ 2019-04-30 16:52 ` Alex Bennée
0 siblings, 0 replies; 53+ messages in thread
From: Alex Bennée @ 2019-04-30 16:52 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm, mark.cave-ayland, cota, Alex Bennée
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
---
tests/tcg/minilib/printf.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/tests/tcg/minilib/printf.c b/tests/tcg/minilib/printf.c
index 121620cb16..d530b32be5 100644
--- a/tests/tcg/minilib/printf.c
+++ b/tests/tcg/minilib/printf.c
@@ -47,7 +47,7 @@ static void print_num(unsigned long long value, int base)
void ml_printf(const char *fmt, ...)
{
va_list ap;
- char *str;
+ char *str, c;
int base;
int has_long;
int alt_form;
@@ -119,6 +119,10 @@ void ml_printf(const char *fmt, ...)
str = va_arg(ap, char*);
print_str(str);
break;
+ case 'c':
+ c = (char) va_arg(ap, int);
+ __sys_outc(c);
+ break;
case '%':
__sys_outc(*fmt);
break;
--
2.20.1
^ permalink raw reply related [flat|nested] 53+ messages in thread
* [Qemu-devel] [PATCH v5 05/15] tests/tcg/minilib: support %c format char
@ 2019-04-30 16:52 ` Alex Bennée
0 siblings, 0 replies; 53+ messages in thread
From: Alex Bennée @ 2019-04-30 16:52 UTC (permalink / raw)
To: qemu-devel; +Cc: Alex Bennée, qemu-arm, mark.cave-ayland, cota
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
---
tests/tcg/minilib/printf.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/tests/tcg/minilib/printf.c b/tests/tcg/minilib/printf.c
index 121620cb16..d530b32be5 100644
--- a/tests/tcg/minilib/printf.c
+++ b/tests/tcg/minilib/printf.c
@@ -47,7 +47,7 @@ static void print_num(unsigned long long value, int base)
void ml_printf(const char *fmt, ...)
{
va_list ap;
- char *str;
+ char *str, c;
int base;
int has_long;
int alt_form;
@@ -119,6 +119,10 @@ void ml_printf(const char *fmt, ...)
str = va_arg(ap, char*);
print_str(str);
break;
+ case 'c':
+ c = (char) va_arg(ap, int);
+ __sys_outc(c);
+ break;
case '%':
__sys_outc(*fmt);
break;
--
2.20.1
^ permalink raw reply related [flat|nested] 53+ messages in thread
* [Qemu-devel] [PATCH v5 06/15] tests/tcg/multiarch: expand system memory test to cover more
@ 2019-04-30 16:52 ` Alex Bennée
0 siblings, 0 replies; 53+ messages in thread
From: Alex Bennée @ 2019-04-30 16:52 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm, mark.cave-ayland, cota, Alex Bennée
Expand the memory test to cover move of the softmmu code. Specifically
we:
- improve commentary
- add some helpers (for later BE support)
- reduce boiler plate into helpers
- add signed reads at various sizes/offsets
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
---
tests/tcg/multiarch/system/memory.c | 254 ++++++++++++++++++++++++----
1 file changed, 219 insertions(+), 35 deletions(-)
diff --git a/tests/tcg/multiarch/system/memory.c b/tests/tcg/multiarch/system/memory.c
index a7a0a8e978..5befbb36bb 100644
--- a/tests/tcg/multiarch/system/memory.c
+++ b/tests/tcg/multiarch/system/memory.c
@@ -5,16 +5,21 @@
* behave across normal and unaligned accesses across several pages.
* We are not replicating memory tests for stuck bits and other
* hardware level failures but looking for issues with different size
- * accesses when:
-
+ * accesses when access is:
*
+ * - unaligned at various sizes
+ * - spanning a (softmmu) page
+ * - sign extension when loading
*/
#include <inttypes.h>
+#include <stdbool.h>
#include <minilib.h>
-#define TEST_SIZE (4096 * 4) /* 4 pages */
+#define PAGE_SIZE 4096 /* nominal 4k "pages" */
+#define TEST_SIZE (PAGE_SIZE * 4) /* 4 pages */
+__attribute__((aligned(PAGE_SIZE)))
static uint8_t test_data[TEST_SIZE];
static void pdot(int count)
@@ -24,11 +29,19 @@ static void pdot(int count)
}
}
+/*
+ * Helper macros for shift/extract so we can keep our endian handling
+ * in one place.
+ */
+#define BYTE_SHIFT(b, pos) ((uint64_t)b << (pos * 8))
+#define BYTE_EXTRACT(b, pos) ((b >> (pos * 8)) & 0xff)
/*
- * Fill the data with ascending value bytes. As x86 is a LE machine we
- * write in ascending order and then read and high byte should either
- * be zero or higher than the lower bytes.
+ * Fill the data with ascending value bytes.
+ *
+ * Currently we only support Little Endian machines so write in
+ * ascending address order. When we read higher address bytes should
+ * either be zero or higher than the lower bytes.
*/
static void init_test_data_u8(void)
@@ -44,60 +57,109 @@ static void init_test_data_u8(void)
ml_printf("done\n");
}
+/*
+ * Full the data with alternating positive and negative bytes. This
+ * should mean for reads larger than a byte all subsequent reads will
+ * stay either negative or positive. We never write 0.
+ */
+
+static inline uint8_t get_byte(int index, bool neg)
+{
+ return neg ? ( 0xff << (index % 7)) : ( 0xff >> ((index % 6) + 1));
+}
+
+static void init_test_data_s8(bool neg_first)
+{
+ uint8_t top, bottom, *ptr = &test_data[0];
+ int i;
+
+ ml_printf("Filling test area with s8 pairs (%s):", neg_first ? "neg first":"pos first");
+ for (i = 0; i < TEST_SIZE / 2; i++) {
+ *ptr++ = get_byte(i, neg_first);
+ *ptr++ = get_byte(i, !neg_first);
+ pdot(i);
+ }
+ ml_printf("done\n");
+}
+
+/*
+ * Zero the first few bytes of the test data in preparation for
+ * new offset values.
+ */
+static void reset_start_data(int offset)
+{
+ uint32_t *ptr = (uint32_t *) &test_data[0];
+ int i;
+ for (i = 0; i < offset; i++) {
+ *ptr++ = 0;
+ }
+}
+
static void init_test_data_u16(int offset)
{
uint8_t count = 0;
- uint16_t word, *ptr = (uint16_t *) &test_data[0];
+ uint16_t word, *ptr = (uint16_t *) &test_data[offset];
const int max = (TEST_SIZE - offset) / sizeof(word);
int i;
- ml_printf("Filling test area with u16 (offset %d):", offset);
+ ml_printf("Filling test area with u16 (offset %d, %p):", offset, ptr);
- /* Leading zeros */
- for (i = 0; i < offset; i++) {
- *ptr = 0;
- }
+ reset_start_data(offset);
- ptr = (uint16_t *) &test_data[offset];
for (i = 0; i < max; i++) {
- uint8_t high, low;
- low = count++;
- high = count++;
- word = (high << 8) | low;
+ uint8_t low = count++, high = count++;
+ word = BYTE_SHIFT(high, 1) | BYTE_SHIFT(low, 0);
*ptr++ = word;
pdot(i);
}
- ml_printf("done\n");
+ ml_printf("done @ %p\n", ptr);
}
static void init_test_data_u32(int offset)
{
uint8_t count = 0;
- uint32_t word, *ptr = (uint32_t *) &test_data[0];
+ uint32_t word, *ptr = (uint32_t *) &test_data[offset];
const int max = (TEST_SIZE - offset) / sizeof(word);
int i;
- ml_printf("Filling test area with u32 (offset %d):", offset);
+ ml_printf("Filling test area with u32 (offset %d, %p):", offset, ptr);
- /* Leading zeros */
- for (i = 0; i < offset; i++) {
- *ptr = 0;
- }
+ reset_start_data(offset);
- ptr = (uint32_t *) &test_data[offset];
for (i = 0; i < max; i++) {
- uint8_t b1, b2, b3, b4;
- b4 = count++;
- b3 = count++;
- b2 = count++;
- b1 = count++;
- word = (b1 << 24) | (b2 << 16) | (b3 << 8) | b4;
+ uint8_t b4 = count++, b3 = count++;
+ uint8_t b2 = count++, b1 = count++;
+ word = BYTE_SHIFT(b1, 3) | BYTE_SHIFT(b2, 2) | BYTE_SHIFT(b3, 1) | b4;
*ptr++ = word;
pdot(i);
}
- ml_printf("done\n");
+ ml_printf("done @ %p\n", ptr);
}
+static void init_test_data_u64(int offset)
+{
+ uint8_t count = 0;
+ uint64_t word, *ptr = (uint64_t *) &test_data[offset];
+ const int max = (TEST_SIZE - offset) / sizeof(word);
+ int i;
+
+ ml_printf("Filling test area with u64 (offset %d, %p):", offset, ptr);
+
+ reset_start_data(offset);
+
+ for (i = 0; i < max; i++) {
+ uint8_t b8 = count++, b7 = count++;
+ uint8_t b6 = count++, b5 = count++;
+ uint8_t b4 = count++, b3 = count++;
+ uint8_t b2 = count++, b1 = count++;
+ word = BYTE_SHIFT(b1, 7) | BYTE_SHIFT(b2, 6) | BYTE_SHIFT(b3, 5) |
+ BYTE_SHIFT(b4, 4) | BYTE_SHIFT(b5, 3) | BYTE_SHIFT(b6, 2) |
+ BYTE_SHIFT(b7, 1) | b8;
+ *ptr++ = word;
+ pdot(i);
+ }
+ ml_printf("done @ %p\n", ptr);
+}
static int read_test_data_u16(int offset)
{
@@ -120,7 +182,7 @@ static int read_test_data_u16(int offset)
}
}
- ml_printf("done\n");
+ ml_printf("done @ %p\n", ptr);
return 0;
}
@@ -150,7 +212,7 @@ static int read_test_data_u32(int offset)
pdot(i);
}
}
- ml_printf("done\n");
+ ml_printf("done @ %p\n", ptr);
return 0;
}
@@ -189,7 +251,7 @@ static int read_test_data_u64(int offset)
pdot(i);
}
}
- ml_printf("done\n");
+ ml_printf("done @ %p\n", ptr);
return 0;
}
@@ -209,6 +271,110 @@ int do_reads(void)
return r;
}
+/*
+ * We need to ensure signed data is read into a larger data type to
+ * ensure that sign extension is working properly.
+ */
+
+static int read_test_data_s8(int offset, bool neg_first)
+{
+ int8_t *ptr = (int8_t *)&test_data[offset];
+ int i;
+ const int max = (TEST_SIZE - offset) / 2;
+
+ ml_printf("Reading s8 pairs from %#lx (offset %d):", ptr, offset);
+
+ for (i = 0; i < max; i++) {
+ int16_t first, second;
+ bool ok;
+ first = *ptr++;
+ second = *ptr++;
+
+ if (neg_first && first < 0 && second > 0) {
+ pdot(i);
+ } else if (!neg_first && first > 0 && second < 0) {
+ pdot(i);
+ } else {
+ ml_printf("Error %d %c %d\n", first, neg_first ? '<' : '>', second);
+ return 1;
+ }
+ }
+ ml_printf("done @ %p\n", ptr);
+ return 0;
+}
+
+static int read_test_data_s16(int offset, bool neg_first)
+{
+ int16_t *ptr = (int16_t *)&test_data[offset];
+ int i;
+ const int max = (TEST_SIZE - offset) / (sizeof(*ptr));
+
+ ml_printf("Reading s16 from %#lx (offset %d, %s):",
+ ptr, offset, neg_first ? "neg":"pos");
+
+ for (i = 0; i < max; i++) {
+ int32_t data = *ptr++;
+
+ if (neg_first && data < 0) {
+ pdot(i);
+ } else if (data > 0) {
+ pdot(i);
+ } else {
+ ml_printf("Error %d %c 0\n", data, neg_first ? '<' : '>');
+ return 1;
+ }
+ }
+ ml_printf("done @ %p\n", ptr);
+ return 0;
+}
+
+static int read_test_data_s32(int offset, bool neg_first)
+{
+ int32_t *ptr = (int32_t *)&test_data[offset];
+ int i;
+ const int max = (TEST_SIZE - offset) / (sizeof(int32_t));
+
+ ml_printf("Reading s32 from %#lx (offset %d, %s):",
+ ptr, offset, neg_first ? "neg":"pos");
+
+ for (i = 0; i < max; i++) {
+ int64_t data = *ptr++;
+
+ if (neg_first && data < 0) {
+ pdot(i);
+ } else if (data > 0) {
+ pdot(i);
+ } else {
+ ml_printf("Error %d %c 0\n", data, neg_first ? '<' : '>');
+ return 1;
+ }
+ }
+ ml_printf("done @ %p\n", ptr);
+ return 0;
+}
+
+/*
+ * Read the test data and verify at various offsets
+ *
+ * For everything except bytes all our reads should be either positive
+ * or negative depending on what offset we are reading from. Currently
+ * we only handle LE systems.
+ */
+int do_signed_reads(bool neg_first)
+{
+ int r = 0;
+ int off = 0;
+
+ while (r == 0 && off < 8) {
+ r = read_test_data_s8(off, neg_first ^ (off & 1));
+ r |= read_test_data_s16(off, !(neg_first ^ (off & 1)));
+ r |= read_test_data_s32(off, !(neg_first ^ (off & 1)));
+ off++;
+ }
+
+ return r;
+}
+
int main(void)
{
int i, r = 0;
@@ -238,6 +404,24 @@ int main(void)
}
}
+ for (i = 0; i < 8; i++) {
+ init_test_data_u64(i);
+
+ r = do_reads();
+ if (r) {
+ return r;
+ }
+ }
+
+ init_test_data_s8(false);
+ r = do_signed_reads(false);
+ if (r) {
+ return r;
+ }
+
+ init_test_data_s8(true);
+ r = do_signed_reads(true);
+
ml_printf("Test complete: %s\n", r == 0 ? "PASSED" : "FAILED");
return r;
}
--
2.20.1
^ permalink raw reply related [flat|nested] 53+ messages in thread
* [Qemu-devel] [PATCH v5 06/15] tests/tcg/multiarch: expand system memory test to cover more
@ 2019-04-30 16:52 ` Alex Bennée
0 siblings, 0 replies; 53+ messages in thread
From: Alex Bennée @ 2019-04-30 16:52 UTC (permalink / raw)
To: qemu-devel; +Cc: Alex Bennée, qemu-arm, mark.cave-ayland, cota
Expand the memory test to cover move of the softmmu code. Specifically
we:
- improve commentary
- add some helpers (for later BE support)
- reduce boiler plate into helpers
- add signed reads at various sizes/offsets
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
---
tests/tcg/multiarch/system/memory.c | 254 ++++++++++++++++++++++++----
1 file changed, 219 insertions(+), 35 deletions(-)
diff --git a/tests/tcg/multiarch/system/memory.c b/tests/tcg/multiarch/system/memory.c
index a7a0a8e978..5befbb36bb 100644
--- a/tests/tcg/multiarch/system/memory.c
+++ b/tests/tcg/multiarch/system/memory.c
@@ -5,16 +5,21 @@
* behave across normal and unaligned accesses across several pages.
* We are not replicating memory tests for stuck bits and other
* hardware level failures but looking for issues with different size
- * accesses when:
-
+ * accesses when access is:
*
+ * - unaligned at various sizes
+ * - spanning a (softmmu) page
+ * - sign extension when loading
*/
#include <inttypes.h>
+#include <stdbool.h>
#include <minilib.h>
-#define TEST_SIZE (4096 * 4) /* 4 pages */
+#define PAGE_SIZE 4096 /* nominal 4k "pages" */
+#define TEST_SIZE (PAGE_SIZE * 4) /* 4 pages */
+__attribute__((aligned(PAGE_SIZE)))
static uint8_t test_data[TEST_SIZE];
static void pdot(int count)
@@ -24,11 +29,19 @@ static void pdot(int count)
}
}
+/*
+ * Helper macros for shift/extract so we can keep our endian handling
+ * in one place.
+ */
+#define BYTE_SHIFT(b, pos) ((uint64_t)b << (pos * 8))
+#define BYTE_EXTRACT(b, pos) ((b >> (pos * 8)) & 0xff)
/*
- * Fill the data with ascending value bytes. As x86 is a LE machine we
- * write in ascending order and then read and high byte should either
- * be zero or higher than the lower bytes.
+ * Fill the data with ascending value bytes.
+ *
+ * Currently we only support Little Endian machines so write in
+ * ascending address order. When we read higher address bytes should
+ * either be zero or higher than the lower bytes.
*/
static void init_test_data_u8(void)
@@ -44,60 +57,109 @@ static void init_test_data_u8(void)
ml_printf("done\n");
}
+/*
+ * Full the data with alternating positive and negative bytes. This
+ * should mean for reads larger than a byte all subsequent reads will
+ * stay either negative or positive. We never write 0.
+ */
+
+static inline uint8_t get_byte(int index, bool neg)
+{
+ return neg ? ( 0xff << (index % 7)) : ( 0xff >> ((index % 6) + 1));
+}
+
+static void init_test_data_s8(bool neg_first)
+{
+ uint8_t top, bottom, *ptr = &test_data[0];
+ int i;
+
+ ml_printf("Filling test area with s8 pairs (%s):", neg_first ? "neg first":"pos first");
+ for (i = 0; i < TEST_SIZE / 2; i++) {
+ *ptr++ = get_byte(i, neg_first);
+ *ptr++ = get_byte(i, !neg_first);
+ pdot(i);
+ }
+ ml_printf("done\n");
+}
+
+/*
+ * Zero the first few bytes of the test data in preparation for
+ * new offset values.
+ */
+static void reset_start_data(int offset)
+{
+ uint32_t *ptr = (uint32_t *) &test_data[0];
+ int i;
+ for (i = 0; i < offset; i++) {
+ *ptr++ = 0;
+ }
+}
+
static void init_test_data_u16(int offset)
{
uint8_t count = 0;
- uint16_t word, *ptr = (uint16_t *) &test_data[0];
+ uint16_t word, *ptr = (uint16_t *) &test_data[offset];
const int max = (TEST_SIZE - offset) / sizeof(word);
int i;
- ml_printf("Filling test area with u16 (offset %d):", offset);
+ ml_printf("Filling test area with u16 (offset %d, %p):", offset, ptr);
- /* Leading zeros */
- for (i = 0; i < offset; i++) {
- *ptr = 0;
- }
+ reset_start_data(offset);
- ptr = (uint16_t *) &test_data[offset];
for (i = 0; i < max; i++) {
- uint8_t high, low;
- low = count++;
- high = count++;
- word = (high << 8) | low;
+ uint8_t low = count++, high = count++;
+ word = BYTE_SHIFT(high, 1) | BYTE_SHIFT(low, 0);
*ptr++ = word;
pdot(i);
}
- ml_printf("done\n");
+ ml_printf("done @ %p\n", ptr);
}
static void init_test_data_u32(int offset)
{
uint8_t count = 0;
- uint32_t word, *ptr = (uint32_t *) &test_data[0];
+ uint32_t word, *ptr = (uint32_t *) &test_data[offset];
const int max = (TEST_SIZE - offset) / sizeof(word);
int i;
- ml_printf("Filling test area with u32 (offset %d):", offset);
+ ml_printf("Filling test area with u32 (offset %d, %p):", offset, ptr);
- /* Leading zeros */
- for (i = 0; i < offset; i++) {
- *ptr = 0;
- }
+ reset_start_data(offset);
- ptr = (uint32_t *) &test_data[offset];
for (i = 0; i < max; i++) {
- uint8_t b1, b2, b3, b4;
- b4 = count++;
- b3 = count++;
- b2 = count++;
- b1 = count++;
- word = (b1 << 24) | (b2 << 16) | (b3 << 8) | b4;
+ uint8_t b4 = count++, b3 = count++;
+ uint8_t b2 = count++, b1 = count++;
+ word = BYTE_SHIFT(b1, 3) | BYTE_SHIFT(b2, 2) | BYTE_SHIFT(b3, 1) | b4;
*ptr++ = word;
pdot(i);
}
- ml_printf("done\n");
+ ml_printf("done @ %p\n", ptr);
}
+static void init_test_data_u64(int offset)
+{
+ uint8_t count = 0;
+ uint64_t word, *ptr = (uint64_t *) &test_data[offset];
+ const int max = (TEST_SIZE - offset) / sizeof(word);
+ int i;
+
+ ml_printf("Filling test area with u64 (offset %d, %p):", offset, ptr);
+
+ reset_start_data(offset);
+
+ for (i = 0; i < max; i++) {
+ uint8_t b8 = count++, b7 = count++;
+ uint8_t b6 = count++, b5 = count++;
+ uint8_t b4 = count++, b3 = count++;
+ uint8_t b2 = count++, b1 = count++;
+ word = BYTE_SHIFT(b1, 7) | BYTE_SHIFT(b2, 6) | BYTE_SHIFT(b3, 5) |
+ BYTE_SHIFT(b4, 4) | BYTE_SHIFT(b5, 3) | BYTE_SHIFT(b6, 2) |
+ BYTE_SHIFT(b7, 1) | b8;
+ *ptr++ = word;
+ pdot(i);
+ }
+ ml_printf("done @ %p\n", ptr);
+}
static int read_test_data_u16(int offset)
{
@@ -120,7 +182,7 @@ static int read_test_data_u16(int offset)
}
}
- ml_printf("done\n");
+ ml_printf("done @ %p\n", ptr);
return 0;
}
@@ -150,7 +212,7 @@ static int read_test_data_u32(int offset)
pdot(i);
}
}
- ml_printf("done\n");
+ ml_printf("done @ %p\n", ptr);
return 0;
}
@@ -189,7 +251,7 @@ static int read_test_data_u64(int offset)
pdot(i);
}
}
- ml_printf("done\n");
+ ml_printf("done @ %p\n", ptr);
return 0;
}
@@ -209,6 +271,110 @@ int do_reads(void)
return r;
}
+/*
+ * We need to ensure signed data is read into a larger data type to
+ * ensure that sign extension is working properly.
+ */
+
+static int read_test_data_s8(int offset, bool neg_first)
+{
+ int8_t *ptr = (int8_t *)&test_data[offset];
+ int i;
+ const int max = (TEST_SIZE - offset) / 2;
+
+ ml_printf("Reading s8 pairs from %#lx (offset %d):", ptr, offset);
+
+ for (i = 0; i < max; i++) {
+ int16_t first, second;
+ bool ok;
+ first = *ptr++;
+ second = *ptr++;
+
+ if (neg_first && first < 0 && second > 0) {
+ pdot(i);
+ } else if (!neg_first && first > 0 && second < 0) {
+ pdot(i);
+ } else {
+ ml_printf("Error %d %c %d\n", first, neg_first ? '<' : '>', second);
+ return 1;
+ }
+ }
+ ml_printf("done @ %p\n", ptr);
+ return 0;
+}
+
+static int read_test_data_s16(int offset, bool neg_first)
+{
+ int16_t *ptr = (int16_t *)&test_data[offset];
+ int i;
+ const int max = (TEST_SIZE - offset) / (sizeof(*ptr));
+
+ ml_printf("Reading s16 from %#lx (offset %d, %s):",
+ ptr, offset, neg_first ? "neg":"pos");
+
+ for (i = 0; i < max; i++) {
+ int32_t data = *ptr++;
+
+ if (neg_first && data < 0) {
+ pdot(i);
+ } else if (data > 0) {
+ pdot(i);
+ } else {
+ ml_printf("Error %d %c 0\n", data, neg_first ? '<' : '>');
+ return 1;
+ }
+ }
+ ml_printf("done @ %p\n", ptr);
+ return 0;
+}
+
+static int read_test_data_s32(int offset, bool neg_first)
+{
+ int32_t *ptr = (int32_t *)&test_data[offset];
+ int i;
+ const int max = (TEST_SIZE - offset) / (sizeof(int32_t));
+
+ ml_printf("Reading s32 from %#lx (offset %d, %s):",
+ ptr, offset, neg_first ? "neg":"pos");
+
+ for (i = 0; i < max; i++) {
+ int64_t data = *ptr++;
+
+ if (neg_first && data < 0) {
+ pdot(i);
+ } else if (data > 0) {
+ pdot(i);
+ } else {
+ ml_printf("Error %d %c 0\n", data, neg_first ? '<' : '>');
+ return 1;
+ }
+ }
+ ml_printf("done @ %p\n", ptr);
+ return 0;
+}
+
+/*
+ * Read the test data and verify at various offsets
+ *
+ * For everything except bytes all our reads should be either positive
+ * or negative depending on what offset we are reading from. Currently
+ * we only handle LE systems.
+ */
+int do_signed_reads(bool neg_first)
+{
+ int r = 0;
+ int off = 0;
+
+ while (r == 0 && off < 8) {
+ r = read_test_data_s8(off, neg_first ^ (off & 1));
+ r |= read_test_data_s16(off, !(neg_first ^ (off & 1)));
+ r |= read_test_data_s32(off, !(neg_first ^ (off & 1)));
+ off++;
+ }
+
+ return r;
+}
+
int main(void)
{
int i, r = 0;
@@ -238,6 +404,24 @@ int main(void)
}
}
+ for (i = 0; i < 8; i++) {
+ init_test_data_u64(i);
+
+ r = do_reads();
+ if (r) {
+ return r;
+ }
+ }
+
+ init_test_data_s8(false);
+ r = do_signed_reads(false);
+ if (r) {
+ return r;
+ }
+
+ init_test_data_s8(true);
+ r = do_signed_reads(true);
+
ml_printf("Test complete: %s\n", r == 0 ? "PASSED" : "FAILED");
return r;
}
--
2.20.1
^ permalink raw reply related [flat|nested] 53+ messages in thread
* [Qemu-devel] [PATCH v5 07/15] accel/tcg: demacro cputlb
@ 2019-04-30 16:52 ` Alex Bennée
0 siblings, 0 replies; 53+ messages in thread
From: Alex Bennée @ 2019-04-30 16:52 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm, mark.cave-ayland, cota, Alex Bennée
Instead of expanding a series of macros to generate the load/store
helpers we move stuff into common functions and rely on the compiler
to eliminate the dead code for each variant.
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
---
v5
- merged rth's fixes:
- cast to uint64_t instead of tcg_target_ulong
- make haddr void * instead of uintptr_t (reduce casting)
- common & size_mask
---
accel/tcg/cputlb.c | 478 ++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 452 insertions(+), 26 deletions(-)
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
index f2f618217d..12f21865ee 100644
--- a/accel/tcg/cputlb.c
+++ b/accel/tcg/cputlb.c
@@ -1168,26 +1168,421 @@ static void *atomic_mmu_lookup(CPUArchState *env, target_ulong addr,
}
#ifdef TARGET_WORDS_BIGENDIAN
-# define TGT_BE(X) (X)
-# define TGT_LE(X) BSWAP(X)
+#define NEED_BE_BSWAP 0
+#define NEED_LE_BSWAP 1
#else
-# define TGT_BE(X) BSWAP(X)
-# define TGT_LE(X) (X)
+#define NEED_BE_BSWAP 1
+#define NEED_LE_BSWAP 0
#endif
-#define MMUSUFFIX _mmu
+/*
+ * Byte Swap Helper
+ *
+ * This should all dead code away depending on the build host and
+ * access type.
+ */
-#define DATA_SIZE 1
-#include "softmmu_template.h"
+static inline uint64_t handle_bswap(uint64_t val, int size, bool big_endian)
+{
+ if ((big_endian && NEED_BE_BSWAP) || (!big_endian && NEED_LE_BSWAP)) {
+ switch (size) {
+ case 1: return val;
+ case 2: return bswap16(val);
+ case 4: return bswap32(val);
+ case 8: return bswap64(val);
+ default:
+ g_assert_not_reached();
+ }
+ } else {
+ return val;
+ }
+}
-#define DATA_SIZE 2
-#include "softmmu_template.h"
+/*
+ * Load Helpers
+ *
+ * We support two different access types. SOFTMMU_CODE_ACCESS is
+ * specifically for reading instructions from system memory. It is
+ * called by the translation loop and in some helpers where the code
+ * is disassembled. It shouldn't be called directly by guest code.
+ */
-#define DATA_SIZE 4
-#include "softmmu_template.h"
+static uint64_t load_helper(CPUArchState *env, target_ulong addr,
+ TCGMemOpIdx oi, uintptr_t retaddr,
+ size_t size, bool big_endian,
+ bool code_read)
+{
+ uintptr_t mmu_idx = get_mmuidx(oi);
+ uintptr_t index = tlb_index(env, mmu_idx, addr);
+ CPUTLBEntry *entry = tlb_entry(env, mmu_idx, addr);
+ target_ulong tlb_addr = code_read ? entry->addr_code : entry->addr_read;
+ const size_t tlb_off = code_read ?
+ offsetof(CPUTLBEntry, addr_code) : offsetof(CPUTLBEntry, addr_read);
+ unsigned a_bits = get_alignment_bits(get_memop(oi));
+ void *haddr;
+ uint64_t res;
+
+ /* Handle CPU specific unaligned behaviour */
+ if (addr & ((1 << a_bits) - 1)) {
+ cpu_unaligned_access(ENV_GET_CPU(env), addr,
+ code_read ? MMU_INST_FETCH : MMU_DATA_LOAD,
+ mmu_idx, retaddr);
+ }
-#define DATA_SIZE 8
-#include "softmmu_template.h"
+ /* If the TLB entry is for a different page, reload and try again. */
+ if (!tlb_hit(tlb_addr, addr)) {
+ if (!victim_tlb_hit(env, mmu_idx, index, tlb_off,
+ addr & TARGET_PAGE_MASK)) {
+ tlb_fill(ENV_GET_CPU(env), addr, size,
+ code_read ? MMU_INST_FETCH : MMU_DATA_LOAD,
+ mmu_idx, retaddr);
+ index = tlb_index(env, mmu_idx, addr);
+ entry = tlb_entry(env, mmu_idx, addr);
+ }
+ tlb_addr = code_read ? entry->addr_code : entry->addr_read;
+ }
+
+ /* Handle an IO access. */
+ if (unlikely(tlb_addr & ~TARGET_PAGE_MASK)) {
+ CPUIOTLBEntry *iotlbentry = &env->iotlb[mmu_idx][index];
+ uint64_t tmp;
+
+ if ((addr & (size - 1)) != 0) {
+ goto do_unaligned_access;
+ }
+
+ tmp = io_readx(env, iotlbentry, mmu_idx, addr, retaddr,
+ tlb_addr & TLB_RECHECK,
+ code_read ? MMU_INST_FETCH : MMU_DATA_LOAD, size);
+ return handle_bswap(tmp, size, big_endian);
+ }
+
+ /* Handle slow unaligned access (it spans two pages or IO). */
+ if (size > 1
+ && unlikely((addr & ~TARGET_PAGE_MASK) + size - 1
+ >= TARGET_PAGE_SIZE)) {
+ target_ulong addr1, addr2;
+ tcg_target_ulong r1, r2;
+ unsigned shift;
+ do_unaligned_access:
+ addr1 = addr & ~(size - 1);
+ addr2 = addr1 + size;
+ r1 = load_helper(env, addr1, oi, retaddr, size, big_endian, code_read);
+ r2 = load_helper(env, addr2, oi, retaddr, size, big_endian, code_read);
+ shift = (addr & (size - 1)) * 8;
+
+ if (big_endian) {
+ /* Big-endian combine. */
+ res = (r1 << shift) | (r2 >> ((size * 8) - shift));
+ } else {
+ /* Little-endian combine. */
+ res = (r1 >> shift) | (r2 << ((size * 8) - shift));
+ }
+ return res & MAKE_64BIT_MASK(0, size * 8);
+ }
+
+ haddr = (void *)((uintptr_t)addr + entry->addend);
+
+ switch (size) {
+ case 1:
+ res = ldub_p(haddr);
+ break;
+ case 2:
+ if (big_endian) {
+ res = lduw_be_p(haddr);
+ } else {
+ res = lduw_le_p(haddr);
+ }
+ break;
+ case 4:
+ if (big_endian) {
+ res = (uint32_t)ldl_be_p(haddr);
+ } else {
+ res = (uint32_t)ldl_le_p(haddr);
+ }
+ break;
+ case 8:
+ if (big_endian) {
+ res = ldq_be_p(haddr);
+ } else {
+ res = ldq_le_p(haddr);
+ }
+ break;
+ default:
+ g_assert_not_reached();
+ }
+
+ return res;
+}
+
+/*
+ * For the benefit of TCG generated code, we want to avoid the
+ * complication of ABI-specific return type promotion and always
+ * return a value extended to the register size of the host. This is
+ * tcg_target_long, except in the case of a 32-bit host and 64-bit
+ * data, and for that we always have uint64_t.
+ *
+ * We don't bother with this widened value for SOFTMMU_CODE_ACCESS.
+ */
+
+tcg_target_ulong __attribute__((flatten))
+helper_ret_ldub_mmu(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi,
+ uintptr_t retaddr)
+{
+ return load_helper(env, addr, oi, retaddr, 1, false, false);
+}
+
+tcg_target_ulong __attribute__((flatten))
+helper_le_lduw_mmu(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi,
+ uintptr_t retaddr)
+{
+ return load_helper(env, addr, oi, retaddr, 2, false, false);
+}
+
+tcg_target_ulong __attribute__((flatten))
+helper_be_lduw_mmu(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi,
+ uintptr_t retaddr)
+{
+ return load_helper(env, addr, oi, retaddr, 2, true, false);
+}
+
+tcg_target_ulong __attribute__((flatten))
+helper_le_ldul_mmu(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi,
+ uintptr_t retaddr)
+{
+ return load_helper(env, addr, oi, retaddr, 4, false, false);
+}
+
+tcg_target_ulong __attribute__((flatten))
+helper_be_ldul_mmu(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi,
+ uintptr_t retaddr)
+{
+ return load_helper(env, addr, oi, retaddr, 4, true, false);
+}
+
+uint64_t __attribute__((flatten))
+helper_le_ldq_mmu(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi,
+ uintptr_t retaddr)
+{
+ return load_helper(env, addr, oi, retaddr, 8, false, false);
+}
+
+uint64_t __attribute__((flatten))
+helper_be_ldq_mmu(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi,
+ uintptr_t retaddr)
+{
+ return load_helper(env, addr, oi, retaddr, 8, true, false);
+}
+
+/*
+ * Provide signed versions of the load routines as well. We can of course
+ * avoid this for 64-bit data, or for 32-bit data on 32-bit host.
+ */
+
+
+tcg_target_ulong helper_ret_ldsb_mmu(CPUArchState *env, target_ulong addr,
+ TCGMemOpIdx oi, uintptr_t retaddr)
+{
+ return (int8_t)helper_ret_ldub_mmu(env, addr, oi, retaddr);
+}
+
+tcg_target_ulong helper_le_ldsw_mmu(CPUArchState *env, target_ulong addr,
+ TCGMemOpIdx oi, uintptr_t retaddr)
+{
+ return (int16_t)helper_le_lduw_mmu(env, addr, oi, retaddr);
+}
+
+tcg_target_ulong helper_be_ldsw_mmu(CPUArchState *env, target_ulong addr,
+ TCGMemOpIdx oi, uintptr_t retaddr)
+{
+ return (int16_t)helper_be_lduw_mmu(env, addr, oi, retaddr);
+}
+
+tcg_target_ulong helper_le_ldsl_mmu(CPUArchState *env, target_ulong addr,
+ TCGMemOpIdx oi, uintptr_t retaddr)
+{
+ return (int32_t)helper_le_ldul_mmu(env, addr, oi, retaddr);
+}
+
+tcg_target_ulong helper_be_ldsl_mmu(CPUArchState *env, target_ulong addr,
+ TCGMemOpIdx oi, uintptr_t retaddr)
+{
+ return (int32_t)helper_be_ldul_mmu(env, addr, oi, retaddr);
+}
+
+/*
+ * Store Helpers
+ */
+
+static void store_helper(CPUArchState *env, target_ulong addr, uint64_t val,
+ TCGMemOpIdx oi, uintptr_t retaddr, size_t size,
+ bool big_endian)
+{
+ uintptr_t mmu_idx = get_mmuidx(oi);
+ uintptr_t index = tlb_index(env, mmu_idx, addr);
+ CPUTLBEntry *entry = tlb_entry(env, mmu_idx, addr);
+ target_ulong tlb_addr = tlb_addr_write(entry);
+ const size_t tlb_off = offsetof(CPUTLBEntry, addr_write);
+ unsigned a_bits = get_alignment_bits(get_memop(oi));
+ void *haddr;
+
+ /* Handle CPU specific unaligned behaviour */
+ if (addr & ((1 << a_bits) - 1)) {
+ cpu_unaligned_access(ENV_GET_CPU(env), addr, MMU_DATA_STORE,
+ mmu_idx, retaddr);
+ }
+
+ /* If the TLB entry is for a different page, reload and try again. */
+ if (!tlb_hit(tlb_addr, addr)) {
+ if (!victim_tlb_hit(env, mmu_idx, index, tlb_off,
+ addr & TARGET_PAGE_MASK)) {
+ tlb_fill(ENV_GET_CPU(env), addr, size, MMU_DATA_STORE,
+ mmu_idx, retaddr);
+ index = tlb_index(env, mmu_idx, addr);
+ entry = tlb_entry(env, mmu_idx, addr);
+ }
+ tlb_addr = tlb_addr_write(entry) & ~TLB_INVALID_MASK;
+ }
+
+ /* Handle an IO access. */
+ if (unlikely(tlb_addr & ~TARGET_PAGE_MASK)) {
+ CPUIOTLBEntry *iotlbentry = &env->iotlb[mmu_idx][index];
+
+ if ((addr & (size - 1)) != 0) {
+ goto do_unaligned_access;
+ }
+
+ io_writex(env, iotlbentry, mmu_idx,
+ handle_bswap(val, size, big_endian),
+ addr, retaddr, tlb_addr & TLB_RECHECK, size);
+ return;
+ }
+
+ /* Handle slow unaligned access (it spans two pages or IO). */
+ if (size > 1
+ && unlikely((addr & ~TARGET_PAGE_MASK) + size - 1
+ >= TARGET_PAGE_SIZE)) {
+ int i;
+ uintptr_t index2;
+ CPUTLBEntry *entry2;
+ target_ulong page2, tlb_addr2;
+ do_unaligned_access:
+ /*
+ * Ensure the second page is in the TLB. Note that the first page
+ * is already guaranteed to be filled, and that the second page
+ * cannot evict the first.
+ */
+ page2 = (addr + size) & TARGET_PAGE_MASK;
+ index2 = tlb_index(env, mmu_idx, page2);
+ entry2 = tlb_entry(env, mmu_idx, page2);
+ tlb_addr2 = tlb_addr_write(entry2);
+ if (!tlb_hit_page(tlb_addr2, page2)
+ && !victim_tlb_hit(env, mmu_idx, index2, tlb_off,
+ page2 & TARGET_PAGE_MASK)) {
+ tlb_fill(ENV_GET_CPU(env), page2, size, MMU_DATA_STORE,
+ mmu_idx, retaddr);
+ }
+
+ /*
+ * XXX: not efficient, but simple.
+ * This loop must go in the forward direction to avoid issues
+ * with self-modifying code in Windows 64-bit.
+ */
+ for (i = 0; i < size; ++i) {
+ uint8_t val8;
+ if (big_endian) {
+ /* Big-endian extract. */
+ val8 = val >> (((size - 1) * 8) - (i * 8));
+ } else {
+ /* Little-endian extract. */
+ val8 = val >> (i * 8);
+ }
+ store_helper(env, addr + i, val8, oi, retaddr, 1, big_endian);
+ }
+ return;
+ }
+
+ haddr = (void *)((uintptr_t)addr + entry->addend);
+
+ switch (size) {
+ case 1:
+ stb_p(haddr, val);
+ break;
+ case 2:
+ if (big_endian) {
+ stw_be_p(haddr, val);
+ } else {
+ stw_le_p(haddr, val);
+ }
+ break;
+ case 4:
+ if (big_endian) {
+ stl_be_p(haddr, val);
+ } else {
+ stl_le_p(haddr, val);
+ }
+ break;
+ case 8:
+ if (big_endian) {
+ stq_be_p(haddr, val);
+ } else {
+ stq_le_p(haddr, val);
+ }
+ break;
+ default:
+ g_assert_not_reached();
+ break;
+ }
+}
+
+void __attribute__((flatten))
+helper_ret_stb_mmu(CPUArchState *env, target_ulong addr, uint8_t val,
+ TCGMemOpIdx oi, uintptr_t retaddr)
+{
+ store_helper(env, addr, val, oi, retaddr, 1, false);
+}
+
+void __attribute__((flatten))
+helper_le_stw_mmu(CPUArchState *env, target_ulong addr, uint16_t val,
+ TCGMemOpIdx oi, uintptr_t retaddr)
+{
+ store_helper(env, addr, val, oi, retaddr, 2, false);
+}
+
+void __attribute__((flatten))
+helper_be_stw_mmu(CPUArchState *env, target_ulong addr, uint16_t val,
+ TCGMemOpIdx oi, uintptr_t retaddr)
+{
+ store_helper(env, addr, val, oi, retaddr, 2, true);
+}
+
+void __attribute__((flatten))
+helper_le_stl_mmu(CPUArchState *env, target_ulong addr, uint32_t val,
+ TCGMemOpIdx oi, uintptr_t retaddr)
+{
+ store_helper(env, addr, val, oi, retaddr, 4, false);
+}
+
+void __attribute__((flatten))
+helper_be_stl_mmu(CPUArchState *env, target_ulong addr, uint32_t val,
+ TCGMemOpIdx oi, uintptr_t retaddr)
+{
+ store_helper(env, addr, val, oi, retaddr, 4, true);
+}
+
+void __attribute__((flatten))
+helper_le_stq_mmu(CPUArchState *env, target_ulong addr, uint64_t val,
+ TCGMemOpIdx oi, uintptr_t retaddr)
+{
+ store_helper(env, addr, val, oi, retaddr, 8, false);
+}
+
+void __attribute__((flatten))
+helper_be_stq_mmu(CPUArchState *env, target_ulong addr, uint64_t val,
+ TCGMemOpIdx oi, uintptr_t retaddr)
+{
+ store_helper(env, addr, val, oi, retaddr, 8, true);
+}
/* First set of helpers allows passing in of OI and RETADDR. This makes
them callable from other helpers. */
@@ -1248,20 +1643,51 @@ static void *atomic_mmu_lookup(CPUArchState *env, target_ulong addr,
/* Code access functions. */
-#undef MMUSUFFIX
-#define MMUSUFFIX _cmmu
-#undef GETPC
-#define GETPC() ((uintptr_t)0)
-#define SOFTMMU_CODE_ACCESS
+uint8_t __attribute__((flatten))
+helper_ret_ldb_cmmu(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi,
+ uintptr_t retaddr)
+{
+ return load_helper(env, addr, oi, retaddr, 1, false, true);
+}
-#define DATA_SIZE 1
-#include "softmmu_template.h"
+uint16_t __attribute__((flatten))
+helper_le_ldw_cmmu(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi,
+ uintptr_t retaddr)
+{
+ return load_helper(env, addr, oi, retaddr, 2, false, true);
+}
-#define DATA_SIZE 2
-#include "softmmu_template.h"
+uint16_t __attribute__((flatten))
+helper_be_ldw_cmmu(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi,
+ uintptr_t retaddr)
+{
+ return load_helper(env, addr, oi, retaddr, 2, true, true);
+}
-#define DATA_SIZE 4
-#include "softmmu_template.h"
+uint32_t __attribute__((flatten))
+helper_le_ldl_cmmu(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi,
+ uintptr_t retaddr)
+{
+ return load_helper(env, addr, oi, retaddr, 4, false, true);
+}
-#define DATA_SIZE 8
-#include "softmmu_template.h"
+uint32_t __attribute__((flatten))
+helper_be_ldl_cmmu(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi,
+ uintptr_t retaddr)
+{
+ return load_helper(env, addr, oi, retaddr, 4, true, true);
+}
+
+uint64_t __attribute__((flatten))
+helper_le_ldq_cmmu(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi,
+ uintptr_t retaddr)
+{
+ return load_helper(env, addr, oi, retaddr, 8, false, true);
+}
+
+uint64_t __attribute__((flatten))
+helper_be_ldq_cmmu(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi,
+ uintptr_t retaddr)
+{
+ return load_helper(env, addr, oi, retaddr, 8, true, true);
+}
--
2.20.1
^ permalink raw reply related [flat|nested] 53+ messages in thread
* [Qemu-devel] [PATCH v5 07/15] accel/tcg: demacro cputlb
@ 2019-04-30 16:52 ` Alex Bennée
0 siblings, 0 replies; 53+ messages in thread
From: Alex Bennée @ 2019-04-30 16:52 UTC (permalink / raw)
To: qemu-devel; +Cc: Alex Bennée, qemu-arm, mark.cave-ayland, cota
Instead of expanding a series of macros to generate the load/store
helpers we move stuff into common functions and rely on the compiler
to eliminate the dead code for each variant.
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
---
v5
- merged rth's fixes:
- cast to uint64_t instead of tcg_target_ulong
- make haddr void * instead of uintptr_t (reduce casting)
- common & size_mask
---
accel/tcg/cputlb.c | 478 ++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 452 insertions(+), 26 deletions(-)
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
index f2f618217d..12f21865ee 100644
--- a/accel/tcg/cputlb.c
+++ b/accel/tcg/cputlb.c
@@ -1168,26 +1168,421 @@ static void *atomic_mmu_lookup(CPUArchState *env, target_ulong addr,
}
#ifdef TARGET_WORDS_BIGENDIAN
-# define TGT_BE(X) (X)
-# define TGT_LE(X) BSWAP(X)
+#define NEED_BE_BSWAP 0
+#define NEED_LE_BSWAP 1
#else
-# define TGT_BE(X) BSWAP(X)
-# define TGT_LE(X) (X)
+#define NEED_BE_BSWAP 1
+#define NEED_LE_BSWAP 0
#endif
-#define MMUSUFFIX _mmu
+/*
+ * Byte Swap Helper
+ *
+ * This should all dead code away depending on the build host and
+ * access type.
+ */
-#define DATA_SIZE 1
-#include "softmmu_template.h"
+static inline uint64_t handle_bswap(uint64_t val, int size, bool big_endian)
+{
+ if ((big_endian && NEED_BE_BSWAP) || (!big_endian && NEED_LE_BSWAP)) {
+ switch (size) {
+ case 1: return val;
+ case 2: return bswap16(val);
+ case 4: return bswap32(val);
+ case 8: return bswap64(val);
+ default:
+ g_assert_not_reached();
+ }
+ } else {
+ return val;
+ }
+}
-#define DATA_SIZE 2
-#include "softmmu_template.h"
+/*
+ * Load Helpers
+ *
+ * We support two different access types. SOFTMMU_CODE_ACCESS is
+ * specifically for reading instructions from system memory. It is
+ * called by the translation loop and in some helpers where the code
+ * is disassembled. It shouldn't be called directly by guest code.
+ */
-#define DATA_SIZE 4
-#include "softmmu_template.h"
+static uint64_t load_helper(CPUArchState *env, target_ulong addr,
+ TCGMemOpIdx oi, uintptr_t retaddr,
+ size_t size, bool big_endian,
+ bool code_read)
+{
+ uintptr_t mmu_idx = get_mmuidx(oi);
+ uintptr_t index = tlb_index(env, mmu_idx, addr);
+ CPUTLBEntry *entry = tlb_entry(env, mmu_idx, addr);
+ target_ulong tlb_addr = code_read ? entry->addr_code : entry->addr_read;
+ const size_t tlb_off = code_read ?
+ offsetof(CPUTLBEntry, addr_code) : offsetof(CPUTLBEntry, addr_read);
+ unsigned a_bits = get_alignment_bits(get_memop(oi));
+ void *haddr;
+ uint64_t res;
+
+ /* Handle CPU specific unaligned behaviour */
+ if (addr & ((1 << a_bits) - 1)) {
+ cpu_unaligned_access(ENV_GET_CPU(env), addr,
+ code_read ? MMU_INST_FETCH : MMU_DATA_LOAD,
+ mmu_idx, retaddr);
+ }
-#define DATA_SIZE 8
-#include "softmmu_template.h"
+ /* If the TLB entry is for a different page, reload and try again. */
+ if (!tlb_hit(tlb_addr, addr)) {
+ if (!victim_tlb_hit(env, mmu_idx, index, tlb_off,
+ addr & TARGET_PAGE_MASK)) {
+ tlb_fill(ENV_GET_CPU(env), addr, size,
+ code_read ? MMU_INST_FETCH : MMU_DATA_LOAD,
+ mmu_idx, retaddr);
+ index = tlb_index(env, mmu_idx, addr);
+ entry = tlb_entry(env, mmu_idx, addr);
+ }
+ tlb_addr = code_read ? entry->addr_code : entry->addr_read;
+ }
+
+ /* Handle an IO access. */
+ if (unlikely(tlb_addr & ~TARGET_PAGE_MASK)) {
+ CPUIOTLBEntry *iotlbentry = &env->iotlb[mmu_idx][index];
+ uint64_t tmp;
+
+ if ((addr & (size - 1)) != 0) {
+ goto do_unaligned_access;
+ }
+
+ tmp = io_readx(env, iotlbentry, mmu_idx, addr, retaddr,
+ tlb_addr & TLB_RECHECK,
+ code_read ? MMU_INST_FETCH : MMU_DATA_LOAD, size);
+ return handle_bswap(tmp, size, big_endian);
+ }
+
+ /* Handle slow unaligned access (it spans two pages or IO). */
+ if (size > 1
+ && unlikely((addr & ~TARGET_PAGE_MASK) + size - 1
+ >= TARGET_PAGE_SIZE)) {
+ target_ulong addr1, addr2;
+ tcg_target_ulong r1, r2;
+ unsigned shift;
+ do_unaligned_access:
+ addr1 = addr & ~(size - 1);
+ addr2 = addr1 + size;
+ r1 = load_helper(env, addr1, oi, retaddr, size, big_endian, code_read);
+ r2 = load_helper(env, addr2, oi, retaddr, size, big_endian, code_read);
+ shift = (addr & (size - 1)) * 8;
+
+ if (big_endian) {
+ /* Big-endian combine. */
+ res = (r1 << shift) | (r2 >> ((size * 8) - shift));
+ } else {
+ /* Little-endian combine. */
+ res = (r1 >> shift) | (r2 << ((size * 8) - shift));
+ }
+ return res & MAKE_64BIT_MASK(0, size * 8);
+ }
+
+ haddr = (void *)((uintptr_t)addr + entry->addend);
+
+ switch (size) {
+ case 1:
+ res = ldub_p(haddr);
+ break;
+ case 2:
+ if (big_endian) {
+ res = lduw_be_p(haddr);
+ } else {
+ res = lduw_le_p(haddr);
+ }
+ break;
+ case 4:
+ if (big_endian) {
+ res = (uint32_t)ldl_be_p(haddr);
+ } else {
+ res = (uint32_t)ldl_le_p(haddr);
+ }
+ break;
+ case 8:
+ if (big_endian) {
+ res = ldq_be_p(haddr);
+ } else {
+ res = ldq_le_p(haddr);
+ }
+ break;
+ default:
+ g_assert_not_reached();
+ }
+
+ return res;
+}
+
+/*
+ * For the benefit of TCG generated code, we want to avoid the
+ * complication of ABI-specific return type promotion and always
+ * return a value extended to the register size of the host. This is
+ * tcg_target_long, except in the case of a 32-bit host and 64-bit
+ * data, and for that we always have uint64_t.
+ *
+ * We don't bother with this widened value for SOFTMMU_CODE_ACCESS.
+ */
+
+tcg_target_ulong __attribute__((flatten))
+helper_ret_ldub_mmu(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi,
+ uintptr_t retaddr)
+{
+ return load_helper(env, addr, oi, retaddr, 1, false, false);
+}
+
+tcg_target_ulong __attribute__((flatten))
+helper_le_lduw_mmu(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi,
+ uintptr_t retaddr)
+{
+ return load_helper(env, addr, oi, retaddr, 2, false, false);
+}
+
+tcg_target_ulong __attribute__((flatten))
+helper_be_lduw_mmu(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi,
+ uintptr_t retaddr)
+{
+ return load_helper(env, addr, oi, retaddr, 2, true, false);
+}
+
+tcg_target_ulong __attribute__((flatten))
+helper_le_ldul_mmu(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi,
+ uintptr_t retaddr)
+{
+ return load_helper(env, addr, oi, retaddr, 4, false, false);
+}
+
+tcg_target_ulong __attribute__((flatten))
+helper_be_ldul_mmu(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi,
+ uintptr_t retaddr)
+{
+ return load_helper(env, addr, oi, retaddr, 4, true, false);
+}
+
+uint64_t __attribute__((flatten))
+helper_le_ldq_mmu(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi,
+ uintptr_t retaddr)
+{
+ return load_helper(env, addr, oi, retaddr, 8, false, false);
+}
+
+uint64_t __attribute__((flatten))
+helper_be_ldq_mmu(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi,
+ uintptr_t retaddr)
+{
+ return load_helper(env, addr, oi, retaddr, 8, true, false);
+}
+
+/*
+ * Provide signed versions of the load routines as well. We can of course
+ * avoid this for 64-bit data, or for 32-bit data on 32-bit host.
+ */
+
+
+tcg_target_ulong helper_ret_ldsb_mmu(CPUArchState *env, target_ulong addr,
+ TCGMemOpIdx oi, uintptr_t retaddr)
+{
+ return (int8_t)helper_ret_ldub_mmu(env, addr, oi, retaddr);
+}
+
+tcg_target_ulong helper_le_ldsw_mmu(CPUArchState *env, target_ulong addr,
+ TCGMemOpIdx oi, uintptr_t retaddr)
+{
+ return (int16_t)helper_le_lduw_mmu(env, addr, oi, retaddr);
+}
+
+tcg_target_ulong helper_be_ldsw_mmu(CPUArchState *env, target_ulong addr,
+ TCGMemOpIdx oi, uintptr_t retaddr)
+{
+ return (int16_t)helper_be_lduw_mmu(env, addr, oi, retaddr);
+}
+
+tcg_target_ulong helper_le_ldsl_mmu(CPUArchState *env, target_ulong addr,
+ TCGMemOpIdx oi, uintptr_t retaddr)
+{
+ return (int32_t)helper_le_ldul_mmu(env, addr, oi, retaddr);
+}
+
+tcg_target_ulong helper_be_ldsl_mmu(CPUArchState *env, target_ulong addr,
+ TCGMemOpIdx oi, uintptr_t retaddr)
+{
+ return (int32_t)helper_be_ldul_mmu(env, addr, oi, retaddr);
+}
+
+/*
+ * Store Helpers
+ */
+
+static void store_helper(CPUArchState *env, target_ulong addr, uint64_t val,
+ TCGMemOpIdx oi, uintptr_t retaddr, size_t size,
+ bool big_endian)
+{
+ uintptr_t mmu_idx = get_mmuidx(oi);
+ uintptr_t index = tlb_index(env, mmu_idx, addr);
+ CPUTLBEntry *entry = tlb_entry(env, mmu_idx, addr);
+ target_ulong tlb_addr = tlb_addr_write(entry);
+ const size_t tlb_off = offsetof(CPUTLBEntry, addr_write);
+ unsigned a_bits = get_alignment_bits(get_memop(oi));
+ void *haddr;
+
+ /* Handle CPU specific unaligned behaviour */
+ if (addr & ((1 << a_bits) - 1)) {
+ cpu_unaligned_access(ENV_GET_CPU(env), addr, MMU_DATA_STORE,
+ mmu_idx, retaddr);
+ }
+
+ /* If the TLB entry is for a different page, reload and try again. */
+ if (!tlb_hit(tlb_addr, addr)) {
+ if (!victim_tlb_hit(env, mmu_idx, index, tlb_off,
+ addr & TARGET_PAGE_MASK)) {
+ tlb_fill(ENV_GET_CPU(env), addr, size, MMU_DATA_STORE,
+ mmu_idx, retaddr);
+ index = tlb_index(env, mmu_idx, addr);
+ entry = tlb_entry(env, mmu_idx, addr);
+ }
+ tlb_addr = tlb_addr_write(entry) & ~TLB_INVALID_MASK;
+ }
+
+ /* Handle an IO access. */
+ if (unlikely(tlb_addr & ~TARGET_PAGE_MASK)) {
+ CPUIOTLBEntry *iotlbentry = &env->iotlb[mmu_idx][index];
+
+ if ((addr & (size - 1)) != 0) {
+ goto do_unaligned_access;
+ }
+
+ io_writex(env, iotlbentry, mmu_idx,
+ handle_bswap(val, size, big_endian),
+ addr, retaddr, tlb_addr & TLB_RECHECK, size);
+ return;
+ }
+
+ /* Handle slow unaligned access (it spans two pages or IO). */
+ if (size > 1
+ && unlikely((addr & ~TARGET_PAGE_MASK) + size - 1
+ >= TARGET_PAGE_SIZE)) {
+ int i;
+ uintptr_t index2;
+ CPUTLBEntry *entry2;
+ target_ulong page2, tlb_addr2;
+ do_unaligned_access:
+ /*
+ * Ensure the second page is in the TLB. Note that the first page
+ * is already guaranteed to be filled, and that the second page
+ * cannot evict the first.
+ */
+ page2 = (addr + size) & TARGET_PAGE_MASK;
+ index2 = tlb_index(env, mmu_idx, page2);
+ entry2 = tlb_entry(env, mmu_idx, page2);
+ tlb_addr2 = tlb_addr_write(entry2);
+ if (!tlb_hit_page(tlb_addr2, page2)
+ && !victim_tlb_hit(env, mmu_idx, index2, tlb_off,
+ page2 & TARGET_PAGE_MASK)) {
+ tlb_fill(ENV_GET_CPU(env), page2, size, MMU_DATA_STORE,
+ mmu_idx, retaddr);
+ }
+
+ /*
+ * XXX: not efficient, but simple.
+ * This loop must go in the forward direction to avoid issues
+ * with self-modifying code in Windows 64-bit.
+ */
+ for (i = 0; i < size; ++i) {
+ uint8_t val8;
+ if (big_endian) {
+ /* Big-endian extract. */
+ val8 = val >> (((size - 1) * 8) - (i * 8));
+ } else {
+ /* Little-endian extract. */
+ val8 = val >> (i * 8);
+ }
+ store_helper(env, addr + i, val8, oi, retaddr, 1, big_endian);
+ }
+ return;
+ }
+
+ haddr = (void *)((uintptr_t)addr + entry->addend);
+
+ switch (size) {
+ case 1:
+ stb_p(haddr, val);
+ break;
+ case 2:
+ if (big_endian) {
+ stw_be_p(haddr, val);
+ } else {
+ stw_le_p(haddr, val);
+ }
+ break;
+ case 4:
+ if (big_endian) {
+ stl_be_p(haddr, val);
+ } else {
+ stl_le_p(haddr, val);
+ }
+ break;
+ case 8:
+ if (big_endian) {
+ stq_be_p(haddr, val);
+ } else {
+ stq_le_p(haddr, val);
+ }
+ break;
+ default:
+ g_assert_not_reached();
+ break;
+ }
+}
+
+void __attribute__((flatten))
+helper_ret_stb_mmu(CPUArchState *env, target_ulong addr, uint8_t val,
+ TCGMemOpIdx oi, uintptr_t retaddr)
+{
+ store_helper(env, addr, val, oi, retaddr, 1, false);
+}
+
+void __attribute__((flatten))
+helper_le_stw_mmu(CPUArchState *env, target_ulong addr, uint16_t val,
+ TCGMemOpIdx oi, uintptr_t retaddr)
+{
+ store_helper(env, addr, val, oi, retaddr, 2, false);
+}
+
+void __attribute__((flatten))
+helper_be_stw_mmu(CPUArchState *env, target_ulong addr, uint16_t val,
+ TCGMemOpIdx oi, uintptr_t retaddr)
+{
+ store_helper(env, addr, val, oi, retaddr, 2, true);
+}
+
+void __attribute__((flatten))
+helper_le_stl_mmu(CPUArchState *env, target_ulong addr, uint32_t val,
+ TCGMemOpIdx oi, uintptr_t retaddr)
+{
+ store_helper(env, addr, val, oi, retaddr, 4, false);
+}
+
+void __attribute__((flatten))
+helper_be_stl_mmu(CPUArchState *env, target_ulong addr, uint32_t val,
+ TCGMemOpIdx oi, uintptr_t retaddr)
+{
+ store_helper(env, addr, val, oi, retaddr, 4, true);
+}
+
+void __attribute__((flatten))
+helper_le_stq_mmu(CPUArchState *env, target_ulong addr, uint64_t val,
+ TCGMemOpIdx oi, uintptr_t retaddr)
+{
+ store_helper(env, addr, val, oi, retaddr, 8, false);
+}
+
+void __attribute__((flatten))
+helper_be_stq_mmu(CPUArchState *env, target_ulong addr, uint64_t val,
+ TCGMemOpIdx oi, uintptr_t retaddr)
+{
+ store_helper(env, addr, val, oi, retaddr, 8, true);
+}
/* First set of helpers allows passing in of OI and RETADDR. This makes
them callable from other helpers. */
@@ -1248,20 +1643,51 @@ static void *atomic_mmu_lookup(CPUArchState *env, target_ulong addr,
/* Code access functions. */
-#undef MMUSUFFIX
-#define MMUSUFFIX _cmmu
-#undef GETPC
-#define GETPC() ((uintptr_t)0)
-#define SOFTMMU_CODE_ACCESS
+uint8_t __attribute__((flatten))
+helper_ret_ldb_cmmu(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi,
+ uintptr_t retaddr)
+{
+ return load_helper(env, addr, oi, retaddr, 1, false, true);
+}
-#define DATA_SIZE 1
-#include "softmmu_template.h"
+uint16_t __attribute__((flatten))
+helper_le_ldw_cmmu(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi,
+ uintptr_t retaddr)
+{
+ return load_helper(env, addr, oi, retaddr, 2, false, true);
+}
-#define DATA_SIZE 2
-#include "softmmu_template.h"
+uint16_t __attribute__((flatten))
+helper_be_ldw_cmmu(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi,
+ uintptr_t retaddr)
+{
+ return load_helper(env, addr, oi, retaddr, 2, true, true);
+}
-#define DATA_SIZE 4
-#include "softmmu_template.h"
+uint32_t __attribute__((flatten))
+helper_le_ldl_cmmu(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi,
+ uintptr_t retaddr)
+{
+ return load_helper(env, addr, oi, retaddr, 4, false, true);
+}
-#define DATA_SIZE 8
-#include "softmmu_template.h"
+uint32_t __attribute__((flatten))
+helper_be_ldl_cmmu(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi,
+ uintptr_t retaddr)
+{
+ return load_helper(env, addr, oi, retaddr, 4, true, true);
+}
+
+uint64_t __attribute__((flatten))
+helper_le_ldq_cmmu(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi,
+ uintptr_t retaddr)
+{
+ return load_helper(env, addr, oi, retaddr, 8, false, true);
+}
+
+uint64_t __attribute__((flatten))
+helper_be_ldq_cmmu(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi,
+ uintptr_t retaddr)
+{
+ return load_helper(env, addr, oi, retaddr, 8, true, true);
+}
--
2.20.1
^ permalink raw reply related [flat|nested] 53+ messages in thread
* [Qemu-devel] [PATCH v5 08/15] cputlb: Move TLB_RECHECK handling into load/store_helper
@ 2019-04-30 16:52 ` Alex Bennée
0 siblings, 0 replies; 53+ messages in thread
From: Alex Bennée @ 2019-04-30 16:52 UTC (permalink / raw)
To: qemu-devel
Cc: qemu-arm, mark.cave-ayland, cota, Richard Henderson, Alex Bennée
From: Richard Henderson <richard.henderson@linaro.org>
Having this in io_readx/io_writex meant that we forgot to
re-compute index after tlb_fill. It also means we can use
the normal aligned memory load path. It also fixes a bug
in that we had cached a use of index across a tlb_fill.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
---
accel/tcg/cputlb.c | 126 ++++++++++++++++++++-------------------------
1 file changed, 55 insertions(+), 71 deletions(-)
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
index 12f21865ee..9c04eb1687 100644
--- a/accel/tcg/cputlb.c
+++ b/accel/tcg/cputlb.c
@@ -856,9 +856,8 @@ static inline ram_addr_t qemu_ram_addr_from_host_nofail(void *ptr)
}
static uint64_t io_readx(CPUArchState *env, CPUIOTLBEntry *iotlbentry,
- int mmu_idx,
- target_ulong addr, uintptr_t retaddr,
- bool recheck, MMUAccessType access_type, int size)
+ int mmu_idx, target_ulong addr, uintptr_t retaddr,
+ MMUAccessType access_type, int size)
{
CPUState *cpu = ENV_GET_CPU(env);
hwaddr mr_offset;
@@ -868,30 +867,6 @@ static uint64_t io_readx(CPUArchState *env, CPUIOTLBEntry *iotlbentry,
bool locked = false;
MemTxResult r;
- if (recheck) {
- /*
- * This is a TLB_RECHECK access, where the MMU protection
- * covers a smaller range than a target page, and we must
- * repeat the MMU check here. This tlb_fill() call might
- * longjump out if this access should cause a guest exception.
- */
- CPUTLBEntry *entry;
- target_ulong tlb_addr;
-
- tlb_fill(cpu, addr, size, access_type, mmu_idx, retaddr);
-
- entry = tlb_entry(env, mmu_idx, addr);
- tlb_addr = (access_type == MMU_DATA_LOAD ?
- entry->addr_read : entry->addr_code);
- if (!(tlb_addr & ~(TARGET_PAGE_MASK | TLB_RECHECK))) {
- /* RAM access */
- uintptr_t haddr = addr + entry->addend;
-
- return ldn_p((void *)haddr, size);
- }
- /* Fall through for handling IO accesses */
- }
-
section = iotlb_to_section(cpu, iotlbentry->addr, iotlbentry->attrs);
mr = section->mr;
mr_offset = (iotlbentry->addr & TARGET_PAGE_MASK) + addr;
@@ -925,9 +900,8 @@ static uint64_t io_readx(CPUArchState *env, CPUIOTLBEntry *iotlbentry,
}
static void io_writex(CPUArchState *env, CPUIOTLBEntry *iotlbentry,
- int mmu_idx,
- uint64_t val, target_ulong addr,
- uintptr_t retaddr, bool recheck, int size)
+ int mmu_idx, uint64_t val, target_ulong addr,
+ uintptr_t retaddr, int size)
{
CPUState *cpu = ENV_GET_CPU(env);
hwaddr mr_offset;
@@ -936,30 +910,6 @@ static void io_writex(CPUArchState *env, CPUIOTLBEntry *iotlbentry,
bool locked = false;
MemTxResult r;
- if (recheck) {
- /*
- * This is a TLB_RECHECK access, where the MMU protection
- * covers a smaller range than a target page, and we must
- * repeat the MMU check here. This tlb_fill() call might
- * longjump out if this access should cause a guest exception.
- */
- CPUTLBEntry *entry;
- target_ulong tlb_addr;
-
- tlb_fill(cpu, addr, size, MMU_DATA_STORE, mmu_idx, retaddr);
-
- entry = tlb_entry(env, mmu_idx, addr);
- tlb_addr = tlb_addr_write(entry);
- if (!(tlb_addr & ~(TARGET_PAGE_MASK | TLB_RECHECK))) {
- /* RAM access */
- uintptr_t haddr = addr + entry->addend;
-
- stn_p((void *)haddr, size, val);
- return;
- }
- /* Fall through for handling IO accesses */
- }
-
section = iotlb_to_section(cpu, iotlbentry->addr, iotlbentry->attrs);
mr = section->mr;
mr_offset = (iotlbentry->addr & TARGET_PAGE_MASK) + addr;
@@ -1218,14 +1168,15 @@ static uint64_t load_helper(CPUArchState *env, target_ulong addr,
target_ulong tlb_addr = code_read ? entry->addr_code : entry->addr_read;
const size_t tlb_off = code_read ?
offsetof(CPUTLBEntry, addr_code) : offsetof(CPUTLBEntry, addr_read);
+ const MMUAccessType access_type =
+ code_read ? MMU_INST_FETCH : MMU_DATA_LOAD;
unsigned a_bits = get_alignment_bits(get_memop(oi));
void *haddr;
uint64_t res;
/* Handle CPU specific unaligned behaviour */
if (addr & ((1 << a_bits) - 1)) {
- cpu_unaligned_access(ENV_GET_CPU(env), addr,
- code_read ? MMU_INST_FETCH : MMU_DATA_LOAD,
+ cpu_unaligned_access(ENV_GET_CPU(env), addr, access_type,
mmu_idx, retaddr);
}
@@ -1234,8 +1185,7 @@ static uint64_t load_helper(CPUArchState *env, target_ulong addr,
if (!victim_tlb_hit(env, mmu_idx, index, tlb_off,
addr & TARGET_PAGE_MASK)) {
tlb_fill(ENV_GET_CPU(env), addr, size,
- code_read ? MMU_INST_FETCH : MMU_DATA_LOAD,
- mmu_idx, retaddr);
+ access_type, mmu_idx, retaddr);
index = tlb_index(env, mmu_idx, addr);
entry = tlb_entry(env, mmu_idx, addr);
}
@@ -1244,17 +1194,33 @@ static uint64_t load_helper(CPUArchState *env, target_ulong addr,
/* Handle an IO access. */
if (unlikely(tlb_addr & ~TARGET_PAGE_MASK)) {
- CPUIOTLBEntry *iotlbentry = &env->iotlb[mmu_idx][index];
- uint64_t tmp;
-
if ((addr & (size - 1)) != 0) {
goto do_unaligned_access;
}
- tmp = io_readx(env, iotlbentry, mmu_idx, addr, retaddr,
- tlb_addr & TLB_RECHECK,
- code_read ? MMU_INST_FETCH : MMU_DATA_LOAD, size);
- return handle_bswap(tmp, size, big_endian);
+ if (tlb_addr & TLB_RECHECK) {
+ /*
+ * This is a TLB_RECHECK access, where the MMU protection
+ * covers a smaller range than a target page, and we must
+ * repeat the MMU check here. This tlb_fill() call might
+ * longjump out if this access should cause a guest exception.
+ */
+ tlb_fill(ENV_GET_CPU(env), addr, size,
+ access_type, mmu_idx, retaddr);
+ index = tlb_index(env, mmu_idx, addr);
+ entry = tlb_entry(env, mmu_idx, addr);
+
+ tlb_addr = code_read ? entry->addr_code : entry->addr_read;
+ tlb_addr &= ~TLB_RECHECK;
+ if (!(tlb_addr & ~TARGET_PAGE_MASK)) {
+ /* RAM access */
+ goto do_aligned_access;
+ }
+ }
+
+ res = io_readx(env, &env->iotlb[mmu_idx][index], mmu_idx, addr,
+ retaddr, access_type, size);
+ return handle_bswap(res, size, big_endian);
}
/* Handle slow unaligned access (it spans two pages or IO). */
@@ -1281,8 +1247,8 @@ static uint64_t load_helper(CPUArchState *env, target_ulong addr,
return res & MAKE_64BIT_MASK(0, size * 8);
}
+ do_aligned_access:
haddr = (void *)((uintptr_t)addr + entry->addend);
-
switch (size) {
case 1:
res = ldub_p(haddr);
@@ -1446,15 +1412,33 @@ static void store_helper(CPUArchState *env, target_ulong addr, uint64_t val,
/* Handle an IO access. */
if (unlikely(tlb_addr & ~TARGET_PAGE_MASK)) {
- CPUIOTLBEntry *iotlbentry = &env->iotlb[mmu_idx][index];
-
if ((addr & (size - 1)) != 0) {
goto do_unaligned_access;
}
- io_writex(env, iotlbentry, mmu_idx,
+ if (tlb_addr & TLB_RECHECK) {
+ /*
+ * This is a TLB_RECHECK access, where the MMU protection
+ * covers a smaller range than a target page, and we must
+ * repeat the MMU check here. This tlb_fill() call might
+ * longjump out if this access should cause a guest exception.
+ */
+ tlb_fill(ENV_GET_CPU(env), addr, size, MMU_DATA_STORE,
+ mmu_idx, retaddr);
+ index = tlb_index(env, mmu_idx, addr);
+ entry = tlb_entry(env, mmu_idx, addr);
+
+ tlb_addr = tlb_addr_write(entry);
+ tlb_addr &= ~TLB_RECHECK;
+ if (!(tlb_addr & ~TARGET_PAGE_MASK)) {
+ /* RAM access */
+ goto do_aligned_access;
+ }
+ }
+
+ io_writex(env, &env->iotlb[mmu_idx][index], mmu_idx,
handle_bswap(val, size, big_endian),
- addr, retaddr, tlb_addr & TLB_RECHECK, size);
+ addr, retaddr, size);
return;
}
@@ -1502,8 +1486,8 @@ static void store_helper(CPUArchState *env, target_ulong addr, uint64_t val,
return;
}
+ do_aligned_access:
haddr = (void *)((uintptr_t)addr + entry->addend);
-
switch (size) {
case 1:
stb_p(haddr, val);
--
2.20.1
^ permalink raw reply related [flat|nested] 53+ messages in thread
* [Qemu-devel] [PATCH v5 08/15] cputlb: Move TLB_RECHECK handling into load/store_helper
@ 2019-04-30 16:52 ` Alex Bennée
0 siblings, 0 replies; 53+ messages in thread
From: Alex Bennée @ 2019-04-30 16:52 UTC (permalink / raw)
To: qemu-devel
Cc: Alex Bennée, Richard Henderson, qemu-arm, mark.cave-ayland, cota
From: Richard Henderson <richard.henderson@linaro.org>
Having this in io_readx/io_writex meant that we forgot to
re-compute index after tlb_fill. It also means we can use
the normal aligned memory load path. It also fixes a bug
in that we had cached a use of index across a tlb_fill.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
---
accel/tcg/cputlb.c | 126 ++++++++++++++++++++-------------------------
1 file changed, 55 insertions(+), 71 deletions(-)
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
index 12f21865ee..9c04eb1687 100644
--- a/accel/tcg/cputlb.c
+++ b/accel/tcg/cputlb.c
@@ -856,9 +856,8 @@ static inline ram_addr_t qemu_ram_addr_from_host_nofail(void *ptr)
}
static uint64_t io_readx(CPUArchState *env, CPUIOTLBEntry *iotlbentry,
- int mmu_idx,
- target_ulong addr, uintptr_t retaddr,
- bool recheck, MMUAccessType access_type, int size)
+ int mmu_idx, target_ulong addr, uintptr_t retaddr,
+ MMUAccessType access_type, int size)
{
CPUState *cpu = ENV_GET_CPU(env);
hwaddr mr_offset;
@@ -868,30 +867,6 @@ static uint64_t io_readx(CPUArchState *env, CPUIOTLBEntry *iotlbentry,
bool locked = false;
MemTxResult r;
- if (recheck) {
- /*
- * This is a TLB_RECHECK access, where the MMU protection
- * covers a smaller range than a target page, and we must
- * repeat the MMU check here. This tlb_fill() call might
- * longjump out if this access should cause a guest exception.
- */
- CPUTLBEntry *entry;
- target_ulong tlb_addr;
-
- tlb_fill(cpu, addr, size, access_type, mmu_idx, retaddr);
-
- entry = tlb_entry(env, mmu_idx, addr);
- tlb_addr = (access_type == MMU_DATA_LOAD ?
- entry->addr_read : entry->addr_code);
- if (!(tlb_addr & ~(TARGET_PAGE_MASK | TLB_RECHECK))) {
- /* RAM access */
- uintptr_t haddr = addr + entry->addend;
-
- return ldn_p((void *)haddr, size);
- }
- /* Fall through for handling IO accesses */
- }
-
section = iotlb_to_section(cpu, iotlbentry->addr, iotlbentry->attrs);
mr = section->mr;
mr_offset = (iotlbentry->addr & TARGET_PAGE_MASK) + addr;
@@ -925,9 +900,8 @@ static uint64_t io_readx(CPUArchState *env, CPUIOTLBEntry *iotlbentry,
}
static void io_writex(CPUArchState *env, CPUIOTLBEntry *iotlbentry,
- int mmu_idx,
- uint64_t val, target_ulong addr,
- uintptr_t retaddr, bool recheck, int size)
+ int mmu_idx, uint64_t val, target_ulong addr,
+ uintptr_t retaddr, int size)
{
CPUState *cpu = ENV_GET_CPU(env);
hwaddr mr_offset;
@@ -936,30 +910,6 @@ static void io_writex(CPUArchState *env, CPUIOTLBEntry *iotlbentry,
bool locked = false;
MemTxResult r;
- if (recheck) {
- /*
- * This is a TLB_RECHECK access, where the MMU protection
- * covers a smaller range than a target page, and we must
- * repeat the MMU check here. This tlb_fill() call might
- * longjump out if this access should cause a guest exception.
- */
- CPUTLBEntry *entry;
- target_ulong tlb_addr;
-
- tlb_fill(cpu, addr, size, MMU_DATA_STORE, mmu_idx, retaddr);
-
- entry = tlb_entry(env, mmu_idx, addr);
- tlb_addr = tlb_addr_write(entry);
- if (!(tlb_addr & ~(TARGET_PAGE_MASK | TLB_RECHECK))) {
- /* RAM access */
- uintptr_t haddr = addr + entry->addend;
-
- stn_p((void *)haddr, size, val);
- return;
- }
- /* Fall through for handling IO accesses */
- }
-
section = iotlb_to_section(cpu, iotlbentry->addr, iotlbentry->attrs);
mr = section->mr;
mr_offset = (iotlbentry->addr & TARGET_PAGE_MASK) + addr;
@@ -1218,14 +1168,15 @@ static uint64_t load_helper(CPUArchState *env, target_ulong addr,
target_ulong tlb_addr = code_read ? entry->addr_code : entry->addr_read;
const size_t tlb_off = code_read ?
offsetof(CPUTLBEntry, addr_code) : offsetof(CPUTLBEntry, addr_read);
+ const MMUAccessType access_type =
+ code_read ? MMU_INST_FETCH : MMU_DATA_LOAD;
unsigned a_bits = get_alignment_bits(get_memop(oi));
void *haddr;
uint64_t res;
/* Handle CPU specific unaligned behaviour */
if (addr & ((1 << a_bits) - 1)) {
- cpu_unaligned_access(ENV_GET_CPU(env), addr,
- code_read ? MMU_INST_FETCH : MMU_DATA_LOAD,
+ cpu_unaligned_access(ENV_GET_CPU(env), addr, access_type,
mmu_idx, retaddr);
}
@@ -1234,8 +1185,7 @@ static uint64_t load_helper(CPUArchState *env, target_ulong addr,
if (!victim_tlb_hit(env, mmu_idx, index, tlb_off,
addr & TARGET_PAGE_MASK)) {
tlb_fill(ENV_GET_CPU(env), addr, size,
- code_read ? MMU_INST_FETCH : MMU_DATA_LOAD,
- mmu_idx, retaddr);
+ access_type, mmu_idx, retaddr);
index = tlb_index(env, mmu_idx, addr);
entry = tlb_entry(env, mmu_idx, addr);
}
@@ -1244,17 +1194,33 @@ static uint64_t load_helper(CPUArchState *env, target_ulong addr,
/* Handle an IO access. */
if (unlikely(tlb_addr & ~TARGET_PAGE_MASK)) {
- CPUIOTLBEntry *iotlbentry = &env->iotlb[mmu_idx][index];
- uint64_t tmp;
-
if ((addr & (size - 1)) != 0) {
goto do_unaligned_access;
}
- tmp = io_readx(env, iotlbentry, mmu_idx, addr, retaddr,
- tlb_addr & TLB_RECHECK,
- code_read ? MMU_INST_FETCH : MMU_DATA_LOAD, size);
- return handle_bswap(tmp, size, big_endian);
+ if (tlb_addr & TLB_RECHECK) {
+ /*
+ * This is a TLB_RECHECK access, where the MMU protection
+ * covers a smaller range than a target page, and we must
+ * repeat the MMU check here. This tlb_fill() call might
+ * longjump out if this access should cause a guest exception.
+ */
+ tlb_fill(ENV_GET_CPU(env), addr, size,
+ access_type, mmu_idx, retaddr);
+ index = tlb_index(env, mmu_idx, addr);
+ entry = tlb_entry(env, mmu_idx, addr);
+
+ tlb_addr = code_read ? entry->addr_code : entry->addr_read;
+ tlb_addr &= ~TLB_RECHECK;
+ if (!(tlb_addr & ~TARGET_PAGE_MASK)) {
+ /* RAM access */
+ goto do_aligned_access;
+ }
+ }
+
+ res = io_readx(env, &env->iotlb[mmu_idx][index], mmu_idx, addr,
+ retaddr, access_type, size);
+ return handle_bswap(res, size, big_endian);
}
/* Handle slow unaligned access (it spans two pages or IO). */
@@ -1281,8 +1247,8 @@ static uint64_t load_helper(CPUArchState *env, target_ulong addr,
return res & MAKE_64BIT_MASK(0, size * 8);
}
+ do_aligned_access:
haddr = (void *)((uintptr_t)addr + entry->addend);
-
switch (size) {
case 1:
res = ldub_p(haddr);
@@ -1446,15 +1412,33 @@ static void store_helper(CPUArchState *env, target_ulong addr, uint64_t val,
/* Handle an IO access. */
if (unlikely(tlb_addr & ~TARGET_PAGE_MASK)) {
- CPUIOTLBEntry *iotlbentry = &env->iotlb[mmu_idx][index];
-
if ((addr & (size - 1)) != 0) {
goto do_unaligned_access;
}
- io_writex(env, iotlbentry, mmu_idx,
+ if (tlb_addr & TLB_RECHECK) {
+ /*
+ * This is a TLB_RECHECK access, where the MMU protection
+ * covers a smaller range than a target page, and we must
+ * repeat the MMU check here. This tlb_fill() call might
+ * longjump out if this access should cause a guest exception.
+ */
+ tlb_fill(ENV_GET_CPU(env), addr, size, MMU_DATA_STORE,
+ mmu_idx, retaddr);
+ index = tlb_index(env, mmu_idx, addr);
+ entry = tlb_entry(env, mmu_idx, addr);
+
+ tlb_addr = tlb_addr_write(entry);
+ tlb_addr &= ~TLB_RECHECK;
+ if (!(tlb_addr & ~TARGET_PAGE_MASK)) {
+ /* RAM access */
+ goto do_aligned_access;
+ }
+ }
+
+ io_writex(env, &env->iotlb[mmu_idx][index], mmu_idx,
handle_bswap(val, size, big_endian),
- addr, retaddr, tlb_addr & TLB_RECHECK, size);
+ addr, retaddr, size);
return;
}
@@ -1502,8 +1486,8 @@ static void store_helper(CPUArchState *env, target_ulong addr, uint64_t val,
return;
}
+ do_aligned_access:
haddr = (void *)((uintptr_t)addr + entry->addend);
-
switch (size) {
case 1:
stb_p(haddr, val);
--
2.20.1
^ permalink raw reply related [flat|nested] 53+ messages in thread
* [Qemu-devel] [PATCH v5 09/15] accel/tcg: remove softmmu_template.h
@ 2019-04-30 16:52 ` Alex Bennée
0 siblings, 0 replies; 53+ messages in thread
From: Alex Bennée @ 2019-04-30 16:52 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm, mark.cave-ayland, cota, Alex Bennée
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
---
accel/tcg/softmmu_template.h | 454 -----------------------------------
1 file changed, 454 deletions(-)
delete mode 100644 accel/tcg/softmmu_template.h
diff --git a/accel/tcg/softmmu_template.h b/accel/tcg/softmmu_template.h
deleted file mode 100644
index e970a8b378..0000000000
--- a/accel/tcg/softmmu_template.h
+++ /dev/null
@@ -1,454 +0,0 @@
-/*
- * Software MMU support
- *
- * Generate helpers used by TCG for qemu_ld/st ops and code load
- * functions.
- *
- * Included from target op helpers and exec.c.
- *
- * Copyright (c) 2003 Fabrice Bellard
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see <http://www.gnu.org/licenses/>.
- */
-#if DATA_SIZE == 8
-#define SUFFIX q
-#define LSUFFIX q
-#define SDATA_TYPE int64_t
-#define DATA_TYPE uint64_t
-#elif DATA_SIZE == 4
-#define SUFFIX l
-#define LSUFFIX l
-#define SDATA_TYPE int32_t
-#define DATA_TYPE uint32_t
-#elif DATA_SIZE == 2
-#define SUFFIX w
-#define LSUFFIX uw
-#define SDATA_TYPE int16_t
-#define DATA_TYPE uint16_t
-#elif DATA_SIZE == 1
-#define SUFFIX b
-#define LSUFFIX ub
-#define SDATA_TYPE int8_t
-#define DATA_TYPE uint8_t
-#else
-#error unsupported data size
-#endif
-
-
-/* For the benefit of TCG generated code, we want to avoid the complication
- of ABI-specific return type promotion and always return a value extended
- to the register size of the host. This is tcg_target_long, except in the
- case of a 32-bit host and 64-bit data, and for that we always have
- uint64_t. Don't bother with this widened value for SOFTMMU_CODE_ACCESS. */
-#if defined(SOFTMMU_CODE_ACCESS) || DATA_SIZE == 8
-# define WORD_TYPE DATA_TYPE
-# define USUFFIX SUFFIX
-#else
-# define WORD_TYPE tcg_target_ulong
-# define USUFFIX glue(u, SUFFIX)
-# define SSUFFIX glue(s, SUFFIX)
-#endif
-
-#ifdef SOFTMMU_CODE_ACCESS
-#define READ_ACCESS_TYPE MMU_INST_FETCH
-#define ADDR_READ addr_code
-#else
-#define READ_ACCESS_TYPE MMU_DATA_LOAD
-#define ADDR_READ addr_read
-#endif
-
-#if DATA_SIZE == 8
-# define BSWAP(X) bswap64(X)
-#elif DATA_SIZE == 4
-# define BSWAP(X) bswap32(X)
-#elif DATA_SIZE == 2
-# define BSWAP(X) bswap16(X)
-#else
-# define BSWAP(X) (X)
-#endif
-
-#if DATA_SIZE == 1
-# define helper_le_ld_name glue(glue(helper_ret_ld, USUFFIX), MMUSUFFIX)
-# define helper_be_ld_name helper_le_ld_name
-# define helper_le_lds_name glue(glue(helper_ret_ld, SSUFFIX), MMUSUFFIX)
-# define helper_be_lds_name helper_le_lds_name
-# define helper_le_st_name glue(glue(helper_ret_st, SUFFIX), MMUSUFFIX)
-# define helper_be_st_name helper_le_st_name
-#else
-# define helper_le_ld_name glue(glue(helper_le_ld, USUFFIX), MMUSUFFIX)
-# define helper_be_ld_name glue(glue(helper_be_ld, USUFFIX), MMUSUFFIX)
-# define helper_le_lds_name glue(glue(helper_le_ld, SSUFFIX), MMUSUFFIX)
-# define helper_be_lds_name glue(glue(helper_be_ld, SSUFFIX), MMUSUFFIX)
-# define helper_le_st_name glue(glue(helper_le_st, SUFFIX), MMUSUFFIX)
-# define helper_be_st_name glue(glue(helper_be_st, SUFFIX), MMUSUFFIX)
-#endif
-
-#ifndef SOFTMMU_CODE_ACCESS
-static inline DATA_TYPE glue(io_read, SUFFIX)(CPUArchState *env,
- size_t mmu_idx, size_t index,
- target_ulong addr,
- uintptr_t retaddr,
- bool recheck,
- MMUAccessType access_type)
-{
- CPUIOTLBEntry *iotlbentry = &env->iotlb[mmu_idx][index];
- return io_readx(env, iotlbentry, mmu_idx, addr, retaddr, recheck,
- access_type, DATA_SIZE);
-}
-#endif
-
-WORD_TYPE helper_le_ld_name(CPUArchState *env, target_ulong addr,
- TCGMemOpIdx oi, uintptr_t retaddr)
-{
- uintptr_t mmu_idx = get_mmuidx(oi);
- uintptr_t index = tlb_index(env, mmu_idx, addr);
- CPUTLBEntry *entry = tlb_entry(env, mmu_idx, addr);
- target_ulong tlb_addr = entry->ADDR_READ;
- unsigned a_bits = get_alignment_bits(get_memop(oi));
- uintptr_t haddr;
- DATA_TYPE res;
-
- if (addr & ((1 << a_bits) - 1)) {
- cpu_unaligned_access(ENV_GET_CPU(env), addr, READ_ACCESS_TYPE,
- mmu_idx, retaddr);
- }
-
- /* If the TLB entry is for a different page, reload and try again. */
- if (!tlb_hit(tlb_addr, addr)) {
- if (!VICTIM_TLB_HIT(ADDR_READ, addr)) {
- tlb_fill(ENV_GET_CPU(env), addr, DATA_SIZE, READ_ACCESS_TYPE,
- mmu_idx, retaddr);
- index = tlb_index(env, mmu_idx, addr);
- entry = tlb_entry(env, mmu_idx, addr);
- }
- tlb_addr = entry->ADDR_READ;
- }
-
- /* Handle an IO access. */
- if (unlikely(tlb_addr & ~TARGET_PAGE_MASK)) {
- if ((addr & (DATA_SIZE - 1)) != 0) {
- goto do_unaligned_access;
- }
-
- /* ??? Note that the io helpers always read data in the target
- byte ordering. We should push the LE/BE request down into io. */
- res = glue(io_read, SUFFIX)(env, mmu_idx, index, addr, retaddr,
- tlb_addr & TLB_RECHECK,
- READ_ACCESS_TYPE);
- res = TGT_LE(res);
- return res;
- }
-
- /* Handle slow unaligned access (it spans two pages or IO). */
- if (DATA_SIZE > 1
- && unlikely((addr & ~TARGET_PAGE_MASK) + DATA_SIZE - 1
- >= TARGET_PAGE_SIZE)) {
- target_ulong addr1, addr2;
- DATA_TYPE res1, res2;
- unsigned shift;
- do_unaligned_access:
- addr1 = addr & ~(DATA_SIZE - 1);
- addr2 = addr1 + DATA_SIZE;
- res1 = helper_le_ld_name(env, addr1, oi, retaddr);
- res2 = helper_le_ld_name(env, addr2, oi, retaddr);
- shift = (addr & (DATA_SIZE - 1)) * 8;
-
- /* Little-endian combine. */
- res = (res1 >> shift) | (res2 << ((DATA_SIZE * 8) - shift));
- return res;
- }
-
- haddr = addr + entry->addend;
-#if DATA_SIZE == 1
- res = glue(glue(ld, LSUFFIX), _p)((uint8_t *)haddr);
-#else
- res = glue(glue(ld, LSUFFIX), _le_p)((uint8_t *)haddr);
-#endif
- return res;
-}
-
-#if DATA_SIZE > 1
-WORD_TYPE helper_be_ld_name(CPUArchState *env, target_ulong addr,
- TCGMemOpIdx oi, uintptr_t retaddr)
-{
- uintptr_t mmu_idx = get_mmuidx(oi);
- uintptr_t index = tlb_index(env, mmu_idx, addr);
- CPUTLBEntry *entry = tlb_entry(env, mmu_idx, addr);
- target_ulong tlb_addr = entry->ADDR_READ;
- unsigned a_bits = get_alignment_bits(get_memop(oi));
- uintptr_t haddr;
- DATA_TYPE res;
-
- if (addr & ((1 << a_bits) - 1)) {
- cpu_unaligned_access(ENV_GET_CPU(env), addr, READ_ACCESS_TYPE,
- mmu_idx, retaddr);
- }
-
- /* If the TLB entry is for a different page, reload and try again. */
- if (!tlb_hit(tlb_addr, addr)) {
- if (!VICTIM_TLB_HIT(ADDR_READ, addr)) {
- tlb_fill(ENV_GET_CPU(env), addr, DATA_SIZE, READ_ACCESS_TYPE,
- mmu_idx, retaddr);
- index = tlb_index(env, mmu_idx, addr);
- entry = tlb_entry(env, mmu_idx, addr);
- }
- tlb_addr = entry->ADDR_READ;
- }
-
- /* Handle an IO access. */
- if (unlikely(tlb_addr & ~TARGET_PAGE_MASK)) {
- if ((addr & (DATA_SIZE - 1)) != 0) {
- goto do_unaligned_access;
- }
-
- /* ??? Note that the io helpers always read data in the target
- byte ordering. We should push the LE/BE request down into io. */
- res = glue(io_read, SUFFIX)(env, mmu_idx, index, addr, retaddr,
- tlb_addr & TLB_RECHECK,
- READ_ACCESS_TYPE);
- res = TGT_BE(res);
- return res;
- }
-
- /* Handle slow unaligned access (it spans two pages or IO). */
- if (DATA_SIZE > 1
- && unlikely((addr & ~TARGET_PAGE_MASK) + DATA_SIZE - 1
- >= TARGET_PAGE_SIZE)) {
- target_ulong addr1, addr2;
- DATA_TYPE res1, res2;
- unsigned shift;
- do_unaligned_access:
- addr1 = addr & ~(DATA_SIZE - 1);
- addr2 = addr1 + DATA_SIZE;
- res1 = helper_be_ld_name(env, addr1, oi, retaddr);
- res2 = helper_be_ld_name(env, addr2, oi, retaddr);
- shift = (addr & (DATA_SIZE - 1)) * 8;
-
- /* Big-endian combine. */
- res = (res1 << shift) | (res2 >> ((DATA_SIZE * 8) - shift));
- return res;
- }
-
- haddr = addr + entry->addend;
- res = glue(glue(ld, LSUFFIX), _be_p)((uint8_t *)haddr);
- return res;
-}
-#endif /* DATA_SIZE > 1 */
-
-#ifndef SOFTMMU_CODE_ACCESS
-
-/* Provide signed versions of the load routines as well. We can of course
- avoid this for 64-bit data, or for 32-bit data on 32-bit host. */
-#if DATA_SIZE * 8 < TCG_TARGET_REG_BITS
-WORD_TYPE helper_le_lds_name(CPUArchState *env, target_ulong addr,
- TCGMemOpIdx oi, uintptr_t retaddr)
-{
- return (SDATA_TYPE)helper_le_ld_name(env, addr, oi, retaddr);
-}
-
-# if DATA_SIZE > 1
-WORD_TYPE helper_be_lds_name(CPUArchState *env, target_ulong addr,
- TCGMemOpIdx oi, uintptr_t retaddr)
-{
- return (SDATA_TYPE)helper_be_ld_name(env, addr, oi, retaddr);
-}
-# endif
-#endif
-
-static inline void glue(io_write, SUFFIX)(CPUArchState *env,
- size_t mmu_idx, size_t index,
- DATA_TYPE val,
- target_ulong addr,
- uintptr_t retaddr,
- bool recheck)
-{
- CPUIOTLBEntry *iotlbentry = &env->iotlb[mmu_idx][index];
- return io_writex(env, iotlbentry, mmu_idx, val, addr, retaddr,
- recheck, DATA_SIZE);
-}
-
-void helper_le_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
- TCGMemOpIdx oi, uintptr_t retaddr)
-{
- uintptr_t mmu_idx = get_mmuidx(oi);
- uintptr_t index = tlb_index(env, mmu_idx, addr);
- CPUTLBEntry *entry = tlb_entry(env, mmu_idx, addr);
- target_ulong tlb_addr = tlb_addr_write(entry);
- unsigned a_bits = get_alignment_bits(get_memop(oi));
- uintptr_t haddr;
-
- if (addr & ((1 << a_bits) - 1)) {
- cpu_unaligned_access(ENV_GET_CPU(env), addr, MMU_DATA_STORE,
- mmu_idx, retaddr);
- }
-
- /* If the TLB entry is for a different page, reload and try again. */
- if (!tlb_hit(tlb_addr, addr)) {
- if (!VICTIM_TLB_HIT(addr_write, addr)) {
- tlb_fill(ENV_GET_CPU(env), addr, DATA_SIZE, MMU_DATA_STORE,
- mmu_idx, retaddr);
- index = tlb_index(env, mmu_idx, addr);
- entry = tlb_entry(env, mmu_idx, addr);
- }
- tlb_addr = tlb_addr_write(entry) & ~TLB_INVALID_MASK;
- }
-
- /* Handle an IO access. */
- if (unlikely(tlb_addr & ~TARGET_PAGE_MASK)) {
- if ((addr & (DATA_SIZE - 1)) != 0) {
- goto do_unaligned_access;
- }
-
- /* ??? Note that the io helpers always read data in the target
- byte ordering. We should push the LE/BE request down into io. */
- val = TGT_LE(val);
- glue(io_write, SUFFIX)(env, mmu_idx, index, val, addr,
- retaddr, tlb_addr & TLB_RECHECK);
- return;
- }
-
- /* Handle slow unaligned access (it spans two pages or IO). */
- if (DATA_SIZE > 1
- && unlikely((addr & ~TARGET_PAGE_MASK) + DATA_SIZE - 1
- >= TARGET_PAGE_SIZE)) {
- int i;
- target_ulong page2;
- CPUTLBEntry *entry2;
- do_unaligned_access:
- /* Ensure the second page is in the TLB. Note that the first page
- is already guaranteed to be filled, and that the second page
- cannot evict the first. */
- page2 = (addr + DATA_SIZE) & TARGET_PAGE_MASK;
- entry2 = tlb_entry(env, mmu_idx, page2);
- if (!tlb_hit_page(tlb_addr_write(entry2), page2)
- && !VICTIM_TLB_HIT(addr_write, page2)) {
- tlb_fill(ENV_GET_CPU(env), page2, DATA_SIZE, MMU_DATA_STORE,
- mmu_idx, retaddr);
- }
-
- /* XXX: not efficient, but simple. */
- /* This loop must go in the forward direction to avoid issues
- with self-modifying code in Windows 64-bit. */
- for (i = 0; i < DATA_SIZE; ++i) {
- /* Little-endian extract. */
- uint8_t val8 = val >> (i * 8);
- glue(helper_ret_stb, MMUSUFFIX)(env, addr + i, val8,
- oi, retaddr);
- }
- return;
- }
-
- haddr = addr + entry->addend;
-#if DATA_SIZE == 1
- glue(glue(st, SUFFIX), _p)((uint8_t *)haddr, val);
-#else
- glue(glue(st, SUFFIX), _le_p)((uint8_t *)haddr, val);
-#endif
-}
-
-#if DATA_SIZE > 1
-void helper_be_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
- TCGMemOpIdx oi, uintptr_t retaddr)
-{
- uintptr_t mmu_idx = get_mmuidx(oi);
- uintptr_t index = tlb_index(env, mmu_idx, addr);
- CPUTLBEntry *entry = tlb_entry(env, mmu_idx, addr);
- target_ulong tlb_addr = tlb_addr_write(entry);
- unsigned a_bits = get_alignment_bits(get_memop(oi));
- uintptr_t haddr;
-
- if (addr & ((1 << a_bits) - 1)) {
- cpu_unaligned_access(ENV_GET_CPU(env), addr, MMU_DATA_STORE,
- mmu_idx, retaddr);
- }
-
- /* If the TLB entry is for a different page, reload and try again. */
- if (!tlb_hit(tlb_addr, addr)) {
- if (!VICTIM_TLB_HIT(addr_write, addr)) {
- tlb_fill(ENV_GET_CPU(env), addr, DATA_SIZE, MMU_DATA_STORE,
- mmu_idx, retaddr);
- index = tlb_index(env, mmu_idx, addr);
- entry = tlb_entry(env, mmu_idx, addr);
- }
- tlb_addr = tlb_addr_write(entry) & ~TLB_INVALID_MASK;
- }
-
- /* Handle an IO access. */
- if (unlikely(tlb_addr & ~TARGET_PAGE_MASK)) {
- if ((addr & (DATA_SIZE - 1)) != 0) {
- goto do_unaligned_access;
- }
-
- /* ??? Note that the io helpers always read data in the target
- byte ordering. We should push the LE/BE request down into io. */
- val = TGT_BE(val);
- glue(io_write, SUFFIX)(env, mmu_idx, index, val, addr, retaddr,
- tlb_addr & TLB_RECHECK);
- return;
- }
-
- /* Handle slow unaligned access (it spans two pages or IO). */
- if (DATA_SIZE > 1
- && unlikely((addr & ~TARGET_PAGE_MASK) + DATA_SIZE - 1
- >= TARGET_PAGE_SIZE)) {
- int i;
- target_ulong page2;
- CPUTLBEntry *entry2;
- do_unaligned_access:
- /* Ensure the second page is in the TLB. Note that the first page
- is already guaranteed to be filled, and that the second page
- cannot evict the first. */
- page2 = (addr + DATA_SIZE) & TARGET_PAGE_MASK;
- entry2 = tlb_entry(env, mmu_idx, page2);
- if (!tlb_hit_page(tlb_addr_write(entry2), page2)
- && !VICTIM_TLB_HIT(addr_write, page2)) {
- tlb_fill(ENV_GET_CPU(env), page2, DATA_SIZE, MMU_DATA_STORE,
- mmu_idx, retaddr);
- }
-
- /* XXX: not efficient, but simple */
- /* This loop must go in the forward direction to avoid issues
- with self-modifying code. */
- for (i = 0; i < DATA_SIZE; ++i) {
- /* Big-endian extract. */
- uint8_t val8 = val >> (((DATA_SIZE - 1) * 8) - (i * 8));
- glue(helper_ret_stb, MMUSUFFIX)(env, addr + i, val8,
- oi, retaddr);
- }
- return;
- }
-
- haddr = addr + entry->addend;
- glue(glue(st, SUFFIX), _be_p)((uint8_t *)haddr, val);
-}
-#endif /* DATA_SIZE > 1 */
-#endif /* !defined(SOFTMMU_CODE_ACCESS) */
-
-#undef READ_ACCESS_TYPE
-#undef DATA_TYPE
-#undef SUFFIX
-#undef LSUFFIX
-#undef DATA_SIZE
-#undef ADDR_READ
-#undef WORD_TYPE
-#undef SDATA_TYPE
-#undef USUFFIX
-#undef SSUFFIX
-#undef BSWAP
-#undef helper_le_ld_name
-#undef helper_be_ld_name
-#undef helper_le_lds_name
-#undef helper_be_lds_name
-#undef helper_le_st_name
-#undef helper_be_st_name
--
2.20.1
^ permalink raw reply related [flat|nested] 53+ messages in thread
* [Qemu-devel] [PATCH v5 09/15] accel/tcg: remove softmmu_template.h
@ 2019-04-30 16:52 ` Alex Bennée
0 siblings, 0 replies; 53+ messages in thread
From: Alex Bennée @ 2019-04-30 16:52 UTC (permalink / raw)
To: qemu-devel; +Cc: Alex Bennée, qemu-arm, mark.cave-ayland, cota
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
---
accel/tcg/softmmu_template.h | 454 -----------------------------------
1 file changed, 454 deletions(-)
delete mode 100644 accel/tcg/softmmu_template.h
diff --git a/accel/tcg/softmmu_template.h b/accel/tcg/softmmu_template.h
deleted file mode 100644
index e970a8b378..0000000000
--- a/accel/tcg/softmmu_template.h
+++ /dev/null
@@ -1,454 +0,0 @@
-/*
- * Software MMU support
- *
- * Generate helpers used by TCG for qemu_ld/st ops and code load
- * functions.
- *
- * Included from target op helpers and exec.c.
- *
- * Copyright (c) 2003 Fabrice Bellard
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see <http://www.gnu.org/licenses/>.
- */
-#if DATA_SIZE == 8
-#define SUFFIX q
-#define LSUFFIX q
-#define SDATA_TYPE int64_t
-#define DATA_TYPE uint64_t
-#elif DATA_SIZE == 4
-#define SUFFIX l
-#define LSUFFIX l
-#define SDATA_TYPE int32_t
-#define DATA_TYPE uint32_t
-#elif DATA_SIZE == 2
-#define SUFFIX w
-#define LSUFFIX uw
-#define SDATA_TYPE int16_t
-#define DATA_TYPE uint16_t
-#elif DATA_SIZE == 1
-#define SUFFIX b
-#define LSUFFIX ub
-#define SDATA_TYPE int8_t
-#define DATA_TYPE uint8_t
-#else
-#error unsupported data size
-#endif
-
-
-/* For the benefit of TCG generated code, we want to avoid the complication
- of ABI-specific return type promotion and always return a value extended
- to the register size of the host. This is tcg_target_long, except in the
- case of a 32-bit host and 64-bit data, and for that we always have
- uint64_t. Don't bother with this widened value for SOFTMMU_CODE_ACCESS. */
-#if defined(SOFTMMU_CODE_ACCESS) || DATA_SIZE == 8
-# define WORD_TYPE DATA_TYPE
-# define USUFFIX SUFFIX
-#else
-# define WORD_TYPE tcg_target_ulong
-# define USUFFIX glue(u, SUFFIX)
-# define SSUFFIX glue(s, SUFFIX)
-#endif
-
-#ifdef SOFTMMU_CODE_ACCESS
-#define READ_ACCESS_TYPE MMU_INST_FETCH
-#define ADDR_READ addr_code
-#else
-#define READ_ACCESS_TYPE MMU_DATA_LOAD
-#define ADDR_READ addr_read
-#endif
-
-#if DATA_SIZE == 8
-# define BSWAP(X) bswap64(X)
-#elif DATA_SIZE == 4
-# define BSWAP(X) bswap32(X)
-#elif DATA_SIZE == 2
-# define BSWAP(X) bswap16(X)
-#else
-# define BSWAP(X) (X)
-#endif
-
-#if DATA_SIZE == 1
-# define helper_le_ld_name glue(glue(helper_ret_ld, USUFFIX), MMUSUFFIX)
-# define helper_be_ld_name helper_le_ld_name
-# define helper_le_lds_name glue(glue(helper_ret_ld, SSUFFIX), MMUSUFFIX)
-# define helper_be_lds_name helper_le_lds_name
-# define helper_le_st_name glue(glue(helper_ret_st, SUFFIX), MMUSUFFIX)
-# define helper_be_st_name helper_le_st_name
-#else
-# define helper_le_ld_name glue(glue(helper_le_ld, USUFFIX), MMUSUFFIX)
-# define helper_be_ld_name glue(glue(helper_be_ld, USUFFIX), MMUSUFFIX)
-# define helper_le_lds_name glue(glue(helper_le_ld, SSUFFIX), MMUSUFFIX)
-# define helper_be_lds_name glue(glue(helper_be_ld, SSUFFIX), MMUSUFFIX)
-# define helper_le_st_name glue(glue(helper_le_st, SUFFIX), MMUSUFFIX)
-# define helper_be_st_name glue(glue(helper_be_st, SUFFIX), MMUSUFFIX)
-#endif
-
-#ifndef SOFTMMU_CODE_ACCESS
-static inline DATA_TYPE glue(io_read, SUFFIX)(CPUArchState *env,
- size_t mmu_idx, size_t index,
- target_ulong addr,
- uintptr_t retaddr,
- bool recheck,
- MMUAccessType access_type)
-{
- CPUIOTLBEntry *iotlbentry = &env->iotlb[mmu_idx][index];
- return io_readx(env, iotlbentry, mmu_idx, addr, retaddr, recheck,
- access_type, DATA_SIZE);
-}
-#endif
-
-WORD_TYPE helper_le_ld_name(CPUArchState *env, target_ulong addr,
- TCGMemOpIdx oi, uintptr_t retaddr)
-{
- uintptr_t mmu_idx = get_mmuidx(oi);
- uintptr_t index = tlb_index(env, mmu_idx, addr);
- CPUTLBEntry *entry = tlb_entry(env, mmu_idx, addr);
- target_ulong tlb_addr = entry->ADDR_READ;
- unsigned a_bits = get_alignment_bits(get_memop(oi));
- uintptr_t haddr;
- DATA_TYPE res;
-
- if (addr & ((1 << a_bits) - 1)) {
- cpu_unaligned_access(ENV_GET_CPU(env), addr, READ_ACCESS_TYPE,
- mmu_idx, retaddr);
- }
-
- /* If the TLB entry is for a different page, reload and try again. */
- if (!tlb_hit(tlb_addr, addr)) {
- if (!VICTIM_TLB_HIT(ADDR_READ, addr)) {
- tlb_fill(ENV_GET_CPU(env), addr, DATA_SIZE, READ_ACCESS_TYPE,
- mmu_idx, retaddr);
- index = tlb_index(env, mmu_idx, addr);
- entry = tlb_entry(env, mmu_idx, addr);
- }
- tlb_addr = entry->ADDR_READ;
- }
-
- /* Handle an IO access. */
- if (unlikely(tlb_addr & ~TARGET_PAGE_MASK)) {
- if ((addr & (DATA_SIZE - 1)) != 0) {
- goto do_unaligned_access;
- }
-
- /* ??? Note that the io helpers always read data in the target
- byte ordering. We should push the LE/BE request down into io. */
- res = glue(io_read, SUFFIX)(env, mmu_idx, index, addr, retaddr,
- tlb_addr & TLB_RECHECK,
- READ_ACCESS_TYPE);
- res = TGT_LE(res);
- return res;
- }
-
- /* Handle slow unaligned access (it spans two pages or IO). */
- if (DATA_SIZE > 1
- && unlikely((addr & ~TARGET_PAGE_MASK) + DATA_SIZE - 1
- >= TARGET_PAGE_SIZE)) {
- target_ulong addr1, addr2;
- DATA_TYPE res1, res2;
- unsigned shift;
- do_unaligned_access:
- addr1 = addr & ~(DATA_SIZE - 1);
- addr2 = addr1 + DATA_SIZE;
- res1 = helper_le_ld_name(env, addr1, oi, retaddr);
- res2 = helper_le_ld_name(env, addr2, oi, retaddr);
- shift = (addr & (DATA_SIZE - 1)) * 8;
-
- /* Little-endian combine. */
- res = (res1 >> shift) | (res2 << ((DATA_SIZE * 8) - shift));
- return res;
- }
-
- haddr = addr + entry->addend;
-#if DATA_SIZE == 1
- res = glue(glue(ld, LSUFFIX), _p)((uint8_t *)haddr);
-#else
- res = glue(glue(ld, LSUFFIX), _le_p)((uint8_t *)haddr);
-#endif
- return res;
-}
-
-#if DATA_SIZE > 1
-WORD_TYPE helper_be_ld_name(CPUArchState *env, target_ulong addr,
- TCGMemOpIdx oi, uintptr_t retaddr)
-{
- uintptr_t mmu_idx = get_mmuidx(oi);
- uintptr_t index = tlb_index(env, mmu_idx, addr);
- CPUTLBEntry *entry = tlb_entry(env, mmu_idx, addr);
- target_ulong tlb_addr = entry->ADDR_READ;
- unsigned a_bits = get_alignment_bits(get_memop(oi));
- uintptr_t haddr;
- DATA_TYPE res;
-
- if (addr & ((1 << a_bits) - 1)) {
- cpu_unaligned_access(ENV_GET_CPU(env), addr, READ_ACCESS_TYPE,
- mmu_idx, retaddr);
- }
-
- /* If the TLB entry is for a different page, reload and try again. */
- if (!tlb_hit(tlb_addr, addr)) {
- if (!VICTIM_TLB_HIT(ADDR_READ, addr)) {
- tlb_fill(ENV_GET_CPU(env), addr, DATA_SIZE, READ_ACCESS_TYPE,
- mmu_idx, retaddr);
- index = tlb_index(env, mmu_idx, addr);
- entry = tlb_entry(env, mmu_idx, addr);
- }
- tlb_addr = entry->ADDR_READ;
- }
-
- /* Handle an IO access. */
- if (unlikely(tlb_addr & ~TARGET_PAGE_MASK)) {
- if ((addr & (DATA_SIZE - 1)) != 0) {
- goto do_unaligned_access;
- }
-
- /* ??? Note that the io helpers always read data in the target
- byte ordering. We should push the LE/BE request down into io. */
- res = glue(io_read, SUFFIX)(env, mmu_idx, index, addr, retaddr,
- tlb_addr & TLB_RECHECK,
- READ_ACCESS_TYPE);
- res = TGT_BE(res);
- return res;
- }
-
- /* Handle slow unaligned access (it spans two pages or IO). */
- if (DATA_SIZE > 1
- && unlikely((addr & ~TARGET_PAGE_MASK) + DATA_SIZE - 1
- >= TARGET_PAGE_SIZE)) {
- target_ulong addr1, addr2;
- DATA_TYPE res1, res2;
- unsigned shift;
- do_unaligned_access:
- addr1 = addr & ~(DATA_SIZE - 1);
- addr2 = addr1 + DATA_SIZE;
- res1 = helper_be_ld_name(env, addr1, oi, retaddr);
- res2 = helper_be_ld_name(env, addr2, oi, retaddr);
- shift = (addr & (DATA_SIZE - 1)) * 8;
-
- /* Big-endian combine. */
- res = (res1 << shift) | (res2 >> ((DATA_SIZE * 8) - shift));
- return res;
- }
-
- haddr = addr + entry->addend;
- res = glue(glue(ld, LSUFFIX), _be_p)((uint8_t *)haddr);
- return res;
-}
-#endif /* DATA_SIZE > 1 */
-
-#ifndef SOFTMMU_CODE_ACCESS
-
-/* Provide signed versions of the load routines as well. We can of course
- avoid this for 64-bit data, or for 32-bit data on 32-bit host. */
-#if DATA_SIZE * 8 < TCG_TARGET_REG_BITS
-WORD_TYPE helper_le_lds_name(CPUArchState *env, target_ulong addr,
- TCGMemOpIdx oi, uintptr_t retaddr)
-{
- return (SDATA_TYPE)helper_le_ld_name(env, addr, oi, retaddr);
-}
-
-# if DATA_SIZE > 1
-WORD_TYPE helper_be_lds_name(CPUArchState *env, target_ulong addr,
- TCGMemOpIdx oi, uintptr_t retaddr)
-{
- return (SDATA_TYPE)helper_be_ld_name(env, addr, oi, retaddr);
-}
-# endif
-#endif
-
-static inline void glue(io_write, SUFFIX)(CPUArchState *env,
- size_t mmu_idx, size_t index,
- DATA_TYPE val,
- target_ulong addr,
- uintptr_t retaddr,
- bool recheck)
-{
- CPUIOTLBEntry *iotlbentry = &env->iotlb[mmu_idx][index];
- return io_writex(env, iotlbentry, mmu_idx, val, addr, retaddr,
- recheck, DATA_SIZE);
-}
-
-void helper_le_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
- TCGMemOpIdx oi, uintptr_t retaddr)
-{
- uintptr_t mmu_idx = get_mmuidx(oi);
- uintptr_t index = tlb_index(env, mmu_idx, addr);
- CPUTLBEntry *entry = tlb_entry(env, mmu_idx, addr);
- target_ulong tlb_addr = tlb_addr_write(entry);
- unsigned a_bits = get_alignment_bits(get_memop(oi));
- uintptr_t haddr;
-
- if (addr & ((1 << a_bits) - 1)) {
- cpu_unaligned_access(ENV_GET_CPU(env), addr, MMU_DATA_STORE,
- mmu_idx, retaddr);
- }
-
- /* If the TLB entry is for a different page, reload and try again. */
- if (!tlb_hit(tlb_addr, addr)) {
- if (!VICTIM_TLB_HIT(addr_write, addr)) {
- tlb_fill(ENV_GET_CPU(env), addr, DATA_SIZE, MMU_DATA_STORE,
- mmu_idx, retaddr);
- index = tlb_index(env, mmu_idx, addr);
- entry = tlb_entry(env, mmu_idx, addr);
- }
- tlb_addr = tlb_addr_write(entry) & ~TLB_INVALID_MASK;
- }
-
- /* Handle an IO access. */
- if (unlikely(tlb_addr & ~TARGET_PAGE_MASK)) {
- if ((addr & (DATA_SIZE - 1)) != 0) {
- goto do_unaligned_access;
- }
-
- /* ??? Note that the io helpers always read data in the target
- byte ordering. We should push the LE/BE request down into io. */
- val = TGT_LE(val);
- glue(io_write, SUFFIX)(env, mmu_idx, index, val, addr,
- retaddr, tlb_addr & TLB_RECHECK);
- return;
- }
-
- /* Handle slow unaligned access (it spans two pages or IO). */
- if (DATA_SIZE > 1
- && unlikely((addr & ~TARGET_PAGE_MASK) + DATA_SIZE - 1
- >= TARGET_PAGE_SIZE)) {
- int i;
- target_ulong page2;
- CPUTLBEntry *entry2;
- do_unaligned_access:
- /* Ensure the second page is in the TLB. Note that the first page
- is already guaranteed to be filled, and that the second page
- cannot evict the first. */
- page2 = (addr + DATA_SIZE) & TARGET_PAGE_MASK;
- entry2 = tlb_entry(env, mmu_idx, page2);
- if (!tlb_hit_page(tlb_addr_write(entry2), page2)
- && !VICTIM_TLB_HIT(addr_write, page2)) {
- tlb_fill(ENV_GET_CPU(env), page2, DATA_SIZE, MMU_DATA_STORE,
- mmu_idx, retaddr);
- }
-
- /* XXX: not efficient, but simple. */
- /* This loop must go in the forward direction to avoid issues
- with self-modifying code in Windows 64-bit. */
- for (i = 0; i < DATA_SIZE; ++i) {
- /* Little-endian extract. */
- uint8_t val8 = val >> (i * 8);
- glue(helper_ret_stb, MMUSUFFIX)(env, addr + i, val8,
- oi, retaddr);
- }
- return;
- }
-
- haddr = addr + entry->addend;
-#if DATA_SIZE == 1
- glue(glue(st, SUFFIX), _p)((uint8_t *)haddr, val);
-#else
- glue(glue(st, SUFFIX), _le_p)((uint8_t *)haddr, val);
-#endif
-}
-
-#if DATA_SIZE > 1
-void helper_be_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
- TCGMemOpIdx oi, uintptr_t retaddr)
-{
- uintptr_t mmu_idx = get_mmuidx(oi);
- uintptr_t index = tlb_index(env, mmu_idx, addr);
- CPUTLBEntry *entry = tlb_entry(env, mmu_idx, addr);
- target_ulong tlb_addr = tlb_addr_write(entry);
- unsigned a_bits = get_alignment_bits(get_memop(oi));
- uintptr_t haddr;
-
- if (addr & ((1 << a_bits) - 1)) {
- cpu_unaligned_access(ENV_GET_CPU(env), addr, MMU_DATA_STORE,
- mmu_idx, retaddr);
- }
-
- /* If the TLB entry is for a different page, reload and try again. */
- if (!tlb_hit(tlb_addr, addr)) {
- if (!VICTIM_TLB_HIT(addr_write, addr)) {
- tlb_fill(ENV_GET_CPU(env), addr, DATA_SIZE, MMU_DATA_STORE,
- mmu_idx, retaddr);
- index = tlb_index(env, mmu_idx, addr);
- entry = tlb_entry(env, mmu_idx, addr);
- }
- tlb_addr = tlb_addr_write(entry) & ~TLB_INVALID_MASK;
- }
-
- /* Handle an IO access. */
- if (unlikely(tlb_addr & ~TARGET_PAGE_MASK)) {
- if ((addr & (DATA_SIZE - 1)) != 0) {
- goto do_unaligned_access;
- }
-
- /* ??? Note that the io helpers always read data in the target
- byte ordering. We should push the LE/BE request down into io. */
- val = TGT_BE(val);
- glue(io_write, SUFFIX)(env, mmu_idx, index, val, addr, retaddr,
- tlb_addr & TLB_RECHECK);
- return;
- }
-
- /* Handle slow unaligned access (it spans two pages or IO). */
- if (DATA_SIZE > 1
- && unlikely((addr & ~TARGET_PAGE_MASK) + DATA_SIZE - 1
- >= TARGET_PAGE_SIZE)) {
- int i;
- target_ulong page2;
- CPUTLBEntry *entry2;
- do_unaligned_access:
- /* Ensure the second page is in the TLB. Note that the first page
- is already guaranteed to be filled, and that the second page
- cannot evict the first. */
- page2 = (addr + DATA_SIZE) & TARGET_PAGE_MASK;
- entry2 = tlb_entry(env, mmu_idx, page2);
- if (!tlb_hit_page(tlb_addr_write(entry2), page2)
- && !VICTIM_TLB_HIT(addr_write, page2)) {
- tlb_fill(ENV_GET_CPU(env), page2, DATA_SIZE, MMU_DATA_STORE,
- mmu_idx, retaddr);
- }
-
- /* XXX: not efficient, but simple */
- /* This loop must go in the forward direction to avoid issues
- with self-modifying code. */
- for (i = 0; i < DATA_SIZE; ++i) {
- /* Big-endian extract. */
- uint8_t val8 = val >> (((DATA_SIZE - 1) * 8) - (i * 8));
- glue(helper_ret_stb, MMUSUFFIX)(env, addr + i, val8,
- oi, retaddr);
- }
- return;
- }
-
- haddr = addr + entry->addend;
- glue(glue(st, SUFFIX), _be_p)((uint8_t *)haddr, val);
-}
-#endif /* DATA_SIZE > 1 */
-#endif /* !defined(SOFTMMU_CODE_ACCESS) */
-
-#undef READ_ACCESS_TYPE
-#undef DATA_TYPE
-#undef SUFFIX
-#undef LSUFFIX
-#undef DATA_SIZE
-#undef ADDR_READ
-#undef WORD_TYPE
-#undef SDATA_TYPE
-#undef USUFFIX
-#undef SSUFFIX
-#undef BSWAP
-#undef helper_le_ld_name
-#undef helper_be_ld_name
-#undef helper_le_lds_name
-#undef helper_be_lds_name
-#undef helper_le_st_name
-#undef helper_be_st_name
--
2.20.1
^ permalink raw reply related [flat|nested] 53+ messages in thread
* [Qemu-devel] [PATCH v5 10/15] cputlb: Drop attribute flatten
@ 2019-04-30 16:52 ` Alex Bennée
0 siblings, 0 replies; 53+ messages in thread
From: Alex Bennée @ 2019-04-30 16:52 UTC (permalink / raw)
To: qemu-devel
Cc: qemu-arm, mark.cave-ayland, cota, Richard Henderson, Alex Bennée
From: Richard Henderson <richard.henderson@linaro.org>
Going to approach this problem via __attribute__((always_inline))
instead, but full conversion will take several steps.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
---
accel/tcg/cputlb.c | 105 ++++++++++++++++++---------------------------
1 file changed, 42 insertions(+), 63 deletions(-)
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
index 9c04eb1687..ccbb47d8d1 100644
--- a/accel/tcg/cputlb.c
+++ b/accel/tcg/cputlb.c
@@ -1291,51 +1291,44 @@ static uint64_t load_helper(CPUArchState *env, target_ulong addr,
* We don't bother with this widened value for SOFTMMU_CODE_ACCESS.
*/
-tcg_target_ulong __attribute__((flatten))
-helper_ret_ldub_mmu(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi,
- uintptr_t retaddr)
+tcg_target_ulong helper_ret_ldub_mmu(CPUArchState *env, target_ulong addr,
+ TCGMemOpIdx oi, uintptr_t retaddr)
{
return load_helper(env, addr, oi, retaddr, 1, false, false);
}
-tcg_target_ulong __attribute__((flatten))
-helper_le_lduw_mmu(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi,
- uintptr_t retaddr)
+tcg_target_ulong helper_le_lduw_mmu(CPUArchState *env, target_ulong addr,
+ TCGMemOpIdx oi, uintptr_t retaddr)
{
return load_helper(env, addr, oi, retaddr, 2, false, false);
}
-tcg_target_ulong __attribute__((flatten))
-helper_be_lduw_mmu(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi,
- uintptr_t retaddr)
+tcg_target_ulong helper_be_lduw_mmu(CPUArchState *env, target_ulong addr,
+ TCGMemOpIdx oi, uintptr_t retaddr)
{
return load_helper(env, addr, oi, retaddr, 2, true, false);
}
-tcg_target_ulong __attribute__((flatten))
-helper_le_ldul_mmu(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi,
- uintptr_t retaddr)
+tcg_target_ulong helper_le_ldul_mmu(CPUArchState *env, target_ulong addr,
+ TCGMemOpIdx oi, uintptr_t retaddr)
{
return load_helper(env, addr, oi, retaddr, 4, false, false);
}
-tcg_target_ulong __attribute__((flatten))
-helper_be_ldul_mmu(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi,
- uintptr_t retaddr)
+tcg_target_ulong helper_be_ldul_mmu(CPUArchState *env, target_ulong addr,
+ TCGMemOpIdx oi, uintptr_t retaddr)
{
return load_helper(env, addr, oi, retaddr, 4, true, false);
}
-uint64_t __attribute__((flatten))
-helper_le_ldq_mmu(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi,
- uintptr_t retaddr)
+uint64_t helper_le_ldq_mmu(CPUArchState *env, target_ulong addr,
+ TCGMemOpIdx oi, uintptr_t retaddr)
{
return load_helper(env, addr, oi, retaddr, 8, false, false);
}
-uint64_t __attribute__((flatten))
-helper_be_ldq_mmu(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi,
- uintptr_t retaddr)
+uint64_t helper_be_ldq_mmu(CPUArchState *env, target_ulong addr,
+ TCGMemOpIdx oi, uintptr_t retaddr)
{
return load_helper(env, addr, oi, retaddr, 8, true, false);
}
@@ -1519,51 +1512,44 @@ static void store_helper(CPUArchState *env, target_ulong addr, uint64_t val,
}
}
-void __attribute__((flatten))
-helper_ret_stb_mmu(CPUArchState *env, target_ulong addr, uint8_t val,
- TCGMemOpIdx oi, uintptr_t retaddr)
+void helper_ret_stb_mmu(CPUArchState *env, target_ulong addr, uint8_t val,
+ TCGMemOpIdx oi, uintptr_t retaddr)
{
store_helper(env, addr, val, oi, retaddr, 1, false);
}
-void __attribute__((flatten))
-helper_le_stw_mmu(CPUArchState *env, target_ulong addr, uint16_t val,
- TCGMemOpIdx oi, uintptr_t retaddr)
+void helper_le_stw_mmu(CPUArchState *env, target_ulong addr, uint16_t val,
+ TCGMemOpIdx oi, uintptr_t retaddr)
{
store_helper(env, addr, val, oi, retaddr, 2, false);
}
-void __attribute__((flatten))
-helper_be_stw_mmu(CPUArchState *env, target_ulong addr, uint16_t val,
- TCGMemOpIdx oi, uintptr_t retaddr)
+void helper_be_stw_mmu(CPUArchState *env, target_ulong addr, uint16_t val,
+ TCGMemOpIdx oi, uintptr_t retaddr)
{
store_helper(env, addr, val, oi, retaddr, 2, true);
}
-void __attribute__((flatten))
-helper_le_stl_mmu(CPUArchState *env, target_ulong addr, uint32_t val,
- TCGMemOpIdx oi, uintptr_t retaddr)
+void helper_le_stl_mmu(CPUArchState *env, target_ulong addr, uint32_t val,
+ TCGMemOpIdx oi, uintptr_t retaddr)
{
store_helper(env, addr, val, oi, retaddr, 4, false);
}
-void __attribute__((flatten))
-helper_be_stl_mmu(CPUArchState *env, target_ulong addr, uint32_t val,
- TCGMemOpIdx oi, uintptr_t retaddr)
+void helper_be_stl_mmu(CPUArchState *env, target_ulong addr, uint32_t val,
+ TCGMemOpIdx oi, uintptr_t retaddr)
{
store_helper(env, addr, val, oi, retaddr, 4, true);
}
-void __attribute__((flatten))
-helper_le_stq_mmu(CPUArchState *env, target_ulong addr, uint64_t val,
- TCGMemOpIdx oi, uintptr_t retaddr)
+void helper_le_stq_mmu(CPUArchState *env, target_ulong addr, uint64_t val,
+ TCGMemOpIdx oi, uintptr_t retaddr)
{
store_helper(env, addr, val, oi, retaddr, 8, false);
}
-void __attribute__((flatten))
-helper_be_stq_mmu(CPUArchState *env, target_ulong addr, uint64_t val,
- TCGMemOpIdx oi, uintptr_t retaddr)
+void helper_be_stq_mmu(CPUArchState *env, target_ulong addr, uint64_t val,
+ TCGMemOpIdx oi, uintptr_t retaddr)
{
store_helper(env, addr, val, oi, retaddr, 8, true);
}
@@ -1627,51 +1613,44 @@ helper_be_stq_mmu(CPUArchState *env, target_ulong addr, uint64_t val,
/* Code access functions. */
-uint8_t __attribute__((flatten))
-helper_ret_ldb_cmmu(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi,
- uintptr_t retaddr)
+uint8_t helper_ret_ldb_cmmu(CPUArchState *env, target_ulong addr,
+ TCGMemOpIdx oi, uintptr_t retaddr)
{
return load_helper(env, addr, oi, retaddr, 1, false, true);
}
-uint16_t __attribute__((flatten))
-helper_le_ldw_cmmu(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi,
- uintptr_t retaddr)
+uint16_t helper_le_ldw_cmmu(CPUArchState *env, target_ulong addr,
+ TCGMemOpIdx oi, uintptr_t retaddr)
{
return load_helper(env, addr, oi, retaddr, 2, false, true);
}
-uint16_t __attribute__((flatten))
-helper_be_ldw_cmmu(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi,
- uintptr_t retaddr)
+uint16_t helper_be_ldw_cmmu(CPUArchState *env, target_ulong addr,
+ TCGMemOpIdx oi, uintptr_t retaddr)
{
return load_helper(env, addr, oi, retaddr, 2, true, true);
}
-uint32_t __attribute__((flatten))
-helper_le_ldl_cmmu(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi,
- uintptr_t retaddr)
+uint32_t helper_le_ldl_cmmu(CPUArchState *env, target_ulong addr,
+ TCGMemOpIdx oi, uintptr_t retaddr)
{
return load_helper(env, addr, oi, retaddr, 4, false, true);
}
-uint32_t __attribute__((flatten))
-helper_be_ldl_cmmu(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi,
- uintptr_t retaddr)
+uint32_t helper_be_ldl_cmmu(CPUArchState *env, target_ulong addr,
+ TCGMemOpIdx oi, uintptr_t retaddr)
{
return load_helper(env, addr, oi, retaddr, 4, true, true);
}
-uint64_t __attribute__((flatten))
-helper_le_ldq_cmmu(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi,
- uintptr_t retaddr)
+uint64_t helper_le_ldq_cmmu(CPUArchState *env, target_ulong addr,
+ TCGMemOpIdx oi, uintptr_t retaddr)
{
return load_helper(env, addr, oi, retaddr, 8, false, true);
}
-uint64_t __attribute__((flatten))
-helper_be_ldq_cmmu(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi,
- uintptr_t retaddr)
+uint64_t helper_be_ldq_cmmu(CPUArchState *env, target_ulong addr,
+ TCGMemOpIdx oi, uintptr_t retaddr)
{
return load_helper(env, addr, oi, retaddr, 8, true, true);
}
--
2.20.1
^ permalink raw reply related [flat|nested] 53+ messages in thread
* [Qemu-devel] [PATCH v5 10/15] cputlb: Drop attribute flatten
@ 2019-04-30 16:52 ` Alex Bennée
0 siblings, 0 replies; 53+ messages in thread
From: Alex Bennée @ 2019-04-30 16:52 UTC (permalink / raw)
To: qemu-devel
Cc: Alex Bennée, Richard Henderson, qemu-arm, mark.cave-ayland, cota
From: Richard Henderson <richard.henderson@linaro.org>
Going to approach this problem via __attribute__((always_inline))
instead, but full conversion will take several steps.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
---
accel/tcg/cputlb.c | 105 ++++++++++++++++++---------------------------
1 file changed, 42 insertions(+), 63 deletions(-)
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
index 9c04eb1687..ccbb47d8d1 100644
--- a/accel/tcg/cputlb.c
+++ b/accel/tcg/cputlb.c
@@ -1291,51 +1291,44 @@ static uint64_t load_helper(CPUArchState *env, target_ulong addr,
* We don't bother with this widened value for SOFTMMU_CODE_ACCESS.
*/
-tcg_target_ulong __attribute__((flatten))
-helper_ret_ldub_mmu(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi,
- uintptr_t retaddr)
+tcg_target_ulong helper_ret_ldub_mmu(CPUArchState *env, target_ulong addr,
+ TCGMemOpIdx oi, uintptr_t retaddr)
{
return load_helper(env, addr, oi, retaddr, 1, false, false);
}
-tcg_target_ulong __attribute__((flatten))
-helper_le_lduw_mmu(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi,
- uintptr_t retaddr)
+tcg_target_ulong helper_le_lduw_mmu(CPUArchState *env, target_ulong addr,
+ TCGMemOpIdx oi, uintptr_t retaddr)
{
return load_helper(env, addr, oi, retaddr, 2, false, false);
}
-tcg_target_ulong __attribute__((flatten))
-helper_be_lduw_mmu(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi,
- uintptr_t retaddr)
+tcg_target_ulong helper_be_lduw_mmu(CPUArchState *env, target_ulong addr,
+ TCGMemOpIdx oi, uintptr_t retaddr)
{
return load_helper(env, addr, oi, retaddr, 2, true, false);
}
-tcg_target_ulong __attribute__((flatten))
-helper_le_ldul_mmu(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi,
- uintptr_t retaddr)
+tcg_target_ulong helper_le_ldul_mmu(CPUArchState *env, target_ulong addr,
+ TCGMemOpIdx oi, uintptr_t retaddr)
{
return load_helper(env, addr, oi, retaddr, 4, false, false);
}
-tcg_target_ulong __attribute__((flatten))
-helper_be_ldul_mmu(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi,
- uintptr_t retaddr)
+tcg_target_ulong helper_be_ldul_mmu(CPUArchState *env, target_ulong addr,
+ TCGMemOpIdx oi, uintptr_t retaddr)
{
return load_helper(env, addr, oi, retaddr, 4, true, false);
}
-uint64_t __attribute__((flatten))
-helper_le_ldq_mmu(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi,
- uintptr_t retaddr)
+uint64_t helper_le_ldq_mmu(CPUArchState *env, target_ulong addr,
+ TCGMemOpIdx oi, uintptr_t retaddr)
{
return load_helper(env, addr, oi, retaddr, 8, false, false);
}
-uint64_t __attribute__((flatten))
-helper_be_ldq_mmu(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi,
- uintptr_t retaddr)
+uint64_t helper_be_ldq_mmu(CPUArchState *env, target_ulong addr,
+ TCGMemOpIdx oi, uintptr_t retaddr)
{
return load_helper(env, addr, oi, retaddr, 8, true, false);
}
@@ -1519,51 +1512,44 @@ static void store_helper(CPUArchState *env, target_ulong addr, uint64_t val,
}
}
-void __attribute__((flatten))
-helper_ret_stb_mmu(CPUArchState *env, target_ulong addr, uint8_t val,
- TCGMemOpIdx oi, uintptr_t retaddr)
+void helper_ret_stb_mmu(CPUArchState *env, target_ulong addr, uint8_t val,
+ TCGMemOpIdx oi, uintptr_t retaddr)
{
store_helper(env, addr, val, oi, retaddr, 1, false);
}
-void __attribute__((flatten))
-helper_le_stw_mmu(CPUArchState *env, target_ulong addr, uint16_t val,
- TCGMemOpIdx oi, uintptr_t retaddr)
+void helper_le_stw_mmu(CPUArchState *env, target_ulong addr, uint16_t val,
+ TCGMemOpIdx oi, uintptr_t retaddr)
{
store_helper(env, addr, val, oi, retaddr, 2, false);
}
-void __attribute__((flatten))
-helper_be_stw_mmu(CPUArchState *env, target_ulong addr, uint16_t val,
- TCGMemOpIdx oi, uintptr_t retaddr)
+void helper_be_stw_mmu(CPUArchState *env, target_ulong addr, uint16_t val,
+ TCGMemOpIdx oi, uintptr_t retaddr)
{
store_helper(env, addr, val, oi, retaddr, 2, true);
}
-void __attribute__((flatten))
-helper_le_stl_mmu(CPUArchState *env, target_ulong addr, uint32_t val,
- TCGMemOpIdx oi, uintptr_t retaddr)
+void helper_le_stl_mmu(CPUArchState *env, target_ulong addr, uint32_t val,
+ TCGMemOpIdx oi, uintptr_t retaddr)
{
store_helper(env, addr, val, oi, retaddr, 4, false);
}
-void __attribute__((flatten))
-helper_be_stl_mmu(CPUArchState *env, target_ulong addr, uint32_t val,
- TCGMemOpIdx oi, uintptr_t retaddr)
+void helper_be_stl_mmu(CPUArchState *env, target_ulong addr, uint32_t val,
+ TCGMemOpIdx oi, uintptr_t retaddr)
{
store_helper(env, addr, val, oi, retaddr, 4, true);
}
-void __attribute__((flatten))
-helper_le_stq_mmu(CPUArchState *env, target_ulong addr, uint64_t val,
- TCGMemOpIdx oi, uintptr_t retaddr)
+void helper_le_stq_mmu(CPUArchState *env, target_ulong addr, uint64_t val,
+ TCGMemOpIdx oi, uintptr_t retaddr)
{
store_helper(env, addr, val, oi, retaddr, 8, false);
}
-void __attribute__((flatten))
-helper_be_stq_mmu(CPUArchState *env, target_ulong addr, uint64_t val,
- TCGMemOpIdx oi, uintptr_t retaddr)
+void helper_be_stq_mmu(CPUArchState *env, target_ulong addr, uint64_t val,
+ TCGMemOpIdx oi, uintptr_t retaddr)
{
store_helper(env, addr, val, oi, retaddr, 8, true);
}
@@ -1627,51 +1613,44 @@ helper_be_stq_mmu(CPUArchState *env, target_ulong addr, uint64_t val,
/* Code access functions. */
-uint8_t __attribute__((flatten))
-helper_ret_ldb_cmmu(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi,
- uintptr_t retaddr)
+uint8_t helper_ret_ldb_cmmu(CPUArchState *env, target_ulong addr,
+ TCGMemOpIdx oi, uintptr_t retaddr)
{
return load_helper(env, addr, oi, retaddr, 1, false, true);
}
-uint16_t __attribute__((flatten))
-helper_le_ldw_cmmu(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi,
- uintptr_t retaddr)
+uint16_t helper_le_ldw_cmmu(CPUArchState *env, target_ulong addr,
+ TCGMemOpIdx oi, uintptr_t retaddr)
{
return load_helper(env, addr, oi, retaddr, 2, false, true);
}
-uint16_t __attribute__((flatten))
-helper_be_ldw_cmmu(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi,
- uintptr_t retaddr)
+uint16_t helper_be_ldw_cmmu(CPUArchState *env, target_ulong addr,
+ TCGMemOpIdx oi, uintptr_t retaddr)
{
return load_helper(env, addr, oi, retaddr, 2, true, true);
}
-uint32_t __attribute__((flatten))
-helper_le_ldl_cmmu(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi,
- uintptr_t retaddr)
+uint32_t helper_le_ldl_cmmu(CPUArchState *env, target_ulong addr,
+ TCGMemOpIdx oi, uintptr_t retaddr)
{
return load_helper(env, addr, oi, retaddr, 4, false, true);
}
-uint32_t __attribute__((flatten))
-helper_be_ldl_cmmu(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi,
- uintptr_t retaddr)
+uint32_t helper_be_ldl_cmmu(CPUArchState *env, target_ulong addr,
+ TCGMemOpIdx oi, uintptr_t retaddr)
{
return load_helper(env, addr, oi, retaddr, 4, true, true);
}
-uint64_t __attribute__((flatten))
-helper_le_ldq_cmmu(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi,
- uintptr_t retaddr)
+uint64_t helper_le_ldq_cmmu(CPUArchState *env, target_ulong addr,
+ TCGMemOpIdx oi, uintptr_t retaddr)
{
return load_helper(env, addr, oi, retaddr, 8, false, true);
}
-uint64_t __attribute__((flatten))
-helper_be_ldq_cmmu(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi,
- uintptr_t retaddr)
+uint64_t helper_be_ldq_cmmu(CPUArchState *env, target_ulong addr,
+ TCGMemOpIdx oi, uintptr_t retaddr)
{
return load_helper(env, addr, oi, retaddr, 8, true, true);
}
--
2.20.1
^ permalink raw reply related [flat|nested] 53+ messages in thread
* [Qemu-devel] [PATCH v5 11/15] cputlb: Do unaligned load recursion to outermost function
@ 2019-04-30 16:52 ` Alex Bennée
0 siblings, 0 replies; 53+ messages in thread
From: Alex Bennée @ 2019-04-30 16:52 UTC (permalink / raw)
To: qemu-devel
Cc: qemu-arm, mark.cave-ayland, cota, Richard Henderson, Alex Bennée
From: Richard Henderson <richard.henderson@linaro.org>
If we attempt to recurse from load_helper back to load_helper,
even via intermediary, we do not get all of the constants
expanded away as desired.
But if we recurse back to the original helper (or a shim that
has a consistent function signature), the operands are folded
away as desired.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
---
accel/tcg/cputlb.c | 117 +++++++++++++++++++++++++++++++++++++--------
1 file changed, 97 insertions(+), 20 deletions(-)
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
index ccbb47d8d1..e4d0c94301 100644
--- a/accel/tcg/cputlb.c
+++ b/accel/tcg/cputlb.c
@@ -1157,10 +1157,13 @@ static inline uint64_t handle_bswap(uint64_t val, int size, bool big_endian)
* is disassembled. It shouldn't be called directly by guest code.
*/
-static uint64_t load_helper(CPUArchState *env, target_ulong addr,
- TCGMemOpIdx oi, uintptr_t retaddr,
- size_t size, bool big_endian,
- bool code_read)
+typedef uint64_t FullLoadHelper(CPUArchState *env, target_ulong addr,
+ TCGMemOpIdx oi, uintptr_t retaddr);
+
+static inline uint64_t __attribute__((always_inline))
+load_helper(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi,
+ uintptr_t retaddr, size_t size, bool big_endian, bool code_read,
+ FullLoadHelper *full_load)
{
uintptr_t mmu_idx = get_mmuidx(oi);
uintptr_t index = tlb_index(env, mmu_idx, addr);
@@ -1233,8 +1236,8 @@ static uint64_t load_helper(CPUArchState *env, target_ulong addr,
do_unaligned_access:
addr1 = addr & ~(size - 1);
addr2 = addr1 + size;
- r1 = load_helper(env, addr1, oi, retaddr, size, big_endian, code_read);
- r2 = load_helper(env, addr2, oi, retaddr, size, big_endian, code_read);
+ r1 = full_load(env, addr1, oi, retaddr);
+ r2 = full_load(env, addr2, oi, retaddr);
shift = (addr & (size - 1)) * 8;
if (big_endian) {
@@ -1291,46 +1294,83 @@ static uint64_t load_helper(CPUArchState *env, target_ulong addr,
* We don't bother with this widened value for SOFTMMU_CODE_ACCESS.
*/
+static uint64_t full_ldub_mmu(CPUArchState *env, target_ulong addr,
+ TCGMemOpIdx oi, uintptr_t retaddr)
+{
+ return load_helper(env, addr, oi, retaddr, 1, false, false,
+ full_ldub_mmu);
+}
+
tcg_target_ulong helper_ret_ldub_mmu(CPUArchState *env, target_ulong addr,
TCGMemOpIdx oi, uintptr_t retaddr)
{
- return load_helper(env, addr, oi, retaddr, 1, false, false);
+ return full_ldub_mmu(env, addr, oi, retaddr);
+}
+
+static uint64_t full_le_lduw_mmu(CPUArchState *env, target_ulong addr,
+ TCGMemOpIdx oi, uintptr_t retaddr)
+{
+ return load_helper(env, addr, oi, retaddr, 2, false, false,
+ full_le_lduw_mmu);
}
tcg_target_ulong helper_le_lduw_mmu(CPUArchState *env, target_ulong addr,
TCGMemOpIdx oi, uintptr_t retaddr)
{
- return load_helper(env, addr, oi, retaddr, 2, false, false);
+ return full_le_lduw_mmu(env, addr, oi, retaddr);
+}
+
+static uint64_t full_be_lduw_mmu(CPUArchState *env, target_ulong addr,
+ TCGMemOpIdx oi, uintptr_t retaddr)
+{
+ return load_helper(env, addr, oi, retaddr, 2, true, false,
+ full_be_lduw_mmu);
}
tcg_target_ulong helper_be_lduw_mmu(CPUArchState *env, target_ulong addr,
TCGMemOpIdx oi, uintptr_t retaddr)
{
- return load_helper(env, addr, oi, retaddr, 2, true, false);
+ return full_be_lduw_mmu(env, addr, oi, retaddr);
+}
+
+static uint64_t full_le_ldul_mmu(CPUArchState *env, target_ulong addr,
+ TCGMemOpIdx oi, uintptr_t retaddr)
+{
+ return load_helper(env, addr, oi, retaddr, 4, false, false,
+ full_le_ldul_mmu);
}
tcg_target_ulong helper_le_ldul_mmu(CPUArchState *env, target_ulong addr,
TCGMemOpIdx oi, uintptr_t retaddr)
{
- return load_helper(env, addr, oi, retaddr, 4, false, false);
+ return full_le_ldul_mmu(env, addr, oi, retaddr);
+}
+
+static uint64_t full_be_ldul_mmu(CPUArchState *env, target_ulong addr,
+ TCGMemOpIdx oi, uintptr_t retaddr)
+{
+ return load_helper(env, addr, oi, retaddr, 4, true, false,
+ full_be_ldul_mmu);
}
tcg_target_ulong helper_be_ldul_mmu(CPUArchState *env, target_ulong addr,
TCGMemOpIdx oi, uintptr_t retaddr)
{
- return load_helper(env, addr, oi, retaddr, 4, true, false);
+ return full_be_ldul_mmu(env, addr, oi, retaddr);
}
uint64_t helper_le_ldq_mmu(CPUArchState *env, target_ulong addr,
TCGMemOpIdx oi, uintptr_t retaddr)
{
- return load_helper(env, addr, oi, retaddr, 8, false, false);
+ return load_helper(env, addr, oi, retaddr, 8, false, false,
+ helper_le_ldq_mmu);
}
uint64_t helper_be_ldq_mmu(CPUArchState *env, target_ulong addr,
TCGMemOpIdx oi, uintptr_t retaddr)
{
- return load_helper(env, addr, oi, retaddr, 8, true, false);
+ return load_helper(env, addr, oi, retaddr, 8, true, false,
+ helper_be_ldq_mmu);
}
/*
@@ -1613,44 +1653,81 @@ void helper_be_stq_mmu(CPUArchState *env, target_ulong addr, uint64_t val,
/* Code access functions. */
+static uint64_t full_ldub_cmmu(CPUArchState *env, target_ulong addr,
+ TCGMemOpIdx oi, uintptr_t retaddr)
+{
+ return load_helper(env, addr, oi, retaddr, 1, false, true,
+ full_ldub_cmmu);
+}
+
uint8_t helper_ret_ldb_cmmu(CPUArchState *env, target_ulong addr,
TCGMemOpIdx oi, uintptr_t retaddr)
{
- return load_helper(env, addr, oi, retaddr, 1, false, true);
+ return full_ldub_cmmu(env, addr, oi, retaddr);
+}
+
+static uint64_t full_le_lduw_cmmu(CPUArchState *env, target_ulong addr,
+ TCGMemOpIdx oi, uintptr_t retaddr)
+{
+ return load_helper(env, addr, oi, retaddr, 2, false, true,
+ full_le_lduw_cmmu);
}
uint16_t helper_le_ldw_cmmu(CPUArchState *env, target_ulong addr,
TCGMemOpIdx oi, uintptr_t retaddr)
{
- return load_helper(env, addr, oi, retaddr, 2, false, true);
+ return full_le_lduw_cmmu(env, addr, oi, retaddr);
+}
+
+static uint64_t full_be_lduw_cmmu(CPUArchState *env, target_ulong addr,
+ TCGMemOpIdx oi, uintptr_t retaddr)
+{
+ return load_helper(env, addr, oi, retaddr, 2, true, true,
+ full_be_lduw_cmmu);
}
uint16_t helper_be_ldw_cmmu(CPUArchState *env, target_ulong addr,
TCGMemOpIdx oi, uintptr_t retaddr)
{
- return load_helper(env, addr, oi, retaddr, 2, true, true);
+ return full_be_lduw_cmmu(env, addr, oi, retaddr);
+}
+
+static uint64_t full_le_ldul_cmmu(CPUArchState *env, target_ulong addr,
+ TCGMemOpIdx oi, uintptr_t retaddr)
+{
+ return load_helper(env, addr, oi, retaddr, 4, false, true,
+ full_le_ldul_cmmu);
}
uint32_t helper_le_ldl_cmmu(CPUArchState *env, target_ulong addr,
TCGMemOpIdx oi, uintptr_t retaddr)
{
- return load_helper(env, addr, oi, retaddr, 4, false, true);
+ return full_le_ldul_cmmu(env, addr, oi, retaddr);
+}
+
+static uint64_t full_be_ldul_cmmu(CPUArchState *env, target_ulong addr,
+ TCGMemOpIdx oi, uintptr_t retaddr)
+{
+ return load_helper(env, addr, oi, retaddr, 4, true, true,
+ full_be_ldul_cmmu);
}
uint32_t helper_be_ldl_cmmu(CPUArchState *env, target_ulong addr,
TCGMemOpIdx oi, uintptr_t retaddr)
{
- return load_helper(env, addr, oi, retaddr, 4, true, true);
+ return full_be_ldul_cmmu(env, addr, oi, retaddr);
}
uint64_t helper_le_ldq_cmmu(CPUArchState *env, target_ulong addr,
TCGMemOpIdx oi, uintptr_t retaddr)
{
- return load_helper(env, addr, oi, retaddr, 8, false, true);
+ return load_helper(env, addr, oi, retaddr, 8, false, true,
+ helper_le_ldq_cmmu);
}
uint64_t helper_be_ldq_cmmu(CPUArchState *env, target_ulong addr,
TCGMemOpIdx oi, uintptr_t retaddr)
{
- return load_helper(env, addr, oi, retaddr, 8, true, true);
+ return load_helper(env, addr, oi, retaddr, 8, true, true,
+ helper_be_ldq_cmmu);
}
--
2.20.1
^ permalink raw reply related [flat|nested] 53+ messages in thread
* [Qemu-devel] [PATCH v5 11/15] cputlb: Do unaligned load recursion to outermost function
@ 2019-04-30 16:52 ` Alex Bennée
0 siblings, 0 replies; 53+ messages in thread
From: Alex Bennée @ 2019-04-30 16:52 UTC (permalink / raw)
To: qemu-devel
Cc: Alex Bennée, Richard Henderson, qemu-arm, mark.cave-ayland, cota
From: Richard Henderson <richard.henderson@linaro.org>
If we attempt to recurse from load_helper back to load_helper,
even via intermediary, we do not get all of the constants
expanded away as desired.
But if we recurse back to the original helper (or a shim that
has a consistent function signature), the operands are folded
away as desired.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
---
accel/tcg/cputlb.c | 117 +++++++++++++++++++++++++++++++++++++--------
1 file changed, 97 insertions(+), 20 deletions(-)
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
index ccbb47d8d1..e4d0c94301 100644
--- a/accel/tcg/cputlb.c
+++ b/accel/tcg/cputlb.c
@@ -1157,10 +1157,13 @@ static inline uint64_t handle_bswap(uint64_t val, int size, bool big_endian)
* is disassembled. It shouldn't be called directly by guest code.
*/
-static uint64_t load_helper(CPUArchState *env, target_ulong addr,
- TCGMemOpIdx oi, uintptr_t retaddr,
- size_t size, bool big_endian,
- bool code_read)
+typedef uint64_t FullLoadHelper(CPUArchState *env, target_ulong addr,
+ TCGMemOpIdx oi, uintptr_t retaddr);
+
+static inline uint64_t __attribute__((always_inline))
+load_helper(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi,
+ uintptr_t retaddr, size_t size, bool big_endian, bool code_read,
+ FullLoadHelper *full_load)
{
uintptr_t mmu_idx = get_mmuidx(oi);
uintptr_t index = tlb_index(env, mmu_idx, addr);
@@ -1233,8 +1236,8 @@ static uint64_t load_helper(CPUArchState *env, target_ulong addr,
do_unaligned_access:
addr1 = addr & ~(size - 1);
addr2 = addr1 + size;
- r1 = load_helper(env, addr1, oi, retaddr, size, big_endian, code_read);
- r2 = load_helper(env, addr2, oi, retaddr, size, big_endian, code_read);
+ r1 = full_load(env, addr1, oi, retaddr);
+ r2 = full_load(env, addr2, oi, retaddr);
shift = (addr & (size - 1)) * 8;
if (big_endian) {
@@ -1291,46 +1294,83 @@ static uint64_t load_helper(CPUArchState *env, target_ulong addr,
* We don't bother with this widened value for SOFTMMU_CODE_ACCESS.
*/
+static uint64_t full_ldub_mmu(CPUArchState *env, target_ulong addr,
+ TCGMemOpIdx oi, uintptr_t retaddr)
+{
+ return load_helper(env, addr, oi, retaddr, 1, false, false,
+ full_ldub_mmu);
+}
+
tcg_target_ulong helper_ret_ldub_mmu(CPUArchState *env, target_ulong addr,
TCGMemOpIdx oi, uintptr_t retaddr)
{
- return load_helper(env, addr, oi, retaddr, 1, false, false);
+ return full_ldub_mmu(env, addr, oi, retaddr);
+}
+
+static uint64_t full_le_lduw_mmu(CPUArchState *env, target_ulong addr,
+ TCGMemOpIdx oi, uintptr_t retaddr)
+{
+ return load_helper(env, addr, oi, retaddr, 2, false, false,
+ full_le_lduw_mmu);
}
tcg_target_ulong helper_le_lduw_mmu(CPUArchState *env, target_ulong addr,
TCGMemOpIdx oi, uintptr_t retaddr)
{
- return load_helper(env, addr, oi, retaddr, 2, false, false);
+ return full_le_lduw_mmu(env, addr, oi, retaddr);
+}
+
+static uint64_t full_be_lduw_mmu(CPUArchState *env, target_ulong addr,
+ TCGMemOpIdx oi, uintptr_t retaddr)
+{
+ return load_helper(env, addr, oi, retaddr, 2, true, false,
+ full_be_lduw_mmu);
}
tcg_target_ulong helper_be_lduw_mmu(CPUArchState *env, target_ulong addr,
TCGMemOpIdx oi, uintptr_t retaddr)
{
- return load_helper(env, addr, oi, retaddr, 2, true, false);
+ return full_be_lduw_mmu(env, addr, oi, retaddr);
+}
+
+static uint64_t full_le_ldul_mmu(CPUArchState *env, target_ulong addr,
+ TCGMemOpIdx oi, uintptr_t retaddr)
+{
+ return load_helper(env, addr, oi, retaddr, 4, false, false,
+ full_le_ldul_mmu);
}
tcg_target_ulong helper_le_ldul_mmu(CPUArchState *env, target_ulong addr,
TCGMemOpIdx oi, uintptr_t retaddr)
{
- return load_helper(env, addr, oi, retaddr, 4, false, false);
+ return full_le_ldul_mmu(env, addr, oi, retaddr);
+}
+
+static uint64_t full_be_ldul_mmu(CPUArchState *env, target_ulong addr,
+ TCGMemOpIdx oi, uintptr_t retaddr)
+{
+ return load_helper(env, addr, oi, retaddr, 4, true, false,
+ full_be_ldul_mmu);
}
tcg_target_ulong helper_be_ldul_mmu(CPUArchState *env, target_ulong addr,
TCGMemOpIdx oi, uintptr_t retaddr)
{
- return load_helper(env, addr, oi, retaddr, 4, true, false);
+ return full_be_ldul_mmu(env, addr, oi, retaddr);
}
uint64_t helper_le_ldq_mmu(CPUArchState *env, target_ulong addr,
TCGMemOpIdx oi, uintptr_t retaddr)
{
- return load_helper(env, addr, oi, retaddr, 8, false, false);
+ return load_helper(env, addr, oi, retaddr, 8, false, false,
+ helper_le_ldq_mmu);
}
uint64_t helper_be_ldq_mmu(CPUArchState *env, target_ulong addr,
TCGMemOpIdx oi, uintptr_t retaddr)
{
- return load_helper(env, addr, oi, retaddr, 8, true, false);
+ return load_helper(env, addr, oi, retaddr, 8, true, false,
+ helper_be_ldq_mmu);
}
/*
@@ -1613,44 +1653,81 @@ void helper_be_stq_mmu(CPUArchState *env, target_ulong addr, uint64_t val,
/* Code access functions. */
+static uint64_t full_ldub_cmmu(CPUArchState *env, target_ulong addr,
+ TCGMemOpIdx oi, uintptr_t retaddr)
+{
+ return load_helper(env, addr, oi, retaddr, 1, false, true,
+ full_ldub_cmmu);
+}
+
uint8_t helper_ret_ldb_cmmu(CPUArchState *env, target_ulong addr,
TCGMemOpIdx oi, uintptr_t retaddr)
{
- return load_helper(env, addr, oi, retaddr, 1, false, true);
+ return full_ldub_cmmu(env, addr, oi, retaddr);
+}
+
+static uint64_t full_le_lduw_cmmu(CPUArchState *env, target_ulong addr,
+ TCGMemOpIdx oi, uintptr_t retaddr)
+{
+ return load_helper(env, addr, oi, retaddr, 2, false, true,
+ full_le_lduw_cmmu);
}
uint16_t helper_le_ldw_cmmu(CPUArchState *env, target_ulong addr,
TCGMemOpIdx oi, uintptr_t retaddr)
{
- return load_helper(env, addr, oi, retaddr, 2, false, true);
+ return full_le_lduw_cmmu(env, addr, oi, retaddr);
+}
+
+static uint64_t full_be_lduw_cmmu(CPUArchState *env, target_ulong addr,
+ TCGMemOpIdx oi, uintptr_t retaddr)
+{
+ return load_helper(env, addr, oi, retaddr, 2, true, true,
+ full_be_lduw_cmmu);
}
uint16_t helper_be_ldw_cmmu(CPUArchState *env, target_ulong addr,
TCGMemOpIdx oi, uintptr_t retaddr)
{
- return load_helper(env, addr, oi, retaddr, 2, true, true);
+ return full_be_lduw_cmmu(env, addr, oi, retaddr);
+}
+
+static uint64_t full_le_ldul_cmmu(CPUArchState *env, target_ulong addr,
+ TCGMemOpIdx oi, uintptr_t retaddr)
+{
+ return load_helper(env, addr, oi, retaddr, 4, false, true,
+ full_le_ldul_cmmu);
}
uint32_t helper_le_ldl_cmmu(CPUArchState *env, target_ulong addr,
TCGMemOpIdx oi, uintptr_t retaddr)
{
- return load_helper(env, addr, oi, retaddr, 4, false, true);
+ return full_le_ldul_cmmu(env, addr, oi, retaddr);
+}
+
+static uint64_t full_be_ldul_cmmu(CPUArchState *env, target_ulong addr,
+ TCGMemOpIdx oi, uintptr_t retaddr)
+{
+ return load_helper(env, addr, oi, retaddr, 4, true, true,
+ full_be_ldul_cmmu);
}
uint32_t helper_be_ldl_cmmu(CPUArchState *env, target_ulong addr,
TCGMemOpIdx oi, uintptr_t retaddr)
{
- return load_helper(env, addr, oi, retaddr, 4, true, true);
+ return full_be_ldul_cmmu(env, addr, oi, retaddr);
}
uint64_t helper_le_ldq_cmmu(CPUArchState *env, target_ulong addr,
TCGMemOpIdx oi, uintptr_t retaddr)
{
- return load_helper(env, addr, oi, retaddr, 8, false, true);
+ return load_helper(env, addr, oi, retaddr, 8, false, true,
+ helper_le_ldq_cmmu);
}
uint64_t helper_be_ldq_cmmu(CPUArchState *env, target_ulong addr,
TCGMemOpIdx oi, uintptr_t retaddr)
{
- return load_helper(env, addr, oi, retaddr, 8, true, true);
+ return load_helper(env, addr, oi, retaddr, 8, true, true,
+ helper_be_ldq_cmmu);
}
--
2.20.1
^ permalink raw reply related [flat|nested] 53+ messages in thread
* [Qemu-devel] [PATCH v5 12/15] cputlb: Do unaligned store recursion to outermost function
@ 2019-04-30 16:52 ` Alex Bennée
0 siblings, 0 replies; 53+ messages in thread
From: Alex Bennée @ 2019-04-30 16:52 UTC (permalink / raw)
To: qemu-devel
Cc: qemu-arm, mark.cave-ayland, cota, Richard Henderson, Alex Bennée
From: Richard Henderson <richard.henderson@linaro.org>
This is less tricky than for loads, because we always fall
back to single byte stores to implement unaligned stores.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
---
accel/tcg/cputlb.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
index e4d0c94301..a083324768 100644
--- a/accel/tcg/cputlb.c
+++ b/accel/tcg/cputlb.c
@@ -1413,9 +1413,9 @@ tcg_target_ulong helper_be_ldsl_mmu(CPUArchState *env, target_ulong addr,
* Store Helpers
*/
-static void store_helper(CPUArchState *env, target_ulong addr, uint64_t val,
- TCGMemOpIdx oi, uintptr_t retaddr, size_t size,
- bool big_endian)
+static inline void __attribute__((always_inline))
+store_helper(CPUArchState *env, target_ulong addr, uint64_t val,
+ TCGMemOpIdx oi, uintptr_t retaddr, size_t size, bool big_endian)
{
uintptr_t mmu_idx = get_mmuidx(oi);
uintptr_t index = tlb_index(env, mmu_idx, addr);
@@ -1514,7 +1514,7 @@ static void store_helper(CPUArchState *env, target_ulong addr, uint64_t val,
/* Little-endian extract. */
val8 = val >> (i * 8);
}
- store_helper(env, addr + i, val8, oi, retaddr, 1, big_endian);
+ helper_ret_stb_mmu(env, addr + i, val8, oi, retaddr);
}
return;
}
--
2.20.1
^ permalink raw reply related [flat|nested] 53+ messages in thread
* [Qemu-devel] [PATCH v5 12/15] cputlb: Do unaligned store recursion to outermost function
@ 2019-04-30 16:52 ` Alex Bennée
0 siblings, 0 replies; 53+ messages in thread
From: Alex Bennée @ 2019-04-30 16:52 UTC (permalink / raw)
To: qemu-devel
Cc: Alex Bennée, Richard Henderson, qemu-arm, mark.cave-ayland, cota
From: Richard Henderson <richard.henderson@linaro.org>
This is less tricky than for loads, because we always fall
back to single byte stores to implement unaligned stores.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
---
accel/tcg/cputlb.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
index e4d0c94301..a083324768 100644
--- a/accel/tcg/cputlb.c
+++ b/accel/tcg/cputlb.c
@@ -1413,9 +1413,9 @@ tcg_target_ulong helper_be_ldsl_mmu(CPUArchState *env, target_ulong addr,
* Store Helpers
*/
-static void store_helper(CPUArchState *env, target_ulong addr, uint64_t val,
- TCGMemOpIdx oi, uintptr_t retaddr, size_t size,
- bool big_endian)
+static inline void __attribute__((always_inline))
+store_helper(CPUArchState *env, target_ulong addr, uint64_t val,
+ TCGMemOpIdx oi, uintptr_t retaddr, size_t size, bool big_endian)
{
uintptr_t mmu_idx = get_mmuidx(oi);
uintptr_t index = tlb_index(env, mmu_idx, addr);
@@ -1514,7 +1514,7 @@ static void store_helper(CPUArchState *env, target_ulong addr, uint64_t val,
/* Little-endian extract. */
val8 = val >> (i * 8);
}
- store_helper(env, addr + i, val8, oi, retaddr, 1, big_endian);
+ helper_ret_stb_mmu(env, addr + i, val8, oi, retaddr);
}
return;
}
--
2.20.1
^ permalink raw reply related [flat|nested] 53+ messages in thread
* [Qemu-devel] [PATCH v5 13/15] Makefile: fix coverage-report reference to BUILD_DIR
@ 2019-04-30 16:52 ` Alex Bennée
0 siblings, 0 replies; 53+ messages in thread
From: Alex Bennée @ 2019-04-30 16:52 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm, mark.cave-ayland, cota, Alex Bennée
Commit 337f2311f actually claimed to do this in the commit log but
didn't actually. Oops.
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
---
Makefile | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Makefile b/Makefile
index 626a04d305..45dfe1b585 100644
--- a/Makefile
+++ b/Makefile
@@ -992,7 +992,7 @@ $(filter %.1 %.7 %.8,$(DOCS)): scripts/texi2pod.pl
%/coverage-report.html:
@mkdir -p $*
$(call quiet-command,\
- gcovr -r $(SRC_PATH) --object-directory $(BUILD_PATH) \
+ gcovr -r $(SRC_PATH) --object-directory $(BUILD_DIR) \
-p --html --html-details -o $@, \
"GEN", "coverage-report.html")
--
2.20.1
^ permalink raw reply related [flat|nested] 53+ messages in thread
* [Qemu-devel] [PATCH v5 13/15] Makefile: fix coverage-report reference to BUILD_DIR
@ 2019-04-30 16:52 ` Alex Bennée
0 siblings, 0 replies; 53+ messages in thread
From: Alex Bennée @ 2019-04-30 16:52 UTC (permalink / raw)
To: qemu-devel; +Cc: Alex Bennée, qemu-arm, mark.cave-ayland, cota
Commit 337f2311f actually claimed to do this in the commit log but
didn't actually. Oops.
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
---
Makefile | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Makefile b/Makefile
index 626a04d305..45dfe1b585 100644
--- a/Makefile
+++ b/Makefile
@@ -992,7 +992,7 @@ $(filter %.1 %.7 %.8,$(DOCS)): scripts/texi2pod.pl
%/coverage-report.html:
@mkdir -p $*
$(call quiet-command,\
- gcovr -r $(SRC_PATH) --object-directory $(BUILD_PATH) \
+ gcovr -r $(SRC_PATH) --object-directory $(BUILD_DIR) \
-p --html --html-details -o $@, \
"GEN", "coverage-report.html")
--
2.20.1
^ permalink raw reply related [flat|nested] 53+ messages in thread
* [Qemu-devel] [PATCH v5 14/15] Makefile: include per-target build directories in coverage report
@ 2019-04-30 16:52 ` Alex Bennée
0 siblings, 0 replies; 53+ messages in thread
From: Alex Bennée @ 2019-04-30 16:52 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm, mark.cave-ayland, cota, Alex Bennée
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
---
Makefile | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/Makefile b/Makefile
index 45dfe1b585..bb17b0d692 100644
--- a/Makefile
+++ b/Makefile
@@ -992,7 +992,9 @@ $(filter %.1 %.7 %.8,$(DOCS)): scripts/texi2pod.pl
%/coverage-report.html:
@mkdir -p $*
$(call quiet-command,\
- gcovr -r $(SRC_PATH) --object-directory $(BUILD_DIR) \
+ gcovr -r $(SRC_PATH) \
+ $(foreach t, $(TARGET_DIRS), --object-directory $(BUILD_DIR)/$(t)) \
+ --object-directory $(BUILD_DIR) \
-p --html --html-details -o $@, \
"GEN", "coverage-report.html")
--
2.20.1
^ permalink raw reply related [flat|nested] 53+ messages in thread
* [Qemu-devel] [PATCH v5 14/15] Makefile: include per-target build directories in coverage report
@ 2019-04-30 16:52 ` Alex Bennée
0 siblings, 0 replies; 53+ messages in thread
From: Alex Bennée @ 2019-04-30 16:52 UTC (permalink / raw)
To: qemu-devel; +Cc: Alex Bennée, qemu-arm, mark.cave-ayland, cota
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
---
Makefile | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/Makefile b/Makefile
index 45dfe1b585..bb17b0d692 100644
--- a/Makefile
+++ b/Makefile
@@ -992,7 +992,9 @@ $(filter %.1 %.7 %.8,$(DOCS)): scripts/texi2pod.pl
%/coverage-report.html:
@mkdir -p $*
$(call quiet-command,\
- gcovr -r $(SRC_PATH) --object-directory $(BUILD_DIR) \
+ gcovr -r $(SRC_PATH) \
+ $(foreach t, $(TARGET_DIRS), --object-directory $(BUILD_DIR)/$(t)) \
+ --object-directory $(BUILD_DIR) \
-p --html --html-details -o $@, \
"GEN", "coverage-report.html")
--
2.20.1
^ permalink raw reply related [flat|nested] 53+ messages in thread
* [Qemu-devel] [PATCH v5 15/15] Makefile.target: support per-target coverage reports
@ 2019-04-30 16:52 ` Alex Bennée
0 siblings, 0 replies; 53+ messages in thread
From: Alex Bennée @ 2019-04-30 16:52 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm, mark.cave-ayland, cota, Alex Bennée
Add support for generating a single targets coverage report. Execute:
make coverage-report
In the target build directory. This coverage report only cares about
target specific blobs so only searches the target build subdirectory.
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
---
Makefile.target | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
diff --git a/Makefile.target b/Makefile.target
index ae02495951..aa5d9d6ba6 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -238,3 +238,19 @@ endif
GENERATED_FILES += config-target.h
Makefile: $(GENERATED_FILES)
+
+# Reports/Analysis
+#
+# The target specific coverage report only cares about target specific
+# blobs and not the shared code.
+#
+
+%/coverage-report.html:
+ @mkdir -p $*
+ $(call quiet-command,\
+ gcovr -r $(SRC_PATH) --object-directory $(CURDIR) \
+ -p --html --html-details -o $@, \
+ "GEN", "coverage-report.html")
+
+.PHONY: coverage-report
+coverage-report: $(CURDIR)/reports/coverage/coverage-report.html
--
2.20.1
^ permalink raw reply related [flat|nested] 53+ messages in thread
* [Qemu-devel] [PATCH v5 15/15] Makefile.target: support per-target coverage reports
@ 2019-04-30 16:52 ` Alex Bennée
0 siblings, 0 replies; 53+ messages in thread
From: Alex Bennée @ 2019-04-30 16:52 UTC (permalink / raw)
To: qemu-devel; +Cc: Alex Bennée, qemu-arm, mark.cave-ayland, cota
Add support for generating a single targets coverage report. Execute:
make coverage-report
In the target build directory. This coverage report only cares about
target specific blobs so only searches the target build subdirectory.
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
---
Makefile.target | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
diff --git a/Makefile.target b/Makefile.target
index ae02495951..aa5d9d6ba6 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -238,3 +238,19 @@ endif
GENERATED_FILES += config-target.h
Makefile: $(GENERATED_FILES)
+
+# Reports/Analysis
+#
+# The target specific coverage report only cares about target specific
+# blobs and not the shared code.
+#
+
+%/coverage-report.html:
+ @mkdir -p $*
+ $(call quiet-command,\
+ gcovr -r $(SRC_PATH) --object-directory $(CURDIR) \
+ -p --html --html-details -o $@, \
+ "GEN", "coverage-report.html")
+
+.PHONY: coverage-report
+coverage-report: $(CURDIR)/reports/coverage/coverage-report.html
--
2.20.1
^ permalink raw reply related [flat|nested] 53+ messages in thread
* Re: [Qemu-devel] [PATCH v5 03/15] tests/tcg/aarch64: add system boot.S
2019-04-30 16:52 ` Alex Bennée
(?)
@ 2019-05-01 14:37 ` Richard Henderson
2019-05-01 14:57 ` Alex Bennée
2019-05-08 17:45 ` Alex Bennée
-1 siblings, 2 replies; 53+ messages in thread
From: Richard Henderson @ 2019-05-01 14:37 UTC (permalink / raw)
To: Alex Bennée, qemu-devel; +Cc: qemu-arm, mark.cave-ayland, cota
On 4/30/19 9:52 AM, Alex Bennée wrote:
> +.error:
> + .string "Terminated by exception.\n"
Put it in .rodata just because we can?
> + /* Page table setup (identity mapping). */
> + adrp x0, ttb
> + add x0, x0, :lo12:ttb
You are in control of the layout of the executable,
and adr has a 1MB range. Why use adrp+add?
> + /* Create some (big) pages */
> + adr x1, . /* phys address */
> + bic x1, x1, #(1 << 30) - 1 /* 1GB block alignment */
Do you really want 1GB pages? You'll pretty much only be able to test valid
memory operations with that. Which is also true until there's something other
than an exit for the exception vector... but ya know what I mean.
> + /* Setup some stack space and enter the test code.
> + * Assume everthing except the return value is garbage when we
> + * return, we won't need it.
> + */
> + adrp x0, stack
> + add x0, x0, :lo12:stack
> + mov sp, x0
You need a pointer to the end of the stack, not the beginning.
Again, I think this could be just
adr sp, stack_end
Also, there's tab/space confusion all through this file.
IMO, this is assembly, so it *should* be tabs.
> @@ -0,0 +1,22 @@
> +ENTRY(__start)
> +
> +SECTIONS
> +{
> + /* virt machine, RAM starts at 1gb */
> + . = (1 << 30);
> + .text : {
> + *(.text)
> + }
> + .data : {
> + *(.data)
> + }
> + .rodata : {
> + *(.rodata)
> + }
If you ever wanted to make this read-only, swap .rodata before .data, so that
it's next to .text.
r~
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [Qemu-devel] [PATCH v5 05/15] tests/tcg/minilib: support %c format char
2019-04-30 16:52 ` Alex Bennée
(?)
@ 2019-05-01 14:40 ` Richard Henderson
-1 siblings, 0 replies; 53+ messages in thread
From: Richard Henderson @ 2019-05-01 14:40 UTC (permalink / raw)
To: Alex Bennée, qemu-devel; +Cc: qemu-arm, mark.cave-ayland, cota
On 4/30/19 9:52 AM, Alex Bennée wrote:
> @@ -119,6 +119,10 @@ void ml_printf(const char *fmt, ...)
> str = va_arg(ap, char*);
> print_str(str);
> break;
> + case 'c':
> + c = (char) va_arg(ap, int);
> + __sys_outc(c);
> + break;
The assignment and cast are both unnecessary.
You could just as well write
__sys_outc(va_arg(ap, int))
but it's not wrong so
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
r~
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [Qemu-devel] [PATCH v5 06/15] tests/tcg/multiarch: expand system memory test to cover more
2019-04-30 16:52 ` Alex Bennée
(?)
@ 2019-05-01 14:44 ` Richard Henderson
-1 siblings, 0 replies; 53+ messages in thread
From: Richard Henderson @ 2019-05-01 14:44 UTC (permalink / raw)
To: Alex Bennée, qemu-devel; +Cc: qemu-arm, mark.cave-ayland, cota
On 4/30/19 9:52 AM, Alex Bennée wrote:
> +int do_signed_reads(bool neg_first)
> +{
> + int r = 0;
> + int off = 0;
> +
> + while (r == 0 && off < 8) {
> + r = read_test_data_s8(off, neg_first ^ (off & 1));
> + r |= read_test_data_s16(off, !(neg_first ^ (off & 1)));
> + r |= read_test_data_s32(off, !(neg_first ^ (off & 1)));
You're testing unaligned reads here.
While admirable, and necessary, that's going to limit the number of guests on
which you can run this test.
Do you perhaps want a compiler command-line -DALIGNED_ONLY to control this?
Otherwise,
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
r~
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [Qemu-devel] [PATCH v5 09/15] accel/tcg: remove softmmu_template.h
2019-04-30 16:52 ` Alex Bennée
(?)
@ 2019-05-01 14:46 ` Richard Henderson
2019-05-01 15:10 ` Alex Bennée
-1 siblings, 1 reply; 53+ messages in thread
From: Richard Henderson @ 2019-05-01 14:46 UTC (permalink / raw)
To: Alex Bennée, qemu-devel; +Cc: qemu-arm, mark.cave-ayland, cota
On 4/30/19 9:52 AM, Alex Bennée wrote:
> Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
> ---
> accel/tcg/softmmu_template.h | 454 -----------------------------------
> 1 file changed, 454 deletions(-)
> delete mode 100644 accel/tcg/softmmu_template.h
Why is this separate from patch 7?
r~
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [Qemu-devel] [PATCH v5 13/15] Makefile: fix coverage-report reference to BUILD_DIR
2019-04-30 16:52 ` Alex Bennée
(?)
@ 2019-05-01 14:48 ` Richard Henderson
-1 siblings, 0 replies; 53+ messages in thread
From: Richard Henderson @ 2019-05-01 14:48 UTC (permalink / raw)
To: Alex Bennée, qemu-devel; +Cc: qemu-arm, mark.cave-ayland, cota
On 4/30/19 9:52 AM, Alex Bennée wrote:
> Commit 337f2311f actually claimed to do this in the commit log but
> didn't actually. Oops.
>
> Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
> ---
> Makefile | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
r~
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [Qemu-devel] [PATCH v5 14/15] Makefile: include per-target build directories in coverage report
2019-04-30 16:52 ` Alex Bennée
(?)
@ 2019-05-01 14:49 ` Richard Henderson
-1 siblings, 0 replies; 53+ messages in thread
From: Richard Henderson @ 2019-05-01 14:49 UTC (permalink / raw)
To: Alex Bennée, qemu-devel; +Cc: qemu-arm, mark.cave-ayland, cota
On 4/30/19 9:52 AM, Alex Bennée wrote:
> Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
> ---
> Makefile | 4 +++-
> 1 file changed, 3 insertions(+), 1 deletion(-)
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
r~
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [Qemu-devel] [PATCH v5 15/15] Makefile.target: support per-target coverage reports
2019-04-30 16:52 ` Alex Bennée
(?)
@ 2019-05-01 14:50 ` Richard Henderson
-1 siblings, 0 replies; 53+ messages in thread
From: Richard Henderson @ 2019-05-01 14:50 UTC (permalink / raw)
To: Alex Bennée, qemu-devel; +Cc: qemu-arm, mark.cave-ayland, cota
On 4/30/19 9:52 AM, Alex Bennée wrote:
> Add support for generating a single targets coverage report. Execute:
>
> make coverage-report
>
> In the target build directory. This coverage report only cares about
> target specific blobs so only searches the target build subdirectory.
>
> Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
> ---
> Makefile.target | 16 ++++++++++++++++
> 1 file changed, 16 insertions(+)
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
r~
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [Qemu-devel] [PATCH v5 03/15] tests/tcg/aarch64: add system boot.S
@ 2019-05-01 14:57 ` Alex Bennée
0 siblings, 0 replies; 53+ messages in thread
From: Alex Bennée @ 2019-05-01 14:57 UTC (permalink / raw)
To: Richard Henderson; +Cc: qemu-devel, qemu-arm, mark.cave-ayland, cota
Richard Henderson <richard.henderson@linaro.org> writes:
> On 4/30/19 9:52 AM, Alex Bennée wrote:
>> +.error:
>> + .string "Terminated by exception.\n"
>
> Put it in .rodata just because we can?
Sure.
>
>> + /* Page table setup (identity mapping). */
>> + adrp x0, ttb
>> + add x0, x0, :lo12:ttb
>
> You are in control of the layout of the executable,
> and adr has a 1MB range. Why use adrp+add?
Ok.
>
>> + /* Create some (big) pages */
>> + adr x1, . /* phys address */
>> + bic x1, x1, #(1 << 30) - 1 /* 1GB block alignment */
>
> Do you really want 1GB pages? You'll pretty much only be able to test valid
> memory operations with that. Which is also true until there's something other
> than an exit for the exception vector... but ya know what I mean.
Yeah we can do better here. I mainly went with what libgloss had setup
because I was finding it hard to get find a nice summary of the various
page table formats. I want big enough that I don't have to futz around
create multiple page entries and ideally have some fault-able regions as
well.
>
>> + /* Setup some stack space and enter the test code.
>> + * Assume everthing except the return value is garbage when we
>> + * return, we won't need it.
>> + */
>> + adrp x0, stack
>> + add x0, x0, :lo12:stack
>> + mov sp, x0
>
> You need a pointer to the end of the stack, not the beginning.
> Again, I think this could be just
>
> adr sp, stack_end
lol, I guess the page table was being crapped over....
>
> Also, there's tab/space confusion all through this file.
> IMO, this is assembly, so it *should* be tabs.
That will probably be my editor getting confused because .S implies cpp
>
>> @@ -0,0 +1,22 @@
>> +ENTRY(__start)
>> +
>> +SECTIONS
>> +{
>> + /* virt machine, RAM starts at 1gb */
>> + . = (1 << 30);
>> + .text : {
>> + *(.text)
>> + }
>> + .data : {
>> + *(.data)
>> + }
>> + .rodata : {
>> + *(.rodata)
>> + }
>
> If you ever wanted to make this read-only, swap .rodata before .data, so that
> it's next to .text.
OK
>
>
> r~
--
Alex Bennée
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [Qemu-devel] [PATCH v5 03/15] tests/tcg/aarch64: add system boot.S
@ 2019-05-01 14:57 ` Alex Bennée
0 siblings, 0 replies; 53+ messages in thread
From: Alex Bennée @ 2019-05-01 14:57 UTC (permalink / raw)
To: Richard Henderson; +Cc: qemu-arm, mark.cave-ayland, qemu-devel, cota
Richard Henderson <richard.henderson@linaro.org> writes:
> On 4/30/19 9:52 AM, Alex Bennée wrote:
>> +.error:
>> + .string "Terminated by exception.\n"
>
> Put it in .rodata just because we can?
Sure.
>
>> + /* Page table setup (identity mapping). */
>> + adrp x0, ttb
>> + add x0, x0, :lo12:ttb
>
> You are in control of the layout of the executable,
> and adr has a 1MB range. Why use adrp+add?
Ok.
>
>> + /* Create some (big) pages */
>> + adr x1, . /* phys address */
>> + bic x1, x1, #(1 << 30) - 1 /* 1GB block alignment */
>
> Do you really want 1GB pages? You'll pretty much only be able to test valid
> memory operations with that. Which is also true until there's something other
> than an exit for the exception vector... but ya know what I mean.
Yeah we can do better here. I mainly went with what libgloss had setup
because I was finding it hard to get find a nice summary of the various
page table formats. I want big enough that I don't have to futz around
create multiple page entries and ideally have some fault-able regions as
well.
>
>> + /* Setup some stack space and enter the test code.
>> + * Assume everthing except the return value is garbage when we
>> + * return, we won't need it.
>> + */
>> + adrp x0, stack
>> + add x0, x0, :lo12:stack
>> + mov sp, x0
>
> You need a pointer to the end of the stack, not the beginning.
> Again, I think this could be just
>
> adr sp, stack_end
lol, I guess the page table was being crapped over....
>
> Also, there's tab/space confusion all through this file.
> IMO, this is assembly, so it *should* be tabs.
That will probably be my editor getting confused because .S implies cpp
>
>> @@ -0,0 +1,22 @@
>> +ENTRY(__start)
>> +
>> +SECTIONS
>> +{
>> + /* virt machine, RAM starts at 1gb */
>> + . = (1 << 30);
>> + .text : {
>> + *(.text)
>> + }
>> + .data : {
>> + *(.data)
>> + }
>> + .rodata : {
>> + *(.rodata)
>> + }
>
> If you ever wanted to make this read-only, swap .rodata before .data, so that
> it's next to .text.
OK
>
>
> r~
--
Alex Bennée
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [Qemu-devel] [PATCH v5 09/15] accel/tcg: remove softmmu_template.h
@ 2019-05-01 15:10 ` Alex Bennée
0 siblings, 0 replies; 53+ messages in thread
From: Alex Bennée @ 2019-05-01 15:10 UTC (permalink / raw)
To: Richard Henderson; +Cc: qemu-devel, qemu-arm, mark.cave-ayland, cota
Richard Henderson <richard.henderson@linaro.org> writes:
> On 4/30/19 9:52 AM, Alex Bennée wrote:
>> Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
>> ---
>> accel/tcg/softmmu_template.h | 454 -----------------------------------
>> 1 file changed, 454 deletions(-)
>> delete mode 100644 accel/tcg/softmmu_template.h
>
> Why is this separate from patch 7?
No particular reason, we can certainly merge them.
>
>
> r~
--
Alex Bennée
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [Qemu-devel] [PATCH v5 09/15] accel/tcg: remove softmmu_template.h
@ 2019-05-01 15:10 ` Alex Bennée
0 siblings, 0 replies; 53+ messages in thread
From: Alex Bennée @ 2019-05-01 15:10 UTC (permalink / raw)
To: Richard Henderson; +Cc: qemu-arm, mark.cave-ayland, qemu-devel, cota
Richard Henderson <richard.henderson@linaro.org> writes:
> On 4/30/19 9:52 AM, Alex Bennée wrote:
>> Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
>> ---
>> accel/tcg/softmmu_template.h | 454 -----------------------------------
>> 1 file changed, 454 deletions(-)
>> delete mode 100644 accel/tcg/softmmu_template.h
>
> Why is this separate from patch 7?
No particular reason, we can certainly merge them.
>
>
> r~
--
Alex Bennée
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [Qemu-devel] [PATCH v5 01/15] tests/tcg/multiarch: add support for multiarch system tests
2019-04-30 16:52 ` Alex Bennée
(?)
@ 2019-05-01 18:35 ` Richard Henderson
-1 siblings, 0 replies; 53+ messages in thread
From: Richard Henderson @ 2019-05-01 18:35 UTC (permalink / raw)
To: Alex Bennée, qemu-devel; +Cc: qemu-arm, mark.cave-ayland, cota
On 4/30/19 9:52 AM, Alex Bennée wrote:
> We can certainly support some common tests for system emulation that
> make use of our minimal defined boot.S support. It will still be up to
> individual architectures to ensure they build so we provide a
> MULTIARCH_TESTS variable that they can tack onto TESTS themselves.
>
> Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
> ---
> tests/tcg/Makefile | 1 +
> tests/tcg/multiarch/system/Makefile.softmmu-target | 14 ++++++++++++++
> 2 files changed, 15 insertions(+)
> create mode 100644 tests/tcg/multiarch/system/Makefile.softmmu-target
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
r~
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [Qemu-devel] [PATCH v5 02/15] tests/tcg/multiarch: add hello world system test
2019-04-30 16:52 ` Alex Bennée
(?)
@ 2019-05-01 18:35 ` Richard Henderson
-1 siblings, 0 replies; 53+ messages in thread
From: Richard Henderson @ 2019-05-01 18:35 UTC (permalink / raw)
To: Alex Bennée, qemu-devel; +Cc: qemu-arm, mark.cave-ayland, cota
On 4/30/19 9:52 AM, Alex Bennée wrote:
> This is not really i386 only, we can have the same test for all
> architectures supporting system tests.
>
> Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
> ---
> tests/tcg/i386/Makefile.softmmu-target | 2 +-
> tests/tcg/{i386 => multiarch}/system/hello.c | 0
> 2 files changed, 1 insertion(+), 1 deletion(-)
> rename tests/tcg/{i386 => multiarch}/system/hello.c (100%)
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
r~
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [Qemu-devel] [PATCH v5 04/15] tests/tcg/multiarch: move the system memory test
2019-04-30 16:52 ` Alex Bennée
(?)
@ 2019-05-01 18:35 ` Richard Henderson
-1 siblings, 0 replies; 53+ messages in thread
From: Richard Henderson @ 2019-05-01 18:35 UTC (permalink / raw)
To: Alex Bennée, qemu-devel; +Cc: qemu-arm, mark.cave-ayland, cota
On 4/30/19 9:52 AM, Alex Bennée wrote:
> There is nothing inherently architecture specific about the memory
> test although we may have to manage different restrictions of
> unaligned access across architectures.
>
> Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
> ---
> tests/tcg/{i386 => multiarch}/system/memory.c | 0
> 1 file changed, 0 insertions(+), 0 deletions(-)
> rename tests/tcg/{i386 => multiarch}/system/memory.c (100%)
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
r~
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [Qemu-devel] [PATCH v5 00/15] demacro softmmu (plus tests/coverage)
2019-04-30 16:52 ` Alex Bennée
` (15 preceding siblings ...)
(?)
@ 2019-05-01 18:39 ` Richard Henderson
2019-05-03 19:28 ` Alex Bennée
-1 siblings, 1 reply; 53+ messages in thread
From: Richard Henderson @ 2019-05-01 18:39 UTC (permalink / raw)
To: Alex Bennée, qemu-devel; +Cc: qemu-arm, mark.cave-ayland, cota
On 4/30/19 9:52 AM, Alex Bennée wrote:
> I've also moved the existing system memory test and made it multiarch
> and added the bootstrapping for aarch64 system tests. I would like to
> add support for Big Endian as well but I didn't want to delay the
> posting of the series. It would also be nice to exercise the
> ioread/write paths and other handling but I leave this as an exercise
> for later.
Somewhere in there you're adding
-chardev file,path=hello.out,id=output
but there's no corresponding use of the chardev.
Which, somehow doesn't seem to matter to your aarch64
testcase, but when I try this for alpha I truly get
no output at all. I needed
-serial chardev:output
to populate the file.
r~
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [Qemu-devel] [PATCH v5 00/15] demacro softmmu (plus tests/coverage)
@ 2019-05-03 19:28 ` Alex Bennée
0 siblings, 0 replies; 53+ messages in thread
From: Alex Bennée @ 2019-05-03 19:28 UTC (permalink / raw)
To: Richard Henderson; +Cc: qemu-devel, qemu-arm, mark.cave-ayland, cota
Richard Henderson <richard.henderson@linaro.org> writes:
> On 4/30/19 9:52 AM, Alex Bennée wrote:
>> I've also moved the existing system memory test and made it multiarch
>> and added the bootstrapping for aarch64 system tests. I would like to
>> add support for Big Endian as well but I didn't want to delay the
>> posting of the series. It would also be nice to exercise the
>> ioread/write paths and other handling but I leave this as an exercise
>> for later.
>
> Somewhere in there you're adding
>
> -chardev file,path=hello.out,id=output
It's in the default runner config in tests/tcg/Makefile
> but there's no corresponding use of the chardev.
> Which, somehow doesn't seem to matter to your aarch64
> testcase,
Argh.. it's because -semihosting is different from -serial and doesn't
allow the usual redirection rules you get with a chardev..
> but when I try this for alpha I truly get
> no output at all. I needed
>
> -serial chardev:output
or -serial chadev,id=output?
>
> to populate the file.
>
>
> r~
--
Alex Bennée
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [Qemu-devel] [PATCH v5 00/15] demacro softmmu (plus tests/coverage)
@ 2019-05-03 19:28 ` Alex Bennée
0 siblings, 0 replies; 53+ messages in thread
From: Alex Bennée @ 2019-05-03 19:28 UTC (permalink / raw)
To: Richard Henderson; +Cc: qemu-arm, mark.cave-ayland, qemu-devel, cota
Richard Henderson <richard.henderson@linaro.org> writes:
> On 4/30/19 9:52 AM, Alex Bennée wrote:
>> I've also moved the existing system memory test and made it multiarch
>> and added the bootstrapping for aarch64 system tests. I would like to
>> add support for Big Endian as well but I didn't want to delay the
>> posting of the series. It would also be nice to exercise the
>> ioread/write paths and other handling but I leave this as an exercise
>> for later.
>
> Somewhere in there you're adding
>
> -chardev file,path=hello.out,id=output
It's in the default runner config in tests/tcg/Makefile
> but there's no corresponding use of the chardev.
> Which, somehow doesn't seem to matter to your aarch64
> testcase,
Argh.. it's because -semihosting is different from -serial and doesn't
allow the usual redirection rules you get with a chardev..
> but when I try this for alpha I truly get
> no output at all. I needed
>
> -serial chardev:output
or -serial chadev,id=output?
>
> to populate the file.
>
>
> r~
--
Alex Bennée
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [Qemu-devel] [PATCH v5 03/15] tests/tcg/aarch64: add system boot.S
2019-05-01 14:37 ` Richard Henderson
2019-05-01 14:57 ` Alex Bennée
@ 2019-05-08 17:45 ` Alex Bennée
1 sibling, 0 replies; 53+ messages in thread
From: Alex Bennée @ 2019-05-08 17:45 UTC (permalink / raw)
To: Richard Henderson; +Cc: qemu-arm, mark.cave-ayland, qemu-devel, cota
Richard Henderson <richard.henderson@linaro.org> writes:
> On 4/30/19 9:52 AM, Alex Bennée wrote:
>> +.error:
>> + .string "Terminated by exception.\n"
>
> Put it in .rodata just because we can?
>
>> + /* Page table setup (identity mapping). */
>> + adrp x0, ttb
>> + add x0, x0, :lo12:ttb
>
> You are in control of the layout of the executable,
> and adr has a 1MB range. Why use adrp+add?
Well I have to now as I've aligned .data with:
/* align r/w section to next 2mb */
. = ALIGN(1 << 21);
>
>> + /* Create some (big) pages */
>> + adr x1, . /* phys address */
>> + bic x1, x1, #(1 << 30) - 1 /* 1GB block alignment */
>
> Do you really want 1GB pages? You'll pretty much only be able to test valid
> memory operations with that. Which is also true until there's something other
> than an exit for the exception vector... but ya know what I mean.
Not using it for testing but I'm trying to set-up a 2 stage translation
so we get:
1gb->1gb+2mb = .text/.rodata
1gb+2mb->1gb+4mb = .data/.bss
>
>> + /* Setup some stack space and enter the test code.
>> + * Assume everthing except the return value is garbage when we
>> + * return, we won't need it.
>> + */
>> + adrp x0, stack
>> + add x0, x0, :lo12:stack
>> + mov sp, x0
>
> You need a pointer to the end of the stack, not the beginning.
> Again, I think this could be just
>
> adr sp, stack_end
>
> Also, there's tab/space confusion all through this file.
> IMO, this is assembly, so it *should* be tabs.
I'm adding an entry to editorconfig and fixing up the damage.
>
>> @@ -0,0 +1,22 @@
>> +ENTRY(__start)
>> +
>> +SECTIONS
>> +{
>> + /* virt machine, RAM starts at 1gb */
>> + . = (1 << 30);
>> + .text : {
>> + *(.text)
>> + }
>> + .data : {
>> + *(.data)
>> + }
>> + .rodata : {
>> + *(.rodata)
>> + }
>
> If you ever wanted to make this read-only, swap .rodata before .data, so that
> it's next to .text.
done.
>
>
> r~
--
Alex Bennée
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [Qemu-devel] [PATCH v5 00/15] demacro softmmu (plus tests/coverage)
2019-04-30 16:52 ` Alex Bennée
` (16 preceding siblings ...)
(?)
@ 2019-05-10 10:36 ` Alex Bennée
2019-05-10 14:55 ` Mark Cave-Ayland
2019-05-10 17:01 ` Emilio G. Cota
-1 siblings, 2 replies; 53+ messages in thread
From: Alex Bennée @ 2019-05-10 10:36 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm, mark.cave-ayland, cota
Alex Bennée <alex.bennee@linaro.org> writes:
> Hi,
>
> This is the latest iteration of the softmmu demacro series. The main
> changes from the last submission are some updates from Richard.
Ping Emilio/Mark
Would you be able to re-run your tests to check there are no other
regressions? I can then get the PR prepared for merging ;-)
> Some
> are merged into the main demacro patch (mostly casting cleanups) and
> then a series of 3 patches to out of line some of the less hot code to
> keep the main access functions a reasonable size. For example:
>
> readelf -s aarch64-softmmu/accel/tcg/cputlb.o | ag helper |\
> ag -v atomic | ag mmu | tr -s ' ' | cut -d ' ' -f 4,9 | sort -n
>
> Before:
>
> 16 helper_be_ldsl_mmu
> 16 helper_le_ldsl_mmu
> 18 helper_be_ldsw_mmu
> 18 helper_le_ldsw_mmu
> 18 helper_ret_ldsb_mmu
> 535 helper_ret_ldub_mmu
> 556 helper_ret_ldb_cmmu
> 586 helper_ret_stb_mmu
> 679 helper_le_ldul_mmu
> 681 helper_be_ldul_mmu
> 685 helper_le_ldq_mmu
> 688 helper_be_ldq_mmu
> 688 helper_le_lduw_mmu
> 693 helper_le_ldl_cmmu
> 701 helper_le_ldq_cmmu
> 701 helper_le_ldw_cmmu
> 703 helper_be_ldl_cmmu
> 704 helper_be_ldq_cmmu
> 708 helper_be_lduw_mmu
> 713 helper_be_ldw_cmmu
> 943 helper_le_stw_mmu
> 944 helper_le_stl_mmu
> 952 helper_be_stl_mmu
> 952 helper_le_stq_mmu
> 959 helper_be_stw_mmu
> 960 helper_be_stq_mmu
>
> After:
>
> 5 helper_be_ldul_mmu
> 5 helper_be_lduw_mmu
> 5 helper_le_ldul_mmu
> 5 helper_le_lduw_mmu
> 5 helper_ret_ldub_mmu
> 14 helper_be_ldl_cmmu
> 14 helper_be_ldw_cmmu
> 14 helper_le_ldl_cmmu
> 14 helper_le_ldw_cmmu
> 16 helper_be_ldsl_mmu
> 16 helper_le_ldsl_mmu
> 18 helper_be_ldsw_mmu
> 18 helper_le_ldsw_mmu
> 18 helper_ret_ldsb_mmu
> 783 helper_ret_stb_mmu
> 785 helper_ret_ldb_cmmu
> 881 helper_be_ldq_mmu
> 881 helper_le_ldq_mmu
> 889 helper_le_ldq_cmmu
> 897 helper_be_ldq_cmmu
> 1150 helper_be_stw_mmu
> 1150 helper_le_stw_mmu
> 1151 helper_be_stq_mmu
> 1151 helper_le_stl_mmu
> 1151 helper_le_stq_mmu
> 1159 helper_be_stl_mmu
>
> I've also moved the existing system memory test and made it multiarch
> and added the bootstrapping for aarch64 system tests. I would like to
> add support for Big Endian as well but I didn't want to delay the
> posting of the series. It would also be nice to exercise the
> ioread/write paths and other handling but I leave this as an exercise
> for later.
>
> There are also some minor tweaks for the code coverage reports now I'm
> running with out-of-tree builds.
>
> Alex Bennée (11):
> tests/tcg/multiarch: add support for multiarch system tests
> tests/tcg/multiarch: add hello world system test
> tests/tcg/aarch64: add system boot.S
> tests/tcg/multiarch: move the system memory test
> tests/tcg/minilib: support %c format char
> tests/tcg/multiarch: expand system memory test to cover more
> accel/tcg: demacro cputlb
> accel/tcg: remove softmmu_template.h
> Makefile: fix coverage-report reference to BUILD_DIR
> Makefile: include per-target build directories in coverage report
> Makefile.target: support per-target coverage reports
>
> Richard Henderson (4):
> cputlb: Move TLB_RECHECK handling into load/store_helper
> cputlb: Drop attribute flatten
> cputlb: Do unaligned load recursion to outermost function
> cputlb: Do unaligned store recursion to outermost function
>
> Makefile | 4 +-
> Makefile.target | 16 +
> accel/tcg/cputlb.c | 626 +++++++++++++++---
> accel/tcg/softmmu_template.h | 454 -------------
> tests/tcg/Makefile | 1 +
> tests/tcg/aarch64/Makefile.softmmu-target | 32 +
> tests/tcg/aarch64/system/boot.S | 200 ++++++
> tests/tcg/aarch64/system/kernel.ld | 22 +
> tests/tcg/i386/Makefile.softmmu-target | 2 +-
> tests/tcg/i386/system/memory.c | 243 -------
> tests/tcg/minilib/printf.c | 6 +-
> .../multiarch/system/Makefile.softmmu-target | 14 +
> tests/tcg/{i386 => multiarch}/system/hello.c | 0
> tests/tcg/multiarch/system/memory.c | 427 ++++++++++++
> 14 files changed, 1267 insertions(+), 780 deletions(-)
> delete mode 100644 accel/tcg/softmmu_template.h
> create mode 100644 tests/tcg/aarch64/Makefile.softmmu-target
> create mode 100644 tests/tcg/aarch64/system/boot.S
> create mode 100644 tests/tcg/aarch64/system/kernel.ld
> delete mode 100644 tests/tcg/i386/system/memory.c
> create mode 100644 tests/tcg/multiarch/system/Makefile.softmmu-target
> rename tests/tcg/{i386 => multiarch}/system/hello.c (100%)
> create mode 100644 tests/tcg/multiarch/system/memory.c
--
Alex Bennée
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [Qemu-devel] [PATCH v5 00/15] demacro softmmu (plus tests/coverage)
2019-05-10 10:36 ` Alex Bennée
@ 2019-05-10 14:55 ` Mark Cave-Ayland
2019-05-10 17:01 ` Emilio G. Cota
1 sibling, 0 replies; 53+ messages in thread
From: Mark Cave-Ayland @ 2019-05-10 14:55 UTC (permalink / raw)
To: Alex Bennée, qemu-devel; +Cc: qemu-arm, cota
On 10/05/2019 11:36, Alex Bennée wrote:
> Alex Bennée <alex.bennee@linaro.org> writes:
>
>> Hi,
>>
>> This is the latest iteration of the softmmu demacro series. The main
>> changes from the last submission are some updates from Richard.
>
> Ping Emilio/Mark
>
> Would you be able to re-run your tests to check there are no other
> regressions? I can then get the PR prepared for merging ;-)
Hi Alex,
Sorry for the delay - I've run this through my complete set of PPC/SPARC32/SPARC64
test images and no regressions as far as I can see with this latest version.
Tested-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
ATB,
Mark.
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [Qemu-devel] [PATCH v5 00/15] demacro softmmu (plus tests/coverage)
2019-05-10 10:36 ` Alex Bennée
2019-05-10 14:55 ` Mark Cave-Ayland
@ 2019-05-10 17:01 ` Emilio G. Cota
1 sibling, 0 replies; 53+ messages in thread
From: Emilio G. Cota @ 2019-05-10 17:01 UTC (permalink / raw)
To: Alex Bennée; +Cc: qemu-arm, mark.cave-ayland, qemu-devel
On Fri, May 10, 2019 at 11:36:33 +0100, Alex Bennée wrote:
> Ping Emilio/Mark
>
> Would you be able to re-run your tests to check there are no other
> regressions? I can then get the PR prepared for merging ;-)
I'll try to run some tests next week, but I am not sure I'll
have time to do so. If I were you I'd go ahead with the PR --
it's best to have these type of changes merged early in the
development cycle.
Thanks,
Emilio
^ permalink raw reply [flat|nested] 53+ messages in thread
end of thread, other threads:[~2019-05-10 17:04 UTC | newest]
Thread overview: 53+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-04-30 16:52 [Qemu-devel] [PATCH v5 00/15] demacro softmmu (plus tests/coverage) Alex Bennée
2019-04-30 16:52 ` Alex Bennée
2019-04-30 16:52 ` [Qemu-devel] [PATCH v5 01/15] tests/tcg/multiarch: add support for multiarch system tests Alex Bennée
2019-04-30 16:52 ` Alex Bennée
2019-05-01 18:35 ` Richard Henderson
2019-04-30 16:52 ` [Qemu-devel] [PATCH v5 02/15] tests/tcg/multiarch: add hello world system test Alex Bennée
2019-04-30 16:52 ` Alex Bennée
2019-05-01 18:35 ` Richard Henderson
2019-04-30 16:52 ` [Qemu-devel] [PATCH v5 03/15] tests/tcg/aarch64: add system boot.S Alex Bennée
2019-04-30 16:52 ` Alex Bennée
2019-05-01 14:37 ` Richard Henderson
2019-05-01 14:57 ` Alex Bennée
2019-05-01 14:57 ` Alex Bennée
2019-05-08 17:45 ` Alex Bennée
2019-04-30 16:52 ` [Qemu-devel] [PATCH v5 04/15] tests/tcg/multiarch: move the system memory test Alex Bennée
2019-04-30 16:52 ` Alex Bennée
2019-05-01 18:35 ` Richard Henderson
2019-04-30 16:52 ` [Qemu-devel] [PATCH v5 05/15] tests/tcg/minilib: support %c format char Alex Bennée
2019-04-30 16:52 ` Alex Bennée
2019-05-01 14:40 ` Richard Henderson
2019-04-30 16:52 ` [Qemu-devel] [PATCH v5 06/15] tests/tcg/multiarch: expand system memory test to cover more Alex Bennée
2019-04-30 16:52 ` Alex Bennée
2019-05-01 14:44 ` Richard Henderson
2019-04-30 16:52 ` [Qemu-devel] [PATCH v5 07/15] accel/tcg: demacro cputlb Alex Bennée
2019-04-30 16:52 ` Alex Bennée
2019-04-30 16:52 ` [Qemu-devel] [PATCH v5 08/15] cputlb: Move TLB_RECHECK handling into load/store_helper Alex Bennée
2019-04-30 16:52 ` Alex Bennée
2019-04-30 16:52 ` [Qemu-devel] [PATCH v5 09/15] accel/tcg: remove softmmu_template.h Alex Bennée
2019-04-30 16:52 ` Alex Bennée
2019-05-01 14:46 ` Richard Henderson
2019-05-01 15:10 ` Alex Bennée
2019-05-01 15:10 ` Alex Bennée
2019-04-30 16:52 ` [Qemu-devel] [PATCH v5 10/15] cputlb: Drop attribute flatten Alex Bennée
2019-04-30 16:52 ` Alex Bennée
2019-04-30 16:52 ` [Qemu-devel] [PATCH v5 11/15] cputlb: Do unaligned load recursion to outermost function Alex Bennée
2019-04-30 16:52 ` Alex Bennée
2019-04-30 16:52 ` [Qemu-devel] [PATCH v5 12/15] cputlb: Do unaligned store " Alex Bennée
2019-04-30 16:52 ` Alex Bennée
2019-04-30 16:52 ` [Qemu-devel] [PATCH v5 13/15] Makefile: fix coverage-report reference to BUILD_DIR Alex Bennée
2019-04-30 16:52 ` Alex Bennée
2019-05-01 14:48 ` Richard Henderson
2019-04-30 16:52 ` [Qemu-devel] [PATCH v5 14/15] Makefile: include per-target build directories in coverage report Alex Bennée
2019-04-30 16:52 ` Alex Bennée
2019-05-01 14:49 ` Richard Henderson
2019-04-30 16:52 ` [Qemu-devel] [PATCH v5 15/15] Makefile.target: support per-target coverage reports Alex Bennée
2019-04-30 16:52 ` Alex Bennée
2019-05-01 14:50 ` Richard Henderson
2019-05-01 18:39 ` [Qemu-devel] [PATCH v5 00/15] demacro softmmu (plus tests/coverage) Richard Henderson
2019-05-03 19:28 ` Alex Bennée
2019-05-03 19:28 ` Alex Bennée
2019-05-10 10:36 ` Alex Bennée
2019-05-10 14:55 ` Mark Cave-Ayland
2019-05-10 17:01 ` Emilio G. Cota
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.