#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: patch.c,v 1.8 2023/11/21 22:19:12 thorpej Exp $");
#include "opt_multiprocessor.h"
#include <sys/types.h>
#include <sys/systm.h>
#include <sys/lwp.h>
#include <machine/cpu.h>
#include <machine/alpha.h>
#include <machine/intr.h>
#include <machine/alpha_instruction.h>
void _membar_producer(void);
void _membar_producer_end(void);
void _membar_producer_mp(void);
void _membar_producer_mp_end(void);
void _membar_sync(void);
void _membar_sync_end(void);
void _membar_sync_mp(void);
void _membar_sync_mp_end(void);
extern char alpha_copystr_bwx[], alpha_copystr_bwx_end[];
extern char alpha_copystr[], alpha_copystr_end[];
#if defined(MULTIPROCESSOR)
extern uint32_t *lock_stub_patch_table[];
static void
patch_lock_stubs(void)
{
alpha_instruction insn = {
.mem_format = {
.opcode = op_special,
.displacement = op_mb,
},
};
int i, s;
s = splhigh();
for (i = 0; lock_stub_patch_table[i] != NULL; i++) {
*lock_stub_patch_table[i] = insn.bits;
}
alpha_pal_imb();
splx(s);
}
#endif
static void
patchfunc(void *from_s, void *from_e, void *to_s, void *to_e)
{
int s;
s = splhigh();
if ((uintptr_t)from_e - (uintptr_t)from_s !=
(uintptr_t)to_e - (uintptr_t)to_s)
panic("patchfunc: sizes do not match (from=%p)", from_s);
memcpy(to_s, from_s, (uintptr_t)to_e - (uintptr_t)to_s);
alpha_pal_imb();
splx(s);
}
void
alpha_patch(bool is_mp)
{
if (cpu_amask & ALPHA_AMASK_BWX) {
patchfunc(alpha_copystr_bwx, alpha_copystr_bwx_end,
alpha_copystr, alpha_copystr_end);
}
#if defined(MULTIPROCESSOR)
if (is_mp) {
KASSERT(curcpu()->ci_flags & CPUF_PRIMARY);
KASSERT((cpus_running & ~(1UL << cpu_number())) == 0);
patch_lock_stubs();
patchfunc(_membar_producer_mp, _membar_producer_mp_end,
_membar_producer, _membar_producer_end);
patchfunc(_membar_sync_mp, _membar_sync_mp_end,
_membar_sync, _membar_sync_end);
}
#else
KASSERT(is_mp == false);
#endif
}