@@ -36,13 +36,14 @@
* caller in schedule_work.
*/
static DEFINE_SPINLOCK(payload_lock);
-static LIST_HEAD(payload_list);
-
/*
- * Patches which have been applied. Need RCU in case we crash (and then
- * traps code would iterate via applied_list) when adding entries on the list.
+ * Need RCU in case we crash (and then traps code would iterate via
+ * payload_list) when adding entries on the list.
*/
-static DEFINE_RCU_READ_LOCK(rcu_applied_lock);
+static DEFINE_RCU_READ_LOCK(rcu_payload_lock);
+static LIST_HEAD(payload_list);
+
+/* Patches which have been applied. Only modified from stop machine context. */
static LIST_HEAD(applied_list);
static unsigned int payload_cnt;
@@ -111,12 +112,8 @@ bool is_patch(const void *ptr)
const struct payload *data;
bool r = false;
- /*
- * Only RCU locking since this list is only ever changed during apply
- * or revert context. And in case it dies there we need an safe list.
- */
- rcu_read_lock(&rcu_applied_lock);
- list_for_each_entry_rcu ( data, &applied_list, applied_list )
+ rcu_read_lock(&rcu_payload_lock);
+ list_for_each_entry_rcu ( data, &payload_list, list )
{
if ( (ptr >= data->rw_addr &&
ptr < (data->rw_addr + data->rw_size)) ||
@@ -130,7 +127,7 @@ bool is_patch(const void *ptr)
}
}
- rcu_read_unlock(&rcu_applied_lock);
+ rcu_read_unlock(&rcu_payload_lock);
return r;
}
@@ -166,12 +163,8 @@ static const char *cf_check livepatch_symbols_lookup(
const void *va = (const void *)addr;
const char *n = NULL;
- /*
- * Only RCU locking since this list is only ever changed during apply
- * or revert context. And in case it dies there we need an safe list.
- */
- rcu_read_lock(&rcu_applied_lock);
- list_for_each_entry_rcu ( data, &applied_list, applied_list )
+ rcu_read_lock(&rcu_payload_lock);
+ list_for_each_entry_rcu ( data, &payload_list, list )
{
if ( va < data->text_addr ||
va >= (data->text_addr + data->text_size) )
@@ -200,7 +193,7 @@ static const char *cf_check livepatch_symbols_lookup(
n = data->symtab[best].name;
break;
}
- rcu_read_unlock(&rcu_applied_lock);
+ rcu_read_unlock(&rcu_payload_lock);
return n;
}
@@ -1072,7 +1065,8 @@ static void free_payload(struct payload *data)
{
ASSERT(spin_is_locked(&payload_lock));
unregister_virtual_region(&data->region);
- list_del(&data->list);
+ list_del_rcu(&data->list);
+ rcu_barrier();
payload_cnt--;
payload_version++;
free_payload_data(data);
@@ -1172,7 +1166,7 @@ static int livepatch_upload(struct xen_sysctl_livepatch_upload *upload)
INIT_LIST_HEAD(&data->applied_list);
register_virtual_region(&data->region);
- list_add_tail(&data->list, &payload_list);
+ list_add_tail_rcu(&data->list, &payload_list);
payload_cnt++;
payload_version++;
}
@@ -1383,11 +1377,7 @@ static int apply_payload(struct payload *data)
static inline void apply_payload_tail(struct payload *data)
{
- /*
- * We need RCU variant (which has barriers) in case we crash here.
- * The applied_list is iterated by the trap code.
- */
- list_add_tail_rcu(&data->applied_list, &applied_list);
+ list_add_tail(&data->applied_list, &applied_list);
data->state = LIVEPATCH_STATE_APPLIED;
}
@@ -1427,12 +1417,7 @@ static int revert_payload(struct payload *data)
static inline void revert_payload_tail(struct payload *data)
{
-
- /*
- * We need RCU variant (which has barriers) in case we crash here.
- * The applied_list is iterated by the trap code.
- */
- list_del_rcu(&data->applied_list);
+ list_del(&data->applied_list);
data->reverted = true;
data->state = LIVEPATCH_STATE_CHECKED;