linux-headers/arch/e2k/include/asm/system.h

672 lines
22 KiB
C

/*
* asm-e2k/system.h
*/
#ifndef _E2K_SYSTEM_H_
#define _E2K_SYSTEM_H_
#ifndef __ASSEMBLY__
#include <linux/kernel.h>
#endif /* !(__ASSEMBLY__) */
#include <linux/irqflags.h>
#include <asm/atomic.h>
#include <asm/mas.h>
#include <asm/cpu_regs.h>
#include <asm/e2k_api.h>
#include <asm/ptrace.h>
#include <asm/trap_def.h>
#include <asm/unistd.h>
#define set_mb(var, value) do { var = value; smp_mb(); } while (0)
#define set_wmb(var, value) do { var = value; smp_wmb(); } while (0)
#define NATIVE_PSR_SET_LAST_WISH() \
do { \
unsigned long __psr = NATIVE_NV_READ_PSR_REG_VALUE(); \
__psr |= PSR_LW; \
NATIVE_WRITE_PSR_REG_VALUE(__psr); \
} while (0)
#define PSR_SET_LAST_WISH() \
do { \
unsigned long __psr = READ_PSR_REG_VALUE(); \
__psr |= PSR_LW; \
WRITE_PSR_REG_VALUE(__psr); \
} while (0)
#define boot_native_set_sge() \
({ \
NATIVE_WRITE_PSR_REG_VALUE( \
NATIVE_NV_READ_PSR_REG_VALUE() | PSR_SGE); \
})
static inline bool native_sge_is_set(void)
{
e2k_psr_t psr = NATIVE_NV_READ_PSR_REG();
return psr.PSR_sge;
}
#ifdef CONFIG_E2K_PROFILING
#define boot_smp_processor_id_() \
(((e2k_addr_t)current_thread_info() >= TASK_SIZE) ? \
smp_processor_id() \
: \
((long)READ_CURRENT_REG_VALUE()))
typedef struct {
// FIRST ELEMENT
long max_disable_interrupt; // max #ticks of disable_interrupt
long sum_disable_interrupt; // all #ticks of disable_interrupt
long number_interrupt; // number of interrupts
long number_irqs; // number of closed irq
long number_system_call; // number of system_call
long max_disable_interrupt_after_dump; // max #ticks of disable_interrupt
// after last read or write profile file
long interrupts[exc_max_num]; // interrupt table
long interrupts_time[exc_max_num]; // interrupt time (in ticks)
long max_interrupts_time[exc_max_num]; // max interrupt time (in ticks)
long syscall[NR_syscalls]; // syscall table
long syscall_time[NR_syscalls]; // syscall time (in ticks)
long max_syscall_time[NR_syscalls]; // max syscall time
long clk; // time of interrupt's begining
// NR_VECTORS 256
long max_do_irq_time[256]; // max DO_IRQ's time
long do_irq[256]; // number of DO_IRQ
long do_irq_time[256]; // time of DO_IRQ
long clk_of_do_irq; // time of DO_IRQ's begining
long last_element;
} disable_interrupt_t ;
extern unsigned long get_cmos_time(void);
extern disable_interrupt_t disable_interrupt[NR_CPUS];
#define read_ticks(n) (n = NATIVE_READ_CLKR_REG_VALUE())
#define add_info_interrupt(n, ticks) \
({ long t; int cpu; \
t = NATIVE_READ_CLKR_REG_VALUE() - ticks; \
cpu = boot_smp_processor_id_(); \
disable_interrupt[cpu].interrupts[n]++; \
disable_interrupt[cpu].interrupts_time[n] += t; \
if (t > disable_interrupt[cpu].max_interrupts_time[n]) { \
disable_interrupt[cpu].max_interrupts_time[n] = t; \
} \
})
#define add_info_syscall(n, ticks) \
({ long t; int cpu; \
cpu = boot_smp_processor_id(); \
t = NATIVE_READ_CLKR_REG_VALUE() - ticks; \
disable_interrupt[cpu].syscall[n]++; \
disable_interrupt[cpu].syscall_time[n] += t; \
if (t > disable_interrupt[cpu].max_syscall_time[n]) { \
disable_interrupt[cpu].max_syscall_time[n] = t; \
} \
})
typedef struct {
long max_time;
long full_time;
long begin_time;
long number;
long beg_ip;
long beg_parent_ip;
long end_ip;
long end_parent_ip;
long max_beg_ip;
long max_beg_parent_ip;
long max_end_ip;
long max_begin_time;
long max_end_parent_ip;
} time_info_t;
/*
* For adding new element you need do following things:
* - add new "time_info_t" element after last one
* - add name of your elemen in system_info_name (file e2k_sysworks.c)
* - create two new define similar below:
* #define info_save_mmu_reg(tick) \
* store_max_time_in_system_info(tick,max_mmu_reg)
* #define info_save_mmu_reg(tick) - null for not CONFIG_E2K_PROFILING
* - used your new define for merging what you want
*/
typedef struct {
time_info_t max_disabled_interrupt; // max time of disabled inerrupts
time_info_t max_stack_reg; // max time of saving of stack_registers
time_info_t max_tir_reg; // max time for storing TIR
time_info_t max_mmu_reg; // max time for storing mmu registers
time_info_t max_restore_stack_reg; // max time for restoring of stack_registers
time_info_t max_restoring_reg; // max time for restoring all registers
time_info_t max_restore_mmu_reg; // max time for restoring mmu registers
time_info_t max_cpu_idle; // max time for cpu_idle
} system_info_t ;
extern char* system_info_name[];
extern system_info_t system_info[NR_CPUS];
extern int enable_collect_interrupt_ticks;
#define collect_disable_interrupt_ticks() \
({ int cpu; \
cpu = boot_smp_processor_id_(); \
if (system_info[cpu].max_disabled_interrupt.begin_time >0){ \
store_max_time_in_system_info( \
system_info[cpu].max_disabled_interrupt.begin_time, \
max_disabled_interrupt); \
system_info[cpu].max_disabled_interrupt.begin_time = 0; \
} \
})
#define mark_disable_interrupt_ticks() \
store_begin_ip_in_system_info(max_disabled_interrupt)
#define store_do_irq_ticks() \
({ int cpu = boot_smp_processor_id_(); \
disable_interrupt[cpu].clk_of_do_irq = NATIVE_READ_CLKR_REG_VALUE(); \
})
#define define_time_of_do_irq(N) \
({ long t; int cpu; \
cpu = boot_smp_processor_id_(); \
t = NATIVE_READ_CLKR_REG_VALUE() - \
disable_interrupt[cpu].clk_of_do_irq; \
disable_interrupt[cpu].do_irq_time[N] += t; \
disable_interrupt[cpu].do_irq[N]++; \
if (disable_interrupt[cpu].max_do_irq_time[N] < t) { \
disable_interrupt[cpu].max_do_irq_time[N] = t; \
} \
})
#define info_save_stack_reg(tick) \
store_max_time_in_system_info(tick,max_stack_reg)
#define info_restore_stack_reg(tick) \
store_max_time_in_system_info(tick,max_restore_stack_reg)
#define info_save_mmu_reg(tick) \
store_max_time_in_system_info(tick,max_mmu_reg)
#define info_restore_mmu_reg(tick) \
store_max_time_in_system_info(tick,max_restore_mmu_reg)
#define info_save_tir_reg(tick) \
store_max_time_in_system_info(tick,max_tir_reg)
#define info_restore_all_reg(tick) \
store_max_time_in_system_info(tick,max_restoring_reg); \
#define cpu_idle_time() \
store_begin_time_in_system_info(max_cpu_idle)
#define calculate_cpu_idle_time() \
calculate_max_time_in_system_info(max_cpu_idle)
#define store_begin_time_in_system_info(FIELD) \
({ long t; int cpu; \
register e2k_cr0_hi_t cr0_hi; \
if (enable_collect_interrupt_ticks) { \
cpu = boot_smp_processor_id_(); \
t = NATIVE_READ_CLKR_REG_VALUE(); \
AS_WORD(cr0_hi) = NATIVE_NV_READ_CR0_HI_REG_VALUE(); \
system_info[cpu].FIELD.begin_time = tick; \
system_info[cpu].FIELD.beg_ip = NATIVE_READ_IP_REG_VALUE(); \
system_info[cpu].FIELD.beg_parent_ip = \
(AS_STRUCT(cr0_hi)).ip<<3; \
} \
})
#define store_begin_ip_in_system_info(FIELD) \
({ \
int cpu; \
register e2k_cr0_hi_t cr0_hi; \
cpu = boot_smp_processor_id_(); \
disable_interrupt[cpu].clk = NATIVE_READ_CLKR_REG_VALUE(); \
cr0_hi = NATIVE_NV_READ_CR0_HI_REG_VALUE(); \
system_info[cpu].FIELD.beg_ip = NATIVE_READ_IP_REG_VALUE(); \
system_info[cpu].FIELD.beg_parent_ip = \
(AS_STRUCT(cr0_hi)).ip<<3; \
})
#define store_begin_time_ip_in_system_info(cpu, tick, FIELD) \
({ \
register e2k_cr0_hi_t cr0_hi; \
if (enable_collect_interrupt_ticks) { \
system_info[cpu].FIELD.begin_time = tick; \
cr0_hi = NATIVE_NV_READ_CR0_HI_REG_VALUE(); \
system_info[cpu].FIELD.beg_ip = NATIVE_READ_IP_REG_VALUE(); \
system_info[cpu].FIELD.beg_parent_ip = \
(AS_STRUCT(cr0_hi)).ip<<3; \
} \
})
#define store_end_ip_in_system_info(mutex, FIELD) \
({ \
int cpu; \
register e2k_cr0_hi_t cr0_hi; \
cpu = boot_smp_processor_id_(); \
cr0_hi = NATIVE_NV_READ_CR0_HI_REG_VALUE(); \
system_info[cpu].FIELD.beg_ip = mutex->ip; \
system_info[cpu].FIELD.beg_parent_ip = mutex->caller; \
system_info[cpu].FIELD.end_ip = NATIVE_READ_IP_REG_VALUE(); \
system_info[cpu].FIELD.end_parent_ip = \
(AS_STRUCT(cr0_hi)).ip<<3; \
})
#define calculate_max_time_in_system_info(FIELD) \
({ \
long t; int cpu; \
register e2k_cr0_hi_t cr0_hi; \
cpu = boot_smp_processor_id_(); \
if (enable_collect_interrupt_ticks) { \
t = NATIVE_READ_CLKR_REG_VALUE()-system_info[cpu]. \
FIELD.begin_time; \
system_info[cpu].FIELD.number++; \
system_info[cpu].FIELD.full_time += t; \
if (system_info[cpu].FIELD.max_time < t) { \
system_info[cpu].FIELD.max_time = t; \
system_info[cpu].FIELD.max_beg_ip = \
system_info[cpu].FIELD.beg_ip; \
system_info[cpu].FIELD.max_beg_parent_ip = \
system_info[cpu].FIELD.beg_parent_ip; \
system_info[cpu].FIELD.max_end_ip = \
NATIVE_READ_IP_REG_VALUE(); \
cr0_hi = NATIVE_NV_READ_CR0_HI_REG_VALUE(); \
system_info[cpu].FIELD.max_end_parent_ip = \
(AS_STRUCT(cr0_hi)).ip<<3; \
system_info[cpu].FIELD.max_begin_time = \
system_info[cpu].FIELD.begin_time; \
} \
system_info[cpu].FIELD.begin_time = 0; \
} \
})
extern long TIME;
#define store_max_time_in_system_info(tick, FIELD) \
({ \
long t; int cpu; \
register e2k_cr0_hi_t cr0_hi; \
cpu = boot_smp_processor_id_(); \
t = NATIVE_READ_CLKR_REG_VALUE()-tick; \
if (enable_collect_interrupt_ticks) { \
system_info[cpu].FIELD.number++; \
system_info[cpu].FIELD.full_time += t; \
if (system_info[cpu].FIELD.max_time < t) { \
system_info[cpu].FIELD.max_time = t; \
system_info[cpu].FIELD.max_beg_ip = \
system_info[cpu].FIELD.beg_ip; \
system_info[cpu].FIELD.max_beg_parent_ip = \
system_info[cpu].FIELD.beg_parent_ip; \
system_info[cpu].FIELD.max_end_ip = \
NATIVE_READ_IP_REG_VALUE(); \
cr0_hi = NATIVE_NV_READ_CR0_HI_REG_VALUE(); \
system_info[cpu].FIELD.max_end_parent_ip = \
(AS_STRUCT(cr0_hi)).ip<<3; \
system_info[cpu].FIELD.max_begin_time = \
system_info[cpu].FIELD.begin_time; \
} \
system_info[cpu].FIELD.begin_time = 0; \
} \
})
#define UPSR_RESTORE(__src_upsr) \
({ \
unsigned long upsr1 = READ_UPSR_REG_VALUE(); \
int _cond_ = (upsr1 & UPSR_IE) != ((__src_upsr) & UPSR_IE); \
if (enable_collect_interrupt_ticks && _cond_) { \
if (__src_upsr & UPSR_IE) { \
collect_disable_interrupt_ticks(); \
} else { \
mark_disable_interrupt_ticks(); \
} \
} \
WRITE_UPSR_IRQ_BARRIER(__src_upsr); \
})
#define condition_mark_disable_interrupt_ticks(_cond_) \
({ \
if (enable_collect_interrupt_ticks) { \
mark_disable_interrupt_ticks(); \
} \
})
#define condition_collect_disable_interrupt_ticks(_cond_) \
({ \
if (enable_collect_interrupt_ticks && _cond_) { \
collect_disable_interrupt_ticks(); \
} \
})
# else /* !CONFIG_E2K_PROFILING */
#define store_max_time_in_system_info(tick,FIELD)
#define calculate_max_time_in_system_info(FIELD)
#define store_begin_time_in_system_info(FIELD)
#define store_begin_ip_in_system_info(FIELD)
#define info_save_tir_reg(tick)
#define info_restore_all_reg(tick)
#define info_save_stack_reg(tick)
#define info_restore_stack_reg(tick)
#define info_save_mmu_reg(tick)
#define info_restore_mmu_reg(tick)
#define cpu_idle_time()
#define calculate_cpu_idle_time()
#define store_do_irq_ticks()
#define define_time_of_do_irq(N)
#define condition_collect_disable_interrupt_ticks(_cond_)
#define condition_mark_disable_interrupt_ticks(_cond_)
#define collect_disable_interrupt_ticks()
#define mark_disable_interrupt_ticks()
#define add_info_syscall(n, ticks)
#define add_info_interrupt(n, ticks)
#define read_ticks(n)
#define UPSR_RESTORE(__src_upsr) (WRITE_UPSR_IRQ_BARRIER(__src_upsr))
#endif /* CONFIG_E2K_PROFILING */
#define E2K_KERNEL_PSR_ENABLED ((e2k_psr_t) { { \
pm : 1, \
ie : 1, \
sge : 1, \
lw : 0, \
uie : 1, \
nmie : 1, \
unmie : 1, \
} })
#define E2K_KERNEL_PSR_DISABLED ((e2k_psr_t) { { \
pm : 1, \
ie : 0, \
sge : 1, \
lw : 0, \
uie : 0, \
nmie : 0, \
unmie : 0, \
} })
#define E2K_KERNEL_PSR_DIS_LWISH_EN ((e2k_psr_t) { { \
pm : 1, \
ie : 0, \
sge : 1, \
lw : 1, \
uie : 0, \
nmie : 0, \
unmie : 0, \
} })
#define E2K_KERNEL_PSR_LWISH_DIS ((e2k_psr_t) { { \
pm : 1, \
ie : 0, \
sge : 1, \
lw : 0, \
uie : 0, \
nmie : 0, \
unmie : 0, \
} })
#ifndef CONFIG_ACCESS_CONTROL
#define E2K_KERNEL_UPSR_ENABLED_ASM 0xa1
#define E2K_KERNEL_UPSR_DISABLED_ALL_ASM 0x01
#define E2K_KERNEL_UPSR_DISABLED ((e2k_upsr_t) { { \
fe : 1, \
se : 0, \
ac : 0, \
a20 : 0, \
ie : 0, \
nmie : 1 \
} })
#define E2K_KERNEL_UPSR_ENABLED ((e2k_upsr_t) { { \
fe : 1, \
se : 0, \
ac : 0, \
a20 : 0, \
ie : 1, \
nmie : 1 \
} })
#define E2K_KERNEL_UPSR_DISABLED_ALL ((e2k_upsr_t) { { \
fe : 1, \
se : 0, \
ac : 0, \
a20 : 0, \
ie : 0, \
nmie : 0 \
} })
#else
#define E2K_KERNEL_UPSR_ENABLED_ASM 0xa5
#define E2K_KERNEL_UPSR_DISABLED_ALL_ASM 0x05
#define E2K_KERNEL_UPSR_DISABLED ((e2k_upsr_t) { { \
fe : 1, \
se : 0, \
ac : 1, \
a20 : 0, \
ie : 0, \
nmie : 1 \
} })
#define E2K_KERNEL_UPSR_ENABLED ((e2k_upsr_t) { { \
fe : 1, \
se : 0, \
ac : 1, \
a20 : 0, \
ie : 1, \
nmie : 1 \
} })
#define E2K_KERNEL_UPSR_DISABLED_ALL ((e2k_upsr_t) { { \
fe : 1, \
se : 0, \
ac : 1, \
a20 : 0, \
ie : 0, \
nmie : 0 \
} })
#endif /* ! (CONFIG_ACCESS_CONTROL) */
#define E2K_KERNEL_INITIAL_UPSR E2K_KERNEL_UPSR_DISABLED
#define E2K_KERNEL_INITIAL_UPSR_WITH_DISABLED_NMI \
E2K_KERNEL_UPSR_DISABLED_ALL
#define E2K_USER_INITIAL_UPSR ((e2k_upsr_t) { { \
fe : 1, \
se : 0, \
ac : 0, \
di : 0, \
wp : 0, \
ie : 0, \
a20 : 0, \
nmie : 0 \
} })
#define E2K_USER_INITIAL_PSR ((e2k_psr_t) { { \
pm : 0, \
ie : 1, \
sge : 1, \
lw : 0, \
uie : 0, \
nmie : 1, \
unmie : 0 \
} })
#define PREFIX_INIT_KERNEL_UPSR_REG(PV_TYPE, irq_en, nmirq_dis) \
do { \
e2k_upsr_t upsr = E2K_KERNEL_UPSR_DISABLED; \
if (irq_en) \
AS(upsr).ie = 1; \
if (nmirq_dis) \
AS(upsr).nmie = 0; \
PV_TYPE##_WRITE_UPSR_REG(upsr); \
} while (0)
#define BOOT_PREFIX_INIT_KERNEL_UPSR_REG(PV_TYPE, irq_en, nmirq_dis) \
do { \
e2k_upsr_t upsr = E2K_KERNEL_UPSR_DISABLED; \
if (irq_en) \
AS(upsr).ie = 1; \
if (nmirq_dis) \
AS(upsr).nmie = 0; \
BOOT_##PV_TYPE##_WRITE_UPSR_REG(upsr); \
} while (0)
#define NATIVE_INIT_KERNEL_UPSR_REG(irq_en, nmirq_dis) \
PREFIX_INIT_KERNEL_UPSR_REG(NATIVE, irq_en, nmirq_dis)
#define BOOT_NATIVE_INIT_KERNEL_UPSR_REG(irq_en, nmirq_dis) \
BOOT_PREFIX_INIT_KERNEL_UPSR_REG(NATIVE, irq_en, nmirq_dis)
#define NATIVE_INIT_USER_UPSR_REG() \
NATIVE_WRITE_UPSR_REG(E2K_USER_INITIAL_UPSR)
#define INIT_USER_UPSR_REG() WRITE_UPSR_REG(E2K_USER_INITIAL_UPSR)
#define PREFIX_SET_KERNEL_UPSR(PV_TYPE) \
({ \
PV_TYPE##_INIT_KERNEL_UPSR_REG(false, false); \
PV_TYPE##_SWITCH_IRQ_TO_UPSR(); \
})
#define PREFIX_SET_KERNEL_UPSR_WITH_DISABLED_NMI(PV_TYPE) \
({ \
PV_TYPE##_INIT_KERNEL_UPSR_REG(false, true); \
PV_TYPE##_SWITCH_IRQ_TO_UPSR(); \
})
#define BOOT_PREFIX_SET_KERNEL_UPSR(PV_TYPE) \
({ \
BOOT_##PV_TYPE##_INIT_KERNEL_UPSR_REG(false, false); \
BOOT_##PV_TYPE##_SWITCH_IRQ_TO_UPSR(); \
})
#define NATIVE_SET_KERNEL_UPSR_WITH_DISABLED_NMI() \
PREFIX_SET_KERNEL_UPSR_WITH_DISABLED_NMI(NATIVE)
#define BOOT_NATIVE_SET_KERNEL_UPSR() \
BOOT_PREFIX_SET_KERNEL_UPSR(NATIVE)
/*
* UPSR should be saved and set to kernel initial state (where interrupts
* are disabled) independently of trap or interrupt occurred on user
* or kernel process.
* In user process case it is as above.
* In kernel process case:
* Kernel process can be interrupted (so UPSR enable interrupts)
* Hardware trap or system call operation disables interrupts mask
* in PSR and PSR becomes main register to control interrupts.
* Trap handler should switch interrupts control from PSR to UPSR
* previously it should set UPSR to initial state for kernel with disabled
* interrupts (so UPSR disable interrupts)
* If trap handler returns to trap point without UPSR restore, then
* interrupted kernel process will have UPSR with disabled interrupts.
* So UPSR should be saved and restored in any case
*
* Trap can occur on light hypercall, where switch of user data stack
* to kernel stack is not executed, so these traps handle as user traps
* (SBR < TASK_SIZE) Light hypercall already switch control from PSR to UPSR
* so it need save current UPSR state (enable/disable interrupts)
* to restore this state before return to trapped light hypercall.
* Interrupt control by UPSR will be restored from PSR saved into CR1_LO
*/
#define PREFIX_DO_SWITCH_TO_KERNEL_UPSR(PV_TYPE, pv_type, \
irq_en, nmirq_dis) \
({ \
PV_TYPE##_INIT_KERNEL_UPSR_REG(irq_en, nmirq_dis); \
PV_TYPE##_SWITCH_IRQ_TO_UPSR(); \
if (!irq_en) \
trace_hardirqs_off(); \
})
#define PREFIX_SWITCH_TO_KERNEL_UPSR(PV_TYPE, pv_type, \
upsr_reg, irq_en, nmirq_dis) \
({ \
PV_TYPE##_DO_SAVE_UPSR_REG((upsr_reg)); \
PREFIX_DO_SWITCH_TO_KERNEL_UPSR(PV_TYPE, pv_type, \
irq_en, nmirq_dis); \
})
#define BOOT_PREFIX_SWITCH_TO_KERNEL_UPSR(PV_TYPE, pv_type) \
({ \
unsigned long cur_upsr; \
BOOT_##PV_TYPE##_DO_SAVE_UPSR_REG((cur_upsr)); \
BOOT_##PV_TYPE##_INIT_KERNEL_UPSR_REG(false, false); \
BOOT_##PV_TYPE##_SWITCH_IRQ_TO_UPSR(false); \
})
/* Native version of macroses (all read/write from/to real registers) */
#define NATIVE_DO_SWITCH_TO_KERNEL_UPSR(irq_en, nmirq_dis) \
PREFIX_DO_SWITCH_TO_KERNEL_UPSR(NATIVE, native, \
irq_en, nmirq_dis)
#define NATIVE_SWITCH_TO_KERNEL_UPSR(upsr_reg, irq_en, nmirq_dis) \
PREFIX_SWITCH_TO_KERNEL_UPSR(NATIVE, native, \
upsr_reg, irq_en, nmirq_dis)
#define NATIVE_RETURN_TO_KERNEL_UPSR(upsr_reg) \
do { \
NATIVE_WRITE_PSR_IRQ_BARRIER(AW(E2K_KERNEL_PSR_DISABLED)); \
NATIVE_DO_RESTORE_UPSR_REG(upsr_reg); \
} while (false)
#define PREFIX_RETURN_TO_USER_UPSR(PV_TYPE, pv_type, upsr_reg, under_upsr) \
do { \
PV_TYPE##_WRITE_PSR_IRQ_BARRIER(AW(E2K_KERNEL_PSR_DISABLED)); \
PV_TYPE##_DO_RESTORE_UPSR_REG(upsr_reg); \
} while (false)
#define NATIVE_RETURN_TO_USER_UPSR(upsr_reg) \
PREFIX_RETURN_TO_USER_UPSR(NATIVE, native, upsr_reg, true)
#define NATIVE_RETURN_PSR_IRQ_TO_USER_UPSR(upsr_reg, lwish_en) \
do { \
if (lwish_en) { \
NATIVE_WRITE_PSR_IRQ_BARRIER(AW(E2K_KERNEL_PSR_DIS_LWISH_EN)); \
} else { \
NATIVE_WRITE_PSR_IRQ_BARRIER(AW(E2K_KERNEL_PSR_LWISH_DIS)); \
} \
NATIVE_DO_RESTORE_UPSR_REG(upsr_reg); \
} while (false)
#ifdef CONFIG_ACCESS_CONTROL
#define ACCESS_CONTROL_DISABLE_AND_SAVE(upsr_to_save) \
({ \
e2k_upsr_t upsr; \
upsr_to_save = read_UPSR_reg(); \
upsr = upsr_to_save; \
AS_STRUCT(upsr).ac = 0; \
write_UPSR_reg(upsr); \
})
#define ACCESS_CONTROL_RESTORE(upsr_to_restore) \
({ \
write_UPSR_reg(upsr_to_restore); \
})
#else /* !CONFIG_ACCESS_CONTROL */
#define ACCESS_CONTROL_DISABLE_AND_SAVE(upsr_to_save) do { } while (0)
#define ACCESS_CONTROL_RESTORE(upsr_to_restore) do { } while (0)
#endif /* CONFIG_ACCESS_CONTROL */
extern void * __e2k_read_kernel_return_address(int n);
/* If n == 0 we can read return address directly from cr0.hi */
#define __e2k_kernel_return_address(n) \
({ (n == 0) ? \
((void *) (NATIVE_NV_READ_CR0_HI_REG_VALUE() & ~7UL)) \
: \
__e2k_read_kernel_return_address(n); })
#ifndef CONFIG_CPU_HW_CLEAR_RF
typedef void (*clear_rf_t)(void);
extern const clear_rf_t clear_rf_fn[];
static __always_inline void clear_rf_kernel_except_current(u64 num_q)
{
clear_rf_fn[num_q]();
}
#endif
#define SWITCH_TO_KERNEL_UPSR(upsr_reg, irq_en, nmirq_dis) \
NATIVE_SWITCH_TO_KERNEL_UPSR(upsr_reg, irq_en, nmirq_dis)
#define RETURN_TO_USER_UPSR(upsr_reg) \
NATIVE_RETURN_TO_USER_UPSR(upsr_reg)
#if defined(CONFIG_PARAVIRT_GUEST)
#include <asm/paravirt/system.h>
#elif defined(CONFIG_KVM_GUEST_KERNEL)
#include <asm/kvm/guest/system.h>
#else /* native kernel */
#define INIT_KERNEL_UPSR_REG NATIVE_INIT_KERNEL_UPSR_REG
#define BOOT_SET_KERNEL_UPSR() BOOT_NATIVE_SET_KERNEL_UPSR()
#define RETURN_TO_KERNEL_UPSR(upsr_reg) \
NATIVE_RETURN_TO_KERNEL_UPSR(upsr_reg)
#define SET_KERNEL_UPSR_WITH_DISABLED_NMI() \
NATIVE_SET_KERNEL_UPSR_WITH_DISABLED_NMI()
static inline void *nested_kernel_return_address(int n)
{
return __e2k_read_kernel_return_address(n);
}
#endif /* CONFIG_PARAVIRT_GUEST */
#endif /* _E2K_SYSTEM_H_ */