void arch_vcpu_switch(struct vmm_vcpu *tvcpu, struct vmm_vcpu *vcpu, arch_regs_t *regs) { if (tvcpu) { memcpy(riscv_regs(tvcpu), regs, sizeof(*regs)); } memcpy(regs, riscv_regs(vcpu), sizeof(*regs)); }
int arch_vcpu_init(struct vmm_vcpu *vcpu) { virtual_addr_t sp_exec; /* First time allocate exception stack */ if (!vcpu->reset_count) { sp_exec = vmm_pagepool_alloc(VMM_PAGEPOOL_NORMAL, VMM_SIZE_TO_PAGE(CONFIG_IRQ_STACK_SIZE)); if (!sp_exec) { return VMM_ENOMEM; } sp_exec += CONFIG_IRQ_STACK_SIZE; } else { sp_exec = riscv_regs(vcpu)->sp_exec; } /* For both Orphan & Normal VCPUs */ memset(riscv_regs(vcpu), 0, sizeof(arch_regs_t)); riscv_regs(vcpu)->sepc = vcpu->start_pc; riscv_regs(vcpu)->sstatus = SR_SPP|SR_SPIE; /* TODO: */ riscv_regs(vcpu)->sp = vcpu->stack_va + (vcpu->stack_sz - ARCH_CACHE_LINE_SIZE); riscv_regs(vcpu)->sp = riscv_regs(vcpu)->sp & ~0x7; riscv_regs(vcpu)->sp_exec = sp_exec; /* TODO: For Normal VCPUs */ return VMM_OK; }
void arch_vcpu_regs_dump(struct vmm_chardev *cdev, struct vmm_vcpu *vcpu) { cpu_vcpu_dump_general_regs(cdev, riscv_regs(vcpu)); if (vcpu->is_normal) { cpu_vcpu_dump_private_regs(cdev, riscv_priv(vcpu)); } }
int arch_vcpu_deinit(struct vmm_vcpu *vcpu) { virtual_addr_t sp_exec = riscv_regs(vcpu)->sp_exec - CONFIG_IRQ_STACK_SIZE; /* TODO: For Normal VCPUs */ /* For both Orphan & Normal VCPUs */ /* Free-up excepiton stack */ vmm_pagepool_free(VMM_PAGEPOOL_NORMAL, sp_exec, VMM_SIZE_TO_PAGE(CONFIG_IRQ_STACK_SIZE)); /* Clear arch registers */ memset(riscv_regs(vcpu), 0, sizeof(arch_regs_t)); return VMM_OK; }
void arch_vcpu_switch(struct vmm_vcpu *tvcpu, struct vmm_vcpu *vcpu, arch_regs_t *regs) { struct riscv_priv *priv; if (tvcpu) { memcpy(riscv_regs(tvcpu), regs, sizeof(*regs)); if (tvcpu->is_normal) { priv = riscv_priv(tvcpu); priv->hideleg = csr_read(CSR_HIDELEG); priv->hedeleg = csr_read(CSR_HEDELEG); priv->bsstatus = csr_read(CSR_BSSTATUS); priv->bsie = csr_read(CSR_BSIE); priv->bstvec = csr_read(CSR_BSTVEC); priv->bsscratch = csr_read(CSR_BSSCRATCH); priv->bsepc = csr_read(CSR_BSEPC); priv->bscause = csr_read(CSR_BSCAUSE); priv->bstval = csr_read(CSR_BSTVAL); priv->bsip = csr_read(CSR_BSIP); priv->bsatp = csr_read(CSR_BSATP); } } memcpy(regs, riscv_regs(vcpu), sizeof(*regs)); if (vcpu->is_normal) { priv = riscv_priv(vcpu); csr_write(CSR_HIDELEG, priv->hideleg); csr_write(CSR_HEDELEG, priv->hedeleg); csr_write(CSR_BSSTATUS, priv->bsstatus); csr_write(CSR_BSIE, priv->bsie); csr_write(CSR_BSTVEC, priv->bstvec); csr_write(CSR_BSSCRATCH, priv->bsscratch); csr_write(CSR_BSEPC, priv->bsepc); csr_write(CSR_BSCAUSE, priv->bscause); csr_write(CSR_BSTVAL, priv->bstval); csr_write(CSR_BSIP, priv->bsip); csr_write(CSR_BSATP, priv->bsatp); cpu_mmu_stage2_change_pgtbl(vcpu->guest->id, riscv_guest_priv(vcpu->guest)->pgtbl); } }
int arch_vcpu_init(struct vmm_vcpu *vcpu) { int rc = VMM_OK; const char *attr; virtual_addr_t sp_exec; /* First time allocate exception stack */ if (!vcpu->reset_count) { sp_exec = vmm_pagepool_alloc(VMM_PAGEPOOL_NORMAL, VMM_SIZE_TO_PAGE(CONFIG_IRQ_STACK_SIZE)); if (!sp_exec) { return VMM_ENOMEM; } sp_exec += CONFIG_IRQ_STACK_SIZE; } else { sp_exec = riscv_regs(vcpu)->sp_exec; } /* For both Orphan & Normal VCPUs */ memset(riscv_regs(vcpu), 0, sizeof(arch_regs_t)); riscv_regs(vcpu)->sepc = vcpu->start_pc; riscv_regs(vcpu)->sstatus = SSTATUS_SPP | SSTATUS_SPIE; /* TODO: */ riscv_regs(vcpu)->sp = vcpu->stack_va + (vcpu->stack_sz - ARCH_CACHE_LINE_SIZE); riscv_regs(vcpu)->sp = riscv_regs(vcpu)->sp & ~0x7; riscv_regs(vcpu)->sp_exec = sp_exec; riscv_regs(vcpu)->hstatus = 0; /* For Orphan VCPUs we are done */ if (!vcpu->is_normal) { return VMM_OK; } /* Following initialization for normal VCPUs only */ rc = vmm_devtree_read_string(vcpu->node, VMM_DEVTREE_COMPATIBLE_ATTR_NAME, &attr); if (rc) { goto done; } #if __riscv_xlen == 64 if (strcmp(attr, "riscv64,generic") != 0) { #elif __riscv_xlen == 32 if (strcmp(attr, "riscv32,generic") != 0) { #else #error "Unexpected __riscv_xlen" #endif rc = VMM_EINVALID; goto done; } /* Update HSTATUS */ riscv_regs(vcpu)->hstatus |= HSTATUS_SP2V; riscv_regs(vcpu)->hstatus |= HSTATUS_SP2P; riscv_regs(vcpu)->hstatus |= HSTATUS_SPV; /* First time initialization of private context */ if (!vcpu->reset_count) { /* Alloc private context */ vcpu->arch_priv = vmm_zalloc(sizeof(struct riscv_priv)); if (!vcpu->arch_priv) { rc = VMM_ENOMEM; goto done; } } /* Update BS<xyz> */ riscv_priv(vcpu)->bsstatus = 0; /* TODO: ??? */ riscv_priv(vcpu)->bsie = 0; riscv_priv(vcpu)->bstvec = 0; riscv_priv(vcpu)->bsscratch = 0; riscv_priv(vcpu)->bsepc = 0; riscv_priv(vcpu)->bscause = 0; riscv_priv(vcpu)->bstval = 0; riscv_priv(vcpu)->bsip = 0; riscv_priv(vcpu)->bsatp = 0; /* Update HIDELEG */ riscv_priv(vcpu)->hideleg = 0; riscv_priv(vcpu)->hideleg |= SIP_SSIP; riscv_priv(vcpu)->hideleg |= SIP_STIP; riscv_priv(vcpu)->hideleg |= SIP_SEIP; /* Update HEDELEG */ riscv_priv(vcpu)->hedeleg = 0; riscv_priv(vcpu)->hedeleg |= (1U << CAUSE_MISALIGNED_FETCH); riscv_priv(vcpu)->hedeleg |= (1U << CAUSE_BREAKPOINT); riscv_priv(vcpu)->hedeleg |= (1U << CAUSE_USER_ECALL); riscv_priv(vcpu)->hedeleg |= (1U << CAUSE_FETCH_PAGE_FAULT); riscv_priv(vcpu)->hedeleg |= (1U << CAUSE_LOAD_PAGE_FAULT); riscv_priv(vcpu)->hedeleg |= (1U << CAUSE_STORE_PAGE_FAULT); done: return rc; } int arch_vcpu_deinit(struct vmm_vcpu *vcpu) { virtual_addr_t sp_exec = riscv_regs(vcpu)->sp_exec - CONFIG_IRQ_STACK_SIZE; /* For both Orphan & Normal VCPUs */ /* Free-up excepiton stack */ vmm_pagepool_free(VMM_PAGEPOOL_NORMAL, sp_exec, VMM_SIZE_TO_PAGE(CONFIG_IRQ_STACK_SIZE)); /* Clear arch registers */ memset(riscv_regs(vcpu), 0, sizeof(arch_regs_t)); /* For Orphan VCPUs do nothing else */ if (!vcpu->is_normal) { return VMM_OK; } /* Free private context */ vmm_free(vcpu->arch_priv); vcpu->arch_priv = NULL; return VMM_OK; }