Skip to content

Commit

Permalink
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc
Browse files Browse the repository at this point in the history
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc:
  sparc: Size mondo queues more sanely.
  sparc: Access kernel TSB using physical addressing when possible.
  sparc: Fix __atomic_add_unless() return value.
  sparc: use kbuild-generic support for true asm-generic header files
  sparc: Use popc when possible for ffs/__ffs/ffz.
  sparc: Set reboot-cmd using reboot data hypervisor call if available.
  sparc: Add some missing hypervisor API groups.
  sparc: Use hweight64() in popc emulation.
  sparc: Use popc if possible for hweight routines.
  sparc: Minor tweaks to Niagara page copy/clear.
  sparc: Sanitize cpu feature detection and reporting.
  • Loading branch information
Linus Torvalds committed Aug 5, 2011
2 parents 07d952d + 961f65f commit 8cd290a
Show file tree
Hide file tree
Showing 30 changed files with 661 additions and 258 deletions.
5 changes: 5 additions & 0 deletions arch/sparc/include/asm/Kbuild
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,8 @@ header-y += traps.h
header-y += uctx.h
header-y += utrap.h
header-y += watchdog.h

generic-y += div64.h
generic-y += local64.h
generic-y += irq_regs.h
generic-y += local.h
49 changes: 8 additions & 41 deletions arch/sparc/include/asm/bitops_64.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,61 +26,28 @@ extern void change_bit(unsigned long nr, volatile unsigned long *addr);
#define smp_mb__before_clear_bit() barrier()
#define smp_mb__after_clear_bit() barrier()

#include <asm-generic/bitops/ffz.h>
#include <asm-generic/bitops/__ffs.h>
#include <asm-generic/bitops/fls.h>
#include <asm-generic/bitops/__fls.h>
#include <asm-generic/bitops/fls64.h>

#ifdef __KERNEL__

extern int ffs(int x);
extern unsigned long __ffs(unsigned long);

#include <asm-generic/bitops/ffz.h>
#include <asm-generic/bitops/sched.h>
#include <asm-generic/bitops/ffs.h>

/*
* hweightN: returns the hamming weight (i.e. the number
* of bits set) of a N-bit word
*/

#ifdef ULTRA_HAS_POPULATION_COUNT

static inline unsigned int __arch_hweight64(unsigned long w)
{
unsigned int res;

__asm__ ("popc %1,%0" : "=r" (res) : "r" (w));
return res;
}

static inline unsigned int __arch_hweight32(unsigned int w)
{
unsigned int res;

__asm__ ("popc %1,%0" : "=r" (res) : "r" (w & 0xffffffff));
return res;
}
extern unsigned long __arch_hweight64(__u64 w);
extern unsigned int __arch_hweight32(unsigned int w);
extern unsigned int __arch_hweight16(unsigned int w);
extern unsigned int __arch_hweight8(unsigned int w);

static inline unsigned int __arch_hweight16(unsigned int w)
{
unsigned int res;

__asm__ ("popc %1,%0" : "=r" (res) : "r" (w & 0xffff));
return res;
}

static inline unsigned int __arch_hweight8(unsigned int w)
{
unsigned int res;

__asm__ ("popc %1,%0" : "=r" (res) : "r" (w & 0xff));
return res;
}

#else

#include <asm-generic/bitops/arch_hweight.h>

#endif
#include <asm-generic/bitops/const_hweight.h>
#include <asm-generic/bitops/lock.h>
#endif /* __KERNEL__ */
Expand Down
1 change: 0 additions & 1 deletion arch/sparc/include/asm/div64.h

This file was deleted.

65 changes: 29 additions & 36 deletions arch/sparc/include/asm/elf_64.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,15 +59,33 @@
#define R_SPARC_6 45

/* Bits present in AT_HWCAP, primarily for Sparc32. */

#define HWCAP_SPARC_FLUSH 1 /* CPU supports flush instruction. */
#define HWCAP_SPARC_STBAR 2
#define HWCAP_SPARC_SWAP 4
#define HWCAP_SPARC_MULDIV 8
#define HWCAP_SPARC_V9 16
#define HWCAP_SPARC_ULTRA3 32
#define HWCAP_SPARC_BLKINIT 64
#define HWCAP_SPARC_N2 128
#define HWCAP_SPARC_FLUSH 0x00000001
#define HWCAP_SPARC_STBAR 0x00000002
#define HWCAP_SPARC_SWAP 0x00000004
#define HWCAP_SPARC_MULDIV 0x00000008
#define HWCAP_SPARC_V9 0x00000010
#define HWCAP_SPARC_ULTRA3 0x00000020
#define HWCAP_SPARC_BLKINIT 0x00000040
#define HWCAP_SPARC_N2 0x00000080

/* Solaris compatible AT_HWCAP bits. */
#define AV_SPARC_MUL32 0x00000100 /* 32x32 multiply is efficient */
#define AV_SPARC_DIV32 0x00000200 /* 32x32 divide is efficient */
#define AV_SPARC_FSMULD 0x00000400 /* 'fsmuld' is efficient */
#define AV_SPARC_V8PLUS 0x00000800 /* v9 insn available to 32bit */
#define AV_SPARC_POPC 0x00001000 /* 'popc' is efficient */
#define AV_SPARC_VIS 0x00002000 /* VIS insns available */
#define AV_SPARC_VIS2 0x00004000 /* VIS2 insns available */
#define AV_SPARC_ASI_BLK_INIT 0x00008000 /* block init ASIs available */
#define AV_SPARC_FMAF 0x00010000 /* fused multiply-add */
#define AV_SPARC_VIS3 0x00020000 /* VIS3 insns available */
#define AV_SPARC_HPC 0x00040000 /* HPC insns available */
#define AV_SPARC_RANDOM 0x00080000 /* 'random' insn available */
#define AV_SPARC_TRANS 0x00100000 /* transaction insns available */
#define AV_SPARC_FJFMAU 0x00200000 /* unfused multiply-add */
#define AV_SPARC_IMA 0x00400000 /* integer multiply-add */
#define AV_SPARC_ASI_CACHE_SPARING \
0x00800000 /* cache sparing ASIs available */

#define CORE_DUMP_USE_REGSET

Expand Down Expand Up @@ -162,33 +180,8 @@ typedef struct {
#define ELF_ET_DYN_BASE 0x0000010000000000UL
#define COMPAT_ELF_ET_DYN_BASE 0x0000000070000000UL


/* This yields a mask that user programs can use to figure out what
instruction set this cpu supports. */

/* On Ultra, we support all of the v8 capabilities. */
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) {
if (sun4v_chip_type == SUN4V_CHIP_NIAGARA1 ||
sun4v_chip_type == SUN4V_CHIP_NIAGARA2 ||
sun4v_chip_type == SUN4V_CHIP_NIAGARA3)
cap |= HWCAP_SPARC_BLKINIT;
if (sun4v_chip_type == SUN4V_CHIP_NIAGARA2 ||
sun4v_chip_type == SUN4V_CHIP_NIAGARA3)
cap |= HWCAP_SPARC_N2;
}

return cap;
}

#define ELF_HWCAP sparc64_elf_hwcap()
extern unsigned long sparc64_elf_hwcap;
#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
Expand Down
13 changes: 13 additions & 0 deletions arch/sparc/include/asm/hypervisor.h
Original file line number Diff line number Diff line change
Expand Up @@ -2927,6 +2927,13 @@ extern unsigned long sun4v_ncs_request(unsigned long request,
#define HV_FAST_FIRE_GET_PERFREG 0x120
#define HV_FAST_FIRE_SET_PERFREG 0x121

#define HV_FAST_REBOOT_DATA_SET 0x172

#ifndef __ASSEMBLY__
extern unsigned long sun4v_reboot_data_set(unsigned long ra,
unsigned long len);
#endif

/* Function numbers for HV_CORE_TRAP. */
#define HV_CORE_SET_VER 0x00
#define HV_CORE_PUTCHAR 0x01
Expand All @@ -2940,11 +2947,17 @@ extern unsigned long sun4v_ncs_request(unsigned long request,
#define HV_GRP_CORE 0x0001
#define HV_GRP_INTR 0x0002
#define HV_GRP_SOFT_STATE 0x0003
#define HV_GRP_TM 0x0080
#define HV_GRP_PCI 0x0100
#define HV_GRP_LDOM 0x0101
#define HV_GRP_SVC_CHAN 0x0102
#define HV_GRP_NCS 0x0103
#define HV_GRP_RNG 0x0104
#define HV_GRP_PBOOT 0x0105
#define HV_GRP_TPM 0x0107
#define HV_GRP_SDIO 0x0108
#define HV_GRP_SDIO_ERR 0x0109
#define HV_GRP_REBOOT_DATA 0x0110
#define HV_GRP_NIAG_PERF 0x0200
#define HV_GRP_FIRE_PERF 0x0201
#define HV_GRP_N2_CPU 0x0202
Expand Down
1 change: 0 additions & 1 deletion arch/sparc/include/asm/irq_regs.h

This file was deleted.

6 changes: 0 additions & 6 deletions arch/sparc/include/asm/local.h

This file was deleted.

1 change: 0 additions & 1 deletion arch/sparc/include/asm/local64.h

This file was deleted.

51 changes: 24 additions & 27 deletions arch/sparc/include/asm/tsb.h
Original file line number Diff line number Diff line change
Expand Up @@ -133,29 +133,6 @@ extern struct tsb_phys_patch_entry __tsb_phys_patch, __tsb_phys_patch_end;
sub TSB, 0x8, TSB; \
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; \

#define KTSB_WRITE(TSB, TTE, TAG) \
add TSB, 0x8, TSB; \
stxa TTE, [TSB] ASI_N; \
sub TSB, 0x8, TSB; \
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.
Expand Down Expand Up @@ -239,6 +216,8 @@ extern struct tsb_phys_patch_entry __tsb_phys_patch, __tsb_phys_patch_end;
(KERNEL_TSB_SIZE_BYTES / 16)
#define KERNEL_TSB4M_NENTRIES 4096

#define KTSB_PHYS_SHIFT 15

/* 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
Expand All @@ -247,13 +226,22 @@ extern struct tsb_phys_patch_entry __tsb_phys_patch, __tsb_phys_patch_end;
* 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; \
661: sethi %hi(swapper_tsb), REG1; \
or REG1, %lo(swapper_tsb), REG1; \
.section .swapper_tsb_phys_patch, "ax"; \
.word 661b; \
.previous; \
661: nop; \
.section .tsb_ldquad_phys_patch, "ax"; \
.word 661b; \
sllx REG1, KTSB_PHYS_SHIFT, REG1; \
sllx REG1, KTSB_PHYS_SHIFT, REG1; \
.previous; \
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); \
TSB_LOAD_QUAD(REG2, REG3); \
cmp REG3, TAG; \
be,a,pt %xcc, OK_LABEL; \
mov REG4, REG1;
Expand All @@ -263,12 +251,21 @@ extern struct tsb_phys_patch_entry __tsb_phys_patch, __tsb_phys_patch_end;
* 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; \
661: sethi %hi(swapper_4m_tsb), REG1; \
or REG1, %lo(swapper_4m_tsb), REG1; \
.section .swapper_4m_tsb_phys_patch, "ax"; \
.word 661b; \
.previous; \
661: nop; \
.section .tsb_ldquad_phys_patch, "ax"; \
.word 661b; \
sllx REG1, KTSB_PHYS_SHIFT, REG1; \
sllx REG1, KTSB_PHYS_SHIFT, REG1; \
.previous; \
and TAG, (KERNEL_TSB4M_NENTRIES - 1), REG2; \
sllx REG2, 4, REG2; \
add REG1, REG2, REG2; \
KTSB_LOAD_QUAD(REG2, REG3); \
TSB_LOAD_QUAD(REG2, REG3); \
cmp REG3, TAG; \
be,a,pt %xcc, OK_LABEL; \
mov REG4, REG1;
Expand Down
1 change: 1 addition & 0 deletions arch/sparc/kernel/cpu.c
Original file line number Diff line number Diff line change
Expand Up @@ -396,6 +396,7 @@ static int show_cpuinfo(struct seq_file *m, void *__unused)
, cpu_data(0).clock_tick
#endif
);
cpucap_info(m);
#ifdef CONFIG_SMP
smp_bogo(m);
#endif
Expand Down
30 changes: 28 additions & 2 deletions arch/sparc/kernel/ds.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,15 @@
#include <linux/reboot.h>
#include <linux/cpu.h>

#include <asm/hypervisor.h>
#include <asm/ldc.h>
#include <asm/vio.h>
#include <asm/mdesc.h>
#include <asm/head.h>
#include <asm/irq.h>

#include "kernel.h"

#define DRV_MODULE_NAME "ds"
#define PFX DRV_MODULE_NAME ": "
#define DRV_MODULE_VERSION "1.0"
Expand Down Expand Up @@ -828,18 +831,32 @@ void ldom_set_var(const char *var, const char *value)
}
}

static char full_boot_str[256] __attribute__((aligned(32)));
static int reboot_data_supported;

void ldom_reboot(const char *boot_command)
{
/* Don't bother with any of this if the boot_command
* is empty.
*/
if (boot_command && strlen(boot_command)) {
char full_boot_str[256];
unsigned long len;

strcpy(full_boot_str, "boot ");
strcpy(full_boot_str + strlen("boot "), boot_command);
len = strlen(full_boot_str);

ldom_set_var("reboot-command", full_boot_str);
if (reboot_data_supported) {
unsigned long ra = kimage_addr_to_ra(full_boot_str);
unsigned long hv_ret;

hv_ret = sun4v_reboot_data_set(ra, len);
if (hv_ret != HV_EOK)
pr_err("SUN4V: Unable to set reboot data "
"hv_ret=%lu\n", hv_ret);
} else {
ldom_set_var("reboot-command", full_boot_str);
}
}
sun4v_mach_sir();
}
Expand Down Expand Up @@ -1237,6 +1254,15 @@ static struct vio_driver ds_driver = {

static int __init ds_init(void)
{
unsigned long hv_ret, major, minor;

hv_ret = sun4v_get_version(HV_GRP_REBOOT_DATA, &major, &minor);
if (hv_ret == HV_EOK) {
pr_info("SUN4V: Reboot data supported (maj=%lu,min=%lu).\n",
major, minor);
reboot_data_supported = 1;
}

kthread_run(ds_thread, NULL, "kldomd");

return vio_register_driver(&ds_driver);
Expand Down
14 changes: 14 additions & 0 deletions arch/sparc/kernel/entry.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,20 @@ extern void fpsave(unsigned long *fpregs, unsigned long *fsr,
extern void fpload(unsigned long *fpregs, unsigned long *fsr);

#else /* CONFIG_SPARC32 */
struct popc_3insn_patch_entry {
unsigned int addr;
unsigned int insns[3];
};
extern struct popc_3insn_patch_entry __popc_3insn_patch,
__popc_3insn_patch_end;

struct popc_6insn_patch_entry {
unsigned int addr;
unsigned int insns[6];
};
extern struct popc_6insn_patch_entry __popc_6insn_patch,
__popc_6insn_patch_end;

extern void __init per_cpu_patch(void);
extern void __init sun4v_patch(void);
extern void __init boot_cpu_id_too_large(int cpu);
Expand Down
2 changes: 1 addition & 1 deletion arch/sparc/kernel/head_64.S
Original file line number Diff line number Diff line change
Expand Up @@ -559,7 +559,7 @@ niagara2_patch:
nop
call niagara_patch_bzero
nop
call niagara2_patch_pageops
call niagara_patch_pageops
nop

ba,a,pt %xcc, 80f
Expand Down
Loading

0 comments on commit 8cd290a

Please sign in to comment.