arch/tile/Kconfig: rename tile_defconfig to tilepro_defconfig
Subsystems (4)
A message that is not in the archive (sent off-list or not yet received): 4F761E1C.80808.com
PATCH 1/1 arch/tile/Kconfig: rename tile_defconfig to tilepro_defconfig
We switched to using "tilepro" for the 32-bit stuff a while ago, but missed this one usage.
--- arch/tile/Kconfig | 5 ++++- 1 files changed, 4 insertions(+), 1 deletions(-)
arch/tile/Kconfig +4 -1
@@ -69,6 +69,9 @@ config ARCH_PHYS_ADDR_T_64BIT config ARCH_DMA_ADDR_T_64BIT def_bool y +config NEED_DMA_MAP_STATE + def_bool y + config LOCKDEP_SUPPORT def_bool y
@@ -118,7 +121,7 @@ config 64BIT config ARCH_DEFCONFIG string - default "arch/tile/configs/tile_defconfig" if !TILEGX + default "arch/tile/configs/tilepro_defconfig" if !TILEGX default "arch/tile/configs/tilegx_defconfig" if TILEGX source "init/Kconfig"
Signature · 1 line
1.6.5.2
PATCH 1/1 arch/tile/Kconfig: don't specify CONFIG_PAGE_OFFSET for 64-bit builds
In reply to a message not in the archiveIt's fixed at half the VA space and there's no point in configuring it.
--- arch/tile/Kconfig | 1 + 1 files changed, 1 insertions(+), 0 deletions(-)
arch/tile/Kconfig +1 -0
@@ -243,6 +243,7 @@ endchoice config PAGE_OFFSET hex + depends on !64BIT default 0xF0000000 if VMSPLIT_3_75G default 0xE0000000 if VMSPLIT_3_5G default 0xB0000000 if VMSPLIT_2_75G
Signature · 1 line
1.6.5.2
PATCH 1/1 arch/tile: fix a couple of comments that needed updating
In reply to a message not in the archiveNot associated with any code changes, so I'm just lumping these comment changes into a commit by themselves.
--- arch/tile/kernel/setup.c | 11 +++++++++-- arch/tile/mm/fault.c | 2 +- 2 files changed, 10 insertions(+), 3 deletions(-)
arch/tile/kernel/setup.c +9 -2
@@ -913,6 +913,13 @@ void __cpuinit setup_cpu(int boot)#ifdef CONFIG_BLK_DEV_INITRD +/* +* Note that the kernel can potentially support other compression +* techniques than gz, though we don't do so by default. If we ever +* decide to do so we can either look for other filename extensions, +* or just allow a file with this name to be compressed with an +* arbitrary compressor (somewhat counterintuitively). +*/ static int __initdata set_initramfs_file;static char __initdata initramfs_file[128 ] ="initramfs.cpio.gz" ;
@@ -928,9 +935,9 @@ static int __init setup_initramfs_file(char *str)early_param ("initramfs_file" , setup_initramfs_file);/* -* We look for an additional "initramfs.cpio.gz" file in the hvfs. +* We look for an "initramfs.cpio.gz" file in the hvfs. * If there is one, we allocate some memory for it and it will be -* unpacked to the initramfs after any built-in initramfs_data. +* unpacked to the initramfs. */ static void __init load_hv_initrd (void ) {
arch/tile/mm/fault.c +1 -1
@@ -131,7 +131,7 @@ static inline pmd_t *vmalloc_sync_one(pgd_t *pgd, unsigned long address) }/* -* Handle a fault on the vmalloc or module mapping area +* Handle a fault on the vmalloc area. */ static inline int vmalloc_fault (pgd_t *pgd,unsigned long address) {
Signature · 1 line
1.6.5.2
PATCH 1/1 arch/tile/Makefile: use KCFLAGS when figuring out the libgcc path.
In reply to a message not in the archive--- arch/tile/Makefile | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-)
arch/tile/Makefile +2 -1
@@ -30,7 +30,8 @@ ifneq ($(CONFIG_DEBUG_EXTRA_FLAGS),"") KBUILD_CFLAGS += $(CONFIG_DEBUG_EXTRA_FLAGS) endif -LIBGCC_PATH := $(shell $(CC) $(KBUILD_CFLAGS) -print-libgcc-file-name) +LIBGCC_PATH := \ + $(shell $(CC) $(KBUILD_CFLAGS) $(KCFLAGS) -print-libgcc-file-name) # Provide the path to use for "make defconfig". KBUILD_DEFCONFIG := $(ARCH)_defconfig
Signature · 1 line
1.6.5.2
PATCH 1/1 arch/tile: don't leak kernel memory when we unload modules
In reply to a message not in the archiveWe were failing to track the memory when we allocated it.
--- arch/tile/kernel/module.c | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-)
arch/tile/kernel/module.c +2 -0
@@ -67,6 +67,8 @@ void *module_alloc(unsigned long size) area =__get_vm_area (size,VM_ALLOC ,MEM_MODULE_START ,MEM_MODULE_END );if (!area) goto error; + area->nr_pages = npages; + area->pages = pages;if (map_vm_area (area, prot_rwx, &pages)) {vunmap (area->addr);
Signature · 1 line
1.6.5.2
PATCH 1/1 arch/tile: fix bug in delay_backoff()
In reply to a message not in the archiveWe were carefully computing a value to use for the number of loops to spin for, and then ignoring it.
--- arch/tile/lib/spinlock_common.h | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
arch/tile/lib/spinlock_common.h +1 -1
@@ -60,5 +60,5 @@ static void delay_backoff(int iterations) loops +=__insn_crc32_32 (stack_pointer,get_cycles_low ()) & (loops -1 ); -relax (1 << exponent); +relax (loops); }
Signature · 1 line
1.6.5.2
PATCH 1/1 arch/tile: remove references to cpu_*_map.
In reply to a message not in the archiveThis has been obsolescent for a while; time for the final push.
--- arch/tile/kernel/setup.c | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-)
arch/tile/kernel/setup.c +3 -3
@@ -1244,7 +1244,7 @@ static void __init setup_cpu_maps(void) sizeof(cpu_lotar_map));if (rc <0 ) {pr_err ("warning: no HV_INQ_TILES_LOTAR; using AVAIL\n" ); - cpu_lotar_map = cpu_possible_map; + cpu_lotar_map = *cpu_possible_mask; }#if CHIP_HAS_CBOX_HOME_MAP ()
@@ -1254,9 +1254,9 @@ static void __init setup_cpu_maps(void) sizeof(hash_for_home_map));if (rc <0 )early_panic ("hv_inquire_tiles(HFH_CACHE) failed: rc %d\n" , rc); -cpumask_or (&cpu_cacheable_map, &cpu_possible_map, &hash_for_home_map); +cpumask_or (&cpu_cacheable_map, cpu_possible_mask, &hash_for_home_map);#else - cpu_cacheable_map = cpu_possible_map; + cpu_cacheable_map = *cpu_possible_mask;#endif }
Signature · 1 line
1.6.5.2
PATCH 1/1 arch/tile: remove bogus performance optimization
In reply to a message not in the archiveWe were re-homing the initial task's kernel stack on the boot cpu, but in fact it's better to let it stay globally homed, since that task isn't bound to the boot cpu anyway. This is more of a general cleanup than an actual performance optimization, but it removes code, which is a good thing. :-)
--- arch/tile/mm/init.c | 5 ----- 1 files changed, 0 insertions(+), 5 deletions(-)
arch/tile/mm/init.c +0 -5
@@ -250,11 +250,6 @@ static pgprot_t __init init_pgprot(ulong address)return construct_pgprot (PAGE_KERNEL_RO ,PAGE_HOME_IMMUTABLE ); } -/* As a performance optimization, keep the boot init stack here. */ -if (address >= (ulong)&init_thread_union && - address < (ulong)&init_thread_union +THREAD_SIZE ) -return construct_pgprot (PAGE_KERNEL ,smp_processor_id ()); -#ifndef __tilegx__#if !ATOMIC_LOCKS_FOUND_VIA_TABLE ()/* Force the atomic_locks[] array page to be hash-for-home. */
Signature · 1 line
1.6.5.2
PATCH 1/1 arch/tile: avoid accidentally unmasking NMI-type interrupt accidentally
In reply to a message not in the archiveThe return path as we reload registers and core state requires that r30 hold a boolean indicating whether we are returning from an NMI, but in a couple of cases we weren't setting this properly, with the result that we could accidentally unmask the NMI interrupt(s), which could cause confusion. Now we set r30 in every place where we jump into the interrupt return path.
--- arch/tile/kernel/intvec_32.S | 24 ++++++++++++++++++++---- arch/tile/kernel/intvec_64.S | 19 ++++++++++++++++--- 2 files changed, 36 insertions(+), 7 deletions(-)
arch/tile/kernel/intvec_32.S +20 -4
@@ -799,6 +799,10 @@ handle_interrupt: * This routine takes a boolean in r30 indicating if this is an NMI. * If so, we also expect a boolean in r31 indicating whether to * re-enable the oprofile interrupts. + * + * Note that .Lresume_userspace is jumped to directly in several + * places, and we need to make sure r30 is set correctly in those + * callers as well. */ STD_ENTRY(interrupt_return) /* If we're resuming to kernel space, don't check thread flags. */
@@ -1237,7 +1241,10 @@ handle_syscall: bzt r30, 1f jal do_syscall_trace FEEDBACK_REENTER(handle_syscall) -1: j .Lresume_userspace /* jump into middle of interrupt_return */ +1: { + movei r30, 0 /* not an NMI */ + j .Lresume_userspace /* jump into middle of interrupt_return */ + } .Linvalid_syscall: /* Report an invalid syscall back to the user program */
@@ -1246,7 +1253,10 @@ handle_syscall: movei r28, -ENOSYS } sw r29, r28 - j .Lresume_userspace /* jump into middle of interrupt_return */ + { + movei r30, 0 /* not an NMI */ + j .Lresume_userspace /* jump into middle of interrupt_return */ + } STD_ENDPROC(handle_syscall) /* Return the address for oprofile to suppress in backtraces. */
@@ -1262,7 +1272,10 @@ STD_ENTRY(ret_from_fork) jal sim_notify_fork jal schedule_tail FEEDBACK_REENTER(ret_from_fork) - j .Lresume_userspace /* jump into middle of interrupt_return */ + { + movei r30, 0 /* not an NMI */ + j .Lresume_userspace /* jump into middle of interrupt_return */ + } STD_ENDPROC(ret_from_fork) /*
@@ -1376,7 +1389,10 @@ handle_ill: jal send_sigtrap /* issue a SIGTRAP */ FEEDBACK_REENTER(handle_ill) - j .Lresume_userspace /* jump into middle of interrupt_return */ + { + movei r30, 0 /* not an NMI */ + j .Lresume_userspace /* jump into middle of interrupt_return */ + } .Ldispatch_normal_ill: {
arch/tile/kernel/intvec_64.S +16 -3
@@ -614,6 +614,10 @@ handle_interrupt: * This routine takes a boolean in r30 indicating if this is an NMI. * If so, we also expect a boolean in r31 indicating whether to * re-enable the oprofile interrupts. + * + * Note that .Lresume_userspace is jumped to directly in several + * places, and we need to make sure r30 is set correctly in those + * callers as well. */ STD_ENTRY(interrupt_return) /* If we're resuming to kernel space, don't check thread flags. */
@@ -1066,7 +1070,10 @@ handle_syscall: } FEEDBACK_REENTER(handle_syscall) -2: j .Lresume_userspace /* jump into middle of interrupt_return */ +2: { + movei r30, 0 /* not an NMI */ + j .Lresume_userspace /* jump into middle of interrupt_return */ + } .Lcompat_syscall: /*
@@ -1100,7 +1107,10 @@ handle_syscall: movei r28, -ENOSYS } st r29, r28 - j .Lresume_userspace /* jump into middle of interrupt_return */ + { + movei r30, 0 /* not an NMI */ + j .Lresume_userspace /* jump into middle of interrupt_return */ + } STD_ENDPROC(handle_syscall) /* Return the address for oprofile to suppress in backtraces. */
@@ -1116,7 +1126,10 @@ STD_ENTRY(ret_from_fork) jal sim_notify_fork jal schedule_tail FEEDBACK_REENTER(ret_from_fork) - j .Lresume_userspace + { + movei r30, 0 /* not an NMI */ + j .Lresume_userspace /* jump into middle of interrupt_return */ + } STD_ENDPROC(ret_from_fork) /* Various stub interrupt handlers and syscall handlers */
Signature · 1 line
1.6.5.2
PATCH 1/1 arch/tile: revert comment for atomic64_add_unless().
In reply to a message not in the archiveIt still returns whether @v was not @u, not the the old value, unlike __atomic_add_unless().
--- arch/tile/include/asm/atomic_32.h | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
arch/tile/include/asm/atomic_32.h +1 -1
@@ -199,7 +199,7 @@ static inline u64 atomic64_add_return(u64 i, atomic64_t *v)* @u: ...unless v is equal to u. * * Atomically adds @a to @v, so long as @v was not already @u. -* Returns the old value of @v. +* Returns non-zero if @v was not @u, and zero otherwise. */ static inline u64 atomic64_add_unless (atomic64_t *v,u64 a,u64 u) {
Signature · 1 line
1.6.5.2
Re: [PATCH] arch/tile: revert comment for atomic64_add_unless().
arch/tile/include/asm/atomic_32.h static inline u64 atomic64_add_return(u64 i, atomic64_t *v) · line 205
Quoted 11 lines · Chris Metcalf
arch/tile/include/asm/atomic_32.h +1
-1@@ -199,7 +199,7 @@ static inline u64 atomic64_add_return(u64 i, atomic64_t *v)* @u: ...unless v is equal to u. * * Atomically adds @a to @v, so long as @v was not already @u. -* Returns the old value of @v. +* Returns non-zero if @v was not @u, and zero otherwise. */ static inline u64 atomic64_add_unless (atomic64_t *v,u64 a,u64 u) {
PATCH 1/1 arch/tile: add descriptive text if the kernel reports a bad trap
In reply to a message not in the archiveIf the kernel unexpectedly takes a bad trap, it's convenient to have it report the type of trap as part of the error. This gives customers a bit more context before they call up customer support.
--- arch/tile/kernel/traps.c | 30 ++++++++++++++++++++++++++++-- 1 files changed, 28 insertions(+), 2 deletions(-)
arch/tile/kernel/traps.c +28 -2
@@ -194,6 +194,25 @@ static int special_ill(bundle_bits bundle, int *sigp, int *codep)return 1 ; } +static const char *const int_name[] = { + [INT_MEM_ERROR ] ="Memory error" , + [INT_ILL ] ="Illegal instruction" , + [INT_GPV ] ="General protection violation" , + [INT_UDN_ACCESS ] ="UDN access" , + [INT_IDN_ACCESS ] ="IDN access" , +#if CHIP_HAS_SN() + [INT_SN_ACCESS ] ="SN access" , +#endif + [INT_SWINT_3 ] ="Software interrupt 3" , + [INT_SWINT_2 ] ="Software interrupt 2" , + [INT_SWINT_0 ] ="Software interrupt 0" , + [INT_UNALIGN_DATA ] ="Unaligned data" , + [INT_DOUBLE_FAULT ] ="Double fault" , +#ifdef __tilegx__ + [INT_ILL_TRANS ] ="Illegal virtual address" , +#endif +}; +void __kprobes do_trap (struct pt_regs *regs,int fault_num,unsigned long reason) {
@@ -210,10 +229,17 @@ void __kprobes do_trap(struct pt_regs *regs, int fault_num,* current process and hope for the best. */ if (!user_mode (regs)) { +const char *name;if (fixup_exception (regs))/* only UNALIGN_DATA in practice */ return ; -pr_alert ("Kernel took bad trap %d at PC %#lx\n" , - fault_num, regs->pc); +if (fault_num >=0 && + fault_num <sizeof (int_name)/sizeof (int_name[0 ]) && + int_name[fault_num] !=NULL ) + name = int_name[fault_num]; +else + name ="Unknown interrupt" ; +pr_alert ("Kernel took bad trap %d (%s) at PC %#lx\n" , + fault_num, name, regs->pc);if (fault_num ==INT_GPV )pr_alert ("GPV_REASON is %#lx\n" , reason);show_regs (regs);
Signature · 1 line
1.6.5.2
PATCH 1/1 arch/tile: return SIGBUS for addresses that are unaligned AND invalid
In reply to a message not in the archivePreviously we were returning SIGSEGV in this case. It seems cleaner to return SIGBUS since the hardware figures out alignment traps before TLB violations, so SIGBUS is the "more correct" signal.
--- arch/tile/kernel/single_step.c | 31 +++++++++++++++++++------------ 1 files changed, 19 insertions(+), 12 deletions(-)
arch/tile/kernel/single_step.c +19 -12
@@ -152,6 +152,25 @@ static tile_bundle_bits rewrite_load_store_unaligned(if (((unsigned long )addr % size) ==0 )return bundle; +/* +* Return SIGBUS with the unaligned address, if requested. +* Note that we return SIGBUS even for completely invalid addresses +* as long as they are in fact unaligned; this matches what the +* tilepro hardware would be doing, if it could provide us with the +* actual bad address in an SPR, which it doesn't. +*/ +if (unaligned_fixup ==0 ) { +siginfo_t info = { + .si_signo =SIGBUS , + .si_code =BUS_ADRALN , + .si_addr = addr + }; +trace_unhandled_signal ("unaligned trap" , regs, + (unsigned long )addr,SIGBUS ); +force_sig_info (info.si_signo, &info, current); +return (tilepro_bundle_bits )0 ; + } +/* Handle unaligned load/store */ if (mem_op ==MEMOP_LOAD || mem_op ==MEMOP_LOAD_POSTINCR ) {unsigned short val_16;
@@ -199,18 +218,6 @@ static tile_bundle_bits rewrite_load_store_unaligned(return (tile_bundle_bits )0 ; } -if (unaligned_fixup ==0 ) { -siginfo_t info = { - .si_signo =SIGBUS , - .si_code =BUS_ADRALN , - .si_addr = addr - }; -trace_unhandled_signal ("unaligned trap" , regs, - (unsigned long )addr,SIGBUS ); -force_sig_info (info.si_signo, &info, current); -return (tile_bundle_bits )0 ; - } -if (unaligned_printk || unaligned_fixup_count ==0 ) { pr_info("Process %d/%s: PC %#lx: Fixup of" " unaligned %s at %#lx.\n",
Signature · 1 line
1.6.5.2
PATCH 1/1 arch/tile: allow querying cpu module information from the hypervisor
In reply to a message not in the archiveThis just adds a few more attributes to the information Linux can query from the hypervisor for the /sys/hypervisor/board/ directory, providing part, serial#, revision#, and description for cpu modules (as opposed to the board itself, or any mezzanine boards).
--- arch/tile/include/hv/hypervisor.h | 14 +++++++++++++- arch/tile/kernel/sysfs.c | 8 ++++++++ 2 files changed, 21 insertions(+), 1 deletions(-)
arch/tile/include/hv/hypervisor.h +13 -1
@@ -508,7 +508,19 @@ typedef enum {HV_CONFSTR_SWITCH_CONTROL =14 ,/** Chip revision level. */ - HV_CONFSTR_CHIP_REV = 15 +HV_CONFSTR_CHIP_REV =15 , + +/** CPU module part number. */ +HV_CONFSTR_CPUMOD_PART_NUM =16 , + +/** CPU module serial number. */ +HV_CONFSTR_CPUMOD_SERIAL_NUM =17 , + +/** CPU module revision level. */ +HV_CONFSTR_CPUMOD_REV =18 , + +/** Human-readable CPU module description. */ + HV_CONFSTR_CPUMOD_DESC = 19 } HV_ConfstrQuery;
arch/tile/kernel/sysfs.c +8 -0
@@ -93,6 +93,10 @@ HV_CONF_ATTR(mezz_part, HV_CONFSTR_MEZZ_PART_NUM) HV_CONF_ATTR(mezz_serial, HV_CONFSTR_MEZZ_SERIAL_NUM) HV_CONF_ATTR(mezz_revision, HV_CONFSTR_MEZZ_REV) HV_CONF_ATTR(mezz_description, HV_CONFSTR_MEZZ_DESC) +HV_CONF_ATTR(cpumod_part, HV_CONFSTR_CPUMOD_PART_NUM) +HV_CONF_ATTR(cpumod_serial, HV_CONFSTR_CPUMOD_SERIAL_NUM) +HV_CONF_ATTR(cpumod_revision, HV_CONFSTR_CPUMOD_REV) +HV_CONF_ATTR(cpumod_description,HV_CONFSTR_CPUMOD_DESC) HV_CONF_ATTR(switch_control, HV_CONFSTR_SWITCH_CONTROL)static struct attribute *board_attrs[] = {
@@ -104,6 +108,10 @@ static struct attribute *board_attrs[] = { &dev_attr_mezz_serial.attr, &dev_attr_mezz_revision.attr, &dev_attr_mezz_description.attr, + &dev_attr_cpumod_part.attr, + &dev_attr_cpumod_serial.attr, + &dev_attr_cpumod_revision.attr, + &dev_attr_cpumod_description.attr, &dev_attr_switch_control.attr,NULL };
Signature · 1 line
1.6.5.2
PATCH 1/1 arch/tile: fix hardwall for tilegx and generalize for idn and ipi
In reply to a message not in the archiveThe hardwall drain code was not properly implemented for tilegx, just tilepro, so you couldn't reliably restart an application that made use of the udn.
In addition, the code was only applicable to the udn (user dynamic network). On tilegx there is a second user network that is available (the "idn"), and there is support for having I/O shims deliver user-level interrupts to applications ("ipi") which functions in a very similar way to the inter-core permissions used for udn/idn. So this change also generalizes the code from supporting just the udn to supports udn/idn/ipi on tilegx.
By default we now use /dev/hardwall/{udn,idn,ipi} with separate minor numbers for the three devices.
--- arch/tile/include/arch/spr_def_32.h | 56 +++ arch/tile/include/arch/spr_def_64.h | 43 ++ arch/tile/include/asm/hardwall.h | 18 +- arch/tile/include/asm/processor.h | 17 +- arch/tile/include/asm/system.h | 10 +- arch/tile/kernel/hardwall.c | 754 +++++++++++++++++++++++------------ arch/tile/kernel/intvec_64.S | 2 +- arch/tile/kernel/process.c | 16 +- 8 files changed, 636 insertions(+), 280 deletions(-)
arch/tile/include/arch/spr_def_32.h +56 -0
@@ -65,6 +65,31 @@#define SPR_EX_CONTEXT_2_1__ICS_RMASK 0x1#define SPR_EX_CONTEXT_2_1__ICS_MASK 0x4#define SPR_FAIL 0x4e09 +#define SPR_IDN_AVAIL_EN 0x3e05 +#define SPR_IDN_CA_DATA 0x0b00 +#define SPR_IDN_DATA_AVAIL 0x0b03 +#define SPR_IDN_DEADLOCK_TIMEOUT 0x3406 +#define SPR_IDN_DEMUX_CA_COUNT 0x0a05 +#define SPR_IDN_DEMUX_COUNT_0 0x0a06 +#define SPR_IDN_DEMUX_COUNT_1 0x0a07 +#define SPR_IDN_DEMUX_CTL 0x0a08 +#define SPR_IDN_DEMUX_QUEUE_SEL 0x0a0a +#define SPR_IDN_DEMUX_STATUS 0x0a0b +#define SPR_IDN_DEMUX_WRITE_FIFO 0x0a0c +#define SPR_IDN_DIRECTION_PROTECT 0x2e05 +#define SPR_IDN_PENDING 0x0a0e +#define SPR_IDN_REFILL_EN 0x0e05 +#define SPR_IDN_SP_FIFO_DATA 0x0a0f +#define SPR_IDN_SP_FIFO_SEL 0x0a10 +#define SPR_IDN_SP_FREEZE 0x0a11 +#define SPR_IDN_SP_FREEZE__SP_FRZ_MASK 0x1 +#define SPR_IDN_SP_FREEZE__DEMUX_FRZ_MASK 0x2 +#define SPR_IDN_SP_FREEZE__NON_DEST_EXT_MASK 0x4 +#define SPR_IDN_SP_STATE 0x0a12 +#define SPR_IDN_TAG_0 0x0a13 +#define SPR_IDN_TAG_1 0x0a14 +#define SPR_IDN_TAG_VALID 0x0a15 +#define SPR_IDN_TILE_COORD 0x0a16#define SPR_INTCTRL_0_STATUS 0x4a07#define SPR_INTCTRL_1_STATUS 0x4807#define SPR_INTCTRL_2_STATUS 0x4607
@@ -87,12 +112,36 @@#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_AUX_PERF_COUNT_SET_0 0x6000 +#define SPR_MPL_AUX_PERF_COUNT_SET_1 0x6001 +#define SPR_MPL_AUX_PERF_COUNT_SET_2 0x6002#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_IDN_ACCESS_SET_0 0x0a00 +#define SPR_MPL_IDN_ACCESS_SET_1 0x0a01 +#define SPR_MPL_IDN_ACCESS_SET_2 0x0a02 +#define SPR_MPL_IDN_AVAIL_SET_0 0x3e00 +#define SPR_MPL_IDN_AVAIL_SET_1 0x3e01 +#define SPR_MPL_IDN_AVAIL_SET_2 0x3e02 +#define SPR_MPL_IDN_CA_SET_0 0x3a00 +#define SPR_MPL_IDN_CA_SET_1 0x3a01 +#define SPR_MPL_IDN_CA_SET_2 0x3a02 +#define SPR_MPL_IDN_COMPLETE_SET_0 0x1200 +#define SPR_MPL_IDN_COMPLETE_SET_1 0x1201 +#define SPR_MPL_IDN_COMPLETE_SET_2 0x1202 +#define SPR_MPL_IDN_FIREWALL_SET_0 0x2e00 +#define SPR_MPL_IDN_FIREWALL_SET_1 0x2e01 +#define SPR_MPL_IDN_FIREWALL_SET_2 0x2e02 +#define SPR_MPL_IDN_REFILL_SET_0 0x0e00 +#define SPR_MPL_IDN_REFILL_SET_1 0x0e01 +#define SPR_MPL_IDN_REFILL_SET_2 0x0e02 +#define SPR_MPL_IDN_TIMER_SET_0 0x3400 +#define SPR_MPL_IDN_TIMER_SET_1 0x3401 +#define SPR_MPL_IDN_TIMER_SET_2 0x3402#define SPR_MPL_INTCTRL_0_SET_0 0x4a00#define SPR_MPL_INTCTRL_0_SET_1 0x4a01#define SPR_MPL_INTCTRL_0_SET_2 0x4a02
@@ -102,6 +151,9 @@#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_PERF_COUNT_SET_0 0x4200 +#define SPR_MPL_PERF_COUNT_SET_1 0x4201 +#define SPR_MPL_PERF_COUNT_SET_2 0x4202#define SPR_MPL_SN_ACCESS_SET_0 0x0800#define SPR_MPL_SN_ACCESS_SET_1 0x0801#define SPR_MPL_SN_ACCESS_SET_2 0x0802
@@ -181,6 +233,7 @@#define SPR_UDN_DEMUX_STATUS 0x0c0d#define SPR_UDN_DEMUX_WRITE_FIFO 0x0c0e#define SPR_UDN_DIRECTION_PROTECT 0x3005 +#define SPR_UDN_PENDING 0x0c10#define SPR_UDN_REFILL_EN 0x1005#define SPR_UDN_SP_FIFO_DATA 0x0c11#define SPR_UDN_SP_FIFO_SEL 0x0c12
@@ -195,6 +248,9 @@#define SPR_UDN_TAG_3 0x0c18#define SPR_UDN_TAG_VALID 0x0c19#define SPR_UDN_TILE_COORD 0x0c1a +#define SPR_WATCH_CTL 0x4209 +#define SPR_WATCH_MASK 0x420a +#define SPR_WATCH_VAL 0x420b#endif /* !defined(__ARCH_SPR_DEF_H__) */
arch/tile/include/arch/spr_def_64.h +43 -0
70 lines not on this page · raw message
arch/tile/include/asm/hardwall.h +7 -11
@@ -11,12 +11,14 @@* NON INFRINGEMENT. See the GNU General Public License for * more details. * -* Provide methods for the HARDWALL_FILE for accessing the UDN. +* Provide methods for access control of per-cpu resources like +* UDN, IDN, or IPI. */ #ifndef _ASM_TILE_HARDWALL_H#define _ASM_TILE_HARDWALL_H +#include <arch/chip.h> #include <linux/ioctl.h> #define HARDWALL_IOCTL_BASE 0xa2
@@ -24,8 +26,9 @@/* * The HARDWALL_CREATE() ioctl is a macro with a "size" argument. * The resulting ioctl value is passed to the kernel in conjunction -* with a pointer to a little-endian bitmask of cpus, which must be -* physically in a rectangular configuration on the chip. +* with a pointer to a standard kernel bitmask of cpus. +* For network resources (UDN or IDN) the bitmask must physically +* represent a rectangular configuration on the chip. * The "size" is the number of bytes of cpu mask data. */ #define _HARDWALL_CREATE 1
@@ -44,13 +47,7 @@#define HARDWALL_GET_ID \ _IO(HARDWALL_IOCTL_BASE, _HARDWALL_GET_ID) -#ifndef __KERNEL__ - -/* This is the canonical name expected by userspace. */ -#define HARDWALL_FILE "/dev/hardwall" - -#else - +#ifdef __KERNEL__/* /proc hooks for hardwall. */ struct proc_dir_entry ;#ifdef CONFIG_HARDWALL
@@ -59,7 +56,6 @@ int proc_pid_hardwall(struct task_struct *task, char *buffer);#else static inline void proc_tile_hardwall_init (struct proc_dir_entry *root) {}#endif -#endif #endif /* _ASM_TILE_HARDWALL_H */
arch/tile/include/asm/processor.h +13 -4
@@ -76,6 +76,17 @@ struct async_tlb {#ifdef CONFIG_HARDWALL struct hardwall_info ; +struct hardwall_task { +/* Which hardwall is this task tied to? (or NULL if none) */ +struct hardwall_info *info; +/* Chains this task into the list at info->task_head. */ +struct list_head list; +}; +#ifdef __tilepro__ +#define HARDWALL_TYPES 1/* udn */ +#else +#define HARDWALL_TYPES 3/* udn, idn, and ipi */ +#endif #endif struct thread_struct {
@@ -116,10 +127,8 @@ struct thread_struct {unsigned long dstream_pf;#endif #ifdef CONFIG_HARDWALL -/* Is this task tied to an activated hardwall? */ -struct hardwall_info *hardwall; -/* Chains this task into the list at hardwall->list. */ -struct list_head hardwall_list; +/* Hardwall information for various resources. */ +struct hardwall_task hardwall[HARDWALL_TYPES ];#endif #if CHIP_HAS_TILE_DMA ()/* Async DMA TLB fault information */
arch/tile/include/asm/system.h +5 -5
@@ -223,14 +223,14 @@ void restrict_dma_mpls(void);#ifdef CONFIG_HARDWALL /* User-level network management functions */ void reset_network_state (void ); -void grant_network_mpls (void ); -void restrict_network_mpls (void ); -int hardwall_deactivate (struct task_struct *task); +void hardwall_switch_tasks (struct task_struct *prev,struct task_struct *next); +void hardwall_deactivate_all (struct task_struct *task); +int hardwall_ipi_valid (int cpu);/* Hook hardwall code into changes in affinity. */ #define arch_set_cpus_allowed (p, new_mask) do { \ - if (p->thread.hardwall && !cpumask_equal(&p->cpus_allowed, new_mask)) \ - hardwall_deactivate(p); \ + if (!cpumask_equal(&p->cpus_allowed, new_mask)) \ + hardwall_deactivate_all(p); \ } while (0)#endif
arch/tile/kernel/hardwall.c +505 -249
1,139 lines not on this page · raw message
arch/tile/kernel/intvec_64.S +1 -1
@@ -1226,7 +1226,7 @@ STD_ENTRY(fill_ra_stack) int_hand INT_UNALIGN_DATA, UNALIGN_DATA, int_unalign int_hand INT_DTLB_MISS, DTLB_MISS, do_page_fault int_hand INT_DTLB_ACCESS, DTLB_ACCESS, do_page_fault - int_hand INT_IDN_FIREWALL, IDN_FIREWALL, bad_intr + int_hand INT_IDN_FIREWALL, IDN_FIREWALL, do_hardwall_trap int_hand INT_UDN_FIREWALL, UDN_FIREWALL, do_hardwall_trap int_hand INT_TILE_TIMER, TILE_TIMER, do_timer_interrupt int_hand INT_IDN_TIMER, IDN_TIMER, bad_intr
arch/tile/kernel/process.c +6 -10
@@ -145,10 +145,10 @@ void free_thread_info(struct thread_info *info)* Calling deactivate here just frees up the data structures. * If the task we're freeing held the last reference to a * hardwall fd, it would have been released prior to this point -* anyway via exit_files(), and "hardwall" would be NULL by now. +* anyway via exit_files(), and the hardwall_task.info pointers +* would be NULL by now. */ -if (info->task->thread.hardwall) -hardwall_deactivate (info->task); +hardwall_deactivate_all (info->task);#endif if (step_state) {
@@ -264,7 +264,8 @@ int copy_thread(unsigned long clone_flags, unsigned long sp,#ifdef CONFIG_HARDWALL /* New thread does not own any networks. */ - p->thread.hardwall =NULL ; +memset (&p->thread.hardwall[0 ],0 , +sizeof (struct hardwall_task ) *HARDWALL_TYPES );#endif
@@ -534,12 +535,7 @@ struct task_struct *__sched _switch_to(struct task_struct *prev,#ifdef CONFIG_HARDWALL /* Enable or disable access to the network registers appropriately. */ -if (prev->thread.hardwall !=NULL ) { -if (next->thread.hardwall ==NULL ) -restrict_network_mpls (); - }else if (next->thread.hardwall !=NULL ) { -grant_network_mpls (); - } +hardwall_switch_tasks (prev, next);#endif /*
Signature · 1 line
1.6.5.2
PATCH 1/1 arch/tile: fix a reference to cpu_possible_map in a comment
In reply to a message not in the archive--- arch/tile/kernel/setup.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
arch/tile/kernel/setup.c +1 -1
@@ -1158,7 +1158,7 @@ EXPORT_SYMBOL(hash_for_home_map);/* * cpu_cacheable_map lists all the cpus whose caches the hypervisor can -* flush on our behalf. It is set to cpu_possible_map OR'ed with +* flush on our behalf. It is set to cpu_possible_mask OR'ed with * hash_for_home_map, and it is what should be passed to * hv_flush_remote() to flush all caches. Note that if there are * dedicated hypervisor driver tiles that have authorized use of their
Signature · 1 line
1.6.5.2
PATCH 1/1 arch/tile: fix finv_buffer_remote() for tilegx
In reply to a message not in the archiveThere were some correctness issues with this code that are now fixed with this change. The change is likely less performant than it could be, but it should no longer be vulnerable to any races with memory operations on the memory network while invalidating a range of memory. This code is run infrequently so performance isn't critical, but correctness definitely is.
--- arch/tile/lib/cacheflush.c | 28 ++++++++++++++++++++++++++-- 1 files changed, 26 insertions(+), 2 deletions(-)
arch/tile/lib/cacheflush.c +26 -2
@@ -39,7 +39,21 @@ void finv_buffer_remote(void *buffer, size_t size, int hfh) {char *p, *base;size_t step_size, load_count; + +/* +* On TILEPro the striping granularity is a fixed 8KB; on +* TILE-Gx it is configurable, and we rely on the fact that +* the hypervisor always configures maximum striping, so that +* bits 9 and 10 of the PA are part of the stripe function, so +* every 512 bytes we hit a striping boundary. +* +*/ +#ifdef __tilegx__ +const unsigned long STRIPE_WIDTH =512 ; +#else const unsigned long STRIPE_WIDTH =8192 ; +#endif +#ifdef __tilegx__/* * On TILE-Gx, we must disable the dstream prefetcher before doing
@@ -74,7 +88,7 @@ void finv_buffer_remote(void *buffer, size_t size, int hfh)* memory, that one load would be sufficient, but since we may * be, we also need to back up to the last load issued to * another memory controller, which would be the point where -* we crossed an 8KB boundary (the granularity of striping +* we crossed a "striping" boundary (the granularity of striping * across memory controllers). Keep backing up and doing this * until we are before the beginning of the buffer, or have * hit all the controllers.
@@ -88,12 +102,22 @@ void finv_buffer_remote(void *buffer, size_t size, int hfh)* every cache line on a full memory stripe on each * controller" that we simply do that, to simplify the logic. * -* FIXME: See bug 9535 for some issues with this code. +* On TILE-Gx the hash-for-home function is much more complex, +* with the upshot being we can't readily guarantee we have +* hit both entries in the 128-entry AMT that were hit by any +* load in the entire range, so we just re-load them all. +* With larger buffers, we may want to consider using a hypervisor +* trap to issue loads directly to each hash-for-home tile for +* each controller (doing it from Linux would trash the TLB). */ if (hfh) { step_size =L2_CACHE_BYTES ; +#ifdef __tilegx__ + load_count = (size +L2_CACHE_BYTES -1 ) /L2_CACHE_BYTES ; +#else load_count = (STRIPE_WIDTH /L2_CACHE_BYTES ) * (1 <<CHIP_LOG_NUM_MSHIMS ()); +#endif }else { step_size =STRIPE_WIDTH ; load_count = (1 <<CHIP_LOG_NUM_MSHIMS ());
Signature · 1 line
1.6.5.2
PATCH 1/1 arch/tile: use atomic exchange in arch_write_unlock()
In reply to a message not in the archiveThis idiom is used elsewhere when we do an unlock by writing a zero, but I missed it here. Using an atomic operation avoids waiting on the write buffer for the unlocking write to be sent to the home cache.
--- arch/tile/include/asm/spinlock_64.h | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
arch/tile/include/asm/spinlock_64.h +1 -1
@@ -137,7 +137,7 @@ static inline void arch_read_unlock(arch_rwlock_t *rw)static inline void arch_write_unlock (arch_rwlock_t *rw) {__insn_mf (); - rw->lock =0 ; +__insn_exch4 (&rw->lock,0 );/* Avoid waiting in the write buffer. */ }static inline int arch_read_trylock (arch_rwlock_t *rw)
Signature · 1 line
1.6.5.2
PATCH 1/1 arch/tile: stop mentioning the "kvm" subdirectory
In reply to a message not in the archiveIt causes "make clean" to fail, for example. Once we have KVM support complete, we'll reinstate the subdir reference.
--- arch/tile/Makefile | 2 -- 1 files changed, 0 insertions(+), 2 deletions(-)
arch/tile/Makefile +0 -2
@@ -54,8 +54,6 @@ 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
Signature · 1 line
1.6.5.2
PATCH 1/1 arch/tile: export the page_home() function.
In reply to a message not in the archive--- arch/tile/mm/homecache.c | 1 + 1 files changed, 1 insertions(+), 0 deletions(-)
arch/tile/mm/homecache.c +1 -0
@@ -394,6 +394,7 @@ int page_home(struct page *page)return pte_to_home (*virt_to_pte (NULL , kva)); } } +EXPORT_SYMBOL (page_home);void homecache_change_page_home (struct page *page,int order,int home) {
Signature · 1 line
1.6.5.2
PATCH 1/1 arch/tile: fix pointer cast in cacheflush.c
In reply to a message not in the archivePragmatically it couldn't be wrong to cast pointers to long to compare them (since all kernel addresses are in the top half of VA space), but it's more correct to cast to unsigned long.
--- arch/tile/lib/cacheflush.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
arch/tile/lib/cacheflush.c +1 -1
@@ -109,7 +109,7 @@ void finv_buffer_remote(void *buffer, size_t size, int hfh)/* Figure out how far back we need to go. */ base = p - (step_size * (load_count -2 )); -if ((long )base < (long )buffer) +if ((unsigned long )base < (unsigned long )buffer) base = buffer;/*
Signature · 1 line
1.6.5.2
PATCH 1/1 arch/tile: fix single-stepping over swint1 instructions on tilegx
In reply to a message not in the archiveIf we are single-stepping and make a syscall, we call ptrace_notify() explicitly on the return path back to user space, since we are returning to a pc value set artificially to the next instruction, and otherwise we won't register that we stepped over the syscall instruction (swint1).
--- arch/tile/kernel/intvec_64.S | 21 ++++++++++++++++++--- 1 files changed, 18 insertions(+), 3 deletions(-)
arch/tile/kernel/intvec_64.S +18 -3
@@ -22,6 +22,7 @@ #include <asm/irqflags.h> #include <asm/asm-offsets.h> #include <asm/types.h> +#include <asm/signal.h> #include <hv/hypervisor.h> #include <arch/abi.h> #include <arch/interrupts.h>
@@ -1047,11 +1048,25 @@ handle_syscall: /* Do syscall trace again, if requested. */ ld r30, r31 - andi r30, r30, _TIF_SYSCALL_TRACE - beqzt r30, 1f + andi r0, r30, _TIF_SYSCALL_TRACE + { + andi r0, r30, _TIF_SINGLESTEP + beqzt r0, 1f + } jal do_syscall_trace FEEDBACK_REENTER(handle_syscall) -1: j .Lresume_userspace /* jump into middle of interrupt_return */ + andi r0, r30, _TIF_SINGLESTEP + +1: beqzt r0, 2f + + /* Single stepping -- notify ptrace. */ + { + movei r0, SIGTRAP + jal ptrace_notify + } + FEEDBACK_REENTER(handle_syscall) + +2: j .Lresume_userspace /* jump into middle of interrupt_return */ .Lcompat_syscall: /*
Signature · 1 line
1.6.5.2
PATCH 1/1 arch/tile: implement panic_smp_self_stop()
In reply to a message not in the archiveThis allows the later-panicking tiles to wait in a lower power state until they get interrupted with an smp_send_stop().
--- arch/tile/kernel/smp.c | 6 ++++++ 1 files changed, 6 insertions(+), 0 deletions(-)
arch/tile/kernel/smp.c +6 -0
@@ -132,6 +132,12 @@ void smp_send_stop(void)send_IPI_allbutself (MSG_TAG_STOP_CPU ); } +/* On panic, just wait; we may get an smp_send_stop() later on. */ +void panic_smp_self_stop (void ) +{ +while (1 ) + asm("nap; nop" ); +}/* * Dispatch code called from hv_message_intr() for HV_MSG_TILE hv messages.
Signature · 1 line
1.6.5.2
PATCH 1/1 arch/tile: add "nop" after "nap" to help GX idle power draw
In reply to a message not in the archiveThis avoids the hardware istream prefetcher doing unnecessary work.
--- arch/tile/kernel/entry.S | 2 ++ arch/tile/kernel/smp.c | 2 +- 2 files changed, 3 insertions(+), 1 deletions(-)
arch/tile/kernel/entry.S +2 -0
@@ -85,6 +85,7 @@ STD_ENTRY(cpu_idle_on_new_stack) /* Loop forever on a nap during SMP boot. */ STD_ENTRY(smp_nap) nap + nop /* avoid provoking the icache prefetch with a jump */ j smp_nap /* we are not architecturally guaranteed not to exit nap */ jrp lr /* clue in the backtracer */ STD_ENDPROC(smp_nap)
@@ -106,5 +107,6 @@ STD_ENTRY(_cpu_idle) .global _cpu_idle_nap _cpu_idle_nap: nap + nop /* avoid provoking the icache prefetch with a jump */ jrp lr STD_ENDPROC(_cpu_idle)
arch/tile/kernel/smp.c +1 -1
@@ -122,7 +122,7 @@ static void smp_stop_cpu_interrupt(void)set_cpu_online (smp_processor_id (),0 );arch_local_irq_disable_all ();for (;;) - asm("nap" ); + asm("nap; nop" ); }/* This function calls the 'stop' function on all other CPUs in the system. */
Signature · 1 line
1.6.5.2
PATCH 1/1 arch/tile: use memparse() for "maxmem" and "maxnodemem" options
In reply to a message not in the archiveThis is more standard and avoids having to remember what units the options actually take.
--- arch/tile/kernel/setup.c | 17 ++++++++--------- 1 files changed, 8 insertions(+), 9 deletions(-)
arch/tile/kernel/setup.c +8 -9
@@ -103,13 +103,11 @@ unsigned long __initdata pci_reserve_end_pfn = -1U;static int __init setup_maxmem (char *str) { -long maxmem_mb; -if (str ==NULL ||strict_strtol (str,0 , &maxmem_mb) !=0 || - maxmem_mb ==0 ) +unsigned long long maxmem; +if (str ==NULL || (maxmem =memparse (str,NULL )) ==0 )return -EINVAL ; - maxmem_pfn = (maxmem_mb >> (HPAGE_SHIFT -20 )) << - (HPAGE_SHIFT -PAGE_SHIFT ); + maxmem_pfn = (maxmem >>HPAGE_SHIFT ) << (HPAGE_SHIFT -PAGE_SHIFT );pr_info ("Forcing RAM used to no more than %dMB\n" , maxmem_pfn >> (20 -PAGE_SHIFT ));return 0 ;
@@ -119,14 +117,15 @@ early_param("maxmem", setup_maxmem);static int __init setup_maxnodemem (char *str) {char *endp; -long maxnodemem_mb, node; +unsigned long long maxnodemem; +long node; node = str ?simple_strtoul (str, &endp,0 ) :INT_MAX ; -if (node >=MAX_NUMNODES || *endp !=':' || -strict_strtol (endp+1 ,0 , &maxnodemem_mb) !=0 ) +if (node >=MAX_NUMNODES || *endp !=':' )return -EINVAL ; - maxnodemem_pfn[node] = (maxnodemem_mb >> (HPAGE_SHIFT -20 )) << + maxnodemem =memparse (endp+1 ,NULL ); + maxnodemem_pfn[node] = (maxnodemem >>HPAGE_SHIFT ) << (HPAGE_SHIFT -PAGE_SHIFT );pr_info ("Forcing RAM used on node %ld to no more than %dMB\n" , node, maxnodemem_pfn[node] >> (20 -PAGE_SHIFT ));
Signature · 1 line
1.6.5.2
PATCH 1/1 arch/tile: fix up locking in pgtable.c slightly
In reply to a message not in the archiveWe should be holding the init_mm.page_table_lock in shatter_huge_page() since we are modifying the kernel page tables. Then, only if we are walking the other root page tables to update them, do we want to take the pgd_lock.
Add a comment about taking the pgd_lock that we always do it with interrupts disabled and therefore are not at risk from the tlbflush IPI deadlock as is seen on x86.
--- arch/tile/mm/pgtable.c | 22 ++++++++++++---------- 1 files changed, 12 insertions(+), 10 deletions(-)
arch/tile/mm/pgtable.c +12 -10
@@ -178,14 +178,10 @@ void shatter_huge_page(unsigned long addr)if (!pmd_huge_page (*pmd))return ; -/* -* Grab the pgd_lock, since we may need it to walk the pgd_list, -* and since we need some kind of lock here to avoid races. -*/ -spin_lock_irqsave (&pgd_lock, flags); +spin_lock_irqsave (&init_mm.page_table_lock, flags);if (!pmd_huge_page (*pmd)) {/* Lost the race to convert the huge page. */ -spin_unlock_irqrestore (&pgd_lock, flags); +spin_unlock_irqrestore (&init_mm.page_table_lock, flags);return ; }
@@ -195,6 +191,7 @@ void shatter_huge_page(unsigned long addr)#ifdef __PAGETABLE_PMD_FOLDED/* Walk every pgd on the system and update the pmd there. */ +spin_lock (&pgd_lock);list_for_each (pos, &pgd_list) {pmd_t *copy_pmd; pgd =list_to_pgd (pos) +pgd_index (addr);
@@ -202,6 +199,7 @@ void shatter_huge_page(unsigned long addr) copy_pmd =pmd_offset (pud, addr); __set_pmd(copy_pmd, *pmd); } +spin_unlock (&pgd_lock);#endif /* Tell every cpu to notice the change. */
@@ -209,7 +207,7 @@ void shatter_huge_page(unsigned long addr) cpu_possible_mask, NULL, 0);/* Hold the lock until the TLB flush is finished to avoid races. */ -spin_unlock_irqrestore (&pgd_lock, flags); +spin_unlock_irqrestore (&init_mm.page_table_lock, flags); }/*
@@ -218,9 +216,13 @@ void shatter_huge_page(unsigned long addr)* against pageattr.c; it is the unique case in which a valid change * of kernel pagetables can't be lazily synchronized by vmalloc faults. * vmalloc faults work because attached pagetables are never freed. -* The locking scheme was chosen on the basis of manfred's -* recommendations and having no core impact whatsoever. -* -- wli +* +* The lock is always taken with interrupts disabled, unlike on x86 +* and other platforms, because we need to take the lock in +* shatter_huge_page(), which may be called from an interrupt context. +* We are not at risk from the tlbflush IPI deadlock that was seen on +* x86, since we use the flush_remote() API to have the hypervisor do +* the TLB flushes regardless of irq disabling. */ DEFINE_SPINLOCK (pgd_lock);LIST_HEAD (pgd_list);
Signature · 1 line
1.6.5.2
PATCH 1/1 arch/tile: support kexec() for tilegx
In reply to a message not in the archive--- arch/tile/include/asm/kexec.h | 12 ++ arch/tile/kernel/Makefile | 2 +- arch/tile/kernel/machine_kexec.c | 35 +++- arch/tile/kernel/relocate_kernel.S | 280 --------------------------------- arch/tile/kernel/relocate_kernel_32.S | 280 +++++++++++++++++++++++++++++++++ arch/tile/kernel/relocate_kernel_64.S | 260 ++++++++++++++++++++++++++++++ 6 files changed, 580 insertions(+), 289 deletions(-) delete mode 100644 arch/tile/kernel/relocate_kernel.S create mode 100644 arch/tile/kernel/relocate_kernel_32.S create mode 100644 arch/tile/kernel/relocate_kernel_64.S
arch/tile/include/asm/kexec.h +12 -0
@@ -19,12 +19,24 @@#include <asm/page.h> +#ifndef __tilegx__/* Maximum physical address we can use pages from. */ #define KEXEC_SOURCE_MEMORY_LIMIT TASK_SIZE/* Maximum address we can reach in physical address mode. */ #define KEXEC_DESTINATION_MEMORY_LIMIT TASK_SIZE/* Maximum address we can use for the control code buffer. */ #define KEXEC_CONTROL_MEMORY_LIMIT TASK_SIZE +#else +/* We need to limit the memory below PGDIR_SIZE since +* we only setup page table for [0, PGDIR_SIZE) before final kexec. +*/ +/* Maximum physical address we can use pages from. */ +#define KEXEC_SOURCE_MEMORY_LIMIT PGDIR_SIZE +/* Maximum address we can reach in physical address mode. */ +#define KEXEC_DESTINATION_MEMORY_LIMIT PGDIR_SIZE +/* Maximum address we can use for the control code buffer. */ +#define KEXEC_CONTROL_MEMORY_LIMIT PGDIR_SIZE +#endif #define KEXEC_CONTROL_PAGE_SIZE PAGE_SIZE
arch/tile/kernel/Makefile +1 -1
@@ -13,5 +13,5 @@ obj-$(CONFIG_COMPAT) += compat.o compat_signal.o obj-$(CONFIG_SMP) += smpboot.o smp.o tlb.o obj-$(CONFIG_MODULES) += module.o obj-$(CONFIG_EARLY_PRINTK) += early_printk.o -obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o +obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel_$(BITS).o obj-$(CONFIG_PCI) += pci.o
arch/tile/kernel/machine_kexec.c +27 -8
@@ -31,6 +31,8 @@#include <asm/pgalloc.h> #include <asm/cacheflush.h> #include <asm/checksum.h> +#include <asm/tlbflush.h> +#include <asm/homecache.h> #include <hv/hypervisor.h>
@@ -222,11 +224,22 @@ struct page *kimage_alloc_pages_arch(gfp_t gfp_mask, unsigned int order)return alloc_pages_node (0 , gfp_mask, order); } +/* +* Address range in which pa=va mapping is set in setup_quasi_va_is_pa(). +* For tilepro, PAGE_OFFSET is used since this is the largest possbile value +* for tilepro, while for tilegx, we limit it to entire middle level page +* table which we assume has been allocated and is undoubtedly large enough. +*/ +#ifndef __tilegx__ +#define QUASI_VA_IS_PA_ADDR_RANGE PAGE_OFFSET +#else +#define QUASI_VA_IS_PA_ADDR_RANGE PGDIR_SIZE +#endif +static void setup_quasi_va_is_pa (void ) { -HV_PTE *pgtable;HV_PTE pte; -int i; +unsigned long i;/* * Flush our TLB to prevent conflicts between the previous contents
@@ -234,16 +247,22 @@ static void setup_quasi_va_is_pa(void)*/ local_flush_tlb_all (); -/* setup VA is PA, at least up to PAGE_OFFSET */ - - pgtable = (HV_PTE *)current->mm->pgd; +/* +* setup VA is PA, at least up to QUASI_VA_IS_PA_ADDR_RANGE. +* Note here we assume that level-1 page table is defined by +* HPAGE_SIZE. +*/ pte =hv_pte (_PAGE_KERNEL | _PAGE_HUGE_PAGE); pte =hv_pte_set_mode (pte,HV_PTE_MODE_CACHE_NO_L3 ); - -for (i =0 ; i <pgd_index (PAGE_OFFSET ); i++) { +for (i =0 ; i < (QUASI_VA_IS_PA_ADDR_RANGE >>HPAGE_SHIFT ); i++) { +unsigned long vaddr = i <<HPAGE_SHIFT ; +pgd_t *pgd =pgd_offset (current->mm, vaddr); +pud_t *pud =pud_offset (pgd, vaddr); +pte_t *ptep = (pte_t *)pmd_offset (pud, vaddr);unsigned long pfn = i << (HPAGE_SHIFT -PAGE_SHIFT ); +if (pfn_valid (pfn)) -__set_pte (&pgtable[i],pfn_pte (pfn, pte)); +__set_pte (ptep,pfn_pte (pfn, pte)); } }
arch/tile/kernel/relocate_kernel.S deleted +0 -280
280 lines not on this page · raw message
arch/tile/kernel/relocate_kernel_32.S new file +280 -0
280 lines not on this page · raw message
arch/tile/kernel/relocate_kernel_64.S new file +260 -0
260 lines not on this page · raw message
Signature · 1 line
1.6.5.2
PATCH 1/1 arch/tile: support loading kernels larger than 16 MB
In reply to a message not in the archivePreviously we only handled kernels up to a single huge page in size. Now we create additional PTEs appropriately.
--- arch/tile/mm/init.c | 21 +++++++++++++++------ 1 files changed, 15 insertions(+), 6 deletions(-)
arch/tile/mm/init.c +15 -6
@@ -554,6 +554,7 @@ static void __init kernel_physical_mapping_init(pgd_t *pgd_base) address =MEM_SV_INTRPT ; pmd =get_pmd (pgtables, address); + pfn =0 ;/* code starts at PA 0 */ if (ktext_small) {/* Allocate an L2 PTE for the kernel text */ int cpu =0 ;
@@ -576,10 +577,15 @@ static void __init kernel_physical_mapping_init(pgd_t *pgd_base) }BUG_ON (address != (unsigned long )_stext); - pfn =0 ;/* code starts at PA 0 */ - pte =alloc_pte (); -for (pte_ofs =0 ; address < (unsigned long )_einittext; - pfn++, pte_ofs++, address +=PAGE_SIZE ) { + pte =NULL ; +for (; address < (unsigned long )_einittext; + pfn++, address +=PAGE_SIZE ) { + pte_ofs =pte_index (address); +if (pte_ofs ==0 ) { +if (pte) +assign_pte (pmd++, pte); + pte =alloc_pte (); + }if (!ktext_local) { prot =set_remote_cache_cpu (prot, cpu); cpu =cpumask_next (cpu, &ktext_mask);
@@ -588,7 +594,8 @@ static void __init kernel_physical_mapping_init(pgd_t *pgd_base) } pte[pte_ofs] =pfn_pte (pfn, prot); } -assign_pte (pmd, pte); +if (pte) +assign_pte (pmd, pte); }else {pte_t pteval =pfn_pte (0 ,PAGE_KERNEL_EXEC ); pteval =pte_mkhuge (pteval);
@@ -611,7 +618,9 @@ static void __init kernel_physical_mapping_init(pgd_t *pgd_base)else pteval =hv_pte_set_mode (pteval,HV_PTE_MODE_CACHE_NO_L3 ); - *(pte_t *)pmd = pteval; +for (; address < (unsigned long )_einittext; + pfn +=PFN_DOWN (HPAGE_SIZE ), address +=HPAGE_SIZE ) + *(pte_t *)(pmd++) =pfn_pte (pfn, pteval); }/* Set swapper_pgprot here so it is flushed to memory right away. */
Signature · 1 line
1.6.5.2
PATCH 1/1 arch/tile: don't enable irqs unconditionally in page fault handler
In reply to a message not in the archiveIf we took a page fault while we had interrupts disabled, we shouldn't enable them in the page fault handler.
--- arch/tile/mm/fault.c | 7 +++++-- 1 files changed, 5 insertions(+), 2 deletions(-)
arch/tile/mm/fault.c +5 -2
@@ -343,9 +343,12 @@ static int handle_page_fault(struct pt_regs *regs,/* * If we're trying to touch user-space addresses, we must * be either at PL0, or else with interrupts enabled in the -* kernel, so either way we can re-enable interrupts here. +* kernel, so either way we can re-enable interrupts here +* unless we are doing atomic access to user space with +* interrupts disabled. */ -local_irq_enable (); +if (!(regs->flags &PT_FLAGS_DISABLE_IRQ )) +local_irq_enable (); mm = tsk->mm;
Signature · 1 line
1.6.5.2
PATCH 1/1 arch/tile: don't set the homecache of a PTE unless appropriate
In reply to a message not in the archiveWe make sure not to try to set the home for an MMIO PTE (on tilegx) or a PTE that isn't referencing memory managed by Linux.
--- arch/tile/mm/pgtable.c | 16 ++++++++++++---- 1 files changed, 12 insertions(+), 4 deletions(-)
arch/tile/mm/pgtable.c +12 -4
@@ -467,10 +467,18 @@ void __set_pte(pte_t *ptep, pte_t pte)void set_pte (pte_t *ptep,pte_t pte) { -struct page *page =pfn_to_page (pte_pfn (pte)); - -/* Update the home of a PTE if necessary */ - pte =pte_set_home (pte,page_home (page)); +if (pte_present (pte) && + (!CHIP_HAS_MMIO () ||hv_pte_get_mode (pte) !=HV_PTE_MODE_MMIO )) { +/* The PTE actually references physical memory. */ +unsigned long pfn =pte_pfn (pte); +if (pfn_valid (pfn)) { +/* Update the home of the PTE from the struct page. */ + pte =pte_set_home (pte,page_home (pfn_to_page (pfn))); + }else if (hv_pte_get_mode (pte) ==0 ) { +/* remap_pfn_range(), etc, must supply PTE mode. */ +panic ("set_pte(): out-of-range PFN and mode 0\n" ); + } + }__set_pte (ptep, pte); }
Signature · 1 line
1.6.5.2
PATCH 1/1 arch/tile: don't wait for migrating PTEs in an NMI handler
In reply to a message not in the archiveDoing so raises the possibility of self-deadlock if we are waiting for a backtrace for an oprofile or perf interrupt while we are in the middle of migrating our own stack page.
--- arch/tile/mm/fault.c | 13 ++++++++++--- 1 files changed, 10 insertions(+), 3 deletions(-)
arch/tile/mm/fault.c +10 -3
@@ -204,9 +204,14 @@ static pgd_t *get_current_pgd(void)* interrupt or a critical region, and must do as little as possible. * Similarly, we can't use atomic ops here, since we may be handling a * fault caused by an atomic op access. +* +* If we find a migrating PTE while we're in an NMI context, and we're +* at a PC that has a registered exception handler, we don't wait, +* since this thread may (e.g.) have been interrupted while migrating +* its own stack, which would then cause us to self-deadlock. */ static int handle_migrating_pte (pgd_t *pgd,int fault_num, -unsigned long address, +unsigned long address,unsigned long pc,int is_kernel_mode,int write) {pud_t *pud;
@@ -228,6 +233,8 @@ static int handle_migrating_pte(pgd_t *pgd, int fault_num,pte_offset_kernel (pmd, address); pteval = *pte;if (pte_migrating (pteval)) { +if (in_nmi () &&search_exception_tables (pc)) +return 0 ;wait_for_migration (pte);return 1 ; }
@@ -301,7 +308,7 @@ static int handle_page_fault(struct pt_regs *regs,* rather than trying to patch up the existing PTE. */ pgd =get_current_pgd (); -if (handle_migrating_pte (pgd, fault_num, address, +if (handle_migrating_pte (pgd, fault_num, address, regs->pc, is_kernel_mode, write))return 1 ;
@@ -666,7 +673,7 @@ struct intvec_state do_page_fault_ics(struct pt_regs *regs, int fault_num,*/ if (fault_num ==INT_DTLB_ACCESS ) write =1 ; -if (handle_migrating_pte (pgd, fault_num, address,1 , write)) +if (handle_migrating_pte (pgd, fault_num, address, pc,1 , write))return state;/* Return zero so that we continue on with normal fault handling. */
Signature · 1 line
1.6.5.2
PATCH 1/1 arch/tile: support <asm/cachectl.h> header for cacheflush() syscall
In reply to a message not in the archiveWe already had a syscall that did some dcache flushing, but it was not used in practice. Make it MIPS compatible instead so it can do both the DCACHE and ICACHE actions. We have code that wants to be able to use the ICACHE flush mode from userspace so this change enables that.
--- arch/tile/include/asm/Kbuild | 1 + arch/tile/include/asm/cachectl.h | 42 ++++++++++++++++++++++++++++++++++++++ arch/tile/include/asm/compat.h | 3 -- arch/tile/include/asm/syscalls.h | 3 +- arch/tile/include/asm/unistd.h | 4 +- arch/tile/kernel/sys.c | 10 +++++++- 6 files changed, 55 insertions(+), 8 deletions(-) create mode 100644 arch/tile/include/asm/cachectl.h
arch/tile/include/asm/Kbuild +1 -0
@@ -2,6 +2,7 @@ include include/asm-generic/Kbuild.asm header-y += ../arch/ +header-y += cachectl.h header-y += ucontext.h header-y += hardwall.h
arch/tile/include/asm/cachectl.h new file +42 -0
42 lines not on this page · raw message
arch/tile/include/asm/compat.h +0 -3
@@ -242,9 +242,6 @@ long compat_sys_fallocate(int fd, int mode,long compat_sys_sched_rr_get_interval (compat_pid_t pid,struct compat_timespec __user *interval); -/* 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,
arch/tile/include/asm/syscalls.h +2 -1
@@ -43,7 +43,8 @@ long sys32_fadvise64(int fd, u32 offset_lo, u32 offset_hi, u32 len, int advice);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_cacheflush (unsigned long addr,unsigned long len, +unsigned long flags);#ifndef __tilegx__/* No mmap() in the 32-bit kernel. */ #define sys_mmap sys_mmap#endif
arch/tile/include/asm/unistd.h +2 -2
@@ -24,8 +24,8 @@#include <asm-generic/unistd.h> /* Additional Tilera-specific syscalls. */ -#define __NR_flush_cache (__NR_arch_specific_syscall + 1) -__SYSCALL(__NR_flush_cache, sys_flush_cache) +#define __NR_cacheflush (__NR_arch_specific_syscall + 1) +__SYSCALL(__NR_cacheflush, sys_cacheflush)#ifndef __tilegx__/* "Fast" syscalls provide atomic support for 32-bit chips. */
arch/tile/kernel/sys.c +8 -2
@@ -32,11 +32,17 @@#include <asm/syscalls.h> #include <asm/pgtable.h> #include <asm/homecache.h> +#include <asm/cachectl.h> #include <arch/chip.h> -SYSCALL_DEFINE0 (flush_cache) +SYSCALL_DEFINE3(cacheflush, unsigned long, addr, unsigned long, len, + unsigned long, flags) { -homecache_evict (cpumask_of (smp_processor_id ())); +if (flags &DCACHE ) +homecache_evict (cpumask_of (smp_processor_id ())); +if (flags &ICACHE ) +flush_remote (0 ,HV_FLUSH_EVICT_L1I ,mm_cpumask (current->mm), +0 ,0 ,0 ,NULL ,NULL ,0 );return 0 ; }
Signature · 1 line
1.6.5.2
PATCH 1/1 arch/tile: improve trap handling a bit
In reply to a message not in the archiveWe now respond to MEM_ERROR traps (e.g. an atomic instruction to non-cacheable memory) with a SIGBUS.
We also no longer generate a console crash message if a user process die due to a SIGTRAP.
--- arch/tile/kernel/intvec_64.S | 2 +- arch/tile/kernel/traps.c | 9 +++++++-- 2 files changed, 8 insertions(+), 3 deletions(-)
arch/tile/kernel/intvec_64.S +1 -1
@@ -1186,7 +1186,7 @@ STD_ENTRY(fill_ra_stack) #define do_hardwall_trap bad_intr #endif - int_hand INT_MEM_ERROR, MEM_ERROR, bad_intr + int_hand INT_MEM_ERROR, MEM_ERROR, do_trap int_hand INT_SINGLE_STEP_3, SINGLE_STEP_3, bad_intr #if CONFIG_KERNEL_PL == 2 int_hand INT_SINGLE_STEP_2, SINGLE_STEP_2, gx_singlestep_handle
arch/tile/kernel/traps.c +7 -2
@@ -199,7 +199,7 @@ void __kprobes do_trap(struct pt_regs *regs, int fault_num, {siginfo_t info = {0 };int signo, code; -unsigned long address; +unsigned long address =0 ;bundle_bits instr;/* Re-enable interrupts. */
@@ -222,6 +222,10 @@ void __kprobes do_trap(struct pt_regs *regs, int fault_num, }switch (fault_num) { +case INT_MEM_ERROR : + signo =SIGBUS ; + code =BUS_OBJERR ; +break ;case INT_ILL :if (copy_from_user (&instr, (void __user *)regs->pc,sizeof (instr))) {
@@ -311,7 +315,8 @@ void __kprobes do_trap(struct pt_regs *regs, int fault_num, info.si_addr = (void __user *)address;if (signo ==SIGILL ) info.si_trapno = fault_num; -trace_unhandled_signal ("trap" , regs, address, signo); +if (signo !=SIGTRAP ) +trace_unhandled_signal ("trap" , regs, address, signo);force_sig_info (signo, &info, current); }
Signature · 1 line
1.6.5.2
PATCH 1/1 arch/tile: work around a hardware issue with the return-address stack
In reply to a message not in the archiveIn certain circumstances we need to do a bunch of jump-and-link instructions to fill the hardware return-address stack with nonzero values.
--- arch/tile/include/asm/traps.h | 6 +++++- arch/tile/kernel/intvec_64.S | 12 ++++++++++++ arch/tile/kernel/traps.c | 6 +++++- 3 files changed, 22 insertions(+), 2 deletions(-)
arch/tile/include/asm/traps.h +5 -1
@@ -64,7 +64,11 @@ void do_breakpoint(struct pt_regs *, int fault_num);#ifdef __tilegx__ +/* kernel/single_step.c */ void gx_singlestep_handle (struct pt_regs *,int fault_num); + +/* kernel/intvec_64.S */ +void fill_ra_stack (void );#endif -#endif /* _ASM_TILE_SYSCALLS_H */ +#endif /* _ASM_TILE_TRAPS_H */
arch/tile/kernel/intvec_64.S +12 -0
@@ -1164,6 +1164,18 @@ int_unalign: push_extra_callee_saves r0 j do_trap +/* Fill the return address stack with nonzero entries. */ +STD_ENTRY(fill_ra_stack) + { + move r0, lr + jal 1f + } +1: jal 2f +2: jal 3f +3: jal 4f +4: jrp r0 + STD_ENDPROC(fill_ra_stack) + /* Include .intrpt1 array of interrupt vectors */ .section ".intrpt1", "ax"
arch/tile/kernel/traps.c +5 -1
@@ -288,7 +288,10 @@ void __kprobes do_trap(struct pt_regs *regs, int fault_num, address = regs->pc;break ;#ifdef __tilegx__ -case INT_ILL_TRANS : +case INT_ILL_TRANS : { +/* Avoid a hardware erratum with the return address stack. */ +fill_ra_stack (); + signo =SIGSEGV ; code =SEGV_MAPERR ;if (reason &SPR_ILL_TRANS_REASON__I_STREAM_VA_RMASK )
@@ -296,6 +299,7 @@ void __kprobes do_trap(struct pt_regs *regs, int fault_num, else address =0 ;/* FIXME: GX: single-step for address */ break; + }#endif default :panic ("Unexpected do_trap interrupt number %d" , fault_num);
Signature · 1 line
1.6.5.2
PATCH 1/1 arch/tile: various improvements to stack backtracer
In reply to a message not in the archiveFix a long-standing bug in the stack backtracer where we would print garbage to the console instead of kernel function names, if the kernel wasn't built with symbol support (e.g. mboot).
Make sure to tag every line of userspace backtrace output if we actually have the mmap_sem, since that way if there's no tag, we know that it's because we couldn't trylock the semaphore.
Stop doing a TLB flush and examining page tables during backtrace. Instead, just trust that __copy_from_user_inatomic() will properly fault and return a failure, which it should do in all cases.
Fix a latent bug where the backtracer would directly examine a signal context in user space, rather than copying it safely to kernel memory first. This meant that a race with another thread could potentially have caused a kernel panic.
Guard against unaligned sp when trying to restart backtrace at an interrupt or signal handler point in the kernel backtracer.
Report kernel symbolic information for the call instruction rather than for the following instruction. We still report the actual numeric address corresponding to the instruction after the call, for the sake of consistency with the normal expectations for stack backtracers.
--- arch/tile/include/asm/stack.h | 1 - arch/tile/kernel/stack.c | 230 ++++++++++++++++++++--------------------- 2 files changed, 112 insertions(+), 119 deletions(-)
arch/tile/include/asm/stack.h +0 -1
@@ -25,7 +25,6 @@struct KBacktraceIterator {BacktraceIterator it;struct task_struct *task;/* task we are backtracing */ -pte_t *pgtable;/* page table for user space access */ int end;/* iteration complete. */ int new_context;/* new context is starting */ int profile;/* profiling, so stop on async intrpt */
arch/tile/kernel/stack.c +112 -118
325 lines not on this page · raw message
Signature · 1 line
1.6.5.2
PATCH 1/1 arch/tile: make sure to build memcpy_user_64 without frame pointer
In reply to a message not in the archiveAdd a comment explaining why this is important, and add a CFLAGS_REMOVE clause to the Makefile to make sure it happens.
--- arch/tile/lib/Makefile | 1 + arch/tile/lib/memcpy_user_64.c | 8 +++++++- 2 files changed, 8 insertions(+), 1 deletions(-)
arch/tile/lib/Makefile +1 -0
@@ -7,6 +7,7 @@ lib-y = cacheflush.o checksum.o cpumask.o delay.o uaccess.o \ strchr_$(BITS).o strlen_$(BITS).o ifeq ($(CONFIG_TILEGX),y) +CFLAGS_REMOVE_memcpy_user_64.o = -fno-omit-frame-pointer lib-y += memcpy_user_64.o else lib-y += atomic_32.o atomic_asm_32.o memcpy_tile64.o
arch/tile/lib/memcpy_user_64.c +7 -1
@@ -14,7 +14,13 @@* Do memcpy(), but trap and return "n" when a load or store faults. * * Note: this idiom only works when memcpy() compiles to a leaf function. -* If "sp" is updated during memcpy, the "jrp lr" will be incorrect. +* Here leaf function not only means it does not have calls, but also +* requires no stack operations (sp, stack frame pointer) and no +* use of callee-saved registers, else "jrp lr" will be incorrect since +* unwinding stack frame is bypassed. Since memcpy() is not complex so +* these conditions are satisfied here, but we need to be careful when +* modifying this file. This is not a clean solution but is the best +* one so far. * * Also note that we are capturing "n" from the containing scope here. */
Signature · 1 line
1.6.5.2
PATCH 1/1 arch/tile: avoid false corrupt frame warning in early boot
In reply to a message not in the archiveWith lockstat we can end up trying to get a backtrace before "high_memory" is initialized, so don't worry about range testing if it is zero.
--- arch/tile/kernel/process.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
arch/tile/kernel/process.c +1 -1
@@ -286,7 +286,7 @@ struct task_struct *validate_current(void)static struct task_struct corrupt = { .comm ="<corrupt>" };struct task_struct *tsk = current;if (unlikely ((unsigned long )tsk <PAGE_OFFSET || - (void *)tsk > high_memory || + (high_memory && (void *)tsk > high_memory) || ((unsigned long)tsk & (__alignof__(*tsk) - 1)) != 0)) {pr_err ("Corrupt 'current' %p (sp %#lx)\n" , tsk, stack_pointer); tsk = &corrupt;
Signature · 1 line
1.6.5.2
PATCH 1/1 arch/tile: Allow tilegx to build with either 16K or 64K page size
In reply to a message not in the archiveThis change introduces new flags for the hv_install_context() API that passes a page table pointer to the hypervisor. Clients can explicitly request 4K, 16K, or 64K small pages when they install a new context. In practice, the page size is fixed at kernel compile time and the same size is always requested every time a new page table is installed.
The <hv/hypervisor.h> header changes so that it provides more abstract macros for managing "page" things like PFNs and page tables. For example there is now a HV_DEFAULT_PAGE_SIZE_SMALL instead of the old HV_PAGE_SIZE_SMALL. The various PFN routines have been eliminated and only PA- or PTFN-based ones remain (since PTFNs are always expressed in fixed 2KB "page" size). The page-table management macros are renamed with a leading underscore and take page-size arguments with the presumption that clients will use those macros in some single place to provide the "real" macros they will use themselves.
I happened to notice the old hv_set_caching() API was totally broken (it assumed 4KB pages) so I changed it so it would nominally work correctly with other page sizes.
Tag modules with the page size so you can't load a module built with a conflicting page size. (And add a test for SMP while we're at it.)
--- arch/tile/Kconfig | 25 ++++ arch/tile/include/asm/Kbuild | 1 - arch/tile/include/asm/mmu.h | 2 +- arch/tile/include/asm/mmu_context.h | 8 +- arch/tile/include/asm/module.h | 40 +++++++ arch/tile/include/asm/page.h | 13 ++- arch/tile/include/asm/pgalloc.h | 92 +++++++++++---- arch/tile/include/asm/pgtable.h | 10 +- arch/tile/include/asm/pgtable_32.h | 14 ++- arch/tile/include/asm/pgtable_64.h | 28 +++-- arch/tile/include/hv/drv_xgbe_intf.h | 2 +- arch/tile/include/hv/hypervisor.h | 214 +++++++++++++++++++--------------- arch/tile/kernel/head_32.S | 8 +- arch/tile/kernel/head_64.S | 22 ++-- arch/tile/kernel/machine_kexec.c | 7 +- arch/tile/kernel/setup.c | 8 +- arch/tile/kernel/smp.c | 2 +- arch/tile/kernel/stack.c | 13 +- arch/tile/lib/memcpy_tile64.c | 8 +- arch/tile/mm/init.c | 11 +-- arch/tile/mm/pgtable.c | 27 ++--- 21 files changed, 351 insertions(+), 204 deletions(-) create mode 100644 arch/tile/include/asm/module.h
arch/tile/Kconfig +25 -0
@@ -138,6 +138,31 @@ config NR_CPUS smaller kernel memory footprint results from using a smaller value on chips with fewer tiles. +if TILEGX + +choice + prompt "Kernel page size" + default PAGE_SIZE_64KB + help + This lets you select the page size of the kernel. For best + performance on memory-intensive applications, a page size of 64KB + is recommended. For workloads involving many small files, many + connections, etc., it may be better to select 16KB, which uses + memory more efficiently at some cost in TLB performance. + + Note that this option is TILE-Gx specific; currently + TILEPro page size is set by rebuilding the hypervisor. + +config PAGE_SIZE_16KB + bool "16KB" + +config PAGE_SIZE_64KB + bool "64KB" + +endchoice + +endif + source "kernel/time/Kconfig" source "kernel/Kconfig.hz"
arch/tile/include/asm/Kbuild +0 -1
@@ -21,7 +21,6 @@ generic-y += ipcbuf.h generic-y += irq_regs.h generic-y += kdebug.h generic-y += local.h -generic-y += module.h generic-y += msgbuf.h generic-y += mutex.h generic-y += param.h
arch/tile/include/asm/mmu.h +1 -1
@@ -21,7 +21,7 @@ struct mm_context {* Written under the mmap_sem semaphore; read without the * semaphore but atomically, but it is conservatively set. */ -unsigned int priority_cached; +unsigned long priority_cached; };typedef struct mm_context mm_context_t ;
arch/tile/include/asm/mmu_context.h +6 -2
@@ -30,11 +30,15 @@ init_new_context(struct task_struct *tsk, struct mm_struct *mm)return 0 ; } -/* Note that arch/tile/kernel/head.S also calls hv_install_context() */ +/* +* Note that arch/tile/kernel/head_NN.S and arch/tile/mm/migrate_NN.S +* also call hv_install_context(). +*/ static inline void __install_page_table (pgd_t *pgdir,int asid,pgprot_t prot) {/* FIXME: DIRECTIO should not always be set. FIXME. */ -int rc =hv_install_context (__pa (pgdir), prot, asid,HV_CTX_DIRECTIO ); +int rc =hv_install_context (__pa (pgdir), prot, asid, +HV_CTX_DIRECTIO |CTX_PAGE_FLAG );if (rc <0 )panic ("hv_install_context failed: %d" , rc); }
arch/tile/include/asm/module.h new file +40 -0
@@ -0,0 +1,40 @@ +/* +* Copyright 2011 Tilera Corporation. All Rights Reserved. +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation, version 2. +* +* This program is distributed in the hope that it will be useful, but +* WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or +* NON INFRINGEMENT. See the GNU General Public License for +* more details. +*/ + +#ifndef _ASM_TILE_MODULE_H +#define _ASM_TILE_MODULE_H + +#include <arch/chip.h> + +#include <asm-generic/module.h> + +/* We can't use modules built with different page sizes. */ +#if defined(CONFIG_PAGE_SIZE_16KB ) +# define MODULE_PGSZ " 16KB" +#elif defined(CONFIG_PAGE_SIZE_64KB ) +# define MODULE_PGSZ " 64KB" +#else +# define MODULE_PGSZ "" +#endif + +/* We don't really support no-SMP so tag if someone tries. */ +#ifdef CONFIG_SMP +#define MODULE_NOSMP "" +#else +#define MODULE_NOSMP " nosmp" +#endif + +#define MODULE_ARCH_VERMAGIC CHIP_ARCH_NAME MODULE_PGSZ MODULE_NOSMP + +#endif /* _ASM_TILE_MODULE_H */
arch/tile/include/asm/page.h +11 -2
@@ -20,8 +20,17 @@#include <arch/chip.h> /* PAGE_SHIFT and HPAGE_SHIFT determine the page sizes. */ -#define PAGE_SHIFT HV_LOG2_PAGE_SIZE_SMALL -#define HPAGE_SHIFT HV_LOG2_PAGE_SIZE_LARGE +#if defined(CONFIG_PAGE_SIZE_16KB ) +#define PAGE_SHIFT 14 +#define CTX_PAGE_FLAG HV_CTX_PG_SM_16K +#elif defined(CONFIG_PAGE_SIZE_64KB ) +#define PAGE_SHIFT 16 +#define CTX_PAGE_FLAG HV_CTX_PG_SM_64K +#else +#define PAGE_SHIFT HV_LOG2_DEFAULT_PAGE_SIZE_SMALL +#define CTX_PAGE_FLAG 0 +#endif +#define HPAGE_SHIFT HV_LOG2_DEFAULT_PAGE_SIZE_LARGE#define PAGE_SIZE (_AC(1, UL) << PAGE_SHIFT)#define HPAGE_SIZE (_AC(1, UL) << HPAGE_SHIFT)
arch/tile/include/asm/pgalloc.h +67 -25
140 lines not on this page · raw message
arch/tile/include/asm/pgtable.h +6 -4
@@ -27,9 +27,11 @@#include <linux/slab.h> #include <linux/list.h> #include <linux/spinlock.h> +#include <linux/pfn.h> #include <asm/processor.h> #include <asm/fixmap.h> #include <asm/system.h> +#include <asm/page.h> struct mm_struct ;struct vm_area_struct ;
@@ -163,7 +165,7 @@ extern void set_page_homes(void); (pgprot_t ) { ((oldprot).val & ~_PAGE_ALL) | (newprot).val } /* Just setting the PFN to zero suffices. */ -#define pte_pgprot (x) hv_pte_set_pfn((x), 0) +#define pte_pgprot (x) hv_pte_set_pa((x), 0)/* * For PTEs and PDEs, we must clear the Present bit first when
@@ -263,7 +265,7 @@ static inline int pte_none(pte_t pte)static inline unsigned long pte_pfn (pte_t pte) { -return hv_pte_get_pfn (pte); +return PFN_DOWN (hv_pte_get_pa (pte)); }/* Set or get the remote cache cpu in a pgprot with remote caching. */
@@ -272,7 +274,7 @@ extern int get_remote_cache_cpu(pgprot_t prot);static inline pte_t pfn_pte (unsigned long pfn,pgprot_t prot) { -return hv_pte_set_pfn (prot, pfn); +return hv_pte_set_pa (prot,PFN_PHYS (pfn)); }/* Support for priority mappings. */
@@ -472,7 +474,7 @@ static inline unsigned long pmd_page_vaddr(pmd_t pmd)* OK for pte_lockptr(), since we just end up with potentially one * lock being used for several pte_t arrays. */ -#define pmd_page (pmd) pfn_to_page(HV_PTFN_TO_PFN(pmd_ptfn(pmd))) +#define pmd_page (pmd) pfn_to_page(PFN_DOWN(HV_PTFN_TO_CPA(pmd_ptfn(pmd))))static inline void pmd_clear (pmd_t *pmdp) {
arch/tile/include/asm/pgtable_32.h +8 -6
@@ -20,11 +20,12 @@* The level-1 index is defined by the huge page size. A PGD is composed * of PTRS_PER_PGD pgd_t's and is the top level of the page table. */ -#define PGDIR_SHIFT HV_LOG2_PAGE_SIZE_LARGE -#define PGDIR_SIZE HV_PAGE_SIZE_LARGE +#define PGDIR_SHIFT HPAGE_SHIFT +#define PGDIR_SIZE HPAGE_SIZE#define PGDIR_MASK (~(PGDIR_SIZE-1)) -#define PTRS_PER_PGD (1 << (32 - PGDIR_SHIFT)) -#define SIZEOF_PGD (PTRS_PER_PGD * sizeof(pgd_t)) +#define PTRS_PER_PGD _HV_L1_ENTRIES(HPAGE_SHIFT) +#define PGD_INDEX (va) _HV_L1_INDEX(va, HPAGE_SHIFT) +#define SIZEOF_PGD _HV_L1_SIZE(HPAGE_SHIFT)/* * The level-2 index is defined by the difference between the huge
@@ -33,8 +34,9 @@* Note that the hypervisor docs use PTE for what we call pte_t, so * this nomenclature is somewhat confusing. */ -#define PTRS_PER_PTE (1 << (HV_LOG2_PAGE_SIZE_LARGE - HV_LOG2_PAGE_SIZE_SMALL)) -#define SIZEOF_PTE (PTRS_PER_PTE * sizeof(pte_t)) +#define PTRS_PER_PTE _HV_L2_ENTRIES(HPAGE_SHIFT, PAGE_SHIFT) +#define PTE_INDEX (va) _HV_L2_INDEX(va, HPAGE_SHIFT, PAGE_SHIFT) +#define SIZEOF_PTE _HV_L2_SIZE(HPAGE_SHIFT, PAGE_SHIFT)#ifndef __ASSEMBLY__
arch/tile/include/asm/pgtable_64.h +16 -12
@@ -21,17 +21,19 @@#define PGDIR_SIZE HV_L1_SPAN#define PGDIR_MASK (~(PGDIR_SIZE-1))#define PTRS_PER_PGD HV_L0_ENTRIES -#define SIZEOF_PGD (PTRS_PER_PGD * sizeof(pgd_t)) +#define PGD_INDEX (va) HV_L0_INDEX(va) +#define SIZEOF_PGD HV_L0_SIZE/* * The level-1 index is defined by the huge page size. A PMD is composed * of PTRS_PER_PMD pgd_t's and is the middle level of the page table. */ -#define PMD_SHIFT HV_LOG2_PAGE_SIZE_LARGE -#define PMD_SIZE HV_PAGE_SIZE_LARGE +#define PMD_SHIFT HPAGE_SHIFT +#define PMD_SIZE HPAGE_SIZE#define PMD_MASK (~(PMD_SIZE-1)) -#define PTRS_PER_PMD (1 << (PGDIR_SHIFT - PMD_SHIFT)) -#define SIZEOF_PMD (PTRS_PER_PMD * sizeof(pmd_t)) +#define PTRS_PER_PMD _HV_L1_ENTRIES(HPAGE_SHIFT) +#define PMD_INDEX (va) _HV_L1_INDEX(va, HPAGE_SHIFT) +#define SIZEOF_PMD _HV_L1_SIZE(HPAGE_SHIFT)/* * The level-2 index is defined by the difference between the huge
@@ -40,17 +42,19 @@* Note that the hypervisor docs use PTE for what we call pte_t, so * this nomenclature is somewhat confusing. */ -#define PTRS_PER_PTE (1 << (HV_LOG2_PAGE_SIZE_LARGE - HV_LOG2_PAGE_SIZE_SMALL)) -#define SIZEOF_PTE (PTRS_PER_PTE * sizeof(pte_t)) +#define PTRS_PER_PTE _HV_L2_ENTRIES(HPAGE_SHIFT, PAGE_SHIFT) +#define PTE_INDEX (va) _HV_L2_INDEX(va, HPAGE_SHIFT, PAGE_SHIFT) +#define SIZEOF_PTE _HV_L2_SIZE(HPAGE_SHIFT, PAGE_SHIFT)/* -* Align the vmalloc area to an L2 page table, and leave a guard page -* at the beginning and end. The vmalloc code also puts in an internal +* Align the vmalloc area to an L2 page table. Omit guard pages at +* the beginning and end for simplicity (particularly in the per-cpu +* memory allocation code). The vmalloc code puts in an internal * guard page between each allocation. */ #define _VMALLOC_END HUGE_VMAP_BASE -#define VMALLOC_END (_VMALLOC_END - PAGE_SIZE) -#define VMALLOC_START (_VMALLOC_START + PAGE_SIZE) +#define VMALLOC_END _VMALLOC_END +#define VMALLOC_START _VMALLOC_START#define HUGE_VMAP_END (HUGE_VMAP_BASE + PGDIR_SIZE)
@@ -98,7 +102,7 @@ static inline int pud_bad(pud_t pud)* A pud_t points to a pmd_t array. Since we can have multiple per * page, we don't have a one-to-one mapping of pud_t's to pages. */ -#define pud_page (pud) pfn_to_page(HV_PTFN_TO_PFN(pud_ptfn(pud))) +#define pud_page (pud) pfn_to_page(PFN_DOWN(HV_PTFN_TO_CPA(pud_ptfn(pud))))static inline unsigned long pud_index (unsigned long address) {
arch/tile/include/hv/drv_xgbe_intf.h +1 -1
@@ -460,7 +460,7 @@ typedef void* lepp_comp_t;* linux's "MAX_SKB_FRAGS", and presumably over-estimates by one, for * our page size of exactly 65536. We add one for a "body" fragment. */ -#define LEPP_MAX_FRAGS (65536 / HV_PAGE_SIZE_SMALL + 2 + 1) +#define LEPP_MAX_FRAGS (65536 / HV_DEFAULT_PAGE_SIZE_SMALL + 2 + 1)/** Total number of bytes needed for an lepp_tso_cmd_t. */ #define LEPP_TSO_CMD_SIZE (num_frags, header_size) \
arch/tile/include/hv/hypervisor.h +120 -94
348 lines not on this page · raw message
arch/tile/kernel/head_32.S +4 -4
@@ -69,7 +69,7 @@ ENTRY(_start) } { moveli lr, lo16(1f) - move r5, zero + moveli r5, CTX_PAGE_FLAG } { auli lr, lr, ha16(1f)
@@ -141,11 +141,11 @@ ENTRY(empty_zero_page) .macro PTE va, cpa, bits1, no_org=0 .ifeq \no_org - .org swapper_pg_dir + HV_L1_INDEX(\va) * HV_PTE_SIZE + .org swapper_pg_dir + PGD_INDEX(\va) * HV_PTE_SIZE .endif .word HV_PTE_PAGE | HV_PTE_DIRTY | HV_PTE_PRESENT | HV_PTE_ACCESSED | \ (HV_PTE_MODE_CACHE_NO_L3 << HV_PTE_INDEX_MODE) - .word (\bits1) | (HV_CPA_TO_PFN(\cpa) << (HV_PTE_INDEX_PFN - 32)) + .word (\bits1) | (HV_CPA_TO_PTFN(\cpa) << (HV_PTE_INDEX_PTFN - 32)) .endm __PAGE_ALIGNED_DATA
@@ -166,7 +166,7 @@ ENTRY(swapper_pg_dir) /* The true text VAs are mapped as VA = PA + MEM_SV_INTRPT */ PTE MEM_SV_INTRPT, 0, (1 << (HV_PTE_INDEX_READABLE - 32)) | \ (1 << (HV_PTE_INDEX_EXECUTABLE - 32)) - .org swapper_pg_dir + HV_L1_SIZE + .org swapper_pg_dir + PGDIR_SIZE END(swapper_pg_dir) /*
arch/tile/kernel/head_64.S +11 -11
@@ -114,7 +114,7 @@ ENTRY(_start) shl16insli r0, r0, hw0(swapper_pg_dir - PAGE_OFFSET) } { - move r3, zero + moveli r3, CTX_PAGE_FLAG j hv_install_context } 1:
@@ -210,19 +210,19 @@ ENTRY(empty_zero_page) .macro PTE cpa, bits1 .quad HV_PTE_PAGE | HV_PTE_DIRTY | HV_PTE_PRESENT | HV_PTE_ACCESSED |\ HV_PTE_GLOBAL | (HV_PTE_MODE_CACHE_NO_L3 << HV_PTE_INDEX_MODE) |\ - (\bits1) | (HV_CPA_TO_PFN(\cpa) << HV_PTE_INDEX_PFN) + (\bits1) | (HV_CPA_TO_PTFN(\cpa) << HV_PTE_INDEX_PTFN) .endm __PAGE_ALIGNED_DATA .align PAGE_SIZE ENTRY(swapper_pg_dir) - .org swapper_pg_dir + HV_L0_INDEX(PAGE_OFFSET) * HV_PTE_SIZE + .org swapper_pg_dir + PGD_INDEX(PAGE_OFFSET) * HV_PTE_SIZE .Lsv_data_pmd: .quad 0 /* PTE temp_data_pmd - PAGE_OFFSET, 0 */ - .org swapper_pg_dir + HV_L0_INDEX(MEM_SV_START) * HV_PTE_SIZE + .org swapper_pg_dir + PGD_INDEX(MEM_SV_START) * HV_PTE_SIZE .Lsv_code_pmd: .quad 0 /* PTE temp_code_pmd - PAGE_OFFSET, 0 */ - .org swapper_pg_dir + HV_L0_SIZE + .org swapper_pg_dir + SIZEOF_PGD END(swapper_pg_dir) .align HV_PAGE_TABLE_ALIGN
@@ -233,11 +233,11 @@ ENTRY(temp_data_pmd) * permissions later. */ .set addr, 0 - .rept HV_L1_ENTRIES + .rept PTRS_PER_PMD PTE addr, HV_PTE_READABLE | HV_PTE_WRITABLE - .set addr, addr + HV_PAGE_SIZE_LARGE + .set addr, addr + HPAGE_SIZE .endr - .org temp_data_pmd + HV_L1_SIZE + .org temp_data_pmd + SIZEOF_PMD END(temp_data_pmd) .align HV_PAGE_TABLE_ALIGN
@@ -248,11 +248,11 @@ ENTRY(temp_code_pmd) * permissions later. */ .set addr, 0 - .rept HV_L1_ENTRIES + .rept PTRS_PER_PMD PTE addr, HV_PTE_READABLE | HV_PTE_EXECUTABLE - .set addr, addr + HV_PAGE_SIZE_LARGE + .set addr, addr + HPAGE_SIZE .endr - .org temp_code_pmd + HV_L1_SIZE + .org temp_code_pmd + SIZEOF_PMD END(temp_code_pmd) /*
arch/tile/kernel/machine_kexec.c +5 -2
@@ -251,6 +251,7 @@ static void setup_quasi_va_is_pa(void)void machine_kexec (struct kimage *image) {void *reboot_code_buffer; +pte_t *ptep;void (*rnk)(unsigned long ,void *,unsigned long )__noreturn ;
@@ -266,8 +267,10 @@ void machine_kexec(struct kimage *image)*/ homecache_change_page_home (image->control_code_page,0 ,smp_processor_id ()); - reboot_code_buffer =vmap (&image->control_code_page,1 ,0 , -__pgprot (_PAGE_KERNEL | _PAGE_EXECUTABLE)); + reboot_code_buffer =page_address (image->control_code_page); +BUG_ON (reboot_code_buffer ==NULL ); + ptep =virt_to_pte (NULL , (unsigned long )reboot_code_buffer); +__set_pte (ptep,pte_mkexec (*ptep));memcpy (reboot_code_buffer, relocate_new_kernel, relocate_new_kernel_size); __flush_icache_range(
arch/tile/kernel/setup.c +4 -4
@@ -1390,13 +1390,13 @@ void __init setup_per_cpu_areas(void)for (i =0 ; i < size; i +=PAGE_SIZE , ++pfn, ++pg) {/* Update the vmalloc mapping and page home. */ -pte_t *ptep = -virt_to_pte (NULL , (unsigned long )ptr + i); +unsigned long addr = (unsigned long )ptr + i; +pte_t *ptep =virt_to_pte (NULL , addr);pte_t pte = *ptep;BUG_ON (pfn !=pte_pfn (pte)); pte =hv_pte_set_mode (pte,HV_PTE_MODE_CACHE_TILE_L3 ); pte =set_remote_cache_cpu (pte, cpu); -set_pte (ptep, pte); +set_pte_at (&init_mm, addr, ptep, pte);/* Update the lowmem mapping for consistency. */ lowmem_va = (unsigned long )pfn_to_kaddr (pfn);
@@ -1409,7 +1409,7 @@ void __init setup_per_cpu_areas(void)BUG_ON (pte_huge (*ptep)); }BUG_ON (pfn !=pte_pfn (*ptep)); -set_pte (ptep, pte); +set_pte_at (&init_mm, lowmem_va, ptep, pte); } }
arch/tile/kernel/smp.c +1 -1
@@ -216,7 +216,7 @@ void __init ipi_init(void)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 ; + offset =PFN_PHYS (pte_pfn (pte)); ipi_mappings[cpu] = ioremap_prot(offset, PAGE_SIZE, pte); }#endif
arch/tile/kernel/stack.c +6 -7
@@ -56,12 +56,12 @@ static int valid_address(struct KBacktraceIterator *kbt, unsigned long address)if (l1_pgtable ==NULL )return 0 ;/* can't read user space in other tasks */ + pte = l1_pgtable[PGD_INDEX (address)];#ifdef CONFIG_64BIT /* Find the real l1_pgtable by looking in the l0_pgtable. */ - pte = l1_pgtable[HV_L0_INDEX (address)];if (!hv_pte_get_present (pte))return 0 ; - pfn =hv_pte_get_pfn (pte); + pfn =pte_pfn (pte);if (pte_huge (pte)) {if (!pfn_valid (pfn)) {pr_err ("L0 huge page has bad pfn %#lx\n" , pfn);
@@ -72,11 +72,11 @@ static int valid_address(struct KBacktraceIterator *kbt, unsigned long address) page =pfn_to_page (pfn);BUG_ON (PageHighMem (page));/* No HIGHMEM on 64-bit. */ l1_pgtable = (HV_PTE *)pfn_to_kaddr (pfn); + pte = l1_pgtable[PMD_INDEX (address)];#endif - pte = l1_pgtable[HV_L1_INDEX (address)];if (!hv_pte_get_present (pte))return 0 ; - pfn =hv_pte_get_pfn (pte); + pfn =pte_pfn (pte);if (pte_huge (pte)) {if (!pfn_valid (pfn)) {pr_err ("huge page has bad pfn %#lx\n" , pfn);
@@ -87,12 +87,11 @@ static int valid_address(struct KBacktraceIterator *kbt, unsigned long address) page =pfn_to_page (pfn);if (PageHighMem (page)) { -pr_err ("L2 page table not in LOWMEM (%#llx)\n" , -HV_PFN_TO_CPA (pfn)); +pr_err ("L2 page table not in LOWMEM (%#llx)\n" ,PFN_PHYS (pfn));return 0 ; } l2_pgtable = (HV_PTE *)pfn_to_kaddr (pfn); - pte = l2_pgtable[HV_L2_INDEX (address)]; + pte = l2_pgtable[PTE_INDEX (address)];return hv_pte_get_present (pte) &&hv_pte_get_readable (pte); }
arch/tile/lib/memcpy_tile64.c +4 -4
@@ -160,7 +160,7 @@ retry_source:break ;if (get_remote_cache_cpu (src_pte) ==smp_processor_id ())break ; - src_page =pfn_to_page (hv_pte_get_pfn (src_pte)); + src_page =pfn_to_page (pte_pfn (src_pte));get_page (src_page);if (pte_val (src_pte) !=pte_val (*src_ptep)) {put_page (src_page);
@@ -168,7 +168,7 @@ retry_source: }if (pte_huge (src_pte)) {/* Adjust the PTE to correspond to a small page */ -int pfn =hv_pte_get_pfn (src_pte); +int pfn =pte_pfn (src_pte); pfn += (((unsigned long )source & (HPAGE_SIZE -1 )) >>PAGE_SHIFT ); src_pte =pfn_pte (pfn, src_pte);
@@ -188,7 +188,7 @@ retry_dest:put_page (src_page);break ; } - dst_page =pfn_to_page (hv_pte_get_pfn (dst_pte)); + dst_page =pfn_to_page (pte_pfn (dst_pte));if (dst_page == src_page) {/* * Source and dest are on the same page; this
@@ -206,7 +206,7 @@ retry_dest: }if (pte_huge (dst_pte)) {/* Adjust the PTE to correspond to a small page */ -int pfn =hv_pte_get_pfn (dst_pte); +int pfn =pte_pfn (dst_pte); pfn += (((unsigned long )dest & (HPAGE_SIZE -1 )) >>PAGE_SHIFT ); dst_pte =pfn_pte (pfn, dst_pte);
arch/tile/mm/init.c +3 -8
@@ -83,7 +83,7 @@ static int num_l2_ptes[MAX_NUMNODES];static void init_prealloc_ptes (int node,int pages) { -BUG_ON (pages & (HV_L2_ENTRIES -1 )); +BUG_ON (pages & (PTRS_PER_PTE -1 ));if (pages) { num_l2_ptes[node] = pages; l2_ptes[node] = __alloc_bootmem(pages * sizeof(pte_t),
@@ -132,14 +132,9 @@ static void __init assign_pte(pmd_t *pmd, pte_t *page_table)#ifdef __tilegx__ -#if HV_L1_SIZE !=HV_L2_SIZE -# error Rework assumption that L1 and L2 page tables are same size. -#endif - -/* Since pmd_t arrays and pte_t arrays are the same size, just use casts. */ static inline pmd_t *alloc_pmd (void ) { -return (pmd_t *)alloc_pte (); +return __alloc_bootmem (L1_KERNEL_PGTABLE_SIZE ,HV_PAGE_TABLE_ALIGN ,0 ); }static inline void assign_pmd (pud_t *pud,pmd_t *pmd)
@@ -808,7 +803,7 @@ void __init paging_init(void)* changing init_mm once we get up and running, and there's no * need for e.g. vmalloc_sync_all(). */ -BUILD_BUG_ON (pgd_index (VMALLOC_START ) !=pgd_index (VMALLOC_END )); +BUILD_BUG_ON (pgd_index (VMALLOC_START ) !=pgd_index (VMALLOC_END -1 )); pud =pud_offset (pgd_base +pgd_index (VMALLOC_START ),VMALLOC_START );assign_pmd (pud,alloc_pmd ());#endif
arch/tile/mm/pgtable.c +12 -15
@@ -288,13 +288,12 @@ void pgd_free(struct mm_struct *mm, pgd_t *pgd)#define L2_USER_PGTABLE_PAGES (1 << L2_USER_PGTABLE_ORDER) -struct page *pte_alloc_one (struct mm_struct *mm,unsigned long address) +struct page *pgtable_alloc_one (struct mm_struct *mm,unsigned long address, +int order) {gfp_t flags =GFP_KERNEL |__GFP_REPEAT|__GFP_ZERO;struct page *p; -#if L2_USER_PGTABLE_ORDER >0 int i; -#endif #ifdef CONFIG_HIGHPTE flags |= __GFP_HIGHMEM;
@@ -304,17 +303,15 @@ struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address)if (p ==NULL )return NULL ; -#if L2_USER_PGTABLE_ORDER >0 /* * Make every page have a page_count() of one, not just the first. * We don't use __GFP_COMP since it doesn't look like it works * correctly with tlb_remove_page(). */ -for (i =1 ; i <L2_USER_PGTABLE_PAGES ; ++i) { +for (i =1 ; i < order; ++i) {init_page_count (p+i);inc_zone_page_state (p+i,NR_PAGETABLE ); } -#endif pgtable_page_ctor (p);return p;
@@ -325,28 +322,28 @@ struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address)* process). We have to correct whatever pte_alloc_one() did before * returning the pages to the allocator. */ -void pte_free (struct mm_struct *mm,struct page *p) +void pgtable_free (struct mm_struct *mm,struct page *p,int order) {int i;pgtable_page_dtor (p);__free_page (p); -for (i =1 ; i <L2_USER_PGTABLE_PAGES ; ++i) { +for (i =1 ; i < order; ++i) {__free_page (p+i);dec_zone_page_state (p+i,NR_PAGETABLE ); } } -void __pte_free_tlb (struct mmu_gather *tlb,struct page *pte, -unsigned long address) +void __pgtable_free_tlb (struct mmu_gather *tlb,struct page *pte, +unsigned long address,int order) {int i;pgtable_page_dtor (pte);tlb_remove_page (tlb, pte); -for (i =1 ; i <L2_USER_PGTABLE_PAGES ; ++i) { +for (i =1 ; i < order; ++i) {tlb_remove_page (tlb, pte + i);dec_zone_page_state (pte + i,NR_PAGETABLE ); }
@@ -481,7 +478,7 @@ void set_pte(pte_t *ptep, pte_t pte)/* Can this mm load a PTE with cached_priority set? */ static inline int mm_is_priority_cached (struct mm_struct *mm) { -return mm->context.priority_cached; +return mm->context.priority_cached !=0 ; }/*
@@ -491,8 +488,8 @@ static inline int mm_is_priority_cached(struct mm_struct *mm)void start_mm_caching (struct mm_struct *mm) {if (!mm_is_priority_cached (mm)) { - mm->context.priority_cached =-1U ; -hv_set_caching (-1U ); + mm->context.priority_cached =-1UL ; +hv_set_caching (-1UL ); } }
@@ -507,7 +504,7 @@ void start_mm_caching(struct mm_struct *mm)* Presumably we'll come back later and have more luck and clear * the value then; for now we'll just keep the cache marked for priority. */ -static unsigned int update_priority_cached (struct mm_struct *mm) +static unsigned long update_priority_cached (struct mm_struct *mm) {if (mm->context.priority_cached &&down_write_trylock (&mm->mmap_sem)) {struct vm_area_struct *vm;
Signature · 1 line
1.6.5.2
PATCH 1/1 arch/tile: optimize get_user/put_user and friends
In reply to a message not in the archiveUse direct load/store for the get_user/put_user.
Previously, we would call out to a helper routine that would do the appropriate thing and then return, handling the possible exception internally. Now we inline the load or store, along with a "we succeeded" indication in a register; if the load or store faults, we write a "we failed" indication into the same register and then return to the following instruction. This is more efficient and gives us more compact code, as well as being more in line with what other architectures do.
The special futex assembly source file for TILE-Gx also disappears in this change; we just use the same inlining idiom there as well, putting the appropriate atomic operations directly into futex_atomic_op_inuser() (and thus into the FUTEX_WAIT function).
The underlying atomic copy_from_user, copy_to_user functions were renamed using the (cryptic) x86 convention as copy_from_user_ll and copy_to_user_ll.
--- arch/tile/include/asm/atomic_32.h | 10 ++ arch/tile/include/asm/futex.h | 143 ++++++++++++++++-------- arch/tile/include/asm/uaccess.h | 222 ++++++++++++++++++++++--------------- arch/tile/kernel/Makefile | 1 - arch/tile/lib/atomic_32.c | 47 +-------- arch/tile/lib/exports.c | 8 -- arch/tile/lib/usercopy_32.S | 76 ------------- arch/tile/lib/usercopy_64.S | 49 -------- 8 files changed, 241 insertions(+), 315 deletions(-)
arch/tile/include/asm/atomic_32.h +10 -0
@@ -302,7 +302,14 @@ void __init_atomic_per_cpu(void);void __atomic_fault_unlock (int *lock_ptr);#endif +/* Return a pointer to the lock for the given address. */ +int *__atomic_hashed_lock (volatile void *v); +/* Private helper routines in lib/atomic_asm_32.S */ +struct __get_user { +unsigned long val; +int err; +};extern struct __get_user __atomic_cmpxchg (volatile int *p,int *lock,int o,int n);extern struct __get_user __atomic_xchg (volatile int *p,int *lock,int n);
@@ -318,6 +325,9 @@ extern u64 __atomic64_xchg_add(volatile u64 *p, int *lock, u64 n);extern u64 __atomic64_xchg_add_unless (volatile u64 *p,int *lock,u64 o,u64 n); +/* Return failure from the atomic wrappers. */ +struct __get_user __atomic_bad_address (int __user *addr); +#endif /* !__ASSEMBLY__ */ #endif /* _ASM_TILE_ATOMIC_32_H */
arch/tile/include/asm/futex.h +98 -45
203 lines not on this page · raw message
arch/tile/include/asm/uaccess.h +132 -90
253 lines not on this page · raw message
arch/tile/kernel/Makefile +0 -1
@@ -9,7 +9,6 @@ obj-y := backtrace.o entry.o init_task.o irq.o messaging.o \ intvec_$(BITS).o regs_$(BITS).o tile-desc_$(BITS).o obj-$(CONFIG_HARDWALL) += hardwall.o -obj-$(CONFIG_TILEGX) += futex_64.o obj-$(CONFIG_COMPAT) += compat.o compat_signal.o obj-$(CONFIG_SMP) += smpboot.o smp.o tlb.o obj-$(CONFIG_MODULES) += module.o
arch/tile/lib/atomic_32.c +1 -46
69 lines not on this page · raw message
arch/tile/lib/exports.c +0 -8
@@ -18,14 +18,6 @@/* arch/tile/lib/usercopy.S */ #include <linux/uaccess.h> -EXPORT_SYMBOL (__get_user_1); -EXPORT_SYMBOL (__get_user_2); -EXPORT_SYMBOL (__get_user_4); -EXPORT_SYMBOL (__get_user_8); -EXPORT_SYMBOL (__put_user_1); -EXPORT_SYMBOL (__put_user_2); -EXPORT_SYMBOL (__put_user_4); -EXPORT_SYMBOL (__put_user_8);EXPORT_SYMBOL (strnlen_user_asm);EXPORT_SYMBOL (strncpy_from_user_asm);EXPORT_SYMBOL (clear_user_asm);
arch/tile/lib/usercopy_32.S +0 -76
82 lines not on this page · raw message
arch/tile/lib/usercopy_64.S +0 -49
55 lines not on this page · raw message
Signature · 1 line
1.6.5.2
PATCH 1/1 arch/tile: support building big-endian kernel
In reply to a message not in the archiveThe toolchain supports big-endian mode now, so add support for building the kernel to run big-endian as well.
--- arch/tile/include/asm/byteorder.h | 20 ++++++++++++++++++++ arch/tile/include/asm/elf.h | 5 +++++ arch/tile/kernel/module.c | 12 +++++++++++- arch/tile/kernel/single_step.c | 16 ++++++++++++---- arch/tile/lib/memchr_64.c | 8 +++----- arch/tile/lib/memcpy_64.c | 23 +++++++++++++++++++++-- arch/tile/lib/strchr_64.c | 15 +++++---------- arch/tile/lib/string-endian.h | 33 +++++++++++++++++++++++++++++++++ arch/tile/lib/strlen_64.c | 11 ++++------- 9 files changed, 114 insertions(+), 29 deletions(-) create mode 100644 arch/tile/lib/string-endian.h
arch/tile/include/asm/byteorder.h +20 -0
@@ -1 +1,21 @@ +/* +* Copyright 2011 Tilera Corporation. All Rights Reserved. +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation, version 2. +* +* This program is distributed in the hope that it will be useful, but +* WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or +* NON INFRINGEMENT. See the GNU General Public License for +* more details. +*/ + +#if defined (__BIG_ENDIAN__) +#include <linux/byteorder/big_endian.h> +#elif defined (__LITTLE_ENDIAN__)#include <linux/byteorder/little_endian.h> +#else +#error "__BIG_ENDIAN__ or __LITTLE_ENDIAN__ must be defined." +#endif
arch/tile/include/asm/elf.h +5 -0
@@ -44,7 +44,11 @@ typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG];#else #define ELF_CLASS ELFCLASS32#endif +#ifdef __BIG_ENDIAN__ +#define ELF_DATA ELFDATA2MSB +#else #define ELF_DATA ELFDATA2LSB +#endif /* * There seems to be a bug in how compat_binfmt_elf.c works: it
@@ -59,6 +63,7 @@ enum { ELF_ARCH = CHIP_ELF_TYPE() };*/ #define elf_check_arch (x) \ ((x)->e_ident[EI_CLASS] == ELF_CLASS && \ + (x)->e_ident[EI_DATA] == ELF_DATA && \ (x)->e_machine == CHIP_ELF_TYPE())/* The module loader only handles a few relocation types. */
arch/tile/kernel/module.c +11 -1
@@ -157,7 +157,17 @@ int apply_relocate_add(Elf_Shdr *sechdrs,switch (ELF_R_TYPE (rel[i].r_info)) { -#define MUNGE (func) (*location = ((*location & ~func(-1)) | func(value))) +#ifdef __LITTLE_ENDIAN +# define MUNGE (func) \ + (*location = ((*location & ~func(-1)) | func(value))) +#else +/* +* Instructions are always little-endian, so when we read them as data, +* we have to swap them around before and after modifying them. +*/ +# define MUNGE (func) \ + (*location = swab64((swab64(*location) & ~func(-1)) | func(value))) +#endif #ifndef __tilegx__case R_TILE_32 :
arch/tile/kernel/single_step.c +12 -4
@@ -152,9 +152,6 @@ static tile_bundle_bits rewrite_load_store_unaligned(if (((unsigned long )addr % size) ==0 )return bundle; -#ifndef __LITTLE_ENDIAN -# error We assume little-endian representation with copy_xx_user size 2 here -#endif /* Handle unaligned load/store */ if (mem_op ==MEMOP_LOAD || mem_op ==MEMOP_LOAD_POSTINCR ) {unsigned short val_16;
@@ -175,8 +172,19 @@ static tile_bundle_bits rewrite_load_store_unaligned( state->update =1 ; } }else { +unsigned short val_16; val = (val_reg ==TREG_ZERO ) ?0 : regs->regs[val_reg]; - err =copy_to_user (addr, &val, size); +switch (size) { +case 2 : + val_16 = val; + err =copy_to_user (addr, &val_16,sizeof (val_16)); +break ; +case 4 : + err =copy_to_user (addr, &val,sizeof (val)); +break ; +default : +BUG (); + } }if (err) {
arch/tile/lib/memchr_64.c +3 -5
@@ -15,6 +15,7 @@#include <linux/types.h> #include <linux/string.h> #include <linux/module.h> +#include "string-endian.h" void *memchr (const void *s,int c,size_t n) {
@@ -39,11 +40,8 @@ void *memchr(const void *s, int c, size_t n)/* Read the first word, but munge it so that bytes before the array * will not match goal. -* -* Note that this shift count expression works because we know -* shift counts are taken mod 64. */ - before_mask = (1ULL << (s_int <<3 )) -1 ; + before_mask =MASK (s_int); v = (*p | before_mask) ^ (goal & before_mask);/* Compute the address of the last byte. */
@@ -65,7 +63,7 @@ void *memchr(const void *s, int c, size_t n)/* We found a match, but it might be in a byte past the end * of the array. */ - ret = ((char *)p) + (__insn_ctz (bits) >>3 ); + ret = ((char *)p) + (CFZ (bits) >>3 );return (ret <= last_byte_ptr) ? ret :NULL ; }EXPORT_SYMBOL (memchr);
arch/tile/lib/memcpy_64.c +21 -2
@@ -15,7 +15,6 @@#include <linux/types.h> #include <linux/string.h> #include <linux/module.h> -#define __memcpy memcpy/* EXPORT_SYMBOL() is in arch/tile/lib/exports.c since this should be asm. */ /* Must be 8 bytes in size. */
@@ -188,6 +187,7 @@ int USERCOPY_FUNC(void *__restrict dstv, const void *__restrict srcv, size_t n)/* n != 0 if we get here. Write out any trailing bytes. */ dst1 = (char *)dst8; +#ifndef __BIG_ENDIAN__if (n &4 ) {ST4 ((uint32_t *)dst1, final); dst1 +=4 ;
@@ -202,11 +202,30 @@ int USERCOPY_FUNC(void *__restrict dstv, const void *__restrict srcv, size_t n) }if (n)ST1 ((uint8_t *)dst1, final); +#else +if (n &4 ) { +ST4 ((uint32_t *)dst1, final >>32 ); + dst1 +=4 ; + } +else + { + final >>=32 ; + } +if (n &2 ) { +ST2 ((uint16_t *)dst1, final >>16 ); + dst1 +=2 ; + } +else + { + final >>=16 ; + } +if (n &1 ) +ST1 ((uint8_t *)dst1, final >>8 ); +#endif return RETVAL ; } -#ifdef USERCOPY_FUNC #undef ST1#undef ST2
arch/tile/lib/strchr_64.c +5 -10
@@ -15,8 +15,7 @@#include <linux/types.h> #include <linux/string.h> #include <linux/module.h> - -#undef strchr +#include "string-endian.h" char *strchr (const char *s,int c) {
@@ -33,13 +32,9 @@ char *strchr(const char *s, int c)* match neither zero nor goal (we make sure the high bit of each * byte is 1, and the low 7 bits are all the opposite of the goal * byte). -* -* Note that this shift count expression works because we know shift -* counts are taken mod 64. */ -const uint64_t before_mask = (1ULL << (s_int <<3 )) -1 ; -uint64_t v = (*p | before_mask) ^ - (goal &__insn_v1shrsi (before_mask,1 )); +const uint64_t before_mask =MASK (s_int); +uint64_t v = (*p | before_mask) ^ (goal &__insn_v1shrui (before_mask,1 ));uint64_t zero_matches, goal_matches;while (1 ) {
@@ -55,8 +50,8 @@ char *strchr(const char *s, int c) v = *++p; } - z =__insn_ctz (zero_matches); - g =__insn_ctz (goal_matches); + z =CFZ (zero_matches); + g =CFZ (goal_matches);/* If we found c before '\0' we got a match. Note that if c == '\0' * then g == z, and we correctly return the address of the '\0'
arch/tile/lib/string-endian.h new file +33 -0
@@ -0,0 +1,33 @@ +/* +* Copyright 2011 Tilera Corporation. All Rights Reserved. +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation, version 2. +* +* This program is distributed in the hope that it will be useful, but +* WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or +* NON INFRINGEMENT. See the GNU General Public License for +* more details. +* +* Provide a mask based on the pointer alignment that +* sets up non-zero bytes before the beginning of the string. +* The MASK expression works because shift counts are taken mod 64. +* Also, specify how to count "first" and "last" bits +* when the bits have been read as a word. +*/ + +#include <asm/byteorder.h> + +#ifdef __LITTLE_ENDIAN +#define MASK (x) (__insn_shl(1ULL, (x << 3)) - 1) +#define NULMASK (x) ((2ULL << x) - 1) +#define CFZ (x) __insn_ctz(x) +#define REVCZ (x) __insn_clz(x) +#else +#define MASK (x) (__insn_shl(-2LL, ((-x << 3) - 1))) +#define NULMASK (x) (-2LL << (63 - x)) +#define CFZ (x) __insn_clz(x) +#define REVCZ (x) __insn_ctz(x) +#endif
arch/tile/lib/strlen_64.c +4 -7
@@ -15,8 +15,7 @@#include <linux/types.h> #include <linux/string.h> #include <linux/module.h> - -#undef strlen +#include "string-endian.h" size_t strlen (const char *s) {
@@ -24,15 +23,13 @@ size_t strlen(const char *s)const uintptr_t s_int = (uintptr_t ) s;const uint64_t *p = (const uint64_t *)(s_int &-8 ); -/* Read the first word, but force bytes before the string to be nonzero. -* This expression works because we know shift counts are taken mod 64. -*/ -uint64_t v = *p | ((1ULL << (s_int <<3 )) -1 ); +/* Read and MASK the first word. */ +uint64_t v = *p |MASK (s_int);uint64_t bits;while ((bits =__insn_v1cmpeqi (v,0 )) ==0 ) v = *++p; -return ((const char *)p) + (__insn_ctz (bits) >>3 ) - s; +return ((const char *)p) + (CFZ (bits) >>3 ) - s; }EXPORT_SYMBOL (strlen);
Signature · 1 line
1.6.5.2
PATCH 1/1 arch/tile: use interrupt critical sections less
In reply to a message not in the archiveIn general we want to avoid ever touching memory while within an interrupt critical section, since the page fault path goes through a different path from the hypervisor when in an interrupt critical section, and we carefully decided with tilegx that we didn't need to support this path in the kernel. (On tilepro we did implement that path as part of supporting atomic instructions in software.)
In practice we always need to touch the kernel stack, since that's where we store the interrupt state before releasing the critical section, but this change cleans up a few things. The IRQ_ENABLE macro is split up so that when we want to enable interrupts in a deferred way (e.g. for cpu_idle or for interrupt return) we can read the per-cpu enable mask before entering the critical section. The cache-migration code is changed to use interrupt masking instead of interrupt critical sections. And, the interrupt-entry code is changed so that we defer loading "tp" from per-cpu data until after we have released the interrupt critical section.
--- arch/tile/include/asm/irqflags.h | 34 +++++++++++++---- arch/tile/kernel/entry.S | 3 +- arch/tile/kernel/intvec_64.S | 78 +++++++++++++++++++++----------------- arch/tile/mm/init.c | 4 ++ arch/tile/mm/migrate.h | 6 +++ arch/tile/mm/migrate_32.S | 36 ++++------------- arch/tile/mm/migrate_64.S | 34 +++------------- 7 files changed, 96 insertions(+), 99 deletions(-)
arch/tile/include/asm/irqflags.h +26 -8
@@ -28,10 +28,10 @@*/ #if CHIP_HAS_AUX_PERF_COUNTERS ()#define LINUX_MASKABLE_INTERRUPTS_HI \ - (~(INT_MASK_HI(INT_PERF_COUNT) | INT_MASK_HI(INT_AUX_PERF_COUNT))) + (~(INT_MASK_HI(INT_PERF_COUNT) | INT_MASK_HI(INT_AUX_PERF_COUNT)))#else #define LINUX_MASKABLE_INTERRUPTS_HI \ - (~(INT_MASK_HI(INT_PERF_COUNT))) + (~(INT_MASK_HI(INT_PERF_COUNT)))#endif #else
@@ -90,6 +90,14 @@__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) +#define interrupt_mask_save_mask () \ + (__insn_mfspr(SPR_INTERRUPT_MASK_SET_K_0) | \ + (((unsigned long long)__insn_mfspr(SPR_INTERRUPT_MASK_SET_K_1))<<32)) +#define interrupt_mask_restore_mask (mask) do { \ + unsigned long long __m = (mask); \ + __insn_mtspr(SPR_INTERRUPT_MASK_K_0, (unsigned long)(__m)); \ + __insn_mtspr(SPR_INTERRUPT_MASK_K_1, (unsigned long)(__m>>32)); \ +} while (0)#else #define interrupt_mask_set (n) \ __insn_mtspr(SPR_INTERRUPT_MASK_SET_K, (1UL << (n)))
@@ -101,6 +109,10 @@ __insn_mtspr(SPR_INTERRUPT_MASK_SET_K, (mask))#define interrupt_mask_reset_mask (mask) \ __insn_mtspr(SPR_INTERRUPT_MASK_RESET_K, (mask)) +#define interrupt_mask_save_mask () \ + __insn_mfspr(SPR_INTERRUPT_MASK_K) +#define interrupt_mask_restore_mask (mask) \ + __insn_mtspr(SPR_INTERRUPT_MASK_K, (mask))#endif /*
@@ -122,7 +134,7 @@ DECLARE_PER_CPU(unsigned long long, interrupts_enabled_mask);/* Disable all interrupts, including NMIs. */ #define arch_local_irq_disable_all () \ - interrupt_mask_set_mask(-1UL) + interrupt_mask_set_mask(-1ULL)/* Re-enable all maskable interrupts. */ #define arch_local_irq_enable () \
@@ -179,7 +191,7 @@ DECLARE_PER_CPU(unsigned long long, interrupts_enabled_mask);#ifdef __tilegx__#if INT_MEM_ERROR !=0 -# error Fix IRQ_DISABLED() macro +# error Fix IRQS_DISABLED() macro#endif /* Return 0 or 1 to indicate whether interrupts are currently disabled. */
@@ -207,9 +219,10 @@ DECLARE_PER_CPU(unsigned long long, interrupts_enabled_mask); mtspr SPR_INTERRUPT_MASK_SET_K, tmp/* Enable interrupts. */ -#define IRQ_ENABLE (tmp0, tmp1) \ +#define IRQ_ENABLE_LOAD (tmp0, tmp1) \ GET_INTERRUPTS_ENABLED_MASK_PTR(tmp0); \ - ld tmp0, tmp0; \ + ld tmp0, tmp0 +#define IRQ_ENABLE_APPLY (tmp0, tmp1) \ mtspr SPR_INTERRUPT_MASK_RESET_K, tmp0#else /* !__tilegx__ */
@@ -253,17 +266,22 @@ DECLARE_PER_CPU(unsigned long long, interrupts_enabled_mask); mtspr SPR_INTERRUPT_MASK_SET_K_1, tmp/* Enable interrupts. */ -#define IRQ_ENABLE (tmp0, tmp1) \ +#define IRQ_ENABLE_LOAD (tmp0, tmp1) \ GET_INTERRUPTS_ENABLED_MASK_PTR(tmp0); \ { \ lw tmp0, tmp0; \ addi tmp1, tmp0, 4 \ }; \ - lw tmp1, tmp1; \ + lw tmp1, tmp1 +#define IRQ_ENABLE_APPLY (tmp0, tmp1) \ mtspr SPR_INTERRUPT_MASK_RESET_K_0, tmp0; \ mtspr SPR_INTERRUPT_MASK_RESET_K_1, tmp1#endif +#define IRQ_ENABLE (tmp0, tmp1) \ + IRQ_ENABLE_LOAD(tmp0, tmp1); \ + IRQ_ENABLE_APPLY(tmp0, tmp1) +/* * Do the CPU's IRQ-state tracing from assembly code. We call a * C function, but almost everywhere we do, we don't mind clobbering
arch/tile/kernel/entry.S +2 -1
@@ -99,8 +99,9 @@ STD_ENTRY(smp_nap) */ STD_ENTRY(_cpu_idle) movei r1, 1 + IRQ_ENABLE_LOAD(r2, r3) mtspr INTERRUPT_CRITICAL_SECTION, r1 - IRQ_ENABLE(r2, r3) /* unmask, but still with ICS set */ + IRQ_ENABLE_APPLY(r2, r3) /* unmask, but still with ICS set */ mtspr INTERRUPT_CRITICAL_SECTION, zero .global _cpu_idle_nap _cpu_idle_nap:
arch/tile/kernel/intvec_64.S +43 -35
116 lines not on this page · raw message
arch/tile/mm/init.c +4 -0
@@ -450,6 +450,7 @@ static pgd_t pgtables[PTRS_PER_PGD]*/ static void __init kernel_physical_mapping_init (pgd_t *pgd_base) { +unsigned long long irqmask;unsigned long address, pfn;pmd_t *pmd;pte_t *pte;
@@ -630,10 +631,13 @@ static void __init kernel_physical_mapping_init(pgd_t *pgd_base)* - install pgtables[] as the real page table * - flush the TLB so the new page table takes effect */ + irqmask =interrupt_mask_save_mask (); +interrupt_mask_set_mask (-1ULL ); rc =flush_and_install_context (__pa (pgtables),init_pgprot ((unsigned long )pgtables),__get_cpu_var (current_asid),cpumask_bits (my_cpu_mask)); +interrupt_mask_restore_mask (irqmask);BUG_ON (rc !=0 );/* Copy the page table back to the normal swapper_pg_dir. */
arch/tile/mm/migrate.h +6 -0
@@ -24,6 +24,9 @@/* * This function is used as a helper when setting up the initial * page table (swapper_pg_dir). +* +* You must mask ALL interrupts prior to invoking this code, since +* you can't legally touch the stack during the cache flush. */ extern int flush_and_install_context(HV_PhysAddr page_table, HV_PTE access, HV_ASID asid,
@@ -39,6 +42,9 @@ extern int flush_and_install_context(HV_PhysAddr page_table, HV_PTE access,* * Note that any non-NULL pointers must not point to the page that * is handled by the stack_pte itself. +* +* You must mask ALL interrupts prior to invoking this code, since +* you can't legally touch the stack during the cache flush. */ extern int homecache_migrate_stack_and_flush(pte_t stack_pte, unsigned long va, size_t length, pte_t *stack_ptep,
arch/tile/mm/migrate_32.S +8 -28
@@ -40,8 +40,7 @@ #define FRAME_R32 16 #define FRAME_R33 20 #define FRAME_R34 24 -#define FRAME_R35 28 -#define FRAME_SIZE 32 +#define FRAME_SIZE 28
@@ -66,12 +65,11 @@ #define r_my_cpumask r5 /* Locals (callee-save); must not be more than FRAME_xxx above. */ -#define r_save_ics r30 -#define r_context_lo r31 -#define r_context_hi r32 -#define r_access_lo r33 -#define r_access_hi r34 -#define r_asid r35 +#define r_context_lo r30 +#define r_context_hi r31 +#define r_access_lo r32 +#define r_access_hi r33 +#define r_asid r34 STD_ENTRY(flush_and_install_context) /*
@@ -104,11 +102,7 @@ STD_ENTRY(flush_and_install_context) sw r_tmp, r33 addi r_tmp, sp, FRAME_R34 } - { - sw r_tmp, r34 - addi r_tmp, sp, FRAME_R35 - } - sw r_tmp, r35 + sw r_tmp, r34 /* Move some arguments to callee-save registers. */ {
@@ -121,13 +115,6 @@ STD_ENTRY(flush_and_install_context) } move r_asid, r_asid_in - /* Disable interrupts, since we can't use our stack. */ - { - mfspr r_save_ics, INTERRUPT_CRITICAL_SECTION - movei r_tmp, 1 - } - mtspr INTERRUPT_CRITICAL_SECTION, r_tmp - /* First, flush our L2 cache. */ { move r0, zero /* cache_pa */
@@ -163,7 +150,7 @@ STD_ENTRY(flush_and_install_context) } { move r4, r_asid - movei r5, HV_CTX_DIRECTIO + moveli r5, HV_CTX_DIRECTIO | CTX_PAGE_FLAG } jal hv_install_context bnz r0, .Ldone
@@ -175,9 +162,6 @@ STD_ENTRY(flush_and_install_context) } .Ldone: - /* Reset interrupts back how they were before. */ - mtspr INTERRUPT_CRITICAL_SECTION, r_save_ics - /* Restore the callee-saved registers and return. */ addli lr, sp, FRAME_SIZE {
@@ -202,10 +186,6 @@ STD_ENTRY(flush_and_install_context) } { lw r34, r_tmp - addli r_tmp, sp, FRAME_R35 - } - { - lw r35, r_tmp addi sp, sp, FRAME_SIZE } jrp lr
arch/tile/mm/migrate_64.S +7 -27
@@ -38,8 +38,7 @@ #define FRAME_R30 16 #define FRAME_R31 24 #define FRAME_R32 32 -#define FRAME_R33 40 -#define FRAME_SIZE 48 +#define FRAME_SIZE 40
@@ -60,10 +59,9 @@ #define r_my_cpumask r3 /* Locals (callee-save); must not be more than FRAME_xxx above. */ -#define r_save_ics r30 -#define r_context r31 -#define r_access r32 -#define r_asid r33 +#define r_context r30 +#define r_access r31 +#define r_asid r32 /* * Caller-save locals and frame constants are the same as
@@ -93,11 +91,7 @@ STD_ENTRY(flush_and_install_context) st r_tmp, r31 addi r_tmp, sp, FRAME_R32 } - { - st r_tmp, r32 - addi r_tmp, sp, FRAME_R33 - } - st r_tmp, r33 + st r_tmp, r32 /* Move some arguments to callee-save registers. */ {
@@ -106,13 +100,6 @@ STD_ENTRY(flush_and_install_context) } move r_asid, r_asid_in - /* Disable interrupts, since we can't use our stack. */ - { - mfspr r_save_ics, INTERRUPT_CRITICAL_SECTION - movei r_tmp, 1 - } - mtspr INTERRUPT_CRITICAL_SECTION, r_tmp - /* First, flush our L2 cache. */ { move r0, zero /* cache_pa */
@@ -147,7 +134,7 @@ STD_ENTRY(flush_and_install_context) } { move r2, r_asid - movei r3, HV_CTX_DIRECTIO + moveli r3, HV_CTX_DIRECTIO | CTX_PAGE_FLAG } jal hv_install_context bnez r0, 1f
@@ -158,10 +145,7 @@ STD_ENTRY(flush_and_install_context) jal hv_flush_all } -1: /* Reset interrupts back how they were before. */ - mtspr INTERRUPT_CRITICAL_SECTION, r_save_ics - - /* Restore the callee-saved registers and return. */ +1: /* Restore the callee-saved registers and return. */ addli lr, sp, FRAME_SIZE { ld lr, lr
@@ -177,10 +161,6 @@ STD_ENTRY(flush_and_install_context) } { ld r32, r_tmp - addli r_tmp, sp, FRAME_R33 - } - { - ld r33, r_tmp addi sp, sp, FRAME_SIZE } jrp lr
Signature · 1 line
1.6.5.2
PATCH 1/1 arch/tile: use 0 for IRQ_RESCHEDULE instead of 1
In reply to a message not in the archiveThis avoids assigning IRQ 0 to PCI devices, because we've seen that doesn't always work well.
--- arch/tile/include/asm/irq.h | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
arch/tile/include/asm/irq.h +1 -1
@@ -21,7 +21,7 @@#define NR_IRQS 32/* IRQ numbers used for linux IPIs. */ -#define IRQ_RESCHEDULE 1 +#define IRQ_RESCHEDULE 0#define irq_canonicalize (irq) (irq)
Signature · 1 line
1.6.5.2
PATCH 1/1 arch/tile: fix gcc 4.6 warnings in <asm/bitops_64.h>
In reply to a message not in the archiveFix some signedness and variable usage warnings in change_bit() and test_and_change_bit().
--- arch/tile/include/asm/bitops_64.h | 8 ++++---- 1 files changed, 4 insertions(+), 4 deletions(-)
arch/tile/include/asm/bitops_64.h +4 -4
@@ -39,10 +39,10 @@ static inline void clear_bit(unsigned nr, volatile unsigned long *addr) static inline void change_bit(unsigned nr, volatile unsigned long *addr) { - unsigned long old, mask = (1UL << (nr % BITS_PER_LONG)); - long guess, oldval; + unsigned long mask = (1UL << (nr % BITS_PER_LONG)); + unsigned long guess, oldval; addr += nr / BITS_PER_LONG; - old = *addr; + oldval = *addr; do { guess = oldval; oldval = atomic64_cmpxchg((atomic64_t *)addr,
@@ -86,7 +86,7 @@ static inline int test_and_change_bit(unsigned nr, volatile unsigned long *addr) {unsigned long mask = (1UL << (nr %BITS_PER_LONG )); -long guess, oldval = *addr; +unsigned long guess, oldval; addr += nr /BITS_PER_LONG ; oldval = *addr; do {
Signature · 1 line
1.6.5.2
PATCH 1/1 arch/tile: fix typo in <arch/spr_def.h>
In reply to a message not in the archiveWe aren't yet using this definition in the kernel, but fix it up before someone goes looking for it.
--- arch/tile/include/arch/spr_def.h | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-)
arch/tile/include/arch/spr_def.h +2 -2
@@ -60,8 +60,8 @@ _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 SPR_IPI_EVENT_SET_K \ + _concat4(SPR_IPI_EVENT_SET_, CONFIG_KERNEL_PL,,) #define INT_IPI_K \ _concat4(INT_IPI_, CONFIG_KERNEL_PL,,)
Signature · 1 line
1.6.5.2
PATCH 1/1 arch/tile/Kconfig: remove pointless "!M386" test.
In reply to a message not in the archiveLooks like a cut and paste bug from the x86 version.
--- arch/tile/Kconfig | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
arch/tile/Kconfig +1 -1
@@ -12,7 +12,7 @@ config TILE select GENERIC_PENDING_IRQ if SMP select GENERIC_IRQ_SHOW select SYS_HYPERVISOR - select ARCH_HAVE_NMI_SAFE_CMPXCHG if !M386 + select ARCH_HAVE_NMI_SAFE_CMPXCHG # FIXME: investigate whether we need/want these options. # select HAVE_IOREMAP_PROT
Signature · 1 line
1.6.5.2