Merge
This commit is contained in:
commit
5018a0766b
2
.gitignore
vendored
2
.gitignore
vendored
@ -22,5 +22,3 @@ GTAGS
|
|||||||
*.swp
|
*.swp
|
||||||
*.patch
|
*.patch
|
||||||
*.gcov
|
*.gcov
|
||||||
|
|
||||||
/subprojects/slirp
|
|
||||||
|
@ -42,8 +42,8 @@
|
|||||||
stage: test
|
stage: test
|
||||||
image: $CI_REGISTRY_IMAGE/qemu/$IMAGE:latest
|
image: $CI_REGISTRY_IMAGE/qemu/$IMAGE:latest
|
||||||
script:
|
script:
|
||||||
- scripts/git-submodule.sh update
|
- scripts/git-submodule.sh update roms/SLOF
|
||||||
$(sed -n '/GIT_SUBMODULES=/ s/.*=// p' build/config-host.mak)
|
- meson subprojects download $(cd build/subprojects && echo *)
|
||||||
- cd build
|
- cd build
|
||||||
- find . -type f -exec touch {} +
|
- find . -type f -exec touch {} +
|
||||||
# Avoid recompiling by hiding ninja with NINJA=":"
|
# Avoid recompiling by hiding ninja with NINJA=":"
|
||||||
|
@ -103,7 +103,7 @@ crash-test-debian:
|
|||||||
script:
|
script:
|
||||||
- cd build
|
- cd build
|
||||||
- make NINJA=":" check-venv
|
- make NINJA=":" check-venv
|
||||||
- pyvenv/bin/python3 scripts/device-crash-test -q --tcg-only ./qemu-system-i386
|
- tests/venv/bin/python3 scripts/device-crash-test -q --tcg-only ./qemu-system-i386
|
||||||
|
|
||||||
build-system-fedora:
|
build-system-fedora:
|
||||||
extends:
|
extends:
|
||||||
@ -146,8 +146,8 @@ crash-test-fedora:
|
|||||||
script:
|
script:
|
||||||
- cd build
|
- cd build
|
||||||
- make NINJA=":" check-venv
|
- make NINJA=":" check-venv
|
||||||
- pyvenv/bin/python3 scripts/device-crash-test -q ./qemu-system-ppc
|
- tests/venv/bin/python3 scripts/device-crash-test -q ./qemu-system-ppc
|
||||||
- pyvenv/bin/python3 scripts/device-crash-test -q ./qemu-system-riscv32
|
- tests/venv/bin/python3 scripts/device-crash-test -q ./qemu-system-riscv32
|
||||||
|
|
||||||
build-system-centos:
|
build-system-centos:
|
||||||
extends:
|
extends:
|
||||||
|
@ -7,7 +7,6 @@
|
|||||||
before_script:
|
before_script:
|
||||||
- export TAG="$CI_REGISTRY_IMAGE/qemu/$NAME:latest"
|
- export TAG="$CI_REGISTRY_IMAGE/qemu/$NAME:latest"
|
||||||
- export COMMON_TAG="$CI_REGISTRY/qemu-project/qemu/qemu/$NAME:latest"
|
- export COMMON_TAG="$CI_REGISTRY/qemu-project/qemu/qemu/$NAME:latest"
|
||||||
- apk add python3
|
|
||||||
- docker login $CI_REGISTRY -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD"
|
- docker login $CI_REGISTRY -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD"
|
||||||
- until docker info; do sleep 1; done
|
- until docker info; do sleep 1; done
|
||||||
script:
|
script:
|
||||||
|
@ -29,6 +29,14 @@ cross-arm64-user:
|
|||||||
variables:
|
variables:
|
||||||
IMAGE: debian-arm64-cross
|
IMAGE: debian-arm64-cross
|
||||||
|
|
||||||
|
cross-arm64-kvm-only:
|
||||||
|
extends: .cross_accel_build_job
|
||||||
|
needs:
|
||||||
|
job: arm64-debian-cross-container
|
||||||
|
variables:
|
||||||
|
IMAGE: debian-arm64-cross
|
||||||
|
EXTRA_CONFIGURE_OPTS: --disable-tcg --without-default-features
|
||||||
|
|
||||||
cross-i386-user:
|
cross-i386-user:
|
||||||
extends:
|
extends:
|
||||||
- .cross_user_build_job
|
- .cross_user_build_job
|
||||||
|
15
.gitmodules
vendored
15
.gitmodules
vendored
@ -13,9 +13,6 @@
|
|||||||
[submodule "roms/qemu-palcode"]
|
[submodule "roms/qemu-palcode"]
|
||||||
path = roms/qemu-palcode
|
path = roms/qemu-palcode
|
||||||
url = https://gitlab.com/qemu-project/qemu-palcode.git
|
url = https://gitlab.com/qemu-project/qemu-palcode.git
|
||||||
[submodule "subprojects/dtc"]
|
|
||||||
path = subprojects/dtc
|
|
||||||
url = https://gitlab.com/qemu-project/dtc.git
|
|
||||||
[submodule "roms/u-boot"]
|
[submodule "roms/u-boot"]
|
||||||
path = roms/u-boot
|
path = roms/u-boot
|
||||||
url = https://gitlab.com/qemu-project/u-boot.git
|
url = https://gitlab.com/qemu-project/u-boot.git
|
||||||
@ -25,21 +22,12 @@
|
|||||||
[submodule "roms/QemuMacDrivers"]
|
[submodule "roms/QemuMacDrivers"]
|
||||||
path = roms/QemuMacDrivers
|
path = roms/QemuMacDrivers
|
||||||
url = https://gitlab.com/qemu-project/QemuMacDrivers.git
|
url = https://gitlab.com/qemu-project/QemuMacDrivers.git
|
||||||
[submodule "subprojects/keycodemapdb"]
|
|
||||||
path = subprojects/keycodemapdb
|
|
||||||
url = https://gitlab.com/qemu-project/keycodemapdb.git
|
|
||||||
[submodule "roms/seabios-hppa"]
|
[submodule "roms/seabios-hppa"]
|
||||||
path = roms/seabios-hppa
|
path = roms/seabios-hppa
|
||||||
url = https://gitlab.com/qemu-project/seabios-hppa.git
|
url = https://gitlab.com/qemu-project/seabios-hppa.git
|
||||||
[submodule "roms/u-boot-sam460ex"]
|
[submodule "roms/u-boot-sam460ex"]
|
||||||
path = roms/u-boot-sam460ex
|
path = roms/u-boot-sam460ex
|
||||||
url = https://gitlab.com/qemu-project/u-boot-sam460ex.git
|
url = https://gitlab.com/qemu-project/u-boot-sam460ex.git
|
||||||
[submodule "tests/fp/berkeley-testfloat-3"]
|
|
||||||
path = tests/fp/berkeley-testfloat-3
|
|
||||||
url = https://gitlab.com/qemu-project/berkeley-testfloat-3.git
|
|
||||||
[submodule "tests/fp/berkeley-softfloat-3"]
|
|
||||||
path = tests/fp/berkeley-softfloat-3
|
|
||||||
url = https://gitlab.com/qemu-project/berkeley-softfloat-3.git
|
|
||||||
[submodule "roms/edk2"]
|
[submodule "roms/edk2"]
|
||||||
path = roms/edk2
|
path = roms/edk2
|
||||||
url = https://gitlab.com/qemu-project/edk2.git
|
url = https://gitlab.com/qemu-project/edk2.git
|
||||||
@ -55,6 +43,3 @@
|
|||||||
[submodule "tests/lcitool/libvirt-ci"]
|
[submodule "tests/lcitool/libvirt-ci"]
|
||||||
path = tests/lcitool/libvirt-ci
|
path = tests/lcitool/libvirt-ci
|
||||||
url = https://gitlab.com/libvirt/libvirt-ci.git
|
url = https://gitlab.com/libvirt/libvirt-ci.git
|
||||||
[submodule "subprojects/libvfio-user"]
|
|
||||||
path = subprojects/libvfio-user
|
|
||||||
url = https://gitlab.com/qemu-project/libvfio-user.git
|
|
||||||
|
@ -154,6 +154,8 @@ F: include/exec/exec-all.h
|
|||||||
F: include/exec/tb-flush.h
|
F: include/exec/tb-flush.h
|
||||||
F: include/exec/target_long.h
|
F: include/exec/target_long.h
|
||||||
F: include/exec/helper*.h
|
F: include/exec/helper*.h
|
||||||
|
F: include/exec/helper*.h.inc
|
||||||
|
F: include/exec/helper-info.c.inc
|
||||||
F: include/sysemu/cpus.h
|
F: include/sysemu/cpus.h
|
||||||
F: include/sysemu/tcg.h
|
F: include/sysemu/tcg.h
|
||||||
F: include/hw/core/tcg-cpu-ops.h
|
F: include/hw/core/tcg-cpu-ops.h
|
||||||
@ -1738,7 +1740,7 @@ F: hw/rtc/mc146818rtc*
|
|||||||
F: hw/watchdog/wdt_ib700.c
|
F: hw/watchdog/wdt_ib700.c
|
||||||
F: hw/watchdog/wdt_i6300esb.c
|
F: hw/watchdog/wdt_i6300esb.c
|
||||||
F: include/hw/display/vga.h
|
F: include/hw/display/vga.h
|
||||||
F: include/hw/char/parallel.h
|
F: include/hw/char/parallel*.h
|
||||||
F: include/hw/dma/i8257.h
|
F: include/hw/dma/i8257.h
|
||||||
F: include/hw/i2c/pm_smbus.h
|
F: include/hw/i2c/pm_smbus.h
|
||||||
F: include/hw/input/i8042.h
|
F: include/hw/input/i8042.h
|
||||||
@ -1817,7 +1819,7 @@ M: Francisco Iglesias <francisco.iglesias@amd.com>
|
|||||||
S: Maintained
|
S: Maintained
|
||||||
F: hw/net/can/xlnx-*
|
F: hw/net/can/xlnx-*
|
||||||
F: include/hw/net/xlnx-*
|
F: include/hw/net/xlnx-*
|
||||||
F: tests/qtest/xlnx-can-test*
|
F: tests/qtest/xlnx-can*-test*
|
||||||
|
|
||||||
EDU
|
EDU
|
||||||
M: Jiri Slaby <jslaby@suse.cz>
|
M: Jiri Slaby <jslaby@suse.cz>
|
||||||
@ -2865,7 +2867,6 @@ F: ui/cocoa.m
|
|||||||
Main loop
|
Main loop
|
||||||
M: Paolo Bonzini <pbonzini@redhat.com>
|
M: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
S: Maintained
|
S: Maintained
|
||||||
F: include/exec/gen-icount.h
|
|
||||||
F: include/qemu/main-loop.h
|
F: include/qemu/main-loop.h
|
||||||
F: include/sysemu/runstate.h
|
F: include/sysemu/runstate.h
|
||||||
F: include/sysemu/runstate-action.h
|
F: include/sysemu/runstate-action.h
|
||||||
@ -3045,6 +3046,7 @@ F: include/qom/
|
|||||||
F: qapi/qom.json
|
F: qapi/qom.json
|
||||||
F: qapi/qdev.json
|
F: qapi/qdev.json
|
||||||
F: scripts/coccinelle/qom-parent-type.cocci
|
F: scripts/coccinelle/qom-parent-type.cocci
|
||||||
|
F: scripts/qom-cast-macro-clean-cocci-gen.py
|
||||||
F: softmmu/qdev-monitor.c
|
F: softmmu/qdev-monitor.c
|
||||||
F: stubs/qdev.c
|
F: stubs/qdev.c
|
||||||
F: qom/
|
F: qom/
|
||||||
@ -3784,7 +3786,6 @@ F: tests/tcg/aarch64/system/semiheap.c
|
|||||||
Multi-process QEMU
|
Multi-process QEMU
|
||||||
M: Elena Ufimtseva <elena.ufimtseva@oracle.com>
|
M: Elena Ufimtseva <elena.ufimtseva@oracle.com>
|
||||||
M: Jagannathan Raman <jag.raman@oracle.com>
|
M: Jagannathan Raman <jag.raman@oracle.com>
|
||||||
M: John G Johnson <john.g.johnson@oracle.com>
|
|
||||||
S: Maintained
|
S: Maintained
|
||||||
F: docs/devel/multi-process.rst
|
F: docs/devel/multi-process.rst
|
||||||
F: docs/system/multi-process.rst
|
F: docs/system/multi-process.rst
|
||||||
|
12
Makefile
12
Makefile
@ -45,18 +45,6 @@ include config-host.mak
|
|||||||
include Makefile.prereqs
|
include Makefile.prereqs
|
||||||
Makefile.prereqs: config-host.mak
|
Makefile.prereqs: config-host.mak
|
||||||
|
|
||||||
git-submodule-update:
|
|
||||||
.git-submodule-status: git-submodule-update config-host.mak
|
|
||||||
Makefile: .git-submodule-status
|
|
||||||
|
|
||||||
.PHONY: git-submodule-update
|
|
||||||
git-submodule-update:
|
|
||||||
ifneq ($(GIT_SUBMODULES_ACTION),ignore)
|
|
||||||
$(call quiet-command, \
|
|
||||||
(GIT="$(GIT)" "$(SRC_PATH)/scripts/git-submodule.sh" $(GIT_SUBMODULES_ACTION) $(GIT_SUBMODULES)), \
|
|
||||||
"GIT","$(GIT_SUBMODULES)")
|
|
||||||
endif
|
|
||||||
|
|
||||||
# 0. ensure the build tree is okay
|
# 0. ensure the build tree is okay
|
||||||
|
|
||||||
# Check that we're not trying to do an out-of-tree build from
|
# Check that we're not trying to do an out-of-tree build from
|
||||||
|
@ -52,6 +52,7 @@
|
|||||||
#include "qemu/main-loop.h"
|
#include "qemu/main-loop.h"
|
||||||
#include "exec/address-spaces.h"
|
#include "exec/address-spaces.h"
|
||||||
#include "exec/exec-all.h"
|
#include "exec/exec-all.h"
|
||||||
|
#include "exec/gdbstub.h"
|
||||||
#include "sysemu/cpus.h"
|
#include "sysemu/cpus.h"
|
||||||
#include "sysemu/hvf.h"
|
#include "sysemu/hvf.h"
|
||||||
#include "sysemu/hvf_int.h"
|
#include "sysemu/hvf_int.h"
|
||||||
@ -334,18 +335,26 @@ static int hvf_accel_init(MachineState *ms)
|
|||||||
s->slots[x].slot_id = x;
|
s->slots[x].slot_id = x;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QTAILQ_INIT(&s->hvf_sw_breakpoints);
|
||||||
|
|
||||||
hvf_state = s;
|
hvf_state = s;
|
||||||
memory_listener_register(&hvf_memory_listener, &address_space_memory);
|
memory_listener_register(&hvf_memory_listener, &address_space_memory);
|
||||||
|
|
||||||
return hvf_arch_init();
|
return hvf_arch_init();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int hvf_gdbstub_sstep_flags(void)
|
||||||
|
{
|
||||||
|
return SSTEP_ENABLE | SSTEP_NOIRQ;
|
||||||
|
}
|
||||||
|
|
||||||
static void hvf_accel_class_init(ObjectClass *oc, void *data)
|
static void hvf_accel_class_init(ObjectClass *oc, void *data)
|
||||||
{
|
{
|
||||||
AccelClass *ac = ACCEL_CLASS(oc);
|
AccelClass *ac = ACCEL_CLASS(oc);
|
||||||
ac->name = "HVF";
|
ac->name = "HVF";
|
||||||
ac->init_machine = hvf_accel_init;
|
ac->init_machine = hvf_accel_init;
|
||||||
ac->allowed = &hvf_allowed;
|
ac->allowed = &hvf_allowed;
|
||||||
|
ac->gdbstub_supported_sstep_flags = hvf_gdbstub_sstep_flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const TypeInfo hvf_accel_type = {
|
static const TypeInfo hvf_accel_type = {
|
||||||
@ -395,6 +404,8 @@ static int hvf_init_vcpu(CPUState *cpu)
|
|||||||
cpu->vcpu_dirty = 1;
|
cpu->vcpu_dirty = 1;
|
||||||
assert_hvf_ok(r);
|
assert_hvf_ok(r);
|
||||||
|
|
||||||
|
cpu->hvf->guest_debug_enabled = false;
|
||||||
|
|
||||||
return hvf_arch_init_vcpu(cpu);
|
return hvf_arch_init_vcpu(cpu);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -462,6 +473,108 @@ static void hvf_start_vcpu_thread(CPUState *cpu)
|
|||||||
cpu, QEMU_THREAD_JOINABLE);
|
cpu, QEMU_THREAD_JOINABLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int hvf_insert_breakpoint(CPUState *cpu, int type, hwaddr addr, hwaddr len)
|
||||||
|
{
|
||||||
|
struct hvf_sw_breakpoint *bp;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
if (type == GDB_BREAKPOINT_SW) {
|
||||||
|
bp = hvf_find_sw_breakpoint(cpu, addr);
|
||||||
|
if (bp) {
|
||||||
|
bp->use_count++;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bp = g_new(struct hvf_sw_breakpoint, 1);
|
||||||
|
bp->pc = addr;
|
||||||
|
bp->use_count = 1;
|
||||||
|
err = hvf_arch_insert_sw_breakpoint(cpu, bp);
|
||||||
|
if (err) {
|
||||||
|
g_free(bp);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
QTAILQ_INSERT_HEAD(&hvf_state->hvf_sw_breakpoints, bp, entry);
|
||||||
|
} else {
|
||||||
|
err = hvf_arch_insert_hw_breakpoint(addr, len, type);
|
||||||
|
if (err) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CPU_FOREACH(cpu) {
|
||||||
|
err = hvf_update_guest_debug(cpu);
|
||||||
|
if (err) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int hvf_remove_breakpoint(CPUState *cpu, int type, hwaddr addr, hwaddr len)
|
||||||
|
{
|
||||||
|
struct hvf_sw_breakpoint *bp;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
if (type == GDB_BREAKPOINT_SW) {
|
||||||
|
bp = hvf_find_sw_breakpoint(cpu, addr);
|
||||||
|
if (!bp) {
|
||||||
|
return -ENOENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bp->use_count > 1) {
|
||||||
|
bp->use_count--;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = hvf_arch_remove_sw_breakpoint(cpu, bp);
|
||||||
|
if (err) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
QTAILQ_REMOVE(&hvf_state->hvf_sw_breakpoints, bp, entry);
|
||||||
|
g_free(bp);
|
||||||
|
} else {
|
||||||
|
err = hvf_arch_remove_hw_breakpoint(addr, len, type);
|
||||||
|
if (err) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CPU_FOREACH(cpu) {
|
||||||
|
err = hvf_update_guest_debug(cpu);
|
||||||
|
if (err) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void hvf_remove_all_breakpoints(CPUState *cpu)
|
||||||
|
{
|
||||||
|
struct hvf_sw_breakpoint *bp, *next;
|
||||||
|
CPUState *tmpcpu;
|
||||||
|
|
||||||
|
QTAILQ_FOREACH_SAFE(bp, &hvf_state->hvf_sw_breakpoints, entry, next) {
|
||||||
|
if (hvf_arch_remove_sw_breakpoint(cpu, bp) != 0) {
|
||||||
|
/* Try harder to find a CPU that currently sees the breakpoint. */
|
||||||
|
CPU_FOREACH(tmpcpu)
|
||||||
|
{
|
||||||
|
if (hvf_arch_remove_sw_breakpoint(tmpcpu, bp) == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
QTAILQ_REMOVE(&hvf_state->hvf_sw_breakpoints, bp, entry);
|
||||||
|
g_free(bp);
|
||||||
|
}
|
||||||
|
hvf_arch_remove_all_hw_breakpoints();
|
||||||
|
|
||||||
|
CPU_FOREACH(cpu) {
|
||||||
|
hvf_update_guest_debug(cpu);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void hvf_accel_ops_class_init(ObjectClass *oc, void *data)
|
static void hvf_accel_ops_class_init(ObjectClass *oc, void *data)
|
||||||
{
|
{
|
||||||
AccelOpsClass *ops = ACCEL_OPS_CLASS(oc);
|
AccelOpsClass *ops = ACCEL_OPS_CLASS(oc);
|
||||||
@ -473,6 +586,12 @@ static void hvf_accel_ops_class_init(ObjectClass *oc, void *data)
|
|||||||
ops->synchronize_post_init = hvf_cpu_synchronize_post_init;
|
ops->synchronize_post_init = hvf_cpu_synchronize_post_init;
|
||||||
ops->synchronize_state = hvf_cpu_synchronize_state;
|
ops->synchronize_state = hvf_cpu_synchronize_state;
|
||||||
ops->synchronize_pre_loadvm = hvf_cpu_synchronize_pre_loadvm;
|
ops->synchronize_pre_loadvm = hvf_cpu_synchronize_pre_loadvm;
|
||||||
|
|
||||||
|
ops->insert_breakpoint = hvf_insert_breakpoint;
|
||||||
|
ops->remove_breakpoint = hvf_remove_breakpoint;
|
||||||
|
ops->remove_all_breakpoints = hvf_remove_all_breakpoints;
|
||||||
|
ops->update_guest_debug = hvf_update_guest_debug;
|
||||||
|
ops->supports_guest_debug = hvf_arch_supports_guest_debug;
|
||||||
};
|
};
|
||||||
static const TypeInfo hvf_accel_ops_type = {
|
static const TypeInfo hvf_accel_ops_type = {
|
||||||
.name = ACCEL_OPS_NAME("hvf"),
|
.name = ACCEL_OPS_NAME("hvf"),
|
||||||
|
@ -38,9 +38,38 @@ void assert_hvf_ok(hv_return_t ret)
|
|||||||
case HV_UNSUPPORTED:
|
case HV_UNSUPPORTED:
|
||||||
error_report("Error: HV_UNSUPPORTED");
|
error_report("Error: HV_UNSUPPORTED");
|
||||||
break;
|
break;
|
||||||
|
#if defined(MAC_OS_VERSION_11_0) && \
|
||||||
|
MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_VERSION_11_0
|
||||||
|
case HV_DENIED:
|
||||||
|
error_report("Error: HV_DENIED");
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
default:
|
default:
|
||||||
error_report("Unknown Error");
|
error_report("Unknown Error");
|
||||||
}
|
}
|
||||||
|
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct hvf_sw_breakpoint *hvf_find_sw_breakpoint(CPUState *cpu, target_ulong pc)
|
||||||
|
{
|
||||||
|
struct hvf_sw_breakpoint *bp;
|
||||||
|
|
||||||
|
QTAILQ_FOREACH(bp, &hvf_state->hvf_sw_breakpoints, entry) {
|
||||||
|
if (bp->pc == pc) {
|
||||||
|
return bp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int hvf_sw_breakpoints_active(CPUState *cpu)
|
||||||
|
{
|
||||||
|
return !QTAILQ_EMPTY(&hvf_state->hvf_sw_breakpoints);
|
||||||
|
}
|
||||||
|
|
||||||
|
int hvf_update_guest_debug(CPUState *cpu)
|
||||||
|
{
|
||||||
|
hvf_arch_update_guest_debug(cpu);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
specific_ss.add(files('accel-common.c', 'accel-blocker.c'))
|
specific_ss.add(files('accel-common.c', 'accel-blocker.c'))
|
||||||
softmmu_ss.add(files('accel-softmmu.c'))
|
system_ss.add(files('accel-softmmu.c'))
|
||||||
user_ss.add(files('accel-user.c'))
|
user_ss.add(files('accel-user.c'))
|
||||||
|
|
||||||
subdir('tcg')
|
subdir('tcg')
|
||||||
@ -12,4 +12,4 @@ if have_system
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
# qtest
|
# qtest
|
||||||
softmmu_ss.add(files('dummy-cpus.c'))
|
system_ss.add(files('dummy-cpus.c'))
|
||||||
|
@ -1 +1 @@
|
|||||||
qtest_module_ss.add(when: ['CONFIG_SOFTMMU'], if_true: files('qtest.c'))
|
qtest_module_ss.add(when: ['CONFIG_SYSTEM_ONLY'], if_true: files('qtest.c'))
|
||||||
|
@ -4,4 +4,4 @@ sysemu_stubs_ss.add(when: 'CONFIG_XEN', if_false: files('xen-stub.c'))
|
|||||||
sysemu_stubs_ss.add(when: 'CONFIG_KVM', if_false: files('kvm-stub.c'))
|
sysemu_stubs_ss.add(when: 'CONFIG_KVM', if_false: files('kvm-stub.c'))
|
||||||
sysemu_stubs_ss.add(when: 'CONFIG_TCG', if_false: files('tcg-stub.c'))
|
sysemu_stubs_ss.add(when: 'CONFIG_TCG', if_false: files('tcg-stub.c'))
|
||||||
|
|
||||||
specific_ss.add_all(when: ['CONFIG_SOFTMMU'], if_true: sysemu_stubs_ss)
|
specific_ss.add_all(when: ['CONFIG_SYSTEM_ONLY'], if_true: sysemu_stubs_ss)
|
||||||
|
@ -38,7 +38,7 @@
|
|||||||
#include "sysemu/cpu-timers.h"
|
#include "sysemu/cpu-timers.h"
|
||||||
#include "exec/replay-core.h"
|
#include "exec/replay-core.h"
|
||||||
#include "sysemu/tcg.h"
|
#include "sysemu/tcg.h"
|
||||||
#include "exec/helper-proto.h"
|
#include "exec/helper-proto-common.h"
|
||||||
#include "tb-jmp-cache.h"
|
#include "tb-jmp-cache.h"
|
||||||
#include "tb-hash.h"
|
#include "tb-hash.h"
|
||||||
#include "tb-context.h"
|
#include "tb-context.h"
|
||||||
@ -297,7 +297,7 @@ static void log_cpu_exec(target_ulong pc, CPUState *cpu,
|
|||||||
{
|
{
|
||||||
if (qemu_log_in_addr_range(pc)) {
|
if (qemu_log_in_addr_range(pc)) {
|
||||||
qemu_log_mask(CPU_LOG_EXEC,
|
qemu_log_mask(CPU_LOG_EXEC,
|
||||||
"Trace %d: %p [" TARGET_FMT_lx
|
"Trace %d: %p [%08" PRIx64
|
||||||
"/" TARGET_FMT_lx "/%08x/%08x] %s\n",
|
"/" TARGET_FMT_lx "/%08x/%08x] %s\n",
|
||||||
cpu->cpu_index, tb->tc.ptr, tb->cs_base, pc,
|
cpu->cpu_index, tb->tc.ptr, tb->cs_base, pc,
|
||||||
tb->flags, tb->cflags, lookup_symbol(pc));
|
tb->flags, tb->cflags, lookup_symbol(pc));
|
||||||
@ -313,6 +313,9 @@ static void log_cpu_exec(target_ulong pc, CPUState *cpu,
|
|||||||
#if defined(TARGET_I386)
|
#if defined(TARGET_I386)
|
||||||
flags |= CPU_DUMP_CCOP;
|
flags |= CPU_DUMP_CCOP;
|
||||||
#endif
|
#endif
|
||||||
|
if (qemu_loglevel_mask(CPU_LOG_TB_VPU)) {
|
||||||
|
flags |= CPU_DUMP_VPU;
|
||||||
|
}
|
||||||
cpu_dump_state(cpu, logfile, flags);
|
cpu_dump_state(cpu, logfile, flags);
|
||||||
qemu_log_unlock(logfile);
|
qemu_log_unlock(logfile);
|
||||||
}
|
}
|
||||||
@ -563,7 +566,7 @@ void cpu_exec_step_atomic(CPUState *cpu)
|
|||||||
cpu_tb_exec(cpu, tb, &tb_exit);
|
cpu_tb_exec(cpu, tb, &tb_exit);
|
||||||
cpu_exec_exit(cpu);
|
cpu_exec_exit(cpu);
|
||||||
} else {
|
} else {
|
||||||
#ifndef CONFIG_SOFTMMU
|
#ifdef CONFIG_USER_ONLY
|
||||||
clear_helper_retaddr();
|
clear_helper_retaddr();
|
||||||
if (have_mmap_lock()) {
|
if (have_mmap_lock()) {
|
||||||
mmap_unlock();
|
mmap_unlock();
|
||||||
@ -794,7 +797,7 @@ static inline bool cpu_handle_interrupt(CPUState *cpu,
|
|||||||
* Ensure zeroing happens before reading cpu->exit_request or
|
* Ensure zeroing happens before reading cpu->exit_request or
|
||||||
* cpu->interrupt_request (see also smp_wmb in cpu_exit())
|
* cpu->interrupt_request (see also smp_wmb in cpu_exit())
|
||||||
*/
|
*/
|
||||||
qatomic_mb_set(&cpu_neg(cpu)->icount_decr.u16.high, 0);
|
qatomic_set_mb(&cpu_neg(cpu)->icount_decr.u16.high, 0);
|
||||||
|
|
||||||
if (unlikely(qatomic_read(&cpu->interrupt_request))) {
|
if (unlikely(qatomic_read(&cpu->interrupt_request))) {
|
||||||
int interrupt_request;
|
int interrupt_request;
|
||||||
@ -1080,7 +1083,7 @@ static int cpu_exec_setjmp(CPUState *cpu, SyncClocks *sc)
|
|||||||
/* Non-buggy compilers preserve this; assert the correct value. */
|
/* Non-buggy compilers preserve this; assert the correct value. */
|
||||||
g_assert(cpu == current_cpu);
|
g_assert(cpu == current_cpu);
|
||||||
|
|
||||||
#ifndef CONFIG_SOFTMMU
|
#ifdef CONFIG_USER_ONLY
|
||||||
clear_helper_retaddr();
|
clear_helper_retaddr();
|
||||||
if (have_mmap_lock()) {
|
if (have_mmap_lock()) {
|
||||||
mmap_unlock();
|
mmap_unlock();
|
||||||
|
@ -29,7 +29,7 @@
|
|||||||
#include "tcg/tcg.h"
|
#include "tcg/tcg.h"
|
||||||
#include "qemu/error-report.h"
|
#include "qemu/error-report.h"
|
||||||
#include "exec/log.h"
|
#include "exec/log.h"
|
||||||
#include "exec/helper-proto.h"
|
#include "exec/helper-proto-common.h"
|
||||||
#include "qemu/atomic.h"
|
#include "qemu/atomic.h"
|
||||||
#include "qemu/atomic128.h"
|
#include "qemu/atomic128.h"
|
||||||
#include "exec/translate-all.h"
|
#include "exec/translate-all.h"
|
||||||
@ -40,7 +40,7 @@
|
|||||||
#include "qemu/plugin-memory.h"
|
#include "qemu/plugin-memory.h"
|
||||||
#endif
|
#endif
|
||||||
#include "tcg/tcg-ldst.h"
|
#include "tcg/tcg-ldst.h"
|
||||||
#include "exec/helper-proto.h"
|
#include "tcg/oversized-guest.h"
|
||||||
|
|
||||||
/* DEBUG defines, enable DEBUG_TLB_LOG to log to the CPU_LOG_MMU target */
|
/* DEBUG defines, enable DEBUG_TLB_LOG to log to the CPU_LOG_MMU target */
|
||||||
/* #define DEBUG_TLB */
|
/* #define DEBUG_TLB */
|
||||||
@ -1007,11 +1007,15 @@ static void tlb_reset_dirty_range_locked(CPUTLBEntry *tlb_entry,
|
|||||||
addr &= TARGET_PAGE_MASK;
|
addr &= TARGET_PAGE_MASK;
|
||||||
addr += tlb_entry->addend;
|
addr += tlb_entry->addend;
|
||||||
if ((addr - start) < length) {
|
if ((addr - start) < length) {
|
||||||
#if TCG_OVERSIZED_GUEST
|
#if TARGET_LONG_BITS == 32
|
||||||
|
uint32_t *ptr_write = (uint32_t *)&tlb_entry->addr_write;
|
||||||
|
ptr_write += HOST_BIG_ENDIAN;
|
||||||
|
qatomic_set(ptr_write, *ptr_write | TLB_NOTDIRTY);
|
||||||
|
#elif TCG_OVERSIZED_GUEST
|
||||||
tlb_entry->addr_write |= TLB_NOTDIRTY;
|
tlb_entry->addr_write |= TLB_NOTDIRTY;
|
||||||
#else
|
#else
|
||||||
qatomic_set(&tlb_entry->addr_write,
|
qatomic_set(&tlb_entry->addr_write,
|
||||||
tlb_entry->addr_write | TLB_NOTDIRTY);
|
tlb_entry->addr_write | TLB_NOTDIRTY);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2755,6 +2759,7 @@ static uint64_t do_st16_leN(CPUArchState *env, MMULookupPageData *p,
|
|||||||
* and so neither is atomic.
|
* and so neither is atomic.
|
||||||
*/
|
*/
|
||||||
case MO_ATOM_IFALIGN:
|
case MO_ATOM_IFALIGN:
|
||||||
|
case MO_ATOM_WITHIN16:
|
||||||
case MO_ATOM_NONE:
|
case MO_ATOM_NONE:
|
||||||
stq_le_p(p->haddr, int128_getlo(val_le));
|
stq_le_p(p->haddr, int128_getlo(val_le));
|
||||||
return store_bytes_leN(p->haddr + 8, p->size - 8,
|
return store_bytes_leN(p->haddr + 8, p->size - 8,
|
||||||
|
@ -17,10 +17,10 @@
|
|||||||
* memory related structures are protected with mmap_lock.
|
* memory related structures are protected with mmap_lock.
|
||||||
* In !user-mode we use per-page locks.
|
* In !user-mode we use per-page locks.
|
||||||
*/
|
*/
|
||||||
#ifdef CONFIG_SOFTMMU
|
#ifdef CONFIG_USER_ONLY
|
||||||
#define assert_memory_lock()
|
|
||||||
#else
|
|
||||||
#define assert_memory_lock() tcg_debug_assert(have_mmap_lock())
|
#define assert_memory_lock() tcg_debug_assert(have_mmap_lock())
|
||||||
|
#else
|
||||||
|
#define assert_memory_lock()
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(CONFIG_SOFTMMU) && defined(CONFIG_DEBUG_TCG)
|
#if defined(CONFIG_SOFTMMU) && defined(CONFIG_DEBUG_TCG)
|
||||||
|
@ -833,7 +833,9 @@ static uint64_t store_whole_le16(void *pv, int size, Int128 val_le)
|
|||||||
}
|
}
|
||||||
store_atom_insert_al16(pv - o, v, m);
|
store_atom_insert_al16(pv - o, v, m);
|
||||||
|
|
||||||
/* Unused if sz <= 64. */
|
if (sz <= 64) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
return int128_gethi(val_le) >> (sz - 64);
|
return int128_gethi(val_le) >> (sz - 64);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,18 +10,18 @@ tcg_ss.add(files(
|
|||||||
'translator.c',
|
'translator.c',
|
||||||
))
|
))
|
||||||
tcg_ss.add(when: 'CONFIG_USER_ONLY', if_true: files('user-exec.c'))
|
tcg_ss.add(when: 'CONFIG_USER_ONLY', if_true: files('user-exec.c'))
|
||||||
tcg_ss.add(when: 'CONFIG_SOFTMMU', if_false: files('user-exec-stub.c'))
|
tcg_ss.add(when: 'CONFIG_SYSTEM_ONLY', if_false: files('user-exec-stub.c'))
|
||||||
tcg_ss.add(when: 'CONFIG_PLUGIN', if_true: [files('plugin-gen.c')])
|
tcg_ss.add(when: 'CONFIG_PLUGIN', if_true: [files('plugin-gen.c')])
|
||||||
tcg_ss.add(when: libdw, if_true: files('debuginfo.c'))
|
tcg_ss.add(when: libdw, if_true: files('debuginfo.c'))
|
||||||
tcg_ss.add(when: 'CONFIG_LINUX', if_true: files('perf.c'))
|
tcg_ss.add(when: 'CONFIG_LINUX', if_true: files('perf.c'))
|
||||||
specific_ss.add_all(when: 'CONFIG_TCG', if_true: tcg_ss)
|
specific_ss.add_all(when: 'CONFIG_TCG', if_true: tcg_ss)
|
||||||
|
|
||||||
specific_ss.add(when: ['CONFIG_SOFTMMU', 'CONFIG_TCG'], if_true: files(
|
specific_ss.add(when: ['CONFIG_SYSTEM_ONLY', 'CONFIG_TCG'], if_true: files(
|
||||||
'cputlb.c',
|
'cputlb.c',
|
||||||
'monitor.c',
|
'monitor.c',
|
||||||
))
|
))
|
||||||
|
|
||||||
tcg_module_ss.add(when: ['CONFIG_SOFTMMU', 'CONFIG_TCG'], if_true: files(
|
tcg_module_ss.add(when: ['CONFIG_SYSTEM_ONLY', 'CONFIG_TCG'], if_true: files(
|
||||||
'tcg-accel-ops.c',
|
'tcg-accel-ops.c',
|
||||||
'tcg-accel-ops-mttcg.c',
|
'tcg-accel-ops-mttcg.c',
|
||||||
'tcg-accel-ops-icount.c',
|
'tcg-accel-ops-icount.c',
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
#include "sysemu/cpus.h"
|
#include "sysemu/cpus.h"
|
||||||
#include "sysemu/cpu-timers.h"
|
#include "sysemu/cpu-timers.h"
|
||||||
#include "sysemu/tcg.h"
|
#include "sysemu/tcg.h"
|
||||||
|
#include "tcg/tcg.h"
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
|
|
||||||
|
|
||||||
|
@ -111,6 +111,8 @@ static void write_perfmap_entry(const void *start, size_t insn,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static FILE *jitdump;
|
static FILE *jitdump;
|
||||||
|
static size_t perf_marker_size;
|
||||||
|
static void *perf_marker = MAP_FAILED;
|
||||||
|
|
||||||
#define JITHEADER_MAGIC 0x4A695444
|
#define JITHEADER_MAGIC 0x4A695444
|
||||||
#define JITHEADER_VERSION 1
|
#define JITHEADER_VERSION 1
|
||||||
@ -190,7 +192,6 @@ void perf_enable_jitdump(void)
|
|||||||
{
|
{
|
||||||
struct jitheader header;
|
struct jitheader header;
|
||||||
char jitdump_file[32];
|
char jitdump_file[32];
|
||||||
void *perf_marker;
|
|
||||||
|
|
||||||
if (!use_rt_clock) {
|
if (!use_rt_clock) {
|
||||||
warn_report("CLOCK_MONOTONIC is not available, proceeding without jitdump");
|
warn_report("CLOCK_MONOTONIC is not available, proceeding without jitdump");
|
||||||
@ -210,7 +211,8 @@ void perf_enable_jitdump(void)
|
|||||||
* PERF_RECORD_MMAP or PERF_RECORD_MMAP2 event is of the form jit-%d.dump
|
* PERF_RECORD_MMAP or PERF_RECORD_MMAP2 event is of the form jit-%d.dump
|
||||||
* and will process it as a jitdump file.
|
* and will process it as a jitdump file.
|
||||||
*/
|
*/
|
||||||
perf_marker = mmap(NULL, qemu_real_host_page_size(), PROT_READ | PROT_EXEC,
|
perf_marker_size = qemu_real_host_page_size();
|
||||||
|
perf_marker = mmap(NULL, perf_marker_size, PROT_READ | PROT_EXEC,
|
||||||
MAP_PRIVATE, fileno(jitdump), 0);
|
MAP_PRIVATE, fileno(jitdump), 0);
|
||||||
if (perf_marker == MAP_FAILED) {
|
if (perf_marker == MAP_FAILED) {
|
||||||
warn_report("Could not map %s: %s, proceeding without jitdump",
|
warn_report("Could not map %s: %s, proceeding without jitdump",
|
||||||
@ -311,7 +313,8 @@ void perf_report_code(uint64_t guest_pc, TranslationBlock *tb,
|
|||||||
const void *start)
|
const void *start)
|
||||||
{
|
{
|
||||||
struct debuginfo_query *q;
|
struct debuginfo_query *q;
|
||||||
size_t insn;
|
size_t insn, start_words;
|
||||||
|
uint64_t *gen_insn_data;
|
||||||
|
|
||||||
if (!perfmap && !jitdump) {
|
if (!perfmap && !jitdump) {
|
||||||
return;
|
return;
|
||||||
@ -325,9 +328,12 @@ void perf_report_code(uint64_t guest_pc, TranslationBlock *tb,
|
|||||||
debuginfo_lock();
|
debuginfo_lock();
|
||||||
|
|
||||||
/* Query debuginfo for each guest instruction. */
|
/* Query debuginfo for each guest instruction. */
|
||||||
|
gen_insn_data = tcg_ctx->gen_insn_data;
|
||||||
|
start_words = tcg_ctx->insn_start_words;
|
||||||
|
|
||||||
for (insn = 0; insn < tb->icount; insn++) {
|
for (insn = 0; insn < tb->icount; insn++) {
|
||||||
/* FIXME: This replicates the restore_state_to_opc() logic. */
|
/* FIXME: This replicates the restore_state_to_opc() logic. */
|
||||||
q[insn].address = tcg_ctx->gen_insn_data[insn][0];
|
q[insn].address = gen_insn_data[insn * start_words + 0];
|
||||||
if (tb_cflags(tb) & CF_PCREL) {
|
if (tb_cflags(tb) & CF_PCREL) {
|
||||||
q[insn].address |= (guest_pc & TARGET_PAGE_MASK);
|
q[insn].address |= (guest_pc & TARGET_PAGE_MASK);
|
||||||
} else {
|
} else {
|
||||||
@ -368,6 +374,11 @@ void perf_exit(void)
|
|||||||
perfmap = NULL;
|
perfmap = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (perf_marker != MAP_FAILED) {
|
||||||
|
munmap(perf_marker, perf_marker_size);
|
||||||
|
perf_marker = MAP_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
if (jitdump) {
|
if (jitdump) {
|
||||||
fclose(jitdump);
|
fclose(jitdump);
|
||||||
jitdump = NULL;
|
jitdump = NULL;
|
||||||
|
@ -43,12 +43,18 @@
|
|||||||
* CPU's index into a TCG temp, since the first callback did it already.
|
* CPU's index into a TCG temp, since the first callback did it already.
|
||||||
*/
|
*/
|
||||||
#include "qemu/osdep.h"
|
#include "qemu/osdep.h"
|
||||||
|
#include "cpu.h"
|
||||||
#include "tcg/tcg.h"
|
#include "tcg/tcg.h"
|
||||||
#include "tcg/tcg-temp-internal.h"
|
#include "tcg/tcg-temp-internal.h"
|
||||||
#include "tcg/tcg-op.h"
|
#include "tcg/tcg-op.h"
|
||||||
#include "exec/exec-all.h"
|
#include "exec/exec-all.h"
|
||||||
#include "exec/plugin-gen.h"
|
#include "exec/plugin-gen.h"
|
||||||
#include "exec/translator.h"
|
#include "exec/translator.h"
|
||||||
|
#include "exec/helper-proto-common.h"
|
||||||
|
|
||||||
|
#define HELPER_H "accel/tcg/plugin-helpers.h"
|
||||||
|
#include "exec/helper-info.c.inc"
|
||||||
|
#undef HELPER_H
|
||||||
|
|
||||||
#ifdef CONFIG_SOFTMMU
|
#ifdef CONFIG_SOFTMMU
|
||||||
# define CONFIG_SOFTMMU_GATE 1
|
# define CONFIG_SOFTMMU_GATE 1
|
||||||
|
@ -32,7 +32,7 @@
|
|||||||
#include "qemu/guest-random.h"
|
#include "qemu/guest-random.h"
|
||||||
#include "exec/exec-all.h"
|
#include "exec/exec-all.h"
|
||||||
#include "hw/boards.h"
|
#include "hw/boards.h"
|
||||||
|
#include "tcg/tcg.h"
|
||||||
#include "tcg-accel-ops.h"
|
#include "tcg-accel-ops.h"
|
||||||
#include "tcg-accel-ops-mttcg.h"
|
#include "tcg-accel-ops-mttcg.h"
|
||||||
|
|
||||||
@ -119,7 +119,7 @@ static void *mttcg_cpu_thread_fn(void *arg)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
qatomic_mb_set(&cpu->exit_request, 0);
|
qatomic_set_mb(&cpu->exit_request, 0);
|
||||||
qemu_wait_io_event(cpu);
|
qemu_wait_io_event(cpu);
|
||||||
} while (!cpu->unplug || cpu_can_run(cpu));
|
} while (!cpu->unplug || cpu_can_run(cpu));
|
||||||
|
|
||||||
|
@ -32,7 +32,7 @@
|
|||||||
#include "qemu/notify.h"
|
#include "qemu/notify.h"
|
||||||
#include "qemu/guest-random.h"
|
#include "qemu/guest-random.h"
|
||||||
#include "exec/exec-all.h"
|
#include "exec/exec-all.h"
|
||||||
|
#include "tcg/tcg.h"
|
||||||
#include "tcg-accel-ops.h"
|
#include "tcg-accel-ops.h"
|
||||||
#include "tcg-accel-ops-rr.h"
|
#include "tcg-accel-ops-rr.h"
|
||||||
#include "tcg-accel-ops-icount.h"
|
#include "tcg-accel-ops-icount.h"
|
||||||
@ -244,7 +244,7 @@ static void *rr_cpu_thread_fn(void *arg)
|
|||||||
|
|
||||||
while (cpu && cpu_work_list_empty(cpu) && !cpu->exit_request) {
|
while (cpu && cpu_work_list_empty(cpu) && !cpu->exit_request) {
|
||||||
/* Store rr_current_cpu before evaluating cpu_can_run(). */
|
/* Store rr_current_cpu before evaluating cpu_can_run(). */
|
||||||
qatomic_mb_set(&rr_current_cpu, cpu);
|
qatomic_set_mb(&rr_current_cpu, cpu);
|
||||||
|
|
||||||
current_cpu = cpu;
|
current_cpu = cpu;
|
||||||
|
|
||||||
@ -287,7 +287,7 @@ static void *rr_cpu_thread_fn(void *arg)
|
|||||||
qatomic_set(&rr_current_cpu, NULL);
|
qatomic_set(&rr_current_cpu, NULL);
|
||||||
|
|
||||||
if (cpu && cpu->exit_request) {
|
if (cpu && cpu->exit_request) {
|
||||||
qatomic_mb_set(&cpu->exit_request, 0);
|
qatomic_set_mb(&cpu->exit_request, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (icount_enabled() && all_cpu_threads_idle()) {
|
if (icount_enabled() && all_cpu_threads_idle()) {
|
||||||
|
@ -28,6 +28,7 @@
|
|||||||
#include "exec/replay-core.h"
|
#include "exec/replay-core.h"
|
||||||
#include "sysemu/cpu-timers.h"
|
#include "sysemu/cpu-timers.h"
|
||||||
#include "tcg/tcg.h"
|
#include "tcg/tcg.h"
|
||||||
|
#include "tcg/oversized-guest.h"
|
||||||
#include "qapi/error.h"
|
#include "qapi/error.h"
|
||||||
#include "qemu/error-report.h"
|
#include "qemu/error-report.h"
|
||||||
#include "qemu/accel.h"
|
#include "qemu/accel.h"
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
#include "qemu/osdep.h"
|
#include "qemu/osdep.h"
|
||||||
#include "qemu/host-utils.h"
|
#include "qemu/host-utils.h"
|
||||||
#include "cpu.h"
|
#include "cpu.h"
|
||||||
#include "exec/helper-proto.h"
|
#include "exec/helper-proto-common.h"
|
||||||
#include "tcg/tcg-gvec-desc.h"
|
#include "tcg/tcg-gvec-desc.h"
|
||||||
|
|
||||||
|
|
||||||
|
@ -24,13 +24,17 @@
|
|||||||
#include "qemu/osdep.h"
|
#include "qemu/osdep.h"
|
||||||
#include "qemu/host-utils.h"
|
#include "qemu/host-utils.h"
|
||||||
#include "cpu.h"
|
#include "cpu.h"
|
||||||
#include "exec/helper-proto.h"
|
#include "exec/helper-proto-common.h"
|
||||||
#include "exec/cpu_ldst.h"
|
#include "exec/cpu_ldst.h"
|
||||||
#include "exec/exec-all.h"
|
#include "exec/exec-all.h"
|
||||||
#include "disas/disas.h"
|
#include "disas/disas.h"
|
||||||
#include "exec/log.h"
|
#include "exec/log.h"
|
||||||
#include "tcg/tcg.h"
|
#include "tcg/tcg.h"
|
||||||
|
|
||||||
|
#define HELPER_H "accel/tcg/tcg-runtime.h"
|
||||||
|
#include "exec/helper-info.c.inc"
|
||||||
|
#undef HELPER_H
|
||||||
|
|
||||||
//// --- Begin LibAFL code ---
|
//// --- Begin LibAFL code ---
|
||||||
|
|
||||||
#ifndef CONFIG_USER_ONLY
|
#ifndef CONFIG_USER_ONLY
|
||||||
|
@ -19,7 +19,6 @@
|
|||||||
|
|
||||||
#include "qemu/osdep.h"
|
#include "qemu/osdep.h"
|
||||||
|
|
||||||
#define NO_CPU_IO_DEFS
|
|
||||||
#include "trace.h"
|
#include "trace.h"
|
||||||
#include "disas/disas.h"
|
#include "disas/disas.h"
|
||||||
#include "exec/exec-all.h"
|
#include "exec/exec-all.h"
|
||||||
@ -64,6 +63,7 @@
|
|||||||
#include "tb-context.h"
|
#include "tb-context.h"
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
#include "perf.h"
|
#include "perf.h"
|
||||||
|
#include "tcg/insn-start-words.h"
|
||||||
|
|
||||||
//// --- Begin LibAFL code ---
|
//// --- Begin LibAFL code ---
|
||||||
|
|
||||||
@ -719,22 +719,26 @@ static int64_t decode_sleb128(const uint8_t **pp)
|
|||||||
static int encode_search(TranslationBlock *tb, uint8_t *block)
|
static int encode_search(TranslationBlock *tb, uint8_t *block)
|
||||||
{
|
{
|
||||||
uint8_t *highwater = tcg_ctx->code_gen_highwater;
|
uint8_t *highwater = tcg_ctx->code_gen_highwater;
|
||||||
|
uint64_t *insn_data = tcg_ctx->gen_insn_data;
|
||||||
|
uint16_t *insn_end_off = tcg_ctx->gen_insn_end_off;
|
||||||
uint8_t *p = block;
|
uint8_t *p = block;
|
||||||
int i, j, n;
|
int i, j, n;
|
||||||
|
|
||||||
for (i = 0, n = tb->icount; i < n; ++i) {
|
for (i = 0, n = tb->icount; i < n; ++i) {
|
||||||
uint64_t prev;
|
uint64_t prev, curr;
|
||||||
|
|
||||||
for (j = 0; j < TARGET_INSN_START_WORDS; ++j) {
|
for (j = 0; j < TARGET_INSN_START_WORDS; ++j) {
|
||||||
if (i == 0) {
|
if (i == 0) {
|
||||||
prev = (!(tb_cflags(tb) & CF_PCREL) && j == 0 ? tb->pc : 0);
|
prev = (!(tb_cflags(tb) & CF_PCREL) && j == 0 ? tb->pc : 0);
|
||||||
} else {
|
} else {
|
||||||
prev = tcg_ctx->gen_insn_data[i - 1][j];
|
prev = insn_data[(i - 1) * TARGET_INSN_START_WORDS + j];
|
||||||
}
|
}
|
||||||
p = encode_sleb128(p, tcg_ctx->gen_insn_data[i][j] - prev);
|
curr = insn_data[i * TARGET_INSN_START_WORDS + j];
|
||||||
|
p = encode_sleb128(p, curr - prev);
|
||||||
}
|
}
|
||||||
prev = (i == 0 ? 0 : tcg_ctx->gen_insn_end_off[i - 1]);
|
prev = (i == 0 ? 0 : insn_end_off[i - 1]);
|
||||||
p = encode_sleb128(p, tcg_ctx->gen_insn_end_off[i] - prev);
|
curr = insn_end_off[i];
|
||||||
|
p = encode_sleb128(p, curr - prev);
|
||||||
|
|
||||||
/* Test for (pending) buffer overflow. The assumption is that any
|
/* Test for (pending) buffer overflow. The assumption is that any
|
||||||
one row beginning below the high water mark cannot overrun
|
one row beginning below the high water mark cannot overrun
|
||||||
@ -1145,11 +1149,19 @@ TranslationBlock *tb_gen_code(CPUState *cpu,
|
|||||||
tb_set_page_addr0(tb, phys_pc);
|
tb_set_page_addr0(tb, phys_pc);
|
||||||
tb_set_page_addr1(tb, -1);
|
tb_set_page_addr1(tb, -1);
|
||||||
tcg_ctx->gen_tb = tb;
|
tcg_ctx->gen_tb = tb;
|
||||||
tcg_ctx->addr_type = TCG_TYPE_TL;
|
tcg_ctx->addr_type = TARGET_LONG_BITS == 32 ? TCG_TYPE_I32 : TCG_TYPE_I64;
|
||||||
#ifdef CONFIG_SOFTMMU
|
#ifdef CONFIG_SOFTMMU
|
||||||
tcg_ctx->page_bits = TARGET_PAGE_BITS;
|
tcg_ctx->page_bits = TARGET_PAGE_BITS;
|
||||||
tcg_ctx->page_mask = TARGET_PAGE_MASK;
|
tcg_ctx->page_mask = TARGET_PAGE_MASK;
|
||||||
tcg_ctx->tlb_dyn_max_bits = CPU_TLB_DYN_MAX_BITS;
|
tcg_ctx->tlb_dyn_max_bits = CPU_TLB_DYN_MAX_BITS;
|
||||||
|
tcg_ctx->tlb_fast_offset =
|
||||||
|
(int)offsetof(ArchCPU, neg.tlb.f) - (int)offsetof(ArchCPU, env);
|
||||||
|
#endif
|
||||||
|
tcg_ctx->insn_start_words = TARGET_INSN_START_WORDS;
|
||||||
|
#ifdef TCG_GUEST_DEFAULT_MO
|
||||||
|
tcg_ctx->guest_mo = TCG_GUEST_DEFAULT_MO;
|
||||||
|
#else
|
||||||
|
tcg_ctx->guest_mo = TCG_MO_ALL;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
tb_overflow:
|
tb_overflow:
|
||||||
@ -1252,7 +1264,7 @@ TranslationBlock *tb_gen_code(CPUState *cpu,
|
|||||||
fprintf(logfile, "OUT: [size=%d]\n", gen_code_size);
|
fprintf(logfile, "OUT: [size=%d]\n", gen_code_size);
|
||||||
fprintf(logfile,
|
fprintf(logfile,
|
||||||
" -- guest addr 0x%016" PRIx64 " + tb prologue\n",
|
" -- guest addr 0x%016" PRIx64 " + tb prologue\n",
|
||||||
tcg_ctx->gen_insn_data[insn][0]);
|
tcg_ctx->gen_insn_data[insn * TARGET_INSN_START_WORDS]);
|
||||||
chunk_start = tcg_ctx->gen_insn_end_off[insn];
|
chunk_start = tcg_ctx->gen_insn_end_off[insn];
|
||||||
disas(logfile, tb->tc.ptr, chunk_start);
|
disas(logfile, tb->tc.ptr, chunk_start);
|
||||||
|
|
||||||
@ -1265,7 +1277,7 @@ TranslationBlock *tb_gen_code(CPUState *cpu,
|
|||||||
size_t chunk_end = tcg_ctx->gen_insn_end_off[insn];
|
size_t chunk_end = tcg_ctx->gen_insn_end_off[insn];
|
||||||
if (chunk_end > chunk_start) {
|
if (chunk_end > chunk_start) {
|
||||||
fprintf(logfile, " -- guest addr 0x%016" PRIx64 "\n",
|
fprintf(logfile, " -- guest addr 0x%016" PRIx64 "\n",
|
||||||
tcg_ctx->gen_insn_data[insn][0]);
|
tcg_ctx->gen_insn_data[insn * TARGET_INSN_START_WORDS]);
|
||||||
disas(logfile, tb->tc.ptr + chunk_start,
|
disas(logfile, tb->tc.ptr + chunk_start,
|
||||||
chunk_end - chunk_start);
|
chunk_end - chunk_start);
|
||||||
chunk_start = chunk_end;
|
chunk_start = chunk_end;
|
||||||
|
@ -8,15 +8,114 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "qemu/osdep.h"
|
#include "qemu/osdep.h"
|
||||||
|
#include "qemu/log.h"
|
||||||
#include "qemu/error-report.h"
|
#include "qemu/error-report.h"
|
||||||
#include "tcg/tcg.h"
|
|
||||||
#include "tcg/tcg-op.h"
|
|
||||||
#include "exec/exec-all.h"
|
#include "exec/exec-all.h"
|
||||||
#include "exec/gen-icount.h"
|
|
||||||
#include "exec/log.h"
|
|
||||||
#include "exec/translator.h"
|
#include "exec/translator.h"
|
||||||
|
#include "exec/translate-all.h"
|
||||||
#include "exec/plugin-gen.h"
|
#include "exec/plugin-gen.h"
|
||||||
#include "exec/replay-core.h"
|
#include "tcg/tcg-op-common.h"
|
||||||
|
|
||||||
|
static void gen_io_start(void)
|
||||||
|
{
|
||||||
|
tcg_gen_st_i32(tcg_constant_i32(1), cpu_env,
|
||||||
|
offsetof(ArchCPU, parent_obj.can_do_io) -
|
||||||
|
offsetof(ArchCPU, env));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool translator_io_start(DisasContextBase *db)
|
||||||
|
{
|
||||||
|
uint32_t cflags = tb_cflags(db->tb);
|
||||||
|
|
||||||
|
if (!(cflags & CF_USE_ICOUNT)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (db->num_insns == db->max_insns && (cflags & CF_LAST_IO)) {
|
||||||
|
/* Already started in translator_loop. */
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
gen_io_start();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Ensure that this instruction will be the last in the TB.
|
||||||
|
* The target may override this to something more forceful.
|
||||||
|
*/
|
||||||
|
if (db->is_jmp == DISAS_NEXT) {
|
||||||
|
db->is_jmp = DISAS_TOO_MANY;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static TCGOp *gen_tb_start(uint32_t cflags)
|
||||||
|
{
|
||||||
|
TCGv_i32 count = tcg_temp_new_i32();
|
||||||
|
TCGOp *icount_start_insn = NULL;
|
||||||
|
|
||||||
|
tcg_gen_ld_i32(count, cpu_env,
|
||||||
|
offsetof(ArchCPU, neg.icount_decr.u32) -
|
||||||
|
offsetof(ArchCPU, env));
|
||||||
|
|
||||||
|
if (cflags & CF_USE_ICOUNT) {
|
||||||
|
/*
|
||||||
|
* We emit a sub with a dummy immediate argument. Keep the insn index
|
||||||
|
* of the sub so that we later (when we know the actual insn count)
|
||||||
|
* can update the argument with the actual insn count.
|
||||||
|
*/
|
||||||
|
tcg_gen_sub_i32(count, count, tcg_constant_i32(0));
|
||||||
|
icount_start_insn = tcg_last_op();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Emit the check against icount_decr.u32 to see if we should exit
|
||||||
|
* unless we suppress the check with CF_NOIRQ. If we are using
|
||||||
|
* icount and have suppressed interruption the higher level code
|
||||||
|
* should have ensured we don't run more instructions than the
|
||||||
|
* budget.
|
||||||
|
*/
|
||||||
|
if (cflags & CF_NOIRQ) {
|
||||||
|
tcg_ctx->exitreq_label = NULL;
|
||||||
|
} else {
|
||||||
|
tcg_ctx->exitreq_label = gen_new_label();
|
||||||
|
tcg_gen_brcondi_i32(TCG_COND_LT, count, 0, tcg_ctx->exitreq_label);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cflags & CF_USE_ICOUNT) {
|
||||||
|
tcg_gen_st16_i32(count, cpu_env,
|
||||||
|
offsetof(ArchCPU, neg.icount_decr.u16.low) -
|
||||||
|
offsetof(ArchCPU, env));
|
||||||
|
/*
|
||||||
|
* cpu->can_do_io is cleared automatically here at the beginning of
|
||||||
|
* each translation block. The cost is minimal and only paid for
|
||||||
|
* -icount, plus it would be very easy to forget doing it in the
|
||||||
|
* translator. Doing it here means we don't need a gen_io_end() to
|
||||||
|
* go with gen_io_start().
|
||||||
|
*/
|
||||||
|
tcg_gen_st_i32(tcg_constant_i32(0), cpu_env,
|
||||||
|
offsetof(ArchCPU, parent_obj.can_do_io) -
|
||||||
|
offsetof(ArchCPU, env));
|
||||||
|
}
|
||||||
|
|
||||||
|
return icount_start_insn;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void gen_tb_end(const TranslationBlock *tb, uint32_t cflags,
|
||||||
|
TCGOp *icount_start_insn, int num_insns)
|
||||||
|
{
|
||||||
|
if (cflags & CF_USE_ICOUNT) {
|
||||||
|
/*
|
||||||
|
* Update the num_insn immediate parameter now that we know
|
||||||
|
* the actual insn count.
|
||||||
|
*/
|
||||||
|
tcg_set_insn_param(icount_start_insn, 2,
|
||||||
|
tcgv_i32_arg(tcg_constant_i32(num_insns)));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tcg_ctx->exitreq_label) {
|
||||||
|
gen_set_label(tcg_ctx->exitreq_label);
|
||||||
|
tcg_gen_exit_tb(tb, TB_EXIT_REQUESTED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//// --- Begin LibAFL code ---
|
//// --- Begin LibAFL code ---
|
||||||
|
|
||||||
@ -94,6 +193,7 @@ void translator_loop(CPUState *cpu, TranslationBlock *tb, int *max_insns,
|
|||||||
const TranslatorOps *ops, DisasContextBase *db)
|
const TranslatorOps *ops, DisasContextBase *db)
|
||||||
{
|
{
|
||||||
uint32_t cflags = tb_cflags(tb);
|
uint32_t cflags = tb_cflags(tb);
|
||||||
|
TCGOp *icount_start_insn;
|
||||||
bool plugin_enabled;
|
bool plugin_enabled;
|
||||||
|
|
||||||
/* Initialize DisasContext */
|
/* Initialize DisasContext */
|
||||||
@ -115,7 +215,7 @@ void translator_loop(CPUState *cpu, TranslationBlock *tb, int *max_insns,
|
|||||||
tcg_debug_assert(db->is_jmp == DISAS_NEXT); /* no early exit */
|
tcg_debug_assert(db->is_jmp == DISAS_NEXT); /* no early exit */
|
||||||
|
|
||||||
/* Start translating. */
|
/* Start translating. */
|
||||||
gen_tb_start(db->tb);
|
icount_start_insn = gen_tb_start(cflags);
|
||||||
ops->tb_start(db, cpu);
|
ops->tb_start(db, cpu);
|
||||||
tcg_debug_assert(db->is_jmp == DISAS_NEXT); /* no early exit */
|
tcg_debug_assert(db->is_jmp == DISAS_NEXT); /* no early exit */
|
||||||
|
|
||||||
@ -246,7 +346,7 @@ post_translate_insn:
|
|||||||
|
|
||||||
/* Emit code to exit the TB, as indicated by db->is_jmp. */
|
/* Emit code to exit the TB, as indicated by db->is_jmp. */
|
||||||
ops->tb_stop(db, cpu);
|
ops->tb_stop(db, cpu);
|
||||||
gen_tb_end(db->tb, db->num_insns);
|
gen_tb_end(tb, cflags, icount_start_insn, db->num_insns);
|
||||||
|
|
||||||
if (plugin_enabled) {
|
if (plugin_enabled) {
|
||||||
plugin_gen_tb_end(cpu);
|
plugin_gen_tb_end(cpu);
|
||||||
@ -319,6 +419,27 @@ static void *translator_access(CPUArchState *env, DisasContextBase *db,
|
|||||||
return host + (pc - base);
|
return host + (pc - base);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void plugin_insn_append(abi_ptr pc, const void *from, size_t size)
|
||||||
|
{
|
||||||
|
#ifdef CONFIG_PLUGIN
|
||||||
|
struct qemu_plugin_insn *insn = tcg_ctx->plugin_insn;
|
||||||
|
abi_ptr off;
|
||||||
|
|
||||||
|
if (insn == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
off = pc - insn->vaddr;
|
||||||
|
if (off < insn->data->len) {
|
||||||
|
g_byte_array_set_size(insn->data, off);
|
||||||
|
} else if (off > insn->data->len) {
|
||||||
|
/* we have an unexpected gap */
|
||||||
|
g_assert_not_reached();
|
||||||
|
}
|
||||||
|
|
||||||
|
insn->data = g_byte_array_append(insn->data, from, size);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
uint8_t translator_ldub(CPUArchState *env, DisasContextBase *db, abi_ptr pc)
|
uint8_t translator_ldub(CPUArchState *env, DisasContextBase *db, abi_ptr pc)
|
||||||
{
|
{
|
||||||
uint8_t ret;
|
uint8_t ret;
|
||||||
@ -377,3 +498,8 @@ uint64_t translator_ldq(CPUArchState *env, DisasContextBase *db, abi_ptr pc)
|
|||||||
plugin_insn_append(pc, &plug, sizeof(ret));
|
plugin_insn_append(pc, &plug, sizeof(ret));
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void translator_fake_ldb(uint8_t insn8, abi_ptr pc)
|
||||||
|
{
|
||||||
|
plugin_insn_append(pc, &insn8, sizeof(insn8));
|
||||||
|
}
|
||||||
|
@ -35,8 +35,8 @@
|
|||||||
|
|
||||||
static uint32_t toui32(const char *str)
|
static uint32_t toui32(const char *str)
|
||||||
{
|
{
|
||||||
unsigned long long ret;
|
uint64_t ret;
|
||||||
if (parse_uint_full(str, &ret, 10) || ret > UINT32_MAX) {
|
if (parse_uint_full(str, 10, &ret) || ret > UINT32_MAX) {
|
||||||
dolog("Invalid integer value `%s'\n", str);
|
dolog("Invalid integer value `%s'\n", str);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
softmmu_ss.add([spice_headers, files('audio.c')])
|
system_ss.add([spice_headers, files('audio.c')])
|
||||||
softmmu_ss.add(files(
|
system_ss.add(files(
|
||||||
'audio-hmp-cmds.c',
|
'audio-hmp-cmds.c',
|
||||||
'audio_legacy.c',
|
'audio_legacy.c',
|
||||||
'mixeng.c',
|
'mixeng.c',
|
||||||
@ -8,8 +8,8 @@ softmmu_ss.add(files(
|
|||||||
'wavcapture.c',
|
'wavcapture.c',
|
||||||
))
|
))
|
||||||
|
|
||||||
softmmu_ss.add(when: coreaudio, if_true: files('coreaudio.m'))
|
system_ss.add(when: coreaudio, if_true: files('coreaudio.m'))
|
||||||
softmmu_ss.add(when: dsound, if_true: files('dsoundaudio.c', 'audio_win_int.c'))
|
system_ss.add(when: dsound, if_true: files('dsoundaudio.c', 'audio_win_int.c'))
|
||||||
|
|
||||||
audio_modules = {}
|
audio_modules = {}
|
||||||
foreach m : [
|
foreach m : [
|
||||||
|
@ -57,6 +57,7 @@ file_backend_memory_alloc(HostMemoryBackend *backend, Error **errp)
|
|||||||
ram_flags = backend->share ? RAM_SHARED : 0;
|
ram_flags = backend->share ? RAM_SHARED : 0;
|
||||||
ram_flags |= backend->reserve ? 0 : RAM_NORESERVE;
|
ram_flags |= backend->reserve ? 0 : RAM_NORESERVE;
|
||||||
ram_flags |= fb->is_pmem ? RAM_PMEM : 0;
|
ram_flags |= fb->is_pmem ? RAM_PMEM : 0;
|
||||||
|
ram_flags |= RAM_NAMED_FILE;
|
||||||
memory_region_init_ram_from_file(&backend->mr, OBJECT(backend), name,
|
memory_region_init_ram_from_file(&backend->mr, OBJECT(backend), name,
|
||||||
backend->size, fb->align, ram_flags,
|
backend->size, fb->align, ram_flags,
|
||||||
fb->mem_path, fb->offset, fb->readonly,
|
fb->mem_path, fb->offset, fb->readonly,
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
softmmu_ss.add([files(
|
system_ss.add([files(
|
||||||
'cryptodev-builtin.c',
|
'cryptodev-builtin.c',
|
||||||
'cryptodev-hmp-cmds.c',
|
'cryptodev-hmp-cmds.c',
|
||||||
'cryptodev.c',
|
'cryptodev.c',
|
||||||
@ -10,20 +10,20 @@ softmmu_ss.add([files(
|
|||||||
'confidential-guest-support.c',
|
'confidential-guest-support.c',
|
||||||
), numa])
|
), numa])
|
||||||
|
|
||||||
softmmu_ss.add(when: 'CONFIG_POSIX', if_true: files('rng-random.c'))
|
system_ss.add(when: 'CONFIG_POSIX', if_true: files('rng-random.c'))
|
||||||
softmmu_ss.add(when: 'CONFIG_POSIX', if_true: files('hostmem-file.c'))
|
system_ss.add(when: 'CONFIG_POSIX', if_true: files('hostmem-file.c'))
|
||||||
softmmu_ss.add(when: 'CONFIG_LINUX', if_true: files('hostmem-memfd.c'))
|
system_ss.add(when: 'CONFIG_LINUX', if_true: files('hostmem-memfd.c'))
|
||||||
if keyutils.found()
|
if keyutils.found()
|
||||||
softmmu_ss.add(keyutils, files('cryptodev-lkcf.c'))
|
system_ss.add(keyutils, files('cryptodev-lkcf.c'))
|
||||||
endif
|
endif
|
||||||
if have_vhost_user
|
if have_vhost_user
|
||||||
softmmu_ss.add(when: 'CONFIG_VIRTIO', if_true: files('vhost-user.c'))
|
system_ss.add(when: 'CONFIG_VIRTIO', if_true: files('vhost-user.c'))
|
||||||
endif
|
endif
|
||||||
softmmu_ss.add(when: 'CONFIG_VIRTIO_CRYPTO', if_true: files('cryptodev-vhost.c'))
|
system_ss.add(when: 'CONFIG_VIRTIO_CRYPTO', if_true: files('cryptodev-vhost.c'))
|
||||||
if have_vhost_user_crypto
|
if have_vhost_user_crypto
|
||||||
softmmu_ss.add(when: 'CONFIG_VIRTIO_CRYPTO', if_true: files('cryptodev-vhost-user.c'))
|
system_ss.add(when: 'CONFIG_VIRTIO_CRYPTO', if_true: files('cryptodev-vhost-user.c'))
|
||||||
endif
|
endif
|
||||||
softmmu_ss.add(when: gio, if_true: files('dbus-vmstate.c'))
|
system_ss.add(when: gio, if_true: files('dbus-vmstate.c'))
|
||||||
softmmu_ss.add(when: 'CONFIG_SGX', if_true: files('hostmem-epc.c'))
|
system_ss.add(when: 'CONFIG_SGX', if_true: files('hostmem-epc.c'))
|
||||||
|
|
||||||
subdir('tpm')
|
subdir('tpm')
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
if have_tpm
|
if have_tpm
|
||||||
softmmu_ss.add(files('tpm_backend.c'))
|
system_ss.add(files('tpm_backend.c'))
|
||||||
softmmu_ss.add(files('tpm_util.c'))
|
system_ss.add(files('tpm_util.c'))
|
||||||
softmmu_ss.add(when: 'CONFIG_TPM_PASSTHROUGH', if_true: files('tpm_passthrough.c'))
|
system_ss.add(when: 'CONFIG_TPM_PASSTHROUGH', if_true: files('tpm_passthrough.c'))
|
||||||
softmmu_ss.add(when: 'CONFIG_TPM_EMULATOR', if_true: files('tpm_emulator.c'))
|
system_ss.add(when: 'CONFIG_TPM_EMULATOR', if_true: files('tpm_emulator.c'))
|
||||||
endif
|
endif
|
||||||
|
2
block.c
2
block.c
@ -7158,7 +7158,7 @@ void bdrv_img_create(const char *filename, const char *fmt,
|
|||||||
if (!backing_fmt) {
|
if (!backing_fmt) {
|
||||||
error_setg(&local_err,
|
error_setg(&local_err,
|
||||||
"Backing file specified without backing format");
|
"Backing file specified without backing format");
|
||||||
error_append_hint(&local_err, "Detected format of %s.",
|
error_append_hint(&local_err, "Detected format of %s.\n",
|
||||||
bs->drv->format_name);
|
bs->drv->format_name);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
@ -424,7 +424,7 @@ static struct glfs *qemu_gluster_glfs_init(BlockdevOptionsGluster *gconf,
|
|||||||
int ret;
|
int ret;
|
||||||
int old_errno;
|
int old_errno;
|
||||||
SocketAddressList *server;
|
SocketAddressList *server;
|
||||||
unsigned long long port;
|
uint64_t port;
|
||||||
|
|
||||||
glfs = glfs_find_preopened(gconf->volume);
|
glfs = glfs_find_preopened(gconf->volume);
|
||||||
if (glfs) {
|
if (glfs) {
|
||||||
@ -445,7 +445,7 @@ static struct glfs *qemu_gluster_glfs_init(BlockdevOptionsGluster *gconf,
|
|||||||
server->value->u.q_unix.path, 0);
|
server->value->u.q_unix.path, 0);
|
||||||
break;
|
break;
|
||||||
case SOCKET_ADDRESS_TYPE_INET:
|
case SOCKET_ADDRESS_TYPE_INET:
|
||||||
if (parse_uint_full(server->value->u.inet.port, &port, 10) < 0 ||
|
if (parse_uint_full(server->value->u.inet.port, 10, &port) < 0 ||
|
||||||
port > 65535) {
|
port > 65535) {
|
||||||
error_setg(errp, "'%s' is not a valid port number",
|
error_setg(errp, "'%s' is not a valid port number",
|
||||||
server->value->u.inet.port);
|
server->value->u.inet.port);
|
||||||
|
166
block/io.c
166
block/io.c
@ -1441,6 +1441,14 @@ out:
|
|||||||
* @merge_reads is true for small requests,
|
* @merge_reads is true for small requests,
|
||||||
* if @buf_len == @head + bytes + @tail. In this case it is possible that both
|
* if @buf_len == @head + bytes + @tail. In this case it is possible that both
|
||||||
* head and tail exist but @buf_len == align and @tail_buf == @buf.
|
* head and tail exist but @buf_len == align and @tail_buf == @buf.
|
||||||
|
*
|
||||||
|
* @write is true for write requests, false for read requests.
|
||||||
|
*
|
||||||
|
* If padding makes the vector too long (exceeding IOV_MAX), then we need to
|
||||||
|
* merge existing vector elements into a single one. @collapse_bounce_buf acts
|
||||||
|
* as the bounce buffer in such cases. @pre_collapse_qiov has the pre-collapse
|
||||||
|
* I/O vector elements so for read requests, the data can be copied back after
|
||||||
|
* the read is done.
|
||||||
*/
|
*/
|
||||||
typedef struct BdrvRequestPadding {
|
typedef struct BdrvRequestPadding {
|
||||||
uint8_t *buf;
|
uint8_t *buf;
|
||||||
@ -1449,11 +1457,17 @@ typedef struct BdrvRequestPadding {
|
|||||||
size_t head;
|
size_t head;
|
||||||
size_t tail;
|
size_t tail;
|
||||||
bool merge_reads;
|
bool merge_reads;
|
||||||
|
bool write;
|
||||||
QEMUIOVector local_qiov;
|
QEMUIOVector local_qiov;
|
||||||
|
|
||||||
|
uint8_t *collapse_bounce_buf;
|
||||||
|
size_t collapse_len;
|
||||||
|
QEMUIOVector pre_collapse_qiov;
|
||||||
} BdrvRequestPadding;
|
} BdrvRequestPadding;
|
||||||
|
|
||||||
static bool bdrv_init_padding(BlockDriverState *bs,
|
static bool bdrv_init_padding(BlockDriverState *bs,
|
||||||
int64_t offset, int64_t bytes,
|
int64_t offset, int64_t bytes,
|
||||||
|
bool write,
|
||||||
BdrvRequestPadding *pad)
|
BdrvRequestPadding *pad)
|
||||||
{
|
{
|
||||||
int64_t align = bs->bl.request_alignment;
|
int64_t align = bs->bl.request_alignment;
|
||||||
@ -1485,6 +1499,8 @@ static bool bdrv_init_padding(BlockDriverState *bs,
|
|||||||
pad->tail_buf = pad->buf + pad->buf_len - align;
|
pad->tail_buf = pad->buf + pad->buf_len - align;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pad->write = write;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1549,8 +1565,23 @@ zero_mem:
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void bdrv_padding_destroy(BdrvRequestPadding *pad)
|
/**
|
||||||
|
* Free *pad's associated buffers, and perform any necessary finalization steps.
|
||||||
|
*/
|
||||||
|
static void bdrv_padding_finalize(BdrvRequestPadding *pad)
|
||||||
{
|
{
|
||||||
|
if (pad->collapse_bounce_buf) {
|
||||||
|
if (!pad->write) {
|
||||||
|
/*
|
||||||
|
* If padding required elements in the vector to be collapsed into a
|
||||||
|
* bounce buffer, copy the bounce buffer content back
|
||||||
|
*/
|
||||||
|
qemu_iovec_from_buf(&pad->pre_collapse_qiov, 0,
|
||||||
|
pad->collapse_bounce_buf, pad->collapse_len);
|
||||||
|
}
|
||||||
|
qemu_vfree(pad->collapse_bounce_buf);
|
||||||
|
qemu_iovec_destroy(&pad->pre_collapse_qiov);
|
||||||
|
}
|
||||||
if (pad->buf) {
|
if (pad->buf) {
|
||||||
qemu_vfree(pad->buf);
|
qemu_vfree(pad->buf);
|
||||||
qemu_iovec_destroy(&pad->local_qiov);
|
qemu_iovec_destroy(&pad->local_qiov);
|
||||||
@ -1558,6 +1589,101 @@ static void bdrv_padding_destroy(BdrvRequestPadding *pad)
|
|||||||
memset(pad, 0, sizeof(*pad));
|
memset(pad, 0, sizeof(*pad));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create pad->local_qiov by wrapping @iov in the padding head and tail, while
|
||||||
|
* ensuring that the resulting vector will not exceed IOV_MAX elements.
|
||||||
|
*
|
||||||
|
* To ensure this, when necessary, the first two or three elements of @iov are
|
||||||
|
* merged into pad->collapse_bounce_buf and replaced by a reference to that
|
||||||
|
* bounce buffer in pad->local_qiov.
|
||||||
|
*
|
||||||
|
* After performing a read request, the data from the bounce buffer must be
|
||||||
|
* copied back into pad->pre_collapse_qiov (e.g. by bdrv_padding_finalize()).
|
||||||
|
*/
|
||||||
|
static int bdrv_create_padded_qiov(BlockDriverState *bs,
|
||||||
|
BdrvRequestPadding *pad,
|
||||||
|
struct iovec *iov, int niov,
|
||||||
|
size_t iov_offset, size_t bytes)
|
||||||
|
{
|
||||||
|
int padded_niov, surplus_count, collapse_count;
|
||||||
|
|
||||||
|
/* Assert this invariant */
|
||||||
|
assert(niov <= IOV_MAX);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Cannot pad if resulting length would exceed SIZE_MAX. Returning an error
|
||||||
|
* to the guest is not ideal, but there is little else we can do. At least
|
||||||
|
* this will practically never happen on 64-bit systems.
|
||||||
|
*/
|
||||||
|
if (SIZE_MAX - pad->head < bytes ||
|
||||||
|
SIZE_MAX - pad->head - bytes < pad->tail)
|
||||||
|
{
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Length of the resulting IOV if we just concatenated everything */
|
||||||
|
padded_niov = !!pad->head + niov + !!pad->tail;
|
||||||
|
|
||||||
|
qemu_iovec_init(&pad->local_qiov, MIN(padded_niov, IOV_MAX));
|
||||||
|
|
||||||
|
if (pad->head) {
|
||||||
|
qemu_iovec_add(&pad->local_qiov, pad->buf, pad->head);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If padded_niov > IOV_MAX, we cannot just concatenate everything.
|
||||||
|
* Instead, merge the first two or three elements of @iov to reduce the
|
||||||
|
* number of vector elements as necessary.
|
||||||
|
*/
|
||||||
|
if (padded_niov > IOV_MAX) {
|
||||||
|
/*
|
||||||
|
* Only head and tail can have lead to the number of entries exceeding
|
||||||
|
* IOV_MAX, so we can exceed it by the head and tail at most. We need
|
||||||
|
* to reduce the number of elements by `surplus_count`, so we merge that
|
||||||
|
* many elements plus one into one element.
|
||||||
|
*/
|
||||||
|
surplus_count = padded_niov - IOV_MAX;
|
||||||
|
assert(surplus_count <= !!pad->head + !!pad->tail);
|
||||||
|
collapse_count = surplus_count + 1;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Move the elements to collapse into `pad->pre_collapse_qiov`, then
|
||||||
|
* advance `iov` (and associated variables) by those elements.
|
||||||
|
*/
|
||||||
|
qemu_iovec_init(&pad->pre_collapse_qiov, collapse_count);
|
||||||
|
qemu_iovec_concat_iov(&pad->pre_collapse_qiov, iov,
|
||||||
|
collapse_count, iov_offset, SIZE_MAX);
|
||||||
|
iov += collapse_count;
|
||||||
|
iov_offset = 0;
|
||||||
|
niov -= collapse_count;
|
||||||
|
bytes -= pad->pre_collapse_qiov.size;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Construct the bounce buffer to match the length of the to-collapse
|
||||||
|
* vector elements, and for write requests, initialize it with the data
|
||||||
|
* from those elements. Then add it to `pad->local_qiov`.
|
||||||
|
*/
|
||||||
|
pad->collapse_len = pad->pre_collapse_qiov.size;
|
||||||
|
pad->collapse_bounce_buf = qemu_blockalign(bs, pad->collapse_len);
|
||||||
|
if (pad->write) {
|
||||||
|
qemu_iovec_to_buf(&pad->pre_collapse_qiov, 0,
|
||||||
|
pad->collapse_bounce_buf, pad->collapse_len);
|
||||||
|
}
|
||||||
|
qemu_iovec_add(&pad->local_qiov,
|
||||||
|
pad->collapse_bounce_buf, pad->collapse_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
qemu_iovec_concat_iov(&pad->local_qiov, iov, niov, iov_offset, bytes);
|
||||||
|
|
||||||
|
if (pad->tail) {
|
||||||
|
qemu_iovec_add(&pad->local_qiov,
|
||||||
|
pad->buf + pad->buf_len - pad->tail, pad->tail);
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(pad->local_qiov.niov == MIN(padded_niov, IOV_MAX));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* bdrv_pad_request
|
* bdrv_pad_request
|
||||||
*
|
*
|
||||||
@ -1565,6 +1691,8 @@ static void bdrv_padding_destroy(BdrvRequestPadding *pad)
|
|||||||
* read of padding, bdrv_padding_rmw_read() should be called separately if
|
* read of padding, bdrv_padding_rmw_read() should be called separately if
|
||||||
* needed.
|
* needed.
|
||||||
*
|
*
|
||||||
|
* @write is true for write requests, false for read requests.
|
||||||
|
*
|
||||||
* Request parameters (@qiov, &qiov_offset, &offset, &bytes) are in-out:
|
* Request parameters (@qiov, &qiov_offset, &offset, &bytes) are in-out:
|
||||||
* - on function start they represent original request
|
* - on function start they represent original request
|
||||||
* - on failure or when padding is not needed they are unchanged
|
* - on failure or when padding is not needed they are unchanged
|
||||||
@ -1573,26 +1701,34 @@ static void bdrv_padding_destroy(BdrvRequestPadding *pad)
|
|||||||
static int bdrv_pad_request(BlockDriverState *bs,
|
static int bdrv_pad_request(BlockDriverState *bs,
|
||||||
QEMUIOVector **qiov, size_t *qiov_offset,
|
QEMUIOVector **qiov, size_t *qiov_offset,
|
||||||
int64_t *offset, int64_t *bytes,
|
int64_t *offset, int64_t *bytes,
|
||||||
|
bool write,
|
||||||
BdrvRequestPadding *pad, bool *padded,
|
BdrvRequestPadding *pad, bool *padded,
|
||||||
BdrvRequestFlags *flags)
|
BdrvRequestFlags *flags)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
struct iovec *sliced_iov;
|
||||||
|
int sliced_niov;
|
||||||
|
size_t sliced_head, sliced_tail;
|
||||||
|
|
||||||
bdrv_check_qiov_request(*offset, *bytes, *qiov, *qiov_offset, &error_abort);
|
bdrv_check_qiov_request(*offset, *bytes, *qiov, *qiov_offset, &error_abort);
|
||||||
|
|
||||||
if (!bdrv_init_padding(bs, *offset, *bytes, pad)) {
|
if (!bdrv_init_padding(bs, *offset, *bytes, write, pad)) {
|
||||||
if (padded) {
|
if (padded) {
|
||||||
*padded = false;
|
*padded = false;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = qemu_iovec_init_extended(&pad->local_qiov, pad->buf, pad->head,
|
sliced_iov = qemu_iovec_slice(*qiov, *qiov_offset, *bytes,
|
||||||
*qiov, *qiov_offset, *bytes,
|
&sliced_head, &sliced_tail,
|
||||||
pad->buf + pad->buf_len - pad->tail,
|
&sliced_niov);
|
||||||
pad->tail);
|
|
||||||
|
/* Guaranteed by bdrv_check_qiov_request() */
|
||||||
|
assert(*bytes <= SIZE_MAX);
|
||||||
|
ret = bdrv_create_padded_qiov(bs, pad, sliced_iov, sliced_niov,
|
||||||
|
sliced_head, *bytes);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
bdrv_padding_destroy(pad);
|
bdrv_padding_finalize(pad);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
*bytes += pad->head + pad->tail;
|
*bytes += pad->head + pad->tail;
|
||||||
@ -1659,8 +1795,8 @@ int coroutine_fn bdrv_co_preadv_part(BdrvChild *child,
|
|||||||
flags |= BDRV_REQ_COPY_ON_READ;
|
flags |= BDRV_REQ_COPY_ON_READ;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = bdrv_pad_request(bs, &qiov, &qiov_offset, &offset, &bytes, &pad,
|
ret = bdrv_pad_request(bs, &qiov, &qiov_offset, &offset, &bytes, false,
|
||||||
NULL, &flags);
|
&pad, NULL, &flags);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
@ -1670,7 +1806,7 @@ int coroutine_fn bdrv_co_preadv_part(BdrvChild *child,
|
|||||||
bs->bl.request_alignment,
|
bs->bl.request_alignment,
|
||||||
qiov, qiov_offset, flags);
|
qiov, qiov_offset, flags);
|
||||||
tracked_request_end(&req);
|
tracked_request_end(&req);
|
||||||
bdrv_padding_destroy(&pad);
|
bdrv_padding_finalize(&pad);
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
bdrv_dec_in_flight(bs);
|
bdrv_dec_in_flight(bs);
|
||||||
@ -2002,7 +2138,7 @@ bdrv_co_do_zero_pwritev(BdrvChild *child, int64_t offset, int64_t bytes,
|
|||||||
/* This flag doesn't make sense for padding or zero writes */
|
/* This flag doesn't make sense for padding or zero writes */
|
||||||
flags &= ~BDRV_REQ_REGISTERED_BUF;
|
flags &= ~BDRV_REQ_REGISTERED_BUF;
|
||||||
|
|
||||||
padding = bdrv_init_padding(bs, offset, bytes, &pad);
|
padding = bdrv_init_padding(bs, offset, bytes, true, &pad);
|
||||||
if (padding) {
|
if (padding) {
|
||||||
assert(!(flags & BDRV_REQ_NO_WAIT));
|
assert(!(flags & BDRV_REQ_NO_WAIT));
|
||||||
bdrv_make_request_serialising(req, align);
|
bdrv_make_request_serialising(req, align);
|
||||||
@ -2050,7 +2186,7 @@ bdrv_co_do_zero_pwritev(BdrvChild *child, int64_t offset, int64_t bytes,
|
|||||||
}
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
bdrv_padding_destroy(&pad);
|
bdrv_padding_finalize(&pad);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -2118,8 +2254,8 @@ int coroutine_fn bdrv_co_pwritev_part(BdrvChild *child,
|
|||||||
* bdrv_co_do_zero_pwritev() does aligning by itself, so, we do
|
* bdrv_co_do_zero_pwritev() does aligning by itself, so, we do
|
||||||
* alignment only if there is no ZERO flag.
|
* alignment only if there is no ZERO flag.
|
||||||
*/
|
*/
|
||||||
ret = bdrv_pad_request(bs, &qiov, &qiov_offset, &offset, &bytes, &pad,
|
ret = bdrv_pad_request(bs, &qiov, &qiov_offset, &offset, &bytes, true,
|
||||||
&padded, &flags);
|
&pad, &padded, &flags);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -2149,7 +2285,7 @@ int coroutine_fn bdrv_co_pwritev_part(BdrvChild *child,
|
|||||||
ret = bdrv_aligned_pwritev(child, &req, offset, bytes, align,
|
ret = bdrv_aligned_pwritev(child, &req, offset, bytes, align,
|
||||||
qiov, qiov_offset, flags);
|
qiov, qiov_offset, flags);
|
||||||
|
|
||||||
bdrv_padding_destroy(&pad);
|
bdrv_padding_finalize(&pad);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
tracked_request_end(&req);
|
tracked_request_end(&req);
|
||||||
|
@ -42,8 +42,8 @@ block_ss.add(files(
|
|||||||
'write-threshold.c',
|
'write-threshold.c',
|
||||||
), zstd, zlib, gnutls)
|
), zstd, zlib, gnutls)
|
||||||
|
|
||||||
softmmu_ss.add(when: 'CONFIG_TCG', if_true: files('blkreplay.c'))
|
system_ss.add(when: 'CONFIG_TCG', if_true: files('blkreplay.c'))
|
||||||
softmmu_ss.add(files('block-ram-registrar.c'))
|
system_ss.add(files('block-ram-registrar.c'))
|
||||||
|
|
||||||
if get_option('qcow1').allowed()
|
if get_option('qcow1').allowed()
|
||||||
block_ss.add(files('qcow.c'))
|
block_ss.add(files('qcow.c'))
|
||||||
@ -159,7 +159,7 @@ block_ss.add(block_gen_c)
|
|||||||
|
|
||||||
block_ss.add(files('stream.c'))
|
block_ss.add(files('stream.c'))
|
||||||
|
|
||||||
softmmu_ss.add(files('qapi-sysemu.c'))
|
system_ss.add(files('qapi-sysemu.c'))
|
||||||
|
|
||||||
subdir('export')
|
subdir('export')
|
||||||
subdir('monitor')
|
subdir('monitor')
|
||||||
|
@ -1,2 +1,2 @@
|
|||||||
softmmu_ss.add(files('block-hmp-cmds.c'))
|
system_ss.add(files('block-hmp-cmds.c'))
|
||||||
block_ss.add(files('bitmap-qmp-cmds.c'))
|
block_ss.add(files('bitmap-qmp-cmds.c'))
|
||||||
|
@ -397,7 +397,7 @@ static void coroutine_fn GRAPH_RDLOCK nbd_reconnect_attempt(BDRVNBDState *s)
|
|||||||
|
|
||||||
/* Finalize previous connection if any */
|
/* Finalize previous connection if any */
|
||||||
if (s->ioc) {
|
if (s->ioc) {
|
||||||
qio_channel_detach_aio_context(QIO_CHANNEL(s->ioc));
|
qio_channel_detach_aio_context(s->ioc);
|
||||||
yank_unregister_function(BLOCKDEV_YANK_INSTANCE(s->bs->node_name),
|
yank_unregister_function(BLOCKDEV_YANK_INSTANCE(s->bs->node_name),
|
||||||
nbd_yank, s->bs);
|
nbd_yank, s->bs);
|
||||||
object_unref(OBJECT(s->ioc));
|
object_unref(OBJECT(s->ioc));
|
||||||
@ -1455,7 +1455,7 @@ static void nbd_yank(void *opaque)
|
|||||||
BDRVNBDState *s = (BDRVNBDState *)bs->opaque;
|
BDRVNBDState *s = (BDRVNBDState *)bs->opaque;
|
||||||
|
|
||||||
QEMU_LOCK_GUARD(&s->requests_lock);
|
QEMU_LOCK_GUARD(&s->requests_lock);
|
||||||
qio_channel_shutdown(QIO_CHANNEL(s->ioc), QIO_CHANNEL_SHUTDOWN_BOTH, NULL);
|
qio_channel_shutdown(s->ioc, QIO_CHANNEL_SHUTDOWN_BOTH, NULL);
|
||||||
s->state = NBD_CLIENT_QUIT;
|
s->state = NBD_CLIENT_QUIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,13 +114,13 @@ static int nfs_parse_uri(const char *filename, QDict *options, Error **errp)
|
|||||||
qdict_put_str(options, "path", uri->path);
|
qdict_put_str(options, "path", uri->path);
|
||||||
|
|
||||||
for (i = 0; i < qp->n; i++) {
|
for (i = 0; i < qp->n; i++) {
|
||||||
unsigned long long val;
|
uint64_t val;
|
||||||
if (!qp->p[i].value) {
|
if (!qp->p[i].value) {
|
||||||
error_setg(errp, "Value for NFS parameter expected: %s",
|
error_setg(errp, "Value for NFS parameter expected: %s",
|
||||||
qp->p[i].name);
|
qp->p[i].name);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
if (parse_uint_full(qp->p[i].value, &val, 0)) {
|
if (parse_uint_full(qp->p[i].value, 0, &val)) {
|
||||||
error_setg(errp, "Illegal value for NFS parameter: %s",
|
error_setg(errp, "Illegal value for NFS parameter: %s",
|
||||||
qp->p[i].name);
|
qp->p[i].name);
|
||||||
goto out;
|
goto out;
|
||||||
|
@ -165,6 +165,13 @@ static int64_t block_status(BDRVParallelsState *s, int64_t sector_num,
|
|||||||
return start_off;
|
return start_off;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void parallels_set_bat_entry(BDRVParallelsState *s,
|
||||||
|
uint32_t index, uint32_t offset)
|
||||||
|
{
|
||||||
|
s->bat_bitmap[index] = cpu_to_le32(offset);
|
||||||
|
bitmap_set(s->bat_dirty_bmap, bat_entry_off(index) / s->bat_dirty_block, 1);
|
||||||
|
}
|
||||||
|
|
||||||
static int64_t coroutine_fn GRAPH_RDLOCK
|
static int64_t coroutine_fn GRAPH_RDLOCK
|
||||||
allocate_clusters(BlockDriverState *bs, int64_t sector_num,
|
allocate_clusters(BlockDriverState *bs, int64_t sector_num,
|
||||||
int nb_sectors, int *pnum)
|
int nb_sectors, int *pnum)
|
||||||
@ -251,10 +258,8 @@ allocate_clusters(BlockDriverState *bs, int64_t sector_num,
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < to_allocate; i++) {
|
for (i = 0; i < to_allocate; i++) {
|
||||||
s->bat_bitmap[idx + i] = cpu_to_le32(s->data_end / s->off_multiplier);
|
parallels_set_bat_entry(s, idx + i, s->data_end / s->off_multiplier);
|
||||||
s->data_end += s->tracks;
|
s->data_end += s->tracks;
|
||||||
bitmap_set(s->bat_dirty_bmap,
|
|
||||||
bat_entry_off(idx + i) / s->bat_dirty_block, 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return bat2sect(s, idx) + sector_num % s->tracks;
|
return bat2sect(s, idx) + sector_num % s->tracks;
|
||||||
@ -415,16 +420,33 @@ parallels_co_readv(BlockDriverState *bs, int64_t sector_num, int nb_sectors,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void parallels_check_unclean(BlockDriverState *bs,
|
||||||
static int coroutine_fn GRAPH_RDLOCK
|
BdrvCheckResult *res,
|
||||||
parallels_co_check(BlockDriverState *bs, BdrvCheckResult *res,
|
BdrvCheckMode fix)
|
||||||
BdrvCheckMode fix)
|
{
|
||||||
|
BDRVParallelsState *s = bs->opaque;
|
||||||
|
|
||||||
|
if (!s->header_unclean) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(stderr, "%s image was not closed correctly\n",
|
||||||
|
fix & BDRV_FIX_ERRORS ? "Repairing" : "ERROR");
|
||||||
|
res->corruptions++;
|
||||||
|
if (fix & BDRV_FIX_ERRORS) {
|
||||||
|
/* parallels_close will do the job right */
|
||||||
|
res->corruptions_fixed++;
|
||||||
|
s->header_unclean = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int coroutine_fn GRAPH_RDLOCK
|
||||||
|
parallels_check_outside_image(BlockDriverState *bs, BdrvCheckResult *res,
|
||||||
|
BdrvCheckMode fix)
|
||||||
{
|
{
|
||||||
BDRVParallelsState *s = bs->opaque;
|
BDRVParallelsState *s = bs->opaque;
|
||||||
int64_t size, prev_off, high_off;
|
|
||||||
int ret;
|
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
bool flush_bat = false;
|
int64_t off, high_off, size;
|
||||||
|
|
||||||
size = bdrv_getlength(bs->file->bs);
|
size = bdrv_getlength(bs->file->bs);
|
||||||
if (size < 0) {
|
if (size < 0) {
|
||||||
@ -432,65 +454,48 @@ parallels_co_check(BlockDriverState *bs, BdrvCheckResult *res,
|
|||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
qemu_co_mutex_lock(&s->lock);
|
|
||||||
if (s->header_unclean) {
|
|
||||||
fprintf(stderr, "%s image was not closed correctly\n",
|
|
||||||
fix & BDRV_FIX_ERRORS ? "Repairing" : "ERROR");
|
|
||||||
res->corruptions++;
|
|
||||||
if (fix & BDRV_FIX_ERRORS) {
|
|
||||||
/* parallels_close will do the job right */
|
|
||||||
res->corruptions_fixed++;
|
|
||||||
s->header_unclean = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
res->bfi.total_clusters = s->bat_size;
|
|
||||||
res->bfi.compressed_clusters = 0; /* compression is not supported */
|
|
||||||
|
|
||||||
high_off = 0;
|
high_off = 0;
|
||||||
prev_off = 0;
|
|
||||||
for (i = 0; i < s->bat_size; i++) {
|
for (i = 0; i < s->bat_size; i++) {
|
||||||
int64_t off = bat2sect(s, i) << BDRV_SECTOR_BITS;
|
off = bat2sect(s, i) << BDRV_SECTOR_BITS;
|
||||||
if (off == 0) {
|
if (off + s->cluster_size > size) {
|
||||||
prev_off = 0;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* cluster outside the image */
|
|
||||||
if (off > size) {
|
|
||||||
fprintf(stderr, "%s cluster %u is outside image\n",
|
fprintf(stderr, "%s cluster %u is outside image\n",
|
||||||
fix & BDRV_FIX_ERRORS ? "Repairing" : "ERROR", i);
|
fix & BDRV_FIX_ERRORS ? "Repairing" : "ERROR", i);
|
||||||
res->corruptions++;
|
res->corruptions++;
|
||||||
if (fix & BDRV_FIX_ERRORS) {
|
if (fix & BDRV_FIX_ERRORS) {
|
||||||
prev_off = 0;
|
parallels_set_bat_entry(s, i, 0);
|
||||||
s->bat_bitmap[i] = 0;
|
|
||||||
res->corruptions_fixed++;
|
res->corruptions_fixed++;
|
||||||
flush_bat = true;
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
if (high_off < off) {
|
||||||
res->bfi.allocated_clusters++;
|
|
||||||
if (off > high_off) {
|
|
||||||
high_off = off;
|
high_off = off;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (prev_off != 0 && (prev_off + s->cluster_size) != off) {
|
|
||||||
res->bfi.fragmented_clusters++;
|
|
||||||
}
|
|
||||||
prev_off = off;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = 0;
|
if (high_off == 0) {
|
||||||
if (flush_bat) {
|
res->image_end_offset = s->data_end << BDRV_SECTOR_BITS;
|
||||||
ret = bdrv_co_pwrite_sync(bs->file, 0, s->header_size, s->header, 0);
|
} else {
|
||||||
if (ret < 0) {
|
res->image_end_offset = high_off + s->cluster_size;
|
||||||
res->check_errors++;
|
s->data_end = res->image_end_offset >> BDRV_SECTOR_BITS;
|
||||||
goto out;
|
}
|
||||||
}
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int coroutine_fn GRAPH_RDLOCK
|
||||||
|
parallels_check_leak(BlockDriverState *bs, BdrvCheckResult *res,
|
||||||
|
BdrvCheckMode fix)
|
||||||
|
{
|
||||||
|
BDRVParallelsState *s = bs->opaque;
|
||||||
|
int64_t size;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
size = bdrv_getlength(bs->file->bs);
|
||||||
|
if (size < 0) {
|
||||||
|
res->check_errors++;
|
||||||
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
res->image_end_offset = high_off + s->cluster_size;
|
|
||||||
if (size > res->image_end_offset) {
|
if (size > res->image_end_offset) {
|
||||||
int64_t count;
|
int64_t count;
|
||||||
count = DIV_ROUND_UP(size - res->image_end_offset, s->cluster_size);
|
count = DIV_ROUND_UP(size - res->image_end_offset, s->cluster_size);
|
||||||
@ -510,14 +515,74 @@ parallels_co_check(BlockDriverState *bs, BdrvCheckResult *res,
|
|||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
error_report_err(local_err);
|
error_report_err(local_err);
|
||||||
res->check_errors++;
|
res->check_errors++;
|
||||||
goto out;
|
return ret;
|
||||||
}
|
}
|
||||||
res->leaks_fixed += count;
|
res->leaks_fixed += count;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
out:
|
return 0;
|
||||||
qemu_co_mutex_unlock(&s->lock);
|
}
|
||||||
|
|
||||||
|
static void parallels_collect_statistics(BlockDriverState *bs,
|
||||||
|
BdrvCheckResult *res,
|
||||||
|
BdrvCheckMode fix)
|
||||||
|
{
|
||||||
|
BDRVParallelsState *s = bs->opaque;
|
||||||
|
int64_t off, prev_off;
|
||||||
|
uint32_t i;
|
||||||
|
|
||||||
|
res->bfi.total_clusters = s->bat_size;
|
||||||
|
res->bfi.compressed_clusters = 0; /* compression is not supported */
|
||||||
|
|
||||||
|
prev_off = 0;
|
||||||
|
for (i = 0; i < s->bat_size; i++) {
|
||||||
|
off = bat2sect(s, i) << BDRV_SECTOR_BITS;
|
||||||
|
/*
|
||||||
|
* If BDRV_FIX_ERRORS is not set, out-of-image BAT entries were not
|
||||||
|
* fixed. Skip not allocated and out-of-image BAT entries.
|
||||||
|
*/
|
||||||
|
if (off == 0 || off + s->cluster_size > res->image_end_offset) {
|
||||||
|
prev_off = 0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prev_off != 0 && (prev_off + s->cluster_size) != off) {
|
||||||
|
res->bfi.fragmented_clusters++;
|
||||||
|
}
|
||||||
|
prev_off = off;
|
||||||
|
res->bfi.allocated_clusters++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int coroutine_fn GRAPH_RDLOCK
|
||||||
|
parallels_co_check(BlockDriverState *bs, BdrvCheckResult *res,
|
||||||
|
BdrvCheckMode fix)
|
||||||
|
{
|
||||||
|
BDRVParallelsState *s = bs->opaque;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
WITH_QEMU_LOCK_GUARD(&s->lock) {
|
||||||
|
parallels_check_unclean(bs, res, fix);
|
||||||
|
|
||||||
|
ret = parallels_check_outside_image(bs, res, fix);
|
||||||
|
if (ret < 0) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = parallels_check_leak(bs, res, fix);
|
||||||
|
if (ret < 0) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
parallels_collect_statistics(bs, res, fix);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = bdrv_co_flush(bs);
|
||||||
|
if (ret < 0) {
|
||||||
|
res->check_errors++;
|
||||||
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -733,6 +798,7 @@ static int parallels_open(BlockDriverState *bs, QDict *options, int flags,
|
|||||||
BDRVParallelsState *s = bs->opaque;
|
BDRVParallelsState *s = bs->opaque;
|
||||||
ParallelsHeader ph;
|
ParallelsHeader ph;
|
||||||
int ret, size, i;
|
int ret, size, i;
|
||||||
|
int64_t file_nb_sectors;
|
||||||
QemuOpts *opts = NULL;
|
QemuOpts *opts = NULL;
|
||||||
Error *local_err = NULL;
|
Error *local_err = NULL;
|
||||||
char *buf;
|
char *buf;
|
||||||
@ -742,6 +808,11 @@ static int parallels_open(BlockDriverState *bs, QDict *options, int flags,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
file_nb_sectors = bdrv_nb_sectors(bs->file->bs);
|
||||||
|
if (file_nb_sectors < 0) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
ret = bdrv_pread(bs->file, 0, sizeof(ph), &ph, 0);
|
ret = bdrv_pread(bs->file, 0, sizeof(ph), &ph, 0);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
goto fail;
|
goto fail;
|
||||||
@ -806,6 +877,17 @@ static int parallels_open(BlockDriverState *bs, QDict *options, int flags,
|
|||||||
|
|
||||||
for (i = 0; i < s->bat_size; i++) {
|
for (i = 0; i < s->bat_size; i++) {
|
||||||
int64_t off = bat2sect(s, i);
|
int64_t off = bat2sect(s, i);
|
||||||
|
if (off >= file_nb_sectors) {
|
||||||
|
if (flags & BDRV_O_CHECK) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
error_setg(errp, "parallels: Offset %" PRIi64 " in BAT[%d] entry "
|
||||||
|
"is larger than file size (%" PRIi64 ")",
|
||||||
|
off << BDRV_SECTOR_BITS, i,
|
||||||
|
file_nb_sectors << BDRV_SECTOR_BITS);
|
||||||
|
ret = -EINVAL;
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
if (off >= s->data_end) {
|
if (off >= s->data_end) {
|
||||||
s->data_end = off + s->tracks;
|
s->data_end = off + s->tracks;
|
||||||
}
|
}
|
||||||
|
@ -1925,6 +1925,10 @@ static int discard_in_l2_slice(BlockDriverState *bs, uint64_t offset,
|
|||||||
uint64_t new_l2_bitmap = old_l2_bitmap;
|
uint64_t new_l2_bitmap = old_l2_bitmap;
|
||||||
QCow2ClusterType cluster_type =
|
QCow2ClusterType cluster_type =
|
||||||
qcow2_get_cluster_type(bs, old_l2_entry);
|
qcow2_get_cluster_type(bs, old_l2_entry);
|
||||||
|
bool keep_reference = (cluster_type != QCOW2_CLUSTER_COMPRESSED) &&
|
||||||
|
!full_discard &&
|
||||||
|
(s->discard_no_unref &&
|
||||||
|
type == QCOW2_DISCARD_REQUEST);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If full_discard is true, the cluster should not read back as zeroes,
|
* If full_discard is true, the cluster should not read back as zeroes,
|
||||||
@ -1943,10 +1947,22 @@ static int discard_in_l2_slice(BlockDriverState *bs, uint64_t offset,
|
|||||||
new_l2_entry = new_l2_bitmap = 0;
|
new_l2_entry = new_l2_bitmap = 0;
|
||||||
} else if (bs->backing || qcow2_cluster_is_allocated(cluster_type)) {
|
} else if (bs->backing || qcow2_cluster_is_allocated(cluster_type)) {
|
||||||
if (has_subclusters(s)) {
|
if (has_subclusters(s)) {
|
||||||
new_l2_entry = 0;
|
if (keep_reference) {
|
||||||
|
new_l2_entry = old_l2_entry;
|
||||||
|
} else {
|
||||||
|
new_l2_entry = 0;
|
||||||
|
}
|
||||||
new_l2_bitmap = QCOW_L2_BITMAP_ALL_ZEROES;
|
new_l2_bitmap = QCOW_L2_BITMAP_ALL_ZEROES;
|
||||||
} else {
|
} else {
|
||||||
new_l2_entry = s->qcow_version >= 3 ? QCOW_OFLAG_ZERO : 0;
|
if (s->qcow_version >= 3) {
|
||||||
|
if (keep_reference) {
|
||||||
|
new_l2_entry |= QCOW_OFLAG_ZERO;
|
||||||
|
} else {
|
||||||
|
new_l2_entry = QCOW_OFLAG_ZERO;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
new_l2_entry = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1960,8 +1976,16 @@ static int discard_in_l2_slice(BlockDriverState *bs, uint64_t offset,
|
|||||||
if (has_subclusters(s)) {
|
if (has_subclusters(s)) {
|
||||||
set_l2_bitmap(s, l2_slice, l2_index + i, new_l2_bitmap);
|
set_l2_bitmap(s, l2_slice, l2_index + i, new_l2_bitmap);
|
||||||
}
|
}
|
||||||
/* Then decrease the refcount */
|
if (!keep_reference) {
|
||||||
qcow2_free_any_cluster(bs, old_l2_entry, type);
|
/* Then decrease the refcount */
|
||||||
|
qcow2_free_any_cluster(bs, old_l2_entry, type);
|
||||||
|
} else if (s->discard_passthrough[type] &&
|
||||||
|
(cluster_type == QCOW2_CLUSTER_NORMAL ||
|
||||||
|
cluster_type == QCOW2_CLUSTER_ZERO_ALLOC)) {
|
||||||
|
/* If we keep the reference, pass on the discard still */
|
||||||
|
bdrv_pdiscard(s->data_file, old_l2_entry & L2E_OFFSET_MASK,
|
||||||
|
s->cluster_size);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
qcow2_cache_put(s->l2_table_cache, (void **) &l2_slice);
|
qcow2_cache_put(s->l2_table_cache, (void **) &l2_slice);
|
||||||
|
@ -682,6 +682,7 @@ static const char *const mutable_opts[] = {
|
|||||||
QCOW2_OPT_DISCARD_REQUEST,
|
QCOW2_OPT_DISCARD_REQUEST,
|
||||||
QCOW2_OPT_DISCARD_SNAPSHOT,
|
QCOW2_OPT_DISCARD_SNAPSHOT,
|
||||||
QCOW2_OPT_DISCARD_OTHER,
|
QCOW2_OPT_DISCARD_OTHER,
|
||||||
|
QCOW2_OPT_DISCARD_NO_UNREF,
|
||||||
QCOW2_OPT_OVERLAP,
|
QCOW2_OPT_OVERLAP,
|
||||||
QCOW2_OPT_OVERLAP_TEMPLATE,
|
QCOW2_OPT_OVERLAP_TEMPLATE,
|
||||||
QCOW2_OPT_OVERLAP_MAIN_HEADER,
|
QCOW2_OPT_OVERLAP_MAIN_HEADER,
|
||||||
@ -726,6 +727,11 @@ static QemuOptsList qcow2_runtime_opts = {
|
|||||||
.type = QEMU_OPT_BOOL,
|
.type = QEMU_OPT_BOOL,
|
||||||
.help = "Generate discard requests when other clusters are freed",
|
.help = "Generate discard requests when other clusters are freed",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
.name = QCOW2_OPT_DISCARD_NO_UNREF,
|
||||||
|
.type = QEMU_OPT_BOOL,
|
||||||
|
.help = "Do not unreference discarded clusters",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
.name = QCOW2_OPT_OVERLAP,
|
.name = QCOW2_OPT_OVERLAP,
|
||||||
.type = QEMU_OPT_STRING,
|
.type = QEMU_OPT_STRING,
|
||||||
@ -969,6 +975,7 @@ typedef struct Qcow2ReopenState {
|
|||||||
bool use_lazy_refcounts;
|
bool use_lazy_refcounts;
|
||||||
int overlap_check;
|
int overlap_check;
|
||||||
bool discard_passthrough[QCOW2_DISCARD_MAX];
|
bool discard_passthrough[QCOW2_DISCARD_MAX];
|
||||||
|
bool discard_no_unref;
|
||||||
uint64_t cache_clean_interval;
|
uint64_t cache_clean_interval;
|
||||||
QCryptoBlockOpenOptions *crypto_opts; /* Disk encryption runtime options */
|
QCryptoBlockOpenOptions *crypto_opts; /* Disk encryption runtime options */
|
||||||
} Qcow2ReopenState;
|
} Qcow2ReopenState;
|
||||||
@ -1140,6 +1147,15 @@ static int qcow2_update_options_prepare(BlockDriverState *bs,
|
|||||||
r->discard_passthrough[QCOW2_DISCARD_OTHER] =
|
r->discard_passthrough[QCOW2_DISCARD_OTHER] =
|
||||||
qemu_opt_get_bool(opts, QCOW2_OPT_DISCARD_OTHER, false);
|
qemu_opt_get_bool(opts, QCOW2_OPT_DISCARD_OTHER, false);
|
||||||
|
|
||||||
|
r->discard_no_unref = qemu_opt_get_bool(opts, QCOW2_OPT_DISCARD_NO_UNREF,
|
||||||
|
false);
|
||||||
|
if (r->discard_no_unref && s->qcow_version < 3) {
|
||||||
|
error_setg(errp,
|
||||||
|
"discard-no-unref is only supported since qcow2 version 3");
|
||||||
|
ret = -EINVAL;
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
switch (s->crypt_method_header) {
|
switch (s->crypt_method_header) {
|
||||||
case QCOW_CRYPT_NONE:
|
case QCOW_CRYPT_NONE:
|
||||||
if (encryptfmt) {
|
if (encryptfmt) {
|
||||||
@ -1220,6 +1236,8 @@ static void qcow2_update_options_commit(BlockDriverState *bs,
|
|||||||
s->discard_passthrough[i] = r->discard_passthrough[i];
|
s->discard_passthrough[i] = r->discard_passthrough[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
s->discard_no_unref = r->discard_no_unref;
|
||||||
|
|
||||||
if (s->cache_clean_interval != r->cache_clean_interval) {
|
if (s->cache_clean_interval != r->cache_clean_interval) {
|
||||||
cache_clean_timer_del(bs);
|
cache_clean_timer_del(bs);
|
||||||
s->cache_clean_interval = r->cache_clean_interval;
|
s->cache_clean_interval = r->cache_clean_interval;
|
||||||
|
@ -133,6 +133,7 @@
|
|||||||
#define QCOW2_OPT_DISCARD_REQUEST "pass-discard-request"
|
#define QCOW2_OPT_DISCARD_REQUEST "pass-discard-request"
|
||||||
#define QCOW2_OPT_DISCARD_SNAPSHOT "pass-discard-snapshot"
|
#define QCOW2_OPT_DISCARD_SNAPSHOT "pass-discard-snapshot"
|
||||||
#define QCOW2_OPT_DISCARD_OTHER "pass-discard-other"
|
#define QCOW2_OPT_DISCARD_OTHER "pass-discard-other"
|
||||||
|
#define QCOW2_OPT_DISCARD_NO_UNREF "discard-no-unref"
|
||||||
#define QCOW2_OPT_OVERLAP "overlap-check"
|
#define QCOW2_OPT_OVERLAP "overlap-check"
|
||||||
#define QCOW2_OPT_OVERLAP_TEMPLATE "overlap-check.template"
|
#define QCOW2_OPT_OVERLAP_TEMPLATE "overlap-check.template"
|
||||||
#define QCOW2_OPT_OVERLAP_MAIN_HEADER "overlap-check.main-header"
|
#define QCOW2_OPT_OVERLAP_MAIN_HEADER "overlap-check.main-header"
|
||||||
@ -385,6 +386,8 @@ typedef struct BDRVQcow2State {
|
|||||||
|
|
||||||
bool discard_passthrough[QCOW2_DISCARD_MAX];
|
bool discard_passthrough[QCOW2_DISCARD_MAX];
|
||||||
|
|
||||||
|
bool discard_no_unref;
|
||||||
|
|
||||||
int overlap_check; /* bitmask of Qcow2MetadataOverlap values */
|
int overlap_check; /* bitmask of Qcow2MetadataOverlap values */
|
||||||
bool signaled_corruption;
|
bool signaled_corruption;
|
||||||
|
|
||||||
|
@ -341,10 +341,10 @@ static bool parse_stats_intervals(BlockAcctStats *stats, QList *intervals,
|
|||||||
switch (qobject_type(entry->value)) {
|
switch (qobject_type(entry->value)) {
|
||||||
|
|
||||||
case QTYPE_QSTRING: {
|
case QTYPE_QSTRING: {
|
||||||
unsigned long long length;
|
uint64_t length;
|
||||||
const char *str = qstring_get_str(qobject_to(QString,
|
const char *str = qstring_get_str(qobject_to(QString,
|
||||||
entry->value));
|
entry->value));
|
||||||
if (parse_uint_full(str, &length, 10) == 0 &&
|
if (parse_uint_full(str, 10, &length) == 0 &&
|
||||||
length > 0 && length <= UINT_MAX) {
|
length > 0 && length <= UINT_MAX) {
|
||||||
block_acct_add_interval(stats, (unsigned) length);
|
block_acct_add_interval(stats, (unsigned) length);
|
||||||
} else {
|
} else {
|
||||||
|
@ -295,8 +295,16 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
envlist = envlist_create();
|
envlist = envlist_create();
|
||||||
|
|
||||||
/* add current environment into the list */
|
/*
|
||||||
|
* add current environment into the list
|
||||||
|
* envlist_setenv adds to the front of the list; to preserve environ
|
||||||
|
* order add from back to front
|
||||||
|
*/
|
||||||
for (wrk = environ; *wrk != NULL; wrk++) {
|
for (wrk = environ; *wrk != NULL; wrk++) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
while (wrk != environ) {
|
||||||
|
wrk--;
|
||||||
(void) envlist_setenv(envlist, *wrk);
|
(void) envlist_setenv(envlist, *wrk);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -334,7 +334,7 @@ static void char_pty_open(Chardev *chr,
|
|||||||
s = PTY_CHARDEV(chr);
|
s = PTY_CHARDEV(chr);
|
||||||
s->ioc = QIO_CHANNEL(qio_channel_file_new_fd(master_fd));
|
s->ioc = QIO_CHANNEL(qio_channel_file_new_fd(master_fd));
|
||||||
name = g_strdup_printf("chardev-pty-%s", chr->label);
|
name = g_strdup_printf("chardev-pty-%s", chr->label);
|
||||||
qio_channel_set_name(QIO_CHANNEL(s->ioc), name);
|
qio_channel_set_name(s->ioc, name);
|
||||||
g_free(name);
|
g_free(name);
|
||||||
s->timer_src = NULL;
|
s->timer_src = NULL;
|
||||||
*be_opened = false;
|
*be_opened = false;
|
||||||
|
@ -28,7 +28,7 @@ chardev_ss.add(when: 'CONFIG_WIN32', if_true: files(
|
|||||||
|
|
||||||
chardev_ss = chardev_ss.apply(config_host, strict: false)
|
chardev_ss = chardev_ss.apply(config_host, strict: false)
|
||||||
|
|
||||||
softmmu_ss.add(files(
|
system_ss.add(files(
|
||||||
'char-hmp-cmds.c',
|
'char-hmp-cmds.c',
|
||||||
'msmouse.c',
|
'msmouse.c',
|
||||||
'wctablet.c',
|
'wctablet.c',
|
||||||
|
170
configure
vendored
170
configure
vendored
@ -246,14 +246,7 @@ for opt do
|
|||||||
done
|
done
|
||||||
|
|
||||||
|
|
||||||
if test -e "$source_path/.git"
|
git_submodules_action="update"
|
||||||
then
|
|
||||||
git_submodules_action="update"
|
|
||||||
else
|
|
||||||
git_submodules_action="ignore"
|
|
||||||
fi
|
|
||||||
|
|
||||||
git_submodules="subprojects/keycodemapdb"
|
|
||||||
git="git"
|
git="git"
|
||||||
debug_tcg="no"
|
debug_tcg="no"
|
||||||
docs="auto"
|
docs="auto"
|
||||||
@ -266,10 +259,9 @@ bsd_user=""
|
|||||||
plugins="$default_feature"
|
plugins="$default_feature"
|
||||||
ninja=""
|
ninja=""
|
||||||
python=
|
python=
|
||||||
pypi="enabled"
|
download="enabled"
|
||||||
bindir="bin"
|
bindir="bin"
|
||||||
skip_meson=no
|
skip_meson=no
|
||||||
vfio_user_server="disabled"
|
|
||||||
use_containers="yes"
|
use_containers="yes"
|
||||||
gdb_bin=$(command -v "gdb-multiarch" || command -v "gdb")
|
gdb_bin=$(command -v "gdb-multiarch" || command -v "gdb")
|
||||||
gdb_arches=""
|
gdb_arches=""
|
||||||
@ -281,16 +273,13 @@ unset target_list_exclude
|
|||||||
|
|
||||||
# The following Meson options are handled manually (still they
|
# The following Meson options are handled manually (still they
|
||||||
# are included in the automatically generated help message)
|
# are included in the automatically generated help message)
|
||||||
|
# because they automatically enable/disable other options
|
||||||
# 1. Track which submodules are needed
|
|
||||||
fdt="auto"
|
|
||||||
|
|
||||||
# 2. Automatically enable/disable other options
|
|
||||||
tcg="auto"
|
tcg="auto"
|
||||||
cfi="false"
|
cfi="false"
|
||||||
|
|
||||||
# 3. Need to check for -static-pie before Meson runs. Also,
|
# Meson has PIE as a boolean rather than enabled/disabled/auto,
|
||||||
# Meson has PIE as a boolean rather than enabled/disabled/auto.
|
# and we also need to check for -static-pie before Meson runs
|
||||||
|
# which requires knowing whether --static is enabled.
|
||||||
pie=""
|
pie=""
|
||||||
static="no"
|
static="no"
|
||||||
|
|
||||||
@ -746,22 +735,9 @@ for opt do
|
|||||||
;;
|
;;
|
||||||
--disable-cfi) cfi="false"
|
--disable-cfi) cfi="false"
|
||||||
;;
|
;;
|
||||||
--disable-fdt) fdt="disabled"
|
--disable-download) download="disabled"; git_submodules_action=validate;
|
||||||
;;
|
;;
|
||||||
--enable-fdt) fdt="enabled"
|
--enable-download) download="enabled"; git_submodules_action=update;
|
||||||
;;
|
|
||||||
--enable-fdt=git) fdt="internal"
|
|
||||||
;;
|
|
||||||
--enable-fdt=*) fdt="$optarg"
|
|
||||||
;;
|
|
||||||
--with-git=*) git="$optarg"
|
|
||||||
;;
|
|
||||||
--with-git-submodules=*)
|
|
||||||
git_submodules_action="$optarg"
|
|
||||||
;;
|
|
||||||
--disable-pypi) pypi="disabled"
|
|
||||||
;;
|
|
||||||
--enable-pypi) pypi="enabled"
|
|
||||||
;;
|
;;
|
||||||
--enable-plugins) if test "$mingw32" = "yes"; then
|
--enable-plugins) if test "$mingw32" = "yes"; then
|
||||||
error_exit "TCG plugins not currently supported on Windows platforms"
|
error_exit "TCG plugins not currently supported on Windows platforms"
|
||||||
@ -777,10 +753,6 @@ for opt do
|
|||||||
;;
|
;;
|
||||||
--gdb=*) gdb_bin="$optarg"
|
--gdb=*) gdb_bin="$optarg"
|
||||||
;;
|
;;
|
||||||
--enable-vfio-user-server) vfio_user_server="enabled"
|
|
||||||
;;
|
|
||||||
--disable-vfio-user-server) vfio_user_server="disabled"
|
|
||||||
;;
|
|
||||||
--as-shared-lib)
|
--as-shared-lib)
|
||||||
as_shared_lib="yes"
|
as_shared_lib="yes"
|
||||||
CFLAGS="$CFLAGS -fPIC -DAS_LIB=1"
|
CFLAGS="$CFLAGS -fPIC -DAS_LIB=1"
|
||||||
@ -797,47 +769,41 @@ for opt do
|
|||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
|
|
||||||
|
if ! test -e "$source_path/.git"
|
||||||
|
then
|
||||||
|
git_submodules_action="ignore"
|
||||||
|
fi
|
||||||
|
|
||||||
# test for any invalid configuration combinations
|
# test for any invalid configuration combinations
|
||||||
if test "$plugins" = "yes" -a "$tcg" = "disabled"; then
|
if test "$plugins" = "yes" -a "$tcg" = "disabled"; then
|
||||||
error_exit "Can't enable plugins on non-TCG builds"
|
error_exit "Can't enable plugins on non-TCG builds"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
case $git_submodules_action in
|
if ! test -f "$source_path/subprojects/keycodemapdb/README" \
|
||||||
update|validate)
|
&& test "$download" = disabled
|
||||||
if test ! -e "$source_path/.git"; then
|
then
|
||||||
echo "ERROR: cannot $git_submodules_action git submodules without .git"
|
echo
|
||||||
exit 1
|
echo "ERROR: missing subprojects"
|
||||||
fi
|
echo
|
||||||
;;
|
if test -e "$source_path/.git"; then
|
||||||
ignore)
|
echo "--disable-download specified but subprojects were not"
|
||||||
if ! test -f "$source_path/subprojects/keycodemapdb/README"
|
echo 'checked out. Please invoke "meson subprojects download"'
|
||||||
then
|
echo "before configuring QEMU, or remove --disable-download"
|
||||||
echo
|
echo "from the command line."
|
||||||
echo "ERROR: missing GIT submodules"
|
else
|
||||||
echo
|
echo "This is not a GIT checkout but subproject content appears to"
|
||||||
if test -e "$source_path/.git"; then
|
echo "be missing. Do not use 'git archive' or GitHub download links"
|
||||||
echo "--with-git-submodules=ignore specified but submodules were not"
|
echo "to acquire QEMU source archives. Non-GIT builds are only"
|
||||||
echo "checked out. Please initialize and update submodules."
|
echo "supported with source archives linked from:"
|
||||||
else
|
echo
|
||||||
echo "This is not a GIT checkout but module content appears to"
|
echo " https://www.qemu.org/download/#source"
|
||||||
echo "be missing. Do not use 'git archive' or GitHub download links"
|
echo
|
||||||
echo "to acquire QEMU source archives. Non-GIT builds are only"
|
echo "Developers working with GIT can use scripts/archive-source.sh"
|
||||||
echo "supported with source archives linked from:"
|
echo "if they need to create valid source archives."
|
||||||
echo
|
fi
|
||||||
echo " https://www.qemu.org/download/#source"
|
echo
|
||||||
echo
|
exit 1
|
||||||
echo "Developers working with GIT can use scripts/archive-source.sh"
|
fi
|
||||||
echo "if they need to create valid source archives."
|
|
||||||
fi
|
|
||||||
echo
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
echo "ERROR: invalid --with-git-submodules= value '$git_submodules_action'"
|
|
||||||
exit 1
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
default_target_list=""
|
default_target_list=""
|
||||||
mak_wilds=""
|
mak_wilds=""
|
||||||
@ -905,10 +871,6 @@ Advanced options (experts only):
|
|||||||
--python=PYTHON use specified python [$python]
|
--python=PYTHON use specified python [$python]
|
||||||
--ninja=NINJA use specified ninja [$ninja]
|
--ninja=NINJA use specified ninja [$ninja]
|
||||||
--smbd=SMBD use specified smbd [$smbd]
|
--smbd=SMBD use specified smbd [$smbd]
|
||||||
--with-git=GIT use specified git [$git]
|
|
||||||
--with-git-submodules=update update git submodules (default if .git dir exists)
|
|
||||||
--with-git-submodules=validate fail if git submodules are not up to date
|
|
||||||
--with-git-submodules=ignore do not update or check git submodules (default if no .git dir)
|
|
||||||
--static enable static build [$static]
|
--static enable static build [$static]
|
||||||
--bindir=PATH install binaries in PATH
|
--bindir=PATH install binaries in PATH
|
||||||
--with-suffix=SUFFIX suffix for QEMU data inside datadir/libdir/sysconfdir/docdir [$qemu_suffix]
|
--with-suffix=SUFFIX suffix for QEMU data inside datadir/libdir/sysconfdir/docdir [$qemu_suffix]
|
||||||
@ -976,7 +938,7 @@ python="$(command -v "$python")"
|
|||||||
# - venv is allowed to use system packages;
|
# - venv is allowed to use system packages;
|
||||||
# - all setup can be performed offline;
|
# - all setup can be performed offline;
|
||||||
# - missing packages may be fetched from PyPI,
|
# - missing packages may be fetched from PyPI,
|
||||||
# unless --disable-pypi is passed.
|
# unless --disable-download is passed.
|
||||||
# - pip is not installed into the venv when possible,
|
# - pip is not installed into the venv when possible,
|
||||||
# but ensurepip is called as a fallback when necessary.
|
# but ensurepip is called as a fallback when necessary.
|
||||||
|
|
||||||
@ -993,7 +955,7 @@ python="$python -B"
|
|||||||
mkvenv="$python ${source_path}/python/scripts/mkvenv.py"
|
mkvenv="$python ${source_path}/python/scripts/mkvenv.py"
|
||||||
|
|
||||||
mkvenv_flags=""
|
mkvenv_flags=""
|
||||||
if test "$pypi" = "enabled" ; then
|
if test "$download" = "enabled" ; then
|
||||||
mkvenv_flags="--online"
|
mkvenv_flags="--online"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@ -1016,7 +978,7 @@ meson="$(cd pyvenv/bin; pwd)/meson"
|
|||||||
# Conditionally ensure Sphinx is installed.
|
# Conditionally ensure Sphinx is installed.
|
||||||
|
|
||||||
mkvenv_flags=""
|
mkvenv_flags=""
|
||||||
if test "$pypi" = "enabled" -a "$docs" = "enabled" ; then
|
if test "$download" = "enabled" -a "$docs" = "enabled" ; then
|
||||||
mkvenv_flags="--online"
|
mkvenv_flags="--online"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@ -1053,7 +1015,7 @@ fi
|
|||||||
# Consult white-list to determine whether to enable werror
|
# Consult white-list to determine whether to enable werror
|
||||||
# by default. Only enable by default for git builds
|
# by default. Only enable by default for git builds
|
||||||
if test -z "$werror" ; then
|
if test -z "$werror" ; then
|
||||||
if test "$git_submodules_action" != "ignore" && \
|
if test -e "$source_path/.git" && \
|
||||||
{ test "$linux" = "yes" || test "$mingw32" = "yes"; }; then
|
{ test "$linux" = "yes" || test "$mingw32" = "yes"; }; then
|
||||||
werror="yes"
|
werror="yes"
|
||||||
else
|
else
|
||||||
@ -1148,11 +1110,6 @@ if test "$tcg" = "auto"; then
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if test "$tcg" = "enabled"; then
|
|
||||||
git_submodules="$git_submodules tests/fp/berkeley-testfloat-3"
|
|
||||||
git_submodules="$git_submodules tests/fp/berkeley-softfloat-3"
|
|
||||||
fi
|
|
||||||
|
|
||||||
##########################################
|
##########################################
|
||||||
# big/little endian test
|
# big/little endian test
|
||||||
cat > $TMPC << EOF
|
cat > $TMPC << EOF
|
||||||
@ -1180,16 +1137,6 @@ EOF
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
##########################################
|
|
||||||
# fdt probe
|
|
||||||
|
|
||||||
case "$fdt" in
|
|
||||||
auto | enabled | internal)
|
|
||||||
# Simpler to always update submodule, even if not needed.
|
|
||||||
git_submodules="${git_submodules} subprojects/dtc"
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
########################################
|
########################################
|
||||||
# check if ccache is interfering with
|
# check if ccache is interfering with
|
||||||
# semantic analysis of macros
|
# semantic analysis of macros
|
||||||
@ -1449,6 +1396,7 @@ probe_target_compiler() {
|
|||||||
container_cross_prefix=tricore-
|
container_cross_prefix=tricore-
|
||||||
container_cross_as=tricore-as
|
container_cross_as=tricore-as
|
||||||
container_cross_ld=tricore-ld
|
container_cross_ld=tricore-ld
|
||||||
|
container_cross_cc=tricore-gcc
|
||||||
break
|
break
|
||||||
;;
|
;;
|
||||||
x86_64)
|
x86_64)
|
||||||
@ -1625,17 +1573,6 @@ write_target_makefile() {
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
##########################################
|
|
||||||
# check for vfio_user_server
|
|
||||||
|
|
||||||
case "$vfio_user_server" in
|
|
||||||
enabled )
|
|
||||||
if test "$git_submodules_action" != "ignore"; then
|
|
||||||
git_submodules="${git_submodules} subprojects/libvfio-user"
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
#######################################
|
#######################################
|
||||||
# cross-compiled firmware targets
|
# cross-compiled firmware targets
|
||||||
|
|
||||||
@ -1689,7 +1626,8 @@ fi
|
|||||||
|
|
||||||
# Only build s390-ccw bios if the compiler has -march=z900 or -march=z10
|
# Only build s390-ccw bios if the compiler has -march=z900 or -march=z10
|
||||||
# (which is the lowest architecture level that Clang supports)
|
# (which is the lowest architecture level that Clang supports)
|
||||||
if have_target s390x-softmmu && probe_target_compiler s390x-softmmu; then
|
if have_target s390x-softmmu && probe_target_compiler s390x-softmmu && \
|
||||||
|
GIT=git "$source_path/scripts/git-submodule.sh" "$git_submodules_action" roms/SLOF >> config.log 2>&1; then
|
||||||
write_c_skeleton
|
write_c_skeleton
|
||||||
do_compiler "$target_cc" $target_cc_cflags -march=z900 -o $TMPO -c $TMPC
|
do_compiler "$target_cc" $target_cc_cflags -march=z900 -o $TMPO -c $TMPC
|
||||||
has_z900=$?
|
has_z900=$?
|
||||||
@ -1702,29 +1640,20 @@ if have_target s390x-softmmu && probe_target_compiler s390x-softmmu; then
|
|||||||
config_mak=pc-bios/s390-ccw/config-host.mak
|
config_mak=pc-bios/s390-ccw/config-host.mak
|
||||||
echo "# Automatically generated by configure - do not modify" > $config_mak
|
echo "# Automatically generated by configure - do not modify" > $config_mak
|
||||||
echo "SRC_PATH=$source_path/pc-bios/s390-ccw" >> $config_mak
|
echo "SRC_PATH=$source_path/pc-bios/s390-ccw" >> $config_mak
|
||||||
|
echo "GIT_SUBMODULES_ACTION=$git_submodules_action" >> $config_mak
|
||||||
write_target_makefile >> $config_mak
|
write_target_makefile >> $config_mak
|
||||||
# SLOF is required for building the s390-ccw firmware on s390x,
|
|
||||||
# since it is using the libnet code from SLOF for network booting.
|
|
||||||
git_submodules="${git_submodules} roms/SLOF"
|
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
#######################################
|
#######################################
|
||||||
# generate config-host.mak
|
# generate config-host.mak
|
||||||
|
|
||||||
if ! (GIT="$git" "$source_path/scripts/git-submodule.sh" "$git_submodules_action" "$git_submodules"); then
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
config_host_mak="config-host.mak"
|
config_host_mak="config-host.mak"
|
||||||
|
|
||||||
echo "# Automatically generated by configure - do not modify" > $config_host_mak
|
echo "# Automatically generated by configure - do not modify" > $config_host_mak
|
||||||
echo >> $config_host_mak
|
echo >> $config_host_mak
|
||||||
|
|
||||||
echo all: >> $config_host_mak
|
echo all: >> $config_host_mak
|
||||||
echo "GIT=$git" >> $config_host_mak
|
|
||||||
echo "GIT_SUBMODULES=$git_submodules" >> $config_host_mak
|
|
||||||
echo "GIT_SUBMODULES_ACTION=$git_submodules_action" >> $config_host_mak
|
|
||||||
|
|
||||||
if test "$debug_tcg" = "yes" ; then
|
if test "$debug_tcg" = "yes" ; then
|
||||||
echo "CONFIG_DEBUG_TCG=y" >> $config_host_mak
|
echo "CONFIG_DEBUG_TCG=y" >> $config_host_mak
|
||||||
@ -1965,11 +1894,8 @@ if test "$skip_meson" = no; then
|
|||||||
|
|
||||||
rm -rf meson-private meson-info meson-logs
|
rm -rf meson-private meson-info meson-logs
|
||||||
|
|
||||||
# Prevent meson from automatically downloading wrapped subprojects when missing.
|
|
||||||
# You can use 'meson subprojects download' before running configure.
|
|
||||||
meson_option_add "--wrap-mode=nodownload"
|
|
||||||
|
|
||||||
# Built-in options
|
# Built-in options
|
||||||
|
test "$download" = "disabled" && meson_option_add "--wrap-mode=nodownload"
|
||||||
test "$bindir" != "bin" && meson_option_add "-Dbindir=$bindir"
|
test "$bindir" != "bin" && meson_option_add "-Dbindir=$bindir"
|
||||||
test "$default_feature" = no && meson_option_add -Dauto_features=disabled
|
test "$default_feature" = no && meson_option_add -Dauto_features=disabled
|
||||||
test "$static" = yes && meson_option_add -Dprefer_static=true
|
test "$static" = yes && meson_option_add -Dprefer_static=true
|
||||||
@ -1979,12 +1905,10 @@ if test "$skip_meson" = no; then
|
|||||||
# QEMU options
|
# QEMU options
|
||||||
test "$cfi" != false && meson_option_add "-Dcfi=$cfi"
|
test "$cfi" != false && meson_option_add "-Dcfi=$cfi"
|
||||||
test "$docs" != auto && meson_option_add "-Ddocs=$docs"
|
test "$docs" != auto && meson_option_add "-Ddocs=$docs"
|
||||||
test "$fdt" != auto && meson_option_add "-Dfdt=$fdt"
|
|
||||||
test -n "${LIB_FUZZING_ENGINE+xxx}" && meson_option_add "-Dfuzzing_engine=$LIB_FUZZING_ENGINE"
|
test -n "${LIB_FUZZING_ENGINE+xxx}" && meson_option_add "-Dfuzzing_engine=$LIB_FUZZING_ENGINE"
|
||||||
test "$qemu_suffix" != qemu && meson_option_add "-Dqemu_suffix=$qemu_suffix"
|
test "$qemu_suffix" != qemu && meson_option_add "-Dqemu_suffix=$qemu_suffix"
|
||||||
test "$smbd" != '' && meson_option_add "-Dsmbd=$smbd"
|
test "$smbd" != '' && meson_option_add "-Dsmbd=$smbd"
|
||||||
test "$tcg" != enabled && meson_option_add "-Dtcg=$tcg"
|
test "$tcg" != enabled && meson_option_add "-Dtcg=$tcg"
|
||||||
test "$vfio_user_server" != auto && meson_option_add "-Dvfio_user_server=$vfio_user_server"
|
|
||||||
run_meson() {
|
run_meson() {
|
||||||
NINJA=$ninja $meson setup --prefix "$prefix" "$@" $cross_arg "$PWD" "$source_path"
|
NINJA=$ninja $meson setup --prefix "$prefix" "$@" $cross_arg "$PWD" "$source_path"
|
||||||
}
|
}
|
||||||
|
@ -69,7 +69,7 @@ static void
|
|||||||
ivshmem_server_parse_args(IvshmemServerArgs *args, int argc, char *argv[])
|
ivshmem_server_parse_args(IvshmemServerArgs *args, int argc, char *argv[])
|
||||||
{
|
{
|
||||||
int c;
|
int c;
|
||||||
unsigned long long v;
|
uint64_t v;
|
||||||
Error *err = NULL;
|
Error *err = NULL;
|
||||||
|
|
||||||
while ((c = getopt(argc, argv, "hvFp:S:m:M:l:n:")) != -1) {
|
while ((c = getopt(argc, argv, "hvFp:S:m:M:l:n:")) != -1) {
|
||||||
@ -112,7 +112,7 @@ ivshmem_server_parse_args(IvshmemServerArgs *args, int argc, char *argv[])
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 'n': /* number of vectors */
|
case 'n': /* number of vectors */
|
||||||
if (parse_uint_full(optarg, &v, 0) < 0) {
|
if (parse_uint_full(optarg, 0, &v) < 0) {
|
||||||
fprintf(stderr, "cannot parse n_vectors\n");
|
fprintf(stderr, "cannot parse n_vectors\n");
|
||||||
ivshmem_server_help(argv[0]);
|
ivshmem_server_help(argv[0]);
|
||||||
exit(1);
|
exit(1);
|
||||||
|
@ -13,5 +13,5 @@ common_ss.add(when: 'CONFIG_XTENSA_DIS', if_true: files('xtensa.c'))
|
|||||||
common_ss.add(when: capstone, if_true: [files('capstone.c'), capstone])
|
common_ss.add(when: capstone, if_true: [files('capstone.c'), capstone])
|
||||||
common_ss.add(files('disas.c'))
|
common_ss.add(files('disas.c'))
|
||||||
|
|
||||||
softmmu_ss.add(files('disas-mon.c'))
|
system_ss.add(files('disas-mon.c'))
|
||||||
specific_ss.add(capstone)
|
specific_ss.add(capstone)
|
||||||
|
1194
disas/riscv.c
1194
disas/riscv.c
File diff suppressed because it is too large
Load Diff
@ -61,19 +61,19 @@ Under ``tests/avocado/`` as the root we have:
|
|||||||
::
|
::
|
||||||
|
|
||||||
$ make check-venv (needed only the first time to create the venv)
|
$ make check-venv (needed only the first time to create the venv)
|
||||||
$ ./pyvenv/bin/avocado run -t acpi tests/avocado
|
$ ./tests/venv/bin/avocado run -t acpi tests/avocado
|
||||||
|
|
||||||
The above will run all acpi avocado tests including this one.
|
The above will run all acpi avocado tests including this one.
|
||||||
In order to run the individual tests, perform the following:
|
In order to run the individual tests, perform the following:
|
||||||
::
|
::
|
||||||
|
|
||||||
$ ./pyvenv/bin/avocado run tests/avocado/acpi-bits.py --tap -
|
$ ./tests/venv/bin/avocado run tests/avocado/acpi-bits.py --tap -
|
||||||
|
|
||||||
The above will produce output in tap format. You can omit "--tap -" in the
|
The above will produce output in tap format. You can omit "--tap -" in the
|
||||||
end and it will produce output like the following:
|
end and it will produce output like the following:
|
||||||
::
|
::
|
||||||
|
|
||||||
$ ./pyvenv/bin/avocado run tests/avocado/acpi-bits.py
|
$ ./tests/venv/bin/avocado run tests/avocado/acpi-bits.py
|
||||||
Fetching asset from tests/avocado/acpi-bits.py:AcpiBitsTest.test_acpi_smbios_bits
|
Fetching asset from tests/avocado/acpi-bits.py:AcpiBitsTest.test_acpi_smbios_bits
|
||||||
JOB ID : eab225724da7b64c012c65705dc2fa14ab1defef
|
JOB ID : eab225724da7b64c012c65705dc2fa14ab1defef
|
||||||
JOB LOG : /home/anisinha/avocado/job-results/job-2022-10-10T17.58-eab2257/job.log
|
JOB LOG : /home/anisinha/avocado/job-results/job-2022-10-10T17.58-eab2257/job.log
|
||||||
|
@ -102,28 +102,10 @@ Similar operations return the new value of ``*ptr``::
|
|||||||
typeof(*ptr) qatomic_or_fetch(ptr, val)
|
typeof(*ptr) qatomic_or_fetch(ptr, val)
|
||||||
typeof(*ptr) qatomic_xor_fetch(ptr, val)
|
typeof(*ptr) qatomic_xor_fetch(ptr, val)
|
||||||
|
|
||||||
``qemu/atomic.h`` also provides loads and stores that cannot be reordered
|
``qemu/atomic.h`` also provides an optimized shortcut for
|
||||||
with each other::
|
``qatomic_set`` followed by ``smp_mb``::
|
||||||
|
|
||||||
typeof(*ptr) qatomic_mb_read(ptr)
|
void qatomic_set_mb(ptr, val)
|
||||||
void qatomic_mb_set(ptr, val)
|
|
||||||
|
|
||||||
However these do not provide sequential consistency and, in particular,
|
|
||||||
they do not participate in the total ordering enforced by
|
|
||||||
sequentially-consistent operations. For this reason they are deprecated.
|
|
||||||
They should instead be replaced with any of the following (ordered from
|
|
||||||
easiest to hardest):
|
|
||||||
|
|
||||||
- accesses inside a mutex or spinlock
|
|
||||||
|
|
||||||
- lightweight synchronization primitives such as ``QemuEvent``
|
|
||||||
|
|
||||||
- RCU operations (``qatomic_rcu_read``, ``qatomic_rcu_set``) when publishing
|
|
||||||
or accessing a new version of a data structure
|
|
||||||
|
|
||||||
- other atomic accesses: ``qatomic_read`` and ``qatomic_load_acquire`` for
|
|
||||||
loads, ``qatomic_set`` and ``qatomic_store_release`` for stores, ``smp_mb``
|
|
||||||
to forbid reordering subsequent loads before a store.
|
|
||||||
|
|
||||||
|
|
||||||
Weak atomic access and manual memory barriers
|
Weak atomic access and manual memory barriers
|
||||||
@ -523,8 +505,7 @@ and memory barriers, and the equivalents in QEMU:
|
|||||||
| :: |
|
| :: |
|
||||||
| |
|
| |
|
||||||
| a = qatomic_read(&x); |
|
| a = qatomic_read(&x); |
|
||||||
| qatomic_set(&x, a + 2); |
|
| qatomic_set_mb(&x, a + 2); |
|
||||||
| smp_mb(); |
|
|
||||||
| b = qatomic_read(&y); |
|
| b = qatomic_read(&y); |
|
||||||
+--------------------------------+
|
+--------------------------------+
|
||||||
|
|
||||||
|
@ -183,9 +183,9 @@ Target-independent emulator sourcesets:
|
|||||||
This includes error handling infrastructure, standard data structures,
|
This includes error handling infrastructure, standard data structures,
|
||||||
platform portability wrapper functions, etc.
|
platform portability wrapper functions, etc.
|
||||||
|
|
||||||
Target-independent code lives in the ``common_ss``, ``softmmu_ss`` and
|
Target-independent code lives in the ``common_ss``, ``system_ss`` and
|
||||||
``user_ss`` sourcesets. ``common_ss`` is linked into all emulators,
|
``user_ss`` sourcesets. ``common_ss`` is linked into all emulators,
|
||||||
``softmmu_ss`` only in system emulators, ``user_ss`` only in user-mode
|
``system_ss`` only in system emulators, ``user_ss`` only in user-mode
|
||||||
emulators.
|
emulators.
|
||||||
|
|
||||||
Target-independent sourcesets must exercise particular care when using
|
Target-independent sourcesets must exercise particular care when using
|
||||||
@ -197,11 +197,11 @@ Target-independent emulator sourcesets:
|
|||||||
symbol::
|
symbol::
|
||||||
|
|
||||||
# Some targets have CONFIG_ACPI, some don't, so this is not enough
|
# Some targets have CONFIG_ACPI, some don't, so this is not enough
|
||||||
softmmu_ss.add(when: 'CONFIG_ACPI', if_true: files('acpi.c'),
|
system_ss.add(when: 'CONFIG_ACPI', if_true: files('acpi.c'),
|
||||||
if_false: files('acpi-stub.c'))
|
if_false: files('acpi-stub.c'))
|
||||||
|
|
||||||
# This is required as well:
|
# This is required as well:
|
||||||
softmmu_ss.add(when: 'CONFIG_ALL', if_true: files('acpi-stub.c'))
|
system_ss.add(when: 'CONFIG_ALL', if_true: files('acpi-stub.c'))
|
||||||
|
|
||||||
Target-dependent emulator sourcesets:
|
Target-dependent emulator sourcesets:
|
||||||
In the target-dependent set lives CPU emulation, some device emulation and
|
In the target-dependent set lives CPU emulation, some device emulation and
|
||||||
@ -229,16 +229,16 @@ Target-dependent emulator sourcesets:
|
|||||||
for all emulators and for system emulators only. For example::
|
for all emulators and for system emulators only. For example::
|
||||||
|
|
||||||
arm_ss = ss.source_set()
|
arm_ss = ss.source_set()
|
||||||
arm_softmmu_ss = ss.source_set()
|
arm_system_ss = ss.source_set()
|
||||||
...
|
...
|
||||||
target_arch += {'arm': arm_ss}
|
target_arch += {'arm': arm_ss}
|
||||||
target_softmmu_arch += {'arm': arm_softmmu_ss}
|
target_softmmu_arch += {'arm': arm_system_ss}
|
||||||
|
|
||||||
Module sourcesets:
|
Module sourcesets:
|
||||||
There are two dictionaries for modules: ``modules`` is used for
|
There are two dictionaries for modules: ``modules`` is used for
|
||||||
target-independent modules and ``target_modules`` is used for
|
target-independent modules and ``target_modules`` is used for
|
||||||
target-dependent modules. When modules are disabled the ``module``
|
target-dependent modules. When modules are disabled the ``module``
|
||||||
source sets are added to ``softmmu_ss`` and the ``target_modules``
|
source sets are added to ``system_ss`` and the ``target_modules``
|
||||||
source sets are added to ``specific_ss``.
|
source sets are added to ``specific_ss``.
|
||||||
|
|
||||||
Both dictionaries are nested. One dictionary is created per
|
Both dictionaries are nested. One dictionary is created per
|
||||||
|
@ -888,9 +888,9 @@ You can run the avocado tests simply by executing:
|
|||||||
|
|
||||||
make check-avocado
|
make check-avocado
|
||||||
|
|
||||||
This involves the automatic installation, from PyPI, of all the
|
This involves the automatic creation of Python virtual environment
|
||||||
necessary avocado-framework dependencies into the QEMU venv within the
|
within the build tree (at ``tests/venv``) which will have all the
|
||||||
build tree (at ``./pyvenv``). Test results are also saved within the
|
right dependencies, and will save tests results also within the
|
||||||
build tree (at ``tests/results``).
|
build tree (at ``tests/results``).
|
||||||
|
|
||||||
Note: the build environment must be using a Python 3 stack, and have
|
Note: the build environment must be using a Python 3 stack, and have
|
||||||
@ -947,7 +947,7 @@ may be invoked by running:
|
|||||||
|
|
||||||
.. code::
|
.. code::
|
||||||
|
|
||||||
pyvenv/bin/avocado run $OPTION1 $OPTION2 tests/avocado/
|
tests/venv/bin/avocado run $OPTION1 $OPTION2 tests/avocado/
|
||||||
|
|
||||||
Note that if ``make check-avocado`` was not executed before, it is
|
Note that if ``make check-avocado`` was not executed before, it is
|
||||||
possible to create the Python virtual environment with the dependencies
|
possible to create the Python virtual environment with the dependencies
|
||||||
@ -962,20 +962,20 @@ a test file. To run tests from a single file within the build tree, use:
|
|||||||
|
|
||||||
.. code::
|
.. code::
|
||||||
|
|
||||||
pyvenv/bin/avocado run tests/avocado/$TESTFILE
|
tests/venv/bin/avocado run tests/avocado/$TESTFILE
|
||||||
|
|
||||||
To run a single test within a test file, use:
|
To run a single test within a test file, use:
|
||||||
|
|
||||||
.. code::
|
.. code::
|
||||||
|
|
||||||
pyvenv/bin/avocado run tests/avocado/$TESTFILE:$TESTCLASS.$TESTNAME
|
tests/venv/bin/avocado run tests/avocado/$TESTFILE:$TESTCLASS.$TESTNAME
|
||||||
|
|
||||||
Valid test names are visible in the output from any previous execution
|
Valid test names are visible in the output from any previous execution
|
||||||
of Avocado or ``make check-avocado``, and can also be queried using:
|
of Avocado or ``make check-avocado``, and can also be queried using:
|
||||||
|
|
||||||
.. code::
|
.. code::
|
||||||
|
|
||||||
pyvenv/bin/avocado list tests/avocado
|
tests/venv/bin/avocado list tests/avocado
|
||||||
|
|
||||||
Manual Installation
|
Manual Installation
|
||||||
~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~
|
||||||
|
@ -226,6 +226,7 @@ version 2.
|
|||||||
<https://www.zlib.net/> in QEMU. However, clusters with the
|
<https://www.zlib.net/> in QEMU. However, clusters with the
|
||||||
deflate compression type do not have zlib headers.
|
deflate compression type do not have zlib headers.
|
||||||
|
|
||||||
|
105 - 111: Padding, contents defined below.
|
||||||
|
|
||||||
=== Header padding ===
|
=== Header padding ===
|
||||||
|
|
||||||
|
@ -122,6 +122,11 @@ Options specific to Aspeed machines are :
|
|||||||
|
|
||||||
* ``spi-model`` to change the SPI Flash model.
|
* ``spi-model`` to change the SPI Flash model.
|
||||||
|
|
||||||
|
* ``bmc-console`` to change the default console device. Most of the
|
||||||
|
machines use the ``UART5`` device for a boot console, which is
|
||||||
|
mapped on ``/dev/ttyS4`` under Linux, but it is not always the
|
||||||
|
case.
|
||||||
|
|
||||||
For instance, to start the ``ast2500-evb`` machine with a different
|
For instance, to start the ``ast2500-evb`` machine with a different
|
||||||
FMC chip and a bigger (64M) SPI chip, use :
|
FMC chip and a bigger (64M) SPI chip, use :
|
||||||
|
|
||||||
@ -129,6 +134,12 @@ FMC chip and a bigger (64M) SPI chip, use :
|
|||||||
|
|
||||||
-M ast2500-evb,fmc-model=mx25l25635e,spi-model=mx66u51235f
|
-M ast2500-evb,fmc-model=mx25l25635e,spi-model=mx66u51235f
|
||||||
|
|
||||||
|
To change the boot console and use device ``UART3`` (``/dev/ttyS2``
|
||||||
|
under Linux), use :
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
-M ast2500-evb,bmc-console=uart3
|
||||||
|
|
||||||
Aspeed minibmc family boards (``ast1030-evb``)
|
Aspeed minibmc family boards (``ast1030-evb``)
|
||||||
==================================================================
|
==================================================================
|
||||||
|
139
docs/system/arm/bananapi_m2u.rst
Normal file
139
docs/system/arm/bananapi_m2u.rst
Normal file
@ -0,0 +1,139 @@
|
|||||||
|
Banana Pi BPI-M2U (``bpim2u``)
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
Banana Pi BPI-M2 Ultra is a quad-core mini single board computer built with
|
||||||
|
Allwinner A40i/R40/V40 SoC. It features 2GB of RAM and 8GB eMMC. It also
|
||||||
|
has onboard WiFi and BT. On the ports side, the BPI-M2 Ultra has 2 USB A
|
||||||
|
2.0 ports, 1 USB OTG port, 1 HDMI port, 1 audio jack, a DC power port,
|
||||||
|
and last but not least, a SATA port.
|
||||||
|
|
||||||
|
Supported devices
|
||||||
|
"""""""""""""""""
|
||||||
|
|
||||||
|
The Banana Pi M2U machine supports the following devices:
|
||||||
|
|
||||||
|
* SMP (Quad Core Cortex-A7)
|
||||||
|
* Generic Interrupt Controller configuration
|
||||||
|
* SRAM mappings
|
||||||
|
* SDRAM controller
|
||||||
|
* Timer device (re-used from Allwinner A10)
|
||||||
|
* UART
|
||||||
|
* SD/MMC storage controller
|
||||||
|
* EMAC ethernet
|
||||||
|
* GMAC ethernet
|
||||||
|
* Clock Control Unit
|
||||||
|
* TWI (I2C)
|
||||||
|
|
||||||
|
Limitations
|
||||||
|
"""""""""""
|
||||||
|
|
||||||
|
Currently, Banana Pi M2U does *not* support the following features:
|
||||||
|
|
||||||
|
- Graphical output via HDMI, GPU and/or the Display Engine
|
||||||
|
- Audio output
|
||||||
|
- Hardware Watchdog
|
||||||
|
- Real Time Clock
|
||||||
|
- USB 2.0 interfaces
|
||||||
|
|
||||||
|
Also see the 'unimplemented' array in the Allwinner R40 SoC module
|
||||||
|
for a complete list of unimplemented I/O devices: ``./hw/arm/allwinner-r40.c``
|
||||||
|
|
||||||
|
Boot options
|
||||||
|
""""""""""""
|
||||||
|
|
||||||
|
The Banana Pi M2U machine can start using the standard -kernel functionality
|
||||||
|
for loading a Linux kernel or ELF executable. Additionally, the Banana Pi M2U
|
||||||
|
machine can also emulate the BootROM which is present on an actual Allwinner R40
|
||||||
|
based SoC, which loads the bootloader from a SD card, specified via the -sd
|
||||||
|
argument to qemu-system-arm.
|
||||||
|
|
||||||
|
Running mainline Linux
|
||||||
|
""""""""""""""""""""""
|
||||||
|
|
||||||
|
To build a Linux mainline kernel that can be booted by the Banana Pi M2U machine,
|
||||||
|
simply configure the kernel using the sunxi_defconfig configuration:
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
$ ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- make mrproper
|
||||||
|
$ ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- make sunxi_defconfig
|
||||||
|
|
||||||
|
To boot the newly build linux kernel in QEMU with the Banana Pi M2U machine, use:
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
$ qemu-system-arm -M bpim2u -nographic \
|
||||||
|
-kernel /path/to/linux/arch/arm/boot/zImage \
|
||||||
|
-append 'console=ttyS0,115200' \
|
||||||
|
-dtb /path/to/linux/arch/arm/boot/dts/sun8i-r40-bananapi-m2-ultra.dtb
|
||||||
|
|
||||||
|
Banana Pi M2U images
|
||||||
|
""""""""""""""""""""
|
||||||
|
|
||||||
|
Note that the mainline kernel does not have a root filesystem. You can choose
|
||||||
|
to build you own image with buildroot using the bananapi_m2_ultra_defconfig.
|
||||||
|
Also see https://buildroot.org for more information.
|
||||||
|
|
||||||
|
Another possibility is to run an OpenWrt image for Banana Pi M2U which
|
||||||
|
can be downloaded from:
|
||||||
|
|
||||||
|
https://downloads.openwrt.org/releases/22.03.3/targets/sunxi/cortexa7/
|
||||||
|
|
||||||
|
When using an image as an SD card, it must be resized to a power of two. This can be
|
||||||
|
done with the ``qemu-img`` command. It is recommended to only increase the image size
|
||||||
|
instead of shrinking it to a power of two, to avoid loss of data. For example,
|
||||||
|
to prepare a downloaded Armbian image, first extract it and then increase
|
||||||
|
its size to one gigabyte as follows:
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
$ qemu-img resize \
|
||||||
|
openwrt-22.03.3-sunxi-cortexa7-sinovoip_bananapi-m2-ultra-ext4-sdcard.img \
|
||||||
|
1G
|
||||||
|
|
||||||
|
Instead of providing a custom Linux kernel via the -kernel command you may also
|
||||||
|
choose to let the Banana Pi M2U machine load the bootloader from SD card, just like
|
||||||
|
a real board would do using the BootROM. Simply pass the selected image via the -sd
|
||||||
|
argument and remove the -kernel, -append, -dbt and -initrd arguments:
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
$ qemu-system-arm -M bpim2u -nic user -nographic \
|
||||||
|
-sd openwrt-22.03.3-sunxi-cortexa7-sinovoip_bananapi-m2-ultra-ext4-sdcard.img
|
||||||
|
|
||||||
|
Running U-Boot
|
||||||
|
""""""""""""""
|
||||||
|
|
||||||
|
U-Boot mainline can be build and configured using the Bananapi_M2_Ultra_defconfig
|
||||||
|
using similar commands as describe above for Linux. Note that it is recommended
|
||||||
|
for development/testing to select the following configuration setting in U-Boot:
|
||||||
|
|
||||||
|
Device Tree Control > Provider for DTB for DT Control > Embedded DTB
|
||||||
|
|
||||||
|
The BootROM of allwinner R40 loading u-boot from the 8KiB offset of sdcard.
|
||||||
|
Let's create an bootable disk image:
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
$ dd if=/dev/zero of=sd.img bs=32M count=1
|
||||||
|
$ dd if=u-boot-sunxi-with-spl.bin of=sd.img bs=1k seek=8 conv=notrunc
|
||||||
|
|
||||||
|
And then boot it.
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
$ qemu-system-arm -M bpim2u -nographic -sd sd.img
|
||||||
|
|
||||||
|
Banana Pi M2U integration tests
|
||||||
|
"""""""""""""""""""""""""""""""
|
||||||
|
|
||||||
|
The Banana Pi M2U machine has several integration tests included.
|
||||||
|
To run the whole set of tests, build QEMU from source and simply
|
||||||
|
provide the following command:
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
$ cd qemu-build-dir
|
||||||
|
$ AVOCADO_ALLOW_LARGE_STORAGE=yes tests/venv/bin/avocado \
|
||||||
|
--verbose --show=app,console run -t machine:bpim2u \
|
||||||
|
../tests/avocado/boot_linux_console.py
|
@ -50,6 +50,7 @@ the following architecture extensions:
|
|||||||
- FEAT_LRCPC (Load-acquire RCpc instructions)
|
- FEAT_LRCPC (Load-acquire RCpc instructions)
|
||||||
- FEAT_LRCPC2 (Load-acquire RCpc instructions v2)
|
- FEAT_LRCPC2 (Load-acquire RCpc instructions v2)
|
||||||
- FEAT_LSE (Large System Extensions)
|
- FEAT_LSE (Large System Extensions)
|
||||||
|
- FEAT_LSE2 (Large System Extensions v2)
|
||||||
- FEAT_LVA (Large Virtual Address space)
|
- FEAT_LVA (Large Virtual Address space)
|
||||||
- FEAT_MTE (Memory Tagging Extension)
|
- FEAT_MTE (Memory Tagging Extension)
|
||||||
- FEAT_MTE2 (Memory Tagging Extension)
|
- FEAT_MTE2 (Memory Tagging Extension)
|
||||||
|
@ -6,12 +6,7 @@ any real hardware the ``sbsa-ref`` board intends to look like real
|
|||||||
hardware. The `Server Base System Architecture
|
hardware. The `Server Base System Architecture
|
||||||
<https://developer.arm.com/documentation/den0029/latest>`_ defines a
|
<https://developer.arm.com/documentation/den0029/latest>`_ defines a
|
||||||
minimum base line of hardware support and importantly how the firmware
|
minimum base line of hardware support and importantly how the firmware
|
||||||
reports that to any operating system. It is a static system that
|
reports that to any operating system.
|
||||||
reports a very minimal DT to the firmware for non-discoverable
|
|
||||||
information about components affected by the qemu command line (i.e.
|
|
||||||
cpus and memory). As a result it must have a firmware specifically
|
|
||||||
built to expect a certain hardware layout (as you would in a real
|
|
||||||
machine).
|
|
||||||
|
|
||||||
It is intended to be a machine for developing firmware and testing
|
It is intended to be a machine for developing firmware and testing
|
||||||
standards compliance with operating systems.
|
standards compliance with operating systems.
|
||||||
@ -19,7 +14,7 @@ standards compliance with operating systems.
|
|||||||
Supported devices
|
Supported devices
|
||||||
"""""""""""""""""
|
"""""""""""""""""
|
||||||
|
|
||||||
The sbsa-ref board supports:
|
The ``sbsa-ref`` board supports:
|
||||||
|
|
||||||
- A configurable number of AArch64 CPUs
|
- A configurable number of AArch64 CPUs
|
||||||
- GIC version 3
|
- GIC version 3
|
||||||
@ -30,3 +25,32 @@ The sbsa-ref board supports:
|
|||||||
- Bochs display adapter on PCIe bus
|
- Bochs display adapter on PCIe bus
|
||||||
- A generic SBSA watchdog device
|
- A generic SBSA watchdog device
|
||||||
|
|
||||||
|
|
||||||
|
Board to firmware interface
|
||||||
|
"""""""""""""""""""""""""""
|
||||||
|
|
||||||
|
``sbsa-ref`` is a static system that reports a very minimal devicetree to the
|
||||||
|
firmware for non-discoverable information about system components. This
|
||||||
|
includes both internal hardware and parts affected by the qemu command line
|
||||||
|
(i.e. CPUs and memory). As a result it must have a firmware specifically built
|
||||||
|
to expect a certain hardware layout (as you would in a real machine).
|
||||||
|
|
||||||
|
DeviceTree information
|
||||||
|
''''''''''''''''''''''
|
||||||
|
|
||||||
|
The devicetree provided by the board model to the firmware is not intended
|
||||||
|
to be a complete compliant DT. It currently reports:
|
||||||
|
|
||||||
|
- CPUs
|
||||||
|
- memory
|
||||||
|
- platform version
|
||||||
|
- GIC addresses
|
||||||
|
|
||||||
|
The platform version is only for informing platform firmware about
|
||||||
|
what kind of ``sbsa-ref`` board it is running on. It is neither
|
||||||
|
a QEMU versioned machine type nor a reflection of the level of the
|
||||||
|
SBSA/SystemReady SR support provided.
|
||||||
|
|
||||||
|
The ``machine-version-major`` value is updated when changes breaking
|
||||||
|
fw compatibility are introduced. The ``machine-version-minor`` value
|
||||||
|
is updated when features are added that don't break fw compatibility.
|
||||||
|
34
docs/system/arm/xenpvh.rst
Normal file
34
docs/system/arm/xenpvh.rst
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
XENPVH (``xenpvh``)
|
||||||
|
=========================================
|
||||||
|
This machine creates a IOREQ server to register/connect with Xen Hypervisor.
|
||||||
|
|
||||||
|
When TPM is enabled, this machine also creates a tpm-tis-device at a user input
|
||||||
|
tpm base address, adds a TPM emulator and connects to a swtpm application
|
||||||
|
running on host machine via chardev socket. This enables xenpvh to support TPM
|
||||||
|
functionalities for a guest domain.
|
||||||
|
|
||||||
|
More information about TPM use and installing swtpm linux application can be
|
||||||
|
found at: docs/specs/tpm.rst.
|
||||||
|
|
||||||
|
Example for starting swtpm on host machine:
|
||||||
|
.. code-block:: console
|
||||||
|
|
||||||
|
mkdir /tmp/vtpm2
|
||||||
|
swtpm socket --tpmstate dir=/tmp/vtpm2 \
|
||||||
|
--ctrl type=unixio,path=/tmp/vtpm2/swtpm-sock &
|
||||||
|
|
||||||
|
Sample QEMU xenpvh commands for running and connecting with Xen:
|
||||||
|
.. code-block:: console
|
||||||
|
|
||||||
|
qemu-system-aarch64 -xen-domid 1 \
|
||||||
|
-chardev socket,id=libxl-cmd,path=qmp-libxl-1,server=on,wait=off \
|
||||||
|
-mon chardev=libxl-cmd,mode=control \
|
||||||
|
-chardev socket,id=libxenstat-cmd,path=qmp-libxenstat-1,server=on,wait=off \
|
||||||
|
-mon chardev=libxenstat-cmd,mode=control \
|
||||||
|
-xen-attach -name guest0 -vnc none -display none -nographic \
|
||||||
|
-machine xenpvh -m 1301 \
|
||||||
|
-chardev socket,id=chrtpm,path=tmp/vtpm2/swtpm-sock \
|
||||||
|
-tpmdev emulator,id=tpm0,chardev=chrtpm -machine tpm-base-addr=0x0C000000
|
||||||
|
|
||||||
|
In above QEMU command, last two lines are for connecting xenpvh QEMU to swtpm
|
||||||
|
via chardev socket.
|
@ -34,6 +34,7 @@ Implemented devices:
|
|||||||
- DDR memory
|
- DDR memory
|
||||||
- BBRAM (36 bytes of Battery-backed RAM)
|
- BBRAM (36 bytes of Battery-backed RAM)
|
||||||
- eFUSE (3072 bytes of one-time field-programmable bit array)
|
- eFUSE (3072 bytes of one-time field-programmable bit array)
|
||||||
|
- 2 CANFDs
|
||||||
|
|
||||||
QEMU does not yet model any other devices, including the PL and the AI Engine.
|
QEMU does not yet model any other devices, including the PL and the AI Engine.
|
||||||
|
|
||||||
@ -224,3 +225,33 @@ To use a different index value, N, from default of 1, add:
|
|||||||
|
|
||||||
Better yet, do not use actual product data when running guest image
|
Better yet, do not use actual product data when running guest image
|
||||||
on this Xilinx Versal Virt board.
|
on this Xilinx Versal Virt board.
|
||||||
|
|
||||||
|
Using CANFDs for Versal Virt
|
||||||
|
""""""""""""""""""""""""""""
|
||||||
|
Versal CANFD controller is developed based on SocketCAN and QEMU CAN bus
|
||||||
|
implementation. Bus connection and socketCAN connection for each CAN module
|
||||||
|
can be set through command lines.
|
||||||
|
|
||||||
|
To connect both CANFD0 and CANFD1 on the same bus:
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
-object can-bus,id=canbus -machine canbus0=canbus -machine canbus1=canbus
|
||||||
|
|
||||||
|
To connect CANFD0 and CANFD1 to separate buses:
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
-object can-bus,id=canbus0 -object can-bus,id=canbus1 \
|
||||||
|
-machine canbus0=canbus0 -machine canbus1=canbus1
|
||||||
|
|
||||||
|
The SocketCAN interface can connect to a Physical or a Virtual CAN interfaces on
|
||||||
|
the host machine. Please check this document to learn about CAN interface on
|
||||||
|
Linux: docs/system/devices/can.rst
|
||||||
|
|
||||||
|
To connect CANFD0 and CANFD1 to host machine's CAN interface can0:
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
-object can-bus,id=canbus -machine canbus0=canbus -machine canbus1=canbus
|
||||||
|
-object can-host-socketcan,id=canhost0,if=can0,canbus=canbus
|
||||||
|
@ -38,13 +38,13 @@ system memory as defined by the ``-m`` argument.
|
|||||||
Example
|
Example
|
||||||
=======
|
=======
|
||||||
|
|
||||||
First start you daemon.
|
First start your daemon.
|
||||||
|
|
||||||
.. parsed-literal::
|
.. parsed-literal::
|
||||||
|
|
||||||
$ virtio-foo --socket-path=/var/run/foo.sock $OTHER_ARGS
|
$ virtio-foo --socket-path=/var/run/foo.sock $OTHER_ARGS
|
||||||
|
|
||||||
The you start your QEMU instance specifying the device, chardev and
|
Then you start your QEMU instance specifying the device, chardev and
|
||||||
memory objects.
|
memory objects.
|
||||||
|
|
||||||
.. parsed-literal::
|
.. parsed-literal::
|
||||||
|
@ -4,7 +4,7 @@ Multi-process QEMU
|
|||||||
==================
|
==================
|
||||||
|
|
||||||
This document describes how to configure and use multi-process qemu.
|
This document describes how to configure and use multi-process qemu.
|
||||||
For the design document refer to docs/devel/qemu-multiprocess.
|
For the design document refer to docs/devel/multi-process.rst.
|
||||||
|
|
||||||
1) Configuration
|
1) Configuration
|
||||||
----------------
|
----------------
|
||||||
|
@ -53,6 +53,37 @@ with the default OpenSBI firmware image as the -bios. It also supports
|
|||||||
the recommended RISC-V bootflow: U-Boot SPL (M-mode) loads OpenSBI fw_dynamic
|
the recommended RISC-V bootflow: U-Boot SPL (M-mode) loads OpenSBI fw_dynamic
|
||||||
firmware and U-Boot proper (S-mode), using the standard -bios functionality.
|
firmware and U-Boot proper (S-mode), using the standard -bios functionality.
|
||||||
|
|
||||||
|
Using flash devices
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
By default, the first flash device (pflash0) is expected to contain
|
||||||
|
S-mode firmware code. It can be configured as read-only, with the
|
||||||
|
second flash device (pflash1) available to store configuration data.
|
||||||
|
|
||||||
|
For example, booting edk2 looks like
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
$ qemu-system-riscv64 \
|
||||||
|
-blockdev node-name=pflash0,driver=file,read-only=on,filename=<edk2_code> \
|
||||||
|
-blockdev node-name=pflash1,driver=file,filename=<edk2_vars> \
|
||||||
|
-M virt,pflash0=pflash0,pflash1=pflash1 \
|
||||||
|
... other args ....
|
||||||
|
|
||||||
|
For TCG guests only, it is also possible to boot M-mode firmware from
|
||||||
|
the first flash device (pflash0) by additionally passing ``-bios
|
||||||
|
none``, as in
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
$ qemu-system-riscv64 \
|
||||||
|
-bios none \
|
||||||
|
-blockdev node-name=pflash0,driver=file,read-only=on,filename=<m_mode_code> \
|
||||||
|
-M virt,pflash0=pflash0 \
|
||||||
|
... other args ....
|
||||||
|
|
||||||
|
Firmware images used for pflash must be exactly 32 MiB in size.
|
||||||
|
|
||||||
Machine-specific options
|
Machine-specific options
|
||||||
------------------------
|
------------------------
|
||||||
|
|
||||||
|
@ -83,6 +83,7 @@ undocumented; you can get a complete list by running
|
|||||||
arm/versatile
|
arm/versatile
|
||||||
arm/vexpress
|
arm/vexpress
|
||||||
arm/aspeed
|
arm/aspeed
|
||||||
|
arm/bananapi_m2u.rst
|
||||||
arm/sabrelite
|
arm/sabrelite
|
||||||
arm/digic
|
arm/digic
|
||||||
arm/cubieboard
|
arm/cubieboard
|
||||||
@ -106,6 +107,7 @@ undocumented; you can get a complete list by running
|
|||||||
arm/stm32
|
arm/stm32
|
||||||
arm/virt
|
arm/virt
|
||||||
arm/xlnx-versal-virt
|
arm/xlnx-versal-virt
|
||||||
|
arm/xenpvh
|
||||||
|
|
||||||
Emulated CPU architecture support
|
Emulated CPU architecture support
|
||||||
=================================
|
=================================
|
||||||
|
@ -1,2 +1,2 @@
|
|||||||
softmmu_ss.add([files('dump.c', 'dump-hmp-cmds.c'), snappy, lzo])
|
system_ss.add([files('dump.c', 'dump-hmp-cmds.c'), snappy, lzo])
|
||||||
specific_ss.add(when: 'CONFIG_SOFTMMU', if_true: files('win_dump.c'))
|
specific_ss.add(when: 'CONFIG_SYSTEM_ONLY', if_true: files('win_dump.c'))
|
||||||
|
@ -1 +1 @@
|
|||||||
softmmu_ss.add(when: libbpf, if_true: files('ebpf_rss.c'), if_false: files('ebpf_rss-stub.c'))
|
system_ss.add(when: libbpf, if_true: files('ebpf_rss.c'), if_false: files('ebpf_rss-stub.c'))
|
||||||
|
@ -6,8 +6,8 @@ fsdev_ss.add(when: ['CONFIG_FSDEV_9P'], if_true: files(
|
|||||||
'9p-marshal.c',
|
'9p-marshal.c',
|
||||||
'qemu-fsdev.c',
|
'qemu-fsdev.c',
|
||||||
), if_false: files('qemu-fsdev-dummy.c'))
|
), if_false: files('qemu-fsdev-dummy.c'))
|
||||||
softmmu_ss.add_all(when: 'CONFIG_LINUX', if_true: fsdev_ss)
|
system_ss.add_all(when: 'CONFIG_LINUX', if_true: fsdev_ss)
|
||||||
softmmu_ss.add_all(when: 'CONFIG_DARWIN', if_true: fsdev_ss)
|
system_ss.add_all(when: 'CONFIG_DARWIN', if_true: fsdev_ss)
|
||||||
|
|
||||||
if have_virtfs_proxy_helper
|
if have_virtfs_proxy_helper
|
||||||
executable('virtfs-proxy-helper',
|
executable('virtfs-proxy-helper',
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
#include "qemu/xattr.h"
|
#include "qemu/xattr.h"
|
||||||
#include "9p-iov-marshal.h"
|
#include "9p-iov-marshal.h"
|
||||||
#include "hw/9pfs/9p-proxy.h"
|
#include "hw/9pfs/9p-proxy.h"
|
||||||
|
#include "hw/9pfs/9p-util.h"
|
||||||
#include "fsdev/9p-iov-marshal.h"
|
#include "fsdev/9p-iov-marshal.h"
|
||||||
|
|
||||||
#define PROGNAME "virtfs-proxy-helper"
|
#define PROGNAME "virtfs-proxy-helper"
|
||||||
@ -338,6 +339,28 @@ static void resetugid(int suid, int sgid)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Open regular file or directory. Attempts to open any special file are
|
||||||
|
* rejected.
|
||||||
|
*
|
||||||
|
* returns file descriptor or -1 on error
|
||||||
|
*/
|
||||||
|
static int open_regular(const char *pathname, int flags, mode_t mode)
|
||||||
|
{
|
||||||
|
int fd;
|
||||||
|
|
||||||
|
fd = open(pathname, flags, mode);
|
||||||
|
if (fd < 0) {
|
||||||
|
return fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (close_if_special_file(fd) < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return fd;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* send response in two parts
|
* send response in two parts
|
||||||
* 1) ProxyHeader
|
* 1) ProxyHeader
|
||||||
@ -682,7 +705,7 @@ static int do_create(struct iovec *iovec)
|
|||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
goto unmarshal_err_out;
|
goto unmarshal_err_out;
|
||||||
}
|
}
|
||||||
ret = open(path.data, flags, mode);
|
ret = open_regular(path.data, flags, mode);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
ret = -errno;
|
ret = -errno;
|
||||||
}
|
}
|
||||||
@ -707,7 +730,7 @@ static int do_open(struct iovec *iovec)
|
|||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
goto err_out;
|
goto err_out;
|
||||||
}
|
}
|
||||||
ret = open(path.data, flags);
|
ret = open_regular(path.data, flags, 0);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
ret = -errno;
|
ret = -errno;
|
||||||
}
|
}
|
||||||
|
@ -8,14 +8,14 @@
|
|||||||
# cflags so:
|
# cflags so:
|
||||||
|
|
||||||
gdb_user_ss = ss.source_set()
|
gdb_user_ss = ss.source_set()
|
||||||
gdb_softmmu_ss = ss.source_set()
|
gdb_system_ss = ss.source_set()
|
||||||
|
|
||||||
# We build two versions of gdbstub, one for each mode
|
# We build two versions of gdbstub, one for each mode
|
||||||
gdb_user_ss.add(files('gdbstub.c', 'user.c'))
|
gdb_user_ss.add(files('gdbstub.c', 'user.c'))
|
||||||
gdb_softmmu_ss.add(files('gdbstub.c', 'softmmu.c'))
|
gdb_system_ss.add(files('gdbstub.c', 'softmmu.c'))
|
||||||
|
|
||||||
gdb_user_ss = gdb_user_ss.apply(config_host, strict: false)
|
gdb_user_ss = gdb_user_ss.apply(config_host, strict: false)
|
||||||
gdb_softmmu_ss = gdb_softmmu_ss.apply(config_host, strict: false)
|
gdb_system_ss = gdb_system_ss.apply(config_host, strict: false)
|
||||||
|
|
||||||
libgdb_user = static_library('gdb_user',
|
libgdb_user = static_library('gdb_user',
|
||||||
gdb_user_ss.sources() + genh,
|
gdb_user_ss.sources() + genh,
|
||||||
@ -24,14 +24,14 @@ libgdb_user = static_library('gdb_user',
|
|||||||
build_by_default: have_user)
|
build_by_default: have_user)
|
||||||
|
|
||||||
libgdb_softmmu = static_library('gdb_softmmu',
|
libgdb_softmmu = static_library('gdb_softmmu',
|
||||||
gdb_softmmu_ss.sources() + genh,
|
gdb_system_ss.sources() + genh,
|
||||||
name_suffix: 'fa',
|
name_suffix: 'fa',
|
||||||
build_by_default: have_system)
|
build_by_default: have_system)
|
||||||
|
|
||||||
gdb_user = declare_dependency(link_whole: libgdb_user)
|
gdb_user = declare_dependency(link_whole: libgdb_user)
|
||||||
user_ss.add(gdb_user)
|
user_ss.add(gdb_user)
|
||||||
gdb_softmmu = declare_dependency(link_whole: libgdb_softmmu)
|
gdb_softmmu = declare_dependency(link_whole: libgdb_softmmu)
|
||||||
softmmu_ss.add(gdb_softmmu)
|
system_ss.add(gdb_softmmu)
|
||||||
|
|
||||||
common_ss.add(files('syscalls.c'))
|
common_ss.add(files('syscalls.c'))
|
||||||
|
|
||||||
|
@ -8,12 +8,19 @@
|
|||||||
* atomic primitive is meant to provide.
|
* atomic primitive is meant to provide.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef AARCH64_ATOMIC128_LDST_H
|
#ifndef X86_64_ATOMIC128_LDST_H
|
||||||
#define AARCH64_ATOMIC128_LDST_H
|
#define X86_64_ATOMIC128_LDST_H
|
||||||
|
|
||||||
#ifdef CONFIG_INT128_TYPE
|
#ifdef CONFIG_INT128_TYPE
|
||||||
#include "host/cpuinfo.h"
|
#include "host/cpuinfo.h"
|
||||||
#include "tcg/debug-assert.h"
|
#include "tcg/debug-assert.h"
|
||||||
|
#include <immintrin.h>
|
||||||
|
|
||||||
|
typedef union {
|
||||||
|
__m128i v;
|
||||||
|
__int128_t i;
|
||||||
|
Int128 s;
|
||||||
|
} X86Int128Union;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Through clang 16, with -mcx16, __atomic_load_n is incorrectly
|
* Through clang 16, with -mcx16, __atomic_load_n is incorrectly
|
||||||
@ -25,10 +32,10 @@
|
|||||||
|
|
||||||
static inline Int128 atomic16_read_ro(const Int128 *ptr)
|
static inline Int128 atomic16_read_ro(const Int128 *ptr)
|
||||||
{
|
{
|
||||||
Int128Alias r;
|
X86Int128Union r;
|
||||||
|
|
||||||
tcg_debug_assert(HAVE_ATOMIC128_RO);
|
tcg_debug_assert(HAVE_ATOMIC128_RO);
|
||||||
asm("vmovdqa %1, %0" : "=x" (r.i) : "m" (*ptr));
|
asm("vmovdqa %1, %0" : "=x" (r.v) : "m" (*ptr));
|
||||||
|
|
||||||
return r.s;
|
return r.s;
|
||||||
}
|
}
|
||||||
@ -36,10 +43,10 @@ static inline Int128 atomic16_read_ro(const Int128 *ptr)
|
|||||||
static inline Int128 atomic16_read_rw(Int128 *ptr)
|
static inline Int128 atomic16_read_rw(Int128 *ptr)
|
||||||
{
|
{
|
||||||
__int128_t *ptr_align = __builtin_assume_aligned(ptr, 16);
|
__int128_t *ptr_align = __builtin_assume_aligned(ptr, 16);
|
||||||
Int128Alias r;
|
X86Int128Union r;
|
||||||
|
|
||||||
if (HAVE_ATOMIC128_RO) {
|
if (HAVE_ATOMIC128_RO) {
|
||||||
asm("vmovdqa %1, %0" : "=x" (r.i) : "m" (*ptr_align));
|
asm("vmovdqa %1, %0" : "=x" (r.v) : "m" (*ptr_align));
|
||||||
} else {
|
} else {
|
||||||
r.i = __sync_val_compare_and_swap_16(ptr_align, 0, 0);
|
r.i = __sync_val_compare_and_swap_16(ptr_align, 0, 0);
|
||||||
}
|
}
|
||||||
@ -49,10 +56,10 @@ static inline Int128 atomic16_read_rw(Int128 *ptr)
|
|||||||
static inline void atomic16_set(Int128 *ptr, Int128 val)
|
static inline void atomic16_set(Int128 *ptr, Int128 val)
|
||||||
{
|
{
|
||||||
__int128_t *ptr_align = __builtin_assume_aligned(ptr, 16);
|
__int128_t *ptr_align = __builtin_assume_aligned(ptr, 16);
|
||||||
Int128Alias new = { .s = val };
|
X86Int128Union new = { .s = val };
|
||||||
|
|
||||||
if (HAVE_ATOMIC128_RO) {
|
if (HAVE_ATOMIC128_RO) {
|
||||||
asm("vmovdqa %1, %0" : "=m"(*ptr_align) : "x" (new.i));
|
asm("vmovdqa %1, %0" : "=m"(*ptr_align) : "x" (new.v));
|
||||||
} else {
|
} else {
|
||||||
__int128_t old;
|
__int128_t old;
|
||||||
do {
|
do {
|
||||||
@ -65,4 +72,4 @@ static inline void atomic16_set(Int128 *ptr, Int128 val)
|
|||||||
#include "host/include/generic/host/atomic128-ldst.h"
|
#include "host/include/generic/host/atomic128-ldst.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* AARCH64_ATOMIC128_LDST_H */
|
#endif /* X86_64_ATOMIC128_LDST_H */
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
#define X86_64_LOAD_EXTRACT_AL16_AL8_H
|
#define X86_64_LOAD_EXTRACT_AL16_AL8_H
|
||||||
|
|
||||||
#ifdef CONFIG_INT128_TYPE
|
#ifdef CONFIG_INT128_TYPE
|
||||||
#include "host/cpuinfo.h"
|
#include "host/atomic128-ldst.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* load_atom_extract_al16_or_al8:
|
* load_atom_extract_al16_or_al8:
|
||||||
@ -26,7 +26,7 @@ load_atom_extract_al16_or_al8(void *pv, int s)
|
|||||||
uintptr_t pi = (uintptr_t)pv;
|
uintptr_t pi = (uintptr_t)pv;
|
||||||
__int128_t *ptr_align = (__int128_t *)(pi & ~7);
|
__int128_t *ptr_align = (__int128_t *)(pi & ~7);
|
||||||
int shr = (pi & 7) * 8;
|
int shr = (pi & 7) * 8;
|
||||||
Int128Alias r;
|
X86Int128Union r;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ptr_align % 16 is now only 0 or 8.
|
* ptr_align % 16 is now only 0 or 8.
|
||||||
@ -35,9 +35,9 @@ load_atom_extract_al16_or_al8(void *pv, int s)
|
|||||||
* when ptr_align % 16 == 0 for 16-byte atomicity.
|
* when ptr_align % 16 == 0 for 16-byte atomicity.
|
||||||
*/
|
*/
|
||||||
if ((cpuinfo & CPUINFO_ATOMIC_VMOVDQU) || (pi & 8)) {
|
if ((cpuinfo & CPUINFO_ATOMIC_VMOVDQU) || (pi & 8)) {
|
||||||
asm("vmovdqu %1, %0" : "=x" (r.i) : "m" (*ptr_align));
|
asm("vmovdqu %1, %0" : "=x" (r.v) : "m" (*ptr_align));
|
||||||
} else {
|
} else {
|
||||||
asm("vmovdqa %1, %0" : "=x" (r.i) : "m" (*ptr_align));
|
asm("vmovdqa %1, %0" : "=x" (r.v) : "m" (*ptr_align));
|
||||||
}
|
}
|
||||||
return int128_getlo(int128_urshift(r.s, shr));
|
return int128_getlo(int128_urshift(r.s, shr));
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,8 @@
|
|||||||
#ifndef QEMU_9P_UTIL_H
|
#ifndef QEMU_9P_UTIL_H
|
||||||
#define QEMU_9P_UTIL_H
|
#define QEMU_9P_UTIL_H
|
||||||
|
|
||||||
|
#include "qemu/error-report.h"
|
||||||
|
|
||||||
#ifdef O_PATH
|
#ifdef O_PATH
|
||||||
#define O_PATH_9P_UTIL O_PATH
|
#define O_PATH_9P_UTIL O_PATH
|
||||||
#else
|
#else
|
||||||
@ -95,6 +97,7 @@ static inline int errno_to_dotl(int err) {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define qemu_openat openat
|
#define qemu_openat openat
|
||||||
|
#define qemu_fstat fstat
|
||||||
#define qemu_fstatat fstatat
|
#define qemu_fstatat fstatat
|
||||||
#define qemu_mkdirat mkdirat
|
#define qemu_mkdirat mkdirat
|
||||||
#define qemu_renameat renameat
|
#define qemu_renameat renameat
|
||||||
@ -108,6 +111,38 @@ static inline void close_preserve_errno(int fd)
|
|||||||
errno = serrno;
|
errno = serrno;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* close_if_special_file() - Close @fd if neither regular file nor directory.
|
||||||
|
*
|
||||||
|
* @fd: file descriptor of open file
|
||||||
|
* Return: 0 on regular file or directory, -1 otherwise
|
||||||
|
*
|
||||||
|
* CVE-2023-2861: Prohibit opening any special file directly on host
|
||||||
|
* (especially device files), as a compromised client could potentially gain
|
||||||
|
* access outside exported tree under certain, unsafe setups. We expect
|
||||||
|
* client to handle I/O on special files exclusively on guest side.
|
||||||
|
*/
|
||||||
|
static inline int close_if_special_file(int fd)
|
||||||
|
{
|
||||||
|
struct stat stbuf;
|
||||||
|
|
||||||
|
if (qemu_fstat(fd, &stbuf) < 0) {
|
||||||
|
close_preserve_errno(fd);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (!S_ISREG(stbuf.st_mode) && !S_ISDIR(stbuf.st_mode)) {
|
||||||
|
error_report_once(
|
||||||
|
"9p: broken or compromised client detected; attempt to open "
|
||||||
|
"special file (i.e. neither regular file, nor directory)"
|
||||||
|
);
|
||||||
|
close(fd);
|
||||||
|
errno = ENXIO;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static inline int openat_dir(int dirfd, const char *name)
|
static inline int openat_dir(int dirfd, const char *name)
|
||||||
{
|
{
|
||||||
return qemu_openat(dirfd, name,
|
return qemu_openat(dirfd, name,
|
||||||
@ -142,6 +177,10 @@ again:
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (close_if_special_file(fd) < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
serrno = errno;
|
serrno = errno;
|
||||||
/* O_NONBLOCK was only needed to open the file. Let's drop it. We don't
|
/* O_NONBLOCK was only needed to open the file. Let's drop it. We don't
|
||||||
* do that with O_PATH since fcntl(F_SETFL) isn't supported, and openat()
|
* do that with O_PATH since fcntl(F_SETFL) isn't supported, and openat()
|
||||||
|
@ -16,6 +16,6 @@ fs_ss.add(files(
|
|||||||
fs_ss.add(when: 'CONFIG_LINUX', if_true: files('9p-util-linux.c'))
|
fs_ss.add(when: 'CONFIG_LINUX', if_true: files('9p-util-linux.c'))
|
||||||
fs_ss.add(when: 'CONFIG_DARWIN', if_true: files('9p-util-darwin.c'))
|
fs_ss.add(when: 'CONFIG_DARWIN', if_true: files('9p-util-darwin.c'))
|
||||||
fs_ss.add(when: 'CONFIG_XEN_BUS', if_true: files('xen-9p-backend.c'))
|
fs_ss.add(when: 'CONFIG_XEN_BUS', if_true: files('xen-9p-backend.c'))
|
||||||
softmmu_ss.add_all(when: 'CONFIG_FSDEV_9P', if_true: fs_ss)
|
system_ss.add_all(when: 'CONFIG_FSDEV_9P', if_true: fs_ss)
|
||||||
|
|
||||||
specific_ss.add(when: 'CONFIG_VIRTIO_9P', if_true: files('virtio-9p-device.c'))
|
specific_ss.add(when: 'CONFIG_VIRTIO_9P', if_true: files('virtio-9p-device.c'))
|
||||||
|
@ -30,12 +30,12 @@ acpi_ss.add(when: 'CONFIG_PC', if_false: files('acpi-x86-stub.c'))
|
|||||||
if have_tpm
|
if have_tpm
|
||||||
acpi_ss.add(files('tpm.c'))
|
acpi_ss.add(files('tpm.c'))
|
||||||
endif
|
endif
|
||||||
softmmu_ss.add(when: 'CONFIG_ACPI', if_false: files('acpi-stub.c', 'aml-build-stub.c', 'ghes-stub.c', 'acpi_interface.c'))
|
system_ss.add(when: 'CONFIG_ACPI', if_false: files('acpi-stub.c', 'aml-build-stub.c', 'ghes-stub.c', 'acpi_interface.c'))
|
||||||
softmmu_ss.add(when: 'CONFIG_ACPI_PCI_BRIDGE', if_false: files('pci-bridge-stub.c'))
|
system_ss.add(when: 'CONFIG_ACPI_PCI_BRIDGE', if_false: files('pci-bridge-stub.c'))
|
||||||
softmmu_ss.add_all(when: 'CONFIG_ACPI', if_true: acpi_ss)
|
system_ss.add_all(when: 'CONFIG_ACPI', if_true: acpi_ss)
|
||||||
softmmu_ss.add(when: 'CONFIG_ALL', if_true: files('acpi-stub.c', 'aml-build-stub.c',
|
system_ss.add(when: 'CONFIG_ALL', if_true: files('acpi-stub.c', 'aml-build-stub.c',
|
||||||
'acpi-x86-stub.c', 'ipmi-stub.c', 'ghes-stub.c',
|
'acpi-x86-stub.c', 'ipmi-stub.c', 'ghes-stub.c',
|
||||||
'acpi-mem-hotplug-stub.c', 'acpi-cpu-hotplug-stub.c',
|
'acpi-mem-hotplug-stub.c', 'acpi-cpu-hotplug-stub.c',
|
||||||
'acpi-pci-hotplug-stub.c', 'acpi-nvdimm-stub.c',
|
'acpi-pci-hotplug-stub.c', 'acpi-nvdimm-stub.c',
|
||||||
'cxl-stub.c', 'pci-bridge-stub.c'))
|
'cxl-stub.c', 'pci-bridge-stub.c'))
|
||||||
softmmu_ss.add(files('acpi-qmp-cmds.c'))
|
system_ss.add(files('acpi-qmp-cmds.c'))
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
softmmu_ss.add(when: 'CONFIG_STM32F2XX_ADC', if_true: files('stm32f2xx_adc.c'))
|
system_ss.add(when: 'CONFIG_STM32F2XX_ADC', if_true: files('stm32f2xx_adc.c'))
|
||||||
softmmu_ss.add(when: 'CONFIG_ASPEED_SOC', if_true: files('aspeed_adc.c'))
|
system_ss.add(when: 'CONFIG_ASPEED_SOC', if_true: files('aspeed_adc.c'))
|
||||||
softmmu_ss.add(when: 'CONFIG_NPCM7XX', if_true: files('npcm7xx_adc.c'))
|
system_ss.add(when: 'CONFIG_NPCM7XX', if_true: files('npcm7xx_adc.c'))
|
||||||
softmmu_ss.add(when: 'CONFIG_ZYNQ', if_true: files('zynq-xadc.c'))
|
system_ss.add(when: 'CONFIG_ZYNQ', if_true: files('zynq-xadc.c'))
|
||||||
softmmu_ss.add(when: 'CONFIG_MAX111X', if_true: files('max111x.c'))
|
system_ss.add(when: 'CONFIG_MAX111X', if_true: files('max111x.c'))
|
||||||
|
@ -268,6 +268,7 @@ config SBSA_REF
|
|||||||
select PL061 # GPIO
|
select PL061 # GPIO
|
||||||
select USB_EHCI_SYSBUS
|
select USB_EHCI_SYSBUS
|
||||||
select WDT_SBSA
|
select WDT_SBSA
|
||||||
|
select BOCHS_DISPLAY
|
||||||
|
|
||||||
config SABRELITE
|
config SABRELITE
|
||||||
bool
|
bool
|
||||||
@ -383,7 +384,7 @@ config ALLWINNER_A10
|
|||||||
select ALLWINNER_WDT
|
select ALLWINNER_WDT
|
||||||
select ALLWINNER_EMAC
|
select ALLWINNER_EMAC
|
||||||
select ALLWINNER_I2C
|
select ALLWINNER_I2C
|
||||||
select AXP209_PMU
|
select AXP2XX_PMU
|
||||||
select SERIAL
|
select SERIAL
|
||||||
select UNIMP
|
select UNIMP
|
||||||
|
|
||||||
@ -403,6 +404,18 @@ config ALLWINNER_H3
|
|||||||
select USB_EHCI_SYSBUS
|
select USB_EHCI_SYSBUS
|
||||||
select SD
|
select SD
|
||||||
|
|
||||||
|
config ALLWINNER_R40
|
||||||
|
bool
|
||||||
|
default y if TCG && ARM
|
||||||
|
select ALLWINNER_SRAMC
|
||||||
|
select ALLWINNER_A10_PIT
|
||||||
|
select AXP2XX_PMU
|
||||||
|
select SERIAL
|
||||||
|
select ARM_TIMER
|
||||||
|
select ARM_GIC
|
||||||
|
select UNIMP
|
||||||
|
select SD
|
||||||
|
|
||||||
config RASPI
|
config RASPI
|
||||||
bool
|
bool
|
||||||
default y
|
default y
|
||||||
|
526
hw/arm/allwinner-r40.c
Normal file
526
hw/arm/allwinner-r40.c
Normal file
@ -0,0 +1,526 @@
|
|||||||
|
/*
|
||||||
|
* Allwinner R40/A40i/T3 System on Chip emulation
|
||||||
|
*
|
||||||
|
* Copyright (C) 2023 qianfan Zhao <qianfanguijin@163.com>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "qemu/osdep.h"
|
||||||
|
#include "qapi/error.h"
|
||||||
|
#include "qemu/error-report.h"
|
||||||
|
#include "qemu/bswap.h"
|
||||||
|
#include "qemu/module.h"
|
||||||
|
#include "qemu/units.h"
|
||||||
|
#include "hw/qdev-core.h"
|
||||||
|
#include "hw/sysbus.h"
|
||||||
|
#include "hw/char/serial.h"
|
||||||
|
#include "hw/misc/unimp.h"
|
||||||
|
#include "hw/usb/hcd-ehci.h"
|
||||||
|
#include "hw/loader.h"
|
||||||
|
#include "sysemu/sysemu.h"
|
||||||
|
#include "hw/arm/allwinner-r40.h"
|
||||||
|
#include "hw/misc/allwinner-r40-dramc.h"
|
||||||
|
|
||||||
|
/* Memory map */
|
||||||
|
const hwaddr allwinner_r40_memmap[] = {
|
||||||
|
[AW_R40_DEV_SRAM_A1] = 0x00000000,
|
||||||
|
[AW_R40_DEV_SRAM_A2] = 0x00004000,
|
||||||
|
[AW_R40_DEV_SRAM_A3] = 0x00008000,
|
||||||
|
[AW_R40_DEV_SRAM_A4] = 0x0000b400,
|
||||||
|
[AW_R40_DEV_SRAMC] = 0x01c00000,
|
||||||
|
[AW_R40_DEV_EMAC] = 0x01c0b000,
|
||||||
|
[AW_R40_DEV_MMC0] = 0x01c0f000,
|
||||||
|
[AW_R40_DEV_MMC1] = 0x01c10000,
|
||||||
|
[AW_R40_DEV_MMC2] = 0x01c11000,
|
||||||
|
[AW_R40_DEV_MMC3] = 0x01c12000,
|
||||||
|
[AW_R40_DEV_CCU] = 0x01c20000,
|
||||||
|
[AW_R40_DEV_PIT] = 0x01c20c00,
|
||||||
|
[AW_R40_DEV_UART0] = 0x01c28000,
|
||||||
|
[AW_R40_DEV_UART1] = 0x01c28400,
|
||||||
|
[AW_R40_DEV_UART2] = 0x01c28800,
|
||||||
|
[AW_R40_DEV_UART3] = 0x01c28c00,
|
||||||
|
[AW_R40_DEV_UART4] = 0x01c29000,
|
||||||
|
[AW_R40_DEV_UART5] = 0x01c29400,
|
||||||
|
[AW_R40_DEV_UART6] = 0x01c29800,
|
||||||
|
[AW_R40_DEV_UART7] = 0x01c29c00,
|
||||||
|
[AW_R40_DEV_TWI0] = 0x01c2ac00,
|
||||||
|
[AW_R40_DEV_GMAC] = 0x01c50000,
|
||||||
|
[AW_R40_DEV_DRAMCOM] = 0x01c62000,
|
||||||
|
[AW_R40_DEV_DRAMCTL] = 0x01c63000,
|
||||||
|
[AW_R40_DEV_DRAMPHY] = 0x01c65000,
|
||||||
|
[AW_R40_DEV_GIC_DIST] = 0x01c81000,
|
||||||
|
[AW_R40_DEV_GIC_CPU] = 0x01c82000,
|
||||||
|
[AW_R40_DEV_GIC_HYP] = 0x01c84000,
|
||||||
|
[AW_R40_DEV_GIC_VCPU] = 0x01c86000,
|
||||||
|
[AW_R40_DEV_SDRAM] = 0x40000000
|
||||||
|
};
|
||||||
|
|
||||||
|
/* List of unimplemented devices */
|
||||||
|
struct AwR40Unimplemented {
|
||||||
|
const char *device_name;
|
||||||
|
hwaddr base;
|
||||||
|
hwaddr size;
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct AwR40Unimplemented r40_unimplemented[] = {
|
||||||
|
{ "d-engine", 0x01000000, 4 * MiB },
|
||||||
|
{ "d-inter", 0x01400000, 128 * KiB },
|
||||||
|
{ "dma", 0x01c02000, 4 * KiB },
|
||||||
|
{ "nfdc", 0x01c03000, 4 * KiB },
|
||||||
|
{ "ts", 0x01c04000, 4 * KiB },
|
||||||
|
{ "spi0", 0x01c05000, 4 * KiB },
|
||||||
|
{ "spi1", 0x01c06000, 4 * KiB },
|
||||||
|
{ "cs0", 0x01c09000, 4 * KiB },
|
||||||
|
{ "keymem", 0x01c0a000, 4 * KiB },
|
||||||
|
{ "usb0-otg", 0x01c13000, 4 * KiB },
|
||||||
|
{ "usb0-host", 0x01c14000, 4 * KiB },
|
||||||
|
{ "crypto", 0x01c15000, 4 * KiB },
|
||||||
|
{ "spi2", 0x01c17000, 4 * KiB },
|
||||||
|
{ "sata", 0x01c18000, 4 * KiB },
|
||||||
|
{ "usb1-host", 0x01c19000, 4 * KiB },
|
||||||
|
{ "sid", 0x01c1b000, 4 * KiB },
|
||||||
|
{ "usb2-host", 0x01c1c000, 4 * KiB },
|
||||||
|
{ "cs1", 0x01c1d000, 4 * KiB },
|
||||||
|
{ "spi3", 0x01c1f000, 4 * KiB },
|
||||||
|
{ "rtc", 0x01c20400, 1 * KiB },
|
||||||
|
{ "pio", 0x01c20800, 1 * KiB },
|
||||||
|
{ "owa", 0x01c21000, 1 * KiB },
|
||||||
|
{ "ac97", 0x01c21400, 1 * KiB },
|
||||||
|
{ "cir0", 0x01c21800, 1 * KiB },
|
||||||
|
{ "cir1", 0x01c21c00, 1 * KiB },
|
||||||
|
{ "pcm0", 0x01c22000, 1 * KiB },
|
||||||
|
{ "pcm1", 0x01c22400, 1 * KiB },
|
||||||
|
{ "pcm2", 0x01c22800, 1 * KiB },
|
||||||
|
{ "audio", 0x01c22c00, 1 * KiB },
|
||||||
|
{ "keypad", 0x01c23000, 1 * KiB },
|
||||||
|
{ "pwm", 0x01c23400, 1 * KiB },
|
||||||
|
{ "keyadc", 0x01c24400, 1 * KiB },
|
||||||
|
{ "ths", 0x01c24c00, 1 * KiB },
|
||||||
|
{ "rtp", 0x01c25000, 1 * KiB },
|
||||||
|
{ "pmu", 0x01c25400, 1 * KiB },
|
||||||
|
{ "cpu-cfg", 0x01c25c00, 1 * KiB },
|
||||||
|
{ "uart0", 0x01c28000, 1 * KiB },
|
||||||
|
{ "uart1", 0x01c28400, 1 * KiB },
|
||||||
|
{ "uart2", 0x01c28800, 1 * KiB },
|
||||||
|
{ "uart3", 0x01c28c00, 1 * KiB },
|
||||||
|
{ "uart4", 0x01c29000, 1 * KiB },
|
||||||
|
{ "uart5", 0x01c29400, 1 * KiB },
|
||||||
|
{ "uart6", 0x01c29800, 1 * KiB },
|
||||||
|
{ "uart7", 0x01c29c00, 1 * KiB },
|
||||||
|
{ "ps20", 0x01c2a000, 1 * KiB },
|
||||||
|
{ "ps21", 0x01c2a400, 1 * KiB },
|
||||||
|
{ "twi1", 0x01c2b000, 1 * KiB },
|
||||||
|
{ "twi2", 0x01c2b400, 1 * KiB },
|
||||||
|
{ "twi3", 0x01c2b800, 1 * KiB },
|
||||||
|
{ "twi4", 0x01c2c000, 1 * KiB },
|
||||||
|
{ "scr", 0x01c2c400, 1 * KiB },
|
||||||
|
{ "tvd-top", 0x01c30000, 4 * KiB },
|
||||||
|
{ "tvd0", 0x01c31000, 4 * KiB },
|
||||||
|
{ "tvd1", 0x01c32000, 4 * KiB },
|
||||||
|
{ "tvd2", 0x01c33000, 4 * KiB },
|
||||||
|
{ "tvd3", 0x01c34000, 4 * KiB },
|
||||||
|
{ "gpu", 0x01c40000, 64 * KiB },
|
||||||
|
{ "hstmr", 0x01c60000, 4 * KiB },
|
||||||
|
{ "tcon-top", 0x01c70000, 4 * KiB },
|
||||||
|
{ "lcd0", 0x01c71000, 4 * KiB },
|
||||||
|
{ "lcd1", 0x01c72000, 4 * KiB },
|
||||||
|
{ "tv0", 0x01c73000, 4 * KiB },
|
||||||
|
{ "tv1", 0x01c74000, 4 * KiB },
|
||||||
|
{ "tve-top", 0x01c90000, 16 * KiB },
|
||||||
|
{ "tve0", 0x01c94000, 16 * KiB },
|
||||||
|
{ "tve1", 0x01c98000, 16 * KiB },
|
||||||
|
{ "mipi_dsi", 0x01ca0000, 4 * KiB },
|
||||||
|
{ "mipi_dphy", 0x01ca1000, 4 * KiB },
|
||||||
|
{ "ve", 0x01d00000, 1024 * KiB },
|
||||||
|
{ "mp", 0x01e80000, 128 * KiB },
|
||||||
|
{ "hdmi", 0x01ee0000, 128 * KiB },
|
||||||
|
{ "prcm", 0x01f01400, 1 * KiB },
|
||||||
|
{ "debug", 0x3f500000, 64 * KiB },
|
||||||
|
{ "cpubist", 0x3f501000, 4 * KiB },
|
||||||
|
{ "dcu", 0x3fff0000, 64 * KiB },
|
||||||
|
{ "hstmr", 0x01c60000, 4 * KiB },
|
||||||
|
{ "brom", 0xffff0000, 36 * KiB }
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Per Processor Interrupts */
|
||||||
|
enum {
|
||||||
|
AW_R40_GIC_PPI_MAINT = 9,
|
||||||
|
AW_R40_GIC_PPI_HYPTIMER = 10,
|
||||||
|
AW_R40_GIC_PPI_VIRTTIMER = 11,
|
||||||
|
AW_R40_GIC_PPI_SECTIMER = 13,
|
||||||
|
AW_R40_GIC_PPI_PHYSTIMER = 14
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Shared Processor Interrupts */
|
||||||
|
enum {
|
||||||
|
AW_R40_GIC_SPI_UART0 = 1,
|
||||||
|
AW_R40_GIC_SPI_UART1 = 2,
|
||||||
|
AW_R40_GIC_SPI_UART2 = 3,
|
||||||
|
AW_R40_GIC_SPI_UART3 = 4,
|
||||||
|
AW_R40_GIC_SPI_TWI0 = 7,
|
||||||
|
AW_R40_GIC_SPI_UART4 = 17,
|
||||||
|
AW_R40_GIC_SPI_UART5 = 18,
|
||||||
|
AW_R40_GIC_SPI_UART6 = 19,
|
||||||
|
AW_R40_GIC_SPI_UART7 = 20,
|
||||||
|
AW_R40_GIC_SPI_TIMER0 = 22,
|
||||||
|
AW_R40_GIC_SPI_TIMER1 = 23,
|
||||||
|
AW_R40_GIC_SPI_MMC0 = 32,
|
||||||
|
AW_R40_GIC_SPI_MMC1 = 33,
|
||||||
|
AW_R40_GIC_SPI_MMC2 = 34,
|
||||||
|
AW_R40_GIC_SPI_MMC3 = 35,
|
||||||
|
AW_R40_GIC_SPI_EMAC = 55,
|
||||||
|
AW_R40_GIC_SPI_GMAC = 85,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Allwinner R40 general constants */
|
||||||
|
enum {
|
||||||
|
AW_R40_GIC_NUM_SPI = 128
|
||||||
|
};
|
||||||
|
|
||||||
|
#define BOOT0_MAGIC "eGON.BT0"
|
||||||
|
|
||||||
|
/* The low 8-bits of the 'boot_media' field in the SPL header */
|
||||||
|
#define SUNXI_BOOTED_FROM_MMC0 0
|
||||||
|
#define SUNXI_BOOTED_FROM_NAND 1
|
||||||
|
#define SUNXI_BOOTED_FROM_MMC2 2
|
||||||
|
#define SUNXI_BOOTED_FROM_SPI 3
|
||||||
|
|
||||||
|
struct boot_file_head {
|
||||||
|
uint32_t b_instruction;
|
||||||
|
uint8_t magic[8];
|
||||||
|
uint32_t check_sum;
|
||||||
|
uint32_t length;
|
||||||
|
uint32_t pub_head_size;
|
||||||
|
uint32_t fel_script_address;
|
||||||
|
uint32_t fel_uEnv_length;
|
||||||
|
uint32_t dt_name_offset;
|
||||||
|
uint32_t dram_size;
|
||||||
|
uint32_t boot_media;
|
||||||
|
uint32_t string_pool[13];
|
||||||
|
};
|
||||||
|
|
||||||
|
bool allwinner_r40_bootrom_setup(AwR40State *s, BlockBackend *blk, int unit)
|
||||||
|
{
|
||||||
|
const int64_t rom_size = 32 * KiB;
|
||||||
|
g_autofree uint8_t *buffer = g_new0(uint8_t, rom_size);
|
||||||
|
struct boot_file_head *head = (struct boot_file_head *)buffer;
|
||||||
|
|
||||||
|
if (blk_pread(blk, 8 * KiB, rom_size, buffer, 0) < 0) {
|
||||||
|
error_setg(&error_fatal, "%s: failed to read BlockBackend data",
|
||||||
|
__func__);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* we only check the magic string here. */
|
||||||
|
if (memcmp(head->magic, BOOT0_MAGIC, sizeof(head->magic))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Simulate the behavior of the bootROM, it will change the boot_media
|
||||||
|
* flag to indicate where the chip is booting from. R40 can boot from
|
||||||
|
* mmc0 or mmc2, the default value of boot_media is zero
|
||||||
|
* (SUNXI_BOOTED_FROM_MMC0), let's fix this flag when it is booting from
|
||||||
|
* the others.
|
||||||
|
*/
|
||||||
|
if (unit == 2) {
|
||||||
|
head->boot_media = cpu_to_le32(SUNXI_BOOTED_FROM_MMC2);
|
||||||
|
} else {
|
||||||
|
head->boot_media = cpu_to_le32(SUNXI_BOOTED_FROM_MMC0);
|
||||||
|
}
|
||||||
|
|
||||||
|
rom_add_blob("allwinner-r40.bootrom", buffer, rom_size,
|
||||||
|
rom_size, s->memmap[AW_R40_DEV_SRAM_A1],
|
||||||
|
NULL, NULL, NULL, NULL, false);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void allwinner_r40_init(Object *obj)
|
||||||
|
{
|
||||||
|
static const char *mmc_names[AW_R40_NUM_MMCS] = {
|
||||||
|
"mmc0", "mmc1", "mmc2", "mmc3"
|
||||||
|
};
|
||||||
|
AwR40State *s = AW_R40(obj);
|
||||||
|
|
||||||
|
s->memmap = allwinner_r40_memmap;
|
||||||
|
|
||||||
|
for (int i = 0; i < AW_R40_NUM_CPUS; i++) {
|
||||||
|
object_initialize_child(obj, "cpu[*]", &s->cpus[i],
|
||||||
|
ARM_CPU_TYPE_NAME("cortex-a7"));
|
||||||
|
}
|
||||||
|
|
||||||
|
object_initialize_child(obj, "gic", &s->gic, TYPE_ARM_GIC);
|
||||||
|
|
||||||
|
object_initialize_child(obj, "timer", &s->timer, TYPE_AW_A10_PIT);
|
||||||
|
object_property_add_alias(obj, "clk0-freq", OBJECT(&s->timer),
|
||||||
|
"clk0-freq");
|
||||||
|
object_property_add_alias(obj, "clk1-freq", OBJECT(&s->timer),
|
||||||
|
"clk1-freq");
|
||||||
|
|
||||||
|
object_initialize_child(obj, "ccu", &s->ccu, TYPE_AW_R40_CCU);
|
||||||
|
|
||||||
|
for (int i = 0; i < AW_R40_NUM_MMCS; i++) {
|
||||||
|
object_initialize_child(obj, mmc_names[i], &s->mmc[i],
|
||||||
|
TYPE_AW_SDHOST_SUN50I_A64);
|
||||||
|
}
|
||||||
|
|
||||||
|
object_initialize_child(obj, "twi0", &s->i2c0, TYPE_AW_I2C_SUN6I);
|
||||||
|
|
||||||
|
object_initialize_child(obj, "emac", &s->emac, TYPE_AW_EMAC);
|
||||||
|
object_initialize_child(obj, "gmac", &s->gmac, TYPE_AW_SUN8I_EMAC);
|
||||||
|
object_property_add_alias(obj, "gmac-phy-addr",
|
||||||
|
OBJECT(&s->gmac), "phy-addr");
|
||||||
|
|
||||||
|
object_initialize_child(obj, "dramc", &s->dramc, TYPE_AW_R40_DRAMC);
|
||||||
|
object_property_add_alias(obj, "ram-addr", OBJECT(&s->dramc),
|
||||||
|
"ram-addr");
|
||||||
|
object_property_add_alias(obj, "ram-size", OBJECT(&s->dramc),
|
||||||
|
"ram-size");
|
||||||
|
|
||||||
|
object_initialize_child(obj, "sramc", &s->sramc, TYPE_AW_SRAMC_SUN8I_R40);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void allwinner_r40_realize(DeviceState *dev, Error **errp)
|
||||||
|
{
|
||||||
|
const char *r40_nic_models[] = { "gmac", "emac", NULL };
|
||||||
|
AwR40State *s = AW_R40(dev);
|
||||||
|
unsigned i;
|
||||||
|
|
||||||
|
/* CPUs */
|
||||||
|
for (i = 0; i < AW_R40_NUM_CPUS; i++) {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Disable secondary CPUs. Guest EL3 firmware will start
|
||||||
|
* them via CPU reset control registers.
|
||||||
|
*/
|
||||||
|
qdev_prop_set_bit(DEVICE(&s->cpus[i]), "start-powered-off",
|
||||||
|
i > 0);
|
||||||
|
|
||||||
|
/* All exception levels required */
|
||||||
|
qdev_prop_set_bit(DEVICE(&s->cpus[i]), "has_el3", true);
|
||||||
|
qdev_prop_set_bit(DEVICE(&s->cpus[i]), "has_el2", true);
|
||||||
|
|
||||||
|
/* Mark realized */
|
||||||
|
qdev_realize(DEVICE(&s->cpus[i]), NULL, &error_fatal);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Generic Interrupt Controller */
|
||||||
|
qdev_prop_set_uint32(DEVICE(&s->gic), "num-irq", AW_R40_GIC_NUM_SPI +
|
||||||
|
GIC_INTERNAL);
|
||||||
|
qdev_prop_set_uint32(DEVICE(&s->gic), "revision", 2);
|
||||||
|
qdev_prop_set_uint32(DEVICE(&s->gic), "num-cpu", AW_R40_NUM_CPUS);
|
||||||
|
qdev_prop_set_bit(DEVICE(&s->gic), "has-security-extensions", false);
|
||||||
|
qdev_prop_set_bit(DEVICE(&s->gic), "has-virtualization-extensions", true);
|
||||||
|
sysbus_realize(SYS_BUS_DEVICE(&s->gic), &error_fatal);
|
||||||
|
|
||||||
|
sysbus_mmio_map(SYS_BUS_DEVICE(&s->gic), 0, s->memmap[AW_R40_DEV_GIC_DIST]);
|
||||||
|
sysbus_mmio_map(SYS_BUS_DEVICE(&s->gic), 1, s->memmap[AW_R40_DEV_GIC_CPU]);
|
||||||
|
sysbus_mmio_map(SYS_BUS_DEVICE(&s->gic), 2, s->memmap[AW_R40_DEV_GIC_HYP]);
|
||||||
|
sysbus_mmio_map(SYS_BUS_DEVICE(&s->gic), 3, s->memmap[AW_R40_DEV_GIC_VCPU]);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Wire the outputs from each CPU's generic timer and the GICv2
|
||||||
|
* maintenance interrupt signal to the appropriate GIC PPI inputs,
|
||||||
|
* and the GIC's IRQ/FIQ/VIRQ/VFIQ interrupt outputs to the CPU's inputs.
|
||||||
|
*/
|
||||||
|
for (i = 0; i < AW_R40_NUM_CPUS; i++) {
|
||||||
|
DeviceState *cpudev = DEVICE(&s->cpus[i]);
|
||||||
|
int ppibase = AW_R40_GIC_NUM_SPI + i * GIC_INTERNAL + GIC_NR_SGIS;
|
||||||
|
int irq;
|
||||||
|
/*
|
||||||
|
* Mapping from the output timer irq lines from the CPU to the
|
||||||
|
* GIC PPI inputs used for this board.
|
||||||
|
*/
|
||||||
|
const int timer_irq[] = {
|
||||||
|
[GTIMER_PHYS] = AW_R40_GIC_PPI_PHYSTIMER,
|
||||||
|
[GTIMER_VIRT] = AW_R40_GIC_PPI_VIRTTIMER,
|
||||||
|
[GTIMER_HYP] = AW_R40_GIC_PPI_HYPTIMER,
|
||||||
|
[GTIMER_SEC] = AW_R40_GIC_PPI_SECTIMER,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Connect CPU timer outputs to GIC PPI inputs */
|
||||||
|
for (irq = 0; irq < ARRAY_SIZE(timer_irq); irq++) {
|
||||||
|
qdev_connect_gpio_out(cpudev, irq,
|
||||||
|
qdev_get_gpio_in(DEVICE(&s->gic),
|
||||||
|
ppibase + timer_irq[irq]));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Connect GIC outputs to CPU interrupt inputs */
|
||||||
|
sysbus_connect_irq(SYS_BUS_DEVICE(&s->gic), i,
|
||||||
|
qdev_get_gpio_in(cpudev, ARM_CPU_IRQ));
|
||||||
|
sysbus_connect_irq(SYS_BUS_DEVICE(&s->gic), i + AW_R40_NUM_CPUS,
|
||||||
|
qdev_get_gpio_in(cpudev, ARM_CPU_FIQ));
|
||||||
|
sysbus_connect_irq(SYS_BUS_DEVICE(&s->gic), i + (2 * AW_R40_NUM_CPUS),
|
||||||
|
qdev_get_gpio_in(cpudev, ARM_CPU_VIRQ));
|
||||||
|
sysbus_connect_irq(SYS_BUS_DEVICE(&s->gic), i + (3 * AW_R40_NUM_CPUS),
|
||||||
|
qdev_get_gpio_in(cpudev, ARM_CPU_VFIQ));
|
||||||
|
|
||||||
|
/* GIC maintenance signal */
|
||||||
|
sysbus_connect_irq(SYS_BUS_DEVICE(&s->gic), i + (4 * AW_R40_NUM_CPUS),
|
||||||
|
qdev_get_gpio_in(DEVICE(&s->gic),
|
||||||
|
ppibase + AW_R40_GIC_PPI_MAINT));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Timer */
|
||||||
|
sysbus_realize(SYS_BUS_DEVICE(&s->timer), &error_fatal);
|
||||||
|
sysbus_mmio_map(SYS_BUS_DEVICE(&s->timer), 0, s->memmap[AW_R40_DEV_PIT]);
|
||||||
|
sysbus_connect_irq(SYS_BUS_DEVICE(&s->timer), 0,
|
||||||
|
qdev_get_gpio_in(DEVICE(&s->gic),
|
||||||
|
AW_R40_GIC_SPI_TIMER0));
|
||||||
|
sysbus_connect_irq(SYS_BUS_DEVICE(&s->timer), 1,
|
||||||
|
qdev_get_gpio_in(DEVICE(&s->gic),
|
||||||
|
AW_R40_GIC_SPI_TIMER1));
|
||||||
|
|
||||||
|
/* SRAM */
|
||||||
|
sysbus_realize(SYS_BUS_DEVICE(&s->sramc), &error_fatal);
|
||||||
|
sysbus_mmio_map(SYS_BUS_DEVICE(&s->sramc), 0, s->memmap[AW_R40_DEV_SRAMC]);
|
||||||
|
|
||||||
|
memory_region_init_ram(&s->sram_a1, OBJECT(dev), "sram A1",
|
||||||
|
16 * KiB, &error_abort);
|
||||||
|
memory_region_init_ram(&s->sram_a2, OBJECT(dev), "sram A2",
|
||||||
|
16 * KiB, &error_abort);
|
||||||
|
memory_region_init_ram(&s->sram_a3, OBJECT(dev), "sram A3",
|
||||||
|
13 * KiB, &error_abort);
|
||||||
|
memory_region_init_ram(&s->sram_a4, OBJECT(dev), "sram A4",
|
||||||
|
3 * KiB, &error_abort);
|
||||||
|
memory_region_add_subregion(get_system_memory(),
|
||||||
|
s->memmap[AW_R40_DEV_SRAM_A1], &s->sram_a1);
|
||||||
|
memory_region_add_subregion(get_system_memory(),
|
||||||
|
s->memmap[AW_R40_DEV_SRAM_A2], &s->sram_a2);
|
||||||
|
memory_region_add_subregion(get_system_memory(),
|
||||||
|
s->memmap[AW_R40_DEV_SRAM_A3], &s->sram_a3);
|
||||||
|
memory_region_add_subregion(get_system_memory(),
|
||||||
|
s->memmap[AW_R40_DEV_SRAM_A4], &s->sram_a4);
|
||||||
|
|
||||||
|
/* Clock Control Unit */
|
||||||
|
sysbus_realize(SYS_BUS_DEVICE(&s->ccu), &error_fatal);
|
||||||
|
sysbus_mmio_map(SYS_BUS_DEVICE(&s->ccu), 0, s->memmap[AW_R40_DEV_CCU]);
|
||||||
|
|
||||||
|
/* SD/MMC */
|
||||||
|
for (int i = 0; i < AW_R40_NUM_MMCS; i++) {
|
||||||
|
qemu_irq irq = qdev_get_gpio_in(DEVICE(&s->gic),
|
||||||
|
AW_R40_GIC_SPI_MMC0 + i);
|
||||||
|
const hwaddr addr = s->memmap[AW_R40_DEV_MMC0 + i];
|
||||||
|
|
||||||
|
object_property_set_link(OBJECT(&s->mmc[i]), "dma-memory",
|
||||||
|
OBJECT(get_system_memory()), &error_fatal);
|
||||||
|
sysbus_realize(SYS_BUS_DEVICE(&s->mmc[i]), &error_fatal);
|
||||||
|
sysbus_mmio_map(SYS_BUS_DEVICE(&s->mmc[i]), 0, addr);
|
||||||
|
sysbus_connect_irq(SYS_BUS_DEVICE(&s->mmc[i]), 0, irq);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* UART0. For future clocktree API: All UARTS are connected to APB2_CLK. */
|
||||||
|
for (int i = 0; i < AW_R40_NUM_UARTS; i++) {
|
||||||
|
static const int uart_irqs[AW_R40_NUM_UARTS] = {
|
||||||
|
AW_R40_GIC_SPI_UART0,
|
||||||
|
AW_R40_GIC_SPI_UART1,
|
||||||
|
AW_R40_GIC_SPI_UART2,
|
||||||
|
AW_R40_GIC_SPI_UART3,
|
||||||
|
AW_R40_GIC_SPI_UART4,
|
||||||
|
AW_R40_GIC_SPI_UART5,
|
||||||
|
AW_R40_GIC_SPI_UART6,
|
||||||
|
AW_R40_GIC_SPI_UART7,
|
||||||
|
};
|
||||||
|
const hwaddr addr = s->memmap[AW_R40_DEV_UART0 + i];
|
||||||
|
|
||||||
|
serial_mm_init(get_system_memory(), addr, 2,
|
||||||
|
qdev_get_gpio_in(DEVICE(&s->gic), uart_irqs[i]),
|
||||||
|
115200, serial_hd(i), DEVICE_NATIVE_ENDIAN);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* I2C */
|
||||||
|
sysbus_realize(SYS_BUS_DEVICE(&s->i2c0), &error_fatal);
|
||||||
|
sysbus_mmio_map(SYS_BUS_DEVICE(&s->i2c0), 0, s->memmap[AW_R40_DEV_TWI0]);
|
||||||
|
sysbus_connect_irq(SYS_BUS_DEVICE(&s->i2c0), 0,
|
||||||
|
qdev_get_gpio_in(DEVICE(&s->gic), AW_R40_GIC_SPI_TWI0));
|
||||||
|
|
||||||
|
/* DRAMC */
|
||||||
|
sysbus_realize(SYS_BUS_DEVICE(&s->dramc), &error_fatal);
|
||||||
|
sysbus_mmio_map(SYS_BUS_DEVICE(&s->dramc), 0,
|
||||||
|
s->memmap[AW_R40_DEV_DRAMCOM]);
|
||||||
|
sysbus_mmio_map(SYS_BUS_DEVICE(&s->dramc), 1,
|
||||||
|
s->memmap[AW_R40_DEV_DRAMCTL]);
|
||||||
|
sysbus_mmio_map(SYS_BUS_DEVICE(&s->dramc), 2,
|
||||||
|
s->memmap[AW_R40_DEV_DRAMPHY]);
|
||||||
|
|
||||||
|
/* nic support gmac and emac */
|
||||||
|
for (int i = 0; i < ARRAY_SIZE(r40_nic_models) - 1; i++) {
|
||||||
|
NICInfo *nic = &nd_table[i];
|
||||||
|
|
||||||
|
if (!nic->used) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (qemu_show_nic_models(nic->model, r40_nic_models)) {
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (qemu_find_nic_model(nic, r40_nic_models, r40_nic_models[0])) {
|
||||||
|
case 0: /* gmac */
|
||||||
|
qdev_set_nic_properties(DEVICE(&s->gmac), nic);
|
||||||
|
break;
|
||||||
|
case 1: /* emac */
|
||||||
|
qdev_set_nic_properties(DEVICE(&s->emac), nic);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
exit(1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* GMAC */
|
||||||
|
object_property_set_link(OBJECT(&s->gmac), "dma-memory",
|
||||||
|
OBJECT(get_system_memory()), &error_fatal);
|
||||||
|
sysbus_realize(SYS_BUS_DEVICE(&s->gmac), &error_fatal);
|
||||||
|
sysbus_mmio_map(SYS_BUS_DEVICE(&s->gmac), 0, s->memmap[AW_R40_DEV_GMAC]);
|
||||||
|
sysbus_connect_irq(SYS_BUS_DEVICE(&s->gmac), 0,
|
||||||
|
qdev_get_gpio_in(DEVICE(&s->gic), AW_R40_GIC_SPI_GMAC));
|
||||||
|
|
||||||
|
/* EMAC */
|
||||||
|
sysbus_realize(SYS_BUS_DEVICE(&s->emac), &error_fatal);
|
||||||
|
sysbus_mmio_map(SYS_BUS_DEVICE(&s->emac), 0, s->memmap[AW_R40_DEV_EMAC]);
|
||||||
|
sysbus_connect_irq(SYS_BUS_DEVICE(&s->emac), 0,
|
||||||
|
qdev_get_gpio_in(DEVICE(&s->gic), AW_R40_GIC_SPI_EMAC));
|
||||||
|
|
||||||
|
/* Unimplemented devices */
|
||||||
|
for (i = 0; i < ARRAY_SIZE(r40_unimplemented); i++) {
|
||||||
|
create_unimplemented_device(r40_unimplemented[i].device_name,
|
||||||
|
r40_unimplemented[i].base,
|
||||||
|
r40_unimplemented[i].size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void allwinner_r40_class_init(ObjectClass *oc, void *data)
|
||||||
|
{
|
||||||
|
DeviceClass *dc = DEVICE_CLASS(oc);
|
||||||
|
|
||||||
|
dc->realize = allwinner_r40_realize;
|
||||||
|
/* Reason: uses serial_hd() in realize function */
|
||||||
|
dc->user_creatable = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const TypeInfo allwinner_r40_type_info = {
|
||||||
|
.name = TYPE_AW_R40,
|
||||||
|
.parent = TYPE_DEVICE,
|
||||||
|
.instance_size = sizeof(AwR40State),
|
||||||
|
.instance_init = allwinner_r40_init,
|
||||||
|
.class_init = allwinner_r40_class_init,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void allwinner_r40_register_types(void)
|
||||||
|
{
|
||||||
|
type_register_static(&allwinner_r40_type_info);
|
||||||
|
}
|
||||||
|
|
||||||
|
type_init(allwinner_r40_register_types)
|
@ -40,7 +40,9 @@ struct AspeedMachineState {
|
|||||||
/* Public */
|
/* Public */
|
||||||
|
|
||||||
AspeedSoCState soc;
|
AspeedSoCState soc;
|
||||||
|
MemoryRegion boot_rom;
|
||||||
bool mmio_exec;
|
bool mmio_exec;
|
||||||
|
uint32_t uart_chosen;
|
||||||
char *fmc_model;
|
char *fmc_model;
|
||||||
char *spi_model;
|
char *spi_model;
|
||||||
};
|
};
|
||||||
@ -275,15 +277,15 @@ static void write_boot_rom(BlockBackend *blk, hwaddr addr, size_t rom_size,
|
|||||||
* Create a ROM and copy the flash contents at the expected address
|
* Create a ROM and copy the flash contents at the expected address
|
||||||
* (0x0). Boots faster than execute-in-place.
|
* (0x0). Boots faster than execute-in-place.
|
||||||
*/
|
*/
|
||||||
static void aspeed_install_boot_rom(AspeedSoCState *soc, BlockBackend *blk,
|
static void aspeed_install_boot_rom(AspeedMachineState *bmc, BlockBackend *blk,
|
||||||
uint64_t rom_size)
|
uint64_t rom_size)
|
||||||
{
|
{
|
||||||
MemoryRegion *boot_rom = g_new(MemoryRegion, 1);
|
AspeedSoCState *soc = &bmc->soc;
|
||||||
|
|
||||||
memory_region_init_rom(boot_rom, NULL, "aspeed.boot_rom", rom_size,
|
memory_region_init_rom(&bmc->boot_rom, NULL, "aspeed.boot_rom", rom_size,
|
||||||
&error_abort);
|
&error_abort);
|
||||||
memory_region_add_subregion_overlap(&soc->spi_boot_container, 0,
|
memory_region_add_subregion_overlap(&soc->spi_boot_container, 0,
|
||||||
boot_rom, 1);
|
&bmc->boot_rom, 1);
|
||||||
write_boot_rom(blk, ASPEED_SOC_SPI_BOOT_ADDR, rom_size, &error_abort);
|
write_boot_rom(blk, ASPEED_SOC_SPI_BOOT_ADDR, rom_size, &error_abort);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -332,10 +334,11 @@ static void connect_serial_hds_to_uarts(AspeedMachineState *bmc)
|
|||||||
AspeedMachineClass *amc = ASPEED_MACHINE_GET_CLASS(bmc);
|
AspeedMachineClass *amc = ASPEED_MACHINE_GET_CLASS(bmc);
|
||||||
AspeedSoCState *s = &bmc->soc;
|
AspeedSoCState *s = &bmc->soc;
|
||||||
AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(s);
|
AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(s);
|
||||||
|
int uart_chosen = bmc->uart_chosen ? bmc->uart_chosen : amc->uart_default;
|
||||||
|
|
||||||
aspeed_soc_uart_set_chr(s, amc->uart_default, serial_hd(0));
|
aspeed_soc_uart_set_chr(s, uart_chosen, serial_hd(0));
|
||||||
for (int i = 1, uart = ASPEED_DEV_UART1; i < sc->uarts_num; i++, uart++) {
|
for (int i = 1, uart = ASPEED_DEV_UART1; i < sc->uarts_num; i++, uart++) {
|
||||||
if (uart == amc->uart_default) {
|
if (uart == uart_chosen) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
aspeed_soc_uart_set_chr(s, uart, serial_hd(i));
|
aspeed_soc_uart_set_chr(s, uart, serial_hd(i));
|
||||||
@ -431,8 +434,7 @@ static void aspeed_machine_init(MachineState *machine)
|
|||||||
|
|
||||||
if (mtd0) {
|
if (mtd0) {
|
||||||
uint64_t rom_size = memory_region_size(&bmc->soc.spi_boot);
|
uint64_t rom_size = memory_region_size(&bmc->soc.spi_boot);
|
||||||
aspeed_install_boot_rom(&bmc->soc, blk_by_legacy_dinfo(mtd0),
|
aspeed_install_boot_rom(bmc, blk_by_legacy_dinfo(mtd0), rom_size);
|
||||||
rom_size);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -788,8 +790,10 @@ static void rainier_bmc_i2c_init(AspeedMachineState *bmc)
|
|||||||
0x48);
|
0x48);
|
||||||
i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 8), TYPE_TMP105,
|
i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 8), TYPE_TMP105,
|
||||||
0x4a);
|
0x4a);
|
||||||
at24c_eeprom_init(aspeed_i2c_get_bus(&soc->i2c, 8), 0x50, 64 * KiB);
|
at24c_eeprom_init_rom(aspeed_i2c_get_bus(&soc->i2c, 8), 0x50,
|
||||||
at24c_eeprom_init(aspeed_i2c_get_bus(&soc->i2c, 8), 0x51, 64 * KiB);
|
64 * KiB, rainier_bb_fruid, rainier_bb_fruid_len);
|
||||||
|
at24c_eeprom_init_rom(aspeed_i2c_get_bus(&soc->i2c, 8), 0x51,
|
||||||
|
64 * KiB, rainier_bmc_fruid, rainier_bmc_fruid_len);
|
||||||
create_pca9552(soc, 8, 0x60);
|
create_pca9552(soc, 8, 0x60);
|
||||||
create_pca9552(soc, 8, 0x61);
|
create_pca9552(soc, 8, 0x61);
|
||||||
/* Bus 8: ucd90320@11 */
|
/* Bus 8: ucd90320@11 */
|
||||||
@ -1076,6 +1080,35 @@ static void aspeed_set_spi_model(Object *obj, const char *value, Error **errp)
|
|||||||
bmc->spi_model = g_strdup(value);
|
bmc->spi_model = g_strdup(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static char *aspeed_get_bmc_console(Object *obj, Error **errp)
|
||||||
|
{
|
||||||
|
AspeedMachineState *bmc = ASPEED_MACHINE(obj);
|
||||||
|
AspeedMachineClass *amc = ASPEED_MACHINE_GET_CLASS(bmc);
|
||||||
|
int uart_chosen = bmc->uart_chosen ? bmc->uart_chosen : amc->uart_default;
|
||||||
|
|
||||||
|
return g_strdup_printf("uart%d", uart_chosen - ASPEED_DEV_UART1 + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void aspeed_set_bmc_console(Object *obj, const char *value, Error **errp)
|
||||||
|
{
|
||||||
|
AspeedMachineState *bmc = ASPEED_MACHINE(obj);
|
||||||
|
AspeedMachineClass *amc = ASPEED_MACHINE_GET_CLASS(bmc);
|
||||||
|
AspeedSoCClass *sc = ASPEED_SOC_CLASS(object_class_by_name(amc->soc_name));
|
||||||
|
int val;
|
||||||
|
|
||||||
|
if (sscanf(value, "uart%u", &val) != 1) {
|
||||||
|
error_setg(errp, "Bad value for \"uart\" property");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The number of UART depends on the SoC */
|
||||||
|
if (val < 1 || val > sc->uarts_num) {
|
||||||
|
error_setg(errp, "\"uart\" should be in range [1 - %d]", sc->uarts_num);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
bmc->uart_chosen = ASPEED_DEV_UART1 + val - 1;
|
||||||
|
}
|
||||||
|
|
||||||
static void aspeed_machine_class_props_init(ObjectClass *oc)
|
static void aspeed_machine_class_props_init(ObjectClass *oc)
|
||||||
{
|
{
|
||||||
object_class_property_add_bool(oc, "execute-in-place",
|
object_class_property_add_bool(oc, "execute-in-place",
|
||||||
@ -1084,6 +1117,11 @@ static void aspeed_machine_class_props_init(ObjectClass *oc)
|
|||||||
object_class_property_set_description(oc, "execute-in-place",
|
object_class_property_set_description(oc, "execute-in-place",
|
||||||
"boot directly from CE0 flash device");
|
"boot directly from CE0 flash device");
|
||||||
|
|
||||||
|
object_class_property_add_str(oc, "bmc-console", aspeed_get_bmc_console,
|
||||||
|
aspeed_set_bmc_console);
|
||||||
|
object_class_property_set_description(oc, "bmc-console",
|
||||||
|
"Change the default UART to \"uartX\"");
|
||||||
|
|
||||||
object_class_property_add_str(oc, "fmc-model", aspeed_get_fmc_model,
|
object_class_property_add_str(oc, "fmc-model", aspeed_get_fmc_model,
|
||||||
aspeed_set_fmc_model);
|
aspeed_set_fmc_model);
|
||||||
object_class_property_set_description(oc, "fmc-model",
|
object_class_property_set_description(oc, "fmc-model",
|
||||||
|
@ -316,6 +316,8 @@ static void aspeed_soc_ast2600_realize(DeviceState *dev, Error **errp)
|
|||||||
&error_abort);
|
&error_abort);
|
||||||
object_property_set_bool(OBJECT(&s->cpu[i]), "neon", false,
|
object_property_set_bool(OBJECT(&s->cpu[i]), "neon", false,
|
||||||
&error_abort);
|
&error_abort);
|
||||||
|
object_property_set_bool(OBJECT(&s->cpu[i]), "vfp-d32", false,
|
||||||
|
&error_abort);
|
||||||
object_property_set_link(OBJECT(&s->cpu[i]), "memory",
|
object_property_set_link(OBJECT(&s->cpu[i]), "memory",
|
||||||
OBJECT(s->memory), &error_abort);
|
OBJECT(s->memory), &error_abort);
|
||||||
|
|
||||||
|
@ -119,9 +119,52 @@ const uint8_t yosemitev2_bmc_fruid[] = {
|
|||||||
0x6e, 0x66, 0x69, 0x67, 0x20, 0x41, 0xc1, 0x45,
|
0x6e, 0x66, 0x69, 0x67, 0x20, 0x41, 0xc1, 0x45,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const uint8_t rainier_bb_fruid[] = {
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x84,
|
||||||
|
0x28, 0x00, 0x52, 0x54, 0x04, 0x56, 0x48, 0x44, 0x52, 0x56, 0x44, 0x02,
|
||||||
|
0x01, 0x00, 0x50, 0x54, 0x0e, 0x56, 0x54, 0x4f, 0x43, 0x00, 0x00, 0x37,
|
||||||
|
0x00, 0x4a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x46, 0x08, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x00, 0x52, 0x54,
|
||||||
|
0x04, 0x56, 0x54, 0x4f, 0x43, 0x50, 0x54, 0x38, 0x56, 0x49, 0x4e, 0x49,
|
||||||
|
0x00, 0x00, 0x81, 0x00, 0x3a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x56, 0x53,
|
||||||
|
0x59, 0x53, 0x00, 0x00, 0xbb, 0x00, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x56, 0x43, 0x45, 0x4e, 0x00, 0x00, 0xe2, 0x00, 0x27, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x56, 0x53, 0x42, 0x50, 0x00, 0x00, 0x09, 0x01, 0x19, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x50, 0x46, 0x01, 0x00, 0x00, 0x00, 0x36, 0x00,
|
||||||
|
0x52, 0x54, 0x04, 0x56, 0x49, 0x4e, 0x49, 0x44, 0x52, 0x04, 0x44, 0x45,
|
||||||
|
0x53, 0x43, 0x48, 0x57, 0x02, 0x30, 0x31, 0x43, 0x43, 0x04, 0x33, 0x34,
|
||||||
|
0x35, 0x36, 0x46, 0x4e, 0x04, 0x46, 0x52, 0x34, 0x39, 0x53, 0x4e, 0x04,
|
||||||
|
0x53, 0x52, 0x31, 0x32, 0x50, 0x4e, 0x04, 0x50, 0x52, 0x39, 0x39, 0x50,
|
||||||
|
0x46, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0x00, 0x52, 0x54,
|
||||||
|
0x04, 0x56, 0x53, 0x59, 0x53, 0x53, 0x45, 0x07, 0x49, 0x42, 0x4d, 0x53,
|
||||||
|
0x59, 0x53, 0x31, 0x54, 0x4d, 0x08, 0x32, 0x32, 0x32, 0x32, 0x2d, 0x32,
|
||||||
|
0x32, 0x32, 0x50, 0x46, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23,
|
||||||
|
0x00, 0x52, 0x54, 0x04, 0x56, 0x43, 0x45, 0x4e, 0x53, 0x45, 0x07, 0x31,
|
||||||
|
0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x46, 0x43, 0x08, 0x31, 0x31, 0x31,
|
||||||
|
0x31, 0x2d, 0x31, 0x31, 0x31, 0x50, 0x46, 0x04, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x15, 0x00, 0x52, 0x54, 0x04, 0x56, 0x53, 0x42, 0x50, 0x49,
|
||||||
|
0x4d, 0x04, 0x50, 0x00, 0x10, 0x01, 0x50, 0x46, 0x04, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Rainier BMC FRU */
|
||||||
|
const uint8_t rainier_bmc_fruid[] = {
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x84,
|
||||||
|
0x28, 0x00, 0x52, 0x54, 0x04, 0x56, 0x48, 0x44, 0x52, 0x56, 0x44, 0x02,
|
||||||
|
0x01, 0x00, 0x50, 0x54, 0x0e, 0x56, 0x54, 0x4f, 0x43, 0x00, 0x00, 0x37,
|
||||||
|
0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x46, 0x08, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x52, 0x54,
|
||||||
|
0x04, 0x56, 0x54, 0x4f, 0x43, 0x50, 0x54, 0x0e, 0x56, 0x49, 0x4e, 0x49,
|
||||||
|
0x00, 0x00, 0x57, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x46,
|
||||||
|
0x01, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x52, 0x54, 0x04, 0x56, 0x49, 0x4e,
|
||||||
|
0x49, 0x44, 0x52, 0x04, 0x44, 0x45, 0x53, 0x43, 0x48, 0x57, 0x02, 0x30,
|
||||||
|
0x31, 0x50, 0x46, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
};
|
||||||
|
|
||||||
const size_t tiogapass_bmc_fruid_len = sizeof(tiogapass_bmc_fruid);
|
const size_t tiogapass_bmc_fruid_len = sizeof(tiogapass_bmc_fruid);
|
||||||
const size_t fby35_nic_fruid_len = sizeof(fby35_nic_fruid);
|
const size_t fby35_nic_fruid_len = sizeof(fby35_nic_fruid);
|
||||||
const size_t fby35_bb_fruid_len = sizeof(fby35_bb_fruid);
|
const size_t fby35_bb_fruid_len = sizeof(fby35_bb_fruid);
|
||||||
const size_t fby35_bmc_fruid_len = sizeof(fby35_bmc_fruid);
|
const size_t fby35_bmc_fruid_len = sizeof(fby35_bmc_fruid);
|
||||||
|
|
||||||
const size_t yosemitev2_bmc_fruid_len = sizeof(yosemitev2_bmc_fruid);
|
const size_t yosemitev2_bmc_fruid_len = sizeof(yosemitev2_bmc_fruid);
|
||||||
|
const size_t rainier_bb_fruid_len = sizeof(rainier_bb_fruid);
|
||||||
|
const size_t rainier_bmc_fruid_len = sizeof(rainier_bmc_fruid);
|
||||||
|
@ -22,4 +22,9 @@ extern const size_t fby35_bmc_fruid_len;
|
|||||||
extern const uint8_t yosemitev2_bmc_fruid[];
|
extern const uint8_t yosemitev2_bmc_fruid[];
|
||||||
extern const size_t yosemitev2_bmc_fruid_len;
|
extern const size_t yosemitev2_bmc_fruid_len;
|
||||||
|
|
||||||
|
extern const uint8_t rainier_bb_fruid[];
|
||||||
|
extern const size_t rainier_bb_fruid_len;
|
||||||
|
extern const uint8_t rainier_bmc_fruid[];
|
||||||
|
extern const size_t rainier_bmc_fruid_len;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
145
hw/arm/bananapi_m2u.c
Normal file
145
hw/arm/bananapi_m2u.c
Normal file
@ -0,0 +1,145 @@
|
|||||||
|
/*
|
||||||
|
* Bananapi M2U emulation
|
||||||
|
*
|
||||||
|
* Copyright (C) 2023 qianfan Zhao <qianfanguijin@163.com>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "qemu/osdep.h"
|
||||||
|
#include "qemu/units.h"
|
||||||
|
#include "exec/address-spaces.h"
|
||||||
|
#include "qapi/error.h"
|
||||||
|
#include "qemu/error-report.h"
|
||||||
|
#include "hw/boards.h"
|
||||||
|
#include "hw/i2c/i2c.h"
|
||||||
|
#include "hw/qdev-properties.h"
|
||||||
|
#include "hw/arm/allwinner-r40.h"
|
||||||
|
|
||||||
|
static struct arm_boot_info bpim2u_binfo;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* R40 can boot from mmc0 and mmc2, and bpim2u has two mmc interface, one is
|
||||||
|
* connected to sdcard and another mount an emmc media.
|
||||||
|
* Attach the mmc driver and try loading bootloader.
|
||||||
|
*/
|
||||||
|
static void mmc_attach_drive(AwR40State *s, AwSdHostState *mmc, int unit,
|
||||||
|
bool load_bootroom, bool *bootroom_loaded)
|
||||||
|
{
|
||||||
|
DriveInfo *di = drive_get(IF_SD, 0, unit);
|
||||||
|
BlockBackend *blk = di ? blk_by_legacy_dinfo(di) : NULL;
|
||||||
|
BusState *bus;
|
||||||
|
DeviceState *carddev;
|
||||||
|
|
||||||
|
bus = qdev_get_child_bus(DEVICE(mmc), "sd-bus");
|
||||||
|
if (bus == NULL) {
|
||||||
|
error_report("No SD bus found in SOC object");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
carddev = qdev_new(TYPE_SD_CARD);
|
||||||
|
qdev_prop_set_drive_err(carddev, "drive", blk, &error_fatal);
|
||||||
|
qdev_realize_and_unref(carddev, bus, &error_fatal);
|
||||||
|
|
||||||
|
if (load_bootroom && blk && blk_is_available(blk)) {
|
||||||
|
/* Use Boot ROM to copy data from SD card to SRAM */
|
||||||
|
*bootroom_loaded = allwinner_r40_bootrom_setup(s, blk, unit);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void bpim2u_init(MachineState *machine)
|
||||||
|
{
|
||||||
|
bool bootroom_loaded = false;
|
||||||
|
AwR40State *r40;
|
||||||
|
I2CBus *i2c;
|
||||||
|
|
||||||
|
/* BIOS is not supported by this board */
|
||||||
|
if (machine->firmware) {
|
||||||
|
error_report("BIOS not supported for this machine");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Only allow Cortex-A7 for this board */
|
||||||
|
if (strcmp(machine->cpu_type, ARM_CPU_TYPE_NAME("cortex-a7")) != 0) {
|
||||||
|
error_report("This board can only be used with cortex-a7 CPU");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
r40 = AW_R40(object_new(TYPE_AW_R40));
|
||||||
|
object_property_add_child(OBJECT(machine), "soc", OBJECT(r40));
|
||||||
|
object_unref(OBJECT(r40));
|
||||||
|
|
||||||
|
/* Setup timer properties */
|
||||||
|
object_property_set_int(OBJECT(r40), "clk0-freq", 32768, &error_abort);
|
||||||
|
object_property_set_int(OBJECT(r40), "clk1-freq", 24 * 1000 * 1000,
|
||||||
|
&error_abort);
|
||||||
|
|
||||||
|
/* DRAMC */
|
||||||
|
r40->ram_size = machine->ram_size / MiB;
|
||||||
|
object_property_set_uint(OBJECT(r40), "ram-addr",
|
||||||
|
r40->memmap[AW_R40_DEV_SDRAM], &error_abort);
|
||||||
|
object_property_set_int(OBJECT(r40), "ram-size",
|
||||||
|
r40->ram_size, &error_abort);
|
||||||
|
|
||||||
|
/* GMAC PHY */
|
||||||
|
object_property_set_uint(OBJECT(r40), "gmac-phy-addr", 1, &error_abort);
|
||||||
|
|
||||||
|
/* Mark R40 object realized */
|
||||||
|
qdev_realize(DEVICE(r40), NULL, &error_abort);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Plug in SD card and try load bootrom, R40 has 4 mmc controllers but can
|
||||||
|
* only booting from mmc0 and mmc2.
|
||||||
|
*/
|
||||||
|
for (int i = 0; i < AW_R40_NUM_MMCS; i++) {
|
||||||
|
switch (i) {
|
||||||
|
case 0:
|
||||||
|
case 2:
|
||||||
|
mmc_attach_drive(r40, &r40->mmc[i], i,
|
||||||
|
!machine->kernel_filename && !bootroom_loaded,
|
||||||
|
&bootroom_loaded);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
mmc_attach_drive(r40, &r40->mmc[i], i, false, NULL);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Connect AXP221 */
|
||||||
|
i2c = I2C_BUS(qdev_get_child_bus(DEVICE(&r40->i2c0), "i2c"));
|
||||||
|
i2c_slave_create_simple(i2c, "axp221_pmu", 0x34);
|
||||||
|
|
||||||
|
/* SDRAM */
|
||||||
|
memory_region_add_subregion(get_system_memory(),
|
||||||
|
r40->memmap[AW_R40_DEV_SDRAM], machine->ram);
|
||||||
|
|
||||||
|
bpim2u_binfo.loader_start = r40->memmap[AW_R40_DEV_SDRAM];
|
||||||
|
bpim2u_binfo.ram_size = machine->ram_size;
|
||||||
|
bpim2u_binfo.psci_conduit = QEMU_PSCI_CONDUIT_SMC;
|
||||||
|
arm_load_kernel(ARM_CPU(first_cpu), machine, &bpim2u_binfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void bpim2u_machine_init(MachineClass *mc)
|
||||||
|
{
|
||||||
|
mc->desc = "Bananapi M2U (Cortex-A7)";
|
||||||
|
mc->init = bpim2u_init;
|
||||||
|
mc->min_cpus = AW_R40_NUM_CPUS;
|
||||||
|
mc->max_cpus = AW_R40_NUM_CPUS;
|
||||||
|
mc->default_cpus = AW_R40_NUM_CPUS;
|
||||||
|
mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-a7");
|
||||||
|
mc->default_ram_size = 1 * GiB;
|
||||||
|
mc->default_ram_id = "bpim2u.ram";
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFINE_MACHINE("bpim2u", bpim2u_machine_init)
|
@ -70,8 +70,6 @@ static void fby35_bmc_write_boot_rom(DriveInfo *dinfo, MemoryRegion *mr,
|
|||||||
|
|
||||||
static void fby35_bmc_init(Fby35State *s)
|
static void fby35_bmc_init(Fby35State *s)
|
||||||
{
|
{
|
||||||
DriveInfo *drive0 = drive_get(IF_MTD, 0, 0);
|
|
||||||
|
|
||||||
object_initialize_child(OBJECT(s), "bmc", &s->bmc, "ast2600-a3");
|
object_initialize_child(OBJECT(s), "bmc", &s->bmc, "ast2600-a3");
|
||||||
|
|
||||||
memory_region_init(&s->bmc_memory, OBJECT(&s->bmc), "bmc-memory",
|
memory_region_init(&s->bmc_memory, OBJECT(&s->bmc), "bmc-memory",
|
||||||
@ -95,18 +93,21 @@ static void fby35_bmc_init(Fby35State *s)
|
|||||||
aspeed_board_init_flashes(&s->bmc.fmc, "n25q00", 2, 0);
|
aspeed_board_init_flashes(&s->bmc.fmc, "n25q00", 2, 0);
|
||||||
|
|
||||||
/* Install first FMC flash content as a boot rom. */
|
/* Install first FMC flash content as a boot rom. */
|
||||||
if (drive0) {
|
if (!s->mmio_exec) {
|
||||||
AspeedSMCFlash *fl = &s->bmc.fmc.flashes[0];
|
DriveInfo *mtd0 = drive_get(IF_MTD, 0, 0);
|
||||||
MemoryRegion *boot_rom = g_new(MemoryRegion, 1);
|
|
||||||
uint64_t size = memory_region_size(&fl->mmio);
|
|
||||||
|
|
||||||
if (!s->mmio_exec) {
|
if (mtd0) {
|
||||||
memory_region_init_rom(boot_rom, NULL, "aspeed.boot_rom",
|
AspeedSoCState *bmc = &s->bmc;
|
||||||
size, &error_abort);
|
uint64_t rom_size = memory_region_size(&bmc->spi_boot);
|
||||||
memory_region_add_subregion(&s->bmc_memory, FBY35_BMC_FIRMWARE_ADDR,
|
|
||||||
boot_rom);
|
memory_region_init_rom(&s->bmc_boot_rom, NULL, "aspeed.boot_rom",
|
||||||
fby35_bmc_write_boot_rom(drive0, boot_rom, FBY35_BMC_FIRMWARE_ADDR,
|
rom_size, &error_abort);
|
||||||
size, &error_abort);
|
memory_region_add_subregion_overlap(&bmc->spi_boot_container, 0,
|
||||||
|
&s->bmc_boot_rom, 1);
|
||||||
|
|
||||||
|
fby35_bmc_write_boot_rom(mtd0, &s->bmc_boot_rom,
|
||||||
|
FBY35_BMC_FIRMWARE_ADDR,
|
||||||
|
rom_size, &error_abort);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -37,6 +37,7 @@ arm_ss.add(when: 'CONFIG_OMAP', if_true: files('omap1.c', 'omap2.c'))
|
|||||||
arm_ss.add(when: 'CONFIG_STRONGARM', if_true: files('strongarm.c'))
|
arm_ss.add(when: 'CONFIG_STRONGARM', if_true: files('strongarm.c'))
|
||||||
arm_ss.add(when: 'CONFIG_ALLWINNER_A10', if_true: files('allwinner-a10.c', 'cubieboard.c'))
|
arm_ss.add(when: 'CONFIG_ALLWINNER_A10', if_true: files('allwinner-a10.c', 'cubieboard.c'))
|
||||||
arm_ss.add(when: 'CONFIG_ALLWINNER_H3', if_true: files('allwinner-h3.c', 'orangepi.c'))
|
arm_ss.add(when: 'CONFIG_ALLWINNER_H3', if_true: files('allwinner-h3.c', 'orangepi.c'))
|
||||||
|
arm_ss.add(when: 'CONFIG_ALLWINNER_R40', if_true: files('allwinner-r40.c', 'bananapi_m2u.c'))
|
||||||
arm_ss.add(when: 'CONFIG_RASPI', if_true: files('bcm2836.c', 'raspi.c'))
|
arm_ss.add(when: 'CONFIG_RASPI', if_true: files('bcm2836.c', 'raspi.c'))
|
||||||
arm_ss.add(when: 'CONFIG_STM32F100_SOC', if_true: files('stm32f100_soc.c'))
|
arm_ss.add(when: 'CONFIG_STM32F100_SOC', if_true: files('stm32f100_soc.c'))
|
||||||
arm_ss.add(when: 'CONFIG_STM32F205_SOC', if_true: files('stm32f205_soc.c'))
|
arm_ss.add(when: 'CONFIG_STM32F205_SOC', if_true: files('stm32f205_soc.c'))
|
||||||
@ -62,10 +63,12 @@ arm_ss.add(when: 'CONFIG_FSL_IMX7', if_true: files('fsl-imx7.c', 'mcimx7d-sabre.
|
|||||||
arm_ss.add(when: 'CONFIG_ARM_SMMUV3', if_true: files('smmuv3.c'))
|
arm_ss.add(when: 'CONFIG_ARM_SMMUV3', if_true: files('smmuv3.c'))
|
||||||
arm_ss.add(when: 'CONFIG_FSL_IMX6UL', if_true: files('fsl-imx6ul.c', 'mcimx6ul-evk.c'))
|
arm_ss.add(when: 'CONFIG_FSL_IMX6UL', if_true: files('fsl-imx6ul.c', 'mcimx6ul-evk.c'))
|
||||||
arm_ss.add(when: 'CONFIG_NRF51_SOC', if_true: files('nrf51_soc.c'))
|
arm_ss.add(when: 'CONFIG_NRF51_SOC', if_true: files('nrf51_soc.c'))
|
||||||
|
arm_ss.add(when: 'CONFIG_XEN', if_true: files('xen_arm.c'))
|
||||||
|
arm_ss.add_all(xen_ss)
|
||||||
|
|
||||||
softmmu_ss.add(when: 'CONFIG_ARM_SMMUV3', if_true: files('smmu-common.c'))
|
system_ss.add(when: 'CONFIG_ARM_SMMUV3', if_true: files('smmu-common.c'))
|
||||||
softmmu_ss.add(when: 'CONFIG_EXYNOS4', if_true: files('exynos4_boards.c'))
|
system_ss.add(when: 'CONFIG_EXYNOS4', if_true: files('exynos4_boards.c'))
|
||||||
softmmu_ss.add(when: 'CONFIG_RASPI', if_true: files('bcm2835_peripherals.c'))
|
system_ss.add(when: 'CONFIG_RASPI', if_true: files('bcm2835_peripherals.c'))
|
||||||
softmmu_ss.add(when: 'CONFIG_TOSA', if_true: files('tosa.c'))
|
system_ss.add(when: 'CONFIG_TOSA', if_true: files('tosa.c'))
|
||||||
|
|
||||||
hw_arch += {'arm': arm_ss}
|
hw_arch += {'arm': arm_ss}
|
||||||
|
@ -1250,7 +1250,7 @@ static void musicpal_init(MachineState *machine)
|
|||||||
uart_orgate = DEVICE(object_new(TYPE_OR_IRQ));
|
uart_orgate = DEVICE(object_new(TYPE_OR_IRQ));
|
||||||
object_property_set_int(OBJECT(uart_orgate), "num-lines", 2, &error_fatal);
|
object_property_set_int(OBJECT(uart_orgate), "num-lines", 2, &error_fatal);
|
||||||
qdev_realize_and_unref(uart_orgate, NULL, &error_fatal);
|
qdev_realize_and_unref(uart_orgate, NULL, &error_fatal);
|
||||||
qdev_connect_gpio_out(DEVICE(uart_orgate), 0,
|
qdev_connect_gpio_out(uart_orgate, 0,
|
||||||
qdev_get_gpio_in(pic, MP_UART_SHARED_IRQ));
|
qdev_get_gpio_in(pic, MP_UART_SHARED_IRQ));
|
||||||
|
|
||||||
serial_mm_init(address_space_mem, MP_UART1_BASE, 2,
|
serial_mm_init(address_space_mem, MP_UART1_BASE, 2,
|
||||||
|
181
hw/arm/xen_arm.c
Normal file
181
hw/arm/xen_arm.c
Normal file
@ -0,0 +1,181 @@
|
|||||||
|
/*
|
||||||
|
* QEMU ARM Xen PVH Machine
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "qemu/osdep.h"
|
||||||
|
#include "qemu/error-report.h"
|
||||||
|
#include "qapi/qapi-commands-migration.h"
|
||||||
|
#include "qapi/visitor.h"
|
||||||
|
#include "hw/boards.h"
|
||||||
|
#include "hw/sysbus.h"
|
||||||
|
#include "sysemu/block-backend.h"
|
||||||
|
#include "sysemu/tpm_backend.h"
|
||||||
|
#include "sysemu/sysemu.h"
|
||||||
|
#include "hw/xen/xen-hvm-common.h"
|
||||||
|
#include "sysemu/tpm.h"
|
||||||
|
#include "hw/xen/arch_hvm.h"
|
||||||
|
|
||||||
|
#define TYPE_XEN_ARM MACHINE_TYPE_NAME("xenpvh")
|
||||||
|
OBJECT_DECLARE_SIMPLE_TYPE(XenArmState, XEN_ARM)
|
||||||
|
|
||||||
|
static MemoryListener xen_memory_listener = {
|
||||||
|
.region_add = xen_region_add,
|
||||||
|
.region_del = xen_region_del,
|
||||||
|
.log_start = NULL,
|
||||||
|
.log_stop = NULL,
|
||||||
|
.log_sync = NULL,
|
||||||
|
.log_global_start = NULL,
|
||||||
|
.log_global_stop = NULL,
|
||||||
|
.priority = 10,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct XenArmState {
|
||||||
|
/*< private >*/
|
||||||
|
MachineState parent;
|
||||||
|
|
||||||
|
XenIOState *state;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
uint64_t tpm_base_addr;
|
||||||
|
} cfg;
|
||||||
|
};
|
||||||
|
|
||||||
|
void arch_handle_ioreq(XenIOState *state, ioreq_t *req)
|
||||||
|
{
|
||||||
|
hw_error("Invalid ioreq type 0x%x\n", req->type);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void arch_xen_set_memory(XenIOState *state, MemoryRegionSection *section,
|
||||||
|
bool add)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void xen_hvm_modified_memory(ram_addr_t start, ram_addr_t length)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void qmp_xen_set_global_dirty_log(bool enable, Error **errp)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_TPM
|
||||||
|
static void xen_enable_tpm(XenArmState *xam)
|
||||||
|
{
|
||||||
|
Error *errp = NULL;
|
||||||
|
DeviceState *dev;
|
||||||
|
SysBusDevice *busdev;
|
||||||
|
|
||||||
|
TPMBackend *be = qemu_find_tpm_be("tpm0");
|
||||||
|
if (be == NULL) {
|
||||||
|
DPRINTF("Couldn't fine the backend for tpm0\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
dev = qdev_new(TYPE_TPM_TIS_SYSBUS);
|
||||||
|
object_property_set_link(OBJECT(dev), "tpmdev", OBJECT(be), &errp);
|
||||||
|
object_property_set_str(OBJECT(dev), "tpmdev", be->id, &errp);
|
||||||
|
busdev = SYS_BUS_DEVICE(dev);
|
||||||
|
sysbus_realize_and_unref(busdev, &error_fatal);
|
||||||
|
sysbus_mmio_map(busdev, 0, xam->cfg.tpm_base_addr);
|
||||||
|
|
||||||
|
DPRINTF("Connected tpmdev at address 0x%lx\n", xam->cfg.tpm_base_addr);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void xen_arm_init(MachineState *machine)
|
||||||
|
{
|
||||||
|
XenArmState *xam = XEN_ARM(machine);
|
||||||
|
|
||||||
|
xam->state = g_new0(XenIOState, 1);
|
||||||
|
|
||||||
|
xen_register_ioreq(xam->state, machine->smp.cpus, xen_memory_listener);
|
||||||
|
|
||||||
|
#ifdef CONFIG_TPM
|
||||||
|
if (xam->cfg.tpm_base_addr) {
|
||||||
|
xen_enable_tpm(xam);
|
||||||
|
} else {
|
||||||
|
DPRINTF("tpm-base-addr is not provided. TPM will not be enabled\n");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_TPM
|
||||||
|
static void xen_arm_get_tpm_base_addr(Object *obj, Visitor *v,
|
||||||
|
const char *name, void *opaque,
|
||||||
|
Error **errp)
|
||||||
|
{
|
||||||
|
XenArmState *xam = XEN_ARM(obj);
|
||||||
|
uint64_t value = xam->cfg.tpm_base_addr;
|
||||||
|
|
||||||
|
visit_type_uint64(v, name, &value, errp);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void xen_arm_set_tpm_base_addr(Object *obj, Visitor *v,
|
||||||
|
const char *name, void *opaque,
|
||||||
|
Error **errp)
|
||||||
|
{
|
||||||
|
XenArmState *xam = XEN_ARM(obj);
|
||||||
|
uint64_t value;
|
||||||
|
|
||||||
|
if (!visit_type_uint64(v, name, &value, errp)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
xam->cfg.tpm_base_addr = value;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void xen_arm_machine_class_init(ObjectClass *oc, void *data)
|
||||||
|
{
|
||||||
|
|
||||||
|
MachineClass *mc = MACHINE_CLASS(oc);
|
||||||
|
mc->desc = "Xen Para-virtualized PC";
|
||||||
|
mc->init = xen_arm_init;
|
||||||
|
mc->max_cpus = 1;
|
||||||
|
mc->default_machine_opts = "accel=xen";
|
||||||
|
|
||||||
|
#ifdef CONFIG_TPM
|
||||||
|
object_class_property_add(oc, "tpm-base-addr", "uint64_t",
|
||||||
|
xen_arm_get_tpm_base_addr,
|
||||||
|
xen_arm_set_tpm_base_addr,
|
||||||
|
NULL, NULL);
|
||||||
|
object_class_property_set_description(oc, "tpm-base-addr",
|
||||||
|
"Set Base address for TPM device.");
|
||||||
|
|
||||||
|
machine_class_allow_dynamic_sysbus_dev(mc, TYPE_TPM_TIS_SYSBUS);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static const TypeInfo xen_arm_machine_type = {
|
||||||
|
.name = TYPE_XEN_ARM,
|
||||||
|
.parent = TYPE_MACHINE,
|
||||||
|
.class_init = xen_arm_machine_class_init,
|
||||||
|
.instance_size = sizeof(XenArmState),
|
||||||
|
};
|
||||||
|
|
||||||
|
static void xen_arm_machine_register_types(void)
|
||||||
|
{
|
||||||
|
type_register_static(&xen_arm_machine_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
type_init(xen_arm_machine_register_types)
|
@ -40,9 +40,11 @@ struct VersalVirt {
|
|||||||
uint32_t clk_25Mhz;
|
uint32_t clk_25Mhz;
|
||||||
uint32_t usb;
|
uint32_t usb;
|
||||||
uint32_t dwc;
|
uint32_t dwc;
|
||||||
|
uint32_t canfd[2];
|
||||||
} phandle;
|
} phandle;
|
||||||
struct arm_boot_info binfo;
|
struct arm_boot_info binfo;
|
||||||
|
|
||||||
|
CanBusState *canbus[XLNX_VERSAL_NR_CANFD];
|
||||||
struct {
|
struct {
|
||||||
bool secure;
|
bool secure;
|
||||||
} cfg;
|
} cfg;
|
||||||
@ -235,6 +237,38 @@ static void fdt_add_uart_nodes(VersalVirt *s)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void fdt_add_canfd_nodes(VersalVirt *s)
|
||||||
|
{
|
||||||
|
uint64_t addrs[] = { MM_CANFD1, MM_CANFD0 };
|
||||||
|
uint32_t size[] = { MM_CANFD1_SIZE, MM_CANFD0_SIZE };
|
||||||
|
unsigned int irqs[] = { VERSAL_CANFD1_IRQ_0, VERSAL_CANFD0_IRQ_0 };
|
||||||
|
const char clocknames[] = "can_clk\0s_axi_aclk";
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* Create and connect CANFD0 and CANFD1 nodes to canbus0. */
|
||||||
|
for (i = 0; i < ARRAY_SIZE(addrs); i++) {
|
||||||
|
char *name = g_strdup_printf("/canfd@%" PRIx64, addrs[i]);
|
||||||
|
qemu_fdt_add_subnode(s->fdt, name);
|
||||||
|
|
||||||
|
qemu_fdt_setprop_cell(s->fdt, name, "rx-fifo-depth", 0x40);
|
||||||
|
qemu_fdt_setprop_cell(s->fdt, name, "tx-mailbox-count", 0x20);
|
||||||
|
|
||||||
|
qemu_fdt_setprop_cells(s->fdt, name, "clocks",
|
||||||
|
s->phandle.clk_25Mhz, s->phandle.clk_25Mhz);
|
||||||
|
qemu_fdt_setprop(s->fdt, name, "clock-names",
|
||||||
|
clocknames, sizeof(clocknames));
|
||||||
|
qemu_fdt_setprop_cells(s->fdt, name, "interrupts",
|
||||||
|
GIC_FDT_IRQ_TYPE_SPI, irqs[i],
|
||||||
|
GIC_FDT_IRQ_FLAGS_LEVEL_HI);
|
||||||
|
qemu_fdt_setprop_sized_cells(s->fdt, name, "reg",
|
||||||
|
2, addrs[i], 2, size[i]);
|
||||||
|
qemu_fdt_setprop_string(s->fdt, name, "compatible",
|
||||||
|
"xlnx,canfd-2.0");
|
||||||
|
|
||||||
|
g_free(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void fdt_add_fixed_link_nodes(VersalVirt *s, char *gemname,
|
static void fdt_add_fixed_link_nodes(VersalVirt *s, char *gemname,
|
||||||
uint32_t phandle)
|
uint32_t phandle)
|
||||||
{
|
{
|
||||||
@ -639,12 +673,17 @@ static void versal_virt_init(MachineState *machine)
|
|||||||
TYPE_XLNX_VERSAL);
|
TYPE_XLNX_VERSAL);
|
||||||
object_property_set_link(OBJECT(&s->soc), "ddr", OBJECT(machine->ram),
|
object_property_set_link(OBJECT(&s->soc), "ddr", OBJECT(machine->ram),
|
||||||
&error_abort);
|
&error_abort);
|
||||||
|
object_property_set_link(OBJECT(&s->soc), "canbus0", OBJECT(s->canbus[0]),
|
||||||
|
&error_abort);
|
||||||
|
object_property_set_link(OBJECT(&s->soc), "canbus1", OBJECT(s->canbus[1]),
|
||||||
|
&error_abort);
|
||||||
sysbus_realize(SYS_BUS_DEVICE(&s->soc), &error_fatal);
|
sysbus_realize(SYS_BUS_DEVICE(&s->soc), &error_fatal);
|
||||||
|
|
||||||
fdt_create(s);
|
fdt_create(s);
|
||||||
create_virtio_regions(s);
|
create_virtio_regions(s);
|
||||||
fdt_add_gem_nodes(s);
|
fdt_add_gem_nodes(s);
|
||||||
fdt_add_uart_nodes(s);
|
fdt_add_uart_nodes(s);
|
||||||
|
fdt_add_canfd_nodes(s);
|
||||||
fdt_add_gic_nodes(s);
|
fdt_add_gic_nodes(s);
|
||||||
fdt_add_timer_nodes(s);
|
fdt_add_timer_nodes(s);
|
||||||
fdt_add_zdma_nodes(s);
|
fdt_add_zdma_nodes(s);
|
||||||
@ -712,6 +751,20 @@ static void versal_virt_init(MachineState *machine)
|
|||||||
|
|
||||||
static void versal_virt_machine_instance_init(Object *obj)
|
static void versal_virt_machine_instance_init(Object *obj)
|
||||||
{
|
{
|
||||||
|
VersalVirt *s = XLNX_VERSAL_VIRT_MACHINE(obj);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* User can set canbus0 and canbus1 properties to can-bus object and connect
|
||||||
|
* to socketcan(optional) interface via command line.
|
||||||
|
*/
|
||||||
|
object_property_add_link(obj, "canbus0", TYPE_CAN_BUS,
|
||||||
|
(Object **)&s->canbus[0],
|
||||||
|
object_property_allow_set_link,
|
||||||
|
0);
|
||||||
|
object_property_add_link(obj, "canbus1", TYPE_CAN_BUS,
|
||||||
|
(Object **)&s->canbus[1],
|
||||||
|
object_property_allow_set_link,
|
||||||
|
0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void versal_virt_machine_class_init(ObjectClass *oc, void *data)
|
static void versal_virt_machine_class_init(ObjectClass *oc, void *data)
|
||||||
|
@ -184,6 +184,38 @@ static void versal_create_uarts(Versal *s, qemu_irq *pic)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void versal_create_canfds(Versal *s, qemu_irq *pic)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
uint32_t irqs[] = { VERSAL_CANFD0_IRQ_0, VERSAL_CANFD1_IRQ_0};
|
||||||
|
uint64_t addrs[] = { MM_CANFD0, MM_CANFD1 };
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_SIZE(s->lpd.iou.canfd); i++) {
|
||||||
|
char *name = g_strdup_printf("canfd%d", i);
|
||||||
|
SysBusDevice *sbd;
|
||||||
|
MemoryRegion *mr;
|
||||||
|
|
||||||
|
object_initialize_child(OBJECT(s), name, &s->lpd.iou.canfd[i],
|
||||||
|
TYPE_XILINX_CANFD);
|
||||||
|
sbd = SYS_BUS_DEVICE(&s->lpd.iou.canfd[i]);
|
||||||
|
|
||||||
|
object_property_set_int(OBJECT(&s->lpd.iou.canfd[i]), "ext_clk_freq",
|
||||||
|
XLNX_VERSAL_CANFD_REF_CLK , &error_abort);
|
||||||
|
|
||||||
|
object_property_set_link(OBJECT(&s->lpd.iou.canfd[i]), "canfdbus",
|
||||||
|
OBJECT(s->lpd.iou.canbus[i]),
|
||||||
|
&error_abort);
|
||||||
|
|
||||||
|
sysbus_realize(sbd, &error_fatal);
|
||||||
|
|
||||||
|
mr = sysbus_mmio_get_region(sbd, 0);
|
||||||
|
memory_region_add_subregion(&s->mr_ps, addrs[i], mr);
|
||||||
|
|
||||||
|
sysbus_connect_irq(sbd, 0, pic[irqs[i]]);
|
||||||
|
g_free(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void versal_create_usbs(Versal *s, qemu_irq *pic)
|
static void versal_create_usbs(Versal *s, qemu_irq *pic)
|
||||||
{
|
{
|
||||||
DeviceState *dev;
|
DeviceState *dev;
|
||||||
@ -327,7 +359,7 @@ static void versal_create_rtc(Versal *s, qemu_irq *pic)
|
|||||||
object_initialize_child(OBJECT(s), "rtc", &s->pmc.rtc,
|
object_initialize_child(OBJECT(s), "rtc", &s->pmc.rtc,
|
||||||
TYPE_XLNX_ZYNQMP_RTC);
|
TYPE_XLNX_ZYNQMP_RTC);
|
||||||
sbd = SYS_BUS_DEVICE(&s->pmc.rtc);
|
sbd = SYS_BUS_DEVICE(&s->pmc.rtc);
|
||||||
sysbus_realize(SYS_BUS_DEVICE(sbd), &error_fatal);
|
sysbus_realize(sbd, &error_fatal);
|
||||||
|
|
||||||
mr = sysbus_mmio_get_region(sbd, 0);
|
mr = sysbus_mmio_get_region(sbd, 0);
|
||||||
memory_region_add_subregion(&s->mr_ps, MM_PMC_RTC, mr);
|
memory_region_add_subregion(&s->mr_ps, MM_PMC_RTC, mr);
|
||||||
@ -718,6 +750,7 @@ static void versal_realize(DeviceState *dev, Error **errp)
|
|||||||
versal_create_apu_gic(s, pic);
|
versal_create_apu_gic(s, pic);
|
||||||
versal_create_rpu_cpus(s);
|
versal_create_rpu_cpus(s);
|
||||||
versal_create_uarts(s, pic);
|
versal_create_uarts(s, pic);
|
||||||
|
versal_create_canfds(s, pic);
|
||||||
versal_create_usbs(s, pic);
|
versal_create_usbs(s, pic);
|
||||||
versal_create_gems(s, pic);
|
versal_create_gems(s, pic);
|
||||||
versal_create_admas(s, pic);
|
versal_create_admas(s, pic);
|
||||||
@ -757,6 +790,10 @@ static void versal_init(Object *obj)
|
|||||||
static Property versal_properties[] = {
|
static Property versal_properties[] = {
|
||||||
DEFINE_PROP_LINK("ddr", Versal, cfg.mr_ddr, TYPE_MEMORY_REGION,
|
DEFINE_PROP_LINK("ddr", Versal, cfg.mr_ddr, TYPE_MEMORY_REGION,
|
||||||
MemoryRegion *),
|
MemoryRegion *),
|
||||||
|
DEFINE_PROP_LINK("canbus0", Versal, lpd.iou.canbus[0],
|
||||||
|
TYPE_CAN_BUS, CanBusState *),
|
||||||
|
DEFINE_PROP_LINK("canbus1", Versal, lpd.iou.canbus[1],
|
||||||
|
TYPE_CAN_BUS, CanBusState *),
|
||||||
DEFINE_PROP_END_OF_LIST()
|
DEFINE_PROP_END_OF_LIST()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
softmmu_ss.add(files('soundhw.c'))
|
system_ss.add(files('soundhw.c'))
|
||||||
softmmu_ss.add(when: 'CONFIG_AC97', if_true: files('ac97.c'))
|
system_ss.add(when: 'CONFIG_AC97', if_true: files('ac97.c'))
|
||||||
softmmu_ss.add(when: 'CONFIG_ADLIB', if_true: files('fmopl.c', 'adlib.c'))
|
system_ss.add(when: 'CONFIG_ADLIB', if_true: files('fmopl.c', 'adlib.c'))
|
||||||
softmmu_ss.add(when: 'CONFIG_CS4231', if_true: files('cs4231.c'))
|
system_ss.add(when: 'CONFIG_CS4231', if_true: files('cs4231.c'))
|
||||||
softmmu_ss.add(when: 'CONFIG_CS4231A', if_true: files('cs4231a.c'))
|
system_ss.add(when: 'CONFIG_CS4231A', if_true: files('cs4231a.c'))
|
||||||
softmmu_ss.add(when: 'CONFIG_ES1370', if_true: files('es1370.c'))
|
system_ss.add(when: 'CONFIG_ES1370', if_true: files('es1370.c'))
|
||||||
softmmu_ss.add(when: 'CONFIG_GUS', if_true: files('gus.c', 'gusemu_hal.c', 'gusemu_mixer.c'))
|
system_ss.add(when: 'CONFIG_GUS', if_true: files('gus.c', 'gusemu_hal.c', 'gusemu_mixer.c'))
|
||||||
softmmu_ss.add(when: 'CONFIG_HDA', if_true: files('intel-hda.c', 'hda-codec.c'))
|
system_ss.add(when: 'CONFIG_HDA', if_true: files('intel-hda.c', 'hda-codec.c'))
|
||||||
softmmu_ss.add(when: 'CONFIG_MARVELL_88W8618', if_true: files('marvell_88w8618.c'))
|
system_ss.add(when: 'CONFIG_MARVELL_88W8618', if_true: files('marvell_88w8618.c'))
|
||||||
softmmu_ss.add(when: 'CONFIG_PCSPK', if_true: files('pcspk.c'))
|
system_ss.add(when: 'CONFIG_PCSPK', if_true: files('pcspk.c'))
|
||||||
softmmu_ss.add(when: 'CONFIG_PL041', if_true: files('pl041.c', 'lm4549.c'))
|
system_ss.add(when: 'CONFIG_PL041', if_true: files('pl041.c', 'lm4549.c'))
|
||||||
softmmu_ss.add(when: 'CONFIG_SB16', if_true: files('sb16.c'))
|
system_ss.add(when: 'CONFIG_SB16', if_true: files('sb16.c'))
|
||||||
softmmu_ss.add(when: 'CONFIG_VT82C686', if_true: files('via-ac97.c'))
|
system_ss.add(when: 'CONFIG_VT82C686', if_true: files('via-ac97.c'))
|
||||||
softmmu_ss.add(when: 'CONFIG_WM8750', if_true: files('wm8750.c'))
|
system_ss.add(when: 'CONFIG_WM8750', if_true: files('wm8750.c'))
|
||||||
|
@ -1,21 +1,21 @@
|
|||||||
softmmu_ss.add(files(
|
system_ss.add(files(
|
||||||
'block.c',
|
'block.c',
|
||||||
'cdrom.c',
|
'cdrom.c',
|
||||||
'hd-geometry.c'
|
'hd-geometry.c'
|
||||||
))
|
))
|
||||||
softmmu_ss.add(when: 'CONFIG_ECC', if_true: files('ecc.c'))
|
system_ss.add(when: 'CONFIG_ECC', if_true: files('ecc.c'))
|
||||||
softmmu_ss.add(when: 'CONFIG_FDC', if_true: files('fdc.c'))
|
system_ss.add(when: 'CONFIG_FDC', if_true: files('fdc.c'))
|
||||||
softmmu_ss.add(when: 'CONFIG_FDC_ISA', if_true: files('fdc-isa.c'))
|
system_ss.add(when: 'CONFIG_FDC_ISA', if_true: files('fdc-isa.c'))
|
||||||
softmmu_ss.add(when: 'CONFIG_FDC_SYSBUS', if_true: files('fdc-sysbus.c'))
|
system_ss.add(when: 'CONFIG_FDC_SYSBUS', if_true: files('fdc-sysbus.c'))
|
||||||
softmmu_ss.add(when: 'CONFIG_NAND', if_true: files('nand.c'))
|
system_ss.add(when: 'CONFIG_NAND', if_true: files('nand.c'))
|
||||||
softmmu_ss.add(when: 'CONFIG_ONENAND', if_true: files('onenand.c'))
|
system_ss.add(when: 'CONFIG_ONENAND', if_true: files('onenand.c'))
|
||||||
softmmu_ss.add(when: 'CONFIG_PFLASH_CFI01', if_true: files('pflash_cfi01.c'))
|
system_ss.add(when: 'CONFIG_PFLASH_CFI01', if_true: files('pflash_cfi01.c'))
|
||||||
softmmu_ss.add(when: 'CONFIG_PFLASH_CFI02', if_true: files('pflash_cfi02.c'))
|
system_ss.add(when: 'CONFIG_PFLASH_CFI02', if_true: files('pflash_cfi02.c'))
|
||||||
softmmu_ss.add(when: 'CONFIG_SSI_M25P80', if_true: files('m25p80.c'))
|
system_ss.add(when: 'CONFIG_SSI_M25P80', if_true: files('m25p80.c'))
|
||||||
softmmu_ss.add(when: 'CONFIG_SSI_M25P80', if_true: files('m25p80_sfdp.c'))
|
system_ss.add(when: 'CONFIG_SSI_M25P80', if_true: files('m25p80_sfdp.c'))
|
||||||
softmmu_ss.add(when: 'CONFIG_SWIM', if_true: files('swim.c'))
|
system_ss.add(when: 'CONFIG_SWIM', if_true: files('swim.c'))
|
||||||
softmmu_ss.add(when: 'CONFIG_XEN_BUS', if_true: files('xen-block.c'))
|
system_ss.add(when: 'CONFIG_XEN_BUS', if_true: files('xen-block.c'))
|
||||||
softmmu_ss.add(when: 'CONFIG_TC58128', if_true: files('tc58128.c'))
|
system_ss.add(when: 'CONFIG_TC58128', if_true: files('tc58128.c'))
|
||||||
|
|
||||||
specific_ss.add(when: 'CONFIG_VIRTIO_BLK', if_true: files('virtio-blk.c', 'virtio-blk-common.c'))
|
specific_ss.add(when: 'CONFIG_VIRTIO_BLK', if_true: files('virtio-blk.c', 'virtio-blk-common.c'))
|
||||||
specific_ss.add(when: 'CONFIG_VHOST_USER_BLK', if_true: files('vhost-user-blk.c', 'virtio-blk-common.c'))
|
specific_ss.add(when: 'CONFIG_VHOST_USER_BLK', if_true: files('vhost-user-blk.c', 'virtio-blk-common.c'))
|
||||||
|
@ -80,7 +80,7 @@ static void imx_update(IMXSerialState *s)
|
|||||||
* TCEN and TXDC are both bit 3
|
* TCEN and TXDC are both bit 3
|
||||||
* RDR and DREN are both bit 0
|
* RDR and DREN are both bit 0
|
||||||
*/
|
*/
|
||||||
mask |= s->ucr4 & (UCR4_TCEN | UCR4_DREN);
|
mask |= s->ucr4 & (UCR4_WKEN | UCR4_TCEN | UCR4_DREN);
|
||||||
|
|
||||||
usr2 = s->usr2 & mask;
|
usr2 = s->usr2 & mask;
|
||||||
|
|
||||||
@ -321,6 +321,9 @@ static void imx_put_data(void *opaque, uint32_t value)
|
|||||||
|
|
||||||
static void imx_receive(void *opaque, const uint8_t *buf, int size)
|
static void imx_receive(void *opaque, const uint8_t *buf, int size)
|
||||||
{
|
{
|
||||||
|
IMXSerialState *s = (IMXSerialState *)opaque;
|
||||||
|
|
||||||
|
s->usr2 |= USR2_WAKE;
|
||||||
imx_put_data(opaque, *buf);
|
imx_put_data(opaque, *buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,39 +1,39 @@
|
|||||||
softmmu_ss.add(when: 'CONFIG_CADENCE', if_true: files('cadence_uart.c'))
|
system_ss.add(when: 'CONFIG_CADENCE', if_true: files('cadence_uart.c'))
|
||||||
softmmu_ss.add(when: 'CONFIG_CMSDK_APB_UART', if_true: files('cmsdk-apb-uart.c'))
|
system_ss.add(when: 'CONFIG_CMSDK_APB_UART', if_true: files('cmsdk-apb-uart.c'))
|
||||||
softmmu_ss.add(when: 'CONFIG_ESCC', if_true: files('escc.c'))
|
system_ss.add(when: 'CONFIG_ESCC', if_true: files('escc.c'))
|
||||||
softmmu_ss.add(when: 'CONFIG_ETRAXFS', if_true: files('etraxfs_ser.c'))
|
system_ss.add(when: 'CONFIG_ETRAXFS', if_true: files('etraxfs_ser.c'))
|
||||||
softmmu_ss.add(when: 'CONFIG_GRLIB', if_true: files('grlib_apbuart.c'))
|
system_ss.add(when: 'CONFIG_GRLIB', if_true: files('grlib_apbuart.c'))
|
||||||
softmmu_ss.add(when: 'CONFIG_IBEX', if_true: files('ibex_uart.c'))
|
system_ss.add(when: 'CONFIG_IBEX', if_true: files('ibex_uart.c'))
|
||||||
softmmu_ss.add(when: 'CONFIG_IMX', if_true: files('imx_serial.c'))
|
system_ss.add(when: 'CONFIG_IMX', if_true: files('imx_serial.c'))
|
||||||
softmmu_ss.add(when: 'CONFIG_IPACK', if_true: files('ipoctal232.c'))
|
system_ss.add(when: 'CONFIG_IPACK', if_true: files('ipoctal232.c'))
|
||||||
softmmu_ss.add(when: 'CONFIG_ISA_BUS', if_true: files('parallel-isa.c'))
|
system_ss.add(when: 'CONFIG_ISA_BUS', if_true: files('parallel-isa.c'))
|
||||||
softmmu_ss.add(when: 'CONFIG_ISA_DEBUG', if_true: files('debugcon.c'))
|
system_ss.add(when: 'CONFIG_ISA_DEBUG', if_true: files('debugcon.c'))
|
||||||
softmmu_ss.add(when: 'CONFIG_NRF51_SOC', if_true: files('nrf51_uart.c'))
|
system_ss.add(when: 'CONFIG_NRF51_SOC', if_true: files('nrf51_uart.c'))
|
||||||
softmmu_ss.add(when: 'CONFIG_PARALLEL', if_true: files('parallel.c'))
|
system_ss.add(when: 'CONFIG_PARALLEL', if_true: files('parallel.c'))
|
||||||
softmmu_ss.add(when: 'CONFIG_PL011', if_true: files('pl011.c'))
|
system_ss.add(when: 'CONFIG_PL011', if_true: files('pl011.c'))
|
||||||
softmmu_ss.add(when: 'CONFIG_SCLPCONSOLE', if_true: files('sclpconsole.c', 'sclpconsole-lm.c'))
|
system_ss.add(when: 'CONFIG_SCLPCONSOLE', if_true: files('sclpconsole.c', 'sclpconsole-lm.c'))
|
||||||
softmmu_ss.add(when: 'CONFIG_SERIAL', if_true: files('serial.c'))
|
system_ss.add(when: 'CONFIG_SERIAL', if_true: files('serial.c'))
|
||||||
softmmu_ss.add(when: 'CONFIG_SERIAL_ISA', if_true: files('serial-isa.c'))
|
system_ss.add(when: 'CONFIG_SERIAL_ISA', if_true: files('serial-isa.c'))
|
||||||
softmmu_ss.add(when: 'CONFIG_SERIAL_PCI', if_true: files('serial-pci.c'))
|
system_ss.add(when: 'CONFIG_SERIAL_PCI', if_true: files('serial-pci.c'))
|
||||||
softmmu_ss.add(when: 'CONFIG_SERIAL_PCI_MULTI', if_true: files('serial-pci-multi.c'))
|
system_ss.add(when: 'CONFIG_SERIAL_PCI_MULTI', if_true: files('serial-pci-multi.c'))
|
||||||
softmmu_ss.add(when: 'CONFIG_SHAKTI_UART', if_true: files('shakti_uart.c'))
|
system_ss.add(when: 'CONFIG_SHAKTI_UART', if_true: files('shakti_uart.c'))
|
||||||
softmmu_ss.add(when: 'CONFIG_VIRTIO_SERIAL', if_true: files('virtio-console.c'))
|
system_ss.add(when: 'CONFIG_VIRTIO_SERIAL', if_true: files('virtio-console.c'))
|
||||||
softmmu_ss.add(when: 'CONFIG_XEN_BUS', if_true: files('xen_console.c'))
|
system_ss.add(when: 'CONFIG_XEN_BUS', if_true: files('xen_console.c'))
|
||||||
softmmu_ss.add(when: 'CONFIG_XILINX', if_true: files('xilinx_uartlite.c'))
|
system_ss.add(when: 'CONFIG_XILINX', if_true: files('xilinx_uartlite.c'))
|
||||||
|
|
||||||
softmmu_ss.add(when: 'CONFIG_AVR_USART', if_true: files('avr_usart.c'))
|
system_ss.add(when: 'CONFIG_AVR_USART', if_true: files('avr_usart.c'))
|
||||||
softmmu_ss.add(when: 'CONFIG_COLDFIRE', if_true: files('mcf_uart.c'))
|
system_ss.add(when: 'CONFIG_COLDFIRE', if_true: files('mcf_uart.c'))
|
||||||
softmmu_ss.add(when: 'CONFIG_DIGIC', if_true: files('digic-uart.c'))
|
system_ss.add(when: 'CONFIG_DIGIC', if_true: files('digic-uart.c'))
|
||||||
softmmu_ss.add(when: 'CONFIG_EXYNOS4', if_true: files('exynos4210_uart.c'))
|
system_ss.add(when: 'CONFIG_EXYNOS4', if_true: files('exynos4210_uart.c'))
|
||||||
softmmu_ss.add(when: 'CONFIG_OMAP', if_true: files('omap_uart.c'))
|
system_ss.add(when: 'CONFIG_OMAP', if_true: files('omap_uart.c'))
|
||||||
softmmu_ss.add(when: 'CONFIG_RASPI', if_true: files('bcm2835_aux.c'))
|
system_ss.add(when: 'CONFIG_RASPI', if_true: files('bcm2835_aux.c'))
|
||||||
softmmu_ss.add(when: 'CONFIG_RENESAS_SCI', if_true: files('renesas_sci.c'))
|
system_ss.add(when: 'CONFIG_RENESAS_SCI', if_true: files('renesas_sci.c'))
|
||||||
softmmu_ss.add(when: 'CONFIG_SIFIVE_UART', if_true: files('sifive_uart.c'))
|
system_ss.add(when: 'CONFIG_SIFIVE_UART', if_true: files('sifive_uart.c'))
|
||||||
softmmu_ss.add(when: 'CONFIG_SH_SCI', if_true: files('sh_serial.c'))
|
system_ss.add(when: 'CONFIG_SH_SCI', if_true: files('sh_serial.c'))
|
||||||
softmmu_ss.add(when: 'CONFIG_STM32F2XX_USART', if_true: files('stm32f2xx_usart.c'))
|
system_ss.add(when: 'CONFIG_STM32F2XX_USART', if_true: files('stm32f2xx_usart.c'))
|
||||||
softmmu_ss.add(when: 'CONFIG_MCHP_PFSOC_MMUART', if_true: files('mchp_pfsoc_mmuart.c'))
|
system_ss.add(when: 'CONFIG_MCHP_PFSOC_MMUART', if_true: files('mchp_pfsoc_mmuart.c'))
|
||||||
softmmu_ss.add(when: 'CONFIG_HTIF', if_true: files('riscv_htif.c'))
|
system_ss.add(when: 'CONFIG_HTIF', if_true: files('riscv_htif.c'))
|
||||||
softmmu_ss.add(when: 'CONFIG_GOLDFISH_TTY', if_true: files('goldfish_tty.c'))
|
system_ss.add(when: 'CONFIG_GOLDFISH_TTY', if_true: files('goldfish_tty.c'))
|
||||||
|
|
||||||
specific_ss.add(when: 'CONFIG_TERMINAL3270', if_true: files('terminal3270.c'))
|
specific_ss.add(when: 'CONFIG_TERMINAL3270', if_true: files('terminal3270.c'))
|
||||||
specific_ss.add(when: 'CONFIG_VIRTIO', if_true: files('virtio-serial-bus.c'))
|
specific_ss.add(when: 'CONFIG_VIRTIO', if_true: files('virtio-serial-bus.c'))
|
||||||
|
@ -175,12 +175,3 @@ struct omap_uart_s *omap2_uart_init(MemoryRegion *sysmem,
|
|||||||
|
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
void omap_uart_attach(struct omap_uart_s *s, Chardev *chr)
|
|
||||||
{
|
|
||||||
/* TODO: Should reuse or destroy current s->serial */
|
|
||||||
s->serial = serial_mm_init(get_system_memory(), s->base, 2, s->irq,
|
|
||||||
omap_clk_getrate(s->fclk) / 16,
|
|
||||||
chr ?: qemu_chr_new("null", "null", NULL),
|
|
||||||
DEVICE_NATIVE_ENDIAN);
|
|
||||||
}
|
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
#include "sysemu/sysemu.h"
|
#include "sysemu/sysemu.h"
|
||||||
#include "hw/isa/isa.h"
|
#include "hw/isa/isa.h"
|
||||||
#include "hw/qdev-properties.h"
|
#include "hw/qdev-properties.h"
|
||||||
|
#include "hw/char/parallel-isa.h"
|
||||||
#include "hw/char/parallel.h"
|
#include "hw/char/parallel.h"
|
||||||
#include "qapi/error.h"
|
#include "qapi/error.h"
|
||||||
|
|
||||||
|
@ -27,13 +27,11 @@
|
|||||||
#include "qapi/error.h"
|
#include "qapi/error.h"
|
||||||
#include "qemu/module.h"
|
#include "qemu/module.h"
|
||||||
#include "chardev/char-parallel.h"
|
#include "chardev/char-parallel.h"
|
||||||
#include "chardev/char-fe.h"
|
|
||||||
#include "hw/acpi/acpi_aml_interface.h"
|
#include "hw/acpi/acpi_aml_interface.h"
|
||||||
#include "hw/irq.h"
|
|
||||||
#include "hw/isa/isa.h"
|
|
||||||
#include "hw/qdev-properties.h"
|
#include "hw/qdev-properties.h"
|
||||||
#include "hw/qdev-properties-system.h"
|
#include "hw/qdev-properties-system.h"
|
||||||
#include "migration/vmstate.h"
|
#include "migration/vmstate.h"
|
||||||
|
#include "hw/char/parallel-isa.h"
|
||||||
#include "hw/char/parallel.h"
|
#include "hw/char/parallel.h"
|
||||||
#include "sysemu/reset.h"
|
#include "sysemu/reset.h"
|
||||||
#include "sysemu/sysemu.h"
|
#include "sysemu/sysemu.h"
|
||||||
@ -76,34 +74,6 @@
|
|||||||
|
|
||||||
#define PARA_CTR_SIGNAL (PARA_CTR_SELECT|PARA_CTR_INIT|PARA_CTR_AUTOLF|PARA_CTR_STROBE)
|
#define PARA_CTR_SIGNAL (PARA_CTR_SELECT|PARA_CTR_INIT|PARA_CTR_AUTOLF|PARA_CTR_STROBE)
|
||||||
|
|
||||||
typedef struct ParallelState {
|
|
||||||
MemoryRegion iomem;
|
|
||||||
uint8_t dataw;
|
|
||||||
uint8_t datar;
|
|
||||||
uint8_t status;
|
|
||||||
uint8_t control;
|
|
||||||
qemu_irq irq;
|
|
||||||
int irq_pending;
|
|
||||||
CharBackend chr;
|
|
||||||
int hw_driver;
|
|
||||||
int epp_timeout;
|
|
||||||
uint32_t last_read_offset; /* For debugging */
|
|
||||||
/* Memory-mapped interface */
|
|
||||||
int it_shift;
|
|
||||||
PortioList portio_list;
|
|
||||||
} ParallelState;
|
|
||||||
|
|
||||||
OBJECT_DECLARE_SIMPLE_TYPE(ISAParallelState, ISA_PARALLEL)
|
|
||||||
|
|
||||||
struct ISAParallelState {
|
|
||||||
ISADevice parent_obj;
|
|
||||||
|
|
||||||
uint32_t index;
|
|
||||||
uint32_t iobase;
|
|
||||||
uint32_t isairq;
|
|
||||||
ParallelState state;
|
|
||||||
};
|
|
||||||
|
|
||||||
static void parallel_update_irq(ParallelState *s)
|
static void parallel_update_irq(ParallelState *s)
|
||||||
{
|
{
|
||||||
if (s->irq_pending)
|
if (s->irq_pending)
|
||||||
|
@ -196,8 +196,7 @@ static void cpu_common_realizefn(DeviceState *dev, Error **errp)
|
|||||||
* no need to check the ignore_memory_transaction_failures board flag.
|
* no need to check the ignore_memory_transaction_failures board flag.
|
||||||
*/
|
*/
|
||||||
if (object_dynamic_cast(machine, TYPE_MACHINE)) {
|
if (object_dynamic_cast(machine, TYPE_MACHINE)) {
|
||||||
ObjectClass *oc = object_get_class(machine);
|
MachineClass *mc = MACHINE_GET_CLASS(machine);
|
||||||
MachineClass *mc = MACHINE_CLASS(oc);
|
|
||||||
|
|
||||||
if (mc) {
|
if (mc) {
|
||||||
cpu->ignore_memory_transaction_failures =
|
cpu->ignore_memory_transaction_failures =
|
||||||
|
@ -24,18 +24,18 @@ endif
|
|||||||
|
|
||||||
common_ss.add(files('cpu-common.c'))
|
common_ss.add(files('cpu-common.c'))
|
||||||
common_ss.add(files('machine-smp.c'))
|
common_ss.add(files('machine-smp.c'))
|
||||||
softmmu_ss.add(when: 'CONFIG_FITLOADER', if_true: files('loader-fit.c'))
|
system_ss.add(when: 'CONFIG_FITLOADER', if_true: files('loader-fit.c'))
|
||||||
softmmu_ss.add(when: 'CONFIG_GENERIC_LOADER', if_true: files('generic-loader.c'))
|
system_ss.add(when: 'CONFIG_GENERIC_LOADER', if_true: files('generic-loader.c'))
|
||||||
softmmu_ss.add(when: ['CONFIG_GUEST_LOADER', fdt], if_true: files('guest-loader.c'))
|
system_ss.add(when: ['CONFIG_GUEST_LOADER', fdt], if_true: files('guest-loader.c'))
|
||||||
softmmu_ss.add(when: 'CONFIG_OR_IRQ', if_true: files('or-irq.c'))
|
system_ss.add(when: 'CONFIG_OR_IRQ', if_true: files('or-irq.c'))
|
||||||
softmmu_ss.add(when: 'CONFIG_PLATFORM_BUS', if_true: files('platform-bus.c'))
|
system_ss.add(when: 'CONFIG_PLATFORM_BUS', if_true: files('platform-bus.c'))
|
||||||
softmmu_ss.add(when: 'CONFIG_PTIMER', if_true: files('ptimer.c'))
|
system_ss.add(when: 'CONFIG_PTIMER', if_true: files('ptimer.c'))
|
||||||
softmmu_ss.add(when: 'CONFIG_REGISTER', if_true: files('register.c'))
|
system_ss.add(when: 'CONFIG_REGISTER', if_true: files('register.c'))
|
||||||
softmmu_ss.add(when: 'CONFIG_SPLIT_IRQ', if_true: files('split-irq.c'))
|
system_ss.add(when: 'CONFIG_SPLIT_IRQ', if_true: files('split-irq.c'))
|
||||||
softmmu_ss.add(when: 'CONFIG_XILINX_AXI', if_true: files('stream.c'))
|
system_ss.add(when: 'CONFIG_XILINX_AXI', if_true: files('stream.c'))
|
||||||
softmmu_ss.add(when: 'CONFIG_PLATFORM_BUS', if_true: files('sysbus-fdt.c'))
|
system_ss.add(when: 'CONFIG_PLATFORM_BUS', if_true: files('sysbus-fdt.c'))
|
||||||
|
|
||||||
softmmu_ss.add(files(
|
system_ss.add(files(
|
||||||
'cpu-sysemu.c',
|
'cpu-sysemu.c',
|
||||||
'fw-path-provider.c',
|
'fw-path-provider.c',
|
||||||
'gpio.c',
|
'gpio.c',
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user