237 lines
6.6 KiB
C
237 lines
6.6 KiB
C
/* SPDX-License-Identifier: GPL-2.0 */
|
|
#ifndef _ASM_SW64_HMCALL_H
|
|
#define _ASM_SW64_HMCALL_H
|
|
|
|
/*
|
|
* Common HMC-code
|
|
*/
|
|
/* 0x0 - 0x3F : Kernel Level HMC routine */
|
|
#define HMC_halt 0x00
|
|
#define HMC_rdio64 0x01
|
|
#define HMC_rdio32 0x02
|
|
#define HMC_cpuid 0x03
|
|
#define HMC_sleepen 0x05
|
|
#define HMC_rdksp 0x06
|
|
#define HMC_wrasid 0x08
|
|
#define HMC_rdktp 0x09
|
|
#define HMC_wrktp 0x0A
|
|
#define HMC_rdptbr 0x0B
|
|
#define HMC_wrptbr 0x0C
|
|
#define HMC_rdhtctl 0x0D
|
|
#define HMC_wrksp 0x0E
|
|
#define HMC_mtinten 0x0F
|
|
#define HMC_load_mm 0x11
|
|
#define HMC_tbisasid 0x14
|
|
#define HMC_tbivpn 0x19
|
|
#define HMC_ret 0x1A
|
|
#define HMC_wrvpcr 0x29
|
|
#define HMC_wrfen 0x2B
|
|
#define HMC_sflush 0x2F
|
|
#define HMC_entervm 0x31
|
|
#define HMC_hcall 0x32
|
|
#define HMC_tbi 0x33
|
|
#define HMC_wrent 0x34
|
|
#define HMC_swpipl 0x35
|
|
#define HMC_rdps 0x36
|
|
#define HMC_wrkgp 0x37
|
|
#define HMC_wrusp 0x38
|
|
#define HMC_rvpcr 0x39
|
|
#define HMC_rdusp 0x3A
|
|
#define HMC_wrtimer 0x3B
|
|
#define HMC_whami 0x3C
|
|
#define HMC_retsys 0x3D
|
|
#define HMC_sendii 0x3E
|
|
#define HMC_rti 0x3F
|
|
|
|
|
|
/* 0x80 - 0xBF : User Level HMC routine */
|
|
#include <uapi/asm/hmcall.h>
|
|
|
|
/* Following will be deprecated from user level invocation */
|
|
#define HMC_rwreg 0x87
|
|
#define HMC_sz_uflush 0xA8
|
|
#define HMC_longtime 0xB1
|
|
|
|
#ifdef __KERNEL__
|
|
#ifndef __ASSEMBLY__
|
|
|
|
#include <linux/init.h>
|
|
extern void __init fixup_hmcall(void);
|
|
|
|
extern void halt(void) __noreturn;
|
|
|
|
#define __CALL_HMC_VOID(NAME) \
|
|
static inline void NAME(void) \
|
|
{ \
|
|
__asm__ __volatile__( \
|
|
"sys_call %0 " : : "i" (HMC_ ## NAME)); \
|
|
}
|
|
|
|
#define __CALL_HMC_R0(NAME, TYPE) \
|
|
static inline TYPE NAME(void) \
|
|
{ \
|
|
register TYPE __r0 __asm__("$0"); \
|
|
__asm__ __volatile__( \
|
|
"sys_call %1 # " #NAME \
|
|
: "=r" (__r0) \
|
|
: "i" (HMC_ ## NAME) \
|
|
: "$1", "$16", "$22", "$23", "$24", "$25"); \
|
|
return __r0; \
|
|
}
|
|
|
|
#define __CALL_HMC_W1(NAME, TYPE0) \
|
|
static inline void NAME(TYPE0 arg0) \
|
|
{ \
|
|
register TYPE0 __r16 __asm__("$16") = arg0; \
|
|
__asm__ __volatile__( \
|
|
"sys_call %1 # "#NAME \
|
|
: "=r"(__r16) \
|
|
: "i"(HMC_ ## NAME), "0"(__r16) \
|
|
: "$1", "$22", "$23", "$24", "$25"); \
|
|
}
|
|
|
|
#define __CALL_HMC_W2(NAME, TYPE0, TYPE1) \
|
|
static inline void NAME(TYPE0 arg0, TYPE1 arg1) \
|
|
{ \
|
|
register TYPE0 __r16 __asm__("$16") = arg0; \
|
|
register TYPE1 __r17 __asm__("$17") = arg1; \
|
|
__asm__ __volatile__( \
|
|
"sys_call %2 # "#NAME \
|
|
: "=r"(__r16), "=r"(__r17) \
|
|
: "i"(HMC_ ## NAME), "0"(__r16), "1"(__r17) \
|
|
: "$1", "$22", "$23", "$24", "$25"); \
|
|
}
|
|
|
|
#define __CALL_HMC_RW1(NAME, RTYPE, TYPE0) \
|
|
static inline RTYPE NAME(TYPE0 arg0) \
|
|
{ \
|
|
register RTYPE __r0 __asm__("$0"); \
|
|
register TYPE0 __r16 __asm__("$16") = arg0; \
|
|
__asm__ __volatile__( \
|
|
"sys_call %2 # "#NAME \
|
|
: "=r"(__r16), "=r"(__r0) \
|
|
: "i"(HMC_ ## NAME), "0"(__r16) \
|
|
: "$1", "$22", "$23", "$24", "$25"); \
|
|
return __r0; \
|
|
}
|
|
|
|
#define __CALL_HMC_RW2(NAME, RTYPE, TYPE0, TYPE1) \
|
|
static inline RTYPE NAME(TYPE0 arg0, TYPE1 arg1) \
|
|
{ \
|
|
register RTYPE __r0 __asm__("$0"); \
|
|
register TYPE0 __r16 __asm__("$16") = arg0; \
|
|
register TYPE1 __r17 __asm__("$17") = arg1; \
|
|
__asm__ __volatile__( \
|
|
"sys_call %3 # "#NAME \
|
|
: "=r"(__r16), "=r"(__r17), "=r"(__r0) \
|
|
: "i"(HMC_ ## NAME), "0"(__r16), "1"(__r17) \
|
|
: "$1", "$22", "$23", "$24", "$25"); \
|
|
return __r0; \
|
|
}
|
|
|
|
#define __CALL_HMC_RW3(NAME, RTYPE, TYPE0, TYPE1, TYPE2) \
|
|
static inline RTYPE NAME(TYPE0 arg0, TYPE1 arg1, TYPE2 arg2) \
|
|
{ \
|
|
register RTYPE __r0 __asm__("$0"); \
|
|
register TYPE0 __r16 __asm__("$16") = arg0; \
|
|
register TYPE1 __r17 __asm__("$17") = arg1; \
|
|
register TYPE2 __r18 __asm__("$18") = arg2; \
|
|
__asm__ __volatile__( \
|
|
"sys_call %4 # "#NAME \
|
|
: "=r"(__r16), "=r"(__r17), "=r"(__r18), "=r"(__r0) \
|
|
: "i"(HMC_ ## NAME), "0"(__r16), "1"(__r17), "2"(__r18) \
|
|
: "$1", "$22", "$23", "$24", "$25"); \
|
|
return __r0; \
|
|
}
|
|
|
|
|
|
__CALL_HMC_VOID(imb);
|
|
__CALL_HMC_VOID(sflush);
|
|
__CALL_HMC_VOID(wrfen);
|
|
#define fpu_enable() wrfen()
|
|
|
|
__CALL_HMC_VOID(sleepen);
|
|
__CALL_HMC_VOID(mtinten);
|
|
|
|
__CALL_HMC_VOID(rdktp);
|
|
#define restore_ktp() rdktp()
|
|
__CALL_HMC_VOID(wrktp);
|
|
#define save_ktp() wrktp()
|
|
|
|
__CALL_HMC_R0(rdps, unsigned long);
|
|
|
|
__CALL_HMC_R0(rdusp, unsigned long);
|
|
__CALL_HMC_W1(wrusp, unsigned long);
|
|
|
|
__CALL_HMC_R0(rdksp, unsigned long);
|
|
__CALL_HMC_W1(wrksp, unsigned long);
|
|
__CALL_HMC_R0(rdhtctl, unsigned long);
|
|
|
|
/*
|
|
* Load a mm context. This is needed when we change the page
|
|
* table pointer(CSR:PTBR) or when we update the ASID.
|
|
* load_mm(asid, ptbr)
|
|
*
|
|
*/
|
|
__CALL_HMC_W2(load_mm, unsigned long, unsigned long);
|
|
|
|
__CALL_HMC_W1(wrasid, unsigned long);
|
|
__CALL_HMC_R0(rdptbr, unsigned long);
|
|
__CALL_HMC_W1(wrptbr, unsigned long);
|
|
|
|
__CALL_HMC_RW1(swpipl, unsigned long, unsigned long);
|
|
__CALL_HMC_R0(whami, unsigned long);
|
|
__CALL_HMC_RW1(rdio64, unsigned long, unsigned long);
|
|
__CALL_HMC_RW1(rdio32, unsigned int, unsigned long);
|
|
__CALL_HMC_W2(wrent, void*, unsigned long);
|
|
__CALL_HMC_W2(tbisasid, unsigned long, unsigned long);
|
|
__CALL_HMC_W1(wrkgp, unsigned long);
|
|
__CALL_HMC_RW2(wrperfmon, unsigned long, unsigned long, unsigned long);
|
|
__CALL_HMC_RW3(sendii, unsigned long, unsigned long, unsigned long, unsigned long);
|
|
__CALL_HMC_W1(wrtimer, unsigned long);
|
|
__CALL_HMC_RW3(tbivpn, unsigned long, unsigned long, unsigned long, unsigned long);
|
|
__CALL_HMC_RW2(cpuid, unsigned long, unsigned long, unsigned long);
|
|
|
|
__CALL_HMC_W1(wrtp, unsigned long);
|
|
/*
|
|
* TB routines..
|
|
*/
|
|
#define __tbi(nr, arg, arg1...) \
|
|
({ \
|
|
register unsigned long __r16 __asm__("$16") = (nr); \
|
|
register unsigned long __r17 __asm__("$17"); arg; \
|
|
__asm__ __volatile__( \
|
|
"sys_call %3 #__tbi" \
|
|
: "=r" (__r16), "=r" (__r17) \
|
|
: "0" (__r16), "i" (HMC_tbi), ##arg1 \
|
|
: "$0", "$1", "$22", "$23", "$24", "$25"); \
|
|
})
|
|
|
|
#define tbi(x, y) __tbi(x, __r17 = (y), "1" (__r17))
|
|
|
|
/* Invalidate all TLB, only used by hypervisor */
|
|
#define tbia() __tbi(-2, /* no second argument */)
|
|
|
|
/* Invalidate TLB for all processes with currnet VPN */
|
|
#define tbivp() __tbi(-1, /* no second argument */)
|
|
|
|
/* Invalidate all TLB with current VPN */
|
|
#define tbiv() __tbi(0, /* no second argument */)
|
|
|
|
/* Invalidate ITLB of addr with current UPN and VPN */
|
|
#define tbisi(addr) __tbi(1, __r17 = (addr), "1" (__r17))
|
|
|
|
/* Invalidate DTLB of addr with current UPN and VPN */
|
|
#define tbisd(addr) __tbi(2, __r17 = (addr), "1" (__r17))
|
|
|
|
/* Invalidate TLB of addr with current UPN and VPN */
|
|
#define tbis(addr) __tbi(3, __r17 = (addr), "1" (__r17))
|
|
|
|
/* Invalidate all user TLB with current UPN and VPN */
|
|
#define tbiu() __tbi(4, /* no second argument */)
|
|
|
|
#endif /* !__ASSEMBLY__ */
|
|
#endif /* __KERNEL__ */
|
|
|
|
#endif /* _ASM_SW64_HMCALL_H */
|