proc/userintr.c: added temporary fix for executing user interrupt handlers in kernel mode on RISCV64
@@ -45,7 +45,7 @@ int userintr_put(userintr_t *ui)
static int userintr_dispatch(unsigned int n, cpu_context_t *ctx, void *arg)
{
userintr_t *ui = arg;
- int ret, reschedule = 0;
+ int ret, attr, reschedule = 0;
process_t *p = NULL;
if (proc_current() != NULL)
@@ -54,17 +54,30 @@ static int userintr_dispatch(unsigned int n, cpu_context_t *ctx, void *arg)
/* Switch into the handler address space */
pmap_switch(ui->process->pmapp);
+#ifdef TARGET_RISCV64
+ /* Clear PGHD_USER attribute in interrupt handler code page (RISC-V specification forbids user code execution in kernel mode) */
+ /* Assumes that entire interrupt handler code lies within one page */
+ attr = PGHD_READ | PGHD_WRITE | PGHD_EXEC | PGHD_PRESENT;
+ pmap_enter(ui->process->pmapp, pmap_resolve(ui->process->pmapp, ui->f), (void *)((u64)ui->f & ~(SIZE_PAGE - 1)), attr, NULL);
+#endif
+
userintr_common.active = ui;
ret = ui->f(ui->handler.n, ui->arg);
userintr_common.active = NULL;
+#ifdef TARGET_RISCV64
+ /* Restore PGHD_USER attribute */
+ attr |= PGHD_USER;
+ pmap_enter(ui->process->pmapp, pmap_resolve(ui->process->pmapp, ui->f), (void *)((u64)ui->f & ~(SIZE_PAGE - 1)), attr, NULL);
+#endif
+
if (ret >= 0 && ui->cond != NULL) {
reschedule = 1;
proc_threadWakeup(&ui->cond->queue);
}
/* Restore process address space */
- if ((p != NULL) && (p->mapp != NULL))
+ if ((p != NULL) && (p->pmapp != NULL))
pmap_switch(p->pmapp);
return reschedule;
