mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-09 02:24:58 -06:00
Various testing updates
- semihosting re-factor (used in system tests) - aarch64 and alpha system tests - editorconfig tweak for .S - some docker image updates - iotests clean-up (without make check inclusion) -----BEGIN PGP SIGNATURE----- iQEzBAABCgAdFiEEZoWumedRZ7yvyN81+9DbCVqeKkQFAlztYToACgkQ+9DbCVqe KkQU9wf/Uv5qBgDn9MwcCt8tzHTX/i21QHwFLBbCmFoUwZjSridZ2KV6Ma3ig4mF xY+8Cr5oZT186V+aD39K6KCZKqZRulIpRVNkOKXEfAAklUoAyQs95Wa8F8LtO1eG vOtOYEdkXQQiAnlnQ+eaGiZQ2mpbCbREa10JrBhxp6iXh0PYcvtD7iAlOldqIvd2 hDRwOgTtYoiiKh6UdediAgQsRvv6oNPHFUOjWgrGxfhPWKbjCVKl7VS4furg9zux j/S0E0xYKhj+JNq3arjiMUMl19TauCBQLrbQpphd1jOl1s7bELRjAuaKM60TVIbW Hd2/PYbGnkpyUcJQh0Pr1cb4RMcznw== =lvtu -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/stsquad/tags/pull-testing-next-280519-2' into staging Various testing updates - semihosting re-factor (used in system tests) - aarch64 and alpha system tests - editorconfig tweak for .S - some docker image updates - iotests clean-up (without make check inclusion) # gpg: Signature made Tue 28 May 2019 17:26:34 BST # gpg: using RSA key 6685AE99E75167BCAFC8DF35FBD0DB095A9E2A44 # gpg: Good signature from "Alex Bennée (Master Work Key) <alex.bennee@linaro.org>" [full] # Primary key fingerprint: 6685 AE99 E751 67BC AFC8 DF35 FBD0 DB09 5A9E 2A44 * remotes/stsquad/tags/pull-testing-next-280519-2: (27 commits) tests/qemu-iotests: re-format output to for make check-block tests/qemu-iotests/group: Re-use the "auto" group for tests that can always run Makefile.target: support per-target coverage reports Makefile: include per-target build directories in coverage report Makefile: fix coverage-report reference to BUILD_DIR .travis.yml: enable aarch64-softmmu and alpha-softmmu tcg tests tests/tcg/alpha: add system boot.S tests/tcg/multiarch: expand system memory test to cover more tests/tcg/minilib: support %c format char tests/tcg/multiarch: move the system memory test tests/tcg/aarch64: add system boot.S editorconfig: add settings for .s/.S files tests/tcg/multiarch: add hello world system test tests/tcg/multiarch: add support for multiarch system tests tests/docker: Test more components on the Fedora default image tests/docker: add ubuntu 18.04 MAINTAINERS: update for semihostings new home target/mips: convert UHI_plog to use common semihosting code target/mips: only build mips-semi for softmmu target/arm: correct return values for WRITE/READ in arm-semi ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
8c1ecb5904
58 changed files with 2178 additions and 580 deletions
|
@ -8,6 +8,7 @@ ENV PACKAGES \
|
|||
bzip2-devel \
|
||||
ccache \
|
||||
clang \
|
||||
cyrus-sasl-devel \
|
||||
device-mapper-multipath-devel \
|
||||
findutils \
|
||||
flex \
|
||||
|
@ -23,13 +24,17 @@ ENV PACKAGES \
|
|||
libaio-devel \
|
||||
libasan \
|
||||
libattr-devel \
|
||||
libblockdev-mpath-devel \
|
||||
libcap-devel \
|
||||
libcap-ng-devel \
|
||||
libcurl-devel \
|
||||
libfdt-devel \
|
||||
libiscsi-devel \
|
||||
libjpeg-devel \
|
||||
libpmem-devel \
|
||||
libpng-devel \
|
||||
librbd-devel \
|
||||
libseccomp-devel \
|
||||
libssh2-devel \
|
||||
libubsan \
|
||||
libusbx-devel \
|
||||
|
@ -74,10 +79,12 @@ ENV PACKAGES \
|
|||
pixman-devel \
|
||||
python3 \
|
||||
PyYAML \
|
||||
rdma-core-devel \
|
||||
SDL2-devel \
|
||||
snappy-devel \
|
||||
sparse \
|
||||
spice-server-devel \
|
||||
systemd-devel \
|
||||
systemtap-sdt-devel \
|
||||
tar \
|
||||
usbredir-devel \
|
||||
|
|
57
tests/docker/dockerfiles/ubuntu1804.docker
Normal file
57
tests/docker/dockerfiles/ubuntu1804.docker
Normal file
|
@ -0,0 +1,57 @@
|
|||
FROM ubuntu:18.04
|
||||
ENV PACKAGES flex bison \
|
||||
ccache \
|
||||
clang \
|
||||
gcc \
|
||||
gettext \
|
||||
git \
|
||||
glusterfs-common \
|
||||
libaio-dev \
|
||||
libattr1-dev \
|
||||
libbluetooth-dev \
|
||||
libbrlapi-dev \
|
||||
libbz2-dev \
|
||||
libcacard-dev \
|
||||
libcap-dev \
|
||||
libcap-ng-dev \
|
||||
libcurl4-gnutls-dev \
|
||||
libdrm-dev \
|
||||
libepoxy-dev \
|
||||
libfdt-dev \
|
||||
libgbm-dev \
|
||||
libgtk-3-dev \
|
||||
libibverbs-dev \
|
||||
libiscsi-dev \
|
||||
libjemalloc-dev \
|
||||
libjpeg-turbo8-dev \
|
||||
liblzo2-dev \
|
||||
libncurses5-dev \
|
||||
libncursesw5-dev \
|
||||
libnfs-dev \
|
||||
libnss3-dev \
|
||||
libnuma-dev \
|
||||
libpixman-1-dev \
|
||||
librados-dev \
|
||||
librbd-dev \
|
||||
librdmacm-dev \
|
||||
libsasl2-dev \
|
||||
libsdl2-dev \
|
||||
libseccomp-dev \
|
||||
libsnappy-dev \
|
||||
libspice-protocol-dev \
|
||||
libspice-server-dev \
|
||||
libssh2-1-dev \
|
||||
libusb-1.0-0-dev \
|
||||
libusbredirhost-dev \
|
||||
libvdeplug-dev \
|
||||
libvte-2.91-dev \
|
||||
libxen-dev \
|
||||
make \
|
||||
python-yaml \
|
||||
sparse \
|
||||
texinfo \
|
||||
xfslibs-dev
|
||||
RUN apt-get update && \
|
||||
apt-get -y install $PACKAGES
|
||||
RUN dpkg -l $PACKAGES | sort > /packages.txt
|
||||
ENV FEATURES clang pyyaml sdl2
|
|
@ -27,9 +27,7 @@ bad=""
|
|||
notrun=""
|
||||
casenotrun=""
|
||||
interrupt=true
|
||||
|
||||
# by default don't output timestamps
|
||||
timestamp=${TIMESTAMP:=false}
|
||||
makecheck=false
|
||||
|
||||
_init_error()
|
||||
{
|
||||
|
@ -88,6 +86,22 @@ _full_platform_details()
|
|||
echo "$os/$platform $host $kernel"
|
||||
}
|
||||
|
||||
_full_env_details()
|
||||
{
|
||||
cat <<EOF
|
||||
QEMU -- "$QEMU_PROG" $QEMU_OPTIONS
|
||||
QEMU_IMG -- "$QEMU_IMG_PROG" $QEMU_IMG_OPTIONS
|
||||
QEMU_IO -- "$QEMU_IO_PROG" $QEMU_IO_OPTIONS
|
||||
QEMU_NBD -- "$QEMU_NBD_PROG" $QEMU_NBD_OPTIONS
|
||||
IMGFMT -- $FULL_IMGFMT_DETAILS
|
||||
IMGPROTO -- $IMGPROTO
|
||||
PLATFORM -- $FULL_HOST_DETAILS
|
||||
TEST_DIR -- $TEST_DIR
|
||||
SOCKET_SCM_HELPER -- $SOCKET_SCM_HELPER
|
||||
|
||||
EOF
|
||||
}
|
||||
|
||||
# $1 = prog to look for
|
||||
set_prog_path()
|
||||
{
|
||||
|
@ -254,8 +268,8 @@ other options
|
|||
-misalign misalign memory allocations
|
||||
-n show me, do not run tests
|
||||
-o options -o options to pass to qemu-img create/convert
|
||||
-T output timestamps
|
||||
-c mode cache mode
|
||||
-makecheck pretty print output for make check
|
||||
|
||||
testlist options
|
||||
-g group[,group...] include tests from these groups
|
||||
|
@ -403,7 +417,10 @@ testlist options
|
|||
command -v xxdiff >/dev/null 2>&1 && diff=xxdiff
|
||||
fi
|
||||
;;
|
||||
|
||||
-makecheck) # makecheck friendly output
|
||||
makecheck=true
|
||||
xpand=false
|
||||
;;
|
||||
-n) # show me, don't do it
|
||||
showme=true
|
||||
xpand=false
|
||||
|
@ -416,8 +433,7 @@ testlist options
|
|||
cachemode=true
|
||||
xpand=false
|
||||
;;
|
||||
-T) # turn on timestamp output
|
||||
timestamp=true
|
||||
-T) # deprecated timestamp option
|
||||
xpand=false
|
||||
;;
|
||||
|
||||
|
@ -633,12 +649,6 @@ _wallclock()
|
|||
date "+%H %M %S" | awk '{ print $1*3600 + $2*60 + $3 }'
|
||||
}
|
||||
|
||||
_timestamp()
|
||||
{
|
||||
now=$(date "+%T")
|
||||
printf %s " [$now]"
|
||||
}
|
||||
|
||||
_wrapup()
|
||||
{
|
||||
if $showme
|
||||
|
@ -704,23 +714,54 @@ END { if (NR > 0) {
|
|||
|
||||
trap "_wrapup; exit \$status" 0 1 2 3 15
|
||||
|
||||
# Report the test start and results. For makecheck we want to pretty
|
||||
# print the whole report at the end of the execution.
|
||||
# args: $seq, $starttime, $lasttime
|
||||
_report_test_start()
|
||||
{
|
||||
if ! $makecheck; then
|
||||
if [ -n "$3" ]; then
|
||||
local lasttime=" (last: $3s)"
|
||||
fi
|
||||
printf "%-8s %-10s [%s] %4s%-14s\r" "$1" "..." "$2" "..." "$lasttime"
|
||||
fi
|
||||
}
|
||||
# args:$seq $status $starttime $lasttime $thistime $details
|
||||
_report_test_result()
|
||||
{
|
||||
local status lasttime thistime
|
||||
if $makecheck; then
|
||||
if [ -n "$2" ] && [ "$2" != "pass" ]; then
|
||||
status=" [$2]"
|
||||
fi
|
||||
printf " TEST iotest-$IMGFMT: %s%s\n" "$1" "$status"
|
||||
return
|
||||
fi
|
||||
|
||||
if [ -n "$4" ]; then
|
||||
lasttime=" (last: $4s)"
|
||||
fi
|
||||
if [ -n "$5" ]; then
|
||||
thistime=" $5s"
|
||||
fi
|
||||
case "$2" in
|
||||
"pass") status=$(printf "\e[32m%-10s\e[0m" "$2") ;;
|
||||
"fail") status=$(printf "\e[1m\e[31m%-10s\e[0m" "$2") ;;
|
||||
"not run") status=$(printf "\e[33m%-10s\e[0m" "$2") ;;
|
||||
*) status=$(printf "%-10s" "$2") ;;
|
||||
esac
|
||||
|
||||
printf "%-8s %s [%s] [%s] %4s%-14s %s\n" "$1" "$status" "$3" "$(date '+%T')" "$thistime" "$lasttime" "$6"
|
||||
}
|
||||
|
||||
[ -f $TIMESTAMP_FILE ] || touch $TIMESTAMP_FILE
|
||||
|
||||
FULL_IMGFMT_DETAILS=$(_full_imgfmt_details)
|
||||
FULL_HOST_DETAILS=$(_full_platform_details)
|
||||
|
||||
cat <<EOF
|
||||
QEMU -- "$QEMU_PROG" $QEMU_OPTIONS
|
||||
QEMU_IMG -- "$QEMU_IMG_PROG" $QEMU_IMG_OPTIONS
|
||||
QEMU_IO -- "$QEMU_IO_PROG" $QEMU_IO_OPTIONS
|
||||
QEMU_NBD -- "$QEMU_NBD_PROG" $QEMU_NBD_OPTIONS
|
||||
IMGFMT -- $FULL_IMGFMT_DETAILS
|
||||
IMGPROTO -- $IMGPROTO
|
||||
PLATFORM -- $FULL_HOST_DETAILS
|
||||
TEST_DIR -- $TEST_DIR
|
||||
SOCKET_SCM_HELPER -- $SOCKET_SCM_HELPER
|
||||
|
||||
EOF
|
||||
if ! $makecheck; then
|
||||
_full_env_details
|
||||
fi
|
||||
|
||||
seq="check"
|
||||
|
||||
|
@ -728,42 +769,43 @@ seq="check"
|
|||
|
||||
for seq in $list
|
||||
do
|
||||
err=false
|
||||
printf %s "$seq"
|
||||
err=false # error flag
|
||||
printdiff=false # show diff to reference output?
|
||||
status="" # test result summary
|
||||
results="" # test result details
|
||||
|
||||
if [ -n "$TESTS_REMAINING_LOG" ] ; then
|
||||
sed -e "s/$seq//" -e 's/ / /' -e 's/^ *//' $TESTS_REMAINING_LOG > $TESTS_REMAINING_LOG.tmp
|
||||
mv $TESTS_REMAINING_LOG.tmp $TESTS_REMAINING_LOG
|
||||
sync
|
||||
fi
|
||||
|
||||
lasttime=$(sed -n -e "/^$seq /s/.* //p" <$TIMESTAMP_FILE)
|
||||
starttime=$(date "+%T")
|
||||
_report_test_start $seq $starttime $lasttime
|
||||
|
||||
if $showme
|
||||
then
|
||||
echo
|
||||
continue
|
||||
status="not run"
|
||||
elif [ -f expunged ] && $expunge && egrep "^$seq([ ]|\$)" expunged >/dev/null
|
||||
then
|
||||
echo " - expunged"
|
||||
status="not run"
|
||||
results="expunged"
|
||||
rm -f $seq.out.bad
|
||||
echo "/^$seq\$/d" >>$tmp.expunged
|
||||
elif [ ! -f "$source_iotests/$seq" ]
|
||||
then
|
||||
echo " - no such test?"
|
||||
status="not run"
|
||||
results="no such test?"
|
||||
echo "/^$seq\$/d" >>$tmp.expunged
|
||||
else
|
||||
# really going to try and run this one
|
||||
#
|
||||
rm -f $seq.out.bad
|
||||
lasttime=$(sed -n -e "/^$seq /s/.* //p" <$TIMESTAMP_FILE)
|
||||
if [ "X$lasttime" != X ]; then
|
||||
printf %s " ${lasttime}s ..."
|
||||
else
|
||||
printf " " # prettier output with timestamps.
|
||||
fi
|
||||
rm -f core $seq.notrun
|
||||
rm -f $seq.casenotrun
|
||||
|
||||
start=$(_wallclock)
|
||||
$timestamp && printf %s " [$(date "+%T")]"
|
||||
|
||||
if [ "$(head -n 1 "$source_iotests/$seq")" == "#!/usr/bin/env python" ]; then
|
||||
run_command="$PYTHON $seq"
|
||||
|
@ -781,26 +823,26 @@ do
|
|||
$run_command >$tmp.out 2>&1)
|
||||
fi
|
||||
sts=$?
|
||||
$timestamp && _timestamp
|
||||
stop=$(_wallclock)
|
||||
|
||||
if [ -f core ]
|
||||
then
|
||||
printf " [dumped core]"
|
||||
mv core $seq.core
|
||||
status="fail"
|
||||
results="[dumped core] $seq.core"
|
||||
err=true
|
||||
fi
|
||||
|
||||
if [ -f $seq.notrun ]
|
||||
then
|
||||
$timestamp || printf " [not run] "
|
||||
$timestamp && echo " [not run]" && printf %s " $seq -- "
|
||||
cat $seq.notrun
|
||||
notrun="$notrun $seq"
|
||||
# overwrites timestamp output
|
||||
status="not run"
|
||||
results="$(cat $seq.notrun)"
|
||||
else
|
||||
if [ $sts -ne 0 ]
|
||||
then
|
||||
printf %s " [failed, exit status $sts]"
|
||||
status="fail"
|
||||
results=$(printf %s "[failed, exit status $sts]")
|
||||
err=true
|
||||
fi
|
||||
|
||||
|
@ -821,22 +863,23 @@ do
|
|||
|
||||
if [ ! -f "$reference" ]
|
||||
then
|
||||
echo " - no qualified output"
|
||||
status="fail"
|
||||
reason="no qualified output"
|
||||
err=true
|
||||
else
|
||||
if diff -w "$reference" $tmp.out >/dev/null 2>&1
|
||||
then
|
||||
echo ""
|
||||
if $err
|
||||
then
|
||||
:
|
||||
else
|
||||
echo "$seq $(expr $stop - $start)" >>$tmp.time
|
||||
if ! $err; then
|
||||
status="pass"
|
||||
thistime=$(expr $stop - $start)
|
||||
echo "$seq $thistime" >>$tmp.time
|
||||
fi
|
||||
else
|
||||
echo " - output mismatch (see $seq.out.bad)"
|
||||
mv $tmp.out $seq.out.bad
|
||||
$diff -w "$reference" "$PWD"/$seq.out.bad
|
||||
status="fail"
|
||||
results="output mismatch (see $seq.out.bad)"
|
||||
printdiff=true
|
||||
err=true
|
||||
fi
|
||||
fi
|
||||
|
@ -850,13 +893,27 @@ do
|
|||
|
||||
# come here for each test, except when $showme is true
|
||||
#
|
||||
if $err
|
||||
then
|
||||
bad="$bad $seq"
|
||||
n_bad=$(expr $n_bad + 1)
|
||||
quick=false
|
||||
fi
|
||||
[ -f $seq.notrun ] || try=$(expr $try + 1)
|
||||
_report_test_result $seq "$status" "$starttime" "$lasttime" "$thistime" "$results"
|
||||
case "$status" in
|
||||
"pass")
|
||||
try=$(expr $try + 1)
|
||||
;;
|
||||
"fail")
|
||||
try=$(expr $try + 1)
|
||||
if $makecheck; then
|
||||
_full_env_details
|
||||
fi
|
||||
if $printdiff; then
|
||||
$diff -w "$reference" "$PWD"/$seq.out.bad
|
||||
fi
|
||||
bad="$bad $seq"
|
||||
n_bad=$(expr $n_bad + 1)
|
||||
quick=false
|
||||
;;
|
||||
"not run")
|
||||
notrun="$notrun $seq"
|
||||
;;
|
||||
esac
|
||||
|
||||
seq="after_$seq"
|
||||
done
|
||||
|
|
|
@ -1,8 +1,21 @@
|
|||
#
|
||||
# QA groups control file
|
||||
# Defines test groups
|
||||
#
|
||||
# Some notes about the groups:
|
||||
#
|
||||
# - do not start group names with a digit
|
||||
#
|
||||
# - quick : Tests in this group should finish within some few seconds.
|
||||
#
|
||||
# - img : Tests in this group can be used to excercise the qemu-img tool.
|
||||
#
|
||||
# - auto : Tests in this group are used during "make check" and should be
|
||||
# runnable in any case. That means they should run with every QEMU binary
|
||||
# (also non-x86), with every QEMU configuration (i.e. must not fail if
|
||||
# an optional feature is not compiled in - but reporting a "skip" is ok),
|
||||
# and work all kind of host filesystems and users (e.g. "nobody" or "root").
|
||||
#
|
||||
|
||||
#
|
||||
# test-group association ... one line per test
|
||||
|
@ -32,11 +45,11 @@
|
|||
023 rw auto
|
||||
024 rw backing auto quick
|
||||
025 rw auto quick
|
||||
026 rw blkdbg auto
|
||||
026 rw blkdbg
|
||||
027 rw auto quick
|
||||
028 rw backing auto quick
|
||||
028 rw backing quick
|
||||
029 rw auto quick
|
||||
030 rw auto backing
|
||||
030 rw backing
|
||||
031 rw auto quick
|
||||
032 rw auto quick
|
||||
033 rw auto quick
|
||||
|
@ -46,35 +59,35 @@
|
|||
037 rw auto backing quick
|
||||
038 rw auto backing quick
|
||||
039 rw auto quick
|
||||
040 rw auto
|
||||
041 rw auto backing
|
||||
040 rw
|
||||
041 rw backing
|
||||
042 rw auto quick
|
||||
043 rw auto backing
|
||||
044 rw auto
|
||||
045 rw auto quick
|
||||
044 rw
|
||||
045 rw quick
|
||||
046 rw auto aio quick
|
||||
047 rw auto quick
|
||||
048 img auto quick
|
||||
049 rw auto
|
||||
050 rw auto backing quick
|
||||
051 rw auto
|
||||
051 rw
|
||||
052 rw auto backing quick
|
||||
053 rw auto quick
|
||||
054 rw auto quick
|
||||
055 rw auto
|
||||
056 rw auto backing
|
||||
057 rw auto
|
||||
058 rw auto quick
|
||||
055 rw
|
||||
056 rw backing
|
||||
057 rw
|
||||
058 rw quick
|
||||
059 rw auto quick
|
||||
060 rw auto quick
|
||||
061 rw auto
|
||||
062 rw auto quick
|
||||
063 rw auto quick
|
||||
064 rw auto quick
|
||||
065 rw auto quick
|
||||
065 rw quick
|
||||
066 rw auto quick
|
||||
067 rw auto quick
|
||||
068 rw auto quick
|
||||
067 rw quick
|
||||
068 rw quick
|
||||
069 rw auto quick
|
||||
070 rw auto quick
|
||||
071 rw auto quick
|
||||
|
@ -91,18 +104,18 @@
|
|||
082 rw auto quick
|
||||
083 rw auto
|
||||
084 img auto quick
|
||||
085 rw auto
|
||||
085 rw
|
||||
086 rw auto quick
|
||||
087 rw auto quick
|
||||
087 rw quick
|
||||
088 rw auto quick
|
||||
089 rw auto quick
|
||||
090 rw auto quick
|
||||
091 rw auto migration
|
||||
092 rw auto quick
|
||||
093 auto
|
||||
093 throttle
|
||||
094 rw auto quick
|
||||
095 rw auto quick
|
||||
096 rw auto quick
|
||||
095 rw quick
|
||||
096 rw quick
|
||||
097 rw auto backing
|
||||
098 rw auto backing quick
|
||||
099 rw auto quick
|
||||
|
@ -118,60 +131,60 @@
|
|||
109 rw auto
|
||||
110 rw auto backing quick
|
||||
111 rw auto quick
|
||||
112 rw auto
|
||||
112 rw
|
||||
113 rw auto quick
|
||||
114 rw auto quick
|
||||
115 rw auto
|
||||
115 rw
|
||||
116 rw auto quick
|
||||
117 rw auto
|
||||
118 rw auto
|
||||
118 rw
|
||||
119 rw auto quick
|
||||
120 rw auto quick
|
||||
121 rw auto
|
||||
121 rw
|
||||
122 rw auto
|
||||
123 rw auto quick
|
||||
124 rw auto backing
|
||||
125 rw auto
|
||||
124 rw backing
|
||||
125 rw
|
||||
126 rw auto backing
|
||||
127 rw auto backing quick
|
||||
127 rw backing quick
|
||||
128 rw auto quick
|
||||
129 rw auto quick
|
||||
129 rw quick
|
||||
130 rw auto quick
|
||||
131 rw auto quick
|
||||
132 rw auto quick
|
||||
132 rw quick
|
||||
133 auto quick
|
||||
134 rw auto quick
|
||||
135 rw auto
|
||||
136 rw auto
|
||||
136 rw
|
||||
137 rw auto
|
||||
138 rw auto quick
|
||||
139 rw auto quick
|
||||
139 rw quick
|
||||
140 rw auto quick
|
||||
141 rw auto quick
|
||||
142 auto
|
||||
143 auto quick
|
||||
144 rw auto quick
|
||||
145 auto quick
|
||||
144 rw quick
|
||||
145 quick
|
||||
146 auto quick
|
||||
147 auto
|
||||
148 rw auto quick
|
||||
149 rw auto sudo
|
||||
147 img
|
||||
148 rw quick
|
||||
149 rw sudo
|
||||
150 rw auto quick
|
||||
151 rw auto
|
||||
152 rw auto quick
|
||||
153 rw auto quick
|
||||
151 rw
|
||||
152 rw quick
|
||||
153 rw quick
|
||||
154 rw auto backing quick
|
||||
155 rw auto
|
||||
155 rw
|
||||
156 rw auto quick
|
||||
157 auto
|
||||
157 quick
|
||||
158 rw auto quick
|
||||
159 rw auto quick
|
||||
160 rw auto quick
|
||||
161 rw auto quick
|
||||
162 auto quick
|
||||
163 rw auto
|
||||
165 rw auto quick
|
||||
169 rw auto quick migration
|
||||
162 quick
|
||||
163 rw
|
||||
165 rw quick
|
||||
169 rw quick migration
|
||||
170 rw auto quick
|
||||
171 rw auto quick
|
||||
172 auto
|
||||
|
@ -180,74 +193,74 @@
|
|||
175 auto quick
|
||||
176 rw auto backing
|
||||
177 rw auto quick
|
||||
178 auto
|
||||
178 img
|
||||
179 rw auto quick
|
||||
181 rw auto migration
|
||||
182 rw auto quick
|
||||
183 rw auto migration
|
||||
182 rw quick
|
||||
183 rw migration
|
||||
184 rw auto quick
|
||||
185 rw auto
|
||||
185 rw
|
||||
186 rw auto
|
||||
187 rw auto
|
||||
188 rw auto quick
|
||||
189 rw auto
|
||||
188 rw quick
|
||||
189 rw
|
||||
190 rw auto quick
|
||||
191 rw auto
|
||||
192 rw auto quick
|
||||
194 rw auto migration quick
|
||||
194 rw migration quick
|
||||
195 rw auto quick
|
||||
196 rw auto quick migration
|
||||
196 rw quick migration
|
||||
197 rw auto quick
|
||||
198 rw auto
|
||||
199 rw auto migration
|
||||
200 rw auto
|
||||
198 rw
|
||||
199 rw migration
|
||||
200 rw
|
||||
201 rw auto migration
|
||||
202 rw auto quick
|
||||
203 rw auto migration
|
||||
204 rw auto quick
|
||||
205 rw auto quick
|
||||
206 rw auto
|
||||
202 rw quick
|
||||
203 rw migration
|
||||
204 rw quick
|
||||
205 rw quick
|
||||
206 rw
|
||||
207 rw auto
|
||||
208 rw auto quick
|
||||
209 rw auto quick
|
||||
208 rw quick
|
||||
209 rw quick
|
||||
210 rw auto
|
||||
211 rw auto quick
|
||||
212 rw auto quick
|
||||
213 rw auto quick
|
||||
214 rw auto
|
||||
215 rw auto quick
|
||||
216 rw auto quick
|
||||
216 rw quick
|
||||
217 rw auto quick
|
||||
218 rw auto quick
|
||||
219 rw auto
|
||||
218 rw quick
|
||||
219 rw
|
||||
220 rw auto
|
||||
221 rw auto quick
|
||||
222 rw auto quick
|
||||
223 rw auto quick
|
||||
224 rw auto quick
|
||||
222 rw quick
|
||||
223 rw quick
|
||||
224 rw quick
|
||||
225 rw auto quick
|
||||
226 auto quick
|
||||
227 auto quick
|
||||
228 rw auto quick
|
||||
227 quick
|
||||
228 rw quick
|
||||
229 auto quick
|
||||
231 auto quick
|
||||
232 auto quick
|
||||
232 quick
|
||||
233 auto quick
|
||||
234 auto quick migration
|
||||
235 auto quick
|
||||
236 auto quick
|
||||
234 quick migration
|
||||
235 quick
|
||||
236 quick
|
||||
237 rw auto quick
|
||||
238 auto quick
|
||||
238 quick
|
||||
239 rw auto quick
|
||||
240 auto quick
|
||||
240 quick
|
||||
241 rw auto quick
|
||||
242 rw auto quick
|
||||
242 rw quick
|
||||
243 rw auto quick
|
||||
244 rw auto quick
|
||||
245 rw auto
|
||||
246 rw auto quick
|
||||
247 rw auto quick
|
||||
248 rw auto quick
|
||||
245 rw
|
||||
246 rw quick
|
||||
247 rw quick
|
||||
248 rw quick
|
||||
249 rw auto quick
|
||||
252 rw auto backing quick
|
||||
253 rw auto quick
|
||||
|
|
|
@ -96,6 +96,7 @@ else
|
|||
# build options for bare programs are usually pretty different. They
|
||||
# are expected to provide their own build recipes.
|
||||
-include $(SRC_PATH)/tests/tcg/minilib/Makefile.target
|
||||
-include $(SRC_PATH)/tests/tcg/multiarch/system/Makefile.softmmu-target
|
||||
-include $(SRC_PATH)/tests/tcg/$(TARGET_BASE_ARCH)/Makefile.softmmu-target
|
||||
ifneq ($(TARGET_BASE_ARCH),$(TARGET_NAME))
|
||||
-include $(SRC_PATH)/tests/tcg/$(TARGET_NAME)/Makefile.softmmu-target
|
||||
|
|
34
tests/tcg/aarch64/Makefile.softmmu-target
Normal file
34
tests/tcg/aarch64/Makefile.softmmu-target
Normal file
|
@ -0,0 +1,34 @@
|
|||
#
|
||||
# Aarch64 system tests
|
||||
#
|
||||
|
||||
AARCH64_SYSTEM_SRC=$(SRC_PATH)/tests/tcg/aarch64/system
|
||||
VPATH+=$(AARCH64_SYSTEM_SRC)
|
||||
|
||||
# These objects provide the basic boot code and helper functions for all tests
|
||||
CRT_OBJS=boot.o
|
||||
|
||||
AARCH64_TEST_SRCS=$(wildcard $(AARCH64_SYSTEM_SRC)/*.c)
|
||||
AARCH64_TESTS = $(patsubst $(AARCH64_SYSTEM_SRC)/%.c, %, $(AARCH64_TEST_SRCS))
|
||||
|
||||
CRT_PATH=$(AARCH64_SYSTEM_SRC)
|
||||
LINK_SCRIPT=$(AARCH64_SYSTEM_SRC)/kernel.ld
|
||||
LDFLAGS=-Wl,-T$(LINK_SCRIPT)
|
||||
TESTS+=$(AARCH64_TESTS) $(MULTIARCH_TESTS)
|
||||
CFLAGS+=-nostdlib -ggdb -O0 $(MINILIB_INC)
|
||||
LDFLAGS+=-static -nostdlib $(CRT_OBJS) $(MINILIB_OBJS) -lgcc
|
||||
|
||||
# building head blobs
|
||||
.PRECIOUS: $(CRT_OBJS)
|
||||
|
||||
%.o: $(CRT_PATH)/%.S
|
||||
$(CC) $(CFLAGS) -x assembler-with-cpp -c $< -o $@
|
||||
|
||||
# Build and link the tests
|
||||
%: %.c $(LINK_SCRIPT) $(CRT_OBJS) $(MINILIB_OBJS)
|
||||
$(CC) $(CFLAGS) $< -o $@ $(LDFLAGS)
|
||||
|
||||
memory: CFLAGS+=-DCHECK_UNALIGNED=1
|
||||
|
||||
# Running
|
||||
QEMU_OPTS+=-M virt -cpu max -display none -semihosting-config enable=on,target=native,chardev=output -kernel
|
239
tests/tcg/aarch64/system/boot.S
Normal file
239
tests/tcg/aarch64/system/boot.S
Normal file
|
@ -0,0 +1,239 @@
|
|||
/*
|
||||
* Minimal AArch64 system boot code.
|
||||
*
|
||||
* Copyright Linaro Ltd 2019
|
||||
*
|
||||
* Loosely based on the newlib/libgloss setup stubs. Using semihosting
|
||||
* for serial output and exit functions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Semihosting interface on ARM AArch64
|
||||
* See "Semihosting for AArch32 and AArch64 Relase 2.0" by ARM
|
||||
* w0 - semihosting call number
|
||||
* x1 - semihosting parameter
|
||||
*/
|
||||
#define semihosting_call hlt 0xf000
|
||||
#define SYS_WRITEC 0x03 /* character to debug channel */
|
||||
#define SYS_WRITE0 0x04 /* string to debug channel */
|
||||
#define SYS_EXIT 0x18
|
||||
|
||||
.align 12
|
||||
|
||||
.macro ventry label
|
||||
.align 7
|
||||
b \label
|
||||
.endm
|
||||
|
||||
vector_table:
|
||||
/* Current EL with SP0. */
|
||||
ventry curr_sp0_sync /* Synchronous */
|
||||
ventry curr_sp0_irq /* Irq/vIRQ */
|
||||
ventry curr_sp0_fiq /* Fiq/vFIQ */
|
||||
ventry curr_sp0_serror /* SError/VSError */
|
||||
|
||||
/* Current EL with SPx. */
|
||||
ventry curr_spx_sync /* Synchronous */
|
||||
ventry curr_spx_irq /* IRQ/vIRQ */
|
||||
ventry curr_spx_fiq /* FIQ/vFIQ */
|
||||
ventry curr_spx_serror /* SError/VSError */
|
||||
|
||||
/* Lower EL using AArch64. */
|
||||
ventry lower_a64_sync /* Synchronous */
|
||||
ventry lower_a64_irq /* IRQ/vIRQ */
|
||||
ventry lower_a64_fiq /* FIQ/vFIQ */
|
||||
ventry lower_a64_serror /* SError/VSError */
|
||||
|
||||
/* Lower EL using AArch32. */
|
||||
ventry lower_a32_sync /* Synchronous */
|
||||
ventry lower_a32_irq /* IRQ/vIRQ */
|
||||
ventry lower_a32_fiq /* FIQ/vFIQ */
|
||||
ventry lower_a32_serror /* SError/VSError */
|
||||
|
||||
.text
|
||||
.align 4
|
||||
|
||||
/* Common vector handling for now */
|
||||
curr_sp0_sync:
|
||||
curr_sp0_irq:
|
||||
curr_sp0_fiq:
|
||||
curr_sp0_serror:
|
||||
curr_spx_sync:
|
||||
curr_spx_irq:
|
||||
curr_spx_fiq:
|
||||
curr_spx_serror:
|
||||
lower_a64_sync:
|
||||
lower_a64_irq:
|
||||
lower_a64_fiq:
|
||||
lower_a64_serror:
|
||||
lower_a32_sync:
|
||||
lower_a32_irq:
|
||||
lower_a32_fiq:
|
||||
lower_a32_serror:
|
||||
mov x0, SYS_WRITE0
|
||||
adr x1, .error
|
||||
semihosting_call
|
||||
mov x0, SYS_EXIT
|
||||
mov x1, 1
|
||||
semihosting_call
|
||||
/* never returns */
|
||||
|
||||
.section .rodata
|
||||
.error:
|
||||
.string "Terminated by exception.\n"
|
||||
|
||||
.text
|
||||
.align 4
|
||||
.global __start
|
||||
__start:
|
||||
/* Installs a table of exception vectors to catch and handle all
|
||||
exceptions by terminating the process with a diagnostic. */
|
||||
adr x0, vector_table
|
||||
msr vbar_el1, x0
|
||||
|
||||
/* Page table setup (identity mapping). */
|
||||
adrp x0, ttb
|
||||
add x0, x0, :lo12:ttb
|
||||
msr ttbr0_el1, x0
|
||||
|
||||
/*
|
||||
* Setup a flat address mapping page-tables. Stage one simply
|
||||
* maps RAM to the first Gb. The stage2 tables have two 2mb
|
||||
* translation block entries covering a series of adjacent
|
||||
* 4k pages.
|
||||
*/
|
||||
|
||||
/* Stage 1 entry: indexed by IA[38:30] */
|
||||
adr x1, . /* phys address */
|
||||
bic x1, x1, #(1 << 30) - 1 /* 1GB alignment*/
|
||||
add x2, x0, x1, lsr #(30 - 3) /* offset in l1 page table */
|
||||
|
||||
/* point to stage 2 table [47:12] */
|
||||
adrp x0, ttb_stage2
|
||||
orr x1, x0, #3 /* ptr to stage 2 */
|
||||
str x1, [x2]
|
||||
|
||||
/* Stage 2 entries: indexed by IA[29:21] */
|
||||
ldr x5, =(((1 << 9) - 1) << 21)
|
||||
|
||||
/* First block: .text/RO/execute enabled */
|
||||
adr x1, . /* phys address */
|
||||
bic x1, x1, #(1 << 21) - 1 /* 2mb block alignment */
|
||||
and x4, x1, x5 /* IA[29:21] */
|
||||
add x2, x0, x4, lsr #(21 - 3) /* offset in l2 page table */
|
||||
ldr x3, =0x401 /* attr(AF, block) */
|
||||
orr x1, x1, x3
|
||||
str x1, [x2] /* 1st 2mb (.text & rodata) */
|
||||
|
||||
/* Second block: .data/RW/no execute */
|
||||
adrp x1, .data
|
||||
add x1, x1, :lo12:.data
|
||||
bic x1, x1, #(1 << 21) - 1 /* 2mb block alignment */
|
||||
and x4, x1, x5 /* IA[29:21] */
|
||||
add x2, x0, x4, lsr #(21 - 3) /* offset in l2 page table */
|
||||
ldr x3, =(3 << 53) | 0x401 /* attr(AF, NX, block) */
|
||||
orr x1, x1, x3
|
||||
str x1, [x2] /* 2nd 2mb (.data & .bss)*/
|
||||
|
||||
/* Setup/enable the MMU. */
|
||||
|
||||
/*
|
||||
* TCR_EL1 - Translation Control Registers
|
||||
*
|
||||
* IPS[34:32] = 40-bit PA, 1TB
|
||||
* TG0[14:15] = b00 => 4kb granuale
|
||||
* ORGN0[11:10] = Outer: Normal, WB Read-Alloc No Write-Alloc Cacheable
|
||||
* IRGN0[9:8] = Inner: Normal, WB Read-Alloc No Write-Alloc Cacheable
|
||||
* T0SZ[5:0] = 2^(64 - 25)
|
||||
*
|
||||
* The size of T0SZ controls what the initial lookup level. It
|
||||
* would be nice to start at level 2 but unfortunatly for a
|
||||
* flat-mapping on the virt machine we need to handle IA's
|
||||
* with at least 1gb range to see RAM. So we start with a
|
||||
* level 1 lookup.
|
||||
*/
|
||||
ldr x0, = (2 << 32) | 25 | (3 << 10) | (3 << 8)
|
||||
msr tcr_el1, x0
|
||||
|
||||
mov x0, #0xee /* Inner/outer cacheable WB */
|
||||
msr mair_el1, x0
|
||||
isb
|
||||
|
||||
/*
|
||||
* SCTLR_EL1 - System Control Register
|
||||
*
|
||||
* WXN[19] = 0 = no effect, Write does not imply XN (execute never)
|
||||
* I[12] = Instruction cachability control
|
||||
* SA[3] = SP alignment check
|
||||
* C[2] = Data cachability control
|
||||
* M[0] = 1, enable stage 1 address translation for EL0/1
|
||||
*/
|
||||
mrs x0, sctlr_el1
|
||||
ldr x1, =0x100d /* bits I(12) SA(3) C(2) M(0) */
|
||||
bic x0, x0, #(1 << 1) /* clear bit A(1) */
|
||||
bic x0, x0, #(1 << 19) /* clear WXN */
|
||||
orr x0, x0, x1 /* set bits */
|
||||
|
||||
dsb sy
|
||||
msr sctlr_el1, x0
|
||||
isb
|
||||
|
||||
/*
|
||||
* Enable FP registers. The standard C pre-amble will be
|
||||
* saving these and A-profile compilers will use AdvSIMD
|
||||
* registers unless we tell it not to.
|
||||
*/
|
||||
mrs x0, cpacr_el1
|
||||
orr x0, x0, #(3 << 20)
|
||||
msr cpacr_el1, x0
|
||||
|
||||
/* Setup some stack space and enter the test code.
|
||||
* Assume everthing except the return value is garbage when we
|
||||
* return, we won't need it.
|
||||
*/
|
||||
adrp x0, stack_end
|
||||
add x0, x0, :lo12:stack_end
|
||||
mov sp, x0
|
||||
bl main
|
||||
|
||||
/* pass return value to sys exit */
|
||||
mov x1, x0
|
||||
ldr x0, =0x20026 /* ADP_Stopped_ApplicationExit */
|
||||
stp x0, x1, [sp, #-16]!
|
||||
mov x1, sp
|
||||
mov x0, SYS_EXIT
|
||||
semihosting_call
|
||||
/* never returns */
|
||||
|
||||
/*
|
||||
* Helper Functions
|
||||
*/
|
||||
|
||||
/* Output a single character to serial port */
|
||||
.global __sys_outc
|
||||
__sys_outc:
|
||||
stp x0, x1, [sp, #-16]!
|
||||
/* pass address of c on stack */
|
||||
mov x1, sp
|
||||
mov x0, SYS_WRITEC
|
||||
semihosting_call
|
||||
ldp x0, x1, [sp], #16
|
||||
ret
|
||||
|
||||
.data
|
||||
.align 12
|
||||
|
||||
/* Translation table
|
||||
* @4k granuale: 9 bit lookup, 512 entries
|
||||
*/
|
||||
ttb:
|
||||
.space 4096, 0
|
||||
|
||||
.align 12
|
||||
ttb_stage2:
|
||||
.space 4096, 0
|
||||
|
||||
.align 12
|
||||
stack:
|
||||
.space 65536, 0
|
||||
stack_end:
|
24
tests/tcg/aarch64/system/kernel.ld
Normal file
24
tests/tcg/aarch64/system/kernel.ld
Normal file
|
@ -0,0 +1,24 @@
|
|||
ENTRY(__start)
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
/* virt machine, RAM starts at 1gb */
|
||||
. = (1 << 30);
|
||||
.text : {
|
||||
*(.text)
|
||||
}
|
||||
.rodata : {
|
||||
*(.rodata)
|
||||
}
|
||||
/* align r/w section to next 2mb */
|
||||
. = ALIGN(1 << 21);
|
||||
.data : {
|
||||
*(.data)
|
||||
}
|
||||
.bss : {
|
||||
*(.bss)
|
||||
}
|
||||
/DISCARD/ : {
|
||||
*(.ARM.attributes)
|
||||
}
|
||||
}
|
34
tests/tcg/alpha/Makefile.softmmu-target
Normal file
34
tests/tcg/alpha/Makefile.softmmu-target
Normal file
|
@ -0,0 +1,34 @@
|
|||
#
|
||||
# Alpha system tests
|
||||
#
|
||||
|
||||
ALPHA_SYSTEM_SRC=$(SRC_PATH)/tests/tcg/alpha/system
|
||||
VPATH+=$(ALPHA_SYSTEM_SRC)
|
||||
|
||||
# These objects provide the basic boot code and helper functions for all tests
|
||||
CRT_OBJS=boot.o
|
||||
|
||||
ALPHA_TEST_SRCS=$(wildcard $(ALPHA_SYSTEM_SRC)/*.c)
|
||||
ALPHA_TESTS = $(patsubst $(ALPHA_SYSTEM_SRC)/%.c, %, $(ALPHA_TEST_SRCS))
|
||||
|
||||
CRT_PATH=$(ALPHA_SYSTEM_SRC)
|
||||
LINK_SCRIPT=$(ALPHA_SYSTEM_SRC)/kernel.ld
|
||||
LDFLAGS=-Wl,-T$(LINK_SCRIPT)
|
||||
TESTS+=$(ALPHA_TESTS) $(MULTIARCH_TESTS)
|
||||
CFLAGS+=-nostdlib -g -O1 -mcpu=ev6 $(MINILIB_INC)
|
||||
LDFLAGS+=-static -nostdlib $(CRT_OBJS) $(MINILIB_OBJS) -lgcc
|
||||
|
||||
# building head blobs
|
||||
.PRECIOUS: $(CRT_OBJS)
|
||||
|
||||
%.o: $(CRT_PATH)/%.S
|
||||
$(CC) $(CFLAGS) -x assembler-with-cpp -c $< -o $@
|
||||
|
||||
# Build and link the tests
|
||||
%: %.c $(LINK_SCRIPT) $(CRT_OBJS) $(MINILIB_OBJS)
|
||||
$(CC) $(CFLAGS) $< -o $@ $(LDFLAGS)
|
||||
|
||||
memory: CFLAGS+=-DCHECK_UNALIGNED=0
|
||||
|
||||
# Running
|
||||
QEMU_OPTS+=-serial chardev:output -kernel
|
511
tests/tcg/alpha/system/boot.S
Normal file
511
tests/tcg/alpha/system/boot.S
Normal file
|
@ -0,0 +1,511 @@
|
|||
/*
|
||||
* Minimal Alpha system boot code.
|
||||
*
|
||||
* Copyright Linaro Ltd 2019
|
||||
*/
|
||||
|
||||
.set noat
|
||||
.set nomacro
|
||||
.arch ev6
|
||||
.text
|
||||
|
||||
.macro load_pci_io reg
|
||||
/* For typhoon, this is
|
||||
* 0xfffffc0000000000 -- kseg identity map
|
||||
* + 0x10000000000 -- typhoon pio base
|
||||
* + 0x1fc000000 -- typhoon pchip0 pci base
|
||||
* = 0xfffffd01fc000000
|
||||
*/
|
||||
ldah \reg, -3 /* ff..fd0000 */
|
||||
lda \reg, 0x1fc(\reg) /* ff..fd01fc */
|
||||
sll \reg, 24, \reg
|
||||
.endm
|
||||
|
||||
#define com1Rbr 0x3f8
|
||||
#define com1Thr 0x3f8
|
||||
#define com1Ier 0x3f9
|
||||
#define com1Iir 0x3fa
|
||||
#define com1Lcr 0x3fb
|
||||
#define com1Mcr 0x3fc
|
||||
#define com1Lsr 0x3fd
|
||||
#define com1Msr 0x3fe
|
||||
#define com1Scr 0x3ff
|
||||
#define com1Dll 0x3f8
|
||||
#define com1Dlm 0x3f9
|
||||
|
||||
#define PAL_halt 0
|
||||
#define PAL_wrent 52
|
||||
#define PAL_wrkgp 55
|
||||
|
||||
.text
|
||||
.p2align 4
|
||||
.globl _start
|
||||
.ent _start
|
||||
_start:
|
||||
br $gp, .+4
|
||||
ldah $gp, 0($gp) !gpdisp!1
|
||||
lda $gp, 0($gp) !gpdisp!1
|
||||
|
||||
ldah $sp, $stack_end($gp) !gprelhigh
|
||||
lda $sp, $stack_end($sp) !gprellow
|
||||
|
||||
/* Install kernel gp for exception handlers. */
|
||||
mov $gp, $16
|
||||
call_pal PAL_wrkgp
|
||||
|
||||
/* Install exception handlers. */
|
||||
ldah $16, entInt($gp) !gprelhigh
|
||||
lda $16, entInt($16) !gprellow
|
||||
lda $17, 0
|
||||
call_pal PAL_wrent
|
||||
|
||||
ldah $16, entArith($gp) !gprelhigh
|
||||
lda $16, entArith($16) !gprellow
|
||||
lda $17, 1
|
||||
call_pal PAL_wrent
|
||||
|
||||
ldah $16, entMM($gp) !gprelhigh
|
||||
lda $16, entMM($16) !gprellow
|
||||
lda $17, 2
|
||||
call_pal PAL_wrent
|
||||
|
||||
ldah $16, entIF($gp) !gprelhigh
|
||||
lda $16, entIF($16) !gprellow
|
||||
lda $17, 3
|
||||
call_pal PAL_wrent
|
||||
|
||||
ldah $16, entUna($gp) !gprelhigh
|
||||
lda $16, entUna($16) !gprellow
|
||||
lda $17, 4
|
||||
call_pal PAL_wrent
|
||||
|
||||
ldah $16, entSys($gp) !gprelhigh
|
||||
lda $16, entSys($16) !gprellow
|
||||
lda $17, 5
|
||||
call_pal PAL_wrent
|
||||
|
||||
/*
|
||||
* Initialize COM1.
|
||||
*/
|
||||
load_pci_io $1
|
||||
lda $2, 0x87 /* outb(0x87, com1Lcr); */
|
||||
stb $2, com1Lcr($1)
|
||||
stb $31, com1Dlm($1) /* outb(0, com1Dlm); */
|
||||
lda $2, 3 /* baudconst 3 => 56000 */
|
||||
stb $2, com1Dll($1) /* outb(baudconst, com1Dll); */
|
||||
lda $2, 0x07
|
||||
stb $2, com1Lcr($1) /* outb(0x07, com1Lcr) */
|
||||
lda $2, 0x0f
|
||||
stb $2, com1Mcr($1) /* outb(0x0f, com1Mcr) */
|
||||
|
||||
bsr $26, main !samegp
|
||||
|
||||
/* fall through to _exit */
|
||||
.end _start
|
||||
|
||||
.globl _exit
|
||||
.ent _exit
|
||||
_exit:
|
||||
.frame $sp, 0, $26, 0
|
||||
.prologue 0
|
||||
|
||||
/* We cannot return an error code. */
|
||||
call_pal PAL_halt
|
||||
.end _exit
|
||||
|
||||
/*
|
||||
* We have received an exception that we don't handle. Log and exit.
|
||||
*/
|
||||
.ent log_exit
|
||||
log_exit:
|
||||
entInt:
|
||||
entArith:
|
||||
entMM:
|
||||
entIF:
|
||||
entUna:
|
||||
entSys:
|
||||
ldah $16, $errormsg($gp) !gprelhigh
|
||||
lda $16, $errormsg($16) !gprellow
|
||||
bsr $26, __sys_outs !samegp
|
||||
bsr $26, _exit !samegp
|
||||
.end log_exit
|
||||
|
||||
.section .rodata
|
||||
$errormsg:
|
||||
.string "Terminated by exception.\n"
|
||||
.previous
|
||||
|
||||
/*
|
||||
* Helper Functions
|
||||
*/
|
||||
|
||||
/* Output a single character to serial port */
|
||||
.global __sys_outc
|
||||
.ent __sys_outc
|
||||
__sys_outc:
|
||||
.frame $sp, 0, $26, 0
|
||||
.prologue 0
|
||||
|
||||
load_pci_io $1
|
||||
|
||||
/*
|
||||
* while ((inb(com1Lsr) & 0x20) == 0)
|
||||
* continue;
|
||||
*/
|
||||
1: ldbu $0, com1Lsr($1)
|
||||
and $0, 0x20, $0
|
||||
beq $0, 1b
|
||||
|
||||
/* outb(c, com1Thr); */
|
||||
stb $16, com1Thr($1)
|
||||
ret
|
||||
.end __sys_outc
|
||||
|
||||
/* Output a nul-terminated string to serial port */
|
||||
.global __sys_outs
|
||||
.ent __sys_outs
|
||||
__sys_outs:
|
||||
.frame $sp, 0, $26, 0
|
||||
.prologue 0
|
||||
|
||||
load_pci_io $1
|
||||
|
||||
ldbu $2, 0($16)
|
||||
beq $2, 9f
|
||||
|
||||
/*
|
||||
* while ((inb(com1Lsr) & 0x20) == 0)
|
||||
* continue;
|
||||
*/
|
||||
1: ldbu $0, com1Lsr($1)
|
||||
and $0, 0x20, $0
|
||||
beq $0, 1b
|
||||
|
||||
/* outb(c, com1Thr); */
|
||||
stb $2, com1Thr($1)
|
||||
|
||||
addq $16, 1, $16
|
||||
ldbu $2, 0($16)
|
||||
bne $2, 1b
|
||||
|
||||
9: ret
|
||||
.end __sys_outs
|
||||
|
||||
/*
|
||||
* Division routines that are normally in libc.
|
||||
*
|
||||
* These do not follow the C calling convention. Arguments are in $24+$25,
|
||||
* the result is in $27. Register $28 may be clobbered; everything else
|
||||
* must be saved.
|
||||
*
|
||||
* We store the remainder in $28, so that we can share code.
|
||||
*
|
||||
* We do not signal divide by zero.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Unsigned 64-bit division.
|
||||
*/
|
||||
|
||||
.globl __divqu
|
||||
.ent __divqu
|
||||
__divqu:
|
||||
.frame $sp, 48, $23
|
||||
subq $sp, 48, $sp
|
||||
stq $0, 0($sp)
|
||||
stq $1, 8($sp)
|
||||
stq $2, 16($sp)
|
||||
stq $3, 24($sp)
|
||||
stq $4, 32($sp)
|
||||
.prologue 0
|
||||
|
||||
#define mask $0
|
||||
#define divisor $1
|
||||
#define compare $2
|
||||
#define tmp1 $3
|
||||
#define tmp2 $4
|
||||
#define quotient $27
|
||||
#define modulus $28
|
||||
|
||||
mov $24, modulus
|
||||
mov $25, divisor
|
||||
mov $31, quotient
|
||||
mov 1, mask
|
||||
beq $25, 9f
|
||||
|
||||
/* Shift left until divisor >= modulus. */
|
||||
1: cmpult divisor, modulus, compare
|
||||
blt divisor, 2f
|
||||
addq divisor, divisor, divisor
|
||||
addq mask, mask, mask
|
||||
bne compare, 1b
|
||||
|
||||
2: addq quotient, mask, tmp2
|
||||
srl mask, 1, mask
|
||||
cmpule divisor, modulus, compare
|
||||
subq modulus, divisor, tmp1
|
||||
cmovne compare, tmp2, quotient
|
||||
srl divisor, 1, divisor
|
||||
cmovne compare, tmp1, modulus
|
||||
bne mask, 2b
|
||||
|
||||
9: ldq $0, 0($sp)
|
||||
ldq $1, 8($sp)
|
||||
ldq $2, 16($sp)
|
||||
ldq $3, 24($sp)
|
||||
ldq $4, 32($sp)
|
||||
addq $sp, 48, $sp
|
||||
ret $31, ($23), 1
|
||||
|
||||
#undef mask
|
||||
#undef divisor
|
||||
#undef compare
|
||||
#undef tmp1
|
||||
#undef tmp2
|
||||
#undef quotient
|
||||
#undef modulus
|
||||
|
||||
.end __divqu
|
||||
|
||||
/*
|
||||
* Unsigned 64-bit remainder.
|
||||
* Note that __divqu above leaves the result in $28.
|
||||
*/
|
||||
|
||||
.globl __remqu
|
||||
.ent __remqu
|
||||
__remqu:
|
||||
.frame $sp, 16, $23
|
||||
subq $sp, 16, $sp
|
||||
stq $23, 0($sp)
|
||||
.prologue 0
|
||||
|
||||
bsr $23, __divqu
|
||||
|
||||
ldq $23, 0($sp)
|
||||
mov $28, $27
|
||||
addq $sp, 16, $sp
|
||||
ret $31, ($23), 1
|
||||
.end __remqu
|
||||
|
||||
/*
|
||||
* Signed 64-bit division.
|
||||
*/
|
||||
|
||||
.globl __divqs
|
||||
.ent __divqs
|
||||
__divqs:
|
||||
.prologue 0
|
||||
|
||||
/* Common case: both arguments are positive. */
|
||||
bis $24, $25, $28
|
||||
bge $28, __divqu
|
||||
|
||||
/* At least one argument is negative. */
|
||||
subq $sp, 32, $sp
|
||||
stq $23, 0($sp)
|
||||
stq $24, 8($sp)
|
||||
stq $25, 16($sp)
|
||||
|
||||
/* Compute absolute values. */
|
||||
subq $31, $24, $28
|
||||
cmovlt $24, $28, $24
|
||||
subq $31, $25, $28
|
||||
cmovlt $25, $28, $25
|
||||
|
||||
bsr $23, __divqu
|
||||
|
||||
ldq $24, 8($sp)
|
||||
ldq $25, 16($sp)
|
||||
|
||||
/* -a / b = a / -b = -(a / b) */
|
||||
subq $31, $27, $23
|
||||
xor $24, $25, $28
|
||||
cmovlt $28, $23, $27
|
||||
|
||||
ldq $23, 0($sp)
|
||||
addq $sp, 32, $sp
|
||||
ret $31, ($23), 1
|
||||
.end __divqs
|
||||
|
||||
/*
|
||||
* Signed 64-bit remainder.
|
||||
*/
|
||||
|
||||
.globl __remqs
|
||||
.ent __remqs
|
||||
__remqs:
|
||||
.prologue 0
|
||||
|
||||
/* Common case: both arguments are positive. */
|
||||
bis $24, $25, $28
|
||||
bge $28, __remqu
|
||||
|
||||
/* At least one argument is negative. */
|
||||
subq $sp, 32, $sp
|
||||
stq $23, 0($sp)
|
||||
stq $24, 8($sp)
|
||||
stq $25, 16($sp)
|
||||
|
||||
/* Compute absolute values. */
|
||||
subq $31, $24, $28
|
||||
cmovlt $24, $28, $24
|
||||
subq $31, $25, $28
|
||||
cmovlt $25, $28, $25
|
||||
|
||||
bsr $23, __divqu
|
||||
|
||||
ldq $23, 0($sp)
|
||||
ldq $24, 8($sp)
|
||||
ldq $25, 16($sp)
|
||||
|
||||
/* -a % b = -(a % b); a % -b = a % b. */
|
||||
subq $31, $28, $27
|
||||
cmovge $24, $28, $27
|
||||
|
||||
addq $sp, 32, $sp
|
||||
ret $31, ($23), 1
|
||||
.end __remqs
|
||||
|
||||
/*
|
||||
* Unsigned 32-bit division.
|
||||
*/
|
||||
|
||||
.globl __divlu
|
||||
.ent __divlu
|
||||
__divlu:
|
||||
.frame $sp, 32, $23
|
||||
subq $sp, 32, $sp
|
||||
stq $23, 0($sp)
|
||||
stq $24, 8($sp)
|
||||
stq $25, 16($sp)
|
||||
.prologue 0
|
||||
|
||||
/* Zero extend and use the 64-bit routine. */
|
||||
zap $24, 0xf0, $24
|
||||
zap $25, 0xf0, $25
|
||||
bsr $23, __divqu
|
||||
|
||||
addl $27, 0, $27
|
||||
ldq $23, 0($sp)
|
||||
ldq $24, 8($sp)
|
||||
ldq $25, 16($sp)
|
||||
addq $sp, 32, $sp
|
||||
ret $31, ($23), 1
|
||||
.end __divlu
|
||||
|
||||
/*
|
||||
* Unsigned 32-bit remainder.
|
||||
*/
|
||||
|
||||
.globl __remlu
|
||||
.ent __remlu
|
||||
__remlu:
|
||||
.frame $sp, 32, $23
|
||||
subq $sp, 32, $sp
|
||||
stq $23, 0($sp)
|
||||
stq $24, 8($sp)
|
||||
stq $25, 16($sp)
|
||||
.prologue 0
|
||||
|
||||
/* Zero extend and use the 64-bit routine. */
|
||||
zap $24, 0xf0, $24
|
||||
zap $25, 0xf0, $25
|
||||
bsr $23, __divqu
|
||||
|
||||
/* Recall that the remainder is returned in $28. */
|
||||
addl $28, 0, $27
|
||||
ldq $23, 0($sp)
|
||||
ldq $24, 8($sp)
|
||||
ldq $25, 16($sp)
|
||||
addq $sp, 32, $sp
|
||||
ret $31, ($23), 1
|
||||
.end __remlu
|
||||
|
||||
/*
|
||||
* Signed 32-bit division.
|
||||
*/
|
||||
|
||||
.globl __divls
|
||||
.ent __divls
|
||||
__divls:
|
||||
.frame $sp, 32, $23
|
||||
subq $sp, 32, $sp
|
||||
stq $23, 0($sp)
|
||||
stq $24, 8($sp)
|
||||
stq $25, 16($sp)
|
||||
.prologue 0
|
||||
|
||||
/* Sign extend. */
|
||||
addl $24, 0, $24
|
||||
addl $25, 0, $25
|
||||
|
||||
/* Compute absolute values. */
|
||||
subq $31, $24, $28
|
||||
cmovlt $24, $28, $24
|
||||
subq $31, $25, $28
|
||||
cmovlt $25, $28, $25
|
||||
|
||||
bsr $23, __divqu
|
||||
|
||||
ldq $24, 8($sp)
|
||||
ldq $25, 16($sp)
|
||||
|
||||
/* Negate the unsigned result, if necessary. */
|
||||
xor $24, $25, $28
|
||||
subl $31, $27, $23
|
||||
addl $27, 0, $27
|
||||
addl $28, 0, $28
|
||||
cmovlt $28, $23, $27
|
||||
|
||||
ldq $23, 0($sp)
|
||||
addq $sp, 32, $sp
|
||||
ret $31, ($23), 1
|
||||
.end __divls
|
||||
|
||||
/*
|
||||
* Signed 32-bit remainder.
|
||||
*/
|
||||
|
||||
.globl __remls
|
||||
.ent __remls
|
||||
__remls:
|
||||
.frame $sp, 32, $23
|
||||
subq $sp, 32, $sp
|
||||
stq $23, 0($sp)
|
||||
stq $24, 8($sp)
|
||||
stq $25, 16($sp)
|
||||
.prologue 0
|
||||
|
||||
/* Sign extend. */
|
||||
addl $24, 0, $24
|
||||
addl $25, 0, $25
|
||||
|
||||
/* Compute absolute values. */
|
||||
subq $31, $24, $28
|
||||
cmovlt $24, $28, $24
|
||||
subq $31, $25, $28
|
||||
cmovlt $25, $28, $25
|
||||
|
||||
bsr $23, __divqu
|
||||
|
||||
ldq $23, 0($sp)
|
||||
ldq $24, 8($sp)
|
||||
ldq $25, 16($sp)
|
||||
|
||||
/* Negate the unsigned result, if necessary. */
|
||||
subl $31, $28, $27
|
||||
addl $28, 0, $28
|
||||
cmovge $24, $28, $27
|
||||
|
||||
addq $sp, 32, $sp
|
||||
ret $31, ($23), 1
|
||||
.end __remls
|
||||
|
||||
.data
|
||||
.p2align 4
|
||||
stack:
|
||||
.skip 65536
|
||||
$stack_end:
|
||||
.type stack,@object
|
||||
.size stack, . - stack
|
30
tests/tcg/alpha/system/kernel.ld
Normal file
30
tests/tcg/alpha/system/kernel.ld
Normal file
|
@ -0,0 +1,30 @@
|
|||
ENTRY(_start)
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
/* Linux kernel legacy start address. */
|
||||
. = 0xfffffc0000310000;
|
||||
_text = .;
|
||||
.text : {
|
||||
*(.text)
|
||||
}
|
||||
.rodata : {
|
||||
*(.rodata)
|
||||
}
|
||||
_etext = .;
|
||||
|
||||
. = ALIGN(8192);
|
||||
_data = .;
|
||||
.got : {
|
||||
*(.got)
|
||||
}
|
||||
.data : {
|
||||
*(.sdata)
|
||||
*(.data)
|
||||
}
|
||||
_edata = .;
|
||||
.bss : {
|
||||
*(.bss)
|
||||
}
|
||||
_end = .;
|
||||
}
|
|
@ -27,7 +27,7 @@ CFLAGS+=-m32
|
|||
LINK_SCRIPT=$(I386_SYSTEM_SRC)/kernel.ld
|
||||
LDFLAGS=-Wl,-T$(LINK_SCRIPT) -Wl,-melf_i386
|
||||
# FIXME: move to common once x86_64 is bootstrapped
|
||||
TESTS+=$(X86_TESTS)
|
||||
TESTS+=$(X86_TESTS) $(MULTIARCH_TESTS)
|
||||
endif
|
||||
CFLAGS+=-nostdlib -ggdb -O0 $(MINILIB_INC)
|
||||
LDFLAGS+=-static -nostdlib $(CRT_OBJS) $(MINILIB_OBJS) -lgcc
|
||||
|
@ -42,5 +42,7 @@ LDFLAGS+=-static -nostdlib $(CRT_OBJS) $(MINILIB_OBJS) -lgcc
|
|||
%: %.c $(LINK_SCRIPT) $(CRT_OBJS) $(MINILIB_OBJS)
|
||||
$(CC) $(CFLAGS) $< -o $@ $(LDFLAGS)
|
||||
|
||||
memory: CFLAGS+=-DCHECK_UNALIGNED=1
|
||||
|
||||
# Running
|
||||
QEMU_OPTS+=-device isa-debugcon,chardev=output -device isa-debug-exit,iobase=0xf4,iosize=0x4 -kernel
|
||||
|
|
|
@ -1,243 +0,0 @@
|
|||
/*
|
||||
* Memory Test
|
||||
*
|
||||
* This is intended to test the softmmu code and ensure we properly
|
||||
* behave across normal and unaligned accesses across several pages.
|
||||
* We are not replicating memory tests for stuck bits and other
|
||||
* hardware level failures but looking for issues with different size
|
||||
* accesses when:
|
||||
|
||||
*
|
||||
*/
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <minilib.h>
|
||||
|
||||
#define TEST_SIZE (4096 * 4) /* 4 pages */
|
||||
|
||||
static uint8_t test_data[TEST_SIZE];
|
||||
|
||||
static void pdot(int count)
|
||||
{
|
||||
if (count % 128 == 0) {
|
||||
ml_printf(".");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Fill the data with ascending value bytes. As x86 is a LE machine we
|
||||
* write in ascending order and then read and high byte should either
|
||||
* be zero or higher than the lower bytes.
|
||||
*/
|
||||
|
||||
static void init_test_data_u8(void)
|
||||
{
|
||||
uint8_t count = 0, *ptr = &test_data[0];
|
||||
int i;
|
||||
|
||||
ml_printf("Filling test area with u8:");
|
||||
for (i = 0; i < TEST_SIZE; i++) {
|
||||
*ptr++ = count++;
|
||||
pdot(i);
|
||||
}
|
||||
ml_printf("done\n");
|
||||
}
|
||||
|
||||
static void init_test_data_u16(int offset)
|
||||
{
|
||||
uint8_t count = 0;
|
||||
uint16_t word, *ptr = (uint16_t *) &test_data[0];
|
||||
const int max = (TEST_SIZE - offset) / sizeof(word);
|
||||
int i;
|
||||
|
||||
ml_printf("Filling test area with u16 (offset %d):", offset);
|
||||
|
||||
/* Leading zeros */
|
||||
for (i = 0; i < offset; i++) {
|
||||
*ptr = 0;
|
||||
}
|
||||
|
||||
ptr = (uint16_t *) &test_data[offset];
|
||||
for (i = 0; i < max; i++) {
|
||||
uint8_t high, low;
|
||||
low = count++;
|
||||
high = count++;
|
||||
word = (high << 8) | low;
|
||||
*ptr++ = word;
|
||||
pdot(i);
|
||||
}
|
||||
ml_printf("done\n");
|
||||
}
|
||||
|
||||
static void init_test_data_u32(int offset)
|
||||
{
|
||||
uint8_t count = 0;
|
||||
uint32_t word, *ptr = (uint32_t *) &test_data[0];
|
||||
const int max = (TEST_SIZE - offset) / sizeof(word);
|
||||
int i;
|
||||
|
||||
ml_printf("Filling test area with u32 (offset %d):", offset);
|
||||
|
||||
/* Leading zeros */
|
||||
for (i = 0; i < offset; i++) {
|
||||
*ptr = 0;
|
||||
}
|
||||
|
||||
ptr = (uint32_t *) &test_data[offset];
|
||||
for (i = 0; i < max; i++) {
|
||||
uint8_t b1, b2, b3, b4;
|
||||
b4 = count++;
|
||||
b3 = count++;
|
||||
b2 = count++;
|
||||
b1 = count++;
|
||||
word = (b1 << 24) | (b2 << 16) | (b3 << 8) | b4;
|
||||
*ptr++ = word;
|
||||
pdot(i);
|
||||
}
|
||||
ml_printf("done\n");
|
||||
}
|
||||
|
||||
|
||||
static int read_test_data_u16(int offset)
|
||||
{
|
||||
uint16_t word, *ptr = (uint16_t *)&test_data[offset];
|
||||
int i;
|
||||
const int max = (TEST_SIZE - offset) / sizeof(word);
|
||||
|
||||
ml_printf("Reading u16 from %#lx (offset %d):", ptr, offset);
|
||||
|
||||
for (i = 0; i < max; i++) {
|
||||
uint8_t high, low;
|
||||
word = *ptr++;
|
||||
high = (word >> 8) & 0xff;
|
||||
low = word & 0xff;
|
||||
if (high < low && high != 0) {
|
||||
ml_printf("Error %d < %d\n", high, low);
|
||||
return 1;
|
||||
} else {
|
||||
pdot(i);
|
||||
}
|
||||
|
||||
}
|
||||
ml_printf("done\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int read_test_data_u32(int offset)
|
||||
{
|
||||
uint32_t word, *ptr = (uint32_t *)&test_data[offset];
|
||||
int i;
|
||||
const int max = (TEST_SIZE - offset) / sizeof(word);
|
||||
|
||||
ml_printf("Reading u32 from %#lx (offset %d):", ptr, offset);
|
||||
|
||||
for (i = 0; i < max; i++) {
|
||||
uint8_t b1, b2, b3, b4;
|
||||
word = *ptr++;
|
||||
|
||||
b1 = word >> 24 & 0xff;
|
||||
b2 = word >> 16 & 0xff;
|
||||
b3 = word >> 8 & 0xff;
|
||||
b4 = word & 0xff;
|
||||
|
||||
if ((b1 < b2 && b1 != 0) ||
|
||||
(b2 < b3 && b2 != 0) ||
|
||||
(b3 < b4 && b3 != 0)) {
|
||||
ml_printf("Error %d, %d, %d, %d", b1, b2, b3, b4);
|
||||
return 2;
|
||||
} else {
|
||||
pdot(i);
|
||||
}
|
||||
}
|
||||
ml_printf("done\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int read_test_data_u64(int offset)
|
||||
{
|
||||
uint64_t word, *ptr = (uint64_t *)&test_data[offset];
|
||||
int i;
|
||||
const int max = (TEST_SIZE - offset) / sizeof(word);
|
||||
|
||||
ml_printf("Reading u64 from %#lx (offset %d):", ptr, offset);
|
||||
|
||||
for (i = 0; i < max; i++) {
|
||||
uint8_t b1, b2, b3, b4, b5, b6, b7, b8;
|
||||
word = *ptr++;
|
||||
|
||||
b1 = ((uint64_t) (word >> 56)) & 0xff;
|
||||
b2 = ((uint64_t) (word >> 48)) & 0xff;
|
||||
b3 = ((uint64_t) (word >> 40)) & 0xff;
|
||||
b4 = (word >> 32) & 0xff;
|
||||
b5 = (word >> 24) & 0xff;
|
||||
b6 = (word >> 16) & 0xff;
|
||||
b7 = (word >> 8) & 0xff;
|
||||
b8 = (word >> 0) & 0xff;
|
||||
|
||||
if ((b1 < b2 && b1 != 0) ||
|
||||
(b2 < b3 && b2 != 0) ||
|
||||
(b3 < b4 && b3 != 0) ||
|
||||
(b4 < b5 && b4 != 0) ||
|
||||
(b5 < b6 && b5 != 0) ||
|
||||
(b6 < b7 && b6 != 0) ||
|
||||
(b7 < b8 && b7 != 0)) {
|
||||
ml_printf("Error %d, %d, %d, %d, %d, %d, %d, %d",
|
||||
b1, b2, b3, b4, b5, b6, b7, b8);
|
||||
return 2;
|
||||
} else {
|
||||
pdot(i);
|
||||
}
|
||||
}
|
||||
ml_printf("done\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Read the test data and verify at various offsets */
|
||||
int do_reads(void)
|
||||
{
|
||||
int r = 0;
|
||||
int off = 0;
|
||||
|
||||
while (r == 0 && off < 8) {
|
||||
r = read_test_data_u16(off);
|
||||
r |= read_test_data_u32(off);
|
||||
r |= read_test_data_u64(off);
|
||||
off++;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int i, r = 0;
|
||||
|
||||
|
||||
init_test_data_u8();
|
||||
r = do_reads();
|
||||
if (r) {
|
||||
return r;
|
||||
}
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
init_test_data_u16(i);
|
||||
|
||||
r = do_reads();
|
||||
if (r) {
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
init_test_data_u32(i);
|
||||
|
||||
r = do_reads();
|
||||
if (r) {
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
ml_printf("Test complete: %s\n", r == 0 ? "PASSED" : "FAILED");
|
||||
return r;
|
||||
}
|
|
@ -119,6 +119,9 @@ void ml_printf(const char *fmt, ...)
|
|||
str = va_arg(ap, char*);
|
||||
print_str(str);
|
||||
break;
|
||||
case 'c':
|
||||
__sys_outc(va_arg(ap, int));
|
||||
break;
|
||||
case '%':
|
||||
__sys_outc(*fmt);
|
||||
break;
|
||||
|
|
14
tests/tcg/multiarch/system/Makefile.softmmu-target
Normal file
14
tests/tcg/multiarch/system/Makefile.softmmu-target
Normal file
|
@ -0,0 +1,14 @@
|
|||
# -*- Mode: makefile -*-
|
||||
#
|
||||
# Multiarch system tests
|
||||
#
|
||||
# We just collect the tests together here and rely on the actual guest
|
||||
# architecture to add to the test dependancies and deal with the
|
||||
# complications of building.
|
||||
#
|
||||
|
||||
MULTIARCH_SYSTEM_SRC=$(SRC_PATH)/tests/tcg/multiarch/system
|
||||
VPATH+=$(MULTIARCH_SYSTEM_SRC)
|
||||
|
||||
MULTIARCH_TEST_SRCS=$(wildcard $(MULTIARCH_SYSTEM_SRC)/*.c)
|
||||
MULTIARCH_TESTS = $(patsubst $(MULTIARCH_SYSTEM_SRC)/%.c, %, $(MULTIARCH_TEST_SRCS))
|
449
tests/tcg/multiarch/system/memory.c
Normal file
449
tests/tcg/multiarch/system/memory.c
Normal file
|
@ -0,0 +1,449 @@
|
|||
/*
|
||||
* Memory Test
|
||||
*
|
||||
* This is intended to test the softmmu code and ensure we properly
|
||||
* behave across normal and unaligned accesses across several pages.
|
||||
* We are not replicating memory tests for stuck bits and other
|
||||
* hardware level failures but looking for issues with different size
|
||||
* accesses when access is:
|
||||
*
|
||||
* - unaligned at various sizes (if -DCHECK_UNALIGNED set)
|
||||
* - spanning a (softmmu) page
|
||||
* - sign extension when loading
|
||||
*/
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stdbool.h>
|
||||
#include <minilib.h>
|
||||
|
||||
#ifndef CHECK_UNALIGNED
|
||||
# error "Target does not specify CHECK_UNALIGNED"
|
||||
#endif
|
||||
|
||||
#define PAGE_SIZE 4096 /* nominal 4k "pages" */
|
||||
#define TEST_SIZE (PAGE_SIZE * 4) /* 4 pages */
|
||||
|
||||
#define ARRAY_SIZE(x) ((sizeof(x) / sizeof((x)[0])))
|
||||
|
||||
__attribute__((aligned(PAGE_SIZE)))
|
||||
static uint8_t test_data[TEST_SIZE];
|
||||
|
||||
typedef void (*init_ufn) (int offset);
|
||||
typedef bool (*read_ufn) (int offset);
|
||||
typedef bool (*read_sfn) (int offset, bool nf);
|
||||
|
||||
static void pdot(int count)
|
||||
{
|
||||
if (count % 128 == 0) {
|
||||
ml_printf(".");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Helper macros for shift/extract so we can keep our endian handling
|
||||
* in one place.
|
||||
*/
|
||||
#define BYTE_SHIFT(b, pos) ((uint64_t)b << (pos * 8))
|
||||
#define BYTE_EXTRACT(b, pos) ((b >> (pos * 8)) & 0xff)
|
||||
|
||||
/*
|
||||
* Fill the data with ascending value bytes.
|
||||
*
|
||||
* Currently we only support Little Endian machines so write in
|
||||
* ascending address order. When we read higher address bytes should
|
||||
* either be zero or higher than the lower bytes.
|
||||
*/
|
||||
|
||||
static void init_test_data_u8(int unused_offset)
|
||||
{
|
||||
uint8_t count = 0, *ptr = &test_data[0];
|
||||
int i;
|
||||
(void)(unused_offset);
|
||||
|
||||
ml_printf("Filling test area with u8:");
|
||||
for (i = 0; i < TEST_SIZE; i++) {
|
||||
*ptr++ = count++;
|
||||
pdot(i);
|
||||
}
|
||||
ml_printf("done\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* Full the data with alternating positive and negative bytes. This
|
||||
* should mean for reads larger than a byte all subsequent reads will
|
||||
* stay either negative or positive. We never write 0.
|
||||
*/
|
||||
|
||||
static inline uint8_t get_byte(int index, bool neg)
|
||||
{
|
||||
return neg ? (0xff << (index % 7)) : (0xff >> ((index % 6) + 1));
|
||||
}
|
||||
|
||||
static void init_test_data_s8(bool neg_first)
|
||||
{
|
||||
uint8_t top, bottom, *ptr = &test_data[0];
|
||||
int i;
|
||||
|
||||
ml_printf("Filling test area with s8 pairs (%s):",
|
||||
neg_first ? "neg first" : "pos first");
|
||||
for (i = 0; i < TEST_SIZE / 2; i++) {
|
||||
*ptr++ = get_byte(i, neg_first);
|
||||
*ptr++ = get_byte(i, !neg_first);
|
||||
pdot(i);
|
||||
}
|
||||
ml_printf("done\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* Zero the first few bytes of the test data in preparation for
|
||||
* new offset values.
|
||||
*/
|
||||
static void reset_start_data(int offset)
|
||||
{
|
||||
uint32_t *ptr = (uint32_t *) &test_data[0];
|
||||
int i;
|
||||
for (i = 0; i < offset; i++) {
|
||||
*ptr++ = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void init_test_data_u16(int offset)
|
||||
{
|
||||
uint8_t count = 0;
|
||||
uint16_t word, *ptr = (uint16_t *) &test_data[offset];
|
||||
const int max = (TEST_SIZE - offset) / sizeof(word);
|
||||
int i;
|
||||
|
||||
ml_printf("Filling test area with u16 (offset %d, %p):", offset, ptr);
|
||||
|
||||
reset_start_data(offset);
|
||||
|
||||
for (i = 0; i < max; i++) {
|
||||
uint8_t low = count++, high = count++;
|
||||
word = BYTE_SHIFT(high, 1) | BYTE_SHIFT(low, 0);
|
||||
*ptr++ = word;
|
||||
pdot(i);
|
||||
}
|
||||
ml_printf("done @ %p\n", ptr);
|
||||
}
|
||||
|
||||
static void init_test_data_u32(int offset)
|
||||
{
|
||||
uint8_t count = 0;
|
||||
uint32_t word, *ptr = (uint32_t *) &test_data[offset];
|
||||
const int max = (TEST_SIZE - offset) / sizeof(word);
|
||||
int i;
|
||||
|
||||
ml_printf("Filling test area with u32 (offset %d, %p):", offset, ptr);
|
||||
|
||||
reset_start_data(offset);
|
||||
|
||||
for (i = 0; i < max; i++) {
|
||||
uint8_t b4 = count++, b3 = count++;
|
||||
uint8_t b2 = count++, b1 = count++;
|
||||
word = BYTE_SHIFT(b1, 3) | BYTE_SHIFT(b2, 2) | BYTE_SHIFT(b3, 1) | b4;
|
||||
*ptr++ = word;
|
||||
pdot(i);
|
||||
}
|
||||
ml_printf("done @ %p\n", ptr);
|
||||
}
|
||||
|
||||
static void init_test_data_u64(int offset)
|
||||
{
|
||||
uint8_t count = 0;
|
||||
uint64_t word, *ptr = (uint64_t *) &test_data[offset];
|
||||
const int max = (TEST_SIZE - offset) / sizeof(word);
|
||||
int i;
|
||||
|
||||
ml_printf("Filling test area with u64 (offset %d, %p):", offset, ptr);
|
||||
|
||||
reset_start_data(offset);
|
||||
|
||||
for (i = 0; i < max; i++) {
|
||||
uint8_t b8 = count++, b7 = count++;
|
||||
uint8_t b6 = count++, b5 = count++;
|
||||
uint8_t b4 = count++, b3 = count++;
|
||||
uint8_t b2 = count++, b1 = count++;
|
||||
word = BYTE_SHIFT(b1, 7) | BYTE_SHIFT(b2, 6) | BYTE_SHIFT(b3, 5) |
|
||||
BYTE_SHIFT(b4, 4) | BYTE_SHIFT(b5, 3) | BYTE_SHIFT(b6, 2) |
|
||||
BYTE_SHIFT(b7, 1) | b8;
|
||||
*ptr++ = word;
|
||||
pdot(i);
|
||||
}
|
||||
ml_printf("done @ %p\n", ptr);
|
||||
}
|
||||
|
||||
static bool read_test_data_u16(int offset)
|
||||
{
|
||||
uint16_t word, *ptr = (uint16_t *)&test_data[offset];
|
||||
int i;
|
||||
const int max = (TEST_SIZE - offset) / sizeof(word);
|
||||
|
||||
ml_printf("Reading u16 from %#lx (offset %d):", ptr, offset);
|
||||
|
||||
for (i = 0; i < max; i++) {
|
||||
uint8_t high, low;
|
||||
word = *ptr++;
|
||||
high = (word >> 8) & 0xff;
|
||||
low = word & 0xff;
|
||||
if (high < low && high != 0) {
|
||||
ml_printf("Error %d < %d\n", high, low);
|
||||
return false;
|
||||
} else {
|
||||
pdot(i);
|
||||
}
|
||||
|
||||
}
|
||||
ml_printf("done @ %p\n", ptr);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool read_test_data_u32(int offset)
|
||||
{
|
||||
uint32_t word, *ptr = (uint32_t *)&test_data[offset];
|
||||
int i;
|
||||
const int max = (TEST_SIZE - offset) / sizeof(word);
|
||||
|
||||
ml_printf("Reading u32 from %#lx (offset %d):", ptr, offset);
|
||||
|
||||
for (i = 0; i < max; i++) {
|
||||
uint8_t b1, b2, b3, b4;
|
||||
word = *ptr++;
|
||||
|
||||
b1 = word >> 24 & 0xff;
|
||||
b2 = word >> 16 & 0xff;
|
||||
b3 = word >> 8 & 0xff;
|
||||
b4 = word & 0xff;
|
||||
|
||||
if ((b1 < b2 && b1 != 0) ||
|
||||
(b2 < b3 && b2 != 0) ||
|
||||
(b3 < b4 && b3 != 0)) {
|
||||
ml_printf("Error %d, %d, %d, %d", b1, b2, b3, b4);
|
||||
return false;
|
||||
} else {
|
||||
pdot(i);
|
||||
}
|
||||
}
|
||||
ml_printf("done @ %p\n", ptr);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool read_test_data_u64(int offset)
|
||||
{
|
||||
uint64_t word, *ptr = (uint64_t *)&test_data[offset];
|
||||
int i;
|
||||
const int max = (TEST_SIZE - offset) / sizeof(word);
|
||||
|
||||
ml_printf("Reading u64 from %#lx (offset %d):", ptr, offset);
|
||||
|
||||
for (i = 0; i < max; i++) {
|
||||
uint8_t b1, b2, b3, b4, b5, b6, b7, b8;
|
||||
word = *ptr++;
|
||||
|
||||
b1 = ((uint64_t) (word >> 56)) & 0xff;
|
||||
b2 = ((uint64_t) (word >> 48)) & 0xff;
|
||||
b3 = ((uint64_t) (word >> 40)) & 0xff;
|
||||
b4 = (word >> 32) & 0xff;
|
||||
b5 = (word >> 24) & 0xff;
|
||||
b6 = (word >> 16) & 0xff;
|
||||
b7 = (word >> 8) & 0xff;
|
||||
b8 = (word >> 0) & 0xff;
|
||||
|
||||
if ((b1 < b2 && b1 != 0) ||
|
||||
(b2 < b3 && b2 != 0) ||
|
||||
(b3 < b4 && b3 != 0) ||
|
||||
(b4 < b5 && b4 != 0) ||
|
||||
(b5 < b6 && b5 != 0) ||
|
||||
(b6 < b7 && b6 != 0) ||
|
||||
(b7 < b8 && b7 != 0)) {
|
||||
ml_printf("Error %d, %d, %d, %d, %d, %d, %d, %d",
|
||||
b1, b2, b3, b4, b5, b6, b7, b8);
|
||||
return false;
|
||||
} else {
|
||||
pdot(i);
|
||||
}
|
||||
}
|
||||
ml_printf("done @ %p\n", ptr);
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Read the test data and verify at various offsets */
|
||||
read_ufn read_ufns[] = { read_test_data_u16,
|
||||
read_test_data_u32,
|
||||
read_test_data_u64 };
|
||||
|
||||
bool do_unsigned_reads(void)
|
||||
{
|
||||
int i;
|
||||
bool ok = true;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(read_ufns) && ok; i++) {
|
||||
#if CHECK_UNALIGNED
|
||||
int off;
|
||||
for (off = 0; off < 8 && ok; off++) {
|
||||
ok = read_ufns[i](off);
|
||||
}
|
||||
#else
|
||||
ok = read_ufns[i](0);
|
||||
#endif
|
||||
}
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
static bool do_unsigned_test(init_ufn fn)
|
||||
{
|
||||
#if CHECK_UNALIGNED
|
||||
bool ok = true;
|
||||
int i;
|
||||
for (i = 0; i < 8 && ok; i++) {
|
||||
fn(i);
|
||||
ok = do_unsigned_reads();
|
||||
}
|
||||
#else
|
||||
fn(0);
|
||||
return do_unsigned_reads();
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* We need to ensure signed data is read into a larger data type to
|
||||
* ensure that sign extension is working properly.
|
||||
*/
|
||||
|
||||
static bool read_test_data_s8(int offset, bool neg_first)
|
||||
{
|
||||
int8_t *ptr = (int8_t *)&test_data[offset];
|
||||
int i;
|
||||
const int max = (TEST_SIZE - offset) / 2;
|
||||
|
||||
ml_printf("Reading s8 pairs from %#lx (offset %d):", ptr, offset);
|
||||
|
||||
for (i = 0; i < max; i++) {
|
||||
int16_t first, second;
|
||||
bool ok;
|
||||
first = *ptr++;
|
||||
second = *ptr++;
|
||||
|
||||
if (neg_first && first < 0 && second > 0) {
|
||||
pdot(i);
|
||||
} else if (!neg_first && first > 0 && second < 0) {
|
||||
pdot(i);
|
||||
} else {
|
||||
ml_printf("Error %d %c %d\n", first, neg_first ? '<' : '>', second);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
ml_printf("done @ %p\n", ptr);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool read_test_data_s16(int offset, bool neg_first)
|
||||
{
|
||||
int16_t *ptr = (int16_t *)&test_data[offset];
|
||||
int i;
|
||||
const int max = (TEST_SIZE - offset) / (sizeof(*ptr));
|
||||
|
||||
ml_printf("Reading s16 from %#lx (offset %d, %s):", ptr,
|
||||
offset, neg_first ? "neg" : "pos");
|
||||
|
||||
for (i = 0; i < max; i++) {
|
||||
int32_t data = *ptr++;
|
||||
|
||||
if (neg_first && data < 0) {
|
||||
pdot(i);
|
||||
} else if (data > 0) {
|
||||
pdot(i);
|
||||
} else {
|
||||
ml_printf("Error %d %c 0\n", data, neg_first ? '<' : '>');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
ml_printf("done @ %p\n", ptr);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool read_test_data_s32(int offset, bool neg_first)
|
||||
{
|
||||
int32_t *ptr = (int32_t *)&test_data[offset];
|
||||
int i;
|
||||
const int max = (TEST_SIZE - offset) / (sizeof(int32_t));
|
||||
|
||||
ml_printf("Reading s32 from %#lx (offset %d, %s):",
|
||||
ptr, offset, neg_first ? "neg" : "pos");
|
||||
|
||||
for (i = 0; i < max; i++) {
|
||||
int64_t data = *ptr++;
|
||||
|
||||
if (neg_first && data < 0) {
|
||||
pdot(i);
|
||||
} else if (data > 0) {
|
||||
pdot(i);
|
||||
} else {
|
||||
ml_printf("Error %d %c 0\n", data, neg_first ? '<' : '>');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
ml_printf("done @ %p\n", ptr);
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read the test data and verify at various offsets
|
||||
*
|
||||
* For everything except bytes all our reads should be either positive
|
||||
* or negative depending on what offset we are reading from. Currently
|
||||
* we only handle LE systems.
|
||||
*/
|
||||
read_sfn read_sfns[] = { read_test_data_s8,
|
||||
read_test_data_s16,
|
||||
read_test_data_s32 };
|
||||
|
||||
bool do_signed_reads(bool neg_first)
|
||||
{
|
||||
int i;
|
||||
bool ok = true;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(read_sfns) && ok; i++) {
|
||||
#if CHECK_UNALIGNED
|
||||
int off;
|
||||
for (off = 0; off < 8 && ok; off++) {
|
||||
bool nf = i == 0 ? neg_first ^ (off & 1) : !(neg_first ^ (off & 1));
|
||||
ok = read_sfns[i](off, nf);
|
||||
}
|
||||
#else
|
||||
ok = read_sfns[i](0, i == 0 ? neg_first : !neg_first);
|
||||
#endif
|
||||
}
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
init_ufn init_ufns[] = { init_test_data_u8,
|
||||
init_test_data_u16,
|
||||
init_test_data_u32,
|
||||
init_test_data_u64 };
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int i;
|
||||
bool ok = true;
|
||||
|
||||
/* Run through the unsigned tests first */
|
||||
for (i = 0; i < ARRAY_SIZE(init_ufns) && ok; i++) {
|
||||
ok = do_unsigned_test(init_ufns[i]);
|
||||
}
|
||||
|
||||
if (ok) {
|
||||
init_test_data_s8(false);
|
||||
ok = do_signed_reads(false);
|
||||
}
|
||||
|
||||
if (ok) {
|
||||
init_test_data_s8(true);
|
||||
ok = do_signed_reads(true);
|
||||
}
|
||||
|
||||
ml_printf("Test complete: %s\n", ok ? "PASSED" : "FAILED");
|
||||
return ok ? 0 : -1;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue