Compare commits
	
		
			133 Commits
		
	
	
		
			pull-seabi
			...
			pull-input
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					a5d4d7b580 | ||
| 
						 | 
					006a5edebe | ||
| 
						 | 
					6f2b9a5b24 | ||
| 
						 | 
					0c8ff723bd | ||
| 
						 | 
					2a8327e8a8 | ||
| 
						 | 
					8c52f0cbba | ||
| 
						 | 
					0a3346f5de | ||
| 
						 | 
					cb4e0f9ddf | ||
| 
						 | 
					ad7020a7e7 | ||
| 
						 | 
					033af8e9aa | ||
| 
						 | 
					a87310a62d | ||
| 
						 | 
					6fad9e986b | ||
| 
						 | 
					72e3875485 | ||
| 
						 | 
					a88bbb006a | ||
| 
						 | 
					a6c3ed2474 | ||
| 
						 | 
					7144612370 | ||
| 
						 | 
					be67e9ab97 | ||
| 
						 | 
					f44c475cb6 | ||
| 
						 | 
					4e5d45ae57 | ||
| 
						 | 
					f27183abaa | ||
| 
						 | 
					9aaaa18194 | ||
| 
						 | 
					8bac22423e | ||
| 
						 | 
					53432dc9ea | ||
| 
						 | 
					d87636b18f | ||
| 
						 | 
					daeba9699d | ||
| 
						 | 
					0210afe669 | ||
| 
						 | 
					a3590dacce | ||
| 
						 | 
					a8e3fbedc8 | ||
| 
						 | 
					2e4450ff43 | ||
| 
						 | 
					a31bdae5a7 | ||
| 
						 | 
					bc2256c4ae | ||
| 
						 | 
					f08f9271bf | ||
| 
						 | 
					b9174d4f25 | ||
| 
						 | 
					b1028b4e86 | ||
| 
						 | 
					799810fb28 | ||
| 
						 | 
					a59d31a1eb | ||
| 
						 | 
					cfe67cef48 | ||
| 
						 | 
					b58850e79d | ||
| 
						 | 
					6396a193d3 | ||
| 
						 | 
					2e5577bc55 | ||
| 
						 | 
					d6a6b13ea1 | ||
| 
						 | 
					f6bda88ff8 | ||
| 
						 | 
					6cb0b013a1 | ||
| 
						 | 
					3281af8114 | ||
| 
						 | 
					b061a82b8a | ||
| 
						 | 
					decf4f807b | ||
| 
						 | 
					ba890a9b25 | ||
| 
						 | 
					ffdb1409a7 | ||
| 
						 | 
					89e9429c3c | ||
| 
						 | 
					e4a511f8cc | ||
| 
						 | 
					965eb2fcdf | ||
| 
						 | 
					ae46e23964 | ||
| 
						 | 
					fb1a3a051d | ||
| 
						 | 
					397c767b2d | ||
| 
						 | 
					693a3e01af | ||
| 
						 | 
					270746142c | ||
| 
						 | 
					1e7398a140 | ||
| 
						 | 
					74de5504fd | ||
| 
						 | 
					5ba03e2dd7 | ||
| 
						 | 
					1717388645 | ||
| 
						 | 
					5be7d9f1b1 | ||
| 
						 | 
					4ee9b43be9 | ||
| 
						 | 
					8524f1c79e | ||
| 
						 | 
					473a49460d | ||
| 
						 | 
					ff5397bc72 | ||
| 
						 | 
					53f77e4562 | ||
| 
						 | 
					6bc5cf92c0 | ||
| 
						 | 
					1590d266d9 | ||
| 
						 | 
					8ffe756da0 | ||
| 
						 | 
					e1d4210c3a | ||
| 
						 | 
					c5ecd7e18f | ||
| 
						 | 
					ae0a7a1090 | ||
| 
						 | 
					4f35680023 | ||
| 
						 | 
					f9a1427361 | ||
| 
						 | 
					75276710ae | ||
| 
						 | 
					00e4b285a3 | ||
| 
						 | 
					4d076d67c2 | ||
| 
						 | 
					e565d934d2 | ||
| 
						 | 
					a136608727 | ||
| 
						 | 
					8608d25251 | ||
| 
						 | 
					54414047ec | ||
| 
						 | 
					12c7079449 | ||
| 
						 | 
					836c3b01d2 | ||
| 
						 | 
					0311c5bde3 | ||
| 
						 | 
					1b58f5a7f6 | ||
| 
						 | 
					e207527751 | ||
| 
						 | 
					a3122b681a | ||
| 
						 | 
					c80cd6bb9c | ||
| 
						 | 
					04b7a1523d | ||
| 
						 | 
					41d283bdab | ||
| 
						 | 
					332f64073b | ||
| 
						 | 
					06b008d941 | ||
| 
						 | 
					bea2f0982b | ||
| 
						 | 
					28452758c4 | ||
| 
						 | 
					ebe7d8b166 | ||
| 
						 | 
					d4862a87e3 | ||
| 
						 | 
					9dacf32d2c | ||
| 
						 | 
					66ae13bb9e | ||
| 
						 | 
					c69403fcd4 | ||
| 
						 | 
					5e031072e7 | ||
| 
						 | 
					67633bb4f7 | ||
| 
						 | 
					f754c3c9cc | ||
| 
						 | 
					1f68f1d36c | ||
| 
						 | 
					3da0ab3529 | ||
| 
						 | 
					83bb161299 | ||
| 
						 | 
					2f54394997 | ||
| 
						 | 
					311918b979 | ||
| 
						 | 
					8d302e7675 | ||
| 
						 | 
					f0e0d817c2 | ||
| 
						 | 
					2c2275eb41 | ||
| 
						 | 
					777c98c32c | ||
| 
						 | 
					d453d10383 | ||
| 
						 | 
					a8f931a931 | ||
| 
						 | 
					fb01bf4c6b | ||
| 
						 | 
					6da528d14d | ||
| 
						 | 
					fc89efe693 | ||
| 
						 | 
					d7ce6b7a0b | ||
| 
						 | 
					2e83c49626 | ||
| 
						 | 
					ad8a4570ad | ||
| 
						 | 
					2ecacb0b4b | ||
| 
						 | 
					8df7eef305 | ||
| 
						 | 
					cbed0ba78f | ||
| 
						 | 
					cc0d079d45 | ||
| 
						 | 
					7107e5a756 | ||
| 
						 | 
					06e3c077da | ||
| 
						 | 
					a499973ff3 | ||
| 
						 | 
					d49f4ab48e | ||
| 
						 | 
					ae52e585bf | ||
| 
						 | 
					a09f4a9d19 | ||
| 
						 | 
					8c29f8d6b9 | ||
| 
						 | 
					f8d30a4f96 | ||
| 
						 | 
					bf6667d63e | ||
| 
						 | 
					6a084ea39a | 
							
								
								
									
										11
									
								
								MAINTAINERS
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								MAINTAINERS
									
									
									
									
									
								
							@@ -702,6 +702,7 @@ virtio
 | 
			
		||||
M: Michael S. Tsirkin <mst@redhat.com>
 | 
			
		||||
S: Supported
 | 
			
		||||
F: hw/*/virtio*
 | 
			
		||||
F: net/vhost-user.c
 | 
			
		||||
 | 
			
		||||
virtio-9p
 | 
			
		||||
M: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
 | 
			
		||||
@@ -727,6 +728,12 @@ S: Supported
 | 
			
		||||
F: hw/s390x/virtio-ccw.[hc]
 | 
			
		||||
T: git git://github.com/cohuck/qemu virtio-ccw-upstr
 | 
			
		||||
 | 
			
		||||
virtio-input
 | 
			
		||||
M: Gerd Hoffmann <kraxel@redhat.com>
 | 
			
		||||
S: Maintained
 | 
			
		||||
F: hw/input/virtio-input*.c
 | 
			
		||||
F: include/hw/virtio/virtio-input.h
 | 
			
		||||
 | 
			
		||||
virtio-serial
 | 
			
		||||
M: Amit Shah <amit.shah@redhat.com>
 | 
			
		||||
S: Supported
 | 
			
		||||
@@ -952,7 +959,10 @@ M: Markus Armbruster <armbru@redhat.com>
 | 
			
		||||
M: Michael Roth <mdroth@linux.vnet.ibm.com>
 | 
			
		||||
S: Supported
 | 
			
		||||
F: qapi/
 | 
			
		||||
X: qapi/*.json
 | 
			
		||||
F: tests/qapi-schema/
 | 
			
		||||
F: scripts/qapi*
 | 
			
		||||
F: docs/qapi*
 | 
			
		||||
T: git git://repo.or.cz/qemu/armbru.git qapi-next
 | 
			
		||||
 | 
			
		||||
QAPI Schema
 | 
			
		||||
@@ -960,6 +970,7 @@ M: Eric Blake <eblake@redhat.com>
 | 
			
		||||
M: Markus Armbruster <armbru@redhat.com>
 | 
			
		||||
S: Supported
 | 
			
		||||
F: qapi-schema.json
 | 
			
		||||
F: qapi/*.json
 | 
			
		||||
T: git git://repo.or.cz/qemu/armbru.git qapi-next
 | 
			
		||||
 | 
			
		||||
QObject
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										24
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										24
									
								
								Makefile
									
									
									
									
									
								
							@@ -74,7 +74,7 @@ Makefile: ;
 | 
			
		||||
configure: ;
 | 
			
		||||
 | 
			
		||||
.PHONY: all clean cscope distclean dvi html info install install-doc \
 | 
			
		||||
	pdf recurse-all speed test dist
 | 
			
		||||
	pdf recurse-all speed test dist msi
 | 
			
		||||
 | 
			
		||||
$(call set-vpath, $(SRC_PATH))
 | 
			
		||||
 | 
			
		||||
@@ -287,10 +287,32 @@ $(qga-obj-y) qemu-ga.o: $(QGALIB_GEN)
 | 
			
		||||
qemu-ga$(EXESUF): $(qga-obj-y) libqemuutil.a libqemustub.a
 | 
			
		||||
	$(call LINK, $^)
 | 
			
		||||
 | 
			
		||||
ifdef QEMU_GA_MSI_ENABLED
 | 
			
		||||
QEMU_GA_MSI=qemu-ga-$(ARCH).msi
 | 
			
		||||
 | 
			
		||||
msi: ${QEMU_GA_MSI}
 | 
			
		||||
 | 
			
		||||
$(QEMU_GA_MSI): qemu-ga.exe
 | 
			
		||||
 | 
			
		||||
ifdef QEMU_GA_MSI_WITH_VSS
 | 
			
		||||
$(QEMU_GA_MSI): qga/vss-win32/qga-vss.dll
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
$(QEMU_GA_MSI): config-host.mak
 | 
			
		||||
 | 
			
		||||
$(QEMU_GA_MSI):  qga/installer/qemu-ga.wxs
 | 
			
		||||
	$(call quiet-command,QEMU_GA_VERSION="$(QEMU_GA_VERSION)" QEMU_GA_MANUFACTURER="$(QEMU_GA_MANUFACTURER)" QEMU_GA_DISTRO="$(QEMU_GA_DISTRO)" \
 | 
			
		||||
	wixl -o $@ $(QEMU_GA_MSI_ARCH) $(QEMU_GA_MSI_WITH_VSS) $(QEMU_GA_MSI_MINGW_DLL_PATH) $<, "  WIXL  $@")
 | 
			
		||||
else
 | 
			
		||||
msi:
 | 
			
		||||
	@echo MSI build not configured or dependency resolution failed (reconfigure with --enable-guest-agent-msi option)
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
clean:
 | 
			
		||||
# avoid old build problems by removing potentially incorrect old files
 | 
			
		||||
	rm -f config.mak op-i386.h opc-i386.h gen-op-i386.h op-arm.h opc-arm.h gen-op-arm.h
 | 
			
		||||
	rm -f qemu-options.def
 | 
			
		||||
	rm -f *.msi
 | 
			
		||||
	find . \( -name '*.l[oa]' -o -name '*.so' -o -name '*.dll' -o -name '*.mo' -o -name '*.[oda]' \) -type f -exec rm {} +
 | 
			
		||||
	rm -f $(filter-out %.tlb,$(TOOLS)) $(HELPERS-y) qemu-ga TAGS cscope.* *.pod *~ */*~
 | 
			
		||||
	rm -f fsdev/*.pod
 | 
			
		||||
 
 | 
			
		||||
@@ -113,24 +113,17 @@ host_memory_backend_set_host_nodes(Object *obj, Visitor *v, void *opaque,
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
host_memory_backend_get_policy(Object *obj, Visitor *v, void *opaque,
 | 
			
		||||
                               const char *name, Error **errp)
 | 
			
		||||
static int
 | 
			
		||||
host_memory_backend_get_policy(Object *obj, Error **errp G_GNUC_UNUSED)
 | 
			
		||||
{
 | 
			
		||||
    HostMemoryBackend *backend = MEMORY_BACKEND(obj);
 | 
			
		||||
    int policy = backend->policy;
 | 
			
		||||
 | 
			
		||||
    visit_type_enum(v, &policy, HostMemPolicy_lookup, NULL, name, errp);
 | 
			
		||||
    return backend->policy;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
host_memory_backend_set_policy(Object *obj, Visitor *v, void *opaque,
 | 
			
		||||
                               const char *name, Error **errp)
 | 
			
		||||
host_memory_backend_set_policy(Object *obj, int policy, Error **errp)
 | 
			
		||||
{
 | 
			
		||||
    HostMemoryBackend *backend = MEMORY_BACKEND(obj);
 | 
			
		||||
    int policy;
 | 
			
		||||
 | 
			
		||||
    visit_type_enum(v, &policy, HostMemPolicy_lookup, NULL, name, errp);
 | 
			
		||||
    backend->policy = policy;
 | 
			
		||||
 | 
			
		||||
#ifndef CONFIG_NUMA
 | 
			
		||||
@@ -252,9 +245,10 @@ static void host_memory_backend_init(Object *obj)
 | 
			
		||||
    object_property_add(obj, "host-nodes", "int",
 | 
			
		||||
                        host_memory_backend_get_host_nodes,
 | 
			
		||||
                        host_memory_backend_set_host_nodes, NULL, NULL, NULL);
 | 
			
		||||
    object_property_add(obj, "policy", "str",
 | 
			
		||||
                        host_memory_backend_get_policy,
 | 
			
		||||
                        host_memory_backend_set_policy, NULL, NULL, NULL);
 | 
			
		||||
    object_property_add_enum(obj, "policy", "HostMemPolicy",
 | 
			
		||||
                             HostMemPolicy_lookup,
 | 
			
		||||
                             host_memory_backend_get_policy,
 | 
			
		||||
                             host_memory_backend_set_policy, NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
MemoryRegion *
 | 
			
		||||
 
 | 
			
		||||
@@ -942,7 +942,7 @@ DriveInfo *drive_new(QemuOpts *all_opts, BlockInterfaceType block_default_type)
 | 
			
		||||
        devopts = qemu_opts_create(qemu_find_opts("device"), NULL, 0,
 | 
			
		||||
                                   &error_abort);
 | 
			
		||||
        if (arch_type == QEMU_ARCH_S390X) {
 | 
			
		||||
            qemu_opt_set(devopts, "driver", "virtio-blk-s390", &error_abort);
 | 
			
		||||
            qemu_opt_set(devopts, "driver", "virtio-blk-ccw", &error_abort);
 | 
			
		||||
        } else {
 | 
			
		||||
            qemu_opt_set(devopts, "driver", "virtio-blk-pci", &error_abort);
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										66
									
								
								configure
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										66
									
								
								configure
									
									
									
									
										vendored
									
									
								
							@@ -315,6 +315,7 @@ snappy=""
 | 
			
		||||
bzip2=""
 | 
			
		||||
guest_agent=""
 | 
			
		||||
guest_agent_with_vss="no"
 | 
			
		||||
guest_agent_msi=""
 | 
			
		||||
vss_win32_sdk=""
 | 
			
		||||
win_sdk="no"
 | 
			
		||||
want_tools="yes"
 | 
			
		||||
@@ -1078,6 +1079,10 @@ for opt do
 | 
			
		||||
  ;;
 | 
			
		||||
  --disable-guest-agent) guest_agent="no"
 | 
			
		||||
  ;;
 | 
			
		||||
  --enable-guest-agent-msi) guest_agent_msi="yes"
 | 
			
		||||
  ;;
 | 
			
		||||
  --disable-guest-agent-msi) guest_agent_msi="no"
 | 
			
		||||
  ;;
 | 
			
		||||
  --with-vss-sdk) vss_win32_sdk=""
 | 
			
		||||
  ;;
 | 
			
		||||
  --with-vss-sdk=*) vss_win32_sdk="$optarg"
 | 
			
		||||
@@ -1394,6 +1399,8 @@ Advanced options (experts only):
 | 
			
		||||
                           reading bzip2-compressed dmg images)
 | 
			
		||||
  --disable-guest-agent    disable building of the QEMU Guest Agent
 | 
			
		||||
  --enable-guest-agent     enable building of the QEMU Guest Agent
 | 
			
		||||
  --enable-guest-agent-msi enable building guest agent Windows MSI installation package
 | 
			
		||||
  --disable-guest-agent-msi disable building guest agent Windows MSI installation
 | 
			
		||||
  --with-vss-sdk=SDK-path  enable Windows VSS support in QEMU Guest Agent
 | 
			
		||||
  --with-win-sdk=SDK-path  path to Windows Platform SDK (to build VSS .tlb)
 | 
			
		||||
  --disable-seccomp        disable seccomp support
 | 
			
		||||
@@ -3862,6 +3869,56 @@ if test "$mingw32" = "yes" -a "$guest_agent" != "no" -a "$guest_agent_with_vss"
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
##########################################
 | 
			
		||||
# Guest agent Window MSI  package
 | 
			
		||||
 | 
			
		||||
if test "$guest_agent" != yes; then
 | 
			
		||||
  if test "$guest_agent_msi" = yes; then
 | 
			
		||||
    error_exit "MSI guest agent package requires guest agent enabled"
 | 
			
		||||
  fi
 | 
			
		||||
  guest_agent_msi=no
 | 
			
		||||
elif test "$mingw32" != "yes"; then
 | 
			
		||||
  if test "$guest_agent_msi" = "yes"; then
 | 
			
		||||
    error_exit "MSI guest agent package is available only for MinGW Windows cross-compilation"
 | 
			
		||||
  fi
 | 
			
		||||
  guest_agent_msi=no
 | 
			
		||||
elif ! has wixl; then
 | 
			
		||||
  if test "$guest_agent_msi" = "yes"; then
 | 
			
		||||
    error_exit "MSI guest agent package requires wixl tool installed ( usually from msitools package )"
 | 
			
		||||
  fi
 | 
			
		||||
  guest_agent_msi=no
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
if test "$guest_agent_msi" != "no"; then
 | 
			
		||||
  if test "$guest_agent_with_vss" = "yes"; then
 | 
			
		||||
    QEMU_GA_MSI_WITH_VSS="-D InstallVss"
 | 
			
		||||
  fi
 | 
			
		||||
 | 
			
		||||
  if test "$QEMU_GA_MANUFACTURER" = ""; then
 | 
			
		||||
    QEMU_GA_MANUFACTURER=QEMU
 | 
			
		||||
  fi
 | 
			
		||||
 | 
			
		||||
  if test "$QEMU_GA_DISTRO" = ""; then
 | 
			
		||||
    QEMU_GA_DISTRO=Linux
 | 
			
		||||
  fi
 | 
			
		||||
 | 
			
		||||
  if test "$QEMU_GA_VERSION" = ""; then
 | 
			
		||||
      QEMU_GA_VERSION=`cat $source_path/VERSION`
 | 
			
		||||
  fi
 | 
			
		||||
 | 
			
		||||
  QEMU_GA_MSI_MINGW_DLL_PATH="-D Mingw_dlls=`$pkg_config --variable=prefix glib-2.0`/bin"
 | 
			
		||||
  
 | 
			
		||||
  case "$cpu" in
 | 
			
		||||
  x86_64)
 | 
			
		||||
    QEMU_GA_MSI_ARCH="-a x64 -D Arch=64"
 | 
			
		||||
    ;;
 | 
			
		||||
  i386)
 | 
			
		||||
    QEMU_GA_MSI_ARCH="-D Arch=32"
 | 
			
		||||
    ;;
 | 
			
		||||
  *)
 | 
			
		||||
    error_exit "CPU $cpu not supported for building installation package"
 | 
			
		||||
    ;;
 | 
			
		||||
  esac
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
##########################################
 | 
			
		||||
# check if we have fdatasync
 | 
			
		||||
@@ -4558,6 +4615,15 @@ if test "$mingw32" = "yes" ; then
 | 
			
		||||
    echo "CONFIG_QGA_VSS=y" >> $config_host_mak
 | 
			
		||||
    echo "WIN_SDK=\"$win_sdk\"" >> $config_host_mak
 | 
			
		||||
  fi
 | 
			
		||||
  if test "$guest_agent_msi" != "no"; then
 | 
			
		||||
    echo "QEMU_GA_MSI_ENABLED=yes" >> $config_host_mak  
 | 
			
		||||
    echo "QEMU_GA_MSI_MINGW_DLL_PATH=${QEMU_GA_MSI_MINGW_DLL_PATH}" >> $config_host_mak
 | 
			
		||||
    echo "QEMU_GA_MSI_WITH_VSS=${QEMU_GA_MSI_WITH_VSS}" >> $config_host_mak
 | 
			
		||||
    echo "QEMU_GA_MSI_ARCH=${QEMU_GA_MSI_ARCH}" >> $config_host_mak
 | 
			
		||||
    echo "QEMU_GA_MANUFACTURER=${QEMU_GA_MANUFACTURER}" >> $config_host_mak
 | 
			
		||||
    echo "QEMU_GA_DISTRO=${QEMU_GA_DISTRO}" >> $config_host_mak
 | 
			
		||||
    echo "QEMU_GA_VERSION=${QEMU_GA_VERSION}" >> $config_host_mak
 | 
			
		||||
  fi
 | 
			
		||||
else
 | 
			
		||||
  echo "CONFIG_POSIX=y" >> $config_host_mak
 | 
			
		||||
fi
 | 
			
		||||
 
 | 
			
		||||
@@ -680,8 +680,6 @@ Example:
 | 
			
		||||
    out:
 | 
			
		||||
        error_propagate(errp, err);
 | 
			
		||||
    }
 | 
			
		||||
    $ python scripts/qapi-commands.py --output-dir="qapi-generated" \
 | 
			
		||||
    --prefix="example-" example-schema.json
 | 
			
		||||
    $ cat qapi-generated/example-qapi-visit.h
 | 
			
		||||
[Uninteresting stuff omitted...]
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										8
									
								
								exec.c
									
									
									
									
									
								
							
							
						
						
									
										8
									
								
								exec.c
									
									
									
									
									
								
							@@ -341,6 +341,7 @@ address_space_translate_internal(AddressSpaceDispatch *d, hwaddr addr, hwaddr *x
 | 
			
		||||
                                 hwaddr *plen, bool resolve_subpage)
 | 
			
		||||
{
 | 
			
		||||
    MemoryRegionSection *section;
 | 
			
		||||
    MemoryRegion *mr;
 | 
			
		||||
    Int128 diff;
 | 
			
		||||
 | 
			
		||||
    section = address_space_lookup_region(d, addr, resolve_subpage);
 | 
			
		||||
@@ -350,8 +351,11 @@ address_space_translate_internal(AddressSpaceDispatch *d, hwaddr addr, hwaddr *x
 | 
			
		||||
    /* Compute offset within MemoryRegion */
 | 
			
		||||
    *xlat = addr + section->offset_within_region;
 | 
			
		||||
 | 
			
		||||
    diff = int128_sub(section->mr->size, int128_make64(addr));
 | 
			
		||||
    *plen = int128_get64(int128_min(diff, int128_make64(*plen)));
 | 
			
		||||
    mr = section->mr;
 | 
			
		||||
    if (memory_region_is_ram(mr)) {
 | 
			
		||||
        diff = int128_sub(section->size, int128_make64(addr));
 | 
			
		||||
        *plen = int128_get64(int128_min(diff, int128_make64(*plen)));
 | 
			
		||||
    }
 | 
			
		||||
    return section;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -49,6 +49,7 @@ static struct option helper_opts[] = {
 | 
			
		||||
    {"socket", required_argument, NULL, 's'},
 | 
			
		||||
    {"uid", required_argument, NULL, 'u'},
 | 
			
		||||
    {"gid", required_argument, NULL, 'g'},
 | 
			
		||||
    {},
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static bool is_daemon;
 | 
			
		||||
@@ -738,7 +739,12 @@ static int proxy_socket(const char *path, uid_t uid, gid_t gid)
 | 
			
		||||
        return -1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    g_assert(strlen(path) < sizeof(proxy.sun_path));
 | 
			
		||||
    if (strlen(path) >= sizeof(proxy.sun_path)) {
 | 
			
		||||
        do_log(LOG_CRIT, "UNIX domain socket path exceeds %zu characters\n",
 | 
			
		||||
               sizeof(proxy.sun_path));
 | 
			
		||||
        return -1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    sock = socket(AF_UNIX, SOCK_STREAM, 0);
 | 
			
		||||
    if (sock < 0) {
 | 
			
		||||
        do_perror("socket");
 | 
			
		||||
 
 | 
			
		||||
@@ -40,6 +40,7 @@
 | 
			
		||||
#include "cpu.h"
 | 
			
		||||
#include "qemu/sockets.h"
 | 
			
		||||
#include "sysemu/kvm.h"
 | 
			
		||||
#include "exec/semihost.h"
 | 
			
		||||
 | 
			
		||||
#ifdef CONFIG_USER_ONLY
 | 
			
		||||
#define GDB_ATTACHED "0"
 | 
			
		||||
@@ -323,8 +324,6 @@ static GDBState *gdbserver_state;
 | 
			
		||||
 | 
			
		||||
bool gdb_has_xml;
 | 
			
		||||
 | 
			
		||||
int semihosting_target = SEMIHOSTING_TARGET_AUTO;
 | 
			
		||||
 | 
			
		||||
#ifdef CONFIG_USER_ONLY
 | 
			
		||||
/* XXX: This is not thread safe.  Do we care?  */
 | 
			
		||||
static int gdbserver_fd = -1;
 | 
			
		||||
@@ -362,10 +361,11 @@ static enum {
 | 
			
		||||
/* Decide if either remote gdb syscalls or native file IO should be used. */
 | 
			
		||||
int use_gdb_syscalls(void)
 | 
			
		||||
{
 | 
			
		||||
    if (semihosting_target == SEMIHOSTING_TARGET_NATIVE) {
 | 
			
		||||
    SemihostingTarget target = semihosting_get_target();
 | 
			
		||||
    if (target == SEMIHOSTING_TARGET_NATIVE) {
 | 
			
		||||
        /* -semihosting-config target=native */
 | 
			
		||||
        return false;
 | 
			
		||||
    } else if (semihosting_target == SEMIHOSTING_TARGET_GDB) {
 | 
			
		||||
    } else if (target == SEMIHOSTING_TARGET_GDB) {
 | 
			
		||||
        /* -semihosting-config target=gdb */
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -26,6 +26,9 @@
 | 
			
		||||
#include "sysemu/device_tree.h"
 | 
			
		||||
#include "hw/platform-bus.h"
 | 
			
		||||
#include "sysemu/sysemu.h"
 | 
			
		||||
#include "hw/vfio/vfio-platform.h"
 | 
			
		||||
#include "hw/vfio/vfio-calxeda-xgmac.h"
 | 
			
		||||
#include "hw/arm/fdt.h"
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * internal struct that contains the information to create dynamic
 | 
			
		||||
@@ -53,11 +56,81 @@ typedef struct NodeCreationPair {
 | 
			
		||||
    int (*add_fdt_node_fn)(SysBusDevice *sbdev, void *opaque);
 | 
			
		||||
} NodeCreationPair;
 | 
			
		||||
 | 
			
		||||
/* Device Specific Code */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * add_calxeda_midway_xgmac_fdt_node
 | 
			
		||||
 *
 | 
			
		||||
 * Generates a simple node with following properties:
 | 
			
		||||
 * compatible string, regs, interrupts, dma-coherent
 | 
			
		||||
 */
 | 
			
		||||
static int add_calxeda_midway_xgmac_fdt_node(SysBusDevice *sbdev, void *opaque)
 | 
			
		||||
{
 | 
			
		||||
    PlatformBusFDTData *data = opaque;
 | 
			
		||||
    PlatformBusDevice *pbus = data->pbus;
 | 
			
		||||
    void *fdt = data->fdt;
 | 
			
		||||
    const char *parent_node = data->pbus_node_name;
 | 
			
		||||
    int compat_str_len, i, ret = -1;
 | 
			
		||||
    char *nodename;
 | 
			
		||||
    uint32_t *irq_attr, *reg_attr;
 | 
			
		||||
    uint64_t mmio_base, irq_number;
 | 
			
		||||
    VFIOPlatformDevice *vdev = VFIO_PLATFORM_DEVICE(sbdev);
 | 
			
		||||
    VFIODevice *vbasedev = &vdev->vbasedev;
 | 
			
		||||
 | 
			
		||||
    mmio_base = platform_bus_get_mmio_addr(pbus, sbdev, 0);
 | 
			
		||||
    nodename = g_strdup_printf("%s/%s@%" PRIx64, parent_node,
 | 
			
		||||
                               vbasedev->name, mmio_base);
 | 
			
		||||
    qemu_fdt_add_subnode(fdt, nodename);
 | 
			
		||||
 | 
			
		||||
    compat_str_len = strlen(vdev->compat) + 1;
 | 
			
		||||
    qemu_fdt_setprop(fdt, nodename, "compatible",
 | 
			
		||||
                          vdev->compat, compat_str_len);
 | 
			
		||||
 | 
			
		||||
    qemu_fdt_setprop(fdt, nodename, "dma-coherent", "", 0);
 | 
			
		||||
 | 
			
		||||
    reg_attr = g_new(uint32_t, vbasedev->num_regions * 2);
 | 
			
		||||
    for (i = 0; i < vbasedev->num_regions; i++) {
 | 
			
		||||
        mmio_base = platform_bus_get_mmio_addr(pbus, sbdev, i);
 | 
			
		||||
        reg_attr[2 * i] = cpu_to_be32(mmio_base);
 | 
			
		||||
        reg_attr[2 * i + 1] = cpu_to_be32(
 | 
			
		||||
                                memory_region_size(&vdev->regions[i]->mem));
 | 
			
		||||
    }
 | 
			
		||||
    ret = qemu_fdt_setprop(fdt, nodename, "reg", reg_attr,
 | 
			
		||||
                           vbasedev->num_regions * 2 * sizeof(uint32_t));
 | 
			
		||||
    if (ret) {
 | 
			
		||||
        error_report("could not set reg property of node %s", nodename);
 | 
			
		||||
        goto fail_reg;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    irq_attr = g_new(uint32_t, vbasedev->num_irqs * 3);
 | 
			
		||||
    for (i = 0; i < vbasedev->num_irqs; i++) {
 | 
			
		||||
        irq_number = platform_bus_get_irqn(pbus, sbdev , i)
 | 
			
		||||
                         + data->irq_start;
 | 
			
		||||
        irq_attr[3 * i] = cpu_to_be32(GIC_FDT_IRQ_TYPE_SPI);
 | 
			
		||||
        irq_attr[3 * i + 1] = cpu_to_be32(irq_number);
 | 
			
		||||
        irq_attr[3 * i + 2] = cpu_to_be32(GIC_FDT_IRQ_FLAGS_LEVEL_HI);
 | 
			
		||||
    }
 | 
			
		||||
    ret = qemu_fdt_setprop(fdt, nodename, "interrupts",
 | 
			
		||||
                     irq_attr, vbasedev->num_irqs * 3 * sizeof(uint32_t));
 | 
			
		||||
    if (ret) {
 | 
			
		||||
        error_report("could not set interrupts property of node %s",
 | 
			
		||||
                     nodename);
 | 
			
		||||
    }
 | 
			
		||||
    g_free(irq_attr);
 | 
			
		||||
fail_reg:
 | 
			
		||||
    g_free(reg_attr);
 | 
			
		||||
    g_free(nodename);
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* list of supported dynamic sysbus devices */
 | 
			
		||||
static const NodeCreationPair add_fdt_node_functions[] = {
 | 
			
		||||
    {TYPE_VFIO_CALXEDA_XGMAC, add_calxeda_midway_xgmac_fdt_node},
 | 
			
		||||
    {"", NULL}, /* last element */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* Generic Code */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * add_fdt_node - add the device tree node of a dynamic sysbus device
 | 
			
		||||
 *
 | 
			
		||||
 
 | 
			
		||||
@@ -47,21 +47,11 @@
 | 
			
		||||
#include "hw/arm/virt-acpi-build.h"
 | 
			
		||||
#include "hw/arm/sysbus-fdt.h"
 | 
			
		||||
#include "hw/platform-bus.h"
 | 
			
		||||
#include "hw/arm/fdt.h"
 | 
			
		||||
 | 
			
		||||
/* Number of external interrupt lines to configure the GIC with */
 | 
			
		||||
#define NUM_IRQS 256
 | 
			
		||||
 | 
			
		||||
#define GIC_FDT_IRQ_TYPE_SPI 0
 | 
			
		||||
#define GIC_FDT_IRQ_TYPE_PPI 1
 | 
			
		||||
 | 
			
		||||
#define GIC_FDT_IRQ_FLAGS_EDGE_LO_HI 1
 | 
			
		||||
#define GIC_FDT_IRQ_FLAGS_EDGE_HI_LO 2
 | 
			
		||||
#define GIC_FDT_IRQ_FLAGS_LEVEL_HI 4
 | 
			
		||||
#define GIC_FDT_IRQ_FLAGS_LEVEL_LO 8
 | 
			
		||||
 | 
			
		||||
#define GIC_FDT_IRQ_PPI_CPU_START 8
 | 
			
		||||
#define GIC_FDT_IRQ_PPI_CPU_WIDTH 8
 | 
			
		||||
 | 
			
		||||
#define PLATFORM_BUS_NUM_IRQS 64
 | 
			
		||||
 | 
			
		||||
static ARMPlatformBusSystemParams platform_bus_params;
 | 
			
		||||
 
 | 
			
		||||
@@ -65,7 +65,7 @@ static void xlnx_ep108_init(MachineState *machine)
 | 
			
		||||
    xlnx_ep108_binfo.kernel_cmdline = machine->kernel_cmdline;
 | 
			
		||||
    xlnx_ep108_binfo.initrd_filename = machine->initrd_filename;
 | 
			
		||||
    xlnx_ep108_binfo.loader_start = 0;
 | 
			
		||||
    arm_load_kernel(&s->soc.cpu[0], &xlnx_ep108_binfo);
 | 
			
		||||
    arm_load_kernel(s->soc.boot_cpu_ptr, &xlnx_ep108_binfo);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static QEMUMachine xlnx_ep108_machine = {
 | 
			
		||||
 
 | 
			
		||||
@@ -64,10 +64,17 @@ static void xlnx_zynqmp_init(Object *obj)
 | 
			
		||||
    XlnxZynqMPState *s = XLNX_ZYNQMP(obj);
 | 
			
		||||
    int i;
 | 
			
		||||
 | 
			
		||||
    for (i = 0; i < XLNX_ZYNQMP_NUM_CPUS; i++) {
 | 
			
		||||
        object_initialize(&s->cpu[i], sizeof(s->cpu[i]),
 | 
			
		||||
    for (i = 0; i < XLNX_ZYNQMP_NUM_APU_CPUS; i++) {
 | 
			
		||||
        object_initialize(&s->apu_cpu[i], sizeof(s->apu_cpu[i]),
 | 
			
		||||
                          "cortex-a53-" TYPE_ARM_CPU);
 | 
			
		||||
        object_property_add_child(obj, "cpu[*]", OBJECT(&s->cpu[i]),
 | 
			
		||||
        object_property_add_child(obj, "apu-cpu[*]", OBJECT(&s->apu_cpu[i]),
 | 
			
		||||
                                  &error_abort);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    for (i = 0; i < XLNX_ZYNQMP_NUM_RPU_CPUS; i++) {
 | 
			
		||||
        object_initialize(&s->rpu_cpu[i], sizeof(s->rpu_cpu[i]),
 | 
			
		||||
                          "cortex-r5-" TYPE_ARM_CPU);
 | 
			
		||||
        object_property_add_child(obj, "rpu-cpu[*]", OBJECT(&s->rpu_cpu[i]),
 | 
			
		||||
                                  &error_abort);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -90,12 +97,13 @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
 | 
			
		||||
    XlnxZynqMPState *s = XLNX_ZYNQMP(dev);
 | 
			
		||||
    MemoryRegion *system_memory = get_system_memory();
 | 
			
		||||
    uint8_t i;
 | 
			
		||||
    const char *boot_cpu = s->boot_cpu ? s->boot_cpu : "apu-cpu[0]";
 | 
			
		||||
    qemu_irq gic_spi[GIC_NUM_SPI_INTR];
 | 
			
		||||
    Error *err = NULL;
 | 
			
		||||
 | 
			
		||||
    qdev_prop_set_uint32(DEVICE(&s->gic), "num-irq", GIC_NUM_SPI_INTR + 32);
 | 
			
		||||
    qdev_prop_set_uint32(DEVICE(&s->gic), "revision", 2);
 | 
			
		||||
    qdev_prop_set_uint32(DEVICE(&s->gic), "num-cpu", XLNX_ZYNQMP_NUM_CPUS);
 | 
			
		||||
    qdev_prop_set_uint32(DEVICE(&s->gic), "num-cpu", XLNX_ZYNQMP_NUM_APU_CPUS);
 | 
			
		||||
    object_property_set_bool(OBJECT(&s->gic), true, "realized", &err);
 | 
			
		||||
    if (err) {
 | 
			
		||||
        error_propagate((errp), (err));
 | 
			
		||||
@@ -121,38 +129,77 @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    for (i = 0; i < XLNX_ZYNQMP_NUM_CPUS; i++) {
 | 
			
		||||
    for (i = 0; i < XLNX_ZYNQMP_NUM_APU_CPUS; i++) {
 | 
			
		||||
        qemu_irq irq;
 | 
			
		||||
        char *name;
 | 
			
		||||
 | 
			
		||||
        object_property_set_int(OBJECT(&s->cpu[i]), QEMU_PSCI_CONDUIT_SMC,
 | 
			
		||||
        object_property_set_int(OBJECT(&s->apu_cpu[i]), QEMU_PSCI_CONDUIT_SMC,
 | 
			
		||||
                                "psci-conduit", &error_abort);
 | 
			
		||||
        if (i > 0) {
 | 
			
		||||
 | 
			
		||||
        name = object_get_canonical_path_component(OBJECT(&s->apu_cpu[i]));
 | 
			
		||||
        if (strcmp(name, boot_cpu)) {
 | 
			
		||||
            /* Secondary CPUs start in PSCI powered-down state */
 | 
			
		||||
            object_property_set_bool(OBJECT(&s->cpu[i]), true,
 | 
			
		||||
            object_property_set_bool(OBJECT(&s->apu_cpu[i]), true,
 | 
			
		||||
                                     "start-powered-off", &error_abort);
 | 
			
		||||
        } else {
 | 
			
		||||
            s->boot_cpu_ptr = &s->apu_cpu[i];
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        object_property_set_int(OBJECT(&s->cpu[i]), GIC_BASE_ADDR,
 | 
			
		||||
        object_property_set_int(OBJECT(&s->apu_cpu[i]), GIC_BASE_ADDR,
 | 
			
		||||
                                "reset-cbar", &err);
 | 
			
		||||
        if (err) {
 | 
			
		||||
            error_propagate((errp), (err));
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        object_property_set_bool(OBJECT(&s->cpu[i]), true, "realized", &err);
 | 
			
		||||
        object_property_set_bool(OBJECT(&s->apu_cpu[i]), true, "realized",
 | 
			
		||||
                                 &err);
 | 
			
		||||
        if (err) {
 | 
			
		||||
            error_propagate((errp), (err));
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        sysbus_connect_irq(SYS_BUS_DEVICE(&s->gic), i,
 | 
			
		||||
                           qdev_get_gpio_in(DEVICE(&s->cpu[i]), ARM_CPU_IRQ));
 | 
			
		||||
                           qdev_get_gpio_in(DEVICE(&s->apu_cpu[i]),
 | 
			
		||||
                                            ARM_CPU_IRQ));
 | 
			
		||||
        irq = qdev_get_gpio_in(DEVICE(&s->gic),
 | 
			
		||||
                               arm_gic_ppi_index(i, ARM_PHYS_TIMER_PPI));
 | 
			
		||||
        qdev_connect_gpio_out(DEVICE(&s->cpu[i]), 0, irq);
 | 
			
		||||
        qdev_connect_gpio_out(DEVICE(&s->apu_cpu[i]), 0, irq);
 | 
			
		||||
        irq = qdev_get_gpio_in(DEVICE(&s->gic),
 | 
			
		||||
                               arm_gic_ppi_index(i, ARM_VIRT_TIMER_PPI));
 | 
			
		||||
        qdev_connect_gpio_out(DEVICE(&s->cpu[i]), 1, irq);
 | 
			
		||||
        qdev_connect_gpio_out(DEVICE(&s->apu_cpu[i]), 1, irq);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    for (i = 0; i < XLNX_ZYNQMP_NUM_RPU_CPUS; i++) {
 | 
			
		||||
        char *name;
 | 
			
		||||
 | 
			
		||||
        name = object_get_canonical_path_component(OBJECT(&s->rpu_cpu[i]));
 | 
			
		||||
        if (strcmp(name, boot_cpu)) {
 | 
			
		||||
            /* Secondary CPUs start in PSCI powered-down state */
 | 
			
		||||
            object_property_set_bool(OBJECT(&s->rpu_cpu[i]), true,
 | 
			
		||||
                                     "start-powered-off", &error_abort);
 | 
			
		||||
        } else {
 | 
			
		||||
            s->boot_cpu_ptr = &s->rpu_cpu[i];
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        object_property_set_bool(OBJECT(&s->rpu_cpu[i]), true, "reset-hivecs",
 | 
			
		||||
                                 &err);
 | 
			
		||||
        if (err != NULL) {
 | 
			
		||||
            error_propagate(errp, err);
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        object_property_set_bool(OBJECT(&s->rpu_cpu[i]), true, "realized",
 | 
			
		||||
                                 &err);
 | 
			
		||||
        if (err) {
 | 
			
		||||
            error_propagate((errp), (err));
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (!s->boot_cpu_ptr) {
 | 
			
		||||
        error_setg(errp, "ZynqMP Boot cpu %s not found\n", boot_cpu);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    for (i = 0; i < GIC_NUM_SPI_INTR; i++) {
 | 
			
		||||
@@ -188,10 +235,16 @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static Property xlnx_zynqmp_props[] = {
 | 
			
		||||
    DEFINE_PROP_STRING("boot-cpu", XlnxZynqMPState, boot_cpu),
 | 
			
		||||
    DEFINE_PROP_END_OF_LIST()
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void xlnx_zynqmp_class_init(ObjectClass *oc, void *data)
 | 
			
		||||
{
 | 
			
		||||
    DeviceClass *dc = DEVICE_CLASS(oc);
 | 
			
		||||
 | 
			
		||||
    dc->props = xlnx_zynqmp_props;
 | 
			
		||||
    dc->realize = xlnx_zynqmp_realize;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -126,9 +126,9 @@ void qbus_set_bus_hotplug_handler(BusState *bus, Error **errp)
 | 
			
		||||
    qbus_set_hotplug_handler_internal(bus, OBJECT(bus), errp);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Create a new device.  This only initializes the device state structure
 | 
			
		||||
   and allows properties to be set.  qdev_init should be called to
 | 
			
		||||
   initialize the actual device emulation.  */
 | 
			
		||||
/* Create a new device.  This only initializes the device state
 | 
			
		||||
   structure and allows properties to be set.  The device still needs
 | 
			
		||||
   to be realized.  See qdev-core.h.  */
 | 
			
		||||
DeviceState *qdev_create(BusState *bus, const char *name)
 | 
			
		||||
{
 | 
			
		||||
    DeviceState *dev;
 | 
			
		||||
@@ -168,27 +168,6 @@ DeviceState *qdev_try_create(BusState *bus, const char *type)
 | 
			
		||||
    return dev;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Initialize a device.  Device properties should be set before calling
 | 
			
		||||
   this function.  IRQs and MMIO regions should be connected/mapped after
 | 
			
		||||
   calling this function.
 | 
			
		||||
   On failure, destroy the device and return negative value.
 | 
			
		||||
   Return 0 on success.  */
 | 
			
		||||
int qdev_init(DeviceState *dev)
 | 
			
		||||
{
 | 
			
		||||
    Error *local_err = NULL;
 | 
			
		||||
 | 
			
		||||
    assert(!dev->realized);
 | 
			
		||||
 | 
			
		||||
    object_property_set_bool(OBJECT(dev), true, "realized", &local_err);
 | 
			
		||||
    if (local_err != NULL) {
 | 
			
		||||
        qerror_report_err(local_err);
 | 
			
		||||
        error_free(local_err);
 | 
			
		||||
        object_unparent(OBJECT(dev));
 | 
			
		||||
        return -1;
 | 
			
		||||
    }
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static QTAILQ_HEAD(device_listeners, DeviceListener) device_listeners
 | 
			
		||||
    = QTAILQ_HEAD_INITIALIZER(device_listeners);
 | 
			
		||||
 | 
			
		||||
@@ -364,13 +343,19 @@ void qdev_simple_device_unplug_cb(HotplugHandler *hotplug_dev,
 | 
			
		||||
    object_unparent(OBJECT(dev));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Like qdev_init(), but terminate program via error_report() instead of
 | 
			
		||||
   returning an error value.  This is okay during machine creation.
 | 
			
		||||
   Don't use for hotplug, because there callers need to recover from
 | 
			
		||||
   failure.  Exception: if you know the device's init() callback can't
 | 
			
		||||
   fail, then qdev_init_nofail() can't fail either, and is therefore
 | 
			
		||||
   usable even then.  But relying on the device implementation that
 | 
			
		||||
   way is somewhat unclean, and best avoided.  */
 | 
			
		||||
/*
 | 
			
		||||
 * Realize @dev.
 | 
			
		||||
 * Device properties should be set before calling this function.  IRQs
 | 
			
		||||
 * and MMIO regions should be connected/mapped after calling this
 | 
			
		||||
 * function.
 | 
			
		||||
 * On failure, report an error with error_report() and terminate the
 | 
			
		||||
 * program.  This is okay during machine creation.  Don't use for
 | 
			
		||||
 * hotplug, because there callers need to recover from failure.
 | 
			
		||||
 * Exception: if you know the device's init() callback can't fail,
 | 
			
		||||
 * then qdev_init_nofail() can't fail either, and is therefore usable
 | 
			
		||||
 * even then.  But relying on the device implementation that way is
 | 
			
		||||
 * somewhat unclean, and best avoided.
 | 
			
		||||
 */
 | 
			
		||||
void qdev_init_nofail(DeviceState *dev)
 | 
			
		||||
{
 | 
			
		||||
    Error *err = NULL;
 | 
			
		||||
@@ -563,6 +548,7 @@ void qdev_pass_gpios(DeviceState *dev, DeviceState *container,
 | 
			
		||||
        object_property_add_alias(OBJECT(container), propname,
 | 
			
		||||
                                  OBJECT(dev), propname,
 | 
			
		||||
                                  &error_abort);
 | 
			
		||||
        g_free(propname);
 | 
			
		||||
    }
 | 
			
		||||
    for (i = 0; i < ngl->num_out; i++) {
 | 
			
		||||
        const char *nm = ngl->name ? ngl->name : "unnamed-gpio-out";
 | 
			
		||||
@@ -571,6 +557,7 @@ void qdev_pass_gpios(DeviceState *dev, DeviceState *container,
 | 
			
		||||
        object_property_add_alias(OBJECT(container), propname,
 | 
			
		||||
                                  OBJECT(dev), propname,
 | 
			
		||||
                                  &error_abort);
 | 
			
		||||
        g_free(propname);
 | 
			
		||||
    }
 | 
			
		||||
    QLIST_REMOVE(ngl, node);
 | 
			
		||||
    QLIST_INSERT_HEAD(&container->gpios, ngl, node);
 | 
			
		||||
 
 | 
			
		||||
@@ -281,19 +281,15 @@ static void sysbus_dev_print(Monitor *mon, DeviceState *dev, int indent)
 | 
			
		||||
static char *sysbus_get_fw_dev_path(DeviceState *dev)
 | 
			
		||||
{
 | 
			
		||||
    SysBusDevice *s = SYS_BUS_DEVICE(dev);
 | 
			
		||||
    char path[40];
 | 
			
		||||
    int off;
 | 
			
		||||
 | 
			
		||||
    off = snprintf(path, sizeof(path), "%s", qdev_fw_name(dev));
 | 
			
		||||
 | 
			
		||||
    if (s->num_mmio) {
 | 
			
		||||
        snprintf(path + off, sizeof(path) - off, "@"TARGET_FMT_plx,
 | 
			
		||||
                 s->mmio[0].addr);
 | 
			
		||||
    } else if (s->num_pio) {
 | 
			
		||||
        snprintf(path + off, sizeof(path) - off, "@i%04x", s->pio[0]);
 | 
			
		||||
        return g_strdup_printf("%s@" TARGET_FMT_plx, qdev_fw_name(dev),
 | 
			
		||||
                               s->mmio[0].addr);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return g_strdup(path);
 | 
			
		||||
    if (s->num_pio) {
 | 
			
		||||
        return g_strdup_printf("%s@i%04x", qdev_fw_name(dev), s->pio[0]);
 | 
			
		||||
    }
 | 
			
		||||
    return g_strdup(qdev_fw_name(dev));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void sysbus_add_io(SysBusDevice *dev, hwaddr addr,
 | 
			
		||||
 
 | 
			
		||||
@@ -403,6 +403,7 @@ DEFINE_Q35_MACHINE(v2_4, "pc-q35-2.4", NULL,
 | 
			
		||||
static void pc_q35_2_3_machine_options(MachineClass *m)
 | 
			
		||||
{
 | 
			
		||||
    pc_q35_2_4_machine_options(m);
 | 
			
		||||
    m->no_floppy = 0;
 | 
			
		||||
    m->alias = NULL;
 | 
			
		||||
    SET_MACHINE_COMPAT(m, PC_COMPAT_2_3);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -11,6 +11,7 @@ common-obj-$(CONFIG_VMMOUSE) += vmmouse.o
 | 
			
		||||
ifeq ($(CONFIG_LINUX),y)
 | 
			
		||||
common-obj-$(CONFIG_VIRTIO) += virtio-input.o
 | 
			
		||||
common-obj-$(CONFIG_VIRTIO) += virtio-input-hid.o
 | 
			
		||||
common-obj-$(CONFIG_VIRTIO) += virtio-input-host.o
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
obj-$(CONFIG_MILKYMIST) += milkymist-softusb.o
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										188
									
								
								hw/input/virtio-input-host.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										188
									
								
								hw/input/virtio-input-host.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,188 @@
 | 
			
		||||
/*
 | 
			
		||||
 * This work is licensed under the terms of the GNU GPL, version 2 or
 | 
			
		||||
 * (at your option) any later version.  See the COPYING file in the
 | 
			
		||||
 * top-level directory.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "qemu-common.h"
 | 
			
		||||
#include "qemu/sockets.h"
 | 
			
		||||
 | 
			
		||||
#include "hw/qdev.h"
 | 
			
		||||
#include "hw/virtio/virtio.h"
 | 
			
		||||
#include "hw/virtio/virtio-input.h"
 | 
			
		||||
 | 
			
		||||
#include "standard-headers/linux/input.h"
 | 
			
		||||
 | 
			
		||||
/* ----------------------------------------------------------------- */
 | 
			
		||||
 | 
			
		||||
static struct virtio_input_config virtio_input_host_config[] = {
 | 
			
		||||
    { /* empty list */ },
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void virtio_input_host_event(void *opaque)
 | 
			
		||||
{
 | 
			
		||||
    VirtIOInputHost *vih = opaque;
 | 
			
		||||
    VirtIOInput *vinput = VIRTIO_INPUT(vih);
 | 
			
		||||
    struct virtio_input_event virtio;
 | 
			
		||||
    struct input_event evdev;
 | 
			
		||||
    int rc;
 | 
			
		||||
 | 
			
		||||
    for (;;) {
 | 
			
		||||
        rc = read(vih->fd, &evdev, sizeof(evdev));
 | 
			
		||||
        if (rc != sizeof(evdev)) {
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        virtio.type  = cpu_to_le16(evdev.type);
 | 
			
		||||
        virtio.code  = cpu_to_le16(evdev.code);
 | 
			
		||||
        virtio.value = cpu_to_le32(evdev.value);
 | 
			
		||||
        virtio_input_send(vinput, &virtio);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void virtio_input_bits_config(VirtIOInputHost *vih,
 | 
			
		||||
                                     int type, int count)
 | 
			
		||||
{
 | 
			
		||||
    virtio_input_config bits;
 | 
			
		||||
    int rc, i, size = 0;
 | 
			
		||||
 | 
			
		||||
    memset(&bits, 0, sizeof(bits));
 | 
			
		||||
    rc = ioctl(vih->fd, EVIOCGBIT(type, count/8), bits.u.bitmap);
 | 
			
		||||
    if (rc < 0) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    for (i = 0; i < count/8; i++) {
 | 
			
		||||
        if (bits.u.bitmap[i]) {
 | 
			
		||||
            size = i+1;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    if (size == 0) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bits.select = VIRTIO_INPUT_CFG_EV_BITS;
 | 
			
		||||
    bits.subsel = type;
 | 
			
		||||
    bits.size   = size;
 | 
			
		||||
    virtio_input_add_config(VIRTIO_INPUT(vih), &bits);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void virtio_input_host_realize(DeviceState *dev, Error **errp)
 | 
			
		||||
{
 | 
			
		||||
    VirtIOInputHost *vih = VIRTIO_INPUT_HOST(dev);
 | 
			
		||||
    VirtIOInput *vinput = VIRTIO_INPUT(dev);
 | 
			
		||||
    virtio_input_config id;
 | 
			
		||||
    struct input_id ids;
 | 
			
		||||
    int rc, ver;
 | 
			
		||||
 | 
			
		||||
    if (!vih->evdev) {
 | 
			
		||||
        error_setg(errp, "evdev property is required");
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    vih->fd = open(vih->evdev, O_RDWR);
 | 
			
		||||
    if (vih->fd < 0)  {
 | 
			
		||||
        error_setg_file_open(errp, errno, vih->evdev);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    qemu_set_nonblock(vih->fd);
 | 
			
		||||
 | 
			
		||||
    rc = ioctl(vih->fd, EVIOCGVERSION, &ver);
 | 
			
		||||
    if (rc < 0) {
 | 
			
		||||
        error_setg(errp, "%s: is not an evdev device", vih->evdev);
 | 
			
		||||
        goto err_close;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    rc = ioctl(vih->fd, EVIOCGRAB, 1);
 | 
			
		||||
    if (rc < 0) {
 | 
			
		||||
        error_setg_errno(errp, errno, "%s: failed to get exclusive access",
 | 
			
		||||
                         vih->evdev);
 | 
			
		||||
        goto err_close;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    memset(&id, 0, sizeof(id));
 | 
			
		||||
    ioctl(vih->fd, EVIOCGNAME(sizeof(id.u.string)-1), id.u.string);
 | 
			
		||||
    id.select = VIRTIO_INPUT_CFG_ID_NAME;
 | 
			
		||||
    id.size = strlen(id.u.string);
 | 
			
		||||
    virtio_input_add_config(vinput, &id);
 | 
			
		||||
 | 
			
		||||
    if (ioctl(vih->fd, EVIOCGID, &ids) == 0) {
 | 
			
		||||
        memset(&id, 0, sizeof(id));
 | 
			
		||||
        id.select = VIRTIO_INPUT_CFG_ID_DEVIDS;
 | 
			
		||||
        id.size = sizeof(struct virtio_input_devids);
 | 
			
		||||
        id.u.ids.bustype = cpu_to_le16(ids.bustype);
 | 
			
		||||
        id.u.ids.vendor  = cpu_to_le16(ids.vendor);
 | 
			
		||||
        id.u.ids.product = cpu_to_le16(ids.product);
 | 
			
		||||
        id.u.ids.version = cpu_to_le16(ids.version);
 | 
			
		||||
        virtio_input_add_config(vinput, &id);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    virtio_input_bits_config(vih, EV_KEY, KEY_CNT);
 | 
			
		||||
    virtio_input_bits_config(vih, EV_REL, REL_CNT);
 | 
			
		||||
    virtio_input_bits_config(vih, EV_ABS, ABS_CNT);
 | 
			
		||||
    virtio_input_bits_config(vih, EV_MSC, MSC_CNT);
 | 
			
		||||
    virtio_input_bits_config(vih, EV_SW,  SW_CNT);
 | 
			
		||||
 | 
			
		||||
    qemu_set_fd_handler(vih->fd, virtio_input_host_event, NULL, vih);
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
err_close:
 | 
			
		||||
    close(vih->fd);
 | 
			
		||||
    vih->fd = -1;
 | 
			
		||||
    return;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void virtio_input_host_unrealize(DeviceState *dev, Error **errp)
 | 
			
		||||
{
 | 
			
		||||
    VirtIOInputHost *vih = VIRTIO_INPUT_HOST(dev);
 | 
			
		||||
 | 
			
		||||
    if (vih->fd > 0) {
 | 
			
		||||
        qemu_set_fd_handler(vih->fd, NULL, NULL, NULL);
 | 
			
		||||
        close(vih->fd);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const VMStateDescription vmstate_virtio_input_host = {
 | 
			
		||||
    .name = "virtio-input-host",
 | 
			
		||||
    .unmigratable = 1,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static Property virtio_input_host_properties[] = {
 | 
			
		||||
    DEFINE_PROP_STRING("evdev", VirtIOInputHost, evdev),
 | 
			
		||||
    DEFINE_PROP_END_OF_LIST(),
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void virtio_input_host_class_init(ObjectClass *klass, void *data)
 | 
			
		||||
{
 | 
			
		||||
    VirtIOInputClass *vic = VIRTIO_INPUT_CLASS(klass);
 | 
			
		||||
    DeviceClass *dc = DEVICE_CLASS(klass);
 | 
			
		||||
 | 
			
		||||
    dc->vmsd           = &vmstate_virtio_input_host;
 | 
			
		||||
    dc->props          = virtio_input_host_properties;
 | 
			
		||||
    vic->realize       = virtio_input_host_realize;
 | 
			
		||||
    vic->unrealize     = virtio_input_host_unrealize;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void virtio_input_host_init(Object *obj)
 | 
			
		||||
{
 | 
			
		||||
    VirtIOInput *vinput = VIRTIO_INPUT(obj);
 | 
			
		||||
 | 
			
		||||
    virtio_input_init_config(vinput, virtio_input_host_config);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const TypeInfo virtio_input_host_info = {
 | 
			
		||||
    .name          = TYPE_VIRTIO_INPUT_HOST,
 | 
			
		||||
    .parent        = TYPE_VIRTIO_INPUT,
 | 
			
		||||
    .instance_size = sizeof(VirtIOInputHost),
 | 
			
		||||
    .instance_init = virtio_input_host_init,
 | 
			
		||||
    .class_init    = virtio_input_host_class_init,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* ----------------------------------------------------------------- */
 | 
			
		||||
 | 
			
		||||
static void virtio_register_types(void)
 | 
			
		||||
{
 | 
			
		||||
    type_register_static(&virtio_input_host_info);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type_init(virtio_register_types)
 | 
			
		||||
@@ -216,7 +216,7 @@ static void virtio_input_device_realize(DeviceState *dev, Error **errp)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    virtio_input_idstr_config(vinput, VIRTIO_INPUT_CFG_ID_SERIAL,
 | 
			
		||||
                              vinput->input.serial);
 | 
			
		||||
                              vinput->serial);
 | 
			
		||||
 | 
			
		||||
    QTAILQ_FOREACH(cfg, &vinput->cfg_list, node) {
 | 
			
		||||
        if (vinput->cfg_size < cfg->config.size) {
 | 
			
		||||
@@ -248,11 +248,17 @@ static void virtio_input_device_unrealize(DeviceState *dev, Error **errp)
 | 
			
		||||
    virtio_cleanup(vdev);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static Property virtio_input_properties[] = {
 | 
			
		||||
    DEFINE_PROP_STRING("serial", VirtIOInput, serial),
 | 
			
		||||
    DEFINE_PROP_END_OF_LIST(),
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void virtio_input_class_init(ObjectClass *klass, void *data)
 | 
			
		||||
{
 | 
			
		||||
    DeviceClass *dc = DEVICE_CLASS(klass);
 | 
			
		||||
    VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
 | 
			
		||||
 | 
			
		||||
    dc->props          = virtio_input_properties;
 | 
			
		||||
    set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
 | 
			
		||||
    vdc->realize      = virtio_input_device_realize;
 | 
			
		||||
    vdc->unrealize    = virtio_input_device_unrealize;
 | 
			
		||||
 
 | 
			
		||||
@@ -102,6 +102,20 @@ static void mcf_intc_write(void *opaque, hwaddr addr,
 | 
			
		||||
    case 0x0c:
 | 
			
		||||
        s->imr = (s->imr & 0xffffffff00000000ull) | (uint32_t)val;
 | 
			
		||||
        break;
 | 
			
		||||
    case 0x1c:
 | 
			
		||||
        if (val & 0x40) {
 | 
			
		||||
            s->imr = ~0ull;
 | 
			
		||||
        } else {
 | 
			
		||||
            s->imr |= (0x1ull << (val & 0x3f));
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
    case 0x1d:
 | 
			
		||||
        if (val & 0x40) {
 | 
			
		||||
            s->imr = 0ull;
 | 
			
		||||
        } else {
 | 
			
		||||
            s->imr &= ~(0x1ull << (val & 0x3f));
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
    default:
 | 
			
		||||
        hw_error("mcf_intc_write: Bad write offset %d\n", offset);
 | 
			
		||||
        break;
 | 
			
		||||
 
 | 
			
		||||
@@ -64,20 +64,6 @@
 | 
			
		||||
#define SPI_IRQ             4
 | 
			
		||||
#define UART16550_IRQ       5
 | 
			
		||||
 | 
			
		||||
static void machine_cpu_reset(MicroBlazeCPU *cpu)
 | 
			
		||||
{
 | 
			
		||||
    CPUMBState *env = &cpu->env;
 | 
			
		||||
 | 
			
		||||
    env->pvr.regs[10] = 0x0e000000; /* virtex 6 */
 | 
			
		||||
    /* setup pvr to match kernel setting */
 | 
			
		||||
    env->pvr.regs[5] |= PVR5_DCACHE_WRITEBACK_MASK;
 | 
			
		||||
    env->pvr.regs[0] |= PVR0_USE_FPU_MASK | PVR0_ENDI;
 | 
			
		||||
    env->pvr.regs[0] = (env->pvr.regs[0] & ~PVR0_VERSION_MASK) | (0x14 << 8);
 | 
			
		||||
    env->pvr.regs[2] ^= PVR2_USE_FPU2_MASK;
 | 
			
		||||
    env->pvr.regs[4] = 0xc56b8000;
 | 
			
		||||
    env->pvr.regs[5] = 0xc56be000;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
petalogix_ml605_init(MachineState *machine)
 | 
			
		||||
{
 | 
			
		||||
@@ -95,6 +81,13 @@ petalogix_ml605_init(MachineState *machine)
 | 
			
		||||
 | 
			
		||||
    /* init CPUs */
 | 
			
		||||
    cpu = MICROBLAZE_CPU(object_new(TYPE_MICROBLAZE_CPU));
 | 
			
		||||
    /* Use FPU but don't use floating point conversion and square
 | 
			
		||||
     * root instructions
 | 
			
		||||
     */
 | 
			
		||||
    object_property_set_int(OBJECT(cpu), 1, "use-fpu", &error_abort);
 | 
			
		||||
    object_property_set_bool(OBJECT(cpu), true, "dcache-writeback",
 | 
			
		||||
                             &error_abort);
 | 
			
		||||
    object_property_set_bool(OBJECT(cpu), true, "endianness", &error_abort);
 | 
			
		||||
    object_property_set_bool(OBJECT(cpu), true, "realized", &error_abort);
 | 
			
		||||
 | 
			
		||||
    /* Attach emulated BRAM through the LMB.  */
 | 
			
		||||
@@ -201,10 +194,15 @@ petalogix_ml605_init(MachineState *machine)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* setup PVR to match kernel settings */
 | 
			
		||||
    cpu->env.pvr.regs[4] = 0xc56b8000;
 | 
			
		||||
    cpu->env.pvr.regs[5] = 0xc56be000;
 | 
			
		||||
    cpu->env.pvr.regs[10] = 0x0e000000; /* virtex 6 */
 | 
			
		||||
 | 
			
		||||
    microblaze_load_kernel(cpu, MEMORY_BASEADDR, ram_size,
 | 
			
		||||
                           machine->initrd_filename,
 | 
			
		||||
                           BINARY_DEVICE_TREE_FILE,
 | 
			
		||||
                           machine_cpu_reset);
 | 
			
		||||
                           NULL);
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -51,18 +51,10 @@
 | 
			
		||||
#define ETHLITE_IRQ         1
 | 
			
		||||
#define UARTLITE_IRQ        3
 | 
			
		||||
 | 
			
		||||
static void machine_cpu_reset(MicroBlazeCPU *cpu)
 | 
			
		||||
{
 | 
			
		||||
    CPUMBState *env = &cpu->env;
 | 
			
		||||
 | 
			
		||||
    env->pvr.regs[10] = 0x0c000000; /* spartan 3a dsp family.  */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
petalogix_s3adsp1800_init(MachineState *machine)
 | 
			
		||||
{
 | 
			
		||||
    ram_addr_t ram_size = machine->ram_size;
 | 
			
		||||
    const char *cpu_model = machine->cpu_model;
 | 
			
		||||
    DeviceState *dev;
 | 
			
		||||
    MicroBlazeCPU *cpu;
 | 
			
		||||
    DriveInfo *dinfo;
 | 
			
		||||
@@ -73,11 +65,8 @@ petalogix_s3adsp1800_init(MachineState *machine)
 | 
			
		||||
    qemu_irq irq[32];
 | 
			
		||||
    MemoryRegion *sysmem = get_system_memory();
 | 
			
		||||
 | 
			
		||||
    /* init CPUs */
 | 
			
		||||
    if (cpu_model == NULL) {
 | 
			
		||||
        cpu_model = "microblaze";
 | 
			
		||||
    }
 | 
			
		||||
    cpu = cpu_mb_init(cpu_model);
 | 
			
		||||
    cpu = MICROBLAZE_CPU(object_new(TYPE_MICROBLAZE_CPU));
 | 
			
		||||
    object_property_set_bool(OBJECT(cpu), true, "realized", &error_abort);
 | 
			
		||||
 | 
			
		||||
    /* Attach emulated BRAM through the LMB.  */
 | 
			
		||||
    memory_region_init_ram(phys_lmb_bram, NULL,
 | 
			
		||||
@@ -132,7 +121,7 @@ petalogix_s3adsp1800_init(MachineState *machine)
 | 
			
		||||
    microblaze_load_kernel(cpu, ddr_base, ram_size,
 | 
			
		||||
                           machine->initrd_filename,
 | 
			
		||||
                           BINARY_DEVICE_TREE_FILE,
 | 
			
		||||
                           machine_cpu_reset);
 | 
			
		||||
                           NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static QEMUMachine petalogix_s3adsp1800_machine = {
 | 
			
		||||
 
 | 
			
		||||
@@ -698,7 +698,6 @@ static void ivshmem_write_config(PCIDevice *pci_dev, uint32_t address,
 | 
			
		||||
				 uint32_t val, int len)
 | 
			
		||||
{
 | 
			
		||||
    pci_default_write_config(pci_dev, address, val, len);
 | 
			
		||||
    msix_write_config(pci_dev, address, val, len);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int pci_ivshmem_init(PCIDevice *dev)
 | 
			
		||||
 
 | 
			
		||||
@@ -38,6 +38,7 @@
 | 
			
		||||
#include "standard-headers/linux/virtio_ring.h"
 | 
			
		||||
#include "hw/virtio/vhost.h"
 | 
			
		||||
#include "hw/virtio/virtio-bus.h"
 | 
			
		||||
#include "hw/virtio/virtio-access.h"
 | 
			
		||||
 | 
			
		||||
struct vhost_net {
 | 
			
		||||
    struct vhost_dev dev;
 | 
			
		||||
@@ -162,7 +163,7 @@ struct vhost_net *vhost_net_init(VhostNetOptions *options)
 | 
			
		||||
    net->dev.vq_index = net->nc->queue_index;
 | 
			
		||||
 | 
			
		||||
    r = vhost_dev_init(&net->dev, options->opaque,
 | 
			
		||||
                       options->backend_type, options->force);
 | 
			
		||||
                       options->backend_type);
 | 
			
		||||
    if (r < 0) {
 | 
			
		||||
        goto fail;
 | 
			
		||||
    }
 | 
			
		||||
@@ -187,16 +188,32 @@ fail:
 | 
			
		||||
    return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool vhost_net_query(VHostNetState *net, VirtIODevice *dev)
 | 
			
		||||
{
 | 
			
		||||
    return vhost_dev_query(&net->dev, dev);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void vhost_net_set_vq_index(struct vhost_net *net, int vq_index)
 | 
			
		||||
{
 | 
			
		||||
    net->dev.vq_index = vq_index;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int vhost_net_set_vnet_endian(VirtIODevice *dev, NetClientState *peer,
 | 
			
		||||
                                     bool set)
 | 
			
		||||
{
 | 
			
		||||
    int r = 0;
 | 
			
		||||
 | 
			
		||||
    if (virtio_has_feature(dev, VIRTIO_F_VERSION_1) ||
 | 
			
		||||
        (virtio_legacy_is_cross_endian(dev) && !virtio_is_big_endian(dev))) {
 | 
			
		||||
        r = qemu_set_vnet_le(peer, set);
 | 
			
		||||
        if (r) {
 | 
			
		||||
            error_report("backend does not support LE vnet headers");
 | 
			
		||||
        }
 | 
			
		||||
    } else if (virtio_legacy_is_cross_endian(dev)) {
 | 
			
		||||
        r = qemu_set_vnet_be(peer, set);
 | 
			
		||||
        if (r) {
 | 
			
		||||
            error_report("backend does not support BE vnet headers");
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return r;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int vhost_net_start_one(struct vhost_net *net,
 | 
			
		||||
                               VirtIODevice *dev)
 | 
			
		||||
{
 | 
			
		||||
@@ -281,19 +298,6 @@ static void vhost_net_stop_one(struct vhost_net *net,
 | 
			
		||||
    vhost_dev_disable_notifiers(&net->dev, dev);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static bool vhost_net_device_endian_ok(VirtIODevice *vdev)
 | 
			
		||||
{
 | 
			
		||||
#ifdef TARGET_IS_BIENDIAN
 | 
			
		||||
#ifdef HOST_WORDS_BIGENDIAN
 | 
			
		||||
    return virtio_is_big_endian(vdev);
 | 
			
		||||
#else
 | 
			
		||||
    return !virtio_is_big_endian(vdev);
 | 
			
		||||
#endif
 | 
			
		||||
#else
 | 
			
		||||
    return true;
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int vhost_net_start(VirtIODevice *dev, NetClientState *ncs,
 | 
			
		||||
                    int total_queues)
 | 
			
		||||
{
 | 
			
		||||
@@ -302,15 +306,14 @@ int vhost_net_start(VirtIODevice *dev, NetClientState *ncs,
 | 
			
		||||
    VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(vbus);
 | 
			
		||||
    int r, e, i;
 | 
			
		||||
 | 
			
		||||
    if (!vhost_net_device_endian_ok(dev)) {
 | 
			
		||||
        error_report("vhost-net does not support cross-endian");
 | 
			
		||||
    if (!k->set_guest_notifiers) {
 | 
			
		||||
        error_report("binding does not support guest notifiers");
 | 
			
		||||
        r = -ENOSYS;
 | 
			
		||||
        goto err;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (!k->set_guest_notifiers) {
 | 
			
		||||
        error_report("binding does not support guest notifiers");
 | 
			
		||||
        r = -ENOSYS;
 | 
			
		||||
    r = vhost_net_set_vnet_endian(dev, ncs[0].peer, true);
 | 
			
		||||
    if (r < 0) {
 | 
			
		||||
        goto err;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -321,7 +324,7 @@ int vhost_net_start(VirtIODevice *dev, NetClientState *ncs,
 | 
			
		||||
    r = k->set_guest_notifiers(qbus->parent, total_queues * 2, true);
 | 
			
		||||
    if (r < 0) {
 | 
			
		||||
        error_report("Error binding guest notifier: %d", -r);
 | 
			
		||||
        goto err;
 | 
			
		||||
        goto err_endian;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    for (i = 0; i < total_queues; i++) {
 | 
			
		||||
@@ -343,6 +346,8 @@ err_start:
 | 
			
		||||
        fprintf(stderr, "vhost guest notifier cleanup failed: %d\n", e);
 | 
			
		||||
        fflush(stderr);
 | 
			
		||||
    }
 | 
			
		||||
err_endian:
 | 
			
		||||
    vhost_net_set_vnet_endian(dev, ncs[0].peer, false);
 | 
			
		||||
err:
 | 
			
		||||
    return r;
 | 
			
		||||
}
 | 
			
		||||
@@ -365,6 +370,8 @@ void vhost_net_stop(VirtIODevice *dev, NetClientState *ncs,
 | 
			
		||||
        fflush(stderr);
 | 
			
		||||
    }
 | 
			
		||||
    assert(r >= 0);
 | 
			
		||||
 | 
			
		||||
    assert(vhost_net_set_vnet_endian(dev, ncs[0].peer, false) >= 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void vhost_net_cleanup(struct vhost_net *net)
 | 
			
		||||
@@ -412,11 +419,6 @@ struct vhost_net *vhost_net_init(VhostNetOptions *options)
 | 
			
		||||
    return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool vhost_net_query(VHostNetState *net, VirtIODevice *dev)
 | 
			
		||||
{
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int vhost_net_start(VirtIODevice *dev,
 | 
			
		||||
                    NetClientState *ncs,
 | 
			
		||||
                    int total_queues)
 | 
			
		||||
 
 | 
			
		||||
@@ -128,10 +128,6 @@ static void virtio_net_vhost_status(VirtIONet *n, uint8_t status)
 | 
			
		||||
    if (!n->vhost_started) {
 | 
			
		||||
        int r, i;
 | 
			
		||||
 | 
			
		||||
        if (!vhost_net_query(get_vhost_net(nc->peer), vdev)) {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /* Any packets outstanding? Purge them to avoid touching rings
 | 
			
		||||
         * when vhost is running.
 | 
			
		||||
         */
 | 
			
		||||
 
 | 
			
		||||
@@ -2477,14 +2477,6 @@ static const VMStateDescription vmstate_vmxnet3 = {
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
vmxnet3_write_config(PCIDevice *pci_dev, uint32_t addr, uint32_t val, int len)
 | 
			
		||||
{
 | 
			
		||||
    pci_default_write_config(pci_dev, addr, val, len);
 | 
			
		||||
    msix_write_config(pci_dev, addr, val, len);
 | 
			
		||||
    msi_write_config(pci_dev, addr, val, len);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static Property vmxnet3_properties[] = {
 | 
			
		||||
    DEFINE_NIC_PROPERTIES(VMXNET3State, conf),
 | 
			
		||||
    DEFINE_PROP_END_OF_LIST(),
 | 
			
		||||
@@ -2503,7 +2495,6 @@ static void vmxnet3_class_init(ObjectClass *class, void *data)
 | 
			
		||||
    c->class_id = PCI_CLASS_NETWORK_ETHERNET;
 | 
			
		||||
    c->subsystem_vendor_id = PCI_VENDOR_ID_VMWARE;
 | 
			
		||||
    c->subsystem_id = PCI_DEVICE_ID_VMWARE_VMXNET3;
 | 
			
		||||
    c->config_write = vmxnet3_write_config,
 | 
			
		||||
    dc->desc = "VMWare Paravirtualized Ethernet v3";
 | 
			
		||||
    dc->reset = vmxnet3_qdev_reset;
 | 
			
		||||
    dc->vmsd = &vmstate_vmxnet3;
 | 
			
		||||
 
 | 
			
		||||
@@ -216,6 +216,7 @@ static void ccw_machine_class_init(ObjectClass *oc, void *data)
 | 
			
		||||
    mc->no_sdcard = 1;
 | 
			
		||||
    mc->use_sclp = 1;
 | 
			
		||||
    mc->max_cpus = 255;
 | 
			
		||||
    mc->is_default = 1;
 | 
			
		||||
    nc->nmi_monitor_handler = s390_nmi;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -345,7 +345,6 @@ static void s390_machine_class_init(ObjectClass *oc, void *data)
 | 
			
		||||
    mc->no_floppy = 1;
 | 
			
		||||
    mc->no_cdrom = 1;
 | 
			
		||||
    mc->no_sdcard = 1;
 | 
			
		||||
    mc->is_default = 1;
 | 
			
		||||
    nc->nmi_monitor_handler = s390_nmi;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1401,6 +1401,10 @@ static void virtio_ccw_device_plugged(DeviceState *d, Error **errp)
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (!kvm_eventfds_enabled()) {
 | 
			
		||||
        dev->flags &= ~VIRTIO_CCW_FLAG_USE_IOEVENTFD;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    sch->id.cu_model = virtio_bus_get_vdev_id(&dev->bus);
 | 
			
		||||
 | 
			
		||||
    css_generate_sch_crws(sch->cssid, sch->ssid, sch->schid,
 | 
			
		||||
 
 | 
			
		||||
@@ -2407,13 +2407,6 @@ static void megasas_scsi_realize(PCIDevice *dev, Error **errp)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
megasas_write_config(PCIDevice *pci, uint32_t addr, uint32_t val, int len)
 | 
			
		||||
{
 | 
			
		||||
    pci_default_write_config(pci, addr, val, len);
 | 
			
		||||
    msi_write_config(pci, addr, val, len);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static Property megasas_properties_gen1[] = {
 | 
			
		||||
    DEFINE_PROP_UINT32("max_sge", MegasasState, fw_sge,
 | 
			
		||||
                       MEGASAS_DEFAULT_SGE),
 | 
			
		||||
@@ -2516,7 +2509,6 @@ static void megasas_class_init(ObjectClass *oc, void *data)
 | 
			
		||||
    dc->vmsd = info->vmsd;
 | 
			
		||||
    set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
 | 
			
		||||
    dc->desc = info->desc;
 | 
			
		||||
    pc->config_write = megasas_write_config;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const TypeInfo megasas_info = {
 | 
			
		||||
 
 | 
			
		||||
@@ -246,7 +246,7 @@ static void vhost_scsi_realize(DeviceState *dev, Error **errp)
 | 
			
		||||
    s->dev.backend_features = 0;
 | 
			
		||||
 | 
			
		||||
    ret = vhost_dev_init(&s->dev, (void *)(uintptr_t)vhostfd,
 | 
			
		||||
                         VHOST_BACKEND_TYPE_KERNEL, true);
 | 
			
		||||
                         VHOST_BACKEND_TYPE_KERNEL);
 | 
			
		||||
    if (ret < 0) {
 | 
			
		||||
        error_setg(errp, "vhost-scsi: vhost initialization failed: %s",
 | 
			
		||||
                   strerror(-ret));
 | 
			
		||||
 
 | 
			
		||||
@@ -1174,13 +1174,6 @@ static const VMStateDescription vmstate_pvscsi = {
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
pvscsi_write_config(PCIDevice *pci, uint32_t addr, uint32_t val, int len)
 | 
			
		||||
{
 | 
			
		||||
    pci_default_write_config(pci, addr, val, len);
 | 
			
		||||
    msi_write_config(pci, addr, val, len);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static Property pvscsi_properties[] = {
 | 
			
		||||
    DEFINE_PROP_UINT8("use_msg", PVSCSIState, use_msg, 1),
 | 
			
		||||
    DEFINE_PROP_END_OF_LIST(),
 | 
			
		||||
@@ -1202,7 +1195,6 @@ static void pvscsi_class_init(ObjectClass *klass, void *data)
 | 
			
		||||
    dc->vmsd = &vmstate_pvscsi;
 | 
			
		||||
    dc->props = pvscsi_properties;
 | 
			
		||||
    set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
 | 
			
		||||
    k->config_write = pvscsi_write_config;
 | 
			
		||||
    hc->unplug = pvscsi_hot_unplug;
 | 
			
		||||
    hc->plug = pvscsi_hotplug;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -196,6 +196,12 @@ static uint64_t pit_ioport_read(void *opaque, hwaddr addr,
 | 
			
		||||
    PITChannelState *s;
 | 
			
		||||
 | 
			
		||||
    addr &= 3;
 | 
			
		||||
 | 
			
		||||
    if (addr == 3) {
 | 
			
		||||
        /* Mode/Command register is write only, read is ignored */
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    s = &pit->channels[addr];
 | 
			
		||||
    if (s->status_latched) {
 | 
			
		||||
        s->status_latched = 0;
 | 
			
		||||
 
 | 
			
		||||
@@ -723,6 +723,12 @@ static int rtc_post_load(void *opaque, int version_id)
 | 
			
		||||
        check_update_timer(s);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    uint64_t now = qemu_clock_get_ns(rtc_clock);
 | 
			
		||||
    if (now < s->next_periodic_time ||
 | 
			
		||||
        now > (s->next_periodic_time + get_max_clock_jump())) {
 | 
			
		||||
        periodic_timer_update(s, qemu_clock_get_ns(rtc_clock));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
#ifdef TARGET_I386
 | 
			
		||||
    if (version_id >= 2) {
 | 
			
		||||
        if (s->lost_tick_policy == LOST_TICK_POLICY_SLEW) {
 | 
			
		||||
 
 | 
			
		||||
@@ -14,8 +14,8 @@
 | 
			
		||||
 *  Copyright Red Hat, Inc. 2012
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <linux/vfio.h>
 | 
			
		||||
#include <sys/ioctl.h>
 | 
			
		||||
#include <linux/vfio.h>
 | 
			
		||||
 | 
			
		||||
#include "hw/vfio/vfio-platform.h"
 | 
			
		||||
#include "qemu/error-report.h"
 | 
			
		||||
 
 | 
			
		||||
@@ -17,9 +17,11 @@
 | 
			
		||||
#include "hw/hw.h"
 | 
			
		||||
#include "qemu/atomic.h"
 | 
			
		||||
#include "qemu/range.h"
 | 
			
		||||
#include "qemu/error-report.h"
 | 
			
		||||
#include <linux/vhost.h>
 | 
			
		||||
#include "exec/address-spaces.h"
 | 
			
		||||
#include "hw/virtio/virtio-bus.h"
 | 
			
		||||
#include "hw/virtio/virtio-access.h"
 | 
			
		||||
#include "migration/migration.h"
 | 
			
		||||
 | 
			
		||||
static struct vhost_log *vhost_log;
 | 
			
		||||
@@ -689,6 +691,27 @@ static void vhost_log_stop(MemoryListener *listener,
 | 
			
		||||
    /* FIXME: implement */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int vhost_virtqueue_set_vring_endian_legacy(struct vhost_dev *dev,
 | 
			
		||||
                                                   bool is_big_endian,
 | 
			
		||||
                                                   int vhost_vq_index)
 | 
			
		||||
{
 | 
			
		||||
    struct vhost_vring_state s = {
 | 
			
		||||
        .index = vhost_vq_index,
 | 
			
		||||
        .num = is_big_endian
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    if (!dev->vhost_ops->vhost_call(dev, VHOST_SET_VRING_ENDIAN, &s)) {
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (errno == ENOTTY) {
 | 
			
		||||
        error_report("vhost does not support cross-endian");
 | 
			
		||||
        return -ENOSYS;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return -errno;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int vhost_virtqueue_start(struct vhost_dev *dev,
 | 
			
		||||
                                struct VirtIODevice *vdev,
 | 
			
		||||
                                struct vhost_virtqueue *vq,
 | 
			
		||||
@@ -719,6 +742,16 @@ static int vhost_virtqueue_start(struct vhost_dev *dev,
 | 
			
		||||
        return -errno;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (!virtio_has_feature(vdev, VIRTIO_F_VERSION_1) &&
 | 
			
		||||
        virtio_legacy_is_cross_endian(vdev)) {
 | 
			
		||||
        r = vhost_virtqueue_set_vring_endian_legacy(dev,
 | 
			
		||||
                                                    virtio_is_big_endian(vdev),
 | 
			
		||||
                                                    vhost_vq_index);
 | 
			
		||||
        if (r) {
 | 
			
		||||
            return -errno;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    s = l = virtio_queue_get_desc_size(vdev, idx);
 | 
			
		||||
    a = virtio_queue_get_desc_addr(vdev, idx);
 | 
			
		||||
    vq->desc = cpu_physical_memory_map(a, &l, 0);
 | 
			
		||||
@@ -789,8 +822,9 @@ static void vhost_virtqueue_stop(struct vhost_dev *dev,
 | 
			
		||||
                                    struct vhost_virtqueue *vq,
 | 
			
		||||
                                    unsigned idx)
 | 
			
		||||
{
 | 
			
		||||
    int vhost_vq_index = idx - dev->vq_index;
 | 
			
		||||
    struct vhost_vring_state state = {
 | 
			
		||||
        .index = idx - dev->vq_index
 | 
			
		||||
        .index = vhost_vq_index,
 | 
			
		||||
    };
 | 
			
		||||
    int r;
 | 
			
		||||
    assert(idx >= dev->vq_index && idx < dev->vq_index + dev->nvqs);
 | 
			
		||||
@@ -801,6 +835,20 @@ static void vhost_virtqueue_stop(struct vhost_dev *dev,
 | 
			
		||||
    }
 | 
			
		||||
    virtio_queue_set_last_avail_idx(vdev, idx, state.num);
 | 
			
		||||
    virtio_queue_invalidate_signalled_used(vdev, idx);
 | 
			
		||||
 | 
			
		||||
    /* In the cross-endian case, we need to reset the vring endianness to
 | 
			
		||||
     * native as legacy devices expect so by default.
 | 
			
		||||
     */
 | 
			
		||||
    if (!virtio_has_feature(vdev, VIRTIO_F_VERSION_1) &&
 | 
			
		||||
        virtio_legacy_is_cross_endian(vdev)) {
 | 
			
		||||
        r = vhost_virtqueue_set_vring_endian_legacy(dev,
 | 
			
		||||
                                                    !virtio_is_big_endian(vdev),
 | 
			
		||||
                                                    vhost_vq_index);
 | 
			
		||||
        if (r < 0) {
 | 
			
		||||
            error_report("failed to reset vring endianness");
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    assert (r >= 0);
 | 
			
		||||
    cpu_physical_memory_unmap(vq->ring, virtio_queue_get_ring_size(vdev, idx),
 | 
			
		||||
                              0, virtio_queue_get_ring_size(vdev, idx));
 | 
			
		||||
@@ -853,7 +901,7 @@ static void vhost_virtqueue_cleanup(struct vhost_virtqueue *vq)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int vhost_dev_init(struct vhost_dev *hdev, void *opaque,
 | 
			
		||||
                   VhostBackendType backend_type, bool force)
 | 
			
		||||
                   VhostBackendType backend_type)
 | 
			
		||||
{
 | 
			
		||||
    uint64_t features;
 | 
			
		||||
    int i, r;
 | 
			
		||||
@@ -916,7 +964,6 @@ int vhost_dev_init(struct vhost_dev *hdev, void *opaque,
 | 
			
		||||
    hdev->started = false;
 | 
			
		||||
    hdev->memory_changed = false;
 | 
			
		||||
    memory_listener_register(&hdev->memory_listener, &address_space_memory);
 | 
			
		||||
    hdev->force = force;
 | 
			
		||||
    return 0;
 | 
			
		||||
fail_vq:
 | 
			
		||||
    while (--i >= 0) {
 | 
			
		||||
@@ -944,17 +991,6 @@ void vhost_dev_cleanup(struct vhost_dev *hdev)
 | 
			
		||||
    hdev->vhost_ops->vhost_backend_cleanup(hdev);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool vhost_dev_query(struct vhost_dev *hdev, VirtIODevice *vdev)
 | 
			
		||||
{
 | 
			
		||||
    BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vdev)));
 | 
			
		||||
    VirtioBusState *vbus = VIRTIO_BUS(qbus);
 | 
			
		||||
    VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(vbus);
 | 
			
		||||
 | 
			
		||||
    return !k->query_guest_notifiers ||
 | 
			
		||||
           k->query_guest_notifiers(qbus->parent) ||
 | 
			
		||||
           hdev->force;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Stop processing guest IO notifications in qemu.
 | 
			
		||||
 * Start processing them in vhost in kernel.
 | 
			
		||||
 */
 | 
			
		||||
 
 | 
			
		||||
@@ -1900,8 +1900,7 @@ static const TypeInfo virtio_rng_pci_info = {
 | 
			
		||||
 | 
			
		||||
/* virtio-input-pci */
 | 
			
		||||
 | 
			
		||||
static Property virtio_input_hid_pci_properties[] = {
 | 
			
		||||
    DEFINE_VIRTIO_INPUT_PROPERTIES(VirtIOInputPCI, vdev.input),
 | 
			
		||||
static Property virtio_input_pci_properties[] = {
 | 
			
		||||
    DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 2),
 | 
			
		||||
    DEFINE_PROP_END_OF_LIST(),
 | 
			
		||||
};
 | 
			
		||||
@@ -1924,19 +1923,13 @@ static void virtio_input_pci_class_init(ObjectClass *klass, void *data)
 | 
			
		||||
    VirtioPCIClass *k = VIRTIO_PCI_CLASS(klass);
 | 
			
		||||
    PCIDeviceClass *pcidev_k = PCI_DEVICE_CLASS(klass);
 | 
			
		||||
 | 
			
		||||
    dc->props = virtio_input_pci_properties;
 | 
			
		||||
    k->realize = virtio_input_pci_realize;
 | 
			
		||||
    set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
 | 
			
		||||
 | 
			
		||||
    pcidev_k->class_id = PCI_CLASS_INPUT_OTHER;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void virtio_input_hid_pci_class_init(ObjectClass *klass, void *data)
 | 
			
		||||
{
 | 
			
		||||
    DeviceClass *dc = DEVICE_CLASS(klass);
 | 
			
		||||
 | 
			
		||||
    dc->props = virtio_input_hid_pci_properties;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void virtio_input_hid_kbd_pci_class_init(ObjectClass *klass, void *data)
 | 
			
		||||
{
 | 
			
		||||
    PCIDeviceClass *pcidev_k = PCI_DEVICE_CLASS(klass);
 | 
			
		||||
@@ -1955,22 +1948,33 @@ static void virtio_input_hid_mouse_pci_class_init(ObjectClass *klass,
 | 
			
		||||
static void virtio_keyboard_initfn(Object *obj)
 | 
			
		||||
{
 | 
			
		||||
    VirtIOInputHIDPCI *dev = VIRTIO_INPUT_HID_PCI(obj);
 | 
			
		||||
    object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_KEYBOARD);
 | 
			
		||||
    object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
 | 
			
		||||
 | 
			
		||||
    virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev),
 | 
			
		||||
                                TYPE_VIRTIO_KEYBOARD);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void virtio_mouse_initfn(Object *obj)
 | 
			
		||||
{
 | 
			
		||||
    VirtIOInputHIDPCI *dev = VIRTIO_INPUT_HID_PCI(obj);
 | 
			
		||||
    object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_MOUSE);
 | 
			
		||||
    object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
 | 
			
		||||
 | 
			
		||||
    virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev),
 | 
			
		||||
                                TYPE_VIRTIO_MOUSE);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void virtio_tablet_initfn(Object *obj)
 | 
			
		||||
{
 | 
			
		||||
    VirtIOInputHIDPCI *dev = VIRTIO_INPUT_HID_PCI(obj);
 | 
			
		||||
    object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_TABLET);
 | 
			
		||||
    object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
 | 
			
		||||
 | 
			
		||||
    virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev),
 | 
			
		||||
                                TYPE_VIRTIO_TABLET);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void virtio_host_initfn(Object *obj)
 | 
			
		||||
{
 | 
			
		||||
    VirtIOInputHostPCI *dev = VIRTIO_INPUT_HOST_PCI(obj);
 | 
			
		||||
 | 
			
		||||
    virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev),
 | 
			
		||||
                                TYPE_VIRTIO_INPUT_HOST);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const TypeInfo virtio_input_pci_info = {
 | 
			
		||||
@@ -1985,7 +1989,6 @@ static const TypeInfo virtio_input_hid_pci_info = {
 | 
			
		||||
    .name          = TYPE_VIRTIO_INPUT_HID_PCI,
 | 
			
		||||
    .parent        = TYPE_VIRTIO_INPUT_PCI,
 | 
			
		||||
    .instance_size = sizeof(VirtIOInputHIDPCI),
 | 
			
		||||
    .class_init    = virtio_input_hid_pci_class_init,
 | 
			
		||||
    .abstract      = true,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@@ -2012,6 +2015,13 @@ static const TypeInfo virtio_tablet_pci_info = {
 | 
			
		||||
    .instance_init = virtio_tablet_initfn,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static const TypeInfo virtio_host_pci_info = {
 | 
			
		||||
    .name          = TYPE_VIRTIO_INPUT_HOST_PCI,
 | 
			
		||||
    .parent        = TYPE_VIRTIO_INPUT_PCI,
 | 
			
		||||
    .instance_size = sizeof(VirtIOInputHostPCI),
 | 
			
		||||
    .instance_init = virtio_host_initfn,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* virtio-pci-bus */
 | 
			
		||||
 | 
			
		||||
static void virtio_pci_bus_new(VirtioBusState *bus, size_t bus_size,
 | 
			
		||||
@@ -2058,6 +2068,7 @@ static void virtio_pci_register_types(void)
 | 
			
		||||
    type_register_static(&virtio_keyboard_pci_info);
 | 
			
		||||
    type_register_static(&virtio_mouse_pci_info);
 | 
			
		||||
    type_register_static(&virtio_tablet_pci_info);
 | 
			
		||||
    type_register_static(&virtio_host_pci_info);
 | 
			
		||||
    type_register_static(&virtio_pci_bus_info);
 | 
			
		||||
    type_register_static(&virtio_pci_info);
 | 
			
		||||
#ifdef CONFIG_VIRTFS
 | 
			
		||||
 
 | 
			
		||||
@@ -43,6 +43,7 @@ typedef struct VHostSCSIPCI VHostSCSIPCI;
 | 
			
		||||
typedef struct VirtIORngPCI VirtIORngPCI;
 | 
			
		||||
typedef struct VirtIOInputPCI VirtIOInputPCI;
 | 
			
		||||
typedef struct VirtIOInputHIDPCI VirtIOInputHIDPCI;
 | 
			
		||||
typedef struct VirtIOInputHostPCI VirtIOInputHostPCI;
 | 
			
		||||
typedef struct VirtIOGPUPCI VirtIOGPUPCI;
 | 
			
		||||
 | 
			
		||||
/* virtio-pci-bus */
 | 
			
		||||
@@ -263,6 +264,15 @@ struct VirtIOInputHIDPCI {
 | 
			
		||||
    VirtIOInputHID vdev;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define TYPE_VIRTIO_INPUT_HOST_PCI "virtio-input-host-pci"
 | 
			
		||||
#define VIRTIO_INPUT_HOST_PCI(obj) \
 | 
			
		||||
        OBJECT_CHECK(VirtIOInputHostPCI, (obj), TYPE_VIRTIO_INPUT_HOST_PCI)
 | 
			
		||||
 | 
			
		||||
struct VirtIOInputHostPCI {
 | 
			
		||||
    VirtIOPCIProxy parent_obj;
 | 
			
		||||
    VirtIOInputHost vdev;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * virtio-gpu-pci: This extends VirtioPCIProxy.
 | 
			
		||||
 */
 | 
			
		||||
 
 | 
			
		||||
@@ -399,6 +399,8 @@ uint64_t helper_ldq_cmmu(CPUArchState *env, target_ulong addr, int mmu_idx);
 | 
			
		||||
#undef MEMSUFFIX
 | 
			
		||||
#undef SOFTMMU_CODE_ACCESS
 | 
			
		||||
 | 
			
		||||
#endif /* defined(CONFIG_USER_ONLY) */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * tlb_vaddr_to_host:
 | 
			
		||||
 * @env: CPUArchState
 | 
			
		||||
@@ -417,6 +419,9 @@ uint64_t helper_ldq_cmmu(CPUArchState *env, target_ulong addr, int mmu_idx);
 | 
			
		||||
static inline void *tlb_vaddr_to_host(CPUArchState *env, target_ulong addr,
 | 
			
		||||
                                      int access_type, int mmu_idx)
 | 
			
		||||
{
 | 
			
		||||
#if defined(CONFIG_USER_ONLY)
 | 
			
		||||
    return g2h(vaddr);
 | 
			
		||||
#else
 | 
			
		||||
    int index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
 | 
			
		||||
    CPUTLBEntry *tlbentry = &env->tlb_table[mmu_idx][index];
 | 
			
		||||
    target_ulong tlb_addr;
 | 
			
		||||
@@ -449,8 +454,7 @@ static inline void *tlb_vaddr_to_host(CPUArchState *env, target_ulong addr,
 | 
			
		||||
 | 
			
		||||
    haddr = addr + env->tlb_table[mmu_idx][index].addend;
 | 
			
		||||
    return (void *)haddr;
 | 
			
		||||
#endif /* defined(CONFIG_USER_ONLY) */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif /* defined(CONFIG_USER_ONLY) */
 | 
			
		||||
 | 
			
		||||
#endif /* CPU_LDST_H */
 | 
			
		||||
 
 | 
			
		||||
@@ -95,10 +95,4 @@ extern bool gdb_has_xml;
 | 
			
		||||
/* in gdbstub-xml.c, generated by scripts/feature_to_c.sh */
 | 
			
		||||
extern const char *const xml_builtin[][2];
 | 
			
		||||
 | 
			
		||||
/* Command line option defining whether semihosting should go via gdb or not */
 | 
			
		||||
extern int semihosting_target;
 | 
			
		||||
#define SEMIHOSTING_TARGET_AUTO     0
 | 
			
		||||
#define SEMIHOSTING_TARGET_NATIVE   1
 | 
			
		||||
#define SEMIHOSTING_TARGET_GDB      2
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										62
									
								
								include/exec/semihost.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								include/exec/semihost.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,62 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Semihosting support
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright (c) 2015 Imagination Technologies
 | 
			
		||||
 *
 | 
			
		||||
 * 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/>.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef SEMIHOST_H
 | 
			
		||||
#define SEMIHOST_H
 | 
			
		||||
 | 
			
		||||
typedef enum SemihostingTarget {
 | 
			
		||||
    SEMIHOSTING_TARGET_AUTO = 0,
 | 
			
		||||
    SEMIHOSTING_TARGET_NATIVE,
 | 
			
		||||
    SEMIHOSTING_TARGET_GDB
 | 
			
		||||
} SemihostingTarget;
 | 
			
		||||
 | 
			
		||||
#ifdef CONFIG_USER_ONLY
 | 
			
		||||
static inline bool semihosting_enabled(void)
 | 
			
		||||
{
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline SemihostingTarget semihosting_get_target(void)
 | 
			
		||||
{
 | 
			
		||||
    return SEMIHOSTING_TARGET_AUTO;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline const char *semihosting_get_arg(int i)
 | 
			
		||||
{
 | 
			
		||||
    return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline int semihosting_get_argc(void)
 | 
			
		||||
{
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline const char *semihosting_get_cmdline(void)
 | 
			
		||||
{
 | 
			
		||||
    return NULL;
 | 
			
		||||
}
 | 
			
		||||
#else
 | 
			
		||||
bool semihosting_enabled(void);
 | 
			
		||||
SemihostingTarget semihosting_get_target(void);
 | 
			
		||||
const char *semihosting_get_arg(int i);
 | 
			
		||||
int semihosting_get_argc(void);
 | 
			
		||||
const char *semihosting_get_cmdline(void);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										34
									
								
								include/hw/arm/fdt.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								include/hw/arm/fdt.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,34 @@
 | 
			
		||||
/*
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright (c) 2015 Linaro Limited
 | 
			
		||||
 *
 | 
			
		||||
 * This program is free software; you can redistribute it and/or modify it
 | 
			
		||||
 * under the terms and conditions of the GNU General Public License,
 | 
			
		||||
 * version 2 or later, as published by the Free Software Foundation.
 | 
			
		||||
 *
 | 
			
		||||
 * This program is distributed in the hope it will be useful, but WITHOUT
 | 
			
		||||
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 | 
			
		||||
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 | 
			
		||||
 * more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License along with
 | 
			
		||||
 * this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 *
 | 
			
		||||
 * Define macros useful when building ARM device tree nodes
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef QEMU_ARM_FDT_H
 | 
			
		||||
#define QEMU_ARM_FDT_H
 | 
			
		||||
 | 
			
		||||
#define GIC_FDT_IRQ_TYPE_SPI 0
 | 
			
		||||
#define GIC_FDT_IRQ_TYPE_PPI 1
 | 
			
		||||
 | 
			
		||||
#define GIC_FDT_IRQ_FLAGS_EDGE_LO_HI 1
 | 
			
		||||
#define GIC_FDT_IRQ_FLAGS_EDGE_HI_LO 2
 | 
			
		||||
#define GIC_FDT_IRQ_FLAGS_LEVEL_HI 4
 | 
			
		||||
#define GIC_FDT_IRQ_FLAGS_LEVEL_LO 8
 | 
			
		||||
 | 
			
		||||
#define GIC_FDT_IRQ_PPI_CPU_START 8
 | 
			
		||||
#define GIC_FDT_IRQ_PPI_CPU_WIDTH 8
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
@@ -27,7 +27,8 @@
 | 
			
		||||
#define XLNX_ZYNQMP(obj) OBJECT_CHECK(XlnxZynqMPState, (obj), \
 | 
			
		||||
                                       TYPE_XLNX_ZYNQMP)
 | 
			
		||||
 | 
			
		||||
#define XLNX_ZYNQMP_NUM_CPUS 4
 | 
			
		||||
#define XLNX_ZYNQMP_NUM_APU_CPUS 4
 | 
			
		||||
#define XLNX_ZYNQMP_NUM_RPU_CPUS 2
 | 
			
		||||
#define XLNX_ZYNQMP_NUM_GEMS 4
 | 
			
		||||
#define XLNX_ZYNQMP_NUM_UARTS 2
 | 
			
		||||
 | 
			
		||||
@@ -47,11 +48,15 @@ typedef struct XlnxZynqMPState {
 | 
			
		||||
    DeviceState parent_obj;
 | 
			
		||||
 | 
			
		||||
    /*< public >*/
 | 
			
		||||
    ARMCPU cpu[XLNX_ZYNQMP_NUM_CPUS];
 | 
			
		||||
    ARMCPU apu_cpu[XLNX_ZYNQMP_NUM_APU_CPUS];
 | 
			
		||||
    ARMCPU rpu_cpu[XLNX_ZYNQMP_NUM_RPU_CPUS];
 | 
			
		||||
    GICState gic;
 | 
			
		||||
    MemoryRegion gic_mr[XLNX_ZYNQMP_GIC_REGIONS][XLNX_ZYNQMP_GIC_ALIASES];
 | 
			
		||||
    CadenceGEMState gem[XLNX_ZYNQMP_NUM_GEMS];
 | 
			
		||||
    CadenceUARTState uart[XLNX_ZYNQMP_NUM_UARTS];
 | 
			
		||||
 | 
			
		||||
    char *boot_cpu;
 | 
			
		||||
    ARMCPU *boot_cpu_ptr;
 | 
			
		||||
}  XlnxZynqMPState;
 | 
			
		||||
 | 
			
		||||
#define XLNX_ZYNQMP_H
 | 
			
		||||
 
 | 
			
		||||
@@ -65,8 +65,8 @@ struct VMStateDescription;
 | 
			
		||||
 * Operations depending on @props static properties should go into @realize.
 | 
			
		||||
 * After successful realization, setting static properties will fail.
 | 
			
		||||
 *
 | 
			
		||||
 * As an interim step, the #DeviceState:realized property is set by deprecated
 | 
			
		||||
 * functions qdev_init() and qdev_init_nofail().
 | 
			
		||||
 * As an interim step, the #DeviceState:realized property can also be
 | 
			
		||||
 * set with qdev_init_nofail().
 | 
			
		||||
 * In the future, devices will propagate this state change to their children
 | 
			
		||||
 * and along busses they expose.
 | 
			
		||||
 * The point in time will be deferred to machine creation, so that values
 | 
			
		||||
@@ -236,7 +236,7 @@ struct Property {
 | 
			
		||||
struct PropertyInfo {
 | 
			
		||||
    const char *name;
 | 
			
		||||
    const char *description;
 | 
			
		||||
    const char **enum_table;
 | 
			
		||||
    const char * const *enum_table;
 | 
			
		||||
    int (*print)(DeviceState *dev, Property *prop, char *dest, size_t len);
 | 
			
		||||
    ObjectPropertyAccessor *get;
 | 
			
		||||
    ObjectPropertyAccessor *set;
 | 
			
		||||
@@ -262,7 +262,6 @@ typedef struct GlobalProperty {
 | 
			
		||||
 | 
			
		||||
DeviceState *qdev_create(BusState *bus, const char *name);
 | 
			
		||||
DeviceState *qdev_try_create(BusState *bus, const char *name);
 | 
			
		||||
int qdev_init(DeviceState *dev) QEMU_WARN_UNUSED_RESULT;
 | 
			
		||||
void qdev_init_nofail(DeviceState *dev);
 | 
			
		||||
void qdev_set_legacy_instance_id(DeviceState *dev, int alias_id,
 | 
			
		||||
                                 int required_for_version);
 | 
			
		||||
 
 | 
			
		||||
@@ -51,7 +51,6 @@ struct vhost_dev {
 | 
			
		||||
    bool log_enabled;
 | 
			
		||||
    unsigned long long log_size;
 | 
			
		||||
    Error *migration_blocker;
 | 
			
		||||
    bool force;
 | 
			
		||||
    bool memory_changed;
 | 
			
		||||
    hwaddr mem_changed_start_addr;
 | 
			
		||||
    hwaddr mem_changed_end_addr;
 | 
			
		||||
@@ -61,7 +60,7 @@ struct vhost_dev {
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
int vhost_dev_init(struct vhost_dev *hdev, void *opaque,
 | 
			
		||||
                   VhostBackendType backend_type, bool force);
 | 
			
		||||
                   VhostBackendType backend_type);
 | 
			
		||||
void vhost_dev_cleanup(struct vhost_dev *hdev);
 | 
			
		||||
bool vhost_dev_query(struct vhost_dev *hdev, VirtIODevice *vdev);
 | 
			
		||||
int vhost_dev_start(struct vhost_dev *hdev, VirtIODevice *vdev);
 | 
			
		||||
 
 | 
			
		||||
@@ -32,6 +32,19 @@ static inline bool virtio_access_is_big_endian(VirtIODevice *vdev)
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline bool virtio_legacy_is_cross_endian(VirtIODevice *vdev)
 | 
			
		||||
{
 | 
			
		||||
#ifdef TARGET_IS_BIENDIAN
 | 
			
		||||
#ifdef HOST_WORDS_BIGENDIAN
 | 
			
		||||
    return !virtio_is_big_endian(vdev);
 | 
			
		||||
#else
 | 
			
		||||
    return virtio_is_big_endian(vdev);
 | 
			
		||||
#endif
 | 
			
		||||
#else
 | 
			
		||||
    return false;
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline uint16_t virtio_lduw_phys(VirtIODevice *vdev, hwaddr pa)
 | 
			
		||||
{
 | 
			
		||||
    if (virtio_access_is_big_endian(vdev)) {
 | 
			
		||||
 
 | 
			
		||||
@@ -50,17 +50,17 @@ typedef struct virtio_input_event virtio_input_event;
 | 
			
		||||
#define VIRTIO_INPUT_HID_GET_PARENT_CLASS(obj) \
 | 
			
		||||
        OBJECT_GET_PARENT_CLASS(obj, TYPE_VIRTIO_INPUT_HID)
 | 
			
		||||
 | 
			
		||||
#define DEFINE_VIRTIO_INPUT_PROPERTIES(_state, _field)       \
 | 
			
		||||
        DEFINE_PROP_STRING("serial", _state, _field.serial)
 | 
			
		||||
#define TYPE_VIRTIO_INPUT_HOST   "virtio-input-host-device"
 | 
			
		||||
#define VIRTIO_INPUT_HOST(obj) \
 | 
			
		||||
        OBJECT_CHECK(VirtIOInputHost, (obj), TYPE_VIRTIO_INPUT_HOST)
 | 
			
		||||
#define VIRTIO_INPUT_HOST_GET_PARENT_CLASS(obj) \
 | 
			
		||||
        OBJECT_GET_PARENT_CLASS(obj, TYPE_VIRTIO_INPUT_HOST)
 | 
			
		||||
 | 
			
		||||
typedef struct VirtIOInput VirtIOInput;
 | 
			
		||||
typedef struct VirtIOInputClass VirtIOInputClass;
 | 
			
		||||
typedef struct VirtIOInputConfig VirtIOInputConfig;
 | 
			
		||||
typedef struct VirtIOInputHID VirtIOInputHID;
 | 
			
		||||
 | 
			
		||||
struct virtio_input_conf {
 | 
			
		||||
    char *serial;
 | 
			
		||||
};
 | 
			
		||||
typedef struct VirtIOInputHost VirtIOInputHost;
 | 
			
		||||
 | 
			
		||||
struct VirtIOInputConfig {
 | 
			
		||||
    virtio_input_config               config;
 | 
			
		||||
@@ -74,7 +74,7 @@ struct VirtIOInput {
 | 
			
		||||
    uint32_t                          cfg_size;
 | 
			
		||||
    QTAILQ_HEAD(, VirtIOInputConfig)  cfg_list;
 | 
			
		||||
    VirtQueue                         *evt, *sts;
 | 
			
		||||
    virtio_input_conf                 input;
 | 
			
		||||
    char                              *serial;
 | 
			
		||||
 | 
			
		||||
    virtio_input_event                *queue;
 | 
			
		||||
    uint32_t                          qindex, qsize;
 | 
			
		||||
@@ -100,6 +100,12 @@ struct VirtIOInputHID {
 | 
			
		||||
    int                               ledstate;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct VirtIOInputHost {
 | 
			
		||||
    VirtIOInput                       parent_obj;
 | 
			
		||||
    char                              *evdev;
 | 
			
		||||
    int                               fd;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
void virtio_input_send(VirtIOInput *vinput, virtio_input_event *event);
 | 
			
		||||
void virtio_input_init_config(VirtIOInput *vinput,
 | 
			
		||||
                              virtio_input_config *config);
 | 
			
		||||
 
 | 
			
		||||
@@ -55,6 +55,8 @@ typedef bool (HasVnetHdrLen)(NetClientState *, int);
 | 
			
		||||
typedef void (UsingVnetHdr)(NetClientState *, bool);
 | 
			
		||||
typedef void (SetOffload)(NetClientState *, int, int, int, int, int);
 | 
			
		||||
typedef void (SetVnetHdrLen)(NetClientState *, int);
 | 
			
		||||
typedef int (SetVnetLE)(NetClientState *, bool);
 | 
			
		||||
typedef int (SetVnetBE)(NetClientState *, bool);
 | 
			
		||||
 | 
			
		||||
typedef struct NetClientInfo {
 | 
			
		||||
    NetClientOptionsKind type;
 | 
			
		||||
@@ -73,6 +75,8 @@ typedef struct NetClientInfo {
 | 
			
		||||
    UsingVnetHdr *using_vnet_hdr;
 | 
			
		||||
    SetOffload *set_offload;
 | 
			
		||||
    SetVnetHdrLen *set_vnet_hdr_len;
 | 
			
		||||
    SetVnetLE *set_vnet_le;
 | 
			
		||||
    SetVnetBE *set_vnet_be;
 | 
			
		||||
} NetClientInfo;
 | 
			
		||||
 | 
			
		||||
struct NetClientState {
 | 
			
		||||
@@ -139,6 +143,8 @@ void qemu_using_vnet_hdr(NetClientState *nc, bool enable);
 | 
			
		||||
void qemu_set_offload(NetClientState *nc, int csum, int tso4, int tso6,
 | 
			
		||||
                      int ecn, int ufo);
 | 
			
		||||
void qemu_set_vnet_hdr_len(NetClientState *nc, int len);
 | 
			
		||||
int qemu_set_vnet_le(NetClientState *nc, bool is_le);
 | 
			
		||||
int qemu_set_vnet_be(NetClientState *nc, bool is_be);
 | 
			
		||||
void qemu_macaddr_default_if_unset(MACAddr *macaddr);
 | 
			
		||||
int qemu_show_nic_models(const char *arg, const char *const *models);
 | 
			
		||||
void qemu_check_nic_model(NICInfo *nd, const char *model);
 | 
			
		||||
 
 | 
			
		||||
@@ -11,12 +11,10 @@ typedef struct VhostNetOptions {
 | 
			
		||||
    VhostBackendType backend_type;
 | 
			
		||||
    NetClientState *net_backend;
 | 
			
		||||
    void *opaque;
 | 
			
		||||
    bool force;
 | 
			
		||||
} VhostNetOptions;
 | 
			
		||||
 | 
			
		||||
struct vhost_net *vhost_net_init(VhostNetOptions *options);
 | 
			
		||||
 | 
			
		||||
bool vhost_net_query(VHostNetState *net, VirtIODevice *dev);
 | 
			
		||||
int vhost_net_start(VirtIODevice *dev, NetClientState *ncs, int total_queues);
 | 
			
		||||
void vhost_net_stop(VirtIODevice *dev, NetClientState *ncs, int total_queues);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -11,7 +11,7 @@
 | 
			
		||||
#ifndef QAPI_UTIL_H
 | 
			
		||||
#define QAPI_UTIL_H
 | 
			
		||||
 | 
			
		||||
int qapi_enum_parse(const char *lookup[], const char *buf,
 | 
			
		||||
int qapi_enum_parse(const char * const lookup[], const char *buf,
 | 
			
		||||
                    int max, int def, Error **errp);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
@@ -30,7 +30,7 @@ struct Visitor
 | 
			
		||||
    GenericList *(*next_list)(Visitor *v, GenericList **list, Error **errp);
 | 
			
		||||
    void (*end_list)(Visitor *v, Error **errp);
 | 
			
		||||
 | 
			
		||||
    void (*type_enum)(Visitor *v, int *obj, const char *strings[],
 | 
			
		||||
    void (*type_enum)(Visitor *v, int *obj, const char * const strings[],
 | 
			
		||||
                      const char *kind, const char *name, Error **errp);
 | 
			
		||||
    void (*get_next_type)(Visitor *v, int *kind, const int *qobjects,
 | 
			
		||||
                          const char *name, Error **errp);
 | 
			
		||||
@@ -59,9 +59,9 @@ struct Visitor
 | 
			
		||||
    void (*end_union)(Visitor *v, bool data_present, Error **errp);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
void input_type_enum(Visitor *v, int *obj, const char *strings[],
 | 
			
		||||
void input_type_enum(Visitor *v, int *obj, const char * const strings[],
 | 
			
		||||
                     const char *kind, const char *name, Error **errp);
 | 
			
		||||
void output_type_enum(Visitor *v, int *obj, const char *strings[],
 | 
			
		||||
void output_type_enum(Visitor *v, int *obj, const char * const strings[],
 | 
			
		||||
                      const char *kind, const char *name, Error **errp);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
@@ -43,7 +43,7 @@ void visit_optional(Visitor *v, bool *present, const char *name,
 | 
			
		||||
                    Error **errp);
 | 
			
		||||
void visit_get_next_type(Visitor *v, int *obj, const int *qtypes,
 | 
			
		||||
                         const char *name, Error **errp);
 | 
			
		||||
void visit_type_enum(Visitor *v, int *obj, const char *strings[],
 | 
			
		||||
void visit_type_enum(Visitor *v, int *obj, const char * const strings[],
 | 
			
		||||
                     const char *kind, const char *name, Error **errp);
 | 
			
		||||
void visit_type_int(Visitor *v, int64_t *obj, const char *name, Error **errp);
 | 
			
		||||
void visit_type_uint8(Visitor *v, uint8_t *obj, const char *name, Error **errp);
 | 
			
		||||
 
 | 
			
		||||
@@ -24,6 +24,12 @@
 | 
			
		||||
#define QEMU_WARN_UNUSED_RESULT
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if QEMU_GNUC_PREREQ(4, 0)
 | 
			
		||||
#define QEMU_SENTINEL __attribute__((sentinel))
 | 
			
		||||
#else
 | 
			
		||||
#define QEMU_SENTINEL
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if QEMU_GNUC_PREREQ(4, 3)
 | 
			
		||||
#define QEMU_ARTIFICIAL __attribute__((always_inline, artificial))
 | 
			
		||||
#else
 | 
			
		||||
 
 | 
			
		||||
@@ -787,6 +787,15 @@ static inline int64_t get_ticks_per_sec(void)
 | 
			
		||||
    return 1000000000LL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline int64_t get_max_clock_jump(void)
 | 
			
		||||
{
 | 
			
		||||
    /* This should be small enough to prevent excessive interrupts from being
 | 
			
		||||
     * generated by the RTC on clock jumps, but large enough to avoid frequent
 | 
			
		||||
     * unnecessary resets in idle VMs.
 | 
			
		||||
     */
 | 
			
		||||
    return 60 * get_ticks_per_sec();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Low level clock functions
 | 
			
		||||
 */
 | 
			
		||||
 
 | 
			
		||||
@@ -606,6 +606,134 @@ Object *object_new(const char *typename);
 | 
			
		||||
 */
 | 
			
		||||
Object *object_new_with_type(Type type);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * object_new_with_props:
 | 
			
		||||
 * @typename:  The name of the type of the object to instantiate.
 | 
			
		||||
 * @parent: the parent object
 | 
			
		||||
 * @id: The unique ID of the object
 | 
			
		||||
 * @errp: pointer to error object
 | 
			
		||||
 * @...: list of property names and values
 | 
			
		||||
 *
 | 
			
		||||
 * This function will initialize a new object using heap allocated memory.
 | 
			
		||||
 * The returned object has a reference count of 1, and will be freed when
 | 
			
		||||
 * the last reference is dropped.
 | 
			
		||||
 *
 | 
			
		||||
 * The @id parameter will be used when registering the object as a
 | 
			
		||||
 * child of @parent in the composition tree.
 | 
			
		||||
 *
 | 
			
		||||
 * The variadic parameters are a list of pairs of (propname, propvalue)
 | 
			
		||||
 * strings. The propname of %NULL indicates the end of the property
 | 
			
		||||
 * list. If the object implements the user creatable interface, the
 | 
			
		||||
 * object will be marked complete once all the properties have been
 | 
			
		||||
 * processed.
 | 
			
		||||
 *
 | 
			
		||||
 * <example>
 | 
			
		||||
 *   <title>Creating an object with properties</title>
 | 
			
		||||
 *   <programlisting>
 | 
			
		||||
 *   Error *err = NULL;
 | 
			
		||||
 *   Object *obj;
 | 
			
		||||
 *
 | 
			
		||||
 *   obj = object_new_with_props(TYPE_MEMORY_BACKEND_FILE,
 | 
			
		||||
 *                               object_get_objects_root(),
 | 
			
		||||
 *                               "hostmem0",
 | 
			
		||||
 *                               &err,
 | 
			
		||||
 *                               "share", "yes",
 | 
			
		||||
 *                               "mem-path", "/dev/shm/somefile",
 | 
			
		||||
 *                               "prealloc", "yes",
 | 
			
		||||
 *                               "size", "1048576",
 | 
			
		||||
 *                               NULL);
 | 
			
		||||
 *
 | 
			
		||||
 *   if (!obj) {
 | 
			
		||||
 *     g_printerr("Cannot create memory backend: %s\n",
 | 
			
		||||
 *                error_get_pretty(err));
 | 
			
		||||
 *   }
 | 
			
		||||
 *   </programlisting>
 | 
			
		||||
 * </example>
 | 
			
		||||
 *
 | 
			
		||||
 * The returned object will have one stable reference maintained
 | 
			
		||||
 * for as long as it is present in the object hierarchy.
 | 
			
		||||
 *
 | 
			
		||||
 * Returns: The newly allocated, instantiated & initialized object.
 | 
			
		||||
 */
 | 
			
		||||
Object *object_new_with_props(const char *typename,
 | 
			
		||||
                              Object *parent,
 | 
			
		||||
                              const char *id,
 | 
			
		||||
                              Error **errp,
 | 
			
		||||
                              ...) QEMU_SENTINEL;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * object_new_with_propv:
 | 
			
		||||
 * @typename:  The name of the type of the object to instantiate.
 | 
			
		||||
 * @parent: the parent object
 | 
			
		||||
 * @id: The unique ID of the object
 | 
			
		||||
 * @errp: pointer to error object
 | 
			
		||||
 * @vargs: list of property names and values
 | 
			
		||||
 *
 | 
			
		||||
 * See object_new_with_props() for documentation.
 | 
			
		||||
 */
 | 
			
		||||
Object *object_new_with_propv(const char *typename,
 | 
			
		||||
                              Object *parent,
 | 
			
		||||
                              const char *id,
 | 
			
		||||
                              Error **errp,
 | 
			
		||||
                              va_list vargs);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * object_set_props:
 | 
			
		||||
 * @obj: the object instance to set properties on
 | 
			
		||||
 * @errp: pointer to error object
 | 
			
		||||
 * @...: list of property names and values
 | 
			
		||||
 *
 | 
			
		||||
 * This function will set a list of properties on an existing object
 | 
			
		||||
 * instance.
 | 
			
		||||
 *
 | 
			
		||||
 * The variadic parameters are a list of pairs of (propname, propvalue)
 | 
			
		||||
 * strings. The propname of %NULL indicates the end of the property
 | 
			
		||||
 * list.
 | 
			
		||||
 *
 | 
			
		||||
 * <example>
 | 
			
		||||
 *   <title>Update an object's properties</title>
 | 
			
		||||
 *   <programlisting>
 | 
			
		||||
 *   Error *err = NULL;
 | 
			
		||||
 *   Object *obj = ...get / create object...;
 | 
			
		||||
 *
 | 
			
		||||
 *   obj = object_set_props(obj,
 | 
			
		||||
 *                          &err,
 | 
			
		||||
 *                          "share", "yes",
 | 
			
		||||
 *                          "mem-path", "/dev/shm/somefile",
 | 
			
		||||
 *                          "prealloc", "yes",
 | 
			
		||||
 *                          "size", "1048576",
 | 
			
		||||
 *                          NULL);
 | 
			
		||||
 *
 | 
			
		||||
 *   if (!obj) {
 | 
			
		||||
 *     g_printerr("Cannot set properties: %s\n",
 | 
			
		||||
 *                error_get_pretty(err));
 | 
			
		||||
 *   }
 | 
			
		||||
 *   </programlisting>
 | 
			
		||||
 * </example>
 | 
			
		||||
 *
 | 
			
		||||
 * The returned object will have one stable reference maintained
 | 
			
		||||
 * for as long as it is present in the object hierarchy.
 | 
			
		||||
 *
 | 
			
		||||
 * Returns: -1 on error, 0 on success
 | 
			
		||||
 */
 | 
			
		||||
int object_set_props(Object *obj,
 | 
			
		||||
                     Error **errp,
 | 
			
		||||
                     ...) QEMU_SENTINEL;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * object_set_propv:
 | 
			
		||||
 * @obj: the object instance to set properties on
 | 
			
		||||
 * @errp: pointer to error object
 | 
			
		||||
 * @vargs: list of property names and values
 | 
			
		||||
 *
 | 
			
		||||
 * See object_set_props() for documentation.
 | 
			
		||||
 *
 | 
			
		||||
 * Returns: -1 on error, 0 on success
 | 
			
		||||
 */
 | 
			
		||||
int object_set_propv(Object *obj,
 | 
			
		||||
                     Error **errp,
 | 
			
		||||
                     va_list vargs);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * object_initialize_with_type:
 | 
			
		||||
 * @data: A pointer to the memory to be used for the object.
 | 
			
		||||
@@ -945,7 +1073,7 @@ int64_t object_property_get_int(Object *obj, const char *name,
 | 
			
		||||
 * object_property_get_enum:
 | 
			
		||||
 * @obj: the object
 | 
			
		||||
 * @name: the name of the property
 | 
			
		||||
 * @strings: strings corresponding to enums
 | 
			
		||||
 * @typename: the name of the enum data type
 | 
			
		||||
 * @errp: returns an error if this function fails
 | 
			
		||||
 *
 | 
			
		||||
 * Returns: the value of the property, converted to an integer, or
 | 
			
		||||
@@ -953,7 +1081,7 @@ int64_t object_property_get_int(Object *obj, const char *name,
 | 
			
		||||
 * an enum).
 | 
			
		||||
 */
 | 
			
		||||
int object_property_get_enum(Object *obj, const char *name,
 | 
			
		||||
                             const char *strings[], Error **errp);
 | 
			
		||||
                             const char *typename, Error **errp);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * object_property_get_uint16List:
 | 
			
		||||
@@ -1026,6 +1154,18 @@ const char *object_property_get_type(Object *obj, const char *name,
 | 
			
		||||
 */
 | 
			
		||||
Object *object_get_root(void);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * object_get_objects_root:
 | 
			
		||||
 *
 | 
			
		||||
 * Get the container object that holds user created
 | 
			
		||||
 * object instances. This is the object at path
 | 
			
		||||
 * "/objects"
 | 
			
		||||
 *
 | 
			
		||||
 * Returns: the user object container
 | 
			
		||||
 */
 | 
			
		||||
Object *object_get_objects_root(void);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * object_get_canonical_path_component:
 | 
			
		||||
 *
 | 
			
		||||
@@ -1203,6 +1343,25 @@ void object_property_add_bool(Object *obj, const char *name,
 | 
			
		||||
                              void (*set)(Object *, bool, Error **),
 | 
			
		||||
                              Error **errp);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * object_property_add_enum:
 | 
			
		||||
 * @obj: the object to add a property to
 | 
			
		||||
 * @name: the name of the property
 | 
			
		||||
 * @typename: the name of the enum data type
 | 
			
		||||
 * @get: the getter or %NULL if the property is write-only.
 | 
			
		||||
 * @set: the setter or %NULL if the property is read-only
 | 
			
		||||
 * @errp: if an error occurs, a pointer to an area to store the error
 | 
			
		||||
 *
 | 
			
		||||
 * Add an enum property using getters/setters.  This function will add a
 | 
			
		||||
 * property of type '@typename'.
 | 
			
		||||
 */
 | 
			
		||||
void object_property_add_enum(Object *obj, const char *name,
 | 
			
		||||
                              const char *typename,
 | 
			
		||||
                              const char * const *strings,
 | 
			
		||||
                              int (*get)(Object *, Error **),
 | 
			
		||||
                              void (*set)(Object *, int, Error **),
 | 
			
		||||
                              Error **errp);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * object_property_add_tm:
 | 
			
		||||
 * @obj: the object to add a property to
 | 
			
		||||
 
 | 
			
		||||
@@ -126,7 +126,6 @@ extern int cursor_hide;
 | 
			
		||||
extern int graphic_rotate;
 | 
			
		||||
extern int no_quit;
 | 
			
		||||
extern int no_shutdown;
 | 
			
		||||
extern int semihosting_enabled;
 | 
			
		||||
extern int old_param;
 | 
			
		||||
extern int boot_menu;
 | 
			
		||||
extern bool boot_strict;
 | 
			
		||||
 
 | 
			
		||||
@@ -19,8 +19,6 @@
 | 
			
		||||
#include "qmp-commands.h"
 | 
			
		||||
#include "qemu/error-report.h"
 | 
			
		||||
 | 
			
		||||
#define IOTHREADS_PATH "/objects"
 | 
			
		||||
 | 
			
		||||
typedef ObjectClass IOThreadClass;
 | 
			
		||||
 | 
			
		||||
#define IOTHREAD_GET_CLASS(obj) \
 | 
			
		||||
@@ -160,7 +158,7 @@ IOThreadInfoList *qmp_query_iothreads(Error **errp)
 | 
			
		||||
{
 | 
			
		||||
    IOThreadInfoList *head = NULL;
 | 
			
		||||
    IOThreadInfoList **prev = &head;
 | 
			
		||||
    Object *container = container_get(object_get_root(), IOTHREADS_PATH);
 | 
			
		||||
    Object *container = object_get_objects_root();
 | 
			
		||||
 | 
			
		||||
    object_child_foreach(container, query_one_iothread, &prev);
 | 
			
		||||
    return head;
 | 
			
		||||
 
 | 
			
		||||
@@ -103,6 +103,20 @@ struct vhost_memory {
 | 
			
		||||
/* Get accessor: reads index, writes value in num */
 | 
			
		||||
#define VHOST_GET_VRING_BASE _IOWR(VHOST_VIRTIO, 0x12, struct vhost_vring_state)
 | 
			
		||||
 | 
			
		||||
/* Set the vring byte order in num. Valid values are VHOST_VRING_LITTLE_ENDIAN
 | 
			
		||||
 * or VHOST_VRING_BIG_ENDIAN (other values return -EINVAL).
 | 
			
		||||
 * The byte order cannot be changed while the device is active: trying to do so
 | 
			
		||||
 * returns -EBUSY.
 | 
			
		||||
 * This is a legacy only API that is simply ignored when VIRTIO_F_VERSION_1 is
 | 
			
		||||
 * set.
 | 
			
		||||
 * Not all kernel configurations support this ioctl, but all configurations that
 | 
			
		||||
 * support SET also support GET.
 | 
			
		||||
 */
 | 
			
		||||
#define VHOST_VRING_LITTLE_ENDIAN 0
 | 
			
		||||
#define VHOST_VRING_BIG_ENDIAN 1
 | 
			
		||||
#define VHOST_SET_VRING_ENDIAN _IOW(VHOST_VIRTIO, 0x13, struct vhost_vring_state)
 | 
			
		||||
#define VHOST_GET_VRING_ENDIAN _IOW(VHOST_VIRTIO, 0x14, struct vhost_vring_state)
 | 
			
		||||
 | 
			
		||||
/* The following ioctls use eventfd file descriptors to signal and poll
 | 
			
		||||
 * for events. */
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										18
									
								
								net/net.c
									
									
									
									
									
								
							
							
						
						
									
										18
									
								
								net/net.c
									
									
									
									
									
								
							@@ -510,6 +510,24 @@ void qemu_set_vnet_hdr_len(NetClientState *nc, int len)
 | 
			
		||||
    nc->info->set_vnet_hdr_len(nc, len);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int qemu_set_vnet_le(NetClientState *nc, bool is_le)
 | 
			
		||||
{
 | 
			
		||||
    if (!nc || !nc->info->set_vnet_le) {
 | 
			
		||||
        return -ENOSYS;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return nc->info->set_vnet_le(nc, is_le);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int qemu_set_vnet_be(NetClientState *nc, bool is_be)
 | 
			
		||||
{
 | 
			
		||||
    if (!nc || !nc->info->set_vnet_be) {
 | 
			
		||||
        return -ENOSYS;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return nc->info->set_vnet_be(nc, is_be);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int qemu_can_send_packet(NetClientState *sender)
 | 
			
		||||
{
 | 
			
		||||
    int vm_running = runstate_is_running();
 | 
			
		||||
 
 | 
			
		||||
@@ -55,6 +55,16 @@ void tap_fd_set_vnet_hdr_len(int fd, int len)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int tap_fd_set_vnet_le(int fd, int is_le)
 | 
			
		||||
{
 | 
			
		||||
    return -EINVAL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int tap_fd_set_vnet_be(int fd, int is_be)
 | 
			
		||||
{
 | 
			
		||||
    return -EINVAL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void tap_fd_set_offload(int fd, int csum, int tso4,
 | 
			
		||||
                        int tso6, int ecn, int ufo)
 | 
			
		||||
{
 | 
			
		||||
 
 | 
			
		||||
@@ -196,6 +196,16 @@ void tap_fd_set_vnet_hdr_len(int fd, int len)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int tap_fd_set_vnet_le(int fd, int is_le)
 | 
			
		||||
{
 | 
			
		||||
    return -EINVAL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int tap_fd_set_vnet_be(int fd, int is_be)
 | 
			
		||||
{
 | 
			
		||||
    return -EINVAL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void tap_fd_set_offload(int fd, int csum, int tso4,
 | 
			
		||||
                        int tso6, int ecn, int ufo)
 | 
			
		||||
{
 | 
			
		||||
 
 | 
			
		||||
@@ -55,6 +55,16 @@ void tap_fd_set_vnet_hdr_len(int fd, int len)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int tap_fd_set_vnet_le(int fd, int is_le)
 | 
			
		||||
{
 | 
			
		||||
    return -EINVAL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int tap_fd_set_vnet_be(int fd, int is_be)
 | 
			
		||||
{
 | 
			
		||||
    return -EINVAL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void tap_fd_set_offload(int fd, int csum, int tso4,
 | 
			
		||||
                        int tso6, int ecn, int ufo)
 | 
			
		||||
{
 | 
			
		||||
 
 | 
			
		||||
@@ -198,6 +198,40 @@ void tap_fd_set_vnet_hdr_len(int fd, int len)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int tap_fd_set_vnet_le(int fd, int is_le)
 | 
			
		||||
{
 | 
			
		||||
    int arg = is_le ? 1 : 0;
 | 
			
		||||
 | 
			
		||||
    if (!ioctl(fd, TUNSETVNETLE, &arg)) {
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Check if our kernel supports TUNSETVNETLE */
 | 
			
		||||
    if (errno == EINVAL) {
 | 
			
		||||
        return -errno;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    error_report("TUNSETVNETLE ioctl() failed: %s.\n", strerror(errno));
 | 
			
		||||
    abort();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int tap_fd_set_vnet_be(int fd, int is_be)
 | 
			
		||||
{
 | 
			
		||||
    int arg = is_be ? 1 : 0;
 | 
			
		||||
 | 
			
		||||
    if (!ioctl(fd, TUNSETVNETBE, &arg)) {
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Check if our kernel supports TUNSETVNETBE */
 | 
			
		||||
    if (errno == EINVAL) {
 | 
			
		||||
        return -errno;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    error_report("TUNSETVNETBE ioctl() failed: %s.\n", strerror(errno));
 | 
			
		||||
    abort();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void tap_fd_set_offload(int fd, int csum, int tso4,
 | 
			
		||||
                        int tso6, int ecn, int ufo)
 | 
			
		||||
{
 | 
			
		||||
 
 | 
			
		||||
@@ -30,6 +30,8 @@
 | 
			
		||||
#define TUNGETVNETHDRSZ _IOR('T', 215, int)
 | 
			
		||||
#define TUNSETVNETHDRSZ _IOW('T', 216, int)
 | 
			
		||||
#define TUNSETQUEUE  _IOW('T', 217, int)
 | 
			
		||||
#define TUNSETVNETLE _IOW('T', 220, int)
 | 
			
		||||
#define TUNSETVNETBE _IOW('T', 222, int)
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -223,6 +223,16 @@ void tap_fd_set_vnet_hdr_len(int fd, int len)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int tap_fd_set_vnet_le(int fd, int is_le)
 | 
			
		||||
{
 | 
			
		||||
    return -EINVAL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int tap_fd_set_vnet_be(int fd, int is_be)
 | 
			
		||||
{
 | 
			
		||||
    return -EINVAL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void tap_fd_set_offload(int fd, int csum, int tso4,
 | 
			
		||||
                        int tso6, int ecn, int ufo)
 | 
			
		||||
{
 | 
			
		||||
 
 | 
			
		||||
@@ -688,6 +688,16 @@ void tap_fd_set_vnet_hdr_len(int fd, int len)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int tap_fd_set_vnet_le(int fd, int is_le)
 | 
			
		||||
{
 | 
			
		||||
    return -EINVAL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int tap_fd_set_vnet_be(int fd, int is_be)
 | 
			
		||||
{
 | 
			
		||||
    return -EINVAL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void tap_using_vnet_hdr(NetClientState *nc, bool using_vnet_hdr)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										17
									
								
								net/tap.c
									
									
									
									
									
								
							
							
						
						
									
										17
									
								
								net/tap.c
									
									
									
									
									
								
							@@ -266,6 +266,20 @@ static void tap_using_vnet_hdr(NetClientState *nc, bool using_vnet_hdr)
 | 
			
		||||
    s->using_vnet_hdr = using_vnet_hdr;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int tap_set_vnet_le(NetClientState *nc, bool is_le)
 | 
			
		||||
{
 | 
			
		||||
    TAPState *s = DO_UPCAST(TAPState, nc, nc);
 | 
			
		||||
 | 
			
		||||
    return tap_fd_set_vnet_le(s->fd, is_le);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int tap_set_vnet_be(NetClientState *nc, bool is_be)
 | 
			
		||||
{
 | 
			
		||||
    TAPState *s = DO_UPCAST(TAPState, nc, nc);
 | 
			
		||||
 | 
			
		||||
    return tap_fd_set_vnet_be(s->fd, is_be);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void tap_set_offload(NetClientState *nc, int csum, int tso4,
 | 
			
		||||
                     int tso6, int ecn, int ufo)
 | 
			
		||||
{
 | 
			
		||||
@@ -332,6 +346,8 @@ static NetClientInfo net_tap_info = {
 | 
			
		||||
    .using_vnet_hdr = tap_using_vnet_hdr,
 | 
			
		||||
    .set_offload = tap_set_offload,
 | 
			
		||||
    .set_vnet_hdr_len = tap_set_vnet_hdr_len,
 | 
			
		||||
    .set_vnet_le = tap_set_vnet_le,
 | 
			
		||||
    .set_vnet_be = tap_set_vnet_be,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static TAPState *net_tap_fd_init(NetClientState *peer,
 | 
			
		||||
@@ -646,7 +662,6 @@ static void net_init_tap_one(const NetdevTapOptions *tap, NetClientState *peer,
 | 
			
		||||
 | 
			
		||||
        options.backend_type = VHOST_BACKEND_TYPE_KERNEL;
 | 
			
		||||
        options.net_backend = &s->nc;
 | 
			
		||||
        options.force = tap->has_vhostforce && tap->vhostforce;
 | 
			
		||||
 | 
			
		||||
        if (tap->has_vhostfd || tap->has_vhostfds) {
 | 
			
		||||
            vhostfd = monitor_fd_param(cur_mon, vhostfdname, &err);
 | 
			
		||||
 
 | 
			
		||||
@@ -40,6 +40,8 @@ int tap_probe_vnet_hdr_len(int fd, int len);
 | 
			
		||||
int tap_probe_has_ufo(int fd);
 | 
			
		||||
void tap_fd_set_offload(int fd, int csum, int tso4, int tso6, int ecn, int ufo);
 | 
			
		||||
void tap_fd_set_vnet_hdr_len(int fd, int len);
 | 
			
		||||
int tap_fd_set_vnet_le(int fd, int vnet_is_le);
 | 
			
		||||
int tap_fd_set_vnet_be(int fd, int vnet_is_be);
 | 
			
		||||
int tap_fd_enable(int fd);
 | 
			
		||||
int tap_fd_disable(int fd);
 | 
			
		||||
int tap_fd_get_ifname(int fd, char *ifname);
 | 
			
		||||
 
 | 
			
		||||
@@ -50,7 +50,6 @@ static int vhost_user_start(VhostUserState *s)
 | 
			
		||||
    options.backend_type = VHOST_BACKEND_TYPE_USER;
 | 
			
		||||
    options.net_backend = &s->nc;
 | 
			
		||||
    options.opaque = s->chr;
 | 
			
		||||
    options.force = true;
 | 
			
		||||
 | 
			
		||||
    s->vhost_net = vhost_net_init(&options);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										4
									
								
								numa.c
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								numa.c
									
									
									
									
									
								
							@@ -456,7 +456,7 @@ static int query_memdev(Object *obj, void *opaque)
 | 
			
		||||
 | 
			
		||||
        m->value->policy = object_property_get_enum(obj,
 | 
			
		||||
                                                    "policy",
 | 
			
		||||
                                                    HostMemPolicy_lookup,
 | 
			
		||||
                                                    "HostMemPolicy",
 | 
			
		||||
                                                    &err);
 | 
			
		||||
        if (err) {
 | 
			
		||||
            goto error;
 | 
			
		||||
@@ -485,7 +485,7 @@ MemdevList *qmp_query_memdev(Error **errp)
 | 
			
		||||
    Object *obj;
 | 
			
		||||
    MemdevList *list = NULL;
 | 
			
		||||
 | 
			
		||||
    obj = object_resolve_path("/objects", NULL);
 | 
			
		||||
    obj = object_get_objects_root();
 | 
			
		||||
    if (obj == NULL) {
 | 
			
		||||
        return NULL;
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							@@ -156,7 +156,8 @@ static void qapi_dealloc_type_size(Visitor *v, uint64_t *obj, const char *name,
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void qapi_dealloc_type_enum(Visitor *v, int *obj, const char *strings[],
 | 
			
		||||
static void qapi_dealloc_type_enum(Visitor *v, int *obj,
 | 
			
		||||
                                   const char * const strings[],
 | 
			
		||||
                                   const char *kind, const char *name,
 | 
			
		||||
                                   Error **errp)
 | 
			
		||||
{
 | 
			
		||||
 
 | 
			
		||||
@@ -14,7 +14,7 @@
 | 
			
		||||
#include "qapi/error.h"
 | 
			
		||||
#include "qapi/util.h"
 | 
			
		||||
 | 
			
		||||
int qapi_enum_parse(const char *lookup[], const char *buf,
 | 
			
		||||
int qapi_enum_parse(const char * const lookup[], const char *buf,
 | 
			
		||||
                    int max, int def, Error **errp)
 | 
			
		||||
{
 | 
			
		||||
    int i;
 | 
			
		||||
 
 | 
			
		||||
@@ -89,7 +89,7 @@ void visit_get_next_type(Visitor *v, int *obj, const int *qtypes,
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void visit_type_enum(Visitor *v, int *obj, const char *strings[],
 | 
			
		||||
void visit_type_enum(Visitor *v, int *obj, const char * const strings[],
 | 
			
		||||
                     const char *kind, const char *name, Error **errp)
 | 
			
		||||
{
 | 
			
		||||
    v->type_enum(v, obj, strings, kind, name, errp);
 | 
			
		||||
@@ -260,7 +260,7 @@ void visit_type_number(Visitor *v, double *obj, const char *name, Error **errp)
 | 
			
		||||
    v->type_number(v, obj, name, errp);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void output_type_enum(Visitor *v, int *obj, const char *strings[],
 | 
			
		||||
void output_type_enum(Visitor *v, int *obj, const char * const strings[],
 | 
			
		||||
                      const char *kind, const char *name,
 | 
			
		||||
                      Error **errp)
 | 
			
		||||
{
 | 
			
		||||
@@ -279,7 +279,7 @@ void output_type_enum(Visitor *v, int *obj, const char *strings[],
 | 
			
		||||
    visit_type_str(v, &enum_str, name, errp);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void input_type_enum(Visitor *v, int *obj, const char *strings[],
 | 
			
		||||
void input_type_enum(Visitor *v, int *obj, const char * const strings[],
 | 
			
		||||
                     const char *kind, const char *name,
 | 
			
		||||
                     Error **errp)
 | 
			
		||||
{
 | 
			
		||||
 
 | 
			
		||||
@@ -42,9 +42,9 @@ static const QDevAlias qdev_alias_table[] = {
 | 
			
		||||
    { "virtio-serial-pci", "virtio-serial", QEMU_ARCH_ALL & ~QEMU_ARCH_S390X },
 | 
			
		||||
    { "virtio-balloon-pci", "virtio-balloon",
 | 
			
		||||
            QEMU_ARCH_ALL & ~QEMU_ARCH_S390X },
 | 
			
		||||
    { "virtio-blk-s390", "virtio-blk", QEMU_ARCH_S390X },
 | 
			
		||||
    { "virtio-net-s390", "virtio-net", QEMU_ARCH_S390X },
 | 
			
		||||
    { "virtio-serial-s390", "virtio-serial", QEMU_ARCH_S390X },
 | 
			
		||||
    { "virtio-blk-ccw", "virtio-blk", QEMU_ARCH_S390X },
 | 
			
		||||
    { "virtio-net-ccw", "virtio-net", QEMU_ARCH_S390X },
 | 
			
		||||
    { "virtio-serial-ccw", "virtio-serial", QEMU_ARCH_S390X },
 | 
			
		||||
    { "lsi53c895a", "lsi" },
 | 
			
		||||
    { "ich9-ahci", "ahci" },
 | 
			
		||||
    { "kvm-pci-assign", "pci-assign" },
 | 
			
		||||
 
 | 
			
		||||
@@ -3351,14 +3351,25 @@ STEXI
 | 
			
		||||
Enable semihosting mode (ARM, M68K, Xtensa only).
 | 
			
		||||
ETEXI
 | 
			
		||||
DEF("semihosting-config", HAS_ARG, QEMU_OPTION_semihosting_config,
 | 
			
		||||
    "-semihosting-config [enable=on|off,]target=native|gdb|auto   semihosting configuration\n",
 | 
			
		||||
    "-semihosting-config [enable=on|off][,target=native|gdb|auto][,arg=str[,...]]\n" \
 | 
			
		||||
    "                semihosting configuration\n",
 | 
			
		||||
QEMU_ARCH_ARM | QEMU_ARCH_M68K | QEMU_ARCH_XTENSA | QEMU_ARCH_LM32)
 | 
			
		||||
STEXI
 | 
			
		||||
@item -semihosting-config [enable=on|off,]target=native|gdb|auto
 | 
			
		||||
@item -semihosting-config [enable=on|off][,target=native|gdb|auto][,arg=str[,...]]
 | 
			
		||||
@findex -semihosting-config
 | 
			
		||||
Enable semihosting and define where the semihosting calls will be addressed,
 | 
			
		||||
to QEMU (@code{native}) or to GDB (@code{gdb}). The default is @code{auto}, which means
 | 
			
		||||
@code{gdb} during debug sessions and @code{native} otherwise (ARM, M68K, Xtensa only).
 | 
			
		||||
Enable and configure semihosting (ARM, M68K, Xtensa only).
 | 
			
		||||
@table @option
 | 
			
		||||
@item target=@code{native|gdb|auto}
 | 
			
		||||
Defines where the semihosting calls will be addressed, to QEMU (@code{native})
 | 
			
		||||
or to GDB (@code{gdb}). The default is @code{auto}, which means @code{gdb}
 | 
			
		||||
during debug sessions and @code{native} otherwise.
 | 
			
		||||
@item arg=@var{str1},arg=@var{str2},...
 | 
			
		||||
Allows the user to pass input arguments, and can be used multiple times to build
 | 
			
		||||
up a list. The old-style @code{-kernel}/@code{-append} method of passing a
 | 
			
		||||
command line is still supported for backward compatibility. If both the
 | 
			
		||||
@code{--semihosting-config arg} and the @code{-kernel}/@code{-append} are
 | 
			
		||||
specified, the former is passed to semihosting as it always takes precedence.
 | 
			
		||||
@end table
 | 
			
		||||
ETEXI
 | 
			
		||||
DEF("old-param", 0, QEMU_OPTION_old_param,
 | 
			
		||||
    "-old-param      old param mode\n", QEMU_ARCH_ARM)
 | 
			
		||||
@@ -3476,22 +3487,6 @@ 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("object", HAS_ARG, QEMU_OPTION_object,
 | 
			
		||||
    "-object TYPENAME[,PROP1=VALUE1,...]\n"
 | 
			
		||||
    "                create an new object of type TYPENAME setting properties\n"
 | 
			
		||||
    "                in the order they are specified.  Note that the 'id'\n"
 | 
			
		||||
    "                property must be set.  These objects are placed in the\n"
 | 
			
		||||
    "                '/objects' path.\n",
 | 
			
		||||
    QEMU_ARCH_ALL)
 | 
			
		||||
STEXI
 | 
			
		||||
@item -object @var{typename}[,@var{prop1}=@var{value1},...]
 | 
			
		||||
@findex -object
 | 
			
		||||
Create an new object of type @var{typename} setting properties
 | 
			
		||||
in the order they are specified.  Note that the 'id'
 | 
			
		||||
property must be set.  These objects are placed in the
 | 
			
		||||
'/objects' path.
 | 
			
		||||
ETEXI
 | 
			
		||||
 | 
			
		||||
DEF("msg", HAS_ARG, QEMU_OPTION_msg,
 | 
			
		||||
    "-msg timestamp[=on|off]\n"
 | 
			
		||||
    "                change the format of messages\n"
 | 
			
		||||
@@ -3517,6 +3512,60 @@ Dump json-encoded vmstate information for current machine type to file
 | 
			
		||||
in @var{file}
 | 
			
		||||
ETEXI
 | 
			
		||||
 | 
			
		||||
DEFHEADING(Generic object creation)
 | 
			
		||||
 | 
			
		||||
DEF("object", HAS_ARG, QEMU_OPTION_object,
 | 
			
		||||
    "-object TYPENAME[,PROP1=VALUE1,...]\n"
 | 
			
		||||
    "                create a new object of type TYPENAME setting properties\n"
 | 
			
		||||
    "                in the order they are specified.  Note that the 'id'\n"
 | 
			
		||||
    "                property must be set.  These objects are placed in the\n"
 | 
			
		||||
    "                '/objects' path.\n",
 | 
			
		||||
    QEMU_ARCH_ALL)
 | 
			
		||||
STEXI
 | 
			
		||||
@item -object @var{typename}[,@var{prop1}=@var{value1},...]
 | 
			
		||||
@findex -object
 | 
			
		||||
Create a new object of type @var{typename} setting properties
 | 
			
		||||
in the order they are specified.  Note that the 'id'
 | 
			
		||||
property must be set.  These objects are placed in the
 | 
			
		||||
'/objects' path.
 | 
			
		||||
 | 
			
		||||
@table @option
 | 
			
		||||
 | 
			
		||||
@item -object memory-backend-file,id=@var{id},size=@var{size},mem-path=@var{dir},share=@var{on|off}
 | 
			
		||||
 | 
			
		||||
Creates a memory file backend object, which can be used to back
 | 
			
		||||
the guest RAM with huge pages. The @option{id} parameter is a
 | 
			
		||||
unique ID that will be used to reference this memory region
 | 
			
		||||
when configuring the @option{-numa} argument. The @option{size}
 | 
			
		||||
option provides the size of the memory region, and accepts
 | 
			
		||||
common suffixes, eg @option{500M}. The @option{mem-path} provides
 | 
			
		||||
the path to either a shared memory or huge page filesystem mount.
 | 
			
		||||
The @option{share} boolean option determines whether the memory
 | 
			
		||||
region is marked as private to QEMU, or shared. The latter allows
 | 
			
		||||
a co-operating external process to access the QEMU memory region.
 | 
			
		||||
 | 
			
		||||
@item -object rng-random,id=@var{id},filename=@var{/dev/random}
 | 
			
		||||
 | 
			
		||||
Creates a random number generator backend which obtains entropy from
 | 
			
		||||
a device on the host. The @option{id} parameter is a unique ID that
 | 
			
		||||
will be used to reference this entropy backend from the @option{virtio-rng}
 | 
			
		||||
device. The @option{filename} parameter specifies which file to obtain
 | 
			
		||||
entropy from and if omitted defaults to @option{/dev/random}.
 | 
			
		||||
 | 
			
		||||
@item -object rng-egd,id=@var{id},chardev=@var{chardevid}
 | 
			
		||||
 | 
			
		||||
Creates a random number generator backend which obtains entropy from
 | 
			
		||||
an external daemon running on the host. The @option{id} parameter is
 | 
			
		||||
a unique ID that will be used to reference this entropy backend from
 | 
			
		||||
the @option{virtio-rng} device. The @option{chardev} parameter is
 | 
			
		||||
the unique ID of a character device backend that provides the connection
 | 
			
		||||
to the RNG daemon.
 | 
			
		||||
 | 
			
		||||
@end table
 | 
			
		||||
 | 
			
		||||
ETEXI
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
HXCOMM This is the last statement. Insert new options before this line!
 | 
			
		||||
STEXI
 | 
			
		||||
@end table
 | 
			
		||||
 
 | 
			
		||||
@@ -573,7 +573,7 @@ int64_t qemu_clock_get_ns(QEMUClockType type)
 | 
			
		||||
        now = get_clock_realtime();
 | 
			
		||||
        last = clock->last;
 | 
			
		||||
        clock->last = now;
 | 
			
		||||
        if (now < last) {
 | 
			
		||||
        if (now < last || now > (last + get_max_clock_jump())) {
 | 
			
		||||
            notifier_list_notify(&clock->reset_notifiers, &now);
 | 
			
		||||
        }
 | 
			
		||||
        return now;
 | 
			
		||||
 
 | 
			
		||||
@@ -306,7 +306,7 @@ static gboolean ga_channel_open(GAChannel *c, GAChannelMethod method,
 | 
			
		||||
                           OPEN_EXISTING,
 | 
			
		||||
                           FILE_FLAG_NO_BUFFERING | FILE_FLAG_OVERLAPPED, NULL);
 | 
			
		||||
    if (c->handle == INVALID_HANDLE_VALUE) {
 | 
			
		||||
        g_critical("error opening path");
 | 
			
		||||
        g_critical("error opening path %s", newpath);
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -721,6 +721,7 @@ GList *ga_command_blacklist_init(GList *blacklist)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (!vss_init(true)) {
 | 
			
		||||
        g_debug("vss_init failed, vss commands are going to be disabled");
 | 
			
		||||
        const char *list[] = {
 | 
			
		||||
            "guest-get-fsinfo", "guest-fsfreeze-status",
 | 
			
		||||
            "guest-fsfreeze-freeze", "guest-fsfreeze-thaw", NULL};
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										145
									
								
								qga/installer/qemu-ga.wxs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										145
									
								
								qga/installer/qemu-ga.wxs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,145 @@
 | 
			
		||||
<?xml version="1.0" encoding="UTF-8"?>
 | 
			
		||||
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
 | 
			
		||||
  <?ifndef env.QEMU_GA_VERSION ?>
 | 
			
		||||
    <?error Environment variable QEMU_GA_VERSION undefined?>
 | 
			
		||||
  <?endif?>
 | 
			
		||||
 | 
			
		||||
  <?ifndef env.QEMU_GA_DISTRO ?>
 | 
			
		||||
    <?error Environment variable QEMU_GA_DISTRO undefined?>
 | 
			
		||||
  <?endif?>
 | 
			
		||||
 | 
			
		||||
  <?ifndef env.QEMU_GA_MANUFACTURER ?>
 | 
			
		||||
    <?error Environment variable QEMU_GA_MANUFACTURER undefined?>
 | 
			
		||||
  <?endif?>
 | 
			
		||||
 | 
			
		||||
  <?ifndef var.Arch?>
 | 
			
		||||
    <?error Define Arch to 32 or 64?>
 | 
			
		||||
  <?endif?>
 | 
			
		||||
 | 
			
		||||
  <?ifndef var.Mingw_bin?>
 | 
			
		||||
    <?if $(var.Arch) = "64"?>
 | 
			
		||||
      <?define Mingw_bin=/usr/x86_64-w64-mingw32/sys-root/mingw/bin ?>
 | 
			
		||||
    <?endif?>
 | 
			
		||||
    <?if $(var.Arch) = "32"?>
 | 
			
		||||
      <?define Mingw_bin=/usr/i686-w64-mingw32/sys-root/mingw/bin ?>
 | 
			
		||||
    <?endif?>
 | 
			
		||||
  <?endif?>
 | 
			
		||||
 | 
			
		||||
  <?if $(var.Arch) = "64"?>
 | 
			
		||||
    <?define ArchLib=libgcc_s_seh-1.dll?>
 | 
			
		||||
    <?define GaProgramFilesFolder="ProgramFiles64Folder" ?>
 | 
			
		||||
  <?endif?>
 | 
			
		||||
 | 
			
		||||
  <?if $(var.Arch) = "32"?>
 | 
			
		||||
    <?define ArchLib=libgcc_s_sjlj-1.dll?>
 | 
			
		||||
    <?define GaProgramFilesFolder="ProgramFilesFolder" ?>
 | 
			
		||||
  <?endif?>
 | 
			
		||||
 | 
			
		||||
  <?ifndef var.ArchLib ?>
 | 
			
		||||
    <?error Unexpected Arch value $(var.Arch)?>
 | 
			
		||||
  <?endif?>
 | 
			
		||||
 | 
			
		||||
  <Product
 | 
			
		||||
    Name="QEMU guest agent"
 | 
			
		||||
    Id="*"
 | 
			
		||||
    UpgradeCode="{EB6B8302-C06E-4bec-ADAC-932C68A3A98D}"
 | 
			
		||||
    Manufacturer="$(env.QEMU_GA_MANUFACTURER)"
 | 
			
		||||
    Version="$(env.QEMU_GA_VERSION)"
 | 
			
		||||
    Language="1033">
 | 
			
		||||
    <?if $(var.Arch) = 32 ?>
 | 
			
		||||
    <Condition Message="Error: 32-bit version of Qemu GA can not be installed on 64-bit Windows.">NOT VersionNT64</Condition>
 | 
			
		||||
    <?endif?>
 | 
			
		||||
    <Package
 | 
			
		||||
      Manufacturer="$(env.QEMU_GA_MANUFACTURER)"
 | 
			
		||||
      InstallerVersion="200"
 | 
			
		||||
      Languages="1033"
 | 
			
		||||
      Compressed="yes"
 | 
			
		||||
      InstallScope="perMachine"
 | 
			
		||||
      />
 | 
			
		||||
    <Media Id="1" Cabinet="qemu_ga.$(env.QEMU_GA_VERSION).cab" EmbedCab="yes" />
 | 
			
		||||
    <Property Id="WHSLogo">1</Property>
 | 
			
		||||
    <Property Id="PREVIOUSVERSIONSINSTALLED" />
 | 
			
		||||
    <Upgrade Id="{EB6B8302-C06E-4bec-ADAC-932C68A3A98D}">
 | 
			
		||||
      <UpgradeVersion
 | 
			
		||||
        Minimum="1.0.0.0" Maximum="$(env.QEMU_GA_VERSION)"
 | 
			
		||||
        Property="PREVIOUSVERSIONSINSTALLED"
 | 
			
		||||
        IncludeMinimum="yes" IncludeMaximum="no" />
 | 
			
		||||
    </Upgrade>
 | 
			
		||||
 | 
			
		||||
    <Directory Id="TARGETDIR" Name="SourceDir">
 | 
			
		||||
      <Directory Id="$(var.GaProgramFilesFolder)" Name="QEMU Guest Agent">
 | 
			
		||||
        <Directory Id="qemu_ga_directory" Name="Qemu-ga">
 | 
			
		||||
          <Component Id="qemu_ga" Guid="{908B7199-DE2A-4dc6-A8D0-27A5AE444FEA}">
 | 
			
		||||
            <File Id="qemu_ga.exe" Name="qemu-ga.exe" Source="../../qemu-ga.exe" KeyPath="yes" DiskId="1"/>
 | 
			
		||||
            <?ifdef var.InstallVss ?>
 | 
			
		||||
            <File Id="qga_vss.dll" Name="qga-vss.dll" Source="../vss-win32/qga-vss.dll" KeyPath="no" DiskId="1"/>
 | 
			
		||||
            <File Id="qga_vss.tlb" Name="qga-vss.tlb" Source="../vss-win32/qga-vss.tlb" KeyPath="no" DiskId="1"/>
 | 
			
		||||
            <?endif?>
 | 
			
		||||
            <File Id="iconv.dll" Name="iconv.dll" Source="$(var.Mingw_bin)/iconv.dll" KeyPath="no" DiskId="1"/>
 | 
			
		||||
            <File Id="libgcc_arch_lib" Name="$(var.ArchLib)" Source="$(var.Mingw_bin)/$(var.ArchLib)" KeyPath="no" DiskId="1"/>
 | 
			
		||||
            <File Id="libglib_2.0_0.dll" Name="libglib-2.0-0.dll" Source="$(var.Mingw_bin)/libglib-2.0-0.dll" KeyPath="no" DiskId="1"/>
 | 
			
		||||
            <File Id="libintl_8.dll" Name="libintl-8.dll" Source="$(var.Mingw_bin)/libintl-8.dll" KeyPath="no" DiskId="1"/>
 | 
			
		||||
            <File Id="libssp_0.dll" Name="libssp-0.dll" Source="$(var.Mingw_bin)/libssp-0.dll" KeyPath="no" DiskId="1"/>
 | 
			
		||||
            <File Id="libwinpthread_1.dll" Name="libwinpthread-1.dll" Source="$(var.Mingw_bin)/libwinpthread-1.dll" KeyPath="no" DiskId="1"/>
 | 
			
		||||
            <ServiceInstall
 | 
			
		||||
              Id="ServiceInstaller"
 | 
			
		||||
              Type="ownProcess"
 | 
			
		||||
              Vital="yes"
 | 
			
		||||
              Name="QEMU-GA"
 | 
			
		||||
              DisplayName="QEMU Guest Agent"
 | 
			
		||||
              Description="QEMU Guest Agent"
 | 
			
		||||
              Start="auto"
 | 
			
		||||
              Account="LocalSystem"
 | 
			
		||||
              ErrorControl="ignore"
 | 
			
		||||
              Interactive="no"
 | 
			
		||||
              Arguments="-d"
 | 
			
		||||
              >
 | 
			
		||||
            </ServiceInstall>
 | 
			
		||||
            <ServiceControl Id="StartService" Start="install" Stop="both" Remove="uninstall" Name="QEMU-GA" Wait="no" />
 | 
			
		||||
          </Component>
 | 
			
		||||
 | 
			
		||||
          <Component Id="registry_entries" Guid="d075d109-51ca-11e3-9f8b-000c29858960">
 | 
			
		||||
            <RegistryKey Root="HKLM"
 | 
			
		||||
                         Key="Software\$(env.QEMU_GA_MANUFACTURER)\$(env.QEMU_GA_DISTRO)\Tools\QemuGA">
 | 
			
		||||
              <RegistryValue Type="string" Name="ProductID" Value="fb0a0d66-c7fb-4e2e-a16b-c4a3bfe8d13b" />
 | 
			
		||||
              <RegistryValue Type="string" Name="Version" Value="$(env.QEMU_GA_VERSION)" />
 | 
			
		||||
            </RegistryKey>
 | 
			
		||||
          </Component>
 | 
			
		||||
        </Directory>
 | 
			
		||||
      </Directory>
 | 
			
		||||
    </Directory>
 | 
			
		||||
 | 
			
		||||
    <Property Id="cmd" Value="cmd.exe"/>
 | 
			
		||||
 | 
			
		||||
    <?ifdef var.InstallVss ?>
 | 
			
		||||
    <CustomAction Id="RegisterCom"
 | 
			
		||||
             ExeCommand='/c "[qemu_ga_directory]qemu-ga.exe" -s vss-install'
 | 
			
		||||
              Execute="deferred"
 | 
			
		||||
              Property="cmd"
 | 
			
		||||
              Impersonate="no"
 | 
			
		||||
              Return="check"
 | 
			
		||||
              >
 | 
			
		||||
    </CustomAction>
 | 
			
		||||
    <CustomAction Id="UnRegisterCom"
 | 
			
		||||
              ExeCommand='/c "[qemu_ga_directory]qemu-ga.exe" -s vss-uninstall'
 | 
			
		||||
              Execute="deferred"
 | 
			
		||||
              Property="cmd"
 | 
			
		||||
              Impersonate="no"
 | 
			
		||||
              Return="check"
 | 
			
		||||
              ></CustomAction>
 | 
			
		||||
    <?endif?>
 | 
			
		||||
 | 
			
		||||
    <Feature Id="QEMUFeature" Title="QEMU Guest Agent" Level="1">
 | 
			
		||||
      <ComponentRef Id="qemu_ga" />
 | 
			
		||||
      <ComponentRef Id="registry_entries" />
 | 
			
		||||
    </Feature>
 | 
			
		||||
 | 
			
		||||
    <InstallExecuteSequence>
 | 
			
		||||
      <RemoveExistingProducts Before="InstallInitialize" />
 | 
			
		||||
      <?ifdef var.InstallVss ?>
 | 
			
		||||
      <Custom Action="RegisterCom" After="InstallServices">NOT Installed</Custom>
 | 
			
		||||
      <Custom Action="UnRegisterCom" After="StopServices">Installed</Custom>
 | 
			
		||||
      <?endif?>
 | 
			
		||||
    </InstallExecuteSequence>
 | 
			
		||||
  </Product>
 | 
			
		||||
</Wix>
 | 
			
		||||
							
								
								
									
										10
									
								
								qga/main.c
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								qga/main.c
									
									
									
									
									
								
							@@ -211,7 +211,7 @@ static void usage(const char *cmd)
 | 
			
		||||
"  -V, --version     print version information and exit\n"
 | 
			
		||||
"  -d, --daemonize   become a daemon\n"
 | 
			
		||||
#ifdef _WIN32
 | 
			
		||||
"  -s, --service     service commands: install, uninstall\n"
 | 
			
		||||
"  -s, --service     service commands: install, uninstall, vss-install, vss-uninstall\n"
 | 
			
		||||
#endif
 | 
			
		||||
"  -b, --blacklist   comma-separated list of RPCs to disable (no spaces, \"?\"\n"
 | 
			
		||||
"                    to list available RPCs)\n"
 | 
			
		||||
@@ -1036,6 +1036,14 @@ int main(int argc, char **argv)
 | 
			
		||||
            } else if (strcmp(service, "uninstall") == 0) {
 | 
			
		||||
                ga_uninstall_vss_provider();
 | 
			
		||||
                return ga_uninstall_service();
 | 
			
		||||
            } else if (strcmp(service, "vss-install") == 0) {
 | 
			
		||||
                if (ga_install_vss_provider()) {
 | 
			
		||||
                    return EXIT_FAILURE;
 | 
			
		||||
                }
 | 
			
		||||
                return EXIT_SUCCESS;
 | 
			
		||||
            } else if (strcmp(service, "vss-uninstall") == 0) {
 | 
			
		||||
                ga_uninstall_vss_provider();
 | 
			
		||||
                return EXIT_SUCCESS;
 | 
			
		||||
            } else {
 | 
			
		||||
                printf("Unknown service command.\n");
 | 
			
		||||
                return EXIT_FAILURE;
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										6
									
								
								qmp.c
									
									
									
									
									
								
							
							
						
						
									
										6
									
								
								qmp.c
									
									
									
									
									
								
							@@ -651,7 +651,7 @@ void object_add(const char *type, const char *id, const QDict *qdict,
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    object_property_add_child(container_get(object_get_root(), "/objects"),
 | 
			
		||||
    object_property_add_child(object_get_objects_root(),
 | 
			
		||||
                              id, obj, &local_err);
 | 
			
		||||
    if (local_err) {
 | 
			
		||||
        goto out;
 | 
			
		||||
@@ -659,7 +659,7 @@ void object_add(const char *type, const char *id, const QDict *qdict,
 | 
			
		||||
 | 
			
		||||
    user_creatable_complete(obj, &local_err);
 | 
			
		||||
    if (local_err) {
 | 
			
		||||
        object_property_del(container_get(object_get_root(), "/objects"),
 | 
			
		||||
        object_property_del(object_get_objects_root(),
 | 
			
		||||
                            id, &error_abort);
 | 
			
		||||
        goto out;
 | 
			
		||||
    }
 | 
			
		||||
@@ -706,7 +706,7 @@ void qmp_object_del(const char *id, Error **errp)
 | 
			
		||||
    Object *container;
 | 
			
		||||
    Object *obj;
 | 
			
		||||
 | 
			
		||||
    container = container_get(object_get_root(), "/objects");
 | 
			
		||||
    container = object_get_objects_root();
 | 
			
		||||
    obj = object_resolve_path_component(container, id);
 | 
			
		||||
    if (!obj) {
 | 
			
		||||
        error_setg(errp, "object id not found");
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										196
									
								
								qom/object.c
									
									
									
									
									
								
							
							
						
						
									
										196
									
								
								qom/object.c
									
									
									
									
									
								
							@@ -11,6 +11,7 @@
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "qom/object.h"
 | 
			
		||||
#include "qom/object_interfaces.h"
 | 
			
		||||
#include "qemu-common.h"
 | 
			
		||||
#include "qapi/visitor.h"
 | 
			
		||||
#include "qapi-visit.h"
 | 
			
		||||
@@ -439,6 +440,114 @@ Object *object_new(const char *typename)
 | 
			
		||||
    return object_new_with_type(ti);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Object *object_new_with_props(const char *typename,
 | 
			
		||||
                              Object *parent,
 | 
			
		||||
                              const char *id,
 | 
			
		||||
                              Error **errp,
 | 
			
		||||
                              ...)
 | 
			
		||||
{
 | 
			
		||||
    va_list vargs;
 | 
			
		||||
    Object *obj;
 | 
			
		||||
 | 
			
		||||
    va_start(vargs, errp);
 | 
			
		||||
    obj = object_new_with_propv(typename, parent, id, errp, vargs);
 | 
			
		||||
    va_end(vargs);
 | 
			
		||||
 | 
			
		||||
    return obj;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Object *object_new_with_propv(const char *typename,
 | 
			
		||||
                              Object *parent,
 | 
			
		||||
                              const char *id,
 | 
			
		||||
                              Error **errp,
 | 
			
		||||
                              va_list vargs)
 | 
			
		||||
{
 | 
			
		||||
    Object *obj;
 | 
			
		||||
    ObjectClass *klass;
 | 
			
		||||
    Error *local_err = NULL;
 | 
			
		||||
 | 
			
		||||
    klass = object_class_by_name(typename);
 | 
			
		||||
    if (!klass) {
 | 
			
		||||
        error_setg(errp, "invalid object type: %s", typename);
 | 
			
		||||
        return NULL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (object_class_is_abstract(klass)) {
 | 
			
		||||
        error_setg(errp, "object type '%s' is abstract", typename);
 | 
			
		||||
        return NULL;
 | 
			
		||||
    }
 | 
			
		||||
    obj = object_new(typename);
 | 
			
		||||
 | 
			
		||||
    if (object_set_propv(obj, &local_err, vargs) < 0) {
 | 
			
		||||
        goto error;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    object_property_add_child(parent, id, obj, &local_err);
 | 
			
		||||
    if (local_err) {
 | 
			
		||||
        goto error;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (object_dynamic_cast(obj, TYPE_USER_CREATABLE)) {
 | 
			
		||||
        user_creatable_complete(obj, &local_err);
 | 
			
		||||
        if (local_err) {
 | 
			
		||||
            object_unparent(obj);
 | 
			
		||||
            goto error;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    object_unref(OBJECT(obj));
 | 
			
		||||
    return obj;
 | 
			
		||||
 | 
			
		||||
 error:
 | 
			
		||||
    if (local_err) {
 | 
			
		||||
        error_propagate(errp, local_err);
 | 
			
		||||
    }
 | 
			
		||||
    object_unref(obj);
 | 
			
		||||
    return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
int object_set_props(Object *obj,
 | 
			
		||||
                     Error **errp,
 | 
			
		||||
                     ...)
 | 
			
		||||
{
 | 
			
		||||
    va_list vargs;
 | 
			
		||||
    int ret;
 | 
			
		||||
 | 
			
		||||
    va_start(vargs, errp);
 | 
			
		||||
    ret = object_set_propv(obj, errp, vargs);
 | 
			
		||||
    va_end(vargs);
 | 
			
		||||
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
int object_set_propv(Object *obj,
 | 
			
		||||
                     Error **errp,
 | 
			
		||||
                     va_list vargs)
 | 
			
		||||
{
 | 
			
		||||
    const char *propname;
 | 
			
		||||
    Error *local_err = NULL;
 | 
			
		||||
 | 
			
		||||
    propname = va_arg(vargs, char *);
 | 
			
		||||
    while (propname != NULL) {
 | 
			
		||||
        const char *value = va_arg(vargs, char *);
 | 
			
		||||
 | 
			
		||||
        g_assert(value != NULL);
 | 
			
		||||
        object_property_parse(obj, value, propname, &local_err);
 | 
			
		||||
        if (local_err) {
 | 
			
		||||
            error_propagate(errp, local_err);
 | 
			
		||||
            return -1;
 | 
			
		||||
        }
 | 
			
		||||
        propname = va_arg(vargs, char *);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Object *object_dynamic_cast(Object *obj, const char *typename)
 | 
			
		||||
{
 | 
			
		||||
    if (obj && object_class_dynamic_cast(object_get_class(obj), typename)) {
 | 
			
		||||
@@ -960,13 +1069,34 @@ int64_t object_property_get_int(Object *obj, const char *name,
 | 
			
		||||
    return retval;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
typedef struct EnumProperty {
 | 
			
		||||
    const char * const *strings;
 | 
			
		||||
    int (*get)(Object *, Error **);
 | 
			
		||||
    void (*set)(Object *, int, Error **);
 | 
			
		||||
} EnumProperty;
 | 
			
		||||
 | 
			
		||||
int object_property_get_enum(Object *obj, const char *name,
 | 
			
		||||
                             const char *strings[], Error **errp)
 | 
			
		||||
                             const char *typename, Error **errp)
 | 
			
		||||
{
 | 
			
		||||
    StringOutputVisitor *sov;
 | 
			
		||||
    StringInputVisitor *siv;
 | 
			
		||||
    char *str;
 | 
			
		||||
    int ret;
 | 
			
		||||
    ObjectProperty *prop = object_property_find(obj, name, errp);
 | 
			
		||||
    EnumProperty *enumprop;
 | 
			
		||||
 | 
			
		||||
    if (prop == NULL) {
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (!g_str_equal(prop->type, typename)) {
 | 
			
		||||
        error_setg(errp, "Property %s on %s is not '%s' enum type",
 | 
			
		||||
                   name, object_class_get_name(
 | 
			
		||||
                       object_get_class(obj)), typename);
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    enumprop = prop->opaque;
 | 
			
		||||
 | 
			
		||||
    sov = string_output_visitor_new(false);
 | 
			
		||||
    object_property_get(obj, string_output_get_visitor(sov), name, errp);
 | 
			
		||||
@@ -974,7 +1104,7 @@ int object_property_get_enum(Object *obj, const char *name,
 | 
			
		||||
    siv = string_input_visitor_new(str);
 | 
			
		||||
    string_output_visitor_cleanup(sov);
 | 
			
		||||
    visit_type_enum(string_input_get_visitor(siv),
 | 
			
		||||
                    &ret, strings, NULL, name, errp);
 | 
			
		||||
                    &ret, enumprop->strings, NULL, name, errp);
 | 
			
		||||
 | 
			
		||||
    g_free(str);
 | 
			
		||||
    string_input_visitor_cleanup(siv);
 | 
			
		||||
@@ -1054,6 +1184,11 @@ Object *object_get_root(void)
 | 
			
		||||
    return root;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Object *object_get_objects_root(void)
 | 
			
		||||
{
 | 
			
		||||
    return container_get(object_get_root(), "/objects");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void object_get_child_property(Object *obj, Visitor *v, void *opaque,
 | 
			
		||||
                                      const char *name, Error **errp)
 | 
			
		||||
{
 | 
			
		||||
@@ -1559,6 +1694,58 @@ void object_property_add_bool(Object *obj, const char *name,
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void property_get_enum(Object *obj, Visitor *v, void *opaque,
 | 
			
		||||
                              const char *name, Error **errp)
 | 
			
		||||
{
 | 
			
		||||
    EnumProperty *prop = opaque;
 | 
			
		||||
    int value;
 | 
			
		||||
 | 
			
		||||
    value = prop->get(obj, errp);
 | 
			
		||||
    visit_type_enum(v, &value, prop->strings, NULL, name, errp);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void property_set_enum(Object *obj, Visitor *v, void *opaque,
 | 
			
		||||
                              const char *name, Error **errp)
 | 
			
		||||
{
 | 
			
		||||
    EnumProperty *prop = opaque;
 | 
			
		||||
    int value;
 | 
			
		||||
 | 
			
		||||
    visit_type_enum(v, &value, prop->strings, NULL, name, errp);
 | 
			
		||||
    prop->set(obj, value, errp);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void property_release_enum(Object *obj, const char *name,
 | 
			
		||||
                                  void *opaque)
 | 
			
		||||
{
 | 
			
		||||
    EnumProperty *prop = opaque;
 | 
			
		||||
    g_free(prop);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void object_property_add_enum(Object *obj, const char *name,
 | 
			
		||||
                              const char *typename,
 | 
			
		||||
                              const char * const *strings,
 | 
			
		||||
                              int (*get)(Object *, Error **),
 | 
			
		||||
                              void (*set)(Object *, int, Error **),
 | 
			
		||||
                              Error **errp)
 | 
			
		||||
{
 | 
			
		||||
    Error *local_err = NULL;
 | 
			
		||||
    EnumProperty *prop = g_malloc(sizeof(*prop));
 | 
			
		||||
 | 
			
		||||
    prop->strings = strings;
 | 
			
		||||
    prop->get = get;
 | 
			
		||||
    prop->set = set;
 | 
			
		||||
 | 
			
		||||
    object_property_add(obj, name, typename,
 | 
			
		||||
                        get ? property_get_enum : NULL,
 | 
			
		||||
                        set ? property_set_enum : NULL,
 | 
			
		||||
                        property_release_enum,
 | 
			
		||||
                        prop, &local_err);
 | 
			
		||||
    if (local_err) {
 | 
			
		||||
        error_propagate(errp, local_err);
 | 
			
		||||
        g_free(prop);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
typedef struct TMProperty {
 | 
			
		||||
    void (*get)(Object *, struct tm *, Error **);
 | 
			
		||||
} TMProperty;
 | 
			
		||||
@@ -1705,7 +1892,7 @@ void object_property_add_uint64_ptr(Object *obj, const char *name,
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
    Object *target_obj;
 | 
			
		||||
    const char *target_name;
 | 
			
		||||
    char *target_name;
 | 
			
		||||
} AliasProperty;
 | 
			
		||||
 | 
			
		||||
static void property_get_alias(Object *obj, struct Visitor *v, void *opaque,
 | 
			
		||||
@@ -1736,6 +1923,7 @@ static void property_release_alias(Object *obj, const char *name, void *opaque)
 | 
			
		||||
{
 | 
			
		||||
    AliasProperty *prop = opaque;
 | 
			
		||||
 | 
			
		||||
    g_free(prop->target_name);
 | 
			
		||||
    g_free(prop);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -1763,7 +1951,7 @@ void object_property_add_alias(Object *obj, const char *name,
 | 
			
		||||
 | 
			
		||||
    prop = g_malloc(sizeof(*prop));
 | 
			
		||||
    prop->target_obj = target_obj;
 | 
			
		||||
    prop->target_name = target_name;
 | 
			
		||||
    prop->target_name = g_strdup(target_name);
 | 
			
		||||
 | 
			
		||||
    op = object_property_add(obj, name, prop_type,
 | 
			
		||||
                             property_get_alias,
 | 
			
		||||
 
 | 
			
		||||
 Submodule roms/openbios updated: 5d3db90143...18f02b14de
									
								
							@@ -12,9 +12,8 @@
 | 
			
		||||
from ordereddict import OrderedDict
 | 
			
		||||
from qapi import *
 | 
			
		||||
 | 
			
		||||
def generate_fwd_struct(name, members, builtin_type=False):
 | 
			
		||||
    if builtin_type:
 | 
			
		||||
        return mcgen('''
 | 
			
		||||
def generate_fwd_builtin(name):
 | 
			
		||||
    return mcgen('''
 | 
			
		||||
 | 
			
		||||
typedef struct %(name)sList
 | 
			
		||||
{
 | 
			
		||||
@@ -25,9 +24,10 @@ typedef struct %(name)sList
 | 
			
		||||
    struct %(name)sList *next;
 | 
			
		||||
} %(name)sList;
 | 
			
		||||
''',
 | 
			
		||||
                     type=c_type(name),
 | 
			
		||||
                     name=name)
 | 
			
		||||
                 type=c_type(name),
 | 
			
		||||
                 name=name)
 | 
			
		||||
 | 
			
		||||
def generate_fwd_struct(name):
 | 
			
		||||
    return mcgen('''
 | 
			
		||||
 | 
			
		||||
typedef struct %(name)s %(name)s;
 | 
			
		||||
@@ -43,7 +43,7 @@ typedef struct %(name)sList
 | 
			
		||||
''',
 | 
			
		||||
                 name=c_name(name))
 | 
			
		||||
 | 
			
		||||
def generate_fwd_enum_struct(name, members):
 | 
			
		||||
def generate_fwd_enum_struct(name):
 | 
			
		||||
    return mcgen('''
 | 
			
		||||
typedef struct %(name)sList
 | 
			
		||||
{
 | 
			
		||||
@@ -75,7 +75,6 @@ def generate_struct_fields(members):
 | 
			
		||||
def generate_struct(expr):
 | 
			
		||||
 | 
			
		||||
    structname = expr.get('struct', "")
 | 
			
		||||
    fieldname = expr.get('field', "")
 | 
			
		||||
    members = expr['data']
 | 
			
		||||
    base = expr.get('base')
 | 
			
		||||
 | 
			
		||||
@@ -98,18 +97,15 @@ struct %(name)s
 | 
			
		||||
    char qapi_dummy_field_for_empty_struct;
 | 
			
		||||
''')
 | 
			
		||||
 | 
			
		||||
    if len(fieldname):
 | 
			
		||||
        fieldname = " " + fieldname
 | 
			
		||||
    ret += mcgen('''
 | 
			
		||||
}%(field)s;
 | 
			
		||||
''',
 | 
			
		||||
            field=fieldname)
 | 
			
		||||
};
 | 
			
		||||
''')
 | 
			
		||||
 | 
			
		||||
    return ret
 | 
			
		||||
 | 
			
		||||
def generate_enum_lookup(name, values):
 | 
			
		||||
    ret = mcgen('''
 | 
			
		||||
const char *%(name)s_lookup[] = {
 | 
			
		||||
const char * const %(name)s_lookup[] = {
 | 
			
		||||
''',
 | 
			
		||||
                name=c_name(name))
 | 
			
		||||
    i = 0
 | 
			
		||||
@@ -132,7 +128,7 @@ const char *%(name)s_lookup[] = {
 | 
			
		||||
def generate_enum(name, values):
 | 
			
		||||
    name = c_name(name)
 | 
			
		||||
    lookup_decl = mcgen('''
 | 
			
		||||
extern const char *%(name)s_lookup[];
 | 
			
		||||
extern const char * const %(name)s_lookup[];
 | 
			
		||||
''',
 | 
			
		||||
                name=name)
 | 
			
		||||
 | 
			
		||||
@@ -329,30 +325,29 @@ fdecl.write(mcgen('''
 | 
			
		||||
'''))
 | 
			
		||||
 | 
			
		||||
exprs = parse_schema(input_file)
 | 
			
		||||
exprs = filter(lambda expr: not expr.has_key('gen'), exprs)
 | 
			
		||||
 | 
			
		||||
fdecl.write(guardstart("QAPI_TYPES_BUILTIN_STRUCT_DECL"))
 | 
			
		||||
for typename in builtin_types.keys():
 | 
			
		||||
    fdecl.write(generate_fwd_struct(typename, None, builtin_type=True))
 | 
			
		||||
    fdecl.write(generate_fwd_builtin(typename))
 | 
			
		||||
fdecl.write(guardend("QAPI_TYPES_BUILTIN_STRUCT_DECL"))
 | 
			
		||||
 | 
			
		||||
for expr in exprs:
 | 
			
		||||
    ret = "\n"
 | 
			
		||||
    if expr.has_key('struct'):
 | 
			
		||||
        ret += generate_fwd_struct(expr['struct'], expr['data'])
 | 
			
		||||
        ret += generate_fwd_struct(expr['struct'])
 | 
			
		||||
    elif expr.has_key('enum'):
 | 
			
		||||
        ret += generate_enum(expr['enum'], expr['data']) + "\n"
 | 
			
		||||
        ret += generate_fwd_enum_struct(expr['enum'], expr['data'])
 | 
			
		||||
        ret += generate_fwd_enum_struct(expr['enum'])
 | 
			
		||||
        fdef.write(generate_enum_lookup(expr['enum'], expr['data']))
 | 
			
		||||
    elif expr.has_key('union'):
 | 
			
		||||
        ret += generate_fwd_struct(expr['union'], expr['data']) + "\n"
 | 
			
		||||
        ret += generate_fwd_struct(expr['union']) + "\n"
 | 
			
		||||
        enum_define = discriminator_find_enum_define(expr)
 | 
			
		||||
        if not enum_define:
 | 
			
		||||
            ret += generate_enum('%sKind' % expr['union'], expr['data'].keys())
 | 
			
		||||
            fdef.write(generate_enum_lookup('%sKind' % expr['union'],
 | 
			
		||||
                                            expr['data'].keys()))
 | 
			
		||||
    elif expr.has_key('alternate'):
 | 
			
		||||
        ret += generate_fwd_struct(expr['alternate'], expr['data']) + "\n"
 | 
			
		||||
        ret += generate_fwd_struct(expr['alternate']) + "\n"
 | 
			
		||||
        ret += generate_enum('%sKind' % expr['alternate'], expr['data'].keys())
 | 
			
		||||
        fdef.write(generate_enum_lookup('%sKind' % expr['alternate'],
 | 
			
		||||
                                        expr['data'].keys()))
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										348
									
								
								scripts/qapi.py
									
									
									
									
									
								
							
							
						
						
									
										348
									
								
								scripts/qapi.py
									
									
									
									
									
								
							@@ -65,6 +65,10 @@ union_types = []
 | 
			
		||||
events = []
 | 
			
		||||
all_names = {}
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# Parsing the schema into expressions
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
def error_path(parent):
 | 
			
		||||
    res = ""
 | 
			
		||||
    while parent:
 | 
			
		||||
@@ -75,7 +79,7 @@ def error_path(parent):
 | 
			
		||||
 | 
			
		||||
class QAPISchemaError(Exception):
 | 
			
		||||
    def __init__(self, schema, msg):
 | 
			
		||||
        self.input_file = schema.input_file
 | 
			
		||||
        self.fname = schema.fname
 | 
			
		||||
        self.msg = msg
 | 
			
		||||
        self.col = 1
 | 
			
		||||
        self.line = schema.line
 | 
			
		||||
@@ -84,11 +88,11 @@ class QAPISchemaError(Exception):
 | 
			
		||||
                self.col = (self.col + 7) % 8 + 1
 | 
			
		||||
            else:
 | 
			
		||||
                self.col += 1
 | 
			
		||||
        self.info = schema.parent_info
 | 
			
		||||
        self.info = schema.incl_info
 | 
			
		||||
 | 
			
		||||
    def __str__(self):
 | 
			
		||||
        return error_path(self.info) + \
 | 
			
		||||
            "%s:%d:%d: %s" % (self.input_file, self.line, self.col, self.msg)
 | 
			
		||||
            "%s:%d:%d: %s" % (self.fname, self.line, self.col, self.msg)
 | 
			
		||||
 | 
			
		||||
class QAPIExprError(Exception):
 | 
			
		||||
    def __init__(self, expr_info, msg):
 | 
			
		||||
@@ -101,19 +105,12 @@ class QAPIExprError(Exception):
 | 
			
		||||
 | 
			
		||||
class QAPISchema:
 | 
			
		||||
 | 
			
		||||
    def __init__(self, fp, input_relname=None, include_hist=[],
 | 
			
		||||
                 previously_included=[], parent_info=None):
 | 
			
		||||
        """ include_hist is a stack used to detect inclusion cycles
 | 
			
		||||
            previously_included is a global state used to avoid multiple
 | 
			
		||||
                                inclusions of the same file"""
 | 
			
		||||
        input_fname = os.path.abspath(fp.name)
 | 
			
		||||
        if input_relname is None:
 | 
			
		||||
            input_relname = fp.name
 | 
			
		||||
        self.input_dir = os.path.dirname(input_fname)
 | 
			
		||||
        self.input_file = input_relname
 | 
			
		||||
        self.include_hist = include_hist + [(input_relname, input_fname)]
 | 
			
		||||
        previously_included.append(input_fname)
 | 
			
		||||
        self.parent_info = parent_info
 | 
			
		||||
    def __init__(self, fp, previously_included = [], incl_info = None):
 | 
			
		||||
        abs_fname = os.path.abspath(fp.name)
 | 
			
		||||
        fname = fp.name
 | 
			
		||||
        self.fname = fname
 | 
			
		||||
        previously_included.append(abs_fname)
 | 
			
		||||
        self.incl_info = incl_info
 | 
			
		||||
        self.src = fp.read()
 | 
			
		||||
        if self.src == '' or self.src[-1] != '\n':
 | 
			
		||||
            self.src += '\n'
 | 
			
		||||
@@ -124,7 +121,8 @@ class QAPISchema:
 | 
			
		||||
        self.accept()
 | 
			
		||||
 | 
			
		||||
        while self.tok != None:
 | 
			
		||||
            expr_info = {'file': input_relname, 'line': self.line, 'parent': self.parent_info}
 | 
			
		||||
            expr_info = {'file': fname, 'line': self.line,
 | 
			
		||||
                         'parent': self.incl_info}
 | 
			
		||||
            expr = self.get_expr(False)
 | 
			
		||||
            if isinstance(expr, dict) and "include" in expr:
 | 
			
		||||
                if len(expr) != 1:
 | 
			
		||||
@@ -134,21 +132,25 @@ class QAPISchema:
 | 
			
		||||
                    raise QAPIExprError(expr_info,
 | 
			
		||||
                                        'Expected a file name (string), got: %s'
 | 
			
		||||
                                        % include)
 | 
			
		||||
                include_path = os.path.join(self.input_dir, include)
 | 
			
		||||
                for elem in self.include_hist:
 | 
			
		||||
                    if include_path == elem[1]:
 | 
			
		||||
                incl_abs_fname = os.path.join(os.path.dirname(abs_fname),
 | 
			
		||||
                                              include)
 | 
			
		||||
                # catch inclusion cycle
 | 
			
		||||
                inf = expr_info
 | 
			
		||||
                while inf:
 | 
			
		||||
                    if incl_abs_fname == os.path.abspath(inf['file']):
 | 
			
		||||
                        raise QAPIExprError(expr_info, "Inclusion loop for %s"
 | 
			
		||||
                                            % include)
 | 
			
		||||
                    inf = inf['parent']
 | 
			
		||||
                # skip multiple include of the same file
 | 
			
		||||
                if include_path in previously_included:
 | 
			
		||||
                if incl_abs_fname in previously_included:
 | 
			
		||||
                    continue
 | 
			
		||||
                try:
 | 
			
		||||
                    fobj = open(include_path, 'r')
 | 
			
		||||
                    fobj = open(incl_abs_fname, 'r')
 | 
			
		||||
                except IOError, e:
 | 
			
		||||
                    raise QAPIExprError(expr_info,
 | 
			
		||||
                                        '%s: %s' % (e.strerror, include))
 | 
			
		||||
                exprs_include = QAPISchema(fobj, include, self.include_hist,
 | 
			
		||||
                                           previously_included, expr_info)
 | 
			
		||||
                exprs_include = QAPISchema(fobj, previously_included,
 | 
			
		||||
                                           expr_info)
 | 
			
		||||
                self.exprs.extend(exprs_include.exprs)
 | 
			
		||||
            else:
 | 
			
		||||
                expr_elem = {'expr': expr,
 | 
			
		||||
@@ -219,20 +221,18 @@ class QAPISchema:
 | 
			
		||||
                        return
 | 
			
		||||
                    else:
 | 
			
		||||
                        string += ch
 | 
			
		||||
            elif self.tok in "tfn":
 | 
			
		||||
                val = self.src[self.cursor - 1:]
 | 
			
		||||
                if val.startswith("true"):
 | 
			
		||||
                    self.val = True
 | 
			
		||||
                    self.cursor += 3
 | 
			
		||||
                    return
 | 
			
		||||
                elif val.startswith("false"):
 | 
			
		||||
                    self.val = False
 | 
			
		||||
                    self.cursor += 4
 | 
			
		||||
                    return
 | 
			
		||||
                elif val.startswith("null"):
 | 
			
		||||
                    self.val = None
 | 
			
		||||
                    self.cursor += 3
 | 
			
		||||
                    return
 | 
			
		||||
            elif self.src.startswith("true", self.pos):
 | 
			
		||||
                self.val = True
 | 
			
		||||
                self.cursor += 3
 | 
			
		||||
                return
 | 
			
		||||
            elif self.src.startswith("false", self.pos):
 | 
			
		||||
                self.val = False
 | 
			
		||||
                self.cursor += 4
 | 
			
		||||
                return
 | 
			
		||||
            elif self.src.startswith("null", self.pos):
 | 
			
		||||
                self.val = None
 | 
			
		||||
                self.cursor += 3
 | 
			
		||||
                return
 | 
			
		||||
            elif self.tok == '\n':
 | 
			
		||||
                if self.cursor == len(self.src):
 | 
			
		||||
                    self.tok = None
 | 
			
		||||
@@ -300,6 +300,10 @@ class QAPISchema:
 | 
			
		||||
            raise QAPISchemaError(self, 'Expected "{", "[" or string')
 | 
			
		||||
        return expr
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# Semantic analysis of schema expressions
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
def find_base_fields(base):
 | 
			
		||||
    base_struct_define = find_struct(base)
 | 
			
		||||
    if not base_struct_define:
 | 
			
		||||
@@ -360,6 +364,60 @@ def check_name(expr_info, source, name, allow_optional = False,
 | 
			
		||||
        raise QAPIExprError(expr_info,
 | 
			
		||||
                            "%s uses invalid name '%s'" % (source, name))
 | 
			
		||||
 | 
			
		||||
def add_name(name, info, meta, implicit = False):
 | 
			
		||||
    global all_names
 | 
			
		||||
    check_name(info, "'%s'" % meta, name)
 | 
			
		||||
    if name in all_names:
 | 
			
		||||
        raise QAPIExprError(info,
 | 
			
		||||
                            "%s '%s' is already defined"
 | 
			
		||||
                            % (all_names[name], name))
 | 
			
		||||
    if not implicit and name[-4:] == 'Kind':
 | 
			
		||||
        raise QAPIExprError(info,
 | 
			
		||||
                            "%s '%s' should not end in 'Kind'"
 | 
			
		||||
                            % (meta, name))
 | 
			
		||||
    all_names[name] = meta
 | 
			
		||||
 | 
			
		||||
def add_struct(definition, info):
 | 
			
		||||
    global struct_types
 | 
			
		||||
    name = definition['struct']
 | 
			
		||||
    add_name(name, info, 'struct')
 | 
			
		||||
    struct_types.append(definition)
 | 
			
		||||
 | 
			
		||||
def find_struct(name):
 | 
			
		||||
    global struct_types
 | 
			
		||||
    for struct in struct_types:
 | 
			
		||||
        if struct['struct'] == name:
 | 
			
		||||
            return struct
 | 
			
		||||
    return None
 | 
			
		||||
 | 
			
		||||
def add_union(definition, info):
 | 
			
		||||
    global union_types
 | 
			
		||||
    name = definition['union']
 | 
			
		||||
    add_name(name, info, 'union')
 | 
			
		||||
    union_types.append(definition)
 | 
			
		||||
 | 
			
		||||
def find_union(name):
 | 
			
		||||
    global union_types
 | 
			
		||||
    for union in union_types:
 | 
			
		||||
        if union['union'] == name:
 | 
			
		||||
            return union
 | 
			
		||||
    return None
 | 
			
		||||
 | 
			
		||||
def add_enum(name, info, enum_values = None, implicit = False):
 | 
			
		||||
    global enum_types
 | 
			
		||||
    add_name(name, info, 'enum', implicit)
 | 
			
		||||
    enum_types.append({"enum_name": name, "enum_values": enum_values})
 | 
			
		||||
 | 
			
		||||
def find_enum(name):
 | 
			
		||||
    global enum_types
 | 
			
		||||
    for enum in enum_types:
 | 
			
		||||
        if enum['enum_name'] == name:
 | 
			
		||||
            return enum
 | 
			
		||||
    return None
 | 
			
		||||
 | 
			
		||||
def is_enum(name):
 | 
			
		||||
    return find_enum(name) != None
 | 
			
		||||
 | 
			
		||||
def check_type(expr_info, source, value, allow_array = False,
 | 
			
		||||
               allow_dict = False, allow_optional = False,
 | 
			
		||||
               allow_star = False, allow_metas = []):
 | 
			
		||||
@@ -522,7 +580,7 @@ def check_union(expr, expr_info):
 | 
			
		||||
        # Each value must name a known type; furthermore, in flat unions,
 | 
			
		||||
        # branches must be a struct with no overlapping member names
 | 
			
		||||
        check_type(expr_info, "Member '%s' of union '%s'" % (key, name),
 | 
			
		||||
                   value, allow_array=True, allow_metas=allow_metas)
 | 
			
		||||
                   value, allow_array=not base, allow_metas=allow_metas)
 | 
			
		||||
        if base:
 | 
			
		||||
            branch_struct = find_struct(value)
 | 
			
		||||
            assert branch_struct
 | 
			
		||||
@@ -607,26 +665,6 @@ def check_struct(expr, expr_info):
 | 
			
		||||
    if expr.get('base'):
 | 
			
		||||
        check_member_clash(expr_info, expr['base'], expr['data'])
 | 
			
		||||
 | 
			
		||||
def check_exprs(schema):
 | 
			
		||||
    for expr_elem in schema.exprs:
 | 
			
		||||
        expr = expr_elem['expr']
 | 
			
		||||
        info = expr_elem['info']
 | 
			
		||||
 | 
			
		||||
        if expr.has_key('enum'):
 | 
			
		||||
            check_enum(expr, info)
 | 
			
		||||
        elif expr.has_key('union'):
 | 
			
		||||
            check_union(expr, info)
 | 
			
		||||
        elif expr.has_key('alternate'):
 | 
			
		||||
            check_alternate(expr, info)
 | 
			
		||||
        elif expr.has_key('struct'):
 | 
			
		||||
            check_struct(expr, info)
 | 
			
		||||
        elif expr.has_key('command'):
 | 
			
		||||
            check_command(expr, info)
 | 
			
		||||
        elif expr.has_key('event'):
 | 
			
		||||
            check_event(expr, info)
 | 
			
		||||
        else:
 | 
			
		||||
            assert False, 'unexpected meta type'
 | 
			
		||||
 | 
			
		||||
def check_keys(expr_elem, meta, required, optional=[]):
 | 
			
		||||
    expr = expr_elem['expr']
 | 
			
		||||
    info = expr_elem['info']
 | 
			
		||||
@@ -650,69 +688,83 @@ def check_keys(expr_elem, meta, required, optional=[]):
 | 
			
		||||
                                "Key '%s' is missing from %s '%s'"
 | 
			
		||||
                                % (key, meta, name))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def parse_schema(input_file):
 | 
			
		||||
def check_exprs(exprs):
 | 
			
		||||
    global all_names
 | 
			
		||||
    exprs = []
 | 
			
		||||
 | 
			
		||||
    # First pass: read entire file into memory
 | 
			
		||||
    # Learn the types and check for valid expression keys
 | 
			
		||||
    for builtin in builtin_types.keys():
 | 
			
		||||
        all_names[builtin] = 'built-in'
 | 
			
		||||
    for expr_elem in exprs:
 | 
			
		||||
        expr = expr_elem['expr']
 | 
			
		||||
        info = expr_elem['info']
 | 
			
		||||
        if expr.has_key('enum'):
 | 
			
		||||
            check_keys(expr_elem, 'enum', ['data'])
 | 
			
		||||
            add_enum(expr['enum'], info, expr['data'])
 | 
			
		||||
        elif expr.has_key('union'):
 | 
			
		||||
            check_keys(expr_elem, 'union', ['data'],
 | 
			
		||||
                       ['base', 'discriminator'])
 | 
			
		||||
            add_union(expr, info)
 | 
			
		||||
        elif expr.has_key('alternate'):
 | 
			
		||||
            check_keys(expr_elem, 'alternate', ['data'])
 | 
			
		||||
            add_name(expr['alternate'], info, 'alternate')
 | 
			
		||||
        elif expr.has_key('struct'):
 | 
			
		||||
            check_keys(expr_elem, 'struct', ['data'], ['base'])
 | 
			
		||||
            add_struct(expr, info)
 | 
			
		||||
        elif expr.has_key('command'):
 | 
			
		||||
            check_keys(expr_elem, 'command', [],
 | 
			
		||||
                       ['data', 'returns', 'gen', 'success-response'])
 | 
			
		||||
            add_name(expr['command'], info, 'command')
 | 
			
		||||
        elif expr.has_key('event'):
 | 
			
		||||
            check_keys(expr_elem, 'event', [], ['data'])
 | 
			
		||||
            add_name(expr['event'], info, 'event')
 | 
			
		||||
        else:
 | 
			
		||||
            raise QAPIExprError(expr_elem['info'],
 | 
			
		||||
                                "Expression is missing metatype")
 | 
			
		||||
 | 
			
		||||
    # Try again for hidden UnionKind enum
 | 
			
		||||
    for expr_elem in exprs:
 | 
			
		||||
        expr = expr_elem['expr']
 | 
			
		||||
        if expr.has_key('union'):
 | 
			
		||||
            if not discriminator_find_enum_define(expr):
 | 
			
		||||
                add_enum('%sKind' % expr['union'], expr_elem['info'],
 | 
			
		||||
                         implicit=True)
 | 
			
		||||
        elif expr.has_key('alternate'):
 | 
			
		||||
            add_enum('%sKind' % expr['alternate'], expr_elem['info'],
 | 
			
		||||
                     implicit=True)
 | 
			
		||||
 | 
			
		||||
    # Validate that exprs make sense
 | 
			
		||||
    for expr_elem in exprs:
 | 
			
		||||
        expr = expr_elem['expr']
 | 
			
		||||
        info = expr_elem['info']
 | 
			
		||||
 | 
			
		||||
        if expr.has_key('enum'):
 | 
			
		||||
            check_enum(expr, info)
 | 
			
		||||
        elif expr.has_key('union'):
 | 
			
		||||
            check_union(expr, info)
 | 
			
		||||
        elif expr.has_key('alternate'):
 | 
			
		||||
            check_alternate(expr, info)
 | 
			
		||||
        elif expr.has_key('struct'):
 | 
			
		||||
            check_struct(expr, info)
 | 
			
		||||
        elif expr.has_key('command'):
 | 
			
		||||
            check_command(expr, info)
 | 
			
		||||
        elif expr.has_key('event'):
 | 
			
		||||
            check_event(expr, info)
 | 
			
		||||
        else:
 | 
			
		||||
            assert False, 'unexpected meta type'
 | 
			
		||||
 | 
			
		||||
    return map(lambda expr_elem: expr_elem['expr'], exprs)
 | 
			
		||||
 | 
			
		||||
def parse_schema(fname):
 | 
			
		||||
    try:
 | 
			
		||||
        schema = QAPISchema(open(input_file, "r"))
 | 
			
		||||
        schema = QAPISchema(open(fname, "r"))
 | 
			
		||||
        return check_exprs(schema.exprs)
 | 
			
		||||
    except (QAPISchemaError, QAPIExprError), e:
 | 
			
		||||
        print >>sys.stderr, e
 | 
			
		||||
        exit(1)
 | 
			
		||||
 | 
			
		||||
    try:
 | 
			
		||||
        # Next pass: learn the types and check for valid expression keys. At
 | 
			
		||||
        # this point, top-level 'include' has already been flattened.
 | 
			
		||||
        for builtin in builtin_types.keys():
 | 
			
		||||
            all_names[builtin] = 'built-in'
 | 
			
		||||
        for expr_elem in schema.exprs:
 | 
			
		||||
            expr = expr_elem['expr']
 | 
			
		||||
            info = expr_elem['info']
 | 
			
		||||
            if expr.has_key('enum'):
 | 
			
		||||
                check_keys(expr_elem, 'enum', ['data'])
 | 
			
		||||
                add_enum(expr['enum'], info, expr['data'])
 | 
			
		||||
            elif expr.has_key('union'):
 | 
			
		||||
                check_keys(expr_elem, 'union', ['data'],
 | 
			
		||||
                           ['base', 'discriminator'])
 | 
			
		||||
                add_union(expr, info)
 | 
			
		||||
            elif expr.has_key('alternate'):
 | 
			
		||||
                check_keys(expr_elem, 'alternate', ['data'])
 | 
			
		||||
                add_name(expr['alternate'], info, 'alternate')
 | 
			
		||||
            elif expr.has_key('struct'):
 | 
			
		||||
                check_keys(expr_elem, 'struct', ['data'], ['base'])
 | 
			
		||||
                add_struct(expr, info)
 | 
			
		||||
            elif expr.has_key('command'):
 | 
			
		||||
                check_keys(expr_elem, 'command', [],
 | 
			
		||||
                           ['data', 'returns', 'gen', 'success-response'])
 | 
			
		||||
                add_name(expr['command'], info, 'command')
 | 
			
		||||
            elif expr.has_key('event'):
 | 
			
		||||
                check_keys(expr_elem, 'event', [], ['data'])
 | 
			
		||||
                add_name(expr['event'], info, 'event')
 | 
			
		||||
            else:
 | 
			
		||||
                raise QAPIExprError(expr_elem['info'],
 | 
			
		||||
                                    "Expression is missing metatype")
 | 
			
		||||
            exprs.append(expr)
 | 
			
		||||
 | 
			
		||||
        # Try again for hidden UnionKind enum
 | 
			
		||||
        for expr_elem in schema.exprs:
 | 
			
		||||
            expr = expr_elem['expr']
 | 
			
		||||
            if expr.has_key('union'):
 | 
			
		||||
                if not discriminator_find_enum_define(expr):
 | 
			
		||||
                    add_enum('%sKind' % expr['union'], expr_elem['info'],
 | 
			
		||||
                             implicit=True)
 | 
			
		||||
            elif expr.has_key('alternate'):
 | 
			
		||||
                add_enum('%sKind' % expr['alternate'], expr_elem['info'],
 | 
			
		||||
                         implicit=True)
 | 
			
		||||
 | 
			
		||||
        # Final pass - validate that exprs make sense
 | 
			
		||||
        check_exprs(schema)
 | 
			
		||||
    except QAPIExprError, e:
 | 
			
		||||
        print >>sys.stderr, e
 | 
			
		||||
        exit(1)
 | 
			
		||||
 | 
			
		||||
    return exprs
 | 
			
		||||
#
 | 
			
		||||
# Code generation helpers
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
def parse_args(typeinfo):
 | 
			
		||||
    if isinstance(typeinfo, str):
 | 
			
		||||
@@ -831,60 +883,6 @@ def type_name(value):
 | 
			
		||||
        return value
 | 
			
		||||
    return c_name(value)
 | 
			
		||||
 | 
			
		||||
def add_name(name, info, meta, implicit = False):
 | 
			
		||||
    global all_names
 | 
			
		||||
    check_name(info, "'%s'" % meta, name)
 | 
			
		||||
    if name in all_names:
 | 
			
		||||
        raise QAPIExprError(info,
 | 
			
		||||
                            "%s '%s' is already defined"
 | 
			
		||||
                            % (all_names[name], name))
 | 
			
		||||
    if not implicit and name[-4:] == 'Kind':
 | 
			
		||||
        raise QAPIExprError(info,
 | 
			
		||||
                            "%s '%s' should not end in 'Kind'"
 | 
			
		||||
                            % (meta, name))
 | 
			
		||||
    all_names[name] = meta
 | 
			
		||||
 | 
			
		||||
def add_struct(definition, info):
 | 
			
		||||
    global struct_types
 | 
			
		||||
    name = definition['struct']
 | 
			
		||||
    add_name(name, info, 'struct')
 | 
			
		||||
    struct_types.append(definition)
 | 
			
		||||
 | 
			
		||||
def find_struct(name):
 | 
			
		||||
    global struct_types
 | 
			
		||||
    for struct in struct_types:
 | 
			
		||||
        if struct['struct'] == name:
 | 
			
		||||
            return struct
 | 
			
		||||
    return None
 | 
			
		||||
 | 
			
		||||
def add_union(definition, info):
 | 
			
		||||
    global union_types
 | 
			
		||||
    name = definition['union']
 | 
			
		||||
    add_name(name, info, 'union')
 | 
			
		||||
    union_types.append(definition)
 | 
			
		||||
 | 
			
		||||
def find_union(name):
 | 
			
		||||
    global union_types
 | 
			
		||||
    for union in union_types:
 | 
			
		||||
        if union['union'] == name:
 | 
			
		||||
            return union
 | 
			
		||||
    return None
 | 
			
		||||
 | 
			
		||||
def add_enum(name, info, enum_values = None, implicit = False):
 | 
			
		||||
    global enum_types
 | 
			
		||||
    add_name(name, info, 'enum', implicit)
 | 
			
		||||
    enum_types.append({"enum_name": name, "enum_values": enum_values})
 | 
			
		||||
 | 
			
		||||
def find_enum(name):
 | 
			
		||||
    global enum_types
 | 
			
		||||
    for enum in enum_types:
 | 
			
		||||
        if enum['enum_name'] == name:
 | 
			
		||||
            return enum
 | 
			
		||||
    return None
 | 
			
		||||
 | 
			
		||||
def is_enum(name):
 | 
			
		||||
    return find_enum(name) != None
 | 
			
		||||
 | 
			
		||||
eatspace = '\033EATSPACE.'
 | 
			
		||||
pointer_suffix = ' *' + eatspace
 | 
			
		||||
 | 
			
		||||
@@ -981,6 +979,10 @@ def guardend(name):
 | 
			
		||||
''',
 | 
			
		||||
                 name=guardname(name))
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# Common command line parsing
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
def parse_command_line(extra_options = "", extra_long_options = []):
 | 
			
		||||
 | 
			
		||||
    try:
 | 
			
		||||
@@ -1018,9 +1020,13 @@ def parse_command_line(extra_options = "", extra_long_options = []):
 | 
			
		||||
    if len(args) != 1:
 | 
			
		||||
        print >>sys.stderr, "%s: need exactly one argument" % sys.argv[0]
 | 
			
		||||
        sys.exit(1)
 | 
			
		||||
    input_file = args[0]
 | 
			
		||||
    fname = args[0]
 | 
			
		||||
 | 
			
		||||
    return (input_file, output_dir, do_c, do_h, prefix, extra_opts)
 | 
			
		||||
    return (fname, output_dir, do_c, do_h, prefix, extra_opts)
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# Generate output files with boilerplate
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
def open_output(output_dir, do_c, do_h, prefix, c_file, h_file,
 | 
			
		||||
                c_comment, h_comment):
 | 
			
		||||
 
 | 
			
		||||
@@ -65,6 +65,11 @@ def list_node(path):
 | 
			
		||||
    print ''
 | 
			
		||||
    for item in items:
 | 
			
		||||
        if item['type'].startswith('child<'):
 | 
			
		||||
            list_node(path + '/' + item['name'])
 | 
			
		||||
            list_node((path if (path != '/') else '')  + '/' + item['name'])
 | 
			
		||||
 | 
			
		||||
list_node('/machine')
 | 
			
		||||
if len(args) == 0:
 | 
			
		||||
    path = '/'
 | 
			
		||||
else:
 | 
			
		||||
    path = args[0]
 | 
			
		||||
 | 
			
		||||
list_node(path)
 | 
			
		||||
 
 | 
			
		||||
@@ -27,6 +27,7 @@
 | 
			
		||||
#include <time.h>
 | 
			
		||||
 | 
			
		||||
#include "cpu.h"
 | 
			
		||||
#include "exec/semihost.h"
 | 
			
		||||
#ifdef CONFIG_USER_ONLY
 | 
			
		||||
#include "qemu.h"
 | 
			
		||||
 | 
			
		||||
@@ -440,10 +441,7 @@ uint32_t do_arm_semihosting(CPUARMState *env)
 | 
			
		||||
            input_size = arg1;
 | 
			
		||||
            /* Compute the size of the output string.  */
 | 
			
		||||
#if !defined(CONFIG_USER_ONLY)
 | 
			
		||||
            output_size = strlen(ts->boot_info->kernel_filename)
 | 
			
		||||
                        + 1  /* Separating space.  */
 | 
			
		||||
                        + strlen(ts->boot_info->kernel_cmdline)
 | 
			
		||||
                        + 1; /* Terminating null byte.  */
 | 
			
		||||
            output_size = strlen(semihosting_get_cmdline()) + 1;
 | 
			
		||||
#else
 | 
			
		||||
            unsigned int i;
 | 
			
		||||
 | 
			
		||||
@@ -474,9 +472,7 @@ uint32_t do_arm_semihosting(CPUARMState *env)
 | 
			
		||||
 | 
			
		||||
            /* Copy the command-line arguments.  */
 | 
			
		||||
#if !defined(CONFIG_USER_ONLY)
 | 
			
		||||
            pstrcpy(output_buffer, output_size, ts->boot_info->kernel_filename);
 | 
			
		||||
            pstrcat(output_buffer, output_size, " ");
 | 
			
		||||
            pstrcat(output_buffer, output_size, ts->boot_info->kernel_cmdline);
 | 
			
		||||
            pstrcpy(output_buffer, output_size, semihosting_get_cmdline());
 | 
			
		||||
#else
 | 
			
		||||
            if (output_size == 1) {
 | 
			
		||||
                /* Empty command-line.  */
 | 
			
		||||
 
 | 
			
		||||
@@ -105,6 +105,8 @@ typedef struct ARMCPU {
 | 
			
		||||
 | 
			
		||||
    /* CPU has memory protection unit */
 | 
			
		||||
    bool has_mpu;
 | 
			
		||||
    /* PMSAv7 MPU number of supported regions */
 | 
			
		||||
    uint32_t pmsav7_dregion;
 | 
			
		||||
 | 
			
		||||
    /* PSCI conduit used to invoke PSCI methods
 | 
			
		||||
     * 0 - disabled, 1 - smc, 2 - hvc
 | 
			
		||||
 
 | 
			
		||||
@@ -55,7 +55,7 @@ static void cp_reg_reset(gpointer key, gpointer value, gpointer opaque)
 | 
			
		||||
    ARMCPRegInfo *ri = value;
 | 
			
		||||
    ARMCPU *cpu = opaque;
 | 
			
		||||
 | 
			
		||||
    if (ri->type & ARM_CP_SPECIAL) {
 | 
			
		||||
    if (ri->type & (ARM_CP_SPECIAL | ARM_CP_ALIAS)) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -457,6 +457,9 @@ static Property arm_cpu_has_el3_property =
 | 
			
		||||
static Property arm_cpu_has_mpu_property =
 | 
			
		||||
            DEFINE_PROP_BOOL("has-mpu", ARMCPU, has_mpu, true);
 | 
			
		||||
 | 
			
		||||
static Property arm_cpu_pmsav7_dregion_property =
 | 
			
		||||
            DEFINE_PROP_UINT32("pmsav7-dregion", ARMCPU, pmsav7_dregion, 16);
 | 
			
		||||
 | 
			
		||||
static void arm_cpu_post_init(Object *obj)
 | 
			
		||||
{
 | 
			
		||||
    ARMCPU *cpu = ARM_CPU(obj);
 | 
			
		||||
@@ -488,6 +491,11 @@ static void arm_cpu_post_init(Object *obj)
 | 
			
		||||
    if (arm_feature(&cpu->env, ARM_FEATURE_MPU)) {
 | 
			
		||||
        qdev_property_add_static(DEVICE(obj), &arm_cpu_has_mpu_property,
 | 
			
		||||
                                 &error_abort);
 | 
			
		||||
        if (arm_feature(&cpu->env, ARM_FEATURE_V7)) {
 | 
			
		||||
            qdev_property_add_static(DEVICE(obj),
 | 
			
		||||
                                     &arm_cpu_pmsav7_dregion_property,
 | 
			
		||||
                                     &error_abort);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -580,6 +588,22 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
 | 
			
		||||
        unset_feature(env, ARM_FEATURE_MPU);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (arm_feature(env, ARM_FEATURE_MPU) &&
 | 
			
		||||
        arm_feature(env, ARM_FEATURE_V7)) {
 | 
			
		||||
        uint32_t nr = cpu->pmsav7_dregion;
 | 
			
		||||
 | 
			
		||||
        if (nr > 0xff) {
 | 
			
		||||
            error_setg(errp, "PMSAv7 MPU #regions invalid %" PRIu32 "\n", nr);
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (nr) {
 | 
			
		||||
            env->pmsav7.drbar = g_new0(uint32_t, nr);
 | 
			
		||||
            env->pmsav7.drsr = g_new0(uint32_t, nr);
 | 
			
		||||
            env->pmsav7.dracr = g_new0(uint32_t, nr);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    register_cp_regs_for_features(cpu);
 | 
			
		||||
    arm_cpu_register_gdb_regs_for_features(cpu);
 | 
			
		||||
 | 
			
		||||
@@ -812,6 +836,15 @@ static void cortex_m3_initfn(Object *obj)
 | 
			
		||||
    cpu->midr = 0x410fc231;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void cortex_m4_initfn(Object *obj)
 | 
			
		||||
{
 | 
			
		||||
    ARMCPU *cpu = ARM_CPU(obj);
 | 
			
		||||
 | 
			
		||||
    set_feature(&cpu->env, ARM_FEATURE_V7);
 | 
			
		||||
    set_feature(&cpu->env, ARM_FEATURE_M);
 | 
			
		||||
    set_feature(&cpu->env, ARM_FEATURE_THUMB_DSP);
 | 
			
		||||
    cpu->midr = 0x410fc240; /* r0p0 */
 | 
			
		||||
}
 | 
			
		||||
static void arm_v7m_class_init(ObjectClass *oc, void *data)
 | 
			
		||||
{
 | 
			
		||||
    CPUClass *cc = CPU_CLASS(oc);
 | 
			
		||||
@@ -823,6 +856,43 @@ static void arm_v7m_class_init(ObjectClass *oc, void *data)
 | 
			
		||||
    cc->cpu_exec_interrupt = arm_v7m_cpu_exec_interrupt;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const ARMCPRegInfo cortexr5_cp_reginfo[] = {
 | 
			
		||||
    /* Dummy the TCM region regs for the moment */
 | 
			
		||||
    { .name = "ATCM", .cp = 15, .opc1 = 0, .crn = 9, .crm = 1, .opc2 = 0,
 | 
			
		||||
      .access = PL1_RW, .type = ARM_CP_CONST },
 | 
			
		||||
    { .name = "BTCM", .cp = 15, .opc1 = 0, .crn = 9, .crm = 1, .opc2 = 1,
 | 
			
		||||
      .access = PL1_RW, .type = ARM_CP_CONST },
 | 
			
		||||
    REGINFO_SENTINEL
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void cortex_r5_initfn(Object *obj)
 | 
			
		||||
{
 | 
			
		||||
    ARMCPU *cpu = ARM_CPU(obj);
 | 
			
		||||
 | 
			
		||||
    set_feature(&cpu->env, ARM_FEATURE_V7);
 | 
			
		||||
    set_feature(&cpu->env, ARM_FEATURE_THUMB_DIV);
 | 
			
		||||
    set_feature(&cpu->env, ARM_FEATURE_ARM_DIV);
 | 
			
		||||
    set_feature(&cpu->env, ARM_FEATURE_V7MP);
 | 
			
		||||
    set_feature(&cpu->env, ARM_FEATURE_MPU);
 | 
			
		||||
    cpu->midr = 0x411fc153; /* r1p3 */
 | 
			
		||||
    cpu->id_pfr0 = 0x0131;
 | 
			
		||||
    cpu->id_pfr1 = 0x001;
 | 
			
		||||
    cpu->id_dfr0 = 0x010400;
 | 
			
		||||
    cpu->id_afr0 = 0x0;
 | 
			
		||||
    cpu->id_mmfr0 = 0x0210030;
 | 
			
		||||
    cpu->id_mmfr1 = 0x00000000;
 | 
			
		||||
    cpu->id_mmfr2 = 0x01200000;
 | 
			
		||||
    cpu->id_mmfr3 = 0x0211;
 | 
			
		||||
    cpu->id_isar0 = 0x2101111;
 | 
			
		||||
    cpu->id_isar1 = 0x13112111;
 | 
			
		||||
    cpu->id_isar2 = 0x21232141;
 | 
			
		||||
    cpu->id_isar3 = 0x01112131;
 | 
			
		||||
    cpu->id_isar4 = 0x0010142;
 | 
			
		||||
    cpu->id_isar5 = 0x0;
 | 
			
		||||
    cpu->mp_is_up = true;
 | 
			
		||||
    define_arm_cp_regs(cpu, cortexr5_cp_reginfo);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const ARMCPRegInfo cortexa8_cp_reginfo[] = {
 | 
			
		||||
    { .name = "L2LOCKDOWN", .cp = 15, .crn = 9, .crm = 0, .opc1 = 1, .opc2 = 0,
 | 
			
		||||
      .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
 | 
			
		||||
@@ -1214,6 +1284,9 @@ static const ARMCPUInfo arm_cpus[] = {
 | 
			
		||||
    { .name = "arm11mpcore", .initfn = arm11mpcore_initfn },
 | 
			
		||||
    { .name = "cortex-m3",   .initfn = cortex_m3_initfn,
 | 
			
		||||
                             .class_init = arm_v7m_class_init },
 | 
			
		||||
    { .name = "cortex-m4",   .initfn = cortex_m4_initfn,
 | 
			
		||||
                             .class_init = arm_v7m_class_init },
 | 
			
		||||
    { .name = "cortex-r5",   .initfn = cortex_r5_initfn },
 | 
			
		||||
    { .name = "cortex-a8",   .initfn = cortex_a8_initfn },
 | 
			
		||||
    { .name = "cortex-a9",   .initfn = cortex_a9_initfn },
 | 
			
		||||
    { .name = "cortex-a15",  .initfn = cortex_a15_initfn },
 | 
			
		||||
 
 | 
			
		||||
@@ -284,6 +284,9 @@ typedef struct CPUARMState {
 | 
			
		||||
            };
 | 
			
		||||
            uint64_t par_el[4];
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        uint32_t c6_rgnr;
 | 
			
		||||
 | 
			
		||||
        uint32_t c9_insn; /* Cache lockdown registers.  */
 | 
			
		||||
        uint32_t c9_data;
 | 
			
		||||
        uint64_t c9_pmcr; /* performance monitor control register */
 | 
			
		||||
@@ -482,6 +485,13 @@ typedef struct CPUARMState {
 | 
			
		||||
    /* Internal CPU feature flags.  */
 | 
			
		||||
    uint64_t features;
 | 
			
		||||
 | 
			
		||||
    /* PMSAv7 MPU */
 | 
			
		||||
    struct {
 | 
			
		||||
        uint32_t *drbar;
 | 
			
		||||
        uint32_t *drsr;
 | 
			
		||||
        uint32_t *dracr;
 | 
			
		||||
    } pmsav7;
 | 
			
		||||
 | 
			
		||||
    void *nvic;
 | 
			
		||||
    const struct arm_boot_info *boot_info;
 | 
			
		||||
} CPUARMState;
 | 
			
		||||
@@ -550,6 +560,7 @@ void pmccntr_sync(CPUARMState *env);
 | 
			
		||||
#define SCTLR_DT      (1U << 16) /* up to ??, RAO in v6 and v7 */
 | 
			
		||||
#define SCTLR_nTWI    (1U << 16) /* v8 onward */
 | 
			
		||||
#define SCTLR_HA      (1U << 17)
 | 
			
		||||
#define SCTLR_BR      (1U << 17) /* PMSA only */
 | 
			
		||||
#define SCTLR_IT      (1U << 18) /* up to ??, RAO in v6 and v7 */
 | 
			
		||||
#define SCTLR_nTWE    (1U << 18) /* v8 onward */
 | 
			
		||||
#define SCTLR_WXN     (1U << 19)
 | 
			
		||||
@@ -1116,8 +1127,8 @@ static inline uint64_t cpreg_to_kvm_id(uint32_t cpregid)
 | 
			
		||||
 * old must have the OVERRIDE bit set.
 | 
			
		||||
 * ALIAS indicates that this register is an alias view of some underlying
 | 
			
		||||
 * state which is also visible via another register, and that the other
 | 
			
		||||
 * register is handling migration; registers marked ALIAS will not be migrated
 | 
			
		||||
 * but may have their state set by syncing of register state from KVM.
 | 
			
		||||
 * register is handling migration and reset; registers marked ALIAS will not be
 | 
			
		||||
 * migrated but may have their state set by syncing of register state from KVM.
 | 
			
		||||
 * NO_RAW indicates that this register has no underlying state and does not
 | 
			
		||||
 * support raw access for state saving/loading; it will not be used for either
 | 
			
		||||
 * migration or KVM state synchronization. (Typically this is for "registers"
 | 
			
		||||
 
 | 
			
		||||
@@ -10,6 +10,7 @@
 | 
			
		||||
#include "exec/cpu_ldst.h"
 | 
			
		||||
#include "arm_ldst.h"
 | 
			
		||||
#include <zlib.h> /* For crc32 */
 | 
			
		||||
#include "exec/semihost.h"
 | 
			
		||||
 | 
			
		||||
#ifndef CONFIG_USER_ONLY
 | 
			
		||||
static inline bool get_phys_addr(CPUARMState *env, target_ulong address,
 | 
			
		||||
@@ -984,7 +985,7 @@ static const ARMCPRegInfo v7_cp_reginfo[] = {
 | 
			
		||||
    { .name = "PMINTENCLR", .cp = 15, .crn = 9, .crm = 14, .opc1 = 0, .opc2 = 2,
 | 
			
		||||
      .access = PL1_RW, .type = ARM_CP_ALIAS,
 | 
			
		||||
      .fieldoffset = offsetof(CPUARMState, cp15.c9_pminten),
 | 
			
		||||
      .resetvalue = 0, .writefn = pmintenclr_write, },
 | 
			
		||||
      .writefn = pmintenclr_write, },
 | 
			
		||||
    { .name = "VBAR", .state = ARM_CP_STATE_BOTH,
 | 
			
		||||
      .opc0 = 3, .crn = 12, .crm = 0, .opc1 = 0, .opc2 = 0,
 | 
			
		||||
      .access = PL1_RW, .writefn = vbar_write,
 | 
			
		||||
@@ -1323,7 +1324,6 @@ static const ARMCPRegInfo generic_timer_cp_reginfo[] = {
 | 
			
		||||
      .type = ARM_CP_ALIAS,
 | 
			
		||||
      .access = PL1_RW | PL0_R, .accessfn = gt_cntfrq_access,
 | 
			
		||||
      .fieldoffset = offsetoflow32(CPUARMState, cp15.c14_cntfrq),
 | 
			
		||||
      .resetfn = arm_cp_reset_ignore,
 | 
			
		||||
    },
 | 
			
		||||
    { .name = "CNTFRQ_EL0", .state = ARM_CP_STATE_AA64,
 | 
			
		||||
      .opc0 = 3, .opc1 = 3, .crn = 14, .crm = 0, .opc2 = 0,
 | 
			
		||||
@@ -1344,7 +1344,6 @@ static const ARMCPRegInfo generic_timer_cp_reginfo[] = {
 | 
			
		||||
      .accessfn = gt_ptimer_access,
 | 
			
		||||
      .fieldoffset = offsetoflow32(CPUARMState,
 | 
			
		||||
                                   cp15.c14_timer[GTIMER_PHYS].ctl),
 | 
			
		||||
      .resetfn = arm_cp_reset_ignore,
 | 
			
		||||
      .writefn = gt_ctl_write, .raw_writefn = raw_write,
 | 
			
		||||
    },
 | 
			
		||||
    { .name = "CNTP_CTL_EL0", .state = ARM_CP_STATE_AA64,
 | 
			
		||||
@@ -1360,7 +1359,6 @@ static const ARMCPRegInfo generic_timer_cp_reginfo[] = {
 | 
			
		||||
      .accessfn = gt_vtimer_access,
 | 
			
		||||
      .fieldoffset = offsetoflow32(CPUARMState,
 | 
			
		||||
                                   cp15.c14_timer[GTIMER_VIRT].ctl),
 | 
			
		||||
      .resetfn = arm_cp_reset_ignore,
 | 
			
		||||
      .writefn = gt_ctl_write, .raw_writefn = raw_write,
 | 
			
		||||
    },
 | 
			
		||||
    { .name = "CNTV_CTL_EL0", .state = ARM_CP_STATE_AA64,
 | 
			
		||||
@@ -1422,7 +1420,7 @@ static const ARMCPRegInfo generic_timer_cp_reginfo[] = {
 | 
			
		||||
      .access = PL1_RW | PL0_R,
 | 
			
		||||
      .type = ARM_CP_64BIT | ARM_CP_IO | ARM_CP_ALIAS,
 | 
			
		||||
      .fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_PHYS].cval),
 | 
			
		||||
      .accessfn = gt_ptimer_access, .resetfn = arm_cp_reset_ignore,
 | 
			
		||||
      .accessfn = gt_ptimer_access,
 | 
			
		||||
      .writefn = gt_cval_write, .raw_writefn = raw_write,
 | 
			
		||||
    },
 | 
			
		||||
    { .name = "CNTP_CVAL_EL0", .state = ARM_CP_STATE_AA64,
 | 
			
		||||
@@ -1437,7 +1435,7 @@ static const ARMCPRegInfo generic_timer_cp_reginfo[] = {
 | 
			
		||||
      .access = PL1_RW | PL0_R,
 | 
			
		||||
      .type = ARM_CP_64BIT | ARM_CP_IO | ARM_CP_ALIAS,
 | 
			
		||||
      .fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_VIRT].cval),
 | 
			
		||||
      .accessfn = gt_vtimer_access, .resetfn = arm_cp_reset_ignore,
 | 
			
		||||
      .accessfn = gt_vtimer_access,
 | 
			
		||||
      .writefn = gt_cval_write, .raw_writefn = raw_write,
 | 
			
		||||
    },
 | 
			
		||||
    { .name = "CNTV_CVAL_EL0", .state = ARM_CP_STATE_AA64,
 | 
			
		||||
@@ -1710,16 +1708,89 @@ static uint64_t pmsav5_insn_ap_read(CPUARMState *env, const ARMCPRegInfo *ri)
 | 
			
		||||
    return simple_mpu_ap_bits(env->cp15.pmsav5_insn_ap);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static uint64_t pmsav7_read(CPUARMState *env, const ARMCPRegInfo *ri)
 | 
			
		||||
{
 | 
			
		||||
    uint32_t *u32p = *(uint32_t **)raw_ptr(env, ri);
 | 
			
		||||
 | 
			
		||||
    if (!u32p) {
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    u32p += env->cp15.c6_rgnr;
 | 
			
		||||
    return *u32p;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void pmsav7_write(CPUARMState *env, const ARMCPRegInfo *ri,
 | 
			
		||||
                         uint64_t value)
 | 
			
		||||
{
 | 
			
		||||
    ARMCPU *cpu = arm_env_get_cpu(env);
 | 
			
		||||
    uint32_t *u32p = *(uint32_t **)raw_ptr(env, ri);
 | 
			
		||||
 | 
			
		||||
    if (!u32p) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    u32p += env->cp15.c6_rgnr;
 | 
			
		||||
    tlb_flush(CPU(cpu), 1); /* Mappings may have changed - purge! */
 | 
			
		||||
    *u32p = value;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void pmsav7_reset(CPUARMState *env, const ARMCPRegInfo *ri)
 | 
			
		||||
{
 | 
			
		||||
    ARMCPU *cpu = arm_env_get_cpu(env);
 | 
			
		||||
    uint32_t *u32p = *(uint32_t **)raw_ptr(env, ri);
 | 
			
		||||
 | 
			
		||||
    if (!u32p) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    memset(u32p, 0, sizeof(*u32p) * cpu->pmsav7_dregion);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void pmsav7_rgnr_write(CPUARMState *env, const ARMCPRegInfo *ri,
 | 
			
		||||
                              uint64_t value)
 | 
			
		||||
{
 | 
			
		||||
    ARMCPU *cpu = arm_env_get_cpu(env);
 | 
			
		||||
    uint32_t nrgs = cpu->pmsav7_dregion;
 | 
			
		||||
 | 
			
		||||
    if (value >= nrgs) {
 | 
			
		||||
        qemu_log_mask(LOG_GUEST_ERROR,
 | 
			
		||||
                      "PMSAv7 RGNR write >= # supported regions, %" PRIu32
 | 
			
		||||
                      " > %" PRIu32 "\n", (uint32_t)value, nrgs);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    raw_write(env, ri, value);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const ARMCPRegInfo pmsav7_cp_reginfo[] = {
 | 
			
		||||
    { .name = "DRBAR", .cp = 15, .crn = 6, .opc1 = 0, .crm = 1, .opc2 = 0,
 | 
			
		||||
      .access = PL1_RW, .type = ARM_CP_NO_RAW,
 | 
			
		||||
      .fieldoffset = offsetof(CPUARMState, pmsav7.drbar),
 | 
			
		||||
      .readfn = pmsav7_read, .writefn = pmsav7_write, .resetfn = pmsav7_reset },
 | 
			
		||||
    { .name = "DRSR", .cp = 15, .crn = 6, .opc1 = 0, .crm = 1, .opc2 = 2,
 | 
			
		||||
      .access = PL1_RW, .type = ARM_CP_NO_RAW,
 | 
			
		||||
      .fieldoffset = offsetof(CPUARMState, pmsav7.drsr),
 | 
			
		||||
      .readfn = pmsav7_read, .writefn = pmsav7_write, .resetfn = pmsav7_reset },
 | 
			
		||||
    { .name = "DRACR", .cp = 15, .crn = 6, .opc1 = 0, .crm = 1, .opc2 = 4,
 | 
			
		||||
      .access = PL1_RW, .type = ARM_CP_NO_RAW,
 | 
			
		||||
      .fieldoffset = offsetof(CPUARMState, pmsav7.dracr),
 | 
			
		||||
      .readfn = pmsav7_read, .writefn = pmsav7_write, .resetfn = pmsav7_reset },
 | 
			
		||||
    { .name = "RGNR", .cp = 15, .crn = 6, .opc1 = 0, .crm = 2, .opc2 = 0,
 | 
			
		||||
      .access = PL1_RW,
 | 
			
		||||
      .fieldoffset = offsetof(CPUARMState, cp15.c6_rgnr),
 | 
			
		||||
      .writefn = pmsav7_rgnr_write },
 | 
			
		||||
    REGINFO_SENTINEL
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static const ARMCPRegInfo pmsav5_cp_reginfo[] = {
 | 
			
		||||
    { .name = "DATA_AP", .cp = 15, .crn = 5, .crm = 0, .opc1 = 0, .opc2 = 0,
 | 
			
		||||
      .access = PL1_RW, .type = ARM_CP_ALIAS,
 | 
			
		||||
      .fieldoffset = offsetof(CPUARMState, cp15.pmsav5_data_ap),
 | 
			
		||||
      .resetvalue = 0,
 | 
			
		||||
      .readfn = pmsav5_data_ap_read, .writefn = pmsav5_data_ap_write, },
 | 
			
		||||
    { .name = "INSN_AP", .cp = 15, .crn = 5, .crm = 0, .opc1 = 0, .opc2 = 1,
 | 
			
		||||
      .access = PL1_RW, .type = ARM_CP_ALIAS,
 | 
			
		||||
      .fieldoffset = offsetof(CPUARMState, cp15.pmsav5_insn_ap),
 | 
			
		||||
      .resetvalue = 0,
 | 
			
		||||
      .readfn = pmsav5_insn_ap_read, .writefn = pmsav5_insn_ap_write, },
 | 
			
		||||
    { .name = "DATA_EXT_AP", .cp = 15, .crn = 5, .crm = 0, .opc1 = 0, .opc2 = 2,
 | 
			
		||||
      .access = PL1_RW,
 | 
			
		||||
@@ -1851,8 +1922,7 @@ static const ARMCPRegInfo vmsa_pmsa_cp_reginfo[] = {
 | 
			
		||||
    { .name = "DFSR", .cp = 15, .crn = 5, .crm = 0, .opc1 = 0, .opc2 = 0,
 | 
			
		||||
      .access = PL1_RW, .type = ARM_CP_ALIAS,
 | 
			
		||||
      .bank_fieldoffsets = { offsetoflow32(CPUARMState, cp15.dfsr_s),
 | 
			
		||||
                             offsetoflow32(CPUARMState, cp15.dfsr_ns) },
 | 
			
		||||
      .resetfn = arm_cp_reset_ignore, },
 | 
			
		||||
                             offsetoflow32(CPUARMState, cp15.dfsr_ns) }, },
 | 
			
		||||
    { .name = "IFSR", .cp = 15, .crn = 5, .crm = 0, .opc1 = 0, .opc2 = 1,
 | 
			
		||||
      .access = PL1_RW, .resetvalue = 0,
 | 
			
		||||
      .bank_fieldoffsets = { offsetoflow32(CPUARMState, cp15.ifsr_s),
 | 
			
		||||
@@ -1890,7 +1960,7 @@ static const ARMCPRegInfo vmsa_cp_reginfo[] = {
 | 
			
		||||
      .fieldoffset = offsetof(CPUARMState, cp15.tcr_el[1]) },
 | 
			
		||||
    { .name = "TTBCR", .cp = 15, .crn = 2, .crm = 0, .opc1 = 0, .opc2 = 2,
 | 
			
		||||
      .access = PL1_RW, .type = ARM_CP_ALIAS, .writefn = vmsa_ttbcr_write,
 | 
			
		||||
      .resetfn = arm_cp_reset_ignore, .raw_writefn = vmsa_ttbcr_raw_write,
 | 
			
		||||
      .raw_writefn = vmsa_ttbcr_raw_write,
 | 
			
		||||
      .bank_fieldoffsets = { offsetoflow32(CPUARMState, cp15.tcr_el[3]),
 | 
			
		||||
                             offsetoflow32(CPUARMState, cp15.tcr_el[1])} },
 | 
			
		||||
    REGINFO_SENTINEL
 | 
			
		||||
@@ -2109,12 +2179,12 @@ static const ARMCPRegInfo lpae_cp_reginfo[] = {
 | 
			
		||||
      .access = PL1_RW, .type = ARM_CP_64BIT | ARM_CP_ALIAS,
 | 
			
		||||
      .bank_fieldoffsets = { offsetof(CPUARMState, cp15.ttbr0_s),
 | 
			
		||||
                             offsetof(CPUARMState, cp15.ttbr0_ns) },
 | 
			
		||||
      .writefn = vmsa_ttbr_write, .resetfn = arm_cp_reset_ignore },
 | 
			
		||||
      .writefn = vmsa_ttbr_write, },
 | 
			
		||||
    { .name = "TTBR1", .cp = 15, .crm = 2, .opc1 = 1,
 | 
			
		||||
      .access = PL1_RW, .type = ARM_CP_64BIT | ARM_CP_ALIAS,
 | 
			
		||||
      .bank_fieldoffsets = { offsetof(CPUARMState, cp15.ttbr1_s),
 | 
			
		||||
                             offsetof(CPUARMState, cp15.ttbr1_ns) },
 | 
			
		||||
      .writefn = vmsa_ttbr_write, .resetfn = arm_cp_reset_ignore },
 | 
			
		||||
      .writefn = vmsa_ttbr_write, },
 | 
			
		||||
    REGINFO_SENTINEL
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@@ -2641,7 +2711,6 @@ static const ARMCPRegInfo el2_cp_reginfo[] = {
 | 
			
		||||
      .fieldoffset = offsetof(CPUARMState, cp15.ttbr0_el[2]) },
 | 
			
		||||
    { .name = "HTTBR", .cp = 15, .opc1 = 4, .crm = 2,
 | 
			
		||||
      .access = PL2_RW, .type = ARM_CP_64BIT | ARM_CP_ALIAS,
 | 
			
		||||
      .resetvalue = 0,
 | 
			
		||||
      .fieldoffset = offsetof(CPUARMState, cp15.ttbr0_el[2]) },
 | 
			
		||||
    { .name = "TLBI_ALLE2", .state = ARM_CP_STATE_AA64,
 | 
			
		||||
      .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 7, .opc2 = 0,
 | 
			
		||||
@@ -2666,7 +2735,7 @@ static const ARMCPRegInfo el3_cp_reginfo[] = {
 | 
			
		||||
    { .name = "SCR",  .type = ARM_CP_ALIAS,
 | 
			
		||||
      .cp = 15, .opc1 = 0, .crn = 1, .crm = 1, .opc2 = 0,
 | 
			
		||||
      .access = PL3_RW, .fieldoffset = offsetoflow32(CPUARMState, cp15.scr_el3),
 | 
			
		||||
      .resetfn = arm_cp_reset_ignore, .writefn = scr_write },
 | 
			
		||||
      .writefn = scr_write },
 | 
			
		||||
    { .name = "SDER32_EL3", .state = ARM_CP_STATE_AA64,
 | 
			
		||||
      .opc0 = 3, .opc1 = 6, .crn = 1, .crm = 1, .opc2 = 1,
 | 
			
		||||
      .access = PL3_RW, .resetvalue = 0,
 | 
			
		||||
@@ -2761,8 +2830,7 @@ static const ARMCPRegInfo debug_cp_reginfo[] = {
 | 
			
		||||
      .cp = 14, .opc0 = 2, .opc1 = 0, .crn = 0, .crm = 1, .opc2 = 0,
 | 
			
		||||
      .type = ARM_CP_ALIAS,
 | 
			
		||||
      .access = PL1_R,
 | 
			
		||||
      .fieldoffset = offsetof(CPUARMState, cp15.mdscr_el1),
 | 
			
		||||
      .resetfn = arm_cp_reset_ignore },
 | 
			
		||||
      .fieldoffset = offsetof(CPUARMState, cp15.mdscr_el1), },
 | 
			
		||||
    /* We define a dummy WI OSLAR_EL1, because Linux writes to it. */
 | 
			
		||||
    { .name = "OSLAR_EL1", .state = ARM_CP_STATE_BOTH,
 | 
			
		||||
      .cp = 14, .opc0 = 2, .opc1 = 0, .crn = 1, .crm = 0, .opc2 = 4,
 | 
			
		||||
@@ -3345,13 +3413,14 @@ void register_cp_regs_for_features(ARMCPU *cpu)
 | 
			
		||||
        define_one_arm_cp_reg(cpu, &rvbar);
 | 
			
		||||
    }
 | 
			
		||||
    if (arm_feature(env, ARM_FEATURE_MPU)) {
 | 
			
		||||
        /* These are the MPU registers prior to PMSAv6. Any new
 | 
			
		||||
         * PMSA core later than the ARM946 will require that we
 | 
			
		||||
         * implement the PMSAv6 or PMSAv7 registers, which are
 | 
			
		||||
         * completely different.
 | 
			
		||||
         */
 | 
			
		||||
        assert(!arm_feature(env, ARM_FEATURE_V6));
 | 
			
		||||
        define_arm_cp_regs(cpu, pmsav5_cp_reginfo);
 | 
			
		||||
        if (arm_feature(env, ARM_FEATURE_V6)) {
 | 
			
		||||
            /* PMSAv6 not implemented */
 | 
			
		||||
            assert(arm_feature(env, ARM_FEATURE_V7));
 | 
			
		||||
            define_arm_cp_regs(cpu, vmsa_pmsa_cp_reginfo);
 | 
			
		||||
            define_arm_cp_regs(cpu, pmsav7_cp_reginfo);
 | 
			
		||||
        } else {
 | 
			
		||||
            define_arm_cp_regs(cpu, pmsav5_cp_reginfo);
 | 
			
		||||
        }
 | 
			
		||||
    } else {
 | 
			
		||||
        define_arm_cp_regs(cpu, vmsa_pmsa_cp_reginfo);
 | 
			
		||||
        define_arm_cp_regs(cpu, vmsa_cp_reginfo);
 | 
			
		||||
@@ -3465,6 +3534,13 @@ void register_cp_regs_for_features(ARMCPU *cpu)
 | 
			
		||||
              .cp = 15, .crn = 0, .crm = 0, .opc1 = 0, .opc2 = 3,
 | 
			
		||||
              .access = PL1_R, .type = ARM_CP_CONST, .resetvalue = 0,
 | 
			
		||||
        };
 | 
			
		||||
        /* MPUIR is specific to PMSA V6+ */
 | 
			
		||||
        ARMCPRegInfo id_mpuir_reginfo = {
 | 
			
		||||
              .name = "MPUIR",
 | 
			
		||||
              .cp = 15, .crn = 0, .crm = 0, .opc1 = 0, .opc2 = 4,
 | 
			
		||||
              .access = PL1_R, .type = ARM_CP_CONST,
 | 
			
		||||
              .resetvalue = cpu->pmsav7_dregion << 8
 | 
			
		||||
        };
 | 
			
		||||
        ARMCPRegInfo crn0_wi_reginfo = {
 | 
			
		||||
            .name = "CRN0_WI", .cp = 15, .crn = 0, .crm = CP_ANY,
 | 
			
		||||
            .opc1 = CP_ANY, .opc2 = CP_ANY, .access = PL1_W,
 | 
			
		||||
@@ -3487,6 +3563,7 @@ void register_cp_regs_for_features(ARMCPU *cpu)
 | 
			
		||||
                r->access = PL1_RW;
 | 
			
		||||
            }
 | 
			
		||||
            id_tlbtr_reginfo.access = PL1_RW;
 | 
			
		||||
            id_tlbtr_reginfo.access = PL1_RW;
 | 
			
		||||
        }
 | 
			
		||||
        if (arm_feature(env, ARM_FEATURE_V8)) {
 | 
			
		||||
            define_arm_cp_regs(cpu, id_v8_midr_cp_reginfo);
 | 
			
		||||
@@ -3496,6 +3573,8 @@ void register_cp_regs_for_features(ARMCPU *cpu)
 | 
			
		||||
        define_arm_cp_regs(cpu, id_cp_reginfo);
 | 
			
		||||
        if (!arm_feature(env, ARM_FEATURE_MPU)) {
 | 
			
		||||
            define_one_arm_cp_reg(cpu, &id_tlbtr_reginfo);
 | 
			
		||||
        } else if (arm_feature(env, ARM_FEATURE_V7)) {
 | 
			
		||||
            define_one_arm_cp_reg(cpu, &id_mpuir_reginfo);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -3721,14 +3800,12 @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
 | 
			
		||||
            if ((r->state == ARM_CP_STATE_BOTH && ns) ||
 | 
			
		||||
                (arm_feature(&cpu->env, ARM_FEATURE_V8) && !ns)) {
 | 
			
		||||
                r2->type |= ARM_CP_ALIAS;
 | 
			
		||||
                r2->resetfn = arm_cp_reset_ignore;
 | 
			
		||||
            }
 | 
			
		||||
        } else if ((secstate != r->secure) && !ns) {
 | 
			
		||||
            /* The register is not banked so we only want to allow migration of
 | 
			
		||||
             * the non-secure instance.
 | 
			
		||||
             */
 | 
			
		||||
            r2->type |= ARM_CP_ALIAS;
 | 
			
		||||
            r2->resetfn = arm_cp_reset_ignore;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (r->state == ARM_CP_STATE_BOTH) {
 | 
			
		||||
@@ -4478,7 +4555,7 @@ void arm_v7m_cpu_do_interrupt(CPUState *cs)
 | 
			
		||||
        armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_MEM);
 | 
			
		||||
        return;
 | 
			
		||||
    case EXCP_BKPT:
 | 
			
		||||
        if (semihosting_enabled) {
 | 
			
		||||
        if (semihosting_enabled()) {
 | 
			
		||||
            int nr;
 | 
			
		||||
            nr = arm_lduw_code(env, env->regs[15], env->bswap_code) & 0xff;
 | 
			
		||||
            if (nr == 0xab) {
 | 
			
		||||
@@ -4790,7 +4867,7 @@ void arm_cpu_do_interrupt(CPUState *cs)
 | 
			
		||||
            offset = 4;
 | 
			
		||||
        break;
 | 
			
		||||
    case EXCP_SWI:
 | 
			
		||||
        if (semihosting_enabled) {
 | 
			
		||||
        if (semihosting_enabled()) {
 | 
			
		||||
            /* Check for semihosting interrupt.  */
 | 
			
		||||
            if (env->thumb) {
 | 
			
		||||
                mask = arm_lduw_code(env, env->regs[15] - 2, env->bswap_code)
 | 
			
		||||
@@ -4817,7 +4894,7 @@ void arm_cpu_do_interrupt(CPUState *cs)
 | 
			
		||||
        break;
 | 
			
		||||
    case EXCP_BKPT:
 | 
			
		||||
        /* See if this is a semihosting syscall.  */
 | 
			
		||||
        if (env->thumb && semihosting_enabled) {
 | 
			
		||||
        if (env->thumb && semihosting_enabled()) {
 | 
			
		||||
            mask = arm_lduw_code(env, env->regs[15], env->bswap_code) & 0xff;
 | 
			
		||||
            if (mask == 0xab
 | 
			
		||||
                  && (env->uncached_cpsr & CPSR_M) != ARM_CPU_MODE_USR) {
 | 
			
		||||
@@ -5759,6 +5836,167 @@ do_fault:
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void get_phys_addr_pmsav7_default(CPUARMState *env,
 | 
			
		||||
                                                ARMMMUIdx mmu_idx,
 | 
			
		||||
                                                int32_t address, int *prot)
 | 
			
		||||
{
 | 
			
		||||
    *prot = PAGE_READ | PAGE_WRITE;
 | 
			
		||||
    switch (address) {
 | 
			
		||||
    case 0xF0000000 ... 0xFFFFFFFF:
 | 
			
		||||
        if (regime_sctlr(env, mmu_idx) & SCTLR_V) { /* hivecs execing is ok */
 | 
			
		||||
            *prot |= PAGE_EXEC;
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
    case 0x00000000 ... 0x7FFFFFFF:
 | 
			
		||||
        *prot |= PAGE_EXEC;
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static bool get_phys_addr_pmsav7(CPUARMState *env, uint32_t address,
 | 
			
		||||
                                 int access_type, ARMMMUIdx mmu_idx,
 | 
			
		||||
                                 hwaddr *phys_ptr, int *prot, uint32_t *fsr)
 | 
			
		||||
{
 | 
			
		||||
    ARMCPU *cpu = arm_env_get_cpu(env);
 | 
			
		||||
    int n;
 | 
			
		||||
    bool is_user = regime_is_user(env, mmu_idx);
 | 
			
		||||
 | 
			
		||||
    *phys_ptr = address;
 | 
			
		||||
    *prot = 0;
 | 
			
		||||
 | 
			
		||||
    if (regime_translation_disabled(env, mmu_idx)) { /* MPU disabled */
 | 
			
		||||
        get_phys_addr_pmsav7_default(env, mmu_idx, address, prot);
 | 
			
		||||
    } else { /* MPU enabled */
 | 
			
		||||
        for (n = (int)cpu->pmsav7_dregion - 1; n >= 0; n--) {
 | 
			
		||||
            /* region search */
 | 
			
		||||
            uint32_t base = env->pmsav7.drbar[n];
 | 
			
		||||
            uint32_t rsize = extract32(env->pmsav7.drsr[n], 1, 5);
 | 
			
		||||
            uint32_t rmask;
 | 
			
		||||
            bool srdis = false;
 | 
			
		||||
 | 
			
		||||
            if (!(env->pmsav7.drsr[n] & 0x1)) {
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (!rsize) {
 | 
			
		||||
                qemu_log_mask(LOG_GUEST_ERROR, "DRSR.Rsize field can not be 0");
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
            rsize++;
 | 
			
		||||
            rmask = (1ull << rsize) - 1;
 | 
			
		||||
 | 
			
		||||
            if (base & rmask) {
 | 
			
		||||
                qemu_log_mask(LOG_GUEST_ERROR, "DRBAR %" PRIx32 " misaligned "
 | 
			
		||||
                              "to DRSR region size, mask = %" PRIx32,
 | 
			
		||||
                              base, rmask);
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (address < base || address > base + rmask) {
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            /* Region matched */
 | 
			
		||||
 | 
			
		||||
            if (rsize >= 8) { /* no subregions for regions < 256 bytes */
 | 
			
		||||
                int i, snd;
 | 
			
		||||
                uint32_t srdis_mask;
 | 
			
		||||
 | 
			
		||||
                rsize -= 3; /* sub region size (power of 2) */
 | 
			
		||||
                snd = ((address - base) >> rsize) & 0x7;
 | 
			
		||||
                srdis = extract32(env->pmsav7.drsr[n], snd + 8, 1);
 | 
			
		||||
 | 
			
		||||
                srdis_mask = srdis ? 0x3 : 0x0;
 | 
			
		||||
                for (i = 2; i <= 8 && rsize < TARGET_PAGE_BITS; i *= 2) {
 | 
			
		||||
                    /* This will check in groups of 2, 4 and then 8, whether
 | 
			
		||||
                     * the subregion bits are consistent. rsize is incremented
 | 
			
		||||
                     * back up to give the region size, considering consistent
 | 
			
		||||
                     * adjacent subregions as one region. Stop testing if rsize
 | 
			
		||||
                     * is already big enough for an entire QEMU page.
 | 
			
		||||
                     */
 | 
			
		||||
                    int snd_rounded = snd & ~(i - 1);
 | 
			
		||||
                    uint32_t srdis_multi = extract32(env->pmsav7.drsr[n],
 | 
			
		||||
                                                     snd_rounded + 8, i);
 | 
			
		||||
                    if (srdis_mask ^ srdis_multi) {
 | 
			
		||||
                        break;
 | 
			
		||||
                    }
 | 
			
		||||
                    srdis_mask = (srdis_mask << i) | srdis_mask;
 | 
			
		||||
                    rsize++;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            if (rsize < TARGET_PAGE_BITS) {
 | 
			
		||||
                qemu_log_mask(LOG_UNIMP, "No support for MPU (sub)region"
 | 
			
		||||
                              "alignment of %" PRIu32 " bits. Minimum is %d\n",
 | 
			
		||||
                              rsize, TARGET_PAGE_BITS);
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
            if (srdis) {
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (n == -1) { /* no hits */
 | 
			
		||||
            if (cpu->pmsav7_dregion &&
 | 
			
		||||
                (is_user || !(regime_sctlr(env, mmu_idx) & SCTLR_BR))) {
 | 
			
		||||
                /* background fault */
 | 
			
		||||
                *fsr = 0;
 | 
			
		||||
                return true;
 | 
			
		||||
            }
 | 
			
		||||
            get_phys_addr_pmsav7_default(env, mmu_idx, address, prot);
 | 
			
		||||
        } else { /* a MPU hit! */
 | 
			
		||||
            uint32_t ap = extract32(env->pmsav7.dracr[n], 8, 3);
 | 
			
		||||
 | 
			
		||||
            if (is_user) { /* User mode AP bit decoding */
 | 
			
		||||
                switch (ap) {
 | 
			
		||||
                case 0:
 | 
			
		||||
                case 1:
 | 
			
		||||
                case 5:
 | 
			
		||||
                    break; /* no access */
 | 
			
		||||
                case 3:
 | 
			
		||||
                    *prot |= PAGE_WRITE;
 | 
			
		||||
                    /* fall through */
 | 
			
		||||
                case 2:
 | 
			
		||||
                case 6:
 | 
			
		||||
                    *prot |= PAGE_READ | PAGE_EXEC;
 | 
			
		||||
                    break;
 | 
			
		||||
                default:
 | 
			
		||||
                    qemu_log_mask(LOG_GUEST_ERROR,
 | 
			
		||||
                                  "Bad value for AP bits in DRACR %"
 | 
			
		||||
                                  PRIx32 "\n", ap);
 | 
			
		||||
                }
 | 
			
		||||
            } else { /* Priv. mode AP bits decoding */
 | 
			
		||||
                switch (ap) {
 | 
			
		||||
                case 0:
 | 
			
		||||
                    break; /* no access */
 | 
			
		||||
                case 1:
 | 
			
		||||
                case 2:
 | 
			
		||||
                case 3:
 | 
			
		||||
                    *prot |= PAGE_WRITE;
 | 
			
		||||
                    /* fall through */
 | 
			
		||||
                case 5:
 | 
			
		||||
                case 6:
 | 
			
		||||
                    *prot |= PAGE_READ | PAGE_EXEC;
 | 
			
		||||
                    break;
 | 
			
		||||
                default:
 | 
			
		||||
                    qemu_log_mask(LOG_GUEST_ERROR,
 | 
			
		||||
                                  "Bad value for AP bits in DRACR %"
 | 
			
		||||
                                  PRIx32 "\n", ap);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            /* execute never */
 | 
			
		||||
            if (env->pmsav7.dracr[n] & (1 << 12)) {
 | 
			
		||||
                *prot &= ~PAGE_EXEC;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    *fsr = 0x00d; /* Permission fault */
 | 
			
		||||
    return !(*prot & (1 << access_type));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static bool get_phys_addr_pmsav5(CPUARMState *env, uint32_t address,
 | 
			
		||||
                                 int access_type, ARMMMUIdx mmu_idx,
 | 
			
		||||
                                 hwaddr *phys_ptr, int *prot, uint32_t *fsr)
 | 
			
		||||
@@ -5844,7 +6082,7 @@ static bool get_phys_addr_pmsav5(CPUARMState *env, uint32_t address,
 | 
			
		||||
 * DFSR/IFSR fault register, with the following caveats:
 | 
			
		||||
 *  * we honour the short vs long DFSR format differences.
 | 
			
		||||
 *  * the WnR bit is never set (the caller must do this).
 | 
			
		||||
 *  * for MPU based systems we don't bother to return a full FSR format
 | 
			
		||||
 *  * for PSMAv5 based systems we don't bother to return a full FSR format
 | 
			
		||||
 *    value.
 | 
			
		||||
 *
 | 
			
		||||
 * @env: CPUARMState
 | 
			
		||||
@@ -5892,6 +6130,16 @@ static inline bool get_phys_addr(CPUARMState *env, target_ulong address,
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* pmsav7 has special handling for when MPU is disabled so call it before
 | 
			
		||||
     * the common MMU/MPU disabled check below.
 | 
			
		||||
     */
 | 
			
		||||
    if (arm_feature(env, ARM_FEATURE_MPU) &&
 | 
			
		||||
        arm_feature(env, ARM_FEATURE_V7)) {
 | 
			
		||||
        *page_size = TARGET_PAGE_SIZE;
 | 
			
		||||
        return get_phys_addr_pmsav7(env, address, access_type, mmu_idx,
 | 
			
		||||
                                    phys_ptr, prot, fsr);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (regime_translation_disabled(env, mmu_idx)) {
 | 
			
		||||
        /* MMU/MPU disabled.  */
 | 
			
		||||
        *phys_ptr = address;
 | 
			
		||||
@@ -5901,6 +6149,7 @@ static inline bool get_phys_addr(CPUARMState *env, target_ulong address,
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (arm_feature(env, ARM_FEATURE_MPU)) {
 | 
			
		||||
        /* Pre-v7 MPU */
 | 
			
		||||
        *page_size = TARGET_PAGE_SIZE;
 | 
			
		||||
        return get_phys_addr_pmsav5(env, address, access_type, mmu_idx,
 | 
			
		||||
                                    phys_ptr, prot, fsr);
 | 
			
		||||
 
 | 
			
		||||
@@ -125,6 +125,39 @@ static const VMStateDescription vmstate_thumb2ee = {
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static bool pmsav7_needed(void *opaque)
 | 
			
		||||
{
 | 
			
		||||
    ARMCPU *cpu = opaque;
 | 
			
		||||
    CPUARMState *env = &cpu->env;
 | 
			
		||||
 | 
			
		||||
    return arm_feature(env, ARM_FEATURE_MPU) &&
 | 
			
		||||
           arm_feature(env, ARM_FEATURE_V7);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static bool pmsav7_rgnr_vmstate_validate(void *opaque, int version_id)
 | 
			
		||||
{
 | 
			
		||||
    ARMCPU *cpu = opaque;
 | 
			
		||||
 | 
			
		||||
    return cpu->env.cp15.c6_rgnr < cpu->pmsav7_dregion;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const VMStateDescription vmstate_pmsav7 = {
 | 
			
		||||
    .name = "cpu/pmsav7",
 | 
			
		||||
    .version_id = 1,
 | 
			
		||||
    .minimum_version_id = 1,
 | 
			
		||||
    .needed = pmsav7_needed,
 | 
			
		||||
    .fields = (VMStateField[]) {
 | 
			
		||||
        VMSTATE_VARRAY_UINT32(env.pmsav7.drbar, ARMCPU, pmsav7_dregion, 0,
 | 
			
		||||
                              vmstate_info_uint32, uint32_t),
 | 
			
		||||
        VMSTATE_VARRAY_UINT32(env.pmsav7.drsr, ARMCPU, pmsav7_dregion, 0,
 | 
			
		||||
                              vmstate_info_uint32, uint32_t),
 | 
			
		||||
        VMSTATE_VARRAY_UINT32(env.pmsav7.dracr, ARMCPU, pmsav7_dregion, 0,
 | 
			
		||||
                              vmstate_info_uint32, uint32_t),
 | 
			
		||||
        VMSTATE_VALIDATE("rgnr is valid", pmsav7_rgnr_vmstate_validate),
 | 
			
		||||
        VMSTATE_END_OF_LIST()
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static int get_cpsr(QEMUFile *f, void *opaque, size_t size)
 | 
			
		||||
{
 | 
			
		||||
    ARMCPU *cpu = opaque;
 | 
			
		||||
@@ -291,6 +324,7 @@ const VMStateDescription vmstate_arm_cpu = {
 | 
			
		||||
        &vmstate_iwmmxt,
 | 
			
		||||
        &vmstate_m,
 | 
			
		||||
        &vmstate_thumb2ee,
 | 
			
		||||
        &vmstate_pmsav7,
 | 
			
		||||
        NULL
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
@@ -20,6 +20,7 @@
 | 
			
		||||
#include "cpu.h"
 | 
			
		||||
#include "qemu/host-utils.h"
 | 
			
		||||
#include "sysemu/sysemu.h"
 | 
			
		||||
#include "exec/semihost.h"
 | 
			
		||||
 | 
			
		||||
int lm32_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int rw,
 | 
			
		||||
                              int mmu_idx)
 | 
			
		||||
@@ -162,7 +163,7 @@ void lm32_cpu_do_interrupt(CPUState *cs)
 | 
			
		||||
 | 
			
		||||
    switch (cs->exception_index) {
 | 
			
		||||
    case EXCP_SYSTEMCALL:
 | 
			
		||||
        if (unlikely(semihosting_enabled)) {
 | 
			
		||||
        if (unlikely(semihosting_enabled())) {
 | 
			
		||||
            /* do_semicall() returns true if call was handled. Otherwise
 | 
			
		||||
             * do the normal exception handling. */
 | 
			
		||||
            if (lm32_cpu_do_semihosting(cs)) {
 | 
			
		||||
 
 | 
			
		||||
@@ -19,6 +19,7 @@
 | 
			
		||||
#include "cpu.h"
 | 
			
		||||
#include "exec/helper-proto.h"
 | 
			
		||||
#include "exec/cpu_ldst.h"
 | 
			
		||||
#include "exec/semihost.h"
 | 
			
		||||
 | 
			
		||||
#if defined(CONFIG_USER_ONLY)
 | 
			
		||||
 | 
			
		||||
@@ -33,8 +34,6 @@ static inline void do_interrupt_m68k_hardirq(CPUM68KState *env)
 | 
			
		||||
 | 
			
		||||
#else
 | 
			
		||||
 | 
			
		||||
extern int semihosting_enabled;
 | 
			
		||||
 | 
			
		||||
/* Try to fill the TLB and return an exception if error. If retaddr is
 | 
			
		||||
   NULL, it means that the function was called in C code (i.e. not
 | 
			
		||||
   from generated code or from helper.c) */
 | 
			
		||||
@@ -63,8 +62,8 @@ static void do_rte(CPUM68KState *env)
 | 
			
		||||
    env->pc = cpu_ldl_kernel(env, sp + 4);
 | 
			
		||||
    sp |= (fmt >> 28) & 3;
 | 
			
		||||
    env->sr = fmt & 0xffff;
 | 
			
		||||
    m68k_switch_sp(env);
 | 
			
		||||
    env->aregs[7] = sp + 8;
 | 
			
		||||
    m68k_switch_sp(env);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void do_interrupt_all(CPUM68KState *env, int is_hw)
 | 
			
		||||
@@ -85,7 +84,7 @@ static void do_interrupt_all(CPUM68KState *env, int is_hw)
 | 
			
		||||
            do_rte(env);
 | 
			
		||||
            return;
 | 
			
		||||
        case EXCP_HALT_INSN:
 | 
			
		||||
            if (semihosting_enabled
 | 
			
		||||
            if (semihosting_enabled()
 | 
			
		||||
                    && (env->sr & SR_S) != 0
 | 
			
		||||
                    && (env->pc & 3) == 0
 | 
			
		||||
                    && cpu_lduw_code(env, env->pc - 4) == 0x4e71
 | 
			
		||||
@@ -108,10 +107,7 @@ static void do_interrupt_all(CPUM68KState *env, int is_hw)
 | 
			
		||||
 | 
			
		||||
    vector = cs->exception_index << 2;
 | 
			
		||||
 | 
			
		||||
    sp = env->aregs[7];
 | 
			
		||||
 | 
			
		||||
    fmt |= 0x40000000;
 | 
			
		||||
    fmt |= (sp & 3) << 28;
 | 
			
		||||
    fmt |= vector << 16;
 | 
			
		||||
    fmt |= env->sr;
 | 
			
		||||
 | 
			
		||||
@@ -121,6 +117,8 @@ static void do_interrupt_all(CPUM68KState *env, int is_hw)
 | 
			
		||||
        env->sr &= ~SR_M;
 | 
			
		||||
    }
 | 
			
		||||
    m68k_switch_sp(env);
 | 
			
		||||
    sp = env->aregs[7];
 | 
			
		||||
    fmt |= (sp & 3) << 28;
 | 
			
		||||
 | 
			
		||||
    /* ??? This could cause MMU faults.  */
 | 
			
		||||
    sp &= ~3;
 | 
			
		||||
 
 | 
			
		||||
@@ -1995,8 +1995,8 @@ DISAS_INSN(move_from_usp)
 | 
			
		||||
        gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    /* TODO: Implement USP.  */
 | 
			
		||||
    gen_exception(s, s->pc - 2, EXCP_ILLEGAL);
 | 
			
		||||
    tcg_gen_ld_i32(AREG(insn, 0), cpu_env,
 | 
			
		||||
                   offsetof(CPUM68KState, sp[M68K_USP]));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
DISAS_INSN(move_to_usp)
 | 
			
		||||
@@ -2005,8 +2005,8 @@ DISAS_INSN(move_to_usp)
 | 
			
		||||
        gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    /* TODO: Implement USP.  */
 | 
			
		||||
    gen_exception(s, s->pc - 2, EXCP_ILLEGAL);
 | 
			
		||||
    tcg_gen_st_i32(AREG(insn, 0), cpu_env,
 | 
			
		||||
                   offsetof(CPUM68KState, sp[M68K_USP]));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
DISAS_INSN(halt)
 | 
			
		||||
 
 | 
			
		||||
@@ -56,9 +56,21 @@ typedef struct MicroBlazeCPUClass {
 | 
			
		||||
typedef struct MicroBlazeCPU {
 | 
			
		||||
    /*< private >*/
 | 
			
		||||
    CPUState parent_obj;
 | 
			
		||||
    uint32_t base_vectors;
 | 
			
		||||
 | 
			
		||||
    /*< public >*/
 | 
			
		||||
 | 
			
		||||
    /* Microblaze Configuration Settings */
 | 
			
		||||
    struct {
 | 
			
		||||
        bool stackprot;
 | 
			
		||||
        uint32_t base_vectors;
 | 
			
		||||
        uint8_t use_fpu;
 | 
			
		||||
        bool use_mmu;
 | 
			
		||||
        bool dcache_writeback;
 | 
			
		||||
        bool endi;
 | 
			
		||||
        char *version;
 | 
			
		||||
        uint8_t pvr;
 | 
			
		||||
    } cfg;
 | 
			
		||||
 | 
			
		||||
    CPUMBState env;
 | 
			
		||||
} MicroBlazeCPU;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -26,6 +26,43 @@
 | 
			
		||||
#include "hw/qdev-properties.h"
 | 
			
		||||
#include "migration/vmstate.h"
 | 
			
		||||
 | 
			
		||||
static const struct {
 | 
			
		||||
    const char *name;
 | 
			
		||||
    uint8_t version_id;
 | 
			
		||||
} mb_cpu_lookup[] = {
 | 
			
		||||
    /* These key value are as per MBV field in PVR0 */
 | 
			
		||||
    {"5.00.a", 0x01},
 | 
			
		||||
    {"5.00.b", 0x02},
 | 
			
		||||
    {"5.00.c", 0x03},
 | 
			
		||||
    {"6.00.a", 0x04},
 | 
			
		||||
    {"6.00.b", 0x06},
 | 
			
		||||
    {"7.00.a", 0x05},
 | 
			
		||||
    {"7.00.b", 0x07},
 | 
			
		||||
    {"7.10.a", 0x08},
 | 
			
		||||
    {"7.10.b", 0x09},
 | 
			
		||||
    {"7.10.c", 0x0a},
 | 
			
		||||
    {"7.10.d", 0x0b},
 | 
			
		||||
    {"7.20.a", 0x0c},
 | 
			
		||||
    {"7.20.b", 0x0d},
 | 
			
		||||
    {"7.20.c", 0x0e},
 | 
			
		||||
    {"7.20.d", 0x0f},
 | 
			
		||||
    {"7.30.a", 0x10},
 | 
			
		||||
    {"7.30.b", 0x11},
 | 
			
		||||
    {"8.00.a", 0x12},
 | 
			
		||||
    {"8.00.b", 0x13},
 | 
			
		||||
    {"8.10.a", 0x14},
 | 
			
		||||
    {"8.20.a", 0x15},
 | 
			
		||||
    {"8.20.b", 0x16},
 | 
			
		||||
    {"8.30.a", 0x17},
 | 
			
		||||
    {"8.40.a", 0x18},
 | 
			
		||||
    {"8.40.b", 0x19},
 | 
			
		||||
    {"8.50.a", 0x1A},
 | 
			
		||||
    {"9.0", 0x1B},
 | 
			
		||||
    {"9.1", 0x1D},
 | 
			
		||||
    {"9.2", 0x1F},
 | 
			
		||||
    {"9.3", 0x20},
 | 
			
		||||
    {NULL, 0},
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void mb_cpu_set_pc(CPUState *cs, vaddr value)
 | 
			
		||||
{
 | 
			
		||||
@@ -63,45 +100,16 @@ static void mb_cpu_reset(CPUState *s)
 | 
			
		||||
 | 
			
		||||
    mcc->parent_reset(s);
 | 
			
		||||
 | 
			
		||||
    memset(env, 0, sizeof(CPUMBState));
 | 
			
		||||
    memset(env, 0, offsetof(CPUMBState, pvr));
 | 
			
		||||
    env->res_addr = RES_ADDR_NONE;
 | 
			
		||||
    tlb_flush(s, 1);
 | 
			
		||||
 | 
			
		||||
    /* Disable stack protector.  */
 | 
			
		||||
    env->shr = ~0;
 | 
			
		||||
 | 
			
		||||
    env->pvr.regs[0] = PVR0_PVR_FULL_MASK \
 | 
			
		||||
                       | PVR0_USE_BARREL_MASK \
 | 
			
		||||
                       | PVR0_USE_DIV_MASK \
 | 
			
		||||
                       | PVR0_USE_HW_MUL_MASK \
 | 
			
		||||
                       | PVR0_USE_EXC_MASK \
 | 
			
		||||
                       | PVR0_USE_ICACHE_MASK \
 | 
			
		||||
                       | PVR0_USE_DCACHE_MASK \
 | 
			
		||||
                       | PVR0_USE_MMU \
 | 
			
		||||
                       | (0xb << 8);
 | 
			
		||||
    env->pvr.regs[2] = PVR2_D_OPB_MASK \
 | 
			
		||||
                        | PVR2_D_LMB_MASK \
 | 
			
		||||
                        | PVR2_I_OPB_MASK \
 | 
			
		||||
                        | PVR2_I_LMB_MASK \
 | 
			
		||||
                        | PVR2_USE_MSR_INSTR \
 | 
			
		||||
                        | PVR2_USE_PCMP_INSTR \
 | 
			
		||||
                        | PVR2_USE_BARREL_MASK \
 | 
			
		||||
                        | PVR2_USE_DIV_MASK \
 | 
			
		||||
                        | PVR2_USE_HW_MUL_MASK \
 | 
			
		||||
                        | PVR2_USE_MUL64_MASK \
 | 
			
		||||
                        | PVR2_USE_FPU_MASK \
 | 
			
		||||
                        | PVR2_USE_FPU2_MASK \
 | 
			
		||||
                        | PVR2_FPU_EXC_MASK \
 | 
			
		||||
                        | 0;
 | 
			
		||||
    env->pvr.regs[10] = 0x0c000000; /* Default to spartan 3a dsp family.  */
 | 
			
		||||
    env->pvr.regs[11] = PVR11_USE_MMU | (16 << 17);
 | 
			
		||||
 | 
			
		||||
    env->sregs[SR_PC] = cpu->base_vectors;
 | 
			
		||||
 | 
			
		||||
#if defined(CONFIG_USER_ONLY)
 | 
			
		||||
    /* start in user mode with interrupts enabled.  */
 | 
			
		||||
    env->sregs[SR_MSR] = MSR_EE | MSR_IE | MSR_VM | MSR_UM;
 | 
			
		||||
    env->pvr.regs[10] = 0x0c000000; /* Spartan 3a dsp.  */
 | 
			
		||||
#else
 | 
			
		||||
    env->sregs[SR_MSR] = 0;
 | 
			
		||||
    mmu_init(&env->mmu);
 | 
			
		||||
@@ -115,10 +123,62 @@ static void mb_cpu_realizefn(DeviceState *dev, Error **errp)
 | 
			
		||||
{
 | 
			
		||||
    CPUState *cs = CPU(dev);
 | 
			
		||||
    MicroBlazeCPUClass *mcc = MICROBLAZE_CPU_GET_CLASS(dev);
 | 
			
		||||
    MicroBlazeCPU *cpu = MICROBLAZE_CPU(cs);
 | 
			
		||||
    CPUMBState *env = &cpu->env;
 | 
			
		||||
    uint8_t version_code = 0;
 | 
			
		||||
    int i = 0;
 | 
			
		||||
 | 
			
		||||
    cpu_reset(cs);
 | 
			
		||||
    qemu_init_vcpu(cs);
 | 
			
		||||
 | 
			
		||||
    env->pvr.regs[0] = PVR0_USE_BARREL_MASK \
 | 
			
		||||
                       | PVR0_USE_DIV_MASK \
 | 
			
		||||
                       | PVR0_USE_HW_MUL_MASK \
 | 
			
		||||
                       | PVR0_USE_EXC_MASK \
 | 
			
		||||
                       | PVR0_USE_ICACHE_MASK \
 | 
			
		||||
                       | PVR0_USE_DCACHE_MASK \
 | 
			
		||||
                       | (0xb << 8);
 | 
			
		||||
    env->pvr.regs[2] = PVR2_D_OPB_MASK \
 | 
			
		||||
                        | PVR2_D_LMB_MASK \
 | 
			
		||||
                        | PVR2_I_OPB_MASK \
 | 
			
		||||
                        | PVR2_I_LMB_MASK \
 | 
			
		||||
                        | PVR2_USE_MSR_INSTR \
 | 
			
		||||
                        | PVR2_USE_PCMP_INSTR \
 | 
			
		||||
                        | PVR2_USE_BARREL_MASK \
 | 
			
		||||
                        | PVR2_USE_DIV_MASK \
 | 
			
		||||
                        | PVR2_USE_HW_MUL_MASK \
 | 
			
		||||
                        | PVR2_USE_MUL64_MASK \
 | 
			
		||||
                        | PVR2_FPU_EXC_MASK \
 | 
			
		||||
                        | 0;
 | 
			
		||||
 | 
			
		||||
    for (i = 0; mb_cpu_lookup[i].name && cpu->cfg.version; i++) {
 | 
			
		||||
        if (strcmp(mb_cpu_lookup[i].name, cpu->cfg.version) == 0) {
 | 
			
		||||
            version_code = mb_cpu_lookup[i].version_id;
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (!version_code) {
 | 
			
		||||
        qemu_log("Invalid MicroBlaze version number: %s\n", cpu->cfg.version);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    env->pvr.regs[0] |= (cpu->cfg.stackprot ? PVR0_SPROT_MASK : 0) |
 | 
			
		||||
                        (cpu->cfg.use_fpu ? PVR0_USE_FPU_MASK : 0) |
 | 
			
		||||
                        (cpu->cfg.use_mmu ? PVR0_USE_MMU_MASK : 0) |
 | 
			
		||||
                        (cpu->cfg.endi ? PVR0_ENDI_MASK : 0) |
 | 
			
		||||
                        (version_code << 16) |
 | 
			
		||||
                        (cpu->cfg.pvr == C_PVR_FULL ? PVR0_PVR_FULL_MASK : 0);
 | 
			
		||||
 | 
			
		||||
    env->pvr.regs[2] |= (cpu->cfg.use_fpu ? PVR2_USE_FPU_MASK : 0) |
 | 
			
		||||
                        (cpu->cfg.use_fpu > 1 ? PVR2_USE_FPU2_MASK : 0);
 | 
			
		||||
 | 
			
		||||
    env->pvr.regs[5] |= cpu->cfg.dcache_writeback ?
 | 
			
		||||
                                        PVR5_DCACHE_WRITEBACK_MASK : 0;
 | 
			
		||||
 | 
			
		||||
    env->pvr.regs[10] = 0x0c000000; /* Default to spartan 3a dsp family.  */
 | 
			
		||||
    env->pvr.regs[11] = PVR11_USE_MMU | (16 << 17);
 | 
			
		||||
 | 
			
		||||
    env->sregs[SR_PC] = cpu->cfg.base_vectors;
 | 
			
		||||
 | 
			
		||||
    mcc->parent_realize(dev, errp);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -151,7 +211,20 @@ static const VMStateDescription vmstate_mb_cpu = {
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static Property mb_properties[] = {
 | 
			
		||||
    DEFINE_PROP_UINT32("xlnx.base-vectors", MicroBlazeCPU, base_vectors, 0),
 | 
			
		||||
    DEFINE_PROP_UINT32("base-vectors", MicroBlazeCPU, cfg.base_vectors, 0),
 | 
			
		||||
    DEFINE_PROP_BOOL("use-stack-protection", MicroBlazeCPU, cfg.stackprot,
 | 
			
		||||
                     false),
 | 
			
		||||
    /* If use-fpu > 0 - FPU is enabled
 | 
			
		||||
     * If use-fpu = 2 - Floating point conversion and square root instructions
 | 
			
		||||
     *                  are enabled
 | 
			
		||||
     */
 | 
			
		||||
    DEFINE_PROP_UINT8("use-fpu", MicroBlazeCPU, cfg.use_fpu, 2),
 | 
			
		||||
    DEFINE_PROP_BOOL("use-mmu", MicroBlazeCPU, cfg.use_mmu, true),
 | 
			
		||||
    DEFINE_PROP_BOOL("dcache-writeback", MicroBlazeCPU, cfg.dcache_writeback,
 | 
			
		||||
                     false),
 | 
			
		||||
    DEFINE_PROP_BOOL("endianness", MicroBlazeCPU, cfg.endi, false),
 | 
			
		||||
    DEFINE_PROP_STRING("version", MicroBlazeCPU, cfg.version),
 | 
			
		||||
    DEFINE_PROP_UINT8("pvr", MicroBlazeCPU, cfg.pvr, C_PVR_FULL),
 | 
			
		||||
    DEFINE_PROP_END_OF_LIST(),
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user