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@parallels.com Signed-off-by: Denis V. Lunev den@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;
} while (timeout--); ptr = ichdev->last_pos;if (ptr1 == igetword(chip, ichdev->reg_offset + ichdev->roff_picb)) break;
@@ -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