summaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorPaolo Bonzini <pbonzini@redhat.com>2026-06-12 09:55:30 +0200
committerPaolo Bonzini <pbonzini@redhat.com>2026-06-12 09:55:30 +0200
commit94e6ddf9a0caf407d628ef41c92b59371e1cd338 (patch)
tree06b4cc281422aa64525293ed4633ddc8175c66a6 /include
parent9fb628b4cd3488a36e3fc9b22bb840048aa1a9d2 (diff)
parentabeb7eb57f1671d9185ddf11236c784f07bdb928 (diff)
Merge tag 'kvm-s390-master-7.1-4' of https://git.kernel.org/pub/scm/linux/kernel/git/kvms390/linux into HEAD
KVM: s390: A few more misc gmap fixes.
Diffstat (limited to 'include')
-rw-r--r--include/hyperv/hvgdk.h10
-rw-r--r--include/hyperv/hvhdk.h1
-rw-r--r--include/linux/cfi.h1
-rw-r--r--include/linux/hugetlb.h8
-rw-r--r--include/linux/hyperv.h7
-rw-r--r--include/linux/mm.h8
-rw-r--r--include/linux/rseq_entry.h5
-rw-r--r--include/linux/tracepoint.h8
-rw-r--r--include/net/act_api.h1
-rw-r--r--include/net/bluetooth/l2cap.h1
-rw-r--r--include/net/ip_vs.h3
-rw-r--r--include/net/mptcp.h7
-rw-r--r--include/net/tc_act/tc_pedit.h1
-rw-r--r--include/rdma/ib_umem.h8
-rw-r--r--include/rv/da_monitor.h139
-rw-r--r--include/rv/ha_monitor.h91
-rw-r--r--include/rv/ltl_monitor.h1
-rw-r--r--include/uapi/linux/tee.h1
18 files changed, 242 insertions, 59 deletions
diff --git a/include/hyperv/hvgdk.h b/include/hyperv/hvgdk.h
index 384c3f3ff4a5..f538144280ca 100644
--- a/include/hyperv/hvgdk.h
+++ b/include/hyperv/hvgdk.h
@@ -10,18 +10,12 @@
/*
* The guest OS needs to register the guest ID with the hypervisor.
- * The guest ID is a 64 bit entity and the structure of this ID is
+ * The guest ID is a 64-bit entity and the structure of this ID is
* specified in the Hyper-V TLFS specification.
*
- * While the current guideline does not specify how Linux guest ID(s)
- * need to be generated, our plan is to publish the guidelines for
- * Linux and other guest operating systems that currently are hosted
- * on Hyper-V. The implementation here conforms to this yet
- * unpublished guidelines.
- *
* Bit(s)
* 63 - Indicates if the OS is Open Source or not; 1 is Open Source
- * 62:56 - Os Type; Linux is 0x100
+ * 62:56 - OS Type; Linux is 0x1
* 55:48 - Distro specific identification
* 47:16 - Linux kernel version number
* 15:0 - Distro specific identification
diff --git a/include/hyperv/hvhdk.h b/include/hyperv/hvhdk.h
index 5e83d3714966..0c89c62c9706 100644
--- a/include/hyperv/hvhdk.h
+++ b/include/hyperv/hvhdk.h
@@ -79,6 +79,7 @@ struct hv_vp_register_page {
u64 registers[18];
};
+ u8 reserved[8];
/* Volatile XMM registers (HV_X64_REGISTER_CLASS_XMM) */
union {
struct {
diff --git a/include/linux/cfi.h b/include/linux/cfi.h
index 1fd22ea6eba4..0f220d29225c 100644
--- a/include/linux/cfi.h
+++ b/include/linux/cfi.h
@@ -9,6 +9,7 @@
#include <linux/bug.h>
#include <linux/module.h>
+#include <linux/uaccess.h>
#include <asm/cfi.h>
#ifdef CONFIG_CFI
diff --git a/include/linux/hugetlb.h b/include/linux/hugetlb.h
index 5957bc25efa8..2abaf99321e9 100644
--- a/include/linux/hugetlb.h
+++ b/include/linux/hugetlb.h
@@ -153,8 +153,6 @@ long hugetlb_unreserve_pages(struct inode *inode, long start, long end,
long freed);
bool folio_isolate_hugetlb(struct folio *folio, struct list_head *list);
int get_hwpoison_hugetlb_folio(struct folio *folio, bool *hugetlb, bool unpoison);
-int get_huge_page_for_hwpoison(unsigned long pfn, int flags,
- bool *migratable_cleared);
void folio_putback_hugetlb(struct folio *folio);
void move_hugetlb_state(struct folio *old_folio, struct folio *new_folio, int reason);
void hugetlb_fix_reserve_counts(struct inode *inode);
@@ -421,12 +419,6 @@ static inline int get_hwpoison_hugetlb_folio(struct folio *folio, bool *hugetlb,
return 0;
}
-static inline int get_huge_page_for_hwpoison(unsigned long pfn, int flags,
- bool *migratable_cleared)
-{
- return 0;
-}
-
static inline void folio_putback_hugetlb(struct folio *folio)
{
}
diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h
index 964f1be8150c..734b7ef98f4d 100644
--- a/include/linux/hyperv.h
+++ b/include/linux/hyperv.h
@@ -1304,7 +1304,11 @@ static inline void *hv_get_drvdata(struct hv_device *dev)
struct device *hv_get_vmbus_root_device(void);
+#if IS_ENABLED(CONFIG_HYPERV_VMBUS)
bool hv_vmbus_exists(void);
+#else
+static inline bool hv_vmbus_exists(void) { return false; }
+#endif
struct hv_ring_buffer_debug_info {
u32 current_interrupt_mask;
@@ -1336,6 +1340,9 @@ int vmbus_allocate_mmio(struct resource **new, struct hv_device *device_obj,
bool fb_overlap_ok);
void vmbus_free_mmio(resource_size_t start, resource_size_t size);
+void vmbus_initiate_unload(bool crash);
+void vmbus_set_skip_unload(bool skip);
+
/*
* GUID definitions of various offer types - services offered to the guest.
*/
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 06bbe9eba636..fc2acedf0b76 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -4975,8 +4975,6 @@ extern int soft_offline_page(unsigned long pfn, int flags);
*/
extern const struct attribute_group memory_failure_attr_group;
extern void memory_failure_queue(unsigned long pfn, int flags);
-extern int __get_huge_page_for_hwpoison(unsigned long pfn, int flags,
- bool *migratable_cleared);
void num_poisoned_pages_inc(unsigned long pfn);
void num_poisoned_pages_sub(unsigned long pfn, long i);
#else
@@ -4984,12 +4982,6 @@ static inline void memory_failure_queue(unsigned long pfn, int flags)
{
}
-static inline int __get_huge_page_for_hwpoison(unsigned long pfn, int flags,
- bool *migratable_cleared)
-{
- return 0;
-}
-
static inline void num_poisoned_pages_inc(unsigned long pfn)
{
}
diff --git a/include/linux/rseq_entry.h b/include/linux/rseq_entry.h
index 63bc72086e75..ed9da6e41a2a 100644
--- a/include/linux/rseq_entry.h
+++ b/include/linux/rseq_entry.h
@@ -635,10 +635,11 @@ static __always_inline bool rseq_exit_user_update(struct pt_regs *regs, struct t
return true;
}
+ int cpu = task_cpu(t);
struct rseq_ids ids = {
- .cpu_id = task_cpu(t),
+ .cpu_id = cpu,
.mm_cid = task_mm_cid(t),
- .node_id = cpu_to_node(ids.cpu_id),
+ .node_id = cpu_to_node(cpu),
};
return rseq_update_usr(t, regs, &ids);
diff --git a/include/linux/tracepoint.h b/include/linux/tracepoint.h
index 763eea4d80d8..2d2b9f8cdda4 100644
--- a/include/linux/tracepoint.h
+++ b/include/linux/tracepoint.h
@@ -20,6 +20,7 @@
#include <linux/rcupdate_trace.h>
#include <linux/tracepoint-defs.h>
#include <linux/static_call.h>
+#include <linux/cfi.h>
struct module;
struct tracepoint;
@@ -389,6 +390,13 @@ static inline struct tracepoint *tracepoint_ptr_deref(tracepoint_ptr_t *p)
void __probestub_##_name(void *__data, proto) \
{ \
} \
+ /* \
+ * Annotate the probestub 'CFI_NOSEAL' to stop objtool from \
+ * requesting the kernel remove the ENDBR, because the only \
+ * references to the function are in the __tracepoint section, \
+ * that objtool doesn't scan. \
+ */ \
+ CFI_NOSEAL(__probestub_##_name); \
DEFINE_STATIC_CALL(tp_func_##_name, __traceiter_##_name); \
DEFINE_RUST_DO_TRACE(_name, TP_PROTO(proto), TP_ARGS(args))
diff --git a/include/net/act_api.h b/include/net/act_api.h
index d11b79107930..fd2967ee08f7 100644
--- a/include/net/act_api.h
+++ b/include/net/act_api.h
@@ -45,6 +45,7 @@ struct tc_action {
struct tc_cookie __rcu *user_cookie;
struct tcf_chain __rcu *goto_chain;
u32 tcfa_flags;
+ struct rcu_head tcfa_rcu;
u8 hw_stats;
u8 used_hw_stats;
bool used_hw_stats_valid;
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index 5172afee5494..e0a1f2293679 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -33,6 +33,7 @@
/* L2CAP defaults */
#define L2CAP_DEFAULT_MTU 672
#define L2CAP_DEFAULT_MIN_MTU 48
+#define L2CAP_SIG_MTU 48 /* BR/EDR signaling MTU */
#define L2CAP_DEFAULT_FLUSH_TO 0xFFFF
#define L2CAP_EFS_DEFAULT_FLUSH_TO 0xFFFFFFFF
#define L2CAP_DEFAULT_TX_WINDOW 63
diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h
index a02e569813d2..e517eaaa177b 100644
--- a/include/net/ip_vs.h
+++ b/include/net/ip_vs.h
@@ -1824,8 +1824,7 @@ int register_ip_vs_scheduler(struct ip_vs_scheduler *scheduler);
int unregister_ip_vs_scheduler(struct ip_vs_scheduler *scheduler);
int ip_vs_bind_scheduler(struct ip_vs_service *svc,
struct ip_vs_scheduler *scheduler);
-void ip_vs_unbind_scheduler(struct ip_vs_service *svc,
- struct ip_vs_scheduler *sched);
+void ip_vs_unbind_scheduler(struct ip_vs_service *svc);
struct ip_vs_scheduler *ip_vs_scheduler_get(const char *sched_name);
void ip_vs_scheduler_put(struct ip_vs_scheduler *scheduler);
struct ip_vs_conn *
diff --git a/include/net/mptcp.h b/include/net/mptcp.h
index f7263fe2a2e4..ee70f597a4de 100644
--- a/include/net/mptcp.h
+++ b/include/net/mptcp.h
@@ -27,7 +27,9 @@ struct mptcp_ext {
u32 subflow_seq;
u16 data_len;
__sum16 csum;
- u8 use_map:1,
+
+ struct_group(flags,
+ u8 use_map:1,
dsn64:1,
data_fin:1,
use_ack:1,
@@ -35,9 +37,10 @@ struct mptcp_ext {
mpc_map:1,
frozen:1,
reset_transient:1;
- u8 reset_reason:4,
+ u8 reset_reason:4,
csum_reqd:1,
infinite_map:1;
+ ); /* end of flags group */
};
#define MPTCPOPT_HMAC_LEN 20
diff --git a/include/net/tc_act/tc_pedit.h b/include/net/tc_act/tc_pedit.h
index f58ee15cd858..cb7b82f2cbc7 100644
--- a/include/net/tc_act/tc_pedit.h
+++ b/include/net/tc_act/tc_pedit.h
@@ -15,7 +15,6 @@ struct tcf_pedit_parms {
struct tc_pedit_key *tcfp_keys;
struct tcf_pedit_key_ex *tcfp_keys_ex;
int action;
- u32 tcfp_off_max_hint;
unsigned char tcfp_nkeys;
unsigned char tcfp_flags;
struct rcu_head rcu;
diff --git a/include/rdma/ib_umem.h b/include/rdma/ib_umem.h
index 2ad52cc1d52b..49172098a8de 100644
--- a/include/rdma/ib_umem.h
+++ b/include/rdma/ib_umem.h
@@ -156,6 +156,8 @@ void ib_umem_dmabuf_revoke_lock(struct ib_umem_dmabuf *umem_dmabuf);
void ib_umem_dmabuf_revoke_unlock(struct ib_umem_dmabuf *umem_dmabuf);
void ib_umem_dmabuf_revoke(struct ib_umem_dmabuf *umem_dmabuf);
+int ib_umem_check_rereg(struct ib_umem *umem, int flags, int new_access_flags);
+
#else /* CONFIG_INFINIBAND_USER_MEM */
#include <linux/err.h>
@@ -230,5 +232,11 @@ static inline void ib_umem_dmabuf_revoke_lock(struct ib_umem_dmabuf *umem_dmabuf
static inline void ib_umem_dmabuf_revoke_unlock(struct ib_umem_dmabuf *umem_dmabuf) {}
static inline void ib_umem_dmabuf_revoke(struct ib_umem_dmabuf *umem_dmabuf) {}
+static inline int ib_umem_check_rereg(struct ib_umem *umem, int flags,
+ int new_access_flags)
+{
+ return -EOPNOTSUPP;
+}
+
#endif /* CONFIG_INFINIBAND_USER_MEM */
#endif /* IB_UMEM_H */
diff --git a/include/rv/da_monitor.h b/include/rv/da_monitor.h
index 39765ff6f098..34b8fba9ecd4 100644
--- a/include/rv/da_monitor.h
+++ b/include/rv/da_monitor.h
@@ -58,6 +58,15 @@ static struct rv_monitor rv_this;
#endif
/*
+ * Hook to allow the implementation of hybrid automata: define it with a
+ * function that waits for the termination of all monitors background
+ * activities (e.g. all timers). This hook can sleep.
+ */
+#ifndef da_monitor_sync_hook
+#define da_monitor_sync_hook()
+#endif
+
+/*
* Type for the target id, default to int but can be overridden.
* A long type can work as hash table key (PER_OBJ) but will be downgraded to
* int in the event tracepoint.
@@ -77,13 +86,22 @@ static void react(enum states curr_state, enum events event)
}
/*
+ * da_monitor_reset_state - reset a monitor and setting it to init state
+ */
+static inline void da_monitor_reset_state(struct da_monitor *da_mon)
+{
+ WRITE_ONCE(da_mon->monitoring, 0);
+ /* Pair with load in __ha_monitor_timer_callback */
+ smp_store_release(&da_mon->curr_state, model_get_initial_state());
+}
+
+/*
* da_monitor_reset - reset a monitor and setting it to init state
*/
static inline void da_monitor_reset(struct da_monitor *da_mon)
{
da_monitor_reset_hook(da_mon);
- da_mon->monitoring = 0;
- da_mon->curr_state = model_get_initial_state();
+ da_monitor_reset_state(da_mon);
}
/*
@@ -95,8 +113,9 @@ static inline void da_monitor_reset(struct da_monitor *da_mon)
static inline void da_monitor_start(struct da_monitor *da_mon)
{
da_mon->curr_state = model_get_initial_state();
- da_mon->monitoring = 1;
da_monitor_init_hook(da_mon);
+ /* Pairs with smp_load_acquire in da_monitoring(). */
+ smp_store_release(&da_mon->monitoring, 1);
}
/*
@@ -104,7 +123,8 @@ static inline void da_monitor_start(struct da_monitor *da_mon)
*/
static inline bool da_monitoring(struct da_monitor *da_mon)
{
- return da_mon->monitoring;
+ /* Pairs with smp_store_release in da_monitor_start(). */
+ return smp_load_acquire(&da_mon->monitoring);
}
/*
@@ -157,11 +177,27 @@ static struct da_monitor *da_get_monitor(void)
}
/*
+ * __da_monitor_reset_all - reset the single monitor
+ */
+static void __da_monitor_reset_all(void (*reset)(struct da_monitor *))
+{
+ reset(da_get_monitor());
+}
+
+/*
* da_monitor_reset_all - reset the single monitor
*/
static void da_monitor_reset_all(void)
{
- da_monitor_reset(da_get_monitor());
+ __da_monitor_reset_all(da_monitor_reset);
+}
+
+/*
+ * da_monitor_reset_state_all - reset the single monitor
+ */
+static inline void da_monitor_reset_state_all(void)
+{
+ __da_monitor_reset_all(da_monitor_reset_state);
}
/*
@@ -169,7 +205,7 @@ static void da_monitor_reset_all(void)
*/
static inline int da_monitor_init(void)
{
- da_monitor_reset_all();
+ da_monitor_reset_state_all();
return 0;
}
@@ -179,8 +215,13 @@ static inline int da_monitor_init(void)
static inline void da_monitor_destroy(void)
{
da_monitor_reset_all();
+ da_monitor_sync_hook();
}
+#ifndef da_implicit_guard
+#define da_implicit_guard()
+#endif
+
#elif RV_MON_TYPE == RV_MON_PER_CPU
/*
* Functions to define, init and get a per-cpu monitor.
@@ -200,25 +241,41 @@ static struct da_monitor *da_get_monitor(void)
}
/*
- * da_monitor_reset_all - reset all CPUs' monitor
+ * __da_monitor_reset_all - reset all CPUs' monitor
*/
-static void da_monitor_reset_all(void)
+static void __da_monitor_reset_all(void (*reset)(struct da_monitor *))
{
struct da_monitor *da_mon;
int cpu;
for_each_cpu(cpu, cpu_online_mask) {
da_mon = per_cpu_ptr(&DA_MON_NAME, cpu);
- da_monitor_reset(da_mon);
+ reset(da_mon);
}
}
/*
+ * da_monitor_reset_all - reset all CPUs' monitor
+ */
+static void da_monitor_reset_all(void)
+{
+ __da_monitor_reset_all(da_monitor_reset);
+}
+
+/*
+ * da_monitor_reset_state_all - reset all CPUs' monitor
+ */
+static inline void da_monitor_reset_state_all(void)
+{
+ __da_monitor_reset_all(da_monitor_reset_state);
+}
+
+/*
* da_monitor_init - initialize all CPUs' monitor
*/
static inline int da_monitor_init(void)
{
- da_monitor_reset_all();
+ da_monitor_reset_state_all();
return 0;
}
@@ -228,8 +285,13 @@ static inline int da_monitor_init(void)
static inline void da_monitor_destroy(void)
{
da_monitor_reset_all();
+ da_monitor_sync_hook();
}
+#ifndef da_implicit_guard
+#define da_implicit_guard() guard(migrate)()
+#endif
+
#elif RV_MON_TYPE == RV_MON_PER_TASK
/*
* Functions to define, init and get a per-task monitor.
@@ -267,19 +329,29 @@ static inline da_id_type da_get_id(struct da_monitor *da_mon)
return da_get_target(da_mon)->pid;
}
-static void da_monitor_reset_all(void)
+static void __da_monitor_reset_all(void (*reset)(struct da_monitor *))
{
struct task_struct *g, *p;
int cpu;
read_lock(&tasklist_lock);
for_each_process_thread(g, p)
- da_monitor_reset(da_get_monitor(p));
+ reset(da_get_monitor(p));
for_each_present_cpu(cpu)
- da_monitor_reset(da_get_monitor(idle_task(cpu)));
+ reset(da_get_monitor(idle_task(cpu)));
read_unlock(&tasklist_lock);
}
+static void da_monitor_reset_all(void)
+{
+ __da_monitor_reset_all(da_monitor_reset);
+}
+
+static inline void da_monitor_reset_state_all(void)
+{
+ __da_monitor_reset_all(da_monitor_reset_state);
+}
+
/*
* da_monitor_init - initialize the per-task monitor
*
@@ -296,12 +368,15 @@ static int da_monitor_init(void)
task_mon_slot = slot;
- da_monitor_reset_all();
+ da_monitor_reset_state_all();
return 0;
}
/*
* da_monitor_destroy - return the allocated slot
+ *
+ * Wait for all in-flight handlers before returning the slot to avoid
+ * out-of-bound accesses.
*/
static inline void da_monitor_destroy(void)
{
@@ -309,10 +384,13 @@ static inline void da_monitor_destroy(void)
WARN_ONCE(1, "Disabling a disabled monitor: " __stringify(MONITOR_NAME));
return;
}
- rv_put_task_monitor_slot(task_mon_slot);
- task_mon_slot = RV_PER_TASK_MONITOR_INIT;
+ tracepoint_synchronize_unregister();
da_monitor_reset_all();
+ da_monitor_sync_hook();
+
+ rv_put_task_monitor_slot(task_mon_slot);
+ task_mon_slot = RV_PER_TASK_MONITOR_INIT;
}
#elif RV_MON_TYPE == RV_MON_PER_OBJ
@@ -483,15 +561,24 @@ static inline void da_destroy_storage(da_id_type id)
kfree_rcu(mon_storage, rcu);
}
-static void da_monitor_reset_all(void)
+static void __da_monitor_reset_all(void (*reset)(struct da_monitor *))
{
struct da_monitor_storage *mon_storage;
int bkt;
- rcu_read_lock();
+ guard(rcu)();
hash_for_each_rcu(da_monitor_ht, bkt, mon_storage, node)
- da_monitor_reset(&mon_storage->rv.da_mon);
- rcu_read_unlock();
+ reset(&mon_storage->rv.da_mon);
+}
+
+static void da_monitor_reset_all(void)
+{
+ __da_monitor_reset_all(da_monitor_reset);
+}
+
+static inline void da_monitor_reset_state_all(void)
+{
+ __da_monitor_reset_all(da_monitor_reset_state);
}
static inline int da_monitor_init(void)
@@ -506,13 +593,14 @@ static inline void da_monitor_destroy(void)
struct hlist_node *tmp;
int bkt;
+ tracepoint_synchronize_unregister();
+ da_monitor_reset_all();
+ da_monitor_sync_hook();
/*
- * This function is called after all probes are disabled, we need only
- * worry about concurrency against old events.
+ * This function is called after all probes are disabled and no longer
+ * pending, we can safely assume no concurrent user.
*/
- synchronize_rcu();
hash_for_each_safe(da_monitor_ht, bkt, tmp, mon_storage, node) {
- da_monitor_reset_hook(&mon_storage->rv.da_mon);
hash_del_rcu(&mon_storage->node);
kfree(mon_storage);
}
@@ -676,6 +764,7 @@ static inline bool __da_handle_start_run_event(struct da_monitor *da_mon,
*/
static inline void da_handle_event(enum events event)
{
+ da_implicit_guard();
__da_handle_event(da_get_monitor(), event, 0);
}
@@ -691,6 +780,7 @@ static inline void da_handle_event(enum events event)
*/
static inline bool da_handle_start_event(enum events event)
{
+ da_implicit_guard();
return __da_handle_start_event(da_get_monitor(), event, 0);
}
@@ -702,6 +792,7 @@ static inline bool da_handle_start_event(enum events event)
*/
static inline bool da_handle_start_run_event(enum events event)
{
+ da_implicit_guard();
return __da_handle_start_run_event(da_get_monitor(), event, 0);
}
diff --git a/include/rv/ha_monitor.h b/include/rv/ha_monitor.h
index d59507e8cb30..28d3c74cabfc 100644
--- a/include/rv/ha_monitor.h
+++ b/include/rv/ha_monitor.h
@@ -28,6 +28,7 @@ static inline void ha_monitor_init_env(struct da_monitor *da_mon);
static inline void ha_monitor_reset_env(struct da_monitor *da_mon);
static inline void ha_setup_timer(struct ha_monitor *ha_mon);
static inline bool ha_cancel_timer(struct ha_monitor *ha_mon);
+static inline void ha_cancel_timer_sync(struct ha_monitor *ha_mon);
static bool ha_monitor_handle_constraint(struct da_monitor *da_mon,
enum states curr_state,
enum events event,
@@ -36,6 +37,27 @@ static bool ha_monitor_handle_constraint(struct da_monitor *da_mon,
#define da_monitor_event_hook ha_monitor_handle_constraint
#define da_monitor_init_hook ha_monitor_init_env
#define da_monitor_reset_hook ha_monitor_reset_env
+#define da_monitor_sync_hook() synchronize_rcu()
+
+#if !defined(HA_SKIP_AUTO_CLEANUP) && RV_MON_TYPE == RV_MON_PER_TASK
+/*
+ * Automatic cleanup handlers for per-task HA monitors, only skip if you know
+ * what you are doing (e.g. you want to implement cleanup manually in another
+ * handler doing more things).
+ */
+static void ha_handle_sched_process_exit(void *data, struct task_struct *p,
+ bool group_dead);
+
+#define ha_monitor_enable_hook() \
+ rv_attach_trace_probe(__stringify(MONITOR_NAME), sched_process_exit, \
+ ha_handle_sched_process_exit)
+#define ha_monitor_disable_hook() \
+ rv_detach_trace_probe(__stringify(MONITOR_NAME), sched_process_exit, \
+ ha_handle_sched_process_exit)
+#else
+#define ha_monitor_enable_hook() ((void)0)
+#define ha_monitor_disable_hook() ((void)0)
+#endif
#include <rv/da_monitor.h>
#include <linux/seq_buf.h>
@@ -115,6 +137,26 @@ static enum hrtimer_restart ha_monitor_timer_callback(struct hrtimer *hrtimer);
#define ha_get_ns() 0
#endif /* HA_CLK_NS */
+static bool ha_mon_destroying;
+
+static int ha_monitor_init(void)
+{
+ int ret;
+
+ WRITE_ONCE(ha_mon_destroying, false);
+ ret = da_monitor_init();
+ if (ret == 0)
+ ha_monitor_enable_hook();
+ return ret;
+}
+
+static void ha_monitor_destroy(void)
+{
+ WRITE_ONCE(ha_mon_destroying, true);
+ ha_monitor_disable_hook();
+ da_monitor_destroy();
+}
+
/* Should be supplied by the monitor */
static u64 ha_get_env(struct ha_monitor *ha_mon, enum envs env, u64 time_ns);
static bool ha_verify_constraint(struct ha_monitor *ha_mon,
@@ -153,12 +195,12 @@ static inline void ha_monitor_init_env(struct da_monitor *da_mon)
* Called from a hook in the DA reset functions, it supplies the da_mon
* corresponding to the current ha_mon.
* Not all hybrid automata require the timer, still clear it for simplicity.
+ * Monitors that never started have their timer uninitialized, do not stop those.
*/
static inline void ha_monitor_reset_env(struct da_monitor *da_mon)
{
struct ha_monitor *ha_mon = to_ha_monitor(da_mon);
- /* Initialisation resets the monitor before initialising the timer */
if (likely(da_monitoring(da_mon)))
ha_cancel_timer(ha_mon);
}
@@ -200,6 +242,20 @@ static inline void ha_trace_error_env(struct ha_monitor *ha_mon,
{
CONCATENATE(trace_error_env_, MONITOR_NAME)(id, curr_state, event, env);
}
+
+#if !defined(HA_SKIP_AUTO_CLEANUP) && RV_MON_TYPE == RV_MON_PER_TASK
+static void ha_handle_sched_process_exit(void *data, struct task_struct *p,
+ bool group_dead)
+{
+ struct da_monitor *da_mon = da_get_monitor(p);
+
+ if (likely(da_monitoring(da_mon))) {
+ da_monitor_reset(da_mon);
+ ha_cancel_timer_sync(to_ha_monitor(da_mon));
+ }
+}
+#endif
+
#endif /* RV_MON_TYPE */
/*
@@ -237,12 +293,30 @@ static bool ha_monitor_handle_constraint(struct da_monitor *da_mon,
return false;
}
+/*
+ * __ha_monitor_timer_callback - generic callback representation
+ *
+ * This callback runs in an RCU read-side critical section to allow the
+ * destruction sequence to easily synchronize_rcu() with all pending timers
+ * after asynchronously disabling them. The ha_mon_destroying check ensures
+ * any callback entering the RCU section after synchronize_rcu() completes
+ * will see the flag and bail out immediately.
+ */
static inline void __ha_monitor_timer_callback(struct ha_monitor *ha_mon)
{
- enum states curr_state = READ_ONCE(ha_mon->da_mon.curr_state);
DECLARE_SEQ_BUF(env_string, ENV_BUFFER_SIZE);
- u64 time_ns = ha_get_ns();
-
+ enum states curr_state;
+ u64 time_ns;
+
+ guard(rcu)();
+ if (unlikely(READ_ONCE(ha_mon_destroying)))
+ return;
+ /* Ensure consistent curr_state if we race with da_monitor_reset */
+ curr_state = smp_load_acquire(&ha_mon->da_mon.curr_state);
+ if (unlikely(!da_monitor_handling_event(&ha_mon->da_mon)))
+ return;
+
+ time_ns = ha_get_ns();
ha_get_env_string(&env_string, ha_mon, time_ns);
ha_react(curr_state, EVENT_NONE, env_string.buffer);
ha_trace_error_env(ha_mon, model_get_state_name(curr_state),
@@ -412,6 +486,10 @@ static inline bool ha_cancel_timer(struct ha_monitor *ha_mon)
{
return timer_delete(&ha_mon->timer);
}
+static inline void ha_cancel_timer_sync(struct ha_monitor *ha_mon)
+{
+ timer_delete_sync(&ha_mon->timer);
+}
#elif HA_TIMER_TYPE == HA_TIMER_HRTIMER
/*
* Helper functions to handle the monitor timer.
@@ -463,6 +541,10 @@ static inline bool ha_cancel_timer(struct ha_monitor *ha_mon)
{
return hrtimer_try_to_cancel(&ha_mon->hrtimer) == 1;
}
+static inline void ha_cancel_timer_sync(struct ha_monitor *ha_mon)
+{
+ hrtimer_cancel(&ha_mon->hrtimer);
+}
#else /* HA_TIMER_NONE */
/*
* Start function is intentionally not defined, monitors using timers must
@@ -473,6 +555,7 @@ static inline bool ha_cancel_timer(struct ha_monitor *ha_mon)
{
return false;
}
+static inline void ha_cancel_timer_sync(struct ha_monitor *ha_mon) { }
#endif
#endif
diff --git a/include/rv/ltl_monitor.h b/include/rv/ltl_monitor.h
index eff60cd61106..38e792401f76 100644
--- a/include/rv/ltl_monitor.h
+++ b/include/rv/ltl_monitor.h
@@ -77,6 +77,7 @@ static void ltl_monitor_destroy(void)
{
rv_detach_trace_probe(name, task_newtask, handle_task_newtask);
+ tracepoint_synchronize_unregister();
rv_put_task_monitor_slot(ltl_monitor_slot);
ltl_monitor_slot = RV_PER_TASK_MONITOR_INIT;
}
diff --git a/include/uapi/linux/tee.h b/include/uapi/linux/tee.h
index cab5cadca8ef..5203977ed35d 100644
--- a/include/uapi/linux/tee.h
+++ b/include/uapi/linux/tee.h
@@ -470,6 +470,7 @@ struct tee_ioctl_object_invoke_arg {
__u32 op;
__u32 ret;
__u32 num_params;
+ __u32 :32;
/* num_params tells the actual number of element in params */
struct tee_ioctl_param params[];
};