Bug 211117
Summary: | dma_mmap_coherent() - garbage sound output with mem_encrypt on Ryzen platform | ||
---|---|---|---|
Product: | Drivers | Reporter: | Triton Circonflexe (triton+enkelr) |
Component: | Platform_x86 | Assignee: | drivers_platform_x86 (drivers_platform_x86) |
Status: | NEW --- | ||
Severity: | high | CC: | perex, thomas.lendacky, tiwai |
Priority: | P1 | ||
Hardware: | x86-64 | ||
OS: | Linux | ||
Kernel Version: | 5.10.6 | Subsystem: | |
Regression: | No | Bisected commit-id: | |
Attachments: |
.asoundrc configuration file
Output of alsa-info.sh |
Description
Triton Circonflexe
2021-01-10 16:28:30 UTC
Do you have the issue if you play without alsa-lib plugins, i.e. with aplay -Dhw:0 or such? And is this bug specific to the oxygen driver, or it happens on other devices like USB-audio? I'm wondering which part is problematic with SEV. Direct play to "hw:D2X,0" works (the copy was just to try to capture the result but the result is the same without it). -> Meaning it's probably a plugin issue. And as explained, the exact same configuration on an integrated Realtek ALC 1200A (hda-intel driver) works perfectly fine. -> Meaning it's probably a driver issue. So honestly, I'm quite at loss here. :-/ Hm, that's quite puzzling. Does the behavior change if you call dma_set_mask_and_coherent() with DMA_BIT_MASK(32) explicitly in the oxygen driver? I'm willing to test but I have no idea how/where to do that (developer but not a kernel driver dev), could you explain? It's something like: --- a/sound/pci/oxygen/oxygen_lib.c +++ b/sound/pci/oxygen/oxygen_lib.c @@ -650,6 +650,8 @@ int oxygen_pci_probe(struct pci_dev *pci, int index, char *id, pci_set_master(pci); card->private_free = oxygen_card_free; + dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(32)); + configure_pcie_bridge(pci); oxygen_init(chip); chip->model.init(chip); I don't expect much by this change, so just to be sure... Other than that, check the contents of /proc/asound/card*/pcm0p/sub0/hw_params while playing back different cases (with working device, with non-working device, with plugins, etc). Especially check if it's running in the mmap access mode or not. e.g. you can run aplay with -M option to enforce the mmap mode for -Dhw:*, too. Sorry for the delay, here are the test results: With or without the patch, always the same result (what was working is still working and vice-versa). Now, regarding the content of /proc/asound/card*/pcm0p/sub0/hw_params Note: card0 = D2X/virtuoso and card1 = Generic/hda-intel. The content of the settings for any given test is entirely identical with or without the mem_encrypt=off boot option. The content of /proc/asound/card0/pcm0p/sub0/hw_params for a test with hw:0,0 is very similar to the content of /proc/asound/card1/pcm0p/sub0/hw_params for the same test with hw:1,0: - period_size and buffer_size vary but buffer_size/period_size = 4.0 in all cases. - everything else is identical, beginning with access. Probably no surprise here, but tested anyway. Regarding the tests with speaker-test: - routed_* shows MMAP_INTERLEAVED - copied_* shows RW_INTERLEAVED (as well as hw:*,0) Surely enough, the tests with aplay are consistent with the request: - aplay -D"hw:$card,0" shows RW_INTERLEAVED and works - aplay -M -D"hw:$card,0" shows MMAP_INTERLEAVED and outputs white noise on D2X Additional tests with the default system configuration alsa shows MMAP_INTERLEAVED which is once again consistent. Thanks. It's clearer now that it's the mmap that causes the problem. Could you give alsa-info.sh output for further verification? Run the script with --no-upload option and attach the output to Bugzilla. And, now let's try other way round; modify HD-audio driver and see whether the issue happens with the mmap mode. The patch below enforces the 32bit DMA mask and the same buffer allocation type without S/G for HD-audio: --- a/sound/pci/hda/hda_controller.c +++ b/sound/pci/hda/hda_controller.c @@ -720,7 +720,7 @@ int snd_hda_attach_pcm_stream(struct hda_bus *_bus, struct hda_codec *codec, int pcm_dev = cpcm->device; unsigned int size; int s, err; - int type = SNDRV_DMA_TYPE_DEV_SG; + int type = SNDRV_DMA_TYPE_DEV; list_for_each_entry(apcm, &chip->pcm_list, list) { if (apcm->pcm->device == pcm_dev) { @@ -759,8 +759,6 @@ int snd_hda_attach_pcm_stream(struct hda_bus *_bus, struct hda_codec *codec, size = CONFIG_SND_HDA_PREALLOC_SIZE * 1024; if (size > MAX_PREALLOC_SIZE) size = MAX_PREALLOC_SIZE; - if (chip->uc_buffer) - type = SNDRV_DMA_TYPE_DEV_UC_SG; snd_pcm_set_managed_buffer_all(pcm, type, chip->card->dev, size, MAX_PREALLOC_SIZE); return 0; diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 8d568277088a..bcf3b0cadf5c 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -1967,6 +1967,7 @@ static int azx_first_init(struct azx *chip) /* allow 64bit DMA address if supported by H/W */ if (!(gcap & AZX_GCAP_64OK)) dma_bits = 32; + dma_bits = 32; if (!dma_set_mask(&pci->dev, DMA_BIT_MASK(dma_bits))) { dma_set_coherent_mask(&pci->dev, DMA_BIT_MASK(dma_bits)); } else { Created attachment 294699 [details]
Output of alsa-info.sh
Good news... well, sorta: the sound is now equally horrible on hda-intel with mmap activated.
Note: I had a few error messages on alsa-info.sh execution:
cat: /proc/asound/modules: No such file or directory
cat: /sys/class/sound/hwC1D0/user_pin_configs: No such file or directory
cat: /sys/class/sound/hwC1D0/init_verbs: No such file or directory
cat: /sys/class/sound/hwC1D0/hints: No such file or directory
cat: /sys/class/sound/hwC2D0/user_pin_configs: No such file or directory
cat: /sys/class/sound/hwC2D0/init_verbs: No such file or directory
cat: /sys/class/sound/hwC2D0/hints: No such file or directory
One thing I forgot to mention is that the virtuoso driver is built in-kernel while the hda-intel is built as a module because at first, I didn't intend to build the hda-intel at all since I did not think I would use the embedded chip.
OK, then could you check which change causes the problem on snd-hda-intel: the change in hda_intel.c (setting dma_mask) or in hda-controller.c (setting SNDRV_DMA_TYPE_*)? I can. - With only the hda_intel.c (dma_bits = 32) part of the patch, I hear music. - With only the hda_controller.c (type = SNDRV_DMA_TYPE_DEV) part of the patch, I hear white noise. OK, thanks. Then, could you try the change below together with SNDRV_DMA_TYPE_DEV change? Does it work now? --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -3713,7 +3713,7 @@ int snd_pcm_lib_default_mmap(struct snd_pcm_substream *substream, area->vm_end - area->vm_start, area->vm_page_prot); } #endif /* CONFIG_GENERIC_ALLOCATOR */ - if (IS_ENABLED(CONFIG_HAS_DMA) && !substream->ops->page && + if (0 && IS_ENABLED(CONFIG_HAS_DMA) && !substream->ops->page && (substream->dma_buffer.dev.type == SNDRV_DMA_TYPE_DEV || substream->dma_buffer.dev.type == SNDRV_DMA_TYPE_DEV_UC)) return dma_mmap_coherent(substream->dma_buffer.dev.dev, With hda_controller.c AND pcm_native.c patches, the Generic/hda-intel device is working as expected. pcm_native.c being obviously a common file, I also tested the D2X/virtuoso device and it works too. So, the test result implies that dma_mmap_coherent() is broken with the memory encryption while the mmap with the page fault still works. I'll trust you on that. :-) In any case, I stay available for further tests if needed. It looks like an issue which is not related directly to audio, right? Reassigning to Platform_X86 . Yes, this must be a generic issue. I'll ask Christoph at first. This sounds like a mismatch between the encryption bit in the kernel and the encryption bit in userspace. It looks like that should be taken care of by the dma_pgprot() call in dma_mmap_attrs() or in iommu_dma_mmap(). But maybe the force_dma_unencrypted() in arch/x86/mm/mem_encrypt.c needs to understand if the IOMMU is doing the mapping. Since, even if the device doesn't support 48-bit or higher DMA, it will still done encrypted because of the IOMMU. I don't see any dmesg output, is the IOMMU enabled? What happens if you do iommu=pt on the kernel command line? Alternatively, if you want memory encryption for your bare-metal system, you can see if the BIOS supports TSME (Transparent SME). Then you can remove mem_encrypt=on or add mem_encrypt=off (if enabled by default), and still get memory encryption. Tested with iommu=pt (and no mem_encrypt option, so "on" by default): still white noise. Regarding the encryption, I don't really have a _need_ for that. If I use it, it's in part because Virtualbox seems to require it in some use cases (not even entirely sure about that) and mostly because it's activated by default (and I like default settings to work correctly). I checked the BIOS anyway but did not find any TSME or similar option (thanks for the information, though). Right now, I'm working with mem_encrypt=off and I can do everything I need for now (no vbox for the moment). I will continue to follow this bug because I can reproduce the problem easily and do tests if required. |