[PATCH 07/16] per-vcpu lguest timers
Here, I introduce per-vcpu timers. With this, we can have local expiries, needed for accounting time in smp guests Signed-off-by: Glauber de Oliveira Costa <[EMAIL PROTECTED]> --- drivers/lguest/hypercalls.c |2 +- drivers/lguest/interrupts_and_traps.c | 20 ++-- drivers/lguest/lg.h | 10 +- drivers/lguest/lguest_user.c | 12 +++- 4 files changed, 23 insertions(+), 21 deletions(-) diff --git a/drivers/lguest/hypercalls.c b/drivers/lguest/hypercalls.c index 9417601..1bf133e 100644 --- a/drivers/lguest/hypercalls.c +++ b/drivers/lguest/hypercalls.c @@ -78,7 +78,7 @@ static void do_hcall(struct lg_vcpu *vcpu, struct hcall_args *args) guest_set_pmd(lg, args->arg1, args->arg2); break; case LHCALL_SET_CLOCKEVENT: - guest_set_clockevent(lg, args->arg1); + guest_set_clockevent(vcpu, args->arg1); break; case LHCALL_TS: /* This sets the TS flag, as we saw used in run_guest(). */ diff --git a/drivers/lguest/interrupts_and_traps.c b/drivers/lguest/interrupts_and_traps.c index 2b66f79..3be18a6 100644 --- a/drivers/lguest/interrupts_and_traps.c +++ b/drivers/lguest/interrupts_and_traps.c @@ -470,13 +470,13 @@ void copy_traps(const struct lguest *lg, struct desc_struct *idt, * infrastructure to set a callback at that time. * * 0 means "turn off the clock". */ -void guest_set_clockevent(struct lguest *lg, unsigned long delta) +void guest_set_clockevent(struct lg_vcpu *vcpu, unsigned long delta) { ktime_t expires; if (unlikely(delta == 0)) { /* Clock event device is shutting down. */ - hrtimer_cancel(&lg->hrt); + hrtimer_cancel(&vcpu->hrt); return; } @@ -484,25 +484,25 @@ void guest_set_clockevent(struct lguest *lg, unsigned long delta) * all the time between now and the timer interrupt it asked for. This * is almost always the right thing to do. */ expires = ktime_add_ns(ktime_get_real(), delta); - hrtimer_start(&lg->hrt, expires, HRTIMER_MODE_ABS); + hrtimer_start(&vcpu->hrt, expires, HRTIMER_MODE_ABS); } /* This is the function called when the Guest's timer expires. */ static enum hrtimer_restart clockdev_fn(struct hrtimer *timer) { - struct lguest *lg = container_of(timer, struct lguest, hrt); + struct lg_vcpu *vcpu = container_of(timer, struct lg_vcpu, hrt); /* Remember the first interrupt is the timer interrupt. */ - set_bit(0, lg->irqs_pending); + set_bit(0, vcpu->lg->irqs_pending); /* If the Guest is actually stopped, we need to wake it up. */ - if (lg->halted) - wake_up_process(lg->tsk); + if (vcpu->lg->halted) + wake_up_process(vcpu->lg->tsk); return HRTIMER_NORESTART; } /* This sets up the timer for this Guest. */ -void init_clockdev(struct lguest *lg) +void init_clockdev(struct lg_vcpu *vcpu) { - hrtimer_init(&lg->hrt, CLOCK_REALTIME, HRTIMER_MODE_ABS); - lg->hrt.function = clockdev_fn; + hrtimer_init(&vcpu->hrt, CLOCK_REALTIME, HRTIMER_MODE_ABS); + vcpu->hrt.function = clockdev_fn; } diff --git a/drivers/lguest/lg.h b/drivers/lguest/lg.h index 13a991a..9c90fd3 100644 --- a/drivers/lguest/lg.h +++ b/drivers/lguest/lg.h @@ -47,6 +47,9 @@ struct lg_vcpu { /* If a hypercall was asked for, this points to the arguments. */ struct hcall_args *hcall; u32 next_hcall; + + /* Virtual clock device */ + struct hrtimer hrt; }; /* The private info the thread maintains about the guest. */ @@ -95,9 +98,6 @@ struct lguest struct lguest_arch arch; - /* Virtual clock device */ - struct hrtimer hrt; - /* Pending virtual interrupts */ DECLARE_BITMAP(irqs_pending, LGUEST_IRQS); }; @@ -145,8 +145,8 @@ void setup_default_idt_entries(struct lguest_ro_state *state, const unsigned long *def); void copy_traps(const struct lguest *lg, struct desc_struct *idt, const unsigned long *def); -void guest_set_clockevent(struct lguest *lg, unsigned long delta); -void init_clockdev(struct lguest *lg); +void guest_set_clockevent(struct lg_vcpu *vcpu, unsigned long delta); +void init_clockdev(struct lg_vcpu *vcpu); bool check_syscall_vector(struct lguest *lg); int init_interrupts(void); void free_interrupts(void); diff --git a/drivers/lguest/lguest_user.c b/drivers/lguest/lguest_user.c index d176004..cd2b0bf 100644 --- a/drivers/lguest/lguest_user.c +++ b/drivers/lguest/lguest_user.c @@ -104,6 +104,9 @@ static int vcpu_start(struct lg_vcpu *vcpu, int vcpu_id, vcpu->vcpu_id = vcpu_id; + /* The timer for lguest's clock needs initialization. */ + init_clockdev(vcpu); + vcpu->lg = container_of((vcpu - vcpu_id), struct lguest, vcpus[0]); vcp
[PATCH 07/16] per-vcpu lguest timers
Here, I introduce per-vcpu timers. With this, we can have local expiries, needed for accounting time in smp guests Signed-off-by: Glauber de Oliveira Costa <[EMAIL PROTECTED]> --- drivers/lguest/hypercalls.c |2 +- drivers/lguest/interrupts_and_traps.c | 20 ++-- drivers/lguest/lg.h | 10 +- drivers/lguest/lguest_user.c | 12 +++- 4 files changed, 23 insertions(+), 21 deletions(-) diff --git a/drivers/lguest/hypercalls.c b/drivers/lguest/hypercalls.c index 62da355..4364bc2 100644 --- a/drivers/lguest/hypercalls.c +++ b/drivers/lguest/hypercalls.c @@ -78,7 +78,7 @@ static void do_hcall(struct lguest_vcpu *vcpu, struct hcall_args *args) guest_set_pmd(lg, args->arg1, args->arg2); break; case LHCALL_SET_CLOCKEVENT: - guest_set_clockevent(lg, args->arg1); + guest_set_clockevent(vcpu, args->arg1); break; case LHCALL_TS: /* This sets the TS flag, as we saw used in run_guest(). */ diff --git a/drivers/lguest/interrupts_and_traps.c b/drivers/lguest/interrupts_and_traps.c index 2b66f79..189d66e 100644 --- a/drivers/lguest/interrupts_and_traps.c +++ b/drivers/lguest/interrupts_and_traps.c @@ -470,13 +470,13 @@ void copy_traps(const struct lguest *lg, struct desc_struct *idt, * infrastructure to set a callback at that time. * * 0 means "turn off the clock". */ -void guest_set_clockevent(struct lguest *lg, unsigned long delta) +void guest_set_clockevent(struct lguest_vcpu *vcpu, unsigned long delta) { ktime_t expires; if (unlikely(delta == 0)) { /* Clock event device is shutting down. */ - hrtimer_cancel(&lg->hrt); + hrtimer_cancel(&vcpu->hrt); return; } @@ -484,25 +484,25 @@ void guest_set_clockevent(struct lguest *lg, unsigned long delta) * all the time between now and the timer interrupt it asked for. This * is almost always the right thing to do. */ expires = ktime_add_ns(ktime_get_real(), delta); - hrtimer_start(&lg->hrt, expires, HRTIMER_MODE_ABS); + hrtimer_start(&vcpu->hrt, expires, HRTIMER_MODE_ABS); } /* This is the function called when the Guest's timer expires. */ static enum hrtimer_restart clockdev_fn(struct hrtimer *timer) { - struct lguest *lg = container_of(timer, struct lguest, hrt); + struct lguest_vcpu *vcpu = container_of(timer, struct lguest_vcpu, hrt); /* Remember the first interrupt is the timer interrupt. */ - set_bit(0, lg->irqs_pending); + set_bit(0, vcpu->lg->irqs_pending); /* If the Guest is actually stopped, we need to wake it up. */ - if (lg->halted) - wake_up_process(lg->tsk); + if (vcpu->lg->halted) + wake_up_process(vcpu->lg->tsk); return HRTIMER_NORESTART; } /* This sets up the timer for this Guest. */ -void init_clockdev(struct lguest *lg) +void init_clockdev(struct lguest_vcpu *vcpu) { - hrtimer_init(&lg->hrt, CLOCK_REALTIME, HRTIMER_MODE_ABS); - lg->hrt.function = clockdev_fn; + hrtimer_init(&vcpu->hrt, CLOCK_REALTIME, HRTIMER_MODE_ABS); + vcpu->hrt.function = clockdev_fn; } diff --git a/drivers/lguest/lg.h b/drivers/lguest/lg.h index 696cdf1..0205409 100644 --- a/drivers/lguest/lg.h +++ b/drivers/lguest/lg.h @@ -47,6 +47,9 @@ struct lguest_vcpu { /* If a hypercall was asked for, this points to the arguments. */ struct hcall_args *hcall; u32 next_hcall; + + /* Virtual clock device */ + struct hrtimer hrt; }; /* The private info the thread maintains about the guest. */ @@ -95,9 +98,6 @@ struct lguest struct lguest_arch arch; - /* Virtual clock device */ - struct hrtimer hrt; - /* Pending virtual interrupts */ DECLARE_BITMAP(irqs_pending, LGUEST_IRQS); }; @@ -150,8 +150,8 @@ void setup_default_idt_entries(struct lguest_ro_state *state, const unsigned long *def); void copy_traps(const struct lguest *lg, struct desc_struct *idt, const unsigned long *def); -void guest_set_clockevent(struct lguest *lg, unsigned long delta); -void init_clockdev(struct lguest *lg); +void guest_set_clockevent(struct lguest_vcpu *vcpu, unsigned long delta); +void init_clockdev(struct lguest_vcpu *vcpu); bool check_syscall_vector(struct lguest *lg); int init_interrupts(void); void free_interrupts(void); diff --git a/drivers/lguest/lguest_user.c b/drivers/lguest/lguest_user.c index ae5bf4c..7481e82 100644 --- a/drivers/lguest/lguest_user.c +++ b/drivers/lguest/lguest_user.c @@ -97,6 +97,9 @@ static int vcpu_start(struct lguest_vcpu *vcpu, int vcpu_id, { vcpu->vcpu_id = vcpu_id; + /* The timer for lguest's clock needs initialization. */ + init_clockdev(vcpu); + vcpu->lg = container_of((vcpu - vcpu_id), st