Commit e404f91e authored by Linus Torvalds's avatar Linus Torvalds

Merge git://git.kernel.org/pub/scm/linux/kernel/git/cmetcalf/linux-tile

* git://git.kernel.org/pub/scm/linux/kernel/git/cmetcalf/linux-tile:
  arch/tile: convert a BUG_ON to BUILD_BUG_ON
  arch/tile: make ptrace() work properly for TILE-Gx COMPAT mode
  arch/tile: support new info op generated by compiler
  arch/tile: minor whitespace/naming changes for string support files
  arch/tile: enable single-step support for TILE-Gx
  arch/tile: parameterize system PLs to support KVM port
  arch/tile: add Tilera's <arch/sim.h> header as an open-source header
  arch/tile: Bomb C99 comments to C89 comments in tile's <arch/sim_def.h>
  arch/tile: prevent corrupt top frame from causing backtracer runaway
  arch/tile: various top-level Makefile cleanups
  arch/tile: change lower bound on syscall error return to -4095
  arch/tile: properly export __mb_incoherent for modules
  arch/tile: provide a definition of MAP_STACK
  kmemleak: add TILE to the list of supported architectures.
  char: hvc: check for error case
  arch/tile: Add a warning if we try to allocate too much vmalloc memory.
  arch/tile: update some comments to clarify register usage.
  arch/tile: use better "punctuation" for VMSPLIT_3_5G and friends
  arch/tile: Use <asm-generic/syscalls.h>
  tile: replace some BUG_ON checks with BUILD_BUG_ON checks
parents 18a043f9 e18105c1
......@@ -96,6 +96,7 @@ config HVC_TILE
config TILE
def_bool y
select HAVE_KVM if !TILEGX
select GENERIC_FIND_FIRST_BIT
select GENERIC_FIND_NEXT_BIT
select USE_GENERIC_SMP_HELPERS
......@@ -236,9 +237,9 @@ choice
If you are not absolutely sure what you are doing, leave this
option alone!
config VMSPLIT_375G
config VMSPLIT_3_75G
bool "3.75G/0.25G user/kernel split (no kernel networking)"
config VMSPLIT_35G
config VMSPLIT_3_5G
bool "3.5G/0.5G user/kernel split"
config VMSPLIT_3G
bool "3G/1G user/kernel split"
......@@ -252,8 +253,8 @@ endchoice
config PAGE_OFFSET
hex
default 0xF0000000 if VMSPLIT_375G
default 0xE0000000 if VMSPLIT_35G
default 0xF0000000 if VMSPLIT_3_75G
default 0xE0000000 if VMSPLIT_3_5G
default 0xB0000000 if VMSPLIT_3G_OPT
default 0x80000000 if VMSPLIT_2G
default 0x40000000 if VMSPLIT_1G
......@@ -314,6 +315,15 @@ config HARDWALL
bool "Hardwall support to allow access to user dynamic network"
default y
config KERNEL_PL
int "Processor protection level for kernel"
range 1 2
default "1"
---help---
This setting determines the processor protection level the
kernel will be built to run at. Generally you should use
the default value here.
endmenu # Tilera-specific configuration
menu "Bus options"
......@@ -354,3 +364,5 @@ source "security/Kconfig"
source "crypto/Kconfig"
source "lib/Kconfig"
source "arch/tile/kvm/Kconfig"
......@@ -26,8 +26,9 @@ $(error Set TILERA_ROOT or CROSS_COMPILE when building $(ARCH) on $(HOST_ARCH))
endif
endif
ifneq ($(CONFIG_DEBUG_EXTRA_FLAGS),"")
KBUILD_CFLAGS += $(CONFIG_DEBUG_EXTRA_FLAGS)
endif
LIBGCC_PATH := $(shell $(CC) $(KBUILD_CFLAGS) -print-libgcc-file-name)
......@@ -49,6 +50,20 @@ head-y := arch/tile/kernel/head_$(BITS).o
libs-y += arch/tile/lib/
libs-y += $(LIBGCC_PATH)
# See arch/tile/Kbuild for content of core part of the kernel
core-y += arch/tile/
core-$(CONFIG_KVM) += arch/tile/kvm/
ifdef TILERA_ROOT
INSTALL_PATH ?= $(TILERA_ROOT)/tile/boot
endif
install:
install -D -m 755 vmlinux $(INSTALL_PATH)/vmlinux-$(KERNELRELEASE)
install -D -m 644 .config $(INSTALL_PATH)/config-$(KERNELRELEASE)
install -D -m 644 System.map $(INSTALL_PATH)/System.map-$(KERNELRELEASE)
define archhelp
echo ' install - install kernel into $(INSTALL_PATH)'
endef
This diff is collapsed.
This diff is collapsed.
......@@ -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
......
......@@ -146,7 +146,10 @@ enum {
CALLER_SP_IN_R52_BASE = 4,
CALLER_SP_OFFSET_BASE = 8
CALLER_SP_OFFSET_BASE = 8,
/* Marks the entry point of certain functions. */
ENTRY_POINT_INFO_OP = 16
};
......
......@@ -216,15 +216,16 @@ struct compat_siginfo;
struct compat_sigaltstack;
long compat_sys_execve(const char __user *path,
const compat_uptr_t __user *argv,
const compat_uptr_t __user *envp);
const compat_uptr_t __user *envp, struct pt_regs *);
long compat_sys_rt_sigaction(int sig, struct compat_sigaction __user *act,
struct compat_sigaction __user *oact,
size_t sigsetsize);
long compat_sys_rt_sigqueueinfo(int pid, int sig,
struct compat_siginfo __user *uinfo);
long compat_sys_rt_sigreturn(void);
long compat_sys_rt_sigreturn(struct pt_regs *);
long compat_sys_sigaltstack(const struct compat_sigaltstack __user *uss_ptr,
struct compat_sigaltstack __user *uoss_ptr);
struct compat_sigaltstack __user *uoss_ptr,
struct pt_regs *);
long compat_sys_truncate64(char __user *filename, u32 dummy, u32 low, u32 high);
long compat_sys_ftruncate64(unsigned int fd, u32 dummy, u32 low, u32 high);
long compat_sys_pread64(unsigned int fd, char __user *ubuf, size_t count,
......@@ -255,4 +256,12 @@ long tile_compat_sys_ptrace(compat_long_t request, compat_long_t pid,
/* Tilera Linux syscalls that don't have "compat" versions. */
#define compat_sys_flush_cache sys_flush_cache
/* These are the intvec_64.S trampolines. */
long _compat_sys_execve(const char __user *path,
const compat_uptr_t __user *argv,
const compat_uptr_t __user *envp);
long _compat_sys_sigaltstack(const struct compat_sigaltstack __user *uss_ptr,
struct compat_sigaltstack __user *uoss_ptr);
long _compat_sys_rt_sigreturn(void);
#endif /* _ASM_TILE_COMPAT_H */
......@@ -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
......@@ -170,7 +170,7 @@ 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. */
......@@ -185,18 +185,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__ */
......@@ -210,14 +210,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);\
auli reg, reg, ha16(interrupts_enabled_mask); \
add reg, reg, tp
/* Disable interrupts. */
......@@ -227,16 +227,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) \
......@@ -246,8 +246,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
/*
......
......@@ -23,6 +23,7 @@
#define MAP_POPULATE 0x0040 /* populate (prefault) pagetables */
#define MAP_NONBLOCK 0x0080 /* do not block on IO */
#define MAP_GROWSDOWN 0x0100 /* stack-like segment */
#define MAP_STACK MAP_GROWSDOWN /* provide convenience alias */
#define MAP_LOCKED 0x0200 /* pages are locked */
#define MAP_NORESERVE 0x0400 /* don't check for reservations */
#define MAP_DENYWRITE 0x0800 /* ETXTBSY */
......
......@@ -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) */
......
......@@ -32,8 +32,9 @@ extern void *compat_sys_call_table[];
/*
* Note that by convention, any syscall which requires the current
* register set takes an additional "struct pt_regs *" pointer; the
* sys_xxx() function just adds the pointer and tail-calls to _sys_xxx().
* register set takes an additional "struct pt_regs *" pointer; a
* _sys_xxx() trampoline in intvec*.S just sets up the pointer and
* jumps to sys_xxx().
*/
/* kernel/sys.c */
......@@ -43,66 +44,17 @@ long sys32_fadvise64(int fd, u32 offset_lo, u32 offset_hi,
int sys32_fadvise64_64(int fd, u32 offset_lo, u32 offset_hi,
u32 len_lo, u32 len_hi, int advice);
long sys_flush_cache(void);
long sys_mmap2(unsigned long addr, unsigned long len,
unsigned long prot, unsigned long flags,
unsigned long fd, unsigned long pgoff);
#ifdef __tilegx__
long sys_mmap(unsigned long addr, unsigned long len,
unsigned long prot, unsigned long flags,
unsigned long fd, off_t pgoff);
#ifndef __tilegx__ /* No mmap() in the 32-bit kernel. */
#define sys_mmap sys_mmap
#endif
/* kernel/process.c */
long sys_clone(unsigned long clone_flags, unsigned long newsp,
void __user *parent_tid, void __user *child_tid);
long _sys_clone(unsigned long clone_flags, unsigned long newsp,
void __user *parent_tid, void __user *child_tid,
struct pt_regs *regs);
long sys_fork(void);
long _sys_fork(struct pt_regs *regs);
long sys_vfork(void);
long _sys_vfork(struct pt_regs *regs);
long sys_execve(const char __user *filename,
const char __user *const __user *argv,
const char __user *const __user *envp);
long _sys_execve(const char __user *filename,
const char __user *const __user *argv,
const char __user *const __user *envp, struct pt_regs *regs);
/* kernel/signal.c */
long sys_sigaltstack(const stack_t __user *, stack_t __user *);
long _sys_sigaltstack(const stack_t __user *, stack_t __user *,
struct pt_regs *);
long sys_rt_sigreturn(void);
long _sys_rt_sigreturn(struct pt_regs *regs);
/* platform-independent functions */
long sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize);
long sys_rt_sigaction(int sig, const struct sigaction __user *act,
struct sigaction __user *oact, size_t sigsetsize);
#ifndef __tilegx__
/* mm/fault.c */
int sys_cmpxchg_badaddr(unsigned long address);
int _sys_cmpxchg_badaddr(unsigned long address, struct pt_regs *);
long sys_cmpxchg_badaddr(unsigned long address, struct pt_regs *);
long _sys_cmpxchg_badaddr(unsigned long address);
#endif
#ifdef CONFIG_COMPAT
long compat_sys_execve(const char __user *path,
const compat_uptr_t __user *argv,
const compat_uptr_t __user *envp);
long _compat_sys_execve(const char __user *path,
const compat_uptr_t __user *argv,
const compat_uptr_t __user *envp,
struct pt_regs *regs);
long compat_sys_sigaltstack(const struct compat_sigaltstack __user *uss_ptr,
struct compat_sigaltstack __user *uoss_ptr);
long _compat_sys_sigaltstack(const struct compat_sigaltstack __user *uss_ptr,
struct compat_sigaltstack __user *uoss_ptr,
struct pt_regs *regs);
long compat_sys_rt_sigreturn(void);
long _compat_sys_rt_sigreturn(struct pt_regs *regs);
/* These four are not defined for 64-bit, but serve as "compat" syscalls. */
long sys_fcntl64(unsigned int fd, unsigned int cmd, unsigned long arg);
long sys_fstat64(unsigned long fd, struct stat64 __user *statbuf);
......@@ -110,4 +62,15 @@ long sys_truncate64(const char __user *path, loff_t length);
long sys_ftruncate64(unsigned int fd, loff_t length);
#endif
/* These are the intvec*.S trampolines. */
long _sys_sigaltstack(const stack_t __user *, stack_t __user *);
long _sys_rt_sigreturn(void);
long _sys_clone(unsigned long clone_flags, unsigned long newsp,
void __user *parent_tid, void __user *child_tid);
long _sys_execve(const char __user *filename,
const char __user *const __user *argv,
const char __user *const __user *envp);
#include <asm-generic/syscalls.h>
#endif /* _ASM_TILE_SYSCALLS_H */
......@@ -89,6 +89,10 @@
#define get_cycles_low() __insn_mfspr(SPR_CYCLE) /* just get all 64 bits */
#endif
#if !CHIP_HAS_MF_WAITS_FOR_VICTIMS()
int __mb_incoherent(void); /* Helper routine for mb_incoherent(). */
#endif
/* Fence to guarantee visibility of stores to incoherent memory. */
static inline void
mb_incoherent(void)
......@@ -97,7 +101,6 @@ mb_incoherent(void)
#if !CHIP_HAS_MF_WAITS_FOR_VICTIMS()
{
int __mb_incoherent(void);
#if CHIP_HAS_TILE_WRITE_PENDING()
const unsigned long WRITE_TIMEOUT_CYCLES = 400;
unsigned long start = get_cycles_low();
......@@ -161,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);
......@@ -214,13 +217,6 @@ int hardwall_deactivate(struct task_struct *task);
} while (0)
#endif
/* Invoke the simulator "syscall" mechanism (see arch/tile/kernel/entry.S). */
extern int _sim_syscall(int syscall_num, ...);
#define sim_syscall(syscall_num, ...) \
_sim_syscall(SIM_CONTROL_SYSCALL + \
((syscall_num) << _SIM_CONTROL_OPERATOR_BITS), \
## __VA_ARGS__)
/*
* Kernel threads can check to see if they need to migrate their
* stack whenever they return from a context switch; for user
......
......@@ -59,4 +59,8 @@ void do_hardwall_trap(struct pt_regs *, int fault_num);
void do_breakpoint(struct pt_regs *, int fault_num);
#ifdef __tilegx__
void gx_singlestep_handle(struct pt_regs *, int fault_num);
#endif
#endif /* _ASM_TILE_SYSCALLS_H */
......@@ -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.
*
* Under some circumstances, the firing of INTCTRL_1 can race with
* 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_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:
*
......
......@@ -369,6 +369,10 @@ static void find_caller_pc_and_caller_sp(CallerLocation *location,
/* Weird; reserved value, ignore it. */
continue;
}
if (info_operand & ENTRY_POINT_INFO_OP) {
/* This info op is ignored by the backtracer. */
continue;
}
/* Skip info ops which are not in the
* "one_ago" mode we want right now.
......
......@@ -154,8 +154,14 @@ long tile_compat_sys_msgrcv(int msqid,
#define compat_sys_fstat64 sys_newfstat
#define compat_sys_fstatat64 sys_newfstatat
/* Pass full 64-bit values through ptrace. */
#define compat_sys_ptrace tile_compat_sys_ptrace
/* The native sys_ptrace dynamically handles compat binaries. */
#define compat_sys_ptrace sys_ptrace
/* Call the trampolines to manage pt_regs where necessary. */
#define compat_sys_execve _compat_sys_execve
#define compat_sys_sigaltstack _compat_sys_sigaltstack
#define compat_sys_rt_sigreturn _compat_sys_rt_sigreturn
#define sys_clone _sys_clone
/*
* Note that we can't include <linux/unistd.h> here since the header
......
......@@ -256,7 +256,7 @@ int copy_siginfo_from_user32(siginfo_t *to, struct compat_siginfo __user *from)
return err;
}
long _compat_sys_sigaltstack(const struct compat_sigaltstack __user *uss_ptr,
long compat_sys_sigaltstack(const struct compat_sigaltstack __user *uss_ptr,
struct compat_sigaltstack __user *uoss_ptr,
struct pt_regs *regs)
{
......@@ -291,7 +291,7 @@ long _compat_sys_sigaltstack(const struct compat_sigaltstack __user *uss_ptr,
return ret;
}
long _compat_sys_rt_sigreturn(struct pt_regs *regs)
long compat_sys_rt_sigreturn(struct pt_regs *regs)
{
struct compat_rt_sigframe __user *frame =
(struct compat_rt_sigframe __user *) compat_ptr(regs->sp);
......@@ -312,7 +312,7 @@ long _compat_sys_rt_sigreturn(struct pt_regs *regs)
if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &r0))
goto badframe;
if (_compat_sys_sigaltstack(&frame->uc.uc_stack, NULL, regs) != 0)
if (compat_sys_sigaltstack(&frame->uc.uc_stack, NULL, regs) != 0)
goto badframe;
return r0;
......
......@@ -15,7 +15,9 @@
#include <linux/linkage.h>
#include <linux/unistd.h>
#include <asm/irqflags.h>
#include <asm/processor.h>
#include <arch/abi.h>
#include <arch/spr_def.h>
#ifdef __tilegx__
#define bnzt bnezt
......@@ -25,28 +27,6 @@ STD_ENTRY(current_text_addr)
{ move r0, lr; jrp lr }
STD_ENDPROC(current_text_addr)
STD_ENTRY(_sim_syscall)
/*
* Wait for r0-r9 to be ready (and lr on the off chance we
* want the syscall to locate its caller), then make a magic
* simulator syscall.
*
* We carefully stall until the registers are readable in case they
* are the target of a slow load, etc. so that tile-sim will
* definitely be able to read all of them inside the magic syscall.
*
* Technically this is wrong for r3-r9 and lr, since an interrupt
* could come in and restore the registers with a slow load right
* before executing the mtspr. We may need to modify tile-sim to
* explicitly stall for this case, but we do not yet have
* a way to implement such a stall.
*/
{ and zero, lr, r9 ; and zero, r8, r7 }
{ and zero, r6, r5 ; and zero, r4, r3 }
{ and zero, r2, r1 ; mtspr SIM_CONTROL, r0 }
{ jrp lr }
STD_ENDPROC(_sim_syscall)
/*
* Implement execve(). The i386 code has a note that forking from kernel
* space results in no copy on write until the execve, so we should be
......@@ -102,7 +82,7 @@ STD_ENTRY(KBacktraceIterator_init_current)
STD_ENTRY(cpu_idle_on_new_stack)
{
move sp, r1
mtspr SYSTEM_SAVE_1_0, r2
mtspr SPR_SYSTEM_SAVE_K_0, r2
}
jal free_thread_info
j cpu_idle
......@@ -124,15 +104,15 @@ STD_ENTRY(smp_nap)
STD_ENTRY(_cpu_idle)
{
lnk r0
movei r1, 1
movei r1, KERNEL_PL
}
{
addli r0, r0, _cpu_idle_nap - .
mtspr INTERRUPT_CRITICAL_SECTION, r1
}
IRQ_ENABLE(r2, r3) /* unmask, but still with ICS set */
mtspr EX_CONTEXT_1_1, r1 /* PL1, ICS clear */
mtspr EX_CONTEXT_1_0, r0
mtspr SPR_EX_CONTEXT_K_1, r1 /* Kernel PL, ICS clear */
mtspr SPR_EX_CONTEXT_K_0, r0
iret
.global _cpu_idle_nap
_cpu_idle_nap:
......
......@@ -23,6 +23,7 @@
#include <asm/asm-offsets.h>
#include <hv/hypervisor.h>
#include <arch/chip.h>
#include <arch/spr_def.h>
/*
* This module contains the entry code for kernel images. It performs the
......@@ -76,7 +77,7 @@ ENTRY(_start)
}
1:
/* Get our processor number and save it away in SAVE_1_0. */
/* Get our processor number and save it away in SAVE_K_0. */
jal hv_inquire_topology
mulll_uu r4, r1, r2 /* r1 == y, r2 == width */
add r4, r4, r0 /* r0 == x, so r4 == cpu == y*width + x */
......@@ -124,7 +125,7 @@ ENTRY(_start)
lw r0, r0
lw sp, r1
or r4, sp, r4
mtspr SYSTEM_SAVE_1_0, r4 /* save ksp0 + cpu */
mtspr SPR_SYSTEM_SAVE_K_0, r4 /* save ksp0 + cpu */
addi sp, sp, -STACK_TOP_DELTA
{
move lr, zero /* stop backtraces in the called function */
......
This diff is collapsed.
......@@ -61,9 +61,9 @@ static DEFINE_SPINLOCK(available_irqs_lock);
#if CHIP_HAS_IPI()
/* Use SPRs to manipulate device interrupts. */
#define mask_irqs(irq_mask) __insn_mtspr(SPR_IPI_MASK_SET_1, irq_mask)
#define unmask_irqs(irq_mask) __insn_mtspr(SPR_IPI_MASK_RESET_1, irq_mask)
#define clear_irqs(irq_mask) __insn_mtspr(SPR_IPI_EVENT_RESET_1, irq_mask)
#define mask_irqs(irq_mask) __insn_mtspr(SPR_IPI_MASK_SET_K, irq_mask)
#define unmask_irqs(irq_mask) __insn_mtspr(SPR_IPI_MASK_RESET_K, irq_mask)
#define clear_irqs(irq_mask) __insn_mtspr(SPR_IPI_EVENT_RESET_K, irq_mask)
#else
/* Use HV to manipulate device interrupts. */
#define mask_irqs(irq_mask) hv_disable_intr(irq_mask)
......@@ -89,16 +89,16 @@ void tile_dev_intr(struct pt_regs *regs, int intnum)
* masked by a previous interrupt. Then, mask out the ones
* we're going to handle.
*/
unsigned long masked = __insn_mfspr(SPR_IPI_MASK_1);
original_irqs = __insn_mfspr(SPR_IPI_EVENT_1) & ~masked;
__insn_mtspr(SPR_IPI_MASK_SET_1, original_irqs);
unsigned long masked = __insn_mfspr(SPR_IPI_MASK_K);
original_irqs = __insn_mfspr(SPR_IPI_EVENT_K) & ~masked;
__insn_mtspr(SPR_IPI_MASK_SET_K, original_irqs);
#else
/*
* Hypervisor performs the equivalent of the Gx code above and
* then puts the pending interrupt mask into a system save reg
* for us to find.
*/
original_irqs = __insn_mfspr(SPR_SYSTEM_SAVE_1_3);
original_irqs = __insn_mfspr(SPR_SYSTEM_SAVE_K_3);
#endif
remaining_irqs = original_irqs;
......@@ -225,7 +225,7 @@ void __cpuinit setup_irq_regs(void)
/* Enable interrupt delivery. */
unmask_irqs(~0UL);
#if CHIP_HAS_IPI()
raw_local_irq_unmask(INT_IPI_1);
raw_local_irq_unmask(INT_IPI_K);
#endif
}
......
......@@ -34,7 +34,7 @@ void __cpuinit init_messaging(void)
panic("hv_register_message_state: error %d", rc);
/* Make sure downcall interrupts will be enabled. */
raw_local_irq_unmask(INT_INTCTRL_1);
raw_local_irq_unmask(INT_INTCTRL_K);
}
void hv_message_intr(struct pt_regs *regs, int intnum)
......
......@@ -214,9 +214,10 @@ int copy_thread(unsigned long clone_flags, unsigned long sp,
/*
* Copy the callee-saved registers from the passed pt_regs struct
* into the context-switch callee-saved registers area.
* We have to restore the callee-saved registers since we may
* be cloning a userspace task with userspace register state,
* and we won't be unwinding the same kernel frames to restore them.
* This way when we start the interrupt-return sequence, the
* callee-save registers will be correctly in registers, which
* is how we assume the compiler leaves them as we start doing
* the normal return-from-interrupt path after calling C code.
* Zero out the C ABI save area to mark the top of the stack.
*/
ksp = (unsigned long) childregs;
......@@ -304,15 +305,25 @@ int dump_task_regs(struct task_struct *tsk, elf_gregset_t *regs)
/* Allow user processes to access the DMA SPRs */
void grant_dma_mpls(void)
{
#if CONFIG_KERNEL_PL == 2
__insn_mtspr(SPR_MPL_DMA_CPL_SET_1, 1);
__insn_mtspr(SPR_MPL_DMA_NOTIFY_SET_1, 1);
#else
__insn_mtspr(SPR_MPL_DMA_CPL_SET_0, 1);
__insn_mtspr(SPR_MPL_DMA_NOTIFY_SET_0, 1);
#endif
}
/* Forbid user processes from accessing the DMA SPRs */
void restrict_dma_mpls(void)
{
#if CONFIG_KERNEL_PL == 2
__insn_mtspr(SPR_MPL_DMA_CPL_SET_2, 1);
__insn_mtspr(SPR_MPL_DMA_NOTIFY_SET_2, 1);
#else
__insn_mtspr(SPR_MPL_DMA_CPL_SET_1, 1);
__insn_mtspr(SPR_MPL_DMA_NOTIFY_SET_1, 1);
#endif
}
/* Pause the DMA engine, then save off its state registers. */
......@@ -523,19 +534,14 @@ struct task_struct *__sched _switch_to(struct task_struct *prev,
* Switch kernel SP, PC, and callee-saved registers.
* In the context of the new task, return the old task pointer
* (i.e. the task that actually called __switch_to).
* Pass the value to use for SYSTEM_SAVE_1_0 when we reset our sp.
* Pass the value to use for SYSTEM_SAVE_K_0 when we reset our sp.
*/
return __switch_to(prev, next, next_current_ksp0(next));
}
long _sys_fork(struct pt_regs *regs)
{
return do_fork(SIGCHLD, regs->sp, regs, 0, NULL, NULL);
}
long _sys_clone(unsigned long clone_flags, unsigned long newsp,
void __user *parent_tidptr, void __user *child_tidptr,
struct pt_regs *regs)
SYSCALL_DEFINE5(clone, unsigned long, clone_flags, unsigned long, newsp,
void __user *, parent_tidptr, void __user *, child_tidptr,
struct pt_regs *, regs)
{
if (!newsp)
newsp = regs->sp;
......@@ -543,18 +549,13 @@ long _sys_clone(unsigned long clone_flags, unsigned long newsp,
parent_tidptr, child_tidptr);
}
long _sys_vfork(struct pt_regs *regs)
{
return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->sp,
regs, 0, NULL, NULL);
}
/*
* sys_execve() executes a new program.
*/
long _sys_execve(const char __user *path,
const char __user *const __user *argv,
const char __user *const __user *envp, struct pt_regs *regs)
SYSCALL_DEFINE4(execve, const char __user *, path,
const char __user *const __user *, argv,
const char __user *const __user *, envp,
struct pt_regs *, regs)
{
long error;
char *filename;
......@@ -570,9 +571,10 @@ long _sys_execve(const char __user *path,
}
#ifdef CONFIG_COMPAT
long _compat_sys_execve(const char __user *path,
long compat_sys_execve(const char __user *path,
const compat_uptr_t __user *argv,
const compat_uptr_t __user *envp, struct pt_regs *regs)
const compat_uptr_t __user *envp,
struct pt_regs *regs)
{
long error;
char *filename;
......
......@@ -31,25 +31,6 @@ void user_disable_single_step(struct task_struct *child)
clear_tsk_thread_flag(child, TIF_SINGLESTEP);
}
/*
* This routine will put a word on the process's privileged stack.
*/
static void putreg(struct task_struct *task,
unsigned long addr, unsigned long value)
{
unsigned int regno = addr / sizeof(unsigned long);
struct pt_regs *childregs = task_pt_regs(task);
childregs->regs[regno] = value;
childregs->flags |= PT_FLAGS_RESTORE_REGS;
}
static unsigned long getreg(struct task_struct *task, unsigned long addr)
{
unsigned int regno = addr / sizeof(unsigned long);
struct pt_regs *childregs = task_pt_regs(task);
return childregs->regs[regno];
}
/*
* Called by kernel/ptrace.c when detaching..
*/
......@@ -66,59 +47,72 @@ void ptrace_disable(struct task_struct *child)
long arch_ptrace(struct task_struct *child, long request, long addr, long data)
{
unsigned long __user *datap;
unsigned long __user *datap = (long __user __force *)data;
unsigned long tmp;
int i;
long ret = -EIO;
#ifdef CONFIG_COMPAT
if (task_thread_info(current)->status & TS_COMPAT)
data = (u32)data;
if (task_thread_info(child)->status & TS_COMPAT)
addr = (u32)addr;
#endif
datap = (unsigned long __user __force *)data;
unsigned long *childregs;
char *childreg;
switch (request) {
case PTRACE_PEEKUSR: /* Read register from pt_regs. */
if (addr & (sizeof(data)-1))
break;
if (addr < 0 || addr >= PTREGS_SIZE)
break;
tmp = getreg(child, addr); /* Read register */
ret = put_user(tmp, datap);
childreg = (char *)task_pt_regs(child) + addr;
#ifdef CONFIG_COMPAT
if (is_compat_task()) {
if (addr & (sizeof(compat_long_t)-1))
break;
ret = put_user(*(compat_long_t *)childreg,
(compat_long_t __user *)datap);
} else
#endif
{
if (addr & (sizeof(long)-1))
break;
ret = put_user(*(long *)childreg, datap);
}
break;
case PTRACE_POKEUSR: /* Write register in pt_regs. */
if (addr & (sizeof(data)-1))
break;
if (addr < 0 || addr >= PTREGS_SIZE)
break;
putreg(child, addr, data); /* Write register */
childreg = (char *)task_pt_regs(child) + addr;
#ifdef CONFIG_COMPAT
if (is_compat_task()) {
if (addr & (sizeof(compat_long_t)-1))
break;
*(compat_long_t *)childreg = data;
} else
#endif
{
if (addr & (sizeof(long)-1))
break;
*(long *)childreg = data;
}
ret = 0;
break;
case PTRACE_GETREGS: /* Get all registers from the child. */
if (!access_ok(VERIFY_WRITE, datap, PTREGS_SIZE))
break;
for (i = 0; i < PTREGS_SIZE; i += sizeof(long)) {
ret = __put_user(getreg(child, i), datap);
childregs = (long *)task_pt_regs(child);
for (i = 0; i < sizeof(struct pt_regs)/sizeof(long); ++i) {
ret = __put_user(childregs[i], &datap[i]);
if (ret != 0)
break;
datap++;
}
break;
case PTRACE_SETREGS: /* Set all registers in the child. */
if (!access_ok(VERIFY_READ, datap, PTREGS_SIZE))
break;
for (i = 0; i < PTREGS_SIZE; i += sizeof(long)) {
ret = __get_user(tmp, datap);
childregs = (long *)task_pt_regs(child);
for (i = 0; i < sizeof(struct pt_regs)/sizeof(long); ++i) {
ret = __get_user(childregs[i], &datap[i]);
if (ret != 0)
break;
putreg(child, i, tmp);
datap++;
}
break;
......
......@@ -85,7 +85,7 @@ STD_ENTRY_SECTION(__switch_to, .sched.text)
{
/* Update sp and ksp0 simultaneously to avoid backtracer warnings. */
move sp, r13
mtspr SYSTEM_SAVE_1_0, r2
mtspr SPR_SYSTEM_SAVE_K_0, r2
}
FOR_EACH_CALLEE_SAVED_REG(LOAD_REG)
.L__switch_to_pc:
......
......@@ -187,11 +187,11 @@ early_param("vmalloc", parse_vmalloc);
#ifdef CONFIG_HIGHMEM
/*
* Determine for each controller where its lowmem is mapped and how
* much of it is mapped there. On controller zero, the first few
* megabytes are mapped at 0xfd000000 as code, so in principle we
* could start our data mappings higher up, but for now we don't
* bother, to avoid additional confusion.
* Determine for each controller where its lowmem is mapped and how much of
* it is mapped there. On controller zero, the first few megabytes are
* already mapped in as code at MEM_SV_INTRPT, so in principle we could
* start our data mappings higher up, but for now we don't bother, to avoid
* additional confusion.
*
* One question is whether, on systems with more than 768 Mb and
* controllers of different sizes, to map in a proportionate amount of
......@@ -311,7 +311,7 @@ static void __init setup_memory(void)
#endif
/* We are using a char to hold the cpu_2_node[] mapping */
BUG_ON(MAX_NUMNODES > 127);
BUILD_BUG_ON(MAX_NUMNODES > 127);
/* Discover the ranges of memory available to us */
for (i = 0; ; ++i) {
......@@ -876,6 +876,9 @@ void __cpuinit setup_cpu(int boot)
#if CHIP_HAS_SN_PROC()
raw_local_irq_unmask(INT_SNITLB_MISS);
#endif
#ifdef __tilegx__
raw_local_irq_unmask(INT_SINGLE_STEP_K);
#endif
/*
* Allow user access to many generic SPRs, like the cycle
......@@ -893,11 +896,12 @@ void __cpuinit setup_cpu(int boot)
#endif
/*
* Set the MPL for interrupt control 0 to user level.
* This includes access to the SYSTEM_SAVE and EX_CONTEXT SPRs,
* as well as the PL 0 interrupt mask.
* Set the MPL for interrupt control 0 & 1 to the corresponding
* values. This includes access to the SYSTEM_SAVE and EX_CONTEXT
* SPRs, as well as the interrupt mask.
*/
__insn_mtspr(SPR_MPL_INTCTRL_0_SET_0, 1);
__insn_mtspr(SPR_MPL_INTCTRL_1_SET_1, 1);
/* Initialize IRQ support for this cpu. */
setup_irq_regs();
......@@ -1033,7 +1037,7 @@ static void __init validate_va(void)
* In addition, make sure we CAN'T use the end of memory, since
* we use the last chunk of each pgd for the pgd_list.
*/
int i, fc_fd_ok = 0;
int i, user_kernel_ok = 0;
unsigned long max_va = 0;
unsigned long list_va =
((PGD_LIST_OFFSET / sizeof(pgd_t)) << PGDIR_SHIFT);
......@@ -1044,13 +1048,13 @@ static void __init validate_va(void)
break;
if (range.start <= MEM_USER_INTRPT &&
range.start + range.size >= MEM_HV_INTRPT)
fc_fd_ok = 1;
user_kernel_ok = 1;
if (range.start == 0)
max_va = range.size;
BUG_ON(range.start + range.size > list_va);
}
if (!fc_fd_ok)
early_panic("Hypervisor not configured for VAs 0xfc/0xfd\n");
if (!user_kernel_ok)
early_panic("Hypervisor not configured for user/kernel VAs\n");
if (max_va == 0)
early_panic("Hypervisor not configured for low VAs\n");
if (max_va < KERNEL_HIGH_VADDR)
......@@ -1334,6 +1338,10 @@ static void __init pcpu_fc_populate_pte(unsigned long addr)
pte_t *pte;
BUG_ON(pgd_addr_invalid(addr));
if (addr < VMALLOC_START || addr >= VMALLOC_END)
panic("PCPU addr %#lx outside vmalloc range %#lx..%#lx;"
" try increasing CONFIG_VMALLOC_RESERVE\n",
addr, VMALLOC_START, VMALLOC_END);
pgd = swapper_pg_dir + pgd_index(addr);
pud = pud_offset(pgd, addr);
......
......@@ -41,8 +41,8 @@
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
long _sys_sigaltstack(const stack_t __user *uss,
stack_t __user *uoss, struct pt_regs *regs)
SYSCALL_DEFINE3(sigaltstack, const stack_t __user *, uss,
stack_t __user *, uoss, struct pt_regs *, regs)
{
return do_sigaltstack(uss, uoss, regs->sp);
}
......@@ -78,7 +78,7 @@ int restore_sigcontext(struct pt_regs *regs,
}
/* sigreturn() returns long since it restores r0 in the interrupted code. */
long _sys_rt_sigreturn(struct pt_regs *regs)
SYSCALL_DEFINE1(rt_sigreturn, struct pt_regs *, regs)
{
struct rt_sigframe __user *frame =
(struct rt_sigframe __user *)(regs->sp);
......
......@@ -15,7 +15,7 @@
* Derived from iLib's single-stepping code.
*/
#ifndef __tilegx__ /* No support for single-step yet. */
#ifndef __tilegx__ /* Hardware support for single step unavailable. */
/* These functions are only used on the TILE platform */
#include <linux/slab.h>
......@@ -660,4 +660,75 @@ void single_step_once(struct pt_regs *regs)
regs->pc += 8;
}
#else
#include <linux/smp.h>
#include <linux/ptrace.h>
#include <arch/spr_def.h>
static DEFINE_PER_CPU(unsigned long, ss_saved_pc);
/*
* Called directly on the occasion of an interrupt.
*
* If the process doesn't have single step set, then we use this as an
* opportunity to turn single step off.
*
* It has been mentioned that we could conditionally turn off single stepping
* on each entry into the kernel and rely on single_step_once to turn it
* on for the processes that matter (as we already do), but this
* implementation is somewhat more efficient in that we muck with registers
* once on a bum interrupt rather than on every entry into the kernel.
*
* If SINGLE_STEP_CONTROL_K has CANCELED set, then an interrupt occurred,
* so we have to run through this process again before we can say that an
* instruction has executed.
*
* swint will set CANCELED, but it's a legitimate instruction. Fortunately
* it changes the PC. If it hasn't changed, then we know that the interrupt
* wasn't generated by swint and we'll need to run this process again before
* we can say an instruction has executed.
*
* If either CANCELED == 0 or the PC's changed, we send out SIGTRAPs and get
* on with our lives.
*/
void gx_singlestep_handle(struct pt_regs *regs, int fault_num)
{
unsigned long *ss_pc = &__get_cpu_var(ss_saved_pc);
struct thread_info *info = (void *)current_thread_info();
int is_single_step = test_ti_thread_flag(info, TIF_SINGLESTEP);
unsigned long control = __insn_mfspr(SPR_SINGLE_STEP_CONTROL_K);
if (is_single_step == 0) {
__insn_mtspr(SPR_SINGLE_STEP_EN_K_K, 0);
} else if ((*ss_pc != regs->pc) ||
(!(control & SPR_SINGLE_STEP_CONTROL_1__CANCELED_MASK))) {
ptrace_notify(SIGTRAP);
control |= SPR_SINGLE_STEP_CONTROL_1__CANCELED_MASK;
control |= SPR_SINGLE_STEP_CONTROL_1__INHIBIT_MASK;
__insn_mtspr(SPR_SINGLE_STEP_CONTROL_K, control);
}
}
/*
* Called from need_singlestep. Set up the control registers and the enable
* register, then return back.
*/
void single_step_once(struct pt_regs *regs)
{
unsigned long *ss_pc = &__get_cpu_var(ss_saved_pc);
unsigned long control = __insn_mfspr(SPR_SINGLE_STEP_CONTROL_K);
*ss_pc = regs->pc;
control |= SPR_SINGLE_STEP_CONTROL_1__CANCELED_MASK;
control |= SPR_SINGLE_STEP_CONTROL_1__INHIBIT_MASK;
__insn_mtspr(SPR_SINGLE_STEP_CONTROL_K, control);
__insn_mtspr(SPR_SINGLE_STEP_EN_K_K, 1 << USER_PL);
}
#endif /* !__tilegx__ */
......@@ -212,7 +212,7 @@ void __init ipi_init(void)
tile.x = cpu_x(cpu);
tile.y = cpu_y(cpu);
if (hv_get_ipi_pte(tile, 1, &pte) != 0)
if (hv_get_ipi_pte(tile, KERNEL_PL, &pte) != 0)
panic("Failed to initialize IPI for cpu %d\n", cpu);
offset = hv_pte_get_pfn(pte) << PAGE_SHIFT;
......
......@@ -30,6 +30,10 @@
#include <arch/abi.h>
#include <arch/interrupts.h>
#define KBT_ONGOING 0 /* Backtrace still ongoing */
#define KBT_DONE 1 /* Backtrace cleanly completed */
#define KBT_RUNNING 2 /* Can't run backtrace on a running task */
#define KBT_LOOP 3 /* Backtrace entered a loop */
/* Is address on the specified kernel stack? */
static int in_kernel_stack(struct KBacktraceIterator *kbt, VirtualAddress sp)
......@@ -207,11 +211,11 @@ static int KBacktraceIterator_next_item_inclusive(
for (;;) {
do {
if (!KBacktraceIterator_is_sigreturn(kbt))
return 1;
return KBT_ONGOING;
} while (backtrace_next(&kbt->it));
if (!KBacktraceIterator_restart(kbt))
return 0;
return KBT_DONE;
}
}
......@@ -264,7 +268,7 @@ void KBacktraceIterator_init(struct KBacktraceIterator *kbt,
kbt->pgtable = NULL;
kbt->verbose = 0; /* override in caller if desired */
kbt->profile = 0; /* override in caller if desired */
kbt->end = 0;
kbt->end = KBT_ONGOING;
kbt->new_context = 0;
if (is_current) {
HV_PhysAddr pgdir_pa = hv_inquire_context().page_table;
......@@ -290,7 +294,7 @@ void KBacktraceIterator_init(struct KBacktraceIterator *kbt,
if (regs == NULL) {
if (is_current || t->state == TASK_RUNNING) {
/* Can't do this; we need registers */
kbt->end = 1;
kbt->end = KBT_RUNNING;
return;
}
pc = get_switch_to_pc();
......@@ -305,26 +309,29 @@ void KBacktraceIterator_init(struct KBacktraceIterator *kbt,
}
backtrace_init(&kbt->it, read_memory_func, kbt, pc, lr, sp, r52);
kbt->end = !KBacktraceIterator_next_item_inclusive(kbt);
kbt->end = KBacktraceIterator_next_item_inclusive(kbt);
}
EXPORT_SYMBOL(KBacktraceIterator_init);
int KBacktraceIterator_end(struct KBacktraceIterator *kbt)
{
return kbt->end;
return kbt->end != KBT_ONGOING;
}
EXPORT_SYMBOL(KBacktraceIterator_end);
void KBacktraceIterator_next(struct KBacktraceIterator *kbt)
{
VirtualAddress old_pc = kbt->it.pc, old_sp = kbt->it.sp;
kbt->new_context = 0;
if (!backtrace_next(&kbt->it) &&
!KBacktraceIterator_restart(kbt)) {
kbt->end = 1;
if (!backtrace_next(&kbt->it) && !KBacktraceIterator_restart(kbt)) {
kbt->end = KBT_DONE;
return;
}
kbt->end = !KBacktraceIterator_next_item_inclusive(kbt);
kbt->end = KBacktraceIterator_next_item_inclusive(kbt);
if (old_pc == kbt->it.pc && old_sp == kbt->it.sp) {
/* Trapped in a loop; give up. */
kbt->end = KBT_LOOP;
}
}
EXPORT_SYMBOL(KBacktraceIterator_next);
......@@ -387,6 +394,8 @@ void tile_show_stack(struct KBacktraceIterator *kbt, int headers)
break;
}
}
if (kbt->end == KBT_LOOP)
pr_err("Stack dump stopped; next frame identical to this one\n");
if (headers)
pr_err("Stack dump complete\n");
}
......
......@@ -110,6 +110,15 @@ SYSCALL_DEFINE6(mmap, unsigned long, addr, unsigned long, len,
#define sys_sync_file_range sys_sync_file_range2
#endif
/* Call the trampolines to manage pt_regs where necessary. */
#define sys_execve _sys_execve
#define sys_sigaltstack _sys_sigaltstack
#define sys_rt_sigreturn _sys_rt_sigreturn
#define sys_clone _sys_clone
#ifndef __tilegx__
#define sys_cmpxchg_badaddr _sys_cmpxchg_badaddr
#endif
/*
* Note that we can't include <linux/unistd.h> here since the header
* guard will defeat us; <asm/unistd.h> checks for __SYSCALL as well.
......
......@@ -260,7 +260,7 @@ void __kprobes do_trap(struct pt_regs *regs, int fault_num,
address = regs->pc;
break;
case INT_UNALIGN_DATA:
#ifndef __tilegx__ /* FIXME: GX: no single-step yet */
#ifndef __tilegx__ /* Emulated support for single step debugging */
if (unaligned_fixup >= 0) {
struct single_step_state *state =
current_thread_info()->step_state;
......@@ -278,7 +278,7 @@ void __kprobes do_trap(struct pt_regs *regs, int fault_num,
case INT_DOUBLE_FAULT:
/*
* For double fault, "reason" is actually passed as
* SYSTEM_SAVE_1_2, the hypervisor's double-fault info, so
* SYSTEM_SAVE_K_2, the hypervisor's double-fault info, so
* we can provide the original fault number rather than
* the uninteresting "INT_DOUBLE_FAULT" so the user can
* learn what actually struck while PL0 ICS was set.
......
#
# KVM configuration
#
source "virt/kvm/Kconfig"
menuconfig VIRTUALIZATION
bool "Virtualization"
---help---
Say Y here to get to see options for using your Linux host to run
other operating systems inside virtual machines (guests).
This option alone does not add any kernel code.
If you say N, all options in this submenu will be skipped and
disabled.
if VIRTUALIZATION
config KVM
tristate "Kernel-based Virtual Machine (KVM) support"
depends on HAVE_KVM && MODULES && EXPERIMENTAL
select PREEMPT_NOTIFIERS
select ANON_INODES
---help---
Support hosting paravirtualized guest machines.
This module provides access to the hardware capabilities through
a character device node named /dev/kvm.
To compile this as a module, choose M here: the module
will be called kvm.
If unsure, say N.
source drivers/vhost/Kconfig
source drivers/virtio/Kconfig
endif # VIRTUALIZATION
......@@ -3,8 +3,8 @@
#
lib-y = cacheflush.o checksum.o cpumask.o delay.o \
mb_incoherent.o uaccess.o \
memcpy_$(BITS).o memchr_$(BITS).o memmove_$(BITS).o memset_$(BITS).o \
mb_incoherent.o uaccess.o memmove.o \
memcpy_$(BITS).o memchr_$(BITS).o memset_$(BITS).o \
strchr_$(BITS).o strlen_$(BITS).o
ifeq ($(CONFIG_TILEGX),y)
......
......@@ -300,7 +300,7 @@ void __init __init_atomic_per_cpu(void)
#else /* ATOMIC_LOCKS_FOUND_VIA_TABLE() */
/* Validate power-of-two and "bigger than cpus" assumption */
BUG_ON(ATOMIC_HASH_SIZE & (ATOMIC_HASH_SIZE-1));
BUILD_BUG_ON(ATOMIC_HASH_SIZE & (ATOMIC_HASH_SIZE-1));
BUG_ON(ATOMIC_HASH_SIZE < nr_cpu_ids);
/*
......@@ -314,17 +314,17 @@ void __init __init_atomic_per_cpu(void)
BUG_ON((unsigned long)atomic_locks % PAGE_SIZE != 0);
/* The locks must all fit on one page. */
BUG_ON(ATOMIC_HASH_SIZE * sizeof(int) > PAGE_SIZE);
BUILD_BUG_ON(ATOMIC_HASH_SIZE * sizeof(int) > PAGE_SIZE);
/*
* We use the page offset of the atomic value's address as
* an index into atomic_locks, excluding the low 3 bits.
* That should not produce more indices than ATOMIC_HASH_SIZE.
*/
BUG_ON((PAGE_SIZE >> 3) > ATOMIC_HASH_SIZE);
BUILD_BUG_ON((PAGE_SIZE >> 3) > ATOMIC_HASH_SIZE);
#endif /* ATOMIC_LOCKS_FOUND_VIA_TABLE() */
/* The futex code makes this assumption, so we validate it here. */
BUG_ON(sizeof(atomic_t) != sizeof(int));
BUILD_BUG_ON(sizeof(atomic_t) != sizeof(int));
}
......@@ -45,6 +45,9 @@ EXPORT_SYMBOL(__copy_from_user_zeroing);
EXPORT_SYMBOL(__copy_in_user_inatomic);
#endif
/* arch/tile/lib/mb_incoherent.S */
EXPORT_SYMBOL(__mb_incoherent);
/* hypervisor glue */
#include <hv/hypervisor.h>
EXPORT_SYMBOL(hv_dev_open);
......
......@@ -10,14 +10,16 @@
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
* NON INFRINGEMENT. See the GNU General Public License for
* more details.
*
* This file shares the implementation of the userspace memcpy and
* the kernel's memcpy, copy_to_user and copy_from_user.
*/
#include <arch/chip.h>
/*
* This file shares the implementation of the userspace memcpy and
* the kernel's memcpy, copy_to_user and copy_from_user.
*/
#include <linux/linkage.h>
/* On TILE64, we wrap these functions via arch/tile/lib/memcpy_tile64.c */
......
......@@ -18,6 +18,7 @@
#include <linux/string.h>
#include <linux/module.h>
#undef memset
void *memset(void *s, int c, size_t n)
{
......
......@@ -16,6 +16,8 @@
#include <linux/string.h>
#include <linux/module.h>
#undef strlen
size_t strlen(const char *s)
{
/* Get an aligned pointer. */
......
......@@ -66,10 +66,10 @@ static noinline void force_sig_info_fault(int si_signo, int si_code,
#ifndef __tilegx__
/*
* Synthesize the fault a PL0 process would get by doing a word-load of
* an unaligned address or a high kernel address. Called indirectly
* from sys_cmpxchg() in kernel/intvec.S.
* an unaligned address or a high kernel address.
*/
int _sys_cmpxchg_badaddr(unsigned long address, struct pt_regs *regs)
SYSCALL_DEFINE2(cmpxchg_badaddr, unsigned long, address,
struct pt_regs *, regs)
{
if (address >= PAGE_OFFSET)
force_sig_info_fault(SIGSEGV, SEGV_MAPERR, address,
......@@ -563,10 +563,10 @@ static int handle_page_fault(struct pt_regs *regs,
/*
* When we take an ITLB or DTLB fault or access violation in the
* supervisor while the critical section bit is set, the hypervisor is
* reluctant to write new values into the EX_CONTEXT_1_x registers,
* reluctant to write new values into the EX_CONTEXT_K_x registers,
* since that might indicate we have not yet squirreled the SPR
* contents away and can thus safely take a recursive interrupt.
* Accordingly, the hypervisor passes us the PC via SYSTEM_SAVE_1_2.
* Accordingly, the hypervisor passes us the PC via SYSTEM_SAVE_K_2.
*
* Note that this routine is called before homecache_tlb_defer_enter(),
* which means that we can properly unlock any atomics that might
......@@ -610,7 +610,7 @@ struct intvec_state do_page_fault_ics(struct pt_regs *regs, int fault_num,
* fault. We didn't set up a kernel stack on initial entry to
* sys_cmpxchg, but instead had one set up by the fault, which
* (because sys_cmpxchg never releases ICS) came to us via the
* SYSTEM_SAVE_1_2 mechanism, and thus EX_CONTEXT_1_[01] are
* SYSTEM_SAVE_K_2 mechanism, and thus EX_CONTEXT_K_[01] are
* still referencing the original user code. We release the
* atomic lock and rewrite pt_regs so that it appears that we
* came from user-space directly, and after we finish the
......
......@@ -37,6 +37,8 @@
#include <asm/pgalloc.h>
#include <asm/homecache.h>
#include <arch/sim.h>
#include "migrate.h"
......@@ -217,13 +219,6 @@ static unsigned long cache_flush_length(unsigned long length)
return (length >= CHIP_L2_CACHE_SIZE()) ? HV_FLUSH_EVICT_L2 : length;
}
/* On the simulator, confirm lines have been evicted everywhere. */
static void validate_lines_evicted(unsigned long pfn, size_t length)
{
sim_syscall(SIM_SYSCALL_VALIDATE_LINES_EVICTED,
(HV_PhysAddr)pfn << PAGE_SHIFT, length);
}
/* Flush a page out of whatever cache(s) it is in. */
void homecache_flush_cache(struct page *page, int order)
{
......@@ -234,7 +229,7 @@ void homecache_flush_cache(struct page *page, int order)
homecache_mask(page, pages, &home_mask);
flush_remote(pfn, length, &home_mask, 0, 0, 0, NULL, NULL, 0);
validate_lines_evicted(pfn, pages * PAGE_SIZE);
sim_validate_lines_evicted(PFN_PHYS(pfn), pages * PAGE_SIZE);
}
......
......@@ -1060,7 +1060,7 @@ void free_initmem(void)
/*
* Free the pages mapped from 0xc0000000 that correspond to code
* pages from 0xfd000000 that we won't use again after init.
* pages from MEM_SV_INTRPT that we won't use again after init.
*/
free_init_pages("unused kernel text",
(unsigned long)_sinittext - text_delta,
......
......@@ -61,7 +61,8 @@ console_initcall(hvc_tile_console_init);
static int __init hvc_tile_init(void)
{
hvc_alloc(0, 0, &hvc_tile_get_put_ops, 128);
return 0;
struct hvc_struct *s;
s = hvc_alloc(0, 0, &hvc_tile_get_put_ops, 128);
return IS_ERR(s) ? PTR_ERR(s) : 0;
}
device_initcall(hvc_tile_init);
......@@ -374,7 +374,7 @@ config SLUB_STATS
config DEBUG_KMEMLEAK
bool "Kernel memory leak detector"
depends on DEBUG_KERNEL && EXPERIMENTAL && !MEMORY_HOTPLUG && \
(X86 || ARM || PPC || S390 || SPARC64 || SUPERH || MICROBLAZE)
(X86 || ARM || PPC || S390 || SPARC64 || SUPERH || MICROBLAZE || TILE)
select DEBUG_FS if SYSFS
select STACKTRACE if STACKTRACE_SUPPORT
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment