aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKimplul <kimi.h.kuparinen@gmail.com>2023-07-31 22:24:29 +0300
committerKimplul <kimi.h.kuparinen@gmail.com>2023-07-31 22:24:29 +0300
commit6ad1b899ed93f8bc110cdec7a722c8740f9f8d66 (patch)
tree99fe36028ffc4583c59e77d03bea2ade7a6c5ace
parent3212707a9ab549119ad0ad6441a07fe774c99f3b (diff)
downloadkmi-6ad1b899ed93f8bc110cdec7a722c8740f9f8d66.tar.gz
kmi-6ad1b899ed93f8bc110cdec7a722c8740f9f8d66.zip
start working on irqs
-rw-r--r--TODO1
-rw-r--r--arch/riscv64/kernel/entry.S22
-rw-r--r--arch/riscv64/kernel/irq.c66
-rw-r--r--common/ipi.c4
-rw-r--r--common/irq.c66
-rw-r--r--common/main.c2
-rw-r--r--common/panic.c24
-rw-r--r--common/timer.c2
-rw-r--r--common/uapi/dispatch.c1
-rw-r--r--common/uapi/irq.c28
-rw-r--r--common/uapi/proc.c1
-rw-r--r--include/arch/cpu.h6
-rw-r--r--include/arch/irq.h43
-rw-r--r--include/arch/proc.h2
-rw-r--r--include/kmi/caps.h3
-rw-r--r--include/kmi/ipi.h9
-rw-r--r--include/kmi/irq.h42
-rw-r--r--include/kmi/panic.h22
-rw-r--r--include/kmi/syscalls.h4
-rw-r--r--include/kmi/timer.h2
-rw-r--r--include/kmi/uapi.h134
21 files changed, 442 insertions, 42 deletions
diff --git a/TODO b/TODO
index f0265f5..9a987ed 100644
--- a/TODO
+++ b/TODO
@@ -51,6 +51,7 @@ associated program. Easy. (started)
+ Start working on proper context swaps and RPC swaps. (which thread ID should
be visible from cur_tcb() when in an RPC? should I use some kind
of effective tid instead of cur_tcb()?)
++ Export VM flags to userspace, separate header or something?
!!! FUTURE:
+ Cache locality?
diff --git a/arch/riscv64/kernel/entry.S b/arch/riscv64/kernel/entry.S
index 9d4d951..698dae7 100644
--- a/arch/riscv64/kernel/entry.S
+++ b/arch/riscv64/kernel/entry.S
@@ -62,15 +62,18 @@
sr t4, offsetof_t4(sp)
.endm
-.global handle_irq
-handle_irq:
+.global handle_trap
+handle_trap:
csrrw tp, CSR_SSCRATCH, tp
- bnez tp, continue_irq
- /* the exception came from the kernel, should probably handle but for
- * now just spin in place */
- 1: j 1b
+ bnez tp, continue_trap
+ /* the trap came from the kernel, should never happen so just panic
+ * and abort or whatever */
+ csrr a0, CSR_SEPC
+ csrr a1, CSR_STVAL
+ csrr a2, CSR_SCAUSE
+ call kernel_panic
-continue_irq:
+continue_trap:
sr sp, offsetof_tcbd(tp)
lr sp, offsetof_regs(tp)
addi sp, sp, -sizeof_registers
@@ -88,12 +91,15 @@ continue_irq:
/* load supervisor cause */
csrr t5, CSR_SCAUSE
/* interrupts fall through, exceptions jump */
+ /* (leading 1 means the value is interpreted as negative) */
bge t5, zero, handle_exception
save_regs
save_args
- /* TODO: handle interrupts */
+ mv t5, a0
+ call riscv_handle_interrupt
+
j _load_context
handle_exception:
diff --git a/arch/riscv64/kernel/irq.c b/arch/riscv64/kernel/irq.c
index 698a834..964401f 100644
--- a/arch/riscv64/kernel/irq.c
+++ b/arch/riscv64/kernel/irq.c
@@ -8,34 +8,78 @@
#include <kmi/attrs.h>
#include <kmi/debug.h>
-#include <arch/irq.h>
+#include <kmi/timer.h>
+#include <kmi/ipi.h>
+#include <kmi/irq.h>
#include "csr.h"
/** Defined in arch/riscv64/kernel/entry.S. */
-extern void handle_irq();
+extern void handle_trap();
-/** Called from arch/riscv64/kernel/entry.S. */
-void handle_sys_irq()
-{
-}
-
-void init_irq(void *fdt)
+void setup_irq(void *fdt)
{
UNUSED(fdt);
- csr_write(CSR_STVEC, &handle_irq);
+ csr_write(CSR_STVEC, &handle_trap);
long s = 0;
csr_read(CSR_SIE, s);
info("CSR_SIE: %lx\n", s);
}
+stat_t activate_irq(irq_t id)
+{
+ /** @todo implement plic */
+ return OK;
+}
+
+stat_t deactivate_irq(irq_t id)
+{
+ /** @todo implement plic */
+ return OK;
+}
+
/* very simple for now */
-void enable_irq()
+void enable_irqs()
{
csr_set(CSR_SSTATUS, CSR_SIE);
}
-void disable_irq()
+void disable_irqs()
{
csr_clear(CSR_SSTATUS, CSR_SIE);
}
+
+irq_t get_irq()
+{
+ /** @todo implement */
+ return 0;
+}
+
+/**
+ * Prints out a bug message about unknown interrupt cause.
+ *
+ * @param id ID of interrupt.
+ */
+static void riscv_unknown_interrupt(long id)
+{
+ bug("unknown interrupt: %llu\n", (unsigned long long)id);
+}
+
+/**
+ * Handle RISCV interrupt.
+ * Branches out to correct interrupt handler.
+ *
+ * @param id ID of interrupt, with interrupt bit still set.
+ */
+void riscv_handle_interrupt(long id)
+{
+ id = -id;
+
+ switch (id) {
+ /* I think */
+ case 1: handle_ipi(); break;
+ case 5: handle_timer(); break;
+ case 9: handle_irq(); break;
+ default: riscv_unknown_interrupt(id); break;
+ }
+}
diff --git a/common/ipi.c b/common/ipi.c
index a5435a3..59f9fd1 100644
--- a/common/ipi.c
+++ b/common/ipi.c
@@ -25,11 +25,11 @@ void send_ipi(struct tcb *t)
cpu_send_ipi(t->cpu_id);
}
-struct sys_ret handle_ipi(struct tcb *t)
+void handle_ipi()
{
+ struct tcb *t = cur_tcb();
adjust_ipi(t);
/** @todo use rpc stack */
set_return(t, t->callback);
- return get_args(t);
}
diff --git a/common/irq.c b/common/irq.c
new file mode 100644
index 0000000..9c538a2
--- /dev/null
+++ b/common/irq.c
@@ -0,0 +1,66 @@
+/* SPDX-License-Identifier: copyleft-next-0.3.1 */
+
+/**
+ * @file irq.c
+ * Common IRQ handling stuff implementations.
+ */
+
+#include <kmi/irq.h>
+#include <kmi/pmem.h>
+#include <kmi/debug.h>
+#include <kmi/assert.h>
+#include <kmi/string.h>
+#include <arch/irq.h>
+
+/** Hold maximum IRQ id supported by system. */
+static size_t max_irq;
+
+/** Hold map of IRD ID -> thread id. @todo process id? */
+static id_t *irq_map;
+
+void init_irq(void *fdt)
+{
+ /** @todo check arch max irq and adjust accordingly */
+ irq_map = (id_t *)alloc_page(MM_O0);
+ memset(irq_map, 0, order_size(MM_O0));
+ max_irq = order_size(MM_O0) / sizeof(irq_map[0]);
+
+ setup_irq(fdt);
+}
+
+stat_t register_irq(struct tcb *t, irq_t id)
+{
+ if (id >= max_irq)
+ return ERR_INVAL;
+
+ if (irq_map[id])
+ return ERR_EXT;
+
+ irq_map[id] = t->tid;
+ return activate_irq(id);
+}
+
+stat_t unregister_irq(struct tcb *t, irq_t id)
+{
+ id_t tid = irq_map[id];
+ if (tid != t->tid)
+ return ERR_PERM;
+
+ irq_map[id] = 0;
+ return deactivate_irq(id);
+}
+
+void handle_irq()
+{
+ irq_t id = get_irq();
+ hard_assert(id < max_irq, RETURN_VOID);
+
+ id_t tid = irq_map[id];
+
+ if (!tid) {
+ bug("unregistered irq: %llu\n", (unsigned long long)id);
+ return;
+ }
+
+ /** @todo switch to thread */
+}
diff --git a/common/main.c b/common/main.c
index 9eb6414..30d9ed5 100644
--- a/common/main.c
+++ b/common/main.c
@@ -12,9 +12,9 @@
#include <kmi/proc.h>
#include <kmi/debug.h>
#include <kmi/vmem.h>
+#include <kmi/irq.h>
#include <arch/arch.h>
#include <arch/proc.h>
-#include <arch/irq.h>
#include <libfdt.h>
/**
diff --git a/common/panic.c b/common/panic.c
new file mode 100644
index 0000000..c2b6948
--- /dev/null
+++ b/common/panic.c
@@ -0,0 +1,24 @@
+/* SPDX-License-Identifier: copyleft-next-0.3.1 */
+
+/**
+ * @file panic.c
+ * Kernel panic handler implementation.
+ */
+
+#include <kmi/power.h>
+#include <kmi/debug.h>
+
+void kernel_panic(void *pc, void *addr, long cause)
+{
+ /* could be useful to print out register values as well? */
+ error("kernel paniced at pc: %p with address %p and cause %lx\n",
+ pc, addr, cause);
+
+ info("attempting to reboot\n");
+
+ poweroff(COLD_REBOOT);
+
+ /* spin if poweroff failed for some reason */
+ error("reboot failed, spinning in place\n");
+ while (1);
+}
diff --git a/common/timer.c b/common/timer.c
index 50ec237..272ba02 100644
--- a/common/timer.c
+++ b/common/timer.c
@@ -195,7 +195,7 @@ ticks_t nsecs_to_ticks(tunit_t nsecs)
}
/* call to this function from exception handlers */
-void update_timers()
+void handle_timer()
{
struct timer *t = newest_timer();
remove_timer(t);
diff --git a/common/uapi/dispatch.c b/common/uapi/dispatch.c
index a9caa1e..5b523cc 100644
--- a/common/uapi/dispatch.c
+++ b/common/uapi/dispatch.c
@@ -76,6 +76,7 @@ void handle_syscall(sys_arg_t syscall, sys_arg_t a, sys_arg_t b,
case SYS_GET_CAP: sys_get_cap(t, a, b, c, d, e); break;
case SYS_CLEAR_CAP: sys_clear_cap(t, a, b, c, d, e); break;
case SYS_POWEROFF: sys_poweroff(t, a, b, c, d, e); break;
+ case SYS_IRQ_REQ: sys_irq_req(t, a, b, c, d, e); break;
default:
error("Syscall %zu outside allowed range [0 - %i]\n", syscall,
SYS_NUM - 1);
diff --git a/common/uapi/irq.c b/common/uapi/irq.c
new file mode 100644
index 0000000..3aa040e
--- /dev/null
+++ b/common/uapi/irq.c
@@ -0,0 +1,28 @@
+/* SPDX-License-Identifier: copyleft-next-0.3.1 */
+
+/**
+ * @file irq.c
+ * IRQ request syscall handling implementation.
+ */
+
+#include <kmi/uapi.h>
+#include <kmi/irq.h>
+
+/**
+ * Actual IRQ handling request syscall handler.
+ *
+ * @param t Current tcb.
+ * @param id IRQ id to request to handle.
+ *
+ * @return OK on success, non-zero otherwise.
+ */
+SYSCALL_DEFINE1(irq_req)(struct tcb *t, sys_arg_t id)
+{
+ if (!has_cap(t->caps, CAP_IRQ))
+ return_args1(t, ERR_PERM);
+
+ if (!t->callback)
+ return_args1(t, ERR_NF);
+
+ return_args1(t, register_irq(t, id));
+}
diff --git a/common/uapi/proc.c b/common/uapi/proc.c
index 0ec19fb..b6018b8 100644
--- a/common/uapi/proc.c
+++ b/common/uapi/proc.c
@@ -151,6 +151,7 @@ SYSCALL_DEFINE1(kill)(struct tcb *t, sys_arg_t tid)
return_args1(t, ERR_PERM);
/** @todo implement */
+ /** @todo remember to unregister IRQ handlers */
return_args1(t, OK);
}
diff --git a/include/arch/cpu.h b/include/arch/cpu.h
index d142433..1fd146e 100644
--- a/include/arch/cpu.h
+++ b/include/arch/cpu.h
@@ -1,8 +1,8 @@
/* SPDX-License-Identifier: copyleft-next-0.3.1 */
/* Copyright 2021 - 2022, Kim Kuparinen < kimi.h.kuparinen@gmail.com > */
-#ifndef KMI_CPU_H
-#define KMI_CPU_H
+#ifndef KMI_ARCH_CPU_H
+#define KMI_ARCH_CPU_H
/**
* @file cpu.h
@@ -43,4 +43,4 @@ void cpu_assign(struct tcb *t);
*/
void cpu_send_ipi(id_t cpu_id);
-#endif /* KMI_CPU_H */
+#endif /* KMI_ARCH_CPU_H */
diff --git a/include/arch/irq.h b/include/arch/irq.h
index 72b998e..85a7360 100644
--- a/include/arch/irq.h
+++ b/include/arch/irq.h
@@ -1,8 +1,11 @@
/* SPDX-License-Identifier: copyleft-next-0.3.1 */
/* Copyright 2021 - 2022, Kim Kuparinen < kimi.h.kuparinen@gmail.com > */
-#ifndef KMI_IRQ_H
-#define KMI_IRQ_H
+#ifndef KMI_ARCH_IRQ_H
+#define KMI_ARCH_IRQ_H
+
+/** Type for IRQ id. */
+typedef uint_fast32_t irq_t;
/**
* @file irq.h
@@ -19,16 +22,42 @@
#endif
/**
- * Initialize IRQ subsystem.
+ * Initialize arch-specific IRQ stuff.
*
* @param fdt Global FDT pointer.
*/
-void init_irq(void *fdt);
+void setup_irq(void *fdt);
+
+/**
+ * Activate IRQ for \p id.
+ * Assumes there's one interrupt controller for the whole system, which might be
+ * an oversimplification.
+ *
+ * @param id IRQ id to deactivate.
+ * @return OK on success, non-zero otherwise.
+ */
+stat_t activate_irq(irq_t id);
+
+/**
+ * Deactivates IRQ for \p id.
+ *
+ * @param id IRQ id to deactivate.
+ * @return OK on success, non-zero otherwise.
+ */
+stat_t deactivate_irq(irq_t id);
/** Enable IRQs. */
-void enable_irq();
+void enable_irqs();
/** Disable IRQs. */
-void disable_irq();
+void disable_irqs();
+
+/** Get IRQ to handle.
+ *
+ * @return ID of IRQ to handle.
+ *
+ * @todo what about illegal IRQs due to bug or something?
+ */
+irq_t get_irq();
-#endif /* KMI_IRQ_H */
+#endif /* KMI_ARCH_IRQ_H */
diff --git a/include/arch/proc.h b/include/arch/proc.h
index 79b099e..341a2f4 100644
--- a/include/arch/proc.h
+++ b/include/arch/proc.h
@@ -21,6 +21,8 @@
* Attach argument data to thread.
*
* @param t Thread that will run after return.
+ * @param n How many of the arguments to attach. Might micro-optimize some
+ * stuff.
* @param a Arguments to attach.
*/
void set_args(struct tcb *t, size_t n, struct sys_ret a);
diff --git a/include/kmi/caps.h b/include/kmi/caps.h
index 078dd3d..2813634 100644
--- a/include/kmi/caps.h
+++ b/include/kmi/caps.h
@@ -34,6 +34,9 @@ enum {
/** Thread is allowed to access configuration parameters. */
CAP_CONF = (1 << 4),
+
+ /** Thread is allowed to request to handle IRQs. */
+ CAP_IRQ = (1 << 5),
};
/**
diff --git a/include/kmi/ipi.h b/include/kmi/ipi.h
index 4567edb..72b54b9 100644
--- a/include/kmi/ipi.h
+++ b/include/kmi/ipi.h
@@ -29,12 +29,7 @@ bool clear_ipi(struct tcb *t);
*/
void send_ipi(struct tcb *t);
-/**
- * Handle IPI.
- *
- * @param t Thread who was interrupted by IPI.
- * @return Possible arguments to IPI.
- */
-struct sys_ret handle_ipi(struct tcb *t);
+/** Handle IPI. */
+void handle_ipi();
#endif /* KMI_IPI_H */
diff --git a/include/kmi/irq.h b/include/kmi/irq.h
new file mode 100644
index 0000000..ccc654b
--- /dev/null
+++ b/include/kmi/irq.h
@@ -0,0 +1,42 @@
+/* SPDX-License-Identifier: copyleft-next-0.3.1 */
+
+#ifndef KMI_IRQ_H
+#define KMI_IRQ_H
+
+/**
+ * @file irq.h
+ * Common IRQ handling stuff.
+ */
+
+#include <kmi/tcb.h>
+#include <arch/irq.h>
+
+/**
+ * Initialize IRQ subsystem.
+ *
+ * @param fdt Flattened device tree.
+ */
+void init_irq(void *fdt);
+
+/** Handle irq. */
+void handle_irq();
+
+/**
+ * Register IRQ with thread \p t.
+ *
+ * @param t Thread to register IRQ \p id to.
+ * @param id IRQ id to register to \p t.
+ * @return OK on success, non-zero otherwise.
+ */
+stat_t register_irq(struct tcb *t, irq_t id);
+
+/**
+ * Unregister IRQ with thread \p t.
+ *
+ * @param t Thread to unregister \p id from.
+ * @param id IRQ id to unregister from \p t.
+ * @return OK on success, non-zero otherwise.
+ */
+stat_t unregister_irq(struct tcb *t, irq_t id);
+
+#endif /* KMI_IRQ_H */
diff --git a/include/kmi/panic.h b/include/kmi/panic.h
new file mode 100644
index 0000000..44593a3
--- /dev/null
+++ b/include/kmi/panic.h
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: copyleft-next-0.3.1 */
+
+#ifndef KMI_PANIC_H
+#define KMI_PANIC_H
+
+/**
+ * @file panic.h
+ * Kernel panic handler.
+ */
+
+/**
+ * Call on kernel panic, tries to reboot the system. Failing that, spin.
+ * Ideally registers and kernel state would be printed, but keep things simple
+ * for now.
+ *
+ * @param pc Address where fault occured. Should preferably be in the kernel.
+ * @param addr Possibly associated address.
+ * @param cause Possible error code associated with panic. Page fault, etc.
+ */
+__noreturn void kernel_panic(void *pc, void *addr, long cause);
+
+#endif /* KMI_PANIC_H */
diff --git a/include/kmi/syscalls.h b/include/kmi/syscalls.h
index 8ca6546..79cd692 100644
--- a/include/kmi/syscalls.h
+++ b/include/kmi/syscalls.h
@@ -134,6 +134,10 @@ enum {
/** Shutdown, reboot, etc. */
SYS_POWEROFF,
+
+ /** Request to handle IRQ. */
+ SYS_IRQ_REQ,
+
/** @} */
SYS_NUM,
diff --git a/include/kmi/timer.h b/include/kmi/timer.h
index c0855e4..c1a07a2 100644
--- a/include/kmi/timer.h
+++ b/include/kmi/timer.h
@@ -133,4 +133,6 @@ static inline ticks_t secs_to_ticks(tunit_t secs)
return msecs_to_ticks(secs * 1000);
}
+void handle_timer();
+
#endif /* KMI_TIMER_H */
diff --git a/include/kmi/uapi.h b/include/kmi/uapi.h
index 477e315..891b5f9 100644
--- a/include/kmi/uapi.h
+++ b/include/kmi/uapi.h
@@ -796,6 +796,21 @@ SYSCALL_DECLARE3(clear_cap, tid, off, cap);
* Shouldn't return at all.
*/
SYSCALL_DECLARE1(poweroff, type);
+
+/**
+ * Request to handle IRQ.
+ *
+ * @param t Current tcb.
+ * @param id ID if IRQ to handle.
+ * @param b Unused.
+ * @param c Unused.
+ * @param d Unused.
+ * @param e Unused.
+ *
+ * Returns OK on success, non-zero otherwise.
+ * @todo document error codes better.
+ */
+SYSCALL_DECLARE1(irq_req, id);
/** @} */
/**
@@ -818,32 +833,147 @@ void handle_syscall(sys_arg_t syscall, sys_arg_t a, sys_arg_t b,
#include <arch/proc.h>
+/**
+ * Set one argument to pass to thread when returning to userspace.
+ *
+ * @param t Thread whose arguments to set.
+ * @param a First argument.
+ */
#define set_args1(t, a) set_args(t, 1, SYS_RET1(a))
+
+/**
+ * Set two arguments to pass to thread when returning to userspace.
+ *
+ * @param t Thread whose arguments to set.
+ * @param a First argument.
+ * @param b Second argument.
+ */
#define set_args2(t, a, b) set_args(t, 2, SYS_RET2(a, b))
+
+/**
+ * Set three arguments to pass to thread when returning to userspace.
+ *
+ * @param t Thread whose arguments to set.
+ * @param a First argument.
+ * @param b Second argument.
+ * @param c Third argument.
+ */
#define set_args3(t, a, b, c) set_args(t, 3, SYS_RET3(a, b, c))
+
+/**
+ * Set four arguments to pass to thread when returning to userspace.
+ *
+ * @param t Thread whose arguments to set.
+ * @param a First argument.
+ * @param b Second argument.
+ * @param c Third argument.
+ * @param d Fourth argument.
+ */
#define set_args4(t, a, b, c, d) set_args(t, 4, SYS_RET4(a, b, c, d))
+
+/**
+ * Set five arguments to pass to thread when returning to userspace.
+ *
+ * @param t Thread whose arguments to set.
+ * @param a First argument.
+ * @param b Second argument.
+ * @param c Third argument.
+ * @param d Fourth argument.
+ * @param e Fifth argument.
+ */
#define set_args5(t, a, b, c, d, e) set_args(t, 5, SYS_RET5(a, b, c, d, e))
-#define set_args6(t, a, b, c, d, e, f) set_args(t, 6, \
- SYS_RET6(a, b, c, d, e, f))
+/**
+ * Set six arguments to pass to thread when returning to userspace.
+ *
+ * @param t Thread whose arguments to set.
+ * @param a First argument.
+ * @param b Second argument.
+ * @param c Third argument.
+ * @param d Fourth argument.
+ * @param e Fifth argument.
+ * @param f Sixth argument.
+ */
+#define set_args6(t, a, b, c, d, e, f) \
+ set_args(t, 6, SYS_RET6(a, b, c, d, e, f))
+
+/**
+ * Set one argument and return from uapi function.
+ * Essentially a beauty macro and slight micro-optimization, avoiding setting
+ * registers to zero when not required.
+ *
+ * @param t Thread whose arguments to set.
+ * @param a First argument.
+ */
#define return_args1(t, a) \
{set_args1(t, a); return;}
+/**
+ * Set two arguments and return from uapi function.
+ *
+ * @param t Thread whose arguments to set.
+ * @param a First argument.
+ * @param b Second argument.
+ */
#define return_args2(t, a, b) \
{set_args2(t, a, b); return;}
+/**
+ * Set three arguments and return from uapi function.
+ *
+ * @param t Thread whose arguments to set.
+ * @param a First argument.
+ * @param b Second argument.
+ * @param c Third argument.
+ */
#define return_args3(t, a, b, c) \
{set_args3(t, a, b, c); return;}
+/**
+ * Set four arguments and return from uapi function.
+ *
+ * @param t Thread whose arguments to set.
+ * @param a First argument.
+ * @param b Second argument.
+ * @param c Third argument.
+ * @param d Fourth argument.
+ */
#define return_args4(t, a, b, c, d) \
{set_args4(t, a, b, c, d); return;}
+/**
+ * Set five arguments and return from uapi function.
+ *
+ * @param t Thread whose arguments to set.
+ * @param a First argument.
+ * @param b Second argument.
+ * @param c Third argument.
+ * @param d Fourth argument.
+ * @param e Fifth argument.
+ */
#define return_args5(t, a, b, c, d, e) \
{set_args5(t, a, b, c, d, e); return;}
+/**
+ * Set six arguments and return from uapi function.
+ *
+ * @param t Thread whose arguments to set.
+ * @param a First argument.
+ * @param b Second argument.
+ * @param c Third argument.
+ * @param d Fourth argument.
+ * @param e Fifth argument.
+ * @param f Sixth argument.
+ */
#define return_args6(t, a, b, c, d, e, f) \
{set_args6(t, a, b, c, d, e, f); return;}
+/**
+ * Set all arguments and return from uapi function.
+ *
+ * @param t Thread whose arguments to set.
+ * @param x Arguments to set.
+ */
#define return_args(t, x) {set_args((t), 6, (x)); return;}
#endif /* KMI_UAPI_H */