* Don't silently truncate extremely long words in the command line
* dtc configure fixes * MemoryRegionCache second try * Deprecated option removal * add support for Hyper-V reenlightenment MSRs -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.22 (GNU/Linux) iQEcBAABAgAGBQJa9Y2qAAoJEL/70l94x66Df8EIAI4pi+zf1mTlH0Koi+oqOg+d geBC6N9IA+n1p90XERnPbuiT19NjON2R1Z907SbzDkijxdNRoYUoQf7Z+ZBTENjn dYsVvgLYzajGLWWtJetPPaNFAqeF2z8B3lbVQnGVLzH5pQQ2NS1NJsvXQA2LslLs 2ll1CJ2EEBhayoBSbHK+0cY85f+DUgK/T1imIV2T/rwcef9Rw218nvPfGhPBSoL6 tI2xIOxz8bBOvZNg2wdxpaoPuDipBFu6koVVbaGSgXORg8k5CEcKNxInztufdELW KZK5ORa3T0uqu5T/GGPAfm/NbYVQ4aTB5mddshsXtKbBhnbSfRYvpVsR4kQB/Hc= =oC1r -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/bonzini/tags/for-upstream' into staging * Don't silently truncate extremely long words in the command line * dtc configure fixes * MemoryRegionCache second try * Deprecated option removal * add support for Hyper-V reenlightenment MSRs # gpg: Signature made Fri 11 May 2018 13:33:46 BST # gpg: using RSA key BFFBD25F78C7AE83 # gpg: Good signature from "Paolo Bonzini <bonzini@gnu.org>" # gpg: aka "Paolo Bonzini <pbonzini@redhat.com>" # Primary key fingerprint: 46F5 9FBD 57D6 12E7 BFD4 E2F7 7E15 100C CD36 69B1 # Subkey fingerprint: F133 3857 4B66 2389 866C 7682 BFFB D25F 78C7 AE83 * remotes/bonzini/tags/for-upstream: (29 commits) rename included C files to foo.inc.c, remove osdep.h pc-dimm: fix error messages if no slots were defined build: Silence dtc directory creation shippable: Remove Debian 8 libfdt kludge configure: Display if libfdt is from system or git configure: Really use local libfdt if the system one is too old i386/kvm: add support for Hyper-V reenlightenment MSRs qemu-doc: provide details of supported build platforms qemu-options: Remove deprecated -no-kvm-irqchip qemu-options: Remove deprecated -no-kvm-pit-reinjection qemu-options: Bail out on unsupported options instead of silently ignoring them qemu-options: Remove remainders of the -tdf option qemu-options: Mark -virtioconsole as deprecated target/i386: sev: fix memory leaks opts: don't silently truncate long option values opts: don't silently truncate long parameter keys accel: use g_strsplit for parsing accelerator names update-linux-headers: drop hyperv.h qemu-thread: always keep the posix wrapper layer exec: reintroduce MemoryRegion caching ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
9ba1733a76
@ -35,13 +35,5 @@ build:
|
||||
options: "-e HOME=/root"
|
||||
ci:
|
||||
- unset CC
|
||||
# some targets require newer up to date packages, for example TARGET_LIST matching
|
||||
# aarch64*-softmmu|arm*-softmmu|ppc*-softmmu|microblaze*-softmmu|mips64el-softmmu)
|
||||
# see the configure script:
|
||||
# error_exit "DTC (libfdt) version >= 1.4.2 not present. Your options:"
|
||||
# " (1) Preferred: Install the DTC (libfdt) devel package"
|
||||
# " (2) Fetch the DTC submodule, using:"
|
||||
# " git submodule update --init dtc"
|
||||
- dpkg --compare-versions `dpkg-query --showformat='${Version}' --show libfdt-dev` ge 1.4.2 || git submodule update --init dtc
|
||||
- ./configure ${QEMU_CONFIGURE_OPTS} --target-list=${TARGET_LIST}
|
||||
- make -j$(($(getconf _NPROCESSORS_ONLN) + 1))
|
||||
|
2
Makefile
2
Makefile
@ -485,7 +485,7 @@ subdir-dtc: .git-submodule-status dtc/libfdt dtc/tests
|
||||
$(call quiet-command,$(MAKE) $(DTC_MAKE_ARGS) CPPFLAGS="$(DTC_CPPFLAGS)" CFLAGS="$(DTC_CFLAGS)" LDFLAGS="$(LDFLAGS)" ARFLAGS="$(ARFLAGS)" CC="$(CC)" AR="$(AR)" LD="$(LD)" $(SUBDIR_MAKEFLAGS) libfdt/libfdt.a,)
|
||||
|
||||
dtc/%: .git-submodule-status
|
||||
mkdir -p $@
|
||||
@mkdir -p $@
|
||||
|
||||
# Overriding CFLAGS causes us to lose defines added in the sub-makefile.
|
||||
# Not overriding CFLAGS leads to mis-matches between compilation modes.
|
||||
|
@ -70,8 +70,8 @@ static int accel_init_machine(AccelClass *acc, MachineState *ms)
|
||||
|
||||
void configure_accelerator(MachineState *ms)
|
||||
{
|
||||
const char *accel, *p;
|
||||
char buf[10];
|
||||
const char *accel;
|
||||
char **accel_list, **tmp;
|
||||
int ret;
|
||||
bool accel_initialised = false;
|
||||
bool init_failed = false;
|
||||
@ -83,13 +83,10 @@ void configure_accelerator(MachineState *ms)
|
||||
accel = "tcg";
|
||||
}
|
||||
|
||||
p = accel;
|
||||
while (!accel_initialised && *p != '\0') {
|
||||
if (*p == ':') {
|
||||
p++;
|
||||
}
|
||||
p = get_opt_name(buf, sizeof(buf), p, ':');
|
||||
acc = accel_find(buf);
|
||||
accel_list = g_strsplit(accel, ":", 0);
|
||||
|
||||
for (tmp = accel_list; !accel_initialised && tmp && *tmp; tmp++) {
|
||||
acc = accel_find(*tmp);
|
||||
if (!acc) {
|
||||
continue;
|
||||
}
|
||||
@ -107,6 +104,7 @@ void configure_accelerator(MachineState *ms)
|
||||
accel_initialised = true;
|
||||
}
|
||||
}
|
||||
g_strfreev(accel_list);
|
||||
|
||||
if (!accel_initialised) {
|
||||
if (!init_failed) {
|
||||
|
@ -369,24 +369,6 @@ host_memory_backend_can_be_deleted(UserCreatable *uc)
|
||||
}
|
||||
}
|
||||
|
||||
static char *get_id(Object *o, Error **errp)
|
||||
{
|
||||
HostMemoryBackend *backend = MEMORY_BACKEND(o);
|
||||
|
||||
return g_strdup(backend->id);
|
||||
}
|
||||
|
||||
static void set_id(Object *o, const char *str, Error **errp)
|
||||
{
|
||||
HostMemoryBackend *backend = MEMORY_BACKEND(o);
|
||||
|
||||
if (backend->id) {
|
||||
error_setg(errp, "cannot change property value");
|
||||
return;
|
||||
}
|
||||
backend->id = g_strdup(str);
|
||||
}
|
||||
|
||||
static bool host_memory_backend_get_share(Object *o, Error **errp)
|
||||
{
|
||||
HostMemoryBackend *backend = MEMORY_BACKEND(o);
|
||||
@ -434,18 +416,11 @@ host_memory_backend_class_init(ObjectClass *oc, void *data)
|
||||
&HostMemPolicy_lookup,
|
||||
host_memory_backend_get_policy,
|
||||
host_memory_backend_set_policy, &error_abort);
|
||||
object_class_property_add_str(oc, "id", get_id, set_id, &error_abort);
|
||||
object_class_property_add_bool(oc, "share",
|
||||
host_memory_backend_get_share, host_memory_backend_set_share,
|
||||
&error_abort);
|
||||
}
|
||||
|
||||
static void host_memory_backend_finalize(Object *o)
|
||||
{
|
||||
HostMemoryBackend *backend = MEMORY_BACKEND(o);
|
||||
g_free(backend->id);
|
||||
}
|
||||
|
||||
static const TypeInfo host_memory_backend_info = {
|
||||
.name = TYPE_MEMORY_BACKEND,
|
||||
.parent = TYPE_OBJECT,
|
||||
@ -454,7 +429,6 @@ static const TypeInfo host_memory_backend_info = {
|
||||
.class_init = host_memory_backend_class_init,
|
||||
.instance_size = sizeof(HostMemoryBackend),
|
||||
.instance_init = host_memory_backend_init,
|
||||
.instance_finalize = host_memory_backend_finalize,
|
||||
.interfaces = (InterfaceInfo[]) {
|
||||
{ TYPE_USER_CREATABLE },
|
||||
{ }
|
||||
|
17
configure
vendored
17
configure
vendored
@ -964,6 +964,8 @@ for opt do
|
||||
;;
|
||||
--firmwarepath=*) firmwarepath="$optarg"
|
||||
;;
|
||||
--host=*|--build=*|\
|
||||
--disable-dependency-tracking|\
|
||||
--sbindir=*|--sharedstatedir=*|\
|
||||
--oldincludedir=*|--datarootdir=*|--infodir=*|--localedir=*|\
|
||||
--htmldir=*|--dvidir=*|--pdfdir=*|--psdir=*)
|
||||
@ -3787,22 +3789,22 @@ int main(void) { fdt_first_subnode(0, 0); return 0; }
|
||||
EOF
|
||||
if compile_prog "" "$fdt_libs" ; then
|
||||
# system DTC is good - use it
|
||||
fdt=yes
|
||||
fdt=system
|
||||
else
|
||||
# have GIT checkout, so activate dtc submodule
|
||||
if test -e "${source_path}/.git" ; then
|
||||
git_submodules="${git_submodules} dtc"
|
||||
fi
|
||||
if test -d "${source_path}/dtc/libfdt" || test -e "${source_path}/.git" ; then
|
||||
fdt=yes
|
||||
dtc_internal="yes"
|
||||
fdt=git
|
||||
mkdir -p dtc
|
||||
if [ "$pwd_is_source_path" != "y" ] ; then
|
||||
symlink "$source_path/dtc/Makefile" "dtc/Makefile"
|
||||
symlink "$source_path/dtc/scripts" "dtc/scripts"
|
||||
fi
|
||||
fdt_cflags="-I\$(SRC_PATH)/dtc/libfdt"
|
||||
fdt_libs="-L\$(BUILD_DIR)/dtc/libfdt $fdt_libs"
|
||||
fdt_ldflags="-L\$(BUILD_DIR)/dtc/libfdt"
|
||||
fdt_libs="$fdt_libs"
|
||||
elif test "$fdt" = "yes" ; then
|
||||
# Not a git build & no libfdt found, prompt for system install
|
||||
error_exit "DTC (libfdt) version >= 1.4.2 not present." \
|
||||
@ -5744,6 +5746,7 @@ echo_version() {
|
||||
|
||||
# prepend pixman and ftd flags after all config tests are done
|
||||
QEMU_CFLAGS="$pixman_cflags $fdt_cflags $QEMU_CFLAGS"
|
||||
QEMU_LDFLAGS="$fdt_ldflags $QEMU_LDFLAGS"
|
||||
libs_softmmu="$pixman_libs $libs_softmmu"
|
||||
|
||||
echo "Install prefix $prefix"
|
||||
@ -5774,6 +5777,7 @@ echo "ARFLAGS $ARFLAGS"
|
||||
echo "CFLAGS $CFLAGS"
|
||||
echo "QEMU_CFLAGS $QEMU_CFLAGS"
|
||||
echo "LDFLAGS $LDFLAGS"
|
||||
echo "QEMU_LDFLAGS $QEMU_LDFLAGS"
|
||||
echo "make $make"
|
||||
echo "install $install"
|
||||
echo "python $python"
|
||||
@ -6333,7 +6337,7 @@ fi
|
||||
if test "$preadv" = "yes" ; then
|
||||
echo "CONFIG_PREADV=y" >> $config_host_mak
|
||||
fi
|
||||
if test "$fdt" = "yes" ; then
|
||||
if test "$fdt" != "no" ; then
|
||||
echo "CONFIG_FDT=y" >> $config_host_mak
|
||||
fi
|
||||
if test "$membarrier" = "yes" ; then
|
||||
@ -6708,6 +6712,7 @@ else
|
||||
fi
|
||||
echo "LDFLAGS=$LDFLAGS" >> $config_host_mak
|
||||
echo "LDFLAGS_NOPIE=$LDFLAGS_NOPIE" >> $config_host_mak
|
||||
echo "QEMU_LDFLAGS=$QEMU_LDFLAGS" >> $config_host_mak
|
||||
echo "LD_REL_FLAGS=$LD_REL_FLAGS" >> $config_host_mak
|
||||
echo "LD_I386_EMULATION=$ld_i386_emulation" >> $config_host_mak
|
||||
echo "LIBS+=$LIBS" >> $config_host_mak
|
||||
@ -7134,7 +7139,7 @@ echo "QEMU_CFLAGS+=$cflags" >> $config_target_mak
|
||||
|
||||
done # for target in $targets
|
||||
|
||||
if [ "$dtc_internal" = "yes" ]; then
|
||||
if [ "$fdt" = "git" ]; then
|
||||
echo "config-host.h: subdir-dtc" >> $config_host_mak
|
||||
fi
|
||||
if [ "$capstone" = "git" -o "$capstone" = "internal" ]; then
|
||||
|
18
cpus.c
18
cpus.c
@ -1648,7 +1648,7 @@ static void *qemu_tcg_cpu_thread_fn(void *arg)
|
||||
/* process any pending work */
|
||||
cpu->exit_request = 1;
|
||||
|
||||
while (1) {
|
||||
do {
|
||||
if (cpu_can_run(cpu)) {
|
||||
int r;
|
||||
qemu_mutex_unlock_iothread();
|
||||
@ -2043,7 +2043,6 @@ int vm_stop(RunState state)
|
||||
int vm_prepare_start(void)
|
||||
{
|
||||
RunState requested;
|
||||
int res = 0;
|
||||
|
||||
qemu_vmstop_requested(&requested);
|
||||
if (runstate_is_running() && requested == RUN_STATE__MAX) {
|
||||
@ -2057,17 +2056,18 @@ int vm_prepare_start(void)
|
||||
*/
|
||||
if (runstate_is_running()) {
|
||||
qapi_event_send_stop(&error_abort);
|
||||
res = -1;
|
||||
} else {
|
||||
replay_enable_events();
|
||||
cpu_enable_ticks();
|
||||
runstate_set(RUN_STATE_RUNNING);
|
||||
vm_state_notify(1, RUN_STATE_RUNNING);
|
||||
qapi_event_send_resume(&error_abort);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* We are sending this now, but the CPUs will be resumed shortly later */
|
||||
qapi_event_send_resume(&error_abort);
|
||||
return res;
|
||||
|
||||
replay_enable_events();
|
||||
cpu_enable_ticks();
|
||||
runstate_set(RUN_STATE_RUNNING);
|
||||
vm_state_notify(1, RUN_STATE_RUNNING);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void vm_start(void)
|
||||
|
242
exec.c
242
exec.c
@ -461,6 +461,70 @@ address_space_translate_internal(AddressSpaceDispatch *d, hwaddr addr, hwaddr *x
|
||||
return section;
|
||||
}
|
||||
|
||||
/**
|
||||
* address_space_translate_iommu - translate an address through an IOMMU
|
||||
* memory region and then through the target address space.
|
||||
*
|
||||
* @iommu_mr: the IOMMU memory region that we start the translation from
|
||||
* @addr: the address to be translated through the MMU
|
||||
* @xlat: the translated address offset within the destination memory region.
|
||||
* It cannot be %NULL.
|
||||
* @plen_out: valid read/write length of the translated address. It
|
||||
* cannot be %NULL.
|
||||
* @page_mask_out: page mask for the translated address. This
|
||||
* should only be meaningful for IOMMU translated
|
||||
* addresses, since there may be huge pages that this bit
|
||||
* would tell. It can be %NULL if we don't care about it.
|
||||
* @is_write: whether the translation operation is for write
|
||||
* @is_mmio: whether this can be MMIO, set true if it can
|
||||
* @target_as: the address space targeted by the IOMMU
|
||||
*
|
||||
* This function is called from RCU critical section. It is the common
|
||||
* part of flatview_do_translate and address_space_translate_cached.
|
||||
*/
|
||||
static MemoryRegionSection address_space_translate_iommu(IOMMUMemoryRegion *iommu_mr,
|
||||
hwaddr *xlat,
|
||||
hwaddr *plen_out,
|
||||
hwaddr *page_mask_out,
|
||||
bool is_write,
|
||||
bool is_mmio,
|
||||
AddressSpace **target_as)
|
||||
{
|
||||
MemoryRegionSection *section;
|
||||
hwaddr page_mask = (hwaddr)-1;
|
||||
|
||||
do {
|
||||
hwaddr addr = *xlat;
|
||||
IOMMUMemoryRegionClass *imrc = memory_region_get_iommu_class_nocheck(iommu_mr);
|
||||
IOMMUTLBEntry iotlb = imrc->translate(iommu_mr, addr, is_write ?
|
||||
IOMMU_WO : IOMMU_RO);
|
||||
|
||||
if (!(iotlb.perm & (1 << is_write))) {
|
||||
goto unassigned;
|
||||
}
|
||||
|
||||
addr = ((iotlb.translated_addr & ~iotlb.addr_mask)
|
||||
| (addr & iotlb.addr_mask));
|
||||
page_mask &= iotlb.addr_mask;
|
||||
*plen_out = MIN(*plen_out, (addr | iotlb.addr_mask) - addr + 1);
|
||||
*target_as = iotlb.target_as;
|
||||
|
||||
section = address_space_translate_internal(
|
||||
address_space_to_dispatch(iotlb.target_as), addr, xlat,
|
||||
plen_out, is_mmio);
|
||||
|
||||
iommu_mr = memory_region_get_iommu(section->mr);
|
||||
} while (unlikely(iommu_mr));
|
||||
|
||||
if (page_mask_out) {
|
||||
*page_mask_out = page_mask;
|
||||
}
|
||||
return *section;
|
||||
|
||||
unassigned:
|
||||
return (MemoryRegionSection) { .mr = &io_mem_unassigned };
|
||||
}
|
||||
|
||||
/**
|
||||
* flatview_do_translate - translate an address in FlatView
|
||||
*
|
||||
@ -476,6 +540,7 @@ address_space_translate_internal(AddressSpaceDispatch *d, hwaddr addr, hwaddr *x
|
||||
* would tell. It can be @NULL if we don't care about it.
|
||||
* @is_write: whether the translation operation is for write
|
||||
* @is_mmio: whether this can be MMIO, set true if it can
|
||||
* @target_as: the address space targeted by the IOMMU
|
||||
*
|
||||
* This function is called from RCU critical section
|
||||
*/
|
||||
@ -488,61 +553,31 @@ static MemoryRegionSection flatview_do_translate(FlatView *fv,
|
||||
bool is_mmio,
|
||||
AddressSpace **target_as)
|
||||
{
|
||||
IOMMUTLBEntry iotlb;
|
||||
MemoryRegionSection *section;
|
||||
IOMMUMemoryRegion *iommu_mr;
|
||||
IOMMUMemoryRegionClass *imrc;
|
||||
hwaddr page_mask = (hwaddr)(-1);
|
||||
hwaddr plen = (hwaddr)(-1);
|
||||
|
||||
if (plen_out) {
|
||||
plen = *plen_out;
|
||||
if (!plen_out) {
|
||||
plen_out = &plen;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
section = address_space_translate_internal(
|
||||
flatview_to_dispatch(fv), addr, &addr,
|
||||
&plen, is_mmio);
|
||||
section = address_space_translate_internal(
|
||||
flatview_to_dispatch(fv), addr, xlat,
|
||||
plen_out, is_mmio);
|
||||
|
||||
iommu_mr = memory_region_get_iommu(section->mr);
|
||||
if (!iommu_mr) {
|
||||
break;
|
||||
}
|
||||
imrc = memory_region_get_iommu_class_nocheck(iommu_mr);
|
||||
|
||||
iotlb = imrc->translate(iommu_mr, addr, is_write ?
|
||||
IOMMU_WO : IOMMU_RO);
|
||||
addr = ((iotlb.translated_addr & ~iotlb.addr_mask)
|
||||
| (addr & iotlb.addr_mask));
|
||||
page_mask &= iotlb.addr_mask;
|
||||
plen = MIN(plen, (addr | iotlb.addr_mask) - addr + 1);
|
||||
if (!(iotlb.perm & (1 << is_write))) {
|
||||
goto translate_fail;
|
||||
}
|
||||
|
||||
fv = address_space_to_flatview(iotlb.target_as);
|
||||
*target_as = iotlb.target_as;
|
||||
iommu_mr = memory_region_get_iommu(section->mr);
|
||||
if (unlikely(iommu_mr)) {
|
||||
return address_space_translate_iommu(iommu_mr, xlat,
|
||||
plen_out, page_mask_out,
|
||||
is_write, is_mmio,
|
||||
target_as);
|
||||
}
|
||||
|
||||
*xlat = addr;
|
||||
|
||||
if (page_mask == (hwaddr)(-1)) {
|
||||
/* Not behind an IOMMU, use default page size. */
|
||||
page_mask = ~TARGET_PAGE_MASK;
|
||||
}
|
||||
|
||||
if (page_mask_out) {
|
||||
*page_mask_out = page_mask;
|
||||
}
|
||||
|
||||
if (plen_out) {
|
||||
*plen_out = plen;
|
||||
/* Not behind an IOMMU, use default page size. */
|
||||
*page_mask_out = ~TARGET_PAGE_MASK;
|
||||
}
|
||||
|
||||
return *section;
|
||||
|
||||
translate_fail:
|
||||
return (MemoryRegionSection) { .mr = &io_mem_unassigned };
|
||||
}
|
||||
|
||||
/* Called from RCU critical section */
|
||||
@ -3606,33 +3641,130 @@ int64_t address_space_cache_init(MemoryRegionCache *cache,
|
||||
hwaddr len,
|
||||
bool is_write)
|
||||
{
|
||||
cache->len = len;
|
||||
cache->as = as;
|
||||
cache->xlat = addr;
|
||||
return len;
|
||||
AddressSpaceDispatch *d;
|
||||
hwaddr l;
|
||||
MemoryRegion *mr;
|
||||
|
||||
assert(len > 0);
|
||||
|
||||
l = len;
|
||||
cache->fv = address_space_get_flatview(as);
|
||||
d = flatview_to_dispatch(cache->fv);
|
||||
cache->mrs = *address_space_translate_internal(d, addr, &cache->xlat, &l, true);
|
||||
|
||||
mr = cache->mrs.mr;
|
||||
memory_region_ref(mr);
|
||||
if (memory_access_is_direct(mr, is_write)) {
|
||||
l = flatview_extend_translation(cache->fv, addr, len, mr,
|
||||
cache->xlat, l, is_write);
|
||||
cache->ptr = qemu_ram_ptr_length(mr->ram_block, cache->xlat, &l, true);
|
||||
} else {
|
||||
cache->ptr = NULL;
|
||||
}
|
||||
|
||||
cache->len = l;
|
||||
cache->is_write = is_write;
|
||||
return l;
|
||||
}
|
||||
|
||||
void address_space_cache_invalidate(MemoryRegionCache *cache,
|
||||
hwaddr addr,
|
||||
hwaddr access_len)
|
||||
{
|
||||
assert(cache->is_write);
|
||||
if (likely(cache->ptr)) {
|
||||
invalidate_and_set_dirty(cache->mrs.mr, addr + cache->xlat, access_len);
|
||||
}
|
||||
}
|
||||
|
||||
void address_space_cache_destroy(MemoryRegionCache *cache)
|
||||
{
|
||||
cache->as = NULL;
|
||||
if (!cache->mrs.mr) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (xen_enabled()) {
|
||||
xen_invalidate_map_cache_entry(cache->ptr);
|
||||
}
|
||||
memory_region_unref(cache->mrs.mr);
|
||||
flatview_unref(cache->fv);
|
||||
cache->mrs.mr = NULL;
|
||||
cache->fv = NULL;
|
||||
}
|
||||
|
||||
/* Called from RCU critical section. This function has the same
|
||||
* semantics as address_space_translate, but it only works on a
|
||||
* predefined range of a MemoryRegion that was mapped with
|
||||
* address_space_cache_init.
|
||||
*/
|
||||
static inline MemoryRegion *address_space_translate_cached(
|
||||
MemoryRegionCache *cache, hwaddr addr, hwaddr *xlat,
|
||||
hwaddr *plen, bool is_write)
|
||||
{
|
||||
MemoryRegionSection section;
|
||||
MemoryRegion *mr;
|
||||
IOMMUMemoryRegion *iommu_mr;
|
||||
AddressSpace *target_as;
|
||||
|
||||
assert(!cache->ptr);
|
||||
*xlat = addr + cache->xlat;
|
||||
|
||||
mr = cache->mrs.mr;
|
||||
iommu_mr = memory_region_get_iommu(mr);
|
||||
if (!iommu_mr) {
|
||||
/* MMIO region. */
|
||||
return mr;
|
||||
}
|
||||
|
||||
section = address_space_translate_iommu(iommu_mr, xlat, plen,
|
||||
NULL, is_write, true,
|
||||
&target_as);
|
||||
return section.mr;
|
||||
}
|
||||
|
||||
/* Called from RCU critical section. address_space_read_cached uses this
|
||||
* out of line function when the target is an MMIO or IOMMU region.
|
||||
*/
|
||||
void
|
||||
address_space_read_cached_slow(MemoryRegionCache *cache, hwaddr addr,
|
||||
void *buf, int len)
|
||||
{
|
||||
hwaddr addr1, l;
|
||||
MemoryRegion *mr;
|
||||
|
||||
l = len;
|
||||
mr = address_space_translate_cached(cache, addr, &addr1, &l, false);
|
||||
flatview_read_continue(cache->fv,
|
||||
addr, MEMTXATTRS_UNSPECIFIED, buf, len,
|
||||
addr1, l, mr);
|
||||
}
|
||||
|
||||
/* Called from RCU critical section. address_space_write_cached uses this
|
||||
* out of line function when the target is an MMIO or IOMMU region.
|
||||
*/
|
||||
void
|
||||
address_space_write_cached_slow(MemoryRegionCache *cache, hwaddr addr,
|
||||
const void *buf, int len)
|
||||
{
|
||||
hwaddr addr1, l;
|
||||
MemoryRegion *mr;
|
||||
|
||||
l = len;
|
||||
mr = address_space_translate_cached(cache, addr, &addr1, &l, true);
|
||||
flatview_write_continue(cache->fv,
|
||||
addr, MEMTXATTRS_UNSPECIFIED, buf, len,
|
||||
addr1, l, mr);
|
||||
}
|
||||
|
||||
#define ARG1_DECL MemoryRegionCache *cache
|
||||
#define ARG1 cache
|
||||
#define SUFFIX _cached
|
||||
#define TRANSLATE(addr, ...) \
|
||||
address_space_translate(cache->as, cache->xlat + (addr), __VA_ARGS__)
|
||||
#define IS_DIRECT(mr, is_write) true
|
||||
#define MAP_RAM(mr, ofs) qemu_map_ram_ptr((mr)->ram_block, ofs)
|
||||
#define SUFFIX _cached_slow
|
||||
#define TRANSLATE(...) address_space_translate_cached(cache, __VA_ARGS__)
|
||||
#define IS_DIRECT(mr, is_write) memory_access_is_direct(mr, is_write)
|
||||
#define MAP_RAM(mr, ofs) (cache->ptr + (ofs - cache->xlat))
|
||||
#define INVALIDATE(mr, ofs, len) invalidate_and_set_dirty(mr, ofs, len)
|
||||
#define RCU_READ_LOCK() rcu_read_lock()
|
||||
#define RCU_READ_UNLOCK() rcu_read_unlock()
|
||||
#define RCU_READ_LOCK() ((void)0)
|
||||
#define RCU_READ_UNLOCK() ((void)0)
|
||||
#include "memory_ldst.inc.c"
|
||||
|
||||
/* virtual memory access for debug (includes writing to ROM) */
|
||||
|
@ -291,12 +291,16 @@ int load_multiboot(FWCfgState *fw_cfg,
|
||||
cmdline_len = strlen(kernel_filename) + 1;
|
||||
cmdline_len += strlen(kernel_cmdline) + 1;
|
||||
if (initrd_filename) {
|
||||
const char *r = initrd_filename;
|
||||
const char *r = get_opt_value(initrd_filename, NULL);
|
||||
cmdline_len += strlen(r) + 1;
|
||||
mbs.mb_mods_avail = 1;
|
||||
while (*(r = get_opt_value(NULL, 0, r))) {
|
||||
mbs.mb_mods_avail++;
|
||||
r++;
|
||||
while (1) {
|
||||
mbs.mb_mods_avail++;
|
||||
r = get_opt_value(r, NULL);
|
||||
if (!*r) {
|
||||
break;
|
||||
}
|
||||
r++;
|
||||
}
|
||||
}
|
||||
|
||||
@ -313,7 +317,8 @@ int load_multiboot(FWCfgState *fw_cfg,
|
||||
|
||||
if (initrd_filename) {
|
||||
const char *next_initrd;
|
||||
char not_last, tmpbuf[strlen(initrd_filename) + 1];
|
||||
char not_last;
|
||||
char *one_file = NULL;
|
||||
|
||||
mbs.offset_mods = mbs.mb_buf_size;
|
||||
|
||||
@ -322,24 +327,26 @@ int load_multiboot(FWCfgState *fw_cfg,
|
||||
int mb_mod_length;
|
||||
uint32_t offs = mbs.mb_buf_size;
|
||||
|
||||
next_initrd = get_opt_value(tmpbuf, sizeof(tmpbuf), initrd_filename);
|
||||
next_initrd = get_opt_value(initrd_filename, &one_file);
|
||||
not_last = *next_initrd;
|
||||
/* if a space comes after the module filename, treat everything
|
||||
after that as parameters */
|
||||
hwaddr c = mb_add_cmdline(&mbs, tmpbuf);
|
||||
if ((next_space = strchr(tmpbuf, ' ')))
|
||||
hwaddr c = mb_add_cmdline(&mbs, one_file);
|
||||
next_space = strchr(one_file, ' ');
|
||||
if (next_space) {
|
||||
*next_space = '\0';
|
||||
mb_debug("multiboot loading module: %s", tmpbuf);
|
||||
mb_mod_length = get_image_size(tmpbuf);
|
||||
}
|
||||
mb_debug("multiboot loading module: %s", one_file);
|
||||
mb_mod_length = get_image_size(one_file);
|
||||
if (mb_mod_length < 0) {
|
||||
error_report("Failed to open file '%s'", tmpbuf);
|
||||
error_report("Failed to open file '%s'", one_file);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
mbs.mb_buf_size = TARGET_PAGE_ALIGN(mb_mod_length + mbs.mb_buf_size);
|
||||
mbs.mb_buf = g_realloc(mbs.mb_buf, mbs.mb_buf_size);
|
||||
|
||||
load_image(tmpbuf, (unsigned char *)mbs.mb_buf + offs);
|
||||
load_image(one_file, (unsigned char *)mbs.mb_buf + offs);
|
||||
mb_add_mod(&mbs, mbs.mb_buf_phys + offs,
|
||||
mbs.mb_buf_phys + offs + mb_mod_length, c);
|
||||
|
||||
@ -347,6 +354,8 @@ int load_multiboot(FWCfgState *fw_cfg,
|
||||
(char *)mbs.mb_buf + offs,
|
||||
(char *)mbs.mb_buf + offs + mb_mod_length, c);
|
||||
initrd_filename = next_initrd+1;
|
||||
g_free(one_file);
|
||||
one_file = NULL;
|
||||
} while (not_last);
|
||||
}
|
||||
|
||||
|
@ -118,9 +118,16 @@ static int pc_dimm_slot2bitmap(Object *obj, void *opaque)
|
||||
|
||||
int pc_dimm_get_free_slot(const int *hint, int max_slots, Error **errp)
|
||||
{
|
||||
unsigned long *bitmap = bitmap_new(max_slots);
|
||||
unsigned long *bitmap;
|
||||
int slot = 0;
|
||||
|
||||
if (max_slots <= 0) {
|
||||
error_setg(errp, "no slots where allocated, please specify "
|
||||
"the 'slots' option");
|
||||
return slot;
|
||||
}
|
||||
|
||||
bitmap = bitmap_new(max_slots);
|
||||
object_child_foreach(qdev_get_machine(), pc_dimm_slot2bitmap, bitmap);
|
||||
|
||||
/* check if requested slot is not occupied */
|
||||
|
@ -168,51 +168,40 @@ extern unsigned long reserved_va;
|
||||
#else
|
||||
|
||||
#include "exec/hwaddr.h"
|
||||
uint32_t lduw_phys(AddressSpace *as, hwaddr addr);
|
||||
uint32_t ldl_phys(AddressSpace *as, hwaddr addr);
|
||||
uint64_t ldq_phys(AddressSpace *as, hwaddr addr);
|
||||
void stl_phys_notdirty(AddressSpace *as, hwaddr addr, uint32_t val);
|
||||
void stw_phys(AddressSpace *as, hwaddr addr, uint32_t val);
|
||||
void stl_phys(AddressSpace *as, hwaddr addr, uint32_t val);
|
||||
void stq_phys(AddressSpace *as, hwaddr addr, uint64_t val);
|
||||
|
||||
uint32_t address_space_lduw(AddressSpace *as, hwaddr addr,
|
||||
MemTxAttrs attrs, MemTxResult *result);
|
||||
uint32_t address_space_ldl(AddressSpace *as, hwaddr addr,
|
||||
MemTxAttrs attrs, MemTxResult *result);
|
||||
uint64_t address_space_ldq(AddressSpace *as, hwaddr addr,
|
||||
MemTxAttrs attrs, MemTxResult *result);
|
||||
void address_space_stl_notdirty(AddressSpace *as, hwaddr addr, uint32_t val,
|
||||
MemTxAttrs attrs, MemTxResult *result);
|
||||
void address_space_stw(AddressSpace *as, hwaddr addr, uint32_t val,
|
||||
MemTxAttrs attrs, MemTxResult *result);
|
||||
void address_space_stl(AddressSpace *as, hwaddr addr, uint32_t val,
|
||||
MemTxAttrs attrs, MemTxResult *result);
|
||||
void address_space_stq(AddressSpace *as, hwaddr addr, uint64_t val,
|
||||
MemTxAttrs attrs, MemTxResult *result);
|
||||
#define SUFFIX
|
||||
#define ARG1 as
|
||||
#define ARG1_DECL AddressSpace *as
|
||||
#define TARGET_ENDIANNESS
|
||||
#include "exec/memory_ldst.inc.h"
|
||||
|
||||
uint32_t lduw_phys_cached(MemoryRegionCache *cache, hwaddr addr);
|
||||
uint32_t ldl_phys_cached(MemoryRegionCache *cache, hwaddr addr);
|
||||
uint64_t ldq_phys_cached(MemoryRegionCache *cache, hwaddr addr);
|
||||
void stl_phys_notdirty_cached(MemoryRegionCache *cache, hwaddr addr, uint32_t val);
|
||||
void stw_phys_cached(MemoryRegionCache *cache, hwaddr addr, uint32_t val);
|
||||
void stl_phys_cached(MemoryRegionCache *cache, hwaddr addr, uint32_t val);
|
||||
void stq_phys_cached(MemoryRegionCache *cache, hwaddr addr, uint64_t val);
|
||||
#define SUFFIX _cached_slow
|
||||
#define ARG1 cache
|
||||
#define ARG1_DECL MemoryRegionCache *cache
|
||||
#define TARGET_ENDIANNESS
|
||||
#include "exec/memory_ldst.inc.h"
|
||||
|
||||
uint32_t address_space_lduw_cached(MemoryRegionCache *cache, hwaddr addr,
|
||||
MemTxAttrs attrs, MemTxResult *result);
|
||||
uint32_t address_space_ldl_cached(MemoryRegionCache *cache, hwaddr addr,
|
||||
MemTxAttrs attrs, MemTxResult *result);
|
||||
uint64_t address_space_ldq_cached(MemoryRegionCache *cache, hwaddr addr,
|
||||
MemTxAttrs attrs, MemTxResult *result);
|
||||
void address_space_stl_notdirty_cached(MemoryRegionCache *cache, hwaddr addr,
|
||||
uint32_t val, MemTxAttrs attrs, MemTxResult *result);
|
||||
void address_space_stw_cached(MemoryRegionCache *cache, hwaddr addr, uint32_t val,
|
||||
MemTxAttrs attrs, MemTxResult *result);
|
||||
void address_space_stl_cached(MemoryRegionCache *cache, hwaddr addr, uint32_t val,
|
||||
MemTxAttrs attrs, MemTxResult *result);
|
||||
void address_space_stq_cached(MemoryRegionCache *cache, hwaddr addr, uint64_t val,
|
||||
MemTxAttrs attrs, MemTxResult *result);
|
||||
static inline void stl_phys_notdirty(AddressSpace *as, hwaddr addr, uint32_t val)
|
||||
{
|
||||
address_space_stl_notdirty(as, addr, val,
|
||||
MEMTXATTRS_UNSPECIFIED, NULL);
|
||||
}
|
||||
|
||||
#define SUFFIX
|
||||
#define ARG1 as
|
||||
#define ARG1_DECL AddressSpace *as
|
||||
#define TARGET_ENDIANNESS
|
||||
#include "exec/memory_ldst_phys.inc.h"
|
||||
|
||||
/* Inline fast path for direct RAM access. */
|
||||
#define ENDIANNESS
|
||||
#include "exec/memory_ldst_cached.inc.h"
|
||||
|
||||
#define SUFFIX _cached
|
||||
#define ARG1 cache
|
||||
#define ARG1_DECL MemoryRegionCache *cache
|
||||
#define TARGET_ENDIANNESS
|
||||
#include "exec/memory_ldst_phys.inc.h"
|
||||
#endif
|
||||
|
||||
/* page related stuff */
|
||||
|
@ -31,6 +31,9 @@ static inline AddressSpaceDispatch *address_space_to_dispatch(AddressSpace *as)
|
||||
return flatview_to_dispatch(address_space_to_flatview(as));
|
||||
}
|
||||
|
||||
FlatView *address_space_get_flatview(AddressSpace *as);
|
||||
void flatview_unref(FlatView *view);
|
||||
|
||||
extern const MemoryRegionOps unassigned_mem_ops;
|
||||
|
||||
bool memory_region_access_valid(MemoryRegion *mr, hwaddr addr,
|
||||
|
@ -1676,57 +1676,91 @@ MemTxResult address_space_write(AddressSpace *as, hwaddr addr,
|
||||
* @result: location to write the success/failure of the transaction;
|
||||
* if NULL, this information is discarded
|
||||
*/
|
||||
uint32_t address_space_ldub(AddressSpace *as, hwaddr addr,
|
||||
MemTxAttrs attrs, MemTxResult *result);
|
||||
uint32_t address_space_lduw_le(AddressSpace *as, hwaddr addr,
|
||||
MemTxAttrs attrs, MemTxResult *result);
|
||||
uint32_t address_space_lduw_be(AddressSpace *as, hwaddr addr,
|
||||
MemTxAttrs attrs, MemTxResult *result);
|
||||
uint32_t address_space_ldl_le(AddressSpace *as, hwaddr addr,
|
||||
MemTxAttrs attrs, MemTxResult *result);
|
||||
uint32_t address_space_ldl_be(AddressSpace *as, hwaddr addr,
|
||||
MemTxAttrs attrs, MemTxResult *result);
|
||||
uint64_t address_space_ldq_le(AddressSpace *as, hwaddr addr,
|
||||
MemTxAttrs attrs, MemTxResult *result);
|
||||
uint64_t address_space_ldq_be(AddressSpace *as, hwaddr addr,
|
||||
MemTxAttrs attrs, MemTxResult *result);
|
||||
void address_space_stb(AddressSpace *as, hwaddr addr, uint32_t val,
|
||||
MemTxAttrs attrs, MemTxResult *result);
|
||||
void address_space_stw_le(AddressSpace *as, hwaddr addr, uint32_t val,
|
||||
MemTxAttrs attrs, MemTxResult *result);
|
||||
void address_space_stw_be(AddressSpace *as, hwaddr addr, uint32_t val,
|
||||
MemTxAttrs attrs, MemTxResult *result);
|
||||
void address_space_stl_le(AddressSpace *as, hwaddr addr, uint32_t val,
|
||||
MemTxAttrs attrs, MemTxResult *result);
|
||||
void address_space_stl_be(AddressSpace *as, hwaddr addr, uint32_t val,
|
||||
MemTxAttrs attrs, MemTxResult *result);
|
||||
void address_space_stq_le(AddressSpace *as, hwaddr addr, uint64_t val,
|
||||
MemTxAttrs attrs, MemTxResult *result);
|
||||
void address_space_stq_be(AddressSpace *as, hwaddr addr, uint64_t val,
|
||||
MemTxAttrs attrs, MemTxResult *result);
|
||||
|
||||
uint32_t ldub_phys(AddressSpace *as, hwaddr addr);
|
||||
uint32_t lduw_le_phys(AddressSpace *as, hwaddr addr);
|
||||
uint32_t lduw_be_phys(AddressSpace *as, hwaddr addr);
|
||||
uint32_t ldl_le_phys(AddressSpace *as, hwaddr addr);
|
||||
uint32_t ldl_be_phys(AddressSpace *as, hwaddr addr);
|
||||
uint64_t ldq_le_phys(AddressSpace *as, hwaddr addr);
|
||||
uint64_t ldq_be_phys(AddressSpace *as, hwaddr addr);
|
||||
void stb_phys(AddressSpace *as, hwaddr addr, uint32_t val);
|
||||
void stw_le_phys(AddressSpace *as, hwaddr addr, uint32_t val);
|
||||
void stw_be_phys(AddressSpace *as, hwaddr addr, uint32_t val);
|
||||
void stl_le_phys(AddressSpace *as, hwaddr addr, uint32_t val);
|
||||
void stl_be_phys(AddressSpace *as, hwaddr addr, uint32_t val);
|
||||
void stq_le_phys(AddressSpace *as, hwaddr addr, uint64_t val);
|
||||
void stq_be_phys(AddressSpace *as, hwaddr addr, uint64_t val);
|
||||
#define SUFFIX
|
||||
#define ARG1 as
|
||||
#define ARG1_DECL AddressSpace *as
|
||||
#include "exec/memory_ldst.inc.h"
|
||||
|
||||
#define SUFFIX
|
||||
#define ARG1 as
|
||||
#define ARG1_DECL AddressSpace *as
|
||||
#include "exec/memory_ldst_phys.inc.h"
|
||||
|
||||
struct MemoryRegionCache {
|
||||
void *ptr;
|
||||
hwaddr xlat;
|
||||
hwaddr len;
|
||||
AddressSpace *as;
|
||||
FlatView *fv;
|
||||
MemoryRegionSection mrs;
|
||||
bool is_write;
|
||||
};
|
||||
|
||||
#define MEMORY_REGION_CACHE_INVALID ((MemoryRegionCache) { .as = NULL })
|
||||
#define MEMORY_REGION_CACHE_INVALID ((MemoryRegionCache) { .mrs.mr = NULL })
|
||||
|
||||
|
||||
/* address_space_ld*_cached: load from a cached #MemoryRegion
|
||||
* address_space_st*_cached: store into a cached #MemoryRegion
|
||||
*
|
||||
* These functions perform a load or store of the byte, word,
|
||||
* longword or quad to the specified address. The address is
|
||||
* a physical address in the AddressSpace, but it must lie within
|
||||
* a #MemoryRegion that was mapped with address_space_cache_init.
|
||||
*
|
||||
* The _le suffixed functions treat the data as little endian;
|
||||
* _be indicates big endian; no suffix indicates "same endianness
|
||||
* as guest CPU".
|
||||
*
|
||||
* The "guest CPU endianness" accessors are deprecated for use outside
|
||||
* target-* code; devices should be CPU-agnostic and use either the LE
|
||||
* or the BE accessors.
|
||||
*
|
||||
* @cache: previously initialized #MemoryRegionCache to be accessed
|
||||
* @addr: address within the address space
|
||||
* @val: data value, for stores
|
||||
* @attrs: memory transaction attributes
|
||||
* @result: location to write the success/failure of the transaction;
|
||||
* if NULL, this information is discarded
|
||||
*/
|
||||
|
||||
#define SUFFIX _cached_slow
|
||||
#define ARG1 cache
|
||||
#define ARG1_DECL MemoryRegionCache *cache
|
||||
#include "exec/memory_ldst.inc.h"
|
||||
|
||||
/* Inline fast path for direct RAM access. */
|
||||
static inline uint8_t address_space_ldub_cached(MemoryRegionCache *cache,
|
||||
hwaddr addr, MemTxAttrs attrs, MemTxResult *result)
|
||||
{
|
||||
assert(addr < cache->len);
|
||||
if (likely(cache->ptr)) {
|
||||
return ldub_p(cache->ptr + addr);
|
||||
} else {
|
||||
return address_space_ldub_cached_slow(cache, addr, attrs, result);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void address_space_stb_cached(MemoryRegionCache *cache,
|
||||
hwaddr addr, uint32_t val, MemTxAttrs attrs, MemTxResult *result)
|
||||
{
|
||||
assert(addr < cache->len);
|
||||
if (likely(cache->ptr)) {
|
||||
stb_p(cache->ptr + addr, val);
|
||||
} else {
|
||||
address_space_stb_cached_slow(cache, addr, val, attrs, result);
|
||||
}
|
||||
}
|
||||
|
||||
#define ENDIANNESS _le
|
||||
#include "exec/memory_ldst_cached.inc.h"
|
||||
|
||||
#define ENDIANNESS _be
|
||||
#include "exec/memory_ldst_cached.inc.h"
|
||||
|
||||
#define SUFFIX _cached
|
||||
#define ARG1 cache
|
||||
#define ARG1_DECL MemoryRegionCache *cache
|
||||
#include "exec/memory_ldst_phys.inc.h"
|
||||
|
||||
/* address_space_cache_init: prepare for repeated access to a physical
|
||||
* memory region
|
||||
@ -1772,72 +1806,6 @@ void address_space_cache_invalidate(MemoryRegionCache *cache,
|
||||
*/
|
||||
void address_space_cache_destroy(MemoryRegionCache *cache);
|
||||
|
||||
/* address_space_ld*_cached: load from a cached #MemoryRegion
|
||||
* address_space_st*_cached: store into a cached #MemoryRegion
|
||||
*
|
||||
* These functions perform a load or store of the byte, word,
|
||||
* longword or quad to the specified address. The address is
|
||||
* a physical address in the AddressSpace, but it must lie within
|
||||
* a #MemoryRegion that was mapped with address_space_cache_init.
|
||||
*
|
||||
* The _le suffixed functions treat the data as little endian;
|
||||
* _be indicates big endian; no suffix indicates "same endianness
|
||||
* as guest CPU".
|
||||
*
|
||||
* The "guest CPU endianness" accessors are deprecated for use outside
|
||||
* target-* code; devices should be CPU-agnostic and use either the LE
|
||||
* or the BE accessors.
|
||||
*
|
||||
* @cache: previously initialized #MemoryRegionCache to be accessed
|
||||
* @addr: address within the address space
|
||||
* @val: data value, for stores
|
||||
* @attrs: memory transaction attributes
|
||||
* @result: location to write the success/failure of the transaction;
|
||||
* if NULL, this information is discarded
|
||||
*/
|
||||
uint32_t address_space_ldub_cached(MemoryRegionCache *cache, hwaddr addr,
|
||||
MemTxAttrs attrs, MemTxResult *result);
|
||||
uint32_t address_space_lduw_le_cached(MemoryRegionCache *cache, hwaddr addr,
|
||||
MemTxAttrs attrs, MemTxResult *result);
|
||||
uint32_t address_space_lduw_be_cached(MemoryRegionCache *cache, hwaddr addr,
|
||||
MemTxAttrs attrs, MemTxResult *result);
|
||||
uint32_t address_space_ldl_le_cached(MemoryRegionCache *cache, hwaddr addr,
|
||||
MemTxAttrs attrs, MemTxResult *result);
|
||||
uint32_t address_space_ldl_be_cached(MemoryRegionCache *cache, hwaddr addr,
|
||||
MemTxAttrs attrs, MemTxResult *result);
|
||||
uint64_t address_space_ldq_le_cached(MemoryRegionCache *cache, hwaddr addr,
|
||||
MemTxAttrs attrs, MemTxResult *result);
|
||||
uint64_t address_space_ldq_be_cached(MemoryRegionCache *cache, hwaddr addr,
|
||||
MemTxAttrs attrs, MemTxResult *result);
|
||||
void address_space_stb_cached(MemoryRegionCache *cache, hwaddr addr, uint32_t val,
|
||||
MemTxAttrs attrs, MemTxResult *result);
|
||||
void address_space_stw_le_cached(MemoryRegionCache *cache, hwaddr addr, uint32_t val,
|
||||
MemTxAttrs attrs, MemTxResult *result);
|
||||
void address_space_stw_be_cached(MemoryRegionCache *cache, hwaddr addr, uint32_t val,
|
||||
MemTxAttrs attrs, MemTxResult *result);
|
||||
void address_space_stl_le_cached(MemoryRegionCache *cache, hwaddr addr, uint32_t val,
|
||||
MemTxAttrs attrs, MemTxResult *result);
|
||||
void address_space_stl_be_cached(MemoryRegionCache *cache, hwaddr addr, uint32_t val,
|
||||
MemTxAttrs attrs, MemTxResult *result);
|
||||
void address_space_stq_le_cached(MemoryRegionCache *cache, hwaddr addr, uint64_t val,
|
||||
MemTxAttrs attrs, MemTxResult *result);
|
||||
void address_space_stq_be_cached(MemoryRegionCache *cache, hwaddr addr, uint64_t val,
|
||||
MemTxAttrs attrs, MemTxResult *result);
|
||||
|
||||
uint32_t ldub_phys_cached(MemoryRegionCache *cache, hwaddr addr);
|
||||
uint32_t lduw_le_phys_cached(MemoryRegionCache *cache, hwaddr addr);
|
||||
uint32_t lduw_be_phys_cached(MemoryRegionCache *cache, hwaddr addr);
|
||||
uint32_t ldl_le_phys_cached(MemoryRegionCache *cache, hwaddr addr);
|
||||
uint32_t ldl_be_phys_cached(MemoryRegionCache *cache, hwaddr addr);
|
||||
uint64_t ldq_le_phys_cached(MemoryRegionCache *cache, hwaddr addr);
|
||||
uint64_t ldq_be_phys_cached(MemoryRegionCache *cache, hwaddr addr);
|
||||
void stb_phys_cached(MemoryRegionCache *cache, hwaddr addr, uint32_t val);
|
||||
void stw_le_phys_cached(MemoryRegionCache *cache, hwaddr addr, uint32_t val);
|
||||
void stw_be_phys_cached(MemoryRegionCache *cache, hwaddr addr, uint32_t val);
|
||||
void stl_le_phys_cached(MemoryRegionCache *cache, hwaddr addr, uint32_t val);
|
||||
void stl_be_phys_cached(MemoryRegionCache *cache, hwaddr addr, uint32_t val);
|
||||
void stq_le_phys_cached(MemoryRegionCache *cache, hwaddr addr, uint64_t val);
|
||||
void stq_be_phys_cached(MemoryRegionCache *cache, hwaddr addr, uint64_t val);
|
||||
/* address_space_get_iotlb_entry: translate an address into an IOTLB
|
||||
* entry. Should be called from an RCU critical section.
|
||||
*/
|
||||
@ -1925,6 +1893,13 @@ MemTxResult flatview_read_continue(FlatView *fv, hwaddr addr,
|
||||
MemoryRegion *mr);
|
||||
void *qemu_map_ram_ptr(RAMBlock *ram_block, ram_addr_t addr);
|
||||
|
||||
/* Internal functions, part of the implementation of address_space_read_cached
|
||||
* and address_space_write_cached. */
|
||||
void address_space_read_cached_slow(MemoryRegionCache *cache,
|
||||
hwaddr addr, void *buf, int len);
|
||||
void address_space_write_cached_slow(MemoryRegionCache *cache,
|
||||
hwaddr addr, const void *buf, int len);
|
||||
|
||||
static inline bool memory_access_is_direct(MemoryRegion *mr, bool is_write)
|
||||
{
|
||||
if (is_write) {
|
||||
@ -1993,7 +1968,11 @@ address_space_read_cached(MemoryRegionCache *cache, hwaddr addr,
|
||||
void *buf, int len)
|
||||
{
|
||||
assert(addr < cache->len && len <= cache->len - addr);
|
||||
address_space_read(cache->as, cache->xlat + addr, MEMTXATTRS_UNSPECIFIED, buf, len);
|
||||
if (likely(cache->ptr)) {
|
||||
memcpy(buf, cache->ptr + addr, len);
|
||||
} else {
|
||||
address_space_read_cached_slow(cache, addr, buf, len);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2009,7 +1988,11 @@ address_space_write_cached(MemoryRegionCache *cache, hwaddr addr,
|
||||
void *buf, int len)
|
||||
{
|
||||
assert(addr < cache->len && len <= cache->len - addr);
|
||||
address_space_write(cache->as, cache->xlat + addr, MEMTXATTRS_UNSPECIFIED, buf, len);
|
||||
if (likely(cache->ptr)) {
|
||||
memcpy(cache->ptr + addr, buf, len);
|
||||
} else {
|
||||
address_space_write_cached_slow(cache, addr, buf, len);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
71
include/exec/memory_ldst.inc.h
Normal file
71
include/exec/memory_ldst.inc.h
Normal file
@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Physical memory access templates
|
||||
*
|
||||
* Copyright (c) 2003 Fabrice Bellard
|
||||
* Copyright (c) 2015 Linaro, Inc.
|
||||
* Copyright (c) 2016 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifdef TARGET_ENDIANNESS
|
||||
extern uint32_t glue(address_space_lduw, SUFFIX)(ARG1_DECL,
|
||||
hwaddr addr, MemTxAttrs attrs, MemTxResult *result);
|
||||
extern uint32_t glue(address_space_ldl, SUFFIX)(ARG1_DECL,
|
||||
hwaddr addr, MemTxAttrs attrs, MemTxResult *result);
|
||||
extern uint64_t glue(address_space_ldq, SUFFIX)(ARG1_DECL,
|
||||
hwaddr addr, MemTxAttrs attrs, MemTxResult *result);
|
||||
extern void glue(address_space_stl_notdirty, SUFFIX)(ARG1_DECL,
|
||||
hwaddr addr, uint32_t val, MemTxAttrs attrs, MemTxResult *result);
|
||||
extern void glue(address_space_stw, SUFFIX)(ARG1_DECL,
|
||||
hwaddr addr, uint32_t val, MemTxAttrs attrs, MemTxResult *result);
|
||||
extern void glue(address_space_stl, SUFFIX)(ARG1_DECL,
|
||||
hwaddr addr, uint32_t val, MemTxAttrs attrs, MemTxResult *result);
|
||||
extern void glue(address_space_stq, SUFFIX)(ARG1_DECL,
|
||||
hwaddr addr, uint64_t val, MemTxAttrs attrs, MemTxResult *result);
|
||||
#else
|
||||
extern uint32_t glue(address_space_ldub, SUFFIX)(ARG1_DECL,
|
||||
hwaddr addr, MemTxAttrs attrs, MemTxResult *result);
|
||||
extern uint32_t glue(address_space_lduw_le, SUFFIX)(ARG1_DECL,
|
||||
hwaddr addr, MemTxAttrs attrs, MemTxResult *result);
|
||||
extern uint32_t glue(address_space_lduw_be, SUFFIX)(ARG1_DECL,
|
||||
hwaddr addr, MemTxAttrs attrs, MemTxResult *result);
|
||||
extern uint32_t glue(address_space_ldl_le, SUFFIX)(ARG1_DECL,
|
||||
hwaddr addr, MemTxAttrs attrs, MemTxResult *result);
|
||||
extern uint32_t glue(address_space_ldl_be, SUFFIX)(ARG1_DECL,
|
||||
hwaddr addr, MemTxAttrs attrs, MemTxResult *result);
|
||||
extern uint64_t glue(address_space_ldq_le, SUFFIX)(ARG1_DECL,
|
||||
hwaddr addr, MemTxAttrs attrs, MemTxResult *result);
|
||||
extern uint64_t glue(address_space_ldq_be, SUFFIX)(ARG1_DECL,
|
||||
hwaddr addr, MemTxAttrs attrs, MemTxResult *result);
|
||||
extern void glue(address_space_stb, SUFFIX)(ARG1_DECL,
|
||||
hwaddr addr, uint32_t val, MemTxAttrs attrs, MemTxResult *result);
|
||||
extern void glue(address_space_stw_le, SUFFIX)(ARG1_DECL,
|
||||
hwaddr addr, uint32_t val, MemTxAttrs attrs, MemTxResult *result);
|
||||
extern void glue(address_space_stw_be, SUFFIX)(ARG1_DECL,
|
||||
hwaddr addr, uint32_t val, MemTxAttrs attrs, MemTxResult *result);
|
||||
extern void glue(address_space_stl_le, SUFFIX)(ARG1_DECL,
|
||||
hwaddr addr, uint32_t val, MemTxAttrs attrs, MemTxResult *result);
|
||||
extern void glue(address_space_stl_be, SUFFIX)(ARG1_DECL,
|
||||
hwaddr addr, uint32_t val, MemTxAttrs attrs, MemTxResult *result);
|
||||
extern void glue(address_space_stq_le, SUFFIX)(ARG1_DECL,
|
||||
hwaddr addr, uint64_t val, MemTxAttrs attrs, MemTxResult *result);
|
||||
extern void glue(address_space_stq_be, SUFFIX)(ARG1_DECL,
|
||||
hwaddr addr, uint64_t val, MemTxAttrs attrs, MemTxResult *result);
|
||||
#endif
|
||||
|
||||
#undef ARG1_DECL
|
||||
#undef ARG1
|
||||
#undef SUFFIX
|
||||
#undef TARGET_ENDIANNESS
|
108
include/exec/memory_ldst_cached.inc.h
Normal file
108
include/exec/memory_ldst_cached.inc.h
Normal file
@ -0,0 +1,108 @@
|
||||
/*
|
||||
* Memory access templates for MemoryRegionCache
|
||||
*
|
||||
* Copyright (c) 2018 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#define ADDRESS_SPACE_LD_CACHED(size) \
|
||||
glue(glue(address_space_ld, size), glue(ENDIANNESS, _cached))
|
||||
#define ADDRESS_SPACE_LD_CACHED_SLOW(size) \
|
||||
glue(glue(address_space_ld, size), glue(ENDIANNESS, _cached_slow))
|
||||
#define LD_P(size) \
|
||||
glue(glue(ld, size), glue(ENDIANNESS, _p))
|
||||
|
||||
static inline uint32_t ADDRESS_SPACE_LD_CACHED(l)(MemoryRegionCache *cache,
|
||||
hwaddr addr, MemTxAttrs attrs, MemTxResult *result)
|
||||
{
|
||||
assert(addr < cache->len && 4 <= cache->len - addr);
|
||||
if (likely(cache->ptr)) {
|
||||
return LD_P(l)(cache->ptr + addr);
|
||||
} else {
|
||||
return ADDRESS_SPACE_LD_CACHED_SLOW(l)(cache, addr, attrs, result);
|
||||
}
|
||||
}
|
||||
|
||||
static inline uint64_t ADDRESS_SPACE_LD_CACHED(q)(MemoryRegionCache *cache,
|
||||
hwaddr addr, MemTxAttrs attrs, MemTxResult *result)
|
||||
{
|
||||
assert(addr < cache->len && 8 <= cache->len - addr);
|
||||
if (likely(cache->ptr)) {
|
||||
return LD_P(q)(cache->ptr + addr);
|
||||
} else {
|
||||
return ADDRESS_SPACE_LD_CACHED_SLOW(q)(cache, addr, attrs, result);
|
||||
}
|
||||
}
|
||||
|
||||
static inline uint32_t ADDRESS_SPACE_LD_CACHED(uw)(MemoryRegionCache *cache,
|
||||
hwaddr addr, MemTxAttrs attrs, MemTxResult *result)
|
||||
{
|
||||
assert(addr < cache->len && 2 <= cache->len - addr);
|
||||
if (likely(cache->ptr)) {
|
||||
return LD_P(uw)(cache->ptr + addr);
|
||||
} else {
|
||||
return ADDRESS_SPACE_LD_CACHED_SLOW(uw)(cache, addr, attrs, result);
|
||||
}
|
||||
}
|
||||
|
||||
#undef ADDRESS_SPACE_LD_CACHED
|
||||
#undef ADDRESS_SPACE_LD_CACHED_SLOW
|
||||
#undef LD_P
|
||||
|
||||
#define ADDRESS_SPACE_ST_CACHED(size) \
|
||||
glue(glue(address_space_st, size), glue(ENDIANNESS, _cached))
|
||||
#define ADDRESS_SPACE_ST_CACHED_SLOW(size) \
|
||||
glue(glue(address_space_st, size), glue(ENDIANNESS, _cached_slow))
|
||||
#define ST_P(size) \
|
||||
glue(glue(st, size), glue(ENDIANNESS, _p))
|
||||
|
||||
static inline void ADDRESS_SPACE_ST_CACHED(l)(MemoryRegionCache *cache,
|
||||
hwaddr addr, uint32_t val, MemTxAttrs attrs, MemTxResult *result)
|
||||
{
|
||||
assert(addr < cache->len && 4 <= cache->len - addr);
|
||||
if (likely(cache->ptr)) {
|
||||
ST_P(l)(cache->ptr + addr, val);
|
||||
} else {
|
||||
ADDRESS_SPACE_ST_CACHED_SLOW(l)(cache, addr, val, attrs, result);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void ADDRESS_SPACE_ST_CACHED(w)(MemoryRegionCache *cache,
|
||||
hwaddr addr, uint32_t val, MemTxAttrs attrs, MemTxResult *result)
|
||||
{
|
||||
assert(addr < cache->len && 2 <= cache->len - addr);
|
||||
if (likely(cache->ptr)) {
|
||||
ST_P(w)(cache->ptr + addr, val);
|
||||
} else {
|
||||
ADDRESS_SPACE_ST_CACHED_SLOW(w)(cache, addr, val, attrs, result);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void ADDRESS_SPACE_ST_CACHED(q)(MemoryRegionCache *cache,
|
||||
hwaddr addr, uint64_t val, MemTxAttrs attrs, MemTxResult *result)
|
||||
{
|
||||
assert(addr < cache->len && 8 <= cache->len - addr);
|
||||
if (likely(cache->ptr)) {
|
||||
ST_P(q)(cache->ptr + addr, val);
|
||||
} else {
|
||||
ADDRESS_SPACE_ST_CACHED_SLOW(q)(cache, addr, val, attrs, result);
|
||||
}
|
||||
}
|
||||
|
||||
#undef ADDRESS_SPACE_ST_CACHED
|
||||
#undef ADDRESS_SPACE_ST_CACHED_SLOW
|
||||
#undef ST_P
|
||||
|
||||
#undef ENDIANNESS
|
147
include/exec/memory_ldst_phys.inc.h
Normal file
147
include/exec/memory_ldst_phys.inc.h
Normal file
@ -0,0 +1,147 @@
|
||||
/*
|
||||
* Physical memory access templates
|
||||
*
|
||||
* Copyright (c) 2003 Fabrice Bellard
|
||||
* Copyright (c) 2015 Linaro, Inc.
|
||||
* Copyright (c) 2016 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifdef TARGET_ENDIANNESS
|
||||
static inline uint32_t glue(ldl_phys, SUFFIX)(ARG1_DECL, hwaddr addr)
|
||||
{
|
||||
return glue(address_space_ldl, SUFFIX)(ARG1, addr,
|
||||
MEMTXATTRS_UNSPECIFIED, NULL);
|
||||
}
|
||||
|
||||
static inline uint64_t glue(ldq_phys, SUFFIX)(ARG1_DECL, hwaddr addr)
|
||||
{
|
||||
return glue(address_space_ldq, SUFFIX)(ARG1, addr,
|
||||
MEMTXATTRS_UNSPECIFIED, NULL);
|
||||
}
|
||||
|
||||
static inline uint32_t glue(lduw_phys, SUFFIX)(ARG1_DECL, hwaddr addr)
|
||||
{
|
||||
return glue(address_space_lduw, SUFFIX)(ARG1, addr,
|
||||
MEMTXATTRS_UNSPECIFIED, NULL);
|
||||
}
|
||||
|
||||
static inline void glue(stl_phys, SUFFIX)(ARG1_DECL, hwaddr addr, uint32_t val)
|
||||
{
|
||||
glue(address_space_stl, SUFFIX)(ARG1, addr, val,
|
||||
MEMTXATTRS_UNSPECIFIED, NULL);
|
||||
}
|
||||
|
||||
static inline void glue(stw_phys, SUFFIX)(ARG1_DECL, hwaddr addr, uint32_t val)
|
||||
{
|
||||
glue(address_space_stw, SUFFIX)(ARG1, addr, val,
|
||||
MEMTXATTRS_UNSPECIFIED, NULL);
|
||||
}
|
||||
|
||||
static inline void glue(stq_phys, SUFFIX)(ARG1_DECL, hwaddr addr, uint64_t val)
|
||||
{
|
||||
glue(address_space_stq, SUFFIX)(ARG1, addr, val,
|
||||
MEMTXATTRS_UNSPECIFIED, NULL);
|
||||
}
|
||||
#else
|
||||
static inline uint32_t glue(ldl_le_phys, SUFFIX)(ARG1_DECL, hwaddr addr)
|
||||
{
|
||||
return glue(address_space_ldl_le, SUFFIX)(ARG1, addr,
|
||||
MEMTXATTRS_UNSPECIFIED, NULL);
|
||||
}
|
||||
|
||||
static inline uint32_t glue(ldl_be_phys, SUFFIX)(ARG1_DECL, hwaddr addr)
|
||||
{
|
||||
return glue(address_space_ldl_be, SUFFIX)(ARG1, addr,
|
||||
MEMTXATTRS_UNSPECIFIED, NULL);
|
||||
}
|
||||
|
||||
static inline uint64_t glue(ldq_le_phys, SUFFIX)(ARG1_DECL, hwaddr addr)
|
||||
{
|
||||
return glue(address_space_ldq_le, SUFFIX)(ARG1, addr,
|
||||
MEMTXATTRS_UNSPECIFIED, NULL);
|
||||
}
|
||||
|
||||
static inline uint64_t glue(ldq_be_phys, SUFFIX)(ARG1_DECL, hwaddr addr)
|
||||
{
|
||||
return glue(address_space_ldq_be, SUFFIX)(ARG1, addr,
|
||||
MEMTXATTRS_UNSPECIFIED, NULL);
|
||||
}
|
||||
|
||||
static inline uint32_t glue(ldub_phys, SUFFIX)(ARG1_DECL, hwaddr addr)
|
||||
{
|
||||
return glue(address_space_ldub, SUFFIX)(ARG1, addr,
|
||||
MEMTXATTRS_UNSPECIFIED, NULL);
|
||||
}
|
||||
|
||||
static inline uint32_t glue(lduw_le_phys, SUFFIX)(ARG1_DECL, hwaddr addr)
|
||||
{
|
||||
return glue(address_space_lduw_le, SUFFIX)(ARG1, addr,
|
||||
MEMTXATTRS_UNSPECIFIED, NULL);
|
||||
}
|
||||
|
||||
static inline uint32_t glue(lduw_be_phys, SUFFIX)(ARG1_DECL, hwaddr addr)
|
||||
{
|
||||
return glue(address_space_lduw_be, SUFFIX)(ARG1, addr,
|
||||
MEMTXATTRS_UNSPECIFIED, NULL);
|
||||
}
|
||||
|
||||
static inline void glue(stl_le_phys, SUFFIX)(ARG1_DECL, hwaddr addr, uint32_t val)
|
||||
{
|
||||
glue(address_space_stl_le, SUFFIX)(ARG1, addr, val,
|
||||
MEMTXATTRS_UNSPECIFIED, NULL);
|
||||
}
|
||||
|
||||
static inline void glue(stl_be_phys, SUFFIX)(ARG1_DECL, hwaddr addr, uint32_t val)
|
||||
{
|
||||
glue(address_space_stl_be, SUFFIX)(ARG1, addr, val,
|
||||
MEMTXATTRS_UNSPECIFIED, NULL);
|
||||
}
|
||||
|
||||
static inline void glue(stb_phys, SUFFIX)(ARG1_DECL, hwaddr addr, uint32_t val)
|
||||
{
|
||||
glue(address_space_stb, SUFFIX)(ARG1, addr, val,
|
||||
MEMTXATTRS_UNSPECIFIED, NULL);
|
||||
}
|
||||
|
||||
static inline void glue(stw_le_phys, SUFFIX)(ARG1_DECL, hwaddr addr, uint32_t val)
|
||||
{
|
||||
glue(address_space_stw_le, SUFFIX)(ARG1, addr, val,
|
||||
MEMTXATTRS_UNSPECIFIED, NULL);
|
||||
}
|
||||
|
||||
static inline void glue(stw_be_phys, SUFFIX)(ARG1_DECL, hwaddr addr, uint32_t val)
|
||||
{
|
||||
glue(address_space_stw_be, SUFFIX)(ARG1, addr, val,
|
||||
MEMTXATTRS_UNSPECIFIED, NULL);
|
||||
}
|
||||
|
||||
static inline void glue(stq_le_phys, SUFFIX)(ARG1_DECL, hwaddr addr, uint64_t val)
|
||||
{
|
||||
glue(address_space_stq_le, SUFFIX)(ARG1, addr, val,
|
||||
MEMTXATTRS_UNSPECIFIED, NULL);
|
||||
}
|
||||
|
||||
static inline void glue(stq_be_phys, SUFFIX)(ARG1_DECL, hwaddr addr, uint64_t val)
|
||||
{
|
||||
glue(address_space_stq_be, SUFFIX)(ARG1, addr, val,
|
||||
MEMTXATTRS_UNSPECIFIED, NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
#undef ARG1_DECL
|
||||
#undef ARG1
|
||||
#undef SUFFIX
|
||||
#undef TARGET_ENDIANNESS
|
@ -137,7 +137,7 @@ char *qemu_find_file(int type, const char *name);
|
||||
/* OS specific functions */
|
||||
void os_setup_early_signal_handling(void);
|
||||
char *os_find_datadir(void);
|
||||
void os_parse_cmd_args(int index, const char *optarg);
|
||||
int os_parse_cmd_args(int index, const char *optarg);
|
||||
|
||||
#include "qemu/module.h"
|
||||
|
||||
|
@ -28,8 +28,7 @@
|
||||
|
||||
#include "qemu/queue.h"
|
||||
|
||||
const char *get_opt_name(char *buf, int buf_size, const char *p, char delim);
|
||||
const char *get_opt_value(char *buf, int buf_size, const char *p);
|
||||
const char *get_opt_value(const char *p, char **value);
|
||||
|
||||
void parse_option_size(const char *name, const char *value,
|
||||
uint64_t *ret, Error **errp);
|
||||
|
@ -1302,6 +1302,7 @@ Object *object_get_internal_root(void);
|
||||
*
|
||||
* Returns: The final component in the object's canonical path. The canonical
|
||||
* path is the path within the composition tree starting from the root.
|
||||
* %NULL if the object doesn't have a parent (and thus a canonical path).
|
||||
*/
|
||||
gchar *object_get_canonical_path_component(Object *obj);
|
||||
|
||||
|
@ -52,7 +52,6 @@ struct HostMemoryBackend {
|
||||
Object parent;
|
||||
|
||||
/* protected */
|
||||
char *id;
|
||||
uint64_t size;
|
||||
bool merge, dump;
|
||||
bool prealloc, force_prealloc, is_mapped, share;
|
||||
|
4
memory.c
4
memory.c
@ -298,7 +298,7 @@ static bool flatview_ref(FlatView *view)
|
||||
return atomic_fetch_inc_nonzero(&view->ref) > 0;
|
||||
}
|
||||
|
||||
static void flatview_unref(FlatView *view)
|
||||
void flatview_unref(FlatView *view)
|
||||
{
|
||||
if (atomic_fetch_dec(&view->ref) == 1) {
|
||||
trace_flatview_destroy_rcu(view, view->root);
|
||||
@ -822,7 +822,7 @@ static void address_space_add_del_ioeventfds(AddressSpace *as,
|
||||
}
|
||||
}
|
||||
|
||||
static FlatView *address_space_get_flatview(AddressSpace *as)
|
||||
FlatView *address_space_get_flatview(AddressSpace *as)
|
||||
{
|
||||
FlatView *view;
|
||||
|
||||
|
@ -95,24 +95,6 @@ uint32_t glue(address_space_ldl_be, SUFFIX)(ARG1_DECL,
|
||||
DEVICE_BIG_ENDIAN);
|
||||
}
|
||||
|
||||
uint32_t glue(ldl_phys, SUFFIX)(ARG1_DECL, hwaddr addr)
|
||||
{
|
||||
return glue(address_space_ldl, SUFFIX)(ARG1, addr,
|
||||
MEMTXATTRS_UNSPECIFIED, NULL);
|
||||
}
|
||||
|
||||
uint32_t glue(ldl_le_phys, SUFFIX)(ARG1_DECL, hwaddr addr)
|
||||
{
|
||||
return glue(address_space_ldl_le, SUFFIX)(ARG1, addr,
|
||||
MEMTXATTRS_UNSPECIFIED, NULL);
|
||||
}
|
||||
|
||||
uint32_t glue(ldl_be_phys, SUFFIX)(ARG1_DECL, hwaddr addr)
|
||||
{
|
||||
return glue(address_space_ldl_be, SUFFIX)(ARG1, addr,
|
||||
MEMTXATTRS_UNSPECIFIED, NULL);
|
||||
}
|
||||
|
||||
/* warning: addr must be aligned */
|
||||
static inline uint64_t glue(address_space_ldq_internal, SUFFIX)(ARG1_DECL,
|
||||
hwaddr addr, MemTxAttrs attrs, MemTxResult *result,
|
||||
@ -189,24 +171,6 @@ uint64_t glue(address_space_ldq_be, SUFFIX)(ARG1_DECL,
|
||||
DEVICE_BIG_ENDIAN);
|
||||
}
|
||||
|
||||
uint64_t glue(ldq_phys, SUFFIX)(ARG1_DECL, hwaddr addr)
|
||||
{
|
||||
return glue(address_space_ldq, SUFFIX)(ARG1, addr,
|
||||
MEMTXATTRS_UNSPECIFIED, NULL);
|
||||
}
|
||||
|
||||
uint64_t glue(ldq_le_phys, SUFFIX)(ARG1_DECL, hwaddr addr)
|
||||
{
|
||||
return glue(address_space_ldq_le, SUFFIX)(ARG1, addr,
|
||||
MEMTXATTRS_UNSPECIFIED, NULL);
|
||||
}
|
||||
|
||||
uint64_t glue(ldq_be_phys, SUFFIX)(ARG1_DECL, hwaddr addr)
|
||||
{
|
||||
return glue(address_space_ldq_be, SUFFIX)(ARG1, addr,
|
||||
MEMTXATTRS_UNSPECIFIED, NULL);
|
||||
}
|
||||
|
||||
uint32_t glue(address_space_ldub, SUFFIX)(ARG1_DECL,
|
||||
hwaddr addr, MemTxAttrs attrs, MemTxResult *result)
|
||||
{
|
||||
@ -241,12 +205,6 @@ uint32_t glue(address_space_ldub, SUFFIX)(ARG1_DECL,
|
||||
return val;
|
||||
}
|
||||
|
||||
uint32_t glue(ldub_phys, SUFFIX)(ARG1_DECL, hwaddr addr)
|
||||
{
|
||||
return glue(address_space_ldub, SUFFIX)(ARG1, addr,
|
||||
MEMTXATTRS_UNSPECIFIED, NULL);
|
||||
}
|
||||
|
||||
/* warning: addr must be aligned */
|
||||
static inline uint32_t glue(address_space_lduw_internal, SUFFIX)(ARG1_DECL,
|
||||
hwaddr addr, MemTxAttrs attrs, MemTxResult *result,
|
||||
@ -323,24 +281,6 @@ uint32_t glue(address_space_lduw_be, SUFFIX)(ARG1_DECL,
|
||||
DEVICE_BIG_ENDIAN);
|
||||
}
|
||||
|
||||
uint32_t glue(lduw_phys, SUFFIX)(ARG1_DECL, hwaddr addr)
|
||||
{
|
||||
return glue(address_space_lduw, SUFFIX)(ARG1, addr,
|
||||
MEMTXATTRS_UNSPECIFIED, NULL);
|
||||
}
|
||||
|
||||
uint32_t glue(lduw_le_phys, SUFFIX)(ARG1_DECL, hwaddr addr)
|
||||
{
|
||||
return glue(address_space_lduw_le, SUFFIX)(ARG1, addr,
|
||||
MEMTXATTRS_UNSPECIFIED, NULL);
|
||||
}
|
||||
|
||||
uint32_t glue(lduw_be_phys, SUFFIX)(ARG1_DECL, hwaddr addr)
|
||||
{
|
||||
return glue(address_space_lduw_be, SUFFIX)(ARG1, addr,
|
||||
MEMTXATTRS_UNSPECIFIED, NULL);
|
||||
}
|
||||
|
||||
/* warning: addr must be aligned. The ram page is not masked as dirty
|
||||
and the code inside is not invalidated. It is useful if the dirty
|
||||
bits are used to track modified PTEs */
|
||||
@ -380,12 +320,6 @@ void glue(address_space_stl_notdirty, SUFFIX)(ARG1_DECL,
|
||||
RCU_READ_UNLOCK();
|
||||
}
|
||||
|
||||
void glue(stl_phys_notdirty, SUFFIX)(ARG1_DECL, hwaddr addr, uint32_t val)
|
||||
{
|
||||
glue(address_space_stl_notdirty, SUFFIX)(ARG1, addr, val,
|
||||
MEMTXATTRS_UNSPECIFIED, NULL);
|
||||
}
|
||||
|
||||
/* warning: addr must be aligned */
|
||||
static inline void glue(address_space_stl_internal, SUFFIX)(ARG1_DECL,
|
||||
hwaddr addr, uint32_t val, MemTxAttrs attrs,
|
||||
@ -460,24 +394,6 @@ void glue(address_space_stl_be, SUFFIX)(ARG1_DECL,
|
||||
result, DEVICE_BIG_ENDIAN);
|
||||
}
|
||||
|
||||
void glue(stl_phys, SUFFIX)(ARG1_DECL, hwaddr addr, uint32_t val)
|
||||
{
|
||||
glue(address_space_stl, SUFFIX)(ARG1, addr, val,
|
||||
MEMTXATTRS_UNSPECIFIED, NULL);
|
||||
}
|
||||
|
||||
void glue(stl_le_phys, SUFFIX)(ARG1_DECL, hwaddr addr, uint32_t val)
|
||||
{
|
||||
glue(address_space_stl_le, SUFFIX)(ARG1, addr, val,
|
||||
MEMTXATTRS_UNSPECIFIED, NULL);
|
||||
}
|
||||
|
||||
void glue(stl_be_phys, SUFFIX)(ARG1_DECL, hwaddr addr, uint32_t val)
|
||||
{
|
||||
glue(address_space_stl_be, SUFFIX)(ARG1, addr, val,
|
||||
MEMTXATTRS_UNSPECIFIED, NULL);
|
||||
}
|
||||
|
||||
void glue(address_space_stb, SUFFIX)(ARG1_DECL,
|
||||
hwaddr addr, uint32_t val, MemTxAttrs attrs, MemTxResult *result)
|
||||
{
|
||||
@ -509,12 +425,6 @@ void glue(address_space_stb, SUFFIX)(ARG1_DECL,
|
||||
RCU_READ_UNLOCK();
|
||||
}
|
||||
|
||||
void glue(stb_phys, SUFFIX)(ARG1_DECL, hwaddr addr, uint32_t val)
|
||||
{
|
||||
glue(address_space_stb, SUFFIX)(ARG1, addr, val,
|
||||
MEMTXATTRS_UNSPECIFIED, NULL);
|
||||
}
|
||||
|
||||
/* warning: addr must be aligned */
|
||||
static inline void glue(address_space_stw_internal, SUFFIX)(ARG1_DECL,
|
||||
hwaddr addr, uint32_t val, MemTxAttrs attrs,
|
||||
@ -589,24 +499,6 @@ void glue(address_space_stw_be, SUFFIX)(ARG1_DECL,
|
||||
DEVICE_BIG_ENDIAN);
|
||||
}
|
||||
|
||||
void glue(stw_phys, SUFFIX)(ARG1_DECL, hwaddr addr, uint32_t val)
|
||||
{
|
||||
glue(address_space_stw, SUFFIX)(ARG1, addr, val,
|
||||
MEMTXATTRS_UNSPECIFIED, NULL);
|
||||
}
|
||||
|
||||
void glue(stw_le_phys, SUFFIX)(ARG1_DECL, hwaddr addr, uint32_t val)
|
||||
{
|
||||
glue(address_space_stw_le, SUFFIX)(ARG1, addr, val,
|
||||
MEMTXATTRS_UNSPECIFIED, NULL);
|
||||
}
|
||||
|
||||
void glue(stw_be_phys, SUFFIX)(ARG1_DECL, hwaddr addr, uint32_t val)
|
||||
{
|
||||
glue(address_space_stw_be, SUFFIX)(ARG1, addr, val,
|
||||
MEMTXATTRS_UNSPECIFIED, NULL);
|
||||
}
|
||||
|
||||
static void glue(address_space_stq_internal, SUFFIX)(ARG1_DECL,
|
||||
hwaddr addr, uint64_t val, MemTxAttrs attrs,
|
||||
MemTxResult *result, enum device_endian endian)
|
||||
@ -680,24 +572,6 @@ void glue(address_space_stq_be, SUFFIX)(ARG1_DECL,
|
||||
DEVICE_BIG_ENDIAN);
|
||||
}
|
||||
|
||||
void glue(stq_phys, SUFFIX)(ARG1_DECL, hwaddr addr, uint64_t val)
|
||||
{
|
||||
glue(address_space_stq, SUFFIX)(ARG1, addr, val,
|
||||
MEMTXATTRS_UNSPECIFIED, NULL);
|
||||
}
|
||||
|
||||
void glue(stq_le_phys, SUFFIX)(ARG1_DECL, hwaddr addr, uint64_t val)
|
||||
{
|
||||
glue(address_space_stq_le, SUFFIX)(ARG1, addr, val,
|
||||
MEMTXATTRS_UNSPECIFIED, NULL);
|
||||
}
|
||||
|
||||
void glue(stq_be_phys, SUFFIX)(ARG1_DECL, hwaddr addr, uint64_t val)
|
||||
{
|
||||
glue(address_space_stq_be, SUFFIX)(ARG1, addr, val,
|
||||
MEMTXATTRS_UNSPECIFIED, NULL);
|
||||
}
|
||||
|
||||
#undef ARG1_DECL
|
||||
#undef ARG1
|
||||
#undef SUFFIX
|
||||
|
2
numa.c
2
numa.c
@ -580,7 +580,7 @@ static int query_memdev(Object *obj, void *opaque)
|
||||
|
||||
m->value = g_malloc0(sizeof(*m->value));
|
||||
|
||||
m->value->id = object_property_get_str(obj, "id", NULL);
|
||||
m->value->id = object_get_canonical_path_component(obj);
|
||||
m->value->has_id = !!m->value->id;
|
||||
|
||||
m->value->size = object_property_get_uint(obj, "size",
|
||||
|
@ -165,7 +165,7 @@ static bool os_parse_runas_uid_gid(const char *optarg)
|
||||
* Parse OS specific command line options.
|
||||
* return 0 if option handled, -1 otherwise
|
||||
*/
|
||||
void os_parse_cmd_args(int index, const char *optarg)
|
||||
int os_parse_cmd_args(int index, const char *optarg)
|
||||
{
|
||||
switch (index) {
|
||||
#ifdef CONFIG_SLIRP
|
||||
@ -199,7 +199,11 @@ void os_parse_cmd_args(int index, const char *optarg)
|
||||
fips_set_state(true);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void change_process_uid(void)
|
||||
|
@ -93,9 +93,9 @@ void os_set_line_buffering(void)
|
||||
* Parse OS specific command line options.
|
||||
* return 0 if option handled, -1 otherwise
|
||||
*/
|
||||
void os_parse_cmd_args(int index, const char *optarg)
|
||||
int os_parse_cmd_args(int index, const char *optarg)
|
||||
{
|
||||
return;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int qemu_create_pidfile(const char *filename)
|
||||
|
@ -39,6 +39,7 @@
|
||||
* QEMU User space emulator::
|
||||
* Implementation notes::
|
||||
* Deprecated features::
|
||||
* Supported build platforms::
|
||||
* License::
|
||||
* Index::
|
||||
@end menu
|
||||
@ -2786,16 +2787,6 @@ which is the default.
|
||||
|
||||
@section System emulator command line arguments
|
||||
|
||||
@subsection -no-kvm-pit-reinjection (since 1.3.0)
|
||||
|
||||
The ``-no-kvm-pit-reinjection'' argument is now a
|
||||
synonym for setting ``-global kvm-pit.lost_tick_policy=discard''.
|
||||
|
||||
@subsection -no-kvm-irqchip (since 1.3.0)
|
||||
|
||||
The ``-no-kvm-irqchip'' argument is now a synonym for
|
||||
setting ``-machine kernel_irqchip=off''.
|
||||
|
||||
@subsection -no-kvm (since 1.3.0)
|
||||
|
||||
The ``-no-kvm'' argument is now a synonym for setting
|
||||
@ -2931,6 +2922,11 @@ The @code{-localtime} option has been replaced by @code{-rtc base=localtime}.
|
||||
|
||||
The @code{-startdate} option has been replaced by @code{-rtc base=@var{date}}.
|
||||
|
||||
@subsection -virtioconsole (since 2.13.0)
|
||||
|
||||
Option @option{-virtioconsole} has been replaced by
|
||||
@option{-device virtconsole}.
|
||||
|
||||
@section qemu-img command line arguments
|
||||
|
||||
@subsection convert -s (since 2.0.0)
|
||||
@ -2981,6 +2977,73 @@ The ``xlnx-zcu102'' machine has the same features and capabilites in QEMU.
|
||||
In order to prevent QEMU from automatically opening an image's backing
|
||||
chain, use ``"backing": null'' instead.
|
||||
|
||||
@node Supported build platforms
|
||||
@appendix Supported build platforms
|
||||
|
||||
QEMU aims to support building and executing on multiple host OS platforms.
|
||||
This appendix outlines which platforms are the major build targets. These
|
||||
platforms are used as the basis for deciding upon the minimum required
|
||||
versions of 3rd party software QEMU depends on. The supported platforms
|
||||
are the targets for automated testing performed by the project when patches
|
||||
are submitted for review, and tested before and after merge.
|
||||
|
||||
If a platform is not listed here, it does not imply that QEMU won't work.
|
||||
If an unlisted platform has comparable software versions to a listed platform,
|
||||
there is every expectation that it will work. Bug reports are welcome for
|
||||
problems encountered on unlisted platforms unless they are clearly older
|
||||
vintage than what is described here.
|
||||
|
||||
Note that when considering software versions shipped in distros as support
|
||||
targets, QEMU considers only the version number, and assumes the features in
|
||||
that distro match the upstream release with the same version. In other words,
|
||||
if a distro backports extra features to the software in their distro, QEMU
|
||||
upstream code will not add explicit support for those backports, unless the
|
||||
feature is auto-detectable in a manner that works for the upstream releases
|
||||
too.
|
||||
|
||||
The Repology site @url{https://repology.org} is a useful resource to identify
|
||||
currently shipped versions of software in various operating systems, though
|
||||
it does not cover all distros listed below.
|
||||
|
||||
@section Linux OS
|
||||
|
||||
For distributions with frequent, short-lifetime releases, the project will
|
||||
aim to support all versions that are not end of life by their respective
|
||||
vendors. For the purposes of identifying supported software versions, the
|
||||
project will look at Fedora, Ubuntu, and openSUSE distros. Other short-
|
||||
lifetime distros will be assumed to ship similar software versions.
|
||||
|
||||
For distributions with long-lifetime releases, the project will aim to support
|
||||
the most recent major version at all times. Support for the previous major
|
||||
version will be dropped 2 years after the new major version is released. For
|
||||
the purposes of identifying supported software versions, the project will look
|
||||
at RHEL, Debian, Ubuntu LTS, and SLES distros. Other long-lifetime distros will
|
||||
be assumed to ship similar software versions.
|
||||
|
||||
@section Windows
|
||||
|
||||
The project supports building with current versions of the MinGW toolchain,
|
||||
hosted on Linux.
|
||||
|
||||
@section macOS
|
||||
|
||||
The project supports building with the two most recent versions of macOS, with
|
||||
the current homebrew package set available.
|
||||
|
||||
@section FreeBSD
|
||||
|
||||
The project aims to support the all the versions which are not end of life.
|
||||
|
||||
@section NetBSD
|
||||
|
||||
The project aims to support the most recent major version at all times. Support
|
||||
for the previous major version will be dropped 2 years after the new major
|
||||
version is released.
|
||||
|
||||
@section OpenBSD
|
||||
|
||||
The project aims to support the all the versions which are not end of life.
|
||||
|
||||
@node License
|
||||
@appendix License
|
||||
|
||||
|
@ -3675,10 +3675,7 @@ STEXI
|
||||
@item -virtioconsole @var{c}
|
||||
@findex -virtioconsole
|
||||
Set virtio console.
|
||||
|
||||
This option is maintained for backward compatibility.
|
||||
|
||||
Please use @code{-device virtconsole} for the new way of invocation.
|
||||
This option is deprecated, please use @option{-device virtconsole} instead.
|
||||
ETEXI
|
||||
|
||||
DEF("show-cursor", 0, QEMU_OPTION_show_cursor, \
|
||||
@ -3917,16 +3914,6 @@ ETEXI
|
||||
HXCOMM Deprecated by -machine accel=tcg property
|
||||
DEF("no-kvm", 0, QEMU_OPTION_no_kvm, "", QEMU_ARCH_I386)
|
||||
|
||||
HXCOMM Deprecated by kvm-pit driver properties
|
||||
DEF("no-kvm-pit-reinjection", 0, QEMU_OPTION_no_kvm_pit_reinjection,
|
||||
"", QEMU_ARCH_I386)
|
||||
|
||||
HXCOMM Deprecated by -machine kernel_irqchip=on|off property
|
||||
DEF("no-kvm-irqchip", 0, QEMU_OPTION_no_kvm_irqchip, "", QEMU_ARCH_I386)
|
||||
|
||||
HXCOMM Deprecated (ignored)
|
||||
DEF("tdf", 0, QEMU_OPTION_tdf,"", QEMU_ARCH_ALL)
|
||||
|
||||
DEF("msg", HAS_ARG, QEMU_OPTION_msg,
|
||||
"-msg timestamp[=on|off]\n"
|
||||
" change the format of messages\n"
|
||||
|
@ -1644,8 +1644,9 @@ gchar *object_get_canonical_path_component(Object *obj)
|
||||
ObjectProperty *prop = NULL;
|
||||
GHashTableIter iter;
|
||||
|
||||
g_assert(obj);
|
||||
g_assert(obj->parent != NULL);
|
||||
if (obj->parent == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
g_hash_table_iter_init(&iter, obj->parent->properties);
|
||||
while (g_hash_table_iter_next(&iter, NULL, (gpointer *)&prop)) {
|
||||
|
@ -65,12 +65,6 @@ Object *user_creatable_add_type(const char *type, const char *id,
|
||||
|
||||
assert(qdict);
|
||||
obj = object_new(type);
|
||||
if (object_property_find(obj, "id", NULL)) {
|
||||
object_property_set_str(obj, id, "id", &local_err);
|
||||
if (local_err) {
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
visit_start_struct(v, NULL, NULL, 0, &local_err);
|
||||
if (local_err) {
|
||||
goto out;
|
||||
|
@ -73,7 +73,7 @@ expand-objs = $(strip $(sort $(filter %.o,$1)) \
|
||||
# must link with the C++ compiler, not the plain C compiler.
|
||||
LINKPROG = $(or $(CXX),$(CC))
|
||||
|
||||
LINK = $(call quiet-command, $(LINKPROG) $(QEMU_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ \
|
||||
LINK = $(call quiet-command, $(LINKPROG) $(QEMU_LDFLAGS) $(QEMU_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ \
|
||||
$(call process-archive-undefs, $1) \
|
||||
$(version-obj-y) $(call extract-libs,$1) $(LIBS),"LINK","$(TARGET_DIR)$@")
|
||||
|
||||
|
@ -265,8 +265,36 @@ our @typeList = (
|
||||
qr{${Ident}_handler_fn},
|
||||
qr{target_(?:u)?long},
|
||||
qr{hwaddr},
|
||||
# external libraries
|
||||
qr{xml${Ident}},
|
||||
qr{xendevicemodel_handle},
|
||||
# Glib definitions
|
||||
qr{gchar},
|
||||
qr{gshort},
|
||||
qr{glong},
|
||||
qr{gint},
|
||||
qr{gboolean},
|
||||
qr{guchar},
|
||||
qr{gushort},
|
||||
qr{gulong},
|
||||
qr{guint},
|
||||
qr{gfloat},
|
||||
qr{gdouble},
|
||||
qr{gpointer},
|
||||
qr{gconstpointer},
|
||||
qr{gint8},
|
||||
qr{guint8},
|
||||
qr{gint16},
|
||||
qr{guint16},
|
||||
qr{gint32},
|
||||
qr{guint32},
|
||||
qr{gint64},
|
||||
qr{guint64},
|
||||
qr{gsize},
|
||||
qr{gssize},
|
||||
qr{goffset},
|
||||
qr{gintptr},
|
||||
qr{guintptr},
|
||||
);
|
||||
|
||||
# This can be modified by sub possible. Since it can be empty, be careful
|
||||
|
@ -118,9 +118,6 @@ for arch in $ARCHLIST; do
|
||||
cp "$tmpdir/include/asm/unistd-common.h" "$output/linux-headers/asm-arm/"
|
||||
fi
|
||||
if [ $arch = x86 ]; then
|
||||
cat <<-EOF >"$output/include/standard-headers/asm-x86/hyperv.h"
|
||||
/* this is a temporary placeholder until kvm_para.h stops including it */
|
||||
EOF
|
||||
cp "$tmpdir/include/asm/unistd_32.h" "$output/linux-headers/asm-x86/"
|
||||
cp "$tmpdir/include/asm/unistd_x32.h" "$output/linux-headers/asm-x86/"
|
||||
cp "$tmpdir/include/asm/unistd_64.h" "$output/linux-headers/asm-x86/"
|
||||
@ -144,9 +141,6 @@ else
|
||||
cp "$linux/COPYING" "$output/linux-headers"
|
||||
fi
|
||||
|
||||
cat <<EOF >$output/linux-headers/asm-x86/hyperv.h
|
||||
#include "standard-headers/asm-x86/hyperv.h"
|
||||
EOF
|
||||
cat <<EOF >$output/linux-headers/linux/virtio_config.h
|
||||
#include "standard-headers/linux/virtio_config.h"
|
||||
EOF
|
||||
|
@ -3047,7 +3047,7 @@ static unsigned int crisv32_decoder(CPUCRISState *env, DisasContext *dc)
|
||||
return insn_len;
|
||||
}
|
||||
|
||||
#include "translate_v10.c"
|
||||
#include "translate_v10.inc.c"
|
||||
|
||||
/*
|
||||
* Delay slots on QEMU/CRIS.
|
||||
|
@ -416,7 +416,8 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = {
|
||||
NULL /* hv_vpindex_access */, NULL /* hv_msr_reset_access */,
|
||||
NULL /* hv_msr_stats_access */, NULL /* hv_reftsc_access */,
|
||||
NULL /* hv_msr_idle_access */, NULL /* hv_msr_frequency_access */,
|
||||
NULL, NULL, NULL, NULL,
|
||||
NULL /* hv_msr_debug_access */, NULL /* hv_msr_reenlightenment_access */,
|
||||
NULL, NULL,
|
||||
NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL,
|
||||
@ -4770,6 +4771,7 @@ static Property x86_cpu_properties[] = {
|
||||
DEFINE_PROP_BOOL("hv-synic", X86CPU, hyperv_synic, false),
|
||||
DEFINE_PROP_BOOL("hv-stimer", X86CPU, hyperv_stimer, false),
|
||||
DEFINE_PROP_BOOL("hv-frequencies", X86CPU, hyperv_frequencies, false),
|
||||
DEFINE_PROP_BOOL("hv-reenlightenment", X86CPU, hyperv_reenlightenment, false),
|
||||
DEFINE_PROP_BOOL("check", X86CPU, check_cpuid, true),
|
||||
DEFINE_PROP_BOOL("enforce", X86CPU, enforce_cpuid, false),
|
||||
DEFINE_PROP_BOOL("kvm", X86CPU, expose_kvm, true),
|
||||
|
@ -1174,6 +1174,9 @@ typedef struct CPUX86State {
|
||||
uint64_t msr_hv_synic_sint[HV_SINT_COUNT];
|
||||
uint64_t msr_hv_stimer_config[HV_STIMER_COUNT];
|
||||
uint64_t msr_hv_stimer_count[HV_STIMER_COUNT];
|
||||
uint64_t msr_hv_reenlightenment_control;
|
||||
uint64_t msr_hv_tsc_emulation_control;
|
||||
uint64_t msr_hv_tsc_emulation_status;
|
||||
|
||||
uint64_t msr_rtit_ctrl;
|
||||
uint64_t msr_rtit_status;
|
||||
@ -1297,6 +1300,7 @@ struct X86CPU {
|
||||
bool hyperv_synic;
|
||||
bool hyperv_stimer;
|
||||
bool hyperv_frequencies;
|
||||
bool hyperv_reenlightenment;
|
||||
bool check_cpuid;
|
||||
bool enforce_cpuid;
|
||||
bool expose_kvm;
|
||||
|
@ -35,7 +35,7 @@
|
||||
#define HV_RESET_AVAILABLE (1u << 7)
|
||||
#define HV_REFERENCE_TSC_AVAILABLE (1u << 9)
|
||||
#define HV_ACCESS_FREQUENCY_MSRS (1u << 11)
|
||||
|
||||
#define HV_ACCESS_REENLIGHTENMENTS_CONTROL (1u << 13)
|
||||
|
||||
/*
|
||||
* HV_CPUID_FEATURES.EDX bits
|
||||
@ -129,6 +129,13 @@
|
||||
#define HV_X64_MSR_CRASH_CTL 0x40000105
|
||||
#define HV_CRASH_CTL_NOTIFY (1ull << 63)
|
||||
|
||||
/*
|
||||
* Reenlightenment notification MSRs
|
||||
*/
|
||||
#define HV_X64_MSR_REENLIGHTENMENT_CONTROL 0x40000106
|
||||
#define HV_X64_MSR_TSC_EMULATION_CONTROL 0x40000107
|
||||
#define HV_X64_MSR_TSC_EMULATION_STATUS 0x40000108
|
||||
|
||||
/*
|
||||
* Hypercall status code
|
||||
*/
|
||||
|
@ -90,6 +90,7 @@ static bool has_msr_hv_runtime;
|
||||
static bool has_msr_hv_synic;
|
||||
static bool has_msr_hv_stimer;
|
||||
static bool has_msr_hv_frequencies;
|
||||
static bool has_msr_hv_reenlightenment;
|
||||
static bool has_msr_xss;
|
||||
static bool has_msr_spec_ctrl;
|
||||
static bool has_msr_smi_count;
|
||||
@ -583,7 +584,8 @@ static bool hyperv_enabled(X86CPU *cpu)
|
||||
cpu->hyperv_vpindex ||
|
||||
cpu->hyperv_runtime ||
|
||||
cpu->hyperv_synic ||
|
||||
cpu->hyperv_stimer);
|
||||
cpu->hyperv_stimer ||
|
||||
cpu->hyperv_reenlightenment);
|
||||
}
|
||||
|
||||
static int kvm_arch_set_tsc_khz(CPUState *cs)
|
||||
@ -669,6 +671,16 @@ static int hyperv_handle_properties(CPUState *cs)
|
||||
}
|
||||
env->features[FEAT_HYPERV_EDX] |= HV_GUEST_CRASH_MSR_AVAILABLE;
|
||||
}
|
||||
if (cpu->hyperv_reenlightenment) {
|
||||
if (!has_msr_hv_reenlightenment) {
|
||||
fprintf(stderr,
|
||||
"Hyper-V Reenlightenment MSRs "
|
||||
"(requested by 'hv-reenlightenment' cpu flag) "
|
||||
"are not supported by kernel\n");
|
||||
return -ENOSYS;
|
||||
}
|
||||
env->features[FEAT_HYPERV_EAX] |= HV_ACCESS_REENLIGHTENMENTS_CONTROL;
|
||||
}
|
||||
env->features[FEAT_HYPERV_EDX] |= HV_CPU_DYNAMIC_PARTITIONING_AVAILABLE;
|
||||
if (cpu->hyperv_reset) {
|
||||
if (!has_msr_hv_reset) {
|
||||
@ -1215,6 +1227,9 @@ static int kvm_get_supported_msrs(KVMState *s)
|
||||
case HV_X64_MSR_TSC_FREQUENCY:
|
||||
has_msr_hv_frequencies = true;
|
||||
break;
|
||||
case HV_X64_MSR_REENLIGHTENMENT_CONTROL:
|
||||
has_msr_hv_reenlightenment = true;
|
||||
break;
|
||||
case MSR_IA32_SPEC_CTRL:
|
||||
has_msr_spec_ctrl = true;
|
||||
break;
|
||||
@ -1778,6 +1793,14 @@ static int kvm_put_msrs(X86CPU *cpu, int level)
|
||||
kvm_msr_entry_add(cpu, HV_X64_MSR_REFERENCE_TSC,
|
||||
env->msr_hv_tsc);
|
||||
}
|
||||
if (cpu->hyperv_reenlightenment) {
|
||||
kvm_msr_entry_add(cpu, HV_X64_MSR_REENLIGHTENMENT_CONTROL,
|
||||
env->msr_hv_reenlightenment_control);
|
||||
kvm_msr_entry_add(cpu, HV_X64_MSR_TSC_EMULATION_CONTROL,
|
||||
env->msr_hv_tsc_emulation_control);
|
||||
kvm_msr_entry_add(cpu, HV_X64_MSR_TSC_EMULATION_STATUS,
|
||||
env->msr_hv_tsc_emulation_status);
|
||||
}
|
||||
}
|
||||
if (cpu->hyperv_vapic) {
|
||||
kvm_msr_entry_add(cpu, HV_X64_MSR_APIC_ASSIST_PAGE,
|
||||
@ -2140,6 +2163,11 @@ static int kvm_get_msrs(X86CPU *cpu)
|
||||
if (cpu->hyperv_time) {
|
||||
kvm_msr_entry_add(cpu, HV_X64_MSR_REFERENCE_TSC, 0);
|
||||
}
|
||||
if (cpu->hyperv_reenlightenment) {
|
||||
kvm_msr_entry_add(cpu, HV_X64_MSR_REENLIGHTENMENT_CONTROL, 0);
|
||||
kvm_msr_entry_add(cpu, HV_X64_MSR_TSC_EMULATION_CONTROL, 0);
|
||||
kvm_msr_entry_add(cpu, HV_X64_MSR_TSC_EMULATION_STATUS, 0);
|
||||
}
|
||||
if (has_msr_hv_crash) {
|
||||
int j;
|
||||
|
||||
@ -2397,6 +2425,15 @@ static int kvm_get_msrs(X86CPU *cpu)
|
||||
env->msr_hv_stimer_count[(index - HV_X64_MSR_STIMER0_COUNT)/2] =
|
||||
msrs[i].data;
|
||||
break;
|
||||
case HV_X64_MSR_REENLIGHTENMENT_CONTROL:
|
||||
env->msr_hv_reenlightenment_control = msrs[i].data;
|
||||
break;
|
||||
case HV_X64_MSR_TSC_EMULATION_CONTROL:
|
||||
env->msr_hv_tsc_emulation_control = msrs[i].data;
|
||||
break;
|
||||
case HV_X64_MSR_TSC_EMULATION_STATUS:
|
||||
env->msr_hv_tsc_emulation_status = msrs[i].data;
|
||||
break;
|
||||
case MSR_MTRRdefType:
|
||||
env->mtrr_deftype = msrs[i].data;
|
||||
break;
|
||||
|
@ -713,6 +713,29 @@ static const VMStateDescription vmstate_msr_hyperv_stimer = {
|
||||
}
|
||||
};
|
||||
|
||||
static bool hyperv_reenlightenment_enable_needed(void *opaque)
|
||||
{
|
||||
X86CPU *cpu = opaque;
|
||||
CPUX86State *env = &cpu->env;
|
||||
|
||||
return env->msr_hv_reenlightenment_control != 0 ||
|
||||
env->msr_hv_tsc_emulation_control != 0 ||
|
||||
env->msr_hv_tsc_emulation_status != 0;
|
||||
}
|
||||
|
||||
static const VMStateDescription vmstate_msr_hyperv_reenlightenment = {
|
||||
.name = "cpu/msr_hyperv_reenlightenment",
|
||||
.version_id = 1,
|
||||
.minimum_version_id = 1,
|
||||
.needed = hyperv_reenlightenment_enable_needed,
|
||||
.fields = (VMStateField[]) {
|
||||
VMSTATE_UINT64(env.msr_hv_reenlightenment_control, X86CPU),
|
||||
VMSTATE_UINT64(env.msr_hv_tsc_emulation_control, X86CPU),
|
||||
VMSTATE_UINT64(env.msr_hv_tsc_emulation_status, X86CPU),
|
||||
VMSTATE_END_OF_LIST()
|
||||
}
|
||||
};
|
||||
|
||||
static bool avx512_needed(void *opaque)
|
||||
{
|
||||
X86CPU *cpu = opaque;
|
||||
@ -1005,6 +1028,7 @@ VMStateDescription vmstate_x86_cpu = {
|
||||
&vmstate_msr_hyperv_runtime,
|
||||
&vmstate_msr_hyperv_synic,
|
||||
&vmstate_msr_hyperv_stimer,
|
||||
&vmstate_msr_hyperv_reenlightenment,
|
||||
&vmstate_avx512,
|
||||
&vmstate_xss,
|
||||
&vmstate_tsc_khz,
|
||||
|
@ -430,7 +430,8 @@ static int
|
||||
sev_get_pdh_info(int fd, guchar **pdh, size_t *pdh_len, guchar **cert_chain,
|
||||
size_t *cert_chain_len)
|
||||
{
|
||||
guchar *pdh_data, *cert_chain_data;
|
||||
guchar *pdh_data = NULL;
|
||||
guchar *cert_chain_data = NULL;
|
||||
struct sev_user_data_pdh_cert_export export = {};
|
||||
int err, r;
|
||||
|
||||
@ -471,8 +472,9 @@ e_free:
|
||||
SevCapability *
|
||||
sev_get_capabilities(void)
|
||||
{
|
||||
SevCapability *cap;
|
||||
guchar *pdh_data, *cert_chain_data;
|
||||
SevCapability *cap = NULL;
|
||||
guchar *pdh_data = NULL;
|
||||
guchar *cert_chain_data = NULL;
|
||||
size_t pdh_len = 0, cert_chain_len = 0;
|
||||
uint32_t ebx;
|
||||
int fd;
|
||||
@ -486,7 +488,7 @@ sev_get_capabilities(void)
|
||||
|
||||
if (sev_get_pdh_info(fd, &pdh_data, &pdh_len,
|
||||
&cert_chain_data, &cert_chain_len)) {
|
||||
return NULL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
cap = g_new0(SevCapability, 1);
|
||||
@ -502,9 +504,9 @@ sev_get_capabilities(void)
|
||||
*/
|
||||
cap->reduced_phys_bits = 1;
|
||||
|
||||
out:
|
||||
g_free(pdh_data);
|
||||
g_free(cert_chain_data);
|
||||
|
||||
close(fd);
|
||||
return cap;
|
||||
}
|
||||
@ -530,7 +532,7 @@ sev_launch_start(SEVState *s)
|
||||
{
|
||||
gsize sz;
|
||||
int ret = 1;
|
||||
int fw_error;
|
||||
int fw_error, rc;
|
||||
QSevGuestInfo *sev = s->sev_info;
|
||||
struct kvm_sev_launch_start *start;
|
||||
guchar *session = NULL, *dh_cert = NULL;
|
||||
@ -543,7 +545,7 @@ sev_launch_start(SEVState *s)
|
||||
&error_abort);
|
||||
if (sev->session_file) {
|
||||
if (sev_read_file_base64(sev->session_file, &session, &sz) < 0) {
|
||||
return 1;
|
||||
goto out;
|
||||
}
|
||||
start->session_uaddr = (unsigned long)session;
|
||||
start->session_len = sz;
|
||||
@ -551,18 +553,18 @@ sev_launch_start(SEVState *s)
|
||||
|
||||
if (sev->dh_cert_file) {
|
||||
if (sev_read_file_base64(sev->dh_cert_file, &dh_cert, &sz) < 0) {
|
||||
return 1;
|
||||
goto out;
|
||||
}
|
||||
start->dh_uaddr = (unsigned long)dh_cert;
|
||||
start->dh_len = sz;
|
||||
}
|
||||
|
||||
trace_kvm_sev_launch_start(start->policy, session, dh_cert);
|
||||
ret = sev_ioctl(s->sev_fd, KVM_SEV_LAUNCH_START, start, &fw_error);
|
||||
if (ret < 0) {
|
||||
rc = sev_ioctl(s->sev_fd, KVM_SEV_LAUNCH_START, start, &fw_error);
|
||||
if (rc < 0) {
|
||||
error_report("%s: LAUNCH_START ret=%d fw_error=%d '%s'",
|
||||
__func__, ret, fw_error, fw_error_to_str(fw_error));
|
||||
return 1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
object_property_set_int(OBJECT(sev), start->handle, "handle",
|
||||
@ -570,12 +572,13 @@ sev_launch_start(SEVState *s)
|
||||
sev_set_guest_state(SEV_STATE_LAUNCH_UPDATE);
|
||||
s->handle = start->handle;
|
||||
s->policy = start->policy;
|
||||
ret = 0;
|
||||
|
||||
out:
|
||||
g_free(start);
|
||||
g_free(session);
|
||||
g_free(dh_cert);
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
@ -712,7 +715,7 @@ sev_guest_init(const char *id)
|
||||
uint32_t host_cbitpos;
|
||||
struct sev_user_data_status status = {};
|
||||
|
||||
s = g_new0(SEVState, 1);
|
||||
sev_state = s = g_new0(SEVState, 1);
|
||||
s->sev_info = lookup_sev_guest_info(id);
|
||||
if (!s->sev_info) {
|
||||
error_report("%s: '%s' is not a valid '%s' object",
|
||||
@ -720,7 +723,6 @@ sev_guest_init(const char *id)
|
||||
goto err;
|
||||
}
|
||||
|
||||
sev_state = s;
|
||||
s->state = SEV_STATE_UNINIT;
|
||||
|
||||
host_cpuid(0x8000001F, 0, NULL, &ebx, NULL, NULL);
|
||||
|
@ -20500,7 +20500,7 @@ void mips_tcg_init(void)
|
||||
"fcr31");
|
||||
}
|
||||
|
||||
#include "translate_init.c"
|
||||
#include "translate_init.inc.c"
|
||||
|
||||
void cpu_mips_realize_env(CPUMIPSState *env)
|
||||
{
|
||||
|
@ -379,7 +379,7 @@ target_ulong helper_divso(CPUPPCState *env, target_ulong arg1,
|
||||
target_ulong helper_602_mfrom(target_ulong arg)
|
||||
{
|
||||
if (likely(arg < 602)) {
|
||||
#include "mfrom_table.c"
|
||||
#include "mfrom_table.inc.c"
|
||||
return mfrom_ROM_table[arg];
|
||||
} else {
|
||||
return 0;
|
||||
|
@ -6991,7 +6991,7 @@ GEN_HANDLER2_E(trechkpt, "trechkpt", 0x1F, 0x0E, 0x1F, 0x03FFF800, \
|
||||
};
|
||||
|
||||
#include "helper_regs.h"
|
||||
#include "translate_init.c"
|
||||
#include "translate_init.inc.c"
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Misc PowerPC helpers */
|
||||
|
@ -18,7 +18,6 @@
|
||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "disas/bfd.h"
|
||||
#include "exec/gdbstub.h"
|
||||
#include "kvm_ppc.h"
|
@ -459,8 +459,6 @@ static void test_opts_parse(void)
|
||||
{
|
||||
Error *err = NULL;
|
||||
QemuOpts *opts;
|
||||
char long_key[129];
|
||||
char *params;
|
||||
|
||||
/* Nothing */
|
||||
opts = qemu_opts_parse(&opts_list_03, "", false, &error_abort);
|
||||
@ -471,22 +469,6 @@ static void test_opts_parse(void)
|
||||
g_assert_cmpuint(opts_count(opts), ==, 1);
|
||||
g_assert_cmpstr(qemu_opt_get(opts, ""), ==, "val");
|
||||
|
||||
/* Long key */
|
||||
memset(long_key, 'a', 127);
|
||||
long_key[127] = 'z';
|
||||
long_key[128] = 0;
|
||||
params = g_strdup_printf("%s=v", long_key);
|
||||
opts = qemu_opts_parse(&opts_list_03, params + 1, NULL, &error_abort);
|
||||
g_assert_cmpuint(opts_count(opts), ==, 1);
|
||||
g_assert_cmpstr(qemu_opt_get(opts, long_key + 1), ==, "v");
|
||||
|
||||
/* Overlong key gets truncated */
|
||||
opts = qemu_opts_parse(&opts_list_03, params, NULL, &error_abort);
|
||||
g_assert(opts_count(opts) == 1);
|
||||
long_key[127] = 0;
|
||||
g_assert_cmpstr(qemu_opt_get(opts, long_key), ==, "v");
|
||||
g_free(params);
|
||||
|
||||
/* Multiple keys, last one wins */
|
||||
opts = qemu_opts_parse(&opts_list_03, "a=1,b=2,,x,a=3",
|
||||
false, &error_abort);
|
||||
|
@ -199,56 +199,56 @@ static void zrle_write_u8(VncState *vs, uint8_t value)
|
||||
|
||||
#define ZRLE_BPP 8
|
||||
#define ZYWRLE_ENDIAN ENDIAN_NO
|
||||
#include "vnc-enc-zrle-template.c"
|
||||
#include "vnc-enc-zrle.inc.c"
|
||||
#undef ZRLE_BPP
|
||||
|
||||
#define ZRLE_BPP 15
|
||||
#undef ZYWRLE_ENDIAN
|
||||
#define ZYWRLE_ENDIAN ENDIAN_LITTLE
|
||||
#include "vnc-enc-zrle-template.c"
|
||||
#include "vnc-enc-zrle.inc.c"
|
||||
|
||||
#undef ZYWRLE_ENDIAN
|
||||
#define ZYWRLE_ENDIAN ENDIAN_BIG
|
||||
#include "vnc-enc-zrle-template.c"
|
||||
#include "vnc-enc-zrle.inc.c"
|
||||
|
||||
#undef ZRLE_BPP
|
||||
#define ZRLE_BPP 16
|
||||
#undef ZYWRLE_ENDIAN
|
||||
#define ZYWRLE_ENDIAN ENDIAN_LITTLE
|
||||
#include "vnc-enc-zrle-template.c"
|
||||
#include "vnc-enc-zrle.inc.c"
|
||||
|
||||
#undef ZYWRLE_ENDIAN
|
||||
#define ZYWRLE_ENDIAN ENDIAN_BIG
|
||||
#include "vnc-enc-zrle-template.c"
|
||||
#include "vnc-enc-zrle.inc.c"
|
||||
|
||||
#undef ZRLE_BPP
|
||||
#define ZRLE_BPP 32
|
||||
#undef ZYWRLE_ENDIAN
|
||||
#define ZYWRLE_ENDIAN ENDIAN_LITTLE
|
||||
#include "vnc-enc-zrle-template.c"
|
||||
#include "vnc-enc-zrle.inc.c"
|
||||
|
||||
#undef ZYWRLE_ENDIAN
|
||||
#define ZYWRLE_ENDIAN ENDIAN_BIG
|
||||
#include "vnc-enc-zrle-template.c"
|
||||
#include "vnc-enc-zrle.inc.c"
|
||||
|
||||
#define ZRLE_COMPACT_PIXEL 24a
|
||||
#undef ZYWRLE_ENDIAN
|
||||
#define ZYWRLE_ENDIAN ENDIAN_LITTLE
|
||||
#include "vnc-enc-zrle-template.c"
|
||||
#include "vnc-enc-zrle.inc.c"
|
||||
|
||||
#undef ZYWRLE_ENDIAN
|
||||
#define ZYWRLE_ENDIAN ENDIAN_BIG
|
||||
#include "vnc-enc-zrle-template.c"
|
||||
#include "vnc-enc-zrle.inc.c"
|
||||
|
||||
#undef ZRLE_COMPACT_PIXEL
|
||||
#define ZRLE_COMPACT_PIXEL 24b
|
||||
#undef ZYWRLE_ENDIAN
|
||||
#define ZYWRLE_ENDIAN ENDIAN_LITTLE
|
||||
#include "vnc-enc-zrle-template.c"
|
||||
#include "vnc-enc-zrle.inc.c"
|
||||
|
||||
#undef ZYWRLE_ENDIAN
|
||||
#define ZYWRLE_ENDIAN ENDIAN_BIG
|
||||
#include "vnc-enc-zrle-template.c"
|
||||
#include "vnc-enc-zrle.inc.c"
|
||||
#undef ZRLE_COMPACT_PIXEL
|
||||
#undef ZRLE_BPP
|
||||
|
||||
|
@ -43,26 +43,23 @@
|
||||
* first byte of the option name)
|
||||
*
|
||||
* The option name is delimited by delim (usually , or =) or the string end
|
||||
* and is copied into buf. If the option name is longer than buf_size, it is
|
||||
* truncated. buf is always zero terminated.
|
||||
* and is copied into option. The caller is responsible for free'ing option
|
||||
* when no longer required.
|
||||
*
|
||||
* The return value is the position of the delimiter/zero byte after the option
|
||||
* name in p.
|
||||
*/
|
||||
const char *get_opt_name(char *buf, int buf_size, const char *p, char delim)
|
||||
static const char *get_opt_name(const char *p, char **option, char delim)
|
||||
{
|
||||
char *q;
|
||||
char *offset = strchr(p, delim);
|
||||
|
||||
q = buf;
|
||||
while (*p != '\0' && *p != delim) {
|
||||
if (q && (q - buf) < buf_size - 1)
|
||||
*q++ = *p;
|
||||
p++;
|
||||
if (offset) {
|
||||
*option = g_strndup(p, offset - p);
|
||||
return offset;
|
||||
} else {
|
||||
*option = g_strdup(p);
|
||||
return p + strlen(p);
|
||||
}
|
||||
if (q)
|
||||
*q = '\0';
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -73,25 +70,37 @@ const char *get_opt_name(char *buf, int buf_size, const char *p, char delim)
|
||||
* delimiter is fixed to be comma which starts a new option. To specify an
|
||||
* option value that contains commas, double each comma.
|
||||
*/
|
||||
const char *get_opt_value(char *buf, int buf_size, const char *p)
|
||||
const char *get_opt_value(const char *p, char **value)
|
||||
{
|
||||
char *q;
|
||||
size_t capacity = 0, length;
|
||||
const char *offset;
|
||||
|
||||
q = buf;
|
||||
while (*p != '\0') {
|
||||
if (*p == ',') {
|
||||
if (*(p + 1) != ',')
|
||||
break;
|
||||
p++;
|
||||
*value = NULL;
|
||||
while (1) {
|
||||
offset = strchr(p, ',');
|
||||
if (!offset) {
|
||||
offset = p + strlen(p);
|
||||
}
|
||||
if (q && (q - buf) < buf_size - 1)
|
||||
*q++ = *p;
|
||||
p++;
|
||||
}
|
||||
if (q)
|
||||
*q = '\0';
|
||||
|
||||
return p;
|
||||
length = offset - p;
|
||||
if (*offset != '\0' && *(offset + 1) == ',') {
|
||||
length++;
|
||||
}
|
||||
if (value) {
|
||||
*value = g_renew(char, *value, capacity + length + 1);
|
||||
strncpy(*value + capacity, p, length);
|
||||
(*value)[capacity + length] = '\0';
|
||||
}
|
||||
capacity += length;
|
||||
if (*offset == '\0' ||
|
||||
*(offset + 1) != ',') {
|
||||
break;
|
||||
}
|
||||
|
||||
p += (offset - p) + 2;
|
||||
}
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
static void parse_option_bool(const char *name, const char *value, bool *ret,
|
||||
@ -165,50 +174,43 @@ void parse_option_size(const char *name, const char *value,
|
||||
|
||||
bool has_help_option(const char *param)
|
||||
{
|
||||
size_t buflen = strlen(param) + 1;
|
||||
char *buf = g_malloc(buflen);
|
||||
const char *p = param;
|
||||
bool result = false;
|
||||
|
||||
while (*p) {
|
||||
p = get_opt_value(buf, buflen, p);
|
||||
while (*p && !result) {
|
||||
char *value;
|
||||
|
||||
p = get_opt_value(p, &value);
|
||||
if (*p) {
|
||||
p++;
|
||||
}
|
||||
|
||||
if (is_help_option(buf)) {
|
||||
result = true;
|
||||
goto out;
|
||||
}
|
||||
result = is_help_option(value);
|
||||
g_free(value);
|
||||
}
|
||||
|
||||
out:
|
||||
g_free(buf);
|
||||
return result;
|
||||
}
|
||||
|
||||
bool is_valid_option_list(const char *param)
|
||||
bool is_valid_option_list(const char *p)
|
||||
{
|
||||
size_t buflen = strlen(param) + 1;
|
||||
char *buf = g_malloc(buflen);
|
||||
const char *p = param;
|
||||
bool result = true;
|
||||
char *value = NULL;
|
||||
bool result = false;
|
||||
|
||||
while (*p) {
|
||||
p = get_opt_value(buf, buflen, p);
|
||||
if (*p && !*++p) {
|
||||
result = false;
|
||||
p = get_opt_value(p, &value);
|
||||
if ((*p && !*++p) ||
|
||||
(!*value || *value == ',')) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!*buf || *buf == ',') {
|
||||
result = false;
|
||||
goto out;
|
||||
}
|
||||
g_free(value);
|
||||
value = NULL;
|
||||
}
|
||||
|
||||
result = true;
|
||||
out:
|
||||
g_free(buf);
|
||||
g_free(value);
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -490,7 +492,7 @@ int qemu_opt_unset(QemuOpts *opts, const char *name)
|
||||
}
|
||||
}
|
||||
|
||||
static void opt_set(QemuOpts *opts, const char *name, const char *value,
|
||||
static void opt_set(QemuOpts *opts, const char *name, char *value,
|
||||
bool prepend, Error **errp)
|
||||
{
|
||||
QemuOpt *opt;
|
||||
@ -499,6 +501,7 @@ static void opt_set(QemuOpts *opts, const char *name, const char *value,
|
||||
|
||||
desc = find_desc_by_name(opts->list->desc, name);
|
||||
if (!desc && !opts_accepts_any(opts)) {
|
||||
g_free(value);
|
||||
error_setg(errp, QERR_INVALID_PARAMETER, name);
|
||||
return;
|
||||
}
|
||||
@ -512,8 +515,7 @@ static void opt_set(QemuOpts *opts, const char *name, const char *value,
|
||||
QTAILQ_INSERT_TAIL(&opts->head, opt, next);
|
||||
}
|
||||
opt->desc = desc;
|
||||
opt->str = g_strdup(value);
|
||||
assert(opt->str);
|
||||
opt->str = value;
|
||||
qemu_opt_parse(opt, &local_err);
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
@ -524,7 +526,7 @@ static void opt_set(QemuOpts *opts, const char *name, const char *value,
|
||||
void qemu_opt_set(QemuOpts *opts, const char *name, const char *value,
|
||||
Error **errp)
|
||||
{
|
||||
opt_set(opts, name, value, false, errp);
|
||||
opt_set(opts, name, g_strdup(value), false, errp);
|
||||
}
|
||||
|
||||
void qemu_opt_set_bool(QemuOpts *opts, const char *name, bool val,
|
||||
@ -757,7 +759,8 @@ void qemu_opts_print(QemuOpts *opts, const char *separator)
|
||||
static void opts_do_parse(QemuOpts *opts, const char *params,
|
||||
const char *firstname, bool prepend, Error **errp)
|
||||
{
|
||||
char option[128], value[1024];
|
||||
char *option = NULL;
|
||||
char *value = NULL;
|
||||
const char *p,*pe,*pc;
|
||||
Error *local_err = NULL;
|
||||
|
||||
@ -768,39 +771,45 @@ static void opts_do_parse(QemuOpts *opts, const char *params,
|
||||
/* found "foo,more" */
|
||||
if (p == params && firstname) {
|
||||
/* implicitly named first option */
|
||||
pstrcpy(option, sizeof(option), firstname);
|
||||
p = get_opt_value(value, sizeof(value), p);
|
||||
option = g_strdup(firstname);
|
||||
p = get_opt_value(p, &value);
|
||||
} else {
|
||||
/* option without value, probably a flag */
|
||||
p = get_opt_name(option, sizeof(option), p, ',');
|
||||
p = get_opt_name(p, &option, ',');
|
||||
if (strncmp(option, "no", 2) == 0) {
|
||||
memmove(option, option+2, strlen(option+2)+1);
|
||||
pstrcpy(value, sizeof(value), "off");
|
||||
value = g_strdup("off");
|
||||
} else {
|
||||
pstrcpy(value, sizeof(value), "on");
|
||||
value = g_strdup("on");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* found "foo=bar,more" */
|
||||
p = get_opt_name(option, sizeof(option), p, '=');
|
||||
if (*p != '=') {
|
||||
break;
|
||||
}
|
||||
p = get_opt_name(p, &option, '=');
|
||||
assert(*p == '=');
|
||||
p++;
|
||||
p = get_opt_value(value, sizeof(value), p);
|
||||
p = get_opt_value(p, &value);
|
||||
}
|
||||
if (strcmp(option, "id") != 0) {
|
||||
/* store and parse */
|
||||
opt_set(opts, option, value, prepend, &local_err);
|
||||
value = NULL;
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
return;
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
if (*p != ',') {
|
||||
break;
|
||||
}
|
||||
g_free(option);
|
||||
g_free(value);
|
||||
option = value = NULL;
|
||||
}
|
||||
|
||||
cleanup:
|
||||
g_free(option);
|
||||
g_free(value);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -819,7 +828,7 @@ static QemuOpts *opts_parse(QemuOptsList *list, const char *params,
|
||||
bool permit_abbrev, bool defaults, Error **errp)
|
||||
{
|
||||
const char *firstname;
|
||||
char value[1024], *id = NULL;
|
||||
char *id = NULL;
|
||||
const char *p;
|
||||
QemuOpts *opts;
|
||||
Error *local_err = NULL;
|
||||
@ -828,11 +837,9 @@ static QemuOpts *opts_parse(QemuOptsList *list, const char *params,
|
||||
firstname = permit_abbrev ? list->implied_opt_name : NULL;
|
||||
|
||||
if (strncmp(params, "id=", 3) == 0) {
|
||||
get_opt_value(value, sizeof(value), params+3);
|
||||
id = value;
|
||||
get_opt_value(params + 3, &id);
|
||||
} else if ((p = strstr(params, ",id=")) != NULL) {
|
||||
get_opt_value(value, sizeof(value), p+4);
|
||||
id = value;
|
||||
get_opt_value(p + 4, &id);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -844,6 +851,7 @@ static QemuOpts *opts_parse(QemuOptsList *list, const char *params,
|
||||
*/
|
||||
assert(!defaults || list->merge_lists);
|
||||
opts = qemu_opts_create(list, id, !defaults, &local_err);
|
||||
g_free(id);
|
||||
if (opts == NULL) {
|
||||
error_propagate(errp, local_err);
|
||||
return NULL;
|
||||
|
@ -482,7 +482,6 @@ static void __attribute__((constructor)) qemu_thread_atexit_init(void)
|
||||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_PTHREAD_SETNAME_NP
|
||||
typedef struct {
|
||||
void *(*start_routine)(void *);
|
||||
void *arg;
|
||||
@ -495,16 +494,18 @@ static void *qemu_thread_start(void *args)
|
||||
void *(*start_routine)(void *) = qemu_thread_args->start_routine;
|
||||
void *arg = qemu_thread_args->arg;
|
||||
|
||||
#ifdef CONFIG_PTHREAD_SETNAME_NP
|
||||
/* Attempt to set the threads name; note that this is for debug, so
|
||||
* we're not going to fail if we can't set it.
|
||||
*/
|
||||
pthread_setname_np(pthread_self(), qemu_thread_args->name);
|
||||
if (name_threads && qemu_thread_args->name) {
|
||||
pthread_setname_np(pthread_self(), qemu_thread_args->name);
|
||||
}
|
||||
#endif
|
||||
g_free(qemu_thread_args->name);
|
||||
g_free(qemu_thread_args);
|
||||
return start_routine(arg);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void qemu_thread_create(QemuThread *thread, const char *name,
|
||||
void *(*start_routine)(void*),
|
||||
@ -513,6 +514,7 @@ void qemu_thread_create(QemuThread *thread, const char *name,
|
||||
sigset_t set, oldset;
|
||||
int err;
|
||||
pthread_attr_t attr;
|
||||
QemuThreadArgs *qemu_thread_args;
|
||||
|
||||
err = pthread_attr_init(&attr);
|
||||
if (err) {
|
||||
@ -527,22 +529,13 @@ void qemu_thread_create(QemuThread *thread, const char *name,
|
||||
sigfillset(&set);
|
||||
pthread_sigmask(SIG_SETMASK, &set, &oldset);
|
||||
|
||||
#ifdef CONFIG_PTHREAD_SETNAME_NP
|
||||
if (name_threads) {
|
||||
QemuThreadArgs *qemu_thread_args;
|
||||
qemu_thread_args = g_new0(QemuThreadArgs, 1);
|
||||
qemu_thread_args->name = g_strdup(name);
|
||||
qemu_thread_args->start_routine = start_routine;
|
||||
qemu_thread_args->arg = arg;
|
||||
qemu_thread_args = g_new0(QemuThreadArgs, 1);
|
||||
qemu_thread_args->name = g_strdup(name);
|
||||
qemu_thread_args->start_routine = start_routine;
|
||||
qemu_thread_args->arg = arg;
|
||||
|
||||
err = pthread_create(&thread->thread, &attr,
|
||||
qemu_thread_start, qemu_thread_args);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
err = pthread_create(&thread->thread, &attr,
|
||||
start_routine, arg);
|
||||
}
|
||||
err = pthread_create(&thread->thread, &attr,
|
||||
qemu_thread_start, qemu_thread_args);
|
||||
|
||||
if (err)
|
||||
error_exit(err, __func__);
|
||||
|
24
vl.c
24
vl.c
@ -3138,11 +3138,6 @@ int main(int argc, char **argv, char **envp)
|
||||
exit(1);
|
||||
}
|
||||
switch(popt->index) {
|
||||
case QEMU_OPTION_no_kvm_irqchip: {
|
||||
olist = qemu_find_opts("machine");
|
||||
qemu_opts_parse_noisily(olist, "kernel_irqchip=off", false);
|
||||
break;
|
||||
}
|
||||
case QEMU_OPTION_cpu:
|
||||
/* hw initialization will check this */
|
||||
cpu_model = optarg;
|
||||
@ -3587,6 +3582,8 @@ int main(int argc, char **argv, char **envp)
|
||||
}
|
||||
break;
|
||||
case QEMU_OPTION_virtiocon:
|
||||
warn_report("This option is deprecated, "
|
||||
"use '-device virtconsole' instead");
|
||||
add_device_config(DEV_VIRTCON, optarg);
|
||||
default_virtcon = 0;
|
||||
if (strncmp(optarg, "mon:", 4) == 0) {
|
||||
@ -3694,18 +3691,6 @@ int main(int argc, char **argv, char **envp)
|
||||
olist = qemu_find_opts("machine");
|
||||
qemu_opts_parse_noisily(olist, "accel=tcg", false);
|
||||
break;
|
||||
case QEMU_OPTION_no_kvm_pit_reinjection: {
|
||||
static GlobalProperty kvm_pit_lost_tick_policy = {
|
||||
.driver = "kvm-pit",
|
||||
.property = "lost_tick_policy",
|
||||
.value = "discard",
|
||||
};
|
||||
|
||||
warn_report("deprecated, replaced by "
|
||||
"-global kvm-pit.lost_tick_policy=discard");
|
||||
qdev_prop_register_global(&kvm_pit_lost_tick_policy);
|
||||
break;
|
||||
}
|
||||
case QEMU_OPTION_accel:
|
||||
accel_opts = qemu_opts_parse_noisily(qemu_find_opts("accel"),
|
||||
optarg, true);
|
||||
@ -4031,7 +4016,10 @@ int main(int argc, char **argv, char **envp)
|
||||
}
|
||||
break;
|
||||
default:
|
||||
os_parse_cmd_args(popt->index, optarg);
|
||||
if (os_parse_cmd_args(popt->index, optarg)) {
|
||||
error_report("Option not supported in this build");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user