+ return 0;
+}
+
+int lttng_syscalls_register(struct lttng_channel *chan, void *filter)
+{
+ struct lttng_kernel_event ev;
+ int ret;
+
+ wrapper_vmalloc_sync_all();
+
+ if (!chan->sc_table) {
+ /* create syscall table mapping syscall to events */
+ chan->sc_table = kzalloc(sizeof(struct lttng_event *)
+ * ARRAY_SIZE(sc_table), GFP_KERNEL);
+ if (!chan->sc_table)
+ return -ENOMEM;
+ }
+ if (!chan->sc_exit_table) {
+ /* create syscall table mapping syscall to events */
+ chan->sc_exit_table = kzalloc(sizeof(struct lttng_event *)
+ * ARRAY_SIZE(sc_exit_table), GFP_KERNEL);
+ if (!chan->sc_exit_table)
+ return -ENOMEM;
+ }
+
+
+#ifdef CONFIG_COMPAT
+ if (!chan->compat_sc_table) {
+ /* create syscall table mapping compat syscall to events */
+ chan->compat_sc_table = kzalloc(sizeof(struct lttng_event *)
+ * ARRAY_SIZE(compat_sc_table), GFP_KERNEL);
+ if (!chan->compat_sc_table)
+ return -ENOMEM;
+ }
+
+ if (!chan->compat_sc_exit_table) {
+ /* create syscall table mapping compat syscall to events */
+ chan->compat_sc_exit_table = kzalloc(sizeof(struct lttng_event *)
+ * ARRAY_SIZE(compat_sc_exit_table), GFP_KERNEL);
+ if (!chan->compat_sc_exit_table)
+ return -ENOMEM;
+ }
+#endif
+ if (!chan->sc_unknown) {
+ const struct lttng_event_desc *desc =
+ &__event_desc___syscall_enter_unknown;
+
+ memset(&ev, 0, sizeof(ev));
+ strncpy(ev.name, desc->name, LTTNG_KERNEL_SYM_NAME_LEN);
+ ev.name[LTTNG_KERNEL_SYM_NAME_LEN - 1] = '\0';
+ ev.instrumentation = LTTNG_KERNEL_NOOP;
+ chan->sc_unknown = lttng_event_create(chan, &ev, filter,
+ desc);
+ WARN_ON_ONCE(!chan->sc_unknown);
+ if (IS_ERR(chan->sc_unknown)) {
+ return PTR_ERR(chan->sc_unknown);
+ }
+ }
+
+ if (!chan->sc_compat_unknown) {
+ const struct lttng_event_desc *desc =
+ &__event_desc___compat_syscall_enter_unknown;
+
+ memset(&ev, 0, sizeof(ev));
+ strncpy(ev.name, desc->name, LTTNG_KERNEL_SYM_NAME_LEN);
+ ev.name[LTTNG_KERNEL_SYM_NAME_LEN - 1] = '\0';
+ ev.instrumentation = LTTNG_KERNEL_NOOP;
+ chan->sc_compat_unknown = lttng_event_create(chan, &ev, filter,
+ desc);
+ WARN_ON_ONCE(!chan->sc_unknown);
+ if (IS_ERR(chan->sc_compat_unknown)) {
+ return PTR_ERR(chan->sc_compat_unknown);
+ }
+ }
+
+ if (!chan->compat_sc_exit_unknown) {
+ const struct lttng_event_desc *desc =
+ &__event_desc___compat_syscall_exit_unknown;
+
+ memset(&ev, 0, sizeof(ev));
+ strncpy(ev.name, desc->name, LTTNG_KERNEL_SYM_NAME_LEN);
+ ev.name[LTTNG_KERNEL_SYM_NAME_LEN - 1] = '\0';
+ ev.instrumentation = LTTNG_KERNEL_NOOP;
+ chan->compat_sc_exit_unknown = lttng_event_create(chan, &ev,
+ filter, desc);
+ WARN_ON_ONCE(!chan->compat_sc_exit_unknown);
+ if (IS_ERR(chan->compat_sc_exit_unknown)) {
+ return PTR_ERR(chan->compat_sc_exit_unknown);
+ }
+ }
+
+ if (!chan->sc_exit_unknown) {
+ const struct lttng_event_desc *desc =
+ &__event_desc___syscall_exit_unknown;
+
+ memset(&ev, 0, sizeof(ev));
+ strncpy(ev.name, desc->name, LTTNG_KERNEL_SYM_NAME_LEN);
+ ev.name[LTTNG_KERNEL_SYM_NAME_LEN - 1] = '\0';
+ ev.instrumentation = LTTNG_KERNEL_NOOP;
+ chan->sc_exit_unknown = lttng_event_create(chan, &ev, filter,
+ desc);
+ WARN_ON_ONCE(!chan->sc_exit_unknown);
+ if (IS_ERR(chan->sc_exit_unknown)) {
+ return PTR_ERR(chan->sc_exit_unknown);
+ }
+ }
+
+ ret = fill_table(sc_table, ARRAY_SIZE(sc_table),
+ chan->sc_table, chan, filter, SC_TYPE_ENTRY);
+ if (ret)
+ return ret;
+ ret = fill_table(sc_exit_table, ARRAY_SIZE(sc_exit_table),
+ chan->sc_exit_table, chan, filter, SC_TYPE_EXIT);
+ if (ret)
+ return ret;
+
+#ifdef CONFIG_COMPAT
+ ret = fill_table(compat_sc_table, ARRAY_SIZE(compat_sc_table),
+ chan->compat_sc_table, chan, filter,
+ SC_TYPE_COMPAT_ENTRY);
+ if (ret)
+ return ret;
+ ret = fill_table(compat_sc_exit_table, ARRAY_SIZE(compat_sc_exit_table),
+ chan->compat_sc_exit_table, chan, filter,
+ SC_TYPE_COMPAT_EXIT);
+ if (ret)
+ return ret;
+#endif
+ if (!chan->sys_enter_registered) {
+ ret = lttng_wrapper_tracepoint_probe_register("sys_enter",
+ (void *) syscall_entry_probe, chan);
+ if (ret)
+ return ret;
+ chan->sys_enter_registered = 1;
+ }
+ /*
+ * We change the name of sys_exit tracepoint due to namespace
+ * conflict with sys_exit syscall entry.
+ */
+ if (!chan->sys_exit_registered) {
+ ret = lttng_wrapper_tracepoint_probe_register("sys_exit",
+ (void *) syscall_exit_probe, chan);
+ if (ret) {
+ WARN_ON_ONCE(lttng_wrapper_tracepoint_probe_unregister("sys_enter",
+ (void *) syscall_entry_probe, chan));
+ return ret;
+ }
+ chan->sys_exit_registered = 1;
+ }