#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: efi_machdep.c,v 1.4 2023/07/10 07:00:12 rin Exp $");
#include <sys/param.h>
#include <uvm/uvm_extern.h>
#include <arm/efirt.h>
#include <arm/vfpreg.h>
#include <arm/arm/efi_runtime.h>
#include <arm/arm32/machdep.h>
static struct {
struct faultbuf aert_faultbuf;
uint32_t aert_tpidrprw;
uint32_t aert_fpexc;
} arm_efirt_state;
int
arm_efirt_md_enter(void)
{
kpreempt_disable();
struct lwp * const l = curlwp;
arm_efirt_state.aert_tpidrprw = armreg_tpidrprw_read();
arm_efirt_state.aert_fpexc = armreg_fpexc_read();
armreg_fpexc_write(arm_efirt_state.aert_fpexc & ~VFP_FPEXC_EN);
isb();
int err = cpu_set_onfault(&arm_efirt_state.aert_faultbuf);
if (err)
return err;
if ((l->l_flag & LW_SYSTEM) == 0) {
pmap_deactivate(l);
}
pmap_activate_efirt();
return 0;
}
void
arm_efirt_md_exit(void)
{
struct lwp * const l = curlwp;
pmap_deactivate_efirt();
if ((l->l_flag & LW_SYSTEM) == 0) {
pmap_activate(l);
}
armreg_tpidrprw_write(arm_efirt_state.aert_tpidrprw);
armreg_fpexc_write(arm_efirt_state.aert_fpexc);
isb();
cpu_unset_onfault();
kpreempt_enable();
}
void
cpu_efirt_map_range(vaddr_t va, paddr_t pa, size_t sz,
enum cpu_efirt_mem_type type)
{
int flags = 0;
int prot = 0;
switch (type) {
case ARM_EFIRT_MEM_CODE:
prot = VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE;
flags = prot;
break;
case ARM_EFIRT_MEM_DATA:
prot = VM_PROT_READ | VM_PROT_WRITE;
flags = prot;
break;
case ARM_EFIRT_MEM_MMIO:
prot = VM_PROT_READ | VM_PROT_WRITE;
flags = prot | PMAP_DEV;
break;
default:
panic("%s: unsupported type %d", __func__, type);
}
if (va >= VM_MAXUSER_ADDRESS || va >= VM_MAXUSER_ADDRESS - sz) {
printf("Incorrect EFI mapping range %" PRIxVADDR
"- %" PRIxVADDR "\n", va, va + sz);
}
while (sz != 0) {
pmap_enter(pmap_efirt(), va, pa, prot, flags | PMAP_WIRED);
va += PAGE_SIZE;
pa += PAGE_SIZE;
sz -= PAGE_SIZE;
}
pmap_update(pmap_efirt());
}