From 526b08d3eb3595fa999ede6c004f8171b8b6e125 Mon Sep 17 00:00:00 2001 From: Pekka Enberg Date: Sun, 9 Jan 2011 00:46:07 +0200 Subject: [PATCH] kvm: Implement support interrupt injection This patch implement support for injecting interrupts from the userspace hypervisor to the guest. Signed-off-by: Pekka Enberg --- tools/kvm/Makefile | 4 ++- tools/kvm/early_printk.c | 5 +++ tools/kvm/include/kvm/early_printk.h | 3 ++ tools/kvm/kvm.c | 5 ++- tools/kvm/main.c | 49 +++++++++++++++++++++++++++- 5 files changed, 63 insertions(+), 3 deletions(-) diff --git a/tools/kvm/Makefile b/tools/kvm/Makefile index 9d6564c82455..f100f020aecf 100644 --- a/tools/kvm/Makefile +++ b/tools/kvm/Makefile @@ -27,6 +27,8 @@ DEPS := $(patsubst %.o,%.d,$(OBJS)) OBJS += bios.o OBJS += bios/bios.o +LIBS += -lrt + uname_M := $(shell uname -m | sed -e s/i.86/i386/) ifeq ($(uname_M),i386) DEFINES += -DCONFIG_X86_32 @@ -60,7 +62,7 @@ all: $(PROGRAM) $(PROGRAM): $(DEPS) $(OBJS) $(E) " LINK " $@ - $(Q) $(CC) $(OBJS) -o $@ + $(Q) $(CC) $(OBJS) $(LIBS) -o $@ $(DEPS): diff --git a/tools/kvm/early_printk.c b/tools/kvm/early_printk.c index d5db3a12a523..af3070f8e14f 100644 --- a/tools/kvm/early_printk.c +++ b/tools/kvm/early_printk.c @@ -65,6 +65,11 @@ static struct serial8250_device device = { .iobase = 0x3f8, /* ttyS0 */ }; +void serial8250__interrupt(struct kvm *self) +{ + /* TODO: inject 8250 interrupt for the guest */ +} + static bool serial8250_out(struct kvm *self, uint16_t port, void *data, int size, uint32_t count) { uint16_t offset = port - device.iobase; diff --git a/tools/kvm/include/kvm/early_printk.h b/tools/kvm/include/kvm/early_printk.h index 3ff49c0ee9aa..156717c3e2db 100644 --- a/tools/kvm/include/kvm/early_printk.h +++ b/tools/kvm/include/kvm/early_printk.h @@ -1,6 +1,9 @@ #ifndef KVM__EARLY_PRINTK_H #define KVM__EARLY_PRINTK_H +struct kvm; + void early_printk__init(void); +void serial8250__interrupt(struct kvm *self); #endif /* KVM__EARLY_PRINTK_H */ diff --git a/tools/kvm/kvm.c b/tools/kvm/kvm.c index 8f4a56a0aa42..a2d8f5b7ac7e 100644 --- a/tools/kvm/kvm.c +++ b/tools/kvm/kvm.c @@ -608,7 +608,10 @@ void kvm__setup_mem(struct kvm *self) void kvm__run(struct kvm *self) { - if (ioctl(self->vcpu_fd, KVM_RUN, 0) < 0) + int err; + + err = ioctl(self->vcpu_fd, KVM_RUN, 0); + if (err && (errno != EINTR && errno != EAGAIN)) die_perror("KVM_RUN failed"); } diff --git a/tools/kvm/main.c b/tools/kvm/main.c index 5331928776ba..748719cf92f2 100644 --- a/tools/kvm/main.c +++ b/tools/kvm/main.c @@ -12,6 +12,7 @@ #include #include #include +#include extern bool ioport_debug; @@ -45,6 +46,47 @@ static bool option_matches(char *arg, const char *option) return !strncmp(arg, option, strlen(option)); } +#define TIMER_INTERVAL_NS 1000000000 + +static void alarm_handler(int sig) +{ +} + +/* + * This function sets up a timer that's used to inject interrupts from the + * userspace hypervisor into the guest at periodical intervals. Please note + * that clock interrupt, for example, is not handled here. + */ +static void setup_timer(void) +{ + struct itimerspec its; + struct sigaction sa; + struct sigevent sev; + timer_t timerid; + + sigfillset(&sa.sa_mask); + sa.sa_flags = 0; + sa.sa_handler = alarm_handler; + + sigaction(SIGALRM, &sa, NULL); + + memset(&sev, 0, sizeof(struct sigevent)); + sev.sigev_value.sival_int = 0; + sev.sigev_notify = SIGEV_SIGNAL; + sev.sigev_signo = SIGALRM; + + its.it_value.tv_sec = TIMER_INTERVAL_NS / 1000000000; + its.it_value.tv_nsec = TIMER_INTERVAL_NS % 1000000000; + its.it_interval.tv_sec = its.it_value.tv_sec; + its.it_interval.tv_nsec = its.it_value.tv_nsec; + if (timer_create(CLOCK_MONOTONIC, &sev, &timerid) < 0) + die("timer_create()"); + + if (timer_settime(timerid, 0, &its, NULL) < 0) + die("timer_settime()"); +} + + int main(int argc, char *argv[]) { const char *kernel_filename = NULL; @@ -131,6 +173,8 @@ int main(int argc, char *argv[]) blk_virtio__init(kvm); + setup_timer(); + for (;;) { kvm__run(kvm); @@ -165,7 +209,10 @@ int main(int argc, char *argv[]) if (!ret) goto exit_kvm; break; - + } + case KVM_EXIT_INTR: { + serial8250__interrupt(kvm); + break; } default: goto exit_kvm; -- 2.39.5