Skip to content

Commit da50f5a

Browse files
zhaotianrui-loongsonchenhuacai
authored andcommitted
LoongArch: KVM: Implement handle csr exception
Implement kvm handle LoongArch vcpu exit caused by reading, writing and exchanging csr. Use kvm_vcpu_arch::csr structure to emulate the software registers. Reviewed-by: Bibo Mao <[email protected]> Tested-by: Huacai Chen <[email protected]> Signed-off-by: Tianrui Zhao <[email protected]> Signed-off-by: Huacai Chen <[email protected]>
1 parent 752e2cd commit da50f5a

File tree

1 file changed

+105
-0
lines changed

1 file changed

+105
-0
lines changed

arch/loongarch/kvm/exit.c

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
/*
3+
* Copyright (C) 2020-2023 Loongson Technology Corporation Limited
4+
*/
5+
6+
#include <linux/err.h>
7+
#include <linux/errno.h>
8+
#include <linux/kvm_host.h>
9+
#include <linux/module.h>
10+
#include <linux/preempt.h>
11+
#include <linux/vmalloc.h>
12+
#include <asm/fpu.h>
13+
#include <asm/inst.h>
14+
#include <asm/loongarch.h>
15+
#include <asm/mmzone.h>
16+
#include <asm/numa.h>
17+
#include <asm/time.h>
18+
#include <asm/tlb.h>
19+
#include <asm/kvm_csr.h>
20+
#include <asm/kvm_vcpu.h>
21+
#include "trace.h"
22+
23+
static unsigned long kvm_emu_read_csr(struct kvm_vcpu *vcpu, int csrid)
24+
{
25+
unsigned long val = 0;
26+
struct loongarch_csrs *csr = vcpu->arch.csr;
27+
28+
/*
29+
* From LoongArch Reference Manual Volume 1 Chapter 4.2.1
30+
* For undefined CSR id, return value is 0
31+
*/
32+
if (get_gcsr_flag(csrid) & SW_GCSR)
33+
val = kvm_read_sw_gcsr(csr, csrid);
34+
else
35+
pr_warn_once("Unsupported csrrd 0x%x with pc %lx\n", csrid, vcpu->arch.pc);
36+
37+
return val;
38+
}
39+
40+
static unsigned long kvm_emu_write_csr(struct kvm_vcpu *vcpu, int csrid, unsigned long val)
41+
{
42+
unsigned long old = 0;
43+
struct loongarch_csrs *csr = vcpu->arch.csr;
44+
45+
if (get_gcsr_flag(csrid) & SW_GCSR) {
46+
old = kvm_read_sw_gcsr(csr, csrid);
47+
kvm_write_sw_gcsr(csr, csrid, val);
48+
} else
49+
pr_warn_once("Unsupported csrwr 0x%x with pc %lx\n", csrid, vcpu->arch.pc);
50+
51+
return old;
52+
}
53+
54+
static unsigned long kvm_emu_xchg_csr(struct kvm_vcpu *vcpu, int csrid,
55+
unsigned long csr_mask, unsigned long val)
56+
{
57+
unsigned long old = 0;
58+
struct loongarch_csrs *csr = vcpu->arch.csr;
59+
60+
if (get_gcsr_flag(csrid) & SW_GCSR) {
61+
old = kvm_read_sw_gcsr(csr, csrid);
62+
val = (old & ~csr_mask) | (val & csr_mask);
63+
kvm_write_sw_gcsr(csr, csrid, val);
64+
old = old & csr_mask;
65+
} else
66+
pr_warn_once("Unsupported csrxchg 0x%x with pc %lx\n", csrid, vcpu->arch.pc);
67+
68+
return old;
69+
}
70+
71+
static int kvm_handle_csr(struct kvm_vcpu *vcpu, larch_inst inst)
72+
{
73+
unsigned int rd, rj, csrid;
74+
unsigned long csr_mask, val = 0;
75+
76+
/*
77+
* CSR value mask imm
78+
* rj = 0 means csrrd
79+
* rj = 1 means csrwr
80+
* rj != 0,1 means csrxchg
81+
*/
82+
rd = inst.reg2csr_format.rd;
83+
rj = inst.reg2csr_format.rj;
84+
csrid = inst.reg2csr_format.csr;
85+
86+
/* Process CSR ops */
87+
switch (rj) {
88+
case 0: /* process csrrd */
89+
val = kvm_emu_read_csr(vcpu, csrid);
90+
vcpu->arch.gprs[rd] = val;
91+
break;
92+
case 1: /* process csrwr */
93+
val = vcpu->arch.gprs[rd];
94+
val = kvm_emu_write_csr(vcpu, csrid, val);
95+
vcpu->arch.gprs[rd] = val;
96+
break;
97+
default: /* process csrxchg */
98+
val = vcpu->arch.gprs[rd];
99+
csr_mask = vcpu->arch.gprs[rj];
100+
val = kvm_emu_xchg_csr(vcpu, csrid, csr_mask, val);
101+
vcpu->arch.gprs[rd] = val;
102+
}
103+
104+
return EMULATE_DONE;
105+
}

0 commit comments

Comments
 (0)