Merge master.kernel.org:/pub/scm/linux/kernel/git/davem/sparc-2.6
* master.kernel.org:/pub/scm/linux/kernel/git/davem/sparc-2.6: (230 commits) [SPARC64]: Update defconfig. [SPARC64]: Fix 2 bugs in huge page support. [SPARC64]: CONFIG_BLK_DEV_RAM fix [SPARC64]: Optimized TSB table initialization. [SPARC64]: Allow CONFIG_MEMORY_HOTPLUG to build. [SPARC64]: Use SLAB caches for TSB tables. [SPARC64]: Don't kill the page allocator when growing a TSB. [SPARC64]: Randomize mm->mmap_base when PF_RANDOMIZE is set. [SPARC64]: Increase top of 32-bit process stack. [SPARC64]: Top-down address space allocation for 32-bit tasks. [SPARC64] bbc_i2c: Fix cpu check and add missing module license. [SPARC64]: Fix and re-enable dynamic TSB sizing. [SUNSU]: Fix missing spinlock initialization. [TG3]: Do not try to access NIC_SRAM_DATA_SIG on Sun parts. [SPARC64]: First cut at VIS simulator for Niagara. [SPARC64]: Fix system type in /proc/cpuinfo and remove bogus OBP check. [SPARC64]: Add SMT scheduling support for Niagara. [SPARC64]: Fix 32-bit truncation which broke sparsemem. [SPARC64]: Move over to sparsemem. [SPARC64]: Fix new context version SMP handling. ...
This commit is contained in:
@@ -7,27 +7,19 @@
|
||||
#ifndef _SPARC_IDPROM_H
|
||||
#define _SPARC_IDPROM_H
|
||||
|
||||
/* Offset into the EEPROM where the id PROM is located on the 4c */
|
||||
#define IDPROM_OFFSET 0x7d8
|
||||
#include <linux/types.h>
|
||||
|
||||
/* On sun4m; physical. */
|
||||
/* MicroSPARC(-II) does not decode 31rd bit, but it works. */
|
||||
#define IDPROM_OFFSET_M 0xfd8
|
||||
|
||||
struct idprom
|
||||
{
|
||||
unsigned char id_format; /* Format identifier (always 0x01) */
|
||||
unsigned char id_machtype; /* Machine type */
|
||||
unsigned char id_ethaddr[6]; /* Hardware ethernet address */
|
||||
long id_date; /* Date of manufacture */
|
||||
unsigned int id_sernum:24; /* Unique serial number */
|
||||
unsigned char id_cksum; /* Checksum - xor of the data bytes */
|
||||
unsigned char reserved[16];
|
||||
struct idprom {
|
||||
u8 id_format; /* Format identifier (always 0x01) */
|
||||
u8 id_machtype; /* Machine type */
|
||||
u8 id_ethaddr[6]; /* Hardware ethernet address */
|
||||
s32 id_date; /* Date of manufacture */
|
||||
u32 id_sernum:24; /* Unique serial number */
|
||||
u8 id_cksum; /* Checksum - xor of the data bytes */
|
||||
u8 reserved[16];
|
||||
};
|
||||
|
||||
extern struct idprom *idprom;
|
||||
extern void idprom_init(void);
|
||||
|
||||
#define IDPROM_SIZE (sizeof(struct idprom))
|
||||
|
||||
#endif /* !(_SPARC_IDPROM_H) */
|
||||
|
||||
@@ -165,6 +165,7 @@ enum prom_input_device {
|
||||
PROMDEV_ITTYA, /* input from ttya */
|
||||
PROMDEV_ITTYB, /* input from ttyb */
|
||||
PROMDEV_IRSC, /* input from rsc */
|
||||
PROMDEV_IVCONS, /* input from virtual-console */
|
||||
PROMDEV_I_UNK,
|
||||
};
|
||||
|
||||
@@ -177,6 +178,7 @@ enum prom_output_device {
|
||||
PROMDEV_OTTYA, /* to ttya */
|
||||
PROMDEV_OTTYB, /* to ttyb */
|
||||
PROMDEV_ORSC, /* to rsc */
|
||||
PROMDEV_OVCONS, /* to virtual-console */
|
||||
PROMDEV_O_UNK,
|
||||
};
|
||||
|
||||
|
||||
@@ -120,17 +120,6 @@ case 8: __put_user_asm(x,d,addr,__pu_ret); break; \
|
||||
default: __pu_ret = __put_user_bad(); break; \
|
||||
} } else { __pu_ret = -EFAULT; } __pu_ret; })
|
||||
|
||||
#define __put_user_check_ret(x,addr,size,retval) ({ \
|
||||
register int __foo __asm__ ("l1"); \
|
||||
if (__access_ok(addr,size)) { \
|
||||
switch (size) { \
|
||||
case 1: __put_user_asm_ret(x,b,addr,retval,__foo); break; \
|
||||
case 2: __put_user_asm_ret(x,h,addr,retval,__foo); break; \
|
||||
case 4: __put_user_asm_ret(x,,addr,retval,__foo); break; \
|
||||
case 8: __put_user_asm_ret(x,d,addr,retval,__foo); break; \
|
||||
default: if (__put_user_bad()) return retval; break; \
|
||||
} } else return retval; })
|
||||
|
||||
#define __put_user_nocheck(x,addr,size) ({ \
|
||||
register int __pu_ret; \
|
||||
switch (size) { \
|
||||
@@ -141,16 +130,6 @@ case 8: __put_user_asm(x,d,addr,__pu_ret); break; \
|
||||
default: __pu_ret = __put_user_bad(); break; \
|
||||
} __pu_ret; })
|
||||
|
||||
#define __put_user_nocheck_ret(x,addr,size,retval) ({ \
|
||||
register int __foo __asm__ ("l1"); \
|
||||
switch (size) { \
|
||||
case 1: __put_user_asm_ret(x,b,addr,retval,__foo); break; \
|
||||
case 2: __put_user_asm_ret(x,h,addr,retval,__foo); break; \
|
||||
case 4: __put_user_asm_ret(x,,addr,retval,__foo); break; \
|
||||
case 8: __put_user_asm_ret(x,d,addr,retval,__foo); break; \
|
||||
default: if (__put_user_bad()) return retval; break; \
|
||||
} })
|
||||
|
||||
#define __put_user_asm(x,size,addr,ret) \
|
||||
__asm__ __volatile__( \
|
||||
"/* Put user asm, inline. */\n" \
|
||||
@@ -170,32 +149,6 @@ __asm__ __volatile__( \
|
||||
: "=&r" (ret) : "r" (x), "m" (*__m(addr)), \
|
||||
"i" (-EFAULT))
|
||||
|
||||
#define __put_user_asm_ret(x,size,addr,ret,foo) \
|
||||
if (__builtin_constant_p(ret) && ret == -EFAULT) \
|
||||
__asm__ __volatile__( \
|
||||
"/* Put user asm ret, inline. */\n" \
|
||||
"1:\t" "st"#size " %1, %2\n\n\t" \
|
||||
".section __ex_table,#alloc\n\t" \
|
||||
".align 4\n\t" \
|
||||
".word 1b, __ret_efault\n\n\t" \
|
||||
".previous\n\n\t" \
|
||||
: "=r" (foo) : "r" (x), "m" (*__m(addr))); \
|
||||
else \
|
||||
__asm__ __volatile( \
|
||||
"/* Put user asm ret, inline. */\n" \
|
||||
"1:\t" "st"#size " %1, %2\n\n\t" \
|
||||
".section .fixup,#alloc,#execinstr\n\t" \
|
||||
".align 4\n" \
|
||||
"3:\n\t" \
|
||||
"ret\n\t" \
|
||||
" restore %%g0, %3, %%o0\n\t" \
|
||||
".previous\n\n\t" \
|
||||
".section __ex_table,#alloc\n\t" \
|
||||
".align 4\n\t" \
|
||||
".word 1b, 3b\n\n\t" \
|
||||
".previous\n\n\t" \
|
||||
: "=r" (foo) : "r" (x), "m" (*__m(addr)), "i" (ret))
|
||||
|
||||
extern int __put_user_bad(void);
|
||||
|
||||
#define __get_user_check(x,addr,size,type) ({ \
|
||||
|
||||
@@ -95,7 +95,11 @@ struct relocation_info /* used when header.a_machtype == M_SPARC */
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
#define STACK_TOP (test_thread_flag(TIF_32BIT) ? 0xf0000000 : 0x80000000000L)
|
||||
#define STACK_TOP32 ((1UL << 32UL) - PAGE_SIZE)
|
||||
#define STACK_TOP64 (0x0000080000000000UL - (1UL << 32UL))
|
||||
|
||||
#define STACK_TOP (test_thread_flag(TIF_32BIT) ? \
|
||||
STACK_TOP32 : STACK_TOP64)
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -25,14 +25,27 @@
|
||||
|
||||
/* SpitFire and later extended ASIs. The "(III)" marker designates
|
||||
* UltraSparc-III and later specific ASIs. The "(CMT)" marker designates
|
||||
* Chip Multi Threading specific ASIs.
|
||||
* Chip Multi Threading specific ASIs. "(NG)" designates Niagara specific
|
||||
* ASIs, "(4V)" designates SUN4V specific ASIs.
|
||||
*/
|
||||
#define ASI_PHYS_USE_EC 0x14 /* PADDR, E-cachable */
|
||||
#define ASI_PHYS_BYPASS_EC_E 0x15 /* PADDR, E-bit */
|
||||
#define ASI_BLK_AIUP_4V 0x16 /* (4V) Prim, user, block ld/st */
|
||||
#define ASI_BLK_AIUS_4V 0x17 /* (4V) Sec, user, block ld/st */
|
||||
#define ASI_PHYS_USE_EC_L 0x1c /* PADDR, E-cachable, little endian*/
|
||||
#define ASI_PHYS_BYPASS_EC_E_L 0x1d /* PADDR, E-bit, little endian */
|
||||
#define ASI_BLK_AIUP_L_4V 0x1e /* (4V) Prim, user, block, l-endian*/
|
||||
#define ASI_BLK_AIUS_L_4V 0x1f /* (4V) Sec, user, block, l-endian */
|
||||
#define ASI_SCRATCHPAD 0x20 /* (4V) Scratch Pad Registers */
|
||||
#define ASI_MMU 0x21 /* (4V) MMU Context Registers */
|
||||
#define ASI_BLK_INIT_QUAD_LDD_AIUS 0x23 /* (NG) init-store, twin load,
|
||||
* secondary, user
|
||||
*/
|
||||
#define ASI_NUCLEUS_QUAD_LDD 0x24 /* Cachable, qword load */
|
||||
#define ASI_QUEUE 0x25 /* (4V) Interrupt Queue Registers */
|
||||
#define ASI_QUAD_LDD_PHYS_4V 0x26 /* (4V) Physical, qword load */
|
||||
#define ASI_NUCLEUS_QUAD_LDD_L 0x2c /* Cachable, qword load, l-endian */
|
||||
#define ASI_QUAD_LDD_PHYS_L_4V 0x2e /* (4V) Phys, qword load, l-endian */
|
||||
#define ASI_PCACHE_DATA_STATUS 0x30 /* (III) PCache data stat RAM diag */
|
||||
#define ASI_PCACHE_DATA 0x31 /* (III) PCache data RAM diag */
|
||||
#define ASI_PCACHE_TAG 0x32 /* (III) PCache tag RAM diag */
|
||||
@@ -137,6 +150,9 @@
|
||||
#define ASI_FL16_SL 0xdb /* Secondary, 1 16-bit, fpu ld/st,L*/
|
||||
#define ASI_BLK_COMMIT_P 0xe0 /* Primary, blk store commit */
|
||||
#define ASI_BLK_COMMIT_S 0xe1 /* Secondary, blk store commit */
|
||||
#define ASI_BLK_INIT_QUAD_LDD_P 0xe2 /* (NG) init-store, twin load,
|
||||
* primary, implicit
|
||||
*/
|
||||
#define ASI_BLK_P 0xf0 /* Primary, blk ld/st */
|
||||
#define ASI_BLK_S 0xf1 /* Secondary, blk ld/st */
|
||||
#define ASI_BLK_PL 0xf8 /* Primary, blk ld/st, little */
|
||||
|
||||
+193
-10
@@ -1,41 +1,224 @@
|
||||
/* cpudata.h: Per-cpu parameters.
|
||||
*
|
||||
* Copyright (C) 2003, 2005 David S. Miller (davem@redhat.com)
|
||||
* Copyright (C) 2003, 2005, 2006 David S. Miller (davem@davemloft.net)
|
||||
*/
|
||||
|
||||
#ifndef _SPARC64_CPUDATA_H
|
||||
#define _SPARC64_CPUDATA_H
|
||||
|
||||
#include <asm/hypervisor.h>
|
||||
#include <asm/asi.h>
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
#include <linux/percpu.h>
|
||||
#include <linux/threads.h>
|
||||
|
||||
typedef struct {
|
||||
/* Dcache line 1 */
|
||||
unsigned int __softirq_pending; /* must be 1st, see rtrap.S */
|
||||
unsigned int multiplier;
|
||||
unsigned int counter;
|
||||
unsigned int idle_volume;
|
||||
unsigned int __pad1;
|
||||
unsigned long clock_tick; /* %tick's per second */
|
||||
unsigned long udelay_val;
|
||||
|
||||
/* Dcache line 2 */
|
||||
unsigned int pgcache_size;
|
||||
unsigned int __pad1;
|
||||
unsigned long *pte_cache[2];
|
||||
unsigned long *pgd_cache;
|
||||
|
||||
/* Dcache line 3, rarely used */
|
||||
/* Dcache line 2, rarely used */
|
||||
unsigned int dcache_size;
|
||||
unsigned int dcache_line_size;
|
||||
unsigned int icache_size;
|
||||
unsigned int icache_line_size;
|
||||
unsigned int ecache_size;
|
||||
unsigned int ecache_line_size;
|
||||
unsigned int __pad2;
|
||||
unsigned int __pad3;
|
||||
unsigned int __pad4;
|
||||
} cpuinfo_sparc;
|
||||
|
||||
DECLARE_PER_CPU(cpuinfo_sparc, __cpu_data);
|
||||
#define cpu_data(__cpu) per_cpu(__cpu_data, (__cpu))
|
||||
#define local_cpu_data() __get_cpu_var(__cpu_data)
|
||||
|
||||
/* Trap handling code needs to get at a few critical values upon
|
||||
* trap entry and to process TSB misses. These cannot be in the
|
||||
* per_cpu() area as we really need to lock them into the TLB and
|
||||
* thus make them part of the main kernel image. As a result we
|
||||
* try to make this as small as possible.
|
||||
*
|
||||
* This is padded out and aligned to 64-bytes to avoid false sharing
|
||||
* on SMP.
|
||||
*/
|
||||
|
||||
/* If you modify the size of this structure, please update
|
||||
* TRAP_BLOCK_SZ_SHIFT below.
|
||||
*/
|
||||
struct thread_info;
|
||||
struct trap_per_cpu {
|
||||
/* D-cache line 1: Basic thread information, cpu and device mondo queues */
|
||||
struct thread_info *thread;
|
||||
unsigned long pgd_paddr;
|
||||
unsigned long cpu_mondo_pa;
|
||||
unsigned long dev_mondo_pa;
|
||||
|
||||
/* D-cache line 2: Error Mondo Queue and kernel buffer pointers */
|
||||
unsigned long resum_mondo_pa;
|
||||
unsigned long resum_kernel_buf_pa;
|
||||
unsigned long nonresum_mondo_pa;
|
||||
unsigned long nonresum_kernel_buf_pa;
|
||||
|
||||
/* Dcache lines 3, 4, 5, and 6: Hypervisor Fault Status */
|
||||
struct hv_fault_status fault_info;
|
||||
|
||||
/* Dcache line 7: Physical addresses of CPU send mondo block and CPU list. */
|
||||
unsigned long cpu_mondo_block_pa;
|
||||
unsigned long cpu_list_pa;
|
||||
unsigned long __pad1[2];
|
||||
|
||||
/* Dcache line 8: Unused, needed to keep trap_block a power-of-2 in size. */
|
||||
unsigned long __pad2[4];
|
||||
} __attribute__((aligned(64)));
|
||||
extern struct trap_per_cpu trap_block[NR_CPUS];
|
||||
extern void init_cur_cpu_trap(struct thread_info *);
|
||||
extern void setup_tba(void);
|
||||
|
||||
struct cpuid_patch_entry {
|
||||
unsigned int addr;
|
||||
unsigned int cheetah_safari[4];
|
||||
unsigned int cheetah_jbus[4];
|
||||
unsigned int starfire[4];
|
||||
unsigned int sun4v[4];
|
||||
};
|
||||
extern struct cpuid_patch_entry __cpuid_patch, __cpuid_patch_end;
|
||||
|
||||
struct sun4v_1insn_patch_entry {
|
||||
unsigned int addr;
|
||||
unsigned int insn;
|
||||
};
|
||||
extern struct sun4v_1insn_patch_entry __sun4v_1insn_patch,
|
||||
__sun4v_1insn_patch_end;
|
||||
|
||||
struct sun4v_2insn_patch_entry {
|
||||
unsigned int addr;
|
||||
unsigned int insns[2];
|
||||
};
|
||||
extern struct sun4v_2insn_patch_entry __sun4v_2insn_patch,
|
||||
__sun4v_2insn_patch_end;
|
||||
|
||||
#endif /* !(__ASSEMBLY__) */
|
||||
|
||||
#define TRAP_PER_CPU_THREAD 0x00
|
||||
#define TRAP_PER_CPU_PGD_PADDR 0x08
|
||||
#define TRAP_PER_CPU_CPU_MONDO_PA 0x10
|
||||
#define TRAP_PER_CPU_DEV_MONDO_PA 0x18
|
||||
#define TRAP_PER_CPU_RESUM_MONDO_PA 0x20
|
||||
#define TRAP_PER_CPU_RESUM_KBUF_PA 0x28
|
||||
#define TRAP_PER_CPU_NONRESUM_MONDO_PA 0x30
|
||||
#define TRAP_PER_CPU_NONRESUM_KBUF_PA 0x38
|
||||
#define TRAP_PER_CPU_FAULT_INFO 0x40
|
||||
#define TRAP_PER_CPU_CPU_MONDO_BLOCK_PA 0xc0
|
||||
#define TRAP_PER_CPU_CPU_LIST_PA 0xc8
|
||||
|
||||
#define TRAP_BLOCK_SZ_SHIFT 8
|
||||
|
||||
#include <asm/scratchpad.h>
|
||||
|
||||
#define __GET_CPUID(REG) \
|
||||
/* Spitfire implementation (default). */ \
|
||||
661: ldxa [%g0] ASI_UPA_CONFIG, REG; \
|
||||
srlx REG, 17, REG; \
|
||||
and REG, 0x1f, REG; \
|
||||
nop; \
|
||||
.section .cpuid_patch, "ax"; \
|
||||
/* Instruction location. */ \
|
||||
.word 661b; \
|
||||
/* Cheetah Safari implementation. */ \
|
||||
ldxa [%g0] ASI_SAFARI_CONFIG, REG; \
|
||||
srlx REG, 17, REG; \
|
||||
and REG, 0x3ff, REG; \
|
||||
nop; \
|
||||
/* Cheetah JBUS implementation. */ \
|
||||
ldxa [%g0] ASI_JBUS_CONFIG, REG; \
|
||||
srlx REG, 17, REG; \
|
||||
and REG, 0x1f, REG; \
|
||||
nop; \
|
||||
/* Starfire implementation. */ \
|
||||
sethi %hi(0x1fff40000d0 >> 9), REG; \
|
||||
sllx REG, 9, REG; \
|
||||
or REG, 0xd0, REG; \
|
||||
lduwa [REG] ASI_PHYS_BYPASS_EC_E, REG;\
|
||||
/* sun4v implementation. */ \
|
||||
mov SCRATCHPAD_CPUID, REG; \
|
||||
ldxa [REG] ASI_SCRATCHPAD, REG; \
|
||||
nop; \
|
||||
nop; \
|
||||
.previous;
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
|
||||
#define TRAP_LOAD_TRAP_BLOCK(DEST, TMP) \
|
||||
__GET_CPUID(TMP) \
|
||||
sethi %hi(trap_block), DEST; \
|
||||
sllx TMP, TRAP_BLOCK_SZ_SHIFT, TMP; \
|
||||
or DEST, %lo(trap_block), DEST; \
|
||||
add DEST, TMP, DEST; \
|
||||
|
||||
/* Clobbers TMP, current address space PGD phys address into DEST. */
|
||||
#define TRAP_LOAD_PGD_PHYS(DEST, TMP) \
|
||||
TRAP_LOAD_TRAP_BLOCK(DEST, TMP) \
|
||||
ldx [DEST + TRAP_PER_CPU_PGD_PADDR], DEST;
|
||||
|
||||
/* Clobbers TMP, loads local processor's IRQ work area into DEST. */
|
||||
#define TRAP_LOAD_IRQ_WORK(DEST, TMP) \
|
||||
__GET_CPUID(TMP) \
|
||||
sethi %hi(__irq_work), DEST; \
|
||||
sllx TMP, 6, TMP; \
|
||||
or DEST, %lo(__irq_work), DEST; \
|
||||
add DEST, TMP, DEST;
|
||||
|
||||
/* Clobbers TMP, loads DEST with current thread info pointer. */
|
||||
#define TRAP_LOAD_THREAD_REG(DEST, TMP) \
|
||||
TRAP_LOAD_TRAP_BLOCK(DEST, TMP) \
|
||||
ldx [DEST + TRAP_PER_CPU_THREAD], DEST;
|
||||
|
||||
/* Given the current thread info pointer in THR, load the per-cpu
|
||||
* area base of the current processor into DEST. REG1, REG2, and REG3 are
|
||||
* clobbered.
|
||||
*
|
||||
* You absolutely cannot use DEST as a temporary in this code. The
|
||||
* reason is that traps can happen during execution, and return from
|
||||
* trap will load the fully resolved DEST per-cpu base. This can corrupt
|
||||
* the calculations done by the macro mid-stream.
|
||||
*/
|
||||
#define LOAD_PER_CPU_BASE(DEST, THR, REG1, REG2, REG3) \
|
||||
ldub [THR + TI_CPU], REG1; \
|
||||
sethi %hi(__per_cpu_shift), REG3; \
|
||||
sethi %hi(__per_cpu_base), REG2; \
|
||||
ldx [REG3 + %lo(__per_cpu_shift)], REG3; \
|
||||
ldx [REG2 + %lo(__per_cpu_base)], REG2; \
|
||||
sllx REG1, REG3, REG3; \
|
||||
add REG3, REG2, DEST;
|
||||
|
||||
#else
|
||||
|
||||
#define TRAP_LOAD_TRAP_BLOCK(DEST, TMP) \
|
||||
sethi %hi(trap_block), DEST; \
|
||||
or DEST, %lo(trap_block), DEST; \
|
||||
|
||||
/* Uniprocessor versions, we know the cpuid is zero. */
|
||||
#define TRAP_LOAD_PGD_PHYS(DEST, TMP) \
|
||||
TRAP_LOAD_TRAP_BLOCK(DEST, TMP) \
|
||||
ldx [DEST + TRAP_PER_CPU_PGD_PADDR], DEST;
|
||||
|
||||
#define TRAP_LOAD_IRQ_WORK(DEST, TMP) \
|
||||
sethi %hi(__irq_work), DEST; \
|
||||
or DEST, %lo(__irq_work), DEST;
|
||||
|
||||
#define TRAP_LOAD_THREAD_REG(DEST, TMP) \
|
||||
TRAP_LOAD_TRAP_BLOCK(DEST, TMP) \
|
||||
ldx [DEST + TRAP_PER_CPU_THREAD], DEST;
|
||||
|
||||
/* No per-cpu areas on uniprocessor, so no need to load DEST. */
|
||||
#define LOAD_PER_CPU_BASE(DEST, THR, REG1, REG2, REG3)
|
||||
|
||||
#endif /* !(CONFIG_SMP) */
|
||||
|
||||
#endif /* _SPARC64_CPUDATA_H */
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#ifdef __KERNEL__
|
||||
#include <asm/processor.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/spitfire.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -68,6 +69,7 @@
|
||||
#define HWCAP_SPARC_MULDIV 8
|
||||
#define HWCAP_SPARC_V9 16
|
||||
#define HWCAP_SPARC_ULTRA3 32
|
||||
#define HWCAP_SPARC_BLKINIT 64
|
||||
|
||||
/*
|
||||
* These are used to set parameters in the core dumps.
|
||||
@@ -145,11 +147,21 @@ typedef struct {
|
||||
instruction set this cpu supports. */
|
||||
|
||||
/* On Ultra, we support all of the v8 capabilities. */
|
||||
#define ELF_HWCAP ((HWCAP_SPARC_FLUSH | HWCAP_SPARC_STBAR | \
|
||||
HWCAP_SPARC_SWAP | HWCAP_SPARC_MULDIV | \
|
||||
HWCAP_SPARC_V9) | \
|
||||
((tlb_type == cheetah || tlb_type == cheetah_plus) ? \
|
||||
HWCAP_SPARC_ULTRA3 : 0))
|
||||
static inline unsigned int sparc64_elf_hwcap(void)
|
||||
{
|
||||
unsigned int cap = (HWCAP_SPARC_FLUSH | HWCAP_SPARC_STBAR |
|
||||
HWCAP_SPARC_SWAP | HWCAP_SPARC_MULDIV |
|
||||
HWCAP_SPARC_V9);
|
||||
|
||||
if (tlb_type == cheetah || tlb_type == cheetah_plus)
|
||||
cap |= HWCAP_SPARC_ULTRA3;
|
||||
else if (tlb_type == hypervisor)
|
||||
cap |= HWCAP_SPARC_BLKINIT;
|
||||
|
||||
return cap;
|
||||
}
|
||||
|
||||
#define ELF_HWCAP sparc64_elf_hwcap();
|
||||
|
||||
/* This yields a string that ld.so will use to load implementation
|
||||
specific libraries for optimization. This is more specific in
|
||||
|
||||
@@ -4,12 +4,21 @@
|
||||
|
||||
#include <asm/pstate.h>
|
||||
|
||||
/* wrpr %g0, val, %gl */
|
||||
#define SET_GL(val) \
|
||||
.word 0xa1902000 | val
|
||||
|
||||
/* rdpr %gl, %gN */
|
||||
#define GET_GL_GLOBAL(N) \
|
||||
.word 0x81540000 | (N << 25)
|
||||
|
||||
#define KERNBASE 0x400000
|
||||
|
||||
#define PTREGS_OFF (STACK_BIAS + STACKFRAME_SZ)
|
||||
|
||||
#define __CHEETAH_ID 0x003e0014
|
||||
#define __JALAPENO_ID 0x003e0016
|
||||
#define __SERRANO_ID 0x003e0022
|
||||
|
||||
#define CHEETAH_MANUF 0x003e
|
||||
#define CHEETAH_IMPL 0x0014 /* Ultra-III */
|
||||
@@ -19,6 +28,12 @@
|
||||
#define PANTHER_IMPL 0x0019 /* Ultra-IV+ */
|
||||
#define SERRANO_IMPL 0x0022 /* Ultra-IIIi+ */
|
||||
|
||||
#define BRANCH_IF_SUN4V(tmp1,label) \
|
||||
sethi %hi(is_sun4v), %tmp1; \
|
||||
lduw [%tmp1 + %lo(is_sun4v)], %tmp1; \
|
||||
brnz,pn %tmp1, label; \
|
||||
nop
|
||||
|
||||
#define BRANCH_IF_CHEETAH_BASE(tmp1,tmp2,label) \
|
||||
rdpr %ver, %tmp1; \
|
||||
sethi %hi(__CHEETAH_ID), %tmp2; \
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -9,15 +9,7 @@
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
/* Offset into the EEPROM where the id PROM is located on the 4c */
|
||||
#define IDPROM_OFFSET 0x7d8
|
||||
|
||||
/* On sun4m; physical. */
|
||||
/* MicroSPARC(-II) does not decode 31rd bit, but it works. */
|
||||
#define IDPROM_OFFSET_M 0xfd8
|
||||
|
||||
struct idprom
|
||||
{
|
||||
struct idprom {
|
||||
u8 id_format; /* Format identifier (always 0x01) */
|
||||
u8 id_machtype; /* Machine type */
|
||||
u8 id_ethaddr[6]; /* Hardware ethernet address */
|
||||
@@ -30,6 +22,4 @@ struct idprom
|
||||
extern struct idprom *idprom;
|
||||
extern void idprom_init(void);
|
||||
|
||||
#define IDPROM_SIZE (sizeof(struct idprom))
|
||||
|
||||
#endif /* !(_SPARC_IDPROM_H) */
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
#ifndef _SPARC64_INTR_QUEUE_H
|
||||
#define _SPARC64_INTR_QUEUE_H
|
||||
|
||||
/* Sun4v interrupt queue registers, accessed via ASI_QUEUE. */
|
||||
|
||||
#define INTRQ_CPU_MONDO_HEAD 0x3c0 /* CPU mondo head */
|
||||
#define INTRQ_CPU_MONDO_TAIL 0x3c8 /* CPU mondo tail */
|
||||
#define INTRQ_DEVICE_MONDO_HEAD 0x3d0 /* Device mondo head */
|
||||
#define INTRQ_DEVICE_MONDO_TAIL 0x3d8 /* Device mondo tail */
|
||||
#define INTRQ_RESUM_MONDO_HEAD 0x3e0 /* Resumable error mondo head */
|
||||
#define INTRQ_RESUM_MONDO_TAIL 0x3e8 /* Resumable error mondo tail */
|
||||
#define INTRQ_NONRESUM_MONDO_HEAD 0x3f0 /* Non-resumable error mondo head */
|
||||
#define INTRQ_NONRESUM_MONDO_TAIL 0x3f8 /* Non-resumable error mondo head */
|
||||
|
||||
#endif /* !(_SPARC64_INTR_QUEUE_H) */
|
||||
@@ -72,8 +72,11 @@ struct ino_bucket {
|
||||
#define IMAP_VALID 0x80000000 /* IRQ Enabled */
|
||||
#define IMAP_TID_UPA 0x7c000000 /* UPA TargetID */
|
||||
#define IMAP_TID_JBUS 0x7c000000 /* JBUS TargetID */
|
||||
#define IMAP_TID_SHIFT 26
|
||||
#define IMAP_AID_SAFARI 0x7c000000 /* Safari AgentID */
|
||||
#define IMAP_AID_SHIFT 26
|
||||
#define IMAP_NID_SAFARI 0x03e00000 /* Safari NodeID */
|
||||
#define IMAP_NID_SHIFT 21
|
||||
#define IMAP_IGN 0x000007c0 /* IRQ Group Number */
|
||||
#define IMAP_INO 0x0000003f /* IRQ Number */
|
||||
#define IMAP_INR 0x000007ff /* Full interrupt number*/
|
||||
@@ -111,6 +114,7 @@ extern void disable_irq(unsigned int);
|
||||
#define disable_irq_nosync disable_irq
|
||||
extern void enable_irq(unsigned int);
|
||||
extern unsigned int build_irq(int pil, int inofixup, unsigned long iclr, unsigned long imap);
|
||||
extern unsigned int sun4v_build_irq(u32 devhandle, unsigned int devino, int pil, unsigned char flags);
|
||||
extern unsigned int sbus_build_irq(void *sbus, unsigned int ino);
|
||||
|
||||
static __inline__ void set_softint(unsigned long bits)
|
||||
|
||||
+22
-14
@@ -4,20 +4,9 @@
|
||||
#include <linux/config.h>
|
||||
#include <asm/page.h>
|
||||
#include <asm/const.h>
|
||||
#include <asm/hypervisor.h>
|
||||
|
||||
/*
|
||||
* For the 8k pagesize kernel, use only 10 hw context bits to optimize some
|
||||
* shifts in the fast tlbmiss handlers, instead of all 13 bits (specifically
|
||||
* for vpte offset calculation). For other pagesizes, this optimization in
|
||||
* the tlbhandlers can not be done; but still, all 13 bits can not be used
|
||||
* because the tlb handlers use "andcc" instruction which sign extends 13
|
||||
* bit arguments.
|
||||
*/
|
||||
#if PAGE_SHIFT == 13
|
||||
#define CTX_NR_BITS 10
|
||||
#else
|
||||
#define CTX_NR_BITS 12
|
||||
#endif
|
||||
#define CTX_NR_BITS 13
|
||||
|
||||
#define TAG_CONTEXT_BITS ((_AC(1,UL) << CTX_NR_BITS) - _AC(1,UL))
|
||||
|
||||
@@ -90,8 +79,27 @@
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
#define TSB_ENTRY_ALIGNMENT 16
|
||||
|
||||
struct tsb {
|
||||
unsigned long tag;
|
||||
unsigned long pte;
|
||||
} __attribute__((aligned(TSB_ENTRY_ALIGNMENT)));
|
||||
|
||||
extern void __tsb_insert(unsigned long ent, unsigned long tag, unsigned long pte);
|
||||
extern void tsb_flush(unsigned long ent, unsigned long tag);
|
||||
extern void tsb_init(struct tsb *tsb, unsigned long size);
|
||||
|
||||
typedef struct {
|
||||
unsigned long sparc64_ctx_val;
|
||||
spinlock_t lock;
|
||||
unsigned long sparc64_ctx_val;
|
||||
struct tsb *tsb;
|
||||
unsigned long tsb_rss_limit;
|
||||
unsigned long tsb_nentries;
|
||||
unsigned long tsb_reg_val;
|
||||
unsigned long tsb_map_vaddr;
|
||||
unsigned long tsb_map_pte;
|
||||
struct hv_tsb_descr tsb_descr;
|
||||
} mm_context_t;
|
||||
|
||||
#endif /* !__ASSEMBLY__ */
|
||||
|
||||
@@ -19,96 +19,98 @@ extern unsigned long tlb_context_cache;
|
||||
extern unsigned long mmu_context_bmap[];
|
||||
|
||||
extern void get_new_mmu_context(struct mm_struct *mm);
|
||||
#ifdef CONFIG_SMP
|
||||
extern void smp_new_mmu_context_version(void);
|
||||
#else
|
||||
#define smp_new_mmu_context_version() do { } while (0)
|
||||
#endif
|
||||
|
||||
/* Initialize a new mmu context. This is invoked when a new
|
||||
* address space instance (unique or shared) is instantiated.
|
||||
* This just needs to set mm->context to an invalid context.
|
||||
*/
|
||||
#define init_new_context(__tsk, __mm) \
|
||||
(((__mm)->context.sparc64_ctx_val = 0UL), 0)
|
||||
extern int init_new_context(struct task_struct *tsk, struct mm_struct *mm);
|
||||
extern void destroy_context(struct mm_struct *mm);
|
||||
|
||||
/* Destroy a dead context. This occurs when mmput drops the
|
||||
* mm_users count to zero, the mmaps have been released, and
|
||||
* all the page tables have been flushed. Our job is to destroy
|
||||
* any remaining processor-specific state, and in the sparc64
|
||||
* case this just means freeing up the mmu context ID held by
|
||||
* this task if valid.
|
||||
*/
|
||||
#define destroy_context(__mm) \
|
||||
do { spin_lock(&ctx_alloc_lock); \
|
||||
if (CTX_VALID((__mm)->context)) { \
|
||||
unsigned long nr = CTX_NRBITS((__mm)->context); \
|
||||
mmu_context_bmap[nr>>6] &= ~(1UL << (nr & 63)); \
|
||||
} \
|
||||
spin_unlock(&ctx_alloc_lock); \
|
||||
} while(0)
|
||||
extern void __tsb_context_switch(unsigned long pgd_pa,
|
||||
unsigned long tsb_reg,
|
||||
unsigned long tsb_vaddr,
|
||||
unsigned long tsb_pte,
|
||||
unsigned long tsb_descr_pa);
|
||||
|
||||
/* Reload the two core values used by TLB miss handler
|
||||
* processing on sparc64. They are:
|
||||
* 1) The physical address of mm->pgd, when full page
|
||||
* table walks are necessary, this is where the
|
||||
* search begins.
|
||||
* 2) A "PGD cache". For 32-bit tasks only pgd[0] is
|
||||
* ever used since that maps the entire low 4GB
|
||||
* completely. To speed up TLB miss processing we
|
||||
* make this value available to the handlers. This
|
||||
* decreases the amount of memory traffic incurred.
|
||||
*/
|
||||
#define reload_tlbmiss_state(__tsk, __mm) \
|
||||
do { \
|
||||
register unsigned long paddr asm("o5"); \
|
||||
register unsigned long pgd_cache asm("o4"); \
|
||||
paddr = __pa((__mm)->pgd); \
|
||||
pgd_cache = 0UL; \
|
||||
if (task_thread_info(__tsk)->flags & _TIF_32BIT) \
|
||||
pgd_cache = get_pgd_cache((__mm)->pgd); \
|
||||
__asm__ __volatile__("wrpr %%g0, 0x494, %%pstate\n\t" \
|
||||
"mov %3, %%g4\n\t" \
|
||||
"mov %0, %%g7\n\t" \
|
||||
"stxa %1, [%%g4] %2\n\t" \
|
||||
"membar #Sync\n\t" \
|
||||
"wrpr %%g0, 0x096, %%pstate" \
|
||||
: /* no outputs */ \
|
||||
: "r" (paddr), "r" (pgd_cache),\
|
||||
"i" (ASI_DMMU), "i" (TSB_REG)); \
|
||||
} while(0)
|
||||
static inline void tsb_context_switch(struct mm_struct *mm)
|
||||
{
|
||||
__tsb_context_switch(__pa(mm->pgd), mm->context.tsb_reg_val,
|
||||
mm->context.tsb_map_vaddr,
|
||||
mm->context.tsb_map_pte,
|
||||
__pa(&mm->context.tsb_descr));
|
||||
}
|
||||
|
||||
extern void tsb_grow(struct mm_struct *mm, unsigned long mm_rss);
|
||||
#ifdef CONFIG_SMP
|
||||
extern void smp_tsb_sync(struct mm_struct *mm);
|
||||
#else
|
||||
#define smp_tsb_sync(__mm) do { } while (0)
|
||||
#endif
|
||||
|
||||
/* Set MMU context in the actual hardware. */
|
||||
#define load_secondary_context(__mm) \
|
||||
__asm__ __volatile__("stxa %0, [%1] %2\n\t" \
|
||||
"flush %%g6" \
|
||||
: /* No outputs */ \
|
||||
: "r" (CTX_HWBITS((__mm)->context)), \
|
||||
"r" (SECONDARY_CONTEXT), "i" (ASI_DMMU))
|
||||
__asm__ __volatile__( \
|
||||
"\n661: stxa %0, [%1] %2\n" \
|
||||
" .section .sun4v_1insn_patch, \"ax\"\n" \
|
||||
" .word 661b\n" \
|
||||
" stxa %0, [%1] %3\n" \
|
||||
" .previous\n" \
|
||||
" flush %%g6\n" \
|
||||
: /* No outputs */ \
|
||||
: "r" (CTX_HWBITS((__mm)->context)), \
|
||||
"r" (SECONDARY_CONTEXT), "i" (ASI_DMMU), "i" (ASI_MMU))
|
||||
|
||||
extern void __flush_tlb_mm(unsigned long, unsigned long);
|
||||
|
||||
/* Switch the current MM context. */
|
||||
/* Switch the current MM context. Interrupts are disabled. */
|
||||
static inline void switch_mm(struct mm_struct *old_mm, struct mm_struct *mm, struct task_struct *tsk)
|
||||
{
|
||||
unsigned long ctx_valid;
|
||||
unsigned long ctx_valid, flags;
|
||||
int cpu;
|
||||
|
||||
/* Note: page_table_lock is used here to serialize switch_mm
|
||||
* and activate_mm, and their calls to get_new_mmu_context.
|
||||
* This use of page_table_lock is unrelated to its other uses.
|
||||
*/
|
||||
spin_lock(&mm->page_table_lock);
|
||||
spin_lock_irqsave(&mm->context.lock, flags);
|
||||
ctx_valid = CTX_VALID(mm->context);
|
||||
if (!ctx_valid)
|
||||
get_new_mmu_context(mm);
|
||||
spin_unlock(&mm->page_table_lock);
|
||||
|
||||
if (!ctx_valid || (old_mm != mm)) {
|
||||
load_secondary_context(mm);
|
||||
reload_tlbmiss_state(tsk, mm);
|
||||
}
|
||||
/* We have to be extremely careful here or else we will miss
|
||||
* a TSB grow if we switch back and forth between a kernel
|
||||
* thread and an address space which has it's TSB size increased
|
||||
* on another processor.
|
||||
*
|
||||
* It is possible to play some games in order to optimize the
|
||||
* switch, but the safest thing to do is to unconditionally
|
||||
* perform the secondary context load and the TSB context switch.
|
||||
*
|
||||
* For reference the bad case is, for address space "A":
|
||||
*
|
||||
* CPU 0 CPU 1
|
||||
* run address space A
|
||||
* set cpu0's bits in cpu_vm_mask
|
||||
* switch to kernel thread, borrow
|
||||
* address space A via entry_lazy_tlb
|
||||
* run address space A
|
||||
* set cpu1's bit in cpu_vm_mask
|
||||
* flush_tlb_pending()
|
||||
* reset cpu_vm_mask to just cpu1
|
||||
* TSB grow
|
||||
* run address space A
|
||||
* context was valid, so skip
|
||||
* TSB context switch
|
||||
*
|
||||
* At that point cpu0 continues to use a stale TSB, the one from
|
||||
* before the TSB grow performed on cpu1. cpu1 did not cross-call
|
||||
* cpu0 to update it's TSB because at that point the cpu_vm_mask
|
||||
* only had cpu1 set in it.
|
||||
*/
|
||||
load_secondary_context(mm);
|
||||
tsb_context_switch(mm);
|
||||
|
||||
/* Even if (mm == old_mm) we _must_ check
|
||||
* the cpu_vm_mask. If we do not we could
|
||||
* corrupt the TLB state because of how
|
||||
* smp_flush_tlb_{page,range,mm} on sparc64
|
||||
* and lazy tlb switches work. -DaveM
|
||||
/* Any time a processor runs a context on an address space
|
||||
* for the first time, we must flush that context out of the
|
||||
* local TLB.
|
||||
*/
|
||||
cpu = smp_processor_id();
|
||||
if (!ctx_valid || !cpu_isset(cpu, mm->cpu_vm_mask)) {
|
||||
@@ -116,6 +118,7 @@ static inline void switch_mm(struct mm_struct *old_mm, struct mm_struct *mm, str
|
||||
__flush_tlb_mm(CTX_HWBITS(mm->context),
|
||||
SECONDARY_CONTEXT);
|
||||
}
|
||||
spin_unlock_irqrestore(&mm->context.lock, flags);
|
||||
}
|
||||
|
||||
#define deactivate_mm(tsk,mm) do { } while (0)
|
||||
@@ -123,23 +126,20 @@ static inline void switch_mm(struct mm_struct *old_mm, struct mm_struct *mm, str
|
||||
/* Activate a new MM instance for the current task. */
|
||||
static inline void activate_mm(struct mm_struct *active_mm, struct mm_struct *mm)
|
||||
{
|
||||
unsigned long flags;
|
||||
int cpu;
|
||||
|
||||
/* Note: page_table_lock is used here to serialize switch_mm
|
||||
* and activate_mm, and their calls to get_new_mmu_context.
|
||||
* This use of page_table_lock is unrelated to its other uses.
|
||||
*/
|
||||
spin_lock(&mm->page_table_lock);
|
||||
spin_lock_irqsave(&mm->context.lock, flags);
|
||||
if (!CTX_VALID(mm->context))
|
||||
get_new_mmu_context(mm);
|
||||
cpu = smp_processor_id();
|
||||
if (!cpu_isset(cpu, mm->cpu_vm_mask))
|
||||
cpu_set(cpu, mm->cpu_vm_mask);
|
||||
spin_unlock(&mm->page_table_lock);
|
||||
|
||||
load_secondary_context(mm);
|
||||
__flush_tlb_mm(CTX_HWBITS(mm->context), SECONDARY_CONTEXT);
|
||||
reload_tlbmiss_state(current, mm);
|
||||
tsb_context_switch(mm);
|
||||
spin_unlock_irqrestore(&mm->context.lock, flags);
|
||||
}
|
||||
|
||||
#endif /* !(__ASSEMBLY__) */
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
#ifndef _SPARC64_NUMNODES_H
|
||||
#define _SPARC64_NUMNODES_H
|
||||
|
||||
#define NODES_SHIFT 0
|
||||
|
||||
#endif /* !(_SPARC64_NUMNODES_H) */
|
||||
+19
-24
@@ -12,18 +12,8 @@
|
||||
#include <linux/config.h>
|
||||
#include <asm/openprom.h>
|
||||
|
||||
/* Enumeration to describe the prom major version we have detected. */
|
||||
enum prom_major_version {
|
||||
PROM_V0, /* Original sun4c V0 prom */
|
||||
PROM_V2, /* sun4c and early sun4m V2 prom */
|
||||
PROM_V3, /* sun4m and later, up to sun4d/sun4e machines V3 */
|
||||
PROM_P1275, /* IEEE compliant ISA based Sun PROM, only sun4u */
|
||||
PROM_AP1000, /* actually no prom at all */
|
||||
};
|
||||
|
||||
extern enum prom_major_version prom_vers;
|
||||
/* Revision, and firmware revision. */
|
||||
extern unsigned int prom_rev, prom_prev;
|
||||
/* OBP version string. */
|
||||
extern char prom_version[];
|
||||
|
||||
/* Root node of the prom device tree, this stays constant after
|
||||
* initialization is complete.
|
||||
@@ -39,6 +29,9 @@ extern int prom_stdin, prom_stdout;
|
||||
extern int prom_chosen_node;
|
||||
|
||||
/* Helper values and strings in arch/sparc64/kernel/head.S */
|
||||
extern const char prom_peer_name[];
|
||||
extern const char prom_compatible_name[];
|
||||
extern const char prom_root_compatible[];
|
||||
extern const char prom_finddev_name[];
|
||||
extern const char prom_chosen_path[];
|
||||
extern const char prom_getprop_name[];
|
||||
@@ -130,15 +123,6 @@ extern void prom_setcallback(callback_func_t func_ptr);
|
||||
*/
|
||||
extern unsigned char prom_get_idprom(char *idp_buffer, int idpbuf_size);
|
||||
|
||||
/* Get the prom major version. */
|
||||
extern int prom_version(void);
|
||||
|
||||
/* Get the prom plugin revision. */
|
||||
extern int prom_getrev(void);
|
||||
|
||||
/* Get the prom firmware revision. */
|
||||
extern int prom_getprev(void);
|
||||
|
||||
/* Character operations to/from the console.... */
|
||||
|
||||
/* Non-blocking get character from console. */
|
||||
@@ -164,6 +148,7 @@ enum prom_input_device {
|
||||
PROMDEV_ITTYA, /* input from ttya */
|
||||
PROMDEV_ITTYB, /* input from ttyb */
|
||||
PROMDEV_IRSC, /* input from rsc */
|
||||
PROMDEV_IVCONS, /* input from virtual-console */
|
||||
PROMDEV_I_UNK,
|
||||
};
|
||||
|
||||
@@ -176,6 +161,7 @@ enum prom_output_device {
|
||||
PROMDEV_OTTYA, /* to ttya */
|
||||
PROMDEV_OTTYB, /* to ttyb */
|
||||
PROMDEV_ORSC, /* to rsc */
|
||||
PROMDEV_OVCONS, /* to virtual-console */
|
||||
PROMDEV_O_UNK,
|
||||
};
|
||||
|
||||
@@ -183,10 +169,18 @@ extern enum prom_output_device prom_query_output_device(void);
|
||||
|
||||
/* Multiprocessor operations... */
|
||||
#ifdef CONFIG_SMP
|
||||
/* Start the CPU with the given device tree node, context table, and context
|
||||
* at the passed program counter.
|
||||
/* Start the CPU with the given device tree node at the passed program
|
||||
* counter with the given arg passed in via register %o0.
|
||||
*/
|
||||
extern void prom_startcpu(int cpunode, unsigned long pc, unsigned long o0);
|
||||
extern void prom_startcpu(int cpunode, unsigned long pc, unsigned long arg);
|
||||
|
||||
/* Start the CPU with the given cpu ID at the passed program
|
||||
* counter with the given arg passed in via register %o0.
|
||||
*/
|
||||
extern void prom_startcpu_cpuid(int cpuid, unsigned long pc, unsigned long arg);
|
||||
|
||||
/* Stop the CPU with the given cpu ID. */
|
||||
extern void prom_stopcpu_cpuid(int cpuid);
|
||||
|
||||
/* Stop the current CPU. */
|
||||
extern void prom_stopself(void);
|
||||
@@ -335,6 +329,7 @@ int cpu_find_by_mid(int mid, int *prom_node);
|
||||
|
||||
/* Client interface level routines. */
|
||||
extern void prom_set_trap_table(unsigned long tba);
|
||||
extern void prom_set_trap_table_sun4v(unsigned long tba, unsigned long mmfsa);
|
||||
|
||||
extern long p1275_cmd(const char *, long, ...);
|
||||
|
||||
|
||||
@@ -104,10 +104,12 @@ typedef unsigned long pgprot_t;
|
||||
#define HUGETLB_PAGE_ORDER (HPAGE_SHIFT - PAGE_SHIFT)
|
||||
#define ARCH_HAS_SETCLEAR_HUGE_PTE
|
||||
#define ARCH_HAS_HUGETLB_PREFAULT_HOOK
|
||||
#define HAVE_ARCH_HUGETLB_UNMAPPED_AREA
|
||||
#endif
|
||||
|
||||
#define TASK_UNMAPPED_BASE (test_thread_flag(TIF_32BIT) ? \
|
||||
(_AC(0x0000000070000000,UL)) : (PAGE_OFFSET))
|
||||
(_AC(0x0000000070000000,UL)) : \
|
||||
(_AC(0xfffff80000000000,UL) + (1UL << 32UL)))
|
||||
|
||||
#endif /* !(__ASSEMBLY__) */
|
||||
|
||||
@@ -124,17 +126,10 @@ typedef unsigned long pgprot_t;
|
||||
#define __pa(x) ((unsigned long)(x) - PAGE_OFFSET)
|
||||
#define __va(x) ((void *)((unsigned long) (x) + PAGE_OFFSET))
|
||||
|
||||
/* PFNs are real physical page numbers. However, mem_map only begins to record
|
||||
* per-page information starting at pfn_base. This is to handle systems where
|
||||
* the first physical page in the machine is at some huge physical address,
|
||||
* such as 4GB. This is common on a partitioned E10000, for example.
|
||||
*/
|
||||
extern struct page *pfn_to_page(unsigned long pfn);
|
||||
extern unsigned long page_to_pfn(struct page *);
|
||||
#define pfn_to_kaddr(pfn) __va((pfn) << PAGE_SHIFT)
|
||||
|
||||
#define virt_to_page(kaddr) pfn_to_page(__pa(kaddr)>>PAGE_SHIFT)
|
||||
|
||||
#define pfn_valid(pfn) (((pfn)-(pfn_base)) < max_mapnr)
|
||||
#define virt_addr_valid(kaddr) pfn_valid(__pa(kaddr) >> PAGE_SHIFT)
|
||||
|
||||
#define virt_to_phys __pa
|
||||
|
||||
@@ -139,6 +139,9 @@ struct pci_pbm_info {
|
||||
/* Opaque 32-bit system bus Port ID. */
|
||||
u32 portid;
|
||||
|
||||
/* Opaque 32-bit handle used for hypervisor calls. */
|
||||
u32 devhandle;
|
||||
|
||||
/* Chipset version information. */
|
||||
int chip_type;
|
||||
#define PBM_CHIP_TYPE_SABRE 1
|
||||
|
||||
+45
-11
@@ -41,10 +41,26 @@ static inline void pcibios_penalize_isa_irq(int irq, int active)
|
||||
|
||||
struct pci_dev;
|
||||
|
||||
struct pci_iommu_ops {
|
||||
void *(*alloc_consistent)(struct pci_dev *, size_t, dma_addr_t *);
|
||||
void (*free_consistent)(struct pci_dev *, size_t, void *, dma_addr_t);
|
||||
dma_addr_t (*map_single)(struct pci_dev *, void *, size_t, int);
|
||||
void (*unmap_single)(struct pci_dev *, dma_addr_t, size_t, int);
|
||||
int (*map_sg)(struct pci_dev *, struct scatterlist *, int, int);
|
||||
void (*unmap_sg)(struct pci_dev *, struct scatterlist *, int, int);
|
||||
void (*dma_sync_single_for_cpu)(struct pci_dev *, dma_addr_t, size_t, int);
|
||||
void (*dma_sync_sg_for_cpu)(struct pci_dev *, struct scatterlist *, int, int);
|
||||
};
|
||||
|
||||
extern struct pci_iommu_ops *pci_iommu_ops;
|
||||
|
||||
/* Allocate and map kernel buffer using consistent mode DMA for a device.
|
||||
* hwdev should be valid struct pci_dev pointer for PCI devices.
|
||||
*/
|
||||
extern void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size, dma_addr_t *dma_handle);
|
||||
static inline void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size, dma_addr_t *dma_handle)
|
||||
{
|
||||
return pci_iommu_ops->alloc_consistent(hwdev, size, dma_handle);
|
||||
}
|
||||
|
||||
/* Free and unmap a consistent DMA buffer.
|
||||
* cpu_addr is what was returned from pci_alloc_consistent,
|
||||
@@ -54,7 +70,10 @@ extern void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size, dma_addr_t
|
||||
* References to the memory and mappings associated with cpu_addr/dma_addr
|
||||
* past this call are illegal.
|
||||
*/
|
||||
extern void pci_free_consistent(struct pci_dev *hwdev, size_t size, void *vaddr, dma_addr_t dma_handle);
|
||||
static inline void pci_free_consistent(struct pci_dev *hwdev, size_t size, void *vaddr, dma_addr_t dma_handle)
|
||||
{
|
||||
return pci_iommu_ops->free_consistent(hwdev, size, vaddr, dma_handle);
|
||||
}
|
||||
|
||||
/* Map a single buffer of the indicated size for DMA in streaming mode.
|
||||
* The 32-bit bus address to use is returned.
|
||||
@@ -62,7 +81,10 @@ extern void pci_free_consistent(struct pci_dev *hwdev, size_t size, void *vaddr,
|
||||
* Once the device is given the dma address, the device owns this memory
|
||||
* until either pci_unmap_single or pci_dma_sync_single_for_cpu is performed.
|
||||
*/
|
||||
extern dma_addr_t pci_map_single(struct pci_dev *hwdev, void *ptr, size_t size, int direction);
|
||||
static inline dma_addr_t pci_map_single(struct pci_dev *hwdev, void *ptr, size_t size, int direction)
|
||||
{
|
||||
return pci_iommu_ops->map_single(hwdev, ptr, size, direction);
|
||||
}
|
||||
|
||||
/* Unmap a single streaming mode DMA translation. The dma_addr and size
|
||||
* must match what was provided for in a previous pci_map_single call. All
|
||||
@@ -71,7 +93,10 @@ extern dma_addr_t pci_map_single(struct pci_dev *hwdev, void *ptr, size_t size,
|
||||
* After this call, reads by the cpu to the buffer are guaranteed to see
|
||||
* whatever the device wrote there.
|
||||
*/
|
||||
extern void pci_unmap_single(struct pci_dev *hwdev, dma_addr_t dma_addr, size_t size, int direction);
|
||||
static inline void pci_unmap_single(struct pci_dev *hwdev, dma_addr_t dma_addr, size_t size, int direction)
|
||||
{
|
||||
pci_iommu_ops->unmap_single(hwdev, dma_addr, size, direction);
|
||||
}
|
||||
|
||||
/* No highmem on sparc64, plus we have an IOMMU, so mapping pages is easy. */
|
||||
#define pci_map_page(dev, page, off, size, dir) \
|
||||
@@ -107,15 +132,19 @@ extern void pci_unmap_single(struct pci_dev *hwdev, dma_addr_t dma_addr, size_t
|
||||
* Device ownership issues as mentioned above for pci_map_single are
|
||||
* the same here.
|
||||
*/
|
||||
extern int pci_map_sg(struct pci_dev *hwdev, struct scatterlist *sg,
|
||||
int nents, int direction);
|
||||
static inline int pci_map_sg(struct pci_dev *hwdev, struct scatterlist *sg, int nents, int direction)
|
||||
{
|
||||
return pci_iommu_ops->map_sg(hwdev, sg, nents, direction);
|
||||
}
|
||||
|
||||
/* Unmap a set of streaming mode DMA translations.
|
||||
* Again, cpu read rules concerning calls here are the same as for
|
||||
* pci_unmap_single() above.
|
||||
*/
|
||||
extern void pci_unmap_sg(struct pci_dev *hwdev, struct scatterlist *sg,
|
||||
int nhwents, int direction);
|
||||
static inline void pci_unmap_sg(struct pci_dev *hwdev, struct scatterlist *sg, int nhwents, int direction)
|
||||
{
|
||||
pci_iommu_ops->unmap_sg(hwdev, sg, nhwents, direction);
|
||||
}
|
||||
|
||||
/* Make physical memory consistent for a single
|
||||
* streaming mode DMA translation after a transfer.
|
||||
@@ -127,8 +156,10 @@ extern void pci_unmap_sg(struct pci_dev *hwdev, struct scatterlist *sg,
|
||||
* must first perform a pci_dma_sync_for_device, and then the
|
||||
* device again owns the buffer.
|
||||
*/
|
||||
extern void pci_dma_sync_single_for_cpu(struct pci_dev *hwdev, dma_addr_t dma_handle,
|
||||
size_t size, int direction);
|
||||
static inline void pci_dma_sync_single_for_cpu(struct pci_dev *hwdev, dma_addr_t dma_handle, size_t size, int direction)
|
||||
{
|
||||
pci_iommu_ops->dma_sync_single_for_cpu(hwdev, dma_handle, size, direction);
|
||||
}
|
||||
|
||||
static inline void
|
||||
pci_dma_sync_single_for_device(struct pci_dev *hwdev, dma_addr_t dma_handle,
|
||||
@@ -144,7 +175,10 @@ pci_dma_sync_single_for_device(struct pci_dev *hwdev, dma_addr_t dma_handle,
|
||||
* The same as pci_dma_sync_single_* but for a scatter-gather list,
|
||||
* same rules and usage.
|
||||
*/
|
||||
extern void pci_dma_sync_sg_for_cpu(struct pci_dev *hwdev, struct scatterlist *sg, int nelems, int direction);
|
||||
static inline void pci_dma_sync_sg_for_cpu(struct pci_dev *hwdev, struct scatterlist *sg, int nelems, int direction)
|
||||
{
|
||||
pci_iommu_ops->dma_sync_sg_for_cpu(hwdev, sg, nelems, direction);
|
||||
}
|
||||
|
||||
static inline void
|
||||
pci_dma_sync_sg_for_device(struct pci_dev *hwdev, struct scatterlist *sg,
|
||||
|
||||
+30
-142
@@ -6,6 +6,7 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <asm/spitfire.h>
|
||||
#include <asm/cpudata.h>
|
||||
@@ -13,172 +14,59 @@
|
||||
#include <asm/page.h>
|
||||
|
||||
/* Page table allocation/freeing. */
|
||||
#ifdef CONFIG_SMP
|
||||
/* Sliiiicck */
|
||||
#define pgt_quicklists local_cpu_data()
|
||||
#else
|
||||
extern struct pgtable_cache_struct {
|
||||
unsigned long *pgd_cache;
|
||||
unsigned long *pte_cache[2];
|
||||
unsigned int pgcache_size;
|
||||
} pgt_quicklists;
|
||||
#endif
|
||||
#define pgd_quicklist (pgt_quicklists.pgd_cache)
|
||||
#define pmd_quicklist ((unsigned long *)0)
|
||||
#define pte_quicklist (pgt_quicklists.pte_cache)
|
||||
#define pgtable_cache_size (pgt_quicklists.pgcache_size)
|
||||
extern kmem_cache_t *pgtable_cache;
|
||||
|
||||
static __inline__ void free_pgd_fast(pgd_t *pgd)
|
||||
static inline pgd_t *pgd_alloc(struct mm_struct *mm)
|
||||
{
|
||||
preempt_disable();
|
||||
*(unsigned long *)pgd = (unsigned long) pgd_quicklist;
|
||||
pgd_quicklist = (unsigned long *) pgd;
|
||||
pgtable_cache_size++;
|
||||
preempt_enable();
|
||||
return kmem_cache_alloc(pgtable_cache, GFP_KERNEL);
|
||||
}
|
||||
|
||||
static __inline__ pgd_t *get_pgd_fast(void)
|
||||
static inline void pgd_free(pgd_t *pgd)
|
||||
{
|
||||
unsigned long *ret;
|
||||
|
||||
preempt_disable();
|
||||
if((ret = pgd_quicklist) != NULL) {
|
||||
pgd_quicklist = (unsigned long *)(*ret);
|
||||
ret[0] = 0;
|
||||
pgtable_cache_size--;
|
||||
preempt_enable();
|
||||
} else {
|
||||
preempt_enable();
|
||||
ret = (unsigned long *) __get_free_page(GFP_KERNEL|__GFP_REPEAT);
|
||||
if(ret)
|
||||
memset(ret, 0, PAGE_SIZE);
|
||||
}
|
||||
return (pgd_t *)ret;
|
||||
kmem_cache_free(pgtable_cache, pgd);
|
||||
}
|
||||
|
||||
static __inline__ void free_pgd_slow(pgd_t *pgd)
|
||||
{
|
||||
free_page((unsigned long)pgd);
|
||||
}
|
||||
|
||||
#ifdef DCACHE_ALIASING_POSSIBLE
|
||||
#define VPTE_COLOR(address) (((address) >> (PAGE_SHIFT + 10)) & 1UL)
|
||||
#define DCACHE_COLOR(address) (((address) >> PAGE_SHIFT) & 1UL)
|
||||
#else
|
||||
#define VPTE_COLOR(address) 0
|
||||
#define DCACHE_COLOR(address) 0
|
||||
#endif
|
||||
|
||||
#define pud_populate(MM, PUD, PMD) pud_set(PUD, PMD)
|
||||
|
||||
static __inline__ pmd_t *pmd_alloc_one_fast(struct mm_struct *mm, unsigned long address)
|
||||
static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long addr)
|
||||
{
|
||||
unsigned long *ret;
|
||||
int color = 0;
|
||||
|
||||
preempt_disable();
|
||||
if (pte_quicklist[color] == NULL)
|
||||
color = 1;
|
||||
|
||||
if((ret = (unsigned long *)pte_quicklist[color]) != NULL) {
|
||||
pte_quicklist[color] = (unsigned long *)(*ret);
|
||||
ret[0] = 0;
|
||||
pgtable_cache_size--;
|
||||
}
|
||||
preempt_enable();
|
||||
|
||||
return (pmd_t *)ret;
|
||||
return kmem_cache_alloc(pgtable_cache,
|
||||
GFP_KERNEL|__GFP_REPEAT);
|
||||
}
|
||||
|
||||
static __inline__ pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long address)
|
||||
static inline void pmd_free(pmd_t *pmd)
|
||||
{
|
||||
pmd_t *pmd;
|
||||
|
||||
pmd = pmd_alloc_one_fast(mm, address);
|
||||
if (!pmd) {
|
||||
pmd = (pmd_t *)__get_free_page(GFP_KERNEL|__GFP_REPEAT);
|
||||
if (pmd)
|
||||
memset(pmd, 0, PAGE_SIZE);
|
||||
}
|
||||
return pmd;
|
||||
kmem_cache_free(pgtable_cache, pmd);
|
||||
}
|
||||
|
||||
static __inline__ void free_pmd_fast(pmd_t *pmd)
|
||||
static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm,
|
||||
unsigned long address)
|
||||
{
|
||||
unsigned long color = DCACHE_COLOR((unsigned long)pmd);
|
||||
|
||||
preempt_disable();
|
||||
*(unsigned long *)pmd = (unsigned long) pte_quicklist[color];
|
||||
pte_quicklist[color] = (unsigned long *) pmd;
|
||||
pgtable_cache_size++;
|
||||
preempt_enable();
|
||||
return kmem_cache_alloc(pgtable_cache,
|
||||
GFP_KERNEL|__GFP_REPEAT);
|
||||
}
|
||||
|
||||
static __inline__ void free_pmd_slow(pmd_t *pmd)
|
||||
static inline struct page *pte_alloc_one(struct mm_struct *mm,
|
||||
unsigned long address)
|
||||
{
|
||||
free_page((unsigned long)pmd);
|
||||
return virt_to_page(pte_alloc_one_kernel(mm, address));
|
||||
}
|
||||
|
||||
static inline void pte_free_kernel(pte_t *pte)
|
||||
{
|
||||
kmem_cache_free(pgtable_cache, pte);
|
||||
}
|
||||
|
||||
static inline void pte_free(struct page *ptepage)
|
||||
{
|
||||
pte_free_kernel(page_address(ptepage));
|
||||
}
|
||||
|
||||
|
||||
#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_kernel(struct mm_struct *mm, unsigned long address);
|
||||
|
||||
static inline struct page *
|
||||
pte_alloc_one(struct mm_struct *mm, unsigned long addr)
|
||||
{
|
||||
pte_t *pte = pte_alloc_one_kernel(mm, addr);
|
||||
|
||||
if (pte)
|
||||
return virt_to_page(pte);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static __inline__ pte_t *pte_alloc_one_fast(struct mm_struct *mm, unsigned long address)
|
||||
{
|
||||
unsigned long color = VPTE_COLOR(address);
|
||||
unsigned long *ret;
|
||||
|
||||
preempt_disable();
|
||||
if((ret = (unsigned long *)pte_quicklist[color]) != NULL) {
|
||||
pte_quicklist[color] = (unsigned long *)(*ret);
|
||||
ret[0] = 0;
|
||||
pgtable_cache_size--;
|
||||
}
|
||||
preempt_enable();
|
||||
return (pte_t *)ret;
|
||||
}
|
||||
|
||||
static __inline__ void free_pte_fast(pte_t *pte)
|
||||
{
|
||||
unsigned long color = DCACHE_COLOR((unsigned long)pte);
|
||||
|
||||
preempt_disable();
|
||||
*(unsigned long *)pte = (unsigned long) pte_quicklist[color];
|
||||
pte_quicklist[color] = (unsigned long *) pte;
|
||||
pgtable_cache_size++;
|
||||
preempt_enable();
|
||||
}
|
||||
|
||||
static __inline__ void free_pte_slow(pte_t *pte)
|
||||
{
|
||||
free_page((unsigned long)pte);
|
||||
}
|
||||
|
||||
static inline void pte_free_kernel(pte_t *pte)
|
||||
{
|
||||
free_pte_fast(pte);
|
||||
}
|
||||
|
||||
static inline void pte_free(struct page *ptepage)
|
||||
{
|
||||
free_pte_fast(page_address(ptepage));
|
||||
}
|
||||
|
||||
#define pmd_free(pmd) free_pmd_fast(pmd)
|
||||
#define pgd_free(pgd) free_pgd_fast(pgd)
|
||||
#define pgd_alloc(mm) get_pgd_fast()
|
||||
#define check_pgt_cache() do { } while (0)
|
||||
|
||||
#endif /* _SPARC64_PGALLOC_H */
|
||||
|
||||
+520
-192
@@ -25,7 +25,8 @@
|
||||
#include <asm/const.h>
|
||||
|
||||
/* The kernel image occupies 0x4000000 to 0x1000000 (4MB --> 32MB).
|
||||
* The page copy blockops can use 0x2000000 to 0x10000000.
|
||||
* The page copy blockops can use 0x2000000 to 0x4000000.
|
||||
* The TSB is mapped in the 0x4000000 to 0x6000000 range.
|
||||
* The PROM resides in an area spanning 0xf0000000 to 0x100000000.
|
||||
* The vmalloc area spans 0x100000000 to 0x200000000.
|
||||
* Since modules need to be in the lowest 32-bits of the address space,
|
||||
@@ -34,6 +35,7 @@
|
||||
* 0x400000000.
|
||||
*/
|
||||
#define TLBTEMP_BASE _AC(0x0000000002000000,UL)
|
||||
#define TSBMAP_BASE _AC(0x0000000004000000,UL)
|
||||
#define MODULES_VADDR _AC(0x0000000010000000,UL)
|
||||
#define MODULES_LEN _AC(0x00000000e0000000,UL)
|
||||
#define MODULES_END _AC(0x00000000f0000000,UL)
|
||||
@@ -88,132 +90,132 @@
|
||||
|
||||
#endif /* !(__ASSEMBLY__) */
|
||||
|
||||
/* Spitfire/Cheetah TTE bits. */
|
||||
#define _PAGE_VALID _AC(0x8000000000000000,UL) /* Valid TTE */
|
||||
#define _PAGE_R _AC(0x8000000000000000,UL) /* Keep ref bit up to date*/
|
||||
#define _PAGE_SZ4MB _AC(0x6000000000000000,UL) /* 4MB Page */
|
||||
#define _PAGE_SZ512K _AC(0x4000000000000000,UL) /* 512K Page */
|
||||
#define _PAGE_SZ64K _AC(0x2000000000000000,UL) /* 64K Page */
|
||||
#define _PAGE_SZ8K _AC(0x0000000000000000,UL) /* 8K Page */
|
||||
#define _PAGE_NFO _AC(0x1000000000000000,UL) /* No Fault Only */
|
||||
#define _PAGE_IE _AC(0x0800000000000000,UL) /* Invert Endianness */
|
||||
#define _PAGE_SOFT2 _AC(0x07FC000000000000,UL) /* Software bits, set 2 */
|
||||
#define _PAGE_RES1 _AC(0x0002000000000000,UL) /* Reserved */
|
||||
#define _PAGE_SZ32MB _AC(0x0001000000000000,UL) /* (Panther) 32MB page */
|
||||
#define _PAGE_SZ256MB _AC(0x2001000000000000,UL) /* (Panther) 256MB page */
|
||||
#define _PAGE_SN _AC(0x0000800000000000,UL) /* (Cheetah) Snoop */
|
||||
#define _PAGE_RES2 _AC(0x0000780000000000,UL) /* Reserved */
|
||||
#define _PAGE_PADDR_SF _AC(0x000001FFFFFFE000,UL) /* (Spitfire) paddr[40:13]*/
|
||||
#define _PAGE_PADDR _AC(0x000007FFFFFFE000,UL) /* (Cheetah) paddr[42:13] */
|
||||
#define _PAGE_SOFT _AC(0x0000000000001F80,UL) /* Software bits */
|
||||
#define _PAGE_L _AC(0x0000000000000040,UL) /* Locked TTE */
|
||||
#define _PAGE_CP _AC(0x0000000000000020,UL) /* Cacheable in P-Cache */
|
||||
#define _PAGE_CV _AC(0x0000000000000010,UL) /* Cacheable in V-Cache */
|
||||
#define _PAGE_E _AC(0x0000000000000008,UL) /* side-Effect */
|
||||
#define _PAGE_P _AC(0x0000000000000004,UL) /* Privileged Page */
|
||||
#define _PAGE_W _AC(0x0000000000000002,UL) /* Writable */
|
||||
#define _PAGE_G _AC(0x0000000000000001,UL) /* Global */
|
||||
/* PTE bits which are the same in SUN4U and SUN4V format. */
|
||||
#define _PAGE_VALID _AC(0x8000000000000000,UL) /* Valid TTE */
|
||||
#define _PAGE_R _AC(0x8000000000000000,UL) /* Keep ref bit uptodate*/
|
||||
|
||||
/* Here are the SpitFire software bits we use in the TTE's.
|
||||
*
|
||||
* WARNING: If you are going to try and start using some
|
||||
* of the soft2 bits, you will need to make
|
||||
* modifications to the swap entry implementation.
|
||||
* For example, one thing that could happen is that
|
||||
* swp_entry_to_pte() would BUG_ON() if you tried
|
||||
* to use one of the soft2 bits for _PAGE_FILE.
|
||||
*
|
||||
* Like other architectures, I have aliased _PAGE_FILE with
|
||||
* _PAGE_MODIFIED. This works because _PAGE_FILE is never
|
||||
* interpreted that way unless _PAGE_PRESENT is clear.
|
||||
*/
|
||||
#define _PAGE_EXEC _AC(0x0000000000001000,UL) /* Executable SW bit */
|
||||
#define _PAGE_MODIFIED _AC(0x0000000000000800,UL) /* Modified (dirty) */
|
||||
#define _PAGE_FILE _AC(0x0000000000000800,UL) /* Pagecache page */
|
||||
#define _PAGE_ACCESSED _AC(0x0000000000000400,UL) /* Accessed (ref'd) */
|
||||
#define _PAGE_READ _AC(0x0000000000000200,UL) /* Readable SW Bit */
|
||||
#define _PAGE_WRITE _AC(0x0000000000000100,UL) /* Writable SW Bit */
|
||||
#define _PAGE_PRESENT _AC(0x0000000000000080,UL) /* Present */
|
||||
/* SUN4U pte bits... */
|
||||
#define _PAGE_SZ4MB_4U _AC(0x6000000000000000,UL) /* 4MB Page */
|
||||
#define _PAGE_SZ512K_4U _AC(0x4000000000000000,UL) /* 512K Page */
|
||||
#define _PAGE_SZ64K_4U _AC(0x2000000000000000,UL) /* 64K Page */
|
||||
#define _PAGE_SZ8K_4U _AC(0x0000000000000000,UL) /* 8K Page */
|
||||
#define _PAGE_NFO_4U _AC(0x1000000000000000,UL) /* No Fault Only */
|
||||
#define _PAGE_IE_4U _AC(0x0800000000000000,UL) /* Invert Endianness */
|
||||
#define _PAGE_SOFT2_4U _AC(0x07FC000000000000,UL) /* Software bits, set 2 */
|
||||
#define _PAGE_RES1_4U _AC(0x0002000000000000,UL) /* Reserved */
|
||||
#define _PAGE_SZ32MB_4U _AC(0x0001000000000000,UL) /* (Panther) 32MB page */
|
||||
#define _PAGE_SZ256MB_4U _AC(0x2001000000000000,UL) /* (Panther) 256MB page */
|
||||
#define _PAGE_SN_4U _AC(0x0000800000000000,UL) /* (Cheetah) Snoop */
|
||||
#define _PAGE_RES2_4U _AC(0x0000780000000000,UL) /* Reserved */
|
||||
#define _PAGE_PADDR_4U _AC(0x000007FFFFFFE000,UL) /* (Cheetah) pa[42:13] */
|
||||
#define _PAGE_SOFT_4U _AC(0x0000000000001F80,UL) /* Software bits: */
|
||||
#define _PAGE_EXEC_4U _AC(0x0000000000001000,UL) /* Executable SW bit */
|
||||
#define _PAGE_MODIFIED_4U _AC(0x0000000000000800,UL) /* Modified (dirty) */
|
||||
#define _PAGE_FILE_4U _AC(0x0000000000000800,UL) /* Pagecache page */
|
||||
#define _PAGE_ACCESSED_4U _AC(0x0000000000000400,UL) /* Accessed (ref'd) */
|
||||
#define _PAGE_READ_4U _AC(0x0000000000000200,UL) /* Readable SW Bit */
|
||||
#define _PAGE_WRITE_4U _AC(0x0000000000000100,UL) /* Writable SW Bit */
|
||||
#define _PAGE_PRESENT_4U _AC(0x0000000000000080,UL) /* Present */
|
||||
#define _PAGE_L_4U _AC(0x0000000000000040,UL) /* Locked TTE */
|
||||
#define _PAGE_CP_4U _AC(0x0000000000000020,UL) /* Cacheable in P-Cache */
|
||||
#define _PAGE_CV_4U _AC(0x0000000000000010,UL) /* Cacheable in V-Cache */
|
||||
#define _PAGE_E_4U _AC(0x0000000000000008,UL) /* side-Effect */
|
||||
#define _PAGE_P_4U _AC(0x0000000000000004,UL) /* Privileged Page */
|
||||
#define _PAGE_W_4U _AC(0x0000000000000002,UL) /* Writable */
|
||||
|
||||
/* SUN4V pte bits... */
|
||||
#define _PAGE_NFO_4V _AC(0x4000000000000000,UL) /* No Fault Only */
|
||||
#define _PAGE_SOFT2_4V _AC(0x3F00000000000000,UL) /* Software bits, set 2 */
|
||||
#define _PAGE_MODIFIED_4V _AC(0x2000000000000000,UL) /* Modified (dirty) */
|
||||
#define _PAGE_ACCESSED_4V _AC(0x1000000000000000,UL) /* Accessed (ref'd) */
|
||||
#define _PAGE_READ_4V _AC(0x0800000000000000,UL) /* Readable SW Bit */
|
||||
#define _PAGE_WRITE_4V _AC(0x0400000000000000,UL) /* Writable SW Bit */
|
||||
#define _PAGE_PADDR_4V _AC(0x00FFFFFFFFFFE000,UL) /* paddr[55:13] */
|
||||
#define _PAGE_IE_4V _AC(0x0000000000001000,UL) /* Invert Endianness */
|
||||
#define _PAGE_E_4V _AC(0x0000000000000800,UL) /* side-Effect */
|
||||
#define _PAGE_CP_4V _AC(0x0000000000000400,UL) /* Cacheable in P-Cache */
|
||||
#define _PAGE_CV_4V _AC(0x0000000000000200,UL) /* Cacheable in V-Cache */
|
||||
#define _PAGE_P_4V _AC(0x0000000000000100,UL) /* Privileged Page */
|
||||
#define _PAGE_EXEC_4V _AC(0x0000000000000080,UL) /* Executable Page */
|
||||
#define _PAGE_W_4V _AC(0x0000000000000040,UL) /* Writable */
|
||||
#define _PAGE_SOFT_4V _AC(0x0000000000000030,UL) /* Software bits */
|
||||
#define _PAGE_FILE_4V _AC(0x0000000000000020,UL) /* Pagecache page */
|
||||
#define _PAGE_PRESENT_4V _AC(0x0000000000000010,UL) /* Present */
|
||||
#define _PAGE_RESV_4V _AC(0x0000000000000008,UL) /* Reserved */
|
||||
#define _PAGE_SZ16GB_4V _AC(0x0000000000000007,UL) /* 16GB Page */
|
||||
#define _PAGE_SZ2GB_4V _AC(0x0000000000000006,UL) /* 2GB Page */
|
||||
#define _PAGE_SZ256MB_4V _AC(0x0000000000000005,UL) /* 256MB Page */
|
||||
#define _PAGE_SZ32MB_4V _AC(0x0000000000000004,UL) /* 32MB Page */
|
||||
#define _PAGE_SZ4MB_4V _AC(0x0000000000000003,UL) /* 4MB Page */
|
||||
#define _PAGE_SZ512K_4V _AC(0x0000000000000002,UL) /* 512K Page */
|
||||
#define _PAGE_SZ64K_4V _AC(0x0000000000000001,UL) /* 64K Page */
|
||||
#define _PAGE_SZ8K_4V _AC(0x0000000000000000,UL) /* 8K Page */
|
||||
|
||||
#if PAGE_SHIFT == 13
|
||||
#define _PAGE_SZBITS _PAGE_SZ8K
|
||||
#define _PAGE_SZBITS_4U _PAGE_SZ8K_4U
|
||||
#define _PAGE_SZBITS_4V _PAGE_SZ8K_4V
|
||||
#elif PAGE_SHIFT == 16
|
||||
#define _PAGE_SZBITS _PAGE_SZ64K
|
||||
#define _PAGE_SZBITS_4U _PAGE_SZ64K_4U
|
||||
#define _PAGE_SZBITS_4V _PAGE_SZ64K_4V
|
||||
#elif PAGE_SHIFT == 19
|
||||
#define _PAGE_SZBITS _PAGE_SZ512K
|
||||
#define _PAGE_SZBITS_4U _PAGE_SZ512K_4U
|
||||
#define _PAGE_SZBITS_4V _PAGE_SZ512K_4V
|
||||
#elif PAGE_SHIFT == 22
|
||||
#define _PAGE_SZBITS _PAGE_SZ4MB
|
||||
#define _PAGE_SZBITS_4U _PAGE_SZ4MB_4U
|
||||
#define _PAGE_SZBITS_4V _PAGE_SZ4MB_4V
|
||||
#else
|
||||
#error Wrong PAGE_SHIFT specified
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_HUGETLB_PAGE_SIZE_4MB)
|
||||
#define _PAGE_SZHUGE _PAGE_SZ4MB
|
||||
#define _PAGE_SZHUGE_4U _PAGE_SZ4MB_4U
|
||||
#define _PAGE_SZHUGE_4V _PAGE_SZ4MB_4V
|
||||
#elif defined(CONFIG_HUGETLB_PAGE_SIZE_512K)
|
||||
#define _PAGE_SZHUGE _PAGE_SZ512K
|
||||
#define _PAGE_SZHUGE_4U _PAGE_SZ512K_4U
|
||||
#define _PAGE_SZHUGE_4V _PAGE_SZ512K_4V
|
||||
#elif defined(CONFIG_HUGETLB_PAGE_SIZE_64K)
|
||||
#define _PAGE_SZHUGE _PAGE_SZ64K
|
||||
#define _PAGE_SZHUGE_4U _PAGE_SZ64K_4U
|
||||
#define _PAGE_SZHUGE_4V _PAGE_SZ64K_4V
|
||||
#endif
|
||||
|
||||
#define _PAGE_CACHE (_PAGE_CP | _PAGE_CV)
|
||||
/* These are actually filled in at boot time by sun4{u,v}_pgprot_init() */
|
||||
#define __P000 __pgprot(0)
|
||||
#define __P001 __pgprot(0)
|
||||
#define __P010 __pgprot(0)
|
||||
#define __P011 __pgprot(0)
|
||||
#define __P100 __pgprot(0)
|
||||
#define __P101 __pgprot(0)
|
||||
#define __P110 __pgprot(0)
|
||||
#define __P111 __pgprot(0)
|
||||
|
||||
#define __DIRTY_BITS (_PAGE_MODIFIED | _PAGE_WRITE | _PAGE_W)
|
||||
#define __ACCESS_BITS (_PAGE_ACCESSED | _PAGE_READ | _PAGE_R)
|
||||
#define __PRIV_BITS _PAGE_P
|
||||
|
||||
#define PAGE_NONE __pgprot (_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_CACHE)
|
||||
|
||||
/* Don't set the TTE _PAGE_W bit here, else the dirty bit never gets set. */
|
||||
#define PAGE_SHARED __pgprot (_PAGE_PRESENT | _PAGE_VALID | _PAGE_CACHE | \
|
||||
__ACCESS_BITS | _PAGE_WRITE | _PAGE_EXEC)
|
||||
|
||||
#define PAGE_COPY __pgprot (_PAGE_PRESENT | _PAGE_VALID | _PAGE_CACHE | \
|
||||
__ACCESS_BITS | _PAGE_EXEC)
|
||||
|
||||
#define PAGE_READONLY __pgprot (_PAGE_PRESENT | _PAGE_VALID | _PAGE_CACHE | \
|
||||
__ACCESS_BITS | _PAGE_EXEC)
|
||||
|
||||
#define PAGE_KERNEL __pgprot (_PAGE_PRESENT | _PAGE_VALID | _PAGE_CACHE | \
|
||||
__PRIV_BITS | \
|
||||
__ACCESS_BITS | __DIRTY_BITS | _PAGE_EXEC)
|
||||
|
||||
#define PAGE_SHARED_NOEXEC __pgprot (_PAGE_PRESENT | _PAGE_VALID | \
|
||||
_PAGE_CACHE | \
|
||||
__ACCESS_BITS | _PAGE_WRITE)
|
||||
|
||||
#define PAGE_COPY_NOEXEC __pgprot (_PAGE_PRESENT | _PAGE_VALID | \
|
||||
_PAGE_CACHE | __ACCESS_BITS)
|
||||
|
||||
#define PAGE_READONLY_NOEXEC __pgprot (_PAGE_PRESENT | _PAGE_VALID | \
|
||||
_PAGE_CACHE | __ACCESS_BITS)
|
||||
|
||||
#define _PFN_MASK _PAGE_PADDR
|
||||
|
||||
#define pg_iobits (_PAGE_VALID | _PAGE_PRESENT | __DIRTY_BITS | \
|
||||
__ACCESS_BITS | _PAGE_E)
|
||||
|
||||
#define __P000 PAGE_NONE
|
||||
#define __P001 PAGE_READONLY_NOEXEC
|
||||
#define __P010 PAGE_COPY_NOEXEC
|
||||
#define __P011 PAGE_COPY_NOEXEC
|
||||
#define __P100 PAGE_READONLY
|
||||
#define __P101 PAGE_READONLY
|
||||
#define __P110 PAGE_COPY
|
||||
#define __P111 PAGE_COPY
|
||||
|
||||
#define __S000 PAGE_NONE
|
||||
#define __S001 PAGE_READONLY_NOEXEC
|
||||
#define __S010 PAGE_SHARED_NOEXEC
|
||||
#define __S011 PAGE_SHARED_NOEXEC
|
||||
#define __S100 PAGE_READONLY
|
||||
#define __S101 PAGE_READONLY
|
||||
#define __S110 PAGE_SHARED
|
||||
#define __S111 PAGE_SHARED
|
||||
#define __S000 __pgprot(0)
|
||||
#define __S001 __pgprot(0)
|
||||
#define __S010 __pgprot(0)
|
||||
#define __S011 __pgprot(0)
|
||||
#define __S100 __pgprot(0)
|
||||
#define __S101 __pgprot(0)
|
||||
#define __S110 __pgprot(0)
|
||||
#define __S111 __pgprot(0)
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
extern unsigned long phys_base;
|
||||
extern unsigned long pfn_base;
|
||||
extern pte_t mk_pte_io(unsigned long, pgprot_t, int, unsigned long);
|
||||
|
||||
extern unsigned long pte_sz_bits(unsigned long size);
|
||||
|
||||
extern pgprot_t PAGE_KERNEL;
|
||||
extern pgprot_t PAGE_KERNEL_LOCKED;
|
||||
extern pgprot_t PAGE_COPY;
|
||||
extern pgprot_t PAGE_SHARED;
|
||||
|
||||
/* XXX This uglyness is for the atyfb driver's sparc mmap() support. XXX */
|
||||
extern unsigned long _PAGE_IE;
|
||||
extern unsigned long _PAGE_E;
|
||||
extern unsigned long _PAGE_CACHE;
|
||||
|
||||
extern unsigned long pg_iobits;
|
||||
extern unsigned long _PAGE_ALL_SZ_BITS;
|
||||
extern unsigned long _PAGE_SZBITS;
|
||||
|
||||
extern struct page *mem_map_zero;
|
||||
#define ZERO_PAGE(vaddr) (mem_map_zero)
|
||||
@@ -223,27 +225,403 @@ extern struct page *mem_map_zero;
|
||||
* the first physical page in the machine is at some huge physical address,
|
||||
* such as 4GB. This is common on a partitioned E10000, for example.
|
||||
*/
|
||||
static inline pte_t pfn_pte(unsigned long pfn, pgprot_t prot)
|
||||
{
|
||||
unsigned long paddr = pfn << PAGE_SHIFT;
|
||||
unsigned long sz_bits;
|
||||
|
||||
#define pfn_pte(pfn, prot) \
|
||||
__pte(((pfn) << PAGE_SHIFT) | pgprot_val(prot) | _PAGE_SZBITS)
|
||||
sz_bits = 0UL;
|
||||
if (_PAGE_SZBITS_4U != 0UL || _PAGE_SZBITS_4V != 0UL) {
|
||||
__asm__ __volatile__(
|
||||
"\n661: sethi %uhi(%1), %0\n"
|
||||
" sllx %0, 32, %0\n"
|
||||
" .section .sun4v_2insn_patch, \"ax\"\n"
|
||||
" .word 661b\n"
|
||||
" mov %2, %0\n"
|
||||
" nop\n"
|
||||
" .previous\n"
|
||||
: "=r" (sz_bits)
|
||||
: "i" (_PAGE_SZBITS_4U), "i" (_PAGE_SZBITS_4V));
|
||||
}
|
||||
return __pte(paddr | sz_bits | pgprot_val(prot));
|
||||
}
|
||||
#define mk_pte(page, pgprot) pfn_pte(page_to_pfn(page), (pgprot))
|
||||
|
||||
#define pte_pfn(x) ((pte_val(x) & _PAGE_PADDR)>>PAGE_SHIFT)
|
||||
#define pte_page(x) pfn_to_page(pte_pfn(x))
|
||||
|
||||
static inline pte_t pte_modify(pte_t orig_pte, pgprot_t new_prot)
|
||||
/* This one can be done with two shifts. */
|
||||
static inline unsigned long pte_pfn(pte_t pte)
|
||||
{
|
||||
pte_t __pte;
|
||||
const unsigned long preserve_mask = (_PFN_MASK |
|
||||
_PAGE_MODIFIED | _PAGE_ACCESSED |
|
||||
_PAGE_CACHE | _PAGE_E |
|
||||
_PAGE_PRESENT | _PAGE_SZBITS);
|
||||
unsigned long ret;
|
||||
|
||||
pte_val(__pte) = (pte_val(orig_pte) & preserve_mask) |
|
||||
(pgprot_val(new_prot) & ~preserve_mask);
|
||||
__asm__ __volatile__(
|
||||
"\n661: sllx %1, %2, %0\n"
|
||||
" srlx %0, %3, %0\n"
|
||||
" .section .sun4v_2insn_patch, \"ax\"\n"
|
||||
" .word 661b\n"
|
||||
" sllx %1, %4, %0\n"
|
||||
" srlx %0, %5, %0\n"
|
||||
" .previous\n"
|
||||
: "=r" (ret)
|
||||
: "r" (pte_val(pte)),
|
||||
"i" (21), "i" (21 + PAGE_SHIFT),
|
||||
"i" (8), "i" (8 + PAGE_SHIFT));
|
||||
|
||||
return __pte;
|
||||
return ret;
|
||||
}
|
||||
#define pte_page(x) pfn_to_page(pte_pfn(x))
|
||||
|
||||
static inline pte_t pte_modify(pte_t pte, pgprot_t prot)
|
||||
{
|
||||
unsigned long mask, tmp;
|
||||
|
||||
/* SUN4U: 0x600307ffffffecb8 (negated == 0x9ffcf80000001347)
|
||||
* SUN4V: 0x30ffffffffffee17 (negated == 0xcf000000000011e8)
|
||||
*
|
||||
* Even if we use negation tricks the result is still a 6
|
||||
* instruction sequence, so don't try to play fancy and just
|
||||
* do the most straightforward implementation.
|
||||
*
|
||||
* Note: We encode this into 3 sun4v 2-insn patch sequences.
|
||||
*/
|
||||
|
||||
__asm__ __volatile__(
|
||||
"\n661: sethi %%uhi(%2), %1\n"
|
||||
" sethi %%hi(%2), %0\n"
|
||||
"\n662: or %1, %%ulo(%2), %1\n"
|
||||
" or %0, %%lo(%2), %0\n"
|
||||
"\n663: sllx %1, 32, %1\n"
|
||||
" or %0, %1, %0\n"
|
||||
" .section .sun4v_2insn_patch, \"ax\"\n"
|
||||
" .word 661b\n"
|
||||
" sethi %%uhi(%3), %1\n"
|
||||
" sethi %%hi(%3), %0\n"
|
||||
" .word 662b\n"
|
||||
" or %1, %%ulo(%3), %1\n"
|
||||
" or %0, %%lo(%3), %0\n"
|
||||
" .word 663b\n"
|
||||
" sllx %1, 32, %1\n"
|
||||
" or %0, %1, %0\n"
|
||||
" .previous\n"
|
||||
: "=r" (mask), "=r" (tmp)
|
||||
: "i" (_PAGE_PADDR_4U | _PAGE_MODIFIED_4U | _PAGE_ACCESSED_4U |
|
||||
_PAGE_CP_4U | _PAGE_CV_4U | _PAGE_E_4U | _PAGE_PRESENT_4U |
|
||||
_PAGE_SZBITS_4U),
|
||||
"i" (_PAGE_PADDR_4V | _PAGE_MODIFIED_4V | _PAGE_ACCESSED_4V |
|
||||
_PAGE_CP_4V | _PAGE_CV_4V | _PAGE_E_4V | _PAGE_PRESENT_4V |
|
||||
_PAGE_SZBITS_4V));
|
||||
|
||||
return __pte((pte_val(pte) & mask) | (pgprot_val(prot) & ~mask));
|
||||
}
|
||||
|
||||
static inline pte_t pgoff_to_pte(unsigned long off)
|
||||
{
|
||||
off <<= PAGE_SHIFT;
|
||||
|
||||
__asm__ __volatile__(
|
||||
"\n661: or %0, %2, %0\n"
|
||||
" .section .sun4v_1insn_patch, \"ax\"\n"
|
||||
" .word 661b\n"
|
||||
" or %0, %3, %0\n"
|
||||
" .previous\n"
|
||||
: "=r" (off)
|
||||
: "0" (off), "i" (_PAGE_FILE_4U), "i" (_PAGE_FILE_4V));
|
||||
|
||||
return __pte(off);
|
||||
}
|
||||
|
||||
static inline pgprot_t pgprot_noncached(pgprot_t prot)
|
||||
{
|
||||
unsigned long val = pgprot_val(prot);
|
||||
|
||||
__asm__ __volatile__(
|
||||
"\n661: andn %0, %2, %0\n"
|
||||
" or %0, %3, %0\n"
|
||||
" .section .sun4v_2insn_patch, \"ax\"\n"
|
||||
" .word 661b\n"
|
||||
" andn %0, %4, %0\n"
|
||||
" or %0, %3, %0\n"
|
||||
" .previous\n"
|
||||
: "=r" (val)
|
||||
: "0" (val), "i" (_PAGE_CP_4U | _PAGE_CV_4U), "i" (_PAGE_E_4U),
|
||||
"i" (_PAGE_CP_4V | _PAGE_CV_4V), "i" (_PAGE_E_4V));
|
||||
|
||||
return __pgprot(val);
|
||||
}
|
||||
/* Various pieces of code check for platform support by ifdef testing
|
||||
* on "pgprot_noncached". That's broken and should be fixed, but for
|
||||
* now...
|
||||
*/
|
||||
#define pgprot_noncached pgprot_noncached
|
||||
|
||||
#ifdef CONFIG_HUGETLB_PAGE
|
||||
static inline pte_t pte_mkhuge(pte_t pte)
|
||||
{
|
||||
unsigned long mask;
|
||||
|
||||
__asm__ __volatile__(
|
||||
"\n661: sethi %%uhi(%1), %0\n"
|
||||
" sllx %0, 32, %0\n"
|
||||
" .section .sun4v_2insn_patch, \"ax\"\n"
|
||||
" .word 661b\n"
|
||||
" mov %2, %0\n"
|
||||
" nop\n"
|
||||
" .previous\n"
|
||||
: "=r" (mask)
|
||||
: "i" (_PAGE_SZHUGE_4U), "i" (_PAGE_SZHUGE_4V));
|
||||
|
||||
return __pte(pte_val(pte) | mask);
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline pte_t pte_mkdirty(pte_t pte)
|
||||
{
|
||||
unsigned long val = pte_val(pte), tmp;
|
||||
|
||||
__asm__ __volatile__(
|
||||
"\n661: or %0, %3, %0\n"
|
||||
" nop\n"
|
||||
"\n662: nop\n"
|
||||
" nop\n"
|
||||
" .section .sun4v_2insn_patch, \"ax\"\n"
|
||||
" .word 661b\n"
|
||||
" sethi %%uhi(%4), %1\n"
|
||||
" sllx %1, 32, %1\n"
|
||||
" .word 662b\n"
|
||||
" or %1, %%lo(%4), %1\n"
|
||||
" or %0, %1, %0\n"
|
||||
" .previous\n"
|
||||
: "=r" (val), "=r" (tmp)
|
||||
: "0" (val), "i" (_PAGE_MODIFIED_4U | _PAGE_W_4U),
|
||||
"i" (_PAGE_MODIFIED_4V | _PAGE_W_4V));
|
||||
|
||||
return __pte(val);
|
||||
}
|
||||
|
||||
static inline pte_t pte_mkclean(pte_t pte)
|
||||
{
|
||||
unsigned long val = pte_val(pte), tmp;
|
||||
|
||||
__asm__ __volatile__(
|
||||
"\n661: andn %0, %3, %0\n"
|
||||
" nop\n"
|
||||
"\n662: nop\n"
|
||||
" nop\n"
|
||||
" .section .sun4v_2insn_patch, \"ax\"\n"
|
||||
" .word 661b\n"
|
||||
" sethi %%uhi(%4), %1\n"
|
||||
" sllx %1, 32, %1\n"
|
||||
" .word 662b\n"
|
||||
" or %1, %%lo(%4), %1\n"
|
||||
" andn %0, %1, %0\n"
|
||||
" .previous\n"
|
||||
: "=r" (val), "=r" (tmp)
|
||||
: "0" (val), "i" (_PAGE_MODIFIED_4U | _PAGE_W_4U),
|
||||
"i" (_PAGE_MODIFIED_4V | _PAGE_W_4V));
|
||||
|
||||
return __pte(val);
|
||||
}
|
||||
|
||||
static inline pte_t pte_mkwrite(pte_t pte)
|
||||
{
|
||||
unsigned long val = pte_val(pte), mask;
|
||||
|
||||
__asm__ __volatile__(
|
||||
"\n661: mov %1, %0\n"
|
||||
" nop\n"
|
||||
" .section .sun4v_2insn_patch, \"ax\"\n"
|
||||
" .word 661b\n"
|
||||
" sethi %%uhi(%2), %0\n"
|
||||
" sllx %0, 32, %0\n"
|
||||
" .previous\n"
|
||||
: "=r" (mask)
|
||||
: "i" (_PAGE_WRITE_4U), "i" (_PAGE_WRITE_4V));
|
||||
|
||||
return __pte(val | mask);
|
||||
}
|
||||
|
||||
static inline pte_t pte_wrprotect(pte_t pte)
|
||||
{
|
||||
unsigned long val = pte_val(pte), tmp;
|
||||
|
||||
__asm__ __volatile__(
|
||||
"\n661: andn %0, %3, %0\n"
|
||||
" nop\n"
|
||||
"\n662: nop\n"
|
||||
" nop\n"
|
||||
" .section .sun4v_2insn_patch, \"ax\"\n"
|
||||
" .word 661b\n"
|
||||
" sethi %%uhi(%4), %1\n"
|
||||
" sllx %1, 32, %1\n"
|
||||
" .word 662b\n"
|
||||
" or %1, %%lo(%4), %1\n"
|
||||
" andn %0, %1, %0\n"
|
||||
" .previous\n"
|
||||
: "=r" (val), "=r" (tmp)
|
||||
: "0" (val), "i" (_PAGE_WRITE_4U | _PAGE_W_4U),
|
||||
"i" (_PAGE_WRITE_4V | _PAGE_W_4V));
|
||||
|
||||
return __pte(val);
|
||||
}
|
||||
|
||||
static inline pte_t pte_mkold(pte_t pte)
|
||||
{
|
||||
unsigned long mask;
|
||||
|
||||
__asm__ __volatile__(
|
||||
"\n661: mov %1, %0\n"
|
||||
" nop\n"
|
||||
" .section .sun4v_2insn_patch, \"ax\"\n"
|
||||
" .word 661b\n"
|
||||
" sethi %%uhi(%2), %0\n"
|
||||
" sllx %0, 32, %0\n"
|
||||
" .previous\n"
|
||||
: "=r" (mask)
|
||||
: "i" (_PAGE_ACCESSED_4U), "i" (_PAGE_ACCESSED_4V));
|
||||
|
||||
mask |= _PAGE_R;
|
||||
|
||||
return __pte(pte_val(pte) & ~mask);
|
||||
}
|
||||
|
||||
static inline pte_t pte_mkyoung(pte_t pte)
|
||||
{
|
||||
unsigned long mask;
|
||||
|
||||
__asm__ __volatile__(
|
||||
"\n661: mov %1, %0\n"
|
||||
" nop\n"
|
||||
" .section .sun4v_2insn_patch, \"ax\"\n"
|
||||
" .word 661b\n"
|
||||
" sethi %%uhi(%2), %0\n"
|
||||
" sllx %0, 32, %0\n"
|
||||
" .previous\n"
|
||||
: "=r" (mask)
|
||||
: "i" (_PAGE_ACCESSED_4U), "i" (_PAGE_ACCESSED_4V));
|
||||
|
||||
mask |= _PAGE_R;
|
||||
|
||||
return __pte(pte_val(pte) | mask);
|
||||
}
|
||||
|
||||
static inline unsigned long pte_young(pte_t pte)
|
||||
{
|
||||
unsigned long mask;
|
||||
|
||||
__asm__ __volatile__(
|
||||
"\n661: mov %1, %0\n"
|
||||
" nop\n"
|
||||
" .section .sun4v_2insn_patch, \"ax\"\n"
|
||||
" .word 661b\n"
|
||||
" sethi %%uhi(%2), %0\n"
|
||||
" sllx %0, 32, %0\n"
|
||||
" .previous\n"
|
||||
: "=r" (mask)
|
||||
: "i" (_PAGE_ACCESSED_4U), "i" (_PAGE_ACCESSED_4V));
|
||||
|
||||
return (pte_val(pte) & mask);
|
||||
}
|
||||
|
||||
static inline unsigned long pte_dirty(pte_t pte)
|
||||
{
|
||||
unsigned long mask;
|
||||
|
||||
__asm__ __volatile__(
|
||||
"\n661: mov %1, %0\n"
|
||||
" nop\n"
|
||||
" .section .sun4v_2insn_patch, \"ax\"\n"
|
||||
" .word 661b\n"
|
||||
" sethi %%uhi(%2), %0\n"
|
||||
" sllx %0, 32, %0\n"
|
||||
" .previous\n"
|
||||
: "=r" (mask)
|
||||
: "i" (_PAGE_MODIFIED_4U), "i" (_PAGE_MODIFIED_4V));
|
||||
|
||||
return (pte_val(pte) & mask);
|
||||
}
|
||||
|
||||
static inline unsigned long pte_write(pte_t pte)
|
||||
{
|
||||
unsigned long mask;
|
||||
|
||||
__asm__ __volatile__(
|
||||
"\n661: mov %1, %0\n"
|
||||
" nop\n"
|
||||
" .section .sun4v_2insn_patch, \"ax\"\n"
|
||||
" .word 661b\n"
|
||||
" sethi %%uhi(%2), %0\n"
|
||||
" sllx %0, 32, %0\n"
|
||||
" .previous\n"
|
||||
: "=r" (mask)
|
||||
: "i" (_PAGE_WRITE_4U), "i" (_PAGE_WRITE_4V));
|
||||
|
||||
return (pte_val(pte) & mask);
|
||||
}
|
||||
|
||||
static inline unsigned long pte_exec(pte_t pte)
|
||||
{
|
||||
unsigned long mask;
|
||||
|
||||
__asm__ __volatile__(
|
||||
"\n661: sethi %%hi(%1), %0\n"
|
||||
" .section .sun4v_1insn_patch, \"ax\"\n"
|
||||
" .word 661b\n"
|
||||
" mov %2, %0\n"
|
||||
" .previous\n"
|
||||
: "=r" (mask)
|
||||
: "i" (_PAGE_EXEC_4U), "i" (_PAGE_EXEC_4V));
|
||||
|
||||
return (pte_val(pte) & mask);
|
||||
}
|
||||
|
||||
static inline unsigned long pte_read(pte_t pte)
|
||||
{
|
||||
unsigned long mask;
|
||||
|
||||
__asm__ __volatile__(
|
||||
"\n661: mov %1, %0\n"
|
||||
" nop\n"
|
||||
" .section .sun4v_2insn_patch, \"ax\"\n"
|
||||
" .word 661b\n"
|
||||
" sethi %%uhi(%2), %0\n"
|
||||
" sllx %0, 32, %0\n"
|
||||
" .previous\n"
|
||||
: "=r" (mask)
|
||||
: "i" (_PAGE_READ_4U), "i" (_PAGE_READ_4V));
|
||||
|
||||
return (pte_val(pte) & mask);
|
||||
}
|
||||
|
||||
static inline unsigned long pte_file(pte_t pte)
|
||||
{
|
||||
unsigned long val = pte_val(pte);
|
||||
|
||||
__asm__ __volatile__(
|
||||
"\n661: and %0, %2, %0\n"
|
||||
" .section .sun4v_1insn_patch, \"ax\"\n"
|
||||
" .word 661b\n"
|
||||
" and %0, %3, %0\n"
|
||||
" .previous\n"
|
||||
: "=r" (val)
|
||||
: "0" (val), "i" (_PAGE_FILE_4U), "i" (_PAGE_FILE_4V));
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
static inline unsigned long pte_present(pte_t pte)
|
||||
{
|
||||
unsigned long val = pte_val(pte);
|
||||
|
||||
__asm__ __volatile__(
|
||||
"\n661: and %0, %2, %0\n"
|
||||
" .section .sun4v_1insn_patch, \"ax\"\n"
|
||||
" .word 661b\n"
|
||||
" and %0, %3, %0\n"
|
||||
" .previous\n"
|
||||
: "=r" (val)
|
||||
: "0" (val), "i" (_PAGE_PRESENT_4U), "i" (_PAGE_PRESENT_4V));
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
#define pmd_set(pmdp, ptep) \
|
||||
(pmd_val(*(pmdp)) = (__pa((unsigned long) (ptep)) >> 11UL))
|
||||
#define pud_set(pudp, pmdp) \
|
||||
@@ -253,8 +631,6 @@ static inline pte_t pte_modify(pte_t orig_pte, pgprot_t new_prot)
|
||||
#define pmd_page(pmd) virt_to_page((void *)__pmd_page(pmd))
|
||||
#define pud_page(pud) \
|
||||
((unsigned long) __va((((unsigned long)pud_val(pud))<<11UL)))
|
||||
#define pte_none(pte) (!pte_val(pte))
|
||||
#define pte_present(pte) (pte_val(pte) & _PAGE_PRESENT)
|
||||
#define pmd_none(pmd) (!pmd_val(pmd))
|
||||
#define pmd_bad(pmd) (0)
|
||||
#define pmd_present(pmd) (pmd_val(pmd) != 0U)
|
||||
@@ -264,30 +640,8 @@ static inline pte_t pte_modify(pte_t orig_pte, pgprot_t new_prot)
|
||||
#define pud_present(pud) (pud_val(pud) != 0U)
|
||||
#define pud_clear(pudp) (pud_val(*(pudp)) = 0U)
|
||||
|
||||
/* The following only work if pte_present() is true.
|
||||
* Undefined behaviour if not..
|
||||
*/
|
||||
#define pte_read(pte) (pte_val(pte) & _PAGE_READ)
|
||||
#define pte_exec(pte) (pte_val(pte) & _PAGE_EXEC)
|
||||
#define pte_write(pte) (pte_val(pte) & _PAGE_WRITE)
|
||||
#define pte_dirty(pte) (pte_val(pte) & _PAGE_MODIFIED)
|
||||
#define pte_young(pte) (pte_val(pte) & _PAGE_ACCESSED)
|
||||
#define pte_wrprotect(pte) (__pte(pte_val(pte) & ~(_PAGE_WRITE|_PAGE_W)))
|
||||
#define pte_rdprotect(pte) \
|
||||
(__pte(((pte_val(pte)<<1UL)>>1UL) & ~_PAGE_READ))
|
||||
#define pte_mkclean(pte) \
|
||||
(__pte(pte_val(pte) & ~(_PAGE_MODIFIED|_PAGE_W)))
|
||||
#define pte_mkold(pte) \
|
||||
(__pte(((pte_val(pte)<<1UL)>>1UL) & ~_PAGE_ACCESSED))
|
||||
|
||||
/* Permanent address of a page. */
|
||||
#define __page_address(page) page_address(page)
|
||||
|
||||
/* Be very careful when you change these three, they are delicate. */
|
||||
#define pte_mkyoung(pte) (__pte(pte_val(pte) | _PAGE_ACCESSED | _PAGE_R))
|
||||
#define pte_mkwrite(pte) (__pte(pte_val(pte) | _PAGE_WRITE))
|
||||
#define pte_mkdirty(pte) (__pte(pte_val(pte) | _PAGE_MODIFIED | _PAGE_W))
|
||||
#define pte_mkhuge(pte) (__pte(pte_val(pte) | _PAGE_SZHUGE))
|
||||
/* Same in both SUN4V and SUN4U. */
|
||||
#define pte_none(pte) (!pte_val(pte))
|
||||
|
||||
/* to find an entry in a page-table-directory. */
|
||||
#define pgd_index(address) (((address) >> PGDIR_SHIFT) & (PTRS_PER_PGD - 1))
|
||||
@@ -296,11 +650,6 @@ static inline pte_t pte_modify(pte_t orig_pte, pgprot_t new_prot)
|
||||
/* to find an entry in a kernel page-table-directory */
|
||||
#define pgd_offset_k(address) pgd_offset(&init_mm, address)
|
||||
|
||||
/* extract the pgd cache used for optimizing the tlb miss
|
||||
* slow path when executing 32-bit compat processes
|
||||
*/
|
||||
#define get_pgd_cache(pgd) ((unsigned long) pgd_val(*pgd) << 11)
|
||||
|
||||
/* Find an entry in the second-level page table.. */
|
||||
#define pmd_offset(pudp, address) \
|
||||
((pmd_t *) pud_page(*(pudp)) + \
|
||||
@@ -327,6 +676,9 @@ static inline void set_pte_at(struct mm_struct *mm, unsigned long addr, pte_t *p
|
||||
|
||||
/* It is more efficient to let flush_tlb_kernel_range()
|
||||
* handle init_mm tlb flushes.
|
||||
*
|
||||
* SUN4V NOTE: _PAGE_VALID is the same value in both the SUN4U
|
||||
* and SUN4V pte layout, so this inline test is fine.
|
||||
*/
|
||||
if (likely(mm != &init_mm) && (pte_val(orig) & _PAGE_VALID))
|
||||
tlb_batch_add(mm, addr, ptep, orig);
|
||||
@@ -361,42 +713,23 @@ extern void update_mmu_cache(struct vm_area_struct *, unsigned long, pte_t);
|
||||
#define __swp_entry_to_pte(x) ((pte_t) { (x).val })
|
||||
|
||||
/* File offset in PTE support. */
|
||||
#define pte_file(pte) (pte_val(pte) & _PAGE_FILE)
|
||||
extern unsigned long pte_file(pte_t);
|
||||
#define pte_to_pgoff(pte) (pte_val(pte) >> PAGE_SHIFT)
|
||||
#define pgoff_to_pte(off) (__pte(((off) << PAGE_SHIFT) | _PAGE_FILE))
|
||||
extern pte_t pgoff_to_pte(unsigned long);
|
||||
#define PTE_FILE_MAX_BITS (64UL - PAGE_SHIFT - 1UL)
|
||||
|
||||
extern unsigned long prom_virt_to_phys(unsigned long, int *);
|
||||
|
||||
static __inline__ unsigned long
|
||||
sun4u_get_pte (unsigned long addr)
|
||||
{
|
||||
pgd_t *pgdp;
|
||||
pud_t *pudp;
|
||||
pmd_t *pmdp;
|
||||
pte_t *ptep;
|
||||
extern unsigned long sun4u_get_pte(unsigned long);
|
||||
|
||||
if (addr >= PAGE_OFFSET)
|
||||
return addr & _PAGE_PADDR;
|
||||
if ((addr >= LOW_OBP_ADDRESS) && (addr < HI_OBP_ADDRESS))
|
||||
return prom_virt_to_phys(addr, NULL);
|
||||
pgdp = pgd_offset_k(addr);
|
||||
pudp = pud_offset(pgdp, addr);
|
||||
pmdp = pmd_offset(pudp, addr);
|
||||
ptep = pte_offset_kernel(pmdp, addr);
|
||||
return pte_val(*ptep) & _PAGE_PADDR;
|
||||
static inline unsigned long __get_phys(unsigned long addr)
|
||||
{
|
||||
return sun4u_get_pte(addr);
|
||||
}
|
||||
|
||||
static __inline__ unsigned long
|
||||
__get_phys (unsigned long addr)
|
||||
static inline int __get_iospace(unsigned long addr)
|
||||
{
|
||||
return sun4u_get_pte (addr);
|
||||
}
|
||||
|
||||
static __inline__ int
|
||||
__get_iospace (unsigned long addr)
|
||||
{
|
||||
return ((sun4u_get_pte (addr) & 0xf0000000) >> 28);
|
||||
return ((sun4u_get_pte(addr) & 0xf0000000) >> 28);
|
||||
}
|
||||
|
||||
extern unsigned long *sparc64_valid_addr_bitmap;
|
||||
@@ -409,11 +742,6 @@ extern int io_remap_pfn_range(struct vm_area_struct *vma, unsigned long from,
|
||||
unsigned long pfn,
|
||||
unsigned long size, pgprot_t prot);
|
||||
|
||||
/* Clear virtual and physical cachability, set side-effect bit. */
|
||||
#define pgprot_noncached(prot) \
|
||||
(__pgprot((pgprot_val(prot) & ~(_PAGE_CP | _PAGE_CV)) | \
|
||||
_PAGE_E))
|
||||
|
||||
/*
|
||||
* For sparc32&64, the pfn in io_remap_pfn_range() carries <iospace> in
|
||||
* its high 4 bits. These macros/functions put it there or get it from there.
|
||||
@@ -424,8 +752,11 @@ extern int io_remap_pfn_range(struct vm_area_struct *vma, unsigned long from,
|
||||
|
||||
#include <asm-generic/pgtable.h>
|
||||
|
||||
/* We provide our own get_unmapped_area to cope with VA holes for userland */
|
||||
/* We provide our own get_unmapped_area to cope with VA holes and
|
||||
* SHM area cache aliasing for userland.
|
||||
*/
|
||||
#define HAVE_ARCH_UNMAPPED_AREA
|
||||
#define HAVE_ARCH_UNMAPPED_AREA_TOPDOWN
|
||||
|
||||
/* We provide a special get_unmapped_area for framebuffer mmaps to try and use
|
||||
* the largest alignment possible such that larget PTEs can be used.
|
||||
@@ -435,12 +766,9 @@ extern unsigned long get_fb_unmapped_area(struct file *filp, unsigned long,
|
||||
unsigned long);
|
||||
#define HAVE_ARCH_FB_UNMAPPED_AREA
|
||||
|
||||
/*
|
||||
* No page table caches to initialise
|
||||
*/
|
||||
#define pgtable_cache_init() do { } while (0)
|
||||
|
||||
extern void check_pgt_cache(void);
|
||||
extern void pgtable_cache_init(void);
|
||||
extern void sun4v_register_fault_status(void);
|
||||
extern void sun4v_ktsb_register(void);
|
||||
|
||||
#endif /* !(__ASSEMBLY__) */
|
||||
|
||||
|
||||
@@ -16,11 +16,13 @@
|
||||
#define PIL_SMP_CALL_FUNC 1
|
||||
#define PIL_SMP_RECEIVE_SIGNAL 2
|
||||
#define PIL_SMP_CAPTURE 3
|
||||
#define PIL_SMP_CTX_NEW_VERSION 4
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
#define PIL_RESERVED(PIL) ((PIL) == PIL_SMP_CALL_FUNC || \
|
||||
(PIL) == PIL_SMP_RECEIVE_SIGNAL || \
|
||||
(PIL) == PIL_SMP_CAPTURE)
|
||||
(PIL) == PIL_SMP_CAPTURE || \
|
||||
(PIL) == PIL_SMP_CTX_NEW_VERSION)
|
||||
#endif
|
||||
|
||||
#endif /* !(_SPARC64_PIL_H) */
|
||||
|
||||
@@ -28,6 +28,8 @@
|
||||
* User lives in his very own context, and cannot reference us. Note
|
||||
* that TASK_SIZE is a misnomer, it really gives maximum user virtual
|
||||
* address that the kernel will allocate out.
|
||||
*
|
||||
* XXX No longer using virtual page tables, kill this upper limit...
|
||||
*/
|
||||
#define VA_BITS 44
|
||||
#ifndef __ASSEMBLY__
|
||||
@@ -37,18 +39,6 @@
|
||||
#endif
|
||||
#define TASK_SIZE ((unsigned long)-VPTE_SIZE)
|
||||
|
||||
/*
|
||||
* The vpte base must be able to hold the entire vpte, half
|
||||
* of which lives above, and half below, the base. And it
|
||||
* is placed as close to the highest address range as possible.
|
||||
*/
|
||||
#define VPTE_BASE_SPITFIRE (-(VPTE_SIZE/2))
|
||||
#if 1
|
||||
#define VPTE_BASE_CHEETAH VPTE_BASE_SPITFIRE
|
||||
#else
|
||||
#define VPTE_BASE_CHEETAH 0xffe0000000000000
|
||||
#endif
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
typedef struct {
|
||||
@@ -101,7 +91,8 @@ extern unsigned long thread_saved_pc(struct task_struct *);
|
||||
/* Do necessary setup to start up a newly executed thread. */
|
||||
#define start_thread(regs, pc, sp) \
|
||||
do { \
|
||||
regs->tstate = (regs->tstate & (TSTATE_CWP)) | (TSTATE_INITIAL_MM|TSTATE_IE) | (ASI_PNF << 24); \
|
||||
unsigned long __asi = ASI_PNF; \
|
||||
regs->tstate = (regs->tstate & (TSTATE_CWP)) | (TSTATE_INITIAL_MM|TSTATE_IE) | (__asi << 24UL); \
|
||||
regs->tpc = ((pc & (~3)) - 4); \
|
||||
regs->tnpc = regs->tpc + 4; \
|
||||
regs->y = 0; \
|
||||
@@ -138,10 +129,10 @@ do { \
|
||||
|
||||
#define start_thread32(regs, pc, sp) \
|
||||
do { \
|
||||
unsigned long __asi = ASI_PNF; \
|
||||
pc &= 0x00000000ffffffffUL; \
|
||||
sp &= 0x00000000ffffffffUL; \
|
||||
\
|
||||
regs->tstate = (regs->tstate & (TSTATE_CWP))|(TSTATE_INITIAL_MM|TSTATE_IE|TSTATE_AM); \
|
||||
regs->tstate = (regs->tstate & (TSTATE_CWP))|(TSTATE_INITIAL_MM|TSTATE_IE|TSTATE_AM) | (__asi << 24UL); \
|
||||
regs->tpc = ((pc & (~3)) - 4); \
|
||||
regs->tnpc = regs->tpc + 4; \
|
||||
regs->y = 0; \
|
||||
@@ -226,6 +217,8 @@ static inline void prefetchw(const void *x)
|
||||
|
||||
#define spin_lock_prefetch(x) prefetchw(x)
|
||||
|
||||
#define HAVE_ARCH_PICK_MMAP_LAYOUT
|
||||
|
||||
#endif /* !(__ASSEMBLY__) */
|
||||
|
||||
#endif /* !(__ASM_SPARC64_PROCESSOR_H) */
|
||||
|
||||
@@ -28,11 +28,12 @@
|
||||
|
||||
/* The V9 TSTATE Register (with SpitFire and Linux extensions).
|
||||
*
|
||||
* ---------------------------------------------------------------
|
||||
* | Resv | CCR | ASI | %pil | PSTATE | Resv | CWP |
|
||||
* ---------------------------------------------------------------
|
||||
* 63 40 39 32 31 24 23 20 19 8 7 5 4 0
|
||||
* ---------------------------------------------------------------------
|
||||
* | Resv | GL | CCR | ASI | %pil | PSTATE | Resv | CWP |
|
||||
* ---------------------------------------------------------------------
|
||||
* 63 43 42 40 39 32 31 24 23 20 19 8 7 5 4 0
|
||||
*/
|
||||
#define TSTATE_GL _AC(0x0000070000000000,UL) /* Global reg level */
|
||||
#define TSTATE_CCR _AC(0x000000ff00000000,UL) /* Condition Codes. */
|
||||
#define TSTATE_XCC _AC(0x000000f000000000,UL) /* Condition Codes. */
|
||||
#define TSTATE_XNEG _AC(0x0000008000000000,UL) /* %xcc Negative. */
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
#ifndef _SPARC64_SCRATCHPAD_H
|
||||
#define _SPARC64_SCRATCHPAD_H
|
||||
|
||||
/* Sun4v scratchpad registers, accessed via ASI_SCRATCHPAD. */
|
||||
|
||||
#define SCRATCHPAD_MMU_MISS 0x00 /* Shared with OBP - set by OBP */
|
||||
#define SCRATCHPAD_CPUID 0x08 /* Shared with OBP - set by hypervisor */
|
||||
#define SCRATCHPAD_UTSBREG1 0x10
|
||||
#define SCRATCHPAD_UTSBREG2 0x18
|
||||
/* 0x20 and 0x28, hypervisor only... */
|
||||
#define SCRATCHPAD_UNUSED1 0x30
|
||||
#define SCRATCHPAD_UNUSED2 0x38 /* Reserved for OBP */
|
||||
|
||||
#endif /* !(_SPARC64_SCRATCHPAD_H) */
|
||||
@@ -33,37 +33,13 @@
|
||||
extern cpumask_t phys_cpu_present_map;
|
||||
#define cpu_possible_map phys_cpu_present_map
|
||||
|
||||
extern cpumask_t cpu_sibling_map[NR_CPUS];
|
||||
|
||||
/*
|
||||
* General functions that each host system must provide.
|
||||
*/
|
||||
|
||||
static __inline__ int hard_smp_processor_id(void)
|
||||
{
|
||||
if (tlb_type == cheetah || tlb_type == cheetah_plus) {
|
||||
unsigned long cfg, ver;
|
||||
__asm__ __volatile__("rdpr %%ver, %0" : "=r" (ver));
|
||||
if ((ver >> 32) == 0x003e0016) {
|
||||
__asm__ __volatile__("ldxa [%%g0] %1, %0"
|
||||
: "=r" (cfg)
|
||||
: "i" (ASI_JBUS_CONFIG));
|
||||
return ((cfg >> 17) & 0x1f);
|
||||
} else {
|
||||
__asm__ __volatile__("ldxa [%%g0] %1, %0"
|
||||
: "=r" (cfg)
|
||||
: "i" (ASI_SAFARI_CONFIG));
|
||||
return ((cfg >> 17) & 0x3ff);
|
||||
}
|
||||
} else if (this_is_starfire != 0) {
|
||||
return starfire_hard_smp_processor_id();
|
||||
} else {
|
||||
unsigned long upaconfig;
|
||||
__asm__ __volatile__("ldxa [%%g0] %1, %0"
|
||||
: "=r" (upaconfig)
|
||||
: "i" (ASI_UPA_CONFIG));
|
||||
return ((upaconfig >> 17) & 0x1f);
|
||||
}
|
||||
}
|
||||
|
||||
extern int hard_smp_processor_id(void);
|
||||
#define raw_smp_processor_id() (current_thread_info()->cpu)
|
||||
|
||||
extern void smp_setup_cpu_possible_map(void);
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
#ifndef _SPARC64_SPARSEMEM_H
|
||||
#define _SPARC64_SPARSEMEM_H
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
#define SECTION_SIZE_BITS 26
|
||||
#define MAX_PHYSADDR_BITS 42
|
||||
#define MAX_PHYSMEM_BITS 42
|
||||
|
||||
#endif /* !(__KERNEL__) */
|
||||
|
||||
#endif /* !(_SPARC64_SPARSEMEM_H) */
|
||||
@@ -44,6 +44,7 @@ enum ultra_tlb_layout {
|
||||
spitfire = 0,
|
||||
cheetah = 1,
|
||||
cheetah_plus = 2,
|
||||
hypervisor = 3,
|
||||
};
|
||||
|
||||
extern enum ultra_tlb_layout tlb_type;
|
||||
|
||||
@@ -209,9 +209,10 @@ do { if (test_thread_flag(TIF_PERFCTR)) { \
|
||||
/* so that ASI is only written if it changes, think again. */ \
|
||||
__asm__ __volatile__("wr %%g0, %0, %%asi" \
|
||||
: : "r" (__thread_flag_byte_ptr(task_thread_info(next))[TI_FLAG_BYTE_CURRENT_DS]));\
|
||||
trap_block[current_thread_info()->cpu].thread = \
|
||||
task_thread_info(next); \
|
||||
__asm__ __volatile__( \
|
||||
"mov %%g4, %%g7\n\t" \
|
||||
"wrpr %%g0, 0x95, %%pstate\n\t" \
|
||||
"stx %%i6, [%%sp + 2047 + 0x70]\n\t" \
|
||||
"stx %%i7, [%%sp + 2047 + 0x78]\n\t" \
|
||||
"rdpr %%wstate, %%o5\n\t" \
|
||||
@@ -225,14 +226,10 @@ do { if (test_thread_flag(TIF_PERFCTR)) { \
|
||||
"ldx [%%g6 + %3], %%o6\n\t" \
|
||||
"ldub [%%g6 + %2], %%o5\n\t" \
|
||||
"ldub [%%g6 + %4], %%o7\n\t" \
|
||||
"mov %%g6, %%l2\n\t" \
|
||||
"wrpr %%o5, 0x0, %%wstate\n\t" \
|
||||
"ldx [%%sp + 2047 + 0x70], %%i6\n\t" \
|
||||
"ldx [%%sp + 2047 + 0x78], %%i7\n\t" \
|
||||
"wrpr %%g0, 0x94, %%pstate\n\t" \
|
||||
"mov %%l2, %%g6\n\t" \
|
||||
"ldx [%%g6 + %6], %%g4\n\t" \
|
||||
"wrpr %%g0, 0x96, %%pstate\n\t" \
|
||||
"brz,pt %%o7, 1f\n\t" \
|
||||
" mov %%g7, %0\n\t" \
|
||||
"b,a ret_from_syscall\n\t" \
|
||||
|
||||
@@ -64,8 +64,6 @@ struct thread_info {
|
||||
__u64 kernel_cntd0, kernel_cntd1;
|
||||
__u64 pcr_reg;
|
||||
|
||||
__u64 cee_stuff;
|
||||
|
||||
struct restart_block restart_block;
|
||||
|
||||
struct pt_regs *kern_una_regs;
|
||||
@@ -104,10 +102,9 @@ struct thread_info {
|
||||
#define TI_KERN_CNTD0 0x00000480
|
||||
#define TI_KERN_CNTD1 0x00000488
|
||||
#define TI_PCR 0x00000490
|
||||
#define TI_CEE_STUFF 0x00000498
|
||||
#define TI_RESTART_BLOCK 0x000004a0
|
||||
#define TI_KUNA_REGS 0x000004c8
|
||||
#define TI_KUNA_INSN 0x000004d0
|
||||
#define TI_RESTART_BLOCK 0x00000498
|
||||
#define TI_KUNA_REGS 0x000004c0
|
||||
#define TI_KUNA_INSN 0x000004c8
|
||||
#define TI_FPREGS 0x00000500
|
||||
|
||||
/* We embed this in the uppermost byte of thread_info->flags */
|
||||
|
||||
@@ -14,4 +14,10 @@
|
||||
typedef unsigned long cycles_t;
|
||||
#define get_cycles() tick_ops->get_tick()
|
||||
|
||||
#define ARCH_HAS_READ_CURRENT_TIMER 1
|
||||
#define read_current_timer(timer_val_p) \
|
||||
({ *timer_val_p = tick_ops->get_tick(); \
|
||||
0; \
|
||||
})
|
||||
|
||||
#endif
|
||||
|
||||
@@ -5,6 +5,11 @@
|
||||
#include <linux/mm.h>
|
||||
#include <asm/mmu_context.h>
|
||||
|
||||
/* TSB flush operations. */
|
||||
struct mmu_gather;
|
||||
extern void flush_tsb_kernel_range(unsigned long start, unsigned long end);
|
||||
extern void flush_tsb_user(struct mmu_gather *mp);
|
||||
|
||||
/* TLB flush operations. */
|
||||
|
||||
extern void flush_tlb_pending(void);
|
||||
@@ -14,28 +19,36 @@ extern void flush_tlb_pending(void);
|
||||
#define flush_tlb_page(vma,addr) flush_tlb_pending()
|
||||
#define flush_tlb_mm(mm) flush_tlb_pending()
|
||||
|
||||
/* Local cpu only. */
|
||||
extern void __flush_tlb_all(void);
|
||||
|
||||
extern void __flush_tlb_page(unsigned long context, unsigned long page, unsigned long r);
|
||||
|
||||
extern void __flush_tlb_kernel_range(unsigned long start, unsigned long end);
|
||||
|
||||
#ifndef CONFIG_SMP
|
||||
|
||||
#define flush_tlb_all() __flush_tlb_all()
|
||||
#define flush_tlb_kernel_range(start,end) \
|
||||
__flush_tlb_kernel_range(start,end)
|
||||
do { flush_tsb_kernel_range(start,end); \
|
||||
__flush_tlb_kernel_range(start,end); \
|
||||
} while (0)
|
||||
|
||||
#else /* CONFIG_SMP */
|
||||
|
||||
extern void smp_flush_tlb_all(void);
|
||||
extern void smp_flush_tlb_kernel_range(unsigned long start, unsigned long end);
|
||||
|
||||
#define flush_tlb_all() smp_flush_tlb_all()
|
||||
#define flush_tlb_kernel_range(start, end) \
|
||||
smp_flush_tlb_kernel_range(start, end)
|
||||
do { flush_tsb_kernel_range(start,end); \
|
||||
smp_flush_tlb_kernel_range(start, end); \
|
||||
} while (0)
|
||||
|
||||
#endif /* ! CONFIG_SMP */
|
||||
|
||||
extern void flush_tlb_pgtables(struct mm_struct *, unsigned long, unsigned long);
|
||||
static inline void flush_tlb_pgtables(struct mm_struct *mm, unsigned long start, unsigned long end)
|
||||
{
|
||||
/* We don't use virtual page tables for TLB miss processing
|
||||
* any more. Nowadays we use the TSB.
|
||||
*/
|
||||
}
|
||||
|
||||
#endif /* _SPARC64_TLBFLUSH_H */
|
||||
|
||||
@@ -0,0 +1,281 @@
|
||||
#ifndef _SPARC64_TSB_H
|
||||
#define _SPARC64_TSB_H
|
||||
|
||||
/* The sparc64 TSB is similar to the powerpc hashtables. It's a
|
||||
* power-of-2 sized table of TAG/PTE pairs. The cpu precomputes
|
||||
* pointers into this table for 8K and 64K page sizes, and also a
|
||||
* comparison TAG based upon the virtual address and context which
|
||||
* faults.
|
||||
*
|
||||
* TLB miss trap handler software does the actual lookup via something
|
||||
* of the form:
|
||||
*
|
||||
* ldxa [%g0] ASI_{D,I}MMU_TSB_8KB_PTR, %g1
|
||||
* ldxa [%g0] ASI_{D,I}MMU, %g6
|
||||
* sllx %g6, 22, %g6
|
||||
* srlx %g6, 22, %g6
|
||||
* ldda [%g1] ASI_NUCLEUS_QUAD_LDD, %g4
|
||||
* cmp %g4, %g6
|
||||
* bne,pn %xcc, tsb_miss_{d,i}tlb
|
||||
* mov FAULT_CODE_{D,I}TLB, %g3
|
||||
* stxa %g5, [%g0] ASI_{D,I}TLB_DATA_IN
|
||||
* retry
|
||||
*
|
||||
*
|
||||
* Each 16-byte slot of the TSB is the 8-byte tag and then the 8-byte
|
||||
* PTE. The TAG is of the same layout as the TLB TAG TARGET mmu
|
||||
* register which is:
|
||||
*
|
||||
* -------------------------------------------------
|
||||
* | - | CONTEXT | - | VADDR bits 63:22 |
|
||||
* -------------------------------------------------
|
||||
* 63 61 60 48 47 42 41 0
|
||||
*
|
||||
* But actually, since we use per-mm TSB's, we zero out the CONTEXT
|
||||
* field.
|
||||
*
|
||||
* Like the powerpc hashtables we need to use locking in order to
|
||||
* synchronize while we update the entries. PTE updates need locking
|
||||
* as well.
|
||||
*
|
||||
* We need to carefully choose a lock bits for the TSB entry. We
|
||||
* choose to use bit 47 in the tag. Also, since we never map anything
|
||||
* at page zero in context zero, we use zero as an invalid tag entry.
|
||||
* When the lock bit is set, this forces a tag comparison failure.
|
||||
*/
|
||||
|
||||
#define TSB_TAG_LOCK_BIT 47
|
||||
#define TSB_TAG_LOCK_HIGH (1 << (TSB_TAG_LOCK_BIT - 32))
|
||||
|
||||
#define TSB_TAG_INVALID_BIT 46
|
||||
#define TSB_TAG_INVALID_HIGH (1 << (TSB_TAG_INVALID_BIT - 32))
|
||||
|
||||
#define TSB_MEMBAR membar #StoreStore
|
||||
|
||||
/* Some cpus support physical address quad loads. We want to use
|
||||
* those if possible so we don't need to hard-lock the TSB mapping
|
||||
* into the TLB. We encode some instruction patching in order to
|
||||
* support this.
|
||||
*
|
||||
* The kernel TSB is locked into the TLB by virtue of being in the
|
||||
* kernel image, so we don't play these games for swapper_tsb access.
|
||||
*/
|
||||
#ifndef __ASSEMBLY__
|
||||
struct tsb_ldquad_phys_patch_entry {
|
||||
unsigned int addr;
|
||||
unsigned int sun4u_insn;
|
||||
unsigned int sun4v_insn;
|
||||
};
|
||||
extern struct tsb_ldquad_phys_patch_entry __tsb_ldquad_phys_patch,
|
||||
__tsb_ldquad_phys_patch_end;
|
||||
|
||||
struct tsb_phys_patch_entry {
|
||||
unsigned int addr;
|
||||
unsigned int insn;
|
||||
};
|
||||
extern struct tsb_phys_patch_entry __tsb_phys_patch, __tsb_phys_patch_end;
|
||||
#endif
|
||||
#define TSB_LOAD_QUAD(TSB, REG) \
|
||||
661: ldda [TSB] ASI_NUCLEUS_QUAD_LDD, REG; \
|
||||
.section .tsb_ldquad_phys_patch, "ax"; \
|
||||
.word 661b; \
|
||||
ldda [TSB] ASI_QUAD_LDD_PHYS, REG; \
|
||||
ldda [TSB] ASI_QUAD_LDD_PHYS_4V, REG; \
|
||||
.previous
|
||||
|
||||
#define TSB_LOAD_TAG_HIGH(TSB, REG) \
|
||||
661: lduwa [TSB] ASI_N, REG; \
|
||||
.section .tsb_phys_patch, "ax"; \
|
||||
.word 661b; \
|
||||
lduwa [TSB] ASI_PHYS_USE_EC, REG; \
|
||||
.previous
|
||||
|
||||
#define TSB_LOAD_TAG(TSB, REG) \
|
||||
661: ldxa [TSB] ASI_N, REG; \
|
||||
.section .tsb_phys_patch, "ax"; \
|
||||
.word 661b; \
|
||||
ldxa [TSB] ASI_PHYS_USE_EC, REG; \
|
||||
.previous
|
||||
|
||||
#define TSB_CAS_TAG_HIGH(TSB, REG1, REG2) \
|
||||
661: casa [TSB] ASI_N, REG1, REG2; \
|
||||
.section .tsb_phys_patch, "ax"; \
|
||||
.word 661b; \
|
||||
casa [TSB] ASI_PHYS_USE_EC, REG1, REG2; \
|
||||
.previous
|
||||
|
||||
#define TSB_CAS_TAG(TSB, REG1, REG2) \
|
||||
661: casxa [TSB] ASI_N, REG1, REG2; \
|
||||
.section .tsb_phys_patch, "ax"; \
|
||||
.word 661b; \
|
||||
casxa [TSB] ASI_PHYS_USE_EC, REG1, REG2; \
|
||||
.previous
|
||||
|
||||
#define TSB_STORE(ADDR, VAL) \
|
||||
661: stxa VAL, [ADDR] ASI_N; \
|
||||
.section .tsb_phys_patch, "ax"; \
|
||||
.word 661b; \
|
||||
stxa VAL, [ADDR] ASI_PHYS_USE_EC; \
|
||||
.previous
|
||||
|
||||
#define TSB_LOCK_TAG(TSB, REG1, REG2) \
|
||||
99: TSB_LOAD_TAG_HIGH(TSB, REG1); \
|
||||
sethi %hi(TSB_TAG_LOCK_HIGH), REG2;\
|
||||
andcc REG1, REG2, %g0; \
|
||||
bne,pn %icc, 99b; \
|
||||
nop; \
|
||||
TSB_CAS_TAG_HIGH(TSB, REG1, REG2); \
|
||||
cmp REG1, REG2; \
|
||||
bne,pn %icc, 99b; \
|
||||
nop; \
|
||||
TSB_MEMBAR
|
||||
|
||||
#define TSB_WRITE(TSB, TTE, TAG) \
|
||||
add TSB, 0x8, TSB; \
|
||||
TSB_STORE(TSB, TTE); \
|
||||
sub TSB, 0x8, TSB; \
|
||||
TSB_MEMBAR; \
|
||||
TSB_STORE(TSB, TAG);
|
||||
|
||||
#define KTSB_LOAD_QUAD(TSB, REG) \
|
||||
ldda [TSB] ASI_NUCLEUS_QUAD_LDD, REG;
|
||||
|
||||
#define KTSB_STORE(ADDR, VAL) \
|
||||
stxa VAL, [ADDR] ASI_N;
|
||||
|
||||
#define KTSB_LOCK_TAG(TSB, REG1, REG2) \
|
||||
99: lduwa [TSB] ASI_N, REG1; \
|
||||
sethi %hi(TSB_TAG_LOCK_HIGH), REG2;\
|
||||
andcc REG1, REG2, %g0; \
|
||||
bne,pn %icc, 99b; \
|
||||
nop; \
|
||||
casa [TSB] ASI_N, REG1, REG2;\
|
||||
cmp REG1, REG2; \
|
||||
bne,pn %icc, 99b; \
|
||||
nop; \
|
||||
TSB_MEMBAR
|
||||
|
||||
#define KTSB_WRITE(TSB, TTE, TAG) \
|
||||
add TSB, 0x8, TSB; \
|
||||
stxa TTE, [TSB] ASI_N; \
|
||||
sub TSB, 0x8, TSB; \
|
||||
TSB_MEMBAR; \
|
||||
stxa TAG, [TSB] ASI_N;
|
||||
|
||||
/* Do a kernel page table walk. Leaves physical PTE pointer in
|
||||
* REG1. Jumps to FAIL_LABEL on early page table walk termination.
|
||||
* VADDR will not be clobbered, but REG2 will.
|
||||
*/
|
||||
#define KERN_PGTABLE_WALK(VADDR, REG1, REG2, FAIL_LABEL) \
|
||||
sethi %hi(swapper_pg_dir), REG1; \
|
||||
or REG1, %lo(swapper_pg_dir), REG1; \
|
||||
sllx VADDR, 64 - (PGDIR_SHIFT + PGDIR_BITS), REG2; \
|
||||
srlx REG2, 64 - PAGE_SHIFT, REG2; \
|
||||
andn REG2, 0x3, REG2; \
|
||||
lduw [REG1 + REG2], REG1; \
|
||||
brz,pn REG1, FAIL_LABEL; \
|
||||
sllx VADDR, 64 - (PMD_SHIFT + PMD_BITS), REG2; \
|
||||
srlx REG2, 64 - PAGE_SHIFT, REG2; \
|
||||
sllx REG1, 11, REG1; \
|
||||
andn REG2, 0x3, REG2; \
|
||||
lduwa [REG1 + REG2] ASI_PHYS_USE_EC, REG1; \
|
||||
brz,pn REG1, FAIL_LABEL; \
|
||||
sllx VADDR, 64 - PMD_SHIFT, REG2; \
|
||||
srlx REG2, 64 - PAGE_SHIFT, REG2; \
|
||||
sllx REG1, 11, REG1; \
|
||||
andn REG2, 0x7, REG2; \
|
||||
add REG1, REG2, REG1;
|
||||
|
||||
/* Do a user page table walk in MMU globals. Leaves physical PTE
|
||||
* pointer in REG1. Jumps to FAIL_LABEL on early page table walk
|
||||
* termination. Physical base of page tables is in PHYS_PGD which
|
||||
* will not be modified.
|
||||
*
|
||||
* VADDR will not be clobbered, but REG1 and REG2 will.
|
||||
*/
|
||||
#define USER_PGTABLE_WALK_TL1(VADDR, PHYS_PGD, REG1, REG2, FAIL_LABEL) \
|
||||
sllx VADDR, 64 - (PGDIR_SHIFT + PGDIR_BITS), REG2; \
|
||||
srlx REG2, 64 - PAGE_SHIFT, REG2; \
|
||||
andn REG2, 0x3, REG2; \
|
||||
lduwa [PHYS_PGD + REG2] ASI_PHYS_USE_EC, REG1; \
|
||||
brz,pn REG1, FAIL_LABEL; \
|
||||
sllx VADDR, 64 - (PMD_SHIFT + PMD_BITS), REG2; \
|
||||
srlx REG2, 64 - PAGE_SHIFT, REG2; \
|
||||
sllx REG1, 11, REG1; \
|
||||
andn REG2, 0x3, REG2; \
|
||||
lduwa [REG1 + REG2] ASI_PHYS_USE_EC, REG1; \
|
||||
brz,pn REG1, FAIL_LABEL; \
|
||||
sllx VADDR, 64 - PMD_SHIFT, REG2; \
|
||||
srlx REG2, 64 - PAGE_SHIFT, REG2; \
|
||||
sllx REG1, 11, REG1; \
|
||||
andn REG2, 0x7, REG2; \
|
||||
add REG1, REG2, REG1;
|
||||
|
||||
/* Lookup a OBP mapping on VADDR in the prom_trans[] table at TL>0.
|
||||
* If no entry is found, FAIL_LABEL will be branched to. On success
|
||||
* the resulting PTE value will be left in REG1. VADDR is preserved
|
||||
* by this routine.
|
||||
*/
|
||||
#define OBP_TRANS_LOOKUP(VADDR, REG1, REG2, REG3, FAIL_LABEL) \
|
||||
sethi %hi(prom_trans), REG1; \
|
||||
or REG1, %lo(prom_trans), REG1; \
|
||||
97: ldx [REG1 + 0x00], REG2; \
|
||||
brz,pn REG2, FAIL_LABEL; \
|
||||
nop; \
|
||||
ldx [REG1 + 0x08], REG3; \
|
||||
add REG2, REG3, REG3; \
|
||||
cmp REG2, VADDR; \
|
||||
bgu,pt %xcc, 98f; \
|
||||
cmp VADDR, REG3; \
|
||||
bgeu,pt %xcc, 98f; \
|
||||
ldx [REG1 + 0x10], REG3; \
|
||||
sub VADDR, REG2, REG2; \
|
||||
ba,pt %xcc, 99f; \
|
||||
add REG3, REG2, REG1; \
|
||||
98: ba,pt %xcc, 97b; \
|
||||
add REG1, (3 * 8), REG1; \
|
||||
99:
|
||||
|
||||
/* We use a 32K TSB for the whole kernel, this allows to
|
||||
* handle about 16MB of modules and vmalloc mappings without
|
||||
* incurring many hash conflicts.
|
||||
*/
|
||||
#define KERNEL_TSB_SIZE_BYTES (32 * 1024)
|
||||
#define KERNEL_TSB_NENTRIES \
|
||||
(KERNEL_TSB_SIZE_BYTES / 16)
|
||||
#define KERNEL_TSB4M_NENTRIES 4096
|
||||
|
||||
/* Do a kernel TSB lookup at tl>0 on VADDR+TAG, branch to OK_LABEL
|
||||
* on TSB hit. REG1, REG2, REG3, and REG4 are used as temporaries
|
||||
* and the found TTE will be left in REG1. REG3 and REG4 must
|
||||
* be an even/odd pair of registers.
|
||||
*
|
||||
* VADDR and TAG will be preserved and not clobbered by this macro.
|
||||
*/
|
||||
#define KERN_TSB_LOOKUP_TL1(VADDR, TAG, REG1, REG2, REG3, REG4, OK_LABEL) \
|
||||
sethi %hi(swapper_tsb), REG1; \
|
||||
or REG1, %lo(swapper_tsb), REG1; \
|
||||
srlx VADDR, PAGE_SHIFT, REG2; \
|
||||
and REG2, (KERNEL_TSB_NENTRIES - 1), REG2; \
|
||||
sllx REG2, 4, REG2; \
|
||||
add REG1, REG2, REG2; \
|
||||
KTSB_LOAD_QUAD(REG2, REG3); \
|
||||
cmp REG3, TAG; \
|
||||
be,a,pt %xcc, OK_LABEL; \
|
||||
mov REG4, REG1;
|
||||
|
||||
/* This version uses a trick, the TAG is already (VADDR >> 22) so
|
||||
* we can make use of that for the index computation.
|
||||
*/
|
||||
#define KERN_TSB4M_LOOKUP_TL1(TAG, REG1, REG2, REG3, REG4, OK_LABEL) \
|
||||
sethi %hi(swapper_4m_tsb), REG1; \
|
||||
or REG1, %lo(swapper_4m_tsb), REG1; \
|
||||
and TAG, (KERNEL_TSB_NENTRIES - 1), REG2; \
|
||||
sllx REG2, 4, REG2; \
|
||||
add REG1, REG2, REG2; \
|
||||
KTSB_LOAD_QUAD(REG2, REG3); \
|
||||
cmp REG3, TAG; \
|
||||
be,a,pt %xcc, OK_LABEL; \
|
||||
mov REG4, REG1;
|
||||
|
||||
#endif /* !(_SPARC64_TSB_H) */
|
||||
+261
-11
@@ -93,7 +93,7 @@
|
||||
|
||||
#define SYSCALL_TRAP(routine, systbl) \
|
||||
sethi %hi(109f), %g7; \
|
||||
ba,pt %xcc, scetrap; \
|
||||
ba,pt %xcc, etrap; \
|
||||
109: or %g7, %lo(109b), %g7; \
|
||||
sethi %hi(systbl), %l7; \
|
||||
ba,pt %xcc, routine; \
|
||||
@@ -109,14 +109,14 @@
|
||||
nop;nop;nop;
|
||||
|
||||
#define TRAP_UTRAP(handler,lvl) \
|
||||
ldx [%g6 + TI_UTRAPS], %g1; \
|
||||
sethi %hi(109f), %g7; \
|
||||
brz,pn %g1, utrap; \
|
||||
or %g7, %lo(109f), %g7; \
|
||||
ba,pt %xcc, utrap; \
|
||||
109: ldx [%g1 + handler*8], %g1; \
|
||||
ba,pt %xcc, utrap_ill; \
|
||||
mov lvl, %o1;
|
||||
mov handler, %g3; \
|
||||
ba,pt %xcc, utrap_trap; \
|
||||
mov lvl, %g4; \
|
||||
nop; \
|
||||
nop; \
|
||||
nop; \
|
||||
nop; \
|
||||
nop;
|
||||
|
||||
#ifdef CONFIG_SUNOS_EMUL
|
||||
#define SUNOS_SYSCALL_TRAP SYSCALL_TRAP(linux_sparc_syscall32, sunos_sys_table)
|
||||
@@ -136,8 +136,6 @@
|
||||
#else
|
||||
#define SOLARIS_SYSCALL_TRAP TRAP(solaris_syscall)
|
||||
#endif
|
||||
/* FIXME: Write these actually */
|
||||
#define NETBSD_SYSCALL_TRAP TRAP(netbsd_syscall)
|
||||
#define BREAKPOINT_TRAP TRAP(breakpoint_trap)
|
||||
|
||||
#define TRAP_IRQ(routine, level) \
|
||||
@@ -182,6 +180,26 @@
|
||||
#define KPROBES_TRAP(lvl) TRAP_ARG(bad_trap, lvl)
|
||||
#endif
|
||||
|
||||
#define SUN4V_ITSB_MISS \
|
||||
ldxa [%g0] ASI_SCRATCHPAD, %g2; \
|
||||
ldx [%g2 + HV_FAULT_I_ADDR_OFFSET], %g4; \
|
||||
ldx [%g2 + HV_FAULT_I_CTX_OFFSET], %g5; \
|
||||
srlx %g4, 22, %g6; \
|
||||
ba,pt %xcc, sun4v_itsb_miss; \
|
||||
nop; \
|
||||
nop; \
|
||||
nop;
|
||||
|
||||
#define SUN4V_DTSB_MISS \
|
||||
ldxa [%g0] ASI_SCRATCHPAD, %g2; \
|
||||
ldx [%g2 + HV_FAULT_D_ADDR_OFFSET], %g4; \
|
||||
ldx [%g2 + HV_FAULT_D_CTX_OFFSET], %g5; \
|
||||
srlx %g4, 22, %g6; \
|
||||
ba,pt %xcc, sun4v_dtsb_miss; \
|
||||
nop; \
|
||||
nop; \
|
||||
nop;
|
||||
|
||||
/* Before touching these macros, you owe it to yourself to go and
|
||||
* see how arch/sparc64/kernel/winfixup.S works... -DaveM
|
||||
*
|
||||
@@ -221,6 +239,31 @@
|
||||
saved; retry; nop; nop; nop; nop; nop; nop; \
|
||||
nop; nop; nop; nop; nop; nop; nop; nop;
|
||||
|
||||
#define SPILL_0_NORMAL_ETRAP \
|
||||
etrap_kernel_spill: \
|
||||
stx %l0, [%sp + STACK_BIAS + 0x00]; \
|
||||
stx %l1, [%sp + STACK_BIAS + 0x08]; \
|
||||
stx %l2, [%sp + STACK_BIAS + 0x10]; \
|
||||
stx %l3, [%sp + STACK_BIAS + 0x18]; \
|
||||
stx %l4, [%sp + STACK_BIAS + 0x20]; \
|
||||
stx %l5, [%sp + STACK_BIAS + 0x28]; \
|
||||
stx %l6, [%sp + STACK_BIAS + 0x30]; \
|
||||
stx %l7, [%sp + STACK_BIAS + 0x38]; \
|
||||
stx %i0, [%sp + STACK_BIAS + 0x40]; \
|
||||
stx %i1, [%sp + STACK_BIAS + 0x48]; \
|
||||
stx %i2, [%sp + STACK_BIAS + 0x50]; \
|
||||
stx %i3, [%sp + STACK_BIAS + 0x58]; \
|
||||
stx %i4, [%sp + STACK_BIAS + 0x60]; \
|
||||
stx %i5, [%sp + STACK_BIAS + 0x68]; \
|
||||
stx %i6, [%sp + STACK_BIAS + 0x70]; \
|
||||
stx %i7, [%sp + STACK_BIAS + 0x78]; \
|
||||
saved; \
|
||||
sub %g1, 2, %g1; \
|
||||
ba,pt %xcc, etrap_save; \
|
||||
wrpr %g1, %cwp; \
|
||||
nop; nop; nop; nop; nop; nop; nop; nop; \
|
||||
nop; nop; nop; nop;
|
||||
|
||||
/* Normal 64bit spill */
|
||||
#define SPILL_1_GENERIC(ASI) \
|
||||
add %sp, STACK_BIAS + 0x00, %g1; \
|
||||
@@ -254,6 +297,67 @@
|
||||
b,a,pt %xcc, spill_fixup_mna; \
|
||||
b,a,pt %xcc, spill_fixup;
|
||||
|
||||
#define SPILL_1_GENERIC_ETRAP \
|
||||
etrap_user_spill_64bit: \
|
||||
stxa %l0, [%sp + STACK_BIAS + 0x00] %asi; \
|
||||
stxa %l1, [%sp + STACK_BIAS + 0x08] %asi; \
|
||||
stxa %l2, [%sp + STACK_BIAS + 0x10] %asi; \
|
||||
stxa %l3, [%sp + STACK_BIAS + 0x18] %asi; \
|
||||
stxa %l4, [%sp + STACK_BIAS + 0x20] %asi; \
|
||||
stxa %l5, [%sp + STACK_BIAS + 0x28] %asi; \
|
||||
stxa %l6, [%sp + STACK_BIAS + 0x30] %asi; \
|
||||
stxa %l7, [%sp + STACK_BIAS + 0x38] %asi; \
|
||||
stxa %i0, [%sp + STACK_BIAS + 0x40] %asi; \
|
||||
stxa %i1, [%sp + STACK_BIAS + 0x48] %asi; \
|
||||
stxa %i2, [%sp + STACK_BIAS + 0x50] %asi; \
|
||||
stxa %i3, [%sp + STACK_BIAS + 0x58] %asi; \
|
||||
stxa %i4, [%sp + STACK_BIAS + 0x60] %asi; \
|
||||
stxa %i5, [%sp + STACK_BIAS + 0x68] %asi; \
|
||||
stxa %i6, [%sp + STACK_BIAS + 0x70] %asi; \
|
||||
stxa %i7, [%sp + STACK_BIAS + 0x78] %asi; \
|
||||
saved; \
|
||||
sub %g1, 2, %g1; \
|
||||
ba,pt %xcc, etrap_save; \
|
||||
wrpr %g1, %cwp; \
|
||||
nop; nop; nop; nop; nop; \
|
||||
nop; nop; nop; nop; \
|
||||
ba,a,pt %xcc, etrap_spill_fixup_64bit; \
|
||||
ba,a,pt %xcc, etrap_spill_fixup_64bit; \
|
||||
ba,a,pt %xcc, etrap_spill_fixup_64bit;
|
||||
|
||||
#define SPILL_1_GENERIC_ETRAP_FIXUP \
|
||||
etrap_spill_fixup_64bit: \
|
||||
ldub [%g6 + TI_WSAVED], %g1; \
|
||||
sll %g1, 3, %g3; \
|
||||
add %g6, %g3, %g3; \
|
||||
stx %sp, [%g3 + TI_RWIN_SPTRS]; \
|
||||
sll %g1, 7, %g3; \
|
||||
add %g6, %g3, %g3; \
|
||||
stx %l0, [%g3 + TI_REG_WINDOW + 0x00]; \
|
||||
stx %l1, [%g3 + TI_REG_WINDOW + 0x08]; \
|
||||
stx %l2, [%g3 + TI_REG_WINDOW + 0x10]; \
|
||||
stx %l3, [%g3 + TI_REG_WINDOW + 0x18]; \
|
||||
stx %l4, [%g3 + TI_REG_WINDOW + 0x20]; \
|
||||
stx %l5, [%g3 + TI_REG_WINDOW + 0x28]; \
|
||||
stx %l6, [%g3 + TI_REG_WINDOW + 0x30]; \
|
||||
stx %l7, [%g3 + TI_REG_WINDOW + 0x38]; \
|
||||
stx %i0, [%g3 + TI_REG_WINDOW + 0x40]; \
|
||||
stx %i1, [%g3 + TI_REG_WINDOW + 0x48]; \
|
||||
stx %i2, [%g3 + TI_REG_WINDOW + 0x50]; \
|
||||
stx %i3, [%g3 + TI_REG_WINDOW + 0x58]; \
|
||||
stx %i4, [%g3 + TI_REG_WINDOW + 0x60]; \
|
||||
stx %i5, [%g3 + TI_REG_WINDOW + 0x68]; \
|
||||
stx %i6, [%g3 + TI_REG_WINDOW + 0x70]; \
|
||||
stx %i7, [%g3 + TI_REG_WINDOW + 0x78]; \
|
||||
add %g1, 1, %g1; \
|
||||
stb %g1, [%g6 + TI_WSAVED]; \
|
||||
saved; \
|
||||
rdpr %cwp, %g1; \
|
||||
sub %g1, 2, %g1; \
|
||||
ba,pt %xcc, etrap_save; \
|
||||
wrpr %g1, %cwp; \
|
||||
nop; nop; nop
|
||||
|
||||
/* Normal 32bit spill */
|
||||
#define SPILL_2_GENERIC(ASI) \
|
||||
srl %sp, 0, %sp; \
|
||||
@@ -287,6 +391,68 @@
|
||||
b,a,pt %xcc, spill_fixup_mna; \
|
||||
b,a,pt %xcc, spill_fixup;
|
||||
|
||||
#define SPILL_2_GENERIC_ETRAP \
|
||||
etrap_user_spill_32bit: \
|
||||
srl %sp, 0, %sp; \
|
||||
stwa %l0, [%sp + 0x00] %asi; \
|
||||
stwa %l1, [%sp + 0x04] %asi; \
|
||||
stwa %l2, [%sp + 0x08] %asi; \
|
||||
stwa %l3, [%sp + 0x0c] %asi; \
|
||||
stwa %l4, [%sp + 0x10] %asi; \
|
||||
stwa %l5, [%sp + 0x14] %asi; \
|
||||
stwa %l6, [%sp + 0x18] %asi; \
|
||||
stwa %l7, [%sp + 0x1c] %asi; \
|
||||
stwa %i0, [%sp + 0x20] %asi; \
|
||||
stwa %i1, [%sp + 0x24] %asi; \
|
||||
stwa %i2, [%sp + 0x28] %asi; \
|
||||
stwa %i3, [%sp + 0x2c] %asi; \
|
||||
stwa %i4, [%sp + 0x30] %asi; \
|
||||
stwa %i5, [%sp + 0x34] %asi; \
|
||||
stwa %i6, [%sp + 0x38] %asi; \
|
||||
stwa %i7, [%sp + 0x3c] %asi; \
|
||||
saved; \
|
||||
sub %g1, 2, %g1; \
|
||||
ba,pt %xcc, etrap_save; \
|
||||
wrpr %g1, %cwp; \
|
||||
nop; nop; nop; nop; \
|
||||
nop; nop; nop; nop; \
|
||||
ba,a,pt %xcc, etrap_spill_fixup_32bit; \
|
||||
ba,a,pt %xcc, etrap_spill_fixup_32bit; \
|
||||
ba,a,pt %xcc, etrap_spill_fixup_32bit;
|
||||
|
||||
#define SPILL_2_GENERIC_ETRAP_FIXUP \
|
||||
etrap_spill_fixup_32bit: \
|
||||
ldub [%g6 + TI_WSAVED], %g1; \
|
||||
sll %g1, 3, %g3; \
|
||||
add %g6, %g3, %g3; \
|
||||
stx %sp, [%g3 + TI_RWIN_SPTRS]; \
|
||||
sll %g1, 7, %g3; \
|
||||
add %g6, %g3, %g3; \
|
||||
stw %l0, [%g3 + TI_REG_WINDOW + 0x00]; \
|
||||
stw %l1, [%g3 + TI_REG_WINDOW + 0x04]; \
|
||||
stw %l2, [%g3 + TI_REG_WINDOW + 0x08]; \
|
||||
stw %l3, [%g3 + TI_REG_WINDOW + 0x0c]; \
|
||||
stw %l4, [%g3 + TI_REG_WINDOW + 0x10]; \
|
||||
stw %l5, [%g3 + TI_REG_WINDOW + 0x14]; \
|
||||
stw %l6, [%g3 + TI_REG_WINDOW + 0x18]; \
|
||||
stw %l7, [%g3 + TI_REG_WINDOW + 0x1c]; \
|
||||
stw %i0, [%g3 + TI_REG_WINDOW + 0x20]; \
|
||||
stw %i1, [%g3 + TI_REG_WINDOW + 0x24]; \
|
||||
stw %i2, [%g3 + TI_REG_WINDOW + 0x28]; \
|
||||
stw %i3, [%g3 + TI_REG_WINDOW + 0x2c]; \
|
||||
stw %i4, [%g3 + TI_REG_WINDOW + 0x30]; \
|
||||
stw %i5, [%g3 + TI_REG_WINDOW + 0x34]; \
|
||||
stw %i6, [%g3 + TI_REG_WINDOW + 0x38]; \
|
||||
stw %i7, [%g3 + TI_REG_WINDOW + 0x3c]; \
|
||||
add %g1, 1, %g1; \
|
||||
stb %g1, [%g6 + TI_WSAVED]; \
|
||||
saved; \
|
||||
rdpr %cwp, %g1; \
|
||||
sub %g1, 2, %g1; \
|
||||
ba,pt %xcc, etrap_save; \
|
||||
wrpr %g1, %cwp; \
|
||||
nop; nop; nop
|
||||
|
||||
#define SPILL_1_NORMAL SPILL_1_GENERIC(ASI_AIUP)
|
||||
#define SPILL_2_NORMAL SPILL_2_GENERIC(ASI_AIUP)
|
||||
#define SPILL_3_NORMAL SPILL_0_NORMAL
|
||||
@@ -325,6 +491,35 @@
|
||||
restored; retry; nop; nop; nop; nop; nop; nop; \
|
||||
nop; nop; nop; nop; nop; nop; nop; nop;
|
||||
|
||||
#define FILL_0_NORMAL_RTRAP \
|
||||
kern_rtt_fill: \
|
||||
rdpr %cwp, %g1; \
|
||||
sub %g1, 1, %g1; \
|
||||
wrpr %g1, %cwp; \
|
||||
ldx [%sp + STACK_BIAS + 0x00], %l0; \
|
||||
ldx [%sp + STACK_BIAS + 0x08], %l1; \
|
||||
ldx [%sp + STACK_BIAS + 0x10], %l2; \
|
||||
ldx [%sp + STACK_BIAS + 0x18], %l3; \
|
||||
ldx [%sp + STACK_BIAS + 0x20], %l4; \
|
||||
ldx [%sp + STACK_BIAS + 0x28], %l5; \
|
||||
ldx [%sp + STACK_BIAS + 0x30], %l6; \
|
||||
ldx [%sp + STACK_BIAS + 0x38], %l7; \
|
||||
ldx [%sp + STACK_BIAS + 0x40], %i0; \
|
||||
ldx [%sp + STACK_BIAS + 0x48], %i1; \
|
||||
ldx [%sp + STACK_BIAS + 0x50], %i2; \
|
||||
ldx [%sp + STACK_BIAS + 0x58], %i3; \
|
||||
ldx [%sp + STACK_BIAS + 0x60], %i4; \
|
||||
ldx [%sp + STACK_BIAS + 0x68], %i5; \
|
||||
ldx [%sp + STACK_BIAS + 0x70], %i6; \
|
||||
ldx [%sp + STACK_BIAS + 0x78], %i7; \
|
||||
restored; \
|
||||
add %g1, 1, %g1; \
|
||||
ba,pt %xcc, kern_rtt_restore; \
|
||||
wrpr %g1, %cwp; \
|
||||
nop; nop; nop; nop; nop; \
|
||||
nop; nop; nop; nop;
|
||||
|
||||
|
||||
/* Normal 64bit fill */
|
||||
#define FILL_1_GENERIC(ASI) \
|
||||
add %sp, STACK_BIAS + 0x00, %g1; \
|
||||
@@ -356,6 +551,33 @@
|
||||
b,a,pt %xcc, fill_fixup_mna; \
|
||||
b,a,pt %xcc, fill_fixup;
|
||||
|
||||
#define FILL_1_GENERIC_RTRAP \
|
||||
user_rtt_fill_64bit: \
|
||||
ldxa [%sp + STACK_BIAS + 0x00] %asi, %l0; \
|
||||
ldxa [%sp + STACK_BIAS + 0x08] %asi, %l1; \
|
||||
ldxa [%sp + STACK_BIAS + 0x10] %asi, %l2; \
|
||||
ldxa [%sp + STACK_BIAS + 0x18] %asi, %l3; \
|
||||
ldxa [%sp + STACK_BIAS + 0x20] %asi, %l4; \
|
||||
ldxa [%sp + STACK_BIAS + 0x28] %asi, %l5; \
|
||||
ldxa [%sp + STACK_BIAS + 0x30] %asi, %l6; \
|
||||
ldxa [%sp + STACK_BIAS + 0x38] %asi, %l7; \
|
||||
ldxa [%sp + STACK_BIAS + 0x40] %asi, %i0; \
|
||||
ldxa [%sp + STACK_BIAS + 0x48] %asi, %i1; \
|
||||
ldxa [%sp + STACK_BIAS + 0x50] %asi, %i2; \
|
||||
ldxa [%sp + STACK_BIAS + 0x58] %asi, %i3; \
|
||||
ldxa [%sp + STACK_BIAS + 0x60] %asi, %i4; \
|
||||
ldxa [%sp + STACK_BIAS + 0x68] %asi, %i5; \
|
||||
ldxa [%sp + STACK_BIAS + 0x70] %asi, %i6; \
|
||||
ldxa [%sp + STACK_BIAS + 0x78] %asi, %i7; \
|
||||
ba,pt %xcc, user_rtt_pre_restore; \
|
||||
restored; \
|
||||
nop; nop; nop; nop; nop; nop; \
|
||||
nop; nop; nop; nop; nop; \
|
||||
ba,a,pt %xcc, user_rtt_fill_fixup; \
|
||||
ba,a,pt %xcc, user_rtt_fill_fixup; \
|
||||
ba,a,pt %xcc, user_rtt_fill_fixup;
|
||||
|
||||
|
||||
/* Normal 32bit fill */
|
||||
#define FILL_2_GENERIC(ASI) \
|
||||
srl %sp, 0, %sp; \
|
||||
@@ -387,6 +609,34 @@
|
||||
b,a,pt %xcc, fill_fixup_mna; \
|
||||
b,a,pt %xcc, fill_fixup;
|
||||
|
||||
#define FILL_2_GENERIC_RTRAP \
|
||||
user_rtt_fill_32bit: \
|
||||
srl %sp, 0, %sp; \
|
||||
lduwa [%sp + 0x00] %asi, %l0; \
|
||||
lduwa [%sp + 0x04] %asi, %l1; \
|
||||
lduwa [%sp + 0x08] %asi, %l2; \
|
||||
lduwa [%sp + 0x0c] %asi, %l3; \
|
||||
lduwa [%sp + 0x10] %asi, %l4; \
|
||||
lduwa [%sp + 0x14] %asi, %l5; \
|
||||
lduwa [%sp + 0x18] %asi, %l6; \
|
||||
lduwa [%sp + 0x1c] %asi, %l7; \
|
||||
lduwa [%sp + 0x20] %asi, %i0; \
|
||||
lduwa [%sp + 0x24] %asi, %i1; \
|
||||
lduwa [%sp + 0x28] %asi, %i2; \
|
||||
lduwa [%sp + 0x2c] %asi, %i3; \
|
||||
lduwa [%sp + 0x30] %asi, %i4; \
|
||||
lduwa [%sp + 0x34] %asi, %i5; \
|
||||
lduwa [%sp + 0x38] %asi, %i6; \
|
||||
lduwa [%sp + 0x3c] %asi, %i7; \
|
||||
ba,pt %xcc, user_rtt_pre_restore; \
|
||||
restored; \
|
||||
nop; nop; nop; nop; nop; \
|
||||
nop; nop; nop; nop; nop; \
|
||||
ba,a,pt %xcc, user_rtt_fill_fixup; \
|
||||
ba,a,pt %xcc, user_rtt_fill_fixup; \
|
||||
ba,a,pt %xcc, user_rtt_fill_fixup;
|
||||
|
||||
|
||||
#define FILL_1_NORMAL FILL_1_GENERIC(ASI_AIUP)
|
||||
#define FILL_2_NORMAL FILL_2_GENERIC(ASI_AIUP)
|
||||
#define FILL_3_NORMAL FILL_0_NORMAL
|
||||
|
||||
@@ -114,16 +114,6 @@ case 8: __put_user_asm(data,x,addr,__pu_ret); break; \
|
||||
default: __pu_ret = __put_user_bad(); break; \
|
||||
} __pu_ret; })
|
||||
|
||||
#define __put_user_nocheck_ret(data,addr,size,retval) ({ \
|
||||
register int __foo __asm__ ("l1"); \
|
||||
switch (size) { \
|
||||
case 1: __put_user_asm_ret(data,b,addr,retval,__foo); break; \
|
||||
case 2: __put_user_asm_ret(data,h,addr,retval,__foo); break; \
|
||||
case 4: __put_user_asm_ret(data,w,addr,retval,__foo); break; \
|
||||
case 8: __put_user_asm_ret(data,x,addr,retval,__foo); break; \
|
||||
default: if (__put_user_bad()) return retval; break; \
|
||||
} })
|
||||
|
||||
#define __put_user_asm(x,size,addr,ret) \
|
||||
__asm__ __volatile__( \
|
||||
"/* Put user asm, inline. */\n" \
|
||||
@@ -143,33 +133,6 @@ __asm__ __volatile__( \
|
||||
: "=r" (ret) : "r" (x), "r" (__m(addr)), \
|
||||
"i" (-EFAULT))
|
||||
|
||||
#define __put_user_asm_ret(x,size,addr,ret,foo) \
|
||||
if (__builtin_constant_p(ret) && ret == -EFAULT) \
|
||||
__asm__ __volatile__( \
|
||||
"/* Put user asm ret, inline. */\n" \
|
||||
"1:\t" "st"#size "a %1, [%2] %%asi\n\n\t" \
|
||||
".section __ex_table,\"a\"\n\t" \
|
||||
".align 4\n\t" \
|
||||
".word 1b, __ret_efault\n\n\t" \
|
||||
".previous\n\n\t" \
|
||||
: "=r" (foo) : "r" (x), "r" (__m(addr))); \
|
||||
else \
|
||||
__asm__ __volatile__( \
|
||||
"/* Put user asm ret, inline. */\n" \
|
||||
"1:\t" "st"#size "a %1, [%2] %%asi\n\n\t" \
|
||||
".section .fixup,#alloc,#execinstr\n\t" \
|
||||
".align 4\n" \
|
||||
"3:\n\t" \
|
||||
"ret\n\t" \
|
||||
" restore %%g0, %3, %%o0\n\n\t" \
|
||||
".previous\n\t" \
|
||||
".section __ex_table,\"a\"\n\t" \
|
||||
".align 4\n\t" \
|
||||
".word 1b, 3b\n\n\t" \
|
||||
".previous\n\n\t" \
|
||||
: "=r" (foo) : "r" (x), "r" (__m(addr)), \
|
||||
"i" (ret))
|
||||
|
||||
extern int __put_user_bad(void);
|
||||
|
||||
#define __get_user_nocheck(data,addr,size,type) ({ \
|
||||
@@ -289,14 +252,7 @@ copy_in_user(void __user *to, void __user *from, unsigned long size)
|
||||
}
|
||||
#define __copy_in_user copy_in_user
|
||||
|
||||
extern unsigned long __must_check __bzero_noasi(void __user *, unsigned long);
|
||||
|
||||
static inline unsigned long __must_check
|
||||
__clear_user(void __user *addr, unsigned long size)
|
||||
{
|
||||
|
||||
return __bzero_noasi(addr, size);
|
||||
}
|
||||
extern unsigned long __must_check __clear_user(void __user *, unsigned long);
|
||||
|
||||
#define clear_user __clear_user
|
||||
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
/* vdev.h: SUN4V virtual device interfaces and defines.
|
||||
*
|
||||
* Copyright (C) 2006 David S. Miller <davem@davemloft.net>
|
||||
*/
|
||||
|
||||
#ifndef _SPARC64_VDEV_H
|
||||
#define _SPARC64_VDEV_H
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
extern u32 sun4v_vdev_devhandle;
|
||||
extern int sun4v_vdev_root;
|
||||
|
||||
extern unsigned int sun4v_vdev_device_interrupt(unsigned int);
|
||||
|
||||
#endif /* !(_SPARC64_VDEV_H) */
|
||||
@@ -2,9 +2,11 @@
|
||||
* include/asm-sparc64/xor.h
|
||||
*
|
||||
* High speed xor_block operation for RAID4/5 utilizing the
|
||||
* UltraSparc Visual Instruction Set.
|
||||
* UltraSparc Visual Instruction Set and Niagara block-init
|
||||
* twin-load instructions.
|
||||
*
|
||||
* Copyright (C) 1997, 1999 Jakub Jelinek (jj@ultra.linux.cz)
|
||||
* Copyright (C) 2006 David S. Miller <davem@davemloft.net>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -16,8 +18,7 @@
|
||||
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include <asm/pstate.h>
|
||||
#include <asm/asi.h>
|
||||
#include <asm/spitfire.h>
|
||||
|
||||
extern void xor_vis_2(unsigned long, unsigned long *, unsigned long *);
|
||||
extern void xor_vis_3(unsigned long, unsigned long *, unsigned long *,
|
||||
@@ -37,4 +38,29 @@ static struct xor_block_template xor_block_VIS = {
|
||||
.do_5 = xor_vis_5,
|
||||
};
|
||||
|
||||
#define XOR_TRY_TEMPLATES xor_speed(&xor_block_VIS)
|
||||
extern void xor_niagara_2(unsigned long, unsigned long *, unsigned long *);
|
||||
extern void xor_niagara_3(unsigned long, unsigned long *, unsigned long *,
|
||||
unsigned long *);
|
||||
extern void xor_niagara_4(unsigned long, unsigned long *, unsigned long *,
|
||||
unsigned long *, unsigned long *);
|
||||
extern void xor_niagara_5(unsigned long, unsigned long *, unsigned long *,
|
||||
unsigned long *, unsigned long *, unsigned long *);
|
||||
|
||||
static struct xor_block_template xor_block_niagara = {
|
||||
.name = "Niagara",
|
||||
.do_2 = xor_niagara_2,
|
||||
.do_3 = xor_niagara_3,
|
||||
.do_4 = xor_niagara_4,
|
||||
.do_5 = xor_niagara_5,
|
||||
};
|
||||
|
||||
#undef XOR_TRY_TEMPLATES
|
||||
#define XOR_TRY_TEMPLATES \
|
||||
do { \
|
||||
xor_speed(&xor_block_VIS); \
|
||||
xor_speed(&xor_block_niagara); \
|
||||
} while (0)
|
||||
|
||||
/* For VIS for everything except Niagara. */
|
||||
#define XOR_SELECT_TEMPLATE(FASTEST) \
|
||||
(tlb_type == hypervisor ? &xor_block_niagara : &xor_block_VIS)
|
||||
|
||||
@@ -127,6 +127,9 @@
|
||||
/* Hilscher netx */
|
||||
#define PORT_NETX 71
|
||||
|
||||
/* SUN4V Hypervisor Console */
|
||||
#define PORT_SUNHV 72
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
#include <linux/config.h>
|
||||
|
||||
Reference in New Issue
Block a user