From bdd30274ed6456f556e9c4646edf9e042a65913c Mon Sep 17 00:00:00 2001 From: Alek Ratzloff Date: Wed, 4 Mar 2020 14:23:57 -0500 Subject: [PATCH] Add interrupts draft to spec Signed-off-by: Alek Ratzloff --- vm.md | 115 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 114 insertions(+), 1 deletion(-) diff --git a/vm.md b/vm.md index 2f16eaa..9f40ee6 100644 --- a/vm.md +++ b/vm.md @@ -25,8 +25,17 @@ CPU registers are addressed by a value between 0-63 (6 bits). All registers are * FLAGS - CPU flags * STATUS - Generic status code * NIL - Always zero for reading and will never change after writing. +* IVT - Interrupt vector table pointer * R0-R31 -* (26 unused registers) +* (25 reserved registers) + +The following registers are caller-save (i.e., their value may change after a function call): + +* FLAGS +* STATUS +* IVT + +The rest are callee-save. ## CPU Flags @@ -190,6 +199,7 @@ wrapping around to 0. * Push the current stack frame pointer * Push the IP of the next instruction * Update the IP (i.e., jump) to the value at the given source. + * Update the frame pointer to the current stack pointer - 16 * Ret * Opcode: 0x2001 * When this instruction is executed, these actions occur: @@ -209,6 +219,31 @@ wrapping around to 0. * When this instruction is executed, these actions occur: * Decrement the stack pointer by the size of value at the destination. * Copy the value at the stack pointer into the destination. +* Int + * Opcode: 0x2004 + * Params: Source, Source + * When this instruction is executed, these actions occur: + * Push the current stack frame pointer + * Push the IP of the next instruction to be called + * Push the FLAGS register + * Push the STATUS register + * Push the R0 register + * Push the R1 register + * Update the IP (i.e., jump) to the address of the given interrupt vector in the IVT + * Update the R0 register to the value in the first parameter + * Update the R1 register to the value in the second parameter + * Update the frame pointer to the current stack pointer - 48 +* IRet + * Opcode: 0x2005 + * When this instruction is executed, these actions occur: + * Update the stack pointer to the current frame pointer + 48 + * Pop the old R1 value + * Pop the old R0 value + * Pop the old STATUS value + * Pop the old FLAGS value + * Pop the IP of the next instruction + * Pop the old stack frame + * Restore the last 6 values in an undefined order ## Data movement @@ -225,6 +260,84 @@ wrapping around to 0. * Dump * Opcode: 0xF002 +# Interrupts + +Interrupts are signaled explicitly from software or from hardware signaling the CPU. When an +interrupt signal is set, the CPU will finish whatever instruction it is executing, and then begin +handling the interrupt whose signal was set. Software interrupts may be invoked using the `int` +instruction, supplying the index of the interrupt to invoke. Hardware interrupts are invoked +directly by a hardware event, e.g. a keypress. Hardware and software interrupts are treated equally +in the CPU, and as such, they are all maskable. + +## Interrupt vector table + +Interrupts are defined by the IVT register. The address stored in the IVT register must be a +multiple of 64. The IVT always has 512 entries, with 8 bytes for each entry. Thus, the entire table +is 512 * 8 = 4096 bytes, or one page. + +## Interrupt table entries + +Interrupt table entries make up the interrupt vector table, each entry being 64 bits (8 bytes) long. + +* 1 bit - Enabled +* 4 bits - Reserved, set to 0 +* 59 bits - Interrupt address, multiplied by 64 for the start address + +## Interrupt handling + +After an interrupt is signaled, the CPU looks up the index of the interrupt in the IVT, calculates +its address, sets up the stack for the interrupt handler, and jumps to the interrupt handler's +address. + +The interrupt stack is structured similarly to a normal call stack, but since interrupts may be +invoked at any time, it saves additional state. Interrupt handlers have two explicit arguments: the +interrupt index itself, and an auxiliary 64-bit value or pointer specific to that interrupt. The +index is stored in the R0 register, and the auxiliary value is stored in the R1 register. These +registers, along with the FP, IP, FLAGS, and STATUS registers are saved on the stack before calling +an interrupt handler. + +Before an interrupt handler is called, these actions occur: + +* Push the current stack frame pointer +* Push the IP of the next instruction to be called +* Push the FLAGS register +* Push the STATUS register +* Push the R0 register +* Push the R1 register + +Interrupt handlers must be exited using the `iret` instruction. + +## Exceptions + +The first 256 interrupt vectors are reserved for CPU and hardware-sourced events - these are known +as exceptions. Exceptions may occur for a number of reasons: + +* Illegal operation attempted, e.g. divide by zero or accessing protected memory +* Illegal operation attempted while handling an interrupt (double fault) +* A hardware event occurred, e.g. a timer tick + +The following list defines all exceptions that the CPU may invoke. All other vectors in 0-255 not +defined in this table are reserved and may be used in the future. + +* Divide by zero + * Interrupt vector: 0 + * Auxiliary: N/A + * Invoked upon a divide-by-zero +* Invalid opcode + * Interrupt vector: 1 + * Auxiliary: N/A + * Attempted to invoke an illegal opcode +* Illegal memory address + * Interrupt vector: 2 + * Auxiliary: Memory address causing the interrupt + * Attempted to access a memory address in an illegal way - either it's out of bounds or is + protected in some way. +* Hardware event + * Interrupt vector: 3 + * Auxiliary: Pointer to the hardware event structure. + * A hardware device has an event that needs attention. +* Interrupt vector 4-255: Reserved for future use + # Binary object format The binary object format is composed of a header followed by sections that make up the content of