1) Update for schedule_tail and switch_to arg changes.
2) Update for PTE highmem.
3) Add random ioctls to ioctl32 translations.
4) Kill migration IPI.
5) Fixup scheduler bitmap function and move into bitops.h
CONFIG_VT=y
CONFIG_VT_CONSOLE=y
CONFIG_SMP=y
+# CONFIG_PREEMPT is not set
CONFIG_SPARC64=y
CONFIG_HOTPLUG=y
CONFIG_HAVE_DEC_LOCK=y
#
# Block devices
#
-CONFIG_BLK_DEV_FD=y
+# CONFIG_BLK_DEV_FD is not set
CONFIG_BLK_DEV_LOOP=m
CONFIG_BLK_DEV_NBD=m
CONFIG_ACENIC=m
# CONFIG_ACENIC_OMIT_TIGON_I is not set
CONFIG_DL2K=m
+CONFIG_E1000=m
CONFIG_MYRI_SBUS=m
CONFIG_NS83820=m
CONFIG_HAMACHI=m
CONFIG_YELLOWFIN=m
CONFIG_SK98LIN=m
-# CONFIG_TIGON3 is not set
CONFIG_FDDI=y
# CONFIG_DEFXX is not set
CONFIG_SKFP=m
# CONFIG_ROOT_NFS is not set
CONFIG_NFSD=m
CONFIG_NFSD_V3=y
+CONFIG_NFSD_TCP=y
CONFIG_SUNRPC=y
CONFIG_LOCKD=y
CONFIG_LOCKD_V4=y
# Sound
#
CONFIG_SOUND=m
-CONFIG_SOUND_BT878=m
-# CONFIG_SOUND_CMPCI is not set
-# CONFIG_SOUND_EMU10K1 is not set
-# CONFIG_MIDI_EMU10K1 is not set
-# CONFIG_SOUND_FUSION is not set
-# CONFIG_SOUND_CS4281 is not set
-# CONFIG_SOUND_ES1370 is not set
-CONFIG_SOUND_ES1371=m
-# CONFIG_SOUND_ESSSOLO1 is not set
-# CONFIG_SOUND_MAESTRO is not set
-# CONFIG_SOUND_MAESTRO3 is not set
-# CONFIG_SOUND_ICH is not set
-# CONFIG_SOUND_RME96XX is not set
-# CONFIG_SOUND_SONICVIBES is not set
-CONFIG_SOUND_TRIDENT=m
-# CONFIG_SOUND_MSNDCLAS is not set
-# CONFIG_SOUND_MSNDPIN is not set
-# CONFIG_SOUND_VIA82CXXX is not set
-# CONFIG_MIDI_VIA82CXXX is not set
-# CONFIG_SOUND_OSS is not set
-# CONFIG_SOUND_TVMIXER is not set
+
+#
+# Open Sound System
+#
+# CONFIG_SOUND_PRIME is not set
+
+#
+# Advanced Linux Sound Architecture
+#
+# CONFIG_SND is not set
#
# USB support
CONFIG_USB_VICAM=m
CONFIG_USB_DSBR=m
CONFIG_USB_DABUSB=m
+CONFIG_USB_KONICAWC=m
#
# USB Network adaptors
* %o7 for us. Check performance counter stuff too.
*/
andn %o7, _TIF_NEWCHILD, %l0
- mov %g5, %o0 /* 'prev' */
call schedule_tail
stx %l0, [%g6 + TI_FLAGS]
andcc %l0, _TIF_PERFCTR, %g0
#include <linux/usb.h>
#include <linux/usbdevice_fs.h>
#include <linux/nbd.h>
+#include <linux/random.h>
/* Use this to get at 32-bit user passed pointers.
See sys_sparc32.c for description about these. */
COMPATIBLE_IOCTL(WIOCSTART)
COMPATIBLE_IOCTL(WIOCSTOP)
COMPATIBLE_IOCTL(WIOCGSTAT)
+/* Big R */
+COMPATIBLE_IOCTL(RNDGETENTCNT)
+COMPATIBLE_IOCTL(RNDADDTOENTCNT)
+COMPATIBLE_IOCTL(RNDGETPOOL)
+COMPATIBLE_IOCTL(RNDADDENTROPY)
+COMPATIBLE_IOCTL(RNDZAPENTCNT)
+COMPATIBLE_IOCTL(RNDCLEARPOOL)
/* Bluetooth ioctls */
COMPATIBLE_IOCTL(HCIDEVUP)
COMPATIBLE_IOCTL(HCIDEVDOWN)
int cpu = smp_processor_id();
if (local_irq_count(cpu) == 0 &&
- local_bh_count(cpu) == 0)
- preempt_schedule();
- current_thread_info()->preempt_count--;
+ local_bh_count(cpu) == 0 &&
+ test_thread_flag(TIF_NEED_RESCHED)) {
+ current->state = TASK_RUNNING;
+ schedule();
+ }
}
#endif
if (!(current->ptrace & PT_PTRACED))
return;
current->exit_code = SIGTRAP;
+ preempt_disable();
current->state = TASK_STOPPED;
notify_parent(current, SIGCHLD);
schedule();
+ preempt_enable();
/*
* this isn't the same as continuing with a signal, but it will do
* for normal use. strace only continues with a signal if the
add %l5, 1, %l6
stw %l6, [%g6 + TI_PRE_COUNT]
call kpreempt_maybe
- wrpr %g0, RTRAP_PSTATE, %pstate
- wrpr %g0, RTRAP_PSTATE_IRQOFF, %pstate
- stw %l5, [%g6 + TI_PRE_COUNT]
+ nop
+ ba,pt %xcc, rtrap
+ stw %l5, [%g6 + TI_PRE_COUNT]
#endif
kern_fpucheck: ldub [%g6 + TI_FPDEPTH], %l5
brz,pt %l5, rt_continue
pmdp = pmd_offset(pgdp, va);
if (pmd_none(*pmdp))
goto done;
- ptep = pte_offset(pmdp, va);
- if (!pte_present(*ptep))
- goto done;
- tte = pte_val(*ptep);
- res = PROM_TRUE;
+
+ /* Preemption implicitly disabled by virtue of
+ * being called from inside OBP.
+ */
+ ptep = pte_offset_map(pmdp, va);
+ if (pte_present(*ptep)) {
+ tte = pte_val(*ptep);
+ res = PROM_TRUE;
+ }
+ pte_unmap(ptep);
goto done;
}
pmdp = pmd_offset(pgdp, va);
if (pmd_none(*pmdp))
goto done;
- ptep = pte_offset(pmdp, va);
- if (!pte_present(*ptep))
- goto done;
- tte = pte_val(*ptep);
- res = PROM_TRUE;
+
+ /* Preemption implicitly disabled by virtue of
+ * being called from inside OBP.
+ */
+ ptep = pte_offset_kernel(pmdp, va);
+ if (pte_present(*ptep)) {
+ tte = pte_val(*ptep);
+ res = PROM_TRUE;
+ }
goto done;
}
if (!root_flags)
root_mountflags &= ~MS_RDONLY;
ROOT_DEV = to_kdev_t(root_dev);
-#ifdef CONFIG_BLK_DEV_RAM
+#ifdef CONFIG_BLK_DEV_INITRD
rd_image_start = ram_flags & RAMDISK_IMAGE_START_MASK;
rd_prompt = ((ram_flags & RAMDISK_PROMPT_FLAG) != 0);
rd_doload = ((ram_flags & RAMDISK_LOAD_FLAG) != 0);
if ((current->ptrace & PT_PTRACED) && signr != SIGKILL) {
current->exit_code = signr;
+ preempt_disable();
current->state = TASK_STOPPED;
notify_parent(current, SIGCHLD);
schedule();
+ preempt_enable();
if (!(signr = current->exit_code))
continue;
current->exit_code = 0;
if (is_orphaned_pgrp(current->pgrp))
continue;
- case SIGSTOP:
- if (current->ptrace & PT_PTRACED)
- continue;
- current->state = TASK_STOPPED;
+ case SIGSTOP: {
+ struct signal_struct *sig;
+
current->exit_code = signr;
- if (!(current->p_pptr->sig->action[SIGCHLD-1].sa.sa_flags &
+ sig = current->p_pptr->sig;
+ preempt_disable();
+ current->state = TASK_STOPPED;
+ if (sig && !(sig->action[SIGCHLD-1].sa.sa_flags &
SA_NOCLDSTOP))
notify_parent(current, SIGCHLD);
schedule();
+ preempt_enable();
continue;
+ }
case SIGQUIT: case SIGILL: case SIGTRAP:
case SIGABRT: case SIGFPE: case SIGSEGV:
unsigned long address = ((unsigned long)&(sf->insns[0]));
pgd_t *pgdp = pgd_offset(current->mm, address);
pmd_t *pmdp = pmd_offset(pgdp, address);
- pte_t *ptep = pte_offset(pmdp, address);
+ pte_t *ptep;
regs->u_regs[UREG_I7] = (unsigned long) (&(sf->insns[0]) - 2);
if (err)
goto sigsegv;
+ preempt_disable();
+ ptep = pte_offset_map(pmdp, address);
if (pte_present(*ptep)) {
unsigned long page = (unsigned long) page_address(pte_page(*ptep));
: : "r" (page), "r" (address & (PAGE_SIZE - 1))
: "memory");
}
+ pte_unmap(ptep);
+ preempt_enable();
}
return;
unsigned long address = ((unsigned long)&(sf->insns[0]));
pgd_t *pgdp = pgd_offset(current->mm, address);
pmd_t *pmdp = pmd_offset(pgdp, address);
- pte_t *ptep = pte_offset(pmdp, address);
+ pte_t *ptep;
regs->u_regs[UREG_I7] = (unsigned long) (&(sf->insns[0]) - 2);
if (err)
goto sigsegv;
+ preempt_disable();
+ ptep = pte_offset_map(pmdp, address);
if (pte_present(*ptep)) {
unsigned long page = (unsigned long) page_address(pte_page(*ptep));
: : "r" (page), "r" (address & (PAGE_SIZE - 1))
: "memory");
}
+ pte_unmap(ptep);
+ preempt_enable();
}
return;
if ((current->ptrace & PT_PTRACED) && signr != SIGKILL) {
current->exit_code = signr;
+ preempt_disable();
current->state = TASK_STOPPED;
notify_parent(current, SIGCHLD);
schedule();
+ preempt_enable();
if (!(signr = current->exit_code))
continue;
current->exit_code = 0;
if (is_orphaned_pgrp(current->pgrp))
continue;
- case SIGSTOP:
- if (current->ptrace & PT_PTRACED)
- continue;
- current->state = TASK_STOPPED;
+ case SIGSTOP: {
+ struct signal_struct *sig;
+
current->exit_code = signr;
- if (!(current->p_pptr->sig->action[SIGCHLD-1].sa.sa_flags &
+ sig = current->p_pptr->sig;
+ preempt_disable();
+ current->state = TASK_STOPPED;
+ if (sig && !(sig->action[SIGCHLD-1].sa.sa_flags &
SA_NOCLDSTOP))
notify_parent(current, SIGCHLD);
schedule();
+ preempt_enable();
continue;
-
+ }
case SIGQUIT: case SIGILL: case SIGTRAP:
case SIGABRT: case SIGFPE: case SIGSEGV:
case SIGBUS: case SIGSYS: case SIGXCPU: case SIGXFSZ:
}
}
-/* Process migration IPIs. */
-
-extern unsigned long xcall_migrate_task;
-
-static spinlock_t migration_lock = SPIN_LOCK_UNLOCKED;
-static task_t *new_task;
-
-void smp_migrate_task(int cpu, task_t *p)
-{
- unsigned long mask = 1UL << cpu;
-
- if (cpu == smp_processor_id())
- return;
-
- if (smp_processors_ready && (cpu_present_map & mask) != 0) {
- u64 data0 = (((u64)&xcall_migrate_task) & 0xffffffff);
-
- _raw_spin_lock(&migration_lock);
- new_task = p;
-
- if (tlb_type == spitfire)
- spitfire_xcall_deliver(data0, 0, 0, mask);
- else
- cheetah_xcall_deliver(data0, 0, 0, mask);
- }
-}
-
-/* Called at PIL level 1. */
-asmlinkage void smp_task_migration_interrupt(int irq, struct pt_regs *regs)
-{
- task_t *p;
-
- if (irq != PIL_MIGRATE)
- BUG();
-
- clear_softint(1 << irq);
-
- p = new_task;
- _raw_spin_unlock(&migration_lock);
- sched_task_migrated(p);
-}
-
/* CPU capture. */
/* #define CAPTURE_DEBUG */
extern unsigned long xcall_capture;
/* Should really be in linux/kernel/ksyms.c */
EXPORT_SYMBOL(dump_thread);
EXPORT_SYMBOL(dump_fpu);
-EXPORT_SYMBOL(pte_alloc_one);
+EXPORT_SYMBOL(pte_alloc_one_kernel);
#ifndef CONFIG_SMP
EXPORT_SYMBOL(pgt_quicklists);
#endif
#include <linux/icmpv6.h>
#include <linux/sysctl.h>
#include <linux/binfmts.h>
+#include <linux/dnotify.h>
#include <asm/types.h>
#include <asm/ipc.h>
/* First get the "struct iovec" from user memory and
* verify all the pointers
*/
+ retval = 0;
if (!count)
- return 0;
+ goto out_nofree;
+ retval = -EFAULT;
if (verify_area(VERIFY_READ, vector, sizeof(struct iovec32)*count))
- return -EFAULT;
+ goto out_nofree;
+ retval = -EINVAL;
if (count > UIO_MAXIOV)
- return -EINVAL;
+ goto out_nofree;
if (count > UIO_FASTIOV) {
+ retval = -ENOMEM;
iov = kmalloc(count*sizeof(struct iovec), GFP_KERNEL);
if (!iov)
- return -ENOMEM;
+ goto out_nofree;
}
tot_len = 0;
out:
if (iov != iovstack)
kfree(iov);
+out_nofree:
+ /* VERIFY_WRITE actually means a read, as we write to user space */
+ if ((retval + (type == VERIFY_WRITE)) > 0)
+ dnotify_parent(file->f_dentry,
+ (type == VERIFY_WRITE) ? DN_MODIFY : DN_ACCESS);
return retval;
}
tl0_privact: TRAP_NOSAVE(__do_privact)
tl0_resv038: BTRAP(0x38) BTRAP(0x39) BTRAP(0x3a) BTRAP(0x3b) BTRAP(0x3c) BTRAP(0x3d)
tl0_resv03e: BTRAP(0x3e) BTRAP(0x3f) BTRAP(0x40)
-#ifdef CONFIG_SMP
-tl0_irq1: TRAP_IRQ(smp_task_migration_interrupt, 1)
-#else
tl0_irq1: BTRAP(0x41)
-#endif
tl0_irq2: TRAP_IRQ(handler_irq, 2)
tl0_irq3: TRAP_IRQ(handler_irq, 3) TRAP_IRQ(handler_irq, 4)
tl0_irq5: TRAP_IRQ(handler_irq, 5) TRAP_IRQ(handler_irq, 6)
pmdp = pmd_offset(pgdp, tpc);
if (pmd_none(*pmdp))
goto outret;
- ptep = pte_offset(pmdp, tpc);
+
+ /* This disables preemption for us as well. */
__asm__ __volatile__("rdpr %%pstate, %0" : "=r" (pstate));
__asm__ __volatile__("wrpr %0, %1, %%pstate"
: : "r" (pstate), "i" (PSTATE_IE));
+ ptep = pte_offset_map(pmdp, tpc);
pte = *ptep;
if (!pte_present(pte))
goto out;
: "r" (pa), "i" (ASI_PHYS_USE_EC));
out:
+ pte_unmap(ptep);
__asm__ __volatile__("wrpr %0, 0x0, %%pstate" : : "r" (pstate));
outret:
return insn;
end = PGDIR_SIZE;
offset -= address;
do {
- pte_t * pte = pte_alloc(current->mm, pmd, address);
+ pte_t * pte = pte_alloc_map(current->mm, pmd, address);
if (!pte)
return -ENOMEM;
io_remap_pte_range(pte, address, end - address, address + offset, prot, space);
+ pte_unmap(pte);
address = (address + PMD_SIZE) & PMD_MASK;
pmd++;
} while (address < end);
int bigkernel = 0;
-int do_check_pgt_cache(int low, int high)
-{
- int freed = 0;
+/* XXX Tune this... */
+#define PGT_CACHE_LOW 25
+#define PGT_CACHE_HIGH 50
- if (pgtable_cache_size > high) {
+void check_pgt_cache(void)
+{
+ preempt_disable();
+ if (pgtable_cache_size > PGT_CACHE_HIGH) {
do {
#ifdef CONFIG_SMP
if (pgd_quicklist)
- free_pgd_slow(get_pgd_fast()), freed++;
+ free_pgd_slow(get_pgd_fast());
#endif
if (pte_quicklist[0])
- free_pte_slow(pte_alloc_one_fast(NULL, 0)), freed++;
+ free_pte_slow(pte_alloc_one_fast(NULL, 0));
if (pte_quicklist[1])
- free_pte_slow(pte_alloc_one_fast(NULL, 1 << (PAGE_SHIFT + 10))), freed++;
- } while (pgtable_cache_size > low);
+ free_pte_slow(pte_alloc_one_fast(NULL, 1 << (PAGE_SHIFT + 10)));
+ } while (pgtable_cache_size > PGT_CACHE_LOW);
}
-#ifndef CONFIG_SMP
- if (pgd_cache_size > high / 4) {
+#ifndef CONFIG_SMP
+ if (pgd_cache_size > PGT_CACHE_HIGH / 4) {
struct page *page, *page2;
for (page2 = NULL, page = (struct page *)pgd_quicklist; page;) {
if ((unsigned long)page->pprev_hash == 3) {
page->pprev_hash = NULL;
pgd_cache_size -= 2;
__free_page(page);
- freed++;
if (page2)
page = page2->next_hash;
else
page = (struct page *)pgd_quicklist;
- if (pgd_cache_size <= low / 4)
+ if (pgd_cache_size <= PGT_CACHE_LOW / 4)
break;
continue;
}
}
}
#endif
- return freed;
+ preempt_enable();
}
#ifdef CONFIG_DEBUG_DCFLUSH
static __inline__ void set_dcache_dirty(struct page *page)
{
unsigned long mask = smp_processor_id();
- unsigned long non_cpu_bits = (1UL << 24UL) - 1UL;
+ unsigned long non_cpu_bits = ~((NR_CPUS - 1UL) << 24UL);
mask = (mask << 24) | (1UL << PG_dcache_dirty);
__asm__ __volatile__("1:\n\t"
"ldx [%2], %%g7\n\t"
"1:\n\t"
"ldx [%2], %%g7\n\t"
"srlx %%g7, 24, %%g5\n\t"
+ "and %%g5, %3, %%g5\n\t"
"cmp %%g5, %0\n\t"
"bne,pn %%icc, 2f\n\t"
" andn %%g7, %1, %%g5\n\t"
" membar #StoreLoad | #StoreStore\n"
"2:"
: /* no outputs */
- : "r" (cpu), "r" (mask), "r" (&page->flags)
+ : "r" (cpu), "r" (mask), "r" (&page->flags),
+ "i" (NR_CPUS - 1UL)
: "g5", "g7");
}
if (VALID_PAGE(page) &&
page->mapping &&
((pg_flags = page->flags) & (1UL << PG_dcache_dirty))) {
- int cpu = (pg_flags >> 24);
+ int cpu = ((pg_flags >> 24) & (NR_CPUS - 1UL));
/* This is just to optimize away some function calls
* in the SMP case.
int dirty_cpu = dcache_dirty_cpu(page);
if (page->mapping &&
- page->mapping->i_mmap == NULL &&
- page->mapping->i_mmap_shared == NULL) {
+ list_empty(&page->mapping->i_mmap) &&
+ list_empty(&page->mapping->i_mmap_shared)) {
if (dirty) {
if (dirty_cpu == smp_processor_id())
return;
if (pmd_none(*pmd))
return;
- ptep = pte_offset(pmd, address);
+ ptep = pte_offset_map(pmd, address);
offset = address & ~PMD_MASK;
if (offset + size > PMD_SIZE)
size = PMD_SIZE - offset;
flush_dcache_page_all(mm, page);
}
}
+ pte_unmap(ptep - 1);
}
static inline void flush_cache_pmd_range(struct mm_struct *mm, pgd_t *dir, unsigned long address, unsigned long size)
*error = 1;
return(0);
}
- ptep = (pte_t *)pmd_page(*pmdp) + ((promva >> 13) & 0x3ff);
+ ptep = (pte_t *)__pmd_page(*pmdp) + ((promva >> 13) & 0x3ff);
if (!pte_present(*ptep)) {
if (error)
*error = 1;
memset(ptep, 0, BASE_PAGE_SIZE);
pmd_set(pmdp, ptep);
}
- ptep = (pte_t *)pmd_page(*pmdp) +
+ ptep = (pte_t *)__pmd_page(*pmdp) +
((vaddr >> 13) & 0x3ff);
val = trans[i].data;
#else
#define DC_ALIAS_SHIFT 0
#endif
-pte_t *pte_alloc_one(struct mm_struct *mm, unsigned long address)
+pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
{
- struct page *page = alloc_pages(GFP_KERNEL, DC_ALIAS_SHIFT);
- unsigned long color = VPTE_COLOR(address);
+ struct page *page;
+ unsigned long color;
+
+ {
+ pte_t *ptep = pte_alloc_one_fast(mm, address);
+
+ if (ptep)
+ return ptep;
+ }
+ color = VPTE_COLOR(address);
+ page = alloc_pages(GFP_KERNEL, DC_ALIAS_SHIFT);
if (page) {
unsigned long *to_free;
unsigned long paddr;
#if (L1DCACHE_SIZE > PAGE_SIZE) /* is there D$ aliasing problem */
/* Now free the other one up, adjust cache size. */
+ preempt_disable();
*to_free = (unsigned long) pte_quicklist[color ^ 0x1];
pte_quicklist[color ^ 0x1] = to_free;
pgtable_cache_size++;
+ preempt_enable();
#endif
return pte;
b,pt %xcc, rtrap_irq
nop
- .globl xcall_migrate_task
-xcall_migrate_task:
- mov 1, %g2
- sllx %g2, (PIL_MIGRATE), %g2
- wr %g2, 0x0, %set_softint
- retry
-
#endif /* CONFIG_SMP */
#ifndef _SPARC64_BITOPS_H
#define _SPARC64_BITOPS_H
+#include <linux/compiler.h>
#include <asm/byteorder.h>
extern long ___test_and_set_bit(unsigned long nr, volatile void *addr);
#ifdef __KERNEL__
+/*
+ * Every architecture must define this function. It's the fastest
+ * way of searching a 140-bit bitmap where the first 100 bits are
+ * unlikely to be set. It's guaranteed that at least one of the 140
+ * bits is cleared.
+ */
+static inline int sched_find_first_bit(unsigned long *b)
+{
+ if (unlikely(b[0]))
+ return __ffs(b[0]);
+ if (unlikely(((unsigned int)b[1])))
+ return __ffs(b[1]) + 64;
+ if (b[1] >> 32)
+ return __ffs(b[1] >> 32) + 96;
+ return __ffs(b[2]) + 128;
+}
+
/*
* ffs: find first bit set. This is defined the same way as
* the libc and compiler builtin ffs routines, therefore
#include <asm/system.h>
#include <asm/spitfire.h>
-/*
- * Every architecture must define this function. It's the fastest
- * way of searching a 168-bit bitmap where the first 128 bits are
- * unlikely to be set. It's guaranteed that at least one of the 168
- * bits is cleared.
- */
-#if MAX_RT_PRIO != 128 || MAX_PRIO != 168
-# error update this function.
-#endif
-
-static inline int sched_find_first_bit(unsigned long *b)
-{
- if (unlikely(b[0]))
- return __ffs(b[0]);
- if (unlikely(b[1]))
- return __ffs(b[1]) + 64;
- return __ffs(b[2]) + 128;
-}
-
static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk, unsigned cpu)
{
}
#include <asm/spitfire.h>
#include <asm/pgtable.h>
-/* Cache and TLB flush operations. */
-
-/* These are the same regardless of whether this is an SMP kernel or not. */
-#define flush_cache_mm(__mm) \
- do { if ((__mm) == current->mm) flushw_user(); } while(0)
-extern void flush_cache_range(struct vm_area_struct *, unsigned long, unsigned long);
-#define flush_cache_page(vma, page) \
- flush_cache_mm((vma)->vm_mm)
-
-/* This is unnecessary on the SpitFire since D-CACHE is write-through. */
-#define flush_page_to_ram(page) do { } while (0)
-
-/*
- * On spitfire, the icache doesn't snoop local stores and we don't
- * use block commit stores (which invalidate icache lines) during
- * module load, so we need this.
- */
-extern void flush_icache_range(unsigned long start, unsigned long end);
-
-extern void __flush_dcache_page(void *addr, int flush_icache);
-extern void __flush_icache_page(unsigned long);
-extern void flush_dcache_page_impl(struct page *page);
-#ifdef CONFIG_SMP
-extern void smp_flush_dcache_page_impl(struct page *page, int cpu);
-extern void flush_dcache_page_all(struct mm_struct *mm, struct page *page);
-#else
-#define smp_flush_dcache_page_impl(page,cpu) flush_dcache_page_impl(page)
-#define flush_dcache_page_all(mm,page) flush_dcache_page_impl(page)
-#endif
-
-extern void flush_dcache_page(struct page *page);
-
-extern void __flush_dcache_range(unsigned long start, unsigned long end);
-
-extern void __flush_cache_all(void);
-
-extern void __flush_tlb_all(void);
-extern void __flush_tlb_mm(unsigned long context, unsigned long r);
-extern void __flush_tlb_range(unsigned long context, unsigned long start,
- unsigned long r, unsigned long end,
- unsigned long pgsz, unsigned long size);
-extern void __flush_tlb_page(unsigned long context, unsigned long page, unsigned long r);
-
-#ifndef CONFIG_SMP
-
-#define flush_cache_all() __flush_cache_all()
-#define flush_tlb_all() __flush_tlb_all()
-
-#define flush_tlb_mm(__mm) \
-do { if(CTX_VALID((__mm)->context)) \
- __flush_tlb_mm(CTX_HWBITS((__mm)->context), SECONDARY_CONTEXT); \
-} while(0)
-
-#define flush_tlb_range(__vma, start, end) \
-do { if(CTX_VALID((__vma)->vm_mm->context)) { \
- unsigned long __start = (start)&PAGE_MASK; \
- unsigned long __end = PAGE_ALIGN(end); \
- __flush_tlb_range(CTX_HWBITS((__vma)->vm_mm->context), __start, \
- SECONDARY_CONTEXT, __end, PAGE_SIZE, \
- (__end - __start)); \
- } \
-} while(0)
-
-#define flush_tlb_page(vma, page) \
-do { struct mm_struct *__mm = (vma)->vm_mm; \
- if(CTX_VALID(__mm->context)) \
- __flush_tlb_page(CTX_HWBITS(__mm->context), (page)&PAGE_MASK, \
- SECONDARY_CONTEXT); \
-} while(0)
-
-#else /* CONFIG_SMP */
-
-extern void smp_flush_cache_all(void);
-extern void smp_flush_tlb_all(void);
-extern void smp_flush_tlb_mm(struct mm_struct *mm);
-extern void smp_flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
- unsigned long end);
-extern void smp_flush_tlb_page(struct mm_struct *mm, unsigned long page);
-
-#define flush_cache_all() smp_flush_cache_all()
-#define flush_tlb_all() smp_flush_tlb_all()
-#define flush_tlb_mm(mm) smp_flush_tlb_mm(mm)
-#define flush_tlb_range(vma, start, end) \
- smp_flush_tlb_range(vma, start, end)
-#define flush_tlb_page(vma, page) \
- smp_flush_tlb_page((vma)->vm_mm, page)
-
-#endif /* ! CONFIG_SMP */
-
#define VPTE_BASE_SPITFIRE 0xfffffffe00000000
#if 1
#define VPTE_BASE_CHEETAH VPTE_BASE_SPITFIRE
#define VPTE_BASE_CHEETAH 0xffe0000000000000
#endif
-extern __inline__ void flush_tlb_pgtables(struct mm_struct *mm, unsigned long start,
+static __inline__ void flush_tlb_pgtables(struct mm_struct *mm, unsigned long start,
unsigned long end)
{
/* Note the signed type. */
#ifndef CONFIG_SMP
-extern __inline__ void free_pgd_fast(pgd_t *pgd)
+static __inline__ void free_pgd_fast(pgd_t *pgd)
{
struct page *page = virt_to_page(pgd);
preempt_enable();
}
-extern __inline__ pgd_t *get_pgd_fast(void)
+static __inline__ pgd_t *get_pgd_fast(void)
{
struct page *ret;
#else /* CONFIG_SMP */
-extern __inline__ void free_pgd_fast(pgd_t *pgd)
+static __inline__ void free_pgd_fast(pgd_t *pgd)
{
preempt_disable();
*(unsigned long *)pgd = (unsigned long) pgd_quicklist;
preempt_enable();
}
-extern __inline__ pgd_t *get_pgd_fast(void)
+static __inline__ pgd_t *get_pgd_fast(void)
{
unsigned long *ret;
return (pgd_t *)ret;
}
-extern __inline__ void free_pgd_slow(pgd_t *pgd)
+static __inline__ void free_pgd_slow(pgd_t *pgd)
{
free_page((unsigned long)pgd);
}
#define pgd_populate(MM, PGD, PMD) pgd_set(PGD, PMD)
-extern __inline__ pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long address)
-{
- pmd_t *pmd = (pmd_t *)__get_free_page(GFP_KERNEL);
- if (pmd)
- memset(pmd, 0, PAGE_SIZE);
- return pmd;
-}
-
-extern __inline__ pmd_t *pmd_alloc_one_fast(struct mm_struct *mm, unsigned long address)
+static __inline__ pmd_t *pmd_alloc_one_fast(struct mm_struct *mm, unsigned long address)
{
unsigned long *ret;
int color = 0;
+ preempt_disable();
if (pte_quicklist[color] == NULL)
color = 1;
- preempt_disable();
if((ret = (unsigned long *)pte_quicklist[color]) != NULL) {
pte_quicklist[color] = (unsigned long *)(*ret);
ret[0] = 0;
return (pmd_t *)ret;
}
-extern __inline__ void free_pmd_fast(pmd_t *pmd)
+static __inline__ pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long address)
+{
+ pmd_t *pmd;
+
+ pmd = pmd_alloc_one_fast(mm, address);
+ if (!pmd) {
+ pmd = (pmd_t *)__get_free_page(GFP_KERNEL);
+ if (pmd)
+ memset(pmd, 0, PAGE_SIZE);
+ }
+ return pmd;
+}
+
+static __inline__ void free_pmd_fast(pmd_t *pmd)
{
unsigned long color = DCACHE_COLOR((unsigned long)pmd);
preempt_enable();
}
-extern __inline__ void free_pmd_slow(pmd_t *pmd)
+static __inline__ void free_pmd_slow(pmd_t *pmd)
{
free_page((unsigned long)pmd);
}
-#define pmd_populate(MM, PMD, PTE) pmd_set(PMD, PTE)
+#define pmd_populate_kernel(MM, PMD, PTE) pmd_set(PMD, PTE)
+#define pmd_populate(MM,PMD,PTE_PAGE) \
+ pmd_populate_kernel(MM,PMD,page_address(PTE_PAGE))
-extern pte_t *pte_alloc_one(struct mm_struct *mm, unsigned long address);
+extern pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address);
+#define pte_alloc_one(MM,ADDR) virt_to_page(pte_alloc_one_kernel(MM,ADDR))
-extern __inline__ pte_t *pte_alloc_one_fast(struct mm_struct *mm, unsigned long address)
+static __inline__ pte_t *pte_alloc_one_fast(struct mm_struct *mm, unsigned long address)
{
unsigned long color = VPTE_COLOR(address);
unsigned long *ret;
return (pte_t *)ret;
}
-extern __inline__ void free_pte_fast(pte_t *pte)
+static __inline__ void free_pte_fast(pte_t *pte)
{
unsigned long color = DCACHE_COLOR((unsigned long)pte);
preempt_enable();
}
-extern __inline__ void free_pte_slow(pte_t *pte)
+static __inline__ void free_pte_slow(pte_t *pte)
{
free_page((unsigned long)pte);
}
-#define pte_free(pte) free_pte_fast(pte)
+#define pte_free_kernel(pte) free_pte_fast(pte)
+#define pte_free(pte) free_pte_fast(page_address(pte))
#define pmd_free(pmd) free_pmd_fast(pmd)
#define pgd_free(pgd) free_pgd_fast(pgd)
#define pgd_alloc(mm) get_pgd_fast()
-extern int do_check_pgt_cache(int, int);
-
#endif /* _SPARC64_PGALLOC_H */
#define LOW_OBP_ADDRESS 0x00000000f0000000
#define HI_OBP_ADDRESS 0x0000000100000000
+#ifndef __ASSEMBLY__
+
+/* Cache and TLB flush operations. */
+
+/* These are the same regardless of whether this is an SMP kernel or not. */
+#define flush_cache_mm(__mm) \
+ do { if ((__mm) == current->mm) flushw_user(); } while(0)
+extern void flush_cache_range(struct vm_area_struct *, unsigned long, unsigned long);
+#define flush_cache_page(vma, page) \
+ flush_cache_mm((vma)->vm_mm)
+
+
+/*
+ * On spitfire, the icache doesn't snoop local stores and we don't
+ * use block commit stores (which invalidate icache lines) during
+ * module load, so we need this.
+ */
+extern void flush_icache_range(unsigned long start, unsigned long end);
+
+extern void __flush_dcache_page(void *addr, int flush_icache);
+extern void __flush_icache_page(unsigned long);
+extern void flush_dcache_page_impl(struct page *page);
+#ifdef CONFIG_SMP
+extern void smp_flush_dcache_page_impl(struct page *page, int cpu);
+extern void flush_dcache_page_all(struct mm_struct *mm, struct page *page);
+#else
+#define smp_flush_dcache_page_impl(page,cpu) flush_dcache_page_impl(page)
+#define flush_dcache_page_all(mm,page) flush_dcache_page_impl(page)
+#endif
+
+extern void __flush_dcache_range(unsigned long start, unsigned long end);
+
+extern void __flush_cache_all(void);
+
+extern void __flush_tlb_all(void);
+extern void __flush_tlb_mm(unsigned long context, unsigned long r);
+extern void __flush_tlb_range(unsigned long context, unsigned long start,
+ unsigned long r, unsigned long end,
+ unsigned long pgsz, unsigned long size);
+extern void __flush_tlb_page(unsigned long context, unsigned long page, unsigned long r);
+
+#ifndef CONFIG_SMP
+
+#define flush_cache_all() __flush_cache_all()
+#define flush_tlb_all() __flush_tlb_all()
+
+#define flush_tlb_mm(__mm) \
+do { if(CTX_VALID((__mm)->context)) \
+ __flush_tlb_mm(CTX_HWBITS((__mm)->context), SECONDARY_CONTEXT); \
+} while(0)
+
+#define flush_tlb_range(__vma, start, end) \
+do { if(CTX_VALID((__vma)->vm_mm->context)) { \
+ unsigned long __start = (start)&PAGE_MASK; \
+ unsigned long __end = PAGE_ALIGN(end); \
+ __flush_tlb_range(CTX_HWBITS((__vma)->vm_mm->context), __start, \
+ SECONDARY_CONTEXT, __end, PAGE_SIZE, \
+ (__end - __start)); \
+ } \
+} while(0)
+
+#define flush_tlb_page(vma, page) \
+do { struct mm_struct *__mm = (vma)->vm_mm; \
+ if(CTX_VALID(__mm->context)) \
+ __flush_tlb_page(CTX_HWBITS(__mm->context), (page)&PAGE_MASK, \
+ SECONDARY_CONTEXT); \
+} while(0)
+
+#else /* CONFIG_SMP */
+
+extern void smp_flush_cache_all(void);
+extern void smp_flush_tlb_all(void);
+extern void smp_flush_tlb_mm(struct mm_struct *mm);
+extern void smp_flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
+ unsigned long end);
+extern void smp_flush_tlb_page(struct mm_struct *mm, unsigned long page);
+
+#define flush_cache_all() smp_flush_cache_all()
+#define flush_tlb_all() smp_flush_tlb_all()
+#define flush_tlb_mm(mm) smp_flush_tlb_mm(mm)
+#define flush_tlb_range(vma, start, end) \
+ smp_flush_tlb_range(vma, start, end)
+#define flush_tlb_page(vma, page) \
+ smp_flush_tlb_page((vma)->vm_mm, page)
+
+#endif /* ! CONFIG_SMP */
+
+#endif /* ! __ASSEMBLY__ */
+
/* XXX All of this needs to be rethought so we can take advantage
* XXX cheetah's full 64-bit virtual address space, ie. no more hole
* XXX in the middle like on spitfire. -DaveM
(pmd_val(*(pmdp)) = (__pa((unsigned long) (ptep)) >> 11UL))
#define pgd_set(pgdp, pmdp) \
(pgd_val(*(pgdp)) = (__pa((unsigned long) (pmdp)) >> 11UL))
-#define pmd_page(pmd) ((unsigned long) __va((pmd_val(pmd)<<11UL)))
+#define __pmd_page(pmd) ((unsigned long) __va((pmd_val(pmd)<<11UL)))
+#define pmd_page(pmd) virt_to_page((void *)__pmd_page(pmd))
#define pgd_page(pgd) ((unsigned long) __va((pgd_val(pgd)<<11UL)))
#define pte_none(pte) (!pte_val(pte))
#define pte_present(pte) (pte_val(pte) & _PAGE_PRESENT)
((address >> PMD_SHIFT) & (REAL_PTRS_PER_PMD-1)))
/* Find an entry in the third-level page table.. */
-#define pte_offset(dir, address) ((pte_t *) pmd_page(*(dir)) + \
+#define __pte_offset(dir, address) ((pte_t *) __pmd_page(*(dir)) + \
((address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1)))
+#define pte_offset_kernel __pte_offset
+#define pte_offset_map __pte_offset
+#define pte_offset_map_nested __pte_offset
+#define pte_unmap(pte) do { } while (0)
+#define pte_unmap_nested(pte) do { } while (0)
extern pgd_t swapper_pg_dir[1];
return addr & _PAGE_PADDR;
if ((addr >= LOW_OBP_ADDRESS) && (addr < HI_OBP_ADDRESS))
return prom_virt_to_phys(addr, 0);
- pgdp = pgd_offset_k (addr);
- pmdp = pmd_offset (pgdp, addr);
- ptep = pte_offset (pmdp, addr);
- return pte_val (*ptep) & _PAGE_PADDR;
+ pgdp = pgd_offset_k(addr);
+ pmdp = pmd_offset(pgdp, addr);
+ ptep = pte_offset_kernel(pmdp, addr);
+ return pte_val(*ptep) & _PAGE_PADDR;
}
extern __inline__ unsigned long
extern unsigned long get_fb_unmapped_area(struct file *filp, unsigned long, unsigned long, unsigned long, unsigned long);
#define HAVE_ARCH_FB_UNMAPPED_AREA
-#endif /* !(__ASSEMBLY__) */
-
/*
* No page table caches to initialise
*/
#define pgtable_cache_init() do { } while (0)
+extern void check_pgt_cache(void);
+
+extern void flush_dcache_page(struct page *page);
+
+/* This is unnecessary on the SpitFire since D-CACHE is write-through. */
+#define flush_page_to_ram(page) do { } while (0)
+
+#endif /* !(__ASSEMBLY__) */
+
#endif /* !(_SPARC64_PGTABLE_H) */
* XXX happily sit at the same PIL. We would then need only two
* XXX PILs, one for devices and one for the CPU local timer tick.
*/
-#define PIL_MIGRATE 1
+/* None currently allocated, '1' is available for use. */
+#define PIL_SMP_1 1
#ifndef __ASSEMBLY__
-#define PIL_RESERVED(PIL) ((PIL) == PIL_MIGRATE)
+#define PIL_RESERVED(PIL) ((PIL) == PIL_SMP_1)
#endif
#endif /* !(_SPARC64_PIL_H) */
* not preserve it's value. Hairy, but it lets us remove 2 loads
* and 2 stores in this critical code path. -DaveM
*/
-#define switch_to(prev, next, last) \
+#define switch_to(prev, next) \
do { CHECK_LOCKS(prev); \
if (test_thread_flag(TIF_PERFCTR)) { \
unsigned long __tmp; \
"stx %%i6, [%%sp + 2047 + 0x70]\n\t" \
"stx %%i7, [%%sp + 2047 + 0x78]\n\t" \
"rdpr %%wstate, %%o5\n\t" \
- "stx %%o6, [%%g6 + %3]\n\t" \
- "stb %%o5, [%%g6 + %2]\n\t" \
+ "stx %%o6, [%%g6 + %2]\n\t" \
+ "stb %%o5, [%%g6 + %1]\n\t" \
"rdpr %%cwp, %%o5\n\t" \
- "stb %%o5, [%%g6 + %5]\n\t" \
- "mov %1, %%g6\n\t" \
- "ldub [%1 + %5], %%g1\n\t" \
+ "stb %%o5, [%%g6 + %4]\n\t" \
+ "mov %0, %%g6\n\t" \
+ "ldub [%0 + %4], %%g1\n\t" \
"wrpr %%g1, %%cwp\n\t" \
- "ldx [%%g6 + %3], %%o6\n\t" \
- "ldub [%%g6 + %2], %%o5\n\t" \
- "ldx [%%g6 + %4], %%o7\n\t" \
+ "ldx [%%g6 + %2], %%o6\n\t" \
+ "ldub [%%g6 + %1], %%o5\n\t" \
+ "ldx [%%g6 + %3], %%o7\n\t" \
"mov %%g6, %%l2\n\t" \
"wrpr %%o5, 0x0, %%wstate\n\t" \
"ldx [%%sp + 2047 + 0x70], %%i6\n\t" \
"wrpr %%g0, 0x94, %%pstate\n\t" \
"mov %%l2, %%g6\n\t" \
"wrpr %%g0, 0x96, %%pstate\n\t" \
- "andcc %%o7, %6, %%g0\n\t" \
+ "andcc %%o7, %5, %%g0\n\t" \
"bne,pn %%icc, ret_from_syscall\n\t" \
- " ldx [%%g5 + %7], %0\n\t" \
- : "=&r" (last) \
+ " nop\n\t" \
+ : /* no outputs */ \
: "r" (next->thread_info), \
"i" (TI_WSTATE), "i" (TI_KSP), "i" (TI_FLAGS), "i" (TI_CWP), \
- "i" (_TIF_NEWCHILD), "i" (TI_TASK) \
+ "i" (_TIF_NEWCHILD) \
: "cc", "g1", "g2", "g3", "g5", "g7", \
"l2", "l3", "l4", "l5", "l6", "l7", \
"i0", "i1", "i2", "i3", "i4", "i5", \