arch/loongarch/kvm/exit.c

Source file repositories/reference/linux-study-clean/arch/loongarch/kvm/exit.c

File Facts

System
Linux kernel
Corpus path
arch/loongarch/kvm/exit.c
Extension
.c
Size
23375 bytes
Lines
972
Domain
Architecture Layer
Bucket
arch/loongarch
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 (kvm_guest_has_pmu(&vcpu->arch)) {
			vcpu->arch.pc -= 4;
			kvm_make_request(KVM_REQ_PMU, vcpu);
			return EMULATE_DONE;
		}
	}

	/* Process CSR ops */
	switch (rj) {
	case 0: /* process csrrd */
		val = kvm_emu_read_csr(vcpu, csrid);
		vcpu->arch.gprs[rd] = val;
		break;
	case 1: /* process csrwr */
		val = vcpu->arch.gprs[rd];
		val = kvm_emu_write_csr(vcpu, csrid, val);
		vcpu->arch.gprs[rd] = val;
		break;
	default: /* process csrxchg */
		val = vcpu->arch.gprs[rd];
		csr_mask = vcpu->arch.gprs[rj];
		val = kvm_emu_xchg_csr(vcpu, csrid, csr_mask, val);
		vcpu->arch.gprs[rd] = val;
	}

	return EMULATE_DONE;
}

int kvm_emu_iocsr(larch_inst inst, struct kvm_run *run, struct kvm_vcpu *vcpu)
{
	int idx, ret;
	unsigned long *val;
	u32 addr, rd, rj, opcode;

	/*
	 * Each IOCSR with different opcode
	 */
	rd = inst.reg2_format.rd;
	rj = inst.reg2_format.rj;
	opcode = inst.reg2_format.opcode;
	addr = vcpu->arch.gprs[rj];
	run->iocsr_io.phys_addr = addr;
	run->iocsr_io.is_write = 0;
	val = &vcpu->arch.gprs[rd];

	/* LoongArch is Little endian */
	switch (opcode) {
	case iocsrrdb_op:
		run->iocsr_io.len = 1;
		break;
	case iocsrrdh_op:
		run->iocsr_io.len = 2;
		break;
	case iocsrrdw_op:
		run->iocsr_io.len = 4;
		break;
	case iocsrrdd_op:
		run->iocsr_io.len = 8;
		break;
	case iocsrwrb_op:
		run->iocsr_io.len = 1;
		run->iocsr_io.is_write = 1;
		break;
	case iocsrwrh_op:
		run->iocsr_io.len = 2;
		run->iocsr_io.is_write = 1;
		break;
	case iocsrwrw_op:
		run->iocsr_io.len = 4;
		run->iocsr_io.is_write = 1;
		break;
	case iocsrwrd_op:
		run->iocsr_io.len = 8;
		run->iocsr_io.is_write = 1;
		break;
	default:
		return EMULATE_FAIL;
	}

	if (run->iocsr_io.is_write) {
		idx = srcu_read_lock(&vcpu->kvm->srcu);
		ret = kvm_io_bus_write(vcpu, KVM_IOCSR_BUS, addr, run->iocsr_io.len, val);
		srcu_read_unlock(&vcpu->kvm->srcu, idx);
		if (ret == 0)
			ret = EMULATE_DONE;
		else {
			ret = EMULATE_DO_IOCSR;
			/* Save data and let user space to write it */
			memcpy(run->iocsr_io.data, val, run->iocsr_io.len);
		}

Annotation

Implementation Notes