aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGlauber de Oliveira Costa <gcosta@redhat.com>2008-01-07 08:05:28 -0500
committerRusty Russell <rusty@rustcorp.com.au>2008-01-30 06:50:08 -0500
commitad8d8f3bc61ec712dd141e1029ae68c47fadc4a7 (patch)
tree70bd69e85ef7f159a62f4cd8aa2799d8d542b92c
parent73044f05a4ac65f2df42753e9566444b9d2a660f (diff)
lguest: 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 <gcosta@redhat.com> Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
-rw-r--r--drivers/lguest/hypercalls.c2
-rw-r--r--drivers/lguest/interrupts_and_traps.c20
-rw-r--r--drivers/lguest/lg.h10
-rw-r--r--drivers/lguest/lguest_user.c10
4 files changed, 21 insertions, 21 deletions
diff --git a/drivers/lguest/hypercalls.c b/drivers/lguest/hypercalls.c
index 7827671b2234..6f8c70ae380d 100644
--- a/drivers/lguest/hypercalls.c
+++ b/drivers/lguest/hypercalls.c
@@ -80,7 +80,7 @@ static void do_hcall(struct lg_cpu *cpu, struct hcall_args *args)
80 guest_set_pmd(lg, args->arg1, args->arg2); 80 guest_set_pmd(lg, args->arg1, args->arg2);
81 break; 81 break;
82 case LHCALL_SET_CLOCKEVENT: 82 case LHCALL_SET_CLOCKEVENT:
83 guest_set_clockevent(lg, args->arg1); 83 guest_set_clockevent(cpu, args->arg1);
84 break; 84 break;
85 case LHCALL_TS: 85 case LHCALL_TS:
86 /* This sets the TS flag, as we saw used in run_guest(). */ 86 /* 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 2b66f79c208b..22c692aae51c 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,
470 * infrastructure to set a callback at that time. 470 * infrastructure to set a callback at that time.
471 * 471 *
472 * 0 means "turn off the clock". */ 472 * 0 means "turn off the clock". */
473void guest_set_clockevent(struct lguest *lg, unsigned long delta) 473void guest_set_clockevent(struct lg_cpu *cpu, unsigned long delta)
474{ 474{
475 ktime_t expires; 475 ktime_t expires;
476 476
477 if (unlikely(delta == 0)) { 477 if (unlikely(delta == 0)) {
478 /* Clock event device is shutting down. */ 478 /* Clock event device is shutting down. */
479 hrtimer_cancel(&lg->hrt); 479 hrtimer_cancel(&cpu->hrt);
480 return; 480 return;
481 } 481 }
482 482
@@ -484,25 +484,25 @@ void guest_set_clockevent(struct lguest *lg, unsigned long delta)
484 * all the time between now and the timer interrupt it asked for. This 484 * all the time between now and the timer interrupt it asked for. This
485 * is almost always the right thing to do. */ 485 * is almost always the right thing to do. */
486 expires = ktime_add_ns(ktime_get_real(), delta); 486 expires = ktime_add_ns(ktime_get_real(), delta);
487 hrtimer_start(&lg->hrt, expires, HRTIMER_MODE_ABS); 487 hrtimer_start(&cpu->hrt, expires, HRTIMER_MODE_ABS);
488} 488}
489 489
490/* This is the function called when the Guest's timer expires. */ 490/* This is the function called when the Guest's timer expires. */
491static enum hrtimer_restart clockdev_fn(struct hrtimer *timer) 491static enum hrtimer_restart clockdev_fn(struct hrtimer *timer)
492{ 492{
493 struct lguest *lg = container_of(timer, struct lguest, hrt); 493 struct lg_cpu *cpu = container_of(timer, struct lg_cpu, hrt);
494 494
495 /* Remember the first interrupt is the timer interrupt. */ 495 /* Remember the first interrupt is the timer interrupt. */
496 set_bit(0, lg->irqs_pending); 496 set_bit(0, cpu->lg->irqs_pending);
497 /* If the Guest is actually stopped, we need to wake it up. */ 497 /* If the Guest is actually stopped, we need to wake it up. */
498 if (lg->halted) 498 if (cpu->lg->halted)
499 wake_up_process(lg->tsk); 499 wake_up_process(cpu->lg->tsk);
500 return HRTIMER_NORESTART; 500 return HRTIMER_NORESTART;
501} 501}
502 502
503/* This sets up the timer for this Guest. */ 503/* This sets up the timer for this Guest. */
504void init_clockdev(struct lguest *lg) 504void init_clockdev(struct lg_cpu *cpu)
505{ 505{
506 hrtimer_init(&lg->hrt, CLOCK_REALTIME, HRTIMER_MODE_ABS); 506 hrtimer_init(&cpu->hrt, CLOCK_REALTIME, HRTIMER_MODE_ABS);
507 lg->hrt.function = clockdev_fn; 507 cpu->hrt.function = clockdev_fn;
508} 508}
diff --git a/drivers/lguest/lg.h b/drivers/lguest/lg.h
index a4ebd415fa27..7da7b3f68da8 100644
--- a/drivers/lguest/lg.h
+++ b/drivers/lguest/lg.h
@@ -47,6 +47,9 @@ struct lg_cpu {
47 /* If a hypercall was asked for, this points to the arguments. */ 47 /* If a hypercall was asked for, this points to the arguments. */
48 struct hcall_args *hcall; 48 struct hcall_args *hcall;
49 u32 next_hcall; 49 u32 next_hcall;
50
51 /* Virtual clock device */
52 struct hrtimer hrt;
50}; 53};
51 54
52/* The private info the thread maintains about the guest. */ 55/* The private info the thread maintains about the guest. */
@@ -95,9 +98,6 @@ struct lguest
95 98
96 struct lguest_arch arch; 99 struct lguest_arch arch;
97 100
98 /* Virtual clock device */
99 struct hrtimer hrt;
100
101 /* Pending virtual interrupts */ 101 /* Pending virtual interrupts */
102 DECLARE_BITMAP(irqs_pending, LGUEST_IRQS); 102 DECLARE_BITMAP(irqs_pending, LGUEST_IRQS);
103}; 103};
@@ -145,8 +145,8 @@ void setup_default_idt_entries(struct lguest_ro_state *state,
145 const unsigned long *def); 145 const unsigned long *def);
146void copy_traps(const struct lguest *lg, struct desc_struct *idt, 146void copy_traps(const struct lguest *lg, struct desc_struct *idt,
147 const unsigned long *def); 147 const unsigned long *def);
148void guest_set_clockevent(struct lguest *lg, unsigned long delta); 148void guest_set_clockevent(struct lg_cpu *cpu, unsigned long delta);
149void init_clockdev(struct lguest *lg); 149void init_clockdev(struct lg_cpu *cpu);
150bool check_syscall_vector(struct lguest *lg); 150bool check_syscall_vector(struct lguest *lg);
151int init_interrupts(void); 151int init_interrupts(void);
152void free_interrupts(void); 152void free_interrupts(void);
diff --git a/drivers/lguest/lguest_user.c b/drivers/lguest/lguest_user.c
index 2562082a3ea3..f231b9be0b64 100644
--- a/drivers/lguest/lguest_user.c
+++ b/drivers/lguest/lguest_user.c
@@ -104,6 +104,7 @@ static int lg_cpu_start(struct lg_cpu *cpu, unsigned id, unsigned long start_ip)
104 cpu->id = id; 104 cpu->id = id;
105 cpu->lg = container_of((cpu - id), struct lguest, cpus[0]); 105 cpu->lg = container_of((cpu - id), struct lguest, cpus[0]);
106 cpu->lg->nr_cpus++; 106 cpu->lg->nr_cpus++;
107 init_clockdev(cpu);
107 108
108 return 0; 109 return 0;
109} 110}
@@ -180,9 +181,6 @@ static int initialize(struct file *file, const unsigned long __user *input)
180 * address. */ 181 * address. */
181 lguest_arch_setup_regs(lg, args[3]); 182 lguest_arch_setup_regs(lg, args[3]);
182 183
183 /* The timer for lguest's clock needs initialization. */
184 init_clockdev(lg);
185
186 /* We keep a pointer to the Launcher task (ie. current task) for when 184 /* We keep a pointer to the Launcher task (ie. current task) for when
187 * other Guests want to wake this one (inter-Guest I/O). */ 185 * other Guests want to wake this one (inter-Guest I/O). */
188 lg->tsk = current; 186 lg->tsk = current;
@@ -273,6 +271,7 @@ static ssize_t write(struct file *file, const char __user *in,
273static int close(struct inode *inode, struct file *file) 271static int close(struct inode *inode, struct file *file)
274{ 272{
275 struct lguest *lg = file->private_data; 273 struct lguest *lg = file->private_data;
274 unsigned int i;
276 275
277 /* If we never successfully initialized, there's nothing to clean up */ 276 /* If we never successfully initialized, there's nothing to clean up */
278 if (!lg) 277 if (!lg)
@@ -281,8 +280,9 @@ static int close(struct inode *inode, struct file *file)
281 /* We need the big lock, to protect from inter-guest I/O and other 280 /* We need the big lock, to protect from inter-guest I/O and other
282 * Launchers initializing guests. */ 281 * Launchers initializing guests. */
283 mutex_lock(&lguest_lock); 282 mutex_lock(&lguest_lock);
284 /* Cancels the hrtimer set via LHCALL_SET_CLOCKEVENT. */ 283 for (i = 0; i < lg->nr_cpus; i++)
285 hrtimer_cancel(&lg->hrt); 284 /* Cancels the hrtimer set via LHCALL_SET_CLOCKEVENT. */
285 hrtimer_cancel(&lg->cpus[i].hrt);
286 /* Free up the shadow page tables for the Guest. */ 286 /* Free up the shadow page tables for the Guest. */
287 free_guest_pagetable(lg); 287 free_guest_pagetable(lg);
288 /* Now all the memory cleanups are done, it's safe to release the 288 /* Now all the memory cleanups are done, it's safe to release the