Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Andrea Fioraldi 2021-12-21 11:09:43 +01:00
commit 29ff573753
329 changed files with 12410 additions and 6409 deletions

View File

@ -100,6 +100,17 @@ avocado-system-debian:
IMAGE: debian-amd64
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:
extends: .native_build_job_template
needs:
@ -134,6 +145,18 @@ avocado-system-fedora:
IMAGE: fedora
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:
extends: .native_build_job_template
needs:

View File

@ -89,3 +89,38 @@ x64-macos-11-base-build:
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
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

View 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

View File

@ -11,3 +11,4 @@ include:
- local: '/.gitlab-ci.d/static_checks.yml'
- local: '/.gitlab-ci.d/custom-runners.yml'
- local: '/.gitlab-ci.d/cirrus.yml'
- local: '/.gitlab-ci.d/windows.yml'

98
.gitlab-ci.d/windows.yml Normal file
View 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'

View File

@ -50,6 +50,7 @@ Aleksandar Rikalo <aleksandar.rikalo@syrmia.com> <arikalo@wavecomp.com>
Aleksandar Rikalo <aleksandar.rikalo@syrmia.com> <aleksandar.rikalo@rt-rk.com>
Alexander Graf <agraf@csgraf.de> <agraf@suse.de>
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>
Frederic Konrad <konrad@adacore.com> <fred.konrad@greensocs.com>
Greg Kurz <groug@kaod.org> <gkurz@linux.vnet.ibm.com>

View File

@ -393,7 +393,7 @@ F: target/ppc/kvm.c
S390 KVM CPUs
M: Halil Pasic <pasic@linux.ibm.com>
M: Christian Borntraeger <borntraeger@de.ibm.com>
M: Christian Borntraeger <borntraeger@linux.ibm.com>
S: Supported
F: target/s390x/kvm/
F: target/s390x/ioinst.[ch]
@ -1527,7 +1527,7 @@ S390 Machines
-------------
S390 Virtio-ccw
M: Halil Pasic <pasic@linux.ibm.com>
M: Christian Borntraeger <borntraeger@de.ibm.com>
M: Christian Borntraeger <borntraeger@linux.ibm.com>
S: Supported
F: hw/char/sclp*.[hc]
F: hw/char/terminal3270.c
@ -1541,7 +1541,7 @@ T: git https://github.com/borntraeger/qemu.git s390-next
L: qemu-s390x@nongnu.org
S390-ccw boot
M: Christian Borntraeger <borntraeger@de.ibm.com>
M: Christian Borntraeger <borntraeger@linux.ibm.com>
M: Thomas Huth <thuth@redhat.com>
S: Supported
F: hw/s390x/ipl.*
@ -1825,6 +1825,7 @@ F: hw/scsi/*
F: tests/qtest/virtio-scsi-test.c
F: tests/qtest/fuzz-virtio-scsi-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
SSI
@ -3076,8 +3077,9 @@ Usermode Emulation
Overall usermode emulation
M: Riku Voipio <riku.voipio@iki.fi>
S: Maintained
F: thunk.c
F: accel/tcg/user-exec*.c
F: include/user/
F: common-user/
BSD user
M: Warner Losh <imp@bsdimp.com>

View File

@ -1 +1 @@
6.1.93
6.2.50

View File

@ -61,6 +61,10 @@
#endif
#define PAGE_SIZE qemu_real_host_page_size
#ifndef KVM_GUESTDBG_BLOCKIRQ
#define KVM_GUESTDBG_BLOCKIRQ 0
#endif
//#define DEBUG_KVM
#ifdef DEBUG_KVM
@ -168,6 +172,8 @@ bool kvm_vm_attributes_allowed;
bool kvm_direct_msi_allowed;
bool kvm_ioeventfd_any_length_allowed;
bool kvm_msi_use_devid;
bool kvm_has_guest_debug;
int kvm_sstep_flags;
static bool kvm_immediate_exit;
static hwaddr kvm_max_slot_size = ~0;
@ -2564,6 +2570,25 @@ static int kvm_init(MachineState *ms)
kvm_ioeventfd_any_length_allowed =
(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;
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) {
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);

View File

@ -206,8 +206,9 @@ static void nvme_free_req_queue_cb(void *opaque)
NVMeQueuePair *q = opaque;
qemu_mutex_lock(&q->lock);
while (qemu_co_enter_next(&q->free_req_queue, &q->lock)) {
/* Retry all pending requests */
while (q->free_req_head != -1 &&
qemu_co_enter_next(&q->free_req_queue, &q->lock)) {
/* Retry waiting requests */
}
qemu_mutex_unlock(&q->lock);
}

View File

@ -303,16 +303,6 @@ int drive_get_max_bus(BlockInterfaceType type)
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)
{
qemu_printf(" %s", name);

View File

@ -151,6 +151,10 @@
/* Internal errors: */
#define TARGET_EJUSTRETURN 254 /* Just return without modifing regs */
#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_ */

View File

@ -2,6 +2,10 @@ if not have_bsd_user
subdir_done()
endif
bsd_user_ss = ss.source_set()
common_user_inc += include_directories('.')
bsd_user_ss.add(files(
'bsdload.c',
'elfload.c',
@ -15,3 +19,5 @@ bsd_user_ss.add(files(
# Pull in the OS-specific build glue, if any
subdir(targetos)
specific_ss.add_all(when: 'CONFIG_BSD_USER', if_true: bsd_user_ss)

24
bsd-user/special-errno.h Normal file
View 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 */

View 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

View 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

View 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

View 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)

View 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

View 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

View 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

View 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

View File

@ -1,7 +1,7 @@
/*
* 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 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>
*
@ -19,9 +19,6 @@
* 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').
* 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:
.cfi_startproc
@ -35,9 +32,9 @@ safe_syscall_base:
.cfi_adjust_cfa_offset 8
.cfi_rel_offset rbp, 0
/* The syscall calling convention isn't the same as the
* C one:
* we enter with rdi == *signal_pending
/*
* The syscall calling convention isn't the same as the C one:
* we enter with rdi == &signal_pending
* rsi == syscall number
* rdx, rcx, r8, r9, (stack), (stack) == syscall arguments
* and return the result in rax
@ -67,25 +64,42 @@ safe_syscall_base:
*/
safe_syscall_start:
/* if signal_pending is non-zero, don't do the call */
cmpl $0, (%rbp)
jnz 1f
cmpl $0, (%rbp)
jnz 2f
syscall
safe_syscall_end:
/* 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
.cfi_remember_state
.cfi_def_cfa_offset 8
.cfi_restore rbp
ret
1:
/* code path when we didn't execute the syscall */
.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_restore rbp
ret
jmp safe_syscall_set_errno_tail
.cfi_endproc
.size safe_syscall_base, .-safe_syscall_base

6
common-user/meson.build Normal file
View 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',
))

View 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;
}

View File

@ -10,15 +10,12 @@
* See the COPYING file in the top-level directory.
*/
#include "hostdep.h"
#include "target_errno_defs.h"
#include "special-errno.h"
/* We have the correct host directory on our include path
* so that this will pull in the right fragment for the architecture.
*/
#ifdef HAVE_SAFE_SYSCALL
#include "safe-syscall.inc.S"
#endif
/* We must specifically say that we're happy for the stack to not be
* executable, otherwise the toolchain will default to assuming our

287
configure vendored
View File

@ -344,7 +344,6 @@ debug_stack_usage="no"
crypto_afalg="no"
tls_priority="NORMAL"
tpm="$default_feature"
libssh="$default_feature"
live_block_migration=${default_feature:-yes}
numa="$default_feature"
replication=${default_feature:-yes}
@ -502,42 +501,93 @@ EOF
}
if check_define __linux__ ; then
targetos="Linux"
targetos=linux
elif check_define _WIN32 ; then
targetos='MINGW32'
targetos=windows
elif check_define __OpenBSD__ ; then
targetos='OpenBSD'
targetos=openbsd
elif check_define __sun__ ; then
targetos='SunOS'
targetos=sunos
elif check_define __HAIKU__ ; then
targetos='Haiku'
targetos=haiku
elif check_define __FreeBSD__ ; then
targetos='FreeBSD'
targetos=freebsd
elif check_define __FreeBSD_kernel__ && check_define __GLIBC__; then
targetos='GNU/kFreeBSD'
targetos=gnu/kfreebsd
elif check_define __DragonFly__ ; then
targetos='DragonFly'
targetos=dragonfly
elif check_define __NetBSD__; then
targetos='NetBSD'
targetos=netbsd
elif check_define __APPLE__; then
targetos='Darwin'
targetos=darwin
else
# 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
# be the result of a missing compiler.
targetos='bogus'
targetos=bogus
fi
# Some host OSes need non-standard checks for which CPU to use.
# 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.
# OS specific
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
# 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
cpu="x86_64"
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
if test ! -z "$cpu" ; then
@ -585,98 +635,46 @@ else
cpu=$(uname -m)
fi
ARCH=
# Normalise host CPU name and set ARCH.
# Normalise host CPU name, set multilib cflags
# Note that this case should only have supported host CPUs, not guests.
case "$cpu" in
ppc|ppc64|s390x|sparc64|x32|riscv)
;;
ppc64le)
ARCH="ppc64"
;;
armv*b|armv*l|arm)
cpu="arm" ;;
i386|i486|i586|i686|i86pc|BePC)
cpu="i386"
;;
CPU_CFLAGS="-m32" ;;
x32)
cpu="x86_64"
CPU_CFLAGS="-mx32" ;;
x86_64|amd64)
cpu="x86_64"
;;
armv*b|armv*l|arm)
cpu="arm"
;;
aarch64)
cpu="aarch64"
;;
# ??? 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.
CPU_CFLAGS="-m64 -mcx16" ;;
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])
cpu="sparc"
;;
*)
# This will result in either an error or falling back to TCI later
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}
;;
CPU_CFLAGS="-m32 -mv8plus -mcpu=ultrasparc" ;;
sparc64)
CPU_CFLAGS="-m64 -mcpu=ultrasparc" ;;
esac
: ${make=${MAKE-make}}
@ -1080,10 +1078,6 @@ for opt do
;;
--enable-tpm) tpm="yes"
;;
--disable-libssh) libssh="no"
;;
--enable-libssh) libssh="yes"
;;
--disable-live-block-migration) live_block_migration="no"
;;
--enable-live-block-migration) live_block_migration="yes"
@ -1276,24 +1270,6 @@ local_statedir="${local_statedir:-$prefix/var}"
firmwarepath="${firmwarepath:-$datadir/qemu-firmware}"
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
eval "cross_cc_${cpu}=\$cc"
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
coroutine-pool coroutine freelist (better performance)
tpm TPM support
libssh ssh block device support
numa libnuma support
avx2 AVX2 optimization support
avx512f AVX512F optimization support
@ -2573,21 +2548,6 @@ if test "$modules" = yes; then
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
@ -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
roms=
if { test "$cpu" = "i386" || test "$cpu" = "x86_64"; } && \
test "$targetos" != "Darwin" && test "$targetos" != "SunOS" && \
test "$targetos" != "Haiku" && test "$softmmu" = yes ; then
test "$targetos" != "darwin" && test "$targetos" != "sunos" && \
test "$targetos" != "haiku" && test "$softmmu" = yes ; then
# 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
# 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_ACTION=$git_submodules_action" >> $config_host_mak
echo "ARCH=$ARCH" >> $config_host_mak
if test "$debug_tcg" = "yes" ; then
echo "CONFIG_DEBUG_TCG=y" >> $config_host_mak
fi
@ -3484,9 +3442,6 @@ fi
if test "$solaris" = "yes" ; then
echo "CONFIG_SOLARIS=y" >> $config_host_mak
fi
if test "$haiku" = "yes" ; then
echo "CONFIG_HAIKU=y" >> $config_host_mak
fi
if test "$static" = "yes" ; then
echo "CONFIG_STATIC=y" >> $config_host_mak
fi
@ -3648,12 +3603,6 @@ if test "$cmpxchg128" = "yes" ; then
echo "CONFIG_CMPXCHG128=y" >> $config_host_mak
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
echo "CONFIG_LIVE_BLOCK_MIGRATION=y" >> $config_host_mak
fi
@ -3777,10 +3726,10 @@ fi
if test "$linux" = "yes" ; then
mkdir -p linux-headers
case "$cpu" in
i386|x86_64|x32)
i386|x86_64)
linux_arch=x86
;;
ppc|ppc64|ppc64le)
ppc|ppc64)
linux_arch=powerpc
;;
s390x)
@ -3805,7 +3754,7 @@ fi
for target in $target_list; do
target_dir="$target"
target_name=$(echo $target | cut -d '-' -f 1)
target_name=$(echo $target | cut -d '-' -f 1)$EXESUF
mkdir -p $target_dir
case $target in
*-user) symlink "../qemu-$target_name" "$target_dir/qemu-$target_name" ;;
@ -3832,7 +3781,6 @@ if test "$safe_stack" = "yes"; then
fi
# 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
# (these can be both files and directories).
# 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
# that might get into the way when doing "git update" without doing
# 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="$LINKS tests/tcg/Makefile.target"
LINKS="$LINKS pc-bios/optionrom/Makefile"
@ -3871,16 +3813,15 @@ for bios_file in \
$source_path/pc-bios/*.img \
$source_path/pc-bios/openbios-* \
$source_path/pc-bios/u-boot.* \
$source_path/pc-bios/edk2-*.fd.bz2 \
$source_path/pc-bios/palcode-* \
$source_path/pc-bios/qemu_vga.ndrv
do
LINKS="$LINKS pc-bios/$(basename $bios_file)"
done
mkdir -p $DIRS
for f in $LINKS ; do
if [ -e "$source_path/$f" ]; then
mkdir -p `dirname ./$f`
symlink "$source_path/$f" "$f"
fi
done
@ -3954,27 +3895,13 @@ if test "$skip_meson" = no; then
if test "$cross_compile" = "yes"; then
cross_arg="--cross-file config-meson.cross"
echo "[host_machine]" >> $cross
if test "$mingw32" = "yes" ; then
echo "system = 'windows'" >> $cross
fi
if test "$linux" = "yes" ; then
echo "system = 'linux'" >> $cross
fi
if test "$darwin" = "yes" ; then
echo "system = 'darwin'" >> $cross
fi
case "$ARCH" in
echo "system = '$targetos'" >> $cross
case "$cpu" in
i386)
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
echo "cpu = '$cpu'" >> $cross

5
cpu.c
View File

@ -318,12 +318,10 @@ void cpu_exec_realizefn(CPUState *cpu, Error **errp)
if (!accel_cpu_realizefn(cpu, errp)) {
return;
}
#ifdef CONFIG_TCG
/* NB: errp parameter is unused currently */
if (tcg_enabled()) {
tcg_exec_realizefn(cpu, errp);
}
#endif /* CONFIG_TCG */
#ifdef CONFIG_USER_ONLY
assert(qdev_get_vmsd(DEVICE(cpu)) == NULL ||
@ -350,12 +348,9 @@ void cpu_exec_unrealizefn(CPUState *cpu)
vmstate_unregister(NULL, &vmstate_cpu_common, cpu);
}
#endif
#ifdef CONFIG_TCG
/* NB: errp parameter is unused currently */
if (tcg_enabled()) {
tcg_exec_unrealizefn(cpu);
}
#endif /* CONFIG_TCG */
cpu_list_remove(cpu);
}

View File

@ -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
``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
---------------

View File

@ -179,7 +179,7 @@ Primary:
Secondary:
-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.driver=qcow2,\
file.backing.file.filename=hidden_disk.qcow2,\

View File

@ -18,12 +18,12 @@ if sphinx_build.found()
# This is a bit awkward but works: create a trivial document and
# try to run it with our configuration file (which enforces a
# version requirement). This will fail if sphinx-build is too old.
run_command('mkdir', ['-p', tmpdir / 'sphinx'])
run_command('touch', [tmpdir / 'sphinx/index.rst'])
run_command('mkdir', ['-p', tmpdir / 'sphinx'], check: true)
run_command('touch', [tmpdir / 'sphinx/index.rst'], check: true)
sphinx_build_test_out = run_command(SPHINX_ARGS + [
'-c', meson.current_source_dir(),
'-b', 'html', tmpdir / 'sphinx',
tmpdir / 'sphinx/out'])
tmpdir / 'sphinx/out'], check: false)
build_docs = (sphinx_build_test_out.returncode() == 0)
if not build_docs

View 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.

View File

@ -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

View File

@ -14,6 +14,7 @@ AST2400 SoC based machines :
- ``palmetto-bmc`` OpenPOWER Palmetto POWER8 BMC
- ``quanta-q71l-bmc`` OpenBMC Quanta BMC
- ``supermicrox11-bmc`` Supermicro X11 BMC
AST2500 SoC based machines :
@ -21,12 +22,16 @@ AST2500 SoC based machines :
- ``romulus-bmc`` OpenPOWER Romulus POWER9 BMC
- ``witherspoon-bmc`` OpenPOWER Witherspoon POWER9 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-evb`` Aspeed AST2600 Evaluation board (Cortex-A7)
- ``tacoma-bmc`` OpenPOWER Witherspoon POWER9 AST2600 BMC
- ``rainier-bmc`` IBM Rainier POWER10 BMC
- ``fuji-bmc`` Facebook Fuji BMC
Supported devices
-----------------
@ -51,13 +56,13 @@ Supported devices
* Front LEDs (PCA9552 on I2C bus)
* LPC Peripheral Controller (a subset of subdevices are supported)
* Hash/Crypto Engine (HACE) - Hash support only. TODO: HMAC and RSA
* ADC
Missing devices
---------------
* Coprocessor support
* ADC (out of tree implementation)
* PWM and Fan Controller
* Slave GPIO Controller
* Super I/O Controller
@ -73,16 +78,25 @@ Missing devices
Boot options
------------
The Aspeed machines can be started using the ``-kernel`` option to
load a Linux kernel or from a firmware. Images can be downloaded from
the OpenBMC jenkins :
The Aspeed machines can be started using the ``-kernel`` and ``-dtb`` options
to load a Linux kernel or from a firmware. Images can be downloaded from the
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 :
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 :
.. code-block:: bash

View File

@ -141,8 +141,7 @@ To launch a SGX guest:
|qemu_system_x86| \\
-cpu host,+sgx-provisionkey \\
-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.1.memdev=mem2
-M sgx-epc.0.memdev=mem1,sgx-epc.0.node=0
Utilizing SGX in the guest requires a kernel/OS with SGX support.
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::
$ dmesg | grep sgx
[ 1.242142] sgx: EPC section 0x180000000-0x181bfffff
[ 1.242319] sgx: EPC section 0x181c00000-0x1837fffff
[ 0.182807] sgx: EPC section 0x140000000-0x143ffffff
[ 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
----------

View File

@ -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
be used as an hypervisor OS, running KVM guests, or simply as a host
OS.
@ -16,16 +16,14 @@ Supported devices
-----------------
* Multi processor support for POWER8, POWER8NVL and POWER9.
* XSCOM, serial communication sideband bus to configure chiplets
* Simple LPC Controller
* Processor Service Interface (PSI) Controller
* Interrupt Controller, XICS (POWER8) and XIVE (POWER9)
* POWER8 PHB3 PCIe Host bridge and POWER9 PHB4 PCIe Host bridge
* Simple OCC is an on-chip microcontroller used for power management
tasks
* iBT device to handle BMC communication, with the internal BMC
simulator provided by QEMU or an external BMC such as an Aspeed
QEMU machine.
* XSCOM, serial communication sideband bus to configure chiplets.
* Simple LPC Controller.
* Processor Service Interface (PSI) Controller.
* Interrupt Controller, XICS (POWER8) and XIVE (POWER9) and XIVE2 (Power10).
* POWER8 PHB3 PCIe Host bridge and POWER9 PHB4 PCIe Host bridge.
* Simple OCC is an on-chip micro-controller used for power management tasks.
* iBT device to handle BMC communication, with the internal BMC simulator
provided by QEMU or an external BMC such as an Aspeed QEMU machine.
* PNOR containing the different firmware partitions.
Missing devices
@ -33,31 +31,42 @@ Missing devices
A lot is missing, among which :
* POWER10 processor
* XIVE2 (POWER10) interrupt controller
* I2C controllers (yet to be merged)
* NPU/NPU2/NPU3 controllers
* EEH support for PCIe Host bridge controllers
* NX controller
* VAS controller
* chipTOD (Time Of Day)
* I2C controllers (yet to be merged).
* NPU/NPU2/NPU3 controllers.
* EEH support for PCIe Host bridge controllers.
* NX controller.
* VAS controller.
* chipTOD (Time Of Day).
* Self Boot Engine (SBE).
* FSI bus
* FSI bus.
Firmware
--------
The OPAL firmware (OpenPower Abstraction Layer) for OpenPower systems
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
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
------------
@ -83,6 +92,7 @@ and a SATA disk :
Complex PCIe configuration
~~~~~~~~~~~~~~~~~~~~~~~~~~
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
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>`__
and `palmetto-FRU.bin <http://www.kaod.org/qemu/powernv/palmetto-FRU.bin>`__
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.
.. code-block:: bash
@ -189,4 +199,8 @@ CAVEATS
-------
* 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>

View File

@ -1,12 +1,238 @@
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
-----------------
* 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
---------------
* SPICE support.
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>

View File

@ -1293,14 +1293,6 @@ static size_t get_len_buf_out(size_t page_size, uint32_t flag_compress)
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)
{
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)) {
/* 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),
false);
if (ret < 0) {

View File

@ -19,7 +19,7 @@ static void partsN(return_nan)(FloatPartsN *a, float_status *s)
{
switch (a->cls) {
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) {
parts_default_nan(a, s);
} else {
@ -40,7 +40,7 @@ static FloatPartsN *partsN(pick_nan)(FloatPartsN *a, FloatPartsN *b,
float_status *s)
{
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) {
@ -68,7 +68,7 @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
int which;
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,
@ -354,7 +354,7 @@ static FloatPartsN *partsN(addsub)(FloatPartsN *a, FloatPartsN *b,
return a;
}
/* Inf - Inf */
float_raise(float_flag_invalid, s);
float_raise(float_flag_invalid | float_flag_invalid_isi, s);
parts_default_nan(a, s);
return a;
}
@ -423,7 +423,7 @@ static FloatPartsN *partsN(mul)(FloatPartsN *a, FloatPartsN *b,
/* Inf * Zero == NaN */
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);
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_infzero)) {
float_raise(float_flag_invalid | float_flag_invalid_imz, s);
goto d_nan;
}
if (ab_mask & float_cmask_inf) {
if (c->cls == float_class_inf && a->sign != c->sign) {
float_raise(float_flag_invalid | float_flag_invalid_isi, s);
goto d_nan;
}
goto return_inf;
@ -566,7 +568,6 @@ static FloatPartsN *partsN(muladd)(FloatPartsN *a, FloatPartsN *b,
goto finish_sign;
d_nan:
float_raise(float_flag_invalid, s);
parts_default_nan(a, s);
return a;
}
@ -589,11 +590,13 @@ static FloatPartsN *partsN(div)(FloatPartsN *a, FloatPartsN *b,
}
/* 0/0 or Inf/Inf => NaN */
if (unlikely(ab_mask == float_cmask_zero) ||
unlikely(ab_mask == float_cmask_inf)) {
float_raise(float_flag_invalid, s);
parts_default_nan(a, s);
return a;
if (unlikely(ab_mask == float_cmask_zero)) {
float_raise(float_flag_invalid | float_flag_invalid_zdz, s);
goto d_nan;
}
if (unlikely(ab_mask == float_cmask_inf)) {
float_raise(float_flag_invalid | float_flag_invalid_idi, s);
goto d_nan;
}
/* All the NaN cases */
@ -624,6 +627,10 @@ static FloatPartsN *partsN(div)(FloatPartsN *a, FloatPartsN *b,
float_raise(float_flag_divbyzero, s);
a->cls = float_class_inf;
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;
d_nan:
float_raise(float_flag_invalid, status);
float_raise(float_flag_invalid | float_flag_invalid_sqrt, status);
parts_default_nan(a, status);
}
@ -1042,13 +1049,15 @@ static int64_t partsN(float_to_sint)(FloatPartsN *p, FloatRoundMode rmode,
switch (p->cls) {
case float_class_snan:
flags |= float_flag_invalid_snan;
/* fall through */
case float_class_qnan:
flags = float_flag_invalid;
flags |= float_flag_invalid;
r = max;
break;
case float_class_inf:
flags = float_flag_invalid;
flags = float_flag_invalid | float_flag_invalid_cvti;
r = p->sign ? min : max;
break;
@ -1070,11 +1079,11 @@ static int64_t partsN(float_to_sint)(FloatPartsN *p, FloatRoundMode rmode,
if (r <= -(uint64_t)min) {
r = -r;
} else {
flags = float_flag_invalid;
flags = float_flag_invalid | float_flag_invalid_cvti;
r = min;
}
} else if (r > max) {
flags = float_flag_invalid;
flags = float_flag_invalid | float_flag_invalid_cvti;
r = max;
}
break;
@ -1107,13 +1116,15 @@ static uint64_t partsN(float_to_uint)(FloatPartsN *p, FloatRoundMode rmode,
switch (p->cls) {
case float_class_snan:
flags |= float_flag_invalid_snan;
/* fall through */
case float_class_qnan:
flags = float_flag_invalid;
flags |= float_flag_invalid;
r = max;
break;
case float_class_inf:
flags = float_flag_invalid;
flags = float_flag_invalid | float_flag_invalid_cvti;
r = p->sign ? 0 : max;
break;
@ -1131,15 +1142,15 @@ static uint64_t partsN(float_to_uint)(FloatPartsN *p, FloatRoundMode rmode,
}
if (p->sign) {
flags = float_flag_invalid;
flags = float_flag_invalid | float_flag_invalid_cvti;
r = 0;
} else if (p->exp > DECOMPOSED_BINARY_POINT) {
flags = float_flag_invalid;
flags = float_flag_invalid | float_flag_invalid_cvti;
r = max;
} else {
r = p->frac_hi >> (DECOMPOSED_BINARY_POINT - p->exp);
if (r > max) {
flags = float_flag_invalid;
flags = float_flag_invalid | float_flag_invalid_cvti;
r = max;
}
}
@ -1334,7 +1345,9 @@ static FloatRelation partsN(compare)(FloatPartsN *a, FloatPartsN *b,
}
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);
}
return float_relation_unordered;

View File

@ -506,7 +506,7 @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
* the default NaN
*/
if (infzero && is_qnan(c_cls)) {
float_raise(float_flag_invalid, status);
float_raise(float_flag_invalid | float_flag_invalid_imz, status);
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
*/
if (infzero) {
float_raise(float_flag_invalid, status);
float_raise(float_flag_invalid | float_flag_invalid_imz, status);
return 3;
}
/* 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'
*/
if (infzero) {
float_raise(float_flag_invalid, status);
float_raise(float_flag_invalid | float_flag_invalid_imz, status);
return 2;
}
/* 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
*/
if (infzero) {
float_raise(float_flag_invalid, status);
float_raise(float_flag_invalid | float_flag_invalid_imz, status);
return 2;
}
@ -597,7 +597,7 @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
#elif defined(TARGET_RISCV)
/* For RISC-V, InvalidOp is set when multiplicands are Inf and zero */
if (infzero) {
float_raise(float_flag_invalid, status);
float_raise(float_flag_invalid | float_flag_invalid_imz, status);
}
return 3; /* default NaN */
#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).
*/
if (infzero) {
float_raise(float_flag_invalid, status);
float_raise(float_flag_invalid | float_flag_invalid_imz, status);
return 2;
}
if (status->use_first_nan) {

View File

@ -1693,6 +1693,50 @@ static float64 float64_round_pack_canonical(FloatParts64 *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,
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);
}
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
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);
}
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_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);
}
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,
int flags, float_status *status)
{
@ -2419,6 +2509,17 @@ float64_div(float64 a, float64 b, float_status *s)
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_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)
{
switch (a->cls) {
case float_class_qnan:
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
* 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);
}
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)
{
FloatParts64 p;

View File

@ -368,27 +368,10 @@ typedef struct GDBState {
gdb_syscall_complete_cb current_syscall_cb;
GString *str_buf;
GByteArray *mem_buf;
int sstep_flags;
int supported_sstep_flags;
} 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 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.mem_buf = g_byte_array_sized_new(MAX_PACKET_LENGTH);
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
@ -505,7 +511,7 @@ static int gdb_continue_partial(char *newstates)
CPU_FOREACH(cpu) {
if (newstates[cpu->cpu_index] == 's') {
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;
@ -524,7 +530,7 @@ static int gdb_continue_partial(char *newstates)
break; /* nothing to do here */
case 's':
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);
flag = 1;
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);
}
cpu_single_step(gdbserver_state.c_cpu, get_sstep_flags());
cpu_single_step(gdbserver_state.c_cpu, gdbserver_state.sstep_flags);
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)
{
g_string_printf(gdbserver_state.str_buf, "ENABLE=%x,NOIRQ=%x,NOTIMER=%x",
SSTEP_ENABLE, SSTEP_NOIRQ, SSTEP_NOTIMER);
g_string_printf(gdbserver_state.str_buf, "ENABLE=%x", SSTEP_ENABLE);
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();
}
static void handle_set_qemu_sstep(GArray *params, void *user_ctx)
{
int new_sstep_flags;
if (!params->len) {
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");
}
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();
}
@ -3497,6 +3523,11 @@ int gdbserver_start(const char *device)
return -1;
}
if (kvm_enabled() && !kvm_supports_guest_debug()) {
error_report("gdbstub: KVM doesn't support guest debugging");
return -1;
}
if (!device)
return -1;
if (strcmp(device, "none") != 0) {

View File

@ -27,6 +27,7 @@ config ARM_VIRT
select DIMM
select ACPI_HW_REDUCED
select ACPI_APEI
select ACPI_VIOT
config CHEETAH
bool

View File

@ -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,
const char *flashtype)
const char *flashtype,
int unit0)
{
int 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;
DeviceState *dev;
@ -382,10 +383,12 @@ static void aspeed_machine_init(MachineState *machine)
"max_ram", max_ram_size - machine->ram_size);
memory_region_add_subregion(&bmc->ram_container, machine->ram_size, &bmc->max_ram);
aspeed_board_init_flashes(&bmc->soc.fmc, bmc->fmc_model ?
bmc->fmc_model : amc->fmc_model);
aspeed_board_init_flashes(&bmc->soc.spi[0], bmc->spi_model ?
bmc->spi_model : amc->spi_model);
aspeed_board_init_flashes(&bmc->soc.fmc,
bmc->fmc_model ? bmc->fmc_model : amc->fmc_model,
0);
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. */
if (drive0) {
@ -435,11 +438,13 @@ static void aspeed_machine_init(MachineState *machine)
}
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) {
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);

View File

@ -8,7 +8,6 @@
*/
#include "qemu/osdep.h"
#include "qemu-common.h"
#include "qemu/datadir.h"
#include "qemu/error-report.h"
#include "qapi/error.h"

View File

@ -81,7 +81,7 @@ static void cubieboard_init(MachineState *machine)
}
/* Retrieve SD bus */
di = drive_get_next(IF_SD);
di = drive_get(IF_SD, 0, 0);
blk = di ? blk_by_legacy_dinfo(di) : NULL;
bus = qdev_get_child_bus(DEVICE(a10), "sd-bus");

View File

@ -25,7 +25,6 @@
#include "qemu/osdep.h"
#include "qapi/error.h"
#include "qemu-common.h"
#include "qemu/datadir.h"
#include "hw/boards.h"
#include "qemu/error-report.h"

View File

@ -18,7 +18,6 @@
*/
#include "qemu/osdep.h"
#include "qemu-common.h"
#include "qemu/datadir.h"
#include "qapi/error.h"
#include "hw/sysbus.h"

View File

@ -123,7 +123,7 @@ static void imx25_pdk_init(MachineState *machine)
DriveInfo *di;
BlockBackend *blk;
di = drive_get_next(IF_SD);
di = drive_get(IF_SD, 0, i);
blk = di ? blk_by_legacy_dinfo(di) : NULL;
bus = qdev_get_child_bus(DEVICE(&s->soc.esdhc[i]), "sd-bus");
carddev = qdev_new(TYPE_SD_CARD);

View File

@ -649,7 +649,7 @@ static void integratorcp_init(MachineState *machine)
qdev_get_gpio_in_named(icp, ICP_GPIO_MMC_WPROT, 0));
qdev_connect_gpio_out_named(dev, "card-inserted", 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) {
DeviceState *card;

View File

@ -52,7 +52,7 @@ static void mcimx6ul_evk_init(MachineState *machine)
DriveInfo *di;
BlockBackend *blk;
di = drive_get_next(IF_SD);
di = drive_get(IF_SD, 0, i);
blk = di ? blk_by_legacy_dinfo(di) : NULL;
bus = qdev_get_child_bus(DEVICE(&s->usdhc[i]), "sd-bus");
carddev = qdev_new(TYPE_SD_CARD);

View File

@ -52,7 +52,7 @@ static void mcimx7d_sabre_init(MachineState *machine)
DriveInfo *di;
BlockBackend *blk;
di = drive_get_next(IF_SD);
di = drive_get(IF_SD, 0, i);
blk = di ? blk_by_legacy_dinfo(di) : NULL;
bus = qdev_get_child_bus(DEVICE(&s->usdhc[i]), "sd-bus");
carddev = qdev_new(TYPE_SD_CARD);

View File

@ -45,7 +45,7 @@ static void emcraft_sf2_s2s010_init(MachineState *machine)
DeviceState *spi_flash;
MSF2State *soc;
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;
BusState *spi_bus;
MemoryRegion *sysmem = get_system_memory();

View File

@ -24,7 +24,6 @@
#include "hw/qdev-core.h"
#include "hw/qdev-properties.h"
#include "qapi/error.h"
#include "qemu-common.h"
#include "qemu/datadir.h"
#include "qemu/units.h"
#include "sysemu/blockdev.h"
@ -84,9 +83,9 @@ static void npcm7xx_connect_dram(NPCM7xxState *soc, MemoryRegion *dram)
&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;
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));
quanta_gbs_i2c_init(soc);
sdhci_attach_drive(&soc->mmc.sdhci);
sdhci_attach_drive(&soc->mmc.sdhci, 0);
npcm7xx_load_kernel(machine, soc);
}

View File

@ -85,7 +85,7 @@ static void orangepi_init(MachineState *machine)
qdev_realize(DEVICE(h3), NULL, &error_abort);
/* Retrieve SD bus */
di = drive_get_next(IF_SD);
di = drive_get(IF_SD, 0, 0);
blk = di ? blk_by_legacy_dinfo(di) : NULL;
bus = qdev_get_child_bus(DEVICE(h3), "sd-bus");

View File

@ -284,7 +284,7 @@ static void raspi_machine_init(MachineState *machine)
qdev_realize(DEVICE(&s->soc), NULL, &error_fatal);
/* 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;
bus = qdev_get_child_bus(DEVICE(&s->soc), "sd-bus");
if (bus == NULL) {

View File

@ -237,7 +237,7 @@ static void realview_init(MachineState *machine,
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-inserted", 0, mmc_irq[1]);
dinfo = drive_get_next(IF_SD);
dinfo = drive_get(IF_SD, 0, 0);
if (dinfo) {
DeviceState *card;

View File

@ -76,7 +76,7 @@ static void sabrelite_init(MachineState *machine)
if (spi_bus) {
DeviceState *flash_dev;
qemu_irq cs_line;
DriveInfo *dinfo = drive_get_next(IF_MTD);
DriveInfo *dinfo = drive_get(IF_MTD, 0, 0);
flash_dev = qdev_new("sst25vf016b");
if (dinfo) {

View File

@ -18,7 +18,6 @@
*/
#include "qemu/osdep.h"
#include "qemu-common.h"
#include "qemu/datadir.h"
#include "qapi/error.h"
#include "qemu/error-report.h"

View File

@ -10,6 +10,7 @@
#include "qemu/osdep.h"
#include "qapi/error.h"
#include "hw/sysbus.h"
#include "hw/sd/sd.h"
#include "hw/ssi/ssi.h"
#include "hw/arm/boot.h"
#include "qemu/timer.h"
@ -1157,6 +1158,9 @@ static void stellaris_init(MachineState *ms, stellaris_board_info *board)
void *bus;
DeviceState *sddev;
DeviceState *ssddev;
DriveInfo *dinfo;
DeviceState *carddev;
BlockBackend *blk;
/*
* 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
*/
bus = qdev_get_child_bus(dev, "ssi");
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");
gpio_out[GPIO_D][0] = qemu_irq_split(
qdev_get_gpio_in_named(sddev, SSI_GPIO_CS, 0),

View File

@ -24,7 +24,6 @@
#include "qemu/osdep.h"
#include "qapi/error.h"
#include "qemu-common.h"
#include "exec/address-spaces.h"
#include "sysemu/sysemu.h"
#include "hw/arm/stm32f405_soc.h"

View File

@ -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));
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) {
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);
dinfo = drive_get_next(IF_SD);
dinfo = drive_get(IF_SD, 0, 1);
if (dinfo) {
DeviceState *card;

View File

@ -23,7 +23,6 @@
#include "qemu/osdep.h"
#include "qapi/error.h"
#include "qemu-common.h"
#include "qemu/datadir.h"
#include "cpu.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_connect_gpio_out_named(dev, "card-inserted", 0,
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) {
DeviceState *card;
@ -657,7 +656,7 @@ static void vexpress_common_init(MachineState *machine)
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",
dinfo);
if (!pflash0) {
@ -673,7 +672,7 @@ static void vexpress_common_init(MachineState *machine)
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",
dinfo)) {
error_report("vexpress: error registering flash 1");

View File

@ -55,6 +55,7 @@
#include "kvm_arm.h"
#include "migration/vmstate.h"
#include "hw/acpi/ghes.h"
#include "hw/acpi/viot.h"
#define ARM_SPI_BASE 32
@ -1011,6 +1012,12 @@ void virt_acpi_build(VirtMachineState *vms, AcpiBuildTables *tables)
}
#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 = tables_blob->len;
build_xsdt(tables_blob, tables->linker, table_offsets, vms->oem_id,

View File

@ -29,7 +29,6 @@
*/
#include "qemu/osdep.h"
#include "qemu-common.h"
#include "qemu/datadir.h"
#include "qemu/units.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;
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) {
case VIRT_MSI_CTRL_NONE:
return;
@ -2513,8 +2517,9 @@ static void virt_machine_device_pre_plug_cb(HotplugHandler *hotplug_dev,
db_start, db_end,
VIRTIO_IOMMU_RESV_MEM_T_MSI);
qdev_prop_set_uint32(dev, "len-reserved-regions", 1);
qdev_prop_set_string(dev, "reserved-regions[0]", resv_prop_str);
object_property_set_uint(OBJECT(dev), "len-reserved-regions", 1, errp);
object_property_set_str(OBJECT(dev), "reserved-regions[0]",
resv_prop_str, errp);
g_free(resv_prop_str);
}
}
@ -2614,16 +2619,10 @@ static HotplugHandler *virt_machine_get_hotplug_handler(MachineState *machine,
MachineClass *mc = MACHINE_GET_CLASS(machine);
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);
}
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;
}

View File

@ -125,9 +125,10 @@ static void gem_init(NICInfo *nd, uint32_t base, qemu_irq irq)
sysbus_connect_irq(s, 0, irq);
}
static inline void zynq_init_spi_flashes(uint32_t base_addr, qemu_irq irq,
bool is_qspi)
static inline int zynq_init_spi_flashes(uint32_t base_addr, qemu_irq irq,
bool is_qspi, int unit0)
{
int unit = unit0;
DeviceState *dev;
SysBusDevice *busdev;
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);
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");
if (dinfo) {
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)
@ -247,9 +249,9 @@ static void zynq_init(MachineState *machine)
pic[n] = qdev_get_gpio_in(dev, n);
}
zynq_init_spi_flashes(0xE0006000, pic[58-IRQ_OFFSET], false);
zynq_init_spi_flashes(0xE0007000, pic[81-IRQ_OFFSET], false);
zynq_init_spi_flashes(0xE000D000, pic[51-IRQ_OFFSET], true);
n = zynq_init_spi_flashes(0xE0006000, pic[58 - IRQ_OFFSET], false, 0);
n = zynq_init_spi_flashes(0xE0007000, pic[81 - IRQ_OFFSET], false, n);
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, 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_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;
carddev = qdev_new(TYPE_SD_CARD);
qdev_prop_set_drive_err(carddev, "drive", blk, &error_fatal);

View File

@ -669,7 +669,8 @@ static void versal_virt_init(MachineState *machine)
/* Plugin SD cards. */
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;

View File

@ -169,7 +169,7 @@ static void xlnx_zcu102_init(MachineState *machine)
/* Create and plug in the SD cards */
for (i = 0; i < XLNX_ZYNQMP_NUM_SDHCI; i++) {
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;
DeviceState *carddev;
char *bus_name;
@ -190,7 +190,7 @@ static void xlnx_zcu102_init(MachineState *machine)
BusState *spi_bus;
DeviceState *flash_dev;
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);
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;
DeviceState *flash_dev;
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;
gchar *bus_name = g_strdup_printf("qspi%d", bus);

View File

@ -233,7 +233,7 @@ static void atmega_realize(DeviceState *dev, Error **errp)
/* CPU */
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);
/* SRAM */

View File

@ -222,7 +222,7 @@ int virtio_blk_data_plane_start(VirtIODevice *vdev)
memory_region_transaction_commit();
while (j--) {
virtio_bus_cleanup_host_notifier(VIRTIO_BUS(qbus), i);
virtio_bus_cleanup_host_notifier(VIRTIO_BUS(qbus), j);
}
goto fail_host_notifiers;
}

View File

@ -103,10 +103,11 @@ static uint64_t stm32f2xx_usart_read(void *opaque, hwaddr addr,
return retvalue;
case 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;
qemu_chr_fe_accept_input(&s->chr);
qemu_set_irq(s->irq, 0);
return s->usart_dr & 0x3FF;
return retvalue;
case USART_BRR:
return s->usart_brr;
case USART_CR1:

View File

@ -784,9 +784,8 @@ static void numa_stat_memory_devices(NumaNodeMem node_mem[])
break;
case MEMORY_DEVICE_INFO_KIND_SGX_EPC:
se = value->u.sgx_epc.data;
/* TODO: once we support numa, assign to right node */
node_mem[0].node_mem += se->size;
node_mem[0].node_plugged_mem += se->size;
node_mem[se->node].node_mem += se->size;
node_mem[se->node].node_plugged_mem = 0;
break;
default:
g_assert_not_reached();

View File

@ -33,7 +33,6 @@
#include "hw/loader.h"
#include "hw/qdev-properties.h"
#include "qom/object.h"
#include "qapi/error.h"
#define TYPE_ISA_VGA "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;
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;
vga_common_init(s, OBJECT(dev));
s->legacy_address_space = isa_address_space(isadev);

View File

@ -2068,6 +2068,8 @@ build_srat(GArray *table_data, BIOSLinker *linker, MachineState *machine)
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
* without these entries. But I recall there were issues the last time I

View File

@ -21,6 +21,7 @@
static Property sgx_epc_properties[] = {
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,
TYPE_MEMORY_BACKEND_EPC, HostMemoryBackendEpc *),
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->size = object_property_get_uint(OBJECT(epc), SGX_EPC_SIZE_PROP,
NULL);
se->node = object_property_get_uint(OBJECT(epc), SGX_EPC_NUMA_NODE_PROP,
NULL);
se->memdev = object_get_canonical_path(OBJECT(epc->hostmem));
info->u.sgx_epc.data = se;

View File

@ -6,6 +6,10 @@
#include "qapi/error.h"
#include "qapi/qapi-commands-misc-target.h"
void sgx_epc_build_srat(GArray *table_data)
{
}
SGXInfo *qmp_query_sgx(Error **errp)
{
error_setg(errp, "SGX support is not compiled in");

View File

@ -23,6 +23,7 @@
#include "sysemu/hw_accel.h"
#include "sysemu/reset.h"
#include <sys/ioctl.h>
#include "hw/acpi/aml-build.h"
#define SGX_MAX_EPC_SECTIONS 8
#define SGX_CPUID_EPC_INVALID 0x0
@ -36,17 +37,59 @@
#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)
{
return (low & MAKE_64BIT_MASK(12, 20)) +
((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 eax, ebx, ecx, edx;
uint64_t size = 0;
uint32_t j = 0;
for (i = 0; i < SGX_MAX_EPC_SECTIONS; i++) {
host_cpuid(0x12, i + 2, &eax, &ebx, &ecx, &edx);
@ -60,10 +103,13 @@ static uint64_t sgx_calc_host_epc_section_size(void)
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)
@ -127,13 +173,35 @@ SGXInfo *qmp_query_sgx_capabilities(Error **errp)
info->sgx1 = eax & (1U << 0) ? 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);
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 *info = NULL;
@ -152,14 +220,13 @@ SGXInfo *qmp_query_sgx(Error **errp)
return NULL;
}
SGXEPCState *sgx_epc = &pcms->sgx_epc;
info = g_new0(SGXInfo, 1);
info->sgx = true;
info->sgx1 = true;
info->sgx2 = true;
info->flc = true;
info->section_size = sgx_epc->size;
info->sections = sgx_get_epc_sections_list();
return info;
}
@ -167,6 +234,7 @@ SGXInfo *qmp_query_sgx(Error **errp)
void hmp_info_sgx(Monitor *mon, const QDict *qdict)
{
Error *err = NULL;
SGXEPCSectionList *section_list, *section;
g_autoptr(SGXInfo) info = qmp_query_sgx(&err);
if (err) {
@ -181,8 +249,14 @@ void hmp_info_sgx(Monitor *mon, const QDict *qdict)
info->sgx2 ? "enabled" : "disabled");
monitor_printf(mon, "FLC support: %s\n",
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)
@ -226,6 +300,9 @@ void pc_machine_init_sgx_epc(PCMachineState *pcms)
/* set the memdev link with memory backend */
object_property_parse(obj, SGX_EPC_MEMDEV_PROP, list->value->memdev,
&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_unref(obj);
}

View File

@ -286,6 +286,10 @@ static void vmmouse_realizefn(DeviceState *dev, Error **errp)
DPRINTF("vmmouse_init\n");
if (!s->i8042) {
error_setg(errp, "'i8042' link is not set");
return;
}
if (!object_resolve_path_type("", TYPE_VMPORT, NULL)) {
error_setg(errp, "vmmouse needs a machine with vmport");
return;

View File

@ -25,6 +25,11 @@ config APIC
select MSI_NONBROKEN
select I8259
config ARM_GIC_TCG
bool
default y
depends on ARM_GIC && TCG
config ARM_GIC_KVM
bool
default y

View File

@ -1,5 +1,5 @@
/*
* ARM Generic Interrupt Controller v3
* ARM Generic Interrupt Controller v3 (emulation)
*
* Copyright (c) 2015 Huawei.
* Copyright (c) 2016 Linaro Limited

View File

@ -1,5 +1,5 @@
/*
* ARM Generic Interrupt Controller v3
* ARM Generic Interrupt Controller v3 (emulation)
*
* Copyright (c) 2016 Linaro Limited
* Written by Peter Maydell
@ -21,14 +21,6 @@
#include "hw/irq.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)
{
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 */
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;
}

View 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;
};

View File

@ -274,21 +274,36 @@ static bool process_its_cmd(GICv3ITSState *s, uint64_t value, uint32_t offset,
if (res != MEMTX_OK) {
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)) {
/*
* In this implementation, in case of guest errors we ignore the
* command and move onto the next command in the queue.
*/
if (devid > s->dt.maxids.max_devids) {
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
* we ignore this command and move onto the next
* command in the queue
*/
"%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 {
/*
* Current implementation only supports rdbase == procnum

View File

@ -3,12 +3,14 @@ softmmu_ss.add(when: 'CONFIG_ARM_GIC', if_true: files(
'arm_gic.c',
'arm_gic_common.c',
'arm_gicv2m.c',
'arm_gicv3.c',
'arm_gicv3_common.c',
'arm_gicv3_dist.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_redist.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'))
@ -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_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', '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'))

View File

@ -183,7 +183,7 @@ petalogix_ml605_init(MachineState *machine)
spi = (SSIBus *)qdev_get_child_bus(dev, "spi");
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;
dev = qdev_new("n25q128");

View File

@ -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_K1, addr);
bl_gen_sd(p, BL_REG_K0, BL_REG_K1, 0x0);
if (bootcpu_supports_isa(ISA_MIPS3)) {
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)

View File

@ -777,14 +777,15 @@ static void boston_mach_init(MachineState *machine)
exit(1);
}
} 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,
cpu_mips_kseg0_to_phys, NULL,
&kernel_entry, NULL, &kernel_high,
NULL, 0, EM_MIPS, 1, 0);
if (kernel_size) {
if (kernel_size > 0) {
int dt_size;
g_autofree const void *dtb_file_data, *dtb_load_data;
hwaddr dtb_paddr = QEMU_ALIGN_UP(kernel_high, 64 * KiB);

View File

@ -243,7 +243,7 @@ static uint64_t ivshmem_io_read(void *opaque, hwaddr addr,
static const MemoryRegionOps ivshmem_mmio_ops = {
.read = ivshmem_io_read,
.write = ivshmem_io_write,
.endianness = DEVICE_NATIVE_ENDIAN,
.endianness = DEVICE_LITTLE_ENDIAN,
.impl = {
.min_access_size = 4,
.max_access_size = 4,

View File

@ -209,9 +209,9 @@ static void sifive_u_otp_realize(DeviceState *dev, Error **errp)
TYPE_SIFIVE_U_OTP, SIFIVE_U_OTP_REG_SIZE);
sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->mmio);
dinfo = drive_get_next(IF_PFLASH);
dinfo = drive_get(IF_PFLASH, 0, 0);
if (!dinfo) {
dinfo = drive_get_next(IF_NONE);
dinfo = drive_get(IF_NONE, 0, 0);
if (dinfo) {
warn_report("using \"-drive if=none\" for the OTP is deprecated, "
"use \"-drive if=pflash\" instead.");

View File

@ -284,6 +284,12 @@ static void emc_halt_rx(NPCM7xxEMCState *emc, uint32_t 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,
const NPCM7xxEMCTxDesc *tx_desc,
uint32_t desc_addr)
@ -581,13 +587,6 @@ static ssize_t emc_receive(NetClientState *nc, const uint8_t *buf, size_t len1)
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)
{
NPCM7xxEMCState *emc = opaque;
@ -703,7 +702,7 @@ static void npcm7xx_emc_write(void *opaque, hwaddr offset,
emc->regs[REG_MGSTA] |= REG_MGSTA_RXHA;
}
if (value & REG_MCMDR_RXON) {
emc->rx_active = true;
emc_enable_rx_and_flush(emc);
} else {
emc_halt_rx(emc, 0);
}
@ -739,8 +738,7 @@ static void npcm7xx_emc_write(void *opaque, hwaddr offset,
break;
case REG_RSDR:
if (emc->regs[REG_MCMDR] & REG_MCMDR_RXON) {
emc->rx_active = true;
emc_try_receive_next_packet(emc);
emc_enable_rx_and_flush(emc);
}
break;
case REG_MIIDA:

View File

@ -993,7 +993,7 @@ static void pnv_phb3_realize(DeviceState *dev, Error **errp)
PnvMachineState *pnv = PNV_MACHINE(qdev_get_machine());
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);
return;
}
@ -1092,6 +1092,7 @@ static const char *pnv_phb3_root_bus_path(PCIHostState *host_bridge,
static Property pnv_phb3_properties[] = {
DEFINE_PROP_UINT32("index", PnvPHB3, phb_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(),
};

View File

@ -284,6 +284,17 @@ static void pnv_pbcq_realize(DeviceState *dev, Error **errp)
pnv_xscom_region_init(&pbcq->xscom_spci_regs, OBJECT(dev),
&pnv_pbcq_spci_xscom_ops, pbcq, name,
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,

View File

@ -1205,6 +1205,7 @@ static void pnv_phb4_realize(DeviceState *dev, Error **errp)
&phb->pci_mmio, &phb->pci_io,
0, 4, TYPE_PNV_PHB4_ROOT_BUS);
pci_setup_iommu(pci->bus, pnv_phb4_dma_iommu, phb);
pci->bus->flags |= PCI_BUS_EXTENDED_CONFIG_SPACE;
/* Add a single Root port */
qdev_prop_set_uint8(DEVICE(&phb->root), "chassis", phb->chip_id);

View File

@ -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)
{
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, mask, size;
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)
{
PnvPhb4PecState *pec = PNV_PHB4_PEC(dev);
PnvPhb4PecClass *pecc = PNV_PHB4_PEC_GET_CLASS(pec);
char name[64];
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 */
for (i = 0; i < pec->num_stacks; i++) {
PnvPhb4PecStack *stack = &pec->stacks[i];
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, "phb-id", phb_id, &error_abort);
object_property_set_link(stk_obj, "pec", OBJECT(pec), &error_abort);
if (!qdev_realize(DEVICE(stk_obj), NULL, errp)) {
return;
@ -460,10 +481,9 @@ static int pnv_pec_dt_xscom(PnvXScomInterface *dev, void *fdt,
static Property pnv_pec_properties[] = {
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_LINK("system-memory", PnvPhb4PecState, system_memory,
TYPE_MEMORY_REGION, MemoryRegion *),
DEFINE_PROP_LINK("chip", PnvPhb4PecState, chip, TYPE_PNV_CHIP,
PnvChip *),
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;
}
/*
* 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)
{
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->stk_compat = 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 = {
@ -519,12 +549,17 @@ static void pnv_pec_stk_instance_init(Object *obj)
PnvPhb4PecStack *stack = PNV_PHB4_PEC_STACK(obj);
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)
{
PnvPhb4PecStack *stack = PNV_PHB4_PEC_STACK(dev);
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];
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_phb4_xscom_ops, &stack->phb, name, 0x40);
/*
* Let the machine/chip realize the PHB object to customize more
* easily some fields
*/
object_property_set_int(OBJECT(&stack->phb), "chip-id", pec->chip_id,
&error_fatal);
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[] = {

View File

@ -36,9 +36,6 @@
#include "hw/pci-host/uninorth.h"
#include "qom/object.h"
/* SMP is not enabled, for now */
#define MAX_CPUS 1
#define NVRAM_SIZE 0x2000
#define PROM_FILENAME "openbios-ppc"

View File

@ -581,7 +581,8 @@ static void core99_machine_class_init(ObjectClass *oc, void *data)
mc->desc = "Mac99 based PowerMAC";
mc->init = ppc_core99_init;
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_display = "std";
mc->kvm_type = core99_kvm_type;

View File

@ -423,7 +423,8 @@ static void heathrow_class_init(ObjectClass *oc, void *data)
mc->desc = "Heathrow based PowerMAC";
mc->init = ppc_heathrow_init;
mc->block_default_type = IF_IDE;
mc->max_cpus = MAX_CPUS;
/* SMP is not supported currently */
mc->max_cpus = 1;
#ifndef TARGET_PPC64
mc->is_default = true;
#endif

View File

@ -522,7 +522,7 @@ static void *pnv_dt_create(MachineState *machine)
buf = qemu_uuid_unparse_strdup(&qemu_uuid);
_FDT((fdt_setprop_string(fdt, 0, "vm,uuid", buf)));
if (qemu_uuid_set) {
_FDT((fdt_property_string(fdt, "system-id", buf)));
_FDT((fdt_setprop_string(fdt, 0, "system-id", 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);
}
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)
{
Pnv8Chip *chip8 = PNV8_CHIP(chip);
int i;
ics_pic_print_info(&chip8->psi.ics, mon);
for (i = 0; i < chip->num_phbs; i++) {
pnv_phb3_msi_pic_print_info(&chip8->phbs[i].msis, mon);
ics_pic_print_info(&chip8->phbs[i].lsis, mon);
object_child_foreach(OBJECT(chip),
pnv_chip_power8_pic_print_info_child, 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)
{
Pnv9Chip *chip9 = PNV9_CHIP(chip);
int i, j;
pnv_xive_pic_print_info(&chip9->xive, mon);
pnv_psi_pic_print_info(&chip9->psi, mon);
for (i = 0; i < PNV9_CHIP_MAX_PEC; i++) {
PnvPhb4PecState *pec = &chip9->pecs[i];
for (j = 0; j < pec->num_stacks; j++) {
pnv_phb4_pic_print_info(&pec->stacks[j].phb, mon);
}
}
object_child_foreach_recursive(OBJECT(chip),
pnv_chip_power9_pic_print_info_child, mon);
}
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);
DeviceState *dev;
if (kvm_enabled()) {
error_report("The powernv machine does not work with KVM acceleration");
exit(EXIT_FAILURE);
}
/* allocate RAM */
if (machine->ram_size < 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 */
for (i = 0; i < chip->num_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), "chip-id", chip->chip_id,
&error_fatal);
object_property_set_link(OBJECT(phb), "chip", OBJECT(chip),
&error_fatal);
if (!sysbus_realize(SYS_BUS_DEVICE(phb), errp)) {
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);
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],
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)
@ -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);
int i, j;
int phb_id = 0;
int i;
for (i = 0; i < PNV9_CHIP_MAX_PEC; i++) {
for (i = 0; i < chip->num_pecs; i++) {
PnvPhb4PecState *pec = &chip9->pecs[i];
PnvPhb4PecClass *pecc = PNV_PHB4_PEC_GET_CLASS(pec);
uint32_t pec_nest_base;
uint32_t pec_pci_base;
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,
&error_fatal);
object_property_set_link(OBJECT(pec), "system-memory",
OBJECT(get_system_memory()), &error_abort);
object_property_set_link(OBJECT(pec), "chip", OBJECT(chip),
&error_fatal);
if (!qdev_realize(DEVICE(pec), NULL, errp)) {
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_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),
&chip9->homer.regs);
/* PHBs */
pnv_chip_power9_phb_realize(chip, &local_err);
/* PEC PHBs */
pnv_chip_power9_pec_realize(chip, &local_err);
if (local_err) {
error_propagate(errp, local_err);
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_pcba = pnv_chip_power9_xscom_pcba;
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,
&k->parent_realize);
@ -1764,7 +1733,6 @@ static Property pnv_chip_properties[] = {
DEFINE_PROP_UINT32("nr-cores", PnvChip, nr_cores, 1),
DEFINE_PROP_UINT64("cores-mask", PnvChip, cores_mask, 0x0),
DEFINE_PROP_UINT32("nr-threads", PnvChip, nr_threads, 1),
DEFINE_PROP_UINT32("num-phbs", PnvChip, num_phbs, 0),
DEFINE_PROP_END_OF_LIST(),
};
@ -1795,10 +1763,32 @@ PowerPCCPU *pnv_chip_find_cpu(PnvChip *chip, uint32_t pir)
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)
{
PnvMachineState *pnv = PNV_MACHINE(xi);
int i, j;
ForeachPhb3Args args = { irq, NULL };
int i;
for (i = 0; i < pnv->num_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)) {
return &chip8->psi.ics;
}
for (j = 0; j < chip->num_phbs; j++) {
if (ics_valid_irq(&chip8->phbs[j].lsis, irq)) {
return &chip8->phbs[j].lsis;
}
if (ics_valid_irq(ICS(&chip8->phbs[j].msis), irq)) {
return ICS(&chip8->phbs[j].msis);
}
object_child_foreach(OBJECT(chip), pnv_ics_get_child, &args);
if (args.ics) {
return args.ics;
}
}
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)
{
PnvMachineState *pnv = PNV_MACHINE(xi);
int i, j;
int i;
for (i = 0; i < pnv->num_chips; i++) {
PnvChip *chip = pnv->chips[i];
Pnv8Chip *chip8 = PNV8_CHIP(pnv->chips[i]);
ics_resend(&chip8->psi.ics);
for (j = 0; j < chip->num_phbs; j++) {
ics_resend(&chip8->phbs[j].lsis);
ics_resend(ICS(&chip8->phbs[j].msis));
}
object_child_foreach(OBJECT(chip), pnv_ics_resend_child, NULL);
}
}

View File

@ -1367,6 +1367,7 @@ int ppc_dcr_read (ppc_dcr_t *dcr_env, int dcrn, uint32_t *valp)
if (dcr->dcr_read == NULL)
goto error;
*valp = (*dcr->dcr_read)(dcr->opaque, dcrn);
trace_ppc_dcr_read(dcrn, *valp);
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];
if (dcr->dcr_write == NULL)
goto error;
trace_ppc_dcr_write(dcrn, val);
(*dcr->dcr_write)(dcr->opaque, dcrn, val);
return 0;

View File

@ -27,6 +27,13 @@
#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 */
typedef struct ppc4xx_bd_info_t 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_pci_busfreq;
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_iic_fast[2];
};
/* PowerPC 405 core */
ram_addr_t ppc405_set_bootinfo (CPUPPCState *env, ppc4xx_bd_info_t *bd,
uint32_t flags);
ram_addr_t ppc405_set_bootinfo(CPUPPCState *env, ram_addr_t ram_size);
void ppc4xx_plb_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],
hwaddr ram_bases[2],
hwaddr ram_sizes[2],

Some files were not shown because too many files have changed in this diff Show More