[alsa-devel] [PATCH 1/1] intel8x0: [v2] Improve performance in virtual environment

Takashi Iwai tiwai at suse.de
Wed Oct 26 15:03:48 CEST 2011


At Wed, 26 Oct 2011 16:00:15 +0400,
Konstantin Ozerkov wrote:
> 
> v2: add detection for virtual environments (KVM and Parallels)
> 
> This patch is intended to improve performance in virtualized environments
> like Parallels Desktop or KVM/VirtualBox/QEMU (virtual ICH/AC97 audio).
> 
> I/O access is very time-expensive operation in virtual world: VCPU
> can be rescheduled and in the worst case we get more than 10ms delay on
> each I/O access.
> 
> In the virtual environment loop exit rule
> (old_civ == current_civ && old_picb == current_picb) is never satisfied,
> because old_picb is never the same as current_picb due to delay inspired
> by reading current_civ. As a result loop ended by timeout and we get 10x
> more I/O operations.
> 
> Experimental data from Prallels Desktop 7, RHEL6 guest (I/O ops per
> second):
> 
> Original code:
> In Port    Counter         Callback
>    f014      41550         fffff00000179d00 ac97_bm_read_civ+0x000
>    f018      41387         fffff0000017a580 ac97_bm_read_picb+0x000
> 
> With patch:
> In Port    Counter         Callback
>    f014       4090         fffff00000179d00 ac97_bm_read_civ+0x000
>    f018       1964         fffff0000017a580 ac97_bm_read_picb+0x000
> 
> Signed-off-by: Konstantin Ozerkov <kozerkov at parallels.com>
> Signed-off-by: Denis V. Lunev <den at openvz.org>

Are the changes specific to x86, right?
boot_cpu_has() seems x86 only, and kvm_para_*() isn't provided for all
architectures.

The best would be to provide a standard API for such detection.  But,
as a workaround, we may need a simple ifdef.


thanks,

Takashi

> diff --git a/pci/intel8x0.c b/pci/intel8x0.c
> index 6a5b387..0974ae5 100644
> --- a/pci/intel8x0.c
> +++ b/pci/intel8x0.c
> @@ -27,6 +27,7 @@
>   */      
>  
>  #include <asm/io.h>
> +#include <asm/kvm_para.h>
>  #include <linux/delay.h>
>  #include <linux/interrupt.h>
>  #include <linux/init.h>
> @@ -77,6 +78,7 @@ static int buggy_semaphore;
>  static int buggy_irq = -1; /* auto-check */
>  static int xbox;
>  static int spdif_aclink = -1;
> +static int inside_vm = -1;
>  
>  module_param(index, int, 0444);
>  MODULE_PARM_DESC(index, "Index value for Intel i8x0 soundcard.");
> @@ -94,6 +96,8 @@ module_param(xbox, bool, 0444);
>  MODULE_PARM_DESC(xbox, "Set to 1 for Xbox, if you have problems with the AC'97 codec detection.");
>  module_param(spdif_aclink, int, 0444);
>  MODULE_PARM_DESC(spdif_aclink, "S/PDIF over AC-link.");
> +module_param(inside_vm, bool, 0444);
> +MODULE_PARM_DESC(inside_vm, "KVM/Parallels optimization.");
>  
>  /* just for backward compatibility */
>  static int enable;
> @@ -400,6 +404,7 @@ struct intel8x0 {
>  	unsigned buggy_irq: 1;		/* workaround for buggy mobos */
>  	unsigned xbox: 1;		/* workaround for Xbox AC'97 detection */
>  	unsigned buggy_semaphore: 1;	/* workaround for buggy codec semaphore */
> +	unsigned inside_vm: 1;		/* enable VM optimization */
>  
>  	int spdif_idx;	/* SPDIF BAR index; *_SPBAR or -1 if use PCMOUT */
>  	unsigned int sdm_saved;	/* SDM reg value */
> @@ -1065,8 +1070,11 @@ static snd_pcm_uframes_t snd_intel8x0_pcm_pointer(struct snd_pcm_substream *subs
>  			udelay(10);
>  			continue;
>  		}
> -		if (civ == igetbyte(chip, ichdev->reg_offset + ICH_REG_OFF_CIV) &&
> -		    ptr1 == igetword(chip, ichdev->reg_offset + ichdev->roff_picb))
> +		if (civ != igetbyte(chip, ichdev->reg_offset + ICH_REG_OFF_CIV))
> +			continue;
> +		if (chip->inside_vm)
> +			break;
> +		if (ptr1 == igetword(chip, ichdev->reg_offset + ichdev->roff_picb))
>  			break;
>  	} while (timeout--);
>  	ptr = ichdev->last_pos;
> @@ -2984,6 +2992,10 @@ static int __devinit snd_intel8x0_create(struct snd_card *card,
>  	if (xbox)
>  		chip->xbox = 1;
>  
> +	chip->inside_vm = inside_vm;
> +	if (inside_vm)
> +		printk(KERN_INFO "intel8x0: enable KVM optimization\n");
> +
>  	if (pci->vendor == PCI_VENDOR_ID_INTEL &&
>  	    pci->device == PCI_DEVICE_ID_INTEL_440MX)
>  		chip->fix_nocache = 1; /* enable workaround */
> @@ -3226,6 +3238,11 @@ static int __devinit snd_intel8x0_probe(struct pci_dev *pci,
>  			buggy_irq = 0;
>  	}
>  
> +	if (inside_vm < 0) {
> +		/* detect KVM and Parallels virtual environments */
> +		inside_vm = kvm_para_available() || boot_cpu_has(X86_FEATURE_HYPERVISOR);
> +	}
> +
>  	if ((err = snd_intel8x0_create(card, pci, pci_id->driver_data,
>  				       &chip)) < 0) {
>  		snd_card_free(card);
> -- 
> 1.7.7
> 


More information about the Alsa-devel mailing list