2019-08-25 17:49:19 +08:00
|
|
|
/* SPDX-License-Identifier: GPL-2.0 */
|
2015-11-03 00:16:37 +08:00
|
|
|
/*
|
|
|
|
* Copyright (C) 2012 - 2014 Cisco Systems
|
|
|
|
* Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef __TIMER_INTERNAL_H__
|
|
|
|
#define __TIMER_INTERNAL_H__
|
um: time-travel: Rewrite as an event scheduler
Instead of tracking all the various timer configurations,
modify the time-travel mode to have an event scheduler and
use a timer event on the scheduler to handle the different
timer configurations.
This doesn't change the function right now, but it prepares
the code for having different kinds of events in the future
(i.e. interrupts coming from other devices that are part of
co-simulation.)
While at it, also move time_travel_sleep() to time.c to
reduce the externally visible API surface.
Also, we really should mark time-travel as incompatible with
SMP, even if UML doesn't support SMP yet.
Finally, I noticed a bug while developing this - if we move
time forward due to consuming time while reading the clock,
we might move across the next event and that would cause us
to go backward in time when we then handle that event. Fix
that by invoking the whole event machine in this case, but
in order to simplify this, make reading the clock only cost
something when interrupts are not disabled. Otherwise, we'd
have to hook into the interrupt delivery machinery etc. and
that's somewhat intrusive.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Richard Weinberger <richard@nod.at>
2020-02-13 21:26:45 +08:00
|
|
|
#include <linux/list.h>
|
2015-11-03 00:16:37 +08:00
|
|
|
|
|
|
|
#define TIMER_MULTIPLIER 256
|
|
|
|
#define TIMER_MIN_DELTA 500
|
|
|
|
|
2019-05-27 16:34:27 +08:00
|
|
|
enum time_travel_mode {
|
|
|
|
TT_MODE_OFF,
|
|
|
|
TT_MODE_BASIC,
|
|
|
|
TT_MODE_INFCPU,
|
2020-02-13 21:26:47 +08:00
|
|
|
TT_MODE_EXTERNAL,
|
2019-05-27 16:34:27 +08:00
|
|
|
};
|
|
|
|
|
um: time-travel: Rewrite as an event scheduler
Instead of tracking all the various timer configurations,
modify the time-travel mode to have an event scheduler and
use a timer event on the scheduler to handle the different
timer configurations.
This doesn't change the function right now, but it prepares
the code for having different kinds of events in the future
(i.e. interrupts coming from other devices that are part of
co-simulation.)
While at it, also move time_travel_sleep() to time.c to
reduce the externally visible API surface.
Also, we really should mark time-travel as incompatible with
SMP, even if UML doesn't support SMP yet.
Finally, I noticed a bug while developing this - if we move
time forward due to consuming time while reading the clock,
we might move across the next event and that would cause us
to go backward in time when we then handle that event. Fix
that by invoking the whole event machine in this case, but
in order to simplify this, make reading the clock only cost
something when interrupts are not disabled. Otherwise, we'd
have to hook into the interrupt delivery machinery etc. and
that's somewhat intrusive.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Richard Weinberger <richard@nod.at>
2020-02-13 21:26:45 +08:00
|
|
|
#ifdef CONFIG_UML_TIME_TRAVEL_SUPPORT
|
|
|
|
struct time_travel_event {
|
|
|
|
unsigned long long time;
|
|
|
|
void (*fn)(struct time_travel_event *d);
|
|
|
|
struct list_head list;
|
|
|
|
bool pending, onstack;
|
2019-05-27 16:34:27 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
extern enum time_travel_mode time_travel_mode;
|
|
|
|
|
um: time-travel: Rewrite as an event scheduler
Instead of tracking all the various timer configurations,
modify the time-travel mode to have an event scheduler and
use a timer event on the scheduler to handle the different
timer configurations.
This doesn't change the function right now, but it prepares
the code for having different kinds of events in the future
(i.e. interrupts coming from other devices that are part of
co-simulation.)
While at it, also move time_travel_sleep() to time.c to
reduce the externally visible API surface.
Also, we really should mark time-travel as incompatible with
SMP, even if UML doesn't support SMP yet.
Finally, I noticed a bug while developing this - if we move
time forward due to consuming time while reading the clock,
we might move across the next event and that would cause us
to go backward in time when we then handle that event. Fix
that by invoking the whole event machine in this case, but
in order to simplify this, make reading the clock only cost
something when interrupts are not disabled. Otherwise, we'd
have to hook into the interrupt delivery machinery etc. and
that's somewhat intrusive.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Richard Weinberger <richard@nod.at>
2020-02-13 21:26:45 +08:00
|
|
|
void time_travel_sleep(unsigned long long duration);
|
2019-05-27 16:34:27 +08:00
|
|
|
|
um: time-travel: Rewrite as an event scheduler
Instead of tracking all the various timer configurations,
modify the time-travel mode to have an event scheduler and
use a timer event on the scheduler to handle the different
timer configurations.
This doesn't change the function right now, but it prepares
the code for having different kinds of events in the future
(i.e. interrupts coming from other devices that are part of
co-simulation.)
While at it, also move time_travel_sleep() to time.c to
reduce the externally visible API surface.
Also, we really should mark time-travel as incompatible with
SMP, even if UML doesn't support SMP yet.
Finally, I noticed a bug while developing this - if we move
time forward due to consuming time while reading the clock,
we might move across the next event and that would cause us
to go backward in time when we then handle that event. Fix
that by invoking the whole event machine in this case, but
in order to simplify this, make reading the clock only cost
something when interrupts are not disabled. Otherwise, we'd
have to hook into the interrupt delivery machinery etc. and
that's somewhat intrusive.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Richard Weinberger <richard@nod.at>
2020-02-13 21:26:45 +08:00
|
|
|
static inline void
|
|
|
|
time_travel_set_event_fn(struct time_travel_event *e,
|
|
|
|
void (*fn)(struct time_travel_event *d))
|
2019-05-27 16:34:27 +08:00
|
|
|
{
|
um: time-travel: Rewrite as an event scheduler
Instead of tracking all the various timer configurations,
modify the time-travel mode to have an event scheduler and
use a timer event on the scheduler to handle the different
timer configurations.
This doesn't change the function right now, but it prepares
the code for having different kinds of events in the future
(i.e. interrupts coming from other devices that are part of
co-simulation.)
While at it, also move time_travel_sleep() to time.c to
reduce the externally visible API surface.
Also, we really should mark time-travel as incompatible with
SMP, even if UML doesn't support SMP yet.
Finally, I noticed a bug while developing this - if we move
time forward due to consuming time while reading the clock,
we might move across the next event and that would cause us
to go backward in time when we then handle that event. Fix
that by invoking the whole event machine in this case, but
in order to simplify this, make reading the clock only cost
something when interrupts are not disabled. Otherwise, we'd
have to hook into the interrupt delivery machinery etc. and
that's somewhat intrusive.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Richard Weinberger <richard@nod.at>
2020-02-13 21:26:45 +08:00
|
|
|
e->fn = fn;
|
2019-09-10 23:03:52 +08:00
|
|
|
}
|
2020-02-13 21:26:47 +08:00
|
|
|
|
|
|
|
void __time_travel_propagate_time(void);
|
|
|
|
|
|
|
|
static inline void time_travel_propagate_time(void)
|
|
|
|
{
|
|
|
|
if (time_travel_mode == TT_MODE_EXTERNAL)
|
|
|
|
__time_travel_propagate_time();
|
|
|
|
}
|
|
|
|
|
|
|
|
void __time_travel_wait_readable(int fd);
|
|
|
|
|
|
|
|
static inline void time_travel_wait_readable(int fd)
|
|
|
|
{
|
|
|
|
if (time_travel_mode == TT_MODE_EXTERNAL)
|
|
|
|
__time_travel_wait_readable(fd);
|
|
|
|
}
|
|
|
|
|
|
|
|
void time_travel_add_irq_event(struct time_travel_event *e);
|
2019-05-27 16:34:27 +08:00
|
|
|
#else
|
um: time-travel: Rewrite as an event scheduler
Instead of tracking all the various timer configurations,
modify the time-travel mode to have an event scheduler and
use a timer event on the scheduler to handle the different
timer configurations.
This doesn't change the function right now, but it prepares
the code for having different kinds of events in the future
(i.e. interrupts coming from other devices that are part of
co-simulation.)
While at it, also move time_travel_sleep() to time.c to
reduce the externally visible API surface.
Also, we really should mark time-travel as incompatible with
SMP, even if UML doesn't support SMP yet.
Finally, I noticed a bug while developing this - if we move
time forward due to consuming time while reading the clock,
we might move across the next event and that would cause us
to go backward in time when we then handle that event. Fix
that by invoking the whole event machine in this case, but
in order to simplify this, make reading the clock only cost
something when interrupts are not disabled. Otherwise, we'd
have to hook into the interrupt delivery machinery etc. and
that's somewhat intrusive.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Richard Weinberger <richard@nod.at>
2020-02-13 21:26:45 +08:00
|
|
|
struct time_travel_event {
|
|
|
|
};
|
2019-07-22 15:12:56 +08:00
|
|
|
|
um: time-travel: Rewrite as an event scheduler
Instead of tracking all the various timer configurations,
modify the time-travel mode to have an event scheduler and
use a timer event on the scheduler to handle the different
timer configurations.
This doesn't change the function right now, but it prepares
the code for having different kinds of events in the future
(i.e. interrupts coming from other devices that are part of
co-simulation.)
While at it, also move time_travel_sleep() to time.c to
reduce the externally visible API surface.
Also, we really should mark time-travel as incompatible with
SMP, even if UML doesn't support SMP yet.
Finally, I noticed a bug while developing this - if we move
time forward due to consuming time while reading the clock,
we might move across the next event and that would cause us
to go backward in time when we then handle that event. Fix
that by invoking the whole event machine in this case, but
in order to simplify this, make reading the clock only cost
something when interrupts are not disabled. Otherwise, we'd
have to hook into the interrupt delivery machinery etc. and
that's somewhat intrusive.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Richard Weinberger <richard@nod.at>
2020-02-13 21:26:45 +08:00
|
|
|
#define time_travel_mode TT_MODE_OFF
|
2019-07-03 16:52:01 +08:00
|
|
|
|
um: time-travel: Rewrite as an event scheduler
Instead of tracking all the various timer configurations,
modify the time-travel mode to have an event scheduler and
use a timer event on the scheduler to handle the different
timer configurations.
This doesn't change the function right now, but it prepares
the code for having different kinds of events in the future
(i.e. interrupts coming from other devices that are part of
co-simulation.)
While at it, also move time_travel_sleep() to time.c to
reduce the externally visible API surface.
Also, we really should mark time-travel as incompatible with
SMP, even if UML doesn't support SMP yet.
Finally, I noticed a bug while developing this - if we move
time forward due to consuming time while reading the clock,
we might move across the next event and that would cause us
to go backward in time when we then handle that event. Fix
that by invoking the whole event machine in this case, but
in order to simplify this, make reading the clock only cost
something when interrupts are not disabled. Otherwise, we'd
have to hook into the interrupt delivery machinery etc. and
that's somewhat intrusive.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Richard Weinberger <richard@nod.at>
2020-02-13 21:26:45 +08:00
|
|
|
static inline void time_travel_sleep(unsigned long long duration)
|
2019-09-10 23:03:52 +08:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
um: time-travel: Rewrite as an event scheduler
Instead of tracking all the various timer configurations,
modify the time-travel mode to have an event scheduler and
use a timer event on the scheduler to handle the different
timer configurations.
This doesn't change the function right now, but it prepares
the code for having different kinds of events in the future
(i.e. interrupts coming from other devices that are part of
co-simulation.)
While at it, also move time_travel_sleep() to time.c to
reduce the externally visible API surface.
Also, we really should mark time-travel as incompatible with
SMP, even if UML doesn't support SMP yet.
Finally, I noticed a bug while developing this - if we move
time forward due to consuming time while reading the clock,
we might move across the next event and that would cause us
to go backward in time when we then handle that event. Fix
that by invoking the whole event machine in this case, but
in order to simplify this, make reading the clock only cost
something when interrupts are not disabled. Otherwise, we'd
have to hook into the interrupt delivery machinery etc. and
that's somewhat intrusive.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Richard Weinberger <richard@nod.at>
2020-02-13 21:26:45 +08:00
|
|
|
/* this is a macro so the event/function need not exist */
|
|
|
|
#define time_travel_set_event_fn(e, fn) do {} while (0)
|
2020-02-13 21:26:47 +08:00
|
|
|
|
|
|
|
static inline void time_travel_propagate_time(void)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void time_travel_wait_readable(int fd)
|
|
|
|
{
|
|
|
|
}
|
um: time-travel: Rewrite as an event scheduler
Instead of tracking all the various timer configurations,
modify the time-travel mode to have an event scheduler and
use a timer event on the scheduler to handle the different
timer configurations.
This doesn't change the function right now, but it prepares
the code for having different kinds of events in the future
(i.e. interrupts coming from other devices that are part of
co-simulation.)
While at it, also move time_travel_sleep() to time.c to
reduce the externally visible API surface.
Also, we really should mark time-travel as incompatible with
SMP, even if UML doesn't support SMP yet.
Finally, I noticed a bug while developing this - if we move
time forward due to consuming time while reading the clock,
we might move across the next event and that would cause us
to go backward in time when we then handle that event. Fix
that by invoking the whole event machine in this case, but
in order to simplify this, make reading the clock only cost
something when interrupts are not disabled. Otherwise, we'd
have to hook into the interrupt delivery machinery etc. and
that's somewhat intrusive.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Richard Weinberger <richard@nod.at>
2020-02-13 21:26:45 +08:00
|
|
|
#endif /* CONFIG_UML_TIME_TRAVEL_SUPPORT */
|
2020-02-13 21:26:48 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Without CONFIG_UML_TIME_TRAVEL_SUPPORT this is a linker error if used,
|
|
|
|
* which is intentional since we really shouldn't link it in that case.
|
|
|
|
*/
|
|
|
|
void time_travel_ndelay(unsigned long nsec);
|
um: time-travel: Rewrite as an event scheduler
Instead of tracking all the various timer configurations,
modify the time-travel mode to have an event scheduler and
use a timer event on the scheduler to handle the different
timer configurations.
This doesn't change the function right now, but it prepares
the code for having different kinds of events in the future
(i.e. interrupts coming from other devices that are part of
co-simulation.)
While at it, also move time_travel_sleep() to time.c to
reduce the externally visible API surface.
Also, we really should mark time-travel as incompatible with
SMP, even if UML doesn't support SMP yet.
Finally, I noticed a bug while developing this - if we move
time forward due to consuming time while reading the clock,
we might move across the next event and that would cause us
to go backward in time when we then handle that event. Fix
that by invoking the whole event machine in this case, but
in order to simplify this, make reading the clock only cost
something when interrupts are not disabled. Otherwise, we'd
have to hook into the interrupt delivery machinery etc. and
that's somewhat intrusive.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Richard Weinberger <richard@nod.at>
2020-02-13 21:26:45 +08:00
|
|
|
#endif /* __TIMER_INTERNAL_H__ */
|