* i8254 security fix
* Avoid long 100% CPU wait after restarting guests that use the periodic timer * Fixes for access clamping (WinXP, MIPS) * wixl/.msi support for qemu-ga on Windows -----BEGIN PGP SIGNATURE----- Version: GnuPG v2 iQEcBAABCAAGBQJVg+9dAAoJEL/70l94x66Df/MH/jWRacMKQAGJwmlXS4NsTCdh HF85290kWn+P9NH1e7TBnhPrgBdDTJmxK3fAMHKZwXs3vDs2lC1eBJyoGZw7lVxQ uihlnQjSSaRd5R6IpXNgr0wFrS8T3pN+FzOkStYqEHYINa1uBa6CBXYzOzGTFgd+ OOrU0O15NAVsxU29jBW4HPqX4S0zT4KbpvIESGWPgGbLyBhgLAuMLlvbWwNkFZt0 3bDtel9QQnL0Sm4wl7IWCqePEIkCkbF4tRIwCn34Bq/SuE0RgESiHGKUJ638oSuj /ga1StztyHZhnk+SSAcnma//Holauh+2nBm+8sGyyFFeUbEJsPG70ODCrfxbQf0= =AXLV -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/bonzini/tags/for-upstream' into staging * i8254 security fix * Avoid long 100% CPU wait after restarting guests that use the periodic timer * Fixes for access clamping (WinXP, MIPS) * wixl/.msi support for qemu-ga on Windows # gpg: Signature made Fri Jun 19 11:30:53 2015 BST using RSA key ID 78C7AE83 # gpg: Good signature from "Paolo Bonzini <bonzini@gnu.org>" # gpg: aka "Paolo Bonzini <pbonzini@redhat.com>" # gpg: WARNING: This key is not certified with sufficiently trusted signatures! # gpg: It is not certain that the signature belongs to the owner. # Primary key fingerprint: 46F5 9FBD 57D6 12E7 BFD4 E2F7 7E15 100C CD36 69B1 # Subkey fingerprint: F133 3857 4B66 2389 866C 7682 BFFB D25F 78C7 AE83 * remotes/bonzini/tags/for-upstream: exec: clamp accesses against the MemoryRegionSection exec: do not clamp accesses to MMIO regions mc146818rtc: Reset the periodic timer on load qemu-timer: Call clock reset notifiers on forward jumps tests: virtio-scsi: Add test for unaligned WRITE SAME tests: virtio-scsi: Move start/stop to individual test functions libqos: Complete virtio device ID definition list libqos: Allow calling guest_free on NULL pointer tests: Link libqos virtio object to virtio-scsi-test i8254: fix out-of-bounds memory access in pit_ioport_read() qemu-ga: Building Windows MSI installation with configure/Makefile qemu-ga: Introduce Windows MSI script qemu-ga: debug printouts to help troubleshoot installation qemu-ga: adding vss-[un]install options qemu-log: Open file for logging when specified Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
		
						commit
						cb4e0f9ddf
					
				
							
								
								
									
										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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
 */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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};
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -371,7 +371,7 @@ tests/virtio-balloon-test$(EXESUF): tests/virtio-balloon-test.o
 | 
			
		|||
tests/virtio-blk-test$(EXESUF): tests/virtio-blk-test.o $(libqos-virtio-obj-y)
 | 
			
		||||
tests/virtio-net-test$(EXESUF): tests/virtio-net-test.o $(libqos-pc-obj-y)
 | 
			
		||||
tests/virtio-rng-test$(EXESUF): tests/virtio-rng-test.o $(libqos-pc-obj-y)
 | 
			
		||||
tests/virtio-scsi-test$(EXESUF): tests/virtio-scsi-test.o
 | 
			
		||||
tests/virtio-scsi-test$(EXESUF): tests/virtio-scsi-test.o $(libqos-virtio-obj-y)
 | 
			
		||||
tests/virtio-9p-test$(EXESUF): tests/virtio-9p-test.o
 | 
			
		||||
tests/virtio-serial-test$(EXESUF): tests/virtio-serial-test.o
 | 
			
		||||
tests/virtio-console-test$(EXESUF): tests/virtio-console-test.o
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -285,6 +285,9 @@ uint64_t guest_alloc(QGuestAllocator *allocator, size_t size)
 | 
			
		|||
 | 
			
		||||
void guest_free(QGuestAllocator *allocator, uint64_t addr)
 | 
			
		||||
{
 | 
			
		||||
    if (!addr) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    mlist_free(allocator, addr);
 | 
			
		||||
    if (allocator->opts & ALLOC_PARANOID) {
 | 
			
		||||
        mlist_check(allocator);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -19,8 +19,14 @@
 | 
			
		|||
#define QVIRTIO_DRIVER          0x2
 | 
			
		||||
#define QVIRTIO_DRIVER_OK       0x4
 | 
			
		||||
 | 
			
		||||
#define QVIRTIO_NET_DEVICE_ID   0x1
 | 
			
		||||
#define QVIRTIO_BLK_DEVICE_ID   0x2
 | 
			
		||||
#define QVIRTIO_NET_DEVICE_ID       0x1
 | 
			
		||||
#define QVIRTIO_BLK_DEVICE_ID       0x2
 | 
			
		||||
#define QVIRTIO_CONSOLE_DEVICE_ID   0x3
 | 
			
		||||
#define QVIRTIO_RNG_DEVICE_ID       0x4
 | 
			
		||||
#define QVIRTIO_BALLOON_DEVICE_ID   0x5
 | 
			
		||||
#define QVIRTIO_RPMSG_DEVICE_ID     0x7
 | 
			
		||||
#define QVIRTIO_SCSI_DEVICE_ID      0x8
 | 
			
		||||
#define QVIRTIO_9P_DEVICE_ID        0x9
 | 
			
		||||
 | 
			
		||||
#define QVIRTIO_F_NOTIFY_ON_EMPTY       0x01000000
 | 
			
		||||
#define QVIRTIO_F_ANY_LAYOUT            0x08000000
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,6 +2,7 @@
 | 
			
		|||
 * QTest testcase for VirtIO SCSI
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright (c) 2014 SUSE LINUX Products GmbH
 | 
			
		||||
 * Copyright (c) 2015 Red Hat Inc.
 | 
			
		||||
 *
 | 
			
		||||
 * This work is licensed under the terms of the GNU GPL, version 2 or later.
 | 
			
		||||
 * See the COPYING file in the top-level directory.
 | 
			
		||||
| 
						 | 
				
			
			@ -11,16 +12,187 @@
 | 
			
		|||
#include <string.h>
 | 
			
		||||
#include "libqtest.h"
 | 
			
		||||
#include "qemu/osdep.h"
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include "libqos/virtio.h"
 | 
			
		||||
#include "libqos/virtio-pci.h"
 | 
			
		||||
#include "libqos/pci-pc.h"
 | 
			
		||||
#include "libqos/malloc.h"
 | 
			
		||||
#include "libqos/malloc-pc.h"
 | 
			
		||||
#include "libqos/malloc-generic.h"
 | 
			
		||||
 | 
			
		||||
#define PCI_SLOT                0x02
 | 
			
		||||
#define PCI_FN                  0x00
 | 
			
		||||
#define QVIRTIO_SCSI_TIMEOUT_US (1 * 1000 * 1000)
 | 
			
		||||
#define CDB_SIZE 32
 | 
			
		||||
 | 
			
		||||
#define MAX_NUM_QUEUES 64
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
    QVirtioDevice *dev;
 | 
			
		||||
    QGuestAllocator *alloc;
 | 
			
		||||
    QPCIBus *bus;
 | 
			
		||||
    int num_queues;
 | 
			
		||||
    QVirtQueue *vq[MAX_NUM_QUEUES + 2];
 | 
			
		||||
} QVirtIOSCSI;
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
    uint8_t lun[8];
 | 
			
		||||
    int64_t tag;
 | 
			
		||||
    uint8_t task_attr;
 | 
			
		||||
    uint8_t prio;
 | 
			
		||||
    uint8_t crn;
 | 
			
		||||
    uint8_t cdb[CDB_SIZE];
 | 
			
		||||
} QEMU_PACKED QVirtIOSCSICmdReq;
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
    uint32_t sense_len;
 | 
			
		||||
    uint32_t resid;
 | 
			
		||||
    uint16_t status_qualifier;
 | 
			
		||||
    uint8_t status;
 | 
			
		||||
    uint8_t response;
 | 
			
		||||
    uint8_t sense[96];
 | 
			
		||||
} QEMU_PACKED QVirtIOSCSICmdResp;
 | 
			
		||||
 | 
			
		||||
static void qvirtio_scsi_start(const char *extra_opts)
 | 
			
		||||
{
 | 
			
		||||
    char *cmdline;
 | 
			
		||||
 | 
			
		||||
    cmdline = g_strdup_printf(
 | 
			
		||||
                "-drive id=drv0,if=none,file=/dev/null,format=raw "
 | 
			
		||||
                "-device virtio-scsi-pci,id=vs0 "
 | 
			
		||||
                "-device scsi-hd,bus=vs0.0,drive=drv0 %s",
 | 
			
		||||
                extra_opts ? : "");
 | 
			
		||||
    qtest_start(cmdline);
 | 
			
		||||
    g_free(cmdline);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void qvirtio_scsi_stop(void)
 | 
			
		||||
{
 | 
			
		||||
    qtest_end();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static QVirtIOSCSI *qvirtio_scsi_pci_init(int slot)
 | 
			
		||||
{
 | 
			
		||||
    QVirtIOSCSI *vs;
 | 
			
		||||
    QVirtioPCIDevice *dev;
 | 
			
		||||
    void *addr;
 | 
			
		||||
    int i;
 | 
			
		||||
 | 
			
		||||
    vs = g_new0(QVirtIOSCSI, 1);
 | 
			
		||||
    vs->alloc = pc_alloc_init();
 | 
			
		||||
    vs->bus = qpci_init_pc();
 | 
			
		||||
 | 
			
		||||
    dev = qvirtio_pci_device_find(vs->bus, QVIRTIO_SCSI_DEVICE_ID);
 | 
			
		||||
    vs->dev = (QVirtioDevice *)dev;
 | 
			
		||||
    g_assert(dev != NULL);
 | 
			
		||||
    g_assert_cmphex(vs->dev->device_type, ==, QVIRTIO_SCSI_DEVICE_ID);
 | 
			
		||||
 | 
			
		||||
    qvirtio_pci_device_enable(dev);
 | 
			
		||||
    qvirtio_reset(&qvirtio_pci, vs->dev);
 | 
			
		||||
    qvirtio_set_acknowledge(&qvirtio_pci, vs->dev);
 | 
			
		||||
    qvirtio_set_driver(&qvirtio_pci, vs->dev);
 | 
			
		||||
 | 
			
		||||
    addr = dev->addr + QVIRTIO_PCI_DEVICE_SPECIFIC_NO_MSIX;
 | 
			
		||||
    vs->num_queues = qvirtio_config_readl(&qvirtio_pci, vs->dev,
 | 
			
		||||
                                          (uint64_t)(uintptr_t)addr);
 | 
			
		||||
 | 
			
		||||
    g_assert_cmpint(vs->num_queues, <, MAX_NUM_QUEUES);
 | 
			
		||||
 | 
			
		||||
    for (i = 0; i < vs->num_queues + 2; i++) {
 | 
			
		||||
        vs->vq[i] = qvirtqueue_setup(&qvirtio_pci, vs->dev, vs->alloc, i);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return vs;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void qvirtio_scsi_pci_free(QVirtIOSCSI *vs)
 | 
			
		||||
{
 | 
			
		||||
    int i;
 | 
			
		||||
 | 
			
		||||
    for (i = 0; i < vs->num_queues + 2; i++) {
 | 
			
		||||
        guest_free(vs->alloc, vs->vq[i]->desc);
 | 
			
		||||
    }
 | 
			
		||||
    pc_alloc_uninit(vs->alloc);
 | 
			
		||||
    qvirtio_pci_device_disable(container_of(vs->dev, QVirtioPCIDevice, vdev));
 | 
			
		||||
    g_free(vs->dev);
 | 
			
		||||
    qpci_free_pc(vs->bus);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static uint64_t qvirtio_scsi_alloc(QVirtIOSCSI *vs, size_t alloc_size,
 | 
			
		||||
                                   const void *data)
 | 
			
		||||
{
 | 
			
		||||
    uint64_t addr;
 | 
			
		||||
 | 
			
		||||
    addr = guest_alloc(vs->alloc, alloc_size);
 | 
			
		||||
    if (data) {
 | 
			
		||||
        memwrite(addr, data, alloc_size);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return addr;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static uint8_t virtio_scsi_do_command(QVirtIOSCSI *vs, const uint8_t *cdb,
 | 
			
		||||
                                      const uint8_t *data_in,
 | 
			
		||||
                                      size_t data_in_len,
 | 
			
		||||
                                      uint8_t *data_out, size_t data_out_len)
 | 
			
		||||
{
 | 
			
		||||
    QVirtQueue *vq;
 | 
			
		||||
    QVirtIOSCSICmdReq req = { { 0 } };
 | 
			
		||||
    QVirtIOSCSICmdResp resp = { .response = 0xff, .status = 0xff };
 | 
			
		||||
    uint64_t req_addr, resp_addr, data_in_addr = 0, data_out_addr = 0;
 | 
			
		||||
    uint8_t response;
 | 
			
		||||
    uint32_t free_head;
 | 
			
		||||
 | 
			
		||||
    vq = vs->vq[2];
 | 
			
		||||
 | 
			
		||||
    req.lun[0] = 1; /* Select LUN */
 | 
			
		||||
    req.lun[1] = 1; /* Select target 1 */
 | 
			
		||||
    memcpy(req.cdb, cdb, CDB_SIZE);
 | 
			
		||||
 | 
			
		||||
    /* XXX: Fix endian if any multi-byte field in req/resp is used */
 | 
			
		||||
 | 
			
		||||
    /* Add request header */
 | 
			
		||||
    req_addr = qvirtio_scsi_alloc(vs, sizeof(req), &req);
 | 
			
		||||
    free_head = qvirtqueue_add(vq, req_addr, sizeof(req), false, true);
 | 
			
		||||
 | 
			
		||||
    if (data_out_len) {
 | 
			
		||||
        data_out_addr = qvirtio_scsi_alloc(vs, data_out_len, data_out);
 | 
			
		||||
        qvirtqueue_add(vq, data_out_addr, data_out_len, false, true);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Add response header */
 | 
			
		||||
    resp_addr = qvirtio_scsi_alloc(vs, sizeof(resp), &resp);
 | 
			
		||||
    qvirtqueue_add(vq, resp_addr, sizeof(resp), true, !!data_in_len);
 | 
			
		||||
 | 
			
		||||
    if (data_in_len) {
 | 
			
		||||
        data_in_addr = qvirtio_scsi_alloc(vs, data_in_len, data_in);
 | 
			
		||||
        qvirtqueue_add(vq, data_in_addr, data_in_len, true, false);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    qvirtqueue_kick(&qvirtio_pci, vs->dev, vq, free_head);
 | 
			
		||||
    qvirtio_wait_queue_isr(&qvirtio_pci, vs->dev, vq, QVIRTIO_SCSI_TIMEOUT_US);
 | 
			
		||||
 | 
			
		||||
    response = readb(resp_addr + offsetof(QVirtIOSCSICmdResp, response));
 | 
			
		||||
 | 
			
		||||
    guest_free(vs->alloc, req_addr);
 | 
			
		||||
    guest_free(vs->alloc, resp_addr);
 | 
			
		||||
    guest_free(vs->alloc, data_in_addr);
 | 
			
		||||
    guest_free(vs->alloc, data_out_addr);
 | 
			
		||||
    return response;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Tests only initialization so far. TODO: Replace with functional tests */
 | 
			
		||||
static void pci_nop(void)
 | 
			
		||||
{
 | 
			
		||||
    qvirtio_scsi_start(NULL);
 | 
			
		||||
    qvirtio_scsi_stop();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void hotplug(void)
 | 
			
		||||
{
 | 
			
		||||
    QDict *response;
 | 
			
		||||
 | 
			
		||||
    qvirtio_scsi_start("-drive id=drv1,if=none,file=/dev/null,format=raw");
 | 
			
		||||
    response = qmp("{\"execute\": \"device_add\","
 | 
			
		||||
                   " \"arguments\": {"
 | 
			
		||||
                   "   \"driver\": \"scsi-hd\","
 | 
			
		||||
| 
						 | 
				
			
			@ -42,6 +214,27 @@ static void hotplug(void)
 | 
			
		|||
    g_assert(qdict_haskey(response, "event"));
 | 
			
		||||
    g_assert(!strcmp(qdict_get_str(response, "event"), "DEVICE_DELETED"));
 | 
			
		||||
    QDECREF(response);
 | 
			
		||||
    qvirtio_scsi_stop();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Test WRITE SAME with the lba not aligned */
 | 
			
		||||
static void test_unaligned_write_same(void)
 | 
			
		||||
{
 | 
			
		||||
    QVirtIOSCSI *vs;
 | 
			
		||||
    uint8_t buf[512] = { 0 };
 | 
			
		||||
    const uint8_t write_same_cdb[CDB_SIZE] = { 0x41, 0x00, 0x00, 0x00, 0x00,
 | 
			
		||||
                                               0x01, 0x00, 0x00, 0x02, 0x00 };
 | 
			
		||||
 | 
			
		||||
    qvirtio_scsi_start("-drive file=blkdebug::null-co://,if=none,id=dr1"
 | 
			
		||||
                       ",format=raw,file.align=4k "
 | 
			
		||||
                       "-device scsi-disk,drive=dr1,lun=0,scsi-id=1");
 | 
			
		||||
    vs = qvirtio_scsi_pci_init(PCI_SLOT);
 | 
			
		||||
 | 
			
		||||
    g_assert_cmphex(0, ==,
 | 
			
		||||
        virtio_scsi_do_command(vs, write_same_cdb, NULL, 0, buf, 512));
 | 
			
		||||
 | 
			
		||||
    qvirtio_scsi_pci_free(vs);
 | 
			
		||||
    qvirtio_scsi_stop();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int main(int argc, char **argv)
 | 
			
		||||
| 
						 | 
				
			
			@ -51,14 +244,10 @@ int main(int argc, char **argv)
 | 
			
		|||
    g_test_init(&argc, &argv, NULL);
 | 
			
		||||
    qtest_add_func("/virtio/scsi/pci/nop", pci_nop);
 | 
			
		||||
    qtest_add_func("/virtio/scsi/pci/hotplug", hotplug);
 | 
			
		||||
    qtest_add_func("/virtio/scsi/pci/scsi-disk/unaligned-write-same",
 | 
			
		||||
                   test_unaligned_write_same);
 | 
			
		||||
 | 
			
		||||
    qtest_start("-drive id=drv0,if=none,file=/dev/null,format=raw "
 | 
			
		||||
                "-drive id=drv1,if=none,file=/dev/null,format=raw "
 | 
			
		||||
                "-device virtio-scsi-pci,id=vscsi0 "
 | 
			
		||||
                "-device scsi-hd,bus=vscsi0.0,drive=drv0");
 | 
			
		||||
    ret = g_test_run();
 | 
			
		||||
 | 
			
		||||
    qtest_end();
 | 
			
		||||
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										13
									
								
								vl.c
								
								
								
								
							
							
						
						
									
										13
									
								
								vl.c
								
								
								
								
							| 
						 | 
				
			
			@ -3997,17 +3997,14 @@ int main(int argc, char **argv, char **envp)
 | 
			
		|||
        exit(0);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Open the logfile at this point, if necessary. We can't open the logfile
 | 
			
		||||
     * when encountering either of the logging options (-d or -D) because the
 | 
			
		||||
     * other one may be encountered later on the command line, changing the
 | 
			
		||||
     * location or level of logging.
 | 
			
		||||
    /* Open the logfile at this point and set the log mask if necessary.
 | 
			
		||||
     */
 | 
			
		||||
    if (log_file) {
 | 
			
		||||
        qemu_set_log_filename(log_file);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (log_mask) {
 | 
			
		||||
        int mask;
 | 
			
		||||
        if (log_file) {
 | 
			
		||||
            qemu_set_log_filename(log_file);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        mask = qemu_str_to_log_mask(log_mask);
 | 
			
		||||
        if (!mask) {
 | 
			
		||||
            qemu_print_log_usage(stdout);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue