diff options
| author | Sohil Mehta <[email protected]> | 2021-05-25 16:57:41 -0700 |
|---|---|---|
| committer | Sohil Mehta <[email protected]> | 2021-09-12 19:22:18 -0700 |
| commit | ecf00695f241969452cba62c749ce9890bacc1f0 (patch) | |
| tree | 0c3513fd6e62490df0f9ff5e6224ee64aae75ffc | |
| parent | 84601913d66e8995ab772ea6e9857cad2d0920f2 (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/Makefile | 22 | ||||
| -rw-r--r-- | tools/uintr/sample/README | 11 | ||||
| -rw-r--r-- | tools/uintr/sample/uipi_sample.c | 94 |
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); +} |
