-int geekos_hook_interrupt_new(uint_t irq, void *opaque);
+int geekos_hook_interrupt(struct guest_info * info, uint_t irq);
unsigned int get_cpu_khz();
os_hooks.free = &VMM_Free;
os_hooks.vaddr_to_paddr = &Identity;
os_hooks.paddr_to_vaddr = &Identity;
- os_hooks.hook_interrupt = &geekos_hook_interrupt_new;
+ os_hooks.hook_interrupt = &geekos_hook_interrupt;
os_hooks.ack_irq = &ack_irq;
os_hooks.get_cpu_khz = &get_cpu_khz;
#include <geekos/vmm_stubs.h>
#include <geekos/serial.h>
-#include <palacios/vm_guest.h>
#include <geekos/debug.h>
+#include <palacios/vmm.h>
Free(addr);
}
-//
-//
-// This is the interrupt state that the VMM's interrupt handlers need to see
-//
-struct vmm_intr_state {
- uint_t irq;
- uint_t error;
-
- uint_t should_ack; // Should the vmm ack this interrupt, or will
- // the host OS do it?
-
- // This is the value given when the interrupt is hooked.
- // This will never be NULL
- void *opaque;
-};
// This is the function the interface code should call to deliver
// the interrupt to the vmm for handling
-extern void deliver_interrupt_to_vmm(struct vmm_intr_state *state);
-
+//extern int v3_deliver_interrupt(struct guest_info * vm, struct v3_interrupt *intr);
-struct guest_info * irq_map[256];
-void *my_opaque[256];
+struct guest_info * irq_to_guest_map[256];
-static void translate_intr_handler(struct Interrupt_State *state)
-{
-
- struct vmm_intr_state mystate;
+void translate_intr_handler(struct Interrupt_State *state) {
+ struct v3_interrupt intr;
- mystate.irq=state->intNum-32;
- mystate.error=state->errorCode;
- mystate.should_ack=0;
- mystate.opaque=my_opaque[mystate.irq];
+ intr.irq = state->intNum - 32;
+ intr.error = state->errorCode;
+ intr.should_ack = 0;
// PrintBoth("translate_intr_handler: opaque=0x%x\n",mystate.opaque);
- deliver_interrupt_to_vmm(&mystate);
+ v3_deliver_irq(irq_to_guest_map[intr.irq], &intr);
End_IRQ(state);
}
-/*
-static void pic_intr_handler(struct Interrupt_State * state) {
- Begin_IRQ(state);
- struct guest_info * info = irq_map[state->intNum - 32];
- SerialPrint("Interrupt %d (IRQ=%d)\n", state->intNum, state->intNum - 32);
-
- if (info) {
- info->vm_ops.raise_irq(info, state->intNum - 32);
- } else {
- SerialPrint("Interrupt handler error: NULL pointer found, no action taken\n");
- End_IRQ(state);
- return;
- }
-
- // End_IRQ(state);
-}
-*/
-//
-//
-// I really don't know what the heck this is doing... PAD
-//
-/*
-int hook_irq_stub(struct guest_info * info, int irq) {
- if (irq_map[irq]) {
- return -1;
- }
-
- SerialPrint("Hooking IRQ: %d (vm=0x%x)\n", irq, info);
- irq_map[irq] = info;
- volatile void *foo = pic_intr_handler;
-
- // This is disabled for the time being
- foo = 0;
-
-
- Disable_IRQ(irq);
- Install_IRQ(irq, pic_intr_handler);
- Enable_IRQ(irq);
- return 0;
-}
-*/
-int geekos_hook_interrupt_new(uint_t irq, void * opaque)
+int geekos_hook_interrupt(struct guest_info * vm, unsigned int irq)
{
- if (my_opaque[irq]) {
+ if (irq_to_guest_map[irq]) {
PrintBoth("Attempt to hook interrupt that is already hooked\n");
return -1;
} else {
- PrintBoth("Hooked interrupt 0x%x with opaque 0x%x\n",irq,opaque);
- my_opaque[irq]=opaque;
+ PrintBoth("Hooked interrupt 0x%x with opaque 0x%x\n", irq, vm);
+ irq_to_guest_map[irq] = vm;
}
Disable_IRQ(irq);
- Install_IRQ(irq,translate_intr_handler);
+ Install_IRQ(irq, translate_intr_handler);
Enable_IRQ(irq);
return 0;
}
void Init_Stubs() {
- memset(irq_map, 0, sizeof(struct guest_info *) * 256);
+ memset(irq_to_guest_map, 0, sizeof(struct guest_info *) * 256);
}
# ----------------------------------------------------------------------
# Flags used for all C source files
-GENERAL_OPTS := -O -Wall $(EXTRA_C_OPTS) $(VMM_FLAGS) -fPIC #-fvisibility=hidden
+#GENERAL_OPTS := -O -Wall $(EXTRA_C_OPTS) $(VMM_FLAGS) -fPIC #-fvisibility=hidden
+GENERAL_OPTS := -Wall $(EXTRA_C_OPTS) $(VMM_FLAGS) -fPIC #-fvisibility=hidden
CC_GENERAL_OPTS := $(GENERAL_OPTS) -Werror
# Flags used for VMM C source files
struct shadow_map;
struct vmm_io_map;
struct emulation_state;
+struct v3_intr_state;
-/*Zheng 07/30/2008*/
struct vm_ctrl_ops {
int (*raise_irq)(struct guest_info * info, int irq);
int (*lower_irq)(struct guest_info * info, int irq);
// This structure is how we get interrupts for the guest
- struct vm_intr intr_state;
+ struct v3_intr_state intr_state;
struct vmm_io_map io_map;
// device_map
-//
-//
-// This is the interrupt state that the VMM's interrupt handlers need to see
-//
-struct vmm_intr_state {
- unsigned int irq;
- unsigned int error;
-
- unsigned int should_ack; // Should the vmm ack this interrupt, or will
- // the host OS do it?
-
- // This is the value given when the interrupt is hooked.
- // This will never be NULL
- void * opaque;
-};
-
-void deliver_interrupt_to_vmm(struct vmm_intr_state * state);
-
+struct guest_info;
/* This will contain function pointers that provide OS services */
struct vmm_os_hooks {
// int (*hook_interrupt)(struct guest_info *s, int irq);
- int (*hook_interrupt)(unsigned int irq, void *opaque);
+ int (*hook_interrupt)(struct guest_info * vm, unsigned int irq);
int (*ack_irq)(int irq);
-void Init_V3(struct vmm_os_hooks * hooks, struct vmm_ctrl_ops * vmm_ops);
+//
+//
+// This is the interrupt state that the VMM's interrupt handlers need to see
+//
+struct v3_interrupt {
+ unsigned int irq;
+ unsigned int error;
+
+ unsigned int should_ack; // Should the vmm ack this interrupt, or will
+ // the host OS do it?
+};
+
+void Init_V3(struct vmm_os_hooks * hooks, struct vmm_ctrl_ops * vmm_ops);
+
+int v3_deliver_irq(struct guest_info * vm, struct v3_interrupt * intr);
+
#endif
#include <palacios/vmm_intr.h>
#include <palacios/vmm_types.h>
+
#define DE_EXCEPTION 0x00
#define DB_EXCEPTION 0x01
#define NMI_EXCEPTION 0x02
typedef enum {INVALID_INTR, EXTERNAL_IRQ, NMI, EXCEPTION, SOFTWARE_INTR, VIRTUAL_INTR} intr_type_t;
struct guest_info;
+struct v3_interrupt;
/* We need a way to allow the APIC/PIC to decide when they are supposed to receive interrupts...
* Maybe a notification call when they have been turned on, to deliver irqs to them...
*/
-struct vm_intr {
+struct v3_irq_hook {
+ int (*handler)(struct guest_info * info, struct v3_interrupt * intr, void * priv_data);
+ void * priv_data;
+};
+
+
+struct v3_intr_state {
/* We need to rework the exception state, to handle stacking */
uint_t excp_pending;
/* some way to get the [A]PIC intr */
+ struct v3_irq_hook * hooks[256];
+
};
int end_irq(struct vm_intr * intr, int irq);
*/
-#endif // !__V3VEE__
-
-
+int v3_hook_irq(struct guest_info * info,
+ uint_t irq,
+ int (*handler)(struct guest_info * info, struct v3_interrupt * intr, void * priv_data),
+ void * priv_data);
+int v3_hook_passthrough_irq(struct guest_info *info, uint_t irq);
-struct vmm_intr_state;
-
-int v3_hook_irq(uint_t irq,
- void (*handler)(struct vmm_intr_state *state),
- void *opaque);
+#endif // !__V3VEE__
-int v3_hook_irq_for_guest_injection(struct guest_info *info, int irq);
#endif
#if 0
// give floppy controller to vm
- v3_hook_irq_for_guest_injection(info, 6);
+ v3_hook_passthrough_irq(info, 6);
#endif
if (!use_ramdisk) {
//primary ide
- v3_hook_irq_for_guest_injection(info, 14);
+ v3_hook_passthrough_irq(info, 14);
// secondary ide
- v3_hook_irq_for_guest_injection(info, 15);
+ v3_hook_passthrough_irq(info, 15);
}
//v3_hook_io_port(info, 1234, &IO_Read, NULL, info);
-/*Zheng 07/30/2008*/
+
void init_interrupt_state(struct guest_info * info) {
info->intr_state.excp_pending = 0;
info->intr_state.excp_num = 0;
info->intr_state.excp_error_code = 0;
+ memset((uchar_t *)(info->intr_state.hooks), 0, sizeof(struct v3_irq_hook *) * 256);
+
info->vm_ops.raise_irq = &v3_raise_irq;
- info->vm_ops.lower_irq = &v3_lower_irq; //Zheng added
+ info->vm_ops.lower_irq = &v3_lower_irq;
}
void set_intr_controller(struct guest_info * info, struct intr_ctrl_ops * ops, void * state) {
-// This structure is used to dispatch
-// interrupts delivered to vmm via deliver interrupt to vmm
-// it is what we put into the opaque field given to
-// the host os when we install the handler
-struct vmm_intr_decode {
- void (*handler)(struct vmm_intr_state *state);
- // This opaque is user supplied by the caller
- // of hook_irq_new
- void *opaque;
-};
-int v3_hook_irq(uint_t irq,
- void (*handler)(struct vmm_intr_state *state),
- void *opaque)
+static inline struct v3_irq_hook * get_irq_hook(struct guest_info * info, uint_t irq) {
+ V3_ASSERT(irq <= 256);
+ return info->intr_state.hooks[irq];
+}
+
+
+int v3_hook_irq(struct guest_info * info,
+ uint_t irq,
+ int (*handler)(struct guest_info * info, struct v3_interrupt * intr, void * priv_data),
+ void * priv_data)
{
- struct vmm_intr_decode *d = (struct vmm_intr_decode *)V3_Malloc(sizeof(struct vmm_intr_decode));
+ struct v3_irq_hook * hook = (struct v3_irq_hook *)V3_Malloc(sizeof(struct v3_irq_hook));
- if (!d) { return -1; }
+ if (hook == NULL) {
+ return -1;
+ }
+
+ if (get_irq_hook(info, irq) != NULL) {
+ PrintError("IRQ %d already hooked\n", irq);
+ return -1;
+ }
- d->handler = handler;
- d->opaque = opaque;
+ hook->handler = handler;
+ hook->priv_data = priv_data;
- if (V3_Hook_Interrupt(irq,d)) {
- PrintError("hook_irq: failed to hook irq 0x%x to decode 0x%x\n", irq,d);
+ info->intr_state.hooks[irq] = hook;
+
+ if (V3_Hook_Interrupt(info, irq)) {
+ PrintError("hook_irq: failed to hook irq %d\n", irq);
return -1;
} else {
- PrintDebug("hook_irq: hooked irq 0x%x to decode 0x%x\n", irq,d);
+ PrintDebug("hook_irq: hooked irq %d\n", irq);
return 0;
}
}
-void deliver_interrupt_to_vmm(struct vmm_intr_state *state)
-{
-
- PrintDebug("deliver_interrupt_to_vmm: state=0x%x\n",state);
-
- struct vmm_intr_decode *d = (struct vmm_intr_decode *)(state->opaque);
-
- void *temp = state->opaque;
- state->opaque = d->opaque;
- d->handler(state);
-
- state->opaque=temp;
-}
+static int passthrough_irq_handler(struct guest_info * info, struct v3_interrupt * intr, void * priv_data)
+{
+ PrintDebug("[passthrough_irq_handler] raise_irq=%d (guest=0x%x)\n", intr->irq, info);
+ return v3_raise_irq(info, intr->irq);
-static void guest_injection_irq_handler(struct vmm_intr_state *state)
-{
- struct guest_info *guest = (struct guest_info *)(state->opaque);
- PrintDebug("[guest_injection_irq_handler] raise_irq=0x%x (guest=0x%x)\n", state->irq, guest);
- PrintDebug("guest_irq_injection: state=0x%x\n", state);
- guest->vm_ops.raise_irq(guest,state->irq);
}
-
-int v3_hook_irq_for_guest_injection(struct guest_info *info, int irq)
+int v3_hook_passthrough_irq(struct guest_info * info, uint_t irq)
{
- int rc = v3_hook_irq(irq,
- guest_injection_irq_handler,
- info);
+ int rc = v3_hook_irq(info,
+ irq,
+ passthrough_irq_handler,
+ NULL);
if (rc) {
PrintError("guest_irq_injection: failed to hook irq 0x%x (guest=0x%x)\n", irq, info);
+
+int v3_deliver_irq(struct guest_info * info, struct v3_interrupt * intr) {
+ PrintDebug("v3_deliver_irq: irq=%d state=0x%x, \n", intr->irq, intr);
+
+ struct v3_irq_hook * hook = get_irq_hook(info, intr->irq);
+
+ if (hook == NULL) {
+ PrintError("Attempting to deliver interrupt to non registered hook(irq=%d)\n", intr->irq);
+ return -1;
+ }
+
+ return hook->handler(info, intr, hook->priv_data);
+}
+
+
+
+
+
+
+
+
int v3_raise_exception_with_error(struct guest_info * info, uint_t excp, uint_t error_code) {
- struct vm_intr * intr_state = &(info->intr_state);
+ struct v3_intr_state * intr_state = &(info->intr_state);
if (intr_state->excp_pending == 0) {
intr_state->excp_pending = 1;
}
int v3_raise_exception(struct guest_info * info, uint_t excp) {
- struct vm_intr * intr_state = &(info->intr_state);
+ struct v3_intr_state * intr_state = &(info->intr_state);
PrintDebug("[v3_raise_exception]\n");
if (intr_state->excp_pending == 0) {
intr_state->excp_pending = 1;
return 0;
}
-/*Zheng 07/30/2008*/
int v3_lower_irq(struct guest_info * info, int irq) {
// Look up PIC and resend
V3_ASSERT(info);
V3_ASSERT(info->intr_state.controller);
- V3_ASSERT(info->intr_state.controller->raise_intr);
+ V3_ASSERT(info->intr_state.controller->lower_intr);
PrintDebug("[v3_lower_irq]\n");
if ((info->intr_state.controller) &&
- (info->intr_state.controller->raise_intr)) {
+ (info->intr_state.controller->lower_intr)) {
info->intr_state.controller->lower_intr(info->intr_state.controller_state, irq);
} else {
PrintDebug("There is no registered Interrupt Controller... (NULL POINTER)\n");
int intr_pending(struct guest_info * info) {
- struct vm_intr * intr_state = &(info->intr_state);
+ struct v3_intr_state * intr_state = &(info->intr_state);
// PrintDebug("[intr_pending]\n");
if (intr_state->excp_pending == 1) {
uint_t get_intr_number(struct guest_info * info) {
- struct vm_intr * intr_state = &(info->intr_state);
+ struct v3_intr_state * intr_state = &(info->intr_state);
if (intr_state->excp_pending == 1) {
return intr_state->excp_num;
intr_type_t get_intr_type(struct guest_info * info) {
- struct vm_intr * intr_state = &(info->intr_state);
+ struct v3_intr_state * intr_state = &(info->intr_state);
if (intr_state->excp_pending) {
PrintDebug("[get_intr_type] Exception\n");
int injecting_intr(struct guest_info * info, uint_t intr_num, intr_type_t type) {
- struct vm_intr * intr_state = &(info->intr_state);
+ struct v3_intr_state * intr_state = &(info->intr_state);
if (type == EXCEPTION) {
PrintDebug("[injecting_intr] Exception\n");