nvmf/vfio-user: Fix doorbell polling not working on some ARM platform

On aarch64 platforms, doorbells update from guest VM may not be seen
on SPDK target side. This is because there is memory type mismatch
situation here. That is on guest VM side, the doorbells are treated as
device memory while on SPDK target side, it is treated as normal
memory. And this situation cause problem on ARM platform.
Refer to "https://developer.arm.com/documentation/102376/0100/
Memory-aliasing-and-mismatched-memory-types". Only using spdk_mb()
cannot fix this. Use "dc civac" to invalidate cache may solve this.

Profiling data did not show big performance degradataion.

Signed-off-by: Rui Chang <rui.chang@arm.com>
Change-Id: I9a18718f8c4307b3007b18c32ab02e6796548958
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/10222
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Community-CI: Broadcom CI <spdk-ci.pdl@broadcom.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Reviewed-by: Changpeng Liu <changpeng.liu@intel.com>
This commit is contained in:
Rui Chang 2021-11-11 18:15:48 +08:00 committed by Tomasz Zawadzki
parent 3911bc344b
commit 5d926c48ea
2 changed files with 19 additions and 0 deletions

View File

@ -66,6 +66,9 @@ extern "C" {
/** SMP read/write memory barrier. */
#define spdk_smp_mb() _spdk_smp_mb()
/** Invalidate data cache, input is data pointer */
#define spdk_ivdt_dcache(pdata) _spdk_ivdt_dcache(pdata)
#ifdef __PPC64__
#define _spdk_rmb() __asm volatile("sync" ::: "memory")
@ -74,6 +77,7 @@ extern "C" {
#define _spdk_smp_rmb() __asm volatile("lwsync" ::: "memory")
#define _spdk_smp_wmb() __asm volatile("lwsync" ::: "memory")
#define _spdk_smp_mb() spdk_mb()
#define _spdk_ivdt_dcache(pdata)
#elif defined(__aarch64__)
@ -83,6 +87,7 @@ extern "C" {
#define _spdk_smp_rmb() __asm volatile("dmb ishld" ::: "memory")
#define _spdk_smp_wmb() __asm volatile("dmb ishst" ::: "memory")
#define _spdk_smp_mb() __asm volatile("dmb ish" ::: "memory")
#define _spdk_ivdt_dcache(pdata) asm volatile("dc civac, %0" : : "r"(pdata) : "memory");
#elif defined(__i386__) || defined(__x86_64__)
@ -96,6 +101,7 @@ extern "C" {
#elif defined(__i386__)
#define _spdk_smp_mb() __asm volatile("lock addl $0, -128(%%esp); " ::: "memory");
#endif
#define _spdk_ivdt_dcache(pdata)
#else
@ -105,6 +111,7 @@ extern "C" {
#define _spdk_smp_rmb()
#define _spdk_smp_wmb()
#define _spdk_smp_mb()
#define _spdk_ivdt_dcache(pdata)
#error Unknown architecture
#endif

View File

@ -2836,6 +2836,18 @@ nvmf_vfio_user_qpair_poll(struct nvmf_vfio_user_qpair *qpair)
ctrlr = qpair->ctrlr;
/* On aarch64 platforms, doorbells update from guest VM may not be seen
* on SPDK target side. This is because there is memory type mismatch
* situation here. That is on guest VM side, the doorbells are treated as
* device memory while on SPDK target side, it is treated as normal
* memory. And this situation cause problem on ARM platform.
* Refer to "https://developer.arm.com/documentation/102376/0100/
* Memory-aliasing-and-mismatched-memory-types". Only using spdk_mb()
* cannot fix this. Use "dc civac" to invalidate cache may solve
* this.
*/
spdk_ivdt_dcache(tdbl(ctrlr, &qpair->sq));
/* Load-Acquire. */
new_tail = *tdbl(ctrlr, &qpair->sq);