예제 #1
0
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));
}
예제 #2
0
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;
}
예제 #3
0
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));
	}
}
예제 #4
0
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;
}
예제 #5
0
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);
	}
}
예제 #6
0
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;
}