Commit 9c82de55 authored by Tiwei Bie's avatar Tiwei Bie Committed by Johannes Berg
Browse files

um: Define timers on a per-CPU basis



Define timers on a per-CPU basis to enable each CPU to have its
own timer. This is a preparation for adding SMP support.

Signed-off-by: default avatarTiwei Bie <tiwei.btw@antgroup.com>
Link: https://patch.msgid.link/20251027001815.1666872-5-tiwei.bie@linux.dev


Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent 2670917c
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -90,4 +90,7 @@ extern unsigned long tt_extra_sched_jiffies;
 * which is intentional since we really shouldn't link it in that case.
 */
void time_travel_ndelay(unsigned long nsec);

int um_setup_timer(void);

#endif /* __TIMER_INTERNAL_H__ */
+3 −3
Original line number Diff line number Diff line
@@ -269,9 +269,9 @@ extern void os_warn(const char *fmt, ...)
/* time.c */
extern void os_idle_sleep(void);
extern int os_timer_create(void);
extern int os_timer_set_interval(unsigned long long nsecs);
extern int os_timer_one_shot(unsigned long long nsecs);
extern void os_timer_disable(void);
extern int os_timer_set_interval(int cpu, unsigned long long nsecs);
extern int os_timer_one_shot(int cpu, unsigned long long nsecs);
extern void os_timer_disable(int cpu);
extern long long os_persistent_clock_emulation(void);
extern long long os_nsecs(void);

+1 −1
Original line number Diff line number Diff line
@@ -683,7 +683,7 @@ void __init init_IRQ(void)
{
	int i;

	irq_set_chip_and_handler(TIMER_IRQ, &alarm_irq_type, handle_edge_irq);
	irq_set_chip_and_handler(TIMER_IRQ, &alarm_irq_type, handle_percpu_irq);

	for (i = 1; i < UM_LAST_SIGNAL_IRQ; i++)
		irq_set_chip_and_handler(i, &normal_irq_type, handle_edge_irq);
+41 −17
Original line number Diff line number Diff line
@@ -625,9 +625,10 @@ void time_travel_sleep(void)
	 * controller application.
	 */
	unsigned long long next = S64_MAX;
	int cpu = raw_smp_processor_id();

	if (time_travel_mode == TT_MODE_BASIC)
		os_timer_disable();
		os_timer_disable(cpu);

	time_travel_update_time(next, true);

@@ -638,9 +639,9 @@ void time_travel_sleep(void)
			 * This is somewhat wrong - we should get the first
			 * one sooner like the os_timer_one_shot() below...
			 */
			os_timer_set_interval(time_travel_timer_interval);
			os_timer_set_interval(cpu, time_travel_timer_interval);
		} else {
			os_timer_one_shot(time_travel_timer_event.time - next);
			os_timer_one_shot(cpu, time_travel_timer_event.time - next);
		}
	}
}
@@ -758,6 +759,8 @@ extern u64 time_travel_ext_req(u32 op, u64 time);
#define time_travel_del_event(e) do { } while (0)
#endif

static struct clock_event_device timer_clockevent[NR_CPUS];

void timer_handler(int sig, struct siginfo *unused_si, struct uml_pt_regs *regs)
{
	unsigned long flags;
@@ -780,12 +783,14 @@ void timer_handler(int sig, struct siginfo *unused_si, struct uml_pt_regs *regs)

static int itimer_shutdown(struct clock_event_device *evt)
{
	int cpu = evt - &timer_clockevent[0];

	if (time_travel_mode != TT_MODE_OFF)
		time_travel_del_event(&time_travel_timer_event);

	if (time_travel_mode != TT_MODE_INFCPU &&
	    time_travel_mode != TT_MODE_EXTERNAL)
		os_timer_disable();
		os_timer_disable(cpu);

	return 0;
}
@@ -793,6 +798,7 @@ static int itimer_shutdown(struct clock_event_device *evt)
static int itimer_set_periodic(struct clock_event_device *evt)
{
	unsigned long long interval = NSEC_PER_SEC / HZ;
	int cpu = evt - &timer_clockevent[0];

	if (time_travel_mode != TT_MODE_OFF) {
		time_travel_del_event(&time_travel_timer_event);
@@ -805,7 +811,7 @@ static int itimer_set_periodic(struct clock_event_device *evt)

	if (time_travel_mode != TT_MODE_INFCPU &&
	    time_travel_mode != TT_MODE_EXTERNAL)
		os_timer_set_interval(interval);
		os_timer_set_interval(cpu, interval);

	return 0;
}
@@ -825,7 +831,7 @@ static int itimer_next_event(unsigned long delta,

	if (time_travel_mode != TT_MODE_INFCPU &&
	    time_travel_mode != TT_MODE_EXTERNAL)
		return os_timer_one_shot(delta);
		return os_timer_one_shot(raw_smp_processor_id(), delta);

	return 0;
}
@@ -835,10 +841,9 @@ static int itimer_one_shot(struct clock_event_device *evt)
	return itimer_next_event(0, evt);
}

static struct clock_event_device timer_clockevent = {
static struct clock_event_device _timer_clockevent = {
	.name			= "posix-timer",
	.rating			= 250,
	.cpumask		= cpu_possible_mask,
	.features		= CLOCK_EVT_FEAT_PERIODIC |
				  CLOCK_EVT_FEAT_ONESHOT,
	.set_state_shutdown	= itimer_shutdown,
@@ -856,6 +861,9 @@ static struct clock_event_device timer_clockevent = {

static irqreturn_t um_timer(int irq, void *dev)
{
	int cpu = raw_smp_processor_id();
	struct clock_event_device *evt = &timer_clockevent[cpu];

	/*
	 * Interrupt the (possibly) running userspace process, technically this
	 * should only happen if userspace is currently executing.
@@ -867,7 +875,7 @@ static irqreturn_t um_timer(int irq, void *dev)
	    get_current()->mm)
		os_alarm_process(get_current()->mm->context.id.pid);

	(*timer_clockevent.event_handler)(&timer_clockevent);
	evt->event_handler(evt);

	return IRQ_HANDLED;
}
@@ -904,7 +912,24 @@ static struct clocksource timer_clocksource = {
	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
};

static void __init um_timer_setup(void)
int um_setup_timer(void)
{
	int cpu = raw_smp_processor_id();
	struct clock_event_device *evt = &timer_clockevent[cpu];
	int err;

	err = os_timer_create();
	if (err)
		return err;

	memcpy(evt, &_timer_clockevent, sizeof(*evt));
	evt->cpumask = cpumask_of(cpu);
	clockevents_register_device(evt);

	return 0;
}

static void __init um_timer_init(void)
{
	int err;

@@ -913,8 +938,8 @@ static void __init um_timer_setup(void)
		printk(KERN_ERR "register_timer : request_irq failed - "
		       "errno = %d\n", -err);

	err = os_timer_create();
	if (err != 0) {
	err = um_setup_timer();
	if (err) {
		printk(KERN_ERR "creation of timer failed - errno = %d\n", -err);
		return;
	}
@@ -924,7 +949,6 @@ static void __init um_timer_setup(void)
		printk(KERN_ERR "clocksource_register_hz returned %d\n", err);
		return;
	}
	clockevents_register_device(&timer_clockevent);
}

void read_persistent_clock64(struct timespec64 *ts)
@@ -945,7 +969,7 @@ void read_persistent_clock64(struct timespec64 *ts)
void __init time_init(void)
{
	timer_set_signal_handler();
	late_time_init = um_timer_setup;
	late_time_init = um_timer_init;
}

#ifdef CONFIG_UML_TIME_TRAVEL_SUPPORT
@@ -961,21 +985,21 @@ static int setup_time_travel(char *str)
{
	if (strcmp(str, "=inf-cpu") == 0) {
		time_travel_mode = TT_MODE_INFCPU;
		timer_clockevent.name = "time-travel-timer-infcpu";
		_timer_clockevent.name = "time-travel-timer-infcpu";
		timer_clocksource.name = "time-travel-clock";
		return 1;
	}

	if (strncmp(str, "=ext:", 5) == 0) {
		time_travel_mode = TT_MODE_EXTERNAL;
		timer_clockevent.name = "time-travel-timer-external";
		_timer_clockevent.name = "time-travel-timer-external";
		timer_clocksource.name = "time-travel-clock-external";
		return time_travel_connect_external(str + 5);
	}

	if (!*str) {
		time_travel_mode = TT_MODE_BASIC;
		timer_clockevent.name = "time-travel-timer";
		_timer_clockevent.name = "time-travel-timer";
		timer_clocksource.name = "time-travel-clock";
		return 1;
	}
+1 −1
Original line number Diff line number Diff line
@@ -171,7 +171,7 @@ int __init main(int argc, char **argv, char **envp)
	 */

	/* stop timers and set timer signal to be ignored */
	os_timer_disable();
	os_timer_disable(0);

	/* disable SIGIO for the fds and set SIGIO to be ignored */
	err = deactivate_all_fds();
Loading