If using paging you may need to invalidate the TLB entry which contains execute permission for the page.
On x86 if using segments, after changing segment attributes you need to reload the segment selectors.
The execution pipeline may need to be flushed, using a serialising instruction.
When modifying code in place that may be being executed by another thread on another core at the same time, some modifications may trigger CPU errata.
On particular CPUs there may be other kinds of caches or state invalidation required, but hopefully the OS provides a "flush I-cache" function that covers all of them.