summaryrefslogtreecommitdiff
path: root/kernel6/源码阅读.md
diff options
context:
space:
mode:
Diffstat (limited to 'kernel6/源码阅读.md')
-rw-r--r--kernel6/源码阅读.md154
1 files changed, 154 insertions, 0 deletions
diff --git a/kernel6/源码阅读.md b/kernel6/源码阅读.md
new file mode 100644
index 0000000..4f15a58
--- /dev/null
+++ b/kernel6/源码阅读.md
@@ -0,0 +1,154 @@
+## 应用层接口
+
+```c
+unsigned int uintr_received;
+unsigned int uvec_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(uvec_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(uipi_index, 0);
+
+ return NULL;
+}
+
+int main(int argc, char *argv[])
+{
+ pthread_t pt;
+
+ if (uintr_register_handler(uintr_handler, 0)) {
+ printf("Interrupt handler register error\n");
+ exit(EXIT_FAILURE);
+ }
+
+ uvec_fd = uintr_vector_fd(0, 0);
+ if (uvec_fd < 0) {
+ printf("Interrupt vector registration error\n");
+ exit(EXIT_FAILURE);
+ }
+
+ _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(uvec_fd);
+ uintr_unregister_handler(0);
+
+ printf("Success\n");
+ exit(EXIT_SUCCESS);
+}
+```
+
+系统调用列表
+
+| 名称 | 功能 | 描述 |
+| ------------------------ | ------------------------------ | ------------------------------------ |
+| uintr_register_handler | 用户态中断 接收方 注册中断处理函数 | |
+| uintr_unregister_handler | 接收方 注销 中断处理函数 | 注销后硬件将不在记录 中断处理函数地址 |
+| uintr_vector_fd | 创建 中断向量 `vector` (封装是 文件描述符FD) | 接收方创建,传递给发送方.进入中断处理函数参数带有该值,以区分不同发送方 |
+| uintr_register_sender | 发送方 注册 `sender` 文件描述符 | |
+| uintr_unregister_sender | 注销用户态中断的发送方 | |
+| uintr_wait | | |
+| uintr_register_self() | | |
+| uintr_alt_stack | | |
+| uintr_ipi_fd | | |
+
+硬件指令
+
+- ` _clui() `- Disable user interrupts - clear UIF (User Interrupt Flag).
+- `_stui()` - enable user interrupts - set UIF.
+- `_testui()` - test current value of UIF.
+- `_uiret()` - return from a user interrupt handler.
+- `_senduipi` <uipi_index> - send a user IPI to a target task. The
+ - uipi_index is obtained using uintr_register_sender(2).
+
+## 追踪
+
+### uintr_register_handler(uintr_handler, 0)
+
+对应到 uintr.c 的 `SYSCALL_DEFINE2(uintr_register_handler, u64 __user *, handler, unsigned int, flags)`
+
+经历参数校验到了同文件下的 `do_uintr_register_handler`
+
+#### do_uintr_register_handler
+
+首先检查当前进程是否已经注册了中断处理程序,如果已经注册,则返回错误码 `-EBUSY`。
+
+分配一个 UPID 上下文结构体 `upid_ctx`,并将其保存在当前进程的 `thread` 结构体中。如果之前已经分配了 `upid_ctx`,则直接使用之前的结构体。
+
+upid 等等初始化,
+
+特别的有了 `upid_ctx->waiting_cost` 等待的代价由哪一方承担.
+
+返回
+
+## uintr_vector_fd(0, 0);
+
+匿名 inode,关联 uintrfd_ctx ,返回 uintrfd
+
+## uintr_register_sender(uvec_fd, 0);
+
+### do_uintr_register_sender
+
+uitt_ctx 被搬到了 mm_context_t 结构中 而不是原来的 thread_struct
+
+## wait
+
+uintr 的 wait 流程似乎完全不同了.
+
+等待list 还是全局的 `uintr_wait_list`
+
+```c
+static DEFINE_SPINLOCK(uintr_wait_lock);
+static struct list_head uintr_wait_list = LIST_HEAD_INIT(uintr_wait_list);
+```
+
+添加到等待列表的地方只有在 `uintr_switch_to_kernel_interrupt` 上级是 `switch_uintr_prepare` --> `arch/x86/kernel/process_64.c`:: `__switch_to`
+
+数据结构中多了一个 `upid_ctx->waiting_cost` 需要由谁承担.如果是 接收者承担才会执行 `uintr_switch_to_kernel_interrupt` 添加到等待列表.
+
+`upid_ctx->waiting_cost` 的判断还有一个调用分支, `switch_uintr_finish` 上级是 `__switch_to`::`switch_uintr_finish(next_p);`
+
+```c
+void switch_uintr_finish(struct task_struct *next)
+{
+ if (IS_ENABLED(CONFIG_X86_UINTR_BLOCKING) && // 如果开启了阻塞模式
+ is_uintr_receiver(next) && // 如果是接收者
+ is_uintr_waiting(next)) { // 如果正在等待
+ if (is_uintr_waiting_cost_sender(next)) //等待成本由发送者承担
+ uintr_clear_blocked_bit(next->thread.upid_ctx); // 清除 UINTR_UPID_STATUS_BLKD
+ else
+ uintr_remove_task_wait(next);
+ }
+}
+```
+
+这里牵扯出了 `UINTR_UPID_STATUS_BLKD` 占用了 `nc.status` 的保留位 7.