#define  CPUCFG48_VFPU_CG              BIT(2)
 #define  CPUCFG48_RAM_CG               BIT(3)
 
+/*
+ * CPUCFG index area: 0x40000000 -- 0x400000ff
+ * SW emulation for KVM hypervirsor
+ */
+#define CPUCFG_KVM_BASE                        0x40000000
+#define CPUCFG_KVM_SIZE                        0x100
+
+#define CPUCFG_KVM_SIG                 (CPUCFG_KVM_BASE + 0)
+#define  KVM_SIGNATURE                 "KVM\0"
+#define CPUCFG_KVM_FEATURE             (CPUCFG_KVM_BASE + 4)
+
 #ifndef __ASSEMBLY__
 
 /* CSR */
 
 #include <asm/kvm_vcpu.h>
 #include "trace.h"
 
+static int kvm_emu_cpucfg(struct kvm_vcpu *vcpu, larch_inst inst)
+{
+       int rd, rj;
+       unsigned int index;
+
+       if (inst.reg2_format.opcode != cpucfg_op)
+               return EMULATE_FAIL;
+
+       rd = inst.reg2_format.rd;
+       rj = inst.reg2_format.rj;
+       ++vcpu->stat.cpucfg_exits;
+       index = vcpu->arch.gprs[rj];
+
+       /*
+        * By LoongArch Reference Manual 2.2.10.5
+        * Return value is 0 for undefined CPUCFG index
+        *
+        * Disable preemption since hw gcsr is accessed
+        */
+       preempt_disable();
+       switch (index) {
+       case 0 ... (KVM_MAX_CPUCFG_REGS - 1):
+               vcpu->arch.gprs[rd] = vcpu->arch.cpucfg[index];
+               break;
+       case CPUCFG_KVM_SIG:
+               /* CPUCFG emulation between 0x40000000 -- 0x400000ff */
+               vcpu->arch.gprs[rd] = *(unsigned int *)KVM_SIGNATURE;
+               break;
+       default:
+               vcpu->arch.gprs[rd] = 0;
+               break;
+       }
+       preempt_enable();
+
+       return EMULATE_DONE;
+}
+
 static unsigned long kvm_emu_read_csr(struct kvm_vcpu *vcpu, int csrid)
 {
        unsigned long val = 0;
 
 static int kvm_trap_handle_gspr(struct kvm_vcpu *vcpu)
 {
-       int rd, rj;
-       unsigned int index;
        unsigned long curr_pc;
        larch_inst inst;
        enum emulation_result er = EMULATE_DONE;
        er = EMULATE_FAIL;
        switch (((inst.word >> 24) & 0xff)) {
        case 0x0: /* CPUCFG GSPR */
-               if (inst.reg2_format.opcode == 0x1B) {
-                       rd = inst.reg2_format.rd;
-                       rj = inst.reg2_format.rj;
-                       ++vcpu->stat.cpucfg_exits;
-                       index = vcpu->arch.gprs[rj];
-                       er = EMULATE_DONE;
-                       /*
-                        * By LoongArch Reference Manual 2.2.10.5
-                        * return value is 0 for undefined cpucfg index
-                        */
-                       if (index < KVM_MAX_CPUCFG_REGS)
-                               vcpu->arch.gprs[rd] = vcpu->arch.cpucfg[index];
-                       else
-                               vcpu->arch.gprs[rd] = 0;
-               }
+               er = kvm_emu_cpucfg(vcpu, inst);
                break;
        case 0x4: /* CSR{RD,WR,XCHG} GSPR */
                er = kvm_handle_csr(vcpu, inst);