This commit is contained in:
Andrea Fioraldi 2023-06-21 15:51:34 +02:00
commit 5018a0766b
600 changed files with 22296 additions and 11388 deletions

2
.gitignore vendored
View File

@ -22,5 +22,3 @@ GTAGS
*.swp *.swp
*.patch *.patch
*.gcov *.gcov
/subprojects/slirp

View File

@ -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=":"

View File

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

View File

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

View File

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

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

View File

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

View File

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

View File

@ -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"),

View File

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

View File

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

View File

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

View File

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

View File

@ -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();

View File

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

View File

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

View File

@ -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);
} }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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()) {

View File

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

View File

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

View File

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

View File

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

View File

@ -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));
}

View File

@ -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);
} }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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);
} }

View File

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

View File

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

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

@ -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); |
+--------------------------------+ +--------------------------------+

View File

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

View File

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

View File

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

View File

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

View 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

View File

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

View File

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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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));
} }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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);
} }
} }
} }

View File

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

View File

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

View File

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

View File

@ -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()
}; };

View File

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

View File

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

View File

@ -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);
} }

View File

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

View File

@ -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);
}

View File

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

View File

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

View File

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

View File

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