Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ad8d8f3b authored by Glauber de Oliveira Costa's avatar Glauber de Oliveira Costa Committed by Rusty Russell
Browse files

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: default avatarGlauber de Oliveira Costa <gcosta@redhat.com>
Signed-off-by: default avatarRusty Russell <rusty@rustcorp.com.au>
parent 73044f05
Loading
Loading
Loading
Loading
+1 −1
Original line number Original line Diff line number Diff line
@@ -80,7 +80,7 @@ static void do_hcall(struct lg_cpu *cpu, struct hcall_args *args)
		guest_set_pmd(lg, args->arg1, args->arg2);
		guest_set_pmd(lg, args->arg1, args->arg2);
		break;
		break;
	case LHCALL_SET_CLOCKEVENT:
	case LHCALL_SET_CLOCKEVENT:
		guest_set_clockevent(lg, args->arg1);
		guest_set_clockevent(cpu, args->arg1);
		break;
		break;
	case LHCALL_TS:
	case LHCALL_TS:
		/* This sets the TS flag, as we saw used in run_guest(). */
		/* This sets the TS flag, as we saw used in run_guest(). */
+10 −10
Original line number Original line Diff line number Diff line
@@ -470,13 +470,13 @@ void copy_traps(const struct lguest *lg, struct desc_struct *idt,
 * infrastructure to set a callback at that time.
 * infrastructure to set a callback at that time.
 *
 *
 * 0 means "turn off the clock". */
 * 0 means "turn off the clock". */
void guest_set_clockevent(struct lguest *lg, unsigned long delta)
void guest_set_clockevent(struct lg_cpu *cpu, unsigned long delta)
{
{
	ktime_t expires;
	ktime_t expires;


	if (unlikely(delta == 0)) {
	if (unlikely(delta == 0)) {
		/* Clock event device is shutting down. */
		/* Clock event device is shutting down. */
		hrtimer_cancel(&lg->hrt);
		hrtimer_cancel(&cpu->hrt);
		return;
		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
	 * all the time between now and the timer interrupt it asked for.  This
	 * is almost always the right thing to do. */
	 * is almost always the right thing to do. */
	expires = ktime_add_ns(ktime_get_real(), delta);
	expires = ktime_add_ns(ktime_get_real(), delta);
	hrtimer_start(&lg->hrt, expires, HRTIMER_MODE_ABS);
	hrtimer_start(&cpu->hrt, expires, HRTIMER_MODE_ABS);
}
}


/* This is the function called when the Guest's timer expires. */
/* This is the function called when the Guest's timer expires. */
static enum hrtimer_restart clockdev_fn(struct hrtimer *timer)
static enum hrtimer_restart clockdev_fn(struct hrtimer *timer)
{
{
	struct lguest *lg = container_of(timer, struct lguest, hrt);
	struct lg_cpu *cpu = container_of(timer, struct lg_cpu, hrt);


	/* Remember the first interrupt is the timer interrupt. */
	/* Remember the first interrupt is the timer interrupt. */
	set_bit(0, lg->irqs_pending);
	set_bit(0, cpu->lg->irqs_pending);
	/* If the Guest is actually stopped, we need to wake it up. */
	/* If the Guest is actually stopped, we need to wake it up. */
	if (lg->halted)
	if (cpu->lg->halted)
		wake_up_process(lg->tsk);
		wake_up_process(cpu->lg->tsk);
	return HRTIMER_NORESTART;
	return HRTIMER_NORESTART;
}
}


/* This sets up the timer for this Guest. */
/* This sets up the timer for this Guest. */
void init_clockdev(struct lguest *lg)
void init_clockdev(struct lg_cpu *cpu)
{
{
	hrtimer_init(&lg->hrt, CLOCK_REALTIME, HRTIMER_MODE_ABS);
	hrtimer_init(&cpu->hrt, CLOCK_REALTIME, HRTIMER_MODE_ABS);
	lg->hrt.function = clockdev_fn;
	cpu->hrt.function = clockdev_fn;
}
}
+5 −5
Original line number Original line Diff line number Diff line
@@ -47,6 +47,9 @@ struct lg_cpu {
	/* If a hypercall was asked for, this points to the arguments. */
	/* If a hypercall was asked for, this points to the arguments. */
	struct hcall_args *hcall;
	struct hcall_args *hcall;
	u32 next_hcall;
	u32 next_hcall;

	/* Virtual clock device */
	struct hrtimer hrt;
};
};


/* The private info the thread maintains about the guest. */
/* The private info the thread maintains about the guest. */
@@ -95,9 +98,6 @@ struct lguest


	struct lguest_arch arch;
	struct lguest_arch arch;


	/* Virtual clock device */
	struct hrtimer hrt;

	/* Pending virtual interrupts */
	/* Pending virtual interrupts */
	DECLARE_BITMAP(irqs_pending, LGUEST_IRQS);
	DECLARE_BITMAP(irqs_pending, LGUEST_IRQS);
};
};
@@ -145,8 +145,8 @@ void setup_default_idt_entries(struct lguest_ro_state *state,
			       const unsigned long *def);
			       const unsigned long *def);
void copy_traps(const struct lguest *lg, struct desc_struct *idt,
void copy_traps(const struct lguest *lg, struct desc_struct *idt,
		const unsigned long *def);
		const unsigned long *def);
void guest_set_clockevent(struct lguest *lg, unsigned long delta);
void guest_set_clockevent(struct lg_cpu *cpu, unsigned long delta);
void init_clockdev(struct lguest *lg);
void init_clockdev(struct lg_cpu *cpu);
bool check_syscall_vector(struct lguest *lg);
bool check_syscall_vector(struct lguest *lg);
int init_interrupts(void);
int init_interrupts(void);
void free_interrupts(void);
void free_interrupts(void);
+5 −5
Original line number Original line Diff line number Diff line
@@ -104,6 +104,7 @@ static int lg_cpu_start(struct lg_cpu *cpu, unsigned id, unsigned long start_ip)
	cpu->id = id;
	cpu->id = id;
	cpu->lg = container_of((cpu - id), struct lguest, cpus[0]);
	cpu->lg = container_of((cpu - id), struct lguest, cpus[0]);
	cpu->lg->nr_cpus++;
	cpu->lg->nr_cpus++;
	init_clockdev(cpu);


	return 0;
	return 0;
}
}
@@ -180,9 +181,6 @@ static int initialize(struct file *file, const unsigned long __user *input)
	 * address. */
	 * address. */
	lguest_arch_setup_regs(lg, args[3]);
	lguest_arch_setup_regs(lg, args[3]);


	/* The timer for lguest's clock needs initialization. */
	init_clockdev(lg);

	/* We keep a pointer to the Launcher task (ie. current task) for when
	/* We keep a pointer to the Launcher task (ie. current task) for when
	 * other Guests want to wake this one (inter-Guest I/O). */
	 * other Guests want to wake this one (inter-Guest I/O). */
	lg->tsk = current;
	lg->tsk = current;
@@ -273,6 +271,7 @@ static ssize_t write(struct file *file, const char __user *in,
static int close(struct inode *inode, struct file *file)
static int close(struct inode *inode, struct file *file)
{
{
	struct lguest *lg = file->private_data;
	struct lguest *lg = file->private_data;
	unsigned int i;


	/* If we never successfully initialized, there's nothing to clean up */
	/* If we never successfully initialized, there's nothing to clean up */
	if (!lg)
	if (!lg)
@@ -281,8 +280,9 @@ static int close(struct inode *inode, struct file *file)
	/* We need the big lock, to protect from inter-guest I/O and other
	/* We need the big lock, to protect from inter-guest I/O and other
	 * Launchers initializing guests. */
	 * Launchers initializing guests. */
	mutex_lock(&lguest_lock);
	mutex_lock(&lguest_lock);
	for (i = 0; i < lg->nr_cpus; i++)
		/* Cancels the hrtimer set via LHCALL_SET_CLOCKEVENT. */
		/* Cancels the hrtimer set via LHCALL_SET_CLOCKEVENT. */
	hrtimer_cancel(&lg->hrt);
		hrtimer_cancel(&lg->cpus[i].hrt);
	/* Free up the shadow page tables for the Guest. */
	/* Free up the shadow page tables for the Guest. */
	free_guest_pagetable(lg);
	free_guest_pagetable(lg);
	/* Now all the memory cleanups are done, it's safe to release the
	/* Now all the memory cleanups are done, it's safe to release the