Skip to content

Commit

Permalink
Style src/arch/aarch64/fault.c
Browse files Browse the repository at this point in the history
Signed-off-by: Ivan Velickovic <[email protected]>
  • Loading branch information
Ivan-Velickovic committed Sep 3, 2024
1 parent 5315476 commit 66781ec
Showing 1 changed file with 162 additions and 116 deletions.
278 changes: 162 additions & 116 deletions src/arch/aarch64/fault.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@
// return !CPSR_IS_THUMB(regs->spsr);
// }

bool fault_advance_vcpu(size_t vcpu_id, seL4_UserContext *regs) {
bool fault_advance_vcpu(size_t vcpu_id, seL4_UserContext *regs)
{
// For now we just ignore it and continue
// Assume 32-bit instruction
regs->pc += 4;
Expand All @@ -32,15 +33,23 @@ bool fault_advance_vcpu(size_t vcpu_id, seL4_UserContext *regs) {
return (err == seL4_NoError);
}

char *fault_to_string(seL4_Word fault_label) {
char *fault_to_string(seL4_Word fault_label)
{
switch (fault_label) {
case seL4_Fault_VMFault: return "virtual memory";
case seL4_Fault_UnknownSyscall: return "unknown syscall";
case seL4_Fault_UserException: return "user exception";
case seL4_Fault_VGICMaintenance: return "VGIC maintenance";
case seL4_Fault_VCPUFault: return "VCPU";
case seL4_Fault_VPPIEvent: return "VPPI event";
default: return "unknown fault";
case seL4_Fault_VMFault:
return "virtual memory";
case seL4_Fault_UnknownSyscall:
return "unknown syscall";
case seL4_Fault_UserException:
return "user exception";
case seL4_Fault_VGICMaintenance:
return "VGIC maintenance";
case seL4_Fault_VCPUFault:
return "VCPU";
case seL4_Fault_VPPIEvent:
return "VPPI event";
default:
return "unknown fault";
}
}

Expand All @@ -59,7 +68,7 @@ enum fault_width {
static enum fault_width fault_get_width(uint64_t fsr)
{
if (HSR_IS_SYNDROME_VALID(fsr) && HSR_SYNDROME_WIDTH(fsr) <= WIDTH_DOUBLEWORD) {
return (enum fault_width) (HSR_SYNDROME_WIDTH(fsr));
return (enum fault_width)(HSR_SYNDROME_WIDTH(fsr));
} else {
LOG_VMM_ERR("Received invalid FSR: 0x%lx\n", fsr);
// @ivanv: reviist
Expand All @@ -74,26 +83,26 @@ uint64_t fault_get_data_mask(uint64_t addr, uint64_t fsr)
{
uint64_t mask = 0;
switch (fault_get_width(fsr)) {
case WIDTH_BYTE:
mask = 0x000000ff;
assert(!(addr & 0x0));
break;
case WIDTH_HALFWORD:
mask = 0x0000ffff;
assert(!(addr & 0x1));
break;
case WIDTH_WORD:
mask = 0xffffffff;
assert(!(addr & 0x3));
break;
case WIDTH_DOUBLEWORD:
mask = ~mask;
break;
default:
LOG_VMM_ERR("unknown width: 0x%lx, from FSR: 0x%lx, addr: 0x%lx\n",
fault_get_width(fsr), fsr, addr);
assert(0);
return 0;
case WIDTH_BYTE:
mask = 0x000000ff;
assert(!(addr & 0x0));
break;
case WIDTH_HALFWORD:
mask = 0x0000ffff;
assert(!(addr & 0x1));
break;
case WIDTH_WORD:
mask = 0xffffffff;
assert(!(addr & 0x3));
break;
case WIDTH_DOUBLEWORD:
mask = ~mask;
break;
default:
LOG_VMM_ERR("unknown width: 0x%lx, from FSR: 0x%lx, addr: 0x%lx\n",
fault_get_width(fsr), fsr, addr);
assert(0);
return 0;
}
mask <<= (addr & 0x3) * 8;
return mask;
Expand All @@ -108,41 +117,73 @@ seL4_Word *decode_rt(size_t reg_idx, seL4_UserContext *regs)
* encodes the Syndrome Register transfer.
*/
switch (reg_idx) {
case 0: return &regs->x0;
case 1: return &regs->x1;
case 2: return &regs->x2;
case 3: return &regs->x3;
case 4: return &regs->x4;
case 5: return &regs->x5;
case 6: return &regs->x6;
case 7: return &regs->x7;
case 8: return &regs->x8;
case 9: return &regs->x9;
case 10: return &regs->x10;
case 11: return &regs->x11;
case 12: return &regs->x12;
case 13: return &regs->x13;
case 14: return &regs->x14;
case 15: return &regs->x15;
case 16: return &regs->x16;
case 17: return &regs->x17;
case 18: return &regs->x18;
case 19: return &regs->x19;
case 20: return &regs->x20;
case 21: return &regs->x21;
case 22: return &regs->x22;
case 23: return &regs->x23;
case 24: return &regs->x24;
case 25: return &regs->x25;
case 26: return &regs->x26;
case 27: return &regs->x27;
case 28: return &regs->x28;
case 29: return &regs->x29;
case 30: return &regs->x30;
case 31: return &wzr;
default:
LOG_VMM_ERR("failed to decode Rt, attempted to access invalid register index 0x%lx\n", reg_idx);
return NULL;
case 0:
return &regs->x0;
case 1:
return &regs->x1;
case 2:
return &regs->x2;
case 3:
return &regs->x3;
case 4:
return &regs->x4;
case 5:
return &regs->x5;
case 6:
return &regs->x6;
case 7:
return &regs->x7;
case 8:
return &regs->x8;
case 9:
return &regs->x9;
case 10:
return &regs->x10;
case 11:
return &regs->x11;
case 12:
return &regs->x12;
case 13:
return &regs->x13;
case 14:
return &regs->x14;
case 15:
return &regs->x15;
case 16:
return &regs->x16;
case 17:
return &regs->x17;
case 18:
return &regs->x18;
case 19:
return &regs->x19;
case 20:
return &regs->x20;
case 21:
return &regs->x21;
case 22:
return &regs->x22;
case 23:
return &regs->x23;
case 24:
return &regs->x24;
case 25:
return &regs->x25;
case 26:
return &regs->x26;
case 27:
return &regs->x27;
case 28:
return &regs->x28;
case 29:
return &regs->x29;
case 30:
return &regs->x30;
case 31:
return &wzr;
default:
LOG_VMM_ERR("failed to decode Rt, attempted to access invalid register index 0x%lx\n", reg_idx);
return NULL;
}
}

Expand Down Expand Up @@ -195,7 +236,8 @@ uint64_t fault_emulate(seL4_UserContext *regs, uint64_t reg, uint64_t addr, uint
}
}

void fault_emulate_write(seL4_UserContext *regs, size_t addr, size_t fsr, size_t reg_val) {
void fault_emulate_write(seL4_UserContext *regs, size_t addr, size_t fsr, size_t reg_val)
{
// @ivanv: audit
/* Get register opearand */
int rt = get_rt(fsr);
Expand All @@ -219,14 +261,14 @@ bool fault_handle_vcpu_exception(size_t vcpu_id)
uint32_t hsr = microkit_mr_get(seL4_VCPUFault_HSR);
uint64_t hsr_ec_class = HSR_EXCEPTION_CLASS(hsr);
switch (hsr_ec_class) {
case HSR_SMC_64_EXCEPTION:
return smc_handle(vcpu_id, hsr);
case HSR_WFx_EXCEPTION:
// If we get a WFI exception, we just do nothing in the VMM.
return true;
default:
LOG_VMM_ERR("unknown SMC exception, EC class: 0x%lx, HSR: 0x%lx\n", hsr_ec_class, hsr);
return false;
case HSR_SMC_64_EXCEPTION:
return smc_handle(vcpu_id, hsr);
case HSR_WFx_EXCEPTION:
// If we get a WFI exception, we just do nothing in the VMM.
return true;
default:
LOG_VMM_ERR("unknown SMC exception, EC class: 0x%lx, HSR: 0x%lx\n", hsr_ec_class, hsr);
return false;
}
}

Expand Down Expand Up @@ -270,17 +312,17 @@ bool fault_handle_unknown_syscall(size_t vcpu_id)

LOG_VMM("Received syscall 0x%lx\n", syscall);
switch (syscall) {
case SYSCALL_PA_TO_IPA:
// @ivanv: why do we not do anything here?
// @ivanv, how to get the physical address to translate?
LOG_VMM("Received PA translation syscall\n");
break;
case SYSCALL_NOP:
LOG_VMM("Received NOP syscall\n");
break;
default:
LOG_VMM_ERR("Unknown syscall: syscall number: 0x%lx, PC: 0x%lx\n", syscall, fault_ip);
return false;
case SYSCALL_PA_TO_IPA:
// @ivanv: why do we not do anything here?
// @ivanv, how to get the physical address to translate?
LOG_VMM("Received PA translation syscall\n");
break;
case SYSCALL_NOP:
LOG_VMM("Received NOP syscall\n");
break;
default:
LOG_VMM_ERR("Unknown syscall: syscall number: 0x%lx, PC: 0x%lx\n", syscall, fault_ip);
return false;
}

seL4_UserContext regs;
Expand All @@ -304,7 +346,8 @@ struct vm_exception_handler {
struct vm_exception_handler registered_vm_exception_handlers[MAX_VM_EXCEPTION_HANDLERS];
size_t vm_exception_handler_index = 0;

bool fault_register_vm_exception_handler(uintptr_t base, size_t size, vm_exception_handler_t callback, void *data) {
bool fault_register_vm_exception_handler(uintptr_t base, size_t size, vm_exception_handler_t callback, void *data)
{
// @ivanv audit necessary here since this code was written very quickly. Other things to check such
// as the region of memory is not overlapping with other regions, also should have GIC_DIST regions
// use this API.
Expand All @@ -328,7 +371,8 @@ bool fault_register_vm_exception_handler(uintptr_t base, size_t size, vm_excepti
return true;
}

static bool fault_handle_registered_vm_exceptions(size_t vcpu_id, uintptr_t addr, size_t fsr, seL4_UserContext *regs) {
static bool fault_handle_registered_vm_exceptions(size_t vcpu_id, uintptr_t addr, size_t fsr, seL4_UserContext *regs)
{
for (int i = 0; i < MAX_VM_EXCEPTION_HANDLERS; i++) {
uintptr_t base = registered_vm_exception_handlers[i].base;
uintptr_t end = registered_vm_exception_handlers[i].end;
Expand All @@ -338,7 +382,8 @@ static bool fault_handle_registered_vm_exceptions(size_t vcpu_id, uintptr_t addr
bool success = callback(vcpu_id, addr - base, fsr, regs, data);
if (!success) {
// @ivanv: improve error message
LOG_VMM_ERR("registered virtual memory exception handler for region [0x%lx..0x%lx) at address 0x%lx failed\n", base, end, addr);
LOG_VMM_ERR("registered virtual memory exception handler for region [0x%lx..0x%lx) at address 0x%lx failed\n", base,
end, addr);
}
/* Whether or not the callback actually successfully handled the
* exception, we return true to say that we at least found a handler
Expand Down Expand Up @@ -372,7 +417,7 @@ bool fault_handle_vm_exception(size_t vcpu_id)
size_t is_prefetch = seL4_GetMR(seL4_VMFault_PrefetchFault);
bool is_write = fault_is_write(fsr);
LOG_VMM_ERR("unexpected memory fault on address: 0x%lx, FSR: 0x%lx, IP: 0x%lx, is_prefetch: %s, is_write: %s\n",
addr, fsr, ip, is_prefetch ? "true" : "false", is_write ? "true" : "false");
addr, fsr, ip, is_prefetch ? "true" : "false", is_write ? "true" : "false");
tcb_print_regs(vcpu_id);
vcpu_print_regs(vcpu_id);
} else {
Expand All @@ -382,36 +427,37 @@ bool fault_handle_vm_exception(size_t vcpu_id)
return success;
}

bool fault_handle(size_t vcpu_id, microkit_msginfo msginfo) {
bool fault_handle(size_t vcpu_id, microkit_msginfo msginfo)
{
size_t label = microkit_msginfo_get_label(msginfo);
bool success = false;
switch (label) {
case seL4_Fault_VMFault:
success = fault_handle_vm_exception(vcpu_id);
break;
case seL4_Fault_UnknownSyscall:
success = fault_handle_unknown_syscall(vcpu_id);
break;
case seL4_Fault_UserException:
success = fault_handle_user_exception(vcpu_id);
break;
case seL4_Fault_VGICMaintenance:
success = fault_handle_vgic_maintenance(vcpu_id);
break;
case seL4_Fault_VCPUFault:
success = fault_handle_vcpu_exception(vcpu_id);
break;
case seL4_Fault_VPPIEvent:
success = fault_handle_vppi_event(vcpu_id);
break;
default:
/* We have reached a genuinely unexpected case, stop the guest. */
LOG_VMM_ERR("unknown fault label 0x%lx, stopping guest with ID 0x%lx\n", label, vcpu_id);
microkit_vcpu_stop(vcpu_id);
/* Dump the TCB and vCPU registers to hopefully get information as
* to what has gone wrong. */
tcb_print_regs(vcpu_id);
vcpu_print_regs(vcpu_id);
case seL4_Fault_VMFault:
success = fault_handle_vm_exception(vcpu_id);
break;
case seL4_Fault_UnknownSyscall:
success = fault_handle_unknown_syscall(vcpu_id);
break;
case seL4_Fault_UserException:
success = fault_handle_user_exception(vcpu_id);
break;
case seL4_Fault_VGICMaintenance:
success = fault_handle_vgic_maintenance(vcpu_id);
break;
case seL4_Fault_VCPUFault:
success = fault_handle_vcpu_exception(vcpu_id);
break;
case seL4_Fault_VPPIEvent:
success = fault_handle_vppi_event(vcpu_id);
break;
default:
/* We have reached a genuinely unexpected case, stop the guest. */
LOG_VMM_ERR("unknown fault label 0x%lx, stopping guest with ID 0x%lx\n", label, vcpu_id);
microkit_vcpu_stop(vcpu_id);
/* Dump the TCB and vCPU registers to hopefully get information as
* to what has gone wrong. */
tcb_print_regs(vcpu_id);
vcpu_print_regs(vcpu_id);
}

if (!success) {
Expand Down

0 comments on commit 66781ec

Please sign in to comment.