/* SPDX-License-Identifier: GPL-2.0-only */ #ifndef SELFTEST_KVM_PROCESSOR_H#define SELFTEST_KVM_PROCESSOR_H #ifndef __ASSEMBLER__#include "ucall_common.h" #else/* general registers */#define zero $r0#define ra $r1#define tp $r2#define sp $r3#define a0 $r4#define a1 $r5#define a2 $r6#define a3 $r7#define a4 $r8#define a5 $r9#define a6 $r10#define a7 $r11#define t0 $r12#define t1 $r13#define t2 $r14#define t3 $r15#define t4 $r16#define t5 $r17#define t6 $r18#define t7 $r19#define t8 $r20#define u0 $r21#define fp $r22#define s0 $r23#define s1 $r24#define s2 $r25#define s3 $r26#define s4 $r27#define s5 $r28#define s6 $r29#define s7 $r30#define s8 $r31#endif /* * LoongArch page table entry definition * Original header file arch/loongarch/include/asm/loongarch.h */#define _PAGE_VALID_SHIFT 0#define _PAGE_DIRTY_SHIFT 1#define _PAGE_PLV_SHIFT 2 /* 2~3, two bits */#define PLV_KERN 0#define PLV_USER 3#define PLV_MASK 0x3#define _CACHE_SHIFT 4 /* 4~5, two bits */#define _PAGE_PRESENT_SHIFT 7#define _PAGE_WRITE_SHIFT 8 #define _PAGE_VALID BIT_ULL(_PAGE_VALID_SHIFT)#define _PAGE_PRESENT BIT_ULL(_PAGE_PRESENT_SHIFT)#define _PAGE_WRITE BIT_ULL(_PAGE_WRITE_SHIFT)#define _PAGE_DIRTY BIT_ULL(_PAGE_DIRTY_SHIFT)#define _PAGE_USER (PLV_USER << _PAGE_PLV_SHIFT)#define __READABLE (_PAGE_VALID)#define __WRITEABLE (_PAGE_DIRTY | _PAGE_WRITE)/* Coherent Cached */#define _CACHE_CC BIT_ULL(_CACHE_SHIFT)#define PS_4K 0x0000000c#define PS_16K 0x0000000e#define PS_64K 0x00000010#define PS_DEFAULT_SIZE PS_16K #define LOONGARCH_CPUCFG2 0x2#define CPUCFG2_FP BIT(0)#define CPUCFG2_FPSP BIT(1)#define CPUCFG2_FPDP BIT(2)#define CPUCFG2_FPVERS GENMASK(5, 3)#define CPUCFG2_LSX BIT(6)#define CPUCFG2_LASX BIT(7)#define CPUCFG2_LLFTP BIT(14)#define CPUCFG2_LLFTPREV GENMASK(17, 15) /* LoongArch Basic CSR registers */#define LOONGARCH_CSR_CRMD 0x0 /* Current mode info */#define CSR_CRMD_PG_SHIFT 4#define CSR_CRMD_PG BIT_ULL(CSR_CRMD_PG_SHIFT)#define CSR_CRMD_IE_SHIFT 2#define CSR_CRMD_IE BIT_ULL(CSR_CRMD_IE_SHIFT)#define CSR_CRMD_PLV_SHIFT 0#define CSR_CRMD_PLV_WIDTH 2#define CSR_CRMD_PLV (0x3UL << CSR_CRMD_PLV_SHIFT)#define PLV_MASK 0x3#define LOONGARCH_CSR_PRMD 0x1#define LOONGARCH_CSR_EUEN 0x2#define CSR_EUEN_LBTEN_SHIFT 3#define CSR_EUEN_LBTEN BIT_ULL(CSR_EUEN_LBTEN_SHIFT)#define CSR_EUEN_LASXEN_SHIFT 2#define CSR_EUEN_LASXEN BIT_ULL(CSR_EUEN_LASXEN_SHIFT)#define CSR_EUEN_LSXEN_SHIFT 1#define CSR_EUEN_LSXEN BIT_ULL(CSR_EUEN_LSXEN_SHIFT)#define CSR_EUEN_FPEN_SHIFT 0#define CSR_EUEN_FPEN BIT_ULL(CSR_EUEN_FPEN_SHIFT)#define LOONGARCH_CSR_ECFG 0x4#define ECFGB_PMU 10#define ECFGF_PMU (BIT_ULL(ECFGB_PMU))#define ECFGB_TIMER 11#define ECFGF_TIMER (BIT_ULL(ECFGB_TIMER))#define LOONGARCH_CSR_ESTAT 0x5 /* Exception status */#define CSR_ESTAT_EXC_SHIFT 16#define CSR_ESTAT_EXC_WIDTH 6#define CSR_ESTAT_EXC (0x3f << CSR_ESTAT_EXC_SHIFT)#define EXCCODE_INT 0 /* Interrupt */#define INT_PMI 10 /* PMU interrupt */#define INT_TI 11 /* Timer interrupt*/#define LOONGARCH_CSR_ERA 0x6 /* ERA */#define LOONGARCH_CSR_BADV 0x7 /* Bad virtual address */#define LOONGARCH_CSR_EENTRY 0xc#define LOONGARCH_CSR_TLBIDX 0x10 /* TLB Index, EHINV, PageSize */#define CSR_TLBIDX_PS_SHIFT 24#define CSR_TLBIDX_PS_WIDTH 6#define CSR_TLBIDX_PS (0x3fUL << CSR_TLBIDX_PS_SHIFT)#define CSR_TLBIDX_SIZEM 0x3f000000#define CSR_TLBIDX_SIZE CSR_TLBIDX_PS_SHIFT#define LOONGARCH_CSR_ASID 0x18 /* ASID */#define LOONGARCH_CSR_PGDL 0x19#define LOONGARCH_CSR_PGDH 0x1a/* Page table base */#define LOONGARCH_CSR_PGD 0x1b#define LOONGARCH_CSR_PWCTL0 0x1c#define LOONGARCH_CSR_PWCTL1 0x1d#define LOONGARCH_CSR_STLBPGSIZE 0x1e#define LOONGARCH_CSR_CPUID 0x20#define LOONGARCH_CSR_KS0 0x30#define LOONGARCH_CSR_KS1 0x31#define LOONGARCH_CSR_TMID 0x40#define LOONGARCH_CSR_TCFG 0x41#define CSR_TCFG_VAL (BIT_ULL(48) - BIT_ULL(2))#define CSR_TCFG_PERIOD_SHIFT 1#define CSR_TCFG_PERIOD (0x1UL << CSR_TCFG_PERIOD_SHIFT)#define CSR_TCFG_EN (0x1UL)#define LOONGARCH_CSR_TVAL 0x42#define LOONGARCH_CSR_TINTCLR 0x44 /* Timer interrupt clear */#define CSR_TINTCLR_TI_SHIFT 0#define CSR_TINTCLR_TI (1 << CSR_TINTCLR_TI_SHIFT)/* TLB refill exception entry */#define LOONGARCH_CSR_TLBRENTRY 0x88#define LOONGARCH_CSR_TLBRSAVE 0x8b#define LOONGARCH_CSR_TLBREHI 0x8e#define CSR_TLBREHI_PS_SHIFT 0#define CSR_TLBREHI_PS (0x3fUL << CSR_TLBREHI_PS_SHIFT) #define read_cpucfg(reg) \({ \ register unsigned long __v; \ __asm__ __volatile__( \ "cpucfg %0, %1\n\t" \ : "=r" (__v) \ : "r" (reg) \ : "memory"); \ __v; \}) #define csr_read(csr) \({ \ register unsigned long __v; \ __asm__ __volatile__( \ "csrrd %[val], %[reg]\n\t" \ : [val] "=r" (__v) \ : [reg] "i" (csr) \ : "memory"); \ __v; \}) #define csr_write(v, csr) \({ \ register unsigned long __v = v; \ __asm__ __volatile__ ( \ "csrwr %[val], %[reg]\n\t" \ : [val] "+r" (__v) \ : [reg] "i" (csr) \ : "memory"); \ __v; \}) #define EXREGS_GPRS (32) #ifndef __ASSEMBLER__void handle_tlb_refill(void);void handle_exception(void); struct ex_regs { unsigned long regs[EXREGS_GPRS]; unsigned long pc; unsigned long estat; unsigned long badv; unsigned long prmd;}; #define PC_OFFSET_EXREGS offsetof(struct ex_regs, pc)#define ESTAT_OFFSET_EXREGS offsetof(struct ex_regs, estat)#define BADV_OFFSET_EXREGS offsetof(struct ex_regs, badv)#define PRMD_OFFSET_EXREGS offsetof(struct ex_regs, prmd)#define EXREGS_SIZE sizeof(struct ex_regs) #define VECTOR_NUM 64 typedef void(*handler_fn)(struct ex_regs *); struct handlers { handler_fn exception_handlers[VECTOR_NUM];}; void loongarch_vcpu_setup(struct kvm_vcpu *vcpu);void vm_init_descriptor_tables(struct kvm_vm *vm);void vm_install_exception_handler(struct kvm_vm *vm, int vector, handler_fn handler); static inline void cpu_relax(void){ asm volatile("nop" ::: "memory");} static inline void local_irq_enable(void){ unsigned int flags = CSR_CRMD_IE; register unsigned int mask asm("$t0") = CSR_CRMD_IE; __asm__ __volatile__( "csrxchg %[val], %[mask], %[reg]\n\t" : [val] "+r" (flags) : [mask] "r" (mask), [reg] "i" (LOONGARCH_CSR_CRMD) : "memory");} static inline void local_irq_disable(void){ unsigned int flags = 0; register unsigned int mask asm("$t0") = CSR_CRMD_IE; __asm__ __volatile__( "csrxchg %[val], %[mask], %[reg]\n\t" : [val] "+r" (flags) : [mask] "r" (mask), [reg] "i" (LOONGARCH_CSR_CRMD) : "memory");}#else#define PC_OFFSET_EXREGS ((EXREGS_GPRS + 0) * 8)#define ESTAT_OFFSET_EXREGS ((EXREGS_GPRS + 1) * 8)#define BADV_OFFSET_EXREGS ((EXREGS_GPRS + 2) * 8)#define PRMD_OFFSET_EXREGS ((EXREGS_GPRS + 3) * 8)#define EXREGS_SIZE ((EXREGS_GPRS + 4) * 8)#endif #endif /* SELFTEST_KVM_PROCESSOR_H */
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef SELFTEST_KVM_PROCESSOR_H
#define SELFTEST_KVM_PROCESSOR_H
#ifndef __ASSEMBLER__
#include "ucall_common.h"
#else
/* general registers */
#define zero $r0
#define ra $r1
#define tp $r2
#define sp $r3
#define a0 $r4
#define a1 $r5
#define a2 $r6
#define a3 $r7
#define a4 $r8
#define a5 $r9
#define a6 $r10
#define a7 $r11
#define t0 $r12
#define t1 $r13
#define t2 $r14
#define t3 $r15
#define t4 $r16
#define t5 $r17
#define t6 $r18
#define t7 $r19
#define t8 $r20
#define u0 $r21
#define fp $r22
#define s0 $r23
#define s1 $r24
#define s2 $r25
#define s3 $r26
#define s4 $r27
#define s5 $r28
#define s6 $r29
#define s7 $r30
#define s8 $r31
#endif
/*
* LoongArch page table entry definition
* Original header file arch/loongarch/include/asm/loongarch.h
*/
#define _PAGE_VALID_SHIFT 0
#define _PAGE_DIRTY_SHIFT 1
#define _PAGE_PLV_SHIFT 2 /* 2~3, two bits */
#define PLV_KERN 0
#define PLV_USER 3
#define PLV_MASK 0x3
#define _CACHE_SHIFT 4 /* 4~5, two bits */
#define _PAGE_PRESENT_SHIFT 7
#define _PAGE_WRITE_SHIFT 8
#define _PAGE_VALID BIT_ULL(_PAGE_VALID_SHIFT)
#define _PAGE_PRESENT BIT_ULL(_PAGE_PRESENT_SHIFT)
#define _PAGE_WRITE BIT_ULL(_PAGE_WRITE_SHIFT)
#define _PAGE_DIRTY BIT_ULL(_PAGE_DIRTY_SHIFT)
#define _PAGE_USER (PLV_USER << _PAGE_PLV_SHIFT)
#define __READABLE (_PAGE_VALID)
#define __WRITEABLE (_PAGE_DIRTY | _PAGE_WRITE)
/* Coherent Cached */
#define _CACHE_CC BIT_ULL(_CACHE_SHIFT)
#define PS_4K 0x0000000c
#define PS_16K 0x0000000e
#define PS_64K 0x00000010
#define PS_DEFAULT_SIZE PS_16K
#define LOONGARCH_CPUCFG2 0x2
#define CPUCFG2_FP BIT(0)
#define CPUCFG2_FPSP BIT(1)
#define CPUCFG2_FPDP BIT(2)
#define CPUCFG2_FPVERS GENMASK(5, 3)
#define CPUCFG2_LSX BIT(6)
#define CPUCFG2_LASX BIT(7)
#define CPUCFG2_LLFTP BIT(14)
#define CPUCFG2_LLFTPREV GENMASK(17, 15)
/* LoongArch Basic CSR registers */
#define LOONGARCH_CSR_CRMD 0x0 /* Current mode info */
#define CSR_CRMD_PG_SHIFT 4
#define CSR_CRMD_PG BIT_ULL(CSR_CRMD_PG_SHIFT)
#define CSR_CRMD_IE_SHIFT 2
#define CSR_CRMD_IE BIT_ULL(CSR_CRMD_IE_SHIFT)
#define CSR_CRMD_PLV_SHIFT 0
#define CSR_CRMD_PLV_WIDTH 2
#define CSR_CRMD_PLV (0x3UL << CSR_CRMD_PLV_SHIFT)
#define PLV_MASK 0x3
#define LOONGARCH_CSR_PRMD 0x1
#define LOONGARCH_CSR_EUEN 0x2
#define CSR_EUEN_LBTEN_SHIFT 3
#define CSR_EUEN_LBTEN BIT_ULL(CSR_EUEN_LBTEN_SHIFT)
#define CSR_EUEN_LASXEN_SHIFT 2
#define CSR_EUEN_LASXEN BIT_ULL(CSR_EUEN_LASXEN_SHIFT)
#define CSR_EUEN_LSXEN_SHIFT 1
#define CSR_EUEN_LSXEN BIT_ULL(CSR_EUEN_LSXEN_SHIFT)
#define CSR_EUEN_FPEN_SHIFT 0
#define CSR_EUEN_FPEN BIT_ULL(CSR_EUEN_FPEN_SHIFT)
#define LOONGARCH_CSR_ECFG 0x4
#define ECFGB_PMU 10
#define ECFGF_PMU (BIT_ULL(ECFGB_PMU))
#define ECFGB_TIMER 11
#define ECFGF_TIMER (BIT_ULL(ECFGB_TIMER))
#define LOONGARCH_CSR_ESTAT 0x5 /* Exception status */
#define CSR_ESTAT_EXC_SHIFT 16
#define CSR_ESTAT_EXC_WIDTH 6
#define CSR_ESTAT_EXC (0x3f << CSR_ESTAT_EXC_SHIFT)
#define EXCCODE_INT 0 /* Interrupt */
#define INT_PMI 10 /* PMU interrupt */
#define INT_TI 11 /* Timer interrupt*/
#define LOONGARCH_CSR_ERA 0x6 /* ERA */
#define LOONGARCH_CSR_BADV 0x7 /* Bad virtual address */
#define LOONGARCH_CSR_EENTRY 0xc
#define LOONGARCH_CSR_TLBIDX 0x10 /* TLB Index, EHINV, PageSize */
#define CSR_TLBIDX_PS_SHIFT 24
#define CSR_TLBIDX_PS_WIDTH 6
#define CSR_TLBIDX_PS (0x3fUL << CSR_TLBIDX_PS_SHIFT)
#define CSR_TLBIDX_SIZEM 0x3f000000
#define CSR_TLBIDX_SIZE CSR_TLBIDX_PS_SHIFT
#define LOONGARCH_CSR_ASID 0x18 /* ASID */
#define LOONGARCH_CSR_PGDL 0x19
#define LOONGARCH_CSR_PGDH 0x1a
/* Page table base */
#define LOONGARCH_CSR_PGD 0x1b
#define LOONGARCH_CSR_PWCTL0 0x1c
#define LOONGARCH_CSR_PWCTL1 0x1d
#define LOONGARCH_CSR_STLBPGSIZE 0x1e
#define LOONGARCH_CSR_CPUID 0x20
#define LOONGARCH_CSR_KS0 0x30
#define LOONGARCH_CSR_KS1 0x31
#define LOONGARCH_CSR_TMID 0x40
#define LOONGARCH_CSR_TCFG 0x41
#define CSR_TCFG_VAL (BIT_ULL(48) - BIT_ULL(2))
#define CSR_TCFG_PERIOD_SHIFT 1
#define CSR_TCFG_PERIOD (0x1UL << CSR_TCFG_PERIOD_SHIFT)
#define CSR_TCFG_EN (0x1UL)
#define LOONGARCH_CSR_TVAL 0x42
#define LOONGARCH_CSR_TINTCLR 0x44 /* Timer interrupt clear */
#define CSR_TINTCLR_TI_SHIFT 0
#define CSR_TINTCLR_TI (1 << CSR_TINTCLR_TI_SHIFT)
/* TLB refill exception entry */
#define LOONGARCH_CSR_TLBRENTRY 0x88
#define LOONGARCH_CSR_TLBRSAVE 0x8b
#define LOONGARCH_CSR_TLBREHI 0x8e
#define CSR_TLBREHI_PS_SHIFT 0
#define CSR_TLBREHI_PS (0x3fUL << CSR_TLBREHI_PS_SHIFT)
#define read_cpucfg(reg) \
({ \
register unsigned long __v; \
__asm__ __volatile__( \
"cpucfg %0, %1\n\t" \
: "=r" (__v) \
: "r" (reg) \
: "memory"); \
__v; \
})
#define csr_read(csr) \
({ \
register unsigned long __v; \
__asm__ __volatile__( \
"csrrd %[val], %[reg]\n\t" \
: [val] "=r" (__v) \
: [reg] "i" (csr) \
: "memory"); \
__v; \
})
#define csr_write(v, csr) \
({ \
register unsigned long __v = v; \
__asm__ __volatile__ ( \
"csrwr %[val], %[reg]\n\t" \
: [val] "+r" (__v) \
: [reg] "i" (csr) \
: "memory"); \
__v; \
})
#define EXREGS_GPRS (32)
#ifndef __ASSEMBLER__
void handle_tlb_refill(void);
void handle_exception(void);
struct ex_regs {
unsigned long regs[EXREGS_GPRS];
unsigned long pc;
unsigned long estat;
unsigned long badv;
unsigned long prmd;
};
#define PC_OFFSET_EXREGS offsetof(struct ex_regs, pc)
#define ESTAT_OFFSET_EXREGS offsetof(struct ex_regs, estat)
#define BADV_OFFSET_EXREGS offsetof(struct ex_regs, badv)
#define PRMD_OFFSET_EXREGS offsetof(struct ex_regs, prmd)
#define EXREGS_SIZE sizeof(struct ex_regs)
#define VECTOR_NUM 64
typedef void(*handler_fn)(struct ex_regs *);
struct handlers {
handler_fn exception_handlers[VECTOR_NUM];
};
void loongarch_vcpu_setup(struct kvm_vcpu *vcpu);
void vm_init_descriptor_tables(struct kvm_vm *vm);
void vm_install_exception_handler(struct kvm_vm *vm, int vector, handler_fn handler);
static inline void cpu_relax(void)
{
asm volatile("nop" ::: "memory");
}
static inline void local_irq_enable(void)
{
unsigned int flags = CSR_CRMD_IE;
register unsigned int mask asm("$t0") = CSR_CRMD_IE;
__asm__ __volatile__(
"csrxchg %[val], %[mask], %[reg]\n\t"
: [val] "+r" (flags)
: [mask] "r" (mask), [reg] "i" (LOONGARCH_CSR_CRMD)
: "memory");
}
static inline void local_irq_disable(void)
{
unsigned int flags = 0;
register unsigned int mask asm("$t0") = CSR_CRMD_IE;
__asm__ __volatile__(
"csrxchg %[val], %[mask], %[reg]\n\t"
: [val] "+r" (flags)
: [mask] "r" (mask), [reg] "i" (LOONGARCH_CSR_CRMD)
: "memory");
}
#else
#define PC_OFFSET_EXREGS ((EXREGS_GPRS + 0) * 8)
#define ESTAT_OFFSET_EXREGS ((EXREGS_GPRS + 1) * 8)
#define BADV_OFFSET_EXREGS ((EXREGS_GPRS + 2) * 8)
#define PRMD_OFFSET_EXREGS ((EXREGS_GPRS + 3) * 8)
#define EXREGS_SIZE ((EXREGS_GPRS + 4) * 8)
#endif
#endif /* SELFTEST_KVM_PROCESSOR_H */