Hi David, thanks for reviewing!
Some comments inline.
On 7/3/2020 4:19 PM, David Marchand wrote:
On Thu, Jul 2, 2020 at 11:24 AM Radu Nicolau<radu.nico...@intel.com> wrote:
+static inline void
+rte_write32_wc(uint32_t value, volatile void *addr);
This is a new API, and even if inlined, it should be marked experimental.
Will do.
Is volatile necessary?
Yes, most of these functions will be called on mmio addresses/volatile
pointers. All other io functions have it.
+static inline void
+rte_write32_wc_relaxed(uint32_t value, volatile void *addr);
+
+
Double empty line (there are some other in this patch that I won't flag again).
I will check all occurrences.
#endif /* __DOXYGEN__ */
#ifndef RTE_OVERRIDE_IO_H
@@ -345,6 +378,20 @@ rte_write64(uint64_t value, volatile void *addr)
rte_write64_relaxed(value, addr);
}
+#ifndef RTE_NATIVE_WRITE32_WC
Missing return type, this causes build failure on anything but x86.
Yes, got lost in the copy/paste. I will fix it in the next version
+rte_write32_wc(uint32_t value, volatile void *addr)
+{
+ rte_write32(value, addr);
+}
+
+static __rte_always_inline void
+rte_write32_wc_relaxed(uint32_t value, volatile void *addr)
+{
+ rte_write32_relaxed(value, addr);
+}
+#endif /* RTE_NATIVE_WRITE32_WC */
+
+
#endif /* RTE_OVERRIDE_IO_H */
#endif /* _RTE_IO_H_ */
diff --git a/lib/librte_eal/x86/include/rte_io.h
b/lib/librte_eal/x86/include/rte_io.h
index 2db71b1..c95ed67 100644
--- a/lib/librte_eal/x86/include/rte_io.h
+++ b/lib/librte_eal/x86/include/rte_io.h
@@ -9,8 +9,64 @@
extern "C" {
#endif
+#include "rte_cpuflags.h"
Inclusion of this header should be out of the extern "C" block.
Why? It is used elsewhere inside the extern "C" block e.g.
x86/rte_spinlock.h
+
+#define RTE_NATIVE_WRITE32_WC
#include "generic/rte_io.h"
+/**
+ * @internal
+ * MOVDIRI wrapper.
+ */
+static __rte_always_inline void
+_rte_x86_movdiri(uint32_t value, volatile void *addr)
+{
+ asm volatile(
+ /* MOVDIRI */
+ ".byte 0x40, 0x0f, 0x38, 0xf9, 0x02"
+ :
+ : "a" (value), "d" (addr));
+}
+
+static __rte_always_inline void
+rte_write32_wc(uint32_t value, volatile void *addr)
+{
+ static int _x86_movdiri_flag = -1;
+ if (_x86_movdiri_flag == 1) {
+ rte_wmb();
+ _rte_x86_movdiri(value, addr);
+ } else if (_x86_movdiri_flag == 0) {
+ rte_write32(value, addr);
+ } else {
+ _x86_movdiri_flag =
+ (rte_cpu_get_flag_enabled(RTE_CPUFLAG_MOVDIRI) > 0);
Can't this cpu flag check be moved in a constructor?
This would avoid this copy/paste.
We evaluated this approach but it creates more problems than if fixes -
it will need a variable that needs to be exported and there is no good
place to put it.
+ if (_x86_movdiri_flag == 1) {
+ rte_wmb();
+ _rte_x86_movdiri(value, addr);
+ } else {
+ rte_write32(value, addr);
+ }
+ }
+}
+
+static __rte_always_inline void
+rte_write32_wc_relaxed(uint32_t value, volatile void *addr)
+{
+ static int _x86_movdiri_flag = -1;
Same check with a static variable with the same name.
It should be no problem, they are static local variables.
I wonder if wrapping all of this in a single function would be more elegant.
Then rte_write32_wc(|_relaxed) would call it with a flag.
Yes, it will be more elegant but also it will cost more, it was written
like this to minimize the number of branches taken for the movdiri path.