#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: vm_machdep.c,v 1.119 2025/02/28 20:11:21 hans Exp $");
#include "opt_execfmt.h"
#include "opt_compat_ultrix.h"
#include "opt_multiprocessor.h"
#include "opt_cputype.h"
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/buf.h>
#include <sys/core.h>
#include <sys/cpu.h>
#include <sys/exec.h>
#include <sys/exec_aout.h>
#include <sys/proc.h>
#include <sys/syscallargs.h>
#include <uvm/uvm_extern.h>
#include <machine/vmparam.h>
#include <machine/macros.h>
#include <machine/frame.h>
#include <machine/sid.h>
void cpu_lwp_bootstrap(void);
void
cpu_lwp_fork(struct lwp *l1, struct lwp *l2, void *stack, size_t stacksize,
void (*func)(void *), void *arg)
{
struct callsframe *cf;
extern int sret;
struct pcb * const pcb2 = lwp_getpcb(l2);
#ifdef DIAGNOSTIC
if (l1 != curlwp && l1 != &lwp0)
panic("cpu_lwp_fork: curlwp");
#endif
memset(pcb2, 0, sizeof(*pcb2));
const vaddr_t uv = uvm_lwp_getuarea(l2);
struct trapframe * const tf = (struct trapframe *)(uv + USPACE) - 1;
l2->l_md.md_utf = tf;
*tf = *l1->l_md.md_utf;
pcb2->pcb_pm = NULL;
pmap_activate(l2);
kvtopte((uintptr_t)uv + REDZONEADDR)->pg_v = 0;
cf = (struct callsframe *)tf - 1;
cf->ca_cond = 0;
cf->ca_maskpsw = 0x20000000;
cf->ca_ap = 0;
cf->ca_fp = 0;
cf->ca_pc = (uintptr_t)&sret;
cf->ca_argno = 1;
cf->ca_arg1 = 0;
pcb2->pcb_onfault = NULL;
pcb2->AP = (uintptr_t)&cf->ca_argno;
pcb2->KSP = (uintptr_t)cf;
pcb2->FP = (uintptr_t)cf;
pcb2->PC = (uintptr_t)cpu_lwp_bootstrap + 2;
pcb2->PSL = PSL_HIGHIPL;
pcb2->ESP = (uintptr_t)&pcb2->pcb_onfault;
pcb2->SSP = (uintptr_t)l2;
pcb2->R[1] = (uintptr_t)l2;
pcb2->R[2] = (uintptr_t)func;
pcb2->R[3] = (uintptr_t)arg;
pcb2->pcb_paddr = kvtophys(pcb2);
if (stack != NULL)
tf->tf_sp = (uintptr_t)stack + stacksize;
tf->tf_r0 = l1->l_proc->p_pid;
tf->tf_r1 = 1;
tf->tf_psl = PSL_U|PSL_PREVU;
}
vaddr_t
cpu_lwp_pc(struct lwp *l)
{
return l->l_md.md_utf->tf_pc;
}
void
cpu_lwp_free(struct lwp *l, int proc)
{
(void)l;
(void)proc;
}
void
cpu_lwp_free2(struct lwp *l)
{
(void)l;
}
#ifdef EXEC_AOUT
int
cpu_exec_aout_makecmds(struct lwp *l, struct exec_package *epp)
{
return ENOEXEC;
}
#endif
int
sys_sysarch(struct lwp *l, const struct sys_sysarch_args *uap, register_t *retval)
{
return (ENOSYS);
}
void
ioaccess(vaddr_t vaddr, paddr_t paddr, size_t npgs)
{
uint32_t *pte = (uint32_t *)kvtopte(vaddr);
int i;
for (i = 0; i < npgs; i++)
pte[i] = PG_V | PG_KW | (PG_PFNUM(paddr) + i);
}
void
iounaccess(vaddr_t vaddr, size_t npgs)
{
uint32_t *pte = (uint32_t *)kvtopte(vaddr);
int i;
for (i = 0; i < npgs; i++)
pte[i] = 0;
mtpr(0, PR_TBIA);
}
int
vmapbuf(struct buf *bp, vsize_t len)
{
#if VAX46 || VAX48 || VAX49 || VAX53 || VAXANY
vaddr_t faddr, taddr, off;
paddr_t pa;
struct proc *p;
if (vax_boardtype != VAX_BTYP_46
&& vax_boardtype != VAX_BTYP_48
&& vax_boardtype != VAX_BTYP_49
&& vax_boardtype != VAX_BTYP_53)
return 0;
if ((bp->b_flags & B_PHYS) == 0)
panic("vmapbuf");
p = bp->b_proc;
bp->b_saveaddr = bp->b_data;
faddr = trunc_page((vaddr_t)bp->b_saveaddr);
off = (vaddr_t)bp->b_data - faddr;
len = round_page(off + len);
taddr = uvm_km_alloc(phys_map, len, 0, UVM_KMF_VAONLY | UVM_KMF_WAITVA);
bp->b_data = (void *)(taddr + off);
len = atop(len);
while (len--) {
if (pmap_extract(vm_map_pmap(&p->p_vmspace->vm_map), faddr,
&pa) == false)
panic("vmapbuf: null page frame");
pmap_enter(vm_map_pmap(phys_map), taddr, trunc_page(pa),
VM_PROT_READ|VM_PROT_WRITE, PMAP_WIRED);
faddr += PAGE_SIZE;
taddr += PAGE_SIZE;
}
pmap_update(vm_map_pmap(phys_map));
#endif
return 0;
}
void
vunmapbuf(struct buf *bp, vsize_t len)
{
#if VAX46 || VAX48 || VAX49 || VAX53 || VAXANY
vaddr_t addr, off;
if (vax_boardtype != VAX_BTYP_46
&& vax_boardtype != VAX_BTYP_48
&& vax_boardtype != VAX_BTYP_49
&& vax_boardtype != VAX_BTYP_53)
return;
if ((bp->b_flags & B_PHYS) == 0)
panic("vunmapbuf");
addr = trunc_page((vaddr_t)bp->b_data);
off = (vaddr_t)bp->b_data - addr;
len = round_page(off + len);
pmap_remove(vm_map_pmap(phys_map), addr, addr + len);
pmap_update(vm_map_pmap(phys_map));
uvm_km_free(phys_map, addr, len, UVM_KMF_VAONLY);
bp->b_data = bp->b_saveaddr;
bp->b_saveaddr = NULL;
#endif
}