Merge branch 'master' into enable_libusb

This commit is contained in:
Fred Hallock 2025-02-16 13:26:32 -05:00 committed by GitHub
commit 173bba197c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
99 changed files with 745 additions and 236 deletions

View File

@ -93,8 +93,8 @@ jobs:
uses: actions/cache@v4
with:
path: /tmp/xemu-ccache
key: cache-wincross-${{ runner.os }}-${{ matrix.configuration }}-${{ github.sha }}
restore-keys: cache-wincross-${{ runner.os }}-${{ matrix.configuration }}-
key: cache-wincross-${{ runner.os }}-${{ matrix.arch }}-${{ matrix.configuration }}-${{ github.sha }}
restore-keys: cache-wincross-${{ runner.os }}-${{ matrix.arch }}-${{ matrix.configuration }}-
- name: Pull Docker image
run: docker pull $DOCKER_IMAGE_NAME
- name: Compile
@ -163,28 +163,44 @@ jobs:
path: dist
Ubuntu:
name: Build for Ubuntu (${{ matrix.configuration }})
runs-on: ubuntu-latest
name: Build for Ubuntu (${{matrix.arch}}, ${{ matrix.configuration }})
runs-on: ${{ matrix.runs-on }}
needs: Init
strategy:
matrix:
include:
- configuration: Debug
- arch: x86_64
configuration: Debug
build_param: --debug
artifact_name: xemu-ubuntu-debug
artifact_filename: xemu-ubuntu-debug.tgz
- configuration: Release
artifact_name: xemu-ubuntu-x86_64-debug
artifact_filename: xemu-ubuntu-x86_64-debug.tgz
runs-on: ubuntu-24.04
- arch: x86_64
configuration: Release
build_param:
artifact_name: xemu-ubuntu-release
artifact_filename: xemu-ubuntu-release.tgz
artifact_name: xemu-ubuntu-x86_64-release
artifact_filename: xemu-ubuntu-x86_64-release.tgz
runs-on: ubuntu-22.04
- arch: aarch64
configuration: Debug
build_param: --debug
artifact_name: xemu-ubuntu-aarch64-debug
artifact_filename: xemu-ubuntu-aarch64-debug.tgz
runs-on: ubuntu-24.04-arm
- arch: aarch64
configuration: Release
build_param:
artifact_name: xemu-ubuntu-aarch64-release
artifact_filename: xemu-ubuntu-aarch64-release.tgz
runs-on: ubuntu-24.04-arm
steps:
- name: Initialize compiler cache
id: cache
uses: actions/cache@v4
with:
path: /tmp/xemu-ccache
key: cache-${{ runner.os }}-${{ matrix.configuration }}-${{ github.sha }}
restore-keys: cache-${{ runner.os }}-${{ matrix.configuration }}-
key: cache-${{ runner.os }}-${{ matrix.arch }}-${{ matrix.configuration }}-${{ github.sha }}
restore-keys: cache-${{ runner.os }}-${{ matrix.arch }}-${{ matrix.configuration }}-
- name: Download source package
uses: actions/download-artifact@v4
with:
@ -231,8 +247,8 @@ jobs:
ccache -s
- name: Generate AppImage
run: |
wget --no-verbose https://github.com/linuxdeploy/linuxdeploy/releases/latest/download/linuxdeploy-x86_64.AppImage
chmod +x linuxdeploy-x86_64.AppImage
wget --no-verbose https://github.com/linuxdeploy/linuxdeploy/releases/latest/download/linuxdeploy-${{ matrix.arch }}.AppImage
chmod +x linuxdeploy-${{ matrix.arch }}.AppImage
ar x dist/*.deb
mkdir appimage
@ -244,7 +260,7 @@ jobs:
export VERSION=$VERSION-dbg
fi
./linuxdeploy-x86_64.AppImage --output appimage --appdir appimage
./linuxdeploy-${{ matrix.arch }}.AppImage --output appimage --appdir appimage
mv xemu-*.AppImage dist
- name: Bundle artifacts
run: |
@ -388,13 +404,13 @@ jobs:
echo "XEMU_VERSION=$(cat XEMU_VERSION)" >> $GITHUB_ENV
- name: Extract Ubuntu artifacts
run: |
pushd dist/xemu-ubuntu-release
tar xvf xemu-ubuntu-release.tgz
popd
pushd dist/xemu-ubuntu-debug
tar xvf xemu-ubuntu-debug.tgz
popd
for arch in x86_64 aarch64; do
for config in release debug; do
pushd dist/xemu-ubuntu-$arch-$config
tar xvf xemu-ubuntu-$arch-$config.tgz
popd
done
done
# Architecture tags were recently added to the Windows release path. Provide an alias with the former name for a while.
- name: Add transitionary package alias
run: |
@ -419,8 +435,10 @@ jobs:
dist/xemu-win-x86_64-release-pdb/xemu-win-release.zip
dist/xemu-macos-universal-release/xemu-macos-universal-release.zip
dist/xemu-macos-universal-debug/xemu-macos-universal-debug.zip
dist/xemu-ubuntu-release/xemu/xemu-v${{ env.XEMU_VERSION }}-x86_64.AppImage
dist/xemu-ubuntu-debug/xemu/xemu-v${{ env.XEMU_VERSION }}-dbg-x86_64.AppImage
dist/xemu-ubuntu-x86_64-debug/xemu/xemu-v${{ env.XEMU_VERSION }}-dbg-x86_64.AppImage
dist/xemu-ubuntu-x86_64-release/xemu/xemu-v${{ env.XEMU_VERSION }}-x86_64.AppImage
dist/xemu-ubuntu-aarch64-debug/xemu/xemu-v${{ env.XEMU_VERSION }}-dbg-aarch64.AppImage
dist/xemu-ubuntu-aarch64-release/xemu/xemu-v${{ env.XEMU_VERSION }}-aarch64.AppImage
- name: Trigger website update
uses: benc-uk/workflow-dispatch@v1.2.2
with:

View File

@ -1 +1 @@
9.2.0
9.2.1

View File

@ -437,6 +437,16 @@ int kvm_unpark_vcpu(KVMState *s, unsigned long vcpu_id)
return kvm_fd;
}
static void kvm_reset_parked_vcpus(void *param)
{
KVMState *s = param;
struct KVMParkedVcpu *cpu;
QLIST_FOREACH(cpu, &s->kvm_parked_vcpus, node) {
kvm_arch_reset_parked_vcpu(cpu->vcpu_id, cpu->kvm_fd);
}
}
int kvm_create_vcpu(CPUState *cpu)
{
unsigned long vcpu_id = kvm_arch_vcpu_id(cpu);
@ -2728,6 +2738,7 @@ static int kvm_init(MachineState *ms)
}
qemu_register_reset(kvm_unpoison_all, NULL);
qemu_register_reset(kvm_reset_parked_vcpus, s);
if (s->kernel_irqchip_allowed) {
kvm_irqchip_create(s);

View File

@ -281,8 +281,7 @@ static int cryptodev_vhost_user_create_session(
break;
default:
error_setg(&local_error, "Unsupported opcode :%" PRIu32 "",
sess_info->op_code);
error_report("Unsupported opcode :%" PRIu32 "", sess_info->op_code);
return -VIRTIO_CRYPTO_NOTSUPP;
}

View File

@ -151,7 +151,7 @@ display:
fullscreen_exclusive: bool
startup_size:
type: enum
values: [last_used, 640x480, 1280x720, 1280x800, 1280x960, 1920x1080, 2560x1440, 2560x1600, 2560x1920, 3840x2160]
values: [last_used, 640x480, 720x480, 1280x720, 1280x800, 1280x960, 1920x1080, 2560x1440, 2560x1600, 2560x1920, 3840x2160]
default: 1280x960
last_width:
type: integer

View File

@ -1,4 +1,5 @@
TARGET_ARCH=i386
TARGET_SUPPORTS_MTTCG=y
TARGET_KVM_HAVE_GUEST_DEBUG=y
TARGET_KVM_HAVE_RESET_PARKED_VCPU=y
TARGET_XML_FILES= gdb-xml/i386-32bit.xml

View File

@ -2,4 +2,5 @@ TARGET_ARCH=x86_64
TARGET_BASE_ARCH=i386
TARGET_SUPPORTS_MTTCG=y
TARGET_KVM_HAVE_GUEST_DEBUG=y
TARGET_KVM_HAVE_RESET_PARKED_VCPU=y
TARGET_XML_FILES= gdb-xml/i386-64bit.xml

View File

@ -107,7 +107,7 @@ static void *threaded_qcrypto_pbkdf2_count_iters(void *data)
size_t nsalt = iters_data->nsalt;
size_t nout = iters_data->nout;
Error **errp = iters_data->errp;
size_t scaled = 0;
uint64_t ret = -1;
g_autofree uint8_t *out = g_new(uint8_t, nout);
uint64_t iterations = (1 << 15);
@ -131,7 +131,17 @@ static void *threaded_qcrypto_pbkdf2_count_iters(void *data)
delta_ms = end_ms - start_ms;
if (delta_ms == 0) { /* sanity check */
/*
* For very small 'iterations' values, CPU (or crypto
* accelerator) might be fast enough that the scheduler
* hasn't incremented getrusage() data, or incremented
* it by a very small amount, resulting in delta_ms == 0.
* Once we've scaled 'iterations' x10, 5 times, we really
* should be seeing delta_ms != 0, so sanity check at
* that point.
*/
if (scaled > 5 &&
delta_ms == 0) { /* sanity check */
error_setg(errp, "Unable to get accurate CPU usage");
goto cleanup;
} else if (delta_ms > 500) {
@ -141,6 +151,7 @@ static void *threaded_qcrypto_pbkdf2_count_iters(void *data)
} else {
iterations = (iterations * 1000 / delta_ms);
}
scaled++;
}
iterations = iterations * 1000 / delta_ms;

View File

@ -75,7 +75,7 @@ marked deprecated since 9.0, users have to ensure that all the topology members
described with -smp are supported by the target machine.
``-runas`` (since 9.1)
----------------------
''''''''''''''''''''''
Use ``-run-with user=..`` instead.

View File

@ -518,7 +518,7 @@ and later do not support it because the virtio-scsi device was introduced for
full SCSI support. Use virtio-scsi instead when SCSI passthrough is required.
``-fsdev proxy`` and ``-virtfs proxy`` (since 9.2)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
''''''''''''''''''''''''''''''''''''''''''''''''''
The 9p ``proxy`` filesystem backend driver was originally developed to
enhance security by dispatching low level filesystem operations from 9p
@ -1077,8 +1077,8 @@ processor IP (see `Intel discontinuance notification`_).
TCG introspection features
--------------------------
TCG trace-events (since 6.2)
''''''''''''''''''''''''''''
TCG trace-events (removed in 7.0)
'''''''''''''''''''''''''''''''''
The ability to add new TCG trace points had bit rotted and as the
feature can be replicated with TCG plugins it was removed. If

View File

@ -317,9 +317,9 @@ void gdb_handle_v_file_open(GArray *params, void *user_ctx)
int fd = open(filename, flags, mode);
#endif
if (fd < 0) {
g_string_printf(gdbserver_state.str_buf, "F-1,%d", errno);
g_string_printf(gdbserver_state.str_buf, "F-1,%x", errno);
} else {
g_string_printf(gdbserver_state.str_buf, "F%d", fd);
g_string_printf(gdbserver_state.str_buf, "F%x", fd);
}
gdb_put_strbuf();
}
@ -329,7 +329,7 @@ void gdb_handle_v_file_close(GArray *params, void *user_ctx)
int fd = gdb_get_cmd_param(params, 0)->val_ul;
if (close(fd) == -1) {
g_string_printf(gdbserver_state.str_buf, "F-1,%d", errno);
g_string_printf(gdbserver_state.str_buf, "F-1,%x", errno);
gdb_put_strbuf();
return;
}
@ -352,7 +352,7 @@ void gdb_handle_v_file_pread(GArray *params, void *user_ctx)
ssize_t n = pread(fd, buf, bufsiz, offset);
if (n < 0) {
g_string_printf(gdbserver_state.str_buf, "F-1,%d", errno);
g_string_printf(gdbserver_state.str_buf, "F-1,%x", errno);
gdb_put_strbuf();
return;
}
@ -375,7 +375,7 @@ void gdb_handle_v_file_readlink(GArray *params, void *user_ctx)
ssize_t n = readlink(filename, buf, BUFSIZ);
#endif
if (n < 0) {
g_string_printf(gdbserver_state.str_buf, "F-1,%d", errno);
g_string_printf(gdbserver_state.str_buf, "F-1,%x", errno);
gdb_put_strbuf();
return;
}

View File

@ -177,20 +177,27 @@ again:
return -1;
}
if (close_if_special_file(fd) < 0) {
return -1;
}
serrno = errno;
/* 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()
* ignored it anyway.
*/
/* Only if O_PATH is not set ... */
if (!(flags & O_PATH_9P_UTIL)) {
/*
* Prevent I/O on special files (device files, etc.) on host side,
* however it is safe and required to allow opening them with O_PATH,
* as this is limited to (required) path based operations only.
*/
if (close_if_special_file(fd) < 0) {
return -1;
}
serrno = errno;
/*
* 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() ignored it anyway.
*/
ret = fcntl(fd, F_SETFL, flags);
assert(!ret);
errno = serrno;
}
errno = serrno;
return fd;
}

View File

@ -657,6 +657,7 @@ static Aml *aml_pci_pdsm(void)
Aml *acpi_index = aml_local(2);
Aml *zero = aml_int(0);
Aml *one = aml_int(1);
Aml *not_supp = aml_int(0xFFFFFFFF);
Aml *func = aml_arg(2);
Aml *params = aml_arg(4);
Aml *bnum = aml_derefof(aml_index(params, aml_int(0)));
@ -681,7 +682,7 @@ static Aml *aml_pci_pdsm(void)
*/
ifctx1 = aml_if(aml_lnot(
aml_or(aml_equal(acpi_index, zero),
aml_equal(acpi_index, aml_int(0xFFFFFFFF)), NULL)
aml_equal(acpi_index, not_supp), NULL)
));
{
/* have supported functions */
@ -707,18 +708,30 @@ static Aml *aml_pci_pdsm(void)
{
Aml *pkg = aml_package(2);
aml_append(pkg, zero);
/*
* optional, if not impl. should return null string
*/
aml_append(pkg, aml_string("%s", ""));
aml_append(ifctx, aml_store(pkg, ret));
aml_append(ifctx, aml_store(aml_call2("AIDX", bnum, sunum), acpi_index));
aml_append(ifctx, aml_store(pkg, ret));
/*
* update acpi-index to actual value
* Windows calls func=7 without checking if it's available,
* as workaround Microsoft has suggested to return invalid for func7
* Package, so return 2 elements package but only initialize elements
* when acpi_index is supported and leave them uninitialized, which
* leads elements to being Uninitialized ObjectType and should trip
* Windows into discarding result as an unexpected and prevent setting
* bogus 'PCI Label' on the device.
*/
aml_append(ifctx, aml_store(acpi_index, aml_index(ret, zero)));
ifctx1 = aml_if(aml_lnot(aml_lor(
aml_equal(acpi_index, zero), aml_equal(acpi_index, not_supp)
)));
{
aml_append(ifctx1, aml_store(acpi_index, aml_index(ret, zero)));
/*
* optional, if not impl. should return null string
*/
aml_append(ifctx1, aml_store(aml_string("%s", ""),
aml_index(ret, one)));
}
aml_append(ifctx, ifctx1);
aml_append(ifctx, aml_return(ret));
}

View File

@ -945,7 +945,7 @@ void x86_load_linux(X86MachineState *x86ms,
* kernel on the other side of the fw_cfg interface matches the hash of the
* file the user passed in.
*/
if (!sev_enabled()) {
if (!sev_enabled() && protocol > 0) {
memcpy(setup, header, MIN(sizeof(header), setup_size));
}

View File

@ -465,7 +465,7 @@ static ItsCmdResult lookup_vte(GICv3ITSState *s, const char *who,
static ItsCmdResult process_its_cmd_phys(GICv3ITSState *s, const ITEntry *ite,
int irqlevel)
{
CTEntry cte;
CTEntry cte = {};
ItsCmdResult cmdres;
cmdres = lookup_cte(s, __func__, ite->icid, &cte);
@ -479,7 +479,7 @@ static ItsCmdResult process_its_cmd_phys(GICv3ITSState *s, const ITEntry *ite,
static ItsCmdResult process_its_cmd_virt(GICv3ITSState *s, const ITEntry *ite,
int irqlevel)
{
VTEntry vte;
VTEntry vte = {};
ItsCmdResult cmdres;
cmdres = lookup_vte(s, __func__, ite->vpeid, &vte);
@ -514,8 +514,8 @@ static ItsCmdResult process_its_cmd_virt(GICv3ITSState *s, const ITEntry *ite,
static ItsCmdResult do_process_its_cmd(GICv3ITSState *s, uint32_t devid,
uint32_t eventid, ItsCmdType cmd)
{
DTEntry dte;
ITEntry ite;
DTEntry dte = {};
ITEntry ite = {};
ItsCmdResult cmdres;
int irqlevel;
@ -583,8 +583,8 @@ static ItsCmdResult process_mapti(GICv3ITSState *s, const uint64_t *cmdpkt,
uint32_t pIntid = 0;
uint64_t num_eventids;
uint16_t icid = 0;
DTEntry dte;
ITEntry ite;
DTEntry dte = {};
ITEntry ite = {};
devid = (cmdpkt[0] & DEVID_MASK) >> DEVID_SHIFT;
eventid = cmdpkt[1] & EVENTID_MASK;
@ -651,8 +651,8 @@ static ItsCmdResult process_vmapti(GICv3ITSState *s, const uint64_t *cmdpkt,
{
uint32_t devid, eventid, vintid, doorbell, vpeid;
uint32_t num_eventids;
DTEntry dte;
ITEntry ite;
DTEntry dte = {};
ITEntry ite = {};
if (!its_feature_virtual(s)) {
return CMD_CONTINUE;
@ -761,7 +761,7 @@ static bool update_cte(GICv3ITSState *s, uint16_t icid, const CTEntry *cte)
static ItsCmdResult process_mapc(GICv3ITSState *s, const uint64_t *cmdpkt)
{
uint16_t icid;
CTEntry cte;
CTEntry cte = {};
icid = cmdpkt[2] & ICID_MASK;
cte.valid = cmdpkt[2] & CMD_FIELD_VALID_MASK;
@ -822,7 +822,7 @@ static bool update_dte(GICv3ITSState *s, uint32_t devid, const DTEntry *dte)
static ItsCmdResult process_mapd(GICv3ITSState *s, const uint64_t *cmdpkt)
{
uint32_t devid;
DTEntry dte;
DTEntry dte = {};
devid = (cmdpkt[0] & DEVID_MASK) >> DEVID_SHIFT;
dte.size = cmdpkt[1] & SIZE_MASK;
@ -886,9 +886,9 @@ static ItsCmdResult process_movi(GICv3ITSState *s, const uint64_t *cmdpkt)
{
uint32_t devid, eventid;
uint16_t new_icid;
DTEntry dte;
CTEntry old_cte, new_cte;
ITEntry old_ite;
DTEntry dte = {};
CTEntry old_cte = {}, new_cte = {};
ITEntry old_ite = {};
ItsCmdResult cmdres;
devid = FIELD_EX64(cmdpkt[0], MOVI_0, DEVICEID);
@ -965,7 +965,7 @@ static bool update_vte(GICv3ITSState *s, uint32_t vpeid, const VTEntry *vte)
static ItsCmdResult process_vmapp(GICv3ITSState *s, const uint64_t *cmdpkt)
{
VTEntry vte;
VTEntry vte = {};
uint32_t vpeid;
if (!its_feature_virtual(s)) {
@ -1030,7 +1030,7 @@ static void vmovp_callback(gpointer data, gpointer opaque)
*/
GICv3ITSState *s = data;
VmovpCallbackData *cbdata = opaque;
VTEntry vte;
VTEntry vte = {};
ItsCmdResult cmdres;
cmdres = lookup_vte(s, __func__, cbdata->vpeid, &vte);
@ -1085,9 +1085,9 @@ static ItsCmdResult process_vmovi(GICv3ITSState *s, const uint64_t *cmdpkt)
{
uint32_t devid, eventid, vpeid, doorbell;
bool doorbell_valid;
DTEntry dte;
ITEntry ite;
VTEntry old_vte, new_vte;
DTEntry dte = {};
ITEntry ite = {};
VTEntry old_vte = {}, new_vte = {};
ItsCmdResult cmdres;
if (!its_feature_virtual(s)) {
@ -1186,10 +1186,10 @@ static ItsCmdResult process_vinvall(GICv3ITSState *s, const uint64_t *cmdpkt)
static ItsCmdResult process_inv(GICv3ITSState *s, const uint64_t *cmdpkt)
{
uint32_t devid, eventid;
ITEntry ite;
DTEntry dte;
CTEntry cte;
VTEntry vte;
ITEntry ite = {};
DTEntry dte = {};
CTEntry cte = {};
VTEntry vte = {};
ItsCmdResult cmdres;
devid = FIELD_EX64(cmdpkt[0], INV_0, DEVICEID);

View File

@ -248,9 +248,12 @@ static void riscv_aplic_set_pending(RISCVAPLICState *aplic,
if ((sm == APLIC_SOURCECFG_SM_LEVEL_HIGH) ||
(sm == APLIC_SOURCECFG_SM_LEVEL_LOW)) {
if (!aplic->msimode || (aplic->msimode && !pending)) {
if (!aplic->msimode) {
return;
}
if (aplic->msimode && !pending) {
goto noskip_write_pending;
}
if ((aplic->state[irq] & APLIC_ISTATE_INPUT) &&
(sm == APLIC_SOURCECFG_SM_LEVEL_LOW)) {
return;
@ -261,6 +264,7 @@ static void riscv_aplic_set_pending(RISCVAPLICState *aplic,
}
}
noskip_write_pending:
riscv_aplic_set_pending_raw(aplic, irq, pending);
}

View File

@ -843,7 +843,7 @@ static void ct3_realize(PCIDevice *pci_dev, Error **errp)
ComponentRegisters *regs = &cxl_cstate->crb;
MemoryRegion *mr = &regs->component_registers;
uint8_t *pci_conf = pci_dev->config;
unsigned short msix_num = 6;
unsigned short msix_num = 10;
int i, rc;
uint16_t count;

View File

@ -250,7 +250,7 @@ static uint64_t msix_pba_mmio_read(void *opaque, hwaddr addr,
PCIDevice *dev = opaque;
if (dev->msix_vector_poll_notifier) {
unsigned vector_start = addr * 8;
unsigned vector_end = MIN(addr + size * 8, dev->msix_entries_nr);
unsigned vector_end = MIN((addr + size) * 8, dev->msix_entries_nr);
dev->msix_vector_poll_notifier(dev, vector_start, vector_end);
}

View File

@ -1113,18 +1113,22 @@ void pcie_sync_bridge_lnk(PCIDevice *bridge_dev)
if ((lnksta & PCI_EXP_LNKSTA_NLW) > (lnkcap & PCI_EXP_LNKCAP_MLW)) {
lnksta &= ~PCI_EXP_LNKSTA_NLW;
lnksta |= lnkcap & PCI_EXP_LNKCAP_MLW;
} else if (!(lnksta & PCI_EXP_LNKSTA_NLW)) {
lnksta |= QEMU_PCI_EXP_LNKSTA_NLW(QEMU_PCI_EXP_LNK_X1);
}
if ((lnksta & PCI_EXP_LNKSTA_CLS) > (lnkcap & PCI_EXP_LNKCAP_SLS)) {
lnksta &= ~PCI_EXP_LNKSTA_CLS;
lnksta |= lnkcap & PCI_EXP_LNKCAP_SLS;
} else if (!(lnksta & PCI_EXP_LNKSTA_CLS)) {
lnksta |= QEMU_PCI_EXP_LNKSTA_CLS(QEMU_PCI_EXP_LNK_2_5GT);
}
}
if (!(lnksta & PCI_EXP_LNKSTA_NLW)) {
lnksta |= QEMU_PCI_EXP_LNKSTA_NLW(QEMU_PCI_EXP_LNK_X1);
}
if (!(lnksta & PCI_EXP_LNKSTA_CLS)) {
lnksta |= QEMU_PCI_EXP_LNKSTA_CLS(QEMU_PCI_EXP_LNK_2_5GT);
}
pci_word_test_and_clear_mask(exp_cap + PCI_EXP_LNKSTA,
PCI_EXP_LNKSTA_CLS | PCI_EXP_LNKSTA_NLW);
pci_word_test_and_set_mask(exp_cap + PCI_EXP_LNKSTA, lnksta &

View File

@ -180,6 +180,17 @@ static void s390_memory_init(MemoryRegion *ram)
{
MemoryRegion *sysmem = get_system_memory();
if (!QEMU_IS_ALIGNED(memory_region_size(ram), 1 * MiB)) {
/*
* SCLP cannot possibly expose smaller granularity right now and KVM
* cannot handle smaller granularity. As we don't support NUMA, the
* region size directly corresponds to machine->ram_size, and the region
* is a single RAM memory region.
*/
error_report("ram size must be multiples of 1 MiB");
exit(EXIT_FAILURE);
}
/* allocate RAM for core */
memory_region_add_subregion(sysmem, 0, ram);
@ -1189,6 +1200,7 @@ static void ccw_machine_2_9_instance_options(MachineState *machine)
s390_cpudef_featoff_greater(12, 1, S390_FEAT_ZPCI);
s390_cpudef_featoff_greater(12, 1, S390_FEAT_ADAPTER_INT_SUPPRESSION);
s390_cpudef_featoff_greater(12, 1, S390_FEAT_ADAPTER_EVENT_NOTIFICATION);
css_migration_enabled = false;
}
static void ccw_machine_2_9_class_options(MachineClass *mc)
@ -1201,7 +1213,6 @@ static void ccw_machine_2_9_class_options(MachineClass *mc)
ccw_machine_2_10_class_options(mc);
compat_props_add(mc->compat_props, hw_compat_2_9, hw_compat_2_9_len);
compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat));
css_migration_enabled = false;
}
DEFINE_CCW_MACHINE(2, 9);

View File

@ -1164,7 +1164,7 @@ static QueryRespCode ufs_exec_query_attr(UfsRequest *req, int op)
value = ufs_read_attr_value(u, idn);
ret = UFS_QUERY_RESULT_SUCCESS;
} else {
value = req->req_upiu.qr.value;
value = be32_to_cpu(req->req_upiu.qr.value);
ret = ufs_write_attr_value(u, idn, value);
}
req->rsp_upiu.qr.value = cpu_to_be32(value);

View File

@ -197,8 +197,8 @@ static void canokey_handle_data(USBDevice *dev, USBPacket *p)
switch (p->pid) {
case USB_TOKEN_OUT:
trace_canokey_handle_data_out(ep_out, p->iov.size);
usb_packet_copy(p, key->ep_out_buffer[ep_out], p->iov.size);
out_pos = 0;
/* segment packet into (possibly multiple) ep_out */
while (out_pos != p->iov.size) {
/*
* key->ep_out[ep_out] set by prepare_receive
@ -207,8 +207,8 @@ static void canokey_handle_data(USBDevice *dev, USBPacket *p)
* to be the buffer length
*/
out_len = MIN(p->iov.size - out_pos, key->ep_out_size[ep_out]);
memcpy(key->ep_out[ep_out],
key->ep_out_buffer[ep_out] + out_pos, out_len);
/* usb_packet_copy would update the pos offset internally */
usb_packet_copy(p, key->ep_out[ep_out], out_len);
out_pos += out_len;
/* update ep_out_size to actual len */
key->ep_out_size[ep_out] = out_len;

View File

@ -24,8 +24,6 @@
#define CANOKEY_EP_NUM 3
/* BULK/INTR IN can be up to 1352 bytes, e.g. get key info */
#define CANOKEY_EP_IN_BUFFER_SIZE 2048
/* BULK OUT can be up to 270 bytes, e.g. PIV import cert */
#define CANOKEY_EP_OUT_BUFFER_SIZE 512
typedef enum {
CANOKEY_EP_IN_WAIT,
@ -59,8 +57,6 @@ typedef struct CanoKeyState {
/* OUT pointer to canokey recv buffer */
uint8_t *ep_out[CANOKEY_EP_NUM];
uint32_t ep_out_size[CANOKEY_EP_NUM];
/* For large BULK OUT, multiple write to ep_out is needed */
uint8_t ep_out_buffer[CANOKEY_EP_NUM][CANOKEY_EP_OUT_BUFFER_SIZE];
/* Properties */
char *file; /* canokey-file */

View File

@ -74,6 +74,7 @@ static bool xhci_pci_intr_raise(XHCIState *xhci, int n, bool level)
}
if (msi_enabled(pci_dev) && level) {
n %= msi_nr_vectors_allocated(pci_dev);
msi_notify(pci_dev, n);
return true;
}

View File

@ -218,7 +218,7 @@ static int voice_resample(MCPXAPUState *d, uint16_t v, float samples[][2],
static void voice_reset_filters(MCPXAPUState *d, uint16_t v);
static void voice_process(MCPXAPUState *d,
float mixbins[NUM_MIXBINS][NUM_SAMPLES_PER_FRAME],
uint16_t v);
uint16_t v, int voice_list);
static int voice_get_samples(MCPXAPUState *d, uint32_t v, float samples[][2],
int num_samples_requested);
static void se_frame(MCPXAPUState *d);
@ -245,6 +245,7 @@ static void mcpx_debug_begin_frame(void)
{
for (int i = 0; i < MCPX_HW_MAX_VOICES; i++) {
g_dbg.vp.v[i].active = false;
g_dbg.vp.v[i].multipass_dst_voice = 0xFFFF;
}
}
@ -286,6 +287,19 @@ void mcpx_apu_debug_clear_isolations(void)
static bool voice_should_mute(uint16_t v)
{
bool m = (g_dbg_voice_monitor >= 0) && (v != g_dbg_voice_monitor);
if (m && g_dbg_cache.vp.v[g_dbg_voice_monitor].multipass) {
uint8_t mp_bin = g_dbg_cache.vp.v[g_dbg_voice_monitor].multipass_bin;
struct McpxApuDebugVoice *d = &g_dbg_cache.vp.v[v];
for (int i = 0; i < sizeof(d->bin) / sizeof(d->bin[0]); i++) {
if (d->bin[i] == mp_bin) {
m = false;
break;
}
}
}
return m || mcpx_apu_debug_is_muted(v);
}
@ -1590,9 +1604,101 @@ static void voice_reset_filters(MCPXAPUState *d, uint16_t v)
}
}
static int peek_ahead_multipass_bin(MCPXAPUState *d, uint16_t v,
uint16_t *dst_voice)
{
bool first = true;
while (v != 0xFFFF) {
bool multipass = voice_get_mask(d, v, NV_PAVS_VOICE_CFG_FMT,
NV_PAVS_VOICE_CFG_FMT_MULTIPASS);
if (multipass) {
if (first) {
break;
}
*dst_voice = v;
int mp_bin = voice_get_mask(d, v, NV_PAVS_VOICE_CFG_FMT,
NV_PAVS_VOICE_CFG_FMT_MULTIPASS_BIN);
return mp_bin;
}
v = voice_get_mask(d, v, NV_PAVS_VOICE_TAR_PITCH_LINK,
NV_PAVS_VOICE_TAR_PITCH_LINK_NEXT_VOICE_HANDLE);
first = false;
}
*dst_voice = 0xFFFF;
return -1;
}
static void dump_multipass_unused_debug_info(MCPXAPUState *d, uint16_t v)
{
unsigned int sample_size = voice_get_mask(
d, v, NV_PAVS_VOICE_CFG_FMT, NV_PAVS_VOICE_CFG_FMT_SAMPLE_SIZE);
unsigned int container_size_index = voice_get_mask(
d, v, NV_PAVS_VOICE_CFG_FMT, NV_PAVS_VOICE_CFG_FMT_CONTAINER_SIZE);
bool stream = voice_get_mask(d, v, NV_PAVS_VOICE_CFG_FMT,
NV_PAVS_VOICE_CFG_FMT_DATA_TYPE);
bool loop =
voice_get_mask(d, v, NV_PAVS_VOICE_CFG_FMT, NV_PAVS_VOICE_CFG_FMT_LOOP);
uint32_t ebo = voice_get_mask(d, v, NV_PAVS_VOICE_PAR_NEXT,
NV_PAVS_VOICE_PAR_NEXT_EBO);
uint32_t cbo = voice_get_mask(d, v, NV_PAVS_VOICE_PAR_OFFSET,
NV_PAVS_VOICE_PAR_OFFSET_CBO);
uint32_t lbo = voice_get_mask(d, v, NV_PAVS_VOICE_CUR_PSH_SAMPLE,
NV_PAVS_VOICE_CUR_PSH_SAMPLE_LBO);
uint32_t ba = voice_get_mask(d, v, NV_PAVS_VOICE_CUR_PSL_START,
NV_PAVS_VOICE_CUR_PSL_START_BA);
bool persist = voice_get_mask(d, v, NV_PAVS_VOICE_CFG_FMT,
NV_PAVS_VOICE_CFG_FMT_PERSIST);
bool linked = voice_get_mask(d, v, NV_PAVS_VOICE_CFG_FMT,
NV_PAVS_VOICE_CFG_FMT_LINKED);
struct McpxApuDebugVoice *dbg = &g_dbg.vp.v[v];
dbg->container_size = container_size_index;
dbg->sample_size = sample_size;
dbg->stream = stream;
dbg->loop = loop;
dbg->ebo = ebo;
dbg->cbo = cbo;
dbg->lbo = lbo;
dbg->ba = ba;
dbg->samples_per_block = 0; // Value overloaded with multipass bin
dbg->persist = persist;
dbg->linked = linked;
}
static void get_multipass_samples(MCPXAPUState *d,
float mixbins[][NUM_SAMPLES_PER_FRAME],
uint16_t v, float samples[][2])
{
struct McpxApuDebugVoice *dbg = &g_dbg.vp.v[v];
// DirectSound sets bin to 31, but hardware would allow other bins
int mp_bin = voice_get_mask(d, v, NV_PAVS_VOICE_CFG_FMT,
NV_PAVS_VOICE_CFG_FMT_MULTIPASS_BIN);
dbg->multipass_bin = mp_bin;
for (int i = 0; i < NUM_SAMPLES_PER_FRAME; i++) {
samples[i][0] = mixbins[mp_bin][i];
samples[i][1] = mixbins[mp_bin][i];
}
// DirectSound sets clear mix to true
bool clear_mix = voice_get_mask(d, v, NV_PAVS_VOICE_CFG_FMT,
NV_PAVS_VOICE_CFG_FMT_CLEAR_MIX);
if (clear_mix) {
memset(&mixbins[mp_bin][0], 0, sizeof(mixbins[0]));
}
// Dump irrelevant data for audio debug UI to avoid showing stale info
dump_multipass_unused_debug_info(d, v);
}
static void voice_process(MCPXAPUState *d,
float mixbins[NUM_MIXBINS][NUM_SAMPLES_PER_FRAME],
uint16_t v)
uint16_t v, int voice_list)
{
assert(v < MCPX_HW_MAX_VOICES);
bool stereo = voice_get_mask(d, v, NV_PAVS_VOICE_CFG_FMT,
@ -1633,18 +1739,28 @@ static void voice_process(MCPXAPUState *d,
assert(ea_value <= 1.0f);
float samples[NUM_SAMPLES_PER_FRAME][2] = { 0 };
for (int sample_count = 0; sample_count < NUM_SAMPLES_PER_FRAME;) {
int active = voice_get_mask(d, v, NV_PAVS_VOICE_PAR_STATE,
NV_PAVS_VOICE_PAR_STATE_ACTIVE_VOICE);
if (!active) {
return;
bool multipass = voice_get_mask(d, v, NV_PAVS_VOICE_CFG_FMT,
NV_PAVS_VOICE_CFG_FMT_MULTIPASS);
dbg->multipass = multipass;
if (multipass) {
get_multipass_samples(d, mixbins, v, samples);
} else {
for (int sample_count = 0; sample_count < NUM_SAMPLES_PER_FRAME;) {
int active = voice_get_mask(d, v, NV_PAVS_VOICE_PAR_STATE,
NV_PAVS_VOICE_PAR_STATE_ACTIVE_VOICE);
if (!active) {
return;
}
int count =
voice_resample(d, v, &samples[sample_count],
NUM_SAMPLES_PER_FRAME - sample_count, rate);
if (count < 0) {
break;
}
sample_count += count;
}
int count = voice_resample(d, v, &samples[sample_count],
NUM_SAMPLES_PER_FRAME - sample_count, rate);
if (count < 0) {
break;
}
sample_count += count;
}
int active = voice_get_mask(d, v, NV_PAVS_VOICE_PAR_STATE,
@ -1771,9 +1887,32 @@ static void voice_process(MCPXAPUState *d,
/* For VP mon, simply mix all voices together here, selecting the
* maximal volume used for any given mixbin as the overall volume for
* this voice.
*
* If the current voice belongs to a multipass sub-voice group we must
* skip it here to avoid mixing it in twice because the sub-voices are
* mixed into the multipass bin and that sub-mix will be mixed in here
* later when the destination (i.e. second pass) voice is processed.
* TODO: Are the 2D, 3D and MP voice lists merely a DirectSound
* convention? Perhaps hardware doesn't care if e.g. a multipass
* voice is in the 2D or 3D list. On the other hand, MON_VP is
* not how the hardware works anyway so not much point worrying
* about precise emulation here. DirectSound compatibility is
* enough.
*/
int mp_bin = -1;
uint16_t mp_dst_voice = 0xFFFF;
if (voice_list == NV1BA0_PIO_SET_ANTECEDENT_VOICE_LIST_MP_TOP - 1) {
mp_bin = peek_ahead_multipass_bin(d, v, &mp_dst_voice);
}
dbg->multipass_dst_voice = mp_dst_voice;
bool debug_isolation =
g_dbg_voice_monitor >= 0 && g_dbg_voice_monitor == v;
float g = 0.0f;
for (int b = 0; b < 8; b++) {
if (bin[b] == mp_bin && !debug_isolation) {
continue;
}
float hr = 1 << d->vp.submix_headroom[bin[b]];
g = fmax(g, attenuate(vol[b]) / hr);
}
@ -1822,6 +1961,8 @@ static int voice_get_samples(MCPXAPUState *d, uint32_t v, float samples[][2],
bool linked = voice_get_mask(d, v, NV_PAVS_VOICE_CFG_FMT,
NV_PAVS_VOICE_CFG_FMT_LINKED); /* FIXME? */
assert(!multipass); // Multipass is handled before this
int ssl_index = 0;
int ssl_seg = 0;
int page = 0;
@ -1954,11 +2095,6 @@ static int voice_get_samples(MCPXAPUState *d, uint32_t v, float samples[][2],
DPRINTF("CBO=%d EBO=%d\n", cbo, ebo);
if (multipass) {
// FIXME
samples_per_block = 1;
}
block_size *= samples_per_block;
// FIXME: Restructure this loop
@ -2147,7 +2283,7 @@ static void se_frame(MCPXAPUState *d)
qemu_cond_wait(&d->cond, &d->lock);
qemu_spin_lock(&d->vp.voice_spinlocks[v]);
}
voice_process(d, mixbins, v);
voice_process(d, mixbins, v, list);
qemu_spin_unlock(&d->vp.voice_spinlocks[v]);
}
d->regs[current] = d->regs[next];

View File

@ -44,6 +44,8 @@ struct McpxApuDebugVoice
bool persist;
bool multipass;
bool linked;
uint8_t multipass_bin;
uint16_t multipass_dst_voice;
int container_size, sample_size;
unsigned int samples_per_block;
uint32_t ebo, cbo, lbo, ba;

View File

@ -377,6 +377,14 @@ int kvm_arch_init(MachineState *ms, KVMState *s);
int kvm_arch_init_vcpu(CPUState *cpu);
int kvm_arch_destroy_vcpu(CPUState *cpu);
#ifdef TARGET_KVM_HAVE_RESET_PARKED_VCPU
void kvm_arch_reset_parked_vcpu(unsigned long vcpu_id, int kvm_fd);
#else
static inline void kvm_arch_reset_parked_vcpu(unsigned long vcpu_id, int kvm_fd)
{
}
#endif
bool kvm_vcpu_id_is_valid(int vcpu_id);
/* Returns VCPU ID to be used on KVM_CREATE_VCPU ioctl() */

View File

@ -1143,7 +1143,7 @@ endif
libnfs = not_found
if not get_option('libnfs').auto() or have_block
libnfs = dependency('libnfs', version: '>=1.9.3',
libnfs = dependency('libnfs', version: ['>=1.9.3', '<6.0.0'],
required: get_option('libnfs'),
method: 'pkg-config')
endif

View File

@ -362,6 +362,7 @@ int multifd_ram_flush_and_sync(void)
bool multifd_send_prepare_common(MultiFDSendParams *p)
{
MultiFDPages_t *pages = &p->data->u.ram;
multifd_send_prepare_header(p);
multifd_send_zero_page_detect(p);
if (!pages->normal_num) {
@ -369,8 +370,6 @@ bool multifd_send_prepare_common(MultiFDSendParams *p)
return false;
}
multifd_send_prepare_header(p);
return true;
}

View File

@ -373,6 +373,7 @@ static int qatzip_recv(MultiFDRecvParams *p, Error **errp)
/* Copy each page to its appropriate location. */
for (int i = 0; i < p->normal_num; i++) {
memcpy(p->host + p->normal[i], q->out_buf + page_size * i, page_size);
ramblock_recv_bitmap_set_offset(p->block, p->normal[i]);
}
return 0;
}

View File

@ -679,6 +679,7 @@ static int multifd_qpl_recv(MultiFDRecvParams *p, Error **errp)
qpl->zlen[i] = be32_to_cpu(qpl->zlen[i]);
assert(qpl->zlen[i] <= multifd_ram_page_size());
zbuf_len += qpl->zlen[i];
ramblock_recv_bitmap_set_offset(p->block, p->normal[i]);
}
/* read compressed pages */

View File

@ -169,7 +169,7 @@ static int multifd_uadk_send_prepare(MultiFDSendParams *p, Error **errp)
.src_len = page_size,
.dst = buf,
/* Set dst_len to double the src in case compressed out >= page_size */
.dst_len = p->page_size * 2,
.dst_len = page_size * 2,
};
if (uadk_data->handle) {

View File

@ -252,9 +252,8 @@ static int multifd_recv_unfill_packet(MultiFDRecvParams *p, Error **errp)
p->packet_num = be64_to_cpu(packet->packet_num);
p->packets_recved++;
if (!(p->flags & MULTIFD_FLAG_SYNC)) {
ret = multifd_ram_unfill_packet(p, errp);
}
/* Always unfill, old QEMUs (<9.0) send data along with SYNC */
ret = multifd_ram_unfill_packet(p, errp);
trace_multifd_recv_unfill(p->id, p->packet_num, p->flags,
p->next_packet_size);
@ -1151,9 +1150,13 @@ static void *multifd_recv_thread(void *opaque)
flags = p->flags;
/* recv methods don't know how to handle the SYNC flag */
p->flags &= ~MULTIFD_FLAG_SYNC;
if (!(flags & MULTIFD_FLAG_SYNC)) {
has_data = p->normal_num || p->zero_num;
}
/*
* Even if it's a SYNC packet, this needs to be set
* because older QEMUs (<9.0) still send data along with
* the SYNC packet.
*/
has_data = p->normal_num || p->zero_num;
qemu_mutex_unlock(&p->mutex);
} else {
/*

View File

@ -338,7 +338,7 @@ static int put_nullptr(QEMUFile *f, void *pv, size_t size,
}
const VMStateInfo vmstate_info_nullptr = {
.name = "uint64",
.name = "nullptr",
.get = get_nullptr,
.put = put_nullptr,
};

View File

@ -51,6 +51,36 @@ vmstate_field_exists(const VMStateDescription *vmsd, const VMStateField *field,
return result;
}
/*
* Create a fake nullptr field when there's a NULL pointer detected in the
* array of a VMS_ARRAY_OF_POINTER VMSD field. It's needed because we
* can't dereference the NULL pointer.
*/
static const VMStateField *
vmsd_create_fake_nullptr_field(const VMStateField *field)
{
VMStateField *fake = g_new0(VMStateField, 1);
/* It can only happen on an array of pointers! */
assert(field->flags & VMS_ARRAY_OF_POINTER);
/* Some of fake's properties should match the original's */
fake->name = field->name;
fake->version_id = field->version_id;
/* Do not need "field_exists" check as it always exists (which is null) */
fake->field_exists = NULL;
/* See vmstate_info_nullptr - use 1 byte to represent nullptr */
fake->size = 1;
fake->info = &vmstate_info_nullptr;
fake->flags = VMS_SINGLE;
/* All the rest fields shouldn't matter.. */
return (const VMStateField *)fake;
}
static int vmstate_n_elems(void *opaque, const VMStateField *field)
{
int n_elems = 1;
@ -143,23 +173,39 @@ int vmstate_load_state(QEMUFile *f, const VMStateDescription *vmsd,
}
for (i = 0; i < n_elems; i++) {
void *curr_elem = first_elem + size * i;
const VMStateField *inner_field;
if (field->flags & VMS_ARRAY_OF_POINTER) {
curr_elem = *(void **)curr_elem;
}
if (!curr_elem && size) {
/* if null pointer check placeholder and do not follow */
assert(field->flags & VMS_ARRAY_OF_POINTER);
ret = vmstate_info_nullptr.get(f, curr_elem, size, NULL);
} else if (field->flags & VMS_STRUCT) {
ret = vmstate_load_state(f, field->vmsd, curr_elem,
field->vmsd->version_id);
} else if (field->flags & VMS_VSTRUCT) {
ret = vmstate_load_state(f, field->vmsd, curr_elem,
field->struct_version_id);
/*
* If null pointer found (which should only happen in
* an array of pointers), use null placeholder and do
* not follow.
*/
inner_field = vmsd_create_fake_nullptr_field(field);
} else {
ret = field->info->get(f, curr_elem, size, field);
inner_field = field;
}
if (inner_field->flags & VMS_STRUCT) {
ret = vmstate_load_state(f, inner_field->vmsd, curr_elem,
inner_field->vmsd->version_id);
} else if (inner_field->flags & VMS_VSTRUCT) {
ret = vmstate_load_state(f, inner_field->vmsd, curr_elem,
inner_field->struct_version_id);
} else {
ret = inner_field->info->get(f, curr_elem, size,
inner_field);
}
/* If we used a fake temp field.. free it now */
if (inner_field != field) {
g_clear_pointer((gpointer *)&inner_field, g_free);
}
if (ret >= 0) {
ret = qemu_file_get_error(f);
}
@ -311,7 +357,7 @@ static void vmsd_desc_field_start(const VMStateDescription *vmsd,
static void vmsd_desc_field_end(const VMStateDescription *vmsd,
JSONWriter *vmdesc,
const VMStateField *field, size_t size, int i)
const VMStateField *field, size_t size)
{
if (!vmdesc) {
return;
@ -379,37 +425,89 @@ int vmstate_save_state_v(QEMUFile *f, const VMStateDescription *vmsd,
int size = vmstate_size(opaque, field);
uint64_t old_offset, written_bytes;
JSONWriter *vmdesc_loop = vmdesc;
bool is_prev_null = false;
trace_vmstate_save_state_loop(vmsd->name, field->name, n_elems);
if (field->flags & VMS_POINTER) {
first_elem = *(void **)first_elem;
assert(first_elem || !n_elems || !size);
}
for (i = 0; i < n_elems; i++) {
void *curr_elem = first_elem + size * i;
const VMStateField *inner_field;
bool is_null;
int max_elems = n_elems - i;
vmsd_desc_field_start(vmsd, vmdesc_loop, field, i, n_elems);
old_offset = qemu_file_transferred(f);
if (field->flags & VMS_ARRAY_OF_POINTER) {
assert(curr_elem);
curr_elem = *(void **)curr_elem;
}
if (!curr_elem && size) {
/* if null pointer write placeholder and do not follow */
assert(field->flags & VMS_ARRAY_OF_POINTER);
ret = vmstate_info_nullptr.put(f, curr_elem, size, NULL,
NULL);
} else if (field->flags & VMS_STRUCT) {
ret = vmstate_save_state(f, field->vmsd, curr_elem,
vmdesc_loop);
} else if (field->flags & VMS_VSTRUCT) {
ret = vmstate_save_state_v(f, field->vmsd, curr_elem,
vmdesc_loop,
field->struct_version_id, errp);
/*
* If null pointer found (which should only happen in
* an array of pointers), use null placeholder and do
* not follow.
*/
inner_field = vmsd_create_fake_nullptr_field(field);
is_null = true;
} else {
ret = field->info->put(f, curr_elem, size, field,
vmdesc_loop);
inner_field = field;
is_null = false;
}
/*
* Due to the fake nullptr handling above, if there's mixed
* null/non-null data, it doesn't make sense to emit a
* compressed array representation spanning the entire array
* because the field types will be different (e.g. struct
* vs. nullptr). Search ahead for the next null/non-null element
* and start a new compressed array if found.
*/
if (field->flags & VMS_ARRAY_OF_POINTER &&
is_null != is_prev_null) {
is_prev_null = is_null;
vmdesc_loop = vmdesc;
for (int j = i + 1; j < n_elems; j++) {
void *elem = *(void **)(first_elem + size * j);
bool elem_is_null = !elem && size;
if (is_null != elem_is_null) {
max_elems = j - i;
break;
}
}
}
vmsd_desc_field_start(vmsd, vmdesc_loop, inner_field,
i, max_elems);
if (inner_field->flags & VMS_STRUCT) {
ret = vmstate_save_state(f, inner_field->vmsd,
curr_elem, vmdesc_loop);
} else if (inner_field->flags & VMS_VSTRUCT) {
ret = vmstate_save_state_v(f, inner_field->vmsd,
curr_elem, vmdesc_loop,
inner_field->struct_version_id,
errp);
} else {
ret = inner_field->info->put(f, curr_elem, size,
inner_field, vmdesc_loop);
}
written_bytes = qemu_file_transferred(f) - old_offset;
vmsd_desc_field_end(vmsd, vmdesc_loop, inner_field,
written_bytes);
/* If we used a fake temp field.. free it now */
if (inner_field != field) {
g_clear_pointer((gpointer *)&inner_field, g_free);
}
if (ret) {
error_setg(errp, "Save of field %s/%s failed",
vmsd->name, field->name);
@ -419,9 +517,6 @@ int vmstate_save_state_v(QEMUFile *f, const VMStateDescription *vmsd,
return ret;
}
written_bytes = qemu_file_transferred(f) - old_offset;
vmsd_desc_field_end(vmsd, vmdesc_loop, field, written_bytes, i);
/* Compressed arrays only care about the first element */
if (vmdesc_loop && vmsd_can_compress(field)) {
vmdesc_loop = NULL;

View File

@ -155,7 +155,8 @@ static ssize_t filter_dump_receive_iov(NetFilterState *nf, NetClientState *sndr,
{
NetFilterDumpState *nfds = FILTER_DUMP(nf);
dump_receive_iov(&nfds->ds, iov, iovcnt, qemu_get_vnet_hdr_len(nf->netdev));
dump_receive_iov(&nfds->ds, iov, iovcnt, flags & QEMU_NET_PACKET_FLAG_RAW ?
0 : qemu_get_vnet_hdr_len(nf->netdev));
return 0;
}

View File

@ -822,6 +822,7 @@ static ssize_t qemu_deliver_packet_iov(NetClientState *sender,
iov_copy[0].iov_len = nc->vnet_hdr_len;
memcpy(&iov_copy[1], iov, iovcnt * sizeof(*iov));
iov = iov_copy;
iovcnt++;
}
if (nc->info->receive_iov) {

View File

@ -0,0 +1,31 @@
{
"description": "UEFI firmware for riscv64",
"interface-types": [
"uefi"
],
"mapping": {
"device": "flash",
"executable": {
"filename": "@DATADIR@/edk2-riscv-code.fd",
"format": "raw"
},
"nvram-template": {
"filename": "@DATADIR@/edk2-riscv-vars.fd",
"format": "raw"
}
},
"targets": [
{
"architecture": "riscv64",
"machines": [
"virt*"
]
}
],
"features": [
],
"tags": [
]
}

View File

@ -6,7 +6,8 @@ if unpack_edk2_blobs and get_option('install_blobs')
'60-edk2-arm.json',
'60-edk2-i386.json',
'60-edk2-x86_64.json',
'60-edk2-loongarch64.json'
'60-edk2-loongarch64.json',
'60-edk2-riscv64.json'
]
configure_file(input: files(f),
output: f,

View File

@ -157,6 +157,11 @@ edk2-version: edk2
touch $@; \
fi
edk2-basetools: edk2-version
$(PYTHON) edk2-build.py --config edk2-build.config \
--silent --no-logs \
--match none # build only basetools
efi: edk2-version
$(PYTHON) edk2-build.py --config edk2-build.config \
--version-override "$(EDK2_STABLE)$(FIRMWARE_EXTRAVERSION)" \

View File

@ -65,6 +65,9 @@ class MigrationFile(object):
def tell(self):
return self.file.tell()
def seek(self, a, b):
return self.file.seek(a, b)
# The VMSD description is at the end of the file, after EOF. Look for
# the last NULL byte, then for the beginning brace of JSON.
def read_migration_debug_json(self):
@ -272,11 +275,24 @@ class S390StorageAttributes(object):
self.section_key = section_key
def read(self):
pos = 0
while True:
addr_flags = self.file.read64()
flags = addr_flags & 0xfff
if (flags & (self.STATTR_FLAG_DONE | self.STATTR_FLAG_EOS)):
if flags & self.STATTR_FLAG_DONE:
pos = self.file.tell()
continue
elif flags & self.STATTR_FLAG_EOS:
return
else:
# No EOS came after DONE, that's OK, but rewind the
# stream because this is not our data.
if pos:
self.file.seek(pos, os.SEEK_SET)
return
raise Exception("Unknown flags %x", flags)
if (flags & self.STATTR_FLAG_ERROR):
raise Exception("Error in migration stream")
count = self.file.read64()
@ -401,6 +417,28 @@ class VMSDFieldIntLE(VMSDFieldInt):
super(VMSDFieldIntLE, self).__init__(desc, file)
self.dtype = '<i%d' % self.size
class VMSDFieldNull(VMSDFieldGeneric):
NULL_PTR_MARKER = b'0'
def __init__(self, desc, file):
super(VMSDFieldNull, self).__init__(desc, file)
def __repr__(self):
# A NULL pointer is encoded in the stream as a '0' to
# disambiguate from a mere 0x0 value and avoid consumers
# trying to follow the NULL pointer. Displaying '0', 0x30 or
# 0x0 when analyzing the JSON debug stream could become
# confusing, so use an explicit term instead.
return "nullptr"
def __str__(self):
return self.__repr__()
def read(self):
super(VMSDFieldNull, self).read()
assert(self.data == self.NULL_PTR_MARKER)
return self.data
class VMSDFieldBool(VMSDFieldGeneric):
def __init__(self, desc, file):
super(VMSDFieldBool, self).__init__(desc, file)
@ -429,6 +467,9 @@ class VMSDFieldStruct(VMSDFieldGeneric):
super(VMSDFieldStruct, self).__init__(desc, file)
self.data = collections.OrderedDict()
if 'fields' not in self.desc['struct']:
raise Exception("No fields in struct. VMSD:\n%s" % self.desc)
# When we see compressed array elements, unfold them here
new_fields = []
for field in self.desc['struct']['fields']:
@ -461,15 +502,25 @@ class VMSDFieldStruct(VMSDFieldGeneric):
field['data'] = reader(field, self.file)
field['data'].read()
if 'index' in field:
if field['name'] not in self.data:
self.data[field['name']] = []
a = self.data[field['name']]
if len(a) != int(field['index']):
raise Exception("internal index of data field unmatched (%d/%d)" % (len(a), int(field['index'])))
a.append(field['data'])
fname = field['name']
fdata = field['data']
# The field could be:
# i) a single data entry, e.g. uint64
# ii) an array, indicated by it containing the 'index' key
#
# However, the overall data after parsing the whole
# stream, could be a mix of arrays and single data fields,
# all sharing the same field name due to how QEMU breaks
# up arrays with NULL pointers into multiple compressed
# array segments.
if fname not in self.data:
self.data[fname] = fdata
elif type(self.data[fname]) == list:
self.data[fname].append(fdata)
else:
self.data[field['name']] = field['data']
tmp = self.data[fname]
self.data[fname] = [tmp, fdata]
if 'subsections' in self.desc['struct']:
for subsection in self.desc['struct']['subsections']:
@ -477,6 +528,10 @@ class VMSDFieldStruct(VMSDFieldGeneric):
raise Exception("Subsection %s not found at offset %x" % ( subsection['vmsd_name'], self.file.tell()))
name = self.file.readstr()
version_id = self.file.read32()
if not subsection:
raise Exception("Empty description for subsection: %s" % name)
self.data[name] = VMSDSection(self.file, version_id, subsection, (name, 0))
self.data[name].read()
@ -535,6 +590,7 @@ vmsd_field_readers = {
"bitmap" : VMSDFieldGeneric,
"struct" : VMSDFieldStruct,
"capability": VMSDFieldCap,
"nullptr": VMSDFieldNull,
"unknown" : VMSDFieldGeneric,
}
@ -574,10 +630,13 @@ class MigrationDump(object):
}
self.filename = filename
self.vmsd_desc = None
self.vmsd_json = ""
def read(self, desc_only = False, dump_memory = False, write_memory = False):
def read(self, desc_only = False, dump_memory = False,
write_memory = False):
# Read in the whole file
file = MigrationFile(self.filename)
self.vmsd_json = file.read_migration_debug_json()
# File magic
data = file.read32()
@ -635,9 +694,11 @@ class MigrationDump(object):
file.close()
def load_vmsd_json(self, file):
vmsd_json = file.read_migration_debug_json()
self.vmsd_desc = json.loads(vmsd_json, object_pairs_hook=collections.OrderedDict)
self.vmsd_desc = json.loads(self.vmsd_json,
object_pairs_hook=collections.OrderedDict)
for device in self.vmsd_desc['devices']:
if 'fields' not in device:
raise Exception("vmstate for device %s has no fields" % device['name'])
key = (device['name'], device['instance_id'])
value = ( VMSDSection, device )
self.section_classes[key] = value
@ -666,31 +727,34 @@ args = parser.parse_args()
jsonenc = JSONEncoder(indent=4, separators=(',', ': '))
if args.extract:
dump = MigrationDump(args.file)
dump.read(desc_only = True)
print("desc.json")
f = open("desc.json", "w")
f.truncate()
f.write(jsonenc.encode(dump.vmsd_desc))
f.close()
dump.read(write_memory = True)
dict = dump.getDict()
print("state.json")
f = open("state.json", "w")
f.truncate()
f.write(jsonenc.encode(dict))
f.close()
elif args.dump == "state":
dump = MigrationDump(args.file)
dump.read(dump_memory = args.memory)
dict = dump.getDict()
print(jsonenc.encode(dict))
elif args.dump == "desc":
dump = MigrationDump(args.file)
dump.read(desc_only = True)
print(jsonenc.encode(dump.vmsd_desc))
else:
if not any([args.extract, args.dump == "state", args.dump == "desc"]):
raise Exception("Please specify either -x, -d state or -d desc")
try:
dump = MigrationDump(args.file)
if args.extract:
dump.read(desc_only = True)
print("desc.json")
f = open("desc.json", "w")
f.truncate()
f.write(jsonenc.encode(dump.vmsd_desc))
f.close()
dump.read(write_memory = True)
dict = dump.getDict()
print("state.json")
f = open("state.json", "w")
f.truncate()
f.write(jsonenc.encode(dict))
f.close()
elif args.dump == "state":
dump.read(dump_memory = args.memory)
dict = dump.getDict()
print(jsonenc.encode(dict))
elif args.dump == "desc":
dump.read(desc_only = True)
print(jsonenc.encode(dump.vmsd_desc))
except Exception:
raise Exception("Full JSON dump:\n%s", dump.vmsd_json)

View File

@ -10,6 +10,27 @@
# This work is licensed under the terms of the GNU GPLv2 or later.
# See the COPYING file in the top-level directory.
function subproject_dir() {
if test ! -f "subprojects/$1.wrap"; then
error "scripts/archive-source.sh should only process wrap subprojects"
fi
# Print the directory key of the wrap file, defaulting to the
# subproject name. The wrap file is in ini format and should
# have a single section only. There should be only one section
# named "[wrap-*]", which helps keeping the script simple.
local dir
dir=$(sed -n \
-e '/^\[wrap-[a-z][a-z]*\]$/,/^\[/{' \
-e '/^directory *= */!b' \
-e 's///p' \
-e 'q' \
-e '}' \
"subprojects/$1.wrap")
echo "${dir:-$1}"
}
if [ $# -ne 2 ]; then
echo "Usage:"
echo " $0 gitrepo version"
@ -51,5 +72,13 @@ meson subprojects download $SUBPROJECTS
CryptoPkg/Library/OpensslLib/openssl \
MdeModulePkg/Library/BrotliCustomDecompressLib/brotli)
popd
tar --exclude=.git -cJf ${destination}.tar.xz ${destination}
exclude=(--exclude=.git)
# include the tarballs in subprojects/packagecache but not their expansion
for sp in $SUBPROJECTS; do
if grep -xqF "[wrap-file]" subprojects/$sp.wrap; then
exclude+=(--exclude=subprojects/"$(subproject_dir $sp)")
fi
done
tar "${exclude[@]}" -cJf ${destination}.tar.xz ${destination}
rm -rf ${destination}

View File

@ -57,8 +57,8 @@ if have_user
stub_ss.add(files('cpu-synchronize-state.c'))
# Stubs for QAPI events. Those can always be included in the build, but
# they are not built at all for --disable-system --disable-tools builds.
if not (have_system or have_tools)
# they are not built at all for --disable-system builds.
if not have_system
stub_ss.add(files('qdev.c'))
endif
endif

View File

@ -1,4 +1,4 @@
[wrap-git]
url=https://github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator
revision=v3.2.0
revision=v3.2.1
depth=1

View File

@ -1,13 +1,13 @@
[wrap-file]
directory = xxHash-0.8.2
source_url = https://github.com/Cyan4973/xxHash/archive/v0.8.2.tar.gz
source_filename = xxHash-0.8.2.tar.gz
source_hash = baee0c6afd4f03165de7a4e67988d16f0f2b257b51d0e3cb91909302a26a79c4
patch_filename = xxhash_0.8.2-1_patch.zip
patch_url = https://wrapdb.mesonbuild.com/v2/xxhash_0.8.2-1/get_patch
patch_hash = e721ef7a4c4ee0ade8b8440f6f7cb9f935b68e825249d74cb1c2503c53e68d25
source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/xxhash_0.8.2-1/xxHash-0.8.2.tar.gz
wrapdb_version = 0.8.2-1
directory = xxHash-0.8.3
source_url = https://github.com/Cyan4973/xxHash/archive/v0.8.3.tar.gz
source_filename = xxHash-0.8.3.tar.gz
source_hash = aae608dfe8213dfd05d909a57718ef82f30722c392344583d3f39050c7f29a80
patch_filename = xxhash_0.8.3-1_patch.zip
patch_url = https://wrapdb.mesonbuild.com/v2/xxhash_0.8.3-1/get_patch
patch_hash = 39c2418defa1d34cfe079c477b314b0a7a1bca657d91cdff4a05b8a7ed78aceb
source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/xxhash_0.8.3-1/xxHash-0.8.3.tar.gz
wrapdb_version = 0.8.3-1
[provide]
libxxhash = xxhash_dep

View File

@ -2054,10 +2054,12 @@ RAMBlock *qemu_ram_alloc_from_fd(ram_addr_t size, MemoryRegion *mr,
size = REAL_HOST_PAGE_ALIGN(size);
file_size = get_file_size(fd);
if (file_size > offset && file_size < (offset + size)) {
error_setg(errp, "backing store size 0x%" PRIx64
" does not match 'size' option 0x" RAM_ADDR_FMT,
file_size, size);
if (file_size && file_size < offset + size) {
error_setg(errp, "%s backing store size 0x%" PRIx64
" is too small for 'size' option 0x" RAM_ADDR_FMT
" plus 'offset' option 0x%" PRIx64,
memory_region_name(mr), file_size, size,
(uint64_t)offset);
return NULL;
}

View File

@ -7362,7 +7362,7 @@ static void arm_reset_sve_state(CPUARMState *env)
memset(env->vfp.zregs, 0, sizeof(env->vfp.zregs));
/* Recall that FFR is stored as pregs[16]. */
memset(env->vfp.pregs, 0, sizeof(env->vfp.pregs));
vfp_set_fpcr(env, 0x0800009f);
vfp_set_fpsr(env, 0x0800009f);
}
void aarch64_set_svcr(CPUARMState *env, uint64_t new, uint64_t mask)

View File

@ -3715,6 +3715,7 @@ static const X86CPUDefinition builtin_x86_defs[] = {
},
{
.version = 4,
.note = "IBRS, EPT switching, no TSX",
.props = (PropValue[]) {
{ "vmx-eptp-switching", "on" },
{ /* end of list */ }
@ -3849,7 +3850,7 @@ static const X86CPUDefinition builtin_x86_defs[] = {
},
},
{ .version = 4,
.note = "ARCH_CAPABILITIES, no TSX",
.note = "ARCH_CAPABILITIES, EPT switching, no TSX",
.props = (PropValue[]) {
{ "vmx-eptp-switching", "on" },
{ /* end of list */ }
@ -7768,8 +7769,10 @@ static bool x86_cpu_filter_features(X86CPU *cpu, bool verbose)
env->avx10_version = version;
have_filtered_features = true;
}
} else if (env->avx10_version && prefix) {
warn_report("%s: avx10.%d.", prefix, env->avx10_version);
} else if (env->avx10_version) {
if (prefix) {
warn_report("%s: avx10.%d.", prefix, env->avx10_version);
}
have_filtered_features = true;
}

View File

@ -2415,6 +2415,21 @@ void kvm_arch_after_reset_vcpu(X86CPU *cpu)
}
}
void kvm_arch_reset_parked_vcpu(unsigned long vcpu_id, int kvm_fd)
{
g_autofree struct kvm_msrs *msrs = NULL;
msrs = g_malloc0(sizeof(*msrs) + sizeof(msrs->entries[0]));
msrs->entries[0].index = MSR_IA32_TSC;
msrs->entries[0].data = 1; /* match the value in x86_cpu_reset() */
msrs->nmsrs++;
if (ioctl(kvm_fd, KVM_SET_MSRS, msrs) != 1) {
warn_report("parked vCPU %lu TSC reset failed: %d",
vcpu_id, errno);
}
}
void kvm_arch_do_init_vcpu(X86CPU *cpu)
{
CPUX86State *env = &cpu->env;

View File

@ -5126,7 +5126,7 @@ static bool do_vbsrl_v(DisasContext *ctx, arg_vv_i *a, uint32_t oprsz)
{
int i, ofs;
if (!check_vec(ctx, 32)) {
if (!check_vec(ctx, oprsz)) {
return true;
}

View File

@ -146,7 +146,7 @@ static inline int s390_probe_access(CPUArchState *env, target_ulong addr,
int mmu_idx, bool nonfault,
void **phost, uintptr_t ra)
{
int flags = probe_access_flags(env, addr, 0, access_type, mmu_idx,
int flags = probe_access_flags(env, addr, size, access_type, mmu_idx,
nonfault, phost, ra);
if (unlikely(flags & TLB_INVALID_MASK)) {

View File

@ -1624,7 +1624,7 @@ static void tcg_out_mb(TCGContext *s, TCGArg a0)
insn |= 0x02100000;
}
if (a0 & TCG_MO_ST_ST) {
insn |= 0x02200000;
insn |= 0x01100000;
}
tcg_out32(s, insn);
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -25,13 +25,16 @@ class RxGdbSimMachine(QemuSystemTest):
KERNEL_COMMON_COMMAND_LINE = 'printk.time=0 '
ASSET_UBOOT = Asset(
'https://acc.dl.osdn.jp/users/23/23888/u-boot.bin.gz',
'7146567d669e91dbac166384b29aeba1715beb844c8551e904b86831bfd9d046')
('https://github.com/philmd/qemu-testing-blob/raw/rx-gdbsim/rx/gdbsim/'
'u-boot.bin'),
'dd7dd4220cccf7aeb32227b26233bf39600db05c3f8e26005bcc2bf6c927207d')
ASSET_DTB = Asset(
'https://acc.dl.osdn.jp/users/23/23887/rx-virt.dtb',
('https://github.com/philmd/qemu-testing-blob/raw/rx-gdbsim/rx/gdbsim/'
'rx-gdbsim.dtb'),
'aa278d9c1907a4501741d7ee57e7f65c02dd1b3e0323b33c6d4247f1b32cf29a')
ASSET_KERNEL = Asset(
'http://acc.dl.osdn.jp/users/23/23845/zImage',
('https://github.com/philmd/qemu-testing-blob/raw/rx-gdbsim/rx/gdbsim/'
'zImage'),
'baa43205e74a7220ed8482188c5e9ce497226712abb7f4e7e4f825ce19ff9656')
def test_uboot(self):
@ -40,9 +43,7 @@ class RxGdbSimMachine(QemuSystemTest):
"""
self.set_machine('gdbsim-r5f562n8')
uboot_path_gz = self.ASSET_UBOOT.fetch()
uboot_path = os.path.join(self.workdir, 'u-boot.bin')
gzip_uncompress(uboot_path_gz, uboot_path)
uboot_path = self.ASSET_UBOOT.fetch()
self.vm.set_console()
self.vm.add_args('-bios', uboot_path,

View File

@ -185,7 +185,7 @@ static const testdef_t tests[] = {
sizeof(kernel_plml605), kernel_plml605 },
{ "arm", "raspi2b", "", "TT", sizeof(bios_raspi2), 0, bios_raspi2 },
/* For hppa, force bios to output to serial by disabling graphics. */
{ "hppa", "hppa", "-vga none", "SeaBIOS wants SYSTEM HALT" },
{ "hppa", "B160L", "-vga none", "SeaBIOS wants SYSTEM HALT" },
{ "aarch64", "virt", "-cpu max", "TT", sizeof(kernel_aarch64),
kernel_aarch64 },
{ "arm", "microbit", "", "T", sizeof(kernel_nrf51), kernel_nrf51 },

View File

@ -145,7 +145,7 @@ static void ufs_send_query(QUfs *ufs, uint8_t slot, uint8_t query_function,
req_upiu.qr.idn = idn;
req_upiu.qr.index = index;
req_upiu.qr.selector = selector;
req_upiu.qr.value = attr_value;
req_upiu.qr.value = cpu_to_be32(attr_value);
req_upiu.qr.length = UFS_QUERY_DESC_MAX_SIZE;
qtest_memwrite(ufs->dev.bus->qts, req_upiu_addr, &req_upiu,
sizeof(req_upiu));

View File

@ -6,10 +6,10 @@ FROM ubuntu:24.04
ENV MXE_PATH=/opt/mxe
ENV MXE_REPO=https://github.com/mxe/mxe.git
ENV MXE_VERSION=7f054f14930d109412d2d61d019c12fa80816b8c
ENV MXE_VERSION=866492387740cc6580ef516c8a746402be645453
ENV MXE_LLVM_MINGW_REPO=https://github.com/libvips/build-win64-mxe
ENV MXE_LLVM_MINGW_VERSION=8a4e0ab8a3b574287378459356f6bdaecc727de2
ENV MXE_LLVM_MINGW_VERSION=32a2d0ecdfd3ea16bb4a99e333a8d5a3d63be491
ENV MXE_LLVM_MINGW_PATH=/opt/build-win64-mxe
ARG PLUGIN_DIRS="${MXE_LLVM_MINGW_PATH} ${MXE_LLVM_MINGW_PATH}/build/plugins/llvm-mingw"

View File

@ -731,6 +731,7 @@ static void sdl2_display_very_early_init(DisplayOptions *o)
const int res_table[][2] = {
{640, 480},
{720, 480},
{1280, 720},
{1280, 800},
{1280, 960},

View File

@ -22,6 +22,8 @@
#include "font-manager.hh"
#include "viewport-manager.hh"
#define MAX_VOICES 256
DebugApuWindow::DebugApuWindow() : m_is_open(false)
{
}
@ -60,8 +62,7 @@ void DebugApuWindow::Draw()
ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 0);
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(2*g_viewport_mgr.m_scale, 2*g_viewport_mgr.m_scale));
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(4*g_viewport_mgr.m_scale, 4*g_viewport_mgr.m_scale));
for (int i = 0; i < 256; i++)
{
for (int i = 0; i < MAX_VOICES; i++) {
if (i % 16) {
ImGui::SameLine();
}
@ -132,8 +133,15 @@ void DebugApuWindow::Draw()
assert(voice->container_size < 4);
assert(voice->sample_size < 4);
ImGui::Text("Container Size: %s, Sample Size: %s, Samples per Block: %d",
cs[voice->container_size], ss[voice->sample_size], voice->samples_per_block);
const char *spb_or_bin_label = "Samples per Block";
unsigned int spb_or_bin = voice->samples_per_block;
if (voice->multipass) {
spb_or_bin_label = "Multipass Bin";
spb_or_bin = voice->multipass_bin;
}
ImGui::Text("Container Size: %s, Sample Size: %s, %s: %d",
cs[voice->container_size], ss[voice->sample_size],
spb_or_bin_label, spb_or_bin);
ImGui::Text("Rate: %f (%d Hz)", voice->rate, (int)(48000.0/voice->rate));
ImGui::Text("EBO=%d CBO=%d LBO=%d BA=%x",
voice->ebo, voice->cbo, voice->lbo, voice->ba);
@ -153,6 +161,30 @@ void DebugApuWindow::Draw()
}
ImGui::Text("%-17s", buf);
}
int mon = mcpx_apu_debug_get_monitor();
if (mon == MCPX_APU_DEBUG_MON_VP) {
if (voice->multipass_dst_voice != 0xFFFF) {
ImGui::Text("Multipass Dest Voice: 0x%02x",
voice->multipass_dst_voice);
}
if (voice->multipass) {
ImGui::Text("Multipass Src Voices:");
int n = 0;
for (int i = 0; i < MAX_VOICES; i++) {
if (dbg->vp.v[i].multipass_dst_voice == voice_info) {
if (n > 0 && ((n & 7) == 0)) {
ImGui::Text(" ");
}
ImGui::SameLine();
ImGui::Text("0x%02x", i);
n++;
}
}
}
}
ImGui::PopFont();
ImGui::EndTooltip();
}

View File

@ -525,6 +525,7 @@ void MainMenuDisplayView::Draw()
if (ChevronCombo("Window size", &g_config.display.window.startup_size,
"Last Used\0"
"640x480\0"
"720x480\0"
"1280x720\0"
"1280x800\0"
"1280x960\0"