int are_tcbs_distinct(seL4_CPtr tcb1, seL4_CPtr tcb2) { int error, i; seL4_UserContext regs; /* Initialise regs to prevent compiler warning. */ error = seL4_TCB_ReadRegisters(tcb1, 0, 0, 1, ®s); if (error) { return error; } for (i = 0; i < 2; ++i) { sel4utils_set_instruction_pointer(®s, i); error = seL4_TCB_WriteRegisters(tcb1, 0, 0, 1, ®s); /* Check that we had permission to do that and the cap was a TCB. */ if (error) { return error; } error = seL4_TCB_ReadRegisters(tcb2, 0, 0, 1, ®s); /* Check that we had permission to do that and the cap was a TCB. */ if (error) { return error; } else if (sel4utils_get_instruction_pointer(regs) != i) { return 1; } } return 0; }
int /*? me.interface.name ?*/__run(void) { // Make connection to gdb seL4_Word delegate_tcb; seL4_UserContext regs; while (1) { seL4_Recv(/*? mem_ep ?*/, &delegate_tcb); seL4_TCB_ReadRegisters(delegate_tcb, false, 0, sizeof(seL4_UserContext) / sizeof(seL4_Word), ®s); // Check eax is 0 so that we know they were checking memory // TODO Add a check on pc to see if they were in the mem check function if (regs.eax == 0) { // Signal to the delegate the memory is invalid regs.eax = 1; // Increment past the faulting instruction regs.eip += 2; // Write registers back seL4_TCB_WriteRegisters(delegate_tcb, false, 0, sizeof(seL4_UserContext) / sizeof(seL4_Word), ®s); // Resume the caller seL4_MessageInfo_t info = seL4_MessageInfo_new(0, 0, 0, 1); seL4_SetMR(0, regs.eip); seL4_Reply(info); } } }
static int handle_exception(vm_t* vm, seL4_Word ip) { seL4_UserContext regs; seL4_CPtr tcb = vm_get_tcb(vm); int err; printf("%sInvalid instruction from [%s] at PC: 0x"XFMT"%s\n", CERROR, vm->name, seL4_GetMR(0), CNORMAL); err = seL4_TCB_ReadRegisters(tcb, false, 0, sizeof(regs) / sizeof(regs.pc), ®s); assert(!err); print_ctx_regs(®s); return 1; }
int vm_set_bootargs(vm_t* vm, void* pc, uint32_t mach_type, uint32_t atags) { seL4_UserContext regs; seL4_CPtr tcb; int err; assert(vm); /* Write CPU registers */ tcb = vm_get_tcb(vm); err = seL4_TCB_ReadRegisters(tcb, false, 0, sizeof(regs) / sizeof(regs.pc), ®s); assert(!err); regs.r0 = 0; regs.r1 = mach_type; regs.r2 = atags; regs.pc = (seL4_Word)pc; regs.cpsr = MODE_SUPERVISOR; err = seL4_TCB_WriteRegisters(tcb, false, 0, sizeof(regs) / sizeof(regs.pc), ®s); assert(!err); return err; }
static int handle_syscall(vm_t* vm, seL4_Word length) { seL4_Word syscall, ip; seL4_UserContext regs; seL4_CPtr tcb; int err; syscall = seL4_GetMR(EXCEPT_IPC_SYS_MR_SYSCALL), ip = seL4_GetMR(EXCEPT_IPC_SYS_MR_PC); tcb = vm_get_tcb(vm); err = seL4_TCB_ReadRegisters(tcb, false, 0, sizeof(regs) / sizeof(regs.pc), ®s); assert(!err); regs.pc += 4; DSTRACE("Syscall %d from [%s]\n", syscall, vm->name); switch (syscall) { case 65: sys_pa_to_ipa(vm, ®s); break; case 66: sys_ipa_to_pa(vm, ®s); break; case 67: sys_nop(vm, ®s); break; default: printf("%sBad syscall from [%s]: scno "DFMT" at PC: 0x"XFMT"%s\n", CERROR, vm->name, syscall, ip, CNORMAL); return -1; } err = seL4_TCB_WriteRegisters(tcb, false, 0, sizeof(regs) / sizeof(regs.pc), ®s); assert(!err); return 0; }
int vm_event(vm_t* vm, seL4_MessageInfo_t tag) { seL4_Word label; seL4_Word length; label = seL4_MessageInfo_get_label(tag); length = seL4_MessageInfo_get_length(tag); switch (label) { case SEL4_PFIPC_LABEL: { int err; fault_t* fault; fault = vm->fault; err = new_fault(fault); assert(!err); do { err = handle_page_fault(vm, fault); if (err) { return -1; } } while (!fault_handled(fault)); } break; case SEL4_EXCEPT_IPC_LABEL: { int err; assert(length == SEL4_EXCEPT_IPC_LENGTH); err = handle_syscall(vm, length); assert(!err); if (!err) { seL4_MessageInfo_t reply; reply = seL4_MessageInfo_new(0, 0, 0, 0); seL4_Reply(reply); } } break; case SEL4_USER_EXCEPTION_LABEL: { seL4_Word ip; int err; assert(length == SEL4_USER_EXCEPTION_LENGTH); ip = seL4_GetMR(0); err = handle_exception(vm, ip); assert(!err); if (!err) { seL4_MessageInfo_t reply; reply = seL4_MessageInfo_new(0, 0, 0, 0); seL4_Reply(reply); } } break; case SEL4_VGIC_MAINTENANCE_LABEL: { int idx; int err; assert(length == SEL4_VGIC_MAINTENANCE_LENGTH); idx = seL4_GetMR(EXCEPT_IPC_SYS_MR_R0); /* Currently not handling spurious IRQs */ assert(idx >= 0); err = handle_vgic_maintenance(vm, idx); assert(!err); if (!err) { seL4_MessageInfo_t reply; reply = seL4_MessageInfo_new(0, 0, 0, 0); seL4_Reply(reply); } } break; case SEL4_VCPU_FAULT_LABEL: { seL4_MessageInfo_t reply; seL4_UserContext regs; seL4_CPtr tcb; uint32_t hsr; int err; assert(length == SEL4_VCPU_FAULT_LENGTH); hsr = seL4_GetMR(EXCEPT_IPC_SYS_MR_R0); /* Increment the PC and ignore the fault */ tcb = vm_get_tcb(vm); err = seL4_TCB_ReadRegisters(tcb, false, 0, sizeof(regs) / sizeof(regs.pc), ®s); assert(!err); switch (hsr) { case HSR_WFI: case HSR_WFE: regs.pc += (regs.cpsr & BIT(5)) ? 2 : 4; err = seL4_TCB_WriteRegisters(tcb, false, 0, sizeof(regs) / sizeof(regs.pc), ®s); assert(!err); reply = seL4_MessageInfo_new(0, 0, 0, 0); seL4_Reply(reply); return 0; default: printf("Unhandled VCPU fault from [%s]: HSR 0x%08x\n", vm->name, hsr); print_ctx_regs(®s); return -1; } } break; default: /* What? Why are we here? What just happened? */ printf("Unknown fault from [%s]: label=0x%x length=0x%x\n", vm->name, label, length); return -1; } return 0; }