mirror of
https://github.com/Atmosphere-NX/Atmosphere.git
synced 2025-06-03 16:18:51 -04:00
thermosphere: add in basic hypervisor skeleton
This commit is contained in:
parent
60c0df032d
commit
d104ff61ca
15 changed files with 2989 additions and 0 deletions
99
thermosphere/src/exceptions.c
Normal file
99
thermosphere/src/exceptions.c
Normal file
|
@ -0,0 +1,99 @@
|
|||
/**
|
||||
* Thermosphère: exception handler
|
||||
* Handles all exceptions, including a return to EL2.
|
||||
*
|
||||
* Copyright (c) 2018 Kate J. Temkin <k@ktemkin.com>
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include "exceptions.h"
|
||||
|
||||
#include "lib/printk.h"
|
||||
|
||||
/**
|
||||
* Simple debug function that prints all of our saved registers.
|
||||
*/
|
||||
static void print_registers(struct guest_state *regs)
|
||||
{
|
||||
// print x0-29
|
||||
for(int i = 0; i < 30; i += 2) {
|
||||
printk("x%d:\t0x%p\t", i, regs->x[i]);
|
||||
printk("x%d:\t0x%p\n", i + 1, regs->x[i + 1]);
|
||||
}
|
||||
|
||||
// print x30; don't bother with x31 (SP), as it's used by the stack that's
|
||||
// storing this stuff; we really care about the saved SP anyways
|
||||
printk("x30:\t0x%p\n", regs->x[30]);
|
||||
|
||||
// Special registers.
|
||||
printk("pc:\t0x%p\tcpsr:\t0x%p\n", regs->pc, regs->cpsr);
|
||||
printk("sp_el1:\t0x%p\tsp_el0:\t0x%p\n", regs->sp_el1, regs->sp_el0);
|
||||
printk("elr_el1:0x%p\tspsr_el1:0x%p\n", regs->elr_el1, regs->spsr_el1);
|
||||
|
||||
// Note that we don't print ESR_EL2, as this isn't really part of the saved state.
|
||||
}
|
||||
|
||||
/**
|
||||
* Placeholder function that triggers whenever a vector happens we're not
|
||||
* expecting. Currently prints out some debug information.
|
||||
*/
|
||||
void unhandled_vector(struct guest_state *regs)
|
||||
{
|
||||
printk("\nAn unexpected vector happened!\n");
|
||||
print_registers(regs);
|
||||
printk("\n\n");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Handles an HVC call.
|
||||
*/
|
||||
static void handle_hvc(struct guest_state *regs, int call_number)
|
||||
{
|
||||
|
||||
switch(call_number) {
|
||||
|
||||
|
||||
default:
|
||||
printk("Got a HVC call from 64-bit code.\n");
|
||||
printk("Calling instruction was: hvc %d\n\n", call_number);
|
||||
printk("Calling context (you can use these regs as hypercall args!):\n");
|
||||
print_registers(regs);
|
||||
printk("\n\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Placeholder function that triggers whenever a user event triggers a
|
||||
* synchronous interrupt. Currently, we really only care about 'hvc',
|
||||
* so that's all we're going to handle here.
|
||||
*/
|
||||
|
||||
void handle_hypercall(struct guest_state *regs)
|
||||
{
|
||||
// This is demonstration code.
|
||||
// In the future, you'd stick your hypercall table here.
|
||||
|
||||
switch (regs->esr_el2.ec) {
|
||||
|
||||
case HSR_EC_HVC64: {
|
||||
// Read the hypercall number.
|
||||
int hvc_nr = regs->esr_el2.iss & 0xFFFF;
|
||||
|
||||
// ... and handle the hypercall.
|
||||
handle_hvc(regs, hvc_nr);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
printk("Unexpected hypercall! ESR=%p\n", regs->esr_el2.bits);
|
||||
print_registers(regs);
|
||||
printk("\n\n");
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue