#ifndef _VMM_ARM64_H_
#define _VMM_ARM64_H_
#include <machine/reg.h>
#include <machine/hypervisor.h>
#include <machine/pcpu.h>
#include "mmu.h"
#include "io/vgic_v3.h"
#include "io/vtimer.h"
struct vgic_v3;
struct vgic_v3_cpu;
#define VNCR_REG(reg) reg = (VNCR_START + VNCR_##reg / 8)
#define REG_VNCR_OFFSET(val) ((val - VNCR_START) * 8)
#define PMEVCNTR_EL0(n) (PMEVCNTR0_EL0 + MIN(n, 30))
#define PMEVTYPER_EL0(n) (PMEVTYPER0_EL0 + MIN(n, 30))
#define DBGBCR_EL1(n) (DBGBCR0_EL1 + MIN(n, 15))
#define DBGBVR_EL1(n) (DBGBVR0_EL1 + MIN(n, 15))
#define DBGWCR_EL1(n) (DBGWCR0_EL1 + MIN(n, 15))
#define DBGWVR_EL1(n) (DBGWVR0_EL1 + MIN(n, 15))
#define HOST_ICH_LR_EL2(n) (HOST_ICH_LR0_EL2 + MIN(n, VGIC_ICH_LR_NUM_MAX-1))
#define HOST_ICH_AP0R_EL2(n) (HOST_ICH_AP0R0_EL2 + MIN(n, VGIC_ICH_APR_NUM_MAX-1))
#define HOST_ICH_AP1R_EL2(n) (HOST_ICH_AP1R0_EL2 + MIN(n, VGIC_ICH_APR_NUM_MAX-1))
#define GPR_X(n) (GPR_X0 + MIN(n, 30))
enum hypctx_sysreg {
HOST_SPSR_EL2,
HOST_ESR_EL2,
CSSELR_EL1,
MDCCINT_EL1,
PAR_EL1,
PMCR_EL0,
PMCCNTR_EL0,
PMCCFILTR_EL0,
PMUSERENR_EL0,
PMSELR_EL0,
PMXEVCNTR_EL0,
PMCNTENSET_EL0,
PMINTENSET_EL1,
PMOVSSET_EL0,
PMEVCNTR0_EL0,
PMEVCNTR30_EL0 = PMEVCNTR0_EL0 + 30,
PMEVTYPER0_EL0,
PMEVTYPER30_EL0 = PMEVTYPER0_EL0 + 30,
DBGCLAIMSET_EL1,
DBGBCR0_EL1,
DBGBCR15_EL1 = DBGBCR0_EL1 + 15,
DBGBVR0_EL1,
DBGBVR15_EL1 = DBGBVR0_EL1 + 15,
DBGWCR0_EL1,
DBGWCR15_EL1 = DBGWCR0_EL1 + 15,
DBGWVR0_EL1,
DBGWVR15_EL1 = DBGWVR0_EL1 + 15,
HOST_CPTR_EL2,
HOST_HCR_EL2,
HOST_HCRX_EL2,
HOST_MDCR_EL2,
HOST_VPIDR_EL2,
HOST_VMPIDR_EL2,
HOST_VNCR_EL2,
HOST_VTTBR_EL2,
HOST_HDFGRTR_EL2,
HOST_HDFGWTR_EL2,
HOST_HFGITR_EL2,
HOST_HFGRTR_EL2,
HOST_HFGWTR_EL2,
HOST_HDFGRTR2_EL2,
HOST_HDFGWTR2_EL2,
HOST_HFGITR2_EL2,
HOST_HFGRTR2_EL2,
HOST_HFGWTR2_EL2,
HOST_FAR_EL2,
HOST_HPFAR_EL2,
HOST_ICH_EISR_EL2,
HOST_ICH_ELRSR_EL2,
HOST_ICH_HCR_EL2,
HOST_ICH_MISR_EL2,
HOST_ICH_VMCR_EL2,
HOST_ICH_LR0_EL2,
HOST_ICH_LR_MAX_EL2 = HOST_ICH_LR0_EL2 + (VGIC_ICH_LR_NUM_MAX - 1),
HOST_ICH_AP0R0_EL2,
HOST_ICH_AP0R_MAX_EL2 = HOST_ICH_AP0R0_EL2 + (VGIC_ICH_APR_NUM_MAX - 1),
HOST_ICH_AP1R0_EL2,
HOST_ICH_AP1R_MAX_EL2 = HOST_ICH_AP1R0_EL2 + (VGIC_ICH_APR_NUM_MAX - 1),
HOST_CNTHCTL_EL2,
HOST_CNTVOFF_EL2,
NR_NON_VNCR_REGS,
VNCR_START,
VNCR_REG(VTTBR_EL2),
VNCR_REG(VSTTBR_EL2),
VNCR_REG(VTCR_EL2),
VNCR_REG(VSTCR_EL2),
VNCR_REG(VMPIDR_EL2),
VNCR_REG(CNTVOFF_EL2),
VNCR_REG(HCR_EL2),
VNCR_REG(HSTR_EL2),
VNCR_REG(VPIDR_EL2),
VNCR_REG(TPIDR_EL2),
VNCR_REG(HCRX_EL2),
VNCR_REG(VNCR_EL2),
VNCR_REG(CPACR_EL1),
VNCR_REG(CONTEXTIDR_EL1),
VNCR_REG(SCTLR_EL1),
VNCR_REG(ACTLR_EL1),
VNCR_REG(TCR_EL1),
VNCR_REG(AFSR0_EL1),
VNCR_REG(AFSR1_EL1),
VNCR_REG(ESR_EL1),
VNCR_REG(MAIR_EL1),
VNCR_REG(AMAIR_EL1),
VNCR_REG(MDSCR_EL1),
VNCR_REG(SPSR_EL1),
VNCR_REG(CNTV_CVAL_EL0),
VNCR_REG(CNTV_CTL_EL0),
VNCR_REG(CNTP_CVAL_EL0),
VNCR_REG(CNTP_CTL_EL0),
VNCR_REG(SCXTNUM_EL1),
VNCR_REG(TFSR_EL1),
VNCR_REG(HDFGRTR2_EL2),
VNCR_REG(CNTPOFF_EL2),
VNCR_REG(HDFGWTR2_EL2),
VNCR_REG(HFGRTR_EL2),
VNCR_REG(HFGWTR_EL2),
VNCR_REG(HFGITR_EL2),
VNCR_REG(HDFGRTR_EL2),
VNCR_REG(HDFGWTR_EL2),
VNCR_REG(ZCR_EL1),
VNCR_REG(HAFGRTR_EL2),
VNCR_REG(SMCR_EL1),
VNCR_REG(SMPRIMAP_EL2),
VNCR_REG(TTBR0_EL1),
VNCR_REG(TTBR1_EL1),
VNCR_REG(FAR_EL1),
VNCR_REG(ELR_EL1),
VNCR_REG(SP_EL1),
VNCR_REG(VBAR_EL1),
VNCR_REG(TCR2_EL1),
VNCR_REG(SCTLR2_EL1),
VNCR_REG(MAIR2_EL1),
VNCR_REG(AMAIR2_EL1),
VNCR_REG(PIRE0_EL1),
VNCR_REG(PIRE0_EL2),
VNCR_REG(PIR_EL1),
VNCR_REG(POR_EL1),
VNCR_REG(S2PIR_EL2),
VNCR_REG(S2POR_EL1),
VNCR_REG(HFGRTR2_EL2),
VNCR_REG(HFGWTR2_EL2),
VNCR_REG(PFAR_EL1),
VNCR_REG(HFGITR2_EL2),
VNCR_REG(SCTLRMASK_EL1),
VNCR_REG(CPACRMASK_EL1),
VNCR_REG(SCTLR2MASK_EL1),
VNCR_REG(TCRMASK_EL1),
VNCR_REG(TCR2MASK_EL1),
VNCR_REG(ACTLRMASK_EL1),
VNCR_REG(ICH_HCR_EL2),
VNCR_REG(ICH_VMCR_EL2),
VNCR_REG(VDISR_EL2),
VNCR_REG(VSESR_EL2),
VNCR_REG(PMBLIMITR_EL1),
VNCR_REG(PMBPTR_EL1),
VNCR_REG(PMBSR_EL1),
VNCR_REG(PMSCR_EL1),
VNCR_REG(PMSEVFR_EL1),
VNCR_REG(PMSICR_EL1),
VNCR_REG(PMSIRR_EL1),
VNCR_REG(PMSLATFR_EL1),
VNCR_REG(PMSNEVFR_EL1),
VNCR_REG(PMSDSFR_EL1),
VNCR_REG(TRFCR_EL1),
VNCR_REG(TRCITECR_EL1),
VNCR_REG(GCSPR_EL1),
VNCR_REG(GCSCR_EL1),
VNCR_REG(BRBCR_EL1),
VNCR_REG(SPMACCESSR_EL1),
VA_REGS_START,
GPR_LR,
GPR_X0,
GPR_X30 = GPR_X0 + 30,
SP_EL0,
TPIDR_EL0,
TPIDRRO_EL0,
TPIDR_EL1,
HOST_SP_EL1,
HOST_ELR_EL2,
VA_REGS_END,
};
struct hypctx {
uint64_t va_regs[VA_REGS_END - VA_REGS_START - 1];
uint64_t sys_regs[NR_NON_VNCR_REGS];
struct hyp *hyp;
struct vcpu *vcpu;
struct vtimer_cpu vtimer_cpu;
uint64_t setcaps;
uint64_t debug_spsr;
uint64_t debug_mdscr;
struct {
uint16_t ich_lr_num;
uint16_t ich_apr_num;
} vgic_v3;
struct vgic_v3_cpu *vgic_cpu;
bool has_exception;
bool dbg_oslock;
void *vncr_regs;
void *host_vncr_regs;
uint64_t el2_addr;
uint64_t el2_vncr_addr;
uint64_t el2_host_vncr_addr;
};
#ifndef __hypctx_vncr_sysreg
#define __hypctx_vncr_sysreg(hypctx, reg) \
((uint64_t *)((char *)hypctx->vncr_regs + REG_VNCR_OFFSET(reg)))
#endif
#ifndef __hypctx_va_sysreg
#define __hypctx_va_sysreg(hypctx, reg) \
(&hypctx->va_regs[reg - VA_REGS_START - 1])
#endif
static inline uint64_t *
hypctx_sys_reg(struct hypctx *hypctx, int reg )
{
if (reg > VA_REGS_START)
return (__hypctx_va_sysreg(hypctx, reg));
if (reg > VNCR_START)
return (__hypctx_vncr_sysreg(hypctx, reg));
return (&hypctx->sys_regs[reg]);
}
static inline void
hypctx_write_sys_reg(struct hypctx *hypctx, enum hypctx_sysreg reg,
uint64_t val)
{
*hypctx_sys_reg(hypctx, reg) = val;
}
static inline uint64_t
hypctx_read_sys_reg(struct hypctx *hypctx, enum hypctx_sysreg reg)
{
return (*hypctx_sys_reg(hypctx, reg));
}
struct hyp {
struct vm *vm;
uint64_t vmid_generation;
uint64_t cntvoff_el2;
uint64_t el2_addr;
uint64_t feats;
#define HYP_FEAT_HCX (0x1ul << 0)
#define HYP_FEAT_ECV_POFF (0x1ul << 1)
#define HYP_FEAT_FGT (0x1ul << 2)
#define HYP_FEAT_FGT2 (0x1ul << 3)
bool vgic_attached;
struct vgic_v3 *vgic;
struct hypctx *ctx[];
};
uint64_t vmm_call_hyp(uint64_t, ...);
#if 0
#define eprintf(fmt, ...) printf("%s:%d " fmt, __func__, __LINE__, ##__VA_ARGS__)
#else
#define eprintf(fmt, ...) do {} while(0)
#endif
struct hypctx *arm64_get_active_vcpu(void);
void raise_data_insn_abort(struct hypctx *, uint64_t, bool, int);
#endif