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; }
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; }