Add support for multiple microarchitectures in single binary
[vpp.git] / vlib / vlib / node.h
index 806a9da..9b33a0a 100644 (file)
@@ -40,6 +40,7 @@
 #ifndef included_vlib_node_h
 #define included_vlib_node_h
 
+#include <vppinfra/cpu.h>
 #include <vppinfra/longjmp.h>
 #include <vppinfra/timing_wheel.h>
 #include <vlib/trace.h>                /* for vlib_trace_filter_t */
@@ -149,6 +150,32 @@ static void __vlib_add_node_registration_##x (void)                     \
 }                                                                       \
 __VA_ARGS__ vlib_node_registration_t x 
 
+#if CLIB_DEBUG > 0
+#define VLIB_NODE_FUNCTION_CLONE_TEMPLATE(arch, fn)
+#define VLIB_NODE_FUNCTION_MULTIARCH_CLONE(fn)
+#define VLIB_NODE_FUNCTION_MULTIARCH(node, fn)
+#else
+#define VLIB_NODE_FUNCTION_CLONE_TEMPLATE(arch, fn, tgt)               \
+  uword                                                                        \
+  __attribute__ ((flatten))                                            \
+  __attribute__ ((target (tgt)))                                       \
+  CLIB_CPU_OPTIMIZED                                                   \
+  fn ## _ ## arch ( struct vlib_main_t * vm,                           \
+                   struct vlib_node_runtime_t * node,                  \
+                   struct vlib_frame_t * frame)                                \
+  { return fn (vm, node, frame); }
+
+#define VLIB_NODE_FUNCTION_MULTIARCH_CLONE(fn)                         \
+  foreach_march_variant(VLIB_NODE_FUNCTION_CLONE_TEMPLATE, fn)
+
+#define VLIB_NODE_FUNCTION_MULTIARCH(node, fn)                         \
+  VLIB_NODE_FUNCTION_MULTIARCH_CLONE(fn)                               \
+  CLIB_MULTIARCH_SELECT_FN(fn, static inline)                          \
+  static void __attribute__((__constructor__))                         \
+  __vlib_node_function_multiarch_select_##node (void)                  \
+  { node.function = fn ## _multiarch_select(); }
+#endif
+
 always_inline vlib_node_registration_t *
 vlib_node_next_registered (vlib_node_registration_t * c)
 {
@@ -290,6 +317,7 @@ typedef struct vlib_node_t {
 
 /* Max number of vector elements to process at once per node. */
 #define VLIB_FRAME_SIZE 256
+#define VLIB_FRAME_ALIGN VLIB_MAX_CPUS
 
 /* Calling frame (think stack frame) for a node. */
 typedef struct vlib_frame_t {
@@ -495,17 +523,32 @@ typedef struct {
   /* When suspending saves cpu cycle counter when process is to be resumed. */
   u64 resume_cpu_time;
 
+  /* Default output function and its argument for any CLI outputs
+     within the process. */
+  vlib_cli_output_function_t *output_function;
+  uword output_function_arg;
+
 #ifdef CLIB_UNIX
   /* Pad to a multiple of the page size so we can mprotect process stacks */
-  CLIB_PAD_FROM_TO (0x140, 0x1000);
+#define PAGE_SIZE_MULTIPLE 0x1000
+#define ALIGN_ON_MULTIPLE_PAGE_BOUNDARY_FOR_MPROTECT  __attribute__ ((aligned (PAGE_SIZE_MULTIPLE)))
+#else
+#define ALIGN_ON_MULTIPLE_PAGE_BOUNDARY_FOR_MPROTECT
 #endif
+
   /* Process stack.  Starts here and extends 2^log2_n_stack_bytes
      bytes. */
 
 #define VLIB_PROCESS_STACK_MAGIC (0xdead7ead)
-  u32 stack[0];
+  u32 stack[0] ALIGN_ON_MULTIPLE_PAGE_BOUNDARY_FOR_MPROTECT;
 } vlib_process_t __attribute__ ((aligned (CLIB_CACHE_LINE_BYTES)));
 
+#ifdef CLIB_UNIX
+  /* Ensure that the stack is aligned on the multiple of the page size */
+typedef char assert_process_stack_must_be_aligned_exactly_to_page_size_multiple
+                [(sizeof(vlib_process_t) - PAGE_SIZE_MULTIPLE) == 0 ? 0 : -1];
+#endif
+
 typedef struct {
     u32 node_index;