Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
29ff573753
@ -100,6 +100,17 @@ avocado-system-debian:
|
|||||||
IMAGE: debian-amd64
|
IMAGE: debian-amd64
|
||||||
MAKE_CHECK_ARGS: check-avocado
|
MAKE_CHECK_ARGS: check-avocado
|
||||||
|
|
||||||
|
crash-test-debian:
|
||||||
|
extends: .native_test_job_template
|
||||||
|
needs:
|
||||||
|
- job: build-system-debian
|
||||||
|
artifacts: true
|
||||||
|
variables:
|
||||||
|
IMAGE: debian-amd64
|
||||||
|
script:
|
||||||
|
- cd build
|
||||||
|
- scripts/device-crash-test -q ./qemu-system-i386
|
||||||
|
|
||||||
build-system-fedora:
|
build-system-fedora:
|
||||||
extends: .native_build_job_template
|
extends: .native_build_job_template
|
||||||
needs:
|
needs:
|
||||||
@ -134,6 +145,18 @@ avocado-system-fedora:
|
|||||||
IMAGE: fedora
|
IMAGE: fedora
|
||||||
MAKE_CHECK_ARGS: check-avocado
|
MAKE_CHECK_ARGS: check-avocado
|
||||||
|
|
||||||
|
crash-test-fedora:
|
||||||
|
extends: .native_test_job_template
|
||||||
|
needs:
|
||||||
|
- job: build-system-fedora
|
||||||
|
artifacts: true
|
||||||
|
variables:
|
||||||
|
IMAGE: fedora
|
||||||
|
script:
|
||||||
|
- cd build
|
||||||
|
- scripts/device-crash-test -q ./qemu-system-ppc
|
||||||
|
- scripts/device-crash-test -q ./qemu-system-riscv32
|
||||||
|
|
||||||
build-system-centos:
|
build-system-centos:
|
||||||
extends: .native_build_job_template
|
extends: .native_build_job_template
|
||||||
needs:
|
needs:
|
||||||
|
@ -89,3 +89,38 @@ x64-macos-11-base-build:
|
|||||||
PATH_EXTRA: /usr/local/opt/ccache/libexec:/usr/local/opt/gettext/bin
|
PATH_EXTRA: /usr/local/opt/ccache/libexec:/usr/local/opt/gettext/bin
|
||||||
PKG_CONFIG_PATH: /usr/local/opt/curl/lib/pkgconfig:/usr/local/opt/ncurses/lib/pkgconfig:/usr/local/opt/readline/lib/pkgconfig
|
PKG_CONFIG_PATH: /usr/local/opt/curl/lib/pkgconfig:/usr/local/opt/ncurses/lib/pkgconfig:/usr/local/opt/readline/lib/pkgconfig
|
||||||
TEST_TARGETS: check-unit check-block check-qapi-schema check-softfloat check-qtest-x86_64
|
TEST_TARGETS: check-unit check-block check-qapi-schema check-softfloat check-qtest-x86_64
|
||||||
|
|
||||||
|
|
||||||
|
# The following jobs run VM-based tests via KVM on a Linux-based Cirrus-CI job
|
||||||
|
.cirrus_kvm_job:
|
||||||
|
stage: build
|
||||||
|
image: registry.gitlab.com/libvirt/libvirt-ci/cirrus-run:master
|
||||||
|
needs: []
|
||||||
|
timeout: 80m
|
||||||
|
allow_failure: true
|
||||||
|
script:
|
||||||
|
- sed -e "s|[@]CI_REPOSITORY_URL@|$CI_REPOSITORY_URL|g"
|
||||||
|
-e "s|[@]CI_COMMIT_REF_NAME@|$CI_COMMIT_REF_NAME|g"
|
||||||
|
-e "s|[@]CI_COMMIT_SHA@|$CI_COMMIT_SHA|g"
|
||||||
|
-e "s|[@]NAME@|$NAME|g"
|
||||||
|
-e "s|[@]CONFIGURE_ARGS@|$CONFIGURE_ARGS|g"
|
||||||
|
-e "s|[@]TEST_TARGETS@|$TEST_TARGETS|g"
|
||||||
|
<.gitlab-ci.d/cirrus/kvm-build.yml >.gitlab-ci.d/cirrus/$NAME.yml
|
||||||
|
- cat .gitlab-ci.d/cirrus/$NAME.yml
|
||||||
|
- cirrus-run -v --show-build-log always .gitlab-ci.d/cirrus/$NAME.yml
|
||||||
|
rules:
|
||||||
|
- when: manual
|
||||||
|
|
||||||
|
x86-netbsd:
|
||||||
|
extends: .cirrus_kvm_job
|
||||||
|
variables:
|
||||||
|
NAME: netbsd
|
||||||
|
CONFIGURE_ARGS: --target-list=x86_64-softmmu,ppc64-softmmu,aarch64-softmmu
|
||||||
|
TEST_TARGETS: check
|
||||||
|
|
||||||
|
x86-openbsd:
|
||||||
|
extends: .cirrus_kvm_job
|
||||||
|
variables:
|
||||||
|
NAME: openbsd
|
||||||
|
CONFIGURE_ARGS: --target-list=i386-softmmu,riscv64-softmmu,mips64-softmmu
|
||||||
|
TEST_TARGETS: check
|
||||||
|
31
.gitlab-ci.d/cirrus/kvm-build.yml
Normal file
31
.gitlab-ci.d/cirrus/kvm-build.yml
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
container:
|
||||||
|
image: fedora:35
|
||||||
|
cpu: 4
|
||||||
|
memory: 8Gb
|
||||||
|
kvm: true
|
||||||
|
|
||||||
|
env:
|
||||||
|
CIRRUS_CLONE_DEPTH: 1
|
||||||
|
CI_REPOSITORY_URL: "@CI_REPOSITORY_URL@"
|
||||||
|
CI_COMMIT_REF_NAME: "@CI_COMMIT_REF_NAME@"
|
||||||
|
CI_COMMIT_SHA: "@CI_COMMIT_SHA@"
|
||||||
|
|
||||||
|
@NAME@_task:
|
||||||
|
@NAME@_vm_cache:
|
||||||
|
folder: $HOME/.cache/qemu-vm
|
||||||
|
install_script:
|
||||||
|
- dnf update -y
|
||||||
|
- dnf install -y git make openssh-clients qemu-img qemu-system-x86 wget
|
||||||
|
clone_script:
|
||||||
|
- git clone --depth 100 "$CI_REPOSITORY_URL" .
|
||||||
|
- git fetch origin "$CI_COMMIT_REF_NAME"
|
||||||
|
- git reset --hard "$CI_COMMIT_SHA"
|
||||||
|
build_script:
|
||||||
|
- if [ -f $HOME/.cache/qemu-vm/images/@NAME@.img ]; then
|
||||||
|
make vm-build-@NAME@ J=$(getconf _NPROCESSORS_ONLN)
|
||||||
|
EXTRA_CONFIGURE_OPTS="@CONFIGURE_ARGS@"
|
||||||
|
BUILD_TARGET="@TEST_TARGETS@" ;
|
||||||
|
else
|
||||||
|
make vm-build-@NAME@ J=$(getconf _NPROCESSORS_ONLN) BUILD_TARGET=help
|
||||||
|
EXTRA_CONFIGURE_OPTS="--disable-system --disable-user --disable-tools" ;
|
||||||
|
fi
|
@ -11,3 +11,4 @@ include:
|
|||||||
- local: '/.gitlab-ci.d/static_checks.yml'
|
- local: '/.gitlab-ci.d/static_checks.yml'
|
||||||
- local: '/.gitlab-ci.d/custom-runners.yml'
|
- local: '/.gitlab-ci.d/custom-runners.yml'
|
||||||
- local: '/.gitlab-ci.d/cirrus.yml'
|
- local: '/.gitlab-ci.d/cirrus.yml'
|
||||||
|
- local: '/.gitlab-ci.d/windows.yml'
|
||||||
|
98
.gitlab-ci.d/windows.yml
Normal file
98
.gitlab-ci.d/windows.yml
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
.shared_msys2_builder:
|
||||||
|
tags:
|
||||||
|
- shared-windows
|
||||||
|
- windows
|
||||||
|
- windows-1809
|
||||||
|
cache:
|
||||||
|
key: "${CI_JOB_NAME}-cache"
|
||||||
|
paths:
|
||||||
|
- ${CI_PROJECT_DIR}/msys64/var/cache
|
||||||
|
needs: []
|
||||||
|
stage: build
|
||||||
|
timeout: 70m
|
||||||
|
before_script:
|
||||||
|
- If ( !(Test-Path -Path msys64\var\cache ) ) {
|
||||||
|
mkdir msys64\var\cache
|
||||||
|
}
|
||||||
|
- If ( !(Test-Path -Path msys64\var\cache\msys2.exe ) ) {
|
||||||
|
Invoke-WebRequest
|
||||||
|
"https://github.com/msys2/msys2-installer/releases/download/2021-07-25/msys2-base-x86_64-20210725.sfx.exe"
|
||||||
|
-outfile "msys64\var\cache\msys2.exe"
|
||||||
|
}
|
||||||
|
- msys64\var\cache\msys2.exe -y
|
||||||
|
- ((Get-Content -path .\msys64\etc\\post-install\\07-pacman-key.post -Raw)
|
||||||
|
-replace '--refresh-keys', '--version') |
|
||||||
|
Set-Content -Path ${CI_PROJECT_DIR}\msys64\etc\\post-install\\07-pacman-key.post
|
||||||
|
- .\msys64\usr\bin\bash -lc "sed -i 's/^CheckSpace/#CheckSpace/g' /etc/pacman.conf"
|
||||||
|
- .\msys64\usr\bin\bash -lc 'pacman --noconfirm -Syuu' # Core update
|
||||||
|
- .\msys64\usr\bin\bash -lc 'pacman --noconfirm -Syuu' # Normal update
|
||||||
|
- taskkill /F /FI "MODULES eq msys-2.0.dll"
|
||||||
|
|
||||||
|
msys2-64bit:
|
||||||
|
extends: .shared_msys2_builder
|
||||||
|
script:
|
||||||
|
- .\msys64\usr\bin\bash -lc "pacman -Sy --noconfirm --needed
|
||||||
|
diffutils git grep make sed
|
||||||
|
mingw-w64-x86_64-capstone
|
||||||
|
mingw-w64-x86_64-curl
|
||||||
|
mingw-w64-x86_64-cyrus-sasl
|
||||||
|
mingw-w64-x86_64-gcc
|
||||||
|
mingw-w64-x86_64-glib2
|
||||||
|
mingw-w64-x86_64-gnutls
|
||||||
|
mingw-w64-x86_64-libnfs
|
||||||
|
mingw-w64-x86_64-libpng
|
||||||
|
mingw-w64-x86_64-libssh
|
||||||
|
mingw-w64-x86_64-libtasn1
|
||||||
|
mingw-w64-x86_64-libusb
|
||||||
|
mingw-w64-x86_64-libxml2
|
||||||
|
mingw-w64-x86_64-nettle
|
||||||
|
mingw-w64-x86_64-ninja
|
||||||
|
mingw-w64-x86_64-pixman
|
||||||
|
mingw-w64-x86_64-pkgconf
|
||||||
|
mingw-w64-x86_64-python
|
||||||
|
mingw-w64-x86_64-SDL2
|
||||||
|
mingw-w64-x86_64-SDL2_image
|
||||||
|
mingw-w64-x86_64-snappy
|
||||||
|
mingw-w64-x86_64-usbredir
|
||||||
|
mingw-w64-x86_64-zstd "
|
||||||
|
- $env:CHERE_INVOKING = 'yes' # Preserve the current working directory
|
||||||
|
- $env:MSYSTEM = 'MINGW64' # Start a 64 bit Mingw environment
|
||||||
|
- .\msys64\usr\bin\bash -lc './configure --target-list=x86_64-softmmu
|
||||||
|
--enable-capstone=system --without-default-devices'
|
||||||
|
- .\msys64\usr\bin\bash -lc "sed -i '/^ROMS=/d' build/config-host.mak"
|
||||||
|
- .\msys64\usr\bin\bash -lc 'make -j2'
|
||||||
|
- .\msys64\usr\bin\bash -lc 'make check'
|
||||||
|
|
||||||
|
msys2-32bit:
|
||||||
|
extends: .shared_msys2_builder
|
||||||
|
script:
|
||||||
|
- .\msys64\usr\bin\bash -lc "pacman -Sy --noconfirm --needed
|
||||||
|
diffutils git grep make sed
|
||||||
|
mingw-w64-i686-capstone
|
||||||
|
mingw-w64-i686-curl
|
||||||
|
mingw-w64-i686-cyrus-sasl
|
||||||
|
mingw-w64-i686-gcc
|
||||||
|
mingw-w64-i686-glib2
|
||||||
|
mingw-w64-i686-gnutls
|
||||||
|
mingw-w64-i686-gtk3
|
||||||
|
mingw-w64-i686-libgcrypt
|
||||||
|
mingw-w64-i686-libjpeg-turbo
|
||||||
|
mingw-w64-i686-libssh
|
||||||
|
mingw-w64-i686-libtasn1
|
||||||
|
mingw-w64-i686-libusb
|
||||||
|
mingw-w64-i686-libxml2
|
||||||
|
mingw-w64-i686-lzo2
|
||||||
|
mingw-w64-i686-ninja
|
||||||
|
mingw-w64-i686-pixman
|
||||||
|
mingw-w64-i686-pkgconf
|
||||||
|
mingw-w64-i686-python
|
||||||
|
mingw-w64-i686-snappy
|
||||||
|
mingw-w64-i686-usbredir "
|
||||||
|
- $env:CHERE_INVOKING = 'yes' # Preserve the current working directory
|
||||||
|
- $env:MSYSTEM = 'MINGW32' # Start a 32-bit MinG environment
|
||||||
|
- mkdir output
|
||||||
|
- cd output
|
||||||
|
- ..\msys64\usr\bin\bash -lc "../configure --target-list=ppc64-softmmu
|
||||||
|
--enable-capstone=system"
|
||||||
|
- ..\msys64\usr\bin\bash -lc 'make -j2'
|
||||||
|
- ..\msys64\usr\bin\bash -lc 'make check'
|
1
.mailmap
1
.mailmap
@ -50,6 +50,7 @@ Aleksandar Rikalo <aleksandar.rikalo@syrmia.com> <arikalo@wavecomp.com>
|
|||||||
Aleksandar Rikalo <aleksandar.rikalo@syrmia.com> <aleksandar.rikalo@rt-rk.com>
|
Aleksandar Rikalo <aleksandar.rikalo@syrmia.com> <aleksandar.rikalo@rt-rk.com>
|
||||||
Alexander Graf <agraf@csgraf.de> <agraf@suse.de>
|
Alexander Graf <agraf@csgraf.de> <agraf@suse.de>
|
||||||
Anthony Liguori <anthony@codemonkey.ws> Anthony Liguori <aliguori@us.ibm.com>
|
Anthony Liguori <anthony@codemonkey.ws> Anthony Liguori <aliguori@us.ibm.com>
|
||||||
|
Christian Borntraeger <borntraeger@linux.ibm.com> <borntraeger@de.ibm.com>
|
||||||
Filip Bozuta <filip.bozuta@syrmia.com> <filip.bozuta@rt-rk.com.com>
|
Filip Bozuta <filip.bozuta@syrmia.com> <filip.bozuta@rt-rk.com.com>
|
||||||
Frederic Konrad <konrad@adacore.com> <fred.konrad@greensocs.com>
|
Frederic Konrad <konrad@adacore.com> <fred.konrad@greensocs.com>
|
||||||
Greg Kurz <groug@kaod.org> <gkurz@linux.vnet.ibm.com>
|
Greg Kurz <groug@kaod.org> <gkurz@linux.vnet.ibm.com>
|
||||||
|
10
MAINTAINERS
10
MAINTAINERS
@ -393,7 +393,7 @@ F: target/ppc/kvm.c
|
|||||||
|
|
||||||
S390 KVM CPUs
|
S390 KVM CPUs
|
||||||
M: Halil Pasic <pasic@linux.ibm.com>
|
M: Halil Pasic <pasic@linux.ibm.com>
|
||||||
M: Christian Borntraeger <borntraeger@de.ibm.com>
|
M: Christian Borntraeger <borntraeger@linux.ibm.com>
|
||||||
S: Supported
|
S: Supported
|
||||||
F: target/s390x/kvm/
|
F: target/s390x/kvm/
|
||||||
F: target/s390x/ioinst.[ch]
|
F: target/s390x/ioinst.[ch]
|
||||||
@ -1527,7 +1527,7 @@ S390 Machines
|
|||||||
-------------
|
-------------
|
||||||
S390 Virtio-ccw
|
S390 Virtio-ccw
|
||||||
M: Halil Pasic <pasic@linux.ibm.com>
|
M: Halil Pasic <pasic@linux.ibm.com>
|
||||||
M: Christian Borntraeger <borntraeger@de.ibm.com>
|
M: Christian Borntraeger <borntraeger@linux.ibm.com>
|
||||||
S: Supported
|
S: Supported
|
||||||
F: hw/char/sclp*.[hc]
|
F: hw/char/sclp*.[hc]
|
||||||
F: hw/char/terminal3270.c
|
F: hw/char/terminal3270.c
|
||||||
@ -1541,7 +1541,7 @@ T: git https://github.com/borntraeger/qemu.git s390-next
|
|||||||
L: qemu-s390x@nongnu.org
|
L: qemu-s390x@nongnu.org
|
||||||
|
|
||||||
S390-ccw boot
|
S390-ccw boot
|
||||||
M: Christian Borntraeger <borntraeger@de.ibm.com>
|
M: Christian Borntraeger <borntraeger@linux.ibm.com>
|
||||||
M: Thomas Huth <thuth@redhat.com>
|
M: Thomas Huth <thuth@redhat.com>
|
||||||
S: Supported
|
S: Supported
|
||||||
F: hw/s390x/ipl.*
|
F: hw/s390x/ipl.*
|
||||||
@ -1825,6 +1825,7 @@ F: hw/scsi/*
|
|||||||
F: tests/qtest/virtio-scsi-test.c
|
F: tests/qtest/virtio-scsi-test.c
|
||||||
F: tests/qtest/fuzz-virtio-scsi-test.c
|
F: tests/qtest/fuzz-virtio-scsi-test.c
|
||||||
F: tests/qtest/am53c974-test.c
|
F: tests/qtest/am53c974-test.c
|
||||||
|
F: tests/qtest/fuzz-lsi53c895a-test.c
|
||||||
T: git https://github.com/bonzini/qemu.git scsi-next
|
T: git https://github.com/bonzini/qemu.git scsi-next
|
||||||
|
|
||||||
SSI
|
SSI
|
||||||
@ -3076,8 +3077,9 @@ Usermode Emulation
|
|||||||
Overall usermode emulation
|
Overall usermode emulation
|
||||||
M: Riku Voipio <riku.voipio@iki.fi>
|
M: Riku Voipio <riku.voipio@iki.fi>
|
||||||
S: Maintained
|
S: Maintained
|
||||||
F: thunk.c
|
|
||||||
F: accel/tcg/user-exec*.c
|
F: accel/tcg/user-exec*.c
|
||||||
|
F: include/user/
|
||||||
|
F: common-user/
|
||||||
|
|
||||||
BSD user
|
BSD user
|
||||||
M: Warner Losh <imp@bsdimp.com>
|
M: Warner Losh <imp@bsdimp.com>
|
||||||
|
@ -61,6 +61,10 @@
|
|||||||
#endif
|
#endif
|
||||||
#define PAGE_SIZE qemu_real_host_page_size
|
#define PAGE_SIZE qemu_real_host_page_size
|
||||||
|
|
||||||
|
#ifndef KVM_GUESTDBG_BLOCKIRQ
|
||||||
|
#define KVM_GUESTDBG_BLOCKIRQ 0
|
||||||
|
#endif
|
||||||
|
|
||||||
//#define DEBUG_KVM
|
//#define DEBUG_KVM
|
||||||
|
|
||||||
#ifdef DEBUG_KVM
|
#ifdef DEBUG_KVM
|
||||||
@ -168,6 +172,8 @@ bool kvm_vm_attributes_allowed;
|
|||||||
bool kvm_direct_msi_allowed;
|
bool kvm_direct_msi_allowed;
|
||||||
bool kvm_ioeventfd_any_length_allowed;
|
bool kvm_ioeventfd_any_length_allowed;
|
||||||
bool kvm_msi_use_devid;
|
bool kvm_msi_use_devid;
|
||||||
|
bool kvm_has_guest_debug;
|
||||||
|
int kvm_sstep_flags;
|
||||||
static bool kvm_immediate_exit;
|
static bool kvm_immediate_exit;
|
||||||
static hwaddr kvm_max_slot_size = ~0;
|
static hwaddr kvm_max_slot_size = ~0;
|
||||||
|
|
||||||
@ -2564,6 +2570,25 @@ static int kvm_init(MachineState *ms)
|
|||||||
kvm_ioeventfd_any_length_allowed =
|
kvm_ioeventfd_any_length_allowed =
|
||||||
(kvm_check_extension(s, KVM_CAP_IOEVENTFD_ANY_LENGTH) > 0);
|
(kvm_check_extension(s, KVM_CAP_IOEVENTFD_ANY_LENGTH) > 0);
|
||||||
|
|
||||||
|
#ifdef KVM_CAP_SET_GUEST_DEBUG
|
||||||
|
kvm_has_guest_debug =
|
||||||
|
(kvm_check_extension(s, KVM_CAP_SET_GUEST_DEBUG) > 0);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
kvm_sstep_flags = 0;
|
||||||
|
if (kvm_has_guest_debug) {
|
||||||
|
kvm_sstep_flags = SSTEP_ENABLE;
|
||||||
|
|
||||||
|
#if defined KVM_CAP_SET_GUEST_DEBUG2
|
||||||
|
int guest_debug_flags =
|
||||||
|
kvm_check_extension(s, KVM_CAP_SET_GUEST_DEBUG2);
|
||||||
|
|
||||||
|
if (guest_debug_flags & KVM_GUESTDBG_BLOCKIRQ) {
|
||||||
|
kvm_sstep_flags |= SSTEP_NOIRQ;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
kvm_state = s;
|
kvm_state = s;
|
||||||
|
|
||||||
ret = kvm_arch_init(ms, s);
|
ret = kvm_arch_init(ms, s);
|
||||||
@ -3193,6 +3218,10 @@ int kvm_update_guest_debug(CPUState *cpu, unsigned long reinject_trap)
|
|||||||
|
|
||||||
if (cpu->singlestep_enabled) {
|
if (cpu->singlestep_enabled) {
|
||||||
data.dbg.control |= KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_SINGLESTEP;
|
data.dbg.control |= KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_SINGLESTEP;
|
||||||
|
|
||||||
|
if (cpu->singlestep_enabled & SSTEP_NOIRQ) {
|
||||||
|
data.dbg.control |= KVM_GUESTDBG_BLOCKIRQ;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
kvm_arch_update_guest_debug(cpu, &data.dbg);
|
kvm_arch_update_guest_debug(cpu, &data.dbg);
|
||||||
|
|
||||||
|
@ -206,8 +206,9 @@ static void nvme_free_req_queue_cb(void *opaque)
|
|||||||
NVMeQueuePair *q = opaque;
|
NVMeQueuePair *q = opaque;
|
||||||
|
|
||||||
qemu_mutex_lock(&q->lock);
|
qemu_mutex_lock(&q->lock);
|
||||||
while (qemu_co_enter_next(&q->free_req_queue, &q->lock)) {
|
while (q->free_req_head != -1 &&
|
||||||
/* Retry all pending requests */
|
qemu_co_enter_next(&q->free_req_queue, &q->lock)) {
|
||||||
|
/* Retry waiting requests */
|
||||||
}
|
}
|
||||||
qemu_mutex_unlock(&q->lock);
|
qemu_mutex_unlock(&q->lock);
|
||||||
}
|
}
|
||||||
|
10
blockdev.c
10
blockdev.c
@ -303,16 +303,6 @@ int drive_get_max_bus(BlockInterfaceType type)
|
|||||||
return max_bus;
|
return max_bus;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get a block device. This should only be used for single-drive devices
|
|
||||||
(e.g. SD/Floppy/MTD). Multi-disk devices (scsi/ide) should use the
|
|
||||||
appropriate bus. */
|
|
||||||
DriveInfo *drive_get_next(BlockInterfaceType type)
|
|
||||||
{
|
|
||||||
static int next_block_unit[IF_COUNT];
|
|
||||||
|
|
||||||
return drive_get(type, 0, next_block_unit[type]++);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void bdrv_format_print(void *opaque, const char *name)
|
static void bdrv_format_print(void *opaque, const char *name)
|
||||||
{
|
{
|
||||||
qemu_printf(" %s", name);
|
qemu_printf(" %s", name);
|
||||||
|
@ -151,6 +151,10 @@
|
|||||||
/* Internal errors: */
|
/* Internal errors: */
|
||||||
#define TARGET_EJUSTRETURN 254 /* Just return without modifing regs */
|
#define TARGET_EJUSTRETURN 254 /* Just return without modifing regs */
|
||||||
#define TARGET_ERESTART 255 /* Restart syscall */
|
#define TARGET_ERESTART 255 /* Restart syscall */
|
||||||
#define TARGET_ERESTARTSYS TARGET_ERESTART /* Linux compat */
|
|
||||||
|
#include "special-errno.h"
|
||||||
|
|
||||||
|
_Static_assert(TARGET_ERESTART == QEMU_ERESTARTSYS,
|
||||||
|
"TARGET_ERESTART and QEMU_ERESTARTSYS expected to match");
|
||||||
|
|
||||||
#endif /* ! _ERRNO_DEFS_H_ */
|
#endif /* ! _ERRNO_DEFS_H_ */
|
||||||
|
@ -2,6 +2,10 @@ if not have_bsd_user
|
|||||||
subdir_done()
|
subdir_done()
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
bsd_user_ss = ss.source_set()
|
||||||
|
|
||||||
|
common_user_inc += include_directories('.')
|
||||||
|
|
||||||
bsd_user_ss.add(files(
|
bsd_user_ss.add(files(
|
||||||
'bsdload.c',
|
'bsdload.c',
|
||||||
'elfload.c',
|
'elfload.c',
|
||||||
@ -15,3 +19,5 @@ bsd_user_ss.add(files(
|
|||||||
|
|
||||||
# Pull in the OS-specific build glue, if any
|
# Pull in the OS-specific build glue, if any
|
||||||
subdir(targetos)
|
subdir(targetos)
|
||||||
|
|
||||||
|
specific_ss.add_all(when: 'CONFIG_BSD_USER', if_true: bsd_user_ss)
|
||||||
|
24
bsd-user/special-errno.h
Normal file
24
bsd-user/special-errno.h
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
/* SPDX-License-Identifier: BSD-3-Clause */
|
||||||
|
/*
|
||||||
|
* QEMU internal errno values for implementing user-only POSIX.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2021 Linaro, Ltd.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SPECIAL_ERRNO_H
|
||||||
|
#define SPECIAL_ERRNO_H
|
||||||
|
|
||||||
|
/*
|
||||||
|
* All of these are QEMU internal, not visible to the guest.
|
||||||
|
* They should be chosen so as to not overlap with any host
|
||||||
|
* or guest errno.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is returned when a system call should be restarted, to tell the
|
||||||
|
* main loop that it should wind the guest PC backwards so it will
|
||||||
|
* re-execute the syscall after handling any pending signals.
|
||||||
|
*/
|
||||||
|
#define QEMU_ERESTARTSYS 255
|
||||||
|
|
||||||
|
#endif /* SPECIAL_ERRNO_H */
|
88
common-user/host/aarch64/safe-syscall.inc.S
Normal file
88
common-user/host/aarch64/safe-syscall.inc.S
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
/*
|
||||||
|
* safe-syscall.inc.S : host-specific assembly fragment
|
||||||
|
* to handle signals occurring at the same time as system calls.
|
||||||
|
* This is intended to be included by common-user/safe-syscall.S
|
||||||
|
*
|
||||||
|
* Written by Richard Henderson <rth@twiddle.net>
|
||||||
|
* Copyright (C) 2016 Red Hat, Inc.
|
||||||
|
*
|
||||||
|
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||||
|
* See the COPYING file in the top-level directory.
|
||||||
|
*/
|
||||||
|
|
||||||
|
.global safe_syscall_base
|
||||||
|
.global safe_syscall_start
|
||||||
|
.global safe_syscall_end
|
||||||
|
.type safe_syscall_base, #function
|
||||||
|
.type safe_syscall_start, #function
|
||||||
|
.type safe_syscall_end, #function
|
||||||
|
|
||||||
|
/* This is the entry point for making a system call. The calling
|
||||||
|
* convention here is that of a C varargs function with the
|
||||||
|
* first argument an 'int *' to the signal_pending flag, the
|
||||||
|
* second one the system call number (as a 'long'), and all further
|
||||||
|
* arguments being syscall arguments (also 'long').
|
||||||
|
*/
|
||||||
|
safe_syscall_base:
|
||||||
|
.cfi_startproc
|
||||||
|
/* The syscall calling convention isn't the same as the
|
||||||
|
* C one:
|
||||||
|
* we enter with x0 == &signal_pending
|
||||||
|
* x1 == syscall number
|
||||||
|
* x2 ... x7, (stack) == syscall arguments
|
||||||
|
* and return the result in x0
|
||||||
|
* and the syscall instruction needs
|
||||||
|
* x8 == syscall number
|
||||||
|
* x0 ... x6 == syscall arguments
|
||||||
|
* and returns the result in x0
|
||||||
|
* Shuffle everything around appropriately.
|
||||||
|
*/
|
||||||
|
mov x9, x0 /* signal_pending pointer */
|
||||||
|
mov x8, x1 /* syscall number */
|
||||||
|
mov x0, x2 /* syscall arguments */
|
||||||
|
mov x1, x3
|
||||||
|
mov x2, x4
|
||||||
|
mov x3, x5
|
||||||
|
mov x4, x6
|
||||||
|
mov x5, x7
|
||||||
|
ldr x6, [sp]
|
||||||
|
|
||||||
|
/* This next sequence of code works in conjunction with the
|
||||||
|
* rewind_if_safe_syscall_function(). If a signal is taken
|
||||||
|
* and the interrupted PC is anywhere between 'safe_syscall_start'
|
||||||
|
* and 'safe_syscall_end' then we rewind it to 'safe_syscall_start'.
|
||||||
|
* The code sequence must therefore be able to cope with this, and
|
||||||
|
* the syscall instruction must be the final one in the sequence.
|
||||||
|
*/
|
||||||
|
safe_syscall_start:
|
||||||
|
/* if signal_pending is non-zero, don't do the call */
|
||||||
|
ldr w10, [x9]
|
||||||
|
cbnz w10, 2f
|
||||||
|
svc 0x0
|
||||||
|
safe_syscall_end:
|
||||||
|
|
||||||
|
/* code path for having successfully executed the syscall */
|
||||||
|
#if defined(__linux__)
|
||||||
|
/* Linux kernel returns (small) negative errno. */
|
||||||
|
cmp x0, #-4096
|
||||||
|
b.hi 0f
|
||||||
|
#elif defined(__FreeBSD__)
|
||||||
|
/* FreeBSD kernel returns positive errno and C bit set. */
|
||||||
|
b.cs 1f
|
||||||
|
#else
|
||||||
|
#error "unsupported os"
|
||||||
|
#endif
|
||||||
|
ret
|
||||||
|
|
||||||
|
#if defined(__linux__)
|
||||||
|
/* code path setting errno */
|
||||||
|
0: neg w0, w0
|
||||||
|
b safe_syscall_set_errno_tail
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* code path when we didn't execute the syscall */
|
||||||
|
2: mov w0, #QEMU_ERESTARTSYS
|
||||||
|
1: b safe_syscall_set_errno_tail
|
||||||
|
|
||||||
|
.cfi_endproc
|
||||||
|
.size safe_syscall_base, .-safe_syscall_base
|
108
common-user/host/arm/safe-syscall.inc.S
Normal file
108
common-user/host/arm/safe-syscall.inc.S
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
/*
|
||||||
|
* safe-syscall.inc.S : host-specific assembly fragment
|
||||||
|
* to handle signals occurring at the same time as system calls.
|
||||||
|
* This is intended to be included by common-user/safe-syscall.S
|
||||||
|
*
|
||||||
|
* Written by Richard Henderson <rth@twiddle.net>
|
||||||
|
* Copyright (C) 2016 Red Hat, Inc.
|
||||||
|
*
|
||||||
|
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||||
|
* See the COPYING file in the top-level directory.
|
||||||
|
*/
|
||||||
|
|
||||||
|
.global safe_syscall_base
|
||||||
|
.global safe_syscall_start
|
||||||
|
.global safe_syscall_end
|
||||||
|
.type safe_syscall_base, %function
|
||||||
|
|
||||||
|
.cfi_sections .debug_frame
|
||||||
|
|
||||||
|
.text
|
||||||
|
.syntax unified
|
||||||
|
.arm
|
||||||
|
.align 2
|
||||||
|
|
||||||
|
/* This is the entry point for making a system call. The calling
|
||||||
|
* convention here is that of a C varargs function with the
|
||||||
|
* first argument an 'int *' to the signal_pending flag, the
|
||||||
|
* second one the system call number (as a 'long'), and all further
|
||||||
|
* arguments being syscall arguments (also 'long').
|
||||||
|
*/
|
||||||
|
safe_syscall_base:
|
||||||
|
.fnstart
|
||||||
|
.cfi_startproc
|
||||||
|
mov r12, sp /* save entry stack */
|
||||||
|
push { r4, r5, r6, r7, r8, lr }
|
||||||
|
.save { r4, r5, r6, r7, r8, lr }
|
||||||
|
.cfi_adjust_cfa_offset 24
|
||||||
|
.cfi_rel_offset r4, 0
|
||||||
|
.cfi_rel_offset r5, 4
|
||||||
|
.cfi_rel_offset r6, 8
|
||||||
|
.cfi_rel_offset r7, 12
|
||||||
|
.cfi_rel_offset r8, 16
|
||||||
|
.cfi_rel_offset lr, 20
|
||||||
|
|
||||||
|
/* The syscall calling convention isn't the same as the C one:
|
||||||
|
* we enter with r0 == &signal_pending
|
||||||
|
* r1 == syscall number
|
||||||
|
* r2, r3, [sp+0] ... [sp+12] == syscall arguments
|
||||||
|
* and return the result in r0
|
||||||
|
* and the syscall instruction needs
|
||||||
|
* r7 == syscall number
|
||||||
|
* r0 ... r6 == syscall arguments
|
||||||
|
* and returns the result in r0
|
||||||
|
* Shuffle everything around appropriately.
|
||||||
|
* Note the 16 bytes that we pushed to save registers.
|
||||||
|
*/
|
||||||
|
mov r8, r0 /* copy signal_pending */
|
||||||
|
mov r7, r1 /* syscall number */
|
||||||
|
mov r0, r2 /* syscall args */
|
||||||
|
mov r1, r3
|
||||||
|
ldm r12, { r2, r3, r4, r5, r6 }
|
||||||
|
|
||||||
|
/* This next sequence of code works in conjunction with the
|
||||||
|
* rewind_if_safe_syscall_function(). If a signal is taken
|
||||||
|
* and the interrupted PC is anywhere between 'safe_syscall_start'
|
||||||
|
* and 'safe_syscall_end' then we rewind it to 'safe_syscall_start'.
|
||||||
|
* The code sequence must therefore be able to cope with this, and
|
||||||
|
* the syscall instruction must be the final one in the sequence.
|
||||||
|
*/
|
||||||
|
safe_syscall_start:
|
||||||
|
/* if signal_pending is non-zero, don't do the call */
|
||||||
|
ldr r12, [r8] /* signal_pending */
|
||||||
|
tst r12, r12
|
||||||
|
bne 2f
|
||||||
|
swi 0
|
||||||
|
safe_syscall_end:
|
||||||
|
|
||||||
|
/* code path for having successfully executed the syscall */
|
||||||
|
#if defined(__linux__)
|
||||||
|
/* Linux kernel returns (small) negative errno. */
|
||||||
|
cmp r0, #-4096
|
||||||
|
neghi r0, r0
|
||||||
|
bhi 1f
|
||||||
|
#elif defined(__FreeBSD__)
|
||||||
|
/* FreeBSD kernel returns positive errno and C bit set. */
|
||||||
|
bcs 1f
|
||||||
|
#else
|
||||||
|
#error "unsupported os"
|
||||||
|
#endif
|
||||||
|
pop { r4, r5, r6, r7, r8, pc }
|
||||||
|
|
||||||
|
/* code path when we didn't execute the syscall */
|
||||||
|
2: mov r0, #QEMU_ERESTARTSYS
|
||||||
|
|
||||||
|
/* code path setting errno */
|
||||||
|
1: pop { r4, r5, r6, r7, r8, lr }
|
||||||
|
.cfi_adjust_cfa_offset -24
|
||||||
|
.cfi_restore r4
|
||||||
|
.cfi_restore r5
|
||||||
|
.cfi_restore r6
|
||||||
|
.cfi_restore r7
|
||||||
|
.cfi_restore r8
|
||||||
|
.cfi_restore lr
|
||||||
|
b safe_syscall_set_errno_tail
|
||||||
|
|
||||||
|
.fnend
|
||||||
|
.cfi_endproc
|
||||||
|
.size safe_syscall_base, .-safe_syscall_base
|
126
common-user/host/i386/safe-syscall.inc.S
Normal file
126
common-user/host/i386/safe-syscall.inc.S
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
/*
|
||||||
|
* safe-syscall.inc.S : host-specific assembly fragment
|
||||||
|
* to handle signals occurring at the same time as system calls.
|
||||||
|
* This is intended to be included by common-user/safe-syscall.S
|
||||||
|
*
|
||||||
|
* Written by Richard Henderson <rth@twiddle.net>
|
||||||
|
* Copyright (C) 2016 Red Hat, Inc.
|
||||||
|
*
|
||||||
|
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||||
|
* See the COPYING file in the top-level directory.
|
||||||
|
*/
|
||||||
|
|
||||||
|
.global safe_syscall_base
|
||||||
|
.global safe_syscall_start
|
||||||
|
.global safe_syscall_end
|
||||||
|
.type safe_syscall_base, @function
|
||||||
|
|
||||||
|
/* This is the entry point for making a system call. The calling
|
||||||
|
* convention here is that of a C varargs function with the
|
||||||
|
* first argument an 'int *' to the signal_pending flag, the
|
||||||
|
* second one the system call number (as a 'long'), and all further
|
||||||
|
* arguments being syscall arguments (also 'long').
|
||||||
|
*/
|
||||||
|
safe_syscall_base:
|
||||||
|
.cfi_startproc
|
||||||
|
push %ebp
|
||||||
|
.cfi_adjust_cfa_offset 4
|
||||||
|
.cfi_rel_offset ebp, 0
|
||||||
|
push %esi
|
||||||
|
.cfi_adjust_cfa_offset 4
|
||||||
|
.cfi_rel_offset esi, 0
|
||||||
|
push %edi
|
||||||
|
.cfi_adjust_cfa_offset 4
|
||||||
|
.cfi_rel_offset edi, 0
|
||||||
|
push %ebx
|
||||||
|
.cfi_adjust_cfa_offset 4
|
||||||
|
.cfi_rel_offset ebx, 0
|
||||||
|
|
||||||
|
/* The syscall calling convention isn't the same as the C one:
|
||||||
|
* we enter with 0(%esp) == return address
|
||||||
|
* 4(%esp) == &signal_pending
|
||||||
|
* 8(%esp) == syscall number
|
||||||
|
* 12(%esp) ... 32(%esp) == syscall arguments
|
||||||
|
* and return the result in eax
|
||||||
|
* and the syscall instruction needs
|
||||||
|
* eax == syscall number
|
||||||
|
* ebx, ecx, edx, esi, edi, ebp == syscall arguments
|
||||||
|
* and returns the result in eax
|
||||||
|
* Shuffle everything around appropriately.
|
||||||
|
* Note the 16 bytes that we pushed to save registers.
|
||||||
|
*/
|
||||||
|
mov 12+16(%esp), %ebx /* the syscall arguments */
|
||||||
|
mov 16+16(%esp), %ecx
|
||||||
|
mov 20+16(%esp), %edx
|
||||||
|
mov 24+16(%esp), %esi
|
||||||
|
mov 28+16(%esp), %edi
|
||||||
|
mov 32+16(%esp), %ebp
|
||||||
|
|
||||||
|
/* This next sequence of code works in conjunction with the
|
||||||
|
* rewind_if_safe_syscall_function(). If a signal is taken
|
||||||
|
* and the interrupted PC is anywhere between 'safe_syscall_start'
|
||||||
|
* and 'safe_syscall_end' then we rewind it to 'safe_syscall_start'.
|
||||||
|
* The code sequence must therefore be able to cope with this, and
|
||||||
|
* the syscall instruction must be the final one in the sequence.
|
||||||
|
*/
|
||||||
|
safe_syscall_start:
|
||||||
|
/* if signal_pending is non-zero, don't do the call */
|
||||||
|
mov 4+16(%esp), %eax /* signal_pending */
|
||||||
|
cmpl $0, (%eax)
|
||||||
|
jnz 2f
|
||||||
|
mov 8+16(%esp), %eax /* syscall number */
|
||||||
|
int $0x80
|
||||||
|
safe_syscall_end:
|
||||||
|
|
||||||
|
/* code path for having successfully executed the syscall */
|
||||||
|
#if defined(__linux__)
|
||||||
|
/* Linux kernel returns (small) negative errno. */
|
||||||
|
cmp $-4095, %eax
|
||||||
|
jae 0f
|
||||||
|
#elif defined(__FreeBSD__)
|
||||||
|
/* FreeBSD kernel returns positive errno and C bit set. */
|
||||||
|
jc 1f
|
||||||
|
#else
|
||||||
|
#error "unsupported os"
|
||||||
|
#endif
|
||||||
|
pop %ebx
|
||||||
|
.cfi_remember_state
|
||||||
|
.cfi_adjust_cfa_offset -4
|
||||||
|
.cfi_restore ebx
|
||||||
|
pop %edi
|
||||||
|
.cfi_adjust_cfa_offset -4
|
||||||
|
.cfi_restore edi
|
||||||
|
pop %esi
|
||||||
|
.cfi_adjust_cfa_offset -4
|
||||||
|
.cfi_restore esi
|
||||||
|
pop %ebp
|
||||||
|
.cfi_adjust_cfa_offset -4
|
||||||
|
.cfi_restore ebp
|
||||||
|
ret
|
||||||
|
.cfi_restore_state
|
||||||
|
|
||||||
|
#if defined(__linux__)
|
||||||
|
0: neg %eax
|
||||||
|
jmp 1f
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* code path when we didn't execute the syscall */
|
||||||
|
2: mov $QEMU_ERESTARTSYS, %eax
|
||||||
|
|
||||||
|
/* code path setting errno */
|
||||||
|
1: pop %ebx
|
||||||
|
.cfi_adjust_cfa_offset -4
|
||||||
|
.cfi_restore ebx
|
||||||
|
pop %edi
|
||||||
|
.cfi_adjust_cfa_offset -4
|
||||||
|
.cfi_restore edi
|
||||||
|
pop %esi
|
||||||
|
.cfi_adjust_cfa_offset -4
|
||||||
|
.cfi_restore esi
|
||||||
|
pop %ebp
|
||||||
|
.cfi_adjust_cfa_offset -4
|
||||||
|
.cfi_restore ebp
|
||||||
|
jmp safe_syscall_set_errno_tail
|
||||||
|
|
||||||
|
.cfi_endproc
|
||||||
|
.size safe_syscall_base, .-safe_syscall_base
|
148
common-user/host/mips/safe-syscall.inc.S
Normal file
148
common-user/host/mips/safe-syscall.inc.S
Normal file
@ -0,0 +1,148 @@
|
|||||||
|
/*
|
||||||
|
* safe-syscall.inc.S : host-specific assembly fragment
|
||||||
|
* to handle signals occurring at the same time as system calls.
|
||||||
|
* This is intended to be included by common-user/safe-syscall.S
|
||||||
|
*
|
||||||
|
* Written by Richard Henderson <richard.henderson@linaro.org>
|
||||||
|
* Copyright (C) 2021 Linaro, Inc.
|
||||||
|
*
|
||||||
|
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||||
|
* See the COPYING file in the top-level directory.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "sys/regdef.h"
|
||||||
|
#include "sys/asm.h"
|
||||||
|
|
||||||
|
.text
|
||||||
|
.set nomips16
|
||||||
|
.set reorder
|
||||||
|
|
||||||
|
.global safe_syscall_start
|
||||||
|
.global safe_syscall_end
|
||||||
|
.type safe_syscall_start, @function
|
||||||
|
.type safe_syscall_end, @function
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is the entry point for making a system call. The calling
|
||||||
|
* convention here is that of a C varargs function with the
|
||||||
|
* first argument an 'int *' to the signal_pending flag, the
|
||||||
|
* second one the system call number (as a 'long'), and all further
|
||||||
|
* arguments being syscall arguments (also 'long').
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if _MIPS_SIM == _ABIO32
|
||||||
|
/* 8 * 4 = 32 for outgoing parameters; 1 * 4 for s0 save; 1 * 4 for align. */
|
||||||
|
#define FRAME 40
|
||||||
|
#define OFS_S0 32
|
||||||
|
#else
|
||||||
|
/* 1 * 8 for s0 save; 1 * 8 for align. */
|
||||||
|
#define FRAME 16
|
||||||
|
#define OFS_S0 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
NESTED(safe_syscall_base, FRAME, ra)
|
||||||
|
.cfi_startproc
|
||||||
|
PTR_ADDIU sp, sp, -FRAME
|
||||||
|
.cfi_adjust_cfa_offset FRAME
|
||||||
|
REG_S s0, OFS_S0(sp)
|
||||||
|
.cfi_rel_offset s0, OFS_S0
|
||||||
|
#if _MIPS_SIM == _ABIO32
|
||||||
|
/*
|
||||||
|
* The syscall calling convention is nearly the same as C:
|
||||||
|
* we enter with a0 == &signal_pending
|
||||||
|
* a1 == syscall number
|
||||||
|
* a2, a3, stack == syscall arguments
|
||||||
|
* and return the result in a0
|
||||||
|
* and the syscall instruction needs
|
||||||
|
* v0 == syscall number
|
||||||
|
* a0 ... a3, stack == syscall arguments
|
||||||
|
* and returns the result in v0
|
||||||
|
* Shuffle everything around appropriately.
|
||||||
|
*/
|
||||||
|
move s0, a0 /* signal_pending pointer */
|
||||||
|
move v0, a1 /* syscall number */
|
||||||
|
move a0, a2 /* syscall arguments */
|
||||||
|
move a1, a3
|
||||||
|
lw a2, FRAME+16(sp)
|
||||||
|
lw a3, FRAME+20(sp)
|
||||||
|
lw t4, FRAME+24(sp)
|
||||||
|
lw t5, FRAME+28(sp)
|
||||||
|
lw t6, FRAME+32(sp)
|
||||||
|
lw t7, FRAME+40(sp)
|
||||||
|
sw t4, 16(sp)
|
||||||
|
sw t5, 20(sp)
|
||||||
|
sw t6, 24(sp)
|
||||||
|
sw t7, 28(sp)
|
||||||
|
#else
|
||||||
|
/*
|
||||||
|
* The syscall calling convention is nearly the same as C:
|
||||||
|
* we enter with a0 == &signal_pending
|
||||||
|
* a1 == syscall number
|
||||||
|
* a2 ... a7 == syscall arguments
|
||||||
|
* and return the result in a0
|
||||||
|
* and the syscall instruction needs
|
||||||
|
* v0 == syscall number
|
||||||
|
* a0 ... a5 == syscall arguments
|
||||||
|
* and returns the result in v0
|
||||||
|
* Shuffle everything around appropriately.
|
||||||
|
*/
|
||||||
|
move s0, a0 /* signal_pending pointer */
|
||||||
|
move v0, a1 /* syscall number */
|
||||||
|
move a0, a2 /* syscall arguments */
|
||||||
|
move a1, a3
|
||||||
|
move a2, a4
|
||||||
|
move a3, a5
|
||||||
|
move a4, a6
|
||||||
|
move a5, a7
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This next sequence of code works in conjunction with the
|
||||||
|
* rewind_if_safe_syscall_function(). If a signal is taken
|
||||||
|
* and the interrupted PC is anywhere between 'safe_syscall_start'
|
||||||
|
* and 'safe_syscall_end' then we rewind it to 'safe_syscall_start'.
|
||||||
|
* The code sequence must therefore be able to cope with this, and
|
||||||
|
* the syscall instruction must be the final one in the sequence.
|
||||||
|
*/
|
||||||
|
safe_syscall_start:
|
||||||
|
/* If signal_pending is non-zero, don't do the call */
|
||||||
|
lw t1, 0(s0)
|
||||||
|
bnez t1, 2f
|
||||||
|
syscall
|
||||||
|
safe_syscall_end:
|
||||||
|
|
||||||
|
/* code path for having successfully executed the syscall */
|
||||||
|
REG_L s0, OFS_S0(sp)
|
||||||
|
PTR_ADDIU sp, sp, FRAME
|
||||||
|
.cfi_remember_state
|
||||||
|
.cfi_adjust_cfa_offset -FRAME
|
||||||
|
.cfi_restore s0
|
||||||
|
bnez a3, 1f
|
||||||
|
jr ra
|
||||||
|
.cfi_restore_state
|
||||||
|
|
||||||
|
/* code path when we didn't execute the syscall */
|
||||||
|
2: REG_L s0, OFS_S0(sp)
|
||||||
|
PTR_ADDIU sp, sp, FRAME
|
||||||
|
.cfi_adjust_cfa_offset -FRAME
|
||||||
|
.cfi_restore s0
|
||||||
|
li v0, QEMU_ERESTARTSYS
|
||||||
|
|
||||||
|
/* code path setting errno */
|
||||||
|
/*
|
||||||
|
* We didn't setup GP on entry, optimistic of the syscall success.
|
||||||
|
* We must do so now to load the address of the helper, as required
|
||||||
|
* by the ABI, into t9.
|
||||||
|
*
|
||||||
|
* Note that SETUP_GPX and SETUP_GPX64 are themselves conditional,
|
||||||
|
* so we can simply let the one that's not empty succeed.
|
||||||
|
*/
|
||||||
|
1: USE_ALT_CP(t0)
|
||||||
|
SETUP_GPX(t1)
|
||||||
|
SETUP_GPX64(t0, t1)
|
||||||
|
PTR_LA t9, safe_syscall_set_errno_tail
|
||||||
|
jr t9
|
||||||
|
|
||||||
|
.cfi_endproc
|
||||||
|
END(safe_syscall_base)
|
94
common-user/host/ppc64/safe-syscall.inc.S
Normal file
94
common-user/host/ppc64/safe-syscall.inc.S
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
/*
|
||||||
|
* safe-syscall.inc.S : host-specific assembly fragment
|
||||||
|
* to handle signals occurring at the same time as system calls.
|
||||||
|
* This is intended to be included by common-user/safe-syscall.S
|
||||||
|
*
|
||||||
|
* Written by Richard Henderson <rth@twiddle.net>
|
||||||
|
* Copyright (C) 2016 Red Hat, Inc.
|
||||||
|
*
|
||||||
|
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||||
|
* See the COPYING file in the top-level directory.
|
||||||
|
*/
|
||||||
|
|
||||||
|
.global safe_syscall_base
|
||||||
|
.global safe_syscall_start
|
||||||
|
.global safe_syscall_end
|
||||||
|
.type safe_syscall_base, @function
|
||||||
|
|
||||||
|
.text
|
||||||
|
|
||||||
|
/* This is the entry point for making a system call. The calling
|
||||||
|
* convention here is that of a C varargs function with the
|
||||||
|
* first argument an 'int *' to the signal_pending flag, the
|
||||||
|
* second one the system call number (as a 'long'), and all further
|
||||||
|
* arguments being syscall arguments (also 'long').
|
||||||
|
*/
|
||||||
|
#if _CALL_ELF == 2
|
||||||
|
safe_syscall_base:
|
||||||
|
.cfi_startproc
|
||||||
|
.localentry safe_syscall_base,0
|
||||||
|
#else
|
||||||
|
.section ".opd","aw"
|
||||||
|
.align 3
|
||||||
|
safe_syscall_base:
|
||||||
|
.quad .L.safe_syscall_base,.TOC.@tocbase,0
|
||||||
|
.previous
|
||||||
|
.L.safe_syscall_base:
|
||||||
|
.cfi_startproc
|
||||||
|
#endif
|
||||||
|
/* We enter with r3 == &signal_pending
|
||||||
|
* r4 == syscall number
|
||||||
|
* r5 ... r10 == syscall arguments
|
||||||
|
* and return the result in r3
|
||||||
|
* and the syscall instruction needs
|
||||||
|
* r0 == syscall number
|
||||||
|
* r3 ... r8 == syscall arguments
|
||||||
|
* and returns the result in r3
|
||||||
|
* Shuffle everything around appropriately.
|
||||||
|
*/
|
||||||
|
std 14, 16(1) /* Preserve r14 in SP+16 */
|
||||||
|
.cfi_offset 14, 16
|
||||||
|
mr 14, 3 /* signal_pending */
|
||||||
|
mr 0, 4 /* syscall number */
|
||||||
|
mr 3, 5 /* syscall arguments */
|
||||||
|
mr 4, 6
|
||||||
|
mr 5, 7
|
||||||
|
mr 6, 8
|
||||||
|
mr 7, 9
|
||||||
|
mr 8, 10
|
||||||
|
|
||||||
|
/* This next sequence of code works in conjunction with the
|
||||||
|
* rewind_if_safe_syscall_function(). If a signal is taken
|
||||||
|
* and the interrupted PC is anywhere between 'safe_syscall_start'
|
||||||
|
* and 'safe_syscall_end' then we rewind it to 'safe_syscall_start'.
|
||||||
|
* The code sequence must therefore be able to cope with this, and
|
||||||
|
* the syscall instruction must be the final one in the sequence.
|
||||||
|
*/
|
||||||
|
safe_syscall_start:
|
||||||
|
/* if signal_pending is non-zero, don't do the call */
|
||||||
|
lwz 12, 0(14)
|
||||||
|
cmpwi 0, 12, 0
|
||||||
|
bne- 2f
|
||||||
|
sc
|
||||||
|
safe_syscall_end:
|
||||||
|
/* code path when we did execute the syscall */
|
||||||
|
ld 14, 16(1) /* restore r14 */
|
||||||
|
bso- 1f
|
||||||
|
blr
|
||||||
|
|
||||||
|
/* code path when we didn't execute the syscall */
|
||||||
|
2: ld 14, 16(1) /* restore r14 */
|
||||||
|
addi 3, 0, QEMU_ERESTARTSYS
|
||||||
|
|
||||||
|
/* code path setting errno */
|
||||||
|
1: b safe_syscall_set_errno_tail
|
||||||
|
nop /* per abi, for the linker to modify */
|
||||||
|
|
||||||
|
.cfi_endproc
|
||||||
|
|
||||||
|
#if _CALL_ELF == 2
|
||||||
|
.size safe_syscall_base, .-safe_syscall_base
|
||||||
|
#else
|
||||||
|
.size safe_syscall_base, .-.L.safe_syscall_base
|
||||||
|
.size .L.safe_syscall_base, .-.L.safe_syscall_base
|
||||||
|
#endif
|
79
common-user/host/riscv/safe-syscall.inc.S
Normal file
79
common-user/host/riscv/safe-syscall.inc.S
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
/*
|
||||||
|
* safe-syscall.inc.S : host-specific assembly fragment
|
||||||
|
* to handle signals occurring at the same time as system calls.
|
||||||
|
* This is intended to be included by common-user/safe-syscall.S
|
||||||
|
*
|
||||||
|
* Written by Richard Henderson <rth@twiddle.net>
|
||||||
|
* Copyright (C) 2018 Linaro, Inc.
|
||||||
|
*
|
||||||
|
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||||
|
* See the COPYING file in the top-level directory.
|
||||||
|
*/
|
||||||
|
|
||||||
|
.global safe_syscall_base
|
||||||
|
.global safe_syscall_start
|
||||||
|
.global safe_syscall_end
|
||||||
|
.type safe_syscall_base, @function
|
||||||
|
.type safe_syscall_start, @function
|
||||||
|
.type safe_syscall_end, @function
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is the entry point for making a system call. The calling
|
||||||
|
* convention here is that of a C varargs function with the
|
||||||
|
* first argument an 'int *' to the signal_pending flag, the
|
||||||
|
* second one the system call number (as a 'long'), and all further
|
||||||
|
* arguments being syscall arguments (also 'long').
|
||||||
|
*/
|
||||||
|
safe_syscall_base:
|
||||||
|
.cfi_startproc
|
||||||
|
/*
|
||||||
|
* The syscall calling convention is nearly the same as C:
|
||||||
|
* we enter with a0 == &signal_pending
|
||||||
|
* a1 == syscall number
|
||||||
|
* a2 ... a7 == syscall arguments
|
||||||
|
* and return the result in a0
|
||||||
|
* and the syscall instruction needs
|
||||||
|
* a7 == syscall number
|
||||||
|
* a0 ... a5 == syscall arguments
|
||||||
|
* and returns the result in a0
|
||||||
|
* Shuffle everything around appropriately.
|
||||||
|
*/
|
||||||
|
mv t0, a0 /* signal_pending pointer */
|
||||||
|
mv t1, a1 /* syscall number */
|
||||||
|
mv a0, a2 /* syscall arguments */
|
||||||
|
mv a1, a3
|
||||||
|
mv a2, a4
|
||||||
|
mv a3, a5
|
||||||
|
mv a4, a6
|
||||||
|
mv a5, a7
|
||||||
|
mv a7, t1
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This next sequence of code works in conjunction with the
|
||||||
|
* rewind_if_safe_syscall_function(). If a signal is taken
|
||||||
|
* and the interrupted PC is anywhere between 'safe_syscall_start'
|
||||||
|
* and 'safe_syscall_end' then we rewind it to 'safe_syscall_start'.
|
||||||
|
* The code sequence must therefore be able to cope with this, and
|
||||||
|
* the syscall instruction must be the final one in the sequence.
|
||||||
|
*/
|
||||||
|
safe_syscall_start:
|
||||||
|
/* If signal_pending is non-zero, don't do the call */
|
||||||
|
lw t1, 0(t0)
|
||||||
|
bnez t1, 2f
|
||||||
|
scall
|
||||||
|
safe_syscall_end:
|
||||||
|
/* code path for having successfully executed the syscall */
|
||||||
|
li t2, -4096
|
||||||
|
bgtu a0, t2, 0f
|
||||||
|
ret
|
||||||
|
|
||||||
|
/* code path setting errno */
|
||||||
|
0: neg a0, a0
|
||||||
|
j safe_syscall_set_errno_tail
|
||||||
|
|
||||||
|
/* code path when we didn't execute the syscall */
|
||||||
|
2: li a0, QEMU_ERESTARTSYS
|
||||||
|
j safe_syscall_set_errno_tail
|
||||||
|
|
||||||
|
.cfi_endproc
|
||||||
|
.size safe_syscall_base, .-safe_syscall_base
|
98
common-user/host/s390x/safe-syscall.inc.S
Normal file
98
common-user/host/s390x/safe-syscall.inc.S
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
/*
|
||||||
|
* safe-syscall.inc.S : host-specific assembly fragment
|
||||||
|
* to handle signals occurring at the same time as system calls.
|
||||||
|
* This is intended to be included by common-user/safe-syscall.S
|
||||||
|
*
|
||||||
|
* Written by Richard Henderson <rth@twiddle.net>
|
||||||
|
* Copyright (C) 2016 Red Hat, Inc.
|
||||||
|
*
|
||||||
|
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||||
|
* See the COPYING file in the top-level directory.
|
||||||
|
*/
|
||||||
|
|
||||||
|
.global safe_syscall_base
|
||||||
|
.global safe_syscall_start
|
||||||
|
.global safe_syscall_end
|
||||||
|
.type safe_syscall_base, @function
|
||||||
|
|
||||||
|
/* This is the entry point for making a system call. The calling
|
||||||
|
* convention here is that of a C varargs function with the
|
||||||
|
* first argument an 'int *' to the signal_pending flag, the
|
||||||
|
* second one the system call number (as a 'long'), and all further
|
||||||
|
* arguments being syscall arguments (also 'long').
|
||||||
|
*/
|
||||||
|
safe_syscall_base:
|
||||||
|
.cfi_startproc
|
||||||
|
stmg %r6,%r15,48(%r15) /* save all call-saved registers */
|
||||||
|
.cfi_offset %r15,-40
|
||||||
|
.cfi_offset %r14,-48
|
||||||
|
.cfi_offset %r13,-56
|
||||||
|
.cfi_offset %r12,-64
|
||||||
|
.cfi_offset %r11,-72
|
||||||
|
.cfi_offset %r10,-80
|
||||||
|
.cfi_offset %r9,-88
|
||||||
|
.cfi_offset %r8,-96
|
||||||
|
.cfi_offset %r7,-104
|
||||||
|
.cfi_offset %r6,-112
|
||||||
|
lgr %r1,%r15
|
||||||
|
lg %r0,8(%r15) /* load eos */
|
||||||
|
aghi %r15,-160
|
||||||
|
.cfi_adjust_cfa_offset 160
|
||||||
|
stg %r1,0(%r15) /* store back chain */
|
||||||
|
stg %r0,8(%r15) /* store eos */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The syscall calling convention isn't the same as the C one:
|
||||||
|
* we enter with r2 == &signal_pending
|
||||||
|
* r3 == syscall number
|
||||||
|
* r4, r5, r6, (stack) == syscall arguments
|
||||||
|
* and return the result in r2
|
||||||
|
* and the syscall instruction needs
|
||||||
|
* r1 == syscall number
|
||||||
|
* r2 ... r7 == syscall arguments
|
||||||
|
* and returns the result in r2
|
||||||
|
* Shuffle everything around appropriately.
|
||||||
|
*/
|
||||||
|
lgr %r8,%r2 /* signal_pending pointer */
|
||||||
|
lgr %r1,%r3 /* syscall number */
|
||||||
|
lgr %r2,%r4 /* syscall args */
|
||||||
|
lgr %r3,%r5
|
||||||
|
lgr %r4,%r6
|
||||||
|
lmg %r5,%r7,320(%r15)
|
||||||
|
|
||||||
|
/* This next sequence of code works in conjunction with the
|
||||||
|
* rewind_if_safe_syscall_function(). If a signal is taken
|
||||||
|
* and the interrupted PC is anywhere between 'safe_syscall_start'
|
||||||
|
* and 'safe_syscall_end' then we rewind it to 'safe_syscall_start'.
|
||||||
|
* The code sequence must therefore be able to cope with this, and
|
||||||
|
* the syscall instruction must be the final one in the sequence.
|
||||||
|
*/
|
||||||
|
safe_syscall_start:
|
||||||
|
/* if signal_pending is non-zero, don't do the call */
|
||||||
|
icm %r0,15,0(%r8)
|
||||||
|
jne 2f
|
||||||
|
svc 0
|
||||||
|
safe_syscall_end:
|
||||||
|
|
||||||
|
/* code path for having successfully executed the syscall */
|
||||||
|
lg %r15,0(%r15) /* load back chain */
|
||||||
|
.cfi_remember_state
|
||||||
|
.cfi_adjust_cfa_offset -160
|
||||||
|
lmg %r6,%r15,48(%r15) /* load saved registers */
|
||||||
|
|
||||||
|
lghi %r0, -4095 /* check for syscall error */
|
||||||
|
clgr %r2, %r0
|
||||||
|
blr %r14 /* return on success */
|
||||||
|
lcr %r2, %r2 /* create positive errno */
|
||||||
|
jg safe_syscall_set_errno_tail
|
||||||
|
.cfi_restore_state
|
||||||
|
|
||||||
|
/* code path when we didn't execute the syscall */
|
||||||
|
2: lg %r15,0(%r15) /* load back chain */
|
||||||
|
.cfi_adjust_cfa_offset -160
|
||||||
|
lmg %r6,%r15,48(%r15) /* load saved registers */
|
||||||
|
lghi %r2, QEMU_ERESTARTSYS
|
||||||
|
jg safe_syscall_set_errno_tail
|
||||||
|
|
||||||
|
.cfi_endproc
|
||||||
|
.size safe_syscall_base, .-safe_syscall_base
|
89
common-user/host/sparc64/safe-syscall.inc.S
Normal file
89
common-user/host/sparc64/safe-syscall.inc.S
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
/*
|
||||||
|
* safe-syscall.inc.S : host-specific assembly fragment
|
||||||
|
* to handle signals occurring at the same time as system calls.
|
||||||
|
* This is intended to be included by common-user/safe-syscall.S
|
||||||
|
*
|
||||||
|
* Written by Richard Henderson <richard.henderson@linaro.org>
|
||||||
|
* Copyright (C) 2021 Linaro, Inc.
|
||||||
|
*
|
||||||
|
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||||
|
* See the COPYING file in the top-level directory.
|
||||||
|
*/
|
||||||
|
|
||||||
|
.text
|
||||||
|
.balign 4
|
||||||
|
|
||||||
|
.register %g2, #scratch
|
||||||
|
.register %g3, #scratch
|
||||||
|
|
||||||
|
.global safe_syscall_base
|
||||||
|
.global safe_syscall_start
|
||||||
|
.global safe_syscall_end
|
||||||
|
.type safe_syscall_base, @function
|
||||||
|
.type safe_syscall_start, @function
|
||||||
|
.type safe_syscall_end, @function
|
||||||
|
|
||||||
|
#define STACK_BIAS 2047
|
||||||
|
#define PARAM(N) STACK_BIAS + N*8
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is the entry point for making a system call. The calling
|
||||||
|
* convention here is that of a C varargs function with the
|
||||||
|
* first argument an 'int *' to the signal_pending flag, the
|
||||||
|
* second one the system call number (as a 'long'), and all further
|
||||||
|
* arguments being syscall arguments (also 'long').
|
||||||
|
*/
|
||||||
|
safe_syscall_base:
|
||||||
|
.cfi_startproc
|
||||||
|
/*
|
||||||
|
* The syscall calling convention isn't the same as the C one:
|
||||||
|
* we enter with o0 == &signal_pending
|
||||||
|
* o1 == syscall number
|
||||||
|
* o2 ... o5, (stack) == syscall arguments
|
||||||
|
* and return the result in x0
|
||||||
|
* and the syscall instruction needs
|
||||||
|
* g1 == syscall number
|
||||||
|
* o0 ... o5 == syscall arguments
|
||||||
|
* and returns the result in o0
|
||||||
|
* Shuffle everything around appropriately.
|
||||||
|
*/
|
||||||
|
mov %o0, %g2 /* signal_pending pointer */
|
||||||
|
mov %o1, %g1 /* syscall number */
|
||||||
|
mov %o2, %o0 /* syscall arguments */
|
||||||
|
mov %o3, %o1
|
||||||
|
mov %o4, %o2
|
||||||
|
mov %o5, %o3
|
||||||
|
ldx [%sp + PARAM(6)], %o4
|
||||||
|
ldx [%sp + PARAM(7)], %o5
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This next sequence of code works in conjunction with the
|
||||||
|
* rewind_if_safe_syscall_function(). If a signal is taken
|
||||||
|
* and the interrupted PC is anywhere between 'safe_syscall_start'
|
||||||
|
* and 'safe_syscall_end' then we rewind it to 'safe_syscall_start'.
|
||||||
|
* The code sequence must therefore be able to cope with this, and
|
||||||
|
* the syscall instruction must be the final one in the sequence.
|
||||||
|
*/
|
||||||
|
safe_syscall_start:
|
||||||
|
/* if signal_pending is non-zero, don't do the call */
|
||||||
|
lduw [%g2], %g3
|
||||||
|
brnz,pn %g3, 2f
|
||||||
|
nop
|
||||||
|
ta 0x6d
|
||||||
|
safe_syscall_end:
|
||||||
|
/* code path for having successfully executed the syscall */
|
||||||
|
bcs,pn %xcc, 1f
|
||||||
|
nop
|
||||||
|
ret
|
||||||
|
nop
|
||||||
|
|
||||||
|
/* code path when we didn't execute the syscall */
|
||||||
|
2: set QEMU_ERESTARTSYS, %o0
|
||||||
|
|
||||||
|
/* code path setting errno */
|
||||||
|
1: mov %o7, %g1
|
||||||
|
call safe_syscall_set_errno_tail
|
||||||
|
mov %g1, %o7
|
||||||
|
|
||||||
|
.cfi_endproc
|
||||||
|
.size safe_syscall_base, .-safe_syscall_base
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* safe-syscall.inc.S : host-specific assembly fragment
|
* safe-syscall.inc.S : host-specific assembly fragment
|
||||||
* to handle signals occurring at the same time as system calls.
|
* to handle signals occurring at the same time as system calls.
|
||||||
* This is intended to be included by linux-user/safe-syscall.S
|
* This is intended to be included by common-user/safe-syscall.S
|
||||||
*
|
*
|
||||||
* Copyright (C) 2015 Timothy Edward Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
|
* Copyright (C) 2015 Timothy Edward Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
|
||||||
*
|
*
|
||||||
@ -19,9 +19,6 @@
|
|||||||
* first argument an 'int *' to the signal_pending flag, the
|
* first argument an 'int *' to the signal_pending flag, the
|
||||||
* second one the system call number (as a 'long'), and all further
|
* second one the system call number (as a 'long'), and all further
|
||||||
* arguments being syscall arguments (also 'long').
|
* arguments being syscall arguments (also 'long').
|
||||||
* We return a long which is the syscall's return value, which
|
|
||||||
* may be negative-errno on failure. Conversion to the
|
|
||||||
* -1-and-errno-set convention is done by the calling wrapper.
|
|
||||||
*/
|
*/
|
||||||
safe_syscall_base:
|
safe_syscall_base:
|
||||||
.cfi_startproc
|
.cfi_startproc
|
||||||
@ -35,9 +32,9 @@ safe_syscall_base:
|
|||||||
.cfi_adjust_cfa_offset 8
|
.cfi_adjust_cfa_offset 8
|
||||||
.cfi_rel_offset rbp, 0
|
.cfi_rel_offset rbp, 0
|
||||||
|
|
||||||
/* The syscall calling convention isn't the same as the
|
/*
|
||||||
* C one:
|
* The syscall calling convention isn't the same as the C one:
|
||||||
* we enter with rdi == *signal_pending
|
* we enter with rdi == &signal_pending
|
||||||
* rsi == syscall number
|
* rsi == syscall number
|
||||||
* rdx, rcx, r8, r9, (stack), (stack) == syscall arguments
|
* rdx, rcx, r8, r9, (stack), (stack) == syscall arguments
|
||||||
* and return the result in rax
|
* and return the result in rax
|
||||||
@ -68,24 +65,41 @@ safe_syscall_base:
|
|||||||
safe_syscall_start:
|
safe_syscall_start:
|
||||||
/* if signal_pending is non-zero, don't do the call */
|
/* if signal_pending is non-zero, don't do the call */
|
||||||
cmpl $0, (%rbp)
|
cmpl $0, (%rbp)
|
||||||
jnz 1f
|
jnz 2f
|
||||||
syscall
|
syscall
|
||||||
safe_syscall_end:
|
safe_syscall_end:
|
||||||
|
|
||||||
/* code path for having successfully executed the syscall */
|
/* code path for having successfully executed the syscall */
|
||||||
|
#if defined(__linux__)
|
||||||
|
/* Linux kernel returns (small) negative errno. */
|
||||||
|
cmp $-4095, %rax
|
||||||
|
jae 0f
|
||||||
|
#elif defined(__FreeBSD__)
|
||||||
|
/* FreeBSD kernel returns positive errno and C bit set. */
|
||||||
|
jc 1f
|
||||||
|
#else
|
||||||
|
#error "unsupported os"
|
||||||
|
#endif
|
||||||
pop %rbp
|
pop %rbp
|
||||||
.cfi_remember_state
|
.cfi_remember_state
|
||||||
.cfi_def_cfa_offset 8
|
.cfi_def_cfa_offset 8
|
||||||
.cfi_restore rbp
|
.cfi_restore rbp
|
||||||
ret
|
ret
|
||||||
|
|
||||||
1:
|
|
||||||
/* code path when we didn't execute the syscall */
|
|
||||||
.cfi_restore_state
|
.cfi_restore_state
|
||||||
mov $-TARGET_ERESTARTSYS, %rax
|
|
||||||
pop %rbp
|
#if defined(__linux__)
|
||||||
|
0: neg %eax
|
||||||
|
jmp 1f
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* code path when we didn't execute the syscall */
|
||||||
|
2: mov $QEMU_ERESTARTSYS, %eax
|
||||||
|
|
||||||
|
/* code path setting errno */
|
||||||
|
1: pop %rbp
|
||||||
.cfi_def_cfa_offset 8
|
.cfi_def_cfa_offset 8
|
||||||
.cfi_restore rbp
|
.cfi_restore rbp
|
||||||
ret
|
jmp safe_syscall_set_errno_tail
|
||||||
.cfi_endproc
|
.cfi_endproc
|
||||||
|
|
||||||
.size safe_syscall_base, .-safe_syscall_base
|
.size safe_syscall_base, .-safe_syscall_base
|
6
common-user/meson.build
Normal file
6
common-user/meson.build
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
common_user_inc += include_directories('host/' / host_arch)
|
||||||
|
|
||||||
|
common_user_ss.add(files(
|
||||||
|
'safe-syscall.S',
|
||||||
|
'safe-syscall-error.c',
|
||||||
|
))
|
25
common-user/safe-syscall-error.c
Normal file
25
common-user/safe-syscall-error.c
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
/*
|
||||||
|
* safe-syscall-error.c: errno setting fragment
|
||||||
|
* This is intended to be invoked by safe-syscall.S
|
||||||
|
*
|
||||||
|
* Written by Richard Henderson <rth@twiddle.net>
|
||||||
|
* Copyright (C) 2021 Red Hat, Inc.
|
||||||
|
*
|
||||||
|
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||||
|
* See the COPYING file in the top-level directory.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "qemu/osdep.h"
|
||||||
|
#include "user/safe-syscall.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is intended to be invoked via tail-call on the error path
|
||||||
|
* from the assembly in host/arch/safe-syscall.inc.S. This takes
|
||||||
|
* care of the host specific addressing of errno.
|
||||||
|
* Return -1 to finalize the return value for safe_syscall_base.
|
||||||
|
*/
|
||||||
|
long safe_syscall_set_errno_tail(int value)
|
||||||
|
{
|
||||||
|
errno = value;
|
||||||
|
return -1;
|
||||||
|
}
|
@ -10,15 +10,12 @@
|
|||||||
* See the COPYING file in the top-level directory.
|
* See the COPYING file in the top-level directory.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "hostdep.h"
|
#include "special-errno.h"
|
||||||
#include "target_errno_defs.h"
|
|
||||||
|
|
||||||
/* We have the correct host directory on our include path
|
/* We have the correct host directory on our include path
|
||||||
* so that this will pull in the right fragment for the architecture.
|
* so that this will pull in the right fragment for the architecture.
|
||||||
*/
|
*/
|
||||||
#ifdef HAVE_SAFE_SYSCALL
|
|
||||||
#include "safe-syscall.inc.S"
|
#include "safe-syscall.inc.S"
|
||||||
#endif
|
|
||||||
|
|
||||||
/* We must specifically say that we're happy for the stack to not be
|
/* We must specifically say that we're happy for the stack to not be
|
||||||
* executable, otherwise the toolchain will default to assuming our
|
* executable, otherwise the toolchain will default to assuming our
|
287
configure
vendored
287
configure
vendored
@ -344,7 +344,6 @@ debug_stack_usage="no"
|
|||||||
crypto_afalg="no"
|
crypto_afalg="no"
|
||||||
tls_priority="NORMAL"
|
tls_priority="NORMAL"
|
||||||
tpm="$default_feature"
|
tpm="$default_feature"
|
||||||
libssh="$default_feature"
|
|
||||||
live_block_migration=${default_feature:-yes}
|
live_block_migration=${default_feature:-yes}
|
||||||
numa="$default_feature"
|
numa="$default_feature"
|
||||||
replication=${default_feature:-yes}
|
replication=${default_feature:-yes}
|
||||||
@ -502,42 +501,93 @@ EOF
|
|||||||
}
|
}
|
||||||
|
|
||||||
if check_define __linux__ ; then
|
if check_define __linux__ ; then
|
||||||
targetos="Linux"
|
targetos=linux
|
||||||
elif check_define _WIN32 ; then
|
elif check_define _WIN32 ; then
|
||||||
targetos='MINGW32'
|
targetos=windows
|
||||||
elif check_define __OpenBSD__ ; then
|
elif check_define __OpenBSD__ ; then
|
||||||
targetos='OpenBSD'
|
targetos=openbsd
|
||||||
elif check_define __sun__ ; then
|
elif check_define __sun__ ; then
|
||||||
targetos='SunOS'
|
targetos=sunos
|
||||||
elif check_define __HAIKU__ ; then
|
elif check_define __HAIKU__ ; then
|
||||||
targetos='Haiku'
|
targetos=haiku
|
||||||
elif check_define __FreeBSD__ ; then
|
elif check_define __FreeBSD__ ; then
|
||||||
targetos='FreeBSD'
|
targetos=freebsd
|
||||||
elif check_define __FreeBSD_kernel__ && check_define __GLIBC__; then
|
elif check_define __FreeBSD_kernel__ && check_define __GLIBC__; then
|
||||||
targetos='GNU/kFreeBSD'
|
targetos=gnu/kfreebsd
|
||||||
elif check_define __DragonFly__ ; then
|
elif check_define __DragonFly__ ; then
|
||||||
targetos='DragonFly'
|
targetos=dragonfly
|
||||||
elif check_define __NetBSD__; then
|
elif check_define __NetBSD__; then
|
||||||
targetos='NetBSD'
|
targetos=netbsd
|
||||||
elif check_define __APPLE__; then
|
elif check_define __APPLE__; then
|
||||||
targetos='Darwin'
|
targetos=darwin
|
||||||
else
|
else
|
||||||
# This is a fatal error, but don't report it yet, because we
|
# This is a fatal error, but don't report it yet, because we
|
||||||
# might be going to just print the --help text, or it might
|
# might be going to just print the --help text, or it might
|
||||||
# be the result of a missing compiler.
|
# be the result of a missing compiler.
|
||||||
targetos='bogus'
|
targetos=bogus
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Some host OSes need non-standard checks for which CPU to use.
|
# OS specific
|
||||||
# Note that these checks are broken for cross-compilation: if you're
|
|
||||||
# cross-compiling to one of these OSes then you'll need to specify
|
|
||||||
# the correct CPU with the --cpu option.
|
|
||||||
case $targetos in
|
case $targetos in
|
||||||
SunOS)
|
windows)
|
||||||
|
mingw32="yes"
|
||||||
|
plugins="no"
|
||||||
|
pie="no"
|
||||||
|
;;
|
||||||
|
gnu/kfreebsd)
|
||||||
|
bsd="yes"
|
||||||
|
;;
|
||||||
|
freebsd)
|
||||||
|
bsd="yes"
|
||||||
|
bsd_user="yes"
|
||||||
|
make="${MAKE-gmake}"
|
||||||
|
# needed for kinfo_getvmmap(3) in libutil.h
|
||||||
|
;;
|
||||||
|
dragonfly)
|
||||||
|
bsd="yes"
|
||||||
|
make="${MAKE-gmake}"
|
||||||
|
;;
|
||||||
|
netbsd)
|
||||||
|
bsd="yes"
|
||||||
|
make="${MAKE-gmake}"
|
||||||
|
;;
|
||||||
|
openbsd)
|
||||||
|
bsd="yes"
|
||||||
|
make="${MAKE-gmake}"
|
||||||
|
;;
|
||||||
|
darwin)
|
||||||
|
bsd="yes"
|
||||||
|
darwin="yes"
|
||||||
|
# Disable attempts to use ObjectiveC features in os/object.h since they
|
||||||
|
# won't work when we're compiling with gcc as a C compiler.
|
||||||
|
QEMU_CFLAGS="-DOS_OBJECT_USE_OBJC=0 $QEMU_CFLAGS"
|
||||||
|
;;
|
||||||
|
sunos)
|
||||||
|
solaris="yes"
|
||||||
|
make="${MAKE-gmake}"
|
||||||
|
smbd="${SMBD-/usr/sfw/sbin/smbd}"
|
||||||
|
# needed for CMSG_ macros in sys/socket.h
|
||||||
|
QEMU_CFLAGS="-D_XOPEN_SOURCE=600 $QEMU_CFLAGS"
|
||||||
|
# needed for TIOCWIN* defines in termios.h
|
||||||
|
QEMU_CFLAGS="-D__EXTENSIONS__ $QEMU_CFLAGS"
|
||||||
# $(uname -m) returns i86pc even on an x86_64 box, so default based on isainfo
|
# $(uname -m) returns i86pc even on an x86_64 box, so default based on isainfo
|
||||||
|
# Note that this check is broken for cross-compilation: if you're
|
||||||
|
# cross-compiling to one of these OSes then you'll need to specify
|
||||||
|
# the correct CPU with the --cpu option.
|
||||||
if test -z "$cpu" && test "$(isainfo -k)" = "amd64"; then
|
if test -z "$cpu" && test "$(isainfo -k)" = "amd64"; then
|
||||||
cpu="x86_64"
|
cpu="x86_64"
|
||||||
fi
|
fi
|
||||||
|
;;
|
||||||
|
haiku)
|
||||||
|
pie="no"
|
||||||
|
QEMU_CFLAGS="-DB_USE_POSITIVE_POSIX_ERRORS -D_BSD_SOURCE -fPIC $QEMU_CFLAGS"
|
||||||
|
;;
|
||||||
|
linux)
|
||||||
|
linux="yes"
|
||||||
|
linux_user="yes"
|
||||||
|
vhost_user=${default_feature:-yes}
|
||||||
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
if test ! -z "$cpu" ; then
|
if test ! -z "$cpu" ; then
|
||||||
@ -585,98 +635,46 @@ else
|
|||||||
cpu=$(uname -m)
|
cpu=$(uname -m)
|
||||||
fi
|
fi
|
||||||
|
|
||||||
ARCH=
|
# Normalise host CPU name, set multilib cflags
|
||||||
# Normalise host CPU name and set ARCH.
|
|
||||||
# Note that this case should only have supported host CPUs, not guests.
|
# Note that this case should only have supported host CPUs, not guests.
|
||||||
case "$cpu" in
|
case "$cpu" in
|
||||||
ppc|ppc64|s390x|sparc64|x32|riscv)
|
armv*b|armv*l|arm)
|
||||||
;;
|
cpu="arm" ;;
|
||||||
ppc64le)
|
|
||||||
ARCH="ppc64"
|
|
||||||
;;
|
|
||||||
i386|i486|i586|i686|i86pc|BePC)
|
i386|i486|i586|i686|i86pc|BePC)
|
||||||
cpu="i386"
|
cpu="i386"
|
||||||
;;
|
CPU_CFLAGS="-m32" ;;
|
||||||
|
x32)
|
||||||
|
cpu="x86_64"
|
||||||
|
CPU_CFLAGS="-mx32" ;;
|
||||||
x86_64|amd64)
|
x86_64|amd64)
|
||||||
cpu="x86_64"
|
cpu="x86_64"
|
||||||
;;
|
# ??? Only extremely old AMD cpus do not have cmpxchg16b.
|
||||||
armv*b|armv*l|arm)
|
# If we truly care, we should simply detect this case at
|
||||||
cpu="arm"
|
# runtime and generate the fallback to serial emulation.
|
||||||
;;
|
CPU_CFLAGS="-m64 -mcx16" ;;
|
||||||
aarch64)
|
|
||||||
cpu="aarch64"
|
|
||||||
;;
|
|
||||||
mips*)
|
mips*)
|
||||||
cpu="mips"
|
cpu="mips" ;;
|
||||||
;;
|
|
||||||
|
ppc)
|
||||||
|
CPU_CFLAGS="-m32" ;;
|
||||||
|
ppc64)
|
||||||
|
CPU_CFLAGS="-m64 -mbig" ;;
|
||||||
|
ppc64le)
|
||||||
|
cpu="ppc64"
|
||||||
|
CPU_CFLAGS="-m64 -mlittle" ;;
|
||||||
|
|
||||||
|
s390)
|
||||||
|
CPU_CFLAGS="-m31" ;;
|
||||||
|
s390x)
|
||||||
|
CPU_CFLAGS="-m64" ;;
|
||||||
|
|
||||||
sparc|sun4[cdmuv])
|
sparc|sun4[cdmuv])
|
||||||
cpu="sparc"
|
cpu="sparc"
|
||||||
;;
|
CPU_CFLAGS="-m32 -mv8plus -mcpu=ultrasparc" ;;
|
||||||
*)
|
sparc64)
|
||||||
# This will result in either an error or falling back to TCI later
|
CPU_CFLAGS="-m64 -mcpu=ultrasparc" ;;
|
||||||
ARCH=unknown
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
if test -z "$ARCH"; then
|
|
||||||
ARCH="$cpu"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# OS specific
|
|
||||||
|
|
||||||
case $targetos in
|
|
||||||
MINGW32*)
|
|
||||||
mingw32="yes"
|
|
||||||
supported_os="yes"
|
|
||||||
plugins="no"
|
|
||||||
pie="no"
|
|
||||||
;;
|
|
||||||
GNU/kFreeBSD)
|
|
||||||
bsd="yes"
|
|
||||||
;;
|
|
||||||
FreeBSD)
|
|
||||||
bsd="yes"
|
|
||||||
bsd_user="yes"
|
|
||||||
make="${MAKE-gmake}"
|
|
||||||
# needed for kinfo_getvmmap(3) in libutil.h
|
|
||||||
;;
|
|
||||||
DragonFly)
|
|
||||||
bsd="yes"
|
|
||||||
make="${MAKE-gmake}"
|
|
||||||
;;
|
|
||||||
NetBSD)
|
|
||||||
bsd="yes"
|
|
||||||
make="${MAKE-gmake}"
|
|
||||||
;;
|
|
||||||
OpenBSD)
|
|
||||||
bsd="yes"
|
|
||||||
make="${MAKE-gmake}"
|
|
||||||
;;
|
|
||||||
Darwin)
|
|
||||||
bsd="yes"
|
|
||||||
darwin="yes"
|
|
||||||
# Disable attempts to use ObjectiveC features in os/object.h since they
|
|
||||||
# won't work when we're compiling with gcc as a C compiler.
|
|
||||||
QEMU_CFLAGS="-DOS_OBJECT_USE_OBJC=0 $QEMU_CFLAGS"
|
|
||||||
;;
|
|
||||||
SunOS)
|
|
||||||
solaris="yes"
|
|
||||||
make="${MAKE-gmake}"
|
|
||||||
smbd="${SMBD-/usr/sfw/sbin/smbd}"
|
|
||||||
# needed for CMSG_ macros in sys/socket.h
|
|
||||||
QEMU_CFLAGS="-D_XOPEN_SOURCE=600 $QEMU_CFLAGS"
|
|
||||||
# needed for TIOCWIN* defines in termios.h
|
|
||||||
QEMU_CFLAGS="-D__EXTENSIONS__ $QEMU_CFLAGS"
|
|
||||||
;;
|
|
||||||
Haiku)
|
|
||||||
haiku="yes"
|
|
||||||
pie="no"
|
|
||||||
QEMU_CFLAGS="-DB_USE_POSITIVE_POSIX_ERRORS -D_BSD_SOURCE -fPIC $QEMU_CFLAGS"
|
|
||||||
;;
|
|
||||||
Linux)
|
|
||||||
linux="yes"
|
|
||||||
linux_user="yes"
|
|
||||||
vhost_user=${default_feature:-yes}
|
|
||||||
;;
|
|
||||||
esac
|
esac
|
||||||
|
|
||||||
: ${make=${MAKE-make}}
|
: ${make=${MAKE-make}}
|
||||||
@ -1080,10 +1078,6 @@ for opt do
|
|||||||
;;
|
;;
|
||||||
--enable-tpm) tpm="yes"
|
--enable-tpm) tpm="yes"
|
||||||
;;
|
;;
|
||||||
--disable-libssh) libssh="no"
|
|
||||||
;;
|
|
||||||
--enable-libssh) libssh="yes"
|
|
||||||
;;
|
|
||||||
--disable-live-block-migration) live_block_migration="no"
|
--disable-live-block-migration) live_block_migration="no"
|
||||||
;;
|
;;
|
||||||
--enable-live-block-migration) live_block_migration="yes"
|
--enable-live-block-migration) live_block_migration="yes"
|
||||||
@ -1276,24 +1270,6 @@ local_statedir="${local_statedir:-$prefix/var}"
|
|||||||
firmwarepath="${firmwarepath:-$datadir/qemu-firmware}"
|
firmwarepath="${firmwarepath:-$datadir/qemu-firmware}"
|
||||||
localedir="${localedir:-$datadir/locale}"
|
localedir="${localedir:-$datadir/locale}"
|
||||||
|
|
||||||
case "$cpu" in
|
|
||||||
ppc) CPU_CFLAGS="-m32" ;;
|
|
||||||
ppc64) CPU_CFLAGS="-m64" ;;
|
|
||||||
sparc) CPU_CFLAGS="-m32 -mv8plus -mcpu=ultrasparc" ;;
|
|
||||||
sparc64) CPU_CFLAGS="-m64 -mcpu=ultrasparc" ;;
|
|
||||||
s390) CPU_CFLAGS="-m31" ;;
|
|
||||||
s390x) CPU_CFLAGS="-m64" ;;
|
|
||||||
i386) CPU_CFLAGS="-m32" ;;
|
|
||||||
x32) CPU_CFLAGS="-mx32" ;;
|
|
||||||
|
|
||||||
# ??? Only extremely old AMD cpus do not have cmpxchg16b.
|
|
||||||
# If we truly care, we should simply detect this case at
|
|
||||||
# runtime and generate the fallback to serial emulation.
|
|
||||||
x86_64) CPU_CFLAGS="-m64 -mcx16" ;;
|
|
||||||
|
|
||||||
# No special flags required for other host CPUs
|
|
||||||
esac
|
|
||||||
|
|
||||||
if eval test -z "\${cross_cc_$cpu}"; then
|
if eval test -z "\${cross_cc_$cpu}"; then
|
||||||
eval "cross_cc_${cpu}=\$cc"
|
eval "cross_cc_${cpu}=\$cc"
|
||||||
cross_cc_vars="$cross_cc_vars cross_cc_${cpu}"
|
cross_cc_vars="$cross_cc_vars cross_cc_${cpu}"
|
||||||
@ -1460,7 +1436,6 @@ cat << EOF
|
|||||||
live-block-migration Block migration in the main migration stream
|
live-block-migration Block migration in the main migration stream
|
||||||
coroutine-pool coroutine freelist (better performance)
|
coroutine-pool coroutine freelist (better performance)
|
||||||
tpm TPM support
|
tpm TPM support
|
||||||
libssh ssh block device support
|
|
||||||
numa libnuma support
|
numa libnuma support
|
||||||
avx2 AVX2 optimization support
|
avx2 AVX2 optimization support
|
||||||
avx512f AVX512F optimization support
|
avx512f AVX512F optimization support
|
||||||
@ -2573,21 +2548,6 @@ if test "$modules" = yes; then
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
##########################################
|
|
||||||
# libssh probe
|
|
||||||
if test "$libssh" != "no" ; then
|
|
||||||
if $pkg_config --exists "libssh >= 0.8.7"; then
|
|
||||||
libssh_cflags=$($pkg_config libssh --cflags)
|
|
||||||
libssh_libs=$($pkg_config libssh --libs)
|
|
||||||
libssh=yes
|
|
||||||
else
|
|
||||||
if test "$libssh" = "yes" ; then
|
|
||||||
error_exit "libssh required for --enable-libssh"
|
|
||||||
fi
|
|
||||||
libssh=no
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
##########################################
|
##########################################
|
||||||
# TPM emulation is only on POSIX
|
# TPM emulation is only on POSIX
|
||||||
|
|
||||||
@ -3369,8 +3329,8 @@ QEMU_GA_MSI_MINGW_DLL_PATH="$($pkg_config --variable=prefix glib-2.0)/bin"
|
|||||||
# Mac OS X ships with a broken assembler
|
# Mac OS X ships with a broken assembler
|
||||||
roms=
|
roms=
|
||||||
if { test "$cpu" = "i386" || test "$cpu" = "x86_64"; } && \
|
if { test "$cpu" = "i386" || test "$cpu" = "x86_64"; } && \
|
||||||
test "$targetos" != "Darwin" && test "$targetos" != "SunOS" && \
|
test "$targetos" != "darwin" && test "$targetos" != "sunos" && \
|
||||||
test "$targetos" != "Haiku" && test "$softmmu" = yes ; then
|
test "$targetos" != "haiku" && test "$softmmu" = yes ; then
|
||||||
# Different host OS linkers have different ideas about the name of the ELF
|
# Different host OS linkers have different ideas about the name of the ELF
|
||||||
# emulation. Linux and OpenBSD/amd64 use 'elf_i386'; FreeBSD uses the _fbsd
|
# emulation. Linux and OpenBSD/amd64 use 'elf_i386'; FreeBSD uses the _fbsd
|
||||||
# variant; OpenBSD/i386 uses the _obsd variant; and Windows uses i386pe.
|
# variant; OpenBSD/i386 uses the _obsd variant; and Windows uses i386pe.
|
||||||
@ -3447,8 +3407,6 @@ echo "GIT=$git" >> $config_host_mak
|
|||||||
echo "GIT_SUBMODULES=$git_submodules" >> $config_host_mak
|
echo "GIT_SUBMODULES=$git_submodules" >> $config_host_mak
|
||||||
echo "GIT_SUBMODULES_ACTION=$git_submodules_action" >> $config_host_mak
|
echo "GIT_SUBMODULES_ACTION=$git_submodules_action" >> $config_host_mak
|
||||||
|
|
||||||
echo "ARCH=$ARCH" >> $config_host_mak
|
|
||||||
|
|
||||||
if test "$debug_tcg" = "yes" ; then
|
if test "$debug_tcg" = "yes" ; then
|
||||||
echo "CONFIG_DEBUG_TCG=y" >> $config_host_mak
|
echo "CONFIG_DEBUG_TCG=y" >> $config_host_mak
|
||||||
fi
|
fi
|
||||||
@ -3484,9 +3442,6 @@ fi
|
|||||||
if test "$solaris" = "yes" ; then
|
if test "$solaris" = "yes" ; then
|
||||||
echo "CONFIG_SOLARIS=y" >> $config_host_mak
|
echo "CONFIG_SOLARIS=y" >> $config_host_mak
|
||||||
fi
|
fi
|
||||||
if test "$haiku" = "yes" ; then
|
|
||||||
echo "CONFIG_HAIKU=y" >> $config_host_mak
|
|
||||||
fi
|
|
||||||
if test "$static" = "yes" ; then
|
if test "$static" = "yes" ; then
|
||||||
echo "CONFIG_STATIC=y" >> $config_host_mak
|
echo "CONFIG_STATIC=y" >> $config_host_mak
|
||||||
fi
|
fi
|
||||||
@ -3648,12 +3603,6 @@ if test "$cmpxchg128" = "yes" ; then
|
|||||||
echo "CONFIG_CMPXCHG128=y" >> $config_host_mak
|
echo "CONFIG_CMPXCHG128=y" >> $config_host_mak
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if test "$libssh" = "yes" ; then
|
|
||||||
echo "CONFIG_LIBSSH=y" >> $config_host_mak
|
|
||||||
echo "LIBSSH_CFLAGS=$libssh_cflags" >> $config_host_mak
|
|
||||||
echo "LIBSSH_LIBS=$libssh_libs" >> $config_host_mak
|
|
||||||
fi
|
|
||||||
|
|
||||||
if test "$live_block_migration" = "yes" ; then
|
if test "$live_block_migration" = "yes" ; then
|
||||||
echo "CONFIG_LIVE_BLOCK_MIGRATION=y" >> $config_host_mak
|
echo "CONFIG_LIVE_BLOCK_MIGRATION=y" >> $config_host_mak
|
||||||
fi
|
fi
|
||||||
@ -3777,10 +3726,10 @@ fi
|
|||||||
if test "$linux" = "yes" ; then
|
if test "$linux" = "yes" ; then
|
||||||
mkdir -p linux-headers
|
mkdir -p linux-headers
|
||||||
case "$cpu" in
|
case "$cpu" in
|
||||||
i386|x86_64|x32)
|
i386|x86_64)
|
||||||
linux_arch=x86
|
linux_arch=x86
|
||||||
;;
|
;;
|
||||||
ppc|ppc64|ppc64le)
|
ppc|ppc64)
|
||||||
linux_arch=powerpc
|
linux_arch=powerpc
|
||||||
;;
|
;;
|
||||||
s390x)
|
s390x)
|
||||||
@ -3805,7 +3754,7 @@ fi
|
|||||||
|
|
||||||
for target in $target_list; do
|
for target in $target_list; do
|
||||||
target_dir="$target"
|
target_dir="$target"
|
||||||
target_name=$(echo $target | cut -d '-' -f 1)
|
target_name=$(echo $target | cut -d '-' -f 1)$EXESUF
|
||||||
mkdir -p $target_dir
|
mkdir -p $target_dir
|
||||||
case $target in
|
case $target in
|
||||||
*-user) symlink "../qemu-$target_name" "$target_dir/qemu-$target_name" ;;
|
*-user) symlink "../qemu-$target_name" "$target_dir/qemu-$target_name" ;;
|
||||||
@ -3832,7 +3781,6 @@ if test "$safe_stack" = "yes"; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# If we're using a separate build tree, set it up now.
|
# If we're using a separate build tree, set it up now.
|
||||||
# DIRS are directories which we simply mkdir in the build tree;
|
|
||||||
# LINKS are things to symlink back into the source tree
|
# LINKS are things to symlink back into the source tree
|
||||||
# (these can be both files and directories).
|
# (these can be both files and directories).
|
||||||
# Caution: do not add files or directories here using wildcards. This
|
# Caution: do not add files or directories here using wildcards. This
|
||||||
@ -3844,12 +3792,6 @@ fi
|
|||||||
# UNLINK is used to remove symlinks from older development versions
|
# UNLINK is used to remove symlinks from older development versions
|
||||||
# that might get into the way when doing "git update" without doing
|
# that might get into the way when doing "git update" without doing
|
||||||
# a "make distclean" in between.
|
# a "make distclean" in between.
|
||||||
DIRS="tests tests/tcg tests/qapi-schema tests/qtest/libqos"
|
|
||||||
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="Makefile"
|
||||||
LINKS="$LINKS tests/tcg/Makefile.target"
|
LINKS="$LINKS tests/tcg/Makefile.target"
|
||||||
LINKS="$LINKS pc-bios/optionrom/Makefile"
|
LINKS="$LINKS pc-bios/optionrom/Makefile"
|
||||||
@ -3871,16 +3813,15 @@ for bios_file in \
|
|||||||
$source_path/pc-bios/*.img \
|
$source_path/pc-bios/*.img \
|
||||||
$source_path/pc-bios/openbios-* \
|
$source_path/pc-bios/openbios-* \
|
||||||
$source_path/pc-bios/u-boot.* \
|
$source_path/pc-bios/u-boot.* \
|
||||||
$source_path/pc-bios/edk2-*.fd.bz2 \
|
|
||||||
$source_path/pc-bios/palcode-* \
|
$source_path/pc-bios/palcode-* \
|
||||||
$source_path/pc-bios/qemu_vga.ndrv
|
$source_path/pc-bios/qemu_vga.ndrv
|
||||||
|
|
||||||
do
|
do
|
||||||
LINKS="$LINKS pc-bios/$(basename $bios_file)"
|
LINKS="$LINKS pc-bios/$(basename $bios_file)"
|
||||||
done
|
done
|
||||||
mkdir -p $DIRS
|
|
||||||
for f in $LINKS ; do
|
for f in $LINKS ; do
|
||||||
if [ -e "$source_path/$f" ]; then
|
if [ -e "$source_path/$f" ]; then
|
||||||
|
mkdir -p `dirname ./$f`
|
||||||
symlink "$source_path/$f" "$f"
|
symlink "$source_path/$f" "$f"
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
@ -3954,27 +3895,13 @@ if test "$skip_meson" = no; then
|
|||||||
if test "$cross_compile" = "yes"; then
|
if test "$cross_compile" = "yes"; then
|
||||||
cross_arg="--cross-file config-meson.cross"
|
cross_arg="--cross-file config-meson.cross"
|
||||||
echo "[host_machine]" >> $cross
|
echo "[host_machine]" >> $cross
|
||||||
if test "$mingw32" = "yes" ; then
|
echo "system = '$targetos'" >> $cross
|
||||||
echo "system = 'windows'" >> $cross
|
case "$cpu" in
|
||||||
fi
|
|
||||||
if test "$linux" = "yes" ; then
|
|
||||||
echo "system = 'linux'" >> $cross
|
|
||||||
fi
|
|
||||||
if test "$darwin" = "yes" ; then
|
|
||||||
echo "system = 'darwin'" >> $cross
|
|
||||||
fi
|
|
||||||
case "$ARCH" in
|
|
||||||
i386)
|
i386)
|
||||||
echo "cpu_family = 'x86'" >> $cross
|
echo "cpu_family = 'x86'" >> $cross
|
||||||
;;
|
;;
|
||||||
x86_64|x32)
|
|
||||||
echo "cpu_family = 'x86_64'" >> $cross
|
|
||||||
;;
|
|
||||||
ppc64le)
|
|
||||||
echo "cpu_family = 'ppc64'" >> $cross
|
|
||||||
;;
|
|
||||||
*)
|
*)
|
||||||
echo "cpu_family = '$ARCH'" >> $cross
|
echo "cpu_family = '$cpu'" >> $cross
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
echo "cpu = '$cpu'" >> $cross
|
echo "cpu = '$cpu'" >> $cross
|
||||||
|
5
cpu.c
5
cpu.c
@ -318,12 +318,10 @@ void cpu_exec_realizefn(CPUState *cpu, Error **errp)
|
|||||||
if (!accel_cpu_realizefn(cpu, errp)) {
|
if (!accel_cpu_realizefn(cpu, errp)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#ifdef CONFIG_TCG
|
|
||||||
/* NB: errp parameter is unused currently */
|
/* NB: errp parameter is unused currently */
|
||||||
if (tcg_enabled()) {
|
if (tcg_enabled()) {
|
||||||
tcg_exec_realizefn(cpu, errp);
|
tcg_exec_realizefn(cpu, errp);
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_TCG */
|
|
||||||
|
|
||||||
#ifdef CONFIG_USER_ONLY
|
#ifdef CONFIG_USER_ONLY
|
||||||
assert(qdev_get_vmsd(DEVICE(cpu)) == NULL ||
|
assert(qdev_get_vmsd(DEVICE(cpu)) == NULL ||
|
||||||
@ -350,12 +348,9 @@ void cpu_exec_unrealizefn(CPUState *cpu)
|
|||||||
vmstate_unregister(NULL, &vmstate_cpu_common, cpu);
|
vmstate_unregister(NULL, &vmstate_cpu_common, cpu);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_TCG
|
|
||||||
/* NB: errp parameter is unused currently */
|
|
||||||
if (tcg_enabled()) {
|
if (tcg_enabled()) {
|
||||||
tcg_exec_unrealizefn(cpu);
|
tcg_exec_unrealizefn(cpu);
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_TCG */
|
|
||||||
|
|
||||||
cpu_list_remove(cpu);
|
cpu_list_remove(cpu);
|
||||||
}
|
}
|
||||||
|
@ -315,6 +315,15 @@ This machine is deprecated because we have enough AST2500 based OpenPOWER
|
|||||||
machines. It can be easily replaced by the ``witherspoon-bmc`` or the
|
machines. It can be easily replaced by the ``witherspoon-bmc`` or the
|
||||||
``romulus-bmc`` machines.
|
``romulus-bmc`` machines.
|
||||||
|
|
||||||
|
PPC 405 ``taihu`` machine (since 7.0)
|
||||||
|
'''''''''''''''''''''''''''''''''''''
|
||||||
|
|
||||||
|
The PPC 405 CPU is a system-on-a-chip, so all 405 machines are very similar,
|
||||||
|
except for some external periphery. However, the periphery of the ``taihu``
|
||||||
|
machine is hardly emulated at all (e.g. neither the LCD nor the USB part had
|
||||||
|
been implemented), so there is not much value added by this board. Use the
|
||||||
|
``ref405ep`` machine instead.
|
||||||
|
|
||||||
Backend options
|
Backend options
|
||||||
---------------
|
---------------
|
||||||
|
|
||||||
|
@ -179,7 +179,7 @@ Primary:
|
|||||||
|
|
||||||
Secondary:
|
Secondary:
|
||||||
-drive if=none,driver=raw,file.filename=1.raw,id=colo1 \
|
-drive if=none,driver=raw,file.filename=1.raw,id=colo1 \
|
||||||
-drive if=none,id=childs1,driver=replication,mode=secondary,top-id=childs1
|
-drive if=none,id=childs1,driver=replication,mode=secondary,top-id=top-disk1
|
||||||
file.file.filename=active_disk.qcow2,\
|
file.file.filename=active_disk.qcow2,\
|
||||||
file.driver=qcow2,\
|
file.driver=qcow2,\
|
||||||
file.backing.file.filename=hidden_disk.qcow2,\
|
file.backing.file.filename=hidden_disk.qcow2,\
|
||||||
|
@ -18,12 +18,12 @@ if sphinx_build.found()
|
|||||||
# This is a bit awkward but works: create a trivial document and
|
# This is a bit awkward but works: create a trivial document and
|
||||||
# try to run it with our configuration file (which enforces a
|
# try to run it with our configuration file (which enforces a
|
||||||
# version requirement). This will fail if sphinx-build is too old.
|
# version requirement). This will fail if sphinx-build is too old.
|
||||||
run_command('mkdir', ['-p', tmpdir / 'sphinx'])
|
run_command('mkdir', ['-p', tmpdir / 'sphinx'], check: true)
|
||||||
run_command('touch', [tmpdir / 'sphinx/index.rst'])
|
run_command('touch', [tmpdir / 'sphinx/index.rst'], check: true)
|
||||||
sphinx_build_test_out = run_command(SPHINX_ARGS + [
|
sphinx_build_test_out = run_command(SPHINX_ARGS + [
|
||||||
'-c', meson.current_source_dir(),
|
'-c', meson.current_source_dir(),
|
||||||
'-b', 'html', tmpdir / 'sphinx',
|
'-b', 'html', tmpdir / 'sphinx',
|
||||||
tmpdir / 'sphinx/out'])
|
tmpdir / 'sphinx/out'], check: false)
|
||||||
build_docs = (sphinx_build_test_out.returncode() == 0)
|
build_docs = (sphinx_build_test_out.returncode() == 0)
|
||||||
|
|
||||||
if not build_docs
|
if not build_docs
|
||||||
|
100
docs/specs/ppc-spapr-hcalls.rst
Normal file
100
docs/specs/ppc-spapr-hcalls.rst
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
sPAPR hypervisor calls
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
When used with the ``pseries`` machine type, ``qemu-system-ppc64`` implements
|
||||||
|
a set of hypervisor calls (a.k.a. hcalls) defined in the `Linux on Power
|
||||||
|
Architecture Reference document (LoPAR)
|
||||||
|
<https://cdn.openpowerfoundation.org/wp-content/uploads/2020/07/LoPAR-20200812.pdf>`_.
|
||||||
|
This document is a subset of the Power Architecture Platform Reference (PAPR+)
|
||||||
|
specification (IBM internal only), which is what PowerVM, the IBM proprietary
|
||||||
|
hypervisor, adheres to.
|
||||||
|
|
||||||
|
The subset in LoPAR is selected based on the requirements of Linux as a guest.
|
||||||
|
|
||||||
|
In addition to those calls, we have added our own private hypervisor
|
||||||
|
calls which are mostly used as a private interface between the firmware
|
||||||
|
running in the guest and QEMU.
|
||||||
|
|
||||||
|
All those hypercalls start at hcall number 0xf000 which correspond
|
||||||
|
to an implementation specific range in PAPR.
|
||||||
|
|
||||||
|
H_RTAS (0xf000)
|
||||||
|
^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
RTAS stands for Run-Time Abstraction Sercies and is a set of runtime services
|
||||||
|
generally provided by the firmware inside the guest to the operating system. It
|
||||||
|
predates the existence of hypervisors (it was originally an extension to Open
|
||||||
|
Firmware) and is still used by PAPR and LoPAR to provide various services that
|
||||||
|
are not performance sensitive.
|
||||||
|
|
||||||
|
We currently implement the RTAS services in QEMU itself. The actual RTAS
|
||||||
|
"firmware" blob in the guest is a small stub of a few instructions which
|
||||||
|
calls our private H_RTAS hypervisor call to pass the RTAS calls to QEMU.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
``r3``: ``H_RTAS (0xf000)``
|
||||||
|
|
||||||
|
``r4``: Guest physical address of RTAS parameter block.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
``H_SUCCESS``: Successfully called the RTAS function (RTAS result will have
|
||||||
|
been stored in the parameter block).
|
||||||
|
|
||||||
|
``H_PARAMETER``: Unknown token.
|
||||||
|
|
||||||
|
H_LOGICAL_MEMOP (0xf001)
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
When the guest runs in "real mode" (in powerpc terminology this means with MMU
|
||||||
|
disabled, i.e. guest effective address equals to guest physical address), it
|
||||||
|
only has access to a subset of memory and no I/Os.
|
||||||
|
|
||||||
|
PAPR and LoPAR provides a set of hypervisor calls to perform cacheable or
|
||||||
|
non-cacheable accesses to any guest physical addresses that the
|
||||||
|
guest can use in order to access IO devices while in real mode.
|
||||||
|
|
||||||
|
This is typically used by the firmware running in the guest.
|
||||||
|
|
||||||
|
However, doing a hypercall for each access is extremely inefficient
|
||||||
|
(even more so when running KVM) when accessing the frame buffer. In
|
||||||
|
that case, things like scrolling become unusably slow.
|
||||||
|
|
||||||
|
This hypercall allows the guest to request a "memory op" to be applied
|
||||||
|
to memory. The supported memory ops at this point are to copy a range
|
||||||
|
of memory (supports overlap of source and destination) and XOR which
|
||||||
|
is used by our SLOF firmware to invert the screen.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
``r3 ``: ``H_LOGICAL_MEMOP (0xf001)``
|
||||||
|
|
||||||
|
``r4``: Guest physical address of destination.
|
||||||
|
|
||||||
|
``r5``: Guest physical address of source.
|
||||||
|
|
||||||
|
``r6``: Individual element size, defined by the binary logarithm of the
|
||||||
|
desired size. Supported values are:
|
||||||
|
|
||||||
|
``0`` = 1 byte
|
||||||
|
|
||||||
|
``1`` = 2 bytes
|
||||||
|
|
||||||
|
``2`` = 4 bytes
|
||||||
|
|
||||||
|
``3`` = 8 bytes
|
||||||
|
|
||||||
|
``r7``: Number of elements.
|
||||||
|
|
||||||
|
``r8``: Operation. Supported values are:
|
||||||
|
|
||||||
|
``0``: copy
|
||||||
|
|
||||||
|
``1``: xor
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
``H_SUCCESS``: Success.
|
||||||
|
|
||||||
|
``H_PARAMETER``: Invalid argument.
|
@ -1,78 +0,0 @@
|
|||||||
When used with the "pseries" machine type, QEMU-system-ppc64 implements
|
|
||||||
a set of hypervisor calls using a subset of the server "PAPR" specification
|
|
||||||
(IBM internal at this point), which is also what IBM's proprietary hypervisor
|
|
||||||
adheres too.
|
|
||||||
|
|
||||||
The subset is selected based on the requirements of Linux as a guest.
|
|
||||||
|
|
||||||
In addition to those calls, we have added our own private hypervisor
|
|
||||||
calls which are mostly used as a private interface between the firmware
|
|
||||||
running in the guest and QEMU.
|
|
||||||
|
|
||||||
All those hypercalls start at hcall number 0xf000 which correspond
|
|
||||||
to an implementation specific range in PAPR.
|
|
||||||
|
|
||||||
- H_RTAS (0xf000)
|
|
||||||
|
|
||||||
RTAS is a set of runtime services generally provided by the firmware
|
|
||||||
inside the guest to the operating system. It predates the existence
|
|
||||||
of hypervisors (it was originally an extension to Open Firmware) and
|
|
||||||
is still used by PAPR to provide various services that aren't performance
|
|
||||||
sensitive.
|
|
||||||
|
|
||||||
We currently implement the RTAS services in QEMU itself. The actual RTAS
|
|
||||||
"firmware" blob in the guest is a small stub of a few instructions which
|
|
||||||
calls our private H_RTAS hypervisor call to pass the RTAS calls to QEMU.
|
|
||||||
|
|
||||||
Arguments:
|
|
||||||
|
|
||||||
r3 : H_RTAS (0xf000)
|
|
||||||
r4 : Guest physical address of RTAS parameter block
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
|
|
||||||
H_SUCCESS : Successfully called the RTAS function (RTAS result
|
|
||||||
will have been stored in the parameter block)
|
|
||||||
H_PARAMETER : Unknown token
|
|
||||||
|
|
||||||
- H_LOGICAL_MEMOP (0xf001)
|
|
||||||
|
|
||||||
When the guest runs in "real mode" (in powerpc lingua this means
|
|
||||||
with MMU disabled, ie guest effective == guest physical), it only
|
|
||||||
has access to a subset of memory and no IOs.
|
|
||||||
|
|
||||||
PAPR provides a set of hypervisor calls to perform cacheable or
|
|
||||||
non-cacheable accesses to any guest physical addresses that the
|
|
||||||
guest can use in order to access IO devices while in real mode.
|
|
||||||
|
|
||||||
This is typically used by the firmware running in the guest.
|
|
||||||
|
|
||||||
However, doing a hypercall for each access is extremely inefficient
|
|
||||||
(even more so when running KVM) when accessing the frame buffer. In
|
|
||||||
that case, things like scrolling become unusably slow.
|
|
||||||
|
|
||||||
This hypercall allows the guest to request a "memory op" to be applied
|
|
||||||
to memory. The supported memory ops at this point are to copy a range
|
|
||||||
of memory (supports overlap of source and destination) and XOR which
|
|
||||||
is used by our SLOF firmware to invert the screen.
|
|
||||||
|
|
||||||
Arguments:
|
|
||||||
|
|
||||||
r3: H_LOGICAL_MEMOP (0xf001)
|
|
||||||
r4: Guest physical address of destination
|
|
||||||
r5: Guest physical address of source
|
|
||||||
r6: Individual element size
|
|
||||||
0 = 1 byte
|
|
||||||
1 = 2 bytes
|
|
||||||
2 = 4 bytes
|
|
||||||
3 = 8 bytes
|
|
||||||
r7: Number of elements
|
|
||||||
r8: Operation
|
|
||||||
0 = copy
|
|
||||||
1 = xor
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
|
|
||||||
H_SUCCESS : Success
|
|
||||||
H_PARAMETER : Invalid argument
|
|
||||||
|
|
@ -14,6 +14,7 @@ AST2400 SoC based machines :
|
|||||||
|
|
||||||
- ``palmetto-bmc`` OpenPOWER Palmetto POWER8 BMC
|
- ``palmetto-bmc`` OpenPOWER Palmetto POWER8 BMC
|
||||||
- ``quanta-q71l-bmc`` OpenBMC Quanta BMC
|
- ``quanta-q71l-bmc`` OpenBMC Quanta BMC
|
||||||
|
- ``supermicrox11-bmc`` Supermicro X11 BMC
|
||||||
|
|
||||||
AST2500 SoC based machines :
|
AST2500 SoC based machines :
|
||||||
|
|
||||||
@ -21,12 +22,16 @@ AST2500 SoC based machines :
|
|||||||
- ``romulus-bmc`` OpenPOWER Romulus POWER9 BMC
|
- ``romulus-bmc`` OpenPOWER Romulus POWER9 BMC
|
||||||
- ``witherspoon-bmc`` OpenPOWER Witherspoon POWER9 BMC
|
- ``witherspoon-bmc`` OpenPOWER Witherspoon POWER9 BMC
|
||||||
- ``sonorapass-bmc`` OCP SonoraPass BMC
|
- ``sonorapass-bmc`` OCP SonoraPass BMC
|
||||||
- ``swift-bmc`` OpenPOWER Swift BMC POWER9
|
- ``swift-bmc`` OpenPOWER Swift BMC POWER9 (to be removed in v7.0)
|
||||||
|
- ``fp5280g2-bmc`` Inspur FP5280G2 BMC
|
||||||
|
- ``g220a-bmc`` Bytedance G220A BMC
|
||||||
|
|
||||||
AST2600 SoC based machines :
|
AST2600 SoC based machines :
|
||||||
|
|
||||||
- ``ast2600-evb`` Aspeed AST2600 Evaluation board (Cortex-A7)
|
- ``ast2600-evb`` Aspeed AST2600 Evaluation board (Cortex-A7)
|
||||||
- ``tacoma-bmc`` OpenPOWER Witherspoon POWER9 AST2600 BMC
|
- ``tacoma-bmc`` OpenPOWER Witherspoon POWER9 AST2600 BMC
|
||||||
|
- ``rainier-bmc`` IBM Rainier POWER10 BMC
|
||||||
|
- ``fuji-bmc`` Facebook Fuji BMC
|
||||||
|
|
||||||
Supported devices
|
Supported devices
|
||||||
-----------------
|
-----------------
|
||||||
@ -51,13 +56,13 @@ Supported devices
|
|||||||
* Front LEDs (PCA9552 on I2C bus)
|
* Front LEDs (PCA9552 on I2C bus)
|
||||||
* LPC Peripheral Controller (a subset of subdevices are supported)
|
* LPC Peripheral Controller (a subset of subdevices are supported)
|
||||||
* Hash/Crypto Engine (HACE) - Hash support only. TODO: HMAC and RSA
|
* Hash/Crypto Engine (HACE) - Hash support only. TODO: HMAC and RSA
|
||||||
|
* ADC
|
||||||
|
|
||||||
|
|
||||||
Missing devices
|
Missing devices
|
||||||
---------------
|
---------------
|
||||||
|
|
||||||
* Coprocessor support
|
* Coprocessor support
|
||||||
* ADC (out of tree implementation)
|
|
||||||
* PWM and Fan Controller
|
* PWM and Fan Controller
|
||||||
* Slave GPIO Controller
|
* Slave GPIO Controller
|
||||||
* Super I/O Controller
|
* Super I/O Controller
|
||||||
@ -73,16 +78,25 @@ Missing devices
|
|||||||
Boot options
|
Boot options
|
||||||
------------
|
------------
|
||||||
|
|
||||||
The Aspeed machines can be started using the ``-kernel`` option to
|
The Aspeed machines can be started using the ``-kernel`` and ``-dtb`` options
|
||||||
load a Linux kernel or from a firmware. Images can be downloaded from
|
to load a Linux kernel or from a firmware. Images can be downloaded from the
|
||||||
the OpenBMC jenkins :
|
OpenBMC jenkins :
|
||||||
|
|
||||||
https://jenkins.openbmc.org/job/ci-openbmc/lastSuccessfulBuild/distro=ubuntu,label=docker-builder
|
https://jenkins.openbmc.org/job/ci-openbmc/lastSuccessfulBuild/
|
||||||
|
|
||||||
or directly from the OpenBMC GitHub release repository :
|
or directly from the OpenBMC GitHub release repository :
|
||||||
|
|
||||||
https://github.com/openbmc/openbmc/releases
|
https://github.com/openbmc/openbmc/releases
|
||||||
|
|
||||||
|
To boot a kernel directly from a Linux build tree:
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
$ qemu-system-arm -M ast2600-evb -nographic \
|
||||||
|
-kernel arch/arm/boot/zImage \
|
||||||
|
-dtb arch/arm/boot/dts/aspeed-ast2600-evb.dtb \
|
||||||
|
-initrd rootfs.cpio
|
||||||
|
|
||||||
The image should be attached as an MTD drive. Run :
|
The image should be attached as an MTD drive. Run :
|
||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
@ -141,8 +141,7 @@ To launch a SGX guest:
|
|||||||
|qemu_system_x86| \\
|
|qemu_system_x86| \\
|
||||||
-cpu host,+sgx-provisionkey \\
|
-cpu host,+sgx-provisionkey \\
|
||||||
-object memory-backend-epc,id=mem1,size=64M,prealloc=on \\
|
-object memory-backend-epc,id=mem1,size=64M,prealloc=on \\
|
||||||
-object memory-backend-epc,id=mem2,size=28M \\
|
-M sgx-epc.0.memdev=mem1,sgx-epc.0.node=0
|
||||||
-M sgx-epc.0.memdev=mem1,sgx-epc.1.memdev=mem2
|
|
||||||
|
|
||||||
Utilizing SGX in the guest requires a kernel/OS with SGX support.
|
Utilizing SGX in the guest requires a kernel/OS with SGX support.
|
||||||
The support can be determined in guest by::
|
The support can be determined in guest by::
|
||||||
@ -152,8 +151,32 @@ The support can be determined in guest by::
|
|||||||
and SGX epc info by::
|
and SGX epc info by::
|
||||||
|
|
||||||
$ dmesg | grep sgx
|
$ dmesg | grep sgx
|
||||||
[ 1.242142] sgx: EPC section 0x180000000-0x181bfffff
|
[ 0.182807] sgx: EPC section 0x140000000-0x143ffffff
|
||||||
[ 1.242319] sgx: EPC section 0x181c00000-0x1837fffff
|
[ 0.183695] sgx: [Firmware Bug]: Unable to map EPC section to online node. Fallback to the NUMA node 0.
|
||||||
|
|
||||||
|
To launch a SGX numa guest:
|
||||||
|
|
||||||
|
.. parsed-literal::
|
||||||
|
|
||||||
|
|qemu_system_x86| \\
|
||||||
|
-cpu host,+sgx-provisionkey \\
|
||||||
|
-object memory-backend-ram,size=2G,host-nodes=0,policy=bind,id=node0 \\
|
||||||
|
-object memory-backend-epc,id=mem0,size=64M,prealloc=on,host-nodes=0,policy=bind \\
|
||||||
|
-numa node,nodeid=0,cpus=0-1,memdev=node0 \\
|
||||||
|
-object memory-backend-ram,size=2G,host-nodes=1,policy=bind,id=node1 \\
|
||||||
|
-object memory-backend-epc,id=mem1,size=28M,prealloc=on,host-nodes=1,policy=bind \\
|
||||||
|
-numa node,nodeid=1,cpus=2-3,memdev=node1 \\
|
||||||
|
-M sgx-epc.0.memdev=mem0,sgx-epc.0.node=0,sgx-epc.1.memdev=mem1,sgx-epc.1.node=1
|
||||||
|
|
||||||
|
and SGX epc numa info by::
|
||||||
|
|
||||||
|
$ dmesg | grep sgx
|
||||||
|
[ 0.369937] sgx: EPC section 0x180000000-0x183ffffff
|
||||||
|
[ 0.370259] sgx: EPC section 0x184000000-0x185bfffff
|
||||||
|
|
||||||
|
$ dmesg | grep SRAT
|
||||||
|
[ 0.009981] ACPI: SRAT: Node 0 PXM 0 [mem 0x180000000-0x183ffffff]
|
||||||
|
[ 0.009982] ACPI: SRAT: Node 1 PXM 1 [mem 0x184000000-0x185bfffff]
|
||||||
|
|
||||||
References
|
References
|
||||||
----------
|
----------
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
PowerNV family boards (``powernv8``, ``powernv9``)
|
PowerNV family boards (``powernv8``, ``powernv9``, ``powernv10``)
|
||||||
==================================================================
|
==================================================================
|
||||||
|
|
||||||
PowerNV (as Non-Virtualized) is the "baremetal" platform using the
|
PowerNV (as Non-Virtualized) is the "bare metal" platform using the
|
||||||
OPAL firmware. It runs Linux on IBM and OpenPOWER systems and it can
|
OPAL firmware. It runs Linux on IBM and OpenPOWER systems and it can
|
||||||
be used as an hypervisor OS, running KVM guests, or simply as a host
|
be used as an hypervisor OS, running KVM guests, or simply as a host
|
||||||
OS.
|
OS.
|
||||||
@ -16,16 +16,14 @@ Supported devices
|
|||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
* Multi processor support for POWER8, POWER8NVL and POWER9.
|
* Multi processor support for POWER8, POWER8NVL and POWER9.
|
||||||
* XSCOM, serial communication sideband bus to configure chiplets
|
* XSCOM, serial communication sideband bus to configure chiplets.
|
||||||
* Simple LPC Controller
|
* Simple LPC Controller.
|
||||||
* Processor Service Interface (PSI) Controller
|
* Processor Service Interface (PSI) Controller.
|
||||||
* Interrupt Controller, XICS (POWER8) and XIVE (POWER9)
|
* Interrupt Controller, XICS (POWER8) and XIVE (POWER9) and XIVE2 (Power10).
|
||||||
* POWER8 PHB3 PCIe Host bridge and POWER9 PHB4 PCIe Host bridge
|
* POWER8 PHB3 PCIe Host bridge and POWER9 PHB4 PCIe Host bridge.
|
||||||
* Simple OCC is an on-chip microcontroller used for power management
|
* Simple OCC is an on-chip micro-controller used for power management tasks.
|
||||||
tasks
|
* iBT device to handle BMC communication, with the internal BMC simulator
|
||||||
* iBT device to handle BMC communication, with the internal BMC
|
provided by QEMU or an external BMC such as an Aspeed QEMU machine.
|
||||||
simulator provided by QEMU or an external BMC such as an Aspeed
|
|
||||||
QEMU machine.
|
|
||||||
* PNOR containing the different firmware partitions.
|
* PNOR containing the different firmware partitions.
|
||||||
|
|
||||||
Missing devices
|
Missing devices
|
||||||
@ -33,31 +31,42 @@ Missing devices
|
|||||||
|
|
||||||
A lot is missing, among which :
|
A lot is missing, among which :
|
||||||
|
|
||||||
* POWER10 processor
|
* I2C controllers (yet to be merged).
|
||||||
* XIVE2 (POWER10) interrupt controller
|
* NPU/NPU2/NPU3 controllers.
|
||||||
* I2C controllers (yet to be merged)
|
* EEH support for PCIe Host bridge controllers.
|
||||||
* NPU/NPU2/NPU3 controllers
|
* NX controller.
|
||||||
* EEH support for PCIe Host bridge controllers
|
* VAS controller.
|
||||||
* NX controller
|
* chipTOD (Time Of Day).
|
||||||
* VAS controller
|
|
||||||
* chipTOD (Time Of Day)
|
|
||||||
* Self Boot Engine (SBE).
|
* Self Boot Engine (SBE).
|
||||||
* FSI bus
|
* FSI bus.
|
||||||
|
|
||||||
Firmware
|
Firmware
|
||||||
--------
|
--------
|
||||||
|
|
||||||
The OPAL firmware (OpenPower Abstraction Layer) for OpenPower systems
|
The OPAL firmware (OpenPower Abstraction Layer) for OpenPower systems
|
||||||
includes the runtime services ``skiboot`` and the bootloader kernel and
|
includes the runtime services ``skiboot`` and the bootloader kernel and
|
||||||
initramfs ``skiroot``. Source code can be found on GitHub:
|
initramfs ``skiroot``. Source code can be found on the `OpenPOWER account at
|
||||||
|
GitHub <https://github.com/open-power>`_.
|
||||||
|
|
||||||
https://github.com/open-power.
|
Prebuilt images of ``skiboot`` and ``skiroot`` are made available on the
|
||||||
|
`OpenPOWER <https://github.com/open-power/op-build/releases/>`__ site.
|
||||||
Prebuilt images of ``skiboot`` and ``skiroot`` are made available on the `OpenPOWER <https://github.com/open-power/op-build/releases/>`__ site.
|
|
||||||
|
|
||||||
QEMU includes a prebuilt image of ``skiboot`` which is updated when a
|
QEMU includes a prebuilt image of ``skiboot`` which is updated when a
|
||||||
more recent version is required by the models.
|
more recent version is required by the models.
|
||||||
|
|
||||||
|
Current acceleration status
|
||||||
|
---------------------------
|
||||||
|
|
||||||
|
KVM acceleration in Linux Power hosts is provided by the kvm-hv and
|
||||||
|
kvm-pr modules. kvm-hv is adherent to PAPR and it's not compliant with
|
||||||
|
powernv. kvm-pr in theory could be used as a valid accel option but
|
||||||
|
this isn't supported by kvm-pr at this moment.
|
||||||
|
|
||||||
|
To spare users from dealing with not so informative errors when attempting
|
||||||
|
to use accel=kvm, the powernv machine will throw an error informing that
|
||||||
|
KVM is not supported. This can be revisited in the future if kvm-pr (or
|
||||||
|
any other KVM alternative) is usable as KVM accel for this machine.
|
||||||
|
|
||||||
Boot options
|
Boot options
|
||||||
------------
|
------------
|
||||||
|
|
||||||
@ -83,6 +92,7 @@ and a SATA disk :
|
|||||||
|
|
||||||
Complex PCIe configuration
|
Complex PCIe configuration
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
Six PHBs are defined per chip (POWER9) but no default PCI layout is
|
Six PHBs are defined per chip (POWER9) but no default PCI layout is
|
||||||
provided (to be compatible with libvirt). One PCI device can be added
|
provided (to be compatible with libvirt). One PCI device can be added
|
||||||
on any of the available PCIe slots using command line options such as:
|
on any of the available PCIe slots using command line options such as:
|
||||||
@ -157,7 +167,7 @@ one on the command line :
|
|||||||
The files `palmetto-SDR.bin <http://www.kaod.org/qemu/powernv/palmetto-SDR.bin>`__
|
The files `palmetto-SDR.bin <http://www.kaod.org/qemu/powernv/palmetto-SDR.bin>`__
|
||||||
and `palmetto-FRU.bin <http://www.kaod.org/qemu/powernv/palmetto-FRU.bin>`__
|
and `palmetto-FRU.bin <http://www.kaod.org/qemu/powernv/palmetto-FRU.bin>`__
|
||||||
define a Sensor Data Record repository and a Field Replaceable Unit
|
define a Sensor Data Record repository and a Field Replaceable Unit
|
||||||
inventory for a palmetto BMC. They can be used to extend the QEMU BMC
|
inventory for a Palmetto BMC. They can be used to extend the QEMU BMC
|
||||||
simulator.
|
simulator.
|
||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
@ -189,4 +199,8 @@ CAVEATS
|
|||||||
-------
|
-------
|
||||||
|
|
||||||
* No support for multiple HW threads (SMT=1). Same as pseries.
|
* No support for multiple HW threads (SMT=1). Same as pseries.
|
||||||
* CPU can hang when doing intensive I/Os. Use ``-append powersave=off`` in that case.
|
|
||||||
|
Maintainer contact information
|
||||||
|
------------------------------
|
||||||
|
|
||||||
|
Cédric Le Goater <clg@kaod.org>
|
||||||
|
@ -1,12 +1,238 @@
|
|||||||
pSeries family boards (``pseries``)
|
pSeries family boards (``pseries``)
|
||||||
===================================
|
===================================
|
||||||
|
|
||||||
|
The Power machine para-virtualized environment described by the `Linux on Power
|
||||||
|
Architecture Reference document (LoPAR)
|
||||||
|
<https://openpowerfoundation.org/wp-content/uploads/2020/07/LoPAR-20200812.pdf>`_
|
||||||
|
is called pSeries. This environment is also known as sPAPR, System p guests, or
|
||||||
|
simply Power Linux guests (although it is capable of running other operating
|
||||||
|
systems, such as AIX).
|
||||||
|
|
||||||
|
Even though pSeries is designed to behave as a guest environment, it is also
|
||||||
|
capable of acting as a hypervisor OS, providing, on that role, nested
|
||||||
|
virtualization capabilities.
|
||||||
|
|
||||||
Supported devices
|
Supported devices
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
|
* Multi processor support for many Power processors generations: POWER7,
|
||||||
|
POWER7+, POWER8, POWER8NVL, POWER9, and Power10. Support for POWER5+ exists,
|
||||||
|
but its state is unknown.
|
||||||
|
* Interrupt Controller, XICS (POWER8) and XIVE (POWER9 and Power10)
|
||||||
|
* vPHB PCIe Host bridge.
|
||||||
|
* vscsi and vnet devices, compatible with the same devices available on a
|
||||||
|
PowerVM hypervisor with VIOS managing LPARs.
|
||||||
|
* Virtio based devices.
|
||||||
|
* PCIe device pass through.
|
||||||
|
|
||||||
Missing devices
|
Missing devices
|
||||||
---------------
|
---------------
|
||||||
|
|
||||||
|
* SPICE support.
|
||||||
|
|
||||||
Firmware
|
Firmware
|
||||||
--------
|
--------
|
||||||
|
|
||||||
|
`SLOF <https://github.com/aik/SLOF>`_ (Slimline Open Firmware) is an
|
||||||
|
implementation of the `IEEE 1275-1994, Standard for Boot (Initialization
|
||||||
|
Configuration) Firmware: Core Requirements and Practices
|
||||||
|
<https://standards.ieee.org/standard/1275-1994.html>`_.
|
||||||
|
|
||||||
|
QEMU includes a prebuilt image of SLOF which is updated when a more recent
|
||||||
|
version is required.
|
||||||
|
|
||||||
|
Build directions
|
||||||
|
----------------
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
./configure --target-list=ppc64-softmmu && make
|
||||||
|
|
||||||
|
Running instructions
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
Someone can select the pSeries machine type by running QEMU with the following
|
||||||
|
options:
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
qemu-system-ppc64 -M pseries <other QEMU arguments>
|
||||||
|
|
||||||
|
sPAPR devices
|
||||||
|
-------------
|
||||||
|
|
||||||
|
The sPAPR specification defines a set of para-virtualized devices, which are
|
||||||
|
also supported by the pSeries machine in QEMU and can be instantiated with the
|
||||||
|
``-device`` option:
|
||||||
|
|
||||||
|
* ``spapr-vlan`` : a virtual network interface.
|
||||||
|
* ``spapr-vscsi`` : a virtual SCSI disk interface.
|
||||||
|
* ``spapr-rng`` : a pseudo-device for passing random number generator data to the
|
||||||
|
guest (see the `H_RANDOM hypercall feature
|
||||||
|
<https://wiki.qemu.org/Features/HRandomHypercall>`_ for details).
|
||||||
|
* ``spapr-vty``: a virtual teletype.
|
||||||
|
* ``spapr-pci-host-bridge``: a PCI host bridge.
|
||||||
|
* ``tpm-spapr``: a Trusted Platform Module (TPM).
|
||||||
|
* ``spapr-tpm-proxy``: a TPM proxy.
|
||||||
|
|
||||||
|
These are compatible with the devices historically available for use when
|
||||||
|
running the IBM PowerVM hypervisor with LPARs.
|
||||||
|
|
||||||
|
However, since these devices have originally been specified with another
|
||||||
|
hypervisor and non-Linux guests in mind, you should use the virtio counterparts
|
||||||
|
(virtio-net, virtio-blk/scsi and virtio-rng for instance) if possible instead,
|
||||||
|
since they will most probably give you better performance with Linux guests in a
|
||||||
|
QEMU environment.
|
||||||
|
|
||||||
|
The pSeries machine in QEMU is always instantiated with the following devices:
|
||||||
|
|
||||||
|
* A NVRAM device (``spapr-nvram``).
|
||||||
|
* A virtual teletype (``spapr-vty``).
|
||||||
|
* A PCI host bridge (``spapr-pci-host-bridge``).
|
||||||
|
|
||||||
|
Hence, it is not needed to add them manually, unless you use the ``-nodefaults``
|
||||||
|
command line option in QEMU.
|
||||||
|
|
||||||
|
In the case of the default ``spapr-nvram`` device, if someone wants to make the
|
||||||
|
contents of the NVRAM device persistent, they will need to specify a PFLASH
|
||||||
|
device when starting QEMU, i.e. either use
|
||||||
|
``-drive if=pflash,file=<filename>,format=raw`` to set the default PFLASH
|
||||||
|
device, or specify one with an ID
|
||||||
|
(``-drive if=none,file=<filename>,format=raw,id=pfid``) and pass that ID to the
|
||||||
|
NVRAM device with ``-global spapr-nvram.drive=pfid``.
|
||||||
|
|
||||||
|
sPAPR specification
|
||||||
|
^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
The main source of documentation on the sPAPR standard is the `Linux on Power
|
||||||
|
Architecture Reference document (LoPAR)
|
||||||
|
<https://openpowerfoundation.org/wp-content/uploads/2020/07/LoPAR-20200812.pdf>`_.
|
||||||
|
However, documentation specific to QEMU's implementation of the specification
|
||||||
|
can also be found in QEMU documentation:
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:maxdepth: 1
|
||||||
|
|
||||||
|
../../specs/ppc-spapr-hcalls.rst
|
||||||
|
../../specs/ppc-spapr-numa.rst
|
||||||
|
../../specs/ppc-spapr-xive.rst
|
||||||
|
|
||||||
|
Other documentation available in QEMU docs directory:
|
||||||
|
|
||||||
|
* Hot plug (``/docs/specs/ppc-spapr-hotplug.txt``).
|
||||||
|
* Hypervisor calls needed by the Ultravisor
|
||||||
|
(``/docs/specs/ppc-spapr-uv-hcalls.txt``).
|
||||||
|
|
||||||
|
Switching between the KVM-PR and KVM-HV kernel module
|
||||||
|
-----------------------------------------------------
|
||||||
|
|
||||||
|
Currently, there are two implementations of KVM on Power, ``kvm_hv.ko`` and
|
||||||
|
``kvm_pr.ko``.
|
||||||
|
|
||||||
|
|
||||||
|
If a host supports both KVM modes, and both KVM kernel modules are loaded, it is
|
||||||
|
possible to switch between the two modes with the ``kvm-type`` parameter:
|
||||||
|
|
||||||
|
* Use ``qemu-system-ppc64 -M pseries,accel=kvm,kvm-type=PR`` to use the
|
||||||
|
``kvm_pr.ko`` kernel module.
|
||||||
|
* Use ``qemu-system-ppc64 -M pseries,accel=kvm,kvm-type=HV`` to use ``kvm_hv.ko``
|
||||||
|
instead.
|
||||||
|
|
||||||
|
KVM-PR
|
||||||
|
^^^^^^
|
||||||
|
|
||||||
|
KVM-PR uses the so-called **PR**\ oblem state of the PPC CPUs to run the guests,
|
||||||
|
i.e. the virtual machine is run in user mode and all privileged instructions
|
||||||
|
trap and have to be emulated by the host. That means you can run KVM-PR inside
|
||||||
|
a pSeries guest (or a PowerVM LPAR for that matter), and that is where it has
|
||||||
|
originated, as historically (prior to POWER7) it was not possible to run Linux
|
||||||
|
on hypervisor mode on a Power processor (this function was restricted to
|
||||||
|
PowerVM, the IBM proprietary hypervisor).
|
||||||
|
|
||||||
|
Because all privileged instructions are trapped, guests that use a lot of
|
||||||
|
privileged instructions run quite slow with KVM-PR. On the other hand, because
|
||||||
|
of that, this kernel module can run on pretty much every PPC hardware, and is
|
||||||
|
able to emulate a lot of guests CPUs. This module can even be used to run other
|
||||||
|
PowerPC guests like an emulated PowerMac.
|
||||||
|
|
||||||
|
As KVM-PR can be run inside a pSeries guest, it can also provide nested
|
||||||
|
virtualization capabilities (i.e. running a guest from within a guest).
|
||||||
|
|
||||||
|
It is important to notice that, as KVM-HV provides a much better execution
|
||||||
|
performance, maintenance work has been much more focused on it in the past
|
||||||
|
years. Maintenance for KVM-PR has been minimal.
|
||||||
|
|
||||||
|
In order to run KVM-PR guests with POWER9 processors, someone will need to start
|
||||||
|
QEMU with ``kernel_irqchip=off`` command line option.
|
||||||
|
|
||||||
|
KVM-HV
|
||||||
|
^^^^^^
|
||||||
|
|
||||||
|
KVM-HV uses the hypervisor mode of more recent Power processors, that allow
|
||||||
|
access to the bare metal hardware directly. Although POWER7 had this capability,
|
||||||
|
it was only starting with POWER8 that this was officially supported by IBM.
|
||||||
|
|
||||||
|
Originally, KVM-HV was only available when running on a PowerNV platform (a.k.a.
|
||||||
|
Power bare metal). Although it runs on a PowerNV platform, it can only be used
|
||||||
|
to start pSeries guests. As the pSeries guest doesn't have access to the
|
||||||
|
hypervisor mode of the Power CPU, it wasn't possible to run KVM-HV on a guest.
|
||||||
|
This limitation has been lifted, and now it is possible to run KVM-HV inside
|
||||||
|
pSeries guests as well, making nested virtualization possible with KVM-HV.
|
||||||
|
|
||||||
|
As KVM-HV has access to privileged instructions, guests that use a lot of these
|
||||||
|
can run much faster than with KVM-PR. On the other hand, the guest CPU has to be
|
||||||
|
of the same type as the host CPU this way, e.g. it is not possible to specify an
|
||||||
|
embedded PPC CPU for the guest with KVM-HV. However, there is at least the
|
||||||
|
possibility to run the guest in a backward-compatibility mode of the previous
|
||||||
|
CPUs generations, e.g. you can run a POWER7 guest on a POWER8 host by using
|
||||||
|
``-cpu POWER8,compat=power7`` as parameter to QEMU.
|
||||||
|
|
||||||
|
Modules support
|
||||||
|
---------------
|
||||||
|
|
||||||
|
As noticed in the sections above, each module can run in a different
|
||||||
|
environment. The following table shows with which environment each module can
|
||||||
|
run. As long as you are in a supported environment, you can run KVM-PR or KVM-HV
|
||||||
|
nested. Combinations not shown in the table are not available.
|
||||||
|
|
||||||
|
+--------------+------------+------+-------------------+----------+--------+
|
||||||
|
| Platform | Host type | Bits | Page table format | KVM-HV | KVM-PR |
|
||||||
|
+==============+============+======+===================+==========+========+
|
||||||
|
| PowerNV | bare metal | 32 | hash | no | yes |
|
||||||
|
| | | +-------------------+----------+--------+
|
||||||
|
| | | | radix | N/A | N/A |
|
||||||
|
| | +------+-------------------+----------+--------+
|
||||||
|
| | | 64 | hash | yes | yes |
|
||||||
|
| | | +-------------------+----------+--------+
|
||||||
|
| | | | radix | yes | no |
|
||||||
|
+--------------+------------+------+-------------------+----------+--------+
|
||||||
|
| pSeries [1]_ | PowerNV | 32 | hash | no | yes |
|
||||||
|
| | | +-------------------+----------+--------+
|
||||||
|
| | | | radix | N/A | N/A |
|
||||||
|
| | +------+-------------------+----------+--------+
|
||||||
|
| | | 64 | hash | no | yes |
|
||||||
|
| | | +-------------------+----------+--------+
|
||||||
|
| | | | radix | yes [2]_ | no |
|
||||||
|
| +------------+------+-------------------+----------+--------+
|
||||||
|
| | PowerVM | 32 | hash | no | yes |
|
||||||
|
| | | +-------------------+----------+--------+
|
||||||
|
| | | | radix | N/A | N/A |
|
||||||
|
| | +------+-------------------+----------+--------+
|
||||||
|
| | | 64 | hash | no | yes |
|
||||||
|
| | | +-------------------+----------+--------+
|
||||||
|
| | | | radix [3]_ | no | yes |
|
||||||
|
+--------------+------------+------+-------------------+----------+--------+
|
||||||
|
|
||||||
|
.. [1] On POWER9 DD2.1 processors, the page table format on the host and guest
|
||||||
|
must be the same.
|
||||||
|
|
||||||
|
.. [2] KVM-HV cannot run nested on POWER8 machines.
|
||||||
|
|
||||||
|
.. [3] Introduced on Power10 machines.
|
||||||
|
|
||||||
|
Maintainer contact information
|
||||||
|
------------------------------
|
||||||
|
|
||||||
|
Cédric Le Goater <clg@kaod.org>
|
||||||
|
|
||||||
|
Daniel Henrique Barboza <danielhb413@gmail.com>
|
||||||
|
10
dump/dump.c
10
dump/dump.c
@ -1293,14 +1293,6 @@ static size_t get_len_buf_out(size_t page_size, uint32_t flag_compress)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* check if the page is all 0
|
|
||||||
*/
|
|
||||||
static inline bool is_zero_page(const uint8_t *buf, size_t page_size)
|
|
||||||
{
|
|
||||||
return buffer_is_zero(buf, page_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void write_dump_pages(DumpState *s, Error **errp)
|
static void write_dump_pages(DumpState *s, Error **errp)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
@ -1357,7 +1349,7 @@ static void write_dump_pages(DumpState *s, Error **errp)
|
|||||||
*/
|
*/
|
||||||
while (get_next_page(&block_iter, &pfn_iter, &buf, s)) {
|
while (get_next_page(&block_iter, &pfn_iter, &buf, s)) {
|
||||||
/* check zero page */
|
/* check zero page */
|
||||||
if (is_zero_page(buf, s->dump_info.page_size)) {
|
if (buffer_is_zero(buf, s->dump_info.page_size)) {
|
||||||
ret = write_cache(&page_desc, &pd_zero, sizeof(PageDescriptor),
|
ret = write_cache(&page_desc, &pd_zero, sizeof(PageDescriptor),
|
||||||
false);
|
false);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
|
@ -19,7 +19,7 @@ static void partsN(return_nan)(FloatPartsN *a, float_status *s)
|
|||||||
{
|
{
|
||||||
switch (a->cls) {
|
switch (a->cls) {
|
||||||
case float_class_snan:
|
case float_class_snan:
|
||||||
float_raise(float_flag_invalid, s);
|
float_raise(float_flag_invalid | float_flag_invalid_snan, s);
|
||||||
if (s->default_nan_mode) {
|
if (s->default_nan_mode) {
|
||||||
parts_default_nan(a, s);
|
parts_default_nan(a, s);
|
||||||
} else {
|
} else {
|
||||||
@ -40,7 +40,7 @@ static FloatPartsN *partsN(pick_nan)(FloatPartsN *a, FloatPartsN *b,
|
|||||||
float_status *s)
|
float_status *s)
|
||||||
{
|
{
|
||||||
if (is_snan(a->cls) || is_snan(b->cls)) {
|
if (is_snan(a->cls) || is_snan(b->cls)) {
|
||||||
float_raise(float_flag_invalid, s);
|
float_raise(float_flag_invalid | float_flag_invalid_snan, s);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (s->default_nan_mode) {
|
if (s->default_nan_mode) {
|
||||||
@ -68,7 +68,7 @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
|
|||||||
int which;
|
int which;
|
||||||
|
|
||||||
if (unlikely(abc_mask & float_cmask_snan)) {
|
if (unlikely(abc_mask & float_cmask_snan)) {
|
||||||
float_raise(float_flag_invalid, s);
|
float_raise(float_flag_invalid | float_flag_invalid_snan, s);
|
||||||
}
|
}
|
||||||
|
|
||||||
which = pickNaNMulAdd(a->cls, b->cls, c->cls,
|
which = pickNaNMulAdd(a->cls, b->cls, c->cls,
|
||||||
@ -354,7 +354,7 @@ static FloatPartsN *partsN(addsub)(FloatPartsN *a, FloatPartsN *b,
|
|||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
/* Inf - Inf */
|
/* Inf - Inf */
|
||||||
float_raise(float_flag_invalid, s);
|
float_raise(float_flag_invalid | float_flag_invalid_isi, s);
|
||||||
parts_default_nan(a, s);
|
parts_default_nan(a, s);
|
||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
@ -423,7 +423,7 @@ static FloatPartsN *partsN(mul)(FloatPartsN *a, FloatPartsN *b,
|
|||||||
|
|
||||||
/* Inf * Zero == NaN */
|
/* Inf * Zero == NaN */
|
||||||
if (unlikely(ab_mask == float_cmask_infzero)) {
|
if (unlikely(ab_mask == float_cmask_infzero)) {
|
||||||
float_raise(float_flag_invalid, s);
|
float_raise(float_flag_invalid | float_flag_invalid_imz, s);
|
||||||
parts_default_nan(a, s);
|
parts_default_nan(a, s);
|
||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
@ -489,11 +489,13 @@ static FloatPartsN *partsN(muladd)(FloatPartsN *a, FloatPartsN *b,
|
|||||||
|
|
||||||
if (unlikely(ab_mask != float_cmask_normal)) {
|
if (unlikely(ab_mask != float_cmask_normal)) {
|
||||||
if (unlikely(ab_mask == float_cmask_infzero)) {
|
if (unlikely(ab_mask == float_cmask_infzero)) {
|
||||||
|
float_raise(float_flag_invalid | float_flag_invalid_imz, s);
|
||||||
goto d_nan;
|
goto d_nan;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ab_mask & float_cmask_inf) {
|
if (ab_mask & float_cmask_inf) {
|
||||||
if (c->cls == float_class_inf && a->sign != c->sign) {
|
if (c->cls == float_class_inf && a->sign != c->sign) {
|
||||||
|
float_raise(float_flag_invalid | float_flag_invalid_isi, s);
|
||||||
goto d_nan;
|
goto d_nan;
|
||||||
}
|
}
|
||||||
goto return_inf;
|
goto return_inf;
|
||||||
@ -566,7 +568,6 @@ static FloatPartsN *partsN(muladd)(FloatPartsN *a, FloatPartsN *b,
|
|||||||
goto finish_sign;
|
goto finish_sign;
|
||||||
|
|
||||||
d_nan:
|
d_nan:
|
||||||
float_raise(float_flag_invalid, s);
|
|
||||||
parts_default_nan(a, s);
|
parts_default_nan(a, s);
|
||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
@ -589,11 +590,13 @@ static FloatPartsN *partsN(div)(FloatPartsN *a, FloatPartsN *b,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* 0/0 or Inf/Inf => NaN */
|
/* 0/0 or Inf/Inf => NaN */
|
||||||
if (unlikely(ab_mask == float_cmask_zero) ||
|
if (unlikely(ab_mask == float_cmask_zero)) {
|
||||||
unlikely(ab_mask == float_cmask_inf)) {
|
float_raise(float_flag_invalid | float_flag_invalid_zdz, s);
|
||||||
float_raise(float_flag_invalid, s);
|
goto d_nan;
|
||||||
parts_default_nan(a, s);
|
}
|
||||||
return a;
|
if (unlikely(ab_mask == float_cmask_inf)) {
|
||||||
|
float_raise(float_flag_invalid | float_flag_invalid_idi, s);
|
||||||
|
goto d_nan;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* All the NaN cases */
|
/* All the NaN cases */
|
||||||
@ -624,6 +627,10 @@ static FloatPartsN *partsN(div)(FloatPartsN *a, FloatPartsN *b,
|
|||||||
float_raise(float_flag_divbyzero, s);
|
float_raise(float_flag_divbyzero, s);
|
||||||
a->cls = float_class_inf;
|
a->cls = float_class_inf;
|
||||||
return a;
|
return a;
|
||||||
|
|
||||||
|
d_nan:
|
||||||
|
parts_default_nan(a, s);
|
||||||
|
return a;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -862,7 +869,7 @@ static void partsN(sqrt)(FloatPartsN *a, float_status *status,
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
d_nan:
|
d_nan:
|
||||||
float_raise(float_flag_invalid, status);
|
float_raise(float_flag_invalid | float_flag_invalid_sqrt, status);
|
||||||
parts_default_nan(a, status);
|
parts_default_nan(a, status);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1042,13 +1049,15 @@ static int64_t partsN(float_to_sint)(FloatPartsN *p, FloatRoundMode rmode,
|
|||||||
|
|
||||||
switch (p->cls) {
|
switch (p->cls) {
|
||||||
case float_class_snan:
|
case float_class_snan:
|
||||||
|
flags |= float_flag_invalid_snan;
|
||||||
|
/* fall through */
|
||||||
case float_class_qnan:
|
case float_class_qnan:
|
||||||
flags = float_flag_invalid;
|
flags |= float_flag_invalid;
|
||||||
r = max;
|
r = max;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case float_class_inf:
|
case float_class_inf:
|
||||||
flags = float_flag_invalid;
|
flags = float_flag_invalid | float_flag_invalid_cvti;
|
||||||
r = p->sign ? min : max;
|
r = p->sign ? min : max;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -1070,11 +1079,11 @@ static int64_t partsN(float_to_sint)(FloatPartsN *p, FloatRoundMode rmode,
|
|||||||
if (r <= -(uint64_t)min) {
|
if (r <= -(uint64_t)min) {
|
||||||
r = -r;
|
r = -r;
|
||||||
} else {
|
} else {
|
||||||
flags = float_flag_invalid;
|
flags = float_flag_invalid | float_flag_invalid_cvti;
|
||||||
r = min;
|
r = min;
|
||||||
}
|
}
|
||||||
} else if (r > max) {
|
} else if (r > max) {
|
||||||
flags = float_flag_invalid;
|
flags = float_flag_invalid | float_flag_invalid_cvti;
|
||||||
r = max;
|
r = max;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -1107,13 +1116,15 @@ static uint64_t partsN(float_to_uint)(FloatPartsN *p, FloatRoundMode rmode,
|
|||||||
|
|
||||||
switch (p->cls) {
|
switch (p->cls) {
|
||||||
case float_class_snan:
|
case float_class_snan:
|
||||||
|
flags |= float_flag_invalid_snan;
|
||||||
|
/* fall through */
|
||||||
case float_class_qnan:
|
case float_class_qnan:
|
||||||
flags = float_flag_invalid;
|
flags |= float_flag_invalid;
|
||||||
r = max;
|
r = max;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case float_class_inf:
|
case float_class_inf:
|
||||||
flags = float_flag_invalid;
|
flags = float_flag_invalid | float_flag_invalid_cvti;
|
||||||
r = p->sign ? 0 : max;
|
r = p->sign ? 0 : max;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -1131,15 +1142,15 @@ static uint64_t partsN(float_to_uint)(FloatPartsN *p, FloatRoundMode rmode,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (p->sign) {
|
if (p->sign) {
|
||||||
flags = float_flag_invalid;
|
flags = float_flag_invalid | float_flag_invalid_cvti;
|
||||||
r = 0;
|
r = 0;
|
||||||
} else if (p->exp > DECOMPOSED_BINARY_POINT) {
|
} else if (p->exp > DECOMPOSED_BINARY_POINT) {
|
||||||
flags = float_flag_invalid;
|
flags = float_flag_invalid | float_flag_invalid_cvti;
|
||||||
r = max;
|
r = max;
|
||||||
} else {
|
} else {
|
||||||
r = p->frac_hi >> (DECOMPOSED_BINARY_POINT - p->exp);
|
r = p->frac_hi >> (DECOMPOSED_BINARY_POINT - p->exp);
|
||||||
if (r > max) {
|
if (r > max) {
|
||||||
flags = float_flag_invalid;
|
flags = float_flag_invalid | float_flag_invalid_cvti;
|
||||||
r = max;
|
r = max;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1334,7 +1345,9 @@ static FloatRelation partsN(compare)(FloatPartsN *a, FloatPartsN *b,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (unlikely(ab_mask & float_cmask_anynan)) {
|
if (unlikely(ab_mask & float_cmask_anynan)) {
|
||||||
if (!is_quiet || (ab_mask & float_cmask_snan)) {
|
if (ab_mask & float_cmask_snan) {
|
||||||
|
float_raise(float_flag_invalid | float_flag_invalid_snan, s);
|
||||||
|
} else if (!is_quiet) {
|
||||||
float_raise(float_flag_invalid, s);
|
float_raise(float_flag_invalid, s);
|
||||||
}
|
}
|
||||||
return float_relation_unordered;
|
return float_relation_unordered;
|
||||||
|
@ -506,7 +506,7 @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
|
|||||||
* the default NaN
|
* the default NaN
|
||||||
*/
|
*/
|
||||||
if (infzero && is_qnan(c_cls)) {
|
if (infzero && is_qnan(c_cls)) {
|
||||||
float_raise(float_flag_invalid, status);
|
float_raise(float_flag_invalid | float_flag_invalid_imz, status);
|
||||||
return 3;
|
return 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -533,7 +533,7 @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
|
|||||||
* case sets InvalidOp and returns the default NaN
|
* case sets InvalidOp and returns the default NaN
|
||||||
*/
|
*/
|
||||||
if (infzero) {
|
if (infzero) {
|
||||||
float_raise(float_flag_invalid, status);
|
float_raise(float_flag_invalid | float_flag_invalid_imz, status);
|
||||||
return 3;
|
return 3;
|
||||||
}
|
}
|
||||||
/* Prefer sNaN over qNaN, in the a, b, c order. */
|
/* Prefer sNaN over qNaN, in the a, b, c order. */
|
||||||
@ -556,7 +556,7 @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
|
|||||||
* case sets InvalidOp and returns the input value 'c'
|
* case sets InvalidOp and returns the input value 'c'
|
||||||
*/
|
*/
|
||||||
if (infzero) {
|
if (infzero) {
|
||||||
float_raise(float_flag_invalid, status);
|
float_raise(float_flag_invalid | float_flag_invalid_imz, status);
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
/* Prefer sNaN over qNaN, in the c, a, b order. */
|
/* Prefer sNaN over qNaN, in the c, a, b order. */
|
||||||
@ -580,7 +580,7 @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
|
|||||||
* a default NaN
|
* a default NaN
|
||||||
*/
|
*/
|
||||||
if (infzero) {
|
if (infzero) {
|
||||||
float_raise(float_flag_invalid, status);
|
float_raise(float_flag_invalid | float_flag_invalid_imz, status);
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -597,7 +597,7 @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
|
|||||||
#elif defined(TARGET_RISCV)
|
#elif defined(TARGET_RISCV)
|
||||||
/* For RISC-V, InvalidOp is set when multiplicands are Inf and zero */
|
/* For RISC-V, InvalidOp is set when multiplicands are Inf and zero */
|
||||||
if (infzero) {
|
if (infzero) {
|
||||||
float_raise(float_flag_invalid, status);
|
float_raise(float_flag_invalid | float_flag_invalid_imz, status);
|
||||||
}
|
}
|
||||||
return 3; /* default NaN */
|
return 3; /* default NaN */
|
||||||
#elif defined(TARGET_XTENSA)
|
#elif defined(TARGET_XTENSA)
|
||||||
@ -606,7 +606,7 @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
|
|||||||
* an input NaN if we have one (ie c).
|
* an input NaN if we have one (ie c).
|
||||||
*/
|
*/
|
||||||
if (infzero) {
|
if (infzero) {
|
||||||
float_raise(float_flag_invalid, status);
|
float_raise(float_flag_invalid | float_flag_invalid_imz, status);
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
if (status->use_first_nan) {
|
if (status->use_first_nan) {
|
||||||
|
114
fpu/softfloat.c
114
fpu/softfloat.c
@ -1693,6 +1693,50 @@ static float64 float64_round_pack_canonical(FloatParts64 *p,
|
|||||||
return float64_pack_raw(p);
|
return float64_pack_raw(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static float64 float64r32_round_pack_canonical(FloatParts64 *p,
|
||||||
|
float_status *s)
|
||||||
|
{
|
||||||
|
parts_uncanon(p, s, &float32_params);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* In parts_uncanon, we placed the fraction for float32 at the lsb.
|
||||||
|
* We need to adjust the fraction higher so that the least N bits are
|
||||||
|
* zero, and the fraction is adjacent to the float64 implicit bit.
|
||||||
|
*/
|
||||||
|
switch (p->cls) {
|
||||||
|
case float_class_normal:
|
||||||
|
if (unlikely(p->exp == 0)) {
|
||||||
|
/*
|
||||||
|
* The result is denormal for float32, but can be represented
|
||||||
|
* in normalized form for float64. Adjust, per canonicalize.
|
||||||
|
*/
|
||||||
|
int shift = frac_normalize(p);
|
||||||
|
p->exp = (float32_params.frac_shift -
|
||||||
|
float32_params.exp_bias - shift + 1 +
|
||||||
|
float64_params.exp_bias);
|
||||||
|
frac_shr(p, float64_params.frac_shift);
|
||||||
|
} else {
|
||||||
|
frac_shl(p, float32_params.frac_shift - float64_params.frac_shift);
|
||||||
|
p->exp += float64_params.exp_bias - float32_params.exp_bias;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case float_class_snan:
|
||||||
|
case float_class_qnan:
|
||||||
|
frac_shl(p, float32_params.frac_shift - float64_params.frac_shift);
|
||||||
|
p->exp = float64_params.exp_max;
|
||||||
|
break;
|
||||||
|
case float_class_inf:
|
||||||
|
p->exp = float64_params.exp_max;
|
||||||
|
break;
|
||||||
|
case float_class_zero:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
g_assert_not_reached();
|
||||||
|
}
|
||||||
|
|
||||||
|
return float64_pack_raw(p);
|
||||||
|
}
|
||||||
|
|
||||||
static void float128_unpack_canonical(FloatParts128 *p, float128 f,
|
static void float128_unpack_canonical(FloatParts128 *p, float128 f,
|
||||||
float_status *s)
|
float_status *s)
|
||||||
{
|
{
|
||||||
@ -1938,6 +1982,28 @@ float64_sub(float64 a, float64 b, float_status *s)
|
|||||||
return float64_addsub(a, b, s, hard_f64_sub, soft_f64_sub);
|
return float64_addsub(a, b, s, hard_f64_sub, soft_f64_sub);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static float64 float64r32_addsub(float64 a, float64 b, float_status *status,
|
||||||
|
bool subtract)
|
||||||
|
{
|
||||||
|
FloatParts64 pa, pb, *pr;
|
||||||
|
|
||||||
|
float64_unpack_canonical(&pa, a, status);
|
||||||
|
float64_unpack_canonical(&pb, b, status);
|
||||||
|
pr = parts_addsub(&pa, &pb, status, subtract);
|
||||||
|
|
||||||
|
return float64r32_round_pack_canonical(pr, status);
|
||||||
|
}
|
||||||
|
|
||||||
|
float64 float64r32_add(float64 a, float64 b, float_status *status)
|
||||||
|
{
|
||||||
|
return float64r32_addsub(a, b, status, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
float64 float64r32_sub(float64 a, float64 b, float_status *status)
|
||||||
|
{
|
||||||
|
return float64r32_addsub(a, b, status, true);
|
||||||
|
}
|
||||||
|
|
||||||
static bfloat16 QEMU_FLATTEN
|
static bfloat16 QEMU_FLATTEN
|
||||||
bfloat16_addsub(bfloat16 a, bfloat16 b, float_status *status, bool subtract)
|
bfloat16_addsub(bfloat16 a, bfloat16 b, float_status *status, bool subtract)
|
||||||
{
|
{
|
||||||
@ -2069,6 +2135,17 @@ float64_mul(float64 a, float64 b, float_status *s)
|
|||||||
f64_is_zon2, f64_addsubmul_post);
|
f64_is_zon2, f64_addsubmul_post);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float64 float64r32_mul(float64 a, float64 b, float_status *status)
|
||||||
|
{
|
||||||
|
FloatParts64 pa, pb, *pr;
|
||||||
|
|
||||||
|
float64_unpack_canonical(&pa, a, status);
|
||||||
|
float64_unpack_canonical(&pb, b, status);
|
||||||
|
pr = parts_mul(&pa, &pb, status);
|
||||||
|
|
||||||
|
return float64r32_round_pack_canonical(pr, status);
|
||||||
|
}
|
||||||
|
|
||||||
bfloat16 QEMU_FLATTEN
|
bfloat16 QEMU_FLATTEN
|
||||||
bfloat16_mul(bfloat16 a, bfloat16 b, float_status *status)
|
bfloat16_mul(bfloat16 a, bfloat16 b, float_status *status)
|
||||||
{
|
{
|
||||||
@ -2296,6 +2373,19 @@ float64_muladd(float64 xa, float64 xb, float64 xc, int flags, float_status *s)
|
|||||||
return soft_f64_muladd(ua.s, ub.s, uc.s, flags, s);
|
return soft_f64_muladd(ua.s, ub.s, uc.s, flags, s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float64 float64r32_muladd(float64 a, float64 b, float64 c,
|
||||||
|
int flags, float_status *status)
|
||||||
|
{
|
||||||
|
FloatParts64 pa, pb, pc, *pr;
|
||||||
|
|
||||||
|
float64_unpack_canonical(&pa, a, status);
|
||||||
|
float64_unpack_canonical(&pb, b, status);
|
||||||
|
float64_unpack_canonical(&pc, c, status);
|
||||||
|
pr = parts_muladd(&pa, &pb, &pc, flags, status);
|
||||||
|
|
||||||
|
return float64r32_round_pack_canonical(pr, status);
|
||||||
|
}
|
||||||
|
|
||||||
bfloat16 QEMU_FLATTEN bfloat16_muladd(bfloat16 a, bfloat16 b, bfloat16 c,
|
bfloat16 QEMU_FLATTEN bfloat16_muladd(bfloat16 a, bfloat16 b, bfloat16 c,
|
||||||
int flags, float_status *status)
|
int flags, float_status *status)
|
||||||
{
|
{
|
||||||
@ -2419,6 +2509,17 @@ float64_div(float64 a, float64 b, float_status *s)
|
|||||||
f64_div_pre, f64_div_post);
|
f64_div_pre, f64_div_post);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float64 float64r32_div(float64 a, float64 b, float_status *status)
|
||||||
|
{
|
||||||
|
FloatParts64 pa, pb, *pr;
|
||||||
|
|
||||||
|
float64_unpack_canonical(&pa, a, status);
|
||||||
|
float64_unpack_canonical(&pb, b, status);
|
||||||
|
pr = parts_div(&pa, &pb, status);
|
||||||
|
|
||||||
|
return float64r32_round_pack_canonical(pr, status);
|
||||||
|
}
|
||||||
|
|
||||||
bfloat16 QEMU_FLATTEN
|
bfloat16 QEMU_FLATTEN
|
||||||
bfloat16_div(bfloat16 a, bfloat16 b, float_status *status)
|
bfloat16_div(bfloat16 a, bfloat16 b, float_status *status)
|
||||||
{
|
{
|
||||||
@ -2543,8 +2644,10 @@ floatx80 floatx80_mod(floatx80 a, floatx80 b, float_status *status)
|
|||||||
static void parts_float_to_ahp(FloatParts64 *a, float_status *s)
|
static void parts_float_to_ahp(FloatParts64 *a, float_status *s)
|
||||||
{
|
{
|
||||||
switch (a->cls) {
|
switch (a->cls) {
|
||||||
case float_class_qnan:
|
|
||||||
case float_class_snan:
|
case float_class_snan:
|
||||||
|
float_raise(float_flag_invalid_snan, s);
|
||||||
|
/* fall through */
|
||||||
|
case float_class_qnan:
|
||||||
/*
|
/*
|
||||||
* There is no NaN in the destination format. Raise Invalid
|
* There is no NaN in the destination format. Raise Invalid
|
||||||
* and return a zero with the sign of the input NaN.
|
* and return a zero with the sign of the input NaN.
|
||||||
@ -4283,6 +4386,15 @@ float64 QEMU_FLATTEN float64_sqrt(float64 xa, float_status *s)
|
|||||||
return soft_f64_sqrt(ua.s, s);
|
return soft_f64_sqrt(ua.s, s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float64 float64r32_sqrt(float64 a, float_status *status)
|
||||||
|
{
|
||||||
|
FloatParts64 p;
|
||||||
|
|
||||||
|
float64_unpack_canonical(&p, a, status);
|
||||||
|
parts_sqrt(&p, status, &float64_params);
|
||||||
|
return float64r32_round_pack_canonical(&p, status);
|
||||||
|
}
|
||||||
|
|
||||||
bfloat16 QEMU_FLATTEN bfloat16_sqrt(bfloat16 a, float_status *status)
|
bfloat16 QEMU_FLATTEN bfloat16_sqrt(bfloat16 a, float_status *status)
|
||||||
{
|
{
|
||||||
FloatParts64 p;
|
FloatParts64 p;
|
||||||
|
83
gdbstub.c
83
gdbstub.c
@ -368,27 +368,10 @@ typedef struct GDBState {
|
|||||||
gdb_syscall_complete_cb current_syscall_cb;
|
gdb_syscall_complete_cb current_syscall_cb;
|
||||||
GString *str_buf;
|
GString *str_buf;
|
||||||
GByteArray *mem_buf;
|
GByteArray *mem_buf;
|
||||||
|
int sstep_flags;
|
||||||
|
int supported_sstep_flags;
|
||||||
} GDBState;
|
} GDBState;
|
||||||
|
|
||||||
/* By default use no IRQs and no timers while single stepping so as to
|
|
||||||
* make single stepping like an ICE HW step.
|
|
||||||
*/
|
|
||||||
static int sstep_flags = SSTEP_ENABLE|SSTEP_NOIRQ|SSTEP_NOTIMER;
|
|
||||||
|
|
||||||
/* Retrieves flags for single step mode. */
|
|
||||||
static int get_sstep_flags(void)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* In replay mode all events written into the log should be replayed.
|
|
||||||
* That is why NOIRQ flag is removed in this mode.
|
|
||||||
*/
|
|
||||||
if (replay_mode != REPLAY_MODE_NONE) {
|
|
||||||
return SSTEP_ENABLE;
|
|
||||||
} else {
|
|
||||||
return sstep_flags;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static GDBState gdbserver_state;
|
static GDBState gdbserver_state;
|
||||||
|
|
||||||
static void init_gdbserver_state(void)
|
static void init_gdbserver_state(void)
|
||||||
@ -399,6 +382,29 @@ static void init_gdbserver_state(void)
|
|||||||
gdbserver_state.str_buf = g_string_new(NULL);
|
gdbserver_state.str_buf = g_string_new(NULL);
|
||||||
gdbserver_state.mem_buf = g_byte_array_sized_new(MAX_PACKET_LENGTH);
|
gdbserver_state.mem_buf = g_byte_array_sized_new(MAX_PACKET_LENGTH);
|
||||||
gdbserver_state.last_packet = g_byte_array_sized_new(MAX_PACKET_LENGTH + 4);
|
gdbserver_state.last_packet = g_byte_array_sized_new(MAX_PACKET_LENGTH + 4);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* In replay mode all events will come from the log and can't be
|
||||||
|
* suppressed otherwise we would break determinism. However as those
|
||||||
|
* events are tied to the number of executed instructions we won't see
|
||||||
|
* them occurring every time we single step.
|
||||||
|
*/
|
||||||
|
if (replay_mode != REPLAY_MODE_NONE) {
|
||||||
|
gdbserver_state.supported_sstep_flags = SSTEP_ENABLE;
|
||||||
|
} else if (kvm_enabled()) {
|
||||||
|
gdbserver_state.supported_sstep_flags = kvm_get_supported_sstep_flags();
|
||||||
|
} else {
|
||||||
|
gdbserver_state.supported_sstep_flags =
|
||||||
|
SSTEP_ENABLE | SSTEP_NOIRQ | SSTEP_NOTIMER;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* By default use no IRQs and no timers while single stepping so as to
|
||||||
|
* make single stepping like an ICE HW step.
|
||||||
|
*/
|
||||||
|
gdbserver_state.sstep_flags = SSTEP_ENABLE | SSTEP_NOIRQ | SSTEP_NOTIMER;
|
||||||
|
gdbserver_state.sstep_flags &= gdbserver_state.supported_sstep_flags;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef CONFIG_USER_ONLY
|
#ifndef CONFIG_USER_ONLY
|
||||||
@ -505,7 +511,7 @@ static int gdb_continue_partial(char *newstates)
|
|||||||
CPU_FOREACH(cpu) {
|
CPU_FOREACH(cpu) {
|
||||||
if (newstates[cpu->cpu_index] == 's') {
|
if (newstates[cpu->cpu_index] == 's') {
|
||||||
trace_gdbstub_op_stepping(cpu->cpu_index);
|
trace_gdbstub_op_stepping(cpu->cpu_index);
|
||||||
cpu_single_step(cpu, sstep_flags);
|
cpu_single_step(cpu, gdbserver_state.sstep_flags);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
gdbserver_state.running_state = 1;
|
gdbserver_state.running_state = 1;
|
||||||
@ -524,7 +530,7 @@ static int gdb_continue_partial(char *newstates)
|
|||||||
break; /* nothing to do here */
|
break; /* nothing to do here */
|
||||||
case 's':
|
case 's':
|
||||||
trace_gdbstub_op_stepping(cpu->cpu_index);
|
trace_gdbstub_op_stepping(cpu->cpu_index);
|
||||||
cpu_single_step(cpu, get_sstep_flags());
|
cpu_single_step(cpu, gdbserver_state.sstep_flags);
|
||||||
cpu_resume(cpu);
|
cpu_resume(cpu);
|
||||||
flag = 1;
|
flag = 1;
|
||||||
break;
|
break;
|
||||||
@ -1883,7 +1889,7 @@ static void handle_step(GArray *params, void *user_ctx)
|
|||||||
gdb_set_cpu_pc((target_ulong)get_param(params, 0)->val_ull);
|
gdb_set_cpu_pc((target_ulong)get_param(params, 0)->val_ull);
|
||||||
}
|
}
|
||||||
|
|
||||||
cpu_single_step(gdbserver_state.c_cpu, get_sstep_flags());
|
cpu_single_step(gdbserver_state.c_cpu, gdbserver_state.sstep_flags);
|
||||||
gdb_continue();
|
gdb_continue();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2017,24 +2023,44 @@ static void handle_v_commands(GArray *params, void *user_ctx)
|
|||||||
|
|
||||||
static void handle_query_qemu_sstepbits(GArray *params, void *user_ctx)
|
static void handle_query_qemu_sstepbits(GArray *params, void *user_ctx)
|
||||||
{
|
{
|
||||||
g_string_printf(gdbserver_state.str_buf, "ENABLE=%x,NOIRQ=%x,NOTIMER=%x",
|
g_string_printf(gdbserver_state.str_buf, "ENABLE=%x", SSTEP_ENABLE);
|
||||||
SSTEP_ENABLE, SSTEP_NOIRQ, SSTEP_NOTIMER);
|
|
||||||
|
if (gdbserver_state.supported_sstep_flags & SSTEP_NOIRQ) {
|
||||||
|
g_string_append_printf(gdbserver_state.str_buf, ",NOIRQ=%x",
|
||||||
|
SSTEP_NOIRQ);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gdbserver_state.supported_sstep_flags & SSTEP_NOTIMER) {
|
||||||
|
g_string_append_printf(gdbserver_state.str_buf, ",NOTIMER=%x",
|
||||||
|
SSTEP_NOTIMER);
|
||||||
|
}
|
||||||
|
|
||||||
put_strbuf();
|
put_strbuf();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handle_set_qemu_sstep(GArray *params, void *user_ctx)
|
static void handle_set_qemu_sstep(GArray *params, void *user_ctx)
|
||||||
{
|
{
|
||||||
|
int new_sstep_flags;
|
||||||
|
|
||||||
if (!params->len) {
|
if (!params->len) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
sstep_flags = get_param(params, 0)->val_ul;
|
new_sstep_flags = get_param(params, 0)->val_ul;
|
||||||
|
|
||||||
|
if (new_sstep_flags & ~gdbserver_state.supported_sstep_flags) {
|
||||||
|
put_packet("E22");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
gdbserver_state.sstep_flags = new_sstep_flags;
|
||||||
put_packet("OK");
|
put_packet("OK");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handle_query_qemu_sstep(GArray *params, void *user_ctx)
|
static void handle_query_qemu_sstep(GArray *params, void *user_ctx)
|
||||||
{
|
{
|
||||||
g_string_printf(gdbserver_state.str_buf, "0x%x", sstep_flags);
|
g_string_printf(gdbserver_state.str_buf, "0x%x",
|
||||||
|
gdbserver_state.sstep_flags);
|
||||||
put_strbuf();
|
put_strbuf();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3497,6 +3523,11 @@ int gdbserver_start(const char *device)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (kvm_enabled() && !kvm_supports_guest_debug()) {
|
||||||
|
error_report("gdbstub: KVM doesn't support guest debugging");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
if (!device)
|
if (!device)
|
||||||
return -1;
|
return -1;
|
||||||
if (strcmp(device, "none") != 0) {
|
if (strcmp(device, "none") != 0) {
|
||||||
|
@ -27,6 +27,7 @@ config ARM_VIRT
|
|||||||
select DIMM
|
select DIMM
|
||||||
select ACPI_HW_REDUCED
|
select ACPI_HW_REDUCED
|
||||||
select ACPI_APEI
|
select ACPI_APEI
|
||||||
|
select ACPI_VIOT
|
||||||
|
|
||||||
config CHEETAH
|
config CHEETAH
|
||||||
bool
|
bool
|
||||||
|
@ -284,12 +284,13 @@ static void write_boot_rom(DriveInfo *dinfo, hwaddr addr, size_t rom_size,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void aspeed_board_init_flashes(AspeedSMCState *s,
|
static void aspeed_board_init_flashes(AspeedSMCState *s,
|
||||||
const char *flashtype)
|
const char *flashtype,
|
||||||
|
int unit0)
|
||||||
{
|
{
|
||||||
int i ;
|
int i ;
|
||||||
|
|
||||||
for (i = 0; i < s->num_cs; ++i) {
|
for (i = 0; i < s->num_cs; ++i) {
|
||||||
DriveInfo *dinfo = drive_get_next(IF_MTD);
|
DriveInfo *dinfo = drive_get(IF_MTD, 0, unit0 + i);
|
||||||
qemu_irq cs_line;
|
qemu_irq cs_line;
|
||||||
DeviceState *dev;
|
DeviceState *dev;
|
||||||
|
|
||||||
@ -382,10 +383,12 @@ static void aspeed_machine_init(MachineState *machine)
|
|||||||
"max_ram", max_ram_size - machine->ram_size);
|
"max_ram", max_ram_size - machine->ram_size);
|
||||||
memory_region_add_subregion(&bmc->ram_container, machine->ram_size, &bmc->max_ram);
|
memory_region_add_subregion(&bmc->ram_container, machine->ram_size, &bmc->max_ram);
|
||||||
|
|
||||||
aspeed_board_init_flashes(&bmc->soc.fmc, bmc->fmc_model ?
|
aspeed_board_init_flashes(&bmc->soc.fmc,
|
||||||
bmc->fmc_model : amc->fmc_model);
|
bmc->fmc_model ? bmc->fmc_model : amc->fmc_model,
|
||||||
aspeed_board_init_flashes(&bmc->soc.spi[0], bmc->spi_model ?
|
0);
|
||||||
bmc->spi_model : amc->spi_model);
|
aspeed_board_init_flashes(&bmc->soc.spi[0],
|
||||||
|
bmc->spi_model ? bmc->spi_model : amc->spi_model,
|
||||||
|
bmc->soc.fmc.num_cs);
|
||||||
|
|
||||||
/* Install first FMC flash content as a boot rom. */
|
/* Install first FMC flash content as a boot rom. */
|
||||||
if (drive0) {
|
if (drive0) {
|
||||||
@ -435,11 +438,13 @@ static void aspeed_machine_init(MachineState *machine)
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < bmc->soc.sdhci.num_slots; i++) {
|
for (i = 0; i < bmc->soc.sdhci.num_slots; i++) {
|
||||||
sdhci_attach_drive(&bmc->soc.sdhci.slots[i], drive_get_next(IF_SD));
|
sdhci_attach_drive(&bmc->soc.sdhci.slots[i],
|
||||||
|
drive_get(IF_SD, 0, i));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bmc->soc.emmc.num_slots) {
|
if (bmc->soc.emmc.num_slots) {
|
||||||
sdhci_attach_drive(&bmc->soc.emmc.slots[0], drive_get_next(IF_SD));
|
sdhci_attach_drive(&bmc->soc.emmc.slots[0],
|
||||||
|
drive_get(IF_SD, 0, bmc->soc.sdhci.num_slots));
|
||||||
}
|
}
|
||||||
|
|
||||||
arm_load_kernel(ARM_CPU(first_cpu), machine, &aspeed_board_binfo);
|
arm_load_kernel(ARM_CPU(first_cpu), machine, &aspeed_board_binfo);
|
||||||
|
@ -8,7 +8,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "qemu/osdep.h"
|
#include "qemu/osdep.h"
|
||||||
#include "qemu-common.h"
|
|
||||||
#include "qemu/datadir.h"
|
#include "qemu/datadir.h"
|
||||||
#include "qemu/error-report.h"
|
#include "qemu/error-report.h"
|
||||||
#include "qapi/error.h"
|
#include "qapi/error.h"
|
||||||
|
@ -81,7 +81,7 @@ static void cubieboard_init(MachineState *machine)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Retrieve SD bus */
|
/* Retrieve SD bus */
|
||||||
di = drive_get_next(IF_SD);
|
di = drive_get(IF_SD, 0, 0);
|
||||||
blk = di ? blk_by_legacy_dinfo(di) : NULL;
|
blk = di ? blk_by_legacy_dinfo(di) : NULL;
|
||||||
bus = qdev_get_child_bus(DEVICE(a10), "sd-bus");
|
bus = qdev_get_child_bus(DEVICE(a10), "sd-bus");
|
||||||
|
|
||||||
|
@ -25,7 +25,6 @@
|
|||||||
|
|
||||||
#include "qemu/osdep.h"
|
#include "qemu/osdep.h"
|
||||||
#include "qapi/error.h"
|
#include "qapi/error.h"
|
||||||
#include "qemu-common.h"
|
|
||||||
#include "qemu/datadir.h"
|
#include "qemu/datadir.h"
|
||||||
#include "hw/boards.h"
|
#include "hw/boards.h"
|
||||||
#include "qemu/error-report.h"
|
#include "qemu/error-report.h"
|
||||||
|
@ -18,7 +18,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "qemu/osdep.h"
|
#include "qemu/osdep.h"
|
||||||
#include "qemu-common.h"
|
|
||||||
#include "qemu/datadir.h"
|
#include "qemu/datadir.h"
|
||||||
#include "qapi/error.h"
|
#include "qapi/error.h"
|
||||||
#include "hw/sysbus.h"
|
#include "hw/sysbus.h"
|
||||||
|
@ -123,7 +123,7 @@ static void imx25_pdk_init(MachineState *machine)
|
|||||||
DriveInfo *di;
|
DriveInfo *di;
|
||||||
BlockBackend *blk;
|
BlockBackend *blk;
|
||||||
|
|
||||||
di = drive_get_next(IF_SD);
|
di = drive_get(IF_SD, 0, i);
|
||||||
blk = di ? blk_by_legacy_dinfo(di) : NULL;
|
blk = di ? blk_by_legacy_dinfo(di) : NULL;
|
||||||
bus = qdev_get_child_bus(DEVICE(&s->soc.esdhc[i]), "sd-bus");
|
bus = qdev_get_child_bus(DEVICE(&s->soc.esdhc[i]), "sd-bus");
|
||||||
carddev = qdev_new(TYPE_SD_CARD);
|
carddev = qdev_new(TYPE_SD_CARD);
|
||||||
|
@ -649,7 +649,7 @@ static void integratorcp_init(MachineState *machine)
|
|||||||
qdev_get_gpio_in_named(icp, ICP_GPIO_MMC_WPROT, 0));
|
qdev_get_gpio_in_named(icp, ICP_GPIO_MMC_WPROT, 0));
|
||||||
qdev_connect_gpio_out_named(dev, "card-inserted", 0,
|
qdev_connect_gpio_out_named(dev, "card-inserted", 0,
|
||||||
qdev_get_gpio_in_named(icp, ICP_GPIO_MMC_CARDIN, 0));
|
qdev_get_gpio_in_named(icp, ICP_GPIO_MMC_CARDIN, 0));
|
||||||
dinfo = drive_get_next(IF_SD);
|
dinfo = drive_get(IF_SD, 0, 0);
|
||||||
if (dinfo) {
|
if (dinfo) {
|
||||||
DeviceState *card;
|
DeviceState *card;
|
||||||
|
|
||||||
|
@ -52,7 +52,7 @@ static void mcimx6ul_evk_init(MachineState *machine)
|
|||||||
DriveInfo *di;
|
DriveInfo *di;
|
||||||
BlockBackend *blk;
|
BlockBackend *blk;
|
||||||
|
|
||||||
di = drive_get_next(IF_SD);
|
di = drive_get(IF_SD, 0, i);
|
||||||
blk = di ? blk_by_legacy_dinfo(di) : NULL;
|
blk = di ? blk_by_legacy_dinfo(di) : NULL;
|
||||||
bus = qdev_get_child_bus(DEVICE(&s->usdhc[i]), "sd-bus");
|
bus = qdev_get_child_bus(DEVICE(&s->usdhc[i]), "sd-bus");
|
||||||
carddev = qdev_new(TYPE_SD_CARD);
|
carddev = qdev_new(TYPE_SD_CARD);
|
||||||
|
@ -52,7 +52,7 @@ static void mcimx7d_sabre_init(MachineState *machine)
|
|||||||
DriveInfo *di;
|
DriveInfo *di;
|
||||||
BlockBackend *blk;
|
BlockBackend *blk;
|
||||||
|
|
||||||
di = drive_get_next(IF_SD);
|
di = drive_get(IF_SD, 0, i);
|
||||||
blk = di ? blk_by_legacy_dinfo(di) : NULL;
|
blk = di ? blk_by_legacy_dinfo(di) : NULL;
|
||||||
bus = qdev_get_child_bus(DEVICE(&s->usdhc[i]), "sd-bus");
|
bus = qdev_get_child_bus(DEVICE(&s->usdhc[i]), "sd-bus");
|
||||||
carddev = qdev_new(TYPE_SD_CARD);
|
carddev = qdev_new(TYPE_SD_CARD);
|
||||||
|
@ -45,7 +45,7 @@ static void emcraft_sf2_s2s010_init(MachineState *machine)
|
|||||||
DeviceState *spi_flash;
|
DeviceState *spi_flash;
|
||||||
MSF2State *soc;
|
MSF2State *soc;
|
||||||
MachineClass *mc = MACHINE_GET_CLASS(machine);
|
MachineClass *mc = MACHINE_GET_CLASS(machine);
|
||||||
DriveInfo *dinfo = drive_get_next(IF_MTD);
|
DriveInfo *dinfo = drive_get(IF_MTD, 0, 0);
|
||||||
qemu_irq cs_line;
|
qemu_irq cs_line;
|
||||||
BusState *spi_bus;
|
BusState *spi_bus;
|
||||||
MemoryRegion *sysmem = get_system_memory();
|
MemoryRegion *sysmem = get_system_memory();
|
||||||
|
@ -24,7 +24,6 @@
|
|||||||
#include "hw/qdev-core.h"
|
#include "hw/qdev-core.h"
|
||||||
#include "hw/qdev-properties.h"
|
#include "hw/qdev-properties.h"
|
||||||
#include "qapi/error.h"
|
#include "qapi/error.h"
|
||||||
#include "qemu-common.h"
|
|
||||||
#include "qemu/datadir.h"
|
#include "qemu/datadir.h"
|
||||||
#include "qemu/units.h"
|
#include "qemu/units.h"
|
||||||
#include "sysemu/blockdev.h"
|
#include "sysemu/blockdev.h"
|
||||||
@ -84,9 +83,9 @@ static void npcm7xx_connect_dram(NPCM7xxState *soc, MemoryRegion *dram)
|
|||||||
&error_abort);
|
&error_abort);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sdhci_attach_drive(SDHCIState *sdhci)
|
static void sdhci_attach_drive(SDHCIState *sdhci, int unit)
|
||||||
{
|
{
|
||||||
DriveInfo *di = drive_get_next(IF_SD);
|
DriveInfo *di = drive_get(IF_SD, 0, unit);
|
||||||
BlockBackend *blk = di ? blk_by_legacy_dinfo(di) : NULL;
|
BlockBackend *blk = di ? blk_by_legacy_dinfo(di) : NULL;
|
||||||
|
|
||||||
BusState *bus = qdev_get_child_bus(DEVICE(sdhci), "sd-bus");
|
BusState *bus = qdev_get_child_bus(DEVICE(sdhci), "sd-bus");
|
||||||
@ -374,7 +373,7 @@ static void quanta_gbs_init(MachineState *machine)
|
|||||||
drive_get(IF_MTD, 0, 0));
|
drive_get(IF_MTD, 0, 0));
|
||||||
|
|
||||||
quanta_gbs_i2c_init(soc);
|
quanta_gbs_i2c_init(soc);
|
||||||
sdhci_attach_drive(&soc->mmc.sdhci);
|
sdhci_attach_drive(&soc->mmc.sdhci, 0);
|
||||||
npcm7xx_load_kernel(machine, soc);
|
npcm7xx_load_kernel(machine, soc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,7 +85,7 @@ static void orangepi_init(MachineState *machine)
|
|||||||
qdev_realize(DEVICE(h3), NULL, &error_abort);
|
qdev_realize(DEVICE(h3), NULL, &error_abort);
|
||||||
|
|
||||||
/* Retrieve SD bus */
|
/* Retrieve SD bus */
|
||||||
di = drive_get_next(IF_SD);
|
di = drive_get(IF_SD, 0, 0);
|
||||||
blk = di ? blk_by_legacy_dinfo(di) : NULL;
|
blk = di ? blk_by_legacy_dinfo(di) : NULL;
|
||||||
bus = qdev_get_child_bus(DEVICE(h3), "sd-bus");
|
bus = qdev_get_child_bus(DEVICE(h3), "sd-bus");
|
||||||
|
|
||||||
|
@ -284,7 +284,7 @@ static void raspi_machine_init(MachineState *machine)
|
|||||||
qdev_realize(DEVICE(&s->soc), NULL, &error_fatal);
|
qdev_realize(DEVICE(&s->soc), NULL, &error_fatal);
|
||||||
|
|
||||||
/* Create and plug in the SD cards */
|
/* Create and plug in the SD cards */
|
||||||
di = drive_get_next(IF_SD);
|
di = drive_get(IF_SD, 0, 0);
|
||||||
blk = di ? blk_by_legacy_dinfo(di) : NULL;
|
blk = di ? blk_by_legacy_dinfo(di) : NULL;
|
||||||
bus = qdev_get_child_bus(DEVICE(&s->soc), "sd-bus");
|
bus = qdev_get_child_bus(DEVICE(&s->soc), "sd-bus");
|
||||||
if (bus == NULL) {
|
if (bus == NULL) {
|
||||||
|
@ -237,7 +237,7 @@ static void realview_init(MachineState *machine,
|
|||||||
qemu_irq_invert(qdev_get_gpio_in(gpio2, 0)));
|
qemu_irq_invert(qdev_get_gpio_in(gpio2, 0)));
|
||||||
qdev_connect_gpio_out_named(dev, "card-read-only", 0, mmc_irq[0]);
|
qdev_connect_gpio_out_named(dev, "card-read-only", 0, mmc_irq[0]);
|
||||||
qdev_connect_gpio_out_named(dev, "card-inserted", 0, mmc_irq[1]);
|
qdev_connect_gpio_out_named(dev, "card-inserted", 0, mmc_irq[1]);
|
||||||
dinfo = drive_get_next(IF_SD);
|
dinfo = drive_get(IF_SD, 0, 0);
|
||||||
if (dinfo) {
|
if (dinfo) {
|
||||||
DeviceState *card;
|
DeviceState *card;
|
||||||
|
|
||||||
|
@ -76,7 +76,7 @@ static void sabrelite_init(MachineState *machine)
|
|||||||
if (spi_bus) {
|
if (spi_bus) {
|
||||||
DeviceState *flash_dev;
|
DeviceState *flash_dev;
|
||||||
qemu_irq cs_line;
|
qemu_irq cs_line;
|
||||||
DriveInfo *dinfo = drive_get_next(IF_MTD);
|
DriveInfo *dinfo = drive_get(IF_MTD, 0, 0);
|
||||||
|
|
||||||
flash_dev = qdev_new("sst25vf016b");
|
flash_dev = qdev_new("sst25vf016b");
|
||||||
if (dinfo) {
|
if (dinfo) {
|
||||||
|
@ -18,7 +18,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "qemu/osdep.h"
|
#include "qemu/osdep.h"
|
||||||
#include "qemu-common.h"
|
|
||||||
#include "qemu/datadir.h"
|
#include "qemu/datadir.h"
|
||||||
#include "qapi/error.h"
|
#include "qapi/error.h"
|
||||||
#include "qemu/error-report.h"
|
#include "qemu/error-report.h"
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
#include "qemu/osdep.h"
|
#include "qemu/osdep.h"
|
||||||
#include "qapi/error.h"
|
#include "qapi/error.h"
|
||||||
#include "hw/sysbus.h"
|
#include "hw/sysbus.h"
|
||||||
|
#include "hw/sd/sd.h"
|
||||||
#include "hw/ssi/ssi.h"
|
#include "hw/ssi/ssi.h"
|
||||||
#include "hw/arm/boot.h"
|
#include "hw/arm/boot.h"
|
||||||
#include "qemu/timer.h"
|
#include "qemu/timer.h"
|
||||||
@ -1157,6 +1158,9 @@ static void stellaris_init(MachineState *ms, stellaris_board_info *board)
|
|||||||
void *bus;
|
void *bus;
|
||||||
DeviceState *sddev;
|
DeviceState *sddev;
|
||||||
DeviceState *ssddev;
|
DeviceState *ssddev;
|
||||||
|
DriveInfo *dinfo;
|
||||||
|
DeviceState *carddev;
|
||||||
|
BlockBackend *blk;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Some boards have both an OLED controller and SD card connected to
|
* Some boards have both an OLED controller and SD card connected to
|
||||||
@ -1221,8 +1225,17 @@ static void stellaris_init(MachineState *ms, stellaris_board_info *board)
|
|||||||
* - Make the ssd0323 OLED controller chipselect active-low
|
* - Make the ssd0323 OLED controller chipselect active-low
|
||||||
*/
|
*/
|
||||||
bus = qdev_get_child_bus(dev, "ssi");
|
bus = qdev_get_child_bus(dev, "ssi");
|
||||||
|
|
||||||
sddev = ssi_create_peripheral(bus, "ssi-sd");
|
sddev = ssi_create_peripheral(bus, "ssi-sd");
|
||||||
|
|
||||||
|
dinfo = drive_get(IF_SD, 0, 0);
|
||||||
|
blk = dinfo ? blk_by_legacy_dinfo(dinfo) : NULL;
|
||||||
|
carddev = qdev_new(TYPE_SD_CARD);
|
||||||
|
qdev_prop_set_drive_err(carddev, "drive", blk, &error_fatal);
|
||||||
|
qdev_prop_set_bit(carddev, "spi", true);
|
||||||
|
qdev_realize_and_unref(carddev,
|
||||||
|
qdev_get_child_bus(sddev, "sd-bus"),
|
||||||
|
&error_fatal);
|
||||||
|
|
||||||
ssddev = ssi_create_peripheral(bus, "ssd0323");
|
ssddev = ssi_create_peripheral(bus, "ssd0323");
|
||||||
gpio_out[GPIO_D][0] = qemu_irq_split(
|
gpio_out[GPIO_D][0] = qemu_irq_split(
|
||||||
qdev_get_gpio_in_named(sddev, SSI_GPIO_CS, 0),
|
qdev_get_gpio_in_named(sddev, SSI_GPIO_CS, 0),
|
||||||
|
@ -24,7 +24,6 @@
|
|||||||
|
|
||||||
#include "qemu/osdep.h"
|
#include "qemu/osdep.h"
|
||||||
#include "qapi/error.h"
|
#include "qapi/error.h"
|
||||||
#include "qemu-common.h"
|
|
||||||
#include "exec/address-spaces.h"
|
#include "exec/address-spaces.h"
|
||||||
#include "sysemu/sysemu.h"
|
#include "sysemu/sysemu.h"
|
||||||
#include "hw/arm/stm32f405_soc.h"
|
#include "hw/arm/stm32f405_soc.h"
|
||||||
|
@ -310,7 +310,7 @@ static void versatile_init(MachineState *machine, int board_id)
|
|||||||
qdev_connect_gpio_out(sysctl, 0, qdev_get_gpio_in(dev, 0));
|
qdev_connect_gpio_out(sysctl, 0, qdev_get_gpio_in(dev, 0));
|
||||||
|
|
||||||
dev = sysbus_create_varargs("pl181", 0x10005000, sic[22], sic[1], NULL);
|
dev = sysbus_create_varargs("pl181", 0x10005000, sic[22], sic[1], NULL);
|
||||||
dinfo = drive_get_next(IF_SD);
|
dinfo = drive_get(IF_SD, 0, 0);
|
||||||
if (dinfo) {
|
if (dinfo) {
|
||||||
DeviceState *card;
|
DeviceState *card;
|
||||||
|
|
||||||
@ -322,7 +322,7 @@ static void versatile_init(MachineState *machine, int board_id)
|
|||||||
}
|
}
|
||||||
|
|
||||||
dev = sysbus_create_varargs("pl181", 0x1000b000, sic[23], sic[2], NULL);
|
dev = sysbus_create_varargs("pl181", 0x1000b000, sic[23], sic[2], NULL);
|
||||||
dinfo = drive_get_next(IF_SD);
|
dinfo = drive_get(IF_SD, 0, 1);
|
||||||
if (dinfo) {
|
if (dinfo) {
|
||||||
DeviceState *card;
|
DeviceState *card;
|
||||||
|
|
||||||
|
@ -23,7 +23,6 @@
|
|||||||
|
|
||||||
#include "qemu/osdep.h"
|
#include "qemu/osdep.h"
|
||||||
#include "qapi/error.h"
|
#include "qapi/error.h"
|
||||||
#include "qemu-common.h"
|
|
||||||
#include "qemu/datadir.h"
|
#include "qemu/datadir.h"
|
||||||
#include "cpu.h"
|
#include "cpu.h"
|
||||||
#include "hw/sysbus.h"
|
#include "hw/sysbus.h"
|
||||||
@ -625,7 +624,7 @@ static void vexpress_common_init(MachineState *machine)
|
|||||||
qdev_get_gpio_in(sysctl, ARM_SYSCTL_GPIO_MMC_WPROT));
|
qdev_get_gpio_in(sysctl, ARM_SYSCTL_GPIO_MMC_WPROT));
|
||||||
qdev_connect_gpio_out_named(dev, "card-inserted", 0,
|
qdev_connect_gpio_out_named(dev, "card-inserted", 0,
|
||||||
qdev_get_gpio_in(sysctl, ARM_SYSCTL_GPIO_MMC_CARDIN));
|
qdev_get_gpio_in(sysctl, ARM_SYSCTL_GPIO_MMC_CARDIN));
|
||||||
dinfo = drive_get_next(IF_SD);
|
dinfo = drive_get(IF_SD, 0, 0);
|
||||||
if (dinfo) {
|
if (dinfo) {
|
||||||
DeviceState *card;
|
DeviceState *card;
|
||||||
|
|
||||||
@ -657,7 +656,7 @@ static void vexpress_common_init(MachineState *machine)
|
|||||||
|
|
||||||
sysbus_create_simple("pl111", map[VE_CLCD], pic[14]);
|
sysbus_create_simple("pl111", map[VE_CLCD], pic[14]);
|
||||||
|
|
||||||
dinfo = drive_get_next(IF_PFLASH);
|
dinfo = drive_get(IF_PFLASH, 0, 0);
|
||||||
pflash0 = ve_pflash_cfi01_register(map[VE_NORFLASH0], "vexpress.flash0",
|
pflash0 = ve_pflash_cfi01_register(map[VE_NORFLASH0], "vexpress.flash0",
|
||||||
dinfo);
|
dinfo);
|
||||||
if (!pflash0) {
|
if (!pflash0) {
|
||||||
@ -673,7 +672,7 @@ static void vexpress_common_init(MachineState *machine)
|
|||||||
memory_region_add_subregion(sysmem, map[VE_NORFLASHALIAS], flashalias);
|
memory_region_add_subregion(sysmem, map[VE_NORFLASHALIAS], flashalias);
|
||||||
}
|
}
|
||||||
|
|
||||||
dinfo = drive_get_next(IF_PFLASH);
|
dinfo = drive_get(IF_PFLASH, 0, 1);
|
||||||
if (!ve_pflash_cfi01_register(map[VE_NORFLASH1], "vexpress.flash1",
|
if (!ve_pflash_cfi01_register(map[VE_NORFLASH1], "vexpress.flash1",
|
||||||
dinfo)) {
|
dinfo)) {
|
||||||
error_report("vexpress: error registering flash 1");
|
error_report("vexpress: error registering flash 1");
|
||||||
|
@ -55,6 +55,7 @@
|
|||||||
#include "kvm_arm.h"
|
#include "kvm_arm.h"
|
||||||
#include "migration/vmstate.h"
|
#include "migration/vmstate.h"
|
||||||
#include "hw/acpi/ghes.h"
|
#include "hw/acpi/ghes.h"
|
||||||
|
#include "hw/acpi/viot.h"
|
||||||
|
|
||||||
#define ARM_SPI_BASE 32
|
#define ARM_SPI_BASE 32
|
||||||
|
|
||||||
@ -1011,6 +1012,12 @@ void virt_acpi_build(VirtMachineState *vms, AcpiBuildTables *tables)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (vms->iommu == VIRT_IOMMU_VIRTIO) {
|
||||||
|
acpi_add_table(table_offsets, tables_blob);
|
||||||
|
build_viot(ms, tables_blob, tables->linker, vms->virtio_iommu_bdf,
|
||||||
|
vms->oem_id, vms->oem_table_id);
|
||||||
|
}
|
||||||
|
|
||||||
/* XSDT is pointed to by RSDP */
|
/* XSDT is pointed to by RSDP */
|
||||||
xsdt = tables_blob->len;
|
xsdt = tables_blob->len;
|
||||||
build_xsdt(tables_blob, tables->linker, table_offsets, vms->oem_id,
|
build_xsdt(tables_blob, tables->linker, table_offsets, vms->oem_id,
|
||||||
|
@ -29,7 +29,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "qemu/osdep.h"
|
#include "qemu/osdep.h"
|
||||||
#include "qemu-common.h"
|
|
||||||
#include "qemu/datadir.h"
|
#include "qemu/datadir.h"
|
||||||
#include "qemu/units.h"
|
#include "qemu/units.h"
|
||||||
#include "qemu/option.h"
|
#include "qemu/option.h"
|
||||||
@ -2494,6 +2493,11 @@ static void virt_machine_device_pre_plug_cb(HotplugHandler *hotplug_dev,
|
|||||||
hwaddr db_start = 0, db_end = 0;
|
hwaddr db_start = 0, db_end = 0;
|
||||||
char *resv_prop_str;
|
char *resv_prop_str;
|
||||||
|
|
||||||
|
if (vms->iommu != VIRT_IOMMU_NONE) {
|
||||||
|
error_setg(errp, "virt machine does not support multiple IOMMUs");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
switch (vms->msi_controller) {
|
switch (vms->msi_controller) {
|
||||||
case VIRT_MSI_CTRL_NONE:
|
case VIRT_MSI_CTRL_NONE:
|
||||||
return;
|
return;
|
||||||
@ -2513,8 +2517,9 @@ static void virt_machine_device_pre_plug_cb(HotplugHandler *hotplug_dev,
|
|||||||
db_start, db_end,
|
db_start, db_end,
|
||||||
VIRTIO_IOMMU_RESV_MEM_T_MSI);
|
VIRTIO_IOMMU_RESV_MEM_T_MSI);
|
||||||
|
|
||||||
qdev_prop_set_uint32(dev, "len-reserved-regions", 1);
|
object_property_set_uint(OBJECT(dev), "len-reserved-regions", 1, errp);
|
||||||
qdev_prop_set_string(dev, "reserved-regions[0]", resv_prop_str);
|
object_property_set_str(OBJECT(dev), "reserved-regions[0]",
|
||||||
|
resv_prop_str, errp);
|
||||||
g_free(resv_prop_str);
|
g_free(resv_prop_str);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2614,16 +2619,10 @@ static HotplugHandler *virt_machine_get_hotplug_handler(MachineState *machine,
|
|||||||
MachineClass *mc = MACHINE_GET_CLASS(machine);
|
MachineClass *mc = MACHINE_GET_CLASS(machine);
|
||||||
|
|
||||||
if (device_is_dynamic_sysbus(mc, dev) ||
|
if (device_is_dynamic_sysbus(mc, dev) ||
|
||||||
(object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM))) {
|
object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM) ||
|
||||||
|
object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_IOMMU_PCI)) {
|
||||||
return HOTPLUG_HANDLER(machine);
|
return HOTPLUG_HANDLER(machine);
|
||||||
}
|
}
|
||||||
if (object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_IOMMU_PCI)) {
|
|
||||||
VirtMachineState *vms = VIRT_MACHINE(machine);
|
|
||||||
|
|
||||||
if (!vms->bootinfo.firmware_loaded || !virt_is_acpi_enabled(vms)) {
|
|
||||||
return HOTPLUG_HANDLER(machine);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,9 +125,10 @@ static void gem_init(NICInfo *nd, uint32_t base, qemu_irq irq)
|
|||||||
sysbus_connect_irq(s, 0, irq);
|
sysbus_connect_irq(s, 0, irq);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void zynq_init_spi_flashes(uint32_t base_addr, qemu_irq irq,
|
static inline int zynq_init_spi_flashes(uint32_t base_addr, qemu_irq irq,
|
||||||
bool is_qspi)
|
bool is_qspi, int unit0)
|
||||||
{
|
{
|
||||||
|
int unit = unit0;
|
||||||
DeviceState *dev;
|
DeviceState *dev;
|
||||||
SysBusDevice *busdev;
|
SysBusDevice *busdev;
|
||||||
SSIBus *spi;
|
SSIBus *spi;
|
||||||
@ -156,7 +157,7 @@ static inline void zynq_init_spi_flashes(uint32_t base_addr, qemu_irq irq,
|
|||||||
spi = (SSIBus *)qdev_get_child_bus(dev, bus_name);
|
spi = (SSIBus *)qdev_get_child_bus(dev, bus_name);
|
||||||
|
|
||||||
for (j = 0; j < num_ss; ++j) {
|
for (j = 0; j < num_ss; ++j) {
|
||||||
DriveInfo *dinfo = drive_get_next(IF_MTD);
|
DriveInfo *dinfo = drive_get(IF_MTD, 0, unit++);
|
||||||
flash_dev = qdev_new("n25q128");
|
flash_dev = qdev_new("n25q128");
|
||||||
if (dinfo) {
|
if (dinfo) {
|
||||||
qdev_prop_set_drive_err(flash_dev, "drive",
|
qdev_prop_set_drive_err(flash_dev, "drive",
|
||||||
@ -170,6 +171,7 @@ static inline void zynq_init_spi_flashes(uint32_t base_addr, qemu_irq irq,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return unit;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void zynq_init(MachineState *machine)
|
static void zynq_init(MachineState *machine)
|
||||||
@ -247,9 +249,9 @@ static void zynq_init(MachineState *machine)
|
|||||||
pic[n] = qdev_get_gpio_in(dev, n);
|
pic[n] = qdev_get_gpio_in(dev, n);
|
||||||
}
|
}
|
||||||
|
|
||||||
zynq_init_spi_flashes(0xE0006000, pic[58-IRQ_OFFSET], false);
|
n = zynq_init_spi_flashes(0xE0006000, pic[58 - IRQ_OFFSET], false, 0);
|
||||||
zynq_init_spi_flashes(0xE0007000, pic[81-IRQ_OFFSET], false);
|
n = zynq_init_spi_flashes(0xE0007000, pic[81 - IRQ_OFFSET], false, n);
|
||||||
zynq_init_spi_flashes(0xE000D000, pic[51-IRQ_OFFSET], true);
|
n = zynq_init_spi_flashes(0xE000D000, pic[51 - IRQ_OFFSET], true, n);
|
||||||
|
|
||||||
sysbus_create_simple(TYPE_CHIPIDEA, 0xE0002000, pic[53 - IRQ_OFFSET]);
|
sysbus_create_simple(TYPE_CHIPIDEA, 0xE0002000, pic[53 - IRQ_OFFSET]);
|
||||||
sysbus_create_simple(TYPE_CHIPIDEA, 0xE0003000, pic[76 - IRQ_OFFSET]);
|
sysbus_create_simple(TYPE_CHIPIDEA, 0xE0003000, pic[76 - IRQ_OFFSET]);
|
||||||
@ -298,7 +300,7 @@ static void zynq_init(MachineState *machine)
|
|||||||
sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, hci_addr);
|
sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, hci_addr);
|
||||||
sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic[hci_irq - IRQ_OFFSET]);
|
sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic[hci_irq - IRQ_OFFSET]);
|
||||||
|
|
||||||
di = drive_get_next(IF_SD);
|
di = drive_get(IF_SD, 0, n);
|
||||||
blk = di ? blk_by_legacy_dinfo(di) : NULL;
|
blk = di ? blk_by_legacy_dinfo(di) : NULL;
|
||||||
carddev = qdev_new(TYPE_SD_CARD);
|
carddev = qdev_new(TYPE_SD_CARD);
|
||||||
qdev_prop_set_drive_err(carddev, "drive", blk, &error_fatal);
|
qdev_prop_set_drive_err(carddev, "drive", blk, &error_fatal);
|
||||||
|
@ -669,7 +669,8 @@ static void versal_virt_init(MachineState *machine)
|
|||||||
|
|
||||||
/* Plugin SD cards. */
|
/* Plugin SD cards. */
|
||||||
for (i = 0; i < ARRAY_SIZE(s->soc.pmc.iou.sd); i++) {
|
for (i = 0; i < ARRAY_SIZE(s->soc.pmc.iou.sd); i++) {
|
||||||
sd_plugin_card(&s->soc.pmc.iou.sd[i], drive_get_next(IF_SD));
|
sd_plugin_card(&s->soc.pmc.iou.sd[i],
|
||||||
|
drive_get(IF_SD, 0, i));
|
||||||
}
|
}
|
||||||
|
|
||||||
s->binfo.ram_size = machine->ram_size;
|
s->binfo.ram_size = machine->ram_size;
|
||||||
|
@ -169,7 +169,7 @@ static void xlnx_zcu102_init(MachineState *machine)
|
|||||||
/* Create and plug in the SD cards */
|
/* Create and plug in the SD cards */
|
||||||
for (i = 0; i < XLNX_ZYNQMP_NUM_SDHCI; i++) {
|
for (i = 0; i < XLNX_ZYNQMP_NUM_SDHCI; i++) {
|
||||||
BusState *bus;
|
BusState *bus;
|
||||||
DriveInfo *di = drive_get_next(IF_SD);
|
DriveInfo *di = drive_get(IF_SD, 0, i);
|
||||||
BlockBackend *blk = di ? blk_by_legacy_dinfo(di) : NULL;
|
BlockBackend *blk = di ? blk_by_legacy_dinfo(di) : NULL;
|
||||||
DeviceState *carddev;
|
DeviceState *carddev;
|
||||||
char *bus_name;
|
char *bus_name;
|
||||||
@ -190,7 +190,7 @@ static void xlnx_zcu102_init(MachineState *machine)
|
|||||||
BusState *spi_bus;
|
BusState *spi_bus;
|
||||||
DeviceState *flash_dev;
|
DeviceState *flash_dev;
|
||||||
qemu_irq cs_line;
|
qemu_irq cs_line;
|
||||||
DriveInfo *dinfo = drive_get_next(IF_MTD);
|
DriveInfo *dinfo = drive_get(IF_MTD, 0, i);
|
||||||
gchar *bus_name = g_strdup_printf("spi%d", i);
|
gchar *bus_name = g_strdup_printf("spi%d", i);
|
||||||
|
|
||||||
spi_bus = qdev_get_child_bus(DEVICE(&s->soc), bus_name);
|
spi_bus = qdev_get_child_bus(DEVICE(&s->soc), bus_name);
|
||||||
@ -212,7 +212,7 @@ static void xlnx_zcu102_init(MachineState *machine)
|
|||||||
BusState *spi_bus;
|
BusState *spi_bus;
|
||||||
DeviceState *flash_dev;
|
DeviceState *flash_dev;
|
||||||
qemu_irq cs_line;
|
qemu_irq cs_line;
|
||||||
DriveInfo *dinfo = drive_get_next(IF_MTD);
|
DriveInfo *dinfo = drive_get(IF_MTD, 0, XLNX_ZYNQMP_NUM_SPIS + i);
|
||||||
int bus = i / XLNX_ZYNQMP_NUM_QSPI_BUS_CS;
|
int bus = i / XLNX_ZYNQMP_NUM_QSPI_BUS_CS;
|
||||||
gchar *bus_name = g_strdup_printf("qspi%d", bus);
|
gchar *bus_name = g_strdup_printf("qspi%d", bus);
|
||||||
|
|
||||||
|
@ -233,7 +233,7 @@ static void atmega_realize(DeviceState *dev, Error **errp)
|
|||||||
|
|
||||||
/* CPU */
|
/* CPU */
|
||||||
object_initialize_child(OBJECT(dev), "cpu", &s->cpu, mc->cpu_type);
|
object_initialize_child(OBJECT(dev), "cpu", &s->cpu, mc->cpu_type);
|
||||||
object_property_set_bool(OBJECT(&s->cpu), "realized", true, &error_abort);
|
qdev_realize(DEVICE(&s->cpu), NULL, &error_abort);
|
||||||
cpudev = DEVICE(&s->cpu);
|
cpudev = DEVICE(&s->cpu);
|
||||||
|
|
||||||
/* SRAM */
|
/* SRAM */
|
||||||
|
@ -222,7 +222,7 @@ int virtio_blk_data_plane_start(VirtIODevice *vdev)
|
|||||||
memory_region_transaction_commit();
|
memory_region_transaction_commit();
|
||||||
|
|
||||||
while (j--) {
|
while (j--) {
|
||||||
virtio_bus_cleanup_host_notifier(VIRTIO_BUS(qbus), i);
|
virtio_bus_cleanup_host_notifier(VIRTIO_BUS(qbus), j);
|
||||||
}
|
}
|
||||||
goto fail_host_notifiers;
|
goto fail_host_notifiers;
|
||||||
}
|
}
|
||||||
|
@ -103,10 +103,11 @@ static uint64_t stm32f2xx_usart_read(void *opaque, hwaddr addr,
|
|||||||
return retvalue;
|
return retvalue;
|
||||||
case USART_DR:
|
case USART_DR:
|
||||||
DB_PRINT("Value: 0x%" PRIx32 ", %c\n", s->usart_dr, (char) s->usart_dr);
|
DB_PRINT("Value: 0x%" PRIx32 ", %c\n", s->usart_dr, (char) s->usart_dr);
|
||||||
|
retvalue = s->usart_dr & 0x3FF;
|
||||||
s->usart_sr &= ~USART_SR_RXNE;
|
s->usart_sr &= ~USART_SR_RXNE;
|
||||||
qemu_chr_fe_accept_input(&s->chr);
|
qemu_chr_fe_accept_input(&s->chr);
|
||||||
qemu_set_irq(s->irq, 0);
|
qemu_set_irq(s->irq, 0);
|
||||||
return s->usart_dr & 0x3FF;
|
return retvalue;
|
||||||
case USART_BRR:
|
case USART_BRR:
|
||||||
return s->usart_brr;
|
return s->usart_brr;
|
||||||
case USART_CR1:
|
case USART_CR1:
|
||||||
|
@ -784,9 +784,8 @@ static void numa_stat_memory_devices(NumaNodeMem node_mem[])
|
|||||||
break;
|
break;
|
||||||
case MEMORY_DEVICE_INFO_KIND_SGX_EPC:
|
case MEMORY_DEVICE_INFO_KIND_SGX_EPC:
|
||||||
se = value->u.sgx_epc.data;
|
se = value->u.sgx_epc.data;
|
||||||
/* TODO: once we support numa, assign to right node */
|
node_mem[se->node].node_mem += se->size;
|
||||||
node_mem[0].node_mem += se->size;
|
node_mem[se->node].node_plugged_mem = 0;
|
||||||
node_mem[0].node_plugged_mem += se->size;
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
g_assert_not_reached();
|
g_assert_not_reached();
|
||||||
|
@ -33,7 +33,6 @@
|
|||||||
#include "hw/loader.h"
|
#include "hw/loader.h"
|
||||||
#include "hw/qdev-properties.h"
|
#include "hw/qdev-properties.h"
|
||||||
#include "qom/object.h"
|
#include "qom/object.h"
|
||||||
#include "qapi/error.h"
|
|
||||||
|
|
||||||
#define TYPE_ISA_VGA "isa-vga"
|
#define TYPE_ISA_VGA "isa-vga"
|
||||||
OBJECT_DECLARE_SIMPLE_TYPE(ISAVGAState, ISA_VGA)
|
OBJECT_DECLARE_SIMPLE_TYPE(ISAVGAState, ISA_VGA)
|
||||||
@ -62,15 +61,6 @@ static void vga_isa_realizefn(DeviceState *dev, Error **errp)
|
|||||||
MemoryRegion *vga_io_memory;
|
MemoryRegion *vga_io_memory;
|
||||||
const MemoryRegionPortio *vga_ports, *vbe_ports;
|
const MemoryRegionPortio *vga_ports, *vbe_ports;
|
||||||
|
|
||||||
/*
|
|
||||||
* make sure this device is not being added twice, if so
|
|
||||||
* exit without crashing qemu
|
|
||||||
*/
|
|
||||||
if (object_resolve_path_type("", TYPE_ISA_VGA, NULL)) {
|
|
||||||
error_setg(errp, "at most one %s device is permitted", TYPE_ISA_VGA);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
s->global_vmstate = true;
|
s->global_vmstate = true;
|
||||||
vga_common_init(s, OBJECT(dev));
|
vga_common_init(s, OBJECT(dev));
|
||||||
s->legacy_address_space = isa_address_space(isadev);
|
s->legacy_address_space = isa_address_space(isadev);
|
||||||
|
@ -2068,6 +2068,8 @@ build_srat(GArray *table_data, BIOSLinker *linker, MachineState *machine)
|
|||||||
nvdimm_build_srat(table_data);
|
nvdimm_build_srat(table_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sgx_epc_build_srat(table_data);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* TODO: this part is not in ACPI spec and current linux kernel boots fine
|
* TODO: this part is not in ACPI spec and current linux kernel boots fine
|
||||||
* without these entries. But I recall there were issues the last time I
|
* without these entries. But I recall there were issues the last time I
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
|
|
||||||
static Property sgx_epc_properties[] = {
|
static Property sgx_epc_properties[] = {
|
||||||
DEFINE_PROP_UINT64(SGX_EPC_ADDR_PROP, SGXEPCDevice, addr, 0),
|
DEFINE_PROP_UINT64(SGX_EPC_ADDR_PROP, SGXEPCDevice, addr, 0),
|
||||||
|
DEFINE_PROP_UINT32(SGX_EPC_NUMA_NODE_PROP, SGXEPCDevice, node, 0),
|
||||||
DEFINE_PROP_LINK(SGX_EPC_MEMDEV_PROP, SGXEPCDevice, hostmem,
|
DEFINE_PROP_LINK(SGX_EPC_MEMDEV_PROP, SGXEPCDevice, hostmem,
|
||||||
TYPE_MEMORY_BACKEND_EPC, HostMemoryBackendEpc *),
|
TYPE_MEMORY_BACKEND_EPC, HostMemoryBackendEpc *),
|
||||||
DEFINE_PROP_END_OF_LIST(),
|
DEFINE_PROP_END_OF_LIST(),
|
||||||
@ -139,6 +140,8 @@ static void sgx_epc_md_fill_device_info(const MemoryDeviceState *md,
|
|||||||
se->memaddr = epc->addr;
|
se->memaddr = epc->addr;
|
||||||
se->size = object_property_get_uint(OBJECT(epc), SGX_EPC_SIZE_PROP,
|
se->size = object_property_get_uint(OBJECT(epc), SGX_EPC_SIZE_PROP,
|
||||||
NULL);
|
NULL);
|
||||||
|
se->node = object_property_get_uint(OBJECT(epc), SGX_EPC_NUMA_NODE_PROP,
|
||||||
|
NULL);
|
||||||
se->memdev = object_get_canonical_path(OBJECT(epc->hostmem));
|
se->memdev = object_get_canonical_path(OBJECT(epc->hostmem));
|
||||||
|
|
||||||
info->u.sgx_epc.data = se;
|
info->u.sgx_epc.data = se;
|
||||||
|
@ -6,6 +6,10 @@
|
|||||||
#include "qapi/error.h"
|
#include "qapi/error.h"
|
||||||
#include "qapi/qapi-commands-misc-target.h"
|
#include "qapi/qapi-commands-misc-target.h"
|
||||||
|
|
||||||
|
void sgx_epc_build_srat(GArray *table_data)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
SGXInfo *qmp_query_sgx(Error **errp)
|
SGXInfo *qmp_query_sgx(Error **errp)
|
||||||
{
|
{
|
||||||
error_setg(errp, "SGX support is not compiled in");
|
error_setg(errp, "SGX support is not compiled in");
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
#include "sysemu/hw_accel.h"
|
#include "sysemu/hw_accel.h"
|
||||||
#include "sysemu/reset.h"
|
#include "sysemu/reset.h"
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
|
#include "hw/acpi/aml-build.h"
|
||||||
|
|
||||||
#define SGX_MAX_EPC_SECTIONS 8
|
#define SGX_MAX_EPC_SECTIONS 8
|
||||||
#define SGX_CPUID_EPC_INVALID 0x0
|
#define SGX_CPUID_EPC_INVALID 0x0
|
||||||
@ -36,17 +37,59 @@
|
|||||||
|
|
||||||
#define RETRY_NUM 2
|
#define RETRY_NUM 2
|
||||||
|
|
||||||
|
static int sgx_epc_device_list(Object *obj, void *opaque)
|
||||||
|
{
|
||||||
|
GSList **list = opaque;
|
||||||
|
|
||||||
|
if (object_dynamic_cast(obj, TYPE_SGX_EPC)) {
|
||||||
|
*list = g_slist_append(*list, DEVICE(obj));
|
||||||
|
}
|
||||||
|
|
||||||
|
object_child_foreach(obj, sgx_epc_device_list, opaque);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GSList *sgx_epc_get_device_list(void)
|
||||||
|
{
|
||||||
|
GSList *list = NULL;
|
||||||
|
|
||||||
|
object_child_foreach(qdev_get_machine(), sgx_epc_device_list, &list);
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
void sgx_epc_build_srat(GArray *table_data)
|
||||||
|
{
|
||||||
|
GSList *device_list = sgx_epc_get_device_list();
|
||||||
|
|
||||||
|
for (; device_list; device_list = device_list->next) {
|
||||||
|
DeviceState *dev = device_list->data;
|
||||||
|
Object *obj = OBJECT(dev);
|
||||||
|
uint64_t addr, size;
|
||||||
|
int node;
|
||||||
|
|
||||||
|
node = object_property_get_uint(obj, SGX_EPC_NUMA_NODE_PROP,
|
||||||
|
&error_abort);
|
||||||
|
addr = object_property_get_uint(obj, SGX_EPC_ADDR_PROP, &error_abort);
|
||||||
|
size = object_property_get_uint(obj, SGX_EPC_SIZE_PROP, &error_abort);
|
||||||
|
|
||||||
|
build_srat_memory(table_data, addr, size, node, MEM_AFFINITY_ENABLED);
|
||||||
|
}
|
||||||
|
g_slist_free(device_list);
|
||||||
|
}
|
||||||
|
|
||||||
static uint64_t sgx_calc_section_metric(uint64_t low, uint64_t high)
|
static uint64_t sgx_calc_section_metric(uint64_t low, uint64_t high)
|
||||||
{
|
{
|
||||||
return (low & MAKE_64BIT_MASK(12, 20)) +
|
return (low & MAKE_64BIT_MASK(12, 20)) +
|
||||||
((high & MAKE_64BIT_MASK(0, 20)) << 32);
|
((high & MAKE_64BIT_MASK(0, 20)) << 32);
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint64_t sgx_calc_host_epc_section_size(void)
|
static SGXEPCSectionList *sgx_calc_host_epc_sections(void)
|
||||||
{
|
{
|
||||||
|
SGXEPCSectionList *head = NULL, **tail = &head;
|
||||||
|
SGXEPCSection *section;
|
||||||
uint32_t i, type;
|
uint32_t i, type;
|
||||||
uint32_t eax, ebx, ecx, edx;
|
uint32_t eax, ebx, ecx, edx;
|
||||||
uint64_t size = 0;
|
uint32_t j = 0;
|
||||||
|
|
||||||
for (i = 0; i < SGX_MAX_EPC_SECTIONS; i++) {
|
for (i = 0; i < SGX_MAX_EPC_SECTIONS; i++) {
|
||||||
host_cpuid(0x12, i + 2, &eax, &ebx, &ecx, &edx);
|
host_cpuid(0x12, i + 2, &eax, &ebx, &ecx, &edx);
|
||||||
@ -60,10 +103,13 @@ static uint64_t sgx_calc_host_epc_section_size(void)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
size += sgx_calc_section_metric(ecx, edx);
|
section = g_new0(SGXEPCSection, 1);
|
||||||
|
section->node = j++;
|
||||||
|
section->size = sgx_calc_section_metric(ecx, edx);
|
||||||
|
QAPI_LIST_APPEND(tail, section);
|
||||||
}
|
}
|
||||||
|
|
||||||
return size;
|
return head;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sgx_epc_reset(void *opaque)
|
static void sgx_epc_reset(void *opaque)
|
||||||
@ -127,13 +173,35 @@ SGXInfo *qmp_query_sgx_capabilities(Error **errp)
|
|||||||
info->sgx1 = eax & (1U << 0) ? true : false;
|
info->sgx1 = eax & (1U << 0) ? true : false;
|
||||||
info->sgx2 = eax & (1U << 1) ? true : false;
|
info->sgx2 = eax & (1U << 1) ? true : false;
|
||||||
|
|
||||||
info->section_size = sgx_calc_host_epc_section_size();
|
info->sections = sgx_calc_host_epc_sections();
|
||||||
|
|
||||||
close(fd);
|
close(fd);
|
||||||
|
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static SGXEPCSectionList *sgx_get_epc_sections_list(void)
|
||||||
|
{
|
||||||
|
GSList *device_list = sgx_epc_get_device_list();
|
||||||
|
SGXEPCSectionList *head = NULL, **tail = &head;
|
||||||
|
SGXEPCSection *section;
|
||||||
|
|
||||||
|
for (; device_list; device_list = device_list->next) {
|
||||||
|
DeviceState *dev = device_list->data;
|
||||||
|
Object *obj = OBJECT(dev);
|
||||||
|
|
||||||
|
section = g_new0(SGXEPCSection, 1);
|
||||||
|
section->node = object_property_get_uint(obj, SGX_EPC_NUMA_NODE_PROP,
|
||||||
|
&error_abort);
|
||||||
|
section->size = object_property_get_uint(obj, SGX_EPC_SIZE_PROP,
|
||||||
|
&error_abort);
|
||||||
|
QAPI_LIST_APPEND(tail, section);
|
||||||
|
}
|
||||||
|
g_slist_free(device_list);
|
||||||
|
|
||||||
|
return head;
|
||||||
|
}
|
||||||
|
|
||||||
SGXInfo *qmp_query_sgx(Error **errp)
|
SGXInfo *qmp_query_sgx(Error **errp)
|
||||||
{
|
{
|
||||||
SGXInfo *info = NULL;
|
SGXInfo *info = NULL;
|
||||||
@ -152,14 +220,13 @@ SGXInfo *qmp_query_sgx(Error **errp)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
SGXEPCState *sgx_epc = &pcms->sgx_epc;
|
|
||||||
info = g_new0(SGXInfo, 1);
|
info = g_new0(SGXInfo, 1);
|
||||||
|
|
||||||
info->sgx = true;
|
info->sgx = true;
|
||||||
info->sgx1 = true;
|
info->sgx1 = true;
|
||||||
info->sgx2 = true;
|
info->sgx2 = true;
|
||||||
info->flc = true;
|
info->flc = true;
|
||||||
info->section_size = sgx_epc->size;
|
info->sections = sgx_get_epc_sections_list();
|
||||||
|
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
@ -167,6 +234,7 @@ SGXInfo *qmp_query_sgx(Error **errp)
|
|||||||
void hmp_info_sgx(Monitor *mon, const QDict *qdict)
|
void hmp_info_sgx(Monitor *mon, const QDict *qdict)
|
||||||
{
|
{
|
||||||
Error *err = NULL;
|
Error *err = NULL;
|
||||||
|
SGXEPCSectionList *section_list, *section;
|
||||||
g_autoptr(SGXInfo) info = qmp_query_sgx(&err);
|
g_autoptr(SGXInfo) info = qmp_query_sgx(&err);
|
||||||
|
|
||||||
if (err) {
|
if (err) {
|
||||||
@ -181,8 +249,14 @@ void hmp_info_sgx(Monitor *mon, const QDict *qdict)
|
|||||||
info->sgx2 ? "enabled" : "disabled");
|
info->sgx2 ? "enabled" : "disabled");
|
||||||
monitor_printf(mon, "FLC support: %s\n",
|
monitor_printf(mon, "FLC support: %s\n",
|
||||||
info->flc ? "enabled" : "disabled");
|
info->flc ? "enabled" : "disabled");
|
||||||
monitor_printf(mon, "size: %" PRIu64 "\n",
|
|
||||||
info->section_size);
|
section_list = info->sections;
|
||||||
|
for (section = section_list; section; section = section->next) {
|
||||||
|
monitor_printf(mon, "NUMA node #%" PRId64 ": ",
|
||||||
|
section->value->node);
|
||||||
|
monitor_printf(mon, "size=%" PRIu64 "\n",
|
||||||
|
section->value->size);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool sgx_epc_get_section(int section_nr, uint64_t *addr, uint64_t *size)
|
bool sgx_epc_get_section(int section_nr, uint64_t *addr, uint64_t *size)
|
||||||
@ -226,6 +300,9 @@ void pc_machine_init_sgx_epc(PCMachineState *pcms)
|
|||||||
/* set the memdev link with memory backend */
|
/* set the memdev link with memory backend */
|
||||||
object_property_parse(obj, SGX_EPC_MEMDEV_PROP, list->value->memdev,
|
object_property_parse(obj, SGX_EPC_MEMDEV_PROP, list->value->memdev,
|
||||||
&error_fatal);
|
&error_fatal);
|
||||||
|
/* set the numa node property for sgx epc object */
|
||||||
|
object_property_set_uint(obj, SGX_EPC_NUMA_NODE_PROP, list->value->node,
|
||||||
|
&error_fatal);
|
||||||
object_property_set_bool(obj, "realized", true, &error_fatal);
|
object_property_set_bool(obj, "realized", true, &error_fatal);
|
||||||
object_unref(obj);
|
object_unref(obj);
|
||||||
}
|
}
|
||||||
|
@ -286,6 +286,10 @@ static void vmmouse_realizefn(DeviceState *dev, Error **errp)
|
|||||||
|
|
||||||
DPRINTF("vmmouse_init\n");
|
DPRINTF("vmmouse_init\n");
|
||||||
|
|
||||||
|
if (!s->i8042) {
|
||||||
|
error_setg(errp, "'i8042' link is not set");
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (!object_resolve_path_type("", TYPE_VMPORT, NULL)) {
|
if (!object_resolve_path_type("", TYPE_VMPORT, NULL)) {
|
||||||
error_setg(errp, "vmmouse needs a machine with vmport");
|
error_setg(errp, "vmmouse needs a machine with vmport");
|
||||||
return;
|
return;
|
||||||
|
@ -25,6 +25,11 @@ config APIC
|
|||||||
select MSI_NONBROKEN
|
select MSI_NONBROKEN
|
||||||
select I8259
|
select I8259
|
||||||
|
|
||||||
|
config ARM_GIC_TCG
|
||||||
|
bool
|
||||||
|
default y
|
||||||
|
depends on ARM_GIC && TCG
|
||||||
|
|
||||||
config ARM_GIC_KVM
|
config ARM_GIC_KVM
|
||||||
bool
|
bool
|
||||||
default y
|
default y
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* ARM Generic Interrupt Controller v3
|
* ARM Generic Interrupt Controller v3 (emulation)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015 Huawei.
|
* Copyright (c) 2015 Huawei.
|
||||||
* Copyright (c) 2016 Linaro Limited
|
* Copyright (c) 2016 Linaro Limited
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* ARM Generic Interrupt Controller v3
|
* ARM Generic Interrupt Controller v3 (emulation)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2016 Linaro Limited
|
* Copyright (c) 2016 Linaro Limited
|
||||||
* Written by Peter Maydell
|
* Written by Peter Maydell
|
||||||
@ -21,14 +21,6 @@
|
|||||||
#include "hw/irq.h"
|
#include "hw/irq.h"
|
||||||
#include "cpu.h"
|
#include "cpu.h"
|
||||||
|
|
||||||
void gicv3_set_gicv3state(CPUState *cpu, GICv3CPUState *s)
|
|
||||||
{
|
|
||||||
ARMCPU *arm_cpu = ARM_CPU(cpu);
|
|
||||||
CPUARMState *env = &arm_cpu->env;
|
|
||||||
|
|
||||||
env->gicv3state = (void *)s;
|
|
||||||
};
|
|
||||||
|
|
||||||
static GICv3CPUState *icc_cs_from_env(CPUARMState *env)
|
static GICv3CPUState *icc_cs_from_env(CPUARMState *env)
|
||||||
{
|
{
|
||||||
return env->gicv3state;
|
return env->gicv3state;
|
||||||
@ -351,7 +343,8 @@ static uint32_t maintenance_interrupt_state(GICv3CPUState *cs)
|
|||||||
/* Scan list registers and fill in the U, NP and EOI bits */
|
/* Scan list registers and fill in the U, NP and EOI bits */
|
||||||
eoi_maintenance_interrupt_state(cs, &value);
|
eoi_maintenance_interrupt_state(cs, &value);
|
||||||
|
|
||||||
if (cs->ich_hcr_el2 & (ICH_HCR_EL2_LRENPIE | ICH_HCR_EL2_EOICOUNT_MASK)) {
|
if ((cs->ich_hcr_el2 & ICH_HCR_EL2_LRENPIE) &&
|
||||||
|
(cs->ich_hcr_el2 & ICH_HCR_EL2_EOICOUNT_MASK)) {
|
||||||
value |= ICH_MISR_EL2_LRENP;
|
value |= ICH_MISR_EL2_LRENP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
22
hw/intc/arm_gicv3_cpuif_common.c
Normal file
22
hw/intc/arm_gicv3_cpuif_common.c
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||||
|
/*
|
||||||
|
* ARM Generic Interrupt Controller v3
|
||||||
|
*
|
||||||
|
* Copyright (c) 2016 Linaro Limited
|
||||||
|
* Written by Peter Maydell
|
||||||
|
*
|
||||||
|
* This code is licensed under the GPL, version 2 or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "qemu/osdep.h"
|
||||||
|
#include "gicv3_internal.h"
|
||||||
|
#include "cpu.h"
|
||||||
|
|
||||||
|
void gicv3_set_gicv3state(CPUState *cpu, GICv3CPUState *s)
|
||||||
|
{
|
||||||
|
ARMCPU *arm_cpu = ARM_CPU(cpu);
|
||||||
|
CPUARMState *env = &arm_cpu->env;
|
||||||
|
|
||||||
|
env->gicv3state = (void *)s;
|
||||||
|
};
|
@ -274,21 +274,36 @@ static bool process_its_cmd(GICv3ITSState *s, uint64_t value, uint32_t offset,
|
|||||||
if (res != MEMTX_OK) {
|
if (res != MEMTX_OK) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
qemu_log_mask(LOG_GUEST_ERROR,
|
||||||
|
"%s: invalid command attributes: "
|
||||||
|
"invalid dte: %"PRIx64" for %d (MEM_TX: %d)\n",
|
||||||
|
__func__, dte, devid, res);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((devid > s->dt.maxids.max_devids) || !dte_valid || !ite_valid ||
|
|
||||||
!cte_valid || (eventid > max_eventid)) {
|
|
||||||
qemu_log_mask(LOG_GUEST_ERROR,
|
|
||||||
"%s: invalid command attributes "
|
|
||||||
"devid %d or eventid %d or invalid dte %d or"
|
|
||||||
"invalid cte %d or invalid ite %d\n",
|
|
||||||
__func__, devid, eventid, dte_valid, cte_valid,
|
|
||||||
ite_valid);
|
|
||||||
/*
|
/*
|
||||||
* in this implementation, in case of error
|
* In this implementation, in case of guest errors we ignore the
|
||||||
* we ignore this command and move onto the next
|
* command and move onto the next command in the queue.
|
||||||
* command in the queue
|
|
||||||
*/
|
*/
|
||||||
|
if (devid > s->dt.maxids.max_devids) {
|
||||||
|
qemu_log_mask(LOG_GUEST_ERROR,
|
||||||
|
"%s: invalid command attributes: devid %d>%d",
|
||||||
|
__func__, devid, s->dt.maxids.max_devids);
|
||||||
|
|
||||||
|
} else if (!dte_valid || !ite_valid || !cte_valid) {
|
||||||
|
qemu_log_mask(LOG_GUEST_ERROR,
|
||||||
|
"%s: invalid command attributes: "
|
||||||
|
"dte: %s, ite: %s, cte: %s\n",
|
||||||
|
__func__,
|
||||||
|
dte_valid ? "valid" : "invalid",
|
||||||
|
ite_valid ? "valid" : "invalid",
|
||||||
|
cte_valid ? "valid" : "invalid");
|
||||||
|
} else if (eventid > max_eventid) {
|
||||||
|
qemu_log_mask(LOG_GUEST_ERROR,
|
||||||
|
"%s: invalid command attributes: eventid %d > %d\n",
|
||||||
|
__func__, eventid, max_eventid);
|
||||||
} else {
|
} else {
|
||||||
/*
|
/*
|
||||||
* Current implementation only supports rdbase == procnum
|
* Current implementation only supports rdbase == procnum
|
||||||
|
@ -3,12 +3,14 @@ softmmu_ss.add(when: 'CONFIG_ARM_GIC', if_true: files(
|
|||||||
'arm_gic.c',
|
'arm_gic.c',
|
||||||
'arm_gic_common.c',
|
'arm_gic_common.c',
|
||||||
'arm_gicv2m.c',
|
'arm_gicv2m.c',
|
||||||
'arm_gicv3.c',
|
|
||||||
'arm_gicv3_common.c',
|
'arm_gicv3_common.c',
|
||||||
'arm_gicv3_dist.c',
|
|
||||||
'arm_gicv3_its_common.c',
|
'arm_gicv3_its_common.c',
|
||||||
'arm_gicv3_redist.c',
|
))
|
||||||
|
softmmu_ss.add(when: 'CONFIG_ARM_GIC_TCG', if_true: files(
|
||||||
|
'arm_gicv3.c',
|
||||||
|
'arm_gicv3_dist.c',
|
||||||
'arm_gicv3_its.c',
|
'arm_gicv3_its.c',
|
||||||
|
'arm_gicv3_redist.c',
|
||||||
))
|
))
|
||||||
softmmu_ss.add(when: 'CONFIG_ETRAXFS', if_true: files('etraxfs_pic.c'))
|
softmmu_ss.add(when: 'CONFIG_ETRAXFS', if_true: files('etraxfs_pic.c'))
|
||||||
softmmu_ss.add(when: 'CONFIG_HEATHROW_PIC', if_true: files('heathrow_pic.c'))
|
softmmu_ss.add(when: 'CONFIG_HEATHROW_PIC', if_true: files('heathrow_pic.c'))
|
||||||
@ -25,7 +27,8 @@ softmmu_ss.add(when: 'CONFIG_XLNX_ZYNQMP_PMU', if_true: files('xlnx-pmu-iomod-in
|
|||||||
|
|
||||||
specific_ss.add(when: 'CONFIG_ALLWINNER_A10_PIC', if_true: files('allwinner-a10-pic.c'))
|
specific_ss.add(when: 'CONFIG_ALLWINNER_A10_PIC', if_true: files('allwinner-a10-pic.c'))
|
||||||
specific_ss.add(when: 'CONFIG_APIC', if_true: files('apic.c', 'apic_common.c'))
|
specific_ss.add(when: 'CONFIG_APIC', if_true: files('apic.c', 'apic_common.c'))
|
||||||
specific_ss.add(when: 'CONFIG_ARM_GIC', if_true: files('arm_gicv3_cpuif.c'))
|
specific_ss.add(when: 'CONFIG_ARM_GIC', if_true: files('arm_gicv3_cpuif_common.c'))
|
||||||
|
specific_ss.add(when: 'CONFIG_ARM_GIC_TCG', if_true: files('arm_gicv3_cpuif.c'))
|
||||||
specific_ss.add(when: 'CONFIG_ARM_GIC_KVM', if_true: files('arm_gic_kvm.c'))
|
specific_ss.add(when: 'CONFIG_ARM_GIC_KVM', if_true: files('arm_gic_kvm.c'))
|
||||||
specific_ss.add(when: ['CONFIG_ARM_GIC_KVM', 'TARGET_AARCH64'], if_true: files('arm_gicv3_kvm.c', 'arm_gicv3_its_kvm.c'))
|
specific_ss.add(when: ['CONFIG_ARM_GIC_KVM', 'TARGET_AARCH64'], if_true: files('arm_gicv3_kvm.c', 'arm_gicv3_its_kvm.c'))
|
||||||
specific_ss.add(when: 'CONFIG_ARM_V7M', if_true: files('armv7m_nvic.c'))
|
specific_ss.add(when: 'CONFIG_ARM_V7M', if_true: files('armv7m_nvic.c'))
|
||||||
|
@ -183,7 +183,7 @@ petalogix_ml605_init(MachineState *machine)
|
|||||||
spi = (SSIBus *)qdev_get_child_bus(dev, "spi");
|
spi = (SSIBus *)qdev_get_child_bus(dev, "spi");
|
||||||
|
|
||||||
for (i = 0; i < NUM_SPI_FLASHES; i++) {
|
for (i = 0; i < NUM_SPI_FLASHES; i++) {
|
||||||
DriveInfo *dinfo = drive_get_next(IF_MTD);
|
DriveInfo *dinfo = drive_get(IF_MTD, 0, i);
|
||||||
qemu_irq cs_line;
|
qemu_irq cs_line;
|
||||||
|
|
||||||
dev = qdev_new("n25q128");
|
dev = qdev_new("n25q128");
|
||||||
|
@ -182,7 +182,11 @@ void bl_gen_write_ulong(uint32_t **p, target_ulong addr, target_ulong val)
|
|||||||
{
|
{
|
||||||
bl_gen_load_ulong(p, BL_REG_K0, val);
|
bl_gen_load_ulong(p, BL_REG_K0, val);
|
||||||
bl_gen_load_ulong(p, BL_REG_K1, addr);
|
bl_gen_load_ulong(p, BL_REG_K1, addr);
|
||||||
|
if (bootcpu_supports_isa(ISA_MIPS3)) {
|
||||||
bl_gen_sd(p, BL_REG_K0, BL_REG_K1, 0x0);
|
bl_gen_sd(p, BL_REG_K0, BL_REG_K1, 0x0);
|
||||||
|
} else {
|
||||||
|
bl_gen_sw(p, BL_REG_K0, BL_REG_K1, 0x0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void bl_gen_write_u32(uint32_t **p, target_ulong addr, uint32_t val)
|
void bl_gen_write_u32(uint32_t **p, target_ulong addr, uint32_t val)
|
||||||
|
@ -777,14 +777,15 @@ static void boston_mach_init(MachineState *machine)
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
} else if (machine->kernel_filename) {
|
} else if (machine->kernel_filename) {
|
||||||
uint64_t kernel_entry, kernel_high, kernel_size;
|
uint64_t kernel_entry, kernel_high;
|
||||||
|
ssize_t kernel_size;
|
||||||
|
|
||||||
kernel_size = load_elf(machine->kernel_filename, NULL,
|
kernel_size = load_elf(machine->kernel_filename, NULL,
|
||||||
cpu_mips_kseg0_to_phys, NULL,
|
cpu_mips_kseg0_to_phys, NULL,
|
||||||
&kernel_entry, NULL, &kernel_high,
|
&kernel_entry, NULL, &kernel_high,
|
||||||
NULL, 0, EM_MIPS, 1, 0);
|
NULL, 0, EM_MIPS, 1, 0);
|
||||||
|
|
||||||
if (kernel_size) {
|
if (kernel_size > 0) {
|
||||||
int dt_size;
|
int dt_size;
|
||||||
g_autofree const void *dtb_file_data, *dtb_load_data;
|
g_autofree const void *dtb_file_data, *dtb_load_data;
|
||||||
hwaddr dtb_paddr = QEMU_ALIGN_UP(kernel_high, 64 * KiB);
|
hwaddr dtb_paddr = QEMU_ALIGN_UP(kernel_high, 64 * KiB);
|
||||||
|
@ -243,7 +243,7 @@ static uint64_t ivshmem_io_read(void *opaque, hwaddr addr,
|
|||||||
static const MemoryRegionOps ivshmem_mmio_ops = {
|
static const MemoryRegionOps ivshmem_mmio_ops = {
|
||||||
.read = ivshmem_io_read,
|
.read = ivshmem_io_read,
|
||||||
.write = ivshmem_io_write,
|
.write = ivshmem_io_write,
|
||||||
.endianness = DEVICE_NATIVE_ENDIAN,
|
.endianness = DEVICE_LITTLE_ENDIAN,
|
||||||
.impl = {
|
.impl = {
|
||||||
.min_access_size = 4,
|
.min_access_size = 4,
|
||||||
.max_access_size = 4,
|
.max_access_size = 4,
|
||||||
|
@ -209,9 +209,9 @@ static void sifive_u_otp_realize(DeviceState *dev, Error **errp)
|
|||||||
TYPE_SIFIVE_U_OTP, SIFIVE_U_OTP_REG_SIZE);
|
TYPE_SIFIVE_U_OTP, SIFIVE_U_OTP_REG_SIZE);
|
||||||
sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->mmio);
|
sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->mmio);
|
||||||
|
|
||||||
dinfo = drive_get_next(IF_PFLASH);
|
dinfo = drive_get(IF_PFLASH, 0, 0);
|
||||||
if (!dinfo) {
|
if (!dinfo) {
|
||||||
dinfo = drive_get_next(IF_NONE);
|
dinfo = drive_get(IF_NONE, 0, 0);
|
||||||
if (dinfo) {
|
if (dinfo) {
|
||||||
warn_report("using \"-drive if=none\" for the OTP is deprecated, "
|
warn_report("using \"-drive if=none\" for the OTP is deprecated, "
|
||||||
"use \"-drive if=pflash\" instead.");
|
"use \"-drive if=pflash\" instead.");
|
||||||
|
@ -284,6 +284,12 @@ static void emc_halt_rx(NPCM7xxEMCState *emc, uint32_t mista_flag)
|
|||||||
emc_set_mista(emc, mista_flag);
|
emc_set_mista(emc, mista_flag);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void emc_enable_rx_and_flush(NPCM7xxEMCState *emc)
|
||||||
|
{
|
||||||
|
emc->rx_active = true;
|
||||||
|
qemu_flush_queued_packets(qemu_get_queue(emc->nic));
|
||||||
|
}
|
||||||
|
|
||||||
static void emc_set_next_tx_descriptor(NPCM7xxEMCState *emc,
|
static void emc_set_next_tx_descriptor(NPCM7xxEMCState *emc,
|
||||||
const NPCM7xxEMCTxDesc *tx_desc,
|
const NPCM7xxEMCTxDesc *tx_desc,
|
||||||
uint32_t desc_addr)
|
uint32_t desc_addr)
|
||||||
@ -581,13 +587,6 @@ static ssize_t emc_receive(NetClientState *nc, const uint8_t *buf, size_t len1)
|
|||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void emc_try_receive_next_packet(NPCM7xxEMCState *emc)
|
|
||||||
{
|
|
||||||
if (emc_can_receive(qemu_get_queue(emc->nic))) {
|
|
||||||
qemu_flush_queued_packets(qemu_get_queue(emc->nic));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint64_t npcm7xx_emc_read(void *opaque, hwaddr offset, unsigned size)
|
static uint64_t npcm7xx_emc_read(void *opaque, hwaddr offset, unsigned size)
|
||||||
{
|
{
|
||||||
NPCM7xxEMCState *emc = opaque;
|
NPCM7xxEMCState *emc = opaque;
|
||||||
@ -703,7 +702,7 @@ static void npcm7xx_emc_write(void *opaque, hwaddr offset,
|
|||||||
emc->regs[REG_MGSTA] |= REG_MGSTA_RXHA;
|
emc->regs[REG_MGSTA] |= REG_MGSTA_RXHA;
|
||||||
}
|
}
|
||||||
if (value & REG_MCMDR_RXON) {
|
if (value & REG_MCMDR_RXON) {
|
||||||
emc->rx_active = true;
|
emc_enable_rx_and_flush(emc);
|
||||||
} else {
|
} else {
|
||||||
emc_halt_rx(emc, 0);
|
emc_halt_rx(emc, 0);
|
||||||
}
|
}
|
||||||
@ -739,8 +738,7 @@ static void npcm7xx_emc_write(void *opaque, hwaddr offset,
|
|||||||
break;
|
break;
|
||||||
case REG_RSDR:
|
case REG_RSDR:
|
||||||
if (emc->regs[REG_MCMDR] & REG_MCMDR_RXON) {
|
if (emc->regs[REG_MCMDR] & REG_MCMDR_RXON) {
|
||||||
emc->rx_active = true;
|
emc_enable_rx_and_flush(emc);
|
||||||
emc_try_receive_next_packet(emc);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case REG_MIIDA:
|
case REG_MIIDA:
|
||||||
|
@ -993,7 +993,7 @@ static void pnv_phb3_realize(DeviceState *dev, Error **errp)
|
|||||||
PnvMachineState *pnv = PNV_MACHINE(qdev_get_machine());
|
PnvMachineState *pnv = PNV_MACHINE(qdev_get_machine());
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (phb->phb_id >= PNV8_CHIP_PHB3_MAX) {
|
if (phb->phb_id >= PNV_CHIP_GET_CLASS(phb->chip)->num_phbs) {
|
||||||
error_setg(errp, "invalid PHB index: %d", phb->phb_id);
|
error_setg(errp, "invalid PHB index: %d", phb->phb_id);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1092,6 +1092,7 @@ static const char *pnv_phb3_root_bus_path(PCIHostState *host_bridge,
|
|||||||
static Property pnv_phb3_properties[] = {
|
static Property pnv_phb3_properties[] = {
|
||||||
DEFINE_PROP_UINT32("index", PnvPHB3, phb_id, 0),
|
DEFINE_PROP_UINT32("index", PnvPHB3, phb_id, 0),
|
||||||
DEFINE_PROP_UINT32("chip-id", PnvPHB3, chip_id, 0),
|
DEFINE_PROP_UINT32("chip-id", PnvPHB3, chip_id, 0),
|
||||||
|
DEFINE_PROP_LINK("chip", PnvPHB3, chip, TYPE_PNV_CHIP, PnvChip *),
|
||||||
DEFINE_PROP_END_OF_LIST(),
|
DEFINE_PROP_END_OF_LIST(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -284,6 +284,17 @@ static void pnv_pbcq_realize(DeviceState *dev, Error **errp)
|
|||||||
pnv_xscom_region_init(&pbcq->xscom_spci_regs, OBJECT(dev),
|
pnv_xscom_region_init(&pbcq->xscom_spci_regs, OBJECT(dev),
|
||||||
&pnv_pbcq_spci_xscom_ops, pbcq, name,
|
&pnv_pbcq_spci_xscom_ops, pbcq, name,
|
||||||
PNV_XSCOM_PBCQ_SPCI_SIZE);
|
PNV_XSCOM_PBCQ_SPCI_SIZE);
|
||||||
|
|
||||||
|
/* Populate the XSCOM address space. */
|
||||||
|
pnv_xscom_add_subregion(phb->chip,
|
||||||
|
PNV_XSCOM_PBCQ_NEST_BASE + 0x400 * phb->phb_id,
|
||||||
|
&pbcq->xscom_nest_regs);
|
||||||
|
pnv_xscom_add_subregion(phb->chip,
|
||||||
|
PNV_XSCOM_PBCQ_PCI_BASE + 0x400 * phb->phb_id,
|
||||||
|
&pbcq->xscom_pci_regs);
|
||||||
|
pnv_xscom_add_subregion(phb->chip,
|
||||||
|
PNV_XSCOM_PBCQ_SPCI_BASE + 0x040 * phb->phb_id,
|
||||||
|
&pbcq->xscom_spci_regs);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int pnv_pbcq_dt_xscom(PnvXScomInterface *dev, void *fdt,
|
static int pnv_pbcq_dt_xscom(PnvXScomInterface *dev, void *fdt,
|
||||||
|
@ -1205,6 +1205,7 @@ static void pnv_phb4_realize(DeviceState *dev, Error **errp)
|
|||||||
&phb->pci_mmio, &phb->pci_io,
|
&phb->pci_mmio, &phb->pci_io,
|
||||||
0, 4, TYPE_PNV_PHB4_ROOT_BUS);
|
0, 4, TYPE_PNV_PHB4_ROOT_BUS);
|
||||||
pci_setup_iommu(pci->bus, pnv_phb4_dma_iommu, phb);
|
pci_setup_iommu(pci->bus, pnv_phb4_dma_iommu, phb);
|
||||||
|
pci->bus->flags |= PCI_BUS_EXTENDED_CONFIG_SPACE;
|
||||||
|
|
||||||
/* Add a single Root port */
|
/* Add a single Root port */
|
||||||
qdev_prop_set_uint8(DEVICE(&phb->root), "chassis", phb->chip_id);
|
qdev_prop_set_uint8(DEVICE(&phb->root), "chassis", phb->chip_id);
|
||||||
|
@ -124,7 +124,7 @@ static uint64_t pnv_pec_stk_nest_xscom_read(void *opaque, hwaddr addr,
|
|||||||
static void pnv_pec_stk_update_map(PnvPhb4PecStack *stack)
|
static void pnv_pec_stk_update_map(PnvPhb4PecStack *stack)
|
||||||
{
|
{
|
||||||
PnvPhb4PecState *pec = stack->pec;
|
PnvPhb4PecState *pec = stack->pec;
|
||||||
MemoryRegion *sysmem = pec->system_memory;
|
MemoryRegion *sysmem = get_system_memory();
|
||||||
uint64_t bar_en = stack->nest_regs[PEC_NEST_STK_BAR_EN];
|
uint64_t bar_en = stack->nest_regs[PEC_NEST_STK_BAR_EN];
|
||||||
uint64_t bar, mask, size;
|
uint64_t bar, mask, size;
|
||||||
char name[64];
|
char name[64];
|
||||||
@ -374,20 +374,41 @@ static void pnv_pec_instance_init(Object *obj)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int pnv_pec_phb_offset(PnvPhb4PecState *pec)
|
||||||
|
{
|
||||||
|
PnvPhb4PecClass *pecc = PNV_PHB4_PEC_GET_CLASS(pec);
|
||||||
|
int index = pec->index;
|
||||||
|
int offset = 0;
|
||||||
|
|
||||||
|
while (index--) {
|
||||||
|
offset += pecc->num_stacks[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
return offset;
|
||||||
|
}
|
||||||
|
|
||||||
static void pnv_pec_realize(DeviceState *dev, Error **errp)
|
static void pnv_pec_realize(DeviceState *dev, Error **errp)
|
||||||
{
|
{
|
||||||
PnvPhb4PecState *pec = PNV_PHB4_PEC(dev);
|
PnvPhb4PecState *pec = PNV_PHB4_PEC(dev);
|
||||||
|
PnvPhb4PecClass *pecc = PNV_PHB4_PEC_GET_CLASS(pec);
|
||||||
char name[64];
|
char name[64];
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
assert(pec->system_memory);
|
if (pec->index >= PNV_CHIP_GET_CLASS(pec->chip)->num_pecs) {
|
||||||
|
error_setg(errp, "invalid PEC index: %d", pec->index);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
pec->num_stacks = pecc->num_stacks[pec->index];
|
||||||
|
|
||||||
/* Create stacks */
|
/* Create stacks */
|
||||||
for (i = 0; i < pec->num_stacks; i++) {
|
for (i = 0; i < pec->num_stacks; i++) {
|
||||||
PnvPhb4PecStack *stack = &pec->stacks[i];
|
PnvPhb4PecStack *stack = &pec->stacks[i];
|
||||||
Object *stk_obj = OBJECT(stack);
|
Object *stk_obj = OBJECT(stack);
|
||||||
|
int phb_id = pnv_pec_phb_offset(pec) + i;
|
||||||
|
|
||||||
object_property_set_int(stk_obj, "stack-no", i, &error_abort);
|
object_property_set_int(stk_obj, "stack-no", i, &error_abort);
|
||||||
|
object_property_set_int(stk_obj, "phb-id", phb_id, &error_abort);
|
||||||
object_property_set_link(stk_obj, "pec", OBJECT(pec), &error_abort);
|
object_property_set_link(stk_obj, "pec", OBJECT(pec), &error_abort);
|
||||||
if (!qdev_realize(DEVICE(stk_obj), NULL, errp)) {
|
if (!qdev_realize(DEVICE(stk_obj), NULL, errp)) {
|
||||||
return;
|
return;
|
||||||
@ -460,10 +481,9 @@ static int pnv_pec_dt_xscom(PnvXScomInterface *dev, void *fdt,
|
|||||||
|
|
||||||
static Property pnv_pec_properties[] = {
|
static Property pnv_pec_properties[] = {
|
||||||
DEFINE_PROP_UINT32("index", PnvPhb4PecState, index, 0),
|
DEFINE_PROP_UINT32("index", PnvPhb4PecState, index, 0),
|
||||||
DEFINE_PROP_UINT32("num-stacks", PnvPhb4PecState, num_stacks, 0),
|
|
||||||
DEFINE_PROP_UINT32("chip-id", PnvPhb4PecState, chip_id, 0),
|
DEFINE_PROP_UINT32("chip-id", PnvPhb4PecState, chip_id, 0),
|
||||||
DEFINE_PROP_LINK("system-memory", PnvPhb4PecState, system_memory,
|
DEFINE_PROP_LINK("chip", PnvPhb4PecState, chip, TYPE_PNV_CHIP,
|
||||||
TYPE_MEMORY_REGION, MemoryRegion *),
|
PnvChip *),
|
||||||
DEFINE_PROP_END_OF_LIST(),
|
DEFINE_PROP_END_OF_LIST(),
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -477,6 +497,13 @@ static uint32_t pnv_pec_xscom_nest_base(PnvPhb4PecState *pec)
|
|||||||
return PNV9_XSCOM_PEC_NEST_BASE + 0x400 * pec->index;
|
return PNV9_XSCOM_PEC_NEST_BASE + 0x400 * pec->index;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* PEC0 -> 1 stack
|
||||||
|
* PEC1 -> 2 stacks
|
||||||
|
* PEC2 -> 3 stacks
|
||||||
|
*/
|
||||||
|
static const uint32_t pnv_pec_num_stacks[] = { 1, 2, 3 };
|
||||||
|
|
||||||
static void pnv_pec_class_init(ObjectClass *klass, void *data)
|
static void pnv_pec_class_init(ObjectClass *klass, void *data)
|
||||||
{
|
{
|
||||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||||
@ -499,6 +526,9 @@ static void pnv_pec_class_init(ObjectClass *klass, void *data)
|
|||||||
pecc->compat_size = sizeof(compat);
|
pecc->compat_size = sizeof(compat);
|
||||||
pecc->stk_compat = stk_compat;
|
pecc->stk_compat = stk_compat;
|
||||||
pecc->stk_compat_size = sizeof(stk_compat);
|
pecc->stk_compat_size = sizeof(stk_compat);
|
||||||
|
pecc->version = PNV_PHB4_VERSION;
|
||||||
|
pecc->device_id = PNV_PHB4_DEVICE_ID;
|
||||||
|
pecc->num_stacks = pnv_pec_num_stacks;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const TypeInfo pnv_pec_type_info = {
|
static const TypeInfo pnv_pec_type_info = {
|
||||||
@ -519,12 +549,17 @@ static void pnv_pec_stk_instance_init(Object *obj)
|
|||||||
PnvPhb4PecStack *stack = PNV_PHB4_PEC_STACK(obj);
|
PnvPhb4PecStack *stack = PNV_PHB4_PEC_STACK(obj);
|
||||||
|
|
||||||
object_initialize_child(obj, "phb", &stack->phb, TYPE_PNV_PHB4);
|
object_initialize_child(obj, "phb", &stack->phb, TYPE_PNV_PHB4);
|
||||||
|
object_property_add_alias(obj, "phb-id", OBJECT(&stack->phb), "index");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pnv_pec_stk_realize(DeviceState *dev, Error **errp)
|
static void pnv_pec_stk_realize(DeviceState *dev, Error **errp)
|
||||||
{
|
{
|
||||||
PnvPhb4PecStack *stack = PNV_PHB4_PEC_STACK(dev);
|
PnvPhb4PecStack *stack = PNV_PHB4_PEC_STACK(dev);
|
||||||
PnvPhb4PecState *pec = stack->pec;
|
PnvPhb4PecState *pec = stack->pec;
|
||||||
|
PnvPhb4PecClass *pecc = PNV_PHB4_PEC_GET_CLASS(pec);
|
||||||
|
PnvChip *chip = pec->chip;
|
||||||
|
uint32_t pec_nest_base;
|
||||||
|
uint32_t pec_pci_base;
|
||||||
char name[64];
|
char name[64];
|
||||||
|
|
||||||
assert(pec);
|
assert(pec);
|
||||||
@ -548,10 +583,32 @@ static void pnv_pec_stk_realize(DeviceState *dev, Error **errp)
|
|||||||
pnv_xscom_region_init(&stack->phb_regs_mr, OBJECT(&stack->phb),
|
pnv_xscom_region_init(&stack->phb_regs_mr, OBJECT(&stack->phb),
|
||||||
&pnv_phb4_xscom_ops, &stack->phb, name, 0x40);
|
&pnv_phb4_xscom_ops, &stack->phb, name, 0x40);
|
||||||
|
|
||||||
/*
|
object_property_set_int(OBJECT(&stack->phb), "chip-id", pec->chip_id,
|
||||||
* Let the machine/chip realize the PHB object to customize more
|
&error_fatal);
|
||||||
* easily some fields
|
object_property_set_int(OBJECT(&stack->phb), "version", pecc->version,
|
||||||
*/
|
&error_fatal);
|
||||||
|
object_property_set_int(OBJECT(&stack->phb), "device-id", pecc->device_id,
|
||||||
|
&error_fatal);
|
||||||
|
object_property_set_link(OBJECT(&stack->phb), "stack", OBJECT(stack),
|
||||||
|
&error_abort);
|
||||||
|
if (!sysbus_realize(SYS_BUS_DEVICE(&stack->phb), errp)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
pec_nest_base = pecc->xscom_nest_base(pec);
|
||||||
|
pec_pci_base = pecc->xscom_pci_base(pec);
|
||||||
|
|
||||||
|
/* Populate the XSCOM address space. */
|
||||||
|
pnv_xscom_add_subregion(chip,
|
||||||
|
pec_nest_base + 0x40 * (stack->stack_no + 1),
|
||||||
|
&stack->nest_regs_mr);
|
||||||
|
pnv_xscom_add_subregion(chip,
|
||||||
|
pec_pci_base + 0x40 * (stack->stack_no + 1),
|
||||||
|
&stack->pci_regs_mr);
|
||||||
|
pnv_xscom_add_subregion(chip,
|
||||||
|
pec_pci_base + PNV9_XSCOM_PEC_PCI_STK0 +
|
||||||
|
0x40 * stack->stack_no,
|
||||||
|
&stack->phb_regs_mr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Property pnv_pec_stk_properties[] = {
|
static Property pnv_pec_stk_properties[] = {
|
||||||
|
@ -36,9 +36,6 @@
|
|||||||
#include "hw/pci-host/uninorth.h"
|
#include "hw/pci-host/uninorth.h"
|
||||||
#include "qom/object.h"
|
#include "qom/object.h"
|
||||||
|
|
||||||
/* SMP is not enabled, for now */
|
|
||||||
#define MAX_CPUS 1
|
|
||||||
|
|
||||||
#define NVRAM_SIZE 0x2000
|
#define NVRAM_SIZE 0x2000
|
||||||
#define PROM_FILENAME "openbios-ppc"
|
#define PROM_FILENAME "openbios-ppc"
|
||||||
|
|
||||||
|
@ -581,7 +581,8 @@ static void core99_machine_class_init(ObjectClass *oc, void *data)
|
|||||||
mc->desc = "Mac99 based PowerMAC";
|
mc->desc = "Mac99 based PowerMAC";
|
||||||
mc->init = ppc_core99_init;
|
mc->init = ppc_core99_init;
|
||||||
mc->block_default_type = IF_IDE;
|
mc->block_default_type = IF_IDE;
|
||||||
mc->max_cpus = MAX_CPUS;
|
/* SMP is not supported currently */
|
||||||
|
mc->max_cpus = 1;
|
||||||
mc->default_boot_order = "cd";
|
mc->default_boot_order = "cd";
|
||||||
mc->default_display = "std";
|
mc->default_display = "std";
|
||||||
mc->kvm_type = core99_kvm_type;
|
mc->kvm_type = core99_kvm_type;
|
||||||
|
@ -423,7 +423,8 @@ static void heathrow_class_init(ObjectClass *oc, void *data)
|
|||||||
mc->desc = "Heathrow based PowerMAC";
|
mc->desc = "Heathrow based PowerMAC";
|
||||||
mc->init = ppc_heathrow_init;
|
mc->init = ppc_heathrow_init;
|
||||||
mc->block_default_type = IF_IDE;
|
mc->block_default_type = IF_IDE;
|
||||||
mc->max_cpus = MAX_CPUS;
|
/* SMP is not supported currently */
|
||||||
|
mc->max_cpus = 1;
|
||||||
#ifndef TARGET_PPC64
|
#ifndef TARGET_PPC64
|
||||||
mc->is_default = true;
|
mc->is_default = true;
|
||||||
#endif
|
#endif
|
||||||
|
177
hw/ppc/pnv.c
177
hw/ppc/pnv.c
@ -522,7 +522,7 @@ static void *pnv_dt_create(MachineState *machine)
|
|||||||
buf = qemu_uuid_unparse_strdup(&qemu_uuid);
|
buf = qemu_uuid_unparse_strdup(&qemu_uuid);
|
||||||
_FDT((fdt_setprop_string(fdt, 0, "vm,uuid", buf)));
|
_FDT((fdt_setprop_string(fdt, 0, "vm,uuid", buf)));
|
||||||
if (qemu_uuid_set) {
|
if (qemu_uuid_set) {
|
||||||
_FDT((fdt_property_string(fdt, "system-id", buf)));
|
_FDT((fdt_setprop_string(fdt, 0, "system-id", buf)));
|
||||||
}
|
}
|
||||||
g_free(buf);
|
g_free(buf);
|
||||||
|
|
||||||
@ -638,32 +638,47 @@ static ISABus *pnv_isa_create(PnvChip *chip, Error **errp)
|
|||||||
return PNV_CHIP_GET_CLASS(chip)->isa_create(chip, errp);
|
return PNV_CHIP_GET_CLASS(chip)->isa_create(chip, errp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int pnv_chip_power8_pic_print_info_child(Object *child, void *opaque)
|
||||||
|
{
|
||||||
|
Monitor *mon = opaque;
|
||||||
|
PnvPHB3 *phb3 = (PnvPHB3 *) object_dynamic_cast(child, TYPE_PNV_PHB3);
|
||||||
|
|
||||||
|
if (phb3) {
|
||||||
|
pnv_phb3_msi_pic_print_info(&phb3->msis, mon);
|
||||||
|
ics_pic_print_info(&phb3->lsis, mon);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static void pnv_chip_power8_pic_print_info(PnvChip *chip, Monitor *mon)
|
static void pnv_chip_power8_pic_print_info(PnvChip *chip, Monitor *mon)
|
||||||
{
|
{
|
||||||
Pnv8Chip *chip8 = PNV8_CHIP(chip);
|
Pnv8Chip *chip8 = PNV8_CHIP(chip);
|
||||||
int i;
|
|
||||||
|
|
||||||
ics_pic_print_info(&chip8->psi.ics, mon);
|
ics_pic_print_info(&chip8->psi.ics, mon);
|
||||||
for (i = 0; i < chip->num_phbs; i++) {
|
object_child_foreach(OBJECT(chip),
|
||||||
pnv_phb3_msi_pic_print_info(&chip8->phbs[i].msis, mon);
|
pnv_chip_power8_pic_print_info_child, mon);
|
||||||
ics_pic_print_info(&chip8->phbs[i].lsis, mon);
|
}
|
||||||
|
|
||||||
|
static int pnv_chip_power9_pic_print_info_child(Object *child, void *opaque)
|
||||||
|
{
|
||||||
|
Monitor *mon = opaque;
|
||||||
|
PnvPHB4 *phb4 = (PnvPHB4 *) object_dynamic_cast(child, TYPE_PNV_PHB4);
|
||||||
|
|
||||||
|
if (phb4) {
|
||||||
|
pnv_phb4_pic_print_info(phb4, mon);
|
||||||
}
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pnv_chip_power9_pic_print_info(PnvChip *chip, Monitor *mon)
|
static void pnv_chip_power9_pic_print_info(PnvChip *chip, Monitor *mon)
|
||||||
{
|
{
|
||||||
Pnv9Chip *chip9 = PNV9_CHIP(chip);
|
Pnv9Chip *chip9 = PNV9_CHIP(chip);
|
||||||
int i, j;
|
|
||||||
|
|
||||||
pnv_xive_pic_print_info(&chip9->xive, mon);
|
pnv_xive_pic_print_info(&chip9->xive, mon);
|
||||||
pnv_psi_pic_print_info(&chip9->psi, mon);
|
pnv_psi_pic_print_info(&chip9->psi, mon);
|
||||||
|
|
||||||
for (i = 0; i < PNV9_CHIP_MAX_PEC; i++) {
|
object_child_foreach_recursive(OBJECT(chip),
|
||||||
PnvPhb4PecState *pec = &chip9->pecs[i];
|
pnv_chip_power9_pic_print_info_child, mon);
|
||||||
for (j = 0; j < pec->num_stacks; j++) {
|
|
||||||
pnv_phb4_pic_print_info(&pec->stacks[j].phb, mon);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint64_t pnv_chip_power8_xscom_core_base(PnvChip *chip,
|
static uint64_t pnv_chip_power8_xscom_core_base(PnvChip *chip,
|
||||||
@ -742,6 +757,11 @@ static void pnv_init(MachineState *machine)
|
|||||||
DriveInfo *pnor = drive_get(IF_MTD, 0, 0);
|
DriveInfo *pnor = drive_get(IF_MTD, 0, 0);
|
||||||
DeviceState *dev;
|
DeviceState *dev;
|
||||||
|
|
||||||
|
if (kvm_enabled()) {
|
||||||
|
error_report("The powernv machine does not work with KVM acceleration");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
/* allocate RAM */
|
/* allocate RAM */
|
||||||
if (machine->ram_size < mc->default_ram_size) {
|
if (machine->ram_size < mc->default_ram_size) {
|
||||||
char *sz = size_to_str(mc->default_ram_size);
|
char *sz = size_to_str(mc->default_ram_size);
|
||||||
@ -1221,25 +1241,15 @@ static void pnv_chip_power8_realize(DeviceState *dev, Error **errp)
|
|||||||
/* PHB3 controllers */
|
/* PHB3 controllers */
|
||||||
for (i = 0; i < chip->num_phbs; i++) {
|
for (i = 0; i < chip->num_phbs; i++) {
|
||||||
PnvPHB3 *phb = &chip8->phbs[i];
|
PnvPHB3 *phb = &chip8->phbs[i];
|
||||||
PnvPBCQState *pbcq = &phb->pbcq;
|
|
||||||
|
|
||||||
object_property_set_int(OBJECT(phb), "index", i, &error_fatal);
|
object_property_set_int(OBJECT(phb), "index", i, &error_fatal);
|
||||||
object_property_set_int(OBJECT(phb), "chip-id", chip->chip_id,
|
object_property_set_int(OBJECT(phb), "chip-id", chip->chip_id,
|
||||||
&error_fatal);
|
&error_fatal);
|
||||||
|
object_property_set_link(OBJECT(phb), "chip", OBJECT(chip),
|
||||||
|
&error_fatal);
|
||||||
if (!sysbus_realize(SYS_BUS_DEVICE(phb), errp)) {
|
if (!sysbus_realize(SYS_BUS_DEVICE(phb), errp)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Populate the XSCOM address space. */
|
|
||||||
pnv_xscom_add_subregion(chip,
|
|
||||||
PNV_XSCOM_PBCQ_NEST_BASE + 0x400 * phb->phb_id,
|
|
||||||
&pbcq->xscom_nest_regs);
|
|
||||||
pnv_xscom_add_subregion(chip,
|
|
||||||
PNV_XSCOM_PBCQ_PCI_BASE + 0x400 * phb->phb_id,
|
|
||||||
&pbcq->xscom_pci_regs);
|
|
||||||
pnv_xscom_add_subregion(chip,
|
|
||||||
PNV_XSCOM_PBCQ_SPCI_BASE + 0x040 * phb->phb_id,
|
|
||||||
&pbcq->xscom_spci_regs);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1340,15 +1350,13 @@ static void pnv_chip_power9_instance_init(Object *obj)
|
|||||||
|
|
||||||
object_initialize_child(obj, "homer", &chip9->homer, TYPE_PNV9_HOMER);
|
object_initialize_child(obj, "homer", &chip9->homer, TYPE_PNV9_HOMER);
|
||||||
|
|
||||||
for (i = 0; i < PNV9_CHIP_MAX_PEC; i++) {
|
/* Number of PECs is the chip default */
|
||||||
|
chip->num_pecs = pcc->num_pecs;
|
||||||
|
|
||||||
|
for (i = 0; i < chip->num_pecs; i++) {
|
||||||
object_initialize_child(obj, "pec[*]", &chip9->pecs[i],
|
object_initialize_child(obj, "pec[*]", &chip9->pecs[i],
|
||||||
TYPE_PNV_PHB4_PEC);
|
TYPE_PNV_PHB4_PEC);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Number of PHBs is the chip default
|
|
||||||
*/
|
|
||||||
chip->num_phbs = pcc->num_phbs;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pnv_chip_quad_realize(Pnv9Chip *chip9, Error **errp)
|
static void pnv_chip_quad_realize(Pnv9Chip *chip9, Error **errp)
|
||||||
@ -1378,30 +1386,22 @@ static void pnv_chip_quad_realize(Pnv9Chip *chip9, Error **errp)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pnv_chip_power9_phb_realize(PnvChip *chip, Error **errp)
|
static void pnv_chip_power9_pec_realize(PnvChip *chip, Error **errp)
|
||||||
{
|
{
|
||||||
Pnv9Chip *chip9 = PNV9_CHIP(chip);
|
Pnv9Chip *chip9 = PNV9_CHIP(chip);
|
||||||
int i, j;
|
int i;
|
||||||
int phb_id = 0;
|
|
||||||
|
|
||||||
for (i = 0; i < PNV9_CHIP_MAX_PEC; i++) {
|
for (i = 0; i < chip->num_pecs; i++) {
|
||||||
PnvPhb4PecState *pec = &chip9->pecs[i];
|
PnvPhb4PecState *pec = &chip9->pecs[i];
|
||||||
PnvPhb4PecClass *pecc = PNV_PHB4_PEC_GET_CLASS(pec);
|
PnvPhb4PecClass *pecc = PNV_PHB4_PEC_GET_CLASS(pec);
|
||||||
uint32_t pec_nest_base;
|
uint32_t pec_nest_base;
|
||||||
uint32_t pec_pci_base;
|
uint32_t pec_pci_base;
|
||||||
|
|
||||||
object_property_set_int(OBJECT(pec), "index", i, &error_fatal);
|
object_property_set_int(OBJECT(pec), "index", i, &error_fatal);
|
||||||
/*
|
|
||||||
* PEC0 -> 1 stack
|
|
||||||
* PEC1 -> 2 stacks
|
|
||||||
* PEC2 -> 3 stacks
|
|
||||||
*/
|
|
||||||
object_property_set_int(OBJECT(pec), "num-stacks", i + 1,
|
|
||||||
&error_fatal);
|
|
||||||
object_property_set_int(OBJECT(pec), "chip-id", chip->chip_id,
|
object_property_set_int(OBJECT(pec), "chip-id", chip->chip_id,
|
||||||
&error_fatal);
|
&error_fatal);
|
||||||
object_property_set_link(OBJECT(pec), "system-memory",
|
object_property_set_link(OBJECT(pec), "chip", OBJECT(chip),
|
||||||
OBJECT(get_system_memory()), &error_abort);
|
&error_fatal);
|
||||||
if (!qdev_realize(DEVICE(pec), NULL, errp)) {
|
if (!qdev_realize(DEVICE(pec), NULL, errp)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1411,37 +1411,6 @@ static void pnv_chip_power9_phb_realize(PnvChip *chip, Error **errp)
|
|||||||
|
|
||||||
pnv_xscom_add_subregion(chip, pec_nest_base, &pec->nest_regs_mr);
|
pnv_xscom_add_subregion(chip, pec_nest_base, &pec->nest_regs_mr);
|
||||||
pnv_xscom_add_subregion(chip, pec_pci_base, &pec->pci_regs_mr);
|
pnv_xscom_add_subregion(chip, pec_pci_base, &pec->pci_regs_mr);
|
||||||
|
|
||||||
for (j = 0; j < pec->num_stacks && phb_id < chip->num_phbs;
|
|
||||||
j++, phb_id++) {
|
|
||||||
PnvPhb4PecStack *stack = &pec->stacks[j];
|
|
||||||
Object *obj = OBJECT(&stack->phb);
|
|
||||||
|
|
||||||
object_property_set_int(obj, "index", phb_id, &error_fatal);
|
|
||||||
object_property_set_int(obj, "chip-id", chip->chip_id,
|
|
||||||
&error_fatal);
|
|
||||||
object_property_set_int(obj, "version", PNV_PHB4_VERSION,
|
|
||||||
&error_fatal);
|
|
||||||
object_property_set_int(obj, "device-id", PNV_PHB4_DEVICE_ID,
|
|
||||||
&error_fatal);
|
|
||||||
object_property_set_link(obj, "stack", OBJECT(stack),
|
|
||||||
&error_abort);
|
|
||||||
if (!sysbus_realize(SYS_BUS_DEVICE(obj), errp)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Populate the XSCOM address space. */
|
|
||||||
pnv_xscom_add_subregion(chip,
|
|
||||||
pec_nest_base + 0x40 * (stack->stack_no + 1),
|
|
||||||
&stack->nest_regs_mr);
|
|
||||||
pnv_xscom_add_subregion(chip,
|
|
||||||
pec_pci_base + 0x40 * (stack->stack_no + 1),
|
|
||||||
&stack->pci_regs_mr);
|
|
||||||
pnv_xscom_add_subregion(chip,
|
|
||||||
pec_pci_base + PNV9_XSCOM_PEC_PCI_STK0 +
|
|
||||||
0x40 * stack->stack_no,
|
|
||||||
&stack->phb_regs_mr);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1537,8 +1506,8 @@ static void pnv_chip_power9_realize(DeviceState *dev, Error **errp)
|
|||||||
memory_region_add_subregion(get_system_memory(), PNV9_HOMER_BASE(chip),
|
memory_region_add_subregion(get_system_memory(), PNV9_HOMER_BASE(chip),
|
||||||
&chip9->homer.regs);
|
&chip9->homer.regs);
|
||||||
|
|
||||||
/* PHBs */
|
/* PEC PHBs */
|
||||||
pnv_chip_power9_phb_realize(chip, &local_err);
|
pnv_chip_power9_pec_realize(chip, &local_err);
|
||||||
if (local_err) {
|
if (local_err) {
|
||||||
error_propagate(errp, local_err);
|
error_propagate(errp, local_err);
|
||||||
return;
|
return;
|
||||||
@ -1569,7 +1538,7 @@ static void pnv_chip_power9_class_init(ObjectClass *klass, void *data)
|
|||||||
k->xscom_core_base = pnv_chip_power9_xscom_core_base;
|
k->xscom_core_base = pnv_chip_power9_xscom_core_base;
|
||||||
k->xscom_pcba = pnv_chip_power9_xscom_pcba;
|
k->xscom_pcba = pnv_chip_power9_xscom_pcba;
|
||||||
dc->desc = "PowerNV Chip POWER9";
|
dc->desc = "PowerNV Chip POWER9";
|
||||||
k->num_phbs = 6;
|
k->num_pecs = PNV9_CHIP_MAX_PEC;
|
||||||
|
|
||||||
device_class_set_parent_realize(dc, pnv_chip_power9_realize,
|
device_class_set_parent_realize(dc, pnv_chip_power9_realize,
|
||||||
&k->parent_realize);
|
&k->parent_realize);
|
||||||
@ -1764,7 +1733,6 @@ static Property pnv_chip_properties[] = {
|
|||||||
DEFINE_PROP_UINT32("nr-cores", PnvChip, nr_cores, 1),
|
DEFINE_PROP_UINT32("nr-cores", PnvChip, nr_cores, 1),
|
||||||
DEFINE_PROP_UINT64("cores-mask", PnvChip, cores_mask, 0x0),
|
DEFINE_PROP_UINT64("cores-mask", PnvChip, cores_mask, 0x0),
|
||||||
DEFINE_PROP_UINT32("nr-threads", PnvChip, nr_threads, 1),
|
DEFINE_PROP_UINT32("nr-threads", PnvChip, nr_threads, 1),
|
||||||
DEFINE_PROP_UINT32("num-phbs", PnvChip, num_phbs, 0),
|
|
||||||
DEFINE_PROP_END_OF_LIST(),
|
DEFINE_PROP_END_OF_LIST(),
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1795,10 +1763,32 @@ PowerPCCPU *pnv_chip_find_cpu(PnvChip *chip, uint32_t pir)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef struct ForeachPhb3Args {
|
||||||
|
int irq;
|
||||||
|
ICSState *ics;
|
||||||
|
} ForeachPhb3Args;
|
||||||
|
|
||||||
|
static int pnv_ics_get_child(Object *child, void *opaque)
|
||||||
|
{
|
||||||
|
ForeachPhb3Args *args = opaque;
|
||||||
|
PnvPHB3 *phb3 = (PnvPHB3 *) object_dynamic_cast(child, TYPE_PNV_PHB3);
|
||||||
|
|
||||||
|
if (phb3) {
|
||||||
|
if (ics_valid_irq(&phb3->lsis, args->irq)) {
|
||||||
|
args->ics = &phb3->lsis;
|
||||||
|
}
|
||||||
|
if (ics_valid_irq(ICS(&phb3->msis), args->irq)) {
|
||||||
|
args->ics = ICS(&phb3->msis);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return args->ics ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
static ICSState *pnv_ics_get(XICSFabric *xi, int irq)
|
static ICSState *pnv_ics_get(XICSFabric *xi, int irq)
|
||||||
{
|
{
|
||||||
PnvMachineState *pnv = PNV_MACHINE(xi);
|
PnvMachineState *pnv = PNV_MACHINE(xi);
|
||||||
int i, j;
|
ForeachPhb3Args args = { irq, NULL };
|
||||||
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < pnv->num_chips; i++) {
|
for (i = 0; i < pnv->num_chips; i++) {
|
||||||
PnvChip *chip = pnv->chips[i];
|
PnvChip *chip = pnv->chips[i];
|
||||||
@ -1807,32 +1797,37 @@ static ICSState *pnv_ics_get(XICSFabric *xi, int irq)
|
|||||||
if (ics_valid_irq(&chip8->psi.ics, irq)) {
|
if (ics_valid_irq(&chip8->psi.ics, irq)) {
|
||||||
return &chip8->psi.ics;
|
return &chip8->psi.ics;
|
||||||
}
|
}
|
||||||
for (j = 0; j < chip->num_phbs; j++) {
|
|
||||||
if (ics_valid_irq(&chip8->phbs[j].lsis, irq)) {
|
object_child_foreach(OBJECT(chip), pnv_ics_get_child, &args);
|
||||||
return &chip8->phbs[j].lsis;
|
if (args.ics) {
|
||||||
}
|
return args.ics;
|
||||||
if (ics_valid_irq(ICS(&chip8->phbs[j].msis), irq)) {
|
|
||||||
return ICS(&chip8->phbs[j].msis);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int pnv_ics_resend_child(Object *child, void *opaque)
|
||||||
|
{
|
||||||
|
PnvPHB3 *phb3 = (PnvPHB3 *) object_dynamic_cast(child, TYPE_PNV_PHB3);
|
||||||
|
|
||||||
|
if (phb3) {
|
||||||
|
ics_resend(&phb3->lsis);
|
||||||
|
ics_resend(ICS(&phb3->msis));
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static void pnv_ics_resend(XICSFabric *xi)
|
static void pnv_ics_resend(XICSFabric *xi)
|
||||||
{
|
{
|
||||||
PnvMachineState *pnv = PNV_MACHINE(xi);
|
PnvMachineState *pnv = PNV_MACHINE(xi);
|
||||||
int i, j;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < pnv->num_chips; i++) {
|
for (i = 0; i < pnv->num_chips; i++) {
|
||||||
PnvChip *chip = pnv->chips[i];
|
PnvChip *chip = pnv->chips[i];
|
||||||
Pnv8Chip *chip8 = PNV8_CHIP(pnv->chips[i]);
|
Pnv8Chip *chip8 = PNV8_CHIP(pnv->chips[i]);
|
||||||
|
|
||||||
ics_resend(&chip8->psi.ics);
|
ics_resend(&chip8->psi.ics);
|
||||||
for (j = 0; j < chip->num_phbs; j++) {
|
object_child_foreach(OBJECT(chip), pnv_ics_resend_child, NULL);
|
||||||
ics_resend(&chip8->phbs[j].lsis);
|
|
||||||
ics_resend(ICS(&chip8->phbs[j].msis));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1367,6 +1367,7 @@ int ppc_dcr_read (ppc_dcr_t *dcr_env, int dcrn, uint32_t *valp)
|
|||||||
if (dcr->dcr_read == NULL)
|
if (dcr->dcr_read == NULL)
|
||||||
goto error;
|
goto error;
|
||||||
*valp = (*dcr->dcr_read)(dcr->opaque, dcrn);
|
*valp = (*dcr->dcr_read)(dcr->opaque, dcrn);
|
||||||
|
trace_ppc_dcr_read(dcrn, *valp);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@ -1386,6 +1387,7 @@ int ppc_dcr_write (ppc_dcr_t *dcr_env, int dcrn, uint32_t val)
|
|||||||
dcr = &dcr_env->dcrn[dcrn];
|
dcr = &dcr_env->dcrn[dcrn];
|
||||||
if (dcr->dcr_write == NULL)
|
if (dcr->dcr_write == NULL)
|
||||||
goto error;
|
goto error;
|
||||||
|
trace_ppc_dcr_write(dcrn, val);
|
||||||
(*dcr->dcr_write)(dcr->opaque, dcrn, val);
|
(*dcr->dcr_write)(dcr->opaque, dcrn, val);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -27,6 +27,13 @@
|
|||||||
|
|
||||||
#include "hw/ppc/ppc4xx.h"
|
#include "hw/ppc/ppc4xx.h"
|
||||||
|
|
||||||
|
#define PPC405EP_SDRAM_BASE 0x00000000
|
||||||
|
#define PPC405EP_NVRAM_BASE 0xF0000000
|
||||||
|
#define PPC405EP_FPGA_BASE 0xF0300000
|
||||||
|
#define PPC405EP_SRAM_BASE 0xFFF00000
|
||||||
|
#define PPC405EP_SRAM_SIZE (512 * KiB)
|
||||||
|
#define PPC405EP_FLASH_BASE 0xFFF80000
|
||||||
|
|
||||||
/* Bootinfo as set-up by u-boot */
|
/* Bootinfo as set-up by u-boot */
|
||||||
typedef struct ppc4xx_bd_info_t ppc4xx_bd_info_t;
|
typedef struct ppc4xx_bd_info_t ppc4xx_bd_info_t;
|
||||||
struct ppc4xx_bd_info_t {
|
struct ppc4xx_bd_info_t {
|
||||||
@ -50,19 +57,18 @@ struct ppc4xx_bd_info_t {
|
|||||||
uint32_t bi_plb_busfreq;
|
uint32_t bi_plb_busfreq;
|
||||||
uint32_t bi_pci_busfreq;
|
uint32_t bi_pci_busfreq;
|
||||||
uint8_t bi_pci_enetaddr[6];
|
uint8_t bi_pci_enetaddr[6];
|
||||||
uint32_t bi_pci_enetaddr2[6];
|
uint8_t bi_pci_enetaddr2[6]; /* PPC405EP specific */
|
||||||
uint32_t bi_opbfreq;
|
uint32_t bi_opbfreq;
|
||||||
uint32_t bi_iic_fast[2];
|
uint32_t bi_iic_fast[2];
|
||||||
};
|
};
|
||||||
|
|
||||||
/* PowerPC 405 core */
|
/* PowerPC 405 core */
|
||||||
ram_addr_t ppc405_set_bootinfo (CPUPPCState *env, ppc4xx_bd_info_t *bd,
|
ram_addr_t ppc405_set_bootinfo(CPUPPCState *env, ram_addr_t ram_size);
|
||||||
uint32_t flags);
|
|
||||||
|
|
||||||
void ppc4xx_plb_init(CPUPPCState *env);
|
void ppc4xx_plb_init(CPUPPCState *env);
|
||||||
void ppc405_ebc_init(CPUPPCState *env);
|
void ppc405_ebc_init(CPUPPCState *env);
|
||||||
|
|
||||||
CPUPPCState *ppc405ep_init(MemoryRegion *address_space_mem,
|
PowerPCCPU *ppc405ep_init(MemoryRegion *address_space_mem,
|
||||||
MemoryRegion ram_memories[2],
|
MemoryRegion ram_memories[2],
|
||||||
hwaddr ram_bases[2],
|
hwaddr ram_bases[2],
|
||||||
hwaddr ram_sizes[2],
|
hwaddr ram_sizes[2],
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user