mirror of
https://github.com/clearlinux/kvmtool.git
synced 2026-09-04 20:51:28 +00:00
kvm: Implement support interrupt injection
This patch implement support for injecting interrupts from the userspace hypervisor to the guest. Signed-off-by: Pekka Enberg <penberg@kernel.org>
This commit is contained in:
committed by
Will Deacon
parent
ceba1fad4c
commit
8bb34e0dfa
@@ -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):
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
|
||||
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;
|
||||
|
||||
Reference in New Issue
Block a user