Skip to content

Commit 2737dee

Browse files
bibo-maochenhuacai
authored andcommitted
LoongArch: KVM: Add hypercall service support for usermode VMM
Some VMMs provides special hypercall service in usermode, KVM should not handle the usermode hypercall service, thus pass it to usermode, let the usermode VMM handle it. Here a new code KVM_HCALL_CODE_USER_SERVICE is added for the user-mode hypercall service, KVM lets all six registers visible to usermode VMM. Signed-off-by: Bibo Mao <maobibo@loongson.cn> Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
1 parent 4d38d04 commit 2737dee

File tree

6 files changed

+42
-1
lines changed

6 files changed

+42
-1
lines changed

arch/loongarch/include/asm/kvm_host.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,7 @@ enum emulation_result {
162162
#define LOONGARCH_PV_FEAT_UPDATED BIT_ULL(63)
163163
#define LOONGARCH_PV_FEAT_MASK (BIT(KVM_FEATURE_IPI) | \
164164
BIT(KVM_FEATURE_STEAL_TIME) | \
165+
BIT(KVM_FEATURE_USER_HCALL) | \
165166
BIT(KVM_FEATURE_VIRT_EXTIOI))
166167

167168
struct kvm_vcpu_arch {

arch/loongarch/include/asm/kvm_para.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,16 @@
1313

1414
#define KVM_HCALL_CODE_SERVICE 0
1515
#define KVM_HCALL_CODE_SWDBG 1
16+
#define KVM_HCALL_CODE_USER_SERVICE 2
1617

1718
#define KVM_HCALL_SERVICE HYPERCALL_ENCODE(HYPERVISOR_KVM, KVM_HCALL_CODE_SERVICE)
1819
#define KVM_HCALL_FUNC_IPI 1
1920
#define KVM_HCALL_FUNC_NOTIFY 2
2021

2122
#define KVM_HCALL_SWDBG HYPERCALL_ENCODE(HYPERVISOR_KVM, KVM_HCALL_CODE_SWDBG)
2223

24+
#define KVM_HCALL_USER_SERVICE HYPERCALL_ENCODE(HYPERVISOR_KVM, KVM_HCALL_CODE_USER_SERVICE)
25+
2326
/*
2427
* LoongArch hypercall return code
2528
*/

arch/loongarch/include/asm/kvm_vcpu.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ int kvm_emu_mmio_read(struct kvm_vcpu *vcpu, larch_inst inst);
4343
int kvm_emu_mmio_write(struct kvm_vcpu *vcpu, larch_inst inst);
4444
int kvm_complete_mmio_read(struct kvm_vcpu *vcpu, struct kvm_run *run);
4545
int kvm_complete_iocsr_read(struct kvm_vcpu *vcpu, struct kvm_run *run);
46+
int kvm_complete_user_service(struct kvm_vcpu *vcpu, struct kvm_run *run);
4647
int kvm_emu_idle(struct kvm_vcpu *vcpu);
4748
int kvm_pending_timer(struct kvm_vcpu *vcpu);
4849
int kvm_handle_fault(struct kvm_vcpu *vcpu, int fault);

arch/loongarch/include/uapi/asm/kvm_para.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,5 +17,6 @@
1717
#define KVM_FEATURE_STEAL_TIME 2
1818
/* BIT 24 - 31 are features configurable by user space vmm */
1919
#define KVM_FEATURE_VIRT_EXTIOI 24
20+
#define KVM_FEATURE_USER_HCALL 25
2021

2122
#endif /* _UAPI_ASM_KVM_PARA_H */

arch/loongarch/kvm/exit.c

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -709,6 +709,14 @@ static int kvm_handle_write_fault(struct kvm_vcpu *vcpu)
709709
return kvm_handle_rdwr_fault(vcpu, true);
710710
}
711711

712+
int kvm_complete_user_service(struct kvm_vcpu *vcpu, struct kvm_run *run)
713+
{
714+
update_pc(&vcpu->arch);
715+
kvm_write_reg(vcpu, LOONGARCH_GPR_A0, run->hypercall.ret);
716+
717+
return 0;
718+
}
719+
712720
/**
713721
* kvm_handle_fpu_disabled() - Guest used fpu however it is disabled at host
714722
* @vcpu: Virtual CPU context.
@@ -873,6 +881,28 @@ static int kvm_handle_hypercall(struct kvm_vcpu *vcpu)
873881
vcpu->stat.hypercall_exits++;
874882
kvm_handle_service(vcpu);
875883
break;
884+
case KVM_HCALL_USER_SERVICE:
885+
if (!kvm_guest_has_pv_feature(vcpu, KVM_FEATURE_USER_HCALL)) {
886+
kvm_write_reg(vcpu, LOONGARCH_GPR_A0, KVM_HCALL_INVALID_CODE);
887+
break;
888+
}
889+
890+
vcpu->stat.hypercall_exits++;
891+
vcpu->run->exit_reason = KVM_EXIT_HYPERCALL;
892+
vcpu->run->hypercall.nr = KVM_HCALL_USER_SERVICE;
893+
vcpu->run->hypercall.args[0] = kvm_read_reg(vcpu, LOONGARCH_GPR_A0);
894+
vcpu->run->hypercall.args[1] = kvm_read_reg(vcpu, LOONGARCH_GPR_A1);
895+
vcpu->run->hypercall.args[2] = kvm_read_reg(vcpu, LOONGARCH_GPR_A2);
896+
vcpu->run->hypercall.args[3] = kvm_read_reg(vcpu, LOONGARCH_GPR_A3);
897+
vcpu->run->hypercall.args[4] = kvm_read_reg(vcpu, LOONGARCH_GPR_A4);
898+
vcpu->run->hypercall.args[5] = kvm_read_reg(vcpu, LOONGARCH_GPR_A5);
899+
vcpu->run->hypercall.flags = 0;
900+
/*
901+
* Set invalid return value by default, let user-mode VMM modify it.
902+
*/
903+
vcpu->run->hypercall.ret = KVM_HCALL_INVALID_CODE;
904+
ret = RESUME_HOST;
905+
break;
876906
case KVM_HCALL_SWDBG:
877907
/* KVM_HCALL_SWDBG only in effective when SW_BP is enabled */
878908
if (vcpu->guest_debug & KVM_GUESTDBG_SW_BP_MASK) {

arch/loongarch/kvm/vcpu.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1732,9 +1732,14 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu)
17321732
vcpu->mmio_needed = 0;
17331733
}
17341734

1735-
if (run->exit_reason == KVM_EXIT_LOONGARCH_IOCSR) {
1735+
switch (run->exit_reason) {
1736+
case KVM_EXIT_HYPERCALL:
1737+
kvm_complete_user_service(vcpu, run);
1738+
break;
1739+
case KVM_EXIT_LOONGARCH_IOCSR:
17361740
if (!run->iocsr_io.is_write)
17371741
kvm_complete_iocsr_read(vcpu, run);
1742+
break;
17381743
}
17391744

17401745
if (!vcpu->wants_to_run)

0 commit comments

Comments
 (0)