Commit 5bc705e9 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/sparc-2.6

* 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/sparc-2.6:
  [MATH-EMU]: Fix underflow exception reporting.
  [SPARC64]: Create a HWCAP_SPARC_N2 and report it to userspace on Niagara-2.
  [SPARC64]: SMP trampoline needs to avoid %tick_cmpr on sun4v too.
  [SPARC64]: Do not touch %tick_cmpr on sun4v cpus.
  [SPARC64]: Niagara-2 optimized copies.
  [SPARC64]: Allow userspace to get at the machine description.
  [SPARC32]: Remove superfluous 'kernel_end' alignment on sun4c.
  [SPARC32]: Fix bogus ramdisk image location check.
  [SPARC32]: Remove iommu from struct sbus_bus and use archdata like sparc64.
parents 605a494e 40584961
......@@ -238,6 +238,7 @@ void __init fill_ebus_device(struct device_node *dp, struct linux_ebus_device *d
sd = &dev->ofdev.dev.archdata;
sd->prom_node = dp;
sd->op = &dev->ofdev;
sd->iommu = dev->bus->ofdev.dev.parent->archdata.iommu;
dev->ofdev.node = dp;
dev->ofdev.dev.parent = &dev->bus->ofdev.dev;
......
......@@ -206,7 +206,6 @@ unsigned long __init bootmem_init(unsigned long *pages_avail)
#ifdef CONFIG_BLK_DEV_INITRD
/* Now have to check initial ramdisk, so that bootmap does not overwrite it */
if (sparc_ramdisk_image) {
if (sparc_ramdisk_image >= (unsigned long)&_end - 2 * PAGE_SIZE)
sparc_ramdisk_image -= KERNBASE;
initrd_start = sparc_ramdisk_image + phys_base;
initrd_end = initrd_start + sparc_ramdisk_size;
......
......@@ -66,7 +66,7 @@ iounit_init(int sbi_node, int io_node, struct sbus_bus *sbus)
}
if(!xpt) panic("Cannot map External Page Table.");
sbus->iommu = (struct iommu_struct *)iounit;
sbus->ofdev.dev.archdata.iommu = iounit;
iounit->page_table = xpt;
spin_lock_init(&iounit->lock);
......@@ -127,7 +127,7 @@ nexti: scan = find_next_zero_bit(iounit->bmap, limit, scan);
static __u32 iounit_get_scsi_one(char *vaddr, unsigned long len, struct sbus_bus *sbus)
{
unsigned long ret, flags;
struct iounit_struct *iounit = (struct iounit_struct *)sbus->iommu;
struct iounit_struct *iounit = sbus->ofdev.dev.archdata.iommu;
spin_lock_irqsave(&iounit->lock, flags);
ret = iounit_get_area(iounit, (unsigned long)vaddr, len);
......@@ -138,7 +138,7 @@ static __u32 iounit_get_scsi_one(char *vaddr, unsigned long len, struct sbus_bus
static void iounit_get_scsi_sgl(struct scatterlist *sg, int sz, struct sbus_bus *sbus)
{
unsigned long flags;
struct iounit_struct *iounit = (struct iounit_struct *)sbus->iommu;
struct iounit_struct *iounit = sbus->ofdev.dev.archdata.iommu;
/* FIXME: Cache some resolved pages - often several sg entries are to the same page */
spin_lock_irqsave(&iounit->lock, flags);
......@@ -153,7 +153,7 @@ static void iounit_get_scsi_sgl(struct scatterlist *sg, int sz, struct sbus_bus
static void iounit_release_scsi_one(__u32 vaddr, unsigned long len, struct sbus_bus *sbus)
{
unsigned long flags;
struct iounit_struct *iounit = (struct iounit_struct *)sbus->iommu;
struct iounit_struct *iounit = sbus->ofdev.dev.archdata.iommu;
spin_lock_irqsave(&iounit->lock, flags);
len = ((vaddr & ~PAGE_MASK) + len + (PAGE_SIZE-1)) >> PAGE_SHIFT;
......@@ -168,7 +168,7 @@ static void iounit_release_scsi_sgl(struct scatterlist *sg, int sz, struct sbus_
{
unsigned long flags;
unsigned long vaddr, len;
struct iounit_struct *iounit = (struct iounit_struct *)sbus->iommu;
struct iounit_struct *iounit = sbus->ofdev.dev.archdata.iommu;
spin_lock_irqsave(&iounit->lock, flags);
while (sz != 0) {
......@@ -211,7 +211,7 @@ static int iounit_map_dma_area(dma_addr_t *pba, unsigned long va, __u32 addr, in
i = ((addr - IOUNIT_DMA_BASE) >> PAGE_SHIFT);
for_each_sbus(sbus) {
struct iounit_struct *iounit = (struct iounit_struct *)sbus->iommu;
struct iounit_struct *iounit = sbus->ofdev.dev.archdata.iommu;
iopte = (iopte_t *)(iounit->page_table + i);
*iopte = MKIOPTE(__pa(page));
......@@ -235,7 +235,7 @@ static void iounit_unmap_dma_area(unsigned long addr, int len)
static struct page *iounit_translate_dvma(unsigned long addr)
{
struct sbus_bus *sbus = sbus_root; /* They are all the same */
struct iounit_struct *iounit = (struct iounit_struct *)sbus->iommu;
struct iounit_struct *iounit = sbus->ofdev.dev.archdata.iommu;
int i;
iopte_t *iopte;
......@@ -279,7 +279,7 @@ __u32 iounit_map_dma_init(struct sbus_bus *sbus, int size)
unsigned long rotor, scan, limit;
unsigned long flags;
__u32 ret;
struct iounit_struct *iounit = (struct iounit_struct *)sbus->iommu;
struct iounit_struct *iounit = sbus->ofdev.dev.archdata.iommu;
npages = (size + (PAGE_SIZE-1)) >> PAGE_SHIFT;
i = 0x0213;
......@@ -315,7 +315,7 @@ nexti: scan = find_next_zero_bit(iounit->bmap, limit, scan);
__u32 iounit_map_dma_page(__u32 vaddr, void *addr, struct sbus_bus *sbus)
{
int scan = (vaddr - IOUNIT_DMA_BASE) >> PAGE_SHIFT;
struct iounit_struct *iounit = (struct iounit_struct *)sbus->iommu;
struct iounit_struct *iounit = sbus->ofdev.dev.archdata.iommu;
iounit->page_table[scan] = MKIOPTE(__pa(((unsigned long)addr) & PAGE_MASK));
return vaddr + (((unsigned long)addr) & ~PAGE_MASK);
......
......@@ -132,7 +132,7 @@ iommu_init(int iommund, struct sbus_bus *sbus)
impl, vers, iommu->page_table,
(int)(IOMMU_NPTES*sizeof(iopte_t)), (int)IOMMU_NPTES);
sbus->iommu = iommu;
sbus->ofdev.dev.archdata.iommu = iommu;
}
/* This begs to be btfixup-ed by srmmu. */
......@@ -166,7 +166,7 @@ static void iommu_flush_iotlb(iopte_t *iopte, unsigned int niopte)
static u32 iommu_get_one(struct page *page, int npages, struct sbus_bus *sbus)
{
struct iommu_struct *iommu = sbus->iommu;
struct iommu_struct *iommu = sbus->ofdev.dev.archdata.iommu;
int ioptex;
iopte_t *iopte, *iopte0;
unsigned int busa, busa0;
......@@ -291,7 +291,7 @@ static void iommu_get_scsi_sgl_pflush(struct scatterlist *sg, int sz, struct sbu
static void iommu_release_one(u32 busa, int npages, struct sbus_bus *sbus)
{
struct iommu_struct *iommu = sbus->iommu;
struct iommu_struct *iommu = sbus->ofdev.dev.archdata.iommu;
int ioptex;
int i;
......@@ -334,7 +334,7 @@ static int iommu_map_dma_area(dma_addr_t *pba, unsigned long va,
unsigned long addr, int len)
{
unsigned long page, end;
struct iommu_struct *iommu = sbus_root->iommu;
struct iommu_struct *iommu = sbus_root->ofdev.dev.archdata.iommu;
iopte_t *iopte = iommu->page_table;
iopte_t *first;
int ioptex;
......@@ -399,7 +399,7 @@ static int iommu_map_dma_area(dma_addr_t *pba, unsigned long va,
static void iommu_unmap_dma_area(unsigned long busa, int len)
{
struct iommu_struct *iommu = sbus_root->iommu;
struct iommu_struct *iommu = sbus_root->ofdev.dev.archdata.iommu;
iopte_t *iopte = iommu->page_table;
unsigned long end;
int ioptex = (busa - iommu->start) >> PAGE_SHIFT;
......@@ -420,7 +420,7 @@ static void iommu_unmap_dma_area(unsigned long busa, int len)
static struct page *iommu_translate_dvma(unsigned long busa)
{
struct iommu_struct *iommu = sbus_root->iommu;
struct iommu_struct *iommu = sbus_root->ofdev.dev.archdata.iommu;
iopte_t *iopte = iommu->page_table;
iopte += ((busa - iommu->start) >> PAGE_SHIFT);
......
......@@ -268,7 +268,6 @@ static inline void sun4c_init_clean_mmu(unsigned long kernel_end)
unsigned char savectx, ctx;
savectx = sun4c_get_context();
kernel_end = SUN4C_REAL_PGDIR_ALIGN(kernel_end);
for (ctx = 0; ctx < num_contexts; ctx++) {
sun4c_set_context(ctx);
for (vaddr = 0; vaddr < 0x20000000; vaddr += SUN4C_REAL_PGDIR_SIZE)
......@@ -2064,7 +2063,6 @@ void __init sun4c_paging_init(void)
unsigned long end_pfn, pages_avail;
kernel_end = (unsigned long) &end;
kernel_end += (SUN4C_REAL_PGDIR_SIZE * 4);
kernel_end = SUN4C_REAL_PGDIR_ALIGN(kernel_end);
pages_avail = 0;
......
......@@ -501,7 +501,7 @@ niagara_tlb_fixup:
cmp %g1, SUN4V_CHIP_NIAGARA1
be,pt %xcc, niagara_patch
cmp %g1, SUN4V_CHIP_NIAGARA2
be,pt %xcc, niagara_patch
be,pt %xcc, niagara2_patch
nop
call generic_patch_copyops
......@@ -512,6 +512,15 @@ niagara_tlb_fixup:
nop
ba,a,pt %xcc, 80f
niagara2_patch:
call niagara2_patch_copyops
nop
call niagara_patch_bzero
nop
call niagara2_patch_pageops
nop
ba,a,pt %xcc, 80f
niagara_patch:
call niagara_patch_copyops
......@@ -706,12 +715,13 @@ setup_trap_table:
membar #Sync
BRANCH_IF_SUN4V(o2, 1f)
/* Kill PROM timer */
sethi %hi(0x80000000), %o2
sllx %o2, 32, %o2
wr %o2, 0, %tick_cmpr
BRANCH_IF_SUN4V(o2, 1f)
BRANCH_IF_ANY_CHEETAH(o2, o3, 1f)
ba,pt %xcc, 2f
......
......@@ -9,6 +9,7 @@
#include <linux/list.h>
#include <linux/slab.h>
#include <linux/mm.h>
#include <linux/miscdevice.h>
#include <asm/hypervisor.h>
#include <asm/mdesc.h>
......@@ -836,6 +837,43 @@ void __devinit mdesc_fill_in_cpu_data(cpumask_t mask)
mdesc_release(hp);
}
static ssize_t mdesc_read(struct file *file, char __user *buf,
size_t len, loff_t *offp)
{
struct mdesc_handle *hp = mdesc_grab();
int err;
if (!hp)
return -ENODEV;
err = hp->handle_size;
if (len < hp->handle_size)
err = -EMSGSIZE;
else if (copy_to_user(buf, &hp->mdesc, hp->handle_size))
err = -EFAULT;
mdesc_release(hp);
return err;
}
static const struct file_operations mdesc_fops = {
.read = mdesc_read,
.owner = THIS_MODULE,
};
static struct miscdevice mdesc_misc = {
.minor = MISC_DYNAMIC_MINOR,
.name = "mdesc",
.fops = &mdesc_fops,
};
static int __init mdesc_misc_init(void)
{
return misc_register(&mdesc_misc);
}
__initcall(mdesc_misc_init);
void __init sun4v_mdesc_init(void)
{
struct mdesc_handle *hp;
......
......@@ -95,14 +95,13 @@ spitfire_startup:
membar #Sync
startup_continue:
mov %o0, %l0
BRANCH_IF_SUN4V(g1, niagara_lock_tlb)
sethi %hi(0x80000000), %g2
sllx %g2, 32, %g2
wr %g2, 0, %tick_cmpr
mov %o0, %l0
BRANCH_IF_SUN4V(g1, niagara_lock_tlb)
/* Call OBP by hand to lock KERNBASE into i/d tlbs.
* We lock 2 consequetive entries if we are 'bigkernel'.
*/
......
......@@ -13,6 +13,8 @@ lib-y := PeeCeeI.o copy_page.o clear_page.o strlen.o strncmp.o \
U3memcpy.o U3copy_from_user.o U3copy_to_user.o U3patch.o \
NGmemcpy.o NGcopy_from_user.o NGcopy_to_user.o NGpatch.o \
NGpage.o NGbzero.o \
NG2memcpy.o NG2copy_from_user.o NG2copy_to_user.o NG2patch.o \
NG2page.o \
GENmemcpy.o GENcopy_from_user.o GENcopy_to_user.o GENpatch.o \
GENpage.o GENbzero.o \
copy_in_user.o user_fixup.o memmove.o \
......
/* NG2copy_from_user.S: Niagara-2 optimized copy from userspace.
*
* Copyright (C) 2007 David S. Miller (davem@davemloft.net)
*/
#define EX_LD(x) \
98: x; \
.section .fixup; \
.align 4; \
99: wr %g0, ASI_AIUS, %asi;\
retl; \
mov 1, %o0; \
.section __ex_table,"a";\
.align 4; \
.word 98b, 99b; \
.text; \
.align 4;
#ifndef ASI_AIUS
#define ASI_AIUS 0x11
#endif
#ifndef ASI_BLK_AIUS_4V
#define ASI_BLK_AIUS_4V 0x17
#endif
#define FUNC_NAME NG2copy_from_user
#define LOAD(type,addr,dest) type##a [addr] %asi, dest
#define LOAD_BLK(addr,dest) ldda [addr] ASI_BLK_AIUS_4V, dest
#define EX_RETVAL(x) 0
#ifdef __KERNEL__
#define PREAMBLE \
rd %asi, %g1; \
cmp %g1, ASI_AIUS; \
bne,pn %icc, memcpy_user_stub; \
nop
#endif
#include "NG2memcpy.S"
/* NG2copy_to_user.S: Niagara-2 optimized copy to userspace.
*
* Copyright (C) 2007 David S. Miller (davem@davemloft.net)
*/
#define EX_ST(x) \
98: x; \
.section .fixup; \
.align 4; \
99: wr %g0, ASI_AIUS, %asi;\
retl; \
mov 1, %o0; \
.section __ex_table,"a";\
.align 4; \
.word 98b, 99b; \
.text; \
.align 4;
#ifndef ASI_AIUS
#define ASI_AIUS 0x11
#endif
#ifndef ASI_BLK_AIUS_4V
#define ASI_BLK_AIUS_4V 0x17
#endif
#ifndef ASI_BLK_INIT_QUAD_LDD_AIUS
#define ASI_BLK_INIT_QUAD_LDD_AIUS 0x23
#endif
#define FUNC_NAME NG2copy_to_user
#define STORE(type,src,addr) type##a src, [addr] ASI_AIUS
#define STORE_ASI ASI_BLK_INIT_QUAD_LDD_AIUS
#define STORE_BLK(src,addr) stda src, [addr] ASI_BLK_AIUS_4V
#define EX_RETVAL(x) 0
#ifdef __KERNEL__
/* Writing to %asi is _expensive_ so we hardcode it.
* Reading %asi to check for KERNEL_DS is comparatively
* cheap.
*/
#define PREAMBLE \
rd %asi, %g1; \
cmp %g1, ASI_AIUS; \
bne,pn %icc, memcpy_user_stub; \
nop
#endif
#include "NG2memcpy.S"
This diff is collapsed.
/* NG2page.S: Niagara-2 optimized clear and copy page.
*
* Copyright (C) 2007 (davem@davemloft.net)
*/
#include <asm/asi.h>
#include <asm/page.h>
#include <asm/visasm.h>
.text
.align 32
/* This is heavily simplified from the sun4u variants
* because Niagara-2 does not have any D-cache aliasing issues.
*/
NG2copy_user_page: /* %o0=dest, %o1=src, %o2=vaddr */
prefetch [%o1 + 0x00], #one_read
prefetch [%o1 + 0x40], #one_read
VISEntryHalf
set PAGE_SIZE, %g7
sub %o0, %o1, %g3
1: stxa %g0, [%o1 + %g3] ASI_BLK_INIT_QUAD_LDD_P
subcc %g7, 64, %g7
ldda [%o1] ASI_BLK_P, %f0
stda %f0, [%o1 + %g3] ASI_BLK_P
add %o1, 64, %o1
bne,pt %xcc, 1b
prefetch [%o1 + 0x40], #one_read
membar #Sync
VISExitHalf
retl
nop
#define BRANCH_ALWAYS 0x10680000
#define NOP 0x01000000
#define NG_DO_PATCH(OLD, NEW) \
sethi %hi(NEW), %g1; \
or %g1, %lo(NEW), %g1; \
sethi %hi(OLD), %g2; \
or %g2, %lo(OLD), %g2; \
sub %g1, %g2, %g1; \
sethi %hi(BRANCH_ALWAYS), %g3; \
sll %g1, 11, %g1; \
srl %g1, 11 + 2, %g1; \
or %g3, %lo(BRANCH_ALWAYS), %g3; \
or %g3, %g1, %g3; \
stw %g3, [%g2]; \
sethi %hi(NOP), %g3; \
or %g3, %lo(NOP), %g3; \
stw %g3, [%g2 + 0x4]; \
flush %g2;
.globl niagara2_patch_pageops
.type niagara2_patch_pageops,#function
niagara2_patch_pageops:
NG_DO_PATCH(copy_user_page, NG2copy_user_page)
NG_DO_PATCH(_clear_page, NGclear_page)
NG_DO_PATCH(clear_user_page, NGclear_user_page)
retl
nop
.size niagara2_patch_pageops,.-niagara2_patch_pageops
/* NG2patch.S: Patch Ultra-I routines with Niagara-2 variant.
*
* Copyright (C) 2007 David S. Miller <davem@davemloft.net>
*/
#define BRANCH_ALWAYS 0x10680000
#define NOP 0x01000000
#define NG_DO_PATCH(OLD, NEW) \
sethi %hi(NEW), %g1; \
or %g1, %lo(NEW), %g1; \
sethi %hi(OLD), %g2; \
or %g2, %lo(OLD), %g2; \
sub %g1, %g2, %g1; \
sethi %hi(BRANCH_ALWAYS), %g3; \
sll %g1, 11, %g1; \
srl %g1, 11 + 2, %g1; \
or %g3, %lo(BRANCH_ALWAYS), %g3; \
or %g3, %g1, %g3; \
stw %g3, [%g2]; \
sethi %hi(NOP), %g3; \
or %g3, %lo(NOP), %g3; \
stw %g3, [%g2 + 0x4]; \
flush %g2;
.globl niagara2_patch_copyops
.type niagara2_patch_copyops,#function
niagara2_patch_copyops:
NG_DO_PATCH(memcpy, NG2memcpy)
NG_DO_PATCH(___copy_from_user, NG2copy_from_user)
NG_DO_PATCH(___copy_to_user, NG2copy_to_user)
retl
nop
.size niagara2_patch_copyops,.-niagara2_patch_copyops
......@@ -45,6 +45,7 @@ NGcopy_user_page: /* %o0=dest, %o1=src, %o2=vaddr */
retl
nop
.globl NGclear_page, NGclear_user_page
NGclear_page: /* %o0=dest */
NGclear_user_page: /* %o0=dest, %o1=vaddr */
mov 8, %g1
......
......@@ -68,7 +68,6 @@ struct sbus_dev {
/* This struct describes the SBus(s) found on this machine. */
struct sbus_bus {
struct of_device ofdev;
void *iommu; /* Opaque IOMMU cookie */
struct sbus_dev *devices; /* Link to devices on this SBus */
struct sbus_bus *next; /* next SBus, if more than one SBus */
int prom_node; /* PROM device tree node for this SBus */
......
......@@ -203,4 +203,10 @@ extern struct task_struct *last_task_used_math;
#define FP_INHIBIT_RESULTS ((last_task_used_math->thread.fsr >> 23) & _fex)
#endif
#ifdef CONFIG_SMP
#define FP_TRAPPING_EXCEPTIONS ((current->thread.fsr >> 23) & 0x1f)
#else
#define FP_TRAPPING_EXCEPTIONS ((last_task_used_math->thread.fsr >> 23) & 0x1f)
#endif
#endif
......@@ -70,6 +70,7 @@
#define HWCAP_SPARC_V9 16
#define HWCAP_SPARC_ULTRA3 32
#define HWCAP_SPARC_BLKINIT 64
#define HWCAP_SPARC_N2 128
/*
* These are used to set parameters in the core dumps.
......@@ -155,8 +156,13 @@ static inline unsigned int sparc64_elf_hwcap(void)
if (tlb_type == cheetah || tlb_type == cheetah_plus)
cap |= HWCAP_SPARC_ULTRA3;
else if (tlb_type == hypervisor)
else if (tlb_type == hypervisor) {
if (sun4v_chip_type == SUN4V_CHIP_NIAGARA1 ||
sun4v_chip_type == SUN4V_CHIP_NIAGARA2)
cap |= HWCAP_SPARC_BLKINIT;
if (sun4v_chip_type == SUN4V_CHIP_NIAGARA2)
cap |= HWCAP_SPARC_N2;
}
return cap;
}
......
......@@ -88,4 +88,6 @@
#define FP_INHIBIT_RESULTS ((current_thread_info()->xfsr[0] >> 23) & _fex)
#define FP_TRAPPING_EXCEPTIONS ((current_thread_info()->xfsr[0] >> 23) & 0x1f)
#endif
......@@ -145,13 +145,16 @@ do { \
{ \
X##_e = 1; \
_FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc); \
FP_SET_EXCEPTION(FP_EX_INEXACT); \
} \
else \
{ \
X##_e = 0; \
_FP_FRAC_SRL_##wc(X, _FP_WORKBITS); \
FP_SET_EXCEPTION(FP_EX_UNDERFLOW); \
} \
if ((FP_CUR_EXCEPTIONS & FP_EX_INEXACT) || \
(FP_TRAPPING_EXCEPTIONS & FP_EX_UNDERFLOW)) \
FP_SET_EXCEPTION(FP_EX_UNDERFLOW); \
} \
else \
{ \
......
......@@ -97,12 +97,19 @@
#define FP_INHIBIT_RESULTS 0
#endif
#ifndef FP_TRAPPING_EXCEPTIONS
#define FP_TRAPPING_EXCPETIONS 0
#endif
#define FP_SET_EXCEPTION(ex) \
_fex |= (ex)
#define FP_UNSET_EXCEPTION(ex) \
_fex &= ~(ex)
#define FP_CUR_EXCEPTIONS \
(_fex)
#define FP_CLEAR_EXCEPTIONS \
_fex = 0
......
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