summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSohil Mehta <[email protected]>2021-05-25 16:57:41 -0700
committerSohil Mehta <[email protected]>2021-09-12 19:22:18 -0700
commitecf00695f241969452cba62c749ce9890bacc1f0 (patch)
tree0c3513fd6e62490df0f9ff5e6224ee64aae75ffc
parent84601913d66e8995ab772ea6e9857cad2d0920f2 (diff)
!REVIEW: x86/uintr/app: Add a sample application for user IPI
Add a sample application to showcase user IPI usage. <This sample is also included in the manpage for uintr related syscalls. Eventually planning to move this to /samples.> Signed-off-by: Sohil Mehta <[email protected]>
-rw-r--r--tools/uintr/sample/Makefile22
-rw-r--r--tools/uintr/sample/README11
-rw-r--r--tools/uintr/sample/uipi_sample.c94
3 files changed, 127 insertions, 0 deletions
diff --git a/tools/uintr/sample/Makefile b/tools/uintr/sample/Makefile
new file mode 100644
index 000000000000..1f5042ba5d5d
--- /dev/null
+++ b/tools/uintr/sample/Makefile
@@ -0,0 +1,22 @@
+CC = $(CROSS_COMPILE)gcc
+BUILD_OUTPUT := $(CURDIR)
+PREFIX ?= /usr
+DESTDIR ?=
+
+ifeq ("$(origin O)", "command line")
+ BUILD_OUTPUT := $(O)
+endif
+
+uipi_sample : uipi_sample.c
+
+CFLAGS += -Wall -static -muintr -mgeneral-regs-only -minline-all-stringops
+LDFLAGS += -lpthread
+%: %.c
+ @mkdir -p $(BUILD_OUTPUT)
+ $(CC) $(CFLAGS) $< $(LDFLAGS) -o $(BUILD_OUTPUT)/$@
+
+all: uipi_sample
+
+.PHONY : clean
+clean :
+ @rm -f $(BUILD_OUTPUT)/uipi_sample
diff --git a/tools/uintr/sample/README b/tools/uintr/sample/README
new file mode 100644
index 000000000000..76f0cf77bf55
--- /dev/null
+++ b/tools/uintr/sample/README
@@ -0,0 +1,11 @@
+====Build====
+To compile this sample an updated toolchain is needed.
+- Use GCC release 11 or higher &
+- Use Binutils release 2.36 or higher
+
+====Run====
+$./uipi_sample
+Receiver enabled interrupts
+Sending IPI from sender thread
+ -- User Interrupt handler --
+Success
diff --git a/tools/uintr/sample/uipi_sample.c b/tools/uintr/sample/uipi_sample.c
new file mode 100644
index 000000000000..5f206acbc560
--- /dev/null
+++ b/tools/uintr/sample/uipi_sample.c
@@ -0,0 +1,94 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2020, Intel Corporation.
+ *
+ * Sohil Mehta <[email protected]>
+ */
+#define _GNU_SOURCE
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <syscall.h>
+#include <unistd.h>
+#include <x86gprintrin.h>
+
+#define __NR_uintr_register_handler 449
+#define __NR_uintr_unregister_handler 450
+#define __NR_uintr_create_fd 451
+#define __NR_uintr_register_sender 452
+#define __NR_uintr_unregister_sender 453
+
+/* For simiplicity, until glibc support is added */
+#define uintr_register_handler(handler, flags) syscall(__NR_uintr_register_handler, handler, flags)
+#define uintr_unregister_handler(flags) syscall(__NR_uintr_unregister_handler, flags)
+#define uintr_create_fd(vector, flags) syscall(__NR_uintr_create_fd, vector, flags)
+#define uintr_register_sender(fd, flags) syscall(__NR_uintr_register_sender, fd, flags)
+#define uintr_unregister_sender(fd, flags) syscall(__NR_uintr_unregister_sender, fd, flags)
+
+unsigned int uintr_received;
+unsigned int uintr_fd;
+
+void __attribute__ ((interrupt)) uintr_handler(struct __uintr_frame *ui_frame,
+ unsigned long long vector)
+{
+ static const char print[] = "\t-- User Interrupt handler --\n";
+
+ write(STDOUT_FILENO, print, sizeof(print) - 1);
+ uintr_received = 1;
+}
+
+void *sender_thread(void *arg)
+{
+ int uipi_index;
+
+ uipi_index = uintr_register_sender(uintr_fd, 0);
+ if (uipi_index < 0) {
+ printf("Sender register error\n");
+ exit(EXIT_FAILURE);
+ }
+
+ printf("Sending IPI from sender thread\n");
+ _senduipi(uipi_index);
+
+ uintr_unregister_sender(uintr_fd, 0);
+
+ return NULL;
+}
+
+int main(int argc, char *argv[])
+{
+ pthread_t pt;
+ int ret;
+
+ if (uintr_register_handler(uintr_handler, 0)) {
+ printf("Interrupt handler register error\n");
+ exit(EXIT_FAILURE);
+ }
+
+ ret = uintr_create_fd(0, 0);
+ if (ret < 0) {
+ printf("Interrupt vector allocation error\n");
+ exit(EXIT_FAILURE);
+ }
+
+ uintr_fd = ret;
+
+ _stui();
+ printf("Receiver enabled interrupts\n");
+
+ if (pthread_create(&pt, NULL, &sender_thread, NULL)) {
+ printf("Error creating sender thread\n");
+ exit(EXIT_FAILURE);
+ }
+
+ /* Do some other work */
+ while (!uintr_received)
+ usleep(1);
+
+ pthread_join(pt, NULL);
+ close(uintr_fd);
+ uintr_unregister_handler(0);
+
+ printf("Success\n");
+ exit(EXIT_SUCCESS);
+}