arch/riscv/kvm/vcpu_sbi_replace.c

Source file repositories/reference/linux-study-clean/arch/riscv/kvm/vcpu_sbi_replace.c

File Facts

System
Linux kernel
Corpus path
arch/riscv/kvm/vcpu_sbi_replace.c
Extension
.c
Size
5076 bytes
Lines
188
Domain
Architecture Layer
Bucket
arch/riscv
Inferred role
Architecture Layer: implementation source
Status
source implementation candidate

Why This File Exists

CPU and platform-specific kernel glue: boot entry, traps, syscall entry, interrupts, page tables, context switch, and low-level barriers.

Dependency Surface

Detected Declarations

Annotated Snippet

if (hbase != -1UL) {
			if (tmp->vcpu_id < hbase)
				continue;
			hart_bit = tmp->vcpu_id - hbase;
			if (hart_bit >= __riscv_xlen)
				goto done;
			if (!(hmask & (1UL << hart_bit)))
				continue;
		}
		ret = kvm_riscv_vcpu_set_interrupt(tmp, IRQ_VS_SOFT);
		if (ret < 0)
			break;
		sentmask |= 1UL << hart_bit;
		kvm_riscv_vcpu_pmu_incr_fw(tmp, SBI_PMU_FW_IPI_RCVD);
	}

done:
	if (hbase != -1UL && (hmask ^ sentmask))
		retdata->err_val = SBI_ERR_INVALID_PARAM;

	return ret;
}

const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_ipi = {
	.extid_start = SBI_EXT_IPI,
	.extid_end = SBI_EXT_IPI,
	.handler = kvm_sbi_ext_ipi_handler,
};

static int kvm_sbi_ext_rfence_handler(struct kvm_vcpu *vcpu, struct kvm_run *run,
				      struct kvm_vcpu_sbi_return *retdata)
{
	struct kvm_cpu_context *cp = &vcpu->arch.guest_context;
	unsigned long hmask = cp->a0;
	unsigned long hbase = cp->a1;
	unsigned long funcid = cp->a6;
	unsigned long vmid;

	switch (funcid) {
	case SBI_EXT_RFENCE_REMOTE_FENCE_I:
		kvm_riscv_fence_i(vcpu->kvm, hbase, hmask);
		kvm_riscv_vcpu_pmu_incr_fw(vcpu, SBI_PMU_FW_FENCE_I_SENT);
		break;
	case SBI_EXT_RFENCE_REMOTE_SFENCE_VMA:
		vmid = READ_ONCE(vcpu->kvm->arch.vmid.vmid);
		if ((cp->a2 == 0 && cp->a3 == 0) || cp->a3 == -1UL)
			kvm_riscv_hfence_vvma_all(vcpu->kvm, hbase, hmask, vmid);
		else
			kvm_riscv_hfence_vvma_gva(vcpu->kvm, hbase, hmask,
						  cp->a2, cp->a3, PAGE_SHIFT, vmid);
		kvm_riscv_vcpu_pmu_incr_fw(vcpu, SBI_PMU_FW_HFENCE_VVMA_SENT);
		break;
	case SBI_EXT_RFENCE_REMOTE_SFENCE_VMA_ASID:
		vmid = READ_ONCE(vcpu->kvm->arch.vmid.vmid);
		if ((cp->a2 == 0 && cp->a3 == 0) || cp->a3 == -1UL)
			kvm_riscv_hfence_vvma_asid_all(vcpu->kvm, hbase, hmask,
						       cp->a4, vmid);
		else
			kvm_riscv_hfence_vvma_asid_gva(vcpu->kvm, hbase, hmask, cp->a2,
						       cp->a3, PAGE_SHIFT, cp->a4, vmid);
		kvm_riscv_vcpu_pmu_incr_fw(vcpu, SBI_PMU_FW_HFENCE_VVMA_ASID_SENT);
		break;
	case SBI_EXT_RFENCE_REMOTE_HFENCE_GVMA:
	case SBI_EXT_RFENCE_REMOTE_HFENCE_GVMA_VMID:
	case SBI_EXT_RFENCE_REMOTE_HFENCE_VVMA:
	case SBI_EXT_RFENCE_REMOTE_HFENCE_VVMA_ASID:
		/*
		 * Until nested virtualization is implemented, the
		 * SBI HFENCE calls should return not supported
		 * hence fallthrough.
		 */
	default:
		retdata->err_val = SBI_ERR_NOT_SUPPORTED;
	}

	return 0;
}

const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_rfence = {
	.extid_start = SBI_EXT_RFENCE,
	.extid_end = SBI_EXT_RFENCE,
	.handler = kvm_sbi_ext_rfence_handler,
};

static int kvm_sbi_ext_srst_handler(struct kvm_vcpu *vcpu,
				    struct kvm_run *run,
				    struct kvm_vcpu_sbi_return *retdata)
{
	struct kvm_cpu_context *cp = &vcpu->arch.guest_context;
	unsigned long funcid = cp->a6;

Annotation

Implementation Notes