Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc
Pull Sparc updates from David S. Miller: 1) Remove the idiotic situation wherein Leon was a special case in all of the TLB/cache handling code. The worst side effect of this bogosity is that you couldn't build a kernel with Leon support enabled (to get better build coverage), and test boot it on a non-LEON cpu. Leon is, in all core respects, programatically identical to the 32-bit SRMMU. Except that they put the TLB registers in a different alternate address space location. Through code patching (for fast paths) and run time checks, this issue is now a thing of the past. From Sam Ravnborg. 2) There was a mis-merge of arch/sparc/Kconfig for one of the clockevents changes that went in, causing 32-bit sparc to start failing to build. I merged in your tree to get those clockevents changes (and added a note to the merge commit) then added Stephen Rothwell's fix for the merge error. 3) Software quad floating point emulation was not working properly on more recent Niagara chips, because the way the situation is reported by the cpu has changed. Nobody noticed because gcc emits calls to software emulation routines in glibc. * git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc: (25 commits) sparc: fix sparc64 build due to leon.h inclusion sparc32: remove unused variable in head_32.S sparc32,leon: fix leon bootup sparc32: Export leon_dma_ops to modules. sparc32: support leon + sun in dma_make_coherent() sparc32,leon: always support leon in ioport sparc32,leon: always include leon_pmc in build sparc32: refactor cpu_idle() sparc32: srmmu_probe now knows about leon too sparc32: drop LEON hack for ASI_M_MMUREGS sparc32: introduce run-time patching of srmmu access functions sparc32: introduce support for run-time patching for all shared assembler code sparc32,leon: fix section mismatch warning sparc32,leon: always include leon_smp + leon_mm in build sparc32,leon: always include leon_kernel in build sparc32,leon: clean up leon.h sparc32: handle leon in cpu.c sparc32: handle leon in irq_32.c sparc32: add support for run-time patching of leon/sun single instructions sparc32: introduce sparc32_start_kernel called from head_32.S ...
This commit is contained in:
commit
f737c7705f
34 changed files with 449 additions and 387 deletions
|
@ -41,7 +41,6 @@ config SPARC32
|
||||||
def_bool !64BIT
|
def_bool !64BIT
|
||||||
select GENERIC_ATOMIC64
|
select GENERIC_ATOMIC64
|
||||||
select CLZ_TAB
|
select CLZ_TAB
|
||||||
select ARCH_USES_GETTIMEOFFSET
|
|
||||||
|
|
||||||
config SPARC64
|
config SPARC64
|
||||||
def_bool 64BIT
|
def_bool 64BIT
|
||||||
|
|
|
@ -40,11 +40,7 @@
|
||||||
#define ASI_M_UNA01 0x01 /* Same here... */
|
#define ASI_M_UNA01 0x01 /* Same here... */
|
||||||
#define ASI_M_MXCC 0x02 /* Access to TI VIKING MXCC registers */
|
#define ASI_M_MXCC 0x02 /* Access to TI VIKING MXCC registers */
|
||||||
#define ASI_M_FLUSH_PROBE 0x03 /* Reference MMU Flush/Probe; rw, ss */
|
#define ASI_M_FLUSH_PROBE 0x03 /* Reference MMU Flush/Probe; rw, ss */
|
||||||
#ifndef CONFIG_SPARC_LEON
|
|
||||||
#define ASI_M_MMUREGS 0x04 /* MMU Registers; rw, ss */
|
#define ASI_M_MMUREGS 0x04 /* MMU Registers; rw, ss */
|
||||||
#else
|
|
||||||
#define ASI_M_MMUREGS 0x19
|
|
||||||
#endif /* CONFIG_SPARC_LEON */
|
|
||||||
#define ASI_M_TLBDIAG 0x05 /* MMU TLB only Diagnostics */
|
#define ASI_M_TLBDIAG 0x05 /* MMU TLB only Diagnostics */
|
||||||
#define ASI_M_DIAGS 0x06 /* Reference MMU Diagnostics */
|
#define ASI_M_DIAGS 0x06 /* Reference MMU Diagnostics */
|
||||||
#define ASI_M_IODIAG 0x07 /* MMU I/O TLB only Diagnostics */
|
#define ASI_M_IODIAG 0x07 /* MMU I/O TLB only Diagnostics */
|
||||||
|
|
|
@ -20,4 +20,26 @@
|
||||||
/* All traps low-level code here must end with this macro. */
|
/* All traps low-level code here must end with this macro. */
|
||||||
#define RESTORE_ALL b ret_trap_entry; clr %l6;
|
#define RESTORE_ALL b ret_trap_entry; clr %l6;
|
||||||
|
|
||||||
|
/* Support for run-time patching of single instructions.
|
||||||
|
* This is used to handle the differences in the ASI for
|
||||||
|
* MMUREGS for LEON and SUN.
|
||||||
|
*
|
||||||
|
* Sample:
|
||||||
|
* LEON_PI(lda [%g0] ASI_LEON_MMUREGS, %o0
|
||||||
|
* SUN_PI_(lda [%g0] ASI_M_MMUREGS, %o0
|
||||||
|
* PI == Patch Instruction
|
||||||
|
*
|
||||||
|
* For LEON we will use the first variant,
|
||||||
|
* and for all other we will use the SUN variant.
|
||||||
|
* The order is important.
|
||||||
|
*/
|
||||||
|
#define LEON_PI(...) \
|
||||||
|
662: __VA_ARGS__
|
||||||
|
|
||||||
|
#define SUN_PI_(...) \
|
||||||
|
.section .leon_1insn_patch, "ax"; \
|
||||||
|
.word 662b; \
|
||||||
|
__VA_ARGS__; \
|
||||||
|
.previous
|
||||||
|
|
||||||
#endif /* !(_SPARC_ASMMACRO_H) */
|
#endif /* !(_SPARC_ASMMACRO_H) */
|
||||||
|
|
|
@ -12,13 +12,18 @@ extern int dma_supported(struct device *dev, u64 mask);
|
||||||
#define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
|
#define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
|
||||||
#define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h)
|
#define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h)
|
||||||
|
|
||||||
extern struct dma_map_ops *dma_ops, pci32_dma_ops;
|
extern struct dma_map_ops *dma_ops;
|
||||||
|
extern struct dma_map_ops *leon_dma_ops;
|
||||||
|
extern struct dma_map_ops pci32_dma_ops;
|
||||||
|
|
||||||
extern struct bus_type pci_bus_type;
|
extern struct bus_type pci_bus_type;
|
||||||
|
|
||||||
static inline struct dma_map_ops *get_dma_ops(struct device *dev)
|
static inline struct dma_map_ops *get_dma_ops(struct device *dev)
|
||||||
{
|
{
|
||||||
#if defined(CONFIG_SPARC32) && defined(CONFIG_PCI)
|
#if defined(CONFIG_SPARC32) && defined(CONFIG_PCI)
|
||||||
if (dev->bus == &pci_bus_type)
|
if (sparc_cpu_model == sparc_leon)
|
||||||
|
return leon_dma_ops;
|
||||||
|
else if (dev->bus == &pci_bus_type)
|
||||||
return &pci32_dma_ops;
|
return &pci32_dma_ops;
|
||||||
#endif
|
#endif
|
||||||
return dma_ops;
|
return dma_ops;
|
||||||
|
|
|
@ -8,8 +8,6 @@
|
||||||
#ifndef LEON_H_INCLUDE
|
#ifndef LEON_H_INCLUDE
|
||||||
#define LEON_H_INCLUDE
|
#define LEON_H_INCLUDE
|
||||||
|
|
||||||
#ifdef CONFIG_SPARC_LEON
|
|
||||||
|
|
||||||
/* mmu register access, ASI_LEON_MMUREGS */
|
/* mmu register access, ASI_LEON_MMUREGS */
|
||||||
#define LEON_CNR_CTRL 0x000
|
#define LEON_CNR_CTRL 0x000
|
||||||
#define LEON_CNR_CTXP 0x100
|
#define LEON_CNR_CTXP 0x100
|
||||||
|
@ -62,15 +60,6 @@
|
||||||
|
|
||||||
#ifndef __ASSEMBLY__
|
#ifndef __ASSEMBLY__
|
||||||
|
|
||||||
/* do a virtual address read without cache */
|
|
||||||
static inline unsigned long leon_readnobuffer_reg(unsigned long paddr)
|
|
||||||
{
|
|
||||||
unsigned long retval;
|
|
||||||
__asm__ __volatile__("lda [%1] %2, %0\n\t" :
|
|
||||||
"=r"(retval) : "r"(paddr), "i"(ASI_LEON_NOCACHE));
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* do a physical address bypass write, i.e. for 0x80000000 */
|
/* do a physical address bypass write, i.e. for 0x80000000 */
|
||||||
static inline void leon_store_reg(unsigned long paddr, unsigned long value)
|
static inline void leon_store_reg(unsigned long paddr, unsigned long value)
|
||||||
{
|
{
|
||||||
|
@ -87,47 +76,16 @@ static inline unsigned long leon_load_reg(unsigned long paddr)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void leon_srmmu_disabletlb(void)
|
|
||||||
{
|
|
||||||
unsigned int retval;
|
|
||||||
__asm__ __volatile__("lda [%%g0] %2, %0\n\t" : "=r"(retval) : "r"(0),
|
|
||||||
"i"(ASI_LEON_MMUREGS));
|
|
||||||
retval |= LEON_CNR_CTRL_TLBDIS;
|
|
||||||
__asm__ __volatile__("sta %0, [%%g0] %2\n\t" : : "r"(retval), "r"(0),
|
|
||||||
"i"(ASI_LEON_MMUREGS) : "memory");
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void leon_srmmu_enabletlb(void)
|
|
||||||
{
|
|
||||||
unsigned int retval;
|
|
||||||
__asm__ __volatile__("lda [%%g0] %2, %0\n\t" : "=r"(retval) : "r"(0),
|
|
||||||
"i"(ASI_LEON_MMUREGS));
|
|
||||||
retval = retval & ~LEON_CNR_CTRL_TLBDIS;
|
|
||||||
__asm__ __volatile__("sta %0, [%%g0] %2\n\t" : : "r"(retval), "r"(0),
|
|
||||||
"i"(ASI_LEON_MMUREGS) : "memory");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* macro access for leon_load_reg() and leon_store_reg() */
|
/* macro access for leon_load_reg() and leon_store_reg() */
|
||||||
#define LEON3_BYPASS_LOAD_PA(x) (leon_load_reg((unsigned long)(x)))
|
#define LEON3_BYPASS_LOAD_PA(x) (leon_load_reg((unsigned long)(x)))
|
||||||
#define LEON3_BYPASS_STORE_PA(x, v) (leon_store_reg((unsigned long)(x), (unsigned long)(v)))
|
#define LEON3_BYPASS_STORE_PA(x, v) (leon_store_reg((unsigned long)(x), (unsigned long)(v)))
|
||||||
#define LEON3_BYPASS_ANDIN_PA(x, v) LEON3_BYPASS_STORE_PA(x, LEON3_BYPASS_LOAD_PA(x) & v)
|
|
||||||
#define LEON3_BYPASS_ORIN_PA(x, v) LEON3_BYPASS_STORE_PA(x, LEON3_BYPASS_LOAD_PA(x) | v)
|
|
||||||
#define LEON_BYPASS_LOAD_PA(x) leon_load_reg((unsigned long)(x))
|
#define LEON_BYPASS_LOAD_PA(x) leon_load_reg((unsigned long)(x))
|
||||||
#define LEON_BYPASS_STORE_PA(x, v) leon_store_reg((unsigned long)(x), (unsigned long)(v))
|
#define LEON_BYPASS_STORE_PA(x, v) leon_store_reg((unsigned long)(x), (unsigned long)(v))
|
||||||
#define LEON_REGLOAD_PA(x) leon_load_reg((unsigned long)(x)+LEON_PREGS)
|
|
||||||
#define LEON_REGSTORE_PA(x, v) leon_store_reg((unsigned long)(x)+LEON_PREGS, (unsigned long)(v))
|
|
||||||
#define LEON_REGSTORE_OR_PA(x, v) LEON_REGSTORE_PA(x, LEON_REGLOAD_PA(x) | (unsigned long)(v))
|
|
||||||
#define LEON_REGSTORE_AND_PA(x, v) LEON_REGSTORE_PA(x, LEON_REGLOAD_PA(x) & (unsigned long)(v))
|
|
||||||
|
|
||||||
/* macro access for leon_readnobuffer_reg() */
|
|
||||||
#define LEON_BYPASSCACHE_LOAD_VA(x) leon_readnobuffer_reg((unsigned long)(x))
|
|
||||||
|
|
||||||
extern void leon_init(void);
|
extern void leon_init(void);
|
||||||
extern void leon_switch_mm(void);
|
extern void leon_switch_mm(void);
|
||||||
extern void leon_init_IRQ(void);
|
extern void leon_init_IRQ(void);
|
||||||
|
|
||||||
extern unsigned long last_valid_pfn;
|
|
||||||
|
|
||||||
static inline unsigned long sparc_leon3_get_dcachecfg(void)
|
static inline unsigned long sparc_leon3_get_dcachecfg(void)
|
||||||
{
|
{
|
||||||
unsigned int retval;
|
unsigned int retval;
|
||||||
|
@ -230,9 +188,6 @@ static inline int sparc_leon3_cpuid(void)
|
||||||
#error cannot determine LEON_PAGE_SIZE_LEON
|
#error cannot determine LEON_PAGE_SIZE_LEON
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define PAGE_MIN_SHIFT (12)
|
|
||||||
#define PAGE_MIN_SIZE (1UL << PAGE_MIN_SHIFT)
|
|
||||||
|
|
||||||
#define LEON3_XCCR_SETS_MASK 0x07000000UL
|
#define LEON3_XCCR_SETS_MASK 0x07000000UL
|
||||||
#define LEON3_XCCR_SSIZE_MASK 0x00f00000UL
|
#define LEON3_XCCR_SSIZE_MASK 0x00f00000UL
|
||||||
|
|
||||||
|
@ -242,7 +197,7 @@ static inline int sparc_leon3_cpuid(void)
|
||||||
#ifndef __ASSEMBLY__
|
#ifndef __ASSEMBLY__
|
||||||
struct vm_area_struct;
|
struct vm_area_struct;
|
||||||
|
|
||||||
extern unsigned long srmmu_swprobe(unsigned long vaddr, unsigned long *paddr);
|
extern unsigned long leon_swprobe(unsigned long vaddr, unsigned long *paddr);
|
||||||
extern void leon_flush_icache_all(void);
|
extern void leon_flush_icache_all(void);
|
||||||
extern void leon_flush_dcache_all(void);
|
extern void leon_flush_dcache_all(void);
|
||||||
extern void leon_flush_cache_all(void);
|
extern void leon_flush_cache_all(void);
|
||||||
|
@ -258,15 +213,7 @@ struct leon3_cacheregs {
|
||||||
unsigned long dccr; /* 0x0c - Data Cache Configuration Register */
|
unsigned long dccr; /* 0x0c - Data Cache Configuration Register */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* struct that hold LEON2 cache configuration register
|
#include <linux/irq.h>
|
||||||
* & configuration register
|
|
||||||
*/
|
|
||||||
struct leon2_cacheregs {
|
|
||||||
unsigned long ccr, cfg;
|
|
||||||
};
|
|
||||||
|
|
||||||
#ifdef __KERNEL__
|
|
||||||
|
|
||||||
#include <linux/interrupt.h>
|
#include <linux/interrupt.h>
|
||||||
|
|
||||||
struct device_node;
|
struct device_node;
|
||||||
|
@ -292,24 +239,15 @@ extern void leon_smp_done(void);
|
||||||
extern void leon_boot_cpus(void);
|
extern void leon_boot_cpus(void);
|
||||||
extern int leon_boot_one_cpu(int i, struct task_struct *);
|
extern int leon_boot_one_cpu(int i, struct task_struct *);
|
||||||
void leon_init_smp(void);
|
void leon_init_smp(void);
|
||||||
extern void cpu_idle(void);
|
|
||||||
extern void init_IRQ(void);
|
|
||||||
extern void cpu_panic(void);
|
|
||||||
extern int __leon_processor_id(void);
|
|
||||||
void leon_enable_irq_cpu(unsigned int irq_nr, unsigned int cpu);
|
void leon_enable_irq_cpu(unsigned int irq_nr, unsigned int cpu);
|
||||||
extern irqreturn_t leon_percpu_timer_interrupt(int irq, void *unused);
|
extern irqreturn_t leon_percpu_timer_interrupt(int irq, void *unused);
|
||||||
|
|
||||||
extern unsigned int real_irq_entry[];
|
|
||||||
extern unsigned int smpleon_ipi[];
|
extern unsigned int smpleon_ipi[];
|
||||||
extern unsigned int patchme_maybe_smp_msg[];
|
extern unsigned int linux_trap_ipi15_leon[];
|
||||||
extern unsigned int t_nmi[], linux_trap_ipi15_leon[];
|
|
||||||
extern unsigned int linux_trap_ipi15_sun4m[];
|
|
||||||
extern int leon_ipi_irq;
|
extern int leon_ipi_irq;
|
||||||
|
|
||||||
#endif /* CONFIG_SMP */
|
#endif /* CONFIG_SMP */
|
||||||
|
|
||||||
#endif /* __KERNEL__ */
|
|
||||||
|
|
||||||
#endif /* __ASSEMBLY__ */
|
#endif /* __ASSEMBLY__ */
|
||||||
|
|
||||||
/* macros used in leon_mm.c */
|
/* macros used in leon_mm.c */
|
||||||
|
@ -317,18 +255,4 @@ extern int leon_ipi_irq;
|
||||||
#define _pfn_valid(pfn) ((pfn < last_valid_pfn) && (pfn >= PFN(phys_base)))
|
#define _pfn_valid(pfn) ((pfn < last_valid_pfn) && (pfn >= PFN(phys_base)))
|
||||||
#define _SRMMU_PTE_PMASK_LEON 0xffffffff
|
#define _SRMMU_PTE_PMASK_LEON 0xffffffff
|
||||||
|
|
||||||
#else /* defined(CONFIG_SPARC_LEON) */
|
|
||||||
|
|
||||||
/* nop definitions for !LEON case */
|
|
||||||
#define leon_init() do {} while (0)
|
|
||||||
#define leon_switch_mm() do {} while (0)
|
|
||||||
#define leon_init_IRQ() do {} while (0)
|
|
||||||
#define init_leon() do {} while (0)
|
|
||||||
#define leon_smp_done() do {} while (0)
|
|
||||||
#define leon_boot_cpus() do {} while (0)
|
|
||||||
#define leon_boot_one_cpu(i, t) 1
|
|
||||||
#define leon_init_smp() do {} while (0)
|
|
||||||
|
|
||||||
#endif /* !defined(CONFIG_SPARC_LEON) */
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -87,8 +87,6 @@ struct amba_prom_registers {
|
||||||
#define LEON3_GPTIMER_CONFIG_NRTIMERS(c) ((c)->config & 0x7)
|
#define LEON3_GPTIMER_CONFIG_NRTIMERS(c) ((c)->config & 0x7)
|
||||||
#define LEON3_GPTIMER_CTRL_ISPENDING(r) (((r)&LEON3_GPTIMER_CTRL_PENDING) ? 1 : 0)
|
#define LEON3_GPTIMER_CTRL_ISPENDING(r) (((r)&LEON3_GPTIMER_CTRL_PENDING) ? 1 : 0)
|
||||||
|
|
||||||
#ifdef CONFIG_SPARC_LEON
|
|
||||||
|
|
||||||
#ifndef __ASSEMBLY__
|
#ifndef __ASSEMBLY__
|
||||||
|
|
||||||
struct leon3_irqctrl_regs_map {
|
struct leon3_irqctrl_regs_map {
|
||||||
|
@ -264,6 +262,4 @@ extern unsigned int sparc_leon_eirq;
|
||||||
|
|
||||||
#define amba_device(x) (((x) >> 12) & 0xfff)
|
#define amba_device(x) (((x) >> 12) & 0xfff)
|
||||||
|
|
||||||
#endif /* !defined(CONFIG_SPARC_LEON) */
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -139,6 +139,7 @@
|
||||||
restore %g0, %g0, %g0;
|
restore %g0, %g0, %g0;
|
||||||
|
|
||||||
#ifndef __ASSEMBLY__
|
#ifndef __ASSEMBLY__
|
||||||
|
extern unsigned long last_valid_pfn;
|
||||||
|
|
||||||
/* This makes sense. Honest it does - Anton */
|
/* This makes sense. Honest it does - Anton */
|
||||||
/* XXX Yes but it's ugly as sin. FIXME. -KMW */
|
/* XXX Yes but it's ugly as sin. FIXME. -KMW */
|
||||||
|
@ -148,67 +149,13 @@ extern void *srmmu_nocache_pool;
|
||||||
#define __nocache_fix(VADDR) __va(__nocache_pa(VADDR))
|
#define __nocache_fix(VADDR) __va(__nocache_pa(VADDR))
|
||||||
|
|
||||||
/* Accessing the MMU control register. */
|
/* Accessing the MMU control register. */
|
||||||
static inline unsigned int srmmu_get_mmureg(void)
|
unsigned int srmmu_get_mmureg(void);
|
||||||
{
|
void srmmu_set_mmureg(unsigned long regval);
|
||||||
unsigned int retval;
|
void srmmu_set_ctable_ptr(unsigned long paddr);
|
||||||
__asm__ __volatile__("lda [%%g0] %1, %0\n\t" :
|
void srmmu_set_context(int context);
|
||||||
"=r" (retval) :
|
int srmmu_get_context(void);
|
||||||
"i" (ASI_M_MMUREGS));
|
unsigned int srmmu_get_fstatus(void);
|
||||||
return retval;
|
unsigned int srmmu_get_faddr(void);
|
||||||
}
|
|
||||||
|
|
||||||
static inline void srmmu_set_mmureg(unsigned long regval)
|
|
||||||
{
|
|
||||||
__asm__ __volatile__("sta %0, [%%g0] %1\n\t" : :
|
|
||||||
"r" (regval), "i" (ASI_M_MMUREGS) : "memory");
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void srmmu_set_ctable_ptr(unsigned long paddr)
|
|
||||||
{
|
|
||||||
paddr = ((paddr >> 4) & SRMMU_CTX_PMASK);
|
|
||||||
__asm__ __volatile__("sta %0, [%1] %2\n\t" : :
|
|
||||||
"r" (paddr), "r" (SRMMU_CTXTBL_PTR),
|
|
||||||
"i" (ASI_M_MMUREGS) :
|
|
||||||
"memory");
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void srmmu_set_context(int context)
|
|
||||||
{
|
|
||||||
__asm__ __volatile__("sta %0, [%1] %2\n\t" : :
|
|
||||||
"r" (context), "r" (SRMMU_CTX_REG),
|
|
||||||
"i" (ASI_M_MMUREGS) : "memory");
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int srmmu_get_context(void)
|
|
||||||
{
|
|
||||||
register int retval;
|
|
||||||
__asm__ __volatile__("lda [%1] %2, %0\n\t" :
|
|
||||||
"=r" (retval) :
|
|
||||||
"r" (SRMMU_CTX_REG),
|
|
||||||
"i" (ASI_M_MMUREGS));
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline unsigned int srmmu_get_fstatus(void)
|
|
||||||
{
|
|
||||||
unsigned int retval;
|
|
||||||
|
|
||||||
__asm__ __volatile__("lda [%1] %2, %0\n\t" :
|
|
||||||
"=r" (retval) :
|
|
||||||
"r" (SRMMU_FAULT_STATUS), "i" (ASI_M_MMUREGS));
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline unsigned int srmmu_get_faddr(void)
|
|
||||||
{
|
|
||||||
unsigned int retval;
|
|
||||||
|
|
||||||
__asm__ __volatile__("lda [%1] %2, %0\n\t" :
|
|
||||||
"=r" (retval) :
|
|
||||||
"r" (SRMMU_FAULT_ADDR), "i" (ASI_M_MMUREGS));
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* This is guaranteed on all SRMMU's. */
|
/* This is guaranteed on all SRMMU's. */
|
||||||
static inline void srmmu_flush_whole_tlb(void)
|
static inline void srmmu_flush_whole_tlb(void)
|
||||||
|
@ -219,23 +166,6 @@ static inline void srmmu_flush_whole_tlb(void)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* These flush types are not available on all chips... */
|
|
||||||
#ifndef CONFIG_SPARC_LEON
|
|
||||||
static inline unsigned long srmmu_hwprobe(unsigned long vaddr)
|
|
||||||
{
|
|
||||||
unsigned long retval;
|
|
||||||
|
|
||||||
vaddr &= PAGE_MASK;
|
|
||||||
__asm__ __volatile__("lda [%1] %2, %0\n\t" :
|
|
||||||
"=r" (retval) :
|
|
||||||
"r" (vaddr | 0x400), "i" (ASI_M_FLUSH_PROBE));
|
|
||||||
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
#define srmmu_hwprobe(addr) srmmu_swprobe(addr, 0)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
srmmu_get_pte (unsigned long addr)
|
srmmu_get_pte (unsigned long addr)
|
||||||
{
|
{
|
||||||
|
|
|
@ -35,6 +35,14 @@
|
||||||
#define PSR_VERS 0x0f000000 /* cpu-version field */
|
#define PSR_VERS 0x0f000000 /* cpu-version field */
|
||||||
#define PSR_IMPL 0xf0000000 /* cpu-implementation field */
|
#define PSR_IMPL 0xf0000000 /* cpu-implementation field */
|
||||||
|
|
||||||
|
#define PSR_VERS_SHIFT 24
|
||||||
|
#define PSR_IMPL_SHIFT 28
|
||||||
|
#define PSR_VERS_SHIFTED_MASK 0xf
|
||||||
|
#define PSR_IMPL_SHIFTED_MASK 0xf
|
||||||
|
|
||||||
|
#define PSR_IMPL_TI 0x4
|
||||||
|
#define PSR_IMPL_LEON 0xf
|
||||||
|
|
||||||
#ifdef __KERNEL__
|
#ifdef __KERNEL__
|
||||||
|
|
||||||
#ifndef __ASSEMBLY__
|
#ifndef __ASSEMBLY__
|
||||||
|
|
|
@ -7,4 +7,7 @@
|
||||||
/* sparc entry point */
|
/* sparc entry point */
|
||||||
extern char _start[];
|
extern char _start[];
|
||||||
|
|
||||||
|
extern char __leon_1insn_patch[];
|
||||||
|
extern char __leon_1insn_patch_end[];
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -51,8 +51,8 @@ obj-y += of_device_common.o
|
||||||
obj-y += of_device_$(BITS).o
|
obj-y += of_device_$(BITS).o
|
||||||
obj-$(CONFIG_SPARC64) += prom_irqtrans.o
|
obj-$(CONFIG_SPARC64) += prom_irqtrans.o
|
||||||
|
|
||||||
obj-$(CONFIG_SPARC_LEON)+= leon_kernel.o
|
obj-$(CONFIG_SPARC32) += leon_kernel.o
|
||||||
obj-$(CONFIG_SPARC_LEON)+= leon_pmc.o
|
obj-$(CONFIG_SPARC32) += leon_pmc.o
|
||||||
|
|
||||||
obj-$(CONFIG_SPARC64) += reboot.o
|
obj-$(CONFIG_SPARC64) += reboot.o
|
||||||
obj-$(CONFIG_SPARC64) += sysfs.o
|
obj-$(CONFIG_SPARC64) += sysfs.o
|
||||||
|
|
|
@ -121,7 +121,7 @@ static const struct manufacturer_info __initconst manufacturer_info[] = {
|
||||||
FPU(-1, NULL)
|
FPU(-1, NULL)
|
||||||
}
|
}
|
||||||
},{
|
},{
|
||||||
4,
|
PSR_IMPL_TI,
|
||||||
.cpu_info = {
|
.cpu_info = {
|
||||||
CPU(0, "Texas Instruments, Inc. - SuperSparc-(II)"),
|
CPU(0, "Texas Instruments, Inc. - SuperSparc-(II)"),
|
||||||
/* SparcClassic -- borned STP1010TAB-50*/
|
/* SparcClassic -- borned STP1010TAB-50*/
|
||||||
|
@ -191,7 +191,7 @@ static const struct manufacturer_info __initconst manufacturer_info[] = {
|
||||||
FPU(-1, NULL)
|
FPU(-1, NULL)
|
||||||
}
|
}
|
||||||
},{
|
},{
|
||||||
0xF, /* Aeroflex Gaisler */
|
PSR_IMPL_LEON, /* Aeroflex Gaisler */
|
||||||
.cpu_info = {
|
.cpu_info = {
|
||||||
CPU(3, "LEON"),
|
CPU(3, "LEON"),
|
||||||
CPU(-1, NULL)
|
CPU(-1, NULL)
|
||||||
|
@ -440,16 +440,16 @@ static int __init cpu_type_probe(void)
|
||||||
int psr_impl, psr_vers, fpu_vers;
|
int psr_impl, psr_vers, fpu_vers;
|
||||||
int psr;
|
int psr;
|
||||||
|
|
||||||
psr_impl = ((get_psr() >> 28) & 0xf);
|
psr_impl = ((get_psr() >> PSR_IMPL_SHIFT) & PSR_IMPL_SHIFTED_MASK);
|
||||||
psr_vers = ((get_psr() >> 24) & 0xf);
|
psr_vers = ((get_psr() >> PSR_VERS_SHIFT) & PSR_VERS_SHIFTED_MASK);
|
||||||
|
|
||||||
psr = get_psr();
|
psr = get_psr();
|
||||||
put_psr(psr | PSR_EF);
|
put_psr(psr | PSR_EF);
|
||||||
#ifdef CONFIG_SPARC_LEON
|
|
||||||
fpu_vers = get_psr() & PSR_EF ? ((get_fsr() >> 17) & 0x7) : 7;
|
if (psr_impl == PSR_IMPL_LEON)
|
||||||
#else
|
fpu_vers = get_psr() & PSR_EF ? ((get_fsr() >> 17) & 0x7) : 7;
|
||||||
fpu_vers = ((get_fsr() >> 17) & 0x7);
|
else
|
||||||
#endif
|
fpu_vers = ((get_fsr() >> 17) & 0x7);
|
||||||
|
|
||||||
put_psr(psr);
|
put_psr(psr);
|
||||||
|
|
||||||
|
|
|
@ -393,7 +393,6 @@ linux_trap_ipi15_sun4d:
|
||||||
/* FIXME */
|
/* FIXME */
|
||||||
1: b,a 1b
|
1: b,a 1b
|
||||||
|
|
||||||
#ifdef CONFIG_SPARC_LEON
|
|
||||||
.globl smpleon_ipi
|
.globl smpleon_ipi
|
||||||
.extern leon_ipi_interrupt
|
.extern leon_ipi_interrupt
|
||||||
/* SMP per-cpu IPI interrupts are handled specially. */
|
/* SMP per-cpu IPI interrupts are handled specially. */
|
||||||
|
@ -424,8 +423,6 @@ linux_trap_ipi15_leon:
|
||||||
b ret_trap_lockless_ipi
|
b ret_trap_lockless_ipi
|
||||||
clr %l6
|
clr %l6
|
||||||
|
|
||||||
#endif /* CONFIG_SPARC_LEON */
|
|
||||||
|
|
||||||
#endif /* CONFIG_SMP */
|
#endif /* CONFIG_SMP */
|
||||||
|
|
||||||
/* This routine handles illegal instructions and privileged
|
/* This routine handles illegal instructions and privileged
|
||||||
|
@ -770,8 +767,11 @@ srmmu_fault:
|
||||||
mov 0x400, %l5
|
mov 0x400, %l5
|
||||||
mov 0x300, %l4
|
mov 0x300, %l4
|
||||||
|
|
||||||
lda [%l5] ASI_M_MMUREGS, %l6 ! read sfar first
|
LEON_PI(lda [%l5] ASI_LEON_MMUREGS, %l6) ! read sfar first
|
||||||
lda [%l4] ASI_M_MMUREGS, %l5 ! read sfsr last
|
SUN_PI_(lda [%l5] ASI_M_MMUREGS, %l6) ! read sfar first
|
||||||
|
|
||||||
|
LEON_PI(lda [%l4] ASI_LEON_MMUREGS, %l5) ! read sfsr last
|
||||||
|
SUN_PI_(lda [%l4] ASI_M_MMUREGS, %l5) ! read sfsr last
|
||||||
|
|
||||||
andn %l6, 0xfff, %l6
|
andn %l6, 0xfff, %l6
|
||||||
srl %l5, 6, %l5 ! and encode all info into l7
|
srl %l5, 6, %l5 ! and encode all info into l7
|
||||||
|
|
|
@ -234,7 +234,8 @@ tsetup_srmmu_stackchk:
|
||||||
|
|
||||||
cmp %glob_tmp, %sp
|
cmp %glob_tmp, %sp
|
||||||
bleu,a 1f
|
bleu,a 1f
|
||||||
lda [%g0] ASI_M_MMUREGS, %glob_tmp ! read MMU control
|
LEON_PI( lda [%g0] ASI_LEON_MMUREGS, %glob_tmp) ! read MMU control
|
||||||
|
SUN_PI_( lda [%g0] ASI_M_MMUREGS, %glob_tmp) ! read MMU control
|
||||||
|
|
||||||
trap_setup_user_stack_is_bolixed:
|
trap_setup_user_stack_is_bolixed:
|
||||||
/* From user/kernel into invalid window w/bad user
|
/* From user/kernel into invalid window w/bad user
|
||||||
|
@ -249,18 +250,25 @@ trap_setup_user_stack_is_bolixed:
|
||||||
1:
|
1:
|
||||||
/* Clear the fault status and turn on the no_fault bit. */
|
/* Clear the fault status and turn on the no_fault bit. */
|
||||||
or %glob_tmp, 0x2, %glob_tmp ! or in no_fault bit
|
or %glob_tmp, 0x2, %glob_tmp ! or in no_fault bit
|
||||||
sta %glob_tmp, [%g0] ASI_M_MMUREGS ! set it
|
LEON_PI(sta %glob_tmp, [%g0] ASI_LEON_MMUREGS) ! set it
|
||||||
|
SUN_PI_(sta %glob_tmp, [%g0] ASI_M_MMUREGS) ! set it
|
||||||
|
|
||||||
/* Dump the registers and cross fingers. */
|
/* Dump the registers and cross fingers. */
|
||||||
STORE_WINDOW(sp)
|
STORE_WINDOW(sp)
|
||||||
|
|
||||||
/* Clear the no_fault bit and check the status. */
|
/* Clear the no_fault bit and check the status. */
|
||||||
andn %glob_tmp, 0x2, %glob_tmp
|
andn %glob_tmp, 0x2, %glob_tmp
|
||||||
sta %glob_tmp, [%g0] ASI_M_MMUREGS
|
LEON_PI(sta %glob_tmp, [%g0] ASI_LEON_MMUREGS)
|
||||||
|
SUN_PI_(sta %glob_tmp, [%g0] ASI_M_MMUREGS)
|
||||||
|
|
||||||
mov AC_M_SFAR, %glob_tmp
|
mov AC_M_SFAR, %glob_tmp
|
||||||
lda [%glob_tmp] ASI_M_MMUREGS, %g0
|
LEON_PI(lda [%glob_tmp] ASI_LEON_MMUREGS, %g0)
|
||||||
|
SUN_PI_(lda [%glob_tmp] ASI_M_MMUREGS, %g0)
|
||||||
|
|
||||||
mov AC_M_SFSR, %glob_tmp
|
mov AC_M_SFSR, %glob_tmp
|
||||||
lda [%glob_tmp] ASI_M_MMUREGS, %glob_tmp ! save away status of winstore
|
LEON_PI(lda [%glob_tmp] ASI_LEON_MMUREGS, %glob_tmp)! save away status of winstore
|
||||||
|
SUN_PI_(lda [%glob_tmp] ASI_M_MMUREGS, %glob_tmp) ! save away status of winstore
|
||||||
|
|
||||||
andcc %glob_tmp, 0x2, %g0 ! did we fault?
|
andcc %glob_tmp, 0x2, %g0 ! did we fault?
|
||||||
bne trap_setup_user_stack_is_bolixed ! failure
|
bne trap_setup_user_stack_is_bolixed ! failure
|
||||||
nop
|
nop
|
||||||
|
|
|
@ -30,10 +30,6 @@
|
||||||
* the cpu-type
|
* the cpu-type
|
||||||
*/
|
*/
|
||||||
.align 4
|
.align 4
|
||||||
cputyp:
|
|
||||||
.word 1
|
|
||||||
|
|
||||||
.align 4
|
|
||||||
.globl cputypval
|
.globl cputypval
|
||||||
cputypval:
|
cputypval:
|
||||||
.asciz "sun4m"
|
.asciz "sun4m"
|
||||||
|
@ -46,8 +42,8 @@ cputypvar:
|
||||||
|
|
||||||
.align 4
|
.align 4
|
||||||
|
|
||||||
sun4c_notsup:
|
notsup:
|
||||||
.asciz "Sparc-Linux sun4/sun4c support does no longer exist.\n\n"
|
.asciz "Sparc-Linux sun4/sun4c or MMU-less not supported\n\n"
|
||||||
.align 4
|
.align 4
|
||||||
|
|
||||||
sun4e_notsup:
|
sun4e_notsup:
|
||||||
|
@ -123,7 +119,7 @@ current_pc:
|
||||||
tst %o0
|
tst %o0
|
||||||
be no_sun4u_here
|
be no_sun4u_here
|
||||||
mov %g4, %o7 /* Previous %o7. */
|
mov %g4, %o7 /* Previous %o7. */
|
||||||
|
|
||||||
mov %o0, %l0 ! stash away romvec
|
mov %o0, %l0 ! stash away romvec
|
||||||
mov %o0, %g7 ! put it here too
|
mov %o0, %g7 ! put it here too
|
||||||
mov %o1, %l1 ! stash away debug_vec too
|
mov %o1, %l1 ! stash away debug_vec too
|
||||||
|
@ -132,7 +128,7 @@ current_pc:
|
||||||
set current_pc, %g5
|
set current_pc, %g5
|
||||||
cmp %g3, %g5
|
cmp %g3, %g5
|
||||||
be already_mapped
|
be already_mapped
|
||||||
nop
|
nop
|
||||||
|
|
||||||
/* %l6 will hold the offset we have to subtract
|
/* %l6 will hold the offset we have to subtract
|
||||||
* from absolute symbols in order to access areas
|
* from absolute symbols in order to access areas
|
||||||
|
@ -192,9 +188,9 @@ copy_prom_done:
|
||||||
bne not_a_sun4
|
bne not_a_sun4
|
||||||
nop
|
nop
|
||||||
|
|
||||||
halt_sun4_or_sun4c:
|
halt_notsup:
|
||||||
ld [%g7 + 0x68], %o1
|
ld [%g7 + 0x68], %o1
|
||||||
set sun4c_notsup, %o0
|
set notsup, %o0
|
||||||
sub %o0, %l6, %o0
|
sub %o0, %l6, %o0
|
||||||
call %o1
|
call %o1
|
||||||
nop
|
nop
|
||||||
|
@ -202,18 +198,31 @@ halt_sun4_or_sun4c:
|
||||||
nop
|
nop
|
||||||
|
|
||||||
not_a_sun4:
|
not_a_sun4:
|
||||||
lda [%g0] ASI_M_MMUREGS, %g1
|
/* It looks like this is a machine we support.
|
||||||
andcc %g1, 1, %g0
|
* Now find out what MMU we are dealing with
|
||||||
be halt_sun4_or_sun4c
|
* LEON - identified by the psr.impl field
|
||||||
|
* Viking - identified by the psr.impl field
|
||||||
|
* In all other cases a sun4m srmmu.
|
||||||
|
* We check that the MMU is enabled in all cases.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Check if this is a LEON CPU */
|
||||||
|
rd %psr, %g3
|
||||||
|
srl %g3, PSR_IMPL_SHIFT, %g3
|
||||||
|
and %g3, PSR_IMPL_SHIFTED_MASK, %g3
|
||||||
|
cmp %g3, PSR_IMPL_LEON
|
||||||
|
be leon_remap /* It is a LEON - jump */
|
||||||
nop
|
nop
|
||||||
|
|
||||||
srmmu_remap:
|
/* Sanity-check, is MMU enabled */
|
||||||
/* First, check for a viking (TI) module. */
|
lda [%g0] ASI_M_MMUREGS, %g1
|
||||||
set 0x40000000, %g2
|
andcc %g1, 1, %g0
|
||||||
rd %psr, %g3
|
be halt_notsup
|
||||||
and %g2, %g3, %g3
|
nop
|
||||||
subcc %g3, 0x0, %g0
|
|
||||||
bz srmmu_nviking
|
/* Check for a viking (TI) module. */
|
||||||
|
cmp %g3, PSR_IMPL_TI
|
||||||
|
bne srmmu_not_viking
|
||||||
nop
|
nop
|
||||||
|
|
||||||
/* Figure out what kind of viking we are on.
|
/* Figure out what kind of viking we are on.
|
||||||
|
@ -228,14 +237,14 @@ srmmu_remap:
|
||||||
lda [%g0] ASI_M_MMUREGS, %g3 ! peek in the control reg
|
lda [%g0] ASI_M_MMUREGS, %g3 ! peek in the control reg
|
||||||
and %g2, %g3, %g3
|
and %g2, %g3, %g3
|
||||||
subcc %g3, 0x0, %g0
|
subcc %g3, 0x0, %g0
|
||||||
bnz srmmu_nviking ! is in mbus mode
|
bnz srmmu_not_viking ! is in mbus mode
|
||||||
nop
|
nop
|
||||||
|
|
||||||
rd %psr, %g3 ! DO NOT TOUCH %g3
|
rd %psr, %g3 ! DO NOT TOUCH %g3
|
||||||
andn %g3, PSR_ET, %g2
|
andn %g3, PSR_ET, %g2
|
||||||
wr %g2, 0x0, %psr
|
wr %g2, 0x0, %psr
|
||||||
WRITE_PAUSE
|
WRITE_PAUSE
|
||||||
|
|
||||||
/* Get context table pointer, then convert to
|
/* Get context table pointer, then convert to
|
||||||
* a physical address, which is 36 bits.
|
* a physical address, which is 36 bits.
|
||||||
*/
|
*/
|
||||||
|
@ -258,12 +267,12 @@ srmmu_remap:
|
||||||
lda [%g4] ASI_M_BYPASS, %o1 ! This is a level 1 ptr
|
lda [%g4] ASI_M_BYPASS, %o1 ! This is a level 1 ptr
|
||||||
srl %o1, 0x4, %o1 ! Clear low 4 bits
|
srl %o1, 0x4, %o1 ! Clear low 4 bits
|
||||||
sll %o1, 0x8, %o1 ! Make physical
|
sll %o1, 0x8, %o1 ! Make physical
|
||||||
|
|
||||||
/* Ok, pull in the PTD. */
|
/* Ok, pull in the PTD. */
|
||||||
lda [%o1] ASI_M_BYPASS, %o2 ! This is the 0x0 16MB pgd
|
lda [%o1] ASI_M_BYPASS, %o2 ! This is the 0x0 16MB pgd
|
||||||
|
|
||||||
/* Calculate to KERNBASE entry. */
|
/* Calculate to KERNBASE entry. */
|
||||||
add %o1, KERNBASE >> (SRMMU_PGDIR_SHIFT - 2), %o3
|
add %o1, KERNBASE >> (SRMMU_PGDIR_SHIFT - 2), %o3
|
||||||
|
|
||||||
/* Poke the entry into the calculated address. */
|
/* Poke the entry into the calculated address. */
|
||||||
sta %o2, [%o3] ASI_M_BYPASS
|
sta %o2, [%o3] ASI_M_BYPASS
|
||||||
|
@ -293,12 +302,12 @@ srmmu_remap:
|
||||||
b go_to_highmem
|
b go_to_highmem
|
||||||
nop
|
nop
|
||||||
|
|
||||||
|
srmmu_not_viking:
|
||||||
/* This works on viking's in Mbus mode and all
|
/* This works on viking's in Mbus mode and all
|
||||||
* other MBUS modules. It is virtually the same as
|
* other MBUS modules. It is virtually the same as
|
||||||
* the above madness sans turning traps off and flipping
|
* the above madness sans turning traps off and flipping
|
||||||
* the AC bit.
|
* the AC bit.
|
||||||
*/
|
*/
|
||||||
srmmu_nviking:
|
|
||||||
set AC_M_CTPR, %g1
|
set AC_M_CTPR, %g1
|
||||||
lda [%g1] ASI_M_MMUREGS, %g1 ! get ctx table ptr
|
lda [%g1] ASI_M_MMUREGS, %g1 ! get ctx table ptr
|
||||||
sll %g1, 0x4, %g1 ! make physical addr
|
sll %g1, 0x4, %g1 ! make physical addr
|
||||||
|
@ -313,6 +322,29 @@ srmmu_nviking:
|
||||||
nop ! wheee....
|
nop ! wheee....
|
||||||
|
|
||||||
|
|
||||||
|
leon_remap:
|
||||||
|
/* Sanity-check, is MMU enabled */
|
||||||
|
lda [%g0] ASI_LEON_MMUREGS, %g1
|
||||||
|
andcc %g1, 1, %g0
|
||||||
|
be halt_notsup
|
||||||
|
nop
|
||||||
|
|
||||||
|
/* Same code as in the srmmu_not_viking case,
|
||||||
|
* with the LEON ASI for mmuregs
|
||||||
|
*/
|
||||||
|
set AC_M_CTPR, %g1
|
||||||
|
lda [%g1] ASI_LEON_MMUREGS, %g1 ! get ctx table ptr
|
||||||
|
sll %g1, 0x4, %g1 ! make physical addr
|
||||||
|
lda [%g1] ASI_M_BYPASS, %g1 ! ptr to level 1 pg_table
|
||||||
|
srl %g1, 0x4, %g1
|
||||||
|
sll %g1, 0x8, %g1 ! make phys addr for l1 tbl
|
||||||
|
|
||||||
|
lda [%g1] ASI_M_BYPASS, %g2 ! get level1 entry for 0x0
|
||||||
|
add %g1, KERNBASE >> (SRMMU_PGDIR_SHIFT - 2), %g3
|
||||||
|
sta %g2, [%g3] ASI_M_BYPASS ! place at KERNBASE entry
|
||||||
|
b go_to_highmem
|
||||||
|
nop ! wheee....
|
||||||
|
|
||||||
/* Now do a non-relative jump so that PC is in high-memory */
|
/* Now do a non-relative jump so that PC is in high-memory */
|
||||||
go_to_highmem:
|
go_to_highmem:
|
||||||
set execute_in_high_mem, %g1
|
set execute_in_high_mem, %g1
|
||||||
|
@ -336,8 +368,9 @@ execute_in_high_mem:
|
||||||
sethi %hi(linux_dbvec), %g1
|
sethi %hi(linux_dbvec), %g1
|
||||||
st %o1, [%g1 + %lo(linux_dbvec)]
|
st %o1, [%g1 + %lo(linux_dbvec)]
|
||||||
|
|
||||||
/* Get the machine type via the mysterious romvec node operations. */
|
/* Get the machine type via the romvec
|
||||||
|
* getprops node operation
|
||||||
|
*/
|
||||||
add %g7, 0x1c, %l1
|
add %g7, 0x1c, %l1
|
||||||
ld [%l1], %l0
|
ld [%l1], %l0
|
||||||
ld [%l0], %l0
|
ld [%l0], %l0
|
||||||
|
@ -356,9 +389,42 @@ execute_in_high_mem:
|
||||||
! to a buf where above string
|
! to a buf where above string
|
||||||
! will get stored by the prom.
|
! will get stored by the prom.
|
||||||
|
|
||||||
#ifdef CONFIG_SPARC_LEON
|
|
||||||
/* no cpu-type check is needed, it is a SPARC-LEON */
|
|
||||||
|
|
||||||
|
/* Check value of "compatible" property.
|
||||||
|
* "value" => "model"
|
||||||
|
* leon => sparc_leon
|
||||||
|
* sun4m => sun4m
|
||||||
|
* sun4s => sun4m
|
||||||
|
* sun4d => sun4d
|
||||||
|
* sun4e => "no_sun4e_here"
|
||||||
|
* '*' => "no_sun4u_here"
|
||||||
|
* Check single letters only
|
||||||
|
*/
|
||||||
|
|
||||||
|
set cputypval, %o2
|
||||||
|
/* If cputypval[0] == 'l' (lower case letter L) this is leon */
|
||||||
|
ldub [%o2], %l1
|
||||||
|
cmp %l1, 'l'
|
||||||
|
be leon_init
|
||||||
|
nop
|
||||||
|
|
||||||
|
/* Check cputypval[4] to find the sun model */
|
||||||
|
ldub [%o2 + 0x4], %l1
|
||||||
|
|
||||||
|
cmp %l1, 'm'
|
||||||
|
be sun4m_init
|
||||||
|
cmp %l1, 's'
|
||||||
|
be sun4m_init
|
||||||
|
cmp %l1, 'd'
|
||||||
|
be sun4d_init
|
||||||
|
cmp %l1, 'e'
|
||||||
|
be no_sun4e_here ! Could be a sun4e.
|
||||||
|
nop
|
||||||
|
b no_sun4u_here ! AIEEE, a V9 sun4u... Get our BIG BROTHER kernel :))
|
||||||
|
nop
|
||||||
|
|
||||||
|
leon_init:
|
||||||
|
/* LEON CPU - set boot_cpu_id */
|
||||||
sethi %hi(boot_cpu_id), %g2 ! boot-cpu index
|
sethi %hi(boot_cpu_id), %g2 ! boot-cpu index
|
||||||
|
|
||||||
#ifdef CONFIG_SMP
|
#ifdef CONFIG_SMP
|
||||||
|
@ -376,26 +442,6 @@ execute_in_high_mem:
|
||||||
|
|
||||||
ba continue_boot
|
ba continue_boot
|
||||||
nop
|
nop
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Check to cputype. We may be booted on a sun4u (64 bit box),
|
|
||||||
* and sun4d needs special treatment.
|
|
||||||
*/
|
|
||||||
|
|
||||||
set cputypval, %o2
|
|
||||||
ldub [%o2 + 0x4], %l1
|
|
||||||
|
|
||||||
cmp %l1, 'm'
|
|
||||||
be sun4m_init
|
|
||||||
cmp %l1, 's'
|
|
||||||
be sun4m_init
|
|
||||||
cmp %l1, 'd'
|
|
||||||
be sun4d_init
|
|
||||||
cmp %l1, 'e'
|
|
||||||
be no_sun4e_here ! Could be a sun4e.
|
|
||||||
nop
|
|
||||||
b no_sun4u_here ! AIEEE, a V9 sun4u... Get our BIG BROTHER kernel :))
|
|
||||||
nop
|
|
||||||
|
|
||||||
/* CPUID in bootbus can be found at PA 0xff0140000 */
|
/* CPUID in bootbus can be found at PA 0xff0140000 */
|
||||||
#define SUN4D_BOOTBUS_CPUID 0xf0140000
|
#define SUN4D_BOOTBUS_CPUID 0xf0140000
|
||||||
|
@ -431,9 +477,9 @@ sun4m_init:
|
||||||
/* This sucks, apparently this makes Vikings call prom panic, will fix later */
|
/* This sucks, apparently this makes Vikings call prom panic, will fix later */
|
||||||
2:
|
2:
|
||||||
rd %psr, %o1
|
rd %psr, %o1
|
||||||
srl %o1, 28, %o1 ! Get a type of the CPU
|
srl %o1, PSR_IMPL_SHIFT, %o1 ! Get a type of the CPU
|
||||||
|
|
||||||
subcc %o1, 4, %g0 ! TI: Viking or MicroSPARC
|
subcc %o1, PSR_IMPL_TI, %g0 ! TI: Viking or MicroSPARC
|
||||||
be continue_boot
|
be continue_boot
|
||||||
nop
|
nop
|
||||||
|
|
||||||
|
@ -459,10 +505,6 @@ continue_boot:
|
||||||
/* Aieee, now set PC and nPC, enable traps, give ourselves a stack and it's
|
/* Aieee, now set PC and nPC, enable traps, give ourselves a stack and it's
|
||||||
* show-time!
|
* show-time!
|
||||||
*/
|
*/
|
||||||
|
|
||||||
sethi %hi(cputyp), %o0
|
|
||||||
st %g4, [%o0 + %lo(cputyp)]
|
|
||||||
|
|
||||||
/* Turn on Supervisor, EnableFloating, and all the PIL bits.
|
/* Turn on Supervisor, EnableFloating, and all the PIL bits.
|
||||||
* Also puts us in register window zero with traps off.
|
* Also puts us in register window zero with traps off.
|
||||||
*/
|
*/
|
||||||
|
@ -480,7 +522,7 @@ continue_boot:
|
||||||
set __bss_start , %o0 ! First address of BSS
|
set __bss_start , %o0 ! First address of BSS
|
||||||
set _end , %o1 ! Last address of BSS
|
set _end , %o1 ! Last address of BSS
|
||||||
add %o0, 0x1, %o0
|
add %o0, 0x1, %o0
|
||||||
1:
|
1:
|
||||||
stb %g0, [%o0]
|
stb %g0, [%o0]
|
||||||
subcc %o0, %o1, %g0
|
subcc %o0, %o1, %g0
|
||||||
bl 1b
|
bl 1b
|
||||||
|
@ -546,7 +588,7 @@ continue_boot:
|
||||||
set dest, %g2; \
|
set dest, %g2; \
|
||||||
ld [%g5], %g4; \
|
ld [%g5], %g4; \
|
||||||
st %g4, [%g2];
|
st %g4, [%g2];
|
||||||
|
|
||||||
/* Patch for window spills... */
|
/* Patch for window spills... */
|
||||||
PATCH_INSN(spnwin_patch1_7win, spnwin_patch1)
|
PATCH_INSN(spnwin_patch1_7win, spnwin_patch1)
|
||||||
PATCH_INSN(spnwin_patch2_7win, spnwin_patch2)
|
PATCH_INSN(spnwin_patch2_7win, spnwin_patch2)
|
||||||
|
@ -597,7 +639,7 @@ continue_boot:
|
||||||
st %g4, [%g5 + 0x18]
|
st %g4, [%g5 + 0x18]
|
||||||
st %g4, [%g5 + 0x1c]
|
st %g4, [%g5 + 0x1c]
|
||||||
|
|
||||||
2:
|
2:
|
||||||
sethi %hi(nwindows), %g4
|
sethi %hi(nwindows), %g4
|
||||||
st %g3, [%g4 + %lo(nwindows)] ! store final value
|
st %g3, [%g4 + %lo(nwindows)] ! store final value
|
||||||
sub %g3, 0x1, %g3
|
sub %g3, 0x1, %g3
|
||||||
|
@ -617,18 +659,12 @@ continue_boot:
|
||||||
wr %g3, PSR_ET, %psr
|
wr %g3, PSR_ET, %psr
|
||||||
WRITE_PAUSE
|
WRITE_PAUSE
|
||||||
|
|
||||||
/* First we call prom_init() to set up PROMLIB, then
|
/* Call sparc32_start_kernel(struct linux_romvec *rp) */
|
||||||
* off to start_kernel().
|
|
||||||
*/
|
|
||||||
|
|
||||||
sethi %hi(prom_vector_p), %g5
|
sethi %hi(prom_vector_p), %g5
|
||||||
ld [%g5 + %lo(prom_vector_p)], %o0
|
ld [%g5 + %lo(prom_vector_p)], %o0
|
||||||
call prom_init
|
call sparc32_start_kernel
|
||||||
nop
|
nop
|
||||||
|
|
||||||
call start_kernel
|
|
||||||
nop
|
|
||||||
|
|
||||||
/* We should not get here. */
|
/* We should not get here. */
|
||||||
call halt_me
|
call halt_me
|
||||||
nop
|
nop
|
||||||
|
@ -659,7 +695,7 @@ sun4u_5:
|
||||||
.asciz "write"
|
.asciz "write"
|
||||||
.align 4
|
.align 4
|
||||||
sun4u_6:
|
sun4u_6:
|
||||||
.asciz "\n\rOn sun4u you have to use UltraLinux (64bit) kernel\n\rand not a 32bit sun4[cdem] version\n\r\n\r"
|
.asciz "\n\rOn sun4u you have to use sparc64 kernel\n\rand not a sparc32 version\n\r\n\r"
|
||||||
sun4u_6e:
|
sun4u_6e:
|
||||||
.align 4
|
.align 4
|
||||||
sun4u_7:
|
sun4u_7:
|
||||||
|
|
|
@ -55,17 +55,13 @@ const struct sparc32_dma_ops *sparc32_dma_ops;
|
||||||
/* This function must make sure that caches and memory are coherent after DMA
|
/* This function must make sure that caches and memory are coherent after DMA
|
||||||
* On LEON systems without cache snooping it flushes the entire D-CACHE.
|
* On LEON systems without cache snooping it flushes the entire D-CACHE.
|
||||||
*/
|
*/
|
||||||
#ifndef CONFIG_SPARC_LEON
|
|
||||||
static inline void dma_make_coherent(unsigned long pa, unsigned long len)
|
static inline void dma_make_coherent(unsigned long pa, unsigned long len)
|
||||||
{
|
{
|
||||||
|
if (sparc_cpu_model == sparc_leon) {
|
||||||
|
if (!sparc_leon3_snooping_enabled())
|
||||||
|
leon_flush_dcache_all();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
static inline void dma_make_coherent(unsigned long pa, unsigned long len)
|
|
||||||
{
|
|
||||||
if (!sparc_leon3_snooping_enabled())
|
|
||||||
leon_flush_dcache_all();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static void __iomem *_sparc_ioremap(struct resource *res, u32 bus, u32 pa, int sz);
|
static void __iomem *_sparc_ioremap(struct resource *res, u32 bus, u32 pa, int sz);
|
||||||
static void __iomem *_sparc_alloc_io(unsigned int busno, unsigned long phys,
|
static void __iomem *_sparc_alloc_io(unsigned int busno, unsigned long phys,
|
||||||
|
@ -427,9 +423,6 @@ arch_initcall(sparc_register_ioport);
|
||||||
#endif /* CONFIG_SBUS */
|
#endif /* CONFIG_SBUS */
|
||||||
|
|
||||||
|
|
||||||
/* LEON reuses PCI DMA ops */
|
|
||||||
#if defined(CONFIG_PCI) || defined(CONFIG_SPARC_LEON)
|
|
||||||
|
|
||||||
/* Allocate and map kernel buffer using consistent mode DMA for a device.
|
/* Allocate and map kernel buffer using consistent mode DMA for a device.
|
||||||
* hwdev should be valid struct pci_dev pointer for PCI devices.
|
* hwdev should be valid struct pci_dev pointer for PCI devices.
|
||||||
*/
|
*/
|
||||||
|
@ -657,14 +650,11 @@ struct dma_map_ops pci32_dma_ops = {
|
||||||
};
|
};
|
||||||
EXPORT_SYMBOL(pci32_dma_ops);
|
EXPORT_SYMBOL(pci32_dma_ops);
|
||||||
|
|
||||||
#endif /* CONFIG_PCI || CONFIG_SPARC_LEON */
|
/* leon re-uses pci32_dma_ops */
|
||||||
|
struct dma_map_ops *leon_dma_ops = &pci32_dma_ops;
|
||||||
|
EXPORT_SYMBOL(leon_dma_ops);
|
||||||
|
|
||||||
#ifdef CONFIG_SPARC_LEON
|
|
||||||
struct dma_map_ops *dma_ops = &pci32_dma_ops;
|
|
||||||
#elif defined(CONFIG_SBUS)
|
|
||||||
struct dma_map_ops *dma_ops = &sbus_dma_ops;
|
struct dma_map_ops *dma_ops = &sbus_dma_ops;
|
||||||
#endif
|
|
||||||
|
|
||||||
EXPORT_SYMBOL(dma_ops);
|
EXPORT_SYMBOL(dma_ops);
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -241,9 +241,6 @@ int sparc_floppy_request_irq(unsigned int irq, irq_handler_t irq_handler)
|
||||||
unsigned int cpu_irq;
|
unsigned int cpu_irq;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
#if defined CONFIG_SMP && !defined CONFIG_SPARC_LEON
|
|
||||||
struct tt_entry *trap_table;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
err = request_irq(irq, irq_handler, 0, "floppy", NULL);
|
err = request_irq(irq, irq_handler, 0, "floppy", NULL);
|
||||||
if (err)
|
if (err)
|
||||||
|
@ -264,13 +261,18 @@ int sparc_floppy_request_irq(unsigned int irq, irq_handler_t irq_handler)
|
||||||
table[SP_TRAP_IRQ1+(cpu_irq-1)].inst_four = SPARC_NOP;
|
table[SP_TRAP_IRQ1+(cpu_irq-1)].inst_four = SPARC_NOP;
|
||||||
|
|
||||||
INSTANTIATE(sparc_ttable)
|
INSTANTIATE(sparc_ttable)
|
||||||
#if defined CONFIG_SMP && !defined CONFIG_SPARC_LEON
|
|
||||||
trap_table = &trapbase_cpu1;
|
#if defined CONFIG_SMP
|
||||||
INSTANTIATE(trap_table)
|
if (sparc_cpu_model != sparc_leon) {
|
||||||
trap_table = &trapbase_cpu2;
|
struct tt_entry *trap_table;
|
||||||
INSTANTIATE(trap_table)
|
|
||||||
trap_table = &trapbase_cpu3;
|
trap_table = &trapbase_cpu1;
|
||||||
INSTANTIATE(trap_table)
|
INSTANTIATE(trap_table)
|
||||||
|
trap_table = &trapbase_cpu2;
|
||||||
|
INSTANTIATE(trap_table)
|
||||||
|
trap_table = &trapbase_cpu3;
|
||||||
|
INSTANTIATE(trap_table)
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
#undef INSTANTIATE
|
#undef INSTANTIATE
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -26,6 +26,9 @@ static inline unsigned long kimage_addr_to_ra(const char *p)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_SPARC32
|
#ifdef CONFIG_SPARC32
|
||||||
|
/* setup_32.c */
|
||||||
|
void sparc32_start_kernel(struct linux_romvec *rp);
|
||||||
|
|
||||||
/* cpu.c */
|
/* cpu.c */
|
||||||
extern void cpu_probe(void);
|
extern void cpu_probe(void);
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
#include <asm/smp.h>
|
#include <asm/smp.h>
|
||||||
#include <asm/setup.h>
|
#include <asm/setup.h>
|
||||||
|
|
||||||
|
#include "kernel.h"
|
||||||
#include "prom.h"
|
#include "prom.h"
|
||||||
#include "irq.h"
|
#include "irq.h"
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#include <linux/pm.h>
|
#include <linux/pm.h>
|
||||||
|
|
||||||
#include <asm/leon_amba.h>
|
#include <asm/leon_amba.h>
|
||||||
|
#include <asm/cpu_type.h>
|
||||||
#include <asm/leon.h>
|
#include <asm/leon.h>
|
||||||
|
|
||||||
/* List of Systems that need fixup instructions around power-down instruction */
|
/* List of Systems that need fixup instructions around power-down instruction */
|
||||||
|
@ -65,13 +66,15 @@ void pmc_leon_idle(void)
|
||||||
/* Install LEON Power Down function */
|
/* Install LEON Power Down function */
|
||||||
static int __init leon_pmc_install(void)
|
static int __init leon_pmc_install(void)
|
||||||
{
|
{
|
||||||
/* Assign power management IDLE handler */
|
if (sparc_cpu_model == sparc_leon) {
|
||||||
if (pmc_leon_need_fixup())
|
/* Assign power management IDLE handler */
|
||||||
pm_idle = pmc_leon_idle_fixup;
|
if (pmc_leon_need_fixup())
|
||||||
else
|
pm_idle = pmc_leon_idle_fixup;
|
||||||
pm_idle = pmc_leon_idle;
|
else
|
||||||
|
pm_idle = pmc_leon_idle;
|
||||||
|
|
||||||
printk(KERN_INFO "leon: power management initialized\n");
|
printk(KERN_INFO "leon: power management initialized\n");
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,15 +48,13 @@
|
||||||
|
|
||||||
#include "kernel.h"
|
#include "kernel.h"
|
||||||
|
|
||||||
#ifdef CONFIG_SPARC_LEON
|
|
||||||
|
|
||||||
#include "irq.h"
|
#include "irq.h"
|
||||||
|
|
||||||
extern ctxd_t *srmmu_ctx_table_phys;
|
extern ctxd_t *srmmu_ctx_table_phys;
|
||||||
static int smp_processors_ready;
|
static int smp_processors_ready;
|
||||||
extern volatile unsigned long cpu_callin_map[NR_CPUS];
|
extern volatile unsigned long cpu_callin_map[NR_CPUS];
|
||||||
extern cpumask_t smp_commenced_mask;
|
extern cpumask_t smp_commenced_mask;
|
||||||
void __init leon_configure_cache_smp(void);
|
void __cpuinit leon_configure_cache_smp(void);
|
||||||
static void leon_ipi_init(void);
|
static void leon_ipi_init(void);
|
||||||
|
|
||||||
/* IRQ number of LEON IPIs */
|
/* IRQ number of LEON IPIs */
|
||||||
|
@ -123,7 +121,7 @@ void __cpuinit leon_callin(void)
|
||||||
|
|
||||||
extern struct linux_prom_registers smp_penguin_ctable;
|
extern struct linux_prom_registers smp_penguin_ctable;
|
||||||
|
|
||||||
void __init leon_configure_cache_smp(void)
|
void __cpuinit leon_configure_cache_smp(void)
|
||||||
{
|
{
|
||||||
unsigned long cfg = sparc_leon3_get_dcachecfg();
|
unsigned long cfg = sparc_leon3_get_dcachecfg();
|
||||||
int me = smp_processor_id();
|
int me = smp_processor_id();
|
||||||
|
@ -507,5 +505,3 @@ void __init leon_init_smp(void)
|
||||||
|
|
||||||
sparc32_ipi_ops = &leon_ipi_ops;
|
sparc32_ipi_ops = &leon_ipi_ops;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* CONFIG_SPARC_LEON */
|
|
||||||
|
|
|
@ -65,50 +65,25 @@ extern void fpsave(unsigned long *, unsigned long *, void *, unsigned long *);
|
||||||
struct task_struct *last_task_used_math = NULL;
|
struct task_struct *last_task_used_math = NULL;
|
||||||
struct thread_info *current_set[NR_CPUS];
|
struct thread_info *current_set[NR_CPUS];
|
||||||
|
|
||||||
#ifndef CONFIG_SMP
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* the idle loop on a Sparc... ;)
|
* the idle loop on a Sparc... ;)
|
||||||
*/
|
*/
|
||||||
void cpu_idle(void)
|
void cpu_idle(void)
|
||||||
{
|
{
|
||||||
|
set_thread_flag(TIF_POLLING_NRFLAG);
|
||||||
|
|
||||||
/* endless idle loop with no priority at all */
|
/* endless idle loop with no priority at all */
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (pm_idle) {
|
while (!need_resched()) {
|
||||||
while (!need_resched())
|
if (pm_idle)
|
||||||
(*pm_idle)();
|
(*pm_idle)();
|
||||||
} else {
|
else
|
||||||
while (!need_resched())
|
|
||||||
cpu_relax();
|
cpu_relax();
|
||||||
}
|
}
|
||||||
schedule_preempt_disabled();
|
schedule_preempt_disabled();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
/* This is being executed in task 0 'user space'. */
|
|
||||||
void cpu_idle(void)
|
|
||||||
{
|
|
||||||
set_thread_flag(TIF_POLLING_NRFLAG);
|
|
||||||
/* endless idle loop with no priority at all */
|
|
||||||
while(1) {
|
|
||||||
#ifdef CONFIG_SPARC_LEON
|
|
||||||
if (pm_idle) {
|
|
||||||
while (!need_resched())
|
|
||||||
(*pm_idle)();
|
|
||||||
} else
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
while (!need_resched())
|
|
||||||
cpu_relax();
|
|
||||||
}
|
|
||||||
schedule_preempt_disabled();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* XXX cli/sti -> local_irq_xxx here, check this works once SMP is fixed. */
|
/* XXX cli/sti -> local_irq_xxx here, check this works once SMP is fixed. */
|
||||||
void machine_halt(void)
|
void machine_halt(void)
|
||||||
{
|
{
|
||||||
|
|
|
@ -23,7 +23,6 @@
|
||||||
#include <linux/of_pdt.h>
|
#include <linux/of_pdt.h>
|
||||||
#include <asm/prom.h>
|
#include <asm/prom.h>
|
||||||
#include <asm/oplib.h>
|
#include <asm/oplib.h>
|
||||||
#include <asm/leon.h>
|
|
||||||
|
|
||||||
#include "prom.h"
|
#include "prom.h"
|
||||||
|
|
||||||
|
|
|
@ -231,11 +231,14 @@ srmmu_rett_stackchk:
|
||||||
cmp %g1, %fp
|
cmp %g1, %fp
|
||||||
bleu ret_trap_user_stack_is_bolixed
|
bleu ret_trap_user_stack_is_bolixed
|
||||||
mov AC_M_SFSR, %g1
|
mov AC_M_SFSR, %g1
|
||||||
lda [%g1] ASI_M_MMUREGS, %g0
|
LEON_PI(lda [%g1] ASI_LEON_MMUREGS, %g0)
|
||||||
|
SUN_PI_(lda [%g1] ASI_M_MMUREGS, %g0)
|
||||||
|
|
||||||
lda [%g0] ASI_M_MMUREGS, %g1
|
LEON_PI(lda [%g0] ASI_LEON_MMUREGS, %g1)
|
||||||
|
SUN_PI_(lda [%g0] ASI_M_MMUREGS, %g1)
|
||||||
or %g1, 0x2, %g1
|
or %g1, 0x2, %g1
|
||||||
sta %g1, [%g0] ASI_M_MMUREGS
|
LEON_PI(sta %g1, [%g0] ASI_LEON_MMUREGS)
|
||||||
|
SUN_PI_(sta %g1, [%g0] ASI_M_MMUREGS)
|
||||||
|
|
||||||
restore %g0, %g0, %g0
|
restore %g0, %g0, %g0
|
||||||
|
|
||||||
|
@ -244,13 +247,16 @@ srmmu_rett_stackchk:
|
||||||
save %g0, %g0, %g0
|
save %g0, %g0, %g0
|
||||||
|
|
||||||
andn %g1, 0x2, %g1
|
andn %g1, 0x2, %g1
|
||||||
sta %g1, [%g0] ASI_M_MMUREGS
|
LEON_PI(sta %g1, [%g0] ASI_LEON_MMUREGS)
|
||||||
|
SUN_PI_(sta %g1, [%g0] ASI_M_MMUREGS)
|
||||||
|
|
||||||
mov AC_M_SFAR, %g2
|
mov AC_M_SFAR, %g2
|
||||||
lda [%g2] ASI_M_MMUREGS, %g2
|
LEON_PI(lda [%g2] ASI_LEON_MMUREGS, %g2)
|
||||||
|
SUN_PI_(lda [%g2] ASI_M_MMUREGS, %g2)
|
||||||
|
|
||||||
mov AC_M_SFSR, %g1
|
mov AC_M_SFSR, %g1
|
||||||
lda [%g1] ASI_M_MMUREGS, %g1
|
LEON_PI(lda [%g1] ASI_LEON_MMUREGS, %g1)
|
||||||
|
SUN_PI_(lda [%g1] ASI_M_MMUREGS, %g1)
|
||||||
andcc %g1, 0x2, %g0
|
andcc %g1, 0x2, %g0
|
||||||
be ret_trap_userwins_ok
|
be ret_trap_userwins_ok
|
||||||
nop
|
nop
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
#include <linux/cpu.h>
|
#include <linux/cpu.h>
|
||||||
#include <linux/kdebug.h>
|
#include <linux/kdebug.h>
|
||||||
#include <linux/export.h>
|
#include <linux/export.h>
|
||||||
|
#include <linux/start_kernel.h>
|
||||||
|
|
||||||
#include <asm/io.h>
|
#include <asm/io.h>
|
||||||
#include <asm/processor.h>
|
#include <asm/processor.h>
|
||||||
|
@ -45,6 +46,7 @@
|
||||||
#include <asm/cpudata.h>
|
#include <asm/cpudata.h>
|
||||||
#include <asm/setup.h>
|
#include <asm/setup.h>
|
||||||
#include <asm/cacheflush.h>
|
#include <asm/cacheflush.h>
|
||||||
|
#include <asm/sections.h>
|
||||||
|
|
||||||
#include "kernel.h"
|
#include "kernel.h"
|
||||||
|
|
||||||
|
@ -237,13 +239,62 @@ static void __init per_cpu_patch(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct leon_1insn_patch_entry {
|
||||||
|
unsigned int addr;
|
||||||
|
unsigned int insn;
|
||||||
|
};
|
||||||
|
|
||||||
enum sparc_cpu sparc_cpu_model;
|
enum sparc_cpu sparc_cpu_model;
|
||||||
EXPORT_SYMBOL(sparc_cpu_model);
|
EXPORT_SYMBOL(sparc_cpu_model);
|
||||||
|
|
||||||
struct tt_entry *sparc_ttable;
|
static __init void leon_patch(void)
|
||||||
|
{
|
||||||
|
struct leon_1insn_patch_entry *start = (void *)__leon_1insn_patch;
|
||||||
|
struct leon_1insn_patch_entry *end = (void *)__leon_1insn_patch_end;
|
||||||
|
|
||||||
|
/* Default instruction is leon - no patching */
|
||||||
|
if (sparc_cpu_model == sparc_leon)
|
||||||
|
return;
|
||||||
|
|
||||||
|
while (start < end) {
|
||||||
|
unsigned long addr = start->addr;
|
||||||
|
|
||||||
|
*(unsigned int *)(addr) = start->insn;
|
||||||
|
flushi(addr);
|
||||||
|
|
||||||
|
start++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct tt_entry *sparc_ttable;
|
||||||
struct pt_regs fake_swapper_regs;
|
struct pt_regs fake_swapper_regs;
|
||||||
|
|
||||||
|
/* Called from head_32.S - before we have setup anything
|
||||||
|
* in the kernel. Be very careful with what you do here.
|
||||||
|
*/
|
||||||
|
void __init sparc32_start_kernel(struct linux_romvec *rp)
|
||||||
|
{
|
||||||
|
prom_init(rp);
|
||||||
|
|
||||||
|
/* Set sparc_cpu_model */
|
||||||
|
sparc_cpu_model = sun_unknown;
|
||||||
|
if (!strcmp(&cputypval[0], "sun4m"))
|
||||||
|
sparc_cpu_model = sun4m;
|
||||||
|
if (!strcmp(&cputypval[0], "sun4s"))
|
||||||
|
sparc_cpu_model = sun4m; /* CP-1200 with PROM 2.30 -E */
|
||||||
|
if (!strcmp(&cputypval[0], "sun4d"))
|
||||||
|
sparc_cpu_model = sun4d;
|
||||||
|
if (!strcmp(&cputypval[0], "sun4e"))
|
||||||
|
sparc_cpu_model = sun4e;
|
||||||
|
if (!strcmp(&cputypval[0], "sun4u"))
|
||||||
|
sparc_cpu_model = sun4u;
|
||||||
|
if (!strncmp(&cputypval[0], "leon" , 4))
|
||||||
|
sparc_cpu_model = sparc_leon;
|
||||||
|
|
||||||
|
leon_patch();
|
||||||
|
start_kernel();
|
||||||
|
}
|
||||||
|
|
||||||
void __init setup_arch(char **cmdline_p)
|
void __init setup_arch(char **cmdline_p)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
@ -260,21 +311,6 @@ void __init setup_arch(char **cmdline_p)
|
||||||
|
|
||||||
register_console(&prom_early_console);
|
register_console(&prom_early_console);
|
||||||
|
|
||||||
/* Set sparc_cpu_model */
|
|
||||||
sparc_cpu_model = sun_unknown;
|
|
||||||
if (!strcmp(&cputypval[0], "sun4m"))
|
|
||||||
sparc_cpu_model = sun4m;
|
|
||||||
if (!strcmp(&cputypval[0], "sun4s"))
|
|
||||||
sparc_cpu_model = sun4m; /* CP-1200 with PROM 2.30 -E */
|
|
||||||
if (!strcmp(&cputypval[0], "sun4d"))
|
|
||||||
sparc_cpu_model = sun4d;
|
|
||||||
if (!strcmp(&cputypval[0], "sun4e"))
|
|
||||||
sparc_cpu_model = sun4e;
|
|
||||||
if (!strcmp(&cputypval[0], "sun4u"))
|
|
||||||
sparc_cpu_model = sun4u;
|
|
||||||
if (!strncmp(&cputypval[0], "leon" , 4))
|
|
||||||
sparc_cpu_model = sparc_leon;
|
|
||||||
|
|
||||||
printk("ARCH: ");
|
printk("ARCH: ");
|
||||||
switch(sparc_cpu_model) {
|
switch(sparc_cpu_model) {
|
||||||
case sun4m:
|
case sun4m:
|
||||||
|
|
|
@ -149,8 +149,6 @@ sun4d_cpu_startup:
|
||||||
|
|
||||||
b,a smp_do_cpu_idle
|
b,a smp_do_cpu_idle
|
||||||
|
|
||||||
#ifdef CONFIG_SPARC_LEON
|
|
||||||
|
|
||||||
__CPUINIT
|
__CPUINIT
|
||||||
.align 4
|
.align 4
|
||||||
.global leon_smp_cpu_startup, smp_penguin_ctable
|
.global leon_smp_cpu_startup, smp_penguin_ctable
|
||||||
|
@ -161,7 +159,7 @@ leon_smp_cpu_startup:
|
||||||
ld [%g1+4],%g1
|
ld [%g1+4],%g1
|
||||||
srl %g1,4,%g1
|
srl %g1,4,%g1
|
||||||
set 0x00000100,%g5 /* SRMMU_CTXTBL_PTR */
|
set 0x00000100,%g5 /* SRMMU_CTXTBL_PTR */
|
||||||
sta %g1, [%g5] ASI_M_MMUREGS
|
sta %g1, [%g5] ASI_LEON_MMUREGS
|
||||||
|
|
||||||
/* Set up a sane %psr -- PIL<0xf> S<0x1> PS<0x1> CWP<0x0> */
|
/* Set up a sane %psr -- PIL<0xf> S<0x1> PS<0x1> CWP<0x0> */
|
||||||
set (PSR_PIL | PSR_S | PSR_PS), %g1
|
set (PSR_PIL | PSR_S | PSR_PS), %g1
|
||||||
|
@ -207,5 +205,3 @@ leon_smp_cpu_startup:
|
||||||
nop
|
nop
|
||||||
|
|
||||||
b,a smp_do_cpu_idle
|
b,a smp_do_cpu_idle
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
|
@ -2054,7 +2054,7 @@ void do_fpieee(struct pt_regs *regs)
|
||||||
do_fpe_common(regs);
|
do_fpe_common(regs);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern int do_mathemu(struct pt_regs *, struct fpustate *);
|
extern int do_mathemu(struct pt_regs *, struct fpustate *, bool);
|
||||||
|
|
||||||
void do_fpother(struct pt_regs *regs)
|
void do_fpother(struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
|
@ -2068,7 +2068,7 @@ void do_fpother(struct pt_regs *regs)
|
||||||
switch ((current_thread_info()->xfsr[0] & 0x1c000)) {
|
switch ((current_thread_info()->xfsr[0] & 0x1c000)) {
|
||||||
case (2 << 14): /* unfinished_FPop */
|
case (2 << 14): /* unfinished_FPop */
|
||||||
case (3 << 14): /* unimplemented_FPop */
|
case (3 << 14): /* unimplemented_FPop */
|
||||||
ret = do_mathemu(regs, f);
|
ret = do_mathemu(regs, f, false);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (ret)
|
if (ret)
|
||||||
|
@ -2308,10 +2308,12 @@ void do_illegal_instruction(struct pt_regs *regs)
|
||||||
} else {
|
} else {
|
||||||
struct fpustate *f = FPUSTATE;
|
struct fpustate *f = FPUSTATE;
|
||||||
|
|
||||||
/* XXX maybe verify XFSR bits like
|
/* On UltraSPARC T2 and later, FPU insns which
|
||||||
* XXX do_fpother() does?
|
* are not implemented in HW signal an illegal
|
||||||
|
* instruction trap and do not set the FP Trap
|
||||||
|
* Trap in the %fsr to unimplemented_FPop.
|
||||||
*/
|
*/
|
||||||
if (do_mathemu(regs, f))
|
if (do_mathemu(regs, f, true))
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -107,6 +107,11 @@ SECTIONS
|
||||||
*(.sun4v_2insn_patch)
|
*(.sun4v_2insn_patch)
|
||||||
__sun4v_2insn_patch_end = .;
|
__sun4v_2insn_patch_end = .;
|
||||||
}
|
}
|
||||||
|
.leon_1insn_patch : {
|
||||||
|
__leon_1insn_patch = .;
|
||||||
|
*(.leon_1insn_patch)
|
||||||
|
__leon_1insn_patch_end = .;
|
||||||
|
}
|
||||||
.swapper_tsb_phys_patch : {
|
.swapper_tsb_phys_patch : {
|
||||||
__swapper_tsb_phys_patch = .;
|
__swapper_tsb_phys_patch = .;
|
||||||
*(.swapper_tsb_phys_patch)
|
*(.swapper_tsb_phys_patch)
|
||||||
|
|
|
@ -332,24 +332,30 @@ spwin_srmmu_stackchk:
|
||||||
mov AC_M_SFSR, %glob_tmp
|
mov AC_M_SFSR, %glob_tmp
|
||||||
|
|
||||||
/* Clear the fault status and turn on the no_fault bit. */
|
/* Clear the fault status and turn on the no_fault bit. */
|
||||||
lda [%glob_tmp] ASI_M_MMUREGS, %g0 ! eat SFSR
|
LEON_PI(lda [%glob_tmp] ASI_LEON_MMUREGS, %g0) ! eat SFSR
|
||||||
|
SUN_PI_(lda [%glob_tmp] ASI_M_MMUREGS, %g0) ! eat SFSR
|
||||||
|
|
||||||
lda [%g0] ASI_M_MMUREGS, %glob_tmp ! read MMU control
|
LEON_PI(lda [%g0] ASI_LEON_MMUREGS, %glob_tmp) ! read MMU control
|
||||||
|
SUN_PI_(lda [%g0] ASI_M_MMUREGS, %glob_tmp) ! read MMU control
|
||||||
or %glob_tmp, 0x2, %glob_tmp ! or in no_fault bit
|
or %glob_tmp, 0x2, %glob_tmp ! or in no_fault bit
|
||||||
sta %glob_tmp, [%g0] ASI_M_MMUREGS ! set it
|
LEON_PI(sta %glob_tmp, [%g0] ASI_LEON_MMUREGS) ! set it
|
||||||
|
SUN_PI_(sta %glob_tmp, [%g0] ASI_M_MMUREGS) ! set it
|
||||||
|
|
||||||
/* Dump the registers and cross fingers. */
|
/* Dump the registers and cross fingers. */
|
||||||
STORE_WINDOW(sp)
|
STORE_WINDOW(sp)
|
||||||
|
|
||||||
/* Clear the no_fault bit and check the status. */
|
/* Clear the no_fault bit and check the status. */
|
||||||
andn %glob_tmp, 0x2, %glob_tmp
|
andn %glob_tmp, 0x2, %glob_tmp
|
||||||
sta %glob_tmp, [%g0] ASI_M_MMUREGS
|
LEON_PI(sta %glob_tmp, [%g0] ASI_LEON_MMUREGS)
|
||||||
|
SUN_PI_(sta %glob_tmp, [%g0] ASI_M_MMUREGS)
|
||||||
|
|
||||||
mov AC_M_SFAR, %glob_tmp
|
mov AC_M_SFAR, %glob_tmp
|
||||||
lda [%glob_tmp] ASI_M_MMUREGS, %g0
|
LEON_PI(lda [%glob_tmp] ASI_LEON_MMUREGS, %g0)
|
||||||
|
SUN_PI_(lda [%glob_tmp] ASI_M_MMUREGS, %g0)
|
||||||
|
|
||||||
mov AC_M_SFSR, %glob_tmp
|
mov AC_M_SFSR, %glob_tmp
|
||||||
lda [%glob_tmp] ASI_M_MMUREGS, %glob_tmp
|
LEON_PI(lda [%glob_tmp] ASI_LEON_MMUREGS, %glob_tmp)
|
||||||
|
SUN_PI_(lda [%glob_tmp] ASI_M_MMUREGS, %glob_tmp)
|
||||||
andcc %glob_tmp, 0x2, %g0 ! did we fault?
|
andcc %glob_tmp, 0x2, %g0 ! did we fault?
|
||||||
be,a spwin_finish_up + 0x4 ! cool beans, success
|
be,a spwin_finish_up + 0x4 ! cool beans, success
|
||||||
restore %g0, %g0, %g0
|
restore %g0, %g0, %g0
|
||||||
|
|
|
@ -254,16 +254,19 @@ srmmu_fwin_stackchk:
|
||||||
mov AC_M_SFSR, %l4
|
mov AC_M_SFSR, %l4
|
||||||
cmp %l5, %sp
|
cmp %l5, %sp
|
||||||
bleu fwin_user_stack_is_bolixed
|
bleu fwin_user_stack_is_bolixed
|
||||||
lda [%l4] ASI_M_MMUREGS, %g0 ! clear fault status
|
LEON_PI( lda [%l4] ASI_LEON_MMUREGS, %g0) ! clear fault status
|
||||||
|
SUN_PI_( lda [%l4] ASI_M_MMUREGS, %g0) ! clear fault status
|
||||||
|
|
||||||
/* The technique is, turn off faults on this processor,
|
/* The technique is, turn off faults on this processor,
|
||||||
* just let the load rip, then check the sfsr to see if
|
* just let the load rip, then check the sfsr to see if
|
||||||
* a fault did occur. Then we turn on fault traps again
|
* a fault did occur. Then we turn on fault traps again
|
||||||
* and branch conditionally based upon what happened.
|
* and branch conditionally based upon what happened.
|
||||||
*/
|
*/
|
||||||
lda [%g0] ASI_M_MMUREGS, %l5 ! read mmu-ctrl reg
|
LEON_PI(lda [%g0] ASI_LEON_MMUREGS, %l5) ! read mmu-ctrl reg
|
||||||
|
SUN_PI_(lda [%g0] ASI_M_MMUREGS, %l5) ! read mmu-ctrl reg
|
||||||
or %l5, 0x2, %l5 ! turn on no-fault bit
|
or %l5, 0x2, %l5 ! turn on no-fault bit
|
||||||
sta %l5, [%g0] ASI_M_MMUREGS ! store it
|
LEON_PI(sta %l5, [%g0] ASI_LEON_MMUREGS) ! store it
|
||||||
|
SUN_PI_(sta %l5, [%g0] ASI_M_MMUREGS) ! store it
|
||||||
|
|
||||||
/* Cross fingers and go for it. */
|
/* Cross fingers and go for it. */
|
||||||
LOAD_WINDOW(sp)
|
LOAD_WINDOW(sp)
|
||||||
|
@ -275,18 +278,22 @@ srmmu_fwin_stackchk:
|
||||||
|
|
||||||
/* LOCATION: Window 'T' */
|
/* LOCATION: Window 'T' */
|
||||||
|
|
||||||
lda [%g0] ASI_M_MMUREGS, %twin_tmp1 ! load mmu-ctrl again
|
LEON_PI(lda [%g0] ASI_LEON_MMUREGS, %twin_tmp1) ! load mmu-ctrl again
|
||||||
andn %twin_tmp1, 0x2, %twin_tmp1 ! clear no-fault bit
|
SUN_PI_(lda [%g0] ASI_M_MMUREGS, %twin_tmp1) ! load mmu-ctrl again
|
||||||
sta %twin_tmp1, [%g0] ASI_M_MMUREGS ! store it
|
andn %twin_tmp1, 0x2, %twin_tmp1 ! clear no-fault bit
|
||||||
|
LEON_PI(sta %twin_tmp1, [%g0] ASI_LEON_MMUREGS) ! store it
|
||||||
|
SUN_PI_(sta %twin_tmp1, [%g0] ASI_M_MMUREGS) ! store it
|
||||||
|
|
||||||
mov AC_M_SFAR, %twin_tmp2
|
mov AC_M_SFAR, %twin_tmp2
|
||||||
lda [%twin_tmp2] ASI_M_MMUREGS, %g0 ! read fault address
|
LEON_PI(lda [%twin_tmp2] ASI_LEON_MMUREGS, %g0) ! read fault address
|
||||||
|
SUN_PI_(lda [%twin_tmp2] ASI_M_MMUREGS, %g0) ! read fault address
|
||||||
|
|
||||||
mov AC_M_SFSR, %twin_tmp2
|
mov AC_M_SFSR, %twin_tmp2
|
||||||
lda [%twin_tmp2] ASI_M_MMUREGS, %twin_tmp2 ! read fault status
|
LEON_PI(lda [%twin_tmp2] ASI_LEON_MMUREGS, %twin_tmp2) ! read fault status
|
||||||
andcc %twin_tmp2, 0x2, %g0 ! did fault occur?
|
SUN_PI_(lda [%twin_tmp2] ASI_M_MMUREGS, %twin_tmp2) ! read fault status
|
||||||
|
andcc %twin_tmp2, 0x2, %g0 ! did fault occur?
|
||||||
|
|
||||||
bne 1f ! yep, cleanup
|
bne 1f ! yep, cleanup
|
||||||
nop
|
nop
|
||||||
|
|
||||||
wr %t_psr, 0x0, %psr
|
wr %t_psr, 0x0, %psr
|
||||||
|
|
|
@ -163,7 +163,7 @@ typedef union {
|
||||||
u64 q[2];
|
u64 q[2];
|
||||||
} *argp;
|
} *argp;
|
||||||
|
|
||||||
int do_mathemu(struct pt_regs *regs, struct fpustate *f)
|
int do_mathemu(struct pt_regs *regs, struct fpustate *f, bool illegal_insn_trap)
|
||||||
{
|
{
|
||||||
unsigned long pc = regs->tpc;
|
unsigned long pc = regs->tpc;
|
||||||
unsigned long tstate = regs->tstate;
|
unsigned long tstate = regs->tstate;
|
||||||
|
@ -218,7 +218,7 @@ int do_mathemu(struct pt_regs *regs, struct fpustate *f)
|
||||||
case FSQRTS: {
|
case FSQRTS: {
|
||||||
unsigned long x = current_thread_info()->xfsr[0];
|
unsigned long x = current_thread_info()->xfsr[0];
|
||||||
|
|
||||||
x = (x >> 14) & 0xf;
|
x = (x >> 14) & 0x7;
|
||||||
TYPE(x,1,1,1,1,0,0);
|
TYPE(x,1,1,1,1,0,0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -226,7 +226,7 @@ int do_mathemu(struct pt_regs *regs, struct fpustate *f)
|
||||||
case FSQRTD: {
|
case FSQRTD: {
|
||||||
unsigned long x = current_thread_info()->xfsr[0];
|
unsigned long x = current_thread_info()->xfsr[0];
|
||||||
|
|
||||||
x = (x >> 14) & 0xf;
|
x = (x >> 14) & 0x7;
|
||||||
TYPE(x,2,1,2,1,0,0);
|
TYPE(x,2,1,2,1,0,0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -357,9 +357,17 @@ int do_mathemu(struct pt_regs *regs, struct fpustate *f)
|
||||||
if (type) {
|
if (type) {
|
||||||
argp rs1 = NULL, rs2 = NULL, rd = NULL;
|
argp rs1 = NULL, rs2 = NULL, rd = NULL;
|
||||||
|
|
||||||
freg = (current_thread_info()->xfsr[0] >> 14) & 0xf;
|
/* Starting with UltraSPARC-T2, the cpu does not set the FP Trap
|
||||||
if (freg != (type >> 9))
|
* Type field in the %fsr to unimplemented_FPop. Nor does it
|
||||||
goto err;
|
* use the fp_exception_other trap. Instead it signals an
|
||||||
|
* illegal instruction and leaves the FP trap type field of
|
||||||
|
* the %fsr unchanged.
|
||||||
|
*/
|
||||||
|
if (!illegal_insn_trap) {
|
||||||
|
int ftt = (current_thread_info()->xfsr[0] >> 14) & 0x7;
|
||||||
|
if (ftt != (type >> 9))
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
current_thread_info()->xfsr[0] &= ~0x1c000;
|
current_thread_info()->xfsr[0] &= ~0x1c000;
|
||||||
freg = ((insn >> 14) & 0x1f);
|
freg = ((insn >> 14) & 0x1f);
|
||||||
switch (type & 0x3) {
|
switch (type & 0x3) {
|
||||||
|
|
|
@ -8,8 +8,9 @@ obj-$(CONFIG_SPARC64) += ultra.o tlb.o tsb.o gup.o
|
||||||
obj-y += fault_$(BITS).o
|
obj-y += fault_$(BITS).o
|
||||||
obj-y += init_$(BITS).o
|
obj-y += init_$(BITS).o
|
||||||
obj-$(CONFIG_SPARC32) += extable.o srmmu.o iommu.o io-unit.o
|
obj-$(CONFIG_SPARC32) += extable.o srmmu.o iommu.o io-unit.o
|
||||||
|
obj-$(CONFIG_SPARC32) += srmmu_access.o
|
||||||
obj-$(CONFIG_SPARC32) += hypersparc.o viking.o tsunami.o swift.o
|
obj-$(CONFIG_SPARC32) += hypersparc.o viking.o tsunami.o swift.o
|
||||||
obj-$(CONFIG_SPARC_LEON)+= leon_mm.o
|
obj-$(CONFIG_SPARC32) += leon_mm.o
|
||||||
|
|
||||||
# Only used by sparc64
|
# Only used by sparc64
|
||||||
obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o
|
obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o
|
||||||
|
|
|
@ -32,7 +32,7 @@ static inline unsigned long leon_get_ctable_ptr(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
unsigned long srmmu_swprobe(unsigned long vaddr, unsigned long *paddr)
|
unsigned long leon_swprobe(unsigned long vaddr, unsigned long *paddr)
|
||||||
{
|
{
|
||||||
|
|
||||||
unsigned int ctxtbl;
|
unsigned int ctxtbl;
|
||||||
|
|
|
@ -646,6 +646,23 @@ static void __init srmmu_allocate_ptable_skeleton(unsigned long start,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* These flush types are not available on all chips... */
|
||||||
|
static inline unsigned long srmmu_probe(unsigned long vaddr)
|
||||||
|
{
|
||||||
|
unsigned long retval;
|
||||||
|
|
||||||
|
if (sparc_cpu_model != sparc_leon) {
|
||||||
|
|
||||||
|
vaddr &= PAGE_MASK;
|
||||||
|
__asm__ __volatile__("lda [%1] %2, %0\n\t" :
|
||||||
|
"=r" (retval) :
|
||||||
|
"r" (vaddr | 0x400), "i" (ASI_M_FLUSH_PROBE));
|
||||||
|
} else {
|
||||||
|
retval = leon_swprobe(vaddr, 0);
|
||||||
|
}
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This is much cleaner than poking around physical address space
|
* This is much cleaner than poking around physical address space
|
||||||
* looking at the prom's page table directly which is what most
|
* looking at the prom's page table directly which is what most
|
||||||
|
@ -665,7 +682,7 @@ static void __init srmmu_inherit_prom_mappings(unsigned long start,
|
||||||
break; /* probably wrap around */
|
break; /* probably wrap around */
|
||||||
if(start == 0xfef00000)
|
if(start == 0xfef00000)
|
||||||
start = KADB_DEBUGGER_BEGVM;
|
start = KADB_DEBUGGER_BEGVM;
|
||||||
if(!(prompte = srmmu_hwprobe(start))) {
|
if(!(prompte = srmmu_probe(start))) {
|
||||||
start += PAGE_SIZE;
|
start += PAGE_SIZE;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -674,12 +691,12 @@ static void __init srmmu_inherit_prom_mappings(unsigned long start,
|
||||||
what = 0;
|
what = 0;
|
||||||
|
|
||||||
if(!(start & ~(SRMMU_REAL_PMD_MASK))) {
|
if(!(start & ~(SRMMU_REAL_PMD_MASK))) {
|
||||||
if(srmmu_hwprobe((start-PAGE_SIZE) + SRMMU_REAL_PMD_SIZE) == prompte)
|
if(srmmu_probe((start-PAGE_SIZE) + SRMMU_REAL_PMD_SIZE) == prompte)
|
||||||
what = 1;
|
what = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!(start & ~(SRMMU_PGDIR_MASK))) {
|
if(!(start & ~(SRMMU_PGDIR_MASK))) {
|
||||||
if(srmmu_hwprobe((start-PAGE_SIZE) + SRMMU_PGDIR_SIZE) ==
|
if(srmmu_probe((start-PAGE_SIZE) + SRMMU_PGDIR_SIZE) ==
|
||||||
prompte)
|
prompte)
|
||||||
what = 2;
|
what = 2;
|
||||||
}
|
}
|
||||||
|
@ -1156,7 +1173,7 @@ static void turbosparc_flush_page_to_ram(unsigned long page)
|
||||||
#ifdef TURBOSPARC_WRITEBACK
|
#ifdef TURBOSPARC_WRITEBACK
|
||||||
volatile unsigned long clear;
|
volatile unsigned long clear;
|
||||||
|
|
||||||
if (srmmu_hwprobe(page))
|
if (srmmu_probe(page))
|
||||||
turbosparc_flush_page_cache(page);
|
turbosparc_flush_page_cache(page);
|
||||||
clear = srmmu_get_fstatus();
|
clear = srmmu_get_fstatus();
|
||||||
#endif
|
#endif
|
||||||
|
|
82
arch/sparc/mm/srmmu_access.S
Normal file
82
arch/sparc/mm/srmmu_access.S
Normal file
|
@ -0,0 +1,82 @@
|
||||||
|
/* Assembler variants of srmmu access functions.
|
||||||
|
* Implemented in assembler to allow run-time patching.
|
||||||
|
* LEON uses a different ASI for MMUREGS than SUN.
|
||||||
|
*
|
||||||
|
* The leon_1insn_patch infrastructure is used
|
||||||
|
* for the run-time patching.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/linkage.h>
|
||||||
|
|
||||||
|
#include <asm/asmmacro.h>
|
||||||
|
#include <asm/pgtsrmmu.h>
|
||||||
|
#include <asm/asi.h>
|
||||||
|
|
||||||
|
/* unsigned int srmmu_get_mmureg(void) */
|
||||||
|
ENTRY(srmmu_get_mmureg)
|
||||||
|
LEON_PI(lda [%g0] ASI_LEON_MMUREGS, %o0)
|
||||||
|
SUN_PI_(lda [%g0] ASI_M_MMUREGS, %o0)
|
||||||
|
retl
|
||||||
|
nop
|
||||||
|
ENDPROC(srmmu_get_mmureg)
|
||||||
|
|
||||||
|
/* void srmmu_set_mmureg(unsigned long regval) */
|
||||||
|
ENTRY(srmmu_set_mmureg)
|
||||||
|
LEON_PI(sta %o0, [%g0] ASI_LEON_MMUREGS)
|
||||||
|
SUN_PI_(sta %o0, [%g0] ASI_M_MMUREGS)
|
||||||
|
retl
|
||||||
|
nop
|
||||||
|
ENDPROC(srmmu_set_mmureg)
|
||||||
|
|
||||||
|
/* void srmmu_set_ctable_ptr(unsigned long paddr) */
|
||||||
|
ENTRY(srmmu_set_ctable_ptr)
|
||||||
|
/* paddr = ((paddr >> 4) & SRMMU_CTX_PMASK); */
|
||||||
|
srl %o0, 4, %g1
|
||||||
|
and %g1, SRMMU_CTX_PMASK, %g1
|
||||||
|
|
||||||
|
mov SRMMU_CTXTBL_PTR, %g2
|
||||||
|
LEON_PI(sta %g1, [%g2] ASI_LEON_MMUREGS)
|
||||||
|
SUN_PI_(sta %g1, [%g2] ASI_M_MMUREGS)
|
||||||
|
retl
|
||||||
|
nop
|
||||||
|
ENDPROC(srmmu_set_ctable_ptr)
|
||||||
|
|
||||||
|
|
||||||
|
/* void srmmu_set_context(int context) */
|
||||||
|
ENTRY(srmmu_set_context)
|
||||||
|
mov SRMMU_CTX_REG, %g1
|
||||||
|
LEON_PI(sta %o0, [%g1] ASI_LEON_MMUREGS)
|
||||||
|
SUN_PI_(sta %o0, [%g1] ASI_M_MMUREGS)
|
||||||
|
retl
|
||||||
|
nop
|
||||||
|
ENDPROC(srmmu_set_context)
|
||||||
|
|
||||||
|
|
||||||
|
/* int srmmu_get_context(void) */
|
||||||
|
ENTRY(srmmu_get_context)
|
||||||
|
mov SRMMU_CTX_REG, %o0
|
||||||
|
LEON_PI(lda [%o0] ASI_LEON_MMUREGS, %o0)
|
||||||
|
SUN_PI_(lda [%o0] ASI_M_MMUREGS, %o0)
|
||||||
|
retl
|
||||||
|
nop
|
||||||
|
ENDPROC(srmmu_get_context)
|
||||||
|
|
||||||
|
|
||||||
|
/* unsigned int srmmu_get_fstatus(void) */
|
||||||
|
ENTRY(srmmu_get_fstatus)
|
||||||
|
mov SRMMU_FAULT_STATUS, %o0
|
||||||
|
LEON_PI(lda [%o0] ASI_LEON_MMUREGS, %o0)
|
||||||
|
SUN_PI_(lda [%o0] ASI_M_MMUREGS, %o0)
|
||||||
|
retl
|
||||||
|
nop
|
||||||
|
ENDPROC(srmmu_get_fstatus)
|
||||||
|
|
||||||
|
|
||||||
|
/* unsigned int srmmu_get_faddr(void) */
|
||||||
|
ENTRY(srmmu_get_faddr)
|
||||||
|
mov SRMMU_FAULT_ADDR, %o0
|
||||||
|
LEON_PI(lda [%o0] ASI_LEON_MMUREGS, %o0)
|
||||||
|
SUN_PI_(lda [%o0] ASI_M_MMUREGS, %o0)
|
||||||
|
retl
|
||||||
|
nop
|
||||||
|
ENDPROC(srmmu_get_faddr)
|
Loading…
Add table
Reference in a new issue