aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.travis.yml2
-rw-r--r--CODING_STYLE.rst37
-rw-r--r--MAINTAINERS12
-rw-r--r--Makefile11
-rwxr-xr-xconfigure48
-rw-r--r--contrib/plugins/Makefile42
-rw-r--r--contrib/plugins/hotblocks.c (renamed from tests/plugin/hotblocks.c)0
-rw-r--r--contrib/plugins/hotpages.c (renamed from tests/plugin/hotpages.c)0
-rw-r--r--contrib/plugins/howvec.c (renamed from tests/plugin/howvec.c)0
-rw-r--r--contrib/plugins/lockstep.c (renamed from tests/plugin/lockstep.c)0
-rw-r--r--default-configs/riscv64-softmmu.mak1
-rw-r--r--docs/devel/tcg-plugins.rst146
-rw-r--r--docs/system/deprecated.rst7
-rw-r--r--hw/arm/xilinx_zynq.c1
-rw-r--r--hw/arm/xlnx-versal.c1
-rw-r--r--hw/arm/xlnx-zynqmp.c2
-rw-r--r--hw/char/Kconfig9
-rw-r--r--hw/char/mchp_pfsoc_mmuart.c86
-rw-r--r--hw/char/meson.build3
-rw-r--r--hw/char/riscv_htif.c (renamed from hw/riscv/riscv_htif.c)2
-rw-r--r--hw/char/sifive_uart.c (renamed from hw/riscv/sifive_uart.c)2
-rw-r--r--hw/dma/Kconfig3
-rw-r--r--hw/dma/meson.build1
-rw-r--r--hw/dma/sifive_pdma.c313
-rw-r--r--hw/gpio/Kconfig3
-rw-r--r--hw/gpio/meson.build1
-rw-r--r--hw/gpio/sifive_gpio.c (renamed from hw/riscv/sifive_gpio.c)2
-rw-r--r--hw/gpio/trace-events6
-rw-r--r--hw/i386/pc_piix.c2
-rw-r--r--hw/intc/Kconfig6
-rw-r--r--hw/intc/meson.build2
-rw-r--r--hw/intc/sifive_clint.c (renamed from hw/riscv/sifive_clint.c)28
-rw-r--r--hw/intc/sifive_plic.c (renamed from hw/riscv/sifive_plic.c)2
-rw-r--r--hw/intc/sifive_plic.h (renamed from include/hw/riscv/sifive_plic.h)0
-rw-r--r--hw/misc/Kconfig12
-rw-r--r--hw/misc/meson.build6
-rw-r--r--hw/misc/sifive_e_prci.c (renamed from hw/riscv/sifive_e_prci.c)2
-rw-r--r--hw/misc/sifive_test.c (renamed from hw/riscv/sifive_test.c)4
-rw-r--r--hw/misc/sifive_u_otp.c (renamed from hw/riscv/sifive_u_otp.c)2
-rw-r--r--hw/misc/sifive_u_prci.c (renamed from hw/riscv/sifive_u_prci.c)2
-rw-r--r--hw/net/cadence_gem.c7
-rw-r--r--hw/riscv/Kconfig70
-rw-r--r--hw/riscv/meson.build12
-rw-r--r--hw/riscv/microchip_pfsoc.c437
-rw-r--r--hw/riscv/opentitan.c1
-rw-r--r--hw/riscv/riscv_hart.c3
-rw-r--r--hw/riscv/sifive_e.c12
-rw-r--r--hw/riscv/sifive_u.c41
-rw-r--r--hw/riscv/spike.c7
-rw-r--r--hw/riscv/trace-events7
-rw-r--r--hw/riscv/trace.h1
-rw-r--r--hw/riscv/virt.c9
-rw-r--r--hw/sd/Kconfig4
-rw-r--r--hw/sd/cadence_sdhci.c193
-rw-r--r--hw/sd/meson.build1
-rw-r--r--hw/usb/host-libusb.c2
-rw-r--r--include/hw/char/mchp_pfsoc_mmuart.h61
-rw-r--r--include/hw/char/riscv_htif.h (renamed from include/hw/riscv/riscv_htif.h)0
-rw-r--r--include/hw/char/sifive_uart.h (renamed from include/hw/riscv/sifive_uart.h)0
-rw-r--r--include/hw/dma/sifive_pdma.h57
-rw-r--r--include/hw/gpio/sifive_gpio.h (renamed from include/hw/riscv/sifive_gpio.h)0
-rw-r--r--include/hw/intc/sifive_clint.h (renamed from include/hw/riscv/sifive_clint.h)4
-rw-r--r--include/hw/misc/sifive_e_prci.h (renamed from include/hw/riscv/sifive_e_prci.h)0
-rw-r--r--include/hw/misc/sifive_test.h (renamed from include/hw/riscv/sifive_test.h)0
-rw-r--r--include/hw/misc/sifive_u_otp.h (renamed from include/hw/riscv/sifive_u_otp.h)0
-rw-r--r--include/hw/misc/sifive_u_prci.h (renamed from include/hw/riscv/sifive_u_prci.h)0
-rw-r--r--include/hw/net/cadence_gem.h2
-rw-r--r--include/hw/riscv/microchip_pfsoc.h133
-rw-r--r--include/hw/riscv/riscv_hart.h1
-rw-r--r--include/hw/riscv/sifive_e.h2
-rw-r--r--include/hw/riscv/sifive_u.h17
-rw-r--r--include/hw/sd/cadence_sdhci.h47
-rw-r--r--meson.build1
-rw-r--r--target/mips/translate.c12
-rw-r--r--target/riscv/cpu.c19
-rw-r--r--target/riscv/cpu.h8
-rw-r--r--target/riscv/cpu_helper.c8
-rw-r--r--target/riscv/csr.c4
-rw-r--r--tests/Makefile.include4
-rw-r--r--tests/acceptance/avocado_qemu/__init__.py12
-rw-r--r--tests/meson.build3
-rw-r--r--tests/plugin/meson.build4
-rw-r--r--tests/requirements.txt2
-rw-r--r--tests/tcg/Makefile.target3
84 files changed, 1872 insertions, 148 deletions
diff --git a/.travis.yml b/.travis.yml
index 1d0ade0a13..65341634d0 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -138,7 +138,7 @@ jobs:
# Just build tools and run minimal unit and softfloat checks
- - name: "GCC check-softfloat (user)"
+ - name: "GCC check-unit and check-softfloat"
env:
- BASE_CONFIG="--enable-tools"
- CONFIG="--disable-user --disable-system"
diff --git a/CODING_STYLE.rst b/CODING_STYLE.rst
index 427699e0e4..8b13ef0669 100644
--- a/CODING_STYLE.rst
+++ b/CODING_STYLE.rst
@@ -109,8 +109,41 @@ names are lower_case_with_underscores_ending_with_a_t, like the POSIX
uint64_t and family. Note that this last convention contradicts POSIX
and is therefore likely to be changed.
-When wrapping standard library functions, use the prefix ``qemu_`` to alert
-readers that they are seeing a wrapped version; otherwise avoid this prefix.
+Variable Naming Conventions
+---------------------------
+
+A number of short naming conventions exist for variables that use
+common QEMU types. For example, the architecture independent CPUState
+is often held as a ``cs`` pointer variable, whereas the concrete
+CPUArchState is usually held in a pointer called ``env``.
+
+Likewise, in device emulation code the common DeviceState is usually
+called ``dev``.
+
+Function Naming Conventions
+---------------------------
+
+Wrapped version of standard library or GLib functions use a ``qemu_``
+prefix to alert readers that they are seeing a wrapped version, for
+example ``qemu_strtol`` or ``qemu_mutex_lock``. Other utility functions
+that are widely called from across the codebase should not have any
+prefix, for example ``pstrcpy`` or bit manipulation functions such as
+``find_first_bit``.
+
+The ``qemu_`` prefix is also used for functions that modify global
+emulator state, for example ``qemu_add_vm_change_state_handler``.
+However, if there is an obvious subsystem-specific prefix it should be
+used instead.
+
+Public functions from a file or subsystem (declared in headers) tend
+to have a consistent prefix to show where they came from. For example,
+``tlb_`` for functions from ``cputlb.c`` or ``cpu_`` for functions
+from cpus.c.
+
+If there are two versions of a function to be called with or without a
+lock held, the function that expects the lock to be already held
+usually uses the suffix ``_locked``.
+
Block structure
===============
diff --git a/MAINTAINERS b/MAINTAINERS
index cf96fa8379..d817ee6c6f 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1316,6 +1316,15 @@ F: include/hw/riscv/opentitan.h
F: include/hw/char/ibex_uart.h
F: include/hw/intc/ibex_plic.h
+Microchip PolarFire SoC Icicle Kit
+M: Bin Meng <bin.meng@windriver.com>
+L: qemu-riscv@nongnu.org
+S: Supported
+F: hw/riscv/microchip_pfsoc.c
+F: hw/char/mchp_pfsoc_mmuart.c
+F: include/hw/riscv/microchip_pfsoc.h
+F: include/hw/char/mchp_pfsoc_mmuart.h
+
RX Machines
-----------
rx-gdbsim
@@ -2750,7 +2759,8 @@ M: Alex Bennée <alex.bennee@linaro.org>
S: Maintained
F: docs/devel/tcg-plugins.rst
F: plugins/
-F: tests/plugin
+F: tests/plugin/
+F: contrib/plugins/
AArch64 TCG target
M: Richard Henderson <richard.henderson@linaro.org>
diff --git a/Makefile b/Makefile
index 2ed19310cf..57f72f56c6 100644
--- a/Makefile
+++ b/Makefile
@@ -106,6 +106,12 @@ config-host.mak: $(SRC_PATH)/configure $(SRC_PATH)/pc-bios $(SRC_PATH)/VERSION
# Force configure to re-run if the API symbols are updated
ifeq ($(CONFIG_PLUGIN),y)
config-host.mak: $(SRC_PATH)/plugins/qemu-plugins.symbols
+
+.PHONY: plugins
+plugins:
+ $(call quiet-command,\
+ $(MAKE) $(SUBDIR_MAKEFLAGS) -C contrib/plugins V="$(V)", \
+ "BUILD", "example plugins")
endif
else
@@ -258,6 +264,11 @@ help:
$(call print-help,cscope,Generate cscope index)
$(call print-help,sparse,Run sparse on the QEMU source)
@echo ''
+ifeq ($(CONFIG_PLUGIN),y)
+ @echo 'Plugin targets:'
+ $(call print-help,plugins,Build the example TCG plugins)
+ @echo ''
+endif
@echo 'Cleaning targets:'
$(call print-help,clean,Remove most generated files but keep the config)
$(call print-help,distclean,Remove all generated files)
diff --git a/configure b/configure
index 4231d56bcc..2b6a1196da 100755
--- a/configure
+++ b/configure
@@ -542,6 +542,8 @@ gettext=""
bogus_os="no"
malloc_trim=""
+deprecated_features=""
+
# parse CC options first
for opt do
optarg=$(expr "x$opt" : 'x[^=]*=\(.*\)')
@@ -1720,26 +1722,25 @@ if [ "$bsd_user" = "yes" ]; then
mak_wilds="${mak_wilds} $source_path/default-configs/*-bsd-user.mak"
fi
-if test -z "$target_list_exclude"; then
- for config in $mak_wilds; do
- default_target_list="${default_target_list} $(basename "$config" .mak)"
- done
-else
- exclude_list=$(echo "$target_list_exclude" | sed -e 's/,/ /g')
- for config in $mak_wilds; do
- target="$(basename "$config" .mak)"
- exclude="no"
- for excl in $exclude_list; do
- if test "$excl" = "$target"; then
- exclude="yes"
- break;
- fi
- done
- if test "$exclude" = "no"; then
- default_target_list="${default_target_list} $target"
+if test -z "$target_list_exclude" -a -z "$target_list"; then
+ # if the user doesn't specify anything lets skip deprecating stuff
+ target_list_exclude=ppc64abi32-linux-user
+fi
+
+exclude_list=$(echo "$target_list_exclude" | sed -e 's/,/ /g')
+for config in $mak_wilds; do
+ target="$(basename "$config" .mak)"
+ exclude="no"
+ for excl in $exclude_list; do
+ if test "$excl" = "$target"; then
+ exclude="yes"
+ break;
fi
done
-fi
+ if test "$exclude" = "no"; then
+ default_target_list="${default_target_list} $target"
+ fi
+done
# Enumerate public trace backends for --help output
trace_backend_list=$(echo $(grep -le '^PUBLIC = True$' "$source_path"/scripts/tracetool/backend/*.py | sed -e 's/^.*\/\(.*\)\.py$/\1/'))
@@ -7557,7 +7558,7 @@ TARGET_SYSTBL=""
case "$target_name" in
i386)
mttcg="yes"
- gdb_xml_files="i386-32bit.xml"
+ gdb_xml_files="i386-32bit.xml"
TARGET_SYSTBL_ABI=i386
TARGET_SYSTBL=syscall_32.tbl
;;
@@ -7667,6 +7668,7 @@ case "$target_name" in
TARGET_SYSTBL_ABI=common,nospu,32
echo "TARGET_ABI32=y" >> $config_target_mak
gdb_xml_files="power64-core.xml power-fpu.xml power-altivec.xml power-spe.xml power-vsx.xml"
+ deprecated_features="ppc64abi32 ${deprecated_features}"
;;
riscv32)
TARGET_BASE_ARCH=riscv
@@ -7853,6 +7855,7 @@ DIRS="$DIRS tests/qtest tests/qemu-iotests tests/vm tests/fp tests/qgraph"
DIRS="$DIRS docs docs/interop fsdev scsi"
DIRS="$DIRS pc-bios/optionrom pc-bios/s390-ccw"
DIRS="$DIRS roms/seabios"
+DIRS="$DIRS contrib/plugins/"
LINKS="Makefile"
LINKS="$LINKS tests/tcg/lm32/Makefile"
LINKS="$LINKS tests/tcg/Makefile.target"
@@ -7864,6 +7867,7 @@ LINKS="$LINKS .gdbinit scripts" # scripts needed by relative path in .gdbinit
LINKS="$LINKS tests/acceptance tests/data"
LINKS="$LINKS tests/qemu-iotests/check"
LINKS="$LINKS python"
+LINKS="$LINKS contrib/plugins/Makefile "
UNLINK="pc-bios/keymaps"
for bios_file in \
$source_path/pc-bios/*.bin \
@@ -8011,6 +8015,12 @@ fi
touch ninjatool.stamp
fi
+if test -n "${deprecated_features}"; then
+ echo "Warning, deprecated features enabled."
+ echo "Please see docs/system/deprecated.rst"
+ echo " features: ${deprecated_features}"
+fi
+
# Save the configure command line for later reuse.
cat <<EOD >config.status
#!/bin/sh
diff --git a/contrib/plugins/Makefile b/contrib/plugins/Makefile
new file mode 100644
index 0000000000..7801b08b0d
--- /dev/null
+++ b/contrib/plugins/Makefile
@@ -0,0 +1,42 @@
+# -*- Mode: makefile -*-
+#
+# This Makefile example is fairly independent from the main makefile
+# so users can take and adapt it for their build. We only really
+# include config-host.mak so we don't have to repeat probing for
+# cflags that the main configure has already done for us.
+#
+
+BUILD_DIR := $(CURDIR)/../..
+
+include $(BUILD_DIR)/config-host.mak
+
+VPATH += $(SRC_PATH)/contrib/plugins
+
+NAMES :=
+NAMES += hotblocks
+NAMES += hotpages
+NAMES += howvec
+NAMES += lockstep
+
+SONAMES := $(addsuffix .so,$(addprefix lib,$(NAMES)))
+
+# The main QEMU uses Glib extensively so it's perfectly fine to use it
+# in plugins (which many example do).
+CFLAGS = $(GLIB_CFLAGS)
+CFLAGS += -fPIC
+CFLAGS += $(if $(findstring no-psabi,$(QEMU_CFLAGS)),-Wpsabi)
+CFLAGS += -I$(SRC_PATH)/include/qemu
+
+all: $(SONAMES)
+
+%.o: %.c
+ $(CC) $(CFLAGS) -c -o $@ $<
+
+lib%.so: %.o
+ $(CC) -shared -Wl,-soname,$@ -o $@ $^ $(LDLIBS)
+
+clean:
+ rm -f *.o *.so *.d
+ rm -Rf .libs
+
+.PHONY: all clean
diff --git a/tests/plugin/hotblocks.c b/contrib/plugins/hotblocks.c
index 3942a2ca54..3942a2ca54 100644
--- a/tests/plugin/hotblocks.c
+++ b/contrib/plugins/hotblocks.c
diff --git a/tests/plugin/hotpages.c b/contrib/plugins/hotpages.c
index ecd6c18732..ecd6c18732 100644
--- a/tests/plugin/hotpages.c
+++ b/contrib/plugins/hotpages.c
diff --git a/tests/plugin/howvec.c b/contrib/plugins/howvec.c
index 3b9a6939f2..3b9a6939f2 100644
--- a/tests/plugin/howvec.c
+++ b/contrib/plugins/howvec.c
diff --git a/tests/plugin/lockstep.c b/contrib/plugins/lockstep.c
index a696673dff..a696673dff 100644
--- a/tests/plugin/lockstep.c
+++ b/contrib/plugins/lockstep.c
diff --git a/default-configs/riscv64-softmmu.mak b/default-configs/riscv64-softmmu.mak
index aaf6d735bb..76b6195648 100644
--- a/default-configs/riscv64-softmmu.mak
+++ b/default-configs/riscv64-softmmu.mak
@@ -10,3 +10,4 @@ CONFIG_SPIKE=y
CONFIG_SIFIVE_E=y
CONFIG_SIFIVE_U=y
CONFIG_RISCV_VIRT=y
+CONFIG_MICROCHIP_PFSOC=y
diff --git a/docs/devel/tcg-plugins.rst b/docs/devel/tcg-plugins.rst
index a05990906c..0568dfa6a4 100644
--- a/docs/devel/tcg-plugins.rst
+++ b/docs/devel/tcg-plugins.rst
@@ -134,3 +134,149 @@ longer want to instrument the code. This operation is asynchronous
which means callbacks may still occur after the uninstall operation is
requested. The plugin isn't completely uninstalled until the safe work
has executed while all vCPUs are quiescent.
+
+Example Plugins
+===============
+
+There are a number of plugins included with QEMU and you are
+encouraged to contribute your own plugins plugins upstream. There is a
+`contrib/plugins` directory where they can go.
+
+- tests/plugins
+
+These are some basic plugins that are used to test and exercise the
+API during the `make check-tcg` target.
+
+- contrib/plugins/hotblocks.c
+
+The hotblocks plugin allows you to examine the where hot paths of
+execution are in your program. Once the program has finished you will
+get a sorted list of blocks reporting the starting PC, translation
+count, number of instructions and execution count. This will work best
+with linux-user execution as system emulation tends to generate
+re-translations as blocks from different programs get swapped in and
+out of system memory.
+
+If your program is single-threaded you can use the `inline` option for
+slightly faster (but not thread safe) counters.
+
+Example::
+
+ ./aarch64-linux-user/qemu-aarch64 \
+ -plugin contrib/plugins/libhotblocks.so -d plugin \
+ ./tests/tcg/aarch64-linux-user/sha1
+ SHA1=15dd99a1991e0b3826fede3deffc1feba42278e6
+ collected 903 entries in the hash table
+ pc, tcount, icount, ecount
+ 0x0000000041ed10, 1, 5, 66087
+ 0x000000004002b0, 1, 4, 66087
+ ...
+
+- contrib/plugins/hotpages.c
+
+Similar to hotblocks but this time tracks memory accesses::
+
+ ./aarch64-linux-user/qemu-aarch64 \
+ -plugin contrib/plugins/libhotpages.so -d plugin \
+ ./tests/tcg/aarch64-linux-user/sha1
+ SHA1=15dd99a1991e0b3826fede3deffc1feba42278e6
+ Addr, RCPUs, Reads, WCPUs, Writes
+ 0x000055007fe000, 0x0001, 31747952, 0x0001, 8835161
+ 0x000055007ff000, 0x0001, 29001054, 0x0001, 8780625
+ 0x00005500800000, 0x0001, 687465, 0x0001, 335857
+ 0x0000000048b000, 0x0001, 130594, 0x0001, 355
+ 0x0000000048a000, 0x0001, 1826, 0x0001, 11
+
+- contrib/plugins/howvec.c
+
+This is an instruction classifier so can be used to count different
+types of instructions. It has a number of options to refine which get
+counted. You can give an argument for a class of instructions to break
+it down fully, so for example to see all the system registers
+accesses::
+
+ ./aarch64-softmmu/qemu-system-aarch64 $(QEMU_ARGS) \
+ -append "root=/dev/sda2 systemd.unit=benchmark.service" \
+ -smp 4 -plugin ./contrib/plugins/libhowvec.so,arg=sreg -d plugin
+
+which will lead to a sorted list after the class breakdown::
+
+ Instruction Classes:
+ Class: UDEF not counted
+ Class: SVE (68 hits)
+ Class: PCrel addr (47789483 hits)
+ Class: Add/Sub (imm) (192817388 hits)
+ Class: Logical (imm) (93852565 hits)
+ Class: Move Wide (imm) (76398116 hits)
+ Class: Bitfield (44706084 hits)
+ Class: Extract (5499257 hits)
+ Class: Cond Branch (imm) (147202932 hits)
+ Class: Exception Gen (193581 hits)
+ Class: NOP not counted
+ Class: Hints (6652291 hits)
+ Class: Barriers (8001661 hits)
+ Class: PSTATE (1801695 hits)
+ Class: System Insn (6385349 hits)
+ Class: System Reg counted individually
+ Class: Branch (reg) (69497127 hits)
+ Class: Branch (imm) (84393665 hits)
+ Class: Cmp & Branch (110929659 hits)
+ Class: Tst & Branch (44681442 hits)
+ Class: AdvSimd ldstmult (736 hits)
+ Class: ldst excl (9098783 hits)
+ Class: Load Reg (lit) (87189424 hits)
+ Class: ldst noalloc pair (3264433 hits)
+ Class: ldst pair (412526434 hits)
+ Class: ldst reg (imm) (314734576 hits)
+ Class: Loads & Stores (2117774 hits)
+ Class: Data Proc Reg (223519077 hits)
+ Class: Scalar FP (31657954 hits)
+ Individual Instructions:
+ Instr: mrs x0, sp_el0 (2682661 hits) (op=0xd5384100/ System Reg)
+ Instr: mrs x1, tpidr_el2 (1789339 hits) (op=0xd53cd041/ System Reg)
+ Instr: mrs x2, tpidr_el2 (1513494 hits) (op=0xd53cd042/ System Reg)
+ Instr: mrs x0, tpidr_el2 (1490823 hits) (op=0xd53cd040/ System Reg)
+ Instr: mrs x1, sp_el0 (933793 hits) (op=0xd5384101/ System Reg)
+ Instr: mrs x2, sp_el0 (699516 hits) (op=0xd5384102/ System Reg)
+ Instr: mrs x4, tpidr_el2 (528437 hits) (op=0xd53cd044/ System Reg)
+ Instr: mrs x30, ttbr1_el1 (480776 hits) (op=0xd538203e/ System Reg)
+ Instr: msr ttbr1_el1, x30 (480713 hits) (op=0xd518203e/ System Reg)
+ Instr: msr vbar_el1, x30 (480671 hits) (op=0xd518c01e/ System Reg)
+ ...
+
+To find the argument shorthand for the class you need to examine the
+source code of the plugin at the moment, specifically the `*opt`
+argument in the InsnClassExecCount tables.
+
+- contrib/plugins/lockstep.c
+
+This is a debugging tool for developers who want to find out when and
+where execution diverges after a subtle change to TCG code generation.
+It is not an exact science and results are likely to be mixed once
+asynchronous events are introduced. While the use of -icount can
+introduce determinism to the execution flow it doesn't always follow
+the translation sequence will be exactly the same. Typically this is
+caused by a timer firing to service the GUI causing a block to end
+early. However in some cases it has proved to be useful in pointing
+people at roughly where execution diverges. The only argument you need
+for the plugin is a path for the socket the two instances will
+communicate over::
+
+
+ ./sparc-softmmu/qemu-system-sparc -monitor none -parallel none \
+ -net none -M SS-20 -m 256 -kernel day11/zImage.elf \
+ -plugin ./contrib/plugins/liblockstep.so,arg=lockstep-sparc.sock \
+ -d plugin,nochain
+
+which will eventually report::
+
+ qemu-system-sparc: warning: nic lance.0 has no peer
+ @ 0x000000ffd06678 vs 0x000000ffd001e0 (2/1 since last)
+ @ 0x000000ffd07d9c vs 0x000000ffd06678 (3/1 since last)
+ Δ insn_count @ 0x000000ffd07d9c (809900609) vs 0x000000ffd06678 (809900612)
+ previously @ 0x000000ffd06678/10 (809900609 insns)
+ previously @ 0x000000ffd001e0/4 (809900599 insns)
+ previously @ 0x000000ffd080ac/2 (809900595 insns)
+ previously @ 0x000000ffd08098/5 (809900593 insns)
+ previously @ 0x000000ffd080c0/1 (809900588 insns)
+
diff --git a/docs/system/deprecated.rst b/docs/system/deprecated.rst
index 851dbdeb8a..a158e765c3 100644
--- a/docs/system/deprecated.rst
+++ b/docs/system/deprecated.rst
@@ -424,6 +424,13 @@ linux-user mode) is deprecated and will be removed in a future version
of QEMU. Support for this CPU was removed from the upstream Linux
kernel in 2018, and has also been dropped from glibc.
+``ppc64abi32`` CPUs (since 5.2.0)
+'''''''''''''''''''''''''''''''''
+
+The ``ppc64abi32`` architecture has a number of issues which regularly
+trip up our CI testing and is suspected to be quite broken. For that
+reason the maintainers strongly suspect no one actually uses it.
+
Related binaries
----------------
diff --git a/hw/arm/xilinx_zynq.c b/hw/arm/xilinx_zynq.c
index 9eb9cea8d4..f45e71e89b 100644
--- a/hw/arm/xilinx_zynq.c
+++ b/hw/arm/xilinx_zynq.c
@@ -121,6 +121,7 @@ static void gem_init(NICInfo *nd, uint32_t base, qemu_irq irq)
qemu_check_nic_model(nd, TYPE_CADENCE_GEM);
qdev_set_nic_properties(dev, nd);
}
+ object_property_set_int(OBJECT(dev), "phy-addr", 23, &error_abort);
s = SYS_BUS_DEVICE(dev);
sysbus_realize_and_unref(s, &error_fatal);
sysbus_mmio_map(s, 0, base);
diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
index e3aa4bd1e5..12ba6c4eba 100644
--- a/hw/arm/xlnx-versal.c
+++ b/hw/arm/xlnx-versal.c
@@ -165,6 +165,7 @@ static void versal_create_gems(Versal *s, qemu_irq *pic)
qemu_check_nic_model(nd, "cadence_gem");
qdev_set_nic_properties(dev, nd);
}
+ object_property_set_int(OBJECT(dev), "phy-addr", 23, &error_abort);
object_property_set_int(OBJECT(dev), "num-priority-queues", 2,
&error_abort);
object_property_set_link(OBJECT(dev), "dma", OBJECT(&s->mr_ps),
diff --git a/hw/arm/xlnx-zynqmp.c b/hw/arm/xlnx-zynqmp.c
index c435b9d52a..7885bb1774 100644
--- a/hw/arm/xlnx-zynqmp.c
+++ b/hw/arm/xlnx-zynqmp.c
@@ -460,6 +460,8 @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
}
object_property_set_int(OBJECT(&s->gem[i]), "revision", GEM_REVISION,
&error_abort);
+ object_property_set_int(OBJECT(&s->gem[i]), "phy-addr", 23,
+ &error_abort);
object_property_set_int(OBJECT(&s->gem[i]), "num-priority-queues", 2,
&error_abort);
if (!sysbus_realize(SYS_BUS_DEVICE(&s->gem[i]), errp)) {
diff --git a/hw/char/Kconfig b/hw/char/Kconfig
index b7e0e4d5fa..939bc44758 100644
--- a/hw/char/Kconfig
+++ b/hw/char/Kconfig
@@ -1,6 +1,9 @@
config ESCC
bool
+config HTIF
+ bool
+
config PARALLEL
bool
default y
@@ -52,3 +55,9 @@ config RENESAS_SCI
config AVR_USART
bool
+
+config MCHP_PFSOC_MMUART
+ bool
+
+config SIFIVE_UART
+ bool
diff --git a/hw/char/mchp_pfsoc_mmuart.c b/hw/char/mchp_pfsoc_mmuart.c
new file mode 100644
index 0000000000..8a002b0a19
--- /dev/null
+++ b/hw/char/mchp_pfsoc_mmuart.c
@@ -0,0 +1,86 @@
+/*
+ * Microchip PolarFire SoC MMUART emulation
+ *
+ * Copyright (c) 2020 Wind River Systems, Inc.
+ *
+ * Author:
+ * Bin Meng <bin.meng@windriver.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 or
+ * (at your option) version 3 of the License.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+#include "chardev/char.h"
+#include "exec/address-spaces.h"
+#include "hw/char/mchp_pfsoc_mmuart.h"
+
+static uint64_t mchp_pfsoc_mmuart_read(void *opaque, hwaddr addr, unsigned size)
+{
+ MchpPfSoCMMUartState *s = opaque;
+
+ if (addr >= MCHP_PFSOC_MMUART_REG_SIZE) {
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: read: addr=0x%" HWADDR_PRIx "\n",
+ __func__, addr);
+ return 0;
+ }
+
+ return s->reg[addr / sizeof(uint32_t)];
+}
+
+static void mchp_pfsoc_mmuart_write(void *opaque, hwaddr addr,
+ uint64_t value, unsigned size)
+{
+ MchpPfSoCMMUartState *s = opaque;
+ uint32_t val32 = (uint32_t)value;
+
+ if (addr >= MCHP_PFSOC_MMUART_REG_SIZE) {
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: bad write: addr=0x%" HWADDR_PRIx
+ " v=0x%x\n", __func__, addr, val32);
+ return;
+ }
+
+ s->reg[addr / sizeof(uint32_t)] = val32;
+}
+
+static const MemoryRegionOps mchp_pfsoc_mmuart_ops = {
+ .read = mchp_pfsoc_mmuart_read,
+ .write = mchp_pfsoc_mmuart_write,
+ .endianness = DEVICE_LITTLE_ENDIAN,
+ .impl = {
+ .min_access_size = 4,
+ .max_access_size = 4,
+ },
+};
+
+MchpPfSoCMMUartState *mchp_pfsoc_mmuart_create(MemoryRegion *sysmem,
+ hwaddr base, qemu_irq irq, Chardev *chr)
+{
+ MchpPfSoCMMUartState *s;
+
+ s = g_new0(MchpPfSoCMMUartState, 1);
+
+ memory_region_init_io(&s->iomem, NULL, &mchp_pfsoc_mmuart_ops, s,
+ "mchp.pfsoc.mmuart", 0x1000);
+
+ s->base = base;
+ s->irq = irq;
+
+ s->serial = serial_mm_init(sysmem, base, 2, irq, 399193, chr,
+ DEVICE_LITTLE_ENDIAN);
+
+ memory_region_add_subregion(sysmem, base + 0x20, &s->iomem);
+
+ return s;
+}
diff --git a/hw/char/meson.build b/hw/char/meson.build
index e888215145..196ac91fa2 100644
--- a/hw/char/meson.build
+++ b/hw/char/meson.build
@@ -30,9 +30,12 @@ softmmu_ss.add(when: 'CONFIG_EXYNOS4', if_true: files('exynos4210_uart.c'))
softmmu_ss.add(when: 'CONFIG_OMAP', if_true: files('omap_uart.c'))
softmmu_ss.add(when: 'CONFIG_RASPI', if_true: files('bcm2835_aux.c'))
softmmu_ss.add(when: 'CONFIG_RENESAS_SCI', if_true: files('renesas_sci.c'))
+softmmu_ss.add(when: 'CONFIG_SIFIVE_UART', if_true: files('sifive_uart.c'))
softmmu_ss.add(when: 'CONFIG_SH4', if_true: files('sh_serial.c'))
softmmu_ss.add(when: 'CONFIG_STM32F2XX_USART', if_true: files('stm32f2xx_usart.c'))
+softmmu_ss.add(when: 'CONFIG_MCHP_PFSOC_MMUART', if_true: files('mchp_pfsoc_mmuart.c'))
+specific_ss.add(when: 'CONFIG_HTIF', if_true: files('riscv_htif.c'))
specific_ss.add(when: 'CONFIG_TERMINAL3270', if_true: files('terminal3270.c'))
specific_ss.add(when: 'CONFIG_VIRTIO', if_true: files('virtio-serial-bus.c'))
specific_ss.add(when: 'CONFIG_PSERIES', if_true: files('spapr_vty.c'))
diff --git a/hw/riscv/riscv_htif.c b/hw/char/riscv_htif.c
index ca87a5cf9f..ba1af1cfc4 100644
--- a/hw/riscv/riscv_htif.c
+++ b/hw/char/riscv_htif.c
@@ -24,10 +24,10 @@
#include "qapi/error.h"
#include "qemu/log.h"
#include "hw/sysbus.h"
+#include "hw/char/riscv_htif.h"
#include "hw/char/serial.h"
#include "chardev/char.h"
#include "chardev/char-fe.h"
-#include "hw/riscv/riscv_htif.h"
#include "qemu/timer.h"
#include "qemu/error-report.h"
diff --git a/hw/riscv/sifive_uart.c b/hw/char/sifive_uart.c
index 9350482662..3a00ba7f00 100644
--- a/hw/riscv/sifive_uart.c
+++ b/hw/char/sifive_uart.c
@@ -24,7 +24,7 @@
#include "chardev/char-fe.h"
#include "hw/hw.h"
#include "hw/irq.h"
-#include "hw/riscv/sifive_uart.h"
+#include "hw/char/sifive_uart.h"
/*
* Not yet implemented:
diff --git a/hw/dma/Kconfig b/hw/dma/Kconfig
index 5c61b67bc0..d67492d36c 100644
--- a/hw/dma/Kconfig
+++ b/hw/dma/Kconfig
@@ -20,3 +20,6 @@ config ZYNQ_DEVCFG
config STP2000
bool
+
+config SIFIVE_PDMA
+ bool
diff --git a/hw/dma/meson.build b/hw/dma/meson.build
index ff5bb3748f..b991d7698c 100644
--- a/hw/dma/meson.build
+++ b/hw/dma/meson.build
@@ -13,3 +13,4 @@ softmmu_ss.add(when: 'CONFIG_XLNX_ZYNQMP_ARM', if_true: files('xlnx-zdma.c'))
softmmu_ss.add(when: 'CONFIG_OMAP', if_true: files('omap_dma.c', 'soc_dma.c'))
softmmu_ss.add(when: 'CONFIG_PXA2XX', if_true: files('pxa2xx_dma.c'))
softmmu_ss.add(when: 'CONFIG_RASPI', if_true: files('bcm2835_dma.c'))
+softmmu_ss.add(when: 'CONFIG_SIFIVE_PDMA', if_true: files('sifive_pdma.c'))
diff --git a/hw/dma/sifive_pdma.c b/hw/dma/sifive_pdma.c
new file mode 100644
index 0000000000..e1f6fedbda
--- /dev/null
+++ b/hw/dma/sifive_pdma.c
@@ -0,0 +1,313 @@
+/*
+ * SiFive Platform DMA emulation
+ *
+ * Copyright (c) 2020 Wind River Systems, Inc.
+ *
+ * Author:
+ * Bin Meng <bin.meng@windriver.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 or
+ * (at your option) version 3 of the License.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/bitops.h"
+#include "qemu/log.h"
+#include "qapi/error.h"
+#include "hw/hw.h"
+#include "hw/irq.h"
+#include "hw/qdev-properties.h"
+#include "hw/sysbus.h"
+#include "migration/vmstate.h"
+#include "sysemu/dma.h"
+#include "hw/dma/sifive_pdma.h"
+
+#define DMA_CONTROL 0x000
+#define CONTROL_CLAIM BIT(0)
+#define CONTROL_RUN BIT(1)
+#define CONTROL_DONE_IE BIT(14)
+#define CONTROL_ERR_IE BIT(15)
+#define CONTROL_DONE BIT(30)
+#define CONTROL_ERR BIT(31)
+
+#define DMA_NEXT_CONFIG 0x004
+#define CONFIG_REPEAT BIT(2)
+#define CONFIG_ORDER BIT(3)
+#define CONFIG_WRSZ_SHIFT 24
+#define CONFIG_RDSZ_SHIFT 28
+#define CONFIG_SZ_MASK 0xf
+
+#define DMA_NEXT_BYTES 0x008
+#define DMA_NEXT_DST 0x010
+#define DMA_NEXT_SRC 0x018
+#define DMA_EXEC_CONFIG 0x104
+#define DMA_EXEC_BYTES 0x108
+#define DMA_EXEC_DST 0x110
+#define DMA_EXEC_SRC 0x118
+
+enum dma_chan_state {
+ DMA_CHAN_STATE_IDLE,
+ DMA_CHAN_STATE_STARTED,
+ DMA_CHAN_STATE_ERROR,
+ DMA_CHAN_STATE_DONE
+};
+
+static void sifive_pdma_run(SiFivePDMAState *s, int ch)
+{
+ uint64_t bytes = s->chan[ch].next_bytes;
+ uint64_t dst = s->chan[ch].next_dst;
+ uint64_t src = s->chan[ch].next_src;
+ uint32_t config = s->chan[ch].next_config;
+ int wsize, rsize, size;
+ uint8_t buf[64];
+ int n;
+
+ /* do nothing if bytes to transfer is zero */
+ if (!bytes) {
+ goto error;
+ }
+
+ /*
+ * The manual does not describe how the hardware behaviors when
+ * config.wsize and config.rsize are given different values.
+ * A common case is memory to memory DMA, and in this case they
+ * are normally the same. Abort if this expectation fails.
+ */
+ wsize = (config >> CONFIG_WRSZ_SHIFT) & CONFIG_SZ_MASK;
+ rsize = (config >> CONFIG_RDSZ_SHIFT) & CONFIG_SZ_MASK;
+ if (wsize != rsize) {
+ goto error;
+ }
+
+ /*
+ * Calculate the transaction size
+ *
+ * size field is base 2 logarithm of DMA transaction size,
+ * but there is an upper limit of 64 bytes per transaction.
+ */
+ size = wsize;
+ if (size > 6) {
+ size = 6;
+ }
+ size = 1 << size;
+
+ /* the bytes to transfer should be multiple of transaction size */
+ if (bytes % size) {
+ goto error;
+ }
+
+ /* indicate a DMA transfer is started */
+ s->chan[ch].state = DMA_CHAN_STATE_STARTED;
+ s->chan[ch].control &= ~CONTROL_DONE;
+ s->chan[ch].control &= ~CONTROL_ERR;
+
+ /* load the next_ registers into their exec_ counterparts */
+ s->chan[ch].exec_config = config;
+ s->chan[ch].exec_bytes = bytes;
+ s->chan[ch].exec_dst = dst;
+ s->chan[ch].exec_src = src;
+
+ for (n = 0; n < bytes / size; n++) {
+ cpu_physical_memory_read(s->chan[ch].exec_src, buf, size);
+ cpu_physical_memory_write(s->chan[ch].exec_dst, buf, size);
+ s->chan[ch].exec_src += size;
+ s->chan[ch].exec_dst += size;
+ s->chan[ch].exec_bytes -= size;
+ }
+
+ /* indicate a DMA transfer is done */
+ s->chan[ch].state = DMA_CHAN_STATE_DONE;
+ s->chan[ch].control &= ~CONTROL_RUN;
+ s->chan[ch].control |= CONTROL_DONE;
+
+ /* reload exec_ registers if repeat is required */
+ if (s->chan[ch].next_config & CONFIG_REPEAT) {
+ s->chan[ch].exec_bytes = bytes;
+ s->chan[ch].exec_dst = dst;
+ s->chan[ch].exec_src = src;
+ }
+
+ return;
+
+error:
+ s->chan[ch].state = DMA_CHAN_STATE_ERROR;
+ s->chan[ch].control |= CONTROL_ERR;
+ return;
+}
+
+static inline void sifive_pdma_update_irq(SiFivePDMAState *s, int ch)
+{
+ bool done_ie, err_ie;
+
+ done_ie = !!(s->chan[ch].control & CONTROL_DONE_IE);
+ err_ie = !!(s->chan[ch].control & CONTROL_ERR_IE);
+
+ if (done_ie && (s->chan[ch].control & CONTROL_DONE)) {
+ qemu_irq_raise(s->irq[ch * 2]);
+ } else {
+ qemu_irq_lower(s->irq[ch * 2]);
+ }
+
+ if (err_ie && (s->chan[ch].control & CONTROL_ERR)) {
+ qemu_irq_raise(s->irq[ch * 2 + 1]);
+ } else {
+ qemu_irq_lower(s->irq[ch * 2 + 1]);
+ }
+
+ s->chan[ch].state = DMA_CHAN_STATE_IDLE;
+}
+
+static uint64_t sifive_pdma_read(void *opaque, hwaddr offset, unsigned size)
+{
+ SiFivePDMAState *s = opaque;
+ int ch = SIFIVE_PDMA_CHAN_NO(offset);
+ uint64_t val = 0;
+
+ if (ch >= SIFIVE_PDMA_CHANS) {
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Invalid channel no %d\n",
+ __func__, ch);
+ return 0;
+ }
+
+ offset &= 0xfff;
+ switch (offset) {
+ case DMA_CONTROL:
+ val = s->chan[ch].control;
+ break;
+ case DMA_NEXT_CONFIG:
+ val = s->chan[ch].next_config;
+ break;
+ case DMA_NEXT_BYTES:
+ val = s->chan[ch].next_bytes;
+ break;
+ case DMA_NEXT_DST:
+ val = s->chan[ch].next_dst;
+ break;
+ case DMA_NEXT_SRC:
+ val = s->chan[ch].next_src;
+ break;
+ case DMA_EXEC_CONFIG:
+ val = s->chan[ch].exec_config;
+ break;
+ case DMA_EXEC_BYTES:
+ val = s->chan[ch].exec_bytes;
+ break;
+ case DMA_EXEC_DST:
+ val = s->chan[ch].exec_dst;
+ break;
+ case DMA_EXEC_SRC:
+ val = s->chan[ch].exec_src;
+ break;
+ default:
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIX "\n",
+ __func__, offset);
+ break;
+ }
+
+ return val;
+}
+
+static void sifive_pdma_write(void *opaque, hwaddr offset,
+ uint64_t value, unsigned size)
+{
+ SiFivePDMAState *s = opaque;
+ int ch = SIFIVE_PDMA_CHAN_NO(offset);
+
+ if (ch >= SIFIVE_PDMA_CHANS) {
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Invalid channel no %d\n",
+ __func__, ch);
+ return;
+ }
+
+ offset &= 0xfff;
+ switch (offset) {
+ case DMA_CONTROL:
+ s->chan[ch].control = value;
+
+ if (value & CONTROL_RUN) {
+ sifive_pdma_run(s, ch);
+ }
+
+ sifive_pdma_update_irq(s, ch);
+ break;
+ case DMA_NEXT_CONFIG:
+ s->chan[ch].next_config = value;
+ break;
+ case DMA_NEXT_BYTES:
+ s->chan[ch].next_bytes = value;
+ break;
+ case DMA_NEXT_DST:
+ s->chan[ch].next_dst = value;
+ break;
+ case DMA_NEXT_SRC:
+ s->chan[ch].next_src = value;
+ break;
+ case DMA_EXEC_CONFIG:
+ case DMA_EXEC_BYTES:
+ case DMA_EXEC_DST:
+ case DMA_EXEC_SRC:
+ /* these are read-only registers */
+ break;
+ default:
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIX "\n",
+ __func__, offset);
+ break;
+ }
+}
+
+static const MemoryRegionOps sifive_pdma_ops = {
+ .read = sifive_pdma_read,
+ .write = sifive_pdma_write,
+ .endianness = DEVICE_LITTLE_ENDIAN,
+ /* there are 32-bit and 64-bit wide registers */
+ .impl = {
+ .min_access_size = 4,
+ .max_access_size = 8,
+ }
+};
+
+static void sifive_pdma_realize(DeviceState *dev, Error **errp)
+{
+ SiFivePDMAState *s = SIFIVE_PDMA(dev);
+ int i;
+
+ memory_region_init_io(&s->iomem, OBJECT(dev), &sifive_pdma_ops, s,
+ TYPE_SIFIVE_PDMA, SIFIVE_PDMA_REG_SIZE);
+ sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->iomem);
+
+ for (i = 0; i < SIFIVE_PDMA_IRQS; i++) {
+ sysbus_init_irq(SYS_BUS_DEVICE(dev), &s->irq[i]);
+ }
+}
+
+static void sifive_pdma_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+
+ dc->desc = "SiFive Platform DMA controller";
+ dc->realize = sifive_pdma_realize;
+}
+
+static const TypeInfo sifive_pdma_info = {
+ .name = TYPE_SIFIVE_PDMA,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(SiFivePDMAState),
+ .class_init = sifive_pdma_class_init,
+};
+
+static void sifive_pdma_register_types(void)
+{
+ type_register_static(&sifive_pdma_info);
+}
+
+type_init(sifive_pdma_register_types)
diff --git a/hw/gpio/Kconfig b/hw/gpio/Kconfig
index 9227cb5598..b6fdaa2586 100644
--- a/hw/gpio/Kconfig
+++ b/hw/gpio/Kconfig
@@ -7,3 +7,6 @@ config PL061
config GPIO_KEY
bool
+
+config SIFIVE_GPIO
+ bool
diff --git a/hw/gpio/meson.build b/hw/gpio/meson.build
index 6bcdfa6b1d..86cae9a0f3 100644
--- a/hw/gpio/meson.build
+++ b/hw/gpio/meson.build
@@ -10,3 +10,4 @@ softmmu_ss.add(when: 'CONFIG_NRF51_SOC', if_true: files('nrf51_gpio.c'))
softmmu_ss.add(when: 'CONFIG_OMAP', if_true: files('omap_gpio.c'))
softmmu_ss.add(when: 'CONFIG_RASPI', if_true: files('bcm2835_gpio.c'))
softmmu_ss.add(when: 'CONFIG_ASPEED_SOC', if_true: files('aspeed_gpio.c'))
+softmmu_ss.add(when: 'CONFIG_SIFIVE_GPIO', if_true: files('sifive_gpio.c'))
diff --git a/hw/riscv/sifive_gpio.c b/hw/gpio/sifive_gpio.c
index aac6b44cac..78bf29e996 100644
--- a/hw/riscv/sifive_gpio.c
+++ b/hw/gpio/sifive_gpio.c
@@ -15,7 +15,7 @@
#include "qemu/log.h"
#include "hw/irq.h"
#include "hw/qdev-properties.h"
-#include "hw/riscv/sifive_gpio.h"
+#include "hw/gpio/sifive_gpio.h"
#include "migration/vmstate.h"
#include "trace.h"
diff --git a/hw/gpio/trace-events b/hw/gpio/trace-events
index c1271fdfb2..6e3f048745 100644
--- a/hw/gpio/trace-events
+++ b/hw/gpio/trace-events
@@ -5,3 +5,9 @@ nrf51_gpio_read(uint64_t offset, uint64_t r) "offset 0x%" PRIx64 " value 0x%" PR
nrf51_gpio_write(uint64_t offset, uint64_t value) "offset 0x%" PRIx64 " value 0x%" PRIx64
nrf51_gpio_set(int64_t line, int64_t value) "line %" PRIi64 " value %" PRIi64
nrf51_gpio_update_output_irq(int64_t line, int64_t value) "line %" PRIi64 " value %" PRIi64
+
+# sifive_gpio.c
+sifive_gpio_read(uint64_t offset, uint64_t r) "offset 0x%" PRIx64 " value 0x%" PRIx64
+sifive_gpio_write(uint64_t offset, uint64_t value) "offset 0x%" PRIx64 " value 0x%" PRIx64
+sifive_gpio_set(int64_t line, int64_t value) "line %" PRIi64 " value %" PRIi64
+sifive_gpio_update_output_irq(int64_t line, int64_t value) "line %" PRIi64 " value %" PRIi64
diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
index 32b1453e6a..33fa035fb7 100644
--- a/hw/i386/pc_piix.c
+++ b/hw/i386/pc_piix.c
@@ -930,7 +930,7 @@ void igd_passthrough_isa_bridge_create(PCIBus *bus, uint16_t gpu_dev_id)
struct PCIDevice *bridge_dev;
int i, num;
uint16_t pch_dev_id = 0xffff;
- uint8_t pch_rev_id;
+ uint8_t pch_rev_id = 0;
num = ARRAY_SIZE(igd_combo_id_infos);
for (i = 0; i < num; i++) {
diff --git a/hw/intc/Kconfig b/hw/intc/Kconfig
index 2ae1e89497..d07954086a 100644
--- a/hw/intc/Kconfig
+++ b/hw/intc/Kconfig
@@ -67,3 +67,9 @@ config RX_ICU
config LOONGSON_LIOINTC
bool
+
+config SIFIVE_CLINT
+ bool
+
+config SIFIVE_PLIC
+ bool
diff --git a/hw/intc/meson.build b/hw/intc/meson.build
index c16f7f036e..3f82cc230a 100644
--- a/hw/intc/meson.build
+++ b/hw/intc/meson.build
@@ -47,6 +47,8 @@ specific_ss.add(when: 'CONFIG_RX_ICU', if_true: files('rx_icu.c'))
specific_ss.add(when: 'CONFIG_S390_FLIC', if_true: files('s390_flic.c'))
specific_ss.add(when: 'CONFIG_S390_FLIC_KVM', if_true: files('s390_flic_kvm.c'))
specific_ss.add(when: 'CONFIG_SH4', if_true: files('sh_intc.c'))
+specific_ss.add(when: 'CONFIG_SIFIVE_CLINT', if_true: files('sifive_clint.c'))
+specific_ss.add(when: 'CONFIG_SIFIVE_PLIC', if_true: files('sifive_plic.c'))
specific_ss.add(when: 'CONFIG_XICS', if_true: files('xics.c'))
specific_ss.add(when: 'CONFIG_XICS_KVM', if_true: files('xics_kvm.c'))
specific_ss.add(when: 'CONFIG_XICS_SPAPR', if_true: files('xics_spapr.c'))
diff --git a/hw/riscv/sifive_clint.c b/hw/intc/sifive_clint.c
index 15e13d5f7a..0f41e5ea1c 100644
--- a/hw/riscv/sifive_clint.c
+++ b/hw/intc/sifive_clint.c
@@ -26,25 +26,26 @@
#include "hw/sysbus.h"
#include "target/riscv/cpu.h"
#include "hw/qdev-properties.h"
-#include "hw/riscv/sifive_clint.h"
+#include "hw/intc/sifive_clint.h"
#include "qemu/timer.h"
-static uint64_t cpu_riscv_read_rtc(void)
+static uint64_t cpu_riscv_read_rtc(uint32_t timebase_freq)
{
return muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL),
- SIFIVE_CLINT_TIMEBASE_FREQ, NANOSECONDS_PER_SECOND);
+ timebase_freq, NANOSECONDS_PER_SECOND);
}
/*
* Called when timecmp is written to update the QEMU timer or immediately
* trigger timer interrupt if mtimecmp <= current timer value.
*/
-static void sifive_clint_write_timecmp(RISCVCPU *cpu, uint64_t value)
+static void sifive_clint_write_timecmp(RISCVCPU *cpu, uint64_t value,
+ uint32_t timebase_freq)
{
uint64_t next;
uint64_t diff;
- uint64_t rtc_r = cpu_riscv_read_rtc();
+ uint64_t rtc_r = cpu_riscv_read_rtc(timebase_freq);
cpu->env.timecmp = value;
if (cpu->env.timecmp <= rtc_r) {
@@ -59,7 +60,7 @@ static void sifive_clint_write_timecmp(RISCVCPU *cpu, uint64_t value)
diff = cpu->env.timecmp - rtc_r;
/* back to ns (note args switched in muldiv64) */
next = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
- muldiv64(diff, NANOSECONDS_PER_SECOND, SIFIVE_CLINT_TIMEBASE_FREQ);
+ muldiv64(diff, NANOSECONDS_PER_SECOND, timebase_freq);
timer_mod(cpu->env.timer, next);
}
@@ -112,10 +113,10 @@ static uint64_t sifive_clint_read(void *opaque, hwaddr addr, unsigned size)
}
} else if (addr == clint->time_base) {
/* time_lo */
- return cpu_riscv_read_rtc() & 0xFFFFFFFF;
+ return cpu_riscv_read_rtc(clint->timebase_freq) & 0xFFFFFFFF;
} else if (addr == clint->time_base + 4) {
/* time_hi */
- return (cpu_riscv_read_rtc() >> 32) & 0xFFFFFFFF;
+ return (cpu_riscv_read_rtc(clint->timebase_freq) >> 32) & 0xFFFFFFFF;
}
error_report("clint: invalid read: %08x", (uint32_t)addr);
@@ -153,13 +154,13 @@ static void sifive_clint_write(void *opaque, hwaddr addr, uint64_t value,
/* timecmp_lo */
uint64_t timecmp_hi = env->timecmp >> 32;
sifive_clint_write_timecmp(RISCV_CPU(cpu),
- timecmp_hi << 32 | (value & 0xFFFFFFFF));
+ timecmp_hi << 32 | (value & 0xFFFFFFFF), clint->timebase_freq);
return;
} else if ((addr & 0x7) == 4) {
/* timecmp_hi */
uint64_t timecmp_lo = env->timecmp;
sifive_clint_write_timecmp(RISCV_CPU(cpu),
- value << 32 | (timecmp_lo & 0xFFFFFFFF));
+ value << 32 | (timecmp_lo & 0xFFFFFFFF), clint->timebase_freq);
} else {
error_report("clint: invalid timecmp write: %08x", (uint32_t)addr);
}
@@ -194,6 +195,7 @@ static Property sifive_clint_properties[] = {
DEFINE_PROP_UINT32("timecmp-base", SiFiveCLINTState, timecmp_base, 0),
DEFINE_PROP_UINT32("time-base", SiFiveCLINTState, time_base, 0),
DEFINE_PROP_UINT32("aperture-size", SiFiveCLINTState, aperture_size, 0),
+ DEFINE_PROP_UINT32("timebase-freq", SiFiveCLINTState, timebase_freq, 0),
DEFINE_PROP_END_OF_LIST(),
};
@@ -232,7 +234,8 @@ type_init(sifive_clint_register_types)
*/
DeviceState *sifive_clint_create(hwaddr addr, hwaddr size,
uint32_t hartid_base, uint32_t num_harts, uint32_t sip_base,
- uint32_t timecmp_base, uint32_t time_base, bool provide_rdtime)
+ uint32_t timecmp_base, uint32_t time_base, uint32_t timebase_freq,
+ bool provide_rdtime)
{
int i;
for (i = 0; i < num_harts; i++) {
@@ -242,7 +245,7 @@ DeviceState *sifive_clint_create(hwaddr addr, hwaddr size,
continue;
}
if (provide_rdtime) {
- riscv_cpu_set_rdtime_fn(env, cpu_riscv_read_rtc);
+ riscv_cpu_set_rdtime_fn(env, cpu_riscv_read_rtc, timebase_freq);
}
env->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL,
&sifive_clint_timer_cb, cpu);
@@ -256,6 +259,7 @@ DeviceState *sifive_clint_create(hwaddr addr, hwaddr size,
qdev_prop_set_uint32(dev, "timecmp-base", timecmp_base);
qdev_prop_set_uint32(dev, "time-base", time_base);
qdev_prop_set_uint32(dev, "aperture-size", size);
+ qdev_prop_set_uint32(dev, "timebase-freq", timebase_freq);
sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, addr);
return dev;
diff --git a/hw/riscv/sifive_plic.c b/hw/intc/sifive_plic.c
index 11ef147606..af611f8db8 100644
--- a/hw/riscv/sifive_plic.c
+++ b/hw/intc/sifive_plic.c
@@ -27,9 +27,9 @@
#include "hw/pci/msi.h"
#include "hw/boards.h"
#include "hw/qdev-properties.h"
+#include "hw/intc/sifive_plic.h"
#include "target/riscv/cpu.h"
#include "sysemu/sysemu.h"
-#include "hw/riscv/sifive_plic.h"
#define RISCV_DEBUG_PLIC 0
diff --git a/include/hw/riscv/sifive_plic.h b/hw/intc/sifive_plic.h
index ace76d0f1b..ace76d0f1b 100644
--- a/include/hw/riscv/sifive_plic.h
+++ b/hw/intc/sifive_plic.h
diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig
index 92c397ca07..3185456110 100644
--- a/hw/misc/Kconfig
+++ b/hw/misc/Kconfig
@@ -134,4 +134,16 @@ config MAC_VIA
config AVR_POWER
bool
+config SIFIVE_TEST
+ bool
+
+config SIFIVE_E_PRCI
+ bool
+
+config SIFIVE_U_OTP
+ bool
+
+config SIFIVE_U_PRCI
+ bool
+
source macio/Kconfig
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
index e1576b81cf..bd24132757 100644
--- a/hw/misc/meson.build
+++ b/hw/misc/meson.build
@@ -21,6 +21,12 @@ softmmu_ss.add(when: 'CONFIG_ARM11SCU', if_true: files('arm11scu.c'))
# Mac devices
softmmu_ss.add(when: 'CONFIG_MOS6522', if_true: files('mos6522.c'))
+# RISC-V devices
+softmmu_ss.add(when: 'CONFIG_SIFIVE_TEST', if_true: files('sifive_test.c'))
+softmmu_ss.add(when: 'CONFIG_SIFIVE_E_PRCI', if_true: files('sifive_e_prci.c'))
+softmmu_ss.add(when: 'CONFIG_SIFIVE_U_OTP', if_true: files('sifive_u_otp.c'))
+softmmu_ss.add(when: 'CONFIG_SIFIVE_U_PRCI', if_true: files('sifive_u_prci.c'))
+
# PKUnity SoC devices
softmmu_ss.add(when: 'CONFIG_PUV3', if_true: files('puv3_pm.c'))
diff --git a/hw/riscv/sifive_e_prci.c b/hw/misc/sifive_e_prci.c
index 17dfa74715..8ec4ee4b41 100644
--- a/hw/riscv/sifive_e_prci.c
+++ b/hw/misc/sifive_e_prci.c
@@ -24,7 +24,7 @@
#include "qemu/log.h"
#include "qemu/module.h"
#include "hw/hw.h"
-#include "hw/riscv/sifive_e_prci.h"
+#include "hw/misc/sifive_e_prci.h"
static uint64_t sifive_e_prci_read(void *opaque, hwaddr addr, unsigned int size)
{
diff --git a/hw/riscv/sifive_test.c b/hw/misc/sifive_test.c
index 0c78fb2c93..2deb2072cc 100644
--- a/hw/riscv/sifive_test.c
+++ b/hw/misc/sifive_test.c
@@ -25,7 +25,7 @@
#include "qemu/module.h"
#include "sysemu/runstate.h"
#include "hw/hw.h"
-#include "hw/riscv/sifive_test.h"
+#include "hw/misc/sifive_test.h"
static uint64_t sifive_test_read(void *opaque, hwaddr addr, unsigned int size)
{
@@ -59,7 +59,7 @@ static const MemoryRegionOps sifive_test_ops = {
.write = sifive_test_write,
.endianness = DEVICE_NATIVE_ENDIAN,
.valid = {
- .min_access_size = 4,
+ .min_access_size = 2,
.max_access_size = 4
}
};
diff --git a/hw/riscv/sifive_u_otp.c b/hw/misc/sifive_u_otp.c
index f6ecbaa2ca..c2f3c8e129 100644
--- a/hw/riscv/sifive_u_otp.c
+++ b/hw/misc/sifive_u_otp.c
@@ -23,7 +23,7 @@
#include "hw/sysbus.h"
#include "qemu/log.h"
#include "qemu/module.h"
-#include "hw/riscv/sifive_u_otp.h"
+#include "hw/misc/sifive_u_otp.h"
static uint64_t sifive_u_otp_read(void *opaque, hwaddr addr, unsigned int size)
{
diff --git a/hw/riscv/sifive_u_prci.c b/hw/misc/sifive_u_prci.c
index 4fa590c064..5d9d446ee8 100644
--- a/hw/riscv/sifive_u_prci.c
+++ b/hw/misc/sifive_u_prci.c
@@ -22,7 +22,7 @@
#include "hw/sysbus.h"
#include "qemu/log.h"
#include "qemu/module.h"
-#include "hw/riscv/sifive_u_prci.h"
+#include "hw/misc/sifive_u_prci.h"
static uint64_t sifive_u_prci_read(void *opaque, hwaddr addr, unsigned int size)
{
diff --git a/hw/net/cadence_gem.c b/hw/net/cadence_gem.c
index a93b5c07ce..7a534691f1 100644
--- a/hw/net/cadence_gem.c
+++ b/hw/net/cadence_gem.c
@@ -250,7 +250,7 @@
#define GEM_PHYMNTNC_REG_SHIFT 18
/* Marvell PHY definitions */
-#define BOARD_PHY_ADDRESS 23 /* PHY address we will emulate a device at */
+#define BOARD_PHY_ADDRESS 0 /* PHY address we will emulate a device at */
#define PHY_REG_CONTROL 0
#define PHY_REG_STATUS 1
@@ -1446,7 +1446,7 @@ static uint64_t gem_read(void *opaque, hwaddr offset, unsigned size)
uint32_t phy_addr, reg_num;
phy_addr = (retval & GEM_PHYMNTNC_ADDR) >> GEM_PHYMNTNC_ADDR_SHFT;
- if (phy_addr == BOARD_PHY_ADDRESS || phy_addr == 0) {
+ if (phy_addr == s->phy_addr) {
reg_num = (retval & GEM_PHYMNTNC_REG) >> GEM_PHYMNTNC_REG_SHIFT;
retval &= 0xFFFF0000;
retval |= gem_phy_read(s, reg_num);
@@ -1569,7 +1569,7 @@ static void gem_write(void *opaque, hwaddr offset, uint64_t val,
uint32_t phy_addr, reg_num;
phy_addr = (val & GEM_PHYMNTNC_ADDR) >> GEM_PHYMNTNC_ADDR_SHFT;
- if (phy_addr == BOARD_PHY_ADDRESS || phy_addr == 0) {
+ if (phy_addr == s->phy_addr) {
reg_num = (val & GEM_PHYMNTNC_REG) >> GEM_PHYMNTNC_REG_SHIFT;
gem_phy_write(s, reg_num, val);
}
@@ -1682,6 +1682,7 @@ static Property gem_properties[] = {
DEFINE_NIC_PROPERTIES(CadenceGEMState, conf),
DEFINE_PROP_UINT32("revision", CadenceGEMState, revision,
GEM_MODID_VALUE),
+ DEFINE_PROP_UINT8("phy-addr", CadenceGEMState, phy_addr, BOARD_PHY_ADDRESS),
DEFINE_PROP_UINT8("num-priority-queues", CadenceGEMState,
num_priority_queues, 1),
DEFINE_PROP_UINT8("num-type1-screeners", CadenceGEMState,
diff --git a/hw/riscv/Kconfig b/hw/riscv/Kconfig
index 28947ef3e0..2df978fe8d 100644
--- a/hw/riscv/Kconfig
+++ b/hw/riscv/Kconfig
@@ -1,50 +1,62 @@
-config HTIF
+config IBEX
bool
-config HART
+config MICROCHIP_PFSOC
bool
+ select CADENCE_SDHCI
+ select MCHP_PFSOC_MMUART
+ select MSI_NONBROKEN
+ select SIFIVE_CLINT
+ select SIFIVE_PDMA
+ select SIFIVE_PLIC
+ select UNIMP
-config IBEX
+config OPENTITAN
bool
+ select IBEX
+ select UNIMP
-config SIFIVE
+config RISCV_VIRT
bool
+ imply PCI_DEVICES
+ imply TEST_DEVICES
+ select GOLDFISH_RTC
select MSI_NONBROKEN
+ select PCI
+ select PCI_EXPRESS_GENERIC_BRIDGE
+ select PFLASH_CFI01
+ select SERIAL
+ select SIFIVE_CLINT
+ select SIFIVE_PLIC
+ select SIFIVE_TEST
+ select VIRTIO_MMIO
config SIFIVE_E
bool
- select HART
- select SIFIVE
+ select MSI_NONBROKEN
+ select SIFIVE_CLINT
+ select SIFIVE_GPIO
+ select SIFIVE_PLIC
+ select SIFIVE_UART
+ select SIFIVE_E_PRCI
select UNIMP
config SIFIVE_U
bool
select CADENCE
- select HART
- select SIFIVE
+ select MSI_NONBROKEN
+ select SIFIVE_CLINT
+ select SIFIVE_GPIO
+ select SIFIVE_PDMA
+ select SIFIVE_PLIC
+ select SIFIVE_UART
+ select SIFIVE_U_OTP
+ select SIFIVE_U_PRCI
select UNIMP
config SPIKE
bool
- select HART
select HTIF
- select SIFIVE
-
-config OPENTITAN
- bool
- select IBEX
- select HART
- select UNIMP
-
-config RISCV_VIRT
- bool
- imply PCI_DEVICES
- imply TEST_DEVICES
- select PCI
- select HART
- select SERIAL
- select GOLDFISH_RTC
- select VIRTIO_MMIO
- select PCI_EXPRESS_GENERIC_BRIDGE
- select PFLASH_CFI01
- select SIFIVE
+ select MSI_NONBROKEN
+ select SIFIVE_CLINT
+ select SIFIVE_PLIC
diff --git a/hw/riscv/meson.build b/hw/riscv/meson.build
index fe2ea75f65..275c0f7eb7 100644
--- a/hw/riscv/meson.build
+++ b/hw/riscv/meson.build
@@ -1,20 +1,12 @@
riscv_ss = ss.source_set()
riscv_ss.add(files('boot.c'), fdt)
riscv_ss.add(files('numa.c'))
-riscv_ss.add(when: 'CONFIG_HART', if_true: files('riscv_hart.c'))
+riscv_ss.add(files('riscv_hart.c'))
riscv_ss.add(when: 'CONFIG_OPENTITAN', if_true: files('opentitan.c'))
riscv_ss.add(when: 'CONFIG_RISCV_VIRT', if_true: files('virt.c'))
-riscv_ss.add(when: 'CONFIG_SIFIVE', if_true: files('sifive_clint.c'))
-riscv_ss.add(when: 'CONFIG_SIFIVE', if_true: files('sifive_gpio.c'))
-riscv_ss.add(when: 'CONFIG_SIFIVE', if_true: files('sifive_plic.c'))
-riscv_ss.add(when: 'CONFIG_SIFIVE', if_true: files('sifive_test.c'))
-riscv_ss.add(when: 'CONFIG_SIFIVE', if_true: files('sifive_uart.c'))
riscv_ss.add(when: 'CONFIG_SIFIVE_E', if_true: files('sifive_e.c'))
-riscv_ss.add(when: 'CONFIG_SIFIVE_E', if_true: files('sifive_e_prci.c'))
riscv_ss.add(when: 'CONFIG_SIFIVE_U', if_true: files('sifive_u.c'))
-riscv_ss.add(when: 'CONFIG_SIFIVE_U', if_true: files('sifive_u_otp.c'))
-riscv_ss.add(when: 'CONFIG_SIFIVE_U', if_true: files('sifive_u_prci.c'))
-riscv_ss.add(when: 'CONFIG_SPIKE', if_true: files('riscv_htif.c'))
riscv_ss.add(when: 'CONFIG_SPIKE', if_true: files('spike.c'))
+riscv_ss.add(when: 'CONFIG_MICROCHIP_PFSOC', if_true: files('microchip_pfsoc.c'))
hw_arch += {'riscv': riscv_ss}
diff --git a/hw/riscv/microchip_pfsoc.c b/hw/riscv/microchip_pfsoc.c
new file mode 100644
index 0000000000..4627179cd3
--- /dev/null
+++ b/hw/riscv/microchip_pfsoc.c
@@ -0,0 +1,437 @@
+/*
+ * QEMU RISC-V Board Compatible with Microchip PolarFire SoC Icicle Kit
+ *
+ * Copyright (c) 2020 Wind River Systems, Inc.
+ *
+ * Author:
+ * Bin Meng <bin.meng@windriver.com>
+ *
+ * Provides a board compatible with the Microchip PolarFire SoC Icicle Kit
+ *
+ * 0) CLINT (Core Level Interruptor)
+ * 1) PLIC (Platform Level Interrupt Controller)
+ * 2) eNVM (Embedded Non-Volatile Memory)
+ * 3) MMUARTs (Multi-Mode UART)
+ * 4) Cadence eMMC/SDHC controller and an SD card connected to it
+ * 5) SiFive Platform DMA (Direct Memory Access Controller)
+ * 6) GEM (Gigabit Ethernet MAC Controller)
+ *
+ * This board currently generates devicetree dynamically that indicates at least
+ * two harts and up to five harts.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/error-report.h"
+#include "qemu/log.h"
+#include "qemu/units.h"
+#include "qemu/cutils.h"
+#include "qapi/error.h"
+#include "hw/boards.h"
+#include "hw/irq.h"
+#include "hw/loader.h"
+#include "hw/sysbus.h"
+#include "chardev/char.h"
+#include "hw/cpu/cluster.h"
+#include "target/riscv/cpu.h"
+#include "hw/misc/unimp.h"
+#include "hw/riscv/boot.h"
+#include "hw/riscv/riscv_hart.h"
+#include "hw/riscv/microchip_pfsoc.h"
+#include "hw/intc/sifive_clint.h"
+#include "hw/intc/sifive_plic.h"
+#include "sysemu/sysemu.h"
+
+/*
+ * The BIOS image used by this machine is called Hart Software Services (HSS).
+ * See https://github.com/polarfire-soc/hart-software-services
+ */
+#define BIOS_FILENAME "hss.bin"
+#define RESET_VECTOR 0x20220000
+
+/* CLINT timebase frequency */
+#define CLINT_TIMEBASE_FREQ 1000000
+
+/* GEM version */
+#define GEM_REVISION 0x0107010c
+
+static const struct MemmapEntry {
+ hwaddr base;
+ hwaddr size;
+} microchip_pfsoc_memmap[] = {
+ [MICROCHIP_PFSOC_DEBUG] = { 0x0, 0x1000 },
+ [MICROCHIP_PFSOC_E51_DTIM] = { 0x1000000, 0x2000 },
+ [MICROCHIP_PFSOC_BUSERR_UNIT0] = { 0x1700000, 0x1000 },
+ [MICROCHIP_PFSOC_BUSERR_UNIT1] = { 0x1701000, 0x1000 },
+ [MICROCHIP_PFSOC_BUSERR_UNIT2] = { 0x1702000, 0x1000 },
+ [MICROCHIP_PFSOC_BUSERR_UNIT3] = { 0x1703000, 0x1000 },
+ [MICROCHIP_PFSOC_BUSERR_UNIT4] = { 0x1704000, 0x1000 },
+ [MICROCHIP_PFSOC_CLINT] = { 0x2000000, 0x10000 },
+ [MICROCHIP_PFSOC_L2CC] = { 0x2010000, 0x1000 },
+ [MICROCHIP_PFSOC_DMA] = { 0x3000000, 0x100000 },
+ [MICROCHIP_PFSOC_L2LIM] = { 0x8000000, 0x2000000 },
+ [MICROCHIP_PFSOC_PLIC] = { 0xc000000, 0x4000000 },
+ [MICROCHIP_PFSOC_MMUART0] = { 0x20000000, 0x1000 },
+ [MICROCHIP_PFSOC_SYSREG] = { 0x20002000, 0x2000 },
+ [MICROCHIP_PFSOC_MPUCFG] = { 0x20005000, 0x1000 },
+ [MICROCHIP_PFSOC_EMMC_SD] = { 0x20008000, 0x1000 },
+ [MICROCHIP_PFSOC_MMUART1] = { 0x20100000, 0x1000 },
+ [MICROCHIP_PFSOC_MMUART2] = { 0x20102000, 0x1000 },
+ [MICROCHIP_PFSOC_MMUART3] = { 0x20104000, 0x1000 },
+ [MICROCHIP_PFSOC_MMUART4] = { 0x20106000, 0x1000 },
+ [MICROCHIP_PFSOC_GEM0] = { 0x20110000, 0x2000 },
+ [MICROCHIP_PFSOC_GEM1] = { 0x20112000, 0x2000 },
+ [MICROCHIP_PFSOC_GPIO0] = { 0x20120000, 0x1000 },
+ [MICROCHIP_PFSOC_GPIO1] = { 0x20121000, 0x1000 },
+ [MICROCHIP_PFSOC_GPIO2] = { 0x20122000, 0x1000 },
+ [MICROCHIP_PFSOC_ENVM_CFG] = { 0x20200000, 0x1000 },
+ [MICROCHIP_PFSOC_ENVM_DATA] = { 0x20220000, 0x20000 },
+ [MICROCHIP_PFSOC_IOSCB_CFG] = { 0x37080000, 0x1000 },
+ [MICROCHIP_PFSOC_DRAM] = { 0x80000000, 0x0 },
+};
+
+static void microchip_pfsoc_soc_instance_init(Object *obj)
+{
+ MachineState *ms = MACHINE(qdev_get_machine());
+ MicrochipPFSoCState *s = MICROCHIP_PFSOC(obj);
+
+ object_initialize_child(obj, "e-cluster", &s->e_cluster, TYPE_CPU_CLUSTER);
+ qdev_prop_set_uint32(DEVICE(&s->e_cluster), "cluster-id", 0);
+
+ object_initialize_child(OBJECT(&s->e_cluster), "e-cpus", &s->e_cpus,
+ TYPE_RISCV_HART_ARRAY);
+ qdev_prop_set_uint32(DEVICE(&s->e_cpus), "num-harts", 1);
+ qdev_prop_set_uint32(DEVICE(&s->e_cpus), "hartid-base", 0);
+ qdev_prop_set_string(DEVICE(&s->e_cpus), "cpu-type",
+ TYPE_RISCV_CPU_SIFIVE_E51);
+ qdev_prop_set_uint64(DEVICE(&s->e_cpus), "resetvec", RESET_VECTOR);
+
+ object_initialize_child(obj, "u-cluster", &s->u_cluster, TYPE_CPU_CLUSTER);
+ qdev_prop_set_uint32(DEVICE(&s->u_cluster), "cluster-id", 1);
+
+ object_initialize_child(OBJECT(&s->u_cluster), "u-cpus", &s->u_cpus,
+ TYPE_RISCV_HART_ARRAY);
+ qdev_prop_set_uint32(DEVICE(&s->u_cpus), "num-harts", ms->smp.cpus - 1);
+ qdev_prop_set_uint32(DEVICE(&s->u_cpus), "hartid-base", 1);
+ qdev_prop_set_string(DEVICE(&s->u_cpus), "cpu-type",
+ TYPE_RISCV_CPU_SIFIVE_U54);
+ qdev_prop_set_uint64(DEVICE(&s->u_cpus), "resetvec", RESET_VECTOR);
+
+ object_initialize_child(obj, "dma-controller", &s->dma,
+ TYPE_SIFIVE_PDMA);
+
+ object_initialize_child(obj, "gem0", &s->gem0, TYPE_CADENCE_GEM);
+ object_initialize_child(obj, "gem1", &s->gem1, TYPE_CADENCE_GEM);
+
+ object_initialize_child(obj, "sd-controller", &s->sdhci,
+ TYPE_CADENCE_SDHCI);
+}
+
+static void microchip_pfsoc_soc_realize(DeviceState *dev, Error **errp)
+{
+ MachineState *ms = MACHINE(qdev_get_machine());
+ MicrochipPFSoCState *s = MICROCHIP_PFSOC(dev);
+ const struct MemmapEntry *memmap = microchip_pfsoc_memmap;
+ MemoryRegion *system_memory = get_system_memory();
+ MemoryRegion *e51_dtim_mem = g_new(MemoryRegion, 1);
+ MemoryRegion *l2lim_mem = g_new(MemoryRegion, 1);
+ MemoryRegion *envm_data = g_new(MemoryRegion, 1);
+ char *plic_hart_config;
+ size_t plic_hart_config_len;
+ NICInfo *nd;
+ int i;
+
+ sysbus_realize(SYS_BUS_DEVICE(&s->e_cpus), &error_abort);
+ sysbus_realize(SYS_BUS_DEVICE(&s->u_cpus), &error_abort);
+ /*
+ * The cluster must be realized after the RISC-V hart array container,
+ * as the container's CPU object is only created on realize, and the
+ * CPU must exist and have been parented into the cluster before the
+ * cluster is realized.
+ */
+ qdev_realize(DEVICE(&s->e_cluster), NULL, &error_abort);
+ qdev_realize(DEVICE(&s->u_cluster), NULL, &error_abort);
+
+ /* E51 DTIM */
+ memory_region_init_ram(e51_dtim_mem, NULL, "microchip.pfsoc.e51_dtim_mem",
+ memmap[MICROCHIP_PFSOC_E51_DTIM].size, &error_fatal);
+ memory_region_add_subregion(system_memory,
+ memmap[MICROCHIP_PFSOC_E51_DTIM].base,
+ e51_dtim_mem);
+
+ /* Bus Error Units */
+ create_unimplemented_device("microchip.pfsoc.buserr_unit0_mem",
+ memmap[MICROCHIP_PFSOC_BUSERR_UNIT0].base,
+ memmap[MICROCHIP_PFSOC_BUSERR_UNIT0].size);
+ create_unimplemented_device("microchip.pfsoc.buserr_unit1_mem",
+ memmap[MICROCHIP_PFSOC_BUSERR_UNIT1].base,
+ memmap[MICROCHIP_PFSOC_BUSERR_UNIT1].size);
+ create_unimplemented_device("microchip.pfsoc.buserr_unit2_mem",
+ memmap[MICROCHIP_PFSOC_BUSERR_UNIT2].base,
+ memmap[MICROCHIP_PFSOC_BUSERR_UNIT2].size);
+ create_unimplemented_device("microchip.pfsoc.buserr_unit3_mem",
+ memmap[MICROCHIP_PFSOC_BUSERR_UNIT3].base,
+ memmap[MICROCHIP_PFSOC_BUSERR_UNIT3].size);
+ create_unimplemented_device("microchip.pfsoc.buserr_unit4_mem",
+ memmap[MICROCHIP_PFSOC_BUSERR_UNIT4].base,
+ memmap[MICROCHIP_PFSOC_BUSERR_UNIT4].size);
+
+ /* CLINT */
+ sifive_clint_create(memmap[MICROCHIP_PFSOC_CLINT].base,
+ memmap[MICROCHIP_PFSOC_CLINT].size, 0, ms->smp.cpus,
+ SIFIVE_SIP_BASE, SIFIVE_TIMECMP_BASE, SIFIVE_TIME_BASE,
+ CLINT_TIMEBASE_FREQ, false);
+
+ /* L2 cache controller */
+ create_unimplemented_device("microchip.pfsoc.l2cc",
+ memmap[MICROCHIP_PFSOC_L2CC].base, memmap[MICROCHIP_PFSOC_L2CC].size);
+
+ /*
+ * Add L2-LIM at reset size.
+ * This should be reduced in size as the L2 Cache Controller WayEnable
+ * register is incremented. Unfortunately I don't see a nice (or any) way
+ * to handle reducing or blocking out the L2 LIM while still allowing it
+ * be re returned to all enabled after a reset. For the time being, just
+ * leave it enabled all the time. This won't break anything, but will be
+ * too generous to misbehaving guests.
+ */
+ memory_region_init_ram(l2lim_mem, NULL, "microchip.pfsoc.l2lim",
+ memmap[MICROCHIP_PFSOC_L2LIM].size, &error_fatal);
+ memory_region_add_subregion(system_memory,
+ memmap[MICROCHIP_PFSOC_L2LIM].base,
+ l2lim_mem);
+
+ /* create PLIC hart topology configuration string */
+ plic_hart_config_len = (strlen(MICROCHIP_PFSOC_PLIC_HART_CONFIG) + 1) *
+ ms->smp.cpus;
+ plic_hart_config = g_malloc0(plic_hart_config_len);
+ for (i = 0; i < ms->smp.cpus; i++) {
+ if (i != 0) {
+ strncat(plic_hart_config, "," MICROCHIP_PFSOC_PLIC_HART_CONFIG,
+ plic_hart_config_len);
+ } else {
+ strncat(plic_hart_config, "M", plic_hart_config_len);
+ }
+ plic_hart_config_len -= (strlen(MICROCHIP_PFSOC_PLIC_HART_CONFIG) + 1);
+ }
+
+ /* PLIC */
+ s->plic = sifive_plic_create(memmap[MICROCHIP_PFSOC_PLIC].base,
+ plic_hart_config, 0,
+ MICROCHIP_PFSOC_PLIC_NUM_SOURCES,
+ MICROCHIP_PFSOC_PLIC_NUM_PRIORITIES,
+ MICROCHIP_PFSOC_PLIC_PRIORITY_BASE,
+ MICROCHIP_PFSOC_PLIC_PENDING_BASE,
+ MICROCHIP_PFSOC_PLIC_ENABLE_BASE,
+ MICROCHIP_PFSOC_PLIC_ENABLE_STRIDE,
+ MICROCHIP_PFSOC_PLIC_CONTEXT_BASE,
+ MICROCHIP_PFSOC_PLIC_CONTEXT_STRIDE,
+ memmap[MICROCHIP_PFSOC_PLIC].size);
+ g_free(plic_hart_config);
+
+ /* DMA */
+ sysbus_realize(SYS_BUS_DEVICE(&s->dma), errp);
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->dma), 0,
+ memmap[MICROCHIP_PFSOC_DMA].base);
+ for (i = 0; i < SIFIVE_PDMA_IRQS; i++) {
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->dma), i,
+ qdev_get_gpio_in(DEVICE(s->plic),
+ MICROCHIP_PFSOC_DMA_IRQ0 + i));
+ }
+
+ /* SYSREG */
+ create_unimplemented_device("microchip.pfsoc.sysreg",
+ memmap[MICROCHIP_PFSOC_SYSREG].base,
+ memmap[MICROCHIP_PFSOC_SYSREG].size);
+
+ /* MPUCFG */
+ create_unimplemented_device("microchip.pfsoc.mpucfg",
+ memmap[MICROCHIP_PFSOC_MPUCFG].base,
+ memmap[MICROCHIP_PFSOC_MPUCFG].size);
+
+ /* SDHCI */
+ sysbus_realize(SYS_BUS_DEVICE(&s->sdhci), errp);
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->sdhci), 0,
+ memmap[MICROCHIP_PFSOC_EMMC_SD].base);
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->sdhci), 0,
+ qdev_get_gpio_in(DEVICE(s->plic), MICROCHIP_PFSOC_EMMC_SD_IRQ));
+
+ /* MMUARTs */
+ s->serial0 = mchp_pfsoc_mmuart_create(system_memory,
+ memmap[MICROCHIP_PFSOC_MMUART0].base,
+ qdev_get_gpio_in(DEVICE(s->plic), MICROCHIP_PFSOC_MMUART0_IRQ),
+ serial_hd(0));
+ s->serial1 = mchp_pfsoc_mmuart_create(system_memory,
+ memmap[MICROCHIP_PFSOC_MMUART1].base,
+ qdev_get_gpio_in(DEVICE(s->plic), MICROCHIP_PFSOC_MMUART1_IRQ),
+ serial_hd(1));
+ s->serial2 = mchp_pfsoc_mmuart_create(system_memory,
+ memmap[MICROCHIP_PFSOC_MMUART2].base,
+ qdev_get_gpio_in(DEVICE(s->plic), MICROCHIP_PFSOC_MMUART2_IRQ),
+ serial_hd(2));
+ s->serial3 = mchp_pfsoc_mmuart_create(system_memory,
+ memmap[MICROCHIP_PFSOC_MMUART3].base,
+ qdev_get_gpio_in(DEVICE(s->plic), MICROCHIP_PFSOC_MMUART3_IRQ),
+ serial_hd(3));
+ s->serial4 = mchp_pfsoc_mmuart_create(system_memory,
+ memmap[MICROCHIP_PFSOC_MMUART4].base,
+ qdev_get_gpio_in(DEVICE(s->plic), MICROCHIP_PFSOC_MMUART4_IRQ),
+ serial_hd(4));
+
+ /* GEMs */
+
+ nd = &nd_table[0];
+ if (nd->used) {
+ qemu_check_nic_model(nd, TYPE_CADENCE_GEM);
+ qdev_set_nic_properties(DEVICE(&s->gem0), nd);
+ }
+ nd = &nd_table[1];
+ if (nd->used) {
+ qemu_check_nic_model(nd, TYPE_CADENCE_GEM);
+ qdev_set_nic_properties(DEVICE(&s->gem1), nd);
+ }
+
+ object_property_set_int(OBJECT(&s->gem0), "revision", GEM_REVISION, errp);
+ object_property_set_int(OBJECT(&s->gem0), "phy-addr", 8, errp);
+ sysbus_realize(SYS_BUS_DEVICE(&s->gem0), errp);
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->gem0), 0,
+ memmap[MICROCHIP_PFSOC_GEM0].base);
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->gem0), 0,
+ qdev_get_gpio_in(DEVICE(s->plic), MICROCHIP_PFSOC_GEM0_IRQ));
+
+ object_property_set_int(OBJECT(&s->gem1), "revision", GEM_REVISION, errp);
+ object_property_set_int(OBJECT(&s->gem1), "phy-addr", 9, errp);
+ sysbus_realize(SYS_BUS_DEVICE(&s->gem1), errp);
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->gem1), 0,
+ memmap[MICROCHIP_PFSOC_GEM1].base);
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->gem1), 0,
+ qdev_get_gpio_in(DEVICE(s->plic), MICROCHIP_PFSOC_GEM1_IRQ));
+
+ /* GPIOs */
+ create_unimplemented_device("microchip.pfsoc.gpio0",
+ memmap[MICROCHIP_PFSOC_GPIO0].base,
+ memmap[MICROCHIP_PFSOC_GPIO0].size);
+ create_unimplemented_device("microchip.pfsoc.gpio1",
+ memmap[MICROCHIP_PFSOC_GPIO1].base,
+ memmap[MICROCHIP_PFSOC_GPIO1].size);
+ create_unimplemented_device("microchip.pfsoc.gpio2",
+ memmap[MICROCHIP_PFSOC_GPIO2].base,
+ memmap[MICROCHIP_PFSOC_GPIO2].size);
+
+ /* eNVM */
+ memory_region_init_rom(envm_data, OBJECT(dev), "microchip.pfsoc.envm.data",
+ memmap[MICROCHIP_PFSOC_ENVM_DATA].size,
+ &error_fatal);
+ memory_region_add_subregion(system_memory,
+ memmap[MICROCHIP_PFSOC_ENVM_DATA].base,
+ envm_data);
+
+ /* IOSCBCFG */
+ create_unimplemented_device("microchip.pfsoc.ioscb.cfg",
+ memmap[MICROCHIP_PFSOC_IOSCB_CFG].base,
+ memmap[MICROCHIP_PFSOC_IOSCB_CFG].size);
+}
+
+static void microchip_pfsoc_soc_class_init(ObjectClass *oc, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(oc);
+
+ dc->realize = microchip_pfsoc_soc_realize;
+ /* Reason: Uses serial_hds in realize function, thus can't be used twice */
+ dc->user_creatable = false;
+}
+
+static const TypeInfo microchip_pfsoc_soc_type_info = {
+ .name = TYPE_MICROCHIP_PFSOC,
+ .parent = TYPE_DEVICE,
+ .instance_size = sizeof(MicrochipPFSoCState),
+ .instance_init = microchip_pfsoc_soc_instance_init,
+ .class_init = microchip_pfsoc_soc_class_init,
+};
+
+static void microchip_pfsoc_soc_register_types(void)
+{
+ type_register_static(&microchip_pfsoc_soc_type_info);
+}
+
+type_init(microchip_pfsoc_soc_register_types)
+
+static void microchip_icicle_kit_machine_init(MachineState *machine)
+{
+ MachineClass *mc = MACHINE_GET_CLASS(machine);
+ const struct MemmapEntry *memmap = microchip_pfsoc_memmap;
+ MicrochipIcicleKitState *s = MICROCHIP_ICICLE_KIT_MACHINE(machine);
+ MemoryRegion *system_memory = get_system_memory();
+ MemoryRegion *main_mem = g_new(MemoryRegion, 1);
+ DriveInfo *dinfo = drive_get_next(IF_SD);
+
+ /* Sanity check on RAM size */
+ if (machine->ram_size < mc->default_ram_size) {
+ char *sz = size_to_str(mc->default_ram_size);
+ error_report("Invalid RAM size, should be bigger than %s", sz);
+ g_free(sz);
+ exit(EXIT_FAILURE);
+ }
+
+ /* Initialize SoC */
+ object_initialize_child(OBJECT(machine), "soc", &s->soc,
+ TYPE_MICROCHIP_PFSOC);
+ qdev_realize(DEVICE(&s->soc), NULL, &error_abort);
+
+ /* Register RAM */
+ memory_region_init_ram(main_mem, NULL, "microchip.icicle.kit.ram",
+ machine->ram_size, &error_fatal);
+ memory_region_add_subregion(system_memory,
+ memmap[MICROCHIP_PFSOC_DRAM].base, main_mem);
+
+ /* Load the firmware */
+ riscv_find_and_load_firmware(machine, BIOS_FILENAME, RESET_VECTOR, NULL);
+
+ /* Attach an SD card */
+ if (dinfo) {
+ CadenceSDHCIState *sdhci = &(s->soc.sdhci);
+ DeviceState *card = qdev_new(TYPE_SD_CARD);
+
+ qdev_prop_set_drive_err(card, "drive", blk_by_legacy_dinfo(dinfo),
+ &error_fatal);
+ qdev_realize_and_unref(card, sdhci->bus, &error_fatal);
+ }
+}
+
+static void microchip_icicle_kit_machine_class_init(ObjectClass *oc, void *data)
+{
+ MachineClass *mc = MACHINE_CLASS(oc);
+
+ mc->desc = "Microchip PolarFire SoC Icicle Kit";
+ mc->init = microchip_icicle_kit_machine_init;
+ mc->max_cpus = MICROCHIP_PFSOC_MANAGEMENT_CPU_COUNT +
+ MICROCHIP_PFSOC_COMPUTE_CPU_COUNT;
+ mc->min_cpus = MICROCHIP_PFSOC_MANAGEMENT_CPU_COUNT + 1;
+ mc->default_cpus = mc->min_cpus;
+ mc->default_ram_size = 1 * GiB;
+}
+
+static const TypeInfo microchip_icicle_kit_machine_typeinfo = {
+ .name = MACHINE_TYPE_NAME("microchip-icicle-kit"),
+ .parent = TYPE_MACHINE,
+ .class_init = microchip_icicle_kit_machine_class_init,
+ .instance_size = sizeof(MicrochipIcicleKitState),
+};
+
+static void microchip_icicle_kit_machine_init_register_types(void)
+{
+ type_register_static(&microchip_icicle_kit_machine_typeinfo);
+}
+
+type_init(microchip_icicle_kit_machine_init_register_types)
diff --git a/hw/riscv/opentitan.c b/hw/riscv/opentitan.c
index 23ba3b4bfc..0531bd879b 100644
--- a/hw/riscv/opentitan.c
+++ b/hw/riscv/opentitan.c
@@ -111,6 +111,7 @@ static void lowrisc_ibex_soc_realize(DeviceState *dev_soc, Error **errp)
&error_abort);
object_property_set_int(OBJECT(&s->cpus), "num-harts", ms->smp.cpus,
&error_abort);
+ object_property_set_int(OBJECT(&s->cpus), "resetvec", 0x8090, &error_abort);
sysbus_realize(SYS_BUS_DEVICE(&s->cpus), &error_abort);
/* Boot ROM */
diff --git a/hw/riscv/riscv_hart.c b/hw/riscv/riscv_hart.c
index f59fe52f0f..613ea2aaa0 100644
--- a/hw/riscv/riscv_hart.c
+++ b/hw/riscv/riscv_hart.c
@@ -31,6 +31,8 @@ static Property riscv_harts_props[] = {
DEFINE_PROP_UINT32("num-harts", RISCVHartArrayState, num_harts, 1),
DEFINE_PROP_UINT32("hartid-base", RISCVHartArrayState, hartid_base, 0),
DEFINE_PROP_STRING("cpu-type", RISCVHartArrayState, cpu_type),
+ DEFINE_PROP_UINT64("resetvec", RISCVHartArrayState, resetvec,
+ DEFAULT_RSTVEC),
DEFINE_PROP_END_OF_LIST(),
};
@@ -44,6 +46,7 @@ static bool riscv_hart_realize(RISCVHartArrayState *s, int idx,
char *cpu_type, Error **errp)
{
object_initialize_child(OBJECT(s), "harts[*]", &s->harts[idx], cpu_type);
+ qdev_prop_set_uint64(DEVICE(&s->harts[idx]), "resetvec", s->resetvec);
s->harts[idx].env.mhartid = s->hartid_base + idx;
qemu_register_reset(riscv_harts_cpu_reset, &s->harts[idx]);
return qdev_realize(DEVICE(&s->harts[idx]), NULL, errp);
diff --git a/hw/riscv/sifive_e.c b/hw/riscv/sifive_e.c
index ca55cc438a..40bbf530d4 100644
--- a/hw/riscv/sifive_e.c
+++ b/hw/riscv/sifive_e.c
@@ -39,12 +39,12 @@
#include "hw/misc/unimp.h"
#include "target/riscv/cpu.h"
#include "hw/riscv/riscv_hart.h"
-#include "hw/riscv/sifive_plic.h"
-#include "hw/riscv/sifive_clint.h"
-#include "hw/riscv/sifive_uart.h"
#include "hw/riscv/sifive_e.h"
-#include "hw/riscv/sifive_e_prci.h"
#include "hw/riscv/boot.h"
+#include "hw/char/sifive_uart.h"
+#include "hw/intc/sifive_clint.h"
+#include "hw/intc/sifive_plic.h"
+#include "hw/misc/sifive_e_prci.h"
#include "chardev/char.h"
#include "sysemu/arch_init.h"
#include "sysemu/sysemu.h"
@@ -177,6 +177,7 @@ static void sifive_e_soc_init(Object *obj)
object_initialize_child(obj, "cpus", &s->cpus, TYPE_RISCV_HART_ARRAY);
object_property_set_int(OBJECT(&s->cpus), "num-harts", ms->smp.cpus,
&error_abort);
+ object_property_set_int(OBJECT(&s->cpus), "resetvec", 0x1004, &error_abort);
object_initialize_child(obj, "riscv.sifive.e.gpio0", &s->gpio,
TYPE_SIFIVE_GPIO);
}
@@ -212,7 +213,8 @@ static void sifive_e_soc_realize(DeviceState *dev, Error **errp)
memmap[SIFIVE_E_PLIC].size);
sifive_clint_create(memmap[SIFIVE_E_CLINT].base,
memmap[SIFIVE_E_CLINT].size, 0, ms->smp.cpus,
- SIFIVE_SIP_BASE, SIFIVE_TIMECMP_BASE, SIFIVE_TIME_BASE, false);
+ SIFIVE_SIP_BASE, SIFIVE_TIMECMP_BASE, SIFIVE_TIME_BASE,
+ SIFIVE_CLINT_TIMEBASE_FREQ, false);
create_unimplemented_device("riscv.sifive.e.aon",
memmap[SIFIVE_E_AON].base, memmap[SIFIVE_E_AON].size);
sifive_e_prci_create(memmap[SIFIVE_E_PRCI].base);
diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c
index a48046c6a0..4f12a93188 100644
--- a/hw/riscv/sifive_u.c
+++ b/hw/riscv/sifive_u.c
@@ -14,6 +14,7 @@
* 4) GPIO (General Purpose Input/Output Controller)
* 5) OTP (One-Time Programmable) memory with stored serial number
* 6) GEM (Gigabit Ethernet Controller) and management block
+ * 7) DMA (Direct Memory Access Controller)
*
* This board currently generates devicetree dynamically that indicates at least
* two harts and up to five harts.
@@ -45,11 +46,11 @@
#include "hw/misc/unimp.h"
#include "target/riscv/cpu.h"
#include "hw/riscv/riscv_hart.h"
-#include "hw/riscv/sifive_plic.h"
-#include "hw/riscv/sifive_clint.h"
-#include "hw/riscv/sifive_uart.h"
#include "hw/riscv/sifive_u.h"
#include "hw/riscv/boot.h"
+#include "hw/char/sifive_uart.h"
+#include "hw/intc/sifive_clint.h"
+#include "hw/intc/sifive_plic.h"
#include "chardev/char.h"
#include "net/eth.h"
#include "sysemu/arch_init.h"
@@ -73,6 +74,7 @@ static const struct MemmapEntry {
[SIFIVE_U_MROM] = { 0x1000, 0xf000 },
[SIFIVE_U_CLINT] = { 0x2000000, 0x10000 },
[SIFIVE_U_L2CC] = { 0x2010000, 0x1000 },
+ [SIFIVE_U_PDMA] = { 0x3000000, 0x100000 },
[SIFIVE_U_L2LIM] = { 0x8000000, 0x2000000 },
[SIFIVE_U_PLIC] = { 0xc000000, 0x4000000 },
[SIFIVE_U_PRCI] = { 0x10000000, 0x1000 },
@@ -303,6 +305,22 @@ static void create_fdt(SiFiveUState *s, const struct MemmapEntry *memmap,
qemu_fdt_setprop_string(fdt, nodename, "compatible", "gpio-restart");
g_free(nodename);
+ nodename = g_strdup_printf("/soc/dma@%lx",
+ (long)memmap[SIFIVE_U_PDMA].base);
+ qemu_fdt_add_subnode(fdt, nodename);
+ qemu_fdt_setprop_cell(fdt, nodename, "#dma-cells", 1);
+ qemu_fdt_setprop_cells(fdt, nodename, "interrupts",
+ SIFIVE_U_PDMA_IRQ0, SIFIVE_U_PDMA_IRQ1, SIFIVE_U_PDMA_IRQ2,
+ SIFIVE_U_PDMA_IRQ3, SIFIVE_U_PDMA_IRQ4, SIFIVE_U_PDMA_IRQ5,
+ SIFIVE_U_PDMA_IRQ6, SIFIVE_U_PDMA_IRQ7);
+ qemu_fdt_setprop_cell(fdt, nodename, "interrupt-parent", plic_phandle);
+ qemu_fdt_setprop_cells(fdt, nodename, "reg",
+ 0x0, memmap[SIFIVE_U_PDMA].base,
+ 0x0, memmap[SIFIVE_U_PDMA].size);
+ qemu_fdt_setprop_string(fdt, nodename, "compatible",
+ "sifive,fu540-c000-pdma");
+ g_free(nodename);
+
nodename = g_strdup_printf("/soc/cache-controller@%lx",
(long)memmap[SIFIVE_U_L2CC].base);
qemu_fdt_add_subnode(fdt, nodename);
@@ -611,6 +629,7 @@ static void sifive_u_soc_instance_init(Object *obj)
qdev_prop_set_uint32(DEVICE(&s->e_cpus), "num-harts", 1);
qdev_prop_set_uint32(DEVICE(&s->e_cpus), "hartid-base", 0);
qdev_prop_set_string(DEVICE(&s->e_cpus), "cpu-type", SIFIVE_E_CPU);
+ qdev_prop_set_uint64(DEVICE(&s->e_cpus), "resetvec", 0x1004);
object_initialize_child(obj, "u-cluster", &s->u_cluster, TYPE_CPU_CLUSTER);
qdev_prop_set_uint32(DEVICE(&s->u_cluster), "cluster-id", 1);
@@ -620,11 +639,13 @@ static void sifive_u_soc_instance_init(Object *obj)
qdev_prop_set_uint32(DEVICE(&s->u_cpus), "num-harts", ms->smp.cpus - 1);
qdev_prop_set_uint32(DEVICE(&s->u_cpus), "hartid-base", 1);
qdev_prop_set_string(DEVICE(&s->u_cpus), "cpu-type", SIFIVE_U_CPU);
+ qdev_prop_set_uint64(DEVICE(&s->u_cpus), "resetvec", 0x1004);
object_initialize_child(obj, "prci", &s->prci, TYPE_SIFIVE_U_PRCI);
object_initialize_child(obj, "otp", &s->otp, TYPE_SIFIVE_U_OTP);
object_initialize_child(obj, "gem", &s->gem, TYPE_CADENCE_GEM);
object_initialize_child(obj, "gpio", &s->gpio, TYPE_SIFIVE_GPIO);
+ object_initialize_child(obj, "pdma", &s->dma, TYPE_SIFIVE_PDMA);
}
static void sifive_u_soc_realize(DeviceState *dev, Error **errp)
@@ -704,7 +725,8 @@ static void sifive_u_soc_realize(DeviceState *dev, Error **errp)
serial_hd(1), qdev_get_gpio_in(DEVICE(s->plic), SIFIVE_U_UART1_IRQ));
sifive_clint_create(memmap[SIFIVE_U_CLINT].base,
memmap[SIFIVE_U_CLINT].size, 0, ms->smp.cpus,
- SIFIVE_SIP_BASE, SIFIVE_TIMECMP_BASE, SIFIVE_TIME_BASE, false);
+ SIFIVE_SIP_BASE, SIFIVE_TIMECMP_BASE, SIFIVE_TIME_BASE,
+ SIFIVE_CLINT_TIMEBASE_FREQ, false);
if (!sysbus_realize(SYS_BUS_DEVICE(&s->prci), errp)) {
return;
@@ -727,6 +749,17 @@ static void sifive_u_soc_realize(DeviceState *dev, Error **errp)
SIFIVE_U_GPIO_IRQ0 + i));
}
+ /* PDMA */
+ sysbus_realize(SYS_BUS_DEVICE(&s->dma), errp);
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->dma), 0, memmap[SIFIVE_U_PDMA].base);
+
+ /* Connect PDMA interrupts to the PLIC */
+ for (i = 0; i < SIFIVE_PDMA_IRQS; i++) {
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->dma), i,
+ qdev_get_gpio_in(DEVICE(s->plic),
+ SIFIVE_U_PDMA_IRQ0 + i));
+ }
+
qdev_prop_set_uint32(DEVICE(&s->otp), "serial", s->serial);
if (!sysbus_realize(SYS_BUS_DEVICE(&s->otp), errp)) {
return;
diff --git a/hw/riscv/spike.c b/hw/riscv/spike.c
index 56f5fe73c7..3fd152a035 100644
--- a/hw/riscv/spike.c
+++ b/hw/riscv/spike.c
@@ -31,12 +31,12 @@
#include "hw/loader.h"
#include "hw/sysbus.h"
#include "target/riscv/cpu.h"
-#include "hw/riscv/riscv_htif.h"
#include "hw/riscv/riscv_hart.h"
-#include "hw/riscv/sifive_clint.h"
#include "hw/riscv/spike.h"
#include "hw/riscv/boot.h"
#include "hw/riscv/numa.h"
+#include "hw/char/riscv_htif.h"
+#include "hw/intc/sifive_clint.h"
#include "chardev/char.h"
#include "sysemu/arch_init.h"
#include "sysemu/device_tree.h"
@@ -242,7 +242,8 @@ static void spike_board_init(MachineState *machine)
sifive_clint_create(
memmap[SPIKE_CLINT].base + i * memmap[SPIKE_CLINT].size,
memmap[SPIKE_CLINT].size, base_hartid, hart_count,
- SIFIVE_SIP_BASE, SIFIVE_TIMECMP_BASE, SIFIVE_TIME_BASE, false);
+ SIFIVE_SIP_BASE, SIFIVE_TIMECMP_BASE, SIFIVE_TIME_BASE,
+ SIFIVE_CLINT_TIMEBASE_FREQ, false);
}
/* register system main memory (actual RAM) */
diff --git a/hw/riscv/trace-events b/hw/riscv/trace-events
deleted file mode 100644
index b819878963..0000000000
--- a/hw/riscv/trace-events
+++ /dev/null
@@ -1,7 +0,0 @@
-# See docs/devel/tracing.txt for syntax documentation.
-
-# sifive_gpio.c
-sifive_gpio_read(uint64_t offset, uint64_t r) "offset 0x%" PRIx64 " value 0x%" PRIx64
-sifive_gpio_write(uint64_t offset, uint64_t value) "offset 0x%" PRIx64 " value 0x%" PRIx64
-sifive_gpio_set(int64_t line, int64_t value) "line %" PRIi64 " value %" PRIi64
-sifive_gpio_update_output_irq(int64_t line, int64_t value) "line %" PRIi64 " value %" PRIi64
diff --git a/hw/riscv/trace.h b/hw/riscv/trace.h
deleted file mode 100644
index 8c0e3ca1f3..0000000000
--- a/hw/riscv/trace.h
+++ /dev/null
@@ -1 +0,0 @@
-#include "trace/trace-hw_riscv.h"
diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
index 6fca513ec9..41bd2f38ba 100644
--- a/hw/riscv/virt.c
+++ b/hw/riscv/virt.c
@@ -30,12 +30,12 @@
#include "hw/char/serial.h"
#include "target/riscv/cpu.h"
#include "hw/riscv/riscv_hart.h"
-#include "hw/riscv/sifive_plic.h"
-#include "hw/riscv/sifive_clint.h"
-#include "hw/riscv/sifive_test.h"
#include "hw/riscv/virt.h"
#include "hw/riscv/boot.h"
#include "hw/riscv/numa.h"
+#include "hw/intc/sifive_clint.h"
+#include "hw/intc/sifive_plic.h"
+#include "hw/misc/sifive_test.h"
#include "chardev/char.h"
#include "sysemu/arch_init.h"
#include "sysemu/device_tree.h"
@@ -541,7 +541,8 @@ static void virt_machine_init(MachineState *machine)
sifive_clint_create(
memmap[VIRT_CLINT].base + i * memmap[VIRT_CLINT].size,
memmap[VIRT_CLINT].size, base_hartid, hart_count,
- SIFIVE_SIP_BASE, SIFIVE_TIMECMP_BASE, SIFIVE_TIME_BASE, true);
+ SIFIVE_SIP_BASE, SIFIVE_TIMECMP_BASE, SIFIVE_TIME_BASE,
+ SIFIVE_CLINT_TIMEBASE_FREQ, true);
/* Per-socket PLIC hart topology configuration string */
plic_hart_config_len =
diff --git a/hw/sd/Kconfig b/hw/sd/Kconfig
index c5e1e5581c..633b9afec9 100644
--- a/hw/sd/Kconfig
+++ b/hw/sd/Kconfig
@@ -19,3 +19,7 @@ config SDHCI_PCI
default y if PCI_DEVICES
depends on PCI
select SDHCI
+
+config CADENCE_SDHCI
+ bool
+ select SDHCI
diff --git a/hw/sd/cadence_sdhci.c b/hw/sd/cadence_sdhci.c
new file mode 100644
index 0000000000..0b371c843d
--- /dev/null
+++ b/hw/sd/cadence_sdhci.c
@@ -0,0 +1,193 @@
+/*
+ * Cadence SDHCI emulation
+ *
+ * Copyright (c) 2020 Wind River Systems, Inc.
+ *
+ * Author:
+ * Bin Meng <bin.meng@windriver.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 or
+ * (at your option) version 3 of the License.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/bitops.h"
+#include "qemu/error-report.h"
+#include "qemu/log.h"
+#include "qapi/error.h"
+#include "migration/vmstate.h"
+#include "hw/irq.h"
+#include "hw/sd/cadence_sdhci.h"
+#include "sdhci-internal.h"
+
+/* HRS - Host Register Set (specific to Cadence) */
+
+#define CADENCE_SDHCI_HRS00 0x00 /* general information */
+#define CADENCE_SDHCI_HRS00_SWR BIT(0)
+#define CADENCE_SDHCI_HRS00_POR_VAL 0x00010000
+
+#define CADENCE_SDHCI_HRS04 0x10 /* PHY access port */
+#define CADENCE_SDHCI_HRS04_WR BIT(24)
+#define CADENCE_SDHCI_HRS04_RD BIT(25)
+#define CADENCE_SDHCI_HRS04_ACK BIT(26)
+
+#define CADENCE_SDHCI_HRS06 0x18 /* eMMC control */
+#define CADENCE_SDHCI_HRS06_TUNE_UP BIT(15)
+
+/* SRS - Slot Register Set (SDHCI-compatible) */
+
+#define CADENCE_SDHCI_SRS_BASE 0x200
+
+#define TO_REG(addr) ((addr) / sizeof(uint32_t))
+
+static void cadence_sdhci_instance_init(Object *obj)
+{
+ CadenceSDHCIState *s = CADENCE_SDHCI(obj);
+
+ object_initialize_child(OBJECT(s), "generic-sdhci",
+ &s->sdhci, TYPE_SYSBUS_SDHCI);
+}
+
+static void cadence_sdhci_reset(DeviceState *dev)
+{
+ CadenceSDHCIState *s = CADENCE_SDHCI(dev);
+
+ memset(s->regs, 0, CADENCE_SDHCI_REG_SIZE);
+ s->regs[TO_REG(CADENCE_SDHCI_HRS00)] = CADENCE_SDHCI_HRS00_POR_VAL;
+
+ device_cold_reset(DEVICE(&s->sdhci));
+}
+
+static uint64_t cadence_sdhci_read(void *opaque, hwaddr addr, unsigned int size)
+{
+ CadenceSDHCIState *s = opaque;
+ uint32_t val;
+
+ val = s->regs[TO_REG(addr)];
+
+ return (uint64_t)val;
+}
+
+static void cadence_sdhci_write(void *opaque, hwaddr addr, uint64_t val,
+ unsigned int size)
+{
+ CadenceSDHCIState *s = opaque;
+ uint32_t val32 = (uint32_t)val;
+
+ switch (addr) {
+ case CADENCE_SDHCI_HRS00:
+ /*
+ * The only writable bit is SWR (software reset) and it automatically
+ * clears to zero, so essentially this register remains unchanged.
+ */
+ if (val32 & CADENCE_SDHCI_HRS00_SWR) {
+ cadence_sdhci_reset(DEVICE(s));
+ }
+
+ break;
+ case CADENCE_SDHCI_HRS04:
+ /*
+ * Only emulate the ACK bit behavior when read or write transaction
+ * are requested.
+ */
+ if (val32 & (CADENCE_SDHCI_HRS04_WR | CADENCE_SDHCI_HRS04_RD)) {
+ val32 |= CADENCE_SDHCI_HRS04_ACK;
+ } else {
+ val32 &= ~CADENCE_SDHCI_HRS04_ACK;
+ }
+
+ s->regs[TO_REG(addr)] = val32;
+ break;
+ case CADENCE_SDHCI_HRS06:
+ if (val32 & CADENCE_SDHCI_HRS06_TUNE_UP) {
+ val32 &= ~CADENCE_SDHCI_HRS06_TUNE_UP;
+ }
+
+ s->regs[TO_REG(addr)] = val32;
+ break;
+ default:
+ s->regs[TO_REG(addr)] = val32;
+ break;
+ }
+}
+
+static const MemoryRegionOps cadence_sdhci_ops = {
+ .read = cadence_sdhci_read,
+ .write = cadence_sdhci_write,
+ .endianness = DEVICE_NATIVE_ENDIAN,
+ .impl = {
+ .min_access_size = 4,
+ .max_access_size = 4,
+ },
+ .valid = {
+ .min_access_size = 4,
+ .max_access_size = 4,
+ }
+};
+
+static void cadence_sdhci_realize(DeviceState *dev, Error **errp)
+{
+ CadenceSDHCIState *s = CADENCE_SDHCI(dev);
+ SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
+ SysBusDevice *sbd_sdhci = SYS_BUS_DEVICE(&s->sdhci);
+
+ memory_region_init(&s->container, OBJECT(s),
+ "cadence.sdhci-container", 0x1000);
+ sysbus_init_mmio(sbd, &s->container);
+
+ memory_region_init_io(&s->iomem, OBJECT(s), &cadence_sdhci_ops,
+ s, TYPE_CADENCE_SDHCI, CADENCE_SDHCI_REG_SIZE);
+ memory_region_add_subregion(&s->container, 0, &s->iomem);
+
+ sysbus_realize(sbd_sdhci, errp);
+ memory_region_add_subregion(&s->container, CADENCE_SDHCI_SRS_BASE,
+ sysbus_mmio_get_region(sbd_sdhci, 0));
+
+ /* propagate irq and "sd-bus" from generic-sdhci */
+ sysbus_pass_irq(sbd, sbd_sdhci);
+ s->bus = qdev_get_child_bus(DEVICE(sbd_sdhci), "sd-bus");
+}
+
+static const VMStateDescription vmstate_cadence_sdhci = {
+ .name = TYPE_CADENCE_SDHCI,
+ .version_id = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32_ARRAY(regs, CadenceSDHCIState, CADENCE_SDHCI_NUM_REGS),
+ VMSTATE_END_OF_LIST(),
+ },
+};
+
+static void cadence_sdhci_class_init(ObjectClass *classp, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(classp);
+
+ dc->desc = "Cadence SD/SDIO/eMMC Host Controller (SD4HC)";
+ dc->realize = cadence_sdhci_realize;
+ dc->reset = cadence_sdhci_reset;
+ dc->vmsd = &vmstate_cadence_sdhci;
+}
+
+static TypeInfo cadence_sdhci_info = {
+ .name = TYPE_CADENCE_SDHCI,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(CadenceSDHCIState),
+ .instance_init = cadence_sdhci_instance_init,
+ .class_init = cadence_sdhci_class_init,
+};
+
+static void cadence_sdhci_register_types(void)
+{
+ type_register_static(&cadence_sdhci_info);
+}
+
+type_init(cadence_sdhci_register_types)
diff --git a/hw/sd/meson.build b/hw/sd/meson.build
index b43e59bd00..9c29691e13 100644
--- a/hw/sd/meson.build
+++ b/hw/sd/meson.build
@@ -10,3 +10,4 @@ softmmu_ss.add(when: 'CONFIG_PXA2XX', if_true: files('pxa2xx_mmci.c'))
softmmu_ss.add(when: 'CONFIG_RASPI', if_true: files('bcm2835_sdhost.c'))
softmmu_ss.add(when: 'CONFIG_ASPEED_SOC', if_true: files('aspeed_sdhci.c'))
softmmu_ss.add(when: 'CONFIG_ALLWINNER_H3', if_true: files('allwinner-sdhost.c'))
+softmmu_ss.add(when: 'CONFIG_CADENCE_SDHCI', if_true: files('cadence_sdhci.c'))
diff --git a/hw/usb/host-libusb.c b/hw/usb/host-libusb.c
index 2ba1de68df..43c93504a2 100644
--- a/hw/usb/host-libusb.c
+++ b/hw/usb/host-libusb.c
@@ -943,7 +943,7 @@ static int usb_host_open(USBHostDevice *s, libusb_device *dev, int hostfd)
usb_host_ep_update(s);
libusb_speed = libusb_get_device_speed(dev);
-#ifdef CONFIG_LINUX
+#if LIBUSB_API_VERSION >= 0x01000107 && defined(CONFIG_LINUX)
if (hostfd && libusb_speed == 0) {
/*
* Workaround libusb bug: libusb_get_device_speed() does not
diff --git a/include/hw/char/mchp_pfsoc_mmuart.h b/include/hw/char/mchp_pfsoc_mmuart.h
new file mode 100644
index 0000000000..f61990215f
--- /dev/null
+++ b/include/hw/char/mchp_pfsoc_mmuart.h
@@ -0,0 +1,61 @@
+/*
+ * Microchip PolarFire SoC MMUART emulation
+ *
+ * Copyright (c) 2020 Wind River Systems, Inc.
+ *
+ * Author:
+ * Bin Meng <bin.meng@windriver.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef HW_MCHP_PFSOC_MMUART_H
+#define HW_MCHP_PFSOC_MMUART_H
+
+#include "hw/char/serial.h"
+
+#define MCHP_PFSOC_MMUART_REG_SIZE 52
+
+typedef struct MchpPfSoCMMUartState {
+ MemoryRegion iomem;
+ hwaddr base;
+ qemu_irq irq;
+
+ SerialMM *serial;
+
+ uint32_t reg[MCHP_PFSOC_MMUART_REG_SIZE / sizeof(uint32_t)];
+} MchpPfSoCMMUartState;
+
+/**
+ * mchp_pfsoc_mmuart_create - Create a Microchip PolarFire SoC MMUART
+ *
+ * This is a helper routine for board to create a MMUART device that is
+ * compatible with Microchip PolarFire SoC.
+ *
+ * @sysmem: system memory region to map
+ * @base: base address of the MMUART registers
+ * @irq: IRQ number of the MMUART device
+ * @chr: character device to associate to
+ *
+ * @return: a pointer to the device specific control structure
+ */
+MchpPfSoCMMUartState *mchp_pfsoc_mmuart_create(MemoryRegion *sysmem,
+ hwaddr base, qemu_irq irq, Chardev *chr);
+
+#endif /* HW_MCHP_PFSOC_MMUART_H */
diff --git a/include/hw/riscv/riscv_htif.h b/include/hw/char/riscv_htif.h
index fb9452cf51..fb9452cf51 100644
--- a/include/hw/riscv/riscv_htif.h
+++ b/include/hw/char/riscv_htif.h
diff --git a/include/hw/riscv/sifive_uart.h b/include/hw/char/sifive_uart.h
index 65668825a3..65668825a3 100644
--- a/include/hw/riscv/sifive_uart.h
+++ b/include/hw/char/sifive_uart.h
diff --git a/include/hw/dma/sifive_pdma.h b/include/hw/dma/sifive_pdma.h
new file mode 100644
index 0000000000..e319bbd6c4
--- /dev/null
+++ b/include/hw/dma/sifive_pdma.h
@@ -0,0 +1,57 @@
+/*
+ * SiFive Platform DMA emulation
+ *
+ * Copyright (c) 2020 Wind River Systems, Inc.
+ *
+ * Author:
+ * Bin Meng <bin.meng@windriver.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 or
+ * (at your option) version 3 of the License.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef SIFIVE_PDMA_H
+#define SIFIVE_PDMA_H
+
+struct sifive_pdma_chan {
+ uint32_t control;
+ uint32_t next_config;
+ uint64_t next_bytes;
+ uint64_t next_dst;
+ uint64_t next_src;
+ uint32_t exec_config;
+ uint64_t exec_bytes;
+ uint64_t exec_dst;
+ uint64_t exec_src;
+ int state;
+};
+
+#define SIFIVE_PDMA_CHANS 4
+#define SIFIVE_PDMA_IRQS (SIFIVE_PDMA_CHANS * 2)
+#define SIFIVE_PDMA_REG_SIZE 0x100000
+#define SIFIVE_PDMA_CHAN_NO(reg) ((reg & (SIFIVE_PDMA_REG_SIZE - 1)) >> 12)
+
+typedef struct SiFivePDMAState {
+ SysBusDevice parent;
+ MemoryRegion iomem;
+ qemu_irq irq[SIFIVE_PDMA_IRQS];
+
+ struct sifive_pdma_chan chan[SIFIVE_PDMA_CHANS];
+} SiFivePDMAState;
+
+#define TYPE_SIFIVE_PDMA "sifive.pdma"
+
+#define SIFIVE_PDMA(obj) \
+ OBJECT_CHECK(SiFivePDMAState, (obj), TYPE_SIFIVE_PDMA)
+
+#endif /* SIFIVE_PDMA_H */
diff --git a/include/hw/riscv/sifive_gpio.h b/include/hw/gpio/sifive_gpio.h
index cf12fcfd62..cf12fcfd62 100644
--- a/include/hw/riscv/sifive_gpio.h
+++ b/include/hw/gpio/sifive_gpio.h
diff --git a/include/hw/riscv/sifive_clint.h b/include/hw/intc/sifive_clint.h
index 9f5fb3d31d..a30be0f3d6 100644
--- a/include/hw/riscv/sifive_clint.h
+++ b/include/hw/intc/sifive_clint.h
@@ -39,11 +39,13 @@ typedef struct SiFiveCLINTState {
uint32_t timecmp_base;
uint32_t time_base;
uint32_t aperture_size;
+ uint32_t timebase_freq;
} SiFiveCLINTState;
DeviceState *sifive_clint_create(hwaddr addr, hwaddr size,
uint32_t hartid_base, uint32_t num_harts, uint32_t sip_base,
- uint32_t timecmp_base, uint32_t time_base, bool provide_rdtime);
+ uint32_t timecmp_base, uint32_t time_base, uint32_t timebase_freq,
+ bool provide_rdtime);
enum {
SIFIVE_SIP_BASE = 0x0,
diff --git a/include/hw/riscv/sifive_e_prci.h b/include/hw/misc/sifive_e_prci.h
index 698b0b451c..698b0b451c 100644
--- a/include/hw/riscv/sifive_e_prci.h
+++ b/include/hw/misc/sifive_e_prci.h
diff --git a/include/hw/riscv/sifive_test.h b/include/hw/misc/sifive_test.h
index 1ec416ac1b..1ec416ac1b 100644
--- a/include/hw/riscv/sifive_test.h
+++ b/include/hw/misc/sifive_test.h
diff --git a/include/hw/riscv/sifive_u_otp.h b/include/hw/misc/sifive_u_otp.h
index 639297564a..639297564a 100644
--- a/include/hw/riscv/sifive_u_otp.h
+++ b/include/hw/misc/sifive_u_otp.h
diff --git a/include/hw/riscv/sifive_u_prci.h b/include/hw/misc/sifive_u_prci.h
index 0a531fdadc..0a531fdadc 100644
--- a/include/hw/riscv/sifive_u_prci.h
+++ b/include/hw/misc/sifive_u_prci.h
diff --git a/include/hw/net/cadence_gem.h b/include/hw/net/cadence_gem.h
index dff1083738..89d2dab513 100644
--- a/include/hw/net/cadence_gem.h
+++ b/include/hw/net/cadence_gem.h
@@ -76,6 +76,8 @@ struct CadenceGEMState {
/* Mask of register bits which are write 1 to clear */
uint32_t regs_w1c[CADENCE_GEM_MAXREG];
+ /* PHY address */
+ uint8_t phy_addr;
/* PHY registers backing store */
uint16_t phy_regs[32];
diff --git a/include/hw/riscv/microchip_pfsoc.h b/include/hw/riscv/microchip_pfsoc.h
new file mode 100644
index 0000000000..8bfc7e1a85
--- /dev/null
+++ b/include/hw/riscv/microchip_pfsoc.h
@@ -0,0 +1,133 @@
+/*
+ * Microchip PolarFire SoC machine interface
+ *
+ * Copyright (c) 2020 Wind River Systems, Inc.
+ *
+ * Author:
+ * Bin Meng <bin.meng@windriver.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef HW_MICROCHIP_PFSOC_H
+#define HW_MICROCHIP_PFSOC_H
+
+#include "hw/char/mchp_pfsoc_mmuart.h"
+#include "hw/dma/sifive_pdma.h"
+#include "hw/net/cadence_gem.h"
+#include "hw/sd/cadence_sdhci.h"
+
+typedef struct MicrochipPFSoCState {
+ /*< private >*/
+ DeviceState parent_obj;
+
+ /*< public >*/
+ CPUClusterState e_cluster;
+ CPUClusterState u_cluster;
+ RISCVHartArrayState e_cpus;
+ RISCVHartArrayState u_cpus;
+ DeviceState *plic;
+ MchpPfSoCMMUartState *serial0;
+ MchpPfSoCMMUartState *serial1;
+ MchpPfSoCMMUartState *serial2;
+ MchpPfSoCMMUartState *serial3;
+ MchpPfSoCMMUartState *serial4;
+ SiFivePDMAState dma;
+ CadenceGEMState gem0;
+ CadenceGEMState gem1;
+ CadenceSDHCIState sdhci;
+} MicrochipPFSoCState;
+
+#define TYPE_MICROCHIP_PFSOC "microchip.pfsoc"
+#define MICROCHIP_PFSOC(obj) \
+ OBJECT_CHECK(MicrochipPFSoCState, (obj), TYPE_MICROCHIP_PFSOC)
+
+typedef struct MicrochipIcicleKitState {
+ /*< private >*/
+ MachineState parent_obj;
+
+ /*< public >*/
+ MicrochipPFSoCState soc;
+} MicrochipIcicleKitState;
+
+#define TYPE_MICROCHIP_ICICLE_KIT_MACHINE \
+ MACHINE_TYPE_NAME("microchip-icicle-kit")
+#define MICROCHIP_ICICLE_KIT_MACHINE(obj) \
+ OBJECT_CHECK(MicrochipIcicleKitState, (obj), \
+ TYPE_MICROCHIP_ICICLE_KIT_MACHINE)
+
+enum {
+ MICROCHIP_PFSOC_DEBUG,
+ MICROCHIP_PFSOC_E51_DTIM,
+ MICROCHIP_PFSOC_BUSERR_UNIT0,
+ MICROCHIP_PFSOC_BUSERR_UNIT1,
+ MICROCHIP_PFSOC_BUSERR_UNIT2,
+ MICROCHIP_PFSOC_BUSERR_UNIT3,
+ MICROCHIP_PFSOC_BUSERR_UNIT4,
+ MICROCHIP_PFSOC_CLINT,
+ MICROCHIP_PFSOC_L2CC,
+ MICROCHIP_PFSOC_DMA,
+ MICROCHIP_PFSOC_L2LIM,
+ MICROCHIP_PFSOC_PLIC,
+ MICROCHIP_PFSOC_MMUART0,
+ MICROCHIP_PFSOC_SYSREG,
+ MICROCHIP_PFSOC_MPUCFG,
+ MICROCHIP_PFSOC_EMMC_SD,
+ MICROCHIP_PFSOC_MMUART1,
+ MICROCHIP_PFSOC_MMUART2,
+ MICROCHIP_PFSOC_MMUART3,
+ MICROCHIP_PFSOC_MMUART4,
+ MICROCHIP_PFSOC_GEM0,
+ MICROCHIP_PFSOC_GEM1,
+ MICROCHIP_PFSOC_GPIO0,
+ MICROCHIP_PFSOC_GPIO1,
+ MICROCHIP_PFSOC_GPIO2,
+ MICROCHIP_PFSOC_ENVM_CFG,
+ MICROCHIP_PFSOC_ENVM_DATA,
+ MICROCHIP_PFSOC_IOSCB_CFG,
+ MICROCHIP_PFSOC_DRAM,
+};
+
+enum {
+ MICROCHIP_PFSOC_DMA_IRQ0 = 5,
+ MICROCHIP_PFSOC_DMA_IRQ1 = 6,
+ MICROCHIP_PFSOC_DMA_IRQ2 = 7,
+ MICROCHIP_PFSOC_DMA_IRQ3 = 8,
+ MICROCHIP_PFSOC_DMA_IRQ4 = 9,
+ MICROCHIP_PFSOC_DMA_IRQ5 = 10,
+ MICROCHIP_PFSOC_DMA_IRQ6 = 11,
+ MICROCHIP_PFSOC_DMA_IRQ7 = 12,
+ MICROCHIP_PFSOC_GEM0_IRQ = 64,
+ MICROCHIP_PFSOC_GEM1_IRQ = 70,
+ MICROCHIP_PFSOC_EMMC_SD_IRQ = 88,
+ MICROCHIP_PFSOC_MMUART0_IRQ = 90,
+ MICROCHIP_PFSOC_MMUART1_IRQ = 91,
+ MICROCHIP_PFSOC_MMUART2_IRQ = 92,
+ MICROCHIP_PFSOC_MMUART3_IRQ = 93,
+ MICROCHIP_PFSOC_MMUART4_IRQ = 94,
+};
+
+#define MICROCHIP_PFSOC_MANAGEMENT_CPU_COUNT 1
+#define MICROCHIP_PFSOC_COMPUTE_CPU_COUNT 4
+
+#define MICROCHIP_PFSOC_PLIC_HART_CONFIG "MS"
+#define MICROCHIP_PFSOC_PLIC_NUM_SOURCES 185
+#define MICROCHIP_PFSOC_PLIC_NUM_PRIORITIES 7
+#define MICROCHIP_PFSOC_PLIC_PRIORITY_BASE 0x04
+#define MICROCHIP_PFSOC_PLIC_PENDING_BASE 0x1000
+#define MICROCHIP_PFSOC_PLIC_ENABLE_BASE 0x2000
+#define MICROCHIP_PFSOC_PLIC_ENABLE_STRIDE 0x80
+#define MICROCHIP_PFSOC_PLIC_CONTEXT_BASE 0x200000
+#define MICROCHIP_PFSOC_PLIC_CONTEXT_STRIDE 0x1000
+
+#endif /* HW_MICROCHIP_PFSOC_H */
diff --git a/include/hw/riscv/riscv_hart.h b/include/hw/riscv/riscv_hart.h
index 9be1fd80ed..ac2cb62e1b 100644
--- a/include/hw/riscv/riscv_hart.h
+++ b/include/hw/riscv/riscv_hart.h
@@ -39,6 +39,7 @@ struct RISCVHartArrayState {
uint32_t num_harts;
uint32_t hartid_base;
char *cpu_type;
+ uint64_t resetvec;
RISCVCPU *harts;
};
diff --git a/include/hw/riscv/sifive_e.h b/include/hw/riscv/sifive_e.h
index 637414130b..b1400843c2 100644
--- a/include/hw/riscv/sifive_e.h
+++ b/include/hw/riscv/sifive_e.h
@@ -21,7 +21,7 @@
#include "hw/riscv/riscv_hart.h"
#include "hw/riscv/sifive_cpu.h"
-#include "hw/riscv/sifive_gpio.h"
+#include "hw/gpio/sifive_gpio.h"
#define TYPE_RISCV_E_SOC "riscv.sifive.e.soc"
#define RISCV_E_SOC(obj) \
diff --git a/include/hw/riscv/sifive_u.h b/include/hw/riscv/sifive_u.h
index d3c0c00d10..fe5c580845 100644
--- a/include/hw/riscv/sifive_u.h
+++ b/include/hw/riscv/sifive_u.h
@@ -19,12 +19,13 @@
#ifndef HW_SIFIVE_U_H
#define HW_SIFIVE_U_H
+#include "hw/dma/sifive_pdma.h"
#include "hw/net/cadence_gem.h"
#include "hw/riscv/riscv_hart.h"
#include "hw/riscv/sifive_cpu.h"
-#include "hw/riscv/sifive_gpio.h"
-#include "hw/riscv/sifive_u_prci.h"
-#include "hw/riscv/sifive_u_otp.h"
+#include "hw/gpio/sifive_gpio.h"
+#include "hw/misc/sifive_u_otp.h"
+#include "hw/misc/sifive_u_prci.h"
#define TYPE_RISCV_U_SOC "riscv.sifive.u.soc"
#define RISCV_U_SOC(obj) \
@@ -43,6 +44,7 @@ typedef struct SiFiveUSoCState {
SiFiveUPRCIState prci;
SIFIVEGPIOState gpio;
SiFiveUOTPState otp;
+ SiFivePDMAState dma;
CadenceGEMState gem;
uint32_t serial;
@@ -72,6 +74,7 @@ enum {
SIFIVE_U_MROM,
SIFIVE_U_CLINT,
SIFIVE_U_L2CC,
+ SIFIVE_U_PDMA,
SIFIVE_U_L2LIM,
SIFIVE_U_PLIC,
SIFIVE_U_PRCI,
@@ -108,6 +111,14 @@ enum {
SIFIVE_U_GPIO_IRQ13 = 20,
SIFIVE_U_GPIO_IRQ14 = 21,
SIFIVE_U_GPIO_IRQ15 = 22,
+ SIFIVE_U_PDMA_IRQ0 = 23,
+ SIFIVE_U_PDMA_IRQ1 = 24,
+ SIFIVE_U_PDMA_IRQ2 = 25,
+ SIFIVE_U_PDMA_IRQ3 = 26,
+ SIFIVE_U_PDMA_IRQ4 = 27,
+ SIFIVE_U_PDMA_IRQ5 = 28,
+ SIFIVE_U_PDMA_IRQ6 = 29,
+ SIFIVE_U_PDMA_IRQ7 = 30,
SIFIVE_U_GEM_IRQ = 0x35
};
diff --git a/include/hw/sd/cadence_sdhci.h b/include/hw/sd/cadence_sdhci.h
new file mode 100644
index 0000000000..cd8288b7d8
--- /dev/null
+++ b/include/hw/sd/cadence_sdhci.h
@@ -0,0 +1,47 @@
+/*
+ * Cadence SDHCI emulation
+ *
+ * Copyright (c) 2020 Wind River Systems, Inc.
+ *
+ * Author:
+ * Bin Meng <bin.meng@windriver.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 or
+ * (at your option) version 3 of the License.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef CADENCE_SDHCI_H
+#define CADENCE_SDHCI_H
+
+#include "hw/sd/sdhci.h"
+
+#define CADENCE_SDHCI_REG_SIZE 0x100
+#define CADENCE_SDHCI_NUM_REGS (CADENCE_SDHCI_REG_SIZE / sizeof(uint32_t))
+
+typedef struct CadenceSDHCIState {
+ SysBusDevice parent;
+
+ MemoryRegion container;
+ MemoryRegion iomem;
+ BusState *bus;
+
+ uint32_t regs[CADENCE_SDHCI_NUM_REGS];
+
+ SDHCIState sdhci;
+} CadenceSDHCIState;
+
+#define TYPE_CADENCE_SDHCI "cadence.sdhci"
+#define CADENCE_SDHCI(obj) OBJECT_CHECK(CadenceSDHCIState, (obj), \
+ TYPE_CADENCE_SDHCI)
+
+#endif /* CADENCE_SDHCI_H */
diff --git a/meson.build b/meson.build
index bd84a1e777..690723b470 100644
--- a/meson.build
+++ b/meson.build
@@ -773,7 +773,6 @@ if have_system
'hw/watchdog',
'hw/xen',
'hw/gpio',
- 'hw/riscv',
'migration',
'net',
'softmmu',
diff --git a/target/mips/translate.c b/target/mips/translate.c
index 899b90ae0f..398edf7289 100644
--- a/target/mips/translate.c
+++ b/target/mips/translate.c
@@ -20028,8 +20028,7 @@ static void gen_pool32axf_nanomips_insn(CPUMIPSState *env, DisasContext *ctx)
static void gen_compute_imm_branch(DisasContext *ctx, uint32_t opc,
int rt, int32_t imm, int32_t offset)
{
- TCGCond cond;
- int bcond_compute = 0;
+ TCGCond cond = TCG_COND_ALWAYS;
TCGv t0 = tcg_temp_new();
TCGv t1 = tcg_temp_new();
@@ -20046,7 +20045,6 @@ static void gen_compute_imm_branch(DisasContext *ctx, uint32_t opc,
/* Treat as NOP */
goto out;
} else {
- bcond_compute = 1;
cond = TCG_COND_EQ;
}
break;
@@ -20065,7 +20063,6 @@ static void gen_compute_imm_branch(DisasContext *ctx, uint32_t opc,
tcg_gen_shri_tl(t0, t0, imm);
tcg_gen_andi_tl(t0, t0, 1);
tcg_gen_movi_tl(t1, 0);
- bcond_compute = 1;
if (opc == NM_BBEQZC) {
cond = TCG_COND_EQ;
} else {
@@ -20080,7 +20077,6 @@ static void gen_compute_imm_branch(DisasContext *ctx, uint32_t opc,
} else if (rt == 0 && imm != 0) {
/* Unconditional branch */
} else {
- bcond_compute = 1;
cond = TCG_COND_NE;
}
break;
@@ -20088,24 +20084,20 @@ static void gen_compute_imm_branch(DisasContext *ctx, uint32_t opc,
if (rt == 0 && imm == 0) {
/* Unconditional branch */
} else {
- bcond_compute = 1;
cond = TCG_COND_GE;
}
break;
case NM_BLTIC:
- bcond_compute = 1;
cond = TCG_COND_LT;
break;
case NM_BGEIUC:
if (rt == 0 && imm == 0) {
/* Unconditional branch */
} else {
- bcond_compute = 1;
cond = TCG_COND_GEU;
}
break;
case NM_BLTIUC:
- bcond_compute = 1;
cond = TCG_COND_LTU;
break;
default:
@@ -20118,7 +20110,7 @@ static void gen_compute_imm_branch(DisasContext *ctx, uint32_t opc,
clear_branch_hflags(ctx);
ctx->base.is_jmp = DISAS_NORETURN;
- if (bcond_compute == 0) {
+ if (cond == TCG_COND_ALWAYS) {
/* Uncoditional compact branch */
gen_goto_tb(ctx, 0, ctx->btarget);
} else {
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 228b9bdb5d..57c006df5d 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -96,6 +96,17 @@ const char * const riscv_intr_names[] = {
"reserved"
};
+const char *riscv_cpu_get_trap_name(target_ulong cause, bool async)
+{
+ if (async) {
+ return (cause < ARRAY_SIZE(riscv_intr_names)) ?
+ riscv_intr_names[cause] : "(unknown)";
+ } else {
+ return (cause < ARRAY_SIZE(riscv_excp_names)) ?
+ riscv_excp_names[cause] : "(unknown)";
+ }
+}
+
static void set_misa(CPURISCVState *env, target_ulong misa)
{
env->misa_mask = env->misa = misa;
@@ -128,7 +139,6 @@ static void riscv_any_cpu_init(Object *obj)
CPURISCVState *env = &RISCV_CPU(obj)->env;
set_misa(env, RVXLEN | RVI | RVM | RVA | RVF | RVD | RVC | RVU);
set_priv_version(env, PRIV_VERSION_1_11_0);
- set_resetvec(env, DEFAULT_RSTVEC);
}
static void riscv_base_cpu_init(Object *obj)
@@ -136,7 +146,6 @@ static void riscv_base_cpu_init(Object *obj)
CPURISCVState *env = &RISCV_CPU(obj)->env;
/* We set this in the realise function */
set_misa(env, 0);
- set_resetvec(env, DEFAULT_RSTVEC);
}
static void rvxx_sifive_u_cpu_init(Object *obj)
@@ -144,7 +153,6 @@ static void rvxx_sifive_u_cpu_init(Object *obj)
CPURISCVState *env = &RISCV_CPU(obj)->env;
set_misa(env, RVXLEN | RVI | RVM | RVA | RVF | RVD | RVC | RVS | RVU);
set_priv_version(env, PRIV_VERSION_1_10_0);
- set_resetvec(env, 0x1004);
}
static void rvxx_sifive_e_cpu_init(Object *obj)
@@ -152,7 +160,6 @@ static void rvxx_sifive_e_cpu_init(Object *obj)
CPURISCVState *env = &RISCV_CPU(obj)->env;
set_misa(env, RVXLEN | RVI | RVM | RVA | RVC | RVU);
set_priv_version(env, PRIV_VERSION_1_10_0);
- set_resetvec(env, 0x1004);
qdev_prop_set_bit(DEVICE(obj), "mmu", false);
}
@@ -163,7 +170,6 @@ static void rv32_ibex_cpu_init(Object *obj)
CPURISCVState *env = &RISCV_CPU(obj)->env;
set_misa(env, RV32 | RVI | RVM | RVC | RVU);
set_priv_version(env, PRIV_VERSION_1_10_0);
- set_resetvec(env, 0x8090);
qdev_prop_set_bit(DEVICE(obj), "mmu", false);
}
@@ -373,6 +379,8 @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp)
set_feature(env, RISCV_FEATURE_PMP);
}
+ set_resetvec(env, cpu->cfg.resetvec);
+
/* If misa isn't set (rv32 and rv64 machines) set it here */
if (!env->misa) {
/* Do some ISA extension error checking */
@@ -518,6 +526,7 @@ static Property riscv_cpu_properties[] = {
DEFINE_PROP_UINT16("elen", RISCVCPU, cfg.elen, 64),
DEFINE_PROP_BOOL("mmu", RISCVCPU, cfg.mmu, true),
DEFINE_PROP_BOOL("pmp", RISCVCPU, cfg.pmp, true),
+ DEFINE_PROP_UINT64("resetvec", RISCVCPU, cfg.resetvec, DEFAULT_RSTVEC),
DEFINE_PROP_END_OF_LIST(),
};
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index ca75fc761e..4c00d35ccd 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -220,7 +220,8 @@ struct CPURISCVState {
pmp_table_t pmp_state;
/* machine specific rdtime callback */
- uint64_t (*rdtime_fn)(void);
+ uint64_t (*rdtime_fn)(uint32_t);
+ uint32_t rdtime_fn_arg;
/* True if in debugger mode. */
bool debugger;
@@ -288,6 +289,7 @@ struct RISCVCPU {
uint16_t elen;
bool mmu;
bool pmp;
+ uint64_t resetvec;
} cfg;
};
@@ -309,6 +311,7 @@ extern const char * const riscv_fpr_regnames[];
extern const char * const riscv_excp_names[];
extern const char * const riscv_intr_names[];
+const char *riscv_cpu_get_trap_name(target_ulong cause, bool async);
void riscv_cpu_do_interrupt(CPUState *cpu);
int riscv_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg);
int riscv_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
@@ -345,7 +348,8 @@ void riscv_cpu_swap_hypervisor_regs(CPURISCVState *env);
int riscv_cpu_claim_interrupts(RISCVCPU *cpu, uint32_t interrupts);
uint32_t riscv_cpu_update_mip(RISCVCPU *cpu, uint32_t mask, uint32_t value);
#define BOOL_TO_MASK(x) (-!!(x)) /* helper for riscv_cpu_update_mip value */
-void riscv_cpu_set_rdtime_fn(CPURISCVState *env, uint64_t (*fn)(void));
+void riscv_cpu_set_rdtime_fn(CPURISCVState *env, uint64_t (*fn)(uint32_t),
+ uint32_t arg);
#endif
void riscv_cpu_set_mode(CPURISCVState *env, target_ulong newpriv);
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index dc7ae3e7b1..f4c4111536 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -276,9 +276,11 @@ uint32_t riscv_cpu_update_mip(RISCVCPU *cpu, uint32_t mask, uint32_t value)
return old;
}
-void riscv_cpu_set_rdtime_fn(CPURISCVState *env, uint64_t (*fn)(void))
+void riscv_cpu_set_rdtime_fn(CPURISCVState *env, uint64_t (*fn)(uint32_t),
+ uint32_t arg)
{
env->rdtime_fn = fn;
+ env->rdtime_fn_arg = arg;
}
void riscv_cpu_set_mode(CPURISCVState *env, target_ulong newpriv)
@@ -892,8 +894,8 @@ void riscv_cpu_do_interrupt(CPUState *cs)
}
}
- trace_riscv_trap(env->mhartid, async, cause, env->pc, tval, cause < 23 ?
- (async ? riscv_intr_names : riscv_excp_names)[cause] : "(unknown)");
+ trace_riscv_trap(env->mhartid, async, cause, env->pc, tval,
+ riscv_cpu_get_trap_name(cause, async));
if (env->priv <= PRV_S &&
cause < TARGET_LONG_BITS && ((deleg >> cause) & 1)) {
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index 200001de74..26ae347b4a 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -351,7 +351,7 @@ static int read_time(CPURISCVState *env, int csrno, target_ulong *val)
return -RISCV_EXCP_ILLEGAL_INST;
}
- *val = env->rdtime_fn() + delta;
+ *val = env->rdtime_fn(env->rdtime_fn_arg) + delta;
return 0;
}
@@ -364,7 +364,7 @@ static int read_timeh(CPURISCVState *env, int csrno, target_ulong *val)
return -RISCV_EXCP_ILLEGAL_INST;
}
- *val = (env->rdtime_fn() + delta) >> 32;
+ *val = (env->rdtime_fn(env->rdtime_fn_arg) + delta) >> 32;
return 0;
}
#endif
diff --git a/tests/Makefile.include b/tests/Makefile.include
index f93e611220..40d909badc 100644
--- a/tests/Makefile.include
+++ b/tests/Makefile.include
@@ -50,7 +50,7 @@ RUN_TCG_TARGET_RULES=$(patsubst %,run-tcg-tests-%, $(TARGET_DIRS))
$(foreach PROBE_TARGET,$(TARGET_DIRS), \
$(eval -include $(SRC_PATH)/tests/tcg/Makefile.prereqs))
-build-tcg-tests-%: $(if $(CONFIG_PLUGIN),plugins)
+build-tcg-tests-%: $(if $(CONFIG_PLUGIN),test-plugins)
$(call quiet-command,$(MAKE) $(SUBDIR_MAKEFLAGS) \
-f $(SRC_PATH)/tests/tcg/Makefile.qemu \
SRC_PATH=$(SRC_PATH) \
@@ -127,7 +127,7 @@ check-acceptance: check-venv $(TESTS_RESULTS_DIR) get-vm-images
--show=$(AVOCADO_SHOW) run --job-results-dir=$(TESTS_RESULTS_DIR) \
--filter-by-tags-include-empty --filter-by-tags-include-empty-key \
$(AVOCADO_TAGS) \
- $(if $(GITLAB_CI),,--failfast=on) tests/acceptance, \
+ $(if $(GITLAB_CI),,--failfast) tests/acceptance, \
"AVOCADO", "tests/acceptance")
# Consolidated targets
diff --git a/tests/acceptance/avocado_qemu/__init__.py b/tests/acceptance/avocado_qemu/__init__.py
index db9c0f5d79..4cda037187 100644
--- a/tests/acceptance/avocado_qemu/__init__.py
+++ b/tests/acceptance/avocado_qemu/__init__.py
@@ -192,3 +192,15 @@ class Test(avocado.Test):
def tearDown(self):
for vm in self._vms.values():
vm.shutdown()
+
+ def fetch_asset(self, name,
+ asset_hash=None, algorithm=None,
+ locations=None, expire=None,
+ find_only=False, cancel_on_missing=True):
+ return super(Test, self).fetch_asset(name,
+ asset_hash=asset_hash,
+ algorithm=algorithm,
+ locations=locations,
+ expire=expire,
+ find_only=find_only,
+ cancel_on_missing=cancel_on_missing)
diff --git a/tests/meson.build b/tests/meson.build
index 998e4c48f9..dae8a77df1 100644
--- a/tests/meson.build
+++ b/tests/meson.build
@@ -259,8 +259,9 @@ test('decodetree', sh,
workdir: meson.current_source_dir() / 'decode',
suite: 'decodetree')
+subdir('fp')
+
if 'CONFIG_TCG' in config_host
- subdir('fp')
if 'CONFIG_PLUGIN' in config_host
subdir('plugin')
endif
diff --git a/tests/plugin/meson.build b/tests/plugin/meson.build
index dbbdcbaa67..1eacfa6e35 100644
--- a/tests/plugin/meson.build
+++ b/tests/plugin/meson.build
@@ -1,7 +1,7 @@
t = []
-foreach i : ['bb', 'empty', 'insn', 'mem', 'hotblocks', 'howvec', 'hotpages', 'lockstep']
+foreach i : ['bb', 'empty', 'insn', 'mem']
t += shared_module(i, files(i + '.c'),
include_directories: '../../include/qemu',
dependencies: glib)
endforeach
-alias_target('plugins', t)
+alias_target('test-plugins', t)
diff --git a/tests/requirements.txt b/tests/requirements.txt
index f9c84b4ba1..036691c922 100644
--- a/tests/requirements.txt
+++ b/tests/requirements.txt
@@ -1,5 +1,5 @@
# Add Python module requirements, one per line, to be installed
# in the tests/venv Python virtual environment. For more info,
# refer to: https://pip.pypa.io/en/stable/user_guide/#id1
-avocado-framework==76.0
+avocado-framework==81.0
pycdlib==1.9.0
diff --git a/tests/tcg/Makefile.target b/tests/tcg/Makefile.target
index 4b2b696fce..2ae86776cd 100644
--- a/tests/tcg/Makefile.target
+++ b/tests/tcg/Makefile.target
@@ -129,8 +129,7 @@ ifeq ($(CONFIG_PLUGIN),y)
PLUGIN_SRC=$(SRC_PATH)/tests/plugin
PLUGIN_LIB=../../plugin
VPATH+=$(PLUGIN_LIB)
-PLUGINS=$(filter-out liblockstep.so,\
- $(patsubst %.c, lib%.so, $(notdir $(wildcard $(PLUGIN_SRC)/*.c))))
+PLUGINS=$(patsubst %.c, lib%.so, $(notdir $(wildcard $(PLUGIN_SRC)/*.c)))
# We need to ensure expand the run-plugin-TEST-with-PLUGIN
# pre-requistes manually here as we can't use stems to handle it. We