[1/6] mem: add function for checking memsegs IOVAs addresses

Message ID 1530552423-32301-2-git-send-email-alejandro.lucero@netronome.com (mailing list archive)
State Superseded, archived
Delegated to: Thomas Monjalon
Headers
Series Use IOVAs check based on DMA mask |

Checks

Context Check Description
ci/checkpatch success coding style OK
ci/Intel-compilation fail Compilation issues

Commit Message

Alejandro Lucero July 2, 2018, 5:26 p.m. UTC
  A device can suffer addressing limitations. This functions checks
memsegs have iovas within the supported range based on dma mask.

PMD should use this during initialization if supported devices
suffer addressing limitations, returning an error if this function
returns memsegs out of range.

Another potential usage is for emulated IOMMU hardware with addressing
limitations.

Signed-off-by: Alejandro Lucero <alejandro.lucero@netronome.com>
---
 lib/librte_eal/common/eal_common_memory.c  | 37 ++++++++++++++++++++++++++++++
 lib/librte_eal/common/include/rte_memory.h |  3 +++
 2 files changed, 40 insertions(+)
  

Comments

Burakov, Anatoly July 3, 2018, 9:07 a.m. UTC | #1
On 02-Jul-18 6:26 PM, Alejandro Lucero wrote:
> A device can suffer addressing limitations. This functions checks
> memsegs have iovas within the supported range based on dma mask.
> 
> PMD should use this during initialization if supported devices
> suffer addressing limitations, returning an error if this function
> returns memsegs out of range.
> 
> Another potential usage is for emulated IOMMU hardware with addressing
> limitations.
> 
> Signed-off-by: Alejandro Lucero <alejandro.lucero@netronome.com>
> ---

<snip>

> +	const struct rte_mem_config *mcfg;
> +	uint64_t mask;
> +	int i;
> +	int ret = 0;
> +
> +	/* create dma mask */
> +	mask = 1ULL << maskbits;
> +	mask -= 1;

mask = ~((1ULL << maskbits) - 1);

? IMO this makes it much more clear what you're trying to do.

> +
> +	/* get pointer to global configuration */
> +	mcfg = rte_eal_get_configuration()->mem_config;
> +
> +	for (i = 0; i < RTE_MAX_MEMSEG; i++) {
> +		if (mcfg->memseg[i].addr == NULL)
> +			break;
> +
> +		if (mcfg->memseg[i].iova & ~mask) {
> +			ret = -1;
> +			break;
> +		}
> +	}
> +
> +	if (!ret)
> +		return ret;
> +
> +	RTE_LOG(INFO, EAL, "memseg[%d] iova %"PRIx64" out of range:\n",
> +			   i, mcfg->memseg[i].iova);
> +	RTE_LOG(INFO, EAL, "\tusing dma mask %"PRIx64"\n", mask);
> +
> +	return -1;

The control flow looks weird to me. You break if iova has any bits that 
are in the mask, then you display log messages and return -1. How about 
just logging error and returning -1, and simply returning 0 after the loop?
  
Alejandro Lucero July 3, 2018, 10:01 a.m. UTC | #2
On Tue, Jul 3, 2018 at 10:07 AM, Burakov, Anatoly <anatoly.burakov@intel.com
> wrote:

> On 02-Jul-18 6:26 PM, Alejandro Lucero wrote:
>
>> A device can suffer addressing limitations. This functions checks
>> memsegs have iovas within the supported range based on dma mask.
>>
>> PMD should use this during initialization if supported devices
>> suffer addressing limitations, returning an error if this function
>> returns memsegs out of range.
>>
>> Another potential usage is for emulated IOMMU hardware with addressing
>> limitations.
>>
>> Signed-off-by: Alejandro Lucero <alejandro.lucero@netronome.com>
>> ---
>>
>
> <snip>
>
> +       const struct rte_mem_config *mcfg;
>> +       uint64_t mask;
>> +       int i;
>> +       int ret = 0;
>> +
>> +       /* create dma mask */
>> +       mask = 1ULL << maskbits;
>> +       mask -= 1;
>>
>
> mask = ~((1ULL << maskbits) - 1);
>
> ? IMO this makes it much more clear what you're trying to do.
>
>
Sure. I will change it.


> +
>> +       /* get pointer to global configuration */
>> +       mcfg = rte_eal_get_configuration()->mem_config;
>> +
>> +       for (i = 0; i < RTE_MAX_MEMSEG; i++) {
>> +               if (mcfg->memseg[i].addr == NULL)
>> +                       break;
>> +
>> +               if (mcfg->memseg[i].iova & ~mask) {
>> +                       ret = -1;
>> +                       break;
>> +               }
>> +       }
>> +
>> +       if (!ret)
>> +               return ret;
>> +
>> +       RTE_LOG(INFO, EAL, "memseg[%d] iova %"PRIx64" out of range:\n",
>> +                          i, mcfg->memseg[i].iova);
>> +       RTE_LOG(INFO, EAL, "\tusing dma mask %"PRIx64"\n", mask);
>> +
>> +       return -1;
>>
>
> The control flow looks weird to me. You break if iova has any bits that
> are in the mask, then you display log messages and return -1. How about
> just logging error and returning -1, and simply returning 0 after the loop?
>
>
I agree. The truth is I did that initially, but the log lines were too long
with the indent. I will go back to the original.

Thanks


> --
> Thanks,
> Anatoly
>
  

Patch

diff --git a/lib/librte_eal/common/eal_common_memory.c b/lib/librte_eal/common/eal_common_memory.c
index fc6c44d..ca49e5c 100644
--- a/lib/librte_eal/common/eal_common_memory.c
+++ b/lib/librte_eal/common/eal_common_memory.c
@@ -109,6 +109,43 @@ 
 	}
 }
 
+/* check memseg iovas are within the required range based on dma mask */
+int
+rte_eal_check_dma_mask(uint8_t maskbits)
+{
+
+	const struct rte_mem_config *mcfg;
+	uint64_t mask;
+	int i;
+	int ret = 0;
+
+	/* create dma mask */
+	mask = 1ULL << maskbits;
+	mask -= 1;
+
+	/* get pointer to global configuration */
+	mcfg = rte_eal_get_configuration()->mem_config;
+
+	for (i = 0; i < RTE_MAX_MEMSEG; i++) {
+		if (mcfg->memseg[i].addr == NULL)
+			break;
+
+		if (mcfg->memseg[i].iova & ~mask) {
+			ret = -1;
+			break;
+		}
+	}
+
+	if (!ret)
+		return ret;
+
+	RTE_LOG(INFO, EAL, "memseg[%d] iova %"PRIx64" out of range:\n",
+			   i, mcfg->memseg[i].iova);
+	RTE_LOG(INFO, EAL, "\tusing dma mask %"PRIx64"\n", mask);
+
+	return -1;
+}
+
 /* return the number of memory channels */
 unsigned rte_memory_get_nchannel(void)
 {
diff --git a/lib/librte_eal/common/include/rte_memory.h b/lib/librte_eal/common/include/rte_memory.h
index 80a8fc0..b2a0168 100644
--- a/lib/librte_eal/common/include/rte_memory.h
+++ b/lib/librte_eal/common/include/rte_memory.h
@@ -209,6 +209,9 @@  struct rte_memseg {
  */
 unsigned rte_memory_get_nrank(void);
 
+/* check memsegs iovas are within a range based on dma mask */
+int rte_eal_check_dma_mask(uint8_t maskbits);
+
 /**
  * Drivers based on uio will not load unless physical
  * addresses are obtainable. It is only possible to get