Skip to content

Commit 81efe04

Browse files
zhaotianrui-loongsonchenhuacai
authored andcommitted
LoongArch: KVM: Implement handle iocsr exception
Implement kvm handle vcpu iocsr exception, setting the iocsr info into vcpu_run and return to user space to handle it. 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 da50f5a commit 81efe04

File tree

2 files changed

+107
-0
lines changed

2 files changed

+107
-0
lines changed

arch/loongarch/include/asm/inst.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,14 @@ enum reg2_op {
6565
revbd_op = 0x0f,
6666
revh2w_op = 0x10,
6767
revhd_op = 0x11,
68+
iocsrrdb_op = 0x19200,
69+
iocsrrdh_op = 0x19201,
70+
iocsrrdw_op = 0x19202,
71+
iocsrrdd_op = 0x19203,
72+
iocsrwrb_op = 0x19204,
73+
iocsrwrh_op = 0x19205,
74+
iocsrwrw_op = 0x19206,
75+
iocsrwrd_op = 0x19207,
6876
};
6977

7078
enum reg2i5_op {
@@ -318,6 +326,13 @@ struct reg2bstrd_format {
318326
unsigned int opcode : 10;
319327
};
320328

329+
struct reg2csr_format {
330+
unsigned int rd : 5;
331+
unsigned int rj : 5;
332+
unsigned int csr : 14;
333+
unsigned int opcode : 8;
334+
};
335+
321336
struct reg3_format {
322337
unsigned int rd : 5;
323338
unsigned int rj : 5;
@@ -346,6 +361,7 @@ union loongarch_instruction {
346361
struct reg2i14_format reg2i14_format;
347362
struct reg2i16_format reg2i16_format;
348363
struct reg2bstrd_format reg2bstrd_format;
364+
struct reg2csr_format reg2csr_format;
349365
struct reg3_format reg3_format;
350366
struct reg3sa2_format reg3sa2_format;
351367
};

arch/loongarch/kvm/exit.c

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,3 +103,94 @@ static int kvm_handle_csr(struct kvm_vcpu *vcpu, larch_inst inst)
103103

104104
return EMULATE_DONE;
105105
}
106+
107+
int kvm_emu_iocsr(larch_inst inst, struct kvm_run *run, struct kvm_vcpu *vcpu)
108+
{
109+
int ret;
110+
unsigned long val;
111+
u32 addr, rd, rj, opcode;
112+
113+
/*
114+
* Each IOCSR with different opcode
115+
*/
116+
rd = inst.reg2_format.rd;
117+
rj = inst.reg2_format.rj;
118+
opcode = inst.reg2_format.opcode;
119+
addr = vcpu->arch.gprs[rj];
120+
ret = EMULATE_DO_IOCSR;
121+
run->iocsr_io.phys_addr = addr;
122+
run->iocsr_io.is_write = 0;
123+
124+
/* LoongArch is Little endian */
125+
switch (opcode) {
126+
case iocsrrdb_op:
127+
run->iocsr_io.len = 1;
128+
break;
129+
case iocsrrdh_op:
130+
run->iocsr_io.len = 2;
131+
break;
132+
case iocsrrdw_op:
133+
run->iocsr_io.len = 4;
134+
break;
135+
case iocsrrdd_op:
136+
run->iocsr_io.len = 8;
137+
break;
138+
case iocsrwrb_op:
139+
run->iocsr_io.len = 1;
140+
run->iocsr_io.is_write = 1;
141+
break;
142+
case iocsrwrh_op:
143+
run->iocsr_io.len = 2;
144+
run->iocsr_io.is_write = 1;
145+
break;
146+
case iocsrwrw_op:
147+
run->iocsr_io.len = 4;
148+
run->iocsr_io.is_write = 1;
149+
break;
150+
case iocsrwrd_op:
151+
run->iocsr_io.len = 8;
152+
run->iocsr_io.is_write = 1;
153+
break;
154+
default:
155+
ret = EMULATE_FAIL;
156+
break;
157+
}
158+
159+
if (ret == EMULATE_DO_IOCSR) {
160+
if (run->iocsr_io.is_write) {
161+
val = vcpu->arch.gprs[rd];
162+
memcpy(run->iocsr_io.data, &val, run->iocsr_io.len);
163+
}
164+
vcpu->arch.io_gpr = rd;
165+
}
166+
167+
return ret;
168+
}
169+
170+
int kvm_complete_iocsr_read(struct kvm_vcpu *vcpu, struct kvm_run *run)
171+
{
172+
enum emulation_result er = EMULATE_DONE;
173+
unsigned long *gpr = &vcpu->arch.gprs[vcpu->arch.io_gpr];
174+
175+
switch (run->iocsr_io.len) {
176+
case 1:
177+
*gpr = *(s8 *)run->iocsr_io.data;
178+
break;
179+
case 2:
180+
*gpr = *(s16 *)run->iocsr_io.data;
181+
break;
182+
case 4:
183+
*gpr = *(s32 *)run->iocsr_io.data;
184+
break;
185+
case 8:
186+
*gpr = *(s64 *)run->iocsr_io.data;
187+
break;
188+
default:
189+
kvm_err("Bad IOCSR length: %d, addr is 0x%lx\n",
190+
run->iocsr_io.len, vcpu->arch.badv);
191+
er = EMULATE_FAIL;
192+
break;
193+
}
194+
195+
return er;
196+
}

0 commit comments

Comments
 (0)