Re: [PATCH v3 0/6] Static calls
From: H. Peter Anvin
Date: Mon Jan 14 2019 - 17:55:39 EST
I think this sequence ought to work (keep in mind we are already under a
mutex, so the global data is safe even if we are preempted):
set up page table entries
invlpg
set up bp patching global data
cpu = get_cpu()
bp_old_value = atomic_read(bp_write_addr)
do {
atomic_write(&bp_poke_state, 1)
atomic_write(bp_write_addr, 0xcc)
mask <- online_cpu_mask - self
send IPIs
wait for mask = 0
} while (cmpxchg(&bp_poke_state, 1, 2) != 1);
patch sites, remove breakpoints after patching each one
atomic_write(&bp_poke_state, 3);
mask <- online_cpu_mask - self
send IPIs
wait for mask = 0
atomic_write(&bp_poke_state, 0);
tear down patching global data
tear down page table entries
The #BP handler would then look like:
state = cmpxchg(&bp_poke_state, 1, 4);
switch (state) {
case 1:
case 4:
invlpg
cmpxchg(bp_write_addr, 0xcc, bp_old_value)
break;
case 2:
invlpg
complete patch sequence
remove breakpoint
break;
case 3:
/* If we are here, the #BP will go away on its own */
break;
case 0:
/* No patching in progress!!! */
return 0;
}
clear bit in mask
return 1;
The IPI handler:
clear bit in mask
sync_core /* Needed if multiple IPI events are chained */