|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Minios-devel] [UNIKRAFT PATCH 2/7] plat/linuxu: Add linuxu (x86_64) interrupts support
We use signals to emulate the behavior of interrupts on plat/linuxu.
Signed-off-by: Costin Lupu <costin.lupu@xxxxxxxxx>
---
plat/linuxu/Makefile.uk | 2 +
plat/linuxu/include/linuxu/irq.h | 50 ++++++++
plat/linuxu/include/linuxu/signal.h | 151 ++++++++++++++++++++++++
plat/linuxu/include/linuxu/syscall-x86_64.h | 4 +
plat/linuxu/include/linuxu/syscall.h | 24 +++-
plat/linuxu/irq.c | 176 ++++++++++++++++++++++++++++
plat/linuxu/lcpu.c | 63 +++++++---
7 files changed, 454 insertions(+), 16 deletions(-)
create mode 100644 plat/linuxu/include/linuxu/irq.h
create mode 100644 plat/linuxu/include/linuxu/signal.h
create mode 100644 plat/linuxu/irq.c
diff --git a/plat/linuxu/Makefile.uk b/plat/linuxu/Makefile.uk
index 38f92ac..8f07cb3 100644
--- a/plat/linuxu/Makefile.uk
+++ b/plat/linuxu/Makefile.uk
@@ -12,6 +12,7 @@ $(eval $(call addplatlib,linuxu,liblinuxuplat))
## Platform library definitions
##
LIBLINUXUPLAT_CINCLUDES-y += -I$(LIBLINUXUPLAT_BASE)/include
+LIBLINUXUPLAT_CINCLUDES-y += -I$(UK_PLAT_COMMON_BASE)/include
LIBLINUXUPLAT_SRCS-$(ARCH_X86_32) += $(LIBLINUXUPLAT_BASE)/x86/entry32.S
LIBLINUXUPLAT_SRCS-$(ARCH_X86_64) += $(LIBLINUXUPLAT_BASE)/x86/entry64.S
@@ -22,4 +23,5 @@ LIBLINUXUPLAT_SRCS-y +=
$(LIBLINUXUPLAT_BASE)/console.c
LIBLINUXUPLAT_SRCS-y += $(LIBLINUXUPLAT_BASE)/shutdown.c
LIBLINUXUPLAT_SRCS-y += $(LIBLINUXUPLAT_BASE)/memory.c
LIBLINUXUPLAT_SRCS-y += $(LIBLINUXUPLAT_BASE)/lcpu.c
+LIBLINUXUPLAT_SRCS-y += $(LIBLINUXUPLAT_BASE)/irq.c
LIBLINUXUPLAT_SRCS-y += $(LIBLINUXUPLAT_BASE)/time.c
diff --git a/plat/linuxu/include/linuxu/irq.h b/plat/linuxu/include/linuxu/irq.h
new file mode 100644
index 0000000..d1b1c5e
--- /dev/null
+++ b/plat/linuxu/include/linuxu/irq.h
@@ -0,0 +1,50 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+/*
+ * Authors: Costin Lupu <costin.lupu@xxxxxxxxx>
+ *
+ * Copyright (c) 2018, NEC Europe Ltd., NEC Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holder nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * THIS HEADER MAY NOT BE EXTRACTED OR MODIFIED IN ANY WAY.
+ */
+
+#ifndef __IRQ_H__
+#define __IRQ_H__
+
+void irq_enable(void);
+void irq_disable(void);
+int irq_disabled(void);
+
+unsigned long irq_save(void);
+void irq_restore(unsigned long flags);
+
+typedef int (*irq_handler_func_t)(void *arg);
+
+void irq_register(int irq, irq_handler_func_t func, void *arg);
+void irq_handle(int irq);
+
+#endif /* __IRQ_H__ */
diff --git a/plat/linuxu/include/linuxu/signal.h
b/plat/linuxu/include/linuxu/signal.h
new file mode 100644
index 0000000..f46ce4e
--- /dev/null
+++ b/plat/linuxu/include/linuxu/signal.h
@@ -0,0 +1,151 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+/*
+ * Authors: Costin Lupu <costin.lupu@xxxxxxxxx>
+ *
+ * Copyright (c) 2018, NEC Europe Ltd., NEC Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holder nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * THIS HEADER MAY NOT BE EXTRACTED OR MODIFIED IN ANY WAY.
+ */
+#ifndef __SIGNAL_H__
+#define __SIGNAL_H__
+
+/* Signal numbers */
+#define SIGALRM 14
+
+
+/* sigaction */
+
+typedef void (*uk_sighandler_t)(int);
+typedef void (*uk_sigrestore_t)(void);
+
+struct uk_sigaction {
+ uk_sighandler_t sa_handler;
+ int sa_flags;
+ uk_sigrestore_t sa_restorer;
+ sigset_t sa_mask;
+};
+
+/* sigaction flags */
+#define SA_SIGINFO 0x00000004
+#define SA_RESTORER 0x04000000
+
+
+/* Signal enabling/disabling definitions (sigprocmask) */
+#ifndef SIG_BLOCK
+#define SIG_BLOCK 0
+#endif
+#ifndef SIG_UNBLOCK
+#define SIG_UNBLOCK 1
+#endif
+#ifndef SIG_SETMASK
+#define SIG_SETMASK 2
+#endif
+
+/* sigset utils */
+#define SIGSET_WORDS_NUM (sizeof(sigset_t) / sizeof(unsigned long int))
+
+#define sigemptyset(set) \
+ ({ \
+ unsigned int __count = 0; \
+ unsigned long int *__set = (set); \
+ while (__count++ < SIGSET_WORDS_NUM) \
+ *__set++ = 0; \
+ 0; \
+ })
+
+#define sigfillset(set) \
+ ({ \
+ unsigned int __count = 0; \
+ unsigned long int *__set = (set); \
+ while (__count++ < SIGSET_WORDS_NUM) \
+ *__set++ = ~0UL; \
+ 0; \
+ })
+
+#define sigisemptyset(set) \
+ ({ \
+ unsigned int __count = 0; \
+ const unsigned long int *__set = (set); \
+ int __ret = __set[__count++]; \
+ while (!__ret && __count < SIGSET_WORDS_NUM) \
+ __ret = __set[__count++]; \
+ __ret == 0; \
+ })
+
+
+#define sig_word_idx(sig) \
+ (((sig) - 1) / (8 * sizeof (unsigned long int)))
+
+#define sig_word_mask(sig) \
+ (((unsigned long int) 1) << (((sig) - 1) % (8 * sizeof (unsigned long
int))))
+
+
+#define sigaddset(set, sig) \
+ ({ \
+ unsigned long int __word = sig_word_idx(sig); \
+ unsigned long int __mask = sig_word_mask(sig); \
+ unsigned long int *__set = (set); \
+ __set[__word] |= __mask; \
+ 0; \
+ })
+
+#define sigdelset(set, sig) \
+ ({ \
+ unsigned long int __word = sig_word_idx(sig); \
+ unsigned long int __mask = sig_word_mask(sig); \
+ unsigned long int *__set = (set); \
+ __set[__word] &= ~__mask; \
+ 0; \
+ })
+
+#define sigismember(set, sig) \
+ ({ \
+ unsigned long int __word = sig_word_idx(sig); \
+ unsigned long int __mask = sig_word_mask(sig); \
+ unsigned long int *__set = (set); \
+ __set[__word] & __mask ? 1 : 0; \
+ })
+
+
+/* Signal event definitions */
+typedef union uk_sigval {
+ int sival_int;
+ void *sival_ptr;
+} uk_sigval_t;
+
+typedef struct uk_sigevent {
+ uk_sigval_t sigev_value;
+ int sigev_signo;
+ int sigev_notify;
+
+ /* We aren't interested now in what follows here */
+ int pad[64];
+
+} uk_sigevent_t;
+
+#endif /* __SIGNAL_H__ */
diff --git a/plat/linuxu/include/linuxu/syscall-x86_64.h
b/plat/linuxu/include/linuxu/syscall-x86_64.h
index c3c4550..5622921 100644
--- a/plat/linuxu/include/linuxu/syscall-x86_64.h
+++ b/plat/linuxu/include/linuxu/syscall-x86_64.h
@@ -46,6 +46,10 @@
#define __SC_MUNMAP 11
#define __SC_IOCTL 16
#define __SC_EXIT 60
+
+#define __SC_RT_SIGACTION 13
+#define __SC_RT_SIGPROCMASK 14
+
#define __SC_PSELECT6 270
/* NOTE: from linux-4.6.3 (arch/x86/entry/entry_64.S):
diff --git a/plat/linuxu/include/linuxu/syscall.h
b/plat/linuxu/include/linuxu/syscall.h
index 1b0a3bc..2f4125b 100644
--- a/plat/linuxu/include/linuxu/syscall.h
+++ b/plat/linuxu/include/linuxu/syscall.h
@@ -37,8 +37,7 @@
#define __SYSCALL_H__
#include <sys/types.h>
-#include <sys/select.h>
-#include <sys/time.h>
+#include <linuxu/signal.h>
#if defined __X86_64__
#include <linuxu/syscall-x86_64.h>
@@ -95,6 +94,27 @@ static inline void *sys_mmap(void *addr, size_t len, int
prot, int flags,
sys_mmap((addr), (len), (PROT_READ | PROT_WRITE), \
(MAP_SHARED | MAP_ANONYMOUS), -1, 0)
+
+static inline int sys_sigaction(int signum,
+ const struct uk_sigaction *action, struct uk_sigaction
*oldaction)
+{
+ return (int) syscall4(__SC_RT_SIGACTION,
+ (long) signum,
+ (long) action,
+ (long) oldaction,
+ sizeof(sigset_t));
+}
+
+static inline int sys_sigprocmask(int how,
+ const sigset_t *set, sigset_t *oldset)
+{
+ return (int) syscall4(__SC_RT_SIGPROCMASK,
+ (long) how,
+ (long) set,
+ (long) oldset,
+ sizeof(sigset_t));
+}
+
static inline int sys_pselect6(int nfds,
fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
const struct timespec *timeout, const void *sigmask)
diff --git a/plat/linuxu/irq.c b/plat/linuxu/irq.c
new file mode 100644
index 0000000..4dbdd20
--- /dev/null
+++ b/plat/linuxu/irq.c
@@ -0,0 +1,176 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+/*
+ * Authors: Costin Lupu <costin.lupu@xxxxxxxxx>
+ *
+ * Copyright (c) 2018, NEC Europe Ltd., NEC Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holder nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * THIS HEADER MAY NOT BE EXTRACTED OR MODIFIED IN ANY WAY.
+ */
+#include <stdlib.h>
+#include <uk/alloc.h>
+#include <uk/list.h>
+#include <uk/plat/lcpu.h>
+#include <linuxu/irq.h>
+#include <linuxu/syscall.h>
+#include <linuxu/signal.h>
+#include <linuxu/assert.h>
+
+#define IRQS_NUM 16
+
+/* IRQ handlers declarations */
+struct irq_handler {
+ irq_handler_func_t func;
+ void *arg;
+
+ struct uk_sigaction oldaction;
+
+ UK_SLIST_ENTRY(struct irq_handler) entries;
+};
+
+UK_SLIST_HEAD(irq_handler_head, struct irq_handler);
+static struct irq_handler_head irq_handlers[IRQS_NUM];
+
+static struct uk_alloc *allocator;
+static sigset_t handled_signals_set;
+static unsigned long irq_enabled = 0;
+
+
+void irq_enable(void)
+{
+ int rc;
+
+ rc = sys_sigprocmask(SIG_UNBLOCK, &handled_signals_set, NULL);
+ LINUXU_ASSERT(rc, 0);
+
+ irq_enabled = 1;
+}
+
+void irq_disable(void)
+{
+ int rc;
+
+ rc = sys_sigprocmask(SIG_BLOCK, &handled_signals_set, NULL);
+ LINUXU_ASSERT(rc, 0);
+
+ irq_enabled = 0;
+}
+
+int irq_disabled(void)
+{
+ return (irq_enabled == 0);
+}
+
+unsigned long irq_save(void)
+{
+ unsigned long flags = irq_enabled;
+
+ if (irq_enabled)
+ irq_disable();
+
+ return flags;
+}
+
+void irq_restore(unsigned long flags)
+{
+ if (flags) {
+ if (!irq_enabled)
+ irq_enable();
+
+ } else if (irq_enabled)
+ irq_disable();
+}
+
+void __restorer();
+asm("__restorer:mov $15,%rax\nsyscall");
+
+void irq_register(int irq, irq_handler_func_t func, void *arg)
+{
+ struct irq_handler *h;
+ struct uk_sigaction action;
+ sigset_t set;
+ unsigned long flags;
+ int rc;
+
+ UK_ASSERT(irq < IRQS_NUM);
+
+ /* New handler */
+ h = uk_malloc(allocator, sizeof(struct irq_handler));
+ UK_ASSERT(h != NULL);
+ h->func = func;
+ h->arg = arg;
+
+ /* Register signal action */
+ memset(&action, 0, sizeof(action));
+ action.sa_handler = irq_handle;
+ action.sa_flags = SA_RESTORER;
+ action.sa_restorer = __restorer;
+
+ rc = sys_sigaction(irq, &action, &h->oldaction);
+ LINUXU_ASSERT(rc, 0);
+
+ flags = ukplat_lcpu_save_irqf();
+ UK_SLIST_INSERT_HEAD(&irq_handlers[irq], h, entries);
+ ukplat_lcpu_restore_irqf(flags);
+
+ /* Unblock the signal */
+ sigemptyset(&set);
+ sigaddset(&set, irq);
+
+ rc = sys_sigprocmask(SIG_UNBLOCK, &set, NULL);
+ LINUXU_ASSERT(rc, 0);
+
+ /* Add to our handled signals set */
+ sigaddset(&handled_signals_set, irq);
+}
+
+void irq_handle(int irq)
+{
+ struct irq_handler *h;
+ int handled = 0;
+
+ UK_SLIST_FOREACH(h, &irq_handlers[irq], entries) {
+ if (h->func(h->arg) == 1) {
+ handled = 1;
+ break;
+ }
+ }
+
+ if (!handled)
+ UK_CRASH("Unhandled irq=%d\n", irq);
+}
+
+int ukplat_irq_init(struct uk_alloc *a)
+{
+ UK_ASSERT(irq_enabled == 0);
+ UK_ASSERT(allocator == NULL);
+
+ allocator = a;
+ sigemptyset(&handled_signals_set);
+
+ return 0;
+}
diff --git a/plat/linuxu/lcpu.c b/plat/linuxu/lcpu.c
index 42f5690..52ce23d 100644
--- a/plat/linuxu/lcpu.c
+++ b/plat/linuxu/lcpu.c
@@ -33,11 +33,48 @@
*/
#include <stdlib.h>
+#include <uk/plat/lcpu.h>
+#include <_time.h>
#include <linuxu/syscall.h>
+#include <linuxu/irq.h>
#include <uk/print.h>
-#include <uk/plat/lcpu.h>
-void ukplat_lcpu_halt(void)
+
+void ukplat_lcpu_enable_irq(void)
+{
+ irq_enable();
+}
+
+void ukplat_lcpu_disable_irq(void)
+{
+ irq_disable();
+}
+
+unsigned long ukplat_lcpu_save_irqf(void)
+{
+ unsigned long flags;
+
+ flags = irq_save();
+
+ return flags;
+}
+
+void ukplat_lcpu_restore_irqf(unsigned long flags)
+{
+ irq_restore(flags);
+}
+
+int ukplat_lcpu_irqs_disabled(void)
+{
+ return irq_disabled();
+}
+
+void ukplat_lcpu_irqs_handle_pending(void)
+{
+
+}
+
+static void do_pselect(struct timespec *timeout)
{
int ret;
int nfds = 0;
@@ -45,24 +82,22 @@ void ukplat_lcpu_halt(void)
fd_set *writefds = NULL;
fd_set *exceptfds = NULL;
- ret = sys_pselect6(nfds, readfds, writefds, exceptfds, NULL, NULL);
+ ret = sys_pselect6(nfds, readfds, writefds, exceptfds, timeout, NULL);
if (ret < 0)
uk_printd(DLVL_WARN, "Failed to halt LCPU: %d\n", ret);
}
-void ukplat_lcpu_halt_to(unsigned long millis)
+void halt(void)
+{
+ do_pselect(NULL);
+}
+
+void time_block_until(__snsec until)
{
- int ret;
- int nfds = 0;
- fd_set *readfds = NULL;
- fd_set *writefds = NULL;
- fd_set *exceptfds = NULL;
struct timespec timeout;
- timeout.tv_sec = millis / 1000;
- timeout.tv_nsec = millis % 1000 * 1000000;
+ timeout.tv_sec = until / ukarch_time_sec_to_nsec(1);
+ timeout.tv_nsec = until % ukarch_time_sec_to_nsec(1);
- ret = sys_pselect6(nfds, readfds, writefds, exceptfds, &timeout, NULL);
- if (ret < 0)
- uk_printd(DLVL_WARN, "Failed to halt LCPU: %d\n", ret);
+ do_pselect(&timeout);
}
--
2.1.4
_______________________________________________
Minios-devel mailing list
Minios-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/minios-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |