Compare commits
39
Commits
block
...
staging-0.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b2bdfb711a | ||
|
|
dbdbd71acf | ||
|
|
6b765cbbc2 | ||
|
|
be76977ec8 | ||
|
|
8e964243f5 | ||
|
|
7d807dcea2 | ||
|
|
b249153dfd | ||
|
|
9acb3d7e52 | ||
|
|
1335d26a8b | ||
|
|
1d7592186e | ||
|
|
99812af143 | ||
|
|
8c2fe857e8 | ||
|
|
37cc3ad29e | ||
|
|
d24558bb62 | ||
|
|
5b0c365c64 | ||
|
|
ded28d8298 | ||
|
|
83f6cbc53c | ||
|
|
8c3fab5ce8 | ||
|
|
26519231ac | ||
|
|
58e2d19b0e | ||
|
|
6a3b8807e9 | ||
|
|
64c5abe2bf | ||
|
|
fbcb93bea2 | ||
|
|
6c9a80b394 | ||
|
|
0bf73763a5 | ||
|
|
f3690e0398 | ||
|
|
a3c3caf2ab | ||
|
|
42a21b2f78 | ||
|
|
f298d3488d | ||
|
|
2a999aa155 | ||
|
|
ae7daf9b86 | ||
|
|
4520611f88 | ||
|
|
e8df2d66bb | ||
|
|
5810375131 | ||
|
|
14a40a9157 | ||
|
|
464aaf8b82 | ||
|
|
814eda6232 | ||
|
|
26df00f45b | ||
|
|
6773aac9c7 |
+56
-7
@@ -1,10 +1,24 @@
|
||||
|
||||
variables:
|
||||
# On stable branches this is changed by later rules. Should also
|
||||
# be overridden per pipeline if running pipelines concurrently
|
||||
# for different branches in contributor forks.
|
||||
QEMU_CI_CONTAINER_TAG: latest
|
||||
|
||||
# For purposes of CI rules, upstream is the gitlab.com/qemu-project
|
||||
# namespace. When testing CI, it might be usefult to override this
|
||||
# to point to a fork repo
|
||||
QEMU_CI_UPSTREAM: qemu-project
|
||||
|
||||
# The order of rules defined here is critically important.
|
||||
# They are evaluated in order and first match wins.
|
||||
#
|
||||
# Thus we group them into a number of stages, ordered from
|
||||
# most restrictive to least restrictive
|
||||
#
|
||||
# For pipelines running for stable "staging-X.Y" branches
|
||||
# we must override QEMU_CI_CONTAINER_TAG
|
||||
#
|
||||
.base_job_template:
|
||||
variables:
|
||||
# Each script line from will be in a collapsible section in the job output
|
||||
@@ -19,28 +33,36 @@
|
||||
# want jobs to run
|
||||
#############################################################
|
||||
|
||||
# Never run jobs upstream on stable branch, staging branch jobs already ran
|
||||
- if: '$CI_PROJECT_NAMESPACE == $QEMU_CI_UPSTREAM && $CI_COMMIT_BRANCH =~ /^stable-/'
|
||||
when: never
|
||||
|
||||
# Never run jobs upstream on tags, staging branch jobs already ran
|
||||
- if: '$CI_PROJECT_NAMESPACE == $QEMU_CI_UPSTREAM && $CI_COMMIT_TAG'
|
||||
when: never
|
||||
|
||||
# Cirrus jobs can't run unless the creds / target repo are set
|
||||
- if: '$QEMU_JOB_CIRRUS && ($CIRRUS_GITHUB_REPO == null || $CIRRUS_API_TOKEN == null)'
|
||||
when: never
|
||||
|
||||
# Publishing jobs should only run on the default branch in upstream
|
||||
- if: '$QEMU_JOB_PUBLISH == "1" && $CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH != $CI_DEFAULT_BRANCH'
|
||||
- if: '$QEMU_JOB_PUBLISH == "1" && $CI_PROJECT_NAMESPACE == $QEMU_CI_UPSTREAM && $CI_COMMIT_BRANCH != $CI_DEFAULT_BRANCH'
|
||||
when: never
|
||||
|
||||
# Non-publishing jobs should only run on staging branches in upstream
|
||||
- if: '$QEMU_JOB_PUBLISH != "1" && $CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH !~ /staging/'
|
||||
- if: '$QEMU_JOB_PUBLISH != "1" && $CI_PROJECT_NAMESPACE == $QEMU_CI_UPSTREAM && $CI_COMMIT_BRANCH !~ /staging/'
|
||||
when: never
|
||||
|
||||
# Jobs only intended for forks should always be skipped on upstream
|
||||
- if: '$QEMU_JOB_ONLY_FORKS == "1" && $CI_PROJECT_NAMESPACE == "qemu-project"'
|
||||
- if: '$QEMU_JOB_ONLY_FORKS == "1" && $CI_PROJECT_NAMESPACE == $QEMU_CI_UPSTREAM'
|
||||
when: never
|
||||
|
||||
# Forks don't get pipelines unless QEMU_CI=1 or QEMU_CI=2 is set
|
||||
- if: '$QEMU_CI != "1" && $QEMU_CI != "2" && $CI_PROJECT_NAMESPACE != "qemu-project"'
|
||||
- if: '$QEMU_CI != "1" && $QEMU_CI != "2" && $CI_PROJECT_NAMESPACE != $QEMU_CI_UPSTREAM'
|
||||
when: never
|
||||
|
||||
# Avocado jobs don't run in forks unless $QEMU_CI_AVOCADO_TESTING is set
|
||||
- if: '$QEMU_JOB_AVOCADO && $QEMU_CI_AVOCADO_TESTING != "1" && $CI_PROJECT_NAMESPACE != "qemu-project"'
|
||||
- if: '$QEMU_JOB_AVOCADO && $QEMU_CI_AVOCADO_TESTING != "1" && $CI_PROJECT_NAMESPACE != $QEMU_CI_UPSTREAM'
|
||||
when: never
|
||||
|
||||
|
||||
@@ -50,17 +72,29 @@
|
||||
#############################################################
|
||||
|
||||
# Optional jobs should not be run unless manually triggered
|
||||
- if: '$QEMU_JOB_OPTIONAL && $CI_PROJECT_NAMESPACE == $QEMU_CI_UPSTREAM && $CI_COMMIT_BRANCH =~ /staging-[[:digit:]]+\.[[:digit:]]/'
|
||||
when: manual
|
||||
allow_failure: true
|
||||
variables:
|
||||
QEMU_CI_CONTAINER_TAG: $CI_COMMIT_REF_SLUG
|
||||
|
||||
- if: '$QEMU_JOB_OPTIONAL'
|
||||
when: manual
|
||||
allow_failure: true
|
||||
|
||||
# Skipped jobs should not be run unless manually triggered
|
||||
- if: '$QEMU_JOB_SKIPPED && $CI_PROJECT_NAMESPACE == $QEMU_CI_UPSTREAM && $CI_COMMIT_BRANCH =~ /staging-[[:digit:]]+\.[[:digit:]]/'
|
||||
when: manual
|
||||
allow_failure: true
|
||||
variables:
|
||||
QEMU_CI_CONTAINER_TAG: $CI_COMMIT_REF_SLUG
|
||||
|
||||
- if: '$QEMU_JOB_SKIPPED'
|
||||
when: manual
|
||||
allow_failure: true
|
||||
|
||||
# Avocado jobs can be manually start in forks if $QEMU_CI_AVOCADO_TESTING is unset
|
||||
- if: '$QEMU_JOB_AVOCADO && $CI_PROJECT_NAMESPACE != "qemu-project"'
|
||||
- if: '$QEMU_JOB_AVOCADO && $CI_PROJECT_NAMESPACE != $QEMU_CI_UPSTREAM'
|
||||
when: manual
|
||||
allow_failure: true
|
||||
|
||||
@@ -72,8 +106,23 @@
|
||||
|
||||
# Forks pipeline jobs don't start automatically unless
|
||||
# QEMU_CI=2 is set
|
||||
- if: '$QEMU_CI != "2" && $CI_PROJECT_NAMESPACE != "qemu-project"'
|
||||
- if: '$QEMU_CI != "2" && $CI_PROJECT_NAMESPACE != $QEMU_CI_UPSTREAM'
|
||||
when: manual
|
||||
|
||||
# Upstream pipeline jobs start automatically unless told not to
|
||||
# by setting QEMU_CI=1
|
||||
- if: '$QEMU_CI == "1" && $CI_PROJECT_NAMESPACE == $QEMU_CI_UPSTREAM && $CI_COMMIT_BRANCH =~ /staging/'
|
||||
when: manual
|
||||
variables:
|
||||
QEMU_CI_CONTAINER_TAG: $CI_COMMIT_REF_SLUG
|
||||
|
||||
- if: '$QEMU_CI == "1" && $CI_PROJECT_NAMESPACE == $QEMU_CI_UPSTREAM'
|
||||
when: manual
|
||||
|
||||
# Jobs can run if any jobs they depend on were successful
|
||||
- if: '$QEMU_JOB_SKIPPED && $CI_PROJECT_NAMESPACE == $QEMU_CI_UPSTREAM && $CI_COMMIT_BRANCH =~ /staging-[[:digit:]]+\.[[:digit:]]/'
|
||||
when: on_success
|
||||
variables:
|
||||
QEMU_CI_CONTAINER_TAG: $CI_COMMIT_REF_SLUG
|
||||
|
||||
- when: on_success
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
.native_build_job_template:
|
||||
extends: .base_job_template
|
||||
stage: build
|
||||
image: $CI_REGISTRY_IMAGE/qemu/$IMAGE:latest
|
||||
image: $CI_REGISTRY_IMAGE/qemu/$IMAGE:$QEMU_CI_CONTAINER_TAG
|
||||
before_script:
|
||||
- JOBS=$(expr $(nproc) + 1)
|
||||
script:
|
||||
@@ -44,7 +44,7 @@
|
||||
.common_test_job_template:
|
||||
extends: .base_job_template
|
||||
stage: test
|
||||
image: $CI_REGISTRY_IMAGE/qemu/$IMAGE:latest
|
||||
image: $CI_REGISTRY_IMAGE/qemu/$IMAGE:$QEMU_CI_CONTAINER_TAG
|
||||
script:
|
||||
- scripts/git-submodule.sh update
|
||||
$(sed -n '/GIT_SUBMODULES=/ s/.*=// p' build/config-host.mak)
|
||||
|
||||
@@ -103,7 +103,7 @@ crash-test-debian:
|
||||
script:
|
||||
- cd build
|
||||
- make check-venv
|
||||
- tests/venv/bin/python3 scripts/device-crash-test -q ./qemu-system-i386
|
||||
- tests/venv/bin/python3 scripts/device-crash-test ./qemu-system-i386
|
||||
|
||||
build-system-fedora:
|
||||
extends:
|
||||
@@ -532,7 +532,7 @@ build-without-defaults:
|
||||
build-libvhost-user:
|
||||
extends: .base_job_template
|
||||
stage: build
|
||||
image: $CI_REGISTRY_IMAGE/qemu/fedora:latest
|
||||
image: $CI_REGISTRY_IMAGE/qemu/fedora:$QEMU_CI_CONTAINER_TAG
|
||||
needs:
|
||||
job: amd64-fedora-container
|
||||
script:
|
||||
@@ -572,7 +572,7 @@ build-tools-and-docs-debian:
|
||||
# of what topic branch they're currently using
|
||||
pages:
|
||||
extends: .base_job_template
|
||||
image: $CI_REGISTRY_IMAGE/qemu/debian-amd64:latest
|
||||
image: $CI_REGISTRY_IMAGE/qemu/debian-amd64:$QEMU_CI_CONTAINER_TAG
|
||||
stage: test
|
||||
needs:
|
||||
- job: build-tools-and-docs-debian
|
||||
|
||||
@@ -5,7 +5,8 @@
|
||||
services:
|
||||
- docker:dind
|
||||
before_script:
|
||||
- export TAG="$CI_REGISTRY_IMAGE/qemu/$NAME:latest"
|
||||
- export TAG="$CI_REGISTRY_IMAGE/qemu/$NAME:$QEMU_CI_CONTAINER_TAG"
|
||||
# Always ':latest' because we always use upstream as a common cache source
|
||||
- export COMMON_TAG="$CI_REGISTRY/qemu-project/qemu/qemu/$NAME:latest"
|
||||
- apk add python3
|
||||
- docker info
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
.cross_system_build_job:
|
||||
extends: .base_job_template
|
||||
stage: build
|
||||
image: $CI_REGISTRY_IMAGE/qemu/$IMAGE:latest
|
||||
image: $CI_REGISTRY_IMAGE/qemu/$IMAGE:$QEMU_CI_CONTAINER_TAG
|
||||
timeout: 80m
|
||||
script:
|
||||
- mkdir build
|
||||
@@ -27,7 +27,7 @@
|
||||
.cross_accel_build_job:
|
||||
extends: .base_job_template
|
||||
stage: build
|
||||
image: $CI_REGISTRY_IMAGE/qemu/$IMAGE:latest
|
||||
image: $CI_REGISTRY_IMAGE/qemu/$IMAGE:$QEMU_CI_CONTAINER_TAG
|
||||
timeout: 30m
|
||||
script:
|
||||
- mkdir build
|
||||
@@ -39,7 +39,7 @@
|
||||
.cross_user_build_job:
|
||||
extends: .base_job_template
|
||||
stage: build
|
||||
image: $CI_REGISTRY_IMAGE/qemu/$IMAGE:latest
|
||||
image: $CI_REGISTRY_IMAGE/qemu/$IMAGE:$QEMU_CI_CONTAINER_TAG
|
||||
script:
|
||||
- mkdir build
|
||||
- cd build
|
||||
|
||||
@@ -26,7 +26,7 @@ check-dco:
|
||||
check-python-minreqs:
|
||||
extends: .base_job_template
|
||||
stage: test
|
||||
image: $CI_REGISTRY_IMAGE/qemu/python:latest
|
||||
image: $CI_REGISTRY_IMAGE/qemu/python:$QEMU_CI_CONTAINER_TAG
|
||||
script:
|
||||
- make -C python check-minreqs
|
||||
variables:
|
||||
@@ -37,7 +37,7 @@ check-python-minreqs:
|
||||
check-python-tox:
|
||||
extends: .base_job_template
|
||||
stage: test
|
||||
image: $CI_REGISTRY_IMAGE/qemu/python:latest
|
||||
image: $CI_REGISTRY_IMAGE/qemu/python:$QEMU_CI_CONTAINER_TAG
|
||||
script:
|
||||
- make -C python check-tox
|
||||
variables:
|
||||
|
||||
+1
-1
@@ -1830,7 +1830,7 @@ static void *atomic_mmu_lookup(CPUArchState *env, target_ulong addr,
|
||||
} else /* if (prot & PAGE_READ) */ {
|
||||
tlb_addr = tlbe->addr_read;
|
||||
if (!tlb_hit(tlb_addr, addr)) {
|
||||
if (!VICTIM_TLB_HIT(addr_write, addr)) {
|
||||
if (!VICTIM_TLB_HIT(addr_read, addr)) {
|
||||
tlb_fill(env_cpu(env), addr, size,
|
||||
MMU_DATA_LOAD, mmu_idx, retaddr);
|
||||
index = tlb_index(env, mmu_idx, addr);
|
||||
|
||||
@@ -680,7 +680,7 @@ int coroutine_fn bdrv_co_create_opts_simple(BlockDriver *drv,
|
||||
|
||||
ret = 0;
|
||||
out:
|
||||
blk_unref(blk);
|
||||
blk_co_unref(blk);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -2018,7 +2018,15 @@ void blk_activate(BlockBackend *blk, Error **errp)
|
||||
return;
|
||||
}
|
||||
|
||||
bdrv_activate(bs, errp);
|
||||
/*
|
||||
* Migration code can call this function in coroutine context, so leave
|
||||
* coroutine context if necessary.
|
||||
*/
|
||||
if (qemu_in_coroutine()) {
|
||||
bdrv_co_activate(bs, errp);
|
||||
} else {
|
||||
bdrv_activate(bs, errp);
|
||||
}
|
||||
}
|
||||
|
||||
bool coroutine_fn blk_co_is_inserted(BlockBackend *blk)
|
||||
|
||||
+3
-3
@@ -355,7 +355,7 @@ block_crypto_co_create_generic(BlockDriverState *bs, int64_t size,
|
||||
ret = 0;
|
||||
cleanup:
|
||||
qcrypto_block_free(crypto);
|
||||
blk_unref(blk);
|
||||
blk_co_unref(blk);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -661,7 +661,7 @@ block_crypto_co_create_luks(BlockdevCreateOptions *create_options, Error **errp)
|
||||
|
||||
ret = 0;
|
||||
fail:
|
||||
bdrv_unref(bs);
|
||||
bdrv_co_unref(bs);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -730,7 +730,7 @@ fail:
|
||||
bdrv_co_delete_file_noerr(bs);
|
||||
}
|
||||
|
||||
bdrv_unref(bs);
|
||||
bdrv_co_unref(bs);
|
||||
qapi_free_QCryptoBlockCreateOptions(create_opts);
|
||||
qobject_unref(cryptoopts);
|
||||
return ret;
|
||||
|
||||
@@ -192,6 +192,7 @@ BlockExport *blk_exp_add(BlockExportOptions *export, Error **errp)
|
||||
return exp;
|
||||
|
||||
fail:
|
||||
blk_set_dev_ops(exp->blk, NULL, NULL);
|
||||
blk_unref(blk);
|
||||
aio_context_release(ctx);
|
||||
if (exp) {
|
||||
@@ -219,6 +220,7 @@ static void blk_exp_delete_bh(void *opaque)
|
||||
assert(exp->refcount == 0);
|
||||
QLIST_REMOVE(exp, next);
|
||||
exp->drv->delete(exp);
|
||||
blk_set_dev_ops(exp->blk, NULL, NULL);
|
||||
blk_unref(exp->blk);
|
||||
qapi_event_send_block_export_deleted(exp->id);
|
||||
g_free(exp->id);
|
||||
|
||||
@@ -346,7 +346,6 @@ static void vduse_blk_exp_delete(BlockExport *exp)
|
||||
|
||||
blk_remove_aio_context_notifier(exp->blk, blk_aio_attached, blk_aio_detach,
|
||||
vblk_exp);
|
||||
blk_set_dev_ops(exp->blk, NULL, NULL);
|
||||
ret = vduse_dev_destroy(vblk_exp->dev);
|
||||
if (ret != -EBUSY) {
|
||||
unlink(vblk_exp->recon_file);
|
||||
|
||||
@@ -214,15 +214,17 @@ void hmp_commit(Monitor *mon, const QDict *qdict)
|
||||
error_report("Device '%s' not found", device);
|
||||
return;
|
||||
}
|
||||
if (!blk_is_available(blk)) {
|
||||
error_report("Device '%s' has no medium", device);
|
||||
return;
|
||||
}
|
||||
|
||||
bs = bdrv_skip_implicit_filters(blk_bs(blk));
|
||||
aio_context = bdrv_get_aio_context(bs);
|
||||
aio_context_acquire(aio_context);
|
||||
|
||||
if (!blk_is_available(blk)) {
|
||||
error_report("Device '%s' has no medium", device);
|
||||
aio_context_release(aio_context);
|
||||
return;
|
||||
}
|
||||
|
||||
ret = bdrv_commit(bs);
|
||||
|
||||
aio_context_release(aio_context);
|
||||
|
||||
+3
-3
@@ -613,8 +613,8 @@ static int coroutine_fn parallels_co_create(BlockdevCreateOptions* opts,
|
||||
|
||||
ret = 0;
|
||||
out:
|
||||
blk_unref(blk);
|
||||
bdrv_unref(bs);
|
||||
blk_co_unref(blk);
|
||||
bdrv_co_unref(bs);
|
||||
return ret;
|
||||
|
||||
exit:
|
||||
@@ -691,7 +691,7 @@ parallels_co_create_opts(BlockDriver *drv, const char *filename,
|
||||
|
||||
done:
|
||||
qobject_unref(qdict);
|
||||
bdrv_unref(bs);
|
||||
bdrv_co_unref(bs);
|
||||
qapi_free_BlockdevCreateOptions(create_options);
|
||||
return ret;
|
||||
}
|
||||
|
||||
+3
-3
@@ -915,8 +915,8 @@ static int coroutine_fn qcow_co_create(BlockdevCreateOptions *opts,
|
||||
g_free(tmp);
|
||||
ret = 0;
|
||||
exit:
|
||||
blk_unref(qcow_blk);
|
||||
bdrv_unref(bs);
|
||||
blk_co_unref(qcow_blk);
|
||||
bdrv_co_unref(bs);
|
||||
qcrypto_block_free(crypto);
|
||||
return ret;
|
||||
}
|
||||
@@ -1015,7 +1015,7 @@ qcow_co_create_opts(BlockDriver *drv, const char *filename,
|
||||
fail:
|
||||
g_free(backing_fmt);
|
||||
qobject_unref(qdict);
|
||||
bdrv_unref(bs);
|
||||
bdrv_co_unref(bs);
|
||||
qapi_free_BlockdevCreateOptions(create_options);
|
||||
return ret;
|
||||
}
|
||||
|
||||
+7
-7
@@ -3705,7 +3705,7 @@ qcow2_co_create(BlockdevCreateOptions *create_options, Error **errp)
|
||||
goto out;
|
||||
}
|
||||
|
||||
blk_unref(blk);
|
||||
blk_co_unref(blk);
|
||||
blk = NULL;
|
||||
|
||||
/*
|
||||
@@ -3785,7 +3785,7 @@ qcow2_co_create(BlockdevCreateOptions *create_options, Error **errp)
|
||||
}
|
||||
}
|
||||
|
||||
blk_unref(blk);
|
||||
blk_co_unref(blk);
|
||||
blk = NULL;
|
||||
|
||||
/* Reopen the image without BDRV_O_NO_FLUSH to flush it before returning.
|
||||
@@ -3810,9 +3810,9 @@ qcow2_co_create(BlockdevCreateOptions *create_options, Error **errp)
|
||||
|
||||
ret = 0;
|
||||
out:
|
||||
blk_unref(blk);
|
||||
bdrv_unref(bs);
|
||||
bdrv_unref(data_bs);
|
||||
blk_co_unref(blk);
|
||||
bdrv_co_unref(bs);
|
||||
bdrv_co_unref(data_bs);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -3943,8 +3943,8 @@ finish:
|
||||
}
|
||||
|
||||
qobject_unref(qdict);
|
||||
bdrv_unref(bs);
|
||||
bdrv_unref(data_bs);
|
||||
bdrv_co_unref(bs);
|
||||
bdrv_co_unref(data_bs);
|
||||
qapi_free_BlockdevCreateOptions(create_options);
|
||||
return ret;
|
||||
}
|
||||
|
||||
+3
-3
@@ -748,8 +748,8 @@ static int coroutine_fn bdrv_qed_co_create(BlockdevCreateOptions *opts,
|
||||
ret = 0; /* success */
|
||||
out:
|
||||
g_free(l1_table);
|
||||
blk_unref(blk);
|
||||
bdrv_unref(bs);
|
||||
blk_co_unref(blk);
|
||||
bdrv_co_unref(bs);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -819,7 +819,7 @@ bdrv_qed_co_create_opts(BlockDriver *drv, const char *filename,
|
||||
|
||||
fail:
|
||||
qobject_unref(qdict);
|
||||
bdrv_unref(bs);
|
||||
bdrv_co_unref(bs);
|
||||
qapi_free_BlockdevCreateOptions(create_options);
|
||||
return ret;
|
||||
}
|
||||
|
||||
+3
-3
@@ -886,8 +886,8 @@ static int coroutine_fn vdi_co_do_create(BlockdevCreateOptions *create_options,
|
||||
|
||||
ret = 0;
|
||||
exit:
|
||||
blk_unref(blk);
|
||||
bdrv_unref(bs_file);
|
||||
blk_co_unref(blk);
|
||||
bdrv_co_unref(bs_file);
|
||||
g_free(bmap);
|
||||
return ret;
|
||||
}
|
||||
@@ -975,7 +975,7 @@ vdi_co_create_opts(BlockDriver *drv, const char *filename,
|
||||
done:
|
||||
qobject_unref(qdict);
|
||||
qapi_free_BlockdevCreateOptions(create_options);
|
||||
bdrv_unref(bs_file);
|
||||
bdrv_co_unref(bs_file);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
+3
-3
@@ -2053,8 +2053,8 @@ static int coroutine_fn vhdx_co_create(BlockdevCreateOptions *opts,
|
||||
|
||||
ret = 0;
|
||||
delete_and_exit:
|
||||
blk_unref(blk);
|
||||
bdrv_unref(bs);
|
||||
blk_co_unref(blk);
|
||||
bdrv_co_unref(bs);
|
||||
g_free(creator);
|
||||
return ret;
|
||||
}
|
||||
@@ -2144,7 +2144,7 @@ vhdx_co_create_opts(BlockDriver *drv, const char *filename,
|
||||
|
||||
fail:
|
||||
qobject_unref(qdict);
|
||||
bdrv_unref(bs);
|
||||
bdrv_co_unref(bs);
|
||||
qapi_free_BlockdevCreateOptions(create_options);
|
||||
return ret;
|
||||
}
|
||||
|
||||
+9
-9
@@ -2306,7 +2306,7 @@ exit:
|
||||
if (pbb) {
|
||||
*pbb = blk;
|
||||
} else {
|
||||
blk_unref(blk);
|
||||
blk_co_unref(blk);
|
||||
blk = NULL;
|
||||
}
|
||||
}
|
||||
@@ -2516,12 +2516,12 @@ vmdk_co_do_create(int64_t size,
|
||||
if (strcmp(blk_bs(backing)->drv->format_name, "vmdk")) {
|
||||
error_setg(errp, "Invalid backing file format: %s. Must be vmdk",
|
||||
blk_bs(backing)->drv->format_name);
|
||||
blk_unref(backing);
|
||||
blk_co_unref(backing);
|
||||
ret = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
ret = vmdk_read_cid(blk_bs(backing), 0, &parent_cid);
|
||||
blk_unref(backing);
|
||||
blk_co_unref(backing);
|
||||
if (ret) {
|
||||
error_setg(errp, "Failed to read parent CID");
|
||||
goto exit;
|
||||
@@ -2542,14 +2542,14 @@ vmdk_co_do_create(int64_t size,
|
||||
blk_bs(extent_blk)->filename);
|
||||
created_size += cur_size;
|
||||
extent_idx++;
|
||||
blk_unref(extent_blk);
|
||||
blk_co_unref(extent_blk);
|
||||
}
|
||||
|
||||
/* Check whether we got excess extents */
|
||||
extent_blk = extent_fn(-1, extent_idx, flat, split, compress, zeroed_grain,
|
||||
opaque, NULL);
|
||||
if (extent_blk) {
|
||||
blk_unref(extent_blk);
|
||||
blk_co_unref(extent_blk);
|
||||
error_setg(errp, "List of extents contains unused extents");
|
||||
ret = -EINVAL;
|
||||
goto exit;
|
||||
@@ -2590,7 +2590,7 @@ vmdk_co_do_create(int64_t size,
|
||||
ret = 0;
|
||||
exit:
|
||||
if (blk) {
|
||||
blk_unref(blk);
|
||||
blk_co_unref(blk);
|
||||
}
|
||||
g_free(desc);
|
||||
g_free(parent_desc_line);
|
||||
@@ -2641,7 +2641,7 @@ vmdk_co_create_opts_cb(int64_t size, int idx, bool flat, bool split,
|
||||
errp)) {
|
||||
goto exit;
|
||||
}
|
||||
bdrv_unref(bs);
|
||||
bdrv_co_unref(bs);
|
||||
exit:
|
||||
g_free(ext_filename);
|
||||
return blk;
|
||||
@@ -2797,12 +2797,12 @@ static BlockBackend * coroutine_fn vmdk_co_create_cb(int64_t size, int idx,
|
||||
return NULL;
|
||||
}
|
||||
blk_set_allow_write_beyond_eof(blk, true);
|
||||
bdrv_unref(bs);
|
||||
bdrv_co_unref(bs);
|
||||
|
||||
if (size != -1) {
|
||||
ret = vmdk_init_extent(blk, size, flat, compress, zeroed_grain, errp);
|
||||
if (ret) {
|
||||
blk_unref(blk);
|
||||
blk_co_unref(blk);
|
||||
blk = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
+3
-3
@@ -1082,8 +1082,8 @@ static int coroutine_fn vpc_co_create(BlockdevCreateOptions *opts,
|
||||
}
|
||||
|
||||
out:
|
||||
blk_unref(blk);
|
||||
bdrv_unref(bs);
|
||||
blk_co_unref(blk);
|
||||
bdrv_co_unref(bs);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -1162,7 +1162,7 @@ vpc_co_create_opts(BlockDriver *drv, const char *filename,
|
||||
|
||||
fail:
|
||||
qobject_unref(qdict);
|
||||
bdrv_unref(bs);
|
||||
bdrv_co_unref(bs);
|
||||
qapi_free_BlockdevCreateOptions(create_options);
|
||||
return ret;
|
||||
}
|
||||
|
||||
+16
-6
@@ -153,12 +153,22 @@ void blockdev_mark_auto_del(BlockBackend *blk)
|
||||
|
||||
JOB_LOCK_GUARD();
|
||||
|
||||
for (job = block_job_next_locked(NULL); job;
|
||||
job = block_job_next_locked(job)) {
|
||||
if (block_job_has_bdrv(job, blk_bs(blk))) {
|
||||
do {
|
||||
job = block_job_next_locked(NULL);
|
||||
while (job && (job->job.cancelled ||
|
||||
job->job.deferred_to_main_loop ||
|
||||
!block_job_has_bdrv(job, blk_bs(blk))))
|
||||
{
|
||||
job = block_job_next_locked(job);
|
||||
}
|
||||
if (job) {
|
||||
/*
|
||||
* This drops the job lock temporarily and polls, so we need to
|
||||
* restart processing the list from the start after this.
|
||||
*/
|
||||
job_cancel_locked(&job->job, false);
|
||||
}
|
||||
}
|
||||
} while (job);
|
||||
|
||||
dinfo->auto_del = 1;
|
||||
}
|
||||
@@ -2430,7 +2440,7 @@ void coroutine_fn qmp_block_resize(const char *device, const char *node_name,
|
||||
return;
|
||||
}
|
||||
|
||||
blk = blk_new_with_bs(bs, BLK_PERM_RESIZE, BLK_PERM_ALL, errp);
|
||||
blk = blk_co_new_with_bs(bs, BLK_PERM_RESIZE, BLK_PERM_ALL, errp);
|
||||
if (!blk) {
|
||||
return;
|
||||
}
|
||||
@@ -2445,7 +2455,7 @@ void coroutine_fn qmp_block_resize(const char *device, const char *node_name,
|
||||
|
||||
bdrv_co_lock(bs);
|
||||
bdrv_drained_end(bs);
|
||||
blk_unref(blk);
|
||||
blk_co_unref(blk);
|
||||
bdrv_co_unlock(bs);
|
||||
}
|
||||
|
||||
|
||||
@@ -219,8 +219,8 @@ Use the more generic event ``DEVICE_UNPLUG_GUEST_ERROR`` instead.
|
||||
System emulator machines
|
||||
------------------------
|
||||
|
||||
Arm ``virt`` machine ``dtb-kaslr-seed`` property
|
||||
''''''''''''''''''''''''''''''''''''''''''''''''
|
||||
Arm ``virt`` machine ``dtb-kaslr-seed`` property (since 7.1)
|
||||
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
|
||||
|
||||
The ``dtb-kaslr-seed`` property on the ``virt`` board has been
|
||||
deprecated; use the new name ``dtb-randomness`` instead. The new name
|
||||
|
||||
@@ -70,6 +70,17 @@ in a handful of namespaces
|
||||
repository CI settings, or as git push variables, to influence
|
||||
which jobs get run in a pipeline
|
||||
|
||||
* QEMU_CI_CONTAINER_TAG - the tag used to publish containers
|
||||
in stage 1, for use by build jobs in stage 2. Defaults to
|
||||
'latest', but if running pipelines for different branches
|
||||
concurrently, it should be overridden per pipeline.
|
||||
|
||||
* QEMU_CI_UPSTREAM - gitlab namespace that is considerd to be
|
||||
the 'upstream'. This defaults to 'qemu-project'. Contributors
|
||||
may choose to override this if they are modifying rules in
|
||||
base.yml and need to validate how they will operate when in
|
||||
an upstream context, as opposed to their fork context.
|
||||
|
||||
* nnn - other misc variables not falling into the above
|
||||
categories, or using different names for historical reasons
|
||||
and not yet converted.
|
||||
|
||||
+1
-1
@@ -5135,7 +5135,7 @@ float32 float32_exp2(float32 a, float_status *status)
|
||||
float64_unpack_canonical(&rp, float64_one, status);
|
||||
for (i = 0 ; i < 15 ; i++) {
|
||||
float64_unpack_canonical(&tp, float32_exp2_coefficients[i], status);
|
||||
rp = *parts_muladd(&tp, &xp, &rp, 0, status);
|
||||
rp = *parts_muladd(&tp, &xnp, &rp, 0, status);
|
||||
xnp = *parts_mul(&xnp, &xp, status);
|
||||
}
|
||||
|
||||
|
||||
@@ -48,3 +48,9 @@ v9fs_readlink(uint16_t tag, uint8_t id, int32_t fid) "tag %d id %d fid %d"
|
||||
v9fs_readlink_return(uint16_t tag, uint8_t id, char* target) "tag %d id %d name %s"
|
||||
v9fs_setattr(uint16_t tag, uint8_t id, int32_t fid, int32_t valid, int32_t mode, int32_t uid, int32_t gid, int64_t size, int64_t atime_sec, int64_t mtime_sec) "tag %u id %u fid %d iattr={valid %d mode %d uid %d gid %d size %"PRId64" atime=%"PRId64" mtime=%"PRId64" }"
|
||||
v9fs_setattr_return(uint16_t tag, uint8_t id) "tag %u id %u"
|
||||
|
||||
# xen-9p-backend.c
|
||||
xen_9pfs_alloc(char *name) "name %s"
|
||||
xen_9pfs_connect(char *name) "name %s"
|
||||
xen_9pfs_disconnect(char *name) "name %s"
|
||||
xen_9pfs_free(char *name) "name %s"
|
||||
|
||||
+22
-13
@@ -25,6 +25,8 @@
|
||||
#include "qemu/iov.h"
|
||||
#include "fsdev/qemu-fsdev.h"
|
||||
|
||||
#include "trace.h"
|
||||
|
||||
#define VERSIONS "1"
|
||||
#define MAX_RINGS 8
|
||||
#define MAX_RING_ORDER 9
|
||||
@@ -336,6 +338,8 @@ static void xen_9pfs_disconnect(struct XenLegacyDevice *xendev)
|
||||
Xen9pfsDev *xen_9pdev = container_of(xendev, Xen9pfsDev, xendev);
|
||||
int i;
|
||||
|
||||
trace_xen_9pfs_disconnect(xendev->name);
|
||||
|
||||
for (i = 0; i < xen_9pdev->num_rings; i++) {
|
||||
if (xen_9pdev->rings[i].evtchndev != NULL) {
|
||||
qemu_set_fd_handler(qemu_xen_evtchn_fd(xen_9pdev->rings[i].evtchndev),
|
||||
@@ -344,40 +348,41 @@ static void xen_9pfs_disconnect(struct XenLegacyDevice *xendev)
|
||||
xen_9pdev->rings[i].local_port);
|
||||
xen_9pdev->rings[i].evtchndev = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int xen_9pfs_free(struct XenLegacyDevice *xendev)
|
||||
{
|
||||
Xen9pfsDev *xen_9pdev = container_of(xendev, Xen9pfsDev, xendev);
|
||||
int i;
|
||||
|
||||
if (xen_9pdev->rings[0].evtchndev != NULL) {
|
||||
xen_9pfs_disconnect(xendev);
|
||||
}
|
||||
|
||||
for (i = 0; i < xen_9pdev->num_rings; i++) {
|
||||
if (xen_9pdev->rings[i].data != NULL) {
|
||||
xen_be_unmap_grant_refs(&xen_9pdev->xendev,
|
||||
xen_9pdev->rings[i].data,
|
||||
xen_9pdev->rings[i].intf->ref,
|
||||
(1 << xen_9pdev->rings[i].ring_order));
|
||||
xen_9pdev->rings[i].data = NULL;
|
||||
}
|
||||
if (xen_9pdev->rings[i].intf != NULL) {
|
||||
xen_be_unmap_grant_ref(&xen_9pdev->xendev,
|
||||
xen_9pdev->rings[i].intf,
|
||||
xen_9pdev->rings[i].ref);
|
||||
xen_9pdev->rings[i].intf = NULL;
|
||||
}
|
||||
if (xen_9pdev->rings[i].bh != NULL) {
|
||||
qemu_bh_delete(xen_9pdev->rings[i].bh);
|
||||
xen_9pdev->rings[i].bh = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
g_free(xen_9pdev->id);
|
||||
xen_9pdev->id = NULL;
|
||||
g_free(xen_9pdev->tag);
|
||||
xen_9pdev->tag = NULL;
|
||||
g_free(xen_9pdev->path);
|
||||
xen_9pdev->path = NULL;
|
||||
g_free(xen_9pdev->security_model);
|
||||
xen_9pdev->security_model = NULL;
|
||||
g_free(xen_9pdev->rings);
|
||||
xen_9pdev->rings = NULL;
|
||||
}
|
||||
|
||||
static int xen_9pfs_free(struct XenLegacyDevice *xendev)
|
||||
{
|
||||
trace_xen_9pfs_free(xendev->name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -389,6 +394,8 @@ static int xen_9pfs_connect(struct XenLegacyDevice *xendev)
|
||||
V9fsState *s = &xen_9pdev->state;
|
||||
QemuOpts *fsdev;
|
||||
|
||||
trace_xen_9pfs_connect(xendev->name);
|
||||
|
||||
if (xenstore_read_fe_int(&xen_9pdev->xendev, "num-rings",
|
||||
&xen_9pdev->num_rings) == -1 ||
|
||||
xen_9pdev->num_rings > MAX_RINGS || xen_9pdev->num_rings < 1) {
|
||||
@@ -496,6 +503,8 @@ out:
|
||||
|
||||
static void xen_9pfs_alloc(struct XenLegacyDevice *xendev)
|
||||
{
|
||||
trace_xen_9pfs_alloc(xendev->name);
|
||||
|
||||
xenstore_write_be_str(xendev, "versions", VERSIONS);
|
||||
xenstore_write_be_int(xendev, "max-rings", MAX_RINGS);
|
||||
xenstore_write_be_int(xendev, "max-ring-page-order", MAX_RING_ORDER);
|
||||
|
||||
@@ -357,6 +357,16 @@ void acpi_pcihp_device_unplug_request_cb(HotplugHandler *hotplug_dev,
|
||||
* acpi_pcihp_eject_slot() when the operation is completed.
|
||||
*/
|
||||
pdev->qdev.pending_deleted_event = true;
|
||||
/* if unplug was requested before OSPM is initialized,
|
||||
* linux kernel will clear GPE0.sts[] bits during boot, which effectively
|
||||
* hides unplug event. And than followup qmp_device_del() calls remain
|
||||
* blocked by above flag permanently.
|
||||
* Unblock qmp_device_del() by setting expire limit, so user can
|
||||
* repeat unplug request later when OSPM has been booted.
|
||||
*/
|
||||
pdev->qdev.pending_deleted_expires_ms =
|
||||
qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL); /* 1 msec */
|
||||
|
||||
s->acpi_pcihp_pci_status[bsel].down |= (1U << slot);
|
||||
acpi_send_event(DEVICE(hotplug_dev), ACPI_PCI_HOTPLUG_STATUS);
|
||||
}
|
||||
|
||||
+20
-18
@@ -200,33 +200,35 @@ struct AspeedMachineState {
|
||||
static void aspeed_write_smpboot(ARMCPU *cpu,
|
||||
const struct arm_boot_info *info)
|
||||
{
|
||||
static const uint32_t poll_mailbox_ready[] = {
|
||||
AddressSpace *as = arm_boot_address_space(cpu, info);
|
||||
static const ARMInsnFixup poll_mailbox_ready[] = {
|
||||
/*
|
||||
* r2 = per-cpu go sign value
|
||||
* r1 = AST_SMP_MBOX_FIELD_ENTRY
|
||||
* r0 = AST_SMP_MBOX_FIELD_GOSIGN
|
||||
*/
|
||||
0xee100fb0, /* mrc p15, 0, r0, c0, c0, 5 */
|
||||
0xe21000ff, /* ands r0, r0, #255 */
|
||||
0xe59f201c, /* ldr r2, [pc, #28] */
|
||||
0xe1822000, /* orr r2, r2, r0 */
|
||||
{ 0xee100fb0 }, /* mrc p15, 0, r0, c0, c0, 5 */
|
||||
{ 0xe21000ff }, /* ands r0, r0, #255 */
|
||||
{ 0xe59f201c }, /* ldr r2, [pc, #28] */
|
||||
{ 0xe1822000 }, /* orr r2, r2, r0 */
|
||||
|
||||
0xe59f1018, /* ldr r1, [pc, #24] */
|
||||
0xe59f0018, /* ldr r0, [pc, #24] */
|
||||
{ 0xe59f1018 }, /* ldr r1, [pc, #24] */
|
||||
{ 0xe59f0018 }, /* ldr r0, [pc, #24] */
|
||||
|
||||
0xe320f002, /* wfe */
|
||||
0xe5904000, /* ldr r4, [r0] */
|
||||
0xe1520004, /* cmp r2, r4 */
|
||||
0x1afffffb, /* bne <wfe> */
|
||||
0xe591f000, /* ldr pc, [r1] */
|
||||
AST_SMP_MBOX_GOSIGN,
|
||||
AST_SMP_MBOX_FIELD_ENTRY,
|
||||
AST_SMP_MBOX_FIELD_GOSIGN,
|
||||
{ 0xe320f002 }, /* wfe */
|
||||
{ 0xe5904000 }, /* ldr r4, [r0] */
|
||||
{ 0xe1520004 }, /* cmp r2, r4 */
|
||||
{ 0x1afffffb }, /* bne <wfe> */
|
||||
{ 0xe591f000 }, /* ldr pc, [r1] */
|
||||
{ AST_SMP_MBOX_GOSIGN },
|
||||
{ AST_SMP_MBOX_FIELD_ENTRY },
|
||||
{ AST_SMP_MBOX_FIELD_GOSIGN },
|
||||
{ 0, FIXUP_TERMINATOR }
|
||||
};
|
||||
static const uint32_t fixupcontext[FIXUP_MAX] = { 0 };
|
||||
|
||||
rom_add_blob_fixed("aspeed.smpboot", poll_mailbox_ready,
|
||||
sizeof(poll_mailbox_ready),
|
||||
info->smp_loader_start);
|
||||
arm_write_bootloader("aspeed.smpboot", as, info->smp_loader_start,
|
||||
poll_mailbox_ready, fixupcontext);
|
||||
}
|
||||
|
||||
static void aspeed_reset_secondary(ARMCPU *cpu,
|
||||
|
||||
+8
-27
@@ -60,26 +60,6 @@ AddressSpace *arm_boot_address_space(ARMCPU *cpu,
|
||||
return cpu_get_address_space(cs, asidx);
|
||||
}
|
||||
|
||||
typedef enum {
|
||||
FIXUP_NONE = 0, /* do nothing */
|
||||
FIXUP_TERMINATOR, /* end of insns */
|
||||
FIXUP_BOARDID, /* overwrite with board ID number */
|
||||
FIXUP_BOARD_SETUP, /* overwrite with board specific setup code address */
|
||||
FIXUP_ARGPTR_LO, /* overwrite with pointer to kernel args */
|
||||
FIXUP_ARGPTR_HI, /* overwrite with pointer to kernel args (high half) */
|
||||
FIXUP_ENTRYPOINT_LO, /* overwrite with kernel entry point */
|
||||
FIXUP_ENTRYPOINT_HI, /* overwrite with kernel entry point (high half) */
|
||||
FIXUP_GIC_CPU_IF, /* overwrite with GIC CPU interface address */
|
||||
FIXUP_BOOTREG, /* overwrite with boot register address */
|
||||
FIXUP_DSB, /* overwrite with correct DSB insn for cpu */
|
||||
FIXUP_MAX,
|
||||
} FixupType;
|
||||
|
||||
typedef struct ARMInsnFixup {
|
||||
uint32_t insn;
|
||||
FixupType fixup;
|
||||
} ARMInsnFixup;
|
||||
|
||||
static const ARMInsnFixup bootloader_aarch64[] = {
|
||||
{ 0x580000c0 }, /* ldr x0, arg ; Load the lower 32-bits of DTB */
|
||||
{ 0xaa1f03e1 }, /* mov x1, xzr */
|
||||
@@ -150,9 +130,10 @@ static const ARMInsnFixup smpboot[] = {
|
||||
{ 0, FIXUP_TERMINATOR }
|
||||
};
|
||||
|
||||
static void write_bootloader(const char *name, hwaddr addr,
|
||||
const ARMInsnFixup *insns, uint32_t *fixupcontext,
|
||||
AddressSpace *as)
|
||||
void arm_write_bootloader(const char *name,
|
||||
AddressSpace *as, hwaddr addr,
|
||||
const ARMInsnFixup *insns,
|
||||
const uint32_t *fixupcontext)
|
||||
{
|
||||
/* Fix up the specified bootloader fragment and write it into
|
||||
* guest memory using rom_add_blob_fixed(). fixupcontext is
|
||||
@@ -214,8 +195,8 @@ static void default_write_secondary(ARMCPU *cpu,
|
||||
fixupcontext[FIXUP_DSB] = CP15_DSB_INSN;
|
||||
}
|
||||
|
||||
write_bootloader("smpboot", info->smp_loader_start,
|
||||
smpboot, fixupcontext, as);
|
||||
arm_write_bootloader("smpboot", as, info->smp_loader_start,
|
||||
smpboot, fixupcontext);
|
||||
}
|
||||
|
||||
void arm_write_secure_board_setup_dummy_smc(ARMCPU *cpu,
|
||||
@@ -1186,8 +1167,8 @@ static void arm_setup_direct_kernel_boot(ARMCPU *cpu,
|
||||
fixupcontext[FIXUP_ENTRYPOINT_LO] = entry;
|
||||
fixupcontext[FIXUP_ENTRYPOINT_HI] = entry >> 32;
|
||||
|
||||
write_bootloader("bootloader", info->loader_start,
|
||||
primary_loader, fixupcontext, as);
|
||||
arm_write_bootloader("bootloader", as, info->loader_start,
|
||||
primary_loader, fixupcontext);
|
||||
|
||||
if (info->write_board_setup) {
|
||||
info->write_board_setup(cpu, info);
|
||||
|
||||
+34
-30
@@ -16,6 +16,7 @@
|
||||
#include "qemu/units.h"
|
||||
#include "qemu/cutils.h"
|
||||
#include "qapi/error.h"
|
||||
#include "hw/arm/boot.h"
|
||||
#include "hw/arm/bcm2836.h"
|
||||
#include "hw/registerfields.h"
|
||||
#include "qemu/error-report.h"
|
||||
@@ -124,20 +125,22 @@ static const char *board_type(uint32_t board_rev)
|
||||
|
||||
static void write_smpboot(ARMCPU *cpu, const struct arm_boot_info *info)
|
||||
{
|
||||
static const uint32_t smpboot[] = {
|
||||
0xe1a0e00f, /* mov lr, pc */
|
||||
0xe3a0fe00 + (BOARDSETUP_ADDR >> 4), /* mov pc, BOARDSETUP_ADDR */
|
||||
0xee100fb0, /* mrc p15, 0, r0, c0, c0, 5;get core ID */
|
||||
0xe7e10050, /* ubfx r0, r0, #0, #2 ;extract LSB */
|
||||
0xe59f5014, /* ldr r5, =0x400000CC ;load mbox base */
|
||||
0xe320f001, /* 1: yield */
|
||||
0xe7953200, /* ldr r3, [r5, r0, lsl #4] ;read mbox for our core*/
|
||||
0xe3530000, /* cmp r3, #0 ;spin while zero */
|
||||
0x0afffffb, /* beq 1b */
|
||||
0xe7853200, /* str r3, [r5, r0, lsl #4] ;clear mbox */
|
||||
0xe12fff13, /* bx r3 ;jump to target */
|
||||
0x400000cc, /* (constant: mailbox 3 read/clear base) */
|
||||
static const ARMInsnFixup smpboot[] = {
|
||||
{ 0xe1a0e00f }, /* mov lr, pc */
|
||||
{ 0xe3a0fe00 + (BOARDSETUP_ADDR >> 4) }, /* mov pc, BOARDSETUP_ADDR */
|
||||
{ 0xee100fb0 }, /* mrc p15, 0, r0, c0, c0, 5;get core ID */
|
||||
{ 0xe7e10050 }, /* ubfx r0, r0, #0, #2 ;extract LSB */
|
||||
{ 0xe59f5014 }, /* ldr r5, =0x400000CC ;load mbox base */
|
||||
{ 0xe320f001 }, /* 1: yield */
|
||||
{ 0xe7953200 }, /* ldr r3, [r5, r0, lsl #4] ;read mbox for our core */
|
||||
{ 0xe3530000 }, /* cmp r3, #0 ;spin while zero */
|
||||
{ 0x0afffffb }, /* beq 1b */
|
||||
{ 0xe7853200 }, /* str r3, [r5, r0, lsl #4] ;clear mbox */
|
||||
{ 0xe12fff13 }, /* bx r3 ;jump to target */
|
||||
{ 0x400000cc }, /* (constant: mailbox 3 read/clear base) */
|
||||
{ 0, FIXUP_TERMINATOR }
|
||||
};
|
||||
static const uint32_t fixupcontext[FIXUP_MAX] = { 0 };
|
||||
|
||||
/* check that we don't overrun board setup vectors */
|
||||
QEMU_BUILD_BUG_ON(SMPBOOT_ADDR + sizeof(smpboot) > MVBAR_ADDR);
|
||||
@@ -145,9 +148,8 @@ static void write_smpboot(ARMCPU *cpu, const struct arm_boot_info *info)
|
||||
QEMU_BUILD_BUG_ON((BOARDSETUP_ADDR & 0xf) != 0
|
||||
|| (BOARDSETUP_ADDR >> 4) >= 0x100);
|
||||
|
||||
rom_add_blob_fixed_as("raspi_smpboot", smpboot, sizeof(smpboot),
|
||||
info->smp_loader_start,
|
||||
arm_boot_address_space(cpu, info));
|
||||
arm_write_bootloader("raspi_smpboot", arm_boot_address_space(cpu, info),
|
||||
info->smp_loader_start, smpboot, fixupcontext);
|
||||
}
|
||||
|
||||
static void write_smpboot64(ARMCPU *cpu, const struct arm_boot_info *info)
|
||||
@@ -161,26 +163,28 @@ static void write_smpboot64(ARMCPU *cpu, const struct arm_boot_info *info)
|
||||
* the primary CPU goes into the kernel. We put these variables inside
|
||||
* a rom blob, so that the reset for ROM contents zeroes them for us.
|
||||
*/
|
||||
static const uint32_t smpboot[] = {
|
||||
0xd2801b05, /* mov x5, 0xd8 */
|
||||
0xd53800a6, /* mrs x6, mpidr_el1 */
|
||||
0x924004c6, /* and x6, x6, #0x3 */
|
||||
0xd503205f, /* spin: wfe */
|
||||
0xf86678a4, /* ldr x4, [x5,x6,lsl #3] */
|
||||
0xb4ffffc4, /* cbz x4, spin */
|
||||
0xd2800000, /* mov x0, #0x0 */
|
||||
0xd2800001, /* mov x1, #0x0 */
|
||||
0xd2800002, /* mov x2, #0x0 */
|
||||
0xd2800003, /* mov x3, #0x0 */
|
||||
0xd61f0080, /* br x4 */
|
||||
static const ARMInsnFixup smpboot[] = {
|
||||
{ 0xd2801b05 }, /* mov x5, 0xd8 */
|
||||
{ 0xd53800a6 }, /* mrs x6, mpidr_el1 */
|
||||
{ 0x924004c6 }, /* and x6, x6, #0x3 */
|
||||
{ 0xd503205f }, /* spin: wfe */
|
||||
{ 0xf86678a4 }, /* ldr x4, [x5,x6,lsl #3] */
|
||||
{ 0xb4ffffc4 }, /* cbz x4, spin */
|
||||
{ 0xd2800000 }, /* mov x0, #0x0 */
|
||||
{ 0xd2800001 }, /* mov x1, #0x0 */
|
||||
{ 0xd2800002 }, /* mov x2, #0x0 */
|
||||
{ 0xd2800003 }, /* mov x3, #0x0 */
|
||||
{ 0xd61f0080 }, /* br x4 */
|
||||
{ 0, FIXUP_TERMINATOR }
|
||||
};
|
||||
static const uint32_t fixupcontext[FIXUP_MAX] = { 0 };
|
||||
|
||||
static const uint64_t spintables[] = {
|
||||
0, 0, 0, 0
|
||||
};
|
||||
|
||||
rom_add_blob_fixed_as("raspi_smpboot", smpboot, sizeof(smpboot),
|
||||
info->smp_loader_start, as);
|
||||
arm_write_bootloader("raspi_smpboot", as, info->smp_loader_start,
|
||||
smpboot, fixupcontext);
|
||||
rom_add_blob_fixed_as("raspi_spintables", spintables, sizeof(spintables),
|
||||
SPINTABLE_ADDR, as);
|
||||
}
|
||||
|
||||
@@ -49,12 +49,9 @@ static void aw_a10_pic_update(AwA10PICState *s)
|
||||
static void aw_a10_pic_set_irq(void *opaque, int irq, int level)
|
||||
{
|
||||
AwA10PICState *s = opaque;
|
||||
uint32_t *pending_reg = &s->irq_pending[irq / 32];
|
||||
|
||||
if (level) {
|
||||
set_bit(irq % 32, (void *)&s->irq_pending[irq / 32]);
|
||||
} else {
|
||||
clear_bit(irq % 32, (void *)&s->irq_pending[irq / 32]);
|
||||
}
|
||||
*pending_reg = deposit32(*pending_reg, irq % 32, 1, level);
|
||||
aw_a10_pic_update(s);
|
||||
}
|
||||
|
||||
|
||||
@@ -350,8 +350,13 @@ static void allwinner_sun8i_emac_get_desc(AwSun8iEmacState *s,
|
||||
FrameDescriptor *desc,
|
||||
uint32_t phys_addr)
|
||||
{
|
||||
dma_memory_read(&s->dma_as, phys_addr, desc, sizeof(*desc),
|
||||
uint32_t desc_words[4];
|
||||
dma_memory_read(&s->dma_as, phys_addr, &desc_words, sizeof(desc_words),
|
||||
MEMTXATTRS_UNSPECIFIED);
|
||||
desc->status = le32_to_cpu(desc_words[0]);
|
||||
desc->status2 = le32_to_cpu(desc_words[1]);
|
||||
desc->addr = le32_to_cpu(desc_words[2]);
|
||||
desc->next = le32_to_cpu(desc_words[3]);
|
||||
}
|
||||
|
||||
static uint32_t allwinner_sun8i_emac_next_desc(AwSun8iEmacState *s,
|
||||
@@ -400,10 +405,15 @@ static uint32_t allwinner_sun8i_emac_tx_desc(AwSun8iEmacState *s,
|
||||
}
|
||||
|
||||
static void allwinner_sun8i_emac_flush_desc(AwSun8iEmacState *s,
|
||||
FrameDescriptor *desc,
|
||||
const FrameDescriptor *desc,
|
||||
uint32_t phys_addr)
|
||||
{
|
||||
dma_memory_write(&s->dma_as, phys_addr, desc, sizeof(*desc),
|
||||
uint32_t desc_words[4];
|
||||
desc_words[0] = cpu_to_le32(desc->status);
|
||||
desc_words[1] = cpu_to_le32(desc->status2);
|
||||
desc_words[2] = cpu_to_le32(desc->addr);
|
||||
desc_words[3] = cpu_to_le32(desc->next);
|
||||
dma_memory_write(&s->dma_as, phys_addr, &desc_words, sizeof(desc_words),
|
||||
MEMTXATTRS_UNSPECIFIED);
|
||||
}
|
||||
|
||||
@@ -638,8 +648,7 @@ static uint64_t allwinner_sun8i_emac_read(void *opaque, hwaddr offset,
|
||||
break;
|
||||
case REG_TX_CUR_BUF: /* Transmit Current Buffer */
|
||||
if (s->tx_desc_curr != 0) {
|
||||
dma_memory_read(&s->dma_as, s->tx_desc_curr, &desc, sizeof(desc),
|
||||
MEMTXATTRS_UNSPECIFIED);
|
||||
allwinner_sun8i_emac_get_desc(s, &desc, s->tx_desc_curr);
|
||||
value = desc.addr;
|
||||
} else {
|
||||
value = 0;
|
||||
@@ -652,8 +661,7 @@ static uint64_t allwinner_sun8i_emac_read(void *opaque, hwaddr offset,
|
||||
break;
|
||||
case REG_RX_CUR_BUF: /* Receive Current Buffer */
|
||||
if (s->rx_desc_curr != 0) {
|
||||
dma_memory_read(&s->dma_as, s->rx_desc_curr, &desc, sizeof(desc),
|
||||
MEMTXATTRS_UNSPECIFIED);
|
||||
allwinner_sun8i_emac_get_desc(s, &desc, s->rx_desc_curr);
|
||||
value = desc.addr;
|
||||
} else {
|
||||
value = 0;
|
||||
|
||||
+10
-6
@@ -118,14 +118,18 @@ static void emac_load_desc(MSF2EmacState *s, EmacDesc *d, hwaddr desc)
|
||||
d->next = le32_to_cpu(d->next);
|
||||
}
|
||||
|
||||
static void emac_store_desc(MSF2EmacState *s, EmacDesc *d, hwaddr desc)
|
||||
static void emac_store_desc(MSF2EmacState *s, const EmacDesc *d, hwaddr desc)
|
||||
{
|
||||
/* Convert from host endianness into LE. */
|
||||
d->pktaddr = cpu_to_le32(d->pktaddr);
|
||||
d->pktsize = cpu_to_le32(d->pktsize);
|
||||
d->next = cpu_to_le32(d->next);
|
||||
EmacDesc outd;
|
||||
/*
|
||||
* Convert from host endianness into LE. We use a local struct because
|
||||
* calling code may still want to look at the fields afterwards.
|
||||
*/
|
||||
outd.pktaddr = cpu_to_le32(d->pktaddr);
|
||||
outd.pktsize = cpu_to_le32(d->pktsize);
|
||||
outd.next = cpu_to_le32(d->next);
|
||||
|
||||
address_space_write(&s->dma_as, desc, MEMTXATTRS_UNSPECIFIED, d, sizeof *d);
|
||||
address_space_write(&s->dma_as, desc, MEMTXATTRS_UNSPECIFIED, &outd, sizeof outd);
|
||||
}
|
||||
|
||||
static void msf2_dma_tx(MSF2EmacState *s)
|
||||
|
||||
@@ -311,7 +311,7 @@ static void pxb_cxl_dev_reset(DeviceState *dev)
|
||||
* The CXL specification allows for host bridges with no HDM decoders
|
||||
* if they only have a single root port.
|
||||
*/
|
||||
if (!PXB_DEV(dev)->hdm_for_passthrough) {
|
||||
if (!PXB_CXL_DEV(dev)->hdm_for_passthrough) {
|
||||
dsp_count = pcie_count_ds_ports(hb->bus);
|
||||
}
|
||||
/* Initial reset will have 0 dsp so wait until > 0 */
|
||||
|
||||
@@ -302,6 +302,30 @@ static void allwinner_sdhost_auto_stop(AwSdHostState *s)
|
||||
}
|
||||
}
|
||||
|
||||
static void read_descriptor(AwSdHostState *s, hwaddr desc_addr,
|
||||
TransferDescriptor *desc)
|
||||
{
|
||||
uint32_t desc_words[4];
|
||||
dma_memory_read(&s->dma_as, desc_addr, &desc_words, sizeof(desc_words),
|
||||
MEMTXATTRS_UNSPECIFIED);
|
||||
desc->status = le32_to_cpu(desc_words[0]);
|
||||
desc->size = le32_to_cpu(desc_words[1]);
|
||||
desc->addr = le32_to_cpu(desc_words[2]);
|
||||
desc->next = le32_to_cpu(desc_words[3]);
|
||||
}
|
||||
|
||||
static void write_descriptor(AwSdHostState *s, hwaddr desc_addr,
|
||||
const TransferDescriptor *desc)
|
||||
{
|
||||
uint32_t desc_words[4];
|
||||
desc_words[0] = cpu_to_le32(desc->status);
|
||||
desc_words[1] = cpu_to_le32(desc->size);
|
||||
desc_words[2] = cpu_to_le32(desc->addr);
|
||||
desc_words[3] = cpu_to_le32(desc->next);
|
||||
dma_memory_write(&s->dma_as, desc_addr, &desc_words, sizeof(desc_words),
|
||||
MEMTXATTRS_UNSPECIFIED);
|
||||
}
|
||||
|
||||
static uint32_t allwinner_sdhost_process_desc(AwSdHostState *s,
|
||||
hwaddr desc_addr,
|
||||
TransferDescriptor *desc,
|
||||
@@ -312,9 +336,7 @@ static uint32_t allwinner_sdhost_process_desc(AwSdHostState *s,
|
||||
uint32_t num_bytes = max_bytes;
|
||||
uint8_t buf[1024];
|
||||
|
||||
/* Read descriptor */
|
||||
dma_memory_read(&s->dma_as, desc_addr, desc, sizeof(*desc),
|
||||
MEMTXATTRS_UNSPECIFIED);
|
||||
read_descriptor(s, desc_addr, desc);
|
||||
if (desc->size == 0) {
|
||||
desc->size = klass->max_desc_size;
|
||||
} else if (desc->size > klass->max_desc_size) {
|
||||
@@ -356,8 +378,7 @@ static uint32_t allwinner_sdhost_process_desc(AwSdHostState *s,
|
||||
|
||||
/* Clear hold flag and flush descriptor */
|
||||
desc->status &= ~DESC_STATUS_HOLD;
|
||||
dma_memory_write(&s->dma_as, desc_addr, desc, sizeof(*desc),
|
||||
MEMTXATTRS_UNSPECIFIED);
|
||||
write_descriptor(s, desc_addr, desc);
|
||||
|
||||
return num_done;
|
||||
}
|
||||
|
||||
+1
-1
@@ -179,7 +179,7 @@ static void imx_epit_update_compare_timer(IMXEPITState *s)
|
||||
* the compare value. Otherwise it may fire at most once in the
|
||||
* current round.
|
||||
*/
|
||||
bool is_oneshot = (limit >= s->cmp);
|
||||
is_oneshot = (limit < s->cmp);
|
||||
if (counter >= s->cmp) {
|
||||
/* The compare timer fires in the current round. */
|
||||
counter -= s->cmp;
|
||||
|
||||
@@ -166,7 +166,11 @@ int bdrv_amend_options(BlockDriverState *bs_new, QemuOpts *opts,
|
||||
BlockDriverState *check_to_replace_node(BlockDriverState *parent_bs,
|
||||
const char *node_name, Error **errp);
|
||||
|
||||
int bdrv_activate(BlockDriverState *bs, Error **errp);
|
||||
int no_coroutine_fn bdrv_activate(BlockDriverState *bs, Error **errp);
|
||||
|
||||
int coroutine_fn no_co_wrapper
|
||||
bdrv_co_activate(BlockDriverState *bs, Error **errp);
|
||||
|
||||
void bdrv_activate_all(Error **errp);
|
||||
int bdrv_inactivate_all(void);
|
||||
|
||||
@@ -214,7 +218,8 @@ void bdrv_img_create(const char *filename, const char *fmt,
|
||||
bool quiet, Error **errp);
|
||||
|
||||
void bdrv_ref(BlockDriverState *bs);
|
||||
void bdrv_unref(BlockDriverState *bs);
|
||||
void no_coroutine_fn bdrv_unref(BlockDriverState *bs);
|
||||
void coroutine_fn no_co_wrapper bdrv_co_unref(BlockDriverState *bs);
|
||||
void bdrv_unref_child(BlockDriverState *parent, BdrvChild *child);
|
||||
BdrvChild *bdrv_attach_child(BlockDriverState *parent_bs,
|
||||
BlockDriverState *child_bs,
|
||||
|
||||
@@ -183,4 +183,53 @@ void arm_write_secure_board_setup_dummy_smc(ARMCPU *cpu,
|
||||
const struct arm_boot_info *info,
|
||||
hwaddr mvbar_addr);
|
||||
|
||||
typedef enum {
|
||||
FIXUP_NONE = 0, /* do nothing */
|
||||
FIXUP_TERMINATOR, /* end of insns */
|
||||
FIXUP_BOARDID, /* overwrite with board ID number */
|
||||
FIXUP_BOARD_SETUP, /* overwrite with board specific setup code address */
|
||||
FIXUP_ARGPTR_LO, /* overwrite with pointer to kernel args */
|
||||
FIXUP_ARGPTR_HI, /* overwrite with pointer to kernel args (high half) */
|
||||
FIXUP_ENTRYPOINT_LO, /* overwrite with kernel entry point */
|
||||
FIXUP_ENTRYPOINT_HI, /* overwrite with kernel entry point (high half) */
|
||||
FIXUP_GIC_CPU_IF, /* overwrite with GIC CPU interface address */
|
||||
FIXUP_BOOTREG, /* overwrite with boot register address */
|
||||
FIXUP_DSB, /* overwrite with correct DSB insn for cpu */
|
||||
FIXUP_MAX,
|
||||
} FixupType;
|
||||
|
||||
typedef struct ARMInsnFixup {
|
||||
uint32_t insn;
|
||||
FixupType fixup;
|
||||
} ARMInsnFixup;
|
||||
|
||||
/**
|
||||
* arm_write_bootloader - write a bootloader to guest memory
|
||||
* @name: name of the bootloader blob
|
||||
* @as: AddressSpace to write the bootloader
|
||||
* @addr: guest address to write it
|
||||
* @insns: the blob to be loaded
|
||||
* @fixupcontext: context to be used for any fixups in @insns
|
||||
*
|
||||
* Write a bootloader to guest memory at address @addr in the address
|
||||
* space @as. @name is the name to use for the resulting ROM blob, so
|
||||
* it should be unique in the system and reasonably identifiable for debugging.
|
||||
*
|
||||
* @insns must be an array of ARMInsnFixup structs, each of which has
|
||||
* one 32-bit value to be written to the guest memory, and a fixup to be
|
||||
* applied to the value. FIXUP_NONE (do nothing) is value 0, so effectively
|
||||
* the fixup is optional when writing a struct initializer.
|
||||
* The final entry in the array must be { 0, FIXUP_TERMINATOR }.
|
||||
*
|
||||
* All other supported fixup types have the semantics "ignore insn
|
||||
* and instead use the value from the array element @fixupcontext[fixup]".
|
||||
* The caller should therefore provide @fixupcontext as an array of
|
||||
* size FIXUP_MAX whose elements have been initialized for at least
|
||||
* the entries that @insns refers to.
|
||||
*/
|
||||
void arm_write_bootloader(const char *name,
|
||||
AddressSpace *as, hwaddr addr,
|
||||
const ARMInsnFixup *insns,
|
||||
const uint32_t *fixupcontext);
|
||||
|
||||
#endif /* HW_ARM_BOOT_H */
|
||||
|
||||
@@ -42,7 +42,10 @@ blk_co_new_open(const char *filename, const char *reference, QDict *options,
|
||||
|
||||
int blk_get_refcnt(BlockBackend *blk);
|
||||
void blk_ref(BlockBackend *blk);
|
||||
void blk_unref(BlockBackend *blk);
|
||||
|
||||
void no_coroutine_fn blk_unref(BlockBackend *blk);
|
||||
void coroutine_fn no_co_wrapper blk_co_unref(BlockBackend *blk);
|
||||
|
||||
void blk_remove_all_bs(void);
|
||||
BlockBackend *blk_by_name(const char *name);
|
||||
BlockBackend *blk_next(BlockBackend *blk);
|
||||
|
||||
@@ -3213,6 +3213,10 @@ modinfo_files = []
|
||||
block_mods = []
|
||||
softmmu_mods = []
|
||||
foreach d, list : modules
|
||||
if not (d == 'block' ? have_block : have_system)
|
||||
continue
|
||||
endif
|
||||
|
||||
foreach m, module_ss : list
|
||||
if enable_modules and targetos != 'windows'
|
||||
module_ss = module_ss.apply(config_all, strict: false)
|
||||
|
||||
+22
-2
@@ -1143,10 +1143,22 @@ have gone through several iterations as the feature set and complexity
|
||||
of the block layer have grown. Many online guides to QEMU often
|
||||
reference older and deprecated options, which can lead to confusion.
|
||||
|
||||
The recommended modern way to describe disks is to use a combination of
|
||||
The most explicit way to describe disks is to use a combination of
|
||||
``-device`` to specify the hardware device and ``-blockdev`` to
|
||||
describe the backend. The device defines what the guest sees and the
|
||||
backend describes how QEMU handles the data.
|
||||
backend describes how QEMU handles the data. It is the only guaranteed
|
||||
stable interface for describing block devices and as such is
|
||||
recommended for management tools and scripting.
|
||||
|
||||
The ``-drive`` option combines the device and backend into a single
|
||||
command line option which is a more human friendly. There is however no
|
||||
interface stability guarantee although some older board models still
|
||||
need updating to work with the modern blockdev forms.
|
||||
|
||||
Older options like ``-hda`` are essentially macros which expand into
|
||||
``-drive`` options for various drive interfaces. The original forms
|
||||
bake in a lot of assumptions from the days when QEMU was emulating a
|
||||
legacy PC, they are not recommended for modern configurations.
|
||||
|
||||
ERST
|
||||
|
||||
@@ -1639,6 +1651,14 @@ SRST
|
||||
the raw disk image you use is not written back. You can however
|
||||
force the write back by pressing C-a s (see the :ref:`disk images`
|
||||
chapter in the System Emulation Users Guide).
|
||||
|
||||
.. warning::
|
||||
snapshot is incompatible with ``-blockdev`` (instead use qemu-img
|
||||
to manually create snapshot images to attach to your blockdev).
|
||||
If you have mixed ``-blockdev`` and ``-drive`` declarations you
|
||||
can use the 'snapshot' property on your drive declarations
|
||||
instead of this global option.
|
||||
|
||||
ERST
|
||||
|
||||
DEF("fsdev", HAS_ARG, QEMU_OPTION_fsdev,
|
||||
|
||||
@@ -233,7 +233,7 @@ int aarch64_gdb_get_pauth_reg(CPUARMState *env, GByteArray *buf, int reg)
|
||||
ARMMMUIdx mmu_idx = arm_stage1_mmu_idx(env);
|
||||
ARMVAParameters param;
|
||||
|
||||
param = aa64_va_parameters(env, -is_high, mmu_idx, is_data);
|
||||
param = aa64_va_parameters(env, -is_high, mmu_idx, is_data, false);
|
||||
return gdb_get_reg64(buf, pauth_ptr_mask(param));
|
||||
}
|
||||
default:
|
||||
|
||||
+13
-2
@@ -4904,7 +4904,7 @@ static TLBIRange tlbi_aa64_get_range(CPUARMState *env, ARMMMUIdx mmuidx,
|
||||
unsigned int page_size_granule, page_shift, num, scale, exponent;
|
||||
/* Extract one bit to represent the va selector in use. */
|
||||
uint64_t select = sextract64(value, 36, 1);
|
||||
ARMVAParameters param = aa64_va_parameters(env, select, mmuidx, true);
|
||||
ARMVAParameters param = aa64_va_parameters(env, select, mmuidx, true, false);
|
||||
TLBIRange ret = { };
|
||||
ARMGranuleSize gran;
|
||||
|
||||
@@ -11193,7 +11193,8 @@ static ARMGranuleSize sanitize_gran_size(ARMCPU *cpu, ARMGranuleSize gran,
|
||||
}
|
||||
|
||||
ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va,
|
||||
ARMMMUIdx mmu_idx, bool data)
|
||||
ARMMMUIdx mmu_idx, bool data,
|
||||
bool el1_is_aa32)
|
||||
{
|
||||
uint64_t tcr = regime_tcr(env, mmu_idx);
|
||||
bool epd, hpd, tsz_oob, ds, ha, hd;
|
||||
@@ -11289,6 +11290,16 @@ ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va,
|
||||
}
|
||||
}
|
||||
|
||||
if (stage2 && el1_is_aa32) {
|
||||
/*
|
||||
* For AArch32 EL1 the min txsz (and thus max IPA size) requirements
|
||||
* are loosened: a configured IPA of 40 bits is permitted even if
|
||||
* the implemented PA is less than that (and so a 40 bit IPA would
|
||||
* fault for an AArch64 EL1). See R_DTLMN.
|
||||
*/
|
||||
min_tsz = MIN(min_tsz, 24);
|
||||
}
|
||||
|
||||
if (tsz > max_tsz) {
|
||||
tsz = max_tsz;
|
||||
tsz_oob = true;
|
||||
|
||||
+11
-1
@@ -1091,8 +1091,18 @@ typedef struct ARMVAParameters {
|
||||
ARMGranuleSize gran : 2;
|
||||
} ARMVAParameters;
|
||||
|
||||
/**
|
||||
* aa64_va_parameters: Return parameters for an AArch64 virtual address
|
||||
* @env: CPU
|
||||
* @va: virtual address to look up
|
||||
* @mmu_idx: determines translation regime to use
|
||||
* @data: true if this is a data access
|
||||
* @el1_is_aa32: true if we are asking about stage 2 when EL1 is AArch32
|
||||
* (ignored if @mmu_idx is for a stage 1 regime; only affects tsz/tsz_oob)
|
||||
*/
|
||||
ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va,
|
||||
ARMMMUIdx mmu_idx, bool data);
|
||||
ARMMMUIdx mmu_idx, bool data,
|
||||
bool el1_is_aa32);
|
||||
|
||||
int aa64_va_parameter_tbi(uint64_t tcr, ARMMMUIdx mmu_idx);
|
||||
int aa64_va_parameter_tbid(uint64_t tcr, ARMMMUIdx mmu_idx);
|
||||
|
||||
@@ -280,6 +280,8 @@ int kvm_arch_init(MachineState *ms, KVMState *s)
|
||||
}
|
||||
}
|
||||
|
||||
kvm_arm_init_debug(s);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
+4
-14
@@ -74,24 +74,16 @@ GArray *hw_breakpoints, *hw_watchpoints;
|
||||
#define get_hw_bp(i) (&g_array_index(hw_breakpoints, HWBreakpoint, i))
|
||||
#define get_hw_wp(i) (&g_array_index(hw_watchpoints, HWWatchpoint, i))
|
||||
|
||||
/**
|
||||
* kvm_arm_init_debug() - check for guest debug capabilities
|
||||
* @cs: CPUState
|
||||
*
|
||||
* kvm_check_extension returns the number of debug registers we have
|
||||
* or 0 if we have none.
|
||||
*
|
||||
*/
|
||||
static void kvm_arm_init_debug(CPUState *cs)
|
||||
void kvm_arm_init_debug(KVMState *s)
|
||||
{
|
||||
have_guest_debug = kvm_check_extension(cs->kvm_state,
|
||||
have_guest_debug = kvm_check_extension(s,
|
||||
KVM_CAP_SET_GUEST_DEBUG);
|
||||
|
||||
max_hw_wps = kvm_check_extension(cs->kvm_state, KVM_CAP_GUEST_DEBUG_HW_WPS);
|
||||
max_hw_wps = kvm_check_extension(s, KVM_CAP_GUEST_DEBUG_HW_WPS);
|
||||
hw_watchpoints = g_array_sized_new(true, true,
|
||||
sizeof(HWWatchpoint), max_hw_wps);
|
||||
|
||||
max_hw_bps = kvm_check_extension(cs->kvm_state, KVM_CAP_GUEST_DEBUG_HW_BPS);
|
||||
max_hw_bps = kvm_check_extension(s, KVM_CAP_GUEST_DEBUG_HW_BPS);
|
||||
hw_breakpoints = g_array_sized_new(true, true,
|
||||
sizeof(HWBreakpoint), max_hw_bps);
|
||||
return;
|
||||
@@ -920,8 +912,6 @@ int kvm_arch_init_vcpu(CPUState *cs)
|
||||
}
|
||||
cpu->mp_affinity = mpidr & ARM64_AFFINITY_MASK;
|
||||
|
||||
kvm_arm_init_debug(cs);
|
||||
|
||||
/* Check whether user space can specify guest syndrome value */
|
||||
kvm_arm_init_serror_injection(cs);
|
||||
|
||||
|
||||
@@ -18,6 +18,14 @@
|
||||
#define KVM_ARM_VGIC_V2 (1 << 0)
|
||||
#define KVM_ARM_VGIC_V3 (1 << 1)
|
||||
|
||||
/**
|
||||
* kvm_arm_init_debug() - initialize guest debug capabilities
|
||||
* @s: KVMState
|
||||
*
|
||||
* Should be called only once before using guest debug capabilities.
|
||||
*/
|
||||
void kvm_arm_init_debug(KVMState *s);
|
||||
|
||||
/**
|
||||
* kvm_arm_vcpu_init:
|
||||
* @cs: CPUState
|
||||
|
||||
+53
-37
@@ -103,6 +103,37 @@ ARMMMUIdx arm_stage1_mmu_idx(CPUARMState *env)
|
||||
return stage_1_mmu_idx(arm_mmu_idx(env));
|
||||
}
|
||||
|
||||
/*
|
||||
* Return where we should do ptw loads from for a stage 2 walk.
|
||||
* This depends on whether the address we are looking up is a
|
||||
* Secure IPA or a NonSecure IPA, which we know from whether this is
|
||||
* Stage2 or Stage2_S.
|
||||
* If this is the Secure EL1&0 regime we need to check the NSW and SW bits.
|
||||
*/
|
||||
static ARMMMUIdx ptw_idx_for_stage_2(CPUARMState *env, ARMMMUIdx stage2idx)
|
||||
{
|
||||
bool s2walk_secure;
|
||||
|
||||
/*
|
||||
* We're OK to check the current state of the CPU here because
|
||||
* (1) we always invalidate all TLBs when the SCR_EL3.NS bit changes
|
||||
* (2) there's no way to do a lookup that cares about Stage 2 for a
|
||||
* different security state to the current one for AArch64, and AArch32
|
||||
* never has a secure EL2. (AArch32 ATS12NSO[UP][RW] allow EL3 to do
|
||||
* an NS stage 1+2 lookup while the NS bit is 0.)
|
||||
*/
|
||||
if (!arm_is_secure_below_el3(env) || !arm_el_is_aa64(env, 3)) {
|
||||
return ARMMMUIdx_Phys_NS;
|
||||
}
|
||||
if (stage2idx == ARMMMUIdx_Stage2_S) {
|
||||
s2walk_secure = !(env->cp15.vstcr_el2 & VSTCR_SW);
|
||||
} else {
|
||||
s2walk_secure = !(env->cp15.vtcr_el2 & VTCR_NSW);
|
||||
}
|
||||
return s2walk_secure ? ARMMMUIdx_Phys_S : ARMMMUIdx_Phys_NS;
|
||||
|
||||
}
|
||||
|
||||
static bool regime_translation_big_endian(CPUARMState *env, ARMMMUIdx mmu_idx)
|
||||
{
|
||||
return (regime_sctlr(env, mmu_idx) & SCTLR_EE) != 0;
|
||||
@@ -220,7 +251,6 @@ static bool S1_ptw_translate(CPUARMState *env, S1Translate *ptw,
|
||||
ARMMMUIdx mmu_idx = ptw->in_mmu_idx;
|
||||
ARMMMUIdx s2_mmu_idx = ptw->in_ptw_idx;
|
||||
uint8_t pte_attrs;
|
||||
bool pte_secure;
|
||||
|
||||
ptw->out_virt = addr;
|
||||
|
||||
@@ -232,8 +262,8 @@ static bool S1_ptw_translate(CPUARMState *env, S1Translate *ptw,
|
||||
if (regime_is_stage2(s2_mmu_idx)) {
|
||||
S1Translate s2ptw = {
|
||||
.in_mmu_idx = s2_mmu_idx,
|
||||
.in_ptw_idx = is_secure ? ARMMMUIdx_Phys_S : ARMMMUIdx_Phys_NS,
|
||||
.in_secure = is_secure,
|
||||
.in_ptw_idx = ptw_idx_for_stage_2(env, s2_mmu_idx),
|
||||
.in_secure = s2_mmu_idx == ARMMMUIdx_Stage2_S,
|
||||
.in_debug = true,
|
||||
};
|
||||
GetPhysAddrResult s2 = { };
|
||||
@@ -244,12 +274,12 @@ static bool S1_ptw_translate(CPUARMState *env, S1Translate *ptw,
|
||||
}
|
||||
ptw->out_phys = s2.f.phys_addr;
|
||||
pte_attrs = s2.cacheattrs.attrs;
|
||||
pte_secure = s2.f.attrs.secure;
|
||||
ptw->out_secure = s2.f.attrs.secure;
|
||||
} else {
|
||||
/* Regime is physical. */
|
||||
ptw->out_phys = addr;
|
||||
pte_attrs = 0;
|
||||
pte_secure = is_secure;
|
||||
ptw->out_secure = s2_mmu_idx == ARMMMUIdx_Phys_S;
|
||||
}
|
||||
ptw->out_host = NULL;
|
||||
ptw->out_rw = false;
|
||||
@@ -270,7 +300,7 @@ static bool S1_ptw_translate(CPUARMState *env, S1Translate *ptw,
|
||||
ptw->out_phys = full->phys_addr | (addr & ~TARGET_PAGE_MASK);
|
||||
ptw->out_rw = full->prot & PAGE_WRITE;
|
||||
pte_attrs = full->pte_attrs;
|
||||
pte_secure = full->attrs.secure;
|
||||
ptw->out_secure = full->attrs.secure;
|
||||
#else
|
||||
g_assert_not_reached();
|
||||
#endif
|
||||
@@ -293,11 +323,6 @@ static bool S1_ptw_translate(CPUARMState *env, S1Translate *ptw,
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if page table walk is to secure or non-secure PA space. */
|
||||
ptw->out_secure = (is_secure
|
||||
&& !(pte_secure
|
||||
? env->cp15.vstcr_el2 & VSTCR_SW
|
||||
: env->cp15.vtcr_el2 & VTCR_NSW));
|
||||
ptw->out_be = regime_translation_big_endian(env, mmu_idx);
|
||||
return true;
|
||||
|
||||
@@ -1097,17 +1122,6 @@ static int check_s2_mmu_setup(ARMCPU *cpu, bool is_aa64, uint64_t tcr,
|
||||
|
||||
sl0 = extract32(tcr, 6, 2);
|
||||
if (is_aa64) {
|
||||
/*
|
||||
* AArch64.S2InvalidTxSZ: While we checked tsz_oob near the top of
|
||||
* get_phys_addr_lpae, that used aa64_va_parameters which apply
|
||||
* to aarch64. If Stage1 is aarch32, the min_txsz is larger.
|
||||
* See AArch64.S2MinTxSZ, where min_tsz is 24, translated to
|
||||
* inputsize is 64 - 24 = 40.
|
||||
*/
|
||||
if (iasize < 40 && !arm_el_is_aa64(&cpu->env, 1)) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/*
|
||||
* AArch64.S2InvalidSL: Interpretation of SL depends on the page size,
|
||||
* so interleave AArch64.S2StartLevel.
|
||||
@@ -1247,7 +1261,8 @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
|
||||
int ps;
|
||||
|
||||
param = aa64_va_parameters(env, address, mmu_idx,
|
||||
access_type != MMU_INST_FETCH);
|
||||
access_type != MMU_INST_FETCH,
|
||||
!arm_el_is_aa64(env, 1));
|
||||
level = 0;
|
||||
|
||||
/*
|
||||
@@ -2713,7 +2728,7 @@ static bool get_phys_addr_twostage(CPUARMState *env, S1Translate *ptw,
|
||||
hwaddr ipa;
|
||||
int s1_prot, s1_lgpgsz;
|
||||
bool is_secure = ptw->in_secure;
|
||||
bool ret, ipa_secure, s2walk_secure;
|
||||
bool ret, ipa_secure;
|
||||
ARMCacheAttrs cacheattrs1;
|
||||
bool is_el0;
|
||||
uint64_t hcr;
|
||||
@@ -2727,20 +2742,11 @@ static bool get_phys_addr_twostage(CPUARMState *env, S1Translate *ptw,
|
||||
|
||||
ipa = result->f.phys_addr;
|
||||
ipa_secure = result->f.attrs.secure;
|
||||
if (is_secure) {
|
||||
/* Select TCR based on the NS bit from the S1 walk. */
|
||||
s2walk_secure = !(ipa_secure
|
||||
? env->cp15.vstcr_el2 & VSTCR_SW
|
||||
: env->cp15.vtcr_el2 & VTCR_NSW);
|
||||
} else {
|
||||
assert(!ipa_secure);
|
||||
s2walk_secure = false;
|
||||
}
|
||||
|
||||
is_el0 = ptw->in_mmu_idx == ARMMMUIdx_Stage1_E0;
|
||||
ptw->in_mmu_idx = s2walk_secure ? ARMMMUIdx_Stage2_S : ARMMMUIdx_Stage2;
|
||||
ptw->in_ptw_idx = s2walk_secure ? ARMMMUIdx_Phys_S : ARMMMUIdx_Phys_NS;
|
||||
ptw->in_secure = s2walk_secure;
|
||||
ptw->in_mmu_idx = ipa_secure ? ARMMMUIdx_Stage2_S : ARMMMUIdx_Stage2;
|
||||
ptw->in_secure = ipa_secure;
|
||||
ptw->in_ptw_idx = ptw_idx_for_stage_2(env, ptw->in_mmu_idx);
|
||||
|
||||
/*
|
||||
* S1 is done, now do S2 translation.
|
||||
@@ -2848,6 +2854,16 @@ static bool get_phys_addr_with_struct(CPUARMState *env, S1Translate *ptw,
|
||||
ptw->in_ptw_idx = is_secure ? ARMMMUIdx_Stage2_S : ARMMMUIdx_Stage2;
|
||||
break;
|
||||
|
||||
case ARMMMUIdx_Stage2:
|
||||
case ARMMMUIdx_Stage2_S:
|
||||
/*
|
||||
* Second stage lookup uses physical for ptw; whether this is S or
|
||||
* NS may depend on the SW/NSW bits if this is a stage 2 lookup for
|
||||
* the Secure EL2&0 regime.
|
||||
*/
|
||||
ptw->in_ptw_idx = ptw_idx_for_stage_2(env, mmu_idx);
|
||||
break;
|
||||
|
||||
case ARMMMUIdx_E10_0:
|
||||
s1_mmu_idx = ARMMMUIdx_Stage1_E0;
|
||||
goto do_twostage;
|
||||
@@ -2871,7 +2887,7 @@ static bool get_phys_addr_with_struct(CPUARMState *env, S1Translate *ptw,
|
||||
/* fall through */
|
||||
|
||||
default:
|
||||
/* Single stage and second stage uses physical for ptw. */
|
||||
/* Single stage uses physical for ptw. */
|
||||
ptw->in_ptw_idx = is_secure ? ARMMMUIdx_Phys_S : ARMMMUIdx_Phys_NS;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -293,7 +293,7 @@ static uint64_t pauth_addpac(CPUARMState *env, uint64_t ptr, uint64_t modifier,
|
||||
ARMPACKey *key, bool data)
|
||||
{
|
||||
ARMMMUIdx mmu_idx = arm_stage1_mmu_idx(env);
|
||||
ARMVAParameters param = aa64_va_parameters(env, ptr, mmu_idx, data);
|
||||
ARMVAParameters param = aa64_va_parameters(env, ptr, mmu_idx, data, false);
|
||||
uint64_t pac, ext_ptr, ext, test;
|
||||
int bot_bit, top_bit;
|
||||
|
||||
@@ -355,7 +355,7 @@ static uint64_t pauth_auth(CPUARMState *env, uint64_t ptr, uint64_t modifier,
|
||||
ARMPACKey *key, bool data, int keynumber)
|
||||
{
|
||||
ARMMMUIdx mmu_idx = arm_stage1_mmu_idx(env);
|
||||
ARMVAParameters param = aa64_va_parameters(env, ptr, mmu_idx, data);
|
||||
ARMVAParameters param = aa64_va_parameters(env, ptr, mmu_idx, data, false);
|
||||
int bot_bit, top_bit;
|
||||
uint64_t pac, orig_ptr, test;
|
||||
|
||||
@@ -379,7 +379,7 @@ static uint64_t pauth_auth(CPUARMState *env, uint64_t ptr, uint64_t modifier,
|
||||
static uint64_t pauth_strip(CPUARMState *env, uint64_t ptr, bool data)
|
||||
{
|
||||
ARMMMUIdx mmu_idx = arm_stage1_mmu_idx(env);
|
||||
ARMVAParameters param = aa64_va_parameters(env, ptr, mmu_idx, data);
|
||||
ARMVAParameters param = aa64_va_parameters(env, ptr, mmu_idx, data, false);
|
||||
|
||||
return pauth_original_ptr(ptr, param);
|
||||
}
|
||||
|
||||
@@ -2816,7 +2816,7 @@ static bool msr_banked_access_decode(DisasContext *s, int r, int sysm, int rn,
|
||||
if (arm_dc_feature(s, ARM_FEATURE_AARCH64) &&
|
||||
dc_isar_feature(aa64_sel2, s)) {
|
||||
/* Target EL is EL<3 minus SCR_EL3.EEL2> */
|
||||
tcg_el = load_cpu_field(cp15.scr_el3);
|
||||
tcg_el = load_cpu_field_low32(cp15.scr_el3);
|
||||
tcg_gen_sextract_i32(tcg_el, tcg_el, ctz32(SCR_EEL2), 1);
|
||||
tcg_gen_addi_i32(tcg_el, tcg_el, 3);
|
||||
} else {
|
||||
@@ -6396,7 +6396,7 @@ static bool trans_ERET(DisasContext *s, arg_ERET *a)
|
||||
}
|
||||
if (s->current_el == 2) {
|
||||
/* ERET from Hyp uses ELR_Hyp, not LR */
|
||||
tmp = load_cpu_field(elr_el[2]);
|
||||
tmp = load_cpu_field_low32(elr_el[2]);
|
||||
} else {
|
||||
tmp = load_reg(s, 14);
|
||||
}
|
||||
|
||||
@@ -61,6 +61,13 @@ static inline TCGv_i32 load_cpu_offset(int offset)
|
||||
|
||||
#define load_cpu_field(name) load_cpu_offset(offsetof(CPUARMState, name))
|
||||
|
||||
/* Load from the low half of a 64-bit field to a TCGv_i32 */
|
||||
#define load_cpu_field_low32(name) \
|
||||
({ \
|
||||
QEMU_BUILD_BUG_ON(sizeof_field(CPUARMState, name) != 8); \
|
||||
load_cpu_offset(offsetoflow32(CPUARMState, name)); \
|
||||
})
|
||||
|
||||
void store_cpu_offset(TCGv_i32 var, int offset, int size);
|
||||
|
||||
#define store_cpu_field(var, name) \
|
||||
|
||||
+2
-2
@@ -5718,8 +5718,8 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
|
||||
} else {
|
||||
*eax &= env->features[FEAT_SGX_12_1_EAX];
|
||||
*ebx &= 0; /* ebx reserve */
|
||||
*ecx &= env->features[FEAT_XSAVE_XSS_LO];
|
||||
*edx &= env->features[FEAT_XSAVE_XSS_HI];
|
||||
*ecx &= env->features[FEAT_XSAVE_XCR0_LO];
|
||||
*edx &= env->features[FEAT_XSAVE_XCR0_HI];
|
||||
|
||||
/* FP and SSE are always allowed regardless of XSAVE/XCR0. */
|
||||
*ecx |= XSTATE_FP_MASK | XSTATE_SSE_MASK;
|
||||
|
||||
@@ -2058,7 +2058,7 @@ static bool trans_VEXPANDQM(DisasContext *ctx, arg_VX_tb *a)
|
||||
static bool do_vextractm(DisasContext *ctx, arg_VX_tb *a, unsigned vece)
|
||||
{
|
||||
const uint64_t elem_width = 8 << vece, elem_count_half = 8 >> vece,
|
||||
mask = dup_const(vece, 1 << (elem_width - 1));
|
||||
mask = dup_const(vece, 1ULL << (elem_width - 1));
|
||||
uint64_t i, j;
|
||||
TCGv_i64 lo, hi, t0, t1;
|
||||
|
||||
|
||||
+9
-2
@@ -3797,6 +3797,11 @@ static inline RISCVException riscv_csrrw_check(CPURISCVState *env,
|
||||
return RISCV_EXCP_ILLEGAL_INST;
|
||||
}
|
||||
|
||||
/* ensure CSR is implemented by checking predicate */
|
||||
if (!csr_ops[csrno].predicate) {
|
||||
return RISCV_EXCP_ILLEGAL_INST;
|
||||
}
|
||||
|
||||
/* privileged spec version check */
|
||||
if (env->priv_ver < csr_min_priv) {
|
||||
return RISCV_EXCP_ILLEGAL_INST;
|
||||
@@ -3814,7 +3819,6 @@ static inline RISCVException riscv_csrrw_check(CPURISCVState *env,
|
||||
* illegal instruction exception should be triggered instead of virtual
|
||||
* instruction exception. Hence this comes after the read / write check.
|
||||
*/
|
||||
g_assert(csr_ops[csrno].predicate != NULL);
|
||||
RISCVException ret = csr_ops[csrno].predicate(env, csrno);
|
||||
if (ret != RISCV_EXCP_NONE) {
|
||||
return ret;
|
||||
@@ -3991,7 +3995,10 @@ RISCVException riscv_csrrw_debug(CPURISCVState *env, int csrno,
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Control and Status Register function table */
|
||||
/*
|
||||
* Control and Status Register function table
|
||||
* riscv_csr_operations::predicate() must be provided for an implemented CSR
|
||||
*/
|
||||
riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
|
||||
/* User Floating-Point CSRs */
|
||||
[CSR_FFLAGS] = { "fflags", fs, read_fflags, write_fflags },
|
||||
|
||||
@@ -77,6 +77,9 @@ static bool trans_sret(DisasContext *ctx, arg_sret *a)
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
if (has_ext(ctx, RVS)) {
|
||||
decode_save_opc(ctx);
|
||||
if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
|
||||
gen_io_start();
|
||||
}
|
||||
gen_helper_sret(cpu_pc, cpu_env);
|
||||
exit_tb(ctx); /* no chaining */
|
||||
ctx->base.is_jmp = DISAS_NORETURN;
|
||||
@@ -93,6 +96,9 @@ static bool trans_mret(DisasContext *ctx, arg_mret *a)
|
||||
{
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
decode_save_opc(ctx);
|
||||
if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
|
||||
gen_io_start();
|
||||
}
|
||||
gen_helper_mret(cpu_pc, cpu_env);
|
||||
exit_tb(ctx); /* no chaining */
|
||||
ctx->base.is_jmp = DISAS_NORETURN;
|
||||
|
||||
@@ -606,7 +606,7 @@
|
||||
F(0xed04, LDEB, RXE, Z, 0, m2_32u, new, f1, ldeb, 0, IF_BFP)
|
||||
F(0xed05, LXDB, RXE, Z, 0, m2_64, new_x, x1, lxdb, 0, IF_BFP)
|
||||
F(0xed06, LXEB, RXE, Z, 0, m2_32u, new_x, x1, lxeb, 0, IF_BFP)
|
||||
F(0xb324, LDER, RXE, Z, 0, e2, new, f1, lde, 0, IF_AFP1)
|
||||
F(0xb324, LDER, RRE, Z, 0, e2, new, f1, lde, 0, IF_AFP1)
|
||||
F(0xed24, LDE, RXE, Z, 0, m2_32u, new, f1, lde, 0, IF_AFP1)
|
||||
/* LOAD ROUNDED */
|
||||
F(0xb344, LEDBR, RRF_e, Z, 0, f2, new, e1, ledb, 0, IF_BFP)
|
||||
|
||||
@@ -1534,18 +1534,51 @@ static DisasJumpType op_bal(DisasContext *s, DisasOps *o)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Disassemble the target of a branch. The results are returned in a form
|
||||
* suitable for passing into help_branch():
|
||||
*
|
||||
* - bool IS_IMM reflects whether the target is fixed or computed. Non-EXECUTEd
|
||||
* branches, whose DisasContext *S contains the relative immediate field RI,
|
||||
* are considered fixed. All the other branches are considered computed.
|
||||
* - int IMM is the value of RI.
|
||||
* - TCGv_i64 CDEST is the address of the computed target.
|
||||
*/
|
||||
#define disas_jdest(s, ri, is_imm, imm, cdest) do { \
|
||||
if (have_field(s, ri)) { \
|
||||
if (unlikely(s->ex_value)) { \
|
||||
cdest = tcg_temp_new_i64(); \
|
||||
tcg_gen_ld_i64(cdest, cpu_env, offsetof(CPUS390XState, ex_target));\
|
||||
tcg_gen_addi_i64(cdest, cdest, (int64_t)get_field(s, ri) * 2); \
|
||||
is_imm = false; \
|
||||
} else { \
|
||||
is_imm = true; \
|
||||
} \
|
||||
} else { \
|
||||
is_imm = false; \
|
||||
} \
|
||||
imm = is_imm ? get_field(s, ri) : 0; \
|
||||
} while (false)
|
||||
|
||||
static DisasJumpType op_basi(DisasContext *s, DisasOps *o)
|
||||
{
|
||||
DisasCompare c;
|
||||
bool is_imm;
|
||||
int imm;
|
||||
|
||||
pc_to_link_info(o->out, s, s->pc_tmp);
|
||||
return help_goto_direct(s, s->base.pc_next + (int64_t)get_field(s, i2) * 2);
|
||||
|
||||
disas_jdest(s, i2, is_imm, imm, o->in2);
|
||||
disas_jcc(s, &c, 0xf);
|
||||
return help_branch(s, &c, is_imm, imm, o->in2);
|
||||
}
|
||||
|
||||
static DisasJumpType op_bc(DisasContext *s, DisasOps *o)
|
||||
{
|
||||
int m1 = get_field(s, m1);
|
||||
bool is_imm = have_field(s, i2);
|
||||
int imm = is_imm ? get_field(s, i2) : 0;
|
||||
DisasCompare c;
|
||||
bool is_imm;
|
||||
int imm;
|
||||
|
||||
/* BCR with R2 = 0 causes no branching */
|
||||
if (have_field(s, r2) && get_field(s, r2) == 0) {
|
||||
@@ -1562,6 +1595,7 @@ static DisasJumpType op_bc(DisasContext *s, DisasOps *o)
|
||||
return DISAS_NEXT;
|
||||
}
|
||||
|
||||
disas_jdest(s, i2, is_imm, imm, o->in2);
|
||||
disas_jcc(s, &c, m1);
|
||||
return help_branch(s, &c, is_imm, imm, o->in2);
|
||||
}
|
||||
@@ -1569,10 +1603,10 @@ static DisasJumpType op_bc(DisasContext *s, DisasOps *o)
|
||||
static DisasJumpType op_bct32(DisasContext *s, DisasOps *o)
|
||||
{
|
||||
int r1 = get_field(s, r1);
|
||||
bool is_imm = have_field(s, i2);
|
||||
int imm = is_imm ? get_field(s, i2) : 0;
|
||||
DisasCompare c;
|
||||
bool is_imm;
|
||||
TCGv_i64 t;
|
||||
int imm;
|
||||
|
||||
c.cond = TCG_COND_NE;
|
||||
c.is_64 = false;
|
||||
@@ -1584,6 +1618,7 @@ static DisasJumpType op_bct32(DisasContext *s, DisasOps *o)
|
||||
c.u.s32.b = tcg_constant_i32(0);
|
||||
tcg_gen_extrl_i64_i32(c.u.s32.a, t);
|
||||
|
||||
disas_jdest(s, i2, is_imm, imm, o->in2);
|
||||
return help_branch(s, &c, is_imm, imm, o->in2);
|
||||
}
|
||||
|
||||
@@ -1611,9 +1646,9 @@ static DisasJumpType op_bcth(DisasContext *s, DisasOps *o)
|
||||
static DisasJumpType op_bct64(DisasContext *s, DisasOps *o)
|
||||
{
|
||||
int r1 = get_field(s, r1);
|
||||
bool is_imm = have_field(s, i2);
|
||||
int imm = is_imm ? get_field(s, i2) : 0;
|
||||
DisasCompare c;
|
||||
bool is_imm;
|
||||
int imm;
|
||||
|
||||
c.cond = TCG_COND_NE;
|
||||
c.is_64 = true;
|
||||
@@ -1622,6 +1657,7 @@ static DisasJumpType op_bct64(DisasContext *s, DisasOps *o)
|
||||
c.u.s64.a = regs[r1];
|
||||
c.u.s64.b = tcg_constant_i64(0);
|
||||
|
||||
disas_jdest(s, i2, is_imm, imm, o->in2);
|
||||
return help_branch(s, &c, is_imm, imm, o->in2);
|
||||
}
|
||||
|
||||
@@ -1629,10 +1665,10 @@ static DisasJumpType op_bx32(DisasContext *s, DisasOps *o)
|
||||
{
|
||||
int r1 = get_field(s, r1);
|
||||
int r3 = get_field(s, r3);
|
||||
bool is_imm = have_field(s, i2);
|
||||
int imm = is_imm ? get_field(s, i2) : 0;
|
||||
DisasCompare c;
|
||||
bool is_imm;
|
||||
TCGv_i64 t;
|
||||
int imm;
|
||||
|
||||
c.cond = (s->insn->data ? TCG_COND_LE : TCG_COND_GT);
|
||||
c.is_64 = false;
|
||||
@@ -1645,6 +1681,7 @@ static DisasJumpType op_bx32(DisasContext *s, DisasOps *o)
|
||||
tcg_gen_extrl_i64_i32(c.u.s32.b, regs[r3 | 1]);
|
||||
store_reg32_i64(r1, t);
|
||||
|
||||
disas_jdest(s, i2, is_imm, imm, o->in2);
|
||||
return help_branch(s, &c, is_imm, imm, o->in2);
|
||||
}
|
||||
|
||||
@@ -1652,9 +1689,9 @@ static DisasJumpType op_bx64(DisasContext *s, DisasOps *o)
|
||||
{
|
||||
int r1 = get_field(s, r1);
|
||||
int r3 = get_field(s, r3);
|
||||
bool is_imm = have_field(s, i2);
|
||||
int imm = is_imm ? get_field(s, i2) : 0;
|
||||
DisasCompare c;
|
||||
bool is_imm;
|
||||
int imm;
|
||||
|
||||
c.cond = (s->insn->data ? TCG_COND_LE : TCG_COND_GT);
|
||||
c.is_64 = true;
|
||||
@@ -1668,6 +1705,7 @@ static DisasJumpType op_bx64(DisasContext *s, DisasOps *o)
|
||||
tcg_gen_add_i64(regs[r1], regs[r1], regs[r3]);
|
||||
c.u.s64.a = regs[r1];
|
||||
|
||||
disas_jdest(s, i2, is_imm, imm, o->in2);
|
||||
return help_branch(s, &c, is_imm, imm, o->in2);
|
||||
}
|
||||
|
||||
@@ -1685,10 +1723,9 @@ static DisasJumpType op_cj(DisasContext *s, DisasOps *o)
|
||||
c.u.s64.a = o->in1;
|
||||
c.u.s64.b = o->in2;
|
||||
|
||||
is_imm = have_field(s, i4);
|
||||
if (is_imm) {
|
||||
imm = get_field(s, i4);
|
||||
} else {
|
||||
o->out = NULL;
|
||||
disas_jdest(s, i4, is_imm, imm, o->out);
|
||||
if (!is_imm && !o->out) {
|
||||
imm = 0;
|
||||
o->out = get_address(s, 0, get_field(s, b4),
|
||||
get_field(s, d4));
|
||||
@@ -5774,15 +5811,13 @@ static void in2_a2(DisasContext *s, DisasOps *o)
|
||||
|
||||
static TCGv gen_ri2(DisasContext *s)
|
||||
{
|
||||
int64_t delta = (int64_t)get_field(s, i2) * 2;
|
||||
TCGv ri2;
|
||||
TCGv ri2 = NULL;
|
||||
bool is_imm;
|
||||
int imm;
|
||||
|
||||
if (unlikely(s->ex_value)) {
|
||||
ri2 = tcg_temp_new_i64();
|
||||
tcg_gen_ld_i64(ri2, cpu_env, offsetof(CPUS390XState, ex_target));
|
||||
tcg_gen_addi_i64(ri2, ri2, delta);
|
||||
} else {
|
||||
ri2 = tcg_constant_i64(s->base.pc_next + delta);
|
||||
disas_jdest(s, i2, is_imm, imm, ri2);
|
||||
if (is_imm) {
|
||||
ri2 = tcg_constant_i64(s->base.pc_next + imm * 2);
|
||||
}
|
||||
|
||||
return ri2;
|
||||
|
||||
@@ -1083,7 +1083,7 @@ static void tcg_out_addi_ptr(TCGContext *s, TCGReg rd, TCGReg rs,
|
||||
{
|
||||
/* This function is only used for passing structs by reference. */
|
||||
tcg_debug_assert(imm == (int32_t)imm);
|
||||
tcg_out_modrm_offset(s, OPC_LEA, rd, rs, imm);
|
||||
tcg_out_modrm_offset(s, OPC_LEA | P_REXW, rd, rs, imm);
|
||||
}
|
||||
|
||||
static inline void tcg_out_pushi(TCGContext *s, tcg_target_long val)
|
||||
|
||||
+2
-2
@@ -311,7 +311,7 @@ static bool png_save(int fd, pixman_image_t *image, Error **errp)
|
||||
png_struct *png_ptr;
|
||||
png_info *info_ptr;
|
||||
g_autoptr(pixman_image_t) linebuf =
|
||||
qemu_pixman_linebuf_create(PIXMAN_a8r8g8b8, width);
|
||||
qemu_pixman_linebuf_create(PIXMAN_BE_r8g8b8, width);
|
||||
uint8_t *buf = (uint8_t *)pixman_image_get_data(linebuf);
|
||||
FILE *f = fdopen(fd, "wb");
|
||||
int y;
|
||||
@@ -341,7 +341,7 @@ static bool png_save(int fd, pixman_image_t *image, Error **errp)
|
||||
png_init_io(png_ptr, f);
|
||||
|
||||
png_set_IHDR(png_ptr, info_ptr, width, height, 8,
|
||||
PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE,
|
||||
PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE,
|
||||
PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
|
||||
|
||||
png_write_info(png_ptr, info_ptr);
|
||||
|
||||
@@ -3751,7 +3751,7 @@ static int vnc_display_get_address(const char *addrstr,
|
||||
|
||||
addr->type = SOCKET_ADDRESS_TYPE_INET;
|
||||
inet = &addr->u.inet;
|
||||
if (addrstr[0] == '[' && addrstr[hostlen - 1] == ']') {
|
||||
if (hostlen && addrstr[0] == '[' && addrstr[hostlen - 1] == ']') {
|
||||
inet->host = g_strndup(addrstr + 1, hostlen - 2);
|
||||
} else {
|
||||
inet->host = g_strndup(addrstr, hostlen);
|
||||
|
||||
@@ -164,7 +164,21 @@ int aio_bh_poll(AioContext *ctx)
|
||||
|
||||
/* Synchronizes with QSLIST_INSERT_HEAD_ATOMIC in aio_bh_enqueue(). */
|
||||
QSLIST_MOVE_ATOMIC(&slice.bh_list, &ctx->bh_list);
|
||||
|
||||
/*
|
||||
* GCC13 [-Werror=dangling-pointer=] complains that the local variable
|
||||
* 'slice' is being stored in the global 'ctx->bh_slice_list' but the
|
||||
* list is emptied before this function returns.
|
||||
*/
|
||||
#if !defined(__clang__)
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wpragmas"
|
||||
#pragma GCC diagnostic ignored "-Wdangling-pointer="
|
||||
#endif
|
||||
QSIMPLEQ_INSERT_TAIL(&ctx->bh_slice_list, &slice, next);
|
||||
#if !defined(__clang__)
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
while ((s = QSIMPLEQ_FIRST(&ctx->bh_slice_list))) {
|
||||
QEMUBH *bh;
|
||||
|
||||
Reference in New Issue
Block a user