Commit 0660a9b1 authored by Linus Torvalds's avatar Linus Torvalds

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

* git://git.kernel.org/pub/scm/linux/kernel/git/cmetcalf/linux-tile:
  arch/tile: mark "hardwall" device as non-seekable
  asm-generic/stat.h: support 64-bit file time_t for stat()
  arch/tile: don't allow user code to set the PL via ptrace or signal return
  arch/tile: correct double syscall restart for nested signals
  arch/tile: avoid __must_check warning on one strict_strtol check
  arch/tile: bomb raw_local_irq_ to arch_local_irq_
  arch/tile: complete migration to new kmap_atomic scheme
parents 65f75ace d02db4f8
......@@ -23,7 +23,6 @@
#include <linux/interrupt.h>
#include <linux/threads.h>
#include <asm/kmap_types.h>
#include <asm/tlbflush.h>
#include <asm/homecache.h>
......
......@@ -16,28 +16,42 @@
#define _ASM_TILE_KMAP_TYPES_H
/*
* In TILE Linux each set of four of these uses another 16MB chunk of
* address space, given 64 tiles and 64KB pages, so we only enable
* ones that are required by the kernel configuration.
* In 32-bit TILE Linux we have to balance the desire to have a lot of
* nested atomic mappings with the fact that large page sizes and many
* processors chew up address space quickly. In a typical
* 64-processor, 64KB-page layout build, making KM_TYPE_NR one larger
* adds 4MB of required address-space. For now we leave KM_TYPE_NR
* set to depth 8.
*/
enum km_type {
KM_TYPE_NR = 8
};
/*
* We provide dummy definitions of all the stray values that used to be
* required for kmap_atomic() and no longer are.
*/
enum {
KM_BOUNCE_READ,
KM_SKB_SUNRPC_DATA,
KM_SKB_DATA_SOFTIRQ,
KM_USER0,
KM_USER1,
KM_BIO_SRC_IRQ,
KM_BIO_DST_IRQ,
KM_PTE0,
KM_PTE1,
KM_IRQ0,
KM_IRQ1,
KM_SOFTIRQ0,
KM_SOFTIRQ1,
KM_MEMCPY0,
KM_MEMCPY1,
#if defined(CONFIG_HIGHPTE)
KM_PTE0,
KM_PTE1,
#endif
KM_TYPE_NR
KM_SYNC_ICACHE,
KM_SYNC_DCACHE,
KM_UML_USERCOPY,
KM_IRQ_PTE,
KM_NMI,
KM_NMI_PTE,
KM_KDB
};
#endif /* _ASM_TILE_KMAP_TYPES_H */
......@@ -344,10 +344,8 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
#define pgd_offset_k(address) pgd_offset(&init_mm, address)
#if defined(CONFIG_HIGHPTE)
extern pte_t *_pte_offset_map(pmd_t *, unsigned long address, enum km_type);
#define pte_offset_map(dir, address) \
_pte_offset_map(dir, address, KM_PTE0)
#define pte_unmap(pte) kunmap_atomic(pte, KM_PTE0)
extern pte_t *pte_offset_map(pmd_t *, unsigned long address);
#define pte_unmap(pte) kunmap_atomic(pte)
#else
#define pte_offset_map(dir, address) pte_offset_kernel(dir, address)
#define pte_unmap(pte) do { } while (0)
......
#ifdef CONFIG_COMPAT
#define __ARCH_WANT_STAT64 /* Used for compat_sys_stat64() etc. */
#endif
#include <asm-generic/stat.h>
......@@ -41,6 +41,7 @@ __SYSCALL(__NR_cmpxchg_badaddr, sys_cmpxchg_badaddr)
#ifdef CONFIG_COMPAT
#define __ARCH_WANT_SYS_LLSEEK
#endif
#define __ARCH_WANT_SYS_NEWFSTATAT
#endif
#endif /* _ASM_TILE_UNISTD_H */
......@@ -148,11 +148,11 @@ long tile_compat_sys_msgrcv(int msqid,
#define compat_sys_readahead sys32_readahead
#define compat_sys_sync_file_range compat_sys_sync_file_range2
/* The native 64-bit "struct stat" matches the 32-bit "struct stat64". */
#define compat_sys_stat64 sys_newstat
#define compat_sys_lstat64 sys_newlstat
#define compat_sys_fstat64 sys_newfstat
#define compat_sys_fstatat64 sys_newfstatat
/* We leverage the "struct stat64" type for 32-bit time_t/nsec. */
#define compat_sys_stat64 sys_stat64
#define compat_sys_lstat64 sys_lstat64
#define compat_sys_fstat64 sys_fstat64
#define compat_sys_fstatat64 sys_fstatat64
/* The native sys_ptrace dynamically handles compat binaries. */
#define compat_sys_ptrace sys_ptrace
......
......@@ -54,7 +54,7 @@ void early_printk(const char *fmt, ...)
void early_panic(const char *fmt, ...)
{
va_list ap;
raw_local_irq_disable_all();
arch_local_irq_disable_all();
va_start(ap, fmt);
early_printk("Kernel panic - not syncing: ");
early_vprintk(fmt, ap);
......
......@@ -151,12 +151,12 @@ enum direction_protect {
static void enable_firewall_interrupts(void)
{
raw_local_irq_unmask_now(INT_UDN_FIREWALL);
arch_local_irq_unmask_now(INT_UDN_FIREWALL);
}
static void disable_firewall_interrupts(void)
{
raw_local_irq_mask_now(INT_UDN_FIREWALL);
arch_local_irq_mask_now(INT_UDN_FIREWALL);
}
/* Set up hardwall on this cpu based on the passed hardwall_info. */
......@@ -768,13 +768,13 @@ static int hardwall_release(struct inode *inode, struct file *file)
}
static const struct file_operations dev_hardwall_fops = {
.open = nonseekable_open,
.unlocked_ioctl = hardwall_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = hardwall_compat_ioctl,
#endif
.flush = hardwall_flush,
.release = hardwall_release,
.llseek = noop_llseek,
};
static struct cdev hardwall_dev;
......
......@@ -26,7 +26,7 @@
#define IS_HW_CLEARED 1
/*
* The set of interrupts we enable for raw_local_irq_enable().
* The set of interrupts we enable for arch_local_irq_enable().
* This is initialized to have just a single interrupt that the kernel
* doesn't actually use as a sentinel. During kernel init,
* interrupts are added as the kernel gets prepared to support them.
......@@ -225,7 +225,7 @@ void __cpuinit setup_irq_regs(void)
/* Enable interrupt delivery. */
unmask_irqs(~0UL);
#if CHIP_HAS_IPI()
raw_local_irq_unmask(INT_IPI_K);
arch_local_irq_unmask(INT_IPI_K);
#endif
}
......
......@@ -182,13 +182,13 @@ static void kexec_find_and_set_command_line(struct kimage *image)
if ((entry & IND_SOURCE)) {
void *va =
kmap_atomic_pfn(entry >> PAGE_SHIFT, KM_USER0);
kmap_atomic_pfn(entry >> PAGE_SHIFT);
r = kexec_bn2cl(va);
if (r) {
command_line = r;
break;
}
kunmap_atomic(va, KM_USER0);
kunmap_atomic(va);
}
}
......@@ -198,7 +198,7 @@ static void kexec_find_and_set_command_line(struct kimage *image)
hverr = hv_set_command_line(
(HV_VirtAddr) command_line, strlen(command_line));
kunmap_atomic(command_line, KM_USER0);
kunmap_atomic(command_line);
} else {
pr_info("%s: no command line found; making empty\n",
__func__);
......
......@@ -34,7 +34,7 @@ void __cpuinit init_messaging(void)
panic("hv_register_message_state: error %d", rc);
/* Make sure downcall interrupts will be enabled. */
raw_local_irq_unmask(INT_INTCTRL_K);
arch_local_irq_unmask(INT_INTCTRL_K);
}
void hv_message_intr(struct pt_regs *regs, int intnum)
......
......@@ -50,10 +50,10 @@ long arch_ptrace(struct task_struct *child, long request,
{
unsigned long __user *datap = (long __user __force *)data;
unsigned long tmp;
int i;
long ret = -EIO;
unsigned long *childregs;
char *childreg;
struct pt_regs copyregs;
int ex1_offset;
switch (request) {
......@@ -80,6 +80,16 @@ long arch_ptrace(struct task_struct *child, long request,
if (addr >= PTREGS_SIZE)
break;
childreg = (char *)task_pt_regs(child) + addr;
/* Guard against overwrites of the privilege level. */
ex1_offset = PTREGS_OFFSET_EX1;
#if defined(CONFIG_COMPAT) && defined(__BIG_ENDIAN)
if (is_compat_task()) /* point at low word */
ex1_offset += sizeof(compat_long_t);
#endif
if (addr == ex1_offset)
data = PL_ICS_EX1(USER_PL, EX1_ICS(data));
#ifdef CONFIG_COMPAT
if (is_compat_task()) {
if (addr & (sizeof(compat_long_t)-1))
......@@ -96,26 +106,19 @@ long arch_ptrace(struct task_struct *child, long request,
break;
case PTRACE_GETREGS: /* Get all registers from the child. */
if (!access_ok(VERIFY_WRITE, datap, PTREGS_SIZE))
break;
childregs = (long *)task_pt_regs(child);
for (i = 0; i < sizeof(struct pt_regs)/sizeof(unsigned long);
++i) {
ret = __put_user(childregs[i], &datap[i]);
if (ret != 0)
break;
if (copy_to_user(datap, task_pt_regs(child),
sizeof(struct pt_regs)) == 0) {
ret = 0;
}
break;
case PTRACE_SETREGS: /* Set all registers in the child. */
if (!access_ok(VERIFY_READ, datap, PTREGS_SIZE))
break;
childregs = (long *)task_pt_regs(child);
for (i = 0; i < sizeof(struct pt_regs)/sizeof(unsigned long);
++i) {
ret = __get_user(childregs[i], &datap[i]);
if (ret != 0)
break;
if (copy_from_user(&copyregs, datap,
sizeof(struct pt_regs)) == 0) {
copyregs.ex1 =
PL_ICS_EX1(USER_PL, EX1_ICS(copyregs.ex1));
*task_pt_regs(child) = copyregs;
ret = 0;
}
break;
......
......@@ -27,7 +27,7 @@
void machine_halt(void)
{
warn_early_printk();
raw_local_irq_disable_all();
arch_local_irq_disable_all();
smp_send_stop();
hv_halt();
}
......@@ -35,14 +35,14 @@ void machine_halt(void)
void machine_power_off(void)
{
warn_early_printk();
raw_local_irq_disable_all();
arch_local_irq_disable_all();
smp_send_stop();
hv_power_off();
}
void machine_restart(char *cmd)
{
raw_local_irq_disable_all();
arch_local_irq_disable_all();
smp_send_stop();
hv_restart((HV_VirtAddr) "vmlinux", (HV_VirtAddr) cmd);
}
......
......@@ -868,14 +868,14 @@ void __cpuinit setup_cpu(int boot)
/* Allow asynchronous TLB interrupts. */
#if CHIP_HAS_TILE_DMA()
raw_local_irq_unmask(INT_DMATLB_MISS);
raw_local_irq_unmask(INT_DMATLB_ACCESS);
arch_local_irq_unmask(INT_DMATLB_MISS);
arch_local_irq_unmask(INT_DMATLB_ACCESS);
#endif
#if CHIP_HAS_SN_PROC()
raw_local_irq_unmask(INT_SNITLB_MISS);
arch_local_irq_unmask(INT_SNITLB_MISS);
#endif
#ifdef __tilegx__
raw_local_irq_unmask(INT_SINGLE_STEP_K);
arch_local_irq_unmask(INT_SINGLE_STEP_K);
#endif
/*
......
......@@ -71,6 +71,9 @@ int restore_sigcontext(struct pt_regs *regs,
for (i = 0; i < sizeof(struct pt_regs)/sizeof(long); ++i)
err |= __get_user(regs->regs[i], &sc->gregs[i]);
/* Ensure that the PL is always set to USER_PL. */
regs->ex1 = PL_ICS_EX1(USER_PL, EX1_ICS(regs->ex1));
regs->faultnum = INT_SWINT_1_SIGRETURN;
err |= __get_user(*pr0, &sc->gregs[0]);
......@@ -330,7 +333,7 @@ void do_signal(struct pt_regs *regs)
current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
}
return;
goto done;
}
/* Did we come from a system call? */
......@@ -358,4 +361,8 @@ void do_signal(struct pt_regs *regs)
current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
}
done:
/* Avoid double syscall restart if there are nested signals. */
regs->faultnum = INT_SWINT_1_SIGRETURN;
}
......@@ -115,7 +115,7 @@ static void smp_start_cpu_interrupt(void)
static void smp_stop_cpu_interrupt(void)
{
set_cpu_online(smp_processor_id(), 0);
raw_local_irq_disable_all();
arch_local_irq_disable_all();
for (;;)
asm("nap");
}
......
......@@ -132,7 +132,7 @@ static int tile_timer_set_next_event(unsigned long ticks,
{
BUG_ON(ticks > MAX_TICK);
__insn_mtspr(SPR_TILE_TIMER_CONTROL, ticks);
raw_local_irq_unmask_now(INT_TILE_TIMER);
arch_local_irq_unmask_now(INT_TILE_TIMER);
return 0;
}
......@@ -143,7 +143,7 @@ static int tile_timer_set_next_event(unsigned long ticks,
static void tile_timer_set_mode(enum clock_event_mode mode,
struct clock_event_device *evt)
{
raw_local_irq_mask_now(INT_TILE_TIMER);
arch_local_irq_mask_now(INT_TILE_TIMER);
}
/*
......@@ -172,7 +172,7 @@ void __cpuinit setup_tile_timer(void)
evt->cpumask = cpumask_of(smp_processor_id());
/* Start out with timer not firing. */
raw_local_irq_mask_now(INT_TILE_TIMER);
arch_local_irq_mask_now(INT_TILE_TIMER);
/* Register tile timer. */
clockevents_register_device(evt);
......@@ -188,7 +188,7 @@ void do_timer_interrupt(struct pt_regs *regs, int fault_num)
* Mask the timer interrupt here, since we are a oneshot timer
* and there are now by definition no events pending.
*/
raw_local_irq_mask(INT_TILE_TIMER);
arch_local_irq_mask(INT_TILE_TIMER);
/* Track time spent here in an interrupt context */
irq_enter();
......
......@@ -54,7 +54,7 @@ typedef unsigned long (*memcpy_t)(void *, const void *, unsigned long);
* we must run with interrupts disabled to avoid the risk of some
* other code seeing the incoherent data in our cache. (Recall that
* our cache is indexed by PA, so even if the other code doesn't use
* our KM_MEMCPY virtual addresses, they'll still hit in cache using
* our kmap_atomic virtual addresses, they'll still hit in cache using
* the normal VAs that aren't supposed to hit in cache.)
*/
static void memcpy_multicache(void *dest, const void *source,
......@@ -64,6 +64,7 @@ static void memcpy_multicache(void *dest, const void *source,
unsigned long flags, newsrc, newdst;
pmd_t *pmdp;
pte_t *ptep;
int type0, type1;
int cpu = get_cpu();
/*
......@@ -77,7 +78,8 @@ static void memcpy_multicache(void *dest, const void *source,
sim_allow_multiple_caching(1);
/* Set up the new dest mapping */
idx = FIX_KMAP_BEGIN + (KM_TYPE_NR * cpu) + KM_MEMCPY0;
type0 = kmap_atomic_idx_push();
idx = FIX_KMAP_BEGIN + (KM_TYPE_NR * cpu) + type0;
newdst = __fix_to_virt(idx) + ((unsigned long)dest & (PAGE_SIZE-1));
pmdp = pmd_offset(pud_offset(pgd_offset_k(newdst), newdst), newdst);
ptep = pte_offset_kernel(pmdp, newdst);
......@@ -87,7 +89,8 @@ static void memcpy_multicache(void *dest, const void *source,
}
/* Set up the new source mapping */
idx += (KM_MEMCPY0 - KM_MEMCPY1);
type1 = kmap_atomic_idx_push();
idx += (type0 - type1);
src_pte = hv_pte_set_nc(src_pte);
src_pte = hv_pte_clear_writable(src_pte); /* be paranoid */
newsrc = __fix_to_virt(idx) + ((unsigned long)source & (PAGE_SIZE-1));
......@@ -119,6 +122,8 @@ static void memcpy_multicache(void *dest, const void *source,
* We're done: notify the simulator that all is back to normal,
* and re-enable interrupts and pre-emption.
*/
kmap_atomic_idx_pop();
kmap_atomic_idx_pop();
sim_allow_multiple_caching(0);
local_irq_restore(flags);
put_cpu();
......
......@@ -227,7 +227,7 @@ EXPORT_SYMBOL(kmap_atomic_prot);
void *__kmap_atomic(struct page *page)
{
/* PAGE_NONE is a magic value that tells us to check immutability. */
return kmap_atomic_prot(page, type, PAGE_NONE);
return kmap_atomic_prot(page, PAGE_NONE);
}
EXPORT_SYMBOL(__kmap_atomic);
......
......@@ -988,8 +988,12 @@ static long __write_once initfree = 1;
/* Select whether to free (1) or mark unusable (0) the __init pages. */
static int __init set_initfree(char *str)
{
strict_strtol(str, 0, &initfree);
pr_info("initfree: %s free init pages\n", initfree ? "will" : "won't");
long val;
if (strict_strtol(str, 0, &val)) {
initfree = val;
pr_info("initfree: %s free init pages\n",
initfree ? "will" : "won't");
}
return 1;
}
__setup("initfree=", set_initfree);
......
......@@ -134,9 +134,9 @@ void __set_fixmap(enum fixed_addresses idx, unsigned long phys, pgprot_t flags)
}
#if defined(CONFIG_HIGHPTE)
pte_t *_pte_offset_map(pmd_t *dir, unsigned long address, enum km_type type)
pte_t *_pte_offset_map(pmd_t *dir, unsigned long address)
{
pte_t *pte = kmap_atomic(pmd_page(*dir), type) +
pte_t *pte = kmap_atomic(pmd_page(*dir)) +
(pmd_ptfn(*dir) << HV_LOG2_PAGE_TABLE_ALIGN) & ~PAGE_MASK;
return &pte[pte_index(address)];
}
......
......@@ -33,18 +33,18 @@ struct stat {
int st_blksize; /* Optimal block size for I/O. */
int __pad2;
long st_blocks; /* Number 512-byte blocks allocated. */
int st_atime; /* Time of last access. */
unsigned int st_atime_nsec;
int st_mtime; /* Time of last modification. */
unsigned int st_mtime_nsec;
int st_ctime; /* Time of last status change. */
unsigned int st_ctime_nsec;
long st_atime; /* Time of last access. */
unsigned long st_atime_nsec;
long st_mtime; /* Time of last modification. */
unsigned long st_mtime_nsec;
long st_ctime; /* Time of last status change. */
unsigned long st_ctime_nsec;
unsigned int __unused4;
unsigned int __unused5;
};
#if __BITS_PER_LONG != 64
/* This matches struct stat64 in glibc2.1. Only used for 32 bit. */
#if __BITS_PER_LONG != 64 || defined(__ARCH_WANT_STAT64)
struct stat64 {
unsigned long long st_dev; /* Device. */
unsigned long long st_ino; /* File serial number. */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment