From: Jack Lange Date: Fri, 10 Oct 2008 00:06:13 +0000 (-0500) Subject: reworked the interrupt injection to be guest specific X-Git-Tag: 1.0~3^2 X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?p=palacios.git;a=commitdiff_plain;h=b84c13ec0315404c6b6de8c1d3a7a65ac766a782 reworked the interrupt injection to be guest specific --- diff --git a/geekos/include/geekos/vmm_stubs.h b/geekos/include/geekos/vmm_stubs.h index b7cea63..b56c114 100644 --- a/geekos/include/geekos/vmm_stubs.h +++ b/geekos/include/geekos/vmm_stubs.h @@ -46,7 +46,7 @@ int ack_irq(int irq); -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(); diff --git a/geekos/src/geekos/vm.c b/geekos/src/geekos/vm.c index 72ca417..10c34ca 100644 --- a/geekos/src/geekos/vm.c +++ b/geekos/src/geekos/vm.c @@ -228,7 +228,7 @@ int RunVMM(struct Boot_Info * bootInfo) { 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; diff --git a/geekos/src/geekos/vmm_stubs.c b/geekos/src/geekos/vmm_stubs.c index ed24cee..e40c8dd 100644 --- a/geekos/src/geekos/vmm_stubs.c +++ b/geekos/src/geekos/vmm_stubs.c @@ -19,8 +19,8 @@ #include #include -#include #include +#include @@ -94,106 +94,45 @@ void VMM_Free(void * addr) { 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; } @@ -206,7 +145,7 @@ int ack_irq(int irq) { void Init_Stubs() { - memset(irq_map, 0, sizeof(struct guest_info *) * 256); + memset(irq_to_guest_map, 0, sizeof(struct guest_info *) * 256); } diff --git a/palacios/build/Makefile b/palacios/build/Makefile index d612435..0cfd820 100644 --- a/palacios/build/Makefile +++ b/palacios/build/Makefile @@ -329,7 +329,8 @@ FD_SECTORS_PER_TRACK := $(PERL) $(PROJECT_ROOT)/scripts/numsecs_per_track # ---------------------------------------------------------------------- # 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 diff --git a/palacios/include/palacios/vm_guest.h b/palacios/include/palacios/vm_guest.h index 0be223c..1bd6a8d 100644 --- a/palacios/include/palacios/vm_guest.h +++ b/palacios/include/palacios/vm_guest.h @@ -101,8 +101,8 @@ struct shadow_page_state; 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); @@ -136,7 +136,7 @@ struct guest_info { // 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 diff --git a/palacios/include/palacios/vmm.h b/palacios/include/palacios/vmm.h index b72c2fe..ad139e8 100644 --- a/palacios/include/palacios/vmm.h +++ b/palacios/include/palacios/vmm.h @@ -188,24 +188,7 @@ typedef enum v3_cpu_arch {V3_INVALID_CPU, V3_SVM_CPU, V3_SVM_REV3_CPU, V3_VMX_CP -// -// -// 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 { @@ -224,7 +207,7 @@ 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); @@ -265,10 +248,25 @@ struct vmm_ctrl_ops { -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 diff --git a/palacios/include/palacios/vmm_intr.h b/palacios/include/palacios/vmm_intr.h index 0aa7038..d4543fd 100644 --- a/palacios/include/palacios/vmm_intr.h +++ b/palacios/include/palacios/vmm_intr.h @@ -26,6 +26,7 @@ #include #include + #define DE_EXCEPTION 0x00 #define DB_EXCEPTION 0x01 #define NMI_EXCEPTION 0x02 @@ -50,6 +51,7 @@ 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... @@ -57,7 +59,13 @@ struct guest_info; */ -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; @@ -70,6 +78,8 @@ struct vm_intr { /* some way to get the [A]PIC intr */ + struct v3_irq_hook * hooks[256]; + }; @@ -112,22 +122,19 @@ int start_irq(struct vm_intr * intr); 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 diff --git a/palacios/src/palacios/vmm_config.c b/palacios/src/palacios/vmm_config.c index 16bcb17..fa4fe80 100644 --- a/palacios/src/palacios/vmm_config.c +++ b/palacios/src/palacios/vmm_config.c @@ -359,16 +359,16 @@ int config_guest(struct guest_info * info, struct v3_vm_config * config_ptr) { #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); diff --git a/palacios/src/palacios/vmm_intr.c b/palacios/src/palacios/vmm_intr.c index 51316bb..6bdca1a 100644 --- a/palacios/src/palacios/vmm_intr.c +++ b/palacios/src/palacios/vmm_intr.c @@ -30,14 +30,16 @@ -/*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) { @@ -47,69 +49,60 @@ void set_intr_controller(struct guest_info * info, struct intr_ctrl_ops * ops, v -// 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); @@ -123,8 +116,29 @@ int v3_hook_irq_for_guest_injection(struct guest_info *info, int irq) + +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; @@ -141,7 +155,7 @@ int v3_raise_exception_with_error(struct guest_info * info, uint_t excp, uint_t } 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; @@ -156,18 +170,17 @@ int v3_raise_exception(struct guest_info * info, uint_t excp) { 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"); @@ -199,7 +212,7 @@ int v3_raise_irq(struct guest_info * info, int irq) { 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) { @@ -215,7 +228,7 @@ int intr_pending(struct guest_info * info) { 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; @@ -231,7 +244,7 @@ uint_t get_intr_number(struct guest_info * info) { 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"); @@ -250,7 +263,7 @@ intr_type_t get_intr_type(struct guest_info * info) { 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");