diff options
author | Glauber de Oliveira Costa <gcosta@redhat.com> | 2008-01-07 08:05:28 -0500 |
---|---|---|
committer | Rusty Russell <rusty@rustcorp.com.au> | 2008-01-30 06:50:08 -0500 |
commit | ad8d8f3bc61ec712dd141e1029ae68c47fadc4a7 (patch) | |
tree | 70bd69e85ef7f159a62f4cd8aa2799d8d542b92c | |
parent | 73044f05a4ac65f2df42753e9566444b9d2a660f (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.c | 2 | ||||
-rw-r--r-- | drivers/lguest/interrupts_and_traps.c | 20 | ||||
-rw-r--r-- | drivers/lguest/lg.h | 10 | ||||
-rw-r--r-- | drivers/lguest/lguest_user.c | 10 |
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". */ |
473 | void guest_set_clockevent(struct lguest *lg, unsigned long delta) | 473 | void 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. */ |
491 | static enum hrtimer_restart clockdev_fn(struct hrtimer *timer) | 491 | static 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. */ |
504 | void init_clockdev(struct lguest *lg) | 504 | void 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); |
146 | void copy_traps(const struct lguest *lg, struct desc_struct *idt, | 146 | void copy_traps(const struct lguest *lg, struct desc_struct *idt, |
147 | const unsigned long *def); | 147 | const unsigned long *def); |
148 | void guest_set_clockevent(struct lguest *lg, unsigned long delta); | 148 | void guest_set_clockevent(struct lg_cpu *cpu, unsigned long delta); |
149 | void init_clockdev(struct lguest *lg); | 149 | void init_clockdev(struct lg_cpu *cpu); |
150 | bool check_syscall_vector(struct lguest *lg); | 150 | bool check_syscall_vector(struct lguest *lg); |
151 | int init_interrupts(void); | 151 | int init_interrupts(void); |
152 | void free_interrupts(void); | 152 | void 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, | |||
273 | static int close(struct inode *inode, struct file *file) | 271 | static 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 |