246 lines
7.3 KiB
C
246 lines
7.3 KiB
C
/* linux/include/asm-e2k/traps.h, v 1.0 03/07/2001.
|
|
*
|
|
* Copyright (C) 2001 MCST
|
|
*
|
|
* Defenition of traps handling routines.
|
|
*/
|
|
|
|
#ifndef _E2K_TRAPS_H
|
|
#define _E2K_TRAPS_H
|
|
|
|
#include <linux/interrupt.h>
|
|
#include <asm/ptrace.h>
|
|
#include <asm/trap_def.h>
|
|
|
|
typedef void (*exc_function)(struct pt_regs *regs);
|
|
extern const exc_function exc_tbl[];
|
|
extern const char *exc_tbl_name[];
|
|
|
|
#define S_SIG(regs, signo, trapno, code) \
|
|
do { \
|
|
int nr_TIRs; \
|
|
e2k_tir_hi_t tir_hi; \
|
|
struct trap_pt_regs *trap = (regs)->trap; \
|
|
void __user *addr; \
|
|
\
|
|
if (trap) { \
|
|
AW(tir_hi) = trap->TIR_hi; \
|
|
nr_TIRs = GET_NR_TIRS(AW(tir_hi)); \
|
|
addr = (void __user *) (trap->TIRs[nr_TIRs].TIR_lo.TIR_lo_ip); \
|
|
} else { \
|
|
addr = 0; \
|
|
} \
|
|
\
|
|
force_sig_fault(signo, code, addr, trapno); \
|
|
} while (0)
|
|
|
|
extern int pf_on_page_boundary(unsigned long address, tc_cond_t cond);
|
|
extern bool is_spurious_qp_store(bool store, unsigned long address,
|
|
int fmt, tc_mask_t mask, unsigned long *pf_address);
|
|
extern void parse_TIR_registers(struct pt_regs *regs, u64 exceptions);
|
|
extern void do_aau_fault(int aa_field, struct pt_regs *regs);
|
|
extern int handle_proc_stack_bounds(struct e2k_stacks *stacks,
|
|
struct trap_pt_regs *trap);
|
|
extern int handle_chain_stack_bounds(struct e2k_stacks *stacks,
|
|
struct trap_pt_regs *trap);
|
|
extern int do_page_fault(struct pt_regs *const regs, e2k_addr_t address,
|
|
tc_cond_t condition, tc_mask_t mask, const int instr_page);
|
|
#ifdef CONFIG_KVM_ASYNC_PF
|
|
extern void do_pv_apf_wake(struct pt_regs *regs);
|
|
#endif /* */
|
|
extern void do_trap_cellar(struct pt_regs *regs, int only_system_tc);
|
|
|
|
extern irqreturn_t native_do_interrupt(struct pt_regs *regs);
|
|
extern void do_nm_interrupt(struct pt_regs *regs);
|
|
extern void native_instr_page_fault(struct pt_regs *regs, tc_fault_type_t ftype,
|
|
const int async_instr);
|
|
|
|
extern void do_trap_cellar(struct pt_regs *regs, int only_system_tc);
|
|
|
|
extern int constrict_user_data_stack(struct pt_regs *regs, unsigned long incr);
|
|
extern int expand_user_data_stack(struct pt_regs *regs, unsigned long incr);
|
|
extern void do_notify_resume(struct pt_regs *regs);
|
|
|
|
extern void coredump_in_future(void);
|
|
|
|
enum getsp_action {
|
|
GETSP_OP_FAIL = 1,
|
|
GETSP_OP_SIGSEGV,
|
|
GETSP_OP_INCREMENT,
|
|
GETSP_OP_DECREMENT
|
|
};
|
|
extern enum getsp_action parse_getsp_operation(const struct pt_regs *regs,
|
|
int *incr, void __user **fault_addr);
|
|
|
|
static inline unsigned int user_trap_init(void)
|
|
{
|
|
/* Enable system calls for user's processes. */
|
|
unsigned int linux_osem = 0;
|
|
|
|
/* Enable deprecated generic ttable2 syscall entry. */
|
|
linux_osem = 1 << LINUX_SYSCALL_TRAPNUM_OLD;
|
|
|
|
/* Enable ttable1 syscall entry - 32-bit syscalls only */
|
|
linux_osem |= 1 << LINUX_SYSCALL32_TRAPNUM;
|
|
/* Enable ttable3 syscall entry - 64-bit syscalls only */
|
|
linux_osem |= 1 << LINUX_SYSCALL64_TRAPNUM;
|
|
|
|
/* Enable fast syscalls entries. */
|
|
linux_osem |= 1 << LINUX_FAST_SYSCALL32_TRAPNUM;
|
|
linux_osem |= 1 << LINUX_FAST_SYSCALL64_TRAPNUM;
|
|
linux_osem |= 1 << LINUX_FAST_SYSCALL128_TRAPNUM;
|
|
|
|
#ifdef CONFIG_PROTECTED_MODE
|
|
linux_osem |= (1 << PMODE_SYSCALL_TRAPNUM);
|
|
linux_osem |= (1 << PMODE_NEW_SYSCALL_TRAPNUM);
|
|
#endif /* CONFIG_PROTECTED_MODE */
|
|
|
|
return linux_osem;
|
|
}
|
|
|
|
static inline unsigned int guest_trap_init(void)
|
|
{
|
|
/* Enable system calls for user's processes. */
|
|
unsigned int linux_osem = user_trap_init();
|
|
|
|
#ifdef CONFIG_KVM_HOST_MODE
|
|
linux_osem |= HYPERCALLS_TRAPS_MASK;
|
|
#endif
|
|
|
|
return linux_osem;
|
|
}
|
|
|
|
static inline unsigned int user_hcall_init(void)
|
|
{
|
|
unsigned int linux_hcem = 0;
|
|
|
|
linux_hcem = 1 << LINUX_HCALL_GENERIC_TRAPNUM;
|
|
linux_hcem |= 1 << LINUX_HCALL_LIGHT_TRAPNUM;
|
|
|
|
return linux_hcem;
|
|
}
|
|
|
|
extern char __hypercalls_begin[];
|
|
static inline void kernel_trap_mask_init(void)
|
|
{
|
|
WRITE_OSEM_REG(user_trap_init());
|
|
#ifdef CONFIG_KVM_HOST_MODE
|
|
if (!paravirt_enabled()) {
|
|
machine.rwd(E2K_REG_HCEM, user_hcall_init());
|
|
machine.rwd(E2K_REG_HCEB, (unsigned long) __hypercalls_begin);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
static inline int
|
|
native_host_apply_psp_delta_to_signal_stack(unsigned long base,
|
|
unsigned long size, unsigned long start,
|
|
unsigned long end, unsigned long delta)
|
|
{
|
|
/* native & host kernel cannot be paravirtualized guest */
|
|
return 0;
|
|
}
|
|
|
|
static inline int
|
|
native_host_apply_pcsp_delta_to_signal_stack(unsigned long base,
|
|
unsigned long size, unsigned long start,
|
|
unsigned long end, unsigned long delta)
|
|
{
|
|
/* native & host kernel cannot be paravirtualized guest */
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* MMIO page fault cannot occur on native or host mode,
|
|
* so ignore such traps
|
|
*/
|
|
static inline unsigned long
|
|
native_mmio_page_fault(struct pt_regs *regs, trap_cellar_t *tcellar)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
#ifdef CONFIG_VIRTUALIZATION
|
|
extern void native_sysrq_showstate_interrupt(struct pt_regs *regs);
|
|
static inline void
|
|
native_init_guest_system_handlers_table(void)
|
|
{
|
|
if (paravirt_enabled()) {
|
|
/* It is native guest */
|
|
setup_APIC_vector_handler(SYSRQ_SHOWSTATE_EPIC_VECTOR,
|
|
native_sysrq_showstate_interrupt, 1,
|
|
"native_sysrq_showstate_interrupt");
|
|
}
|
|
}
|
|
# ifndef CONFIG_KVM
|
|
# error "Undefined guest virtualization type"
|
|
# endif /* CONFIG_KVM */
|
|
#else /* ! CONFIG_VIRTUALIZATION */
|
|
/* it is native host kernel without virtualization support */
|
|
static inline void
|
|
native_init_guest_system_handlers_table(void)
|
|
{
|
|
/* Nothing to do */
|
|
}
|
|
# define SET_RUNSTATE_IN_USER_TRAP()
|
|
# define SET_RUNSTATE_OUT_USER_TRAP()
|
|
# define SET_RUNSTATE_IN_KERNEL_TRAP(cur_runstate)
|
|
# define SET_RUNSTATE_OUT_KERNEL_TRAP(cur_runstate)
|
|
#endif /* CONFIG_VIRTUALIZATION */
|
|
|
|
#if defined(CONFIG_KVM_GUEST_KERNEL)
|
|
/* It is pure guest kernel (not paravirtualized) */
|
|
#include <asm/kvm/guest/traps.h>
|
|
#elif defined(CONFIG_PARAVIRT_GUEST)
|
|
/* It is paravirtualized host and guest kernel */
|
|
#include <asm/paravirt/traps.h>
|
|
#else /* ! CONFIG_PARAVIRT_GUEST && ! CONFIG_KVM_GUEST_KERNEL */
|
|
/* it is native kernel without any virtualization */
|
|
/* or it is native host kernel with virtualization support */
|
|
|
|
#define TIR0_clear_false_exceptions(TIR_hi, nr_TIRs) \
|
|
native_TIR0_clear_false_exceptions(TIR_hi, nr_TIRs)
|
|
|
|
static inline void
|
|
handle_interrupt(struct pt_regs *regs)
|
|
{
|
|
native_do_interrupt(regs);
|
|
}
|
|
|
|
extern int apply_psp_delta_to_signal_stack(unsigned long base,
|
|
unsigned long size, unsigned long start, unsigned long end,
|
|
unsigned long delta);
|
|
extern int apply_pcsp_delta_to_signal_stack(unsigned long base,
|
|
unsigned long size, unsigned long start, unsigned long end,
|
|
unsigned long delta);
|
|
|
|
static inline int host_apply_psp_delta_to_signal_stack(unsigned long base,
|
|
unsigned long size, unsigned long start,
|
|
unsigned long end, unsigned long delta)
|
|
{
|
|
return native_host_apply_psp_delta_to_signal_stack(base, size,
|
|
start, end, delta);
|
|
}
|
|
|
|
static inline int host_apply_pcsp_delta_to_signal_stack(unsigned long base,
|
|
unsigned long size, unsigned long start,
|
|
unsigned long end, unsigned long delta)
|
|
{
|
|
return native_host_apply_pcsp_delta_to_signal_stack(base, size,
|
|
start, end, delta);
|
|
}
|
|
|
|
static inline unsigned long
|
|
mmio_page_fault(struct pt_regs *regs, trap_cellar_t *tcellar)
|
|
{
|
|
return native_mmio_page_fault(regs, tcellar);
|
|
}
|
|
static inline void
|
|
init_guest_system_handlers_table(void)
|
|
{
|
|
native_init_guest_system_handlers_table();
|
|
}
|
|
#endif /* ! CONFIG_PARAVIRT_GUEST && ! CONFIG_KVM_GUEST_KERNEL */
|
|
|
|
#endif /* _E2K_TRAPS_H */
|