arch/tile: parameterize system PLs to support KVM port
While not a port to KVM (yet), this change modifies the kernel to be able to build either at PL1 or at PL2 with a suitable config switch. Pushing up this change avoids handling branch merge issues going forward with the KVM work. Signed-off-by: Chris Metcalf <cmetcalf@tilera.com>
This commit is contained in:
@@ -12,8 +12,93 @@
|
||||
* more details.
|
||||
*/
|
||||
|
||||
/*
|
||||
* In addition to including the proper base SPR definition file, depending
|
||||
* on machine architecture, this file defines several macros which allow
|
||||
* kernel code to use protection-level dependent SPRs without worrying
|
||||
* about which PL it's running at. In these macros, the PL that the SPR
|
||||
* or interrupt number applies to is replaced by K.
|
||||
*/
|
||||
|
||||
#if CONFIG_KERNEL_PL != 1 && CONFIG_KERNEL_PL != 2
|
||||
#error CONFIG_KERNEL_PL must be 1 or 2
|
||||
#endif
|
||||
|
||||
/* Concatenate 4 strings. */
|
||||
#define __concat4(a, b, c, d) a ## b ## c ## d
|
||||
#define _concat4(a, b, c, d) __concat4(a, b, c, d)
|
||||
|
||||
#ifdef __tilegx__
|
||||
#include <arch/spr_def_64.h>
|
||||
|
||||
/* TILE-Gx dependent, protection-level dependent SPRs. */
|
||||
|
||||
#define SPR_INTERRUPT_MASK_K \
|
||||
_concat4(SPR_INTERRUPT_MASK_, CONFIG_KERNEL_PL,,)
|
||||
#define SPR_INTERRUPT_MASK_SET_K \
|
||||
_concat4(SPR_INTERRUPT_MASK_SET_, CONFIG_KERNEL_PL,,)
|
||||
#define SPR_INTERRUPT_MASK_RESET_K \
|
||||
_concat4(SPR_INTERRUPT_MASK_RESET_, CONFIG_KERNEL_PL,,)
|
||||
#define SPR_INTERRUPT_VECTOR_BASE_K \
|
||||
_concat4(SPR_INTERRUPT_VECTOR_BASE_, CONFIG_KERNEL_PL,,)
|
||||
|
||||
#define SPR_IPI_MASK_K \
|
||||
_concat4(SPR_IPI_MASK_, CONFIG_KERNEL_PL,,)
|
||||
#define SPR_IPI_MASK_RESET_K \
|
||||
_concat4(SPR_IPI_MASK_RESET_, CONFIG_KERNEL_PL,,)
|
||||
#define SPR_IPI_MASK_SET_K \
|
||||
_concat4(SPR_IPI_MASK_SET_, CONFIG_KERNEL_PL,,)
|
||||
#define SPR_IPI_EVENT_K \
|
||||
_concat4(SPR_IPI_EVENT_, CONFIG_KERNEL_PL,,)
|
||||
#define SPR_IPI_EVENT_RESET_K \
|
||||
_concat4(SPR_IPI_EVENT_RESET_, CONFIG_KERNEL_PL,,)
|
||||
#define SPR_IPI_MASK_SET_K \
|
||||
_concat4(SPR_IPI_MASK_SET_, CONFIG_KERNEL_PL,,)
|
||||
#define INT_IPI_K \
|
||||
_concat4(INT_IPI_, CONFIG_KERNEL_PL,,)
|
||||
|
||||
#define SPR_SINGLE_STEP_CONTROL_K \
|
||||
_concat4(SPR_SINGLE_STEP_CONTROL_, CONFIG_KERNEL_PL,,)
|
||||
#define SPR_SINGLE_STEP_EN_K_K \
|
||||
_concat4(SPR_SINGLE_STEP_EN_, CONFIG_KERNEL_PL, _, CONFIG_KERNEL_PL)
|
||||
#define INT_SINGLE_STEP_K \
|
||||
_concat4(INT_SINGLE_STEP_, CONFIG_KERNEL_PL,,)
|
||||
|
||||
#else
|
||||
#include <arch/spr_def_32.h>
|
||||
|
||||
/* TILEPro dependent, protection-level dependent SPRs. */
|
||||
|
||||
#define SPR_INTERRUPT_MASK_K_0 \
|
||||
_concat4(SPR_INTERRUPT_MASK_, CONFIG_KERNEL_PL, _0,)
|
||||
#define SPR_INTERRUPT_MASK_K_1 \
|
||||
_concat4(SPR_INTERRUPT_MASK_, CONFIG_KERNEL_PL, _1,)
|
||||
#define SPR_INTERRUPT_MASK_SET_K_0 \
|
||||
_concat4(SPR_INTERRUPT_MASK_SET_, CONFIG_KERNEL_PL, _0,)
|
||||
#define SPR_INTERRUPT_MASK_SET_K_1 \
|
||||
_concat4(SPR_INTERRUPT_MASK_SET_, CONFIG_KERNEL_PL, _1,)
|
||||
#define SPR_INTERRUPT_MASK_RESET_K_0 \
|
||||
_concat4(SPR_INTERRUPT_MASK_RESET_, CONFIG_KERNEL_PL, _0,)
|
||||
#define SPR_INTERRUPT_MASK_RESET_K_1 \
|
||||
_concat4(SPR_INTERRUPT_MASK_RESET_, CONFIG_KERNEL_PL, _1,)
|
||||
|
||||
#endif
|
||||
|
||||
/* Generic protection-level dependent SPRs. */
|
||||
|
||||
#define SPR_SYSTEM_SAVE_K_0 \
|
||||
_concat4(SPR_SYSTEM_SAVE_, CONFIG_KERNEL_PL, _0,)
|
||||
#define SPR_SYSTEM_SAVE_K_1 \
|
||||
_concat4(SPR_SYSTEM_SAVE_, CONFIG_KERNEL_PL, _1,)
|
||||
#define SPR_SYSTEM_SAVE_K_2 \
|
||||
_concat4(SPR_SYSTEM_SAVE_, CONFIG_KERNEL_PL, _2,)
|
||||
#define SPR_SYSTEM_SAVE_K_3 \
|
||||
_concat4(SPR_SYSTEM_SAVE_, CONFIG_KERNEL_PL, _3,)
|
||||
#define SPR_EX_CONTEXT_K_0 \
|
||||
_concat4(SPR_EX_CONTEXT_, CONFIG_KERNEL_PL, _0,)
|
||||
#define SPR_EX_CONTEXT_K_1 \
|
||||
_concat4(SPR_EX_CONTEXT_, CONFIG_KERNEL_PL, _1,)
|
||||
#define SPR_INTCTRL_K_STATUS \
|
||||
_concat4(SPR_INTCTRL_, CONFIG_KERNEL_PL, _STATUS,)
|
||||
#define INT_INTCTRL_K \
|
||||
_concat4(INT_INTCTRL_, CONFIG_KERNEL_PL,,)
|
||||
|
@@ -56,58 +56,93 @@
|
||||
#define SPR_EX_CONTEXT_1_1__ICS_SHIFT 2
|
||||
#define SPR_EX_CONTEXT_1_1__ICS_RMASK 0x1
|
||||
#define SPR_EX_CONTEXT_1_1__ICS_MASK 0x4
|
||||
#define SPR_EX_CONTEXT_2_0 0x4605
|
||||
#define SPR_EX_CONTEXT_2_1 0x4606
|
||||
#define SPR_EX_CONTEXT_2_1__PL_SHIFT 0
|
||||
#define SPR_EX_CONTEXT_2_1__PL_RMASK 0x3
|
||||
#define SPR_EX_CONTEXT_2_1__PL_MASK 0x3
|
||||
#define SPR_EX_CONTEXT_2_1__ICS_SHIFT 2
|
||||
#define SPR_EX_CONTEXT_2_1__ICS_RMASK 0x1
|
||||
#define SPR_EX_CONTEXT_2_1__ICS_MASK 0x4
|
||||
#define SPR_FAIL 0x4e09
|
||||
#define SPR_INTCTRL_0_STATUS 0x4a07
|
||||
#define SPR_INTCTRL_1_STATUS 0x4807
|
||||
#define SPR_INTCTRL_2_STATUS 0x4607
|
||||
#define SPR_INTERRUPT_CRITICAL_SECTION 0x4e0a
|
||||
#define SPR_INTERRUPT_MASK_0_0 0x4a08
|
||||
#define SPR_INTERRUPT_MASK_0_1 0x4a09
|
||||
#define SPR_INTERRUPT_MASK_1_0 0x4809
|
||||
#define SPR_INTERRUPT_MASK_1_1 0x480a
|
||||
#define SPR_INTERRUPT_MASK_2_0 0x4608
|
||||
#define SPR_INTERRUPT_MASK_2_1 0x4609
|
||||
#define SPR_INTERRUPT_MASK_RESET_0_0 0x4a0a
|
||||
#define SPR_INTERRUPT_MASK_RESET_0_1 0x4a0b
|
||||
#define SPR_INTERRUPT_MASK_RESET_1_0 0x480b
|
||||
#define SPR_INTERRUPT_MASK_RESET_1_1 0x480c
|
||||
#define SPR_INTERRUPT_MASK_RESET_2_0 0x460a
|
||||
#define SPR_INTERRUPT_MASK_RESET_2_1 0x460b
|
||||
#define SPR_INTERRUPT_MASK_SET_0_0 0x4a0c
|
||||
#define SPR_INTERRUPT_MASK_SET_0_1 0x4a0d
|
||||
#define SPR_INTERRUPT_MASK_SET_1_0 0x480d
|
||||
#define SPR_INTERRUPT_MASK_SET_1_1 0x480e
|
||||
#define SPR_INTERRUPT_MASK_SET_2_0 0x460c
|
||||
#define SPR_INTERRUPT_MASK_SET_2_1 0x460d
|
||||
#define SPR_MPL_DMA_CPL_SET_0 0x5800
|
||||
#define SPR_MPL_DMA_CPL_SET_1 0x5801
|
||||
#define SPR_MPL_DMA_CPL_SET_2 0x5802
|
||||
#define SPR_MPL_DMA_NOTIFY_SET_0 0x3800
|
||||
#define SPR_MPL_DMA_NOTIFY_SET_1 0x3801
|
||||
#define SPR_MPL_DMA_NOTIFY_SET_2 0x3802
|
||||
#define SPR_MPL_INTCTRL_0_SET_0 0x4a00
|
||||
#define SPR_MPL_INTCTRL_0_SET_1 0x4a01
|
||||
#define SPR_MPL_INTCTRL_0_SET_2 0x4a02
|
||||
#define SPR_MPL_INTCTRL_1_SET_0 0x4800
|
||||
#define SPR_MPL_INTCTRL_1_SET_1 0x4801
|
||||
#define SPR_MPL_INTCTRL_1_SET_2 0x4802
|
||||
#define SPR_MPL_INTCTRL_2_SET_0 0x4600
|
||||
#define SPR_MPL_INTCTRL_2_SET_1 0x4601
|
||||
#define SPR_MPL_INTCTRL_2_SET_2 0x4602
|
||||
#define SPR_MPL_SN_ACCESS_SET_0 0x0800
|
||||
#define SPR_MPL_SN_ACCESS_SET_1 0x0801
|
||||
#define SPR_MPL_SN_ACCESS_SET_2 0x0802
|
||||
#define SPR_MPL_SN_CPL_SET_0 0x5a00
|
||||
#define SPR_MPL_SN_CPL_SET_1 0x5a01
|
||||
#define SPR_MPL_SN_CPL_SET_2 0x5a02
|
||||
#define SPR_MPL_SN_FIREWALL_SET_0 0x2c00
|
||||
#define SPR_MPL_SN_FIREWALL_SET_1 0x2c01
|
||||
#define SPR_MPL_SN_FIREWALL_SET_2 0x2c02
|
||||
#define SPR_MPL_SN_NOTIFY_SET_0 0x2a00
|
||||
#define SPR_MPL_SN_NOTIFY_SET_1 0x2a01
|
||||
#define SPR_MPL_SN_NOTIFY_SET_2 0x2a02
|
||||
#define SPR_MPL_UDN_ACCESS_SET_0 0x0c00
|
||||
#define SPR_MPL_UDN_ACCESS_SET_1 0x0c01
|
||||
#define SPR_MPL_UDN_ACCESS_SET_2 0x0c02
|
||||
#define SPR_MPL_UDN_AVAIL_SET_0 0x4000
|
||||
#define SPR_MPL_UDN_AVAIL_SET_1 0x4001
|
||||
#define SPR_MPL_UDN_AVAIL_SET_2 0x4002
|
||||
#define SPR_MPL_UDN_CA_SET_0 0x3c00
|
||||
#define SPR_MPL_UDN_CA_SET_1 0x3c01
|
||||
#define SPR_MPL_UDN_CA_SET_2 0x3c02
|
||||
#define SPR_MPL_UDN_COMPLETE_SET_0 0x1400
|
||||
#define SPR_MPL_UDN_COMPLETE_SET_1 0x1401
|
||||
#define SPR_MPL_UDN_COMPLETE_SET_2 0x1402
|
||||
#define SPR_MPL_UDN_FIREWALL_SET_0 0x3000
|
||||
#define SPR_MPL_UDN_FIREWALL_SET_1 0x3001
|
||||
#define SPR_MPL_UDN_FIREWALL_SET_2 0x3002
|
||||
#define SPR_MPL_UDN_REFILL_SET_0 0x1000
|
||||
#define SPR_MPL_UDN_REFILL_SET_1 0x1001
|
||||
#define SPR_MPL_UDN_REFILL_SET_2 0x1002
|
||||
#define SPR_MPL_UDN_TIMER_SET_0 0x3600
|
||||
#define SPR_MPL_UDN_TIMER_SET_1 0x3601
|
||||
#define SPR_MPL_UDN_TIMER_SET_2 0x3602
|
||||
#define SPR_MPL_WORLD_ACCESS_SET_0 0x4e00
|
||||
#define SPR_MPL_WORLD_ACCESS_SET_1 0x4e01
|
||||
#define SPR_MPL_WORLD_ACCESS_SET_2 0x4e02
|
||||
#define SPR_PASS 0x4e0b
|
||||
#define SPR_PERF_COUNT_0 0x4205
|
||||
#define SPR_PERF_COUNT_1 0x4206
|
||||
#define SPR_PERF_COUNT_CTL 0x4207
|
||||
#define SPR_PERF_COUNT_DN_CTL 0x4210
|
||||
#define SPR_PERF_COUNT_STS 0x4208
|
||||
#define SPR_PROC_STATUS 0x4f00
|
||||
#define SPR_SIM_CONTROL 0x4e0c
|
||||
@@ -124,6 +159,10 @@
|
||||
#define SPR_SYSTEM_SAVE_1_1 0x4901
|
||||
#define SPR_SYSTEM_SAVE_1_2 0x4902
|
||||
#define SPR_SYSTEM_SAVE_1_3 0x4903
|
||||
#define SPR_SYSTEM_SAVE_2_0 0x4700
|
||||
#define SPR_SYSTEM_SAVE_2_1 0x4701
|
||||
#define SPR_SYSTEM_SAVE_2_2 0x4702
|
||||
#define SPR_SYSTEM_SAVE_2_3 0x4703
|
||||
#define SPR_TILE_COORD 0x4c17
|
||||
#define SPR_TILE_RTF_HWM 0x4e10
|
||||
#define SPR_TILE_TIMER_CONTROL 0x3205
|
||||
|
@@ -47,53 +47,53 @@
|
||||
int __n = (n); \
|
||||
int __mask = 1 << (__n & 0x1f); \
|
||||
if (__n < 32) \
|
||||
__insn_mtspr(SPR_INTERRUPT_MASK_SET_1_0, __mask); \
|
||||
__insn_mtspr(SPR_INTERRUPT_MASK_SET_K_0, __mask); \
|
||||
else \
|
||||
__insn_mtspr(SPR_INTERRUPT_MASK_SET_1_1, __mask); \
|
||||
__insn_mtspr(SPR_INTERRUPT_MASK_SET_K_1, __mask); \
|
||||
} while (0)
|
||||
#define interrupt_mask_reset(n) do { \
|
||||
int __n = (n); \
|
||||
int __mask = 1 << (__n & 0x1f); \
|
||||
if (__n < 32) \
|
||||
__insn_mtspr(SPR_INTERRUPT_MASK_RESET_1_0, __mask); \
|
||||
__insn_mtspr(SPR_INTERRUPT_MASK_RESET_K_0, __mask); \
|
||||
else \
|
||||
__insn_mtspr(SPR_INTERRUPT_MASK_RESET_1_1, __mask); \
|
||||
__insn_mtspr(SPR_INTERRUPT_MASK_RESET_K_1, __mask); \
|
||||
} while (0)
|
||||
#define interrupt_mask_check(n) ({ \
|
||||
int __n = (n); \
|
||||
(((__n < 32) ? \
|
||||
__insn_mfspr(SPR_INTERRUPT_MASK_1_0) : \
|
||||
__insn_mfspr(SPR_INTERRUPT_MASK_1_1)) \
|
||||
__insn_mfspr(SPR_INTERRUPT_MASK_K_0) : \
|
||||
__insn_mfspr(SPR_INTERRUPT_MASK_K_1)) \
|
||||
>> (__n & 0x1f)) & 1; \
|
||||
})
|
||||
#define interrupt_mask_set_mask(mask) do { \
|
||||
unsigned long long __m = (mask); \
|
||||
__insn_mtspr(SPR_INTERRUPT_MASK_SET_1_0, (unsigned long)(__m)); \
|
||||
__insn_mtspr(SPR_INTERRUPT_MASK_SET_1_1, (unsigned long)(__m>>32)); \
|
||||
__insn_mtspr(SPR_INTERRUPT_MASK_SET_K_0, (unsigned long)(__m)); \
|
||||
__insn_mtspr(SPR_INTERRUPT_MASK_SET_K_1, (unsigned long)(__m>>32)); \
|
||||
} while (0)
|
||||
#define interrupt_mask_reset_mask(mask) do { \
|
||||
unsigned long long __m = (mask); \
|
||||
__insn_mtspr(SPR_INTERRUPT_MASK_RESET_1_0, (unsigned long)(__m)); \
|
||||
__insn_mtspr(SPR_INTERRUPT_MASK_RESET_1_1, (unsigned long)(__m>>32)); \
|
||||
__insn_mtspr(SPR_INTERRUPT_MASK_RESET_K_0, (unsigned long)(__m)); \
|
||||
__insn_mtspr(SPR_INTERRUPT_MASK_RESET_K_1, (unsigned long)(__m>>32)); \
|
||||
} while (0)
|
||||
#else
|
||||
#define interrupt_mask_set(n) \
|
||||
__insn_mtspr(SPR_INTERRUPT_MASK_SET_1, (1UL << (n)))
|
||||
__insn_mtspr(SPR_INTERRUPT_MASK_SET_K, (1UL << (n)))
|
||||
#define interrupt_mask_reset(n) \
|
||||
__insn_mtspr(SPR_INTERRUPT_MASK_RESET_1, (1UL << (n)))
|
||||
__insn_mtspr(SPR_INTERRUPT_MASK_RESET_K, (1UL << (n)))
|
||||
#define interrupt_mask_check(n) \
|
||||
((__insn_mfspr(SPR_INTERRUPT_MASK_1) >> (n)) & 1)
|
||||
((__insn_mfspr(SPR_INTERRUPT_MASK_K) >> (n)) & 1)
|
||||
#define interrupt_mask_set_mask(mask) \
|
||||
__insn_mtspr(SPR_INTERRUPT_MASK_SET_1, (mask))
|
||||
__insn_mtspr(SPR_INTERRUPT_MASK_SET_K, (mask))
|
||||
#define interrupt_mask_reset_mask(mask) \
|
||||
__insn_mtspr(SPR_INTERRUPT_MASK_RESET_1, (mask))
|
||||
__insn_mtspr(SPR_INTERRUPT_MASK_RESET_K, (mask))
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The set of interrupts we want active if irqs are enabled.
|
||||
* Note that in particular, the tile timer interrupt comes and goes
|
||||
* from this set, since we have no other way to turn off the timer.
|
||||
* Likewise, INTCTRL_1 is removed and re-added during device
|
||||
* Likewise, INTCTRL_K is removed and re-added during device
|
||||
* interrupts, as is the the hardwall UDN_FIREWALL interrupt.
|
||||
* We use a low bit (MEM_ERROR) as our sentinel value and make sure it
|
||||
* is always claimed as an "active interrupt" so we can query that bit
|
||||
@@ -168,14 +168,14 @@ DECLARE_PER_CPU(unsigned long long, interrupts_enabled_mask);
|
||||
|
||||
/* Return 0 or 1 to indicate whether interrupts are currently disabled. */
|
||||
#define IRQS_DISABLED(tmp) \
|
||||
mfspr tmp, INTERRUPT_MASK_1; \
|
||||
mfspr tmp, SPR_INTERRUPT_MASK_K; \
|
||||
andi tmp, tmp, 1
|
||||
|
||||
/* Load up a pointer to &interrupts_enabled_mask. */
|
||||
#define GET_INTERRUPTS_ENABLED_MASK_PTR(reg) \
|
||||
moveli reg, hw2_last(interrupts_enabled_mask); \
|
||||
shl16insli reg, reg, hw1(interrupts_enabled_mask); \
|
||||
shl16insli reg, reg, hw0(interrupts_enabled_mask); \
|
||||
moveli reg, hw2_last(interrupts_enabled_mask); \
|
||||
shl16insli reg, reg, hw1(interrupts_enabled_mask); \
|
||||
shl16insli reg, reg, hw0(interrupts_enabled_mask); \
|
||||
add reg, reg, tp
|
||||
|
||||
/* Disable interrupts. */
|
||||
@@ -183,18 +183,18 @@ DECLARE_PER_CPU(unsigned long long, interrupts_enabled_mask);
|
||||
moveli tmp0, hw2_last(LINUX_MASKABLE_INTERRUPTS); \
|
||||
shl16insli tmp0, tmp0, hw1(LINUX_MASKABLE_INTERRUPTS); \
|
||||
shl16insli tmp0, tmp0, hw0(LINUX_MASKABLE_INTERRUPTS); \
|
||||
mtspr INTERRUPT_MASK_SET_1, tmp0
|
||||
mtspr SPR_INTERRUPT_MASK_SET_K, tmp0
|
||||
|
||||
/* Disable ALL synchronous interrupts (used by NMI entry). */
|
||||
#define IRQ_DISABLE_ALL(tmp) \
|
||||
movei tmp, -1; \
|
||||
mtspr INTERRUPT_MASK_SET_1, tmp
|
||||
mtspr SPR_INTERRUPT_MASK_SET_K, tmp
|
||||
|
||||
/* Enable interrupts. */
|
||||
#define IRQ_ENABLE(tmp0, tmp1) \
|
||||
GET_INTERRUPTS_ENABLED_MASK_PTR(tmp0); \
|
||||
ld tmp0, tmp0; \
|
||||
mtspr INTERRUPT_MASK_RESET_1, tmp0
|
||||
mtspr SPR_INTERRUPT_MASK_RESET_K, tmp0
|
||||
|
||||
#else /* !__tilegx__ */
|
||||
|
||||
@@ -208,14 +208,14 @@ DECLARE_PER_CPU(unsigned long long, interrupts_enabled_mask);
|
||||
* (making the original code's write of the "high" mask word idempotent).
|
||||
*/
|
||||
#define IRQS_DISABLED(tmp) \
|
||||
mfspr tmp, INTERRUPT_MASK_1_0; \
|
||||
mfspr tmp, SPR_INTERRUPT_MASK_K_0; \
|
||||
shri tmp, tmp, INT_MEM_ERROR; \
|
||||
andi tmp, tmp, 1
|
||||
|
||||
/* Load up a pointer to &interrupts_enabled_mask. */
|
||||
#define GET_INTERRUPTS_ENABLED_MASK_PTR(reg) \
|
||||
moveli reg, lo16(interrupts_enabled_mask); \
|
||||
auli reg, reg, ha16(interrupts_enabled_mask);\
|
||||
moveli reg, lo16(interrupts_enabled_mask); \
|
||||
auli reg, reg, ha16(interrupts_enabled_mask); \
|
||||
add reg, reg, tp
|
||||
|
||||
/* Disable interrupts. */
|
||||
@@ -225,16 +225,16 @@ DECLARE_PER_CPU(unsigned long long, interrupts_enabled_mask);
|
||||
moveli tmp1, lo16(LINUX_MASKABLE_INTERRUPTS) \
|
||||
}; \
|
||||
{ \
|
||||
mtspr INTERRUPT_MASK_SET_1_0, tmp0; \
|
||||
mtspr SPR_INTERRUPT_MASK_SET_K_0, tmp0; \
|
||||
auli tmp1, tmp1, ha16(LINUX_MASKABLE_INTERRUPTS) \
|
||||
}; \
|
||||
mtspr INTERRUPT_MASK_SET_1_1, tmp1
|
||||
mtspr SPR_INTERRUPT_MASK_SET_K_1, tmp1
|
||||
|
||||
/* Disable ALL synchronous interrupts (used by NMI entry). */
|
||||
#define IRQ_DISABLE_ALL(tmp) \
|
||||
movei tmp, -1; \
|
||||
mtspr INTERRUPT_MASK_SET_1_0, tmp; \
|
||||
mtspr INTERRUPT_MASK_SET_1_1, tmp
|
||||
mtspr SPR_INTERRUPT_MASK_SET_K_0, tmp; \
|
||||
mtspr SPR_INTERRUPT_MASK_SET_K_1, tmp
|
||||
|
||||
/* Enable interrupts. */
|
||||
#define IRQ_ENABLE(tmp0, tmp1) \
|
||||
@@ -244,8 +244,8 @@ DECLARE_PER_CPU(unsigned long long, interrupts_enabled_mask);
|
||||
addi tmp1, tmp0, 4 \
|
||||
}; \
|
||||
lw tmp1, tmp1; \
|
||||
mtspr INTERRUPT_MASK_RESET_1_0, tmp0; \
|
||||
mtspr INTERRUPT_MASK_RESET_1_1, tmp1
|
||||
mtspr SPR_INTERRUPT_MASK_RESET_K_0, tmp0; \
|
||||
mtspr SPR_INTERRUPT_MASK_RESET_K_1, tmp1
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
@@ -199,17 +199,17 @@ static inline __attribute_const__ int get_order(unsigned long size)
|
||||
* If you want more physical memory than this then see the CONFIG_HIGHMEM
|
||||
* option in the kernel configuration.
|
||||
*
|
||||
* The top two 16MB chunks in the table below (VIRT and HV) are
|
||||
* unavailable to Linux. Since the kernel interrupt vectors must live
|
||||
* at 0xfd000000, we map all of the bottom of RAM at this address with
|
||||
* a huge page table entry to minimize its ITLB footprint (as well as
|
||||
* at PAGE_OFFSET). The last architected requirement is that user
|
||||
* interrupt vectors live at 0xfc000000, so we make that range of
|
||||
* memory available to user processes. The remaining regions are sized
|
||||
* as shown; after the first four addresses, we show "typical" values,
|
||||
* since the actual addresses depend on kernel #defines.
|
||||
* The top 16MB chunk in the table below is unavailable to Linux. Since
|
||||
* the kernel interrupt vectors must live at ether 0xfe000000 or 0xfd000000
|
||||
* (depending on whether the kernel is at PL2 or Pl1), we map all of the
|
||||
* bottom of RAM at this address with a huge page table entry to minimize
|
||||
* its ITLB footprint (as well as at PAGE_OFFSET). The last architected
|
||||
* requirement is that user interrupt vectors live at 0xfc000000, so we
|
||||
* make that range of memory available to user processes. The remaining
|
||||
* regions are sized as shown; the first four addresses use the PL 1
|
||||
* values, and after that, we show "typical" values, since the actual
|
||||
* addresses depend on kernel #defines.
|
||||
*
|
||||
* MEM_VIRT_INTRPT 0xff000000
|
||||
* MEM_HV_INTRPT 0xfe000000
|
||||
* MEM_SV_INTRPT (kernel code) 0xfd000000
|
||||
* MEM_USER_INTRPT (user vector) 0xfc000000
|
||||
@@ -221,9 +221,14 @@ static inline __attribute_const__ int get_order(unsigned long size)
|
||||
*/
|
||||
|
||||
#define MEM_USER_INTRPT _AC(0xfc000000, UL)
|
||||
#if CONFIG_KERNEL_PL == 1
|
||||
#define MEM_SV_INTRPT _AC(0xfd000000, UL)
|
||||
#define MEM_HV_INTRPT _AC(0xfe000000, UL)
|
||||
#define MEM_VIRT_INTRPT _AC(0xff000000, UL)
|
||||
#else
|
||||
#define MEM_GUEST_INTRPT _AC(0xfd000000, UL)
|
||||
#define MEM_SV_INTRPT _AC(0xfe000000, UL)
|
||||
#define MEM_HV_INTRPT _AC(0xff000000, UL)
|
||||
#endif
|
||||
|
||||
#define INTRPT_SIZE 0x4000
|
||||
|
||||
|
@@ -328,18 +328,21 @@ extern int kdata_huge;
|
||||
* Note that assembly code assumes that USER_PL is zero.
|
||||
*/
|
||||
#define USER_PL 0
|
||||
#define KERNEL_PL 1
|
||||
#if CONFIG_KERNEL_PL == 2
|
||||
#define GUEST_PL 1
|
||||
#endif
|
||||
#define KERNEL_PL CONFIG_KERNEL_PL
|
||||
|
||||
/* SYSTEM_SAVE_1_0 holds the current cpu number ORed with ksp0. */
|
||||
/* SYSTEM_SAVE_K_0 holds the current cpu number ORed with ksp0. */
|
||||
#define CPU_LOG_MASK_VALUE 12
|
||||
#define CPU_MASK_VALUE ((1 << CPU_LOG_MASK_VALUE) - 1)
|
||||
#if CONFIG_NR_CPUS > CPU_MASK_VALUE
|
||||
# error Too many cpus!
|
||||
#endif
|
||||
#define raw_smp_processor_id() \
|
||||
((int)__insn_mfspr(SPR_SYSTEM_SAVE_1_0) & CPU_MASK_VALUE)
|
||||
((int)__insn_mfspr(SPR_SYSTEM_SAVE_K_0) & CPU_MASK_VALUE)
|
||||
#define get_current_ksp0() \
|
||||
(__insn_mfspr(SPR_SYSTEM_SAVE_1_0) & ~CPU_MASK_VALUE)
|
||||
(__insn_mfspr(SPR_SYSTEM_SAVE_K_0) & ~CPU_MASK_VALUE)
|
||||
#define next_current_ksp0(task) ({ \
|
||||
unsigned long __ksp0 = task_ksp0(task); \
|
||||
int __cpu = raw_smp_processor_id(); \
|
||||
|
@@ -62,8 +62,8 @@ struct pt_regs {
|
||||
pt_reg_t lr; /* aliases regs[TREG_LR] */
|
||||
|
||||
/* Saved special registers. */
|
||||
pt_reg_t pc; /* stored in EX_CONTEXT_1_0 */
|
||||
pt_reg_t ex1; /* stored in EX_CONTEXT_1_1 (PL and ICS bit) */
|
||||
pt_reg_t pc; /* stored in EX_CONTEXT_K_0 */
|
||||
pt_reg_t ex1; /* stored in EX_CONTEXT_K_1 (PL and ICS bit) */
|
||||
pt_reg_t faultnum; /* fault number (INT_SWINT_1 for syscall) */
|
||||
pt_reg_t orig_r0; /* r0 at syscall entry, else zero */
|
||||
pt_reg_t flags; /* flags (see below) */
|
||||
|
@@ -164,7 +164,7 @@ extern struct task_struct *_switch_to(struct task_struct *prev,
|
||||
/* Helper function for _switch_to(). */
|
||||
extern struct task_struct *__switch_to(struct task_struct *prev,
|
||||
struct task_struct *next,
|
||||
unsigned long new_system_save_1_0);
|
||||
unsigned long new_system_save_k_0);
|
||||
|
||||
/* Address that switched-away from tasks are at. */
|
||||
extern unsigned long get_switch_to_pc(void);
|
||||
|
@@ -1003,37 +1003,37 @@ int hv_console_write(HV_VirtAddr bytes, int len);
|
||||
* when these occur in a client's interrupt critical section, they must
|
||||
* be delivered through the downcall mechanism.
|
||||
*
|
||||
* A downcall is initially delivered to the client as an INTCTRL_1
|
||||
* interrupt. Upon entry to the INTCTRL_1 vector, the client must
|
||||
* immediately invoke the hv_downcall_dispatch service. This service
|
||||
* will not return; instead it will cause one of the client's actual
|
||||
* downcall-handling interrupt vectors to be entered. The EX_CONTEXT
|
||||
* registers in the client will be set so that when the client irets,
|
||||
* it will return to the code which was interrupted by the INTCTRL_1
|
||||
* interrupt.
|
||||
* A downcall is initially delivered to the client as an INTCTRL_CL
|
||||
* interrupt, where CL is the client's PL. Upon entry to the INTCTRL_CL
|
||||
* vector, the client must immediately invoke the hv_downcall_dispatch
|
||||
* service. This service will not return; instead it will cause one of
|
||||
* the client's actual downcall-handling interrupt vectors to be entered.
|
||||
* The EX_CONTEXT registers in the client will be set so that when the
|
||||
* client irets, it will return to the code which was interrupted by the
|
||||
* INTCTRL_CL interrupt.
|
||||
*
|
||||
* Under some circumstances, the firing of INTCTRL_1 can race with
|
||||
* Under some circumstances, the firing of INTCTRL_CL can race with
|
||||
* the lowering of a device interrupt. In such a case, the
|
||||
* hv_downcall_dispatch service may issue an iret instruction instead
|
||||
* of entering one of the client's actual downcall-handling interrupt
|
||||
* vectors. This will return execution to the location that was
|
||||
* interrupted by INTCTRL_1.
|
||||
* interrupted by INTCTRL_CL.
|
||||
*
|
||||
* Any saving of registers should be done by the actual handling
|
||||
* vectors; no registers should be changed by the INTCTRL_1 handler.
|
||||
* vectors; no registers should be changed by the INTCTRL_CL handler.
|
||||
* In particular, the client should not use a jal instruction to invoke
|
||||
* the hv_downcall_dispatch service, as that would overwrite the client's
|
||||
* lr register. Note that the hv_downcall_dispatch service may overwrite
|
||||
* one or more of the client's system save registers.
|
||||
*
|
||||
* The client must not modify the INTCTRL_1_STATUS SPR. The hypervisor
|
||||
* The client must not modify the INTCTRL_CL_STATUS SPR. The hypervisor
|
||||
* will set this register to cause a downcall to happen, and will clear
|
||||
* it when no further downcalls are pending.
|
||||
*
|
||||
* When a downcall vector is entered, the INTCTRL_1 interrupt will be
|
||||
* When a downcall vector is entered, the INTCTRL_CL interrupt will be
|
||||
* masked. When the client is done processing a downcall, and is ready
|
||||
* to accept another, it must unmask this interrupt; if more downcalls
|
||||
* are pending, this will cause the INTCTRL_1 vector to be reentered.
|
||||
* are pending, this will cause the INTCTRL_CL vector to be reentered.
|
||||
* Currently the following interrupt vectors can be entered through a
|
||||
* downcall:
|
||||
*
|
||||
|
Reference in New Issue
Block a user