* [PATCH RT 0/4] Linux v4.19.255-rt114-rc2
@ 2022-11-03 7:55 Daniel Wagner
2022-11-03 7:55 ` [PATCH RT 1/4] timers: Prepare support for PREEMPT_RT Daniel Wagner
` (3 more replies)
0 siblings, 4 replies; 5+ messages in thread
From: Daniel Wagner @ 2022-11-03 7:55 UTC (permalink / raw)
To: LKML, linux-rt-users, Steven Rostedt, Thomas Gleixner,
Carsten Emde, John Kacur, Sebastian Andrzej Siewior, Tom Zanussi,
Clark Williams, Pavel Machek
Cc: Daniel Wagner
Dear RT Folks,
This is the RT stable review cycle of patch 4.19.255-rt114-rc2.
Please scream at me if I messed something up. Please test the patches
too.
The -rc release will be uploaded to kernel.org and will be deleted
when the final release is out. This is just a review release (or
release candidate).
The pre-releases will not be pushed to the git repository, only the
final release is.
If all goes well, this patch will be converted to the next main
release on 2022-11-10.
To build 4.19.255-rt114-rc2 directly, the following patches should be applied:
https://www.kernel.org/pub/linux/kernel/v4.x/linux-4.19.tar.xz
https://www.kernel.org/pub/linux/kernel/v4.x/patch-4.19.255.xz
https://www.kernel.org/pub/linux/kernel/projects/rt/4.19/older/patch-4.19.255-rt114-rc2.patch.xz
Signing key fingerprint:
5BF6 7BC5 0826 72CA BB45 ACAE 587C 5ECA 5D0A 306C
All keys used for the above files and repositories can be found on the
following git repository:
git://git.kernel.org/pub/scm/docs/kernel/pgpkeys.git
Enjoy!
Daniel
Changes from v4.19.255-rt114-rc1:
Anna-Maria Gleixner (1):
timers: Prepare support for PREEMPT_RT
Daniel Wagner (1):
Linux 4.19.255-rt114-rc2
Sebastian Andrzej Siewior (1):
timers: Don't block on ->expiry_lock for TIMER_IRQSAFE timers
Thomas Gleixner (1):
timers: Move clearing of base::timer_running under base:: Lock
kernel/time/timer.c | 137 +++++++++++++++++++++++++++++++-------------
localversion-rt | 2 +-
2 files changed, 98 insertions(+), 41 deletions(-)
--
2.38.0
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH RT 1/4] timers: Prepare support for PREEMPT_RT
2022-11-03 7:55 [PATCH RT 0/4] Linux v4.19.255-rt114-rc2 Daniel Wagner
@ 2022-11-03 7:55 ` Daniel Wagner
2022-11-03 7:55 ` [PATCH RT 2/4] timers: Move clearing of base::timer_running under base:: Lock Daniel Wagner
` (2 subsequent siblings)
3 siblings, 0 replies; 5+ messages in thread
From: Daniel Wagner @ 2022-11-03 7:55 UTC (permalink / raw)
To: LKML, linux-rt-users, Steven Rostedt, Thomas Gleixner,
Carsten Emde, John Kacur, Sebastian Andrzej Siewior, Tom Zanussi,
Clark Williams, Pavel Machek
Cc: Anna-Maria Gleixner, Peter Zijlstra, Daniel Wagner
From: Anna-Maria Gleixner <anna-maria@linutronix.de>
v4.19.255-rt114-rc2 stable review patch.
If anyone has any objections, please let me know.
-----------
Upstream commit 030dcdd197d77374879bb5603d091eee7d8aba80
When PREEMPT_RT is enabled, the soft interrupt thread can be preempted. If
the soft interrupt thread is preempted in the middle of a timer callback,
then calling del_timer_sync() can lead to two issues:
- If the caller is on a remote CPU then it has to spin wait for the timer
handler to complete. This can result in unbound priority inversion.
- If the caller originates from the task which preempted the timer
handler on the same CPU, then spin waiting for the timer handler to
complete is never going to end.
To avoid these issues, add a new lock to the timer base which is held
around the execution of the timer callbacks. If del_timer_sync() detects
that the timer callback is currently running, it blocks on the expiry
lock. When the callback is finished, the expiry lock is dropped by the
softirq thread which wakes up the waiter and the system makes progress.
This addresses both the priority inversion and the life lock issues.
This mechanism is not used for timers which are marked IRQSAFE as for those
preemption is disabled accross the callback and therefore this situation
cannot happen. The callbacks for such timers need to be individually
audited for RT compliance.
The same issue can happen in virtual machines when the vCPU which runs a
timer callback is scheduled out. If a second vCPU of the same guest calls
del_timer_sync() it will spin wait for the other vCPU to be scheduled back
in. The expiry lock mechanism would avoid that. It'd be trivial to enable
this when paravirt spinlocks are enabled in a guest, but it's not clear
whether this is an actual problem in the wild, so for now it's an RT only
mechanism.
As the softirq thread can be preempted with PREEMPT_RT=y, the SMP variant
of del_timer_sync() needs to be used on UP as well.
[ tglx: Refactored it for mainline ]
Signed-off-by: Anna-Maria Gleixner <anna-maria@linutronix.de>
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Link: https://lkml.kernel.org/r/20190726185753.832418500@linutronix.de
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Daniel Wagner <wagi@monom.org>
---
kernel/time/timer.c | 130 ++++++++++++++++++++++++++++++--------------
1 file changed, 88 insertions(+), 42 deletions(-)
diff --git a/kernel/time/timer.c b/kernel/time/timer.c
index 0a6d60b3e67c..b859ecf6424b 100644
--- a/kernel/time/timer.c
+++ b/kernel/time/timer.c
@@ -198,7 +198,10 @@ EXPORT_SYMBOL(jiffies_64);
struct timer_base {
raw_spinlock_t lock;
struct timer_list *running_timer;
+#ifdef CONFIG_PREEMPT_RT
spinlock_t expiry_lock;
+ atomic_t timer_waiters;
+#endif
unsigned long clk;
unsigned long next_expiry;
unsigned int cpu;
@@ -1227,8 +1230,14 @@ int del_timer(struct timer_list *timer)
}
EXPORT_SYMBOL(del_timer);
-static int __try_to_del_timer_sync(struct timer_list *timer,
- struct timer_base **basep)
+/**
+ * try_to_del_timer_sync - Try to deactivate a timer
+ * @timer: timer to delete
+ *
+ * This function tries to deactivate a timer. Upon successful (ret >= 0)
+ * exit the timer is not queued and the handler is not running on any CPU.
+ */
+int try_to_del_timer_sync(struct timer_list *timer)
{
struct timer_base *base;
unsigned long flags;
@@ -1236,7 +1245,7 @@ static int __try_to_del_timer_sync(struct timer_list *timer,
debug_assert_init(timer);
- *basep = base = lock_timer_base(timer, &flags);
+ base = lock_timer_base(timer, &flags);
if (base->running_timer != timer)
ret = detach_if_pending(timer, base, true);
@@ -1245,45 +1254,80 @@ static int __try_to_del_timer_sync(struct timer_list *timer,
return ret;
}
+EXPORT_SYMBOL(try_to_del_timer_sync);
-/**
- * try_to_del_timer_sync - Try to deactivate a timer
- * @timer: timer to delete
- *
- * This function tries to deactivate a timer. Upon successful (ret >= 0)
- * exit the timer is not queued and the handler is not running on any CPU.
- */
-int try_to_del_timer_sync(struct timer_list *timer)
+#ifdef CONFIG_PREEMPT_RT
+static __init void timer_base_init_expiry_lock(struct timer_base *base)
{
- struct timer_base *base;
+ spin_lock_init(&base->expiry_lock);
+}
- return __try_to_del_timer_sync(timer, &base);
+static inline void timer_base_lock_expiry(struct timer_base *base)
+{
+ spin_lock(&base->expiry_lock);
}
-EXPORT_SYMBOL(try_to_del_timer_sync);
-#if defined(CONFIG_SMP) || defined(CONFIG_PREEMPT_RT_FULL)
-static int __del_timer_sync(struct timer_list *timer)
+static inline void timer_base_unlock_expiry(struct timer_base *base)
{
- struct timer_base *base;
- int ret;
+ spin_unlock(&base->expiry_lock);
+}
- for (;;) {
- ret = __try_to_del_timer_sync(timer, &base);
- if (ret >= 0)
- return ret;
+/*
+ * The counterpart to del_timer_wait_running().
+ *
+ * If there is a waiter for base->expiry_lock, then it was waiting for the
+ * timer callback to finish. Drop expiry_lock and reaquire it. That allows
+ * the waiter to acquire the lock and make progress.
+ */
+static void timer_sync_wait_running(struct timer_base *base)
+{
+ if (atomic_read(&base->timer_waiters)) {
+ spin_unlock(&base->expiry_lock);
+ spin_lock(&base->expiry_lock);
+ }
+}
- if (READ_ONCE(timer->flags) & TIMER_IRQSAFE)
- continue;
+/*
+ * This function is called on PREEMPT_RT kernels when the fast path
+ * deletion of a timer failed because the timer callback function was
+ * running.
+ *
+ * This prevents priority inversion, if the softirq thread on a remote CPU
+ * got preempted, and it prevents a life lock when the task which tries to
+ * delete a timer preempted the softirq thread running the timer callback
+ * function.
+ */
+static void del_timer_wait_running(struct timer_list *timer)
+{
+ u32 tf;
+
+ tf = READ_ONCE(timer->flags);
+ if (!(tf & TIMER_MIGRATING)) {
+ struct timer_base *base = get_timer_base(tf);
/*
- * When accessing the lock, timers of base are no longer expired
- * and so timer is no longer running.
+ * Mark the base as contended and grab the expiry lock,
+ * which is held by the softirq across the timer
+ * callback. Drop the lock immediately so the softirq can
+ * expire the next timer. In theory the timer could already
+ * be running again, but that's more than unlikely and just
+ * causes another wait loop.
*/
- spin_lock(&base->expiry_lock);
- spin_unlock(&base->expiry_lock);
+ atomic_inc(&base->timer_waiters);
+ spin_lock_bh(&base->expiry_lock);
+ atomic_dec(&base->timer_waiters);
+ spin_unlock_bh(&base->expiry_lock);
}
}
+#else
+static inline void timer_base_init_expiry_lock(struct timer_base *base) { }
+static inline void timer_base_lock_expiry(struct timer_base *base) { }
+static inline void timer_base_unlock_expiry(struct timer_base *base) { }
+static inline void timer_sync_wait_running(struct timer_base *base) { }
+static inline void del_timer_wait_running(struct timer_list *timer) { }
+#endif
+#if defined(CONFIG_SMP) || defined(CONFIG_PREEMPT_RT_FULL)
/**
* del_timer_sync - deactivate a timer and wait for the handler to finish.
* @timer: the timer to be deactivated
@@ -1322,6 +1366,8 @@ static int __del_timer_sync(struct timer_list *timer)
*/
int del_timer_sync(struct timer_list *timer)
{
+ int ret;
+
#ifdef CONFIG_LOCKDEP
unsigned long flags;
@@ -1339,14 +1385,17 @@ int del_timer_sync(struct timer_list *timer)
* could lead to deadlock.
*/
WARN_ON(in_irq() && !(timer->flags & TIMER_IRQSAFE));
- /*
- * Must be able to sleep on PREEMPT_RT because of the slowpath in
- * __del_timer_sync().
- */
- if (IS_ENABLED(CONFIG_PREEMPT_RT) && !(timer->flags & TIMER_IRQSAFE))
- might_sleep();
- return __del_timer_sync(timer);
+ do {
+ ret = try_to_del_timer_sync(timer);
+
+ if (unlikely(ret < 0)) {
+ del_timer_wait_running(timer);
+ cpu_relax();
+ }
+ } while (ret < 0);
+
+ return ret;
}
EXPORT_SYMBOL(del_timer_sync);
#endif
@@ -1410,15 +1459,12 @@ static void expire_timers(struct timer_base *base, struct hlist_head *head)
raw_spin_unlock(&base->lock);
call_timer_fn(timer, fn);
base->running_timer = NULL;
- spin_unlock(&base->expiry_lock);
- spin_lock(&base->expiry_lock);
raw_spin_lock(&base->lock);
} else {
raw_spin_unlock_irq(&base->lock);
call_timer_fn(timer, fn);
base->running_timer = NULL;
- spin_unlock(&base->expiry_lock);
- spin_lock(&base->expiry_lock);
+ timer_sync_wait_running(base);
raw_spin_lock_irq(&base->lock);
}
}
@@ -1715,7 +1761,7 @@ static inline void __run_timers(struct timer_base *base)
if (!time_after_eq(jiffies, base->clk))
return;
- spin_lock(&base->expiry_lock);
+ timer_base_lock_expiry(base);
raw_spin_lock_irq(&base->lock);
/*
@@ -1743,7 +1789,7 @@ static inline void __run_timers(struct timer_base *base)
expire_timers(base, heads + levels);
}
raw_spin_unlock_irq(&base->lock);
- spin_unlock(&base->expiry_lock);
+ timer_base_unlock_expiry(base);
}
/*
@@ -1990,7 +2036,7 @@ static void __init init_timer_cpu(int cpu)
base->cpu = cpu;
raw_spin_lock_init(&base->lock);
base->clk = jiffies;
- spin_lock_init(&base->expiry_lock);
+ timer_base_init_expiry_lock(base);
}
}
--
2.38.0
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH RT 2/4] timers: Move clearing of base::timer_running under base:: Lock
2022-11-03 7:55 [PATCH RT 0/4] Linux v4.19.255-rt114-rc2 Daniel Wagner
2022-11-03 7:55 ` [PATCH RT 1/4] timers: Prepare support for PREEMPT_RT Daniel Wagner
@ 2022-11-03 7:55 ` Daniel Wagner
2022-11-03 7:55 ` [PATCH RT 3/4] timers: Don't block on ->expiry_lock for TIMER_IRQSAFE timers Daniel Wagner
2022-11-03 7:55 ` [PATCH RT 4/4] Linux 4.19.255-rt114-rc2 Daniel Wagner
3 siblings, 0 replies; 5+ messages in thread
From: Daniel Wagner @ 2022-11-03 7:55 UTC (permalink / raw)
To: LKML, linux-rt-users, Steven Rostedt, Thomas Gleixner,
Carsten Emde, John Kacur, Sebastian Andrzej Siewior, Tom Zanussi,
Clark Williams, Pavel Machek
Cc: syzbot+aa7c2385d46c5eba0b89, syzbot+abea4558531bae1ba9fe, stable,
Daniel Wagner
From: Thomas Gleixner <tglx@linutronix.de>
v4.19.255-rt114-rc2 stable review patch.
If anyone has any objections, please let me know.
-----------
Upstream commit bb7262b295472eb6858b5c49893954794027cd84
syzbot reported KCSAN data races vs. timer_base::timer_running being set to
NULL without holding base::lock in expire_timers().
This looks innocent and most reads are clearly not problematic, but
Frederic identified an issue which is:
int data = 0;
void timer_func(struct timer_list *t)
{
data = 1;
}
CPU 0 CPU 1
------------------------------ --------------------------
base = lock_timer_base(timer, &flags); raw_spin_unlock(&base->lock);
if (base->running_timer != timer) call_timer_fn(timer, fn, baseclk);
ret = detach_if_pending(timer, base, true); base->running_timer = NULL;
raw_spin_unlock_irqrestore(&base->lock, flags); raw_spin_lock(&base->lock);
x = data;
If the timer has previously executed on CPU 1 and then CPU 0 can observe
base->running_timer == NULL and returns, assuming the timer has completed,
but it's not guaranteed on all architectures. The comment for
del_timer_sync() makes that guarantee. Moving the assignment under
base->lock prevents this.
For non-RT kernel it's performance wise completely irrelevant whether the
store happens before or after taking the lock. For an RT kernel moving the
store under the lock requires an extra unlock/lock pair in the case that
there is a waiter for the timer, but that's not the end of the world.
Reported-by: syzbot+aa7c2385d46c5eba0b89@syzkaller.appspotmail.com
Reported-by: syzbot+abea4558531bae1ba9fe@syzkaller.appspotmail.com
Fixes: 030dcdd197d7 ("timers: Prepare support for PREEMPT_RT")
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Tested-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Link: https://lore.kernel.org/r/87lfea7gw8.fsf@nanos.tec.linutronix.de
Cc: stable@vger.kernel.org
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Daniel Wagner <wagi@monom.org>
---
kernel/time/timer.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/kernel/time/timer.c b/kernel/time/timer.c
index b859ecf6424b..603985720f54 100644
--- a/kernel/time/timer.c
+++ b/kernel/time/timer.c
@@ -1282,8 +1282,10 @@ static inline void timer_base_unlock_expiry(struct timer_base *base)
static void timer_sync_wait_running(struct timer_base *base)
{
if (atomic_read(&base->timer_waiters)) {
+ raw_spin_unlock_irq(&base->lock);
spin_unlock(&base->expiry_lock);
spin_lock(&base->expiry_lock);
+ raw_spin_lock_irq(&base->lock);
}
}
@@ -1458,14 +1460,14 @@ static void expire_timers(struct timer_base *base, struct hlist_head *head)
if (timer->flags & TIMER_IRQSAFE) {
raw_spin_unlock(&base->lock);
call_timer_fn(timer, fn);
- base->running_timer = NULL;
raw_spin_lock(&base->lock);
+ base->running_timer = NULL;
} else {
raw_spin_unlock_irq(&base->lock);
call_timer_fn(timer, fn);
+ raw_spin_lock_irq(&base->lock);
base->running_timer = NULL;
timer_sync_wait_running(base);
- raw_spin_lock_irq(&base->lock);
}
}
}
--
2.38.0
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH RT 3/4] timers: Don't block on ->expiry_lock for TIMER_IRQSAFE timers
2022-11-03 7:55 [PATCH RT 0/4] Linux v4.19.255-rt114-rc2 Daniel Wagner
2022-11-03 7:55 ` [PATCH RT 1/4] timers: Prepare support for PREEMPT_RT Daniel Wagner
2022-11-03 7:55 ` [PATCH RT 2/4] timers: Move clearing of base::timer_running under base:: Lock Daniel Wagner
@ 2022-11-03 7:55 ` Daniel Wagner
2022-11-03 7:55 ` [PATCH RT 4/4] Linux 4.19.255-rt114-rc2 Daniel Wagner
3 siblings, 0 replies; 5+ messages in thread
From: Daniel Wagner @ 2022-11-03 7:55 UTC (permalink / raw)
To: LKML, linux-rt-users, Steven Rostedt, Thomas Gleixner,
Carsten Emde, John Kacur, Sebastian Andrzej Siewior, Tom Zanussi,
Clark Williams, Pavel Machek
Cc: Mike Galbraith, Daniel Wagner
From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
v4.19.255-rt114-rc2 stable review patch.
If anyone has any objections, please let me know.
-----------
Upstream commit c725dafc95f1b37027840aaeaa8b7e4e9cd20516
PREEMPT_RT does not spin and wait until a running timer completes its
callback but instead it blocks on a sleeping lock to prevent a livelock in
the case that the task waiting for the callback completion preempted the
callback.
This cannot be done for timers flagged with TIMER_IRQSAFE. These timers can
be canceled from an interrupt disabled context even on RT kernels.
The expiry callback of such timers is invoked with interrupts disabled so
there is no need to use the expiry lock mechanism because obviously the
callback cannot be preempted even on RT kernels.
Do not use the timer_base::expiry_lock mechanism when waiting for a running
callback to complete if the timer is flagged with TIMER_IRQSAFE.
Also add a lockdep assertion for RT kernels to validate that the expiry
lock mechanism is always invoked in preemptible context.
[ bigeasy: Dropping that lockdep_assert_preemption_enabled() check in
backport ]
Reported-by: Mike Galbraith <efault@gmx.de>
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Link: https://lore.kernel.org/r/20201103190937.hga67rqhvknki3tp@linutronix.de
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Daniel Wagner <wagi@monom.org>
---
kernel/time/timer.c | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)
diff --git a/kernel/time/timer.c b/kernel/time/timer.c
index 603985720f54..8c7bfcee9609 100644
--- a/kernel/time/timer.c
+++ b/kernel/time/timer.c
@@ -1304,7 +1304,7 @@ static void del_timer_wait_running(struct timer_list *timer)
u32 tf;
tf = READ_ONCE(timer->flags);
- if (!(tf & TIMER_MIGRATING)) {
+ if (!(tf & (TIMER_MIGRATING | TIMER_IRQSAFE))) {
struct timer_base *base = get_timer_base(tf);
/*
@@ -1388,6 +1388,15 @@ int del_timer_sync(struct timer_list *timer)
*/
WARN_ON(in_irq() && !(timer->flags & TIMER_IRQSAFE));
+ /*
+ * Must be able to sleep on PREEMPT_RT because of the slowpath in
+ * del_timer_wait_running().
+ */
+#if 0
+ if (IS_ENABLED(CONFIG_PREEMPT_RT) && !(timer->flags & TIMER_IRQSAFE))
+ lockdep_assert_preemption_enabled();
+#endif
+
do {
ret = try_to_del_timer_sync(timer);
--
2.38.0
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH RT 4/4] Linux 4.19.255-rt114-rc2
2022-11-03 7:55 [PATCH RT 0/4] Linux v4.19.255-rt114-rc2 Daniel Wagner
` (2 preceding siblings ...)
2022-11-03 7:55 ` [PATCH RT 3/4] timers: Don't block on ->expiry_lock for TIMER_IRQSAFE timers Daniel Wagner
@ 2022-11-03 7:55 ` Daniel Wagner
3 siblings, 0 replies; 5+ messages in thread
From: Daniel Wagner @ 2022-11-03 7:55 UTC (permalink / raw)
To: LKML, linux-rt-users, Steven Rostedt, Thomas Gleixner,
Carsten Emde, John Kacur, Sebastian Andrzej Siewior, Tom Zanussi,
Clark Williams, Pavel Machek
Cc: Daniel Wagner
v4.19.255-rt114-rc2 stable review patch.
If anyone has any objections, please let me know.
-----------
Signed-off-by: Daniel Wagner <wagi@monom.org>
---
localversion-rt | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/localversion-rt b/localversion-rt
index fdcd9167ca0b..02781f8a2f80 100644
--- a/localversion-rt
+++ b/localversion-rt
@@ -1 +1 @@
--rt113
+-rt114-rc2
--
2.38.0
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2022-11-03 7:57 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-11-03 7:55 [PATCH RT 0/4] Linux v4.19.255-rt114-rc2 Daniel Wagner
2022-11-03 7:55 ` [PATCH RT 1/4] timers: Prepare support for PREEMPT_RT Daniel Wagner
2022-11-03 7:55 ` [PATCH RT 2/4] timers: Move clearing of base::timer_running under base:: Lock Daniel Wagner
2022-11-03 7:55 ` [PATCH RT 3/4] timers: Don't block on ->expiry_lock for TIMER_IRQSAFE timers Daniel Wagner
2022-11-03 7:55 ` [PATCH RT 4/4] Linux 4.19.255-rt114-rc2 Daniel Wagner
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®